aboutsummaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/Makefile284
-rw-r--r--usr.bin/Makefile.amd641
-rw-r--r--usr.bin/Makefile.arm0
-rw-r--r--usr.bin/Makefile.i3861
-rw-r--r--usr.bin/Makefile.inc1
-rw-r--r--usr.bin/Makefile.powerpc1
-rw-r--r--usr.bin/addr2line/Makefile16
-rw-r--r--usr.bin/addr2line/Makefile.depend20
-rw-r--r--usr.bin/alias/Makefile19
-rw-r--r--usr.bin/alias/Makefile.depend10
-rw-r--r--usr.bin/alias/generic.sh3
-rw-r--r--usr.bin/apply/Makefile10
-rw-r--r--usr.bin/apply/Makefile.depend16
-rw-r--r--usr.bin/apply/apply.1137
-rw-r--r--usr.bin/apply/apply.c247
-rw-r--r--usr.bin/apply/tests/Makefile11
-rw-r--r--usr.bin/apply/tests/Makefile.depend10
-rw-r--r--usr.bin/apply/tests/legacy_test.sh5
-rw-r--r--usr.bin/apply/tests/regress.00.in1
-rw-r--r--usr.bin/apply/tests/regress.00.out1
-rw-r--r--usr.bin/apply/tests/regress.01.out1
-rw-r--r--usr.bin/apply/tests/regress.01.sh14
-rw-r--r--usr.bin/apply/tests/regress.sh9
-rw-r--r--usr.bin/ar/Makefile15
-rw-r--r--usr.bin/ar/Makefile.depend18
-rw-r--r--usr.bin/ar/acplex.l81
-rw-r--r--usr.bin/ar/acpyacc.y655
-rw-r--r--usr.bin/ar/ar.1609
-rw-r--r--usr.bin/ar/ar.c407
-rw-r--r--usr.bin/ar/ar.h119
-rw-r--r--usr.bin/ar/read.c204
-rw-r--r--usr.bin/ar/util.c86
-rw-r--r--usr.bin/ar/write.c914
-rw-r--r--usr.bin/asa/Makefile7
-rw-r--r--usr.bin/asa/Makefile.depend14
-rw-r--r--usr.bin/asa/asa.196
-rw-r--r--usr.bin/asa/asa.c142
-rw-r--r--usr.bin/asa/tests/Makefile4
-rw-r--r--usr.bin/asa/tests/Makefile.depend10
-rw-r--r--usr.bin/asa/tests/asa_test.sh111
-rw-r--r--usr.bin/at/LEGAL29
-rw-r--r--usr.bin/at/Makefile33
-rw-r--r--usr.bin/at/Makefile.depend15
-rw-r--r--usr.bin/at/Makefile.inc19
-rw-r--r--usr.bin/at/at.c914
-rw-r--r--usr.bin/at/at.h32
-rw-r--r--usr.bin/at/at.man377
-rw-r--r--usr.bin/at/atrun6
-rw-r--r--usr.bin/at/panic.c93
-rw-r--r--usr.bin/at/panic.h33
-rw-r--r--usr.bin/at/parsetime.c674
-rw-r--r--usr.bin/at/parsetime.h29
-rw-r--r--usr.bin/at/perm.c125
-rw-r--r--usr.bin/at/perm.h29
-rw-r--r--usr.bin/at/privs.h107
-rw-r--r--usr.bin/awk/Makefile36
-rw-r--r--usr.bin/awk/Makefile.depend18
-rw-r--r--usr.bin/awk/Makefile.depend.host11
-rw-r--r--usr.bin/awk/Makefile.depend.options6
-rw-r--r--usr.bin/awk/awk.1855
-rw-r--r--usr.bin/awk/tests/Makefile6
-rw-r--r--usr.bin/awk/tests/Makefile.depend0
-rw-r--r--usr.bin/awk/tests/bugs-fixed/Makefile12
-rw-r--r--usr.bin/awk/tests/bugs-fixed/Makefile.depend10
-rw-r--r--usr.bin/awk/tests/bugs-fixed/bug_fix_test.sh75
-rw-r--r--usr.bin/awk/tests/netbsd/Makefile34
-rw-r--r--usr.bin/awk/tests/netbsd/Makefile.depend10
-rw-r--r--usr.bin/backlight/Makefile4
-rw-r--r--usr.bin/backlight/backlight.8100
-rw-r--r--usr.bin/backlight/backlight.c224
-rw-r--r--usr.bin/banner/Makefile4
-rw-r--r--usr.bin/banner/Makefile.depend15
-rw-r--r--usr.bin/banner/banner.680
-rw-r--r--usr.bin/banner/banner.c1168
-rw-r--r--usr.bin/basename/Makefile9
-rw-r--r--usr.bin/basename/Makefile.depend17
-rw-r--r--usr.bin/basename/basename.1119
-rw-r--r--usr.bin/basename/basename.c134
-rw-r--r--usr.bin/basename/tests/Makefile5
-rw-r--r--usr.bin/basename/tests/Makefile.depend10
-rw-r--r--usr.bin/beep/Makefile7
-rw-r--r--usr.bin/beep/beep.182
-rw-r--r--usr.bin/beep/beep.c275
-rw-r--r--usr.bin/biff/Makefile3
-rw-r--r--usr.bin/biff/Makefile.depend15
-rw-r--r--usr.bin/biff/biff.1120
-rw-r--r--usr.bin/biff/biff.c100
-rw-r--r--usr.bin/bintrans/Makefile21
-rw-r--r--usr.bin/bintrans/Makefile.depend16
-rw-r--r--usr.bin/bintrans/bintrans.1284
-rw-r--r--usr.bin/bintrans/bintrans.c165
-rw-r--r--usr.bin/bintrans/qp.c218
-rw-r--r--usr.bin/bintrans/tests/Makefile13
-rw-r--r--usr.bin/bintrans/tests/Makefile.depend10
-rw-r--r--usr.bin/bintrans/tests/bintrans_test.sh35
-rw-r--r--usr.bin/bintrans/tests/legacy_test.sh5
-rw-r--r--usr.bin/bintrans/tests/regress.153276.in4
-rw-r--r--usr.bin/bintrans/tests/regress.153276.out1
-rw-r--r--usr.bin/bintrans/tests/regress.base64.in88
-rw-r--r--usr.bin/bintrans/tests/regress.base64.out74
-rw-r--r--usr.bin/bintrans/tests/regress.inbin0 -> 4096 bytes
-rw-r--r--usr.bin/bintrans/tests/regress.outbin0 -> 4096 bytes
-rw-r--r--usr.bin/bintrans/tests/regress.sh14
-rw-r--r--usr.bin/bintrans/tests/regress.traditional.in95
-rw-r--r--usr.bin/bintrans/tests/regress.traditional.out95
-rw-r--r--usr.bin/bintrans/tests/textqpdec2
-rw-r--r--usr.bin/bintrans/tests/textqpenc6
-rw-r--r--usr.bin/bintrans/uudecode.c486
-rw-r--r--usr.bin/bintrans/uuencode.c275
-rw-r--r--usr.bin/bintrans/uuencode.format.599
-rw-r--r--usr.bin/bluetooth/Makefile9
-rw-r--r--usr.bin/bluetooth/Makefile.inc2
-rw-r--r--usr.bin/bluetooth/bthost/Makefile9
-rw-r--r--usr.bin/bluetooth/bthost/Makefile.depend16
-rw-r--r--usr.bin/bluetooth/bthost/bthost.1114
-rw-r--r--usr.bin/bluetooth/bthost/bthost.c144
-rw-r--r--usr.bin/bluetooth/btsockstat/Makefile11
-rw-r--r--usr.bin/bluetooth/btsockstat/Makefile.depend17
-rw-r--r--usr.bin/bluetooth/btsockstat/btsockstat.182
-rw-r--r--usr.bin/bluetooth/btsockstat/btsockstat.c641
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/Makefile10
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/Makefile.depend18
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c267
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1185
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c461
-rw-r--r--usr.bin/bmake/Makefile203
-rw-r--r--usr.bin/bmake/Makefile.config28
-rw-r--r--usr.bin/bmake/Makefile.depend15
-rw-r--r--usr.bin/bmake/Makefile.inc37
-rw-r--r--usr.bin/bmake/config.h449
-rw-r--r--usr.bin/bmake/tests/Makefile15
-rw-r--r--usr.bin/bmake/tests/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/Makefile.inc1
-rw-r--r--usr.bin/bmake/tests/README173
-rw-r--r--usr.bin/bmake/tests/archives/Makefile5
-rw-r--r--usr.bin/bmake/tests/archives/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/Makefile31
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.test60
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.11
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.21
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.31
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.41
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.51
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.51
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.50
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.60
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.70
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/legacy_test.sh14
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd/libtest.abin0 -> 2104 bytes
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile31
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.test63
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.11
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.21
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.31
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.41
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.51
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.51
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.50
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.60
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.70
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/legacy_test.sh14
-rw-r--r--usr.bin/bmake/tests/archives/fmt_44bsd_mod/libtest.abin0 -> 2104 bytes
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.test61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.11
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.21
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.31
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.41
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.51
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.50
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.61
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.71
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.20
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.30
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.40
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.50
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.60
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.70
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/legacy_test.sh14
-rw-r--r--usr.bin/bmake/tests/archives/fmt_oldbsd/libtest.abin0 -> 2016 bytes
-rw-r--r--usr.bin/bmake/tests/basic/Makefile5
-rw-r--r--usr.bin/bmake/tests/basic/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/basic/t0/Makefile11
-rw-r--r--usr.bin/bmake/tests/basic/t0/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/basic/t0/expected.status.11
-rw-r--r--usr.bin/bmake/tests/basic/t0/expected.stderr.11
-rw-r--r--usr.bin/bmake/tests/basic/t0/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/basic/t0/legacy_test.sh15
-rw-r--r--usr.bin/bmake/tests/basic/t1/Makefile12
-rw-r--r--usr.bin/bmake/tests/basic/t1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/basic/t1/Makefile.test4
-rw-r--r--usr.bin/bmake/tests/basic/t1/expected.status.11
-rw-r--r--usr.bin/bmake/tests/basic/t1/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/basic/t1/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/basic/t1/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/basic/t2/Makefile12
-rw-r--r--usr.bin/bmake/tests/basic/t2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/basic/t2/Makefile.test5
-rw-r--r--usr.bin/bmake/tests/basic/t2/expected.status.11
-rw-r--r--usr.bin/bmake/tests/basic/t2/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/basic/t2/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/basic/t2/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/basic/t3/Makefile11
-rw-r--r--usr.bin/bmake/tests/basic/t3/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/basic/t3/expected.status.11
-rw-r--r--usr.bin/bmake/tests/basic/t3/expected.stderr.11
-rw-r--r--usr.bin/bmake/tests/basic/t3/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/basic/t3/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/common.sh532
-rw-r--r--usr.bin/bmake/tests/execution/Makefile5
-rw-r--r--usr.bin/bmake/tests/execution/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/Makefile12
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/Makefile.test19
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/expected.status.11
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/expected.stdout.112
-rw-r--r--usr.bin/bmake/tests/execution/ellipsis/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/execution/empty/Makefile12
-rw-r--r--usr.bin/bmake/tests/execution/empty/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/execution/empty/Makefile.test11
-rw-r--r--usr.bin/bmake/tests/execution/empty/expected.status.11
-rw-r--r--usr.bin/bmake/tests/execution/empty/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/execution/empty/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/execution/empty/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/execution/joberr/Makefile12
-rw-r--r--usr.bin/bmake/tests/execution/joberr/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/execution/joberr/Makefile.test8
-rw-r--r--usr.bin/bmake/tests/execution/joberr/expected.status.11
-rw-r--r--usr.bin/bmake/tests/execution/joberr/expected.stderr.130
-rw-r--r--usr.bin/bmake/tests/execution/joberr/expected.stdout.190
-rw-r--r--usr.bin/bmake/tests/execution/joberr/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/execution/plus/Makefile12
-rw-r--r--usr.bin/bmake/tests/execution/plus/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/execution/plus/Makefile.test5
-rw-r--r--usr.bin/bmake/tests/execution/plus/expected.status.11
-rw-r--r--usr.bin/bmake/tests/execution/plus/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/execution/plus/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/execution/plus/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/shell/Makefile5
-rw-r--r--usr.bin/bmake/tests/shell/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/builtin/Makefile16
-rw-r--r--usr.bin/bmake/tests/shell/builtin/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/builtin/Makefile.test17
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/shell/builtin/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/shell/builtin/legacy_test.sh16
-rw-r--r--usr.bin/bmake/tests/shell/builtin/sh5
-rw-r--r--usr.bin/bmake/tests/shell/meta/Makefile16
-rw-r--r--usr.bin/bmake/tests/shell/meta/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/meta/Makefile.test17
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/shell/meta/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/shell/meta/legacy_test.sh16
-rw-r--r--usr.bin/bmake/tests/shell/meta/sh5
-rw-r--r--usr.bin/bmake/tests/shell/path/Makefile16
-rw-r--r--usr.bin/bmake/tests/shell/path/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/path/Makefile.test30
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/shell/path/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/shell/path/legacy_test.sh19
-rw-r--r--usr.bin/bmake/tests/shell/path/sh5
-rw-r--r--usr.bin/bmake/tests/shell/path_select/Makefile16
-rw-r--r--usr.bin/bmake/tests/shell/path_select/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/path_select/Makefile.test30
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/shell/path_select/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/shell/path_select/legacy_test.sh18
-rw-r--r--usr.bin/bmake/tests/shell/path_select/shell5
-rw-r--r--usr.bin/bmake/tests/shell/replace/Makefile16
-rw-r--r--usr.bin/bmake/tests/shell/replace/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/replace/Makefile.test20
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.stdout.13
-rw-r--r--usr.bin/bmake/tests/shell/replace/expected.stdout.26
-rw-r--r--usr.bin/bmake/tests/shell/replace/legacy_test.sh16
-rw-r--r--usr.bin/bmake/tests/shell/replace/shell5
-rw-r--r--usr.bin/bmake/tests/shell/select/Makefile15
-rw-r--r--usr.bin/bmake/tests/shell/select/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/shell/select/Makefile.test27
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.status.11
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.status.21
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/shell/select/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/shell/select/legacy_test.sh15
-rw-r--r--usr.bin/bmake/tests/suffixes/Makefile5
-rw-r--r--usr.bin/bmake/tests/suffixes/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/Makefile13
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/Makefile.test12
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/TEST1.a1
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/expected.status.11
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/suffixes/basic/legacy_test.sh18
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/Makefile14
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/Makefile.test5
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/TEST1.a1
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/TEST2.a1
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/expected.status.11
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild1/legacy_test.sh18
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/Makefile14
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/Makefile.test11
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/TEST1.a1
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/TEST2.a1
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/expected.status.11
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/suffixes/src_wild2/legacy_test.sh18
-rw-r--r--usr.bin/bmake/tests/syntax/Makefile5
-rw-r--r--usr.bin/bmake/tests/syntax/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/Makefile12
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/Makefile.test7
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/expected.status.11
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/expected.stderr.12
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/expected.stdout.10
-rw-r--r--usr.bin/bmake/tests/syntax/directive-t0/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/syntax/enl/Makefile24
-rw-r--r--usr.bin/bmake/tests/syntax/enl/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/syntax/enl/Makefile.test58
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.status.11
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.status.21
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.status.31
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.status.41
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.status.51
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stderr.30
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stderr.40
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stderr.50
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stdout.32
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stdout.41
-rw-r--r--usr.bin/bmake/tests/syntax/enl/expected.stdout.51
-rw-r--r--usr.bin/bmake/tests/syntax/enl/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/Makefile15
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/Makefile.test13
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.status.11
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.status.21
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/syntax/funny-targets/legacy_test.sh11
-rw-r--r--usr.bin/bmake/tests/syntax/semi/Makefile15
-rw-r--r--usr.bin/bmake/tests/syntax/semi/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/syntax/semi/Makefile.test25
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.status.11
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.status.21
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/syntax/semi/expected.stdout.22
-rw-r--r--usr.bin/bmake/tests/syntax/semi/legacy_test.sh12
-rw-r--r--usr.bin/bmake/tests/sysmk/Makefile5
-rw-r--r--usr.bin/bmake/tests/sysmk/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/Makefile12
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.test5
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/expected.status.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/1/legacy_test.sh14
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/Makefile5
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/Makefile6
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/mk/Makefile9
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/mk/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t0/mk/sys.mk.test2
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/Makefile12
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/cleanup2
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/expected.status.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/1/legacy_test.sh16
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/Makefile5
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/Makefile6
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/mk/Makefile9
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/mk/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t1/mk/sys.mk.test2
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/Makefile12
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/cleanup2
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/expected.status.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/1/legacy_test.sh16
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/Makefile5
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/Makefile6
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/mk/Makefile9
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/mk/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/sysmk/t2/mk/sys.mk.test2
-rw-r--r--usr.bin/bmake/tests/test-new.mk8
-rw-r--r--usr.bin/bmake/tests/variables/Makefile5
-rw-r--r--usr.bin/bmake/tests/variables/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/Makefile12
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/Makefile.test17
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/expected.status.11
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/expected.stdout.17
-rw-r--r--usr.bin/bmake/tests/variables/modifier_M/legacy_test.sh8
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/Makefile18
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/Makefile.test14
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.status.11
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.status.21
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.status.31
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stderr.30
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stdout.11
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stdout.21
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/expected.stdout.31
-rw-r--r--usr.bin/bmake/tests/variables/modifier_t/legacy_test.sh11
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/Makefile15
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/Makefile.test14
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.status.11
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.status.21
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.stderr.20
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.stdout.12
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/expected.stdout.22
-rw-r--r--usr.bin/bmake/tests/variables/opt_V/legacy_test.sh11
-rw-r--r--usr.bin/bmake/tests/variables/t0/Makefile12
-rw-r--r--usr.bin/bmake/tests/variables/t0/Makefile.depend10
-rw-r--r--usr.bin/bmake/tests/variables/t0/Makefile.test22
-rw-r--r--usr.bin/bmake/tests/variables/t0/expected.status.11
-rw-r--r--usr.bin/bmake/tests/variables/t0/expected.stderr.10
-rw-r--r--usr.bin/bmake/tests/variables/t0/expected.stdout.115
-rw-r--r--usr.bin/bmake/tests/variables/t0/legacy_test.sh8
-rw-r--r--usr.bin/bmake/unit-tests/Makefile918
-rw-r--r--usr.bin/bmake/unit-tests/Makefile.config13
-rw-r--r--usr.bin/brandelf/Makefile11
-rw-r--r--usr.bin/brandelf/Makefile.depend16
-rw-r--r--usr.bin/brandelf/Makefile.depend.options7
-rw-r--r--usr.bin/brandelf/brandelf.1102
-rw-r--r--usr.bin/brandelf/brandelf.c231
-rw-r--r--usr.bin/bsdcat/Makefile29
-rw-r--r--usr.bin/bsdcat/Makefile.depend16
-rw-r--r--usr.bin/bsdcat/tests/Makefile74
-rw-r--r--usr.bin/bsdcat/tests/Makefile.depend14
-rwxr-xr-xusr.bin/bsdcat/tests/functional_test.sh55
-rw-r--r--usr.bin/bsddialog/Makefile13
-rw-r--r--usr.bin/bsdiff/Makefile3
-rw-r--r--usr.bin/bsdiff/Makefile.inc1
-rw-r--r--usr.bin/bsdiff/bsdiff/Makefile16
-rw-r--r--usr.bin/bsdiff/bsdiff/Makefile.depend16
-rw-r--r--usr.bin/bsdiff/bsdiff/bsdiff.186
-rw-r--r--usr.bin/bsdiff/bsdiff/bsdiff.c336
-rw-r--r--usr.bin/bsdiff/bsdiff/config.h81
-rw-r--r--usr.bin/bsdiff/bsdiff/divsufsort64.h180
-rw-r--r--usr.bin/bsdiff/bspatch/Makefile5
-rw-r--r--usr.bin/bsdiff/bspatch/Makefile.depend16
-rw-r--r--usr.bin/bsdiff/bspatch/bspatch.185
-rw-r--r--usr.bin/bsdiff/bspatch/bspatch.c302
-rw-r--r--usr.bin/bzip2/Makefile50
-rw-r--r--usr.bin/bzip2/Makefile.depend17
-rw-r--r--usr.bin/bzip2recover/Makefile9
-rw-r--r--usr.bin/bzip2recover/Makefile.depend15
-rw-r--r--usr.bin/c89/Makefile3
-rw-r--r--usr.bin/c89/Makefile.depend15
-rw-r--r--usr.bin/c89/c89.1182
-rw-r--r--usr.bin/c89/c89.c111
-rw-r--r--usr.bin/c99/Makefile3
-rw-r--r--usr.bin/c99/Makefile.depend15
-rw-r--r--usr.bin/c99/c99.1189
-rw-r--r--usr.bin/c99/c99.c132
-rw-r--r--usr.bin/caesar/Makefile9
-rw-r--r--usr.bin/caesar/Makefile.depend16
-rw-r--r--usr.bin/caesar/caesar.670
-rw-r--r--usr.bin/caesar/caesar.c145
-rw-r--r--usr.bin/caesar/rot13.sh30
-rw-r--r--usr.bin/calendar/Makefile19
-rw-r--r--usr.bin/calendar/Makefile.depend17
-rw-r--r--usr.bin/calendar/calendar.1372
-rw-r--r--usr.bin/calendar/calendar.c244
-rw-r--r--usr.bin/calendar/calendar.h203
-rw-r--r--usr.bin/calendar/calendars/calendar.freebsd509
-rw-r--r--usr.bin/calendar/dates.c457
-rw-r--r--usr.bin/calendar/day.c107
-rw-r--r--usr.bin/calendar/events.c235
-rw-r--r--usr.bin/calendar/io.c728
-rw-r--r--usr.bin/calendar/locale.c166
-rw-r--r--usr.bin/calendar/ostern.c67
-rw-r--r--usr.bin/calendar/parsedata.c1121
-rw-r--r--usr.bin/calendar/paskha.c66
-rw-r--r--usr.bin/calendar/pathnames.h35
-rw-r--r--usr.bin/calendar/pom.c264
-rw-r--r--usr.bin/calendar/sunpos.c448
-rw-r--r--usr.bin/calendar/tests/Makefile49
-rw-r--r--usr.bin/calendar/tests/Makefile.depend10
-rw-r--r--usr.bin/calendar/tests/calendar.calibrate373
-rw-r--r--usr.bin/calendar/tests/calendar.comment11
-rw-r--r--usr.bin/calendar/tests/calendar.cond83
-rwxr-xr-xusr.bin/calendar/tests/comment.sh13
-rwxr-xr-xusr.bin/calendar/tests/comment_test.sh5
-rwxr-xr-xusr.bin/calendar/tests/cond.sh13
-rwxr-xr-xusr.bin/calendar/tests/cond_test.sh5
-rw-r--r--usr.bin/calendar/tests/legacy_test.sh5
-rw-r--r--usr.bin/calendar/tests/regress.a1.out4
-rw-r--r--usr.bin/calendar/tests/regress.a2.out4
-rw-r--r--usr.bin/calendar/tests/regress.a3.out4
-rw-r--r--usr.bin/calendar/tests/regress.a4.out4
-rw-r--r--usr.bin/calendar/tests/regress.a5.out4
-rw-r--r--usr.bin/calendar/tests/regress.b1.out4
-rw-r--r--usr.bin/calendar/tests/regress.b2.out4
-rw-r--r--usr.bin/calendar/tests/regress.b3.out4
-rw-r--r--usr.bin/calendar/tests/regress.b4.out4
-rw-r--r--usr.bin/calendar/tests/regress.b5.out4
-rw-r--r--usr.bin/calendar/tests/regress.comment.out10
-rw-r--r--usr.bin/calendar/tests/regress.cond.out10
-rw-r--r--usr.bin/calendar/tests/regress.s1.out4
-rw-r--r--usr.bin/calendar/tests/regress.s2.out2
-rw-r--r--usr.bin/calendar/tests/regress.s3.out2
-rw-r--r--usr.bin/calendar/tests/regress.s4.out2
-rw-r--r--usr.bin/calendar/tests/regress.s5.out3
-rw-r--r--usr.bin/calendar/tests/regress.sh45
-rw-r--r--usr.bin/calendar/tests/regress.w0-1.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-2.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-3.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-4.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-5.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-6.out1
-rw-r--r--usr.bin/calendar/tests/regress.w0-7.out1
-rw-r--r--usr.bin/calendar/tests/regress.wn-1.out1
-rw-r--r--usr.bin/calendar/tests/regress.wn-2.out2
-rw-r--r--usr.bin/calendar/tests/regress.wn-3.out3
-rw-r--r--usr.bin/calendar/tests/regress.wn-4.out4
-rw-r--r--usr.bin/calendar/tests/regress.wn-5.out5
-rw-r--r--usr.bin/calendar/tests/regress.wn-6.out6
-rw-r--r--usr.bin/calendar/tests/regress.wn-7.out7
-rw-r--r--usr.bin/cap_mkdb/Makefile3
-rw-r--r--usr.bin/cap_mkdb/Makefile.depend15
-rw-r--r--usr.bin/cap_mkdb/Makefile.depend.host10
-rw-r--r--usr.bin/cap_mkdb/Makefile.depend.options6
-rw-r--r--usr.bin/cap_mkdb/cap_mkdb.1102
-rw-r--r--usr.bin/cap_mkdb/cap_mkdb.c255
-rw-r--r--usr.bin/chat/Makefile7
-rw-r--r--usr.bin/chat/Makefile.depend15
-rw-r--r--usr.bin/chat/chat.8644
-rw-r--r--usr.bin/chat/chat.c1526
-rw-r--r--usr.bin/chpass/Makefile42
-rw-r--r--usr.bin/chpass/Makefile.depend17
-rw-r--r--usr.bin/chpass/Makefile.depend.options7
-rw-r--r--usr.bin/chpass/chpass.1488
-rw-r--r--usr.bin/chpass/chpass.c293
-rw-r--r--usr.bin/chpass/chpass.h78
-rw-r--r--usr.bin/chpass/edit.c289
-rw-r--r--usr.bin/chpass/field.c254
-rw-r--r--usr.bin/chpass/table.c56
-rw-r--r--usr.bin/chpass/util.c188
-rw-r--r--usr.bin/cksum/Makefile6
-rw-r--r--usr.bin/cksum/Makefile.depend15
-rw-r--r--usr.bin/cksum/cksum.1188
-rw-r--r--usr.bin/cksum/cksum.c123
-rw-r--r--usr.bin/cksum/crc.c137
-rw-r--r--usr.bin/cksum/crc32.c119
-rw-r--r--usr.bin/cksum/extern.h42
-rw-r--r--usr.bin/cksum/print.c64
-rw-r--r--usr.bin/cksum/sum1.c65
-rw-r--r--usr.bin/cksum/sum2.c68
-rw-r--r--usr.bin/clang/Makefile70
-rw-r--r--usr.bin/clang/Makefile.inc15
-rw-r--r--usr.bin/clang/bugpoint/Makefile14
-rw-r--r--usr.bin/clang/bugpoint/Makefile.depend23
-rw-r--r--usr.bin/clang/bugpoint/bugpoint.1308
-rw-r--r--usr.bin/clang/clang-format/Makefile7
-rw-r--r--usr.bin/clang/clang-format/Makefile.depend23
-rw-r--r--usr.bin/clang/clang-tblgen/Makefile31
-rw-r--r--usr.bin/clang/clang-tblgen/Makefile.depend26
-rw-r--r--usr.bin/clang/clang-tblgen/Makefile.depend.host13
-rw-r--r--usr.bin/clang/clang.prog.mk34
-rwxr-xr-xusr.bin/clang/clang/CC.sh3
-rw-r--r--usr.bin/clang/clang/Makefile31
-rw-r--r--usr.bin/clang/clang/Makefile.depend26
-rw-r--r--usr.bin/clang/clang/clang-driver.cpp18
-rw-r--r--usr.bin/clang/clang/clang.1949
-rw-r--r--usr.bin/clang/llc/Makefile7
-rw-r--r--usr.bin/clang/llc/Makefile.depend23
-rw-r--r--usr.bin/clang/llc/llc.1295
-rw-r--r--usr.bin/clang/lld/Makefile109
-rw-r--r--usr.bin/clang/lld/Makefile.depend25
-rw-r--r--usr.bin/clang/lld/lld-driver.cpp18
-rw-r--r--usr.bin/clang/lldb-server/Makefile53
-rw-r--r--usr.bin/clang/lldb-server/Makefile.depend32
-rw-r--r--usr.bin/clang/lldb-server/lldb-server.1261
-rw-r--r--usr.bin/clang/lldb-tblgen/Makefile10
-rw-r--r--usr.bin/clang/lldb-tblgen/Makefile.depend11
-rw-r--r--usr.bin/clang/lldb/Makefile47
-rw-r--r--usr.bin/clang/lldb/Makefile.depend33
-rw-r--r--usr.bin/clang/lldb/lldb.1429
-rw-r--r--usr.bin/clang/lli/Makefile6
-rw-r--r--usr.bin/clang/lli/Makefile.depend23
-rw-r--r--usr.bin/clang/lli/lli.1300
-rw-r--r--usr.bin/clang/llvm-ar/Makefile17
-rw-r--r--usr.bin/clang/llvm-ar/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-ar/llvm-ar-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-ar/llvm-ar.1469
-rw-r--r--usr.bin/clang/llvm-ar/llvm-ranlib.151
-rw-r--r--usr.bin/clang/llvm-as/Makefile6
-rw-r--r--usr.bin/clang/llvm-as/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-as/llvm-as.186
-rw-r--r--usr.bin/clang/llvm-bcanalyzer/Makefile6
-rw-r--r--usr.bin/clang/llvm-bcanalyzer/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1461
-rw-r--r--usr.bin/clang/llvm-cov/Makefile21
-rw-r--r--usr.bin/clang/llvm-cov/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-cov/llvm-cov.1583
-rw-r--r--usr.bin/clang/llvm-cxxdump/Makefile8
-rw-r--r--usr.bin/clang/llvm-cxxdump/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-cxxfilt/Makefile30
-rw-r--r--usr.bin/clang/llvm-cxxfilt/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt.1117
-rw-r--r--usr.bin/clang/llvm-diff/Makefile9
-rw-r--r--usr.bin/clang/llvm-diff/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-diff/llvm-diff.176
-rw-r--r--usr.bin/clang/llvm-dis/Makefile6
-rw-r--r--usr.bin/clang/llvm-dis/Makefile.depend22
-rw-r--r--usr.bin/clang/llvm-dis/llvm-dis.187
-rw-r--r--usr.bin/clang/llvm-dwarfdump/Makefile8
-rw-r--r--usr.bin/clang/llvm-dwarfdump/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-dwarfdump/llvm-dwarfdump.1272
-rw-r--r--usr.bin/clang/llvm-dwarfutil/Makefile23
-rw-r--r--usr.bin/clang/llvm-dwarfutil/llvm-dwarfutil.1168
-rw-r--r--usr.bin/clang/llvm-dwp/Makefile24
-rw-r--r--usr.bin/clang/llvm-dwp/llvm-dwp-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-extract/Makefile6
-rw-r--r--usr.bin/clang/llvm-extract/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-extract/llvm-extract.1176
-rw-r--r--usr.bin/clang/llvm-link/Makefile6
-rw-r--r--usr.bin/clang/llvm-link/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-link/llvm-link.188
-rw-r--r--usr.bin/clang/llvm-lto/Makefile7
-rw-r--r--usr.bin/clang/llvm-lto/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-lto2/Makefile7
-rw-r--r--usr.bin/clang/llvm-lto2/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-mc/Makefile8
-rw-r--r--usr.bin/clang/llvm-mc/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-mca/Makefile21
-rw-r--r--usr.bin/clang/llvm-mca/llvm-mca.11368
-rw-r--r--usr.bin/clang/llvm-min-tblgen/Makefile8
-rw-r--r--usr.bin/clang/llvm-min-tblgen/Makefile.depend24
-rw-r--r--usr.bin/clang/llvm-min-tblgen/Makefile.depend.host12
-rw-r--r--usr.bin/clang/llvm-modextract/Makefile7
-rw-r--r--usr.bin/clang/llvm-modextract/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-nm/Makefile30
-rw-r--r--usr.bin/clang/llvm-nm/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-nm/llvm-nm-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-nm/llvm-nm.1447
-rw-r--r--usr.bin/clang/llvm-objcopy/Makefile36
-rw-r--r--usr.bin/clang/llvm-objcopy/llvm-objcopy-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-objcopy/llvm-objcopy.1748
-rw-r--r--usr.bin/clang/llvm-objdump/Makefile35
-rw-r--r--usr.bin/clang/llvm-objdump/Makefile.depend25
-rw-r--r--usr.bin/clang/llvm-objdump/llvm-objdump-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-objdump/llvm-objdump.1578
-rw-r--r--usr.bin/clang/llvm-pdbutil/Makefile25
-rw-r--r--usr.bin/clang/llvm-pdbutil/Makefile.depend22
-rw-r--r--usr.bin/clang/llvm-pdbutil/llvm-pdbutil.1744
-rw-r--r--usr.bin/clang/llvm-profdata/Makefile7
-rw-r--r--usr.bin/clang/llvm-profdata/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-profdata/llvm-profdata-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-profdata/llvm-profdata.1466
-rw-r--r--usr.bin/clang/llvm-readobj/Makefile43
-rw-r--r--usr.bin/clang/llvm-readobj/llvm-readelf.1291
-rw-r--r--usr.bin/clang/llvm-readobj/llvm-readobj-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-readobj/llvm-readobj.1445
-rw-r--r--usr.bin/clang/llvm-rtdyld/Makefile7
-rw-r--r--usr.bin/clang/llvm-rtdyld/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-size/Makefile30
-rw-r--r--usr.bin/clang/llvm-size/llvm-size-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-size/llvm-size.1269
-rw-r--r--usr.bin/clang/llvm-strings/Makefile29
-rw-r--r--usr.bin/clang/llvm-strings/llvm-strings.1173
-rw-r--r--usr.bin/clang/llvm-symbolizer/Makefile33
-rw-r--r--usr.bin/clang/llvm-symbolizer/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm-symbolizer/llvm-addr2line.172
-rw-r--r--usr.bin/clang/llvm-symbolizer/llvm-symbolizer-driver.cpp18
-rw-r--r--usr.bin/clang/llvm-symbolizer/llvm-symbolizer.1660
-rw-r--r--usr.bin/clang/llvm-tblgen/Makefile90
-rw-r--r--usr.bin/clang/llvm-tblgen/Makefile.depend25
-rw-r--r--usr.bin/clang/llvm-tblgen/Makefile.depend.host13
-rw-r--r--usr.bin/clang/llvm-xray/Makefile16
-rw-r--r--usr.bin/clang/llvm-xray/Makefile.depend23
-rw-r--r--usr.bin/clang/llvm.prog.mk32
-rw-r--r--usr.bin/clang/opt/Makefile8
-rw-r--r--usr.bin/clang/opt/Makefile.depend23
-rw-r--r--usr.bin/clang/opt/opt.1147
-rw-r--r--usr.bin/cmp/Makefile11
-rw-r--r--usr.bin/cmp/Makefile.depend18
-rw-r--r--usr.bin/cmp/cmp.1210
-rw-r--r--usr.bin/cmp/cmp.c269
-rw-r--r--usr.bin/cmp/extern.h48
-rw-r--r--usr.bin/cmp/link.c103
-rw-r--r--usr.bin/cmp/misc.c62
-rw-r--r--usr.bin/cmp/regular.c191
-rw-r--r--usr.bin/cmp/special.c126
-rw-r--r--usr.bin/cmp/tests/Makefile13
-rw-r--r--usr.bin/cmp/tests/Makefile.depend10
-rw-r--r--usr.bin/cmp/tests/b_flag.out1
-rw-r--r--usr.bin/cmp/tests/bl_flag.out1
-rwxr-xr-xusr.bin/cmp/tests/cmp_test2.sh175
-rw-r--r--usr.bin/col/Makefile8
-rw-r--r--usr.bin/col/Makefile.depend17
-rw-r--r--usr.bin/col/README45
-rw-r--r--usr.bin/col/col.1168
-rw-r--r--usr.bin/col/col.c592
-rw-r--r--usr.bin/col/tests/Makefile15
-rw-r--r--usr.bin/col/tests/Makefile.depend10
-rwxr-xr-xusr.bin/col/tests/col_test.sh112
-rw-r--r--usr.bin/col/tests/hlf.in2
-rw-r--r--usr.bin/col/tests/hlf2.in1
-rw-r--r--usr.bin/col/tests/nl.in2
-rw-r--r--usr.bin/col/tests/nl2.in2
-rw-r--r--usr.bin/col/tests/nl3.in4
-rw-r--r--usr.bin/col/tests/rlf.in2
-rw-r--r--usr.bin/col/tests/rlf2.in2
-rw-r--r--usr.bin/col/tests/rlf3.in1
-rw-r--r--usr.bin/colrm/Makefile3
-rw-r--r--usr.bin/colrm/Makefile.depend15
-rw-r--r--usr.bin/colrm/colrm.1109
-rw-r--r--usr.bin/colrm/colrm.c134
-rw-r--r--usr.bin/column/Makefile3
-rw-r--r--usr.bin/column/Makefile.depend15
-rw-r--r--usr.bin/column/column.198
-rw-r--r--usr.bin/column/column.c326
-rw-r--r--usr.bin/comm/Makefile8
-rw-r--r--usr.bin/comm/Makefile.depend15
-rw-r--r--usr.bin/comm/comm.1142
-rw-r--r--usr.bin/comm/comm.c239
-rw-r--r--usr.bin/comm/tests/Makefile16
-rw-r--r--usr.bin/comm/tests/Makefile.depend10
-rw-r--r--usr.bin/comm/tests/legacy_test.sh5
-rw-r--r--usr.bin/comm/tests/regress.00.out2
-rw-r--r--usr.bin/comm/tests/regress.00a.in5
-rw-r--r--usr.bin/comm/tests/regress.00b.in2
-rw-r--r--usr.bin/comm/tests/regress.01.out2
-rw-r--r--usr.bin/comm/tests/regress.01a.in5
-rw-r--r--usr.bin/comm/tests/regress.01b.in2
-rw-r--r--usr.bin/comm/tests/regress.02.out5
-rw-r--r--usr.bin/comm/tests/regress.02a.in3
-rw-r--r--usr.bin/comm/tests/regress.02b.in3
-rw-r--r--usr.bin/comm/tests/regress.sh10
-rw-r--r--usr.bin/compile_et/Makefile23
-rw-r--r--usr.bin/compile_et/Makefile.depend19
-rw-r--r--usr.bin/compress/Makefile14
-rw-r--r--usr.bin/compress/Makefile.depend15
-rw-r--r--usr.bin/compress/compress.1293
-rw-r--r--usr.bin/compress/compress.c426
-rw-r--r--usr.bin/compress/doc/NOTES140
-rw-r--r--usr.bin/compress/doc/README280
-rw-r--r--usr.bin/compress/doc/revision.log117
-rw-r--r--usr.bin/compress/tests/Makefile5
-rw-r--r--usr.bin/compress/tests/Makefile.depend10
-rwxr-xr-xusr.bin/compress/tests/compress_test.sh195
-rw-r--r--usr.bin/compress/zopen.3134
-rw-r--r--usr.bin/compress/zopen.c736
-rw-r--r--usr.bin/compress/zopen.h34
-rw-r--r--usr.bin/cpio/Makefile32
-rw-r--r--usr.bin/cpio/Makefile.depend16
-rw-r--r--usr.bin/cpio/tests/Makefile126
-rw-r--r--usr.bin/cpio/tests/Makefile.depend14
-rwxr-xr-xusr.bin/cpio/tests/functional_test.sh55
-rw-r--r--usr.bin/csplit/Makefile8
-rw-r--r--usr.bin/csplit/Makefile.depend15
-rw-r--r--usr.bin/csplit/csplit.1167
-rw-r--r--usr.bin/csplit/csplit.c468
-rw-r--r--usr.bin/csplit/tests/Makefile5
-rw-r--r--usr.bin/csplit/tests/Makefile.depend10
-rwxr-xr-xusr.bin/csplit/tests/csplit_test.sh59
-rw-r--r--usr.bin/ctags/C.c557
-rw-r--r--usr.bin/ctags/Makefile5
-rw-r--r--usr.bin/ctags/Makefile.depend15
-rw-r--r--usr.bin/ctags/ctags.1258
-rw-r--r--usr.bin/ctags/ctags.c330
-rw-r--r--usr.bin/ctags/ctags.h93
-rw-r--r--usr.bin/ctags/fortran.c162
-rw-r--r--usr.bin/ctags/lisp.c100
-rw-r--r--usr.bin/ctags/print.c107
-rw-r--r--usr.bin/ctags/test/ctags.test67
-rw-r--r--usr.bin/ctags/tree.c127
-rw-r--r--usr.bin/ctags/yacc.c145
-rw-r--r--usr.bin/ctlstat/Makefile8
-rw-r--r--usr.bin/ctlstat/Makefile.depend17
-rw-r--r--usr.bin/ctlstat/ctlstat.8142
-rw-r--r--usr.bin/ctlstat/ctlstat.c1011
-rw-r--r--usr.bin/cut/Makefile8
-rw-r--r--usr.bin/cut/Makefile.depend15
-rw-r--r--usr.bin/cut/cut.1170
-rw-r--r--usr.bin/cut/cut.c481
-rw-r--r--usr.bin/cut/tests/Makefile16
-rw-r--r--usr.bin/cut/tests/Makefile.depend10
-rwxr-xr-xusr.bin/cut/tests/cut2_test.sh50
-rw-r--r--usr.bin/cxxfilt/Makefile17
-rw-r--r--usr.bin/cxxfilt/Makefile.depend19
-rw-r--r--usr.bin/dc/tests/Makefile.depend10
-rw-r--r--usr.bin/diff/Makefile12
-rw-r--r--usr.bin/diff/TODO9
-rw-r--r--usr.bin/diff/diff.1821
-rw-r--r--usr.bin/diff/diff.c689
-rw-r--r--usr.bin/diff/diff.h128
-rw-r--r--usr.bin/diff/diffdir.c314
-rw-r--r--usr.bin/diff/diffreg.c1736
-rw-r--r--usr.bin/diff/diffreg_new.c335
-rw-r--r--usr.bin/diff/pr.c122
-rw-r--r--usr.bin/diff/pr.h36
-rw-r--r--usr.bin/diff/tests/Bflag_C.out2
-rw-r--r--usr.bin/diff/tests/Bflag_D.out2
-rw-r--r--usr.bin/diff/tests/Bflag_F.out4
-rw-r--r--usr.bin/diff/tests/Makefile50
-rw-r--r--usr.bin/diff/tests/Makefile.depend10
-rwxr-xr-xusr.bin/diff/tests/diff_test.sh393
-rw-r--r--usr.bin/diff/tests/functionname.in29
-rw-r--r--usr.bin/diff/tests/functionname_c.in29
-rw-r--r--usr.bin/diff/tests/functionname_c.out11
-rw-r--r--usr.bin/diff/tests/functionname_objcclassm.in31
-rw-r--r--usr.bin/diff/tests/functionname_objcclassm.out11
-rw-r--r--usr.bin/diff/tests/functionname_objcm.in29
-rw-r--r--usr.bin/diff/tests/functionname_objcm.out11
-rw-r--r--usr.bin/diff/tests/group-format.out27
-rw-r--r--usr.bin/diff/tests/header.out4
-rw-r--r--usr.bin/diff/tests/header_ns.out4
-rw-r--r--usr.bin/diff/tests/ifdef.out26
-rw-r--r--usr.bin/diff/tests/input1.in2
-rw-r--r--usr.bin/diff/tests/input2.in3
-rw-r--r--usr.bin/diff/tests/input_c1.in15
-rw-r--r--usr.bin/diff/tests/input_c2.in16
-rw-r--r--usr.bin/diff/tests/side_by_side_tabbed_a.in4
-rw-r--r--usr.bin/diff/tests/side_by_side_tabbed_b.in4
-rw-r--r--usr.bin/diff/tests/simple.out5
-rw-r--r--usr.bin/diff/tests/simple_b.out6
-rw-r--r--usr.bin/diff/tests/simple_e.out4
-rw-r--r--usr.bin/diff/tests/simple_i.out6
-rw-r--r--usr.bin/diff/tests/simple_n.out4
-rw-r--r--usr.bin/diff/tests/simple_p.out34
-rw-r--r--usr.bin/diff/tests/simple_u.out7
-rw-r--r--usr.bin/diff/tests/simple_w.out6
-rw-r--r--usr.bin/diff/tests/strip_o.out7
-rw-r--r--usr.bin/diff/tests/unified_9999.out21
-rw-r--r--usr.bin/diff/tests/unified_c9999.out36
-rw-r--r--usr.bin/diff/tests/unified_p.out20
-rw-r--r--usr.bin/diff/xmalloc.c85
-rw-r--r--usr.bin/diff/xmalloc.h30
-rw-r--r--usr.bin/diff3/Makefile8
-rw-r--r--usr.bin/diff3/diff3.1221
-rw-r--r--usr.bin/diff3/diff3.c1115
-rw-r--r--usr.bin/diff3/tests/1.out14
-rw-r--r--usr.bin/diff3/tests/1.txt6
-rw-r--r--usr.bin/diff3/tests/1cr.txt6
-rw-r--r--usr.bin/diff3/tests/1t.out14
-rw-r--r--usr.bin/diff3/tests/2.out3
-rw-r--r--usr.bin/diff3/tests/2.txt7
-rw-r--r--usr.bin/diff3/tests/3.out8
-rw-r--r--usr.bin/diff3/tests/3.txt5
-rw-r--r--usr.bin/diff3/tests/4.out8
-rw-r--r--usr.bin/diff3/tests/5.out3
-rw-r--r--usr.bin/diff3/tests/6.out0
-rw-r--r--usr.bin/diff3/tests/7.out14
-rw-r--r--usr.bin/diff3/tests/8.out19
-rw-r--r--usr.bin/diff3/tests/9.out17
-rw-r--r--usr.bin/diff3/tests/Makefile28
-rw-r--r--usr.bin/diff3/tests/Makefile.depend10
-rwxr-xr-xusr.bin/diff3/tests/diff3_test.sh108
-rw-r--r--usr.bin/diff3/tests/fbsdid1.txt5
-rw-r--r--usr.bin/diff3/tests/fbsdid2.txt5
-rw-r--r--usr.bin/diff3/tests/long-A.out22
-rw-r--r--usr.bin/diff3/tests/long-ed.out7
-rw-r--r--usr.bin/diff3/tests/long-m.txt26
-rw-r--r--usr.bin/diff3/tests/long-merge.out35
-rw-r--r--usr.bin/diff3/tests/long-o.txt27
-rw-r--r--usr.bin/diff3/tests/long-y.txt26
-rw-r--r--usr.bin/dirname/Makefile9
-rw-r--r--usr.bin/dirname/Makefile.depend17
-rw-r--r--usr.bin/dirname/dirname.c77
-rw-r--r--usr.bin/dirname/tests/Makefile5
-rw-r--r--usr.bin/dirname/tests/Makefile.depend10
-rw-r--r--usr.bin/dpv/Makefile9
-rw-r--r--usr.bin/dpv/Makefile.depend20
-rw-r--r--usr.bin/dpv/dpv.1448
-rw-r--r--usr.bin/dpv/dpv.c543
-rw-r--r--usr.bin/dpv/dpv_util.h66
-rw-r--r--usr.bin/drill/Makefile15
-rw-r--r--usr.bin/drill/Makefile.depend18
-rw-r--r--usr.bin/dtc/HACKING61
-rw-r--r--usr.bin/dtc/Makefile13
-rw-r--r--usr.bin/dtc/Makefile.depend18
-rw-r--r--usr.bin/dtc/checking.cc285
-rw-r--r--usr.bin/dtc/checking.hh310
-rw-r--r--usr.bin/dtc/dtb.cc341
-rw-r--r--usr.bin/dtc/dtb.hh373
-rw-r--r--usr.bin/dtc/dtc.1445
-rw-r--r--usr.bin/dtc/dtc.cc382
-rw-r--r--usr.bin/dtc/fdt.cc2304
-rw-r--r--usr.bin/dtc/fdt.hh1074
-rw-r--r--usr.bin/dtc/input_buffer.cc1269
-rw-r--r--usr.bin/dtc/input_buffer.hh552
-rw-r--r--usr.bin/dtc/string.cc150
-rw-r--r--usr.bin/dtc/util.hh150
-rw-r--r--usr.bin/du/Makefile10
-rw-r--r--usr.bin/du/Makefile.depend17
-rw-r--r--usr.bin/du/du.1305
-rw-r--r--usr.bin/du/du.c570
-rw-r--r--usr.bin/du/tests/Makefile3
-rw-r--r--usr.bin/du/tests/Makefile.depend10
-rwxr-xr-xusr.bin/du/tests/du_test.sh189
-rw-r--r--usr.bin/ee/Makefile34
-rw-r--r--usr.bin/ee/Makefile.depend17
-rw-r--r--usr.bin/ee/nls/de_DE.ISO8859-1/ee.msg184
-rw-r--r--usr.bin/ee/nls/fr_FR.ISO8859-1/ee.msg184
-rw-r--r--usr.bin/ee/nls/hu_HU.ISO8859-2/ee.msg184
-rw-r--r--usr.bin/ee/nls/pl_PL.ISO8859-2/ee.msg184
-rw-r--r--usr.bin/ee/nls/pt_BR.ISO8859-1/ee.msg185
-rw-r--r--usr.bin/ee/nls/ru_RU.KOI8-R/ee.msg186
-rw-r--r--usr.bin/ee/nls/uk_UA.KOI8-U/ee.msg184
-rw-r--r--usr.bin/elfctl/Makefile9
-rw-r--r--usr.bin/elfctl/elfctl.1109
-rw-r--r--usr.bin/elfctl/elfctl.c466
-rw-r--r--usr.bin/elfdump/Makefile3
-rw-r--r--usr.bin/elfdump/Makefile.depend17
-rw-r--r--usr.bin/elfdump/elfdump.1115
-rw-r--r--usr.bin/elfdump/elfdump.c1287
-rw-r--r--usr.bin/enigma/Makefile8
-rw-r--r--usr.bin/enigma/Makefile.depend16
-rw-r--r--usr.bin/enigma/enigma.1122
-rw-r--r--usr.bin/enigma/enigma.c154
-rw-r--r--usr.bin/env/Makefile12
-rw-r--r--usr.bin/env/Makefile.depend16
-rw-r--r--usr.bin/env/env.1549
-rw-r--r--usr.bin/env/env.c229
-rw-r--r--usr.bin/env/envopts.c468
-rw-r--r--usr.bin/env/envopts.h37
-rw-r--r--usr.bin/env/tests/Makefile6
-rw-r--r--usr.bin/env/tests/Makefile.depend10
-rw-r--r--usr.bin/env/tests/env_test.sh161
-rw-r--r--usr.bin/etdump/Makefile12
-rw-r--r--usr.bin/etdump/etdump.1102
-rw-r--r--usr.bin/etdump/etdump.c272
-rw-r--r--usr.bin/etdump/etdump.h47
-rw-r--r--usr.bin/etdump/output_shell.c67
-rw-r--r--usr.bin/etdump/output_text.c95
-rw-r--r--usr.bin/expand/Makefile4
-rw-r--r--usr.bin/expand/Makefile.depend15
-rw-r--r--usr.bin/expand/expand.1117
-rw-r--r--usr.bin/expand/expand.c184
-rw-r--r--usr.bin/factor/Makefile19
-rw-r--r--usr.bin/factor/Makefile.depend16
-rw-r--r--usr.bin/factor/Makefile.depend.options5
-rw-r--r--usr.bin/factor/factor.6128
-rw-r--r--usr.bin/factor/factor.c399
-rw-r--r--usr.bin/factor/tests/Makefile4
-rwxr-xr-xusr.bin/factor/tests/factor_tests.sh85
-rwxr-xr-xusr.bin/factor/tests/primes_tests.sh75
-rw-r--r--usr.bin/false/Makefile3
-rw-r--r--usr.bin/false/Makefile.depend14
-rw-r--r--usr.bin/false/false.160
-rw-r--r--usr.bin/false/false.c36
-rw-r--r--usr.bin/fetch/Makefile5
-rw-r--r--usr.bin/fetch/Makefile.depend16
-rw-r--r--usr.bin/fetch/fetch.1461
-rw-r--r--usr.bin/fetch/fetch.c1227
-rw-r--r--usr.bin/file/Makefile52
-rw-r--r--usr.bin/file/Makefile.depend16
-rw-r--r--usr.bin/file/tests/Makefile8
-rw-r--r--usr.bin/file/tests/Makefile.depend10
-rw-r--r--usr.bin/file/tests/file_test.sh65
-rw-r--r--usr.bin/file2c/Makefile8
-rw-r--r--usr.bin/file2c/Makefile.depend14
-rw-r--r--usr.bin/file2c/Makefile.depend.host10
-rw-r--r--usr.bin/file2c/Makefile.depend.options6
-rw-r--r--usr.bin/file2c/file2c.173
-rw-r--r--usr.bin/file2c/file2c.c90
-rw-r--r--usr.bin/file2c/tests/Makefile17
-rw-r--r--usr.bin/file2c/tests/Makefile.depend10
-rw-r--r--usr.bin/file2c/tests/legacy_test.sh5
-rw-r--r--usr.bin/file2c/tests/regress.1.out1
-rw-r--r--usr.bin/file2c/tests/regress.2.out3
-rw-r--r--usr.bin/file2c/tests/regress.3.out5
-rw-r--r--usr.bin/file2c/tests/regress.4.out4
-rw-r--r--usr.bin/file2c/tests/regress.5.out1
-rw-r--r--usr.bin/file2c/tests/regress.6.out9
-rw-r--r--usr.bin/file2c/tests/regress.7.out8
-rw-r--r--usr.bin/file2c/tests/regress.8.out4
-rw-r--r--usr.bin/file2c/tests/regress.9.out104
-rw-r--r--usr.bin/file2c/tests/regress.inbin0 -> 2048 bytes
-rw-r--r--usr.bin/file2c/tests/regress.sh18
-rw-r--r--usr.bin/find/Makefile16
-rw-r--r--usr.bin/find/Makefile.depend16
-rw-r--r--usr.bin/find/extern.h127
-rw-r--r--usr.bin/find/find.11204
-rw-r--r--usr.bin/find/find.c243
-rw-r--r--usr.bin/find/find.h171
-rw-r--r--usr.bin/find/function.c1849
-rw-r--r--usr.bin/find/getdate.y946
-rw-r--r--usr.bin/find/ls.c119
-rw-r--r--usr.bin/find/main.c164
-rw-r--r--usr.bin/find/misc.c107
-rw-r--r--usr.bin/find/operator.c267
-rw-r--r--usr.bin/find/option.c209
-rw-r--r--usr.bin/find/tests/Makefile3
-rwxr-xr-xusr.bin/find/tests/find_test.sh71
-rw-r--r--usr.bin/finger/Makefile5
-rw-r--r--usr.bin/finger/Makefile.depend15
-rw-r--r--usr.bin/finger/extern.h60
-rw-r--r--usr.bin/finger/finger.1242
-rw-r--r--usr.bin/finger/finger.c394
-rw-r--r--usr.bin/finger/finger.conf.589
-rw-r--r--usr.bin/finger/finger.h71
-rw-r--r--usr.bin/finger/lprint.c356
-rw-r--r--usr.bin/finger/net.c230
-rw-r--r--usr.bin/finger/pathnames.h41
-rw-r--r--usr.bin/finger/sprint.c177
-rw-r--r--usr.bin/finger/util.c398
-rw-r--r--usr.bin/fmt/Makefile3
-rw-r--r--usr.bin/fmt/Makefile.depend15
-rw-r--r--usr.bin/fmt/fmt.1198
-rw-r--r--usr.bin/fmt/fmt.c784
-rw-r--r--usr.bin/fold/Makefile8
-rw-r--r--usr.bin/fold/Makefile.depend15
-rw-r--r--usr.bin/fold/fold.1130
-rw-r--r--usr.bin/fold/fold.c222
-rw-r--r--usr.bin/fold/tests/Makefile3
-rw-r--r--usr.bin/fold/tests/fold_test.sh80
-rw-r--r--usr.bin/fortune/Makefile7
-rw-r--r--usr.bin/fortune/Makefile.inc4
-rw-r--r--usr.bin/fortune/Notes176
-rw-r--r--usr.bin/fortune/README33
-rw-r--r--usr.bin/fortune/datfiles/Makefile15
-rw-r--r--usr.bin/fortune/datfiles/Makefile.depend10
-rw-r--r--usr.bin/fortune/datfiles/freebsd-tips862
-rw-r--r--usr.bin/fortune/datfiles/freebsd-tips.sp.ok86
-rw-r--r--usr.bin/fortune/fortune/Makefile8
-rw-r--r--usr.bin/fortune/fortune/Makefile.depend16
-rw-r--r--usr.bin/fortune/fortune/fortune.6201
-rw-r--r--usr.bin/fortune/fortune/fortune.c1415
-rw-r--r--usr.bin/fortune/fortune/pathnames.h33
-rw-r--r--usr.bin/fortune/strfile/Makefile5
-rw-r--r--usr.bin/fortune/strfile/Makefile.depend16
-rw-r--r--usr.bin/fortune/strfile/strfile.8156
-rw-r--r--usr.bin/fortune/strfile/strfile.c450
-rw-r--r--usr.bin/fortune/strfile/strfile.h51
-rw-r--r--usr.bin/fortune/tools/Do_spell7
-rw-r--r--usr.bin/fortune/tools/Do_troff7
-rw-r--r--usr.bin/fortune/tools/Troff.mac26
-rw-r--r--usr.bin/fortune/tools/Troff.sed13
-rw-r--r--usr.bin/fortune/tools/do_sort9
-rw-r--r--usr.bin/fortune/tools/do_uniq.py67
-rw-r--r--usr.bin/fortune/unstr/Makefile5
-rw-r--r--usr.bin/fortune/unstr/Makefile.depend16
-rw-r--r--usr.bin/fortune/unstr/unstr.c123
-rw-r--r--usr.bin/from/Makefile3
-rw-r--r--usr.bin/from/Makefile.depend15
-rw-r--r--usr.bin/from/from.193
-rw-r--r--usr.bin/from/from.c155
-rw-r--r--usr.bin/fstat/Makefile8
-rw-r--r--usr.bin/fstat/Makefile.depend17
-rw-r--r--usr.bin/fstat/fstat.1344
-rw-r--r--usr.bin/fstat/fstat.c643
-rw-r--r--usr.bin/fstat/functions.h34
-rw-r--r--usr.bin/fstat/fuser.1151
-rw-r--r--usr.bin/fstat/fuser.c367
-rw-r--r--usr.bin/fstat/main.c49
-rw-r--r--usr.bin/fsync/Makefile4
-rw-r--r--usr.bin/fsync/Makefile.depend14
-rw-r--r--usr.bin/fsync/fsync.161
-rw-r--r--usr.bin/fsync/fsync.c77
-rw-r--r--usr.bin/ftp/Makefile32
-rw-r--r--usr.bin/ftp/Makefile.depend18
-rw-r--r--usr.bin/ftp/tnftp_config.h513
-rw-r--r--usr.bin/gcore/Makefile12
-rw-r--r--usr.bin/gcore/Makefile.depend17
-rw-r--r--usr.bin/gcore/elf32core.c10
-rw-r--r--usr.bin/gcore/elfcore.c878
-rw-r--r--usr.bin/gcore/extern.h38
-rw-r--r--usr.bin/gcore/gcore.1103
-rw-r--r--usr.bin/gcore/gcore.c213
-rw-r--r--usr.bin/gencat/Makefile3
-rw-r--r--usr.bin/gencat/Makefile.depend16
-rw-r--r--usr.bin/gencat/gencat.1189
-rw-r--r--usr.bin/gencat/gencat.c694
-rw-r--r--usr.bin/genl/Makefile4
-rw-r--r--usr.bin/genl/genl.172
-rw-r--r--usr.bin/genl/genl.c440
-rw-r--r--usr.bin/genl/genl.h31
-rw-r--r--usr.bin/genl/parser_rpc.c161
-rw-r--r--usr.bin/getaddrinfo/Makefile17
-rw-r--r--usr.bin/getaddrinfo/Makefile.depend18
-rw-r--r--usr.bin/getaddrinfo/getaddrinfo.1180
-rw-r--r--usr.bin/getaddrinfo/getaddrinfo.c328
-rw-r--r--usr.bin/getaddrinfo/tables.awk61
-rw-r--r--usr.bin/getconf/Makefile42
-rw-r--r--usr.bin/getconf/Makefile.depend15
-rw-r--r--usr.bin/getconf/confstr.gperf79
-rw-r--r--usr.bin/getconf/fake-gperf.awk66
-rw-r--r--usr.bin/getconf/getconf.1223
-rw-r--r--usr.bin/getconf/getconf.c285
-rw-r--r--usr.bin/getconf/getconf.h46
-rw-r--r--usr.bin/getconf/limits.gperf111
-rw-r--r--usr.bin/getconf/pathconf.gperf81
-rw-r--r--usr.bin/getconf/progenv.gperf65
-rw-r--r--usr.bin/getconf/sysconf.gperf160
-rw-r--r--usr.bin/getconf/tests/Makefile7
-rw-r--r--usr.bin/getconf/tests/Makefile.depend15
-rw-r--r--usr.bin/getconf/tests/arch_type.c56
-rwxr-xr-xusr.bin/getconf/tests/getconf_test.sh119
-rw-r--r--usr.bin/getconf/unsigned_limits.gperf41
-rw-r--r--usr.bin/getent/Makefile3
-rw-r--r--usr.bin/getent/Makefile.depend17
-rw-r--r--usr.bin/getent/getent.1142
-rw-r--r--usr.bin/getent/getent.c715
-rw-r--r--usr.bin/getopt/Makefile5
-rw-r--r--usr.bin/getopt/Makefile.depend17
-rw-r--r--usr.bin/getopt/getopt.1133
-rw-r--r--usr.bin/getopt/getopt.c41
-rw-r--r--usr.bin/gh-bc/Makefile130
-rw-r--r--usr.bin/gh-bc/tests/Makefile65
-rw-r--r--usr.bin/gh-bc/tests/Makefile.depend10
-rw-r--r--usr.bin/gprof/Makefile10
-rw-r--r--usr.bin/gprof/Makefile.depend15
-rw-r--r--usr.bin/gprof/arcs.c947
-rw-r--r--usr.bin/gprof/dfn.c315
-rw-r--r--usr.bin/gprof/elf.c140
-rw-r--r--usr.bin/gprof/gprof.1326
-rw-r--r--usr.bin/gprof/gprof.c580
-rw-r--r--usr.bin/gprof/gprof.callg108
-rw-r--r--usr.bin/gprof/gprof.flat32
-rw-r--r--usr.bin/gprof/gprof.h324
-rw-r--r--usr.bin/gprof/hertz.c57
-rw-r--r--usr.bin/gprof/kernel.c62
-rw-r--r--usr.bin/gprof/lookup.c113
-rw-r--r--usr.bin/gprof/pathnames.h34
-rw-r--r--usr.bin/gprof/printgprof.c740
-rw-r--r--usr.bin/gprof/printlist.c84
-rw-r--r--usr.bin/grdc/Makefile7
-rw-r--r--usr.bin/grdc/Makefile.depend17
-rw-r--r--usr.bin/grdc/grdc.661
-rw-r--r--usr.bin/grdc/grdc.c294
-rw-r--r--usr.bin/grep/Makefile61
-rw-r--r--usr.bin/grep/Makefile.depend18
-rw-r--r--usr.bin/grep/Makefile.depend.options7
-rw-r--r--usr.bin/grep/file.c248
-rw-r--r--usr.bin/grep/grep.1592
-rw-r--r--usr.bin/grep/grep.c724
-rw-r--r--usr.bin/grep/grep.h159
-rw-r--r--usr.bin/grep/queue.c142
-rw-r--r--usr.bin/grep/tests/Makefile55
-rw-r--r--usr.bin/grep/tests/Makefile.depend10
-rwxr-xr-xusr.bin/grep/tests/grep_freebsd_test.sh112
-rw-r--r--usr.bin/grep/util.c805
-rw-r--r--usr.bin/grep/zgrep.1112
-rwxr-xr-xusr.bin/grep/zgrep.sh230
-rw-r--r--usr.bin/gzip/Makefile36
-rw-r--r--usr.bin/gzip/Makefile.depend18
-rw-r--r--usr.bin/gzip/Makefile.depend.options7
-rw-r--r--usr.bin/gzip/gzexe178
-rw-r--r--usr.bin/gzip/gzexe.171
-rw-r--r--usr.bin/gzip/gzip.1246
-rw-r--r--usr.bin/gzip/gzip.c2261
-rw-r--r--usr.bin/gzip/tests/Makefile12
-rw-r--r--usr.bin/gzip/tests/Makefile.depend10
-rw-r--r--usr.bin/gzip/tests/foo.diff2
-rw-r--r--usr.bin/gzip/tests/zdiff_test.sh125
-rw-r--r--usr.bin/gzip/unbzip2.c143
-rw-r--r--usr.bin/gzip/unlz.c642
-rw-r--r--usr.bin/gzip/unpack.c334
-rw-r--r--usr.bin/gzip/unxz.c474
-rw-r--r--usr.bin/gzip/unzstd.c89
-rw-r--r--usr.bin/gzip/zdiff141
-rw-r--r--usr.bin/gzip/zdiff.1140
-rw-r--r--usr.bin/gzip/zforce54
-rw-r--r--usr.bin/gzip/zforce.151
-rw-r--r--usr.bin/gzip/zmore81
-rw-r--r--usr.bin/gzip/zmore.1108
-rw-r--r--usr.bin/gzip/znew136
-rw-r--r--usr.bin/gzip/znew.169
-rw-r--r--usr.bin/gzip/zuncompress.c397
-rw-r--r--usr.bin/head/Makefile15
-rw-r--r--usr.bin/head/Makefile.depend17
-rw-r--r--usr.bin/head/Makefile.depend.options7
-rw-r--r--usr.bin/head/head.1105
-rw-r--r--usr.bin/head/head.c215
-rw-r--r--usr.bin/head/tests/Makefile5
-rw-r--r--usr.bin/head/tests/Makefile.depend10
-rwxr-xr-xusr.bin/head/tests/head_test.sh176
-rw-r--r--usr.bin/hesinfo/Makefile3
-rw-r--r--usr.bin/hesinfo/hesinfo.1195
-rw-r--r--usr.bin/hesinfo/hesinfo.c106
-rw-r--r--usr.bin/hexdump/Makefile13
-rw-r--r--usr.bin/hexdump/Makefile.depend17
-rw-r--r--usr.bin/hexdump/conv.c187
-rw-r--r--usr.bin/hexdump/display.c434
-rw-r--r--usr.bin/hexdump/hexdump.1384
-rw-r--r--usr.bin/hexdump/hexdump.c81
-rw-r--r--usr.bin/hexdump/hexdump.h104
-rw-r--r--usr.bin/hexdump/hexsyntax.c134
-rw-r--r--usr.bin/hexdump/od.1279
-rw-r--r--usr.bin/hexdump/odsyntax.c432
-rw-r--r--usr.bin/hexdump/parse.c524
-rw-r--r--usr.bin/hexdump/tests/Makefile43
-rw-r--r--usr.bin/hexdump/tests/Makefile.depend10
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_UCflag_a.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_UCflag_b.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_UCflag_bug118723.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_UCflag_c.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_UCvflag_bug118723.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_a.in1
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_b.in2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_bflag_a.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_bflag_b.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_bflag_c.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_bug118723.in5
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_c.in1
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_cflag_a.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_cflag_b.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_cflag_c.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_a_eb.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_a_el.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_b_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_b_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_c_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_dflag_c_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_nflag_a.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_a_eb.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_a_el.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_b_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_b_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_c_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_oflag_c_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_sflag_a.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_a_eb.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_a_el.out2
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_b_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_b_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_c_eb.out4
-rw-r--r--usr.bin/hexdump/tests/d_hexdump_xflag_c_el.out4
-rw-r--r--usr.bin/hexdump/tests/d_od_cflag_a.out3
-rw-r--r--usr.bin/hexdump/tests/d_od_cflag_b.out3
-rwxr-xr-xusr.bin/hexdump/tests/hexdump_test.sh218
-rwxr-xr-xusr.bin/hexdump/tests/od_test.sh49
-rw-r--r--usr.bin/host/Makefile18
-rw-r--r--usr.bin/host/Makefile.depend17
-rw-r--r--usr.bin/iconv/Makefile9
-rw-r--r--usr.bin/iconv/Makefile.depend17
-rw-r--r--usr.bin/iconv/iconv.1125
-rw-r--r--usr.bin/iconv/iconv.c248
-rw-r--r--usr.bin/id/Makefile14
-rw-r--r--usr.bin/id/Makefile.depend15
-rw-r--r--usr.bin/id/groups.162
-rw-r--r--usr.bin/id/id.1195
-rw-r--r--usr.bin/id/id.c491
-rw-r--r--usr.bin/id/whoami.153
-rw-r--r--usr.bin/ident/Makefile8
-rw-r--r--usr.bin/ident/Makefile.depend17
-rw-r--r--usr.bin/ident/ident.166
-rw-r--r--usr.bin/ident/ident.c286
-rw-r--r--usr.bin/ident/tests/Makefile9
-rw-r--r--usr.bin/ident/tests/Makefile.depend10
-rwxr-xr-xusr.bin/ident/tests/ident_test.sh15
-rw-r--r--usr.bin/ident/tests/test.in15
-rw-r--r--usr.bin/ident/tests/test.out6
-rw-r--r--usr.bin/ident/tests/testnoid0
-rw-r--r--usr.bin/indent/Makefile11
-rw-r--r--usr.bin/indent/Makefile.depend17
-rw-r--r--usr.bin/indent/README98
-rw-r--r--usr.bin/indent/args.c348
-rw-r--r--usr.bin/indent/indent.1613
-rw-r--r--usr.bin/indent/indent.c1309
-rw-r--r--usr.bin/indent/indent.h46
-rw-r--r--usr.bin/indent/indent_codes.h74
-rw-r--r--usr.bin/indent/indent_globs.h323
-rw-r--r--usr.bin/indent/io.c529
-rw-r--r--usr.bin/indent/lexi.c647
-rw-r--r--usr.bin/indent/parse.c341
-rw-r--r--usr.bin/indent/pr_comment.c347
-rw-r--r--usr.bin/indent/tests/Makefile54
-rw-r--r--usr.bin/indent/tests/Makefile.depend10
-rw-r--r--usr.bin/indent/tests/binary.09
-rw-r--r--usr.bin/indent/tests/binary.0.stdout11
-rw-r--r--usr.bin/indent/tests/comments.051
-rw-r--r--usr.bin/indent/tests/comments.0.pro1
-rw-r--r--usr.bin/indent/tests/comments.0.stdout59
-rw-r--r--usr.bin/indent/tests/cs.03
-rw-r--r--usr.bin/indent/tests/cs.0.pro1
-rw-r--r--usr.bin/indent/tests/cs.0.stdout5
-rw-r--r--usr.bin/indent/tests/declarations.078
-rw-r--r--usr.bin/indent/tests/declarations.0.stdout72
-rw-r--r--usr.bin/indent/tests/elsecomment.041
-rw-r--r--usr.bin/indent/tests/elsecomment.0.pro1
-rw-r--r--usr.bin/indent/tests/elsecomment.0.stdout46
-rw-r--r--usr.bin/indent/tests/f_decls.028
-rw-r--r--usr.bin/indent/tests/f_decls.0.stdout31
-rw-r--r--usr.bin/indent/tests/float.07
-rw-r--r--usr.bin/indent/tests/float.0.stdout9
-rwxr-xr-xusr.bin/indent/tests/functional_test.sh89
-rw-r--r--usr.bin/indent/tests/label.012
-rw-r--r--usr.bin/indent/tests/label.0.pro1
-rw-r--r--usr.bin/indent/tests/label.0.stdout13
-rw-r--r--usr.bin/indent/tests/list_head.015
-rw-r--r--usr.bin/indent/tests/list_head.0.stdout13
-rw-r--r--usr.bin/indent/tests/ncs.03
-rw-r--r--usr.bin/indent/tests/ncs.0.pro1
-rw-r--r--usr.bin/indent/tests/ncs.0.stdout5
-rw-r--r--usr.bin/indent/tests/offsetof.04
-rw-r--r--usr.bin/indent/tests/offsetof.0.stdout6
-rw-r--r--usr.bin/indent/tests/parens.026
-rw-r--r--usr.bin/indent/tests/parens.0.pro1
-rw-r--r--usr.bin/indent/tests/parens.0.stdout26
-rw-r--r--usr.bin/indent/tests/pcs.06
-rw-r--r--usr.bin/indent/tests/pcs.0.pro1
-rw-r--r--usr.bin/indent/tests/pcs.0.stdout8
-rw-r--r--usr.bin/indent/tests/ps.04
-rw-r--r--usr.bin/indent/tests/ps.0.pro1
-rw-r--r--usr.bin/indent/tests/ps.0.stdout8
-rw-r--r--usr.bin/indent/tests/struct.020
-rw-r--r--usr.bin/indent/tests/struct.0.stdout22
-rw-r--r--usr.bin/indent/tests/surplusbad.08
-rw-r--r--usr.bin/indent/tests/surplusbad.0.pro1
-rw-r--r--usr.bin/indent/tests/surplusbad.0.stdout8
-rw-r--r--usr.bin/indent/tests/types_from_file.02
-rw-r--r--usr.bin/indent/tests/types_from_file.0.list2
-rw-r--r--usr.bin/indent/tests/types_from_file.0.pro1
-rw-r--r--usr.bin/indent/tests/types_from_file.0.stdout2
-rw-r--r--usr.bin/indent/tests/wchar.05
-rw-r--r--usr.bin/indent/tests/wchar.0.stdout5
-rw-r--r--usr.bin/ipcrm/Makefile9
-rw-r--r--usr.bin/ipcrm/Makefile.depend16
-rw-r--r--usr.bin/ipcrm/ipcrm.1120
-rw-r--r--usr.bin/ipcrm/ipcrm.c298
-rw-r--r--usr.bin/ipcs/Makefile5
-rw-r--r--usr.bin/ipcs/Makefile.depend16
-rw-r--r--usr.bin/ipcs/ipc.c204
-rw-r--r--usr.bin/ipcs/ipc.h71
-rw-r--r--usr.bin/ipcs/ipcs.1174
-rw-r--r--usr.bin/ipcs/ipcs.c555
-rw-r--r--usr.bin/iscsictl/Makefile17
-rw-r--r--usr.bin/iscsictl/Makefile.depend19
-rw-r--r--usr.bin/iscsictl/iscsi.conf.5214
-rw-r--r--usr.bin/iscsictl/iscsictl.8207
-rw-r--r--usr.bin/iscsictl/iscsictl.c963
-rw-r--r--usr.bin/iscsictl/iscsictl.h106
-rw-r--r--usr.bin/iscsictl/parse.y466
-rw-r--r--usr.bin/iscsictl/periphs.c202
-rw-r--r--usr.bin/iscsictl/token.l124
-rw-r--r--usr.bin/join/Makefile8
-rw-r--r--usr.bin/join/Makefile.depend15
-rw-r--r--usr.bin/join/join.1292
-rw-r--r--usr.bin/join/join.c661
-rw-r--r--usr.bin/join/tests/Makefile10
-rw-r--r--usr.bin/join/tests/Makefile.depend10
-rw-r--r--usr.bin/join/tests/legacy_test.sh5
-rw-r--r--usr.bin/join/tests/regress.1.in4
-rw-r--r--usr.bin/join/tests/regress.2.in4
-rw-r--r--usr.bin/join/tests/regress.out5
-rw-r--r--usr.bin/join/tests/regress.sh8
-rw-r--r--usr.bin/jot/Makefile8
-rw-r--r--usr.bin/jot/Makefile.depend17
-rw-r--r--usr.bin/jot/jot.1327
-rw-r--r--usr.bin/jot/jot.c503
-rw-r--r--usr.bin/jot/tests/Makefile68
-rw-r--r--usr.bin/jot/tests/Makefile.depend10
-rw-r--r--usr.bin/jot/tests/legacy_test.sh5
-rw-r--r--usr.bin/jot/tests/regress.ascii.outbin0 -> 256 bytes
-rw-r--r--usr.bin/jot/tests/regress.block.out512
-rw-r--r--usr.bin/jot/tests/regress.dddd.out100
-rw-r--r--usr.bin/jot/tests/regress.dddh.out100
-rw-r--r--usr.bin/jot/tests/regress.ddhd.out100
-rw-r--r--usr.bin/jot/tests/regress.ddhd2.out100
-rw-r--r--usr.bin/jot/tests/regress.ddhh.out100
-rw-r--r--usr.bin/jot/tests/regress.ddhh2.out100
-rw-r--r--usr.bin/jot/tests/regress.dhdd.out100
-rw-r--r--usr.bin/jot/tests/regress.dhdh.out100
-rw-r--r--usr.bin/jot/tests/regress.dhhd.out101
-rw-r--r--usr.bin/jot/tests/regress.dhhd2.out141
-rw-r--r--usr.bin/jot/tests/regress.dhhh.out51
-rw-r--r--usr.bin/jot/tests/regress.dhhh2.out71
-rw-r--r--usr.bin/jot/tests/regress.ed.out30
-rw-r--r--usr.bin/jot/tests/regress.grep.out1
-rw-r--r--usr.bin/jot/tests/regress.hddd.out50
-rw-r--r--usr.bin/jot/tests/regress.hddd2.out30
-rw-r--r--usr.bin/jot/tests/regress.hddh.out50
-rw-r--r--usr.bin/jot/tests/regress.hddh2.out30
-rw-r--r--usr.bin/jot/tests/regress.hdhd.out50
-rw-r--r--usr.bin/jot/tests/regress.hdhd2.out30
-rw-r--r--usr.bin/jot/tests/regress.hdhh.out50
-rw-r--r--usr.bin/jot/tests/regress.hdhh2.out30
-rw-r--r--usr.bin/jot/tests/regress.hhdd.out50
-rw-r--r--usr.bin/jot/tests/regress.hhdd2.out30
-rw-r--r--usr.bin/jot/tests/regress.hhdh.out50
-rw-r--r--usr.bin/jot/tests/regress.hhdh2.out30
-rw-r--r--usr.bin/jot/tests/regress.hhhd.out50
-rw-r--r--usr.bin/jot/tests/regress.hhhd2.out30
-rw-r--r--usr.bin/jot/tests/regress.hhhh.out50
-rw-r--r--usr.bin/jot/tests/regress.hhhh2.out30
-rw-r--r--usr.bin/jot/tests/regress.n21.out21
-rw-r--r--usr.bin/jot/tests/regress.rand1.out10
-rw-r--r--usr.bin/jot/tests/regress.rand2.out10
-rw-r--r--usr.bin/jot/tests/regress.sh67
-rw-r--r--usr.bin/jot/tests/regress.stutter.out19
-rw-r--r--usr.bin/jot/tests/regress.stutter2.out20
-rw-r--r--usr.bin/jot/tests/regress.tabs.out1
-rw-r--r--usr.bin/jot/tests/regress.wX1.out10
-rw-r--r--usr.bin/jot/tests/regress.wXl.out10
-rw-r--r--usr.bin/jot/tests/regress.wc.out10
-rw-r--r--usr.bin/jot/tests/regress.wdl.out0
-rw-r--r--usr.bin/jot/tests/regress.wdn.out10
-rw-r--r--usr.bin/jot/tests/regress.we.out10
-rw-r--r--usr.bin/jot/tests/regress.wf.out10
-rw-r--r--usr.bin/jot/tests/regress.wg.out10
-rw-r--r--usr.bin/jot/tests/regress.wgd.out10
-rw-r--r--usr.bin/jot/tests/regress.wo.out10
-rw-r--r--usr.bin/jot/tests/regress.wp1.out10
-rw-r--r--usr.bin/jot/tests/regress.wp2.out10
-rw-r--r--usr.bin/jot/tests/regress.wp3.out10
-rw-r--r--usr.bin/jot/tests/regress.wp4.out10
-rw-r--r--usr.bin/jot/tests/regress.wp5.out10
-rw-r--r--usr.bin/jot/tests/regress.wp6.out10
-rw-r--r--usr.bin/jot/tests/regress.wu.out10
-rw-r--r--usr.bin/jot/tests/regress.wwe.out10
-rw-r--r--usr.bin/jot/tests/regress.wx.out10
-rw-r--r--usr.bin/jot/tests/regress.wxn.out0
-rw-r--r--usr.bin/jot/tests/regress.x.out1
-rw-r--r--usr.bin/jot/tests/regress.xaa.out26
-rw-r--r--usr.bin/jot/tests/regress.yes.out10
-rw-r--r--usr.bin/kdump/Makefile24
-rw-r--r--usr.bin/kdump/Makefile.depend18
-rw-r--r--usr.bin/kdump/Makefile.depend.options9
-rw-r--r--usr.bin/kdump/kdump.1184
-rw-r--r--usr.bin/kdump/kdump.c2429
-rw-r--r--usr.bin/kdump/kdump.h95
-rw-r--r--usr.bin/kdump/linux.c525
-rw-r--r--usr.bin/killall/Makefile4
-rw-r--r--usr.bin/killall/Makefile.depend16
-rw-r--r--usr.bin/killall/killall.1222
-rw-r--r--usr.bin/killall/killall.c437
-rw-r--r--usr.bin/ktrace/Makefile5
-rw-r--r--usr.bin/ktrace/Makefile.depend15
-rw-r--r--usr.bin/ktrace/ktrace.1229
-rw-r--r--usr.bin/ktrace/ktrace.c227
-rw-r--r--usr.bin/ktrace/ktrace.h44
-rw-r--r--usr.bin/ktrace/subr.c128
-rw-r--r--usr.bin/ktrdump/Makefile5
-rw-r--r--usr.bin/ktrdump/Makefile.depend18
-rw-r--r--usr.bin/ktrdump/ktrdump.893
-rw-r--r--usr.bin/ktrdump/ktrdump.c403
-rw-r--r--usr.bin/kyua/Makefile224
-rw-r--r--usr.bin/kyua/Makefile.depend23
-rw-r--r--usr.bin/kyua/config.h122
-rw-r--r--usr.bin/kyua/kyua.conf-default13
-rw-r--r--usr.bin/kyua/utils/defs.hpp70
-rw-r--r--usr.bin/lam/Makefile3
-rw-r--r--usr.bin/lam/Makefile.depend17
-rw-r--r--usr.bin/lam/lam.1155
-rw-r--r--usr.bin/lam/lam.c238
-rw-r--r--usr.bin/last/Makefile7
-rw-r--r--usr.bin/last/Makefile.depend18
-rw-r--r--usr.bin/last/last.1250
-rw-r--r--usr.bin/last/last.c593
-rw-r--r--usr.bin/lastcomm/Makefile11
-rw-r--r--usr.bin/lastcomm/Makefile.depend15
-rw-r--r--usr.bin/lastcomm/lastcomm.1182
-rw-r--r--usr.bin/lastcomm/lastcomm.c263
-rw-r--r--usr.bin/lastcomm/pathnames.h32
-rw-r--r--usr.bin/lastcomm/readrec.c262
-rw-r--r--usr.bin/lastcomm/tests/Makefile15
-rw-r--r--usr.bin/lastcomm/tests/Makefile.depend10
-rw-r--r--usr.bin/lastcomm/tests/README9
-rw-r--r--usr.bin/lastcomm/tests/legacy_test.sh37
-rw-r--r--usr.bin/lastcomm/tests/v1-amd64-acct.inbin0 -> 1568 bytes
-rw-r--r--usr.bin/lastcomm/tests/v1-amd64.out28
-rw-r--r--usr.bin/lastcomm/tests/v1-i386-acct.inbin0 -> 1344 bytes
-rw-r--r--usr.bin/lastcomm/tests/v1-i386.out28
-rw-r--r--usr.bin/lastcomm/tests/v2-amd64-acct.inbin0 -> 2016 bytes
-rw-r--r--usr.bin/lastcomm/tests/v2-amd64.out28
-rw-r--r--usr.bin/lastcomm/tests/v2-i386-acct.inbin0 -> 1792 bytes
-rw-r--r--usr.bin/lastcomm/tests/v2-i386.out28
-rwxr-xr-xusr.bin/lastcomm/tests/values.sh82
-rw-r--r--usr.bin/ldd/Makefile7
-rw-r--r--usr.bin/ldd/Makefile.depend17
-rw-r--r--usr.bin/ldd/ldd.172
-rw-r--r--usr.bin/ldd/ldd.c471
-rw-r--r--usr.bin/ldd32/Makefile10
-rw-r--r--usr.bin/leave/Makefile5
-rw-r--r--usr.bin/leave/Makefile.depend15
-rw-r--r--usr.bin/leave/leave.193
-rw-r--r--usr.bin/leave/leave.c187
-rw-r--r--usr.bin/less/Makefile21
-rw-r--r--usr.bin/less/Makefile.common10
-rw-r--r--usr.bin/less/Makefile.depend16
-rw-r--r--usr.bin/less/defines.h483
-rw-r--r--usr.bin/less/lesspipe.sh28
-rw-r--r--usr.bin/less/zless.sh6
-rw-r--r--usr.bin/lessecho/Makefile6
-rw-r--r--usr.bin/lessecho/Makefile.depend15
-rw-r--r--usr.bin/lesskey/Makefile6
-rw-r--r--usr.bin/lesskey/Makefile.depend15
-rw-r--r--usr.bin/lex/Makefile61
-rw-r--r--usr.bin/lex/Makefile.depend16
-rw-r--r--usr.bin/lex/Makefile.depend.host10
-rw-r--r--usr.bin/lex/Makefile.depend.options6
-rw-r--r--usr.bin/lex/config.h266
-rw-r--r--usr.bin/lex/initparse.c1843
-rw-r--r--usr.bin/lex/initparse.h45
-rw-r--r--usr.bin/lex/initscan.c5241
-rw-r--r--usr.bin/lex/initskel.c4080
-rw-r--r--usr.bin/lex/lex.14296
-rw-r--r--usr.bin/lex/lib/Makefile15
-rw-r--r--usr.bin/lex/lib/Makefile.depend11
-rw-r--r--usr.bin/lex/version.awk10
-rw-r--r--usr.bin/limits/Makefile11
-rw-r--r--usr.bin/limits/Makefile.depend16
-rw-r--r--usr.bin/limits/limits.1456
-rw-r--r--usr.bin/limits/limits.c782
-rw-r--r--usr.bin/limits/tests/Makefile3
-rw-r--r--usr.bin/limits/tests/Makefile.depend10
-rwxr-xr-xusr.bin/limits/tests/limits_test.sh92
-rw-r--r--usr.bin/locale/Makefile10
-rw-r--r--usr.bin/locale/Makefile.depend16
-rw-r--r--usr.bin/locale/locale.1116
-rw-r--r--usr.bin/locale/locale.c936
-rw-r--r--usr.bin/locale/tests/Makefile14
-rw-r--r--usr.bin/locale/tests/Makefile.depend10
-rw-r--r--usr.bin/locale/tests/k_flag_posix_messages.out2
-rw-r--r--usr.bin/locale/tests/k_flag_posix_monetary.out21
-rw-r--r--usr.bin/locale/tests/k_flag_posix_numeric.out3
-rw-r--r--usr.bin/locale/tests/k_flag_posix_time.out14
-rwxr-xr-xusr.bin/locale/tests/locale_test.sh182
-rw-r--r--usr.bin/locale/tests/no_flags_posix_messages.out2
-rw-r--r--usr.bin/locale/tests/no_flags_posix_monetary.out21
-rw-r--r--usr.bin/locale/tests/no_flags_posix_numeric.out3
-rw-r--r--usr.bin/locale/tests/no_flags_posix_time.out14
-rw-r--r--usr.bin/localedef/Makefile27
-rw-r--r--usr.bin/localedef/Makefile.depend16
-rw-r--r--usr.bin/localedef/README11
-rw-r--r--usr.bin/localedef/bootstrap/_ctype.h46
-rw-r--r--usr.bin/localedef/bootstrap/bootstrap_xlocale_private.h55
-rw-r--r--usr.bin/localedef/bootstrap/collate.h38
-rw-r--r--usr.bin/localedef/bootstrap/ctype.h53
-rw-r--r--usr.bin/localedef/bootstrap/limits.h46
-rw-r--r--usr.bin/localedef/bootstrap/lmessages.h39
-rw-r--r--usr.bin/localedef/bootstrap/lmonetary.h39
-rw-r--r--usr.bin/localedef/bootstrap/lnumeric.h39
-rw-r--r--usr.bin/localedef/bootstrap/namespace.h42
-rw-r--r--usr.bin/localedef/bootstrap/timelocal.h39
-rw-r--r--usr.bin/localedef/bootstrap/un-namespace.h40
-rw-r--r--usr.bin/localedef/bootstrap/xlocale.h53
-rw-r--r--usr.bin/localedef/charmap.c395
-rw-r--r--usr.bin/localedef/collate.c1329
-rw-r--r--usr.bin/localedef/ctype.c484
-rw-r--r--usr.bin/localedef/localedef.1278
-rw-r--r--usr.bin/localedef/localedef.c379
-rw-r--r--usr.bin/localedef/localedef.h177
-rw-r--r--usr.bin/localedef/messages.c119
-rw-r--r--usr.bin/localedef/monetary.c209
-rw-r--r--usr.bin/localedef/numeric.c117
-rw-r--r--usr.bin/localedef/parser.y703
-rw-r--r--usr.bin/localedef/scanner.c864
-rw-r--r--usr.bin/localedef/time.c275
-rw-r--r--usr.bin/localedef/wide.c664
-rw-r--r--usr.bin/locate/Makefile4
-rw-r--r--usr.bin/locate/Makefile.inc3
-rw-r--r--usr.bin/locate/bigram/Makefile6
-rw-r--r--usr.bin/locate/bigram/Makefile.depend17
-rw-r--r--usr.bin/locate/bigram/locate.bigram.c97
-rw-r--r--usr.bin/locate/code/Makefile6
-rw-r--r--usr.bin/locate/code/Makefile.depend15
-rw-r--r--usr.bin/locate/code/locate.code.c233
-rw-r--r--usr.bin/locate/locate/Makefile17
-rw-r--r--usr.bin/locate/locate/Makefile.depend16
-rw-r--r--usr.bin/locate/locate/concatdb.sh71
-rw-r--r--usr.bin/locate/locate/fastfind.c343
-rw-r--r--usr.bin/locate/locate/locate.1268
-rw-r--r--usr.bin/locate/locate/locate.c337
-rw-r--r--usr.bin/locate/locate/locate.h73
-rw-r--r--usr.bin/locate/locate/locate.rc32
-rw-r--r--usr.bin/locate/locate/locate.updatedb.873
-rw-r--r--usr.bin/locate/locate/mklocatedb.sh79
-rw-r--r--usr.bin/locate/locate/pathnames.h32
-rw-r--r--usr.bin/locate/locate/updatedb.sh100
-rw-r--r--usr.bin/locate/locate/util.c297
-rw-r--r--usr.bin/lock/Makefile7
-rw-r--r--usr.bin/lock/Makefile.depend16
-rw-r--r--usr.bin/lock/lock.189
-rw-r--r--usr.bin/lock/lock.c301
-rw-r--r--usr.bin/lockf/Makefile8
-rw-r--r--usr.bin/lockf/Makefile.depend14
-rw-r--r--usr.bin/lockf/lockf.1260
-rw-r--r--usr.bin/lockf/lockf.c352
-rw-r--r--usr.bin/lockf/tests/Makefile5
-rw-r--r--usr.bin/lockf/tests/Makefile.depend10
-rw-r--r--usr.bin/lockf/tests/lockf_test.sh241
-rw-r--r--usr.bin/logger/Makefile17
-rw-r--r--usr.bin/logger/Makefile.depend18
-rw-r--r--usr.bin/logger/logger.1181
-rw-r--r--usr.bin/logger/logger.c440
-rw-r--r--usr.bin/login/Makefile34
-rw-r--r--usr.bin/login/Makefile.depend17
-rw-r--r--usr.bin/login/Makefile.depend.options5
-rw-r--r--usr.bin/login/README10
-rw-r--r--usr.bin/login/fbtab3
-rw-r--r--usr.bin/login/login.1161
-rw-r--r--usr.bin/login/login.access45
-rw-r--r--usr.bin/login/login.c1034
-rw-r--r--usr.bin/login/login.conf332
-rw-r--r--usr.bin/login/login.h37
-rw-r--r--usr.bin/login/login_audit.c203
-rw-r--r--usr.bin/login/login_fbtab.c139
-rw-r--r--usr.bin/login/motd.template20
-rw-r--r--usr.bin/login/pathnames.h37
-rw-r--r--usr.bin/logins/Makefile3
-rw-r--r--usr.bin/logins/Makefile.depend15
-rw-r--r--usr.bin/logins/logins.1102
-rw-r--r--usr.bin/logins/logins.c406
-rw-r--r--usr.bin/logname/Makefile3
-rw-r--r--usr.bin/logname/Makefile.depend17
-rw-r--r--usr.bin/logname/logname.168
-rw-r--r--usr.bin/logname/logname.c61
-rw-r--r--usr.bin/look/Makefile3
-rw-r--r--usr.bin/look/Makefile.depend15
-rw-r--r--usr.bin/look/look.1152
-rw-r--r--usr.bin/look/look.c349
-rw-r--r--usr.bin/look/pathnames.h32
-rw-r--r--usr.bin/lorder/Makefile9
-rw-r--r--usr.bin/lorder/Makefile.depend10
-rw-r--r--usr.bin/lorder/lorder.194
-rw-r--r--usr.bin/lorder/lorder.sh110
-rw-r--r--usr.bin/lorder/tests/Makefile4
-rw-r--r--usr.bin/lorder/tests/Makefile.depend10
-rw-r--r--usr.bin/lorder/tests/lorder_test.sh111
-rw-r--r--usr.bin/lsvfs/Makefile3
-rw-r--r--usr.bin/lsvfs/Makefile.depend15
-rw-r--r--usr.bin/lsvfs/lsvfs.170
-rw-r--r--usr.bin/lsvfs/lsvfs.c99
-rw-r--r--usr.bin/lzmainfo/Makefile19
-rw-r--r--usr.bin/lzmainfo/Makefile.depend16
-rw-r--r--usr.bin/m4/Makefile33
-rw-r--r--usr.bin/m4/Makefile.depend18
-rw-r--r--usr.bin/m4/NOTES64
-rw-r--r--usr.bin/m4/TEST/ack.m436
-rw-r--r--usr.bin/m4/TEST/hanoi.m441
-rw-r--r--usr.bin/m4/TEST/hash.m451
-rw-r--r--usr.bin/m4/TEST/math.m4180
-rw-r--r--usr.bin/m4/TEST/sqroot.m441
-rw-r--r--usr.bin/m4/TEST/string.m441
-rw-r--r--usr.bin/m4/TEST/test.m4239
-rw-r--r--usr.bin/m4/eval.c1035
-rw-r--r--usr.bin/m4/expr.c45
-rw-r--r--usr.bin/m4/extern.h181
-rw-r--r--usr.bin/m4/gnum4.c694
-rw-r--r--usr.bin/m4/look.c339
-rw-r--r--usr.bin/m4/m4.1561
-rw-r--r--usr.bin/m4/main.c660
-rw-r--r--usr.bin/m4/mdef.h237
-rw-r--r--usr.bin/m4/misc.c469
-rw-r--r--usr.bin/m4/parser.y84
-rw-r--r--usr.bin/m4/pathnames.h38
-rw-r--r--usr.bin/m4/stdd.h55
-rw-r--r--usr.bin/m4/tests/Makefile49
-rw-r--r--usr.bin/m4/tests/Makefile.depend10
-rw-r--r--usr.bin/m4/tests/args.m48
-rw-r--r--usr.bin/m4/tests/args2.m44
-rw-r--r--usr.bin/m4/tests/comments.m458
-rw-r--r--usr.bin/m4/tests/esyscmd.m442
-rw-r--r--usr.bin/m4/tests/eval.m45
-rw-r--r--usr.bin/m4/tests/ff_after_dnl.m4.uu10
-rw-r--r--usr.bin/m4/tests/gnueval.m46
-rw-r--r--usr.bin/m4/tests/gnuformat.m41
-rw-r--r--usr.bin/m4/tests/gnupatterns.m43
-rw-r--r--usr.bin/m4/tests/gnupatterns2.m45
-rw-r--r--usr.bin/m4/tests/gnuprefix.m42
-rw-r--r--usr.bin/m4/tests/gnusofterror.m43
-rw-r--r--usr.bin/m4/tests/includes.aux2
-rw-r--r--usr.bin/m4/tests/includes.m44
-rw-r--r--usr.bin/m4/tests/legacy_test.sh5
-rw-r--r--usr.bin/m4/tests/m4wrap3.m411
-rw-r--r--usr.bin/m4/tests/patterns.m411
-rw-r--r--usr.bin/m4/tests/quotes.m457
-rw-r--r--usr.bin/m4/tests/redef.m416
-rw-r--r--usr.bin/m4/tests/regress.args.out3
-rw-r--r--usr.bin/m4/tests/regress.args2.out1
-rw-r--r--usr.bin/m4/tests/regress.comments.out47
-rw-r--r--usr.bin/m4/tests/regress.esyscmd.out578
-rw-r--r--usr.bin/m4/tests/regress.eval.out3
-rw-r--r--usr.bin/m4/tests/regress.ff_after_dnl.out2
-rw-r--r--usr.bin/m4/tests/regress.gnueval.out3
-rw-r--r--usr.bin/m4/tests/regress.gnuformat.out1
-rw-r--r--usr.bin/m4/tests/regress.gnupatterns.out3
-rw-r--r--usr.bin/m4/tests/regress.gnupatterns2.out1
-rw-r--r--usr.bin/m4/tests/regress.gnuprefix.out46
-rw-r--r--usr.bin/m4/tests/regress.gnusofterror.out2
-rw-r--r--usr.bin/m4/tests/regress.gnutranslit2.out6
-rw-r--r--usr.bin/m4/tests/regress.includes.out1
-rw-r--r--usr.bin/m4/tests/regress.m4wrap3.out4
-rw-r--r--usr.bin/m4/tests/regress.patterns.out6
-rw-r--r--usr.bin/m4/tests/regress.quotes.out49
-rw-r--r--usr.bin/m4/tests/regress.redef.out2
-rw-r--r--usr.bin/m4/tests/regress.sh32
-rw-r--r--usr.bin/m4/tests/regress.strangequotes.out1
-rw-r--r--usr.bin/m4/tests/regress.translit.out1
-rw-r--r--usr.bin/m4/tests/regress.translit2.out6
-rw-r--r--usr.bin/m4/tests/strangequotes.m4.uu7
-rw-r--r--usr.bin/m4/tests/translit.m43
-rw-r--r--usr.bin/m4/tests/translit2.m48
-rw-r--r--usr.bin/m4/tokenizer.l114
-rw-r--r--usr.bin/m4/trace.c198
-rw-r--r--usr.bin/mail/Makefile20
-rw-r--r--usr.bin/mail/Makefile.depend15
-rw-r--r--usr.bin/mail/cmd1.c469
-rw-r--r--usr.bin/mail/cmd2.c510
-rw-r--r--usr.bin/mail/cmd3.c723
-rw-r--r--usr.bin/mail/cmdtab.c115
-rw-r--r--usr.bin/mail/collect.c725
-rw-r--r--usr.bin/mail/def.h272
-rw-r--r--usr.bin/mail/edit.c208
-rw-r--r--usr.bin/mail/extern.h250
-rw-r--r--usr.bin/mail/fio.c445
-rw-r--r--usr.bin/mail/getname.c63
-rw-r--r--usr.bin/mail/glob.h96
-rw-r--r--usr.bin/mail/head.c269
-rw-r--r--usr.bin/mail/lex.c693
-rw-r--r--usr.bin/mail/list.c810
-rw-r--r--usr.bin/mail/mail.11270
-rw-r--r--usr.bin/mail/main.c378
-rw-r--r--usr.bin/mail/misc/mail.help23
-rw-r--r--usr.bin/mail/misc/mail.rc2
-rw-r--r--usr.bin/mail/misc/mail.tildehelp36
-rw-r--r--usr.bin/mail/names.c756
-rw-r--r--usr.bin/mail/pathnames.h38
-rw-r--r--usr.bin/mail/popen.c406
-rw-r--r--usr.bin/mail/quit.c489
-rw-r--r--usr.bin/mail/rcv.h40
-rw-r--r--usr.bin/mail/send.c584
-rw-r--r--usr.bin/mail/strings.c120
-rw-r--r--usr.bin/mail/temp.c82
-rw-r--r--usr.bin/mail/tty.c288
-rw-r--r--usr.bin/mail/util.c593
-rw-r--r--usr.bin/mail/v7.local.c90
-rw-r--r--usr.bin/mail/vars.c177
-rw-r--r--usr.bin/mail/version.c36
-rw-r--r--usr.bin/man/Makefile6
-rw-r--r--usr.bin/man/Makefile.depend10
-rw-r--r--usr.bin/man/man.1424
-rw-r--r--usr.bin/man/man.conf.5140
-rwxr-xr-xusr.bin/man/man.sh1119
-rw-r--r--usr.bin/man/manpath.1118
-rw-r--r--usr.bin/mandoc/Makefile107
-rw-r--r--usr.bin/mandoc/Makefile.depend17
-rw-r--r--usr.bin/mdo/Makefile4
-rw-r--r--usr.bin/mdo/mdo.144
-rw-r--r--usr.bin/mdo/mdo.c104
-rw-r--r--usr.bin/mesg/Makefile3
-rw-r--r--usr.bin/mesg/Makefile.depend15
-rw-r--r--usr.bin/mesg/mesg.1105
-rw-r--r--usr.bin/mesg/mesg.c100
-rw-r--r--usr.bin/mididump/Makefile8
-rw-r--r--usr.bin/mididump/mididump.180
-rw-r--r--usr.bin/mididump/mididump.c320
-rw-r--r--usr.bin/ministat/Makefile13
-rw-r--r--usr.bin/ministat/Makefile.depend18
-rw-r--r--usr.bin/ministat/README49
-rw-r--r--usr.bin/ministat/chameleon5
-rw-r--r--usr.bin/ministat/iguana7
-rw-r--r--usr.bin/ministat/ministat.1137
-rw-r--r--usr.bin/ministat/ministat.c691
-rw-r--r--usr.bin/mkcsmapper/Makefile15
-rw-r--r--usr.bin/mkcsmapper/Makefile.depend17
-rw-r--r--usr.bin/mkcsmapper/Makefile.inc7
-rw-r--r--usr.bin/mkcsmapper/ldef.h42
-rw-r--r--usr.bin/mkcsmapper/lex.l110
-rw-r--r--usr.bin/mkcsmapper/mkcsmapper.188
-rw-r--r--usr.bin/mkcsmapper/yacc.y728
-rw-r--r--usr.bin/mkcsmapper_static/Makefile15
-rw-r--r--usr.bin/mkdep/Makefile5
-rw-r--r--usr.bin/mkdep/Makefile.depend10
-rw-r--r--usr.bin/mkdep/Makefile.depend.host10
-rw-r--r--usr.bin/mkdep/Makefile.depend.options6
-rw-r--r--usr.bin/mkdep/mkdep.1126
-rw-r--r--usr.bin/mkdep/mkdep.gcc.sh95
-rw-r--r--usr.bin/mkdep/mkdep.sh107
-rw-r--r--usr.bin/mkesdb/Makefile14
-rw-r--r--usr.bin/mkesdb/Makefile.depend16
-rw-r--r--usr.bin/mkesdb/Makefile.inc3
-rw-r--r--usr.bin/mkesdb/ldef.h40
-rw-r--r--usr.bin/mkesdb/lex.l103
-rw-r--r--usr.bin/mkesdb/mkesdb.182
-rw-r--r--usr.bin/mkesdb/yacc.y332
-rw-r--r--usr.bin/mkesdb_static/Makefile15
-rw-r--r--usr.bin/mkfifo/Makefile3
-rw-r--r--usr.bin/mkfifo/Makefile.depend15
-rw-r--r--usr.bin/mkfifo/mkfifo.195
-rw-r--r--usr.bin/mkfifo/mkfifo.c98
-rw-r--r--usr.bin/mkimg/Makefile37
-rw-r--r--usr.bin/mkimg/Makefile.depend16
-rw-r--r--usr.bin/mkimg/Makefile.depend.host10
-rw-r--r--usr.bin/mkimg/Makefile.depend.options6
-rw-r--r--usr.bin/mkimg/apm.c114
-rw-r--r--usr.bin/mkimg/bsd.c133
-rw-r--r--usr.bin/mkimg/ebr.c129
-rw-r--r--usr.bin/mkimg/endian.h106
-rw-r--r--usr.bin/mkimg/format.c93
-rw-r--r--usr.bin/mkimg/format.h50
-rw-r--r--usr.bin/mkimg/gpt.c296
-rw-r--r--usr.bin/mkimg/image.c753
-rw-r--r--usr.bin/mkimg/image.h45
-rw-r--r--usr.bin/mkimg/mbr.c123
-rw-r--r--usr.bin/mkimg/mkimg.1412
-rw-r--r--usr.bin/mkimg/mkimg.c744
-rw-r--r--usr.bin/mkimg/mkimg.h111
-rw-r--r--usr.bin/mkimg/qcow.c365
-rw-r--r--usr.bin/mkimg/raw.c55
-rw-r--r--usr.bin/mkimg/scheme.c199
-rw-r--r--usr.bin/mkimg/scheme.h95
-rw-r--r--usr.bin/mkimg/tests/Makefile37
-rw-r--r--usr.bin/mkimg/tests/Makefile.depend10
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.hex549
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.hex79
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.raw.hex27
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.hex59
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.hex35
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhdx.hex78
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.hex321
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.hex545
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.hex75
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.hex23
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.hex55
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.hex31
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdx.hex74
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.hex315
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.hex553
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.hex80
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.hex30
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.hex62
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.hex38
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdx.hex79
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.hex322
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.hex579
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.hex101
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.hex48
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.hex80
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.hex56
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdx.hex99
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.hex348
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.hex555
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.hex82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.hex30
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.hex62
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.hex38
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdx.hex81
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.hex324
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.qcow.hex551
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.hex79
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.raw.hex27
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhd.hex59
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.hex35
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhdx.hex78
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.hex321
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.hex545
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.hex75
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.raw.hex23
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.hex55
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.hex31
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhdx.hex74
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.hex315
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.hex553
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.hex80
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.raw.hex30
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.hex62
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.hex38
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhdx.hex79
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.hex322
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.hex579
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.hex101
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.raw.hex48
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.hex80
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.hex56
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhdx.hex99
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.hex348
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.hex555
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.hex82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.raw.hex30
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.hex62
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.hex38
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhdx.hex81
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.hex324
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.hex549
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.hex79
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.raw.hex27
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.hex59
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.hex35
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhdx.hex78
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.hex321
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.hex545
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.hex75
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.hex23
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.hex55
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.hex31
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdx.hex74
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.hex315
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.hex558
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.hex82
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.hex32
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.hex64
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.hex40
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdx.hex81
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.hex326
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.hex579
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.hex101
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.hex48
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.hex84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.hex56
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdx.hex99
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.hex348
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.hex560
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.hex84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.hex32
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.hex64
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.hex40
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdx.hex83
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.hex328
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.qcow.hex551
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.hex79
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.raw.hex27
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhd.hex59
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.hex35
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhdx.hex78
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.hex321
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.hex545
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.hex75
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.raw.hex23
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.hex55
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.hex31
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhdx.hex74
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.hex315
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.hex558
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.hex82
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.raw.hex32
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.hex64
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.hex40
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhdx.hex81
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.hex326
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.hex579
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.hex101
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.raw.hex48
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.hex84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.hex56
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhdx.hex99
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.hex348
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.hex560
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.hex84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.raw.hex32
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.hex64
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.hex40
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhdx.hex83
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.hex328
-rwxr-xr-xusr.bin/mkimg/tests/mkimg_test.sh161
-rw-r--r--usr.bin/mkimg/uuid.c122
-rw-r--r--usr.bin/mkimg/vhd.c412
-rw-r--r--usr.bin/mkimg/vhdx.c533
-rw-r--r--usr.bin/mkimg/vmdk.c257
-rw-r--r--usr.bin/mkstr/Makefile5
-rw-r--r--usr.bin/mkstr/Makefile.depend15
-rw-r--r--usr.bin/mkstr/mkstr.1133
-rw-r--r--usr.bin/mkstr/mkstr.c320
-rw-r--r--usr.bin/mktemp/Makefile10
-rw-r--r--usr.bin/mktemp/Makefile.depend15
-rw-r--r--usr.bin/mktemp/mktemp.1235
-rw-r--r--usr.bin/mktemp/mktemp.c203
-rw-r--r--usr.bin/mktemp/tests/Makefile5
-rw-r--r--usr.bin/mktemp/tests/Makefile.depend10
-rwxr-xr-xusr.bin/mktemp/tests/mktemp_test.sh131
-rw-r--r--usr.bin/mkuzip/Makefile12
-rw-r--r--usr.bin/mkuzip/Makefile.depend21
-rw-r--r--usr.bin/mkuzip/mkuz_blk.c43
-rw-r--r--usr.bin/mkuzip/mkuz_blk.h46
-rw-r--r--usr.bin/mkuzip/mkuz_blk_chain.h33
-rw-r--r--usr.bin/mkuzip/mkuz_blockcache.c146
-rw-r--r--usr.bin/mkuzip/mkuz_blockcache.h29
-rw-r--r--usr.bin/mkuzip/mkuz_cfg.h42
-rw-r--r--usr.bin/mkuzip/mkuz_cloop.h50
-rw-r--r--usr.bin/mkuzip/mkuz_conveyor.c127
-rw-r--r--usr.bin/mkuzip/mkuz_conveyor.h50
-rw-r--r--usr.bin/mkuzip/mkuz_format.h38
-rw-r--r--usr.bin/mkuzip/mkuz_fqueue.c212
-rw-r--r--usr.bin/mkuzip/mkuz_fqueue.h49
-rw-r--r--usr.bin/mkuzip/mkuz_insize.c81
-rw-r--r--usr.bin/mkuzip/mkuz_insize.h27
-rw-r--r--usr.bin/mkuzip/mkuz_lzma.c109
-rw-r--r--usr.bin/mkuzip/mkuz_lzma.h35
-rw-r--r--usr.bin/mkuzip/mkuz_time.c43
-rw-r--r--usr.bin/mkuzip/mkuz_time.h39
-rw-r--r--usr.bin/mkuzip/mkuz_zlib.c81
-rw-r--r--usr.bin/mkuzip/mkuz_zlib.h33
-rw-r--r--usr.bin/mkuzip/mkuz_zstd.c93
-rw-r--r--usr.bin/mkuzip/mkuz_zstd.h34
-rw-r--r--usr.bin/mkuzip/mkuzip.8272
-rw-r--r--usr.bin/mkuzip/mkuzip.c502
-rw-r--r--usr.bin/mkuzip/mkuzip.h34
-rw-r--r--usr.bin/morse/Makefile4
-rw-r--r--usr.bin/morse/Makefile.depend16
-rw-r--r--usr.bin/morse/morse.6210
-rw-r--r--usr.bin/morse/morse.c662
-rw-r--r--usr.bin/msgs/Makefile5
-rw-r--r--usr.bin/msgs/Makefile.depend16
-rw-r--r--usr.bin/msgs/msgs.1229
-rw-r--r--usr.bin/msgs/msgs.c896
-rw-r--r--usr.bin/msgs/pathnames.h36
-rw-r--r--usr.bin/mt/Makefile4
-rw-r--r--usr.bin/mt/Makefile.depend17
-rw-r--r--usr.bin/mt/mt.1693
-rw-r--r--usr.bin/mt/mt.c1583
-rw-r--r--usr.bin/nc/Makefile18
-rw-r--r--usr.bin/nc/Makefile.depend19
-rw-r--r--usr.bin/ncal/Makefile13
-rw-r--r--usr.bin/ncal/Makefile.depend17
-rw-r--r--usr.bin/ncal/ncal.1225
-rw-r--r--usr.bin/ncal/ncal.c1190
-rw-r--r--usr.bin/ncal/tests/Makefile96
-rw-r--r--usr.bin/ncal/tests/Makefile.depend10
-rw-r--r--usr.bin/ncal/tests/legacy_test.sh5
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200901-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200901-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200902-jd-nhl.out18
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200902-md-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200903-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200903-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200904-jd-nhl.out18
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200904-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200905-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200905-md-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200906-jd-nhl.out18
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200906-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200907-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200907-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200908-jd-nhl.out18
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200908-md-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200909-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200909-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200910-jd-nhl.out18
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200910-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200911-jd-nhl.out17
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200911-md-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200912-jd-nhl.out19
-rw-r--r--usr.bin/ncal/tests/regress.b-3m200912-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.b-y2008-jd-nhl.out54
-rw-r--r--usr.bin/ncal/tests/regress.b-y2008-md-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.b-y2009-jd-nhl.out54
-rw-r--r--usr.bin/ncal/tests/regress.b-y2009-md-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.b-y2010-jd-nhl.out54
-rw-r--r--usr.bin/ncal/tests/regress.b-y2010-md-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.b-y2011-jd-nhl.out54
-rw-r--r--usr.bin/ncal/tests/regress.b-y2011-md-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.f-3A-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-3AB-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-3B-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-3gy-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-3y-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-mgm-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-yA-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-yAB-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-yB-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-ygm-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.f-ym-nhl.out1
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200901-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200901-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200902-jd-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200902-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200903-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200903-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200904-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200904-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200905-jd-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200905-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200906-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200906-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200907-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200907-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200908-jd-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200908-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200909-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200909-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200910-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200910-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200911-jd-nhl.out9
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200911-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200912-jd-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-3m200912-md-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.r-y2008-jd-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.r-y2008-md-nhl.out27
-rw-r--r--usr.bin/ncal/tests/regress.r-y2009-jd-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.r-y2009-md-nhl.out27
-rw-r--r--usr.bin/ncal/tests/regress.r-y2010-jd-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.r-y2010-md-nhl.out27
-rw-r--r--usr.bin/ncal/tests/regress.r-y2011-jd-nhl.out36
-rw-r--r--usr.bin/ncal/tests/regress.r-y2011-md-nhl.out27
-rw-r--r--usr.bin/ncal/tests/regress.s-b-3-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-A-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-AB-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-B-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-gmgy-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-m-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-b-mgy-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-3-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-A-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-AB-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-B-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-gmgy-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-m-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.s-r-mgy-nhl.out8
-rw-r--r--usr.bin/ncal/tests/regress.sh79
-rw-r--r--usr.bin/ncurses/Makefile40
-rw-r--r--usr.bin/ncurses/Makefile.depend17
-rw-r--r--usr.bin/ncurses/transform.h10
-rw-r--r--usr.bin/netstat/Makefile74
-rw-r--r--usr.bin/netstat/Makefile.depend21
-rw-r--r--usr.bin/netstat/Makefile.depend.options7
-rw-r--r--usr.bin/netstat/bpf.c167
-rw-r--r--usr.bin/netstat/common.c136
-rw-r--r--usr.bin/netstat/common.h90
-rw-r--r--usr.bin/netstat/if.c740
-rw-r--r--usr.bin/netstat/inet.c1539
-rw-r--r--usr.bin/netstat/inet6.c1359
-rw-r--r--usr.bin/netstat/ipsec.c433
-rw-r--r--usr.bin/netstat/main.c945
-rw-r--r--usr.bin/netstat/mbuf.c354
-rw-r--r--usr.bin/netstat/mroute.c462
-rw-r--r--usr.bin/netstat/mroute6.c274
-rw-r--r--usr.bin/netstat/netgraph.c141
-rw-r--r--usr.bin/netstat/netisr.c506
-rw-r--r--usr.bin/netstat/netstat.1944
-rw-r--r--usr.bin/netstat/netstat.h168
-rw-r--r--usr.bin/netstat/nhgrp.c352
-rw-r--r--usr.bin/netstat/nhops.c477
-rw-r--r--usr.bin/netstat/nlist_symbols50
-rw-r--r--usr.bin/netstat/pfkey.c200
-rw-r--r--usr.bin/netstat/route.c724
-rw-r--r--usr.bin/netstat/route_netlink.c340
-rw-r--r--usr.bin/netstat/sctp.c833
-rw-r--r--usr.bin/netstat/unix.c320
-rw-r--r--usr.bin/newgrp/Makefile10
-rw-r--r--usr.bin/newgrp/Makefile.depend17
-rw-r--r--usr.bin/newgrp/newgrp.1102
-rw-r--r--usr.bin/newgrp/newgrp.c309
-rw-r--r--usr.bin/nfsstat/Makefile8
-rw-r--r--usr.bin/nfsstat/Makefile.depend18
-rw-r--r--usr.bin/nfsstat/nfsstat.1143
-rw-r--r--usr.bin/nfsstat/nfsstat.c1258
-rw-r--r--usr.bin/nice/Makefile3
-rw-r--r--usr.bin/nice/Makefile.depend15
-rw-r--r--usr.bin/nice/nice.1117
-rw-r--r--usr.bin/nice/nice.c98
-rw-r--r--usr.bin/nl/Makefile3
-rw-r--r--usr.bin/nl/Makefile.depend15
-rw-r--r--usr.bin/nl/nl.1284
-rw-r--r--usr.bin/nl/nl.c410
-rw-r--r--usr.bin/nm/Makefile22
-rw-r--r--usr.bin/nm/Makefile.depend19
-rw-r--r--usr.bin/nm/Makefile.depend.options7
-rw-r--r--usr.bin/nohup/Makefile3
-rw-r--r--usr.bin/nohup/Makefile.depend15
-rw-r--r--usr.bin/nohup/nohup.1119
-rw-r--r--usr.bin/nohup/nohup.c121
-rw-r--r--usr.bin/number/Makefile4
-rw-r--r--usr.bin/number/Makefile.depend16
-rw-r--r--usr.bin/number/number.655
-rw-r--r--usr.bin/number/number.c271
-rw-r--r--usr.bin/objcopy/Makefile42
-rw-r--r--usr.bin/objcopy/Makefile.depend19
-rw-r--r--usr.bin/ofed/Makefile12
-rw-r--r--usr.bin/ofed/infiniband-diags/Makefile33
-rw-r--r--usr.bin/ofed/infiniband-diags/Makefile.inc11
-rw-r--r--usr.bin/ofed/infiniband-diags/dump_fts/Makefile6
-rw-r--r--usr.bin/ofed/infiniband-diags/ibaddr/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibcacheedit/Makefile6
-rw-r--r--usr.bin/ofed/infiniband-diags/ibccconfig/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibccquery/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/iblinkinfo/Makefile6
-rw-r--r--usr.bin/ofed/infiniband-diags/ibmirror/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibnetdiscover/Makefile6
-rw-r--r--usr.bin/ofed/infiniband-diags/ibping/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibportstate/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibqueryerrors/Makefile6
-rw-r--r--usr.bin/ofed/infiniband-diags/ibroute/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibstat/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibsysstat/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/ibtracert/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/perfquery/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/saquery/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/sminfo/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/smpdump/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/smpquery/Makefile5
-rw-r--r--usr.bin/ofed/infiniband-diags/vendstat/Makefile5
-rw-r--r--usr.bin/ofed/libibverbs/Makefile12
-rw-r--r--usr.bin/ofed/libibverbs/Makefile.inc8
-rw-r--r--usr.bin/ofed/libibverbs/asyncwatch/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/devices/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/devinfo/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/rc_pingpong/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/srq_pingpong/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/uc_pingpong/Makefile6
-rw-r--r--usr.bin/ofed/libibverbs/ud_pingpong/Makefile6
-rw-r--r--usr.bin/ofed/librdmacm/Makefile5
-rw-r--r--usr.bin/ofed/librdmacm/Makefile.inc8
-rw-r--r--usr.bin/ofed/librdmacm/mckey/Makefile6
-rw-r--r--usr.bin/ofed/librdmacm/mckey/Makefile.depend24
-rw-r--r--usr.bin/ofed/librdmacm/rping/Makefile6
-rw-r--r--usr.bin/ofed/librdmacm/rping/Makefile.depend23
-rw-r--r--usr.bin/ofed/librdmacm/ucmatose/Makefile6
-rw-r--r--usr.bin/ofed/librdmacm/ucmatose/Makefile.depend23
-rw-r--r--usr.bin/ofed/librdmacm/udaddy/Makefile6
-rw-r--r--usr.bin/ofed/librdmacm/udaddy/Makefile.depend23
-rw-r--r--usr.bin/ofed/opensm/Makefile102
-rw-r--r--usr.bin/pagesize/Makefile4
-rw-r--r--usr.bin/pagesize/Makefile.depend10
-rw-r--r--usr.bin/pagesize/pagesize.151
-rw-r--r--usr.bin/pagesize/pagesize.sh34
-rw-r--r--usr.bin/pamtest/Makefile9
-rw-r--r--usr.bin/pamtest/Makefile.depend15
-rw-r--r--usr.bin/passwd/Makefile20
-rw-r--r--usr.bin/passwd/Makefile.depend15
-rw-r--r--usr.bin/passwd/passwd.1231
-rw-r--r--usr.bin/passwd/passwd.c163
-rw-r--r--usr.bin/paste/Makefile3
-rw-r--r--usr.bin/paste/Makefile.depend15
-rw-r--r--usr.bin/paste/paste.1155
-rw-r--r--usr.bin/paste/paste.c259
-rw-r--r--usr.bin/patch/Makefile12
-rw-r--r--usr.bin/patch/Makefile.depend15
-rw-r--r--usr.bin/patch/backupfile.c244
-rw-r--r--usr.bin/patch/backupfile.h38
-rw-r--r--usr.bin/patch/common.h111
-rw-r--r--usr.bin/patch/inp.c432
-rw-r--r--usr.bin/patch/inp.h31
-rw-r--r--usr.bin/patch/mkpath.c79
-rw-r--r--usr.bin/patch/patch.1691
-rw-r--r--usr.bin/patch/patch.c1227
-rw-r--r--usr.bin/patch/pathnames.h11
-rw-r--r--usr.bin/patch/pch.c1662
-rw-r--r--usr.bin/patch/pch.h57
-rw-r--r--usr.bin/patch/tests/Makefile10
-rw-r--r--usr.bin/patch/tests/Makefile.depend10
-rw-r--r--usr.bin/patch/tests/PR74127-cline.diff4
-rw-r--r--usr.bin/patch/tests/PR74127-good.diff4
-rw-r--r--usr.bin/patch/tests/PR74127-repro.diff4
-rw-r--r--usr.bin/patch/tests/PR74127.in14
-rwxr-xr-xusr.bin/patch/tests/unified_patch_test.sh170
-rw-r--r--usr.bin/patch/util.c423
-rw-r--r--usr.bin/patch/util.h50
-rw-r--r--usr.bin/pathchk/Makefile3
-rw-r--r--usr.bin/pathchk/Makefile.depend15
-rw-r--r--usr.bin/pathchk/pathchk.1129
-rw-r--r--usr.bin/pathchk/pathchk.c201
-rw-r--r--usr.bin/perror/Makefile3
-rw-r--r--usr.bin/perror/Makefile.depend15
-rw-r--r--usr.bin/perror/perror.148
-rw-r--r--usr.bin/perror/perror.c80
-rw-r--r--usr.bin/pom/Makefile7
-rw-r--r--usr.bin/pom/Makefile.depend18
-rw-r--r--usr.bin/pom/pom.663
-rw-r--r--usr.bin/pom/pom.c241
-rw-r--r--usr.bin/posixmqcontrol/Makefile4
-rw-r--r--usr.bin/posixmqcontrol/posixmqcontrol.1180
-rw-r--r--usr.bin/posixmqcontrol/posixmqcontrol.c924
-rw-r--r--usr.bin/posixmqcontrol/posixmqcontroltest8qs.sh50
-rw-r--r--usr.bin/posixmqcontrol/posixmqcontroltest8x64.sh99
-rw-r--r--usr.bin/posixmqcontrol/posixmqcontroltestsane.sh28
-rw-r--r--usr.bin/posixshmcontrol/Makefile4
-rw-r--r--usr.bin/posixshmcontrol/posixshmcontrol.1175
-rw-r--r--usr.bin/posixshmcontrol/posixshmcontrol.c592
-rw-r--r--usr.bin/pr/Makefile9
-rw-r--r--usr.bin/pr/Makefile.depend15
-rw-r--r--usr.bin/pr/egetopt.c211
-rw-r--r--usr.bin/pr/extern.h62
-rw-r--r--usr.bin/pr/pr.1386
-rw-r--r--usr.bin/pr/pr.c1849
-rw-r--r--usr.bin/pr/pr.h73
-rw-r--r--usr.bin/pr/tests/Makefile15
-rw-r--r--usr.bin/pr/tests/Makefile.depend10
-rw-r--r--usr.bin/pr/tests/across.out2
-rw-r--r--usr.bin/pr/tests/basic2_test.sh59
-rw-r--r--usr.bin/pr/tests/merge.out3
-rw-r--r--usr.bin/pr/tests/other.in3
-rw-r--r--usr.bin/pr/tests/threecol.out1
-rw-r--r--usr.bin/primes/Makefile6
-rw-r--r--usr.bin/primes/Makefile.depend17
-rw-r--r--usr.bin/primes/pattern.c436
-rw-r--r--usr.bin/primes/pr_tbl.c540
-rw-r--r--usr.bin/primes/primes.c315
-rw-r--r--usr.bin/primes/primes.h71
-rw-r--r--usr.bin/primes/spsp.c198
-rw-r--r--usr.bin/printenv/Makefile8
-rw-r--r--usr.bin/printenv/Makefile.depend17
-rw-r--r--usr.bin/printenv/printenv.181
-rw-r--r--usr.bin/printenv/printenv.c91
-rw-r--r--usr.bin/printenv/tests/Makefile6
-rw-r--r--usr.bin/printenv/tests/Makefile.depend10
-rw-r--r--usr.bin/printenv/tests/printenv_test.sh64
-rw-r--r--usr.bin/printf/Makefile8
-rw-r--r--usr.bin/printf/Makefile.depend15
-rw-r--r--usr.bin/printf/printf.1415
-rw-r--r--usr.bin/printf/printf.c672
-rw-r--r--usr.bin/printf/tests/Makefile21
-rw-r--r--usr.bin/printf/tests/Makefile.depend10
-rw-r--r--usr.bin/printf/tests/legacy_test.sh5
-rw-r--r--usr.bin/printf/tests/regress.b.out1
-rw-r--r--usr.bin/printf/tests/regress.bwidth.out1
-rw-r--r--usr.bin/printf/tests/regress.d.out1
-rw-r--r--usr.bin/printf/tests/regress.f.out1
-rw-r--r--usr.bin/printf/tests/regress.l1.out1
-rw-r--r--usr.bin/printf/tests/regress.l2.out1
-rw-r--r--usr.bin/printf/tests/regress.m1.outbin0 -> 7 bytes
-rw-r--r--usr.bin/printf/tests/regress.m2.out2
-rw-r--r--usr.bin/printf/tests/regress.m3.out4
-rw-r--r--usr.bin/printf/tests/regress.m4.out1
-rw-r--r--usr.bin/printf/tests/regress.m5.out1
-rw-r--r--usr.bin/printf/tests/regress.missingpos1.out1
-rw-r--r--usr.bin/printf/tests/regress.s.out1
-rw-r--r--usr.bin/printf/tests/regress.sh31
-rw-r--r--usr.bin/printf/tests/regress.zero.out1
-rw-r--r--usr.bin/proccontrol/Makefile3
-rw-r--r--usr.bin/proccontrol/Makefile.depend15
-rw-r--r--usr.bin/proccontrol/proccontrol.1146
-rw-r--r--usr.bin/proccontrol/proccontrol.c429
-rw-r--r--usr.bin/procstat/Makefile39
-rw-r--r--usr.bin/procstat/Makefile.depend20
-rw-r--r--usr.bin/procstat/procstat.1901
-rw-r--r--usr.bin/procstat/procstat.c653
-rw-r--r--usr.bin/procstat/procstat.h84
-rw-r--r--usr.bin/procstat/procstat_advlock.c102
-rw-r--r--usr.bin/procstat/procstat_args.c96
-rw-r--r--usr.bin/procstat/procstat_auxv.c269
-rw-r--r--usr.bin/procstat/procstat_basic.c68
-rw-r--r--usr.bin/procstat/procstat_bin.c64
-rw-r--r--usr.bin/procstat/procstat_cred.c103
-rw-r--r--usr.bin/procstat/procstat_cs.c116
-rw-r--r--usr.bin/procstat/procstat_files.c595
-rw-r--r--usr.bin/procstat/procstat_kqueue.c319
-rw-r--r--usr.bin/procstat/procstat_kstack.c247
-rw-r--r--usr.bin/procstat/procstat_penv.c83
-rw-r--r--usr.bin/procstat/procstat_ptlwpinfo.c92
-rw-r--r--usr.bin/procstat/procstat_pwdx.c67
-rw-r--r--usr.bin/procstat/procstat_rlimit.c127
-rw-r--r--usr.bin/procstat/procstat_rlimitusage.c76
-rw-r--r--usr.bin/procstat/procstat_rusage.c194
-rw-r--r--usr.bin/procstat/procstat_sigs.c244
-rw-r--r--usr.bin/procstat/procstat_threads.c133
-rw-r--r--usr.bin/procstat/procstat_vm.c180
-rw-r--r--usr.bin/procstat/tests/Makefile7
-rw-r--r--usr.bin/procstat/tests/Makefile.depend15
-rwxr-xr-xusr.bin/procstat/tests/procstat_test.sh162
-rw-r--r--usr.bin/procstat/tests/while1.c38
-rw-r--r--usr.bin/protect/Makefile3
-rw-r--r--usr.bin/protect/Makefile.depend14
-rw-r--r--usr.bin/protect/protect.1137
-rw-r--r--usr.bin/protect/protect.c122
-rw-r--r--usr.bin/quota/Makefile7
-rw-r--r--usr.bin/quota/Makefile.depend19
-rw-r--r--usr.bin/quota/quota.1173
-rw-r--r--usr.bin/quota/quota.c687
-rw-r--r--usr.bin/random/Makefile5
-rw-r--r--usr.bin/random/Makefile.depend16
-rw-r--r--usr.bin/random/random.6117
-rw-r--r--usr.bin/random/random.c181
-rw-r--r--usr.bin/random/randomize_fd.c246
-rw-r--r--usr.bin/random/randomize_fd.h79
-rw-r--r--usr.bin/rctl/Makefile6
-rw-r--r--usr.bin/rctl/Makefile.depend16
-rw-r--r--usr.bin/rctl/rctl.8298
-rw-r--r--usr.bin/rctl/rctl.c683
-rw-r--r--usr.bin/readelf/Makefile36
-rw-r--r--usr.bin/readelf/Makefile.depend20
-rw-r--r--usr.bin/readelf/Makefile.depend.options7
-rw-r--r--usr.bin/renice/Makefile9
-rw-r--r--usr.bin/renice/Makefile.depend15
-rw-r--r--usr.bin/renice/renice.8125
-rw-r--r--usr.bin/renice/renice.c179
-rw-r--r--usr.bin/renice/tests/Makefile4
-rwxr-xr-xusr.bin/renice/tests/renice_test.sh174
-rw-r--r--usr.bin/resizewin/Makefile4
-rw-r--r--usr.bin/resizewin/Makefile.depend15
-rw-r--r--usr.bin/resizewin/resizewin.185
-rw-r--r--usr.bin/resizewin/resizewin.c158
-rw-r--r--usr.bin/rev/Makefile3
-rw-r--r--usr.bin/rev/Makefile.depend15
-rw-r--r--usr.bin/rev/rev.149
-rw-r--r--usr.bin/rev/rev.c101
-rw-r--r--usr.bin/revoke/Makefile3
-rw-r--r--usr.bin/revoke/Makefile.depend14
-rw-r--r--usr.bin/revoke/revoke.154
-rw-r--r--usr.bin/revoke/revoke.c59
-rw-r--r--usr.bin/rpcgen/Makefile5
-rw-r--r--usr.bin/rpcgen/Makefile.depend15
-rw-r--r--usr.bin/rpcgen/Makefile.depend.host10
-rw-r--r--usr.bin/rpcgen/Makefile.depend.options6
-rw-r--r--usr.bin/rpcgen/rpc_clntout.c268
-rw-r--r--usr.bin/rpcgen/rpc_cout.c710
-rw-r--r--usr.bin/rpcgen/rpc_hout.c513
-rw-r--r--usr.bin/rpcgen/rpc_main.c1354
-rw-r--r--usr.bin/rpcgen/rpc_parse.c620
-rw-r--r--usr.bin/rpcgen/rpc_parse.h195
-rw-r--r--usr.bin/rpcgen/rpc_sample.c289
-rw-r--r--usr.bin/rpcgen/rpc_scan.c488
-rw-r--r--usr.bin/rpcgen/rpc_scan.h131
-rw-r--r--usr.bin/rpcgen/rpc_svcout.c1015
-rw-r--r--usr.bin/rpcgen/rpc_tblout.c162
-rw-r--r--usr.bin/rpcgen/rpc_util.c501
-rw-r--r--usr.bin/rpcgen/rpc_util.h225
-rw-r--r--usr.bin/rpcgen/rpcgen.1534
-rw-r--r--usr.bin/rpcinfo/Makefile9
-rw-r--r--usr.bin/rpcinfo/Makefile.depend17
-rw-r--r--usr.bin/rpcinfo/rpcinfo.8339
-rw-r--r--usr.bin/rpcinfo/rpcinfo.c1665
-rw-r--r--usr.bin/rs/Makefile8
-rw-r--r--usr.bin/rs/Makefile.depend18
-rw-r--r--usr.bin/rs/rs.1244
-rw-r--r--usr.bin/rs/rs.cc462
-rw-r--r--usr.bin/rs/tests/Makefile3
-rw-r--r--usr.bin/rs/tests/rs_test.sh396
-rw-r--r--usr.bin/rup/Makefile5
-rw-r--r--usr.bin/rup/Makefile.depend19
-rw-r--r--usr.bin/rup/rup.193
-rw-r--r--usr.bin/rup/rup.c240
-rw-r--r--usr.bin/ruptime/Makefile5
-rw-r--r--usr.bin/ruptime/Makefile.depend16
-rw-r--r--usr.bin/ruptime/ruptime.187
-rw-r--r--usr.bin/ruptime/ruptime.c310
-rw-r--r--usr.bin/rusers/Makefile5
-rw-r--r--usr.bin/rusers/Makefile.depend19
-rw-r--r--usr.bin/rusers/rusers.1101
-rw-r--r--usr.bin/rusers/rusers.c250
-rw-r--r--usr.bin/rwall/Makefile3
-rw-r--r--usr.bin/rwall/Makefile.depend17
-rw-r--r--usr.bin/rwall/rwall.176
-rw-r--r--usr.bin/rwall/rwall.c172
-rw-r--r--usr.bin/rwho/Makefile5
-rw-r--r--usr.bin/rwho/Makefile.depend18
-rw-r--r--usr.bin/rwho/rwho.177
-rw-r--r--usr.bin/rwho/rwho.c235
-rw-r--r--usr.bin/script/Makefile5
-rw-r--r--usr.bin/script/Makefile.depend16
-rw-r--r--usr.bin/script/script.1304
-rw-r--r--usr.bin/script/script.c653
-rw-r--r--usr.bin/sdiff/Makefile11
-rw-r--r--usr.bin/sdiff/Makefile.depend15
-rw-r--r--usr.bin/sdiff/edit.c208
-rw-r--r--usr.bin/sdiff/extern.h11
-rw-r--r--usr.bin/sdiff/sdiff.1169
-rw-r--r--usr.bin/sdiff/sdiff.c1178
-rw-r--r--usr.bin/sdiff/tests/Makefile33
-rw-r--r--usr.bin/sdiff/tests/Makefile.depend10
-rw-r--r--usr.bin/sdiff/tests/d_dot.in1
-rw-r--r--usr.bin/sdiff/tests/d_flags_l.out102
-rw-r--r--usr.bin/sdiff/tests/d_flags_s.out79
-rw-r--r--usr.bin/sdiff/tests/d_flags_w.out102
-rw-r--r--usr.bin/sdiff/tests/d_iflags_a1.out100
-rw-r--r--usr.bin/sdiff/tests/d_iflags_a2.out96
-rw-r--r--usr.bin/sdiff/tests/d_iflags_b1.out69
-rw-r--r--usr.bin/sdiff/tests/d_iflags_b2.out65
-rw-r--r--usr.bin/sdiff/tests/d_iflags_c1.out99
-rw-r--r--usr.bin/sdiff/tests/d_iflags_c2.out94
-rw-r--r--usr.bin/sdiff/tests/d_iflags_d1.out69
-rw-r--r--usr.bin/sdiff/tests/d_iflags_d2.out65
-rw-r--r--usr.bin/sdiff/tests/d_input172
-rw-r--r--usr.bin/sdiff/tests/d_input269
-rw-r--r--usr.bin/sdiff/tests/d_oneline.in1
-rw-r--r--usr.bin/sdiff/tests/d_oneline_a.out1
-rw-r--r--usr.bin/sdiff/tests/d_oneline_b.out1
-rw-r--r--usr.bin/sdiff/tests/d_same.out72
-rw-r--r--usr.bin/sdiff/tests/d_short.out15
-rw-r--r--usr.bin/sdiff/tests/d_tabends.in17
-rw-r--r--usr.bin/sdiff/tests/d_tabends_a.out17
-rw-r--r--usr.bin/sdiff/tests/d_tabends_b.out17
-rw-r--r--usr.bin/sdiff/tests/d_tabends_c.out17
-rw-r--r--usr.bin/sdiff/tests/d_tabs.out102
-rw-r--r--usr.bin/sdiff/tests/d_tabs1.in72
-rw-r--r--usr.bin/sdiff/tests/d_tabs2.in69
-rwxr-xr-xusr.bin/sdiff/tests/sdiff_test.sh242
-rw-r--r--usr.bin/sdiotool/Makefile7
-rw-r--r--usr.bin/sdiotool/brcmfmac_bus.h26
-rw-r--r--usr.bin/sdiotool/brcmfmac_sdio.h160
-rw-r--r--usr.bin/sdiotool/cam_sdio.c436
-rw-r--r--usr.bin/sdiotool/cam_sdio.h93
-rw-r--r--usr.bin/sdiotool/linux_compat.h56
-rw-r--r--usr.bin/sdiotool/linux_sdio_compat.c100
-rw-r--r--usr.bin/sdiotool/linux_sdio_compat.h61
-rw-r--r--usr.bin/sdiotool/sdiotool.c552
-rw-r--r--usr.bin/sed/Makefile10
-rw-r--r--usr.bin/sed/Makefile.depend15
-rw-r--r--usr.bin/sed/Makefile.depend.host10
-rw-r--r--usr.bin/sed/Makefile.depend.options6
-rw-r--r--usr.bin/sed/POSIX202
-rw-r--r--usr.bin/sed/compile.c1071
-rw-r--r--usr.bin/sed/defs.h148
-rw-r--r--usr.bin/sed/extern.h57
-rw-r--r--usr.bin/sed/main.c544
-rw-r--r--usr.bin/sed/misc.c68
-rw-r--r--usr.bin/sed/process.c784
-rw-r--r--usr.bin/sed/sed.1683
-rw-r--r--usr.bin/sed/tests/Makefile42
-rw-r--r--usr.bin/sed/tests/Makefile.depend10
-rw-r--r--usr.bin/sed/tests/hanoi.sed98
-rw-r--r--usr.bin/sed/tests/inplace_race_test.sh78
-rw-r--r--usr.bin/sed/tests/legacy_test.sh5
-rw-r--r--usr.bin/sed/tests/math.sed438
-rw-r--r--usr.bin/sed/tests/multi_test.sh491
-rw-r--r--usr.bin/sed/tests/regress.G.out8
-rw-r--r--usr.bin/sed/tests/regress.P.out8
-rw-r--r--usr.bin/sed/tests/regress.b2a.out3
-rw-r--r--usr.bin/sed/tests/regress.bcb.out4
-rw-r--r--usr.bin/sed/tests/regress.c0.out4
-rw-r--r--usr.bin/sed/tests/regress.c1.out4
-rw-r--r--usr.bin/sed/tests/regress.c2.out3
-rw-r--r--usr.bin/sed/tests/regress.c3.out3
-rw-r--r--usr.bin/sed/tests/regress.hanoi.out17
-rw-r--r--usr.bin/sed/tests/regress.icase1.out3
-rw-r--r--usr.bin/sed/tests/regress.icase2.out4
-rw-r--r--usr.bin/sed/tests/regress.icase3.out4
-rw-r--r--usr.bin/sed/tests/regress.icase4.out4
-rw-r--r--usr.bin/sed/tests/regress.in4
-rw-r--r--usr.bin/sed/tests/regress.math.out1
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.128
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1014
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1114
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1342
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1442
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1542
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1656
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1728
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.1814
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.328
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.4.114
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.528
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.628
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.728
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.828
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/1.914
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.11
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.101
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.111
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.124
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.1323
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.1423
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.1520
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.1617
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.1717
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.187
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.191
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.21
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.201
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.215
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.223
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.232
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.31
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.41
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.50
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.61
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.70
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.80
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/2.91
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/3.114
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/3.214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/3.314
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/3.414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.147
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.254
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.356
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.51
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.61
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.71
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/4.80
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.117
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.312
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.55
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.65
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.76
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/5.814
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.114
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.213
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.30
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.420
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.514
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/6.60
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.115
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.232
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.324
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.423
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.514
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.614
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.72814
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/7.81
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.114
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1014
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1128
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1314
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1513
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.167
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1714
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1814
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.1914
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.214
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.2014
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.211
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.221
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.231
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.314
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.414
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.514
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.614
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.714
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.814
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/8.942
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.11
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.101
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.111
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.121
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.131
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.141
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.151
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.161
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.171
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.181
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.191
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.21
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.201
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.211
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.221
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.231
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.241
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.251
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.261
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.271
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.281
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.291
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.31
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.301
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.311
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.41
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.51
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.61
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.71
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.81
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/9.91
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/Makefile136
-rw-r--r--usr.bin/sed/tests/regress.multitest.out/Makefile.depend10
-rw-r--r--usr.bin/sed/tests/regress.not.out1
-rw-r--r--usr.bin/sed/tests/regress.psl.out4
-rw-r--r--usr.bin/sed/tests/regress.s3.out1
-rw-r--r--usr.bin/sed/tests/regress.s4.out1
-rw-r--r--usr.bin/sed/tests/regress.s5.out1
-rw-r--r--usr.bin/sed/tests/regress.sg.out1
-rw-r--r--usr.bin/sed/tests/regress.sh74
-rw-r--r--usr.bin/sed/tests/regress.y.out1
-rwxr-xr-xusr.bin/sed/tests/sed2_test.sh209
-rw-r--r--usr.bin/seq/Makefile12
-rw-r--r--usr.bin/seq/Makefile.depend16
-rw-r--r--usr.bin/seq/seq.1209
-rw-r--r--usr.bin/seq/seq.c508
-rw-r--r--usr.bin/seq/tests/Makefile5
-rw-r--r--usr.bin/seq/tests/Makefile.depend10
-rwxr-xr-xusr.bin/seq/tests/seq_test.sh54
-rw-r--r--usr.bin/shar/Makefile4
-rw-r--r--usr.bin/shar/Makefile.depend10
-rw-r--r--usr.bin/shar/shar.1121
-rw-r--r--usr.bin/shar/shar.sh78
-rw-r--r--usr.bin/showmount/Makefile4
-rw-r--r--usr.bin/showmount/Makefile.depend17
-rw-r--r--usr.bin/showmount/showmount.8106
-rw-r--r--usr.bin/showmount/showmount.c414
-rw-r--r--usr.bin/size/Makefile22
-rw-r--r--usr.bin/size/Makefile.depend18
-rw-r--r--usr.bin/size/Makefile.depend.options7
-rw-r--r--usr.bin/smbutil/Makefile14
-rw-r--r--usr.bin/smbutil/Makefile.depend17
-rw-r--r--usr.bin/sockstat/Makefile16
-rw-r--r--usr.bin/sockstat/Makefile.depend23
-rw-r--r--usr.bin/sockstat/sockstat.1249
-rw-r--r--usr.bin/sockstat/sockstat.c1646
-rw-r--r--usr.bin/soelim/Makefile8
-rw-r--r--usr.bin/soelim/Makefile.depend15
-rw-r--r--usr.bin/soelim/soelim.189
-rw-r--r--usr.bin/soelim/soelim.c174
-rw-r--r--usr.bin/soelim/tests/Makefile12
-rw-r--r--usr.bin/soelim/tests/Makefile.depend10
-rw-r--r--usr.bin/soelim/tests/basic1
-rw-r--r--usr.bin/soelim/tests/basic-with-space.in3
-rw-r--r--usr.bin/soelim/tests/basic-with-space.out4
-rw-r--r--usr.bin/soelim/tests/basic.in3
-rw-r--r--usr.bin/soelim/tests/basic.out3
-rw-r--r--usr.bin/soelim/tests/nonexisting.in3
-rwxr-xr-xusr.bin/soelim/tests/soelim_test.sh102
-rw-r--r--usr.bin/sort/Makefile24
-rw-r--r--usr.bin/sort/Makefile.depend16
-rw-r--r--usr.bin/sort/Makefile.depend.options7
-rw-r--r--usr.bin/sort/bwstring.c1047
-rw-r--r--usr.bin/sort/bwstring.h142
-rw-r--r--usr.bin/sort/coll.c1318
-rw-r--r--usr.bin/sort/coll.h181
-rw-r--r--usr.bin/sort/file.c1487
-rw-r--r--usr.bin/sort/file.h127
-rw-r--r--usr.bin/sort/mem.c91
-rw-r--r--usr.bin/sort/mem.h47
-rw-r--r--usr.bin/sort/radixsort.c722
-rw-r--r--usr.bin/sort/radixsort.h39
-rw-r--r--usr.bin/sort/sort.1.in632
-rw-r--r--usr.bin/sort/sort.c1331
-rw-r--r--usr.bin/sort/sort.h128
-rw-r--r--usr.bin/sort/tests/Makefile13
-rw-r--r--usr.bin/sort/tests/Makefile.depend10
-rwxr-xr-xusr.bin/sort/tests/sort_monthsort_test.sh159
-rw-r--r--usr.bin/sort/vsort.c264
-rw-r--r--usr.bin/sort/vsort.h38
-rw-r--r--usr.bin/split/Makefile10
-rw-r--r--usr.bin/split/Makefile.depend16
-rw-r--r--usr.bin/split/split.1232
-rw-r--r--usr.bin/split/split.c451
-rw-r--r--usr.bin/split/tests/Makefile5
-rw-r--r--usr.bin/split/tests/Makefile.depend10
-rwxr-xr-xusr.bin/split/tests/split_test.sh274
-rw-r--r--usr.bin/ssh-copy-id/Makefile5
-rw-r--r--usr.bin/ssh-copy-id/Makefile.depend10
-rw-r--r--usr.bin/ssh-copy-id/ssh-copy-id.187
-rwxr-xr-xusr.bin/ssh-copy-id/ssh-copy-id.sh117
-rw-r--r--usr.bin/stat/Makefile11
-rw-r--r--usr.bin/stat/Makefile.depend15
-rw-r--r--usr.bin/stat/stat.1604
-rw-r--r--usr.bin/stat/stat.c1091
-rw-r--r--usr.bin/stat/tests/Makefile4
-rw-r--r--usr.bin/stat/tests/Makefile.depend10
-rwxr-xr-xusr.bin/stat/tests/readlink_test.sh72
-rwxr-xr-xusr.bin/stat/tests/stat_test.sh245
-rw-r--r--usr.bin/stdbuf/Makefile4
-rw-r--r--usr.bin/stdbuf/Makefile.depend14
-rw-r--r--usr.bin/stdbuf/stdbuf.1114
-rw-r--r--usr.bin/stdbuf/stdbuf.c108
-rw-r--r--usr.bin/strings/Makefile19
-rw-r--r--usr.bin/strings/Makefile.depend18
-rw-r--r--usr.bin/strings/Makefile.depend.options7
-rw-r--r--usr.bin/su/Makefile16
-rw-r--r--usr.bin/su/Makefile.depend17
-rw-r--r--usr.bin/su/Makefile.depend.options5
-rw-r--r--usr.bin/su/su.1247
-rw-r--r--usr.bin/su/su.c629
-rw-r--r--usr.bin/systat/Makefile18
-rw-r--r--usr.bin/systat/Makefile.depend23
-rw-r--r--usr.bin/systat/cmds.c192
-rw-r--r--usr.bin/systat/cmdtab.c85
-rw-r--r--usr.bin/systat/convtbl.c150
-rw-r--r--usr.bin/systat/convtbl.h59
-rw-r--r--usr.bin/systat/devs.c431
-rw-r--r--usr.bin/systat/devs.h46
-rw-r--r--usr.bin/systat/extern.h189
-rw-r--r--usr.bin/systat/fetch.c135
-rw-r--r--usr.bin/systat/icmp.c275
-rw-r--r--usr.bin/systat/icmp6.c275
-rw-r--r--usr.bin/systat/ifcmds.c79
-rw-r--r--usr.bin/systat/ifstat.c514
-rw-r--r--usr.bin/systat/iolat.c520
-rw-r--r--usr.bin/systat/iostat.c384
-rw-r--r--usr.bin/systat/ip.c336
-rw-r--r--usr.bin/systat/ip6.c299
-rw-r--r--usr.bin/systat/keyboard.c176
-rw-r--r--usr.bin/systat/main.c390
-rw-r--r--usr.bin/systat/mode.c96
-rw-r--r--usr.bin/systat/mode.h42
-rw-r--r--usr.bin/systat/netcmds.c304
-rw-r--r--usr.bin/systat/netstat.c633
-rw-r--r--usr.bin/systat/pigs.c184
-rw-r--r--usr.bin/systat/proc.c296
-rw-r--r--usr.bin/systat/sctp.c354
-rw-r--r--usr.bin/systat/swap.c177
-rw-r--r--usr.bin/systat/sysput.c113
-rw-r--r--usr.bin/systat/systat.1745
-rw-r--r--usr.bin/systat/systat.h77
-rw-r--r--usr.bin/systat/tcp.c319
-rw-r--r--usr.bin/systat/vmstat.c817
-rw-r--r--usr.bin/systat/zarc.c236
-rw-r--r--usr.bin/tabs/Makefile5
-rw-r--r--usr.bin/tabs/Makefile.depend16
-rw-r--r--usr.bin/tabs/tabs.1163
-rw-r--r--usr.bin/tabs/tabs.c236
-rw-r--r--usr.bin/tail/Makefile16
-rw-r--r--usr.bin/tail/Makefile.depend17
-rw-r--r--usr.bin/tail/Makefile.depend.options7
-rw-r--r--usr.bin/tail/extern.h77
-rw-r--r--usr.bin/tail/forward.c433
-rw-r--r--usr.bin/tail/misc.c128
-rw-r--r--usr.bin/tail/read.c208
-rw-r--r--usr.bin/tail/reverse.c280
-rw-r--r--usr.bin/tail/tail.1216
-rw-r--r--usr.bin/tail/tail.c368
-rw-r--r--usr.bin/tail/tests/Makefile5
-rw-r--r--usr.bin/tail/tests/Makefile.depend10
-rwxr-xr-xusr.bin/tail/tests/tail_test.sh451
-rw-r--r--usr.bin/talk/Makefile7
-rw-r--r--usr.bin/talk/Makefile.depend19
-rw-r--r--usr.bin/talk/ctl.c118
-rw-r--r--usr.bin/talk/ctl_transact.c101
-rw-r--r--usr.bin/talk/display.c206
-rw-r--r--usr.bin/talk/get_addrs.c61
-rw-r--r--usr.bin/talk/get_iface.c97
-rw-r--r--usr.bin/talk/get_names.c111
-rw-r--r--usr.bin/talk/init_disp.c229
-rw-r--r--usr.bin/talk/invite.c188
-rw-r--r--usr.bin/talk/io.c173
-rw-r--r--usr.bin/talk/look_up.c113
-rw-r--r--usr.bin/talk/msgs.c76
-rw-r--r--usr.bin/talk/talk.1156
-rw-r--r--usr.bin/talk/talk.c70
-rw-r--r--usr.bin/talk/talk.h92
-rw-r--r--usr.bin/talk/talk_ctl.h39
-rw-r--r--usr.bin/tar/Makefile40
-rw-r--r--usr.bin/tar/Makefile.depend16
-rw-r--r--usr.bin/tar/Makefile.depend.host10
-rw-r--r--usr.bin/tar/Makefile.depend.options6
-rw-r--r--usr.bin/tar/tests/Makefile130
-rw-r--r--usr.bin/tar/tests/Makefile.depend14
-rwxr-xr-xusr.bin/tar/tests/functional_test.sh50
-rw-r--r--usr.bin/tcopy/Makefile4
-rw-r--r--usr.bin/tcopy/Makefile.depend15
-rw-r--r--usr.bin/tcopy/tcopy.1132
-rw-r--r--usr.bin/tcopy/tcopy.c338
-rw-r--r--usr.bin/tee/Makefile3
-rw-r--r--usr.bin/tee/Makefile.depend17
-rw-r--r--usr.bin/tee/tee.192
-rw-r--r--usr.bin/tee/tee.c146
-rw-r--r--usr.bin/telnet/Makefile38
-rw-r--r--usr.bin/telnet/Makefile.depend18
-rw-r--r--usr.bin/telnet/Makefile.depend.options10
-rw-r--r--usr.bin/tests/Makefile8
-rw-r--r--usr.bin/tests/Makefile.depend10
-rw-r--r--usr.bin/tests/regress.m458
-rw-r--r--usr.bin/tftp/Makefile15
-rw-r--r--usr.bin/tftp/Makefile.depend17
-rw-r--r--usr.bin/tftp/main.c1087
-rw-r--r--usr.bin/tftp/tests/Makefile8
-rw-r--r--usr.bin/tftp/tests/Makefile.depend10
-rw-r--r--usr.bin/tftp/tests/tftp_test.sh465
-rw-r--r--usr.bin/tftp/tftp.1284
-rw-r--r--usr.bin/tftp/tftp.c268
-rw-r--r--usr.bin/tftp/tftp.h36
-rw-r--r--usr.bin/time/Makefile3
-rw-r--r--usr.bin/time/Makefile.depend15
-rw-r--r--usr.bin/time/time.1202
-rw-r--r--usr.bin/time/time.c299
-rw-r--r--usr.bin/tip/Makefile3
-rw-r--r--usr.bin/tip/Makefile.inc1
-rw-r--r--usr.bin/tip/README62
-rw-r--r--usr.bin/tip/TODO19
-rw-r--r--usr.bin/tip/libacu/biz22.c179
-rw-r--r--usr.bin/tip/libacu/biz31.c246
-rw-r--r--usr.bin/tip/libacu/courier.c346
-rw-r--r--usr.bin/tip/libacu/df.c129
-rw-r--r--usr.bin/tip/libacu/dn11.c141
-rw-r--r--usr.bin/tip/libacu/hayes.c312
-rw-r--r--usr.bin/tip/libacu/t3000.c364
-rw-r--r--usr.bin/tip/libacu/v3451.c204
-rw-r--r--usr.bin/tip/libacu/v831.c255
-rw-r--r--usr.bin/tip/libacu/ventel.c251
-rw-r--r--usr.bin/tip/tip/Makefile60
-rw-r--r--usr.bin/tip/tip/Makefile.depend15
-rw-r--r--usr.bin/tip/tip/acu.c187
-rw-r--r--usr.bin/tip/tip/acutab.c81
-rw-r--r--usr.bin/tip/tip/cmds.c991
-rw-r--r--usr.bin/tip/tip/cmdtab.c58
-rw-r--r--usr.bin/tip/tip/cu.1511
-rw-r--r--usr.bin/tip/tip/cu.c202
-rw-r--r--usr.bin/tip/tip/hunt.c101
-rw-r--r--usr.bin/tip/tip/log.c84
-rw-r--r--usr.bin/tip/tip/partab.c55
-rw-r--r--usr.bin/tip/tip/pathnames.h40
-rw-r--r--usr.bin/tip/tip/phones5
-rw-r--r--usr.bin/tip/tip/remote72
-rw-r--r--usr.bin/tip/tip/remote.c228
-rw-r--r--usr.bin/tip/tip/tip.1605
-rw-r--r--usr.bin/tip/tip/tip.c624
-rw-r--r--usr.bin/tip/tip/tip.h355
-rw-r--r--usr.bin/tip/tip/tipout.c180
-rw-r--r--usr.bin/tip/tip/uucplock.c123
-rw-r--r--usr.bin/tip/tip/value.c355
-rw-r--r--usr.bin/tip/tip/vars.c116
-rw-r--r--usr.bin/top/Makefile9
-rw-r--r--usr.bin/top/Makefile.depend21
-rw-r--r--usr.bin/top/commands.c518
-rw-r--r--usr.bin/top/commands.h59
-rw-r--r--usr.bin/top/display.c1361
-rw-r--r--usr.bin/top/display.h41
-rw-r--r--usr.bin/top/layout.h33
-rw-r--r--usr.bin/top/loadavg.h25
-rw-r--r--usr.bin/top/machine.c1616
-rw-r--r--usr.bin/top/machine.h98
-rw-r--r--usr.bin/top/screen.c316
-rw-r--r--usr.bin/top/screen.h34
-rw-r--r--usr.bin/top/top.1533
-rw-r--r--usr.bin/top/top.c1234
-rw-r--r--usr.bin/top/top.h67
-rw-r--r--usr.bin/top/username.c134
-rw-r--r--usr.bin/top/username.h30
-rw-r--r--usr.bin/top/utils.c329
-rw-r--r--usr.bin/top/utils.h24
-rw-r--r--usr.bin/touch/Makefile7
-rw-r--r--usr.bin/touch/Makefile.depend15
-rw-r--r--usr.bin/touch/tests/Makefile4
-rw-r--r--usr.bin/touch/tests/Makefile.depend10
-rw-r--r--usr.bin/touch/tests/touch_test.sh157
-rw-r--r--usr.bin/touch/touch.1247
-rw-r--r--usr.bin/touch/touch.c407
-rw-r--r--usr.bin/tr/Makefile10
-rw-r--r--usr.bin/tr/Makefile.depend17
-rw-r--r--usr.bin/tr/cmap.c212
-rw-r--r--usr.bin/tr/cmap.h83
-rw-r--r--usr.bin/tr/cset.c290
-rw-r--r--usr.bin/tr/cset.h74
-rw-r--r--usr.bin/tr/extern.h50
-rw-r--r--usr.bin/tr/str.c383
-rw-r--r--usr.bin/tr/tests/Makefile23
-rw-r--r--usr.bin/tr/tests/Makefile.depend10
-rw-r--r--usr.bin/tr/tests/legacy_test.sh5
-rw-r--r--usr.bin/tr/tests/regress.00.out4
-rw-r--r--usr.bin/tr/tests/regress.01.out4
-rw-r--r--usr.bin/tr/tests/regress.02.out4
-rw-r--r--usr.bin/tr/tests/regress.03.out4
-rw-r--r--usr.bin/tr/tests/regress.04.out4
-rw-r--r--usr.bin/tr/tests/regress.05.out4
-rw-r--r--usr.bin/tr/tests/regress.06.out9
-rw-r--r--usr.bin/tr/tests/regress.07.out9
-rw-r--r--usr.bin/tr/tests/regress.08.out9
-rw-r--r--usr.bin/tr/tests/regress.09.out1
-rw-r--r--usr.bin/tr/tests/regress.0a.out1
-rw-r--r--usr.bin/tr/tests/regress.0b.out1
-rw-r--r--usr.bin/tr/tests/regress.0c.out1
-rw-r--r--usr.bin/tr/tests/regress.0d.out1
-rw-r--r--usr.bin/tr/tests/regress.in4
-rw-r--r--usr.bin/tr/tests/regress.sh21
-rw-r--r--usr.bin/tr/tests/regress2.in9
-rw-r--r--usr.bin/tr/tr.1422
-rw-r--r--usr.bin/tr/tr.c370
-rw-r--r--usr.bin/true/Makefile3
-rw-r--r--usr.bin/true/Makefile.depend13
-rw-r--r--usr.bin/true/true.160
-rw-r--r--usr.bin/true/true.c36
-rw-r--r--usr.bin/truncate/Makefile9
-rw-r--r--usr.bin/truncate/Makefile.depend16
-rw-r--r--usr.bin/truncate/tests/Makefile3
-rw-r--r--usr.bin/truncate/tests/Makefile.depend10
-rw-r--r--usr.bin/truncate/tests/truncate_test.sh462
-rw-r--r--usr.bin/truncate/truncate.1256
-rw-r--r--usr.bin/truncate/truncate.c226
-rw-r--r--usr.bin/truss/Makefile9
-rw-r--r--usr.bin/truss/Makefile.depend17
-rw-r--r--usr.bin/truss/extern.h39
-rw-r--r--usr.bin/truss/main.c207
-rw-r--r--usr.bin/truss/setup.c832
-rw-r--r--usr.bin/truss/syscall.h275
-rw-r--r--usr.bin/truss/syscalls.c2832
-rw-r--r--usr.bin/truss/truss.1116
-rw-r--r--usr.bin/truss/truss.h116
-rw-r--r--usr.bin/tsort/Makefile8
-rw-r--r--usr.bin/tsort/Makefile.depend15
-rw-r--r--usr.bin/tsort/tests/Makefile6
-rw-r--r--usr.bin/tsort/tests/Makefile.depend10
-rwxr-xr-xusr.bin/tsort/tests/tsort_test.sh66
-rw-r--r--usr.bin/tsort/tsort.1155
-rw-r--r--usr.bin/tsort/tsort.c419
-rw-r--r--usr.bin/tty/Makefile3
-rw-r--r--usr.bin/tty/Makefile.depend14
-rw-r--r--usr.bin/tty/tty.180
-rw-r--r--usr.bin/tty/tty.c67
-rw-r--r--usr.bin/ul/Makefile5
-rw-r--r--usr.bin/ul/Makefile.depend16
-rw-r--r--usr.bin/ul/ul.187
-rw-r--r--usr.bin/ul/ul.c574
-rw-r--r--usr.bin/uname/Makefile4
-rw-r--r--usr.bin/uname/Makefile.depend14
-rw-r--r--usr.bin/uname/uname.1170
-rw-r--r--usr.bin/uname/uname.c288
-rw-r--r--usr.bin/unexpand/Makefile4
-rw-r--r--usr.bin/unexpand/Makefile.depend15
-rw-r--r--usr.bin/unexpand/unexpand.c215
-rw-r--r--usr.bin/unifdef/Makefile12
-rw-r--r--usr.bin/unifdef/Makefile.depend15
-rw-r--r--usr.bin/unifdef/tests/Makefile11
-rw-r--r--usr.bin/unifdef/tests/Makefile.depend10
-rw-r--r--usr.bin/unifdef/tests/unifdef_test.sh54
-rw-r--r--usr.bin/uniq/Makefile8
-rw-r--r--usr.bin/uniq/Makefile.depend17
-rw-r--r--usr.bin/uniq/tests/Makefile4
-rw-r--r--usr.bin/uniq/tests/Makefile.depend10
-rwxr-xr-xusr.bin/uniq/tests/uniq_test.sh228
-rw-r--r--usr.bin/uniq/uniq.1218
-rw-r--r--usr.bin/uniq/uniq.c373
-rw-r--r--usr.bin/units/Makefile12
-rw-r--r--usr.bin/units/Makefile.depend18
-rw-r--r--usr.bin/units/README17
-rw-r--r--usr.bin/units/definitions.units907
-rw-r--r--usr.bin/units/tests/Makefile5
-rw-r--r--usr.bin/units/tests/Makefile.depend10
-rw-r--r--usr.bin/units/tests/basics_test.sh21
-rw-r--r--usr.bin/units/units.1473
-rw-r--r--usr.bin/units/units.c886
-rw-r--r--usr.bin/unvis/Makefile5
-rw-r--r--usr.bin/unvis/Makefile.depend14
-rw-r--r--usr.bin/unzip/Makefile30
-rw-r--r--usr.bin/unzip/Makefile.depend16
-rw-r--r--usr.bin/unzip/tests/Makefile75
-rw-r--r--usr.bin/unzip/tests/Makefile.depend14
-rwxr-xr-xusr.bin/unzip/tests/functional_test.sh55
-rw-r--r--usr.bin/usbhidaction/Makefile7
-rw-r--r--usr.bin/usbhidaction/Makefile.depend16
-rw-r--r--usr.bin/usbhidaction/usbhidaction.1172
-rw-r--r--usr.bin/usbhidaction/usbhidaction.c519
-rw-r--r--usr.bin/usbhidctl/Makefile8
-rw-r--r--usr.bin/usbhidctl/Makefile.depend16
-rw-r--r--usr.bin/usbhidctl/usbhid.c532
-rw-r--r--usr.bin/usbhidctl/usbhidctl.1150
-rw-r--r--usr.bin/users/Makefile6
-rw-r--r--usr.bin/users/Makefile.depend20
-rw-r--r--usr.bin/users/users.154
-rw-r--r--usr.bin/users/users.cc71
-rw-r--r--usr.bin/vacation/Makefile28
-rw-r--r--usr.bin/vacation/Makefile.depend18
-rw-r--r--usr.bin/vgrind/Makefile24
-rw-r--r--usr.bin/vgrind/Makefile.depend15
-rw-r--r--usr.bin/vgrind/extern.h59
-rw-r--r--usr.bin/vgrind/pathnames.h32
-rw-r--r--usr.bin/vgrind/regexp.c584
-rw-r--r--usr.bin/vgrind/tmac.vgrind71
-rw-r--r--usr.bin/vgrind/vfontedpr.c704
-rw-r--r--usr.bin/vgrind/vgrind.1239
-rw-r--r--usr.bin/vgrind/vgrind.sh128
-rw-r--r--usr.bin/vgrind/vgrindefs.5167
-rw-r--r--usr.bin/vgrind/vgrindefs.src153
-rw-r--r--usr.bin/vi/Makefile76
-rw-r--r--usr.bin/vi/Makefile.depend19
-rw-r--r--usr.bin/vi/catalog/Makefile166
-rw-r--r--usr.bin/vi/catalog/Makefile.depend15
-rw-r--r--usr.bin/vi/catalog/dutch.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/french.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/german.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/polish.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/ru_RU.UTF-8.base311
-rw-r--r--usr.bin/vi/catalog/spanish.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/swedish.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/uk_UA.UTF-8.base306
-rw-r--r--usr.bin/vi/catalog/zh_CN.UTF-8.base311
-rw-r--r--usr.bin/vi/config.h27
-rw-r--r--usr.bin/vi/ex/version.h1
-rw-r--r--usr.bin/vi/ex_def.h76
-rw-r--r--usr.bin/vi/extern.h444
-rw-r--r--usr.bin/vi/options_def.h86
-rw-r--r--usr.bin/vi/pathnames.h26
-rw-r--r--usr.bin/vis/Makefile7
-rw-r--r--usr.bin/vis/Makefile.depend15
-rw-r--r--usr.bin/vmstat/Makefile10
-rw-r--r--usr.bin/vmstat/Makefile.depend20
-rw-r--r--usr.bin/vmstat/tests/Makefile7
-rw-r--r--usr.bin/vmstat/tests/Makefile.depend10
-rw-r--r--usr.bin/vmstat/vmstat.8394
-rw-r--r--usr.bin/vmstat/vmstat.c1626
-rw-r--r--usr.bin/vtfontcvt/Makefile9
-rw-r--r--usr.bin/vtfontcvt/Makefile.depend15
-rw-r--r--usr.bin/vtfontcvt/vtfontcvt.899
-rw-r--r--usr.bin/vtfontcvt/vtfontcvt.c1120
-rw-r--r--usr.bin/w/Makefile9
-rw-r--r--usr.bin/w/Makefile.depend20
-rw-r--r--usr.bin/w/extern.h37
-rw-r--r--usr.bin/w/pr_time.c126
-rw-r--r--usr.bin/w/proc_compare.c114
-rw-r--r--usr.bin/w/uptime.159
-rw-r--r--usr.bin/w/w.1188
-rw-r--r--usr.bin/w/w.c582
-rw-r--r--usr.bin/wall/Makefile6
-rw-r--r--usr.bin/wall/Makefile.depend15
-rw-r--r--usr.bin/wall/ttymsg.c163
-rw-r--r--usr.bin/wall/ttymsg.h4
-rw-r--r--usr.bin/wall/wall.172
-rw-r--r--usr.bin/wall/wall.c280
-rw-r--r--usr.bin/wc/Makefile15
-rw-r--r--usr.bin/wc/Makefile.depend17
-rw-r--r--usr.bin/wc/Makefile.depend.options7
-rw-r--r--usr.bin/wc/tests/Makefile6
-rw-r--r--usr.bin/wc/tests/Makefile.depend10
-rwxr-xr-xusr.bin/wc/tests/wc_test.sh248
-rw-r--r--usr.bin/wc/wc.1209
-rw-r--r--usr.bin/wc/wc.c358
-rw-r--r--usr.bin/wg/Makefile37
-rw-r--r--usr.bin/what/Makefile4
-rw-r--r--usr.bin/what/Makefile.depend14
-rw-r--r--usr.bin/what/what.185
-rw-r--r--usr.bin/what/what.c125
-rw-r--r--usr.bin/whereis/Makefile3
-rw-r--r--usr.bin/whereis/Makefile.depend15
-rw-r--r--usr.bin/whereis/pathnames.h55
-rw-r--r--usr.bin/whereis/whereis.1181
-rw-r--r--usr.bin/whereis/whereis.c688
-rw-r--r--usr.bin/which/Makefile3
-rw-r--r--usr.bin/which/Makefile.depend15
-rw-r--r--usr.bin/which/which.1125
-rw-r--r--usr.bin/which/which.c144
-rw-r--r--usr.bin/who/Makefile4
-rw-r--r--usr.bin/who/Makefile.depend15
-rw-r--r--usr.bin/who/who.1195
-rw-r--r--usr.bin/who/who.c315
-rw-r--r--usr.bin/whois/Makefile10
-rw-r--r--usr.bin/whois/Makefile.depend16
-rw-r--r--usr.bin/whois/whois.1292
-rw-r--r--usr.bin/whois/whois.c610
-rw-r--r--usr.bin/write/Makefile5
-rw-r--r--usr.bin/write/Makefile.depend17
-rw-r--r--usr.bin/write/write.1106
-rw-r--r--usr.bin/write/write.c344
-rw-r--r--usr.bin/xargs/Makefile11
-rw-r--r--usr.bin/xargs/Makefile.depend15
-rw-r--r--usr.bin/xargs/Makefile.depend.host10
-rw-r--r--usr.bin/xargs/Makefile.depend.options6
-rw-r--r--usr.bin/xargs/pathnames.h32
-rw-r--r--usr.bin/xargs/strnsubst.c112
-rw-r--r--usr.bin/xargs/tests/Makefile28
-rw-r--r--usr.bin/xargs/tests/Makefile.depend10
-rw-r--r--usr.bin/xargs/tests/legacy_test.sh5
-rw-r--r--usr.bin/xargs/tests/regress.0.inbin0 -> 86 bytes
-rw-r--r--usr.bin/xargs/tests/regress.0.out8
-rw-r--r--usr.bin/xargs/tests/regress.0I.out18
-rw-r--r--usr.bin/xargs/tests/regress.0J.out4
-rw-r--r--usr.bin/xargs/tests/regress.0L.out6
-rw-r--r--usr.bin/xargs/tests/regress.0P1.out4
-rw-r--r--usr.bin/xargs/tests/regress.I.out4
-rw-r--r--usr.bin/xargs/tests/regress.J.out1
-rw-r--r--usr.bin/xargs/tests/regress.L.out2
-rw-r--r--usr.bin/xargs/tests/regress.P1.out1
-rw-r--r--usr.bin/xargs/tests/regress.R-1.out4
-rw-r--r--usr.bin/xargs/tests/regress.R.out4
-rw-r--r--usr.bin/xargs/tests/regress.in4
-rw-r--r--usr.bin/xargs/tests/regress.n1.out8
-rw-r--r--usr.bin/xargs/tests/regress.n2.out4
-rw-r--r--usr.bin/xargs/tests/regress.n2147483647.out1
-rw-r--r--usr.bin/xargs/tests/regress.n2P0.out4
-rw-r--r--usr.bin/xargs/tests/regress.n3.out3
-rw-r--r--usr.bin/xargs/tests/regress.normal.out1
-rw-r--r--usr.bin/xargs/tests/regress.quotes.in4
-rw-r--r--usr.bin/xargs/tests/regress.quotes.out7
-rw-r--r--usr.bin/xargs/tests/regress.sh32
-rw-r--r--usr.bin/xargs/xargs.1388
-rw-r--r--usr.bin/xargs/xargs.c803
-rw-r--r--usr.bin/xinstall/Makefile25
-rw-r--r--usr.bin/xinstall/Makefile.depend17
-rw-r--r--usr.bin/xinstall/install.1366
-rw-r--r--usr.bin/xinstall/tests/Makefile3
-rw-r--r--usr.bin/xinstall/tests/Makefile.depend10
-rwxr-xr-xusr.bin/xinstall/tests/install_test.sh560
-rw-r--r--usr.bin/xinstall/xinstall.c1499
-rw-r--r--usr.bin/xo/Makefile24
-rw-r--r--usr.bin/xo/Makefile.depend17
-rw-r--r--usr.bin/xo/tests/Makefile39
-rw-r--r--usr.bin/xo/tests/Makefile.depend10
-rwxr-xr-xusr.bin/xo/tests/functional_test.sh71
-rw-r--r--usr.bin/xohtml/Makefile29
-rwxr-xr-xusr.bin/xohtml/xohtml.sh86
-rw-r--r--usr.bin/xolint/Makefile11
-rw-r--r--usr.bin/xopo/Makefile19
-rw-r--r--usr.bin/xstr/Makefile3
-rw-r--r--usr.bin/xstr/Makefile.depend15
-rw-r--r--usr.bin/xstr/pathnames.h32
-rw-r--r--usr.bin/xstr/xstr.1160
-rw-r--r--usr.bin/xstr/xstr.c480
-rw-r--r--usr.bin/xz/Makefile49
-rw-r--r--usr.bin/xz/Makefile.depend16
-rw-r--r--usr.bin/xzdec/Makefile25
-rw-r--r--usr.bin/xzdec/Makefile.depend16
-rw-r--r--usr.bin/yacc/Makefile22
-rw-r--r--usr.bin/yacc/Makefile.depend15
-rw-r--r--usr.bin/yacc/Makefile.depend.host10
-rw-r--r--usr.bin/yacc/Makefile.depend.options6
-rw-r--r--usr.bin/yacc/config.h113
-rw-r--r--usr.bin/yacc/tests/Makefile375
-rw-r--r--usr.bin/yacc/tests/Makefile.depend10
-rwxr-xr-xusr.bin/yacc/tests/yacc_tests.sh16
-rw-r--r--usr.bin/yes/Makefile3
-rw-r--r--usr.bin/yes/Makefile.depend17
-rw-r--r--usr.bin/yes/yes.152
-rw-r--r--usr.bin/yes/yes.c74
-rw-r--r--usr.bin/ypcat/Makefile6
-rw-r--r--usr.bin/ypcat/Makefile.depend17
-rw-r--r--usr.bin/ypcat/ypcat.172
-rw-r--r--usr.bin/ypcat/ypcat.c141
-rw-r--r--usr.bin/ypmatch/Makefile6
-rw-r--r--usr.bin/ypmatch/Makefile.depend17
-rw-r--r--usr.bin/ypmatch/ypmatch.173
-rw-r--r--usr.bin/ypmatch/ypmatch.c139
-rw-r--r--usr.bin/ypwhich/Makefile12
-rw-r--r--usr.bin/ypwhich/Makefile.depend18
-rw-r--r--usr.bin/ypwhich/ypwhich.1101
-rw-r--r--usr.bin/ypwhich/ypwhich.c276
-rw-r--r--usr.bin/zstd/Makefile32
-rw-r--r--usr.bin/zstd/Makefile.depend16
3270 files changed, 396870 insertions, 0 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
new file mode 100644
index 000000000000..bca7896e5a17
--- /dev/null
+++ b/usr.bin/Makefile
@@ -0,0 +1,284 @@
+.include <src.opts.mk>
+
+SUBDIR= alias \
+ apply \
+ asa \
+ awk \
+ backlight \
+ banner \
+ basename \
+ beep \
+ bintrans \
+ brandelf \
+ bsdcat \
+ bsddialog \
+ bsdiff \
+ bzip2 \
+ bzip2recover \
+ cap_mkdb \
+ chat \
+ chpass \
+ cksum \
+ cmp \
+ col \
+ colrm \
+ column \
+ comm \
+ compress \
+ csplit \
+ ctlstat \
+ cut \
+ diff \
+ dirname \
+ dtc \
+ du \
+ elfctl \
+ elfdump \
+ enigma \
+ env \
+ etdump \
+ expand \
+ false \
+ fetch \
+ find \
+ fmt \
+ fold \
+ fstat \
+ fsync \
+ gcore \
+ gencat \
+ getaddrinfo \
+ getconf \
+ getent \
+ getopt \
+ grep \
+ gzip \
+ head \
+ hexdump \
+ id \
+ ident \
+ ipcrm \
+ ipcs \
+ join \
+ jot \
+ killall \
+ ktrace \
+ ktrdump \
+ lam \
+ ldd \
+ leave \
+ less \
+ lessecho \
+ lesskey \
+ limits \
+ locale \
+ localedef \
+ lock \
+ lockf \
+ logger \
+ login \
+ logins \
+ logname \
+ look \
+ lsvfs \
+ lzmainfo \
+ m4 \
+ mandoc \
+ mdo \
+ mesg \
+ mididump \
+ ministat \
+ mkdep \
+ mkfifo \
+ mkimg \
+ mktemp \
+ mkuzip \
+ mt \
+ ncal \
+ ncurses \
+ netstat \
+ newgrp \
+ nfsstat \
+ nice \
+ nl \
+ nohup \
+ pagesize \
+ passwd \
+ paste \
+ patch \
+ pathchk \
+ perror \
+ posixmqcontrol \
+ posixshmcontrol \
+ pr \
+ printenv \
+ printf \
+ proccontrol \
+ procstat \
+ protect \
+ rctl \
+ renice \
+ resizewin \
+ rev \
+ revoke \
+ rpcinfo \
+ rs \
+ rup \
+ ruptime \
+ rusers \
+ rwall \
+ rwho \
+ script \
+ sdiff \
+ sed \
+ seq \
+ shar \
+ showmount \
+ sockstat \
+ soelim \
+ sort \
+ split \
+ stat \
+ stdbuf \
+ su \
+ systat \
+ tail \
+ tar \
+ tcopy \
+ tee \
+ time \
+ tip \
+ top \
+ touch \
+ tr \
+ true \
+ truncate \
+ tsort \
+ tty \
+ uname \
+ unexpand \
+ uniq \
+ unzip \
+ units \
+ unvis \
+ vis \
+ vmstat \
+ w \
+ wall \
+ wc \
+ wg \
+ what \
+ whereis \
+ which \
+ whois \
+ write \
+ xargs \
+ xinstall \
+ xo \
+ xz \
+ xzdec \
+ yes \
+ zstd
+
+# NB: keep these sorted by MK_* knobs
+
+SUBDIR.${MK_ACCT}+= lastcomm
+SUBDIR.${MK_AT}+= at
+SUBDIR.${MK_BLUETOOTH}+= bluetooth
+SUBDIR.${MK_BSD_CPIO}+= cpio
+SUBDIR.${MK_CALENDAR}+= calendar
+.if ${MK_CLANG} != "no" || ${MK_LLVM_BINUTILS} != "no" || \
+ ${MK_LLD} != "no" || ${MK_LLDB} != "no"
+SUBDIR+= clang
+.endif
+SUBDIR.${MK_DIALOG}+= dpv
+SUBDIR.${MK_EE}+= ee
+SUBDIR.${MK_FILE}+= file
+SUBDIR.${MK_FINGER}+= finger
+SUBDIR.${MK_FTP}+= ftp
+SUBDIR.${MK_GAMES}+= caesar
+SUBDIR.${MK_GAMES}+= factor
+SUBDIR.${MK_GAMES}+= fortune
+SUBDIR.${MK_GAMES}+= grdc
+SUBDIR.${MK_GAMES}+= morse
+SUBDIR.${MK_GAMES}+= number
+SUBDIR.${MK_GAMES}+= pom
+SUBDIR.${MK_GAMES}+= primes
+SUBDIR.${MK_GAMES}+= random
+SUBDIR+= gh-bc
+.if ${MK_GNU_DIFF} == "no"
+SUBDIR+= diff3
+.endif
+SUBDIR.${MK_HESIOD}+= hesinfo
+SUBDIR.${MK_ICONV}+= iconv
+SUBDIR.${MK_ICONV}+= mkcsmapper
+SUBDIR.${MK_ICONV}+= mkesdb
+SUBDIR.${MK_ISCSI}+= iscsictl
+SUBDIR.${MK_KDUMP}+= kdump
+SUBDIR.${MK_KDUMP}+= truss
+SUBDIR.${MK_KERBEROS_SUPPORT}+= compile_et
+SUBDIR.${MK_LDNS_UTILS}+= drill
+SUBDIR.${MK_LDNS_UTILS}+= host
+SUBDIR.${MK_LIB32}+= ldd32
+SUBDIR.${MK_LOCATE}+= locate
+# XXX msgs?
+SUBDIR.${MK_MAIL}+= biff
+SUBDIR.${MK_MAIL}+= from
+SUBDIR.${MK_MAIL}+= mail
+SUBDIR.${MK_MAIL}+= msgs
+SUBDIR.${MK_MAKE}+= bmake
+SUBDIR.${MK_MAN_UTILS}+= man
+SUBDIR.${MK_NETCAT}+= nc
+SUBDIR.${MK_NETLINK}+= genl
+SUBDIR.${MK_NIS}+= ypcat
+SUBDIR.${MK_NIS}+= ypmatch
+SUBDIR.${MK_NIS}+= ypwhich
+SUBDIR.${MK_OPENSSH}+= ssh-copy-id
+SUBDIR.${MK_QUOTAS}+= quota
+SUBDIR.${MK_SENDMAIL}+= vacation
+SUBDIR.${MK_TALK}+= talk
+SUBDIR.${MK_TELNET}+= telnet
+SUBDIR.${MK_TESTS_SUPPORT}+= kyua
+SUBDIR.${MK_TESTS}+= tests
+SUBDIR.${MK_TEXTPROC}+= ul
+SUBDIR.${MK_TFTP}+= tftp
+.if ${MK_LLVM_BINUTILS} == "no"
+# Only build the elftoolchain tools if we aren't using the LLVM ones.
+SUBDIR.${MK_TOOLCHAIN}+= addr2line
+SUBDIR.${MK_TOOLCHAIN}+= ar
+SUBDIR.${MK_TOOLCHAIN}+= nm
+SUBDIR.${MK_TOOLCHAIN}+= objcopy
+SUBDIR.${MK_TOOLCHAIN}+= readelf
+SUBDIR.${MK_TOOLCHAIN}+= size
+SUBDIR+= strings
+.endif
+SUBDIR.${MK_TOOLCHAIN}+= c89
+SUBDIR.${MK_TOOLCHAIN}+= c99
+SUBDIR.${MK_TOOLCHAIN}+= ctags
+.if ${MK_LLVM_CXXFILT} == "no"
+SUBDIR.${MK_TOOLCHAIN}+= cxxfilt
+.endif
+SUBDIR.${MK_TOOLCHAIN}+= file2c
+SUBDIR.${MK_TOOLCHAIN}+= gprof
+SUBDIR.${MK_TOOLCHAIN}+= indent
+SUBDIR.${MK_TOOLCHAIN}+= lex
+SUBDIR.${MK_TOOLCHAIN}+= lorder
+SUBDIR.${MK_TOOLCHAIN}+= mkstr
+SUBDIR.${MK_TOOLCHAIN}+= rpcgen
+SUBDIR.${MK_TOOLCHAIN}+= unifdef
+SUBDIR.${MK_TOOLCHAIN}+= xstr
+SUBDIR.${MK_TOOLCHAIN}+= yacc
+SUBDIR.${MK_VI}+= vi
+SUBDIR.${MK_VT}+= vtfontcvt
+SUBDIR.${MK_USB}+= usbhidaction
+SUBDIR.${MK_USB}+= usbhidctl
+SUBDIR.${MK_UTMPX}+= last
+SUBDIR.${MK_UTMPX}+= users
+SUBDIR.${MK_UTMPX}+= who
+SUBDIR.${MK_OFED}+= ofed
+
+.include <bsd.arch.inc.mk>
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/Makefile.amd64 b/usr.bin/Makefile.amd64
new file mode 100644
index 000000000000..8763d7fe0f2c
--- /dev/null
+++ b/usr.bin/Makefile.amd64
@@ -0,0 +1 @@
+SUBDIR+= smbutil
diff --git a/usr.bin/Makefile.arm b/usr.bin/Makefile.arm
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/Makefile.arm
diff --git a/usr.bin/Makefile.i386 b/usr.bin/Makefile.i386
new file mode 100644
index 000000000000..8763d7fe0f2c
--- /dev/null
+++ b/usr.bin/Makefile.i386
@@ -0,0 +1 @@
+SUBDIR+= smbutil
diff --git a/usr.bin/Makefile.inc b/usr.bin/Makefile.inc
new file mode 100644
index 000000000000..c24c4b1a950f
--- /dev/null
+++ b/usr.bin/Makefile.inc
@@ -0,0 +1 @@
+BINDIR?= /usr/bin
diff --git a/usr.bin/Makefile.powerpc b/usr.bin/Makefile.powerpc
new file mode 100644
index 000000000000..8763d7fe0f2c
--- /dev/null
+++ b/usr.bin/Makefile.powerpc
@@ -0,0 +1 @@
+SUBDIR+= smbutil
diff --git a/usr.bin/addr2line/Makefile b/usr.bin/addr2line/Makefile
new file mode 100644
index 000000000000..652282152269
--- /dev/null
+++ b/usr.bin/addr2line/Makefile
@@ -0,0 +1,16 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+ADDR2LINEDIR= ${ELFTCDIR}/addr2line
+
+.PATH: ${ADDR2LINEDIR}
+
+PROG= addr2line
+
+LIBADD= elftc dwarf elf
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/addr2line/Makefile.depend b/usr.bin/addr2line/Makefile.depend
new file mode 100644
index 000000000000..b8bf644ceaa1
--- /dev/null
+++ b/usr.bin/addr2line/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libdwarf \
+ lib/libelf \
+ lib/libelftc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/alias/Makefile b/usr.bin/alias/Makefile
new file mode 100644
index 000000000000..1098c7b7ef1f
--- /dev/null
+++ b/usr.bin/alias/Makefile
@@ -0,0 +1,19 @@
+SCRIPTS=generic.sh
+SCRIPTSNAME=alias
+
+LINKS= ${BINDIR}/alias ${BINDIR}/bg \
+ ${BINDIR}/alias ${BINDIR}/cd \
+ ${BINDIR}/alias ${BINDIR}/command \
+ ${BINDIR}/alias ${BINDIR}/fc \
+ ${BINDIR}/alias ${BINDIR}/fg \
+ ${BINDIR}/alias ${BINDIR}/getopts \
+ ${BINDIR}/alias ${BINDIR}/hash \
+ ${BINDIR}/alias ${BINDIR}/jobs \
+ ${BINDIR}/alias ${BINDIR}/read \
+ ${BINDIR}/alias ${BINDIR}/type \
+ ${BINDIR}/alias ${BINDIR}/ulimit \
+ ${BINDIR}/alias ${BINDIR}/umask \
+ ${BINDIR}/alias ${BINDIR}/unalias \
+ ${BINDIR}/alias ${BINDIR}/wait
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/alias/Makefile.depend b/usr.bin/alias/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/alias/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/alias/generic.sh b/usr.bin/alias/generic.sh
new file mode 100644
index 000000000000..c07b119b560f
--- /dev/null
+++ b/usr.bin/alias/generic.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# This file is in the public domain.
+builtin ${0##*/} ${1+"$@"}
diff --git a/usr.bin/apply/Makefile b/usr.bin/apply/Makefile
new file mode 100644
index 000000000000..86852d41d279
--- /dev/null
+++ b/usr.bin/apply/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PROG= apply
+
+LIBADD= sbuf
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/apply/Makefile.depend b/usr.bin/apply/Makefile.depend
new file mode 100644
index 000000000000..cde253fc72ce
--- /dev/null
+++ b/usr.bin/apply/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsbuf \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/apply/apply.1 b/usr.bin/apply/apply.1
new file mode 100644
index 000000000000..f1c114d40814
--- /dev/null
+++ b/usr.bin/apply/apply.1
@@ -0,0 +1,137 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd January 28, 2022
+.Dt APPLY 1
+.Os
+.Sh NAME
+.Nm apply
+.Nd apply a command to a set of arguments
+.Sh SYNOPSIS
+.Nm
+.Op Fl a Ar c
+.Op Fl d
+.Op Cm - Ns Ar #
+.Ar command argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility runs the named
+.Ar command
+on each
+argument
+.Ar argument
+in turn.
+.Pp
+Character sequences of the form
+.Dq Li \&%d
+in
+.Ar command ,
+where
+.Sq Li d
+is a digit from 1 to 9, are replaced by the
+.Li d Ns \'th
+following unused
+.Ar argument .
+In this case, the largest digit number of arguments are discarded for
+each execution of
+.Ar command .
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Cm - Ns Ar #
+Normally arguments are taken singly; the optional number
+.Ar #
+specifies the number of arguments to be passed to
+.Ar command .
+If the number is zero,
+.Ar command
+is run, without arguments, once for each
+.Ar argument .
+.Pp
+If any sequences of
+.Dq Li \&%d
+occur in
+.Ar command ,
+the
+.Fl #
+option is ignored.
+.It Fl a Ar c
+The use of the character
+.Sq Li %
+as a magic character may be changed with the
+.Fl a
+option.
+.It Fl d
+Display the commands that would have been executed, but do not actually
+execute them.
+.El
+.Sh ENVIRONMENT
+The following environment variable affects the execution of
+.Nm :
+.Bl -tag -width SHELL
+.It Ev SHELL
+Pathname of shell to use.
+If this variable is not defined, the Bourne shell is used.
+.El
+.Sh FILES
+.Bl -tag -width /bin/sh -compact
+.It Pa /bin/sh
+default shell
+.El
+.Sh EXAMPLES
+.Bl -tag -width apply -compact
+.It Li "apply echo *"
+is similar to
+.Xr ls 1 ;
+.It Li "apply \-2 cmp a1 b1 a2 b2 a3 b3"
+compares the `a' files to the `b' files;
+.It Li "apply \-0 who 1 2 3 4 5"
+runs
+.Xr who 1
+5 times; and
+.It Li "apply \'ln %1 /usr/joe\'" *
+links all files in the current directory to the directory
+.Pa /usr/joe .
+.El
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+.An Rob Pike
+.Sh BUGS
+Shell metacharacters in
+.Ar command
+may have bizarre effects; it is best to enclose complicated
+commands in single quotes
+.Pq '' .
+.Pp
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/apply/apply.c b/usr.bin/apply/apply.c
new file mode 100644
index 000000000000..727351c8ff87
--- /dev/null
+++ b/usr.bin/apply/apply.c
@@ -0,0 +1,247 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * 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/sbuf.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ISMAGICNO(p) \
+ (p)[0] == magic && isdigit((unsigned char)(p)[1]) && (p)[1] != '0'
+
+static int exec_shell(const char *, const char *, const char *);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct sbuf *cmdbuf;
+ long arg_max;
+ int ch, debug, i, magic, n, nargs, rval;
+ size_t cmdsize;
+ char buf[4];
+ char *cmd, *name, *p, *shell, *slashp, *tmpshell;
+
+ debug = 0;
+ magic = '%'; /* Default magic char is `%'. */
+ nargs = -1;
+ while ((ch = getopt(argc, argv, "a:d0123456789")) != -1)
+ switch (ch) {
+ case 'a':
+ if (optarg[0] == '\0' || optarg[1] != '\0')
+ errx(1,
+ "illegal magic character specification");
+ magic = optarg[0];
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (nargs != -1)
+ errx(1,
+ "only one -# argument may be specified");
+ nargs = optopt - '0';
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ usage();
+
+ /*
+ * The command to run is argv[0], and the args are argv[1..].
+ * Look for %digit references in the command, remembering the
+ * largest one.
+ */
+ for (n = 0, p = argv[0]; *p != '\0'; ++p)
+ if (ISMAGICNO(p)) {
+ ++p;
+ if (p[0] - '0' > n)
+ n = p[0] - '0';
+ }
+
+ /*
+ * Figure out the shell and name arguments to pass to execl()
+ * in exec_shell(). Always malloc() shell and just set name
+ * to point at the last part of shell if there are any backslashes,
+ * otherwise just set it to point at the space malloc()'d. If
+ * SHELL environment variable exists, replace contents of
+ * shell with it.
+ */
+ shell = name = NULL;
+ tmpshell = getenv("SHELL");
+ shell = (tmpshell != NULL) ? strdup(tmpshell) : strdup(_PATH_BSHELL);
+ if (shell == NULL)
+ err(1, "strdup() failed");
+ slashp = strrchr(shell, '/');
+ name = (slashp != NULL) ? slashp + 1 : shell;
+
+ /*
+ * If there were any %digit references, then use those, otherwise
+ * build a new command string with sufficient %digit references at
+ * the end to consume (nargs) arguments each time round the loop.
+ * Allocate enough space to hold the maximum command. Save the
+ * size to pass to snprintf().
+ */
+ if (n == 0) {
+ cmdsize = strlen(argv[0]) + 9 * (sizeof(" %1") - 1) + 1;
+ if ((cmd = malloc(cmdsize)) == NULL)
+ err(1, NULL);
+ strlcpy(cmd, argv[0], cmdsize);
+
+ /* If nargs not set, default to a single argument. */
+ if (nargs == -1)
+ nargs = 1;
+
+ for (i = 1; i <= nargs; i++) {
+ snprintf(buf, sizeof(buf), " %c%d", magic, i);
+ strlcat(cmd, buf, cmdsize);
+ }
+
+ /*
+ * If nargs set to the special value 0, eat a single
+ * argument for each command execution.
+ */
+ if (nargs == 0)
+ nargs = 1;
+ } else {
+ if ((cmd = strdup(argv[0])) == NULL)
+ err(1, NULL);
+ nargs = n;
+ }
+
+ cmdbuf = sbuf_new(NULL, NULL, 1024, SBUF_AUTOEXTEND);
+ if (cmdbuf == NULL)
+ err(1, NULL);
+
+ arg_max = sysconf(_SC_ARG_MAX);
+
+ /*
+ * (argc) and (argv) are still offset by one to make it simpler to
+ * expand %digit references. At the end of the loop check for (argc)
+ * equals 1 means that all the (argv) has been consumed.
+ */
+ for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
+ sbuf_clear(cmdbuf);
+ if (sbuf_cat(cmdbuf, "exec ") != 0)
+ err(1, "sbuf");
+ /* Expand command argv references. */
+ for (p = cmd; *p != '\0'; ++p) {
+ if (ISMAGICNO(p)) {
+ if (sbuf_cat(cmdbuf, argv[*++p - '0']) != 0)
+ err(1, "sbuf");
+ } else {
+ if (sbuf_putc(cmdbuf, *p) != 0)
+ err(1, "sbuf");
+ }
+ if (sbuf_len(cmdbuf) > arg_max)
+ errc(1, E2BIG, NULL);
+ }
+
+ /* Terminate the command string. */
+ if (sbuf_finish(cmdbuf) != 0)
+ err(1, "sbuf");
+
+ /* Run the command. */
+ if (debug)
+ (void)printf("%s\n", sbuf_data(cmdbuf));
+ else
+ if (exec_shell(sbuf_data(cmdbuf), shell, name))
+ rval = 1;
+ }
+
+ if (argc != 1)
+ errx(1, "expecting additional argument%s after \"%s\"",
+ (nargs - argc) ? "s" : "", argv[argc - 1]);
+ free(cmd);
+ sbuf_delete(cmdbuf);
+ free(shell);
+ exit(rval);
+}
+
+/*
+ * exec_shell --
+ * Execute a shell command using passed use_shell and use_name
+ * arguments.
+ */
+static int
+exec_shell(const char *command, const char *use_shell, const char *use_name)
+{
+ pid_t pid;
+ int omask, pstat;
+ sig_t intsave, quitsave;
+
+ if (!command) /* just checking... */
+ return(1);
+
+ omask = sigblock(sigmask(SIGCHLD));
+ switch(pid = vfork()) {
+ case -1: /* error */
+ err(1, "vfork");
+ case 0: /* child */
+ (void)sigsetmask(omask);
+ execl(use_shell, use_name, "-c", command, (char *)NULL);
+ warn("%s", use_shell);
+ _exit(1);
+ }
+ intsave = signal(SIGINT, SIG_IGN);
+ quitsave = signal(SIGQUIT, SIG_IGN);
+ pid = waitpid(pid, &pstat, 0);
+ (void)sigsetmask(omask);
+ (void)signal(SIGINT, intsave);
+ (void)signal(SIGQUIT, quitsave);
+ return(pid == -1 ? -1 : pstat);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: apply [-a magic] [-d] [-0123456789] command arguments ...\n");
+ exit(1);
+}
diff --git a/usr.bin/apply/tests/Makefile b/usr.bin/apply/tests/Makefile
new file mode 100644
index 000000000000..249b76b63fce
--- /dev/null
+++ b/usr.bin/apply/tests/Makefile
@@ -0,0 +1,11 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.00.in
+${PACKAGE}FILES+= regress.00.out
+${PACKAGE}FILES+= regress.01.out
+${PACKAGE}FILES+= regress.01.sh
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/apply/tests/Makefile.depend b/usr.bin/apply/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/apply/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/apply/tests/legacy_test.sh b/usr.bin/apply/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/apply/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/apply/tests/regress.00.in b/usr.bin/apply/tests/regress.00.in
new file mode 100644
index 000000000000..8282be782435
--- /dev/null
+++ b/usr.bin/apply/tests/regress.00.in
@@ -0,0 +1 @@
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
diff --git a/usr.bin/apply/tests/regress.00.out b/usr.bin/apply/tests/regress.00.out
new file mode 100644
index 000000000000..c725cb2fa98c
--- /dev/null
+++ b/usr.bin/apply/tests/regress.00.out
@@ -0,0 +1 @@
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
diff --git a/usr.bin/apply/tests/regress.01.out b/usr.bin/apply/tests/regress.01.out
new file mode 100644
index 000000000000..bcf5ab29339a
--- /dev/null
+++ b/usr.bin/apply/tests/regress.01.out
@@ -0,0 +1 @@
+apply: Argument list too long
diff --git a/usr.bin/apply/tests/regress.01.sh b/usr.bin/apply/tests/regress.01.sh
new file mode 100644
index 000000000000..a48d8c7a571d
--- /dev/null
+++ b/usr.bin/apply/tests/regress.01.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+SHELL=/bin/sh; export SHELL
+
+ARG_MAX=$(getconf ARG_MAX)
+ARG_MAX_HALF=$((ARG_MAX / 2))
+
+apply 'echo %1 %1 %1' $(jot $ARG_MAX_HALF 1 1 | tr -d '\n') 2>&1
+
+if [ $? -eq 0 ]; then
+ return 1
+else
+ return 0
+fi
diff --git a/usr.bin/apply/tests/regress.sh b/usr.bin/apply/tests/regress.sh
new file mode 100644
index 000000000000..9b89a3cbd1d0
--- /dev/null
+++ b/usr.bin/apply/tests/regress.sh
@@ -0,0 +1,9 @@
+
+echo 1..2
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`00', `apply "echo %1 %1 %1 %1" $(cat ${SRCDIR}/regress.00.in)')
+REGRESSION_TEST(`01', `sh ${SRCDIR}/regress.01.sh')
+
+REGRESSION_END()
diff --git a/usr.bin/ar/Makefile b/usr.bin/ar/Makefile
new file mode 100644
index 000000000000..b926e942795e
--- /dev/null
+++ b/usr.bin/ar/Makefile
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+PROG= ar
+SRCS= ar.c acplex.l acpyacc.y read.c util.c write.c y.tab.h
+
+LIBADD= archive elf
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+CFLAGS+=-I. -I${.CURDIR}
+
+LINKS= ${BINDIR}/ar ${BINDIR}/ranlib
+MLINKS= ar.1 ranlib.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ar/Makefile.depend b/usr.bin/ar/Makefile.depend
new file mode 100644
index 000000000000..a315628f2966
--- /dev/null
+++ b/usr.bin/ar/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libelf \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ar/acplex.l b/usr.bin/ar/acplex.l
new file mode 100644
index 000000000000..a294de1adcfd
--- /dev/null
+++ b/usr.bin/ar/acplex.l
@@ -0,0 +1,81 @@
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2008 Kai Wang
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "y.tab.h"
+
+int lineno = 1;
+
+int yylex(void);
+
+#define YY_DECL int yylex(void)
+
+%}
+
+%option nounput
+%option noinput
+%option noyywrap
+
+%%
+
+ADDLIB|addlib { return (ADDLIB); }
+ADDMOD|addmod { return (ADDMOD); }
+CLEAR|clear { return (CLEAR); }
+CREATE|create { return (CREATE); }
+DELETE|delete { return (DELETE); }
+DIRECTORY|directory { return (DIRECTORY); }
+END|end { return (END); }
+EXTRACT|extract { return (EXTRACT); }
+LIST|list { return (LIST); }
+OPEN|open { return (OPEN); }
+REPLACE|replace { return (REPLACE); }
+VERBOSE|verbose { return (VERBOSE); }
+SAVE|save { return (SAVE); }
+"(" { return (LP); }
+")" { return (RP); }
+"," { return (COMMA); }
+
+[-_A-Za-z0-9/:$.\\]+ {
+ yylval.str = strdup(yytext);
+ if (yylval.str == NULL)
+ errc(EXIT_FAILURE, errno, "strdup failed");
+ return (FNAME);
+}
+
+[ \t] /* whitespace */
+"*".* /* comment */
+";".* /* comment */
+"+\n" { lineno++; /* '+' is line continuation char */ }
+"\n" { lineno++; return (EOL); }
diff --git a/usr.bin/ar/acpyacc.y b/usr.bin/ar/acpyacc.y
new file mode 100644
index 000000000000..4bfc5ab8424d
--- /dev/null
+++ b/usr.bin/ar/acpyacc.y
@@ -0,0 +1,655 @@
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2008 Kai Wang
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ar.h"
+
+#define TEMPLATE "arscp.XXXXXXXX"
+
+struct list {
+ char *str;
+ struct list *next;
+};
+
+
+extern int yylex(void);
+
+static void yyerror(const char *);
+static void arscp_addlib(char *archive, struct list *list);
+static void arscp_addmod(struct list *list);
+static void arscp_clear(void);
+static int arscp_copy(int ifd, int ofd);
+static void arscp_create(char *in, char *out);
+static void arscp_delete(struct list *list);
+static void arscp_dir(char *archive, struct list *list, char *rlt);
+static void arscp_end(int eval);
+static void arscp_extract(struct list *list);
+static void arscp_free_argv(void);
+static void arscp_free_mlist(struct list *list);
+static void arscp_list(void);
+static struct list *arscp_mlist(struct list *list, char *str);
+static void arscp_mlist2argv(struct list *list);
+static int arscp_mlist_len(struct list *list);
+static void arscp_open(char *fname);
+static void arscp_prompt(void);
+static void arscp_replace(struct list *list);
+static void arscp_save(void);
+static int arscp_target_exist(void);
+
+extern int lineno;
+
+static struct bsdar *bsdar;
+static char *target;
+static char *tmpac;
+static int interactive;
+static int verbose;
+
+%}
+
+%token ADDLIB
+%token ADDMOD
+%token CLEAR
+%token CREATE
+%token DELETE
+%token DIRECTORY
+%token END
+%token EXTRACT
+%token LIST
+%token OPEN
+%token REPLACE
+%token VERBOSE
+%token SAVE
+%token LP
+%token RP
+%token COMMA
+%token EOL
+%token <str> FNAME
+%type <list> mod_list
+
+%union {
+ char *str;
+ struct list *list;
+}
+
+%%
+
+begin
+ : { arscp_prompt(); } ar_script
+ ;
+
+ar_script
+ : cmd_list
+ |
+ ;
+
+mod_list
+ : FNAME { $$ = arscp_mlist(NULL, $1); }
+ | mod_list separator FNAME { $$ = arscp_mlist($1, $3); }
+ ;
+
+separator
+ : COMMA
+ |
+ ;
+
+cmd_list
+ : rawcmd
+ | cmd_list rawcmd
+ ;
+
+rawcmd
+ : cmd EOL { arscp_prompt(); }
+ ;
+
+cmd
+ : addlib_cmd
+ | addmod_cmd
+ | clear_cmd
+ | create_cmd
+ | delete_cmd
+ | directory_cmd
+ | end_cmd
+ | extract_cmd
+ | list_cmd
+ | open_cmd
+ | replace_cmd
+ | verbose_cmd
+ | save_cmd
+ | invalid_cmd
+ | empty_cmd
+ | error
+ ;
+
+addlib_cmd
+ : ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); }
+ | ADDLIB FNAME { arscp_addlib($2, NULL); }
+ ;
+
+addmod_cmd
+ : ADDMOD mod_list { arscp_addmod($2); }
+ ;
+
+clear_cmd
+ : CLEAR { arscp_clear(); }
+ ;
+
+create_cmd
+ : CREATE FNAME { arscp_create(NULL, $2); }
+ ;
+
+delete_cmd
+ : DELETE mod_list { arscp_delete($2); }
+ ;
+
+directory_cmd
+ : DIRECTORY FNAME { arscp_dir($2, NULL, NULL); }
+ | DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); }
+ | DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); }
+ ;
+
+end_cmd
+ : END { arscp_end(EXIT_SUCCESS); }
+ ;
+
+extract_cmd
+ : EXTRACT mod_list { arscp_extract($2); }
+ ;
+
+list_cmd
+ : LIST { arscp_list(); }
+ ;
+
+open_cmd
+ : OPEN FNAME { arscp_open($2); }
+ ;
+
+replace_cmd
+ : REPLACE mod_list { arscp_replace($2); }
+ ;
+
+save_cmd
+ : SAVE { arscp_save(); }
+ ;
+
+verbose_cmd
+ : VERBOSE { verbose = !verbose; }
+ ;
+
+empty_cmd
+ :
+ ;
+
+invalid_cmd
+ : FNAME { yyerror(NULL); }
+ ;
+
+%%
+
+/* ARGSUSED */
+static void
+yyerror(const char *s)
+{
+
+ (void) s;
+ printf("Syntax error in archive script, line %d\n", lineno);
+}
+
+/*
+ * arscp_open first open an archive and check its validity. If the archive
+ * format is valid, it calls arscp_create to create a temporary copy of
+ * the archive.
+ */
+static void
+arscp_open(char *fname)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
+ if ((r = archive_read_next_header(a, &entry)))
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ AC(archive_read_close(a));
+ AC(archive_read_free(a));
+ if (r != ARCHIVE_OK)
+ return;
+ arscp_create(fname, fname);
+}
+
+/*
+ * Create archive. in != NULL indicate it's a OPEN cmd, and resulting
+ * archive is based on modification of an existing one. If in == NULL,
+ * we are in CREATE cmd and a new empty archive will be created.
+ */
+static void
+arscp_create(char *in, char *out)
+{
+ struct archive *a;
+ int ifd, ofd;
+
+ /* Delete previously created temporary archive, if any. */
+ if (tmpac) {
+ if (unlink(tmpac) < 0)
+ bsdar_errc(bsdar, errno, "unlink failed");
+ free(tmpac);
+ }
+
+ tmpac = strdup(TEMPLATE);
+ if (tmpac == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ if ((ofd = mkstemp(tmpac)) < 0)
+ bsdar_errc(bsdar, errno, "mkstemp failed");
+
+ if (in) {
+ /*
+ * Command OPEN creates a temporary copy of the
+ * input archive.
+ */
+ if ((ifd = open(in, O_RDONLY)) < 0) {
+ bsdar_warnc(bsdar, errno, "open failed");
+ return;
+ }
+ if (arscp_copy(ifd, ofd)) {
+ bsdar_warnc(bsdar, 0, "arscp_copy failed");
+ return;
+ }
+ close(ifd);
+ close(ofd);
+ } else {
+ /*
+ * Command CREATE creates an "empty" archive.
+ * (archive with only global header)
+ */
+ if ((a = archive_write_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_write_new failed");
+ archive_write_set_format_ar_svr4(a);
+ AC(archive_write_open_fd(a, ofd));
+ AC(archive_write_close(a));
+ AC(archive_write_free(a));
+ }
+
+ /* Override previous target, if any. */
+ if (target)
+ free(target);
+
+ target = out;
+ bsdar->filename = tmpac;
+}
+
+/* A file copying implementation using mmap. */
+static int
+arscp_copy(int ifd, int ofd)
+{
+ struct stat sb;
+ char *buf, *p;
+ ssize_t w;
+ size_t bytes;
+
+ if (fstat(ifd, &sb) < 0) {
+ bsdar_warnc(bsdar, errno, "fstate failed");
+ return (1);
+ }
+ if ((p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd,
+ (off_t)0)) == MAP_FAILED) {
+ bsdar_warnc(bsdar, errno, "mmap failed");
+ return (1);
+ }
+ for (buf = p, bytes = sb.st_size; bytes > 0; bytes -= w) {
+ w = write(ofd, buf, bytes);
+ if (w <= 0) {
+ bsdar_warnc(bsdar, errno, "write failed");
+ break;
+ }
+ }
+ if (munmap(p, sb.st_size) < 0)
+ bsdar_errc(bsdar, errno, "munmap failed");
+ if (bytes > 0)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Add all modules of archive to current archive, if list != NULL,
+ * only those modules specified in 'list' will be added.
+ */
+static void
+arscp_addlib(char *archive, struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ bsdar->addlib = archive;
+ ar_write_archive(bsdar, 'A');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/* Add modules into current archive. */
+static void
+arscp_addmod(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'q');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/* Delete modules from current archive. */
+static void
+arscp_delete(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'd');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/* Extract modules from current archive. */
+static void
+arscp_extract(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_read_archive(bsdar, 'x', stdout);
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/* List modules of archive. (Simple Mode) */
+static void
+arscp_list(void)
+{
+
+ if (!arscp_target_exist())
+ return;
+ bsdar->argc = 0;
+ bsdar->argv = NULL;
+ /* Always verbose. */
+ bsdar->options |= AR_V;
+ ar_read_archive(bsdar, 't', stdout);
+ bsdar->options &= ~AR_V;
+}
+
+/* List modules of archive. (Advance Mode) */
+static void
+arscp_dir(char *archive, struct list *list, char *rlt)
+{
+ FILE *out;
+
+ /* If rlt != NULL, redirect output to it */
+ out = stdout;
+ if (rlt) {
+ if ((out = fopen(rlt, "w")) == NULL)
+ bsdar_errc(bsdar, errno, "fopen %s failed", rlt);
+ }
+
+ bsdar->filename = archive;
+ if (list)
+ arscp_mlist2argv(list);
+ else {
+ bsdar->argc = 0;
+ bsdar->argv = NULL;
+ }
+ if (verbose)
+ bsdar->options |= AR_V;
+ ar_read_archive(bsdar, 't', out);
+ bsdar->options &= ~AR_V;
+
+ if (rlt) {
+ if (fclose(out) == EOF)
+ bsdar_errc(bsdar, errno, "fclose %s failed", rlt);
+ free(rlt);
+ }
+ free(archive);
+ bsdar->filename = tmpac;
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+
+/* Replace modules of current archive. */
+static void
+arscp_replace(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'r');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/* Rename the temporary archive to the target archive. */
+static void
+arscp_save(void)
+{
+ mode_t mask;
+
+ if (target) {
+ if (rename(tmpac, target) < 0)
+ bsdar_errc(bsdar, errno, "rename failed");
+ /*
+ * mkstemp creates temp files with mode 0600, here we
+ * set target archive mode per process umask.
+ */
+ mask = umask(0);
+ umask(mask);
+ if (chmod(target, 0666 & ~mask) < 0)
+ bsdar_errc(bsdar, errno, "chmod failed");
+ free(tmpac);
+ free(target);
+ tmpac = NULL;
+ target= NULL;
+ bsdar->filename = NULL;
+ } else
+ bsdar_warnc(bsdar, 0, "no open output archive");
+}
+
+/*
+ * Discard all the contents of current archive. This is achieved by
+ * invoking CREATE cmd on current archive.
+ */
+static void
+arscp_clear(void)
+{
+ char *new_target;
+
+ if (target) {
+ new_target = strdup(target);
+ if (new_target == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ arscp_create(NULL, new_target);
+ }
+}
+
+/*
+ * Quit ar(1). Note that END cmd will not SAVE current archive
+ * before exit.
+ */
+static void
+arscp_end(int eval)
+{
+
+ if (target)
+ free(target);
+ if (tmpac) {
+ if (unlink(tmpac) == -1)
+ bsdar_errc(bsdar, errno, "unlink %s failed",
+ tmpac);
+ free(tmpac);
+ }
+
+ exit(eval);
+}
+
+/*
+ * Check if target specified, i.e, whether OPEN or CREATE has been
+ * issued by user.
+ */
+static int
+arscp_target_exist(void)
+{
+
+ if (target)
+ return (1);
+
+ bsdar_warnc(bsdar, 0, "no open output archive");
+ return (0);
+}
+
+/* Construct module list. */
+static struct list *
+arscp_mlist(struct list *list, char *str)
+{
+ struct list *l;
+
+ l = malloc(sizeof(*l));
+ if (l == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ l->str = str;
+ l->next = list;
+
+ return (l);
+}
+
+/* Calculate the length of a mlist. */
+static int
+arscp_mlist_len(struct list *list)
+{
+ int len;
+
+ for(len = 0; list; list = list->next)
+ len++;
+
+ return (len);
+}
+
+/* Free the space allocated for mod_list. */
+static void
+arscp_free_mlist(struct list *list)
+{
+ struct list *l;
+
+ /* Note that list->str was freed in arscp_free_argv. */
+ for(; list; list = l) {
+ l = list->next;
+ free(list);
+ }
+}
+
+/* Convert mlist to argv array. */
+static void
+arscp_mlist2argv(struct list *list)
+{
+ char **argv;
+ int i, n;
+
+ n = arscp_mlist_len(list);
+ argv = malloc(n * sizeof(*argv));
+ if (argv == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+
+ /* Note that module names are stored in reverse order in mlist. */
+ for(i = n - 1; i >= 0; i--, list = list->next) {
+ if (list == NULL)
+ bsdar_errc(bsdar, errno, "invalid mlist");
+ argv[i] = list->str;
+ }
+
+ bsdar->argc = n;
+ bsdar->argv = argv;
+}
+
+/* Free space allocated for argv array and its elements. */
+static void
+arscp_free_argv(void)
+{
+ int i;
+
+ for(i = 0; i < bsdar->argc; i++)
+ free(bsdar->argv[i]);
+
+ free(bsdar->argv);
+}
+
+/* Show a prompt if we are in interactive mode */
+static void
+arscp_prompt(void)
+{
+
+ if (interactive) {
+ printf("AR >");
+ fflush(stdout);
+ }
+}
+
+/* Main function for ar script mode. */
+void
+ar_mode_script(struct bsdar *ar)
+{
+
+ bsdar = ar;
+ interactive = isatty(fileno(stdin));
+ while(yyparse()) {
+ if (!interactive)
+ arscp_end(EXIT_FAILURE);
+ }
+
+ /* Script ends without END */
+ arscp_end(EXIT_SUCCESS);
+}
diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1
new file mode 100644
index 000000000000..ae5f0f170bfc
--- /dev/null
+++ b/usr.bin/ar/ar.1
@@ -0,0 +1,609 @@
+.\" Copyright (c) 2007 Joseph Koshy. 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.
+.\"
+.\" This software is provided by Joseph Koshy ``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 Joseph Koshy 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 January 3, 2022
+.Dt AR 1
+.Os
+.Sh NAME
+.Nm ar ,
+.Nm ranlib
+.Nd manage archives
+.Sh SYNOPSIS
+.Nm
+.Fl d
+.Op Fl T
+.Op Fl f
+.Op Fl j
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl m
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl f
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl p
+.Op Fl T
+.Op Fl f
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl q
+.Op Fl T
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl s | Fl S
+.Op Fl U
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl r
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl u
+.Op Fl U
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl s
+.Op Fl j
+.Op Fl z
+.Ar archive
+.Nm
+.Fl t
+.Op Fl f
+.Op Fl T
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl x
+.Op Fl C
+.Op Fl T
+.Op Fl f
+.Op Fl o
+.Op Fl u
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl M
+.Nm ranlib
+.Op Fl D
+.Op Fl U
+.Ar archive ...
+.Sh DESCRIPTION
+The
+.Nm
+utility creates and maintains groups of files combined into an
+archive.
+Once an archive has been created, new files can be added to it, and
+existing files can be extracted, deleted or replaced.
+.Pp
+Files are named in the archive by their last file name component,
+so if a file referenced by a path containing a
+.Dq /
+is archived, it will be named by the last component of the path.
+Similarly when matching paths listed on the command line against
+file names stored in the archive, only the last component of the
+path will be compared.
+.Pp
+The normal use of
+.Nm
+is for the creation and maintenance of libraries suitable for use
+with the link editor
+.Xr ld 1 ,
+although it is not restricted to this purpose.
+The
+.Nm
+utility can create and manage an archive symbol table (see
+.Xr ar 5 )
+used to speed up link editing operations.
+If a symbol table is present in an archive, it will be
+kept up-to-date by subsequent operations on the archive.
+.Pp
+The
+.Nm ranlib
+utility is used to add an archive symbol table
+to an existing archive.
+.Sh OPTIONS
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl a Ar member-after
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to after the archive member named by argument
+.Ar member-after .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added after the archive member named by argument
+.Ar member-after .
+.It Fl b Ar member-before
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to before the archive member named by argument
+.Ar member-before .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added before the archive member named by argument
+.Ar member-before .
+.It Fl c
+Suppress the informational message printed when a new archive is
+created using the
+.Fl r
+and
+.Fl q
+options.
+.It Fl C
+Prevent extracted files from replacing like-named files
+in the file system.
+.It Fl d
+Delete the members named by arguments
+.Ar
+from the archive specified by argument
+.Ar archive .
+The archive's symbol table, if present, is updated to reflect
+the new contents of the archive.
+.It Fl D
+When used in combination with the
+.Fl r
+or
+.Fl q
+option,
+with the
+.Fl s
+option without other options, or when invoked as
+.Nm ranlib ,
+insert 0's instead of the real mtime, uid and gid values
+and 0644 instead of file mode from the members named by arguments
+.Ar .
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
+This option is enabled by default.
+If multiple
+.Fl D
+and
+.Fl U
+options are specified on the command line, the final one takes precedence.
+.It Fl f
+Use only the first fifteen characters of the archive member name or
+command line file name argument when naming archive members.
+.It Fl i Ar member-before
+Synonymous with option
+.Fl b .
+.It Fl j
+This option is accepted but ignored.
+.It Fl l
+This option is accepted for compatibility with GNU
+.Xr ar 1 ,
+but is ignored.
+.It Fl m
+Move archive members specified by arguments
+.Ar
+within the archive.
+If a position has been specified by one of the
+.Fl a ,
+.Fl b
+or
+.Fl i
+options, the members are moved to before or after the specified
+position.
+If no position has been specified, the specified members are moved
+to the end of the archive.
+If the archive has a symbol table, it is updated to reflect the
+new contents of the archive.
+.It Fl M
+Read and execute MRI librarian commands from standard input.
+The commands understood by the
+.Nm
+utility are described in the section
+.Sx "MRI Librarian Commands" .
+.It Fl o
+Preserve the original modification times of members when extracting
+them.
+.It Fl p
+Write the contents of the specified archive members named by
+arguments
+.Ar
+to standard output.
+If no members were specified, the contents of all the files in the
+archive are written in the order they appear in the archive.
+.It Fl q
+Append the files specified by arguments
+.Ar
+to the archive specified by argument
+.Ar archive
+without checking if the files already exist in the archive.
+The archive symbol table will be updated as needed.
+If the file specified by the argument
+.Ar archive
+does not already exist, a new archive will be created.
+.It Fl r
+Replace (add) the files specified by arguments
+.Ar
+in the archive specified by argument
+.Ar archive ,
+creating the archive if necessary.
+Replacing existing members will not change the order of members within
+the archive.
+If a file named in arguments
+.Ar
+does not exist, existing members in the archive that match that
+name are not changed.
+New files are added to the end of the archive unless one of the
+positioning options
+.Fl a ,
+.Fl b
+or
+.Fl i
+is specified.
+The archive symbol table, if it exists, is updated to reflect the
+new state of the archive.
+.It Fl s
+Add an archive symbol table (see
+.Xr ar 5 )
+to the archive specified by argument
+.Ar archive .
+Invoking
+.Nm
+with the
+.Fl s
+option alone is equivalent to invoking
+.Nm ranlib .
+.It Fl S
+Do not generate an archive symbol table.
+.It Fl t
+List the files specified by arguments
+.Ar
+in the order in which they appear in the archive, one per line.
+If no files are specified, all files in the archive are listed.
+.It Fl T
+This option is accepted but ignored.
+In other implementations of
+.Nm ,
+.Fl T
+creates a "thin" archive.
+.It Fl u
+Conditionally update the archive or extract members.
+When used with the
+.Fl r
+option, files named by arguments
+.Ar
+will be replaced in the archive if they are newer than their
+archived versions.
+When used with the
+.Fl x
+option, the members specified by arguments
+.Ar
+will be extracted only if they are newer than the corresponding
+files in the file system.
+.It Fl U
+When used in combination with the
+.Fl r
+or
+.Fl q
+option, insert the real mtime, uid and gid, and file mode values
+from the members named by arguments
+.Ar .
+If multiple
+.Fl D
+and
+.Fl U
+options are specified on the command line, the final one takes precedence.
+.It Fl v
+Provide verbose output.
+When used with the
+.Fl d ,
+.Fl m ,
+.Fl q
+or
+.Fl x
+options,
+.Nm
+gives a file-by-file description of the archive modification being
+performed, which consists of three white-space separated fields:
+the option letter, a dash
+.Dq "-" ,
+and the file name.
+When used with the
+.Fl r
+option,
+.Nm
+displays the description as above, but the initial letter is an
+.Dq a
+if the file is added to the archive, or an
+.Dq r
+if the file replaces a file already in the archive.
+When used with the
+.Fl p
+option, the name of the file enclosed in
+.Dq <
+and
+.Dq >
+characters is written to standard output preceded by a single newline
+character and followed by two newline characters.
+The contents of the named file follow the file name.
+When used with the
+.Fl t
+option,
+.Nm
+displays eight whitespace separated fields:
+the file permissions as displayed by
+.Xr strmode 3 ,
+decimal user and group IDs separated by a slash (
+.Dq / Ns ) ,
+the file size in bytes, the file modification time in
+.Xr strftime 3
+format
+.Dq "%b %e %H:%M %Y" ,
+and the name of the file.
+.It Fl V
+Print a version string and exit.
+.It Fl x
+Extract archive members specified by arguments
+.Ar
+into the current directory.
+If no members have been specified, extract all members of the archive.
+If the file corresponding to an extracted member does not exist it
+will be created.
+If the file corresponding to an extracted member does exist, its owner
+and group will not be changed while its contents will be overwritten
+and its permissions will set to that entered in the archive.
+The file's access and modification time would be that of the time
+of extraction unless the
+.Fl o
+option was specified.
+.It Fl z
+This option is accepted but ignored.
+.El
+.Ss "MRI Librarian Commands"
+If the
+.Fl M
+option is specified, the
+.Nm
+utility will read and execute commands from its standard input.
+If standard input is a terminal, the
+.Nm
+utility will display the prompt
+.Dq Li "AR >"
+before reading a line, and will continue operation even if errors are
+encountered.
+If standard input is not a terminal, the
+.Nm
+utility will not display a prompt and will terminate execution on
+encountering an error.
+.Pp
+Each input line contains a single command.
+Words in an input line are separated by whitespace characters.
+The first word of the line is the command, the remaining words are
+the arguments to the command.
+The command word may be specified in either case.
+Arguments may be separated by commas or blanks.
+.Pp
+Empty lines are allowed and are ignored.
+Long lines are continued by ending them with the
+.Dq Li +
+character.
+.Pp
+The
+.Dq Li *
+and
+.Dq Li "\&;"
+characters start a comment.
+Comments extend till the end of the line.
+.Pp
+When executing an MRI librarian script the
+.Nm
+utility works on a temporary copy of an archive.
+Changes to the copy are made permanent using the
+.Ic save
+command.
+.Pp
+Commands understood by the
+.Nm
+utility are:
+.Bl -tag -width indent
+.It Ic addlib Ar archive | Ic addlib Ar archive Pq Ar member Oo Li , Ar member Oc Ns ...
+Add the contents of the archive named by argument
+.Ar archive
+to the current archive.
+If specific members are named using the arguments
+.Ar member ,
+then those members are added to the current archive.
+If no members are specified, the entire contents of the archive
+are added to the current archive.
+.It Ic addmod Ar member Oo Li , Ar member Oc Ns ...
+Add the files named by arguments
+.Ar member
+to the current archive.
+.It Ic clear
+Discard all the contents of the current archive.
+.It Ic create Ar archive
+Create a new archive named by the argument
+.Ar archive ,
+and makes it the current archive.
+If the named archive already exists, it will be overwritten
+when the
+.Ic save
+command is issued.
+.It Ic delete Ar module Oo Li , Ar member Oc Ns ...
+Delete the modules named by the arguments
+.Ar member
+from the current archive.
+.It Ic directory Ar archive Po Ar member Oo Li , Ar member Oc Ns ... Pc Op Ar outputfile
+List each named module in the archive.
+The format of the output depends on the verbosity setting set using
+the
+.Ic verbose
+command.
+Output is sent to standard output, or to the file specified by
+argument
+.Ar outputfile .
+.It Ic end
+Exit successfully from the
+.Nm
+utility.
+Any unsaved changes to the current archive will be discarded.
+.It Ic extract Ar member Oo Li , Ar member Oc Ns ...
+Extract the members named by the arguments
+.Ar member
+from the current archive.
+.It Ic list
+Display the contents of the current archive in verbose style.
+.It Ic open Ar archive
+Open the archive named by argument
+.Ar archive
+and make it the current archive.
+.It Ic replace Ar member Oo Li , Ar member Oc Ns ...
+Replace named members in the current archive with the files specified
+by arguments
+.Ar member .
+The files must be present in the current directory and the named
+modules must already exist in the current archive.
+.It Ic save
+Commit all changes to the current archive.
+.It Ic verbose
+Toggle the verbosity of the
+.Ic directory
+command.
+.El
+.Sh EXAMPLES
+To create a new archive
+.Pa ex.a
+containing three files
+.Pa ex1.o ,
+.Pa ex2.o
+and
+.Pa ex3.o ,
+use:
+.Dl "ar -rc ex.a ex1.o ex2.o ex3.o"
+.Pp
+To add an archive symbol table to an existing archive
+.Pa ex.a ,
+use:
+.Dl "ar -s ex.a"
+.Pp
+To delete file
+.Pa ex1.o
+from archive
+.Pa ex.a ,
+use:
+.D1 "ar -d ex.a ex1.o"
+.Pp
+To verbosely list the contents of archive
+.Pa ex.a ,
+use:
+.D1 "ar -tv ex.a"
+.Pp
+To create a new archive
+.Pa ex.a
+containing the files
+.Pa ex1.o ,
+and
+.Pa ex2.o ,
+using MRI librarian commands, use the following script:
+.Bd -literal -offset indent
+create ex.a * specify the output archive
+addmod ex1.o ex2.o * add modules
+save * save pending changes
+end * exit the utility
+.Ed
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr archive 3 ,
+.Xr elf 3 ,
+.Xr strftime 3 ,
+.Xr strmode 3 ,
+.Xr ar 5
+.Sh STANDARDS COMPLIANCE
+The
+.Nm
+utility's support for the
+.Fl a ,
+.Fl b ,
+.Fl c ,
+.Fl i ,
+.Fl m ,
+.Fl p ,
+.Fl q ,
+.Fl r ,
+.Fl s ,
+.Fl t ,
+.Fl u ,
+.Fl v ,
+.Fl C
+and
+.Fl T
+options is believed to be compliant with
+.St -p1003.2 .
+.Sh HISTORY
+An
+.Nm
+command first appeared in AT&T UNIX Version 1.
+In
+.Fx 8.0 ,
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+reimplemented
+.Nm
+and
+.Nm ranlib
+using the
+.Lb libarchive
+and the
+.Lb libelf .
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c
new file mode 100644
index 000000000000..9e7cc08468cd
--- /dev/null
+++ b/usr.bin/ar/ar.c
@@ -0,0 +1,407 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * Copyright (c) 2007 Joseph Koshy
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <archive.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ar.h"
+
+enum options
+{
+ OPTION_HELP
+};
+
+static struct option longopts[] =
+{
+ {"help", no_argument, NULL, OPTION_HELP},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+};
+
+static void bsdar_usage(void);
+static void ranlib_usage(void);
+static void set_mode(struct bsdar *bsdar, char opt);
+static void only_mode(struct bsdar *bsdar, const char *opt,
+ const char *valid_modes);
+static void bsdar_version(void);
+static void ranlib_version(void);
+
+int
+main(int argc, char **argv)
+{
+ struct bsdar *bsdar, bsdar_storage;
+ char *p;
+ size_t len;
+ int exitcode, i, opt, Dflag, Uflag;
+
+ bsdar = &bsdar_storage;
+ memset(bsdar, 0, sizeof(*bsdar));
+ exitcode = EXIT_SUCCESS;
+ Dflag = 0;
+ Uflag = 0;
+
+ if ((bsdar->progname = getprogname()) == NULL)
+ bsdar->progname = "ar";
+
+ /* Act like ranlib if our name ends in "ranlib"; this
+ * accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
+ len = strlen(bsdar->progname);
+ if (len >= strlen("ranlib") &&
+ strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
+ while ((opt = getopt_long(argc, argv, "tDUV", longopts,
+ NULL)) != -1) {
+ switch(opt) {
+ case 't':
+ /* Ignored. */
+ break;
+ case 'D':
+ Dflag = 1;
+ Uflag = 0;
+ break;
+ case 'U':
+ Uflag = 1;
+ Dflag = 0;
+ break;
+ case 'V':
+ ranlib_version();
+ break;
+ case OPTION_HELP:
+ ranlib_usage();
+ default:
+ ranlib_usage();
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (*argv == NULL)
+ ranlib_usage();
+
+ /* Enable determinstic mode unless -U is set. */
+ if (Uflag == 0)
+ bsdar->options |= AR_D;
+ bsdar->options |= AR_S;
+ while ((bsdar->filename = *argv++) != NULL)
+ if (ar_write_archive(bsdar, 's'))
+ exitcode = EXIT_FAILURE;
+
+ exit(exitcode);
+ } else {
+ if (argc < 2)
+ bsdar_usage();
+
+ if (*argv[1] != '-') {
+ len = strlen(argv[1]) + 2;
+ if ((p = malloc(len)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ *p = '-';
+ (void)strlcpy(p + 1, argv[1], len - 1);
+ argv[1] = p;
+ }
+ }
+
+ while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz",
+ longopts, NULL)) != -1) {
+ switch(opt) {
+ case 'a':
+ bsdar->options |= AR_A;
+ break;
+ case 'b':
+ case 'i':
+ bsdar->options |= AR_B;
+ break;
+ case 'C':
+ bsdar->options |= AR_CC;
+ break;
+ case 'c':
+ bsdar->options |= AR_C;
+ break;
+ case 'd':
+ set_mode(bsdar, opt);
+ break;
+ case 'D':
+ Dflag = 1;
+ Uflag = 0;
+ break;
+ case 'f':
+ bsdar->options |= AR_TR;
+ break;
+ case 'j':
+ /* ignored */
+ break;
+ case 'l':
+ /* ignored, for GNU ar comptibility */
+ break;
+ case 'M':
+ set_mode(bsdar, opt);
+ break;
+ case 'm':
+ set_mode(bsdar, opt);
+ break;
+ case 'o':
+ bsdar->options |= AR_O;
+ break;
+ case 'p':
+ set_mode(bsdar, opt);
+ break;
+ case 'q':
+ set_mode(bsdar, opt);
+ break;
+ case 'r':
+ set_mode(bsdar, opt);
+ break;
+ case 'S':
+ bsdar->options |= AR_SS;
+ break;
+ case 's':
+ bsdar->options |= AR_S;
+ break;
+ case 'T':
+ /* ignored */
+ break;
+ case 't':
+ set_mode(bsdar, opt);
+ break;
+ case 'U':
+ Uflag = 1;
+ Dflag = 0;
+ break;
+ case 'u':
+ bsdar->options |= AR_U;
+ break;
+ case 'V':
+ bsdar_version();
+ break;
+ case 'v':
+ bsdar->options |= AR_V;
+ break;
+ case 'x':
+ set_mode(bsdar, opt);
+ break;
+ case 'z':
+ /* ignored */
+ break;
+ case OPTION_HELP:
+ bsdar_usage();
+ default:
+ bsdar_usage();
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (*argv == NULL && bsdar->mode != 'M')
+ bsdar_usage();
+
+ if (bsdar->options & AR_A && bsdar->options & AR_B)
+ bsdar_errc(bsdar, 0,
+ "only one of -a and -[bi] options allowed");
+
+ if (bsdar->options & AR_J && bsdar->options & AR_Z)
+ bsdar_errc(bsdar, 0, "only one of -j and -z options allowed");
+
+ if (bsdar->options & AR_S && bsdar->options & AR_SS)
+ bsdar_errc(bsdar, 0, "only one of -s and -S options allowed");
+
+ if (bsdar->options & (AR_A | AR_B)) {
+ if (*argv == NULL)
+ bsdar_errc(bsdar, 0, "no position operand specified");
+ if ((bsdar->posarg = basename(*argv)) == NULL)
+ bsdar_errc(bsdar, errno, "basename failed");
+ argc--;
+ argv++;
+ }
+
+ /* Set determinstic mode for -D, and by default without -U. */
+ if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r' ||
+ (bsdar->mode == '\0' && bsdar->options & AR_S))))
+ bsdar->options |= AR_D;
+
+ if (bsdar->options & AR_A)
+ only_mode(bsdar, "-a", "mqr");
+ if (bsdar->options & AR_B)
+ only_mode(bsdar, "-b", "mqr");
+ if (bsdar->options & AR_C)
+ only_mode(bsdar, "-c", "qr");
+ if (bsdar->options & AR_CC)
+ only_mode(bsdar, "-C", "x");
+ if (Dflag)
+ only_mode(bsdar, "-D", "qr");
+ if (Uflag)
+ only_mode(bsdar, "-U", "qr");
+ if (bsdar->options & AR_O)
+ only_mode(bsdar, "-o", "x");
+ if (bsdar->options & AR_SS)
+ only_mode(bsdar, "-S", "mqr");
+ if (bsdar->options & AR_U)
+ only_mode(bsdar, "-u", "qrx");
+
+ if (bsdar->mode == 'M') {
+ ar_mode_script(bsdar);
+ exit(EXIT_SUCCESS);
+ }
+
+ if ((bsdar->filename = *argv) == NULL)
+ bsdar_usage();
+
+ bsdar->argc = --argc;
+ bsdar->argv = ++argv;
+
+ if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
+ bsdar->options & AR_S) {
+ exitcode = ar_write_archive(bsdar, 's');
+ if (!bsdar->mode)
+ exit(exitcode);
+ }
+
+ switch(bsdar->mode) {
+ case 'd': case 'm': case 'q': case 'r':
+ exitcode = ar_write_archive(bsdar, bsdar->mode);
+ break;
+ case 'p': case 't': case 'x':
+ exitcode = ar_read_archive(bsdar, bsdar->mode, stdout);
+ break;
+ default:
+ bsdar_usage();
+ /* NOTREACHED */
+ }
+
+ for (i = 0; i < bsdar->argc; i++) {
+ if (bsdar->argv[i] != NULL) {
+ bsdar_warnc(bsdar, 0, "%s: not found in archive",
+ bsdar->argv[i]);
+ exitcode = EXIT_FAILURE;
+ }
+ }
+
+ exit(exitcode);
+}
+
+static void
+set_mode(struct bsdar *bsdar, char opt)
+{
+
+ if (bsdar->mode != '\0' && bsdar->mode != opt)
+ bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c", opt,
+ bsdar->mode);
+ bsdar->mode = opt;
+}
+
+static void
+only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
+{
+
+ if (strchr(valid_modes, bsdar->mode) == NULL)
+ bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
+ opt, bsdar->mode);
+}
+
+static void
+bsdar_usage(void)
+{
+
+ (void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n");
+ (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
+ (void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n");
+ (void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n");
+ (void)fprintf(stderr, "\tar -s [-jz] archive\n");
+ (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
+ (void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
+ (void)fprintf(stderr, "\tar -V\n");
+ exit(EXIT_FAILURE);
+}
+
+static void
+ranlib_usage(void)
+{
+
+ (void)fprintf(stderr, "usage: ranlib [-DtU] archive ...\n");
+ (void)fprintf(stderr, "\tranlib -V\n");
+ exit(EXIT_FAILURE);
+}
+
+static void
+bsdar_version(void)
+{
+ (void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string());
+ exit(EXIT_SUCCESS);
+}
+
+static void
+ranlib_version(void)
+{
+ (void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string());
+ exit(EXIT_SUCCESS);
+}
diff --git a/usr.bin/ar/ar.h b/usr.bin/ar/ar.h
new file mode 100644
index 000000000000..f5284d5e3c3c
--- /dev/null
+++ b/usr.bin/ar/ar.h
@@ -0,0 +1,119 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Kai Wang
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 BSDAR_VERSION "1.1.0"
+
+/*
+ * ar(1) options.
+ */
+#define AR_A 0x0001 /* position-after */
+#define AR_B 0x0002 /* position-before */
+#define AR_C 0x0004 /* creating new archive */
+#define AR_CC 0x0008 /* do not overwrite when extracting */
+#define AR_J 0x0010 /* bzip2 compression */
+#define AR_O 0x0020 /* preserve original mtime when extracting */
+#define AR_S 0x0040 /* write archive symbol table */
+#define AR_SS 0x0080 /* do not write archive symbol table */
+#define AR_TR 0x0100 /* only keep first 15 chars for member name */
+#define AR_U 0x0200 /* only extract or update newer members.*/
+#define AR_V 0x0400 /* verbose mode */
+#define AR_Z 0x0800 /* gzip compression */
+#define AR_D 0x1000 /* insert dummy mode, mtime, uid and gid */
+
+#define DEF_BLKSZ 10240 /* default block size */
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define AC(CALL) do { \
+ if ((CALL)) \
+ bsdar_errc(bsdar, archive_errno(a), "%s", \
+ archive_error_string(a)); \
+} while (0)
+
+/*
+ * In-memory representation of archive member(object).
+ */
+struct ar_obj {
+ char *name; /* member name */
+ void *maddr; /* mmap start address */
+ uid_t uid; /* user id */
+ gid_t gid; /* group id */
+ mode_t md; /* octal file permissions */
+ size_t size; /* member size */
+ time_t mtime; /* modification time */
+ int fd; /* file descriptor */
+ dev_t dev; /* inode's device */
+ ino_t ino; /* inode's number */
+
+ TAILQ_ENTRY(ar_obj) objs;
+};
+
+/*
+ * Structure encapsulates the "global" data for "ar" program.
+ */
+struct bsdar {
+ const char *filename; /* archive name. */
+ const char *addlib; /* target of ADDLIB. */
+ const char *posarg; /* position arg for modifiers -a, -b. */
+ char mode; /* program mode */
+ int options; /* command line options */
+
+ const char *progname; /* program name */
+ int argc;
+ char **argv;
+
+ /*
+ * Fields for the archive string table.
+ */
+ char *as; /* buffer for archive string table. */
+ size_t as_sz; /* current size of as table. */
+ size_t as_cap; /* capacity of as table buffer. */
+
+ /*
+ * Fields for the archive symbol table.
+ */
+ uint64_t s_cnt; /* current number of symbols. */
+ uint64_t *s_so; /* symbol offset table. */
+ uint64_t s_so_max; /* maximum symbol offset. */
+ size_t s_so_cap; /* capacity of so table buffer. */
+
+ char *s_sn; /* symbol name table */
+ size_t s_sn_cap; /* capacity of sn table buffer. */
+ size_t s_sn_sz; /* current size of sn table. */
+ /* Current member's offset (relative to the end of pseudo members.) */
+ off_t rela_off;
+
+ TAILQ_HEAD(, ar_obj) v_obj; /* object(member) list */
+};
+
+void ar_mode_script(struct bsdar *ar);
+int ar_read_archive(struct bsdar *ar, int mode, FILE *out);
+int ar_write_archive(struct bsdar *ar, int mode);
+void bsdar_errc(struct bsdar *, int _code, const char *fmt, ...) __dead2;
+void bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
diff --git a/usr.bin/ar/read.c b/usr.bin/ar/read.c
new file mode 100644
index 000000000000..bd3586234c69
--- /dev/null
+++ b/usr.bin/ar/read.c
@@ -0,0 +1,204 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ar.h"
+
+/*
+ * Handle read modes: 'x', 't' and 'p'.
+ */
+int
+ar_read_archive(struct bsdar *bsdar, int mode, FILE *out)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ struct stat sb;
+ struct tm *tp;
+ const char *bname;
+ const char *name;
+ mode_t md;
+ size_t size;
+ time_t mtime;
+ uid_t uid;
+ gid_t gid;
+ char **av;
+ char buf[25];
+ char find;
+ int exitcode, flags, r, i;
+
+ assert(mode == 'p' || mode == 't' || mode == 'x');
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
+
+ exitcode = EXIT_SUCCESS;
+
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+ r == ARCHIVE_FATAL)
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
+ break;
+ if (r == ARCHIVE_RETRY) {
+ bsdar_warnc(bsdar, 0, "Retrying...");
+ continue;
+ }
+
+ if ((name = archive_entry_pathname(entry)) == NULL)
+ break;
+
+ /* Skip pseudo members. */
+ if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0 ||
+ strcmp(name, "/SYM64/") == 0)
+ continue;
+
+ if (bsdar->argc > 0) {
+ find = 0;
+ for(i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av == NULL)
+ continue;
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno,
+ "basename failed");
+ if (strcmp(bname, name) != 0)
+ continue;
+
+ *av = NULL;
+ find = 1;
+ break;
+ }
+ if (!find)
+ continue;
+ }
+
+ if (mode == 't') {
+ if (bsdar->options & AR_V) {
+ md = archive_entry_mode(entry);
+ uid = archive_entry_uid(entry);
+ gid = archive_entry_gid(entry);
+ size = archive_entry_size(entry);
+ mtime = archive_entry_mtime(entry);
+ (void)strmode(md, buf);
+ (void)fprintf(out, "%s %6d/%-6d %8ju ",
+ buf + 1, uid, gid, (uintmax_t)size);
+ tp = localtime(&mtime);
+ (void)strftime(buf, sizeof(buf),
+ "%b %e %H:%M %Y", tp);
+ (void)fprintf(out, "%s %s", buf, name);
+ } else
+ (void)fprintf(out, "%s", name);
+ r = archive_read_data_skip(a);
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+ r == ARCHIVE_FATAL) {
+ (void)fprintf(out, "\n");
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ }
+
+ if (r == ARCHIVE_FATAL)
+ break;
+
+ (void)fprintf(out, "\n");
+ } else {
+ /* mode == 'x' || mode = 'p' */
+ if (mode == 'p') {
+ if (bsdar->options & AR_V) {
+ (void)fprintf(out, "\n<%s>\n\n",
+ name);
+ fflush(out);
+ }
+ r = archive_read_data_into_fd(a, 1);
+ } else {
+ /* mode == 'x' */
+ if (stat(name, &sb) != 0) {
+ if (errno != ENOENT) {
+ bsdar_warnc(bsdar, 0,
+ "stat %s failed",
+ bsdar->filename);
+ continue;
+ }
+ } else {
+ /* stat success, file exist */
+ if (bsdar->options & AR_CC)
+ continue;
+ if (bsdar->options & AR_U &&
+ archive_entry_mtime(entry) <=
+ sb.st_mtime)
+ continue;
+ }
+
+ if (bsdar->options & AR_V)
+ (void)fprintf(out, "x - %s\n", name);
+ /* Disallow absolute paths. */
+ if (name[0] == '/') {
+ bsdar_warnc(bsdar, 0,
+ "Absolute path '%s'", name);
+ continue;
+ }
+ /* Basic path security flags. */
+ flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
+ ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ if (bsdar->options & AR_O)
+ flags |= ARCHIVE_EXTRACT_TIME;
+
+ r = archive_read_extract(a, entry, flags);
+ }
+
+ if (r) {
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ exitcode = EXIT_FAILURE;
+ }
+ }
+ }
+
+ if (r == ARCHIVE_FATAL)
+ exitcode = EXIT_FAILURE;
+
+ AC(archive_read_close(a));
+ AC(archive_read_free(a));
+
+ return (exitcode);
+}
diff --git a/usr.bin/ar/util.c b/usr.bin/ar/util.c
new file mode 100644
index 000000000000..920a2e00e6de
--- /dev/null
+++ b/usr.bin/ar/util.c
@@ -0,0 +1,86 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ar.h"
+
+static void bsdar_vwarnc(struct bsdar *, int code,
+ const char *fmt, va_list ap);
+static void bsdar_verrc(struct bsdar *bsdar, int code,
+ const char *fmt, va_list ap);
+
+static void
+bsdar_vwarnc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+ fprintf(stderr, "%s: warning: ", bsdar->progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+bsdar_warnc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdar_vwarnc(bsdar, code, fmt, ap);
+ va_end(ap);
+}
+
+static void
+bsdar_verrc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+ fprintf(stderr, "%s: fatal: ", bsdar->progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+bsdar_errc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdar_verrc(bsdar, code, fmt, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
new file mode 100644
index 000000000000..a630e81480ee
--- /dev/null
+++ b/usr.bin/ar/write.c
@@ -0,0 +1,914 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Kai Wang
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/endian.h>
+#include <sys/mman.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ar.h"
+
+#define _ARMAG_LEN 8 /* length of ar magic string */
+#define _ARHDR_LEN 60 /* length of ar header */
+#define _INIT_AS_CAP 128 /* initial archive string table size */
+#define _INIT_SYMOFF_CAP (256*(sizeof(uint64_t))) /* initial so table size */
+#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */
+#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */
+#define _TRUNCATE_LEN 15 /* number of bytes to keep for member name */
+
+static void add_to_ar_str_table(struct bsdar *bsdar, const char *name);
+static void add_to_ar_sym_table(struct bsdar *bsdar, const char *name);
+static struct ar_obj *create_obj_from_file(struct bsdar *bsdar,
+ const char *name, time_t mtime);
+static void create_symtab_entry(struct bsdar *bsdar, void *maddr,
+ size_t size);
+static void free_obj(struct bsdar *bsdar, struct ar_obj *obj);
+static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
+ struct ar_obj *pos);
+static void prefault_buffer(const char *buf, size_t s);
+static void read_objs(struct bsdar *bsdar, const char *archive,
+ int checkargv);
+static void write_cleanup(struct bsdar *bsdar);
+static void write_data(struct bsdar *bsdar, struct archive *a,
+ const void *buf, size_t s);
+static void write_objs(struct bsdar *bsdar);
+
+/*
+ * Create object from file, return created obj upon success, or NULL
+ * when an error occurs or the member is not newer than existing
+ * one while -u is specified.
+ */
+static struct ar_obj *
+create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
+{
+ struct ar_obj *obj;
+ struct stat sb;
+ const char *bname;
+ char *tmpname;
+
+ if (name == NULL)
+ return (NULL);
+
+ obj = malloc(sizeof(struct ar_obj));
+ if (obj == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ if ((obj->fd = open(name, O_RDONLY, 0)) < 0) {
+ bsdar_warnc(bsdar, errno, "can't open file: %s", name);
+ free(obj);
+ return (NULL);
+ }
+
+ tmpname = strdup(name);
+ if (tmpname == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ if ((bname = basename(tmpname)) == NULL)
+ bsdar_errc(bsdar, errno, "basename failed");
+ if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
+ if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ (void)strncpy(obj->name, bname, _TRUNCATE_LEN);
+ obj->name[_TRUNCATE_LEN] = '\0';
+ } else
+ if ((obj->name = strdup(bname)) == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ free(tmpname);
+
+ if (fstat(obj->fd, &sb) < 0) {
+ bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name);
+ goto giveup;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name);
+ goto giveup;
+ }
+
+ /*
+ * When option '-u' is specified and member is not newer than the
+ * existing one, the replacement will not happen. While if mtime == 0,
+ * which indicates that this is to "replace a none exist member",
+ * the replace will proceed regardless of '-u'.
+ */
+ if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
+ goto giveup;
+
+ /*
+ * When option '-D' is specified, mtime and UID / GID from the file
+ * will be replaced with 0, and file mode with 644. This ensures that
+ * checksums will match for two archives containing the exact same
+ * files.
+ */
+ if (bsdar->options & AR_D) {
+ obj->uid = 0;
+ obj->gid = 0;
+ obj->mtime = 0;
+ obj->md = S_IFREG | 0644;
+ } else {
+ obj->uid = sb.st_uid;
+ obj->gid = sb.st_gid;
+ obj->mtime = sb.st_mtime;
+ obj->md = sb.st_mode;
+ }
+ obj->size = sb.st_size;
+ obj->dev = sb.st_dev;
+ obj->ino = sb.st_ino;
+
+ if (obj->size == 0) {
+ obj->maddr = NULL;
+ return (obj);
+ }
+
+ if ((obj->maddr = mmap(NULL, obj->size, PROT_READ,
+ MAP_PRIVATE, obj->fd, (off_t)0)) == MAP_FAILED) {
+ bsdar_warnc(bsdar, errno, "can't mmap file: %s", obj->name);
+ goto giveup;
+ }
+ if (close(obj->fd) < 0)
+ bsdar_errc(bsdar, errno, "close failed: %s",
+ obj->name);
+
+ return (obj);
+
+giveup:
+ if (close(obj->fd) < 0)
+ bsdar_errc(bsdar, errno, "close failed: %s",
+ obj->name);
+ free(obj->name);
+ free(obj);
+ return (NULL);
+}
+
+/*
+ * Free object itself and its associated allocations.
+ */
+static void
+free_obj(struct bsdar *bsdar, struct ar_obj *obj)
+{
+ if (obj->fd == -1)
+ free(obj->maddr);
+ else
+ if (obj->maddr != NULL && munmap(obj->maddr, obj->size))
+ bsdar_warnc(bsdar, errno,
+ "can't munmap file: %s", obj->name);
+ free(obj->name);
+ free(obj);
+}
+
+/*
+ * Insert obj to the tail, or before/after the pos obj.
+ */
+static void
+insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
+{
+ if (obj == NULL)
+ bsdar_errc(bsdar, 0, "try to insert a null obj");
+
+ if (pos == NULL || obj == pos)
+ /*
+ * If the object to move happens to be the position obj,
+ * or if there is not a pos obj, move it to tail.
+ */
+ goto tail;
+
+ if (bsdar->options & AR_B) {
+ TAILQ_INSERT_BEFORE(pos, obj, objs);
+ return;
+ }
+ if (bsdar->options & AR_A) {
+ TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs);
+ return;
+ }
+
+tail:
+ TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+
+}
+
+/*
+ * Read objects from archive into v_obj list. Note that checkargv is
+ * set when read_objs is used to read objects from the target of
+ * ADDLIB command (ar script mode), in this case argv array possibly
+ * specifies the members ADDLIB want.
+ */
+static void
+read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ struct ar_obj *obj;
+ const char *name;
+ const char *bname;
+ char *buff;
+ char **av;
+ size_t size;
+ int i, r, find;
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_FATAL)
+ bsdar_errc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ if (r == ARCHIVE_RETRY) {
+ bsdar_warnc(bsdar, 0, "Retrying...");
+ continue;
+ }
+
+ name = archive_entry_pathname(entry);
+
+ /*
+ * skip pseudo members.
+ */
+ if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
+ continue;
+
+ /*
+ * If checkargv is set, only read those members specified
+ * in argv.
+ */
+ if (checkargv && bsdar->argc > 0) {
+ find = 0;
+ for(i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av == NULL)
+ continue;
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno,
+ "basename failed");
+ if (strcmp(bname, name) != 0)
+ continue;
+
+ *av = NULL;
+ find = 1;
+ break;
+ }
+ if (!find)
+ continue;
+ }
+
+ size = archive_entry_size(entry);
+
+ if (size > 0) {
+ if ((buff = malloc(size)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ if (archive_read_data(a, buff, size) != (ssize_t)size) {
+ bsdar_warnc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ free(buff);
+ continue;
+ }
+ } else
+ buff = NULL;
+
+ obj = malloc(sizeof(struct ar_obj));
+ if (obj == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ obj->maddr = buff;
+ if ((obj->name = strdup(name)) == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ obj->size = size;
+ obj->uid = archive_entry_uid(entry);
+ obj->gid = archive_entry_gid(entry);
+ obj->md = archive_entry_mode(entry);
+ obj->mtime = archive_entry_mtime(entry);
+ obj->dev = 0;
+ obj->ino = 0;
+
+ /*
+ * Objects from archive have obj->fd set to -1,
+ * for the ease of cleaning up.
+ */
+ obj->fd = -1;
+ TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+ }
+ AC(archive_read_close(a));
+ AC(archive_read_free(a));
+}
+
+/*
+ * Determine the constitution of resulting archive.
+ */
+int
+ar_write_archive(struct bsdar *bsdar, int mode)
+{
+ struct ar_obj *nobj, *obj, *obj_temp, *pos;
+ struct stat sb;
+ const char *bname;
+ char **av;
+ int exitcode, i;
+
+ TAILQ_INIT(&bsdar->v_obj);
+ exitcode = EXIT_SUCCESS;
+ nobj = NULL;
+ pos = NULL;
+ memset(&sb, 0, sizeof(sb));
+
+ assert(mode == 'A' || mode == 'd' || mode == 'm' || mode == 'q' ||
+ mode == 'r' || mode == 's');
+
+ /*
+ * Test if the specified archive exists, to figure out
+ * whether we are creating one here.
+ */
+ if (stat(bsdar->filename, &sb) != 0) {
+ if (errno != ENOENT) {
+ bsdar_warnc(bsdar, 0, "stat %s failed",
+ bsdar->filename);
+ return (EXIT_FAILURE);
+ }
+
+ /* We do not create archive in mode 'd', 'm' and 's'. */
+ if (mode != 'r' && mode != 'q') {
+ bsdar_warnc(bsdar, 0, "%s: no such file",
+ bsdar->filename);
+ return (EXIT_FAILURE);
+ }
+
+ /* Issue a warning if -c is not specified when creating. */
+ if (!(bsdar->options & AR_C))
+ bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename);
+ goto new_archive;
+ }
+
+ /*
+ * First read members from existing archive.
+ */
+ read_objs(bsdar, bsdar->filename, 0);
+
+ /*
+ * For mode 's', no member will be moved, deleted or replaced.
+ */
+ if (mode == 's')
+ goto write_objs;
+
+ /*
+ * For mode 'q', we don't need to adjust existing members either.
+ * Also, -a, -b and -i are ignored in this mode. New members are
+ * always inserted at tail.
+ */
+ if (mode == 'q')
+ goto new_archive;
+
+ /*
+ * Mode 'A' adds the contents of another archive to the tail of
+ * current archive. Note that mode 'A' is a special mode for the
+ * ADDLIB command of the ar script mode. Currently there is no
+ * access to this function from the ar command line mode.
+ */
+ if (mode == 'A') {
+ /*
+ * Read objects from the target archive of ADDLIB command.
+ * If there are members specified in argv, read those members
+ * only, otherwise the entire archive will be read.
+ */
+ read_objs(bsdar, bsdar->addlib, 1);
+ goto write_objs;
+ }
+
+ /*
+ * Try to find the position member specified by user.
+ */
+ if (bsdar->options & AR_A || bsdar->options & AR_B) {
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ if (strcmp(obj->name, bsdar->posarg) == 0) {
+ pos = obj;
+ break;
+ }
+ }
+
+ /*
+ * If can't find `pos' specified by user,
+ * silently insert objects at tail.
+ */
+ if (pos == NULL)
+ bsdar->options &= ~(AR_A | AR_B);
+ }
+
+ for (i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+
+ TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno, "basename failed");
+ if (bsdar->options & AR_TR) {
+ if (strncmp(bname, obj->name, _TRUNCATE_LEN))
+ continue;
+ } else
+ if (strcmp(bname, obj->name) != 0)
+ continue;
+
+ if (mode == 'r') {
+ /*
+ * if the new member is not qualified
+ * to replace the old one, skip it.
+ */
+ nobj = create_obj_from_file(bsdar, *av,
+ obj->mtime);
+ if (nobj == NULL) {
+ exitcode = EXIT_FAILURE;
+ goto skip_obj;
+ }
+ }
+
+ if (bsdar->options & AR_V)
+ (void)fprintf(stdout, "%c - %s\n", mode,
+ *av);
+
+ TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+ if (mode == 'd' || mode == 'r')
+ free_obj(bsdar, obj);
+
+ if (mode == 'm')
+ insert_obj(bsdar, obj, pos);
+ if (mode == 'r')
+ insert_obj(bsdar, nobj, pos);
+
+ skip_obj:
+ *av = NULL;
+ break;
+ }
+
+ }
+
+new_archive:
+ /*
+ * When operating in mode 'r', directly add those user specified
+ * objects which do not exist in current archive. When operating
+ * in mode 'q', all objects specified in command line args are
+ * appended to the archive, without comparing with existing ones.
+ */
+ for (i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av != NULL && (mode == 'r' || mode == 'q')) {
+ nobj = create_obj_from_file(bsdar, *av, 0);
+ if (nobj == NULL) {
+ exitcode = EXIT_FAILURE;
+ *av = NULL;
+ continue;
+ }
+ insert_obj(bsdar, nobj, pos);
+ if (bsdar->options & AR_V && nobj != NULL)
+ (void)fprintf(stdout, "a - %s\n", *av);
+ *av = NULL;
+ }
+ }
+
+write_objs:
+ write_objs(bsdar);
+ write_cleanup(bsdar);
+
+ return (exitcode);
+}
+
+/*
+ * Memory cleaning up.
+ */
+static void
+write_cleanup(struct bsdar *bsdar)
+{
+ struct ar_obj *obj, *obj_temp;
+
+ TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+ TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+ free_obj(bsdar, obj);
+ }
+
+ free(bsdar->as);
+ free(bsdar->s_so);
+ free(bsdar->s_sn);
+ bsdar->as = NULL;
+ bsdar->s_so = NULL;
+ bsdar->s_so_max = 0;
+ bsdar->s_sn = NULL;
+}
+
+/*
+ * Fault in the buffer prior to writing as a workaround for poor performance
+ * due to interaction with kernel fs deadlock avoidance code. See the comment
+ * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue.
+ */
+static void
+prefault_buffer(const char *buf, size_t s)
+{
+ volatile const char *p;
+ size_t page_size;
+
+ if (s == 0)
+ return;
+ page_size = sysconf(_SC_PAGESIZE);
+ for (p = buf; p < buf + s; p += page_size)
+ *p;
+ /*
+ * Ensure we touch the last page as well, in case the buffer is not
+ * page-aligned.
+ */
+ *(volatile const char *)(buf + s - 1);
+}
+
+/*
+ * Wrapper for archive_write_data().
+ */
+static void
+write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
+{
+ ssize_t written;
+
+ prefault_buffer(buf, s);
+ while (s > 0) {
+ written = archive_write_data(a, buf, s);
+ if (written < 0)
+ bsdar_errc(bsdar, archive_errno(a), "%s",
+ archive_error_string(a));
+ buf = (const char *)buf + written;
+ s -= written;
+ }
+}
+
+/*
+ * Write the resulting archive members.
+ */
+static void
+write_objs(struct bsdar *bsdar)
+{
+ struct ar_obj *obj;
+ struct archive *a;
+ struct archive_entry *entry;
+ size_t s_sz; /* size of archive symbol table. */
+ size_t pm_sz; /* size of pseudo members */
+ size_t w_sz; /* size of words in symbol table */
+ size_t i;
+ uint64_t nr;
+ uint32_t nr32;
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
+ elf_errmsg(-1));
+
+ bsdar->rela_off = 0;
+
+ /* Create archive symbol table and archive string table, if need. */
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ if (!(bsdar->options & AR_SS) && obj->maddr != NULL)
+ create_symtab_entry(bsdar, obj->maddr, obj->size);
+ if (strlen(obj->name) > _MAXNAMELEN_SVR4)
+ add_to_ar_str_table(bsdar, obj->name);
+ bsdar->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
+ }
+
+ /*
+ * Pad the symbol name string table. It is treated specially because
+ * symbol name table should be padded by a '\0', not the common '\n'
+ * for other members. The size of sn table includes the pad bit.
+ */
+ if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0)
+ bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+
+ /*
+ * Archive string table is padded by a "\n" as the normal members.
+ * The difference is that the size of archive string table counts
+ * in the pad bit, while normal members' size fields do not.
+ */
+ if (bsdar->as != NULL && bsdar->as_sz % 2 != 0)
+ bsdar->as[bsdar->as_sz++] = '\n';
+
+ /*
+ * If there is a symbol table, calculate the size of pseudo members,
+ * convert previously stored relative offsets to absolute ones, and
+ * then make them Big Endian.
+ *
+ * absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
+ */
+ w_sz = sizeof(uint32_t);
+ if (bsdar->s_cnt != 0) {
+ s_sz = (bsdar->s_cnt + 1) * sizeof(uint32_t) + bsdar->s_sn_sz;
+ pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
+ if (bsdar->as != NULL)
+ pm_sz += _ARHDR_LEN + bsdar->as_sz;
+ /* Use the 64-bit word size format if necessary. */
+ if (bsdar->s_so_max > UINT32_MAX - pm_sz) {
+ w_sz = sizeof(uint64_t);
+ pm_sz -= s_sz;
+ s_sz = (bsdar->s_cnt + 1) * sizeof(uint64_t) +
+ bsdar->s_sn_sz;
+ pm_sz += s_sz;
+ /* Convert to big-endian. */
+ for (i = 0; i < bsdar->s_cnt; i++)
+ bsdar->s_so[i] =
+ htobe64(bsdar->s_so[i] + pm_sz);
+ } else {
+ /*
+ * Convert to big-endian and shuffle in-place to
+ * the front of the allocation. XXX UB
+ */
+ for (i = 0; i < bsdar->s_cnt; i++)
+ ((uint32_t *)(bsdar->s_so))[i] =
+ htobe32(bsdar->s_so[i] + pm_sz);
+ }
+ }
+
+ if ((a = archive_write_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_write_new failed");
+
+ archive_write_set_format_ar_svr4(a);
+
+ AC(archive_write_open_filename(a, bsdar->filename));
+
+ /*
+ * write the archive symbol table, if there is one.
+ * If options -s is explicitly specified or we are invoked
+ * as ranlib, write the symbol table even if it is empty.
+ */
+ if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) ||
+ bsdar->options & AR_S) {
+ entry = archive_entry_new();
+ if (entry == NULL)
+ bsdar_errc(bsdar, 0, "archive_entry_new failed");
+ if (w_sz == sizeof(uint64_t))
+ archive_entry_copy_pathname(entry, "/SYM64/");
+ else
+ archive_entry_copy_pathname(entry, "/");
+ if ((bsdar->options & AR_D) == 0)
+ archive_entry_set_mtime(entry, time(NULL), 0);
+ archive_entry_set_size(entry, (bsdar->s_cnt + 1) * w_sz +
+ bsdar->s_sn_sz);
+ AC(archive_write_header(a, entry));
+ if (w_sz == sizeof(uint64_t)) {
+ nr = htobe64(bsdar->s_cnt);
+ write_data(bsdar, a, &nr, sizeof(nr));
+ } else {
+ nr32 = htobe32((uint32_t)bsdar->s_cnt);
+ write_data(bsdar, a, &nr32, sizeof(nr32));
+ }
+ write_data(bsdar, a, bsdar->s_so, w_sz * bsdar->s_cnt);
+ write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
+ archive_entry_free(entry);
+ }
+
+ /* write the archive string table, if any. */
+ if (bsdar->as != NULL) {
+ entry = archive_entry_new();
+ if (entry == NULL)
+ bsdar_errc(bsdar, 0, "archive_entry_new failed");
+ archive_entry_copy_pathname(entry, "//");
+ archive_entry_set_size(entry, bsdar->as_sz);
+ AC(archive_write_header(a, entry));
+ write_data(bsdar, a, bsdar->as, bsdar->as_sz);
+ archive_entry_free(entry);
+ }
+
+ /* write normal members. */
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ entry = archive_entry_new();
+ if (entry == NULL)
+ bsdar_errc(bsdar, 0, "archive_entry_new failed");
+ archive_entry_copy_pathname(entry, obj->name);
+ archive_entry_set_uid(entry, obj->uid);
+ archive_entry_set_gid(entry, obj->gid);
+ archive_entry_set_mode(entry, obj->md);
+ archive_entry_set_size(entry, obj->size);
+ archive_entry_set_mtime(entry, obj->mtime, 0);
+ archive_entry_set_dev(entry, obj->dev);
+ archive_entry_set_ino(entry, obj->ino);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ AC(archive_write_header(a, entry));
+ write_data(bsdar, a, obj->maddr, obj->size);
+ archive_entry_free(entry);
+ }
+
+ AC(archive_write_close(a));
+ AC(archive_write_free(a));
+}
+
+/*
+ * Extract global symbols from ELF binary members.
+ */
+static void
+create_symtab_entry(struct bsdar *bsdar, void *maddr, size_t size)
+{
+ Elf *e;
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ GElf_Sym sym;
+ Elf_Data *data;
+ char *name;
+ size_t n, shstrndx;
+ int elferr, tabndx, len, i;
+
+ if ((e = elf_memory(maddr, size)) == NULL) {
+ bsdar_warnc(bsdar, 0, "elf_memory() failed: %s",
+ elf_errmsg(-1));
+ return;
+ }
+ if (elf_kind(e) != ELF_K_ELF) {
+ /* Silently ignore non-elf member. */
+ elf_end(e);
+ return;
+ }
+ if (elf_getshstrndx(e, &shstrndx) == 0) {
+ bsdar_warnc(bsdar, 0, "elf_getshstrndx failed: %s",
+ elf_errmsg(-1));
+ elf_end(e);
+ return;
+ }
+
+ tabndx = -1;
+ scn = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr) {
+ bsdar_warnc(bsdar, 0,
+ "elf_getshdr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
+ bsdar_warnc(bsdar, 0,
+ "elf_strptr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if (strcmp(name, ".strtab") == 0) {
+ tabndx = elf_ndxscn(scn);
+ break;
+ }
+ }
+ elferr = elf_errno();
+ if (elferr != 0)
+ bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+ elf_errmsg(elferr));
+ if (tabndx == -1) {
+ bsdar_warnc(bsdar, 0, "can't find .strtab section");
+ elf_end(e);
+ return;
+ }
+
+ scn = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr) {
+ bsdar_warnc(bsdar, 0, "elf_getshdr failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+ if (shdr.sh_type != SHT_SYMTAB)
+ continue;
+
+ data = NULL;
+ n = 0;
+ while (n < shdr.sh_size &&
+ (data = elf_getdata(scn, data)) != NULL) {
+ len = data->d_size / shdr.sh_entsize;
+ for (i = 0; i < len; i++) {
+ if (gelf_getsym(data, i, &sym) != &sym) {
+ bsdar_warnc(bsdar, 0,
+ "gelf_getsym failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+
+ /* keep only global or weak symbols */
+ if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
+ GELF_ST_BIND(sym.st_info) != STB_WEAK)
+ continue;
+
+ /* keep only defined symbols */
+ if (sym.st_shndx == SHN_UNDEF)
+ continue;
+
+ if ((name = elf_strptr(e, tabndx,
+ sym.st_name)) == NULL) {
+ bsdar_warnc(bsdar, 0,
+ "elf_strptr failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+
+ add_to_ar_sym_table(bsdar, name);
+ }
+ }
+ }
+ elferr = elf_errno();
+ if (elferr != 0)
+ bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+ elf_errmsg(elferr));
+
+ elf_end(e);
+}
+
+/*
+ * Append to the archive string table buffer.
+ */
+static void
+add_to_ar_str_table(struct bsdar *bsdar, const char *name)
+{
+
+ if (bsdar->as == NULL) {
+ bsdar->as_cap = _INIT_AS_CAP;
+ bsdar->as_sz = 0;
+ if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ }
+
+ /*
+ * The space required for holding one member name in as table includes:
+ * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding).
+ */
+ while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) {
+ bsdar->as_cap *= 2;
+ bsdar->as = realloc(bsdar->as, bsdar->as_cap);
+ if (bsdar->as == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
+ bsdar->as_sz += strlen(name);
+ bsdar->as[bsdar->as_sz++] = '/';
+ bsdar->as[bsdar->as_sz++] = '\n';
+}
+
+/*
+ * Append to the archive symbol table buffer.
+ */
+static void
+add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
+{
+
+ if (bsdar->s_so == NULL) {
+ if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
+ NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ bsdar->s_so_cap = _INIT_SYMOFF_CAP;
+ bsdar->s_cnt = 0;
+ }
+
+ if (bsdar->s_sn == NULL) {
+ if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
+ bsdar->s_sn_sz = 0;
+ }
+
+ if (bsdar->s_cnt * sizeof(uint64_t) >= bsdar->s_so_cap) {
+ bsdar->s_so_cap *= 2;
+ bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
+ if (bsdar->s_so == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
+ if ((uint64_t)bsdar->rela_off > bsdar->s_so_max)
+ bsdar->s_so_max = (uint64_t)bsdar->rela_off;
+ bsdar->s_cnt++;
+
+ /*
+ * The space required for holding one symbol name in sn table includes:
+ * strlen(name) + (1 for '\n') + (possibly 1 for padding).
+ */
+ while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) {
+ bsdar->s_sn_cap *= 2;
+ bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
+ if (bsdar->s_sn == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
+ bsdar->s_sn_sz += strlen(name);
+ bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+}
diff --git a/usr.bin/asa/Makefile b/usr.bin/asa/Makefile
new file mode 100644
index 000000000000..a29db0f31781
--- /dev/null
+++ b/usr.bin/asa/Makefile
@@ -0,0 +1,7 @@
+.include <src.opts.mk>
+
+PROG= asa
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/asa/Makefile.depend b/usr.bin/asa/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/asa/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/asa/asa.1 b/usr.bin/asa/asa.1
new file mode 100644
index 000000000000..da1af0e8ce84
--- /dev/null
+++ b/usr.bin/asa/asa.1
@@ -0,0 +1,96 @@
+.\" $NetBSD: asa.1,v 1.11 2002/02/08 01:36:18 ross Exp $
+.\"
+.\" Copyright (c) 1993 Winning Strategies, Inc.
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. 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.
+.\"
+.Dd May 9, 2002
+.Dt ASA 1
+.Os
+.Sh NAME
+.Nm asa
+.Nd interpret carriage-control characters
+.Sh SYNOPSIS
+.Nm
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility reads files sequentially, mapping
+.Tn FORTRAN
+carriage-control characters to line-printer control sequences,
+and writes them to the standard output.
+.Pp
+The first character of each line is interpreted as a carriage-control
+character.
+The following characters are interpreted as follows:
+.Bl -tag -width ".Aq space"
+.It Aq space
+Output the rest of the line without change.
+.It 0
+Output a
+.Aq newline
+character before printing the rest of the line.
+.It 1
+Output a
+.Aq formfeed
+character before printing the rest of the line.
+.It \&+
+The trailing
+.Aq newline
+of the previous line is replaced by a
+.Aq carriage-return
+before printing the rest of the line.
+.El
+.Pp
+Lines beginning with characters other than the above are treated as if they
+begin with
+.Aq space .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To view a file containing the output of a
+.Tn FORTRAN
+program:
+.Pp
+.Dl "asa file"
+.Pp
+To format the output of a
+.Tn FORTRAN
+program and redirect it to a line-printer:
+.Pp
+.Dl "a.out | asa | lpr"
+.Sh SEE ALSO
+.Xr f77 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh AUTHORS
+.An J.T. Conklin ,
+Winning Strategies, Inc.
diff --git a/usr.bin/asa/asa.c b/usr.bin/asa/asa.c
new file mode 100644
index 000000000000..9839dbf8a722
--- /dev/null
+++ b/usr.bin/asa/asa.c
@@ -0,0 +1,142 @@
+/* $NetBSD: asa.c,v 1.17 2016/09/05 00:40:28 sevan Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. 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.
+ */
+
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void asa(FILE *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp;
+ int ch, exval;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ exval = 0;
+ if (*argv == NULL) {
+ asa(stdin);
+ } else {
+ do {
+ if (strcmp(*argv, "-") == 0) {
+ asa(stdin);
+ } else if ((fp = fopen(*argv, "r")) == NULL) {
+ warn("%s", *argv);
+ exval = 1;
+ } else {
+ asa(fp);
+ fclose(fp);
+ }
+ } while (*++argv != NULL);
+ }
+
+ if (fflush(stdout) != 0)
+ err(1, "stdout");
+
+ exit(exval);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: asa [file ...]\n");
+ exit(1);
+}
+
+static void
+asa(FILE *f)
+{
+ char *buf;
+ size_t len;
+ bool eol = false;
+
+ while ((buf = fgetln(f, &len)) != NULL) {
+ /* in all cases but '+', terminate previous line, if any */
+ if (buf[0] != '+' && eol)
+ putchar('\n');
+ /* examine and translate the control character */
+ switch (buf[0]) {
+ default:
+ /*
+ * “It is suggested that implementations treat
+ * characters other than 0, 1, and '+' as <space>
+ * in the absence of any compelling reason to do
+ * otherwise†(POSIX.1-2017)
+ */
+ case ' ':
+ /* nothing */
+ break;
+ case '0':
+ putchar('\n');
+ break;
+ case '1':
+ putchar('\f');
+ break;
+ case '+':
+ /*
+ * “If the '+' is the first character in the
+ * input, it shall be equivalent to <space>.â€
+ * (POSIX.1-2017)
+ */
+ if (eol)
+ putchar('\r');
+ break;
+ }
+ /* trim newline if there is one */
+ if ((eol = (buf[len - 1] == '\n')))
+ --len;
+ /* print the rest of the input line */
+ if (len > 1 && buf[0] && buf[1])
+ fwrite(buf + 1, 1, len - 1, stdout);
+ }
+ /* terminate the last line, if any */
+ if (eol)
+ putchar('\n');
+ /* check for output errors */
+ if (ferror(stdout) != 0)
+ err(1, "stdout");
+}
diff --git a/usr.bin/asa/tests/Makefile b/usr.bin/asa/tests/Makefile
new file mode 100644
index 000000000000..c8c0cde1b3a2
--- /dev/null
+++ b/usr.bin/asa/tests/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= tests
+ATF_TESTS_SH= asa_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/asa/tests/Makefile.depend b/usr.bin/asa/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/asa/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/asa/tests/asa_test.sh b/usr.bin/asa/tests/asa_test.sh
new file mode 100644
index 000000000000..2b8fecb12d98
--- /dev/null
+++ b/usr.bin/asa/tests/asa_test.sh
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+a="The magic words are"
+b="Squeamish Ossifrage"
+
+atf_check_asa() {
+ atf_check -o file:"$2" asa "$1"
+ atf_check -o file:"$2" asa <"$1"
+ atf_check -o file:"$2" asa - <"$1"
+}
+
+atf_test_case space
+space_head() {
+ atf_set descr "First character on line is ' '"
+}
+space_body() {
+ printf " %s\n %s\n" "$a" "$b" >infile
+ printf "%s\n%s\n" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_test_case zero
+zero_head() {
+ atf_set descr "First character on line is '0'"
+}
+zero_body() {
+ printf " %s\n0%s\n" "$a" "$b" >infile
+ printf "%s\n\n%s\n" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_test_case one
+one_head() {
+ atf_set descr "First character on line is '1'"
+}
+one_body() {
+ printf "1%s\n1%s\n" "$a" "$b" >infile
+ printf "\f%s\n\f%s\n" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_test_case plus
+plus_head() {
+ atf_set descr "First character on line is '+'"
+}
+plus_body() {
+ printf " %s\n+%s\n" "$a" "$b" >infile
+ printf "%s\r%s\n" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_test_case plus_top
+plus_top_head() {
+ atf_set descr "First character in input is '+'"
+}
+plus_top_body() {
+ printf "+%s\n+%s\n" "$a" "$b" >infile
+ printf "%s\r%s\n" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_test_case stdout
+stdout_head() {
+ atf_set descr "Failure to write to stdout"
+}
+stdout_body() {
+ (
+ trap "" PIPE
+ sleep 1
+ echo " $a $b" | asa 2>stderr
+ echo $? >result
+ ) | true
+ atf_check -o inline:"1\n" cat result
+ atf_check -o match:"stdout" cat stderr
+}
+
+atf_test_case dashdash
+dashdash_head() {
+ atf_set descr "Use -- to end options"
+}
+dashdash_body() {
+ echo " $a $b" >-infile
+ atf_check -s not-exit:0 -e match:"illegal option" asa -infile
+ atf_check -o inline:"$a $b\n" asa -- -infile
+}
+
+atf_test_case unterminated
+unterminated_head() {
+ atf_set descr "Unterminated input"
+}
+unterminated_body() {
+ printf " %s\n %s" "$a" "$b" >infile
+ printf "%s\n%s" "$a" "$b" >outfile
+ atf_check_asa infile outfile
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case space
+ atf_add_test_case zero
+ atf_add_test_case one
+ atf_add_test_case plus
+ atf_add_test_case plus_top
+ atf_add_test_case stdout
+ atf_add_test_case dashdash
+ atf_add_test_case unterminated
+}
diff --git a/usr.bin/at/LEGAL b/usr.bin/at/LEGAL
new file mode 100644
index 000000000000..92b1b4983110
--- /dev/null
+++ b/usr.bin/at/LEGAL
@@ -0,0 +1,29 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+Sorry for the long wait, but there still were a few things to
+be ironed out in at, which I've finally done :-)
+
+The FreeBSD team does have my permission to use at, version 2.9,
+under the BSD license.
+
+You'll find it on sunsite.unc.edu's Incoming, hopefully; the
+md5 checksum is
+
+3ba2ca3c0e87e1a04feae2c6c1376b0d at-2.9.tgz
+
+Best regards
+ Thomas
+- --
+Thomas Koenig, Thomas.Koenig@ciw.uni-karlsruhe.de, ig25@dkauni2.bitnet.
+The joy of engineering is to find a straight line on a double
+logarithmic diagram.
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.2i
+
+iQCVAwUBMCjVrPBu+cbJcKCVAQFNiQP/dpWP57s/E8plVGUD3zfgOXDmKUvg8U7a
+VwRzJrIMuSgnSJs0wkpvcomc3NLicipfX7hhWLh/xatPM2YbF7O5HZoNdvWvexD2
+1Y67zJ+0HFb1mPnSBOrS5RFiQAe3KqmGec6E14Rih/qNoFQZBVRFXZ4xxuwP+0Rs
+e2U+TVTUz6A=
+=TvyW
+-----END PGP SIGNATURE-----
diff --git a/usr.bin/at/Makefile b/usr.bin/at/Makefile
new file mode 100644
index 000000000000..daf93c472982
--- /dev/null
+++ b/usr.bin/at/Makefile
@@ -0,0 +1,33 @@
+.include "${.CURDIR}/Makefile.inc"
+
+CONFS= atrun
+CONFSDIR= /etc/cron.d
+CONFSNAME= at
+PROG= at
+SRCS= at.c panic.c parsetime.c perm.c
+LINKS= ${BINDIR}/at ${BINDIR}/atq \
+ ${BINDIR}/at ${BINDIR}/atrm \
+ ${BINDIR}/at ${BINDIR}/batch
+MLINKS= at.1 batch.1 \
+ at.1 atq.1 \
+ at.1 atrm.1
+
+NO_WFORMAT=
+
+BINOWN= root
+BINMODE= 4555
+CLEANFILES+= at.1
+
+at.1: at.man
+ @${ECHO} Making ${.TARGET:T} from ${.ALLSRC:T}; \
+ sed -e \
+ "s@_ATSPOOL_DIR@$(ATSPOOL_DIR)@g; \
+ s@_ATJOB_DIR@$(ATJOB_DIR)@g; \
+ s@_DEFAULT_BATCH_QUEUE@$(DEFAULT_BATCH_QUEUE)@g; \
+ s@_DEFAULT_AT_QUEUE@$(DEFAULT_AT_QUEUE)@g; \
+ s@_LOADAVG_MX@$(LOADAVG_MX)@g; \
+ s@_PERM_PATH@$(PERM_PATH)@g; \
+ s@_LOCKFILE@$(LOCKFILE)@g" \
+ < ${.ALLSRC} > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/at/Makefile.depend b/usr.bin/at/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/at/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/at/Makefile.inc b/usr.bin/at/Makefile.inc
new file mode 100644
index 000000000000..903b7a9c9997
--- /dev/null
+++ b/usr.bin/at/Makefile.inc
@@ -0,0 +1,19 @@
+LOCKFILE = .lockfile
+ATSPOOL_DIR=/var/at/spool
+ATJOB_DIR=/var/at/jobs
+ATLIB_DIR=/usr/libexec
+LOADAVG_MX=1.5
+DAEMON_GID=1
+DAEMON_UID=1
+DEFAULT_BATCH_QUEUE=E
+DEFAULT_AT_QUEUE=c
+PERM_PATH=/var/at
+PACKAGE= at
+
+CFLAGS += -DATJOB_DIR=\"$(ATJOB_DIR)/\" \
+ -DLFILE=\"$(ATJOB_DIR)/$(LOCKFILE)\" \
+ -DLOADAVG_MX=$(LOADAVG_MX) -DATSPOOL_DIR=\"$(ATSPOOL_DIR)\" \
+ -DDAEMON_UID=$(DAEMON_UID) -DDAEMON_GID=$(DAEMON_GID) \
+ -DDEFAULT_BATCH_QUEUE=\'$(DEFAULT_BATCH_QUEUE)\' \
+ -DDEFAULT_AT_QUEUE=\'$(DEFAULT_AT_QUEUE)\' -DPERM_PATH=\"$(PERM_PATH)/\"
+
diff --git a/usr.bin/at/at.c b/usr.bin/at/at.c
new file mode 100644
index 000000000000..5b423d9d40d0
--- /dev/null
+++ b/usr.bin/at/at.c
@@ -0,0 +1,914 @@
+/*-
+ * at.c : Put file into atrun queue
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993, 1994 Thomas Koenig
+ *
+ * Atrun & Atq modifications
+ * Copyright (C) 1993 David Parsons
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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/cdefs.h>
+#define _USE_BSD 1
+
+/* System Headers */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifndef __FreeBSD__
+#include <getopt.h>
+#endif
+#ifdef __FreeBSD__
+#include <locale.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Local headers */
+
+#include "at.h"
+#include "panic.h"
+#include "parsetime.h"
+#include "perm.h"
+
+#define MAIN
+#include "privs.h"
+
+/* Macros */
+
+#ifndef ATJOB_DIR
+#define ATJOB_DIR "/usr/spool/atjobs/"
+#endif
+
+#ifndef LFILE
+#define LFILE ATJOB_DIR ".lockfile"
+#endif
+
+#ifndef ATJOB_MX
+#define ATJOB_MX 255
+#endif
+
+#define ALARMC 10 /* Number of seconds to wait for timeout */
+
+#define SIZE 255
+#define TIMESIZE 50
+
+enum { ATQ, ATRM, AT, BATCH, CAT }; /* what program we want to run */
+
+/* File scope variables */
+
+static const char *no_export[] = {
+ "TERM", "TERMCAP", "DISPLAY", "_"
+};
+static int send_mail = 0;
+static char *atinput = NULL; /* where to get input from */
+static char atqueue = 0; /* which queue to examine for jobs (atq) */
+
+/* External variables */
+
+extern char **environ;
+int fcreated;
+char atfile[] = ATJOB_DIR "12345678901234";
+char atverify = 0; /* verify time instead of queuing job */
+char *namep;
+
+/* Function declarations */
+
+static void sigc(int signo);
+static void alarmc(int signo);
+static char *cwdname(void);
+static void writefile(time_t runtimer, char queue);
+static void list_jobs(long *, int);
+static long nextjob(void);
+static time_t ttime(const char *arg);
+static int in_job_list(long, long *, int);
+static long *get_job_list(int, char *[], int *);
+
+/* Signal catching functions */
+
+static void sigc(int signo __unused)
+{
+/* If the user presses ^C, remove the spool file and exit
+ */
+ if (fcreated)
+ {
+ PRIV_START
+ unlink(atfile);
+ PRIV_END
+ }
+
+ _exit(EXIT_FAILURE);
+}
+
+static void alarmc(int signo __unused)
+{
+ char buf[1024];
+
+ /* Time out after some seconds. */
+ strlcpy(buf, namep, sizeof(buf));
+ strlcat(buf, ": file locking timed out\n", sizeof(buf));
+ write(STDERR_FILENO, buf, strlen(buf));
+ sigc(0);
+}
+
+/* Local functions */
+
+static char *cwdname(void)
+{
+/* Read in the current directory; the name will be overwritten on
+ * subsequent calls.
+ */
+ static char *ptr = NULL;
+ static size_t size = SIZE;
+
+ if (ptr == NULL)
+ if ((ptr = malloc(size)) == NULL)
+ errx(EXIT_FAILURE, "virtual memory exhausted");
+
+ while (1)
+ {
+ if (ptr == NULL)
+ panic("out of memory");
+
+ if (getcwd(ptr, size-1) != NULL)
+ return ptr;
+
+ if (errno != ERANGE)
+ perr("cannot get directory");
+
+ free (ptr);
+ size += SIZE;
+ if ((ptr = malloc(size)) == NULL)
+ errx(EXIT_FAILURE, "virtual memory exhausted");
+ }
+}
+
+static long
+nextjob(void)
+{
+ long jobno;
+ FILE *fid;
+
+ if ((fid = fopen(ATJOB_DIR ".SEQ", "r+")) != NULL) {
+ if (fscanf(fid, "%5lx", &jobno) == 1) {
+ rewind(fid);
+ jobno = (1+jobno) % 0xfffff; /* 2^20 jobs enough? */
+ fprintf(fid, "%05lx\n", jobno);
+ }
+ else
+ jobno = EOF;
+ fclose(fid);
+ return jobno;
+ }
+ else if ((fid = fopen(ATJOB_DIR ".SEQ", "w")) != NULL) {
+ fprintf(fid, "%05lx\n", jobno = 1);
+ fclose(fid);
+ return 1;
+ }
+ return EOF;
+}
+
+static void
+writefile(time_t runtimer, char queue)
+{
+/* This does most of the work if at or batch are invoked for writing a job.
+ */
+ long jobno;
+ char *ap, *ppos, *mailname;
+ struct passwd *pass_entry;
+ struct stat statbuf;
+ int fdes, lockdes, fd2;
+ FILE *fp, *fpin;
+ struct sigaction act;
+ char **atenv;
+ int ch;
+ mode_t cmask;
+ struct flock lock;
+
+#ifdef __FreeBSD__
+ (void) setlocale(LC_TIME, "");
+#endif
+
+/* Install the signal handler for SIGINT; terminate after removing the
+ * spool file if necessary
+ */
+ act.sa_handler = sigc;
+ sigemptyset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ sigaction(SIGINT, &act, NULL);
+
+ ppos = atfile + strlen(ATJOB_DIR);
+
+ /* Loop over all possible file names for running something at this
+ * particular time, see if a file is there; the first empty slot at any
+ * particular time is used. Lock the file LFILE first to make sure
+ * we're alone when doing this.
+ */
+
+ PRIV_START
+
+ if ((lockdes = open(LFILE, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR)) < 0)
+ perr("cannot open lockfile " LFILE);
+
+ lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0;
+ lock.l_len = 0;
+
+ act.sa_handler = alarmc;
+ sigemptyset(&(act.sa_mask));
+ act.sa_flags = 0;
+
+ /* Set an alarm so a timeout occurs after ALARMC seconds, in case
+ * something is seriously broken.
+ */
+ sigaction(SIGALRM, &act, NULL);
+ alarm(ALARMC);
+ fcntl(lockdes, F_SETLKW, &lock);
+ alarm(0);
+
+ if ((jobno = nextjob()) == EOF)
+ perr("cannot generate job number");
+
+ sprintf(ppos, "%c%5lx%8lx", queue,
+ jobno, (unsigned long) (runtimer/60));
+
+ for(ap=ppos; *ap != '\0'; ap ++)
+ if (*ap == ' ')
+ *ap = '0';
+
+ if (stat(atfile, &statbuf) != 0)
+ if (errno != ENOENT)
+ perr("cannot access " ATJOB_DIR);
+
+ /* Create the file. The x bit is only going to be set after it has
+ * been completely written out, to make sure it is not executed in the
+ * meantime. To make sure they do not get deleted, turn off their r
+ * bit. Yes, this is a kluge.
+ */
+ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR);
+ if ((fdes = creat(atfile, O_WRONLY)) == -1)
+ perr("cannot create atjob file");
+
+ if ((fd2 = dup(fdes)) <0)
+ perr("error in dup() of job file");
+
+ if(fchown(fd2, real_uid, real_gid) != 0)
+ perr("cannot give away file");
+
+ PRIV_END
+
+ /* We no longer need suid root; now we just need to be able to write
+ * to the directory, if necessary.
+ */
+
+ REDUCE_PRIV(DAEMON_UID, DAEMON_GID)
+
+ /* We've successfully created the file; let's set the flag so it
+ * gets removed in case of an interrupt or error.
+ */
+ fcreated = 1;
+
+ /* Now we can release the lock, so other people can access it
+ */
+ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = 0;
+ lock.l_len = 0;
+ fcntl(lockdes, F_SETLKW, &lock);
+ close(lockdes);
+
+ if((fp = fdopen(fdes, "w")) == NULL)
+ panic("cannot reopen atjob file");
+
+ /* Get the userid to mail to, first by trying getlogin(),
+ * then from LOGNAME, finally from getpwuid().
+ */
+ mailname = getlogin();
+ if (mailname == NULL)
+ mailname = getenv("LOGNAME");
+
+ if ((mailname == NULL) || (mailname[0] == '\0')
+ || (strlen(mailname) >= MAXLOGNAME) || (getpwnam(mailname)==NULL))
+ {
+ pass_entry = getpwuid(real_uid);
+ if (pass_entry != NULL)
+ mailname = pass_entry->pw_name;
+ }
+
+ if (atinput != (char *) NULL)
+ {
+ fpin = freopen(atinput, "r", stdin);
+ if (fpin == NULL)
+ perr("cannot open input file");
+ }
+ fprintf(fp, "#!/bin/sh\n# atrun uid=%ld gid=%ld\n# mail %*s %d\n",
+ (long) real_uid, (long) real_gid, MAXLOGNAME - 1, mailname,
+ send_mail);
+
+ /* Write out the umask at the time of invocation
+ */
+ fprintf(fp, "umask %lo\n", (unsigned long) cmask);
+
+ /* Write out the environment. Anything that may look like a
+ * special character to the shell is quoted, except for \n, which is
+ * done with a pair of "'s. Don't export the no_export list (such
+ * as TERM or DISPLAY) because we don't want these.
+ */
+ for (atenv= environ; *atenv != NULL; atenv++)
+ {
+ int export = 1;
+ char *eqp;
+
+ eqp = strchr(*atenv, '=');
+ if (eqp == NULL)
+ eqp = *atenv;
+ else
+ {
+ size_t i;
+ for (i = 0; i < nitems(no_export); i++)
+ {
+ export = export
+ && (strncmp(*atenv, no_export[i],
+ (size_t) (eqp-*atenv)) != 0);
+ }
+ eqp++;
+ }
+
+ if (export)
+ {
+ (void)fputs("export ", fp);
+ fwrite(*atenv, sizeof(char), eqp-*atenv, fp);
+ for(ap = eqp;*ap != '\0'; ap++)
+ {
+ if (*ap == '\n')
+ fprintf(fp, "\"\n\"");
+ else
+ {
+ if (!isalnum(*ap)) {
+ switch (*ap) {
+ case '%': case '/': case '{': case '[':
+ case ']': case '=': case '}': case '@':
+ case '+': case '#': case ',': case '.':
+ case ':': case '-': case '_':
+ break;
+ default:
+ fputc('\\', fp);
+ break;
+ }
+ }
+ fputc(*ap, fp);
+ }
+ }
+ fputc('\n', fp);
+
+ }
+ }
+ /* Cd to the directory at the time and write out all the
+ * commands the user supplies from stdin.
+ */
+ fprintf(fp, "cd ");
+ for (ap = cwdname(); *ap != '\0'; ap++)
+ {
+ if (*ap == '\n')
+ fprintf(fp, "\"\n\"");
+ else
+ {
+ if (*ap != '/' && !isalnum(*ap))
+ fputc('\\', fp);
+
+ fputc(*ap, fp);
+ }
+ }
+ /* Test cd's exit status: die if the original directory has been
+ * removed, become unreadable or whatever
+ */
+ fprintf(fp, " || {\n\t echo 'Execution directory "
+ "inaccessible' >&2\n\t exit 1\n}\n");
+
+ while((ch = getchar()) != EOF)
+ fputc(ch, fp);
+
+ fprintf(fp, "\n");
+ if (ferror(fp))
+ panic("output error");
+
+ if (ferror(stdin))
+ panic("input error");
+
+ fclose(fp);
+
+ /* Set the x bit so that we're ready to start executing
+ */
+
+ if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
+ perr("cannot give away file");
+
+ close(fd2);
+ fprintf(stderr, "Job %ld will be executed using /bin/sh\n", jobno);
+}
+
+static int
+in_job_list(long job, long *joblist, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (job == joblist[i])
+ return 1;
+
+ return 0;
+}
+
+static void
+list_jobs(long *joblist, int len)
+{
+ /* List all a user's jobs in the queue, by looping through ATJOB_DIR,
+ * or everybody's if we are root
+ */
+ struct passwd *pw;
+ DIR *spool;
+ struct dirent *dirent;
+ struct stat buf;
+ struct tm runtime;
+ unsigned long ctm;
+ char queue;
+ long jobno;
+ time_t runtimer;
+ char timestr[TIMESIZE];
+ int first=1;
+
+#ifdef __FreeBSD__
+ (void) setlocale(LC_TIME, "");
+#endif
+
+ PRIV_START
+
+ if (chdir(ATJOB_DIR) != 0)
+ perr("cannot change to " ATJOB_DIR);
+
+ if ((spool = opendir(".")) == NULL)
+ perr("cannot open " ATJOB_DIR);
+
+ /* Loop over every file in the directory
+ */
+ while((dirent = readdir(spool)) != NULL) {
+ if (stat(dirent->d_name, &buf) != 0)
+ perr("cannot stat in " ATJOB_DIR);
+
+ /* See it's a regular file and has its x bit turned on and
+ * is the user's
+ */
+ if (!S_ISREG(buf.st_mode)
+ || ((buf.st_uid != real_uid) && ! (real_uid == 0))
+ || !(S_IXUSR & buf.st_mode || atverify))
+ continue;
+
+ if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+ continue;
+
+ /* If jobs are given, only list those jobs */
+ if (joblist && !in_job_list(jobno, joblist, len))
+ continue;
+
+ if (atqueue && (queue != atqueue))
+ continue;
+
+ runtimer = 60*(time_t) ctm;
+ runtime = *localtime(&runtimer);
+ strftime(timestr, TIMESIZE, "%+", &runtime);
+ if (first) {
+ printf("Date\t\t\t\tOwner\t\tQueue\tJob#\n");
+ first=0;
+ }
+ pw = getpwuid(buf.st_uid);
+
+ printf("%s\t%-16s%c%s\t%ld\n",
+ timestr,
+ pw ? pw->pw_name : "???",
+ queue,
+ (S_IXUSR & buf.st_mode) ? "":"(done)",
+ jobno);
+ }
+ PRIV_END
+ closedir(spool);
+}
+
+static void
+process_jobs(int argc, char **argv, int what)
+{
+ /* Delete every argument (job - ID) given
+ */
+ int i;
+ int rc;
+ int nofJobs;
+ int nofDone;
+ int statErrno;
+ struct stat buf;
+ DIR *spool;
+ struct dirent *dirent;
+ unsigned long ctm;
+ char queue;
+ long jobno;
+
+ nofJobs = argc - optind;
+ nofDone = 0;
+
+ PRIV_START
+
+ if (chdir(ATJOB_DIR) != 0)
+ perr("cannot change to " ATJOB_DIR);
+
+ if ((spool = opendir(".")) == NULL)
+ perr("cannot open " ATJOB_DIR);
+
+ PRIV_END
+
+ /* Loop over every file in the directory
+ */
+ while((dirent = readdir(spool)) != NULL) {
+
+ PRIV_START
+ rc = stat(dirent->d_name, &buf);
+ statErrno = errno;
+ PRIV_END
+ /* There's a race condition between readdir above and stat here:
+ * another atrm process could have removed the file from the spool
+ * directory under our nose. If this happens, stat will set errno to
+ * ENOENT, which we shouldn't treat as fatal.
+ */
+ if (rc != 0) {
+ if (statErrno == ENOENT)
+ continue;
+ else
+ perr("cannot stat in " ATJOB_DIR);
+ }
+
+ if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
+ continue;
+
+ for (i=optind; i < argc; i++) {
+ if (atoi(argv[i]) == jobno) {
+ if ((buf.st_uid != real_uid) && !(real_uid == 0))
+ errx(EXIT_FAILURE, "%s: not owner", argv[i]);
+ switch (what) {
+ case ATRM:
+
+ PRIV_START
+
+ if (unlink(dirent->d_name) != 0)
+ perr(dirent->d_name);
+
+ PRIV_END
+
+ break;
+
+ case CAT:
+ {
+ FILE *fp;
+ int ch;
+
+ PRIV_START
+
+ fp = fopen(dirent->d_name,"r");
+
+ PRIV_END
+
+ if (!fp) {
+ perr("cannot open file");
+ }
+ while((ch = getc(fp)) != EOF) {
+ putchar(ch);
+ }
+ fclose(fp);
+ }
+ break;
+
+ default:
+ errx(EXIT_FAILURE, "internal error, process_jobs = %d",
+ what);
+ }
+
+ /* All arguments have been processed
+ */
+ if (++nofDone == nofJobs)
+ goto end;
+ }
+ }
+ }
+end:
+ closedir(spool);
+} /* delete_jobs */
+
+#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
+
+static time_t
+ttime(const char *arg)
+{
+ /*
+ * This is pretty much a copy of stime_arg1() from touch.c. I changed
+ * the return value and the argument list because it's more convenient
+ * (IMO) to do everything in one place. - Joe Halpin
+ */
+ struct timeval tv[2];
+ time_t now;
+ struct tm *t;
+ int yearset;
+ char *p;
+
+ if (gettimeofday(&tv[0], NULL))
+ panic("Cannot get current time");
+
+ /* Start with the current time. */
+ now = tv[0].tv_sec;
+ if ((t = localtime(&now)) == NULL)
+ panic("localtime");
+ /* [[CC]YY]MMDDhhmm[.SS] */
+ if ((p = strchr(arg, '.')) == NULL)
+ t->tm_sec = 0; /* Seconds defaults to 0. */
+ else {
+ if (strlen(p + 1) != 2)
+ goto terr;
+ *p++ = '\0';
+ t->tm_sec = ATOI2(p);
+ }
+
+ yearset = 0;
+ switch(strlen(arg)) {
+ case 12: /* CCYYMMDDhhmm */
+ t->tm_year = ATOI2(arg);
+ t->tm_year *= 100;
+ yearset = 1;
+ /* FALLTHROUGH */
+ case 10: /* YYMMDDhhmm */
+ if (yearset) {
+ yearset = ATOI2(arg);
+ t->tm_year += yearset;
+ } else {
+ yearset = ATOI2(arg);
+ t->tm_year = yearset + 2000;
+ }
+ t->tm_year -= 1900; /* Convert to UNIX time. */
+ /* FALLTHROUGH */
+ case 8: /* MMDDhhmm */
+ t->tm_mon = ATOI2(arg);
+ --t->tm_mon; /* Convert from 01-12 to 00-11 */
+ t->tm_mday = ATOI2(arg);
+ t->tm_hour = ATOI2(arg);
+ t->tm_min = ATOI2(arg);
+ break;
+ default:
+ goto terr;
+ }
+
+ t->tm_isdst = -1; /* Figure out DST. */
+ tv[0].tv_sec = tv[1].tv_sec = mktime(t);
+ if (tv[0].tv_sec != -1)
+ return tv[0].tv_sec;
+ else
+terr:
+ panic(
+ "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
+}
+
+static long *
+get_job_list(int argc, char *argv[], int *joblen)
+{
+ int i, len;
+ long *joblist;
+ char *ep;
+
+ joblist = NULL;
+ len = argc;
+ if (len > 0) {
+ if ((joblist = malloc(len * sizeof(*joblist))) == NULL)
+ panic("out of memory");
+
+ for (i = 0; i < argc; i++) {
+ errno = 0;
+ if ((joblist[i] = strtol(argv[i], &ep, 10)) < 0 ||
+ ep == argv[i] || *ep != '\0' || errno)
+ panic("invalid job number");
+ }
+ }
+
+ *joblen = len;
+ return joblist;
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ char queue = DEFAULT_AT_QUEUE;
+ char queue_set = 0;
+ char *pgm;
+
+ int program = AT; /* our default program */
+ const char *options = "q:f:t:rmvldbc"; /* default options for at */
+ time_t timer;
+ long *joblist;
+ int joblen;
+
+ joblist = NULL;
+ joblen = 0;
+ timer = -1;
+ RELINQUISH_PRIVS
+
+ /* Eat any leading paths
+ */
+ if ((pgm = strrchr(argv[0], '/')) == NULL)
+ pgm = argv[0];
+ else
+ pgm++;
+
+ namep = pgm;
+
+ /* find out what this program is supposed to do
+ */
+ if (strcmp(pgm, "atq") == 0) {
+ program = ATQ;
+ options = "q:v";
+ }
+ else if (strcmp(pgm, "atrm") == 0) {
+ program = ATRM;
+ options = "";
+ }
+ else if (strcmp(pgm, "batch") == 0) {
+ program = BATCH;
+ options = "f:q:mv";
+ }
+
+ /* process whatever options we can process
+ */
+ opterr=1;
+ while ((c=getopt(argc, argv, options)) != -1)
+ switch (c) {
+ case 'v': /* verify time settings */
+ atverify = 1;
+ break;
+
+ case 'm': /* send mail when job is complete */
+ send_mail = 1;
+ break;
+
+ case 'f':
+ atinput = optarg;
+ break;
+
+ case 'q': /* specify queue */
+ if (strlen(optarg) > 1)
+ usage();
+
+ atqueue = queue = *optarg;
+ if (!(islower(queue)||isupper(queue)))
+ usage();
+
+ queue_set = 1;
+ break;
+
+ case 'd':
+ warnx("-d is deprecated; use -r instead");
+ /* fall through to 'r' */
+
+ case 'r':
+ if (program != AT)
+ usage();
+
+ program = ATRM;
+ options = "";
+ break;
+
+ case 't':
+ if (program != AT)
+ usage();
+ timer = ttime(optarg);
+ break;
+
+ case 'l':
+ if (program != AT)
+ usage();
+
+ program = ATQ;
+ options = "q:";
+ break;
+
+ case 'b':
+ if (program != AT)
+ usage();
+
+ program = BATCH;
+ options = "f:q:mv";
+ break;
+
+ case 'c':
+ program = CAT;
+ options = "";
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ /* end of options eating
+ */
+
+ /* select our program
+ */
+ if(!check_permission())
+ errx(EXIT_FAILURE, "you do not have permission to use this program");
+ switch (program) {
+ case ATQ:
+
+ REDUCE_PRIV(DAEMON_UID, DAEMON_GID)
+
+ if (queue_set == 0)
+ joblist = get_job_list(argc - optind, argv + optind, &joblen);
+ list_jobs(joblist, joblen);
+ break;
+
+ case ATRM:
+
+ REDUCE_PRIV(DAEMON_UID, DAEMON_GID)
+
+ process_jobs(argc, argv, ATRM);
+ break;
+
+ case CAT:
+
+ process_jobs(argc, argv, CAT);
+ break;
+
+ case AT:
+ /*
+ * If timer is > -1, then the user gave the time with -t. In that
+ * case, it's already been set. If not, set it now.
+ */
+ if (timer == -1)
+ timer = parsetime(argc, argv);
+
+ if (atverify)
+ {
+ struct tm *tm = localtime(&timer);
+ fprintf(stderr, "%s\n", asctime(tm));
+ }
+ writefile(timer, queue);
+ break;
+
+ case BATCH:
+ if (queue_set)
+ queue = toupper(queue);
+ else
+ queue = DEFAULT_BATCH_QUEUE;
+
+ if (argc > optind)
+ timer = parsetime(argc, argv);
+ else
+ timer = time(NULL);
+
+ if (atverify)
+ {
+ struct tm *tm = localtime(&timer);
+ fprintf(stderr, "%s\n", asctime(tm));
+ }
+
+ writefile(timer, queue);
+ break;
+
+ default:
+ panic("internal error");
+ break;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/usr.bin/at/at.h b/usr.bin/at/at.h
new file mode 100644
index 000000000000..4dbcf7fea32f
--- /dev/null
+++ b/usr.bin/at/at.h
@@ -0,0 +1,32 @@
+/*-
+ * at.h - header for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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.
+ */
+
+extern int fcreated;
+extern char *namep;
+extern char atfile[];
+extern char atverify;
diff --git a/usr.bin/at/at.man b/usr.bin/at/at.man
new file mode 100644
index 000000000000..a1002da6545f
--- /dev/null
+++ b/usr.bin/at/at.man
@@ -0,0 +1,377 @@
+.Dd September 18, 2023
+.Dt "AT" 1
+.Os
+.Sh NAME
+.Nm at ,
+.Nm batch ,
+.Nm atq ,
+.Nm atrm
+.Nd queue, examine or delete jobs for later execution
+.Sh SYNOPSIS
+.Nm at
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mldbv
+.Ar time
+.Nm at
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mldbv
+.Fl t
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Ar MM DD hh mm Op . Ar SS
+.Sm on
+.Nm at
+.Fl c Ar job Op Ar job ...
+.Nm at
+.Fl l Op Ar job ...
+.Nm at
+.Fl l
+.Fl q Ar queue
+.Nm at
+.Fl r Ar job Op Ar job ...
+.Pp
+.Nm atq
+.Op Fl q Ar queue
+.Op Fl v
+.Pp
+.Nm atrm
+.Ar job
+.Op Ar job ...
+.Pp
+.Nm batch
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl mv
+.Op Ar time
+.Sh DESCRIPTION
+The
+.Nm at
+and
+.Nm batch
+utilities
+read commands from standard input or a specified file which are to
+be executed at a later time, using
+.Xr sh 1 .
+.Bl -tag -width indent
+.It Nm at
+executes commands at a specified time;
+.It Nm atq
+lists the user's pending jobs, unless the user is the superuser; in that
+case, everybody's jobs are listed;
+.It Nm atrm
+deletes jobs;
+.It Nm batch
+executes commands when system load levels permit; in other words, when
+the load average drops below _LOADAVG_MX times number of active CPUs,
+or the value specified in the invocation of
+.Nm atrun .
+.El
+.Pp
+The
+.Nm at
+utility allows some moderately complex
+.Ar time
+specifications.
+It accepts times of the form
+.Ar HHMM
+or
+.Ar HH:MM
+to run a job at a specific time of day.
+(If that time is already past, the next day is assumed.)
+As an alternative, the following keywords may be specified:
+.Cm midnight ,
+.Cm noon ,
+or
+.Cm teatime
+(4pm)
+and time-of-day may be suffixed with
+.Cm AM
+or
+.Cm PM
+for running in the morning or the evening.
+The day on which the job is to be run may also be specified
+by giving a date in the form
+.Ar \%month-name day
+with an optional
+.Ar year ,
+or giving a date of the forms
+.Ar DD.MM.YYYY ,
+.Ar DD.MM.YY ,
+.Ar MM/DD/YYYY ,
+.Ar MM/DD/YY ,
+.Ar MMDDYYYY ,
+or
+.Ar MMDDYY .
+The specification of a date must follow the specification of
+the time of day.
+Time can also be specified as:
+.Op Cm now
+.Cm \&+ Ar count \%time-units ,
+where the time-units can be
+.Cm minutes ,
+.Cm hours ,
+.Cm days ,
+.Cm weeks ,
+.Cm months
+or
+.Cm years
+and
+.Nm
+may be told to run the job today by suffixing the time with
+.Cm today
+and to run the job tomorrow by suffixing the time with
+.Cm tomorrow .
+.Pp
+The
+.Nm at
+utility also supports the
+.Tn POSIX
+time format (see
+.Fl t
+option).
+.Pp
+For both
+.Nm
+and
+.Nm batch ,
+commands are read from standard input or the file specified
+with the
+.Fl f
+option and executed.
+The working directory, the environment (except for the variables
+.Ev TERM ,
+.Ev TERMCAP ,
+.Ev DISPLAY
+and
+.Ev _ )
+and the
+.Ar umask
+are retained from the time of invocation.
+An
+.Nm
+or
+.Nm batch
+command invoked from a
+.Xr su 1
+shell will retain the current userid.
+The user will be mailed standard error and standard output from his
+commands, if any.
+Mail will be sent using the command
+.Xr sendmail 8 .
+If
+.Nm
+is executed from a
+.Xr su 1
+shell, the owner of the login shell will receive the mail.
+.Pp
+The superuser may use these commands in any case.
+For other users, permission to use
+.Nm
+is determined by the files
+.Pa _PERM_PATH/at.allow
+and
+.Pa _PERM_PATH/at.deny .
+.Pp
+If the file
+.Pa _PERM_PATH/at.allow
+exists, only usernames mentioned in it are allowed to use
+.Nm .
+In these two files, a user is considered to be listed only if the user
+name has no blank or other characters before it on its line and a
+newline character immediately after the name, even at the end of
+the file.
+Other lines are ignored and may be used for comments.
+.Pp
+If
+.Pa _PERM_PATH/at.allow
+does not exist,
+.Pa _PERM_PATH/at.deny
+is checked, every username not mentioned in it is then allowed
+to use
+.Nm .
+.Pp
+If neither exists, only the superuser is allowed use of
+.Nm .
+This is the default configuration.
+.Sh IMPLEMENTATION NOTES
+Note that
+.Nm
+is implemented through the
+.Xr cron 8
+daemon by calling
+.Xr atrun 8
+every five minutes.
+This implies that the granularity of
+.Nm
+might not be optimal for every deployment.
+If a finer granularity is desired, the
+.Pa /etc/cron.d/at
+file can be edited and will be read by the system crontab, from which
+the
+.Ev SHELL
+and
+.Ev PATH
+environment variables are inherited.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl q Ar queue
+Use the specified queue.
+A queue designation consists of a single letter; valid queue designations
+range from
+.Ar a
+to
+.Ar z
+and
+.Ar A
+to
+.Ar Z .
+The
+.Ar _DEFAULT_AT_QUEUE
+queue is the default for
+.Nm
+and the
+.Ar _DEFAULT_BATCH_QUEUE
+queue for
+.Nm batch .
+Queues with higher letters run with increased niceness.
+If a job is submitted to a queue designated with an uppercase letter, it
+is treated as if it had been submitted to batch at that time.
+If
+.Nm atq
+is given a specific queue, it will only show jobs pending in that queue.
+.It Fl m
+Send mail to the user when the job has completed even if there was no
+output.
+.It Fl f Ar file
+Read the job from
+.Ar file
+rather than standard input.
+.It Fl l
+With no arguments, list all jobs for the invoking user.
+If one or more
+job numbers are given, list only those jobs.
+.It Fl d
+Is an alias for
+.Nm atrm
+(this option is deprecated; use
+.Fl r
+instead).
+.It Fl b
+Is an alias for
+.Nm batch .
+.It Fl v
+For
+.Nm atq ,
+shows completed but not yet deleted jobs in the queue; otherwise
+shows the time the job will be executed.
+.It Fl c
+Cat the jobs listed on the command line to standard output.
+.It Fl r
+Remove the specified jobs.
+.It Fl t
+Specify the job time using the \*[Px] time format.
+The argument should be in the form
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Ar MM DD hh mm Op . Ar SS
+.Sm on
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width indent -compact -offset indent
+.It Ar CC
+The first two digits of the year (the century).
+.It Ar YY
+The second two digits of the year.
+.It Ar MM
+The month of the year, from 1 to 12.
+.It Ar DD
+the day of the month, from 1 to 31.
+.It Ar hh
+The hour of the day, from 0 to 23.
+.It Ar mm
+The minute of the hour, from 0 to 59.
+.It Ar SS
+The second of the minute, from 0 to 60.
+.El
+.Pp
+If the
+.Ar CC
+and
+.Ar YY
+letter pairs are not specified, the values default to the current
+year.
+If the
+.Ar SS
+letter pair is not specified, the value defaults to 0.
+.El
+.Sh FILES
+.Bl -tag -width _ATJOB_DIR/_LOCKFILE -compact
+.It Pa _ATJOB_DIR
+directory containing job files
+.It Pa _ATSPOOL_DIR
+directory containing output spool files
+.It Pa /var/run/utx.active
+login records
+.It Pa _PERM_PATH/at.allow
+allow permission control
+.It Pa _PERM_PATH/at.deny
+deny permission control
+.It Pa _ATJOB_DIR/_LOCKFILE
+job-creation lock file
+.El
+.Sh EXAMPLES
+To run a job at 4pm three days from now, use:
+.Bd -literal -offset indent
+at 4pm + 3 days
+.Ed
+.Pp
+To run a job at 10:00am on July 31, use:
+.Bd -literal -offset indent
+at 10am Jul 31
+.Ed
+.Pp
+To run a job at 1am tomorrow, use:
+.Bd -literal -offset indent
+at 1am tomorrow
+.Ed
+.Pp
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr sh 1 ,
+.Xr umask 2 ,
+.Xr atrun 8 ,
+.Xr cron 8 ,
+.Xr sendmail 8
+.Sh AUTHORS
+.An -nosplit
+At was mostly written by
+.An Thomas Koenig Aq Mt ig25@rz.uni-karlsruhe.de .
+The time parsing routines are by
+.An David Parsons Aq Mt orc@pell.chi.il.us ,
+with minor enhancements by
+.An Joe Halpin Aq Mt joe.halpin@attbi.com .
+.Sh BUGS
+If the file
+.Pa /var/run/utx.active
+is not available or corrupted, or if the user is not logged on at the
+time
+.Nm
+is invoked, the mail is sent to the userid found
+in the environment variable
+.Ev LOGNAME .
+If that is undefined or empty, the current userid is assumed.
+.Pp
+The
+.Nm at
+and
+.Nm batch
+utilities
+as presently implemented are not suitable when users are competing for
+resources.
+If this is the case, another batch system such as
+.Em nqs
+may be more suitable.
+.Pp
+Specifying a date past 2038 may not work on some systems.
diff --git a/usr.bin/at/atrun b/usr.bin/at/atrun
new file mode 100644
index 000000000000..0e0b9c3c5151
--- /dev/null
+++ b/usr.bin/at/atrun
@@ -0,0 +1,6 @@
+#
+SHELL=/bin/sh
+PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
+
+# See crontab(5) for field format.
+*/5 * * * * root /usr/libexec/atrun
diff --git a/usr.bin/at/panic.c b/usr.bin/at/panic.c
new file mode 100644
index 000000000000..e72cae4596fa
--- /dev/null
+++ b/usr.bin/at/panic.c
@@ -0,0 +1,93 @@
+/*-
+ * panic.c - terminate fast in case of error
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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/cdefs.h>
+/* System Headers */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Local headers */
+
+#include "panic.h"
+#include "privs.h"
+#include "at.h"
+
+/* External variables */
+
+/* Global functions */
+
+void
+panic(const char *a)
+{
+/* Something fatal has happened, print error message and exit.
+ */
+ if (fcreated) {
+ PRIV_START
+ unlink(atfile);
+ PRIV_END
+ }
+
+ errx(EXIT_FAILURE, "%s", a);
+}
+
+void
+perr(const char *a)
+{
+/* Some operating system error; print error message and exit.
+ */
+ int serrno = errno;
+
+ if (fcreated) {
+ PRIV_START
+ unlink(atfile);
+ PRIV_END
+ }
+
+ errno = serrno;
+ err(EXIT_FAILURE, "%s", a);
+}
+
+void
+usage(void)
+{
+ /* Print usage and exit. */
+ fprintf(stderr, "usage: at [-q x] [-f file] [-m] time\n"
+ " at -c job [job ...]\n"
+ " at [-f file] -t [[CC]YY]MMDDhhmm[.SS]\n"
+ " at -r job [job ...]\n"
+ " at -l -q queuename\n"
+ " at -l [job ...]\n"
+ " atq [-q x] [-v]\n"
+ " atrm job [job ...]\n"
+ " batch [-f file] [-m]\n");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/at/panic.h b/usr.bin/at/panic.h
new file mode 100644
index 000000000000..e9316621d98c
--- /dev/null
+++ b/usr.bin/at/panic.h
@@ -0,0 +1,33 @@
+/*-
+ * panic.h - header for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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/cdefs.h>
+
+void panic(const char *a) __dead2;
+void perr(const char *a) __dead2;
+void usage(void) __dead2;
diff --git a/usr.bin/at/parsetime.c b/usr.bin/at/parsetime.c
new file mode 100644
index 000000000000..a9223f3fb256
--- /dev/null
+++ b/usr.bin/at/parsetime.c
@@ -0,0 +1,674 @@
+/*-
+ * parsetime.c - parse time for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993, 1994 Thomas Koenig
+ *
+ * modifications for English-language times
+ * Copyright (C) 1993 David Parsons
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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.
+ *
+ * at [NOW] PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS
+ * /NUMBER [DOT NUMBER] [AM|PM]\ /[MONTH NUMBER [NUMBER]] \
+ * |NOON | |[TOMORROW] |
+ * |MIDNIGHT | |[DAY OF WEEK] |
+ * \TEATIME / |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
+ * \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
+ */
+
+#include <sys/cdefs.h>
+/* System Headers */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#ifndef __FreeBSD__
+#include <getopt.h>
+#endif
+
+/* Local headers */
+
+#include "at.h"
+#include "panic.h"
+#include "parsetime.h"
+
+
+/* Structures and unions */
+
+enum { /* symbols */
+ MIDNIGHT, NOON, TEATIME,
+ PM, AM, TOMORROW, TODAY, NOW,
+ MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS,
+ NUMBER, PLUS, MINUS, DOT, SLASH, ID, JUNK,
+ JAN, FEB, MAR, APR, MAY, JUN,
+ JUL, AUG, SEP, OCT, NOV, DEC,
+ SUN, MON, TUE, WED, THU, FRI, SAT
+ };
+
+/* parse translation table - table driven parsers can be your FRIEND!
+ */
+static const struct {
+ const char *name; /* token name */
+ int value; /* token id */
+ int plural; /* is this plural? */
+} Specials[] = {
+ { "midnight", MIDNIGHT,0 }, /* 00:00:00 of today or tomorrow */
+ { "noon", NOON,0 }, /* 12:00:00 of today or tomorrow */
+ { "teatime", TEATIME,0 }, /* 16:00:00 of today or tomorrow */
+ { "am", AM,0 }, /* morning times for 0-12 clock */
+ { "pm", PM,0 }, /* evening times for 0-12 clock */
+ { "tomorrow", TOMORROW,0 }, /* execute 24 hours from time */
+ { "today", TODAY, 0 }, /* execute today - don't advance time */
+ { "now", NOW,0 }, /* opt prefix for PLUS */
+
+ { "minute", MINUTES,0 }, /* minutes multiplier */
+ { "minutes", MINUTES,1 }, /* (pluralized) */
+ { "hour", HOURS,0 }, /* hours ... */
+ { "hours", HOURS,1 }, /* (pluralized) */
+ { "day", DAYS,0 }, /* days ... */
+ { "days", DAYS,1 }, /* (pluralized) */
+ { "week", WEEKS,0 }, /* week ... */
+ { "weeks", WEEKS,1 }, /* (pluralized) */
+ { "month", MONTHS,0 }, /* month ... */
+ { "months", MONTHS,1 }, /* (pluralized) */
+ { "year", YEARS,0 }, /* year ... */
+ { "years", YEARS,1 }, /* (pluralized) */
+ { "jan", JAN,0 },
+ { "feb", FEB,0 },
+ { "mar", MAR,0 },
+ { "apr", APR,0 },
+ { "may", MAY,0 },
+ { "jun", JUN,0 },
+ { "jul", JUL,0 },
+ { "aug", AUG,0 },
+ { "sep", SEP,0 },
+ { "oct", OCT,0 },
+ { "nov", NOV,0 },
+ { "dec", DEC,0 },
+ { "january", JAN,0 },
+ { "february", FEB,0 },
+ { "march", MAR,0 },
+ { "april", APR,0 },
+ { "may", MAY,0 },
+ { "june", JUN,0 },
+ { "july", JUL,0 },
+ { "august", AUG,0 },
+ { "september", SEP,0 },
+ { "october", OCT,0 },
+ { "november", NOV,0 },
+ { "december", DEC,0 },
+ { "sunday", SUN, 0 },
+ { "sun", SUN, 0 },
+ { "monday", MON, 0 },
+ { "mon", MON, 0 },
+ { "tuesday", TUE, 0 },
+ { "tue", TUE, 0 },
+ { "wednesday", WED, 0 },
+ { "wed", WED, 0 },
+ { "thursday", THU, 0 },
+ { "thu", THU, 0 },
+ { "friday", FRI, 0 },
+ { "fri", FRI, 0 },
+ { "saturday", SAT, 0 },
+ { "sat", SAT, 0 },
+} ;
+
+/* File scope variables */
+
+static char **scp; /* scanner - pointer at arglist */
+static char scc; /* scanner - count of remaining arguments */
+static char *sct; /* scanner - next char pointer in current argument */
+static int need; /* scanner - need to advance to next argument */
+
+static char *sc_token; /* scanner - token buffer */
+static size_t sc_len; /* scanner - length of token buffer */
+static int sc_tokid; /* scanner - token id */
+static int sc_tokplur; /* scanner - is token plural? */
+
+/* Local functions */
+
+/*
+ * parse a token, checking if it's something special to us
+ */
+static int
+parse_token(char *arg)
+{
+ size_t i;
+
+ for (i=0; i<(sizeof Specials/sizeof Specials[0]); i++)
+ if (strcasecmp(Specials[i].name, arg) == 0) {
+ sc_tokplur = Specials[i].plural;
+ return sc_tokid = Specials[i].value;
+ }
+
+ /* not special - must be some random id */
+ return ID;
+} /* parse_token */
+
+
+/*
+ * init_scanner() sets up the scanner to eat arguments
+ */
+static void
+init_scanner(int argc, char **argv)
+{
+ scp = argv;
+ scc = argc;
+ need = 1;
+ sc_len = 1;
+ while (argc-- > 0)
+ sc_len += strlen(*argv++);
+
+ if ((sc_token = malloc(sc_len)) == NULL)
+ errx(EXIT_FAILURE, "virtual memory exhausted");
+} /* init_scanner */
+
+/*
+ * token() fetches a token from the input stream
+ */
+static int
+token(void)
+{
+ int idx;
+
+ while (1) {
+ memset(sc_token, 0, sc_len);
+ sc_tokid = EOF;
+ sc_tokplur = 0;
+ idx = 0;
+
+ /* if we need to read another argument, walk along the argument list;
+ * when we fall off the arglist, we'll just return EOF forever
+ */
+ if (need) {
+ if (scc < 1)
+ return sc_tokid;
+ sct = *scp;
+ scp++;
+ scc--;
+ need = 0;
+ }
+ /* eat whitespace now - if we walk off the end of the argument,
+ * we'll continue, which puts us up at the top of the while loop
+ * to fetch the next argument in
+ */
+ while (isspace(*sct))
+ ++sct;
+ if (!*sct) {
+ need = 1;
+ continue;
+ }
+
+ /* preserve the first character of the new token
+ */
+ sc_token[0] = *sct++;
+
+ /* then see what it is
+ */
+ if (isdigit(sc_token[0])) {
+ while (isdigit(*sct))
+ sc_token[++idx] = *sct++;
+ sc_token[++idx] = 0;
+ return sc_tokid = NUMBER;
+ }
+ else if (isalpha(sc_token[0])) {
+ while (isalpha(*sct))
+ sc_token[++idx] = *sct++;
+ sc_token[++idx] = 0;
+ return parse_token(sc_token);
+ }
+ else if (sc_token[0] == ':' || sc_token[0] == '.')
+ return sc_tokid = DOT;
+ else if (sc_token[0] == '+')
+ return sc_tokid = PLUS;
+ else if (sc_token[0] == '-')
+ return sc_tokid = MINUS;
+ else if (sc_token[0] == '/')
+ return sc_tokid = SLASH;
+ else
+ return sc_tokid = JUNK;
+ } /* while (1) */
+} /* token */
+
+
+/*
+ * plonk() gives an appropriate error message if a token is incorrect
+ */
+static void
+plonk(int tok)
+{
+ panic((tok == EOF) ? "incomplete time"
+ : "garbled time");
+} /* plonk */
+
+
+/*
+ * expect() gets a token and dies most horribly if it's not the token we want
+ */
+static void
+expect(int desired)
+{
+ if (token() != desired)
+ plonk(sc_tokid); /* and we die here... */
+} /* expect */
+
+
+/*
+ * plus_or_minus() holds functionality common to plus() and minus()
+ */
+static void
+plus_or_minus(struct tm *tm, int delay)
+{
+ int expectplur;
+
+ expectplur = (delay != 1 && delay != -1) ? 1 : 0;
+
+ switch (token()) {
+ case YEARS:
+ tm->tm_year += delay;
+ break;
+ case MONTHS:
+ tm->tm_mon += delay;
+ break;
+ case WEEKS:
+ delay *= 7;
+ case DAYS:
+ tm->tm_mday += delay;
+ break;
+ case HOURS:
+ tm->tm_hour += delay;
+ break;
+ case MINUTES:
+ tm->tm_min += delay;
+ break;
+ default:
+ plonk(sc_tokid);
+ break;
+ }
+
+ if (expectplur != sc_tokplur)
+ warnx("pluralization is wrong");
+
+ tm->tm_isdst = -1;
+ if (mktime(tm) < 0)
+ plonk(sc_tokid);
+} /* plus_or_minus */
+
+
+/*
+ * plus() parses a now + time
+ *
+ * at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS|MONTHS|YEARS]
+ *
+ */
+static void
+plus(struct tm *tm)
+{
+ int delay;
+
+ expect(NUMBER);
+
+ delay = atoi(sc_token);
+ plus_or_minus(tm, delay);
+} /* plus */
+
+
+/*
+ * minus() is like plus but can not be used with NOW
+ */
+static void
+minus(struct tm *tm)
+{
+ int delay;
+
+ expect(NUMBER);
+
+ delay = -atoi(sc_token);
+ plus_or_minus(tm, delay);
+} /* minus */
+
+
+/*
+ * tod() computes the time of day
+ * [NUMBER [DOT NUMBER] [AM|PM]]
+ */
+static void
+tod(struct tm *tm)
+{
+ int hour, minute = 0;
+ int tlen;
+
+ hour = atoi(sc_token);
+ tlen = strlen(sc_token);
+
+ /* first pick out the time of day - if it's 4 digits, we assume
+ * a HHMM time, otherwise it's HH DOT MM time
+ */
+ if (token() == DOT) {
+ expect(NUMBER);
+ minute = atoi(sc_token);
+ if (minute > 59)
+ panic("garbled time");
+ token();
+ }
+ else if (tlen == 4) {
+ minute = hour%100;
+ if (minute > 59)
+ panic("garbled time");
+ hour = hour/100;
+ }
+
+ /* check if an AM or PM specifier was given
+ */
+ if (sc_tokid == AM || sc_tokid == PM) {
+ if (hour > 12)
+ panic("garbled time");
+
+ if (sc_tokid == PM) {
+ if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */
+ hour += 12;
+ } else {
+ if (hour == 12) /* 12:xx AM is 00:xx, not 12:xx */
+ hour = 0;
+ }
+ token();
+ }
+ else if (hour > 23)
+ panic("garbled time");
+
+ /* if we specify an absolute time, we don't want to bump the day even
+ * if we've gone past that time - but if we're specifying a time plus
+ * a relative offset, it's okay to bump things
+ */
+ if ((sc_tokid == EOF || sc_tokid == PLUS || sc_tokid == MINUS) &&
+ tm->tm_hour > hour) {
+ tm->tm_mday++;
+ tm->tm_wday++;
+ }
+
+ tm->tm_hour = hour;
+ tm->tm_min = minute;
+ if (tm->tm_hour == 24) {
+ tm->tm_hour = 0;
+ tm->tm_mday++;
+ }
+} /* tod */
+
+
+/*
+ * assign_date() assigns a date, wrapping to next year if needed
+ */
+static void
+assign_date(struct tm *tm, long mday, long mon, long year)
+{
+
+ /*
+ * Convert year into tm_year format (year - 1900).
+ * We may be given the year in 2 digit, 4 digit, or tm_year format.
+ */
+ if (year != -1) {
+ if (year >= 1900)
+ year -= 1900; /* convert from 4 digit year */
+ else if (year < 100) {
+ /* convert from 2 digit year */
+ struct tm *lt;
+ time_t now;
+
+ time(&now);
+ lt = localtime(&now);
+
+ /* Convert to tm_year assuming current century */
+ year += (lt->tm_year / 100) * 100;
+
+ if (year == lt->tm_year - 1) year++;
+ else if (year < lt->tm_year)
+ year += 100; /* must be in next century */
+ }
+ }
+
+ if (year < 0 &&
+ (tm->tm_mon > mon ||(tm->tm_mon == mon && tm->tm_mday > mday)))
+ year = tm->tm_year + 1;
+
+ tm->tm_mday = mday;
+ tm->tm_mon = mon;
+
+ if (year >= 0)
+ tm->tm_year = year;
+} /* assign_date */
+
+
+/*
+ * month() picks apart a month specification
+ *
+ * /[<month> NUMBER [NUMBER]] \
+ * |[TOMORROW] |
+ * |[DAY OF WEEK] |
+ * |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
+ * \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
+ */
+static void
+month(struct tm *tm)
+{
+ long year= (-1);
+ long mday = 0, wday, mon;
+ int tlen;
+
+ switch (sc_tokid) {
+ case PLUS:
+ plus(tm);
+ break;
+ case MINUS:
+ minus(tm);
+ break;
+
+ case TOMORROW:
+ /* do something tomorrow */
+ tm->tm_mday ++;
+ tm->tm_wday ++;
+ case TODAY: /* force ourselves to stay in today - no further processing */
+ token();
+ break;
+
+ case JAN: case FEB: case MAR: case APR: case MAY: case JUN:
+ case JUL: case AUG: case SEP: case OCT: case NOV: case DEC:
+ /* do month mday [year]
+ */
+ mon = (sc_tokid-JAN);
+ expect(NUMBER);
+ mday = atol(sc_token);
+ if (token() == NUMBER) {
+ year = atol(sc_token);
+ token();
+ }
+ assign_date(tm, mday, mon, year);
+ break;
+
+ case SUN: case MON: case TUE:
+ case WED: case THU: case FRI:
+ case SAT:
+ /* do a particular day of the week
+ */
+ wday = (sc_tokid-SUN);
+
+ mday = tm->tm_mday;
+
+ /* if this day is < today, then roll to next week
+ */
+ if (wday < tm->tm_wday)
+ mday += 7 - (tm->tm_wday - wday);
+ else
+ mday += (wday - tm->tm_wday);
+
+ tm->tm_wday = wday;
+
+ assign_date(tm, mday, tm->tm_mon, tm->tm_year);
+ break;
+
+ case NUMBER:
+ /* get numeric MMDDYY, mm/dd/yy, or dd.mm.yy
+ */
+ tlen = strlen(sc_token);
+ mon = atol(sc_token);
+ token();
+
+ if (sc_tokid == SLASH || sc_tokid == DOT) {
+ int sep;
+
+ sep = sc_tokid;
+ expect(NUMBER);
+ mday = atol(sc_token);
+ if (token() == sep) {
+ expect(NUMBER);
+ year = atol(sc_token);
+ token();
+ }
+
+ /* flip months and days for European timing
+ */
+ if (sep == DOT) {
+ int x = mday;
+ mday = mon;
+ mon = x;
+ }
+ }
+ else if (tlen == 6 || tlen == 8) {
+ if (tlen == 8) {
+ year = (mon % 10000) - 1900;
+ mon /= 10000;
+ }
+ else {
+ year = mon % 100;
+ mon /= 100;
+ }
+ mday = mon % 100;
+ mon /= 100;
+ }
+ else
+ panic("garbled time");
+
+ mon--;
+ if (mon < 0 || mon > 11 || mday < 1 || mday > 31)
+ panic("garbled time");
+
+ assign_date(tm, mday, mon, year);
+ break;
+ } /* case */
+} /* month */
+
+
+/* Global functions */
+
+time_t
+parsetime(int argc, char **argv)
+{
+/* Do the argument parsing, die if necessary, and return the time the job
+ * should be run.
+ */
+ time_t nowtimer, runtimer;
+ struct tm nowtime, runtime;
+ int hr = 0;
+ /* this MUST be initialized to zero for midnight/noon/teatime */
+
+ nowtimer = time(NULL);
+ nowtime = *localtime(&nowtimer);
+
+ runtime = nowtime;
+ runtime.tm_sec = 0;
+ runtime.tm_isdst = 0;
+
+ if (argc <= optind)
+ usage();
+
+ init_scanner(argc-optind, argv+optind);
+
+ switch (token()) {
+ case NOW:
+ if (scc < 1) {
+ return nowtimer;
+ }
+ /* now is optional prefix for PLUS tree */
+ expect(PLUS);
+ /* FALLTHROUGH */
+ case PLUS:
+ plus(&runtime);
+ break;
+
+ /* MINUS is different from PLUS in that NOW is not
+ * an optional prefix for it
+ */
+ case MINUS:
+ minus(&runtime);
+ break;
+ case NUMBER:
+ tod(&runtime);
+ month(&runtime);
+ break;
+
+ /* evil coding for TEATIME|NOON|MIDNIGHT - we've initialised
+ * hr to zero up above, then fall into this case in such a
+ * way so we add +12 +4 hours to it for teatime, +12 hours
+ * to it for noon, and nothing at all for midnight, then
+ * set our runtime to that hour before leaping into the
+ * month scanner
+ */
+ case TEATIME:
+ hr += 4;
+ /* FALLTHROUGH */
+ case NOON:
+ hr += 12;
+ /* FALLTHROUGH */
+ case MIDNIGHT:
+ if (runtime.tm_hour >= hr) {
+ runtime.tm_mday++;
+ runtime.tm_wday++;
+ }
+ runtime.tm_hour = hr;
+ runtime.tm_min = 0;
+ token();
+ /* FALLTHROUGH to month setting */
+ default:
+ month(&runtime);
+ break;
+ } /* ugly case statement */
+ expect(EOF);
+
+ /* convert back to time_t
+ */
+ runtime.tm_isdst = -1;
+ runtimer = mktime(&runtime);
+
+ if (runtimer < 0)
+ panic("garbled time");
+
+ if (nowtimer > runtimer)
+ panic("trying to travel back in time");
+
+ return runtimer;
+} /* parsetime */
diff --git a/usr.bin/at/parsetime.h b/usr.bin/at/parsetime.h
new file mode 100644
index 000000000000..d99af527d845
--- /dev/null
+++ b/usr.bin/at/parsetime.h
@@ -0,0 +1,29 @@
+/*-
+ * at.h - header for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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.
+ */
+
+time_t parsetime(int argc, char **argv);
diff --git a/usr.bin/at/perm.c b/usr.bin/at/perm.c
new file mode 100644
index 000000000000..9e26dbe3563d
--- /dev/null
+++ b/usr.bin/at/perm.c
@@ -0,0 +1,125 @@
+/*-
+ * perm.c - check user permission for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1994 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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/cdefs.h>
+/* System Headers */
+
+#include <sys/types.h>
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Local headers */
+
+#include "at.h"
+#include "perm.h"
+#include "privs.h"
+
+/* Macros */
+
+#define MAXUSERID 10
+
+/* Structures and unions */
+
+/* Function declarations */
+
+static int check_for_user(FILE *fp,const char *name);
+
+/* Local functions */
+
+static int check_for_user(FILE *fp,const char *name)
+{
+ char *buffer;
+ size_t len;
+ int found = 0;
+
+ len = strlen(name);
+ if ((buffer = malloc(len+2)) == NULL)
+ errx(EXIT_FAILURE, "virtual memory exhausted");
+
+ while(fgets(buffer, len+2, fp) != NULL)
+ {
+ if ((strncmp(name, buffer, len) == 0) &&
+ (buffer[len] == '\n'))
+ {
+ found = 1;
+ break;
+ }
+ }
+ fclose(fp);
+ free(buffer);
+ return found;
+}
+/* Global functions */
+int check_permission(void)
+{
+ FILE *fp;
+ uid_t uid = geteuid();
+ struct passwd *pentry;
+
+ if (uid==0)
+ return 1;
+
+ if ((pentry = getpwuid(uid)) == NULL)
+ err(EXIT_FAILURE, "cannot access user database");
+
+ PRIV_START
+
+ fp=fopen(PERM_PATH "at.allow","r");
+
+ PRIV_END
+
+ if (fp != NULL)
+ {
+ return check_for_user(fp, pentry->pw_name);
+ }
+ else if (errno == ENOENT)
+ {
+
+ PRIV_START
+
+ fp=fopen(PERM_PATH "at.deny", "r");
+
+ PRIV_END
+
+ if (fp != NULL)
+ {
+ return !check_for_user(fp, pentry->pw_name);
+ }
+ else if (errno != ENOENT)
+ warn("at.deny");
+ }
+ else
+ warn("at.allow");
+ return 0;
+}
diff --git a/usr.bin/at/perm.h b/usr.bin/at/perm.h
new file mode 100644
index 000000000000..41c1b9584de7
--- /dev/null
+++ b/usr.bin/at/perm.h
@@ -0,0 +1,29 @@
+/*-
+ * perm.h - header for at(1)
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1994 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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 check_permission(void);
diff --git a/usr.bin/at/privs.h b/usr.bin/at/privs.h
new file mode 100644
index 000000000000..6f3d3a2da882
--- /dev/null
+++ b/usr.bin/at/privs.h
@@ -0,0 +1,107 @@
+/*-
+ * privs.h - header for privileged operations
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993 Thomas Koenig
+ *
+ * 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. The name of the author(s) 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(S) ``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(S) 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, WETHER 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 _PRIVS_H
+#define _PRIVS_H
+
+#include <unistd.h>
+
+/* Relinquish privileges temporarily for a setuid or setgid program
+ * with the option of getting them back later. This is done by
+ * utilizing POSIX saved user and group IDs. Call RELINQUISH_PRIVS once
+ * at the beginning of the main program. This will cause all operations
+ * to be executed with the real userid. When you need the privileges
+ * of the setuid/setgid invocation, call PRIV_START; when you no longer
+ * need it, call PRIV_END. Note that it is an error to call PRIV_START
+ * and not PRIV_END within the same function.
+ *
+ * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running
+ * as root, and you want to drop back the effective userid to a
+ * and the effective group id to b, with the option to get them back
+ * later.
+ *
+ * If you no longer need root privileges, but those of some other
+ * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective
+ * is the user's.
+ *
+ * Problems: Do not use return between PRIV_START and PRIV_END; this
+ * will cause the program to continue running in an unprivileged
+ * state.
+ *
+ * It is NOT safe to call exec(), system() or popen() with a user-
+ * supplied program (i.e. without carefully checking PATH and any
+ * library load paths) with relinquished privileges; the called program
+ * can acquire them just as easily. Set both effective and real userid
+ * to the real userid before calling any of them.
+ */
+
+extern uid_t real_uid, effective_uid;
+extern gid_t real_gid, effective_gid;
+
+#ifdef MAIN
+uid_t real_uid, effective_uid;
+gid_t real_gid, effective_gid;
+#endif
+
+#define RELINQUISH_PRIVS { \
+ real_uid = getuid(); \
+ effective_uid = geteuid(); \
+ real_gid = getgid(); \
+ effective_gid = getegid(); \
+ if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
+ if (setegid(real_gid) != 0) err(1, "setegid failed"); \
+}
+
+#define RELINQUISH_PRIVS_ROOT(a, b) { \
+ real_uid = (a); \
+ effective_uid = geteuid(); \
+ real_gid = (b); \
+ effective_gid = getegid(); \
+ if (setegid(real_gid) != 0) err(1, "setegid failed"); \
+ if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
+}
+
+#define PRIV_START { \
+ if (seteuid(effective_uid) != 0) err(1, "seteuid failed"); \
+ if (setegid(effective_gid) != 0) err(1, "setegid failed"); \
+}
+
+#define PRIV_END { \
+ if (setegid(real_gid) != 0) err(1, "setegid failed"); \
+ if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
+}
+
+#define REDUCE_PRIV(a, b) { \
+ PRIV_START \
+ effective_uid = (a); \
+ effective_gid = (b); \
+ if (setregid((gid_t)-1, effective_gid) != 0) err(1, "setregid failed"); \
+ if (setreuid((uid_t)-1, effective_uid) != 0) err(1, "setreuid failed"); \
+ PRIV_END \
+}
+#endif
diff --git a/usr.bin/awk/Makefile b/usr.bin/awk/Makefile
new file mode 100644
index 000000000000..c9d61e594146
--- /dev/null
+++ b/usr.bin/awk/Makefile
@@ -0,0 +1,36 @@
+.include <src.opts.mk>
+
+AWKSRC= ${SRCTOP}/contrib/one-true-awk
+.PATH: ${AWKSRC}
+
+PROG= awk
+SRCS= awkgram.y b.c lex.c lib.c main.c parse.c proctab.c run.c tran.c awkgram.tab.h
+
+CFLAGS+= -DHAS_ISBLANK -I. -I${AWKSRC} -DFOPEN_MAX=64
+
+WARNS?= 1
+
+LIBADD= m
+
+LINKS= ${BINDIR}/awk ${BINDIR}/nawk
+MLINKS= awk.1 nawk.1
+
+CLEANFILES= maketab proctab.c awkgram.tab.h
+
+awkgram.tab.h: awkgram.h
+ ln -sf ${.ALLSRC:M*.h} ${.TARGET}
+
+proctab.c: awkgram.tab.h
+ ${BTOOLSPATH:U.}/maketab awkgram.tab.h > proctab.c
+
+.if ${MACHINE} == "host" || ${MK_DIRDEPS_BUILD} == "no"
+DEPENDOBJS+= maketab
+build-tools: maketab
+proctab.c: maketab
+maketab: awkgram.tab.h ${BUILD_TOOLS_META}
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/awk/Makefile.depend b/usr.bin/awk/Makefile.depend
new file mode 100644
index 000000000000..661c5ac27e5f
--- /dev/null
+++ b/usr.bin/awk/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+ usr.bin/awk.host \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/awk/Makefile.depend.host b/usr.bin/awk/Makefile.depend.host
new file mode 100644
index 000000000000..bcfd629f3335
--- /dev/null
+++ b/usr.bin/awk/Makefile.depend.host
@@ -0,0 +1,11 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ usr.bin/yacc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/awk/Makefile.depend.options b/usr.bin/awk/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/awk/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/awk/awk.1 b/usr.bin/awk/awk.1
new file mode 100644
index 000000000000..65c91738966b
--- /dev/null
+++ b/usr.bin/awk/awk.1
@@ -0,0 +1,855 @@
+.\" $OpenBSD: awk.1,v 1.44 2015/09/14 20:06:58 schwarze Exp $
+.\"
+.\" Copyright (C) Lucent Technologies 1997
+.\" All Rights Reserved
+.\"
+.\" Permission to use, copy, modify, and distribute this software and
+.\" its documentation for any purpose and without fee is hereby
+.\" granted, provided that the above copyright notice appear in all
+.\" copies and that both that the copyright notice and this
+.\" permission notice and warranty disclaimer appear in supporting
+.\" documentation, and that the name Lucent Technologies or any of
+.\" its entities not be used in advertising or publicity pertaining
+.\" to distribution of the software without specific, written prior
+.\" permission.
+.\"
+.\" LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+.\" IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+.\" SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+.\" ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+.\" THIS SOFTWARE.
+.Dd July 30, 2021
+.Dt AWK 1
+.Os
+.Sh NAME
+.Nm awk
+.Nd pattern-directed scanning and processing language
+.Sh SYNOPSIS
+.Nm awk
+.Op Fl safe
+.Op Fl version
+.Op Fl d Ns Op Ar n
+.Op Fl F Ar fs
+.Op Fl v Ar var Ns = Ns Ar value
+.Op Ar prog | Fl f Ar progfile
+.Ar
+.Sh DESCRIPTION
+.Nm
+scans each input
+.Ar file
+for lines that match any of a set of patterns specified literally in
+.Ar prog
+or in one or more files specified as
+.Fl f Ar progfile .
+With each pattern there can be an associated action that will be performed
+when a line of a
+.Ar file
+matches the pattern.
+Each line is matched against the
+pattern portion of every pattern-action statement;
+the associated action is performed for each matched pattern.
+The file name
+.Sq -
+means the standard input.
+Any
+.Ar file
+of the form
+.Ar var Ns = Ns Ar value
+is treated as an assignment, not a filename,
+and is executed at the time it would have been opened if it were a filename.
+.Pp
+The options are as follows:
+.Bl -tag -width "-safe "
+.It Fl d Ns Op Ar n
+Debug mode.
+Set debug level to
+.Ar n ,
+or 1 if
+.Ar n
+is not specified.
+A value greater than 1 causes
+.Nm
+to dump core on fatal errors.
+.It Fl F Ar fs
+Define the input field separator to be the regular expression
+.Ar fs .
+.It Fl f Ar progfile
+Read program code from the specified file
+.Ar progfile
+instead of from the command line.
+.It Fl safe
+Disable file output
+.Pf ( Ic print No > ,
+.Ic print No >> ) ,
+process creation
+.Po
+.Ar cmd | Ic getline ,
+.Ic print | ,
+.Ic system
+.Pc
+and access to the environment
+.Pf ( Va ENVIRON ;
+see the section on variables below).
+This is a first
+.Pq and not very reliable
+approximation to a
+.Dq safe
+version of
+.Nm .
+.It Fl version
+Print the version number of
+.Nm
+to standard output and exit.
+.It Fl v Ar var Ns = Ns Ar value
+Assign
+.Ar value
+to variable
+.Ar var
+before
+.Ar prog
+is executed;
+any number of
+.Fl v
+options may be present.
+.El
+.Pp
+The input is normally made up of input lines
+.Pq records
+separated by newlines, or by the value of
+.Va RS .
+If
+.Va RS
+is null, then any number of blank lines are used as the record separator,
+and newlines are used as field separators
+(in addition to the value of
+.Va FS ) .
+This is convenient when working with multi-line records.
+.Pp
+An input line is normally made up of fields separated by whitespace,
+or by the extended regular expression
+.Va FS
+as described below.
+The fields are denoted
+.Va $1 , $2 , ... ,
+while
+.Va $0
+refers to the entire line.
+If
+.Va FS
+is null, the input line is split into one field per character.
+While both gawk and mawk have the same behavior, it is unspecified in the
+.St -p1003.1-2008
+standard.
+If
+.Va FS
+is a single space, then leading and trailing blank and newline characters are
+skipped.
+Fields are delimited by one or more blank or newline characters.
+A blank character is a space or a tab.
+If
+.Va FS
+is a single character, other than space, fields are delimited by each single
+occurrence of that character.
+The
+.Va FS
+variable defaults to a single space.
+.Pp
+Normally, any number of blanks separate fields.
+In order to set the field separator to a single blank, use the
+.Fl F
+option with a value of
+.Sq [\ \&] .
+If a field separator of
+.Sq t
+is specified,
+.Nm
+treats it as if
+.Sq \et
+had been specified and uses
+.Aq TAB
+as the field separator.
+In order to use a literal
+.Sq t
+as the field separator, use the
+.Fl F
+option with a value of
+.Sq [t] .
+.Pp
+A pattern-action statement has the form
+.Pp
+.D1 Ar pattern Ic \&{ Ar action Ic \&}
+.Pp
+A missing
+.Ic \&{ Ar action Ic \&}
+means print the line;
+a missing pattern always matches.
+Pattern-action statements are separated by newlines or semicolons.
+.Pp
+Newlines are permitted after a terminating statement or following a comma
+.Pq Sq ,\& ,
+an open brace
+.Pq Sq { ,
+a logical AND
+.Pq Sq && ,
+a logical OR
+.Pq Sq || ,
+after the
+.Sq do
+or
+.Sq else
+keywords,
+or after the closing parenthesis of an
+.Sq if ,
+.Sq for ,
+or
+.Sq while
+statement.
+Additionally, a backslash
+.Pq Sq \e
+can be used to escape a newline between tokens.
+.Pp
+An action is a sequence of statements.
+A statement can be one of the following:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Ic if Ar ( expression ) Ar statement Op Ic else Ar statement
+.It Ic while Ar ( expression ) Ar statement
+.It Ic for Ar ( expression ; expression ; expression ) statement
+.It Ic for Ar ( var Ic in Ar array ) statement
+.It Ic do Ar statement Ic while Ar ( expression )
+.It Ic break
+.It Ic continue
+.It Xo Ic {
+.Op Ar statement ...
+.Ic }
+.Xc
+.It Xo Ar expression
+.No # commonly
+.Ar var No = Ar expression
+.Xc
+.It Xo Ic print
+.Op Ar expression-list
+.Op > Ns Ar expression
+.Xc
+.It Xo Ic printf Ar format
+.Op Ar ... , expression-list
+.Op > Ns Ar expression
+.Xc
+.It Ic return Op Ar expression
+.It Xo Ic next
+.No # skip remaining patterns on this input line
+.Xc
+.It Xo Ic nextfile
+.No # skip rest of this file, open next, start at top
+.Xc
+.It Xo Ic delete
+.Sm off
+.Ar array Ic \&[ Ar expression Ic \&]
+.Sm on
+.No # delete an array element
+.Xc
+.It Xo Ic delete Ar array
+.No # delete all elements of array
+.Xc
+.It Xo Ic exit
+.Op Ar expression
+.No # exit immediately; status is Ar expression
+.Xc
+.El
+.Pp
+Statements are terminated by
+semicolons, newlines or right braces.
+An empty
+.Ar expression-list
+stands for
+.Ar $0 .
+String constants are quoted
+.Li \&"" ,
+with the usual C escapes recognized within
+(see
+.Xr printf 1
+for a complete list of these).
+Expressions take on string or numeric values as appropriate,
+and are built using the operators
+.Ic + \- * / % ^
+.Pq exponentiation ,
+and concatenation
+.Pq indicated by whitespace .
+The operators
+.Ic \&! ++ \-\- += \-= *= /= %= ^=
+.Ic > >= < <= == != ?\&:
+are also available in expressions.
+Variables may be scalars, array elements
+(denoted
+.Li x[i] )
+or fields.
+Variables are initialized to the null string.
+Array subscripts may be any string,
+not necessarily numeric;
+this allows for a form of associative memory.
+Multiple subscripts such as
+.Li [i,j,k]
+are permitted; the constituents are concatenated,
+separated by the value of
+.Va SUBSEP
+.Pq see the section on variables below .
+.Pp
+The
+.Ic print
+statement prints its arguments on the standard output
+(or on a file if
+.Pf > Ar file
+or
+.Pf >> Ar file
+is present or on a pipe if
+.Pf |\ \& Ar cmd
+is present), separated by the current output field separator,
+and terminated by the output record separator.
+.Ar file
+and
+.Ar cmd
+may be literal names or parenthesized expressions;
+identical string values in different statements denote
+the same open file.
+The
+.Ic printf
+statement formats its expression list according to the format
+(see
+.Xr printf 1 ) .
+.Pp
+Patterns are arbitrary Boolean combinations
+(with
+.Ic "\&! || &&" )
+of regular expressions and
+relational expressions.
+.Nm
+supports extended regular expressions
+.Pq EREs .
+See
+.Xr re_format 7
+for more information on regular expressions.
+Isolated regular expressions
+in a pattern apply to the entire line.
+Regular expressions may also occur in
+relational expressions, using the operators
+.Ic ~
+and
+.Ic !~ .
+.Pf / Ar re Ns /
+is a constant regular expression;
+any string (constant or variable) may be used
+as a regular expression, except in the position of an isolated regular expression
+in a pattern.
+.Pp
+A pattern may consist of two patterns separated by a comma;
+in this case, the action is performed for all lines
+from an occurrence of the first pattern
+through an occurrence of the second.
+.Pp
+A relational expression is one of the following:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Ar expression matchop regular-expression
+.It Ar expression relop expression
+.It Ar expression Ic in Ar array-name
+.It Xo Ic \&( Ns
+.Ar expr , expr , \&... Ns Ic \&) in
+.Ar array-name
+.Xc
+.El
+.Pp
+where a
+.Ar relop
+is any of the six relational operators in C, and a
+.Ar matchop
+is either
+.Ic ~
+(matches)
+or
+.Ic !~
+(does not match).
+A conditional is an arithmetic expression,
+a relational expression,
+or a Boolean combination
+of these.
+.Pp
+The special patterns
+.Ic BEGIN
+and
+.Ic END
+may be used to capture control before the first input line is read
+and after the last.
+.Ic BEGIN
+and
+.Ic END
+do not combine with other patterns.
+.Pp
+Variable names with special meanings:
+.Pp
+.Bl -tag -width "FILENAME " -compact
+.It Va ARGC
+Argument count, assignable.
+.It Va ARGV
+Argument array, assignable;
+non-null members are taken as filenames.
+.It Va CONVFMT
+Conversion format when converting numbers
+(default
+.Qq Li %.6g ) .
+.It Va ENVIRON
+Array of environment variables; subscripts are names.
+.It Va FILENAME
+The name of the current input file.
+.It Va FNR
+Ordinal number of the current record in the current file.
+.It Va FS
+Regular expression used to separate fields; also settable
+by option
+.Fl F Ar fs .
+.It Va NF
+Number of fields in the current record.
+.Va $NF
+can be used to obtain the value of the last field in the current record.
+.It Va NR
+Ordinal number of the current record.
+.It Va OFMT
+Output format for numbers (default
+.Qq Li %.6g ) .
+.It Va OFS
+Output field separator (default blank).
+.It Va ORS
+Output record separator (default newline).
+.It Va RLENGTH
+The length of the string matched by the
+.Fn match
+function.
+.It Va RS
+Input record separator (default newline).
+.It Va RSTART
+The starting position of the string matched by the
+.Fn match
+function.
+.It Va SUBSEP
+Separates multiple subscripts (default 034).
+.El
+.Sh FUNCTIONS
+The awk language has a variety of built-in functions:
+arithmetic, string, input/output, general, and bit-operation.
+.Pp
+Functions may be defined (at the position of a pattern-action statement)
+thusly:
+.Pp
+.Dl function foo(a, b, c) { ...; return x }
+.Pp
+Parameters are passed by value if scalar, and by reference if array name;
+functions may be called recursively.
+Parameters are local to the function; all other variables are global.
+Thus local variables may be created by providing excess parameters in
+the function definition.
+.Ss Arithmetic Functions
+.Bl -tag -width "atan2(y, x)"
+.It Fn atan2 y x
+Return the arctangent of
+.Fa y Ns / Ns Fa x
+in radians.
+.It Fn cos x
+Return the cosine of
+.Fa x ,
+where
+.Fa x
+is in radians.
+.It Fn exp x
+Return the exponential of
+.Fa x .
+.It Fn int x
+Return
+.Fa x
+truncated to an integer value.
+.It Fn log x
+Return the natural logarithm of
+.Fa x .
+.It Fn rand
+Return a random number,
+.Fa n ,
+such that
+.Sm off
+.Pf 0 \*(Le Fa n No \*(Lt 1 .
+.Sm on
+.It Fn sin x
+Return the sine of
+.Fa x ,
+where
+.Fa x
+is in radians.
+.It Fn sqrt x
+Return the square root of
+.Fa x .
+.It Fn srand expr
+Sets seed for
+.Fn rand
+to
+.Fa expr
+and returns the previous seed.
+If
+.Fa expr
+is omitted, the time of day is used instead.
+.El
+.Ss String Functions
+.Bl -tag -width "split(s, a, fs)"
+.It Fn gsub r t s
+The same as
+.Fn sub
+except that all occurrences of the regular expression are replaced.
+.Fn gsub
+returns the number of replacements.
+.It Fn index s t
+The position in
+.Fa s
+where the string
+.Fa t
+occurs, or 0 if it does not.
+.It Fn length s
+The length of
+.Fa s
+taken as a string,
+or of
+.Va $0
+if no argument is given.
+.It Fn match s r
+The position in
+.Fa s
+where the regular expression
+.Fa r
+occurs, or 0 if it does not.
+The variable
+.Va RSTART
+is set to the starting position of the matched string
+.Pq which is the same as the returned value
+or zero if no match is found.
+The variable
+.Va RLENGTH
+is set to the length of the matched string,
+or \-1 if no match is found.
+.It Fn split s a fs
+Splits the string
+.Fa s
+into array elements
+.Va a[1] , a[2] , ... , a[n]
+and returns
+.Va n .
+The separation is done with the regular expression
+.Ar fs
+or with the field separator
+.Va FS
+if
+.Ar fs
+is not given.
+An empty string as field separator splits the string
+into one array element per character.
+.It Fn sprintf fmt expr ...
+The string resulting from formatting
+.Fa expr , ...
+according to the
+.Xr printf 1
+format
+.Fa fmt .
+.It Fn sub r t s
+Substitutes
+.Fa t
+for the first occurrence of the regular expression
+.Fa r
+in the string
+.Fa s .
+If
+.Fa s
+is not given,
+.Va $0
+is used.
+An ampersand
+.Pq Sq &
+in
+.Fa t
+is replaced in string
+.Fa s
+with regular expression
+.Fa r .
+A literal ampersand can be specified by preceding it with two backslashes
+.Pq Sq \e\e .
+A literal backslash can be specified by preceding it with another backslash
+.Pq Sq \e\e .
+.Fn sub
+returns the number of replacements.
+.It Fn substr s m n
+Return at most the
+.Fa n Ns -character
+substring of
+.Fa s
+that begins at position
+.Fa m
+counted from 1.
+If
+.Fa n
+is omitted, or if
+.Fa n
+specifies more characters than are left in the string,
+the length of the substring is limited by the length of
+.Fa s .
+.It Fn tolower str
+Returns a copy of
+.Fa str
+with all upper-case characters translated to their
+corresponding lower-case equivalents.
+.It Fn toupper str
+Returns a copy of
+.Fa str
+with all lower-case characters translated to their
+corresponding upper-case equivalents.
+.El
+.Ss Input/Output and General Functions
+.Bl -tag -width "getline [var] < file"
+.It Fn close expr
+Closes the file or pipe
+.Fa expr .
+.Fa expr
+should match the string that was used to open the file or pipe.
+.It Ar cmd | Ic getline Op Va var
+Read a record of input from a stream piped from the output of
+.Ar cmd .
+If
+.Va var
+is omitted, the variables
+.Va $0
+and
+.Va NF
+are set.
+Otherwise
+.Va var
+is set.
+If the stream is not open, it is opened.
+As long as the stream remains open, subsequent calls
+will read subsequent records from the stream.
+The stream remains open until explicitly closed with a call to
+.Fn close .
+.Ic getline
+returns 1 for a successful input, 0 for end of file, and \-1 for an error.
+.It Fn fflush [expr]
+Flushes any buffered output for the file or pipe
+.Fa expr ,
+or all open files or pipes if
+.Fa expr
+is omitted.
+.Fa expr
+should match the string that was used to open the file or pipe.
+.It Ic getline
+Sets
+.Va $0
+to the next input record from the current input file.
+This form of
+.Ic getline
+sets the variables
+.Va NF ,
+.Va NR ,
+and
+.Va FNR .
+.Ic getline
+returns 1 for a successful input, 0 for end of file, and \-1 for an error.
+.It Ic getline Va var
+Sets
+.Va $0
+to variable
+.Va var .
+This form of
+.Ic getline
+sets the variables
+.Va NR
+and
+.Va FNR .
+.Ic getline
+returns 1 for a successful input, 0 for end of file, and \-1 for an error.
+.It Xo
+.Ic getline Op Va var
+.Pf \ \&< Ar file
+.Xc
+Sets
+.Va $0
+to the next record from
+.Ar file .
+If
+.Va var
+is omitted, the variables
+.Va $0
+and
+.Va NF
+are set.
+Otherwise
+.Va var
+is set.
+If
+.Ar file
+is not open, it is opened.
+As long as the stream remains open, subsequent calls will read subsequent
+records from
+.Ar file .
+.Ar file
+remains open until explicitly closed with a call to
+.Fn close .
+.It Fn system cmd
+Executes
+.Fa cmd
+and returns its exit status.
+.El
+.Ss Bit-Operation Functions
+.Bl -tag -width "lshift(a, b)"
+.It Fn compl x
+Returns the bitwise complement of integer argument x.
+.It Fn and v1 v2 ...
+Performs a bitwise AND on all arguments provided, as integers.
+There must be at least two values.
+.It Fn or v1 v2 ...
+Performs a bitwise OR on all arguments provided, as integers.
+There must be at least two values.
+.It Fn xor v1 v2 ...
+Performs a bitwise Exclusive-OR on all arguments provided, as integers.
+There must be at least two values.
+.It Fn lshift x n
+Returns integer argument x shifted by n bits to the left.
+.It Fn rshift x n
+Returns integer argument x shifted by n bits to the right.
+.El
+.Sh EXIT STATUS
+.Ex -std awk
+.Pp
+But note that the
+.Ic exit
+expression can modify the exit status.
+.Sh EXAMPLES
+Print lines longer than 72 characters:
+.Pp
+.Dl length($0) > 72
+.Pp
+Print first two fields in opposite order:
+.Pp
+.Dl { print $2, $1 }
+.Pp
+Same, with input fields separated by comma and/or blanks and tabs:
+.Bd -literal -offset indent
+BEGIN { FS = ",[ \et]*|[ \et]+" }
+ { print $2, $1 }
+.Ed
+.Pp
+Add up first column, print sum and average:
+.Bd -literal -offset indent
+{ s += $1 }
+END { print "sum is", s, " average is", s/NR }
+.Ed
+.Pp
+Print all lines between start/stop pairs:
+.Pp
+.Dl /start/, /stop/
+.Pp
+Simulate echo(1):
+.Bd -literal -offset indent
+BEGIN { # Simulate echo(1)
+ for (i = 1; i < ARGC; i++) printf "%s ", ARGV[i]
+ printf "\en"
+ exit }
+.Ed
+.Pp
+Print an error message to standard error:
+.Bd -literal -offset indent
+{ print "error!" > "/dev/stderr" }
+.Ed
+.Sh SEE ALSO
+.Xr cut 1 ,
+.Xr lex 1 ,
+.Xr printf 1 ,
+.Xr sed 1 ,
+.Xr re_format 7
+.Rs
+.%A A. V. Aho
+.%A B. W. Kernighan
+.%A P. J. Weinberger
+.%T The AWK Programming Language
+.%I Addison-Wesley
+.%D 1988
+.%O ISBN 0-201-07981-X
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification,
+except
+.Nm
+does not support {n,m} pattern matching.
+.Pp
+The flags
+.Fl d ,
+.Fl safe ,
+and
+.Fl version
+as well as the commands
+.Cm fflush , compl , and , or ,
+.Cm xor , lshift , rshift ,
+are extensions to that specification.
+.Sh HISTORY
+An
+.Nm
+utility appeared in
+.At v7 .
+.Sh BUGS
+There are no explicit conversions between numbers and strings.
+To force an expression to be treated as a number add 0 to it;
+to force it to be treated as a string concatenate
+.Li \&""
+to it.
+.Pp
+The scope rules for variables in functions are a botch;
+the syntax is worse.
+.Sh DEPRECATED BEHAVIOR
+One True Awk has accepted
+.Fl F Ar t
+to mean the same as
+.Fl F Ar <TAB>
+to make it easier to specify tabs as the separator character.
+Upstream One True Awk has deprecated this wart in the name of better
+compatibility with other awk implementations like gawk and mawk.
+.Pp
+Historically,
+.Nm
+did not accept
+.Dq 0x
+as a hex string.
+However, since One True Awk used strtod to convert strings to floats, and since
+.Dq 0x12
+is a valid hexadecimal representation of a floating point number,
+On
+.Fx ,
+.Nm
+has accepted this notation as an extension since One True Awk was imported in
+.Fx 5.0 .
+Upstream One True Awk has restored the historical behavior for better
+compatibility between the different awk implementations.
+Both gawk and mawk already behave similarly.
+Starting with
+.Fx 14.0
+.Nm
+will no longer accept this extension.
+.Pp
+The
+.Fx
+.Nm
+sets the locale for many years to match the environment it was running in.
+This lead to pattern ranges, like
+.Dq "[A-Z]"
+sometimes matching lower case characters in some locales.
+This misbehavior was never in upstream One True Awk and has been removed as a
+bug in
+.Fx 12.3 ,
+.Fx 13.1 ,
+and
+.Fx 14.0 .
diff --git a/usr.bin/awk/tests/Makefile b/usr.bin/awk/tests/Makefile
new file mode 100644
index 000000000000..f9196563341a
--- /dev/null
+++ b/usr.bin/awk/tests/Makefile
@@ -0,0 +1,6 @@
+.include <bsd.own.mk>
+
+TESTS_SUBDIRS+= bugs-fixed
+TESTS_SUBDIRS+= netbsd
+
+.include <bsd.test.mk>
diff --git a/usr.bin/awk/tests/Makefile.depend b/usr.bin/awk/tests/Makefile.depend
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/awk/tests/Makefile.depend
diff --git a/usr.bin/awk/tests/bugs-fixed/Makefile b/usr.bin/awk/tests/bugs-fixed/Makefile
new file mode 100644
index 000000000000..626069647624
--- /dev/null
+++ b/usr.bin/awk/tests/bugs-fixed/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/awk/${.CURDIR:T}
+TESTSRC= ${SRCTOP}/contrib/one-true-awk/bugs-fixed
+
+ATF_TESTS_SH= bug_fix_test
+
+.PATH: ${TESTSRC}
+# Upstream controls the list of tests, so generate it dynamically
+${PACKAGE}FILES!=(cd ${TESTSRC} ; ls *.awk *.ok *.in *.err)
+
+.include <bsd.test.mk>
diff --git a/usr.bin/awk/tests/bugs-fixed/Makefile.depend b/usr.bin/awk/tests/bugs-fixed/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/awk/tests/bugs-fixed/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/awk/tests/bugs-fixed/bug_fix_test.sh b/usr.bin/awk/tests/bugs-fixed/bug_fix_test.sh
new file mode 100644
index 000000000000..588e2f86b0b7
--- /dev/null
+++ b/usr.bin/awk/tests/bugs-fixed/bug_fix_test.sh
@@ -0,0 +1,75 @@
+#
+# Copyright 2014 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+export LANG=C.UTF-8
+SRCDIR=$(atf_get_srcdir)
+
+check()
+{
+ local tc=${1%.awk}; shift
+ local in_flag out_flag err_flag
+
+ awk=awk
+
+ local out_file="${SRCDIR}/${tc}.ok"
+ [ -f "${out_file}" ] && out_flag="-o file:${out_file}"
+ local err_file="${SRCDIR}/${tc}.err"
+ [ -f "${err_file}" ] && err_flag="-e file:${err_file} -s exit:2"
+ local in_file="${SRCDIR}/${tc}.in"
+ [ -f "${in_file}" ] && in_flag="${in_file}"
+
+ (cd ${SRCDIR} ; atf_check ${out_flag} ${err_flag} ${awk} -f "${tc}.awk" ${in_flag})
+}
+
+add_testcase()
+{
+ local tc=${1%.awk}
+ local tc_escaped word
+
+ case "${tc%.*}" in
+ *-*)
+ local IFS="-"
+ for word in ${tc}; do
+ tc_escaped="${tc_escaped:+${tc_escaped}_}${word}"
+ done
+ ;;
+ *)
+ tc_escaped=${tc}
+ ;;
+ esac
+
+ atf_test_case ${tc_escaped}
+ eval "${tc_escaped}_body() { check ${tc}; }"
+ atf_add_test_case ${tc_escaped}
+}
+
+atf_init_test_cases()
+{
+ for path in $(find -s "${SRCDIR}" -name '*.awk'); do
+ add_testcase ${path##*/}
+ done
+}
diff --git a/usr.bin/awk/tests/netbsd/Makefile b/usr.bin/awk/tests/netbsd/Makefile
new file mode 100644
index 000000000000..5357b99dd972
--- /dev/null
+++ b/usr.bin/awk/tests/netbsd/Makefile
@@ -0,0 +1,34 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/awk/${.CURDIR:T}
+TESTSRC= ${SRCTOP}/contrib/netbsd-tests/usr.bin/awk
+
+NETBSD_ATF_TESTS_SH= awk_test
+
+${PACKAGE}FILES+= d_assign_NF.awk
+${PACKAGE}FILES+= d_assign_NF.in
+${PACKAGE}FILES+= d_assign_NF.out
+${PACKAGE}FILES+= d_big_regexp.awk
+${PACKAGE}FILES+= d_big_regexp.in
+${PACKAGE}FILES+= d_big_regexp.out
+${PACKAGE}FILES+= d_end1.awk
+${PACKAGE}FILES+= d_end1.in
+${PACKAGE}FILES+= d_end1.out
+${PACKAGE}FILES+= d_end2.awk
+${PACKAGE}FILES+= d_end2.in
+${PACKAGE}FILES+= d_end2.out
+${PACKAGE}FILES+= d_period.awk
+${PACKAGE}FILES+= d_period.in
+${PACKAGE}FILES+= d_period.out
+${PACKAGE}FILES+= d_string1.awk
+${PACKAGE}FILES+= d_string1.out
+${PACKAGE}FILES+= d_tolower.awk
+${PACKAGE}FILES+= d_tolower.in
+${PACKAGE}FILES+= d_tolower.out
+${PACKAGE}FILES+= d_toupper.awk
+${PACKAGE}FILES+= d_toupper.in
+${PACKAGE}FILES+= d_toupper.out
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/awk/tests/netbsd/Makefile.depend b/usr.bin/awk/tests/netbsd/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/awk/tests/netbsd/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/backlight/Makefile b/usr.bin/backlight/Makefile
new file mode 100644
index 000000000000..f1b310bb1e77
--- /dev/null
+++ b/usr.bin/backlight/Makefile
@@ -0,0 +1,4 @@
+PROG= backlight
+MAN= backlight.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/backlight/backlight.8 b/usr.bin/backlight/backlight.8
new file mode 100644
index 000000000000..25fa91c0060c
--- /dev/null
+++ b/usr.bin/backlight/backlight.8
@@ -0,0 +1,100 @@
+.\" Copyright (c) 2020 Emmanuel Vadot <manu@freebsd.org>
+.\"
+.\" 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 DEVELOPERS ``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 DEVELOPERS 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 July 19, 2022
+.Dt BACKLIGHT 8
+.Os
+.Sh NAME
+.Nm backlight
+.Nd configure backlight hardware
+.Sh SYNOPSIS
+.Nm
+.Op Fl q
+.Op Fl f Ar device
+.Nm
+.Op Fl q
+.Op Fl f Ar device
+.Fl i
+.Nm
+.Op Fl f Ar device
+.Ar value
+.Nm
+.Op Fl f Ar device
+.Cm incr Ns | Ns Cm +
+.Op Ar value
+.Nm
+.Op Fl f Ar device
+.Cm decr Ns | Ns Cm -
+.Op Ar value
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to configure brightness levels for registered backlights.
+.Pp
+Called without any arguments it will print the current brightness level
+of the first registered backlight.
+.Pp
+The options are as follows:
+.Bl -tag -width "-f device"
+.It Fl f Ar device
+Device to operate on.
+If not specified,
+.Pa /dev/backlight/backlight0
+is used.
+If an unqualified name is provided,
+.Pa /dev/backlight/
+is automatically prepended.
+.It Fl i
+Query information about the backlight (name, type).
+.It Fl q
+When querying the brightness level only print the value.
+.It Ar value
+Set the brightness level to this value, must be between 0 and 100.
+A trailing
+.Dq %
+is valid.
+.It Cm incr Ns | Ns Cm + Op Ar value
+Decrement the backlight level.
+If no value is specified a default of 10 percent is used.
+.It Cm decr Ns | Ns Cm - Op Ar value
+Increment the backlight level.
+If no value is specified a default of 10 percent is used.
+.El
+.Sh EXAMPLES
+Show the current brightness level:
+.Bd -literal -offset indent
+$ backlight -f /dev/backlight/backlight0
+brightness: 98
+.Ed
+.Sh SEE ALSO
+.Xr backlight 9
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 13.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility and this manual page were written by
+.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .
diff --git a/usr.bin/backlight/backlight.c b/usr.bin/backlight/backlight.c
new file mode 100644
index 000000000000..de02bb82915d
--- /dev/null
+++ b/usr.bin/backlight/backlight.c
@@ -0,0 +1,224 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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/ioctl.h>
+#include <stdbool.h>
+#include <sys/capsicum.h>
+#include <sys/backlight.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <capsicum_helpers.h>
+
+#define BACKLIGHT_QUERY 0x0001
+#define BACKLIGHT_SET_BRIGHTNESS 0x0002
+#define BACKLIGHT_INCR 0x0004
+#define BACKLIGHT_DECR 0x0008
+#define BACKLIGHT_INFO 0x0010
+
+static char device_name[PATH_MAX] = "/dev/backlight/backlight0";
+
+static void
+set_device_name(const char *name)
+{
+
+ if (name[0] == '/')
+ strlcpy(device_name, name, sizeof(device_name));
+ else
+ snprintf(device_name, sizeof(device_name), "/dev/backlight/%s", name);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tbacklight [-q] [-f device]\n");
+ fprintf(stderr, "\tbacklight [-q] [-f device] -i\n");
+ fprintf(stderr, "\tbacklight [-f device] value\n");
+ fprintf(stderr, "\tbacklight [-f device] incr|+ value\n");
+ fprintf(stderr, "\tbacklight [-f device] decr|- value\n");
+ exit(1);
+}
+
+static const char *
+backlight_type_to_string(enum backlight_info_type type)
+{
+ switch (type) {
+ case BACKLIGHT_TYPE_PANEL:
+ return ("Panel");
+ case BACKLIGHT_TYPE_KEYBOARD:
+ return ("Keyboard");
+ }
+
+ return ("Unknown");
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct backlight_props props;
+ struct backlight_info info;
+ int fd;
+ int action, ch;
+ cap_rights_t right_ioctl;
+ const unsigned long backlight_ioctls[] = {
+ BACKLIGHTGETSTATUS,
+ BACKLIGHTUPDATESTATUS,
+ BACKLIGHTGETINFO};
+ long percent = -1;
+ const char *percent_error;
+ uint32_t i;
+ bool quiet = false;
+
+ action = BACKLIGHT_QUERY;
+ fd = -1;
+
+ while ((ch = getopt(argc, argv, "f:qhi")) != -1) {
+ switch (ch) {
+ case 'q':
+ quiet = true;
+ break;
+ case 'f':
+ set_device_name(optarg);
+ break;
+ case 'i':
+ action = BACKLIGHT_INFO;
+ break;
+ case 'h':
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc != 0) {
+ if (strcmp("incr", argv[0]) == 0 ||
+ strcmp("+", argv[0]) == 0) {
+ action = BACKLIGHT_INCR;
+ argc -= 1;
+ argv += 1;
+ }
+ else if (strcmp("decr", argv[0]) == 0 ||
+ strcmp("-", argv[0]) == 0) {
+ action = BACKLIGHT_DECR;
+ argc -= 1;
+ argv += 1;
+ } else
+ action = BACKLIGHT_SET_BRIGHTNESS;
+
+ if (argc == 1) {
+ /* ignore a trailing % for user friendlyness */
+ if (strlen(argv[0]) > 0 &&
+ argv[0][strlen(argv[0]) - 1] == '%')
+ argv[0][strlen(argv[0]) - 1] = '\0';
+ percent = strtonum(argv[0], 0, 100, &percent_error);
+ if (percent_error)
+ errx(1, "Cannot parse brightness level %s: %s",
+ argv[0],
+ percent_error);
+ }
+ }
+
+ if ((fd = open(device_name, O_RDWR)) == -1)
+ errx(1, "cannot open %s: %s",
+ device_name, strerror(errno));
+
+ if (caph_limit_stdio() < 0)
+ errx(1, "can't limit stdio rights");
+ caph_cache_catpages();
+ cap_rights_init(&right_ioctl, CAP_IOCTL);
+ if (caph_rights_limit(fd, &right_ioctl) < 0)
+ errx(1, "cap_right_limit() failed");
+ if (caph_ioctls_limit(fd, backlight_ioctls, nitems(backlight_ioctls)) < 0)
+ errx(1, "caph_ioctls_limit() failed");
+ if (caph_enter() < 0)
+ errx(1, "failed to enter capability mode");
+
+ switch (action) {
+ case BACKLIGHT_QUERY:
+ if (ioctl(fd, BACKLIGHTGETSTATUS, &props) == -1)
+ errx(1, "Cannot query the backlight device");
+ if (quiet)
+ printf("%u\n", props.brightness);
+ else {
+ printf("brightness: %d\n", props.brightness);
+ if (props.nlevels != 0) {
+ printf("levels:");
+ for (i = 0; i < props.nlevels; i++)
+ printf(" %d", props.levels[i]);
+ printf("\n");
+ }
+ }
+ break;
+ case BACKLIGHT_SET_BRIGHTNESS:
+ if (percent == -1)
+ usage();
+ props.brightness = percent;
+ if (ioctl(fd, BACKLIGHTUPDATESTATUS, &props) == -1)
+ errx(1, "Cannot update the backlight device");
+ break;
+ case BACKLIGHT_INCR:
+ case BACKLIGHT_DECR:
+ if (percent == 0)
+ /* Avoid any ioctl if we don't have anything to do */
+ break;
+ if (ioctl(fd, BACKLIGHTGETSTATUS, &props) == -1)
+ errx(1, "Cannot query the backlight device");
+ percent = percent == -1 ? 10 : percent;
+ percent = action == BACKLIGHT_INCR ? percent : -percent;
+ props.brightness += percent;
+ if ((int)props.brightness < 0)
+ props.brightness = 0;
+ if (props.brightness > 100)
+ props.brightness = 100;
+ if (ioctl(fd, BACKLIGHTUPDATESTATUS, &props) == -1)
+ errx(1, "Cannot update the backlight device");
+ break;
+ case BACKLIGHT_INFO:
+ if (ioctl(fd, BACKLIGHTGETINFO, &info) == -1)
+ errx(1, "Cannot query the backlight device");
+ if (quiet == false) {
+ printf("Backlight name: %s\n", info.name);
+ printf("Backlight hardware type: %s\n", backlight_type_to_string(info.type));
+ } else {
+ printf("%s\n", info.name);
+ printf("%s\n", backlight_type_to_string(info.type));
+ }
+ break;
+ }
+
+ close(fd);
+ return (0);
+}
diff --git a/usr.bin/banner/Makefile b/usr.bin/banner/Makefile
new file mode 100644
index 000000000000..f3af9a652f56
--- /dev/null
+++ b/usr.bin/banner/Makefile
@@ -0,0 +1,4 @@
+PROG= banner
+MAN= banner.6
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/banner/Makefile.depend b/usr.bin/banner/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/banner/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/banner/banner.6 b/usr.bin/banner/banner.6
new file mode 100644
index 000000000000..614bfc51a286
--- /dev/null
+++ b/usr.bin/banner/banner.6
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1980, 1993, 1995
+.\" 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.
+.\"
+.Dd June 21, 2021
+.Dt BANNER 6
+.Os
+.Sh NAME
+.Nm banner
+.Nd print large banner on printer
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl t
+.Op Fl w Ar width
+.Ar message ...
+.Sh DESCRIPTION
+.Nm Banner
+prints a large, high quality banner on the standard output.
+If the message is omitted, it prompts for and reads one line of its
+standard input.
+.Pp
+The output should be printed on paper of the appropriate width,
+with no breaks between the pages.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d
+Enable debug.
+.It Fl t
+Enable trace.
+.It Fl w Ar width
+Change the output from a width of 132 to
+.Ar width ,
+suitable for a narrow terminal.
+.El
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.At v6 .
+.Sh AUTHORS
+.An Mark Horton
+.Sh BUGS
+Several
+.Tn ASCII
+characters are not defined, notably <, >, [, ], \\,
+^, _, {, }, |, and ~.
+Also, the characters ", ', and & are funny looking (but in a useful way.)
+.Pp
+The
+.Fl w
+option is implemented by skipping some rows and columns.
+The smaller it gets, the grainier the output.
+Sometimes it runs letters together.
+.Pp
+Messages are limited to 1024 characters in length.
diff --git a/usr.bin/banner/banner.c b/usr.bin/banner/banner.c
new file mode 100644
index 000000000000..fcd41eafaadb
--- /dev/null
+++ b/usr.bin/banner/banner.c
@@ -0,0 +1,1168 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1993, 1994
+ * 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.
+ */
+
+/*
+ * banner - prints large signs
+ * banner [-w#] [-d] [-t] message ...
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAXMSG 1024
+#define DWIDTH 132
+#define NCHARS 128
+#define NBYTES 9271
+
+/* Pointers into data_table for each ASCII char */
+static const int asc_ptr[NCHARS] = {
+/* ^@ */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* ^H */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* ^P */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* ^X */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 1, 3, 50, 81, 104, 281, 483, 590,
+/* ( */ 621, 685, 749, 851, 862, 893, 898, 921,
+/* 0 */1019, 1150, 1200, 1419, 1599, 1744, 1934, 2111,
+/* 8 */2235, 2445, 2622, 2659, 0, 2708, 0, 2715,
+/* @ */2857, 3072, 3273, 3403, 3560, 3662, 3730, 3785,
+/* H */3965, 4000, 4015, 4115, 4281, 4314, 4432, 4548,
+/* P */4709, 4790, 4999, 5188, 5397, 5448, 5576, 5710,
+/* X */5892, 6106, 6257, 0, 0, 0, 0, 0,
+/* ` */ 50, 6503, 6642, 6733, 6837, 6930, 7073, 7157,
+/* h */7380, 7452, 7499, 7584, 7689, 7702, 7797, 7869,
+/* p */7978, 8069, 8160, 8222, 8381, 8442, 8508, 8605,
+/* x */8732, 8888, 9016, 0, 0, 0, 0, 0
+};
+
+/*
+ * Table of stuff to print. Format:
+ * 128+n -> print current line n times.
+ * 64+n -> this is last byte of char.
+ * else, put m chars at position n (where m
+ * is the next elt in array) and goto second
+ * next element in array.
+ */
+static const unsigned char data_table[NBYTES] = {
+/* 0 1 2 3 4 5 6 7 8 9 */
+/* 0 */ 129, 227, 130, 34, 6, 90, 19, 129, 32, 10,
+/* 10 */ 74, 40, 129, 31, 12, 64, 53, 129, 30, 14,
+/* 20 */ 54, 65, 129, 30, 14, 53, 67, 129, 30, 14,
+/* 30 */ 54, 65, 129, 31, 12, 64, 53, 129, 32, 10,
+/* 40 */ 74, 40, 129, 34, 6, 90, 19, 129, 194, 130,
+/* 50 */ 99, 9, 129, 97, 14, 129, 96, 18, 129, 95,
+/* 60 */ 22, 129, 95, 16, 117, 2, 129, 95, 14, 129,
+/* 70 */ 96, 11, 129, 97, 9, 129, 99, 6, 129, 194,
+/* 80 */ 129, 87, 4, 101, 4, 131, 82, 28, 131, 87,
+/* 90 */ 4, 101, 4, 133, 82, 28, 131, 87, 4, 101,
+/* 100 */ 4, 131, 193, 129, 39, 1, 84, 27, 129, 38,
+/* 110 */ 3, 81, 32, 129, 37, 5, 79, 35, 129, 36,
+/* 120 */ 5, 77, 38, 129, 35, 5, 76, 40, 129, 34,
+/* 130 */ 5, 75, 21, 103, 14, 129, 33, 5, 74, 19,
+/* 140 */ 107, 11, 129, 32, 5, 73, 17, 110, 9, 129,
+/* 150 */ 32, 4, 73, 16, 112, 7, 129, 31, 4, 72,
+/* 160 */ 15, 114, 6, 129, 31, 4, 72, 14, 115, 5,
+/* 170 */ 129, 30, 4, 71, 15, 116, 5, 129, 27, 97,
+/* 180 */ 131, 30, 4, 69, 14, 117, 4, 129, 30, 4,
+/* 190 */ 68, 15, 117, 4, 132, 30, 4, 68, 14, 117,
+/* 200 */ 4, 129, 27, 97, 131, 30, 5, 65, 15, 116,
+/* 210 */ 5, 129, 31, 4, 65, 14, 116, 4, 129, 31,
+/* 220 */ 6, 64, 15, 116, 4, 129, 32, 7, 62, 16,
+/* 230 */ 115, 4, 129, 32, 9, 61, 17, 114, 5, 129,
+/* 240 */ 33, 11, 58, 19, 113, 5, 129, 34, 14, 55,
+/* 250 */ 21, 112, 5, 129, 35, 40, 111, 5, 129, 36,
+/* 260 */ 38, 110, 5, 129, 37, 35, 109, 5, 129, 38,
+/* 270 */ 32, 110, 3, 129, 40, 27, 111, 1, 129, 193,
+/* 280 */ 129, 30, 4, 103, 9, 129, 30, 7, 100, 15,
+/* 290 */ 129, 30, 10, 99, 17, 129, 33, 10, 97, 6,
+/* 300 */ 112, 6, 129, 36, 10, 96, 5, 114, 5, 129,
+/* 310 */ 39, 10, 96, 4, 115, 4, 129, 42, 10, 95,
+/* 320 */ 4, 116, 4, 129, 45, 10, 95, 3, 117, 3,
+/* 330 */ 129, 48, 10, 95, 3, 117, 3, 129, 51, 10,
+/* 340 */ 95, 4, 116, 4, 129, 54, 10, 96, 4, 115,
+/* 350 */ 4, 129, 57, 10, 96, 5, 114, 5, 129, 60,
+/* 360 */ 10, 97, 6, 112, 6, 129, 63, 10, 99, 17,
+/* 370 */ 129, 66, 10, 100, 15, 129, 69, 10, 103, 9,
+/* 380 */ 129, 39, 9, 72, 10, 129, 36, 15, 75, 10,
+/* 390 */ 129, 35, 17, 78, 10, 129, 33, 6, 48, 6,
+/* 400 */ 81, 10, 129, 32, 5, 50, 5, 84, 10, 129,
+/* 410 */ 32, 4, 51, 4, 87, 10, 129, 31, 4, 52,
+/* 420 */ 4, 90, 10, 129, 31, 3, 53, 3, 93, 10,
+/* 430 */ 129, 31, 3, 53, 3, 96, 10, 129, 31, 4,
+/* 440 */ 52, 4, 99, 10, 129, 32, 4, 51, 4, 102,
+/* 450 */ 10, 129, 32, 5, 50, 5, 105, 10, 129, 33,
+/* 460 */ 6, 48, 6, 108, 10, 129, 35, 17, 111, 10,
+/* 470 */ 129, 36, 15, 114, 7, 129, 40, 9, 118, 4,
+/* 480 */ 129, 193, 129, 48, 18, 129, 43, 28, 129, 41,
+/* 490 */ 32, 129, 39, 36, 129, 37, 40, 129, 35, 44,
+/* 500 */ 129, 34, 46, 129, 33, 13, 68, 13, 129, 32,
+/* 510 */ 9, 73, 9, 129, 32, 7, 75, 7, 129, 31,
+/* 520 */ 6, 77, 6, 129, 31, 5, 78, 5, 129, 30,
+/* 530 */ 5, 79, 5, 129, 20, 74, 132, 30, 4, 80,
+/* 540 */ 4, 129, 31, 3, 79, 4, 129, 31, 4, 79,
+/* 550 */ 4, 129, 32, 3, 78, 4, 129, 32, 4, 76,
+/* 560 */ 6, 129, 33, 4, 74, 7, 129, 34, 4, 72,
+/* 570 */ 8, 129, 35, 5, 72, 7, 129, 37, 5, 73,
+/* 580 */ 4, 129, 39, 4, 74, 1, 129, 129, 193, 130,
+/* 590 */ 111, 6, 129, 109, 10, 129, 108, 12, 129, 107,
+/* 600 */ 14, 129, 97, 2, 105, 16, 129, 99, 22, 129,
+/* 610 */ 102, 18, 129, 105, 14, 129, 108, 9, 129, 194,
+/* 620 */ 130, 63, 25, 129, 57, 37, 129, 52, 47, 129,
+/* 630 */ 48, 55, 129, 44, 63, 129, 41, 69, 129, 38,
+/* 640 */ 75, 129, 36, 79, 129, 34, 83, 129, 33, 28,
+/* 650 */ 90, 28, 129, 32, 23, 96, 23, 129, 32, 17,
+/* 660 */ 102, 17, 129, 31, 13, 107, 13, 129, 30, 9,
+/* 670 */ 112, 9, 129, 30, 5, 116, 5, 129, 30, 1,
+/* 680 */ 120, 1, 129, 194, 130, 30, 1, 120, 1, 129,
+/* 690 */ 30, 5, 116, 5, 129, 30, 9, 112, 9, 129,
+/* 700 */ 31, 13, 107, 13, 129, 32, 17, 102, 17, 129,
+/* 710 */ 32, 23, 96, 23, 129, 33, 28, 90, 28, 129,
+/* 720 */ 34, 83, 129, 36, 79, 129, 38, 75, 129, 41,
+/* 730 */ 69, 129, 44, 63, 129, 48, 55, 129, 52, 47,
+/* 740 */ 129, 57, 37, 129, 63, 25, 129, 194, 129, 80,
+/* 750 */ 4, 130, 80, 4, 129, 68, 2, 80, 4, 94,
+/* 760 */ 2, 129, 66, 6, 80, 4, 92, 6, 129, 67,
+/* 770 */ 7, 80, 4, 90, 7, 129, 69, 7, 80, 4,
+/* 780 */ 88, 7, 129, 71, 6, 80, 4, 87, 6, 129,
+/* 790 */ 72, 20, 129, 74, 16, 129, 76, 12, 129, 62,
+/* 800 */ 40, 131, 76, 12, 129, 74, 16, 129, 72, 20,
+/* 810 */ 129, 71, 6, 80, 4, 87, 6, 129, 69, 7,
+/* 820 */ 80, 4, 88, 7, 129, 67, 7, 80, 4, 90,
+/* 830 */ 7, 129, 66, 6, 80, 4, 92, 6, 129, 68,
+/* 840 */ 2, 80, 4, 94, 2, 129, 80, 4, 130, 193,
+/* 850 */ 129, 60, 4, 139, 41, 42, 131, 60, 4, 139,
+/* 860 */ 193, 130, 34, 6, 129, 32, 10, 129, 31, 12,
+/* 870 */ 129, 30, 14, 129, 20, 2, 28, 16, 129, 22,
+/* 880 */ 22, 129, 24, 19, 129, 27, 15, 129, 31, 9,
+/* 890 */ 129, 194, 129, 60, 4, 152, 193, 130, 34, 6,
+/* 900 */ 129, 32, 10, 129, 31, 12, 129, 30, 14, 131,
+/* 910 */ 31, 12, 129, 32, 10, 129, 34, 6, 129, 194,
+/* 920 */ 129, 30, 4, 129, 30, 7, 129, 30, 10, 129,
+/* 930 */ 33, 10, 129, 36, 10, 129, 39, 10, 129, 42,
+/* 940 */ 10, 129, 45, 10, 129, 48, 10, 129, 51, 10,
+/* 950 */ 129, 54, 10, 129, 57, 10, 129, 60, 10, 129,
+/* 960 */ 63, 10, 129, 66, 10, 129, 69, 10, 129, 72,
+/* 970 */ 10, 129, 75, 10, 129, 78, 10, 129, 81, 10,
+/* 980 */ 129, 84, 10, 129, 87, 10, 129, 90, 10, 129,
+/* 990 */ 93, 10, 129, 96, 10, 129, 99, 10, 129, 102,
+/* 1000 */ 10, 129, 105, 10, 129, 108, 10, 129, 111, 10,
+/* 1010 */ 129, 114, 7, 129, 117, 4, 129, 193, 129, 60,
+/* 1020 */ 31, 129, 53, 45, 129, 49, 53, 129, 46, 59,
+/* 1030 */ 129, 43, 65, 129, 41, 69, 129, 39, 73, 129,
+/* 1040 */ 37, 77, 129, 36, 79, 129, 35, 15, 101, 15,
+/* 1050 */ 129, 34, 11, 106, 11, 129, 33, 9, 109, 9,
+/* 1060 */ 129, 32, 7, 112, 7, 129, 31, 6, 114, 6,
+/* 1070 */ 129, 31, 5, 115, 5, 129, 30, 5, 116, 5,
+/* 1080 */ 129, 30, 4, 117, 4, 132, 30, 5, 116, 5,
+/* 1090 */ 129, 31, 5, 115, 5, 129, 31, 6, 114, 6,
+/* 1100 */ 129, 32, 7, 112, 7, 129, 33, 9, 109, 9,
+/* 1110 */ 129, 34, 11, 106, 11, 129, 35, 15, 101, 15,
+/* 1120 */ 129, 36, 79, 129, 37, 77, 129, 39, 73, 129,
+/* 1130 */ 41, 69, 129, 43, 65, 129, 46, 59, 129, 49,
+/* 1140 */ 53, 129, 53, 45, 129, 60, 31, 129, 193, 129,
+/* 1150 */ 30, 4, 129, 30, 4, 100, 1, 129, 30, 4,
+/* 1160 */ 100, 3, 129, 30, 4, 100, 5, 129, 30, 76,
+/* 1170 */ 129, 30, 78, 129, 30, 80, 129, 30, 82, 129,
+/* 1180 */ 30, 83, 129, 30, 85, 129, 30, 87, 129, 30,
+/* 1190 */ 89, 129, 30, 91, 129, 30, 4, 132, 193, 129,
+/* 1200 */ 30, 3, 129, 30, 7, 129, 30, 10, 112, 1,
+/* 1210 */ 129, 30, 13, 112, 2, 129, 30, 16, 112, 3,
+/* 1220 */ 129, 30, 18, 111, 5, 129, 30, 21, 111, 6,
+/* 1230 */ 129, 30, 23, 112, 6, 129, 30, 14, 47, 8,
+/* 1240 */ 113, 6, 129, 30, 14, 49, 8, 114, 5, 129,
+/* 1250 */ 30, 14, 51, 8, 115, 5, 129, 30, 14, 53,
+/* 1260 */ 8, 116, 4, 129, 30, 14, 55, 8, 116, 5,
+/* 1270 */ 129, 30, 14, 56, 9, 117, 4, 129, 30, 14,
+/* 1280 */ 57, 9, 117, 4, 129, 30, 14, 58, 10, 117,
+/* 1290 */ 4, 129, 30, 14, 59, 10, 117, 4, 129, 30,
+/* 1300 */ 14, 60, 11, 117, 4, 129, 30, 14, 61, 11,
+/* 1310 */ 116, 5, 129, 30, 14, 62, 11, 116, 5, 129,
+/* 1320 */ 30, 14, 63, 12, 115, 6, 129, 30, 14, 64,
+/* 1330 */ 13, 114, 7, 129, 30, 14, 65, 13, 113, 8,
+/* 1340 */ 129, 30, 14, 65, 15, 111, 9, 129, 30, 14,
+/* 1350 */ 66, 16, 109, 11, 129, 30, 14, 67, 17, 107,
+/* 1360 */ 12, 129, 30, 14, 68, 20, 103, 16, 129, 30,
+/* 1370 */ 14, 69, 49, 129, 30, 14, 70, 47, 129, 30,
+/* 1380 */ 14, 71, 45, 129, 30, 14, 73, 42, 129, 30,
+/* 1390 */ 15, 75, 38, 129, 33, 12, 77, 34, 129, 36,
+/* 1400 */ 10, 79, 30, 129, 40, 6, 82, 23, 129, 44,
+/* 1410 */ 3, 86, 15, 129, 47, 1, 129, 193, 129, 129,
+/* 1420 */ 38, 3, 129, 37, 5, 111, 1, 129, 36, 7,
+/* 1430 */ 111, 2, 129, 35, 9, 110, 5, 129, 34, 8,
+/* 1440 */ 110, 6, 129, 33, 7, 109, 8, 129, 32, 7,
+/* 1450 */ 110, 8, 129, 32, 6, 112, 7, 129, 31, 6,
+/* 1460 */ 113, 6, 129, 31, 5, 114, 6, 129, 30, 5,
+/* 1470 */ 115, 5, 129, 30, 5, 116, 4, 129, 30, 4,
+/* 1480 */ 117, 4, 131, 30, 4, 117, 4, 129, 30, 4,
+/* 1490 */ 79, 2, 117, 4, 129, 30, 5, 78, 4, 117,
+/* 1500 */ 4, 129, 30, 5, 77, 6, 116, 5, 129, 30,
+/* 1510 */ 6, 76, 8, 115, 6, 129, 30, 7, 75, 11,
+/* 1520 */ 114, 6, 129, 30, 8, 73, 15, 112, 8, 129,
+/* 1530 */ 31, 9, 71, 19, 110, 9, 129, 31, 11, 68,
+/* 1540 */ 26, 107, 12, 129, 32, 13, 65, 14, 82, 36,
+/* 1550 */ 129, 32, 16, 61, 17, 83, 34, 129, 33, 44,
+/* 1560 */ 84, 32, 129, 34, 42, 85, 30, 129, 35, 40,
+/* 1570 */ 87, 27, 129, 36, 38, 89, 23, 129, 38, 34,
+/* 1580 */ 92, 17, 129, 40, 30, 95, 11, 129, 42, 26,
+/* 1590 */ 129, 45, 20, 129, 49, 11, 129, 193, 129, 49,
+/* 1600 */ 1, 129, 49, 4, 129, 49, 6, 129, 49, 8,
+/* 1610 */ 129, 49, 10, 129, 49, 12, 129, 49, 14, 129,
+/* 1620 */ 49, 17, 129, 49, 19, 129, 49, 21, 129, 49,
+/* 1630 */ 23, 129, 49, 14, 65, 9, 129, 49, 14, 67,
+/* 1640 */ 9, 129, 49, 14, 69, 9, 129, 49, 14, 71,
+/* 1650 */ 10, 129, 49, 14, 74, 9, 129, 49, 14, 76,
+/* 1660 */ 9, 129, 49, 14, 78, 9, 129, 49, 14, 80,
+/* 1670 */ 9, 129, 49, 14, 82, 9, 129, 49, 14, 84,
+/* 1680 */ 9, 129, 30, 4, 49, 14, 86, 10, 129, 30,
+/* 1690 */ 4, 49, 14, 89, 9, 129, 30, 4, 49, 14,
+/* 1700 */ 91, 9, 129, 30, 4, 49, 14, 93, 9, 129,
+/* 1710 */ 30, 74, 129, 30, 76, 129, 30, 78, 129, 30,
+/* 1720 */ 81, 129, 30, 83, 129, 30, 85, 129, 30, 87,
+/* 1730 */ 129, 30, 89, 129, 30, 91, 129, 30, 4, 49,
+/* 1740 */ 14, 132, 193, 129, 37, 1, 129, 36, 3, 77,
+/* 1750 */ 3, 129, 35, 5, 78, 11, 129, 34, 7, 78,
+/* 1760 */ 21, 129, 33, 7, 79, 29, 129, 32, 7, 79,
+/* 1770 */ 38, 129, 32, 6, 80, 4, 92, 29, 129, 31,
+/* 1780 */ 6, 80, 5, 102, 19, 129, 31, 5, 80, 6,
+/* 1790 */ 107, 14, 129, 31, 4, 81, 5, 107, 14, 129,
+/* 1800 */ 30, 5, 81, 6, 107, 14, 129, 30, 4, 81,
+/* 1810 */ 6, 107, 14, 130, 30, 4, 81, 7, 107, 14,
+/* 1820 */ 129, 30, 4, 80, 8, 107, 14, 130, 30, 5,
+/* 1830 */ 80, 8, 107, 14, 129, 30, 5, 79, 9, 107,
+/* 1840 */ 14, 129, 31, 5, 79, 9, 107, 14, 129, 31,
+/* 1850 */ 6, 78, 10, 107, 14, 129, 32, 6, 76, 11,
+/* 1860 */ 107, 14, 129, 32, 8, 74, 13, 107, 14, 129,
+/* 1870 */ 33, 10, 71, 16, 107, 14, 129, 33, 15, 67,
+/* 1880 */ 19, 107, 14, 129, 34, 51, 107, 14, 129, 35,
+/* 1890 */ 49, 107, 14, 129, 36, 47, 107, 14, 129, 37,
+/* 1900 */ 45, 107, 14, 129, 39, 41, 107, 14, 129, 41,
+/* 1910 */ 37, 107, 14, 129, 44, 32, 107, 14, 129, 47,
+/* 1920 */ 25, 111, 10, 129, 51, 16, 115, 6, 129, 119,
+/* 1930 */ 2, 129, 193, 129, 56, 39, 129, 51, 49, 129,
+/* 1940 */ 47, 57, 129, 44, 63, 129, 42, 67, 129, 40,
+/* 1950 */ 71, 129, 38, 75, 129, 37, 77, 129, 35, 81,
+/* 1960 */ 129, 34, 16, 74, 5, 101, 16, 129, 33, 11,
+/* 1970 */ 76, 5, 107, 11, 129, 32, 9, 77, 5, 110,
+/* 1980 */ 9, 129, 32, 7, 79, 4, 112, 7, 129, 31,
+/* 1990 */ 6, 80, 4, 114, 6, 129, 31, 5, 81, 4,
+/* 2000 */ 115, 5, 129, 30, 5, 82, 4, 116, 5, 129,
+/* 2010 */ 30, 4, 82, 4, 116, 5, 129, 30, 4, 82,
+/* 2020 */ 5, 117, 4, 131, 30, 5, 82, 5, 117, 4,
+/* 2030 */ 129, 31, 5, 81, 6, 117, 4, 129, 31, 6,
+/* 2040 */ 80, 7, 117, 4, 129, 32, 7, 79, 8, 117,
+/* 2050 */ 4, 129, 32, 9, 77, 9, 116, 5, 129, 33,
+/* 2060 */ 11, 75, 11, 116, 4, 129, 34, 16, 69, 16,
+/* 2070 */ 115, 5, 129, 35, 49, 114, 5, 129, 37, 46,
+/* 2080 */ 113, 5, 129, 38, 44, 112, 6, 129, 40, 41,
+/* 2090 */ 112, 5, 129, 42, 37, 113, 3, 129, 44, 33,
+/* 2100 */ 114, 1, 129, 47, 27, 129, 51, 17, 129, 193,
+/* 2110 */ 129, 103, 2, 129, 103, 6, 129, 104, 9, 129,
+/* 2120 */ 105, 12, 129, 106, 15, 129, 107, 14, 135, 30,
+/* 2130 */ 10, 107, 14, 129, 30, 17, 107, 14, 129, 30,
+/* 2140 */ 25, 107, 14, 129, 30, 31, 107, 14, 129, 30,
+/* 2150 */ 37, 107, 14, 129, 30, 42, 107, 14, 129, 30,
+/* 2160 */ 46, 107, 14, 129, 30, 50, 107, 14, 129, 30,
+/* 2170 */ 54, 107, 14, 129, 30, 58, 107, 14, 129, 59,
+/* 2180 */ 32, 107, 14, 129, 64, 30, 107, 14, 129, 74,
+/* 2190 */ 23, 107, 14, 129, 81, 18, 107, 14, 129, 86,
+/* 2200 */ 16, 107, 14, 129, 91, 14, 107, 14, 129, 96,
+/* 2210 */ 25, 129, 100, 21, 129, 104, 17, 129, 107, 14,
+/* 2220 */ 129, 111, 10, 129, 114, 7, 129, 117, 4, 129,
+/* 2230 */ 120, 1, 129, 193, 129, 48, 13, 129, 44, 21,
+/* 2240 */ 129, 42, 26, 129, 40, 30, 92, 12, 129, 38,
+/* 2250 */ 34, 88, 20, 129, 36, 37, 86, 25, 129, 35,
+/* 2260 */ 39, 84, 29, 129, 34, 13, 63, 12, 82, 33,
+/* 2270 */ 129, 33, 11, 67, 9, 80, 36, 129, 32, 9,
+/* 2280 */ 70, 7, 79, 38, 129, 31, 8, 72, 46, 129,
+/* 2290 */ 30, 7, 74, 22, 108, 11, 129, 30, 6, 75,
+/* 2300 */ 19, 111, 9, 129, 30, 5, 75, 17, 113, 7,
+/* 2310 */ 129, 30, 5, 74, 16, 114, 6, 129, 30, 4,
+/* 2320 */ 73, 16, 115, 6, 129, 30, 4, 72, 16, 116,
+/* 2330 */ 5, 129, 30, 4, 72, 15, 117, 4, 129, 30,
+/* 2340 */ 4, 71, 16, 117, 4, 129, 30, 5, 70, 16,
+/* 2350 */ 117, 4, 129, 30, 5, 70, 15, 117, 4, 129,
+/* 2360 */ 30, 6, 69, 15, 116, 5, 129, 30, 7, 68,
+/* 2370 */ 17, 115, 5, 129, 30, 9, 67, 19, 114, 6,
+/* 2380 */ 129, 30, 10, 65, 22, 113, 6, 129, 31, 12,
+/* 2390 */ 63, 27, 110, 9, 129, 32, 14, 60, 21, 84,
+/* 2400 */ 9, 106, 12, 129, 33, 47, 85, 32, 129, 34,
+/* 2410 */ 45, 86, 30, 129, 35, 43, 88, 26, 129, 36,
+/* 2420 */ 40, 90, 22, 129, 38, 36, 93, 17, 129, 40,
+/* 2430 */ 32, 96, 10, 129, 42, 28, 129, 44, 23, 129,
+/* 2440 */ 48, 15, 129, 193, 129, 83, 17, 129, 77, 27,
+/* 2450 */ 129, 36, 1, 74, 33, 129, 35, 3, 72, 37,
+/* 2460 */ 129, 34, 5, 70, 41, 129, 33, 6, 69, 44,
+/* 2470 */ 129, 33, 5, 68, 46, 129, 32, 5, 67, 49,
+/* 2480 */ 129, 31, 5, 66, 17, 101, 16, 129, 31, 5,
+/* 2490 */ 66, 11, 108, 10, 129, 30, 4, 65, 9, 110,
+/* 2500 */ 9, 129, 30, 4, 64, 8, 112, 7, 129, 30,
+/* 2510 */ 4, 64, 7, 114, 6, 129, 30, 4, 64, 6,
+/* 2520 */ 115, 5, 129, 30, 4, 64, 5, 116, 5, 129,
+/* 2530 */ 30, 4, 64, 5, 117, 4, 131, 30, 4, 65,
+/* 2540 */ 4, 117, 4, 129, 30, 5, 65, 4, 116, 5,
+/* 2550 */ 129, 31, 5, 66, 4, 115, 5, 129, 31, 6,
+/* 2560 */ 67, 4, 114, 6, 129, 32, 7, 68, 4, 112,
+/* 2570 */ 7, 129, 32, 9, 69, 5, 110, 9, 129, 33,
+/* 2580 */ 11, 70, 5, 107, 11, 129, 34, 16, 72, 5,
+/* 2590 */ 101, 16, 129, 35, 81, 129, 37, 77, 129, 38,
+/* 2600 */ 75, 129, 40, 71, 129, 42, 67, 129, 44, 63,
+/* 2610 */ 129, 47, 57, 129, 51, 49, 129, 56, 39, 129,
+/* 2620 */ 193, 130, 34, 6, 74, 6, 129, 32, 10, 72,
+/* 2630 */ 10, 129, 31, 12, 71, 12, 129, 30, 14, 70,
+/* 2640 */ 14, 131, 31, 12, 71, 12, 129, 32, 10, 72,
+/* 2650 */ 10, 129, 34, 6, 74, 6, 129, 194, 130, 34,
+/* 2660 */ 6, 74, 6, 129, 32, 10, 72, 10, 129, 31,
+/* 2670 */ 12, 71, 12, 129, 30, 14, 70, 14, 129, 20,
+/* 2680 */ 2, 28, 16, 70, 14, 129, 22, 22, 70, 14,
+/* 2690 */ 129, 24, 19, 71, 12, 129, 27, 15, 72, 10,
+/* 2700 */ 129, 31, 9, 74, 6, 129, 194, 129, 53, 4,
+/* 2710 */ 63, 4, 152, 193, 130, 99, 7, 129, 97, 13,
+/* 2720 */ 129, 96, 16, 129, 96, 18, 129, 96, 19, 129,
+/* 2730 */ 97, 19, 129, 99, 6, 110, 7, 129, 112, 6,
+/* 2740 */ 129, 114, 5, 129, 34, 6, 57, 5, 115, 4,
+/* 2750 */ 129, 32, 10, 54, 12, 116, 4, 129, 31, 12,
+/* 2760 */ 53, 16, 117, 3, 129, 30, 14, 52, 20, 117,
+/* 2770 */ 4, 129, 30, 14, 52, 23, 117, 4, 129, 30,
+/* 2780 */ 14, 52, 25, 117, 4, 129, 31, 12, 52, 27,
+/* 2790 */ 117, 4, 129, 32, 10, 53, 10, 70, 11, 116,
+/* 2800 */ 5, 129, 34, 6, 55, 5, 73, 10, 115, 6,
+/* 2810 */ 129, 74, 11, 114, 7, 129, 75, 12, 112, 9,
+/* 2820 */ 129, 76, 13, 110, 10, 129, 77, 16, 106, 14,
+/* 2830 */ 129, 78, 41, 129, 80, 38, 129, 81, 36, 129,
+/* 2840 */ 82, 34, 129, 84, 30, 129, 86, 26, 129, 88,
+/* 2850 */ 22, 129, 92, 14, 129, 194, 129, 55, 15, 129,
+/* 2860 */ 50, 25, 129, 47, 32, 129, 45, 13, 70, 12,
+/* 2870 */ 129, 43, 9, 76, 10, 129, 42, 6, 79, 8,
+/* 2880 */ 129, 41, 5, 81, 7, 129, 40, 4, 84, 6,
+/* 2890 */ 129, 39, 4, 59, 12, 85, 6, 129, 38, 4,
+/* 2900 */ 55, 19, 87, 5, 129, 37, 4, 53, 23, 88,
+/* 2910 */ 4, 129, 36, 4, 51, 8, 71, 6, 89, 4,
+/* 2920 */ 129, 36, 4, 51, 6, 73, 4, 89, 4, 129,
+/* 2930 */ 36, 4, 50, 6, 74, 4, 90, 3, 129, 35,
+/* 2940 */ 4, 50, 5, 75, 3, 90, 4, 129, 35, 4,
+/* 2950 */ 50, 4, 75, 4, 90, 4, 131, 35, 4, 50,
+/* 2960 */ 5, 75, 4, 90, 4, 129, 36, 4, 51, 5,
+/* 2970 */ 75, 4, 90, 4, 129, 36, 4, 51, 6, 75,
+/* 2980 */ 4, 90, 4, 129, 36, 4, 53, 26, 90, 4,
+/* 2990 */ 129, 37, 4, 54, 25, 90, 4, 129, 37, 4,
+/* 3000 */ 52, 27, 90, 3, 129, 38, 4, 52, 4, 89,
+/* 3010 */ 4, 129, 39, 4, 51, 4, 88, 4, 129, 40,
+/* 3020 */ 4, 50, 4, 87, 5, 129, 41, 4, 50, 4,
+/* 3030 */ 86, 5, 129, 42, 4, 50, 4, 85, 5, 129,
+/* 3040 */ 43, 3, 50, 4, 83, 6, 129, 44, 2, 51,
+/* 3050 */ 5, 80, 7, 129, 46, 1, 52, 6, 76, 9,
+/* 3060 */ 129, 54, 28, 129, 56, 23, 129, 60, 16, 129,
+/* 3070 */ 193, 129, 30, 4, 132, 30, 5, 129, 30, 8,
+/* 3080 */ 129, 30, 12, 129, 30, 16, 129, 30, 4, 37,
+/* 3090 */ 12, 129, 30, 4, 41, 12, 129, 30, 4, 44,
+/* 3100 */ 13, 129, 30, 4, 48, 13, 129, 52, 13, 129,
+/* 3110 */ 56, 12, 129, 58, 14, 129, 58, 4, 64, 12,
+/* 3120 */ 129, 58, 4, 68, 12, 129, 58, 4, 72, 12,
+/* 3130 */ 129, 58, 4, 75, 13, 129, 58, 4, 79, 13,
+/* 3140 */ 129, 58, 4, 83, 13, 129, 58, 4, 87, 13,
+/* 3150 */ 129, 58, 4, 91, 12, 129, 58, 4, 95, 12,
+/* 3160 */ 129, 58, 4, 96, 15, 129, 58, 4, 93, 22,
+/* 3170 */ 129, 58, 4, 89, 30, 129, 58, 4, 85, 36,
+/* 3180 */ 129, 58, 4, 81, 38, 129, 58, 4, 77, 38,
+/* 3190 */ 129, 58, 4, 73, 38, 129, 58, 4, 70, 37,
+/* 3200 */ 129, 58, 4, 66, 37, 129, 58, 41, 129, 58,
+/* 3210 */ 37, 129, 54, 38, 129, 30, 4, 50, 38, 129,
+/* 3220 */ 30, 4, 46, 38, 129, 30, 4, 42, 38, 129,
+/* 3230 */ 30, 4, 38, 39, 129, 30, 43, 129, 30, 39,
+/* 3240 */ 129, 30, 35, 129, 30, 31, 129, 30, 27, 129,
+/* 3250 */ 30, 24, 129, 30, 20, 129, 30, 16, 129, 30,
+/* 3260 */ 12, 129, 30, 8, 129, 30, 5, 129, 30, 4,
+/* 3270 */ 132, 193, 129, 30, 4, 117, 4, 132, 30, 91,
+/* 3280 */ 137, 30, 4, 80, 4, 117, 4, 138, 30, 4,
+/* 3290 */ 80, 5, 116, 5, 129, 30, 5, 79, 6, 116,
+/* 3300 */ 5, 130, 30, 6, 78, 8, 115, 6, 129, 31,
+/* 3310 */ 6, 77, 9, 115, 6, 129, 31, 7, 76, 11,
+/* 3320 */ 114, 6, 129, 31, 8, 75, 14, 112, 8, 129,
+/* 3330 */ 32, 8, 74, 16, 111, 9, 129, 32, 9, 73,
+/* 3340 */ 19, 109, 10, 129, 33, 10, 71, 24, 106, 13,
+/* 3350 */ 129, 33, 13, 68, 12, 83, 35, 129, 34, 16,
+/* 3360 */ 64, 15, 84, 33, 129, 35, 43, 85, 31, 129,
+/* 3370 */ 36, 41, 86, 29, 129, 37, 39, 88, 25, 129,
+/* 3380 */ 38, 37, 90, 21, 129, 40, 33, 93, 15, 129,
+/* 3390 */ 42, 29, 96, 9, 129, 45, 24, 129, 49, 16,
+/* 3400 */ 129, 193, 129, 63, 25, 129, 57, 37, 129, 53,
+/* 3410 */ 45, 129, 50, 51, 129, 47, 57, 129, 45, 61,
+/* 3420 */ 129, 43, 65, 129, 41, 69, 129, 39, 73, 129,
+/* 3430 */ 38, 25, 92, 21, 129, 36, 21, 97, 18, 129,
+/* 3440 */ 35, 18, 102, 14, 129, 34, 16, 106, 11, 129,
+/* 3450 */ 33, 14, 108, 10, 129, 32, 12, 111, 8, 129,
+/* 3460 */ 32, 10, 113, 6, 129, 31, 10, 114, 6, 129,
+/* 3470 */ 31, 8, 115, 5, 129, 30, 8, 116, 5, 129,
+/* 3480 */ 30, 7, 116, 5, 129, 30, 6, 117, 4, 130,
+/* 3490 */ 30, 5, 117, 4, 131, 31, 4, 116, 5, 129,
+/* 3500 */ 32, 4, 116, 4, 129, 32, 5, 115, 5, 129,
+/* 3510 */ 33, 4, 114, 5, 129, 34, 4, 112, 6, 129,
+/* 3520 */ 35, 4, 110, 7, 129, 37, 4, 107, 9, 129,
+/* 3530 */ 39, 4, 103, 12, 129, 41, 4, 103, 18, 129,
+/* 3540 */ 43, 4, 103, 18, 129, 45, 5, 103, 18, 129,
+/* 3550 */ 48, 5, 103, 18, 129, 51, 1, 129, 193, 129,
+/* 3560 */ 30, 4, 117, 4, 132, 30, 91, 137, 30, 4,
+/* 3570 */ 117, 4, 135, 30, 5, 116, 5, 130, 30, 6,
+/* 3580 */ 115, 6, 130, 31, 6, 114, 6, 129, 31, 7,
+/* 3590 */ 113, 7, 129, 32, 7, 112, 7, 129, 32, 8,
+/* 3600 */ 111, 8, 129, 33, 9, 109, 9, 129, 33, 12,
+/* 3610 */ 106, 12, 129, 34, 13, 104, 13, 129, 35, 15,
+/* 3620 */ 101, 15, 129, 36, 19, 96, 19, 129, 37, 24,
+/* 3630 */ 90, 24, 129, 39, 73, 129, 40, 71, 129, 42,
+/* 3640 */ 67, 129, 44, 63, 129, 46, 59, 129, 49, 53,
+/* 3650 */ 129, 52, 47, 129, 56, 39, 129, 61, 29, 129,
+/* 3660 */ 193, 129, 30, 4, 117, 4, 132, 30, 91, 137,
+/* 3670 */ 30, 4, 80, 4, 117, 4, 140, 30, 4, 79,
+/* 3680 */ 6, 117, 4, 129, 30, 4, 77, 10, 117, 4,
+/* 3690 */ 129, 30, 4, 73, 18, 117, 4, 132, 30, 4,
+/* 3700 */ 117, 4, 130, 30, 5, 116, 5, 130, 30, 7,
+/* 3710 */ 114, 7, 129, 30, 8, 113, 8, 129, 30, 11,
+/* 3720 */ 110, 11, 129, 30, 18, 103, 18, 132, 193, 129,
+/* 3730 */ 30, 4, 117, 4, 132, 30, 91, 137, 30, 4,
+/* 3740 */ 80, 4, 117, 4, 132, 80, 4, 117, 4, 136,
+/* 3750 */ 79, 6, 117, 4, 129, 77, 10, 117, 4, 129,
+/* 3760 */ 73, 18, 117, 4, 132, 117, 4, 130, 116, 5,
+/* 3770 */ 130, 114, 7, 129, 113, 8, 129, 110, 11, 129,
+/* 3780 */ 103, 18, 132, 193, 129, 63, 25, 129, 57, 37,
+/* 3790 */ 129, 53, 45, 129, 50, 51, 129, 47, 57, 129,
+/* 3800 */ 45, 61, 129, 43, 65, 129, 41, 69, 129, 39,
+/* 3810 */ 73, 129, 38, 25, 92, 21, 129, 36, 21, 97,
+/* 3820 */ 18, 129, 35, 18, 102, 14, 129, 34, 16, 106,
+/* 3830 */ 11, 129, 33, 14, 108, 10, 129, 32, 12, 111,
+/* 3840 */ 8, 129, 32, 10, 113, 6, 129, 31, 10, 114,
+/* 3850 */ 6, 129, 31, 8, 115, 5, 129, 30, 8, 116,
+/* 3860 */ 5, 129, 30, 7, 116, 5, 129, 30, 6, 117,
+/* 3870 */ 4, 130, 30, 5, 117, 4, 131, 30, 5, 75,
+/* 3880 */ 4, 116, 5, 129, 31, 5, 75, 4, 116, 4,
+/* 3890 */ 129, 31, 6, 75, 4, 115, 5, 129, 32, 7,
+/* 3900 */ 75, 4, 114, 5, 129, 32, 9, 75, 4, 112,
+/* 3910 */ 6, 129, 33, 11, 75, 4, 110, 7, 129, 34,
+/* 3920 */ 15, 75, 4, 107, 9, 129, 35, 44, 103, 12,
+/* 3930 */ 129, 36, 43, 103, 18, 129, 38, 41, 103, 18,
+/* 3940 */ 129, 39, 40, 103, 18, 129, 41, 38, 103, 18,
+/* 3950 */ 129, 44, 35, 129, 48, 31, 129, 52, 27, 129,
+/* 3960 */ 61, 18, 129, 193, 129, 30, 4, 117, 4, 132,
+/* 3970 */ 30, 91, 137, 30, 4, 80, 4, 117, 4, 132,
+/* 3980 */ 80, 4, 140, 30, 4, 80, 4, 117, 4, 132,
+/* 3990 */ 30, 91, 137, 30, 4, 117, 4, 132, 193, 129,
+/* 4000 */ 30, 4, 117, 4, 132, 30, 91, 137, 30, 4,
+/* 4010 */ 117, 4, 132, 193, 129, 44, 7, 129, 40, 13,
+/* 4020 */ 129, 37, 17, 129, 35, 20, 129, 34, 22, 129,
+/* 4030 */ 33, 23, 129, 32, 24, 129, 32, 23, 129, 31,
+/* 4040 */ 6, 41, 13, 129, 31, 5, 42, 11, 129, 30,
+/* 4050 */ 5, 44, 7, 129, 30, 4, 132, 30, 5, 130,
+/* 4060 */ 31, 5, 129, 31, 6, 117, 4, 129, 31, 8,
+/* 4070 */ 117, 4, 129, 32, 9, 117, 4, 129, 33, 11,
+/* 4080 */ 117, 4, 129, 34, 87, 129, 35, 86, 129, 36,
+/* 4090 */ 85, 129, 37, 84, 129, 38, 83, 129, 40, 81,
+/* 4100 */ 129, 42, 79, 129, 45, 76, 129, 50, 71, 129,
+/* 4110 */ 117, 4, 132, 193, 129, 30, 4, 117, 4, 132,
+/* 4120 */ 30, 91, 137, 30, 4, 76, 8, 117, 4, 129,
+/* 4130 */ 30, 4, 73, 13, 117, 4, 129, 30, 4, 70,
+/* 4140 */ 18, 117, 4, 129, 30, 4, 67, 23, 117, 4,
+/* 4150 */ 129, 65, 26, 129, 62, 31, 129, 59, 35, 129,
+/* 4160 */ 56, 29, 89, 7, 129, 53, 29, 91, 7, 129,
+/* 4170 */ 50, 29, 93, 7, 129, 47, 29, 95, 6, 129,
+/* 4180 */ 30, 4, 45, 29, 96, 7, 129, 30, 4, 42,
+/* 4190 */ 29, 98, 7, 129, 30, 4, 39, 30, 100, 6,
+/* 4200 */ 129, 30, 4, 36, 30, 101, 7, 129, 30, 33,
+/* 4210 */ 103, 7, 117, 4, 129, 30, 30, 105, 6, 117,
+/* 4220 */ 4, 129, 30, 27, 106, 7, 117, 4, 129, 30,
+/* 4230 */ 25, 108, 7, 117, 4, 129, 30, 22, 110, 11,
+/* 4240 */ 129, 30, 19, 111, 10, 129, 30, 16, 113, 8,
+/* 4250 */ 129, 30, 13, 115, 6, 129, 30, 11, 116, 5,
+/* 4260 */ 129, 30, 8, 117, 4, 129, 30, 5, 117, 4,
+/* 4270 */ 129, 30, 4, 117, 4, 130, 30, 4, 130, 193,
+/* 4280 */ 129, 30, 4, 117, 4, 132, 30, 91, 137, 30,
+/* 4290 */ 4, 117, 4, 132, 30, 4, 144, 30, 5, 130,
+/* 4300 */ 30, 7, 129, 30, 8, 129, 30, 11, 129, 30,
+/* 4310 */ 18, 132, 193, 129, 30, 4, 117, 4, 132, 30,
+/* 4320 */ 91, 132, 30, 4, 103, 18, 129, 30, 4, 97,
+/* 4330 */ 24, 129, 30, 4, 92, 29, 129, 30, 4, 87,
+/* 4340 */ 34, 129, 81, 40, 129, 76, 45, 129, 70, 49,
+/* 4350 */ 129, 65, 49, 129, 60, 49, 129, 55, 49, 129,
+/* 4360 */ 50, 48, 129, 44, 49, 129, 39, 48, 129, 33,
+/* 4370 */ 49, 129, 30, 47, 129, 34, 37, 129, 40, 26,
+/* 4380 */ 129, 46, 19, 129, 52, 19, 129, 58, 19, 129,
+/* 4390 */ 64, 19, 129, 70, 19, 129, 76, 19, 129, 82,
+/* 4400 */ 19, 129, 30, 4, 88, 18, 129, 30, 4, 94,
+/* 4410 */ 18, 129, 30, 4, 100, 18, 129, 30, 4, 106,
+/* 4420 */ 15, 129, 30, 91, 137, 30, 4, 117, 4, 132,
+/* 4430 */ 193, 129, 30, 4, 117, 4, 132, 30, 91, 132,
+/* 4440 */ 30, 4, 107, 14, 129, 30, 4, 104, 17, 129,
+/* 4450 */ 30, 4, 101, 20, 129, 30, 4, 99, 22, 129,
+/* 4460 */ 96, 25, 129, 93, 28, 129, 91, 28, 129, 88,
+/* 4470 */ 29, 129, 85, 29, 129, 82, 29, 129, 79, 29,
+/* 4480 */ 129, 76, 29, 129, 74, 29, 129, 71, 29, 129,
+/* 4490 */ 68, 29, 129, 65, 29, 129, 62, 29, 129, 60,
+/* 4500 */ 29, 129, 57, 29, 129, 54, 29, 129, 51, 29,
+/* 4510 */ 129, 49, 28, 129, 46, 29, 129, 43, 29, 129,
+/* 4520 */ 40, 29, 117, 4, 129, 37, 29, 117, 4, 129,
+/* 4530 */ 35, 29, 117, 4, 129, 32, 29, 117, 4, 129,
+/* 4540 */ 30, 91, 132, 117, 4, 132, 193, 129, 63, 25,
+/* 4550 */ 129, 57, 37, 129, 53, 45, 129, 50, 51, 129,
+/* 4560 */ 47, 57, 129, 45, 61, 129, 43, 65, 129, 41,
+/* 4570 */ 69, 129, 39, 73, 129, 38, 21, 92, 21, 129,
+/* 4580 */ 36, 18, 97, 18, 129, 35, 14, 102, 14, 129,
+/* 4590 */ 34, 11, 106, 11, 129, 33, 10, 108, 10, 129,
+/* 4600 */ 32, 8, 111, 8, 129, 32, 6, 113, 6, 129,
+/* 4610 */ 31, 6, 114, 6, 129, 31, 5, 115, 5, 129,
+/* 4620 */ 30, 5, 116, 5, 130, 30, 4, 117, 4, 132,
+/* 4630 */ 30, 5, 116, 5, 130, 31, 5, 115, 5, 129,
+/* 4640 */ 31, 6, 114, 6, 129, 32, 6, 113, 6, 129,
+/* 4650 */ 32, 8, 111, 8, 129, 33, 10, 108, 10, 129,
+/* 4660 */ 34, 11, 106, 11, 129, 35, 14, 102, 14, 129,
+/* 4670 */ 36, 18, 97, 18, 129, 38, 21, 92, 21, 129,
+/* 4680 */ 39, 73, 129, 41, 69, 129, 43, 65, 129, 45,
+/* 4690 */ 61, 129, 47, 57, 129, 50, 51, 129, 53, 45,
+/* 4700 */ 129, 57, 37, 129, 63, 25, 129, 193, 129, 30,
+/* 4710 */ 4, 117, 4, 132, 30, 91, 137, 30, 4, 80,
+/* 4720 */ 4, 117, 4, 132, 80, 4, 117, 4, 134, 80,
+/* 4730 */ 5, 116, 5, 131, 80, 6, 115, 6, 130, 81,
+/* 4740 */ 6, 114, 6, 129, 81, 8, 112, 8, 129, 81,
+/* 4750 */ 9, 111, 9, 129, 82, 10, 109, 10, 129, 82,
+/* 4760 */ 13, 106, 13, 129, 83, 35, 129, 84, 33, 129,
+/* 4770 */ 85, 31, 129, 86, 29, 129, 88, 25, 129, 90,
+/* 4780 */ 21, 129, 93, 15, 129, 96, 9, 129, 193, 129,
+/* 4790 */ 63, 25, 129, 57, 37, 129, 53, 45, 129, 50,
+/* 4800 */ 51, 129, 47, 57, 129, 45, 61, 129, 43, 65,
+/* 4810 */ 129, 41, 69, 129, 39, 73, 129, 38, 21, 92,
+/* 4820 */ 21, 129, 36, 18, 97, 18, 129, 35, 14, 102,
+/* 4830 */ 14, 129, 34, 11, 106, 11, 129, 33, 10, 108,
+/* 4840 */ 10, 129, 32, 8, 111, 8, 129, 32, 6, 113,
+/* 4850 */ 6, 129, 31, 6, 114, 6, 129, 31, 5, 115,
+/* 4860 */ 5, 129, 30, 5, 116, 5, 130, 30, 4, 39,
+/* 4870 */ 2, 117, 4, 129, 30, 4, 40, 4, 117, 4,
+/* 4880 */ 129, 30, 4, 41, 5, 117, 4, 129, 30, 4,
+/* 4890 */ 41, 6, 117, 4, 129, 30, 5, 40, 8, 116,
+/* 4900 */ 5, 129, 30, 5, 39, 10, 116, 5, 129, 31,
+/* 4910 */ 5, 38, 11, 115, 5, 129, 31, 18, 114, 6,
+/* 4920 */ 129, 32, 17, 113, 6, 129, 32, 16, 111, 8,
+/* 4930 */ 129, 33, 15, 108, 10, 129, 33, 14, 106, 11,
+/* 4940 */ 129, 32, 17, 102, 14, 129, 31, 23, 97, 18,
+/* 4950 */ 129, 31, 28, 92, 21, 129, 30, 82, 129, 30,
+/* 4960 */ 80, 129, 30, 11, 43, 65, 129, 30, 10, 45,
+/* 4970 */ 61, 129, 31, 8, 47, 57, 129, 32, 6, 50,
+/* 4980 */ 51, 129, 33, 5, 53, 45, 129, 35, 4, 57,
+/* 4990 */ 37, 129, 38, 2, 63, 25, 129, 193, 129, 30,
+/* 5000 */ 4, 117, 4, 132, 30, 91, 137, 30, 4, 76,
+/* 5010 */ 8, 117, 4, 129, 30, 4, 73, 11, 117, 4,
+/* 5020 */ 129, 30, 4, 70, 14, 117, 4, 129, 30, 4,
+/* 5030 */ 67, 17, 117, 4, 129, 65, 19, 117, 4, 129,
+/* 5040 */ 62, 22, 117, 4, 129, 59, 25, 117, 4, 129,
+/* 5050 */ 56, 28, 117, 4, 129, 53, 31, 117, 4, 129,
+/* 5060 */ 50, 34, 117, 4, 129, 47, 29, 80, 5, 116,
+/* 5070 */ 5, 129, 30, 4, 45, 29, 80, 5, 116, 5,
+/* 5080 */ 129, 30, 4, 42, 29, 80, 5, 116, 5, 129,
+/* 5090 */ 30, 4, 39, 30, 80, 6, 115, 6, 129, 30,
+/* 5100 */ 4, 36, 30, 80, 6, 115, 6, 129, 30, 33,
+/* 5110 */ 81, 6, 114, 6, 129, 30, 30, 81, 8, 112,
+/* 5120 */ 8, 129, 30, 27, 81, 9, 111, 9, 129, 30,
+/* 5130 */ 25, 82, 10, 109, 10, 129, 30, 22, 82, 13,
+/* 5140 */ 106, 13, 129, 30, 19, 83, 35, 129, 30, 16,
+/* 5150 */ 84, 33, 129, 30, 13, 85, 31, 129, 30, 11,
+/* 5160 */ 86, 29, 129, 30, 8, 88, 25, 129, 30, 5,
+/* 5170 */ 90, 21, 129, 30, 4, 93, 15, 129, 30, 4,
+/* 5180 */ 96, 9, 129, 30, 4, 130, 193, 129, 30, 18,
+/* 5190 */ 130, 30, 18, 89, 15, 129, 30, 18, 85, 23,
+/* 5200 */ 129, 34, 11, 83, 27, 129, 34, 9, 81, 31,
+/* 5210 */ 129, 33, 8, 79, 35, 129, 33, 6, 78, 16,
+/* 5220 */ 106, 9, 129, 32, 6, 77, 15, 109, 7, 129,
+/* 5230 */ 32, 5, 76, 14, 111, 6, 129, 31, 5, 75,
+/* 5240 */ 14, 113, 5, 129, 31, 4, 74, 15, 114, 5,
+/* 5250 */ 129, 31, 4, 74, 14, 115, 4, 129, 30, 4,
+/* 5260 */ 73, 15, 116, 4, 129, 30, 4, 73, 14, 116,
+/* 5270 */ 4, 129, 30, 4, 73, 14, 117, 4, 129, 30,
+/* 5280 */ 4, 72, 15, 117, 4, 130, 30, 4, 71, 15,
+/* 5290 */ 117, 4, 130, 30, 4, 70, 15, 117, 4, 129,
+/* 5300 */ 30, 5, 70, 15, 117, 4, 129, 30, 5, 69,
+/* 5310 */ 15, 116, 5, 129, 30, 6, 68, 16, 115, 5,
+/* 5320 */ 129, 31, 6, 67, 16, 114, 6, 129, 31, 7,
+/* 5330 */ 66, 17, 113, 6, 129, 32, 7, 64, 18, 111,
+/* 5340 */ 8, 129, 32, 8, 62, 19, 109, 9, 129, 33,
+/* 5350 */ 9, 60, 20, 107, 10, 129, 34, 11, 57, 22,
+/* 5360 */ 103, 13, 129, 35, 43, 103, 18, 129, 36, 41,
+/* 5370 */ 103, 18, 129, 38, 38, 103, 18, 129, 39, 35,
+/* 5380 */ 103, 18, 129, 41, 31, 129, 43, 27, 129, 46,
+/* 5390 */ 22, 129, 49, 14, 129, 193, 129, 103, 18, 132,
+/* 5400 */ 110, 11, 129, 113, 8, 129, 114, 7, 129, 116,
+/* 5410 */ 5, 130, 117, 4, 132, 30, 4, 117, 4, 132,
+/* 5420 */ 30, 91, 137, 30, 4, 117, 4, 132, 117, 4,
+/* 5430 */ 132, 116, 5, 130, 114, 7, 129, 113, 8, 129,
+/* 5440 */ 110, 11, 129, 103, 18, 132, 193, 129, 117, 4,
+/* 5450 */ 132, 56, 65, 129, 50, 71, 129, 46, 75, 129,
+/* 5460 */ 44, 77, 129, 42, 79, 129, 40, 81, 129, 38,
+/* 5470 */ 83, 129, 36, 85, 129, 35, 86, 129, 34, 20,
+/* 5480 */ 117, 4, 129, 33, 17, 117, 4, 129, 32, 15,
+/* 5490 */ 117, 4, 129, 32, 13, 117, 4, 129, 31, 12,
+/* 5500 */ 129, 31, 10, 129, 31, 9, 129, 30, 9, 129,
+/* 5510 */ 30, 8, 130, 30, 7, 132, 31, 6, 130, 31,
+/* 5520 */ 7, 129, 32, 6, 129, 32, 7, 129, 33, 7,
+/* 5530 */ 129, 34, 7, 129, 35, 8, 129, 36, 9, 117,
+/* 5540 */ 4, 129, 38, 9, 117, 4, 129, 40, 10, 117,
+/* 5550 */ 4, 129, 42, 12, 117, 4, 129, 44, 77, 129,
+/* 5560 */ 46, 75, 129, 50, 71, 129, 56, 43, 100, 21,
+/* 5570 */ 129, 117, 4, 132, 193, 129, 117, 4, 132, 115,
+/* 5580 */ 6, 129, 110, 11, 129, 105, 16, 129, 101, 20,
+/* 5590 */ 129, 96, 25, 129, 92, 29, 129, 87, 34, 129,
+/* 5600 */ 83, 38, 129, 78, 43, 129, 74, 47, 129, 70,
+/* 5610 */ 42, 117, 4, 129, 65, 42, 117, 4, 129, 60,
+/* 5620 */ 43, 117, 4, 129, 56, 42, 129, 51, 42, 129,
+/* 5630 */ 46, 43, 129, 42, 43, 129, 37, 44, 129, 33,
+/* 5640 */ 43, 129, 30, 42, 129, 33, 34, 129, 38, 25,
+/* 5650 */ 129, 42, 16, 129, 47, 15, 129, 52, 15, 129,
+/* 5660 */ 57, 15, 129, 61, 16, 129, 66, 16, 129, 71,
+/* 5670 */ 16, 129, 76, 16, 129, 80, 16, 129, 85, 16,
+/* 5680 */ 117, 4, 129, 90, 16, 117, 4, 129, 95, 16,
+/* 5690 */ 117, 4, 129, 100, 21, 129, 105, 16, 129, 110,
+/* 5700 */ 11, 129, 114, 7, 129, 117, 4, 132, 193, 129,
+/* 5710 */ 117, 4, 132, 115, 6, 129, 110, 11, 129, 105,
+/* 5720 */ 16, 129, 101, 20, 129, 96, 25, 129, 92, 29,
+/* 5730 */ 129, 87, 34, 129, 83, 38, 129, 78, 43, 129,
+/* 5740 */ 74, 47, 129, 70, 42, 117, 4, 129, 65, 42,
+/* 5750 */ 117, 4, 129, 60, 43, 117, 4, 129, 56, 42,
+/* 5760 */ 129, 51, 42, 129, 46, 43, 129, 42, 43, 129,
+/* 5770 */ 37, 44, 129, 33, 43, 129, 30, 42, 129, 33,
+/* 5780 */ 34, 129, 38, 25, 129, 42, 16, 129, 47, 15,
+/* 5790 */ 129, 52, 15, 129, 57, 15, 129, 61, 16, 129,
+/* 5800 */ 65, 17, 129, 60, 27, 129, 56, 36, 129, 51,
+/* 5810 */ 42, 129, 46, 43, 129, 42, 43, 129, 37, 44,
+/* 5820 */ 129, 33, 43, 129, 30, 42, 129, 33, 34, 129,
+/* 5830 */ 38, 25, 129, 42, 16, 129, 47, 15, 129, 52,
+/* 5840 */ 15, 129, 57, 15, 129, 61, 16, 129, 66, 16,
+/* 5850 */ 129, 71, 16, 129, 76, 16, 129, 80, 16, 129,
+/* 5860 */ 85, 16, 117, 4, 129, 90, 16, 117, 4, 129,
+/* 5870 */ 95, 16, 117, 4, 129, 100, 21, 129, 105, 16,
+/* 5880 */ 129, 110, 11, 129, 114, 7, 129, 117, 4, 132,
+/* 5890 */ 193, 129, 30, 4, 117, 4, 132, 30, 4, 115,
+/* 5900 */ 6, 129, 30, 4, 112, 9, 129, 30, 6, 109,
+/* 5910 */ 12, 129, 30, 9, 106, 15, 129, 30, 11, 103,
+/* 5920 */ 18, 129, 30, 14, 100, 21, 129, 30, 4, 38,
+/* 5930 */ 9, 98, 23, 129, 30, 4, 40, 10, 95, 26,
+/* 5940 */ 129, 30, 4, 43, 9, 92, 29, 129, 46, 9,
+/* 5950 */ 89, 32, 129, 49, 8, 86, 28, 117, 4, 129,
+/* 5960 */ 51, 9, 83, 28, 117, 4, 129, 54, 9, 80,
+/* 5970 */ 28, 117, 4, 129, 57, 8, 77, 28, 117, 4,
+/* 5980 */ 129, 59, 9, 74, 28, 129, 62, 37, 129, 64,
+/* 5990 */ 33, 129, 66, 28, 129, 63, 28, 129, 60, 28,
+/* 6000 */ 129, 57, 28, 129, 54, 33, 129, 51, 39, 129,
+/* 6010 */ 48, 29, 83, 9, 129, 30, 4, 45, 29, 86,
+/* 6020 */ 9, 129, 30, 4, 42, 29, 89, 9, 129, 30,
+/* 6030 */ 4, 39, 29, 92, 8, 129, 30, 4, 36, 29,
+/* 6040 */ 94, 9, 129, 30, 32, 97, 9, 129, 30, 29,
+/* 6050 */ 100, 8, 117, 4, 129, 30, 26, 103, 8, 117,
+/* 6060 */ 4, 129, 30, 23, 105, 9, 117, 4, 129, 30,
+/* 6070 */ 20, 108, 13, 129, 30, 18, 111, 10, 129, 30,
+/* 6080 */ 15, 113, 8, 129, 30, 12, 116, 5, 129, 30,
+/* 6090 */ 9, 117, 4, 129, 30, 6, 117, 4, 129, 30,
+/* 6100 */ 4, 117, 4, 132, 193, 129, 117, 4, 132, 114,
+/* 6110 */ 7, 129, 111, 10, 129, 108, 13, 129, 105, 16,
+/* 6120 */ 129, 102, 19, 129, 100, 21, 129, 96, 25, 129,
+/* 6130 */ 93, 28, 129, 90, 31, 129, 87, 34, 129, 84,
+/* 6140 */ 30, 117, 4, 129, 30, 4, 81, 30, 117, 4,
+/* 6150 */ 129, 30, 4, 78, 30, 117, 4, 129, 30, 4,
+/* 6160 */ 75, 30, 117, 4, 129, 30, 4, 72, 30, 129,
+/* 6170 */ 30, 69, 129, 30, 66, 129, 30, 63, 129, 30,
+/* 6180 */ 60, 129, 30, 57, 129, 30, 54, 129, 30, 51,
+/* 6190 */ 129, 30, 48, 129, 30, 51, 129, 30, 4, 73,
+/* 6200 */ 12, 129, 30, 4, 76, 12, 129, 30, 4, 80,
+/* 6210 */ 12, 129, 30, 4, 83, 12, 129, 87, 12, 129,
+/* 6220 */ 90, 12, 117, 4, 129, 94, 11, 117, 4, 129,
+/* 6230 */ 97, 12, 117, 4, 129, 101, 12, 117, 4, 129,
+/* 6240 */ 104, 17, 129, 108, 13, 129, 111, 10, 129, 115,
+/* 6250 */ 6, 129, 117, 4, 134, 193, 129, 30, 1, 103,
+/* 6260 */ 18, 129, 30, 4, 103, 18, 129, 30, 7, 103,
+/* 6270 */ 18, 129, 30, 9, 103, 18, 129, 30, 12, 110,
+/* 6280 */ 11, 129, 30, 15, 113, 8, 129, 30, 18, 114,
+/* 6290 */ 7, 129, 30, 21, 116, 5, 129, 30, 24, 116,
+/* 6300 */ 5, 129, 30, 27, 117, 4, 129, 30, 30, 117,
+/* 6310 */ 4, 129, 30, 33, 117, 4, 129, 30, 4, 37,
+/* 6320 */ 28, 117, 4, 129, 30, 4, 40, 28, 117, 4,
+/* 6330 */ 129, 30, 4, 42, 29, 117, 4, 129, 30, 4,
+/* 6340 */ 45, 29, 117, 4, 129, 30, 4, 48, 29, 117,
+/* 6350 */ 4, 129, 30, 4, 51, 29, 117, 4, 129, 30,
+/* 6360 */ 4, 54, 29, 117, 4, 129, 30, 4, 57, 29,
+/* 6370 */ 117, 4, 129, 30, 4, 59, 30, 117, 4, 129,
+/* 6380 */ 30, 4, 62, 30, 117, 4, 129, 30, 4, 65,
+/* 6390 */ 30, 117, 4, 129, 30, 4, 68, 30, 117, 4,
+/* 6400 */ 129, 30, 4, 71, 30, 117, 4, 129, 30, 4,
+/* 6410 */ 74, 30, 117, 4, 129, 30, 4, 77, 30, 117,
+/* 6420 */ 4, 129, 30, 4, 80, 30, 117, 4, 129, 30,
+/* 6430 */ 4, 83, 30, 117, 4, 129, 30, 4, 86, 35,
+/* 6440 */ 129, 30, 4, 89, 32, 129, 30, 4, 91, 30,
+/* 6450 */ 129, 30, 4, 94, 27, 129, 30, 5, 97, 24,
+/* 6460 */ 129, 30, 5, 100, 21, 129, 30, 7, 103, 18,
+/* 6470 */ 129, 30, 8, 106, 15, 129, 30, 11, 109, 12,
+/* 6480 */ 129, 30, 18, 112, 9, 129, 30, 18, 115, 6,
+/* 6490 */ 129, 30, 18, 117, 4, 129, 30, 18, 120, 1,
+/* 6500 */ 129, 193, 129, 42, 8, 129, 38, 16, 129, 36,
+/* 6510 */ 20, 129, 34, 24, 71, 5, 129, 33, 26, 69,
+/* 6520 */ 10, 129, 32, 28, 68, 13, 129, 31, 30, 68,
+/* 6530 */ 14, 129, 31, 9, 52, 9, 68, 15, 129, 30,
+/* 6540 */ 8, 54, 8, 69, 14, 129, 30, 7, 55, 7,
+/* 6550 */ 71, 4, 78, 6, 129, 30, 6, 56, 6, 79,
+/* 6560 */ 5, 129, 30, 6, 56, 6, 80, 4, 130, 31,
+/* 6570 */ 5, 56, 5, 80, 4, 129, 31, 5, 56, 5,
+/* 6580 */ 79, 5, 129, 32, 5, 55, 5, 78, 6, 129,
+/* 6590 */ 33, 5, 54, 5, 77, 7, 129, 34, 6, 52,
+/* 6600 */ 6, 74, 9, 129, 35, 48, 129, 33, 49, 129,
+/* 6610 */ 32, 49, 129, 31, 49, 129, 30, 49, 129, 30,
+/* 6620 */ 47, 129, 30, 45, 129, 30, 41, 129, 30, 6,
+/* 6630 */ 129, 30, 4, 129, 30, 3, 129, 30, 2, 129,
+/* 6640 */ 193, 129, 30, 4, 117, 4, 130, 31, 90, 136,
+/* 6650 */ 37, 5, 72, 5, 129, 35, 5, 74, 5, 129,
+/* 6660 */ 33, 5, 76, 5, 129, 32, 5, 77, 5, 129,
+/* 6670 */ 31, 5, 78, 5, 129, 31, 4, 79, 4, 129,
+/* 6680 */ 30, 5, 79, 5, 131, 30, 6, 78, 6, 129,
+/* 6690 */ 30, 7, 77, 7, 129, 31, 8, 75, 8, 129,
+/* 6700 */ 31, 11, 72, 11, 129, 32, 15, 67, 15, 129,
+/* 6710 */ 33, 48, 129, 34, 46, 129, 35, 44, 129, 37,
+/* 6720 */ 40, 129, 39, 36, 129, 42, 30, 129, 46, 22,
+/* 6730 */ 129, 193, 129, 48, 18, 129, 43, 28, 129, 41,
+/* 6740 */ 32, 129, 39, 36, 129, 37, 40, 129, 35, 44,
+/* 6750 */ 129, 34, 46, 129, 33, 13, 68, 13, 129, 32,
+/* 6760 */ 9, 73, 9, 129, 32, 7, 75, 7, 129, 31,
+/* 6770 */ 6, 77, 6, 129, 31, 5, 78, 5, 129, 30,
+/* 6780 */ 5, 79, 5, 129, 30, 4, 80, 4, 133, 31,
+/* 6790 */ 3, 79, 4, 129, 31, 4, 79, 4, 129, 32,
+/* 6800 */ 3, 78, 4, 129, 32, 4, 76, 6, 129, 33,
+/* 6810 */ 4, 74, 7, 129, 34, 4, 72, 8, 129, 35,
+/* 6820 */ 5, 72, 7, 129, 37, 5, 73, 4, 129, 39,
+/* 6830 */ 4, 74, 1, 129, 129, 193, 129, 46, 22, 129,
+/* 6840 */ 42, 30, 129, 39, 36, 129, 37, 40, 129, 35,
+/* 6850 */ 44, 129, 34, 46, 129, 33, 48, 129, 32, 15,
+/* 6860 */ 67, 15, 129, 31, 11, 72, 11, 129, 31, 8,
+/* 6870 */ 75, 8, 129, 30, 7, 77, 7, 129, 30, 6,
+/* 6880 */ 78, 6, 129, 30, 5, 79, 5, 131, 31, 4,
+/* 6890 */ 79, 4, 129, 31, 5, 78, 5, 129, 32, 5,
+/* 6900 */ 77, 5, 129, 33, 5, 76, 5, 129, 35, 5,
+/* 6910 */ 74, 5, 117, 4, 129, 37, 5, 72, 5, 117,
+/* 6920 */ 4, 129, 30, 91, 136, 30, 4, 130, 193, 129,
+/* 6930 */ 48, 18, 129, 43, 28, 129, 41, 32, 129, 39,
+/* 6940 */ 36, 129, 37, 40, 129, 35, 44, 129, 34, 46,
+/* 6950 */ 129, 33, 13, 55, 4, 68, 13, 129, 32, 9,
+/* 6960 */ 55, 4, 73, 9, 129, 32, 7, 55, 4, 75,
+/* 6970 */ 7, 129, 31, 6, 55, 4, 77, 6, 129, 31,
+/* 6980 */ 5, 55, 4, 78, 5, 129, 30, 5, 55, 4,
+/* 6990 */ 79, 5, 129, 30, 4, 55, 4, 80, 4, 132,
+/* 7000 */ 30, 4, 55, 4, 79, 5, 129, 31, 3, 55,
+/* 7010 */ 4, 78, 5, 129, 31, 4, 55, 4, 77, 6,
+/* 7020 */ 129, 32, 3, 55, 4, 75, 7, 129, 32, 4,
+/* 7030 */ 55, 4, 73, 9, 129, 33, 4, 55, 4, 68,
+/* 7040 */ 13, 129, 34, 4, 55, 25, 129, 35, 5, 55,
+/* 7050 */ 24, 129, 37, 5, 55, 22, 129, 39, 4, 55,
+/* 7060 */ 20, 129, 55, 18, 129, 55, 16, 129, 55, 11,
+/* 7070 */ 129, 193, 129, 80, 4, 129, 30, 4, 80, 4,
+/* 7080 */ 130, 30, 78, 129, 30, 82, 129, 30, 85, 129,
+/* 7090 */ 30, 87, 129, 30, 88, 129, 30, 89, 129, 30,
+/* 7100 */ 90, 130, 30, 4, 80, 4, 115, 6, 129, 30,
+/* 7110 */ 4, 80, 4, 117, 4, 129, 80, 4, 105, 6,
+/* 7120 */ 117, 4, 129, 80, 4, 103, 10, 116, 5, 129,
+/* 7130 */ 80, 4, 102, 19, 129, 80, 4, 101, 19, 129,
+/* 7140 */ 101, 19, 129, 101, 18, 129, 102, 16, 129, 103,
+/* 7150 */ 12, 129, 105, 6, 129, 193, 129, 12, 10, 59,
+/* 7160 */ 11, 129, 9, 16, 55, 19, 129, 7, 20, 53,
+/* 7170 */ 23, 129, 6, 7, 23, 5, 32, 6, 51, 27,
+/* 7180 */ 129, 4, 7, 25, 16, 50, 29, 129, 3, 6,
+/* 7190 */ 27, 16, 49, 31, 129, 2, 6, 28, 16, 48,
+/* 7200 */ 33, 129, 1, 6, 27, 18, 47, 35, 129, 1,
+/* 7210 */ 6, 27, 31, 71, 12, 129, 1, 5, 26, 15,
+/* 7220 */ 44, 10, 75, 8, 129, 1, 5, 25, 14, 45,
+/* 7230 */ 7, 77, 7, 129, 1, 5, 25, 13, 45, 5,
+/* 7240 */ 79, 5, 129, 1, 5, 24, 14, 45, 4, 80,
+/* 7250 */ 4, 129, 1, 5, 24, 13, 45, 4, 80, 4,
+/* 7260 */ 129, 1, 5, 23, 14, 45, 4, 80, 4, 129,
+/* 7270 */ 1, 5, 23, 13, 45, 4, 80, 4, 129, 1,
+/* 7280 */ 6, 22, 13, 45, 5, 79, 5, 129, 1, 6,
+/* 7290 */ 21, 14, 45, 7, 77, 7, 129, 1, 7, 21,
+/* 7300 */ 13, 46, 8, 75, 8, 129, 1, 8, 20, 13,
+/* 7310 */ 46, 12, 71, 12, 129, 1, 10, 18, 15, 47,
+/* 7320 */ 35, 129, 2, 30, 48, 33, 129, 3, 29, 49,
+/* 7330 */ 32, 129, 4, 27, 50, 31, 129, 5, 25, 51,
+/* 7340 */ 27, 80, 2, 86, 4, 129, 7, 21, 53, 23,
+/* 7350 */ 80, 3, 85, 6, 129, 9, 17, 55, 19, 80,
+/* 7360 */ 12, 129, 12, 12, 59, 11, 81, 11, 129, 82,
+/* 7370 */ 10, 129, 84, 7, 129, 86, 4, 129, 193, 129,
+/* 7380 */ 30, 4, 117, 4, 130, 30, 91, 136, 30, 4,
+/* 7390 */ 72, 5, 129, 30, 4, 74, 5, 129, 75, 5,
+/* 7400 */ 129, 76, 5, 129, 76, 6, 129, 77, 6, 130,
+/* 7410 */ 77, 7, 130, 76, 8, 129, 30, 4, 75, 9,
+/* 7420 */ 129, 30, 4, 72, 12, 129, 30, 54, 129, 30,
+/* 7430 */ 53, 130, 30, 52, 129, 30, 51, 129, 30, 49,
+/* 7440 */ 129, 30, 46, 129, 30, 42, 129, 30, 4, 130,
+/* 7450 */ 193, 129, 30, 4, 80, 4, 129, 30, 4, 80,
+/* 7460 */ 4, 100, 6, 129, 30, 54, 98, 10, 129, 30,
+/* 7470 */ 54, 97, 12, 129, 30, 54, 96, 14, 131, 30,
+/* 7480 */ 54, 97, 12, 129, 30, 54, 98, 10, 129, 30,
+/* 7490 */ 54, 100, 6, 129, 30, 4, 130, 193, 129, 7,
+/* 7500 */ 6, 129, 4, 11, 129, 3, 13, 129, 2, 14,
+/* 7510 */ 129, 1, 15, 130, 1, 3, 6, 9, 129, 1,
+/* 7520 */ 3, 7, 6, 129, 1, 3, 130, 1, 4, 129,
+/* 7530 */ 1, 5, 80, 4, 129, 1, 7, 80, 4, 100,
+/* 7540 */ 6, 129, 2, 82, 98, 10, 129, 3, 81, 97,
+/* 7550 */ 12, 129, 4, 80, 96, 14, 129, 5, 79, 96,
+/* 7560 */ 14, 129, 7, 77, 96, 14, 129, 10, 74, 97,
+/* 7570 */ 12, 129, 14, 70, 98, 10, 129, 19, 65, 100,
+/* 7580 */ 6, 129, 193, 129, 30, 4, 117, 4, 130, 30,
+/* 7590 */ 91, 136, 30, 4, 57, 9, 129, 30, 4, 55,
+/* 7600 */ 12, 129, 52, 17, 129, 50, 20, 129, 48, 24,
+/* 7610 */ 129, 46, 27, 129, 44, 21, 69, 6, 129, 41,
+/* 7620 */ 22, 70, 6, 80, 4, 129, 30, 4, 39, 21,
+/* 7630 */ 72, 6, 80, 4, 129, 30, 4, 36, 22, 73,
+/* 7640 */ 11, 129, 30, 26, 75, 9, 129, 30, 23, 76,
+/* 7650 */ 8, 129, 30, 21, 78, 6, 129, 30, 19, 79,
+/* 7660 */ 5, 129, 30, 16, 80, 4, 129, 30, 14, 80,
+/* 7670 */ 4, 129, 30, 12, 129, 30, 10, 129, 30, 7,
+/* 7680 */ 129, 30, 5, 129, 30, 4, 130, 193, 129, 30,
+/* 7690 */ 4, 117, 4, 130, 30, 91, 136, 30, 4, 130,
+/* 7700 */ 193, 129, 30, 4, 80, 4, 130, 30, 54, 136,
+/* 7710 */ 30, 4, 72, 5, 129, 30, 4, 74, 5, 129,
+/* 7720 */ 75, 5, 129, 76, 5, 129, 30, 4, 75, 7,
+/* 7730 */ 129, 30, 4, 74, 9, 129, 30, 54, 132, 30,
+/* 7740 */ 53, 129, 30, 52, 129, 30, 51, 129, 30, 48,
+/* 7750 */ 129, 30, 4, 72, 5, 129, 30, 4, 74, 5,
+/* 7760 */ 129, 75, 5, 129, 76, 5, 129, 30, 4, 75,
+/* 7770 */ 7, 129, 30, 4, 74, 9, 129, 30, 54, 132,
+/* 7780 */ 30, 53, 129, 30, 52, 129, 30, 51, 129, 30,
+/* 7790 */ 48, 129, 30, 4, 130, 193, 129, 30, 4, 80,
+/* 7800 */ 4, 130, 30, 54, 136, 30, 4, 72, 5, 129,
+/* 7810 */ 30, 4, 74, 5, 129, 75, 5, 129, 76, 5,
+/* 7820 */ 129, 76, 6, 129, 77, 6, 130, 77, 7, 130,
+/* 7830 */ 76, 8, 129, 30, 4, 75, 9, 129, 30, 4,
+/* 7840 */ 72, 12, 129, 30, 54, 129, 30, 53, 130, 30,
+/* 7850 */ 52, 129, 30, 51, 129, 30, 49, 129, 30, 46,
+/* 7860 */ 129, 30, 42, 129, 30, 4, 130, 193, 129, 48,
+/* 7870 */ 18, 129, 43, 28, 129, 41, 32, 129, 39, 36,
+/* 7880 */ 129, 37, 40, 129, 35, 44, 129, 34, 46, 129,
+/* 7890 */ 33, 13, 68, 13, 129, 32, 9, 73, 9, 129,
+/* 7900 */ 32, 7, 75, 7, 129, 31, 6, 77, 6, 129,
+/* 7910 */ 31, 5, 78, 5, 129, 30, 5, 79, 5, 129,
+/* 7920 */ 30, 4, 80, 4, 132, 30, 5, 79, 5, 130,
+/* 7930 */ 31, 5, 78, 5, 129, 31, 6, 77, 6, 129,
+/* 7940 */ 32, 7, 75, 7, 129, 32, 9, 73, 9, 129,
+/* 7950 */ 33, 13, 68, 13, 129, 34, 46, 129, 35, 44,
+/* 7960 */ 129, 37, 40, 129, 39, 36, 129, 41, 32, 129,
+/* 7970 */ 43, 28, 129, 48, 18, 129, 193, 129, 1, 3,
+/* 7980 */ 80, 4, 130, 1, 83, 137, 37, 5, 72, 5,
+/* 7990 */ 129, 35, 5, 74, 5, 129, 33, 5, 76, 5,
+/* 8000 */ 129, 32, 5, 77, 5, 129, 31, 5, 78, 5,
+/* 8010 */ 129, 31, 4, 79, 4, 129, 30, 5, 79, 5,
+/* 8020 */ 131, 30, 6, 78, 6, 129, 30, 7, 77, 7,
+/* 8030 */ 129, 31, 8, 75, 8, 129, 31, 11, 72, 11,
+/* 8040 */ 129, 32, 15, 67, 15, 129, 33, 48, 129, 34,
+/* 8050 */ 46, 129, 35, 44, 129, 37, 40, 129, 39, 36,
+/* 8060 */ 129, 42, 30, 129, 46, 22, 129, 193, 129, 46,
+/* 8070 */ 22, 129, 42, 30, 129, 39, 36, 129, 37, 40,
+/* 8080 */ 129, 35, 44, 129, 34, 46, 129, 33, 48, 129,
+/* 8090 */ 32, 15, 67, 15, 129, 31, 11, 72, 11, 129,
+/* 8100 */ 31, 8, 75, 8, 129, 30, 7, 77, 7, 129,
+/* 8110 */ 30, 6, 78, 6, 129, 30, 5, 79, 5, 131,
+/* 8120 */ 31, 4, 79, 4, 129, 31, 5, 78, 5, 129,
+/* 8130 */ 32, 5, 77, 5, 129, 33, 5, 76, 5, 129,
+/* 8140 */ 35, 5, 74, 5, 129, 37, 5, 72, 5, 129,
+/* 8150 */ 1, 83, 136, 1, 3, 80, 4, 130, 193, 129,
+/* 8160 */ 30, 4, 80, 4, 130, 30, 54, 136, 30, 4,
+/* 8170 */ 68, 6, 129, 30, 4, 70, 6, 129, 71, 7,
+/* 8180 */ 129, 72, 7, 129, 73, 7, 129, 74, 7, 129,
+/* 8190 */ 74, 8, 129, 75, 8, 130, 69, 15, 129, 67,
+/* 8200 */ 17, 129, 66, 18, 129, 65, 19, 130, 65, 18,
+/* 8210 */ 130, 66, 16, 129, 67, 13, 129, 69, 8, 129,
+/* 8220 */ 193, 129, 30, 13, 64, 8, 129, 30, 13, 61,
+/* 8230 */ 14, 129, 30, 13, 59, 18, 129, 30, 13, 57,
+/* 8240 */ 22, 129, 33, 8, 56, 24, 129, 32, 7, 55,
+/* 8250 */ 26, 129, 32, 6, 54, 28, 129, 31, 6, 53,
+/* 8260 */ 16, 77, 6, 129, 31, 5, 53, 14, 79, 4,
+/* 8270 */ 129, 30, 5, 52, 14, 80, 4, 129, 30, 5,
+/* 8280 */ 52, 13, 80, 4, 129, 30, 4, 52, 13, 80,
+/* 8290 */ 4, 129, 30, 4, 52, 12, 80, 4, 129, 30,
+/* 8300 */ 4, 51, 13, 80, 4, 130, 30, 4, 50, 13,
+/* 8310 */ 79, 5, 129, 30, 4, 50, 13, 78, 5, 129,
+/* 8320 */ 30, 5, 49, 14, 77, 6, 129, 31, 4, 49,
+/* 8330 */ 13, 76, 6, 129, 31, 5, 48, 14, 75, 7,
+/* 8340 */ 129, 32, 5, 47, 14, 73, 8, 129, 32, 6,
+/* 8350 */ 45, 16, 71, 13, 129, 33, 27, 71, 13, 129,
+/* 8360 */ 34, 26, 71, 13, 129, 35, 24, 71, 13, 129,
+/* 8370 */ 37, 20, 129, 39, 16, 129, 43, 9, 129, 193,
+/* 8380 */ 129, 80, 4, 131, 41, 56, 129, 37, 60, 129,
+/* 8390 */ 35, 62, 129, 33, 64, 129, 32, 65, 129, 31,
+/* 8400 */ 66, 129, 30, 67, 130, 30, 11, 80, 4, 129,
+/* 8410 */ 30, 9, 80, 4, 129, 30, 8, 80, 4, 129,
+/* 8420 */ 31, 7, 80, 4, 129, 31, 6, 129, 32, 5,
+/* 8430 */ 129, 33, 5, 129, 35, 4, 129, 38, 3, 129,
+/* 8440 */ 193, 129, 80, 4, 130, 42, 42, 129, 38, 46,
+/* 8450 */ 129, 35, 49, 129, 33, 51, 129, 32, 52, 129,
+/* 8460 */ 31, 53, 130, 30, 54, 129, 30, 12, 129, 30,
+/* 8470 */ 9, 129, 30, 8, 129, 30, 7, 130, 31, 6,
+/* 8480 */ 130, 32, 6, 129, 33, 5, 129, 34, 5, 129,
+/* 8490 */ 35, 5, 80, 4, 129, 37, 5, 80, 4, 129,
+/* 8500 */ 30, 54, 136, 30, 4, 130, 193, 129, 80, 4,
+/* 8510 */ 130, 77, 7, 129, 74, 10, 129, 70, 14, 129,
+/* 8520 */ 66, 18, 129, 62, 22, 129, 59, 25, 129, 55,
+/* 8530 */ 29, 129, 51, 33, 129, 47, 37, 129, 44, 32,
+/* 8540 */ 80, 4, 129, 40, 32, 80, 4, 129, 36, 32,
+/* 8550 */ 129, 32, 33, 129, 30, 31, 129, 33, 24, 129,
+/* 8560 */ 36, 17, 129, 40, 12, 129, 44, 12, 129, 48,
+/* 8570 */ 12, 129, 51, 13, 129, 55, 13, 129, 59, 13,
+/* 8580 */ 80, 4, 129, 63, 13, 80, 4, 129, 67, 17,
+/* 8590 */ 129, 71, 13, 129, 74, 10, 129, 78, 6, 129,
+/* 8600 */ 80, 4, 131, 193, 129, 80, 4, 130, 77, 7,
+/* 8610 */ 129, 74, 10, 129, 70, 14, 129, 66, 18, 129,
+/* 8620 */ 62, 22, 129, 59, 25, 129, 55, 29, 129, 51,
+/* 8630 */ 33, 129, 47, 37, 129, 44, 32, 80, 4, 129,
+/* 8640 */ 40, 32, 80, 4, 129, 36, 32, 129, 32, 33,
+/* 8650 */ 129, 30, 31, 129, 33, 24, 129, 36, 17, 129,
+/* 8660 */ 40, 12, 129, 44, 12, 129, 47, 13, 129, 44,
+/* 8670 */ 20, 129, 40, 28, 129, 36, 31, 129, 32, 32,
+/* 8680 */ 129, 30, 30, 129, 33, 24, 129, 36, 17, 129,
+/* 8690 */ 40, 12, 129, 44, 12, 129, 48, 12, 129, 51,
+/* 8700 */ 13, 129, 55, 13, 129, 59, 13, 80, 4, 129,
+/* 8710 */ 63, 13, 80, 4, 129, 67, 17, 129, 71, 13,
+/* 8720 */ 129, 74, 10, 129, 78, 6, 129, 80, 4, 131,
+/* 8730 */ 193, 129, 30, 4, 80, 4, 130, 30, 4, 79,
+/* 8740 */ 5, 129, 30, 5, 77, 7, 129, 30, 6, 74,
+/* 8750 */ 10, 129, 30, 8, 72, 12, 129, 30, 11, 69,
+/* 8760 */ 15, 129, 30, 13, 67, 17, 129, 30, 4, 37,
+/* 8770 */ 8, 64, 20, 129, 30, 4, 39, 8, 62, 22,
+/* 8780 */ 129, 41, 8, 59, 25, 129, 43, 8, 57, 27,
+/* 8790 */ 129, 45, 8, 55, 22, 80, 4, 129, 47, 27,
+/* 8800 */ 80, 4, 129, 49, 23, 129, 47, 22, 129, 44,
+/* 8810 */ 23, 129, 42, 22, 129, 30, 4, 39, 27, 129,
+/* 8820 */ 30, 4, 37, 31, 129, 30, 27, 62, 8, 129,
+/* 8830 */ 30, 25, 64, 8, 129, 30, 22, 66, 8, 80,
+/* 8840 */ 4, 129, 30, 20, 68, 8, 80, 4, 129, 30,
+/* 8850 */ 17, 70, 8, 80, 4, 129, 30, 15, 73, 11,
+/* 8860 */ 129, 30, 12, 75, 9, 129, 30, 10, 77, 7,
+/* 8870 */ 129, 30, 7, 79, 5, 129, 30, 5, 80, 4,
+/* 8880 */ 129, 30, 4, 80, 4, 130, 193, 129, 4, 5,
+/* 8890 */ 80, 4, 129, 2, 9, 80, 4, 129, 1, 11,
+/* 8900 */ 77, 7, 129, 1, 12, 74, 10, 129, 1, 12,
+/* 8910 */ 70, 14, 129, 1, 12, 66, 18, 129, 1, 11,
+/* 8920 */ 62, 22, 129, 2, 9, 59, 25, 129, 4, 11,
+/* 8930 */ 55, 29, 129, 7, 12, 51, 33, 129, 10, 12,
+/* 8940 */ 47, 37, 129, 14, 12, 44, 32, 80, 4, 129,
+/* 8950 */ 17, 13, 40, 32, 80, 4, 129, 21, 13, 36,
+/* 8960 */ 32, 129, 25, 40, 129, 29, 32, 129, 33, 24,
+/* 8970 */ 129, 36, 17, 129, 40, 12, 129, 44, 12, 129,
+/* 8980 */ 48, 12, 129, 51, 13, 129, 55, 13, 129, 59,
+/* 8990 */ 13, 80, 4, 129, 63, 13, 80, 4, 129, 67,
+/* 9000 */ 17, 129, 71, 13, 129, 74, 10, 129, 78, 6,
+/* 9010 */ 129, 80, 4, 131, 193, 129, 30, 1, 71, 13,
+/* 9020 */ 129, 30, 3, 71, 13, 129, 30, 6, 71, 13,
+/* 9030 */ 129, 30, 9, 75, 9, 129, 30, 11, 77, 7,
+/* 9040 */ 129, 30, 14, 79, 5, 129, 30, 17, 79, 5,
+/* 9050 */ 129, 30, 19, 80, 4, 129, 30, 22, 80, 4,
+/* 9060 */ 129, 30, 25, 80, 4, 129, 30, 27, 80, 4,
+/* 9070 */ 129, 30, 4, 36, 24, 80, 4, 129, 30, 4,
+/* 9080 */ 38, 25, 80, 4, 129, 30, 4, 41, 24, 80,
+/* 9090 */ 4, 129, 30, 4, 44, 24, 80, 4, 129, 30,
+/* 9100 */ 4, 46, 25, 80, 4, 129, 30, 4, 49, 25,
+/* 9110 */ 80, 4, 129, 30, 4, 52, 24, 80, 4, 129,
+/* 9120 */ 30, 4, 54, 30, 129, 30, 4, 57, 27, 129,
+/* 9130 */ 30, 4, 59, 25, 129, 30, 4, 62, 22, 129,
+/* 9140 */ 30, 4, 65, 19, 129, 30, 5, 67, 17, 129,
+/* 9150 */ 30, 5, 70, 14, 129, 30, 7, 73, 11, 129,
+/* 9160 */ 30, 9, 76, 8, 129, 30, 13, 78, 6, 129,
+/* 9170 */ 30, 13, 81, 3, 129, 30, 13, 129, 193, 2,
+/* 9180 */ 9, 59, 25, 129, 4, 11, 55, 29, 129, 7,
+/* 9190 */ 12, 51, 33, 129, 10, 12, 47, 37, 129, 14,
+/* 9200 */ 12, 44, 32, 80, 4, 129, 17, 13, 40, 32,
+/* 9210 */ 80, 4, 129, 21, 13, 36, 32, 129, 25, 40,
+/* 9220 */ 129, 29, 32, 129, 33, 24, 129, 36, 17, 129,
+/* 9230 */ 40, 12, 129, 44, 12, 129, 48, 12, 129, 51,
+/* 9240 */ 13, 129, 55, 13, 129, 59, 13, 80, 4, 129,
+/* 9250 */ 63, 13, 80, 4, 129, 67, 17, 129, 71, 13,
+/* 9260 */ 129, 74, 10, 129, 78, 6, 129, 80, 4, 131,
+/* 9270 */ 193
+};
+
+static char line[DWIDTH];
+static char *message;
+static char print[DWIDTH];
+static int debug, i, j, linen, max, nchars, pc, term, trace, x, y;
+static int width = DWIDTH; /* -w option: scrunch letters to 80 columns */
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "w:td")) != -1)
+ switch (ch) {
+ case 'd':
+ debug = 1;
+ break;
+ case 't':
+ trace = 1;
+ break;
+ case 'w':
+ width = atoi(optarg);
+ if (width <= 0 || width > DWIDTH)
+ errx(1, "illegal argument for -w option");
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; i < width; i++) {
+ j = i * DWIDTH / width;
+ print[j] = 1;
+ }
+
+ /* Have now read in the data. Next get the message to be printed. */
+ if (*argv) {
+ for(i=0, j=0; i < argc; i++)
+ j += strlen(argv[i]) + 1;
+ if ((message = malloc((size_t)j)) == NULL)
+ err(1, "malloc");
+ strlcpy(message, *argv, j);
+ while (*++argv) {
+ strlcat(message, " ", j);
+ strlcat(message, *argv, j);
+ }
+ nchars = strlen(message);
+ } else {
+ if ((message = malloc((size_t)MAXMSG)) == NULL)
+ err(1, "malloc");
+ fprintf(stderr,"Message: ");
+ if (fgets(message, MAXMSG, stdin) == NULL) {
+ nchars = 0;
+ message[0] = '\0';
+ } else {
+ nchars = strlen(message);
+
+ /* Get rid of newline. */
+ if (message[nchars - 1] == '\n')
+ message[--nchars] = '\0';
+ }
+ }
+
+ /* some debugging print statements */
+ if (debug) {
+ printf("const int asc_ptr[NCHARS] = {\n");
+ for (i = 0; i < 128; i++) {
+ printf("%4d, ",asc_ptr[i]);
+ if ((i+1) % 8 == 0)
+ printf("\n");
+ }
+ printf("};\nconst unsigned char data_table[NBYTES] = {\n");
+ printf("/* ");
+ for (i = 0; i < 10; i++) printf(" %3d ",i);
+ printf("*/\n");
+ for (i = 0; i < NBYTES; i += 10) {
+ printf("/* %4d */ ",i);
+ for (j = i; j < i+10; j++) {
+ x = data_table[j] & 0377;
+ printf(" %3d, ",x);
+ }
+ putchar('\n');
+ }
+ printf("};\n");
+ }
+
+ /* check message to make sure it's legal */
+ j = 0;
+ for (i = 0; i < nchars; i++)
+ if ((u_char) message[i] >= NCHARS ||
+ asc_ptr[(u_char) message[i]] == 0) {
+ warnx("the character '%c' is not in my character set",
+ message[i]);
+ j++;
+ }
+ if (j)
+ exit(1);
+
+ if (trace)
+ printf("Message '%s' is OK\n",message);
+ /* Now have message. Print it one character at a time. */
+
+ for (i = 0; i < nchars; i++) {
+ if (trace)
+ printf("Char #%d: %c\n", i, message[i]);
+ for (j = 0; j < DWIDTH; j++) line[j] = ' ';
+ pc = asc_ptr[(u_char) message[i]];
+ term = 0;
+ max = 0;
+ linen = 0;
+ while (!term) {
+ if (pc < 0 || pc > NBYTES) {
+ printf("bad pc: %d\n",pc);
+ exit(1);
+ }
+ x = data_table[pc] & 0377;
+ if (trace)
+ printf("pc=%d, term=%d, max=%d, linen=%d, x=%d\n",pc,term,max,linen,x);
+ if (x >= 128) {
+ if (x>192) term++;
+ x = x & 63;
+ while (x--) {
+ if (print[linen++]) {
+ for (j=0; j <= max; j++)
+ if (print[j])
+ putchar(line[j]);
+ putchar('\n');
+ }
+ }
+ for (j = 0; j < DWIDTH; j++) line[j] = ' ';
+ pc++;
+ }
+ else {
+ y = data_table[pc+1];
+ /* compensate for narrow teminals */
+#ifdef notdef
+ x = (x*width + (DWIDTH/2)) / DWIDTH;
+ y = (y*width + (DWIDTH/2)) / DWIDTH;
+#endif
+ max = x+y;
+ while (x < max) line[x++] = '#';
+ pc += 2;
+ if (trace)
+ printf("x=%d, y=%d, max=%d\n",x,y,max);
+ }
+ }
+ }
+
+ free(message);
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: banner [-d] [-t] [-w width] message ...\n");
+ exit(1);
+}
diff --git a/usr.bin/basename/Makefile b/usr.bin/basename/Makefile
new file mode 100644
index 000000000000..fb590532152a
--- /dev/null
+++ b/usr.bin/basename/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= basename
+MLINKS= basename.1 dirname.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/basename/Makefile.depend b/usr.bin/basename/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/basename/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/basename/basename.1 b/usr.bin/basename/basename.1
new file mode 100644
index 000000000000..41bbcc1ba60b
--- /dev/null
+++ b/usr.bin/basename/basename.1
@@ -0,0 +1,119 @@
+.\" Copyright (c) 1990, 1993, 1994
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 21, 2021
+.Dt BASENAME 1
+.Os
+.Sh NAME
+.Nm basename , dirname
+.Nd return filename or directory portion of pathname
+.Sh SYNOPSIS
+.Nm
+.Ar string
+.Op Ar suffix
+.Nm
+.Op Fl a
+.Op Fl s Ar suffix
+.Ar string
+.Op Ar ...
+.Nm dirname
+.Ar string
+.Op Ar ...
+.Sh DESCRIPTION
+The
+.Nm
+utility deletes any prefix ending with the last slash
+.Ql \&/
+character present in
+.Ar string
+(after first stripping trailing slashes),
+and a
+.Ar suffix ,
+if given.
+The
+.Ar suffix
+is not stripped if it is identical to the remaining characters in
+.Ar string .
+The resulting filename is written to the standard output.
+A non-existent suffix is ignored.
+If
+.Fl a
+is specified, then every argument is treated as a
+.Ar string
+as if
+.Nm
+were invoked with just one argument.
+If
+.Fl s
+is specified, then the
+.Ar suffix
+is taken as its argument, and all other arguments are treated as a
+.Ar string .
+.Pp
+The
+.Nm dirname
+utility deletes the filename portion, beginning
+with the last slash
+.Ql \&/
+character to the end of
+.Ar string
+(after first stripping trailing slashes),
+and writes the result to the standard output.
+.Sh EXIT STATUS
+.Ex -std basename dirname
+.Sh EXAMPLES
+The following line sets the shell variable
+.Ev FOO
+to
+.Pa /usr/bin .
+.Pp
+.Dl FOO=`dirname /usr/bin/trail`
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr sh 1 ,
+.Xr basename 3 ,
+.Xr dirname 3
+.Sh STANDARDS
+The
+.Nm
+and
+.Nm dirname
+utilities are expected to be
+.St -p1003.2
+compatible.
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.At v7 .
+The
+.Nm dirname
+utility first appeared in
+.At III .
diff --git a/usr.bin/basename/basename.c b/usr.bin/basename/basename.c
new file mode 100644
index 000000000000..31d7c2ab4175
--- /dev/null
+++ b/usr.bin/basename/basename.c
@@ -0,0 +1,134 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+void stripsuffix(char *, const char *, size_t);
+void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ char *p, *suffix;
+ size_t suffixlen;
+ int aflag, ch;
+
+ setlocale(LC_ALL, "");
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ aflag = 0;
+ suffix = NULL;
+ suffixlen = 0;
+
+ while ((ch = getopt(argc, argv, "as:")) != -1)
+ switch(ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 's':
+ suffix = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ if (!*argv[0]) {
+ printf("\n");
+ exit(0);
+ }
+ if ((p = basename(argv[0])) == NULL)
+ err(1, "%s", argv[0]);
+ if ((suffix == NULL && !aflag) && argc == 2) {
+ suffix = argv[1];
+ argc--;
+ }
+ if (suffix != NULL)
+ suffixlen = strlen(suffix);
+ while (argc--) {
+ if ((p = basename(*argv)) == NULL)
+ err(1, "%s", argv[0]);
+ stripsuffix(p, suffix, suffixlen);
+ argv++;
+ (void)printf("%s\n", p);
+ }
+ exit(0);
+}
+
+void
+stripsuffix(char *p, const char *suffix, size_t suffixlen)
+{
+ char *q, *r;
+ mbstate_t mbs;
+ size_t n;
+
+ if (suffixlen && (q = strchr(p, '\0') - suffixlen) > p &&
+ strcmp(suffix, q) == 0) {
+ /* Ensure that the match occurred on a character boundary. */
+ memset(&mbs, 0, sizeof(mbs));
+ for (r = p; r < q; r += n) {
+ n = mbrlen(r, MB_LEN_MAX, &mbs);
+ if (n == (size_t)-1 || n == (size_t)-2) {
+ memset(&mbs, 0, sizeof(mbs));
+ n = 1;
+ }
+ }
+ /* Chop off the suffix. */
+ if (q == r)
+ *q = '\0';
+ }
+}
+
+void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+"usage: basename string [suffix]\n"
+" basename [-a] [-s suffix] string [...]\n");
+ exit(1);
+}
diff --git a/usr.bin/basename/tests/Makefile b/usr.bin/basename/tests/Makefile
new file mode 100644
index 000000000000..a2cd60c6d0ce
--- /dev/null
+++ b/usr.bin/basename/tests/Makefile
@@ -0,0 +1,5 @@
+NETBSD_ATF_TESTS_SH= basename_test
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/basename/tests/Makefile.depend b/usr.bin/basename/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/basename/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/beep/Makefile b/usr.bin/beep/Makefile
new file mode 100644
index 000000000000..8388ff7ff986
--- /dev/null
+++ b/usr.bin/beep/Makefile
@@ -0,0 +1,7 @@
+.include <src.opts.mk>
+
+PROG= beep
+MAN= beep.1
+LIBADD= m
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/beep/beep.1 b/usr.bin/beep/beep.1
new file mode 100644
index 000000000000..732f2ae261cd
--- /dev/null
+++ b/usr.bin/beep/beep.1
@@ -0,0 +1,82 @@
+.\"-
+.\" Copyright (c) 2021 Hans Petter Selasky <hselasky@FreeBSD.org>
+.\"
+.\" 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 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.
+.\"
+.Dd November 4, 2021
+.Dt beep 1
+.Os
+.Sh NAME
+.Nm beep
+.Nd play a beep sound
+.Sh SYNOPSIS
+.Nm
+.Op Fl F Ar frequency
+.Op Fl D Ar duration_ms
+.Op Fl r Ar sample_rate_hz
+.Op Fl d Ar oss_device
+.Op Fl g Ar gain
+.Op Fl B
+.Op Fl h
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to playback a beep on the soundcard.
+.Pp
+The options are as follows:
+.Bl -tag -width "-f device"
+.It Fl F
+Sets the center frequency of the beep in Hz.
+The default is 440 Hz .
+.It Fl D
+Sets the duration of the beep in milliseconds.
+The default is 150 ms .
+.It Fl d
+Sets the soundcard to use.
+The default is /dev/dsp .
+.It Fl r
+Sets the soundcard samplerate in Hz.
+The default is 48000 Hz.
+.It Fl g
+Sets the waveform gain, between 0 and 100 inclusively.
+The default is 75.
+.It Fl B
+Runs the
+.Nm
+utility in the background.
+.It Fl h
+Display summary of options.
+.El
+.Sh EXAMPLES
+.Pp
+Playback default beep sound using /dev/dsp .
+.Bl -tag -width Ds -offset indent
+.It $ beep
+.El
+.Sh SEE ALSO
+.Xr mixer 3 ,
+.Xr sound 4
+.Sh HISTORY
+The
+.Nm
+utility first appeared in FreeBSD 14.0.
+.Sh AUTHORS
+.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org
diff --git a/usr.bin/beep/beep.c b/usr.bin/beep/beep.c
new file mode 100644
index 000000000000..2696bacfacf4
--- /dev/null
+++ b/usr.bin/beep/beep.c
@@ -0,0 +1,275 @@
+/*-
+ * Copyright (c) 2021 Hans Petter Selasky <hselasky@freebsd.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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/soundcard.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SAMPLE_RATE_DEF 48000 /* hz */
+#define SAMPLE_RATE_MAX 48000 /* hz */
+#define SAMPLE_RATE_MIN 8000 /* hz */
+
+#define DURATION_DEF 150 /* ms */
+#define DURATION_MAX 2000 /* ms */
+#define DURATION_MIN 50 /* ms */
+
+#define GAIN_DEF 75
+#define GAIN_MAX 100
+#define GAIN_MIN 0
+
+#define WAVE_POWER 1.25f
+
+#define DEFAULT_HZ 440
+
+#define DEFAULT_DEVICE _PATH_DEV "dsp"
+
+static int frequency = DEFAULT_HZ;
+static int duration_ms = DURATION_DEF;
+static int sample_rate = SAMPLE_RATE_DEF;
+static int gain = GAIN_DEF;
+static const char *oss_dev = DEFAULT_DEVICE;
+static bool background;
+
+/*
+ * wave_function_16
+ *
+ * "phase" should be in the range [0.0f .. 1.0f>
+ * "power" should be in the range <0.0f .. 2.0f>
+ *
+ * The return value is in the range [-1.0f .. 1.0f]
+ */
+static float
+wave_function_16(float phase, float power)
+{
+ uint16_t x = phase * (1U << 16);
+ float retval;
+ uint8_t num;
+
+ /* Handle special cases, if any */
+ switch (x) {
+ case 0xffff:
+ case 0x0000:
+ return (1.0f);
+ case 0x3fff:
+ case 0x4000:
+ case 0xBfff:
+ case 0xC000:
+ return (0.0f);
+ case 0x7FFF:
+ case 0x8000:
+ return (-1.0f);
+ default:
+ break;
+ }
+
+ /* Apply Gray coding */
+ for (uint16_t mask = 1U << 15; mask != 1; mask /= 2) {
+ if (x & mask)
+ x ^= (mask - 1);
+ }
+
+ /* Find first set bit */
+ for (num = 0; num != 14; num++) {
+ if (x & (1U << num)) {
+ num++;
+ break;
+ }
+ }
+
+ /* Initialize return value */
+ retval = 0.0;
+
+ /* Compute the rest of the power series */
+ for (; num != 14; num++) {
+ if (x & (1U << num)) {
+ retval = (1.0f - retval) / 2.0f;
+ retval = powf(retval, power);
+ } else {
+ retval = (1.0f + retval) / 2.0f;
+ retval = powf(retval, power);
+ }
+ }
+
+ /* Check if halfway */
+ if (x & (1ULL << 14))
+ retval = -retval;
+
+ return (retval);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s [parameters]\n"
+ "\t" "-F <frequency in HZ, default %d Hz>\n"
+ "\t" "-D <duration in ms, from %d ms to %d ms, default %d ms>\n"
+ "\t" "-r <sample rate in HZ, from %d Hz to %d Hz, default %d Hz>\n"
+ "\t" "-d <OSS device (default %s)>\n"
+ "\t" "-g <gain from %d to %d, default %d>\n"
+ "\t" "-B Run in background\n"
+ "\t" "-h Show usage\n",
+ getprogname(),
+ DEFAULT_HZ,
+ DURATION_MIN, DURATION_MAX, DURATION_DEF,
+ SAMPLE_RATE_MIN, SAMPLE_RATE_MAX, SAMPLE_RATE_DEF,
+ DEFAULT_DEVICE,
+ GAIN_MIN, GAIN_MAX, GAIN_DEF);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int32_t *buffer;
+ size_t slope;
+ size_t size;
+ size_t off;
+ float a;
+ float d;
+ float p;
+ int c;
+ int f;
+
+ while ((c = getopt(argc, argv, "BF:D:r:g:d:h")) != -1) {
+ switch (c) {
+ case 'F':
+ frequency = strtol(optarg, NULL, 10);
+ break;
+ case 'D':
+ duration_ms = strtol(optarg, NULL, 10);
+ if (duration_ms < DURATION_MIN ||
+ duration_ms > DURATION_MAX)
+ usage();
+ break;
+ case 'r':
+ sample_rate = strtol(optarg, NULL, 10);
+ if (sample_rate < SAMPLE_RATE_MIN ||
+ sample_rate > SAMPLE_RATE_MAX)
+ usage();
+ break;
+ case 'g':
+ gain = strtol(optarg, NULL, 10);
+ if (gain < GAIN_MIN ||
+ gain > GAIN_MAX)
+ usage();
+ break;
+ case 'd':
+ oss_dev = optarg;
+ break;
+ case 'B':
+ background = true;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (background && daemon(0, 0) != 0)
+ errx(1, "daemon(0,0) failed");
+
+ f = open(oss_dev, O_WRONLY);
+ if (f < 0)
+ err(1, "Failed to open '%s'", oss_dev);
+
+ c = 1; /* mono */
+ if (ioctl(f, SOUND_PCM_WRITE_CHANNELS, &c) != 0)
+ errx(1, "ioctl SOUND_PCM_WRITE_CHANNELS(1) failed");
+
+ c = AFMT_S32_NE;
+ if (ioctl(f, SNDCTL_DSP_SETFMT, &c) != 0)
+ errx(1, "ioctl SNDCTL_DSP_SETFMT(AFMT_S32_NE) failed");
+
+ if (ioctl(f, SNDCTL_DSP_SPEED, &sample_rate) != 0)
+ errx(1, "ioctl SNDCTL_DSP_SPEED(%d) failed", sample_rate);
+
+ c = (2 << 16);
+ while ((1ULL << (c & 63)) < (size_t)(4 * sample_rate / 50))
+ c++;
+ if (ioctl(f, SNDCTL_DSP_SETFRAGMENT, &c))
+ errx(1, "ioctl SNDCTL_DSP_SETFRAGMENT(0x%x) failed", c);
+
+ if (ioctl(f, SNDCTL_DSP_GETODELAY, &c) != 0)
+ errx(1, "ioctl SNDCTL_DSP_GETODELAY failed");
+
+ size = ((sample_rate * duration_ms) + 999) / 1000;
+ buffer = malloc(sizeof(buffer[0]) * size);
+ if (buffer == NULL)
+ errx(1, "out of memory");
+
+ /* compute slope duration in samples */
+ slope = (DURATION_MIN * sample_rate) / 2000;
+
+ /* compute base gain */
+ a = powf(65536.0f, (float)gain / (float)GAIN_MAX) / 65536.0f;
+
+ /* set initial phase and delta */
+ p = 0;
+ d = (float)frequency / (float)sample_rate;
+
+ /* compute wave */
+ for (p = off = 0; off != size; off++, p += d) {
+ float sample;
+
+ p = p - floorf(p);
+ sample = a * wave_function_16(p, WAVE_POWER);
+
+ if (off < slope)
+ sample = sample * off / (float)slope;
+ else if (off > (size - slope))
+ sample = sample * (size - off - 1) / (float)slope;
+
+ buffer[off] = sample * 0x7fffff00;
+ }
+
+ if (write(f, buffer, size * sizeof(buffer[0])) !=
+ (ssize_t)(size * sizeof(buffer[0])))
+ errx(1, "failed writing to DSP device(%s)", oss_dev);
+
+ free(buffer);
+
+ /* wait for data to be written */
+ while (ioctl(f, SNDCTL_DSP_GETODELAY, &c) == 0) {
+ if (c == 0)
+ break;
+ usleep(10000);
+ }
+
+ /* wait for audio to go out */
+ usleep(50000);
+ close(f);
+
+ return (0);
+}
diff --git a/usr.bin/biff/Makefile b/usr.bin/biff/Makefile
new file mode 100644
index 000000000000..6ba161554ccc
--- /dev/null
+++ b/usr.bin/biff/Makefile
@@ -0,0 +1,3 @@
+PROG= biff
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/biff/Makefile.depend b/usr.bin/biff/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/biff/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/biff/biff.1 b/usr.bin/biff/biff.1
new file mode 100644
index 000000000000..70370d41f843
--- /dev/null
+++ b/usr.bin/biff/biff.1
@@ -0,0 +1,120 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd April 28, 2013
+.Dt BIFF 1
+.Os
+.Sh NAME
+.Nm biff
+.Nd "be notified if mail arrives and who it is from"
+.Sh SYNOPSIS
+.Nm
+.Op Cm n | y | b
+.Sh DESCRIPTION
+The
+.Nm
+utility informs the system whether you want to be notified on your terminal
+when mail arrives.
+.Pp
+Affected is the first terminal associated with the standard input,
+standard output or standard error file descriptor, in that order.
+Thus, it is possible to use the redirection facilities of a shell to
+toggle the notification for other terminals than the one
+.Nm
+runs on.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Cm n
+Disable notification.
+.It Cm y
+Enable header notification.
+.It Cm b
+Enable bell notification.
+.El
+.Pp
+When header notification is enabled, the header and first few lines of
+the message will be printed on your terminal whenever mail arrives.
+A
+.Dq "biff y"
+command is often included in the file
+.Pa .login
+or
+.Pa .profile
+to be executed at each login.
+.Pp
+When bell notification is enabled, only two bell characters
+.Tn ( ASCII
+\\007)
+will be printed on your terminal whenever mail arrives.
+.Pp
+If no arguments are given,
+.Nm
+displays the present notification status of the terminal to the
+standard output.
+.Pp
+The
+.Nm
+utility operates asynchronously.
+For synchronous notification use the
+.Ev MAIL
+variable of
+.Xr sh 1
+or the
+.Va mail
+variable of
+.Xr csh 1 .
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Bl -tag -width indent
+.It 0
+Notification was enabled at the time of invocation.
+.It 1
+Notification was disabled at the time of invocation.
+.It >1
+An error occurred.
+.El
+.Sh COMPATIBILITY
+Previous versions of the
+.Nm
+utility affected the terminal attached to standard error without first
+trying the standard input or output devices.
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr mail 1 ,
+.Xr sh 1 ,
+.Xr comsat 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
+It was named after the dog of Heidi Stettner.
+He died
+in August 1993, at 15.
diff --git a/usr.bin/biff/biff.c b/usr.bin/biff/biff.c
new file mode 100644
index 000000000000..b1cdd5186e7e
--- /dev/null
+++ b/usr.bin/biff/biff.c
@@ -0,0 +1,100 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/stat.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ int ch;
+ char *name;
+
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((name = ttyname(STDIN_FILENO)) == NULL &&
+ (name = ttyname(STDOUT_FILENO)) == NULL &&
+ (name = ttyname(STDERR_FILENO)) == NULL)
+ err(2, "unknown tty");
+
+ if (stat(name, &sb))
+ err(2, "stat");
+
+ if (*argv == NULL) {
+ (void)printf("is %s\n",
+ sb.st_mode & S_IXUSR ? "y" :
+ sb.st_mode & S_IXGRP ? "b" : "n");
+ return (sb.st_mode & (S_IXUSR | S_IXGRP) ? 0 : 1);
+
+ }
+
+ switch (argv[0][0]) {
+ case 'n':
+ if (chmod(name, sb.st_mode & ~(S_IXUSR | S_IXGRP)) < 0)
+ err(2, "%s", name);
+ break;
+ case 'y':
+ if (chmod(name, (sb.st_mode & ~(S_IXUSR | S_IXGRP)) | S_IXUSR)
+ < 0)
+ err(2, "%s", name);
+ break;
+ case 'b':
+ if (chmod(name, (sb.st_mode & ~(S_IXUSR | S_IXGRP)) | S_IXGRP)
+ < 0)
+ err(2, "%s", name);
+ break;
+ default:
+ usage();
+ }
+ return (sb.st_mode & (S_IXUSR | S_IXGRP) ? 0 : 1);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: biff [n | y | b]\n");
+ exit(2);
+}
diff --git a/usr.bin/bintrans/Makefile b/usr.bin/bintrans/Makefile
new file mode 100644
index 000000000000..9e5a0000b0a1
--- /dev/null
+++ b/usr.bin/bintrans/Makefile
@@ -0,0 +1,21 @@
+.include <src.opts.mk>
+
+PROG= bintrans
+SRCS= bintrans.c uuencode.c uudecode.c qp.c
+MAN= bintrans.1 uuencode.format.5
+LINKS+= ${BINDIR}/bintrans ${BINDIR}/uuencode
+LINKS+= ${BINDIR}/bintrans ${BINDIR}/b64encode
+LINKS+= ${BINDIR}/bintrans ${BINDIR}/uudecode
+LINKS+= ${BINDIR}/bintrans ${BINDIR}/b64decode
+LINKS+= ${BINDIR}/bintrans ${BINDIR}/base64
+MLINKS= bintrans.1 uudecode.1 \
+ bintrans.1 uuencode.1 \
+ uuencode.format.5 uuencode.5 \
+ bintrans.1 b64encode.1 \
+ b64encode.1 b64decode.1 \
+ b64encode.1 base64.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bintrans/Makefile.depend b/usr.bin/bintrans/Makefile.depend
new file mode 100644
index 000000000000..344a5d0e9310
--- /dev/null
+++ b/usr.bin/bintrans/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bintrans/bintrans.1 b/usr.bin/bintrans/bintrans.1
new file mode 100644
index 000000000000..73baac115de4
--- /dev/null
+++ b/usr.bin/bintrans/bintrans.1
@@ -0,0 +1,284 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd January 8, 2025
+.Dt BINTRANS 1
+.Os
+.Sh NAME
+.Nm bintrans ,
+.Nm uuencode ,
+.Nm uudecode ,
+.Nm b64encode ,
+.Nm b64decode ,
+.Nm base64
+.Nd encode / decode a binary file
+.Sh SYNOPSIS
+.Nm
+.Op algorithm
+.Op ...
+.Nm uuencode
+.Op Fl m
+.Op Fl r
+.Op Fl o Ar output_file
+.Op Ar file
+.Ar name
+.Nm uudecode
+.Op Fl cimprs
+.Op Ar
+.Nm uudecode
+.Op Fl i
+.Fl o Ar output_file
+.Nm b64encode
+.Op Fl r
+.Op Fl w Ar column
+.Op Fl o Ar output_file
+.Op Ar file
+.Ar name
+.Nm b64decode
+.Op Fl cimprs
+.Op Ar
+.Nm b64decode
+.Op Fl i
+.Fl o Ar output_file
+.Op Ar file
+.Nm base64
+.Op Fl d
+.Op Fl w Ar column
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm uuencode
+and
+.Nm uudecode
+utilities are used to transmit binary files over transmission mediums
+that do not support other than simple
+.Tn ASCII
+data.
+The
+.Nm b64encode
+utility is synonymous with
+.Nm uuencode
+with the
+.Fl m
+flag specified.
+The
+.Nm b64decode
+utility is synonymous with
+.Nm uudecode
+with the
+.Fl m
+flag specified.
+.Pp
+The
+.Nm base64
+utility acts as a base64 decoder when passed the
+.Fl -decode
+.Po or
+.Fl d
+.Pc
+flag and as a base64 encoder otherwise.
+As a decoder it only accepts raw base64 input
+and as an encoder it does not produce the framing lines.
+.Nm base64
+reads standard input or
+.Ar file
+if it is provided and writes to standard output.
+Options
+.Fl -wrap
+.Po or
+.Fl w
+.Pc
+and
+.Fl -ignore-garbage
+.Po or
+.Fl i
+.Pc
+are accepted for compatibility with GNU base64,
+but the latter is unimplemented and silently ignored.
+.Pp
+The
+.Nm uuencode
+utility reads
+.Ar file
+(or by default the standard input) and writes an encoded version
+to the standard output, or
+.Ar output_file
+if one has been specified.
+The encoding uses only printing
+.Tn ASCII
+characters and includes the
+mode of the file and the operand
+.Ar name
+for use by
+.Nm uudecode .
+.Pp
+The
+.Nm uudecode
+utility transforms
+.Em uuencoded
+files (or by default, the standard input) into the original form.
+The resulting file is named either
+.Ar name
+or (depending on options passed to
+.Nm uudecode )
+.Ar output_file
+and will have the mode of the original file except that setuid
+and execute bits are not retained.
+The
+.Nm uudecode
+utility ignores any leading and trailing lines.
+.Pp
+The following options are available for
+.Nm uuencode :
+.Bl -tag -width indent
+.It Fl m
+Use the Base64 method of encoding, rather than the traditional
+.Nm uuencode
+algorithm.
+.It Fl r
+Produce raw output by excluding the initial and final framing lines.
+.It Fl o Ar output_file
+Output to
+.Ar output_file
+instead of standard output.
+.El
+.Pp
+The following options are available for
+.Nm uudecode :
+.Bl -tag -width indent
+.It Fl c
+Decode more than one uuencoded file from
+.Ar file
+if possible.
+.It Fl i
+Do not overwrite files.
+.It Fl m
+When used with the
+.Fl r
+flag, decode Base64 input instead of traditional
+.Nm uuencode
+input.
+Without
+.Fl r
+it has no effect.
+.It Fl o Ar output_file
+Output to
+.Ar output_file
+instead of any pathname contained in the input data.
+.It Fl p
+Decode
+.Ar file
+and write output to standard output.
+.It Fl r
+Decode raw (or broken) input, which is missing the initial and
+possibly the final framing lines.
+The input is assumed to be in the traditional
+.Nm uuencode
+encoding, but if the
+.Fl m
+flag is used, or if the utility is invoked as
+.Nm b64decode ,
+then the input is assumed to be in Base64 format.
+.It Fl s
+Do not strip output pathname to base filename.
+By default
+.Nm uudecode
+deletes any prefix ending with the last slash '/' for security
+reasons.
+.El
+.Pp
+Additionally,
+.Nm b64encode
+accepts the following option:
+.Bl -tag -width indent
+.It Fl w Ar column
+Wrap encoded output after
+.Ar column .
+.El
+.Pp
+.Nm
+is a generic utility that can run
+any of the aforementioned encoders and decoders.
+It can also run algorithms that are not available
+through a dedicated program:
+.Pp
+.Nm qp
+is a quoted-printable converter
+and accepts the following options:
+.Bl -tag -width indent
+.It Fl d
+Decode.
+.It Fl o Ar output_file
+Output to
+.Ar output_file
+instead of standard output.
+.It Fl r
+Encode/Decode in RFC2047 specific variant.
+.El
+.Sh EXAMPLES
+The following example packages up a source tree, compresses it,
+uuencodes it and mails it to a user on another system.
+When
+.Nm uudecode
+is run on the target system, the file ``src_tree.tar.Z'' will be
+created which may then be uncompressed and extracted into the original
+tree.
+.Pp
+.Bd -literal -offset indent -compact
+tar cf \- src_tree \&| compress \&|
+uuencode src_tree.tar.Z \&| mail user@example.com
+.Ed
+.Pp
+The following example unpacks all uuencoded
+files from your mailbox into your current working directory.
+.Pp
+.Bd -literal -offset indent -compact
+uudecode -c < $MAIL
+.Ed
+.Pp
+The following example extracts a compressed tar
+archive from your mailbox
+.Pp
+.Bd -literal -offset indent -compact
+uudecode -o /dev/stdout < $MAIL | zcat | tar xfv -
+.Ed
+.Sh SEE ALSO
+.Xr basename 1 ,
+.Xr compress 1 ,
+.Xr mail 1 ,
+.Xr uucp 1 Pq Pa ports/net/freebsd-uucp ,
+.Xr uuencode 5
+.Sh HISTORY
+The
+.Nm uudecode
+and
+.Nm uuencode
+utilities appeared in
+.Bx 4.0 .
+.Sh BUGS
+Files encoded using the traditional algorithm are expanded by 35% (3
+bytes become 4 plus control information).
diff --git a/usr.bin/bintrans/bintrans.c b/usr.bin/bintrans/bintrans.c
new file mode 100644
index 000000000000..c4b443a9009b
--- /dev/null
+++ b/usr.bin/bintrans/bintrans.c
@@ -0,0 +1,165 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 The FreeBSD Foundation
+ *
+ * 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 AUTHOR 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>
+#include <getopt.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+extern int main_decode(int, char *[]);
+extern int main_encode(int, char *[]);
+extern int main_base64_decode(const char *);
+extern int main_base64_encode(const char *, const char *);
+extern int main_quotedprintable(int, char*[]);
+
+static int search(const char *const);
+static void usage_base64(bool);
+static void version_base64(void);
+static void base64_encode_or_decode(int, char *[]);
+
+enum coders {
+ uuencode, uudecode, b64encode, b64decode, base64, qp
+};
+
+int
+main(int argc, char *argv[])
+{
+ const char *const progname = getprogname();
+ int coder = search(progname);
+
+ if (coder == -1 && argc > 1) {
+ argc--;
+ argv++;
+ coder = search(argv[0]);
+ }
+ switch (coder) {
+ case uuencode:
+ case b64encode:
+ main_encode(argc, argv);
+ break;
+ case uudecode:
+ case b64decode:
+ main_decode(argc, argv);
+ break;
+ case base64:
+ base64_encode_or_decode(argc, argv);
+ break;
+ case qp:
+ main_quotedprintable(argc, argv);
+ break;
+ default:
+ (void)fprintf(stderr,
+ "usage: %1$s <uuencode | uudecode> ...\n"
+ " %1$s <b64encode | b64decode> ...\n"
+ " %1$s <base64> ...\n"
+ " %1$s <qp> ...\n",
+ progname);
+ exit(EX_USAGE);
+ }
+}
+
+static int
+search(const char *const progname)
+{
+#define DESIGNATE(item) [item] = #item
+ const char *const known[] = {
+ DESIGNATE(uuencode),
+ DESIGNATE(uudecode),
+ DESIGNATE(b64encode),
+ DESIGNATE(b64decode),
+ DESIGNATE(base64),
+ DESIGNATE(qp)
+ };
+
+ for (size_t i = 0; i < nitems(known); i++)
+ if (strcmp(progname, known[i]) == 0)
+ return ((int)i);
+ return (-1);
+}
+
+static void
+usage_base64(bool failure)
+{
+ (void)fputs("usage: base64 [-w col | --wrap=col] "
+ "[-d | --decode] [FILE]\n"
+ " base64 --help\n"
+ " base64 --version\n", stderr);
+ exit(failure ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static void
+version_base64(void)
+{
+ (void)fputs("FreeBSD base64\n", stderr);
+ exit(EXIT_SUCCESS);
+}
+
+static void
+base64_encode_or_decode(int argc, char *argv[])
+{
+ int ch;
+ bool decode = false;
+ const char *w = NULL;
+ enum { HELP, VERSION };
+ static const struct option opts[] =
+ {
+ {"decode", no_argument, NULL, 'd'},
+ {"ignore-garbage",no_argument, NULL, 'i'},
+ {"wrap", required_argument, NULL, 'w'},
+ {"help", no_argument, NULL, HELP},
+ {"version", no_argument, NULL, VERSION},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ while ((ch = getopt_long(argc, argv, "diw:", opts, NULL)) != -1)
+ switch (ch) {
+ case 'd':
+ decode = true;
+ break;
+ case 'w':
+ w = optarg;
+ break;
+ case 'i':
+ /* silently ignore */
+ break;
+ case VERSION:
+ version_base64();
+ break;
+ case HELP:
+ default:
+ usage_base64(ch == '?');
+ }
+
+ if (decode)
+ main_base64_decode(argv[optind]);
+ else
+ main_base64_encode(argv[optind], w);
+}
diff --git a/usr.bin/bintrans/qp.c b/usr.bin/bintrans/qp.c
new file mode 100644
index 000000000000..862db437f4e0
--- /dev/null
+++ b/usr.bin/bintrans/qp.c
@@ -0,0 +1,218 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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 <ctype.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern int main_quotedprintable(int, char *[]);
+
+static int
+hexval(int c)
+{
+ if ('0' <= c && c <= '9')
+ return c - '0';
+ return (10 + c - 'A');
+}
+
+
+static int
+decode_char(const char *s)
+{
+ return (16 * hexval(toupper(s[1])) + hexval(toupper(s[2])));
+}
+
+
+static void
+decode_quoted_printable(const char *body, FILE *fpo, bool rfc2047)
+{
+ while (*body != '\0') {
+ switch (*body) {
+ case '=':
+ if (strlen(body) < 2) {
+ fputc(*body, fpo);
+ break;
+ }
+
+ if (body[1] == '\r' && body[2] == '\n') {
+ body += 2;
+ break;
+ }
+ if (body[1] == '\n') {
+ body++;
+ break;
+ }
+ if (strchr("0123456789ABCDEFabcdef", body[1]) == NULL) {
+ fputc(*body, fpo);
+ break;
+ }
+ if (strchr("0123456789ABCDEFabcdef", body[2]) == NULL) {
+ fputc(*body, fpo);
+ break;
+ }
+ fputc(decode_char(body), fpo);
+ body += 2;
+ break;
+ case '_':
+ if (rfc2047) {
+ fputc(0x20, fpo);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ fputc(*body, fpo);
+ break;
+ }
+ body++;
+ }
+}
+
+static void
+encode_quoted_printable(const char *body, FILE *fpo, bool rfc2047)
+{
+ const char *end = body + strlen(body);
+ size_t linelen = 0;
+ char prev = '\0';
+
+ while (*body != '\0') {
+ if (linelen == 75) {
+ fputs("=\r\n", fpo);
+ linelen = 0;
+ }
+ if (!isascii(*body) ||
+ *body == '=' ||
+ (*body == '.' && body + 1 < end &&
+ (body[1] == '\n' || body[1] == '\r'))) {
+ fprintf(fpo, "=%02X", (unsigned char)*body);
+ linelen += 2;
+ prev = *body;
+ } else if (*body < 33 && *body != '\n') {
+ if ((*body == ' ' || *body == '\t') &&
+ body + 1 < end &&
+ (body[1] != '\n' && body[1] != '\r')) {
+ if (*body == 0x20 && rfc2047)
+ fputc('_', fpo);
+ else
+ fputc(*body, fpo);
+ prev = *body;
+ } else {
+ fprintf(fpo, "=%02X", (unsigned char)*body);
+ linelen += 2;
+ prev = '_';
+ }
+ } else if (*body == '\n') {
+ if (prev == ' ' || prev == '\t') {
+ fputc('=', fpo);
+ }
+ fputc('\n', fpo);
+ linelen = 0;
+ prev = 0;
+ } else {
+ fputc(*body, fpo);
+ prev = *body;
+ }
+ body++;
+ linelen++;
+ }
+}
+
+static void
+qp(FILE *fp, FILE *fpo, bool encode, bool rfc2047)
+{
+ char *line = NULL;
+ size_t linecap = 0;
+ void (*codec)(const char *line, FILE *f, bool rfc2047);
+
+ codec = encode ? encode_quoted_printable : decode_quoted_printable ;
+
+ while (getline(&line, &linecap, fp) > 0)
+ codec(line, fpo, rfc2047);
+ free(line);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: bintrans qp [-d] [-r] [-o outputfile] [file name]\n");
+}
+
+int
+main_quotedprintable(int argc, char *argv[])
+{
+ int ch;
+ bool encode = true;
+ bool rfc2047 = false;
+ FILE *fp = stdin;
+ FILE *fpo = stdout;
+
+ static const struct option opts[] =
+ {
+ { "decode", no_argument, NULL, 'd'},
+ { "output", required_argument, NULL, 'o'},
+ { "rfc2047", no_argument, NULL, 'r'},
+ {NULL, no_argument, NULL, 0}
+ };
+
+ while ((ch = getopt_long(argc, argv, "do:ru", opts, NULL)) != -1) {
+ switch(ch) {
+ case 'o':
+ fpo = fopen(optarg, "w");
+ if (fpo == NULL) {
+ perror(optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'u':
+ /* FALLTHROUGH for backward compatibility */
+ case 'd':
+ encode = false;
+ break;
+ case 'r':
+ rfc2047 = true;
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ };
+ argc -= optind;
+ argv += optind;
+ if (argc > 0) {
+ fp = fopen(argv[0], "r");
+ if (fp == NULL) {
+ perror(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ qp(fp, fpo, encode, rfc2047);
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr.bin/bintrans/tests/Makefile b/usr.bin/bintrans/tests/Makefile
new file mode 100644
index 000000000000..8aa936c61334
--- /dev/null
+++ b/usr.bin/bintrans/tests/Makefile
@@ -0,0 +1,13 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= bintrans_test
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= textqpenc textqpdec
+${PACKAGE}FILES+= regress.base64.in regress.base64.out
+${PACKAGE}FILES+= regress.in regress.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.traditional.in regress.traditional.out
+${PACKAGE}FILES+= regress.153276.in regress.153276.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bintrans/tests/Makefile.depend b/usr.bin/bintrans/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bintrans/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bintrans/tests/bintrans_test.sh b/usr.bin/bintrans/tests/bintrans_test.sh
new file mode 100644
index 000000000000..b1f9d8f6d1d6
--- /dev/null
+++ b/usr.bin/bintrans/tests/bintrans_test.sh
@@ -0,0 +1,35 @@
+atf_test_case encode_qp
+encode_qp_body()
+{
+ atf_check -e empty -o file:"$(atf_get_srcdir)/textqpenc" bintrans qp $(atf_get_srcdir)/textqpdec
+}
+
+atf_test_case decode_qp
+decode_qp_body()
+{
+ printf "=" > test
+ atf_check -e empty -o inline:"=" bintrans qp -u test
+ printf "=\ra" > test
+ atf_check -e empty -o inline:"=\ra" bintrans qp -u test
+ printf "=\r\na" > test
+ atf_check -e empty -o inline:"a" bintrans qp -u test
+ printf "This is a line" > test
+ atf_check -e empty -o inline:"This is a line" bintrans qp -u test
+ printf "This= is a line" > test
+ atf_check -e empty -o inline:"This= is a line" bintrans qp -u test
+ printf "This=2 is a line" > test
+ atf_check -e empty -o inline:"This=2 is a line" bintrans qp -u test
+ printf "This=23 is a line" > test
+ atf_check -e empty -o inline:"This# is a line" bintrans qp -u test
+ printf "This=3D is a line" > test
+ atf_check -e empty -o inline:"This= is a line" bintrans qp -u test
+ printf "This_ is a line" > test
+ atf_check -e empty -o inline:"This_ is a line" bintrans qp -u test
+ atf_check -e empty -o file:"$(atf_get_srcdir)/textqpdec" bintrans qp -u $(atf_get_srcdir)/textqpenc
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case decode_qp
+ atf_add_test_case encode_qp
+}
diff --git a/usr.bin/bintrans/tests/legacy_test.sh b/usr.bin/bintrans/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/bintrans/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/bintrans/tests/regress.153276.in b/usr.bin/bintrans/tests/regress.153276.in
new file mode 100644
index 000000000000..d881c8a9389e
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.153276.in
@@ -0,0 +1,4 @@
+begin 644 153276
+/5&AI<R!I<R!A('1E<W0*
+
+end
diff --git a/usr.bin/bintrans/tests/regress.153276.out b/usr.bin/bintrans/tests/regress.153276.out
new file mode 100644
index 000000000000..b82ee6f61b39
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.153276.out
@@ -0,0 +1 @@
+uudecode: stdin: /dev/null: character out of range: [32-96]
diff --git a/usr.bin/bintrans/tests/regress.base64.in b/usr.bin/bintrans/tests/regress.base64.in
new file mode 100644
index 000000000000..3a8bfc2bf1d9
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.base64.in
@@ -0,0 +1,88 @@
+begin-base64 644 regress.out
+dB745nc7bs6q4W24dCU/WprFX3UkvTwO6wlHiV+L4U+QEH1p/P9WjgFZ0MSGI2lE
+TCIH+3j4oqf3JJA/uvQ2WnWzCjFXG17cZpBq8UQGMh/e8QLyahMOTrrHP9Cf2ZE9
+WtybokTG8E2Ft0QrfiTsIpcUPMd7VDRvCQGLD+t6bqJkPJKaGmXXCwLwLz2WpAOX
+RW+d4UhnCnB0aBs7IByd6beMYwQxIcM4XvyAnG1z3XK9gCwvIwzI6wYYzXCIAo/K
+pP90oNA6ijFYYNK3s/uttytzC5QfKn6gaVerwYcb1QQHqyrxoryOrjwgwgazSfwL
+hDK1fLejnpTXL1Uh2j9E+pM0WSftA0wX1tdyKxy7kUarWzEACH8htTSd3NDamR/2
+T66xNHPYZhW31cjeNTX0czIfpRWBbBQI3rc5yhWZlGA0j8X8zQR4puaGpQ6QNnbB
+QkSU4Ak+pveRT8JuFbJVQI6WHemB7H9LV5CSYVCoZ2iOFA/Z8PSM473XXjqBk/M1
+Zz4irDw8V1tBp519qNgXFt52fdrkbzJCa+71pfAuP2LsytpAd2LUJwhgiV7uj6cx
+4DjEfdd/QYdcJGDm435wfsniPoPnrghEJdqfgWIvaFNpuoQ9ByrznWacs50AQFxy
+ZpfAaLJnGNiPehTOosTT6dPOKp8x2ms6mdkr2neZ0I0leoNHxCBKvgUxC0uFieo6
+GLpussFEB8QeCsy1mjnXDI1qsC2Sp34PZTvR5apH29FB1eIeAPFZMkFxO2TTs0Y4
+q3yKDcPGHaAdPy8J64UpyBlO3rbcLyqEbKcuSHHd69iT/5mD4arbyYHMY6S7S7QP
+DHpH1x8Woo5xMo0MVkmBGbKc5Sy4J37T8xjj4h0pcKvEdCSanJ2A1E2jHzpfbe8u
+/NSxpB49+JGYGJ2nsgpsKzwTXabgKDZPydqcAIpNXnAdsQBNskmzBYb8959xCzws
+ybQ7+0g4a0DYyLDcnW2NH/OCYHvkOgyM72FQJAXGg61GnZZiAjSlrqsPX2NVUtXi
+vRrueFSG5rYnYJvO2OfhwgEfxTY8b7x8AFQntBvaKqG5rWC+a2d+4Xj0B2ODy+/M
+5Hppj0dNwpLPKHa8UH6IDd+m0Aql5u5oCbh+WIDovGtN2BpkyCq00M/kKErTbTT+
+qfuWSDow0ZjLeFdSErUtdi1tKhDh5oy5Ev+ShLywKPm4/NfJ3CLhbZSvhOWWxwzf
+KEgMCnHNd8uc3JIDNM7c3Dm5w0QrD0AObOUSBF8iouNBjMvdUviIBVFPeVkZ3xYs
+TciSRJm/fB5QNhrcYRMbZJ5iOVHuuOxFw+zPoEIjVBPO1wXZgsSwgFED20bKLcOv
+SnWGM3IyNZVKqdo3a4oh4H4Lv/y6rMrtSTr7kQJlwEvU6WiyvtQob/fMdHWIbc/W
+RPR47l6JDz4V3AUqPcF3Jy6RaNUKRvFi+7cOWYBKbNFRmE/jA6dyUuVkCYIMDuhu
+I7iQL0u4l//xbdGb9RWtf8WHs/N5nmWi1TLTPbaDz8GBPOMOecpeIfqDVoPqaheq
+GT4fJj3sVBhq6zayVfNpueaEdHb/XTGm9NHS4xsgpbfL/sJw6IVJj3/dgb0RfX90
+ZUgfDvwURsTNvxAVzKuuuH6wrE8AGOpBLgomMZ5UZcgWkeRNjTqcelCsl3JhBIuU
+mJMbYI2SMv/CK+nkIYcIE7zHRaCyF8ngNYosop/chz1o1gTP2Di6NTq4a/SX0h1z
+7fykkKt2pLJvSOA8nccRIUrix5/GTQwhJxMaoR5WQUDVUPHx0c8xRNTTI24bGeik
+G4qKq74bpmZvbZrnsSjQJyLiQiPtraGR8YiI2JwGZmHbama9DPjOKV3bBWT6LgR2
+LEEI0G7BZiSGP4lniTkpOR/FUgp8WmblvhOeZY+KDTamifrq0NhjYIUYWGbZEOUi
+6ImSbiVH/gm4tk+kyAT1uSuK4lTUCWK7XO5I6WLCY2g4v7nYTDNUv/nbJLzai1GQ
+PLz3p0biVq3QwkIf+rZSsTirEIHMTeAxjdfWICDIcPSsxRZgvurgnIAodzIR9RkA
+nsoe4cLvh9SxDNrmlyWDsczkUsc9eG9rr5HH73KOr6wx2CUFug/naqnDBSzEI3H+
+cz12m9X8ATzpH0BT8cFvDE/KKiou+qWWtgLWTwnRoRBmBZVgOHCmQghz5bVgzUyg
+xxQFnYCTD9D5S3d2ndwuHJL3IesR/a+Oq5M4ORktsLMaOGJ7x3obRM6gEtuwpJ1E
+wxfGr/cYrc/QsBFoQfL9LgrcvHLgmE6mazXdF9NfBWiPZhTjFurcB0wD3PqlCrhc
+vsVP9cugGxA1pQ96MywYL2G0yyM1GrRIbiWG4y7y82+0mQSL9xG6G0StzkfWp5rr
+L8psGo/CFPr/8CXz+6tP/pNUp40NqcMVlOicMozUEHalgUe+581gu0GUI+IritwO
+SPM2hc+woGvFQ6WvY3S77fT7gkpnVuRjiSBlvSkV+2Iujs6++ErDKcIjD9j88StJ
+8xySXDZr9vIDLkT+YZIxg+v/CcP4C0tSbwAQNjoS9kpbMQK4YucSAuXIzIZngJHz
+38iU+2I+mzhPKChNi5/MxP0TjK63RqjKsIuJC9OD3c84n7TGXnvC1QqDF4TKYR2z
+Es7UjlyQVOD3HrtixAJP8ubmUQOrbIY2imR9xqUf2SWl8sCYaM6b9E00Wnnj0x2x
+pfZKE+IvarSRiTRgNBp2S7K1u9NTtj+9A67xWPwpBCPcIsyDP4CItCzMoybyqbn3
+rM3RSiygpIj901FlNab/mUi+borZDvXZgcOlhZjUJnhUjiEhuMfpOxYG//hkj/dW
+d3Dg9gaLVriLVZOfl5wUZT1d8W6rN3RQ+jT42pm2hLhE4picD5GEOYOcTf4rolSx
+2IlgK4w4fb77Iqk35/7kC203b9OFzgzIN2MMfY1C50MRJQT5B7qmKva33MjEaPzb
+IxipHCd2wAMzTJHMCShK1qiQ60aki8suOO6RWDiDAdnpzzjnDFhMyL+if5pBgZct
+nfvKvvsxAEWlyOZHcwXBu/v+2Gg5cWFr8e5GtvxmQzK0CamIba1xl5UTiZDeb6bM
+0uKZewkY1okt5lYGVYDL/vdhH2FePzSHB42RbcetO/3J113wvGjPVWz0F5hgoO+H
+T0Rq31vpZ47oK83UvOdDzRTyudiMKyf3VCVEzhqunT/QfyPp5Q7UgSOu0fcY/iap
+wxwUtqeBLUfiDo4vHSeswfAb3b8dcPPpYdjLKU80trpChkV37UyXY0wVFSiAiVOe
+WgWSGa0ABkxF/pNr/OztK1Ms2omJxBulK/FhXHtrog6xFW/QcPcGM0TXILUHJ8Gp
+XTckydbsTCW7Itv59MrY5G/3ps62AOJmcojjQ3kNsJ2UA64/u06RtK8GaP8q3X1z
+eFmikqD+jEIQlpnx1oy/aSOc0P7U9DtWe5MrloS2hHovHkad/se3GiZkgmfFRfqr
+cC+6giz4cjwTj/yEjpto3VOXnXcPycmuXFPjUlDkLBI6RaegecWd+OaQhCe0iut+
+g64p+e6j2wNaDXa64XgU6HEaXwTgaHENJCQ3GNDl79k1umU0efn5PeFJiNDdg1UB
+foaob/WFuE+FT2Ns6rmLocAG9XeXNX8U2l3eIleCQHzkhfXluFFgLQnqFpPGay3W
+liEQrZ1/J2o5yx2YE/OJMi3bvnP3JB1mdMPbgd5ulrwcbCOCe0t/qjTxLQzunP5A
++S7uaweW4iBuDjGiSGPIDH7CPpYQRl+JAj1TYdP1rQ6LpG57cr+NsbyODFEN+DSu
+yOPiu0z5BmMqb1SQcZ3v2MWyYg+n3Lqai+CX96c0lpL8U2SG7ARnkbmMrQVzD5dw
+KxnZuk4yvkrSAX0y4kN7mpWuuMDKw/h5NbCXUM1OsgjZ3NW8gsj2FYt3f7RSgOeX
+/lpLuakHMlYgYDyzXnWL8VuwG7gEN/nJLoym7w2OhTFF/l7xilkflZJ3rcGvxbi9
+gJOsuCKz2oI1ujxJHR5fIX0HSkv7R4464jiK+GUNnbe7QmbBWLoo8Y524u70j5QJ
+sd9ZLcTkwAJdW/u/qUXOjbThd8TLsuwDSTMeQj210Lmq3eYy5Np8GRjxQkOXpp0J
+fkEHrkHb5+s1I9v2AhAxQ6RUOuvORLuEoid4RkpFM1kwTV1vQplg7VmLvPjpE1JZ
+3AbAvKdeqsPsJJVwU+q7Jbw3dVa8M0ZtqS4FCGk1C/4jlobxsakncIxP/haAz7oc
+0IeEFyMzNqu6xjHKqCh9WaqHQpXf1JgJrrV6e+j7Ygh3CsqlSzW6jbSDyxFeKlUx
+pMYHebEJSebLKOKE0mfubsGqizJFOKRPkYr1bQ1/u5P6FNEr0sGQ7lS7BEGRhchJ
+g17bXD9moD2CeJZ2QJYj+YMqjYHk/W6ufHVVHc0pF5jV6/lVMsIYeQ8l3YhI/1hB
++1An/yFOvVgNonYJVd8MohaVPCD+dZUV3M+S76YRiGVniidGQWl5Y6PYzlEqEuM5
+FWftt9dSLVYhXhbABzcfN7mzoCZjyZEv+ZgUv9ipeaSUW0SZ+6iFv/abw7FkZSl4
+5B88ETP2LqClT21/yd69ZyGfdp3FR9daqKrjVjvCFu98zyHTsdR+OF8bsaI280iz
+3WKdXum+iiuadf66GIsjtIyqUQqog74Ji+VKP/xIgOBAFB4ktVULAypA+NsRNwYA
+IBDEa7EMiDduUPQ/9uavMN/F9Jf1POW4MljbH7C66NisM+/3YJ4l4Um2iXQPq9yp
+G6c0AJjzgL6/XtWhFnki1jJYvEJ9IkWvlL650zgXzEvEEOWI6TaQSwrrSh2UTD6a
+fJPCRsymB1rBEWb1FRVsidkr+/rFFL7D3QsDr+EWFesj5ItbABOPNt5w0obx0mKg
+WoKuZaklnqJvJT7JUdVRZQ6ei4JksMnIs+muEl7ouM1OM/e2VM5JRI+2MO4/1Sy9
+brEj3xY0pRYfXJxzNZsIepyKB8T2NoWfvOomcCXlYNz3rIRRVPWgxsV6kqTJuFo+
+Ypu+A7Q8P2AWDfssP2vaHvphJmk5OwUAq4LljFbo6KlC932c6cljUhTRukRsFfz5
+JoYf1dcdgcPg5YGX4qpUuqCGiT99dSIQ/WhCL6n4gLV/IXb5BuMbrmHvx1xVVbiT
+h8S4MjNNqv6zpLumJr8qI7sFfPLDYhm7erthjGYmVnG3n7eEeAu/QU2CJl4kHMoS
+FoRanXJ+o4tprVlrRQ0whlADoNK8swogk2vGtYqqCfYAHuh/aGtETA/vqZI71/j9
+4nDd8YH1hVyf5GI/QvkuqZiLeZKUIrNj03jHio8oHWrim1mBlRhWo/947ac6xHOq
+FqBufMZIC1f2zvHvav1Cu7Y6kAoKsn4h4gTjKw25SImYWL4Lx8GUsVWKl+pm8rEJ
+3NTh6I2Q6vt1EmfP2Oot56oUci+u8WtQ8wvEaoYWWWqKghPp9piEsfHTETmievN5
+8OKlLHwxWbE7xE7teDcAZw==
+====
diff --git a/usr.bin/bintrans/tests/regress.base64.out b/usr.bin/bintrans/tests/regress.base64.out
new file mode 100644
index 000000000000..046f6c5d6886
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.base64.out
@@ -0,0 +1,74 @@
+begin-base64 644 regress.in
+dB745nc7bs6q4W24dCU/WprFX3UkvTwO6wlHiV+L4U+QEH1p/P9WjgFZ0MSGI2lETCIH+3j4oqf3
+JJA/uvQ2WnWzCjFXG17cZpBq8UQGMh/e8QLyahMOTrrHP9Cf2ZE9WtybokTG8E2Ft0QrfiTsIpcU
+PMd7VDRvCQGLD+t6bqJkPJKaGmXXCwLwLz2WpAOXRW+d4UhnCnB0aBs7IByd6beMYwQxIcM4XvyA
+nG1z3XK9gCwvIwzI6wYYzXCIAo/KpP90oNA6ijFYYNK3s/uttytzC5QfKn6gaVerwYcb1QQHqyrx
+oryOrjwgwgazSfwLhDK1fLejnpTXL1Uh2j9E+pM0WSftA0wX1tdyKxy7kUarWzEACH8htTSd3NDa
+mR/2T66xNHPYZhW31cjeNTX0czIfpRWBbBQI3rc5yhWZlGA0j8X8zQR4puaGpQ6QNnbBQkSU4Ak+
+pveRT8JuFbJVQI6WHemB7H9LV5CSYVCoZ2iOFA/Z8PSM473XXjqBk/M1Zz4irDw8V1tBp519qNgX
+Ft52fdrkbzJCa+71pfAuP2LsytpAd2LUJwhgiV7uj6cx4DjEfdd/QYdcJGDm435wfsniPoPnrghE
+JdqfgWIvaFNpuoQ9ByrznWacs50AQFxyZpfAaLJnGNiPehTOosTT6dPOKp8x2ms6mdkr2neZ0I0l
+eoNHxCBKvgUxC0uFieo6GLpussFEB8QeCsy1mjnXDI1qsC2Sp34PZTvR5apH29FB1eIeAPFZMkFx
+O2TTs0Y4q3yKDcPGHaAdPy8J64UpyBlO3rbcLyqEbKcuSHHd69iT/5mD4arbyYHMY6S7S7QPDHpH
+1x8Woo5xMo0MVkmBGbKc5Sy4J37T8xjj4h0pcKvEdCSanJ2A1E2jHzpfbe8u/NSxpB49+JGYGJ2n
+sgpsKzwTXabgKDZPydqcAIpNXnAdsQBNskmzBYb8959xCzwsybQ7+0g4a0DYyLDcnW2NH/OCYHvk
+OgyM72FQJAXGg61GnZZiAjSlrqsPX2NVUtXivRrueFSG5rYnYJvO2OfhwgEfxTY8b7x8AFQntBva
+KqG5rWC+a2d+4Xj0B2ODy+/M5Hppj0dNwpLPKHa8UH6IDd+m0Aql5u5oCbh+WIDovGtN2BpkyCq0
+0M/kKErTbTT+qfuWSDow0ZjLeFdSErUtdi1tKhDh5oy5Ev+ShLywKPm4/NfJ3CLhbZSvhOWWxwzf
+KEgMCnHNd8uc3JIDNM7c3Dm5w0QrD0AObOUSBF8iouNBjMvdUviIBVFPeVkZ3xYsTciSRJm/fB5Q
+NhrcYRMbZJ5iOVHuuOxFw+zPoEIjVBPO1wXZgsSwgFED20bKLcOvSnWGM3IyNZVKqdo3a4oh4H4L
+v/y6rMrtSTr7kQJlwEvU6WiyvtQob/fMdHWIbc/WRPR47l6JDz4V3AUqPcF3Jy6RaNUKRvFi+7cO
+WYBKbNFRmE/jA6dyUuVkCYIMDuhuI7iQL0u4l//xbdGb9RWtf8WHs/N5nmWi1TLTPbaDz8GBPOMO
+ecpeIfqDVoPqaheqGT4fJj3sVBhq6zayVfNpueaEdHb/XTGm9NHS4xsgpbfL/sJw6IVJj3/dgb0R
+fX90ZUgfDvwURsTNvxAVzKuuuH6wrE8AGOpBLgomMZ5UZcgWkeRNjTqcelCsl3JhBIuUmJMbYI2S
+Mv/CK+nkIYcIE7zHRaCyF8ngNYosop/chz1o1gTP2Di6NTq4a/SX0h1z7fykkKt2pLJvSOA8nccR
+IUrix5/GTQwhJxMaoR5WQUDVUPHx0c8xRNTTI24bGeikG4qKq74bpmZvbZrnsSjQJyLiQiPtraGR
+8YiI2JwGZmHbama9DPjOKV3bBWT6LgR2LEEI0G7BZiSGP4lniTkpOR/FUgp8WmblvhOeZY+KDTam
+ifrq0NhjYIUYWGbZEOUi6ImSbiVH/gm4tk+kyAT1uSuK4lTUCWK7XO5I6WLCY2g4v7nYTDNUv/nb
+JLzai1GQPLz3p0biVq3QwkIf+rZSsTirEIHMTeAxjdfWICDIcPSsxRZgvurgnIAodzIR9RkAnsoe
+4cLvh9SxDNrmlyWDsczkUsc9eG9rr5HH73KOr6wx2CUFug/naqnDBSzEI3H+cz12m9X8ATzpH0BT
+8cFvDE/KKiou+qWWtgLWTwnRoRBmBZVgOHCmQghz5bVgzUygxxQFnYCTD9D5S3d2ndwuHJL3IesR
+/a+Oq5M4ORktsLMaOGJ7x3obRM6gEtuwpJ1EwxfGr/cYrc/QsBFoQfL9LgrcvHLgmE6mazXdF9Nf
+BWiPZhTjFurcB0wD3PqlCrhcvsVP9cugGxA1pQ96MywYL2G0yyM1GrRIbiWG4y7y82+0mQSL9xG6
+G0StzkfWp5rrL8psGo/CFPr/8CXz+6tP/pNUp40NqcMVlOicMozUEHalgUe+581gu0GUI+IritwO
+SPM2hc+woGvFQ6WvY3S77fT7gkpnVuRjiSBlvSkV+2Iujs6++ErDKcIjD9j88StJ8xySXDZr9vID
+LkT+YZIxg+v/CcP4C0tSbwAQNjoS9kpbMQK4YucSAuXIzIZngJHz38iU+2I+mzhPKChNi5/MxP0T
+jK63RqjKsIuJC9OD3c84n7TGXnvC1QqDF4TKYR2zEs7UjlyQVOD3HrtixAJP8ubmUQOrbIY2imR9
+xqUf2SWl8sCYaM6b9E00Wnnj0x2xpfZKE+IvarSRiTRgNBp2S7K1u9NTtj+9A67xWPwpBCPcIsyD
+P4CItCzMoybyqbn3rM3RSiygpIj901FlNab/mUi+borZDvXZgcOlhZjUJnhUjiEhuMfpOxYG//hk
+j/dWd3Dg9gaLVriLVZOfl5wUZT1d8W6rN3RQ+jT42pm2hLhE4picD5GEOYOcTf4rolSx2IlgK4w4
+fb77Iqk35/7kC203b9OFzgzIN2MMfY1C50MRJQT5B7qmKva33MjEaPzbIxipHCd2wAMzTJHMCShK
+1qiQ60aki8suOO6RWDiDAdnpzzjnDFhMyL+if5pBgZctnfvKvvsxAEWlyOZHcwXBu/v+2Gg5cWFr
+8e5GtvxmQzK0CamIba1xl5UTiZDeb6bM0uKZewkY1okt5lYGVYDL/vdhH2FePzSHB42RbcetO/3J
+113wvGjPVWz0F5hgoO+HT0Rq31vpZ47oK83UvOdDzRTyudiMKyf3VCVEzhqunT/QfyPp5Q7UgSOu
+0fcY/iapwxwUtqeBLUfiDo4vHSeswfAb3b8dcPPpYdjLKU80trpChkV37UyXY0wVFSiAiVOeWgWS
+Ga0ABkxF/pNr/OztK1Ms2omJxBulK/FhXHtrog6xFW/QcPcGM0TXILUHJ8GpXTckydbsTCW7Itv5
+9MrY5G/3ps62AOJmcojjQ3kNsJ2UA64/u06RtK8GaP8q3X1zeFmikqD+jEIQlpnx1oy/aSOc0P7U
+9DtWe5MrloS2hHovHkad/se3GiZkgmfFRfqrcC+6giz4cjwTj/yEjpto3VOXnXcPycmuXFPjUlDk
+LBI6RaegecWd+OaQhCe0iut+g64p+e6j2wNaDXa64XgU6HEaXwTgaHENJCQ3GNDl79k1umU0efn5
+PeFJiNDdg1UBfoaob/WFuE+FT2Ns6rmLocAG9XeXNX8U2l3eIleCQHzkhfXluFFgLQnqFpPGay3W
+liEQrZ1/J2o5yx2YE/OJMi3bvnP3JB1mdMPbgd5ulrwcbCOCe0t/qjTxLQzunP5A+S7uaweW4iBu
+DjGiSGPIDH7CPpYQRl+JAj1TYdP1rQ6LpG57cr+NsbyODFEN+DSuyOPiu0z5BmMqb1SQcZ3v2MWy
+Yg+n3Lqai+CX96c0lpL8U2SG7ARnkbmMrQVzD5dwKxnZuk4yvkrSAX0y4kN7mpWuuMDKw/h5NbCX
+UM1OsgjZ3NW8gsj2FYt3f7RSgOeX/lpLuakHMlYgYDyzXnWL8VuwG7gEN/nJLoym7w2OhTFF/l7x
+ilkflZJ3rcGvxbi9gJOsuCKz2oI1ujxJHR5fIX0HSkv7R4464jiK+GUNnbe7QmbBWLoo8Y524u70
+j5QJsd9ZLcTkwAJdW/u/qUXOjbThd8TLsuwDSTMeQj210Lmq3eYy5Np8GRjxQkOXpp0JfkEHrkHb
+5+s1I9v2AhAxQ6RUOuvORLuEoid4RkpFM1kwTV1vQplg7VmLvPjpE1JZ3AbAvKdeqsPsJJVwU+q7
+Jbw3dVa8M0ZtqS4FCGk1C/4jlobxsakncIxP/haAz7oc0IeEFyMzNqu6xjHKqCh9WaqHQpXf1JgJ
+rrV6e+j7Ygh3CsqlSzW6jbSDyxFeKlUxpMYHebEJSebLKOKE0mfubsGqizJFOKRPkYr1bQ1/u5P6
+FNEr0sGQ7lS7BEGRhchJg17bXD9moD2CeJZ2QJYj+YMqjYHk/W6ufHVVHc0pF5jV6/lVMsIYeQ8l
+3YhI/1hB+1An/yFOvVgNonYJVd8MohaVPCD+dZUV3M+S76YRiGVniidGQWl5Y6PYzlEqEuM5FWft
+t9dSLVYhXhbABzcfN7mzoCZjyZEv+ZgUv9ipeaSUW0SZ+6iFv/abw7FkZSl45B88ETP2LqClT21/
+yd69ZyGfdp3FR9daqKrjVjvCFu98zyHTsdR+OF8bsaI280iz3WKdXum+iiuadf66GIsjtIyqUQqo
+g74Ji+VKP/xIgOBAFB4ktVULAypA+NsRNwYAIBDEa7EMiDduUPQ/9uavMN/F9Jf1POW4MljbH7C6
+6NisM+/3YJ4l4Um2iXQPq9ypG6c0AJjzgL6/XtWhFnki1jJYvEJ9IkWvlL650zgXzEvEEOWI6TaQ
+SwrrSh2UTD6afJPCRsymB1rBEWb1FRVsidkr+/rFFL7D3QsDr+EWFesj5ItbABOPNt5w0obx0mKg
+WoKuZaklnqJvJT7JUdVRZQ6ei4JksMnIs+muEl7ouM1OM/e2VM5JRI+2MO4/1Sy9brEj3xY0pRYf
+XJxzNZsIepyKB8T2NoWfvOomcCXlYNz3rIRRVPWgxsV6kqTJuFo+Ypu+A7Q8P2AWDfssP2vaHvph
+Jmk5OwUAq4LljFbo6KlC932c6cljUhTRukRsFfz5JoYf1dcdgcPg5YGX4qpUuqCGiT99dSIQ/WhC
+L6n4gLV/IXb5BuMbrmHvx1xVVbiTh8S4MjNNqv6zpLumJr8qI7sFfPLDYhm7erthjGYmVnG3n7eE
+eAu/QU2CJl4kHMoSFoRanXJ+o4tprVlrRQ0whlADoNK8swogk2vGtYqqCfYAHuh/aGtETA/vqZI7
+1/j94nDd8YH1hVyf5GI/QvkuqZiLeZKUIrNj03jHio8oHWrim1mBlRhWo/947ac6xHOqFqBufMZI
+C1f2zvHvav1Cu7Y6kAoKsn4h4gTjKw25SImYWL4Lx8GUsVWKl+pm8rEJ3NTh6I2Q6vt1EmfP2Oot
+56oUci+u8WtQ8wvEaoYWWWqKghPp9piEsfHTETmievN58OKlLHwxWbE7xE7teDcAZw==
+====
diff --git a/usr.bin/bintrans/tests/regress.in b/usr.bin/bintrans/tests/regress.in
new file mode 100644
index 000000000000..fa0dd0897b53
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.in
Binary files differ
diff --git a/usr.bin/bintrans/tests/regress.out b/usr.bin/bintrans/tests/regress.out
new file mode 100644
index 000000000000..fa0dd0897b53
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.out
Binary files differ
diff --git a/usr.bin/bintrans/tests/regress.sh b/usr.bin/bintrans/tests/regress.sh
new file mode 100644
index 000000000000..fea778d01a73
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.sh
@@ -0,0 +1,14 @@
+
+echo 1..5
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`traditional', `uuencode regress.in <${SRCDIR}/regress.in')
+REGRESSION_TEST(`base64', `uuencode -m regress.in <${SRCDIR}/regress.in')
+REGRESSION_TEST_ONE(`uudecode -p <${SRCDIR}/regress.traditional.in', `traditional')
+REGRESSION_TEST_ONE(`uudecode -p <${SRCDIR}/regress.base64.in', `base64')
+
+# was uudecode: stdin: /dev/null: character out of range: [33-96]
+REGRESSION_TEST(`153276', `uudecode -o /dev/null <${SRCDIR}/regress.153276.in 2>&1')
+
+REGRESSION_END()
diff --git a/usr.bin/bintrans/tests/regress.traditional.in b/usr.bin/bintrans/tests/regress.traditional.in
new file mode 100644
index 000000000000..da81415a34d6
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.traditional.in
@@ -0,0 +1,95 @@
+begin 644 regress.out
+M=![XYG<[;LZJX6VX="4_6IK%7W4DO3P.ZPE'B5^+X4^0$'UI_/]6C@%9T,2&
+M(VE$3"('^WCXHJ?W))`_NO0V6G6S"C%7&U[<9I!J\40&,A_>\0+R:A,.3KK'
+M/]"?V9$]6MR;HD3&\$V%MT0K?B3L(I<4/,=[5#1O"0&+#^MZ;J)D/)*:&F77
+M"P+P+SV6I`.716^=X4AG"G!T:!L[(!R=Z;>,8P0Q(<,X7OR`G&USW7*]@"PO
+M(PS(ZP88S7"(`H_*I/]TH-`ZBC%88-*WL_NMMRMS"Y0?*GZ@:5>KP8<;U00'
+MJRKQHKR.KCP@P@:S2?P+A#*U?+>CGI37+U4AVC]$^I,T62?M`TP7UM=R*QR[
+MD4:K6S$`"'\AM32=W-#:F1_V3ZZQ-'/89A6WU<C>-37T<S(?I16!;!0(WK<Y
+MRA69E&`TC\7\S01XIN:&I0Z0-G;!0D24X`D^IO>13\)N%;)50(Z6'>F![']+
+M5Y"285"H9VB.%`_9\/2,X[W77CJ!D_,U9SXBK#P\5UM!IYU]J-@7%MYV?=KD
+M;S)":^[UI?`N/V+LRMI`=V+4)PA@B5[NCZ<QX#C$?==_08=<)&#FXWYP?LGB
+M/H/GK@A$)=J?@6(O:%-INH0]!RKSG6:<LYT`0%QR9I?`:+)G&-B/>A3.HL33
+MZ=/.*I\QVFLZF=DKVG>9T(TE>H-'Q"!*O@4Q"TN%B>HZ&+INLL%$!\0>"LRU
+MFCG7#(UJL"V2IWX/93O1Y:I'V]%!U>(>`/%9,D%Q.V33LT8XJWR*#</&':`=
+M/R\)ZX4IR!E.WK;<+RJ$;*<N2''=Z]B3_YF#X:K;R8',8Z2[2[0/#'I'UQ\6
+MHHYQ,HT,5DF!&;*<Y2RX)W[3\QCCXATI<*O$="2:G)V`U$VC'SI?;>\N_-2Q
+MI!X]^)&8&)VGL@IL*SP37:;@*#9/R=J<`(I-7G`=L0!-LDFS!8;\]Y]Q"SPL
+MR;0[^T@X:T#8R+#<G6V-'_."8'OD.@R,[V%0)`7&@ZU&G99B`C2EKJL/7V-5
+M4M7BO1KN>%2&YK8G8)O.V.?AP@$?Q38\;[Q\`%0GM!O:*J&YK6"^:V=^X7CT
+M!V.#R^_,Y'IICT=-PI+/*':\4'Z(#=^FT`JEYNYH";A^6(#HO&M-V!IDR"JT
+MT,_D*$K3;33^J?N62#HPT9C+>%=2$K4M=BUM*A#AYHRY$O^2A+RP*/FX_-?)
+MW"+A;92OA.66QPS?*$@,"G'-=\N<W)(#-,[<W#FYPT0K#T`.;.42!%\BHN-!
+MC,O=4OB(!5%/>5D9WQ8L3<B21)F_?!Y0-AK<81,;9)YB.5'NN.Q%P^S/H$(C
+M5!/.UP79@L2P@%$#VT;*+<.O2G6&,W(R-95*J=HW:XHAX'X+O_RZK,KM23K[
+MD0)EP$O4Z6BROM0H;_?,='6(;<_61/1X[EZ)#SX5W`4J/<%W)RZ1:-4*1O%B
+M^[<.68!*;-%1F$_C`Z=R4N5D"8(,#NAN([B0+TNXE__Q;=&;]16M?\6'L_-Y
+MGF6BU3+3/;:#S\&!/.,.><I>(?J#5H/J:A>J&3X?)CWL5!AJZS:R5?-IN>:$
+M=';_73&F]-'2XQL@I;?+_L)PZ(5)CW_=@;T1?7]T94@?#OP41L3-OQ`5S*NN
+MN'ZPK$\`&.I!+@HF,9Y49<@6D>1-C3J<>E"LEW)A!(N4F),;8(V2,O_"*^GD
+M(8<($[S'1:"R%\G@-8HLHI_<ASUHU@3/V#BZ-3JX:_27TAUS[?RDD*MVI+)O
+M2.`\G<<1(4KBQY_&30PA)Q,:H1Y604#54/'QT<\Q1-33(VX;&>BD&XJ*J[X;
+MIF9O;9KGL2C0)R+B0B/MK:&1\8B(V)P&9F';:F:]#/C.*5W;!63Z+@1V+$$(
+MT&[!9B2&/XEGB3DI.1_%4@I\6F;EOA.>98^*#3:FB?KJT-AC8(486&;9$.4B
+MZ(F2;B5'_@FXMD^DR`3UN2N*XE34"6*[7.Y(Z6+"8V@XO[G83#-4O_G;)+S:
+MBU&0/+SWIT;B5JW0PD(?^K92L3BK$(',3>`QC=?6("#(</2LQ19@ONK@G(`H
+M=S(1]1D`GLH>X<+OA]2Q#-KFER6#L<SD4L<]>&]KKY''[W*.KZPQV"4%N@_G
+M:JG#!2S$(W'^<SUVF]7\`3SI'T!3\<%O#$_**BHN^J66M@+63PG1H1!F!95@
+M.'"F0@ASY;5@S4R@QQ0%G8"3#]#Y2W=VG=PN')+W(>L1_:^.JY,X.1DML+,:
+M.&)[QWH;1,Z@$MNPI)U$PQ?&K_<8K<_0L!%H0?+]+@K<O'+@F$ZF:S7=%]-?
+M!6B/9A3C%NK<!TP#W/JE"KA<OL5/]<N@&Q`UI0]Z,RP8+V&TRR,U&K1(;B6&
+MXR[R\V^TF02+]Q&Z&T2MSD?6IYKK+\IL&H_"%/K_\"7S^ZM/_I-4IXT-J<,5
+ME.B<,HS4$':E@4>^Y\U@NT&4(^(KBMP.2/,VA<^PH&O%0Z6O8W2[[?3[@DIG
+M5N1CB2!EO2D5^V(NCLZ^^$K#*<(C#]C\\2M)\QR27#9K]O(#+D3^89(Q@^O_
+M"</X"TM2;P`0-CH2]DI;,0*X8N<2`N7(S(9G@)'SW\B4^V(^FSA/*"A-BY_,
+MQ/T3C*ZW1JC*L(N)"].#W<\XG[3&7GO"U0J#%X3*81VS$L[4CER05.#W'KMB
+MQ`)/\N;F40.K;(8VBF1]QJ4?V26E\L"8:,Z;]$TT6GGCTQVQI?9*$^(O:K21
+MB31@-!IV2[*UN]-3MC^]`Z[Q6/PI!"/<(LR#/X"(M"S,HR;RJ;GWK,W12BR@
+MI(C]TU%E-:;_F4B^;HK9#O79@<.EA9C4)GA4CB$AN,?I.Q8&__ADC_=6=W#@
+M]@:+5KB+59.?EYP493U=\6ZK-W10^C3XVIFVA+A$XIB<#Y&$.8.<3?XKHE2Q
+MV(E@*XPX?;[[(JDWY_[D"VTW;].%S@S(-V,,?8U"YT,1)03Y![JF*O:WW,C$
+M:/S;(QBI'"=VP`,S3)',"2A*UJB0ZT:DB\LN..Z16#B#`=GISSCG#%A,R+^B
+M?YI!@9<MG?O*OOLQ`$6ER.9'<P7!N_O^V&@Y<6%K\>Y&MOQF0S*T":F(;:UQ
+MEY43B9#>;Z;,TN*9>PD8UHDMYE8&58#+_O=A'V%>/S2'!XV1;<>M._W)UUWP
+MO&C/56ST%YA@H.^'3T1JWUOI9X[H*\W4O.=#S13RN=B,*R?W5"5$SAJNG3_0
+M?R/IY0[4@2.NT?<8_B:IPQP4MJ>!+4?B#HXO'2>LP?`;W;\=<//I8=C+*4\T
+MMKI"AD5W[4R78TP5%2B`B5.>6@62&:T`!DQ%_I-K_.SM*U,LVHF)Q!NE*_%A
+M7'MKH@ZQ%6_0</<&,T37(+4')\&I73<DR=;L3"6[(MOY],K8Y&_WILZV`.)F
+M<HCC0WD-L)V4`ZX_NTZ1M*\&:/\JW7US>%FBDJ#^C$(0EIGQUHR_:2.<T/[4
+M]#M6>Y,KEH2VA'HO'D:=_L>W&B9D@F?%1?JK<"^Z@BSX<CP3C_R$CIMHW5.7
+MG7</R<FN7%/C4E#D+!(Z1:>@><6=^.:0A">TBNM^@ZXI^>ZCVP-:#7:ZX7@4
+MZ'$:7P3@:'$-)"0W&-#E[]DUNF4T>?GY/>%)B-#=@U4!?H:H;_6%N$^%3V-L
+MZKF+H<`&]7>7-7\4VEW>(E>"0'SDA?7EN%%@+0GJ%I/&:RW6EB$0K9U_)VHY
+MRQV8$_.),BW;OG/W)!UF=,/;@=YNEKP<;".">TM_JC3Q+0SNG/Y`^2[N:P>6
+MXB!N#C&B2&/(#'["/I801E^)`CU38=/UK0Z+I&Y[<K^-L;R.#%$-^#2NR./B
+MNTSY!F,J;U20<9WOV,6R8@^GW+J:B^"7]Z<TEI+\4V2&[`1GD;F,K05S#Y=P
+M*QG9NDXRODK2`7TRXD-[FI6NN,#*P_AY-;"74,U.L@C9W-6\@LCV%8MW?[12
+M@.>7_EI+N:D',E8@8#RS7G6+\5NP&[@$-_G)+HRF[PV.A3%%_E[QBED?E9)W
+MK<&OQ;B]@).LN"*SVH(UNCQ)'1Y?(7T'2DO[1XXZXCB*^&4-G;>[0F;!6+HH
+M\8YVXN[TCY0)L=]9+<3DP`)=6_N_J47.C;3A=\3+LNP#23,>0CVUT+FJW>8R
+MY-I\&1CQ0D.7IIT)?D$'KD';Y^LU(]OV`A`Q0Z14.NO.1+N$HB=X1DI%,UDP
+M35UO0IE@[5F+O/CI$U)9W`;`O*=>JL/L))5P4^J[);PW=5:\,T9MJ2X%"&DU
+M"_XCEH;QL:DG<(Q/_A:`S[H<T(>$%R,S-JNZQC'*J"A]6:J'0I7?U)@)KK5Z
+M>^C[8@AW"LJE2S6ZC;2#RQ%>*E4QI,8'>;$)2>;+*.*$TF?N;L&JBS)%.*1/
+MD8KU;0U_NY/Z%-$KTL&0[E2[!$&1A<A)@U[;7#]FH#V">)9V0)8C^8,JC8'D
+M_6ZN?'55'<TI%YC5Z_E5,L(8>0\EW8A(_UA!^U`G_R%.O5@-HG8)5=\,HA:5
+M/"#^=945W,^2[Z81B&5GBB=&06EY8Z/8SE$J$N,Y%6?MM]=2+58A7A;`!S<?
+M-[FSH"9CR9$O^9@4O]BI>:246T29^ZB%O_:;P[%D92EXY!\\$3/V+J"E3VU_
+MR=Z]9R&?=IW%1]=:J*KC5CO"%N]\SR'3L=1^.%\;L:(V\TBSW6*=7NF^BBN:
+M=?ZZ&(LCM(RJ40JH@[X)B^5*/_Q(@.!`%!XDM54+`RI`^-L1-P8`(!#$:[$,
+MB#=N4/0_]N:O,-_%])?U/.6X,EC;'["ZZ-BL,^_W8)XEX4FVB70/J]RI&Z<T
+M`)CS@+Z_7M6A%GDBUC)8O$)](D6OE+ZYTS@7S$O$$.6(Z3:02PKK2AV43#Z:
+M?)/"1LRF!UK!$6;U%15LB=DK^_K%%+[#W0L#K^$6%>LCY(M;`!./-MYPTH;Q
+MTF*@6H*N9:DEGJ)O)3[)4=5190Z>BX)DL,G(L^FN$E[HN,U.,_>V5,Y)1(^V
+M,.X_U2R];K$CWQ8TI18?7)QS-9L(>IR*!\3V-H6?O.HF<"7E8-SWK(115/6@
+MQL5ZDJ3)N%H^8IN^`[0\/V`6#?LL/VO:'OIA)FDY.P4`JX+EC%;HZ*E"]WV<
+MZ<EC4A31ND1L%?SY)H8?U=<=@</@Y8&7XJI4NJ"&B3]]=2(0_6A"+ZGX@+5_
+M(7;Y!N,;KF'OQUQ55;B3A\2X,C--JOZSI+NF)K\J([L%?/+#8AF[>KMAC&8F
+M5G&WG[>$>`N_04V")EXD',H2%H1:G7)^HXMIK5EK10TPAE`#H-*\LPH@DVO&
+MM8JJ"?8`'NA_:&M$3`_OJ9([U_C]XG#=\8'UA5R?Y&(_0ODNJ9B+>9*4(K-C
+MTWC'BH\H'6KBFUF!E1A6H_]X[:<ZQ'.J%J!N?,9("U?VSO'O:OU"N[8ZD`H*
+MLGXAX@3C*PVY2(F86+X+Q\&4L56*E^IF\K$)W-3AZ(V0ZOMU$F?/V.HMYZH4
+M<B^N\6M0\PO$:H8666J*@A/I]IB$L?'3$3FB>O-Y\.*E+'PQ6;$[Q$[M>#<`
+!9P``
+`
+end
diff --git a/usr.bin/bintrans/tests/regress.traditional.out b/usr.bin/bintrans/tests/regress.traditional.out
new file mode 100644
index 000000000000..ee1352f165a2
--- /dev/null
+++ b/usr.bin/bintrans/tests/regress.traditional.out
@@ -0,0 +1,95 @@
+begin 644 regress.in
+M=![XYG<[;LZJX6VX="4_6IK%7W4DO3P.ZPE'B5^+X4^0$'UI_/]6C@%9T,2&
+M(VE$3"('^WCXHJ?W))`_NO0V6G6S"C%7&U[<9I!J\40&,A_>\0+R:A,.3KK'
+M/]"?V9$]6MR;HD3&\$V%MT0K?B3L(I<4/,=[5#1O"0&+#^MZ;J)D/)*:&F77
+M"P+P+SV6I`.716^=X4AG"G!T:!L[(!R=Z;>,8P0Q(<,X7OR`G&USW7*]@"PO
+M(PS(ZP88S7"(`H_*I/]TH-`ZBC%88-*WL_NMMRMS"Y0?*GZ@:5>KP8<;U00'
+MJRKQHKR.KCP@P@:S2?P+A#*U?+>CGI37+U4AVC]$^I,T62?M`TP7UM=R*QR[
+MD4:K6S$`"'\AM32=W-#:F1_V3ZZQ-'/89A6WU<C>-37T<S(?I16!;!0(WK<Y
+MRA69E&`TC\7\S01XIN:&I0Z0-G;!0D24X`D^IO>13\)N%;)50(Z6'>F![']+
+M5Y"285"H9VB.%`_9\/2,X[W77CJ!D_,U9SXBK#P\5UM!IYU]J-@7%MYV?=KD
+M;S)":^[UI?`N/V+LRMI`=V+4)PA@B5[NCZ<QX#C$?==_08=<)&#FXWYP?LGB
+M/H/GK@A$)=J?@6(O:%-INH0]!RKSG6:<LYT`0%QR9I?`:+)G&-B/>A3.HL33
+MZ=/.*I\QVFLZF=DKVG>9T(TE>H-'Q"!*O@4Q"TN%B>HZ&+INLL%$!\0>"LRU
+MFCG7#(UJL"V2IWX/93O1Y:I'V]%!U>(>`/%9,D%Q.V33LT8XJWR*#</&':`=
+M/R\)ZX4IR!E.WK;<+RJ$;*<N2''=Z]B3_YF#X:K;R8',8Z2[2[0/#'I'UQ\6
+MHHYQ,HT,5DF!&;*<Y2RX)W[3\QCCXATI<*O$="2:G)V`U$VC'SI?;>\N_-2Q
+MI!X]^)&8&)VGL@IL*SP37:;@*#9/R=J<`(I-7G`=L0!-LDFS!8;\]Y]Q"SPL
+MR;0[^T@X:T#8R+#<G6V-'_."8'OD.@R,[V%0)`7&@ZU&G99B`C2EKJL/7V-5
+M4M7BO1KN>%2&YK8G8)O.V.?AP@$?Q38\;[Q\`%0GM!O:*J&YK6"^:V=^X7CT
+M!V.#R^_,Y'IICT=-PI+/*':\4'Z(#=^FT`JEYNYH";A^6(#HO&M-V!IDR"JT
+MT,_D*$K3;33^J?N62#HPT9C+>%=2$K4M=BUM*A#AYHRY$O^2A+RP*/FX_-?)
+MW"+A;92OA.66QPS?*$@,"G'-=\N<W)(#-,[<W#FYPT0K#T`.;.42!%\BHN-!
+MC,O=4OB(!5%/>5D9WQ8L3<B21)F_?!Y0-AK<81,;9)YB.5'NN.Q%P^S/H$(C
+M5!/.UP79@L2P@%$#VT;*+<.O2G6&,W(R-95*J=HW:XHAX'X+O_RZK,KM23K[
+MD0)EP$O4Z6BROM0H;_?,='6(;<_61/1X[EZ)#SX5W`4J/<%W)RZ1:-4*1O%B
+M^[<.68!*;-%1F$_C`Z=R4N5D"8(,#NAN([B0+TNXE__Q;=&;]16M?\6'L_-Y
+MGF6BU3+3/;:#S\&!/.,.><I>(?J#5H/J:A>J&3X?)CWL5!AJZS:R5?-IN>:$
+M=';_73&F]-'2XQL@I;?+_L)PZ(5)CW_=@;T1?7]T94@?#OP41L3-OQ`5S*NN
+MN'ZPK$\`&.I!+@HF,9Y49<@6D>1-C3J<>E"LEW)A!(N4F),;8(V2,O_"*^GD
+M(8<($[S'1:"R%\G@-8HLHI_<ASUHU@3/V#BZ-3JX:_27TAUS[?RDD*MVI+)O
+M2.`\G<<1(4KBQY_&30PA)Q,:H1Y604#54/'QT<\Q1-33(VX;&>BD&XJ*J[X;
+MIF9O;9KGL2C0)R+B0B/MK:&1\8B(V)P&9F';:F:]#/C.*5W;!63Z+@1V+$$(
+MT&[!9B2&/XEGB3DI.1_%4@I\6F;EOA.>98^*#3:FB?KJT-AC8(486&;9$.4B
+MZ(F2;B5'_@FXMD^DR`3UN2N*XE34"6*[7.Y(Z6+"8V@XO[G83#-4O_G;)+S:
+MBU&0/+SWIT;B5JW0PD(?^K92L3BK$(',3>`QC=?6("#(</2LQ19@ONK@G(`H
+M=S(1]1D`GLH>X<+OA]2Q#-KFER6#L<SD4L<]>&]KKY''[W*.KZPQV"4%N@_G
+M:JG#!2S$(W'^<SUVF]7\`3SI'T!3\<%O#$_**BHN^J66M@+63PG1H1!F!95@
+M.'"F0@ASY;5@S4R@QQ0%G8"3#]#Y2W=VG=PN')+W(>L1_:^.JY,X.1DML+,:
+M.&)[QWH;1,Z@$MNPI)U$PQ?&K_<8K<_0L!%H0?+]+@K<O'+@F$ZF:S7=%]-?
+M!6B/9A3C%NK<!TP#W/JE"KA<OL5/]<N@&Q`UI0]Z,RP8+V&TRR,U&K1(;B6&
+MXR[R\V^TF02+]Q&Z&T2MSD?6IYKK+\IL&H_"%/K_\"7S^ZM/_I-4IXT-J<,5
+ME.B<,HS4$':E@4>^Y\U@NT&4(^(KBMP.2/,VA<^PH&O%0Z6O8W2[[?3[@DIG
+M5N1CB2!EO2D5^V(NCLZ^^$K#*<(C#]C\\2M)\QR27#9K]O(#+D3^89(Q@^O_
+M"</X"TM2;P`0-CH2]DI;,0*X8N<2`N7(S(9G@)'SW\B4^V(^FSA/*"A-BY_,
+MQ/T3C*ZW1JC*L(N)"].#W<\XG[3&7GO"U0J#%X3*81VS$L[4CER05.#W'KMB
+MQ`)/\N;F40.K;(8VBF1]QJ4?V26E\L"8:,Z;]$TT6GGCTQVQI?9*$^(O:K21
+MB31@-!IV2[*UN]-3MC^]`Z[Q6/PI!"/<(LR#/X"(M"S,HR;RJ;GWK,W12BR@
+MI(C]TU%E-:;_F4B^;HK9#O79@<.EA9C4)GA4CB$AN,?I.Q8&__ADC_=6=W#@
+M]@:+5KB+59.?EYP493U=\6ZK-W10^C3XVIFVA+A$XIB<#Y&$.8.<3?XKHE2Q
+MV(E@*XPX?;[[(JDWY_[D"VTW;].%S@S(-V,,?8U"YT,1)03Y![JF*O:WW,C$
+M:/S;(QBI'"=VP`,S3)',"2A*UJB0ZT:DB\LN..Z16#B#`=GISSCG#%A,R+^B
+M?YI!@9<MG?O*OOLQ`$6ER.9'<P7!N_O^V&@Y<6%K\>Y&MOQF0S*T":F(;:UQ
+MEY43B9#>;Z;,TN*9>PD8UHDMYE8&58#+_O=A'V%>/S2'!XV1;<>M._W)UUWP
+MO&C/56ST%YA@H.^'3T1JWUOI9X[H*\W4O.=#S13RN=B,*R?W5"5$SAJNG3_0
+M?R/IY0[4@2.NT?<8_B:IPQP4MJ>!+4?B#HXO'2>LP?`;W;\=<//I8=C+*4\T
+MMKI"AD5W[4R78TP5%2B`B5.>6@62&:T`!DQ%_I-K_.SM*U,LVHF)Q!NE*_%A
+M7'MKH@ZQ%6_0</<&,T37(+4')\&I73<DR=;L3"6[(MOY],K8Y&_WILZV`.)F
+M<HCC0WD-L)V4`ZX_NTZ1M*\&:/\JW7US>%FBDJ#^C$(0EIGQUHR_:2.<T/[4
+M]#M6>Y,KEH2VA'HO'D:=_L>W&B9D@F?%1?JK<"^Z@BSX<CP3C_R$CIMHW5.7
+MG7</R<FN7%/C4E#D+!(Z1:>@><6=^.:0A">TBNM^@ZXI^>ZCVP-:#7:ZX7@4
+MZ'$:7P3@:'$-)"0W&-#E[]DUNF4T>?GY/>%)B-#=@U4!?H:H;_6%N$^%3V-L
+MZKF+H<`&]7>7-7\4VEW>(E>"0'SDA?7EN%%@+0GJ%I/&:RW6EB$0K9U_)VHY
+MRQV8$_.),BW;OG/W)!UF=,/;@=YNEKP<;".">TM_JC3Q+0SNG/Y`^2[N:P>6
+MXB!N#C&B2&/(#'["/I801E^)`CU38=/UK0Z+I&Y[<K^-L;R.#%$-^#2NR./B
+MNTSY!F,J;U20<9WOV,6R8@^GW+J:B^"7]Z<TEI+\4V2&[`1GD;F,K05S#Y=P
+M*QG9NDXRODK2`7TRXD-[FI6NN,#*P_AY-;"74,U.L@C9W-6\@LCV%8MW?[12
+M@.>7_EI+N:D',E8@8#RS7G6+\5NP&[@$-_G)+HRF[PV.A3%%_E[QBED?E9)W
+MK<&OQ;B]@).LN"*SVH(UNCQ)'1Y?(7T'2DO[1XXZXCB*^&4-G;>[0F;!6+HH
+M\8YVXN[TCY0)L=]9+<3DP`)=6_N_J47.C;3A=\3+LNP#23,>0CVUT+FJW>8R
+MY-I\&1CQ0D.7IIT)?D$'KD';Y^LU(]OV`A`Q0Z14.NO.1+N$HB=X1DI%,UDP
+M35UO0IE@[5F+O/CI$U)9W`;`O*=>JL/L))5P4^J[);PW=5:\,T9MJ2X%"&DU
+M"_XCEH;QL:DG<(Q/_A:`S[H<T(>$%R,S-JNZQC'*J"A]6:J'0I7?U)@)KK5Z
+M>^C[8@AW"LJE2S6ZC;2#RQ%>*E4QI,8'>;$)2>;+*.*$TF?N;L&JBS)%.*1/
+MD8KU;0U_NY/Z%-$KTL&0[E2[!$&1A<A)@U[;7#]FH#V">)9V0)8C^8,JC8'D
+M_6ZN?'55'<TI%YC5Z_E5,L(8>0\EW8A(_UA!^U`G_R%.O5@-HG8)5=\,HA:5
+M/"#^=945W,^2[Z81B&5GBB=&06EY8Z/8SE$J$N,Y%6?MM]=2+58A7A;`!S<?
+M-[FSH"9CR9$O^9@4O]BI>:246T29^ZB%O_:;P[%D92EXY!\\$3/V+J"E3VU_
+MR=Z]9R&?=IW%1]=:J*KC5CO"%N]\SR'3L=1^.%\;L:(V\TBSW6*=7NF^BBN:
+M=?ZZ&(LCM(RJ40JH@[X)B^5*/_Q(@.!`%!XDM54+`RI`^-L1-P8`(!#$:[$,
+MB#=N4/0_]N:O,-_%])?U/.6X,EC;'["ZZ-BL,^_W8)XEX4FVB70/J]RI&Z<T
+M`)CS@+Z_7M6A%GDBUC)8O$)](D6OE+ZYTS@7S$O$$.6(Z3:02PKK2AV43#Z:
+M?)/"1LRF!UK!$6;U%15LB=DK^_K%%+[#W0L#K^$6%>LCY(M;`!./-MYPTH;Q
+MTF*@6H*N9:DEGJ)O)3[)4=5190Z>BX)DL,G(L^FN$E[HN,U.,_>V5,Y)1(^V
+M,.X_U2R];K$CWQ8TI18?7)QS-9L(>IR*!\3V-H6?O.HF<"7E8-SWK(115/6@
+MQL5ZDJ3)N%H^8IN^`[0\/V`6#?LL/VO:'OIA)FDY.P4`JX+EC%;HZ*E"]WV<
+MZ<EC4A31ND1L%?SY)H8?U=<=@</@Y8&7XJI4NJ"&B3]]=2(0_6A"+ZGX@+5_
+M(7;Y!N,;KF'OQUQ55;B3A\2X,C--JOZSI+NF)K\J([L%?/+#8AF[>KMAC&8F
+M5G&WG[>$>`N_04V")EXD',H2%H1:G7)^HXMIK5EK10TPAE`#H-*\LPH@DVO&
+MM8JJ"?8`'NA_:&M$3`_OJ9([U_C]XG#=\8'UA5R?Y&(_0ODNJ9B+>9*4(K-C
+MTWC'BH\H'6KBFUF!E1A6H_]X[:<ZQ'.J%J!N?,9("U?VSO'O:OU"N[8ZD`H*
+MLGXAX@3C*PVY2(F86+X+Q\&4L56*E^IF\K$)W-3AZ(V0ZOMU$F?/V.HMYZH4
+M<B^N\6M0\PO$:H8666J*@A/I]IB$L?'3$3FB>O-Y\.*E+'PQ6;$[Q$[M>#<`
+!9P``
+`
+end
diff --git a/usr.bin/bintrans/tests/textqpdec b/usr.bin/bintrans/tests/textqpdec
new file mode 100644
index 000000000000..f48aacc191f2
--- /dev/null
+++ b/usr.bin/bintrans/tests/textqpdec
@@ -0,0 +1,2 @@
+J'interdis aux marchands de vanter trop leurs marchandises. Car ils se font vite pédagogues et t'enseignent comme but ce qui n'est par essence qu'un moyen, et te trompant ainsi sur la route à suivre les voilà bientôt qui te dégradent, car si leur musique est vulgaire ils te fabriquent pour te la vendre une âme vulgaire.
+ — Antoine de Saint-Exupéry, Citadelle (1948)
diff --git a/usr.bin/bintrans/tests/textqpenc b/usr.bin/bintrans/tests/textqpenc
new file mode 100644
index 000000000000..c51772d033ab
--- /dev/null
+++ b/usr.bin/bintrans/tests/textqpenc
@@ -0,0 +1,6 @@
+J'interdis aux marchands de vanter trop leurs marchandises. Car ils se font=
+ vite p=C3=A9dagogues et t'enseignent comme but ce qui n'est par essence qu=
+'un moyen, et te trompant ainsi sur la route =C3=A0 suivre les voil=C3=A0 b=
+ient=C3=B4t qui te d=C3=A9gradent, car si leur musique est vulgaire ils te =
+fabriquent pour te la vendre une =C3=A2me vulgaire=2E
+ =E2=80=94=E2=80=89Antoine de Saint-Exup=C3=A9ry, Citadelle (1948)
diff --git a/usr.bin/bintrans/uudecode.c b/usr.bin/bintrans/uudecode.c
new file mode 100644
index 000000000000..5a252b71055e
--- /dev/null
+++ b/usr.bin/bintrans/uudecode.c
@@ -0,0 +1,486 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * uudecode [file ...]
+ *
+ * create the specified file, decoding as you go.
+ * used with uuencode.
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <pwd.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int main_decode(int, char *[]);
+extern int main_base64_decode(const char *);
+
+static const char *infile, *outfile;
+static FILE *infp, *outfp;
+static bool base64, cflag, iflag, oflag, pflag, rflag, sflag;
+
+static void usage(void);
+static int decode(void);
+static int decode2(void);
+static int uu_decode(void);
+static int base64_decode(void);
+
+int
+main_base64_decode(const char *in)
+{
+ base64 = 1;
+ rflag = 1;
+ if (in != NULL) {
+ infile = in;
+ infp = fopen(infile, "r");
+ if (infp == NULL)
+ err(1, "%s", in);
+ } else {
+ infile = "stdin";
+ infp = stdin;
+ }
+ exit(decode());
+}
+
+int
+main_decode(int argc, char *argv[])
+{
+ int rval, ch;
+
+ if (strcmp(basename(argv[0]), "b64decode") == 0)
+ base64 = true;
+
+ while ((ch = getopt(argc, argv, "cimo:prs")) != -1) {
+ switch (ch) {
+ case 'c':
+ if (oflag || rflag)
+ usage();
+ cflag = true; /* multiple uudecode'd files */
+ break;
+ case 'i':
+ iflag = true; /* ask before override files */
+ break;
+ case 'm':
+ base64 = true;
+ break;
+ case 'o':
+ if (cflag || pflag || rflag || sflag)
+ usage();
+ oflag = true; /* output to the specified file */
+ sflag = true; /* do not strip pathnames for output */
+ outfile = optarg; /* set the output filename */
+ break;
+ case 'p':
+ if (oflag)
+ usage();
+ pflag = true; /* print output to stdout */
+ break;
+ case 'r':
+ if (cflag || oflag)
+ usage();
+ rflag = true; /* decode raw data */
+ break;
+ case 's':
+ if (oflag)
+ usage();
+ sflag = true; /* do not strip pathnames for output */
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (*argv != NULL) {
+ rval = 0;
+ do {
+ infp = fopen(infile = *argv, "r");
+ if (infp == NULL) {
+ warn("%s", *argv);
+ rval = 1;
+ continue;
+ }
+ rval |= decode();
+ fclose(infp);
+ } while (*++argv);
+ } else {
+ infile = "stdin";
+ infp = stdin;
+ rval = decode();
+ }
+ exit(rval);
+}
+
+static int
+decode(void)
+{
+ int r, v;
+
+ if (rflag) {
+ /* relaxed alternative to decode2() */
+ outfile = "/dev/stdout";
+ outfp = stdout;
+ if (base64)
+ return (base64_decode());
+ else
+ return (uu_decode());
+ }
+ v = decode2();
+ if (v == EOF) {
+ warnx("%s: missing or bad \"begin\" line", infile);
+ return (1);
+ }
+ for (r = v; cflag; r |= v) {
+ v = decode2();
+ if (v == EOF)
+ break;
+ }
+ return (r);
+}
+
+static int
+decode2(void)
+{
+ int flags, fd, mode;
+ size_t n, m;
+ char *p, *q;
+ void *handle;
+ struct passwd *pw;
+ struct stat st;
+ char buf[MAXPATHLEN + 1];
+
+ base64 = false;
+ /* search for header line */
+ for (;;) {
+ if (fgets(buf, sizeof(buf), infp) == NULL)
+ return (EOF);
+ p = buf;
+ if (strncmp(p, "begin-base64 ", 13) == 0) {
+ base64 = true;
+ p += 13;
+ } else if (strncmp(p, "begin ", 6) == 0)
+ p += 6;
+ else
+ continue;
+ /* p points to mode */
+ q = strchr(p, ' ');
+ if (q == NULL)
+ continue;
+ *q++ = '\0';
+ /* q points to filename */
+ n = strlen(q);
+ while (n > 0 && (q[n-1] == '\n' || q[n-1] == '\r'))
+ q[--n] = '\0';
+ /* found valid header? */
+ if (n > 0)
+ break;
+ }
+
+ handle = setmode(p);
+ if (handle == NULL) {
+ warnx("%s: unable to parse file mode", infile);
+ return (1);
+ }
+ mode = getmode(handle, 0) & 0666;
+ free(handle);
+
+ if (sflag) {
+ /* don't strip, so try ~user/file expansion */
+ p = NULL;
+ pw = NULL;
+ if (*q == '~')
+ p = strchr(q, '/');
+ if (p != NULL) {
+ *p = '\0';
+ pw = getpwnam(q + 1);
+ *p = '/';
+ }
+ if (pw != NULL) {
+ n = strlen(pw->pw_dir);
+ if (buf + n > p) {
+ /* make room */
+ m = strlen(p);
+ if (sizeof(buf) < n + m) {
+ warnx("%s: bad output filename",
+ infile);
+ return (1);
+ }
+ p = memmove(buf + n, p, m);
+ }
+ q = memcpy(p - n, pw->pw_dir, n);
+ }
+ } else {
+ /* strip down to leaf name */
+ p = strrchr(q, '/');
+ if (p != NULL)
+ q = p + 1;
+ }
+ if (!oflag)
+ outfile = q;
+
+ /* POSIX says "/dev/stdout" is a 'magic cookie' not a special file. */
+ if (pflag || strcmp(outfile, "/dev/stdout") == 0)
+ outfp = stdout;
+ else {
+ flags = O_WRONLY | O_CREAT | O_EXCL;
+ if (lstat(outfile, &st) == 0) {
+ if (iflag) {
+ warnc(EEXIST, "%s: %s", infile, outfile);
+ return (0);
+ }
+ switch (st.st_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFLNK:
+ /* avoid symlink attacks */
+ if (unlink(outfile) == 0 || errno == ENOENT)
+ break;
+ warn("%s: unlink %s", infile, outfile);
+ return (1);
+ case S_IFDIR:
+ warnc(EISDIR, "%s: %s", infile, outfile);
+ return (1);
+ default:
+ if (oflag) {
+ /* trust command-line names */
+ flags &= ~O_EXCL;
+ break;
+ }
+ warnc(EEXIST, "%s: %s", infile, outfile);
+ return (1);
+ }
+ } else if (errno != ENOENT) {
+ warn("%s: %s", infile, outfile);
+ return (1);
+ }
+ if ((fd = open(outfile, flags, mode)) < 0 ||
+ (outfp = fdopen(fd, "w")) == NULL) {
+ warn("%s: %s", infile, outfile);
+ return (1);
+ }
+ }
+
+ if (base64)
+ return (base64_decode());
+ else
+ return (uu_decode());
+}
+
+static int
+get_line(char *buf, size_t size)
+{
+
+ if (fgets(buf, size, infp) != NULL)
+ return (2);
+ if (rflag)
+ return (0);
+ warnx("%s: %s: short file", infile, outfile);
+ return (1);
+}
+
+static int
+checkend(const char *ptr, const char *end, const char *msg)
+{
+ size_t n;
+
+ n = strlen(end);
+ if (strncmp(ptr, end, n) != 0 ||
+ strspn(ptr + n, " \t\r\n") != strlen(ptr + n)) {
+ warnx("%s: %s: %s", infile, outfile, msg);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+checkout(int rval)
+{
+ if (fflush(outfp) != 0) {
+ warn("%s: %s", infile, outfile);
+ rval = 1;
+ }
+ if (outfp != stdout) {
+ (void)fclose(outfp);
+ outfp = stdout;
+ }
+ outfile = "/dev/stdout";
+ return (rval);
+}
+
+static int
+uu_decode(void)
+{
+ int i, ch;
+ char *p;
+ char buf[MAXPATHLEN+1];
+
+ /* for each input line */
+ for (;;) {
+ switch (get_line(buf, sizeof(buf))) {
+ case 0:
+ return (checkout(0));
+ case 1:
+ return (checkout(1));
+ }
+
+#define DEC(c) (((c) - ' ') & 077) /* single character decode */
+#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) )
+
+#define OUT_OF_RANGE do { \
+ warnx("%s: %s: character out of range: [%d-%d]", \
+ infile, outfile, ' ', 077 + ' ' + 1); \
+ return (1); \
+} while (0)
+
+ /*
+ * `i' is used to avoid writing out all the characters
+ * at the end of the file.
+ */
+ p = buf;
+ if ((i = DEC(*p)) <= 0)
+ break;
+ for (++p; i > 0; p += 4, i -= 3)
+ if (i >= 3) {
+ if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) &&
+ IS_DEC(*(p + 2)) && IS_DEC(*(p + 3))))
+ OUT_OF_RANGE;
+
+ ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
+ putc(ch, outfp);
+ ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
+ putc(ch, outfp);
+ ch = DEC(p[2]) << 6 | DEC(p[3]);
+ putc(ch, outfp);
+ } else {
+ if (i >= 1) {
+ if (!(IS_DEC(*p) && IS_DEC(*(p + 1))))
+ OUT_OF_RANGE;
+ ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
+ putc(ch, outfp);
+ }
+ if (i >= 2) {
+ if (!(IS_DEC(*(p + 1)) &&
+ IS_DEC(*(p + 2))))
+ OUT_OF_RANGE;
+
+ ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
+ putc(ch, outfp);
+ }
+ if (i >= 3) {
+ if (!(IS_DEC(*(p + 2)) &&
+ IS_DEC(*(p + 3))))
+ OUT_OF_RANGE;
+ ch = DEC(p[2]) << 6 | DEC(p[3]);
+ putc(ch, outfp);
+ }
+ }
+ }
+ switch (get_line(buf, sizeof(buf))) {
+ case 0:
+ return (checkout(0));
+ case 1:
+ return (checkout(1));
+ default:
+ return (checkout(checkend(buf, "end", "no \"end\" line")));
+ }
+}
+
+static int
+base64_decode(void)
+{
+ int n, count, count4;
+ char inbuf[MAXPATHLEN + 1], *p;
+ unsigned char outbuf[MAXPATHLEN * 4];
+ char leftover[MAXPATHLEN + 1];
+
+ leftover[0] = '\0';
+ for (;;) {
+ strcpy(inbuf, leftover);
+ switch (get_line(inbuf + strlen(inbuf),
+ sizeof(inbuf) - strlen(inbuf))) {
+ case 0:
+ return (checkout(0));
+ case 1:
+ return (checkout(1));
+ }
+
+ count = 0;
+ count4 = -1;
+ p = inbuf;
+ while (*p != '\0') {
+ /*
+ * Base64 encoded strings have the following
+ * characters in them: A-Z, a-z, 0-9 and +, / and =
+ */
+ if (isalnum(*p) || *p == '+' || *p == '/' || *p == '=')
+ count++;
+ if (count % 4 == 0)
+ count4 = p - inbuf;
+ p++;
+ }
+
+ strcpy(leftover, inbuf + count4 + 1);
+ inbuf[count4 + 1] = 0;
+
+ n = b64_pton(inbuf, outbuf, sizeof(outbuf));
+
+ if (n < 0)
+ break;
+ fwrite(outbuf, 1, n, outfp);
+ }
+ return (checkout(checkend(inbuf, "====", "error decoding base64 input stream")));
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: uudecode [-cimprs] [file ...]\n"
+ " uudecode [-i] -o output_file [file]\n"
+ " b64decode [-cimprs] [file ...]\n"
+ " b64decode [-i] -o output_file [file]\n");
+ exit(1);
+}
diff --git a/usr.bin/bintrans/uuencode.c b/usr.bin/bintrans/uuencode.c
new file mode 100644
index 000000000000..db0419ef0dac
--- /dev/null
+++ b/usr.bin/bintrans/uuencode.c
@@ -0,0 +1,275 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * uuencode [input] output
+ *
+ * Encode a file so it can be mailed to a remote system.
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libgen.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int main_encode(int, char *[]);
+extern int main_base64_encode(const char *, const char *);
+
+static void encode(void);
+static void base64_encode(void);
+static int arg_to_col(const char *);
+static void usage(void) __dead2;
+
+static FILE *output;
+static int mode;
+static bool raw;
+static char **av;
+static int columns = 76;
+
+int
+main_base64_encode(const char *in, const char *w)
+{
+ raw = 1;
+ if (in != NULL && freopen(in, "r", stdin) == NULL)
+ err(1, "%s", in);
+ output = stdout;
+ if (w != NULL)
+ columns = arg_to_col(w);
+ base64_encode();
+ if (fflush(output) != 0)
+ errx(1, "write error");
+ exit(0);
+}
+
+int
+main_encode(int argc, char *argv[])
+{
+ struct stat sb;
+ bool base64;
+ int ch;
+ const char *outfile;
+
+ base64 = false;
+ outfile = NULL;
+
+ if (strcmp(basename(argv[0]), "b64encode") == 0)
+ base64 = 1;
+
+ while ((ch = getopt(argc, argv, "mo:rw:")) != -1) {
+ switch (ch) {
+ case 'm':
+ base64 = true;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'r':
+ raw = true;
+ break;
+ case 'w':
+ columns = arg_to_col(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ switch (argc) {
+ case 2: /* optional first argument is input file */
+ if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
+ err(1, "%s", *argv);
+#define RWX (S_IRWXU|S_IRWXG|S_IRWXO)
+ mode = sb.st_mode & RWX;
+ ++argv;
+ break;
+ case 1:
+#define RW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+ mode = RW & ~umask(RW);
+ break;
+ case 0:
+ default:
+ usage();
+ }
+
+ av = argv;
+
+ if (outfile != NULL) {
+ output = fopen(outfile, "w+");
+ if (output == NULL)
+ err(1, "unable to open %s for output", outfile);
+ } else
+ output = stdout;
+ if (base64)
+ base64_encode();
+ else
+ encode();
+ if (fflush(output) != 0)
+ errx(1, "write error");
+ exit(0);
+}
+
+/* ENC is the basic 1 character encoding function to make a char printing */
+#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
+
+/*
+ * Copy from in to out, encoding in base64 as you go along.
+ */
+static void
+base64_encode(void)
+{
+ /*
+ * This buffer's length should be a multiple of 24 bits to avoid "="
+ * padding. Once it reached ~1 KB, further expansion didn't improve
+ * performance for me.
+ */
+ unsigned char buf[1023];
+ char buf2[sizeof(buf) * 2 + 1];
+ size_t n;
+ unsigned carry = 0;
+ int rv, written;
+
+ if (!raw)
+ fprintf(output, "begin-base64 %o %s\n", mode, *av);
+ while ((n = fread(buf, 1, sizeof(buf), stdin))) {
+ rv = b64_ntop(buf, n, buf2, nitems(buf2));
+ if (rv == -1)
+ errx(1, "b64_ntop: error encoding base64");
+ if (columns == 0) {
+ fputs(buf2, output);
+ continue;
+ }
+ for (int i = 0; i < rv; i += written) {
+ written = fprintf(output, "%.*s", columns - carry,
+ &buf2[i]);
+
+ carry = (carry + written) % columns;
+ if (carry == 0)
+ fputc('\n', output);
+ }
+ }
+ if (columns == 0 || carry != 0)
+ fputc('\n', output);
+ if (!raw)
+ fprintf(output, "====\n");
+}
+
+/*
+ * Copy from in to out, encoding as you go along.
+ */
+static void
+encode(void)
+{
+ int ch, n;
+ char *p;
+ char buf[80];
+
+ if (!raw)
+ (void)fprintf(output, "begin %o %s\n", mode, *av);
+ while ((n = fread(buf, 1, 45, stdin))) {
+ ch = ENC(n);
+ if (fputc(ch, output) == EOF)
+ break;
+ for (p = buf; n > 0; n -= 3, p += 3) {
+ /* Pad with nulls if not a multiple of 3. */
+ if (n < 3) {
+ p[2] = '\0';
+ if (n < 2)
+ p[1] = '\0';
+ }
+ ch = *p >> 2;
+ ch = ENC(ch);
+ if (fputc(ch, output) == EOF)
+ break;
+ ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
+ ch = ENC(ch);
+ if (fputc(ch, output) == EOF)
+ break;
+ ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
+ ch = ENC(ch);
+ if (fputc(ch, output) == EOF)
+ break;
+ ch = p[2] & 077;
+ ch = ENC(ch);
+ if (fputc(ch, output) == EOF)
+ break;
+ }
+ if (fputc('\n', output) == EOF)
+ break;
+ }
+ if (ferror(stdin))
+ errx(1, "read error");
+ if (!raw)
+ (void)fprintf(output, "%c\nend\n", ENC('\0'));
+}
+
+static int
+arg_to_col(const char *w)
+{
+ char *ep;
+ long option;
+
+ errno = 0;
+ option = strtol(w, &ep, 10);
+ if (option > INT_MAX)
+ errno = ERANGE;
+ else if (ep[0] != '\0')
+ errno = EINVAL;
+ if (errno != 0)
+ err(2, NULL);
+
+ if (option < 0) {
+ errno = EINVAL;
+ err(2, "columns argument must be non-negative");
+ }
+ return (option);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"
+" b64encode [-o outfile] [infile] remotefile\n");
+ exit(1);
+}
diff --git a/usr.bin/bintrans/uuencode.format.5 b/usr.bin/bintrans/uuencode.format.5
new file mode 100644
index 000000000000..4daafda7a337
--- /dev/null
+++ b/usr.bin/bintrans/uuencode.format.5
@@ -0,0 +1,99 @@
+.\" 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.
+.\"
+.Dd January 12, 1994
+.Dt UUENCODE 5
+.Os
+.Sh NAME
+.Nm uuencode
+.Nd format of an encoded uuencode file
+.Sh DESCRIPTION
+Files output by
+.Xr uuencode 1
+consist of a header line,
+followed by a number of body lines,
+and a trailer line.
+The
+.Xr uudecode 1
+command
+will ignore any lines preceding the header or
+following the trailer.
+Lines preceding a header must not, of course,
+look like a header.
+.Pp
+The header line is distinguished by having the first
+6 characters
+.Dq begin\ \&
+(note the trailing space).
+The word
+.Em begin
+is followed by a mode (in octal),
+and a string which names the remote file.
+A space separates the three items in the header line.
+.Pp
+The body consists of a number of lines, each at most 62 characters
+long (including the trailing newline).
+These consist of a character count,
+followed by encoded characters,
+followed by a newline.
+The character count is a single printing character,
+and represents an integer, the number of bytes
+the rest of the line represents.
+Such integers are always in the range from 1 to 45 or 64 and can
+be determined by subtracting the character space (octal 40)
+from the character.
+Character 64 represents a count of zero.
+.Pp
+Groups of 3 bytes are stored in 4 characters, 6 bits per character.
+All characters are always in range from 1 to 64 and are offset by a
+space (octal 40) to make the characters printing.
+Character
+64 represents a count of zero.
+The last line may be shorter than the normal 45 bytes.
+If the size is not a multiple of 3, this fact can be determined
+by the value of the count on the last line.
+Extra null characters will be included to make the character count a multiple
+of 4.
+The body is terminated by a line with a count of zero.
+This line consists of one
+.Tn ASCII
+backquote (octal 140) character.
+.Pp
+The trailer line consists of
+.Dq end
+on a line by itself.
+.Sh SEE ALSO
+.Xr mail 1 ,
+.Xr uucp 1 ,
+.Xr uudecode 1 ,
+.Xr uuencode 1
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 4.0 .
+.\" It was named uuencode.5 prior to 4.3
diff --git a/usr.bin/bluetooth/Makefile b/usr.bin/bluetooth/Makefile
new file mode 100644
index 000000000000..578a16f59d90
--- /dev/null
+++ b/usr.bin/bluetooth/Makefile
@@ -0,0 +1,9 @@
+# $Id $
+
+SUBDIR= \
+ bthost \
+ btsockstat \
+ rfcomm_sppd
+
+.include <bsd.subdir.mk>
+
diff --git a/usr.bin/bluetooth/Makefile.inc b/usr.bin/bluetooth/Makefile.inc
new file mode 100644
index 000000000000..de15587ee7cd
--- /dev/null
+++ b/usr.bin/bluetooth/Makefile.inc
@@ -0,0 +1,2 @@
+.include "${SRCTOP}/usr.bin/Makefile.inc"
+
diff --git a/usr.bin/bluetooth/bthost/Makefile b/usr.bin/bluetooth/bthost/Makefile
new file mode 100644
index 000000000000..4092aac0b7fe
--- /dev/null
+++ b/usr.bin/bluetooth/bthost/Makefile
@@ -0,0 +1,9 @@
+# $Id: Makefile,v 1.4 2003/08/14 20:07:13 max Exp $
+
+PACKAGE= bluetooth
+
+PROG= bthost
+
+LIBADD= bluetooth
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bluetooth/bthost/Makefile.depend b/usr.bin/bluetooth/bthost/Makefile.depend
new file mode 100644
index 000000000000..5d0531350f25
--- /dev/null
+++ b/usr.bin/bluetooth/bthost/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbluetooth \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bluetooth/bthost/bthost.1 b/usr.bin/bluetooth/bthost/bthost.1
new file mode 100644
index 000000000000..337a602e78cb
--- /dev/null
+++ b/usr.bin/bluetooth/bthost/bthost.1
@@ -0,0 +1,114 @@
+.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $Id: bthost.1,v 1.7 2003/05/21 22:19:00 max Exp $
+.\"
+.Dd May 8, 2003
+.Dt BTHOST 1
+.Os
+.Sh NAME
+.Nm bthost
+.Nd look up Bluetooth host names and Protocol Service Multiplexor values
+.Sh SYNOPSIS
+.Nm
+.Op Fl bhp
+.Ar host_or_protocol
+.Sh DESCRIPTION
+The
+.Nm
+utility looks for information about Bluetooth hosts and
+Protocol Service Multiplexor (PSM) values.
+It gets this information from the
+.Pa /etc/bluetooth/hosts
+and
+.Pa /etc/bluetooth/protocols
+files.
+.Pp
+In host mode, it simply converts between the host names and Bluetooth addresses.
+The argument can be either a host name or a Bluetooth address.
+The program first attempts to interpret it as a Bluetooth address.
+If this fails, it will treat it as a host name.
+A Bluetooth address consists of six hex bytes separated by a colon,
+e.g.,
+.Dq Li 01:02:03:04:05:06 .
+A host name consists of names separated by dots, e.g.,
+.Dq Li my.cell.phone .
+.Pp
+In protocol mode, it simply converts between the Protocol Service Multiplexor
+names and assigned numbers.
+The argument can be either a Protocol Service Multiplexor name or
+an assigned number.
+The program first attempts to interpret it as an assigned number.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b
+Produce brief output.
+.It Fl h
+Display usage message and exit.
+.It Fl p
+Activate protocol mode.
+.El
+.Pp
+The
+.Nm
+utility will print results to the standard output, and error messages to the
+standard error.
+An output can be quite different,
+here is an example that demonstrates all of the possibilities:
+.Bd -literal -offset indent
+% bthost localhost
+Host localhost has address FF:FF:FF:00:00:00
+% bthost ff:ff:ff:00:00:00
+Host FF:FF:FF:00:00:00 has name localhost
+% bthost -b localhost
+FF:FF:FF:00:00:00
+% bthost -b ff:ff:ff:00:00:00
+localhost
+% bthost do.not.exists
+do.not.exists: Unknown host
+% bthost 0:0:0:0:0:0
+00:00:00:00:00:00: Unknown host
+% bthost -p sdp
+Protocol/Service Multiplexor sdp has number 1
+% bthost -p 3
+Protocol/Service Multiplexor rfcomm has number 3
+% bthost -bp HID-Control
+17
+% bthost -p foo
+foo: Unknown Protocol/Service Multiplexor
+.Ed
+.Sh FILES
+.Bl -tag -width ".Pa /etc/bluetooth/hosts" -compact
+.It Pa /etc/bluetooth/hosts
+.It Pa /etc/bluetooth/protocols
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr bluetooth 3 ,
+.Xr bluetooth.hosts 5 ,
+.Xr bluetooth.protocols 5
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq Mt m_evmenkin@yahoo.com
diff --git a/usr.bin/bluetooth/bthost/bthost.c b/usr.bin/bluetooth/bthost/bthost.c
new file mode 100644
index 000000000000..23c81f985c53
--- /dev/null
+++ b/usr.bin/bluetooth/bthost/bthost.c
@@ -0,0 +1,144 @@
+/*-
+ * bthost.c
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id: bthost.c,v 1.5 2003/05/21 20:30:01 max Exp $
+ */
+
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int hostmode (char const *arg, int brief);
+static int protomode (char const *arg, int brief);
+static void usage (void);
+
+int
+main(int argc, char **argv)
+{
+ int opt, brief = 0, proto = 0;
+
+ while ((opt = getopt(argc, argv, "bhp")) != -1) {
+ switch (opt) {
+ case 'b':
+ brief = 1;
+ break;
+
+ case 'p':
+ proto = 1;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ /* NOT REACHED */
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ exit(proto? protomode(*argv, brief) : hostmode(*argv, brief));
+}
+
+static int
+hostmode(char const *arg, int brief)
+{
+ struct hostent *he = NULL;
+ bdaddr_t ba;
+ char bastr[32];
+ int reverse;
+
+ if (bt_aton(arg, &ba) == 1) {
+ reverse = 1;
+ he = bt_gethostbyaddr((char const *) &ba, sizeof(ba),
+ AF_BLUETOOTH);
+ } else {
+ reverse = 0;
+ he = bt_gethostbyname(arg);
+ }
+
+ if (he == NULL) {
+ herror(reverse? bt_ntoa(&ba, bastr) : arg);
+ return (1);
+ }
+
+ if (brief)
+ printf("%s", reverse? he->h_name :
+ bt_ntoa((bdaddr_t *)(he->h_addr), bastr));
+ else
+ printf("Host %s has %s %s\n",
+ reverse? bt_ntoa(&ba, bastr) : arg,
+ reverse? "name" : "address",
+ reverse? he->h_name :
+ bt_ntoa((bdaddr_t *)(he->h_addr), bastr));
+
+ return (0);
+}
+
+static int
+protomode(char const *arg, int brief)
+{
+ struct protoent *pe = NULL;
+ int proto;
+
+ if ((proto = atoi(arg)) != 0)
+ pe = bt_getprotobynumber(proto);
+ else
+ pe = bt_getprotobyname(arg);
+
+ if (pe == NULL) {
+ fprintf(stderr, "%s: Unknown Protocol/Service Multiplexor\n", arg);
+ return (1);
+ }
+
+ if (brief) {
+ if (proto)
+ printf("%s", pe->p_name);
+ else
+ printf("%d", pe->p_proto);
+ } else {
+ printf("Protocol/Service Multiplexor %s has number %d\n",
+ pe->p_name, pe->p_proto);
+ }
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stdout, "Usage: bthost [-b -h -p] host_or_protocol\n");
+ exit(255);
+}
+
diff --git a/usr.bin/bluetooth/btsockstat/Makefile b/usr.bin/bluetooth/btsockstat/Makefile
new file mode 100644
index 000000000000..399705862859
--- /dev/null
+++ b/usr.bin/bluetooth/btsockstat/Makefile
@@ -0,0 +1,11 @@
+# $Id: Makefile,v 1.7 2003/08/14 20:07:14 max Exp $
+
+PACKAGE= bluetooth
+PROG= btsockstat
+WARNS?= 2
+BINGRP= kmem
+BINMODE= 2555
+
+LIBADD= bluetooth kvm
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bluetooth/btsockstat/Makefile.depend b/usr.bin/bluetooth/btsockstat/Makefile.depend
new file mode 100644
index 000000000000..2de131f5333d
--- /dev/null
+++ b/usr.bin/bluetooth/btsockstat/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbluetooth \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libkvm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.1 b/usr.bin/bluetooth/btsockstat/btsockstat.1
new file mode 100644
index 000000000000..b1b8fdf6a776
--- /dev/null
+++ b/usr.bin/bluetooth/btsockstat/btsockstat.1
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $Id: btsockstat.1,v 1.6 2003/05/21 00:09:45 max Exp $
+.\"
+.Dd October 12, 2003
+.Dt BTSOCKSTAT 1
+.Os
+.Sh NAME
+.Nm btsockstat
+.Nd show Bluetooth sockets information
+.Sh SYNOPSIS
+.Nm
+.Op Fl nrh
+.Op Fl M Ar core
+.Op Fl p Ar protocol
+.Sh DESCRIPTION
+The
+.Nm
+utility symbolically displays the contents of various Bluetooth sockets
+related data structures.
+There are few output formats, depending on the
+options for the information presented.
+The
+.Nm
+utility
+will print results to the standard output and error messages to the
+standard error.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl h
+Display usage message and exit.
+.It Fl M Ar core
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl n
+Show Bluetooth addresses as numbers.
+Normally,
+.Nm
+attempts to resolve Bluetooth addresses, and display them symbolically.
+.It Fl p Ar protocol
+Display a list of active sockets (protocol control blocks) for each
+specified protocol.
+Supported protocols are:
+.Cm hci_raw , l2cap_raw , l2cap, rfcomm
+and
+.Cm rfcomm_s .
+.It Fl r
+Display a list of active routing entries (if any) for specified protocol.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr ng_btsocket 4
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq Mt m_evmenkin@yahoo.com
+.Sh BUGS
+Most likely.
+Please report if found.
diff --git a/usr.bin/bluetooth/btsockstat/btsockstat.c b/usr.bin/bluetooth/btsockstat/btsockstat.c
new file mode 100644
index 000000000000..99e972f515c7
--- /dev/null
+++ b/usr.bin/bluetooth/btsockstat/btsockstat.c
@@ -0,0 +1,641 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * btsockstat.c
+ *
+ * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/callout.h>
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#define _WANT_SOCKET
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <err.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+
+#include <netgraph/bluetooth/include/ng_bluetooth.h>
+#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h>
+#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
+#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void hcirawpr (kvm_t *kvmd, u_long addr);
+static void l2caprawpr (kvm_t *kvmd, u_long addr);
+static void l2cappr (kvm_t *kvmd, u_long addr);
+static void l2caprtpr (kvm_t *kvmd, u_long addr);
+static void rfcommpr (kvm_t *kvmd, u_long addr);
+static void rfcommpr_s (kvm_t *kvmd, u_long addr);
+
+static char * bdaddrpr (bdaddr_p const ba, char *str, int len);
+
+static kvm_t * kopen (char const *memf);
+static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size);
+
+static void usage (void);
+
+/*
+ * List of symbols
+ */
+
+static struct nlist nl[] = {
+#define N_HCI_RAW 0
+ { "_ng_btsocket_hci_raw_sockets" },
+#define N_L2CAP_RAW 1
+ { "_ng_btsocket_l2cap_raw_sockets" },
+#define N_L2CAP 2
+ { "_ng_btsocket_l2cap_sockets" },
+#define N_L2CAP_RAW_RT 3
+ { "_ng_btsocket_l2cap_raw_rt" },
+#define N_L2CAP_RT 4
+ { "_ng_btsocket_l2cap_rt" },
+#define N_RFCOMM 5
+ { "_ng_btsocket_rfcomm_sockets" },
+#define N_RFCOMM_S 6
+ { "_ng_btsocket_rfcomm_sessions" },
+ { "" },
+};
+
+#define state2str(x) \
+ (((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)])
+
+/*
+ * Main
+ */
+
+static int numeric_bdaddr = 0;
+
+int
+main(int argc, char *argv[])
+{
+ int opt, proto = -1, route = 0;
+ kvm_t *kvmd = NULL;
+ char *memf = NULL;
+
+ while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) {
+ switch (opt) {
+ case 'n':
+ numeric_bdaddr = 1;
+ break;
+
+ case 'M':
+ memf = optarg;
+ break;
+
+ case 'p':
+ if (strcasecmp(optarg, "hci_raw") == 0)
+ proto = N_HCI_RAW;
+ else if (strcasecmp(optarg, "l2cap_raw") == 0)
+ proto = N_L2CAP_RAW;
+ else if (strcasecmp(optarg, "l2cap") == 0)
+ proto = N_L2CAP;
+ else if (strcasecmp(optarg, "rfcomm") == 0)
+ proto = N_RFCOMM;
+ else if (strcasecmp(optarg, "rfcomm_s") == 0)
+ proto = N_RFCOMM_S;
+ else
+ usage();
+ /* NOT REACHED */
+ break;
+
+ case 'r':
+ route = 1;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ /* NOT REACHED */
+ }
+ }
+
+ if ((proto == N_HCI_RAW || proto == N_RFCOMM || proto == N_RFCOMM_S) && route)
+ usage();
+ /* NOT REACHED */
+
+ /*
+ * Discard setgid privileges if not the running kernel so that
+ * bad guys can't print interesting stuff from kernel memory.
+ */
+ if (memf != NULL)
+ if (setgid(getgid()) != 0)
+ err(1, "setgid");
+
+ kvmd = kopen(memf);
+ if (kvmd == NULL)
+ return (1);
+
+ switch (proto) {
+ case N_HCI_RAW:
+ hcirawpr(kvmd, nl[N_HCI_RAW].n_value);
+ break;
+
+ case N_L2CAP_RAW:
+ if (route)
+ l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);
+ else
+ l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);
+ break;
+
+ case N_L2CAP:
+ if (route)
+ l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);
+ else
+ l2cappr(kvmd, nl[N_L2CAP].n_value);
+ break;
+
+ case N_RFCOMM:
+ rfcommpr(kvmd, nl[N_RFCOMM].n_value);
+ break;
+
+ case N_RFCOMM_S:
+ rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);
+ break;
+
+ default:
+ if (route) {
+ l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);
+ l2caprtpr(kvmd, nl[N_L2CAP_RT].n_value);
+ } else {
+ hcirawpr(kvmd, nl[N_HCI_RAW].n_value);
+ l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);
+ l2cappr(kvmd, nl[N_L2CAP].n_value);
+ rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);
+ rfcommpr(kvmd, nl[N_RFCOMM].n_value);
+ }
+ break;
+ }
+
+ return (kvm_close(kvmd));
+} /* main */
+
+/*
+ * Print raw HCI sockets
+ */
+
+static void
+hcirawpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_hci_raw_pcb_p this = NULL, next = NULL;
+ ng_btsocket_hci_raw_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active raw HCI sockets\n" \
+"%-8.8s %-8.8s %-6.6s %-6.6s %-6.6s %-16.16s\n",
+ "Socket",
+ "PCB",
+ "Flags",
+ "Recv-Q",
+ "Send-Q",
+ "Local address");
+ }
+
+ if (pcb.addr.hci_node[0] == 0) {
+ pcb.addr.hci_node[0] = '*';
+ pcb.addr.hci_node[1] = 0;
+ }
+
+ fprintf(stdout,
+"%-8lx %-8lx %-6.6x %6d %6d %-16.16s\n",
+ (unsigned long) pcb.so,
+ (unsigned long) this,
+ pcb.flags,
+ so.so_rcv.sb_ccc,
+ so.so_snd.sb_ccc,
+ pcb.addr.hci_node);
+ }
+} /* hcirawpr */
+
+/*
+ * Print raw L2CAP sockets
+ */
+
+static void
+l2caprawpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_l2cap_raw_pcb_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_raw_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active raw L2CAP sockets\n" \
+"%-8.8s %-8.8s %-6.6s %-6.6s %-17.17s\n",
+ "Socket",
+ "PCB",
+ "Recv-Q",
+ "Send-Q",
+ "Local address");
+ }
+
+ fprintf(stdout,
+"%-8lx %-8lx %6d %6d %-17.17s\n",
+ (unsigned long) pcb.so,
+ (unsigned long) this,
+ so.so_rcv.sb_ccc,
+ so.so_snd.sb_ccc,
+ bdaddrpr(&pcb.src, NULL, 0));
+ }
+} /* l2caprawpr */
+
+/*
+ * Print L2CAP sockets
+ */
+
+static void
+l2cappr(kvm_t *kvmd, u_long addr)
+{
+ static char const * const states[] = {
+ /* NG_BTSOCKET_L2CAP_CLOSED */ "CLOSED",
+ /* NG_BTSOCKET_L2CAP_CONNECTING */ "CON",
+ /* NG_BTSOCKET_L2CAP_CONFIGURING */ "CONFIG",
+ /* NG_BTSOCKET_L2CAP_OPEN */ "OPEN",
+ /* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON"
+ };
+
+ ng_btsocket_l2cap_pcb_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+ char local[24], remote[24];
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active L2CAP sockets\n" \
+"%-8.8s %-6.6s %-6.6s %-23.23s %-17.17s %-5.5s %s\n",
+ "PCB",
+ "Recv-Q",
+ "Send-Q",
+ "Local address/PSM",
+ "Foreign address",
+ "CID",
+ "State");
+ }
+
+ fprintf(stdout,
+"%-8lx %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n",
+ (unsigned long) this,
+ so.so_rcv.sb_ccc,
+ so.so_snd.sb_ccc,
+ bdaddrpr(&pcb.src, local, sizeof(local)),
+ pcb.psm,
+ bdaddrpr(&pcb.dst, remote, sizeof(remote)),
+ pcb.cid,
+ (so.so_options & SO_ACCEPTCONN)?
+ "LISTEN" : state2str(pcb.state));
+ }
+} /* l2cappr */
+
+/*
+ * Print L2CAP routing table
+ */
+
+static void
+l2caprtpr(kvm_t *kvmd, u_long addr)
+{
+ ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL;
+ ng_btsocket_l2cap_rtentry_t rt;
+ int first = 1;
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &rt, sizeof(rt)) < 0)
+ return;
+
+ next = LIST_NEXT(&rt, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : "");
+ fprintf(stdout,
+"%-8.8s %-8.8s %-17.17s\n", "RTentry",
+ "Hook",
+ "BD_ADDR");
+ }
+
+ fprintf(stdout,
+"%-8lx %-8lx %-17.17s\n",
+ (unsigned long) this,
+ (unsigned long) rt.hook,
+ bdaddrpr(&rt.src, NULL, 0));
+ }
+} /* l2caprtpr */
+
+/*
+ * Print RFCOMM sockets
+ */
+
+static void
+rfcommpr(kvm_t *kvmd, u_long addr)
+{
+ static char const * const states[] = {
+ /* NG_BTSOCKET_RFCOMM_DLC_CLOSED */ "CLOSED",
+ /* NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT */ "W4CON",
+ /* NG_BTSOCKET_RFCOMM_DLC_CONFIGURING */ "CONFIG",
+ /* NG_BTSOCKET_RFCOMM_DLC_CONNECTING */ "CONN",
+ /* NG_BTSOCKET_RFCOMM_DLC_CONNECTED */ "OPEN",
+ /* NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING */ "DISCON"
+ };
+
+ ng_btsocket_rfcomm_pcb_p this = NULL, next = NULL;
+ ng_btsocket_rfcomm_pcb_t pcb;
+ struct socket so;
+ int first = 1;
+ char local[24], remote[24];
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
+ return;
+ if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&pcb, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active RFCOMM sockets\n" \
+"%-8.8s %-6.6s %-6.6s %-17.17s %-17.17s %-4.4s %-4.4s %s\n",
+ "PCB",
+ "Recv-Q",
+ "Send-Q",
+ "Local address",
+ "Foreign address",
+ "Chan",
+ "DLCI",
+ "State");
+ }
+
+ fprintf(stdout,
+"%-8lx %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n",
+ (unsigned long) this,
+ so.so_rcv.sb_ccc,
+ so.so_snd.sb_ccc,
+ bdaddrpr(&pcb.src, local, sizeof(local)),
+ bdaddrpr(&pcb.dst, remote, sizeof(remote)),
+ pcb.channel,
+ pcb.dlci,
+ (so.so_options & SO_ACCEPTCONN)?
+ "LISTEN" : state2str(pcb.state));
+ }
+} /* rfcommpr */
+
+/*
+ * Print RFCOMM sessions
+ */
+
+static void
+rfcommpr_s(kvm_t *kvmd, u_long addr)
+{
+ static char const * const states[] = {
+ /* NG_BTSOCKET_RFCOMM_SESSION_CLOSED */ "CLOSED",
+ /* NG_BTSOCKET_RFCOMM_SESSION_LISTENING */ "LISTEN",
+ /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTING */ "CONNECTING",
+ /* NG_BTSOCKET_RFCOMM_SESSION_CONNECTED */ "CONNECTED",
+ /* NG_BTSOCKET_RFCOMM_SESSION_OPEN */ "OPEN",
+ /* NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING */ "DISCONNECTING"
+ };
+
+ ng_btsocket_rfcomm_session_p this = NULL, next = NULL;
+ ng_btsocket_rfcomm_session_t s;
+ struct socket so;
+ int first = 1;
+
+ if (addr == 0)
+ return;
+
+ if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
+ return;
+
+ for ( ; this != NULL; this = next) {
+ if (kread(kvmd, (u_long) this, (char *) &s, sizeof(s)) < 0)
+ return;
+ if (kread(kvmd, (u_long) s.l2so, (char *) &so, sizeof(so)) < 0)
+ return;
+
+ next = LIST_NEXT(&s, next);
+
+ if (first) {
+ first = 0;
+ fprintf(stdout,
+"Active RFCOMM sessions\n" \
+"%-8.8s %-8.8s %-4.4s %-5.5s %-5.5s %-4.4s %s\n",
+ "L2PCB",
+ "PCB",
+ "Flags",
+ "MTU",
+ "Out-Q",
+ "DLCs",
+ "State");
+ }
+
+ fprintf(stdout,
+"%-8lx %-8lx %-4x %-5d %-5d %-4s %s\n",
+ (unsigned long) so.so_pcb,
+ (unsigned long) this,
+ s.flags,
+ s.mtu,
+ s.outq.len,
+ LIST_EMPTY(&s.dlcs)? "No" : "Yes",
+ state2str(s.state));
+ }
+} /* rfcommpr_s */
+
+/*
+ * Return BD_ADDR as string
+ */
+
+static char *
+bdaddrpr(bdaddr_p const ba, char *str, int len)
+{
+ static char buffer[MAXHOSTNAMELEN];
+ struct hostent *he = NULL;
+
+ if (str == NULL) {
+ str = buffer;
+ len = sizeof(buffer);
+ }
+
+ if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {
+ str[0] = '*';
+ str[1] = 0;
+
+ return (str);
+ }
+
+ if (!numeric_bdaddr &&
+ (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {
+ strlcpy(str, he->h_name, len);
+
+ return (str);
+ }
+
+ bt_ntoa(ba, str);
+
+ return (str);
+} /* bdaddrpr */
+
+/*
+ * Open kvm
+ */
+
+static kvm_t *
+kopen(char const *memf)
+{
+ kvm_t *kvmd = NULL;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ kvmd = kvm_openfiles(NULL, memf, NULL, O_RDONLY, errbuf);
+ if (setgid(getgid()) != 0)
+ err(1, "setgid");
+ if (kvmd == NULL) {
+ warnx("kvm_openfiles: %s", errbuf);
+ return (NULL);
+ }
+
+ if (kvm_nlist(kvmd, nl) < 0) {
+ warnx("kvm_nlist: %s", kvm_geterr(kvmd));
+ goto fail;
+ }
+
+ if (nl[0].n_type == 0) {
+ warnx("kvm_nlist: no namelist");
+ goto fail;
+ }
+
+ return (kvmd);
+fail:
+ kvm_close(kvmd);
+
+ return (NULL);
+} /* kopen */
+
+/*
+ * Read kvm
+ */
+
+static int
+kread(kvm_t *kvmd, u_long addr, char *buffer, int size)
+{
+ if (kvmd == NULL || buffer == NULL)
+ return (-1);
+
+ if (kvm_read(kvmd, addr, buffer, size) != size) {
+ warnx("kvm_read: %s", kvm_geterr(kvmd));
+ return (-1);
+ }
+
+ return (0);
+} /* kread */
+
+/*
+ * Print usage and exit
+ */
+
+static void
+usage(void)
+{
+ fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n");
+ exit(255);
+} /* usage */
+
diff --git a/usr.bin/bluetooth/rfcomm_sppd/Makefile b/usr.bin/bluetooth/rfcomm_sppd/Makefile
new file mode 100644
index 000000000000..465a56d77fd6
--- /dev/null
+++ b/usr.bin/bluetooth/rfcomm_sppd/Makefile
@@ -0,0 +1,10 @@
+# $Id: Makefile,v 1.7 2003/09/07 18:15:55 max Exp $
+
+PACKAGE= bluetooth
+PROG= rfcomm_sppd
+SRCS= rfcomm_sppd.c rfcomm_sdp.c
+WARNS?= 2
+
+LIBADD= bluetooth sdp util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bluetooth/rfcomm_sppd/Makefile.depend b/usr.bin/bluetooth/rfcomm_sppd/Makefile.depend
new file mode 100644
index 000000000000..8c9bfd44959f
--- /dev/null
+++ b/usr.bin/bluetooth/rfcomm_sppd/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbluetooth \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsdp \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c
new file mode 100644
index 000000000000..1506eeb30584
--- /dev/null
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c
@@ -0,0 +1,267 @@
+/*-
+ * rfcomm_sdp.c
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id: rfcomm_sdp.c,v 1.1 2003/09/07 18:15:55 max Exp $
+ */
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <errno.h>
+#include <sdp.h>
+#include <stdio.h>
+
+#undef PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE
+#define PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE 256
+
+#undef PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE
+#define PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE 12
+
+static int rfcomm_proto_list_parse (uint8_t const *start, uint8_t const *end,
+ int *channel, int *error);
+
+/*
+ * Lookup RFCOMM channel number in the Protocol Descriptor List
+ */
+
+#undef rfcomm_channel_lookup_exit
+#define rfcomm_channel_lookup_exit(e) { \
+ if (error != NULL) \
+ *error = (e); \
+ if (ss != NULL) { \
+ sdp_close(ss); \
+ ss = NULL; \
+ } \
+ return (((e) == 0)? 0 : -1); \
+}
+
+int
+rfcomm_channel_lookup(bdaddr_t const *local, bdaddr_t const *remote,
+ int service, int *channel, int *error)
+{
+ uint8_t buffer[PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE];
+ void *ss = NULL;
+ uint16_t serv = (uint16_t) service;
+ uint32_t attr = SDP_ATTR_RANGE(
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer };
+ uint32_t type, len;
+
+ if (local == NULL)
+ local = NG_HCI_BDADDR_ANY;
+ if (remote == NULL || channel == NULL)
+ rfcomm_channel_lookup_exit(EINVAL);
+
+ if ((ss = sdp_open(local, remote)) == NULL)
+ rfcomm_channel_lookup_exit(ENOMEM);
+ if (sdp_error(ss) != 0)
+ rfcomm_channel_lookup_exit(sdp_error(ss));
+
+ if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0)
+ rfcomm_channel_lookup_exit(sdp_error(ss));
+ if (proto.flags != SDP_ATTR_OK)
+ rfcomm_channel_lookup_exit(ENOATTR);
+
+ sdp_close(ss);
+ ss = NULL;
+
+ /*
+ * If it is possible for more than one kind of protocol stack to be
+ * used to gain access to the service, the ProtocolDescriptorList
+ * takes the form of a data element alternative. We always use the
+ * first protocol stack.
+ *
+ * A minimal Protocol Descriptor List for RFCOMM based service would
+ * look like
+ *
+ * seq8 len8 - 2 bytes
+ * seq8 len8 - 2 bytes
+ * uuid16 value16 - 3 bytes L2CAP
+ * seq8 len8 - 2 bytes
+ * uuid16 value16 - 3 bytes RFCOMM
+ * uint8 value8 - 2 bytes RFCOMM param #1
+ * =========
+ * 14 bytes
+ *
+ * Lets not count first [seq8 len8] wrapper, so the minimal size of
+ * the Protocol Descriptor List (the data we are actually interested
+ * in) for RFCOMM based service would be 12 bytes.
+ */
+
+ if (proto.vlen < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE)
+ rfcomm_channel_lookup_exit(EINVAL);
+
+ SDP_GET8(type, proto.value);
+
+ if (type == SDP_DATA_ALT8) {
+ SDP_GET8(len, proto.value);
+ } else if (type == SDP_DATA_ALT16) {
+ SDP_GET16(len, proto.value);
+ } else if (type == SDP_DATA_ALT32) {
+ SDP_GET32(len, proto.value);
+ } else
+ len = 0;
+
+ if (len > 0)
+ SDP_GET8(type, proto.value);
+
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, proto.value);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, proto.value);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, proto.value);
+ break;
+
+ default:
+ rfcomm_channel_lookup_exit(ENOATTR);
+ /* NOT REACHED */
+ }
+
+ if (len < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE)
+ rfcomm_channel_lookup_exit(EINVAL);
+
+ return (rfcomm_proto_list_parse(proto.value,
+ buffer + proto.vlen, channel, error));
+}
+
+/*
+ * Parse protocol descriptor list
+ *
+ * The ProtocolDescriptorList attribute describes one or more protocol
+ * stacks that may be used to gain access to the service described by
+ * the service record. If the ProtocolDescriptorList describes a single
+ * stack, it takes the form of a data element sequence in which each
+ * element of the sequence is a protocol descriptor.
+ */
+
+#undef rfcomm_proto_list_parse_exit
+#define rfcomm_proto_list_parse_exit(e) { \
+ if (error != NULL) \
+ *error = (e); \
+ return (((e) == 0)? 0 : -1); \
+}
+
+static int
+rfcomm_proto_list_parse(uint8_t const *start, uint8_t const *end,
+ int *channel, int *error)
+{
+ int type, len, value;
+
+ while (start < end) {
+
+ /*
+ * Parse protocol descriptor
+ *
+ * A protocol descriptor identifies a communications protocol
+ * and provides protocol specific parameters. A protocol
+ * descriptor is represented as a data element sequence. The
+ * first data element in the sequence must be the UUID that
+ * identifies the protocol. Additional data elements optionally
+ * provide protocol specific information, such as the L2CAP
+ * protocol/service multiplexer (PSM) and the RFCOMM server
+ * channel number (CN).
+ */
+
+ /* We must have at least one byte (type) */
+ if (end - start < 1)
+ rfcomm_proto_list_parse_exit(EINVAL)
+
+ SDP_GET8(type, start);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, start);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, start);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, start);
+ break;
+
+ default:
+ rfcomm_proto_list_parse_exit(ENOATTR)
+ /* NOT REACHED */
+ }
+
+ /* We must have at least 3 bytes (type + UUID16) */
+ if (end - start < 3)
+ rfcomm_proto_list_parse_exit(EINVAL);
+
+ /* Get protocol UUID */
+ SDP_GET8(type, start); len -= sizeof(uint8_t);
+ switch (type) {
+ case SDP_DATA_UUID16:
+ SDP_GET16(value, start); len -= sizeof(uint16_t);
+ if (value != SDP_UUID_PROTOCOL_RFCOMM)
+ goto next_protocol;
+ break;
+
+ case SDP_DATA_UUID32: /* XXX FIXME can we have 32-bit UUID */
+ case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */
+ default:
+ rfcomm_proto_list_parse_exit(ENOATTR);
+ /* NOT REACHED */
+ }
+
+ /*
+ * First protocol specific parameter for RFCOMM procotol must
+ * be uint8 that represents RFCOMM channel number. So we must
+ * have at least two bytes.
+ */
+
+ if (end - start < 2)
+ rfcomm_proto_list_parse_exit(EINVAL);
+
+ SDP_GET8(type, start);
+ if (type != SDP_DATA_UINT8)
+ rfcomm_proto_list_parse_exit(ENOATTR);
+
+ SDP_GET8(*channel, start);
+
+ rfcomm_proto_list_parse_exit(0);
+ /* NOT REACHED */
+next_protocol:
+ start += len;
+ }
+
+ /*
+ * If we got here then it means we could not find RFCOMM protocol
+ * descriptor, but the reply format was actually valid.
+ */
+
+ rfcomm_proto_list_parse_exit(ENOATTR);
+}
+
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
new file mode 100644
index 000000000000..bb80ea1ea03f
--- /dev/null
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
@@ -0,0 +1,185 @@
+.\" Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $Id: rfcomm_sppd.1,v 1.3 2003/09/07 18:15:55 max Exp $
+.\"
+.Dd April 21, 2008
+.Dt RFCOMM_SPPD 1
+.Os
+.Sh NAME
+.Nm rfcomm_sppd
+.Nd RFCOMM Serial Port Profile daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl bhtS
+.Fl a Ar address
+.Fl c Ar channel
+.Sh DESCRIPTION
+The
+.Nm
+utility is a Serial Port Profile daemon.
+It can operate in two modes: client and server.
+.Pp
+In client mode,
+.Nm
+opens RFCOMM connection to the specified
+.Ar address
+server and
+.Ar channel .
+Once connection is established, the
+.Nm
+utility provides access to the server's remote serial port via stdin/stdout
+or via
+.Xr pts 4
+interface if
+.Fl t
+option was specified.
+.Pp
+If the
+.Fl S
+option is specified,
+.Nm
+will operate in server mode and act as RFCOMM server,
+listening on
+.Dv ANY
+address and advertising a virtual serial port
+via the
+.Xr sdpd 8
+daemon.
+If
+.Fl t
+options was specified,
+the server side of the virtual serial port is attached to a pseudo-terminal.
+Otherwise the virtual serial port is attached to the stdin/stdout.
+.Nm
+should be run as root in order to communicate with
+.Xr sdpd 8
+in this case.
+.Pp
+The
+.Nm
+utility opens both master and slave pseudo terminals.
+This is done to ensure that RFCOMM connection stays open until
+.Nm
+is terminated.
+The data received from the master pseudo terminal are sent over
+the RFCOMM connection.
+The data received from the RFCOMM connection are written
+into master pseudo terminal.
+The application in its turn opens the slave pseudo
+terminal and operates on it just like it would operate over the standard serial
+port.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a Ar address
+In client mode,
+this required option specifies the address of the remote RFCOMM server.
+If this option is specified in server mode,
+.Nm
+will only accept connections from the
+.Tn Bluetooth
+device with address
+.Ar address .
+The address can be specified as BD_ADDR or name.
+If name was specified then
+.Nm
+utility will attempt to resolve the name via
+.Xr bt_gethostbyname 3 .
+.It Fl b
+Detach from the controlling terminal, i.e., run in background.
+.It Fl c Ar channel
+In both client and server mode,
+this option specifies the RFCOMM channel to connect to or listen on.
+In server mode,
+the channel should be a number between 1 and 30.
+If not specified,
+.Nm
+will try to bind to
+.Dq wildcard
+RFCOMM channel number.
+The actual RFCOMM channel will be obtained via
+.Xr getsockname 2
+call and will be used to register Serial Port service with
+.Xr sdpd 8 .
+In client mode,
+the channel could either be a number between 1 and 30 or a service name.
+Supported service names are:
+.Cm DUN
+(for DialUp Networking service),
+.Cm FAX
+(for Fax service),
+.Cm LAN
+(for LAN Access Using PPP service) and
+.Cm SP
+(for Serial Port service).
+If channel was not specified then
+.Nm
+utility will try to obtain RFCOMM channel for Serial Port service via Service
+Discovery Protocol from the server.
+.It Fl h
+Display usage message and exit.
+.It Fl S
+Server mode; see
+.Sx DESCRIPTION .
+.It Fl t
+Use slave pseudo tty.
+If not set stdin/stdout will be used.
+This option is required if
+.Fl b
+option was specified.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /dev/pts/[num]" -compact
+.It Pa /dev/pts/[num]
+slave pseudo terminals
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Dl "rfcomm_sppd -a 00:01:02:03:04:05 -c 1 -t"
+.Pp
+Will start the
+.Nm
+utility and open RFCOMM connection to the server at
+.Li 00:01:02:03:04:05
+and channel
+.Li 1 .
+Once the connection has been established, a
+.Xr pts 4
+can be used to talk to the remote serial port on the server.
+.Nm
+prints the name of the
+.Xr pts 4
+to use on stdout.
+.Sh SEE ALSO
+.Xr bluetooth 3 ,
+.Xr ng_btsocket 4 ,
+.Xr pts 4 ,
+.Xr rfcomm_pppd 8 ,
+.Xr sdpd 8
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq Mt m_evmenkin@yahoo.com
+.Sh BUGS
+Please report if found.
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
new file mode 100644
index 000000000000..15298920d3c7
--- /dev/null
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
@@ -0,0 +1,461 @@
+/*
+ * rfcomm_sppd.c
+ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $Id: rfcomm_sppd.c,v 1.4 2003/09/07 18:15:55 max Exp $
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <paths.h>
+#include <sdp.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <unistd.h>
+#include <libutil.h>
+
+#define SPPD_IDENT "rfcomm_sppd"
+#define SPPD_BUFFER_SIZE 1024
+#define max(a, b) (((a) > (b))? (a) : (b))
+
+int rfcomm_channel_lookup (bdaddr_t const *local,
+ bdaddr_t const *remote,
+ int service, int *channel, int *error);
+
+static int sppd_ttys_open (char **tty, int *amaster, int *aslave);
+static int sppd_read (int fd, char *buffer, int size);
+static int sppd_write (int fd, char *buffer, int size);
+static void sppd_sighandler (int s);
+static void usage (void);
+
+static int done; /* are we done? */
+
+/* Main */
+int
+main(int argc, char *argv[])
+{
+ struct sigaction sa;
+ struct sockaddr_rfcomm ra;
+ bdaddr_t addr;
+ int n, background, channel, service,
+ s, amaster, aslave, fd, doserver,
+ dopty;
+ fd_set rfd;
+ char *tty = NULL, *ep = NULL, buf[SPPD_BUFFER_SIZE];
+
+ memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr));
+ background = channel = 0;
+ service = SDP_SERVICE_CLASS_SERIAL_PORT;
+ doserver = 0;
+ dopty = 0;
+
+ /* Parse command line options */
+ while ((n = getopt(argc, argv, "a:bc:thS")) != -1) {
+ switch (n) {
+ case 'a': /* BDADDR */
+ if (!bt_aton(optarg, &addr)) {
+ struct hostent *he = NULL;
+
+ if ((he = bt_gethostbyname(optarg)) == NULL)
+ errx(1, "%s: %s", optarg, hstrerror(h_errno));
+
+ memcpy(&addr, he->h_addr, sizeof(addr));
+ }
+ break;
+
+ case 'c': /* RFCOMM channel */
+ channel = strtoul(optarg, &ep, 10);
+ if (*ep != '\0') {
+ channel = 0;
+ switch (tolower(optarg[0])) {
+ case 'd': /* DialUp Networking */
+ service = SDP_SERVICE_CLASS_DIALUP_NETWORKING;
+ break;
+
+ case 'f': /* Fax */
+ service = SDP_SERVICE_CLASS_FAX;
+ break;
+
+ case 'l': /* LAN */
+ service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP;
+ break;
+
+ case 's': /* Serial Port */
+ service = SDP_SERVICE_CLASS_SERIAL_PORT;
+ break;
+
+ default:
+ errx(1, "Unknown service name: %s",
+ optarg);
+ /* NOT REACHED */
+ }
+ }
+ break;
+
+ case 'b': /* Run in background */
+ background = 1;
+ break;
+
+ case 't': /* Open pseudo TTY */
+ dopty = 1;
+ break;
+
+ case 'S':
+ doserver = 1;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ /* NOT REACHED */
+ }
+ }
+
+ /* Check if we have everything we need */
+ if (!doserver && memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
+ usage();
+ /* NOT REACHED */
+
+ /* Set signal handlers */
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sppd_sighandler;
+
+ if (sigaction(SIGTERM, &sa, NULL) < 0)
+ err(1, "Could not sigaction(SIGTERM)");
+
+ if (sigaction(SIGHUP, &sa, NULL) < 0)
+ err(1, "Could not sigaction(SIGHUP)");
+
+ if (sigaction(SIGINT, &sa, NULL) < 0)
+ err(1, "Could not sigaction(SIGINT)");
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+
+ if (sigaction(SIGCHLD, &sa, NULL) < 0)
+ err(1, "Could not sigaction(SIGCHLD)");
+
+ /* Open TTYs */
+ if (dopty) {
+ if (sppd_ttys_open(&tty, &amaster, &aslave) < 0)
+ exit(1);
+
+ fd = amaster;
+ } else {
+ if (background)
+ usage();
+
+ amaster = STDIN_FILENO;
+ fd = STDOUT_FILENO;
+ }
+
+ /* Open RFCOMM connection */
+
+ if (doserver) {
+ struct sockaddr_rfcomm ma;
+ bdaddr_t bt_addr_any;
+ sdp_sp_profile_t sp;
+ void *ss;
+ uint32_t sdp_handle;
+ int acceptsock, aaddrlen;
+
+ acceptsock = socket(PF_BLUETOOTH, SOCK_STREAM,
+ BLUETOOTH_PROTO_RFCOMM);
+ if (acceptsock < 0)
+ err(1, "Could not create socket");
+
+ memcpy(&bt_addr_any, NG_HCI_BDADDR_ANY, sizeof(bt_addr_any));
+
+ memset(&ma, 0, sizeof(ma));
+ ma.rfcomm_len = sizeof(ma);
+ ma.rfcomm_family = AF_BLUETOOTH;
+ memcpy(&ma.rfcomm_bdaddr, &bt_addr_any, sizeof(bt_addr_any));
+ ma.rfcomm_channel = channel;
+
+ if (bind(acceptsock, (struct sockaddr *)&ma, sizeof(ma)) < 0)
+ err(1, "Could not bind socket on channel %d", channel);
+ if (listen(acceptsock, 10) != 0)
+ err(1, "Could not listen on socket");
+
+ aaddrlen = sizeof(ma);
+ if (getsockname(acceptsock, (struct sockaddr *)&ma, &aaddrlen) < 0)
+ err(1, "Could not get socket name");
+ channel = ma.rfcomm_channel;
+
+ ss = sdp_open_local(NULL);
+ if (ss == NULL)
+ errx(1, "Unable to create local SDP session");
+ if (sdp_error(ss) != 0)
+ errx(1, "Unable to open local SDP session. %s (%d)",
+ strerror(sdp_error(ss)), sdp_error(ss));
+ memset(&sp, 0, sizeof(sp));
+ sp.server_channel = channel;
+
+ if (sdp_register_service(ss, SDP_SERVICE_CLASS_SERIAL_PORT,
+ &bt_addr_any, (void *)&sp, sizeof(sp),
+ &sdp_handle) != 0) {
+ errx(1, "Unable to register LAN service with "
+ "local SDP daemon. %s (%d)",
+ strerror(sdp_error(ss)), sdp_error(ss));
+ }
+
+ s = -1;
+ while (s < 0) {
+ aaddrlen = sizeof(ra);
+ s = accept(acceptsock, (struct sockaddr *)&ra,
+ &aaddrlen);
+ if (s < 0)
+ err(1, "Unable to accept()");
+ if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) &&
+ memcmp(&addr, &ra.rfcomm_bdaddr, sizeof(addr))) {
+ warnx("Connect from wrong client");
+ close(s);
+ s = -1;
+ }
+ }
+ sdp_unregister_service(ss, sdp_handle);
+ sdp_close(ss);
+ close(acceptsock);
+ } else {
+ /* Check channel, if was not set then obtain it via SDP */
+ if (channel == 0 && service != 0)
+ if (rfcomm_channel_lookup(NULL, &addr,
+ service, &channel, &n) != 0)
+ errc(1, n, "Could not obtain RFCOMM channel");
+ if (channel <= 0 || channel > 30)
+ errx(1, "Invalid RFCOMM channel number %d", channel);
+
+ s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM);
+ if (s < 0)
+ err(1, "Could not create socket");
+
+ memset(&ra, 0, sizeof(ra));
+ ra.rfcomm_len = sizeof(ra);
+ ra.rfcomm_family = AF_BLUETOOTH;
+
+ if (bind(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
+ err(1, "Could not bind socket");
+
+ memcpy(&ra.rfcomm_bdaddr, &addr, sizeof(ra.rfcomm_bdaddr));
+ ra.rfcomm_channel = channel;
+
+ if (connect(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
+ err(1, "Could not connect socket");
+ }
+
+ /* Became daemon if required */
+ if (background && daemon(0, 0) < 0)
+ err(1, "Could not daemon()");
+
+ openlog(SPPD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "Starting on %s...", (tty != NULL)? tty : "stdin/stdout");
+
+ /* Print used tty on stdout for wrappers to pick up */
+ if (!background)
+ fprintf(stdout, "%s\n", tty);
+
+ for (done = 0; !done; ) {
+ FD_ZERO(&rfd);
+ FD_SET(amaster, &rfd);
+ FD_SET(s, &rfd);
+
+ n = select(max(amaster, s) + 1, &rfd, NULL, NULL, NULL);
+ if (n < 0) {
+ if (errno == EINTR)
+ continue;
+
+ syslog(LOG_ERR, "Could not select(). %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ if (n == 0)
+ continue;
+
+ if (FD_ISSET(amaster, &rfd)) {
+ n = sppd_read(amaster, buf, sizeof(buf));
+ if (n < 0) {
+ syslog(LOG_ERR, "Could not read master pty, " \
+ "fd=%d. %s", amaster, strerror(errno));
+ exit(1);
+ }
+
+ if (n == 0)
+ break; /* XXX */
+
+ if (sppd_write(s, buf, n) < 0) {
+ syslog(LOG_ERR, "Could not write to socket, " \
+ "fd=%d, size=%d. %s",
+ s, n, strerror(errno));
+ exit(1);
+ }
+ }
+
+ if (FD_ISSET(s, &rfd)) {
+ n = sppd_read(s, buf, sizeof(buf));
+ if (n < 0) {
+ syslog(LOG_ERR, "Could not read socket, " \
+ "fd=%d. %s", s, strerror(errno));
+ exit(1);
+ }
+
+ if (n == 0)
+ break;
+
+ if (sppd_write(fd, buf, n) < 0) {
+ syslog(LOG_ERR, "Could not write to master " \
+ "pty, fd=%d, size=%d. %s",
+ fd, n, strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ syslog(LOG_INFO, "Completed on %s", (tty != NULL)? tty : "stdin/stdout");
+ closelog();
+
+ close(s);
+
+ if (tty != NULL) {
+ close(aslave);
+ close(amaster);
+ }
+
+ return (0);
+}
+
+/* Open TTYs */
+static int
+sppd_ttys_open(char **tty, int *amaster, int *aslave)
+{
+ char pty[PATH_MAX];
+ struct termios tio;
+
+ cfmakeraw(&tio);
+
+ if (openpty(amaster, aslave, pty, &tio, NULL) == -1) {
+ syslog(LOG_ERR, "Could not openpty(). %s", strerror(errno));
+ return (-1);
+ }
+
+ if ((*tty = strdup(pty)) == NULL) {
+ syslog(LOG_ERR, "Could not strdup(). %s", strerror(errno));
+ close(*aslave);
+ close(*amaster);
+ return (-1);
+ }
+
+ return (0);
+} /* sppd_ttys_open */
+
+/* Read data */
+static int
+sppd_read(int fd, char *buffer, int size)
+{
+ int n;
+
+again:
+ n = read(fd, buffer, size);
+ if (n < 0) {
+ if (errno == EINTR)
+ goto again;
+
+ return (-1);
+ }
+
+ return (n);
+} /* sppd_read */
+
+/* Write data */
+static int
+sppd_write(int fd, char *buffer, int size)
+{
+ int n, wrote;
+
+ for (wrote = 0; size > 0; ) {
+ n = write(fd, buffer, size);
+ switch (n) {
+ case -1:
+ if (errno != EINTR)
+ return (-1);
+ break;
+
+ case 0:
+ /* XXX can happen? */
+ break;
+
+ default:
+ wrote += n;
+ buffer += n;
+ size -= n;
+ break;
+ }
+ }
+
+ return (wrote);
+} /* sppd_write */
+
+/* Signal handler */
+static void
+sppd_sighandler(int s)
+{
+ syslog(LOG_INFO, "Signal %d received. Total %d signals received\n",
+ s, ++ done);
+} /* sppd_sighandler */
+
+/* Display usage and exit */
+static void
+usage(void)
+{
+ fprintf(stdout,
+"Usage: %s options\n" \
+"Where options are:\n" \
+"\t-a address Peer address (required in client mode)\n" \
+"\t-b Run in background\n" \
+"\t-c channel RFCOMM channel to connect to or listen on\n" \
+"\t-t use slave pseudo tty (required in background mode)\n" \
+"\t-S Server mode\n" \
+"\t-h Display this message\n", SPPD_IDENT);
+ exit(255);
+} /* usage */
+
diff --git a/usr.bin/bmake/Makefile b/usr.bin/bmake/Makefile
new file mode 100644
index 000000000000..a8bcdfd9f859
--- /dev/null
+++ b/usr.bin/bmake/Makefile
@@ -0,0 +1,203 @@
+# This is a generated file, do NOT edit!
+# See contrib/bmake/bsd.after-import.mk
+#
+
+SRCTOP?= ${.CURDIR:H:H}
+
+# look here first for config.h
+CFLAGS+= -I${.CURDIR}
+
+# for after-import
+CLEANDIRS+= FreeBSD
+CLEANFILES+= bootstrap
+
+# $Id: Makefile,v 1.133 2025/03/08 20:12:56 sjg Exp $
+
+PROG?= ${.CURDIR:T}
+
+SRCS= \
+ arch.c \
+ buf.c \
+ compat.c \
+ cond.c \
+ dir.c \
+ for.c \
+ hash.c \
+ job.c \
+ lst.c \
+ main.c \
+ make.c \
+ make_malloc.c \
+ meta.c \
+ metachar.c \
+ parse.c \
+ str.c \
+ suff.c \
+ targ.c \
+ trace.c \
+ util.c \
+ var.c
+
+.MAIN: all
+
+MAN= ${PROG}.1
+SRCS.${MAN}= ${srcdir}/make.1
+
+.-include "Makefile.inc"
+
+# this file gets generated by configure
+.-include "Makefile.config"
+
+.if !empty(LIBOBJS)
+SRCS+= ${LIBOBJS:T:.o=.c}
+.endif
+
+# just in case
+prefix?= /usr
+srcdir?= ${.PARSEDIR}
+srcdir:= ${srcdir}
+
+DEFAULT_SYS_PATH?= ${prefix}/share/mk
+
+CPPFLAGS+= -DUSE_META
+CFLAGS+= ${CPPFLAGS}
+CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
+CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
+CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
+COPTS.main.c+= "-DMAKE_VERSION=\"${_MAKE_VERSION}\""
+
+.for x in FORCE_MAKE_OS FORCE_MACHINE FORCE_MACHINE_ARCH
+.ifdef $x
+COPTS.main.c+= "-D$x=\"${$x}\""
+.endif
+.endfor
+
+# meta mode can be useful even without filemon
+# should be set by now
+USE_FILEMON?= no
+.if ${USE_FILEMON:tl} != "no"
+.PATH: ${srcdir}/filemon
+SRCS+= filemon_${USE_FILEMON}.c
+COPTS.meta.c+= -DUSE_FILEMON -DUSE_FILEMON_${USE_FILEMON:tu}
+COPTS.job.c+= ${COPTS.meta.c}
+
+.if ${USE_FILEMON} == "dev"
+FILEMON_H?= /usr/include/dev/filemon/filemon.h
+.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
+COPTS.filemon_dev.c+= -DHAVE_FILEMON_H -I${FILEMON_H:H}
+.endif
+.elif ${USE_FILEMON} == "ktrace"
+COPTS.filemon_ktrace.c+= -Wno-error=unused-parameter
+.endif
+
+.endif # USE_FILEMON
+
+.PATH: ${srcdir}
+
+
+.if make(obj) || make(clean)
+SUBDIR.${MK_TESTS}+= unit-tests
+.endif
+
+MAN1= ${MAN}
+
+.if ${MK_GEN_MAN:Uno} == "yes"
+
+# we use this to generate ${MAN}
+.include <${srcdir}/mk/genfiles.mk>
+
+.if ${PROG} != "make"
+CLEANFILES+= my.history
+SED_CMDS.${MAN}+= \
+ -e '/^.Dt/s/MAKE/${PROG:tu}/' \
+ -e '/^.Nm/s/make/${PROG}/' \
+
+.endif
+
+.if ${CLEANFILES:U:Mmy.history} != ""
+${MAN}: my.history
+my.history:
+ @(echo ".Nm"; \
+ echo "is derived from NetBSD"; \
+ echo ".Xr make 1 ."; \
+ echo "It uses autoconf to facilitate portability to other platforms."; \
+ echo ".Pp") > $@
+
+SED_CMDS.${MAN}+= \
+ -e '/^.Sh HISTORY/rmy.history' \
+ -e '/^.Sh HISTORY/,/BUGS/s,^.Nm,make,' \
+
+.endif
+
+.if ${.MAKE.OS:N*BSD} != ""
+# assume .Nx is not supported
+SED_CMDS.${MAN}+= -e 's/^\.Nx/NetBSD/'
+.endif
+
+# watch out for a late change of PROG
+.if !empty(SRCS.${MAN})
+.NOPATH: ${MAN}
+${MAN}: ${SRCS.${MAN}} _GENFILES_USE
+
+all man beforeinstall: ${MAN}
+_mfromdir= .
+.endif
+.endif # MK_GEN_MAN
+
+MANTARGET?= cat
+MANDEST?= ${MANDIR}/${MANTARGET}1
+
+.if ${MANTARGET} == "cat"
+_mfromdir= ${srcdir}
+.endif
+
+.include <bsd.prog.mk>
+
+CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H
+COPTS.var.c+= -Wno-cast-qual
+COPTS.job.c+= -Wno-format-nonliteral
+COPTS.parse.c+= -Wno-format-nonliteral
+COPTS.var.c+= -Wno-format-nonliteral
+
+# Force these
+SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share}
+BINDIR= ${BINDIR.bmake:U${prefix}/bin}
+MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
+
+${OBJS}: config.h
+
+
+# A simple unit-test driver to help catch regressions
+TEST_MAKE?= ${.OBJDIR}/${PROG:T}
+accept test: .NOMETA
+ cd ${.CURDIR}/unit-tests && \
+ MAKEFLAGS= ${TEST_MAKE} -r -m / ${.TARGET} ${TESTS:DTESTS=${TESTS:Q}}
+
+
+.if make(test) && ${MK_AUTO_OBJ} == "yes"
+# The test target above visits unit-tests with -r -m /
+# which prevents MK_AUTO_OBJ doing its job
+# so do it here
+.if defined(MAKEOBJDIRPREFIX) || ${MAKEOBJDIR:U:M*/*} != ""
+_utobj= ${.OBJDIR}/unit-tests
+.else
+_utobj= ${.CURDIR}/unit-tests/${MAKEOBJDIR:Uobj}
+.endif
+utobj: .NOMETA
+ @test -d ${_utobj} && exit 0; \
+ echo "[Creating ${_utobj}...]"; \
+ umask ${OBJDIR_UMASK:U002}; \
+ mkdir -p ${_utobj}
+test: utobj
+.endif
+
+# override some simple things
+BINDIR= /usr/bin
+MANDIR= /usr/share/man/man
+
+# make sure we get this
+CFLAGS+= ${COPTS.${.IMPSRC:T}}
+
+after-import: ${SRCTOP}/contrib/bmake/bsd.after-import.mk
+ cd ${.CURDIR} && ${.MAKE} -f ${SRCTOP}/contrib/bmake/bsd.after-import.mk
+
diff --git a/usr.bin/bmake/Makefile.config b/usr.bin/bmake/Makefile.config
new file mode 100644
index 000000000000..a5e81a13cd0a
--- /dev/null
+++ b/usr.bin/bmake/Makefile.config
@@ -0,0 +1,28 @@
+# This is a generated file, do NOT edit!
+# See contrib/bmake/bsd.after-import.mk
+#
+
+SRCTOP?= ${.CURDIR:H:H}
+
+# things set by configure
+
+_MAKE_VERSION?=20250308
+
+prefix?= /usr
+srcdir= ${SRCTOP}/contrib/bmake
+CC?= cc
+MAKE_OS?=
+DEFAULT_SYS_PATH?= .../share/mk:/usr/share/mk
+
+EGREP= egrep
+CPPFLAGS+=
+CFLAGS+= ${CPPFLAGS} -DHAVE_CONFIG_H
+LDFLAGS+=
+LIBOBJS+= ${LIBOBJDIR}stresep$U.o
+LDADD+=
+USE_META?= yes
+USE_FILEMON?= dev
+FILEMON_H?= /usr/include/dev/filemon/filemon.h
+BMAKE_PATH_MAX?= 1024
+# used if MAXPATHLEN not defined
+CPPFLAGS+= -DBMAKE_PATH_MAX=${BMAKE_PATH_MAX}
diff --git a/usr.bin/bmake/Makefile.depend b/usr.bin/bmake/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/bmake/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/Makefile.inc b/usr.bin/bmake/Makefile.inc
new file mode 100644
index 000000000000..5140bd18bb37
--- /dev/null
+++ b/usr.bin/bmake/Makefile.inc
@@ -0,0 +1,37 @@
+# we do not need this
+MK_host_egacy= no
+
+.sinclude <src.opts.mk>
+
+.if defined(.PARSEDIR)
+# make sure this is available to unit-tests/Makefile
+.export SRCTOP
+.endif
+
+.if exists(${.CURDIR}/tests)
+PROG= make
+.if ${PROGNAME:U} != "bmake"
+LINKS= ${BINDIR}/make ${BINDIR}/bmake
+MLINKS= ${MAN} b${MAN}
+.endif
+.endif
+
+# hack to not add tests to tests subdir since this is included from
+# there and to avoid renaming things that require changes to generated
+# files.
+.if defined(MK_TESTS) && ${MK_TESTS} != no && exists(${.CURDIR}/tests)
+SUBDIR+= tests
+.endif
+
+WARNS?=3
+CFLAGS+= -DNO_PWD_OVERRIDE
+
+.if make(after-import)
+# use our preferred value
+DEFAULT_SYS_PATH= .../share/mk:/usr/share/mk
+.export DEFAULT_SYS_PATH
+.endif
+
+.if ${MACHINE} != "host"
+FILEMON_H ?= ${SRCTOP}/sys/dev/filemon/filemon.h
+.endif
diff --git a/usr.bin/bmake/config.h b/usr.bin/bmake/config.h
new file mode 100644
index 000000000000..33aed8f160c8
--- /dev/null
+++ b/usr.bin/bmake/config.h
@@ -0,0 +1,449 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Path of default shell */
+/* #undef DEFSHELL_CUSTOM */
+
+/* Shell spec to use by default */
+/* #undef DEFSHELL_INDEX */
+
+/* Path of default shell */
+/* #undef DEFSHELL_PATH */
+
+/* Define to 1 if you have the <ar.h> header file. */
+#define HAVE_AR_H 1
+
+/* Define to 1 if you have the declaration of 'sys_siglist', and to 0 if you
+ don't. */
+#define HAVE_DECL_SYS_SIGLIST 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines 'DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the 'dirname' function. */
+#define HAVE_DIRNAME 1
+
+/* Define to 1 if you don't have 'vprintf' but do have '_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the 'err' function. */
+#define HAVE_ERR 1
+
+/* Define to 1 if you have the 'errx' function. */
+#define HAVE_ERRX 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the 'fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the 'getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the 'getenv' function. */
+#define HAVE_GETENV 1
+
+/* Define to 1 if you have the 'getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the 'getwd' function. */
+#define HAVE_GETWD 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the 'killpg' function. */
+#define HAVE_KILLPG 1
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if the system has the type 'long long int'. */
+#define HAVE_LONG_LONG_INT 1
+
+/* Define to 1 if you have the <minix/config.h> header file. */
+/* #undef HAVE_MINIX_CONFIG_H */
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines 'DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the 'putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <ranlib.h> header file. */
+#define HAVE_RANLIB_H 1
+
+/* Define to 1 if you have the 'realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the 'select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the 'setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the 'setpgid' function. */
+#define HAVE_SETPGID 1
+
+/* Define to 1 if you have the 'setrlimit' function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define to 1 if you have the 'setsid' function. */
+#define HAVE_SETSID 1
+
+/* Define to 1 if you have the 'sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the 'sigaddset' function. */
+#define HAVE_SIGADDSET 1
+
+/* Define to 1 if you have the 'sigpending' function. */
+#define HAVE_SIGPENDING 1
+
+/* Define to 1 if you have the 'sigprocmask' function. */
+#define HAVE_SIGPROCMASK 1
+
+/* Define to 1 if you have the 'sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if you have the 'sigsuspend' function. */
+#define HAVE_SIGSUSPEND 1
+
+/* Define to 1 if you have the 'sigvec' function. */
+#define HAVE_SIGVEC 1
+
+/* Define to 1 if the system has the type 'sig_atomic_t'. */
+#define HAVE_SIG_ATOMIC_T 1
+
+/* Define to 1 if you have the 'snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the 'strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the 'stresep' function. */
+/* #undef HAVE_STRESEP */
+
+/* Define to 1 if you have the 'strftime' function. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the 'strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the 'strsep' function. */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if you have the 'strtod' function. */
+#define HAVE_STRTOD 1
+
+/* Define to 1 if you have the 'strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the 'strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the 'strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the 'sysctl' function. */
+#define HAVE_SYSCTL 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines 'DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines 'DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the 'unsetenv' function. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if the system has the type 'unsigned long long int'. */
+#define HAVE_UNSIGNED_LONG_LONG_INT 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the 'vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the 'vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the 'vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the 'wait3' function. */
+#define HAVE_WAIT3 1
+
+/* Define to 1 if you have the 'wait4' function. */
+#define HAVE_WAIT4 1
+
+/* Define to 1 if you have the 'waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if you have the 'warn' function. */
+#define HAVE_WARN 1
+
+/* Define to 1 if you have the 'warnx' function. */
+#define HAVE_WARNX 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if 'fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if 'vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "sjg@NetBSD.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "bmake"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "bmake 20240711"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "bmake"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "20240711"
+
+/* Define to 1 if the 'S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your <sys/time.h> declares 'struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Enable extensions on AIX, Interix, z/OS. */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable general extensions on macOS. */
+#ifndef _DARWIN_C_SOURCE
+# define _DARWIN_C_SOURCE 1
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable X/Open compliant socket functions that do not require linking
+ with -lxnet on HP-UX 11.11. */
+#ifndef _HPUX_ALT_XOPEN_SOCKET_API
+# define _HPUX_ALT_XOPEN_SOCKET_API 1
+#endif
+/* Identify the host operating system as Minix.
+ This macro does not affect the system headers' behavior.
+ A future release of Autoconf may stop defining this macro. */
+#ifndef _MINIX
+/* # undef _MINIX */
+#endif
+/* Enable general extensions on NetBSD.
+ Enable NetBSD compatibility extensions on Minix. */
+#ifndef _NETBSD_SOURCE
+# define _NETBSD_SOURCE 1
+#endif
+/* Enable OpenBSD compatibility extensions on NetBSD.
+ Oddly enough, this does nothing on OpenBSD. */
+#ifndef _OPENBSD_SOURCE
+# define _OPENBSD_SOURCE 1
+#endif
+/* Define to 1 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_SOURCE
+/* # undef _POSIX_SOURCE */
+#endif
+/* Define to 2 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_1_SOURCE
+/* # undef _POSIX_1_SOURCE */
+#endif
+/* Enable POSIX-compatible threading on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
+#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
+#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+# define __STDC_WANT_IEC_60559_BFP_EXT__ 1
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
+#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
+# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
+#endif
+/* Enable extensions specified by C23 Annex F. */
+#ifndef __STDC_WANT_IEC_60559_EXT__
+# define __STDC_WANT_IEC_60559_EXT__ 1
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
+#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
+# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
+#endif
+/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
+#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
+# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
+#endif
+/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
+#ifndef __STDC_WANT_LIB_EXT2__
+# define __STDC_WANT_LIB_EXT2__ 1
+#endif
+/* Enable extensions specified by ISO/IEC 24747:2009. */
+#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
+# define __STDC_WANT_MATH_SPEC_FUNCS__ 1
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable X/Open extensions. Define to 500 only if necessary
+ to make mbstate_t available. */
+#ifndef _XOPEN_SOURCE
+/* # undef _XOPEN_SOURCE */
+#endif
+
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* C99 function name */
+/* #undef __func__ */
+
+/* Define to empty if 'const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to '__inline__' or '__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int64_t */
+
+/* Define to 'int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to 'long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define as a signed integer type capable of holding a process identifier. */
+/* #undef pid_t */
+
+/* type that signal handlers can safely frob */
+/* #undef sig_atomic_t */
+
+/* Define as 'unsigned int' if <stddef.h> doesn't define. */
+/* #undef size_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define as 'fork' if 'vfork' does not work. */
+/* #undef vfork */
diff --git a/usr.bin/bmake/tests/Makefile b/usr.bin/bmake/tests/Makefile
new file mode 100644
index 000000000000..4dabc8879b4e
--- /dev/null
+++ b/usr.bin/bmake/tests/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+${PACKAGE}FILES+= common.sh
+${PACKAGE}FILES+= test-new.mk
+
+TESTS_SUBDIRS= archives
+TESTS_SUBDIRS+= basic
+TESTS_SUBDIRS+= execution
+TESTS_SUBDIRS+= shell
+TESTS_SUBDIRS+= suffixes
+TESTS_SUBDIRS+= syntax
+TESTS_SUBDIRS+= sysmk
+TESTS_SUBDIRS+= variables
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/Makefile.depend b/usr.bin/bmake/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/Makefile.inc b/usr.bin/bmake/tests/Makefile.inc
new file mode 100644
index 000000000000..eb3565f76d52
--- /dev/null
+++ b/usr.bin/bmake/tests/Makefile.inc
@@ -0,0 +1 @@
+SUBDIR_PARALLEL= t
diff --git a/usr.bin/bmake/tests/README b/usr.bin/bmake/tests/README
new file mode 100644
index 000000000000..d71e265d18b7
--- /dev/null
+++ b/usr.bin/bmake/tests/README
@@ -0,0 +1,173 @@
+
+This directory contains regression tests for make(1).
+
+To invoke the tests, please refer to tests(7).
+
+----------------------------------------------------------------------------
+
+The rest of this file is intended for developers.
+
+The tests are invoked via the test.sh script or prove(1) from p5-Test-Harness.
+Tests are normally executed in a special test directory that is built under
+/tmp. The reason for this is, that make tests are generally influenced by
+all file in a directory, by files in one of make's obscure object directories
+as well as in other directories make happens to look into. Therefor the
+test scripts build a clean environment in the temp directory and the
+tests are executed by cd-ing into that directory and invoking make. The
+output of the make run (standard output, standard error and the exit status)
+are written into files that are created in another directory. So the layout
+for the shell/builtin test looks like:
+
+ ./shell/builtin/ - directory with test stuff
+ /tmp/make.${USER}/shell/builtin - actual test directory
+ /tmp/make.${USER}/shell/builtin.OUTPUT - output files
+
+So a full test consists of the following steps:
+
+ setup - Set up the test environment by creating the test directory
+ and populating it with the needed files. If the test
+ directory already exists an error is printed.
+
+ run - Run the test and produce the output into the output
+ directory.
+
+ show - Show the result files on the screen.
+
+ compare - Compare the results in the output directory with those
+ in the test source directory. This just prints whether
+ the test was ok or not in the format used by prove(1).
+
+ diff - Diff the output files and the expected output files.
+
+ reset - Reset the test to its initial state.
+
+ clean - Remove both the test directory and the output directory.
+
+Each of these steps can independently be invoked with the test script
+contained in each directory. These test scripts are called test.t.
+Additionally the scripts understand the following commands:
+
+ test - Run setup, run and compare.
+
+ prove - Run setup, run, compare and clean. This is identically
+ to invoking the script without an argument.
+
+ desc - Print a short test description.
+
+ update - Update the expected results from the actual results.
+
+The test script has the following syntax:
+
+ % test.t [-v] [-m path_to_make_binary] command
+
+To invoke it via prove(1) use:
+
+ % [MAKE_PROG=path_to_make_binary] prove [options] [files/directories]
+
+Example:
+ % sh test.t -m `pwd`/../obj/make run
+ % MAKE_PROG=/usr/obj/usr/src/usr.bin/make/make prove -r
+
+The test scripts use the following environment variables that can be set
+by the user in the test script's environment:
+
+ WORK_BASE
+ - Base directory for working files. If not set
+ /tmp/make.${USER} is used.
+
+ MAKE_PROG
+ - Path to the make program to test. If not set
+ /usr/bin/make is used.
+
+The following variables are available to test scripts:
+
+ SRC_BASE
+ - test source base directory. This is determined by
+ repeatedly doing cd .. and checking for common.sh.
+ Therefor this can fail if a test source directory is
+ actually a symbolic link and is physically not located
+ below the directory containing common.sh.
+
+ SUBDIR
+ - subdirectory below WORK_BASE and SRC_BASE for current test
+
+ WORK_DIR
+ - ${WORK_BASE}/${SUBDIR}
+
+ SRC_DIR
+ - ${SRC_BASE}/${SUBDIR}
+
+The following variables and functions may be defined by the test script.
+This also lists special filenames.
+
+ DESC
+ A one-line description of the test.
+
+ TEST_MAKE_DIRS
+ A list of pairs of directory names and modes. These
+ directories are created during setup and reset. When
+ the directory already exists (during reset) only the
+ mode change is applied.
+
+ TEST_MAKE_DIRS="subdir 775 subdir/sub 555"
+
+ TEST_COPY_FILES
+ A list of pairs of file names and modes. These files
+ are copied from the source to the working directory
+ during setup and reset. When the file already exists
+ (during reset) only the mode change is applied. Files
+ may be copied from/to sub-directories. The sub-directory
+ in the working directory must already exists (see
+ TEST_MAKE_DIRS).
+
+ TEST_COPY_FILES="libtest.a 444 subdir/libfoo.a 444"
+
+ TEST_TOUCH
+ List of pairs of file names and arguments to touch(1).
+ During setup and reset for each list element touch(1)
+ is executed.
+
+ TEST_TOUCH="file1 '-t 200501011257'"
+
+ TEST_LINK
+ List of pairs of filenames. Each pair is passed to ln(1).
+ All names are prefixed with the working directory.
+
+ Makefile
+ If a file with this name exists in the source directory
+ it is automatically copied to the working directory.
+
+ setup_test()
+ If this function exists it is executed at the end of the
+ setup.
+
+ reset_test()
+ If this function exists it is executed at the end of the
+ reset.
+
+ TEST_CLEAN_FILES
+ A list of file to be deleted when resetting.
+
+ TEST_N
+ Number of tests in this script. If not set this is assumed
+ to be 1.
+
+ TEST_<number>
+ Arguments to make for test number <number>. If not set
+ the default argument of test<number> is used. To run a test
+ without argument to make, set TEST_<number> to the empty string.
+
+ TEST_<number>_SKIP
+ To skip a test (for whatever reason) this should be set
+ to a string explaining the reason for skipping the test.
+
+ TEST_<number>_TODO
+ For a test that should fail this is a short string describing
+ what the problem in make(1) is that should be fixed.
+
+ run_test()
+ Function to run a test. This function gets a single argument
+ which is the number of the test to executed. The default
+ function evaluates the variable TEST_<number> and calls
+ make with the arguments in this variable.
+
diff --git a/usr.bin/bmake/tests/archives/Makefile b/usr.bin/bmake/tests/archives/Makefile
new file mode 100644
index 000000000000..01437afa8c3c
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/archives
+
+TESTS_SUBDIRS= fmt_44bsd fmt_44bsd_mod fmt_oldbsd
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/archives/Makefile.depend b/usr.bin/bmake/tests/archives/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile
new file mode 100644
index 000000000000..7afea8dd044b
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile
@@ -0,0 +1,31 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/archives/fmt_44bsd
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.status.3
+${PACKAGE}FILES+= expected.status.4
+${PACKAGE}FILES+= expected.status.5
+${PACKAGE}FILES+= expected.status.6
+${PACKAGE}FILES+= expected.status.7
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stderr.3
+${PACKAGE}FILES+= expected.stderr.4
+${PACKAGE}FILES+= expected.stderr.5
+${PACKAGE}FILES+= expected.stderr.6
+${PACKAGE}FILES+= expected.stderr.7
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= expected.stdout.3
+${PACKAGE}FILES+= expected.stdout.4
+${PACKAGE}FILES+= expected.stdout.5
+${PACKAGE}FILES+= expected.stdout.6
+${PACKAGE}FILES+= expected.stdout.7
+${PACKAGE}FILES+= libtest.a
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.depend b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.test b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.test
new file mode 100644
index 000000000000..99f9d504463c
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/Makefile.test
@@ -0,0 +1,60 @@
+# This test checks the code reading archive files. The archive file
+# is a BSD4.4 file with __.SYMTAB and #1/N long file names.
+
+#############################################################################
+
+# should be ok
+test1: libtest.a(short.o)
+ @:
+
+libtest.a(short.o): ood
+ @:
+
+#############################################################################
+
+# should be ok
+test2: libtest.a(exactly15char.o)
+ @:
+
+libtest.a(exactly15char.o): ood
+ @:
+
+#############################################################################
+
+# should be ok
+test3: libtest.a(exactly16chars.o)
+ @:
+
+libtest.a(exactly16chars.o): ood
+ @:
+
+#############################################################################
+
+# should be ok
+test4: libtest.a(verylongobjectname.o)
+ @:
+
+libtest.a(verylongobjectname.o): ood
+ @:
+
+#############################################################################
+
+# Truncated to 16 characters
+# should fail
+test5: libtest.a(verylongobjectna)
+ @:
+
+#############################################################################
+
+# Truncated to 15 characters
+# should fail
+test6: libtest.a(verylongobjectn)
+ @:
+
+#############################################################################
+
+# should fail
+test7: libtest.a(\#1/20)
+ @:
+
+ood:
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.1 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.2 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.3 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.3
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.3
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.4 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.4
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.4
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.5 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.5
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.5
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.6 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.6
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.6
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.7 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.7
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.status.7
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.1 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.1
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.2 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.3 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.3
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.4 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.4
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.5 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.5
new file mode 100644
index 000000000000..7b91643a3821
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.5
@@ -0,0 +1 @@
+make: don't know how to make verylongobjectna. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.6 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.6
new file mode 100644
index 000000000000..fd1519039acc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.6
@@ -0,0 +1 @@
+make: don't know how to make verylongobjectn. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.7 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.7
new file mode 100644
index 000000000000..cb572e189eb1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stderr.7
@@ -0,0 +1 @@
+make: don't know how to make #1/20. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.1 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.1
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.2 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.3 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.3
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.4 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.4
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.5 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.5
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.6 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.6
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.6
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.7 b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.7
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/expected.stdout.7
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/legacy_test.sh b/usr.bin/bmake/tests/archives/fmt_44bsd/legacy_test.sh
new file mode 100644
index 000000000000..9f75b3767061
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/legacy_test.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Archive parsing (BSD4.4 format)."
+
+# Setup
+TEST_COPY_FILES="libtest.a 644"
+
+# Run
+TEST_N=7
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd/libtest.a b/usr.bin/bmake/tests/archives/fmt_44bsd/libtest.a
new file mode 100644
index 000000000000..891ce6e652d7
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd/libtest.a
Binary files differ
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile
new file mode 100644
index 000000000000..ec8d7437ae9e
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile
@@ -0,0 +1,31 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/archives/fmt_44bsd_mod
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.status.3
+${PACKAGE}FILES+= expected.status.4
+${PACKAGE}FILES+= expected.status.5
+${PACKAGE}FILES+= expected.status.6
+${PACKAGE}FILES+= expected.status.7
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stderr.3
+${PACKAGE}FILES+= expected.stderr.4
+${PACKAGE}FILES+= expected.stderr.5
+${PACKAGE}FILES+= expected.stderr.6
+${PACKAGE}FILES+= expected.stderr.7
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= expected.stdout.3
+${PACKAGE}FILES+= expected.stdout.4
+${PACKAGE}FILES+= expected.stdout.5
+${PACKAGE}FILES+= expected.stdout.6
+${PACKAGE}FILES+= expected.stdout.7
+${PACKAGE}FILES+= libtest.a
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.depend b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.test b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.test
new file mode 100644
index 000000000000..f831f6c6b064
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/Makefile.test
@@ -0,0 +1,63 @@
+# This test checks the code reading archive files. The archive file
+# is a BSD4.4 file with __.SYMTAB and #1/N long file names.
+#
+# The modification of the archive consists in slashes appended to short names.
+#
+
+#############################################################################
+
+# must be ok
+test1: libtest.a(short.o)
+ @:
+
+libtest.a(short.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test2: libtest.a(exactly15char.o)
+ @:
+
+libtest.a(exactly15char.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test3: libtest.a(exactly16chars.o)
+ @:
+
+libtest.a(exactly16chars.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test4: libtest.a(verylongobjectname.o)
+ @:
+
+libtest.a(verylongobjectname.o): ood
+ @:
+
+#############################################################################
+
+# Truncated to 16 characters
+# must fail
+test5: libtest.a(verylongobjectna)
+ @:
+
+#############################################################################
+
+# Truncated to 15 characters
+# must fail
+test6: libtest.a(verylongobjectn)
+ @:
+
+#############################################################################
+
+# must fail
+test7: libtest.a(\#1/20)
+ @:
+
+ood:
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.1 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.2 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.3 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.3
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.3
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.4 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.4
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.4
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.5 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.5
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.5
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.6 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.6
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.6
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.7 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.7
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.status.7
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.1 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.1
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.2 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.3 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.3
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.4 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.4
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.5 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.5
new file mode 100644
index 000000000000..7b91643a3821
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.5
@@ -0,0 +1 @@
+make: don't know how to make verylongobjectna. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.6 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.6
new file mode 100644
index 000000000000..fd1519039acc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.6
@@ -0,0 +1 @@
+make: don't know how to make verylongobjectn. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.7 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.7
new file mode 100644
index 000000000000..cb572e189eb1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stderr.7
@@ -0,0 +1 @@
+make: don't know how to make #1/20. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.1 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.1
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.2 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.2
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.3 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.3
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.4 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.4
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.5 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.5
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.6 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.6
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.6
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.7 b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.7
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/expected.stdout.7
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/legacy_test.sh b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/legacy_test.sh
new file mode 100644
index 000000000000..ba0590c070fb
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/legacy_test.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Archive parsing (modified BSD4.4 format)."
+
+# Setup
+TEST_COPY_FILES="libtest.a 644"
+
+# Run
+TEST_N=7
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/archives/fmt_44bsd_mod/libtest.a b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/libtest.a
new file mode 100644
index 000000000000..57bc407a2723
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_44bsd_mod/libtest.a
Binary files differ
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile
new file mode 100644
index 000000000000..f30bfd2ed5d7
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile
@@ -0,0 +1,30 @@
+PACKAGE= tests
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/archives/fmt_oldbsd
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.status.3
+${PACKAGE}FILES+= expected.status.4
+${PACKAGE}FILES+= expected.status.5
+${PACKAGE}FILES+= expected.status.6
+${PACKAGE}FILES+= expected.status.7
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stderr.3
+${PACKAGE}FILES+= expected.stderr.4
+${PACKAGE}FILES+= expected.stderr.5
+${PACKAGE}FILES+= expected.stderr.6
+${PACKAGE}FILES+= expected.stderr.7
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= expected.stdout.3
+${PACKAGE}FILES+= expected.stdout.4
+${PACKAGE}FILES+= expected.stdout.5
+${PACKAGE}FILES+= expected.stdout.6
+${PACKAGE}FILES+= expected.stdout.7
+${PACKAGE}FILES+= libtest.a
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.depend b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.test b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.test
new file mode 100644
index 000000000000..1dafe5c7370a
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/Makefile.test
@@ -0,0 +1,61 @@
+# This test checks the code reading archive files. The archive file
+# is an old BSD file with __.SYMTAB and no long file names. Filenames
+# are truncated to 16 characters.
+
+#############################################################################
+
+# must be ok
+test1: libtest.a(short.o)
+ @:
+
+libtest.a(short.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test2: libtest.a(exactly15char.o)
+ @:
+
+libtest.a(exactly15char.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test3: libtest.a(exactly16chars.o)
+ @:
+
+libtest.a(exactly16chars.o): ood
+ @:
+
+#############################################################################
+
+# must be ok
+test4: libtest.a(verylongobjectname.o)
+ @:
+
+libtest.a(verylongobjectname.o): ood
+ @:
+
+#############################################################################
+
+# Truncated to 16 characters
+# must be ok
+test5: libtest.a(verylongobjectna)
+ @:
+
+#############################################################################
+
+# Truncated to 15 characters
+# must fail
+test6: libtest.a(verylongobjectn)
+ @:
+
+#############################################################################
+
+# must fail
+test7: libtest.a(\#1/20)
+ @:
+
+ood:
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.1 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.2 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.3 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.3
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.3
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.4 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.4
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.4
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.5 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.5
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.5
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.6 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.6
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.6
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.7 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.7
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.status.7
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.1 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.1
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.2 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.2
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.3 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.3
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.4 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.4
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.5 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.5
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.6 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.6
new file mode 100644
index 000000000000..fd1519039acc
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.6
@@ -0,0 +1 @@
+make: don't know how to make verylongobjectn. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.7 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.7
new file mode 100644
index 000000000000..cb572e189eb1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stderr.7
@@ -0,0 +1 @@
+make: don't know how to make #1/20. Stop
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.1 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.1
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.2 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.2
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.3 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.3
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.4 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.4
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.5 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.5
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.6 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.6
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.6
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.7 b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.7
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/expected.stdout.7
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/legacy_test.sh b/usr.bin/bmake/tests/archives/fmt_oldbsd/legacy_test.sh
new file mode 100644
index 000000000000..9fece6fda680
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/legacy_test.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Archive parsing (old BSD format)."
+
+# Setup
+TEST_COPY_FILES="libtest.a 644"
+
+# Run
+TEST_N=7
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/archives/fmt_oldbsd/libtest.a b/usr.bin/bmake/tests/archives/fmt_oldbsd/libtest.a
new file mode 100644
index 000000000000..3434c53898a1
--- /dev/null
+++ b/usr.bin/bmake/tests/archives/fmt_oldbsd/libtest.a
Binary files differ
diff --git a/usr.bin/bmake/tests/basic/Makefile b/usr.bin/bmake/tests/basic/Makefile
new file mode 100644
index 000000000000..129ca34c06f9
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/basic
+
+TESTS_SUBDIRS= t0 t1 t2 t3
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/basic/Makefile.depend b/usr.bin/bmake/tests/basic/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/basic/t0/Makefile b/usr.bin/bmake/tests/basic/t0/Makefile
new file mode 100644
index 000000000000..6f7cf0fec6f5
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/Makefile
@@ -0,0 +1,11 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/basic/t0
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/basic/t0/Makefile.depend b/usr.bin/bmake/tests/basic/t0/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/basic/t0/expected.status.1 b/usr.bin/bmake/tests/basic/t0/expected.status.1
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/expected.status.1
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/basic/t0/expected.stderr.1 b/usr.bin/bmake/tests/basic/t0/expected.stderr.1
new file mode 100644
index 000000000000..90280c8298b9
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/expected.stderr.1
@@ -0,0 +1 @@
+make: no target to make.
diff --git a/usr.bin/bmake/tests/basic/t0/expected.stdout.1 b/usr.bin/bmake/tests/basic/t0/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/expected.stdout.1
diff --git a/usr.bin/bmake/tests/basic/t0/legacy_test.sh b/usr.bin/bmake/tests/basic/t0/legacy_test.sh
new file mode 100644
index 000000000000..60ed3a79599f
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t0/legacy_test.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="An empty Makefile file and no target given."
+
+# Setup
+TEST_TOUCH="Makefile ''"
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/basic/t1/Makefile b/usr.bin/bmake/tests/basic/t1/Makefile
new file mode 100644
index 000000000000..921c35705f2f
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/basic/t1
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/basic/t1/Makefile.depend b/usr.bin/bmake/tests/basic/t1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/basic/t1/Makefile.test b/usr.bin/bmake/tests/basic/t1/Makefile.test
new file mode 100644
index 000000000000..3394bdb325ad
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/Makefile.test
@@ -0,0 +1,4 @@
+#
+# Just a target and nothing else. No target on command line.
+#
+all:
diff --git a/usr.bin/bmake/tests/basic/t1/expected.status.1 b/usr.bin/bmake/tests/basic/t1/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/basic/t1/expected.stderr.1 b/usr.bin/bmake/tests/basic/t1/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/expected.stderr.1
diff --git a/usr.bin/bmake/tests/basic/t1/expected.stdout.1 b/usr.bin/bmake/tests/basic/t1/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/expected.stdout.1
diff --git a/usr.bin/bmake/tests/basic/t1/legacy_test.sh b/usr.bin/bmake/tests/basic/t1/legacy_test.sh
new file mode 100644
index 000000000000..31b85e5db3c3
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t1/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="A Makefile file with only a 'all:' file dependency specification."
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/basic/t2/Makefile b/usr.bin/bmake/tests/basic/t2/Makefile
new file mode 100644
index 000000000000..c75e752580bb
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/basic/t2
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/basic/t2/Makefile.depend b/usr.bin/bmake/tests/basic/t2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/basic/t2/Makefile.test b/usr.bin/bmake/tests/basic/t2/Makefile.test
new file mode 100644
index 000000000000..39889e90da07
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/Makefile.test
@@ -0,0 +1,5 @@
+#
+# Just a target and a command. No command line targets.
+#
+all:
+ echo hello
diff --git a/usr.bin/bmake/tests/basic/t2/expected.status.1 b/usr.bin/bmake/tests/basic/t2/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/basic/t2/expected.stderr.1 b/usr.bin/bmake/tests/basic/t2/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/expected.stderr.1
diff --git a/usr.bin/bmake/tests/basic/t2/expected.stdout.1 b/usr.bin/bmake/tests/basic/t2/expected.stdout.1
new file mode 100644
index 000000000000..e618540e387d
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/expected.stdout.1
@@ -0,0 +1,2 @@
+echo hello
+hello
diff --git a/usr.bin/bmake/tests/basic/t2/legacy_test.sh b/usr.bin/bmake/tests/basic/t2/legacy_test.sh
new file mode 100644
index 000000000000..df8cab594cac
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t2/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="A Makefile file with only a 'all:' file dependency specification, and shell command."
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/basic/t3/Makefile b/usr.bin/bmake/tests/basic/t3/Makefile
new file mode 100644
index 000000000000..292071adcbc7
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/Makefile
@@ -0,0 +1,11 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/basic/t3
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/basic/t3/Makefile.depend b/usr.bin/bmake/tests/basic/t3/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/basic/t3/expected.status.1 b/usr.bin/bmake/tests/basic/t3/expected.status.1
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/expected.status.1
@@ -0,0 +1 @@
+2
diff --git a/usr.bin/bmake/tests/basic/t3/expected.stderr.1 b/usr.bin/bmake/tests/basic/t3/expected.stderr.1
new file mode 100644
index 000000000000..90280c8298b9
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/expected.stderr.1
@@ -0,0 +1 @@
+make: no target to make.
diff --git a/usr.bin/bmake/tests/basic/t3/expected.stdout.1 b/usr.bin/bmake/tests/basic/t3/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/expected.stdout.1
diff --git a/usr.bin/bmake/tests/basic/t3/legacy_test.sh b/usr.bin/bmake/tests/basic/t3/legacy_test.sh
new file mode 100644
index 000000000000..4011c6def4d1
--- /dev/null
+++ b/usr.bin/bmake/tests/basic/t3/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="No Makefile file, no command line target."
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/common.sh b/usr.bin/bmake/tests/common.sh
new file mode 100644
index 000000000000..fa078ef84c4f
--- /dev/null
+++ b/usr.bin/bmake/tests/common.sh
@@ -0,0 +1,532 @@
+#
+# Common code used run regression tests for usr.bin/make.
+
+#
+# Output a message and exit with an error.
+#
+fatal()
+{
+ echo "fatal: $*" >/dev/stderr
+ exit 1
+}
+
+make_is_fmake() {
+ # This test is not very reliable but works for now: the old fmake
+ # does have a -v option while bmake doesn't.
+ ${MAKE_PROG} -f Makefile.non-existent -v 2>&1 | \
+ grep -q "cannot open.*non-existent"
+}
+
+#
+# Check whether the working directory exists - it must.
+#
+ensure_workdir()
+{
+ if [ ! -d ${WORK_DIR} ] ; then
+ fatal "working directory ${WORK_DIR} does not exist."
+ fi
+}
+
+#
+# Make sure all tests have been run
+#
+ensure_run()
+{
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ FAIL=
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ if [ ! -f ${OUTPUT_DIR}/status.${N} -o \
+ ! -f ${OUTPUT_DIR}/stdout.${N} -o \
+ ! -f ${OUTPUT_DIR}/stderr.${N} ] ; then
+ echo "Test ${SUBDIR}/${N} no yet run"
+ FAIL=yes
+ fi
+ fi
+ N=$((N + 1))
+ done
+
+ if [ ! -z "${FAIL}" ] ; then
+ exit 1
+ fi
+}
+
+#
+# Output usage message.
+#
+print_usage()
+{
+ echo "Usage: sh -v -m <path> -w <dir> $0 command(s)"
+ echo " setup - setup working directory"
+ echo " run - run the tests"
+ echo " show - show test results"
+ echo " compare - compare actual and expected results"
+ echo " diff - diff actual and expected results"
+ echo " reset - reset the test to its initial state"
+ echo " clean - delete working and output directory"
+ echo " test - setup + run + compare"
+ echo " prove - setup + run + compare + clean"
+ echo " desc - print short description"
+ echo " update - update the expected results with the current results"
+ echo " help - show this information"
+}
+
+#
+# Return 0 if we should skip the test. 1 otherwise
+#
+skip_test()
+{
+ eval skip=\${TEST_${1}_SKIP}
+ if [ -z "${skip}" ] ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+#
+# Common function for setup and reset.
+#
+common_setup()
+{
+ #
+ # If a Makefile exists in the source directory - copy it over
+ #
+ if [ -e ${SRC_DIR}/Makefile.test -a ! -e ${WORK_DIR}/Makefile ] ; then
+ cp ${SRC_DIR}/Makefile.test ${WORK_DIR}/Makefile
+ fi
+
+ #
+ # If the TEST_MAKE_DIRS variable is set, create those directories
+ #
+ set -- ${TEST_MAKE_DIRS}
+ while [ $# -ne 0 ] ; do
+ if [ ! -d ${WORK_DIR}/${1} ] ; then
+ mkdir -p -m ${2} ${WORK_DIR}/${1}
+ else
+ chmod ${2} ${WORK_DIR}/${1}
+ fi
+ shift ; shift
+ done
+
+ #
+ # If the TEST_COPY_FILES variable is set, copy those files over to
+ # the working directory. The value is assumed to be pairs of
+ # filenames and modes.
+ #
+ set -- ${TEST_COPY_FILES}
+ while [ $# -ne 0 ] ; do
+ local dstname="$(echo ${1} | sed -e 's,Makefile.test,Makefile,')"
+ if [ ! -e ${WORK_DIR}/${dstname} ] ; then
+ cp ${SRC_DIR}/${1} ${WORK_DIR}/${dstname}
+ fi
+ chmod ${2} ${WORK_DIR}/${dstname}
+ shift ; shift
+ done
+
+ #
+ # If the TEST_TOUCH variable is set, it is taken to be a list
+ # of pairs of filenames and arguments to touch(1). The arguments
+ # to touch must be surrounded by single quotes if there are more
+ # than one argument.
+ #
+ eval set -- ${TEST_TOUCH}
+ while [ $# -ne 0 ] ; do
+ eval touch ${2} ${WORK_DIR}/${1}
+ shift ; shift
+ done
+
+ #
+ # Now create links
+ #
+ eval set -- ${TEST_LINKS}
+ while [ $# -ne 0 ] ; do
+ eval ln ${WORK_DIR}/${1} ${WORK_DIR}/${2}
+ shift ; shift
+ done
+}
+
+#
+# Setup the test. This creates the working and output directories and
+# populates it with files. If there is a setup_test() function - call it.
+#
+eval_setup()
+{
+ #
+ # Check whether the working directory exists. If it does exit
+ # fatally so that we don't clobber a test the user is working on.
+ #
+ if [ -d ${WORK_DIR} ] ; then
+ fatal "working directory ${WORK_DIR} already exists."
+ fi
+
+ #
+ # Now create it and the output directory
+ #
+ mkdir -p ${WORK_DIR}
+ rm -rf ${OUTPUT_DIR}
+ mkdir -p ${OUTPUT_DIR}
+
+ #
+ # Common stuff
+ #
+ common_setup
+
+ #
+ # Now after all execute the user's setup function if it exists.
+ #
+ setup_test
+}
+
+#
+# Default setup_test function does nothing. This may be overriden by
+# the test.
+#
+setup_test()
+{
+}
+
+#
+# Reset the test. Here we need to rely on information from the test.
+# We executed the same steps as in the setup, by try not to clobber existing
+# files.
+# All files and directories that are listed on the TEST_CLEAN_FILES
+# variable are removed. Then the TEST_TOUCH list is executed and finally
+# the reset_test() function called if it exists.
+#
+eval_reset()
+{
+ ensure_workdir
+
+ #
+ # Clean the output directory
+ #
+ rm -rf ${OUTPUT_DIR}/*
+
+ #
+ # Common stuff
+ #
+ common_setup
+
+ #
+ # Remove files.
+ #
+ for f in ${TEST_CLEAN_FILES} ; do
+ rm -rf ${WORK_DIR}/${f}
+ done
+
+ #
+ # Execute test's function
+ #
+ reset_test
+}
+
+#
+# Default reset_test function does nothing. This may be overriden by
+# the test.
+#
+reset_test()
+{
+}
+
+#
+# Clean the test. This simply removes the working and output directories.
+#
+eval_clean()
+{
+ #
+ # If you have special cleaning needs, provide a 'cleanup' shell script.
+ #
+ if [ -n "${TEST_CLEANUP}" ] ; then
+ . ${SRC_DIR}/cleanup
+ fi
+ if [ -z "${NO_TEST_CLEANUP}" ] ; then
+ rm -rf ${WORK_DIR}
+ rm -rf ${OUTPUT_DIR}
+ fi
+}
+
+#
+# Run the test.
+#
+eval_run()
+{
+ ensure_workdir
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ ( cd ${WORK_DIR} ;
+ exec 1>${OUTPUT_DIR}/stdout.${N} 2>${OUTPUT_DIR}/stderr.${N}
+ run_test ${N}
+ echo $? >${OUTPUT_DIR}/status.${N}
+ )
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Default run_test() function. It can be replaced by the
+# user specified regression test. The argument to this function is
+# the test number.
+#
+run_test()
+{
+ eval args=\${TEST_${1}-test${1}}
+ ${MAKE_PROG} $args
+}
+
+#
+# Show test results.
+#
+eval_show()
+{
+ ensure_workdir
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ echo "=== Test ${N} Status =================="
+ cat ${OUTPUT_DIR}/status.${N}
+ echo ".......... Stdout .................."
+ cat ${OUTPUT_DIR}/stdout.${N}
+ echo ".......... Stderr .................."
+ cat ${OUTPUT_DIR}/stderr.${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Compare results with expected results
+#
+eval_compare()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ echo "1..${TEST_N}"
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ fail=
+ todo=
+ skip=
+ if ! skip_test ${N} ; then
+ do_compare stdout ${N} || fail="${fail}stdout "
+ do_compare stderr ${N} || fail="${fail}stderr "
+ do_compare status ${N} || fail="${fail}status "
+ eval todo=\${TEST_${N}_TODO}
+ else
+ eval skip=\${TEST_${N}_SKIP}
+ fi
+ msg=
+ if [ ! -z "$fail" ]; then
+ msg="${msg}not "
+ fi
+ msg="${msg}ok ${N} ${SUBDIR}/${N}"
+ if [ ! -z "$fail" -o ! -z "$todo" -o ! -z "$skip" ]; then
+ msg="${msg} # "
+ fi
+ if [ ! -z "$skip" ] ; then
+ msg="${msg}skip ${skip}; "
+ fi
+ if [ ! -z "$todo" ] ; then
+ msg="${msg}TODO ${todo}; "
+ fi
+ if [ ! -z "$fail" ] ; then
+ msg="${msg}reason: ${fail}"
+ fi
+ echo ${msg}
+ N=$((N + 1))
+ done
+}
+
+#
+# Check if the test result is the same as the expected result.
+#
+# $1 Input file
+# $2 Test number
+#
+do_compare()
+{
+ local EXPECTED RESULT
+ EXPECTED="${SRC_DIR}/expected.$1.$2"
+ RESULT="${OUTPUT_DIR}/$1.$2"
+
+ if [ -f $EXPECTED ]; then
+ cat $RESULT | sed -e "s,^$(basename $MAKE_PROG):,make:," | \
+ diff -u $EXPECTED -
+ #diff -q $EXPECTED - 1>/dev/null 2>/dev/null
+ return $?
+ else
+ return 1 # FAIL
+ fi
+}
+
+#
+# Diff current and expected results
+#
+eval_diff()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ FAIL=
+ do_diff stdout ${N}
+ do_diff stderr ${N}
+ do_diff status ${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Check if the test result is the same as the expected result.
+#
+# $1 Input file
+# $2 Test number
+#
+do_diff()
+{
+ local EXPECTED RESULT
+ EXPECTED="${SRC_DIR}/expected.$1.$2"
+ RESULT="${OUTPUT_DIR}/$1.$2"
+
+ echo diff -u $EXPECTED $RESULT
+ if [ -f $EXPECTED ]; then
+ diff -u $EXPECTED $RESULT
+ else
+ echo "${EXPECTED} does not exist"
+ fi
+}
+
+#
+# Update expected results
+#
+eval_update()
+{
+ ensure_workdir
+ ensure_run
+
+ if [ -z "${TEST_N}" ] ; then
+ TEST_N=1
+ fi
+
+ FAIL=
+ N=1
+ while [ ${N} -le ${TEST_N} ] ; do
+ if ! skip_test ${N} ; then
+ cp ${OUTPUT_DIR}/stdout.${N} expected.stdout.${N}
+ cp ${OUTPUT_DIR}/stderr.${N} expected.stderr.${N}
+ cp ${OUTPUT_DIR}/status.${N} expected.status.${N}
+ fi
+ N=$((N + 1))
+ done
+}
+
+#
+# Print description
+#
+eval_desc()
+{
+ echo "${SUBDIR}: ${DESC}"
+}
+
+#
+# Run the test
+#
+eval_test()
+{
+ eval_setup
+ eval_run
+ eval_compare
+}
+
+#
+# Run the test for prove(1)
+#
+eval_prove()
+{
+ eval_setup
+ eval_run
+ eval_compare
+ eval_clean
+}
+
+#
+# Main function. Execute the command(s) on the command line.
+#
+eval_cmd()
+{
+ if [ $# -eq 0 ] ; then
+ # if no arguments given default to 'prove'
+ set -- prove
+ fi
+
+ if ! make_is_fmake ; then
+ for i in $(jot ${TEST_N:-1}) ; do
+ eval TEST_${i}_SKIP=\"make is not fmake\"
+ done
+ fi
+
+ for i
+ do
+ case $i in
+
+ setup | run | compare | diff | clean | reset | show | \
+ test | prove | desc | update)
+ eval eval_$i
+ ;;
+ * | help)
+ print_usage
+ ;;
+ esac
+ done
+}
+
+##############################################################################
+#
+# Main code
+#
+
+#
+# Determine our sub-directory. Argh.
+#
+SRC_DIR=$(dirname $0)
+SRC_BASE=`cd ${SRC_DIR} ; while [ ! -f common.sh ] ; do cd .. ; done ; pwd`
+SUBDIR=`echo ${SRC_DIR} | sed "s@${SRC_BASE}/@@"`
+
+#
+# Construct working directory
+#
+WORK_DIR=$(pwd)/work/${SUBDIR}
+OUTPUT_DIR=${WORK_DIR}.OUTPUT
+
+#
+# Make to use
+#
+MAKE_PROG=${MAKE_PROG:-/usr/bin/make}
diff --git a/usr.bin/bmake/tests/execution/Makefile b/usr.bin/bmake/tests/execution/Makefile
new file mode 100644
index 000000000000..c979fd447b8c
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/execution
+
+TESTS_SUBDIRS= ellipsis empty joberr plus
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/execution/Makefile.depend b/usr.bin/bmake/tests/execution/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/execution/ellipsis/Makefile b/usr.bin/bmake/tests/execution/ellipsis/Makefile
new file mode 100644
index 000000000000..b4f9a0362556
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/execution/ellipsis
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/execution/ellipsis/Makefile.depend b/usr.bin/bmake/tests/execution/ellipsis/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/execution/ellipsis/Makefile.test b/usr.bin/bmake/tests/execution/ellipsis/Makefile.test
new file mode 100644
index 000000000000..a208171e29ad
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/Makefile.test
@@ -0,0 +1,19 @@
+ELLIPSIS= ...
+
+check-ellipsis:
+ @${MAKE} -f ${MAKEFILE} do-$@
+ @${MAKE} -f ${MAKEFILE} -j2 do-$@
+ @${MAKE} -f ${MAKEFILE} -j2 -B do-$@
+
+do-check-ellipsis: do-check-ellipsis-1 do-check-ellipsis-2
+.ORDER: do-check-ellipsis-1 do-check-ellipsis-2
+
+do-check-ellipsis-1:
+ @echo before $@
+ ${ELLIPSIS}
+ @echo after $@
+
+do-check-ellipsis-2:
+ @echo before $@
+ ${ELLIPSIS}
+ @echo after $@
diff --git a/usr.bin/bmake/tests/execution/ellipsis/expected.status.1 b/usr.bin/bmake/tests/execution/ellipsis/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/execution/ellipsis/expected.stderr.1 b/usr.bin/bmake/tests/execution/ellipsis/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/expected.stderr.1
diff --git a/usr.bin/bmake/tests/execution/ellipsis/expected.stdout.1 b/usr.bin/bmake/tests/execution/ellipsis/expected.stdout.1
new file mode 100644
index 000000000000..a7e5727b5181
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/expected.stdout.1
@@ -0,0 +1,12 @@
+before do-check-ellipsis-1
+before do-check-ellipsis-2
+after do-check-ellipsis-1
+after do-check-ellipsis-2
+before do-check-ellipsis-1
+before do-check-ellipsis-2
+after do-check-ellipsis-1
+after do-check-ellipsis-2
+before do-check-ellipsis-1
+before do-check-ellipsis-2
+after do-check-ellipsis-1
+after do-check-ellipsis-2
diff --git a/usr.bin/bmake/tests/execution/ellipsis/legacy_test.sh b/usr.bin/bmake/tests/execution/ellipsis/legacy_test.sh
new file mode 100644
index 000000000000..0c011e3a158c
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/ellipsis/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Ellipsis command from variable"
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/execution/empty/Makefile b/usr.bin/bmake/tests/execution/empty/Makefile
new file mode 100644
index 000000000000..0917b2881011
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/execution/empty
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/execution/empty/Makefile.depend b/usr.bin/bmake/tests/execution/empty/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/execution/empty/Makefile.test b/usr.bin/bmake/tests/execution/empty/Makefile.test
new file mode 100644
index 000000000000..d7567955e6d9
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/Makefile.test
@@ -0,0 +1,11 @@
+EMPTY=
+
+check-empty:
+ @${MAKE} -f ${MAKEFILE} do-$@
+ @${MAKE} -f ${MAKEFILE} -j2 do-$@
+ @${MAKE} -f ${MAKEFILE} -j2 -B do-$@
+
+do-check-empty:
+ ${EMPTY}
+ @${EMPTY}
+ @-${EMPTY}
diff --git a/usr.bin/bmake/tests/execution/empty/expected.status.1 b/usr.bin/bmake/tests/execution/empty/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/execution/empty/expected.stderr.1 b/usr.bin/bmake/tests/execution/empty/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/expected.stderr.1
diff --git a/usr.bin/bmake/tests/execution/empty/expected.stdout.1 b/usr.bin/bmake/tests/execution/empty/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/expected.stdout.1
diff --git a/usr.bin/bmake/tests/execution/empty/legacy_test.sh b/usr.bin/bmake/tests/execution/empty/legacy_test.sh
new file mode 100644
index 000000000000..4a0d809a9773
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/empty/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Empty command (from variable)"
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/execution/joberr/Makefile b/usr.bin/bmake/tests/execution/joberr/Makefile
new file mode 100644
index 000000000000..89d93bbee65f
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/execution/joberr
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/execution/joberr/Makefile.depend b/usr.bin/bmake/tests/execution/joberr/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/execution/joberr/Makefile.test b/usr.bin/bmake/tests/execution/joberr/Makefile.test
new file mode 100644
index 000000000000..8849a3d39651
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/Makefile.test
@@ -0,0 +1,8 @@
+check-joberr:
+.for _t in 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
+ @-${MAKE} -f ${MAKEFILE} -j2 do-$@
+.endfor
+
+do-check-joberr:
+ @echo "Error: build failed"
+ @exit 1
diff --git a/usr.bin/bmake/tests/execution/joberr/expected.status.1 b/usr.bin/bmake/tests/execution/joberr/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/execution/joberr/expected.stderr.1 b/usr.bin/bmake/tests/execution/joberr/expected.stderr.1
new file mode 100644
index 000000000000..d0c8a2eb27b2
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/expected.stderr.1
@@ -0,0 +1,30 @@
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
+1 error
diff --git a/usr.bin/bmake/tests/execution/joberr/expected.stdout.1 b/usr.bin/bmake/tests/execution/joberr/expected.stdout.1
new file mode 100644
index 000000000000..0ee28f4fd515
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/expected.stdout.1
@@ -0,0 +1,90 @@
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+Error: build failed
+*** [do-check-joberr] Error code 1
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
+*** [check-joberr] Error code 2 (ignored)
diff --git a/usr.bin/bmake/tests/execution/joberr/legacy_test.sh b/usr.bin/bmake/tests/execution/joberr/legacy_test.sh
new file mode 100644
index 000000000000..f5f24411bdfc
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/joberr/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Test job make error output"
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/execution/plus/Makefile b/usr.bin/bmake/tests/execution/plus/Makefile
new file mode 100644
index 000000000000..1e7ea12a087d
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/execution/plus
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/execution/plus/Makefile.depend b/usr.bin/bmake/tests/execution/plus/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/execution/plus/Makefile.test b/usr.bin/bmake/tests/execution/plus/Makefile.test
new file mode 100644
index 000000000000..d423d8a7c405
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/Makefile.test
@@ -0,0 +1,5 @@
+check-+:
+ @${MAKE} -f ${MAKEFILE} -j2 -n do-$@
+
+do-check-+:
+ @+echo $@
diff --git a/usr.bin/bmake/tests/execution/plus/expected.status.1 b/usr.bin/bmake/tests/execution/plus/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/execution/plus/expected.stderr.1 b/usr.bin/bmake/tests/execution/plus/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/expected.stderr.1
diff --git a/usr.bin/bmake/tests/execution/plus/expected.stdout.1 b/usr.bin/bmake/tests/execution/plus/expected.stdout.1
new file mode 100644
index 000000000000..b334fc734706
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/expected.stdout.1
@@ -0,0 +1 @@
+do-check-+
diff --git a/usr.bin/bmake/tests/execution/plus/legacy_test.sh b/usr.bin/bmake/tests/execution/plus/legacy_test.sh
new file mode 100644
index 000000000000..c0a83013f96e
--- /dev/null
+++ b/usr.bin/bmake/tests/execution/plus/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Test '+command' execution with -n -jX"
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/Makefile b/usr.bin/bmake/tests/shell/Makefile
new file mode 100644
index 000000000000..7d15b940f412
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell
+
+TESTS_SUBDIRS= builtin meta path path_select replace select
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/Makefile.depend b/usr.bin/bmake/tests/shell/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/builtin/Makefile b/usr.bin/bmake/tests/shell/builtin/Makefile
new file mode 100644
index 000000000000..802d4511e56d
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/builtin
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/builtin/Makefile.depend b/usr.bin/bmake/tests/shell/builtin/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/builtin/Makefile.test b/usr.bin/bmake/tests/shell/builtin/Makefile.test
new file mode 100644
index 000000000000..111bb1821bf9
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/Makefile.test
@@ -0,0 +1,17 @@
+#
+# In compat mode (the default without -j) a line that contains no shell
+# meta characters and no shell builtins is not passed to the shell but
+# executed directly. In our example the ls line without meta characters
+# will really execute ls, while the line with meta characters will execute
+# our special shell.
+#
+
+.SHELL: path="${.CURDIR}/sh"
+
+.PHONY: builtin no-builtin
+
+builtin:
+ @exec ls -d .
+
+no-builtin:
+ @ls -d .
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.status.1 b/usr.bin/bmake/tests/shell/builtin/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.status.2 b/usr.bin/bmake/tests/shell/builtin/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.stderr.1 b/usr.bin/bmake/tests/shell/builtin/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.stderr.2 b/usr.bin/bmake/tests/shell/builtin/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.stdout.1 b/usr.bin/bmake/tests/shell/builtin/expected.stdout.1
new file mode 100644
index 000000000000..9c558e357c41
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.stdout.1
@@ -0,0 +1 @@
+.
diff --git a/usr.bin/bmake/tests/shell/builtin/expected.stdout.2 b/usr.bin/bmake/tests/shell/builtin/expected.stdout.2
new file mode 100644
index 000000000000..e350eaf8c7ea
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/expected.stdout.2
@@ -0,0 +1 @@
+-ec exec ls -d .
diff --git a/usr.bin/bmake/tests/shell/builtin/legacy_test.sh b/usr.bin/bmake/tests/shell/builtin/legacy_test.sh
new file mode 100644
index 000000000000..d569508902fb
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/legacy_test.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Check that a command line with a builtin is passed to the shell."
+
+# Setup
+TEST_COPY_FILES="sh 755"
+
+# Run
+TEST_N=2
+TEST_1="-B no-builtin"
+TEST_2="-B builtin"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/builtin/sh b/usr.bin/bmake/tests/shell/builtin/sh
new file mode 100644
index 000000000000..2c246c988ce8
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/builtin/sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo "$@"
+if ! test -t 0 ; then
+ cat
+fi
diff --git a/usr.bin/bmake/tests/shell/meta/Makefile b/usr.bin/bmake/tests/shell/meta/Makefile
new file mode 100644
index 000000000000..0fde362c203c
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/meta
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/meta/Makefile.depend b/usr.bin/bmake/tests/shell/meta/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/meta/Makefile.test b/usr.bin/bmake/tests/shell/meta/Makefile.test
new file mode 100644
index 000000000000..fbee949acc5d
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/Makefile.test
@@ -0,0 +1,17 @@
+#
+# In compat mode (the default without -j) a line that contains no shell
+# meta characters and no shell builtins is not passed to the shell but
+# executed directly. In our example the ls line without meta characters
+# will really execute ls, while the line with meta characters will execute
+# our special shell.
+#
+
+.SHELL: path="${.OBJDIR}/sh"
+
+.PHONY: meta no-meta
+
+meta:
+ @ls *
+
+no-meta:
+ @ls -d .
diff --git a/usr.bin/bmake/tests/shell/meta/expected.status.1 b/usr.bin/bmake/tests/shell/meta/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/meta/expected.status.2 b/usr.bin/bmake/tests/shell/meta/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/meta/expected.stderr.1 b/usr.bin/bmake/tests/shell/meta/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/meta/expected.stderr.2 b/usr.bin/bmake/tests/shell/meta/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/meta/expected.stdout.1 b/usr.bin/bmake/tests/shell/meta/expected.stdout.1
new file mode 100644
index 000000000000..9c558e357c41
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.stdout.1
@@ -0,0 +1 @@
+.
diff --git a/usr.bin/bmake/tests/shell/meta/expected.stdout.2 b/usr.bin/bmake/tests/shell/meta/expected.stdout.2
new file mode 100644
index 000000000000..6ac6f19502a5
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/expected.stdout.2
@@ -0,0 +1 @@
+-ec ls *
diff --git a/usr.bin/bmake/tests/shell/meta/legacy_test.sh b/usr.bin/bmake/tests/shell/meta/legacy_test.sh
new file mode 100644
index 000000000000..b276f3d434de
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/legacy_test.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Check that a command line with meta characters is passed to the shell."
+
+# Setup
+TEST_COPY_FILES="sh 755"
+
+# Run
+TEST_N=2
+TEST_1="-B no-meta"
+TEST_2="-B meta"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/meta/sh b/usr.bin/bmake/tests/shell/meta/sh
new file mode 100644
index 000000000000..2c246c988ce8
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/meta/sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo "$@"
+if ! test -t 0 ; then
+ cat
+fi
diff --git a/usr.bin/bmake/tests/shell/path/Makefile b/usr.bin/bmake/tests/shell/path/Makefile
new file mode 100644
index 000000000000..78eae358de7f
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/path
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/path/Makefile.depend b/usr.bin/bmake/tests/shell/path/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/path/Makefile.test b/usr.bin/bmake/tests/shell/path/Makefile.test
new file mode 100644
index 000000000000..b5080234d7ce
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/Makefile.test
@@ -0,0 +1,30 @@
+#
+# Change the path for builtin shells. There are two methods to do this.
+# This is the first of them when the basename of the path is equal to
+# one of the builtin shells so that the .SHELL target automatically
+# also selectes the shell without specifying the name.
+#
+# Be sure to include a meta-character into the command line, so that
+# really our shell is executed.
+#
+#
+
+.ifmake sh_test
+
+.SHELL: path=${.OBJDIR}/sh
+sh_test:
+ @: This is the shell.
+
+.elifmake csh_test
+
+.SHELL: path=${.OBJDIR}/csh
+csh_test:
+ @: This is the C-shell.
+
+.elifmake ksh_test
+
+.SHELL: path=${.OBJDIR}/ksh
+ksh_test:
+ @: This is the Korn-shell.
+
+.endif
diff --git a/usr.bin/bmake/tests/shell/path/expected.status.1 b/usr.bin/bmake/tests/shell/path/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/path/expected.status.2 b/usr.bin/bmake/tests/shell/path/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/path/expected.stderr.1 b/usr.bin/bmake/tests/shell/path/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/path/expected.stderr.2 b/usr.bin/bmake/tests/shell/path/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/path/expected.stdout.1 b/usr.bin/bmake/tests/shell/path/expected.stdout.1
new file mode 100644
index 000000000000..d881364744b2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.stdout.1
@@ -0,0 +1 @@
+-ec : This is the shell.
diff --git a/usr.bin/bmake/tests/shell/path/expected.stdout.2 b/usr.bin/bmake/tests/shell/path/expected.stdout.2
new file mode 100644
index 000000000000..de3fc89cc9e2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/expected.stdout.2
@@ -0,0 +1 @@
+-ec : This is the C-shell.
diff --git a/usr.bin/bmake/tests/shell/path/legacy_test.sh b/usr.bin/bmake/tests/shell/path/legacy_test.sh
new file mode 100644
index 000000000000..bd3492774fb7
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/legacy_test.sh
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="New path for builtin shells."
+
+# Setup
+TEST_COPY_FILES="sh 755"
+TEST_LINKS="sh csh sh ksh"
+
+# Run
+TEST_N=3
+TEST_1="sh_test"
+TEST_2="csh_test"
+TEST_3="ksh_test"
+TEST_3_SKIP="no ksh on FreeBSD"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/path/sh b/usr.bin/bmake/tests/shell/path/sh
new file mode 100644
index 000000000000..4363618a2f36
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path/sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo $@
+if ! test -t 0 ; then
+ cat
+fi
diff --git a/usr.bin/bmake/tests/shell/path_select/Makefile b/usr.bin/bmake/tests/shell/path_select/Makefile
new file mode 100644
index 000000000000..15aa45f061a9
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/path_select
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= shell
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/path_select/Makefile.depend b/usr.bin/bmake/tests/shell/path_select/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/path_select/Makefile.test b/usr.bin/bmake/tests/shell/path_select/Makefile.test
new file mode 100644
index 000000000000..7a8042e60a96
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/Makefile.test
@@ -0,0 +1,30 @@
+#
+# Change the path for builtin shells. There are two methods to do this.
+# This is the second of them when both a path and a name are specified.
+# This selects a builtin shell according to the name, but executes it
+# from the specified path.
+#
+# Be sure to include a meta-character into the command line, so that
+# really our shell is executed.
+#
+#
+
+.ifmake sh_test
+
+.SHELL: name=sh path=${.CURDIR}/shell
+sh_test:
+ @: This is the shell.
+
+.elifmake csh_test
+
+.SHELL: name=csh path=${.CURDIR}/shell
+csh_test:
+ @: This is the C-shell.
+
+.elifmake ksh_test
+
+.SHELL: name=ksh path=${.CURDIR}/shell
+ksh_test:
+ @: This is the Korn-shell.
+
+.endif
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.status.1 b/usr.bin/bmake/tests/shell/path_select/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.status.2 b/usr.bin/bmake/tests/shell/path_select/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.stderr.1 b/usr.bin/bmake/tests/shell/path_select/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.stderr.2 b/usr.bin/bmake/tests/shell/path_select/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.stdout.1 b/usr.bin/bmake/tests/shell/path_select/expected.stdout.1
new file mode 100644
index 000000000000..d881364744b2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.stdout.1
@@ -0,0 +1 @@
+-ec : This is the shell.
diff --git a/usr.bin/bmake/tests/shell/path_select/expected.stdout.2 b/usr.bin/bmake/tests/shell/path_select/expected.stdout.2
new file mode 100644
index 000000000000..de3fc89cc9e2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/expected.stdout.2
@@ -0,0 +1 @@
+-ec : This is the C-shell.
diff --git a/usr.bin/bmake/tests/shell/path_select/legacy_test.sh b/usr.bin/bmake/tests/shell/path_select/legacy_test.sh
new file mode 100644
index 000000000000..dbb91dcc9e56
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/legacy_test.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="New path for builtin shells (2)."
+
+# Setup
+TEST_COPY_FILES="shell 755"
+
+# Run
+TEST_N=3
+TEST_1="sh_test"
+TEST_2="csh_test"
+TEST_3="ksh_test"
+TEST_3_SKIP="no ksh on FreeBSD"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/path_select/shell b/usr.bin/bmake/tests/shell/path_select/shell
new file mode 100644
index 000000000000..4363618a2f36
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/path_select/shell
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo $@
+if ! test -t 0 ; then
+ cat
+fi
diff --git a/usr.bin/bmake/tests/shell/replace/Makefile b/usr.bin/bmake/tests/shell/replace/Makefile
new file mode 100644
index 000000000000..e2e7ad948db2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/replace
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= shell
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/replace/Makefile.depend b/usr.bin/bmake/tests/shell/replace/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/replace/Makefile.test b/usr.bin/bmake/tests/shell/replace/Makefile.test
new file mode 100644
index 000000000000..d0076b598214
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/Makefile.test
@@ -0,0 +1,20 @@
+#
+# Test that we can replace the shell and set all the shell parameters
+# (except meta and builtin which have their own test). This is done by
+# using a shell script for the shell that echoes all command line
+# arguments and its standard input. The shell name should not be one of
+# the builtin shells.
+#
+# XXX There seems to be a problem here in -j1 mode: for the line without
+# @- make should switch on echoing again, but it doesn't.
+#
+
+.SHELL: name="shell" path="${.CURDIR}/shell" \
+ quiet="be quiet" echo="be verbose" filter="be verbose" \
+ echoFlag="x" errFlag="y" \
+ hasErrCtl=y check="check errors" ignore="ignore errors"
+
+.PHONY: test1
+test1:
+ -@funny $$
+ funnier $$
diff --git a/usr.bin/bmake/tests/shell/replace/expected.status.1 b/usr.bin/bmake/tests/shell/replace/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/replace/expected.status.2 b/usr.bin/bmake/tests/shell/replace/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/replace/expected.stderr.1 b/usr.bin/bmake/tests/shell/replace/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/replace/expected.stderr.2 b/usr.bin/bmake/tests/shell/replace/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/replace/expected.stdout.1 b/usr.bin/bmake/tests/shell/replace/expected.stdout.1
new file mode 100644
index 000000000000..eff99ea17ab2
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.stdout.1
@@ -0,0 +1,3 @@
+-c funny $
+funnier $
+-ec funnier $
diff --git a/usr.bin/bmake/tests/shell/replace/expected.stdout.2 b/usr.bin/bmake/tests/shell/replace/expected.stdout.2
new file mode 100644
index 000000000000..c79a09af2916
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/expected.stdout.2
@@ -0,0 +1,6 @@
+-yx
+be quiet
+ignore errors
+funny $
+check errors
+funnier $
diff --git a/usr.bin/bmake/tests/shell/replace/legacy_test.sh b/usr.bin/bmake/tests/shell/replace/legacy_test.sh
new file mode 100644
index 000000000000..6e672d57b607
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/legacy_test.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Check that the shell can be replaced."
+
+# Setup
+TEST_COPY_FILES="shell 755"
+
+# Run
+TEST_N=2
+TEST_1=
+TEST_2=-j2
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/shell/replace/shell b/usr.bin/bmake/tests/shell/replace/shell
new file mode 100644
index 000000000000..4363618a2f36
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/replace/shell
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo $@
+if ! test -t 0 ; then
+ cat
+fi
diff --git a/usr.bin/bmake/tests/shell/select/Makefile b/usr.bin/bmake/tests/shell/select/Makefile
new file mode 100644
index 000000000000..851077c23635
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/shell/select
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/shell/select/Makefile.depend b/usr.bin/bmake/tests/shell/select/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/shell/select/Makefile.test b/usr.bin/bmake/tests/shell/select/Makefile.test
new file mode 100644
index 000000000000..ed2b105610ae
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/Makefile.test
@@ -0,0 +1,27 @@
+#
+# We just select the builtin shells and check whether it is really
+# executed. This should print just the shell paths. Because we
+# normally don't have a ksh, we make this test conditional. This means
+# one has to recreate the test results once ksh is installed.
+#
+#
+
+.ifmake sh_test
+
+.SHELL: name=sh
+sh_test: print_path
+
+.elifmake csh_test
+
+.SHELL: name=csh
+csh_test: print_path
+
+.elifmake ksh_test
+
+.SHELL: name=ksh
+ksh_test: print_path
+
+.endif
+
+print_path:
+ @ps -x -opid,command | awk '$$1=='$$$$' { print $$2; }'
diff --git a/usr.bin/bmake/tests/shell/select/expected.status.1 b/usr.bin/bmake/tests/shell/select/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/select/expected.status.2 b/usr.bin/bmake/tests/shell/select/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/shell/select/expected.stderr.1 b/usr.bin/bmake/tests/shell/select/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.stderr.1
diff --git a/usr.bin/bmake/tests/shell/select/expected.stderr.2 b/usr.bin/bmake/tests/shell/select/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.stderr.2
diff --git a/usr.bin/bmake/tests/shell/select/expected.stdout.1 b/usr.bin/bmake/tests/shell/select/expected.stdout.1
new file mode 100644
index 000000000000..c2cdaa0f27c1
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.stdout.1
@@ -0,0 +1 @@
+/bin/sh
diff --git a/usr.bin/bmake/tests/shell/select/expected.stdout.2 b/usr.bin/bmake/tests/shell/select/expected.stdout.2
new file mode 100644
index 000000000000..5a831e82da12
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/expected.stdout.2
@@ -0,0 +1 @@
+/bin/csh
diff --git a/usr.bin/bmake/tests/shell/select/legacy_test.sh b/usr.bin/bmake/tests/shell/select/legacy_test.sh
new file mode 100644
index 000000000000..fc26745d61db
--- /dev/null
+++ b/usr.bin/bmake/tests/shell/select/legacy_test.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Select the builtin sh shell."
+
+# Run
+TEST_N=3
+TEST_1="sh_test"
+TEST_2="csh_test"
+TEST_3="ksh_test"
+TEST_3_SKIP="no ksh on FreeBSD"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/suffixes/Makefile b/usr.bin/bmake/tests/suffixes/Makefile
new file mode 100644
index 000000000000..d8132bcca685
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/suffixes
+
+TESTS_SUBDIRS= basic src_wild1 src_wild2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/suffixes/Makefile.depend b/usr.bin/bmake/tests/suffixes/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/suffixes/basic/Makefile b/usr.bin/bmake/tests/suffixes/basic/Makefile
new file mode 100644
index 000000000000..cfdc32fd8d00
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/Makefile
@@ -0,0 +1,13 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/suffixes/basic
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES= Makefile.test
+${PACKAGE}FILES+= TEST1.a
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/suffixes/basic/Makefile.depend b/usr.bin/bmake/tests/suffixes/basic/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/suffixes/basic/Makefile.test b/usr.bin/bmake/tests/suffixes/basic/Makefile.test
new file mode 100644
index 000000000000..6056774252f4
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/Makefile.test
@@ -0,0 +1,12 @@
+#
+# Check that a simple suffix rule is correctly processed.
+
+test1: TEST1.b
+ diff -u TEST1.a TEST1.b
+
+.SUFFIXES:
+
+.SUFFIXES: .a .b
+
+.a.b:
+ cat ${.IMPSRC} >${.TARGET}
diff --git a/usr.bin/bmake/tests/suffixes/basic/TEST1.a b/usr.bin/bmake/tests/suffixes/basic/TEST1.a
new file mode 100644
index 000000000000..da5569b525e3
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/TEST1.a
@@ -0,0 +1 @@
+I'm test file 1.
diff --git a/usr.bin/bmake/tests/suffixes/basic/expected.status.1 b/usr.bin/bmake/tests/suffixes/basic/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/suffixes/basic/expected.stderr.1 b/usr.bin/bmake/tests/suffixes/basic/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/expected.stderr.1
diff --git a/usr.bin/bmake/tests/suffixes/basic/expected.stdout.1 b/usr.bin/bmake/tests/suffixes/basic/expected.stdout.1
new file mode 100644
index 000000000000..582927e8e98e
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/expected.stdout.1
@@ -0,0 +1,2 @@
+cat TEST1.a >TEST1.b
+diff -u TEST1.a TEST1.b
diff --git a/usr.bin/bmake/tests/suffixes/basic/legacy_test.sh b/usr.bin/bmake/tests/suffixes/basic/legacy_test.sh
new file mode 100644
index 000000000000..19d647a456fd
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/basic/legacy_test.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Basic suffix operation."
+
+# Setup
+TEST_COPY_FILES="TEST1.a 644"
+
+# Reset
+TEST_CLEAN="Test1.b"
+
+# Run
+TEST_N=1
+TEST_1="-r test1"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/Makefile b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile
new file mode 100644
index 000000000000..b941895bf798
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile
@@ -0,0 +1,14 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/suffixes/src_wild1
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= TEST1.a
+${PACKAGE}FILES+= TEST2.a
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.depend b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.test b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.test
new file mode 100644
index 000000000000..08a9c3ab3cb4
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/Makefile.test
@@ -0,0 +1,5 @@
+test1: TEST1.b
+ cat TEST1.a TEST2.a | diff -u - TEST1.b
+
+TEST1.b: *.a
+ cat ${.ALLSRC} >${.TARGET}
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/TEST1.a b/usr.bin/bmake/tests/suffixes/src_wild1/TEST1.a
new file mode 100644
index 000000000000..da5569b525e3
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/TEST1.a
@@ -0,0 +1 @@
+I'm test file 1.
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/TEST2.a b/usr.bin/bmake/tests/suffixes/src_wild1/TEST2.a
new file mode 100644
index 000000000000..34f850858dc0
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/TEST2.a
@@ -0,0 +1 @@
+I'm test file 2.
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/expected.status.1 b/usr.bin/bmake/tests/suffixes/src_wild1/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/expected.stderr.1 b/usr.bin/bmake/tests/suffixes/src_wild1/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/expected.stderr.1
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/expected.stdout.1 b/usr.bin/bmake/tests/suffixes/src_wild1/expected.stdout.1
new file mode 100644
index 000000000000..3cd2129260c1
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/expected.stdout.1
@@ -0,0 +1,2 @@
+cat TEST1.a TEST2.a >TEST1.b
+cat TEST1.a TEST2.a | diff -u - TEST1.b
diff --git a/usr.bin/bmake/tests/suffixes/src_wild1/legacy_test.sh b/usr.bin/bmake/tests/suffixes/src_wild1/legacy_test.sh
new file mode 100644
index 000000000000..555112a3df67
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild1/legacy_test.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Source wildcard expansion."
+
+# Setup
+TEST_COPY_FILES="TEST1.a 644 TEST2.a 644"
+
+# Reset
+TEST_CLEAN="TEST1.b"
+
+# Run
+TEST_N=1
+TEST_1="-r test1"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/Makefile b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile
new file mode 100644
index 000000000000..8f048e9b50d6
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile
@@ -0,0 +1,14 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/suffixes/src_wild2
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= TEST1.a
+${PACKAGE}FILES+= TEST2.a
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.depend b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.test b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.test
new file mode 100644
index 000000000000..7c88e4c58660
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/Makefile.test
@@ -0,0 +1,11 @@
+#
+# Source expansion with the source in a macro
+#
+
+SRC=*.a
+
+test1: TEST1.b
+ cat TEST1.a TEST2.a | diff -u - TEST1.b
+
+TEST1.b: ${SRC}
+ cat ${.ALLSRC} >${.TARGET}
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/TEST1.a b/usr.bin/bmake/tests/suffixes/src_wild2/TEST1.a
new file mode 100644
index 000000000000..da5569b525e3
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/TEST1.a
@@ -0,0 +1 @@
+I'm test file 1.
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/TEST2.a b/usr.bin/bmake/tests/suffixes/src_wild2/TEST2.a
new file mode 100644
index 000000000000..34f850858dc0
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/TEST2.a
@@ -0,0 +1 @@
+I'm test file 2.
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/expected.status.1 b/usr.bin/bmake/tests/suffixes/src_wild2/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/expected.stderr.1 b/usr.bin/bmake/tests/suffixes/src_wild2/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/expected.stderr.1
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/expected.stdout.1 b/usr.bin/bmake/tests/suffixes/src_wild2/expected.stdout.1
new file mode 100644
index 000000000000..3cd2129260c1
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/expected.stdout.1
@@ -0,0 +1,2 @@
+cat TEST1.a TEST2.a >TEST1.b
+cat TEST1.a TEST2.a | diff -u - TEST1.b
diff --git a/usr.bin/bmake/tests/suffixes/src_wild2/legacy_test.sh b/usr.bin/bmake/tests/suffixes/src_wild2/legacy_test.sh
new file mode 100644
index 000000000000..e1faaff022a6
--- /dev/null
+++ b/usr.bin/bmake/tests/suffixes/src_wild2/legacy_test.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Source wildcard expansion (2)."
+
+# Setup
+TEST_COPY_FILES="TEST1.a 644 TEST2.a 644"
+
+# Reset
+TEST_CLEAN="TEST1.b"
+
+# Run
+TEST_N=1
+TEST_1="-r test1"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/syntax/Makefile b/usr.bin/bmake/tests/syntax/Makefile
new file mode 100644
index 000000000000..bed2ece9b2a7
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/syntax
+
+TESTS_SUBDIRS= directive-t0 enl funny-targets semi
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/syntax/Makefile.depend b/usr.bin/bmake/tests/syntax/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/Makefile b/usr.bin/bmake/tests/syntax/directive-t0/Makefile
new file mode 100644
index 000000000000..62945b572d14
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/syntax/directive-t0
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/Makefile.depend b/usr.bin/bmake/tests/syntax/directive-t0/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/Makefile.test b/usr.bin/bmake/tests/syntax/directive-t0/Makefile.test
new file mode 100644
index 000000000000..6081793e876d
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/Makefile.test
@@ -0,0 +1,7 @@
+#
+# A typo'ed directive.
+#
+
+.uudef foo
+
+all:
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/expected.status.1 b/usr.bin/bmake/tests/syntax/directive-t0/expected.status.1
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/expected.status.1
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/expected.stderr.1 b/usr.bin/bmake/tests/syntax/directive-t0/expected.stderr.1
new file mode 100644
index 000000000000..de66fcc37752
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/expected.stderr.1
@@ -0,0 +1,2 @@
+"Makefile", line 6: Unknown directive
+make: fatal errors encountered -- cannot continue
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/expected.stdout.1 b/usr.bin/bmake/tests/syntax/directive-t0/expected.stdout.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/expected.stdout.1
diff --git a/usr.bin/bmake/tests/syntax/directive-t0/legacy_test.sh b/usr.bin/bmake/tests/syntax/directive-t0/legacy_test.sh
new file mode 100644
index 000000000000..9a50d0bb7073
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/directive-t0/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="A typo'ed directive."
+
+# Run
+TEST_N=1
+TEST_1=
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/syntax/enl/Makefile b/usr.bin/bmake/tests/syntax/enl/Makefile
new file mode 100644
index 000000000000..cab0648e3b87
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/Makefile
@@ -0,0 +1,24 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/syntax/enl
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.status.3
+${PACKAGE}FILES+= expected.status.4
+${PACKAGE}FILES+= expected.status.5
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stderr.3
+${PACKAGE}FILES+= expected.stderr.4
+${PACKAGE}FILES+= expected.stderr.5
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= expected.stdout.3
+${PACKAGE}FILES+= expected.stdout.4
+${PACKAGE}FILES+= expected.stdout.5
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/syntax/enl/Makefile.depend b/usr.bin/bmake/tests/syntax/enl/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/syntax/enl/Makefile.test b/usr.bin/bmake/tests/syntax/enl/Makefile.test
new file mode 100644
index 000000000000..cd1cc15ceea1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/Makefile.test
@@ -0,0 +1,58 @@
+#
+# Test handling of escaped newlines.
+#
+
+.ifmake test1
+
+# This should succeed
+\
+\
+\
+test1:
+ @echo ok
+
+.elifmake test2
+
+# This should print ok because the second assignment to foo is actually
+# a continued comment.
+FOO=ok
+#\
+\
+FOO=not ok
+test2:
+ @echo "${FOO}"
+
+.elifmake test3
+
+# Make sure an escaped newline inserts a space
+test3: a\
+b
+
+a:
+ @echo a
+
+b:
+ @echo b
+
+.elifmake test4
+
+# Make sure an escaped newline inserts exactly one space
+FOO=a\
+ b
+
+test4:
+ @echo "${FOO}"
+
+.elifmake test5
+
+# Make sure each escaped newline inserts exactly one space
+FOO=a\
+\
+\
+\
+b
+
+test5:
+ @echo "${FOO}"
+
+.endif
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.status.1 b/usr.bin/bmake/tests/syntax/enl/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.status.2 b/usr.bin/bmake/tests/syntax/enl/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.status.3 b/usr.bin/bmake/tests/syntax/enl/expected.status.3
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.status.3
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.status.4 b/usr.bin/bmake/tests/syntax/enl/expected.status.4
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.status.4
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.status.5 b/usr.bin/bmake/tests/syntax/enl/expected.status.5
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.status.5
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stderr.1 b/usr.bin/bmake/tests/syntax/enl/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stderr.1
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stderr.2 b/usr.bin/bmake/tests/syntax/enl/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stderr.2
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stderr.3 b/usr.bin/bmake/tests/syntax/enl/expected.stderr.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stderr.3
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stderr.4 b/usr.bin/bmake/tests/syntax/enl/expected.stderr.4
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stderr.4
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stderr.5 b/usr.bin/bmake/tests/syntax/enl/expected.stderr.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stderr.5
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stdout.1 b/usr.bin/bmake/tests/syntax/enl/expected.stdout.1
new file mode 100644
index 000000000000..9766475a4185
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stdout.1
@@ -0,0 +1 @@
+ok
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stdout.2 b/usr.bin/bmake/tests/syntax/enl/expected.stdout.2
new file mode 100644
index 000000000000..9766475a4185
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stdout.2
@@ -0,0 +1 @@
+ok
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stdout.3 b/usr.bin/bmake/tests/syntax/enl/expected.stdout.3
new file mode 100644
index 000000000000..422c2b7ab3b3
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stdout.3
@@ -0,0 +1,2 @@
+a
+b
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stdout.4 b/usr.bin/bmake/tests/syntax/enl/expected.stdout.4
new file mode 100644
index 000000000000..b2901ea97cfc
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stdout.4
@@ -0,0 +1 @@
+a b
diff --git a/usr.bin/bmake/tests/syntax/enl/expected.stdout.5 b/usr.bin/bmake/tests/syntax/enl/expected.stdout.5
new file mode 100644
index 000000000000..51200767c616
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/expected.stdout.5
@@ -0,0 +1 @@
+a b
diff --git a/usr.bin/bmake/tests/syntax/enl/legacy_test.sh b/usr.bin/bmake/tests/syntax/enl/legacy_test.sh
new file mode 100644
index 000000000000..20d2a80d9603
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/enl/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Test escaped new-lines handling."
+
+# Run
+TEST_N=5
+TEST_2_TODO="bug in parser"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/Makefile b/usr.bin/bmake/tests/syntax/funny-targets/Makefile
new file mode 100644
index 000000000000..803e745c65a8
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/syntax/funny-targets
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/Makefile.depend b/usr.bin/bmake/tests/syntax/funny-targets/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/Makefile.test b/usr.bin/bmake/tests/syntax/funny-targets/Makefile.test
new file mode 100644
index 000000000000..943c46fe0571
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/Makefile.test
@@ -0,0 +1,13 @@
+#
+# PR bin/6612 / GRN r102178
+#
+
+test1: colons::colons::target
+
+colons::colons::target:
+ @echo '${.TARGET}'
+
+test2: exclamation!target
+
+exclamation!target:
+ @echo '${.TARGET}
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.status.1 b/usr.bin/bmake/tests/syntax/funny-targets/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.status.2 b/usr.bin/bmake/tests/syntax/funny-targets/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.1 b/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.1
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.2 b/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.stderr.2
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.1 b/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.1
new file mode 100644
index 000000000000..09cb2328e9f7
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.1
@@ -0,0 +1 @@
+colons::colons::target
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.2 b/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.2
new file mode 100644
index 000000000000..b2f03648b48d
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/expected.stdout.2
@@ -0,0 +1 @@
+exclamation!target
diff --git a/usr.bin/bmake/tests/syntax/funny-targets/legacy_test.sh b/usr.bin/bmake/tests/syntax/funny-targets/legacy_test.sh
new file mode 100644
index 000000000000..c922ee67227b
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/funny-targets/legacy_test.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC='Target names with "funny" embeded characters.'
+
+# Run
+TEST_N=2
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/syntax/semi/Makefile b/usr.bin/bmake/tests/syntax/semi/Makefile
new file mode 100644
index 000000000000..0af26aed75e6
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/syntax/semi
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/syntax/semi/Makefile.depend b/usr.bin/bmake/tests/syntax/semi/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/syntax/semi/Makefile.test b/usr.bin/bmake/tests/syntax/semi/Makefile.test
new file mode 100644
index 000000000000..c863f7e111e1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/Makefile.test
@@ -0,0 +1,25 @@
+#
+# Test handling of escaped newlines.
+#
+
+.ifmake test1
+
+FOO=
+BAR=bar
+FOO != echo ${FOO} ; echo ${BAR}
+
+test1:
+ echo ${FOO}
+
+.endif
+
+.ifmake test2
+
+FOO=foo
+BAR=bar
+FOO != echo ${FOO} ; echo ${BAR}
+
+test2:
+ echo ${FOO}
+
+.endif
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.status.1 b/usr.bin/bmake/tests/syntax/semi/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.status.2 b/usr.bin/bmake/tests/syntax/semi/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.stderr.1 b/usr.bin/bmake/tests/syntax/semi/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.stderr.1
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.stderr.2 b/usr.bin/bmake/tests/syntax/semi/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.stderr.2
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.stdout.1 b/usr.bin/bmake/tests/syntax/semi/expected.stdout.1
new file mode 100644
index 000000000000..12b9617511d6
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.stdout.1
@@ -0,0 +1,2 @@
+echo bar
+bar
diff --git a/usr.bin/bmake/tests/syntax/semi/expected.stdout.2 b/usr.bin/bmake/tests/syntax/semi/expected.stdout.2
new file mode 100644
index 000000000000..be0fa5556666
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/expected.stdout.2
@@ -0,0 +1,2 @@
+echo foo bar
+foo bar
diff --git a/usr.bin/bmake/tests/syntax/semi/legacy_test.sh b/usr.bin/bmake/tests/syntax/semi/legacy_test.sh
new file mode 100644
index 000000000000..81e8f0d9c69b
--- /dev/null
+++ b/usr.bin/bmake/tests/syntax/semi/legacy_test.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Test semicolon handling."
+
+# Run
+TEST_N=2
+TEST_1_TODO="parser bug"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/sysmk/Makefile b/usr.bin/bmake/tests/sysmk/Makefile
new file mode 100644
index 000000000000..302e8059d0e6
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk
+
+TESTS_SUBDIRS= t0 t1 t2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/Makefile.depend b/usr.bin/bmake/tests/sysmk/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile
new file mode 100644
index 000000000000..69c6ecb522fa
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t0/2/1
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.depend b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.test b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.test
new file mode 100644
index 000000000000..6b4eac3f1880
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/Makefile.test
@@ -0,0 +1,5 @@
+#
+# Can we traverse up to / and find a 'mk/sys.mk'?
+#
+all:
+ @echo ${DASH_M_DOTDOTDOT}
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/expected.status.1 b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stderr.1 b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stderr.1
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stdout.1 b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stdout.1
new file mode 100644
index 000000000000..6f29307aecc3
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/expected.stdout.1
@@ -0,0 +1 @@
+Found_DotDotDot_sys_mk
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/1/legacy_test.sh b/usr.bin/bmake/tests/sysmk/t0/2/1/legacy_test.sh
new file mode 100644
index 000000000000..7b5139751dcb
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/1/legacy_test.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+. $(dirname $0)/../../../../common.sh
+
+# Description
+DESC="Can we traverse up to / and find a 'mk/sys.mk'?"
+
+# Run
+TEST_N=1
+TEST_1="-m .../mk"
+TEST_MAKE_DIRS="../../mk 755"
+TEST_COPY_FILES="../../mk/sys.mk 644"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/Makefile b/usr.bin/bmake/tests/sysmk/t0/2/Makefile
new file mode 100644
index 000000000000..9fbcc9527124
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t0/2
+
+TESTS_SUBDIRS= 1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t0/2/Makefile.depend b/usr.bin/bmake/tests/sysmk/t0/2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t0/Makefile b/usr.bin/bmake/tests/sysmk/t0/Makefile
new file mode 100644
index 000000000000..0ffd2fe9edd6
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/Makefile
@@ -0,0 +1,6 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t0
+
+TESTS_SUBDIRS= 2
+SUBDIR= mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t0/Makefile.depend b/usr.bin/bmake/tests/sysmk/t0/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t0/mk/Makefile b/usr.bin/bmake/tests/sysmk/t0/mk/Makefile
new file mode 100644
index 000000000000..b02918923a3a
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/mk/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t0/mk
+
+${PACKAGE}FILES+= sys.mk.test
+
+${PACKAGE}FILESNAME_sys.mk.test= sys.mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t0/mk/Makefile.depend b/usr.bin/bmake/tests/sysmk/t0/mk/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/mk/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t0/mk/sys.mk.test b/usr.bin/bmake/tests/sysmk/t0/mk/sys.mk.test
new file mode 100644
index 000000000000..b08709e89ca5
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t0/mk/sys.mk.test
@@ -0,0 +1,2 @@
+
+DASH_M_DOTDOTDOT=Found_DotDotDot_sys_mk
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile b/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile
new file mode 100644
index 000000000000..5e448e91e48c
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t1/2/1
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= cleanup
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile.depend b/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/cleanup b/usr.bin/bmake/tests/sysmk/t1/2/1/cleanup
new file mode 100644
index 000000000000..0ca413803115
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/cleanup
@@ -0,0 +1,2 @@
+
+rm -rf ${WORK_DIR}/../../../t0/2/1
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/expected.status.1 b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stderr.1 b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stderr.1
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stdout.1 b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stdout.1
new file mode 100644
index 000000000000..6f29307aecc3
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/expected.stdout.1
@@ -0,0 +1 @@
+Found_DotDotDot_sys_mk
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/1/legacy_test.sh b/usr.bin/bmake/tests/sysmk/t1/2/1/legacy_test.sh
new file mode 100644
index 000000000000..c6483c3f6f1c
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/1/legacy_test.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+. $(dirname $0)/../../../../common.sh
+
+# Description
+DESC="Can we traverse up to / and find a 'mk/sys.mk' with -C -m?"
+
+# Run
+TEST_N=1
+TEST_1="-C ../../../t0/2/1 -m .../mk"
+TEST_MAKE_DIRS="../../mk 755 ../../../t0/mk 755 ../../../t0/2/1 755"
+TEST_COPY_FILES="../../mk/sys.mk 644 ../../../t0/mk/sys.mk 644 ../../../t0/2/1/Makefile.test 644"
+TEST_CLEAN_FILES="../../../t0/2/1"
+TEST_CLEANUP=clean-special
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/Makefile b/usr.bin/bmake/tests/sysmk/t1/2/Makefile
new file mode 100644
index 000000000000..652066ddea0e
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t1/2
+
+TESTS_SUBDIRS= 1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t1/2/Makefile.depend b/usr.bin/bmake/tests/sysmk/t1/2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t1/Makefile b/usr.bin/bmake/tests/sysmk/t1/Makefile
new file mode 100644
index 000000000000..07a2962e6f49
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/Makefile
@@ -0,0 +1,6 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t1
+
+TESTS_SUBDIRS= 2
+SUBDIR= mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t1/Makefile.depend b/usr.bin/bmake/tests/sysmk/t1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t1/mk/Makefile b/usr.bin/bmake/tests/sysmk/t1/mk/Makefile
new file mode 100644
index 000000000000..3d9597d8580e
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/mk/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t1/mk
+
+${PACKAGE}FILES+= sys.mk.test
+
+${PACKAGE}FILESNAME_sys.mk.test= sys.mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t1/mk/Makefile.depend b/usr.bin/bmake/tests/sysmk/t1/mk/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/mk/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t1/mk/sys.mk.test b/usr.bin/bmake/tests/sysmk/t1/mk/sys.mk.test
new file mode 100644
index 000000000000..e49f3829ecab
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t1/mk/sys.mk.test
@@ -0,0 +1,2 @@
+
+DASH_M_DOTDOTDOT=Found_WRONG_DotDotDot_sys_mk__with_C_before_m
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile b/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile
new file mode 100644
index 000000000000..a3b7a56993b5
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t2/2/1
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= cleanup
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile.depend b/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/cleanup b/usr.bin/bmake/tests/sysmk/t2/2/1/cleanup
new file mode 100644
index 000000000000..0ca413803115
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/cleanup
@@ -0,0 +1,2 @@
+
+rm -rf ${WORK_DIR}/../../../t0/2/1
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/expected.status.1 b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stderr.1 b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stderr.1
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stdout.1 b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stdout.1
new file mode 100644
index 000000000000..70f1be3c507c
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/expected.stdout.1
@@ -0,0 +1 @@
+Found_DotDotDot_sys_mk__with_m_before_C
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/1/legacy_test.sh b/usr.bin/bmake/tests/sysmk/t2/2/1/legacy_test.sh
new file mode 100644
index 000000000000..2039eb09280a
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/1/legacy_test.sh
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+. $(dirname $0)/../../../../common.sh
+
+# Description
+DESC="Can we traverse up to / and find a 'mk/sys.mk' with -m -C?"
+
+# Run
+TEST_N=1
+TEST_1="-m .../mk -C ../../../t0/2/1"
+TEST_MAKE_DIRS="../../mk 755 ../../../t0/mk 755 ../../../t0/2/1 755"
+TEST_COPY_FILES="../../mk/sys.mk 644 ../../../t0/mk/sys.mk 644 ../../../t0/2/1/Makefile.test 644"
+TEST_CLEAN_FILES="../../../t0/2/1"
+TEST_CLEANUP=clean-special
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/Makefile b/usr.bin/bmake/tests/sysmk/t2/2/Makefile
new file mode 100644
index 000000000000..04a4f5b41bc2
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t2/2
+
+TESTS_SUBDIRS= 1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t2/2/Makefile.depend b/usr.bin/bmake/tests/sysmk/t2/2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t2/Makefile b/usr.bin/bmake/tests/sysmk/t2/Makefile
new file mode 100644
index 000000000000..9d06ee857c21
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/Makefile
@@ -0,0 +1,6 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t2
+
+TESTS_SUBDIRS= 2
+SUBDIR= mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t2/Makefile.depend b/usr.bin/bmake/tests/sysmk/t2/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t2/mk/Makefile b/usr.bin/bmake/tests/sysmk/t2/mk/Makefile
new file mode 100644
index 000000000000..2f08ba2cea58
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/mk/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/sysmk/t2/mk
+
+${PACKAGE}FILES+= sys.mk.test
+
+${PACKAGE}FILESNAME_sys.mk.test= sys.mk
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/sysmk/t2/mk/Makefile.depend b/usr.bin/bmake/tests/sysmk/t2/mk/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/mk/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/sysmk/t2/mk/sys.mk.test b/usr.bin/bmake/tests/sysmk/t2/mk/sys.mk.test
new file mode 100644
index 000000000000..ceb5f909d390
--- /dev/null
+++ b/usr.bin/bmake/tests/sysmk/t2/mk/sys.mk.test
@@ -0,0 +1,2 @@
+
+DASH_M_DOTDOTDOT=Found_DotDotDot_sys_mk__with_m_before_C
diff --git a/usr.bin/bmake/tests/test-new.mk b/usr.bin/bmake/tests/test-new.mk
new file mode 100644
index 000000000000..761f0a1acc9f
--- /dev/null
+++ b/usr.bin/bmake/tests/test-new.mk
@@ -0,0 +1,8 @@
+
+NEW_DIR!= make -C ${.CURDIR}/../../../../usr.bin/make -V .OBJDIR
+
+all:
+ rm -rf /tmp/${USER}.make.test
+ env MAKE_PROG=${NEW_DIR}/make ${.SHELL} ./all.sh
+
+.include <bsd.obj.mk>
diff --git a/usr.bin/bmake/tests/variables/Makefile b/usr.bin/bmake/tests/variables/Makefile
new file mode 100644
index 000000000000..f138b4b0c436
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/Makefile
@@ -0,0 +1,5 @@
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/variables
+
+TESTS_SUBDIRS= modifier_M modifier_t opt_V t0
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/variables/Makefile.depend b/usr.bin/bmake/tests/variables/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/variables/modifier_M/Makefile b/usr.bin/bmake/tests/variables/modifier_M/Makefile
new file mode 100644
index 000000000000..484de9de0bdc
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/variables/modifier_M
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/variables/modifier_M/Makefile.depend b/usr.bin/bmake/tests/variables/modifier_M/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/variables/modifier_M/Makefile.test b/usr.bin/bmake/tests/variables/modifier_M/Makefile.test
new file mode 100644
index 000000000000..a4fa026431f1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/Makefile.test
@@ -0,0 +1,17 @@
+#
+# Test the M modifier.
+#
+FILES = \
+ main.c globals.h \
+ util.c util.h \
+ map.c map.h \
+ parser.y lexer.l \
+ cmdman.1 format.5
+test1:
+ @echo "all files: ${FILES}"
+ @echo "cfiles: ${FILES:M*.c}"
+ @echo "hfiles: ${FILES:M*.h}"
+ @echo "grammar and lexer: ${FILES:M*.[ly]}"
+ @echo "man page: ${FILES:M*.[1-9]}"
+ @echo "utility files: ${FILES:Mutil.?}"
+ @echo "m files: ${FILES:Mm*}"
diff --git a/usr.bin/bmake/tests/variables/modifier_M/expected.status.1 b/usr.bin/bmake/tests/variables/modifier_M/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/modifier_M/expected.stderr.1 b/usr.bin/bmake/tests/variables/modifier_M/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/expected.stderr.1
diff --git a/usr.bin/bmake/tests/variables/modifier_M/expected.stdout.1 b/usr.bin/bmake/tests/variables/modifier_M/expected.stdout.1
new file mode 100644
index 000000000000..b29e6df10233
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/expected.stdout.1
@@ -0,0 +1,7 @@
+all files: main.c globals.h util.c util.h map.c map.h parser.y lexer.l cmdman.1 format.5
+cfiles: main.c util.c map.c
+hfiles: globals.h util.h map.h
+grammar and lexer: parser.y lexer.l
+man page: cmdman.1 format.5
+utility files: util.c util.h
+m files: main.c map.c map.h
diff --git a/usr.bin/bmake/tests/variables/modifier_M/legacy_test.sh b/usr.bin/bmake/tests/variables/modifier_M/legacy_test.sh
new file mode 100644
index 000000000000..58dccdcf4743
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_M/legacy_test.sh
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Variable expansion with M modifier"
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/variables/modifier_t/Makefile b/usr.bin/bmake/tests/variables/modifier_t/Makefile
new file mode 100644
index 000000000000..2553e4517c4b
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/Makefile
@@ -0,0 +1,18 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/variables/modifier_t
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.status.3
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stderr.3
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+${PACKAGE}FILES+= expected.stdout.3
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/variables/modifier_t/Makefile.depend b/usr.bin/bmake/tests/variables/modifier_t/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/variables/modifier_t/Makefile.test b/usr.bin/bmake/tests/variables/modifier_t/Makefile.test
new file mode 100644
index 000000000000..a99eb194f972
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/Makefile.test
@@ -0,0 +1,14 @@
+#
+# Test the t modifier.
+#
+# below is missing '
+ASCII= !"\#$$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+
+test1:
+ @echo '${ASCII}'
+
+test2:
+ @echo '${ASCII:tl}'
+
+test3:
+ @echo '${ASCII:tu}'
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.status.1 b/usr.bin/bmake/tests/variables/modifier_t/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.status.2 b/usr.bin/bmake/tests/variables/modifier_t/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.status.3 b/usr.bin/bmake/tests/variables/modifier_t/expected.status.3
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.status.3
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.1 b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.1
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.2 b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.2
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.3 b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stderr.3
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.1 b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.1
new file mode 100644
index 000000000000..dff38fdd07ff
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.1
@@ -0,0 +1 @@
+!"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.2 b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.2
new file mode 100644
index 000000000000..71a0f6077ef2
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.2
@@ -0,0 +1 @@
+!"#$%&()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
diff --git a/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.3 b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.3
new file mode 100644
index 000000000000..6434c7ba7434
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/expected.stdout.3
@@ -0,0 +1 @@
+!"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~
diff --git a/usr.bin/bmake/tests/variables/modifier_t/legacy_test.sh b/usr.bin/bmake/tests/variables/modifier_t/legacy_test.sh
new file mode 100644
index 000000000000..42dfbe07e6e9
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/modifier_t/legacy_test.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Variable expansion with t modifiers"
+
+# Run
+TEST_N=3
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/variables/opt_V/Makefile b/usr.bin/bmake/tests/variables/opt_V/Makefile
new file mode 100644
index 000000000000..534b3e4246f6
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/variables/opt_V
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.status.2
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stderr.2
+${PACKAGE}FILES+= expected.stdout.1
+${PACKAGE}FILES+= expected.stdout.2
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/variables/opt_V/Makefile.depend b/usr.bin/bmake/tests/variables/opt_V/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/variables/opt_V/Makefile.test b/usr.bin/bmake/tests/variables/opt_V/Makefile.test
new file mode 100644
index 000000000000..b30ab0c9822c
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/Makefile.test
@@ -0,0 +1,14 @@
+#
+# Test the -V option
+#
+
+FOO= foo
+FOOBAR= ${FOO}bar
+
+test1:
+ @echo "-V FOOBAR"
+ @${MAKE} -V FOOBAR
+
+test2:
+ @echo '-V "$${FOOBAR}"'
+ @${MAKE} -V '$${FOOBAR}'
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.status.1 b/usr.bin/bmake/tests/variables/opt_V/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.status.2 b/usr.bin/bmake/tests/variables/opt_V/expected.status.2
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.status.2
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.stderr.1 b/usr.bin/bmake/tests/variables/opt_V/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.stderr.1
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.stderr.2 b/usr.bin/bmake/tests/variables/opt_V/expected.stderr.2
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.stderr.2
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.stdout.1 b/usr.bin/bmake/tests/variables/opt_V/expected.stdout.1
new file mode 100644
index 000000000000..050db40eed2b
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.stdout.1
@@ -0,0 +1,2 @@
+-V FOOBAR
+foobar
diff --git a/usr.bin/bmake/tests/variables/opt_V/expected.stdout.2 b/usr.bin/bmake/tests/variables/opt_V/expected.stdout.2
new file mode 100644
index 000000000000..4da2aeffad3e
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/expected.stdout.2
@@ -0,0 +1,2 @@
+-V "${FOOBAR}"
+foobar
diff --git a/usr.bin/bmake/tests/variables/opt_V/legacy_test.sh b/usr.bin/bmake/tests/variables/opt_V/legacy_test.sh
new file mode 100644
index 000000000000..2522f6d7e9b1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/opt_V/legacy_test.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Variable expansion using command line '-V'"
+
+# Run
+TEST_N=2
+
+eval_cmd $*
diff --git a/usr.bin/bmake/tests/variables/t0/Makefile b/usr.bin/bmake/tests/variables/t0/Makefile
new file mode 100644
index 000000000000..7cf7bd7dac9a
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/bmake/variables/t0
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= Makefile.test
+${PACKAGE}FILES+= expected.status.1
+${PACKAGE}FILES+= expected.stderr.1
+${PACKAGE}FILES+= expected.stdout.1
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bmake/tests/variables/t0/Makefile.depend b/usr.bin/bmake/tests/variables/t0/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bmake/tests/variables/t0/Makefile.test b/usr.bin/bmake/tests/variables/t0/Makefile.test
new file mode 100644
index 000000000000..222b7befa287
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/Makefile.test
@@ -0,0 +1,22 @@
+#
+# A unsorted set of macro expansions. This should be sorted out.
+#
+A = 0
+AV = 1
+test1:
+ @echo $A
+ @echo ${AV}
+ @echo ${A}
+ @# The following are soo broken why no syntax error?
+ @echo $(
+ @echo $)
+ @echo ${
+ @echo ${A
+ @echo ${A)
+ @echo ${A){
+ @echo ${AV
+ @echo ${AV)
+ @echo ${AV){
+ @echo ${AV{
+ @echo ${A{
+ @echo $}
diff --git a/usr.bin/bmake/tests/variables/t0/expected.status.1 b/usr.bin/bmake/tests/variables/t0/expected.status.1
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/expected.status.1
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/bmake/tests/variables/t0/expected.stderr.1 b/usr.bin/bmake/tests/variables/t0/expected.stderr.1
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/expected.stderr.1
diff --git a/usr.bin/bmake/tests/variables/t0/expected.stdout.1 b/usr.bin/bmake/tests/variables/t0/expected.stdout.1
new file mode 100644
index 000000000000..e2c70dedf68f
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/expected.stdout.1
@@ -0,0 +1,15 @@
+0
+1
+0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/usr.bin/bmake/tests/variables/t0/legacy_test.sh b/usr.bin/bmake/tests/variables/t0/legacy_test.sh
new file mode 100644
index 000000000000..99405f555116
--- /dev/null
+++ b/usr.bin/bmake/tests/variables/t0/legacy_test.sh
@@ -0,0 +1,8 @@
+#! /bin/sh
+
+. $(dirname $0)/../../common.sh
+
+# Description
+DESC="Variable expansion."
+
+eval_cmd $*
diff --git a/usr.bin/bmake/unit-tests/Makefile b/usr.bin/bmake/unit-tests/Makefile
new file mode 100644
index 000000000000..cdf252d5e474
--- /dev/null
+++ b/usr.bin/bmake/unit-tests/Makefile
@@ -0,0 +1,918 @@
+# This is a generated file, do NOT edit!
+# See contrib/bmake/bsd.after-import.mk
+#
+# $Id: Makefile,v 1.230 2025/01/30 18:04:20 sjg Exp $
+#
+# $NetBSD: Makefile,v 1.355 2025/01/25 22:46:30 sjg Exp $
+#
+# Unit tests for make(1)
+#
+# The main targets are:
+#
+# all:
+# run all the tests
+# test:
+# run 'all', and compare to expected results
+# accept:
+# move generated output to expected results
+#
+# Settable variables
+#
+# TEST_MAKE
+# The make program to be tested.
+#
+#
+# Adding a test case
+#
+# Each feature should get its own set of tests in its own suitably
+# named makefile (*.mk), with its own set of expected results (*.exp),
+# and it should be added to the TESTS list.
+#
+
+.MAIN: all
+
+# we use these below but we might be an older make
+.MAKE.OS?= ${uname -s:L:sh}
+.MAKE.UID?= ${id -u:L:sh}
+
+# for many tests we need a TMPDIR that will not collide
+# with other users.
+.if ${.OBJDIR} != ${.CURDIR}
+# easy
+TMPDIR:= ${.OBJDIR}/tmp
+.elif defined(TMPDIR)
+TMPDIR:= ${TMPDIR}/uid${.MAKE.UID}
+.else
+TMPDIR:= /tmp/uid${.MAKE.UID}
+.endif
+# make sure it exists
+.if !exist(${TMPDIR})
+_!= mkdir -p ${TMPDIR}
+.endif
+# and clean it up - outside the context of
+# any target that might be using it.
+.END: rm-tmpdir
+rm-tmpdir: .NOMETA
+ @rm -rf ${TMPDIR}
+
+# Each test is in a sub-makefile.
+# Keep the list sorted.
+# Any test that is commented out must be ignored in
+# src/tests/usr.bin/make/t_make.sh as well.
+#TESTS+= archive
+#TESTS+= archive-suffix
+TESTS+= cmd-errors
+TESTS+= cmd-errors-jobs
+TESTS+= cmd-errors-lint
+TESTS+= cmd-interrupt
+TESTS+= cmdline
+TESTS+= cmdline-redirect-stdin
+TESTS+= cmdline-undefined
+TESTS+= comment
+TESTS+= compat-error
+TESTS+= cond-cmp-numeric
+TESTS+= cond-cmp-numeric-eq
+TESTS+= cond-cmp-numeric-ge
+TESTS+= cond-cmp-numeric-gt
+TESTS+= cond-cmp-numeric-le
+TESTS+= cond-cmp-numeric-lt
+TESTS+= cond-cmp-numeric-ne
+TESTS+= cond-cmp-string
+TESTS+= cond-cmp-unary
+TESTS+= cond-eof
+TESTS+= cond-func
+TESTS+= cond-func-commands
+TESTS+= cond-func-defined
+TESTS+= cond-func-empty
+TESTS+= cond-func-exists
+TESTS+= cond-func-make
+TESTS+= cond-func-make-main
+TESTS+= cond-func-target
+TESTS+= cond-late
+TESTS+= cond-op
+TESTS+= cond-op-and
+TESTS+= cond-op-and-lint
+TESTS+= cond-op-not
+TESTS+= cond-op-or
+TESTS+= cond-op-or-lint
+TESTS+= cond-op-parentheses
+TESTS+= cond-short
+TESTS+= cond-token-number
+TESTS+= cond-token-plain
+TESTS+= cond-token-string
+TESTS+= cond-token-var
+TESTS+= cond-undef-lint
+TESTS+= counter
+TESTS+= counter-append
+TESTS+= dep
+TESTS+= dep-colon
+TESTS+= dep-colon-bug-cross-file
+TESTS+= dep-double-colon
+TESTS+= dep-double-colon-indep
+TESTS+= dep-duplicate
+TESTS+= dep-exclam
+TESTS+= dep-none
+TESTS+= dep-op-missing
+TESTS+= dep-percent
+TESTS+= dep-var
+TESTS+= dep-wildcards
+TESTS+= depsrc
+TESTS+= depsrc-end
+TESTS+= depsrc-exec
+TESTS+= depsrc-ignore
+TESTS+= depsrc-made
+TESTS+= depsrc-make
+TESTS+= depsrc-meta
+TESTS+= depsrc-nometa
+TESTS+= depsrc-nometa_cmp
+TESTS+= depsrc-nopath
+TESTS+= depsrc-notmain
+TESTS+= depsrc-optional
+TESTS+= depsrc-phony
+TESTS+= depsrc-precious
+TESTS+= depsrc-recursive
+TESTS+= depsrc-silent
+TESTS+= depsrc-use
+TESTS+= depsrc-usebefore
+TESTS+= depsrc-usebefore-double-colon
+TESTS+= depsrc-wait
+TESTS+= deptgt
+TESTS+= deptgt-begin
+TESTS+= deptgt-begin-fail
+TESTS+= deptgt-begin-fail-indirect
+TESTS+= deptgt-default
+TESTS+= deptgt-delete_on_error
+TESTS+= deptgt-end
+TESTS+= deptgt-end-fail
+TESTS+= deptgt-end-fail-all
+TESTS+= deptgt-end-fail-indirect
+TESTS+= deptgt-end-jobs
+TESTS+= deptgt-error
+TESTS+= deptgt-ignore
+TESTS+= deptgt-interrupt
+TESTS+= deptgt-main
+TESTS+= deptgt-makeflags
+TESTS+= deptgt-no_parallel
+TESTS+= deptgt-nopath
+TESTS+= deptgt-notparallel
+TESTS+= deptgt-objdir
+TESTS+= deptgt-order
+TESTS+= deptgt-path
+TESTS+= deptgt-path-suffix
+TESTS+= deptgt-phony
+TESTS+= deptgt-posix
+TESTS+= deptgt-precious
+TESTS+= deptgt-shell
+TESTS+= deptgt-silent
+TESTS+= deptgt-silent-jobs
+TESTS+= deptgt-stale
+TESTS+= deptgt-suffixes
+TESTS+= dir
+TESTS+= dir-expand-path
+TESTS+= directive
+TESTS+= directive-dinclude
+TESTS+= directive-elif
+TESTS+= directive-elifdef
+TESTS+= directive-elifmake
+TESTS+= directive-elifndef
+TESTS+= directive-elifnmake
+TESTS+= directive-else
+TESTS+= directive-endfor
+TESTS+= directive-endif
+TESTS+= directive-error
+TESTS+= directive-export
+TESTS+= directive-export-env
+TESTS+= directive-export-impl
+TESTS+= directive-export-gmake
+TESTS+= directive-export-literal
+TESTS+= directive-for
+TESTS+= directive-for-break
+TESTS+= directive-for-empty
+TESTS+= directive-for-errors
+TESTS+= directive-for-escape
+TESTS+= directive-for-generating-endif
+TESTS+= directive-for-if
+TESTS+= directive-for-lines
+TESTS+= directive-for-null
+TESTS+= directive-hyphen-include
+TESTS+= directive-if
+TESTS+= directive-if-nested
+TESTS+= directive-ifdef
+TESTS+= directive-ifmake
+TESTS+= directive-ifndef
+TESTS+= directive-ifnmake
+TESTS+= directive-include
+TESTS+= directive-include-fatal
+TESTS+= directive-include-guard
+TESTS+= directive-info
+TESTS+= directive-misspellings
+TESTS+= directive-sinclude
+TESTS+= directive-undef
+TESTS+= directive-unexport
+TESTS+= directive-unexport-env
+TESTS+= directive-warning
+TESTS+= dollar
+TESTS+= doterror
+TESTS+= dotwait
+TESTS+= error
+TESTS+= # escape # broken by reverting POSIX changes
+TESTS+= export
+TESTS+= export-all
+TESTS+= export-env
+TESTS+= export-variants
+TESTS+= gnode-submake
+TESTS+= hanoi-include
+TESTS+= impsrc
+TESTS+= include-main
+TESTS+= job-flags
+TESTS+= job-output-long-lines
+TESTS+= job-output-null
+TESTS+= jobs-empty-commands
+TESTS+= jobs-empty-commands-error
+TESTS+= jobs-error-indirect
+TESTS+= jobs-error-nested
+TESTS+= jobs-error-nested-make
+TESTS+= lint
+TESTS+= make-exported
+TESTS+= meta-cmd-cmp
+TESTS+= moderrs
+TESTS+= modmisc
+.if ${.MAKE.UID} > 0
+TESTS+= objdir-writable
+.endif
+TESTS+= opt
+TESTS+= opt-backwards
+TESTS+= opt-chdir
+TESTS+= opt-debug
+TESTS+= opt-debug-all
+TESTS+= opt-debug-archive
+TESTS+= opt-debug-curdir
+TESTS+= opt-debug-cond
+TESTS+= opt-debug-dir
+TESTS+= opt-debug-errors
+TESTS+= opt-debug-errors-jobs
+TESTS+= opt-debug-file
+TESTS+= opt-debug-for
+TESTS+= opt-debug-graph1
+TESTS+= opt-debug-graph2
+TESTS+= opt-debug-graph3
+TESTS+= opt-debug-hash
+TESTS+= opt-debug-jobs
+TESTS+= opt-debug-lint
+TESTS+= opt-debug-loud
+TESTS+= opt-debug-meta
+TESTS+= opt-debug-making
+TESTS+= opt-debug-no-rm
+TESTS+= opt-debug-parse
+TESTS+= opt-debug-suff
+TESTS+= opt-debug-targets
+TESTS+= opt-debug-varraw
+TESTS+= opt-debug-var
+TESTS+= opt-debug-x-trace
+TESTS+= opt-define
+TESTS+= opt-env
+TESTS+= opt-file
+TESTS+= opt-ignore
+TESTS+= opt-include-dir
+TESTS+= opt-jobs
+TESTS+= opt-jobs-internal
+TESTS+= opt-jobs-no-action
+TESTS+= opt-keep-going
+TESTS+= opt-keep-going-indirect
+TESTS+= opt-keep-going-multiple
+TESTS+= opt-m-include-dir
+TESTS+= opt-no-action
+TESTS+= opt-no-action-at-all
+TESTS+= opt-no-action-runflags
+TESTS+= opt-no-action-touch
+TESTS+= opt-query
+TESTS+= opt-raw
+TESTS+= opt-silent
+TESTS+= opt-touch
+TESTS+= opt-touch-jobs
+TESTS+= opt-tracefile
+TESTS+= opt-var-expanded
+TESTS+= opt-var-literal
+TESTS+= opt-version
+TESTS+= opt-warnings-as-errors
+TESTS+= opt-where-am-i
+TESTS+= opt-x-reduce-exported
+TESTS+= order
+TESTS+= parse
+TESTS+= parse-var
+TESTS+= phony-end
+TESTS+= posix
+TESTS+= # posix1 # broken by reverting POSIX changes
+TESTS+= recursive
+TESTS+= sh
+TESTS+= sh-dots
+TESTS+= sh-errctl
+TESTS+= sh-flags
+TESTS+= sh-jobs
+TESTS+= sh-jobs-error
+TESTS+= sh-leading-at
+TESTS+= sh-leading-hyphen
+TESTS+= sh-leading-plus
+TESTS+= sh-meta-chars
+TESTS+= sh-multi-line
+TESTS+= sh-single-line
+TESTS+= shell-csh
+TESTS+= shell-custom
+.if exists(/bin/ksh)
+TESTS+= shell-ksh
+.endif
+TESTS+= shell-sh
+TESTS+= suff
+TESTS+= suff-add-later
+TESTS+= suff-clear-regular
+TESTS+= suff-clear-single
+TESTS+= suff-incomplete
+TESTS+= suff-lookup
+TESTS+= suff-main
+TESTS+= suff-main-several
+TESTS+= suff-phony
+TESTS+= suff-rebuild
+TESTS+= suff-self
+TESTS+= suff-transform-debug
+TESTS+= suff-transform-endless
+TESTS+= suff-transform-expand
+TESTS+= suff-transform-select
+TESTS+= suff-use
+TESTS+= sunshcmd
+TESTS+= ternary
+TESTS+= unexport
+TESTS+= unexport-env
+TESTS+= use-inference
+TESTS+= var-readonly
+TESTS+= var-scope
+TESTS+= var-scope-cmdline
+TESTS+= var-scope-env
+TESTS+= var-scope-global
+TESTS+= var-scope-local
+TESTS+= var-scope-local-legacy
+TESTS+= var-eval-short
+TESTS+= var-op
+TESTS+= var-op-append
+TESTS+= var-op-assign
+TESTS+= var-op-default
+TESTS+= var-op-expand
+TESTS+= var-op-shell
+TESTS+= var-op-sunsh
+TESTS+= var-recursive
+TESTS+= varcmd
+TESTS+= vardebug
+TESTS+= varfind
+TESTS+= varmisc
+TESTS+= varmod
+TESTS+= varmod-assign
+TESTS+= varmod-assign-shell
+TESTS+= varmod-defined
+TESTS+= varmod-edge
+TESTS+= varmod-exclam-shell
+TESTS+= varmod-extension
+TESTS+= varmod-gmtime
+TESTS+= varmod-hash
+TESTS+= varmod-head
+TESTS+= varmod-ifelse
+TESTS+= varmod-indirect
+TESTS+= varmod-l-name-to-value
+TESTS+= varmod-localtime
+TESTS+= varmod-loop
+TESTS+= varmod-loop-delete
+TESTS+= varmod-loop-varname
+TESTS+= varmod-match
+TESTS+= varmod-match-escape
+TESTS+= varmod-mtime
+TESTS+= varmod-no-match
+TESTS+= varmod-order
+TESTS+= varmod-order-numeric
+TESTS+= varmod-order-reverse
+TESTS+= varmod-order-shuffle
+TESTS+= varmod-order-string
+TESTS+= varmod-path
+TESTS+= varmod-quote
+TESTS+= varmod-quote-dollar
+TESTS+= varmod-range
+TESTS+= varmod-remember
+TESTS+= varmod-root
+TESTS+= varmod-select-words
+TESTS+= varmod-shell
+TESTS+= varmod-subst
+TESTS+= varmod-subst-regex
+TESTS+= varmod-sun-shell
+TESTS+= varmod-sysv
+TESTS+= varmod-tail
+TESTS+= varmod-to-abs
+TESTS+= varmod-to-lower
+TESTS+= varmod-to-many-words
+TESTS+= varmod-to-one-word
+TESTS+= varmod-to-separator
+TESTS+= varmod-to-title
+TESTS+= varmod-to-upper
+TESTS+= varmod-undefined
+TESTS+= varmod-unique
+TESTS+= varname
+TESTS+= varname-dollar
+TESTS+= varname-dot-alltargets
+TESTS+= varname-dot-curdir
+TESTS+= varname-dot-includes
+TESTS+= varname-dot-includedfromdir
+TESTS+= varname-dot-includedfromfile
+TESTS+= varname-dot-libs
+TESTS+= varname-dot-make-dependfile
+TESTS+= varname-dot-make-expand_variables
+TESTS+= varname-dot-make-exported
+TESTS+= varname-dot-make-jobs
+TESTS+= varname-dot-make-jobs-prefix
+TESTS+= varname-dot-make-level
+TESTS+= varname-dot-make-makefile_preference
+TESTS+= varname-dot-make-makefiles
+TESTS+= varname-dot-make-meta-bailiwick
+TESTS+= varname-dot-make-meta-created
+TESTS+= varname-dot-make-meta-files
+.if ${.MAKE.PATH_FILEMON:Uno:Nktrace:N/dev*} == "" && ${TMPDIR:N/tmp*:N/var/tmp*} != ""
+# these tests will not work if TMPDIR is or is a subdir of
+# /tmp or /var/tmp
+.if ${.MAKE.PATH_FILEMON:N/dev/*} != "" || exists(${.MAKE.PATH_FILEMON})
+TESTS+= varname-dot-make-meta-ignore_filter
+TESTS+= varname-dot-make-meta-ignore_paths
+TESTS+= varname-dot-make-meta-ignore_patterns
+TESTS+= varname-dot-make-path_filemon
+.else
+.warning Skipping tests that require ${.MAKE.PATH_FILEMON}
+.endif
+.endif
+TESTS+= varname-dot-make-meta-prefix
+TESTS+= varname-dot-make-mode
+TESTS+= varname-dot-make-pid
+TESTS+= varname-dot-make-ppid
+TESTS+= varname-dot-make-save_dollars
+TESTS+= varname-dot-makeflags
+TESTS+= varname-dot-makeoverrides
+TESTS+= varname-dot-newline
+TESTS+= varname-dot-objdir
+TESTS+= varname-dot-parsedir
+TESTS+= varname-dot-parsefile
+TESTS+= varname-dot-path
+TESTS+= varname-dot-shell
+TESTS+= varname-dot-suffixes
+TESTS+= varname-dot-targets
+TESTS+= varname-empty
+TESTS+= varname-make
+TESTS+= varname-make_print_var_on_error
+TESTS+= varname-make_print_var_on_error-jobs
+TESTS+= varname-makefile
+TESTS+= varname-makeflags
+TESTS+= varname-pwd
+TESTS+= varname-vpath
+TESTS+= varparse-dynamic
+TESTS+= varparse-errors
+TESTS+= varparse-mod
+TESTS+= varparse-undef-partial
+
+# some shells have quirks
+_shell:= ${.SHELL:tA:T}
+.if ${_shell} == "dash"
+# dash fails -x output
+BROKEN_TESTS+= opt-debug-x-trace
+.elif ${_shell:N*ksh*} == ""
+BROKEN_TESTS+= \
+ deptgt-silent-jobs \
+ job-flags \
+ job-output-long-lines \
+ opt-debug-x-trace \
+ sh-flags \
+ var-op-shell \
+
+.if ${_shell:Nmksh} == ""
+# more broken that pdksh
+BROKEN_TESTS+= \
+ opt-jobs-no-action \
+ sh-errctl \
+ sh-leading-hyphen \
+
+.endif
+.endif
+
+.if ${UTC_1:Uno} == ""
+# this will not work if UTC_1 is set empty
+BROKEN_TESTS+= varmod-localtime
+.endif
+
+.if ${.MAKE.OS:NDarwin} == ""
+BROKEN_TESTS+= shell-ksh
+.endif
+
+.if ${.MAKE.OS:NIRIX*} == ""
+BROKEN_TESTS+= \
+ cmd-interrupt \
+ deptgt-interrupt \
+ job-output-null \
+ opt-chdir \
+ opt-debug-x-trace \
+ sh-leading-hyphen \
+
+.endif
+
+.if ${.MAKE.OS} == "SCO_SV"
+BROKEN_TESTS+= \
+ opt-debug-graph[23] \
+ varmod-localtime \
+ varmod-to-separator \
+
+.if ${_shell} == "bash"
+BROKEN_TESTS+= job-output-null
+.else
+BROKEN_TESTS+= \
+ cmd-interrupt \
+ job-flags \
+
+.endif
+.endif
+
+# Some tests just do not work on some platforms or environments
+# so allow for some filtering.
+.if !empty(BROKEN_TESTS)
+.warning Skipping broken tests: ${BROKEN_TESTS:O:u}
+TESTS:= ${TESTS:${BROKEN_TESTS:S,^,N,:ts:}}
+.endif
+
+# Ideas for more tests:
+# char-0020-space.mk
+# char-005C-backslash.mk
+# escape-cond-str.mk
+# escape-cond-func-arg.mk
+# escape-varmod.mk
+# escape-varmod-define.mk
+# escape-varmod-match.mk
+# escape-varname.mk
+# escape-varassign-varname.mk
+# escape-varassign-varname-cmdline.mk
+# escape-varassign-value.mk
+# escape-varassign-value-cmdline.mk
+# escape-dependency-source.mk
+# escape-dependency-target.mk
+# escape-for-varname.mk
+# escape-for-item.mk
+# posix-*.mk (see posix.mk and posix1.mk)
+
+# Additional environment variables for some of the tests.
+# The base environment is -i PATH="$PATH".
+ENV.depsrc-optional+= TZ=UTC
+ENV.deptgt-phony+= MAKESYSPATH=.
+ENV.directive-undef= ENV_VAR=env-value
+ENV.opt-env= FROM_ENV=value-from-env
+ENV.opt-m-include-dir= ${MAKEOBJDIR:DMAKEOBJDIR=${MAKEOBJDIR}}
+ENV.varmisc= FROM_ENV=env
+ENV.varmisc+= FROM_ENV_BEFORE=env
+ENV.varmisc+= FROM_ENV_AFTER=env
+ENV.varmod-localtime+= TZ=${UTC_1:UEurope/Berlin}
+ENV.varname-vpath+= VPATH=varname-vpath.dir:varname-vpath.dir2
+
+# Override make flags for some of the tests; default is -k.
+# If possible, write ".MAKEFLAGS: -dv" in the test .mk file instead of
+# settings FLAGS.test=-dv here, since that is closer to the test code.
+FLAGS.cond-func-make= via-cmdline
+FLAGS.doterror= # none, especially not -k
+FLAGS.jobs-error-indirect= # none, especially not -k
+FLAGS.jobs-error-nested= # none, especially not -k
+FLAGS.jobs-error-nested-make= # none, especially not -k
+FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmdline-plain'
+
+# Some tests need extra postprocessing.
+SED_CMDS.deptgt-phony= ${STD_SED_CMDS.dd}
+SED_CMDS.dir= ${STD_SED_CMDS.dd}
+SED_CMDS.directive-include-guard= \
+ -e '/\.MAKEFLAGS/d' \
+ -e '/^Parsing .*:[1-9][0-9]*:/d' \
+ -e '/^SetFilenameVars:/d' \
+ -e '/^ParseDependency/d' \
+ -e '/^ParseEOF:/d'
+SED_CMDS.export= -e '/^[^=_A-Za-z0-9]*=/d'
+.if ${.MAKE.OS:NCygwin} == ""
+SED_CMDS.export+= -e '/^WINDIR=/d' -e '/^SYSTEMROOT=/d'
+.endif
+SED_CMDS.export-all= ${SED_CMDS.export}
+SED_CMDS.export-env= ${SED_CMDS.export}
+SED_CMDS.cmdline= -e 's,uid${.MAKE.UID}/,,'
+SED_CMDS.job-output-long-lines= \
+ ${:D Job separators on their own line are ok. } \
+ -e '/^--- job-[ab] ---$$/d' \
+ ${:D Plain output lines are ok as well. } \
+ ${:D They may come in multiples of 1024 or as 10000. } \
+ -e '/^aa*$$/d' \
+ -e '/^bb*$$/d' \
+ ${:D The following lines should rather not occur since the job } \
+ ${:D marker should always be at the beginning of the line. } \
+ -e '/^aa*--- job-b ---$$/d' \
+ -e '/^bb*--- job-a ---$$/d'
+SED_CMDS.opt-chdir= -e 's,\(nonexistent\).[1-9][0-9]*,\1,' \
+ -e '/name/s,file,File,' \
+ -e 's,no such,No such,' \
+ -e 's,Filename,File name,'
+
+# meta line numbers can vary based on filemon implementation
+SED_CMDS.meta-ignore= -e 's,\(\.meta:\) [1-9][0-9]*:,\1 <line>:,'
+SED_CMDS.opt-debug-graph1= ${STD_SED_CMDS.dg1}
+SED_CMDS.opt-debug-graph2= ${STD_SED_CMDS.dg2}
+SED_CMDS.opt-debug-graph3= ${STD_SED_CMDS.dg3}
+SED_CMDS.opt-debug-hash= -e 's,\(entries\)=[1-9][0-9],\1=<entries>,'
+SED_CMDS.opt-debug-jobs= -e 's,([0-9][0-9]*),(<pid>),'
+SED_CMDS.opt-debug-jobs+= -e 's,pid [0-9][0-9]*,pid <pid>,'
+SED_CMDS.opt-debug-jobs+= -e 's,Process [0-9][0-9]*,Process <pid>,'
+SED_CMDS.opt-debug-jobs+= -e 's,JobFinish: [0-9][0-9]*,JobFinish: <pid>,'
+SED_CMDS.opt-debug-jobs+= -e 's,Command: ${.SHELL:T},Command: <shell>,'
+# The "-q" may be there or not, see jobs.c, variable shells.
+SED_CMDS.opt-debug-jobs+= -e 's,^\(.Command: <shell>\) -q,\1,'
+SED_CMDS.opt-debug-lint+= ${STD_SED_CMDS.regex}
+SED_CMDS.opt-jobs-no-action= ${STD_SED_CMDS.hide-from-output}
+SED_CMDS.opt-no-action-runflags= ${STD_SED_CMDS.hide-from-output}
+SED_CMDS.opt-where-am-i= -e '/usr.obj/d'
+# For Compat_RunCommand, useShell == false.
+SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,<not found: ...>,'
+# For Compat_RunCommand, useShell == true.
+SED_CMDS.sh-dots+= -e 's,^make: exec(\(.*\)) failed (.*)$$,<not found: \1>,'
+SED_CMDS.sh-dots+= -e 's,^\(\*\*\* Error code \)[1-9][0-9]*,\1<nonzero>,'
+SED_CMDS.sh-errctl= ${STD_SED_CMDS.dj}
+SED_CMDS.sh-flags= ${STD_SED_CMDS.hide-from-output}
+SED_CMDS.shell-csh= ${STD_SED_CMDS.white-space}
+SED_CMDS.sh-leading-hyphen= ${STD_SED_CMDS.shell}
+SED_CMDS.suff-main+= ${STD_SED_CMDS.dg1}
+SED_CMDS.suff-main-several+= ${STD_SED_CMDS.dg1}
+SED_CMDS.suff-transform-debug+= ${STD_SED_CMDS.dg1}
+SED_CMDS.var-op-shell+= ${STD_SED_CMDS.shell}
+SED_CMDS.var-op-shell+= -e '/command/s,No such.*,not found,'
+SED_CMDS.var-op-shell+= ${STD_SED_CMDS.white-space}
+SED_CMDS.vardebug+= -e 's,${.SHELL},</path/to/shell>,'
+SED_CMDS.varmod-mtime+= -e "s,\(.*\)': .*,\1': <ENOENT>,"
+SED_CMDS.varmod-subst-regex+= ${STD_SED_CMDS.regex}
+SED_CMDS.varparse-errors+= ${STD_SED_CMDS.timestamp}
+SED_CMDS.varname-dot-make-meta-ignore_filter+= ${SED_CMDS.meta-ignore}
+SED_CMDS.varname-dot-make-meta-ignore_paths+= ${SED_CMDS.meta-ignore}
+SED_CMDS.varname-dot-make-meta-ignore_patterns+= ${SED_CMDS.meta-ignore}
+SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
+SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,'
+SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g'
+SED_CMDS.varname-dot-shell+= -e 's,"/[^" ]*","(details omitted)",g'
+SED_CMDS.varname-dot-shell+= -e 's,\[/[^] ]*\],[(details omitted)],g'
+SED_CMDS.varname-empty= ${.OBJDIR .PARSEDIR .PATH .SHELL .SYSPATH:L:@v@-e '/\\$v/d'@}
+
+# Some tests need an additional round of postprocessing.
+POSTPROC.depsrc-wait= sed -e '/^---/d' -e 's,^\(: Making 3[abc]\)[123]$$,\1,'
+POSTPROC.deptgt-suffixes= awk '/^\#\*\*\* Suffixes/,/^never-stop/'
+POSTPROC.gnode-submake= awk '/Input graph/, /^$$/'
+POSTPROC.varname-dot-make-mode= sed 's,^\(: Making [abc]\)[123]$$,\1,'
+
+# Some tests reuse other tests, which makes them unnecessarily fragile.
+export-all.rawout: export.mk
+unexport.rawout: export.mk
+unexport-env.rawout: export.mk
+
+# End of the configuration section.
+
+# Some standard sed commands, to be used in the SED_CMDS above.
+
+# In tests that use the debugging option -dd, ignore debugging output that is
+# only logged in -DCLEANUP mode.
+STD_SED_CMDS.dd= -e '/^OpenDirs_Done:/d'
+STD_SED_CMDS.dd+= -e '/^CachedDir /d'
+STD_SED_CMDS.dd+= -e 's, ${DEFSYSPATH:U/usr/share/mk} , <defsyspath> ,'
+
+# Omit details such as process IDs from the output of the -dg1 option.
+STD_SED_CMDS.dg1= -e '/\#.* \.$$/d'
+STD_SED_CMDS.dg1+= -e '/\.MAKE.PATH_FILEMON/d'
+STD_SED_CMDS.dg1+= -e '/^\#.*\/mk/d'
+STD_SED_CMDS.dg1+= -e 's, ${DEFSYSPATH:U/usr/share/mk}$$, <defsyspath>,'
+STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.[A-Z_]* *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e 's,^\(\.MAKE\.JOBS\.C *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e 's,^\(MACHINE[_ARCH]* *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e 's,^\(MAKE *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e 's,^\(\.SHELL *=\) .*,\1 <details omitted>,'
+STD_SED_CMDS.dg1+= -e '/\.SYSPATH/d'
+
+STD_SED_CMDS.dg2= ${STD_SED_CMDS.dg1}
+STD_SED_CMDS.dg2+= -e 's,\(last modified\) ..:..:.. ... ..\, ....,\1 <timestamp>,'
+STD_SED_CMDS.dg3= ${STD_SED_CMDS.dg2}
+
+# Omit details such as process IDs from the output of the -dj option.
+STD_SED_CMDS.dj= \
+ -e '/Process/d;/JobFinish:/d' \
+ -e 's,^\(Job_TokenWithdraw\)([0-9]*),\1(<pid>),' \
+ -e 's,^([0-9][0-9]*) \(withdrew token\),(<pid>) \1,' \
+ -e 's, \(pid\) [0-9][0-9]*, \1 <pid>,' \
+ -e 's,^\( Command:\) .*,\1 <shell>,'
+
+# Reduce the noise for tests running with the -n option, since there is no
+# other way to suppress the echoing of the commands.
+STD_SED_CMDS.hide-from-output= \
+ -e '/^echo hide-from-output/d' \
+ -e 's,hide-from-output ,,' \
+ -e 's,hide-from-output,,'
+
+# Normalize the output for error messages from the shell.
+#
+# $shell -c '...'
+# NetBSD sh ...: not found
+# NetBSD ksh ksh: ...: not found
+# bash 5.0.18 bash: ...: command not found
+# bash 5.1.0 bash: line 1: ...: command not found
+# dash dash: 1: ...: not found
+#
+# $shell -c '< /nonexistent'
+# NetBSD sh sh: cannot open /nonexistent: no such file
+# NetBSD ksh ksh: cannot open /nonexistent: No such file or directory
+# bash 5.0.18 bash: /nonexistent: No such file or directory
+# bash 5.1.0 bash: line 1: /nonexistent: No such file or directory
+# dash dash: 1: cannot open /nonexistent: No such file
+#
+# echo '< /nonexistent' | $shell
+# NetBSD sh sh: cannot open /nonexistent: no such file
+# NetBSD ksh ksh: <stdin>[1]: cannot open /nonexistent: No such file or directory
+# bash 5.0.18 bash: line 1: /nonexistent: No such file or directory
+# bash 5.1.0 bash: line 1: /nonexistent: No such file or directory
+# dash dash: 1: cannot open /nonexistent: No such file
+#
+STD_SED_CMDS.shell+= -e 's,^${.SHELL},${.SHELL:T},'
+STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: line [0-9][0-9]*: ,,'
+STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: [0-9][0-9]*: ,,'
+STD_SED_CMDS.shell+= -e 's,^${.SHELL:T}: ,,'
+STD_SED_CMDS.shell+= -e 's,: command not found,: not found,'
+
+STD_SED_CMDS.white-space= -e 's, *, ,g' -e 's, *$$,,'
+
+# The actual error messages for a failed regcomp or regexec differ between the
+# implementations.
+STD_SED_CMDS.regex= \
+ -e 's,\(Regex compilation error:\).*,\1 (details omitted),'
+
+# Normalize timestamps from ':gmtime' or ':localtime' to '<timestamp>'.
+# See STD_SED_CMDS.dg2 for timestamps from the debug log.
+STD_SED_CMDS.timestamp= \
+ -e 's,[A-Z][a-z][a-z] [A-Z][a-z][a-z] [ 0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [12][0-9][0-9][0-9],<timestamp>,'
+
+# End of the configuration helpers section.
+
+.-include "Makefile.inc"
+.-include "Makefile.config"
+
+UNIT_TESTS:= ${srcdir}
+.PATH: ${UNIT_TESTS}
+
+.if ${USE_ABSOLUTE_TESTNAMES:Uno} == yes
+OUTFILES= ${TESTS:@test@${.CURDIR:tA}/${test}.out@}
+.else
+OUTFILES= ${TESTS:=.out}
+.endif
+
+all: ${OUTFILES}
+
+CLEANFILES= *.rawout *.out *.status *.tmp *.core *.tmp
+CLEANFILES+= obj*.[och] lib*.a # posix1.mk
+CLEANFILES+= issue* .[ab]* # suffixes.mk
+CLEANDIRS= dir dummy *.tmp # posix1.mk
+
+clean:
+ rm -rf ${CLEANDIRS}
+ rm -f ${CLEANFILES}
+
+TEST_MAKE?= ${.MAKE}
+TOOL_SED?= sed
+TOOL_TR?= tr
+TOOL_DIFF?= diff
+DIFF_FLAGS?= -u
+
+# ensure consistent results from sort(1)
+LC_ALL= C
+LANG= C
+.export LANG LC_ALL
+
+.if ${.MAKE.MODE:Unormal:Mmeta} != ""
+# we don't need the noise
+_MKMSG_TEST= :
+.endif
+
+# Some Linux systems such as Fedora have deprecated egrep in favor of grep -E.
+.if ${.MAKE.OS:NLinux} == ""
+EGREP= grep -E
+.endif
+# Keep the classical definition for all other systems. Just as the bmake code
+# is kept compatible with C90, the tests are kept compatible with systems that
+# are several decades old and don't follow modern POSIX standards.
+EGREP?= egrep
+
+MAKE_TEST_ENV= EGREP="${EGREP}"
+MAKE_TEST_ENV+= MALLOC_OPTIONS="JA" # for jemalloc 100
+MAKE_TEST_ENV+= MALLOC_CONF="junk:true" # for jemalloc 510
+MAKE_TEST_ENV+= TMPDIR=${TMPDIR}
+
+.if ${.MAKE.OS} == "NetBSD"
+LIMIT_RESOURCES?= ulimit -v 300000
+.endif
+LIMIT_RESOURCES?= :
+
+# Each test is run in a sub-make, to keep the tests from interfering with
+# each other, and because they use different environment variables and
+# command line options.
+.SUFFIXES: .mk .rawout .out
+.mk.rawout:
+ @${_MKMSG_TEST:Uecho '# test '} ${.PREFIX}
+ @set -eu; \
+ ${LIMIT_RESOURCES}; \
+ cd ${.OBJDIR}; \
+ env -i PATH="$$PATH" ${MAKE_TEST_ENV} ${ENV.${.PREFIX:T}} \
+ ${TEST_MAKE} \
+ -r -C ${.CURDIR} -f ${.IMPSRC} \
+ ${FLAGS.${.PREFIX:T}:U-k} \
+ > ${.TARGET}.tmp 2>&1 \
+ && status=$$? || status=$$?; \
+ echo $$status > ${.TARGET:R}.status
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+# Postprocess the test output to make the output platform-independent.
+#
+# Replace anything after 'stopped in' with unit-tests
+_SED_CMDS+= -e '/stopped/s, in /.*, in unit-tests,'
+# Allow the test files to be placed anywhere.
+_SED_CMDS+= -e 's,\(\.PARSEDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
+_SED_CMDS+= -e 's,\(\.INCLUDEDFROMDIR}\) = `'"/[^']*'"',\1 = <some-dir>,'
+_SED_CMDS+= -e 's,${TMPDIR},<tmpdir>,g' -e 's,${TMPDIR:tA},<tmpdir>,g'
+# canonicalize ${.OBJDIR} and ${.CURDIR}
+_SED_CMDS+= -e 's,${.CURDIR},<curdir>,g'
+.if ${.OBJDIR} != ${.CURDIR}
+# yes this is inaccurate but none of the tests expect <objdir> anywhere
+# which we get depending on how MAKEOBJDIR is set.
+_SED_CMDS+= -e 's,${.OBJDIR},<curdir>,g' -e 's,${.OBJDIR:tA},<curdir>,g'
+.endif
+# always pretend .MAKE was called 'make'
+_SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,'
+_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,'
+_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,'
+_SED_CMDS+= -e 's,${TEST_MAKE:T:S,.,\\.,g}\(\[[1-9][0-9]*\]:\),make\1,'
+_SED_CMDS+= -e 's,<curdir>/,,g'
+_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g'
+_SED_CMDS+= -e '/MAKE_VERSION/d'
+_SED_CMDS+= -e '/EGREP=/d'
+
+# on AT&T derived systems: false exits 255 not 1
+.if ${.MAKE.OS:N*BSD} != ""
+_SED_CMDS+= -e 's,\(Error code\) 255,\1 1,'
+.endif
+.if ${_shell:N*ksh*} == ""
+_SED_CMDS+= -e '/^set [+-]v/d'
+SED_CMDS.opt-debug-jobs+= -e 's,Command: ksh -v,Command: <shell>,'
+SED_CMDS.opt-debug-jobs+= -e 's,Command: <shell> -v,Command: <shell>,'
+.endif
+
+.rawout.out:
+ @${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} \
+ < ${.IMPSRC} > ${.TARGET}.tmp
+ @${POSTPROC.${.PREFIX:T}:D \
+ ${POSTPROC.${.PREFIX:T}} < ${.TARGET}.tmp > ${.TARGET}.post \
+ && mv ${.TARGET}.post ${.TARGET}.tmp}
+ @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+.if empty(DIFF_FLAGS)
+DIFF_ECHO= echo
+.else
+DIFF_ECHO= :
+.endif
+
+# Compare all output files
+test: ${OUTFILES} .PHONY
+ @failed= ; \
+ for test in ${TESTS}; do \
+ cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out && continue || \
+ ${DIFF_ECHO} diff ${UNIT_TESTS}/$${test}.exp $${test}.out; \
+ ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/$${test}.exp $${test}.out \
+ || failed="$${failed}$${failed:+ }$${test}" ; \
+ done ; \
+ if [ -n "$${failed}" ]; then \
+ echo "Failed tests: $${failed}" ; false ; \
+ else \
+ echo "All tests passed" ; \
+ lua=${LUA:Ulua} ; \
+ have_lua=$$("$$lua" -e 'print "yes"' 2>&1) ; \
+ if [ "$$have_lua" = "yes" -a -s ${.CURDIR}/check-expect.lua ]; then \
+ (cd ${.CURDIR} && "$$lua" ./check-expect.lua *.mk); \
+ fi; \
+ fi
+
+accept:
+ @for test in ${TESTS}; do \
+ cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \
+ || { echo "Replacing $${test}.exp" ; \
+ cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \
+ done
+
+.if exists(${TEST_MAKE})
+${TESTS:=.rawout}: ${TEST_MAKE}
+# in meta mode, we *know* if a target script is impacted
+# by a makefile change.
+.if ${.MAKE.MODE:Unormal:Mmeta} == ""
+${TESTS:=.rawout}: ${.PARSEDIR}/Makefile
+.endif
+.endif
+
+.-include <bsd.obj.mk>
diff --git a/usr.bin/bmake/unit-tests/Makefile.config b/usr.bin/bmake/unit-tests/Makefile.config
new file mode 100644
index 000000000000..cc8823fbb65a
--- /dev/null
+++ b/usr.bin/bmake/unit-tests/Makefile.config
@@ -0,0 +1,13 @@
+# This is a generated file, do NOT edit!
+# See contrib/bmake/bsd.after-import.mk
+#
+
+SRCTOP?= ${.CURDIR:H:H:H}
+
+# $Id: Makefile.config.in,v 1.4 2022/09/09 18:44:56 sjg Exp $
+
+srcdir= ${SRCTOP}/contrib/bmake/unit-tests
+EGREP= egrep
+TOOL_DIFF?= diff
+DIFF_FLAGS?= -u
+UTC_1= Europe/Berlin
diff --git a/usr.bin/brandelf/Makefile b/usr.bin/brandelf/Makefile
new file mode 100644
index 000000000000..8c80ff805311
--- /dev/null
+++ b/usr.bin/brandelf/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PROG= brandelf
+
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/brandelf/Makefile.depend b/usr.bin/brandelf/Makefile.depend
new file mode 100644
index 000000000000..c52f9192ab73
--- /dev/null
+++ b/usr.bin/brandelf/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/brandelf/Makefile.depend.options b/usr.bin/brandelf/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/brandelf/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/brandelf/brandelf.1 b/usr.bin/brandelf/brandelf.1
new file mode 100644
index 000000000000..aad5628b1f38
--- /dev/null
+++ b/usr.bin/brandelf/brandelf.1
@@ -0,0 +1,102 @@
+.\" Copyright 1997 John-Mark Gurney. 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 March 25, 2014
+.Dt BRANDELF 1
+.Os
+.Sh NAME
+.Nm brandelf
+.Nd mark an ELF binary for a specific ABI
+.Sh SYNOPSIS
+.Nm
+.Op Fl lv
+.Op Fl f Ar ELF_ABI_number
+.Op Fl t Ar string
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility marks an ELF binary to be run under a certain ABI for
+.Fx .
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f Ar ELF_ABI_number
+Forces branding with the supplied ELF ABI number.
+Incompatible with the
+.Fl t
+option.
+These values are assigned by SCO/USL.
+.It Fl l
+Writes the list of all known ELF types to the standard error.
+.It Fl v
+Turns on verbose output.
+.It Fl t Ar string
+Brands the given ELF binaries to be of the
+.Ar string
+ABI type.
+Currently supported ABIs are
+.Dq Li FreeBSD ,
+.Dq Li Linux ,
+and
+.Dq Li SVR4 .
+.It Ar file
+If
+.Fl t Ar string
+is given it will brand
+.Ar file
+to be of type
+.Ar string ,
+otherwise it will simply display the branding of
+.Ar file .
+.El
+.Sh EXIT STATUS
+Exit status is 0 on success, and 1 if the command
+fails if a file does not exist, is too short, fails to brand properly,
+or the brand requested is not one of the known types and the
+.Fl f
+option is not set.
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Bd -literal -offset indent
+brandelf file
+brandelf -t Linux file
+.Ed
+.Sh SEE ALSO
+.Rs
+.%A The Santa Cruz Operation, Inc.
+.%T System V Application Binary Interface
+.%D April 29, 1998 (DRAFT)
+.%U http://www.sco.com/developers/devspecs/
+.Re
+.Sh HISTORY
+The
+.Nm
+manual page first appeared in
+.Fx 2.2 .
+.Sh AUTHORS
+This manual page was written by
+.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
diff --git a/usr.bin/brandelf/brandelf.c b/usr.bin/brandelf/brandelf.c
new file mode 100644
index 000000000000..e99af06c428a
--- /dev/null
+++ b/usr.bin/brandelf/brandelf.c
@@ -0,0 +1,231 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2000, 2001 David O'Brien
+ * Copyright (c) 1996 Søren Schmidt
+ * 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
+ * in this position and unchanged.
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/elf_common.h>
+#include <sys/errno.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+static int elftype(const char *);
+static const char *iselftype(int);
+static void printelftypes(void);
+static void usage(void) __dead2;
+
+struct ELFtypes {
+ const char *str;
+ int value;
+};
+/* XXX - any more types? */
+static struct ELFtypes elftypes[] = {
+ { "FreeBSD", ELFOSABI_FREEBSD },
+ { "Linux", ELFOSABI_LINUX },
+ { "Solaris", ELFOSABI_SOLARIS },
+ { "SVR4", ELFOSABI_SYSV }
+};
+
+int
+main(int argc, char **argv)
+{
+
+ const char *strtype = "FreeBSD";
+ int ch, flags, retval, type;
+ bool change, force, listed;
+ fileargs_t *fa;
+ cap_rights_t rights;
+
+ type = ELFOSABI_FREEBSD;
+ retval = 0;
+ change = false;
+ force = false;
+ listed = false;
+
+ while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
+ switch (ch) {
+ case 'f':
+ if (change)
+ errx(1, "f option incompatible with t option");
+ force = true;
+ type = atoi(optarg);
+ if (errno == ERANGE || type < 0 || type > 255) {
+ warnx("invalid argument to option f: %s",
+ optarg);
+ usage();
+ }
+ break;
+ case 'l':
+ printelftypes();
+ listed = true;
+ break;
+ case 'v':
+ /* does nothing */
+ break;
+ case 't':
+ if (force)
+ errx(1, "t option incompatible with f option");
+ change = true;
+ strtype = optarg;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0) {
+ if (listed)
+ exit(0);
+ else {
+ warnx("no file(s) specified");
+ usage();
+ }
+ }
+
+ if (!force && (type = elftype(strtype)) == -1) {
+ warnx("invalid ELF type '%s'", strtype);
+ printelftypes();
+ usage();
+ }
+
+ flags = change || force ? O_RDWR : O_RDONLY;
+ cap_rights_init(&rights, CAP_READ, CAP_SEEK);
+ if (flags == O_RDWR)
+ cap_rights_set(&rights, CAP_WRITE);
+
+ fa = fileargs_init(argc, argv, flags, 0, &rights, FA_OPEN);
+ if (fa == NULL)
+ err(1, "unable to init casper");
+
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter_casper() < 0)
+ err(1, "unable to enter capability mode");
+
+ while (argc != 0) {
+ int fd;
+ char buffer[EI_NIDENT];
+
+ if ((fd = fileargs_open(fa, argv[0])) < 0) {
+ warn("error opening file %s", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+ if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
+ warnx("file '%s' too short", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+ if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
+ buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
+ warnx("file '%s' is not ELF format", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+ if (!change && !force) {
+ fprintf(stdout,
+ "File '%s' is of brand '%s' (%u).\n",
+ argv[0], iselftype(buffer[EI_OSABI]),
+ buffer[EI_OSABI]);
+ if (!iselftype(type)) {
+ warnx("ELF ABI Brand '%u' is unknown",
+ type);
+ printelftypes();
+ }
+ }
+ else {
+ buffer[EI_OSABI] = type;
+ lseek(fd, 0, SEEK_SET);
+ if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
+ warn("error writing %s %d", argv[0], fd);
+ retval = 1;
+ goto fail;
+ }
+ }
+fail:
+ close(fd);
+ argc--;
+ argv++;
+ }
+
+ fileargs_free(fa);
+ return (retval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n");
+ exit(1);
+}
+
+static const char *
+iselftype(int etype)
+{
+ size_t elfwalk;
+
+ for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
+ if (etype == elftypes[elfwalk].value)
+ return (elftypes[elfwalk].str);
+ return (0);
+}
+
+static int
+elftype(const char *elfstrtype)
+{
+ size_t elfwalk;
+
+ for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
+ if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
+ return (elftypes[elfwalk].value);
+ return (-1);
+}
+
+static void
+printelftypes(void)
+{
+ size_t elfwalk;
+
+ fprintf(stderr, "known ELF types are: ");
+ for (elfwalk = 0; elfwalk < nitems(elftypes); elfwalk++)
+ fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
+ elftypes[elfwalk].value);
+ fprintf(stderr, "\n");
+}
diff --git a/usr.bin/bsdcat/Makefile b/usr.bin/bsdcat/Makefile
new file mode 100644
index 000000000000..032207217be6
--- /dev/null
+++ b/usr.bin/bsdcat/Makefile
@@ -0,0 +1,29 @@
+.include <src.opts.mk>
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+_LIBARCHIVECONFDIR= ${SRCTOP}/lib/libarchive
+
+PROG= bsdcat
+BSDCAT_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.],,gp;q;}' \
+ ${_LIBARCHIVEDIR}/libarchive/archive.h
+
+.PATH: ${_LIBARCHIVEDIR}/cat
+SRCS= bsdcat.c cmdline.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+SRCS+= err.c
+
+CFLAGS+= -DBSDCAT_VERSION_STRING=\"${BSDCAT_VERSION_STRING}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\"
+CFLAGS+= -I${_LIBARCHIVEDIR}/cat -I${_LIBARCHIVEDIR}/libarchive_fe
+
+LIBADD= archive
+
+.if ${MK_ICONV} != "no"
+CFLAGS+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DICONV_CONST=const
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bsdcat/Makefile.depend b/usr.bin/bsdcat/Makefile.depend
new file mode 100644
index 000000000000..850d785a03af
--- /dev/null
+++ b/usr.bin/bsdcat/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bsdcat/tests/Makefile b/usr.bin/bsdcat/tests/Makefile
new file mode 100644
index 000000000000..c323da34e080
--- /dev/null
+++ b/usr.bin/bsdcat/tests/Makefile
@@ -0,0 +1,74 @@
+PACKAGE= tests
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR= ${TESTSDIR}
+
+PROGS+= bsdcat_test
+
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
+
+CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${_LIBARCHIVEDIR}/cat -I${_LIBARCHIVEDIR}/cat/test
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
+
+CFLAGS.test_utils.c+= -Wno-cast-align
+
+# Uncomment to link against dmalloc
+#LDADD+= -L/usr/local/lib -ldmalloc
+#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+
+.PATH: ${_LIBARCHIVEDIR}/cat/test
+TESTS_SRCS= \
+ test_0.c \
+ test_empty_gz.c \
+ test_empty_lz4.c \
+ test_empty_xz.c \
+ test_empty_zstd.c \
+ test_error.c \
+ test_error_mixed.c \
+ test_expand_Z.c \
+ test_expand_bz2.c \
+ test_expand_gz.c \
+ test_expand_lz4.c \
+ test_expand_mixed.c \
+ test_expand_plain.c \
+ test_expand_xz.c \
+ test_expand_zstd.c \
+ test_help.c \
+ test_stdin.c \
+ test_version.c
+
+SRCS.bsdcat_test= list.h \
+ ${TESTS_SRCS}
+
+.PATH: ${_LIBARCHIVEDIR}/test_utils
+SRCS.bsdcat_test+= test_main.c \
+ test_utils.c
+
+LIBADD.bsdcat_test= archive
+
+list.h: ${TESTS_SRCS} Makefile
+ @(cd ${_LIBARCHIVEDIR}/tar/test && \
+ grep -h DEFINE_TEST ${.ALLSRC:N*Makefile}) > ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+CLEANFILES+= list.h list.h.tmp
+
+${PACKAGE}FILES+= test_empty.gz.uu
+${PACKAGE}FILES+= test_empty.lz4.uu
+${PACKAGE}FILES+= test_empty.xz.uu
+${PACKAGE}FILES+= test_empty.zst.uu
+${PACKAGE}FILES+= test_expand.Z.uu
+${PACKAGE}FILES+= test_expand.bz2.uu
+${PACKAGE}FILES+= test_expand.gz.uu
+${PACKAGE}FILES+= test_expand.lz4.uu
+${PACKAGE}FILES+= test_expand.plain.uu
+${PACKAGE}FILES+= test_expand.xz.uu
+${PACKAGE}FILES+= test_expand.zst.uu
+
+.include <bsd.test.mk>
diff --git a/usr.bin/bsdcat/tests/Makefile.depend b/usr.bin/bsdcat/tests/Makefile.depend
new file mode 100644
index 000000000000..5f5ceeb3eee7
--- /dev/null
+++ b/usr.bin/bsdcat/tests/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bsdcat/tests/functional_test.sh b/usr.bin/bsdcat/tests/functional_test.sh
new file mode 100755
index 000000000000..efed232374e2
--- /dev/null
+++ b/usr.bin/bsdcat/tests/functional_test.sh
@@ -0,0 +1,55 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+SRCDIR=$(atf_get_srcdir)
+TESTER="${SRCDIR}/bsdcat_test"
+export BSDCAT=$(which bsdcat)
+
+check()
+{
+ local testcase=${1}; shift
+
+ # For some odd reason /bin/sh spuriously writes
+ # "write error on stdout" with some of the testcases
+ #
+ # Probably an issue with how they're written as it calls system(3) to
+ # clean up directories..
+ atf_check -e ignore -o ignore -s exit:0 ${TESTER} -d -r "${SRCDIR}" -v "${testcase}"
+}
+
+atf_init_test_cases()
+{
+ # Redirect stderr to stdout for the usage message because if you don't
+ # kyua list/kyua test will break:
+ # https://github.com/jmmv/kyua/issues/149
+ testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }')
+ for testcase in ${testcases}; do
+ atf_test_case ${testcase}
+ eval "${testcase}_body() { check ${testcase}; }"
+ atf_add_test_case ${testcase}
+ done
+}
diff --git a/usr.bin/bsddialog/Makefile b/usr.bin/bsddialog/Makefile
new file mode 100644
index 000000000000..24a75aaf2f96
--- /dev/null
+++ b/usr.bin/bsddialog/Makefile
@@ -0,0 +1,13 @@
+BSDDIALOG= ${SRCTOP}/contrib/bsddialog/utility
+.PATH: ${BSDDIALOG}
+
+PROG= bsddialog
+SRCS= bsddialog.c \
+ util_builders.c \
+ util_cli.c \
+ util_theme.c
+MAN= bsddialog.1
+CFLAGS+= -I${BSDDIALOG}/../lib
+LIBADD= bsddialog tinfow
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bsdiff/Makefile b/usr.bin/bsdiff/Makefile
new file mode 100644
index 000000000000..ed9dd0f8db5a
--- /dev/null
+++ b/usr.bin/bsdiff/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= bsdiff bspatch
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/bsdiff/Makefile.inc b/usr.bin/bsdiff/Makefile.inc
new file mode 100644
index 000000000000..01b5f23410c8
--- /dev/null
+++ b/usr.bin/bsdiff/Makefile.inc
@@ -0,0 +1 @@
+.include "../Makefile.inc"
diff --git a/usr.bin/bsdiff/bsdiff/Makefile b/usr.bin/bsdiff/bsdiff/Makefile
new file mode 100644
index 000000000000..7af4fc873e13
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/Makefile
@@ -0,0 +1,16 @@
+PROG= bsdiff
+
+# libdivsufsort configured with:
+# cmake -DCMAKE_BUILD_TYPE="Release" -DBUILD_DIVSUFSORT64=ON
+.PATH: ${SRCTOP}/contrib/libdivsufsort/lib
+CFLAGS+= -DHAVE_CONFIG_H=1 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+CFLAGS+= -D_LARGE_FILES -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS
+CFLAGS+= -D__STDC_LIMIT_MACROS -DBUILD_DIVSUFSORT64
+CFLAGS+= -I${SRCTOP}/contrib/libdivsufsort/include -I${.CURDIR}
+SRCS= divsufsort.c sssort.c trsort.c utils.c
+
+SRCS+= bsdiff.c
+
+LIBADD= bz2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bsdiff/bsdiff/Makefile.depend b/usr.bin/bsdiff/bsdiff/Makefile.depend
new file mode 100644
index 000000000000..cc83708e9dfd
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbz2 \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bsdiff/bsdiff/bsdiff.1 b/usr.bin/bsdiff/bsdiff/bsdiff.1
new file mode 100644
index 000000000000..3e79d9cb89b8
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/bsdiff.1
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright 2003-2005 Colin Percival
+.\" All rights reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted providing 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 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.
+.\"
+.Dd May 18, 2003
+.Dt BSDIFF 1
+.Os
+.Sh NAME
+.Nm bsdiff
+.Nd "generate a patch between two binary files"
+.Sh SYNOPSIS
+.Nm
+.Ar oldfile newfile patchfile
+.Sh DESCRIPTION
+The
+.Nm
+utility
+compares
+.Ar oldfile
+to
+.Ar newfile
+and writes to
+.Ar patchfile
+a binary patch suitable for use by
+.Xr bspatch 1 .
+When
+.Ar oldfile
+and
+.Ar newfile
+are two versions of an executable program, the
+patches produced are on average a factor of five smaller
+than those produced by any other binary patch tool known
+to the author.
+.Pp
+The
+.Nm
+utility
+uses memory equal to 17 times the size of
+.Ar oldfile ,
+and requires
+an absolute minimum working set size of 8 times the size of
+.Ar oldfile .
+.Sh SEE ALSO
+.Xr bspatch 1
+.Sh AUTHORS
+.An Colin Percival Aq Mt cperciva@FreeBSD.org
+.Sh BUGS
+The
+.Nm
+utility does not store the hashes of
+.Ar oldfile
+or
+.Ar newfile
+in
+.Ar patchfile .
+As a result, it is possible to apply a patch to the wrong file; this
+will usually produce garbage.
+It is recommended that users of
+.Nm
+store the hashes of
+.Ar oldfile
+and
+.Ar newfile
+and compare against them before and after applying
+.Ar patchfile .
diff --git a/usr.bin/bsdiff/bsdiff/bsdiff.c b/usr.bin/bsdiff/bsdiff/bsdiff.c
new file mode 100644
index 000000000000..06a8812308c8
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/bsdiff.c
@@ -0,0 +1,336 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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 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.
+ */
+
+#include <sys/types.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include "divsufsort64.h"
+#define saidx_t saidx64_t
+#define divsufsort divsufsort64
+
+#define MIN(x,y) (((x)<(y)) ? (x) : (y))
+
+static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
+{
+ off_t i;
+
+ for(i=0;(i<oldsize)&&(i<newsize);i++)
+ if(old[i]!=new[i]) break;
+
+ return i;
+}
+
+static off_t search(off_t *I,u_char *old,off_t oldsize,
+ u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
+{
+ off_t x,y;
+
+ if(en-st<2) {
+ x=matchlen(old+I[st],oldsize-I[st],new,newsize);
+ y=matchlen(old+I[en],oldsize-I[en],new,newsize);
+
+ if(x>y) {
+ *pos=I[st];
+ return x;
+ } else {
+ *pos=I[en];
+ return y;
+ }
+ }
+
+ x=st+(en-st)/2;
+ if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
+ return search(I,old,oldsize,new,newsize,x,en,pos);
+ } else {
+ return search(I,old,oldsize,new,newsize,st,x,pos);
+ };
+}
+
+static void offtout(off_t x,u_char *buf)
+{
+ off_t y;
+
+ if(x<0) y=-x; else y=x;
+
+ buf[0]=y%256;y-=buf[0];
+ y=y/256;buf[1]=y%256;y-=buf[1];
+ y=y/256;buf[2]=y%256;y-=buf[2];
+ y=y/256;buf[3]=y%256;y-=buf[3];
+ y=y/256;buf[4]=y%256;y-=buf[4];
+ y=y/256;buf[5]=y%256;y-=buf[5];
+ y=y/256;buf[6]=y%256;y-=buf[6];
+ y=y/256;buf[7]=y%256;
+
+ if(x<0) buf[7]|=0x80;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: bsdiff oldfile newfile patchfile\n");
+ exit(1);
+}
+
+int main(int argc,char *argv[])
+{
+ int fd;
+ u_char *old,*new;
+ off_t oldsize,newsize,xnewsize;
+ saidx_t *I;
+ off_t scan,pos,len;
+ off_t lastscan,lastpos,lastoffset;
+ off_t oldscore,scsc;
+ off_t s,Sf,lenf,Sb,lenb;
+ off_t overlap,Ss,lens;
+ off_t i;
+ off_t dblen,eblen;
+ u_char *db,*eb;
+ u_char buf[8];
+ u_char header[32];
+ FILE * pf;
+ BZFILE * pfbz2;
+ int bz2err;
+
+ if (argc != 4)
+ usage();
+
+ /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
+ that we never try to malloc(0) and get a NULL pointer */
+ if(((fd=open(argv[1],O_RDONLY|O_BINARY,0))<0) ||
+ ((oldsize=lseek(fd,0,SEEK_END))==-1))
+ err(1, "%s", argv[1]);
+
+ if (oldsize > SSIZE_MAX ||
+ (uintmax_t)oldsize >= SIZE_T_MAX / sizeof(off_t) ||
+ oldsize == OFF_MAX) {
+ errno = EFBIG;
+ err(1, "%s", argv[1]);
+ }
+
+ old = mmap(NULL, oldsize+1, PROT_READ, MAP_SHARED, fd, 0);
+ if (old == MAP_FAILED || close(fd) == -1)
+ err(1, "%s", argv[1]);
+
+ if(((I=malloc((oldsize+1)*sizeof(saidx_t)))==NULL)) err(1,NULL);
+
+ if(divsufsort(old, I, oldsize)) err(1, "divsufsort");
+
+ /* Allocate newsize+1 bytes instead of newsize bytes to ensure
+ that we never try to malloc(0) and get a NULL pointer */
+ if(((fd=open(argv[2],O_RDONLY|O_BINARY,0))<0) ||
+ ((newsize=lseek(fd,0,SEEK_END))==-1))
+ err(1, "%s", argv[2]);
+
+ if (newsize > SSIZE_MAX || (uintmax_t)newsize >= SIZE_T_MAX ||
+ newsize == OFF_MAX) {
+ errno = EFBIG;
+ err(1, "%s", argv[2]);
+ }
+
+ new = mmap(NULL, newsize+1, PROT_READ, MAP_SHARED, fd, 0);
+ if (new == MAP_FAILED || close(fd) == -1)
+ err(1, "%s", argv[2]);
+
+ if(((db=malloc(newsize+1))==NULL) ||
+ ((eb=malloc(newsize+1))==NULL)) err(1,NULL);
+ dblen=0;
+ eblen=0;
+
+ /* Create the patch file */
+ if ((pf = fopen(argv[3], "wb")) == NULL)
+ err(1, "%s", argv[3]);
+
+ /* Header is
+ 0 8 "BSDIFF40"
+ 8 8 length of bzip2ed ctrl block
+ 16 8 length of bzip2ed diff block
+ 24 8 length of new file */
+ /* File is
+ 0 32 Header
+ 32 ?? Bzip2ed ctrl block
+ ?? ?? Bzip2ed diff block
+ ?? ?? Bzip2ed extra block */
+ memcpy(header,"BSDIFF40",8);
+ offtout(0, header + 8);
+ offtout(0, header + 16);
+ offtout(newsize, header + 24);
+ if (fwrite(header, 32, 1, pf) != 1)
+ err(1, "fwrite(%s)", argv[3]);
+
+ /* Compute the differences, writing ctrl as we go */
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
+ scan=0;len=0;pos=0;
+ lastscan=0;lastpos=0;lastoffset=0;
+ while(scan<newsize) {
+ oldscore=0;
+
+ for(scsc=scan+=len;scan<newsize;scan++) {
+ len=search(I,old,oldsize,new+scan,newsize-scan,
+ 0,oldsize-1,&pos);
+
+ for(;scsc<scan+len;scsc++)
+ if((scsc+lastoffset<oldsize) &&
+ (old[scsc+lastoffset] == new[scsc]))
+ oldscore++;
+
+ if(((len==oldscore) && (len!=0)) ||
+ (len>oldscore+8)) break;
+
+ if((scan+lastoffset<oldsize) &&
+ (old[scan+lastoffset] == new[scan]))
+ oldscore--;
+ }
+
+ if((len!=oldscore) || (scan==newsize)) {
+ s=0;Sf=0;lenf=0;
+ for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
+ if(old[lastpos+i]==new[lastscan+i]) s++;
+ i++;
+ if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; }
+ }
+
+ lenb=0;
+ if(scan<newsize) {
+ s=0;Sb=0;
+ for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
+ if(old[pos-i]==new[scan-i]) s++;
+ if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }
+ }
+ }
+
+ if(lastscan+lenf>scan-lenb) {
+ overlap=(lastscan+lenf)-(scan-lenb);
+ s=0;Ss=0;lens=0;
+ for(i=0;i<overlap;i++) {
+ if(new[lastscan+lenf-overlap+i]==
+ old[lastpos+lenf-overlap+i]) s++;
+ if(new[scan-lenb+i]==
+ old[pos-lenb+i]) s--;
+ if(s>Ss) { Ss=s; lens=i+1; }
+ }
+
+ lenf+=lens-overlap;
+ lenb-=lens;
+ }
+
+ for(i=0;i<lenf;i++)
+ db[dblen+i]=new[lastscan+i]-old[lastpos+i];
+ for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
+ eb[eblen+i]=new[lastscan+lenf+i];
+
+ dblen+=lenf;
+ eblen+=(scan-lenb)-(lastscan+lenf);
+
+ offtout(lenf,buf);
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+ offtout((scan-lenb)-(lastscan+lenf),buf);
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+ offtout((pos-lenb)-(lastpos+lenf),buf);
+ BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+
+ lastscan=scan-lenb;
+ lastpos=pos-lenb;
+ lastoffset=pos-scan;
+ }
+ }
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
+
+ /* Compute size of compressed ctrl data */
+ if ((len = ftello(pf)) == -1)
+ err(1, "ftello");
+ offtout(len-32, header + 8);
+
+ /* Write compressed diff data */
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
+ BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
+
+ /* Compute size of compressed diff data */
+ if ((xnewsize = ftello(pf)) == -1)
+ err(1, "ftello");
+ offtout(xnewsize - len, header + 16);
+
+ /* Write compressed extra data */
+ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
+ errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
+ BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
+ BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
+ if (bz2err != BZ_OK)
+ errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
+
+ /* Seek to the beginning, write the header, and close the file */
+ if (fseeko(pf, 0, SEEK_SET))
+ err(1, "fseeko");
+ if (fwrite(header, 32, 1, pf) != 1)
+ err(1, "fwrite(%s)", argv[3]);
+ if (fclose(pf))
+ err(1, "fclose");
+
+ /* Free the memory we used */
+ free(db);
+ free(eb);
+ free(I);
+ munmap(old, oldsize+1);
+ munmap(new, newsize+1);
+
+ return 0;
+}
diff --git a/usr.bin/bsdiff/bsdiff/config.h b/usr.bin/bsdiff/bsdiff/config.h
new file mode 100644
index 000000000000..fb4e71261cd2
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/config.h
@@ -0,0 +1,81 @@
+/*
+ * config.h for libdivsufsort
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Define to the version of this package. **/
+#define PROJECT_VERSION_FULL "2.0.1-14-g5f60d6f"
+
+/** Define to 1 if you have the header files. **/
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_SYS_TYPES_H 1
+
+/** for WinIO **/
+/* #undef HAVE_IO_H */
+/* #undef HAVE_FCNTL_H */
+/* #undef HAVE__SETMODE */
+/* #undef HAVE_SETMODE */
+/* #undef HAVE__FILENO */
+/* #undef HAVE_FOPEN_S */
+/* #undef HAVE__O_BINARY */
+#ifndef HAVE__SETMODE
+# if HAVE_SETMODE
+# define _setmode setmode
+# define HAVE__SETMODE 1
+# endif
+# if HAVE__SETMODE && !HAVE__O_BINARY
+# define _O_BINARY 0
+# define HAVE__O_BINARY 1
+# endif
+#endif
+
+/** for inline **/
+#ifndef INLINE
+# define INLINE inline
+#endif
+
+/** for VC++ warning **/
+#ifdef _MSC_VER
+#pragma warning(disable: 4127)
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _CONFIG_H */
diff --git a/usr.bin/bsdiff/bsdiff/divsufsort64.h b/usr.bin/bsdiff/bsdiff/divsufsort64.h
new file mode 100644
index 000000000000..2f1c375ba45e
--- /dev/null
+++ b/usr.bin/bsdiff/bsdiff/divsufsort64.h
@@ -0,0 +1,180 @@
+/*
+ * divsufsort64.h for libdivsufsort64
+ * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef _DIVSUFSORT64_H
+#define _DIVSUFSORT64_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <inttypes.h>
+
+#ifndef DIVSUFSORT_API
+# ifdef DIVSUFSORT_BUILD_DLL
+# define DIVSUFSORT_API
+# else
+# define DIVSUFSORT_API
+# endif
+#endif
+
+/*- Datatypes -*/
+#ifndef SAUCHAR_T
+#define SAUCHAR_T
+typedef uint8_t sauchar_t;
+#endif /* SAUCHAR_T */
+#ifndef SAINT_T
+#define SAINT_T
+typedef int32_t saint_t;
+#endif /* SAINT_T */
+#ifndef SAIDX64_T
+#define SAIDX64_T
+typedef int64_t saidx64_t;
+#endif /* SAIDX64_T */
+#ifndef PRIdSAINT_T
+#define PRIdSAINT_T PRId32
+#endif /* PRIdSAINT_T */
+#ifndef PRIdSAIDX64_T
+#define PRIdSAIDX64_T PRId64
+#endif /* PRIdSAIDX64_T */
+
+
+/*- Prototypes -*/
+
+/**
+ * Constructs the suffix array of a given string.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The output array of suffixes.
+ * @param n The length of the given string.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+divsufsort64(const sauchar_t *T, saidx64_t *SA, saidx64_t n);
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @return The primary index if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saidx64_t
+divbwt64(const sauchar_t *T, sauchar_t *U, saidx64_t *A, saidx64_t n);
+
+/**
+ * Returns the version of the divsufsort library.
+ * @return The version number string.
+ */
+DIVSUFSORT_API
+const char *
+divsufsort64_version(void);
+
+
+/**
+ * Constructs the burrows-wheeler transformed string of a given string and suffix array.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param SA[0..n-1] The suffix array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The output primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+bw_transform64(const sauchar_t *T, sauchar_t *U,
+ saidx64_t *SA /* can NULL */,
+ saidx64_t n, saidx64_t *idx);
+
+/**
+ * Inverse BW-transforms a given BWTed string.
+ * @param T[0..n-1] The input string.
+ * @param U[0..n-1] The output string. (can be T)
+ * @param A[0..n-1] The temporary array. (can be NULL)
+ * @param n The length of the given string.
+ * @param idx The primary index.
+ * @return 0 if no error occurred, -1 or -2 otherwise.
+ */
+DIVSUFSORT_API
+saint_t
+inverse_bw_transform64(const sauchar_t *T, sauchar_t *U,
+ saidx64_t *A /* can NULL */,
+ saidx64_t n, saidx64_t idx);
+
+/**
+ * Checks the correctness of a given suffix array.
+ * @param T[0..n-1] The input string.
+ * @param SA[0..n-1] The input suffix array.
+ * @param n The length of the given string.
+ * @param verbose The verbose mode.
+ * @return 0 if no error occurred.
+ */
+DIVSUFSORT_API
+saint_t
+sufcheck64(const sauchar_t *T, const saidx64_t *SA, saidx64_t n, saint_t verbose);
+
+/**
+ * Search for the pattern P in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param P[0..Psize-1] The input pattern string.
+ * @param Psize The length of the given pattern string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx64_t
+sa_search64(const sauchar_t *T, saidx64_t Tsize,
+ const sauchar_t *P, saidx64_t Psize,
+ const saidx64_t *SA, saidx64_t SAsize,
+ saidx64_t *left);
+
+/**
+ * Search for the character c in the string T.
+ * @param T[0..Tsize-1] The input string.
+ * @param Tsize The length of the given string.
+ * @param SA[0..SAsize-1] The input suffix array.
+ * @param SAsize The length of the given suffix array.
+ * @param c The input character.
+ * @param idx The output index.
+ * @return The count of matches if no error occurred, -1 otherwise.
+ */
+DIVSUFSORT_API
+saidx64_t
+sa_simplesearch64(const sauchar_t *T, saidx64_t Tsize,
+ const saidx64_t *SA, saidx64_t SAsize,
+ saint_t c, saidx64_t *left);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* _DIVSUFSORT64_H */
diff --git a/usr.bin/bsdiff/bspatch/Makefile b/usr.bin/bsdiff/bspatch/Makefile
new file mode 100644
index 000000000000..12b67fe97577
--- /dev/null
+++ b/usr.bin/bsdiff/bspatch/Makefile
@@ -0,0 +1,5 @@
+PROG= bspatch
+
+LIBADD= bz2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bsdiff/bspatch/Makefile.depend b/usr.bin/bsdiff/bspatch/Makefile.depend
new file mode 100644
index 000000000000..cc83708e9dfd
--- /dev/null
+++ b/usr.bin/bsdiff/bspatch/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbz2 \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bsdiff/bspatch/bspatch.1 b/usr.bin/bsdiff/bspatch/bspatch.1
new file mode 100644
index 000000000000..291f9f2be348
--- /dev/null
+++ b/usr.bin/bsdiff/bspatch/bspatch.1
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright 2003-2005 Colin Percival
+.\" All rights reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted providing 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 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.
+.\"
+.Dd December 22, 2022
+.Dt BSPATCH 1
+.Os
+.Sh NAME
+.Nm bspatch
+.Nd apply a patch built with
+.Xr bsdiff 1
+.Sh SYNOPSIS
+.Nm
+.Ar oldfile newfile patchfile
+.Sh DESCRIPTION
+The
+.Nm
+utility
+generates
+.Ar newfile
+from
+.Ar oldfile
+and
+.Ar patchfile
+where
+.Ar patchfile
+is a binary patch built by
+.Xr bsdiff 1 .
+.Pp
+The
+.Nm
+utility
+uses memory equal to the size of
+.Ar oldfile
+plus the size of
+.Ar newfile ,
+but can tolerate a very small working set without a dramatic loss
+of performance.
+.Sh SEE ALSO
+.Xr bsdiff 1
+.Sh AUTHORS
+.An Colin Percival Aq Mt cperciva@FreeBSD.org
+.Sh BUGS
+The
+.Nm
+utility does not verify that
+.Ar oldfile
+is the correct source file for
+.Ar patchfile .
+Attempting to apply a patch to the wrong file will usually produce
+garbage; consequently it is strongly recommended that users of
+.Nm
+verify that
+.Ar oldfile
+matches the source file from which
+.Ar patchfile
+was built, by comparing cryptographic hashes, for example.
+Users may also wish to verify after running
+.Nm
+that
+.Ar newfile
+matches the target file from which
+.Ar patchfile
+was built.
diff --git a/usr.bin/bsdiff/bspatch/bspatch.c b/usr.bin/bsdiff/bspatch/bspatch.c
new file mode 100644
index 000000000000..ea43d78b12a1
--- /dev/null
+++ b/usr.bin/bsdiff/bspatch/bspatch.c
@@ -0,0 +1,302 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2003-2005 Colin Percival
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef WITHOUT_CAPSICUM
+#include <sys/capsicum.h>
+#endif
+
+#include <bzlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdckdint.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#define HEADER_SIZE 32
+
+static char *newfile;
+static int dirfd = -1;
+
+static void
+exit_cleanup(void)
+{
+
+ if (dirfd != -1 && newfile != NULL)
+ if (unlinkat(dirfd, newfile, 0))
+ warn("unlinkat");
+}
+
+static inline off_t
+add_off_t(off_t a, off_t b)
+{
+ off_t result;
+
+ if (ckd_add(&result, a, b))
+ errx(1, "Corrupt patch");
+ return result;
+}
+
+static off_t offtin(u_char *buf)
+{
+ off_t y;
+
+ y = buf[7] & 0x7F;
+ y = y * 256; y += buf[6];
+ y = y * 256; y += buf[5];
+ y = y * 256; y += buf[4];
+ y = y * 256; y += buf[3];
+ y = y * 256; y += buf[2];
+ y = y * 256; y += buf[1];
+ y = y * 256; y += buf[0];
+
+ if (buf[7] & 0x80)
+ y = -y;
+
+ return (y);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *f, *cpf, *dpf, *epf;
+ BZFILE *cpfbz2, *dpfbz2, *epfbz2;
+ char *directory, *namebuf;
+ int cbz2err, dbz2err, ebz2err;
+ int newfd, oldfd;
+ off_t oldsize, newsize;
+ off_t bzctrllen, bzdatalen;
+ u_char header[HEADER_SIZE], buf[8];
+ u_char *old, *new;
+ off_t oldpos, newpos;
+ off_t ctrl[3];
+ off_t i, lenread, offset;
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_t rights_dir, rights_ro, rights_wr;
+#endif
+
+ if (argc != 4)
+ usage();
+
+ /* Open patch file */
+ if ((f = fopen(argv[3], "rb")) == NULL)
+ err(1, "fopen(%s)", argv[3]);
+ /* Open patch file for control block */
+ if ((cpf = fopen(argv[3], "rb")) == NULL)
+ err(1, "fopen(%s)", argv[3]);
+ /* open patch file for diff block */
+ if ((dpf = fopen(argv[3], "rb")) == NULL)
+ err(1, "fopen(%s)", argv[3]);
+ /* open patch file for extra block */
+ if ((epf = fopen(argv[3], "rb")) == NULL)
+ err(1, "fopen(%s)", argv[3]);
+ /* open oldfile */
+ if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0)
+ err(1, "open(%s)", argv[1]);
+ /* open directory where we'll write newfile */
+ if ((namebuf = strdup(argv[2])) == NULL ||
+ (directory = dirname(namebuf)) == NULL ||
+ (dirfd = open(directory, O_DIRECTORY)) < 0)
+ err(1, "open %s", argv[2]);
+ free(namebuf);
+ if ((newfile = basename(argv[2])) == NULL)
+ err(1, "basename");
+ /* open newfile */
+ if ((newfd = openat(dirfd, newfile,
+ O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0)
+ err(1, "open(%s)", argv[2]);
+ atexit(exit_cleanup);
+
+#ifndef WITHOUT_CAPSICUM
+ if (cap_enter() < 0)
+ err(1, "failed to enter security sandbox");
+
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK, CAP_MMAP_R);
+ cap_rights_init(&rights_wr, CAP_WRITE);
+ cap_rights_init(&rights_dir, CAP_UNLINKAT);
+
+ if (cap_rights_limit(fileno(f), &rights_ro) < 0 ||
+ cap_rights_limit(fileno(cpf), &rights_ro) < 0 ||
+ cap_rights_limit(fileno(dpf), &rights_ro) < 0 ||
+ cap_rights_limit(fileno(epf), &rights_ro) < 0 ||
+ cap_rights_limit(oldfd, &rights_ro) < 0 ||
+ cap_rights_limit(newfd, &rights_wr) < 0 ||
+ cap_rights_limit(dirfd, &rights_dir) < 0)
+ err(1, "cap_rights_limit() failed, could not restrict"
+ " capabilities");
+#endif
+
+ /*
+ File format:
+ 0 8 "BSDIFF40"
+ 8 8 X
+ 16 8 Y
+ 24 8 sizeof(newfile)
+ 32 X bzip2(control block)
+ 32+X Y bzip2(diff block)
+ 32+X+Y ??? bzip2(extra block)
+ with control block a set of triples (x,y,z) meaning "add x bytes
+ from oldfile to x bytes from the diff block; copy y bytes from the
+ extra block; seek forwards in oldfile by z bytes".
+ */
+
+ /* Read header */
+ if (fread(header, 1, HEADER_SIZE, f) < HEADER_SIZE) {
+ if (feof(f))
+ errx(1, "Corrupt patch");
+ err(1, "fread(%s)", argv[3]);
+ }
+
+ /* Check for appropriate magic */
+ if (memcmp(header, "BSDIFF40", 8) != 0)
+ errx(1, "Corrupt patch");
+
+ /* Read lengths from header */
+ bzctrllen = offtin(header + 8);
+ bzdatalen = offtin(header + 16);
+ newsize = offtin(header + 24);
+ if (bzctrllen < 0 || bzctrllen > OFF_MAX - HEADER_SIZE ||
+ bzdatalen < 0 || bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen ||
+ newsize < 0 || newsize > SSIZE_MAX)
+ errx(1, "Corrupt patch");
+
+ /* Close patch file and re-open it via libbzip2 at the right places */
+ if (fclose(f))
+ err(1, "fclose(%s)", argv[3]);
+ offset = HEADER_SIZE;
+ if (fseeko(cpf, offset, SEEK_SET))
+ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
+ offset = add_off_t(offset, bzctrllen);
+ if (fseeko(dpf, offset, SEEK_SET))
+ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
+ offset = add_off_t(offset, bzdatalen);
+ if (fseeko(epf, offset, SEEK_SET))
+ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
+
+ if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 ||
+ oldsize > SSIZE_MAX)
+ err(1, "%s", argv[1]);
+
+ old = mmap(NULL, oldsize+1, PROT_READ, MAP_SHARED, oldfd, 0);
+ if (old == MAP_FAILED || close(oldfd) != 0)
+ err(1, "%s", argv[1]);
+
+ if ((new = malloc(newsize)) == NULL)
+ err(1, NULL);
+
+ oldpos = 0;
+ newpos = 0;
+ while (newpos < newsize) {
+ /* Read control data */
+ for (i = 0; i <= 2; i++) {
+ lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
+ if ((lenread < 8) || ((cbz2err != BZ_OK) &&
+ (cbz2err != BZ_STREAM_END)))
+ errx(1, "Corrupt patch");
+ ctrl[i] = offtin(buf);
+ }
+
+ /* Sanity-check */
+ if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
+ ctrl[1] < 0 || ctrl[1] > INT_MAX)
+ errx(1, "Corrupt patch");
+
+ /* Sanity-check */
+ if (add_off_t(newpos, ctrl[0]) > newsize)
+ errx(1, "Corrupt patch");
+
+ /* Read diff string */
+ lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
+ if ((lenread < ctrl[0]) ||
+ ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
+ errx(1, "Corrupt patch");
+
+ /* Add old data to diff string */
+ for (i = 0; i < ctrl[0]; i++)
+ if (add_off_t(oldpos, i) < oldsize)
+ new[newpos + i] += old[oldpos + i];
+
+ /* Adjust pointers */
+ newpos = add_off_t(newpos, ctrl[0]);
+ oldpos = add_off_t(oldpos, ctrl[0]);
+
+ /* Sanity-check */
+ if (add_off_t(newpos, ctrl[1]) > newsize)
+ errx(1, "Corrupt patch");
+
+ /* Read extra string */
+ lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
+ if ((lenread < ctrl[1]) ||
+ ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
+ errx(1, "Corrupt patch");
+
+ /* Adjust pointers */
+ newpos = add_off_t(newpos, ctrl[1]);
+ oldpos = add_off_t(oldpos, ctrl[2]);
+ }
+
+ /* Clean up the bzip2 reads */
+ BZ2_bzReadClose(&cbz2err, cpfbz2);
+ BZ2_bzReadClose(&dbz2err, dpfbz2);
+ BZ2_bzReadClose(&ebz2err, epfbz2);
+ if (fclose(cpf) || fclose(dpf) || fclose(epf))
+ err(1, "fclose(%s)", argv[3]);
+
+ /* Write the new file */
+ if (write(newfd, new, newsize) != newsize || close(newfd) == -1)
+ err(1, "%s", argv[2]);
+ /* Disable atexit cleanup */
+ newfile = NULL;
+
+ free(new);
+ munmap(old, oldsize+1);
+
+ return (0);
+}
diff --git a/usr.bin/bzip2/Makefile b/usr.bin/bzip2/Makefile
new file mode 100644
index 000000000000..99679cc00c44
--- /dev/null
+++ b/usr.bin/bzip2/Makefile
@@ -0,0 +1,50 @@
+BZ2DIR= ${SRCTOP}/contrib/bzip2
+.PATH: ${BZ2DIR}
+
+PROG= bzip2
+CFLAGS+= -D_FILE_OFFSET_BITS=64
+
+WARNS?= 3
+
+LIBADD= bz2
+
+LINKS= ${BINDIR}/bzip2 ${BINDIR}/bunzip2
+LINKS+= ${BINDIR}/bzip2 ${BINDIR}/bzcat
+MLINKS= bzip2.1 bunzip2.1 \
+ bzip2.1 bzcat.1 \
+ bzip2.1 bzip2recover.1
+
+REFFILES= sample1.ref sample2.ref sample3.ref
+DREFFILES= sample1.bz2 sample2.bz2 sample3.bz2
+TESTFILES= ${REFFILES} ${DREFFILES}
+
+CLEANFILES+= ${TESTFILES} \
+ sample1.rb2 sample2.rb2 sample3.rb2 \
+ sample1.tst sample2.tst sample3.tst
+
+.for f in ${REFFILES}
+${f}: ${f}.gz.uu
+ uudecode -p ${BZ2DIR}/${f}.gz.uu | gunzip > ${f}
+.endfor
+.for f in ${DREFFILES}
+${f}: ${f}.uu
+ uudecode ${BZ2DIR}/${f}.uu
+.endfor
+
+test: bzip2 ${TESTFILES}
+ @cat ${BZ2DIR}/words1
+ ./bzip2 -1 < sample1.ref > sample1.rb2
+ ./bzip2 -2 < sample2.ref > sample2.rb2
+ ./bzip2 -3 < sample3.ref > sample3.rb2
+ ./bzip2 -d < sample1.bz2 > sample1.tst
+ ./bzip2 -d < sample2.bz2 > sample2.tst
+ ./bzip2 -ds < sample3.bz2 > sample3.tst
+ cmp sample1.bz2 sample1.rb2
+ cmp sample2.bz2 sample2.rb2
+ cmp sample3.bz2 sample3.rb2
+ cmp sample1.tst sample1.ref
+ cmp sample2.tst sample2.ref
+ cmp sample3.tst sample3.ref
+ @cat ${BZ2DIR}/words3
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bzip2/Makefile.depend b/usr.bin/bzip2/Makefile.depend
new file mode 100644
index 000000000000..d8f99901543f
--- /dev/null
+++ b/usr.bin/bzip2/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbz2 \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/bzip2recover/Makefile b/usr.bin/bzip2recover/Makefile
new file mode 100644
index 000000000000..2b11d3a45694
--- /dev/null
+++ b/usr.bin/bzip2recover/Makefile
@@ -0,0 +1,9 @@
+BZ2DIR= ${SRCTOP}/contrib/bzip2
+.PATH: ${BZ2DIR}
+
+PROG= bzip2recover
+MAN=
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/bzip2recover/Makefile.depend b/usr.bin/bzip2recover/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/bzip2recover/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/c89/Makefile b/usr.bin/c89/Makefile
new file mode 100644
index 000000000000..325588a3d7a8
--- /dev/null
+++ b/usr.bin/c89/Makefile
@@ -0,0 +1,3 @@
+PROG= c89
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/c89/Makefile.depend b/usr.bin/c89/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/c89/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/c89/c89.1 b/usr.bin/c89/c89.1
new file mode 100644
index 000000000000..ee1f9fa1550b
--- /dev/null
+++ b/usr.bin/c89/c89.1
@@ -0,0 +1,182 @@
+.\"
+.\" Copyright (c) 1997 Joerg Wunsch
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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 September 17, 1997
+.Dt C89 1
+.Os
+.Sh NAME
+.Nm c89
+.Nd POSIX.2 C language compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl cEgOs
+.Oo Fl D Ar name Ns Oo = Ns Ar value Oc Oc ...
+.Oo Fl I Ar directory Oc ...
+.Oo Fl L Ar directory Oc ...
+.Op Fl o Ar outfile
+.Oo Fl U Ar name Oc ...
+.Ar operand ...
+.Sh DESCRIPTION
+This is the name of the C language compiler as required by the
+.St -p1003.2
+standard.
+.Pp
+The
+.Nm
+compiler accepts the following options:
+.Bl -tag -width indent
+.It Fl c
+Suppress the link-edit phase of the compilation, and do not remove any
+object files that are produced.
+.It Fl D Ar name Ns Op = Ns Ar value
+Define name as if by a C-language
+.Ic #define
+directive.
+If no
+.Dq = Ns Ar value
+is given, a value of 1 will be used.
+Note that in order to request a
+translation as specified by
+.St -p1003.2
+you need to define
+.Dv _POSIX_SOURCE
+either in the source or using this option.
+The
+.Fl D
+option has lower precedence than the
+.Fl U
+option.
+That is, if
+.Ar name
+is used in both a
+.Fl U
+and a
+.Fl D
+option,
+.Ar name
+will be undefined regardless of the order of the options.
+The
+.Fl D
+option may be specified more than once.
+.It Fl E
+Copy C-language source files to the standard output, expanding all
+preprocessor directives; no compilation will be performed.
+.It Fl g
+Produce symbolic information in the object or executable files.
+.It Fl I Ar directory
+Change the algorithm for searching for headers whose names are not
+absolute pathnames to look in the directory named by the
+.Ar directory
+pathname before looking in the usual places.
+Thus, headers whose
+names are enclosed in double-quotes
+.Pq Qq
+will be searched for first
+in the directory of the file with the
+.Ic #include
+line, then in
+directories named in
+.Fl I
+options, and last in the usual places.
+For headers whose names are enclosed in angle brackets
+.Pq Aq ,
+the header
+will be searched for only in directories named in
+.Fl I
+options and then in the usual places.
+Directories named in
+.Fl I
+options shall be searched in the order specified.
+The
+.Fl I
+option may be specified more than once.
+.It Fl L Ar directory
+Change the algorithm of searching for the libraries named in the
+.Fl l
+objects to look in the directory named by the
+.Ar directory
+pathname before looking in the usual places.
+Directories named in
+.Fl L
+options will be searched in the order specified.
+The
+.Fl L
+option may be specified more than once.
+.It Fl o Ar outfile
+Use the pathname
+.Ar outfile ,
+instead of the default
+.Pa a.out ,
+for the executable file produced.
+.It Fl O
+Optimize the compilation.
+.It Fl s
+Produce object and/or executable files from which symbolic and other
+information not required for proper execution has been removed
+(stripped).
+.It Fl U Ar name
+Remove any initial definition of
+.Ar name .
+The
+.Fl U
+option may be specified more than once.
+.El
+.Pp
+An operand is either in the form of a pathname or the form
+.Fl l
+library.
+At least one operand of the pathname form needs to be specified.
+Supported operands are of the form:
+.Bl -tag -offset indent -width ".Fl l Ar library"
+.It Ar file Ns Pa .c
+A C-language source file to be compiled and optionally linked.
+The operand must be of this form if the
+.Fl c
+option is used.
+.It Ar file Ns Pa .a
+A library of object files, as produced by
+.Xr ar 1 ,
+passed directly to the link editor.
+.It Ar file Ns Pa .o
+An object file produced by
+.Nm Fl c ,
+and passed directly to the link editor.
+.It Fl l Ar library
+Search the library named
+.Pa lib Ns Ar library Ns Pa .a .
+A library will be searched when its name is encountered, so the
+placement of a
+.Fl l
+operand is significant.
+.El
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr c99 1 ,
+.Xr cc 1
+.Sh STANDARDS
+The
+.Nm
+utility is believed to comply with
+.St -p1003.2 .
diff --git a/usr.bin/c89/c89.c b/usr.bin/c89/c89.c
new file mode 100644
index 000000000000..3e1fd5dbdfeb
--- /dev/null
+++ b/usr.bin/c89/c89.c
@@ -0,0 +1,111 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * This is the Posix.2 mandated C compiler. Basically, a hook to the
+ * cc(1) command.
+ *
+ * Copyright (c) 2001 by Jens Schweikhardt
+ *
+ * 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 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 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/cdefs.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#define CC "/usr/bin/cc" /* The big kahuna doing the actual work. */
+#define N_ARGS_PREPENDED (sizeof(args_prepended) / sizeof(args_prepended[0]))
+
+/*
+ * We do not add -D_POSIX_SOURCE here because any POSIX source is supposed to
+ * define it before inclusion of POSIX headers. This has the additional
+ * benefit of making c89 -D_ANSI_SOURCE do the right thing (or any other
+ * -D_FOO_SOURCE feature test macro we support.)
+ */
+static const char *args_prepended[] = {
+ "-std=iso9899:199409",
+ "-pedantic"
+};
+
+static void usage(void);
+
+/*
+ * Prepend the strings from args_prepended[] to the arg list; parse options,
+ * accepting only the POSIX c89 mandated options. Then exec cc to do the
+ * actual work.
+ */
+int
+main(int argc, char **argv)
+{
+ int Argc, i;
+ size_t j;
+ union {
+ const char **a;
+ char * const *b;
+ } Argv;
+
+ Argc = 0;
+ Argv.a = malloc((argc + 1 + N_ARGS_PREPENDED) * sizeof *Argv.a);
+ if (Argv.a == NULL)
+ err(1, "malloc");
+ Argv.a[Argc++] = CC;
+ for (j = 0; j < N_ARGS_PREPENDED; ++j)
+ Argv.a[Argc++] = args_prepended[j];
+ while ((i = getopt(argc, argv, "cD:EgI:l:L:o:OsU:")) != -1) {
+ if (i == '?')
+ usage();
+ if (i == 'l') {
+ if (argv[optind - 1][0] == '-') /* -llib */
+ optind -= 1;
+ else /* -l lib */
+ optind -= 2;
+ break; /* -llib or -l lib starts the operands. */
+ }
+ }
+ if (argc == optind) {
+ warnx("missing operand");
+ usage();
+ }
+
+ /* Append argv[1..] at the end of Argv[].a. */
+ for (i = 1; i <= argc; ++i)
+ Argv.a[Argc++] = argv[i];
+ (void)execv(CC, Argv.b);
+ err(1, "execv(" CC ")");
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"usage: c89 [-cEgOs] [-D name[=value]] ... [-I directory] ... [-L directory] ...\n"
+" [-o outfile] [-U name] ... operand ...\n"
+"\n"
+" where operand is one or more of file.c, file.o, file.a\n"
+" or -llibrary\n");
+ exit(1);
+}
diff --git a/usr.bin/c99/Makefile b/usr.bin/c99/Makefile
new file mode 100644
index 000000000000..98be921c974c
--- /dev/null
+++ b/usr.bin/c99/Makefile
@@ -0,0 +1,3 @@
+PROG= c99
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/c99/Makefile.depend b/usr.bin/c99/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/c99/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/c99/c99.1 b/usr.bin/c99/c99.1
new file mode 100644
index 000000000000..edd466a39ef2
--- /dev/null
+++ b/usr.bin/c99/c99.1
@@ -0,0 +1,189 @@
+.\"
+.\" Copyright (c) 1997 Joerg Wunsch
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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 FreeBSD: src/usr.bin/c89/c89.1,v 1.11 2007/03/10 07:10:01 ru Exp
+.\"
+.Dd July 13, 2015
+.Dt C99 1
+.Os
+.Sh NAME
+.Nm c99
+.Nd standard C language compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl cEgs
+.Oo Fl D Ar name Ns Oo = Ns Ar value Oc Oc ...
+.Oo Fl I Ar directory Oc ...
+.Oo Fl L Ar directory Oc ...
+.Op Fl o Ar outfile
+.Op Fl O Ar optlevel
+.Oo Fl U Ar name Oc ...
+.Ar operand ...
+.Sh DESCRIPTION
+This is the name of the C language compiler as required by the
+.St -p1003.1-2001
+standard.
+.Pp
+The
+.Nm
+compiler accepts the following options:
+.Bl -tag -width indent
+.It Fl c
+Suppress the link-edit phase of the compilation, and do not remove any
+object files that are produced.
+.It Fl D Ar name Ns Op = Ns Ar value
+Define name as if by a C-language
+.Ic #define
+directive.
+If no
+.Dq = Ns Ar value
+is given, a value of 1 will be used.
+Note that in order to request a
+translation as specified by
+.St -p1003.1-2001 ,
+you need to define
+.Dv _POSIX_C_SOURCE=200112L
+either in the source or using this option.
+The
+.Fl D
+option has lower precedence than the
+.Fl U
+option.
+That is, if
+.Ar name
+is used in both a
+.Fl U
+and a
+.Fl D
+option,
+.Ar name
+will be undefined regardless of the order of the options.
+The
+.Fl D
+option may be specified more than once.
+.It Fl E
+Copy C-language source files to the standard output, expanding all
+preprocessor directives; no compilation will be performed.
+.It Fl g
+Produce symbolic information in the object or executable files.
+.It Fl I Ar directory
+Change the algorithm for searching for headers whose names are not
+absolute pathnames to look in the directory named by the
+.Ar directory
+pathname before looking in the usual places.
+Thus, headers whose
+names are enclosed in double-quotes
+.Pq Qq
+will be searched for first
+in the directory of the file with the
+.Ic #include
+line, then in
+directories named in
+.Fl I
+options, and last in the usual places.
+For headers whose names are enclosed in angle brackets
+.Pq Aq ,
+the header
+will be searched for only in directories named in
+.Fl I
+options and then in the usual places.
+Directories named in
+.Fl I
+options shall be searched in the order specified.
+The
+.Fl I
+option may be specified more than once.
+.It Fl L Ar directory
+Change the algorithm of searching for the libraries named in the
+.Fl l
+objects to look in the directory named by the
+.Ar directory
+pathname before looking in the usual places.
+Directories named in
+.Fl L
+options will be searched in the order specified.
+The
+.Fl L
+option may be specified more than once.
+.It Fl o Ar outfile
+Use the pathname
+.Ar outfile ,
+instead of the default
+.Pa a.out ,
+for the executable file produced.
+.It Fl O Ar optlevel
+If
+.Ar optlevel
+is zero, disable all optimizations.
+Otherwise, enable optimizations at the specified level.
+.It Fl s
+Produce object and/or executable files from which symbolic and other
+information not required for proper execution has been removed
+(stripped).
+.It Fl U Ar name
+Remove any initial definition of
+.Ar name .
+The
+.Fl U
+option may be specified more than once.
+.El
+.Pp
+An operand is either in the form of a pathname or the form
+.Fl l
+library.
+At least one operand of the pathname form needs to be specified.
+Supported operands are of the form:
+.Bl -tag -offset indent -width ".Fl l Ar library"
+.It Ar file Ns Pa .c
+A C-language source file to be compiled and optionally linked.
+The operand must be of this form if the
+.Fl c
+option is used.
+.It Ar file Ns Pa .a
+A library of object files, as produced by
+.Xr ar 1 ,
+passed directly to the link editor.
+.It Ar file Ns Pa .o
+An object file produced by
+.Nm Fl c ,
+and passed directly to the link editor.
+.It Fl l Ar library
+Search the library named
+.Pa lib Ns Ar library Ns Pa .a .
+A library will be searched when its name is encountered, so the
+placement of a
+.Fl l
+operand is significant.
+.El
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr c89 1 ,
+.Xr cc 1 ,
+.Xr c99 7
+.Sh STANDARDS
+The
+.Nm
+utility interface conforms to
+.St -p1003.1-2001 .
diff --git a/usr.bin/c99/c99.c b/usr.bin/c99/c99.c
new file mode 100644
index 000000000000..688321d170bc
--- /dev/null
+++ b/usr.bin/c99/c99.c
@@ -0,0 +1,132 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * c99 -- compile standard C programs
+ *
+ * This is essentially a wrapper around the system C compiler that forces
+ * the compiler into C99 mode and handles some of the standard libraries
+ * specially.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static char **args;
+static u_int cargs, nargs;
+
+static void addarg(const char *);
+static void addlib(const char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i;
+
+ args = NULL;
+ cargs = nargs = 0;
+
+ while ((ch = getopt(argc, argv, "cD:EgI:L:o:O:sU:l:")) != -1) {
+ if (ch == 'l') {
+ /* Gone too far. Back up and get out. */
+ if (argv[optind - 1][0] == '-')
+ optind -= 1;
+ else
+ optind -= 2;
+ break;
+ } else if (ch == '?')
+ usage();
+ }
+
+ addarg("/usr/bin/cc");
+ addarg("-std=iso9899:1999");
+ addarg("-pedantic");
+ for (i = 1; i < optind; i++)
+ addarg(argv[i]);
+ while (i < argc) {
+ if (strncmp(argv[i], "-l", 2) == 0) {
+ if (argv[i][2] != '\0')
+ addlib(argv[i++] + 2);
+ else {
+ if (argv[++i] == NULL)
+ usage();
+ addlib(argv[i++]);
+ }
+ } else
+ addarg(argv[i++]);
+ }
+ execv("/usr/bin/cc", args);
+ err(1, "/usr/bin/cc");
+}
+
+static void
+addarg(const char *item)
+{
+ if (nargs + 1 >= cargs) {
+ cargs += 16;
+ if ((args = realloc(args, sizeof(*args) * cargs)) == NULL)
+ err(1, "malloc");
+ }
+ if ((args[nargs++] = strdup(item)) == NULL)
+ err(1, "strdup");
+ args[nargs] = NULL;
+}
+
+static void
+addlib(const char *lib)
+{
+
+ if (strcmp(lib, "pthread") == 0)
+ /* FreeBSD's gcc uses -pthread instead of -lpthread. */
+ addarg("-pthread");
+ else if (strcmp(lib, "rt") == 0)
+ /* librt functionality is in libc or unimplemented. */
+ ;
+ else if (strcmp(lib, "xnet") == 0)
+ /* xnet functionality is in libc. */
+ ;
+ else {
+ addarg("-l");
+ addarg(lib);
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n",
+"usage: c99 [-cEgs] [-D name[=value]] ... [-I directory] ... [-L directory] ...",
+" [-o outfile] [-O optlevel] [-U name] ... operand ...");
+ exit(1);
+}
diff --git a/usr.bin/caesar/Makefile b/usr.bin/caesar/Makefile
new file mode 100644
index 000000000000..e7496fbb2925
--- /dev/null
+++ b/usr.bin/caesar/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= games
+
+PROG= caesar
+LIBADD= m
+SCRIPTS=rot13.sh
+MAN= caesar.6
+MLINKS= caesar.6 rot13.6
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/caesar/Makefile.depend b/usr.bin/caesar/Makefile.depend
new file mode 100644
index 000000000000..9add648af17b
--- /dev/null
+++ b/usr.bin/caesar/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/caesar/caesar.6 b/usr.bin/caesar/caesar.6
new file mode 100644
index 000000000000..403370d57e36
--- /dev/null
+++ b/usr.bin/caesar/caesar.6
@@ -0,0 +1,70 @@
+.\" 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.
+.\"
+.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/usr.bin/caesar/caesar.c b/usr.bin/caesar/caesar.c
new file mode 100644
index 000000000000..011f9c8e0630
--- /dev/null
+++ b/usr.bin/caesar/caesar.c
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#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/usr.bin/caesar/rot13.sh b/usr.bin/caesar/rot13.sh
new file mode 100644
index 000000000000..1916fa78ad65
--- /dev/null
+++ b/usr.bin/caesar/rot13.sh
@@ -0,0 +1,30 @@
+#!/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.
+
+exec /usr/bin/caesar 13 "$@"
diff --git a/usr.bin/calendar/Makefile b/usr.bin/calendar/Makefile
new file mode 100644
index 000000000000..d931f2f837da
--- /dev/null
+++ b/usr.bin/calendar/Makefile
@@ -0,0 +1,19 @@
+.include <src.opts.mk>
+
+PROG= calendar
+SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
+ ostern.c paskha.c pom.c sunpos.c
+LIBADD= m util
+
+.if ${MK_ICONV} == "yes"
+CFLAGS+= -DWITH_ICONV
+.endif
+
+FILESGROUPS+= CALS
+CALS= calendars/calendar.freebsd
+CALSDIR= ${SHAREDIR}/calendar
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/calendar/Makefile.depend b/usr.bin/calendar/Makefile.depend
new file mode 100644
index 000000000000..af3b7054df7a
--- /dev/null
+++ b/usr.bin/calendar/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/calendar/calendar.1 b/usr.bin/calendar/calendar.1
new file mode 100644
index 000000000000..edb3aca48c92
--- /dev/null
+++ b/usr.bin/calendar/calendar.1
@@ -0,0 +1,372 @@
+.\" Copyright (c) 1989, 1990, 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.
+.\"
+.Dd December 17, 2023
+.Dt CALENDAR 1
+.Os
+.Sh NAME
+.Nm calendar
+.Nd reminder service
+.Sh SYNOPSIS
+.Nm
+.Op Fl A Ar num
+.Op Fl a
+.Op Fl B Ar num
+.Op Fl D Ar moon|sun
+.Op Fl d
+.Op Fl F Ar friday
+.Op Fl f Ar calendarfile
+.Op Fl l Ar longitude
+.Oo
+.Bk -words
+.Fl t Ar dd Ns
+.Sm off
+.Op . Ar mm Op . Ar year
+.Sm on
+.Ek
+.Oc
+.Op Fl U Ar UTC-offset
+.Op Fl W Ar num
+.Sh DESCRIPTION
+The
+.Nm
+utility checks the current directory for a file named
+.Pa calendar
+and displays lines that fall into the specified date range.
+On the day before a weekend (normally Friday), events for the next
+three days are displayed.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl A Ar num
+Print lines from today and the next
+.Ar num
+days (forward, future).
+.It Fl a
+Process the ``calendar'' files for users found in
+.Pa /etc/passwd
+and mail the results
+to them.
+This can result in multiple messages for specific files, since
+.Pa /etc/passwd
+does not require home directories to be unique.
+In particular, by default
+.Ar root ,
+.Ar toor
+and
+.Ar daemon
+share the same home directory.
+If this directory contains calendar information,
+.Nm
+will process the file three times.
+.Pp
+This option requires super-user privileges.
+.It Fl B Ar num
+Print lines from today and the previous
+.Ar num
+days (backward, past).
+.It Fl D Ar moon|sun
+Print UTC offset, longitude and moon or sun information.
+.It Fl d
+Debug option: print current date information.
+.It Fl F Ar friday
+Specify which day of the week is ``Friday'' (the day before the
+weekend begins).
+Default is 5.
+.It Fl f Pa calendarfile
+Use
+.Pa calendarfile
+as the default calendar file.
+.It Fl l Ar longitude
+Perform lunar and solar calculations from this longitude.
+If neither longitude nor UTC offset is specified, the calculations will
+be based on the difference between UTC time and localtime.
+If both are specified, UTC offset overrides longitude.
+.It Xo Fl t
+.Sm off
+.Ar dd
+.Op . Ar mm Op . Ar year
+.Sm on
+.Xc
+For test purposes only: set date directly to argument values.
+.It Fl U Ar UTC-offset
+Perform lunar and solar calculations from this UTC offset.
+If neither UTC offset nor longitude is specified, the calculations
+will be based on the difference between UTC time and localtime.
+If both are specified, UTC offset overrides longitude.
+.It Fl W Ar num
+Print lines from today and the next
+.Ar num
+days (forward, future).
+Ignore weekends when calculating the number of days.
+.El
+.Sh FILE FORMAT
+To handle calendars in your national code table you can specify
+.Dq LANG=<locale_name>
+in the calendar file as early as possible.
+.Pp
+To handle the local name of sequences, you can specify them as:
+.Dq SEQUENCE=<first> <second> <third> <fourth> <fifth> <last>
+in the calendar file as early as possible.
+.Pp
+The names of the following special days are recognized:
+.Bl -tag -width 123456789012345 -compact
+.It Easter
+Catholic Easter.
+.It Paskha
+Orthodox Easter.
+.It NewMoon
+The lunar New Moon.
+.It FullMoon
+The lunar Full Moon.
+.It MarEquinox
+The solar equinox in March.
+.It JunSolstice
+The solar solstice in June.
+.It SepEquinox
+The solar equinox in September.
+.It DecSolstice
+The solar solstice in December.
+.It ChineseNewYear
+The first day of the Chinese year.
+.El
+These names may be reassigned to their local names via an assignment
+like
+.Dq Easter=Pasen
+in the calendar file.
+.Pp
+Other lines should begin with a month and day.
+They may be entered in almost any format, either numeric or as character
+strings.
+If the proper locale is set, national month and weekday
+names can be used.
+A single asterisk (``*'') matches every month.
+A day without a month matches that day of every week.
+A month without a day matches the first of that month.
+Two numbers default to the month followed by the day.
+Lines with leading tabs default to the last entered date, allowing
+multiple line specifications for a single date.
+.Pp
+The names of the recognized special days may be followed by a
+positive or negative integer, like:
+.Dq Easter+3
+or
+.Dq Paskha-4 .
+.Pp
+Weekdays may be followed by ``-4'' ...\& ``+5'' (aliases for
+last, first, second, third, fourth) for moving events like
+``the last Monday in April''.
+.Pp
+By convention, dates followed by an asterisk are not fixed, i.e., change
+from year to year.
+.Pp
+Day descriptions start after the first <tab> character in the line;
+if the line does not contain a <tab> character, it is not displayed.
+If the first character in the line is a <tab> character, it is treated as
+a continuation of the previous line.
+.Pp
+The
+.Nm
+file is preprocessed by a limited subset of
+.Xr cpp 1
+internally, allowing the inclusion of shared files such as
+lists of company holidays or meetings.
+This limited subset consists of \fB#include\fR, \fB#define\fR,
+\fB#undef\fR, \fB#ifdef\fR, \fB#ifndef\fR, \fB#else\fR, \fB#warning\fR,
+and \fB#error\fR.
+.Pp
+Conditions can be nested and the consistency of opening and closing
+instructions is checked.
+Only the first word after #define is used as the name of the
+condition variable being defined.
+More than word following #ifdef, #ifndef, or #undef is considered a syntax
+error, since names cannot include white-space.
+Included files are parsed in a global scope with regard to the condition
+variables being defined or tested therein.
+All conditional blocks are implicitly closed at the end of a file,
+and missing #endif instructions are assumed to be present on implied
+succeeding lines.
+.Pp
+If the shared file is not referenced by a full pathname,
+.Nm
+searches in the same order of precedence described in
+.Sx FILES .
+.Pp
+Blank lines and text protected by the C comment syntax
+.Ql /* ... */
+or
+.Ql //
+are ignored, but the latter only at the beginning of a line or after
+white space to allow for URLs in calendar entries.
+.Pp
+Some possible calendar entries (<tab> characters highlighted by
+\fB\et\fR sequence):
+.Bd -unfilled -offset indent
+LANG=C
+Easter=Ostern
+
+#include <calendar.usholiday>
+#include <calendar.birthday>
+
+6/15\fB\et\fRJune 15 (if ambiguous, will default to month/day).
+Jun. 15\fB\et\fRJune 15.
+15 June\fB\et\fRJune 15.
+Thursday\fB\et\fREvery Thursday.
+June\fB\et\fREvery June 1st.
+15 *\fB\et\fR15th of every month.
+2010/4/15\fB\et\fR15 April 2010
+
+May Sun+2\fB\et\fRsecond Sunday in May (Muttertag)
+04/SunLast\fB\et\fRlast Sunday in April,
+\fB\et\fRsummer time in Europe
+Easter\fB\et\fREaster
+Ostern-2\fB\et\fRGood Friday (2 days before Easter)
+Paskha\fB\et\fROrthodox Easter
+
+.Ed
+.Sh FILES
+.Bl -tag -width calendar.christian -compact
+.It Pa calendar
+file in current directory.
+.It Pa ~/.calendar
+.Pa calendar
+HOME directory.
+A chdir is done into this directory if it exists.
+.It Pa ~/.calendar/calendar
+calendar file to use if no calendar file exists in the current directory.
+.It Pa ~/.calendar/nomail
+do not send mail if this file exists.
+.It Pa /usr/share/calendar
+system wide location of calendar files provided as part of the base system.
+.It Pa /usr/local/share/calendar
+system wide location for calendar files provided by a port or package.
+.El
+.Pp
+The order of precedence in searches for a calendar file is:
+current directory, ~/.calendar, /usr/local/share/calendar, /usr/share/calendar.
+Files of similar names are ignored in lower precedence locations.
+.Pp
+The following default calendar files are provided by the
+deskutils/calendar-data port.
+.Pp
+.Bl -tag -width calendar.southafrica -compact
+.It Pa calendar.all
+File which includes all the default files.
+.It Pa calendar.australia
+Calendar of events in Australia.
+.It Pa calendar.birthday
+Births and deaths of famous (and not-so-famous) people.
+.It Pa calendar.christian
+Christian holidays.
+This calendar should be updated yearly by the local system administrator
+so that roving holidays are set correctly for the current year.
+.It Pa calendar.computer
+Days of special significance to computer people.
+.It Pa calendar.croatian
+Calendar of events in Croatia.
+.It Pa calendar.dutch
+Calendar of events in the Netherlands.
+.It Pa calendar.freebsd
+Birthdays of
+.Fx
+committers.
+.It Pa calendar.french
+Calendar of events in France.
+.It Pa calendar.german
+Calendar of events in Germany.
+.It Pa calendar.history
+Everything else, mostly U.S.\& historical events.
+.It Pa calendar.holiday
+Other holidays, including the not-well-known, obscure, and
+.Em really
+obscure.
+.It Pa calendar.judaic
+Jewish holidays.
+The entries for this calendar have been obtained from the
+deskutils/hebcal port.
+.It Pa calendar.music
+Musical events, births, and deaths.
+Strongly oriented toward rock 'n' roll.
+.It Pa calendar.newzealand
+Calendar of events in New Zealand.
+.It Pa calendar.russian
+Russian calendar.
+.It Pa calendar.southafrica
+Calendar of events in South Africa.
+.It Pa calendar.usholiday
+U.S.\& holidays.
+This calendar should be updated yearly by the local system administrator
+so that roving holidays are set correctly for the current year.
+.It Pa calendar.world
+Includes all calendar files except for national files.
+.El
+.Sh COMPATIBILITY
+The
+.Nm
+program previously selected lines which had the correct date anywhere
+in the line.
+This is no longer true, the date is only recognized when it occurs
+at the beginning of a line.
+.Sh SEE ALSO
+.Xr at 1 ,
+.Xr mail 1 ,
+.Xr cron 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v7 .
+.Sh NOTES
+Chinese New Year is calculated at 120 degrees east of Greenwich,
+which roughly corresponds with the east coast of China.
+For people west of China, this might result that the start of Chinese
+New Year and the day of the related new moon might differ.
+.Pp
+The phases of the moon and the longitude of the sun are calculated
+against the local position which corresponds with 30 degrees times
+the time-difference towards Greenwich.
+.Pp
+The new and full moons are happening on the day indicated: They
+might happen in the time period in the early night or in the late
+evening.
+It does not indicate that they are starting in the night on that date.
+.Pp
+Because of minor differences between the output of the formulas
+used and other sources on the Internet, Druids and Werewolves should
+double-check the start and end time of solar and lunar events.
+.Sh BUGS
+The
+.Nm
+does only recognise the cpp directives #include, #define, #ifdef,
+#ifndef and #else.
+It supports nested conditions, but does not perform any validation
+on the correct use and nesting of conditions.
+#endif without prior #ifdef or #define is ignored and #else outside
+a conditional section skips input lines up to the next #endif.
+.Pp
+There is no possibility to properly specify the local position
+needed for solar and lunar calculations.
diff --git a/usr.bin/calendar/calendar.c b/usr.bin/calendar/calendar.c
new file mode 100644
index 000000000000..ebc8d7f5c35e
--- /dev/null
+++ b/usr.bin/calendar/calendar.c
@@ -0,0 +1,244 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <login_cap.h>
+#include <langinfo.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "calendar.h"
+
+#define UTCOFFSET_NOTSET 100 /* Expected between -24 and +24 */
+#define LONGITUDE_NOTSET 1000 /* Expected between -360 and +360 */
+
+struct passwd *pw;
+int doall = 0;
+int debug = 0;
+static char *DEBUG = NULL;
+static time_t f_time = 0;
+double UTCOffset = UTCOFFSET_NOTSET;
+int EastLongitude = LONGITUDE_NOTSET;
+#ifdef WITH_ICONV
+const char *outputEncoding = NULL;
+#endif
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int f_dayAfter = 0; /* days after current date */
+ int f_dayBefore = 0; /* days before current date */
+ int Friday = 5; /* day before weekend */
+
+ int ch;
+ struct tm tp1, tp2;
+
+ (void)setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "-A:aB:D:dF:f:l:t:U:W:?")) != -1)
+ switch (ch) {
+ case '-': /* backward contemptible */
+ case 'a':
+ if (getuid()) {
+ errno = EPERM;
+ err(1, NULL);
+ }
+ doall = 1;
+ break;
+
+ case 'W': /* we don't need no steenking Fridays */
+ Friday = -1;
+ /* FALLTHROUGH */
+
+ case 'A': /* days after current date */
+ f_dayAfter = atoi(optarg);
+ if (f_dayAfter < 0)
+ errx(1, "number of days must be positive");
+ break;
+
+ case 'B': /* days before current date */
+ f_dayBefore = atoi(optarg);
+ if (f_dayBefore < 0)
+ errx(1, "number of days must be positive");
+ break;
+
+ case 'D': /* debug output of sun and moon info */
+ DEBUG = optarg;
+ break;
+
+ case 'd': /* debug output of current date */
+ debug = 1;
+ break;
+
+ case 'F': /* Change the time: When does weekend start? */
+ Friday = atoi(optarg);
+ break;
+
+ case 'f': /* other calendar file */
+ calendarFile = optarg;
+ break;
+
+ case 'l': /* Change longitudal position */
+ EastLongitude = strtol(optarg, NULL, 10);
+ break;
+
+ case 't': /* other date, for tests */
+ f_time = Mktime(optarg);
+ break;
+
+ case 'U': /* Change UTC offset */
+ UTCOffset = strtod(optarg, NULL);
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ usage();
+
+ /* use current time */
+ if (f_time <= 0)
+ (void)time(&f_time);
+
+ /* if not set, determine where I could be */
+ {
+ if (UTCOffset == UTCOFFSET_NOTSET &&
+ EastLongitude == LONGITUDE_NOTSET) {
+ /* Calculate on difference between here and UTC */
+ time_t t;
+ struct tm tm;
+ long utcoffset, hh, mm, ss;
+ double uo;
+
+ time(&t);
+ localtime_r(&t, &tm);
+ utcoffset = tm.tm_gmtoff;
+ /* seconds -> hh:mm:ss */
+ hh = utcoffset / SECSPERHOUR;
+ utcoffset %= SECSPERHOUR;
+ mm = utcoffset / SECSPERMINUTE;
+ utcoffset %= SECSPERMINUTE;
+ ss = utcoffset;
+
+ /* hh:mm:ss -> hh.mmss */
+ uo = mm + (100.0 * (ss / 60.0));
+ uo /= 60.0 / 100.0;
+ uo = hh + uo / 100;
+
+ UTCOffset = uo;
+ EastLongitude = UTCOffset * 15;
+ } else if (UTCOffset == UTCOFFSET_NOTSET) {
+ /* Base on information given */
+ UTCOffset = EastLongitude / 15;
+ } else if (EastLongitude == LONGITUDE_NOTSET) {
+ /* Base on information given */
+ EastLongitude = UTCOffset * 15;
+ }
+ }
+
+ settimes(f_time, f_dayBefore, f_dayAfter, Friday, &tp1, &tp2);
+ generatedates(&tp1, &tp2);
+
+ /*
+ * FROM now on, we are working in UTC.
+ * This will only affect moon and sun related events anyway.
+ */
+ if (setenv("TZ", "UTC", 1) != 0)
+ errx(1, "setenv: %s", strerror(errno));
+ tzset();
+
+ if (debug)
+ dumpdates();
+
+ if (DEBUG != NULL) {
+ dodebug(DEBUG);
+ exit(0);
+ }
+
+ if (doall)
+ while ((pw = getpwent()) != NULL) {
+ pid_t pid;
+
+ if (chdir(pw->pw_dir) == -1)
+ continue;
+ pid = fork();
+ if (pid < 0)
+ err(1, "fork");
+ if (pid == 0) {
+ login_cap_t *lc;
+
+ lc = login_getpwclass(pw);
+ if (setusercontext(lc, pw, pw->pw_uid,
+ LOGIN_SETALL & ~LOGIN_SETLOGIN) != 0)
+ errx(1, "setusercontext");
+ setenv("HOME", pw->pw_dir, 1);
+ cal();
+ exit(0);
+ }
+ }
+ else {
+#ifdef WITH_ICONV
+ /* Save the information about the encoding used in the terminal. */
+ outputEncoding = strdup(nl_langinfo(CODESET));
+ if (outputEncoding == NULL)
+ errx(1, "cannot allocate memory");
+#endif
+ cal();
+ }
+ exit(0);
+}
+
+
+static void __dead2
+usage(void)
+{
+
+ fprintf(stderr, "%s\n%s\n%s\n",
+ "usage: calendar [-A days] [-a] [-B days] [-D sun|moon] [-d]",
+ " [-F friday] [-f calendarfile] [-l longitude]",
+ " [-t dd[.mm[.year]]] [-U utcoffset] [-W days]"
+ );
+ exit(1);
+}
diff --git a/usr.bin/calendar/calendar.h b/usr.bin/calendar/calendar.h
new file mode 100644
index 000000000000..333660aaeb8c
--- /dev/null
+++ b/usr.bin/calendar/calendar.h
@@ -0,0 +1,203 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#define SECSPERDAY (24 * 60 * 60)
+#define SECSPERHOUR (60 * 60)
+#define SECSPERMINUTE (60)
+#define MINSPERHOUR (60)
+#define HOURSPERDAY (24)
+#define FSECSPERDAY (24.0 * 60.0 * 60.0)
+#define FSECSPERHOUR (60.0 * 60.0)
+#define FSECSPERMINUTE (60.0)
+#define FMINSPERHOUR (60.0)
+#define FHOURSPERDAY (24.0)
+
+#define DAYSPERYEAR 365
+#define DAYSPERLEAPYEAR 366
+
+/* Not yet categorized */
+
+extern struct passwd *pw;
+extern int doall;
+extern time_t t1, t2;
+extern const char *calendarFile;
+extern int yrdays;
+extern struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+extern struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
+extern double UTCOffset;
+extern int EastLongitude;
+#ifdef WITH_ICONV
+extern const char *outputEncoding;
+#endif
+
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+/* Flags to determine the returned values by determinestyle() in parsedata.c */
+#define F_NONE 0x00000
+#define F_MONTH 0x00001
+#define F_DAYOFWEEK 0x00002
+#define F_DAYOFMONTH 0x00004
+#define F_MODIFIERINDEX 0x00008
+#define F_MODIFIEROFFSET 0x00010
+#define F_SPECIALDAY 0x00020
+#define F_ALLMONTH 0x00040
+#define F_ALLDAY 0x00080
+#define F_VARIABLE 0x00100
+#define F_EASTER 0x00200
+#define F_CNY 0x00400
+#define F_PASKHA 0x00800
+#define F_NEWMOON 0x01000
+#define F_FULLMOON 0x02000
+#define F_MAREQUINOX 0x04000
+#define F_SEPEQUINOX 0x08000
+#define F_JUNSOLSTICE 0x10000
+#define F_DECSOLSTICE 0x20000
+#define F_YEAR 0x40000
+
+#define STRING_EASTER "Easter"
+#define STRING_PASKHA "Paskha"
+#define STRING_CNY "ChineseNewYear"
+#define STRING_NEWMOON "NewMoon"
+#define STRING_FULLMOON "FullMoon"
+#define STRING_MAREQUINOX "MarEquinox"
+#define STRING_SEPEQUINOX "SepEquinox"
+#define STRING_JUNSOLSTICE "JunSolstice"
+#define STRING_DECSOLSTICE "DecSolstice"
+
+#define MAXCOUNT 125 /* Random number of maximum number of
+ * repeats of an event. Should be 52
+ * (number of weeks per year), if you
+ * want to show two years then it
+ * should be 104. If you are seeing
+ * more than this you are using this
+ * program wrong.
+ */
+
+/*
+ * All the astronomical calculations are carried out for the meridian 120
+ * degrees east of Greenwich.
+ */
+#define UTCOFFSET_CNY 8.0
+
+extern int debug; /* show parsing of the input */
+extern int year1, year2;
+
+/* events.c */
+/*
+ * Event sorting related functions:
+ * - Use event_add() to create a new event
+ * - Use event_continue() to add more text to the last added event
+ * - Use event_print_all() to display them in time chronological order
+ */
+struct event *event_add(int, int, int, int, char *, char *);
+void event_continue(struct event *events, char *txt);
+void event_print_all(FILE *fp);
+struct event {
+ int year;
+ int month;
+ int day;
+ int var;
+ char *text;
+ char *extra;
+ struct event *next;
+};
+
+/* locale.c */
+
+struct fixs {
+ char *name;
+ size_t len;
+};
+
+extern const char *days[];
+extern const char *fdays[];
+extern const char *fmonths[];
+extern const char *months[];
+extern const char *sequences[];
+extern struct fixs fndays[8]; /* full national days names */
+extern struct fixs fnmonths[13]; /* full national months names */
+extern struct fixs ndays[8]; /* short national days names */
+extern struct fixs nmonths[13]; /* short national month names */
+extern struct fixs nsequences[10];
+
+void setnnames(void);
+void setnsequences(char *);
+
+/* day.c */
+extern const struct tm tm0;
+extern char dayname[];
+void settimes(time_t,int before, int after, int friday, struct tm *tp1, struct tm *tp2);
+time_t Mktime(char *);
+
+/* parsedata.c */
+int parsedaymonth(char *, int *, int *, int *, int *, char **);
+void dodebug(char *type);
+
+/* io.c */
+void cal(void);
+void closecal(FILE *);
+FILE *opencalin(void);
+FILE *opencalout(void);
+
+/* ostern.c / paskha.c */
+int paskha(int);
+int easter(int);
+int j2g(int);
+
+/* dates.c */
+extern int cumdaytab[][14];
+extern int monthdaytab[][14];
+extern int debug_remember;
+void generatedates(struct tm *tp1, struct tm *tp2);
+void dumpdates(void);
+int remember_ymd(int y, int m, int d);
+int remember_yd(int y, int d, int *rm, int *rd);
+int first_dayofweek_of_year(int y);
+int first_dayofweek_of_month(int y, int m);
+int walkthrough_dates(struct event **e);
+void addtodate(struct event *e);
+
+/* pom.c */
+#define MAXMOONS 18
+void pom(int year, double UTCoffset, int *fms, int *nms);
+void fpom(int year, double utcoffset, double *ffms, double *fnms);
+
+/* sunpos.c */
+void equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int *solsticedays);
+void fequinoxsolstice(int year, double UTCoffset, double *equinoxdays, double *solsticedays);
+int calculatesunlongitude30(int year, int degreeGMToffset, int *ichinesemonths);
+
+#ifdef WITH_ICONV
+void set_new_encoding(void);
+#endif
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
new file mode 100644
index 000000000000..0b1a37f43723
--- /dev/null
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -0,0 +1,509 @@
+/*
+ * FreeBSD
+ */
+
+#ifndef _calendar_freebsd_
+#define _calendar_freebsd_
+
+01/01 Dimitry Andric <dim@FreeBSD.org> born in Utrecht, the Netherlands, 1969
+01/01 Lev Serebryakov <lev@FreeBSD.org> born in Leningrad, USSR, 1979
+01/01 Alexander Langer <alex@FreeBSD.org> born in Duesseldorf, Nordrhein-Westfalen, Germany, 1981
+01/01 Zach Leslie <zleslie@FreeBSD.org> born in Grand Junction, Colorado, United States, 1985
+01/02 Ion-Mihai "IOnut" Tetcu <itetcu@FreeBSD.org> born in Bucharest, Romania, 1980
+01/02 Patrick Li <pat@FreeBSD.org> born in Beijing, People's Republic of China, 1985
+01/03 Tetsurou Okazaki <okazaki@FreeBSD.org> born in Mobara, Chiba, Japan, 1972
+01/04 Hiroyuki Hanai <hanai@FreeBSD.org> born in Kagawa pre., Japan, 1969
+01/05 D Scott Phillips <scottph@FreeBSD.org> born in Anderson, Indiana, 1983
+01/06 Adriaan de Groot <adridg@FreeBSD.org> born in Calgary, Canada, 1973
+01/06 Philippe Audeoud <jadawin@FreeBSD.org> born in Bretigny-Sur-Orge, France, 1980
+01/06 Michael Osipov <michaelo@FreeBSD.org> born in Baku, USSR, 1983
+01/08 Michael L. Hostbaek <mich@FreeBSD.org> born in Copenhagen, Denmark, 1977
+01/10 Jean-Yves Lefort <jylefort@FreeBSD.org> born in Charleroi, Belgium, 1980
+01/10 Guangyuan Yang <ygy@FreeBSD.org> born in Yangzhou, Jiangsu, People's Republic of China, 1997
+01/12 Yen-Ming Lee <leeym@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1977
+01/12 Ying-Chieh Liao <ijliao@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1979
+01/12 Kristof Provost <kp@FreeBSD.org> born in Aalst, Belgium, 1983
+01/13 Ruslan Bukin <br@FreeBSD.org> born in Dudinka, Russian Federation, 1985
+01/14 Yi-Jheng Lin <yzlin@FreeBSD.org> born in Taichung, Taiwan, Republic of China, 1985
+01/15 Anne Dickison <anne@FreeBSD.org> born in Madison, Indiana, United States, 1976
+01/16 Ariff Abdullah <ariff@FreeBSD.org> born in Kuala Lumpur, Malaysia, 1978
+01/16 Dmitry Sivachenko <demon@FreeBSD.org> born in Moscow, USSR, 1978
+01/16 Vanilla I. Shu <vanilla@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1978
+01/17 Raphael Kubo da Costa <rakuco@FreeBSD.org> born in Sao Paulo, Sao Paulo, Brazil, 1989
+01/18 Dejan Lesjak <lesi@FreeBSD.org> born in Ljubljana, Slovenia, Yugoslavia, 1977
+01/19 Marshall Kirk McKusick <mckusick@FreeBSD.org> born in Wilmington, Delaware, United States, 1954
+01/19 Ruslan Ermilov <ru@FreeBSD.org> born in Simferopol, USSR, 1974
+01/19 Marcelo S. Araujo <araujo@FreeBSD.org> born in Joinville, Santa Catarina, Brazil, 1981
+01/20 Poul-Henning Kamp <phk@FreeBSD.org> born in Korsoer, Denmark, 1966
+01/21 Mahdi Mokhtari <mmokhi@FreeBSD.org> born in Tehran, Iran, 1995
+01/21 Mitchell Horne <mhorne@FreeBSD.org> born in Toronto, Ontario, Canada, 1997
+01/22 Johann Visagie <wjv@FreeBSD.org> born in Cape Town, South Africa, 1970
+01/23 Hideyuki KURASHINA <rushani@FreeBSD.org> born in Niigata, Japan, 1982
+01/24 Fabien Thomas <fabient@FreeBSD.org> born in Avignon, France, 1971
+01/24 Matteo Riondato <matteo@FreeBSD.org> born in Padova, Italy, 1986
+01/25 Nick Hibma <n_hibma@FreeBSD.org> born in Groningen, the Netherlands, 1972
+01/25 Bernd Walter <ticso@FreeBSD.org> born in Moers, Nordrhein-Westfalen, Germany, 1974
+01/26 Andrew Gallatin <gallatin@FreeBSD.org> born in Buffalo, New York, United States, 1970
+01/27 Nick Sayer <nsayer@FreeBSD.org> born in San Diego, California, United States, 1968
+01/27 Jacques Anthony Vidrine <nectar@FreeBSD.org> born in Baton Rouge, Louisiana, United States, 1971
+01/27 Alexandre C. Guimaraes <rigoletto@FreeBSD.org> born in Rio de Janeiro, Rio de Janeiro, Brazil, 1982
+01/27 Enji Cooper <ngie@FreeBSD.org> born in Seattle, Washington, United States, 1984
+01/31 Hidetoshi Shimokawa <simokawa@FreeBSD.org> born in Yokohama, Kanagawa, Japan, 1970
+02/01 Doug Rabson <dfr@FreeBSD.org> born in London, England, 1966
+02/01 Nicola Vitale <nivit@FreeBSD.org> born in Busto Arsizio, Varese, Italy, 1976
+02/01 Paul Saab <ps@FreeBSD.org> born in Champaign-Urbana, Illinois, United States, 1978
+02/01 Martin Wilke <miwi@FreeBSD.org> born in Ludwigsfelde, Brandenburg, Germany, 1980
+02/01 Christian Brueffer <brueffer@FreeBSD.org> born in Gronau, Nordrhein-Westfalen, Germany, 1982
+02/01 Steven Kreuzer <skreuzer@FreeBSD.org> born in Oceanside, New York, United States, 1982
+02/01 Juli Mallett <jmallett@FreeBSD.org> born in Washington, Pennsylvania, United States, 1985
+02/02 Diomidis D. Spinellis <dds@FreeBSD.org> born in Athens, Greece, 1967
+02/02 Michael W Lucas <mwlucas@FreeBSD.org> born in Detroit, Michigan, United States, 1967
+02/02 Dmitry Chagin <dchagin@FreeBSD.org> born in Stalingrad, USSR, 1976
+02/02 Yoichi Nakayama <yoichi@FreeBSD.org> born in Tsu, Mie, Japan, 1976
+02/02 Yoshihiro Takahashi <nyan@FreeBSD.org> born in Yokohama, Kanagawa, Japan, 1976
+02/03 Jason Helfman <jgh@FreeBSD.org> born in Royal Oak, Michigan, United States, 1972
+02/03 Mateusz Piotrowski <0mp@FreeBSD.org> born in Warsaw, Poland, 1995
+02/04 Eitan Adler <eadler@FreeBSD.org> born in West Hempstead, New York, United States, 1991
+02/05 Frank Laszlo <laszlof@FreeBSD.org> born in Howell, Michigan, United States, 1983
+02/06 Julien Charbon <jch@FreeBSD.org> born in Saint Etienne, Loire, France, 1978
+02/07 Bjoern Heidotting <bhd@FreeBSD.org> born in Uelsen, Germany, 1980
+02/10 David Greenman <dg@FreeBSD.org> born in Portland, Oregon, United States, 1968
+02/10 Paul Richards <paul@FreeBSD.org> born in Ammanford, Carmarthenshire, United Kingdom, 1968
+02/10 Simon Barner <barner@FreeBSD.org> born in Rosenheim, Bayern, Germany, 1980
+02/10 Jason E. Hale <jhale@FreeBSD.org> born in Pittsburgh, Pennsylvania, United States, 1982
+02/13 Jesper Skriver <jesper@FreeBSD.org> born in Aarhus, Denmark, 1975
+02/13 Steve Wills <swills@FreeBSD.org> born in Lynchburg, Virginia, United States, 1975
+02/13 Andrey Slusar <anray@FreeBSD.org> born in Odessa, USSR, 1979
+02/13 David W. Chapman Jr. <dwcjr@FreeBSD.org> born in Bethel, Connecticut, United States, 1981
+02/14 Manolis Kiagias <manolis@FreeBSD.org> born in Chania, Greece, 1970
+02/14 Erwin Lansing <erwin@FreeBSD.org> born in 's-Hertogenbosch, the Netherlands, 1975
+02/14 Martin Blapp <mbr@FreeBSD.org> born in Olten, Switzerland, 1976
+02/15 Hiren Panchasara <hiren@FreeBSD.org> born in Ahmedabad, Gujarat, India, 1984
+02/15 Rajesh Kumar M A <rajeshasp@FreeBSD.org> born in Erode, Tamilnadu, India, 1986
+02/16 Justin Hibbits <jhibbits@FreeBSD.org> born in Toledo, Ohio, United States, 1983
+02/16 Tobias Christian Berner <tcberner@FreeBSD.org> born in Bern, Switzerland, 1985
+02/18 Christoph Moench-Tegeder <cmt@FreeBSD.org> born in Hannover, Niedersachsen, Germany, 1980
+02/19 Murray Stokely <murray@FreeBSD.org> born in Jacksonville, Florida, United States, 1979
+02/20 Anders Nordby <anders@FreeBSD.org> born in Oslo, Norway, 1976
+02/21 Alex Samorukov <samm@FreeBSD.org> born in Kyiv, Ukraine, 1981
+02/21 Alexey Zelkin <phantom@FreeBSD.org> born in Simferopol, Ukraine, 1978
+02/22 Brooks Davis <brooks@FreeBSD.org> born in Longview, Washington, United States, 1976
+02/22 Jake Burkholder <jake@FreeBSD.org> born in Maynooth, Ontario, Canada, 1979
+02/23 Peter Wemm <peter@FreeBSD.org> born in Perth, Western Australia, Australia, 1971
+02/23 Mathieu Arnold <mat@FreeBSD.org> born in Champigny sur Marne, Val de Marne, France, 1978
+02/23 Vinícius Zavam <egypcio@FreeBSD.org> born in Fortaleza, Ceará, Brazil, 1986
+02/23 Hartmut Brandt <harti@FreeBSD.org> born in Gera, Germany, 1963
+02/24 Johan Karlsson <johan@FreeBSD.org> born in Mariannelund, Sweden, 1974
+02/24 Colin Percival <cperciva@FreeBSD.org> born in Burnaby, Canada, 1981
+02/24 Brandon Bergren <bdragon@FreeBSD.org> born in Edmond, Oklahoma, United States, 1984
+02/25 Kevin Bowling <kbowling@FreeBSD.org> born in Scottsdale, Arizona, United States, 1989
+02/26 Pietro Cerutti <gahr@FreeBSD.org> born in Faido, Switzerland, 1984
+02/28 Daichi GOTO <daichi@FreeBSD.org> born in Shimizu Suntou, Shizuoka, Japan, 1980
+02/28 Ruslan Makhmatkhanov <rm@FreeBSD.org> born in Rostov-on-Don, USSR, 1984
+03/01 Hye-Shik Chang <perky@FreeBSD.org> born in Daejeon, Republic of Korea, 1980
+03/02 Cy Schubert <cy@FreeBSD.org> born in Edmonton, Alberta, Canada, 1956
+03/03 Sergey Matveychuk <sem@FreeBSD.org> born in Moscow, Russian Federation, 1973
+03/03 Doug White <dwhite@FreeBSD.org> born in Eugene, Oregon, United States, 1977
+03/03 Gordon Tetlow <gordon@FreeBSD.org> born in Reno, Nevada, United States, 1978
+03/04 Oleksandr Tymoshenko <gonzo@FreeBSD.org> born in Chernihiv, Ukraine, 1980
+03/05 Baptiste Daroussin <bapt@FreeBSD.org> born in Beauvais, France, 1980
+03/05 Philip Paeps <philip@FreeBSD.org> born in Leuven, Belgium, 1983
+03/05 Ulf Lilleengen <lulf@FreeBSD.org> born in Hamar, Norway, 1985
+03/06 Christopher Piazza <cpiazza@FreeBSD.org> born in Kamloops, British Columbia, Canada, 1981
+03/07 Michael P. Pritchard <mpp@FreeBSD.org> born in Los Angeles, California, United States, 1964
+03/07 Giorgos Keramidas <keramida@FreeBSD.org> born in Athens, Greece, 1976
+03/10 Andreas Klemm <andreas@FreeBSD.org> born in Duesseldorf, Nordrhein-Westfalen, Germany, 1963
+03/10 Luiz Otavio O Souza <loos@FreeBSD.org> born in Bauru, Sao Paulo, Brazil, 1978
+03/10 Nikolai Lifanov <lifanov@FreeBSD.org> born in Moscow, Russian Federation, 1989
+03/11 Soeren Straarup <xride@FreeBSD.org> born in Andst, Denmark, 1978
+03/12 Greg Lewis <glewis@FreeBSD.org> born in Adelaide, South Australia, Australia, 1969
+03/13 Alexander Leidinger <netchild@FreeBSD.org> born in Neunkirchen, Saarland, Germany, 1976
+03/13 Will Andrews <will@FreeBSD.org> born in Pontiac, Michigan, United States, 1982
+03/14 Bernhard Froehlich <decke@FreeBSD.org> born in Graz, Styria, Austria, 1985
+03/14 Eric Turgeon <ericbsd@FreeBSD.org> born in Edmundston, New Brunswick, Canada, 1982
+03/15 Paolo Pisati <piso@FreeBSD.org> born in Lodi, Italy, 1977
+03/15 Brian Fundakowski Feldman <green@FreeBSD.org> born in Alexandria, Virginia, United States, 1983
+03/15 First quarterly status reports are due on 03/31
+03/17 Michael Smith <msmith@FreeBSD.org> born in Bankstown, New South Wales, Australia, 1971
+03/17 Alexander Motin <mav@FreeBSD.org> born in Simferopol, Ukraine, 1979
+03/18 Koop Mast <kwm@FreeBSD.org> born in Dokkum, the Netherlands, 1981
+03/19 Mikhail Teterin <mi@FreeBSD.org> born in Kyiv, Ukraine, 1972
+03/19 Dmitry Salychev <dsl@FreeBSD.org> born in Sverdlovsk, Sverdlovskaya oblast, USSR, 1991
+03/20 Joseph S. Atkinson <jsa@FreeBSD.org> born in Batesville, Arkansas, United States, 1977
+03/20 Henrik Brix Andersen <brix@FreeBSD.org> born in Aarhus, Denmark, 1978
+03/20 MANTANI Nobutaka <nobutaka@FreeBSD.org> born in Hiroshima, Japan, 1978
+03/20 Cameron Grant <cg@FreeBSD.org> died in Hemel Hempstead, United Kingdom, 2005
+03/22 Brad Davis <brd@FreeBSD.org> born in Farmington, New Mexico, United States, 1983
+03/23 Daniel C. Sobral <dcs@FreeBSD.org> born in Brasilia, Distrito Federal, Brazil, 1971
+03/23 Benno Rice <benno@FreeBSD.org> born in Adelaide, South Australia, Australia, 1977
+03/24 Marcel Moolenaar <marcel@FreeBSD.org> born in Hilversum, the Netherlands, 1968
+03/24 Emanuel Haupt <ehaupt@FreeBSD.org> born in Zurich, Switzerland, 1979
+03/25 Andrew R. Reiter <arr@FreeBSD.org> born in Springfield, Massachusetts, United States, 1980
+03/26 Jonathan Anderson <jonathan@FreeBSD.org> born in Ottawa, Ontario, Canada, 1983
+03/27 Josef El-Rayes <josef@FreeBSD.org> born in Linz, Austria, 1982
+03/28 Sean C. Farley <scf@FreeBSD.org> born in Indianapolis, Indiana, United States, 1970
+03/29 Neel Chauhan <nc@FreeBSD.org> born in Williamsville, New York, United States, 1997
+03/29 Dave Cottlehuber <dch@FreeBSD.org> born in Christchurch, New Zealand, 1973
+03/29 Thierry Thomas <thierry@FreeBSD.org> born in Luxeuil les Bains, France, 1961
+03/30 Po-Chuan Hsieh <sunpoet@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1978
+04/01 Matthew Jacob <mjacob@FreeBSD.org> born in San Francisco, California, United States, 1958
+04/01 Alexander V. Chernikov <melifaro@FreeBSD.org> born in Moscow, Russian Federation, 1984
+04/01 Bill Fenner <fenner@FreeBSD.org> born in Bellefonte, Pennsylvania, United States, 1971
+04/01 Peter Edwards <peadar@FreeBSD.org> born in Dublin, Ireland, 1973
+04/03 Hellmuth Michaelis <hm@FreeBSD.org> born in Kiel, Schleswig-Holstein, Germany, 1958
+04/03 Tong Liu <nemoliu@FreeBSD.org> born in Beijing, People's Republic of China, 1981
+04/03 Gabor Pali <pgj@FreeBSD.org> born in Kunhegyes, Hungary, 1982
+04/04 Jason Unovitch <junovitch@FreeBSD.org> born in Scranton, Pennsylvania, United States, 1986
+04/05 Stacey Son <sson@FreeBSD.org> born in Burley, Idaho, United States, 1967
+04/06 Peter Jeremy <peterj@FreeBSD.org> born in Sydney, New South Wales, Australia, 1961
+04/07 Edward Tomasz Napierala <trasz@FreeBSD.org> born in Wolsztyn, Poland, 1981
+04/08 Jordan K. Hubbard <jkh@FreeBSD.org> born in Honolulu, Hawaii, United States, 1963
+04/09 Ceri Davies <ceri@FreeBSD.org> born in Haverfordwest, Pembrokeshire, United Kingdom, 1976
+04/11 Bruce A. Mah <bmah@FreeBSD.org> born in Fresno, California, United States, 1969
+04/12 Patrick Gardella <patrick@FreeBSD.org> born in Columbus, Ohio, United States, 1967
+04/12 Ed Schouten <ed@FreeBSD.org> born in Oss, the Netherlands, 1986
+04/12 Ruey-Cherng Yu <rcyu@FreeBSD.org> born in Keelung, Taiwan, 1978
+04/13 Oliver Braun <obraun@FreeBSD.org> born in Nuremberg, Bavaria, Germany, 1972
+04/14 Crist J. Clark <cjc@FreeBSD.org> born in Milwaukee, Wisconsin, United States, 1970
+04/14 Glen J. Barber <gjb@FreeBSD.org> born in Wilkes-Barre, Pennsylvania, United States, 1981
+04/15 David Malone <dwmalone@FreeBSD.org> born in Dublin, Ireland, 1973
+04/17 Alexey Degtyarev <alexey@FreeBSD.org> born in Ahtubinsk, Russian Federation, 1984
+04/17 Dryice Liu <dryice@FreeBSD.org> born in Jinan, Shandong, China, 1975
+04/22 Joerg Wunsch <joerg@FreeBSD.org> born in Dresden, Sachsen, Germany, 1962
+04/22 Jun Kuriyama <kuriyama@FreeBSD.org> born in Matsue, Shimane, Japan, 1973
+04/22 Jakub Klama <jceel@FreeBSD.org> born in Blachownia, Silesia, Poland, 1989
+04/25 Richard Gallamore <ultima@FreeBSD.org> born in Kissimmee, Florida, United States, 1987
+04/26 Rene Ladan <rene@FreeBSD.org> born in Geldrop, the Netherlands, 1980
+04/28 Oleg Bulyzhin <oleg@FreeBSD.org> born in Kharkov, USSR, 1976
+04/28 Andriy Voskoboinyk <avos@FreeBSD.org> born in Bila Tserkva, Ukraine, 1992
+04/28 Nuno Teixeira <eduardo@FreeBSD.org> born in Aveiro, Portugal, 1974
+04/29 Adam Weinberger <adamw@FreeBSD.org> born in Berkeley, California, United States, 1980
+04/29 Eric Anholt <anholt@FreeBSD.org> born in Portland, Oregon, United States, 1983
+05/01 Randall Stewart <rrs@FreeBSD.org> born in Spokane, Washington, United States, 1959
+05/01 Igor Ostapenko <igoro@FreeBSD.org> born in Astana, Kazakhstan, 1985
+05/02 Kai Knoblich <kai@FreeBSD.org> born in Hannover, Niedersachsen, Germany, 1982
+05/02 Danilo G. Baio <dbaio@FreeBSD.org> born in Maringa, Parana, Brazil, 1986
+05/02 Wojciech A. Koszek <wkoszek@FreeBSD.org> born in Czestochowa, Poland, 1987
+05/03 Brian Dean <bsd@FreeBSD.org> born in Elkins, West Virginia, United States, 1966
+05/03 Patrick Kelsey <pkelsey@FreeBSD.org> born in Freehold, New Jersey, United States, 1976
+05/03 Robert Nicholas Maxwell Watson <rwatson@FreeBSD.org> born in Harrow, Middlesex, United Kingdom, 1977
+05/04 Denis Peplin <den@FreeBSD.org> born in Nizhniy Novgorod, Russian Federation, 1977
+05/08 Kirill Ponomarew <krion@FreeBSD.org> born in Volgograd, Russian Federation, 1977
+05/08 Sean Kelly <smkelly@FreeBSD.org> born in Walnut Creek, California, United States, 1982
+05/09 Daniel Eischen <deischen@FreeBSD.org> born in Syracuse, New York, United States, 1963
+05/09 Aaron Dalton <aaron@FreeBSD.org> born in Boise, Idaho, United States, 1973
+05/09 Jase Thew <jase@FreeBSD.org> born in Abergavenny, Gwent, United Kingdom, 1974
+05/09 Leandro Lupori <luporl@FreeBSD.org> born in Sao Paulo, Sao Paulo, Brazil, 1983
+05/10 Markus Brueffer <markus@FreeBSD.org> born in Gronau, Nordrhein-Westfalen, Germany, 1977
+05/11 Kurt Lidl <lidl@FreeBSD.org> born in Rockville, Maryland, United States, 1968
+05/11 Jesus Rodriguez <jesusr@FreeBSD.org> born in Barcelona, Spain, 1972
+05/11 Marcin Wojtas <mw@FreeBSD.org> born in Krakow, Poland, 1986
+05/11 Roman Kurakin <rik@FreeBSD.org> born in Moscow, USSR, 1979
+05/11 Ulrich Spoerlein <uqs@FreeBSD.org> born in Schesslitz, Bayern, Germany, 1981
+05/12 Gabriel M. Dutra <dutra@FreeBSD.org> born in Marialva, Parana, Brazil, 1998
+05/13 Pete Fritchman <petef@FreeBSD.org> born in Lansdale, Pennsylvania, United States, 1983
+05/13 Ben Widawsky <bwidawsk@FreeBSD.org> born in New York City, New York, United States, 1982
+05/14 Tatsumi Hosokawa <hosokawa@FreeBSD.org> born in Tokyo, Japan, 1968
+05/14 Shigeyuku Fukushima <shige@FreeBSD.org> born in Osaka, Japan, 1974
+05/14 Rebecca Cran <bcran@FreeBSD.org> born in Cambridge, United Kingdom, 1981
+05/15 Hans Petter Selasky <hselasky@FreeBSD.org> born in Flekkefjord, Norway, 1982
+05/16 Johann Kois <jkois@FreeBSD.org> born in Wolfsberg, Austria, 1975
+05/16 Marcus Alves Grando <mnag@FreeBSD.org> born in Florianopolis, Santa Catarina, Brazil, 1979
+05/17 Thomas Abthorpe <tabthorpe@FreeBSD.org> born in Port Arthur, Ontario, Canada, 1968
+05/18 Zsolt Udvari <uzsolt@FreeBSD.org> born in Hodmezovasarhely, Hungary, 1981
+05/19 Philippe Charnier <charnier@FreeBSD.org> born in Fontainebleau, France, 1966
+05/19 Ian Dowse <iedowse@FreeBSD.org> born in Dublin, Ireland, 1975
+05/19 Sofian Brabez <sbz@FreeBSD.org> born in Toulouse, France, 1984
+05/20 Dan Moschuk <dan@FreeBSD.org> died in Burlington, Ontario, Canada, 2010
+05/21 Kris Kennaway <kris@FreeBSD.org> born in Winnipeg, Manitoba, Canada, 1978
+05/22 James Gritton <jamie@FreeBSD.org> born in San Francisco, California, United States, 1967
+05/22 Clive Tong-I Lin <clive@FreeBSD.org> born in Changhua, Taiwan, Republic of China, 1978
+05/22 Michael Bushkov <bushman@FreeBSD.org> born in Rostov-on-Don, Russian Federation, 1985
+05/22 Rui Paulo <rpaulo@FreeBSD.org> born in Evora, Portugal, 1986
+05/22 David Naylor <dbn@FreeBSD.org> born in Johannesburg, South Africa, 1988
+05/22 Juraj Lutter <otis@FreeBSD.org> born in Trnava, Slovakia, 1979
+05/23 Dries Michiels <driesm@FreeBSD.org> born in Asse, Belgium, 1993
+05/23 Munechika Sumikawa <sumikawa@FreeBSD.org> born in Osaka, Osaka, Japan, 1972
+05/24 Duncan McLennan Barclay <dmlb@FreeBSD.org> born in London, Middlesex, United Kingdom, 1970
+05/24 Oliver Lehmann <oliver@FreeBSD.org> born in Karlsburg, Germany, 1981
+05/25 Pawel Pekala <pawel@FreeBSD.org> born in Swidnica, Poland, 1980
+05/25 Tom Rhodes <trhodes@FreeBSD.org> born in Ellwood City, Pennsylvania, United States, 1981
+05/25 Roman Divacky <rdivacky@FreeBSD.org> born in Brno, Czech Republic, 1983
+05/26 Jim Pirzyk <pirzyk@FreeBSD.org> born in Chicago, Illinois, United States, 1968
+05/26 Florian Smeets <flo@FreeBSD.org> born in Schwerte, Nordrhein-Westfalen, Germany, 1982
+05/27 Ollivier Robert <roberto@FreeBSD.org> born in Paris, France, 1967
+05/29 Wilko Bulte <wilko@FreeBSD.org> born in Arnhem, the Netherlands, 1965
+05/29 Seigo Tanimura <tanimura@FreeBSD.org> born in Kitakyushu, Fukuoka, Japan, 1976
+05/30 Wen Heping <wen@FreeBSD.org> born in Xiangxiang, Hunan, China, 1970
+05/31 Ville Skytta <scop@FreeBSD.org> born in Helsinki, Finland, 1974
+06/02 Jean-Marc Zucconi <jmz@FreeBSD.org> born in Pontarlier, France, 1954
+06/02 Alexander Botero-Lowry <alexbl@FreeBSD.org> born in Austin, Texas, United States, 1986
+06/03 CHOI Junho <cjh@FreeBSD.org> born in Seoul, Korea, 1974
+06/03 Wesley Shields <wxs@FreeBSD.org> born in Binghamton, New York, United States, 1981
+06/04 Julian Elischer <julian@FreeBSD.org> born in Perth, Australia, 1959
+06/04 Justin Gibbs <gibbs@FreeBSD.org> born in San Pedro, California, United States, 1973
+06/04 Jason Evans <jasone@FreeBSD.org> born in Greeley, Colorado, United States, 1973
+06/04 Thomas Moestl <tmm@FreeBSD.org> born in Braunschweig, Niedersachsen, Germany, 1980
+06/04 Devin Teske <dteske@FreeBSD.org> born in Arcadia, California, United States, 1982
+06/04 Zack Kirsch <zack@FreeBSD.org> born in Memphis, Tennessee, United States, 1982
+06/04 Johannes Jost Meixner <xmj@FreeBSD.org> born in Wiesbaden, Germany, 1987
+06/05 Johannes Lundberg <johalun@FreeBSD.org> born in Ornskoldsvik, Sweden, 1975
+06/06 Sergei Kolobov <sergei@FreeBSD.org> born in Karpinsk, Russian Federation, 1972
+06/06 Ryan Libby <rlibby@FreeBSD.org> born in Kirkland, Washington, United States, 1985
+06/06 Alan Eldridge <alane@FreeBSD.org> died in Denver, Colorado, United States, 2003
+06/07 Jimmy Olgeni <olgeni@FreeBSD.org> born in Milano, Italy, 1976
+06/07 Benjamin Close <benjsc@FreeBSD.org> born in Adelaide, Australia, 1978
+06/07 Roger Pau Monne <royger@FreeBSD.org> born in Reus, Catalunya, Spain, 1986
+06/08 Ravi Pokala <rpokala@FreeBSD.org> born in Royal Oak, Michigan, United States, 1980
+06/09 Stanislav Galabov <sgalabov@FreeBSD.org> born in Sofia, Bulgaria, 1978
+06/11 Alonso Cardenas Marquez <acm@FreeBSD.org> born in Arequipa, Peru, 1979
+06/14 Josh Paetzel <jpaetzel@FreeBSD.org> born in Minneapolis, Minnesota, United States, 1973
+06/15 Second quarterly status reports are due on 06/30
+06/17 Tilman Linneweh <arved@FreeBSD.org> born in Weinheim, Baden-Wuerttemberg, Germany, 1978
+06/18 Li-Wen Hsu <lwhsu@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1984
+06/18 Roman Bogorodskiy <novel@FreeBSD.org> born in Saratov, Russian Federation, 1986
+06/19 Charlie Root <root@FreeBSD.org> born in Portland, Oregon, United States, 1993
+06/21 Ganbold Tsagaankhuu <ganbold@FreeBSD.org> born in Ulaanbaatar, Mongolia, 1971
+06/21 Niels Heinen <niels@FreeBSD.org> born in Markelo, the Netherlands, 1978
+06/22 Andreas Tobler <andreast@FreeBSD.org> born in Heiden, Switzerland, 1968
+06/24 Chris Faulhaber <jedgar@FreeBSD.org> born in Springfield, Illinois, United States, 1971
+06/26 Brian Somers <brian@FreeBSD.org> born in Dundrum, Dublin, Ireland, 1967
+06/28 Mark Santcroos <marks@FreeBSD.org> born in Rotterdam, the Netherlands, 1979
+06/28 Xin Li <delphij@FreeBSD.org> born in Beijing, People's Republic of China, 1982
+06/28 Bradley T. Hughes <bhughes@FreeBSD.org> born in Amarillo, Texas, United States, 1977
+06/29 Wilfredo Sanchez Vega <wsanchez@FreeBSD.org> born in Majaguez, Puerto Rico, United States, 1972
+06/29 Daniel Harris <dannyboy@FreeBSD.org> born in Lubbock, Texas, United States, 1985
+06/29 Andrew Pantyukhin <sat@FreeBSD.org> born in Moscow, Russian Federation, 1985
+06/30 Guido van Rooij <guido@FreeBSD.org> born in Best, Noord-Brabant, the Netherlands, 1965
+07/01 Matthew Dillon <dillon@apollo.backplane.net> born in San Francisco, California, United States, 1966
+07/01 Mateusz Guzik <mjg@FreeBSD.org> born in Dołki Górne, Poland, 1986
+07/02 Mark Christopher Ovens <marko@FreeBSD.org> born in Preston, Lancashire, United Kingdom, 1958
+07/02 Vasil Venelinov Dimov <vd@FreeBSD.org> born in Shumen, Bulgaria, 1982
+07/04 Motoyuki Konno <motoyuki@FreeBSD.org> born in Musashino, Tokyo, Japan, 1969
+07/04 Florent Thoumie <flz@FreeBSD.org> born in Montmorency, Val d'Oise, France, 1982
+07/04 Jake Freeland <jfree@FreeBSD.org> born in St. Paul, Minnesota, United States, 2003
+07/05 Olivier Cochard-Labbe <olivier@FreeBSD.org> born in Brest, France, 1977
+07/05 Sergey Kandaurov <pluknet@FreeBSD.org> born in Gubkin, Russian Federation, 1985
+07/06 Oskar Holmlund <oh@FreeBSD.org> born in Solleftea, Sweden, 1981
+07/07 Andrew Thompson <thompsa@FreeBSD.org> born in Lower Hutt, Wellington, New Zealand, 1979
+07/07 Maxime Henrion <mux@FreeBSD.org> born in Metz, France, 1981
+07/07 George Reid <greid@FreeBSD.org> born in Frimley, Hampshire, United Kingdom, 1983
+07/10 Jung-uk Kim <jkim@FreeBSD.org> born in Seoul, Korea, 1971
+07/10 Justin Seger <jseger@FreeBSD.org> born in Harvard, Massachusetts, United States, 1981
+07/10 David Schultz <das@FreeBSD.org> born in Oakland, California, United States, 1982
+07/10 Ben Woods <woodsb02@FreeBSD.org> born in Perth, Western Australia, Australia, 1984
+07/11 Jesus R. Camou <jcamou@FreeBSD.org> born in Hermosillo, Sonora, Mexico, 1983
+07/12 Yasuhiro Kimura <yasu@FreeBSD.org> born in Okazaki, Aichi, Japan, 1967
+07/14 Fernando Apesteguia <fernape@FreeBSD.org> born in Madrid, Spain, 1981
+07/15 Gary Jennejohn <gj@FreeBSD.org> born in Rochester, New York, United States, 1950
+07/16 Suleiman Souhlal <ssouhlal@FreeBSD.org> born in Roma, Italy, 1983
+07/16 Davide Italiano <davide@FreeBSD.org> born in Milazzo, Italy, 1989
+07/17 Michael Chin-Yuan Wu <keichii@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1980
+07/18 Arthur Kiyanovski <akiyano@FreeBSD.org> Born in Kilia, Republic of Ukraine, USSR, 1985
+07/19 Masafumi NAKANE <max@FreeBSD.org> born in Okazaki, Aichi, Japan, 1972
+07/19 Simon L. Nielsen <simon@FreeBSD.org> born in Copenhagen, Denmark, 1980
+07/19 Gleb Smirnoff <glebius@FreeBSD.org> born in Kharkov, USSR, 1981
+07/20 Dru Lavigne <dru@FreeBSD.org> born in Kingston, Ontario, Canada, 1965
+07/20 Andrey V. Elsukov <ae@FreeBSD.org> born in Kotelnich, Russian Federation, 1981
+07/21 Rainer Hurling <rhurlin@FreeBSD.org> born in Oldenburg i.O., Lower Saxony, Germany, 1963
+07/22 James Housley <jeh@FreeBSD.org> born in Chicago, Illinois, United States, 1965
+07/22 Jens Schweikhardt <schweikh@FreeBSD.org> born in Waiblingen, Baden-Wuerttemberg, Germany, 1967
+07/22 Lukas Ertl <le@FreeBSD.org> born in Weissenbach/Enns, Steiermark, Austria, 1976
+07/23 Sergey A. Osokin <osa@FreeBSD.org> born in Krasnogorsky, Stepnogorsk, Akmolinskaya region, Kazakhstan, 1972
+07/23 Andrey Zonov <zont@FreeBSD.org> born in Kirov, Russian Federation, 1985
+07/24 Alexander Nedotsukov <bland@FreeBSD.org> born in Ulyanovsk, Russian Federation, 1974
+07/24 Alberto Villa <avilla@FreeBSD.org> born in Vercelli, Italy, 1987
+07/27 Andriy Gapon <avg@FreeBSD.org> born in Kyrykivka, Sumy region, Ukraine, 1976
+07/28 Jim Mock <jim@FreeBSD.org> born in Bethlehem, Pennsylvania, United States, 1974
+07/28 Tom Hukins <tom@FreeBSD.org> born in Manchester, United Kingdom, 1976
+07/29 Dirk Meyer <dinoex@FreeBSD.org> born in Kassel, Hessen, Germany, 1965
+07/29 Felippe M. Motta <lippe@FreeBSD.org> born in Maceio, Alagoas, Brazil, 1988
+08/02 Gabor Kovesdan <gabor@FreeBSD.org> born in Budapest, Hungary, 1987
+08/03 Peter Holm <pho@FreeBSD.org> born in Copenhagen, Denmark, 1955
+08/05 Alfred Perlstein <alfred@FreeBSD.org> born in Brooklyn, New York, United States, 1978
+08/06 Anton Berezin <tobez@FreeBSD.org> born in Dnepropetrovsk, Ukraine, 1970
+08/06 John-Mark Gurney <jmg@FreeBSD.org> born in Detroit, Michigan, United States, 1978
+08/06 Damjan Marion <dmarion@FreeBSD.org> born in Rijeka, Croatia, 1978
+08/07 Jonathan Mini <mini@FreeBSD.org> born in San Mateo, California, United States, 1979
+08/08 Mikolaj Golub <trociny@FreeBSD.org> born in Kharkov, USSR, 1977
+08/08 Juergen Lock <nox@FreeBSD.org> died in Bremen, Germany, 2015
+08/09 Stefan Farfeleder <stefanf@FreeBSD.org> died in Wien, Austria, 2015
+08/10 Julio Merino <jmmv@FreeBSD.org> born in Barcelona, Spain, 1984
+08/10 Peter Pentchev <roam@FreeBSD.org> born in Sofia, Bulgaria, 1977
+08/12 Joe Marcus Clarke <marcus@FreeBSD.org> born in Lakeland, Florida, United States, 1976
+08/12 Max Brazhnikov <makc@FreeBSD.org> born in Leningradskaya, Russian Federation, 1979
+08/14 Stefan Esser <se@FreeBSD.org> born in Cologne, Nordrhein-Westfalen, Germany, 1961
+08/16 Andrey Chernov <ache@FreeBSD.org> died in Moscow, Russian Federation, 2017
+08/17 Olivier Houchard <cognet@FreeBSD.org> born in Nancy, France, 1980
+08/19 Chin-San Huang <chinsan@FreeBSD.org> born in Yi-Lan, Taiwan, Republic of China, 1979
+08/19 Pav Lucistnik <pav@FreeBSD.org> born in Kutna Hora, Czech Republic, 1980
+08/20 Michael Heffner <mikeh@FreeBSD.org> born in Cleona, Pennsylvania, United States, 1981
+08/21 Alfredo Dal'Ava Junior <alfredo@FreeBSD.org> born in Pocos de Caldas, Minas Gerais, Brazil, 1981
+08/21 Jason A. Harmening <jah@FreeBSD.org> born in Fort Wayne, Indiana, United States, 1981
+08/22 Ilya Bakulin <kibab@FreeBSD.org> born in Tbilisi, USSR, 1986
+08/24 Mark Linimon <linimon@FreeBSD.org> born in Houston, Texas, United States, 1955
+08/24 Alexander Botero-Lowry <alexbl@FreeBSD.org> died in San Francisco, California, United States, 2012
+08/25 Beech Rintoul <beech@FreeBSD.org> born in Oakland, California, United States, 1952
+08/25 Jean Milanez Melo <jmelo@FreeBSD.org> born in Divinopolis, Minas Gerais, Brazil, 1982
+08/25 Scott Long <scottl@FreeBSD.org> born in Chicago, Illinois, United States, 1974
+08/26 Dima Ruban <dima@FreeBSD.org> born in Nalchik, USSR, 1970
+08/26 Marc Fonvieille <blackend@FreeBSD.org> born in Avignon, France, 1972
+08/26 Herve Quiroz <hq@FreeBSD.org> born in Aix-en-Provence, France, 1977
+08/27 Andrey Chernov <ache@FreeBSD.org> born in Moscow, USSR, 1966
+08/27 Tony Finch <fanf@FreeBSD.org> born in London, United Kingdom, 1974
+08/27 Michael Johnson <ahze@FreeBSD.org> born in Morganton, North Carolina, United States, 1980
+08/28 Norikatsu Shigemura <nork@FreeBSD.org> born in Fujisawa, Kanagawa, Japan, 1974
+08/29 Thomas Gellekum <tg@FreeBSD.org> born in Moenchengladbach, Nordrhein-Westfalen, Germany, 1967
+08/29 Max Laier <mlaier@FreeBSD.org> born in Karlsruhe, Germany, 1981
+08/30 Yuri Pankov <yuripv@FreeBSD.org> born in Krasnodar, USSR, 1979
+09/01 Pyun YongHyeon <yongari@FreeBSD.org> born in Kimcheon, Korea, 1968
+09/01 William Grzybowski <wg@FreeBSD.org> born in Parana, Brazil, 1988
+09/03 Max Khon <fjoe@FreeBSD.org> born in Novosibirsk, USSR, 1976
+09/03 Allan Jude <allanjude@FreeBSD.org> born in Hamilton, Ontario, Canada, 1984
+09/03 Cheng-Lung Sung <clsung@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1977
+09/05 Mark Robert Vaughan Murray <markm@FreeBSD.org> born in Harare, Mashonaland, Zimbabwe, 1961
+09/05 Adrian Harold Chadd <adrian@FreeBSD.org> born in Perth, Western Australia, Australia, 1979
+09/05 Rodrigo Osorio <rodrigo@FreeBSD.org> born in Montevideo, Uruguay, 1975
+09/06 Eric Joyner <erj@FreeBSD.org> born in Fairfax, Virginia, United States, 1991
+09/07 Tim Bishop <tdb@FreeBSD.org> born in Cornwall, United Kingdom, 1978
+09/07 Chris Rees <crees@FreeBSD.org> born in Kettering, United Kingdom, 1987
+09/08 Boris Samorodov <bsam@FreeBSD.org> born in Krasnodar, Russian Federation, 1963
+09/09 Yoshio Mita <mita@FreeBSD.org> born in Hiroshima, Japan, 1972
+09/09 Steven Hartland <smh@FreeBSD.org> born in Wordsley, United Kingdom, 1973
+09/10 Wesley R. Peters <wes@FreeBSD.org> born in Hartford, Alabama, United States, 1961
+09/11 Gordon Bergling <gbe@FreeBSD.org> born in Magdeburg, Germany, 1981
+09/12 Weongyo Jeong <weongyo@FreeBSD.org> born in Haman, Korea, 1980
+09/12 Benedict Christopher Reuschling <bcr@FreeBSD.org> born in Darmstadt, Germany, 1981
+09/12 William C. Fumerola II <billf@FreeBSD.org> born in Detroit, Michigan, United States, 1981
+09/14 Matthew Seaman <matthew@FreeBSD.org> born in Bristol, United Kingdom, 1965
+09/15 Aleksandr Rybalko <ray@FreeBSD.org> born in Odessa, Ukraine, 1977
+09/15 Dima Panov <fluffy@FreeBSD.org> born in Khabarovsk, Russian Federation, 1978
+09/15 Third quarterly status reports are due on 09/30
+09/16 Maksim Yevmenkin <emax@FreeBSD.org> born in Taganrog, USSR, 1974
+09/17 Maxim Bolotin <mb@FreeBSD.org> born in Rostov-on-Don, Russian Federation, 1976
+09/18 Matthew Fleming <mdf@FreeBSD.org> born in Cleveland, Ohio, United States, 1975
+09/20 Kevin Lo <kevlo@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1972
+09/21 Alex Kozlov <ak@FreeBSD.org> born in Bila Tserkva, Ukraine, 1970
+09/21 Gleb Kurtsou <gleb@FreeBSD.org> born in Minsk, Belarus, 1984
+09/22 Alan Somers <asomers@FreeBSD.org> born in San Antonio, Texas, United States, 1982
+09/22 Bryan Drewery <bdrewery@FreeBSD.org> born in San Diego, California, United States, 1984
+09/23 Michael Dexter <dexter@FreeBSD.org> born in Los Angeles, California, 1972
+09/23 Martin Matuska <mm@FreeBSD.org> born in Bratislava, Slovakia, 1979
+09/24 Larry Rosenman <ler@FreeBSD.org> born in Queens, New York, United States, 1957
+09/25 Lewis Cook <lcook@FreeBSD.org> born in London, England, 1998
+09/25 Piotr Kubaj <pkubaj@FreeBSD.org> born in Lubin, Poland, 1991
+09/27 Kyle Evans <kevans@FreeBSD.org> born in Oklahoma City, Oklahoma, United States, 1991
+09/27 Neil Blakey-Milner <nbm@FreeBSD.org> born in Port Elizabeth, South Africa, 1978
+09/27 Renato Botelho <garga@FreeBSD.org> born in Araras, Sao Paulo, Brazil, 1979
+09/28 Greg Lehey <grog@FreeBSD.org> born in Melbourne, Victoria, Australia, 1948
+09/28 Alex Dupre <ale@FreeBSD.org> born in Milano, Italy, 1980
+09/29 Matthew Hunt <mph@FreeBSD.org> born in Johnstown, Pennsylvania, United States, 1976
+09/30 Mark Felder <feld@FreeBSD.org> born in Prairie du Chien, Wisconsin, United States, 1985
+09/30 Hiten M. Pandya <hmp@FreeBSD.org> born in Dar-es-Salaam, Tanzania, East Africa, 1986
+10/02 Beat Gaetzi <beat@FreeBSD.org> born in Zurich, Switzerland, 1980
+10/02 Grzegorz Blach <gblach@FreeBSD.org> born in Starachowice, Poland, 1985
+10/05 Hiroki Sato <hrs@FreeBSD.org> born in Yamagata, Japan, 1977
+10/05 Chris Costello <chris@FreeBSD.org> born in Houston, Texas, United States, 1985
+10/09 Stefan Walter <stefan@FreeBSD.org> born in Werne, Nordrhein-Westfalen, Germany, 1978
+10/11 Rick Macklem <rmacklem@FreeBSD.org> born in Ontario, Canada, 1955
+10/11 Rob Wing <rew@FreeBSD.org> born in Fairbanks, Alaska, 1985
+10/12 Pawel Jakub Dawidek <pjd@FreeBSD.org> born in Radzyn Podlaski, Poland, 1980
+10/15 Maxim Konovalov <maxim@FreeBSD.org> born in Khabarovsk, USSR, 1973
+10/15 Eugene Grosbein <eugen@FreeBSD.org> born in Novokuznetsk, Russian Republic, USSR, 1976
+10/16 Remko Lodder <remko@FreeBSD.org> born in Rotterdam, the Netherlands, 1983
+10/17 Maho NAKATA <maho@FreeBSD.org> born in Osaka, Japan, 1974
+10/18 Sheldon Hearn <sheldonh@FreeBSD.org> born in Cape Town, Western Cape, South Africa, 1974
+10/18 Vladimir Kondratyev <wulf@FreeBSD.org> born in Ryazan, USSR, 1975
+10/19 Nicholas Souchu <nsouch@FreeBSD.org> born in Suresnes, Hauts-de-Seine, France, 1972
+10/19 Nick Barkas <snb@FreeBSD.org> born in Longview, Washington, United States, 1981
+10/19 Pedro Giffuni <pfg@FreeBSD.org> born in Bogotá, Colombia, 1968
+10/20 Joel Dahl <joel@FreeBSD.org> born in Bitterna, Skaraborg, Sweden, 1983
+10/20 Dmitry Marakasov <amdmi3@FreeBSD.org> born in Moscow, Russian Federation, 1984
+10/21 Ben Smithurst <ben@FreeBSD.org> born in Sheffield, South Yorkshire, United Kingdom, 1981
+10/21 Daniel Ebdrup Jensen <debdrup@FreeBSD.org> born in Aalborg, Denmark, 19XX
+10/21 Vladimir Vladimirovich Druzenko <vvd@FreeBSD.org> born in Kishinev, USSR, 1979
+10/22 Jean-Sebastien Pedron <dumbbell@FreeBSD.org> born in Redon, Ille-et-Vilaine, France, 1980
+10/22 R. Christian McDonald <rcm@FreeBSD.org> born in Columbia, South Carolina, United States, 1991
+10/23 Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org> born in Brasilia, Distrito Federal, Brazil, 1976
+10/23 Romain Tartière <romain@FreeBSD.org> born in Clermont-Ferrand, France, 1984
+10/25 Eric Melville <eric@FreeBSD.org> born in Los Gatos, California, United States, 1980
+10/25 Julien Laffaye <jlaffaye@FreeBSD.org> born in Toulouse, France, 1988
+10/25 Ashish SHUKLA <ashish@FreeBSD.org> born in Kanpur, India, 1985
+10/25 Toomas Soome <tsoome@FreeBSD.org> born Estonia, 1971
+10/26 Matthew Ahrens <mahrens@FreeBSD.org> born in United States, 1979
+10/26 Philip M. Gollucci <pgollucci@FreeBSD.org> born in Silver Spring, Maryland, United States, 1979
+10/27 Takanori Watanabe <takawata@FreeBSD.org> born in Numazu, Shizuoka, Japan, 1972
+10/30 Olli Hauer <ohauer@FreeBSD.org> born in Sindelfingen, Germany, 1968
+10/31 Taras Korenko <taras@FreeBSD.org> born in Cherkasy region, Ukraine, 1980
+11/01 Zhenlei Huang <zlei@FreeBSD.org> born in Jingmen, Hubei, People's Republic of China, 1986
+11/03 Ryan Stone <rstone@FreeBSD.org> born in Ottawa, Ontario, Canada, 1985
+11/04 John Hixson <jhixson@FreeBSD.org> born in Burlingame, California, United States, 1974
+11/05 M. Warner Losh <imp@FreeBSD.org> born in Kansas City, Kansas, United States, 1966
+11/06 Michael Zhilin <mizhka@FreeBSD.org> born in Stary Oskol, USSR, 1985
+11/08 Joseph R. Mingrone <jrm@FreeBSD.org> born in Charlottetown, Prince Edward Island, Canada, 1976
+11/09 Coleman Kane <cokane@FreeBSD.org> born in Cincinnati, Ohio, United States, 1980
+11/09 Antoine Brodin <antoine@FreeBSD.org> born in Bagnolet, France, 1981
+11/10 Gregory Neil Shapiro <gshapiro@FreeBSD.org> born in Providence, Rhode Island, United States, 1970
+11/11 Danilo E. Gondolfo <danilo@FreeBSD.org> born in Lobato, Parana, Brazil, 1987
+11/12 Gleb Popov <arrowd@FreeBSD.org> born in Volgograd, Russia, 1991
+11/13 John Baldwin <jhb@FreeBSD.org> born in Stuart, Virginia, United States, 1977
+11/14 Jeremie Le Hen <jlh@FreeBSD.org> born in Nancy, France, 1980
+11/15 Lars Engels <lme@FreeBSD.org> born in Hilden, Nordrhein-Westfalen, Germany, 1980
+11/15 Tijl Coosemans <tijl@FreeBSD.org> born in Duffel, Belgium, 1983
+11/16 Jose Maria Alcaide Salinas <jmas@FreeBSD.org> born in Madrid, Spain, 1962
+11/16 Matt Joras <mjoras@FreeBSD.org> born in Evanston, Illinois, United States, 1992
+11/17 Ralf S. Engelschall <rse@FreeBSD.org> born in Dachau, Bavaria, Germany, 1972
+11/18 Thomas Quinot <thomas@FreeBSD.org> born in Paris, France, 1977
+11/19 Konstantin Belousov <kib@FreeBSD.org> born in Kiev, USSR, 1972
+11/20 Dmitry Morozovsky <marck@FreeBSD.org> born in Moscow, USSR, 1968
+11/20 Gavin Atkinson <gavin@FreeBSD.org> born in Middlesbrough, United Kingdom, 1979
+11/21 Shteryana Shopova <syrinx@FreeBSD.org> born in Petrich, Bulgaria, 1982
+11/21 Mark Johnston <markj@FreeBSD.org> born in Toronto, Ontario, Canada, 1989
+11/22 Frederic Culot <culot@FreeBSD.org> born in Saint-Germain-En-Laye, France, 1976
+11/23 Josef Lawrence Karthauser <joe@FreeBSD.org> born in Pembury, Kent, United Kingdom, 1972
+11/23 Sepherosa Ziehau <sephe@FreeBSD.org> born in Shanghai, China, 1980
+11/23 Luca Pizzamiglio <pizzamig@FreeBSD.org> born in Casalpusterlengo, Italy, 1978
+11/24 Andrey Zakhvatov <andy@FreeBSD.org> born in Chelyabinsk, Russian Federation, 1974
+11/24 Daniel Gerzo <danger@FreeBSD.org> born in Bratislava, Slovakia, 1986
+11/25 Fedor Uporov <fsu@FreeBSD.org> born in Yalta, Crimea, USSR, 1988
+11/28 Nik Clayton <nik@FreeBSD.org> born in Peterborough, United Kingdom, 1973
+11/28 Stanislav Sedov <stas@FreeBSD.org> born in Chelyabinsk, USSR, 1985
+11/29 Doug Moore <dougm@FreeBSD.org> born in Arlington, Texas, United States, 1960
+11/30 Dmitri Goutnik <dmgk@FreeBSD.org> born in Minsk, USSR, 1969
+12/01 Hajimu Umemoto <ume@FreeBSD.org> born in Nara, Japan, 1961
+12/01 Alexey Dokuchaev <danfe@FreeBSD.org> born in Magadan, USSR, 1980
+12/02 Ermal Luçi <eri@FreeBSD.org> born in Tirane, Albania, 1980
+12/03 Diane Bruce <db@FreeBSD.org> born in Ottawa, Ontario, Canada, 1952
+12/04 Mariusz Zaborski <oshogbo@FreeBSD.org> born in Skierniewice, Poland, 1990
+12/05 Ivan Voras <ivoras@FreeBSD.org> born in Slavonski Brod, Croatia, 1981
+12/06 Stefan Farfeleder <stefanf@FreeBSD.org> born in Wien, Austria, 1980
+12/08 Michael Tuexen <tuexen@FreeBSD.org> born in Oldenburg, Germany, 1966
+12/10 Hiroki Tagato <tagattie@FreeBSD.org> born in Shiga, Japan, 1971
+12/11 Ganael Laplanche <martymac@FreeBSD.org> born in Reims, France, 1980
+12/11 Koichiro Iwao <meta@FreeBSD.org> born in Oita, Japan, 1987
+12/15 James FitzGibbon <jfitz@FreeBSD.org> born in Amersham, Buckinghamshire, United Kingdom, 1974
+12/15 Timur I. Bakeyev <timur@FreeBSD.org> born in Kazan, Republic of Tatarstan, USSR, 1974
+12/15 Fourth quarterly status reports are due on 12/31
+12/18 Chris Timmons <cwt@FreeBSD.org> born in Ellensburg, Washington, United States, 1964
+12/18 Dag-Erling Smorgrav <des@FreeBSD.org> born in Brussels, Belgium, 1977
+12/18 Muhammad Moinur Rahman <bofh@FreeBSD.org> born in Dhaka, Bangladesh, 1983
+12/18 Semen Ustimenko <semenu@FreeBSD.org> born in Novosibirsk, Russian Federation, 1979
+12/19 Stephen Hurd <shurd@FreeBSD.org> born in Estevan, Saskatchewan, Canada, 1975
+12/19 Emmanuel Vadot <manu@FreeBSD.org> born in Decines-Charpieu, France, 1983
+12/20 Sean Bruno <sbruno@FreeBSD.org> born in Monterey, California, United States, 1974
+12/21 Rong-En Fan <rafan@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1982
+12/21 Alexander Ziaee <ziaee@FreeBSD.org> born in Columbus, Ohio, United States, 1995
+12/22 Alan L. Cox <alc@FreeBSD.org> born in Warren, Ohio, United States, 1964
+12/22 Maxim Sobolev <sobomax@FreeBSD.org> born in Dnepropetrovsk, Ukraine, 1976
+12/23 Sean Chittenden <seanc@FreeBSD.org> born in Seattle, Washington, United States, 1979
+12/23 Alejandro Pulver <alepulver@FreeBSD.org> born in Buenos Aires, Argentina, 1989
+12/24 Jochen Neumeister <joneum@FreeBSD.org> born in Heidenheim, Germany, 1975
+12/24 Guido Falsi <madpilot@FreeBSD.org> born in Firenze, Italy, 1978
+12/25 Niclas Zeising <zeising@FreeBSD.org> born in Stockholm, Sweden, 1986
+12/28 Soren Schmidt <sos@FreeBSD.org> born in Maribo, Denmark, 1960
+12/28 Ade Lovett <ade@FreeBSD.org> born in London, England, 1969
+12/28 Marius Strobl <marius@FreeBSD.org> born in Cham, Bavaria, Germany, 1978
+12/30 Sean Eric Fagan <sef@FreeBSD.org> born in Los Angeles, California, United States, 1967
+12/31 Edwin Groothuis <edwin@FreeBSD.org> born in Geldrop, the Netherlands, 1970
+
+#endif /* !_calendar_freebsd_ */
diff --git a/usr.bin/calendar/dates.c b/usr.bin/calendar/dates.c
new file mode 100644
index 000000000000..cdcd565dd6e6
--- /dev/null
+++ b/usr.bin/calendar/dates.c
@@ -0,0 +1,457 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <time.h>
+
+#include "calendar.h"
+
+struct cal_year {
+ int year; /* 19xx, 20xx, 21xx */
+ int easter; /* Julian day */
+ int paskha; /* Julian day */
+ int cny; /* Julian day */
+ int firstdayofweek; /* 0 .. 6 */
+ struct cal_month *months;
+ struct cal_year *nextyear;
+};
+
+struct cal_month {
+ int month; /* 01 .. 12 */
+ int firstdayjulian; /* 000 .. 366 */
+ int firstdayofweek; /* 0 .. 6 */
+ struct cal_year *year; /* points back */
+ struct cal_day *days;
+ struct cal_month *nextmonth;
+};
+
+struct cal_day {
+ int dayofmonth; /* 01 .. 31 */
+ int julianday; /* 000 .. 366 */
+ int dayofweek; /* 0 .. 6 */
+ struct cal_day *nextday;
+ struct cal_month *month; /* points back */
+ struct cal_year *year; /* points back */
+ struct event *events;
+ struct event *lastevent;
+};
+
+int debug_remember = 0;
+static struct cal_year *hyear = NULL;
+
+/* 1-based month, 0-based days, cumulative */
+int cumdaytab[][14] = {
+ {0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
+ {0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+};
+/* 1-based month, individual */
+static int *monthdays;
+int monthdaytab[][14] = {
+ {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
+ {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
+};
+
+static struct cal_day * find_day(int yy, int mm, int dd);
+
+static void
+createdate(int y, int m, int d)
+{
+ struct cal_year *py, *pyp;
+ struct cal_month *pm, *pmp;
+ struct cal_day *pd, *pdp;
+ int *cumday;
+
+ pyp = NULL;
+ py = hyear;
+ while (py != NULL) {
+ if (py->year == y + 1900)
+ break;
+ pyp = py;
+ py = py->nextyear;
+ }
+
+ if (py == NULL) {
+ struct tm td;
+ time_t t;
+ py = (struct cal_year *)calloc(1, sizeof(struct cal_year));
+ py->year = y + 1900;
+ py->easter = easter(y);
+ py->paskha = paskha(y);
+
+ td = tm0;
+ td.tm_year = y;
+ td.tm_mday = 1;
+ t = mktime(&td);
+ localtime_r(&t, &td);
+ py->firstdayofweek = td.tm_wday;
+
+ if (pyp != NULL)
+ pyp->nextyear = py;
+ }
+ if (pyp == NULL) {
+ /* The very very very first one */
+ hyear = py;
+ }
+
+ pmp = NULL;
+ pm = py->months;
+ while (pm != NULL) {
+ if (pm->month == m)
+ break;
+ pmp = pm;
+ pm = pm->nextmonth;
+ }
+
+ if (pm == NULL) {
+ pm = (struct cal_month *)calloc(1, sizeof(struct cal_month));
+ pm->year = py;
+ pm->month = m;
+ cumday = cumdaytab[isleap(y)];
+ pm->firstdayjulian = cumday[m] + 2;
+ pm->firstdayofweek =
+ (py->firstdayofweek + pm->firstdayjulian -1) % 7;
+ if (pmp != NULL)
+ pmp->nextmonth = pm;
+ }
+ if (pmp == NULL)
+ py->months = pm;
+
+ pdp = NULL;
+ pd = pm->days;
+ while (pd != NULL) {
+ pdp = pd;
+ pd = pd->nextday;
+ }
+
+ if (pd == NULL) { /* Always true */
+ pd = (struct cal_day *)calloc(1, sizeof(struct cal_day));
+ pd->month = pm;
+ pd->year = py;
+ pd->dayofmonth = d;
+ pd->julianday = pm->firstdayjulian + d - 1;
+ pd->dayofweek = (pm->firstdayofweek + d - 1) % 7;
+ if (pdp != NULL)
+ pdp->nextday = pd;
+ }
+ if (pdp == NULL)
+ pm->days = pd;
+}
+
+void
+generatedates(struct tm *tp1, struct tm *tp2)
+{
+ int y1, m1, d1;
+ int y2, m2, d2;
+ int y, m, d;
+
+ y1 = tp1->tm_year;
+ m1 = tp1->tm_mon + 1;
+ d1 = tp1->tm_mday;
+ y2 = tp2->tm_year;
+ m2 = tp2->tm_mon + 1;
+ d2 = tp2->tm_mday;
+
+ if (y1 == y2) {
+ if (m1 == m2) {
+ /* Same year, same month. Easy! */
+ for (d = d1; d <= d2; d++)
+ createdate(y1, m1, d);
+ return;
+ }
+ /*
+ * Same year, different month.
+ * - Take the leftover days from m1
+ * - Take all days from <m1 .. m2>
+ * - Take the first days from m2
+ */
+ monthdays = monthdaytab[isleap(y1)];
+ for (d = d1; d <= monthdays[m1]; d++)
+ createdate(y1, m1, d);
+ for (m = m1 + 1; m < m2; m++)
+ for (d = 1; d <= monthdays[m]; d++)
+ createdate(y1, m, d);
+ for (d = 1; d <= d2; d++)
+ createdate(y1, m2, d);
+ return;
+ }
+ /*
+ * Different year, different month.
+ * - Take the leftover days from y1-m1
+ * - Take all days from y1-<m1 .. 12]
+ * - Take all days from <y1 .. y2>
+ * - Take all days from y2-[1 .. m2>
+ * - Take the first days of y2-m2
+ */
+ monthdays = monthdaytab[isleap(y1)];
+ for (d = d1; d <= monthdays[m1]; d++)
+ createdate(y1, m1, d);
+ for (m = m1 + 1; m <= 12; m++)
+ for (d = 1; d <= monthdays[m]; d++)
+ createdate(y1, m, d);
+ for (y = y1 + 1; y < y2; y++) {
+ monthdays = monthdaytab[isleap(y)];
+ for (m = 1; m <= 12; m++)
+ for (d = 1; d <= monthdays[m]; d++)
+ createdate(y, m, d);
+ }
+ monthdays = monthdaytab[isleap(y2)];
+ for (m = 1; m < m2; m++)
+ for (d = 1; d <= monthdays[m]; d++)
+ createdate(y2, m, d);
+ for (d = 1; d <= d2; d++)
+ createdate(y2, m2, d);
+}
+
+void
+dumpdates(void)
+{
+ struct cal_year *y;
+ struct cal_month *m;
+ struct cal_day *d;
+
+ y = hyear;
+ while (y != NULL) {
+ printf("%-5d (wday:%d)\n", y->year, y->firstdayofweek);
+ m = y->months;
+ while (m != NULL) {
+ printf("-- %-5d (julian:%d, dow:%d)\n", m->month,
+ m->firstdayjulian, m->firstdayofweek);
+ d = m->days;
+ while (d != NULL) {
+ printf(" -- %-5d (julian:%d, dow:%d)\n",
+ d->dayofmonth, d->julianday, d->dayofweek);
+ d = d->nextday;
+ }
+ m = m->nextmonth;
+ }
+ y = y->nextyear;
+ }
+}
+
+int
+remember_ymd(int yy, int mm, int dd)
+{
+ struct cal_year *y;
+ struct cal_month *m;
+ struct cal_day *d;
+
+ if (debug_remember)
+ printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
+
+ y = hyear;
+ while (y != NULL) {
+ if (y->year != yy) {
+ y = y->nextyear;
+ continue;
+ }
+ m = y->months;
+ while (m != NULL) {
+ if (m->month != mm) {
+ m = m->nextmonth;
+ continue;
+ }
+ d = m->days;
+ while (d != NULL) {
+ if (d->dayofmonth == dd)
+ return (1);
+ d = d->nextday;
+ continue;
+ }
+ return (0);
+ }
+ return (0);
+ }
+ return (0);
+}
+
+int
+remember_yd(int yy, int dd, int *rm, int *rd)
+{
+ struct cal_year *y;
+ struct cal_month *m;
+ struct cal_day *d;
+
+ if (debug_remember)
+ printf("remember_yd: %d - %d\n", yy, dd);
+
+ y = hyear;
+ while (y != NULL) {
+ if (y->year != yy) {
+ y = y->nextyear;
+ continue;
+ }
+ m = y->months;
+ while (m != NULL) {
+ d = m->days;
+ while (d != NULL) {
+ if (d->julianday == dd) {
+ *rm = m->month;
+ *rd = d->dayofmonth;
+ return (1);
+ }
+ d = d->nextday;
+ }
+ m = m->nextmonth;
+ }
+ return (0);
+ }
+ return (0);
+}
+
+int
+first_dayofweek_of_year(int yy)
+{
+ struct cal_year *y;
+
+ y = hyear;
+ while (y != NULL) {
+ if (y->year == yy)
+ return (y->firstdayofweek);
+ y = y->nextyear;
+ }
+
+ /* Should not happen */
+ return (-1);
+}
+
+int
+first_dayofweek_of_month(int yy, int mm)
+{
+ struct cal_year *y;
+ struct cal_month *m;
+
+ y = hyear;
+ while (y != NULL) {
+ if (y->year != yy) {
+ y = y->nextyear;
+ continue;
+ }
+ m = y->months;
+ while (m != NULL) {
+ if (m->month == mm)
+ return (m->firstdayofweek);
+ m = m->nextmonth;
+ }
+ /* No data for this month */
+ return (-1);
+ }
+
+ /* No data for this year. Error? */
+ return (-1);
+}
+
+int
+walkthrough_dates(struct event **e)
+{
+ static struct cal_year *y = NULL;
+ static struct cal_month *m = NULL;
+ static struct cal_day *d = NULL;
+
+ if (y == NULL) {
+ y = hyear;
+ m = y->months;
+ d = m->days;
+ *e = d->events;
+ return (1);
+ }
+ if (d->nextday != NULL) {
+ d = d->nextday;
+ *e = d->events;
+ return (1);
+ }
+ if (m->nextmonth != NULL) {
+ m = m->nextmonth;
+ d = m->days;
+ *e = d->events;
+ return (1);
+ }
+ if (y->nextyear != NULL) {
+ y = y->nextyear;
+ m = y->months;
+ d = m->days;
+ *e = d->events;
+ return (1);
+ }
+
+ return (0);
+}
+
+static struct cal_day *
+find_day(int yy, int mm, int dd)
+{
+ struct cal_year *y;
+ struct cal_month *m;
+ struct cal_day *d;
+
+ if (debug_remember)
+ printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
+
+ y = hyear;
+ while (y != NULL) {
+ if (y->year != yy) {
+ y = y->nextyear;
+ continue;
+ }
+ m = y->months;
+ while (m != NULL) {
+ if (m->month != mm) {
+ m = m->nextmonth;
+ continue;
+ }
+ d = m->days;
+ while (d != NULL) {
+ if (d->dayofmonth == dd)
+ return (d);
+ d = d->nextday;
+ continue;
+ }
+ return (NULL);
+ }
+ return (NULL);
+ }
+ return (NULL);
+}
+
+void
+addtodate(struct event *e)
+{
+ struct cal_day *d;
+ struct event *ee;
+
+ d = find_day(e->year, e->month, e->day);
+ ee = d->lastevent;
+ if (ee != NULL)
+ ee->next = e;
+ else
+ d->events = e;
+ d->lastevent = e;
+}
diff --git a/usr.bin/calendar/day.c b/usr.bin/calendar/day.c
new file mode 100644
index 000000000000..7e52439cad6a
--- /dev/null
+++ b/usr.bin/calendar/day.c
@@ -0,0 +1,107 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "calendar.h"
+
+static time_t time1, time2;
+const struct tm tm0;
+char dayname[100];
+int year1, year2;
+
+
+void
+settimes(time_t now, int before, int after, int friday, struct tm *tp1, struct tm *tp2)
+{
+ struct tm tp;
+
+ localtime_r(&now, &tp);
+
+ /* Friday displays Monday's events */
+ if (after == 0 && before == 0 && friday != -1)
+ after = tp.tm_wday == friday ? 3 : 1;
+
+ time1 = now - SECSPERDAY * before;
+ localtime_r(&time1, tp1);
+ year1 = 1900 + tp1->tm_year;
+ time2 = now + SECSPERDAY * after;
+ localtime_r(&time2, tp2);
+ year2 = 1900 + tp2->tm_year;
+
+ strftime(dayname, sizeof(dayname) - 1, "%A, %d %B %Y", tp1);
+
+ setnnames();
+}
+
+/* convert Day[/Month][/Year] into unix time (since 1970)
+ * Day: two digits, Month: two digits, Year: digits
+ */
+time_t
+Mktime(char *dp)
+{
+ time_t t;
+ int d, m, y;
+ struct tm tm, tp;
+
+ (void)time(&t);
+ localtime_r(&t, &tp);
+
+ tm = tm0;
+ tm.tm_mday = tp.tm_mday;
+ tm.tm_mon = tp.tm_mon;
+ tm.tm_year = tp.tm_year;
+
+ switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) {
+ case 3:
+ if (y > 1900)
+ y -= 1900;
+ tm.tm_year = y;
+ /* FALLTHROUGH */
+ case 2:
+ tm.tm_mon = m - 1;
+ /* FALLTHROUGH */
+ case 1:
+ tm.tm_mday = d;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Mktime: %d %d %s\n",
+ (int)mktime(&tm), (int)t, asctime(&tm));
+#endif
+ return (mktime(&tm));
+}
diff --git a/usr.bin/calendar/events.c b/usr.bin/calendar/events.c
new file mode 100644
index 000000000000..cbc1d09f3890
--- /dev/null
+++ b/usr.bin/calendar/events.c
@@ -0,0 +1,235 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/time.h>
+#include <err.h>
+#include <langinfo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WITH_ICONV
+#include <iconv.h>
+#include <errno.h>
+
+static iconv_t conv = (iconv_t)-1;
+static char *currentEncoding = NULL;
+
+#endif
+
+#include "pathnames.h"
+#include "calendar.h"
+
+#ifdef WITH_ICONV
+void
+set_new_encoding(void)
+{
+ const char *newenc;
+
+ newenc = nl_langinfo(CODESET);
+ if (currentEncoding == NULL) {
+ currentEncoding = strdup(newenc);
+ if (currentEncoding == NULL)
+ errx(1, "set_new_encoding: cannot allocate memory");
+ return;
+ }
+ if (strcmp(currentEncoding, newenc) == 0)
+ return;
+ free(currentEncoding);
+ currentEncoding = strdup(newenc);
+ if (currentEncoding == NULL)
+ errx(1, "set_new_encoding: cannot allocate memory");
+ if (conv != (iconv_t) -1) {
+ iconv_close(conv);
+ conv = (iconv_t) -1;
+ }
+}
+#endif
+
+static char *
+convert(char *input)
+{
+ char *output;
+#ifdef WITH_ICONV
+ size_t inleft, outleft, converted = 0;
+ char *outbuf, *tmp;
+ char *inbuf;
+ size_t outlen;
+
+ if (currentEncoding == NULL) {
+ output = strdup(input);
+ if (output == NULL)
+ errx(1, "convert: cannot allocate memory");
+ return (output);
+ }
+ if (conv == (iconv_t)-1) {
+ conv = iconv_open(outputEncoding, currentEncoding);
+ if (conv == (iconv_t)-1) {
+ if (errno == EINVAL)
+ errx(1, "Conversion is not supported");
+ else
+ err(1, "Initialization failure");
+ }
+ }
+
+ inleft = strlen(input);
+ inbuf = input;
+
+ outlen = inleft;
+ if ((output = malloc(outlen + 1)) == NULL)
+ errx(1, "convert: cannot allocate memory");
+
+ for (;;) {
+ errno = 0;
+ outbuf = output + converted;
+ outleft = outlen - converted;
+
+ converted = iconv(conv, (char **) &inbuf, &inleft, &outbuf, &outleft);
+ if (converted != (size_t) -1 || errno == EINVAL) {
+ /* finished or invalid multibyte, so truncate and ignore */
+ break;
+ }
+
+ if (errno != E2BIG) {
+ free(output);
+ err(1, "convert");
+ }
+
+ converted = outbuf - output;
+ outlen += inleft * 2;
+
+ if ((tmp = realloc(output, outlen + 1)) == NULL) {
+ free(output);
+ errx(1, "convert: cannot allocate memory");
+ }
+
+ output = tmp;
+ outbuf = output + converted;
+ }
+
+ /* flush the iconv conversion */
+ iconv(conv, NULL, NULL, &outbuf, &outleft);
+
+ /* null terminate the string */
+ *outbuf = '\0';
+#else
+ output = strdup(input);
+ if (output == NULL)
+ errx(1, "convert: cannot allocate memory");
+#endif
+
+ return (output);
+}
+
+struct event *
+event_add(int year, int month, int day, int var, char *txt, char *extra)
+{
+ struct event *e;
+
+ /*
+ * Creating a new event:
+ * - Create a new event
+ * - Copy the machine readable day and month
+ * - Copy the text of the event
+ */
+ e = (struct event *)calloc(1, sizeof(struct event));
+ if (e == NULL)
+ errx(1, "event_add: cannot allocate memory");
+ e->year = year;
+ e->month = month;
+ e->day = day;
+ e->var = var;
+ e->text = convert(txt);
+ if (e->text == NULL)
+ errx(1, "event_add: cannot allocate memory");
+ e->extra = NULL;
+ if (extra != NULL && extra[0] != '\0')
+ e->extra = convert(extra);
+ addtodate(e);
+ return (e);
+}
+
+void
+event_continue(struct event *e, char *txt)
+{
+ char *oldtext, *text;
+
+ text = convert(txt);
+ oldtext = e->text;
+ if (oldtext == NULL)
+ errx(1, "event_continue: cannot allocate memory");
+
+ asprintf(&e->text, "%s\n%s", oldtext, text);
+ if (e->text == NULL)
+ errx(1, "event_continue: cannot allocate memory");
+ free(oldtext);
+ free(text);
+
+ return;
+}
+
+void
+event_print_all(FILE *fp)
+{
+ struct event *e;
+ struct tm tm;
+ char dbuf[80];
+ static int d_first;
+
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+
+ while (walkthrough_dates(&e) != 0) {
+ if (e) {
+#ifdef DEBUG
+ fprintf(stderr, "event_print_all month: %d, day: %d\n",
+ e->month, e->day);
+#endif
+ memset(&tm, 0, sizeof(struct tm));
+ tm.tm_mday = e->day;
+ tm.tm_mon = e->month - 1;
+ tm.tm_year = e->year - 1900;
+ (void)strftime(dbuf, sizeof(dbuf), d_first ? "%e %b" : "%b %e", &tm);
+ }
+
+ /*
+ * Go through all events and print the text of the matching
+ * dates
+ */
+ while (e != NULL) {
+ (void)fprintf(fp, "%s%c%s%s%s%s\n", dbuf,
+ e->var ? '*' : ' ', e->text,
+ e->extra != NULL ? " (" : "",
+ e->extra != NULL ? e->extra : "",
+ e->extra != NULL ? ")" : ""
+ );
+
+ e = e->next;
+ }
+ }
+}
diff --git a/usr.bin/calendar/io.c b/usr.bin/calendar/io.c
new file mode 100644
index 000000000000..17cd5b852c09
--- /dev/null
+++ b/usr.bin/calendar/io.c
@@ -0,0 +1,728 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libutil.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+#include "calendar.h"
+
+enum {
+ T_OK = 0,
+ T_ERR,
+ T_PROCESS,
+};
+
+const char *calendarFile = "calendar"; /* default calendar file */
+static const char *calendarHomes[] = {".calendar", _PATH_INCLUDE_LOCAL, _PATH_INCLUDE}; /* HOME */
+static const char *calendarNoMail = "nomail";/* don't sent mail if file exist */
+
+static char path[MAXPATHLEN];
+static const char *cal_home;
+static const char *cal_dir;
+static const char *cal_file;
+static int cal_line;
+
+struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
+
+static int cal_parse(FILE *in, FILE *out);
+
+static StringList *definitions = NULL;
+static struct event *events[MAXCOUNT];
+static char *extradata[MAXCOUNT];
+
+static char *
+trimlr(char **buf)
+{
+ char *walk = *buf;
+ char *sep;
+ char *last;
+
+ while (isspace(*walk))
+ walk++;
+ *buf = walk;
+
+ sep = walk;
+ while (*sep != '\0' && !isspace(*sep))
+ sep++;
+
+ if (*sep != '\0') {
+ last = sep + strlen(sep) - 1;
+ while (last > walk && isspace(*last))
+ last--;
+ *(last+1) = 0;
+ }
+
+ return (sep);
+}
+
+static FILE *
+cal_fopen(const char *file)
+{
+ static int cwdfd = -1;
+ FILE *fp;
+ char *home = getenv("HOME");
+ unsigned int i;
+ int fd;
+ struct stat sb;
+ static bool warned = false;
+ static char calendarhome[MAXPATHLEN];
+
+ if (home == NULL || *home == '\0') {
+ warnx("Cannot get home directory");
+ return (NULL);
+ }
+
+ /*
+ * On -a runs, we would have done a chdir() earlier on, but we also
+ * shouldn't have used the initial cwd anyways lest we bring
+ * unpredictable behavior upon us.
+ */
+ if (!doall && cwdfd == -1) {
+ cwdfd = open(".", O_DIRECTORY | O_PATH);
+ if (cwdfd == -1)
+ err(1, "open(cwd)");
+ }
+
+ /*
+ * Check $PWD first as documented.
+ */
+ if (cwdfd != -1) {
+ if ((fd = openat(cwdfd, file, O_RDONLY)) != -1) {
+ if ((fp = fdopen(fd, "r")) == NULL)
+ err(1, "fdopen(%s)", file);
+
+ cal_home = NULL;
+ cal_dir = NULL;
+ cal_file = file;
+ return (fp);
+ } else if (errno != ENOENT && errno != ENAMETOOLONG) {
+ err(1, "open(%s)", file);
+ }
+ }
+
+ if (chdir(home) != 0) {
+ warnx("Cannot enter home directory \"%s\"", home);
+ return (NULL);
+ }
+
+ for (i = 0; i < nitems(calendarHomes); i++) {
+ if (snprintf(calendarhome, sizeof (calendarhome), calendarHomes[i],
+ getlocalbase()) >= (int)sizeof (calendarhome))
+ continue;
+
+ if (chdir(calendarhome) != 0)
+ continue;
+
+ if ((fp = fopen(file, "r")) != NULL) {
+ cal_home = home;
+ cal_dir = calendarhome;
+ cal_file = file;
+ return (fp);
+ }
+ }
+
+ warnx("can't open calendar file \"%s\"", file);
+ if (!warned) {
+ snprintf(path, sizeof(path), _PATH_INCLUDE_LOCAL, getlocalbase());
+ if (stat(path, &sb) != 0) {
+ warnx("calendar data files now provided by calendar-data pkg.");
+ warned = true;
+ }
+ }
+
+ return (NULL);
+}
+
+static char*
+cal_path(void)
+{
+ static char buffer[MAXPATHLEN + 10];
+
+ if (cal_dir == NULL)
+ snprintf(buffer, sizeof(buffer), "%s", cal_file);
+ else if (cal_dir[0] == '/')
+ snprintf(buffer, sizeof(buffer), "%s/%s", cal_dir, cal_file);
+ else
+ snprintf(buffer, sizeof(buffer), "%s/%s/%s", cal_home, cal_dir, cal_file);
+ return (buffer);
+}
+
+#define WARN0(format) \
+ warnx(format " in %s line %d", cal_path(), cal_line)
+#define WARN1(format, arg1) \
+ warnx(format " in %s line %d", arg1, cal_path(), cal_line)
+
+static char*
+cmptoken(char *line, const char* token)
+{
+ char len = strlen(token);
+
+ if (strncmp(line, token, len) != 0)
+ return NULL;
+ return (line + len);
+}
+
+static int
+token(char *line, FILE *out, int *skip, int *unskip)
+{
+ char *walk, *sep, a, c;
+ const char *this_cal_home;
+ const char *this_cal_dir;
+ const char *this_cal_file;
+ int this_cal_line;
+
+ while (isspace(*line))
+ line++;
+
+ if (cmptoken(line, "endif")) {
+ if (*skip + *unskip == 0) {
+ WARN0("#endif without prior #ifdef or #ifndef");
+ return (T_ERR);
+ }
+ if (*skip > 0)
+ --*skip;
+ else
+ --*unskip;
+
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "ifdef");
+ if (walk != NULL) {
+ sep = trimlr(&walk);
+
+ if (*walk == '\0') {
+ WARN0("Expecting arguments after #ifdef");
+ return (T_ERR);
+ }
+ if (*sep != '\0') {
+ WARN1("Expecting a single word after #ifdef "
+ "but got \"%s\"", walk);
+ return (T_ERR);
+ }
+
+ if (*skip != 0 ||
+ definitions == NULL || sl_find(definitions, walk) == NULL)
+ ++*skip;
+ else
+ ++*unskip;
+
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "ifndef");
+ if (walk != NULL) {
+ sep = trimlr(&walk);
+
+ if (*walk == '\0') {
+ WARN0("Expecting arguments after #ifndef");
+ return (T_ERR);
+ }
+ if (*sep != '\0') {
+ WARN1("Expecting a single word after #ifndef "
+ "but got \"%s\"", walk);
+ return (T_ERR);
+ }
+
+ if (*skip != 0 ||
+ (definitions != NULL && sl_find(definitions, walk) != NULL))
+ ++*skip;
+ else
+ ++*unskip;
+
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "else");
+ if (walk != NULL) {
+ (void)trimlr(&walk);
+
+ if (*walk != '\0') {
+ WARN0("Expecting no arguments after #else");
+ return (T_ERR);
+ }
+ if (*skip + *unskip == 0) {
+ WARN0("#else without prior #ifdef or #ifndef");
+ return (T_ERR);
+ }
+
+ if (*skip == 0) {
+ ++*skip;
+ --*unskip;
+ } else if (*skip == 1) {
+ --*skip;
+ ++*unskip;
+ }
+
+ return (T_OK);
+ }
+
+ if (*skip != 0)
+ return (T_OK);
+
+ walk = cmptoken(line, "include");
+ if (walk != NULL) {
+ (void)trimlr(&walk);
+
+ if (*walk == '\0') {
+ WARN0("Expecting arguments after #include");
+ return (T_ERR);
+ }
+
+ if (*walk != '<' && *walk != '\"') {
+ WARN0("Excecting '<' or '\"' after #include");
+ return (T_ERR);
+ }
+
+ a = *walk == '<' ? '>' : '\"';
+ walk++;
+ c = walk[strlen(walk) - 1];
+
+ if (a != c) {
+ WARN1("Unterminated include expecting '%c'", a);
+ return (T_ERR);
+ }
+ walk[strlen(walk) - 1] = '\0';
+
+ this_cal_home = cal_home;
+ this_cal_dir = cal_dir;
+ this_cal_file = cal_file;
+ this_cal_line = cal_line;
+ if (cal_parse(cal_fopen(walk), out))
+ return (T_ERR);
+ cal_home = this_cal_home;
+ cal_dir = this_cal_dir;
+ cal_file = this_cal_file;
+ cal_line = this_cal_line;
+
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "define");
+ if (walk != NULL) {
+ if (definitions == NULL)
+ definitions = sl_init();
+ sep = trimlr(&walk);
+ *sep = '\0';
+
+ if (*walk == '\0') {
+ WARN0("Expecting arguments after #define");
+ return (T_ERR);
+ }
+
+ if (sl_find(definitions, walk) == NULL)
+ sl_add(definitions, strdup(walk));
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "undef");
+ if (walk != NULL) {
+ if (definitions != NULL) {
+ sep = trimlr(&walk);
+
+ if (*walk == '\0') {
+ WARN0("Expecting arguments after #undef");
+ return (T_ERR);
+ }
+ if (*sep != '\0') {
+ WARN1("Expecting a single word after #undef "
+ "but got \"%s\"", walk);
+ return (T_ERR);
+ }
+
+ walk = sl_find(definitions, walk);
+ if (walk != NULL)
+ walk[0] = '\0';
+ }
+ return (T_OK);
+ }
+
+ walk = cmptoken(line, "warning");
+ if (walk != NULL) {
+ (void)trimlr(&walk);
+ WARN1("Warning: %s", walk);
+ }
+
+ walk = cmptoken(line, "error");
+ if (walk != NULL) {
+ (void)trimlr(&walk);
+ WARN1("Error: %s", walk);
+ return (T_ERR);
+ }
+
+ WARN1("Undefined pre-processor command \"#%s\"", line);
+ return (T_ERR);
+}
+
+static void
+setup_locale(const char *locale)
+{
+ (void)setlocale(LC_ALL, locale);
+#ifdef WITH_ICONV
+ if (!doall)
+ set_new_encoding();
+#endif
+ setnnames();
+}
+
+#define REPLACE(string, slen, struct_) \
+ if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \
+ if (struct_.name != NULL) \
+ free(struct_.name); \
+ if ((struct_.name = strdup(buf + (slen))) == NULL) \
+ errx(1, "cannot allocate memory"); \
+ struct_.len = strlen(buf + (slen)); \
+ continue; \
+ }
+static int
+cal_parse(FILE *in, FILE *out)
+{
+ char *mylocale = NULL;
+ char *line = NULL;
+ char *buf, *bufp;
+ size_t linecap = 0;
+ ssize_t linelen;
+ ssize_t l;
+ static int count = 0;
+ int i;
+ int month[MAXCOUNT];
+ int day[MAXCOUNT];
+ int year[MAXCOUNT];
+ int skip = 0;
+ int unskip = 0;
+ char *pp, p;
+ int flags;
+ char *c, *cc;
+ bool incomment = false;
+
+ if (in == NULL)
+ return (1);
+
+ cal_line = 0;
+ while ((linelen = getline(&line, &linecap, in)) > 0) {
+ cal_line++;
+ buf = line;
+ if (buf[linelen - 1] == '\n')
+ buf[--linelen] = '\0';
+
+ if (incomment) {
+ c = strstr(buf, "*/");
+ if (c) {
+ c += 2;
+ linelen -= c - buf;
+ buf = c;
+ incomment = false;
+ } else {
+ continue;
+ }
+ }
+ if (!incomment) {
+ bufp = buf;
+ do {
+ c = strstr(bufp, "//");
+ cc = strstr(bufp, "/*");
+ if (c != NULL && (cc == NULL || c - cc < 0)) {
+ bufp = c + 2;
+ /* ignore "//" within string to allow it in an URL */
+ if (c == buf || isspace(c[-1])) {
+ /* single line comment */
+ *c = '\0';
+ linelen = c - buf;
+ break;
+ }
+ } else if (cc != NULL) {
+ c = strstr(cc + 2, "*/");
+ if (c != NULL) { // 'a /* b */ c' -- cc=2, c=7+2
+ /* multi-line comment ending on same line */
+ c += 2;
+ memmove(cc, c, buf + linelen + 1 - c);
+ linelen -= c - cc;
+ bufp = cc;
+ } else {
+ /* multi-line comment */
+ *cc = '\0';
+ linelen = cc - buf;
+ incomment = true;
+ break;
+ }
+ }
+ } while (c != NULL || cc != NULL);
+ }
+
+ for (l = linelen;
+ l > 0 && isspace((unsigned char)buf[l - 1]);
+ l--)
+ ;
+ buf[l] = '\0';
+ if (buf[0] == '\0')
+ continue;
+
+ if (buf == line && *buf == '#') {
+ switch (token(buf+1, out, &skip, &unskip)) {
+ case T_ERR:
+ free(line);
+ return (1);
+ case T_OK:
+ continue;
+ case T_PROCESS:
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (skip != 0)
+ continue;
+
+ /*
+ * Setting LANG in user's calendar was an old workaround
+ * for 'calendar -a' being run with C locale to properly
+ * print user's calendars in their native languages.
+ * Now that 'calendar -a' does fork with setusercontext(),
+ * and does not run iconv(), this variable has little use.
+ */
+ if (strncmp(buf, "LANG=", 5) == 0) {
+ if (mylocale == NULL)
+ mylocale = strdup(setlocale(LC_ALL, NULL));
+ setup_locale(buf + 5);
+ continue;
+ }
+ /* Parse special definitions: Easter, Paskha etc */
+ REPLACE("Easter=", 7, neaster);
+ REPLACE("Paskha=", 7, npaskha);
+ REPLACE("ChineseNewYear=", 15, ncny);
+ REPLACE("NewMoon=", 8, nnewmoon);
+ REPLACE("FullMoon=", 9, nfullmoon);
+ REPLACE("MarEquinox=", 11, nmarequinox);
+ REPLACE("SepEquinox=", 11, nsepequinox);
+ REPLACE("JunSolstice=", 12, njunsolstice);
+ REPLACE("DecSolstice=", 12, ndecsolstice);
+ if (strncmp(buf, "SEQUENCE=", 9) == 0) {
+ setnsequences(buf + 9);
+ continue;
+ }
+
+ /*
+ * If the line starts with a tab, the data has to be
+ * added to the previous line
+ */
+ if (buf[0] == '\t') {
+ for (i = 0; i < count; i++)
+ event_continue(events[i], buf);
+ continue;
+ }
+
+ /* Get rid of leading spaces (non-standard) */
+ while (isspace((unsigned char)buf[0]))
+ memcpy(buf, buf + 1, strlen(buf));
+
+ /* No tab in the line, then not a valid line */
+ if ((pp = strchr(buf, '\t')) == NULL)
+ continue;
+
+ /* Trim spaces in front of the tab */
+ while (isspace((unsigned char)pp[-1]))
+ pp--;
+
+ p = *pp;
+ *pp = '\0';
+ if ((count = parsedaymonth(buf, year, month, day, &flags,
+ extradata)) == 0)
+ continue;
+ *pp = p;
+ if (count < 0) {
+ /* Show error status based on return value */
+ if (debug)
+ WARN1("Ignored: \"%s\"", buf);
+ if (count == -1)
+ continue;
+ count = -count + 1;
+ }
+
+ /* Find the last tab */
+ while (pp[1] == '\t')
+ pp++;
+
+ for (i = 0; i < count; i++) {
+ if (debug)
+ WARN1("got \"%s\"", pp);
+ events[i] = event_add(year[i], month[i], day[i],
+ ((flags &= F_VARIABLE) != 0) ? 1 : 0, pp,
+ extradata[i]);
+ }
+ }
+ while (skip-- > 0 || unskip-- > 0) {
+ cal_line++;
+ WARN0("Missing #endif assumed");
+ }
+
+ free(line);
+ fclose(in);
+ if (mylocale != NULL) {
+ setup_locale(mylocale);
+ free(mylocale);
+ }
+
+ return (0);
+}
+
+void
+cal(void)
+{
+ FILE *fpin;
+ FILE *fpout;
+ int i;
+
+ for (i = 0; i < MAXCOUNT; i++)
+ extradata[i] = (char *)calloc(1, 20);
+
+
+ if ((fpin = opencalin()) == NULL)
+ return;
+
+ if ((fpout = opencalout()) == NULL) {
+ fclose(fpin);
+ return;
+ }
+
+ if (cal_parse(fpin, fpout))
+ return;
+
+ event_print_all(fpout);
+ closecal(fpout);
+}
+
+FILE *
+opencalin(void)
+{
+ struct stat sbuf;
+ FILE *fpin;
+
+ /* open up calendar file */
+ cal_file = calendarFile;
+ if ((fpin = fopen(calendarFile, "r")) == NULL) {
+ if (doall) {
+ if (chdir(calendarHomes[0]) != 0)
+ return (NULL);
+ if (stat(calendarNoMail, &sbuf) == 0)
+ return (NULL);
+ if ((fpin = fopen(calendarFile, "r")) == NULL)
+ return (NULL);
+ } else {
+ fpin = cal_fopen(calendarFile);
+ }
+ }
+ return (fpin);
+}
+
+FILE *
+opencalout(void)
+{
+ int fd;
+
+ /* not reading all calendar files, just set output to stdout */
+ if (!doall)
+ return (stdout);
+
+ /* set output to a temporary file, so if no output don't send mail */
+ snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP);
+ if ((fd = mkstemp(path)) < 0)
+ return (NULL);
+ return (fdopen(fd, "w+"));
+}
+
+void
+closecal(FILE *fp)
+{
+ struct stat sbuf;
+ int nread, pdes[2], status;
+ char buf[1024];
+
+ if (!doall)
+ return;
+
+ rewind(fp);
+ if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
+ goto done;
+ if (pipe(pdes) < 0)
+ goto done;
+ switch (fork()) {
+ case -1: /* error */
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+ goto done;
+ case 0:
+ /* child -- set stdin to pipe output */
+ if (pdes[0] != STDIN_FILENO) {
+ (void)dup2(pdes[0], STDIN_FILENO);
+ (void)close(pdes[0]);
+ }
+ (void)close(pdes[1]);
+ execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
+ "\"Reminder Service\"", (char *)NULL);
+ warn(_PATH_SENDMAIL);
+ _exit(1);
+ }
+ /* parent -- write to pipe input */
+ (void)close(pdes[0]);
+
+ write(pdes[1], "From: \"Reminder Service\" <", 26);
+ write(pdes[1], pw->pw_name, strlen(pw->pw_name));
+ write(pdes[1], ">\nTo: <", 7);
+ write(pdes[1], pw->pw_name, strlen(pw->pw_name));
+ write(pdes[1], ">\nSubject: ", 11);
+ write(pdes[1], dayname, strlen(dayname));
+ write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30);
+
+ while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
+ (void)write(pdes[1], buf, nread);
+ (void)close(pdes[1]);
+done: (void)fclose(fp);
+ (void)unlink(path);
+ while (wait(&status) >= 0);
+}
diff --git a/usr.bin/calendar/locale.c b/usr.bin/calendar/locale.c
new file mode 100644
index 000000000000..572b715b8e92
--- /dev/null
+++ b/usr.bin/calendar/locale.c
@@ -0,0 +1,166 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "calendar.h"
+
+const char *fdays[] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+ "Saturday", NULL,
+};
+
+const char *days[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL,
+};
+
+const char *fmonths[] = {
+ "January", "February", "March", "April", "May", "June", "Juli",
+ "August", "September", "October", "November", "December", NULL,
+};
+
+const char *months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL,
+};
+
+const char *sequences[] = {
+ "First", "Second", "Third", "Fourth", "Fifth", "Last"
+};
+
+struct fixs fndays[8]; /* full national days names */
+struct fixs ndays[8]; /* short national days names */
+struct fixs fnmonths[13]; /* full national months names */
+struct fixs nmonths[13]; /* short national month names */
+struct fixs nsequences[10]; /* national sequence names */
+
+
+void
+setnnames(void)
+{
+ char buf[80];
+ int i, l;
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(struct tm));
+ for (i = 0; i < 7; i++) {
+ tm.tm_wday = i;
+ strftime(buf, sizeof(buf), "%a", &tm);
+ for (l = strlen(buf);
+ l > 0 && isspace((unsigned char)buf[l - 1]);
+ l--)
+ ;
+ buf[l] = '\0';
+ if (ndays[i].name != NULL)
+ free(ndays[i].name);
+ if ((ndays[i].name = strdup(buf)) == NULL)
+ errx(1, "cannot allocate memory");
+ ndays[i].len = strlen(buf);
+
+ strftime(buf, sizeof(buf), "%A", &tm);
+ for (l = strlen(buf);
+ l > 0 && isspace((unsigned char)buf[l - 1]);
+ l--)
+ ;
+ buf[l] = '\0';
+ if (fndays[i].name != NULL)
+ free(fndays[i].name);
+ if ((fndays[i].name = strdup(buf)) == NULL)
+ errx(1, "cannot allocate memory");
+ fndays[i].len = strlen(buf);
+ }
+
+ memset(&tm, 0, sizeof(struct tm));
+ for (i = 0; i < 12; i++) {
+ tm.tm_mon = i;
+ strftime(buf, sizeof(buf), "%b", &tm);
+ for (l = strlen(buf);
+ l > 0 && isspace((unsigned char)buf[l - 1]);
+ l--)
+ ;
+ buf[l] = '\0';
+ if (nmonths[i].name != NULL)
+ free(nmonths[i].name);
+ if ((nmonths[i].name = strdup(buf)) == NULL)
+ errx(1, "cannot allocate memory");
+ nmonths[i].len = strlen(buf);
+
+ strftime(buf, sizeof(buf), "%B", &tm);
+ for (l = strlen(buf);
+ l > 0 && isspace((unsigned char)buf[l - 1]);
+ l--)
+ ;
+ buf[l] = '\0';
+ if (fnmonths[i].name != NULL)
+ free(fnmonths[i].name);
+ if ((fnmonths[i].name = strdup(buf)) == NULL)
+ errx(1, "cannot allocate memory");
+ fnmonths[i].len = strlen(buf);
+ }
+}
+
+void
+setnsequences(char *seq)
+{
+ int i;
+ char *p;
+
+ p = seq;
+ for (i = 0; i < 5; i++) {
+ nsequences[i].name = p;
+ if ((p = strchr(p, ' ')) == NULL) {
+ /* Oh oh there is something wrong. Erase! Erase! */
+ for (i = 0; i < 5; i++) {
+ nsequences[i].name = NULL;
+ nsequences[i].len = 0;
+ }
+ return;
+ }
+ *p = '\0';
+ p++;
+ }
+ nsequences[i].name = p;
+
+ for (i = 0; i < 5; i++) {
+ nsequences[i].name = strdup(nsequences[i].name);
+ nsequences[i].len = nsequences[i + 1].name - nsequences[i].name;
+ }
+ nsequences[i].name = strdup(nsequences[i].name);
+ nsequences[i].len = strlen(nsequences[i].name);
+
+ return;
+}
diff --git a/usr.bin/calendar/ostern.c b/usr.bin/calendar/ostern.c
new file mode 100644
index 000000000000..dfbca892cec7
--- /dev/null
+++ b/usr.bin/calendar/ostern.c
@@ -0,0 +1,67 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "calendar.h"
+
+/* return year day for Easter */
+
+/*
+ * This code is based on the Calendar FAQ's code for how to calculate
+ * easter is. This is the Gregorian calendar version. They refer to
+ * the Algorithm of Oudin in the "Explanatory Supplement to the
+ * Astronomical Almanac".
+ */
+
+int
+easter(int year) /* 0 ... abcd, NOT since 1900 */
+{
+ int G, /* Golden number - 1 */
+ C, /* Century */
+ H, /* 23 - epact % 30 */
+ I, /* days from 21 March to Paschal full moon */
+ J, /* weekday of full moon */
+ L; /* days from 21 March to Sunday on of before full moon */
+
+ G = year % 19;
+ C = year / 100;
+ H = (C - C / 4 - (8 * C + 13) / 25 + 19 * G + 15) % 30;
+ I = H - (H / 28) * (1 - (H / 28) * (29 / (H + 1)) * ((21 - G) / 11));
+ J = (year + year / 4 + I + 2 - C + C / 4) % 7;
+
+ L = I - J;
+
+ if (isleap(year))
+ return 31 + 29 + 21 + L + 7;
+ else
+ return 31 + 28 + 21 + L + 7;
+}
diff --git a/usr.bin/calendar/parsedata.c b/usr.bin/calendar/parsedata.c
new file mode 100644
index 000000000000..7b2b4d9114b0
--- /dev/null
+++ b/usr.bin/calendar/parsedata.c
@@ -0,0 +1,1121 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#include "calendar.h"
+
+#define SLEN 100 /* maximum length of date spec. part strings */
+
+static char *showflags(int flags);
+static int isonlydigits(char *s, int nostar);
+static const char *getmonthname(int i);
+static int checkmonth(char *s, size_t *len, size_t *offset, const char **month);
+static const char *getdayofweekname(int i);
+static int checkdayofweek(char *s, size_t *len, size_t *offset, const char **dow);
+static int indextooffset(char *s);
+static int parseoffset(char *s);
+static char *floattoday(int year, double f);
+static char *floattotime(double f);
+static int wdayom (int day, int offset, int month, int year);
+
+/*
+ * Expected styles:
+ *
+ * Date ::= Month . ' ' . DayOfMonth |
+ * Month . ' ' . DayOfWeek . ModifierIndex |
+ * Month . '/' . DayOfMonth |
+ * Month . '/' . DayOfWeek . ModifierIndex |
+ * DayOfMonth . ' ' . Month |
+ * DayOfMonth . '/' . Month |
+ * DayOfWeek . ModifierIndex . ' ' .Month |
+ * DayOfWeek . ModifierIndex . '/' .Month |
+ * DayOfWeek . ModifierIndex |
+ * SpecialDay . ModifierOffset
+ *
+ * Month ::= MonthName | MonthNumber | '*'
+ * MonthNumber ::= '0' ... '9' | '00' ... '09' | '10' ... '12'
+ * MonthName ::= MonthNameShort | MonthNameLong
+ * MonthNameLong ::= 'January' ... 'December'
+ * MonthNameShort ::= 'Jan' ... 'Dec' | 'Jan.' ... 'Dec.'
+ *
+ * DayOfWeek ::= DayOfWeekShort | DayOfWeekLong
+ * DayOfWeekShort ::= 'Mon' .. 'Sun'
+ * DayOfWeekLong ::= 'Monday' .. 'Sunday'
+ * DayOfMonth ::= '0' ... '9' | '00' ... '09' | '10' ... '29' |
+ * '30' ... '31' | '*'
+ *
+ * ModifierOffset ::= '' | '+' . ModifierNumber | '-' . ModifierNumber
+ * ModifierNumber ::= '0' ... '9' | '00' ... '99' | '000' ... '299' |
+ * '300' ... '359' | '360' ... '365'
+ * ModifierIndex ::= 'Second' | 'Third' | 'Fourth' | 'Fifth' |
+ * 'First' | 'Last'
+ *
+ * SpecialDay ::= 'Easter' | 'Paskha' | 'ChineseNewYear'
+ *
+ */
+static int
+determinestyle(char *date, int *flags,
+ char *month, int *imonth, char *dayofmonth, int *idayofmonth,
+ char *dayofweek, int *idayofweek, char *modifieroffset,
+ char *modifierindex, char *specialday, char *year, int *iyear)
+{
+ char *p, *p1, *p2, *py;
+ const char *dow, *pmonth;
+ char pold;
+ size_t len, offset;
+
+ *flags = F_NONE;
+ *month = '\0';
+ *imonth = 0;
+ *year = '\0';
+ *iyear = 0;
+ *dayofmonth = '\0';
+ *idayofmonth = 0;
+ *dayofweek = '\0';
+ *idayofweek = 0;
+ *modifieroffset = '\0';
+ *modifierindex = '\0';
+ *specialday = '\0';
+
+#define CHECKSPECIAL(s1, s2, lens2, type) \
+ if (s2 != NULL && strncmp(s1, s2, lens2) == 0) { \
+ *flags |= F_SPECIALDAY; \
+ *flags |= type; \
+ *flags |= F_VARIABLE; \
+ if (strlen(s1) == lens2) { \
+ strlcpy(specialday, s1, SLEN); \
+ return (1); \
+ } \
+ strncpy(specialday, s1, lens2); \
+ specialday[lens2] = '\0'; \
+ strlcpy(modifieroffset, s1 + lens2, SLEN); \
+ *flags |= F_MODIFIEROFFSET; \
+ return (1); \
+ }
+
+ if ((p = strchr(date, ' ')) == NULL) {
+ if ((p = strchr(date, '/')) == NULL) {
+ CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY),
+ F_CNY);
+ CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY);
+ CHECKSPECIAL(date, STRING_NEWMOON,
+ strlen(STRING_NEWMOON), F_NEWMOON);
+ CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len,
+ F_NEWMOON);
+ CHECKSPECIAL(date, STRING_FULLMOON,
+ strlen(STRING_FULLMOON), F_FULLMOON);
+ CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len,
+ F_FULLMOON);
+ CHECKSPECIAL(date, STRING_PASKHA,
+ strlen(STRING_PASKHA), F_PASKHA);
+ CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA);
+ CHECKSPECIAL(date, STRING_EASTER,
+ strlen(STRING_EASTER), F_EASTER);
+ CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER);
+ CHECKSPECIAL(date, STRING_MAREQUINOX,
+ strlen(STRING_MAREQUINOX), F_MAREQUINOX);
+ CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len,
+ F_SEPEQUINOX);
+ CHECKSPECIAL(date, STRING_SEPEQUINOX,
+ strlen(STRING_SEPEQUINOX), F_SEPEQUINOX);
+ CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len,
+ F_SEPEQUINOX);
+ CHECKSPECIAL(date, STRING_JUNSOLSTICE,
+ strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE);
+ CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len,
+ F_JUNSOLSTICE);
+ CHECKSPECIAL(date, STRING_DECSOLSTICE,
+ strlen(STRING_DECSOLSTICE), F_DECSOLSTICE);
+ CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len,
+ F_DECSOLSTICE);
+ if (checkdayofweek(date, &len, &offset, &dow) != 0) {
+ *flags |= F_DAYOFWEEK;
+ *flags |= F_VARIABLE;
+ *idayofweek = offset;
+ if (strlen(date) == len) {
+ strlcpy(dayofweek, date, SLEN);
+ return (1);
+ }
+ strncpy(dayofweek, date, len);
+ dayofweek[len] = '\0';
+ strlcpy(modifierindex, date + len, SLEN);
+ *flags |= F_MODIFIERINDEX;
+ return (1);
+ }
+ if (isonlydigits(date, 1)) {
+ /* Assume month number only */
+ *flags |= F_MONTH;
+ *imonth = (int)strtol(date, (char **)NULL, 10);
+ strlcpy(month, getmonthname(*imonth), SLEN);
+ return(1);
+ }
+ return (0);
+ }
+ }
+
+ /*
+ * After this, leave by goto-ing to "allfine" or "fail" to restore the
+ * original data in `date'.
+ */
+ pold = *p;
+ *p = 0;
+ p1 = date;
+ p2 = p + 1;
+ /* Now p2 points to the next field and p1 to the first field */
+
+ if ((py = strchr(p2, '/')) != NULL) {
+ /* We have a year in the string. Now this is getting tricky */
+ strlcpy(year, p1, SLEN);
+ *iyear = (int)strtol(year, NULL, 10);
+ p1 = p2;
+ p2 = py + 1;
+ *py = 0;
+ *flags |= F_YEAR;
+ }
+
+ /* Check if there is a month-string in the date */
+ if ((checkmonth(p1, &len, &offset, &pmonth) != 0)
+ || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) {
+ /* p2 is the non-month part */
+ *flags |= F_MONTH;
+ *imonth = offset;
+
+ strlcpy(month, getmonthname(offset), SLEN);
+ if (isonlydigits(p2, 1)) {
+ strlcpy(dayofmonth, p2, SLEN);
+ *idayofmonth = (int)strtol(p2, (char **)NULL, 10);
+ *flags |= F_DAYOFMONTH;
+ goto allfine;
+ }
+ if (strcmp(p2, "*") == 0) {
+ *flags |= F_ALLDAY;
+ goto allfine;
+ }
+
+ if (checkdayofweek(p2, &len, &offset, &dow) != 0) {
+ *flags |= F_DAYOFWEEK;
+ *flags |= F_VARIABLE;
+ *idayofweek = offset;
+ strlcpy(dayofweek, getdayofweekname(offset), SLEN);
+ if (strlen(p2) == len)
+ goto allfine;
+ strlcpy(modifierindex, p2 + len, SLEN);
+ *flags |= F_MODIFIERINDEX;
+ goto allfine;
+ }
+ goto fail;
+ }
+
+ /* Check if there is an every-day or every-month in the string */
+ if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1))
+ || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) {
+ int d;
+
+ *flags |= F_ALLMONTH;
+ *flags |= F_DAYOFMONTH;
+ d = (int)strtol(p2, (char **)NULL, 10);
+ *idayofmonth = d;
+ snprintf(dayofmonth, SLEN, "%d", d);
+ goto allfine;
+ }
+
+ /* Month as a number, then a weekday */
+ if (isonlydigits(p1, 1)
+ && checkdayofweek(p2, &len, &offset, &dow) != 0) {
+ int d;
+
+ *flags |= F_MONTH;
+ *flags |= F_DAYOFWEEK;
+ *flags |= F_VARIABLE;
+
+ *idayofweek = offset;
+ d = (int)strtol(p1, (char **)NULL, 10);
+ *imonth = d;
+ strlcpy(month, getmonthname(d), SLEN);
+
+ strlcpy(dayofweek, getdayofweekname(offset), SLEN);
+ if (strlen(p2) == len)
+ goto allfine;
+ strlcpy(modifierindex, p2 + len, SLEN);
+ *flags |= F_MODIFIERINDEX;
+ goto allfine;
+ }
+
+ /* If both the month and date are specified as numbers */
+ if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) {
+ /* Now who wants to be this ambiguous? :-( */
+ int m, d;
+
+ if (strchr(p2, '*') != NULL)
+ *flags |= F_VARIABLE;
+
+ m = (int)strtol(p1, (char **)NULL, 10);
+ d = (int)strtol(p2, (char **)NULL, 10);
+
+ *flags |= F_MONTH;
+ *flags |= F_DAYOFMONTH;
+
+ if (m > 12) {
+ *imonth = d;
+ *idayofmonth = m;
+ strlcpy(month, getmonthname(d), SLEN);
+ snprintf(dayofmonth, SLEN, "%d", m);
+ } else {
+ *imonth = m;
+ *idayofmonth = d;
+ strlcpy(month, getmonthname(m), SLEN);
+ snprintf(dayofmonth, SLEN, "%d", d);
+ }
+ goto allfine;
+ }
+
+ /* FALLTHROUGH */
+fail:
+ *p = pold;
+ return (0);
+allfine:
+ *p = pold;
+ return (1);
+
+}
+
+static void
+remember(int *rememberindex, int *y, int *m, int *d, char **ed, int yy, int mm,
+ int dd, char *extra)
+{
+ static int warned = 0;
+
+ if (*rememberindex >= MAXCOUNT - 1) {
+ if (warned == 0)
+ warnx("Index > %d, ignored", MAXCOUNT);
+ warned++;
+ return;
+ }
+ y[*rememberindex] = yy;
+ m[*rememberindex] = mm;
+ d[*rememberindex] = dd;
+ if (extra != NULL)
+ strlcpy(ed[*rememberindex], extra, SLEN);
+ else
+ ed[*rememberindex][0] = '\0';
+ *rememberindex += 1;
+}
+
+static void
+debug_determinestyle(int dateonly, char *date, int flags, char *month,
+ int imonth, char *dayofmonth, int idayofmonth, char *dayofweek,
+ int idayofweek, char *modifieroffset, char *modifierindex, char *specialday,
+ char *year, int iyear)
+{
+
+ if (dateonly != 0) {
+ printf("-------\ndate: |%s|\n", date);
+ if (dateonly == 1)
+ return;
+ }
+ printf("flags: %x - %s\n", flags, showflags(flags));
+ if (modifieroffset[0] != '\0')
+ printf("modifieroffset: |%s|\n", modifieroffset);
+ if (modifierindex[0] != '\0')
+ printf("modifierindex: |%s|\n", modifierindex);
+ if (year[0] != '\0')
+ printf("year: |%s| (%d)\n", year, iyear);
+ if (month[0] != '\0')
+ printf("month: |%s| (%d)\n", month, imonth);
+ if (dayofmonth[0] != '\0')
+ printf("dayofmonth: |%s| (%d)\n", dayofmonth, idayofmonth);
+ if (dayofweek[0] != '\0')
+ printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek);
+ if (specialday[0] != '\0')
+ printf("specialday: |%s|\n", specialday);
+}
+
+static struct yearinfo {
+ int year;
+ int ieaster, ipaskha, firstcnyday;
+ double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS];
+ double ffullmooncny[MAXMOONS], fnewmooncny[MAXMOONS];
+ int ichinesemonths[MAXMOONS];
+ double equinoxdays[2], solsticedays[2];
+ int *monthdays;
+ struct yearinfo *next;
+} *years, *yearinfo;
+
+/*
+ * Calculate dates with offset from weekdays, like Thurs-3, Wed+2, etc.
+ * day is the day of the week,
+ * offset the ordinal number of the weekday in the month.
+ */
+static int
+wdayom (int day, int offset, int month, int year)
+{
+/* Weekday of first day in month */
+ int wday1; /* first day of month */
+/* Weekday of last day in month */
+ int wdayn;
+ int d;
+
+ wday1 = first_dayofweek_of_month(year, month);
+ if (wday1 < 0) /* not set */
+ return (wday1);
+ /*
+ * Date of zeroth or first of our weekday in month, depending on the
+ * relationship with the first of the month. The range is -6:6.
+ */
+ d = (day - wday1 + 1) % 7;
+ /*
+ * Which way are we counting? Offset 0 is invalid, abs (offset) > 5 is
+ * meaningless, but that's OK. Offset 5 may or may not be meaningless,
+ * so there's no point in complaining for complaining's sake.
+ */
+ if (offset < 0) { /* back from end of month */
+ /* FIXME */
+ wdayn = d;
+ while (wdayn <= yearinfo->monthdays[month])
+ wdayn += 7;
+ d = offset * 7 + wdayn;
+ } else if (offset > 0){
+ if (d > 0)
+ d += offset * 7 - 7;
+ else
+ d += offset * 7;
+ } else
+ warnx ("Invalid offset 0");
+ return (d);
+}
+
+/*
+ * Possible date formats include any combination of:
+ * 3-charmonth (January, Jan, Jan)
+ * 3-charweekday (Friday, Monday, mon.)
+ * numeric month or day (1, 2, 04)
+ *
+ * Any character may separate them, or they may not be separated. Any line,
+ * following a line that is matched, that starts with "whitespace", is shown
+ * along with the matched line.
+ */
+int
+parsedaymonth(char *date, int *yearp, int *monthp, int *dayp, int *flags,
+ char **edp)
+{
+ char month[SLEN], dayofmonth[SLEN], dayofweek[SLEN], modifieroffset[SLEN];
+ char syear[SLEN];
+ char modifierindex[SLEN], specialday[SLEN];
+ int idayofweek = -1, imonth = -1, idayofmonth = -1, iyear = -1;
+ int year, remindex;
+ int d, m, dow, rm, rd, offset;
+ char *ed;
+ int retvalsign = 1;
+
+ /*
+ * CONVENTION
+ *
+ * Month: 1-12
+ * Monthname: Jan .. Dec
+ * Day: 1-31
+ * Weekday: Mon .. Sun
+ *
+ */
+
+ *flags = 0;
+
+ if (debug)
+ debug_determinestyle(1, date, *flags, month, imonth,
+ dayofmonth, idayofmonth, dayofweek, idayofweek,
+ modifieroffset, modifierindex, specialday, syear, iyear);
+ if (determinestyle(date, flags, month, &imonth, dayofmonth,
+ &idayofmonth, dayofweek, &idayofweek, modifieroffset,
+ modifierindex, specialday, syear, &iyear) == 0) {
+ if (debug)
+ printf("Failed!\n");
+ return (0);
+ }
+
+ if (debug)
+ debug_determinestyle(0, date, *flags, month, imonth,
+ dayofmonth, idayofmonth, dayofweek, idayofweek,
+ modifieroffset, modifierindex, specialday, syear, iyear);
+
+ remindex = 0;
+ for (year = year1; year <= year2; year++) {
+
+ int lflags = *flags;
+ /* If the year is specified, only do it if it is this year! */
+ if ((lflags & F_YEAR) != 0)
+ if (iyear != year)
+ continue;
+ lflags &= ~F_YEAR;
+
+ /* Get important dates for this year */
+ yearinfo = years;
+ while (yearinfo != NULL) {
+ if (yearinfo->year == year)
+ break;
+ yearinfo = yearinfo -> next;
+ }
+ if (yearinfo == NULL) {
+ yearinfo = (struct yearinfo *)calloc(1,
+ sizeof(struct yearinfo));
+ if (yearinfo == NULL)
+ errx(1, "Unable to allocate more years");
+ yearinfo->year = year;
+ yearinfo->next = years;
+ years = yearinfo;
+
+ yearinfo->monthdays = monthdaytab[isleap(year)];
+ yearinfo->ieaster = easter(year);
+ yearinfo->ipaskha = paskha(year);
+ fpom(year, UTCOffset, yearinfo->ffullmoon,
+ yearinfo->fnewmoon);
+ fpom(year, UTCOFFSET_CNY, yearinfo->ffullmooncny,
+ yearinfo->fnewmooncny);
+ fequinoxsolstice(year, UTCOffset,
+ yearinfo->equinoxdays, yearinfo->solsticedays);
+
+ /*
+ * CNY: Match day with sun longitude at 330` with new
+ * moon
+ */
+ yearinfo->firstcnyday = calculatesunlongitude30(year,
+ UTCOFFSET_CNY, yearinfo->ichinesemonths);
+ for (m = 0; yearinfo->fnewmooncny[m] >= 0; m++) {
+ if (yearinfo->fnewmooncny[m] >
+ yearinfo->firstcnyday) {
+ yearinfo->firstcnyday =
+ floor(yearinfo->fnewmooncny[m - 1]);
+ break;
+ }
+ }
+ }
+
+ /* Same day every year */
+ if (lflags == (F_MONTH | F_DAYOFMONTH)) {
+ if (!remember_ymd(year, imonth, idayofmonth))
+ continue;
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, imonth, idayofmonth, NULL);
+ continue;
+ }
+
+ /* XXX Same day every year, but variable */
+ if (lflags == (F_MONTH | F_DAYOFMONTH | F_VARIABLE)) {
+ if (!remember_ymd(year, imonth, idayofmonth))
+ continue;
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, imonth, idayofmonth, NULL);
+ continue;
+ }
+
+ /* Same day every month */
+ if (lflags == (F_ALLMONTH | F_DAYOFMONTH)) {
+ for (m = 1; m <= 12; m++) {
+ if (!remember_ymd(year, m, idayofmonth))
+ continue;
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, m, idayofmonth, NULL);
+ }
+ continue;
+ }
+
+ /* Every day of a month */
+ if (lflags == (F_ALLDAY | F_MONTH)) {
+ for (d = 1; d <= yearinfo->monthdays[imonth]; d++) {
+ if (!remember_ymd(year, imonth, d))
+ continue;
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, imonth, d, NULL);
+ }
+ continue;
+ }
+
+ /* One day of every month */
+ if (lflags == (F_ALLMONTH | F_DAYOFWEEK)) {
+ for (m = 1; m <= 12; m++) {
+ if (!remember_ymd(year, m, idayofmonth))
+ continue;
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, m, idayofmonth, NULL);
+ }
+ continue;
+ }
+
+ /* Every dayofweek of the year */
+ if (lflags == (F_DAYOFWEEK | F_VARIABLE)) {
+ dow = first_dayofweek_of_year(year);
+ if (dow < 0)
+ continue;
+ d = (idayofweek - dow + 7) % 7 + 1;
+ while (d <= 366) {
+ if (remember_yd(year, d, &rm, &rd))
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, rm, rd, NULL);
+ d += 7;
+ }
+ continue;
+ }
+
+ /*
+ * Every so-manied dayofweek of every month of the year:
+ * Thu-3
+ */
+ if (lflags == (F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) {
+ offset = indextooffset(modifierindex);
+
+ for (m = 0; m <= 12; m++) {
+ d = wdayom (idayofweek, offset, m, year);
+ if (remember_ymd(year, m, d)) {
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, m, d, NULL);
+ continue;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * A certain dayofweek of a month
+ * Jan/Thu-3
+ */
+ if (lflags ==
+ (F_MONTH | F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) {
+ offset = indextooffset(modifierindex);
+ dow = first_dayofweek_of_month(year, imonth);
+ if (dow < 0)
+ continue;
+ d = (idayofweek - dow + 7) % 7 + 1;
+
+ if (offset > 0) {
+ while (d <= yearinfo->monthdays[imonth]) {
+ if (--offset == 0
+ && remember_ymd(year, imonth, d)) {
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, imonth, d, NULL);
+ continue;
+ }
+ d += 7;
+ }
+ continue;
+ }
+ if (offset < 0) {
+ while (d <= yearinfo->monthdays[imonth])
+ d += 7;
+ while (offset != 0) {
+ offset++;
+ d -= 7;
+ }
+ if (remember_ymd(year, imonth, d))
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, imonth, d, NULL);
+ continue;
+ }
+ continue;
+ }
+
+ /* Every dayofweek of the month */
+ if (lflags == (F_DAYOFWEEK | F_MONTH | F_VARIABLE)) {
+ dow = first_dayofweek_of_month(year, imonth);
+ if (dow < 0)
+ continue;
+ d = (idayofweek - dow + 7) % 7 + 1;
+ while (d <= yearinfo->monthdays[imonth]) {
+ if (remember_ymd(year, imonth, d))
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, imonth, d, NULL);
+ d += 7;
+ }
+ continue;
+ }
+
+ /* Easter */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_EASTER)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year, yearinfo->ieaster + offset,
+ &rm, &rd))
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, NULL);
+ continue;
+ }
+
+ /* Paskha */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_PASKHA)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year, yearinfo->ipaskha + offset,
+ &rm, &rd))
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, NULL);
+ continue;
+ }
+
+ /* Chinese New Year */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_CNY)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year, yearinfo->firstcnyday + offset,
+ &rm, &rd))
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, NULL);
+ continue;
+ }
+
+ /* FullMoon */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) {
+ int i;
+
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ for (i = 0; yearinfo->ffullmoon[i] > 0; i++) {
+ if (remember_yd(year,
+ floor(yearinfo->ffullmoon[i]) + offset,
+ &rm, &rd)) {
+ ed = floattotime(
+ yearinfo->ffullmoon[i]);
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ }
+ continue;
+ }
+
+ /* NewMoon */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) {
+ int i;
+
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ for (i = 0; yearinfo->ffullmoon[i] > 0; i++) {
+ if (remember_yd(year,
+ floor(yearinfo->fnewmoon[i]) + offset,
+ &rm, &rd)) {
+ ed = floattotime(yearinfo->fnewmoon[i]);
+ remember(&remindex,
+ yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ }
+ continue;
+ }
+
+ /* (Mar|Sep)Equinox */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year, yearinfo->equinoxdays[0] + offset,
+ &rm, &rd)) {
+ ed = floattotime(yearinfo->equinoxdays[0]);
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ continue;
+ }
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year, yearinfo->equinoxdays[1] + offset,
+ &rm, &rd)) {
+ ed = floattotime(yearinfo->equinoxdays[1]);
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ continue;
+ }
+
+ /* (Jun|Dec)Solstice */
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year,
+ yearinfo->solsticedays[0] + offset, &rm, &rd)) {
+ ed = floattotime(yearinfo->solsticedays[0]);
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ continue;
+ }
+ if ((lflags & ~F_MODIFIEROFFSET) ==
+ (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) {
+ offset = 0;
+ if ((lflags & F_MODIFIEROFFSET) != 0)
+ offset = parseoffset(modifieroffset);
+ if (remember_yd(year,
+ yearinfo->solsticedays[1] + offset, &rm, &rd)) {
+ ed = floattotime(yearinfo->solsticedays[1]);
+ remember(&remindex, yearp, monthp, dayp, edp,
+ year, rm, rd, ed);
+ }
+ continue;
+ }
+
+ if (debug) {
+ printf("Unprocessed:\n");
+ debug_determinestyle(2, date, lflags, month, imonth,
+ dayofmonth, idayofmonth, dayofweek, idayofweek,
+ modifieroffset, modifierindex, specialday, syear,
+ iyear);
+ }
+ retvalsign = -1;
+ }
+
+ if (retvalsign == -1)
+ return (-remindex - 1);
+ else
+ return (remindex);
+}
+
+static char *
+showflags(int flags)
+{
+ static char s[SLEN];
+ s[0] = '\0';
+
+ if ((flags & F_YEAR) != 0)
+ strlcat(s, "year ", SLEN);
+ if ((flags & F_MONTH) != 0)
+ strlcat(s, "month ", SLEN);
+ if ((flags & F_DAYOFWEEK) != 0)
+ strlcat(s, "dayofweek ", SLEN);
+ if ((flags & F_DAYOFMONTH) != 0)
+ strlcat(s, "dayofmonth ", SLEN);
+ if ((flags & F_MODIFIERINDEX) != 0)
+ strlcat(s, "modifierindex ", SLEN);
+ if ((flags & F_MODIFIEROFFSET) != 0)
+ strlcat(s, "modifieroffset ", SLEN);
+ if ((flags & F_SPECIALDAY) != 0)
+ strlcat(s, "specialday ", SLEN);
+ if ((flags & F_ALLMONTH) != 0)
+ strlcat(s, "allmonth ", SLEN);
+ if ((flags & F_ALLDAY) != 0)
+ strlcat(s, "allday ", SLEN);
+ if ((flags & F_VARIABLE) != 0)
+ strlcat(s, "variable ", SLEN);
+ if ((flags & F_CNY) != 0)
+ strlcat(s, "chinesenewyear ", SLEN);
+ if ((flags & F_PASKHA) != 0)
+ strlcat(s, "paskha ", SLEN);
+ if ((flags & F_EASTER) != 0)
+ strlcat(s, "easter ", SLEN);
+ if ((flags & F_FULLMOON) != 0)
+ strlcat(s, "fullmoon ", SLEN);
+ if ((flags & F_NEWMOON) != 0)
+ strlcat(s, "newmoon ", SLEN);
+ if ((flags & F_MAREQUINOX) != 0)
+ strlcat(s, "marequinox ", SLEN);
+ if ((flags & F_SEPEQUINOX) != 0)
+ strlcat(s, "sepequinox ", SLEN);
+ if ((flags & F_JUNSOLSTICE) != 0)
+ strlcat(s, "junsolstice ", SLEN);
+ if ((flags & F_DECSOLSTICE) != 0)
+ strlcat(s, "decsolstice ", SLEN);
+
+ return s;
+}
+
+static const char *
+getmonthname(int i)
+{
+ if (i <= 0 || i > 12)
+ return ("");
+ if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL)
+ return (nmonths[i - 1].name);
+ return (months[i - 1]);
+}
+
+static int
+checkmonth(char *s, size_t *len, size_t *offset, const char **month)
+{
+ struct fixs *n;
+ int i;
+
+ for (i = 0; fnmonths[i].name != NULL; i++) {
+ n = fnmonths + i;
+ if (strncasecmp(s, n->name, n->len) == 0) {
+ *len = n->len;
+ *month = n->name;
+ *offset = i + 1;
+ return (1);
+ }
+ }
+ for (i = 0; nmonths[i].name != NULL; i++) {
+ n = nmonths + i;
+ if (strncasecmp(s, n->name, n->len) == 0) {
+ *len = n->len;
+ *month = n->name;
+ *offset = i + 1;
+ return (1);
+ }
+ }
+ for (i = 0; fmonths[i] != NULL; i++) {
+ *len = strlen(fmonths[i]);
+ if (strncasecmp(s, fmonths[i], *len) == 0) {
+ *month = fmonths[i];
+ *offset = i + 1;
+ return (1);
+ }
+ }
+ for (i = 0; months[i] != NULL; i++) {
+ if (strncasecmp(s, months[i], 3) == 0) {
+ *len = 3;
+ *month = months[i];
+ *offset = i + 1;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static const char *
+getdayofweekname(int i)
+{
+ if (ndays[i].len != 0 && ndays[i].name != NULL)
+ return (ndays[i].name);
+ return (days[i]);
+}
+
+static int
+checkdayofweek(char *s, size_t *len, size_t *offset, const char **dow)
+{
+ struct fixs *n;
+ int i;
+
+ for (i = 0; fndays[i].name != NULL; i++) {
+ n = fndays + i;
+ if (strncasecmp(s, n->name, n->len) == 0) {
+ *len = n->len;
+ *dow = n->name;
+ *offset = i;
+ return (1);
+ }
+ }
+ for (i = 0; ndays[i].name != NULL; i++) {
+ n = ndays + i;
+ if (strncasecmp(s, n->name, n->len) == 0) {
+ *len = n->len;
+ *dow = n->name;
+ *offset = i;
+ return (1);
+ }
+ }
+ for (i = 0; fdays[i] != NULL; i++) {
+ *len = strlen(fdays[i]);
+ if (strncasecmp(s, fdays[i], *len) == 0) {
+ *dow = fdays[i];
+ *offset = i;
+ return (1);
+ }
+ }
+ for (i = 0; days[i] != NULL; i++) {
+ if (strncasecmp(s, days[i], 3) == 0) {
+ *len = 3;
+ *dow = days[i];
+ *offset = i;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static int
+isonlydigits(char *s, int nostar)
+{
+ int i;
+ for (i = 0; s[i] != '\0'; i++) {
+ if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0')
+ return 1;
+ if (!isdigit((unsigned char)s[i]))
+ return (0);
+ }
+ return (1);
+}
+
+static int
+indextooffset(char *s)
+{
+ int i;
+ struct fixs *n;
+ char *es;
+
+ if (s[0] == '+' || s[0] == '-') {
+ i = strtol (s, &es, 10);
+ if (*es != '\0') /* trailing junk */
+ errx (1, "Invalid specifier format: %s\n", s);
+ return (i);
+ }
+
+ for (i = 0; i < 6; i++) {
+ if (strcasecmp(s, sequences[i]) == 0) {
+ if (i == 5)
+ return (-1);
+ return (i + 1);
+ }
+ }
+ for (i = 0; i < 6; i++) {
+ n = nsequences + i;
+ if (n->len == 0)
+ continue;
+ if (strncasecmp(s, n->name, n->len) == 0) {
+ if (i == 5)
+ return (-1);
+ return (i + 1);
+ }
+ }
+ return (0);
+}
+
+static int
+parseoffset(char *s)
+{
+ return strtol(s, NULL, 10);
+}
+
+static char *
+floattotime(double f)
+{
+ static char buf[SLEN];
+ int hh, mm, ss, i;
+
+ f -= floor(f);
+ i = f * SECSPERDAY;
+
+ hh = i / SECSPERHOUR;
+ i %= SECSPERHOUR;
+ mm = i / SECSPERMINUTE;
+ i %= SECSPERMINUTE;
+ ss = i;
+
+ snprintf(buf, SLEN, "%02d:%02d:%02d", hh, mm, ss);
+ return (buf);
+}
+
+static char *
+floattoday(int year, double f)
+{
+ static char buf[SLEN];
+ int i, m, d, hh, mm, ss;
+ int *cumdays = cumdaytab[isleap(year)];
+
+ for (i = 0; 1 + cumdays[i] < f; i++)
+ ;
+ m = --i;
+ d = floor(f - 1 - cumdays[i]);
+ f -= floor(f);
+ i = f * SECSPERDAY;
+
+ hh = i / SECSPERHOUR;
+ i %= SECSPERHOUR;
+ mm = i / SECSPERMINUTE;
+ i %= SECSPERMINUTE;
+ ss = i;
+
+ snprintf(buf, SLEN, "%02d-%02d %02d:%02d:%02d", m, d, hh, mm, ss);
+ return (buf);
+}
+
+void
+dodebug(char *what)
+{
+ int year;
+
+ printf("UTCOffset: %g\n", UTCOffset);
+ printf("eastlongitude: %d\n", EastLongitude);
+
+ if (strcmp(what, "moon") == 0) {
+ double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS];
+ int i;
+
+ for (year = year1; year <= year2; year++) {
+ fpom(year, UTCOffset, ffullmoon, fnewmoon);
+ printf("Full moon %d:\t", year);
+ for (i = 0; ffullmoon[i] >= 0; i++) {
+ printf("%g (%s) ", ffullmoon[i],
+ floattoday(year, ffullmoon[i]));
+ }
+ printf("\nNew moon %d:\t", year);
+ for (i = 0; fnewmoon[i] >= 0; i++) {
+ printf("%g (%s) ", fnewmoon[i],
+ floattoday(year, fnewmoon[i]));
+ }
+ printf("\n");
+
+ }
+
+ return;
+ }
+
+ if (strcmp(what, "sun") == 0) {
+ double equinoxdays[2], solsticedays[2];
+ for (year = year1; year <= year2; year++) {
+ printf("Sun in %d:\n", year);
+ fequinoxsolstice(year, UTCOffset, equinoxdays,
+ solsticedays);
+ printf("e[0] - %g (%s)\n",
+ equinoxdays[0],
+ floattoday(year, equinoxdays[0]));
+ printf("e[1] - %g (%s)\n",
+ equinoxdays[1],
+ floattoday(year, equinoxdays[1]));
+ printf("s[0] - %g (%s)\n",
+ solsticedays[0],
+ floattoday(year, solsticedays[0]));
+ printf("s[1] - %g (%s)\n",
+ solsticedays[1],
+ floattoday(year, solsticedays[1]));
+ }
+ return;
+ }
+}
diff --git a/usr.bin/calendar/paskha.c b/usr.bin/calendar/paskha.c
new file mode 100644
index 000000000000..4ea345f9cd5d
--- /dev/null
+++ b/usr.bin/calendar/paskha.c
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.
+ * 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.
+ *
+ * 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 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/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "calendar.h"
+
+#define PASKHA "paskha"
+#define PASKHALEN (sizeof(PASKHA) - 1)
+
+/* return difference in days between Julian and Gregorian calendars */
+int
+j2g(int year)
+{
+ return (year < 1500) ?
+ 0 :
+ 10 + (year/100 - 16) - ((year/100 - 16) / 4);
+}
+
+/* return year day for Orthodox Easter using Gauss formula */
+/* (new style result) */
+
+int
+paskha(int R) /*year*/
+{
+ int a, b, c, d, e;
+ static int x = 15;
+ static int y = 6;
+ int *cumday;
+
+ a = R % 19;
+ b = R % 4;
+ c = R % 7;
+ d = (19 * a + x) % 30;
+ e = (2 * b + 4 * c + 6 * d + y) % 7;
+ cumday = cumdaytab[isleap(R)];
+ return (((cumday[3] + 1) + 22) + (d + e) + j2g(R));
+}
diff --git a/usr.bin/calendar/pathnames.h b/usr.bin/calendar/pathnames.h
new file mode 100644
index 000000000000..e089562b024e
--- /dev/null
+++ b/usr.bin/calendar/pathnames.h
@@ -0,0 +1,35 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <paths.h>
+
+#define _PATH_INCLUDE "/usr/share/calendar"
+#define _PATH_INCLUDE_LOCAL "%s/share/calendar"
diff --git a/usr.bin/calendar/pom.c b/usr.bin/calendar/pom.c
new file mode 100644
index 000000000000..188dae09ffd3
--- /dev/null
+++ b/usr.bin/calendar/pom.c
@@ -0,0 +1,264 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software posted to USENET.
+ *
+ * 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.
+ */
+
+/*
+ * Phase of the Moon. Calculates the current phase of the moon.
+ * Based on routines from `Practical Astronomy with Your Calculator',
+ * by Duffett-Smith. Comments give the section from the book that
+ * particular piece of code was adapted from.
+ *
+ * -- Keith E. Brandt VIII 1984
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "calendar.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+#define EPOCH 85
+#define EPSILONg 279.611371 /* solar ecliptic long at EPOCH */
+#define RHOg 282.680403 /* solar ecliptic long of perigee at EPOCH */
+#define ECCEN 0.01671542 /* solar orbit eccentricity */
+#define lzero 18.251907 /* lunar mean long at EPOCH */
+#define Pzero 192.917585 /* lunar mean long of perigee at EPOCH */
+#define Nzero 55.204723 /* lunar mean long of node at EPOCH */
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+static void adj360(double *);
+static double dtor(double);
+static double potm(double onday);
+static double potm_minute(double onday, int olddir);
+
+void
+pom(int year, double utcoffset, int *fms, int *nms)
+{
+ double ffms[MAXMOONS];
+ double fnms[MAXMOONS];
+ int i, j;
+
+ fpom(year, utcoffset, ffms, fnms);
+
+ j = 0;
+ for (i = 0; ffms[i] != 0; i++)
+ fms[j++] = round(ffms[i]);
+ fms[i] = -1;
+ for (i = 0; fnms[i] != 0; i++)
+ nms[i] = round(fnms[i]);
+ nms[i] = -1;
+}
+
+void
+fpom(int year, double utcoffset, double *ffms, double *fnms)
+{
+ time_t tt;
+ struct tm GMT, tmd_today, tmd_tomorrow;
+ double days_today, days_tomorrow, today, tomorrow;
+ int cnt, d;
+ int yeardays;
+ int olddir, newdir;
+ double *pfnms, *pffms, t;
+
+ pfnms = fnms;
+ pffms = ffms;
+
+ /*
+ * We take the phase of the moon one second before and one second
+ * after midnight.
+ */
+ memset(&tmd_today, 0, sizeof(tmd_today));
+ tmd_today.tm_year = year - 1900;
+ tmd_today.tm_mon = 0;
+ tmd_today.tm_mday = -1; /* 31 December */
+ tmd_today.tm_hour = 23;
+ tmd_today.tm_min = 59;
+ tmd_today.tm_sec = 59;
+ memset(&tmd_tomorrow, 0, sizeof(tmd_tomorrow));
+ tmd_tomorrow.tm_year = year - 1900;
+ tmd_tomorrow.tm_mon = 0;
+ tmd_tomorrow.tm_mday = 0; /* 01 January */
+ tmd_tomorrow.tm_hour = 0;
+ tmd_tomorrow.tm_min = 0;
+ tmd_tomorrow.tm_sec = 1;
+
+ tt = mktime(&tmd_today);
+ gmtime_r(&tt, &GMT);
+ yeardays = 0;
+ for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt)
+ yeardays += isleap(1900 + cnt) ? DAYSPERLEAPYEAR : DAYSPERYEAR;
+ days_today = (GMT.tm_yday + 1) + ((GMT.tm_hour +
+ (GMT.tm_min / FSECSPERMINUTE) + (GMT.tm_sec / FSECSPERHOUR)) /
+ FHOURSPERDAY);
+ days_today += yeardays;
+
+ tt = mktime(&tmd_tomorrow);
+ gmtime_r(&tt, &GMT);
+ yeardays = 0;
+ for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt)
+ yeardays += isleap(1900 + cnt) ? DAYSPERLEAPYEAR : DAYSPERYEAR;
+ days_tomorrow = (GMT.tm_yday + 1) + ((GMT.tm_hour +
+ (GMT.tm_min / FSECSPERMINUTE) + (GMT.tm_sec / FSECSPERHOUR)) /
+ FHOURSPERDAY);
+ days_tomorrow += yeardays;
+
+ today = potm(days_today); /* 30 December 23:59:59 */
+ tomorrow = potm(days_tomorrow); /* 31 December 00:00:01 */
+ olddir = today > tomorrow ? -1 : +1;
+
+ yeardays = 1 + (isleap(year) ? DAYSPERLEAPYEAR : DAYSPERYEAR); /* reuse */
+ for (d = 0; d <= yeardays; d++) {
+ today = potm(days_today);
+ tomorrow = potm(days_tomorrow);
+ newdir = today > tomorrow ? -1 : +1;
+ if (olddir != newdir) {
+ t = potm_minute(days_today - 1, olddir) +
+ utcoffset / FHOURSPERDAY;
+ if (olddir == -1 && newdir == +1) {
+ *pfnms = d - 1 + t;
+ pfnms++;
+ } else if (olddir == +1 && newdir == -1) {
+ *pffms = d - 1 + t;
+ pffms++;
+ }
+ }
+ olddir = newdir;
+ days_today++;
+ days_tomorrow++;
+ }
+ *pffms = -1;
+ *pfnms = -1;
+}
+
+static double
+potm_minute(double onday, int olddir) {
+ double period = FSECSPERDAY / 2.0;
+ double p1, p2;
+ double before, after;
+ int newdir;
+
+// printf("---> days:%g olddir:%d\n", days, olddir);
+
+ p1 = onday + (period / SECSPERDAY);
+ period /= 2;
+
+ while (period > 30) { /* half a minute */
+// printf("period:%g - p1:%g - ", period, p1);
+ p2 = p1 + (2.0 / SECSPERDAY);
+ before = potm(p1);
+ after = potm(p2);
+// printf("before:%10.10g - after:%10.10g\n", before, after);
+ newdir = before < after ? -1 : +1;
+ if (olddir != newdir)
+ p1 += (period / SECSPERDAY);
+ else
+ p1 -= (period / SECSPERDAY);
+ period /= 2;
+// printf("newdir:%d - p1:%10.10f - period:%g\n",
+// newdir, p1, period);
+ }
+ p1 -= floor(p1);
+ //exit(0);
+ return (p1);
+}
+
+/*
+ * potm --
+ * return phase of the moon, as a percentage [0 ... 100]
+ */
+static double
+potm(double onday)
+{
+ double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime;
+ double A4, lprime, V, ldprime, D, Nm;
+
+ N = 360 * onday / 365.2422; /* sec 42 #3 */
+ adj360(&N);
+ Msol = N + EPSILONg - RHOg; /* sec 42 #4 */
+ adj360(&Msol);
+ Ec = 360 / PI * ECCEN * sin(dtor(Msol)); /* sec 42 #5 */
+ LambdaSol = N + Ec + EPSILONg; /* sec 42 #6 */
+ adj360(&LambdaSol);
+ l = 13.1763966 * onday + lzero; /* sec 61 #4 */
+ adj360(&l);
+ Mm = l - (0.1114041 * onday) - Pzero; /* sec 61 #5 */
+ adj360(&Mm);
+ Nm = Nzero - (0.0529539 * onday); /* sec 61 #6 */
+ adj360(&Nm);
+ Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */
+ Ac = 0.1858 * sin(dtor(Msol)); /* sec 61 #8 */
+ A3 = 0.37 * sin(dtor(Msol));
+ Mmprime = Mm + Ev - Ac - A3; /* sec 61 #9 */
+ Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 61 #10 */
+ A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 61 #11 */
+ lprime = l + Ev + Ec - Ac + A4; /* sec 61 #12 */
+ V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 61 #13 */
+ ldprime = lprime + V; /* sec 61 #14 */
+ D = ldprime - LambdaSol; /* sec 63 #2 */
+ return(50 * (1 - cos(dtor(D)))); /* sec 63 #3 */
+}
+
+/*
+ * dtor --
+ * convert degrees to radians
+ */
+static double
+dtor(double deg)
+{
+
+ return(deg * PI / 180);
+}
+
+/*
+ * adj360 --
+ * adjust value so 0 <= deg <= 360
+ */
+static void
+adj360(double *deg)
+{
+
+ for (;;)
+ if (*deg < 0)
+ *deg += 360;
+ else if (*deg > 360)
+ *deg -= 360;
+ else
+ break;
+}
diff --git a/usr.bin/calendar/sunpos.c b/usr.bin/calendar/sunpos.c
new file mode 100644
index 000000000000..a919f40007aa
--- /dev/null
+++ b/usr.bin/calendar/sunpos.c
@@ -0,0 +1,448 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009-2010 Edwin Groothuis <edwin@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+/*
+ * This code is created to match the formulas available at:
+ * Formula and examples obtained from "How to Calculate alt/az: SAAO" at
+ * http://old.saao.ac.za/public-info/sun-moon-stars/sun-index/how-to-calculate-altaz/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+#include <time.h>
+#include "calendar.h"
+
+#define D2R(m) ((m) / 180 * M_PI)
+#define R2D(m) ((m) * 180 / M_PI)
+
+#define SIN(x) (sin(D2R(x)))
+#define COS(x) (cos(D2R(x)))
+#define TAN(x) (tan(D2R(x)))
+#define ASIN(x) (R2D(asin(x)))
+#define ATAN(x) (R2D(atan(x)))
+
+#ifdef NOTDEF
+static void
+comp(char *s, double v, double c)
+{
+
+ printf("%-*s %*g %*g %*g\n", 15, s, 15, v, 15, c, 15, v - c);
+}
+
+int expY;
+double expZJ = 30.5;
+double expUTHM = 8.5;
+double expD = 34743.854;
+double expT = 0.9512349;
+double expL = 324.885;
+double expM = 42.029;
+double expepsilon = 23.4396;
+double explambda = 326.186;
+double expalpha = 328.428;
+double expDEC = -12.789;
+double expeastlongitude = 17.10;
+double explatitude = -22.57;
+double expHA = -37.673;
+double expALT = 49.822;
+double expAZ = 67.49;
+#endif
+
+static double
+fixup(double *d)
+{
+
+ if (*d < 0) {
+ while (*d < 0)
+ *d += 360;
+ } else {
+ while (*d > 360)
+ *d -= 360;
+ }
+
+ return (*d);
+}
+
+static double ZJtable[] = {
+ 0, -0.5, 30.5, 58.5, 89.5, 119.5, 150.5, 180.5, 211.5, 242.5, 272.5, 303.5, 333.5 };
+
+static void
+sunpos(int inYY, int inMM, int inDD, double UTCOFFSET, int inHOUR, int inMIN,
+ int inSEC, double eastlongitude, double latitude, double *L, double *DEC)
+{
+ int Y;
+ double ZJ, D, T, M, epsilon, lambda, alpha, HA, UTHM;
+
+ ZJ = ZJtable[inMM];
+ if (inMM <= 2 && isleap(inYY))
+ ZJ -= 1.0;
+
+ UTHM = inHOUR + inMIN / FMINSPERHOUR + inSEC / FSECSPERHOUR - UTCOFFSET;
+ Y = inYY - 1900; /* 1 */
+ D = floor(365.25 * Y) + ZJ + inDD + UTHM / FHOURSPERDAY; /* 3 */
+ T = D / 36525.0; /* 4 */
+ *L = 279.697 + 36000.769 * T; /* 5 */
+ fixup(L);
+ M = 358.476 + 35999.050 * T; /* 6 */
+ fixup(&M);
+ epsilon = 23.452 - 0.013 * T; /* 7 */
+ fixup(&epsilon);
+
+ lambda = *L + (1.919 - 0.005 * T) * SIN(M) + 0.020 * SIN(2 * M);/* 8 */
+ fixup(&lambda);
+ alpha = ATAN(TAN(lambda) * COS(epsilon)); /* 9 */
+
+ /* Alpha should be in the same quadrant as lamba */
+ {
+ int lssign = sin(D2R(lambda)) < 0 ? -1 : 1;
+ int lcsign = cos(D2R(lambda)) < 0 ? -1 : 1;
+ while (((sin(D2R(alpha)) < 0) ? -1 : 1) != lssign
+ || ((cos(D2R(alpha)) < 0) ? -1 : 1) != lcsign)
+ alpha += 90.0;
+ }
+ fixup(&alpha);
+
+ *DEC = ASIN(SIN(lambda) * SIN(epsilon)); /* 10 */
+ fixup(DEC);
+ fixup(&eastlongitude);
+ HA = *L - alpha + 180 + 15 * UTHM + eastlongitude; /* 12 */
+ fixup(&HA);
+ fixup(&latitude);
+#ifdef NOTDEF
+ printf("%02d/%02d %02d:%02d:%02d l:%g d:%g h:%g\n",
+ inMM, inDD, inHOUR, inMIN, inSEC, latitude, *DEC, HA);
+#endif
+ return;
+
+ /*
+ * The following calculations are not used, so to save time
+ * they are not calculated.
+ */
+#ifdef NOTDEF
+ *ALT = ASIN(SIN(latitude) * SIN(*DEC) +
+ COS(latitude) * COS(*DEC) * COS(HA)); /* 13 */
+ fixup(ALT);
+ *AZ = ATAN(SIN(HA) /
+ (COS(HA) * SIN(latitude) - TAN(*DEC) * COS(latitude))); /* 14 */
+
+ if (*ALT > 180)
+ *ALT -= 360;
+ if (*ALT < -180)
+ *ALT += 360;
+ printf("a:%g a:%g\n", *ALT, *AZ);
+#endif
+
+#ifdef NOTDEF
+ printf("Y:\t\t\t %d\t\t %d\t\t %d\n", Y, expY, Y - expY);
+ comp("ZJ", ZJ, expZJ);
+ comp("UTHM", UTHM, expUTHM);
+ comp("D", D, expD);
+ comp("T", T, expT);
+ comp("L", L, fixup(&expL));
+ comp("M", M, fixup(&expM));
+ comp("epsilon", epsilon, fixup(&expepsilon));
+ comp("lambda", lambda, fixup(&explambda));
+ comp("alpha", alpha, fixup(&expalpha));
+ comp("DEC", DEC, fixup(&expDEC));
+ comp("eastlongitude", eastlongitude, fixup(&expeastlongitude));
+ comp("latitude", latitude, fixup(&explatitude));
+ comp("HA", HA, fixup(&expHA));
+ comp("ALT", ALT, fixup(&expALT));
+ comp("AZ", AZ, fixup(&expAZ));
+#endif
+}
+
+
+#define SIGN(a) (((a) > 180) ? -1 : 1)
+#define ANGLE(a, b) (((a) < (b)) ? 1 : -1)
+#define SHOUR(s) ((s) / 3600)
+#define SMIN(s) (((s) % 3600) / 60)
+#define SSEC(s) ((s) % 60)
+#define HOUR(h) ((h) / 4)
+#define MIN(h) (15 * ((h) % 4))
+#define SEC(h) 0
+#define DEBUG1(y, m, d, hh, mm, pdec, dec) \
+ printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g\n", \
+ y, m, d, hh, mm, pdec, dec)
+#define DEBUG2(y, m, d, hh, mm, pdec, dec, pang, ang) \
+ printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g - %d -> %d\n", \
+ y, m, d, hh, mm, pdec, dec, pang, ang)
+void
+equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int *solsticedays)
+{
+ double fe[2], fs[2];
+
+ fequinoxsolstice(year, UTCoffset, fe, fs);
+ equinoxdays[0] = round(fe[0]);
+ equinoxdays[1] = round(fe[1]);
+ solsticedays[0] = round(fs[0]);
+ solsticedays[1] = round(fs[1]);
+}
+
+void
+fequinoxsolstice(int year, double UTCoffset, double *equinoxdays, double *solsticedays)
+{
+ double dec, prevdec, L;
+ int h, d, prevangle, angle;
+ int found = 0;
+
+ double decleft, decright, decmiddle;
+ int dial, s;
+
+ int *cumdays;
+ cumdays = cumdaytab[isleap(year)];
+
+ /*
+ * Find the first equinox, somewhere in March:
+ * It happens when the returned value "dec" goes from
+ * [350 ... 360> -> [0 ... 10]
+ */
+ for (d = 18; d < 31; d++) {
+ /* printf("Comparing day %d to %d.\n", d, d+1); */
+ sunpos(year, 3, d, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decleft);
+ sunpos(year, 3, d + 1, UTCoffset, 0, 0, 0, 0.0, 0.0,
+ &L, &decright);
+ /* printf("Found %g and %g.\n", decleft, decright); */
+ if (SIGN(decleft) == SIGN(decright))
+ continue;
+
+ dial = SECSPERDAY;
+ s = SECSPERDAY / 2;
+ while (s > 0) {
+ /* printf("Obtaining %d (%02d:%02d)\n",
+ dial, SHOUR(dial), SMIN(dial)); */
+ sunpos(year, 3, d, UTCoffset,
+ SHOUR(dial), SMIN(dial), SSEC(dial),
+ 0.0, 0.0, &L, &decmiddle);
+ /* printf("Found %g\n", decmiddle); */
+ if (SIGN(decleft) == SIGN(decmiddle)) {
+ decleft = decmiddle;
+ dial += s;
+ } else {
+ decright = decmiddle;
+ dial -= s;
+ }
+ /*
+ printf("New boundaries: %g - %g\n", decleft, decright);
+ */
+
+ s /= 2;
+ }
+ equinoxdays[0] = 1 + cumdays[3] + d + (dial / FSECSPERDAY);
+ break;
+ }
+
+ /* Find the second equinox, somewhere in September:
+ * It happens when the returned value "dec" goes from
+ * [10 ... 0] -> <360 ... 350]
+ */
+ for (d = 18; d < 31; d++) {
+ /* printf("Comparing day %d to %d.\n", d, d+1); */
+ sunpos(year, 9, d, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decleft);
+ sunpos(year, 9, d + 1, UTCoffset, 0, 0, 0, 0.0, 0.0,
+ &L, &decright);
+ /* printf("Found %g and %g.\n", decleft, decright); */
+ if (SIGN(decleft) == SIGN(decright))
+ continue;
+
+ dial = SECSPERDAY;
+ s = SECSPERDAY / 2;
+ while (s > 0) {
+ /* printf("Obtaining %d (%02d:%02d)\n",
+ dial, SHOUR(dial), SMIN(dial)); */
+ sunpos(year, 9, d, UTCoffset,
+ SHOUR(dial), SMIN(dial), SSEC(dial),
+ 0.0, 0.0, &L, &decmiddle);
+ /* printf("Found %g\n", decmiddle); */
+ if (SIGN(decleft) == SIGN(decmiddle)) {
+ decleft = decmiddle;
+ dial += s;
+ } else {
+ decright = decmiddle;
+ dial -= s;
+ }
+ /*
+ printf("New boundaries: %g - %g\n", decleft, decright);
+ */
+
+ s /= 2;
+ }
+ equinoxdays[1] = 1 + cumdays[9] + d + (dial / FSECSPERDAY);
+ break;
+ }
+
+ /*
+ * Find the first solstice, somewhere in June:
+ * It happens when the returned value "dec" peaks
+ * [40 ... 45] -> [45 ... 40]
+ */
+ found = 0;
+ prevdec = 0;
+ prevangle = 1;
+ for (d = 18; d < 31; d++) {
+ for (h = 0; h < 4 * HOURSPERDAY; h++) {
+ sunpos(year, 6, d, UTCoffset, HOUR(h), MIN(h), SEC(h),
+ 0.0, 0.0, &L, &dec);
+ angle = ANGLE(prevdec, dec);
+ if (prevangle != angle) {
+#ifdef NOTDEF
+ DEBUG2(year, 6, d, HOUR(h), MIN(h),
+ prevdec, dec, prevangle, angle);
+#endif
+ solsticedays[0] = 1 + cumdays[6] + d +
+ ((h / 4.0) / 24.0);
+ found = 1;
+ break;
+ }
+ prevdec = dec;
+ prevangle = angle;
+ }
+ if (found)
+ break;
+ }
+
+ /*
+ * Find the second solstice, somewhere in December:
+ * It happens when the returned value "dec" peaks
+ * [315 ... 310] -> [310 ... 315]
+ */
+ found = 0;
+ prevdec = 360;
+ prevangle = -1;
+ for (d = 18; d < 31; d++) {
+ for (h = 0; h < 4 * HOURSPERDAY; h++) {
+ sunpos(year, 12, d, UTCoffset, HOUR(h), MIN(h), SEC(h),
+ 0.0, 0.0, &L, &dec);
+ angle = ANGLE(prevdec, dec);
+ if (prevangle != angle) {
+#ifdef NOTDEF
+ DEBUG2(year, 12, d, HOUR(h), MIN(h),
+ prevdec, dec, prevangle, angle);
+#endif
+ solsticedays[1] = 1 + cumdays[12] + d +
+ ((h / 4.0) / 24.0);
+ found = 1;
+ break;
+ }
+ prevdec = dec;
+ prevangle = angle;
+ }
+ if (found)
+ break;
+ }
+
+ return;
+}
+
+int
+calculatesunlongitude30(int year, int degreeGMToffset, int *ichinesemonths)
+{
+ int m, d, h;
+ double dec;
+ double curL, prevL;
+ int *pichinesemonths, *monthdays, *cumdays, i;
+ int firstmonth330 = -1;
+
+ cumdays = cumdaytab[isleap(year)];
+ monthdays = monthdaytab[isleap(year)];
+ pichinesemonths = ichinesemonths;
+
+ h = 0;
+ sunpos(year - 1, 12, 31,
+ -24 * (degreeGMToffset / 360.0),
+ HOUR(h), MIN(h), SEC(h), 0.0, 0.0, &prevL, &dec);
+
+ for (m = 1; m <= 12; m++) {
+ for (d = 1; d <= monthdays[m]; d++) {
+ for (h = 0; h < 4 * HOURSPERDAY; h++) {
+ sunpos(year, m, d,
+ -24 * (degreeGMToffset / 360.0),
+ HOUR(h), MIN(h), SEC(h),
+ 0.0, 0.0, &curL, &dec);
+ if (curL < 180 && prevL > 180) {
+ *pichinesemonths = cumdays[m] + d;
+#ifdef DEBUG
+printf("%04d-%02d-%02d %02d:%02d - %d %g\n",
+ year, m, d, HOUR(h), MIN(h), *pichinesemonths, curL);
+#endif
+ pichinesemonths++;
+ } else {
+ for (i = 0; i <= 360; i += 30)
+ if (curL > i && prevL < i) {
+ *pichinesemonths =
+ cumdays[m] + d;
+#ifdef DEBUG
+printf("%04d-%02d-%02d %02d:%02d - %d %g\n",
+ year, m, d, HOUR(h), MIN(h), *pichinesemonths, curL);
+#endif
+ if (i == 330)
+ firstmonth330 = *pichinesemonths;
+ pichinesemonths++;
+ }
+ }
+ prevL = curL;
+ }
+ }
+ }
+ *pichinesemonths = -1;
+ return (firstmonth330);
+}
+
+#ifdef NOTDEF
+int
+main(int argc, char **argv)
+{
+/*
+ year Mar June Sept Dec
+ day time day time day time day time
+ 2004 20 06:49 21 00:57 22 16:30 21 12:42
+ 2005 20 12:33 21 06:46 22 22:23 21 18:35
+ 2006 20 18:26 21 12:26 23 04:03 22 00:22
+ 2007 21 00:07 21 18:06 23 09:51 22 06:08
+ 2008 20 05:48 20 23:59 22 15:44 21 12:04
+ 2009 20 11:44 21 05:45 22 21:18 21 17:47
+ 2010 20 17:32 21 11:28 23 03:09 21 23:38
+ 2011 20 23:21 21 17:16 23 09:04 22 05:30
+ 2012 20 05:14 20 23:09 22 14:49 21 11:11
+ 2013 20 11:02 21 05:04 22 20:44 21 17:11
+ 2014 20 16:57 21 10:51 23 02:29 21 23:03
+ 2015 20 22:45 21 16:38 23 08:20 22 04:48
+ 2016 20 04:30 20 22:34 22 14:21 21 10:44
+ 2017 20 10:28 21 04:24 22 20:02 21 16:28
+*/
+
+ int eq[2], sol[2];
+ equinoxsolstice(strtol(argv[1], NULL, 10), 0.0, eq, sol);
+ printf("%d - %d - %d - %d\n", eq[0], sol[0], eq[1], sol[1]);
+ return(0);
+}
+#endif
diff --git a/usr.bin/calendar/tests/Makefile b/usr.bin/calendar/tests/Makefile
new file mode 100644
index 000000000000..24ab9572413a
--- /dev/null
+++ b/usr.bin/calendar/tests/Makefile
@@ -0,0 +1,49 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= comment_test cond_test legacy_test
+
+TEST_METADATA.comment_test+= timeout="600"
+TEST_METADATA.cond_test+= timeout="600"
+TEST_METADATA.legacy_test+= timeout="600"
+
+${PACKAGE}FILES+= calendar.comment
+${PACKAGE}FILES+= regress.comment.out
+${PACKAGE}FILES+= comment.sh
+
+${PACKAGE}FILES+= calendar.cond
+${PACKAGE}FILES+= regress.cond.out
+${PACKAGE}FILES+= cond.sh
+
+${PACKAGE}FILES+= calendar.calibrate
+${PACKAGE}FILES+= regress.a1.out
+${PACKAGE}FILES+= regress.a2.out
+${PACKAGE}FILES+= regress.a3.out
+${PACKAGE}FILES+= regress.a4.out
+${PACKAGE}FILES+= regress.a5.out
+${PACKAGE}FILES+= regress.b1.out
+${PACKAGE}FILES+= regress.b2.out
+${PACKAGE}FILES+= regress.b3.out
+${PACKAGE}FILES+= regress.b4.out
+${PACKAGE}FILES+= regress.b5.out
+${PACKAGE}FILES+= regress.s1.out
+${PACKAGE}FILES+= regress.s2.out
+${PACKAGE}FILES+= regress.s3.out
+${PACKAGE}FILES+= regress.s4.out
+${PACKAGE}FILES+= regress.s5.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.w0-1.out
+${PACKAGE}FILES+= regress.w0-2.out
+${PACKAGE}FILES+= regress.w0-3.out
+${PACKAGE}FILES+= regress.w0-4.out
+${PACKAGE}FILES+= regress.w0-5.out
+${PACKAGE}FILES+= regress.w0-6.out
+${PACKAGE}FILES+= regress.w0-7.out
+${PACKAGE}FILES+= regress.wn-1.out
+${PACKAGE}FILES+= regress.wn-2.out
+${PACKAGE}FILES+= regress.wn-3.out
+${PACKAGE}FILES+= regress.wn-4.out
+${PACKAGE}FILES+= regress.wn-5.out
+${PACKAGE}FILES+= regress.wn-6.out
+${PACKAGE}FILES+= regress.wn-7.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/calendar/tests/Makefile.depend b/usr.bin/calendar/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/calendar/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/calendar/tests/calendar.calibrate b/usr.bin/calendar/tests/calendar.calibrate
new file mode 100644
index 000000000000..b18657694660
--- /dev/null
+++ b/usr.bin/calendar/tests/calendar.calibrate
@@ -0,0 +1,373 @@
+/*
+ * Calibration calendar for calendar(1)
+ */
+
+LANG=C
+
+01/01 jan 1
+01/02 jan 2
+01/03 jan 3
+01/04 jan 4
+01/05 jan 5
+01/06 jan 6
+01/07 jan 7
+01/08 jan 8
+01/09 jan 9
+01/10 jan 10
+01/11 jan 11
+01/12 jan 12
+01/13 jan 13
+01/14 jan 14
+01/15 jan 15
+01/16 jan 16
+01/17 jan 17
+01/18 jan 18
+01/19 jan 19
+01/20 jan 20
+01/21 jan 21
+01/22 jan 22
+01/23 jan 23
+01/24 jan 24
+01/25 jan 25
+01/26 jan 26
+01/27 jan 27
+01/28 jan 28
+01/29 jan 29
+01/30 jan 30
+01/31 jan 31
+02/01 feb 1
+02/02 feb 2
+02/03 feb 3
+02/04 feb 4
+02/05 feb 5
+02/06 feb 6
+02/07 feb 7
+02/08 feb 8
+02/09 feb 9
+02/10 feb 10
+02/11 feb 11
+02/12 feb 12
+02/13 feb 13
+02/14 feb 14
+02/15 feb 15
+02/16 feb 16
+02/17 feb 17
+02/18 feb 18
+02/19 feb 19
+02/20 feb 20
+02/21 feb 21
+02/22 feb 22
+02/23 feb 23
+02/24 feb 24
+02/25 feb 25
+02/26 feb 26
+02/27 feb 27
+02/28 feb 28
+02/29 feb 29
+03/01 mar 1
+03/02 mar 2
+03/03 mar 3
+03/04 mar 4
+03/05 mar 5
+03/06 mar 6
+03/07 mar 7
+03/08 mar 8
+03/09 mar 9
+03/10 mar 10
+03/11 mar 11
+03/12 mar 12
+03/13 mar 13
+03/14 mar 14
+03/15 mar 15
+03/16 mar 16
+03/17 mar 17
+03/18 mar 18
+03/19 mar 19
+03/20 mar 20
+03/21 mar 21
+03/22 mar 22
+03/23 mar 23
+03/24 mar 24
+03/25 mar 25
+03/26 mar 26
+03/27 mar 27
+03/28 mar 28
+03/29 mar 29
+03/30 mar 30
+03/31 mar 31
+04/01 apr 1
+04/02 apr 2
+04/03 apr 3
+04/04 apr 4
+04/05 apr 5
+04/06 apr 6
+04/07 apr 7
+04/08 apr 8
+04/09 apr 9
+04/10 apr 10
+04/11 apr 11
+04/12 apr 12
+04/13 apr 13
+04/14 apr 14
+04/15 apr 15
+04/16 apr 16
+04/17 apr 17
+04/18 apr 18
+04/19 apr 19
+04/20 apr 20
+04/21 apr 21
+04/22 apr 22
+04/23 apr 23
+04/24 apr 24
+04/25 apr 25
+04/26 apr 26
+04/27 apr 27
+04/28 apr 28
+04/29 apr 29
+04/30 apr 30
+05/01 may 1
+05/02 may 2
+05/03 may 3
+05/04 may 4
+05/05 may 5
+05/06 may 6
+05/07 may 7
+05/08 may 8
+05/09 may 9
+05/10 may 10
+05/11 may 11
+05/12 may 12
+05/13 may 13
+05/14 may 14
+05/15 may 15
+05/16 may 16
+05/17 may 17
+05/18 may 18
+05/19 may 19
+05/20 may 20
+05/21 may 21
+05/22 may 22
+05/23 may 23
+05/24 may 24
+05/25 may 25
+05/26 may 26
+05/27 may 27
+05/28 may 28
+05/29 may 29
+05/30 may 30
+05/31 may 31
+06/01 jun 1
+06/02 jun 2
+06/03 jun 3
+06/04 jun 4
+06/05 jun 5
+06/06 jun 6
+06/07 jun 7
+06/08 jun 8
+06/09 jun 9
+06/10 jun 10
+06/11 jun 11
+06/12 jun 12
+06/13 jun 13
+06/14 jun 14
+06/15 jun 15
+06/16 jun 16
+06/17 jun 17
+06/18 jun 18
+06/19 jun 19
+06/20 jun 20
+06/21 jun 21
+06/22 jun 22
+06/23 jun 23
+06/24 jun 24
+06/25 jun 25
+06/26 jun 26
+06/27 jun 27
+06/28 jun 28
+06/29 jun 29
+06/30 jun 30
+06/SunThird sunthird
+07/01 jul 1
+07/02 jul 2
+07/03 jul 3
+07/04 jul 4
+07/05 jul 5
+07/06 jul 6
+07/07 jul 7
+07/08 jul 8
+07/09 jul 9
+07/10 jul 10
+07/11 jul 11
+07/12 jul 12
+07/13 jul 13
+07/14 jul 14
+07/15 jul 15
+07/16 jul 16
+07/17 jul 17
+07/18 jul 18
+07/19 jul 19
+07/20 jul 20
+07/21 jul 21
+07/22 jul 22
+07/23 jul 23
+07/24 jul 24
+07/25 jul 25
+07/26 jul 26
+07/27 jul 27
+07/28 jul 28
+07/29 jul 29
+07/30 jul 30
+07/31 jul 31
+08/01 aug 1
+08/02 aug 2
+08/03 aug 3
+08/04 aug 4
+08/05 aug 5
+08/06 aug 6
+08/07 aug 7
+08/08 aug 8
+08/09 aug 9
+08/10 aug 10
+08/11 aug 11
+08/12 aug 12
+08/13 aug 13
+08/14 aug 14
+08/15 aug 15
+08/16 aug 16
+08/17 aug 17
+08/18 aug 18
+08/19 aug 19
+08/20 aug 20
+08/21 aug 21
+08/22 aug 22
+08/23 aug 23
+08/24 aug 24
+08/25 aug 25
+08/26 aug 26
+08/27 aug 27
+08/28 aug 28
+08/29 aug 29
+08/30 aug 30
+08/31 aug 31
+09/01 sep 1
+09/02 sep 2
+09/03 sep 3
+09/04 sep 4
+09/05 sep 5
+09/06 sep 6
+09/07 sep 7
+09/08 sep 8
+09/09 sep 9
+09/10 sep 10
+09/11 sep 11
+09/12 sep 12
+09/13 sep 13
+09/14 sep 14
+09/15 sep 15
+09/16 sep 16
+09/17 sep 17
+09/18 sep 18
+09/19 sep 19
+09/20 sep 20
+09/21 sep 21
+09/22 sep 22
+09/23 sep 23
+09/24 sep 24
+09/25 sep 25
+09/26 sep 26
+09/27 sep 27
+09/28 sep 28
+09/29 sep 29
+09/30 sep 30
+10/01 oct 1
+10/02 oct 2
+10/03 oct 3
+10/04 oct 4
+10/05 oct 5
+10/06 oct 6
+10/07 oct 7
+10/08 oct 8
+10/09 oct 9
+10/10 oct 10
+10/11 oct 11
+10/12 oct 12
+10/13 oct 13
+10/14 oct 14
+10/15 oct 15
+10/16 oct 16
+10/17 oct 17
+10/18 oct 18
+10/19 oct 19
+10/20 oct 20
+10/21 oct 21
+10/22 oct 22
+10/23 oct 23
+10/24 oct 24
+10/25 oct 25
+10/26 oct 26
+10/27 oct 27
+10/28 oct 28
+10/29 oct 29
+10/30 oct 30
+10/31 oct 31
+11/01 nov 1
+11/02 nov 2
+11/03 nov 3
+11/04 nov 4
+11/05 nov 5
+11/06 nov 6
+11/07 nov 7
+11/08 nov 8
+11/09 nov 9
+11/10 nov 10
+11/11 nov 11
+11/12 nov 12
+11/13 nov 13
+11/14 nov 14
+11/15 nov 15
+11/16 nov 16
+11/17 nov 17
+11/18 nov 18
+11/19 nov 19
+11/20 nov 20
+11/21 nov 21
+11/22 nov 22
+11/23 nov 23
+11/24 nov 24
+11/25 nov 25
+11/26 nov 26
+11/27 nov 27
+11/28 nov 28
+11/29 nov 29
+11/30 nov 30
+12/01 dec 1
+12/02 dec 2
+12/03 dec 3
+12/04 dec 4
+12/05 dec 5
+12/06 dec 6
+12/07 dec 7
+12/08 dec 8
+12/09 dec 9
+12/10 dec 10
+12/11 dec 11
+12/12 dec 12
+12/13 dec 13
+12/14 dec 14
+12/15 dec 15
+12/16 dec 16
+12/17 dec 17
+12/18 dec 18
+12/19 dec 19
+12/20 dec 20
+12/21 dec 21
+12/22 dec 22
+12/23 dec 23
+12/24 dec 24
+12/25 dec 25
+12/26 dec 26
+12/27 dec 27
+12/28 dec 28
+12/29 dec 29
+12/30 dec 30
+12/31 dec 31
diff --git a/usr.bin/calendar/tests/calendar.comment b/usr.bin/calendar/tests/calendar.comment
new file mode 100644
index 000000000000..837e5af9e89e
--- /dev/null
+++ b/usr.bin/calendar/tests/calendar.comment
@@ -0,0 +1,11 @@
+1 1 jan 1 // comment
+1 2 jan 2 /* comment */
+1 3 jan /* comment */3
+1 4 /* comment*/jan 4
+// comment
+/* comment */1 5 jan 5
+1/* comment */ 6 jan 6
+1 7 jan 7 // /* comment */ comment
+1 1/* comment */1 jan /* comment */11 // comment
+1 12 http://localhost.local/
+1 13 http://localhost.local/ // URL with additional comment
diff --git a/usr.bin/calendar/tests/calendar.cond b/usr.bin/calendar/tests/calendar.cond
new file mode 100644
index 000000000000..98806e50be67
--- /dev/null
+++ b/usr.bin/calendar/tests/calendar.cond
@@ -0,0 +1,83 @@
+#define DEF1
+
+1 1 jan 1 OK
+
+#ifdef DEF1
+1 2 jan 2 OK
+#endif
+
+1 3 jan 3 OK
+
+#ifdef DEF2
+1 4 jan 4 NOT OK
+#else
+1 5 jan 5 OK
+#endif
+
+#ifndef DEF2
+1 6 jan 6 OK
+#else
+1 7 jan 7 NOT OK
+#endif
+
+#ifdef DEF1
+#ifndef DEF2
+1 8 jan 8 OK
+#endif
+#endif
+
+#ifdef DEF1
+#ifdef DEF2
+1 9 jan 9 NOT OK
+#else
+1 10 jan 10 OK
+#endif
+#else
+1 11 jan 11 NOT OK
+#endif
+
+#define DEF2
+
+#ifndef DEF1 // skip = 1
+#ifndef DEF2 // skip = 2
+1 12 jan 12 NOT OK
+#else // skip = 1 unskip = 0
+1 13 jan 13 NOT OK
+#endif // skip = 0 unskip = 0
+#else // skip = 0 unskip = 1
+1 14 jan 14 OK
+#endif // skip = 0 unskip = 0
+
+#undef DEF1
+
+#ifdef DEF1 // OFF
+#ifdef DEF2 // ON
+#ifdef DEF3 // OFF
+1 15 jan 15 NOT OK
+#else
+1 16 jan 16 NOT OK
+#endif // DEF3
+#else // DEF2
+#ifdef DEF3
+1 17 jan 17 NOT OK
+#else
+1 18 jan 18 NOT OK
+#endif // DEF3
+#endif // DEF2
+#else // DEF1
+#ifdef DEF2
+#ifdef DEF3
+1 19 jan 19 NOT OK
+#else
+1 20 jan 20 OK
+#endif // DEF3
+#else // DEF2
+#ifdef DEF3
+1 21 jan 21 NOT OK
+#else
+1 22 jan 22 NOT OK
+#endif // DEF3
+#endif // DEF2
+#endif // DEF1
+
+1 23 jan 23 OK \ No newline at end of file
diff --git a/usr.bin/calendar/tests/comment.sh b/usr.bin/calendar/tests/comment.sh
new file mode 100755
index 000000000000..0dbc0d36b978
--- /dev/null
+++ b/usr.bin/calendar/tests/comment.sh
@@ -0,0 +1,13 @@
+
+CALENDAR_FILE="-f ${SRCDIR}/calendar.comment"
+CALENDAR_BIN="calendar"
+
+CALENDAR="${CALENDAR_BIN} ${CALENDAR_FILE}"
+
+REGRESSION_START($1)
+
+echo 1..1
+
+REGRESSION_TEST(`comment',`$CALENDAR -t 01.01.2020 -A 30')
+
+REGRESSION_END()
diff --git a/usr.bin/calendar/tests/comment_test.sh b/usr.bin/calendar/tests/comment_test.sh
new file mode 100755
index 000000000000..1c4dfe736bfd
--- /dev/null
+++ b/usr.bin/calendar/tests/comment_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/comment.sh" | sh
diff --git a/usr.bin/calendar/tests/cond.sh b/usr.bin/calendar/tests/cond.sh
new file mode 100755
index 000000000000..3a81220a0eb5
--- /dev/null
+++ b/usr.bin/calendar/tests/cond.sh
@@ -0,0 +1,13 @@
+
+CALENDAR_FILE="-f ${SRCDIR}/calendar.cond"
+CALENDAR_BIN="calendar"
+
+CALENDAR="${CALENDAR_BIN} ${CALENDAR_FILE}"
+
+REGRESSION_START($1)
+
+echo 1..1
+
+REGRESSION_TEST(`cond',`$CALENDAR -t 01.01.2020 -A 30')
+
+REGRESSION_END()
diff --git a/usr.bin/calendar/tests/cond_test.sh b/usr.bin/calendar/tests/cond_test.sh
new file mode 100755
index 000000000000..167ea0a81a13
--- /dev/null
+++ b/usr.bin/calendar/tests/cond_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/cond.sh" | sh
diff --git a/usr.bin/calendar/tests/legacy_test.sh b/usr.bin/calendar/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/calendar/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/calendar/tests/regress.a1.out b/usr.bin/calendar/tests/regress.a1.out
new file mode 100644
index 000000000000..ef3d71db5e57
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.a1.out
@@ -0,0 +1,4 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
diff --git a/usr.bin/calendar/tests/regress.a2.out b/usr.bin/calendar/tests/regress.a2.out
new file mode 100644
index 000000000000..0fed38ba2486
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.a2.out
@@ -0,0 +1,4 @@
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.a3.out b/usr.bin/calendar/tests/regress.a3.out
new file mode 100644
index 000000000000..9dabd3393352
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.a3.out
@@ -0,0 +1,4 @@
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
diff --git a/usr.bin/calendar/tests/regress.a4.out b/usr.bin/calendar/tests/regress.a4.out
new file mode 100644
index 000000000000..e3756b11f2b4
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.a4.out
@@ -0,0 +1,4 @@
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
diff --git a/usr.bin/calendar/tests/regress.a5.out b/usr.bin/calendar/tests/regress.a5.out
new file mode 100644
index 000000000000..4f61d48b291b
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.a5.out
@@ -0,0 +1,4 @@
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
+Jan 4 jan 4
diff --git a/usr.bin/calendar/tests/regress.b1.out b/usr.bin/calendar/tests/regress.b1.out
new file mode 100644
index 000000000000..ef3d71db5e57
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.b1.out
@@ -0,0 +1,4 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
diff --git a/usr.bin/calendar/tests/regress.b2.out b/usr.bin/calendar/tests/regress.b2.out
new file mode 100644
index 000000000000..0fed38ba2486
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.b2.out
@@ -0,0 +1,4 @@
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.b3.out b/usr.bin/calendar/tests/regress.b3.out
new file mode 100644
index 000000000000..9dabd3393352
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.b3.out
@@ -0,0 +1,4 @@
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
diff --git a/usr.bin/calendar/tests/regress.b4.out b/usr.bin/calendar/tests/regress.b4.out
new file mode 100644
index 000000000000..e3756b11f2b4
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.b4.out
@@ -0,0 +1,4 @@
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
diff --git a/usr.bin/calendar/tests/regress.b5.out b/usr.bin/calendar/tests/regress.b5.out
new file mode 100644
index 000000000000..4f61d48b291b
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.b5.out
@@ -0,0 +1,4 @@
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
+Jan 4 jan 4
diff --git a/usr.bin/calendar/tests/regress.comment.out b/usr.bin/calendar/tests/regress.comment.out
new file mode 100644
index 000000000000..fb58fd29ff05
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.comment.out
@@ -0,0 +1,10 @@
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
+Jan 4 jan 4
+Jan 5 jan 5
+Jan 6 jan 6
+Jan 7 jan 7
+Jan 11 jan 11
+Jan 12 http://localhost.local/
+Jan 13 http://localhost.local/
diff --git a/usr.bin/calendar/tests/regress.cond.out b/usr.bin/calendar/tests/regress.cond.out
new file mode 100644
index 000000000000..5f5c24829f0c
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.cond.out
@@ -0,0 +1,10 @@
+Jan 1 jan 1 OK
+Jan 2 jan 2 OK
+Jan 3 jan 3 OK
+Jan 5 jan 5 OK
+Jan 6 jan 6 OK
+Jan 8 jan 8 OK
+Jan 10 jan 10 OK
+Jan 14 jan 14 OK
+Jan 20 jan 20 OK
+Jan 23 jan 23 OK
diff --git a/usr.bin/calendar/tests/regress.s1.out b/usr.bin/calendar/tests/regress.s1.out
new file mode 100644
index 000000000000..0fed38ba2486
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.s1.out
@@ -0,0 +1,4 @@
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.s2.out b/usr.bin/calendar/tests/regress.s2.out
new file mode 100644
index 000000000000..65ab9c9c2733
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.s2.out
@@ -0,0 +1,2 @@
+Dec 30 dec 30
+Dec 31 dec 31
diff --git a/usr.bin/calendar/tests/regress.s3.out b/usr.bin/calendar/tests/regress.s3.out
new file mode 100644
index 000000000000..0c6120786ad0
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.s3.out
@@ -0,0 +1,2 @@
+Dec 31 dec 31
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.s4.out b/usr.bin/calendar/tests/regress.s4.out
new file mode 100644
index 000000000000..848976936398
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.s4.out
@@ -0,0 +1,2 @@
+Jan 1 jan 1
+Jan 2 jan 2
diff --git a/usr.bin/calendar/tests/regress.s5.out b/usr.bin/calendar/tests/regress.s5.out
new file mode 100644
index 000000000000..5134fde7b90a
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.s5.out
@@ -0,0 +1,3 @@
+Jun 21 jun 21
+Jun 21* sunthird
+Jun 22 jun 22
diff --git a/usr.bin/calendar/tests/regress.sh b/usr.bin/calendar/tests/regress.sh
new file mode 100644
index 000000000000..8844b1ef1ced
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.sh
@@ -0,0 +1,45 @@
+
+CALENDAR_FILE="-f ${SRCDIR}/calendar.calibrate"
+CALENDAR_BIN="calendar"
+
+CALENDAR="${CALENDAR_BIN} ${CALENDAR_FILE}"
+
+REGRESSION_START($1)
+
+echo 1..29
+
+REGRESSION_TEST(`s1',`$CALENDAR -t 29.12.2006')
+REGRESSION_TEST(`s2',`$CALENDAR -t 30.12.2006')
+REGRESSION_TEST(`s3',`$CALENDAR -t 31.12.2006')
+REGRESSION_TEST(`s4',`$CALENDAR -t 01.01.2007')
+REGRESSION_TEST(`s5',`$CALENDAR -t 21.06.2015')
+
+REGRESSION_TEST(`a1',`$CALENDAR -A 3 -t 28.12.2006')
+REGRESSION_TEST(`a2',`$CALENDAR -A 3 -t 29.12.2006')
+REGRESSION_TEST(`a3',`$CALENDAR -A 3 -t 30.12.2006')
+REGRESSION_TEST(`a4',`$CALENDAR -A 3 -t 31.12.2006')
+REGRESSION_TEST(`a5',`$CALENDAR -A 3 -t 01.01.2007')
+
+REGRESSION_TEST(`b1',`$CALENDAR -B 3 -t 31.12.2006')
+REGRESSION_TEST(`b2',`$CALENDAR -B 3 -t 01.01.2007')
+REGRESSION_TEST(`b3',`$CALENDAR -B 3 -t 02.01.2007')
+REGRESSION_TEST(`b4',`$CALENDAR -B 3 -t 03.01.2007')
+REGRESSION_TEST(`b5',`$CALENDAR -B 3 -t 04.01.2007')
+
+REGRESSION_TEST(`w0-1',`$CALENDAR -W 0 -t 28.12.2006')
+REGRESSION_TEST(`w0-2',`$CALENDAR -W 0 -t 29.12.2006')
+REGRESSION_TEST(`w0-3',`$CALENDAR -W 0 -t 30.12.2006')
+REGRESSION_TEST(`w0-4',`$CALENDAR -W 0 -t 31.12.2006')
+REGRESSION_TEST(`w0-5',`$CALENDAR -W 0 -t 01.01.2007')
+REGRESSION_TEST(`w0-6',`$CALENDAR -W 0 -t 02.01.2007')
+REGRESSION_TEST(`w0-7',`$CALENDAR -W 0 -t 03.01.2007')
+
+REGRESSION_TEST(`wn-1',`$CALENDAR -W 0 -t 28.12.2006')
+REGRESSION_TEST(`wn-2',`$CALENDAR -W 1 -t 28.12.2006')
+REGRESSION_TEST(`wn-3',`$CALENDAR -W 2 -t 28.12.2006')
+REGRESSION_TEST(`wn-4',`$CALENDAR -W 3 -t 28.12.2006')
+REGRESSION_TEST(`wn-5',`$CALENDAR -W 4 -t 28.12.2006')
+REGRESSION_TEST(`wn-6',`$CALENDAR -W 5 -t 28.12.2006')
+REGRESSION_TEST(`wn-7',`$CALENDAR -W 6 -t 28.12.2006')
+
+REGRESSION_END()
diff --git a/usr.bin/calendar/tests/regress.w0-1.out b/usr.bin/calendar/tests/regress.w0-1.out
new file mode 100644
index 000000000000..5bd407202318
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-1.out
@@ -0,0 +1 @@
+Dec 28 dec 28
diff --git a/usr.bin/calendar/tests/regress.w0-2.out b/usr.bin/calendar/tests/regress.w0-2.out
new file mode 100644
index 000000000000..66e70639ce56
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-2.out
@@ -0,0 +1 @@
+Dec 29 dec 29
diff --git a/usr.bin/calendar/tests/regress.w0-3.out b/usr.bin/calendar/tests/regress.w0-3.out
new file mode 100644
index 000000000000..03073eee3a4b
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-3.out
@@ -0,0 +1 @@
+Dec 30 dec 30
diff --git a/usr.bin/calendar/tests/regress.w0-4.out b/usr.bin/calendar/tests/regress.w0-4.out
new file mode 100644
index 000000000000..a14f6b68b2fa
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-4.out
@@ -0,0 +1 @@
+Dec 31 dec 31
diff --git a/usr.bin/calendar/tests/regress.w0-5.out b/usr.bin/calendar/tests/regress.w0-5.out
new file mode 100644
index 000000000000..1232b9b2d9ec
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-5.out
@@ -0,0 +1 @@
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.w0-6.out b/usr.bin/calendar/tests/regress.w0-6.out
new file mode 100644
index 000000000000..b3545a21bd9a
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-6.out
@@ -0,0 +1 @@
+Jan 2 jan 2
diff --git a/usr.bin/calendar/tests/regress.w0-7.out b/usr.bin/calendar/tests/regress.w0-7.out
new file mode 100644
index 000000000000..6449760481f6
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.w0-7.out
@@ -0,0 +1 @@
+Jan 3 jan 3
diff --git a/usr.bin/calendar/tests/regress.wn-1.out b/usr.bin/calendar/tests/regress.wn-1.out
new file mode 100644
index 000000000000..5bd407202318
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-1.out
@@ -0,0 +1 @@
+Dec 28 dec 28
diff --git a/usr.bin/calendar/tests/regress.wn-2.out b/usr.bin/calendar/tests/regress.wn-2.out
new file mode 100644
index 000000000000..84a2b33a2969
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-2.out
@@ -0,0 +1,2 @@
+Dec 28 dec 28
+Dec 29 dec 29
diff --git a/usr.bin/calendar/tests/regress.wn-3.out b/usr.bin/calendar/tests/regress.wn-3.out
new file mode 100644
index 000000000000..7f027e59a8fe
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-3.out
@@ -0,0 +1,3 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
diff --git a/usr.bin/calendar/tests/regress.wn-4.out b/usr.bin/calendar/tests/regress.wn-4.out
new file mode 100644
index 000000000000..ef3d71db5e57
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-4.out
@@ -0,0 +1,4 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
diff --git a/usr.bin/calendar/tests/regress.wn-5.out b/usr.bin/calendar/tests/regress.wn-5.out
new file mode 100644
index 000000000000..c38c00b86cef
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-5.out
@@ -0,0 +1,5 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
diff --git a/usr.bin/calendar/tests/regress.wn-6.out b/usr.bin/calendar/tests/regress.wn-6.out
new file mode 100644
index 000000000000..63c99fe44e6e
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-6.out
@@ -0,0 +1,6 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
diff --git a/usr.bin/calendar/tests/regress.wn-7.out b/usr.bin/calendar/tests/regress.wn-7.out
new file mode 100644
index 000000000000..4b48f68101c3
--- /dev/null
+++ b/usr.bin/calendar/tests/regress.wn-7.out
@@ -0,0 +1,7 @@
+Dec 28 dec 28
+Dec 29 dec 29
+Dec 30 dec 30
+Dec 31 dec 31
+Jan 1 jan 1
+Jan 2 jan 2
+Jan 3 jan 3
diff --git a/usr.bin/cap_mkdb/Makefile b/usr.bin/cap_mkdb/Makefile
new file mode 100644
index 000000000000..4beb70d551bd
--- /dev/null
+++ b/usr.bin/cap_mkdb/Makefile
@@ -0,0 +1,3 @@
+PROG= cap_mkdb
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cap_mkdb/Makefile.depend b/usr.bin/cap_mkdb/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/cap_mkdb/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cap_mkdb/Makefile.depend.host b/usr.bin/cap_mkdb/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/cap_mkdb/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cap_mkdb/Makefile.depend.options b/usr.bin/cap_mkdb/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/cap_mkdb/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/cap_mkdb/cap_mkdb.1 b/usr.bin/cap_mkdb/cap_mkdb.1
new file mode 100644
index 000000000000..8acb85827120
--- /dev/null
+++ b/usr.bin/cap_mkdb/cap_mkdb.1
@@ -0,0 +1,102 @@
+.\" 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.
+.\"
+.Dd February 22, 2005
+.Dt CAP_MKDB 1
+.Os
+.Sh NAME
+.Nm cap_mkdb
+.Nd create capability database
+.Sh SYNOPSIS
+.Nm
+.Op Fl b | l
+.Op Fl v
+.Op Fl f Ar outfile
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility builds a hashed database out of the
+.Xr getcap 3
+logical database constructed by the concatenation of the specified
+files.
+.Pp
+The database is named by the basename of the first file argument and
+the string
+.Dq .db .
+The
+.Xr getcap 3
+routines can access the database in this form much more quickly
+than they can the original text file(s).
+.Pp
+The ``tc'' capabilities of the records are expanded before the
+record is stored into the database.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl b
+Use big-endian byte order for database metadata.
+.It Fl f Ar outfile
+Specify a different database basename.
+.It Fl l
+Use little-endian byte order for database metadata.
+.It Fl v
+Print out the number of capability records in the database.
+.El
+.Pp
+The
+.Fl b
+and
+.Fl l
+flags are mutually exclusive.
+The default byte ordering is the current host order.
+.Sh FORMAT
+Each record is stored in the database using two different types of keys.
+.Pp
+The first type is a key which consists of the first capability of
+the record (not including the trailing colon (``:'')) with a data
+field consisting of a special byte followed by the rest of the record.
+The special byte is either a 0 or 1, where a 0 means that the record
+is okay, and a 1 means that there was a ``tc'' capability in the record
+that could not be expanded.
+.Pp
+The second type is a key which consists of one of the names from the
+first capability of the record with a data field consisting a special
+byte followed by the first capability of the record.
+The special byte is a 2.
+.Pp
+In normal operation names are looked up in the database, resulting
+in a key/data pair of the second type.
+The data field of this key/data pair is used to look up a key/data
+pair of the first type which has the real data associated with the
+name.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr dbopen 3 ,
+.Xr getcap 3 ,
+.Xr termcap 5
diff --git a/usr.bin/cap_mkdb/cap_mkdb.c b/usr.bin/cap_mkdb/cap_mkdb.c
new file mode 100644
index 000000000000..7ee6d2ddd2b3
--- /dev/null
+++ b/usr.bin/cap_mkdb/cap_mkdb.c
@@ -0,0 +1,255 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <db.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void db_build(char **);
+static void dounlink(void);
+static void usage(void);
+
+static DB *capdbp;
+static int verbose;
+static char *capname, buf[8 * 1024];
+
+static HASHINFO openinfo = {
+ 4096, /* bsize */
+ 0, /* ffactor */
+ 0, /* nelem */
+ 0, /* cachesize */
+ NULL, /* hash() */
+ 0 /* lorder */
+};
+
+/*
+ * Mkcapdb creates a capability hash database for quick retrieval of capability
+ * records. The database contains 2 types of entries: records and references
+ * marked by the first byte in the data. A record entry contains the actual
+ * capability record whereas a reference contains the name (key) under which
+ * the correct record is stored.
+ */
+int
+main(int argc, char *argv[])
+{
+ int byteorder, c;
+
+ capname = NULL;
+ byteorder = 0;
+ while ((c = getopt(argc, argv, "bf:lv")) != -1) {
+ switch(c) {
+ case 'b':
+ case 'l':
+ if (byteorder != 0)
+ usage();
+ byteorder = c == 'b' ? 4321 : 1234;
+ break;
+ case 'f':
+ capname = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (*argv == NULL)
+ usage();
+
+ /* Set byte order. */
+ openinfo.lorder = byteorder;
+
+ /*
+ * The database file is the first argument if no name is specified.
+ * Make arrangements to unlink it if exit badly.
+ */
+ (void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv);
+ if ((capname = strdup(buf)) == NULL)
+ errx(1, "strdup failed");
+ if ((capdbp = dbopen(capname, O_CREAT | O_TRUNC | O_RDWR,
+ DEFFILEMODE, DB_HASH, &openinfo)) == NULL)
+ err(1, "%s", buf);
+
+ if (atexit(dounlink))
+ err(1, "atexit");
+
+ db_build(argv);
+
+ if (capdbp->close(capdbp) < 0)
+ err(1, "%s", capname);
+ capname = NULL;
+ exit(0);
+}
+
+static void
+dounlink(void)
+{
+ if (capname != NULL)
+ (void)unlink(capname);
+}
+
+/*
+ * Any changes to these definitions should be made also in the getcap(3)
+ * library routines.
+ */
+#define RECOK (char)0
+#define TCERR (char)1
+#define SHADOW (char)2
+
+/*
+ * Db_build() builds the name and capability databases according to the
+ * details above.
+ */
+static void
+db_build(char **ifiles)
+{
+ DBT key, data;
+ recno_t reccnt;
+ size_t len, bplen;
+ int st;
+ char *bp, *p, *t;
+
+ data.data = NULL;
+ key.data = NULL;
+ for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) {
+
+ /*
+ * Allocate enough memory to store record, terminating
+ * NULL and one extra byte.
+ */
+ len = strlen(bp);
+ if (bplen <= len + 2) {
+ bplen += MAX(256, len + 2);
+ if ((data.data = realloc(data.data, bplen)) == NULL)
+ errx(1, "malloc failed");
+ }
+
+ /* Find the end of the name field. */
+ if ((p = strchr(bp, ':')) == NULL) {
+ warnx("no name field: %.*s", (int)MIN(len, 20), bp);
+ continue;
+ }
+
+ /* First byte of stored record indicates status. */
+ switch(st) {
+ case 1:
+ ((char *)(data.data))[0] = RECOK;
+ break;
+ case 2:
+ ((char *)(data.data))[0] = TCERR;
+ warnx("record not tc expanded: %.*s", (int)(p - bp),
+ bp);
+ break;
+ }
+
+ /* Create the stored record. */
+ memmove(&((u_char *)(data.data))[1], bp, len + 1);
+ data.size = len + 2;
+
+ /* Store the record under the name field. */
+ key.data = bp;
+ key.size = p - bp;
+
+ switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) {
+ case -1:
+ err(1, "put");
+ /* NOTREACHED */
+ case 1:
+ warnx("ignored duplicate: %.*s",
+ (int)key.size, (char *)key.data);
+ continue;
+ }
+ ++reccnt;
+
+ /* If only one name, ignore the rest. */
+ *p = '\0';
+ if (strchr(bp, '|') == NULL)
+ continue;
+ *p = ':';
+
+ /* The rest of the names reference the entire name. */
+ ((char *)(data.data))[0] = SHADOW;
+ memmove(&((u_char *)(data.data))[1], key.data, key.size);
+ data.size = key.size + 1;
+
+ /* Store references for other names. */
+ for (p = t = bp;; ++p) {
+ if (p > t && (*p == ':' || *p == '|')) {
+ key.size = p - t;
+ key.data = t;
+ switch(capdbp->put(capdbp,
+ &key, &data, R_NOOVERWRITE)) {
+ case -1:
+ err(1, "put");
+ /* NOTREACHED */
+ case 1:
+ warnx("ignored duplicate: %.*s",
+ (int)key.size, (char *)key.data);
+ }
+ t = p + 1;
+ }
+ if (*p == ':')
+ break;
+ }
+ }
+
+ switch(st) {
+ case -1:
+ err(1, "file argument");
+ /* NOTREACHED */
+ case -2:
+ errx(1, "potential reference loop detected");
+ /* NOTREACHED */
+ }
+
+ if (verbose)
+ (void)printf("cap_mkdb: %d capability records\n", reccnt);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: cap_mkdb [-b | -l] [-v] [-f outfile] file ...\n");
+ exit(1);
+}
diff --git a/usr.bin/chat/Makefile b/usr.bin/chat/Makefile
new file mode 100644
index 000000000000..dfe76f71aba7
--- /dev/null
+++ b/usr.bin/chat/Makefile
@@ -0,0 +1,7 @@
+# I once used this extensively, but no longer have a modem. Feel free
+# to ask me questions about it, but I disclaim ownership now. -Peter
+
+PROG= chat
+MAN= chat.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/chat/Makefile.depend b/usr.bin/chat/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/chat/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/chat/chat.8 b/usr.bin/chat/chat.8
new file mode 100644
index 000000000000..ed9b346e4d3b
--- /dev/null
+++ b/usr.bin/chat/chat.8
@@ -0,0 +1,644 @@
+.Dd September 10, 2012
+.Dt CHAT 8
+.Os
+.Sh NAME
+.Nm chat
+.Nd Automated conversational script with a modem
+.Sh SYNOPSIS
+.Nm
+.Op Fl eSsVv
+.Op Fl f Ar chat-file
+.Op Fl r Ar report-file
+.Op Fl T Ar phone-number
+.Op Fl t Ar timeout
+.Op Fl U Ar phone-number2
+.Op Ar script
+.Sh DESCRIPTION
+The
+.Nm
+program defines a conversational exchange between the
+computer and the modem.
+Its primary purpose is to establish the
+connection between the Point-to-Point Protocol Daemon
+.Pq pppd
+and the remote's pppd process.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl e
+Start with the echo option turned on.
+Echoing may also be turned on
+or off at specific points in the chat script by using the ECHO
+keyword.
+When echoing is enabled, all output from the modem is echoed
+to
+.Em stderr .
+.It Fl f Ar chat-file
+Read the chat script from the chat file.
+The use of this option
+is mutually exclusive with the chat script parameters.
+The user must
+have read access to the file.
+Multiple lines are permitted in the file.
+Space or horizontal tab characters should be used to separate
+the strings.
+.It Fl r Ar report-file
+Set the file for output of the report strings.
+If you use the keyword
+.Dv REPORT ,
+the resulting strings are written to this file.
+If this
+option is not used and you still use
+.Dv REPORT
+keywords, the
+.Pa stderr
+file is used for the report strings.
+.It Fl S
+Do not use
+.Xr syslog 3 .
+By default, error messages are sent to
+.Xr syslog 3 .
+The use of
+.Fl S
+will prevent both log messages from
+.Fl v
+and error messages from being sent to
+.Xr syslog 3 .
+.It Fl s
+Use
+.Em stderr .
+All log messages from
+.Fl v
+and all error messages will be
+sent to
+.Em stderr .
+.It Fl T Ar phone-number
+Pass in an arbitrary string, usually a phone number, that will be
+substituted for the \\T substitution metacharacter in a send string.
+.It Fl t Ar timeout
+Set the timeout for the expected string to be received.
+If the string
+is not received within the time limit then the reply string is not
+sent.
+An alternate reply may be sent or the script will fail if there
+is no alternate reply string.
+A failed script will cause the
+.Nm
+program to terminate with a non-zero error code.
+.It Fl U Ar phone-number2
+Pass in a second string, usually a phone number, that will be
+substituted for the \\U substitution metacharacter in a send string.
+This is useful when dialing an ISDN terminal adapter that requires two
+numbers.
+.It Fl V
+Request that the
+.Nm
+script be executed in a
+.Em stderr
+verbose mode.
+The
+.Nm
+program will then log all text received from the
+modem and the output strings sent to the modem to the stderr device.
+This
+device is usually the local console at the station running the chat or
+pppd program.
+.It Fl v
+Request that the
+.Nm
+script be executed in a verbose mode.
+The
+.Nm
+program will then log the execution state of the chat
+script as well as all text received from the modem and the output
+strings sent to the modem.
+The default is to log through
+.Xr syslog 3 ;
+the logging method may be altered with the
+.Fl S
+and
+.Fl s
+flags.
+Logging is done to the
+.Em local2
+facility at level
+.Em info
+for verbose tracing and level
+.Em err
+for some errors.
+.El
+.Sh CHAT SCRIPT
+The
+.Nm
+script defines the communications.
+A script consists of one or more "expect-send" pairs of strings,
+separated by spaces, with an optional "subexpect-subsend" string pair,
+separated by a dash as in the following example:
+.Pp
+.D1 ogin:-BREAK-ogin: ppp ssword: hello2u2
+.Pp
+This line indicates that the
+.Nm
+program should expect the string "ogin:".
+If it fails to receive a login prompt within the time interval
+allotted, it is to send a break sequence to the remote and then expect the
+string "ogin:".
+If the first "ogin:" is received then the break sequence is
+not generated.
+.Pp
+Once it received the login prompt the
+.Nm
+program will send the
+string ppp and then expect the prompt "ssword:".
+When it receives the
+prompt for the password, it will send the password hello2u2.
+.Pp
+A carriage return is normally sent following the reply string.
+It is not
+expected in the "expect" string unless it is specifically requested by using
+the \\r character sequence.
+.Pp
+The expect sequence should contain only what is needed to identify the
+string.
+Since it is normally stored on a disk file, it should not contain
+variable information.
+It is generally not acceptable to look for time
+strings, network identification strings, or other variable pieces of data as
+an expect string.
+.Pp
+To help correct for characters which may be corrupted during the initial
+sequence, look for the string "ogin:" rather than "login:".
+It is possible
+that the leading "l" character may be received in error and you may never
+find the string even though it was sent by the system.
+For this reason,
+scripts look for "ogin:" rather than "login:" and "ssword:" rather than
+"password:".
+.Pp
+A very simple script might look like this:
+.Pp
+.D1 ogin: ppp ssword: hello2u2
+.Pp
+In other words, expect ....ogin:, send ppp, expect ...ssword:, send hello2u2.
+.Pp
+In actual practice, simple scripts are rare.
+At the vary least, you
+should include sub-expect sequences should the original string not be
+received.
+For example, consider the following script:
+.Pp
+.D1 ogin:--ogin: ppp ssword: hello2u2
+.Pp
+This would be a better script than the simple one used earlier.
+This would look
+for the same login: prompt, however, if one was not received, a single
+return sequence is sent and then it will look for login: again.
+Should line
+noise obscure the first login prompt then sending the empty line will
+usually generate a login prompt again.
+.Sh COMMENTS
+Comments can be embedded in the chat script.
+A comment is a line which
+starts with the # (hash) character in column 1.
+Such comment
+lines are just ignored by the chat program.
+If a '#' character is to
+be expected as the first character of the expect sequence, you should
+quote the expect string.
+If you want to wait for a prompt that starts with a # (hash)
+character, you would have to write something like this:
+.Bd -literal -offset indent
+# Now wait for the prompt and send logout string
+\&'# ' logout
+.Ed
+.Sh ABORT STRINGS
+Many modems will report the status of the call as a string.
+These strings may be
+.Dv CONNECTED
+or
+.Dv NO CARRIER
+or
+.Dv BUSY .
+It is often desirable to terminate the script should the modem fail to
+connect to the remote.
+The difficulty is that a script would not know
+exactly which modem string it may receive.
+On one attempt, it may receive
+.Dv BUSY
+while the next time it may receive
+.Dv NO CARRIER .
+.Pp
+These "abort" strings may be specified in the script using the ABORT
+sequence.
+It is written in the script as in the following example:
+.Pp
+.D1 ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ATDT5551212 CONNECT
+.Pp
+This sequence will expect nothing; and then send the string ATZ.
+The expected response to this is the string
+.Dv OK .
+When it receives
+.Dv OK ,
+the string ATDT5551212 to dial the telephone.
+The expected string is
+.Dv CONNECT .
+If the string
+.Dv CONNECT
+is received the remainder of the
+script is executed.
+However, should the modem find a busy telephone, it will
+send the string
+.Dv BUSY .
+This will cause the string to match the abort
+character sequence.
+The script will then fail because it found a match to
+the abort string.
+If it received the string
+.Dv NO CARRIER ,
+it will abort
+for the same reason.
+Either string may be received.
+Either string will
+terminate the
+.Nm
+script.
+.Sh CLR_ABORT STRINGS
+This sequence allows for clearing previously set
+.Dv ABORT
+strings.
+.Dv ABORT
+strings are kept in an array of a pre-determined size (at
+compilation time); CLR_ABORT will reclaim the space for cleared
+entries so that new strings can use that space.
+.Sh SAY STRINGS
+The
+.Dv SAY
+directive allows the script to send strings to the user
+at the terminal via standard error.
+If
+.Nm
+is being run by
+pppd, and pppd is running as a daemon (detached from its controlling
+terminal), standard error will normally be redirected to the file
+.Pa /etc/ppp/connect-errors .
+.Pp
+.Dv SAY
+strings must be enclosed in single or double quotes.
+If carriage return and line feed are needed in the string to be output,
+you must explicitly add them to your string.
+.Pp
+The
+.Dv SAY
+strings could be used to give progress messages in sections of
+the script where you want to have 'ECHO OFF' but still let the user
+know what is happening.
+An example is:
+.Bd -literal -offset indent
+ABORT BUSY
+ECHO OFF
+SAY "Dialling your ISP...\\n"
+\&'' ATDT5551212
+TIMEOUT 120
+SAY "Waiting up to 2 minutes for connection ... "
+CONNECT ''
+SAY "Connected, now logging in ...\\n"
+ogin: account
+ssword: pass
+$ SAY "Logged in OK ...\\n" \fIetc ...\fR
+.Ed
+.Pp
+This sequence will only present the
+.Dv SAY
+strings to the user and all
+the details of the script will remain hidden.
+For example, if the
+above script works, the user will see:
+.Bd -literal -offset indent
+Dialling your ISP...
+Waiting up to 2 minutes for connection ... Connected, now logging in ...
+Logged in OK ...
+.Ed
+.Sh REPORT STRINGS
+A report string is similar to the
+.Dv ABORT
+string.
+The difference
+is that the strings, and all characters to the next control character
+such as a carriage return, are written to the report file.
+.Pp
+The report strings may be used to isolate the transmission rate of the
+modem's connect string and return the value to the chat user.
+The
+analysis of the report string logic occurs in conjunction with the
+other string processing such as looking for the expect string.
+The use
+of the same string for a report and abort sequence is probably not
+very useful, however, it is possible.
+.Pp
+The report strings to no change the completion code of the program.
+.Pp
+These "report" strings may be specified in the script using the
+.Dv REPORT
+sequence.
+It is written in the script as in the following example:
+.Pp
+.D1 REPORT CONNECT ABORT BUSY '' ATDT5551212 CONNECT '' ogin: account
+.Pp
+This sequence will expect nothing; and then send the string
+ATDT5551212 to dial the telephone.
+The expected string is
+.Dv CONNECT .
+If the string
+.Dv CONNECT
+is received the remainder
+of the script is executed.
+In addition the program will write to the
+expect-file the string "CONNECT" plus any characters which follow it
+such as the connection rate.
+.Sh CLR_REPORT STRINGS
+This sequence allows for clearing previously set
+.Dv REPORT
+strings.
+.Dv REPORT
+strings are kept in an array of a pre-determined size (at
+compilation time); CLR_REPORT will reclaim the space for cleared
+entries so that new strings can use that space.
+.Sh ECHO
+The echo options controls whether the output from the modem is echoed
+to
+.Em stderr .
+This option may be set with the
+.Fl e
+option, but
+it can also be controlled by the
+.Dv ECHO
+keyword.
+The "expect-send"
+pair
+.Dv ECHO ON
+enables echoing, and
+.Dv ECHO OFF
+disables it.
+With this keyword you can select which parts of the
+conversation should be visible.
+For instance, with the following
+script:
+.Bd -literal -offset indent
+ABORT 'BUSY'
+ABORT 'NO CARRIER'
+\&'' ATZ
+OK\\r\\n ATD1234567
+\\r\\n \\c
+ECHO ON
+CONNECT \\c
+ogin: account
+.Ed
+.Pp
+all output resulting from modem configuration and dialing is not visible,
+but starting with the
+.Dv CONNECT
+or
+.Dv BUSY
+message, everything
+will be echoed.
+.Sh HANGUP
+The
+.Dv HANGUP
+options control whether a modem hangup should be considered
+as an error or not.
+This option is useful in scripts for dialling
+systems which will hang up and call your system back.
+The
+.Dv HANGUP
+options can be
+.Dv ON
+or
+.Dv OFF .
+.Pp
+When
+.Dv HANGUP
+is set
+.Dv OFF
+and the modem hangs up (e.g., after the first
+stage of logging in to a callback system),
+.Nm
+will continue
+running the script (e.g., waiting for the incoming call and second
+stage login prompt).
+As soon as the incoming call is connected, you
+should use the
+.Dv HANGUP ON
+directive to reinstall normal hang up
+signal behavior.
+Here is a (simple) example script:
+.Bd -literal -offset indent
+ABORT 'BUSY'
+\&'' ATZ
+OK\\r\\n ATD1234567
+\\r\\n \\c
+CONNECT \\c
+\&'Callback login:' call_back_ID
+HANGUP OFF
+ABORT "Bad Login"
+\&'Callback Password:' Call_back_password
+TIMEOUT 120
+CONNECT \\c
+HANGUP ON
+ABORT "NO CARRIER"
+ogin:--BREAK--ogin: real_account
+\fIetc ...\fR
+.Ed
+.Sh TIMEOUT
+The initial timeout value is 45 seconds.
+This may be changed using the
+.Fl t
+parameter.
+.Pp
+To change the timeout value for the next expect string, the following
+example may be used:
+.Bd -literal -offset indent
+ATZ OK ATDT5551212 CONNECT TIMEOUT 10 ogin:--ogin: TIMEOUT 5 assword: hello2u2
+.Ed
+.Pp
+This will change the timeout to 10 seconds when it expects the login:
+prompt.
+The timeout is then changed to 5 seconds when it looks for the
+password prompt.
+.Pp
+The timeout, once changed, remains in effect until it is changed again.
+.Sh SENDING EOT
+The special reply string of
+.Dv EOT
+indicates that the chat program
+should send an
+.Dv EOT
+character to the remote.
+This is normally the
+End-of-file character sequence.
+A return character is not sent
+following the
+.Dv EOT .
+.Pp
+The
+.Dv EOT
+sequence may be embedded into the send string using the
+sequence ^D.
+.Sh GENERATING BREAK
+The special reply string of
+.Dv BREAK
+will cause a break condition
+to be sent.
+The break is a special signal on the transmitter.
+The
+normal processing on the receiver is to change the transmission rate.
+It may be used to cycle through the available transmission rates on
+the remote until you are able to receive a valid login prompt.
+.Pp
+The break sequence may be embedded into the send string using the
+\fI\\K\fR sequence.
+.Sh ESCAPE SEQUENCES
+The expect and reply strings may contain escape sequences.
+All of the
+sequences are legal in the reply string.
+Many are legal in the expect.
+Those which are not valid in the expect sequence are so indicated.
+.Bl -tag -width indent
+.It ''
+Expects or sends a null string.
+If you send a null string then it will still
+send the return character.
+This sequence may either be a pair of apostrophe
+or quote characters.
+.It \eb
+represents a backspace character.
+.It \ec
+Suppresses the newline at the end of the reply string.
+This is the only
+method to send a string without a trailing return character.
+It must
+be at the end of the send string.
+For example,
+the sequence hello\\c will simply send the characters h, e, l, l, o
+.Pq Em not valid in expect .
+.It \ed
+Delay for one second.
+The program uses sleep(1) which will delay to a
+maximum of one second
+.Pq Em not valid in expect .
+.It \eK
+Insert a
+.Dv BREAK
+.Pq Em not valid in expect .
+.It \en
+Send a newline or linefeed character.
+.It \eN
+Send a null character.
+The same sequence may be represented by \\0
+.Pq Em not valid in expect .
+.It \ep
+Pause for a fraction of a second.
+The delay is 1/10th of a second
+.Pq Em not valid in expect .
+.It \eq
+Suppress writing the string to
+.Xr syslogd 8 .
+The string ?????? is
+written to the log in its place
+.Pq Em not valid in expect .
+.It \er
+Send or expect a carriage return.
+.It \es
+Represents a space character in the string.
+This may be used when it
+is not desirable to quote the strings which contains spaces.
+The
+sequence 'HI TIM' and HI\\sTIM are the same.
+.It \et
+Send or expect a tab character.
+.It \e
+Send or expect a backslash character.
+.It \eddd
+Collapse the octal digits (ddd) into a single ASCII character and send that
+character
+.Pq Em some characters are not valid in expect .
+.It \^^C
+Substitute the sequence with the control character represented by C.
+For example, the character DC1 (17) is shown as \^^Q
+.Pq Em some characters are not valid in expect .
+.El
+.Sh TERMINATION CODES
+The
+.Nm
+program will terminate with the following completion
+codes.
+.Bl -tag -width indent
+.It 0
+The normal termination of the program.
+This indicates that the script
+was executed without error to the normal conclusion.
+.It 1
+One or more of the parameters are invalid or an expect string was too
+large for the internal buffers.
+This indicates that the program as not
+properly executed.
+.It 2
+An error occurred during the execution of the program.
+This may be due
+to a read or write operation failing for some reason or chat receiving
+a signal such as
+.Dv SIGINT .
+.It 3
+A timeout event occurred when there was an
+.Em expect
+string without
+having a "-subsend" string.
+This may mean that you did not program the
+script correctly for the condition or that some unexpected event has
+occurred and the expected string could not be found.
+.It 4
+The first string marked as an
+.Dv ABORT
+condition occurred.
+.It 5
+The second string marked as an
+.Dv ABORT
+condition occurred.
+.It 6
+The third string marked as an
+.Dv ABORT
+condition occurred.
+.It 7
+The fourth string marked as an
+.Dv ABORT
+condition occurred.
+.It ...
+The other termination codes are also strings marked as an
+.Dv ABORT
+condition.
+.El
+.Pp
+Using the termination code, it is possible to determine which event
+terminated the script.
+It is possible to decide if the string "BUSY"
+was received from the modem as opposed to "NO DIAL TONE".
+While the
+first event may be retried, the second will probably have little
+chance of succeeding during a retry.
+.Sh SEE ALSO
+Additional information about
+.Nm
+scripts may be found with UUCP
+documentation.
+The
+.Nm
+script was taken from the ideas proposed
+by the scripts used by the uucico program.
+.Pp
+.Xr syslog 3 ,
+.Xr syslogd 8
+.Sh COPYRIGHT
+The
+.Nm
+program is in public domain.
+This is not the GNU public
+license.
+If it breaks then you get to keep both pieces.
diff --git a/usr.bin/chat/chat.c b/usr.bin/chat/chat.c
new file mode 100644
index 000000000000..64dc6cba0dcf
--- /dev/null
+++ b/usr.bin/chat/chat.c
@@ -0,0 +1,1526 @@
+/*
+ * Chat -- a program for automatic session establishment (i.e. dial
+ * the phone and log in).
+ *
+ * Standard termination codes:
+ * 0 - successful completion of the script
+ * 1 - invalid argument, expect string too large, etc.
+ * 2 - error on an I/O operation or fatal error condition.
+ * 3 - timeout waiting for a simple string.
+ * 4 - the first string declared as "ABORT"
+ * 5 - the second string declared as "ABORT"
+ * 6 - ... and so on for successive ABORT strings.
+ *
+ * This software is in the public domain.
+ *
+ * -----------------
+ * added -T and -U option and \T and \U substitution to pass a phone
+ * number into chat script. Two are needed for some ISDN TA applications.
+ * Keith Dart <kdart@cisco.com>
+ *
+ *
+ * Added SAY keyword to send output to stderr.
+ * This allows to turn ECHO OFF and to output specific, user selected,
+ * text to give progress messages. This best works when stderr
+ * exists (i.e.: pppd in nodetach mode).
+ *
+ * Added HANGUP directives to allow for us to be called
+ * back. When HANGUP is set to NO, chat will not hangup at HUP signal.
+ * We rely on timeouts in that case.
+ *
+ * Added CLR_ABORT to clear previously set ABORT string. This has been
+ * dictated by the HANGUP above as "NO CARRIER" (for example) must be
+ * an ABORT condition until we know the other host is going to close
+ * the connection for call back. As soon as we have completed the
+ * first stage of the call back sequence, "NO CARRIER" is a valid, non
+ * fatal string. As soon as we got called back (probably get "CONNECT"),
+ * we should re-arm the ABORT "NO CARRIER". Hence the CLR_ABORT command.
+ * Note that CLR_ABORT packs the abort_strings[] array so that we do not
+ * have unused entries not being reclaimed.
+ *
+ * In the same vein as above, added CLR_REPORT keyword.
+ *
+ * Allow for comments. Line starting with '#' are comments and are
+ * ignored. If a '#' is to be expected as the first character, the
+ * expect string must be quoted.
+ *
+ *
+ * Francis Demierre <Francis@SwissMail.Com>
+ * Thu May 15 17:15:40 MET DST 1997
+ *
+ *
+ * Added -r "report file" switch & REPORT keyword.
+ * Robert Geer <bgeer@xmission.com>
+ *
+ * Added -s "use stderr" and -S "don't use syslog" switches.
+ * June 18, 1997
+ * Karl O. Pinc <kop@meme.com>
+ *
+ *
+ * Added -e "echo" switch & ECHO keyword
+ * Dick Streefland <dicks@tasking.nl>
+ *
+ *
+ * Considerable updates and modifications by
+ * Al Longyear <longyear@pobox.com>
+ * Paul Mackerras <paulus@cs.anu.edu.au>
+ *
+ *
+ * The original author is:
+ *
+ * Karl Fox <karl@MorningStar.Com>
+ * Morning Star Technologies, Inc.
+ * 1760 Zollinger Road
+ * Columbus, OH 43221
+ * (614)451-1883
+ *
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#define STR_LEN 1024
+
+#ifndef SIGTYPE
+#define SIGTYPE void
+#endif
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+#define MAX_ABORTS 50
+#define MAX_REPORTS 50
+#define DEFAULT_CHAT_TIMEOUT 45
+
+static int echo;
+static int verbose;
+static int to_log;
+static int to_stderr;
+static int Verbose;
+static int quiet;
+static int exit_code;
+static FILE* report_fp;
+static char *report_file;
+static char *chat_file;
+static char *phone_num;
+static char *phone_num2;
+static int timeout = DEFAULT_CHAT_TIMEOUT;
+
+static char blank[] = "";
+
+static int have_tty_parameters;
+
+#define term_parms struct termios
+#define get_term_param(param) tcgetattr(0, param)
+#define set_term_param(param) tcsetattr(0, TCSANOW, param)
+static struct termios saved_tty_parameters;
+
+static char *abort_string[MAX_ABORTS], *fail_reason, fail_buffer[50];
+static int n_aborts, abort_next, timeout_next, echo_next;
+static int clear_abort_next;
+
+static char *report_string[MAX_REPORTS];
+static char report_buffer[50];
+static int n_reports, report_next, report_gathering;
+static int clear_report_next;
+
+static int say_next, hup_next;
+
+void *dup_mem(void *b, size_t c);
+void *copy_of(char *s);
+static void usage(void) __dead2;
+void chat_logf(const char *fmt, ...);
+void fatal(int code, const char *fmt, ...);
+SIGTYPE sigalrm(int signo);
+SIGTYPE sigint(int signo);
+SIGTYPE sigterm(int signo);
+SIGTYPE sighup(int signo);
+void init(void);
+void set_tty_parameters(void);
+void echo_stderr(int);
+void break_sequence(void);
+void terminate(int status);
+void do_file(char *chatfile);
+int get_string(char *string);
+int put_string(char *s);
+int write_char(int c);
+int put_char(int c);
+int get_char(void);
+void chat_send(char *s);
+char *character(int c);
+void chat_expect(char *s);
+char *clean(char *s, int sending);
+void pack_array(char **array, int end);
+char *expect_strtok(char *, const char *);
+int vfmtmsg(char *, int, const char *, va_list); /* vsprintf++ */
+
+void *
+dup_mem(void *b, size_t c)
+{
+ void *ans = malloc (c);
+ if (!ans)
+ fatal(2, "memory error!");
+
+ memcpy (ans, b, c);
+ return ans;
+}
+
+void *
+copy_of(char *s)
+{
+ return dup_mem (s, strlen (s) + 1);
+}
+
+/*
+ * chat [-esSvV] [-f chat-file] [-r report-file] [-t timeout]
+ * [-T phone-number] [-U phone-number2] [chat-script]
+ * where chat-script has the form:
+ * [...[[expect[-send[-expect...]] send expect[-send[-expect]] ...]]]
+ *
+ * Perform a UUCP-dialer-like chat script on stdin and stdout.
+ */
+int
+main(int argc, char *argv[])
+{
+ int option;
+
+ tzset();
+
+ while ((option = getopt(argc, argv, "ef:r:sSt:T:U:vV")) != -1) {
+ switch (option) {
+ case 'e':
+ ++echo;
+ break;
+
+ case 'f':
+ if (chat_file != NULL)
+ free(chat_file);
+ chat_file = copy_of(optarg);
+ break;
+
+ case 'r':
+ if (report_fp != NULL)
+ fclose(report_fp);
+ if (report_file != NULL)
+ free(report_file);
+ report_file = copy_of(optarg);
+ report_fp = fopen(report_file, "a");
+ if (report_fp != NULL) {
+ if (verbose)
+ fprintf(report_fp, "Opening \"%s\"...\n", report_file);
+ } else
+ fatal(2, "cannot open \"%s\" for appending", report_file);
+ break;
+
+ case 's':
+ ++to_stderr;
+ break;
+
+ case 'S':
+ to_log = 0;
+ break;
+
+ case 't':
+ timeout = atoi(optarg);
+ break;
+
+ case 'T':
+ if (phone_num != NULL)
+ free(phone_num);
+ phone_num = copy_of(optarg);
+ break;
+
+ case 'U':
+ if (phone_num2 != NULL)
+ free(phone_num2);
+ phone_num2 = copy_of(optarg);
+ break;
+
+ case 'v':
+ ++verbose;
+ break;
+
+ case 'V':
+ ++Verbose;
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+/*
+ * Default the report file to the stderr location
+ */
+ if (report_fp == NULL)
+ report_fp = stderr;
+
+ if (to_log) {
+ openlog("chat", LOG_PID | LOG_NDELAY, LOG_LOCAL2);
+
+ if (verbose)
+ setlogmask(LOG_UPTO(LOG_INFO));
+ else
+ setlogmask(LOG_UPTO(LOG_WARNING));
+ }
+
+ if (chat_file != NULL) {
+ if (*argv != NULL)
+ usage();
+ else {
+ init();
+ do_file(chat_file);
+ }
+ } else {
+ init();
+ while (*argv != NULL && argc > 0) {
+ chat_expect(*argv);
+ argv++;
+ argc--;
+
+ if (*argv != NULL && argc > 0) {
+ chat_send(*argv);
+ argv++;
+ argc--;
+ }
+ }
+ }
+
+ terminate(0);
+ return 0;
+}
+
+/*
+ * Process a chat script when read from a file.
+ */
+
+void
+do_file(char *chatfile)
+{
+ int linect, sendflg;
+ char *sp, *arg, quote;
+ char buf [STR_LEN];
+ FILE *cfp;
+
+ cfp = fopen (chatfile, "r");
+ if (cfp == NULL)
+ fatal(1, "%s -- open failed: %m", chatfile);
+
+ linect = 0;
+ sendflg = 0;
+
+ while (fgets(buf, STR_LEN, cfp) != NULL) {
+ sp = strchr (buf, '\n');
+ if (sp)
+ *sp = '\0';
+
+ linect++;
+ sp = buf;
+
+ /* lines starting with '#' are comments. If a real '#'
+ is to be expected, it should be quoted .... */
+ if ( *sp == '#' )
+ continue;
+
+ while (*sp != '\0') {
+ if (*sp == ' ' || *sp == '\t') {
+ ++sp;
+ continue;
+ }
+
+ if (*sp == '"' || *sp == '\'') {
+ quote = *sp++;
+ arg = sp;
+ while (*sp != quote) {
+ if (*sp == '\0')
+ fatal(1, "unterminated quote (line %d)", linect);
+
+ if (*sp++ == '\\') {
+ if (*sp != '\0')
+ ++sp;
+ }
+ }
+ }
+ else {
+ arg = sp;
+ while (*sp != '\0' && *sp != ' ' && *sp != '\t')
+ ++sp;
+ }
+
+ if (*sp != '\0')
+ *sp++ = '\0';
+
+ if (sendflg)
+ chat_send (arg);
+ else
+ chat_expect (arg);
+ sendflg = !sendflg;
+ }
+ }
+ fclose (cfp);
+}
+
+/*
+ * We got an error parsing the command line.
+ */
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: chat [-esSvV] [-f chat-file] [-r report-file] [-t timeout]\n"
+ " [-T phone-number] [-U phone-number2] [chat-script]\n"
+ "where chat-script has the form:\n"
+ " [...[[expect[-send[-expect...]] send expect[-send[-expect]] ...]]]\n");
+ exit(1);
+}
+
+/*
+ * Send a message to syslog and/or stderr.
+ */
+void
+chat_logf(const char *fmt, ...)
+{
+ char line[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vfmtmsg(line, sizeof(line), fmt, args);
+ va_end(args);
+ if (to_log)
+ syslog(LOG_INFO, "%s", line);
+ if (to_stderr)
+ fprintf(stderr, "%s\n", line);
+}
+
+/*
+ * Print an error message and terminate.
+ */
+
+void
+fatal(int code, const char *fmt, ...)
+{
+ char line[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vfmtmsg(line, sizeof(line), fmt, args);
+ va_end(args);
+ if (to_log)
+ syslog(LOG_ERR, "%s", line);
+ if (to_stderr)
+ fprintf(stderr, "%s\n", line);
+ terminate(code);
+}
+
+static int alarmed;
+
+SIGTYPE sigalrm(int signo __unused)
+{
+ int flags;
+
+ alarm(1);
+ alarmed = 1; /* Reset alarm to avoid race window */
+ signal(SIGALRM, sigalrm); /* that can cause hanging in read() */
+
+ if ((flags = fcntl(0, F_GETFL, 0)) == -1)
+ fatal(2, "Can't get file mode flags on stdin: %m");
+
+ if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1)
+ fatal(2, "Can't set file mode flags on stdin: %m");
+
+ if (verbose)
+ chat_logf("alarm");
+}
+
+SIGTYPE sigint(int signo __unused)
+{
+ fatal(2, "SIGINT");
+}
+
+SIGTYPE sigterm(int signo __unused)
+{
+ fatal(2, "SIGTERM");
+}
+
+SIGTYPE sighup(int signo __unused)
+{
+ fatal(2, "SIGHUP");
+}
+
+void init(void)
+{
+ signal(SIGINT, sigint);
+ signal(SIGTERM, sigterm);
+ signal(SIGHUP, sighup);
+
+ set_tty_parameters();
+ signal(SIGALRM, sigalrm);
+ alarm(0);
+ alarmed = 0;
+}
+
+void set_tty_parameters(void)
+{
+#if defined(get_term_param)
+ term_parms t;
+
+ if (get_term_param (&t) < 0)
+ fatal(2, "Can't get terminal parameters: %m");
+
+ saved_tty_parameters = t;
+ have_tty_parameters = 1;
+
+ t.c_iflag |= IGNBRK | ISTRIP | IGNPAR;
+ t.c_oflag = 0;
+ t.c_lflag = 0;
+ t.c_cc[VERASE] =
+ t.c_cc[VKILL] = 0;
+ t.c_cc[VMIN] = 1;
+ t.c_cc[VTIME] = 0;
+
+ if (set_term_param (&t) < 0)
+ fatal(2, "Can't set terminal parameters: %m");
+#endif
+}
+
+void break_sequence(void)
+{
+ tcsendbreak (0, 0);
+}
+
+void terminate(int status)
+{
+ echo_stderr(-1);
+ if (report_file != (char *) 0 && report_fp != (FILE *) NULL) {
+/*
+ * Allow the last of the report string to be gathered before we terminate.
+ */
+ if (report_gathering) {
+ int c;
+ size_t rep_len;
+
+ rep_len = strlen(report_buffer);
+ while (rep_len + 1 < sizeof(report_buffer)) {
+ alarm(1);
+ c = get_char();
+ alarm(0);
+ if (c < 0 || iscntrl(c))
+ break;
+ report_buffer[rep_len] = c;
+ ++rep_len;
+ }
+ report_buffer[rep_len] = 0;
+ fprintf (report_fp, "chat: %s\n", report_buffer);
+ }
+ if (verbose)
+ fprintf (report_fp, "Closing \"%s\".\n", report_file);
+ fclose (report_fp);
+ report_fp = (FILE *) NULL;
+ }
+
+#if defined(get_term_param)
+ if (have_tty_parameters) {
+ if (set_term_param (&saved_tty_parameters) < 0)
+ fatal(2, "Can't restore terminal parameters: %m");
+ }
+#endif
+
+ exit(status);
+}
+
+/*
+ * 'Clean up' this string.
+ */
+char *
+clean(char *s, int sending)
+{
+ char temp[STR_LEN], cur_chr;
+ char *s1, *phchar;
+ int add_return = sending;
+#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
+
+ s1 = temp;
+ /* Don't overflow buffer, leave room for chars we append later */
+ while (*s && s1 - temp < (off_t)(sizeof(temp) - 2 - add_return)) {
+ cur_chr = *s++;
+ if (cur_chr == '^') {
+ cur_chr = *s++;
+ if (cur_chr == '\0') {
+ *s1++ = '^';
+ break;
+ }
+ cur_chr &= 0x1F;
+ if (cur_chr != 0) {
+ *s1++ = cur_chr;
+ }
+ continue;
+ }
+
+ if (cur_chr != '\\') {
+ *s1++ = cur_chr;
+ continue;
+ }
+
+ cur_chr = *s++;
+ if (cur_chr == '\0') {
+ if (sending) {
+ *s1++ = '\\';
+ *s1++ = '\\';
+ }
+ break;
+ }
+
+ switch (cur_chr) {
+ case 'b':
+ *s1++ = '\b';
+ break;
+
+ case 'c':
+ if (sending && *s == '\0')
+ add_return = 0;
+ else
+ *s1++ = cur_chr;
+ break;
+
+ case '\\':
+ case 'K':
+ case 'p':
+ case 'd':
+ if (sending)
+ *s1++ = '\\';
+
+ *s1++ = cur_chr;
+ break;
+
+ case 'T':
+ if (sending && phone_num) {
+ for ( phchar = phone_num; *phchar != '\0'; phchar++)
+ *s1++ = *phchar;
+ }
+ else {
+ *s1++ = '\\';
+ *s1++ = 'T';
+ }
+ break;
+
+ case 'U':
+ if (sending && phone_num2) {
+ for ( phchar = phone_num2; *phchar != '\0'; phchar++)
+ *s1++ = *phchar;
+ }
+ else {
+ *s1++ = '\\';
+ *s1++ = 'U';
+ }
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ case 'r':
+ *s1++ = '\r';
+ break;
+
+ case 'n':
+ *s1++ = '\n';
+ break;
+
+ case 's':
+ *s1++ = ' ';
+ break;
+
+ case 't':
+ *s1++ = '\t';
+ break;
+
+ case 'N':
+ if (sending) {
+ *s1++ = '\\';
+ *s1++ = '\0';
+ }
+ else
+ *s1++ = 'N';
+ break;
+
+ default:
+ if (isoctal (cur_chr)) {
+ cur_chr &= 0x07;
+ if (isoctal (*s)) {
+ cur_chr <<= 3;
+ cur_chr |= *s++ - '0';
+ if (isoctal (*s)) {
+ cur_chr <<= 3;
+ cur_chr |= *s++ - '0';
+ }
+ }
+
+ if (cur_chr != 0 || sending) {
+ if (sending && (cur_chr == '\\' || cur_chr == 0))
+ *s1++ = '\\';
+ *s1++ = cur_chr;
+ }
+ break;
+ }
+
+ if (sending)
+ *s1++ = '\\';
+ *s1++ = cur_chr;
+ break;
+ }
+ }
+
+ if (add_return)
+ *s1++ = '\r';
+
+ *s1++ = '\0'; /* guarantee closure */
+ *s1++ = '\0'; /* terminate the string */
+ return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
+}
+
+/*
+ * A modified version of 'strtok'. This version skips \ sequences.
+ */
+
+char *
+expect_strtok (char *s, const char *term)
+{
+ static char *str = blank;
+ int escape_flag = 0;
+ char *result;
+
+/*
+ * If a string was specified then do initial processing.
+ */
+ if (s)
+ str = s;
+
+/*
+ * If this is the escape flag then reset it and ignore the character.
+ */
+ if (*str)
+ result = str;
+ else
+ result = (char *) 0;
+
+ while (*str) {
+ if (escape_flag) {
+ escape_flag = 0;
+ ++str;
+ continue;
+ }
+
+ if (*str == '\\') {
+ ++str;
+ escape_flag = 1;
+ continue;
+ }
+
+/*
+ * If this is not in the termination string, continue.
+ */
+ if (strchr (term, *str) == (char *) 0) {
+ ++str;
+ continue;
+ }
+
+/*
+ * This is the terminator. Mark the end of the string and stop.
+ */
+ *str++ = '\0';
+ break;
+ }
+ return (result);
+}
+
+/*
+ * Process the expect string
+ */
+
+void
+chat_expect(char *s)
+{
+ char *expect;
+ char *reply;
+
+ if (strcmp(s, "HANGUP") == 0) {
+ ++hup_next;
+ return;
+ }
+
+ if (strcmp(s, "ABORT") == 0) {
+ ++abort_next;
+ return;
+ }
+
+ if (strcmp(s, "CLR_ABORT") == 0) {
+ ++clear_abort_next;
+ return;
+ }
+
+ if (strcmp(s, "REPORT") == 0) {
+ ++report_next;
+ return;
+ }
+
+ if (strcmp(s, "CLR_REPORT") == 0) {
+ ++clear_report_next;
+ return;
+ }
+
+ if (strcmp(s, "TIMEOUT") == 0) {
+ ++timeout_next;
+ return;
+ }
+
+ if (strcmp(s, "ECHO") == 0) {
+ ++echo_next;
+ return;
+ }
+
+ if (strcmp(s, "SAY") == 0) {
+ ++say_next;
+ return;
+ }
+
+/*
+ * Fetch the expect and reply string.
+ */
+ for (;;) {
+ expect = expect_strtok (s, "-");
+ s = (char *) 0;
+
+ if (expect == (char *) 0)
+ return;
+
+ reply = expect_strtok (s, "-");
+
+/*
+ * Handle the expect string. If successful then exit.
+ */
+ if (get_string (expect))
+ return;
+
+/*
+ * If there is a sub-reply string then send it. Otherwise any condition
+ * is terminal.
+ */
+ if (reply == (char *) 0 || exit_code != 3)
+ break;
+
+ chat_send (reply);
+ }
+
+/*
+ * The expectation did not occur. This is terminal.
+ */
+ if (fail_reason)
+ chat_logf("Failed (%s)", fail_reason);
+ else
+ chat_logf("Failed");
+ terminate(exit_code);
+}
+
+/*
+ * Translate the input character to the appropriate string for printing
+ * the data.
+ */
+
+char *
+character(int c)
+{
+ static char string[10];
+ const char *meta;
+
+ meta = (c & 0x80) ? "M-" : "";
+ c &= 0x7F;
+
+ if (c < 32)
+ sprintf(string, "%s^%c", meta, (int)c + '@');
+ else if (c == 127)
+ sprintf(string, "%s^?", meta);
+ else
+ sprintf(string, "%s%c", meta, c);
+
+ return (string);
+}
+
+/*
+ * process the reply string
+ */
+void
+chat_send(char *s)
+{
+ if (say_next) {
+ say_next = 0;
+ s = clean(s,0);
+ write(STDERR_FILENO, s, strlen(s));
+ free(s);
+ return;
+ }
+
+ if (hup_next) {
+ hup_next = 0;
+ if (strcmp(s, "OFF") == 0)
+ signal(SIGHUP, SIG_IGN);
+ else
+ signal(SIGHUP, sighup);
+ return;
+ }
+
+ if (echo_next) {
+ echo_next = 0;
+ echo = (strcmp(s, "ON") == 0);
+ return;
+ }
+
+ if (abort_next) {
+ char *s1;
+
+ abort_next = 0;
+
+ if (n_aborts >= MAX_ABORTS)
+ fatal(2, "Too many ABORT strings");
+
+ s1 = clean(s, 0);
+
+ if (strlen(s1) > strlen(s)
+ || strlen(s1) + 1 > sizeof(fail_buffer))
+ fatal(1, "Illegal or too-long ABORT string ('%v')", s);
+
+ abort_string[n_aborts++] = s1;
+
+ if (verbose)
+ chat_logf("abort on (%v)", s);
+ return;
+ }
+
+ if (clear_abort_next) {
+ char *s1;
+ int i;
+ int old_max;
+ int pack = 0;
+
+ clear_abort_next = 0;
+
+ s1 = clean(s, 0);
+
+ if (strlen(s1) > strlen(s)
+ || strlen(s1) + 1 > sizeof(fail_buffer))
+ fatal(1, "Illegal or too-long CLR_ABORT string ('%v')", s);
+
+ old_max = n_aborts;
+ for (i=0; i < n_aborts; i++) {
+ if ( strcmp(s1,abort_string[i]) == 0 ) {
+ free(abort_string[i]);
+ abort_string[i] = NULL;
+ pack++;
+ n_aborts--;
+ if (verbose)
+ chat_logf("clear abort on (%v)", s);
+ }
+ }
+ free(s1);
+ if (pack)
+ pack_array(abort_string,old_max);
+ return;
+ }
+
+ if (report_next) {
+ char *s1;
+
+ report_next = 0;
+ if (n_reports >= MAX_REPORTS)
+ fatal(2, "Too many REPORT strings");
+
+ s1 = clean(s, 0);
+
+ if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
+ fatal(1, "Illegal or too-long REPORT string ('%v')", s);
+
+ report_string[n_reports++] = s1;
+
+ if (verbose)
+ chat_logf("report (%v)", s);
+ return;
+ }
+
+ if (clear_report_next) {
+ char *s1;
+ int i;
+ int old_max;
+ int pack = 0;
+
+ clear_report_next = 0;
+
+ s1 = clean(s, 0);
+
+ if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
+ fatal(1, "Illegal or too-long REPORT string ('%v')", s);
+
+ old_max = n_reports;
+ for (i=0; i < n_reports; i++) {
+ if ( strcmp(s1,report_string[i]) == 0 ) {
+ free(report_string[i]);
+ report_string[i] = NULL;
+ pack++;
+ n_reports--;
+ if (verbose)
+ chat_logf("clear report (%v)", s);
+ }
+ }
+ free(s1);
+ if (pack)
+ pack_array(report_string,old_max);
+
+ return;
+ }
+
+ if (timeout_next) {
+ timeout_next = 0;
+ timeout = atoi(s);
+
+ if (timeout <= 0)
+ timeout = DEFAULT_CHAT_TIMEOUT;
+
+ if (verbose)
+ chat_logf("timeout set to %d seconds", timeout);
+
+ return;
+ }
+
+ if (strcmp(s, "EOT") == 0)
+ s = strdup("^D\\c");
+ else if (strcmp(s, "BREAK") == 0)
+ s = strdup("\\K\\c");
+
+ if (!put_string(s))
+ fatal(1, "Failed");
+}
+
+int
+get_char(void)
+{
+ int status;
+ char c;
+
+ status = read(STDIN_FILENO, &c, 1);
+
+ switch (status) {
+ case 1:
+ return ((int)c & 0x7F);
+
+ default:
+ chat_logf("warning: read() on stdin returned %d", status);
+
+ case -1:
+ if ((status = fcntl(0, F_GETFL, 0)) == -1)
+ fatal(2, "Can't get file mode flags on stdin: %m");
+
+ if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
+ fatal(2, "Can't set file mode flags on stdin: %m");
+
+ return (-1);
+ }
+}
+
+int put_char(int c)
+{
+ int status;
+ char ch = c;
+
+ usleep(10000); /* inter-character typing delay (?) */
+
+ status = write(STDOUT_FILENO, &ch, 1);
+
+ switch (status) {
+ case 1:
+ return (0);
+
+ default:
+ chat_logf("warning: write() on stdout returned %d", status);
+
+ case -1:
+ if ((status = fcntl(0, F_GETFL, 0)) == -1)
+ fatal(2, "Can't get file mode flags on stdin, %m");
+
+ if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
+ fatal(2, "Can't set file mode flags on stdin: %m");
+
+ return (-1);
+ }
+}
+
+int
+write_char(int c)
+{
+ if (alarmed || put_char(c) < 0) {
+ alarm(0);
+ alarmed = 0;
+
+ if (verbose) {
+ if (errno == EINTR || errno == EWOULDBLOCK)
+ chat_logf(" -- write timed out");
+ else
+ chat_logf(" -- write failed: %m");
+ }
+ return (0);
+ }
+ return (1);
+}
+
+int
+put_string(char *s)
+{
+ quiet = 0;
+ s = clean(s, 1);
+
+ if (verbose)
+ chat_logf("send (%v)", quiet ? "??????" : s);
+
+ alarm(timeout); alarmed = 0;
+
+ while (*s) {
+ char c = *s++;
+
+ if (c != '\\') {
+ if (!write_char (c))
+ return 0;
+ continue;
+ }
+
+ c = *s++;
+ switch (c) {
+ case 'd':
+ sleep(1);
+ break;
+
+ case 'K':
+ break_sequence();
+ break;
+
+ case 'p':
+ usleep(10000); /* 1/100th of a second (arg is microseconds) */
+ break;
+
+ default:
+ if (!write_char (c))
+ return 0;
+ break;
+ }
+ }
+
+ alarm(0);
+ alarmed = 0;
+ return (1);
+}
+
+/*
+ * Echo a character to stderr.
+ * When called with -1, a '\n' character is generated when
+ * the cursor is not at the beginning of a line.
+ */
+void
+echo_stderr(int n)
+{
+ static int need_lf;
+ char *s;
+
+ switch (n) {
+ case '\r': /* ignore '\r' */
+ break;
+ case -1:
+ if (need_lf == 0)
+ break;
+ /* FALLTHROUGH */
+ case '\n':
+ write(STDERR_FILENO, "\n", 1);
+ need_lf = 0;
+ break;
+ default:
+ s = character(n);
+ write(STDERR_FILENO, s, strlen(s));
+ need_lf = 1;
+ break;
+ }
+}
+
+/*
+ * 'Wait for' this string to appear on this file descriptor.
+ */
+int
+get_string(char *string)
+{
+ char temp[STR_LEN];
+ int c;
+ size_t len, minlen;
+ char *s = temp, *end = s + STR_LEN;
+ char *logged = temp;
+
+ fail_reason = (char *)0;
+
+ if (strlen(string) > STR_LEN) {
+ chat_logf("expect string is too long");
+ exit_code = 1;
+ return 0;
+ }
+
+ string = clean(string, 0);
+ len = strlen(string);
+ minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
+
+ if (verbose)
+ chat_logf("expect (%v)", string);
+
+ if (len == 0) {
+ if (verbose)
+ chat_logf("got it");
+ return (1);
+ }
+
+ alarm(timeout);
+ alarmed = 0;
+
+ while ( ! alarmed && (c = get_char()) >= 0) {
+ int n, abort_len, report_len;
+
+ if (echo)
+ echo_stderr(c);
+ if (verbose && c == '\n') {
+ if (s == logged)
+ chat_logf(""); /* blank line */
+ else
+ chat_logf("%0.*v", s - logged, logged);
+ logged = s + 1;
+ }
+
+ *s++ = c;
+
+ if (verbose && s >= logged + 80) {
+ chat_logf("%0.*v", s - logged, logged);
+ logged = s;
+ }
+
+ if (Verbose) {
+ if (c == '\n')
+ fputc( '\n', stderr );
+ else if (c != '\r')
+ fprintf( stderr, "%s", character(c) );
+ }
+
+ if (!report_gathering) {
+ for (n = 0; n < n_reports; ++n) {
+ if ((report_string[n] != (char*) NULL) &&
+ s - temp >= (report_len = strlen(report_string[n])) &&
+ strncmp(s - report_len, report_string[n], report_len) == 0) {
+ time_t time_now = time ((time_t*) NULL);
+ struct tm* tm_now = localtime (&time_now);
+
+ strftime (report_buffer, 20, "%b %d %H:%M:%S ", tm_now);
+ strcat (report_buffer, report_string[n]);
+
+ report_string[n] = (char *) NULL;
+ report_gathering = 1;
+ break;
+ }
+ }
+ }
+ else {
+ if (!iscntrl (c)) {
+ int rep_len = strlen (report_buffer);
+ report_buffer[rep_len] = c;
+ report_buffer[rep_len + 1] = '\0';
+ }
+ else {
+ report_gathering = 0;
+ fprintf (report_fp, "chat: %s\n", report_buffer);
+ }
+ }
+
+ if ((size_t)(s - temp) >= len &&
+ c == string[len - 1] &&
+ strncmp(s - len, string, len) == 0) {
+ if (verbose) {
+ if (s > logged)
+ chat_logf("%0.*v", s - logged, logged);
+ chat_logf(" -- got it\n");
+ }
+
+ alarm(0);
+ alarmed = 0;
+ return (1);
+ }
+
+ for (n = 0; n < n_aborts; ++n) {
+ if (s - temp >= (abort_len = strlen(abort_string[n])) &&
+ strncmp(s - abort_len, abort_string[n], abort_len) == 0) {
+ if (verbose) {
+ if (s > logged)
+ chat_logf("%0.*v", s - logged, logged);
+ chat_logf(" -- failed");
+ }
+
+ alarm(0);
+ alarmed = 0;
+ exit_code = n + 4;
+ strcpy(fail_reason = fail_buffer, abort_string[n]);
+ return (0);
+ }
+ }
+
+ if (s >= end) {
+ if (logged < s - minlen) {
+ chat_logf("%0.*v", s - logged, logged);
+ logged = s;
+ }
+ s -= minlen;
+ memmove(temp, s, minlen);
+ logged = temp + (logged - s);
+ s = temp + minlen;
+ }
+
+ if (alarmed && verbose)
+ chat_logf("warning: alarm synchronization problem");
+ }
+
+ alarm(0);
+
+ exit_code = 3;
+ alarmed = 0;
+ return (0);
+}
+
+void
+pack_array(char **array, int end)
+{
+ int i, j;
+
+ for (i = 0; i < end; i++) {
+ if (array[i] == NULL) {
+ for (j = i+1; j < end; ++j)
+ if (array[j] != NULL)
+ array[i++] = array[j];
+ for (; i < end; ++i)
+ array[i] = NULL;
+ break;
+ }
+ }
+}
+
+/*
+ * vfmtmsg - format a message into a buffer. Like vsprintf except we
+ * also specify the length of the output buffer, and we handle the
+ * %m (error message) format.
+ * Doesn't do floating-point formats.
+ * Returns the number of chars put into buf.
+ */
+#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
+
+int
+vfmtmsg(char *buf, int buflen, const char *fmt, va_list args)
+{
+ int c, i, n;
+ int width, prec, fillch;
+ int base, len, neg, quoted;
+ unsigned long val = 0;
+ char *str, *buf0;
+ const char *f;
+ unsigned char *p;
+ char num[32];
+ static char hexchars[] = "0123456789abcdef";
+
+ buf0 = buf;
+ --buflen;
+ while (buflen > 0) {
+ for (f = fmt; *f != '%' && *f != 0; ++f)
+ ;
+ if (f > fmt) {
+ len = f - fmt;
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, fmt, len);
+ buf += len;
+ buflen -= len;
+ fmt = f;
+ }
+ if (*fmt == 0)
+ break;
+ c = *++fmt;
+ width = prec = 0;
+ fillch = ' ';
+ if (c == '0') {
+ fillch = '0';
+ c = *++fmt;
+ }
+ if (c == '*') {
+ width = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (isdigit(c)) {
+ width = width * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ if (c == '.') {
+ c = *++fmt;
+ if (c == '*') {
+ prec = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (isdigit(c)) {
+ prec = prec * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ }
+ str = NULL;
+ base = 0;
+ neg = 0;
+ ++fmt;
+ switch (c) {
+ case 'd':
+ i = va_arg(args, int);
+ if (i < 0) {
+ neg = 1;
+ val = -i;
+ } else
+ val = i;
+ base = 10;
+ break;
+ case 'o':
+ val = va_arg(args, unsigned int);
+ base = 8;
+ break;
+ case 'x':
+ val = va_arg(args, unsigned int);
+ base = 16;
+ break;
+ case 'p':
+ val = (unsigned long) va_arg(args, void *);
+ base = 16;
+ neg = 2;
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ break;
+ case 'c':
+ num[0] = va_arg(args, int);
+ num[1] = 0;
+ str = num;
+ break;
+ case 'm':
+ str = strerror(errno);
+ break;
+ case 'v': /* "visible" string */
+ case 'q': /* quoted string */
+ quoted = c == 'q';
+ p = va_arg(args, unsigned char *);
+ if (fillch == '0' && prec > 0) {
+ n = prec;
+ } else {
+ n = strlen((char *)p);
+ if (prec > 0 && prec < n)
+ n = prec;
+ }
+ while (n > 0 && buflen > 0) {
+ c = *p++;
+ --n;
+ if (!quoted && c >= 0x80) {
+ OUTCHAR('M');
+ OUTCHAR('-');
+ c -= 0x80;
+ }
+ if (quoted && (c == '"' || c == '\\'))
+ OUTCHAR('\\');
+ if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
+ if (quoted) {
+ OUTCHAR('\\');
+ switch (c) {
+ case '\t': OUTCHAR('t'); break;
+ case '\n': OUTCHAR('n'); break;
+ case '\b': OUTCHAR('b'); break;
+ case '\f': OUTCHAR('f'); break;
+ default:
+ OUTCHAR('x');
+ OUTCHAR(hexchars[c >> 4]);
+ OUTCHAR(hexchars[c & 0xf]);
+ }
+ } else {
+ if (c == '\t')
+ OUTCHAR(c);
+ else {
+ OUTCHAR('^');
+ OUTCHAR(c ^ 0x40);
+ }
+ }
+ } else
+ OUTCHAR(c);
+ }
+ continue;
+ default:
+ *buf++ = '%';
+ if (c != '%')
+ --fmt; /* so %z outputs %z etc. */
+ --buflen;
+ continue;
+ }
+ if (base != 0) {
+ str = num + sizeof(num);
+ *--str = 0;
+ while (str > num + neg) {
+ *--str = hexchars[val % base];
+ val = val / base;
+ if (--prec <= 0 && val == 0)
+ break;
+ }
+ switch (neg) {
+ case 1:
+ *--str = '-';
+ break;
+ case 2:
+ *--str = 'x';
+ *--str = '0';
+ break;
+ }
+ len = num + sizeof(num) - 1 - str;
+ } else {
+ len = strlen(str);
+ if (prec > 0 && len > prec)
+ len = prec;
+ }
+ if (width > 0) {
+ if (width > buflen)
+ width = buflen;
+ if ((n = width - len) > 0) {
+ buflen -= n;
+ for (; n > 0; --n)
+ *buf++ = fillch;
+ }
+ }
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, str, len);
+ buf += len;
+ buflen -= len;
+ }
+ *buf = 0;
+ return buf - buf0;
+}
diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile
new file mode 100644
index 000000000000..0bf39deeab88
--- /dev/null
+++ b/usr.bin/chpass/Makefile
@@ -0,0 +1,42 @@
+.include <src.opts.mk>
+
+.PATH: ${SRCTOP}/lib/libc/gen
+
+PROG= chpass
+SRCS= chpass.c edit.c field.c pw_scan.c table.c util.c
+BINOWN= root
+BINMODE=4555
+PRECIOUSPROG=
+.if ${MK_NIS} != "no"
+CFLAGS+= -DYP
+.endif
+#Some people need this, uncomment to activate
+#CFLAGS+=-DRESTRICT_FULLNAME_CHANGE
+CFLAGS+=-I${SRCTOP}/lib/libc/gen -I.
+
+LIBADD= crypt util
+.if ${MK_NIS} != "no"
+LIBADD+= ypclnt
+.endif
+
+SYMLINKS= chpass ${BINDIR}/chfn
+SYMLINKS+= chpass ${BINDIR}/chsh
+.if ${MK_NIS} != "no"
+SYMLINKS+= chpass ${BINDIR}/ypchfn
+SYMLINKS+= chpass ${BINDIR}/ypchpass
+SYMLINKS+= chpass ${BINDIR}/ypchsh
+.endif
+
+MLINKS= chpass.1 chfn.1 chpass.1 chsh.1
+.if ${MK_NIS} != "no"
+MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1
+.endif
+
+beforeinstall:
+.for i in chpass chfn chsh ypchpass ypchfn ypchsh
+.if exists(${DESTDIR}${BINDIR}/$i)
+ -chflags noschg ${DESTDIR}${BINDIR}/$i
+.endif
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/chpass/Makefile.depend b/usr.bin/chpass/Makefile.depend
new file mode 100644
index 000000000000..1a673c53cbc6
--- /dev/null
+++ b/usr.bin/chpass/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libcrypt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/chpass/Makefile.depend.options b/usr.bin/chpass/Makefile.depend.options
new file mode 100644
index 000000000000..a43cdcfaffb4
--- /dev/null
+++ b/usr.bin/chpass/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= NIS
+
+DIRDEPS.NIS.yes= lib/libypclnt
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/chpass/chpass.1 b/usr.bin/chpass/chpass.1
new file mode 100644
index 000000000000..0891f3f28c92
--- /dev/null
+++ b/usr.bin/chpass/chpass.1
@@ -0,0 +1,488 @@
+.\" Copyright (c) 1988, 1990, 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.
+.\"
+.Dd May 25, 2021
+.Dt CHPASS 1
+.Os
+.Sh NAME
+.Nm chpass ,
+.Nm chfn ,
+.Nm chsh ,
+.Nm ypchpass ,
+.Nm ypchfn ,
+.Nm ypchsh
+.Nd add or change user database information
+.Sh SYNOPSIS
+.Nm chpass
+.Op Fl a Ar list
+.Op Fl e Ar expiretime
+.Op Fl p Ar encpass
+.Op Fl s Ar newshell
+.Op user
+.Nm ypchpass
+.Op Fl loy
+.Op Fl a Ar list
+.Op Fl d Ar domain
+.Op Fl e Ar expiretime
+.Op Fl h Ar host
+.Op Fl p Ar encpass
+.Op Fl s Ar newshell
+.Op user
+.Sh DESCRIPTION
+The
+.Nm
+utility
+allows editing of the user database information associated
+with
+.Ar user
+or, by default, the current user.
+.Pp
+The
+.Nm chfn ,
+.Nm chsh ,
+.Nm ypchpass ,
+.Nm ypchfn
+and
+.Nm ypchsh
+utilities behave identically to
+.Nm .
+(There is only one program.)
+.Pp
+The information is formatted and supplied to an editor for changes.
+.Pp
+Only the information that the user is allowed to change is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width "-e expiretime"
+.It Fl a Ar list
+The super-user is allowed to directly supply a user database
+entry, in the format specified by
+.Xr passwd 5 ,
+as an argument.
+This argument must be a colon
+.Pq Dq \&:
+separated list of all the
+user database fields, although they may be empty.
+.It Fl e Ar expiretime
+Change the account expire time.
+This option is used to set the expire time
+from a script as if it was done in the interactive editor.
+.It Fl p Ar encpass
+The super-user is allowed to directly supply an encrypted password field,
+in the format used by
+.Xr crypt 3 ,
+as an argument.
+.It Fl s Ar newshell
+Attempt to change the user's shell to
+.Ar newshell .
+.El
+.Pp
+Possible display items are as follows:
+.Pp
+.Bl -tag -width "Other Information:" -compact -offset indent
+.It Login:
+user's login name
+.It Password:
+user's encrypted password
+.It Uid:
+user's login
+.It Gid:
+user's login group
+.It Class:
+user's general classification
+.It Change:
+password change time
+.It Expire:
+account expiration time
+.It Full Name:
+user's real name
+.It Office Location:
+user's office location (1)
+.It Office Phone:
+user's office phone (1)
+.It Home Phone:
+user's home phone (1)
+.It Other Information:
+any locally defined parameters for user (1)
+.It Home Directory:
+user's home directory
+.It Shell:
+user's login shell
+.Pp
+.It NOTE(1) -
+In the actual master.passwd file, these fields are comma-delimited
+fields embedded in the FullName field.
+.El
+.Pp
+The
+.Ar login
+field is the user name used to access the computer account.
+.Pp
+The
+.Ar password
+field contains the encrypted form of the user's password.
+.Pp
+The
+.Ar uid
+field is the number associated with the
+.Ar login
+field.
+Both of these fields should be unique across the system (and often
+across a group of systems) as they control file access.
+.Pp
+While it is possible to have multiple entries with identical login names
+and/or identical user id's, it is usually a mistake to do so.
+Routines
+that manipulate these files will often return only one of the multiple
+entries, and that one by random selection.
+.Pp
+The
+.Ar gid
+field is the group that the user will be placed in at login.
+Since
+.Bx
+supports multiple groups (see
+.Xr groups 1 )
+this field currently has little special meaning.
+This field may be filled in with either a number or a group name (see
+.Xr group 5 ) .
+.Pp
+The
+.Ar class
+field references class descriptions in
+.Pa /etc/login.conf
+and is typically used to initialize the user's system resource limits
+when they login.
+.Pp
+The
+.Ar change
+field is the date by which the password must be changed.
+.Pp
+The
+.Ar expire
+field is the date on which the account expires.
+.Pp
+Both the
+.Ar change
+and
+.Ar expire
+fields should be entered in the form
+.Dq month day year
+where
+.Ar month
+is the month name (the first three characters are sufficient),
+.Ar day
+is the day of the month, and
+.Ar year
+is the year.
+.Pp
+Five fields are available for storing the user's
+.Ar full name , office location ,
+.Ar work
+and
+.Ar home telephone
+numbers and finally
+.Ar other information
+which is a single comma delimited string to represent any additional
+gecos fields (typically used for site specific user information).
+Note that
+.Xr finger 1
+will display the office location and office phone together under the
+heading
+.Ar Office\&: .
+.Pp
+The user's
+.Ar home directory
+is the full
+.Ux
+path name where the user
+will be placed at login.
+.Pp
+The
+.Ar shell
+field is the command interpreter the user prefers.
+If the
+.Ar shell
+field is empty, the Bourne shell,
+.Pa /bin/sh ,
+is assumed.
+When altering a login shell, and not the super-user, the user
+may not change from a non-standard shell or to a non-standard
+shell.
+Non-standard is defined as a shell not found in
+.Pa /etc/shells .
+.Pp
+Once the information has been verified,
+.Nm
+uses
+.Xr pwd_mkdb 8
+to update the user database.
+.Sh ENVIRONMENT
+The
+.Xr vi 1
+editor will be used unless the environment variable
+.Ev EDITOR
+is set to
+an alternate editor.
+When the editor terminates, the information is re-read and used to
+update the user database itself.
+Only the user, or the super-user, may edit the information associated
+with the user.
+.Pp
+See
+.Xr pwd_mkdb 8
+for an explanation of the impact of setting the
+.Ev PW_SCAN_BIG_IDS
+environment variable.
+.Sh NIS INTERACTION
+The
+.Nm
+utility can also be used in conjunction with NIS, however some restrictions
+apply.
+Currently,
+.Nm
+can only make changes to the NIS passwd maps through
+.Xr rpc.yppasswdd 8 ,
+which normally only permits changes to a user's password, shell and GECOS
+fields.
+Except when invoked by the super-user on the NIS master server,
+.Nm
+(and, similarly,
+.Xr passwd 1 )
+cannot use the
+.Xr rpc.yppasswdd 8
+server to change other user information or
+add new records to the NIS passwd maps.
+Furthermore,
+.Xr rpc.yppasswdd 8
+requires password authentication before it will make any
+changes.
+The only user allowed to submit changes without supplying
+a password is the super-user on the NIS master server; all other users,
+including those with root privileges on NIS clients (and NIS slave
+servers) must enter a password.
+(The super-user on the NIS master is allowed to bypass these restrictions
+largely for convenience: a user with root access
+to the NIS master server already has the privileges required to make
+updates to the NIS maps, but editing the map source files by hand can
+be cumbersome.
+.Pp
+Note: these exceptions only apply when the NIS master server is a
+.Fx
+system).
+.Pp
+Consequently, except where noted, the following restrictions apply when
+.Nm
+is used with NIS:
+.Bl -enum -offset indent
+.It
+.Em "Only the shell and GECOS information may be changed" .
+All other
+fields are restricted, even when
+.Nm
+is invoked by the super-user.
+While support for
+changing other fields could be added, this would lead to
+compatibility problems with other NIS-capable systems.
+Even though the super-user may supply data for other fields
+while editing an entry, the extra information (other than the
+password \(em see below) will be silently discarded.
+.Pp
+Exception: the super-user on the NIS master server is permitted to
+change any field.
+.It
+.Em "Password authentication is required" .
+The
+.Nm
+utility will prompt for the user's NIS password before effecting
+any changes.
+If the password is invalid, all changes will be
+discarded.
+.Pp
+Exception: the super-user on the NIS master server is allowed to
+submit changes without supplying a password.
+(The super-user may
+choose to turn off this feature using the
+.Fl o
+flag, described below.)
+.It
+.Em "Adding new records to the local password database is discouraged" .
+The
+.Nm
+utility will allow the administrator to add new records to the
+local password database while NIS is enabled, but this can lead to
+some confusion since the new records are appended to the end of
+the master password file, usually after the special NIS '+' entries.
+The administrator should use
+.Xr vipw 8
+to modify the local password
+file when NIS is running.
+.Pp
+The super-user on the NIS master server is permitted to add new records
+to the NIS password maps, provided the
+.Xr rpc.yppasswdd 8
+server has been started with the
+.Fl a
+flag to permitted additions (it refuses them by default).
+The
+.Nm
+utility tries to update the local password database by default; to update the
+NIS maps instead, invoke chpass with the
+.Fl y
+flag.
+.It
+.Em "Password changes are not permitted".
+Users should use
+.Xr passwd 1
+or
+.Xr yppasswd 1
+to change their NIS passwords.
+The super-user is allowed to specify
+a new password (even though the
+.Dq Password:
+field does not show
+up in the editor template, the super-user may add it back by hand),
+but even the super-user must supply the user's original password
+otherwise
+.Xr rpc.yppasswdd 8
+will refuse to update the NIS maps.
+.Pp
+Exception: the super-user on the NIS master server is permitted to
+change a user's NIS password with
+.Nm .
+.El
+.Pp
+There are also a few extra option flags that are available when
+.Nm
+is compiled with NIS support:
+.Bl -tag -width "-d domain"
+.It Fl d Ar domain
+Specify a particular NIS domain.
+The
+.Nm
+utility uses the system domain name by default, as set by the
+.Xr domainname 1
+utility.
+The
+.Fl d
+option can be used to override a default, or to specify a domain
+when the system domain name is not set.
+.It Fl h Ar host
+Specify the name or address of an NIS server to query.
+Normally,
+.Nm
+will communicate with the NIS master host specified in the
+.Pa master.passwd
+or
+.Pa passwd
+maps.
+On hosts that have not been configured as NIS clients, there is
+no way for the program to determine this information unless the user
+provides the hostname of a server.
+Note that the specified hostname need
+not be that of the NIS master server; the name of any server, master or
+slave, in a given NIS domain will do.
+.Pp
+When using the
+.Fl d
+option, the hostname defaults to
+.Dq localhost .
+The
+.Fl h
+option can be used in conjunction with the
+.Fl d
+option, in which case the user-specified hostname will override
+the default.
+.It Fl l
+Force
+.Nm
+to modify the local copy of a user's password
+information in the event that a user exists in both
+the local and NIS databases.
+.It Fl o
+Force the use of RPC-based updates when communicating with
+.Xr rpc.yppasswdd 8
+.Pq Dq old-mode .
+When invoked by the super-user on the NIS master server,
+.Nm
+allows unrestricted changes to the NIS passwd maps using dedicated,
+non-RPC-based mechanism (in this case, a
+.Ux
+domain socket).
+The
+.Fl o
+flag can be used to force
+.Nm
+to use the standard update mechanism instead.
+This option is provided
+mainly for testing purposes.
+.It Fl y
+Opposite effect of
+.Fl l .
+This flag is largely redundant since
+.Nm
+operates on NIS entries by default if NIS is enabled.
+.El
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/master.passwd
+the user database
+.It Pa /etc/passwd
+a Version 7 format password file
+.It Pa /etc/pw.XXXXXX
+temporary file
+.It Pa /etc/shells
+the list of approved shells
+.El
+.Sh EXAMPLES
+Change the shell of the current user to
+.Ql /usr/local/bin/zsh :
+.Bd -literal -offset indent
+chsh -s /usr/local/bin/zsh
+.Ed
+.Sh SEE ALSO
+.Xr finger 1 ,
+.Xr login 1 ,
+.Xr passwd 1 ,
+.Xr getusershell 3 ,
+.Xr login.conf 5 ,
+.Xr passwd 5 ,
+.Xr pw 8 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8
+.Rs
+.%A Robert Morris
+.%A Ken Thompson
+.%T "UNIX Password security"
+.Re
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.3 Reno .
+.Sh BUGS
+User information should (and eventually will) be stored elsewhere.
diff --git a/usr.bin/chpass/chpass.c b/usr.bin/chpass/chpass.c
new file mode 100644
index 000000000000..e0d1945dd080
--- /dev/null
+++ b/usr.bin/chpass/chpass.c
@@ -0,0 +1,293 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef YP
+#include <ypclnt.h>
+#endif
+
+#include <pw_scan.h>
+#include <libutil.h>
+
+#include "chpass.h"
+
+int master_mode;
+
+static void baduser(void);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op;
+ struct passwd lpw, *old_pw, *pw;
+ int ch, pfd, tfd;
+ const char *password;
+ char *arg = NULL, *cryptpw;
+ uid_t uid;
+#ifdef YP
+ struct ypclnt *ypclnt;
+ const char *yp_domain = NULL, *yp_host = NULL;
+#endif
+
+ pw = old_pw = NULL;
+ op = EDITENTRY;
+#ifdef YP
+ while ((ch = getopt(argc, argv, "a:p:s:e:d:h:loy")) != -1)
+#else
+ while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1)
+#endif
+ switch (ch) {
+ case 'a':
+ op = LOADENTRY;
+ arg = optarg;
+ break;
+ case 's':
+ op = NEWSH;
+ arg = optarg;
+ break;
+ case 'p':
+ op = NEWPW;
+ arg = optarg;
+ break;
+ case 'e':
+ op = NEWEXP;
+ arg = optarg;
+ break;
+#ifdef YP
+ case 'd':
+ yp_domain = optarg;
+ break;
+ case 'h':
+ yp_host = optarg;
+ break;
+ case 'l':
+ case 'o':
+ case 'y':
+ /* compatibility */
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ usage();
+
+ uid = getuid();
+
+ if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) {
+ if (argc == 0) {
+ if ((pw = getpwuid(uid)) == NULL)
+ errx(1, "unknown user: uid %lu",
+ (unsigned long)uid);
+ } else {
+ if ((pw = getpwnam(*argv)) == NULL)
+ errx(1, "unknown user: %s", *argv);
+ if (uid != 0 && uid != pw->pw_uid)
+ baduser();
+ }
+
+ /* Make a copy for later verification */
+ if ((pw = pw_dup(pw)) == NULL ||
+ (old_pw = pw_dup(pw)) == NULL)
+ err(1, "pw_dup");
+ }
+
+#ifdef YP
+ if (pw != NULL && (pw->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
+ ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+ master_mode = (ypclnt != NULL &&
+ ypclnt_connect(ypclnt) != -1 &&
+ ypclnt_havepasswdd(ypclnt) == 1);
+ ypclnt_free(ypclnt);
+ } else
+#endif
+ master_mode = (uid == 0);
+
+ if (op == NEWSH) {
+ /* protect p_shell -- it thinks NULL is /bin/sh */
+ if (!arg[0])
+ usage();
+ if (p_shell(arg, pw, (ENTRY *)NULL) == -1)
+ exit(1);
+ }
+
+ if (op == NEWEXP) {
+ if (uid) /* only root can change expire */
+ baduser();
+ if (p_expire(arg, pw, (ENTRY *)NULL) == -1)
+ exit(1);
+ }
+
+ if (op == LOADENTRY) {
+ if (uid)
+ baduser();
+ pw = &lpw;
+ old_pw = NULL;
+ if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER))
+ exit(1);
+ }
+
+ if (op == NEWPW) {
+ if (uid)
+ baduser();
+
+ if (strchr(arg, ':'))
+ errx(1, "invalid format for password");
+ pw->pw_passwd = arg;
+ }
+
+ if (op == EDITENTRY) {
+ /*
+ * We don't really need pw_*() here, but pw_edit() (used
+ * by edit()) is just too useful...
+ */
+ if (pw_init(NULL, NULL))
+ err(1, "pw_init()");
+ if ((tfd = pw_tmp(-1)) == -1) {
+ pw_fini();
+ err(1, "pw_tmp()");
+ }
+ free(pw);
+ pw = edit(pw_tempname(), old_pw);
+ pw_fini();
+ if (pw == NULL)
+ err(1, "edit()");
+ /*
+ * pw_equal does not check for crypted passwords, so we
+ * should do it explicitly
+ */
+ if (pw_equal(old_pw, pw) &&
+ strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0)
+ errx(0, "user information unchanged");
+ }
+
+ if (old_pw && !master_mode) {
+ password = getpass("Password: ");
+ cryptpw = crypt(password, old_pw->pw_passwd);
+ if (cryptpw == NULL || strcmp(cryptpw, old_pw->pw_passwd) != 0)
+ baduser();
+ } else {
+ password = "";
+ }
+
+ if (old_pw != NULL)
+ pw->pw_fields |= (old_pw->pw_fields & _PWF_SOURCE);
+ switch (pw->pw_fields & _PWF_SOURCE) {
+#ifdef YP
+ case _PWF_NIS:
+ ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host);
+ if (ypclnt == NULL) {
+ warnx("ypclnt_new failed");
+ exit(1);
+ }
+ if (ypclnt_connect(ypclnt) == -1 ||
+ ypclnt_passwd(ypclnt, pw, password) == -1) {
+ warnx("%s", ypclnt->error);
+ ypclnt_free(ypclnt);
+ exit(1);
+ }
+ ypclnt_free(ypclnt);
+ errx(0, "NIS user information updated");
+#endif /* YP */
+ case 0:
+ case _PWF_FILES:
+ if (pw_init(NULL, NULL))
+ err(1, "pw_init()");
+ if ((pfd = pw_lock()) == -1) {
+ pw_fini();
+ err(1, "pw_lock()");
+ }
+ if ((tfd = pw_tmp(-1)) == -1) {
+ pw_fini();
+ err(1, "pw_tmp()");
+ }
+ if (pw_copy(pfd, tfd, pw, old_pw) == -1) {
+ pw_fini();
+ err(1, "pw_copy");
+ }
+ if (pw_mkdb(pw->pw_name) == -1) {
+ pw_fini();
+ err(1, "pw_mkdb()");
+ }
+ pw_fini();
+ errx(0, "user information updated");
+ break;
+ default:
+ errx(1, "unsupported passwd source");
+ }
+}
+
+static void
+baduser(void)
+{
+
+ errx(1, "%s", strerror(EACCES));
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: chpass%s %s [user]\n",
+#ifdef YP
+ " [-d domain] [-h host]",
+#else
+ "",
+#endif
+ "[-a list] [-p encpass] [-s shell] [-e mmm dd yy]");
+ exit(1);
+}
diff --git a/usr.bin/chpass/chpass.h b/usr.bin/chpass/chpass.h
new file mode 100644
index 000000000000..1150830af773
--- /dev/null
+++ b/usr.bin/chpass/chpass.h
@@ -0,0 +1,78 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+struct passwd;
+
+typedef struct _entry {
+ const char *prompt;
+ int (*func)(char *, struct passwd *, struct _entry *);
+ int restricted;
+ size_t len;
+ const char *except, *save;
+} ENTRY;
+
+/* Field numbers. */
+#define E_BPHONE 8
+#define E_HPHONE 9
+#define E_LOCATE 10
+#define E_NAME 7
+#define E_OTHER 11
+#define E_SHELL 13
+
+extern ENTRY list[];
+extern int master_mode;
+
+int atot(char *, time_t *);
+struct passwd *edit(const char *, struct passwd *);
+int ok_shell(char *);
+char *dup_shell(char *);
+int p_change(char *, struct passwd *, ENTRY *);
+int p_class(char *, struct passwd *, ENTRY *);
+int p_expire(char *, struct passwd *, ENTRY *);
+int p_gecos(char *, struct passwd *, ENTRY *);
+int p_gid(char *, struct passwd *, ENTRY *);
+int p_hdir(char *, struct passwd *, ENTRY *);
+int p_login(char *, struct passwd *, ENTRY *);
+int p_passwd(char *, struct passwd *, ENTRY *);
+int p_shell(char *, struct passwd *, ENTRY *);
+int p_uid(char *, struct passwd *, ENTRY *);
+char *ttoa(time_t);
diff --git a/usr.bin/chpass/edit.c b/usr.bin/chpass/edit.c
new file mode 100644
index 000000000000..978a3eb1a63f
--- /dev/null
+++ b/usr.bin/chpass/edit.c
@@ -0,0 +1,289 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <pw_scan.h>
+#include <libutil.h>
+
+#include "chpass.h"
+
+static int display(const char *tfn, struct passwd *pw);
+static struct passwd *verify(const char *tfn, struct passwd *pw);
+
+struct passwd *
+edit(const char *tfn, struct passwd *pw)
+{
+ struct passwd *npw;
+ char *line;
+ size_t len;
+
+ if (display(tfn, pw) == -1)
+ return (NULL);
+ for (;;) {
+ switch (pw_edit(1)) {
+ case -1:
+ return (NULL);
+ case 0:
+ return (pw_dup(pw));
+ default:
+ break;
+ }
+ if ((npw = verify(tfn, pw)) != NULL)
+ return (npw);
+ free(npw);
+ printf("re-edit the password file? ");
+ fflush(stdout);
+ if ((line = fgetln(stdin, &len)) == NULL) {
+ warn("fgetln()");
+ return (NULL);
+ }
+ if (len > 0 && (*line == 'N' || *line == 'n'))
+ return (NULL);
+ }
+}
+
+/*
+ * display --
+ * print out the file for the user to edit; strange side-effect:
+ * set conditional flag if the user gets to edit the shell.
+ */
+static int
+display(const char *tfn, struct passwd *pw)
+{
+ FILE *fp;
+ char *bp, *gecos, *p;
+
+ if ((fp = fopen(tfn, "w")) == NULL) {
+ warn("%s", tfn);
+ return (-1);
+ }
+
+ (void)fprintf(fp,
+ "#Changing user information for %s.\n", pw->pw_name);
+ if (master_mode) {
+ (void)fprintf(fp, "Login: %s\n", pw->pw_name);
+ (void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
+ (void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid);
+ (void)fprintf(fp, "Gid [# or name]: %lu\n",
+ (unsigned long)pw->pw_gid);
+ (void)fprintf(fp, "Change [month day year]: %s\n",
+ ttoa(pw->pw_change));
+ (void)fprintf(fp, "Expire [month day year]: %s\n",
+ ttoa(pw->pw_expire));
+ (void)fprintf(fp, "Class: %s\n", pw->pw_class);
+ (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
+ (void)fprintf(fp, "Shell: %s\n",
+ *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
+ }
+ /* Only admin can change "restricted" shells. */
+#if 0
+ else if (ok_shell(pw->pw_shell))
+ /*
+ * Make shell a restricted field. Ugly with a
+ * necklace, but there's not much else to do.
+ */
+#else
+ else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) ||
+ master_mode)
+ /*
+ * If change not restrict (table.c) and standard shell
+ * OR if root, then allow editing of shell.
+ */
+#endif
+ (void)fprintf(fp, "Shell: %s\n",
+ *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
+ else
+ list[E_SHELL].restricted = 1;
+
+ if ((bp = gecos = strdup(pw->pw_gecos)) == NULL) {
+ warn(NULL);
+ fclose(fp);
+ return (-1);
+ }
+
+ p = strsep(&bp, ",");
+ p = strdup(p ? p : "");
+ list[E_NAME].save = p;
+ if (!list[E_NAME].restricted || master_mode)
+ (void)fprintf(fp, "Full Name: %s\n", p);
+
+ p = strsep(&bp, ",");
+ p = strdup(p ? p : "");
+ list[E_LOCATE].save = p;
+ if (!list[E_LOCATE].restricted || master_mode)
+ (void)fprintf(fp, "Office Location: %s\n", p);
+
+ p = strsep(&bp, ",");
+ p = strdup(p ? p : "");
+ list[E_BPHONE].save = p;
+ if (!list[E_BPHONE].restricted || master_mode)
+ (void)fprintf(fp, "Office Phone: %s\n", p);
+
+ p = strsep(&bp, ",");
+ p = strdup(p ? p : "");
+ list[E_HPHONE].save = p;
+ if (!list[E_HPHONE].restricted || master_mode)
+ (void)fprintf(fp, "Home Phone: %s\n", p);
+
+ bp = strdup(bp ? bp : "");
+ list[E_OTHER].save = bp;
+ if (!list[E_OTHER].restricted || master_mode)
+ (void)fprintf(fp, "Other information: %s\n", bp);
+
+ free(gecos);
+
+ (void)fchown(fileno(fp), getuid(), getgid());
+ (void)fclose(fp);
+ return (0);
+}
+
+static struct passwd *
+verify(const char *tfn, struct passwd *pw)
+{
+ struct passwd *npw;
+ ENTRY *ep;
+ char *buf, *p, *val;
+ struct stat sb;
+ FILE *fp;
+ int line;
+ size_t len;
+
+ if ((pw = pw_dup(pw)) == NULL)
+ return (NULL);
+ if ((fp = fopen(tfn, "r")) == NULL ||
+ fstat(fileno(fp), &sb) == -1) {
+ warn("%s", tfn);
+ free(pw);
+ return (NULL);
+ }
+ if (sb.st_size == 0) {
+ warnx("corrupted temporary file");
+ fclose(fp);
+ free(pw);
+ return (NULL);
+ }
+ val = NULL;
+ for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) {
+ if (*buf == '\0' || *buf == '#')
+ continue;
+ while (len > 0 && isspace(buf[len - 1]))
+ --len;
+ for (ep = list;; ++ep) {
+ if (!ep->prompt) {
+ warnx("%s: unrecognized field on line %d",
+ tfn, line);
+ goto bad;
+ }
+ if (ep->len > len)
+ continue;
+ if (strncasecmp(buf, ep->prompt, ep->len) != 0)
+ continue;
+ if (ep->restricted && !master_mode) {
+ warnx("%s: you may not change the %s field",
+ tfn, ep->prompt);
+ goto bad;
+ }
+ for (p = buf; p < buf + len && *p != ':'; ++p)
+ /* nothing */ ;
+ if (*p != ':') {
+ warnx("%s: line %d corrupted", tfn, line);
+ goto bad;
+ }
+ while (++p < buf + len && isspace(*p))
+ /* nothing */ ;
+ free(val);
+ asprintf(&val, "%.*s", (int)(buf + len - p), p);
+ if (val == NULL)
+ goto bad;
+ if (ep->except && strpbrk(val, ep->except)) {
+ warnx("%s: invalid character in \"%s\" field '%s'",
+ tfn, ep->prompt, val);
+ goto bad;
+ }
+ if ((ep->func)(val, pw, ep))
+ goto bad;
+ break;
+ }
+ }
+ free(val);
+ fclose(fp);
+
+ /* Build the gecos field. */
+ len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save,
+ list[E_LOCATE].save, list[E_BPHONE].save,
+ list[E_HPHONE].save, list[E_OTHER].save);
+ if (p == NULL) {
+ warn("asprintf()");
+ free(pw);
+ return (NULL);
+ }
+ while (len > 0 && p[len - 1] == ',')
+ p[--len] = '\0';
+ pw->pw_gecos = p;
+ buf = pw_make(pw);
+ free(pw);
+ free(p);
+ if (buf == NULL) {
+ warn("pw_make()");
+ return (NULL);
+ }
+ npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER);
+ free(buf);
+ return (npw);
+bad:
+ free(pw);
+ free(val);
+ fclose(fp);
+ return (NULL);
+}
diff --git a/usr.bin/chpass/field.c b/usr.bin/chpass/field.c
new file mode 100644
index 000000000000..b64f33e06fdb
--- /dev/null
+++ b/usr.bin/chpass/field.c
@@ -0,0 +1,254 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "chpass.h"
+
+/* ARGSUSED */
+int
+p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!*p) {
+ warnx("empty login field");
+ return (-1);
+ }
+ if (*p == '-') {
+ warnx("login names may not begin with a hyphen");
+ return (-1);
+ }
+ if (!(pw->pw_name = strdup(p))) {
+ warnx("can't save entry");
+ return (-1);
+ }
+ if (strchr(p, '.'))
+ warnx("\'.\' is dangerous in a login name");
+ for (; *p; ++p)
+ if (isupper(*p)) {
+ warnx("upper-case letters are dangerous in a login name");
+ break;
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!(pw->pw_passwd = strdup(p))) {
+ warnx("can't save password entry");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ uid_t id;
+ char *np;
+
+ if (!*p) {
+ warnx("empty uid field");
+ return (-1);
+ }
+ if (!isdigit(*p)) {
+ warnx("illegal uid");
+ return (-1);
+ }
+ errno = 0;
+ id = strtoul(p, &np, 10);
+ if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
+ warnx("illegal uid");
+ return (-1);
+ }
+ pw->pw_uid = id;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ struct group *gr;
+ gid_t id;
+ char *np;
+
+ if (!*p) {
+ warnx("empty gid field");
+ return (-1);
+ }
+ if (!isdigit(*p)) {
+ if (!(gr = getgrnam(p))) {
+ warnx("unknown group %s", p);
+ return (-1);
+ }
+ pw->pw_gid = gr->gr_gid;
+ return (0);
+ }
+ errno = 0;
+ id = strtoul(p, &np, 10);
+ if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
+ warnx("illegal gid");
+ return (-1);
+ }
+ pw->pw_gid = id;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!(pw->pw_class = strdup(p))) {
+ warnx("can't save entry");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!atot(p, &pw->pw_change))
+ return (0);
+ warnx("illegal date for change field");
+ return (-1);
+}
+
+/* ARGSUSED */
+int
+p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!atot(p, &pw->pw_expire))
+ return (0);
+ warnx("illegal date for expire field");
+ return (-1);
+}
+
+/* ARGSUSED */
+int
+p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
+{
+ if (!(ep->save = strdup(p))) {
+ warnx("can't save entry");
+ return (-1);
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ if (!*p) {
+ warnx("empty home directory field");
+ return (-1);
+ }
+ if (!(pw->pw_dir = strdup(p))) {
+ warnx("can't save entry");
+ return (-1);
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
+p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
+{
+ struct stat sbuf;
+
+ if (!*p) {
+ pw->pw_shell = strdup(_PATH_BSHELL);
+ return (0);
+ }
+ /* only admin can change from or to "restricted" shells */
+ if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
+ warnx("%s: current shell non-standard", pw->pw_shell);
+ return (-1);
+ }
+ if (!ok_shell(p)) {
+ if (!master_mode) {
+ warnx("%s: non-standard shell", p);
+ return (-1);
+ }
+ pw->pw_shell = strdup(p);
+ }
+ else
+ pw->pw_shell = dup_shell(p);
+ if (!pw->pw_shell) {
+ warnx("can't save entry");
+ return (-1);
+ }
+ if (stat(pw->pw_shell, &sbuf) < 0) {
+ if (errno == ENOENT)
+ warnx("WARNING: shell '%s' does not exist",
+ pw->pw_shell);
+ else
+ warn("WARNING: can't stat shell '%s'", pw->pw_shell);
+ return (0);
+ }
+ if (!S_ISREG(sbuf.st_mode)) {
+ warnx("WARNING: shell '%s' is not a regular file",
+ pw->pw_shell);
+ return (0);
+ }
+ if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
+ warnx("WARNING: shell '%s' is not executable", pw->pw_shell);
+ return (0);
+ }
+ return (0);
+}
diff --git a/usr.bin/chpass/table.c b/usr.bin/chpass/table.c
new file mode 100644
index 000000000000..53ed54e825af
--- /dev/null
+++ b/usr.bin/chpass/table.c
@@ -0,0 +1,56 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <stddef.h>
+#include "chpass.h"
+
+ENTRY list[] = {
+ { "login", p_login, 1, 5, ": ", NULL },
+ { "password", p_passwd, 1, 8, ": ", NULL },
+ { "uid", p_uid, 1, 3, ": ", NULL },
+ { "gid", p_gid, 1, 3, ": ", NULL },
+ { "class", p_class, 1, 5, ": ", NULL },
+ { "change", p_change, 1, 6, NULL, NULL },
+ { "expire", p_expire, 1, 6, NULL, NULL },
+#ifdef RESTRICT_FULLNAME_CHANGE /* do not allow fullname changes */
+ { "full name", p_gecos, 1, 9, ":,", NULL },
+#else
+ { "full name", p_gecos, 0, 9, ":,", NULL },
+#endif
+ { "office phone", p_gecos, 0, 12, ":,", NULL },
+ { "home phone", p_gecos, 0, 10, ":,", NULL },
+ { "office location", p_gecos, 0, 15, ":,", NULL },
+ { "other information", p_gecos, 0, 11, ": ", NULL },
+ { "home directory", p_hdir, 1, 14, ": ", NULL },
+ { "shell", p_shell, 0, 5, ": ", NULL },
+ { NULL, NULL, 0, 0, NULL, NULL },
+};
diff --git a/usr.bin/chpass/util.c b/usr.bin/chpass/util.c
new file mode 100644
index 000000000000..9e3b3f7903c7
--- /dev/null
+++ b/usr.bin/chpass/util.c
@@ -0,0 +1,188 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "chpass.h"
+
+static const char *months[] =
+ { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November",
+ "December", NULL };
+
+char *
+ttoa(time_t tval)
+{
+ struct tm *tp;
+ static char tbuf[50];
+
+ if (tval) {
+ tp = localtime(&tval);
+ (void)sprintf(tbuf, "%s %d, %d", months[tp->tm_mon],
+ tp->tm_mday, tp->tm_year + 1900);
+ }
+ else
+ *tbuf = '\0';
+ return (tbuf);
+}
+
+int
+atot(char *p, time_t *store)
+{
+ static struct tm *lt;
+ char *t;
+ const char **mp;
+ time_t tval;
+ int day, month, year;
+
+ if (!*p) {
+ *store = 0;
+ return (0);
+ }
+ if (!lt) {
+ unsetenv("TZ");
+ (void)time(&tval);
+ lt = localtime(&tval);
+ }
+ if (!(t = strtok(p, " \t")))
+ goto bad;
+ if (isdigit(*t)) {
+ month = atoi(t);
+ } else {
+ for (mp = months;; ++mp) {
+ if (!*mp)
+ goto bad;
+ if (!strncasecmp(*mp, t, 3)) {
+ month = mp - months + 1;
+ break;
+ }
+ }
+ }
+ if (!(t = strtok(NULL, " \t,")) || !isdigit(*t))
+ goto bad;
+ day = atoi(t);
+ if (!(t = strtok(NULL, " \t,")) || !isdigit(*t))
+ goto bad;
+ year = atoi(t);
+ if (day < 1 || day > 31 || month < 1 || month > 12)
+ goto bad;
+ /* Allow two digit years 1969-2068 */
+ if (year < 69)
+ year += 2000;
+ else if (year < 100)
+ year += 1900;
+ if (year < 1969)
+bad: return (1);
+ lt->tm_year = year - 1900;
+ lt->tm_mon = month - 1;
+ lt->tm_mday = day;
+ lt->tm_hour = 0;
+ lt->tm_min = 0;
+ lt->tm_sec = 0;
+ lt->tm_isdst = -1;
+ if ((tval = mktime(lt)) < 0)
+ return (1);
+#ifndef __i386__
+ /*
+ * PR227589: The pwd.db and spwd.db files store the change and expire
+ * dates as unsigned 32-bit ints which overflow in 2106, so larger
+ * values must be rejected until the introduction of a v5 password
+ * database. i386 has 32-bit time_t and so dates beyond y2038 are
+ * already rejected by mktime above.
+ */
+ if (tval > UINT32_MAX)
+ return (1);
+#endif
+ *store = tval;
+ return (0);
+}
+
+int
+ok_shell(char *name)
+{
+ char *p, *sh;
+
+ setusershell();
+ while ((sh = getusershell())) {
+ if (!strcmp(name, sh)) {
+ endusershell();
+ return (1);
+ }
+ /* allow just shell name, but use "real" path */
+ if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+ endusershell();
+ return (1);
+ }
+ }
+ endusershell();
+ return (0);
+}
+
+char *
+dup_shell(char *name)
+{
+ char *p, *sh, *ret;
+
+ setusershell();
+ while ((sh = getusershell())) {
+ if (!strcmp(name, sh)) {
+ endusershell();
+ return (strdup(name));
+ }
+ /* allow just shell name, but use "real" path */
+ if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) {
+ ret = strdup(sh);
+ endusershell();
+ return (ret);
+ }
+ }
+ endusershell();
+ return (NULL);
+}
diff --git a/usr.bin/cksum/Makefile b/usr.bin/cksum/Makefile
new file mode 100644
index 000000000000..c8d34f7fe5d5
--- /dev/null
+++ b/usr.bin/cksum/Makefile
@@ -0,0 +1,6 @@
+PROG= cksum
+SRCS= cksum.c crc.c print.c sum1.c sum2.c crc32.c
+LINKS= ${BINDIR}/cksum ${BINDIR}/sum
+MLINKS= cksum.1 sum.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cksum/Makefile.depend b/usr.bin/cksum/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/cksum/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cksum/cksum.1 b/usr.bin/cksum/cksum.1
new file mode 100644
index 000000000000..cd9b78c12306
--- /dev/null
+++ b/usr.bin/cksum/cksum.1
@@ -0,0 +1,188 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd January 18, 2024
+.Dt CKSUM 1
+.Os
+.Sh NAME
+.Nm cksum ,
+.Nm sum
+.Nd display file checksums and block counts
+.Sh SYNOPSIS
+.Nm
+.Op Fl o Ar 1 | 2 | 3
+.Op Ar
+.Nm sum
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes to the standard output three whitespace separated
+fields for each input file.
+These fields are a checksum
+.Tn CRC ,
+the total number of octets in the file and the file name.
+If no file name is specified, the standard input is used and no file name
+is written.
+.Pp
+The
+.Nm sum
+utility is identical to the
+.Nm
+utility, except that it defaults to using historic algorithm 1, as
+described below.
+It is provided for compatibility only.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Use historic algorithms instead of the (superior) default one.
+.Pp
+Algorithm 1 is the algorithm used by historic
+.Bx
+systems as the
+.Xr sum 1
+algorithm and by historic
+.At V
+systems as the
+.Xr sum 1
+algorithm when using the
+.Fl r
+option.
+This is a 16-bit checksum, with a right rotation before each addition;
+overflow is discarded.
+.Pp
+Algorithm 2 is the algorithm used by historic
+.At V
+systems as the
+default
+.Xr sum 1
+algorithm.
+This is a 32-bit checksum, and is defined as follows:
+.Bd -unfilled -offset indent
+s = sum of all bytes;
+r = s % 2^16 + (s % 2^32) / 2^16;
+cksum = (r % 2^16) + r / 2^16;
+.Ed
+.Pp
+Algorithm 3 is what is commonly called the
+.Ql 32bit CRC
+algorithm.
+This is a 32-bit checksum.
+.Pp
+Both algorithm 1 and 2 write to the standard output the same fields as
+the default algorithm except that the size of the file in bytes is
+replaced with the size of the file in blocks.
+For historic reasons, the block size is 1024 for algorithm 1 and 512
+for algorithm 2.
+Partial blocks are rounded up.
+.El
+.Pp
+The default
+.Tn CRC
+used is based on the polynomial used for
+.Tn CRC
+error checking
+in the networking standard
+.St -iso8802-3 .
+The
+.Tn CRC
+checksum encoding is defined by the generating polynomial:
+.Bd -unfilled -offset indent
+G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 +
+ x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
+.Ed
+.Pp
+Mathematically, the
+.Tn CRC
+value corresponding to a given file is defined by
+the following procedure:
+.Bd -ragged -offset indent
+The
+.Ar n
+bits to be evaluated are considered to be the coefficients of a mod 2
+polynomial M(x) of degree
+.Ar n Ns \-1 .
+These
+.Ar n
+bits are the bits from the file, with the most significant bit being the most
+significant bit of the first octet of the file and the last bit being the least
+significant bit of the last octet, padded with zero bits (if necessary) to
+achieve an integral number of octets, followed by one or more octets
+representing the length of the file as a binary value, least significant octet
+first.
+The smallest number of octets capable of representing this integer are used.
+.Pp
+M(x) is multiplied by x^32 (i.e., shifted left 32 bits) and divided by
+G(x) using mod 2 division, producing a remainder R(x) of degree <= 31.
+.Pp
+The coefficients of R(x) are considered to be a 32-bit sequence.
+.Pp
+The bit sequence is complemented and the result is the CRC.
+.Ed
+.Sh EXIT STATUS
+.Ex -std cksum sum
+.Sh EXAMPLES
+Compute the checksum for all available algorithms.
+Notice the difference in the size representation (in bytes for algorithm 1 and 2
+and in blocks for 3 and the default algorithm):
+.Bd -literal -offset indent
+$ echo "hello" | cksum
+3015617425 6
+$ echo "hello" | cksum -o 1
+36979 1
+$ echo "hello" | cksum -o 2
+542 1
+$ echo "hello" | cksum -o 3
+909783072 6
+.Ed
+.Sh SEE ALSO
+.Xr md5 1
+.Pp
+The default calculation is identical to that given in pseudo-code
+in the following
+.Tn ACM
+article.
+.Rs
+.%T "Computation of Cyclic Redundancy Checks Via Table Lookup"
+.%A Dilip V. Sarwate
+.%J "Communications of the" Tn ACM
+.%D "August 1988"
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.2-92 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.4 .
diff --git a/usr.bin/cksum/cksum.c b/usr.bin/cksum/cksum.c
new file mode 100644
index 000000000000..ce69246e1861
--- /dev/null
+++ b/usr.bin/cksum/cksum.c
@@ -0,0 +1,123 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * 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 <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ uint32_t val;
+ int ch, fd, rval;
+ off_t len;
+ char *fn, *p;
+ int (*cfncn)(int, uint32_t *, off_t *);
+ void (*pfncn)(char *, uint32_t, off_t);
+
+ if ((p = strrchr(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (!strcmp(p, "sum")) {
+ cfncn = csum1;
+ pfncn = psum1;
+ ++argv;
+ } else {
+ cfncn = crc;
+ pfncn = pcrc;
+
+ while ((ch = getopt(argc, argv, "o:")) != -1)
+ switch (ch) {
+ case 'o':
+ if (!strcmp(optarg, "1")) {
+ cfncn = csum1;
+ pfncn = psum1;
+ } else if (!strcmp(optarg, "2")) {
+ cfncn = csum2;
+ pfncn = psum2;
+ } else if (!strcmp(optarg, "3")) {
+ cfncn = crc32;
+ pfncn = pcrc;
+ } else {
+ warnx("illegal argument to -o option");
+ usage();
+ }
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ }
+
+ fd = STDIN_FILENO;
+ fn = NULL;
+ rval = 0;
+ do {
+ if (*argv) {
+ fn = *argv++;
+ if ((fd = open(fn, O_RDONLY, 0)) < 0) {
+ warn("%s", fn);
+ rval = 1;
+ continue;
+ }
+ }
+ if (cfncn(fd, &val, &len)) {
+ warn("%s", fn ? fn : "stdin");
+ rval = 1;
+ } else
+ pfncn(fn, val, len);
+ (void)close(fd);
+ } while (*argv);
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: cksum [-o 1 | 2 | 3] [file ...]\n");
+ (void)fprintf(stderr, " sum [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/cksum/crc.c b/usr.bin/cksum/crc.c
new file mode 100644
index 000000000000..1a49e1526874
--- /dev/null
+++ b/usr.bin/cksum/crc.c
@@ -0,0 +1,137 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * 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 <stdint.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static const uint32_t crctab[] = {
+ 0x0,
+ 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+ 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+ 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+ 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+ 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+ 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+ 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+ 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+ 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+ 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+ 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+ 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+ 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+ 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+ 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+ 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+ 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+ 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+ 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+ 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+ 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+ 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+ 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+ 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+ 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+ 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+ 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+ 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+ 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+ 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+ 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+ 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+ 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+ 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+/*
+ * Compute a POSIX 1003.2 checksum. This routine has been broken out so that
+ * other programs can use it. It takes a file descriptor to read from and
+ * locations to store the crc and the number of bytes read. It returns 0 on
+ * success and 1 on failure. Errno is set on failure.
+ */
+static uint32_t crc_total = ~0; /* The crc over a number of files. */
+
+int
+crc(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc;
+ int nr;
+ off_t len;
+ u_char *p;
+ u_char buf[16 * 1024];
+
+#define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+
+ lcrc = len = 0;
+ crc_total = ~crc_total;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (len += nr, p = buf; nr--; ++p) {
+ COMPUTE(lcrc, *p);
+ COMPUTE(crc_total, *p);
+ }
+ if (nr < 0)
+ return (1);
+
+ *clen = len;
+
+ /* Include the length of the file. */
+ for (; len != 0; len >>= 8) {
+ COMPUTE(lcrc, len & 0xff);
+ COMPUTE(crc_total, len & 0xff);
+ }
+
+ *cval = ~lcrc;
+ crc_total = ~crc_total;
+ return (0);
+}
diff --git a/usr.bin/cksum/crc32.c b/usr.bin/cksum/crc32.c
new file mode 100644
index 000000000000..2eb3e1b7d190
--- /dev/null
+++ b/usr.bin/cksum/crc32.c
@@ -0,0 +1,119 @@
+/*
+ * This code implements the AUTODIN II polynomial used by Ethernet,
+ * and can be used to calculate multicast address hash indices.
+ * It assumes that the low order bits will be transmitted first,
+ * and consequently the low byte should be sent first when
+ * the crc computation is finished. The crc should be complemented
+ * before transmission.
+ * The variable corresponding to the macro argument "crc" should
+ * be an unsigned long and should be preset to all ones for Ethernet
+ * use. An error-free packet will leave 0xDEBB20E3 in the crc.
+ * Spencer Garrett <srg@quick.com>
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ * x^32 + x^26 + x^23 + x^22 + x^16 +
+ * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static uint32_t crc32_total = 0;
+
+int
+crc32(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc = ~0;
+ int nr ;
+ off_t len ;
+ char buf[BUFSIZ], *p ;
+
+ len = 0 ;
+ crc32_total = ~crc32_total ;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (len += nr, p = buf; nr--; ++p) {
+ CRC(lcrc, *p) ;
+ CRC(crc32_total, *p) ;
+ }
+ if (nr < 0)
+ return 1 ;
+
+ *clen = len ;
+ *cval = ~lcrc ;
+ crc32_total = ~crc32_total ;
+ return 0 ;
+}
diff --git a/usr.bin/cksum/extern.h b/usr.bin/cksum/extern.h
new file mode 100644
index 000000000000..7561d89f0caf
--- /dev/null
+++ b/usr.bin/cksum/extern.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int crc(int, uint32_t *, off_t *);
+void pcrc(char *, uint32_t, off_t);
+void psum1(char *, uint32_t, off_t);
+void psum2(char *, uint32_t, off_t);
+int csum1(int, uint32_t *, off_t *);
+int csum2(int, uint32_t *, off_t *);
+int crc32(int, uint32_t *, off_t *);
+__END_DECLS
diff --git a/usr.bin/cksum/print.c b/usr.bin/cksum/print.c
new file mode 100644
index 000000000000..345b36b64c44
--- /dev/null
+++ b/usr.bin/cksum/print.c
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+void
+pcrc(char *fn, uint32_t val, off_t len)
+{
+ (void)printf("%lu %jd", (u_long)val, (intmax_t)len);
+ if (fn != NULL)
+ (void)printf(" %s", fn);
+ (void)printf("\n");
+}
+
+void
+psum1(char *fn, uint32_t val, off_t len)
+{
+ (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 1023) / 1024);
+ if (fn != NULL)
+ (void)printf(" %s", fn);
+ (void)printf("\n");
+}
+
+void
+psum2(char *fn, uint32_t val, off_t len)
+{
+ (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 511) / 512);
+ if (fn != NULL)
+ (void)printf(" %s", fn);
+ (void)printf("\n");
+}
diff --git a/usr.bin/cksum/sum1.c b/usr.bin/cksum/sum1.c
new file mode 100644
index 000000000000..6174bae00adf
--- /dev/null
+++ b/usr.bin/cksum/sum1.c
@@ -0,0 +1,65 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+int
+csum1(int fd, uint32_t *cval, off_t *clen)
+{
+ int nr;
+ u_int lcrc;
+ off_t total;
+ u_char *p;
+ u_char buf[8192];
+
+ /*
+ * 16-bit checksum, rotating right before each addition;
+ * overflow is discarded.
+ */
+ lcrc = total = 0;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (total += nr, p = buf; nr--; ++p) {
+ if (lcrc & 1)
+ lcrc |= 0x10000;
+ lcrc = ((lcrc >> 1) + *p) & 0xffff;
+ }
+ if (nr < 0)
+ return (1);
+
+ *cval = lcrc;
+ *clen = total;
+ return (0);
+}
diff --git a/usr.bin/cksum/sum2.c b/usr.bin/cksum/sum2.c
new file mode 100644
index 000000000000..ae74226e5266
--- /dev/null
+++ b/usr.bin/cksum/sum2.c
@@ -0,0 +1,68 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+int
+csum2(int fd, uint32_t *cval, off_t *clen)
+{
+ uint32_t lcrc;
+ int nr;
+ off_t total;
+ u_char *p;
+ u_char buf[8192];
+
+ /*
+ * Draft 8 POSIX 1003.2:
+ *
+ * s = sum of all bytes
+ * r = s % 2^16 + (s % 2^32) / 2^16
+ * lcrc = (r % 2^16) + r / 2^16
+ */
+ lcrc = total = 0;
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (total += nr, p = buf; nr--; ++p)
+ lcrc += *p;
+ if (nr < 0)
+ return (1);
+
+ lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+ lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+
+ *cval = lcrc;
+ *clen = total;
+ return (0);
+}
diff --git a/usr.bin/clang/Makefile b/usr.bin/clang/Makefile
new file mode 100644
index 000000000000..a0cc015590f0
--- /dev/null
+++ b/usr.bin/clang/Makefile
@@ -0,0 +1,70 @@
+.include <src.opts.mk>
+
+.if ${MK_CLANG} != "no"
+SUBDIR+= clang
+.endif
+
+.if !defined(TOOLS_PREFIX)
+# LLVM binutils are needed to support features such as LTO, so we build them
+# by default if clang is enabled. If MK_LLVM_BINUTILS is set, we also use them
+# as the default binutils (ar,nm,addr2line, etc.).
+.if ${MK_CLANG} != "no" || ${MK_LLVM_BINUTILS} != "no"
+SUBDIR+= llvm-ar
+SUBDIR+= llvm-nm
+SUBDIR+= llvm-objcopy
+SUBDIR+= llvm-objdump
+SUBDIR+= llvm-readobj
+SUBDIR+= llvm-size
+SUBDIR+= llvm-strings
+SUBDIR+= llvm-symbolizer
+.endif
+
+.if ${MK_LLVM_BINUTILS} != "no" || ${MK_LLVM_CXXFILT} != "no"
+SUBDIR+= llvm-cxxfilt
+.endif
+
+.if ${MK_CLANG_EXTRAS} != "no"
+SUBDIR+= bugpoint
+SUBDIR+= llc
+SUBDIR+= lli
+SUBDIR+= llvm-as
+SUBDIR+= llvm-bcanalyzer
+SUBDIR+= llvm-cxxdump
+SUBDIR+= llvm-diff
+SUBDIR+= llvm-dis
+SUBDIR+= llvm-dwarfdump
+SUBDIR+= llvm-dwarfutil
+SUBDIR+= llvm-dwp
+SUBDIR+= llvm-extract
+SUBDIR+= llvm-link
+SUBDIR+= llvm-lto
+SUBDIR+= llvm-lto2
+SUBDIR+= llvm-mc
+SUBDIR+= llvm-mca
+SUBDIR+= llvm-modextract
+SUBDIR+= llvm-pdbutil
+SUBDIR+= llvm-rtdyld
+SUBDIR+= llvm-xray
+SUBDIR+= opt
+.endif
+
+.if ${MK_CLANG_EXTRAS} != "no" || ${MK_CLANG_FORMAT} != "no"
+SUBDIR+= clang-format
+.endif
+
+.if ${MK_LLD} != "no"
+SUBDIR+= lld
+.endif
+.if ${MK_LLDB} != "no"
+SUBDIR+= lldb
+SUBDIR+= lldb-server
+.endif
+.if ${MK_LLVM_COV} != "no"
+SUBDIR+= llvm-cov
+SUBDIR+= llvm-profdata
+.endif
+.endif # TOOLS_PREFIX
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/clang/Makefile.inc b/usr.bin/clang/Makefile.inc
new file mode 100644
index 000000000000..bf9fad4032e2
--- /dev/null
+++ b/usr.bin/clang/Makefile.inc
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+MK_PIE:= no # Explicit libXXX.a references
+
+.if ${MK_LLVM_FULL_DEBUGINFO} == "no"
+.if ${COMPILER_TYPE} == "clang"
+DEBUG_FILES_CFLAGS= -gline-tables-only
+.else
+DEBUG_FILES_CFLAGS= -g1
+.endif
+.endif
+
+WARNS?= 0
+
+.include "../Makefile.inc"
diff --git a/usr.bin/clang/bugpoint/Makefile b/usr.bin/clang/bugpoint/Makefile
new file mode 100644
index 000000000000..700cc6a3c78a
--- /dev/null
+++ b/usr.bin/clang/bugpoint/Makefile
@@ -0,0 +1,14 @@
+PROG_CXX= bugpoint
+
+SRCDIR= llvm/tools/bugpoint
+SRCS+= BugDriver.cpp
+SRCS+= CrashDebugger.cpp
+SRCS+= ExecutionDriver.cpp
+SRCS+= ExtractFunction.cpp
+SRCS+= FindBugs.cpp
+SRCS+= Miscompilation.cpp
+SRCS+= OptimizerDriver.cpp
+SRCS+= ToolRunner.cpp
+SRCS+= bugpoint.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/bugpoint/Makefile.depend b/usr.bin/clang/bugpoint/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/bugpoint/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/bugpoint/bugpoint.1 b/usr.bin/clang/bugpoint/bugpoint.1
new file mode 100644
index 000000000000..efbecd28e178
--- /dev/null
+++ b/usr.bin/clang/bugpoint/bugpoint.1
@@ -0,0 +1,308 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "BUGPOINT" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+bugpoint \- automatic test case reduction tool
+.SH SYNOPSIS
+.sp
+\fBbugpoint\fP [\fIoptions\fP] [\fIinput LLVM ll/bc files\fP] [\fILLVM passes\fP] \fB\-\-args\fP
+\fIprogram arguments\fP
+.SH DESCRIPTION
+.sp
+\fBbugpoint\fP narrows down the source of problems in LLVM tools and passes. It
+can be used to debug three types of failures: optimizer crashes, miscompilations
+by optimizers, or bad native code generation (including problems in the static
+and JIT compilers). It aims to reduce large test cases to small, useful ones.
+For more information on the design and inner workings of \fBbugpoint\fP, as well as
+advice for using bugpoint, see \fI\%LLVM bugpoint tool: design and usage\fP in the LLVM
+distribution.
+.SH OPTIONS
+.sp
+\fB\-\-additional\-so\fP \fIlibrary\fP
+.INDENT 0.0
+.INDENT 3.5
+Load the dynamic shared object \fIlibrary\fP into the test program whenever it is
+run. This is useful if you are debugging programs which depend on non\-LLVM
+libraries (such as the X or curses libraries) to run.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-append\-exit\-code\fP=\fI{true,false}\fP
+.INDENT 0.0
+.INDENT 3.5
+Append the test programs exit code to the output file so that a change in exit
+code is considered a test failure. Defaults to false.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-args\fP \fIprogram args\fP
+.INDENT 0.0
+.INDENT 3.5
+Pass all arguments specified after \fB\-\-args\fP to the test program whenever it runs.
+Note that if any of the \fIprogram args\fP start with a \(dq\fB\-\fP\(dq, you should use:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+bugpoint [bugpoint args] \-\-args \-\- [program args]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \(dq\fB\-\-\fP\(dq right after the \fB\-\-args\fP option tells \fBbugpoint\fP to consider
+any options starting with \(dq\fB\-\fP\(dq to be part of the \fB\-\-args\fP option, not as
+options to \fBbugpoint\fP itself.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-tool\-args\fP \fItool args\fP
+.INDENT 0.0
+.INDENT 3.5
+Pass all arguments specified after \fB\-\-tool\-args\fP to the LLVM tool under test
+(\fBllc\fP, \fBlli\fP, etc.) whenever it runs. You should use this option in the
+following way:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+bugpoint [bugpoint args] \-\-tool\-args \-\- [tool args]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \(dq\fB\-\-\fP\(dq right after the \fB\-\-tool\-args\fP option tells \fBbugpoint\fP to
+consider any options starting with \(dq\fB\-\fP\(dq to be part of the \fB\-\-tool\-args\fP
+option, not as options to \fBbugpoint\fP itself. (See \fB\-\-args\fP, above.)
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-safe\-tool\-args\fP \fItool args\fP
+.INDENT 0.0
+.INDENT 3.5
+Pass all arguments specified after \fB\-\-safe\-tool\-args\fP to the \(dqsafe\(dq execution
+tool.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-gcc\-tool\-args\fP \fIgcc tool args\fP
+.INDENT 0.0
+.INDENT 3.5
+Pass all arguments specified after \fB\-\-gcc\-tool\-args\fP to the invocation of
+\fBgcc\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-opt\-args\fP \fIopt args\fP
+.INDENT 0.0
+.INDENT 3.5
+Pass all arguments specified after \fB\-\-opt\-args\fP to the invocation of \fBopt\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-disable\-{dce,simplifycfg}\fP
+.INDENT 0.0
+.INDENT 3.5
+Do not run the specified passes to clean up and reduce the size of the test
+program. By default, \fBbugpoint\fP uses these passes internally when attempting to
+reduce test programs. If you\(aqre trying to find a bug in one of these passes,
+\fBbugpoint\fP may crash.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-enable\-valgrind\fP
+.INDENT 0.0
+.INDENT 3.5
+Use valgrind to find faults in the optimization phase. This will allow
+bugpoint to find otherwise asymptomatic problems caused by memory
+mis\-management.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-find\-bugs\fP
+.INDENT 0.0
+.INDENT 3.5
+Continually randomize the specified passes and run them on the test program
+until a bug is found or the user kills \fBbugpoint\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-help\fP
+.INDENT 0.0
+.INDENT 3.5
+Print a summary of command line options.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-input\fP \fIfilename\fP
+.INDENT 0.0
+.INDENT 3.5
+Open \fIfilename\fP and redirect the standard input of the test program, whenever
+it runs, to come from that file.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-load\fP \fIplugin\fP
+.INDENT 0.0
+.INDENT 3.5
+Load the dynamic object \fIplugin\fP into \fBbugpoint\fP itself. This object should
+register new optimization passes. Once loaded, the object will add new command
+line options to enable various optimizations. To see the new complete list of
+optimizations, use the \fB\-help\fP and \fB\-\-load\fP options together; for example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+bugpoint \-\-load myNewPass.so \-help
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-mlimit\fP \fImegabytes\fP
+.INDENT 0.0
+.INDENT 3.5
+Specifies an upper limit on memory usage of the optimization and codegen. Set
+to zero to disable the limit.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-output\fP \fIfilename\fP
+.INDENT 0.0
+.INDENT 3.5
+Whenever the test program produces output on its standard output stream, it
+should match the contents of \fIfilename\fP (the \(dqreference output\(dq). If you
+do not use this option, \fBbugpoint\fP will attempt to generate a reference output
+by compiling the program with the \(dqsafe\(dq backend and running it.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-run\-{int,jit,llc,custom}\fP
+.INDENT 0.0
+.INDENT 3.5
+Whenever the test program is compiled, \fBbugpoint\fP should generate code for it
+using the specified code generator. These options allow you to choose the
+interpreter, the JIT compiler, the static native code compiler, or a
+custom command (see \fB\-\-exec\-command\fP) respectively.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-safe\-{llc,custom}\fP
+.INDENT 0.0
+.INDENT 3.5
+When debugging a code generator, \fBbugpoint\fP should use the specified code
+generator as the \(dqsafe\(dq code generator. This is a known\-good code generator
+used to generate the \(dqreference output\(dq if it has not been provided, and to
+compile portions of the program that as they are excluded from the testcase.
+These options allow you to choose the
+static native code compiler, or a custom command, (see \fB\-\-exec\-command\fP)
+respectively. The interpreter and the JIT backends cannot currently
+be used as the \(dqsafe\(dq backends.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-exec\-command\fP \fIcommand\fP
+.INDENT 0.0
+.INDENT 3.5
+This option defines the command to use with the \fB\-\-run\-custom\fP and
+\fB\-\-safe\-custom\fP options to execute the bitcode testcase. This can
+be useful for cross\-compilation.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-compile\-command\fP \fIcommand\fP
+.INDENT 0.0
+.INDENT 3.5
+This option defines the command to use with the \fB\-\-compile\-custom\fP
+option to compile the bitcode testcase. The command should exit with a
+failure exit code if the file is \(dqinteresting\(dq and should exit with a
+success exit code (i.e. 0) otherwise (this is the same as if it crashed on
+\(dqinteresting\(dq inputs).
+.sp
+This can be useful for
+testing compiler output without running any link or execute stages. To
+generate a reduced unit test, you may add CHECK directives to the
+testcase and pass the name of an executable compile\-command script in this form:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#!/bin/sh
+llc \(dq$@\(dq
+not FileCheck [bugpoint input file].ll < bugpoint\-test\-program.s
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+This script will \(dqfail\(dq as long as FileCheck passes. So the result
+will be the minimum bitcode that passes FileCheck.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-safe\-path\fP \fIpath\fP
+.INDENT 0.0
+.INDENT 3.5
+This option defines the path to the command to execute with the
+\fB\-\-safe\-{int,jit,llc,custom}\fP
+option.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-verbose\-errors\fP=\fI{true,false}\fP
+.INDENT 0.0
+.INDENT 3.5
+The default behavior of bugpoint is to print \(dq<crash>\(dq when it finds a reduced
+test that crashes compilation. This flag prints the output of the crashing
+program to stderr. This is useful to make sure it is the same error being
+tracked down and not a different error that happens to crash the compiler as
+well. Defaults to false.
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBbugpoint\fP succeeds in finding a problem, it will exit with 0. Otherwise,
+if an error occurs, it will exit with a non\-zero value.
+.SH SEE ALSO
+.sp
+\fBopt(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/clang-format/Makefile b/usr.bin/clang/clang-format/Makefile
new file mode 100644
index 000000000000..8b69ba5294cf
--- /dev/null
+++ b/usr.bin/clang/clang-format/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= clang-format
+MAN=
+
+SRCDIR= clang/tools/clang-format
+SRCS+= ClangFormat.cpp
+
+.include "../clang.prog.mk"
diff --git a/usr.bin/clang/clang-format/Makefile.depend b/usr.bin/clang/clang-format/Makefile.depend
new file mode 100644
index 000000000000..87517ccd6b82
--- /dev/null
+++ b/usr.bin/clang/clang-format/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libclang \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/clang-tblgen/Makefile b/usr.bin/clang/clang-tblgen/Makefile
new file mode 100644
index 000000000000..16ecbf8dc1e0
--- /dev/null
+++ b/usr.bin/clang/clang-tblgen/Makefile
@@ -0,0 +1,31 @@
+PROG_CXX= clang-tblgen
+MAN=
+
+SRCDIR= clang/utils/TableGen
+SRCS+= ASTTableGen.cpp
+SRCS+= ClangASTNodesEmitter.cpp
+SRCS+= ClangASTPropertiesEmitter.cpp
+SRCS+= ClangAttrEmitter.cpp
+SRCS+= ClangBuiltinsEmitter.cpp
+SRCS+= ClangCommentCommandInfoEmitter.cpp
+SRCS+= ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
+SRCS+= ClangCommentHTMLTagsEmitter.cpp
+SRCS+= ClangDataCollectorsEmitter.cpp
+SRCS+= ClangDiagnosticsEmitter.cpp
+SRCS+= ClangOpcodesEmitter.cpp
+SRCS+= ClangOpenCLBuiltinEmitter.cpp
+SRCS+= ClangOptionDocEmitter.cpp
+SRCS+= ClangSACheckersEmitter.cpp
+SRCS+= ClangSyntaxEmitter.cpp
+SRCS+= ClangTypeNodesEmitter.cpp
+SRCS+= MveEmitter.cpp
+SRCS+= NeonEmitter.cpp
+SRCS+= RISCVVEmitter.cpp
+SRCS+= SveEmitter.cpp
+SRCS+= TableGen.cpp
+
+.include "${SRCTOP}/lib/clang/clang.pre.mk"
+
+CFLAGS.RISCVVEmitter.cpp+= -I${CLANG_SRCS}/include
+
+.include "../clang.prog.mk"
diff --git a/usr.bin/clang/clang-tblgen/Makefile.depend b/usr.bin/clang/clang-tblgen/Makefile.depend
new file mode 100644
index 000000000000..336677c3fcb8
--- /dev/null
+++ b/usr.bin/clang/clang-tblgen/Makefile.depend
@@ -0,0 +1,26 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libclang \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/clang-tblgen/Makefile.depend.host b/usr.bin/clang/clang-tblgen/Makefile.depend.host
new file mode 100644
index 000000000000..8127b03d8797
--- /dev/null
+++ b/usr.bin/clang/clang-tblgen/Makefile.depend.host
@@ -0,0 +1,13 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/clang/libclangminimal \
+ lib/clang/libllvmminimal \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/clang.prog.mk b/usr.bin/clang/clang.prog.mk
new file mode 100644
index 000000000000..cf48f02359e9
--- /dev/null
+++ b/usr.bin/clang/clang.prog.mk
@@ -0,0 +1,34 @@
+
+.include "${SRCTOP}/lib/clang/clang.pre.mk"
+
+CFLAGS+= -I${OBJTOP}/lib/clang/libclang
+CFLAGS+= -I${OBJTOP}/lib/clang/libllvm
+
+.include "${SRCTOP}/lib/clang/clang.build.mk"
+
+# Special case for the bootstrap-tools phase.
+.if (defined(TOOLS_PREFIX) || ${MACHINE} == "host") && \
+ ${PROG_CXX} == "clang-tblgen"
+LIBDEPS+= clangminimal
+LIBDEPS+= llvmminimal
+.else
+LIBDEPS+= clang
+LIBDEPS+= llvm
+LIBADD+= z
+LIBADD+= zstd
+.endif
+
+.for lib in ${LIBDEPS}
+DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+.endfor
+
+PACKAGE= clang
+
+.if ${.MAKE.OS} == "FreeBSD" || !defined(BOOTSTRAPPING)
+LIBADD+= execinfo
+LIBADD+= ncursesw
+.endif
+LIBADD+= pthread
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/clang/clang/CC.sh b/usr.bin/clang/clang/CC.sh
new file mode 100755
index 000000000000..8274ed99d2d3
--- /dev/null
+++ b/usr.bin/clang/clang/CC.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# This file is in the public domain.
+exec /usr/bin/c++ "$@"
diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile
new file mode 100644
index 000000000000..50806483b39e
--- /dev/null
+++ b/usr.bin/clang/clang/Makefile
@@ -0,0 +1,31 @@
+.include <src.opts.mk>
+
+PROG_CXX= clang
+
+SRCDIR= clang/tools/driver
+SRCS+= cc1_main.cpp
+SRCS+= cc1as_main.cpp
+SRCS+= cc1gen_reproducer_main.cpp
+SRCS+= clang-driver.cpp
+SRCS+= driver.cpp
+
+LINKS= ${BINDIR}/clang ${BINDIR}/clang++ \
+ ${BINDIR}/clang ${BINDIR}/clang-cpp
+MLINKS= clang.1 clang++.1 \
+ clang.1 clang-cpp.1
+
+SCRIPTS=CC.sh
+SCRIPTSNAME=CC
+
+LINKS+= ${BINDIR}/clang ${BINDIR}/cc \
+ ${BINDIR}/clang ${BINDIR}/c++ \
+ ${BINDIR}/clang ${BINDIR}/cpp
+MLINKS+= clang.1 cc.1 \
+ clang.1 c++.1 \
+ clang.1 CC.1 \
+ clang.1 cpp.1
+
+# Ensure we don't add CFLAGS.clang when using GCC
+NO_TARGET_FLAGS=
+
+.include "../clang.prog.mk"
diff --git a/usr.bin/clang/clang/Makefile.depend b/usr.bin/clang/clang/Makefile.depend
new file mode 100644
index 000000000000..336677c3fcb8
--- /dev/null
+++ b/usr.bin/clang/clang/Makefile.depend
@@ -0,0 +1,26 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libclang \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/clang/clang-driver.cpp b/usr.bin/clang/clang/clang-driver.cpp
new file mode 100644
index 000000000000..bfc1a78f9e0b
--- /dev/null
+++ b/usr.bin/clang/clang/clang-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int clang_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return clang_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/clang/clang.1 b/usr.bin/clang/clang/clang.1
new file mode 100644
index 000000000000..8099bd228799
--- /dev/null
+++ b/usr.bin/clang/clang/clang.1
@@ -0,0 +1,949 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "CLANG" "1" "2023-05-24" "16" "Clang"
+.SH NAME
+clang \- the Clang C, C++, and Objective-C compiler
+.SH SYNOPSIS
+.sp
+\fBclang\fP [\fIoptions\fP] \fIfilename ...\fP
+.SH DESCRIPTION
+.sp
+\fBclang\fP is a C, C++, and Objective\-C compiler which encompasses
+preprocessing, parsing, optimization, code generation, assembly, and linking.
+Depending on which high\-level mode setting is passed, Clang will stop before
+doing a full link. While Clang is highly integrated, it is important to
+understand the stages of compilation, to understand how to invoke it. These
+stages are:
+.INDENT 0.0
+.TP
+.B Driver
+The clang executable is actually a small driver which controls the overall
+execution of other tools such as the compiler, assembler and linker.
+Typically you do not need to interact with the driver, but you
+transparently use it to run the other tools.
+.TP
+.B Preprocessing
+This stage handles tokenization of the input source file, macro expansion,
+#include expansion and handling of other preprocessor directives. The
+output of this stage is typically called a \(dq.i\(dq (for C), \(dq.ii\(dq (for C++),
+\(dq.mi\(dq (for Objective\-C), or \(dq.mii\(dq (for Objective\-C++) file.
+.TP
+.B Parsing and Semantic Analysis
+This stage parses the input file, translating preprocessor tokens into a
+parse tree. Once in the form of a parse tree, it applies semantic
+analysis to compute types for expressions as well and determine whether
+the code is well formed. This stage is responsible for generating most of
+the compiler warnings as well as parse errors. The output of this stage is
+an \(dqAbstract Syntax Tree\(dq (AST).
+.TP
+.B Code Generation and Optimization
+This stage translates an AST into low\-level intermediate code (known as
+\(dqLLVM IR\(dq) and ultimately to machine code. This phase is responsible for
+optimizing the generated code and handling target\-specific code generation.
+The output of this stage is typically called a \(dq.s\(dq file or \(dqassembly\(dq file.
+.sp
+Clang also supports the use of an integrated assembler, in which the code
+generator produces object files directly. This avoids the overhead of
+generating the \(dq.s\(dq file and of calling the target assembler.
+.TP
+.B Assembler
+This stage runs the target assembler to translate the output of the
+compiler into a target object file. The output of this stage is typically
+called a \(dq.o\(dq file or \(dqobject\(dq file.
+.TP
+.B Linker
+This stage runs the target linker to merge multiple object files into an
+executable or dynamic library. The output of this stage is typically called
+an \(dqa.out\(dq, \(dq.dylib\(dq or \(dq.so\(dq file.
+.UNINDENT
+.sp
+\fBClang Static Analyzer\fP
+.sp
+The Clang Static Analyzer is a tool that scans source code to try to find bugs
+through code analysis. This tool uses many parts of Clang and is built into
+the same driver. Please see <\fI\%https://clang\-analyzer.llvm.org\fP> for more details
+on how to use the static analyzer.
+.SH OPTIONS
+.SS Stage Selection Options
+.INDENT 0.0
+.TP
+.B \-E
+Run the preprocessor stage.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fsyntax\-only
+Run the preprocessor, parser and semantic analysis stages.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S
+Run the previous stages as well as LLVM generation and optimization stages
+and target\-specific code generation, producing an assembly file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-c
+Run all of the above, plus the assembler, generating a target \(dq.o\(dq object file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B no stage selection option
+If no stage selection option is specified, all stages above are run, and the
+linker is run to combine the results into an executable or shared library.
+.UNINDENT
+.SS Language Selection and Mode Options
+.INDENT 0.0
+.TP
+.B \-x <language>
+Treat subsequent input files as having type language.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-std=<standard>
+Specify the language standard to compile for.
+.sp
+Supported values for the C language are:
+.INDENT 7.0
+.INDENT 3.5
+.nf
+\fBc89\fP
+\fBc90\fP
+\fBiso9899:1990\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 1990
+.UNINDENT
+.UNINDENT
+.nf
+\fBiso9899:199409\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 1990 with amendment 1
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu89\fP
+\fBgnu90\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 1990 with GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc99\fP
+\fBiso9899:1999\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 1999
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu99\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 1999 with GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc11\fP
+\fBiso9899:2011\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 2011
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu11\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 2011 with GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc17\fP
+\fBiso9899:2017\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 2017
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu17\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C 2017 with GNU extensions
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The default C language standard is \fBgnu17\fP, except on PS4, where it is
+\fBgnu99\fP\&.
+.sp
+Supported values for the C++ language are:
+.INDENT 7.0
+.INDENT 3.5
+.nf
+\fBc++98\fP
+\fBc++03\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 1998 with amendments
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++98\fP
+\fBgnu++03\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 1998 with amendments and GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc++11\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2011 with amendments
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++11\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2011 with amendments and GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc++14\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2014 with amendments
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++14\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2014 with amendments and GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc++17\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2017 with amendments
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++17\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2017 with amendments and GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc++20\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2020 with amendments
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++20\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+ISO C++ 2020 with amendments and GNU extensions
+.UNINDENT
+.UNINDENT
+.nf
+\fBc++2b\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+Working draft for ISO C++ 2023
+.UNINDENT
+.UNINDENT
+.nf
+\fBgnu++2b\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+Working draft for ISO C++ 2023 with GNU extensions
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The default C++ language standard is \fBgnu++17\fP\&.
+.sp
+Supported values for the OpenCL language are:
+.INDENT 7.0
+.INDENT 3.5
+.nf
+\fBcl1.0\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+OpenCL 1.0
+.UNINDENT
+.UNINDENT
+.nf
+\fBcl1.1\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+OpenCL 1.1
+.UNINDENT
+.UNINDENT
+.nf
+\fBcl1.2\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+OpenCL 1.2
+.UNINDENT
+.UNINDENT
+.nf
+\fBcl2.0\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+OpenCL 2.0
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The default OpenCL language standard is \fBcl1.0\fP\&.
+.sp
+Supported values for the CUDA language are:
+.INDENT 7.0
+.INDENT 3.5
+.nf
+\fBcuda\fP
+.fi
+.sp
+.INDENT 0.0
+.INDENT 3.5
+NVIDIA CUDA(tm)
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stdlib=<library>
+Specify the C++ standard library to use; supported options are libstdc++ and
+libc++. If not specified, platform default will be used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-rtlib=<library>
+Specify the compiler runtime library to use; supported options are libgcc and
+compiler\-rt. If not specified, platform default will be used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ansi
+Same as \-std=c89.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ObjC, \-ObjC++
+Treat source input files as Objective\-C and Object\-C++ inputs respectively.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-trigraphs
+Enable trigraphs.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ffreestanding
+Indicate that the file should be compiled for a freestanding, not a hosted,
+environment. Note that it is assumed that a freestanding environment will
+additionally provide \fImemcpy\fP, \fImemmove\fP, \fImemset\fP and \fImemcmp\fP
+implementations, as these are needed for efficient codegen for many programs.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fno\-builtin
+Disable special handling and optimizations of well\-known library functions,
+like \fBstrlen()\fP and \fBmalloc()\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fno\-builtin\-<function>
+Disable special handling and optimizations for the specific library function.
+For example, \fB\-fno\-builtin\-strlen\fP removes any special handling for the
+\fBstrlen()\fP library function.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fno\-builtin\-std\-<function>
+Disable special handling and optimizations for the specific C++ standard
+library function in namespace \fBstd\fP\&. For example,
+\fB\-fno\-builtin\-std\-move_if_noexcept\fP removes any special handling for the
+\fBstd::move_if_noexcept()\fP library function.
+.sp
+For C standard library functions that the C++ standard library also provides
+in namespace \fBstd\fP, use \fI\%\-fno\-builtin\-<function>\fP instead.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fmath\-errno
+Indicate that math functions should be treated as updating \fBerrno\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fpascal\-strings
+Enable support for Pascal\-style strings with \(dq\epfoo\(dq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fms\-extensions
+Enable support for Microsoft extensions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fmsc\-version=
+Set _MSC_VER. Defaults to 1300 on Windows. Not set otherwise.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fborland\-extensions
+Enable support for Borland extensions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fwritable\-strings
+Make all string literals default to writable. This disables uniquing of
+strings and other optimizations.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-flax\-vector\-conversions, \-flax\-vector\-conversions=<kind>, \-fno\-lax\-vector\-conversions
+Allow loose type checking rules for implicit vector conversions.
+Possible values of <kind>:
+.INDENT 7.0
+.IP \(bu 2
+\fBnone\fP: allow no implicit conversions between vectors
+.IP \(bu 2
+\fBinteger\fP: allow implicit bitcasts between integer vectors of the same
+overall bit\-width
+.IP \(bu 2
+\fBall\fP: allow implicit bitcasts between any vectors of the same
+overall bit\-width
+.UNINDENT
+.sp
+<kind> defaults to \fBinteger\fP if unspecified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fblocks
+Enable the \(dqBlocks\(dq language feature.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fobjc\-abi\-version=version
+Select the Objective\-C ABI version to use. Available versions are 1 (legacy
+\(dqfragile\(dq ABI), 2 (non\-fragile ABI 1), and 3 (non\-fragile ABI 2).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fobjc\-nonfragile\-abi\-version=<version>
+Select the Objective\-C non\-fragile ABI version to use by default. This will
+only be used as the Objective\-C ABI when the non\-fragile ABI is enabled
+(either via \fI\%\-fobjc\-nonfragile\-abi\fP, or because it is the platform
+default).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fobjc\-nonfragile\-abi, \-fno\-objc\-nonfragile\-abi
+Enable use of the Objective\-C non\-fragile ABI. On platforms for which this is
+the default ABI, it can be disabled with \fI\%\-fno\-objc\-nonfragile\-abi\fP\&.
+.UNINDENT
+.SS Target Selection Options
+.sp
+Clang fully supports cross compilation as an inherent part of its design.
+Depending on how your version of Clang is configured, it may have support for a
+number of cross compilers, or may only support a native target.
+.INDENT 0.0
+.TP
+.B \-arch <architecture>
+Specify the architecture to build for (Mac OS X specific).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-target <architecture>
+Specify the architecture to build for (all platforms).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mmacosx\-version\-min=<version>
+When building for macOS, specify the minimum version supported by your
+application.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-miphoneos\-version\-min
+When building for iPhone OS, specify the minimum version supported by your
+application.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-supported\-cpus
+Print out a list of supported processors for the given target (specified
+through \fB\-\-target=<architecture>\fP or \fI\%\-arch\fP \fB<architecture>\fP). If no
+target is specified, the system default target will be used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mcpu=?, \-mtune=?
+Acts as an alias for \fI\%\-\-print\-supported\-cpus\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-march=<cpu>
+Specify that Clang should generate code for a specific processor family
+member and later. For example, if you specify \-march=i486, the compiler is
+allowed to generate instructions that are valid on i486 and later processors,
+but which may not exist on earlier ones.
+.UNINDENT
+.SS Code Generation Options
+.INDENT 0.0
+.TP
+.B \-O0, \-O1, \-O2, \-O3, \-Ofast, \-Os, \-Oz, \-Og, \-O, \-O4
+Specify which optimization level to use:
+.INDENT 7.0
+.INDENT 3.5
+\fI\%\-O0\fP Means \(dqno optimization\(dq: this level compiles the fastest and
+generates the most debuggable code.
+.sp
+\fI\%\-O1\fP Somewhere between \fI\%\-O0\fP and \fI\%\-O2\fP\&.
+.sp
+\fI\%\-O2\fP Moderate level of optimization which enables most
+optimizations.
+.sp
+\fI\%\-O3\fP Like \fI\%\-O2\fP, except that it enables optimizations that
+take longer to perform or that may generate larger code (in an attempt to
+make the program run faster).
+.sp
+\fI\%\-Ofast\fP Enables all the optimizations from \fI\%\-O3\fP along
+with other aggressive optimizations that may violate strict compliance with
+language standards.
+.sp
+\fI\%\-Os\fP Like \fI\%\-O2\fP with extra optimizations to reduce code
+size.
+.sp
+\fI\%\-Oz\fP Like \fI\%\-Os\fP (and thus \fI\%\-O2\fP), but reduces code
+size further.
+.sp
+\fI\%\-Og\fP Like \fI\%\-O1\fP\&. In future versions, this option might
+disable different optimizations in order to improve debuggability.
+.sp
+\fI\%\-O\fP Equivalent to \fI\%\-O1\fP\&.
+.sp
+\fI\%\-O4\fP and higher
+.INDENT 0.0
+.INDENT 3.5
+Currently equivalent to \fI\%\-O3\fP
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-g, \-gline\-tables\-only, \-gmodules
+Control debug information output. Note that Clang debug information works
+best at \fI\%\-O0\fP\&. When more than one option starting with \fI\-g\fP is
+specified, the last one wins:
+.INDENT 7.0
+.INDENT 3.5
+\fI\%\-g\fP Generate debug information.
+.sp
+\fI\%\-gline\-tables\-only\fP Generate only line table debug information. This
+allows for symbolicated backtraces with inlining information, but does not
+include any information about variables, their locations or types.
+.sp
+\fI\%\-gmodules\fP Generate debug information that contains external
+references to types defined in Clang modules or precompiled headers instead
+of emitting redundant debug type information into every object file. This
+option transparently switches the Clang module format to object file
+containers that hold the Clang module together with the debug information.
+When compiling a program that uses Clang modules or precompiled headers,
+this option produces complete debug information with faster compile
+times and much smaller object files.
+.sp
+This option should not be used when building static libraries for
+distribution to other machines because the debug info will contain
+references to the module cache on the machine the object files in the
+library were built on.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fstandalone\-debug \-fno\-standalone\-debug
+Clang supports a number of optimizations to reduce the size of debug
+information in the binary. They work based on the assumption that the
+debug type information can be spread out over multiple compilation units.
+For instance, Clang will not emit type definitions for types that are not
+needed by a module and could be replaced with a forward declaration.
+Further, Clang will only emit type info for a dynamic C++ class in the
+module that contains the vtable for the class.
+.sp
+The \fI\%\-fstandalone\-debug\fP option turns off these optimizations.
+This is useful when working with 3rd\-party libraries that don\(aqt come with
+debug information. This is the default on Darwin. Note that Clang will
+never emit type information for types that are not referenced at all by the
+program.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-feliminate\-unused\-debug\-types
+By default, Clang does not emit type information for types that are defined
+but not used in a program. To retain the debug info for these unused types,
+the negation \fB\-fno\-eliminate\-unused\-debug\-types\fP can be used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fexceptions
+Enable generation of unwind information. This allows exceptions to be thrown
+through Clang compiled stack frames. This is on by default in x86\-64.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ftrapv
+Generate code to catch integer overflow errors. Signed integer overflow is
+undefined in C. With this flag, extra code is generated to detect this and
+abort when it happens.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fvisibility
+This flag sets the default visibility level.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fcommon, \-fno\-common
+This flag specifies that variables without initializers get common linkage.
+It can be disabled with \fI\%\-fno\-common\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ftls\-model=<model>
+Set the default thread\-local storage (TLS) model to use for thread\-local
+variables. Valid values are: \(dqglobal\-dynamic\(dq, \(dqlocal\-dynamic\(dq,
+\(dqinitial\-exec\(dq and \(dqlocal\-exec\(dq. The default is \(dqglobal\-dynamic\(dq. The default
+model can be overridden with the tls_model attribute. The compiler will try
+to choose a more efficient model if possible.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-flto, \-flto=full, \-flto=thin, \-emit\-llvm
+Generate output files in LLVM formats, suitable for link time optimization.
+When used with \fI\%\-S\fP this generates LLVM intermediate language
+assembly files, otherwise this generates LLVM bitcode format object files
+(which may be passed to the linker depending on the stage selection options).
+.sp
+The default for \fI\%\-flto\fP is \(dqfull\(dq, in which the
+LLVM bitcode is suitable for monolithic Link Time Optimization (LTO), where
+the linker merges all such modules into a single combined module for
+optimization. With \(dqthin\(dq, \fI\%ThinLTO\fP
+compilation is invoked instead.
+.sp
+\fBNOTE:\fP
+.INDENT 7.0
+.INDENT 3.5
+On Darwin, when using \fI\%\-flto\fP along with \fI\%\-g\fP and
+compiling and linking in separate steps, you also need to pass
+\fB\-Wl,\-object_path_lto,<lto\-filename>.o\fP at the linking step to instruct the
+ld64 linker not to delete the temporary object file generated during Link
+Time Optimization (this flag is automatically passed to the linker by Clang
+if compilation and linking are done in a single step). This allows debugging
+the executable as well as generating the \fB\&.dSYM\fP bundle using \fBdsymutil(1)\fP\&.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Driver Options
+.INDENT 0.0
+.TP
+.B \-###
+Print (but do not run) the commands to run for this compilation.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Display available options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Qunused\-arguments
+Do not emit any warnings for unused driver arguments.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Wa,<args>
+Pass the comma separated arguments in args to the assembler.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Wl,<args>
+Pass the comma separated arguments in args to the linker.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Wp,<args>
+Pass the comma separated arguments in args to the preprocessor.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Xanalyzer <arg>
+Pass arg to the static analyzer.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Xassembler <arg>
+Pass arg to the assembler.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Xlinker <arg>
+Pass arg to the linker.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Xpreprocessor <arg>
+Pass arg to the preprocessor.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <file>
+Write output to file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-file\-name=<file>
+Print the full library path of file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-libgcc\-file\-name
+Print the library path for the currently used compiler runtime library
+(\(dqlibgcc.a\(dq or \(dqlibclang_rt.builtins.*.a\(dq).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-prog\-name=<name>
+Print the full program path of name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-search\-dirs
+Print the paths used for finding libraries and programs.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-save\-temps
+Save intermediate compilation results.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-save\-stats, \-save\-stats=cwd, \-save\-stats=obj
+Save internal code generation (LLVM) statistics to a file in the current
+directory (\fI\%\-save\-stats\fP/\(dq\-save\-stats=cwd\(dq) or the directory
+of the output file (\(dq\-save\-state=obj\(dq).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-integrated\-as, \-no\-integrated\-as
+Used to enable and disable, respectively, the use of the integrated
+assembler. Whether the integrated assembler is on by default is target
+dependent.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-time
+Time individual commands.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ftime\-report
+Print timing summary of each stage of compilation.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v
+Show commands to run and use verbose output.
+.UNINDENT
+.SS Diagnostics Options
+.INDENT 0.0
+.TP
+.B \-fshow\-column, \-fshow\-source\-location, \-fcaret\-diagnostics, \-fdiagnostics\-fixit\-info, \-fdiagnostics\-parseable\-fixits, \-fdiagnostics\-print\-source\-range\-info, \-fprint\-source\-range\-info, \-fdiagnostics\-show\-option, \-fmessage\-length
+These options control how Clang prints out information about diagnostics
+(errors and warnings). Please see the Clang User\(aqs Manual for more information.
+.UNINDENT
+.SS Preprocessor Options
+.INDENT 0.0
+.TP
+.B \-D<macroname>=<value>
+Adds an implicit #define into the predefines buffer which is read before the
+source file is preprocessed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-U<macroname>
+Adds an implicit #undef into the predefines buffer which is read before the
+source file is preprocessed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-include <filename>
+Adds an implicit #include into the predefines buffer which is read before the
+source file is preprocessed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-I<directory>
+Add the specified directory to the search path for include files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-F<directory>
+Add the specified directory to the search path for framework include files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-nostdinc
+Do not search the standard system directories or compiler builtin directories
+for include files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-nostdlibinc
+Do not search the standard system directories for include files, but do
+search compiler builtin include directories.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-nobuiltininc
+Do not search clang\(aqs builtin directory for include files.
+.UNINDENT
+.SH ENVIRONMENT
+.INDENT 0.0
+.TP
+.B TMPDIR, TEMP, TMP
+These environment variables are checked, in order, for the location to write
+temporary files used during the compilation process.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B CPATH
+If this environment variable is present, it is treated as a delimited list of
+paths to be added to the default system include path list. The delimiter is
+the platform dependent delimiter, as used in the PATH environment variable.
+.sp
+Empty components in the environment variable are ignored.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B C_INCLUDE_PATH, OBJC_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJCPLUS_INCLUDE_PATH
+These environment variables specify additional paths, as for \fI\%CPATH\fP, which are
+only used when processing the appropriate language.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B MACOSX_DEPLOYMENT_TARGET
+If \fI\%\-mmacosx\-version\-min\fP is unspecified, the default deployment
+target is read from this environment variable. This option only affects
+Darwin targets.
+.UNINDENT
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/issues/\fP>. Most bug reports should
+include preprocessed source files (use the \fI\%\-E\fP option) and the full
+output of the compiler, along with information to reproduce.
+.SH SEE ALSO
+.sp
+\fBas(1)\fP, \fBld(1)\fP
+.SH AUTHOR
+Maintained by the Clang / LLVM Team (<http://clang.llvm.org>)
+.SH COPYRIGHT
+2007-2023, The Clang Team
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llc/Makefile b/usr.bin/clang/llc/Makefile
new file mode 100644
index 000000000000..ed5c80907920
--- /dev/null
+++ b/usr.bin/clang/llc/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llc
+
+SRCDIR= llvm/tools/llc
+SRCS+= NewPMDriver.cpp
+SRCS+= llc.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llc/Makefile.depend b/usr.bin/clang/llc/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llc/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llc/llc.1 b/usr.bin/clang/llc/llc.1
new file mode 100644
index 000000000000..1dfef564fcd6
--- /dev/null
+++ b/usr.bin/clang/llc/llc.1
@@ -0,0 +1,295 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLC" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llc \- LLVM static compiler
+.SH SYNOPSIS
+.sp
+\fBllc\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+The \fBllc\fP command compiles LLVM source inputs into assembly language
+for a specified architecture. The assembly language output can then be passed
+through a native assembler and linker to generate a native executable.
+.sp
+The choice of architecture for the output assembly code is automatically
+determined from the input file, unless the \fI\%\-march\fP option is used to
+override the default.
+.SH OPTIONS
+.sp
+If \fBfilename\fP is \(dq\fB\-\fP\(dq or omitted, \fBllc\fP reads from standard input.
+Otherwise, it will read from \fBfilename\fP\&. Inputs can be in either the LLVM
+assembly language format (\fB\&.ll\fP) or the LLVM bitcode format (\fB\&.bc\fP).
+.sp
+If the \fI\%\-o\fP option is omitted, then \fBllc\fP will send its output
+to standard output if the input is from standard input. If the \fI\%\-o\fP
+option specifies \(dq\fB\-\fP\(dq, then the output will also be sent to standard output.
+.sp
+If no \fI\%\-o\fP option is specified and an input file other than \(dq\fB\-\fP\(dq is
+specified, then \fBllc\fP creates the output filename by taking the input
+filename, removing any existing \fB\&.bc\fP extension, and adding a \fB\&.s\fP suffix.
+.sp
+Other \fBllc\fP options are described below.
+.SS End\-user Options
+.INDENT 0.0
+.TP
+.B \-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <filename>
+Use \fB<filename>\fP as the output filename. See the summary above for more
+details.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-O=uint
+Generate code at different optimization levels. These correspond to the
+\fB\-O0\fP, \fB\-O1\fP, \fB\-O2\fP, and \fB\-O3\fP optimization levels used by
+\fBclang\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mtriple=<target triple>
+Override the target triple specified in the input file with the specified
+string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-march=<arch>
+Specify the architecture for which to generate assembly, overriding the target
+encoded in the input file. See the output of \fBllc \-help\fP for a list of
+valid architectures. By default this is inferred from the target triple or
+autodetected to the current architecture.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mcpu=<cpuname>
+Specify a specific chip in the current architecture to generate code for.
+By default this is inferred from the target triple and autodetected to
+the current architecture. For a list of available CPUs, use:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+llvm\-as < /dev/null | llc \-march=xyz \-mcpu=help
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-filetype=<output file type>
+Specify what kind of output \fBllc\fP should generated. Options are: \fBasm\fP
+for textual assembly ( \fB\(aq.s\(aq\fP), \fBobj\fP for native object files (\fB\(aq.o\(aq\fP)
+and \fBnull\fP for not emitting anything (for performance testing).
+.sp
+Note that not all targets support all options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mattr=a1,+a2,\-a3,...
+Override or control specific attributes of the target, such as whether SIMD
+operations are enabled or not. The default set of attributes is set by the
+current CPU. For a list of available attributes, use:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+llvm\-as < /dev/null | llc \-march=xyz \-mattr=help
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-frame\-pointer
+Specify effect of frame pointer elimination optimization (all,non\-leaf,none).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-disable\-excess\-fp\-precision
+Disable optimizations that may produce excess precision for floating point.
+Note that this option can dramatically slow down code on some systems
+(e.g. X86).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-no\-infs\-fp\-math
+Enable optimizations that assume no Inf values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-no\-nans\-fp\-math
+Enable optimizations that assume no NAN values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-no\-signed\-zeros\-fp\-math
+Enable FP math optimizations that assume the sign of 0 is insignificant.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-no\-trapping\-fp\-math
+Enable setting the FP exceptions build attribute not to use exceptions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-unsafe\-fp\-math
+Enable optimizations that make unsafe assumptions about IEEE math (e.g. that
+addition is associative) or may not work for all input ranges. These
+optimizations allow the code generator to make use of some instructions which
+would otherwise not be usable (such as \fBfsin\fP on X86).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stats
+Print statistics recorded by code\-generation passes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-time\-passes
+Record the amount of time needed for each pass and print a report to standard
+error.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-load=<dso_path>
+Dynamically load \fBdso_path\fP (a path to a dynamically shared object) that
+implements an LLVM target. This will permit the target name to be used with
+the \fI\%\-march\fP option so that code can be generated for that target.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-meabi=[default|gnu|4|5]
+Specify which EABI version should conform to. Valid EABI versions are \fIgnu\fP,
+\fI4\fP and \fI5\fP\&. Default value (\fIdefault\fP) depends on the triple.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stack\-size\-section
+Emit the .stack_sizes section which contains stack size metadata. The section
+contains an array of pairs of function symbol values (pointer size) and stack
+sizes (unsigned LEB128). The stack size values only include the space allocated
+in the function prologue. Functions with dynamic stack allocations are not
+included.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-remarks\-section
+Emit the __remarks (MachO) section which contains metadata about remark
+diagnostics.
+.UNINDENT
+.SS Tuning/Configuration Options
+.INDENT 0.0
+.TP
+.B \-\-print\-after\-isel
+Print generated machine code after instruction selection (useful for debugging).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-regalloc=<allocator>
+Specify the register allocator to use.
+Valid register allocators are:
+.sp
+\fIbasic\fP
+.INDENT 7.0
+.INDENT 3.5
+Basic register allocator.
+.UNINDENT
+.UNINDENT
+.sp
+\fIfast\fP
+.INDENT 7.0
+.INDENT 3.5
+Fast register allocator. It is the default for unoptimized code.
+.UNINDENT
+.UNINDENT
+.sp
+\fIgreedy\fP
+.INDENT 7.0
+.INDENT 3.5
+Greedy register allocator. It is the default for optimized code.
+.UNINDENT
+.UNINDENT
+.sp
+\fIpbqp\fP
+.INDENT 7.0
+.INDENT 3.5
+Register allocator based on \(aqPartitioned Boolean Quadratic Programming\(aq.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-spiller=<spiller>
+Specify the spiller to use for register allocators that support it. Currently
+this option is used only by the linear scan register allocator. The default
+\fBspiller\fP is \fIlocal\fP\&. Valid spillers are:
+.sp
+\fIsimple\fP
+.INDENT 7.0
+.INDENT 3.5
+Simple spiller
+.UNINDENT
+.UNINDENT
+.sp
+\fIlocal\fP
+.INDENT 7.0
+.INDENT 3.5
+Local spiller
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Intel IA\-32\-specific Options
+.INDENT 0.0
+.TP
+.B \-\-x86\-asm\-syntax=[att|intel]
+Specify whether to emit assembly code in AT&T syntax (the default) or Intel
+syntax.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllc\fP succeeds, it will exit with 0. Otherwise, if an error
+occurs, it will exit with a non\-zero value.
+.SH SEE ALSO
+.sp
+\fBlli(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/lld/Makefile b/usr.bin/clang/lld/Makefile
new file mode 100644
index 000000000000..1c99bd716069
--- /dev/null
+++ b/usr.bin/clang/lld/Makefile
@@ -0,0 +1,109 @@
+.include <src.opts.mk>
+
+LLVM_BASE= ${SRCTOP}/contrib/llvm-project
+LLVM_SRCS= ${LLVM_BASE}/llvm
+LLD_SRCS= ${LLVM_BASE}/lld
+
+PACKAGE= lld
+PROG_CXX= ld.lld
+# Man page directory
+.PATH: ${LLD_SRCS}/docs
+.if !defined(TOOLS_PREFIX) || \
+ (defined(TOOLS_PREFIX) && ${MK_LLD_BOOTSTRAP} != "no")
+SYMLINKS= ${PROG_CXX} ${BINDIR}/ld
+MLINKS= ld.lld.1 ld.1
+.endif
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${LLD_SRCS}/ELF
+CFLAGS+= -I${LLD_SRCS}/include
+CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${OBJTOP}/lib/clang/libllvm
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib
+
+SRCDIR= lld
+SRCS+= Common/Args.cpp
+SRCS+= Common/CommonLinkerContext.cpp
+SRCS+= Common/DWARF.cpp
+SRCS+= Common/DriverDispatcher.cpp
+SRCS+= Common/ErrorHandler.cpp
+SRCS+= Common/Filesystem.cpp
+SRCS+= Common/Memory.cpp
+SRCS+= Common/Reproduce.cpp
+SRCS+= Common/Strings.cpp
+SRCS+= Common/TargetOptionsCommandFlags.cpp
+SRCS+= Common/Version.cpp
+SRCS+= ELF/AArch64ErrataFix.cpp
+SRCS+= ELF/ARMErrataFix.cpp
+SRCS+= ELF/Arch/AArch64.cpp
+SRCS+= ELF/Arch/AMDGPU.cpp
+SRCS+= ELF/Arch/ARM.cpp
+SRCS+= ELF/Arch/AVR.cpp
+SRCS+= ELF/Arch/Hexagon.cpp
+SRCS+= ELF/Arch/LoongArch.cpp
+SRCS+= ELF/Arch/MSP430.cpp
+SRCS+= ELF/Arch/Mips.cpp
+SRCS+= ELF/Arch/MipsArchTree.cpp
+SRCS+= ELF/Arch/PPC.cpp
+SRCS+= ELF/Arch/PPC64.cpp
+SRCS+= ELF/Arch/RISCV.cpp
+SRCS+= ELF/Arch/SPARCV9.cpp
+SRCS+= ELF/Arch/SystemZ.cpp
+SRCS+= ELF/Arch/X86.cpp
+SRCS+= ELF/Arch/X86_64.cpp
+SRCS+= ELF/CallGraphSort.cpp
+SRCS+= ELF/DWARF.cpp
+SRCS+= ELF/Driver.cpp
+SRCS+= ELF/DriverUtils.cpp
+SRCS+= ELF/EhFrame.cpp
+SRCS+= ELF/ICF.cpp
+SRCS+= ELF/InputFiles.cpp
+SRCS+= ELF/InputSection.cpp
+SRCS+= ELF/LTO.cpp
+SRCS+= ELF/LinkerScript.cpp
+SRCS+= ELF/MapFile.cpp
+SRCS+= ELF/MarkLive.cpp
+SRCS+= ELF/OutputSections.cpp
+SRCS+= ELF/Relocations.cpp
+SRCS+= ELF/ScriptLexer.cpp
+SRCS+= ELF/ScriptParser.cpp
+SRCS+= ELF/SymbolTable.cpp
+SRCS+= ELF/Symbols.cpp
+SRCS+= ELF/SyntheticSections.cpp
+SRCS+= ELF/Target.cpp
+SRCS+= ELF/Thunks.cpp
+SRCS+= ELF/Writer.cpp
+SRCS+= lld-driver.cpp
+SRCS+= tools/lld/lld.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.build.mk"
+
+LIBDEPS+= llvm
+
+.for lib in ${LIBDEPS}
+DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+.endfor
+
+INCFILE= Options.inc
+TDFILE= ${LLD_SRCS}/ELF/Options.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.if ${.MAKE.OS} == "FreeBSD" || !defined(BOOTSTRAPPING)
+LIBADD+= execinfo
+LIBADD+= tinfow
+.endif
+LIBADD+= pthread
+LIBADD+= z
+LIBADD+= zstd
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/clang/lld/Makefile.depend b/usr.bin/clang/lld/Makefile.depend
new file mode 100644
index 000000000000..006fa45dd459
--- /dev/null
+++ b/usr.bin/clang/lld/Makefile.depend
@@ -0,0 +1,25 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-tblgen.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/lld/lld-driver.cpp b/usr.bin/clang/lld/lld-driver.cpp
new file mode 100644
index 000000000000..eec634de3c7f
--- /dev/null
+++ b/usr.bin/clang/lld/lld-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int lld_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return lld_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/lldb-server/Makefile b/usr.bin/clang/lldb-server/Makefile
new file mode 100644
index 000000000000..b4d6131d81ab
--- /dev/null
+++ b/usr.bin/clang/lldb-server/Makefile
@@ -0,0 +1,53 @@
+.include "${SRCTOP}/lib/clang/lldb.pre.mk"
+
+PACKAGE= lldb
+PROG_CXX= lldb-server
+
+CFLAGS+= -I${LLDB_SRCS}/include
+CFLAGS+= -I${LLDB_SRCS}/source
+CFLAGS+= -I${.OBJDIR}
+
+SRCDIR= lldb/tools/lldb-server
+
+SRCS+= Acceptor.cpp
+SRCS+= LLDBServerUtilities.cpp
+SRCS+= SystemInitializerLLGS.cpp
+SRCS+= lldb-gdbserver.cpp
+SRCS+= lldb-platform.cpp
+SRCS+= lldb-server.cpp
+
+.include "${SRCTOP}/lib/clang/clang.build.mk"
+
+LIBDEPS+= lldb
+LIBDEPS+= clang
+LIBDEPS+= llvm
+
+.for lib in ${LIBDEPS}
+DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+.endfor
+
+INCFILE= LLGSOptions.inc
+TDFILE= ${LLDB_SRCS}/tools/lldb-server/LLGSOptions.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LIBADD+= tinfow
+LIBADD+= edit
+LIBADD+= execinfo
+LIBADD+= lua
+LIBADD+= lzma
+LIBADD+= ncursesw
+LIBADD+= panel
+LIBADD+= pthread
+LIBADD+= z
+LIBADD+= zstd
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/clang/lldb-server/Makefile.depend b/usr.bin/clang/lldb-server/Makefile.depend
new file mode 100644
index 000000000000..16db985d2ae3
--- /dev/null
+++ b/usr.bin/clang/lldb-server/Makefile.depend
@@ -0,0 +1,32 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libclang \
+ lib/clang/liblldb \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libedit \
+ lib/libexecinfo \
+ lib/liblua \
+ lib/liblzma \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/ncurses \
+ lib/ncurses/panel \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-tblgen.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/lldb-server/lldb-server.1 b/usr.bin/clang/lldb-server/lldb-server.1
new file mode 100644
index 000000000000..439d9d32966b
--- /dev/null
+++ b/usr.bin/clang/lldb-server/lldb-server.1
@@ -0,0 +1,261 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLDB-SERVER" "1" "2021-06-07" "12" "LLDB"
+.SH NAME
+lldb-server \- LLDB Documentation
+.SH SYNOPSIS
+.nf
+\fBlldb\-server\fP v[ersion]
+\fBlldb\-server\fP g[dbserver] [\fIoptions\fP]
+\fBlldb\-server\fP p[latform] [\fIoptions\fP]
+.fi
+.sp
+.SH DESCRIPTION
+.sp
+\fBlldb\-server\fP provides the server counterpart of the LLVM debugger.
+The server runs and monitors the debugged program, while the user interfaces
+with it via a client, either running locally or connecting remotely.
+.sp
+All of the code in the LLDB project is available under the Apache 2.0 License
+with LLVM exceptions.
+.SH COMMANDS
+.sp
+The first argument to lldb\-server specifies a command to run.
+.INDENT 0.0
+.TP
+.B v[ersion]
+Prints lldb\-server version and exits.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B g[dbserver]
+Runs the server using the gdb\-remote protocol. LLDB can afterwards
+connect to the server using \fIgdb\-remote\fP command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B p[latform]
+Runs the platform server. LLDB can afterwards connect to the server using
+\fIplatform select\fP, followed by \fIplatform connect\fP\&.
+.UNINDENT
+.SH GDBSERVER COMMAND
+.nf
+\fBlldb\-server\fP g[dbserver] [\fIoptions\fP] [[\fIhost\fP]:\fIport\fP] [[\-\-] \fIprogram\fP \fIargs\fP\&...]
+.fi
+.sp
+.SS CONNECTION
+.INDENT 0.0
+.TP
+.B host:port
+Specifies the hostname and TCP port to listen on. Obligatory unless another
+listening option is used. If host is empty, \fIlocalhost\fP will be used. If port
+is zero, a random port will be selected, and written as specified by \-\-pipe
+or \-\-named\-pipe options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-fd <fd>
+Communicate over the given file descriptor instead of sockets.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-named\-pipe <name>
+Write the listening port number to the specified named pipe.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-pipe <fd>
+Write the listening port number to the specified pipe (fd).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-reverse\-connect
+Connect to the client instead of passively waiting for a connection. In this
+case, [host]:port denotes the remote address to connect to.
+.UNINDENT
+.SS GENERAL OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-help
+Prints out the usage information and exits.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-log\-channels <channel1 categories...:channel2 categories...>
+Channels to log. A colon\-separated list of entries. Each entry starts with
+a channel followed by a space\-separated list of categories.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-log\-file <file>
+Destination file to log to. If empty, log to stderr.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-setsid
+Run lldb\-server in a new session.
+.UNINDENT
+.SS TARGET SELECTION
+.INDENT 0.0
+.TP
+.B \-\-attach <pid\-or\-name>
+Attach to the process given by a (numeric) process id or a name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\- program args
+Launch a program for debugging.
+.UNINDENT
+.sp
+If neither of target options are used, \fBlldb\-server\fP is started
+without a specific target. It can be afterwards instructed by the client
+to launch or attach.
+.SH PLATFORM COMMAND
+.nf
+\fBlldb\-server\fP p[latform] [\fIoptions\fP] \-\-server \-\-listen [[\fIhost\fP]:\fIport\fP]
+.fi
+.sp
+.SS CONNECTION
+.INDENT 0.0
+.TP
+.B \-\-server
+Run in server mode, handling multiple connections. If this is not specified,
+lldb\-server will accept only one connection and exit when it is finished.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-listen <host>:<port>
+Hostname and port to listen on. Obligatory. If \fIport\fP is zero, a random port
+will be used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-socket\-file <path>
+Write the listening socket port number to the specified file.
+.UNINDENT
+.SS GENERAL OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-log\-channels <channel1 categories...:channel2 categories...>
+Channels to log. A colon\-separated list of entries. Each entry starts with
+a channel followed by a space\-separated list of categories.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-log\-file <file>
+Destination file to log to. If empty, log to stderr.
+.UNINDENT
+.SS GDB\-SERVER CONNECTIONS
+.INDENT 0.0
+.TP
+.B \-\-gdbserver\-port <port>
+Define a port to be used for gdb\-server connections. Can be specified multiple
+times to allow multiple ports. Has no effect if \-\-min\-gdbserver\-port
+and \-\-max\-gdbserver\-port are specified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-min\-gdbserver\-port <port>
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-max\-gdbserver\-port <port>
+Specify the range of ports that can be used for gdb\-server connections. Both
+options need to be specified simultaneously. Overrides \-\-gdbserver\-port.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-port\-offset <offset>
+Add the specified offset to port numbers returned by server. This is useful
+if the server is running behind a firewall, and a range of ports is redirected
+to it with an offset.
+.UNINDENT
+.SH EXAMPLES
+.sp
+The server can be started in several modes.
+.sp
+In order to launch a new process inside the debugger, pass the path to it
+and the arguments to the debugged executable as positional arguments.
+To disambiguate between arguments passed to lldb and arguments passed
+to the debugged executable, arguments starting with a \- must be passed after
+\-\-. The server will launch the new executable and stop it immediately, waiting
+for the client to connect.
+.INDENT 0.0
+.INDENT 3.5
+lldb\-server g :1234 /path/to/program program\-argument \-\- \-\-program\-option
+.UNINDENT
+.UNINDENT
+.sp
+For convenience, passing the executable after \-\- is also supported.
+.INDENT 0.0
+.INDENT 3.5
+lldb\-server g :1234 \-\- /path/to/program program\-argument \-\-program\-option
+.UNINDENT
+.UNINDENT
+.sp
+In order to attach to a running process, pass \-\-attach along with the process
+identifier or name. The process will be stopped immediately after starting
+the server. Note that terminating the server will usually cause the process
+to be detached and continue execution.
+.INDENT 0.0
+.INDENT 3.5
+lldb\-server g :1234 \-\-attach 12345
+lldb\-server g :1234 \-\-attach program\-name
+.UNINDENT
+.UNINDENT
+.sp
+Use \fIgdb\-remote\fP command to connect to the server:
+.INDENT 0.0
+.INDENT 3.5
+(lldb) gdb\-remote 1234
+.UNINDENT
+.UNINDENT
+.sp
+lldb\-server can also be started without an inferior. In this case, the client
+can select the target after connecting to the server. Note that some commands
+(e.g. \fItarget create\fP) will disconnect and launch a local lldb\-server instead.
+.INDENT 0.0
+.INDENT 3.5
+lldb\-server g :1234
+.sp
+(lldb) gdb\-remote 1234
+(lldb) process launch a.out
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+The LLDB project page \fI\%https://lldb.llvm.org\fP has many different resources
+for \fBlldb\-server\fP users.
+.SH AUTHOR
+LLVM project
+.SH COPYRIGHT
+2007-2021, The LLDB Team
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/lldb-tblgen/Makefile b/usr.bin/clang/lldb-tblgen/Makefile
new file mode 100644
index 000000000000..2a069939e195
--- /dev/null
+++ b/usr.bin/clang/lldb-tblgen/Makefile
@@ -0,0 +1,10 @@
+PROG_CXX= lldb-tblgen
+MAN=
+
+SRCDIR= lldb/utils/TableGen
+SRCS+= LLDBOptionDefEmitter.cpp
+SRCS+= LLDBPropertyDefEmitter.cpp
+SRCS+= LLDBTableGen.cpp
+SRCS+= LLDBTableGenUtils.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/lldb-tblgen/Makefile.depend b/usr.bin/clang/lldb-tblgen/Makefile.depend
new file mode 100644
index 000000000000..e41a35dcde12
--- /dev/null
+++ b/usr.bin/clang/lldb-tblgen/Makefile.depend
@@ -0,0 +1,11 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/clang/libllvmminimal \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/lldb/Makefile b/usr.bin/clang/lldb/Makefile
new file mode 100644
index 000000000000..4f01b1d8f0e0
--- /dev/null
+++ b/usr.bin/clang/lldb/Makefile
@@ -0,0 +1,47 @@
+.include "${SRCTOP}/lib/clang/lldb.pre.mk"
+
+PACKAGE= lldb
+PROG_CXX= lldb
+
+CFLAGS+= -I${LLDB_SRCS}/include
+CFLAGS+= -I${.OBJDIR}
+
+SRCDIR= lldb/tools/driver
+SRCS+= Driver.cpp
+
+.include "${SRCTOP}/lib/clang/clang.build.mk"
+
+LIBDEPS+= lldb
+LIBDEPS+= clang
+LIBDEPS+= llvm
+
+.for lib in ${LIBDEPS}
+DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+.endfor
+
+INCFILE= Options.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Options.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LIBADD= tinfow
+LIBADD+= edit
+LIBADD+= execinfo
+LIBADD+= kvm
+LIBADD+= lua
+LIBADD+= lzma
+LIBADD+= ncursesw
+LIBADD+= panelw
+LIBADD+= pthread
+LIBADD+= z
+LIBADD+= zstd
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/clang/lldb/Makefile.depend b/usr.bin/clang/lldb/Makefile.depend
new file mode 100644
index 000000000000..a395caaea392
--- /dev/null
+++ b/usr.bin/clang/lldb/Makefile.depend
@@ -0,0 +1,33 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libclang \
+ lib/clang/liblldb \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libedit \
+ lib/libexecinfo \
+ lib/libkvm \
+ lib/liblua \
+ lib/liblzma \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/ncurses \
+ lib/ncurses/panel \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-tblgen.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/lldb/lldb.1 b/usr.bin/clang/lldb/lldb.1
new file mode 100644
index 000000000000..15fe1476528a
--- /dev/null
+++ b/usr.bin/clang/lldb/lldb.1
@@ -0,0 +1,429 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLDB" "1" "2021-06-07" "12" "LLDB"
+.SH NAME
+lldb \- LLDB Documentation
+.SH SYNOPSIS
+.nf
+\fBlldb\fP [\fIoptions\fP] \fIexecutable\fP
+.fi
+.sp
+.SH DESCRIPTION
+.sp
+\fBlldb\fP is a next generation, high\-performance debugger. It is built as
+a set of reusable components which highly leverage existing libraries in the
+larger LLVM Project, such as the Clang expression parser and LLVM disassembler.
+.sp
+\fBlldb\fP is the default debugger in Xcode on macOS and supports
+debugging C, Objective\-C and C++ on the desktop and iOS devices and simulator.
+.sp
+All of the code in the LLDB project is available under the Apache 2.0 License
+with LLVM exceptions.
+.SH ATTACHING
+.INDENT 0.0
+.TP
+.B \-\-attach\-name <name>
+Tells the debugger to attach to a process with the given name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-attach\-pid <pid>
+Tells the debugger to attach to a process with the given pid.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-n <value>
+Alias for \-\-attach\-name
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-p <value>
+Alias for \-\-attach\-pid
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-wait\-for
+Tells the debugger to wait for a process with the given pid or name to launch before attaching.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-w
+Alias for \-\-wait\-for
+.UNINDENT
+.SH COMMANDS
+.INDENT 0.0
+.TP
+.B \-\-batch
+Tells the debugger to run the commands from \-s, \-S, \-o & \-O, and then quit.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-b
+Alias for \-\-batch
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-K <value>
+Alias for \-\-source\-on\-crash
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-k <value>
+Alias for \-\-one\-line\-on\-crash
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-local\-lldbinit
+Allow the debugger to parse the .lldbinit files in the current working directory, unless \-\-no\-lldbinit is passed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-lldbinit
+Do not automatically parse any \(aq.lldbinit\(aq files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-one\-line\-before\-file <command>
+Tells the debugger to execute this one\-line lldb command before any file provided on the command line has been loaded.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-one\-line\-on\-crash <command>
+When in batch mode, tells the debugger to run this one\-line lldb command if the target crashes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-one\-line <command>
+Tells the debugger to execute this one\-line lldb command after any file provided on the command line has been loaded.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-O <value>
+Alias for \-\-one\-line\-before\-file
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <value>
+Alias for \-\-one\-line
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Q
+Alias for \-\-source\-quietly
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-source\-before\-file <file>
+Tells the debugger to read in and execute the lldb commands in the given file, before any file has been loaded.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-source\-on\-crash <file>
+When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-source\-quietly
+Tells the debugger to execute this one\-line lldb command before any file has been loaded.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-source <file>
+Tells the debugger to read in and execute the lldb commands in the given file, after any file has been loaded.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S <value>
+Alias for \-\-source\-before\-file
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-s <value>
+Alias for \-\-source
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x
+Alias for \-\-no\-lldbinit
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-arch <architecture>
+Tells the debugger to use the specified architecture when starting and running the program.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-a <value>
+Alias for \-\-arch
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-capture\-path <filename>
+Tells the debugger to use the given filename for the reproducer.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-capture
+Tells the debugger to capture a reproducer.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-core <filename>
+Tells the debugger to use the full path to <filename> as the core file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-c <value>
+Alias for \-\-core
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug
+Tells the debugger to print out extra information for debugging itself.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-d
+Alias for \-\-debug
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-editor
+Tells the debugger to open source files using the host\(aqs "external editor" mechanism.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-e
+Alias for \-\-editor
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-file <filename>
+Tells the debugger to use the file <filename> as the program to be debugged.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-f <value>
+Alias for \-\-file
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Prints out the usage information for the LLDB debugger.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-h
+Alias for \-\-help
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-use\-colors
+Do not use colors.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-replay <filename>
+Tells the debugger to replay a reproducer from <filename>.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Prints out the current version number of the LLDB debugger.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v
+Alias for \-\-version
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-X
+Alias for \-\-no\-use\-color
+.UNINDENT
+.SH REPL
+.INDENT 0.0
+.TP
+.B \-r=<flags>
+Alias for \-\-repl=<flags>
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-repl\-language <language>
+Chooses the language for the REPL.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-repl=<flags>
+Runs lldb in REPL mode with a stub process with the given flags.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-R <value>
+Alias for \-\-repl\-language
+.UNINDENT
+.SH SCRIPTING
+.INDENT 0.0
+.TP
+.B \-l <value>
+Alias for \-\-script\-language
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-python\-path
+Prints out the path to the lldb.py file for this version of lldb.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-P
+Alias for \-\-python\-path
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-script\-language <language>
+Tells the debugger to use the specified scripting language for user\-defined scripts.
+.UNINDENT
+.SH EXAMPLES
+.sp
+The debugger can be started in several modes.
+.sp
+Passing an executable as a positional argument prepares lldb to debug the given
+executable. To disambiguate between arguments passed to lldb and arguments
+passed to the debugged executable, arguments starting with a \- must be passed
+after \-\-.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-\-arch x86_64 /path/to/program program argument \-\- \-\-arch arvm7
+.UNINDENT
+.UNINDENT
+.sp
+For convenience, passing the executable after \-\- is also supported.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-\-arch x86_64 \-\- /path/to/program program argument \-\-arch arvm7
+.UNINDENT
+.UNINDENT
+.sp
+Passing one of the attach options causes \fBlldb\fP to immediately attach
+to the given process.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-p <pid>
+lldb \-n <process\-name>
+.UNINDENT
+.UNINDENT
+.sp
+Passing \-\-repl starts \fBlldb\fP in REPL mode.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-r
+.UNINDENT
+.UNINDENT
+.sp
+Passing \-\-core causes \fBlldb\fP to debug the core file.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-c /path/to/core
+.UNINDENT
+.UNINDENT
+.sp
+Command options can be combined with these modes and cause \fBlldb\fP to
+run the specified commands before or after events, like loading the file or
+crashing, in the order provided on the command line.
+.INDENT 0.0
+.INDENT 3.5
+lldb \-O \(aqsettings set stop\-disassembly\-count 20\(aq \-o \(aqrun\(aq \-o \(aqbt\(aq
+lldb \-S /source/before/file \-s /source/after/file
+lldb \-K /source/before/crash \-k /source/after/crash
+.UNINDENT
+.UNINDENT
+.sp
+Note: In REPL mode no file is loaded, so commands specified to run after
+loading the file (via \-o or \-s) will be ignored.
+.SH USING LLDB
+.sp
+In \fBlldb\fP there is a help command which can be used to find
+descriptions and examples of all \fBlldb\fP commands. To get help on
+"breakpoint set" you would type "help breakpoint set".
+.sp
+There is also an apropos command which will search the help text of all
+commands for a given term â€â€ this is useful for locating a command by topic.
+For instance, "apropos breakpoint" will list any command that has the word
+"breakpoint" in its help text.
+.SH CONFIGURATION FILES
+.sp
+\fBlldb\fP reads things like settings, aliases and commands from the
+\&.lldbinit file.
+.sp
+First, \fBlldb\fP will try to read the application specific init file
+whose name is ~/.lldbinit followed by a "\-" and the name of the current
+program. This would be ~/.lldbinit\-lldb for the command line \fBlldb\fP
+and ~/.lldbinit\-Xcode for Xcode. If there is no application specific init
+file, \fBlldb\fP will look for an init file in the home directory.
+If launched with a \fI\%REPL\fP option, it will first look for a REPL configuration
+file, specific to the REPL language. The init file should be named as follow:
+\fB\&.lldbinit\-<language>\-repl\fP (i.e. \fB\&.lldbinit\-swift\-repl\fP). If this file doesn\(aqt
+exist, or \fBlldb\fP wasn\(aqt launch with \fI\%REPL\fP, meaning there is neither
+a REPL init file nor an application specific init file, \fBlldb\fP will fallback to
+the global ~/.lldbinit.
+.sp
+Secondly, it will look for an .lldbinit file in the current working directory.
+For security reasons, \fBlldb\fP will print a warning and not source this
+file by default. This behavior can be changed by changing the
+target.load\-cwd\-lldbinit setting.
+.sp
+To always load the .lldbinit file in the current working directory, add the
+following command to ~/.lldbinit:
+.INDENT 0.0
+.INDENT 3.5
+settings set target.load\-cwd\-lldbinit true
+.UNINDENT
+.UNINDENT
+.sp
+To never load the .lldbinit file in the current working directory and silence
+the warning, add the following command to ~/.lldbinit:
+.INDENT 0.0
+.INDENT 3.5
+settings set target.load\-cwd\-lldbinit false
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+The LLDB project page \fI\%https://lldb.llvm.org\fP has many different resources
+for \fBlldb\fP users â€â€ the gdb/lldb command equivalence page
+\fI\%https://lldb.llvm.org/use/map.html\fP can be especially helpful for users
+coming from gdb.
+.SH AUTHOR
+LLVM project
+.SH COPYRIGHT
+2007-2021, The LLDB Team
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/lli/Makefile b/usr.bin/clang/lli/Makefile
new file mode 100644
index 000000000000..eed2d8b874b5
--- /dev/null
+++ b/usr.bin/clang/lli/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= lli
+
+SRCDIR= llvm/tools/lli
+SRCS+= lli.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/lli/Makefile.depend b/usr.bin/clang/lli/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/lli/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/lli/lli.1 b/usr.bin/clang/lli/lli.1
new file mode 100644
index 000000000000..b82e6a903a1d
--- /dev/null
+++ b/usr.bin/clang/lli/lli.1
@@ -0,0 +1,300 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLI" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+lli \- directly execute programs from LLVM bitcode
+.SH SYNOPSIS
+.sp
+\fBlli\fP [\fIoptions\fP] [\fIfilename\fP] [\fIprogram args\fP]
+.SH DESCRIPTION
+.sp
+\fBlli\fP directly executes programs in LLVM bitcode format. It takes a program
+in LLVM bitcode format and executes it using a just\-in\-time compiler or an
+interpreter.
+.sp
+\fBlli\fP is \fInot\fP an emulator. It will not execute IR of different architectures
+and it can only interpret (or JIT\-compile) for the host architecture.
+.sp
+The JIT compiler takes the same arguments as other tools, like \fBllc\fP,
+but they don\(aqt necessarily work for the interpreter.
+.sp
+If \fIfilename\fP is not specified, then \fBlli\fP reads the LLVM bitcode for the
+program from standard input.
+.sp
+The optional \fIargs\fP specified on the command line are passed to the program as
+arguments.
+.SH GENERAL OPTIONS
+.INDENT 0.0
+.TP
+.B \-fake\-argv0=executable
+Override the \fBargv[0]\fP value passed into the executing program.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-force\-interpreter={false,true}
+If set to true, use the interpreter even if a just\-in\-time compiler is available
+for this architecture. Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-load=pluginfilename
+Causes \fBlli\fP to load the plugin (shared object) named \fIpluginfilename\fP and use
+it for optimization.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stats
+Print statistics from the code\-generation passes. This is only meaningful for
+the just\-in\-time compiler, at present.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-time\-passes
+Record the amount of time needed for each code\-generation pass and print it to
+standard error.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-version
+Print out the version of \fBlli\fP and exit without doing anything else.
+.UNINDENT
+.SH TARGET OPTIONS
+.INDENT 0.0
+.TP
+.B \-mtriple=target triple
+Override the target triple specified in the input bitcode file with the
+specified string. This may result in a crash if you pick an
+architecture which is not compatible with the current system.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-march=arch
+Specify the architecture for which to generate assembly, overriding the target
+encoded in the bitcode file. See the output of \fBllc \-help\fP for a list of
+valid architectures. By default this is inferred from the target triple or
+autodetected to the current architecture.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mcpu=cpuname
+Specify a specific chip in the current architecture to generate code for.
+By default this is inferred from the target triple and autodetected to
+the current architecture. For a list of available CPUs, use:
+\fBllvm\-as < /dev/null | llc \-march=xyz \-mcpu=help\fP
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mattr=a1,+a2,\-a3,...
+Override or control specific attributes of the target, such as whether SIMD
+operations are enabled or not. The default set of attributes is set by the
+current CPU. For a list of available attributes, use:
+\fBllvm\-as < /dev/null | llc \-march=xyz \-mattr=help\fP
+.UNINDENT
+.SH FLOATING POINT OPTIONS
+.INDENT 0.0
+.TP
+.B \-disable\-excess\-fp\-precision
+Disable optimizations that may increase floating point precision.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-enable\-no\-infs\-fp\-math
+Enable optimizations that assume no Inf values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-enable\-no\-nans\-fp\-math
+Enable optimizations that assume no NAN values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-enable\-unsafe\-fp\-math
+Causes \fBlli\fP to enable optimizations that may decrease floating point
+precision.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-soft\-float
+Causes \fBlli\fP to generate software floating point library calls instead of
+equivalent hardware instructions.
+.UNINDENT
+.SH CODE GENERATION OPTIONS
+.INDENT 0.0
+.TP
+.B \-code\-model=model
+Choose the code model from:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+default: Target default code model
+tiny: Tiny code model
+small: Small code model
+kernel: Kernel code model
+medium: Medium code model
+large: Large code model
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-disable\-post\-RA\-scheduler
+Disable scheduling after register allocation.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-disable\-spill\-fusing
+Disable fusing of spill code into instructions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-jit\-enable\-eh
+Exception handling should be enabled in the just\-in\-time compiler.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-join\-liveintervals
+Coalesce copies (default=true).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-nozero\-initialized\-in\-bss
+Don\(aqt place zero\-initialized symbols into the BSS section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-pre\-RA\-sched=scheduler
+Instruction schedulers available (before register allocation):
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=default: Best scheduler for the target
+=none: No scheduling: breadth first sequencing
+=simple: Simple two pass scheduling: minimize critical path and maximize processor utilization
+=simple\-noitin: Simple two pass scheduling: Same as simple except using generic latency
+=list\-burr: Bottom\-up register reduction list scheduling
+=list\-tdrr: Top\-down register reduction list scheduling
+=list\-td: Top\-down list scheduler
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-regalloc=allocator
+Register allocator to use (default=linearscan)
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=bigblock: Big\-block register allocator
+=linearscan: linear scan register allocator
+=local: local register allocator
+=simple: simple register allocator
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-relocation\-model=model
+Choose relocation model from:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=default: Target default relocation model
+=static: Non\-relocatable code
+=pic: Fully relocatable, position independent code
+=dynamic\-no\-pic: Relocatable external references, non\-relocatable code
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-spiller
+Spiller to use (default=local)
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=simple: simple spiller
+=local: local spiller
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x86\-asm\-syntax=syntax
+Choose style of code to emit from X86 backend:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=att: Emit AT&T\-style assembly
+=intel: Emit Intel\-style assembly
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBlli\fP fails to load the program, it will exit with an exit code of 1.
+Otherwise, it will return the exit code of the program it executes.
+.SH SEE ALSO
+.sp
+\fBllc(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-ar/Makefile b/usr.bin/clang/llvm-ar/Makefile
new file mode 100644
index 000000000000..fd12b1ddef57
--- /dev/null
+++ b/usr.bin/clang/llvm-ar/Makefile
@@ -0,0 +1,17 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-ar
+MAN= llvm-ar.1 llvm-ranlib.1
+
+SRCDIR= llvm/tools/llvm-ar
+SRCS+= llvm-ar-driver.cpp
+SRCS+= llvm-ar.cpp
+
+LINKS+= ${BINDIR}/llvm-ar ${BINDIR}/llvm-ranlib
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-ar ${BINDIR}/ar ${BINDIR}/llvm-ar ${BINDIR}/ranlib
+MLINKS+= llvm-ar.1 ar.1 llvm-ar.1 ranlib.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-ar/Makefile.depend b/usr.bin/clang/llvm-ar/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-ar/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-ar/llvm-ar-driver.cpp b/usr.bin/clang/llvm-ar/llvm-ar-driver.cpp
new file mode 100644
index 000000000000..2f00f97da371
--- /dev/null
+++ b/usr.bin/clang/llvm-ar/llvm-ar-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_ar_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_ar_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-ar/llvm-ar.1 b/usr.bin/clang/llvm-ar/llvm-ar.1
new file mode 100644
index 000000000000..9f2be0c401cc
--- /dev/null
+++ b/usr.bin/clang/llvm-ar/llvm-ar.1
@@ -0,0 +1,469 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-AR" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-ar \- LLVM archiver
+.SH SYNOPSIS
+.sp
+\fBllvm\-ar\fP [\-]{dmpqrstx}[abcDilLNoOPsSTuUvV] [relpos] [count] archive [files...]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-ar\fP command is similar to the common Unix utility,
+\fBar\fP\&. It archives several files, such as objects and LLVM bitcode
+files into a single archive library that can be linked into a program. However,
+the archive can contain any kind of file. By default, \fBllvm\-ar\fP
+generates a symbol table that makes linking faster because only the symbol
+table needs to be consulted, not each individual file member of the archive.
+.sp
+The \fBllvm\-ar\fP command can be used to \fIread\fP archive files in SVR4, GNU,
+BSD , Big Archive, and Darwin format, and \fIwrite\fP in the GNU, BSD, Big Archive, and
+Darwin style archive files. If an SVR4 format archive is used with the \fI\%r\fP
+(replace), \fI\%d\fP (delete), \fI\%m\fP (move) or \fI\%q\fP
+(quick update) operations, the archive will be reconstructed in the format
+defined by \fI\%\-\-format\fP\&.
+.sp
+Here\(aqs where \fBllvm\-ar\fP departs from previous \fBar\fP
+implementations:
+.sp
+\fIThe following option is not supported\fP
+.INDENT 0.0
+.INDENT 3.5
+[f] \- truncate inserted filenames
+.UNINDENT
+.UNINDENT
+.sp
+\fIThe following options are ignored for compatibility\fP
+.INDENT 0.0
+.INDENT 3.5
+\-\-plugin=<string> \- load a plugin which adds support for other file formats
+.sp
+[l] \- ignored in \fBar\fP
+.UNINDENT
+.UNINDENT
+.sp
+\fISymbol Table\fP
+.INDENT 0.0
+.INDENT 3.5
+Since \fBllvm\-ar\fP supports bitcode files, the symbol table it creates
+includes both native and bitcode symbols.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDeterministic Archives\fP
+.INDENT 0.0
+.INDENT 3.5
+By default, \fBllvm\-ar\fP always uses zero for timestamps and UIDs/GIDs
+to write archives in a deterministic mode. This is equivalent to the
+\fI\%D\fP modifier being enabled by default. If you wish to maintain
+compatibility with other \fBar\fP implementations, you can pass the
+\fI\%U\fP modifier to write actual timestamps and UIDs/GIDs.
+.UNINDENT
+.UNINDENT
+.sp
+\fIWindows Paths\fP
+.INDENT 0.0
+.INDENT 3.5
+When on Windows \fBllvm\-ar\fP treats the names of archived \fIfiles\fP in the same
+case sensitive manner as the operating system. When on a non\-Windows machine
+\fBllvm\-ar\fP does not consider character case.
+.UNINDENT
+.UNINDENT
+.SH OPTIONS
+.sp
+\fBllvm\-ar\fP operations are compatible with other \fBar\fP
+implementations. However, there are a few modifiers (\fI\%L\fP) that are not
+found in other \fBar\fP implementations. The options for
+\fBllvm\-ar\fP specify a single basic Operation to perform on the archive,
+a variety of Modifiers for that Operation, the name of the archive file, and an
+optional list of file names. If the \fIfiles\fP option is not specified, it
+generally means either \(dqnone\(dq or \(dqall\(dq members, depending on the operation. The
+Options, Operations and Modifiers are explained in the sections below.
+.sp
+The minimal set of options is at least one operator and the name of the
+archive.
+.SS Operations
+.INDENT 0.0
+.TP
+.B d [NT]
+Delete files from the \fBarchive\fP\&. The \fI\%N\fP and \fI\%T\fP modifiers
+apply to this operation. The \fIfiles\fP options specify which members should be
+removed from the archive. It is not an error if a specified file does not
+appear in the archive. If no \fIfiles\fP are specified, the archive is not
+modified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B m [abi]
+Move files from one location in the \fBarchive\fP to another. The \fI\%a\fP,
+\fI\%b\fP, and \fI\%i\fP modifiers apply to this operation. The \fIfiles\fP
+will all be moved to the location given by the modifiers. If no modifiers are
+used, the files will be moved to the end of the archive. If no \fIfiles\fP are
+specified, the archive is not modified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B p [v]
+Print \fIfiles\fP to the standard output stream. If no \fIfiles\fP are specified, the
+entire \fBarchive\fP is printed. With the \fI\%v\fP modifier,
+\fBllvm\-ar\fP also prints out the name of the file being output. Printing
+binary files is ill\-advised as they might confuse your terminal settings. The
+\fI\%p\fP operation never modifies the archive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B q [LT]
+Quickly append files to the end of the \fBarchive\fP without removing
+duplicates. If no \fIfiles\fP are specified, the archive is not modified. The
+behavior when appending one archive to another depends upon whether the
+\fI\%L\fP and \fI\%T\fP modifiers are used:
+.INDENT 7.0
+.IP \(bu 2
+Appending a regular archive to a regular archive will append the archive
+file. If the \fI\%L\fP modifier is specified the members will be appended
+instead.
+.IP \(bu 2
+Appending a regular archive to a thin archive requires the \fI\%T\fP
+modifier and will append the archive file. The \fI\%L\fP modifier is not
+supported.
+.IP \(bu 2
+Appending a thin archive to a regular archive will append the archive file.
+If the \fI\%L\fP modifier is specified the members will be appended
+instead.
+.IP \(bu 2
+Appending a thin archive to a thin archive will always quick append its
+members.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B r [abTu]
+Replace existing \fIfiles\fP or insert them at the end of the \fBarchive\fP if
+they do not exist. The \fI\%a\fP, \fI\%b\fP, \fI\%T\fP and \fI\%u\fP
+modifiers apply to this operation. If no \fIfiles\fP are specified, the archive
+is not modified.
+.UNINDENT
+.sp
+t[v]
+\&.. option:: t [vO]
+.INDENT 0.0
+.INDENT 3.5
+Print the table of contents. Without any modifiers, this operation just prints
+the names of the members to the standard output stream. With the \fI\%v\fP
+modifier, \fBllvm\-ar\fP also prints out the file type (B=bitcode,
+S=symbol table, blank=regular file), the permission mode, the owner and group,
+are ignored when extracting \fIfiles\fP and set to placeholder values when adding
+size, and the date. With the \fI\%O\fP modifier, display member offsets. If
+any \fIfiles\fP are specified, the listing is only for those files. If no \fIfiles\fP
+are specified, the table of contents for the whole archive is printed.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B V
+A synonym for the \fI\%\-\-version\fP option.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B x [oP]
+Extract \fBarchive\fP members back to files. The \fI\%o\fP modifier applies
+to this operation. This operation retrieves the indicated \fIfiles\fP from the
+archive and writes them back to the operating system\(aqs file system. If no
+\fIfiles\fP are specified, the entire archive is extracted.
+.UNINDENT
+.SS Modifiers (operation specific)
+.sp
+The modifiers below are specific to certain operations. See the Operations
+section to determine which modifiers are applicable to which operations.
+.INDENT 0.0
+.TP
+.B a
+When inserting or moving member files, this option specifies the destination
+of the new files as being after the \fIrelpos\fP member. If \fIrelpos\fP is not found,
+the files are placed at the end of the \fBarchive\fP\&. \fIrelpos\fP cannot be
+consumed without either \fI\%a\fP, \fI\%b\fP or \fI\%i\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B b
+When inserting or moving member files, this option specifies the destination
+of the new files as being before the \fIrelpos\fP member. If \fIrelpos\fP is not
+found, the files are placed at the end of the \fBarchive\fP\&. \fIrelpos\fP cannot
+be consumed without either \fI\%a\fP, \fI\%b\fP or \fI\%i\fP\&. This
+modifier is identical to the \fI\%i\fP modifier.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B i
+A synonym for the \fI\%b\fP option.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B L
+When quick appending an \fBarchive\fP, instead quick append its members. This
+is a feature for \fBllvm\-ar\fP that is not found in gnu\-ar.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B N
+When extracting or deleting a member that shares its name with another member,
+the \fIcount\fP parameter allows you to supply a positive whole number that
+selects the instance of the given name, with \(dq1\(dq indicating the first
+instance. If \fI\%N\fP is not specified the first member of that name will
+be selected. If \fIcount\fP is not supplied, the operation fails.*count* cannot be
+.UNINDENT
+.INDENT 0.0
+.TP
+.B o
+When extracting files, use the modification times of any \fIfiles\fP as they
+appear in the \fBarchive\fP\&. By default \fIfiles\fP extracted from the archive
+use the time of extraction.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B O
+Display member offsets inside the archive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B T
+Alias for \fB\-\-thin\fP\&. In many ar implementations \fBT\fP has a different
+meaning, as specified by X/Open System interface.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B v
+When printing \fIfiles\fP or the \fBarchive\fP table of contents, this modifier
+instructs \fBllvm\-ar\fP to include additional information in the output.
+.UNINDENT
+.SS Modifiers (generic)
+.sp
+The modifiers below may be applied to any operation.
+.INDENT 0.0
+.TP
+.B c
+For the \fI\%r\fP (replace)and \fI\%q\fP (quick update) operations,
+\fBllvm\-ar\fP will always create the archive if it doesn\(aqt exist.
+Normally, \fBllvm\-ar\fP will print a warning message indicating that the
+\fBarchive\fP is being created. Using this modifier turns off
+that warning.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B D
+Use zero for timestamps and UIDs/GIDs. This is set by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B P
+Use full paths when matching member names rather than just the file name.
+This can be useful when manipulating an \fBarchive\fP generated by another
+archiver, as some allow paths as member names. This is the default behavior
+for thin archives.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B s
+This modifier requests that an archive index (or symbol table) be added to the
+\fBarchive\fP, as if using ranlib. The symbol table will contain all the
+externally visible functions and global variables defined by all the bitcode
+files in the archive. By default \fBllvm\-ar\fP generates symbol tables in
+archives. This can also be used as an operation.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B S
+This modifier is the opposite of the \fI\%s\fP modifier. It instructs
+\fBllvm\-ar\fP to not build the symbol table. If both \fI\%s\fP and
+\fI\%S\fP are used, the last modifier to occur in the options will prevail.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B u
+Only update \fBarchive\fP members with \fIfiles\fP that have more recent
+timestamps.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B U
+Use actual timestamps and UIDs/GIDs.
+.UNINDENT
+.SS Other
+.INDENT 0.0
+.TP
+.B \-\-format=<type>
+This option allows for default, gnu, darwin or bsd \fB<type>\fP to be selected.
+When creating an \fBarchive\fP, \fB<type>\fP will default to that of the host
+machine.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-h, \-\-help
+Print a summary of command\-line options and their meanings.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-M
+This option allows for MRI scripts to be read through the standard input
+stream. No other options are compatible with this option.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output=<dir>
+Specify a directory where archive members should be extracted to. By default the
+current working directory is used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-rsp\-quoting=<type>
+.TP
+.B This option selects the quoting style \(ga\(ga<type>\(ga\(ga for response files, either
+.TP
+.B \(ga\(gaposix\(ga\(ga or \(ga\(gawindows\(ga\(ga. The default when on Windows is \(ga\(gawindows\(ga\(ga, otherwise the
+.TP
+.B default is \(ga\(gaposix\(ga\(ga.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-thin
+When creating or modifying an archive, this option specifies that the
+\fBarchive\fP will be thin. By default, archives are not created as thin archives
+and when modifying a thin archive, it will be converted to a regular archive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-ar\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-X mode
+Specifies the type of object file \fBllvm\-ar\fP will recognise. The mode must be
+one of the following:
+.INDENT 7.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.B 32
+Process only 32\-bit object files.
+.TP
+.B 64
+Process only 64\-bit object files.
+.TP
+.B 32_64
+Process both 32\-bit and 64\-bit object files.
+.TP
+.B any
+Process all object files.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The default is to process 32\-bit object files (ignore 64\-bit objects). The mode can also
+be set with the OBJECT_MODE environment variable. For example, OBJECT_MODE=64 causes ar to
+process any 64\-bit objects and ignore 32\-bit objects. The \-X flag overrides the OBJECT_MODE
+variable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options and commands from response file \fB<FILE>\fP\&.
+.UNINDENT
+.SH MRI SCRIPTS
+.sp
+\fBllvm\-ar\fP understands a subset of the MRI scripting interface commonly
+supported by archivers following in the ar tradition. An MRI script contains a
+sequence of commands to be executed by the archiver. The \fI\%\-M\fP option
+allows for an MRI script to be passed to \fBllvm\-ar\fP through the
+standard input stream.
+.sp
+Note that \fBllvm\-ar\fP has known limitations regarding the use of MRI
+scripts:
+.INDENT 0.0
+.IP \(bu 2
+Each script can only create one archive.
+.IP \(bu 2
+Existing archives can not be modified.
+.UNINDENT
+.SS MRI Script Commands
+.sp
+Each command begins with the command\(aqs name and must appear on its own line.
+Some commands have arguments, which must be separated from the name by
+whitespace. An MRI script should begin with either a \fI\%CREATE\fP or
+\fI\%CREATETHIN\fP command and will typically end with a \fI\%SAVE\fP
+command. Any text after either \(aq*\(aq or \(aq;\(aq is treated as a comment.
+.INDENT 0.0
+.TP
+.B CREATE archive
+Begin creation of a regular archive with the specified name. Subsequent
+commands act upon this \fBarchive\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B CREATETHIN archive
+Begin creation of a thin archive with the specified name. Subsequent
+commands act upon this \fBarchive\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ADDLIB archive
+Append the contents of \fBarchive\fP to the current archive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ADDMOD <file>
+Append \fB<file>\fP to the current archive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B DELETE <file>
+Delete the member of the current archive whose file name, excluding directory
+components, matches \fB<file>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B SAVE
+Write the current archive to the path specified in the previous
+\fI\%CREATE\fP/\fI\%CREATETHIN\fP command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B END
+Ends the MRI script (optional).
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-ar\fP succeeds, it will exit with 0. Otherwise, if an error occurs, it
+will exit with a non\-zero value.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-ar/llvm-ranlib.1 b/usr.bin/clang/llvm-ar/llvm-ranlib.1
new file mode 100644
index 000000000000..36c715546faa
--- /dev/null
+++ b/usr.bin/clang/llvm-ar/llvm-ranlib.1
@@ -0,0 +1,51 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-RANLIB" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-ranlib \- generates an archive index
+.SH SYNOPSIS
+.sp
+\fBllvm\-ranlib\fP [\fIoptions\fP] \fIarchive...\fP
+.SH DESCRIPTION
+.sp
+\fBllvm\-ranlib\fP is an alias for the \fI\%llvm\-ar\fP tool that
+generates an index for one or more archives. It can be used as a replacement for GNU\(aqs
+\fBranlib\fP tool.
+.sp
+Running \fBllvm\-ranlib\fP is equivalent to running \fBllvm\-ar s\fP\&.
+.SH SEE ALSO
+.sp
+\fBllvm\-ar(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-as/Makefile b/usr.bin/clang/llvm-as/Makefile
new file mode 100644
index 000000000000..e6a6edfdb864
--- /dev/null
+++ b/usr.bin/clang/llvm-as/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= llvm-as
+
+SRCDIR= llvm/tools/llvm-as
+SRCS+= llvm-as.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-as/Makefile.depend b/usr.bin/clang/llvm-as/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-as/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-as/llvm-as.1 b/usr.bin/clang/llvm-as/llvm-as.1
new file mode 100644
index 000000000000..897f2a28a971
--- /dev/null
+++ b/usr.bin/clang/llvm-as/llvm-as.1
@@ -0,0 +1,86 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-AS" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-as \- LLVM assembler
+.SH SYNOPSIS
+.sp
+\fBllvm\-as\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-as\fP is the LLVM assembler. It reads a file containing human\-readable
+LLVM assembly language, translates it to LLVM bitcode, and writes the result
+into a file or to standard output.
+.sp
+If \fIfilename\fP is omitted or is \fB\-\fP, then \fBllvm\-as\fP reads its input from
+standard input.
+.sp
+If an output file is not specified with the \fB\-o\fP option, then
+\fBllvm\-as\fP sends its output to a file or standard output by following
+these rules:
+.INDENT 0.0
+.IP \(bu 2
+If the input is standard input, then the output is standard output.
+.IP \(bu 2
+If the input is a file that ends with \fB\&.ll\fP, then the output file is of the
+same name, except that the suffix is changed to \fB\&.bc\fP\&.
+.IP \(bu 2
+If the input is a file that does not end with the \fB\&.ll\fP suffix, then the
+output file has the same name as the input file, except that the \fB\&.bc\fP
+suffix is appended.
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+\fB\-f\fP
+Enable binary output on terminals. Normally, \fBllvm\-as\fP will refuse to
+write raw bitcode output if the output stream is a terminal. With this option,
+\fBllvm\-as\fP will write raw bitcode regardless of the output device.
+.TP
+\fB\-help\fP
+Print a summary of command line options.
+.TP
+\fB\-o\fP \fIfilename\fP
+Specify the output file name. If \fIfilename\fP is \fB\-\fP, then \fBllvm\-as\fP
+sends its output to standard output.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-as\fP succeeds, it will exit with 0. Otherwise, if an error occurs, it
+will exit with a non\-zero value.
+.SH SEE ALSO
+.sp
+\fBllvm\-dis(1)\fP, as(1)
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-bcanalyzer/Makefile b/usr.bin/clang/llvm-bcanalyzer/Makefile
new file mode 100644
index 000000000000..2c796a362f57
--- /dev/null
+++ b/usr.bin/clang/llvm-bcanalyzer/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= llvm-bcanalyzer
+
+SRCDIR= llvm/tools/llvm-bcanalyzer
+SRCS+= llvm-bcanalyzer.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-bcanalyzer/Makefile.depend b/usr.bin/clang/llvm-bcanalyzer/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-bcanalyzer/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1 b/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1
new file mode 100644
index 000000000000..016298a7711b
--- /dev/null
+++ b/usr.bin/clang/llvm-bcanalyzer/llvm-bcanalyzer.1
@@ -0,0 +1,461 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-BCANALYZER" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-bcanalyzer \- LLVM bitcode analyzer
+.SH SYNOPSIS
+.sp
+\fBllvm\-bcanalyzer\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-bcanalyzer\fP command is a small utility for analyzing bitcode
+files. The tool reads a bitcode file (such as generated with the
+\fBllvm\-as\fP tool) and produces a statistical report on the contents of
+the bitcode file. The tool can also dump a low level but human readable
+version of the bitcode file. This tool is probably not of much interest or
+utility except for those working directly with the bitcode file format. Most
+LLVM users can just ignore this tool.
+.sp
+If \fIfilename\fP is omitted or is \fB\-\fP, then \fBllvm\-bcanalyzer\fP reads its
+input from standard input. This is useful for combining the tool into a
+pipeline. Output is written to the standard output.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-dump
+Causes \fBllvm\-bcanalyzer\fP to dump the bitcode in a human readable
+format. This format is significantly different from LLVM assembly and
+provides details about the encoding of the bitcode file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Print a summary of command line options.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-bcanalyzer\fP succeeds, it will exit with 0. Otherwise, if an
+error occurs, it will exit with a non\-zero value, usually 1.
+.SH SUMMARY OUTPUT DEFINITIONS
+.sp
+The following items are always printed by llvm\-bcanalyzer. They comprize the
+summary output.
+.sp
+\fBBitcode Analysis Of Module\fP
+.INDENT 0.0
+.INDENT 3.5
+This just provides the name of the module for which bitcode analysis is being
+generated.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBitcode Version Number\fP
+.INDENT 0.0
+.INDENT 3.5
+The bitcode version (not LLVM version) of the file read by the analyzer.
+.UNINDENT
+.UNINDENT
+.sp
+\fBFile Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of the entire bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBModule Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of the module block. Percentage is relative to File Size.
+.UNINDENT
+.UNINDENT
+.sp
+\fBFunction Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of all the function blocks. Percentage is relative to File
+Size.
+.UNINDENT
+.UNINDENT
+.sp
+\fBGlobal Types Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of the Global Types Pool. Percentage is relative to File
+Size. This is the size of the definitions of all types in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBConstant Pool Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of the Constant Pool Blocks Percentage is relative to File
+Size.
+.UNINDENT
+.UNINDENT
+.sp
+\fBModule Globals Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+Ths size, in bytes, of the Global Variable Definitions and their initializers.
+Percentage is relative to File Size.
+.UNINDENT
+.UNINDENT
+.sp
+\fBInstruction List Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of all the instruction lists in all the functions.
+Percentage is relative to File Size. Note that this value is also included in
+the Function Bytes.
+.UNINDENT
+.UNINDENT
+.sp
+\fBCompaction Table Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of all the compaction tables in all the functions.
+Percentage is relative to File Size. Note that this value is also included in
+the Function Bytes.
+.UNINDENT
+.UNINDENT
+.sp
+\fBSymbol Table Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of all the symbol tables in all the functions. Percentage is
+relative to File Size. Note that this value is also included in the Function
+Bytes.
+.UNINDENT
+.UNINDENT
+.sp
+\fBDependent Libraries Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The size, in bytes, of the list of dependent libraries in the module. Percentage
+is relative to File Size. Note that this value is also included in the Module
+Global Bytes.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Bitcode Blocks\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of blocks of any kind in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Functions\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of function definitions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Types\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of types defined in the Global Types Pool.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Constants\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of constants (of any type) defined in the Constant Pool.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Basic Blocks\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of basic blocks defined in all functions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Instructions\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of instructions defined in all functions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Long Instructions\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of long instructions defined in all functions in the bitcode
+file. Long instructions are those taking greater than 4 bytes. Typically long
+instructions are GetElementPtr with several indices, PHI nodes, and calls to
+functions with large numbers of arguments.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Operands\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of operands used in all instructions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Compaction Tables\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of compaction tables in all functions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Symbol Tables\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of symbol tables in all functions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber Of Dependent Libs\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of dependent libraries found in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBTotal Instruction Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The total size of the instructions in all functions in the bitcode file.
+.UNINDENT
+.UNINDENT
+.sp
+\fBAverage Instruction Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The average number of bytes per instruction across all functions in the bitcode
+file. This value is computed by dividing Total Instruction Size by Number Of
+Instructions.
+.UNINDENT
+.UNINDENT
+.sp
+\fBMaximum Type Slot Number\fP
+.INDENT 0.0
+.INDENT 3.5
+The maximum value used for a type\(aqs slot number. Larger slot number values take
+more bytes to encode.
+.UNINDENT
+.UNINDENT
+.sp
+\fBMaximum Value Slot Number\fP
+.INDENT 0.0
+.INDENT 3.5
+The maximum value used for a value\(aqs slot number. Larger slot number values take
+more bytes to encode.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Per Value\fP
+.INDENT 0.0
+.INDENT 3.5
+The average size of a Value definition (of any type). This is computed by
+dividing File Size by the total number of values of any type.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Per Global\fP
+.INDENT 0.0
+.INDENT 3.5
+The average size of a global definition (constants and global variables).
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Per Function\fP
+.INDENT 0.0
+.INDENT 3.5
+The average number of bytes per function definition. This is computed by
+dividing Function Bytes by Number Of Functions.
+.UNINDENT
+.UNINDENT
+.sp
+\fB# of VBR 32\-bit Integers\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of 32\-bit integers encoded using the Variable Bit Rate
+encoding scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fB# of VBR 64\-bit Integers\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of 64\-bit integers encoded using the Variable Bit Rate encoding
+scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fB# of VBR Compressed Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes consumed by the 32\-bit and 64\-bit integers that use
+the Variable Bit Rate encoding scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fB# of VBR Expanded Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes that would have been consumed by the 32\-bit and 64\-bit
+integers had they not been compressed with the Variable Bit Rage encoding
+scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Saved With VBR\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes saved by using the Variable Bit Rate encoding scheme.
+The percentage is relative to # of VBR Expanded Bytes.
+.UNINDENT
+.UNINDENT
+.SH DETAILED OUTPUT DEFINITIONS
+.sp
+The following definitions occur only if the \-nodetails option was not given.
+The detailed output provides additional information on a per\-function basis.
+.sp
+\fBType\fP
+.INDENT 0.0
+.INDENT 3.5
+The type signature of the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBByte Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes in the function\(aqs block.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBasic Blocks\fP
+.INDENT 0.0
+.INDENT 3.5
+The number of basic blocks defined by the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBInstructions\fP
+.INDENT 0.0
+.INDENT 3.5
+The number of instructions defined by the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBLong Instructions\fP
+.INDENT 0.0
+.INDENT 3.5
+The number of instructions using the long instruction format in the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBOperands\fP
+.INDENT 0.0
+.INDENT 3.5
+The number of operands used by all instructions in the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBInstruction Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The number of bytes consumed by instructions in the function.
+.UNINDENT
+.UNINDENT
+.sp
+\fBAverage Instruction Size\fP
+.INDENT 0.0
+.INDENT 3.5
+The average number of bytes consumed by the instructions in the function.
+This value is computed by dividing Instruction Size by Instructions.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Per Instruction\fP
+.INDENT 0.0
+.INDENT 3.5
+The average number of bytes used by the function per instruction. This value
+is computed by dividing Byte Size by Instructions. Note that this is not the
+same as Average Instruction Size. It computes a number relative to the total
+function size not just the size of the instruction list.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber of VBR 32\-bit Integers\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of 32\-bit integers found in this function (for any use).
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber of VBR 64\-bit Integers\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of 64\-bit integers found in this function (for any use).
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber of VBR Compressed Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes in this function consumed by the 32\-bit and 64\-bit
+integers that use the Variable Bit Rate encoding scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNumber of VBR Expanded Bytes\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes in this function that would have been consumed by
+the 32\-bit and 64\-bit integers had they not been compressed with the Variable
+Bit Rate encoding scheme.
+.UNINDENT
+.UNINDENT
+.sp
+\fBBytes Saved With VBR\fP
+.INDENT 0.0
+.INDENT 3.5
+The total number of bytes saved in this function by using the Variable Bit
+Rate encoding scheme. The percentage is relative to # of VBR Expanded Bytes.
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBllvm\-dis(1)\fP, \fI\%LLVM Bitcode File Format\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-cov/Makefile b/usr.bin/clang/llvm-cov/Makefile
new file mode 100644
index 000000000000..3eb14eb37139
--- /dev/null
+++ b/usr.bin/clang/llvm-cov/Makefile
@@ -0,0 +1,21 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-cov
+LINKS= ${BINDIR}/llvm-cov ${BINDIR}/gcov
+MLINKS= llvm-cov.1 gcov.1
+
+SRCDIR= llvm/tools/llvm-cov
+SRCS+= CodeCoverage.cpp
+SRCS+= CoverageExporterJson.cpp
+SRCS+= CoverageExporterLcov.cpp
+SRCS+= CoverageFilters.cpp
+SRCS+= CoverageReport.cpp
+SRCS+= CoverageSummaryInfo.cpp
+SRCS+= SourceCoverageView.cpp
+SRCS+= SourceCoverageViewHTML.cpp
+SRCS+= SourceCoverageViewText.cpp
+SRCS+= TestingSupport.cpp
+SRCS+= gcov.cpp
+SRCS+= llvm-cov.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-cov/Makefile.depend b/usr.bin/clang/llvm-cov/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-cov/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-cov/llvm-cov.1 b/usr.bin/clang/llvm-cov/llvm-cov.1
new file mode 100644
index 000000000000..e25461477766
--- /dev/null
+++ b/usr.bin/clang/llvm-cov/llvm-cov.1
@@ -0,0 +1,583 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-COV" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-cov \- emit coverage information
+.SH SYNOPSIS
+.sp
+\fBllvm\-cov\fP \fIcommand\fP [\fIargs...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-cov\fP tool shows code coverage information for
+programs that are instrumented to emit profile data. It can be used to
+work with \fBgcov\fP\-style coverage or with \fBclang\fP\(aqs instrumentation
+based profiling.
+.sp
+If the program is invoked with a base name of \fBgcov\fP, it will behave as if
+the \fBllvm\-cov gcov\fP command were called. Otherwise, a command should
+be provided.
+.SH COMMANDS
+.INDENT 0.0
+.IP \(bu 2
+\fI\%gcov\fP
+.IP \(bu 2
+\fI\%show\fP
+.IP \(bu 2
+\fI\%report\fP
+.IP \(bu 2
+\fI\%export\fP
+.UNINDENT
+.SH GCOV COMMAND
+.SS SYNOPSIS
+.sp
+\fBllvm\-cov gcov\fP [\fIoptions\fP] \fISOURCEFILE\fP
+.SS DESCRIPTION
+.sp
+The \fBllvm\-cov gcov\fP tool reads code coverage data files and displays
+the coverage information for a specified source file. It is compatible with the
+\fBgcov\fP tool from version 4.2 of \fBGCC\fP and may also be compatible with some
+later versions of \fBgcov\fP\&.
+.sp
+To use \fBllvm\-cov gcov\fP, you must first build an instrumented version
+of your application that collects coverage data as it runs. Compile with the
+\fB\-fprofile\-arcs\fP and \fB\-ftest\-coverage\fP options to add the
+instrumentation. (Alternatively, you can use the \fB\-\-coverage\fP option, which
+includes both of those other options.)
+.sp
+At the time you compile the instrumented code, a \fB\&.gcno\fP data file will be
+generated for each object file. These \fB\&.gcno\fP files contain half of the
+coverage data. The other half of the data comes from \fB\&.gcda\fP files that are
+generated when you run the instrumented program, with a separate \fB\&.gcda\fP
+file for each object file. Each time you run the program, the execution counts
+are summed into any existing \fB\&.gcda\fP files, so be sure to remove any old
+files if you do not want their contents to be included.
+.sp
+By default, the \fB\&.gcda\fP files are written into the same directory as the
+object files, but you can override that by setting the \fBGCOV_PREFIX\fP and
+\fBGCOV_PREFIX_STRIP\fP environment variables. The \fBGCOV_PREFIX_STRIP\fP
+variable specifies a number of directory components to be removed from the
+start of the absolute path to the object file directory. After stripping those
+directories, the prefix from the \fBGCOV_PREFIX\fP variable is added. These
+environment variables allow you to run the instrumented program on a machine
+where the original object file directories are not accessible, but you will
+then need to copy the \fB\&.gcda\fP files back to the object file directories
+where \fBllvm\-cov gcov\fP expects to find them.
+.sp
+Once you have generated the coverage data files, run \fBllvm\-cov gcov\fP
+for each main source file where you want to examine the coverage results. This
+should be run from the same directory where you previously ran the
+compiler. The results for the specified source file are written to a file named
+by appending a \fB\&.gcov\fP suffix. A separate output file is also created for
+each file included by the main source file, also with a \fB\&.gcov\fP suffix added.
+.sp
+The basic content of an \fB\&.gcov\fP output file is a copy of the source file with
+an execution count and line number prepended to every line. The execution
+count is shown as \fB\-\fP if a line does not contain any executable code. If
+a line contains code but that code was never executed, the count is displayed
+as \fB#####\fP\&.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-a, \-\-all\-blocks
+Display all basic blocks. If there are multiple blocks for a single line of
+source code, this option causes llvm\-cov to show the count for each block
+instead of just one count for the entire line.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-b, \-\-branch\-probabilities
+Display conditional branch probabilities and a summary of branch information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-c, \-\-branch\-counts
+Display branch counts instead of probabilities (requires \-b).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-m, \-\-demangled\-names
+Demangle function names.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-f, \-\-function\-summaries
+Show a summary of coverage for each function instead of just one summary for
+an entire source file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Display available options (\-\-help\-hidden for more).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-l, \-\-long\-file\-names
+For coverage output of files included from the main source file, add the
+main file name followed by \fB##\fP as a prefix to the output file names. This
+can be combined with the \-\-preserve\-paths option to use complete paths for
+both the main file and the included file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-n, \-\-no\-output
+Do not output any \fB\&.gcov\fP files. Summary information is still
+displayed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <DIR|FILE>, \-\-object\-directory=<DIR>, \-\-object\-file=<FILE>
+Find objects in DIR or based on FILE\(aqs path. If you specify a particular
+object file, the coverage data files are expected to have the same base name
+with \fB\&.gcno\fP and \fB\&.gcda\fP extensions. If you specify a directory, the
+files are expected in that directory with the same base name as the source
+file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-p, \-\-preserve\-paths
+Preserve path components when naming the coverage output files. In addition
+to the source file name, include the directories from the path to that
+file. The directories are separate by \fB#\fP characters, with \fB\&.\fP directories
+removed and \fB\&..\fP directories replaced by \fB^\fP characters. When used with
+the \-\-long\-file\-names option, this applies to both the main file name and the
+included file name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-r
+Only dump files with relative paths or absolute paths with the prefix specified
+by \fB\-s\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-s <string>
+Source prefix to elide.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-t, \-\-stdout
+Print to stdout instead of producing \fB\&.gcov\fP files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-u, \-\-unconditional\-branches
+Include unconditional branches in the output for the \-\-branch\-probabilities
+option.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-version
+Display the version of llvm\-cov.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x, \-\-hash\-filenames
+Use md5 hash of file name when naming the coverage output files. The source
+file name will be suffixed by \fB##\fP followed by MD5 hash calculated for it.
+.UNINDENT
+.SS EXIT STATUS
+.sp
+\fBllvm\-cov gcov\fP returns 1 if it cannot read input files. Otherwise,
+it exits with zero.
+.SH SHOW COMMAND
+.SS SYNOPSIS
+.sp
+\fBllvm\-cov show\fP [\fIoptions\fP] \-instr\-profile \fIPROFILE\fP [\fIBIN\fP] [\fI\-object BIN\fP]... [\fI\-sources\fP] [\fISOURCE\fP]...
+.SS DESCRIPTION
+.sp
+The \fBllvm\-cov show\fP command shows line by line coverage of the
+binaries \fIBIN\fP\&... using the profile data \fIPROFILE\fP\&. It can optionally be
+filtered to only show the coverage for the files listed in \fISOURCE\fP\&....
+.sp
+\fIBIN\fP may be an executable, object file, dynamic library, or archive (thin or
+otherwise).
+.sp
+To use \fBllvm\-cov show\fP, you need a program that is compiled with
+instrumentation to emit profile and coverage data. To build such a program with
+\fBclang\fP use the \fB\-fprofile\-instr\-generate\fP and \fB\-fcoverage\-mapping\fP
+flags. If linking with the \fBclang\fP driver, pass \fB\-fprofile\-instr\-generate\fP
+to the link stage to make sure the necessary runtime libraries are linked in.
+.sp
+The coverage information is stored in the built executable or library itself,
+and this is what you should pass to \fBllvm\-cov show\fP as a \fIBIN\fP
+argument. The profile data is generated by running this instrumented program
+normally. When the program exits it will write out a raw profile file,
+typically called \fBdefault.profraw\fP, which can be converted to a format that
+is suitable for the \fIPROFILE\fP argument using the \fBllvm\-profdata merge\fP
+tool.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-show\-branches=<VIEW>
+Show coverage for branch conditions in terms of either count or percentage.
+The supported views are: \(dqcount\(dq, \(dqpercent\(dq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-line\-counts
+Show the execution counts for each line. Defaults to true, unless another
+\fB\-show\fP option is used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-expansions
+Expand inclusions, such as preprocessor macros or textual inclusions, inline
+in the display of the source file. Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-instantiations
+For source regions that are instantiated multiple times, such as templates in
+\fBC++\fP, show each instantiation separately as well as the combined summary.
+Defaults to true.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-regions
+Show the execution counts for each region by displaying a caret that points to
+the character where the region starts. Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-line\-counts\-or\-regions
+Show the execution counts for each line if there is only one region on the
+line, but show the individual regions if there are multiple on the line.
+Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-use\-color
+Enable or disable color output. By default this is autodetected.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-arch=[*NAMES*]
+Specify a list of architectures such that the Nth entry in the list
+corresponds to the Nth specified binary. If the covered object is a universal
+binary, this specifies the architecture to use. It is an error to specify an
+architecture that is not included in the universal binary or to use an
+architecture that does not match a non\-universal binary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-name=<NAME>
+Show code coverage only for functions with the given name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-name\-allowlist=<FILE>
+Show code coverage only for functions listed in the given file. Each line in
+the file should start with \fIallowlist_fun:\fP, immediately followed by the name
+of the function to accept. This name can be a wildcard expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-name\-regex=<PATTERN>
+Show code coverage only for functions that match the given regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ignore\-filename\-regex=<PATTERN>
+Skip source code files with file paths that match the given regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-format=<FORMAT>
+Use the specified output format. The supported formats are: \(dqtext\(dq, \(dqhtml\(dq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-tab\-size=<TABSIZE>
+Replace tabs with <TABSIZE> spaces when preparing reports. Currently, this is
+only supported for the html format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-output\-dir=PATH
+Specify a directory to write coverage reports into. If the directory does not
+exist, it is created. When used in function view mode (i.e when \-name or
+\-name\-regex are used to select specific functions), the report is written to
+PATH/functions.EXTENSION. When used in file view mode, a report for each file
+is written to PATH/REL_PATH_TO_FILE.EXTENSION.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-Xdemangler=<TOOL>|<TOOL\-OPTION>
+Specify a symbol demangler. This can be used to make reports more
+human\-readable. This option can be specified multiple times to supply
+arguments to the demangler (e.g \fI\-Xdemangler c++filt \-Xdemangler \-n\fP for C++).
+The demangler is expected to read a newline\-separated list of symbols from
+stdin and write a newline\-separated list of the same length to stdout.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-num\-threads=N, \-j=N
+Use N threads to write file reports (only applicable when \-output\-dir is
+specified). When N=0, llvm\-cov auto\-detects an appropriate number of threads to
+use. This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-compilation\-dir=<dir>
+Directory used as a base for relative coverage mapping paths. Only applicable
+when binaries have been compiled with one of \fI\-fcoverage\-prefix\-map\fP
+\fI\-fcoverage\-compilation\-dir\fP, or \fI\-ffile\-compilation\-dir\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-line\-coverage\-gt=<N>
+Show code coverage only for functions with line coverage greater than the
+given threshold.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-line\-coverage\-lt=<N>
+Show code coverage only for functions with line coverage less than the given
+threshold.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-region\-coverage\-gt=<N>
+Show code coverage only for functions with region coverage greater than the
+given threshold.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-region\-coverage\-lt=<N>
+Show code coverage only for functions with region coverage less than the given
+threshold.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-path\-equivalence=<from>,<to>
+Map the paths in the coverage data to local source file paths. This allows you
+to generate the coverage data on one machine, and then use llvm\-cov on a
+different machine where you have the same files on a different path.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-coverage\-watermark=<high>,<low>
+Set high and low watermarks for coverage in html format output. This allows you
+to set the high and low watermark of coverage as desired, green when
+coverage >= high, red when coverage < low, and yellow otherwise. Both high and
+low should be between 0\-100 and high > low.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-debuginfod
+.UNINDENT
+.sp
+Use debuginfod to look up coverage mapping for binary IDs present in the profile
+but not in any object given on the command line. Defaults to true if debuginfod
+is compiled in and configured via the DEBUGINFOD_URLS environment variable.
+.INDENT 0.0
+.TP
+.B \-debug\-file\-directory=<dir>
+.UNINDENT
+.sp
+Provides local directories to search for objects corresponding to binary IDs in
+the profile (as with debuginfod). Defaults to system build ID directories.
+.SH REPORT COMMAND
+.SS SYNOPSIS
+.sp
+\fBllvm\-cov report\fP [\fIoptions\fP] \-instr\-profile \fIPROFILE\fP [\fIBIN\fP] [\fI\-object BIN\fP]... [\fI\-sources\fP] [\fISOURCE\fP]...
+.SS DESCRIPTION
+.sp
+The \fBllvm\-cov report\fP command displays a summary of the coverage of
+the binaries \fIBIN\fP\&... using the profile data \fIPROFILE\fP\&. It can optionally be
+filtered to only show the coverage for the files listed in \fISOURCE\fP\&....
+.sp
+\fIBIN\fP may be an executable, object file, dynamic library, or archive (thin or
+otherwise).
+.sp
+If no source files are provided, a summary line is printed for each file in the
+coverage data. If any files are provided, summaries can be shown for each
+function in the listed files if the \fB\-show\-functions\fP option is enabled.
+.sp
+For information on compiling programs for coverage and generating profile data,
+see \fI\%SHOW COMMAND\fP\&.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-use\-color[=VALUE]
+Enable or disable color output. By default this is autodetected.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-arch=<name>
+If the covered binary is a universal binary, select the architecture to use.
+It is an error to specify an architecture that is not included in the
+universal binary or to use an architecture that does not match a
+non\-universal binary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-region\-summary
+Show statistics for all regions. Defaults to true.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-branch\-summary
+Show statistics for all branch conditions. Defaults to true.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-functions
+Show coverage summaries for each function. Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-instantiation\-summary
+Show statistics for all function instantiations. Defaults to false.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ignore\-filename\-regex=<PATTERN>
+Skip source code files with file paths that match the given regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-compilation\-dir=<dir>
+Directory used as a base for relative coverage mapping paths. Only applicable
+when binaries have been compiled with one of \fI\-fcoverage\-prefix\-map\fP
+\fI\-fcoverage\-compilation\-dir\fP, or \fI\-ffile\-compilation\-dir\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-debuginfod
+.UNINDENT
+.sp
+Attempt to look up coverage mapping from objects using debuginfod. This is
+attempted by default for binary IDs present in the profile but not provided on
+the command line, so long as debuginfod is compiled in and configured via
+DEBUGINFOD_URLS.
+.INDENT 0.0
+.TP
+.B \-debug\-file\-directory=<dir>
+.UNINDENT
+.sp
+Provides a directory to search for objects corresponding to binary IDs in the
+profile.
+.SH EXPORT COMMAND
+.SS SYNOPSIS
+.sp
+\fBllvm\-cov export\fP [\fIoptions\fP] \-instr\-profile \fIPROFILE\fP [\fIBIN\fP] [\fI\-object BIN\fP]... [\fI\-sources\fP] [\fISOURCE\fP]...
+.SS DESCRIPTION
+.sp
+The \fBllvm\-cov export\fP command exports coverage data of the binaries
+\fIBIN\fP\&... using the profile data \fIPROFILE\fP in either JSON or lcov trace file
+format.
+.sp
+When exporting JSON, the regions, functions, branches, expansions, and
+summaries of the coverage data will be exported. When exporting an lcov trace
+file, the line\-based coverage, branch coverage, and summaries will be exported.
+.sp
+The exported data can optionally be filtered to only export the coverage
+for the files listed in \fISOURCE\fP\&....
+.sp
+For information on compiling programs for coverage and generating profile data,
+see \fI\%SHOW COMMAND\fP\&.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-arch=<name>
+If the covered binary is a universal binary, select the architecture to use.
+It is an error to specify an architecture that is not included in the
+universal binary or to use an architecture that does not match a
+non\-universal binary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-format=<FORMAT>
+Use the specified output format. The supported formats are: \(dqtext\(dq (JSON),
+\(dqlcov\(dq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-summary\-only
+Export only summary information for each file in the coverage data. This mode
+will not export coverage information for smaller units such as individual
+functions or regions. The result will contain the same information as produced
+by the \fBllvm\-cov report\fP command, but presented in JSON or lcov
+format rather than text.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ignore\-filename\-regex=<PATTERN>
+Skip source code files with file paths that match the given regular expression.
+.INDENT 7.0
+.TP
+.B \-skip\-expansions
+.UNINDENT
+.sp
+Skip exporting macro expansion coverage data.
+.INDENT 7.0
+.TP
+.B \-skip\-functions
+.UNINDENT
+.sp
+Skip exporting per\-function coverage data.
+.INDENT 7.0
+.TP
+.B \-num\-threads=N, \-j=N
+.UNINDENT
+.sp
+Use N threads to export coverage data. When N=0, llvm\-cov auto\-detects an
+appropriate number of threads to use. This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-compilation\-dir=<dir>
+Directory used as a base for relative coverage mapping paths. Only applicable
+when binaries have been compiled with one of \fI\-fcoverage\-prefix\-map\fP
+\fI\-fcoverage\-compilation\-dir\fP, or \fI\-ffile\-compilation\-dir\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-debuginfod
+.UNINDENT
+.sp
+Attempt to look up coverage mapping from objects using debuginfod. This is
+attempted by default for binary IDs present in the profile but not provided on
+the command line, so long as debuginfod is compiled in and configured via
+DEBUGINFOD_URLS.
+.INDENT 0.0
+.TP
+.B \-debug\-file\-directory=<dir>
+.UNINDENT
+.sp
+Provides a directory to search for objects corresponding to binary IDs in the
+profile.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-cxxdump/Makefile b/usr.bin/clang/llvm-cxxdump/Makefile
new file mode 100644
index 000000000000..40fccfefdafe
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxdump/Makefile
@@ -0,0 +1,8 @@
+PROG_CXX= llvm-cxxdump
+MAN=
+
+SRCDIR= llvm/tools/llvm-cxxdump
+SRCS+= Error.cpp
+SRCS+= llvm-cxxdump.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-cxxdump/Makefile.depend b/usr.bin/clang/llvm-cxxdump/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxdump/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-cxxfilt/Makefile b/usr.bin/clang/llvm-cxxfilt/Makefile
new file mode 100644
index 000000000000..f9621da8da89
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxfilt/Makefile
@@ -0,0 +1,30 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-cxxfilt
+
+SRCDIR= llvm/tools/llvm-cxxfilt
+SRCS+= llvm-cxxfilt-driver.cpp
+SRCS+= llvm-cxxfilt.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.if ${MK_LLVM_CXXFILT} != "no"
+LINKS= ${BINDIR}/llvm-cxxfilt ${BINDIR}/c++filt
+MLINKS= llvm-cxxfilt.1 c++filt.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-cxxfilt/Makefile.depend b/usr.bin/clang/llvm-cxxfilt/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxfilt/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt-driver.cpp b/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt-driver.cpp
new file mode 100644
index 000000000000..969ef2c6412e
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_cxxfilt_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_cxxfilt_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt.1 b/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt.1
new file mode 100644
index 000000000000..133ed151f0aa
--- /dev/null
+++ b/usr.bin/clang/llvm-cxxfilt/llvm-cxxfilt.1
@@ -0,0 +1,117 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-CXXFILT" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-cxxfilt \- LLVM symbol name demangler
+.SH SYNOPSIS
+.sp
+\fBllvm\-cxxfilt\fP [\fIoptions\fP] [\fImangled names...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-cxxfilt\fP is a symbol demangler that can be used as a replacement
+for the GNU \fBc++filt\fP tool. It takes a series of symbol names and
+prints their demangled form on the standard output stream. If a name cannot be
+demangled, it is simply printed as is.
+.sp
+If no names are specified on the command\-line, names are read interactively from
+the standard input stream. When reading names from standard input, each input
+line is split on characters that are not part of valid Itanium name manglings,
+i.e. characters that are not alphanumeric, \(aq.\(aq, \(aq$\(aq, or \(aq_\(aq. Separators between
+names are copied to the output as is.
+.SH EXAMPLE
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-cxxfilt _Z3foov _Z3bari not_mangled
+foo()
+bar(int)
+not_mangled
+$ cat input.txt
+| _Z3foov *** _Z3bari *** not_mangled |
+$ llvm\-cxxfilt < input.txt
+| foo() *** bar(int) *** not_mangled |
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-format=<value>, \-s
+Mangling scheme to assume. Valid values are \fBauto\fP (default, auto\-detect the
+style) and \fBgnu\fP (assume GNU/Itanium style).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-strip\-underscore, \-n
+Do not strip a leading underscore. This is the default for all platforms
+except Mach\-O based hosts.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-underscore, \-_
+Strip a single leading underscore, if present, from each input name before
+demangling. On by default on Mach\-O based platforms.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-types, \-t
+Attempt to demangle names as type names as well as function names.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-cxxfilt\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-cxxfilt\fP returns 0 unless it encounters a usage error, in which
+case a non\-zero exit code is returned.
+.SH SEE ALSO
+.sp
+\fBllvm\-nm(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-diff/Makefile b/usr.bin/clang/llvm-diff/Makefile
new file mode 100644
index 000000000000..90eddc9551d9
--- /dev/null
+++ b/usr.bin/clang/llvm-diff/Makefile
@@ -0,0 +1,9 @@
+PROG_CXX= llvm-diff
+
+SRCDIR= llvm/tools/llvm-diff
+SRCS+= lib/DiffConsumer.cpp
+SRCS+= lib/DiffLog.cpp
+SRCS+= lib/DifferenceEngine.cpp
+SRCS+= llvm-diff.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-diff/Makefile.depend b/usr.bin/clang/llvm-diff/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-diff/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-diff/llvm-diff.1 b/usr.bin/clang/llvm-diff/llvm-diff.1
new file mode 100644
index 000000000000..93439bd08dad
--- /dev/null
+++ b/usr.bin/clang/llvm-diff/llvm-diff.1
@@ -0,0 +1,76 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-DIFF" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-diff \- LLVM structural 'diff'
+.SH SYNOPSIS
+.sp
+\fBllvm\-diff\fP [\fIoptions\fP] \fImodule 1\fP \fImodule 2\fP [\fIglobal name ...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-diff\fP compares the structure of two LLVM modules, primarily
+focusing on differences in function definitions. Insignificant
+differences, such as changes in the ordering of globals or in the
+names of local values, are ignored.
+.sp
+An input module will be interpreted as an assembly file if its name
+ends in \(aq.ll\(aq; otherwise it will be read in as a bitcode file.
+.sp
+If a list of global names is given, just the values with those names
+are compared; otherwise, all global values are compared, and
+diagnostics are produced for globals which only appear in one module
+or the other.
+.sp
+\fBllvm\-diff\fP compares two functions by comparing their basic blocks,
+beginning with the entry blocks. If the terminators seem to match,
+then the corresponding successors are compared; otherwise they are
+ignored. This algorithm is very sensitive to changes in control flow,
+which tend to stop any downstream changes from being detected.
+.sp
+\fBllvm\-diff\fP is intended as a debugging tool for writers of LLVM
+passes and frontends. It does not have a stable output format.
+.SH EXIT STATUS
+.sp
+If \fBllvm\-diff\fP finds no differences between the modules, it will exit
+with 0 and produce no output. Otherwise it will exit with a non\-zero
+value.
+.SH BUGS
+.sp
+Many important differences, like changes in linkage or function
+attributes, are not diagnosed.
+.sp
+Changes in memory behavior (for example, coalescing loads) can cause
+massive detected differences in blocks.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-dis/Makefile b/usr.bin/clang/llvm-dis/Makefile
new file mode 100644
index 000000000000..a290c4647c31
--- /dev/null
+++ b/usr.bin/clang/llvm-dis/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= llvm-dis
+
+SRCDIR= llvm/tools/llvm-dis
+SRCS+= llvm-dis.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-dis/Makefile.depend b/usr.bin/clang/llvm-dis/Makefile.depend
new file mode 100644
index 000000000000..dd4c6894d092
--- /dev/null
+++ b/usr.bin/clang/llvm-dis/Makefile.depend
@@ -0,0 +1,22 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-dis/llvm-dis.1 b/usr.bin/clang/llvm-dis/llvm-dis.1
new file mode 100644
index 000000000000..9a0580d8c2c5
--- /dev/null
+++ b/usr.bin/clang/llvm-dis/llvm-dis.1
@@ -0,0 +1,87 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-DIS" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-dis \- LLVM disassembler
+.SH SYNOPSIS
+.sp
+\fBllvm\-dis\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-dis\fP command is the LLVM disassembler. It takes an LLVM
+bitcode file and converts it into human\-readable LLVM assembly language.
+.sp
+If filename is omitted or specified as \fB\-\fP, \fBllvm\-dis\fP reads its
+input from standard input.
+.sp
+If the input is being read from standard input, then \fBllvm\-dis\fP
+will send its output to standard output by default. Otherwise, the
+output will be written to a file named after the input file, with
+a \fB\&.ll\fP suffix added (any existing \fB\&.bc\fP suffix will first be
+removed). You can override the choice of output file using the
+\fB\-o\fP option.
+.SH OPTIONS
+.sp
+\fB\-f\fP
+.INDENT 0.0
+.INDENT 3.5
+Enable binary output on terminals. Normally, \fBllvm\-dis\fP will refuse to
+write raw bitcode output if the output stream is a terminal. With this option,
+\fBllvm\-dis\fP will write raw bitcode regardless of the output device.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-help\fP
+.INDENT 0.0
+.INDENT 3.5
+Print a summary of command line options.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-o\fP \fIfilename\fP
+.INDENT 0.0
+.INDENT 3.5
+Specify the output file name. If \fIfilename\fP is \-, then the output is sent
+to standard output.
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-dis\fP succeeds, it will exit with 0. Otherwise, if an error
+occurs, it will exit with a non\-zero value.
+.SH SEE ALSO
+.sp
+\fBllvm\-as(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-dwarfdump/Makefile b/usr.bin/clang/llvm-dwarfdump/Makefile
new file mode 100644
index 000000000000..cdbf9822b2ac
--- /dev/null
+++ b/usr.bin/clang/llvm-dwarfdump/Makefile
@@ -0,0 +1,8 @@
+PROG_CXX= llvm-dwarfdump
+
+SRCDIR= llvm/tools/llvm-dwarfdump
+SRCS+= SectionSizes.cpp
+SRCS+= Statistics.cpp
+SRCS+= llvm-dwarfdump.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-dwarfdump/Makefile.depend b/usr.bin/clang/llvm-dwarfdump/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-dwarfdump/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-dwarfdump/llvm-dwarfdump.1 b/usr.bin/clang/llvm-dwarfdump/llvm-dwarfdump.1
new file mode 100644
index 000000000000..7e3c9b6fb6e7
--- /dev/null
+++ b/usr.bin/clang/llvm-dwarfdump/llvm-dwarfdump.1
@@ -0,0 +1,272 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-DWARFDUMP" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-dwarfdump \- dump and verify DWARF debug information
+.SH SYNOPSIS
+.sp
+\fBllvm\-dwarfdump\fP [\fIoptions\fP] [\fIfilename ...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-dwarfdump\fP parses DWARF sections in object files,
+archives, and \fI\&.dSYM\fP bundles and prints their contents in
+human\-readable form. Only the .debug_info section is printed unless one of
+the section\-specific options or \fI\%\-\-all\fP is specified.
+.sp
+If no input file is specified, \fIa.out\fP is used instead. If \fI\-\fP is used as the
+input file, \fBllvm\-dwarfdump\fP reads the input from its standard input
+stream.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-a, \-\-all
+Dump all supported DWARF sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-arch=<arch>
+Dump DWARF debug information for the specified CPU architecture.
+Architectures may be specified by name or by number. This
+option can be specified multiple times, once for each desired
+architecture. All CPU architectures will be printed by
+default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-c, \-\-show\-children
+Show a debug info entry\(aqs children when selectively printing with
+the \fI=<offset>\fP argument of \fI\%\-\-debug\-info\fP, or options such
+as \fI\%\-\-find\fP or \fI\%\-\-name\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-color
+Use colors in output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-f <name>, \-\-find=<name>
+Search for the exact text <name> in the accelerator tables
+and print the matching debug information entries.
+When there is no accelerator tables or the name of the DIE
+you are looking for is not found in the accelerator tables,
+try using the slower but more complete \fI\%\-\-name\fP option.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-F, \-\-show\-form
+Show DWARF form types after the DWARF attribute types.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-h, \-\-help
+Show help and usage for this command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help\-list
+Show help and usage for this command without grouping the options
+into categories.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-i, \-\-ignore\-case
+Ignore case distinctions when using \fI\%\-\-name\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-n <name>, \-\-name=<name>
+Find and print all debug info entries whose name
+(\fIDW_AT_name\fP attribute) is <name>.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-lookup=<address>
+Look up <address> in the debug information and print out the file,
+function, block, and line table details.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <path>
+Redirect output to a file specified by <path>, where \fI\-\fP is the
+standard output stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-p, \-\-show\-parents
+Show a debug info entry\(aqs parents when selectively printing with
+the \fI=<offset>\fP argument of \fI\%\-\-debug\-info\fP, or options such
+as \fI\%\-\-find\fP or \fI\%\-\-name\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-parent\-recurse\-depth=<N>
+When displaying debug info entry parents, only show them to a
+maximum depth of <N>.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-quiet
+Use with \fI\%\-\-verify\fP to not emit to \fISTDOUT\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-r <N>, \-\-recurse\-depth=<N>
+When displaying debug info entries, only show children to a maximum
+depth of <N>.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-section\-sizes
+Show the sizes of all debug sections, expressed in bytes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-sources
+Print all source files mentioned in the debug information. Absolute
+paths are given whenever possible.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-statistics
+Collect debug info quality metrics and print the results
+as machine\-readable single\-line JSON output. The output
+format is described in the section below (\fI\%FORMAT OF STATISTICS OUTPUT\fP).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-summarize\-types
+Abbreviate the description of type unit entries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x, \-\-regex
+Treat any <name> strings as regular expressions when searching
+with \fI\%\-\-name\fP\&. If \fI\%\-\-ignore\-case\fP is also specified,
+the regular expression becomes case\-insensitive.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-u, \-\-uuid
+Show the UUID for each architecture.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-diff
+Dump the output in a format that is more friendly for comparing
+DWARF output from two different files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v, \-\-verbose
+Display verbose information when dumping. This can help to debug
+DWARF issues.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-verify
+Verify the structure of the DWARF information by verifying the
+compile unit chains, DIE relationships graph, address
+ranges, and more.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the tool.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-abbrev, \-\-debug\-addr, \-\-debug\-aranges, \-\-debug\-cu\-index, \-\-debug\-frame [=<offset>], \-\-debug\-gnu\-pubnames, \-\-debug\-gnu\-pubtypes, \-\-debug\-info [=<offset>], \-\-debug\-line [=<offset>], \-\-debug\-line\-str, \-\-debug\-loc [=<offset>], \-\-debug\-loclists [=<offset>], \-\-debug\-macro, \-\-debug\-names, \-\-debug\-pubnames, \-\-debug\-pubtypes, \-\-debug\-ranges, \-\-debug\-rnglists, \-\-debug\-str, \-\-debug\-str\-offsets, \-\-debug\-tu\-index, \-\-debug\-types [=<offset>], \-\-eh\-frame [=<offset>], \-\-gdb\-index, \-\-apple\-names, \-\-apple\-types, \-\-apple\-namespaces, \-\-apple\-objc
+Dump the specified DWARF section by name. Only the
+\fI\&.debug_info\fP section is shown by default. Some entries
+support adding an \fI=<offset>\fP as a way to provide an
+optional offset of the exact entry to dump within the
+respective section. When an offset is provided, only the
+entry at that offset will be dumped, else the entire
+section will be dumped.
+.sp
+The \fI\%\-\-debug\-macro\fP option prints both the .debug_macro and the .debug_macinfo sections.
+.sp
+The \fI\%\-\-debug\-frame\fP and \fI\%\-\-eh\-frame\fP options are aliases, in cases where both sections are present one command outputs both.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from \fI<FILE>\fP\&.
+.UNINDENT
+.SH FORMAT OF STATISTICS OUTPUT
+.sp
+The \fI\%\-\-statistics\fP option generates single\-line JSON output
+representing quality metrics of the processed debug info. These metrics are
+useful to compare changes between two compilers, particularly for judging
+the effect that a change to the compiler has on the debug info quality.
+.sp
+The output is formatted as key\-value pairs. The first pair contains a version
+number. The following naming scheme is used for the keys:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fIvariables\fP ==> local variables and parameters
+.IP \(bu 2
+\fIlocal vars\fP ==> local variables
+.IP \(bu 2
+\fIparams\fP ==> formal parameters
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+For aggregated values, the following keys are used:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fIsum_of_all_variables(...)\fP ==> the sum applied to all variables
+.IP \(bu 2
+\fI#bytes\fP ==> the number of bytes
+.IP \(bu 2
+\fI#variables \- entry values ...\fP ==> the number of variables excluding
+the entry values etc.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-dwarfdump\fP returns 0 if the input files were parsed and dumped
+successfully. Otherwise, it returns 1.
+.SH SEE ALSO
+.sp
+\fBdsymutil(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-dwarfutil/Makefile b/usr.bin/clang/llvm-dwarfutil/Makefile
new file mode 100644
index 000000000000..884ce922492e
--- /dev/null
+++ b/usr.bin/clang/llvm-dwarfutil/Makefile
@@ -0,0 +1,23 @@
+PROG_CXX= llvm-dwarfutil
+
+SRCDIR= llvm/tools/llvm-dwarfutil
+SRCS+= DebugInfoLinker.cpp
+SRCS+= llvm-dwarfutil.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Options.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Options.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-dwarfutil/llvm-dwarfutil.1 b/usr.bin/clang/llvm-dwarfutil/llvm-dwarfutil.1
new file mode 100644
index 000000000000..15015e96f5a7
--- /dev/null
+++ b/usr.bin/clang/llvm-dwarfutil/llvm-dwarfutil.1
@@ -0,0 +1,168 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-DWARFUTIL" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-dwarfutil \- A tool to copy and manipulate debug info
+.SH SYNOPSIS
+.sp
+\fBllvm\-dwarfutil\fP [\fIoptions\fP] \fIinput\fP \fIoutput\fP
+.SH DESCRIPTION
+.sp
+\fBllvm\-dwarfutil\fP is a tool to copy and manipulate debug info.
+.sp
+In basic usage, it makes a semantic copy of the input to the output. If any
+options are specified, the output may be modified along the way, e.g.
+by removing unused debug info.
+.sp
+If \(dq\-\(dq is specified for the input file, the input is read from the program\(aqs
+standard input stream. If \(dq\-\(dq is specified for the output file, the output
+is written to the standard output stream of the program.
+.sp
+The tool is still in active development.
+.SH COMMAND-LINE OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-garbage\-collection
+Removes pieces of debug information related to discarded sections.
+When the linker does section garbage collection the abandoned debug info
+is left behind. Such abandoned debug info references address ranges using
+tombstone values. Thus, when this option is specified, the tool removes
+debug info which is marked with the tombstone value.
+.sp
+That option is enabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-odr\-deduplication
+Remove duplicated types (if \(dqOne Definition Rule\(dq is supported by source
+language). Keeps first type definition and removes other definitions,
+potentially significantly reducing the size of output debug info.
+.sp
+That option is enabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-garbage\-collection
+Disable \fI\%\-\-garbage\-collection\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-odr\-deduplication
+Disable \fI\%\-\-odr\-deduplication\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-separate\-debug\-file
+Disable \fI\%\-\-separate\-debug\-file\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-num\-threads=<n>, \-j
+Specifies the maximum number (\fIn\fP) of simultaneous threads to use
+for processing.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-separate\-debug\-file
+Generate separate file containing output debug info. Using
+\fBllvm\-dwarfutil\fP with that option equals to the
+following set of commands:
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+:program:\(gallvm\-objcopy\(ga \-\-only\-keep\-debug in\-file out\-file.debug
+:program:\(gallvm\-objcopy\(ga \-\-strip\-debug in\-file out\-file
+:program:\(gallvm\-objcopy\(ga \-\-add\-gnu\-debuglink=out\-file.debug out\-file
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-tombstone=<value>
+<value> can be one of the following values:
+.INDENT 7.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fIbfd\fP: zero for all addresses and [1,1] for DWARF v4 (or less) address ranges and exec.
+.IP \(bu 2
+\fImaxpc\fP: \-1 for all addresses and \-2 for DWARF v4 (or less) address ranges.
+.IP \(bu 2
+\fIuniversal\fP: both \fIbfd\fP and \fImaxpc\fP\&.
+.IP \(bu 2
+\fIexec\fP: match with address ranges of executable sections.
+.UNINDENT
+.sp
+The value \fIuniversal\fP is used by default.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-verbose
+Enable verbose logging. This option disables multi\-thread mode.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-verify
+Run the DWARF verifier on the output DWARF debug info.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Print the version of this program.
+.UNINDENT
+.SH SUPPORTED FORMATS
+.sp
+The following formats are currently supported by \fBllvm\-dwarfutil\fP:
+.sp
+ELF
+.SH EXIT STATUS
+.sp
+\fBllvm\-dwarfutil\fP exits with a non\-zero exit code if there is an error.
+Otherwise, it exits with code 0.
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/labels/tools:llvm\-dwarfutil/\fP>.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-dwp/Makefile b/usr.bin/clang/llvm-dwp/Makefile
new file mode 100644
index 000000000000..1d66929143e1
--- /dev/null
+++ b/usr.bin/clang/llvm-dwp/Makefile
@@ -0,0 +1,24 @@
+PROG_CXX= llvm-dwp
+MAN=
+
+SRCDIR= llvm/tools/llvm-dwp
+SRCS+= llvm-dwp-driver.cpp
+SRCS+= llvm-dwp.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-dwp/llvm-dwp-driver.cpp b/usr.bin/clang/llvm-dwp/llvm-dwp-driver.cpp
new file mode 100644
index 000000000000..79077cd973a9
--- /dev/null
+++ b/usr.bin/clang/llvm-dwp/llvm-dwp-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_dwp_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_dwp_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-extract/Makefile b/usr.bin/clang/llvm-extract/Makefile
new file mode 100644
index 000000000000..898414d0fca1
--- /dev/null
+++ b/usr.bin/clang/llvm-extract/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= llvm-extract
+
+SRCDIR= llvm/tools/llvm-extract
+SRCS+= llvm-extract.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-extract/Makefile.depend b/usr.bin/clang/llvm-extract/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-extract/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-extract/llvm-extract.1 b/usr.bin/clang/llvm-extract/llvm-extract.1
new file mode 100644
index 000000000000..b5f3550e8f76
--- /dev/null
+++ b/usr.bin/clang/llvm-extract/llvm-extract.1
@@ -0,0 +1,176 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-EXTRACT" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-extract \- extract a function from an LLVM module
+.SH SYNOPSIS
+.sp
+\fBllvm\-extract\fP [\fIoptions\fP] \fB\-\-func\fP \fIfunction\-name\fP [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-extract\fP command takes the name of a function and extracts
+it from the specified LLVM bitcode file. It is primarily used as a debugging
+tool to reduce test cases from larger programs that are triggering a bug.
+.sp
+In addition to extracting the bitcode of the specified function,
+\fBllvm\-extract\fP will also remove unreachable global variables,
+prototypes, and unused types.
+.sp
+The \fBllvm\-extract\fP command reads its input from standard input if
+filename is omitted or if filename is \fB\-\fP\&. The output is always written to
+standard output, unless the \fB\-o\fP option is specified (see below).
+.SH OPTIONS
+.sp
+\fB\-\-alias\fP \fIalias\-name\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the alias named \fIfunction\-name\fP from the LLVM bitcode. May be
+specified multiple times to extract multiple alias at once.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-ralias\fP \fIalias\-regular\-expr\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the alias matching \fIalias\-regular\-expr\fP from the LLVM bitcode.
+All alias matching the regular expression will be extracted. May be
+specified multiple times.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-bb\fP \fIbasic\-block\-specifier\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract basic blocks(s) specified in \fIbasic\-block\-specifier\fP\&. May be
+specified multiple times. Each <function:bb[;bb]> specifier pair will create
+a function. If multiple basic blocks are specified in one pair, the first
+block in the sequence should dominate the rest.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-delete\fP
+.INDENT 0.0
+.INDENT 3.5
+Delete specified Globals from Module.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-f\fP
+.INDENT 0.0
+.INDENT 3.5
+Enable binary output on terminals. Normally, \fBllvm\-extract\fP will
+refuse to write raw bitcode output if the output stream is a terminal. With
+this option, \fBllvm\-extract\fP will write raw bitcode regardless of the
+output device.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-func\fP \fIfunction\-name\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the function named \fIfunction\-name\fP from the LLVM bitcode. May be
+specified multiple times to extract multiple functions at once.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-rfunc\fP \fIfunction\-regular\-expr\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the function(s) matching \fIfunction\-regular\-expr\fP from the LLVM bitcode.
+All functions matching the regular expression will be extracted. May be
+specified multiple times.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-glob\fP \fIglobal\-name\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the global variable named \fIglobal\-name\fP from the LLVM bitcode. May be
+specified multiple times to extract multiple global variables at once.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-rglob\fP \fIglob\-regular\-expr\fP
+.INDENT 0.0
+.INDENT 3.5
+Extract the global variable(s) matching \fIglobal\-regular\-expr\fP from the LLVM
+bitcode. All global variables matching the regular expression will be
+extracted. May be specified multiple times.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-keep\-const\-init\fP
+.INDENT 0.0
+.INDENT 3.5
+Preserve the values of constant globals.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-\-recursive\fP
+.INDENT 0.0
+.INDENT 3.5
+Recursively extract all called functions
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-help\fP
+.INDENT 0.0
+.INDENT 3.5
+Print a summary of command line options.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-o\fP \fIfilename\fP
+.INDENT 0.0
+.INDENT 3.5
+Specify the output filename. If filename is \(dq\-\(dq (the default), then
+\fBllvm\-extract\fP sends its output to standard output.
+.UNINDENT
+.UNINDENT
+.sp
+\fB\-S\fP
+.INDENT 0.0
+.INDENT 3.5
+Write output in LLVM intermediate language (instead of bitcode).
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-extract\fP succeeds, it will exit with 0. Otherwise, if an error
+occurs, it will exit with a non\-zero value.
+.SH SEE ALSO
+.sp
+\fBbugpoint(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-link/Makefile b/usr.bin/clang/llvm-link/Makefile
new file mode 100644
index 000000000000..a83de498fd32
--- /dev/null
+++ b/usr.bin/clang/llvm-link/Makefile
@@ -0,0 +1,6 @@
+PROG_CXX= llvm-link
+
+SRCDIR= llvm/tools/llvm-link
+SRCS+= llvm-link.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-link/Makefile.depend b/usr.bin/clang/llvm-link/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-link/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-link/llvm-link.1 b/usr.bin/clang/llvm-link/llvm-link.1
new file mode 100644
index 000000000000..3fcc85ba1eb3
--- /dev/null
+++ b/usr.bin/clang/llvm-link/llvm-link.1
@@ -0,0 +1,88 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-LINK" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-link \- LLVM bitcode linker
+.SH SYNOPSIS
+.sp
+\fBllvm\-link\fP [\fIoptions\fP] \fIfilename ...\fP
+.SH DESCRIPTION
+.sp
+\fBllvm\-link\fP takes several LLVM bitcode files and links them together
+into a single LLVM bitcode file. It writes the output file to standard output,
+unless the \fI\%\-o\fP option is used to specify a filename.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-f
+Enable binary output on terminals. Normally, \fBllvm\-link\fP will refuse
+to write raw bitcode output if the output stream is a terminal. With this
+option, \fBllvm\-link\fP will write raw bitcode regardless of the output
+device.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o filename
+Specify the output file name. If \fBfilename\fP is \(dq\fB\-\fP\(dq, then
+\fBllvm\-link\fP will write its output to standard output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S
+Write output in LLVM intermediate language (instead of bitcode).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-d
+If specified, \fBllvm\-link\fP prints a human\-readable version of the
+output bitcode file to standard error.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v
+Verbose mode. Print information about what \fBllvm\-link\fP is doing.
+This typically includes a message for each bitcode file linked in and for each
+library found.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBllvm\-link\fP succeeds, it will exit with 0. Otherwise, if an error
+occurs, it will exit with a non\-zero value.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-lto/Makefile b/usr.bin/clang/llvm-lto/Makefile
new file mode 100644
index 000000000000..8793b8e6a674
--- /dev/null
+++ b/usr.bin/clang/llvm-lto/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llvm-lto
+MAN=
+
+SRCDIR= llvm/tools/llvm-lto
+SRCS= llvm-lto.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-lto/Makefile.depend b/usr.bin/clang/llvm-lto/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-lto/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-lto2/Makefile b/usr.bin/clang/llvm-lto2/Makefile
new file mode 100644
index 000000000000..68c16d422051
--- /dev/null
+++ b/usr.bin/clang/llvm-lto2/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llvm-lto2
+MAN=
+
+SRCDIR= llvm/tools/llvm-lto2
+SRCS= llvm-lto2.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-lto2/Makefile.depend b/usr.bin/clang/llvm-lto2/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-lto2/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-mc/Makefile b/usr.bin/clang/llvm-mc/Makefile
new file mode 100644
index 000000000000..876720b09b70
--- /dev/null
+++ b/usr.bin/clang/llvm-mc/Makefile
@@ -0,0 +1,8 @@
+PROG_CXX= llvm-mc
+MAN=
+
+SRCDIR= llvm/tools/llvm-mc
+SRCS+= Disassembler.cpp
+SRCS+= llvm-mc.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-mc/Makefile.depend b/usr.bin/clang/llvm-mc/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-mc/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-mca/Makefile b/usr.bin/clang/llvm-mca/Makefile
new file mode 100644
index 000000000000..274b7a43e5fe
--- /dev/null
+++ b/usr.bin/clang/llvm-mca/Makefile
@@ -0,0 +1,21 @@
+PROG_CXX= llvm-mca
+
+SRCDIR= llvm/tools/llvm-mca
+SRCS+= CodeRegion.cpp
+SRCS+= CodeRegionGenerator.cpp
+SRCS+= PipelinePrinter.cpp
+SRCS+= Views/BottleneckAnalysis.cpp
+SRCS+= Views/DispatchStatistics.cpp
+SRCS+= Views/InstructionInfoView.cpp
+SRCS+= Views/InstructionView.cpp
+SRCS+= Views/RegisterFileStatistics.cpp
+SRCS+= Views/ResourcePressureView.cpp
+SRCS+= Views/RetireControlUnitStatistics.cpp
+SRCS+= Views/SchedulerStatistics.cpp
+SRCS+= Views/SummaryView.cpp
+SRCS+= Views/TimelineView.cpp
+SRCS+= llvm-mca.cpp
+
+CFLAGS+= -I${LLVM_BASE}/${SRCDIR}
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-mca/llvm-mca.1 b/usr.bin/clang/llvm-mca/llvm-mca.1
new file mode 100644
index 000000000000..7c30c5e95336
--- /dev/null
+++ b/usr.bin/clang/llvm-mca/llvm-mca.1
@@ -0,0 +1,1368 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-MCA" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-mca \- LLVM Machine Code Analyzer
+.SH SYNOPSIS
+.sp
+\fBllvm\-mca\fP [\fIoptions\fP] [input]
+.SH DESCRIPTION
+.sp
+\fBllvm\-mca\fP is a performance analysis tool that uses information
+available in LLVM (e.g. scheduling models) to statically measure the performance
+of machine code in a specific CPU.
+.sp
+Performance is measured in terms of throughput as well as processor resource
+consumption. The tool currently works for processors with a backend for which
+there is a scheduling model available in LLVM.
+.sp
+The main goal of this tool is not just to predict the performance of the code
+when run on the target, but also help with diagnosing potential performance
+issues.
+.sp
+Given an assembly code sequence, \fBllvm\-mca\fP estimates the Instructions
+Per Cycle (IPC), as well as hardware resource pressure. The analysis and
+reporting style were inspired by the IACA tool from Intel.
+.sp
+For example, you can compile code with clang, output assembly, and pipe it
+directly into \fBllvm\-mca\fP for analysis:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ clang foo.c \-O2 \-target x86_64\-unknown\-unknown \-S \-o \- | llvm\-mca \-mcpu=btver2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Or for Intel syntax:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ clang foo.c \-O2 \-target x86_64\-unknown\-unknown \-mllvm \-x86\-asm\-syntax=intel \-S \-o \- | llvm\-mca \-mcpu=btver2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+(\fBllvm\-mca\fP detects Intel syntax by the presence of an \fI\&.intel_syntax\fP
+directive at the beginning of the input. By default its output syntax matches
+that of its input.)
+.sp
+Scheduling models are not just used to compute instruction latencies and
+throughput, but also to understand what processor resources are available
+and how to simulate them.
+.sp
+By design, the quality of the analysis conducted by \fBllvm\-mca\fP is
+inevitably affected by the quality of the scheduling models in LLVM.
+.sp
+If you see that the performance report is not accurate for a processor,
+please \fI\%file a bug\fP
+against the appropriate backend.
+.SH OPTIONS
+.sp
+If \fBinput\fP is \(dq\fB\-\fP\(dq or omitted, \fBllvm\-mca\fP reads from standard
+input. Otherwise, it will read from the specified filename.
+.sp
+If the \fI\%\-o\fP option is omitted, then \fBllvm\-mca\fP will send its output
+to standard output if the input is from standard input. If the \fI\%\-o\fP
+option specifies \(dq\fB\-\fP\(dq, then the output will also be sent to standard output.
+.INDENT 0.0
+.TP
+.B \-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <filename>
+Use \fB<filename>\fP as the output filename. See the summary above for more
+details.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mtriple=<target triple>
+Specify a target triple string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-march=<arch>
+Specify the architecture for which to analyze the code. It defaults to the
+host default target.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-mcpu=<cpuname>
+Specify the processor for which to analyze the code. By default, the cpu name
+is autodetected from the host.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-output\-asm\-variant=<variant id>
+Specify the output assembly variant for the report generated by the tool.
+On x86, possible values are [0, 1]. A value of 0 (vic. 1) for this flag enables
+the AT&T (vic. Intel) assembly format for the code printed out by the tool in
+the analysis report.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-imm\-hex
+Prefer hex format for numeric literals in the output assembly printed as part
+of the report.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-dispatch=<width>
+Specify a different dispatch width for the processor. The dispatch width
+defaults to field \(aqIssueWidth\(aq in the processor scheduling model. If width is
+zero, then the default dispatch width is used.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-register\-file\-size=<size>
+Specify the size of the register file. When specified, this flag limits how
+many physical registers are available for register renaming purposes. A value
+of zero for this flag means \(dqunlimited number of physical registers\(dq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-iterations=<number of iterations>
+Specify the number of iterations to run. If this flag is set to 0, then the
+tool sets the number of iterations to a default value (i.e. 100).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-noalias=<bool>
+If set, the tool assumes that loads and stores don\(aqt alias. This is the
+default behavior.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-lqueue=<load queue size>
+Specify the size of the load queue in the load/store unit emulated by the tool.
+By default, the tool assumes an unbound number of entries in the load queue.
+A value of zero for this flag is ignored, and the default load queue size is
+used instead.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-squeue=<store queue size>
+Specify the size of the store queue in the load/store unit emulated by the
+tool. By default, the tool assumes an unbound number of entries in the store
+queue. A value of zero for this flag is ignored, and the default store queue
+size is used instead.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-timeline
+Enable the timeline view.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-timeline\-max\-iterations=<iterations>
+Limit the number of iterations to print in the timeline view. By default, the
+timeline view prints information for up to 10 iterations.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-timeline\-max\-cycles=<cycles>
+Limit the number of cycles in the timeline view, or use 0 for no limit. By
+default, the number of cycles is set to 80.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-resource\-pressure
+Enable the resource pressure view. This is enabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-register\-file\-stats
+Enable register file usage statistics.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-dispatch\-stats
+Enable extra dispatch statistics. This view collects and analyzes instruction
+dispatch events, as well as static/dynamic dispatch stall events. This view
+is disabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-scheduler\-stats
+Enable extra scheduler statistics. This view collects and analyzes instruction
+issue events. This view is disabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-retire\-stats
+Enable extra retire control unit statistics. This view is disabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-instruction\-info
+Enable the instruction info view. This is enabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-encoding
+Enable the printing of instruction encodings within the instruction info view.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-show\-barriers
+Enable the printing of LoadBarrier and StoreBarrier flags within the
+instruction info view.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-all\-stats
+Print all hardware statistics. This enables extra statistics related to the
+dispatch logic, the hardware schedulers, the register file(s), and the retire
+control unit. This option is disabled by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-all\-views
+Enable all the view.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-instruction\-tables
+Prints resource pressure information based on the static information
+available from the processor model. This differs from the resource pressure
+view because it doesn\(aqt require that the code is simulated. It instead prints
+the theoretical uniform distribution of resource pressure for every
+instruction in sequence.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-bottleneck\-analysis
+Print information about bottlenecks that affect the throughput. This analysis
+can be expensive, and it is disabled by default. Bottlenecks are highlighted
+in the summary view. Bottleneck analysis is currently not supported for
+processors with an in\-order backend.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-json
+Print the requested views in valid JSON format. The instructions and the
+processor resources are printed as members of special top level JSON objects.
+The individual views refer to them by index. However, not all views are
+currently supported. For example, the report from the bottleneck analysis is
+not printed out in JSON. All the default views are currently supported.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-disable\-cb
+Force usage of the generic CustomBehaviour and InstrPostProcess classes rather
+than using the target specific implementation. The generic classes never
+detect any custom hazards or make any post processing modifications to
+instructions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-disable\-im
+Force usage of the generic InstrumentManager rather than using the target
+specific implementation. The generic class creates Instruments that provide
+no extra information, and InstrumentManager never overrides the default
+schedule class for a given instruction.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-mca\fP returns 0 on success. Otherwise, an error message is printed
+to standard error, and the tool returns 1.
+.SH USING MARKERS TO ANALYZE SPECIFIC CODE BLOCKS
+.sp
+\fBllvm\-mca\fP allows for the optional usage of special code comments to
+mark regions of the assembly code to be analyzed. A comment starting with
+substring \fBLLVM\-MCA\-BEGIN\fP marks the beginning of an analysis region. A
+comment starting with substring \fBLLVM\-MCA\-END\fP marks the end of a region.
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-BEGIN
+ ...
+# LLVM\-MCA\-END
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If no user\-defined region is specified, then \fBllvm\-mca\fP assumes a
+default region which contains every instruction in the input file. Every region
+is analyzed in isolation, and the final performance report is the union of all
+the reports generated for every analysis region.
+.sp
+Analysis regions can have names. For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-BEGIN A simple example
+ add %eax, %eax
+# LLVM\-MCA\-END
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The code from the example above defines a region named \(dqA simple example\(dq with a
+single instruction in it. Note how the region name doesn\(aqt have to be repeated
+in the \fBLLVM\-MCA\-END\fP directive. In the absence of overlapping regions,
+an anonymous \fBLLVM\-MCA\-END\fP directive always ends the currently active user
+defined region.
+.sp
+Example of nesting regions:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-BEGIN foo
+ add %eax, %edx
+# LLVM\-MCA\-BEGIN bar
+ sub %eax, %edx
+# LLVM\-MCA\-END bar
+# LLVM\-MCA\-END foo
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example of overlapping regions:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-BEGIN foo
+ add %eax, %edx
+# LLVM\-MCA\-BEGIN bar
+ sub %eax, %edx
+# LLVM\-MCA\-END foo
+ add %eax, %edx
+# LLVM\-MCA\-END bar
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Note that multiple anonymous regions cannot overlap. Also, overlapping regions
+cannot have the same name.
+.sp
+There is no support for marking regions from high\-level source code, like C or
+C++. As a workaround, inline assembly directives may be used:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+int foo(int a, int b) {
+ __asm volatile(\(dq# LLVM\-MCA\-BEGIN foo\(dq:::\(dqmemory\(dq);
+ a += 42;
+ __asm volatile(\(dq# LLVM\-MCA\-END\(dq:::\(dqmemory\(dq);
+ a *= b;
+ return a;
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+However, this interferes with optimizations like loop vectorization and may have
+an impact on the code generated. This is because the \fB__asm\fP statements are
+seen as real code having important side effects, which limits how the code
+around them can be transformed. If users want to make use of inline assembly
+to emit markers, then the recommendation is to always verify that the output
+assembly is equivalent to the assembly generated in the absence of markers.
+The \fI\%Clang options to emit optimization reports\fP
+can also help in detecting missed optimizations.
+.SH INSTRUMENT REGIONS
+.sp
+An InstrumentRegion describes a region of assembly code guarded by
+special LLVM\-MCA comment directives.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-<INSTRUMENT_TYPE> <data>
+ ... ## asm
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+where \fIINSTRUMENT_TYPE\fP is a type defined by the target and expects
+to use \fIdata\fP\&.
+.sp
+A comment starting with substring \fILLVM\-MCA\-<INSTRUMENT_TYPE>\fP
+brings data into scope for llvm\-mca to use in its analysis for
+all following instructions.
+.sp
+If a comment with the same \fIINSTRUMENT_TYPE\fP is found later in the
+instruction list, then the original InstrumentRegion will be
+automatically ended, and a new InstrumentRegion will begin.
+.sp
+If there are comments containing the different \fIINSTRUMENT_TYPE\fP,
+then both data sets remain available. In contrast with an AnalysisRegion,
+an InstrumentRegion does not need a comment to end the region.
+.sp
+Comments that are prefixed with \fILLVM\-MCA\-\fP but do not correspond to
+a valid \fIINSTRUMENT_TYPE\fP for the target cause an error, except for
+\fIBEGIN\fP and \fIEND\fP, since those correspond to AnalysisRegions. Comments
+that do not start with \fILLVM\-MCA\-\fP are ignored by :program \fIllvm\-mca\fP\&.
+.sp
+An instruction (a MCInst) is added to an InstrumentRegion R only
+if its location is in range [R.RangeStart, R.RangeEnd].
+.sp
+On RISCV targets, vector instructions have different behaviour depending
+on the LMUL. Code can be instrumented with a comment that takes the
+following form:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-RISCV\-LMUL <M1|M2|M4|M8|MF2|MF4|MF8>
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The RISCV InstrumentManager will override the schedule class for vector
+instructions to use the scheduling behaviour of its pseudo\-instruction
+which is LMUL dependent. It makes sense to place RISCV instrument
+comments directly after \fIvset{i}vl{i}\fP instructions, although
+they can be placed anywhere in the program.
+.sp
+Example of program with no call to \fIvset{i}vl{i}\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# LLVM\-MCA\-RISCV\-LMUL M2
+vadd.vv v2, v2, v2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example of program with call to \fIvset{i}vl{i}\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+vsetvli zero, a0, e8, m1, tu, mu
+# LLVM\-MCA\-RISCV\-LMUL M1
+vadd.vv v2, v2, v2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example of program with multiple calls to \fIvset{i}vl{i}\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+vsetvli zero, a0, e8, m1, tu, mu
+# LLVM\-MCA\-RISCV\-LMUL M1
+vadd.vv v2, v2, v2
+vsetvli zero, a0, e8, m8, tu, mu
+# LLVM\-MCA\-RISCV\-LMUL M8
+vadd.vv v2, v2, v2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example of program with call to \fIvsetvl\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+vsetvl rd, rs1, rs2
+# LLVM\-MCA\-RISCV\-LMUL M1
+vadd.vv v12, v12, v12
+vsetvl rd, rs1, rs2
+# LLVM\-MCA\-RISCV\-LMUL M4
+vadd.vv v12, v12, v12
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH HOW LLVM-MCA WORKS
+.sp
+\fBllvm\-mca\fP takes assembly code as input. The assembly code is parsed
+into a sequence of MCInst with the help of the existing LLVM target assembly
+parsers. The parsed sequence of MCInst is then analyzed by a \fBPipeline\fP module
+to generate a performance report.
+.sp
+The Pipeline module simulates the execution of the machine code sequence in a
+loop of iterations (default is 100). During this process, the pipeline collects
+a number of execution related statistics. At the end of this process, the
+pipeline generates and prints a report from the collected statistics.
+.sp
+Here is an example of a performance report generated by the tool for a
+dot\-product of two packed float vectors of four elements. The analysis is
+conducted for target x86, cpu btver2. The following result can be produced via
+the following command using the example located at
+\fBtest/tools/llvm\-mca/X86/BtVer2/dot\-product.s\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-mca \-mtriple=x86_64\-unknown\-unknown \-mcpu=btver2 \-iterations=300 dot\-product.s
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Iterations: 300
+Instructions: 900
+Total Cycles: 610
+Total uOps: 900
+
+Dispatch Width: 2
+uOps Per Cycle: 1.48
+IPC: 1.48
+Block RThroughput: 2.0
+
+
+Instruction Info:
+[1]: #uOps
+[2]: Latency
+[3]: RThroughput
+[4]: MayLoad
+[5]: MayStore
+[6]: HasSideEffects (U)
+
+[1] [2] [3] [4] [5] [6] Instructions:
+ 1 2 1.00 vmulps %xmm0, %xmm1, %xmm2
+ 1 3 1.00 vhaddps %xmm2, %xmm2, %xmm3
+ 1 3 1.00 vhaddps %xmm3, %xmm3, %xmm4
+
+
+Resources:
+[0] \- JALU0
+[1] \- JALU1
+[2] \- JDiv
+[3] \- JFPA
+[4] \- JFPM
+[5] \- JFPU0
+[6] \- JFPU1
+[7] \- JLAGU
+[8] \- JMul
+[9] \- JSAGU
+[10] \- JSTC
+[11] \- JVALU0
+[12] \- JVALU1
+[13] \- JVIMUL
+
+
+Resource pressure per iteration:
+[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
+ \- \- \- 2.00 1.00 2.00 1.00 \- \- \- \- \- \- \-
+
+Resource pressure by instruction:
+[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions:
+ \- \- \- \- 1.00 \- 1.00 \- \- \- \- \- \- \- vmulps %xmm0, %xmm1, %xmm2
+ \- \- \- 1.00 \- 1.00 \- \- \- \- \- \- \- \- vhaddps %xmm2, %xmm2, %xmm3
+ \- \- \- 1.00 \- 1.00 \- \- \- \- \- \- \- \- vhaddps %xmm3, %xmm3, %xmm4
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+According to this report, the dot\-product kernel has been executed 300 times,
+for a total of 900 simulated instructions. The total number of simulated micro
+opcodes (uOps) is also 900.
+.sp
+The report is structured in three main sections. The first section collects a
+few performance numbers; the goal of this section is to give a very quick
+overview of the performance throughput. Important performance indicators are
+\fBIPC\fP, \fBuOps Per Cycle\fP, and \fBBlock RThroughput\fP (Block Reciprocal
+Throughput).
+.sp
+Field \fIDispatchWidth\fP is the maximum number of micro opcodes that are dispatched
+to the out\-of\-order backend every simulated cycle. For processors with an
+in\-order backend, \fIDispatchWidth\fP is the maximum number of micro opcodes issued
+to the backend every simulated cycle.
+.sp
+IPC is computed dividing the total number of simulated instructions by the total
+number of cycles.
+.sp
+Field \fIBlock RThroughput\fP is the reciprocal of the block throughput. Block
+throughput is a theoretical quantity computed as the maximum number of blocks
+(i.e. iterations) that can be executed per simulated clock cycle in the absence
+of loop carried dependencies. Block throughput is superiorly limited by the
+dispatch rate, and the availability of hardware resources.
+.sp
+In the absence of loop\-carried data dependencies, the observed IPC tends to a
+theoretical maximum which can be computed by dividing the number of instructions
+of a single iteration by the \fIBlock RThroughput\fP\&.
+.sp
+Field \(aquOps Per Cycle\(aq is computed dividing the total number of simulated micro
+opcodes by the total number of cycles. A delta between Dispatch Width and this
+field is an indicator of a performance issue. In the absence of loop\-carried
+data dependencies, the observed \(aquOps Per Cycle\(aq should tend to a theoretical
+maximum throughput which can be computed by dividing the number of uOps of a
+single iteration by the \fIBlock RThroughput\fP\&.
+.sp
+Field \fIuOps Per Cycle\fP is bounded from above by the dispatch width. That is
+because the dispatch width limits the maximum size of a dispatch group. Both IPC
+and \(aquOps Per Cycle\(aq are limited by the amount of hardware parallelism. The
+availability of hardware resources affects the resource pressure distribution,
+and it limits the number of instructions that can be executed in parallel every
+cycle. A delta between Dispatch Width and the theoretical maximum uOps per
+Cycle (computed by dividing the number of uOps of a single iteration by the
+\fIBlock RThroughput\fP) is an indicator of a performance bottleneck caused by the
+lack of hardware resources.
+In general, the lower the Block RThroughput, the better.
+.sp
+In this example, \fBuOps per iteration/Block RThroughput\fP is 1.50. Since there
+are no loop\-carried dependencies, the observed \fIuOps Per Cycle\fP is expected to
+approach 1.50 when the number of iterations tends to infinity. The delta between
+the Dispatch Width (2.00), and the theoretical maximum uOp throughput (1.50) is
+an indicator of a performance bottleneck caused by the lack of hardware
+resources, and the \fIResource pressure view\fP can help to identify the problematic
+resource usage.
+.sp
+The second section of the report is the \fIinstruction info view\fP\&. It shows the
+latency and reciprocal throughput of every instruction in the sequence. It also
+reports extra information related to the number of micro opcodes, and opcode
+properties (i.e., \(aqMayLoad\(aq, \(aqMayStore\(aq, and \(aqHasSideEffects\(aq).
+.sp
+Field \fIRThroughput\fP is the reciprocal of the instruction throughput. Throughput
+is computed as the maximum number of instructions of a same type that can be
+executed per clock cycle in the absence of operand dependencies. In this
+example, the reciprocal throughput of a vector float multiply is 1
+cycles/instruction. That is because the FP multiplier JFPM is only available
+from pipeline JFPU1.
+.sp
+Instruction encodings are displayed within the instruction info view when flag
+\fI\-show\-encoding\fP is specified.
+.sp
+Below is an example of \fI\-show\-encoding\fP output for the dot\-product kernel:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Instruction Info:
+[1]: #uOps
+[2]: Latency
+[3]: RThroughput
+[4]: MayLoad
+[5]: MayStore
+[6]: HasSideEffects (U)
+[7]: Encoding Size
+
+[1] [2] [3] [4] [5] [6] [7] Encodings: Instructions:
+ 1 2 1.00 4 c5 f0 59 d0 vmulps %xmm0, %xmm1, %xmm2
+ 1 4 1.00 4 c5 eb 7c da vhaddps %xmm2, %xmm2, %xmm3
+ 1 4 1.00 4 c5 e3 7c e3 vhaddps %xmm3, %xmm3, %xmm4
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The \fIEncoding Size\fP column shows the size in bytes of instructions. The
+\fIEncodings\fP column shows the actual instruction encodings (byte sequences in
+hex).
+.sp
+The third section is the \fIResource pressure view\fP\&. This view reports
+the average number of resource cycles consumed every iteration by instructions
+for every processor resource unit available on the target. Information is
+structured in two tables. The first table reports the number of resource cycles
+spent on average every iteration. The second table correlates the resource
+cycles to the machine instruction in the sequence. For example, every iteration
+of the instruction vmulps always executes on resource unit [6]
+(JFPU1 \- floating point pipeline #1), consuming an average of 1 resource cycle
+per iteration. Note that on AMD Jaguar, vector floating\-point multiply can
+only be issued to pipeline JFPU1, while horizontal floating\-point additions can
+only be issued to pipeline JFPU0.
+.sp
+The resource pressure view helps with identifying bottlenecks caused by high
+usage of specific hardware resources. Situations with resource pressure mainly
+concentrated on a few resources should, in general, be avoided. Ideally,
+pressure should be uniformly distributed between multiple resources.
+.SS Timeline View
+.sp
+The timeline view produces a detailed report of each instruction\(aqs state
+transitions through an instruction pipeline. This view is enabled by the
+command line option \fB\-timeline\fP\&. As instructions transition through the
+various stages of the pipeline, their states are depicted in the view report.
+These states are represented by the following characters:
+.INDENT 0.0
+.IP \(bu 2
+D : Instruction dispatched.
+.IP \(bu 2
+e : Instruction executing.
+.IP \(bu 2
+E : Instruction executed.
+.IP \(bu 2
+R : Instruction retired.
+.IP \(bu 2
+= : Instruction already dispatched, waiting to be executed.
+.IP \(bu 2
+\- : Instruction executed, waiting to be retired.
+.UNINDENT
+.sp
+Below is the timeline view for a subset of the dot\-product example located in
+\fBtest/tools/llvm\-mca/X86/BtVer2/dot\-product.s\fP and processed by
+\fBllvm\-mca\fP using the following command:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-mca \-mtriple=x86_64\-unknown\-unknown \-mcpu=btver2 \-iterations=3 \-timeline dot\-product.s
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Timeline view:
+ 012345
+Index 0123456789
+
+[0,0] DeeER. . . vmulps %xmm0, %xmm1, %xmm2
+[0,1] D==eeeER . . vhaddps %xmm2, %xmm2, %xmm3
+[0,2] .D====eeeER . vhaddps %xmm3, %xmm3, %xmm4
+[1,0] .DeeE\-\-\-\-\-R . vmulps %xmm0, %xmm1, %xmm2
+[1,1] . D=eeeE\-\-\-R . vhaddps %xmm2, %xmm2, %xmm3
+[1,2] . D====eeeER . vhaddps %xmm3, %xmm3, %xmm4
+[2,0] . DeeE\-\-\-\-\-R . vmulps %xmm0, %xmm1, %xmm2
+[2,1] . D====eeeER . vhaddps %xmm2, %xmm2, %xmm3
+[2,2] . D======eeeER vhaddps %xmm3, %xmm3, %xmm4
+
+
+Average Wait times (based on the timeline view):
+[0]: Executions
+[1]: Average time spent waiting in a scheduler\(aqs queue
+[2]: Average time spent waiting in a scheduler\(aqs queue while ready
+[3]: Average time elapsed from WB until retire stage
+
+ [0] [1] [2] [3]
+0. 3 1.0 1.0 3.3 vmulps %xmm0, %xmm1, %xmm2
+1. 3 3.3 0.7 1.0 vhaddps %xmm2, %xmm2, %xmm3
+2. 3 5.7 0.0 0.0 vhaddps %xmm3, %xmm3, %xmm4
+ 3 3.3 0.5 1.4 <total>
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+The timeline view is interesting because it shows instruction state changes
+during execution. It also gives an idea of how the tool processes instructions
+executed on the target, and how their timing information might be calculated.
+.sp
+The timeline view is structured in two tables. The first table shows
+instructions changing state over time (measured in cycles); the second table
+(named \fIAverage Wait times\fP) reports useful timing statistics, which should
+help diagnose performance bottlenecks caused by long data dependencies and
+sub\-optimal usage of hardware resources.
+.sp
+An instruction in the timeline view is identified by a pair of indices, where
+the first index identifies an iteration, and the second index is the
+instruction index (i.e., where it appears in the code sequence). Since this
+example was generated using 3 iterations: \fB\-iterations=3\fP, the iteration
+indices range from 0\-2 inclusively.
+.sp
+Excluding the first and last column, the remaining columns are in cycles.
+Cycles are numbered sequentially starting from 0.
+.sp
+From the example output above, we know the following:
+.INDENT 0.0
+.IP \(bu 2
+Instruction [1,0] was dispatched at cycle 1.
+.IP \(bu 2
+Instruction [1,0] started executing at cycle 2.
+.IP \(bu 2
+Instruction [1,0] reached the write back stage at cycle 4.
+.IP \(bu 2
+Instruction [1,0] was retired at cycle 10.
+.UNINDENT
+.sp
+Instruction [1,0] (i.e., vmulps from iteration #1) does not have to wait in the
+scheduler\(aqs queue for the operands to become available. By the time vmulps is
+dispatched, operands are already available, and pipeline JFPU1 is ready to
+serve another instruction. So the instruction can be immediately issued on the
+JFPU1 pipeline. That is demonstrated by the fact that the instruction only
+spent 1cy in the scheduler\(aqs queue.
+.sp
+There is a gap of 5 cycles between the write\-back stage and the retire event.
+That is because instructions must retire in program order, so [1,0] has to wait
+for [0,2] to be retired first (i.e., it has to wait until cycle 10).
+.sp
+In the example, all instructions are in a RAW (Read After Write) dependency
+chain. Register %xmm2 written by vmulps is immediately used by the first
+vhaddps, and register %xmm3 written by the first vhaddps is used by the second
+vhaddps. Long data dependencies negatively impact the ILP (Instruction Level
+Parallelism).
+.sp
+In the dot\-product example, there are anti\-dependencies introduced by
+instructions from different iterations. However, those dependencies can be
+removed at register renaming stage (at the cost of allocating register aliases,
+and therefore consuming physical registers).
+.sp
+Table \fIAverage Wait times\fP helps diagnose performance issues that are caused by
+the presence of long latency instructions and potentially long data dependencies
+which may limit the ILP. Last row, \fB<total>\fP, shows a global average over all
+instructions measured. Note that \fBllvm\-mca\fP, by default, assumes at
+least 1cy between the dispatch event and the issue event.
+.sp
+When the performance is limited by data dependencies and/or long latency
+instructions, the number of cycles spent while in the \fIready\fP state is expected
+to be very small when compared with the total number of cycles spent in the
+scheduler\(aqs queue. The difference between the two counters is a good indicator
+of how large of an impact data dependencies had on the execution of the
+instructions. When performance is mostly limited by the lack of hardware
+resources, the delta between the two counters is small. However, the number of
+cycles spent in the queue tends to be larger (i.e., more than 1\-3cy),
+especially when compared to other low latency instructions.
+.SS Bottleneck Analysis
+.sp
+The \fB\-bottleneck\-analysis\fP command line option enables the analysis of
+performance bottlenecks.
+.sp
+This analysis is potentially expensive. It attempts to correlate increases in
+backend pressure (caused by pipeline resource pressure and data dependencies) to
+dynamic dispatch stalls.
+.sp
+Below is an example of \fB\-bottleneck\-analysis\fP output generated by
+\fBllvm\-mca\fP for 500 iterations of the dot\-product example on btver2.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Cycles with backend pressure increase [ 48.07% ]
+Throughput Bottlenecks:
+ Resource Pressure [ 47.77% ]
+ \- JFPA [ 47.77% ]
+ \- JFPU0 [ 47.77% ]
+ Data Dependencies: [ 0.30% ]
+ \- Register Dependencies [ 0.30% ]
+ \- Memory Dependencies [ 0.00% ]
+
+Critical sequence based on the simulation:
+
+ Instruction Dependency Information
+ +\-\-\-\-< 2. vhaddps %xmm3, %xmm3, %xmm4
+ |
+ | < loop carried >
+ |
+ | 0. vmulps %xmm0, %xmm1, %xmm2
+ +\-\-\-\-> 1. vhaddps %xmm2, %xmm2, %xmm3 ## RESOURCE interference: JFPA [ probability: 74% ]
+ +\-\-\-\-> 2. vhaddps %xmm3, %xmm3, %xmm4 ## REGISTER dependency: %xmm3
+ |
+ | < loop carried >
+ |
+ +\-\-\-\-> 1. vhaddps %xmm2, %xmm2, %xmm3 ## RESOURCE interference: JFPA [ probability: 74% ]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+According to the analysis, throughput is limited by resource pressure and not by
+data dependencies. The analysis observed increases in backend pressure during
+48.07% of the simulated run. Almost all those pressure increase events were
+caused by contention on processor resources JFPA/JFPU0.
+.sp
+The \fIcritical sequence\fP is the most expensive sequence of instructions according
+to the simulation. It is annotated to provide extra information about critical
+register dependencies and resource interferences between instructions.
+.sp
+Instructions from the critical sequence are expected to significantly impact
+performance. By construction, the accuracy of this analysis is strongly
+dependent on the simulation and (as always) by the quality of the processor
+model in llvm.
+.sp
+Bottleneck analysis is currently not supported for processors with an in\-order
+backend.
+.SS Extra Statistics to Further Diagnose Performance Issues
+.sp
+The \fB\-all\-stats\fP command line option enables extra statistics and performance
+counters for the dispatch logic, the reorder buffer, the retire control unit,
+and the register file.
+.sp
+Below is an example of \fB\-all\-stats\fP output generated by \fBllvm\-mca\fP
+for 300 iterations of the dot\-product example discussed in the previous
+sections.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Dynamic Dispatch Stall Cycles:
+RAT \- Register unavailable: 0
+RCU \- Retire tokens unavailable: 0
+SCHEDQ \- Scheduler full: 272 (44.6%)
+LQ \- Load queue full: 0
+SQ \- Store queue full: 0
+GROUP \- Static restrictions on the dispatch group: 0
+
+
+Dispatch Logic \- number of cycles where we saw N micro opcodes dispatched:
+[# dispatched], [# cycles]
+ 0, 24 (3.9%)
+ 1, 272 (44.6%)
+ 2, 314 (51.5%)
+
+
+Schedulers \- number of cycles where we saw N micro opcodes issued:
+[# issued], [# cycles]
+ 0, 7 (1.1%)
+ 1, 306 (50.2%)
+ 2, 297 (48.7%)
+
+Scheduler\(aqs queue usage:
+[1] Resource name.
+[2] Average number of used buffer entries.
+[3] Maximum number of used buffer entries.
+[4] Total number of buffer entries.
+
+ [1] [2] [3] [4]
+JALU01 0 0 20
+JFPU01 17 18 18
+JLSAGU 0 0 12
+
+
+Retire Control Unit \- number of cycles where we saw N instructions retired:
+[# retired], [# cycles]
+ 0, 109 (17.9%)
+ 1, 102 (16.7%)
+ 2, 399 (65.4%)
+
+Total ROB Entries: 64
+Max Used ROB Entries: 35 ( 54.7% )
+Average Used ROB Entries per cy: 32 ( 50.0% )
+
+
+Register File statistics:
+Total number of mappings created: 900
+Max number of mappings used: 35
+
+* Register File #1 \-\- JFpuPRF:
+ Number of physical registers: 72
+ Total number of mappings created: 900
+ Max number of mappings used: 35
+
+* Register File #2 \-\- JIntegerPRF:
+ Number of physical registers: 64
+ Total number of mappings created: 0
+ Max number of mappings used: 0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If we look at the \fIDynamic Dispatch Stall Cycles\fP table, we see the counter for
+SCHEDQ reports 272 cycles. This counter is incremented every time the dispatch
+logic is unable to dispatch a full group because the scheduler\(aqs queue is full.
+.sp
+Looking at the \fIDispatch Logic\fP table, we see that the pipeline was only able to
+dispatch two micro opcodes 51.5% of the time. The dispatch group was limited to
+one micro opcode 44.6% of the cycles, which corresponds to 272 cycles. The
+dispatch statistics are displayed by either using the command option
+\fB\-all\-stats\fP or \fB\-dispatch\-stats\fP\&.
+.sp
+The next table, \fISchedulers\fP, presents a histogram displaying a count,
+representing the number of micro opcodes issued on some number of cycles. In
+this case, of the 610 simulated cycles, single opcodes were issued 306 times
+(50.2%) and there were 7 cycles where no opcodes were issued.
+.sp
+The \fIScheduler\(aqs queue usage\fP table shows that the average and maximum number of
+buffer entries (i.e., scheduler queue entries) used at runtime. Resource JFPU01
+reached its maximum (18 of 18 queue entries). Note that AMD Jaguar implements
+three schedulers:
+.INDENT 0.0
+.IP \(bu 2
+JALU01 \- A scheduler for ALU instructions.
+.IP \(bu 2
+JFPU01 \- A scheduler floating point operations.
+.IP \(bu 2
+JLSAGU \- A scheduler for address generation.
+.UNINDENT
+.sp
+The dot\-product is a kernel of three floating point instructions (a vector
+multiply followed by two horizontal adds). That explains why only the floating
+point scheduler appears to be used.
+.sp
+A full scheduler queue is either caused by data dependency chains or by a
+sub\-optimal usage of hardware resources. Sometimes, resource pressure can be
+mitigated by rewriting the kernel using different instructions that consume
+different scheduler resources. Schedulers with a small queue are less resilient
+to bottlenecks caused by the presence of long data dependencies. The scheduler
+statistics are displayed by using the command option \fB\-all\-stats\fP or
+\fB\-scheduler\-stats\fP\&.
+.sp
+The next table, \fIRetire Control Unit\fP, presents a histogram displaying a count,
+representing the number of instructions retired on some number of cycles. In
+this case, of the 610 simulated cycles, two instructions were retired during the
+same cycle 399 times (65.4%) and there were 109 cycles where no instructions
+were retired. The retire statistics are displayed by using the command option
+\fB\-all\-stats\fP or \fB\-retire\-stats\fP\&.
+.sp
+The last table presented is \fIRegister File statistics\fP\&. Each physical register
+file (PRF) used by the pipeline is presented in this table. In the case of AMD
+Jaguar, there are two register files, one for floating\-point registers (JFpuPRF)
+and one for integer registers (JIntegerPRF). The table shows that of the 900
+instructions processed, there were 900 mappings created. Since this dot\-product
+example utilized only floating point registers, the JFPuPRF was responsible for
+creating the 900 mappings. However, we see that the pipeline only used a
+maximum of 35 of 72 available register slots at any given time. We can conclude
+that the floating point PRF was the only register file used for the example, and
+that it was never resource constrained. The register file statistics are
+displayed by using the command option \fB\-all\-stats\fP or
+\fB\-register\-file\-stats\fP\&.
+.sp
+In this example, we can conclude that the IPC is mostly limited by data
+dependencies, and not by resource pressure.
+.SS Instruction Flow
+.sp
+This section describes the instruction flow through the default pipeline of
+\fBllvm\-mca\fP, as well as the functional units involved in the process.
+.sp
+The default pipeline implements the following sequence of stages used to
+process instructions.
+.INDENT 0.0
+.IP \(bu 2
+Dispatch (Instruction is dispatched to the schedulers).
+.IP \(bu 2
+Issue (Instruction is issued to the processor pipelines).
+.IP \(bu 2
+Write Back (Instruction is executed, and results are written back).
+.IP \(bu 2
+Retire (Instruction is retired; writes are architecturally committed).
+.UNINDENT
+.sp
+The in\-order pipeline implements the following sequence of stages:
+* InOrderIssue (Instruction is issued to the processor pipelines).
+* Retire (Instruction is retired; writes are architecturally committed).
+.sp
+\fBllvm\-mca\fP assumes that instructions have all been decoded and placed
+into a queue before the simulation start. Therefore, the instruction fetch and
+decode stages are not modeled. Performance bottlenecks in the frontend are not
+diagnosed. Also, \fBllvm\-mca\fP does not model branch prediction.
+.SS Instruction Dispatch
+.sp
+During the dispatch stage, instructions are picked in program order from a
+queue of already decoded instructions, and dispatched in groups to the
+simulated hardware schedulers.
+.sp
+The size of a dispatch group depends on the availability of the simulated
+hardware resources. The processor dispatch width defaults to the value
+of the \fBIssueWidth\fP in LLVM\(aqs scheduling model.
+.sp
+An instruction can be dispatched if:
+.INDENT 0.0
+.IP \(bu 2
+The size of the dispatch group is smaller than processor\(aqs dispatch width.
+.IP \(bu 2
+There are enough entries in the reorder buffer.
+.IP \(bu 2
+There are enough physical registers to do register renaming.
+.IP \(bu 2
+The schedulers are not full.
+.UNINDENT
+.sp
+Scheduling models can optionally specify which register files are available on
+the processor. \fBllvm\-mca\fP uses that information to initialize register
+file descriptors. Users can limit the number of physical registers that are
+globally available for register renaming by using the command option
+\fB\-register\-file\-size\fP\&. A value of zero for this option means \fIunbounded\fP\&. By
+knowing how many registers are available for renaming, the tool can predict
+dispatch stalls caused by the lack of physical registers.
+.sp
+The number of reorder buffer entries consumed by an instruction depends on the
+number of micro\-opcodes specified for that instruction by the target scheduling
+model. The reorder buffer is responsible for tracking the progress of
+instructions that are \(dqin\-flight\(dq, and retiring them in program order. The
+number of entries in the reorder buffer defaults to the value specified by field
+\fIMicroOpBufferSize\fP in the target scheduling model.
+.sp
+Instructions that are dispatched to the schedulers consume scheduler buffer
+entries. \fBllvm\-mca\fP queries the scheduling model to determine the set
+of buffered resources consumed by an instruction. Buffered resources are
+treated like scheduler resources.
+.SS Instruction Issue
+.sp
+Each processor scheduler implements a buffer of instructions. An instruction
+has to wait in the scheduler\(aqs buffer until input register operands become
+available. Only at that point, does the instruction becomes eligible for
+execution and may be issued (potentially out\-of\-order) for execution.
+Instruction latencies are computed by \fBllvm\-mca\fP with the help of the
+scheduling model.
+.sp
+\fBllvm\-mca\fP\(aqs scheduler is designed to simulate multiple processor
+schedulers. The scheduler is responsible for tracking data dependencies, and
+dynamically selecting which processor resources are consumed by instructions.
+It delegates the management of processor resource units and resource groups to a
+resource manager. The resource manager is responsible for selecting resource
+units that are consumed by instructions. For example, if an instruction
+consumes 1cy of a resource group, the resource manager selects one of the
+available units from the group; by default, the resource manager uses a
+round\-robin selector to guarantee that resource usage is uniformly distributed
+between all units of a group.
+.sp
+\fBllvm\-mca\fP\(aqs scheduler internally groups instructions into three sets:
+.INDENT 0.0
+.IP \(bu 2
+WaitSet: a set of instructions whose operands are not ready.
+.IP \(bu 2
+ReadySet: a set of instructions ready to execute.
+.IP \(bu 2
+IssuedSet: a set of instructions executing.
+.UNINDENT
+.sp
+Depending on the operands availability, instructions that are dispatched to the
+scheduler are either placed into the WaitSet or into the ReadySet.
+.sp
+Every cycle, the scheduler checks if instructions can be moved from the WaitSet
+to the ReadySet, and if instructions from the ReadySet can be issued to the
+underlying pipelines. The algorithm prioritizes older instructions over younger
+instructions.
+.SS Write\-Back and Retire Stage
+.sp
+Issued instructions are moved from the ReadySet to the IssuedSet. There,
+instructions wait until they reach the write\-back stage. At that point, they
+get removed from the queue and the retire control unit is notified.
+.sp
+When instructions are executed, the retire control unit flags the instruction as
+\(dqready to retire.\(dq
+.sp
+Instructions are retired in program order. The register file is notified of the
+retirement so that it can free the physical registers that were allocated for
+the instruction during the register renaming stage.
+.SS Load/Store Unit and Memory Consistency Model
+.sp
+To simulate an out\-of\-order execution of memory operations, \fBllvm\-mca\fP
+utilizes a simulated load/store unit (LSUnit) to simulate the speculative
+execution of loads and stores.
+.sp
+Each load (or store) consumes an entry in the load (or store) queue. Users can
+specify flags \fB\-lqueue\fP and \fB\-squeue\fP to limit the number of entries in the
+load and store queues respectively. The queues are unbounded by default.
+.sp
+The LSUnit implements a relaxed consistency model for memory loads and stores.
+The rules are:
+.INDENT 0.0
+.IP 1. 3
+A younger load is allowed to pass an older load only if there are no
+intervening stores or barriers between the two loads.
+.IP 2. 3
+A younger load is allowed to pass an older store provided that the load does
+not alias with the store.
+.IP 3. 3
+A younger store is not allowed to pass an older store.
+.IP 4. 3
+A younger store is not allowed to pass an older load.
+.UNINDENT
+.sp
+By default, the LSUnit optimistically assumes that loads do not alias
+(\fI\-noalias=true\fP) store operations. Under this assumption, younger loads are
+always allowed to pass older stores. Essentially, the LSUnit does not attempt
+to run any alias analysis to predict when loads and stores do not alias with
+each other.
+.sp
+Note that, in the case of write\-combining memory, rule 3 could be relaxed to
+allow reordering of non\-aliasing store operations. That being said, at the
+moment, there is no way to further relax the memory model (\fB\-noalias\fP is the
+only option). Essentially, there is no option to specify a different memory
+type (e.g., write\-back, write\-combining, write\-through; etc.) and consequently
+to weaken, or strengthen, the memory model.
+.sp
+Other limitations are:
+.INDENT 0.0
+.IP \(bu 2
+The LSUnit does not know when store\-to\-load forwarding may occur.
+.IP \(bu 2
+The LSUnit does not know anything about cache hierarchy and memory types.
+.IP \(bu 2
+The LSUnit does not know how to identify serializing operations and memory
+fences.
+.UNINDENT
+.sp
+The LSUnit does not attempt to predict if a load or store hits or misses the L1
+cache. It only knows if an instruction \(dqMayLoad\(dq and/or \(dqMayStore.\(dq For
+loads, the scheduling model provides an \(dqoptimistic\(dq load\-to\-use latency (which
+usually matches the load\-to\-use latency for when there is a hit in the L1D).
+.sp
+\fBllvm\-mca\fP does not (on its own) know about serializing operations or
+memory\-barrier like instructions. The LSUnit used to conservatively use an
+instruction\(aqs \(dqMayLoad\(dq, \(dqMayStore\(dq, and unmodeled side effects flags to
+determine whether an instruction should be treated as a memory\-barrier. This was
+inaccurate in general and was changed so that now each instruction has an
+IsAStoreBarrier and IsALoadBarrier flag. These flags are mca specific and
+default to false for every instruction. If any instruction should have either of
+these flags set, it should be done within the target\(aqs InstrPostProcess class.
+For an example, look at the \fIX86InstrPostProcess::postProcessInstruction\fP method
+within \fIllvm/lib/Target/X86/MCA/X86CustomBehaviour.cpp\fP\&.
+.sp
+A load/store barrier consumes one entry of the load/store queue. A load/store
+barrier enforces ordering of loads/stores. A younger load cannot pass a load
+barrier. Also, a younger store cannot pass a store barrier. A younger load
+has to wait for the memory/load barrier to execute. A load/store barrier is
+\(dqexecuted\(dq when it becomes the oldest entry in the load/store queue(s). That
+also means, by construction, all of the older loads/stores have been executed.
+.sp
+In conclusion, the full set of load/store consistency rules are:
+.INDENT 0.0
+.IP 1. 3
+A store may not pass a previous store.
+.IP 2. 3
+A store may not pass a previous load (regardless of \fB\-noalias\fP).
+.IP 3. 3
+A store has to wait until an older store barrier is fully executed.
+.IP 4. 3
+A load may pass a previous load.
+.IP 5. 3
+A load may not pass a previous store unless \fB\-noalias\fP is set.
+.IP 6. 3
+A load has to wait until an older load barrier is fully executed.
+.UNINDENT
+.SS In\-order Issue and Execute
+.sp
+In\-order processors are modelled as a single \fBInOrderIssueStage\fP stage. It
+bypasses Dispatch, Scheduler and Load/Store unit. Instructions are issued as
+soon as their operand registers are available and resource requirements are
+met. Multiple instructions can be issued in one cycle according to the value of
+the \fBIssueWidth\fP parameter in LLVM\(aqs scheduling model.
+.sp
+Once issued, an instruction is moved to \fBIssuedInst\fP set until it is ready to
+retire. \fBllvm\-mca\fP ensures that writes are committed in\-order. However,
+an instruction is allowed to commit writes and retire out\-of\-order if
+\fBRetireOOO\fP property is true for at least one of its writes.
+.SS Custom Behaviour
+.sp
+Due to certain instructions not being expressed perfectly within their
+scheduling model, \fBllvm\-mca\fP isn\(aqt always able to simulate them
+perfectly. Modifying the scheduling model isn\(aqt always a viable
+option though (maybe because the instruction is modeled incorrectly on
+purpose or the instruction\(aqs behaviour is quite complex). The
+CustomBehaviour class can be used in these cases to enforce proper
+instruction modeling (often by customizing data dependencies and detecting
+hazards that \fBllvm\-mca\fP has no way of knowing about).
+.sp
+\fBllvm\-mca\fP comes with one generic and multiple target specific
+CustomBehaviour classes. The generic class will be used if the \fB\-disable\-cb\fP
+flag is used or if a target specific CustomBehaviour class doesn\(aqt exist for
+that target. (The generic class does nothing.) Currently, the CustomBehaviour
+class is only a part of the in\-order pipeline, but there are plans to add it
+to the out\-of\-order pipeline in the future.
+.sp
+CustomBehaviour\(aqs main method is \fIcheckCustomHazard()\fP which uses the
+current instruction and a list of all instructions still executing within
+the pipeline to determine if the current instruction should be dispatched.
+As output, the method returns an integer representing the number of cycles
+that the current instruction must stall for (this can be an underestimate
+if you don\(aqt know the exact number and a value of 0 represents no stall).
+.sp
+If you\(aqd like to add a CustomBehaviour class for a target that doesn\(aqt
+already have one, refer to an existing implementation to see how to set it
+up. The classes are implemented within the target specific backend (for
+example \fI/llvm/lib/Target/AMDGPU/MCA/\fP) so that they can access backend symbols.
+.SS Instrument Manager
+.sp
+On certain architectures, scheduling information for certain instructions
+do not contain all of the information required to identify the most precise
+schedule class. For example, data that can have an impact on scheduling can
+be stored in CSR registers.
+.sp
+One example of this is on RISCV, where values in registers such as \fIvtype\fP
+and \fIvl\fP change the scheduling behaviour of vector instructions. Since MCA
+does not keep track of the values in registers, instrument comments can
+be used to specify these values.
+.sp
+InstrumentManager\(aqs main function is \fIgetSchedClassID()\fP which has access
+to the MCInst and all of the instruments that are active for that MCInst.
+This function can use the instruments to override the schedule class of
+the MCInst.
+.sp
+On RISCV, instrument comments containing LMUL information are used
+by \fIgetSchedClassID()\fP to map a vector instruction and the active
+LMUL to the scheduling class of the pseudo\-instruction that describes
+that base instruction and the active LMUL.
+.SS Custom Views
+.sp
+\fBllvm\-mca\fP comes with several Views such as the Timeline View and
+Summary View. These Views are generic and can work with most (if not all)
+targets. If you wish to add a new View to \fBllvm\-mca\fP and it does not
+require any backend functionality that is not already exposed through MC layer
+classes (MCSubtargetInfo, MCInstrInfo, etc.), please add it to the
+\fI/tools/llvm\-mca/View/\fP directory. However, if your new View is target specific
+AND requires unexposed backend symbols or functionality, you can define it in
+the \fI/lib/Target/<TargetName>/MCA/\fP directory.
+.sp
+To enable this target specific View, you will have to use this target\(aqs
+CustomBehaviour class to override the \fICustomBehaviour::getViews()\fP methods.
+There are 3 variations of these methods based on where you want your View to
+appear in the output: \fIgetStartViews()\fP, \fIgetPostInstrInfoViews()\fP, and
+\fIgetEndViews()\fP\&. These methods returns a vector of Views so you will want to
+return a vector containing all of the target specific Views for the target in
+question.
+.sp
+Because these target specific (and backend dependent) Views require the
+\fICustomBehaviour::getViews()\fP variants, these Views will not be enabled if
+the \fI\-disable\-cb\fP flag is used.
+.sp
+Enabling these custom Views does not affect the non\-custom (generic) Views.
+Continue to use the usual command line arguments to enable / disable those
+Views.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-min-tblgen/Makefile b/usr.bin/clang/llvm-min-tblgen/Makefile
new file mode 100644
index 000000000000..702184a813c5
--- /dev/null
+++ b/usr.bin/clang/llvm-min-tblgen/Makefile
@@ -0,0 +1,8 @@
+PROG_CXX= llvm-min-tblgen
+MAN=
+
+SRCDIR= llvm/utils/TableGen
+SRCS+= TableGen.cpp
+SRCS+= VTEmitter.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-min-tblgen/Makefile.depend b/usr.bin/clang/llvm-min-tblgen/Makefile.depend
new file mode 100644
index 000000000000..bb8d5321da66
--- /dev/null
+++ b/usr.bin/clang/llvm-min-tblgen/Makefile.depend
@@ -0,0 +1,24 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-min-tblgen/Makefile.depend.host b/usr.bin/clang/llvm-min-tblgen/Makefile.depend.host
new file mode 100644
index 000000000000..2f7a10cf10d6
--- /dev/null
+++ b/usr.bin/clang/llvm-min-tblgen/Makefile.depend.host
@@ -0,0 +1,12 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/clang/libllvmminimal \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-modextract/Makefile b/usr.bin/clang/llvm-modextract/Makefile
new file mode 100644
index 000000000000..6e9a79a16495
--- /dev/null
+++ b/usr.bin/clang/llvm-modextract/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llvm-modextract
+MAN=
+
+SRCDIR= llvm/tools/llvm-modextract
+SRCS= llvm-modextract.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-modextract/Makefile.depend b/usr.bin/clang/llvm-modextract/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-modextract/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-nm/Makefile b/usr.bin/clang/llvm-nm/Makefile
new file mode 100644
index 000000000000..825faf74719b
--- /dev/null
+++ b/usr.bin/clang/llvm-nm/Makefile
@@ -0,0 +1,30 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-nm
+
+SRCDIR= llvm/tools/llvm-nm
+SRCS+= llvm-nm-driver.cpp
+SRCS+= llvm-nm.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-nm ${BINDIR}/nm
+MLINKS+= llvm-nm.1 nm.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-nm/Makefile.depend b/usr.bin/clang/llvm-nm/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-nm/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-nm/llvm-nm-driver.cpp b/usr.bin/clang/llvm-nm/llvm-nm-driver.cpp
new file mode 100644
index 000000000000..dd2aad8fe4ee
--- /dev/null
+++ b/usr.bin/clang/llvm-nm/llvm-nm-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_nm_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_nm_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-nm/llvm-nm.1 b/usr.bin/clang/llvm-nm/llvm-nm.1
new file mode 100644
index 000000000000..b6dd910cc6c3
--- /dev/null
+++ b/usr.bin/clang/llvm-nm/llvm-nm.1
@@ -0,0 +1,447 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-NM" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-nm \- list LLVM bitcode and object file's symbol table
+.SH SYNOPSIS
+.sp
+\fBllvm\-nm\fP [\fIoptions\fP] [\fIfilenames...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-nm\fP utility lists the names of symbols from LLVM bitcode
+files, object files, and archives. Each symbol is listed along with some simple
+information about its provenance. If no filename is specified, \fIa.out\fP is used
+as the input. If \fI\-\fP is used as a filename, \fBllvm\-nm\fP will read a file
+from its standard input stream.
+.sp
+\fBllvm\-nm\fP\(aqs default output format is the traditional BSD \fBnm\fP
+output format. Each such output record consists of an (optional) 8\-digit
+hexadecimal address, followed by a type code character, followed by a name, for
+each symbol. One record is printed per line; fields are separated by spaces.
+When the address is omitted, it is replaced by 8 spaces.
+.sp
+The supported type code characters are as follows. Where both lower and
+upper\-case characters are listed for the same meaning, a lower\-case character
+represents a local symbol, whilst an upper\-case character represents a global
+(external) symbol:
+.sp
+a, A
+.INDENT 0.0
+.INDENT 3.5
+Absolute symbol.
+.UNINDENT
+.UNINDENT
+.sp
+b, B
+.INDENT 0.0
+.INDENT 3.5
+Uninitialized data (bss) object.
+.UNINDENT
+.UNINDENT
+.sp
+C
+.INDENT 0.0
+.INDENT 3.5
+Common symbol. Multiple definitions link together into one definition.
+.UNINDENT
+.UNINDENT
+.sp
+d, D
+.INDENT 0.0
+.INDENT 3.5
+Writable data object.
+.UNINDENT
+.UNINDENT
+.sp
+i, I
+.INDENT 0.0
+.INDENT 3.5
+COFF: .idata symbol or symbol in a section with IMAGE_SCN_LNK_INFO set.
+.UNINDENT
+.UNINDENT
+.sp
+n
+.INDENT 0.0
+.INDENT 3.5
+ELF: local symbol from non\-alloc section.
+.sp
+COFF: debug symbol.
+.UNINDENT
+.UNINDENT
+.sp
+N
+.INDENT 0.0
+.INDENT 3.5
+ELF: debug section symbol, or global symbol from non\-alloc section.
+.UNINDENT
+.UNINDENT
+.sp
+s, S
+.INDENT 0.0
+.INDENT 3.5
+COFF: section symbol.
+.sp
+Mach\-O: absolute symbol or symbol from a section other than __TEXT_EXEC __text,
+__TEXT __text, __DATA __data, or __DATA __bss.
+.UNINDENT
+.UNINDENT
+.sp
+r, R
+.INDENT 0.0
+.INDENT 3.5
+Read\-only data object.
+.UNINDENT
+.UNINDENT
+.sp
+t, T
+.INDENT 0.0
+.INDENT 3.5
+Code (text) object.
+.UNINDENT
+.UNINDENT
+.sp
+u
+.INDENT 0.0
+.INDENT 3.5
+ELF: GNU unique symbol.
+.UNINDENT
+.UNINDENT
+.sp
+U
+.INDENT 0.0
+.INDENT 3.5
+Named object is undefined in this file.
+.UNINDENT
+.UNINDENT
+.sp
+v
+.INDENT 0.0
+.INDENT 3.5
+ELF: Undefined weak object. It is not a link failure if the object is not
+defined.
+.UNINDENT
+.UNINDENT
+.sp
+V
+.INDENT 0.0
+.INDENT 3.5
+ELF: Defined weak object symbol. This definition will only be used if no
+regular definitions exist in a link. If multiple weak definitions and no
+regular definitions exist, one of the weak definitions will be used.
+.UNINDENT
+.UNINDENT
+.sp
+w
+.INDENT 0.0
+.INDENT 3.5
+Undefined weak symbol other than an ELF object symbol. It is not a link failure
+if the symbol is not defined.
+.UNINDENT
+.UNINDENT
+.sp
+W
+.INDENT 0.0
+.INDENT 3.5
+Defined weak symbol other than an ELF object symbol. This definition will only
+be used if no regular definitions exist in a link. If multiple weak definitions
+and no regular definitions exist, one of the weak definitions will be used.
+.UNINDENT
+.UNINDENT
+.sp
+\-
+.INDENT 0.0
+.INDENT 3.5
+Mach\-O: N_STAB symbol.
+.UNINDENT
+.UNINDENT
+.sp
+?
+.INDENT 0.0
+.INDENT 3.5
+Something unrecognizable.
+.UNINDENT
+.UNINDENT
+.sp
+Because LLVM bitcode files typically contain objects that are not considered to
+have addresses until they are linked into an executable image or dynamically
+compiled \(dqjust\-in\-time\(dq, \fBllvm\-nm\fP does not print an address for any
+symbol in an LLVM bitcode file, even symbols which are defined in the bitcode
+file.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-B
+Use BSD output format. Alias for \fB\-\-format=bsd\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-X
+Specify the type of XCOFF object file, ELF object file, or IR object file input
+from command line or from archive files that llvm\-nm should examine. The
+mode must be one of the following:
+.INDENT 7.0
+.INDENT 3.5
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.B 32
+Process only 32\-bit object files.
+.TP
+.B 64
+Process only 64\-bit object files.
+.TP
+.B 32_64
+Process both 32\-bit and 64\-bit object files.
+.TP
+.B any
+Process all the supported object files.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+On AIX OS, the default is to process 32\-bit object files only and to ignore
+64\-bit objects. The can be changed by setting the OBJECT_MODE environment
+variable. For example, OBJECT_MODE=64 causes \fBllvm\-nm\fP to process
+64\-bit objects and ignore 32\-bit objects. The \-X flag overrides the OBJECT_MODE
+variable.
+.sp
+On other operating systems, the default is to process all object files: the
+OBJECT_MODE environment variable is not supported.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-syms, \-a
+Show all symbols, even those usually suppressed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-defined\-only, \-U
+Print only symbols defined in this file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-demangle, \-C
+Demangle symbol names.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dynamic, \-D
+Display dynamic symbols instead of normal symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-export\-symbols
+Print sorted symbols with their visibility (if applicable), with duplicates
+removed.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-extern\-only, \-g
+Print only symbols whose definitions are external; that is, accessible from
+other files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-format=<format>, \-f
+Select an output format; \fIformat\fP may be \fIsysv\fP, \fIposix\fP, \fIdarwin\fP, \fIbsd\fP or
+\fIjust\-symbols\fP\&.
+The default is \fIbsd\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Print a summary of command\-line options and their meanings.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-j
+Print just the symbol names. Alias for \fI\-\-format=just\-symbols\(ga\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-m
+Use Darwin format. Alias for \fB\-\-format=darwin\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-demangle
+Don\(aqt demangle symbol names. This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-llvm\-bc
+Disable the LLVM bitcode reader.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-sort, \-p
+Show symbols in the order encountered.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-weak, \-W
+Don\(aqt print weak symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-numeric\-sort, \-n, \-v
+Sort symbols by address.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-portability, \-P
+Use POSIX.2 output format. Alias for \fB\-\-format=posix\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-armap
+Print the archive symbol table, in addition to the symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-file\-name, \-A, \-o
+Precede each symbol with the file it came from.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-size, \-S
+Show symbol size as well as address (not applicable for Mach\-O).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-quiet
+Suppress \(aqno symbols\(aq diagnostic.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-radix=<RADIX>, \-t
+Specify the radix of the symbol address(es). Values accepted are \fId\fP (decimal),
+\fIx\fP (hexadecimal) and \fIo\fP (octal).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-reverse\-sort, \-r
+Sort symbols in reverse order.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-size\-sort
+Sort symbols by size.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-special\-syms
+Do not filter special symbols from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-undefined\-only, \-u
+Print only undefined symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version, \-V
+Display the version of the \fBllvm\-nm\fP executable, then exit. Does not
+stack with other commands.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH MACH-O SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-add\-dyldinfo
+Add symbols from the dyldinfo, if they are not already in the symbol table.
+This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-add\-inlinedinfo
+Add symbols from the inlined libraries, TBD file inputs only.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-arch=<arch1[,arch2,...]>
+Dump the symbols from the specified architecture(s).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyldinfo\-only
+Dump only symbols from the dyldinfo.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-dyldinfo
+Do not add any symbols from the dyldinfo.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-s <segment> <section>
+Dump only symbols from this segment and section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x
+Print symbol entry in hex.
+.UNINDENT
+.SH XCOFF SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-no\-rsrc
+Exclude resource file symbols (\fB__rsrc\fP) from export symbol list.
+.UNINDENT
+.SH BUGS
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fBllvm\-nm\fP does not support the full set of arguments that GNU
+\fBnm\fP does.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-nm\fP exits with an exit code of zero.
+.SH SEE ALSO
+.sp
+\fBllvm\-ar(1)\fP, \fBllvm\-objdump(1)\fP, \fBllvm\-readelf(1)\fP,
+\fBllvm\-readobj(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-objcopy/Makefile b/usr.bin/clang/llvm-objcopy/Makefile
new file mode 100644
index 000000000000..fcf59e4b4bca
--- /dev/null
+++ b/usr.bin/clang/llvm-objcopy/Makefile
@@ -0,0 +1,36 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-objcopy
+
+SRCDIR= llvm/tools/llvm-objcopy
+SRCS+= ObjcopyOptions.cpp
+SRCS+= llvm-objcopy-driver.cpp
+SRCS+= llvm-objcopy.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${LLVM_BASE}/${SRCDIR}
+
+.for hdr in BitcodeStripOpts InstallNameToolOpts ObjcopyOpts StripOpts
+${hdr}.inc: ${LLVM_BASE}/${SRCDIR}/${hdr}.td
+ ${LLVM_TBLGEN} -gen-opt-parser-defs \
+ -I ${LLVM_SRCS}/tools/llvm-objcopy -I ${LLVM_SRCS}/include \
+ -d ${.TARGET}.d -o ${.TARGET} ${LLVM_BASE}/${SRCDIR}/${hdr}.td
+TGHDRS+= ${hdr}.inc
+.endfor
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LINKS= ${BINDIR}/llvm-objcopy ${BINDIR}/llvm-strip
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-objcopy ${BINDIR}/objcopy \
+ ${BINDIR}/llvm-strip ${BINDIR}/strip
+MLINKS= llvm-objcopy.1 objcopy.1 \
+ llvm-objcopy.1 strip.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-objcopy/llvm-objcopy-driver.cpp b/usr.bin/clang/llvm-objcopy/llvm-objcopy-driver.cpp
new file mode 100644
index 000000000000..138346685dcd
--- /dev/null
+++ b/usr.bin/clang/llvm-objcopy/llvm-objcopy-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_objcopy_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_objcopy_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-objcopy/llvm-objcopy.1 b/usr.bin/clang/llvm-objcopy/llvm-objcopy.1
new file mode 100644
index 000000000000..34f8f9c7774c
--- /dev/null
+++ b/usr.bin/clang/llvm-objcopy/llvm-objcopy.1
@@ -0,0 +1,748 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-OBJCOPY" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-objcopy \- object copying and editing tool
+.SH SYNOPSIS
+.sp
+\fBllvm\-objcopy\fP [\fIoptions\fP] \fIinput\fP [\fIoutput\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-objcopy\fP is a tool to copy and manipulate objects. In basic
+usage, it makes a semantic copy of the input to the output. If any options are
+specified, the output may be modified along the way, e.g. by removing sections.
+.sp
+If no output file is specified, the input file is modified in\-place. If \(dq\-\(dq is
+specified for the input file, the input is read from the program\(aqs standard
+input stream. If \(dq\-\(dq is specified for the output file, the output is written to
+the standard output stream of the program.
+.sp
+If the input is an archive, any requested operations will be applied to each
+archive member individually.
+.sp
+The tool is still in active development, but in most scenarios it works as a
+drop\-in replacement for GNU\(aqs \fBobjcopy\fP\&.
+.SH GENERIC AND CROSS-PLATFORM OPTIONS
+.sp
+The following options are either agnostic of the file format, or apply to
+multiple file formats.
+.INDENT 0.0
+.TP
+.B \-\-add\-gnu\-debuglink <debug\-file>
+Add a .gnu_debuglink section for \fB<debug\-file>\fP to the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-add\-section <section=file>
+Add a section named \fB<section>\fP with the contents of \fB<file>\fP to the
+output. For ELF objects the section will be of type \fISHT_NOTE\fP, if the name
+starts with \(dq.note\(dq. Otherwise, it will have type \fISHT_PROGBITS\fP\&. Can be
+specified multiple times to add multiple sections.
+.sp
+For MachO objects, \fB<section>\fP must be formatted as
+\fB<segment name>,<section name>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-binary\-architecture <arch>, \-B
+Ignored for compatibility.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-disable\-deterministic\-archives, \-U
+Use real values for UIDs, GIDs and timestamps when updating archive member
+headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-discard\-all, \-x
+Remove most local symbols from the output. Different file formats may limit
+this to a subset of the local symbols. For example, file and section symbols in
+ELF objects will not be discarded. Additionally, remove all debug sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dump\-section <section>=<file>
+Dump the contents of section \fB<section>\fP into the file \fB<file>\fP\&. Can be
+specified multiple times to dump multiple sections to different files.
+\fB<file>\fP is unrelated to the input and output files provided to
+\fBllvm\-objcopy\fP and as such the normal copying and editing
+operations will still be performed. No operations are performed on the sections
+prior to dumping them.
+.sp
+For MachO objects, \fB<section>\fP must be formatted as
+\fB<segment name>,<section name>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-enable\-deterministic\-archives, \-D
+Enable deterministic mode when copying archives, i.e. use 0 for archive member
+header UIDs, GIDs and timestamp fields. On by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-only\-keep\-debug
+Produce a debug file as the output that only preserves contents of sections
+useful for debugging purposes.
+.sp
+For ELF objects, this removes the contents of \fISHF_ALLOC\fP sections that are not
+\fISHT_NOTE\fP by making them \fISHT_NOBITS\fP and shrinking the program headers where
+possible.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-only\-section <section>, \-j
+Remove all sections from the output, except for sections named \fB<section>\fP\&.
+Can be specified multiple times to keep multiple sections.
+.sp
+For MachO objects, \fB<section>\fP must be formatted as
+\fB<segment name>,<section name>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-redefine\-sym <old>=<new>
+Rename symbols called \fB<old>\fP to \fB<new>\fP in the output. Can be specified
+multiple times to rename multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-redefine\-syms <filename>
+Rename symbols in the output as described in the file \fB<filename>\fP\&. In the
+file, each line represents a single symbol to rename, with the old name and new
+name separated by whitespace. Leading and trailing whitespace is ignored, as is
+anything following a \(aq#\(aq. Can be specified multiple times to read names from
+multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-regex
+If specified, symbol and section names specified by other switches are treated
+as extended POSIX regular expression patterns.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-remove\-section <section>, \-R
+Remove the specified section from the output. Can be specified multiple times
+to remove multiple sections simultaneously.
+.sp
+For MachO objects, \fB<section>\fP must be formatted as
+\fB<segment name>,<section name>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-set\-section\-alignment <section>=<align>
+Set the alignment of section \fB<section>\fP to \fB<align>\fP\&. Can be specified
+multiple times to update multiple sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-set\-section\-flags <section>=<flag>[,<flag>,...]
+Set section properties in the output of section \fB<section>\fP based on the
+specified \fB<flag>\fP values. Can be specified multiple times to update multiple
+sections.
+.sp
+Supported flag names are \fIalloc\fP, \fIload\fP, \fInoload\fP, \fIreadonly\fP, \fIexclude\fP,
+\fIdebug\fP, \fIcode\fP, \fIdata\fP, \fIrom\fP, \fIshare\fP, \fIcontents\fP, \fImerge\fP and \fIstrings\fP\&. Not
+all flags are meaningful for all object file formats.
+.sp
+For ELF objects, the flags have the following effects:
+.INDENT 7.0
+.IP \(bu 2
+\fIalloc\fP = add the \fISHF_ALLOC\fP flag.
+.IP \(bu 2
+\fIload\fP = if the section has \fISHT_NOBITS\fP type, mark it as a \fISHT_PROGBITS\fP
+section.
+.IP \(bu 2
+\fIreadonly\fP = if this flag is not specified, add the \fISHF_WRITE\fP flag.
+.IP \(bu 2
+\fIexclude\fP = add the \fISHF_EXCLUDE\fP flag.
+.IP \(bu 2
+\fIcode\fP = add the \fISHF_EXECINSTR\fP flag.
+.IP \(bu 2
+\fImerge\fP = add the \fISHF_MERGE\fP flag.
+.IP \(bu 2
+\fIstrings\fP = add the \fISHF_STRINGS\fP flag.
+.IP \(bu 2
+\fIcontents\fP = if the section has \fISHT_NOBITS\fP type, mark it as a \fISHT_PROGBITS\fP
+section.
+.UNINDENT
+.sp
+For COFF objects, the flags have the following effects:
+.INDENT 7.0
+.IP \(bu 2
+\fIalloc\fP = add the \fIIMAGE_SCN_CNT_UNINITIALIZED_DATA\fP and \fIIMAGE_SCN_MEM_READ\fP
+flags, unless the \fIload\fP flag is specified.
+.IP \(bu 2
+\fInoload\fP = add the \fIIMAGE_SCN_LNK_REMOVE\fP and \fIIMAGE_SCN_MEM_READ\fP flags.
+.IP \(bu 2
+\fIreadonly\fP = if this flag is not specified, add the \fIIMAGE_SCN_MEM_WRITE\fP
+flag.
+.IP \(bu 2
+\fIexclude\fP = add the \fIIMAGE_SCN_LNK_REMOVE\fP and \fIIMAGE_SCN_MEM_READ\fP flags.
+.IP \(bu 2
+\fIdebug\fP = add the \fIIMAGE_SCN_CNT_INITIALIZED_DATA\fP,
+\fIIMAGE_SCN_MEM_DISCARDABLE\fP and \fIIMAGE_SCN_MEM_READ\fP flags.
+.IP \(bu 2
+\fIcode\fP = add the \fIIMAGE_SCN_CNT_CODE\fP, \fIIMAGE_SCN_MEM_EXECUTE\fP and
+\fIIMAGE_SCN_MEM_READ\fP flags.
+.IP \(bu 2
+\fIdata\fP = add the \fIIMAGE_SCN_CNT_INITIALIZED_DATA\fP and \fIIMAGE_SCN_MEM_READ\fP
+flags.
+.IP \(bu 2
+\fIshare\fP = add the \fIIMAGE_SCN_MEM_SHARED\fP and \fIIMAGE_SCN_MEM_READ\fP flags.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-all\-gnu
+Remove all symbols, debug sections and relocations from the output. This option
+is equivalent to GNU \fBobjcopy\fP\(aqs \fB\-\-strip\-all\fP switch.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-all, \-S
+For ELF objects, remove from the output all symbols and non\-alloc sections not
+within segments, except for .gnu.warning, .ARM.attribute sections and the
+section name table.
+.sp
+For COFF and Mach\-O objects, remove all symbols, debug sections, and
+relocations from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-debug, \-g
+Remove all debug sections from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-symbol <symbol>, \-N
+Remove all symbols named \fB<symbol>\fP from the output. Can be specified
+multiple times to remove multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-symbols <filename>
+Remove all symbols whose names appear in the file \fB<filename>\fP, from the
+output. In the file, each line represents a single symbol name, with leading
+and trailing whitespace ignored, as is anything following a \(aq#\(aq. Can be
+specified multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-unneeded\-symbol <symbol>
+Remove from the output all symbols named \fB<symbol>\fP that are local or
+undefined and are not required by any relocation.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-unneeded\-symbols <filename>
+Remove all symbols whose names appear in the file \fB<filename>\fP, from the
+output, if they are local or undefined and are not required by any relocation.
+In the file, each line represents a single symbol name, with leading and
+trailing whitespace ignored, as is anything following a \(aq#\(aq. Can be specified
+multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-unneeded
+Remove from the output all local or undefined symbols that are not required by
+relocations. Also remove all debug sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-update\-section <name>=<file>
+Replace the contents of the section \fB<name>\fP with contents from the file
+\fB<file>\fP\&. If the section \fB<name>\fP is part of a segment, the new contents
+cannot be larger than the existing section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version, \-V
+Display the version of the \fBllvm\-objcopy\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-wildcard, \-w
+Allow wildcard syntax for symbol\-related flags. On by default for
+section\-related flags. Incompatible with \-\-regex.
+.sp
+Wildcard syntax allows the following special symbols:
+.TS
+center;
+|l|l|l|.
+_
+T{
+Character
+T} T{
+Meaning
+T} T{
+Equivalent
+T}
+_
+T{
+\fB*\fP
+T} T{
+Any number of characters
+T} T{
+\fB\&.*\fP
+T}
+_
+T{
+\fB?\fP
+T} T{
+Any single character
+T} T{
+\fB\&.\fP
+T}
+_
+T{
+\fB\e\fP
+T} T{
+Escape the next character
+T} T{
+\fB\e\fP
+T}
+_
+T{
+\fB[a\-z]\fP
+T} T{
+Character class
+T} T{
+\fB[a\-z]\fP
+T}
+_
+T{
+\fB[!a\-z]\fP, \fB[^a\-z]\fP
+T} T{
+Negated character class
+T} T{
+\fB[^a\-z]\fP
+T}
+_
+.TE
+.sp
+Additionally, starting a wildcard with \(aq!\(aq will prevent a match, even if
+another flag matches. For example \fB\-w \-N \(aq*\(aq \-N \(aq!x\(aq\fP will strip all symbols
+except for \fBx\fP\&.
+.sp
+The order of wildcards does not matter. For example, \fB\-w \-N \(aq*\(aq \-N \(aq!x\(aq\fP is
+the same as \fB\-w \-N \(aq!x\(aq \-N \(aq*\(aq\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options and commands from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH ELF-SPECIFIC OPTIONS
+.sp
+The following options are implemented only for ELF objects. If used with other
+objects, \fBllvm\-objcopy\fP will either emit an error or silently ignore
+them.
+.INDENT 0.0
+.TP
+.B \-\-add\-symbol <name>=[<section>:]<value>[,<flags>]
+Add a new symbol called \fB<name>\fP to the output symbol table, in the section
+named \fB<section>\fP, with value \fB<value>\fP\&. If \fB<section>\fP is not specified,
+the symbol is added as an absolute symbol. The \fB<flags>\fP affect the symbol
+properties. Accepted values are:
+.INDENT 7.0
+.IP \(bu 2
+\fIglobal\fP = the symbol will have global binding.
+.IP \(bu 2
+\fIlocal\fP = the symbol will have local binding.
+.IP \(bu 2
+\fIweak\fP = the symbol will have weak binding.
+.IP \(bu 2
+\fIdefault\fP = the symbol will have default visibility.
+.IP \(bu 2
+\fIhidden\fP = the symbol will have hidden visibility.
+.IP \(bu 2
+\fIprotected\fP = the symbol will have protected visibility.
+.IP \(bu 2
+\fIfile\fP = the symbol will be an \fISTT_FILE\fP symbol.
+.IP \(bu 2
+\fIsection\fP = the symbol will be an \fISTT_SECTION\fP symbol.
+.IP \(bu 2
+\fIobject\fP = the symbol will be an \fISTT_OBJECT\fP symbol.
+.IP \(bu 2
+\fIfunction\fP = the symbol will be an \fISTT_FUNC\fP symbol.
+.IP \(bu 2
+\fIindirect\-function\fP = the symbol will be an \fISTT_GNU_IFUNC\fP symbol.
+.UNINDENT
+.sp
+Additionally, the following flags are accepted but ignored: \fIdebug\fP,
+\fIconstructor\fP, \fIwarning\fP, \fIindirect\fP, \fIsynthetic\fP, \fIunique\-object\fP, \fIbefore\fP\&.
+.sp
+Can be specified multiple times to add multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-allow\-broken\-links
+Allow \fBllvm\-objcopy\fP to remove sections even if it would leave invalid
+section references. Any invalid sh_link fields will be set to zero.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-change\-start <incr>, \-\-adjust\-start
+Add \fB<incr>\fP to the program\(aqs start address. Can be specified multiple
+times, in which case the values will be applied cumulatively.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-compress\-debug\-sections [<format>]
+Compress DWARF debug sections in the output, using the specified format.
+Supported formats are \fBzlib\fP and \fBzstd\fP\&. Use \fBzlib\fP if \fB<format>\fP is omitted.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-decompress\-debug\-sections
+Decompress any compressed DWARF debug sections in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-discard\-locals, \-X
+Remove local symbols starting with \(dq.L\(dq from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-extract\-dwo
+Remove all sections that are not DWARF .dwo sections from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-extract\-main\-partition
+Extract the main partition from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-extract\-partition <name>
+Extract the named partition from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-globalize\-symbol <symbol>
+Mark any defined symbols named \fB<symbol>\fP as global symbols in the output.
+Can be specified multiple times to mark multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-globalize\-symbols <filename>
+Read a list of names from the file \fB<filename>\fP and mark defined symbols with
+those names as global in the output. In the file, each line represents a single
+symbol, with leading and trailing whitespace ignored, as is anything following
+a \(aq#\(aq. Can be specified multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-input\-target <format>, \-I
+Read the input as the specified format. See \fI\%SUPPORTED FORMATS\fP for a list of
+valid \fB<format>\fP values. If unspecified, \fBllvm\-objcopy\fP will attempt
+to determine the format automatically.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-file\-symbols
+Keep symbols of type \fISTT_FILE\fP, even if they would otherwise be stripped.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-global\-symbol <symbol>, \-G
+Make all symbols local in the output, except for symbols with the name
+\fB<symbol>\fP\&. Can be specified multiple times to ignore multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-global\-symbols <filename>
+Make all symbols local in the output, except for symbols named in the file
+\fB<filename>\fP\&. In the file, each line represents a single symbol, with leading
+and trailing whitespace ignored, as is anything following a \(aq#\(aq. Can be
+specified multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-section <section>
+When removing sections from the output, do not remove sections named
+\fB<section>\fP\&. Can be specified multiple times to keep multiple sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-symbol <symbol>, \-K
+When removing symbols from the output, do not remove symbols named
+\fB<symbol>\fP\&. Can be specified multiple times to keep multiple symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-keep\-symbols <filename>
+When removing symbols from the output do not remove symbols named in the file
+\fB<filename>\fP\&. In the file, each line represents a single symbol, with leading
+and trailing whitespace ignored, as is anything following a \(aq#\(aq. Can be
+specified multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-localize\-hidden
+Make all symbols with hidden or internal visibility local in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-localize\-symbol <symbol>, \-L
+Mark any defined non\-common symbol named \fB<symbol>\fP as a local symbol in the
+output. Can be specified multiple times to mark multiple symbols as local.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-localize\-symbols <filename>
+Read a list of names from the file \fB<filename>\fP and mark defined non\-common
+symbols with those names as local in the output. In the file, each line
+represents a single symbol, with leading and trailing whitespace ignored, as is
+anything following a \(aq#\(aq. Can be specified multiple times to read names from
+multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-new\-symbol\-visibility <visibility>
+Specify the visibility of the symbols automatically created when using binary
+input or \fI\%\-\-add\-symbol\fP\&. Valid options are:
+.INDENT 7.0
+.IP \(bu 2
+\fIdefault\fP
+.IP \(bu 2
+\fIhidden\fP
+.IP \(bu 2
+\fIinternal\fP
+.IP \(bu 2
+\fIprotected\fP
+.UNINDENT
+.sp
+The default is \fIdefault\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output\-target <format>, \-O
+Write the output as the specified format. See \fI\%SUPPORTED FORMATS\fP for a list
+of valid \fB<format>\fP values. If unspecified, the output format is assumed to
+be the same as the value specified for \fI\%\-\-input\-target\fP or the input
+file\(aqs format if that option is also unspecified.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-prefix\-alloc\-sections <prefix>
+Add \fB<prefix>\fP to the front of the names of all allocatable sections in the
+output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-prefix\-symbols <prefix>
+Add \fB<prefix>\fP to the front of every symbol name in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-preserve\-dates, \-p
+Preserve access and modification timestamps in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-rename\-section <old>=<new>[,<flag>,...]
+Rename sections called \fB<old>\fP to \fB<new>\fP in the output, and apply any
+specified \fB<flag>\fP values. See \fI\%\-\-set\-section\-flags\fP for a list of
+supported flags. Can be specified multiple times to rename multiple sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-set\-section\-type <section>=<type>
+Set the type of section \fB<section>\fP to the integer \fB<type>\fP\&. Can be
+specified multiple times to update multiple sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-set\-start\-addr <addr>
+Set the start address of the output to \fB<addr>\fP\&. Overrides any previously
+specified \fI\%\-\-change\-start\fP or \fI\%\-\-adjust\-start\fP options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-split\-dwo <dwo\-file>
+Equivalent to running \fBllvm\-objcopy\fP with \fI\%\-\-extract\-dwo\fP and
+\fB<dwo\-file>\fP as the output file and no other options, and then with
+\fI\%\-\-strip\-dwo\fP on the input file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-dwo
+Remove all DWARF .dwo sections from the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-non\-alloc
+Remove from the output all non\-allocatable sections that are not within
+segments.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-strip\-sections
+Remove from the output all section headers and all section data not within
+segments. Note that many tools will not be able to use an object without
+section headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-target <format>, \-F
+Equivalent to \fI\%\-\-input\-target\fP and \fI\%\-\-output\-target\fP for the
+specified format. See \fI\%SUPPORTED FORMATS\fP for a list of valid \fB<format>\fP
+values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-weaken\-symbol <symbol>, \-W
+Mark any global symbol named \fB<symbol>\fP as a weak symbol in the output. Can
+be specified multiple times to mark multiple symbols as weak.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-weaken\-symbols <filename>
+Read a list of names from the file \fB<filename>\fP and mark global symbols with
+those names as weak in the output. In the file, each line represents a single
+symbol, with leading and trailing whitespace ignored, as is anything following
+a \(aq#\(aq. Can be specified multiple times to read names from multiple files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-weaken
+Mark all defined global symbols as weak in the output.
+.UNINDENT
+.SH MACH-O-SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-keep\-undefined
+Keep undefined symbols, even if they would otherwise be stripped.
+.UNINDENT
+.SH COFF-SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-subsystem <name>[:<version>]
+Set the PE subsystem, and optionally subsystem version.
+.UNINDENT
+.SH SUPPORTED FORMATS
+.sp
+The following values are currently supported by \fBllvm\-objcopy\fP for the
+\fI\%\-\-input\-target\fP, \fI\%\-\-output\-target\fP, and \fI\%\-\-target\fP
+options. For GNU \fBobjcopy\fP compatibility, the values are all bfdnames.
+.INDENT 0.0
+.IP \(bu 2
+\fIbinary\fP
+.IP \(bu 2
+\fIihex\fP
+.IP \(bu 2
+\fIelf32\-i386\fP
+.IP \(bu 2
+\fIelf32\-x86\-64\fP
+.IP \(bu 2
+\fIelf64\-x86\-64\fP
+.IP \(bu 2
+\fIelf32\-iamcu\fP
+.IP \(bu 2
+\fIelf32\-littlearm\fP
+.IP \(bu 2
+\fIelf64\-aarch64\fP
+.IP \(bu 2
+\fIelf64\-littleaarch64\fP
+.IP \(bu 2
+\fIelf32\-littleriscv\fP
+.IP \(bu 2
+\fIelf64\-littleriscv\fP
+.IP \(bu 2
+\fIelf32\-powerpc\fP
+.IP \(bu 2
+\fIelf32\-powerpcle\fP
+.IP \(bu 2
+\fIelf64\-powerpc\fP
+.IP \(bu 2
+\fIelf64\-powerpcle\fP
+.IP \(bu 2
+\fIelf32\-bigmips\fP
+.IP \(bu 2
+\fIelf32\-ntradbigmips\fP
+.IP \(bu 2
+\fIelf32\-ntradlittlemips\fP
+.IP \(bu 2
+\fIelf32\-tradbigmips\fP
+.IP \(bu 2
+\fIelf32\-tradlittlemips\fP
+.IP \(bu 2
+\fIelf64\-tradbigmips\fP
+.IP \(bu 2
+\fIelf64\-tradlittlemips\fP
+.IP \(bu 2
+\fIelf32\-sparc\fP
+.IP \(bu 2
+\fIelf32\-sparcel\fP
+.UNINDENT
+.sp
+Additionally, all targets except \fIbinary\fP and \fIihex\fP can have \fI\-freebsd\fP as a
+suffix.
+.SH BINARY INPUT AND OUTPUT
+.sp
+If \fIbinary\fP is used as the value for \fI\%\-\-input\-target\fP, the input file
+will be embedded as a data section in an ELF relocatable object, with symbols
+\fB_binary_<file_name>_start\fP, \fB_binary_<file_name>_end\fP, and
+\fB_binary_<file_name>_size\fP representing the start, end and size of the data,
+where \fB<file_name>\fP is the path of the input file as specified on the command
+line with non\-alphanumeric characters converted to \fB_\fP\&.
+.sp
+If \fIbinary\fP is used as the value for \fI\%\-\-output\-target\fP, the output file
+will be a raw binary file, containing the memory image of the input file.
+Symbols and relocation information will be discarded. The image will start at
+the address of the first loadable section in the output.
+.SH EXIT STATUS
+.sp
+\fBllvm\-objcopy\fP exits with a non\-zero exit code if there is an error.
+Otherwise, it exits with code 0.
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/labels/tools:llvm\-objcopy/strip/\fP>.
+.sp
+There is a known issue with \fI\%\-\-input\-target\fP and \fI\%\-\-target\fP
+causing only \fBbinary\fP and \fBihex\fP formats to have any effect. Other values
+will be ignored and \fBllvm\-objcopy\fP will attempt to guess the input
+format.
+.SH SEE ALSO
+.sp
+\fBllvm\-strip(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile
new file mode 100644
index 000000000000..ad1c7beee95f
--- /dev/null
+++ b/usr.bin/clang/llvm-objdump/Makefile
@@ -0,0 +1,35 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-objdump
+
+SRCDIR= llvm/tools/llvm-objdump
+SRCS+= COFFDump.cpp
+SRCS+= ELFDump.cpp
+SRCS+= MachODump.cpp
+SRCS+= OffloadDump.cpp
+SRCS+= SourcePrinter.cpp
+SRCS+= WasmDump.cpp
+SRCS+= XCOFFDump.cpp
+SRCS+= llvm-objdump-driver.cpp
+SRCS+= llvm-objdump.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+.for hdr in ObjdumpOpts OtoolOpts
+${hdr}.inc: ${LLVM_BASE}/${SRCDIR}/${hdr}.td
+ ${LLVM_TBLGEN} -gen-opt-parser-defs \
+ -I ${LLVM_SRCS}/tools/llvm-objcopy -I ${LLVM_SRCS}/include \
+ -d ${.TARGET}.d -o ${.TARGET} ${LLVM_BASE}/${SRCDIR}/${hdr}.td
+TGHDRS+= ${hdr}.inc
+.endfor
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LINKS= ${BINDIR}/llvm-objdump ${BINDIR}/objdump
+MLINKS= llvm-objdump.1 objdump.1
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-objdump/Makefile.depend b/usr.bin/clang/llvm-objdump/Makefile.depend
new file mode 100644
index 000000000000..006fa45dd459
--- /dev/null
+++ b/usr.bin/clang/llvm-objdump/Makefile.depend
@@ -0,0 +1,25 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-tblgen.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-objdump/llvm-objdump-driver.cpp b/usr.bin/clang/llvm-objdump/llvm-objdump-driver.cpp
new file mode 100644
index 000000000000..a469e0b35531
--- /dev/null
+++ b/usr.bin/clang/llvm-objdump/llvm-objdump-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_objdump_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_objdump_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-objdump/llvm-objdump.1 b/usr.bin/clang/llvm-objdump/llvm-objdump.1
new file mode 100644
index 000000000000..3eb07a444bde
--- /dev/null
+++ b/usr.bin/clang/llvm-objdump/llvm-objdump.1
@@ -0,0 +1,578 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-OBJDUMP" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-objdump \- LLVM's object file dumper
+.SH SYNOPSIS
+.sp
+\fBllvm\-objdump\fP [\fIcommands\fP] [\fIoptions\fP] [\fIfilenames...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-objdump\fP utility prints the contents of object files and
+final linked images named on the command line. If no file name is specified,
+\fBllvm\-objdump\fP will attempt to read from \fIa.out\fP\&. If \fI\-\fP is used as a
+file name, \fBllvm\-objdump\fP will process a file on its standard input
+stream.
+.SH COMMANDS
+.sp
+At least one of the following commands are required, and some commands can be
+combined with other commands:
+.INDENT 0.0
+.TP
+.B \-a, \-\-archive\-headers
+Display the information contained within an archive\(aqs headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-d, \-\-disassemble
+Disassemble all executable sections found in the input files. On some
+architectures (AArch64, PPC64, x86), all known instructions are disassembled by
+default. On the others, \fI\%\-\-mcpu\fP or \fI\%\-\-mattr\fP is needed to
+enable some instruction sets. Disabled instructions are displayed as
+\fB<unknown>\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-D, \-\-disassemble\-all
+Disassemble all sections found in the input files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-disassemble\-symbols=<symbol1[,symbol2,...]>
+Disassemble only the specified symbols. Takes demangled symbol names when
+\fI\%\-\-demangle\fP is specified, otherwise takes mangled symbol names.
+Implies \fI\%\-\-disassemble\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dwarf=<value>
+Dump the specified DWARF debug sections. The supported values are:
+.sp
+\fIframes\fP \- .debug_frame
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-f, \-\-file\-headers
+Display the contents of the overall file header.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-fault\-map\-section
+Display the content of the fault map section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-h, \-\-headers, \-\-section\-headers
+Display summaries of the headers for each section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Display usage information and exit. Does not stack with other commands.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-p, \-\-private\-headers
+Display format\-specific file headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-r, \-\-reloc
+Display the relocation entries in the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-R, \-\-dynamic\-reloc
+Display the dynamic relocation entries in the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-raw\-clang\-ast
+Dump the raw binary contents of the clang AST section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-s, \-\-full\-contents
+Display the contents of each section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-t, \-\-syms
+Display the symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-T, \-\-dynamic\-syms
+Display the contents of the dynamic symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-u, \-\-unwind\-info
+Display the unwind info of the input(s).
+.sp
+This operation is only currently supported for COFF and Mach\-O object files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v, \-\-version
+Display the version of the \fBllvm\-objdump\fP executable. Does not stack
+with other commands.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x, \-\-all\-headers
+Display all available header information. Equivalent to specifying
+\fI\%\-\-archive\-headers\fP, \fI\%\-\-file\-headers\fP,
+\fI\%\-\-private\-headers\fP, \fI\%\-\-reloc\fP, \fI\%\-\-section\-headers\fP,
+and \fI\%\-\-syms\fP\&.
+.UNINDENT
+.SH OPTIONS
+.sp
+\fBllvm\-objdump\fP supports the following options:
+.INDENT 0.0
+.TP
+.B \-\-adjust\-vma=<offset>
+Increase the displayed address in disassembly or section header printing by
+the specified offset.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-arch\-name=<string>
+Specify the target architecture when disassembling. Use \fI\%\-\-version\fP
+for a list of available targets.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-build\-id=<string>
+Look up the object using the given build ID, specified as a hexadecimal
+string. The found object is handled as if it were an input filename.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-C, \-\-demangle
+Demangle symbol names in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-file\-directory <path>
+Provide a path to a directory with a \fI\&.build\-id\fP subdirectory to search for
+debug information for stripped binaries. Multiple instances of this argument
+are searched in the order given.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debuginfod, \-\-no\-debuginfod
+Whether or not to try debuginfod lookups for debug binaries. Unless specified,
+debuginfod is only enabled if libcurl was compiled in (\fBLLVM_ENABLE_CURL\fP)
+and at least one server URL was provided by the environment variable
+\fBDEBUGINFOD_URLS\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-vars=<format>
+Print the locations (in registers or memory) of source\-level variables
+alongside disassembly. \fBformat\fP may be \fBunicode\fP or \fBascii\fP, defaulting
+to \fBunicode\fP if omitted.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-vars\-indent=<width>
+Distance to indent the source\-level variable display, relative to the start
+of the disassembly. Defaults to 52 characters.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-j, \-\-section=<section1[,section2,...]>
+Perform commands on the specified sections only. For Mach\-O use
+\fIsegment,section\fP to specify the section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-l, \-\-line\-numbers
+When disassembling, display source line numbers. Implies
+\fI\%\-\-disassemble\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-M, \-\-disassembler\-options=<opt1[,opt2,...]>
+Pass target\-specific disassembler options. Available options:
+.INDENT 7.0
+.IP \(bu 2
+\fBreg\-names\-std\fP: ARM only (default). Print in ARM \(aqs instruction set documentation, with r13/r14/r15 replaced by sp/lr/pc.
+.IP \(bu 2
+\fBreg\-names\-raw\fP: ARM only. Use r followed by the register number.
+.IP \(bu 2
+\fBno\-aliases\fP: AArch64 and RISC\-V only. Print raw instruction mnemonic instead of pseudo instruction mnemonic.
+.IP \(bu 2
+\fBnumeric\fP: RISC\-V only. Print raw register names instead of ABI mnemonic. (e.g. print x1 instead of ra)
+.IP \(bu 2
+\fBatt\fP: x86 only (default). Print in the AT&T syntax.
+.IP \(bu 2
+\fBintel\fP: x86 only. Print in the intel syntax.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-mcpu=<cpu\-name>
+Target a specific CPU type for disassembly. Specify \fB\-\-mcpu=help\fP to display
+available CPUs.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-mattr=<a1,+a2,\-a3,...>
+Enable/disable target\-specific attributes. Specify \fB\-\-mattr=help\fP to display
+the available attributes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-leading\-addr, \-\-no\-addresses
+When disassembling, do not print leading addresses for instructions or inline
+relocations.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-print\-imm\-hex
+Do not use hex format for immediate values in disassembly output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-show\-raw\-insn
+When disassembling, do not print the raw bytes of each instruction.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-offloading
+Display the content of the LLVM offloading section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-prefix=<prefix>
+When disassembling with the \fI\%\-\-source\fP option, prepend \fBprefix\fP to
+absolute paths.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-prefix\-strip=<level>
+When disassembling with the \fI\%\-\-source\fP option, strip out \fBlevel\fP
+initial directories from absolute paths. This option has no effect without
+\fI\%\-\-prefix\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-imm\-hex
+Use hex format when printing immediate values in disassembly output (default).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S, \-\-source
+When disassembling, display source interleaved with the disassembly. Implies
+\fI\%\-\-disassemble\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-all\-symbols
+Show all symbols during disassembly, even if multiple symbols are defined at
+the same location.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-lma
+Display the LMA column when dumping ELF section headers. Defaults to off
+unless any section has different VMA and LMAs.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-start\-address=<address>
+When disassembling, only disassemble from the specified address.
+.sp
+When printing relocations, only print the relocations patching offsets from at least \fBaddress\fP\&.
+.sp
+When printing symbols, only print symbols with a value of at least \fBaddress\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stop\-address=<address>
+When disassembling, only disassemble up to, but not including the specified address.
+.sp
+When printing relocations, only print the relocations patching offsets up to \fBaddress\fP\&.
+.sp
+When printing symbols, only print symbols with a value up to \fBaddress\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-symbolize\-operands
+When disassembling, symbolize a branch target operand to print a label instead of a real address.
+.sp
+When printing a PC\-relative global symbol reference, print it as an offset from the leading symbol.
+.sp
+When a bb\-address\-map section is present (i.e., the object file is built with \fB\-fbasic\-block\-sections=labels\fP), labels are retrieved from that section instead.
+.sp
+Only works with PowerPC objects or X86 linked images.
+.INDENT 7.0
+.TP
+.B Example:
+A non\-symbolized branch instruction with a local target and pc\-relative memory access like
+.UNINDENT
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+cmp eax, dword ptr [rip + 4112]
+jge 0x20117e <_start+0x25>
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+might become
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+<L0>:
+ cmp eax, dword ptr <g>
+ jge <L0>
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-triple=<string>
+Target triple to disassemble for, see \fB\-\-version\fP for available targets.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-w, \-\-wide
+Ignored for compatibility with GNU objdump.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-x86\-asm\-syntax=<style>
+Deprecated.
+When used with \fI\%\-\-disassemble\fP, choose style of code to emit from
+X86 backend. Supported values are:
+.INDENT 7.0
+.INDENT 3.5
+.INDENT 0.0
+.TP
+.B att
+AT&T\-style assembly
+.UNINDENT
+.INDENT 0.0
+.TP
+.B intel
+Intel\-style assembly
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+The default disassembly style is \fBatt\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-z, \-\-disassemble\-zeroes
+Do not skip blocks of zeroes when disassembling.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options and commands from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH MACH-O ONLY OPTIONS AND COMMANDS
+.INDENT 0.0
+.TP
+.B \-\-arch=<architecture>
+Specify the architecture to disassemble. see \fB\-\-version\fP for available
+architectures.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-archive\-member\-offsets
+Print the offset to each archive member for Mach\-O archives (requires
+\fI\%\-\-archive\-headers\fP).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-bind
+Display binding info
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-data\-in\-code
+Display the data in code table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dis\-symname=<name>
+Disassemble just the specified symbol\(aqs instructions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-chained\-fixups
+Print chained fixup information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyld\-info
+Print bind and rebase information used by dyld to resolve external
+references in a final linked binary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dylibs\-used
+Display the shared libraries used for linked files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dsym=<string>
+Use .dSYM file for debug info.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dylib\-id
+Display the shared library\(aqs ID for dylib files.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-exports\-trie
+Display exported symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-function\-starts [=<addrs|names|both>]
+Print the function starts table for Mach\-O objects. Either \fBaddrs\fP
+(default) to print only the addresses of functions, \fBnames\fP to print only
+the names of the functions (when available), or \fBboth\fP to print the
+names beside the addresses.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-g
+Print line information from debug info if available.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-full\-leading\-addr
+Print the full leading address when disassembling.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-indirect\-symbols
+Display the indirect symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-info\-plist
+Display the info plist section as strings.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-lazy\-bind
+Display lazy binding info.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-link\-opt\-hints
+Display the linker optimization hints.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-m, \-\-macho
+Use Mach\-O specific object file parser. Commands and other options may behave
+differently when used with \fB\-\-macho\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-leading\-headers
+Do not print any leading headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-symbolic\-operands
+Do not print symbolic operands when disassembling.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-non\-verbose
+Display the information for Mach\-O objects in non\-verbose or numeric form.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-objc\-meta\-data
+Display the Objective\-C runtime meta data.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-private\-header
+Display only the first format specific file header.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-rebase
+Display rebasing information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-rpaths
+Display runtime search paths for the binary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-universal\-headers
+Display universal headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-weak\-bind
+Display weak binding information.
+.UNINDENT
+.SH XCOFF ONLY OPTIONS AND COMMANDS
+.INDENT 0.0
+.TP
+.B \-\-symbol\-description
+Add symbol description to disassembly output.
+.UNINDENT
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/labels/tools:llvm\-objdump/\fP>.
+.SH SEE ALSO
+.sp
+\fBllvm\-nm(1)\fP, \fBllvm\-otool(1)\fP, \fBllvm\-readelf(1)\fP,
+\fBllvm\-readobj(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-pdbutil/Makefile b/usr.bin/clang/llvm-pdbutil/Makefile
new file mode 100644
index 000000000000..ddbfc91e0b55
--- /dev/null
+++ b/usr.bin/clang/llvm-pdbutil/Makefile
@@ -0,0 +1,25 @@
+PROG_CXX= llvm-pdbutil
+
+SRCDIR= llvm/tools/llvm-pdbutil
+SRCS+= BytesOutputStyle.cpp
+SRCS+= DumpOutputStyle.cpp
+SRCS+= ExplainOutputStyle.cpp
+SRCS+= MinimalSymbolDumper.cpp
+SRCS+= MinimalTypeDumper.cpp
+SRCS+= PdbYaml.cpp
+SRCS+= PrettyBuiltinDumper.cpp
+SRCS+= PrettyClassDefinitionDumper.cpp
+SRCS+= PrettyClassLayoutGraphicalDumper.cpp
+SRCS+= PrettyCompilandDumper.cpp
+SRCS+= PrettyEnumDumper.cpp
+SRCS+= PrettyExternalSymbolDumper.cpp
+SRCS+= PrettyFunctionDumper.cpp
+SRCS+= PrettyTypeDumper.cpp
+SRCS+= PrettyTypedefDumper.cpp
+SRCS+= PrettyVariableDumper.cpp
+SRCS+= StreamUtil.cpp
+SRCS+= TypeReferenceTracker.cpp
+SRCS+= YAMLOutputStyle.cpp
+SRCS+= llvm-pdbutil.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-pdbutil/Makefile.depend b/usr.bin/clang/llvm-pdbutil/Makefile.depend
new file mode 100644
index 000000000000..dd4c6894d092
--- /dev/null
+++ b/usr.bin/clang/llvm-pdbutil/Makefile.depend
@@ -0,0 +1,22 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-pdbutil/llvm-pdbutil.1 b/usr.bin/clang/llvm-pdbutil/llvm-pdbutil.1
new file mode 100644
index 000000000000..0b98b089b38c
--- /dev/null
+++ b/usr.bin/clang/llvm-pdbutil/llvm-pdbutil.1
@@ -0,0 +1,744 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-PDBUTIL" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-pdbutil \- PDB File forensics and diagnostics
+.INDENT 0.0
+.IP \(bu 2
+\fI\%Synopsis\fP
+.IP \(bu 2
+\fI\%Description\fP
+.IP \(bu 2
+\fI\%Subcommands\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%pretty\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Filtering and Sorting Options\fP
+.IP \(bu 2
+\fI\%Symbol Type Options\fP
+.IP \(bu 2
+\fI\%Other Options\fP
+.UNINDENT
+.UNINDENT
+.IP \(bu 2
+\fI\%dump\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%MSF Container Options\fP
+.IP \(bu 2
+\fI\%Module & File Options\fP
+.IP \(bu 2
+\fI\%Symbol Options\fP
+.IP \(bu 2
+\fI\%Type Record Options\fP
+.IP \(bu 2
+\fI\%Miscellaneous Options\fP
+.UNINDENT
+.UNINDENT
+.IP \(bu 2
+\fI\%bytes\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%MSF File Options\fP
+.IP \(bu 2
+\fI\%PDB Stream Options\fP
+.IP \(bu 2
+\fI\%DBI Stream Options\fP
+.IP \(bu 2
+\fI\%Module Options\fP
+.IP \(bu 2
+\fI\%Type Record Options\fP
+.UNINDENT
+.UNINDENT
+.IP \(bu 2
+\fI\%pdb2yaml\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.UNINDENT
+.IP \(bu 2
+\fI\%yaml2pdb\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.UNINDENT
+.IP \(bu 2
+\fI\%merge\fP
+.INDENT 2.0
+.IP \(bu 2
+\fI\%Summary\fP
+.IP \(bu 2
+\fI\%Options\fP
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH SYNOPSIS
+.sp
+\fBllvm\-pdbutil\fP [\fIsubcommand\fP] [\fIoptions\fP]
+.SH DESCRIPTION
+.sp
+Display types, symbols, CodeView records, and other information from a
+PDB file, as well as manipulate and create PDB files. \fBllvm\-pdbutil\fP
+is normally used by FileCheck\-based tests to test LLVM\(aqs PDB reading and
+writing functionality, but can also be used for general PDB file investigation
+and forensics, or as a replacement for cvdump.
+.SH SUBCOMMANDS
+.sp
+\fBllvm\-pdbutil\fP is separated into several subcommands each tailored to
+a different purpose. A brief summary of each command follows, with more detail
+in the sections that follow.
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+\fI\%pretty\fP \- Dump symbol and type information in a format that
+tries to look as much like the original source code as possible.
+.IP \(bu 2
+\fI\%dump\fP \- Dump low level types and structures from the PDB
+file, including CodeView records, hash tables, PDB streams, etc.
+.IP \(bu 2
+\fI\%bytes\fP \- Dump data from the PDB file\(aqs streams, records,
+types, symbols, etc as raw bytes.
+.IP \(bu 2
+\fI\%yaml2pdb\fP \- Given a yaml description of a PDB file, produce
+a valid PDB file that matches that description.
+.IP \(bu 2
+\fI\%pdb2yaml\fP \- For a given PDB file, produce a YAML
+description of some or all of the file in a way that the PDB can be
+reconstructed.
+.IP \(bu 2
+\fI\%merge\fP \- Given two PDBs, produce a third PDB that is the
+result of merging the two input PDBs.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS pretty
+.sp
+\fBIMPORTANT:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBpretty\fP subcommand is built on the Windows DIA SDK, and as such is not
+supported on non\-Windows platforms.
+.UNINDENT
+.UNINDENT
+.sp
+USAGE: \fBllvm\-pdbutil\fP pretty [\fIoptions\fP] <input PDB file>
+.SS Summary
+.sp
+The \fIpretty\fP subcommand displays a very high level representation of your
+program\(aqs debug info. Since it is built on the Windows DIA SDK which is the
+standard API that Windows tools and debuggers query debug information, it
+presents a more authoritative view of how a debugger is going to interpret your
+debug information than a mode which displays low\-level CodeView records.
+.SS Options
+.SS Filtering and Sorting Options
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+\fIexclude\fP filters take priority over \fIinclude\fP filters. So if a filter
+matches both an include and an exclude rule, then it is excluded.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-exclude\-compilands=<string>
+When dumping compilands, compiland source\-file contributions, or per\-compiland
+symbols, this option instructs \fBllvm\-pdbutil\fP to omit any compilands that
+match the specified regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-exclude\-symbols=<string>
+When dumping global, public, or per\-compiland symbols, this option instructs
+\fBllvm\-pdbutil\fP to omit any symbols that match the specified regular
+expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-exclude\-types=<string>
+When dumping types, this option instructs \fBllvm\-pdbutil\fP to omit any types
+that match the specified regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-include\-compilands=<string>
+When dumping compilands, compiland source\-file contributions, or per\-compiland
+symbols, limit the initial search to only those compilands that match the
+specified regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-include\-symbols=<string>
+When dumping global, public, or per\-compiland symbols, limit the initial
+search to only those symbols that match the specified regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-include\-types=<string>
+When dumping types, limit the initial search to only those types that match
+the specified regular expression.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-min\-class\-padding=<uint>
+Only display types that have at least the specified amount of alignment
+padding, accounting for padding in base classes and aggregate field members.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-min\-class\-padding\-imm=<uint>
+Only display types that have at least the specified amount of alignment
+padding, ignoring padding in base classes and aggregate field members.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-min\-type\-size=<uint>
+Only display types T where sizeof(T) is greater than or equal to the specified
+amount.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-no\-compiler\-generated
+Don\(aqt show compiler generated types and symbols
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-no\-enum\-definitions
+When dumping an enum, don\(aqt show the full enum (e.g. the individual enumerator
+values).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-no\-system\-libs
+Don\(aqt show symbols from system libraries
+.UNINDENT
+.SS Symbol Type Options
+.INDENT 0.0
+.TP
+.B \-all
+Implies all other options in this category.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-class\-definitions=<format>
+Displays class definitions in the specified format.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=all \- Display all class members including data, constants, typedefs, functions, etc (default)
+=layout \- Only display members that contribute to class size.
+=none \- Don\(aqt display class definitions (e.g. only display the name and base list)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-class\-order
+Displays classes in the specified order.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=none \- Undefined / no particular sort order (default)
+=name \- Sort classes by name
+=size \- Sort classes by size
+=padding \- Sort classes by amount of padding
+=padding\-pct \- Sort classes by percentage of space consumed by padding
+=padding\-imm \- Sort classes by amount of immediate padding
+=padding\-pct\-imm \- Sort classes by percentage of space consumed by immediate padding
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-class\-recurse\-depth=<uint>
+When dumping class definitions, stop after recursing the specified number of times. The
+default is 0, which is no limit.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-classes
+Display classes
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-compilands
+Display compilands (e.g. object files)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-enums
+Display enums
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-externals
+Dump external (e.g. exported) symbols
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-globals
+Dump global symbols
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-lines
+Dump the mappings between source lines and code addresses.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-module\-syms
+Display symbols (variables, functions, etc) for each compiland
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-sym\-types=<types>
+Type of symbols to dump when \-globals, \-externals, or \-module\-syms is
+specified. (default all)
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=thunks \- Display thunk symbols
+=data \- Display data symbols
+=funcs \- Display function symbols
+=all \- Display all symbols (default)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-symbol\-order=<order>
+For symbols dumped via the \-module\-syms, \-globals, or \-externals options, sort
+the results in specified order.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+=none \- Undefined / no particular sort order
+=name \- Sort symbols by name
+=size \- Sort symbols by size
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-typedefs
+Display typedef types
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-types
+Display all types (implies \-classes, \-enums, \-typedefs)
+.UNINDENT
+.SS Other Options
+.INDENT 0.0
+.TP
+.B \-color\-output
+Force color output on or off. By default, color if used if outputting to a
+terminal.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-load\-address=<uint>
+When displaying relative virtual addresses, assume the process is loaded at the
+given address and display what would be the absolute address.
+.UNINDENT
+.SS dump
+.sp
+USAGE: \fBllvm\-pdbutil\fP dump [\fIoptions\fP] <input PDB file>
+.SS Summary
+.sp
+The \fBdump\fP subcommand displays low level information about the structure of a
+PDB file. It is used heavily by LLVM\(aqs testing infrastructure, but can also be
+used for PDB forensics. It serves a role similar to that of Microsoft\(aqs
+\fIcvdump\fP tool.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBdump\fP subcommand exposes internal details of the file format. As
+such, the reader should be familiar with \fI\%The PDB File Format\fP before using this
+command.
+.UNINDENT
+.UNINDENT
+.SS Options
+.SS MSF Container Options
+.INDENT 0.0
+.TP
+.B \-streams
+dump a summary of all of the streams in the PDB file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stream\-blocks
+In conjunction with \fI\%\-streams\fP, add information to the output about
+what blocks the specified stream occupies.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-summary
+Dump MSF and PDB header information.
+.UNINDENT
+.SS Module & File Options
+.INDENT 0.0
+.TP
+.B \-modi=<uint>
+For all options that dump information from each module/compiland, limit to
+the specified module.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-files
+Dump the source files that contribute to each displayed module.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-il
+Dump inlinee line information (DEBUG_S_INLINEELINES CodeView subsection)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-l
+Dump line information (DEBUG_S_LINES CodeView subsection)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-modules
+Dump compiland information
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-xme
+Dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS CodeView subsection)
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-xmi
+Dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS CodeView subsection)
+.UNINDENT
+.SS Symbol Options
+.INDENT 0.0
+.TP
+.B \-globals
+dump global symbol records
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-global\-extras
+dump additional information about the globals, such as hash buckets and hash
+values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-publics
+dump public symbol records
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-public\-extras
+dump additional information about the publics, such as hash buckets and hash
+values.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-symbols
+dump symbols (functions, variables, etc) for each module dumped.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-sym\-data
+For each symbol record dumped as a result of the \fI\%\-symbols\fP option,
+display the full bytes of the record in binary as well.
+.UNINDENT
+.SS Type Record Options
+.INDENT 0.0
+.TP
+.B \-types
+Dump CodeView type records from TPI stream
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-type\-extras
+Dump additional information from the TPI stream, such as hashes and the type
+index offsets array.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-type\-data
+For each type record dumped, display the full bytes of the record in binary as
+well.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-type\-index=<uint>
+Only dump types with the specified type index.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-ids
+Dump CodeView type records from IPI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-id\-extras
+Dump additional information from the IPI stream, such as hashes and the type
+index offsets array.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-id\-data
+For each ID record dumped, display the full bytes of the record in binary as
+well.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-id\-index=<uint>
+only dump ID records with the specified hexadecimal type index.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-dependents
+When used in conjunction with \fI\%\-type\-index\fP or \fI\%\-id\-index\fP,
+dumps the entire dependency graph for the specified index instead of just the
+single record with the specified index. For example, if type index 0x4000 is
+a function whose return type has index 0x3000, and you specify
+\fI\-dependents=0x4000\fP, then this would dump both records (as well as any other
+dependents in the tree).
+.UNINDENT
+.SS Miscellaneous Options
+.INDENT 0.0
+.TP
+.B \-all
+Implies most other options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-section\-contribs
+Dump section contributions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-section\-headers
+Dump image section headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-section\-map
+Dump section map.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-string\-table
+Dump PDB string table.
+.UNINDENT
+.SS bytes
+.sp
+USAGE: \fBllvm\-pdbutil\fP bytes [\fIoptions\fP] <input PDB file>
+.SS Summary
+.sp
+Like the \fBdump\fP subcommand, the \fBbytes\fP subcommand displays low level
+information about the structure of a PDB file, but it is used for even deeper
+forensics. The \fBbytes\fP subcommand finds various structures in a PDB file
+based on the command line options specified, and dumps them in hex. Someone
+working on support for emitting PDBs would use this heavily, for example, to
+compare one PDB against another PDB to ensure byte\-for\-byte compatibility. It
+is not enough to simply compare the bytes of an entire file, or an entire stream
+because it\(aqs perfectly fine for the same structure to exist at different
+locations in two different PDBs, and \(dqfinding\(dq the structure is half the battle.
+.SS Options
+.SS MSF File Options
+.INDENT 0.0
+.TP
+.B \-block\-range=<start[\-end]>
+Dump binary data from specified range of MSF file blocks.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-byte\-range=<start[\-end]>
+Dump binary data from specified range of bytes in the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-fpm
+Dump the MSF free page map.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stream\-data=<string>
+Dump binary data from the specified streams. Format is SN[:Start][@Size].
+For example, \fI\-stream\-data=7:3@12\fP dumps 12 bytes from stream 7, starting
+at offset 3 in the stream.
+.UNINDENT
+.SS PDB Stream Options
+.INDENT 0.0
+.TP
+.B \-name\-map
+Dump bytes of PDB Name Map
+.UNINDENT
+.SS DBI Stream Options
+.INDENT 0.0
+.TP
+.B \-ec
+Dump the edit and continue map substream of the DBI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-files
+Dump the file info substream of the DBI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-modi
+Dump the modi substream of the DBI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-sc
+Dump section contributions substream of the DBI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-sm
+Dump the section map from the DBI stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-type\-server
+Dump the type server map from the DBI stream.
+.UNINDENT
+.SS Module Options
+.INDENT 0.0
+.TP
+.B \-mod=<uint>
+Limit all options in this category to the specified module index. By default,
+options in this category will dump bytes from all modules.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-chunks
+Dump the bytes of each module\(aqs C13 debug subsection.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-split\-chunks
+When specified with \fI\%\-chunks\fP, split the C13 debug subsection into a
+separate chunk for each subsection type, and dump them separately.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-syms
+Dump the symbol record substream from each module.
+.UNINDENT
+.SS Type Record Options
+.INDENT 0.0
+.TP
+.B \-id=<uint>
+Dump the record from the IPI stream with the given type index.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-type=<uint>
+Dump the record from the TPI stream with the given type index.
+.UNINDENT
+.SS pdb2yaml
+.sp
+USAGE: \fBllvm\-pdbutil\fP pdb2yaml [\fIoptions\fP] <input PDB file>
+.SS Summary
+.SS Options
+.SS yaml2pdb
+.sp
+USAGE: \fBllvm\-pdbutil\fP yaml2pdb [\fIoptions\fP] <input YAML file>
+.SS Summary
+.sp
+Generate a PDB file from a YAML description. The YAML syntax is not described
+here. Instead, use \fI\%llvm\-pdbutil pdb2yaml\fP and
+examine the output for an example starting point.
+.SS Options
+.INDENT 0.0
+.TP
+.B \-pdb=<file\-name>
+.UNINDENT
+.sp
+Write the resulting PDB to the specified file.
+.SS merge
+.sp
+USAGE: \fBllvm\-pdbutil\fP merge [\fIoptions\fP] <input PDB file 1> <input PDB file 2>
+.SS Summary
+.sp
+Merge two PDB files into a single file.
+.SS Options
+.INDENT 0.0
+.TP
+.B \-pdb=<file\-name>
+.UNINDENT
+.sp
+Write the resulting PDB to the specified file.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-profdata/Makefile b/usr.bin/clang/llvm-profdata/Makefile
new file mode 100644
index 000000000000..aba60836da5d
--- /dev/null
+++ b/usr.bin/clang/llvm-profdata/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llvm-profdata
+
+SRCDIR= llvm/tools/llvm-profdata
+SRCS+= llvm-profdata-driver.cpp
+SRCS+= llvm-profdata.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-profdata/Makefile.depend b/usr.bin/clang/llvm-profdata/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-profdata/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-profdata/llvm-profdata-driver.cpp b/usr.bin/clang/llvm-profdata/llvm-profdata-driver.cpp
new file mode 100644
index 000000000000..7ec0c97fbf04
--- /dev/null
+++ b/usr.bin/clang/llvm-profdata/llvm-profdata-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_profdata_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_profdata_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-profdata/llvm-profdata.1 b/usr.bin/clang/llvm-profdata/llvm-profdata.1
new file mode 100644
index 000000000000..b537594b13d3
--- /dev/null
+++ b/usr.bin/clang/llvm-profdata/llvm-profdata.1
@@ -0,0 +1,466 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-PROFDATA" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-profdata \- Profile data tool
+.SH SYNOPSIS
+.sp
+\fBllvm\-profdata\fP \fIcommand\fP [\fIargs...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-profdata\fP tool is a small utility for working with profile
+data files.
+.SH COMMANDS
+.INDENT 0.0
+.IP \(bu 2
+\fI\%merge\fP
+.IP \(bu 2
+\fI\%show\fP
+.IP \(bu 2
+\fI\%overlap\fP
+.UNINDENT
+.SH MERGE
+.SS SYNOPSIS
+.sp
+\fBllvm\-profdata merge\fP [\fIoptions\fP] [\fIfilename...\fP]
+.SS DESCRIPTION
+.sp
+\fBllvm\-profdata merge\fP takes several profile data files
+generated by PGO instrumentation and merges them together into a single
+indexed profile data file.
+.sp
+By default profile data is merged without modification. This means that the
+relative importance of each input file is proportional to the number of samples
+or counts it contains. In general, the input from a longer training run will be
+interpreted as relatively more important than a shorter run. Depending on the
+nature of the training runs it may be useful to adjust the weight given to each
+input file by using the \fB\-weighted\-input\fP option.
+.sp
+Profiles passed in via \fB\-weighted\-input\fP, \fB\-input\-files\fP, or via positional
+arguments are processed once for each time they are seen.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output=<output>, \-o
+Specify the output file name. \fIOutput\fP cannot be \fB\-\fP as the resulting
+indexed profile data can\(aqt be written to standard output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-weighted\-input=<weight,filename>
+Specify an input file name along with a weight. The profile counts of the
+supplied \fBfilename\fP will be scaled (multiplied) by the supplied
+\fBweight\fP, where \fBweight\fP is a decimal integer >= 1.
+Input files specified without using this option are assigned a default
+weight of 1. Examples are shown below.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-input\-files=<path>, \-f
+Specify a file which contains a list of files to merge. The entries in this
+file are newline\-separated. Lines starting with \(aq#\(aq are skipped. Entries may
+be of the form <filename> or <weight>,<filename>.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-remapping\-file=<path>, \-r
+Specify a file which contains a remapping from symbol names in the input
+profile to the symbol names that should be used in the output profile. The
+file should consist of lines of the form \fB<input\-symbol> <output\-symbol>\fP\&.
+Blank lines and lines starting with \fB#\fP are skipped.
+.sp
+The \fI\%llvm\-cxxmap\fP tool can be used to generate the symbol
+remapping file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-instr (default)
+Specify that the input profile is an instrumentation\-based profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sample
+Specify that the input profile is a sample\-based profile.
+.sp
+The format of the generated file can be generated in one of three ways:
+.INDENT 7.0
+.TP
+.B \-\-binary (default)
+.UNINDENT
+.sp
+Emit the profile using a binary encoding. For instrumentation\-based profile
+the output format is the indexed binary format.
+.INDENT 7.0
+.TP
+.B \-\-extbinary
+.UNINDENT
+.sp
+Emit the profile using an extensible binary encoding. This option can only
+be used with sample\-based profile. The extensible binary encoding can be
+more compact with compression enabled and can be loaded faster than the
+default binary encoding.
+.INDENT 7.0
+.TP
+.B \-\-text
+.UNINDENT
+.sp
+Emit the profile in text mode. This option can also be used with both
+sample\-based and instrumentation\-based profile. When this option is used
+the profile will be dumped in the text format that is parsable by the profile
+reader.
+.INDENT 7.0
+.TP
+.B \-\-gcc
+.UNINDENT
+.sp
+Emit the profile using GCC\(aqs gcov format (Not yet supported).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sparse[=true|false]
+Do not emit function records with 0 execution count. Can only be used in
+conjunction with \-instr. Defaults to false, since it can inhibit compiler
+optimization during PGO.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-num\-threads=<N>, \-j
+Use N threads to perform profile merging. When N=0, llvm\-profdata auto\-detects
+an appropriate number of threads to use. This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-failure\-mode=[any|all]
+Set the failure mode. There are two options: \(aqany\(aq causes the merge command to
+fail if any profiles are invalid, and \(aqall\(aq causes the merge command to fail
+only if all profiles are invalid. If \(aqall\(aq is set, information from any
+invalid profiles is excluded from the final merged product. The default
+failure mode is \(aqany\(aq.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-prof\-sym\-list=<path>
+Specify a file which contains a list of symbols to generate profile symbol
+list in the profile. This option can only be used with sample\-based profile
+in extbinary format. The entries in this file are newline\-separated.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-compress\-all\-sections=[true|false]
+Compress all sections when writing the profile. This option can only be used
+with sample\-based profile in extbinary format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-use\-md5=[true|false]
+Use MD5 to represent string in name table when writing the profile.
+This option can only be used with sample\-based profile in extbinary format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-gen\-partial\-profile=[true|false]
+Mark the profile to be a partial profile which only provides partial profile
+coverage for the optimized target. This option can only be used with
+sample\-based profile in extbinary format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-supplement\-instr\-with\-sample=<file>
+Supplement an instrumentation profile with sample profile. The sample profile
+is the input of the flag. Output will be in instrumentation format (only works
+with \-instr).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-zero\-counter\-threshold=<float>
+For the function which is cold in instr profile but hot in sample profile, if
+the ratio of the number of zero counters divided by the total number of
+counters is above the threshold, the profile of the function will be regarded
+as being harmful for performance and will be dropped.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-instr\-prof\-cold\-threshold=<int>
+User specified cold threshold for instr profile which will override the cold
+threshold got from profile summary.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-suppl\-min\-size\-threshold=<int>
+If the size of a function is smaller than the threshold, assume it can be
+inlined by PGO early inliner and it will not be adjusted based on sample
+profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-info=<path>
+Specify the executable or \fB\&.dSYM\fP that contains debug info for the raw profile.
+When \fB\-debug\-info\-correlate\fP was used for instrumentation, use this option
+to correlate the raw profile.
+.UNINDENT
+.SS EXAMPLES
+.SS Basic Usage
+.sp
+Merge three profiles:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+llvm\-profdata merge foo.profdata bar.profdata baz.profdata \-output merged.profdata
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Weighted Input
+.sp
+The input file \fBfoo.profdata\fP is especially important, multiply its counts by 10:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+llvm\-profdata merge \-\-weighted\-input=10,foo.profdata bar.profdata baz.profdata \-\-output merged.profdata
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Exactly equivalent to the previous invocation (explicit form; useful for programmatic invocation):
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+llvm\-profdata merge \-\-weighted\-input=10,foo.profdata \-\-weighted\-input=1,bar.profdata \-\-weighted\-input=1,baz.profdata \-\-output merged.profdata
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SHOW
+.SS SYNOPSIS
+.sp
+\fBllvm\-profdata show\fP [\fIoptions\fP] [\fIfilename\fP]
+.SS DESCRIPTION
+.sp
+\fBllvm\-profdata show\fP takes a profile data file and displays the
+information about the profile counters for this file and
+for any of the specified function(s).
+.sp
+If \fIfilename\fP is omitted or is \fB\-\fP, then \fBllvm\-profdata show\fP reads its
+input from standard input.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-all\-functions
+Print details for every function.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-binary\-ids
+Print embedded binary ids in a profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-counts
+Print the counter values for the displayed functions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-format=<text|json|yaml>
+Emit output in the selected format if supported by the provided profile type.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-function=<string>
+Print details for a function if the function\(aqs name contains the given string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output=<output>, \-o
+Specify the output file name. If \fIoutput\fP is \fB\-\fP or it isn\(aqt specified,
+then the output is sent to standard output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-instr (default)
+Specify that the input profile is an instrumentation\-based profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-text
+Instruct the profile dumper to show profile counts in the text format of the
+instrumentation\-based profile data representation. By default, the profile
+information is dumped in a more human readable form (also in text) with
+annotations.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-topn=<n>
+Instruct the profile dumper to show the top \fBn\fP functions with the
+hottest basic blocks in the summary section. By default, the topn functions
+are not dumped.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sample
+Specify that the input profile is a sample\-based profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-memop\-sizes
+Show the profiled sizes of the memory intrinsic calls for shown functions.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-value\-cutoff=<n>
+Show only those functions whose max count values are greater or equal to \fBn\fP\&.
+By default, the value\-cutoff is set to 0.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-list\-below\-cutoff
+Only output names of functions whose max count value are below the cutoff
+value.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-profile\-version
+Print profile version.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-showcs
+Only show context sensitive profile counts. The default is to filter all
+context sensitive profile counts.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-prof\-sym\-list=[true|false]
+Show profile symbol list if it exists in the profile. This option is only
+meaningful for sample\-based profile in extbinary format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-show\-sec\-info\-only=[true|false]
+Show basic information about each section in the profile. This option is
+only meaningful for sample\-based profile in extbinary format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-info=<path>
+Specify the executable or \fB\&.dSYM\fP that contains debug info for the raw profile.
+When \fB\-debug\-info\-correlate\fP was used for instrumentation, use this option
+to show the correlated functions from the raw profile.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-covered
+Show only the functions that have been executed, i.e., functions with non\-zero
+counts.
+.UNINDENT
+.SH OVERLAP
+.SS SYNOPSIS
+.sp
+\fBllvm\-profdata overlap\fP [\fIoptions\fP] [\fIbase profile file\fP] [\fItest profile file\fP]
+.SS DESCRIPTION
+.sp
+\fBllvm\-profdata overlap\fP takes two profile data files and displays the
+\fIoverlap\fP of counter distribution between the whole files and between any of the
+specified functions.
+.sp
+In this command, \fIoverlap\fP is defined as follows:
+Suppose \fIbase profile file\fP has the following counts:
+{c1_1, c1_2, ..., c1_n, c1_u_1, c2_u_2, ..., c2_u_s},
+and \fItest profile file\fP has
+{c2_1, c2_2, ..., c2_n, c2_v_1, c2_v_2, ..., c2_v_t}.
+Here c{1|2}_i (i = 1 .. n) are matched counters and c1_u_i (i = 1 .. s) and
+c2_v_i (i = 1 .. v) are unmatched counters (or counters only existing in)
+\fIbase profile file\fP and \fItest profile file\fP, respectively.
+Let sum_1 = c1_1 + c1_2 + ... + c1_n + c1_u_1 + c2_u_2 + ... + c2_u_s, and
+sum_2 = c2_1 + c2_2 + ... + c2_n + c2_v_1 + c2_v_2 + ... + c2_v_t.
+\fIoverlap\fP = min(c1_1/sum_1, c2_1/sum_2) + min(c1_2/sum_1, c2_2/sum_2) + ...
++ min(c1_n/sum_1, c2_n/sum_2).
+.sp
+The result overlap distribution is a percentage number, ranging from 0.0% to
+100.0%, where 0.0% means there is no overlap and 100.0% means a perfect
+overlap.
+.sp
+Here is an example, if \fIbase profile file\fP has counts of {400, 600}, and
+\fItest profile file\fP has matched counts of {60000, 40000}. The \fIoverlap\fP is 80%.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-function=<string>
+Print details for a function if the function\(aqs name contains the given string.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output=<output>, \-o
+Specify the output file name. If \fIoutput\fP is \fB\-\fP or it isn\(aqt specified,
+then the output is sent to standard output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-value\-cutoff=<n>
+Show only those functions whose max count values are greater or equal to \fBn\fP\&.
+By default, the value\-cutoff is set to max of unsigned long long.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-cs
+Only show overlap for the context sensitive profile counts. The default is to show
+non\-context sensitive profile counts.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-profdata\fP returns 1 if the command is omitted or is invalid,
+if it cannot read input files, or if there is a mismatch between their data.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-readobj/Makefile b/usr.bin/clang/llvm-readobj/Makefile
new file mode 100644
index 000000000000..f532358ea79e
--- /dev/null
+++ b/usr.bin/clang/llvm-readobj/Makefile
@@ -0,0 +1,43 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-readobj
+MAN= llvm-readobj.1 llvm-readelf.1
+
+SRCDIR= llvm/tools/llvm-readobj
+SRCS+= ARMWinEHPrinter.cpp
+SRCS+= COFFDumper.cpp
+SRCS+= COFFImportDumper.cpp
+SRCS+= ELFDumper.cpp
+SRCS+= MachODumper.cpp
+SRCS+= ObjDumper.cpp
+SRCS+= WasmDumper.cpp
+SRCS+= Win64EHDumper.cpp
+SRCS+= WindowsResourceDumper.cpp
+SRCS+= XCOFFDumper.cpp
+SRCS+= llvm-readobj-driver.cpp
+SRCS+= llvm-readobj.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LINKS+= ${BINDIR}/llvm-readobj ${BINDIR}/llvm-readelf
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-readelf ${BINDIR}/readelf
+MLINKS+= llvm-readelf.1 readelf.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-readobj/llvm-readelf.1 b/usr.bin/clang/llvm-readobj/llvm-readelf.1
new file mode 100644
index 000000000000..19fc547d747f
--- /dev/null
+++ b/usr.bin/clang/llvm-readobj/llvm-readelf.1
@@ -0,0 +1,291 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-READELF" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-readelf \- GNU-style LLVM Object Reader
+.SH SYNOPSIS
+.sp
+\fBllvm\-readelf\fP [\fIoptions\fP] [\fIinput...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-readelf\fP tool displays low\-level format\-specific information
+about one or more object files.
+.sp
+If \fBinput\fP is \(dq\fB\-\fP\(dq, \fBllvm\-readelf\fP reads from standard
+input. Otherwise, it will read from the specified \fBfilenames\fP\&.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-all, \-a
+Equivalent to specifying all the main display options relevant to the file
+format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-addrsig
+Display the address\-significance table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-arch\-specific, \-A
+Display architecture\-specific information, e.g. the ARM attributes section on ARM.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-bb\-addr\-map
+Display the contents of the basic block address map section(s), which contain the
+address of each function, along with the relative offset of each basic block.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-demangle, \-C
+Display demangled symbol names in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dependent\-libraries
+Display the dependent libraries section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyn\-relocations
+Display the dynamic relocation entries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyn\-symbols, \-\-dyn\-syms
+Display the dynamic symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dynamic\-table, \-\-dynamic, \-d
+Display the dynamic table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-cg\-profile
+Display the callgraph profile section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-histogram, \-I
+Display a bucket list histogram for dynamic symbol hash tables.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-elf\-linker\-options
+Display the linker options section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-elf\-output\-style=<value>
+Format ELF information in the specified style. Valid options are \fBLLVM\fP,
+\fBGNU\fP, and \fBJSON\fP\&. \fBLLVM\fP output is an expanded and structured format.
+\fBGNU\fP (the default) output mimics the equivalent GNU \fBreadelf\fP
+output. \fBJSON\fP is JSON formatted output intended for machine consumption.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-groups, \-g
+Display section groups.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-expand\-relocs
+When used with \fI\%\-\-relocations\fP, display each relocation in an expanded
+multi\-line format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-file\-header, \-h
+Display file headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-gnu\-hash\-table
+Display the GNU hash table for dynamic symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hash\-symbols
+Display the expanded hash table with dynamic symbol data.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hash\-table
+Display the hash table for dynamic symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-headers, \-e
+Equivalent to setting: \fI\%\-\-file\-header\fP, \fI\%\-\-program\-headers\fP,
+and \fI\%\-\-sections\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Display a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hex\-dump=<section[,section,...]>, \-x
+Display the specified section(s) as hexadecimal bytes. \fBsection\fP may be a
+section index or section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-needed\-libs
+Display the needed libraries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-demangle
+Do not display demangled symbol names in the output. On by default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-notes, \-n
+Display all notes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-pretty\-print
+When used with \fI\%\-\-elf\-output\-style\fP, JSON output will be formatted in
+a more readable format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-program\-headers, \-\-segments, \-l
+Display the program headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-raw\-relr
+Do not decode relocations in RELR relocation sections when displaying them.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-relocations, \-\-relocs, \-r
+Display the relocation entries in the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sections, \-\-section\-headers, \-S
+Display all sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-data
+When used with \fI\%\-\-sections\fP, display section data for each section
+shown. This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-details, \-t
+Display all section details. Used as an alternative to \fI\%\-\-sections\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-mapping
+Display the section to segment mapping.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-relocations
+When used with \fI\%\-\-sections\fP, display relocations for each section
+shown. This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-symbols
+When used with \fI\%\-\-sections\fP, display symbols for each section shown.
+This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stackmap
+Display contents of the stackmap section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stack\-sizes
+Display the contents of the stack sizes section(s), i.e. pairs of function
+names and the size of their stack frames. Currently only implemented for GNU
+style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-string\-dump=<section[,section,...]>, \-p
+Display the specified section(s) as a list of strings. \fBsection\fP may be a
+section index or section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-symbols, \-\-syms, \-s
+Display the symbol table. Also display the dynamic symbol table when using GNU output style for ELF.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-unwind, \-u
+Display unwind information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-readelf\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version\-info, \-V
+Display version sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-wide, \-W
+Ignored for GNU readelf compatibility. The output is already similar to when using \-W with GNU readelf.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-readelf\fP returns 0 under normal operation. It returns a non\-zero
+exit code if there were any errors.
+.SH SEE ALSO
+.sp
+\fBllvm\-nm(1)\fP, \fBllvm\-objdump(1)\fP, \fBllvm\-readobj(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-readobj/llvm-readobj-driver.cpp b/usr.bin/clang/llvm-readobj/llvm-readobj-driver.cpp
new file mode 100644
index 000000000000..3152b9ffcd27
--- /dev/null
+++ b/usr.bin/clang/llvm-readobj/llvm-readobj-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_readobj_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_readobj_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-readobj/llvm-readobj.1 b/usr.bin/clang/llvm-readobj/llvm-readobj.1
new file mode 100644
index 000000000000..2e083b92026b
--- /dev/null
+++ b/usr.bin/clang/llvm-readobj/llvm-readobj.1
@@ -0,0 +1,445 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-READOBJ" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-readobj \- LLVM Object Reader
+.SH SYNOPSIS
+.sp
+\fBllvm\-readobj\fP [\fIoptions\fP] [\fIinput...\fP]
+.SH DESCRIPTION
+.sp
+The \fBllvm\-readobj\fP tool displays low\-level format\-specific information
+about one or more object files.
+.sp
+If \fBinput\fP is \(dq\fB\-\fP\(dq, \fBllvm\-readobj\fP reads from standard
+input. Otherwise, it will read from the specified \fBfilenames\fP\&.
+.SH DIFFERENCES TO LLVM-READELF
+.sp
+\fBllvm\-readelf\fP is an alias for the \fBllvm\-readobj\fP tool with a
+slightly different command\-line interface and output that is GNU compatible.
+Following is a list of differences between \fBllvm\-readelf\fP and
+\fBllvm\-readobj\fP:
+.INDENT 0.0
+.IP \(bu 2
+\fBllvm\-readelf\fP uses \fIGNU\fP for the \fI\%\-\-elf\-output\-style\fP option
+by default. \fBllvm\-readobj\fP uses \fILLVM\fP\&.
+.IP \(bu 2
+\fBllvm\-readelf\fP allows single\-letter grouped flags (e.g.
+\fBllvm\-readelf \-SW\fP is the same as \fBllvm\-readelf \-S \-W\fP).
+\fBllvm\-readobj\fP does not allow grouping.
+.IP \(bu 2
+\fBllvm\-readelf\fP provides \fI\%\-s\fP as an alias for
+\fI\%\-\-symbols\fP, for GNU \fBreadelf\fP compatibility, whereas it is
+an alias for \fI\%\-\-section\-headers\fP in \fBllvm\-readobj\fP\&.
+.IP \(bu 2
+\fBllvm\-readobj\fP provides \fB\-t\fP as an alias for \fI\%\-\-symbols\fP\&.
+\fBllvm\-readelf\fP does not.
+.IP \(bu 2
+\fBllvm\-readobj\fP provides \fB\-\-sr\fP, \fB\-\-sd\fP, \fB\-\-st\fP and \fB\-\-dt\fP as
+aliases for \fI\%\-\-section\-relocations\fP, \fI\%\-\-section\-data\fP,
+\fI\%\-\-section\-symbols\fP and \fI\%\-\-dyn\-symbols\fP respectively.
+\fBllvm\-readelf\fP does not provide these aliases, to avoid conflicting
+with grouped flags.
+.UNINDENT
+.SH GENERAL AND MULTI-FORMAT OPTIONS
+.sp
+These options are applicable to more than one file format, or are unrelated to
+file formats.
+.INDENT 0.0
+.TP
+.B \-\-all
+Equivalent to specifying all the main display options relevant to the file
+format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-addrsig
+Display the address\-significance table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-expand\-relocs
+When used with \fI\%\-\-relocs\fP, display each relocation in an expanded
+multi\-line format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-file\-header, \-h
+Display file headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-headers, \-e
+Equivalent to setting: \fI\%\-\-file\-header\fP, \fI\%\-\-program\-headers\fP,
+and \fI\%\-\-sections\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help
+Display a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hex\-dump=<section[,section,...]>, \-x
+Display the specified section(s) as hexadecimal bytes. \fBsection\fP may be a
+section index or section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-needed\-libs
+Display the needed libraries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-relocations, \-\-relocs, \-r
+Display the relocation entries in the file.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sections, \-\-section\-headers, \-S
+Display all sections.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-data, \-\-sd
+When used with \fI\%\-\-sections\fP, display section data for each section
+shown. This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-relocations, \-\-sr
+When used with \fI\%\-\-sections\fP, display relocations for each section
+shown. This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-symbols, \-\-st
+When used with \fI\%\-\-sections\fP, display symbols for each section shown.
+This option has no effect for GNU style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-sort\-symbols=<sort_key[,sort_key]>
+Specify the keys to sort symbols before displaying symtab.
+Valid values for sort_key are \fBname\fP and \fBtype\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stackmap
+Display contents of the stackmap section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-string\-dump=<section[,section,...]>, \-p
+Display the specified section(s) as a list of strings. \fBsection\fP may be a
+section index or section name.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-string\-table
+Display contents of the string table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-symbols, \-\-syms, \-s
+Display the symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-unwind, \-u
+Display unwind information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-readobj\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH ELF SPECIFIC OPTIONS
+.sp
+The following options are implemented only for the ELF file format.
+.INDENT 0.0
+.TP
+.B \-\-arch\-specific, \-A
+Display architecture\-specific information, e.g. the ARM attributes section on ARM.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-bb\-addr\-map
+Display the contents of the basic block address map section(s), which contain the
+address of each function, along with the relative offset of each basic block.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-demangle, \-C
+Display demangled symbol names in the output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dependent\-libraries
+Display the dependent libraries section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyn\-relocations
+Display the dynamic relocation entries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dyn\-symbols, \-\-dyn\-syms, \-\-dt
+Display the dynamic symbol table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dynamic\-table, \-\-dynamic, \-d
+Display the dynamic table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-cg\-profile
+Display the callgraph profile section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-histogram, \-I
+Display a bucket list histogram for dynamic symbol hash tables.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-elf\-linker\-options
+Display the linker options section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-elf\-output\-style=<value>
+Format ELF information in the specified style. Valid options are \fBLLVM\fP,
+\fBGNU\fP, and \fBJSON\fP\&. \fBLLVM\fP output (the default) is an expanded and
+structured format. \fBGNU\fP output mimics the equivalent GNU \fBreadelf\fP
+output. \fBJSON\fP is JSON formatted output intended for machine consumption.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-groups, \-g
+Display section groups.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-gnu\-hash\-table
+Display the GNU hash table for dynamic symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hash\-symbols
+Display the expanded hash table with dynamic symbol data.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-hash\-table
+Display the hash table for dynamic symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-notes, \-n
+Display all notes.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-pretty\-print
+When used with \fI\%\-\-elf\-output\-style\fP, JSON output will be formatted in
+a more readable format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-program\-headers, \-\-segments, \-l
+Display the program headers.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-raw\-relr
+Do not decode relocations in RELR relocation sections when displaying them.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-section\-mapping
+Display the section to segment mapping.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-stack\-sizes
+Display the contents of the stack sizes section(s), i.e. pairs of function
+names and the size of their stack frames. Currently only implemented for GNU
+style output.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version\-info, \-V
+Display version sections.
+.UNINDENT
+.SH MACH-O SPECIFIC OPTIONS
+.sp
+The following options are implemented only for the Mach\-O file format.
+.INDENT 0.0
+.TP
+.B \-\-macho\-data\-in\-code
+Display the Data in Code command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-macho\-dsymtab
+Display the Dsymtab command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-macho\-indirect\-symbols
+Display indirect symbols.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-macho\-linker\-options
+Display the Mach\-O\-specific linker options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-macho\-segment
+Display the Segment command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-macho\-version\-min
+Display the version min command.
+.UNINDENT
+.SH PE/COFF SPECIFIC OPTIONS
+.sp
+The following options are implemented only for the PE/COFF file format.
+.INDENT 0.0
+.TP
+.B \-\-codeview
+Display CodeView debug information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-codeview\-ghash
+Enable global hashing for CodeView type stream de\-duplication.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-codeview\-merged\-types
+Display the merged CodeView type stream.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-codeview\-subsection\-bytes
+Dump raw contents of CodeView debug sections and records.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-basereloc
+Display the .reloc section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-debug\-directory
+Display the debug directory.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-tls\-directory
+Display the TLS directory.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-directives
+Display the .drectve section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-exports
+Display the export table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-imports
+Display the import table.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-load\-config
+Display the load config.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-coff\-resources
+Display the .rsrc section.
+.UNINDENT
+.SH XCOFF SPECIFIC OPTIONS
+.sp
+The following options are implemented only for the XCOFF file format.
+.INDENT 0.0
+.TP
+.B \-\-auxiliary\-header
+Display XCOFF Auxiliary header.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-exception\-section
+Display XCOFF exception section entries.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-loader\-section\-header
+Display XCOFF loader section header.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-loader\-section\-symbols
+Display symbol table of loader section.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-loader\-section\-relocations
+Display relocation entries of loader section.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-readobj\fP returns 0 under normal operation. It returns a non\-zero
+exit code if there were any errors.
+.SH SEE ALSO
+.sp
+\fBllvm\-nm(1)\fP, \fBllvm\-objdump(1)\fP, \fBllvm\-readelf(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-rtdyld/Makefile b/usr.bin/clang/llvm-rtdyld/Makefile
new file mode 100644
index 000000000000..66f491324172
--- /dev/null
+++ b/usr.bin/clang/llvm-rtdyld/Makefile
@@ -0,0 +1,7 @@
+PROG_CXX= llvm-rtdyld
+MAN=
+
+SRCDIR= llvm/tools/llvm-rtdyld
+SRCS+= llvm-rtdyld.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-rtdyld/Makefile.depend b/usr.bin/clang/llvm-rtdyld/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-rtdyld/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-size/Makefile b/usr.bin/clang/llvm-size/Makefile
new file mode 100644
index 000000000000..2860a0069538
--- /dev/null
+++ b/usr.bin/clang/llvm-size/Makefile
@@ -0,0 +1,30 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-size
+
+SRCDIR= llvm/tools/llvm-size
+SRCS+= llvm-size-driver.cpp
+SRCS+= llvm-size.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-size ${BINDIR}/size
+MLINKS+= llvm-size.1 size.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-size/llvm-size-driver.cpp b/usr.bin/clang/llvm-size/llvm-size-driver.cpp
new file mode 100644
index 000000000000..8ab1c282b5d7
--- /dev/null
+++ b/usr.bin/clang/llvm-size/llvm-size-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_size_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_size_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-size/llvm-size.1 b/usr.bin/clang/llvm-size/llvm-size.1
new file mode 100644
index 000000000000..d524ef504d49
--- /dev/null
+++ b/usr.bin/clang/llvm-size/llvm-size.1
@@ -0,0 +1,269 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-SIZE" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-size \- print size information
+.SH SYNOPSIS
+.sp
+\fBllvm\-size\fP [\fIoptions\fP] [\fIinput...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-size\fP is a tool that prints size information for binary files.
+It is intended to be a drop\-in replacement for GNU\(aqs \fBsize\fP\&.
+.sp
+The tool prints size information for each \fBinput\fP specified. If no input is
+specified, the program prints size information for \fBa.out\fP\&. If \(dq\fB\-\fP\(dq is
+specified as an input file, \fBllvm\-size\fP reads a file from the standard
+input stream. If an input is an archive, size information will be displayed for
+all its members.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-A
+Equivalent to \fI\%\-\-format\fP with a value of \fBsysv\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-arch=<arch>
+Architecture(s) from Mach\-O universal binaries to display information for.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-B
+Equivalent to \fI\%\-\-format\fP with a value of \fBberkeley\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-common
+Include ELF common symbol sizes in bss size for \fBberkeley\fP output format, or
+as a separate section entry for \fBsysv\fP output. If not specified, these
+symbols are ignored.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-d
+Equivalent to \fI\%\-\-radix\fP with a value of \fB10\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-l
+Display verbose address and offset information for segments and sections in
+Mach\-O files in \fBdarwin\fP format.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-format=<format>
+Set the output format to the \fB<format>\fP specified. Available \fB<format>\fP
+options are \fBberkeley\fP (the default), \fBsysv\fP and \fBdarwin\fP\&.
+.sp
+Berkeley output summarises text, data and bss sizes in each file, as shown
+below for a typical pair of ELF files:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-format=berkeley test.o test2.o
+ text data bss dec hex filename
+ 182 16 5 203 cb test.elf
+ 82 8 1 91 5b test2.o
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+For Mach\-O files, the output format is slightly different:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-format=berkeley macho.obj macho2.obj
+__TEXT __DATA __OBJC others dec hex
+4 8 0 0 12 c macho.obj
+16 32 0 0 48 30 macho2.obj
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Sysv output displays size and address information for most sections, with each
+file being listed separately:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-format=sysv test.elf test2.o
+ test.elf :
+ section size addr
+ .eh_frame 92 2097496
+ .text 90 2101248
+ .data 16 2105344
+ .bss 5 2105360
+ .comment 209 0
+ Total 412
+
+ test2.o :
+ section size addr
+ .text 26 0
+ .data 8 0
+ .bss 1 0
+ .comment 106 0
+ .note.GNU\-stack 0 0
+ .eh_frame 56 0
+ .llvm_addrsig 2 0
+ Total 199
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBdarwin\fP format only affects Mach\-O input files. If an input of a different
+file format is specified, \fBllvm\-size\fP falls back to \fBberkeley\fP
+format. When producing \fBdarwin\fP format, the tool displays information about
+segments and sections:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-format=darwin macho.obj macho2.obj
+ macho.obj:
+ Segment : 12
+ Section (__TEXT, __text): 4
+ Section (__DATA, __data): 8
+ total 12
+ total 12
+ macho2.obj:
+ Segment : 48
+ Section (__TEXT, __text): 16
+ Section (__DATA, __data): 32
+ total 48
+ total 48
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Display a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-m
+Equivalent to \fI\%\-\-format\fP with a value of \fBdarwin\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o
+Equivalent to \fI\%\-\-radix\fP with a value of \fB8\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-radix=<value>
+Display size information in the specified radix. Permitted values are \fB8\fP,
+\fB10\fP (the default) and \fB16\fP for octal, decimal and hexadecimal output
+respectively.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-radix=8 test.o
+ text data bss oct hex filename
+ 0152 04 04 162 72 test.o
+
+$ llvm\-size \-\-radix=10 test.o
+ text data bss dec hex filename
+ 106 4 4 114 72 test.o
+
+$ llvm\-size \-\-radix=16 test.o
+ text data bss dec hex filename
+ 0x6a 0x4 0x4 114 72 test.o
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-totals, \-t
+Applies only to \fBberkeley\fP output format. Display the totals for all listed
+fields, in addition to the individual file listings.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-size \-\-totals test.elf test2.o
+ text data bss dec hex filename
+ 182 16 5 203 cb test.elf
+ 82 8 1 91 5b test2.o
+ 264 24 6 294 126 (TOTALS)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-size\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-x
+Equivalent to \fI\%\-\-radix\fP with a value of \fB16\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fB<FILE>\fP\&.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-size\fP exits with a non\-zero exit code if there is an error.
+Otherwise, it exits with code 0.
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/labels/tools:llvm\-size/\fP>.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-strings/Makefile b/usr.bin/clang/llvm-strings/Makefile
new file mode 100644
index 000000000000..f01a012b0cb9
--- /dev/null
+++ b/usr.bin/clang/llvm-strings/Makefile
@@ -0,0 +1,29 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-strings
+
+SRCDIR= llvm/tools/llvm-strings
+SRCS+= llvm-strings.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-strings ${BINDIR}/strings
+MLINKS+= llvm-strings.1 strings.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-strings/llvm-strings.1 b/usr.bin/clang/llvm-strings/llvm-strings.1
new file mode 100644
index 000000000000..bde173d10d49
--- /dev/null
+++ b/usr.bin/clang/llvm-strings/llvm-strings.1
@@ -0,0 +1,173 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-STRINGS" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-strings \- print strings
+.SH SYNOPSIS
+.sp
+\fBllvm\-strings\fP [\fIoptions\fP] [\fIinput...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-strings\fP is a tool intended as a drop\-in replacement for GNU\(aqs
+\fBstrings\fP, which looks for printable strings in files and writes them
+to the standard output stream. A printable string is any sequence of four (by
+default) or more printable ASCII characters. The end of the file, or any other
+byte, terminates the current sequence.
+.sp
+\fBllvm\-strings\fP looks for strings in each \fBinput\fP file specified.
+Unlike GNU \fBstrings\fP it looks in the entire input file, regardless of
+file format, rather than restricting the search to certain sections of object
+files. If \(dq\fB\-\fP\(dq is specified as an \fBinput\fP, or no \fBinput\fP is specified,
+the program reads from the standard input stream.
+.SH EXAMPLE
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ cat input.txt
+bars
+foo
+wibble blob
+$ llvm\-strings input.txt
+bars
+wibble blob
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-all, \-a
+Silently ignored. Present for GNU \fBstrings\fP compatibility.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-bytes=<length>, \-n
+Set the minimum number of printable ASCII characters required for a sequence of
+bytes to be considered a string. The default value is 4.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Display a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-file\-name, \-f
+Display the name of the containing file before each string.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-strings \-\-print\-file\-name test.o test.elf
+test.o: _Z5hellov
+test.o: some_bss
+test.o: test.cpp
+test.o: main
+test.elf: test.cpp
+test.elf: test2.cpp
+test.elf: _Z5hellov
+test.elf: main
+test.elf: some_bss
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-radix=<radix>, \-t
+Display the offset within the file of each string, before the string and using
+the specified radix. Valid \fB<radix>\fP values are \fBo\fP, \fBd\fP and \fBx\fP for
+octal, decimal and hexadecimal respectively.
+.sp
+Example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-strings \-\-radix=o test.o
+ 1054 _Z5hellov
+ 1066 .rela.text
+ 1101 .comment
+ 1112 some_bss
+ 1123 .bss
+ 1130 test.cpp
+ 1141 main
+$ llvm\-strings \-\-radix=d test.o
+ 556 _Z5hellov
+ 566 .rela.text
+ 577 .comment
+ 586 some_bss
+ 595 .bss
+ 600 test.cpp
+ 609 main
+$ llvm\-strings \-t x test.o
+ 22c _Z5hellov
+ 236 .rela.text
+ 241 .comment
+ 24a some_bss
+ 253 .bss
+ 258 test.cpp
+ 261 main
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version
+Display the version of the \fBllvm\-strings\fP executable.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fB<FILE>\fP\&.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-strings\fP exits with a non\-zero exit code if there is an error.
+Otherwise, it exits with code 0.
+.SH BUGS
+.sp
+To report bugs, please visit <\fI\%https://github.com/llvm/llvm\-project/labels/tools:llvm\-strings/\fP>.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-symbolizer/Makefile b/usr.bin/clang/llvm-symbolizer/Makefile
new file mode 100644
index 000000000000..c45300c92a90
--- /dev/null
+++ b/usr.bin/clang/llvm-symbolizer/Makefile
@@ -0,0 +1,33 @@
+.include <src.opts.mk>
+
+PROG_CXX= llvm-symbolizer
+MAN= llvm-symbolizer.1 llvm-addr2line.1
+
+SRCDIR= llvm/tools/llvm-symbolizer
+SRCS+= llvm-symbolizer-driver.cpp
+SRCS+= llvm-symbolizer.cpp
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${.OBJDIR}
+
+INCFILE= Opts.inc
+TDFILE= ${LLVM_BASE}/${SRCDIR}/Opts.td
+GENOPT= -gen-opt-parser-defs
+${INCFILE}: ${TDFILE}
+ ${LLVM_TBLGEN} ${GENOPT} -I ${LLVM_SRCS}/include -d ${.TARGET:C/$/.d/} \
+ -o ${.TARGET} ${TDFILE}
+TGHDRS+= ${INCFILE}
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+
+LINKS+= ${BINDIR}/llvm-symbolizer ${BINDIR}/llvm-addr2line
+
+.if ${MK_LLVM_BINUTILS} != "no"
+LINKS+= ${BINDIR}/llvm-symbolizer ${BINDIR}/addr2line
+MLINKS+= llvm-addr2line.1 addr2line.1
+.endif
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-symbolizer/Makefile.depend b/usr.bin/clang/llvm-symbolizer/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-symbolizer/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-symbolizer/llvm-addr2line.1 b/usr.bin/clang/llvm-symbolizer/llvm-addr2line.1
new file mode 100644
index 000000000000..f4a568824c44
--- /dev/null
+++ b/usr.bin/clang/llvm-symbolizer/llvm-addr2line.1
@@ -0,0 +1,72 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-ADDR2LINE" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-addr2line \- a drop-in replacement for addr2line
+.SH SYNOPSIS
+.sp
+\fBllvm\-addr2line\fP [\fIoptions\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-addr2line\fP is an alias for the \fBllvm\-symbolizer(1)\fP
+tool with different defaults. The goal is to make it a drop\-in replacement for
+GNU\(aqs \fBaddr2line\fP\&.
+.sp
+Here are some of those differences:
+.INDENT 0.0
+.IP \(bu 2
+\fBllvm\-addr2line\fP interprets all addresses as hexadecimal and ignores an
+optional \fB0x\fP prefix, whereas \fBllvm\-symbolizer\fP attempts to determine
+the base from the literal\(aqs prefix and defaults to decimal if there is no
+prefix.
+.IP \(bu 2
+\fBllvm\-addr2line\fP defaults not to print function names. Use \fI\%\-f\fP to enable
+that.
+.IP \(bu 2
+\fBllvm\-addr2line\fP defaults not to demangle function names. Use \fI\%\-C\fP to
+switch the demangling on.
+.IP \(bu 2
+\fBllvm\-addr2line\fP defaults not to print inlined frames. Use \fI\%\-i\fP to show
+inlined frames for a source code location in an inlined function.
+.IP \(bu 2
+\fBllvm\-addr2line\fP uses \fI\%\-\-output\-style=GNU\fP by default.
+.IP \(bu 2
+\fBllvm\-addr2line\fP parses options from the environment variable
+\fBLLVM_ADDR2LINE_OPTS\fP instead of from \fBLLVM_SYMBOLIZER_OPTS\fP\&.
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBllvm\-symbolizer(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-symbolizer/llvm-symbolizer-driver.cpp b/usr.bin/clang/llvm-symbolizer/llvm-symbolizer-driver.cpp
new file mode 100644
index 000000000000..57873cd3862d
--- /dev/null
+++ b/usr.bin/clang/llvm-symbolizer/llvm-symbolizer-driver.cpp
@@ -0,0 +1,18 @@
+//===-- driver-template.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LLVMDriver.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/InitLLVM.h"
+
+int llvm_symbolizer_main(int argc, char **, const llvm::ToolContext &);
+
+int main(int argc, char **argv) {
+ llvm::InitLLVM X(argc, argv);
+ return llvm_symbolizer_main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/usr.bin/clang/llvm-symbolizer/llvm-symbolizer.1 b/usr.bin/clang/llvm-symbolizer/llvm-symbolizer.1
new file mode 100644
index 000000000000..40514158f32e
--- /dev/null
+++ b/usr.bin/clang/llvm-symbolizer/llvm-symbolizer.1
@@ -0,0 +1,660 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "LLVM-SYMBOLIZER" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+llvm-symbolizer \- convert addresses into source code locations
+.SH SYNOPSIS
+.sp
+\fBllvm\-symbolizer\fP [\fIoptions\fP] [\fIaddresses...\fP]
+.SH DESCRIPTION
+.sp
+\fBllvm\-symbolizer\fP reads input names and addresses from the command\-line
+and prints corresponding source code locations to standard output. It can also
+symbolize logs containing \fI\%Symbolizer Markup\fP via
+\fI\%\-\-filter\-markup\fP\&.
+.sp
+If no address is specified on the command\-line, it reads the addresses from
+standard input. If no input name is specified on the command\-line, but addresses
+are, or if at any time an input value is not recognized, the input is simply
+echoed to the output.
+.sp
+Input names can be specified together with the addresses either on standard
+input or as positional arguments on the command\-line. By default, input names
+are interpreted as object file paths. However, prefixing a name with
+\fBBUILDID:\fP states that it is a hex build ID rather than a path. This will look
+up the corresponding debug binary. For consistency, prefixing a name with
+\fBFILE:\fP explicitly states that it is an object file path (the default).
+.sp
+A positional argument or standard input value can be preceded by \(dqDATA\(dq or
+\(dqCODE\(dq to indicate that the address should be symbolized as data or executable
+code respectively. If neither is specified, \(dqCODE\(dq is assumed. DATA is
+symbolized as address and symbol size rather than line number.
+.sp
+\fBllvm\-symbolizer\fP parses options from the environment variable
+\fBLLVM_SYMBOLIZER_OPTS\fP after parsing options from the command line.
+\fBLLVM_SYMBOLIZER_OPTS\fP is primarily useful for supplementing the command\-line
+options when \fBllvm\-symbolizer\fP is invoked by another program or
+runtime.
+.SH EXAMPLES
+.sp
+All of the following examples use the following two source files as input. They
+use a mixture of C\-style and C++\-style linkage to illustrate how these names are
+printed differently (see \fI\%\-\-demangle\fP).
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+// test.h
+extern \(dqC\(dq inline int foz() {
+ return 1234;
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+// test.cpp
+#include \(dqtest.h\(dq
+int bar=42;
+
+int foo() {
+ return bar;
+}
+
+int baz() {
+ volatile int k = 42;
+ return foz() + k;
+}
+
+int main() {
+ return foo() + baz();
+}
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+These files are built as follows:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ clang \-g test.cpp \-o test.elf
+$ clang \-g \-O2 test.cpp \-o inlined.elf
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 1 \- addresses and object on command\-line:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=test.elf 0x4004d0 0x400490
+foz
+/tmp/test.h:1:0
+
+baz()
+/tmp/test.cpp:11:0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 2 \- addresses on standard input:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ cat addr.txt
+0x4004a0
+0x400490
+0x4004d0
+$ llvm\-symbolizer \-\-obj=test.elf < addr.txt
+main
+/tmp/test.cpp:15:0
+
+baz()
+/tmp/test.cpp:11:0
+
+foz
+/tmp/./test.h:1:0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 3 \- object specified with address:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \(dqtest.elf 0x400490\(dq \(dqFILE:inlined.elf 0x400480\(dq
+baz()
+/tmp/test.cpp:11:0
+
+foo()
+/tmp/test.cpp:8:10
+
+$ cat addr2.txt
+FILE:test.elf 0x4004a0
+inlined.elf 0x400480
+
+$ llvm\-symbolizer < addr2.txt
+main
+/tmp/test.cpp:15:0
+
+foo()
+/tmp/test.cpp:8:10
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 4 \- BUILDID and FILE prefixes:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \(dqFILE:test.elf 0x400490\(dq \(dqDATA BUILDID:123456789abcdef 0x601028\(dq
+baz()
+/tmp/test.cpp:11:0
+
+bar
+6295592 4
+
+$ cat addr3.txt
+FILE:test.elf 0x400490
+DATA BUILDID:123456789abcdef 0x601028
+
+$ llvm\-symbolizer < addr3.txt
+baz()
+/tmp/test.cpp:11:0
+
+bar
+6295592 4
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 5 \- CODE and DATA prefixes:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=test.elf \(dqCODE 0x400490\(dq \(dqDATA 0x601028\(dq
+baz()
+/tmp/test.cpp:11:0
+
+bar
+6295592 4
+
+$ cat addr4.txt
+CODE test.elf 0x4004a0
+DATA inlined.elf 0x601028
+
+$ llvm\-symbolizer < addr4.txt
+main
+/tmp/test.cpp:15:0
+
+bar
+6295592 4
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Example 6 \- path\-style options:
+.sp
+This example uses the same source file as above, but the source file\(aqs
+full path is /tmp/foo/test.cpp and is compiled as follows. The first case
+shows the default absolute path, the second \-\-basenames, and the third
+shows \-\-relativenames.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ pwd
+/tmp
+$ clang \-g foo/test.cpp \-o test.elf
+$ llvm\-symbolizer \-\-obj=test.elf 0x4004a0
+main
+/tmp/foo/test.cpp:15:0
+$ llvm\-symbolizer \-\-obj=test.elf 0x4004a0 \-\-basenames
+main
+test.cpp:15:0
+$ llvm\-symbolizer \-\-obj=test.elf 0x4004a0 \-\-relativenames
+main
+foo/test.cpp:15:0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-adjust\-vma <offset>
+Add the specified offset to object file addresses when performing lookups.
+This can be used to perform lookups as if the object were relocated by the
+offset.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-basenames, \-s
+Print just the file\(aqs name without any directories, instead of the
+absolute path.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-build\-id
+Look up the object using the given build ID, specified as a hexadecimal
+string. Mutually exclusive with \fI\%\-\-obj\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-color [=<always|auto|never>]
+Specify whether to use color in \fI\%\-\-filter\-markup\fP mode. Defaults to
+\fBauto\fP, which detects whether standard output supports color. Specifying
+\fB\-\-color\fP alone is equivalent to \fB\-\-color=always\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debug\-file\-directory <path>
+Provide a path to a directory with a \fI\&.build\-id\fP subdirectory to search for
+debug information for stripped binaries. Multiple instances of this argument
+are searched in the order given.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-debuginfod, \-\-no\-debuginfod
+Whether or not to try debuginfod lookups for debug binaries. Unless specified,
+debuginfod is only enabled if libcurl was compiled in (\fBLLVM_ENABLE_CURL\fP)
+and at least one server URL was provided by the environment variable
+\fBDEBUGINFOD_URLS\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-demangle, \-C
+Print demangled function names, if the names are mangled (e.g. the mangled
+name \fI_Z3bazv\fP becomes \fIbaz()\fP, whilst the non\-mangled name \fIfoz\fP is printed
+as is). Defaults to true.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dwp <path>
+Use the specified DWP file at \fB<path>\fP for any CUs that have split DWARF
+debug data.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-fallback\-debug\-path <path>
+When a separate file contains debug data, and is referenced by a GNU debug
+link section, use the specified path as a basis for locating the debug data if
+it cannot be found relative to the object.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-filter\-markup
+Reads from standard input, converts contained
+\fI\%Symbolizer Markup\fP into human\-readable form,
+and prints the results to standard output. The following markup elements are
+not yet supported:
+.INDENT 7.0
+.IP \(bu 2
+\fB{{{hexdict}}}\fP
+.IP \(bu 2
+\fB{{{dumpfile}}}\fP
+.UNINDENT
+.sp
+The \fB{{{bt}}}\fP backtrace element reports frames using the following syntax:
+.sp
+\fB#<number>[.<inline>] <address> <function> <file>:<line>:<col> (<module>+<relative address>)\fP
+.sp
+\fB<inline>\fP provides frame numbers for calls inlined into the caller
+coresponding to \fB<number>\fP\&. The inlined call numbers start at 1 and increase
+from callee to caller.
+.sp
+\fB<address>\fP is an address inside the call instruction to the function. The
+address may not be the start of the instruction. \fB<relative address>\fP is
+the corresponding virtual offset in the \fB<module>\fP loaded at that address.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-functions [=<none|short|linkage>], \-f
+Specify the way function names are printed (omit function name, print short
+function name, or print full linkage name, respectively). Defaults to
+\fBlinkage\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-help, \-h
+Show help and usage for this command.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-inlining, \-\-inlines, \-i
+If a source code location is in an inlined function, prints all the inlined
+frames. This is the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-inlines
+Don\(aqt print inlined frames.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-no\-demangle
+Don\(aqt print demangled function names.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-obj <path>, \-\-exe, \-e
+Path to object file to be symbolized. If \fB\-\fP is specified, read the object
+directly from the standard input stream. Mutually exclusive with
+\fI\%\-\-build\-id\fP\&.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-output\-style <LLVM|GNU|JSON>
+Specify the preferred output style. Defaults to \fBLLVM\fP\&. When the output
+style is set to \fBGNU\fP, the tool follows the style of GNU\(aqs \fBaddr2line\fP\&.
+The differences from the \fBLLVM\fP style are:
+.INDENT 7.0
+.IP \(bu 2
+Does not print the column of a source code location.
+.IP \(bu 2
+Does not add an empty line after the report for an address.
+.IP \(bu 2
+Does not replace the name of an inlined function with the name of the
+topmost caller when inlined frames are not shown.
+.IP \(bu 2
+Prints an address\(aqs debug\-data discriminator when it is non\-zero. One way to
+produce discriminators is to compile with clang\(aqs \-fdebug\-info\-for\-profiling.
+.UNINDENT
+.INDENT 7.0
+.TP
+.B \fBJSON\fP style provides a machine readable output in JSON. If addresses are
+supplied via stdin, the output JSON will be a series of individual objects.
+Otherwise, all results will be contained in a single array.
+.UNINDENT
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=inlined.elf 0x4004be 0x400486 \-p
+baz() at /tmp/test.cpp:11:18
+ (inlined by) main at /tmp/test.cpp:15:0
+
+foo() at /tmp/test.cpp:6:3
+
+$ llvm\-symbolizer \-\-output\-style=LLVM \-\-obj=inlined.elf 0x4004be 0x400486 \-p \-\-no\-inlines
+main at /tmp/test.cpp:11:18
+
+foo() at /tmp/test.cpp:6:3
+
+$ llvm\-symbolizer \-\-output\-style=GNU \-\-obj=inlined.elf 0x4004be 0x400486 \-p \-\-no\-inlines
+baz() at /tmp/test.cpp:11
+foo() at /tmp/test.cpp:6
+
+$ clang \-g \-fdebug\-info\-for\-profiling test.cpp \-o profiling.elf
+$ llvm\-symbolizer \-\-output\-style=GNU \-\-obj=profiling.elf 0x401167 \-p \-\-no\-inlines
+main at /tmp/test.cpp:15 (discriminator 2)
+
+$ llvm\-symbolizer \-\-output\-style=JSON \-\-obj=inlined.elf 0x4004be 0x400486 \-p
+[
+ {
+ \(dqAddress\(dq: \(dq0x4004be\(dq,
+ \(dqModuleName\(dq: \(dqinlined.elf\(dq,
+ \(dqSymbol\(dq: [
+ {
+ \(dqColumn\(dq: 18,
+ \(dqDiscriminator\(dq: 0,
+ \(dqFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqFunctionName\(dq: \(dqbaz()\(dq,
+ \(dqLine\(dq: 11,
+ \(dqStartAddress\(dq: \(dq0x4004be\(dq,
+ \(dqStartFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqStartLine\(dq: 9
+ },
+ {
+ \(dqColumn\(dq: 0,
+ \(dqDiscriminator\(dq: 0,
+ \(dqFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqFunctionName\(dq: \(dqmain\(dq,
+ \(dqLine\(dq: 15,
+ \(dqStartAddress\(dq: \(dq0x4004be\(dq,
+ \(dqStartFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqStartLine\(dq: 14
+ }
+ ]
+ },
+ {
+ \(dqAddress\(dq: \(dq0x400486\(dq,
+ \(dqModuleName\(dq: \(dqinlined.elf\(dq,
+ \(dqSymbol\(dq: [
+ {
+ \(dqColumn\(dq: 3,
+ \(dqDiscriminator\(dq: 0,
+ \(dqFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqFunctionName\(dq: \(dqfoo()\(dq,
+ \(dqLine\(dq: 6,
+ \(dqStartAddress\(dq: \(dq0x400486\(dq,
+ \(dqStartFileName\(dq: \(dq/tmp/test.cpp\(dq,
+ \(dqStartLine\(dq: 5
+ }
+ ]
+ }
+]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-pretty\-print, \-p
+Print human readable output. If \fI\%\-\-inlining\fP is specified, the
+enclosing scope is prefixed by (inlined by).
+For JSON output, the option will cause JSON to be indented and split over
+new lines. Otherwise, the JSON output will be printed in a compact form.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=inlined.elf 0x4004be \-\-inlining \-\-pretty\-print
+baz() at /tmp/test.cpp:11:18
+ (inlined by) main at /tmp/test.cpp:15:0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-address, \-\-addresses, \-a
+Print address before the source code location. Defaults to false.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=inlined.elf \-\-print\-address 0x4004be
+0x4004be
+baz()
+/tmp/test.cpp:11:18
+main
+/tmp/test.cpp:15:0
+
+$ llvm\-symbolizer \-\-obj=inlined.elf 0x4004be \-\-pretty\-print \-\-print\-address
+0x4004be: baz() at /tmp/test.cpp:11:18
+ (inlined by) main at /tmp/test.cpp:15:0
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-print\-source\-context\-lines <N>
+Print \fBN\fP lines of source context for each symbolized address.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=test.elf 0x400490 \-\-print\-source\-context\-lines=3
+baz()
+/tmp/test.cpp:11:0
+10 : volatile int k = 42;
+11 >: return foz() + k;
+12 : }
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-relativenames
+Print the file\(aqs path relative to the compilation directory, instead
+of the absolute path. If the command\-line to the compiler included
+the full path, this will be the same as the default.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-verbose
+Print verbose address, line and column information.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ llvm\-symbolizer \-\-obj=inlined.elf \-\-verbose 0x4004be
+baz()
+ Filename: /tmp/test.cpp
+ Function start filename: /tmp/test.cpp
+ Function start line: 9
+ Function start address: 0x4004b6
+ Line: 11
+ Column: 18
+main
+ Filename: /tmp/test.cpp
+ Function start filename: /tmp/test.cpp
+ Function start line: 14
+ Function start address: 0x4004b0
+ Line: 15
+ Column: 18
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-version, \-v
+Print version information for the tool.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B @<FILE>
+Read command\-line options from response file \fI<FILE>\fP\&.
+.UNINDENT
+.SH WINDOWS/PDB SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-dia
+Use the Windows DIA SDK for symbolization. If the DIA SDK is not found,
+llvm\-symbolizer will fall back to the native implementation.
+.UNINDENT
+.SH MACH-O SPECIFIC OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-default\-arch <arch>
+If a binary contains object files for multiple architectures (e.g. it is a
+Mach\-O universal binary), symbolize the object file for a given architecture.
+You can also specify the architecture by writing \fBbinary_name:arch_name\fP in
+the input (see example below). If the architecture is not specified in either
+way, the address will not be symbolized. Defaults to empty string.
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ cat addr.txt
+/tmp/mach_universal_binary:i386 0x1f84
+/tmp/mach_universal_binary:x86_64 0x100000f24
+
+$ llvm\-symbolizer < addr.txt
+_main
+/tmp/source_i386.cc:8
+
+_main
+/tmp/source_x86_64.cc:8
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-\-dsym\-hint <path/to/file.dSYM>
+If the debug info for a binary isn\(aqt present in the default location, look for
+the debug info at the .dSYM path provided via this option. This flag can be
+used multiple times.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+\fBllvm\-symbolizer\fP returns 0. Other exit codes imply an internal program
+error.
+.SH SEE ALSO
+.sp
+\fBllvm\-addr2line(1)\fP
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/clang/llvm-tblgen/Makefile b/usr.bin/clang/llvm-tblgen/Makefile
new file mode 100644
index 000000000000..2ff00b4e0545
--- /dev/null
+++ b/usr.bin/clang/llvm-tblgen/Makefile
@@ -0,0 +1,90 @@
+PROG_CXX= llvm-tblgen
+MAN=
+
+SRCDIR= llvm/utils/TableGen
+SRCS+= ARMTargetDefEmitter.cpp
+SRCS+= AsmMatcherEmitter.cpp
+SRCS+= AsmWriterEmitter.cpp
+SRCS+= Attributes.cpp
+SRCS+= Basic/CodeGenIntrinsics.cpp
+SRCS+= Basic/SDNodeProperties.cpp
+SRCS+= CTagsEmitter.cpp
+SRCS+= CallingConvEmitter.cpp
+SRCS+= CodeEmitterGen.cpp
+SRCS+= CodeGenMapTable.cpp
+SRCS+= Common/AsmWriterInst.cpp
+SRCS+= Common/CodeGenDAGPatterns.cpp
+SRCS+= Common/CodeGenHwModes.cpp
+SRCS+= Common/CodeGenInstAlias.cpp
+SRCS+= Common/CodeGenInstruction.cpp
+SRCS+= Common/CodeGenRegisters.cpp
+SRCS+= Common/CodeGenSchedule.cpp
+SRCS+= Common/CodeGenTarget.cpp
+SRCS+= Common/DAGISelMatcher.cpp
+SRCS+= Common/GlobalISel/CodeExpander.cpp
+SRCS+= Common/GlobalISel/CombinerUtils.cpp
+SRCS+= Common/GlobalISel/CXXPredicates.cpp
+SRCS+= Common/GlobalISel/GlobalISelMatchTable.cpp
+SRCS+= Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
+SRCS+= Common/GlobalISel/PatternParser.cpp
+SRCS+= Common/GlobalISel/Patterns.cpp
+SRCS+= Common/InfoByHwMode.cpp
+SRCS+= Common/OptEmitter.cpp
+SRCS+= Common/PredicateExpander.cpp
+SRCS+= Common/SubtargetFeatureInfo.cpp
+SRCS+= Common/Types.cpp
+SRCS+= Common/VarLenCodeEmitterGen.cpp
+SRCS+= CompressInstEmitter.cpp
+SRCS+= DAGISelEmitter.cpp
+SRCS+= DAGISelMatcherEmitter.cpp
+SRCS+= DAGISelMatcherGen.cpp
+SRCS+= DAGISelMatcherOpt.cpp
+SRCS+= DFAEmitter.cpp
+SRCS+= DFAPacketizerEmitter.cpp
+SRCS+= DXILEmitter.cpp
+SRCS+= DecoderEmitter.cpp
+SRCS+= DirectiveEmitter.cpp
+SRCS+= DisassemblerEmitter.cpp
+SRCS+= ExegesisEmitter.cpp
+SRCS+= FastISelEmitter.cpp
+SRCS+= GlobalISelCombinerEmitter.cpp
+SRCS+= GlobalISelEmitter.cpp
+SRCS+= InstrDocsEmitter.cpp
+SRCS+= InstrInfoEmitter.cpp
+SRCS+= IntrinsicEmitter.cpp
+SRCS+= MacroFusionPredicatorEmitter.cpp
+SRCS+= OptParserEmitter.cpp
+SRCS+= OptRSTEmitter.cpp
+SRCS+= PseudoLoweringEmitter.cpp
+SRCS+= RISCVTargetDefEmitter.cpp
+SRCS+= RegisterBankEmitter.cpp
+SRCS+= RegisterInfoEmitter.cpp
+SRCS+= SearchableTableEmitter.cpp
+SRCS+= SubtargetEmitter.cpp
+SRCS+= TableGen.cpp
+SRCS+= VTEmitter.cpp
+SRCS+= WebAssemblyDisassemblerEmitter.cpp
+SRCS+= X86DisassemblerTables.cpp
+SRCS+= X86FoldTablesEmitter.cpp
+SRCS+= X86InstrMappingEmitter.cpp
+SRCS+= X86MnemonicTables.cpp
+SRCS+= X86ModRMFilters.cpp
+SRCS+= X86RecognizableInstr.cpp
+
+CFLAGS+= -I${LLVM_BASE}/${SRCDIR}
+CFLAGS+= -I${.OBJDIR}
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+llvm/CodeGen/GenVT.inc: ${LLVM_SRCS}/include/llvm/CodeGen/ValueTypes.td
+ ${LLVM_MIN_TBLGEN} -gen-vt \
+ -I ${LLVM_SRCS}/include -d ${.TARGET}.d -o ${.TARGET} \
+ ${LLVM_SRCS}/include/llvm/CodeGen/ValueTypes.td
+TGHDRS+= llvm/CodeGen/GenVT.inc
+
+DEPENDFILES+= ${TGHDRS:C/$/.d/}
+DPSRCS+= ${TGHDRS}
+CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/}
+CLEANFILES+= ${GENSRCS} ${GENSRCS:C/$/.d/}
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-tblgen/Makefile.depend b/usr.bin/clang/llvm-tblgen/Makefile.depend
new file mode 100644
index 000000000000..a4c44d6cfcfb
--- /dev/null
+++ b/usr.bin/clang/llvm-tblgen/Makefile.depend
@@ -0,0 +1,25 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libexecinfo \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-min-tblgen.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-tblgen/Makefile.depend.host b/usr.bin/clang/llvm-tblgen/Makefile.depend.host
new file mode 100644
index 000000000000..4ace687cb406
--- /dev/null
+++ b/usr.bin/clang/llvm-tblgen/Makefile.depend.host
@@ -0,0 +1,13 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/clang/libllvmminimal \
+ lib/ncurses/tinfo \
+ usr.bin/clang/llvm-min-tblgen \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm-xray/Makefile b/usr.bin/clang/llvm-xray/Makefile
new file mode 100644
index 000000000000..43f596b32c0b
--- /dev/null
+++ b/usr.bin/clang/llvm-xray/Makefile
@@ -0,0 +1,16 @@
+PROG_CXX= llvm-xray
+MAN=
+
+SRCDIR= llvm/tools/llvm-xray
+SRCS+= func-id-helper.cpp
+SRCS+= llvm-xray.cpp
+SRCS+= xray-account.cpp
+SRCS+= xray-color-helper.cpp
+SRCS+= xray-converter.cpp
+SRCS+= xray-extract.cpp
+SRCS+= xray-graph-diff.cpp
+SRCS+= xray-graph.cpp
+SRCS+= xray-registry.cpp
+SRCS+= xray-stacks.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/llvm-xray/Makefile.depend b/usr.bin/clang/llvm-xray/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/llvm-xray/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/llvm.prog.mk b/usr.bin/clang/llvm.prog.mk
new file mode 100644
index 000000000000..27a3312726df
--- /dev/null
+++ b/usr.bin/clang/llvm.prog.mk
@@ -0,0 +1,32 @@
+
+.include "${SRCTOP}/lib/clang/llvm.pre.mk"
+
+CFLAGS+= -I${OBJTOP}/lib/clang/libllvm
+
+.include "${SRCTOP}/lib/clang/llvm.build.mk"
+
+# Special case for the bootstrap-tools phase.
+.if (defined(TOOLS_PREFIX) || ${MACHINE} == "host") && \
+ (${PROG_CXX} == "clang-tblgen" || ${PROG_CXX} == "lldb-tblgen" || \
+ ${PROG_CXX} == "llvm-min-tblgen" || ${PROG_CXX} == "llvm-tblgen")
+LIBDEPS+= llvmminimal
+.else
+LIBDEPS+= llvm
+LIBADD+= z
+LIBADD+= zstd
+.endif
+
+.for lib in ${LIBDEPS}
+DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${lib}.a
+.endfor
+
+PACKAGE= clang
+
+.if ${.MAKE.OS} == "FreeBSD" || !defined(BOOTSTRAPPING)
+LIBADD+= execinfo
+LIBADD+= tinfow
+.endif
+LIBADD+= pthread
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/clang/opt/Makefile b/usr.bin/clang/opt/Makefile
new file mode 100644
index 000000000000..dc5f39672f72
--- /dev/null
+++ b/usr.bin/clang/opt/Makefile
@@ -0,0 +1,8 @@
+PROG_CXX= opt
+
+SRCDIR= llvm/tools/opt
+SRCS+= NewPMDriver.cpp
+SRCS+= opt.cpp
+SRCS+= optdriver.cpp
+
+.include "../llvm.prog.mk"
diff --git a/usr.bin/clang/opt/Makefile.depend b/usr.bin/clang/opt/Makefile.depend
new file mode 100644
index 000000000000..73df5dd192a7
--- /dev/null
+++ b/usr.bin/clang/opt/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/clang/libllvm \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libthr \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/clang/opt/opt.1 b/usr.bin/clang/opt/opt.1
new file mode 100644
index 000000000000..d8cfbbc32594
--- /dev/null
+++ b/usr.bin/clang/opt/opt.1
@@ -0,0 +1,147 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "OPT" "1" "2023-05-24" "16" "LLVM"
+.SH NAME
+opt \- LLVM optimizer
+.SH SYNOPSIS
+.sp
+\fBopt\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+The \fBopt\fP command is the modular LLVM optimizer and analyzer. It takes
+LLVM source files as input, runs the specified optimizations or analyses on it,
+and then outputs the optimized file. The optimizations available via
+\fBopt\fP depend upon what libraries were linked into it as well as any
+additional libraries that have been loaded with the \fI\%\-load\fP option. Use
+the \fI\%\-help\fP option to determine what optimizations you can use.
+.sp
+If \fBfilename\fP is omitted from the command line or is \(dq\fB\-\fP\(dq, \fBopt\fP
+reads its input from standard input. Inputs can be in either the LLVM assembly
+language format (\fB\&.ll\fP) or the LLVM bitcode format (\fB\&.bc\fP).
+.sp
+If an output filename is not specified with the \fI\%\-o\fP option,
+\fBopt\fP writes its output to the standard output.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-f
+Enable binary output on terminals. Normally, \fBopt\fP will refuse to
+write raw bitcode output if the output stream is a terminal. With this option,
+\fBopt\fP will write raw bitcode regardless of the output device.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-help
+Print a summary of command line options.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-o <filename>
+Specify the output filename.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-S
+Write output in LLVM intermediate language (instead of bitcode).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-{passname}
+\fBopt\fP provides the ability to run any of LLVM\(aqs optimization or
+analysis passes in any order. The \fI\%\-help\fP option lists all the passes
+available. The order in which the options occur on the command line are the
+order in which they are executed (within pass constraints).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-strip\-debug
+This option causes opt to strip debug information from the module before
+applying other optimizations. It is essentially the same as \fI\-strip\fP
+but it ensures that stripping of debug information is done first.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-verify\-each
+This option causes opt to add a verify pass after every pass otherwise
+specified on the command line (including \fI\-verify\fP). This is useful
+for cases where it is suspected that a pass is creating an invalid module but
+it is not clear which pass is doing it.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-stats
+Print statistics.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-time\-passes
+Record the amount of time needed for each pass and print it to standard
+error.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-debug
+If this is a debug build, this option will enable debug printouts from passes
+which use the \fBLLVM_DEBUG()\fP macro. See the \fI\%LLVM Programmer\(aqs Manual\fP, section \fB#DEBUG\fP for more information.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-load=<plugin>
+Load the dynamic object \fBplugin\fP\&. This object should register new
+optimization or analysis passes. Once loaded, the object will add new command
+line options to enable various optimizations or analyses. To see the new
+complete list of optimizations, use the \fI\%\-help\fP and \fI\%\-load\fP
+options together. For example:
+.INDENT 7.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+opt \-load=plugin.so \-help
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-print\-passes
+Print all available passes and exit.
+.UNINDENT
+.SH EXIT STATUS
+.sp
+If \fBopt\fP succeeds, it will exit with 0. Otherwise, if an error
+occurs, it will exit with a non\-zero value.
+.SH AUTHOR
+Maintained by the LLVM Team (https://llvm.org/).
+.SH COPYRIGHT
+2003-2023, LLVM Project
+.\" Generated by docutils manpage writer.
+.
diff --git a/usr.bin/cmp/Makefile b/usr.bin/cmp/Makefile
new file mode 100644
index 000000000000..6f4720226a3e
--- /dev/null
+++ b/usr.bin/cmp/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PROG= cmp
+SRCS= cmp.c link.c misc.c regular.c special.c
+
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cmp/Makefile.depend b/usr.bin/cmp/Makefile.depend
new file mode 100644
index 000000000000..ad56045f44d3
--- /dev/null
+++ b/usr.bin/cmp/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cmp/cmp.1 b/usr.bin/cmp/cmp.1
new file mode 100644
index 000000000000..ab797fa89e2a
--- /dev/null
+++ b/usr.bin/cmp/cmp.1
@@ -0,0 +1,210 @@
+.\" Copyright (c) 1987, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd September 23, 2021
+.Dt CMP 1
+.Os
+.Sh NAME
+.Nm cmp
+.Nd compare two files
+.Sh SYNOPSIS
+.Nm
+.Op Fl l | s | x
+.Op Fl bhz
+.Op Fl -ignore-initial Ns Cm = Ns Ar num1 Ns Op :num2
+.Op Fl -bytes Ns Cm = Ns Ar num
+.Ar file1 file2
+.Op Ar skip1 Op Ar skip2
+.Sh DESCRIPTION
+The
+.Nm
+utility compares two files of any type and writes the results
+to the standard output.
+By default,
+.Nm
+is silent if the files are the same; if they differ, the byte
+and line number at which the first difference occurred is reported.
+.Pp
+Bytes and lines are numbered beginning with one.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl b , Fl -print-bytes
+Print each byte when a difference is found.
+.It Fl h
+Do not follow symbolic links.
+.It Fl i Ar num1 Ns Oo :num2 Oc , Fl -ignore-initial= Ns Ar num1 Ns Op :num2
+Skip
+.Ar num1
+bytes from
+.Ar file1 ,
+and optionally skip
+.Ar num2
+bytes from
+.Ar file2 .
+If
+.Ar num2
+is not specified, then
+.Ar num1
+is applied for both
+.Ar file1
+and
+.Ar file2 .
+.It Fl l , Fl -verbose
+Print the byte number (decimal) and the differing
+byte values (octal) for each difference.
+.It Fl n Ar num , Fl -bytes= Ns num
+Only compare up to
+.Ar num
+bytes.
+.It Fl s , Fl -silent , Fl -quiet
+Print nothing for differing files; return exit
+status only.
+.It Fl x
+Like
+.Fl l
+but prints in hexadecimal and using zero as index
+for the first byte in the files.
+.It Fl z
+For regular files compare file sizes first, and fail the comparison if they
+are not equal.
+.El
+.Pp
+The optional arguments
+.Ar skip1
+and
+.Ar skip2
+are the byte offsets from the beginning of
+.Ar file1
+and
+.Ar file2 ,
+respectively, where the comparison will begin.
+The offset is decimal by default, but may be expressed as a hexadecimal
+or octal value by preceding it with a leading ``0x'' or ``0''.
+.Pp
+.Ar skip1
+and
+.Ar skip2
+may also be specified with SI size suffixes.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Bl -tag -width 4n
+.It 0
+The files are identical.
+.It 1
+The files are different; this includes the case
+where one file is identical to the first part of
+the other.
+In the latter case, if the
+.Fl s
+option has not been specified,
+.Nm
+writes to standard error that EOF was reached in the shorter
+file (before any differences were found).
+.It >1
+An error occurred.
+.El
+.Sh EXAMPLES
+Assuming a file named
+.Pa example.txt
+with the following contents:
+.Bd -literal -offset indent
+a
+b
+c
+.Ed
+.Pp
+Compare stdin with
+.Pa example.txt :
+.Bd -literal -offset indent
+$ echo -e "a\\nb\\nc" | cmp - example.txt
+.Ed
+.Pp
+Same as above but introducing a change in the third byte of stdin.
+Show the byte number (decimal) and differing byte (octal):
+.Bd -literal -offset indent
+$ echo -e "a\\nR\\nc" | cmp -l - example.txt
+ 3 122 142
+.Ed
+.Pp
+Compare file sizes of
+.Pa example.txt
+and
+.Pa /boot/loader.conf
+and return 1 if they are not equal.
+Note that
+.Fl z
+can only be used with regular files:
+.Bd -literal -offset indent
+$ cmp -z example.txt /boot/loader.conf
+example.txt /boot/loader.conf differ: size
+.Ed
+.Pp
+Compare stdin with
+.Pa example.txt
+omitting the first 4 bytes from stdin and the first 2 bytes from
+.Pa example.txt :
+.Bd -literal -offset indent
+$ echo -e "a\\nR\\nb\\nc" | cmp - example.txt 4 2
+.Ed
+.Sh SEE ALSO
+.Xr diff 1 ,
+.Xr diff3 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+The
+.Fl b ,
+.Fl h ,
+.Fl i ,
+.Fl n ,
+.Fl x ,
+and
+.Fl z
+options are extensions to the standard.
+.Ar skip1
+and
+.Ar skip2
+arguments are extensions to the standard.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+.Sh BUGS
+The phrase
+.Dq SI size suffixes
+above refers to the traditional power of two convention, as described in
+.Xr expand_number 3 .
diff --git a/usr.bin/cmp/cmp.c b/usr.bin/cmp/cmp.c
new file mode 100644
index 000000000000..746616c0c20b
--- /dev/null
+++ b/usr.bin/cmp/cmp.c
@@ -0,0 +1,269 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1990, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <nl_types.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+#include "extern.h"
+
+bool bflag, lflag, sflag, xflag, zflag;
+
+static const struct option long_opts[] =
+{
+ {"print-bytes", no_argument, NULL, 'b'},
+ {"ignore-initial", required_argument, NULL, 'i'},
+ {"verbose", no_argument, NULL, 'l'},
+ {"bytes", required_argument, NULL, 'n'},
+ {"silent", no_argument, NULL, 's'},
+ {"quiet", no_argument, NULL, 's'},
+ {NULL, no_argument, NULL, 0}
+};
+
+#ifdef SIGINFO
+volatile sig_atomic_t info;
+
+static void
+siginfo(int signo)
+{
+ info = signo;
+}
+#endif
+
+static void usage(void) __dead2;
+
+static bool
+parse_iskipspec(char *spec, off_t *skip1, off_t *skip2)
+{
+ char *colon;
+
+ colon = strchr(spec, ':');
+ if (colon != NULL)
+ *colon++ = '\0';
+
+ if (expand_number(spec, skip1) < 0)
+ return (false);
+
+ if (colon != NULL)
+ return (expand_number(colon, skip2) == 0);
+
+ *skip2 = *skip1;
+ return (true);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb1, sb2;
+ off_t skip1, skip2, limit;
+ int ch, fd1, fd2, oflag;
+ bool special;
+ const char *file1, *file2;
+ int ret;
+
+ limit = skip1 = skip2 = ret = 0;
+ oflag = O_RDONLY;
+ while ((ch = getopt_long(argc, argv, "+bhi:ln:sxz", long_opts, NULL)) != -1)
+ switch (ch) {
+ case 'b': /* Print bytes */
+ bflag = true;
+ break;
+ case 'h': /* Don't follow symlinks */
+ oflag |= O_NOFOLLOW;
+ break;
+ case 'i':
+ if (!parse_iskipspec(optarg, &skip1, &skip2)) {
+ fprintf(stderr,
+ "Invalid --ignore-initial: %s\n",
+ optarg);
+ usage();
+ }
+ break;
+ case 'l': /* print all differences */
+ lflag = true;
+ break;
+ case 'n': /* Limit */
+ if (expand_number(optarg, &limit) < 0 || limit < 0) {
+ fprintf(stderr, "Invalid --bytes: %s\n",
+ optarg);
+ usage();
+ }
+ break;
+ case 's': /* silent run */
+ sflag = true;
+ break;
+ case 'x': /* hex output */
+ lflag = true;
+ xflag = true;
+ break;
+ case 'z': /* compare size first */
+ zflag = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (lflag && sflag)
+ errx(ERR_EXIT, "specifying -s with -l or -x is not permitted");
+
+ if (argc < 2 || argc > 4)
+ usage();
+
+ /* Don't limit rights on stdin since it may be one of the inputs. */
+ if (caph_limit_stream(STDOUT_FILENO, CAPH_WRITE | CAPH_IGNORE_EBADF))
+ err(ERR_EXIT, "unable to limit rights on stdout");
+ if (caph_limit_stream(STDERR_FILENO, CAPH_WRITE | CAPH_IGNORE_EBADF))
+ err(ERR_EXIT, "unable to limit rights on stderr");
+
+ /* Backward compatibility -- handle "-" meaning stdin. */
+ special = false;
+ if (strcmp(file1 = argv[0], "-") == 0) {
+ special = true;
+ fd1 = STDIN_FILENO;
+ file1 = "stdin";
+ } else if ((fd1 = open(file1, oflag, 0)) < 0 && errno != EMLINK) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file1);
+ else
+ exit(ERR_EXIT);
+ }
+ if (strcmp(file2 = argv[1], "-") == 0) {
+ if (special)
+ errx(ERR_EXIT,
+ "standard input may only be specified once");
+ special = true;
+ fd2 = STDIN_FILENO;
+ file2 = "stdin";
+ } else if ((fd2 = open(file2, oflag, 0)) < 0 && errno != EMLINK) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file2);
+ else
+ exit(ERR_EXIT);
+ }
+
+ if (argc > 2 && expand_number(argv[2], &skip1) < 0) {
+ fprintf(stderr, "Invalid skip1: %s\n", argv[2]);
+ usage();
+ }
+
+ if (argc == 4 && expand_number(argv[3], &skip2) < 0) {
+ fprintf(stderr, "Invalid skip2: %s\n", argv[3]);
+ usage();
+ }
+
+ if (sflag && skip1 == 0 && skip2 == 0)
+ zflag = true;
+
+ if (fd1 == -1) {
+ if (fd2 == -1) {
+ ret = c_link(file1, skip1, file2, skip2, limit);
+ goto end;
+ } else if (!sflag)
+ errx(ERR_EXIT, "%s: Not a symbolic link", file2);
+ else
+ exit(ERR_EXIT);
+ } else if (fd2 == -1) {
+ if (!sflag)
+ errx(ERR_EXIT, "%s: Not a symbolic link", file1);
+ else
+ exit(ERR_EXIT);
+ }
+
+ /* FD rights are limited in c_special() and c_regular(). */
+ caph_cache_catpages();
+
+ if (!special) {
+ if (fstat(fd1, &sb1)) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file1);
+ else
+ exit(ERR_EXIT);
+ }
+ if (!S_ISREG(sb1.st_mode))
+ special = true;
+ else {
+ if (fstat(fd2, &sb2)) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file2);
+ else
+ exit(ERR_EXIT);
+ }
+ if (!S_ISREG(sb2.st_mode))
+ special = true;
+ }
+ }
+
+#ifdef SIGINFO
+ (void)signal(SIGINFO, siginfo);
+#endif
+ if (special) {
+ ret = c_special(fd1, file1, skip1, fd2, file2, skip2, limit);
+ } else {
+ if (zflag && sb1.st_size != sb2.st_size) {
+ if (!sflag)
+ (void)printf("%s %s differ: size\n",
+ file1, file2);
+ ret = DIFF_EXIT;
+ } else {
+ ret = c_regular(fd1, file1, skip1, sb1.st_size,
+ fd2, file2, skip2, sb2.st_size, limit);
+ }
+ }
+end:
+ if (!sflag && fflush(stdout) != 0)
+ err(ERR_EXIT, "stdout");
+ exit(ret);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: cmp [-l | -s | -x] [-hz] file1 file2 [skip1 [skip2]]\n");
+ exit(ERR_EXIT);
+}
diff --git a/usr.bin/cmp/extern.h b/usr.bin/cmp/extern.h
new file mode 100644
index 000000000000..4671b34653fa
--- /dev/null
+++ b/usr.bin/cmp/extern.h
@@ -0,0 +1,48 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ *
+ */
+
+#define OK_EXIT 0
+#define DIFF_EXIT 1
+#define ERR_EXIT 2 /* error exit code */
+
+int c_link(const char *, off_t, const char *, off_t, off_t);
+int c_regular(int, const char *, off_t, off_t, int, const char *, off_t,
+ off_t, off_t);
+int c_special(int, const char *, off_t, int, const char *, off_t, off_t);
+void diffmsg(const char *, const char *, off_t, off_t, int, int);
+void eofmsg(const char *);
+
+extern bool bflag, lflag, sflag, xflag, zflag;
+
+#ifdef SIGINFO
+extern volatile sig_atomic_t info;
+#endif
diff --git a/usr.bin/cmp/link.c b/usr.bin/cmp/link.c
new file mode 100644
index 000000000000..dfa2f957d829
--- /dev/null
+++ b/usr.bin/cmp/link.c
@@ -0,0 +1,103 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005 Brian Somers <brian@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <err.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+int
+c_link(const char *file1, off_t skip1, const char *file2, off_t skip2,
+ off_t limit)
+{
+ char buf1[PATH_MAX], *p1;
+ char buf2[PATH_MAX], *p2;
+ ssize_t len1, len2;
+ int dfound;
+ off_t byte;
+ u_char ch;
+
+ if ((len1 = readlink(file1, buf1, sizeof(buf1) - 1)) < 0) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file1);
+ else
+ exit(ERR_EXIT);
+ }
+
+ if ((len2 = readlink(file2, buf2, sizeof(buf2) - 1)) < 0) {
+ if (!sflag)
+ err(ERR_EXIT, "%s", file2);
+ else
+ exit(ERR_EXIT);
+ }
+
+ if (skip1 > len1)
+ skip1 = len1;
+ buf1[len1] = '\0';
+
+ if (skip2 > len2)
+ skip2 = len2;
+ buf2[len2] = '\0';
+
+ dfound = 0;
+ byte = 1;
+ for (p1 = buf1 + skip1, p2 = buf2 + skip2;
+ *p1 && *p2 && (limit == 0 || byte <= limit); p1++, p2++) {
+ if ((ch = *p1) != *p2) {
+ if (xflag) {
+ dfound = 1;
+ (void)printf("%08llx %02x %02x\n",
+ (long long)byte - 1, ch, *p2);
+ } else if (lflag) {
+ dfound = 1;
+ if (bflag)
+ (void)printf("%6lld %3o %c %3o %c\n",
+ (long long)byte, ch, ch, *p2, *p2);
+ else
+ (void)printf("%6lld %3o %3o\n",
+ (long long)byte, ch, *p2);
+ } else {
+ diffmsg(file1, file2, byte, 1, ch, *p2);
+ return (DIFF_EXIT);
+ }
+ }
+ byte++;
+ }
+
+ if (*p1 || *p2) {
+ eofmsg (*p1 ? file2 : file1);
+ return (DIFF_EXIT);
+ }
+ return (dfound ? DIFF_EXIT : 0);
+}
diff --git a/usr.bin/cmp/misc.c b/usr.bin/cmp/misc.c
new file mode 100644
index 000000000000..4abefff31cf9
--- /dev/null
+++ b/usr.bin/cmp/misc.c
@@ -0,0 +1,62 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "extern.h"
+
+void
+eofmsg(const char *file)
+{
+ if (!sflag)
+ warnx("EOF on %s", file);
+}
+
+void
+diffmsg(const char *file1, const char *file2, off_t byte, off_t line,
+ int b1, int b2)
+{
+ if (sflag) {
+ /* nothing */
+ } else if (bflag) {
+ (void)printf("%s %s differ: char %lld, line %lld is %3o %c %3o %c\n",
+ file1, file2, (long long)byte, (long long)line, b1, b1,
+ b2, b2);
+ } else {
+ (void)printf("%s %s differ: char %lld, line %lld\n",
+ file1, file2, (long long)byte, (long long)line);
+ }
+}
diff --git a/usr.bin/cmp/regular.c b/usr.bin/cmp/regular.c
new file mode 100644
index 000000000000..c4407f708e8a
--- /dev/null
+++ b/usr.bin/cmp/regular.c
@@ -0,0 +1,191 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static u_char *remmap(u_char *, int, off_t);
+static void segv_handler(int);
+#define MMAP_CHUNK (8*1024*1024)
+
+#define ROUNDPAGE(i) ((i) & ~pagemask)
+
+int
+c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
+ int fd2, const char *file2, off_t skip2, off_t len2, off_t limit)
+{
+ struct sigaction act, oact;
+ cap_rights_t rights;
+ u_char ch, *p1, *p2, *m1, *m2, *e1, *e2;
+ off_t byte, length, line;
+ off_t pagemask, off1, off2;
+ size_t pagesize;
+ int dfound;
+
+ if (skip1 > len1) {
+ eofmsg(file1);
+ return (DIFF_EXIT);
+ }
+ len1 -= skip1;
+ if (skip2 > len2) {
+ eofmsg(file2);
+ return (DIFF_EXIT);
+ }
+ len2 -= skip2;
+
+ if (sflag && len1 != len2)
+ return (DIFF_EXIT);
+
+ pagesize = getpagesize();
+ pagemask = (off_t)pagesize - 1;
+ off1 = ROUNDPAGE(skip1);
+ off2 = ROUNDPAGE(skip2);
+
+ length = MIN(len1, len2);
+ if (limit > 0)
+ length = MIN(length, limit);
+
+ if ((m1 = remmap(NULL, fd1, off1)) == NULL) {
+ return (c_special(fd1, file1, skip1, fd2, file2, skip2, limit));
+ }
+
+ if ((m2 = remmap(NULL, fd2, off2)) == NULL) {
+ munmap(m1, MMAP_CHUNK);
+ return (c_special(fd1, file1, skip1, fd2, file2, skip2, limit));
+ }
+
+ if (caph_rights_limit(fd1, cap_rights_init(&rights, CAP_MMAP_R)) < 0)
+ err(1, "unable to limit rights for %s", file1);
+ if (caph_rights_limit(fd2, cap_rights_init(&rights, CAP_MMAP_R)) < 0)
+ err(1, "unable to limit rights for %s", file2);
+ if (caph_enter() < 0)
+ err(ERR_EXIT, "unable to enter capability mode");
+
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NODEFER;
+ act.sa_handler = segv_handler;
+ if (sigaction(SIGSEGV, &act, &oact))
+ err(ERR_EXIT, "sigaction()");
+
+ dfound = 0;
+ e1 = m1 + MMAP_CHUNK;
+ e2 = m2 + MMAP_CHUNK;
+ p1 = m1 + (skip1 - off1);
+ p2 = m2 + (skip2 - off2);
+
+ for (byte = line = 1; length--; ++byte) {
+#ifdef SIGINFO
+ if (info) {
+ (void)fprintf(stderr, "%s %s char %zu line %zu\n",
+ file1, file2, (size_t)byte, (size_t)line);
+ info = 0;
+ }
+#endif
+ if ((ch = *p1) != *p2) {
+ dfound = 1;
+ if (xflag) {
+ (void)printf("%08llx %02x %02x\n",
+ (long long)byte - 1, ch, *p2);
+ } else if (lflag) {
+ if (bflag)
+ (void)printf("%6lld %3o %c %3o %c\n",
+ (long long)byte, ch, ch, *p2, *p2);
+ else
+ (void)printf("%6lld %3o %3o\n",
+ (long long)byte, ch, *p2);
+ } else {
+ diffmsg(file1, file2, byte, line, ch, *p2);
+ return (DIFF_EXIT);
+ }
+ }
+ if (ch == '\n')
+ ++line;
+ if (++p1 == e1) {
+ off1 += MMAP_CHUNK;
+ if ((p1 = m1 = remmap(m1, fd1, off1)) == NULL) {
+ munmap(m2, MMAP_CHUNK);
+ err(ERR_EXIT, "remmap %s", file1);
+ }
+ e1 = m1 + MMAP_CHUNK;
+ }
+ if (++p2 == e2) {
+ off2 += MMAP_CHUNK;
+ if ((p2 = m2 = remmap(m2, fd2, off2)) == NULL) {
+ munmap(m1, MMAP_CHUNK);
+ err(ERR_EXIT, "remmap %s", file2);
+ }
+ e2 = m2 + MMAP_CHUNK;
+ }
+ }
+ munmap(m1, MMAP_CHUNK);
+ munmap(m2, MMAP_CHUNK);
+
+ if (sigaction(SIGSEGV, &oact, NULL))
+ err(ERR_EXIT, "sigaction()");
+
+ if (len1 != len2) {
+ eofmsg(len1 > len2 ? file2 : file1);
+ return (DIFF_EXIT);
+ }
+ return (dfound ? DIFF_EXIT : 0);
+}
+
+static u_char *
+remmap(u_char *mem, int fd, off_t offset)
+{
+ if (mem != NULL)
+ munmap(mem, MMAP_CHUNK);
+ mem = mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd, offset);
+ if (mem == MAP_FAILED)
+ return (NULL);
+ madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
+ return (mem);
+}
+
+static void
+segv_handler(int sig __unused) {
+ static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
+
+ write(STDERR_FILENO, msg, sizeof(msg));
+ _exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/cmp/special.c b/usr.bin/cmp/special.c
new file mode 100644
index 000000000000..e25e82b17047
--- /dev/null
+++ b/usr.bin/cmp/special.c
@@ -0,0 +1,126 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "extern.h"
+
+int
+c_special(int fd1, const char *file1, off_t skip1,
+ int fd2, const char *file2, off_t skip2, off_t limit)
+{
+ int ch1, ch2;
+ off_t byte, line;
+ FILE *fp1, *fp2;
+ int dfound;
+
+ if (caph_limit_stream(fd1, CAPH_READ) < 0)
+ err(ERR_EXIT, "caph_limit_stream(%s)", file1);
+ if (caph_limit_stream(fd2, CAPH_READ) < 0)
+ err(ERR_EXIT, "caph_limit_stream(%s)", file2);
+ if (caph_enter() < 0)
+ err(ERR_EXIT, "unable to enter capability mode");
+
+ if ((fp1 = fdopen(fd1, "r")) == NULL)
+ err(ERR_EXIT, "%s", file1);
+ (void)setvbuf(fp1, NULL, _IOFBF, 65536);
+ if ((fp2 = fdopen(fd2, "r")) == NULL)
+ err(ERR_EXIT, "%s", file2);
+ (void)setvbuf(fp2, NULL, _IOFBF, 65536);
+
+ dfound = 0;
+ while (skip1--)
+ if (getc(fp1) == EOF)
+ goto eof;
+ while (skip2--)
+ if (getc(fp2) == EOF)
+ goto eof;
+
+ for (byte = line = 1; limit == 0 || byte <= limit; ++byte) {
+#ifdef SIGINFO
+ if (info) {
+ (void)fprintf(stderr, "%s %s char %zu line %zu\n",
+ file1, file2, (size_t)byte, (size_t)line);
+ info = 0;
+ }
+#endif
+ ch1 = getc(fp1);
+ ch2 = getc(fp2);
+ if (ch1 == EOF || ch2 == EOF)
+ break;
+ if (ch1 != ch2) {
+ if (xflag) {
+ dfound = 1;
+ (void)printf("%08llx %02x %02x\n",
+ (long long)byte - 1, ch1, ch2);
+ } else if (lflag) {
+ dfound = 1;
+ if (bflag)
+ (void)printf("%6lld %3o %c %3o %c\n",
+ (long long)byte, ch1, ch1, ch2,
+ ch2);
+ else
+ (void)printf("%6lld %3o %3o\n",
+ (long long)byte, ch1, ch2);
+ } else {
+ diffmsg(file1, file2, byte, line, ch1, ch2);
+ return (DIFF_EXIT);
+ }
+ }
+ if (ch1 == '\n')
+ ++line;
+ }
+
+eof: if (ferror(fp1))
+ err(ERR_EXIT, "%s", file1);
+ if (ferror(fp2))
+ err(ERR_EXIT, "%s", file2);
+ if (feof(fp1)) {
+ if (!feof(fp2)) {
+ eofmsg(file1);
+ return (DIFF_EXIT);
+ }
+ } else {
+ if (feof(fp2)) {
+ eofmsg(file2);
+ return (DIFF_EXIT);
+ }
+ }
+ fclose(fp2);
+ fclose(fp1);
+ return (dfound ? DIFF_EXIT : 0);
+}
diff --git a/usr.bin/cmp/tests/Makefile b/usr.bin/cmp/tests/Makefile
new file mode 100644
index 000000000000..8524fbaee43c
--- /dev/null
+++ b/usr.bin/cmp/tests/Makefile
@@ -0,0 +1,13 @@
+.include <bsd.own.mk>
+
+PACKAGE= tests
+
+ATF_TESTS_SH+= cmp_test2
+NETBSD_ATF_TESTS_SH= cmp_test
+
+${PACKAGE}FILES+= b_flag.out
+${PACKAGE}FILES+= bl_flag.out
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/cmp/tests/Makefile.depend b/usr.bin/cmp/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/cmp/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cmp/tests/b_flag.out b/usr.bin/cmp/tests/b_flag.out
new file mode 100644
index 000000000000..bb3d288716b0
--- /dev/null
+++ b/usr.bin/cmp/tests/b_flag.out
@@ -0,0 +1 @@
+a b differ: char 3, line 1 is 143 c 144 d
diff --git a/usr.bin/cmp/tests/bl_flag.out b/usr.bin/cmp/tests/bl_flag.out
new file mode 100644
index 000000000000..8ec9007d7ed3
--- /dev/null
+++ b/usr.bin/cmp/tests/bl_flag.out
@@ -0,0 +1 @@
+ 3 143 c 144 d
diff --git a/usr.bin/cmp/tests/cmp_test2.sh b/usr.bin/cmp/tests/cmp_test2.sh
new file mode 100755
index 000000000000..bca8fc18a6b8
--- /dev/null
+++ b/usr.bin/cmp/tests/cmp_test2.sh
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2017 Alan Somers
+#
+# 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.
+#
+
+atf_test_case special
+special_head() {
+ atf_set "descr" "Test cmp(1)'s handling of non-regular files"
+}
+special_body() {
+ echo 0123456789abcdef > a
+ echo 0123456789abcdeg > b
+ atf_check -s exit:0 -o empty -e empty cmp a - <a
+ atf_check -s exit:0 -o empty -e empty cmp - a <a
+ atf_check -s exit:1 -o not-empty -e empty cmp a - <b
+ atf_check -s exit:1 -o not-empty -e empty cmp - a <b
+
+ atf_check -s exit:0 -o empty -e empty cmp a a <&-
+}
+
+atf_test_case symlink
+symlink_head() {
+ atf_set "descr" "Test cmp(1)'s handling of symlinks"
+}
+symlink_body() {
+ echo 0123456789abcdef > a
+ echo 0123456789abcdeg > b
+ ln -s a a.lnk
+ ln -s b b.lnk
+ ln -s a a2.lnk
+ cp a adup
+ ln -s adup adup.lnk
+ atf_check -s exit:0 cmp a a.lnk
+ atf_check -s exit:0 cmp a.lnk a
+ atf_check -s not-exit:0 -o ignore cmp a b.lnk
+ atf_check -s not-exit:0 -o ignore cmp b.lnk a
+ atf_check -s not-exit:0 -o ignore -e ignore cmp -h a a.lnk
+ atf_check -s not-exit:0 -o ignore -e ignore cmp -h a.lnk a
+ atf_check -s exit:0 cmp -h a.lnk a2.lnk
+ atf_check -s not-exit:0 -o ignore -e ignore cmp -h a.lnk adup.lnk
+}
+
+atf_test_case pr252542
+pr252542_head()
+{
+ atf_set "descr" "Test cmp(1) -s with file offset skips"
+}
+pr252542_body()
+{
+ echo -n '1234567890' > a
+ echo -n 'abc567890' > b
+ echo -n 'xbc567890' > c
+ atf_check -s exit:0 cmp -s a b 4 3
+ atf_check -s exit:0 cmp -i 4:3 -s a b
+ atf_check -s exit:0 cmp -i 1 -s b c
+ atf_check -s exit:1 -o ignore cmp -z a b 4 3
+ atf_check -s exit:1 -o ignore cmp -i 4:3 -z a b
+ atf_check -s exit:1 -o ignore cmp -i 1 -z a b
+}
+
+atf_test_case skipsuff
+skipsuff_head()
+{
+ atf_set "descr" "Test cmp(1) accepting SI suffixes on skips"
+}
+skipsuff_body()
+{
+
+ jot -nb a -s '' 1028 > a
+ jot -nb b -s '' 1024 > b
+ jot -nb a -s '' 4 >> b
+
+ atf_check -s exit:1 -o ignore cmp -s a b
+ atf_check -s exit:0 cmp -s a b 1k 1k
+}
+
+atf_test_case limit
+limit_head()
+{
+ atf_set "descr" "Test cmp(1) -n (limit)"
+}
+limit_body()
+{
+ echo -n "aaaabbbb" > a
+ echo -n "aaaaxxxx" > b
+
+ atf_check -s exit:1 -o ignore cmp -s a b
+ atf_check -s exit:0 cmp -sn 4 a b
+ atf_check -s exit:0 cmp -sn 3 a b
+ atf_check -s exit:1 -o ignore cmp -sn 5 a b
+
+ # Test special, too. The implementation for link is effectively
+ # identical.
+ atf_check -s exit:0 -e empty cmp -sn 4 b - <a
+ atf_check -s exit:0 -e empty cmp -sn 3 b - <a
+ atf_check -s exit:1 -o ignore cmp -sn 5 b - <a
+}
+
+atf_test_case bflag
+bflag_head()
+{
+ atf_set "descr" "Test cmp(1) -b (print bytes)"
+}
+bflag_body()
+{
+ echo -n "abcd" > a
+ echo -n "abdd" > b
+
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/b_flag.out \
+ cmp -b a b
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/bl_flag.out \
+ cmp -bl a b
+}
+
+# Helper for stdout test case
+atf_check_stdout()
+{
+ (
+ trap "" PIPE
+ sleep 1
+ cmp "$@" 2>stderr
+ echo $? >result
+ ) | true
+ atf_check -o inline:"2\n" cat result
+ atf_check -o match:"stdout" cat stderr
+}
+
+atf_test_case stdout
+stdout_head()
+{
+ atf_set descr "Failure to write to stdout"
+}
+stdout_body()
+{
+ echo a >a
+ echo b >b
+ atf_check_stdout a b
+ atf_check_stdout - b <a
+ atf_check_stdout a - <b
+ ln -s a alnk
+ ln -s b blnk
+ atf_check_stdout -h alnk blnk
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case special
+ atf_add_test_case symlink
+ atf_add_test_case pr252542
+ atf_add_test_case skipsuff
+ atf_add_test_case limit
+ atf_add_test_case bflag
+ atf_add_test_case stdout
+}
diff --git a/usr.bin/col/Makefile b/usr.bin/col/Makefile
new file mode 100644
index 000000000000..ce4cc73337a6
--- /dev/null
+++ b/usr.bin/col/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= col
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/col/Makefile.depend b/usr.bin/col/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/col/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/col/README b/usr.bin/col/README
new file mode 100644
index 000000000000..aac0d02f23ba
--- /dev/null
+++ b/usr.bin/col/README
@@ -0,0 +1,45 @@
+
+col - filter out reverse line feeds.
+
+Options are:
+ -b do not print any backspaces (last character written is printed)
+ -f allow half line feeds in output, by default characters between
+ lines are pushed to the line below
+ -p force unknown control sequences to be passed through unchanged
+ -x do not compress spaces into tabs.
+ -l num keep (at least) num lines in memory, 128 are kept by default
+
+In the 32V source code to col(1) the default behavior was to NOT compress
+spaces into tabs. There was a -h option which caused it to compress spaces
+into tabs. There was no -x flag.
+
+The 32V documentation, however, was consistent with the SVID (actually, V7
+at the time) and documented a -x flag (as defined above) while making no
+mention of a -h flag. Just before 4.3BSD went out, CSRG updated the manual
+page to reflect the way the code worked. Suspecting that this was probably
+the wrong way to go, this version adopts the SVID defaults, and no longer
+documents the -h option.
+
+Known differences between AT&T's col and this one (# is delimiter):
+ Input AT&T col this col
+ #\nabc\E7def\n# # def\nabc\r# # def\nabc\n#
+ #a# ## #a\n#
+ - last line always ends with at least one \n (or \E9)
+ #1234567 8\n# #1234567\t8\n# #1234567 8\n#
+ - single space not expanded to tab
+ -f #a\E8b\n# #ab\n# # b\E9\ra\n#
+ - can back up past first line (as far as you want) so you
+ *can* have a super script on the first line
+ #\E9_\ba\E8\nb\n# #\n_\bb\ba\n# #\n_\ba\bb\n#
+ - always print last character written to a position,
+ AT&T col claims to do this but doesn't.
+
+If a character is to be placed on a line that has been flushed, a warning
+is produced (the AT&T col is silent). The -l flag (not in AT&T col) can
+be used to increase the number of lines buffered to avoid the problem.
+
+General algorithm: a limited number of lines are buffered in a linked
+list. When a printable character is read, it is put in the buffer of
+the current line along with the column it's supposed to be in. When
+a line is flushed, the characters in the line are sorted according to
+column and then printed.
diff --git a/usr.bin/col/col.1 b/usr.bin/col/col.1
new file mode 100644
index 000000000000..97059a5c37f9
--- /dev/null
+++ b/usr.bin/col/col.1
@@ -0,0 +1,168 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Michael Rendell.
+.\"
+.\" 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.
+.\"
+.Dd October 21, 2020
+.Dt COL 1
+.Os
+.Sh NAME
+.Nm col
+.Nd filter reverse line feeds from input
+.Sh SYNOPSIS
+.Nm
+.Op Fl bfhpx
+.Op Fl l Ar num
+.Sh DESCRIPTION
+The
+.Nm
+utility filters out reverse (and half reverse) line feeds so that the output is
+in the correct order with only forward and half forward line
+feeds, and replaces white-space characters with tabs where possible.
+.Pp
+The
+.Nm
+utility reads from the standard input and writes to the standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b
+Do not output any backspaces, printing only the last character
+written to each column position.
+.It Fl f
+Forward half line feeds are permitted (``fine'' mode).
+Normally characters printed on a half line boundary are printed
+on the following line.
+.It Fl h
+Do not output multiple spaces instead of tabs (default).
+.It Fl l Ar num
+Buffer at least
+.Ar num
+lines in memory.
+By default, 128 lines are buffered.
+.It Fl p
+Force unknown control sequences to be passed through unchanged.
+Normally,
+.Nm
+will filter out any control sequences from the input other than those
+recognized and interpreted by itself, which are listed below.
+.It Fl x
+Output multiple spaces instead of tabs.
+.El
+.Pp
+In the input stream,
+.Nm
+understands both the escape sequences of the form escape-digit
+mandated by
+.St -susv2
+and the traditional
+.Bx
+format escape-control-character.
+The control sequences for carriage motion and their ASCII values
+are as follows:
+.Pp
+.Bl -tag -width "carriage return" -compact
+.It ESC\-BELL
+reverse line feed (escape then bell).
+.It ESC\-7
+reverse line feed (escape then 7).
+.It ESC\-BACKSPACE
+half reverse line feed (escape then backspace).
+.It ESC\-8
+half reverse line feed (escape then 8).
+.It ESC\-TAB
+half forward line feed (escape than tab).
+.It ESC\-9
+half forward line feed (escape then 9).
+In
+.Fl f
+mode, this sequence may also occur in the output stream.
+.It backspace
+moves back one column (8); ignored in the first column
+.It carriage return
+(13)
+.It newline
+forward line feed (10); also does carriage return
+.It shift in
+shift to normal character set (15)
+.It shift out
+shift to alternate character set (14)
+.It space
+moves forward one column (32)
+.It tab
+moves forward to next tab stop (9)
+.It vertical tab
+reverse line feed (11)
+.El
+.Pp
+All unrecognized control characters and escape sequences are
+discarded.
+.Pp
+The
+.Nm
+utility keeps track of the character set as characters are read and makes
+sure the character set is correct when they are output.
+.Pp
+If the input attempts to back up to the last flushed line,
+.Nm
+will display a warning message.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+We can use
+.Nm
+to filter the output of
+.Xr man 1
+and remove the backspace characters (
+.Em ^H
+) before searching for some text:
+.Bd -literal -offset indent
+man ls | col -b | grep HISTORY
+.Ed
+.Sh SEE ALSO
+.Xr expand 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -susv2 .
+.Sh HISTORY
+A
+.Nm
+command
+appeared in
+.At v6 .
diff --git a/usr.bin/col/col.c b/usr.bin/col/col.c
new file mode 100644
index 000000000000..6665bf8e7f9b
--- /dev/null
+++ b/usr.bin/col/col.c
@@ -0,0 +1,592 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Rendell of the Memorial University of Newfoundland.
+ *
+ * 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/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define BS '\b' /* backspace */
+#define TAB '\t' /* tab */
+#define SPACE ' ' /* space */
+#define NL '\n' /* newline */
+#define CR '\r' /* carriage return */
+#define ESC '\033' /* escape */
+#define SI '\017' /* shift in to normal character set */
+#define SO '\016' /* shift out to alternate character set */
+#define VT '\013' /* vertical tab (aka reverse line feed) */
+#define RLF '7' /* ESC-7 reverse line feed */
+#define RHLF '8' /* ESC-8 reverse half-line feed */
+#define FHLF '9' /* ESC-9 forward half-line feed */
+
+/* build up at least this many lines before flushing them out */
+#define BUFFER_MARGIN 32
+
+typedef char CSET;
+
+typedef struct char_str {
+#define CS_NORMAL 1
+#define CS_ALTERNATE 2
+ short c_column; /* column character is in */
+ CSET c_set; /* character set (currently only 2) */
+ wchar_t c_char; /* character in question */
+ int c_width; /* character width */
+} CHAR;
+
+typedef struct line_str LINE;
+struct line_str {
+ CHAR *l_line; /* characters on the line */
+ LINE *l_prev; /* previous line */
+ LINE *l_next; /* next line */
+ int l_lsize; /* allocated sizeof l_line */
+ int l_line_len; /* strlen(l_line) */
+ int l_needs_sort; /* set if chars went in out of order */
+ int l_max_col; /* max column in the line */
+};
+
+static void addto_lineno(int *, int);
+static LINE *alloc_line(void);
+static void dowarn(int);
+static void flush_line(LINE *);
+static void flush_lines(int);
+static void flush_blanks(void);
+static void free_line(LINE *);
+static void usage(void);
+
+static CSET last_set; /* char_set of last char printed */
+static LINE *lines;
+static int compress_spaces; /* if doing space -> tab conversion */
+static int fine; /* if `fine' resolution (half lines) */
+static int max_bufd_lines; /* max # of half lines to keep in memory */
+static int nblank_lines; /* # blanks after last flushed line */
+static int no_backspaces; /* if not to output any backspaces */
+static int pass_unknown_seqs; /* pass unknown control sequences */
+
+#define PUTC(ch) \
+ do { \
+ if (putwchar(ch) == WEOF) \
+ errx(1, "write error"); \
+ } while (0)
+
+int
+main(int argc, char **argv)
+{
+ wint_t ch;
+ CHAR *c;
+ CSET cur_set; /* current character set */
+ LINE *l; /* current line */
+ int extra_lines; /* # of lines above first line */
+ int cur_col; /* current column */
+ int cur_line; /* line number of current position */
+ int max_line; /* max value of cur_line */
+ int this_line; /* line l points to */
+ int nflushd_lines; /* number of lines that were flushed */
+ int adjust, opt, warned, width;
+ const char *errstr;
+
+ (void)setlocale(LC_CTYPE, "");
+
+ if (caph_limit_stdio() == -1)
+ err(1, "unable to limit stdio");
+
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ max_bufd_lines = 256;
+ compress_spaces = 1; /* compress spaces into tabs */
+ while ((opt = getopt(argc, argv, "bfhl:px")) != -1)
+ switch (opt) {
+ case 'b': /* do not output backspaces */
+ no_backspaces = 1;
+ break;
+ case 'f': /* allow half forward line feeds */
+ fine = 1;
+ break;
+ case 'h': /* compress spaces into tabs */
+ compress_spaces = 1;
+ break;
+ case 'l': /* buffered line count */
+ max_bufd_lines = strtonum(optarg, 1,
+ (INT_MAX - BUFFER_MARGIN) / 2, &errstr) * 2;
+ if (errstr != NULL)
+ errx(1, "bad -l argument, %s: %s", errstr,
+ optarg);
+ break;
+ case 'p': /* pass unknown control sequences */
+ pass_unknown_seqs = 1;
+ break;
+ case 'x': /* do not compress spaces into tabs */
+ compress_spaces = 0;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (optind != argc)
+ usage();
+
+ adjust = cur_col = extra_lines = warned = 0;
+ cur_line = max_line = nflushd_lines = this_line = 0;
+ cur_set = last_set = CS_NORMAL;
+ lines = l = alloc_line();
+
+ while ((ch = getwchar()) != WEOF) {
+ if (!iswgraph(ch)) {
+ switch (ch) {
+ case BS: /* can't go back further */
+ if (cur_col == 0)
+ continue;
+ --cur_col;
+ continue;
+ case CR:
+ cur_col = 0;
+ continue;
+ case ESC: /* just ignore EOF */
+ switch(getwchar()) {
+ /*
+ * In the input stream, accept both the
+ * XPG5 sequences ESC-digit and the
+ * traditional BSD sequences ESC-ctrl.
+ */
+ case '\007':
+ /* FALLTHROUGH */
+ case RLF:
+ addto_lineno(&cur_line, -2);
+ break;
+ case '\010':
+ /* FALLTHROUGH */
+ case RHLF:
+ addto_lineno(&cur_line, -1);
+ break;
+ case '\011':
+ /* FALLTHROUGH */
+ case FHLF:
+ addto_lineno(&cur_line, 1);
+ if (cur_line > max_line)
+ max_line = cur_line;
+ }
+ continue;
+ case NL:
+ addto_lineno(&cur_line, 2);
+ if (cur_line > max_line)
+ max_line = cur_line;
+ cur_col = 0;
+ continue;
+ case SPACE:
+ ++cur_col;
+ continue;
+ case SI:
+ cur_set = CS_NORMAL;
+ continue;
+ case SO:
+ cur_set = CS_ALTERNATE;
+ continue;
+ case TAB: /* adjust column */
+ cur_col |= 7;
+ ++cur_col;
+ continue;
+ case VT:
+ addto_lineno(&cur_line, -2);
+ continue;
+ }
+ if (iswspace(ch)) {
+ if ((width = wcwidth(ch)) > 0)
+ cur_col += width;
+ continue;
+ }
+ if (!pass_unknown_seqs)
+ continue;
+ }
+
+ /* Must stuff ch in a line - are we at the right one? */
+ if (cur_line + adjust != this_line) {
+ LINE *lnew;
+
+ /* round up to next line */
+ adjust = !fine && (cur_line & 1);
+
+ if (cur_line + adjust < this_line) {
+ while (cur_line + adjust < this_line &&
+ l->l_prev != NULL) {
+ l = l->l_prev;
+ this_line--;
+ }
+ if (cur_line + adjust < this_line) {
+ if (nflushd_lines == 0) {
+ /*
+ * Allow backup past first
+ * line if nothing has been
+ * flushed yet.
+ */
+ while (cur_line + adjust
+ < this_line) {
+ lnew = alloc_line();
+ l->l_prev = lnew;
+ lnew->l_next = l;
+ l = lines = lnew;
+ extra_lines++;
+ this_line--;
+ }
+ } else {
+ if (!warned++)
+ dowarn(cur_line);
+ cur_line = this_line - adjust;
+ }
+ }
+ } else {
+ /* may need to allocate here */
+ while (cur_line + adjust > this_line) {
+ if (l->l_next == NULL) {
+ l->l_next = alloc_line();
+ l->l_next->l_prev = l;
+ }
+ l = l->l_next;
+ this_line++;
+ }
+ }
+ if (this_line > nflushd_lines &&
+ this_line - nflushd_lines >=
+ max_bufd_lines + BUFFER_MARGIN) {
+ if (extra_lines) {
+ flush_lines(extra_lines);
+ extra_lines = 0;
+ }
+ flush_lines(this_line - nflushd_lines -
+ max_bufd_lines);
+ nflushd_lines = this_line - max_bufd_lines;
+ }
+ }
+ /* grow line's buffer? */
+ if (l->l_line_len + 1 >= l->l_lsize) {
+ int need;
+
+ need = l->l_lsize ? l->l_lsize * 2 : 90;
+ if ((l->l_line = realloc(l->l_line,
+ (unsigned)need * sizeof(CHAR))) == NULL)
+ err(1, NULL);
+ l->l_lsize = need;
+ }
+ c = &l->l_line[l->l_line_len++];
+ c->c_char = ch;
+ c->c_set = cur_set;
+ c->c_column = cur_col;
+ c->c_width = wcwidth(ch);
+ /*
+ * If things are put in out of order, they will need sorting
+ * when it is flushed.
+ */
+ if (cur_col < l->l_max_col)
+ l->l_needs_sort = 1;
+ else
+ l->l_max_col = cur_col;
+ if (c->c_width > 0)
+ cur_col += c->c_width;
+ }
+ if (ferror(stdin))
+ err(1, NULL);
+ if (extra_lines) {
+ /*
+ * Extra lines only exist if no lines have been flushed
+ * yet. This means that 'lines' must point to line zero
+ * after we flush the extra lines.
+ */
+ flush_lines(extra_lines);
+ l = lines;
+ this_line = 0;
+ }
+
+ /* goto the last line that had a character on it */
+ for (; l->l_next; l = l->l_next)
+ this_line++;
+ flush_lines(this_line - nflushd_lines + 1);
+
+ /* make sure we leave things in a sane state */
+ if (last_set != CS_NORMAL)
+ PUTC(SI);
+
+ /* flush out the last few blank lines */
+ if (max_line >= this_line)
+ nblank_lines = max_line - this_line + (max_line & 1);
+ if (nblank_lines == 0)
+ /* end with a newline even if the source doesn't */
+ nblank_lines = 2;
+ flush_blanks();
+ exit(0);
+}
+
+/*
+ * Prints the first 'nflush' lines. Printed lines are freed.
+ * After this function returns, 'lines' points to the first
+ * of the remaining lines, and 'nblank_lines' will have the
+ * number of half line feeds between the final flushed line
+ * and the first remaining line.
+ */
+static void
+flush_lines(int nflush)
+{
+ LINE *l;
+
+ while (--nflush >= 0) {
+ l = lines;
+ lines = l->l_next;
+ if (l->l_line) {
+ flush_blanks();
+ flush_line(l);
+ free(l->l_line);
+ }
+ if (l->l_next)
+ nblank_lines++;
+ free_line(l);
+ }
+ if (lines)
+ lines->l_prev = NULL;
+}
+
+/*
+ * Print a number of newline/half newlines.
+ * nblank_lines is the number of half line feeds.
+ */
+static void
+flush_blanks(void)
+{
+ int half, i, nb;
+
+ half = 0;
+ nb = nblank_lines;
+ if (nb & 1) {
+ if (fine)
+ half = 1;
+ else
+ nb++;
+ }
+ nb /= 2;
+ for (i = nb; --i >= 0;)
+ PUTC('\n');
+ if (half) {
+ PUTC(ESC);
+ PUTC(FHLF);
+ if (!nb)
+ PUTC('\r');
+ }
+ nblank_lines = 0;
+}
+
+/*
+ * Write a line to stdout taking care of space to tab conversion (-h flag)
+ * and character set shifts.
+ */
+static void
+flush_line(LINE *l)
+{
+ CHAR *c, *endc;
+ int i, j, nchars, last_col, save, this_col, tot;
+
+ last_col = 0;
+ nchars = l->l_line_len;
+
+ if (l->l_needs_sort) {
+ static CHAR *sorted;
+ static int count_size, *count, sorted_size;
+
+ /*
+ * Do an O(n) sort on l->l_line by column being careful to
+ * preserve the order of characters in the same column.
+ */
+ if (l->l_lsize > sorted_size) {
+ sorted_size = l->l_lsize;
+ if ((sorted = realloc(sorted,
+ (unsigned)sizeof(CHAR) * sorted_size)) == NULL)
+ err(1, NULL);
+ }
+ if (l->l_max_col >= count_size) {
+ count_size = l->l_max_col + 1;
+ if ((count = realloc(count,
+ (unsigned)sizeof(int) * count_size)) == NULL)
+ err(1, NULL);
+ }
+ memset(count, 0, sizeof(int) * l->l_max_col + 1);
+ for (i = nchars, c = l->l_line; --i >= 0; c++)
+ count[c->c_column]++;
+
+ /*
+ * calculate running total (shifted down by 1) to use as
+ * indices into new line.
+ */
+ for (tot = 0, i = 0; i <= l->l_max_col; i++) {
+ save = count[i];
+ count[i] = tot;
+ tot += save;
+ }
+
+ for (i = nchars, c = l->l_line; --i >= 0; c++)
+ sorted[count[c->c_column]++] = *c;
+ c = sorted;
+ } else
+ c = l->l_line;
+ while (nchars > 0) {
+ this_col = c->c_column;
+ endc = c;
+ do {
+ ++endc;
+ } while (--nchars > 0 && this_col == endc->c_column);
+
+ /* if -b only print last character */
+ if (no_backspaces) {
+ c = endc - 1;
+ if (nchars > 0 &&
+ this_col + c->c_width > endc->c_column)
+ continue;
+ }
+
+ if (this_col > last_col) {
+ int nspace = this_col - last_col;
+
+ if (compress_spaces && nspace > 1) {
+ while (1) {
+ int tab_col, tab_size;
+
+ tab_col = (last_col + 8) & ~7;
+ if (tab_col > this_col)
+ break;
+ tab_size = tab_col - last_col;
+ if (tab_size == 1)
+ PUTC(' ');
+ else
+ PUTC('\t');
+ nspace -= tab_size;
+ last_col = tab_col;
+ }
+ }
+ while (--nspace >= 0)
+ PUTC(' ');
+ last_col = this_col;
+ }
+
+ for (;;) {
+ if (c->c_set != last_set) {
+ switch (c->c_set) {
+ case CS_NORMAL:
+ PUTC(SI);
+ break;
+ case CS_ALTERNATE:
+ PUTC(SO);
+ }
+ last_set = c->c_set;
+ }
+ PUTC(c->c_char);
+ if ((c + 1) < endc)
+ for (j = 0; j < c->c_width; j++)
+ PUTC('\b');
+ if (++c >= endc)
+ break;
+ }
+ last_col += (c - 1)->c_width;
+ }
+}
+
+/*
+ * Increment or decrement a line number, checking for overflow.
+ * Stop one below INT_MAX such that the adjust variable is safe.
+ */
+void
+addto_lineno(int *lno, int offset)
+{
+ if (offset > 0) {
+ if (*lno >= INT_MAX - offset)
+ errx(1, "too many lines");
+ } else {
+ if (*lno < INT_MIN - offset)
+ errx(1, "too many reverse line feeds");
+ }
+ *lno += offset;
+}
+
+#define NALLOC 64
+
+static LINE *line_freelist;
+
+static LINE *
+alloc_line(void)
+{
+ LINE *l;
+ int i;
+
+ if (!line_freelist) {
+ if ((l = realloc(NULL, sizeof(LINE) * NALLOC)) == NULL)
+ err(1, NULL);
+ line_freelist = l;
+ for (i = 1; i < NALLOC; i++, l++)
+ l->l_next = l + 1;
+ l->l_next = NULL;
+ }
+ l = line_freelist;
+ line_freelist = l->l_next;
+
+ memset(l, 0, sizeof(LINE));
+ return (l);
+}
+
+static void
+free_line(LINE *l)
+{
+
+ l->l_next = line_freelist;
+ line_freelist = l;
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: col [-bfhpx] [-l nline]\n");
+ exit(1);
+}
+
+static void
+dowarn(int line)
+{
+
+ warnx("warning: can't back up %s",
+ line < 0 ? "past first line" : "-- line already flushed");
+}
diff --git a/usr.bin/col/tests/Makefile b/usr.bin/col/tests/Makefile
new file mode 100644
index 000000000000..c51bd57a5651
--- /dev/null
+++ b/usr.bin/col/tests/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= col_test
+
+${PACKAGE}FILES+= \
+ hlf.in \
+ hlf2.in \
+ nl.in \
+ nl2.in \
+ nl3.in \
+ rlf.in \
+ rlf2.in \
+ rlf3.in
+
+.include <bsd.test.mk>
diff --git a/usr.bin/col/tests/Makefile.depend b/usr.bin/col/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/col/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/col/tests/col_test.sh b/usr.bin/col/tests/col_test.sh
new file mode 100755
index 000000000000..643760f40c39
--- /dev/null
+++ b/usr.bin/col/tests/col_test.sh
@@ -0,0 +1,112 @@
+
+atf_test_case nl
+
+nl_head()
+{
+ atf_set "descr" "testing just newlines"
+}
+nl_body()
+{
+ atf_check \
+ -o inline:"a\nb\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/nl.in
+
+ atf_check \
+ -o inline:"a\nb\n" \
+ -e empty \
+ -s exit:0 \
+ col -f < $(atf_get_srcdir)/nl.in
+
+ atf_check \
+ -o inline:"a\nb\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/nl2.in
+
+ atf_check \
+ -o inline:"a\nb\n" \
+ -e empty \
+ -s exit:0 \
+ col -f < $(atf_get_srcdir)/nl2.in
+
+ atf_check \
+ -o inline:"a\n\nb\n\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/nl3.in
+}
+
+atf_test_case rlf
+
+rlf_head()
+{
+ atf_set "descr" "testing reverse line feed"
+}
+rlf_body()
+{
+ atf_check \
+ -o inline:"a b\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/rlf.in
+
+ atf_check \
+ -o inline:"a b\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/rlf2.in
+
+ atf_check \
+ -o inline:"a b\n" \
+ -e empty \
+ -s exit:0 \
+ col -x < $(atf_get_srcdir)/rlf2.in
+
+ atf_check \
+ -o inline:" b\na\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/rlf3.in
+}
+
+atf_test_case hlf
+
+hlf_head()
+{
+ atf_set "descr" "testing half line feed"
+}
+hlf_body()
+{
+ atf_check \
+ -o inline:"a f\naf\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/hlf.in
+
+ atf_check \
+ -o inline:"a f9 f9 a\n" \
+ -e empty \
+ -s exit:0 \
+ col -f < $(atf_get_srcdir)/hlf.in
+
+ atf_check \
+ -o inline:"a\n f\n" \
+ -e empty \
+ -s exit:0 \
+ col < $(atf_get_srcdir)/hlf2.in
+
+ atf_check \
+ -o inline:"a9 f\n9" \
+ -e empty \
+ -s exit:0 \
+ col -f < $(atf_get_srcdir)/hlf2.in
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case nl
+ atf_add_test_case rlf
+ atf_add_test_case hlf
+}
diff --git a/usr.bin/col/tests/hlf.in b/usr.bin/col/tests/hlf.in
new file mode 100644
index 000000000000..68b877a38f0f
--- /dev/null
+++ b/usr.bin/col/tests/hlf.in
@@ -0,0 +1,2 @@
+a
+a8f8f
diff --git a/usr.bin/col/tests/hlf2.in b/usr.bin/col/tests/hlf2.in
new file mode 100644
index 000000000000..f32626cad7f3
--- /dev/null
+++ b/usr.bin/col/tests/hlf2.in
@@ -0,0 +1 @@
+a9f
diff --git a/usr.bin/col/tests/nl.in b/usr.bin/col/tests/nl.in
new file mode 100644
index 000000000000..422c2b7ab3b3
--- /dev/null
+++ b/usr.bin/col/tests/nl.in
@@ -0,0 +1,2 @@
+a
+b
diff --git a/usr.bin/col/tests/nl2.in b/usr.bin/col/tests/nl2.in
new file mode 100644
index 000000000000..0a207c060e61
--- /dev/null
+++ b/usr.bin/col/tests/nl2.in
@@ -0,0 +1,2 @@
+a
+b \ No newline at end of file
diff --git a/usr.bin/col/tests/nl3.in b/usr.bin/col/tests/nl3.in
new file mode 100644
index 000000000000..bd9430af9840
--- /dev/null
+++ b/usr.bin/col/tests/nl3.in
@@ -0,0 +1,4 @@
+a
+
+b
+
diff --git a/usr.bin/col/tests/rlf.in b/usr.bin/col/tests/rlf.in
new file mode 100644
index 000000000000..57a14e5771b7
--- /dev/null
+++ b/usr.bin/col/tests/rlf.in
@@ -0,0 +1,2 @@
+a
+ 7b
diff --git a/usr.bin/col/tests/rlf2.in b/usr.bin/col/tests/rlf2.in
new file mode 100644
index 000000000000..dd4685174dd7
--- /dev/null
+++ b/usr.bin/col/tests/rlf2.in
@@ -0,0 +1,2 @@
+a
+ 7b
diff --git a/usr.bin/col/tests/rlf3.in b/usr.bin/col/tests/rlf3.in
new file mode 100644
index 000000000000..addbeb298820
--- /dev/null
+++ b/usr.bin/col/tests/rlf3.in
@@ -0,0 +1 @@
+a b
diff --git a/usr.bin/colrm/Makefile b/usr.bin/colrm/Makefile
new file mode 100644
index 000000000000..0da3b5a30c37
--- /dev/null
+++ b/usr.bin/colrm/Makefile
@@ -0,0 +1,3 @@
+PROG= colrm
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/colrm/Makefile.depend b/usr.bin/colrm/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/colrm/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/colrm/colrm.1 b/usr.bin/colrm/colrm.1
new file mode 100644
index 000000000000..d664eaf0edd2
--- /dev/null
+++ b/usr.bin/colrm/colrm.1
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd June 23, 2020
+.Dt COLRM 1
+.Os
+.Sh NAME
+.Nm colrm
+.Nd remove columns from a file
+.Sh SYNOPSIS
+.Nm
+.Op Ar start Op Ar stop
+.Sh DESCRIPTION
+The
+.Nm
+utility removes selected columns from the lines of a file.
+A column is defined as a single character in a line.
+Input is read from the standard input.
+Output is written to the standard output.
+.Pp
+If only the
+.Ar start
+column is specified, columns numbered less than the
+.Ar start
+column will be written.
+If both
+.Ar start
+and
+.Ar stop
+columns are specified, columns numbered less than the
+.Ar start
+column
+or greater than the
+.Ar stop
+column will be written.
+Column numbering starts with one, not zero.
+.Pp
+Tab characters increment the column count to the next multiple of eight.
+Backspace characters decrement the column count by one.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show columns below 3 (c) and above 5 (e):
+.Bd -literal -offset indent
+$ echo -e "abcdefgh\en12345678" | colrm 3 5
+abfgh
+12678
+.Ed
+.Pp
+Specifying a start column bigger than the number of columns in the file is
+allowed and shows all the columns:
+.Bd -literal -offset indent
+$ echo "abcdefgh" | colrm 100
+abcdefgh
+.Ed
+.Pp
+Using 1 as start column will show nothing:
+.Bd -literal -offset indent
+$ echo "abcdefgh" | colrm 1
+
+.Ed
+.Sh SEE ALSO
+.Xr awk 1 ,
+.Xr column 1 ,
+.Xr cut 1 ,
+.Xr paste 1
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 1 .
+.Sh AUTHORS
+.An Jeff Schriebman
+wrote the original version of
+.Nm
+in November 1974.
diff --git a/usr.bin/colrm/colrm.c b/usr.bin/colrm/colrm.c
new file mode 100644
index 000000000000..20bbd6e9a622
--- /dev/null
+++ b/usr.bin/colrm/colrm.c
@@ -0,0 +1,134 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include <capsicum_helpers.h>
+
+#define TAB 8
+
+void check(FILE *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ u_long column, start, stop;
+ int ch, width;
+ char *p;
+
+ setlocale(LC_ALL, "");
+
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(EXIT_FAILURE, "capsicum");
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ start = stop = 0;
+ switch(argc) {
+ case 2:
+ stop = strtol(argv[1], &p, 10);
+ if (stop <= 0 || *p)
+ errx(EXIT_FAILURE, "illegal column -- %s", argv[1]);
+ /* FALLTHROUGH */
+ case 1:
+ start = strtol(argv[0], &p, 10);
+ if (start <= 0 || *p)
+ errx(EXIT_FAILURE, "illegal column -- %s", argv[0]);
+ break;
+ case 0:
+ break;
+ default:
+ usage();
+ }
+
+ if (stop && start > stop)
+ errx(EXIT_FAILURE, "illegal start and stop columns");
+
+ for (column = 0;;) {
+ switch (ch = getwchar()) {
+ case WEOF:
+ check(stdin);
+ break;
+ case '\b':
+ if (column)
+ --column;
+ break;
+ case '\n':
+ column = 0;
+ break;
+ case '\t':
+ column = (column + TAB) & ~(TAB - 1);
+ break;
+ default:
+ if ((width = wcwidth(ch)) > 0)
+ column += width;
+ break;
+ }
+
+ if ((!start || column < start || (stop && column > stop)) &&
+ putwchar(ch) == WEOF)
+ check(stdout);
+ }
+}
+
+void
+check(FILE *stream)
+{
+ if (feof(stream))
+ exit(EXIT_SUCCESS);
+ if (ferror(stream))
+ err(EXIT_FAILURE, "%s", stream == stdin ? "stdin" : "stdout");
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: colrm [start [stop]]\n");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/column/Makefile b/usr.bin/column/Makefile
new file mode 100644
index 000000000000..b0b88c086b41
--- /dev/null
+++ b/usr.bin/column/Makefile
@@ -0,0 +1,3 @@
+PROG= column
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/column/Makefile.depend b/usr.bin/column/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/column/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/column/column.1 b/usr.bin/column/column.1
new file mode 100644
index 000000000000..4481fccf2c3d
--- /dev/null
+++ b/usr.bin/column/column.1
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1989, 1990, 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.
+.\"
+.Dd July 29, 2004
+.Dt COLUMN 1
+.Os
+.Sh NAME
+.Nm column
+.Nd columnate lists
+.Sh SYNOPSIS
+.Nm
+.Op Fl tx
+.Op Fl c Ar columns
+.Op Fl s Ar sep
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility formats its input into multiple columns.
+Rows are filled before columns.
+Input is taken from
+.Ar file
+operands, or, by default, from the standard input.
+Empty lines are ignored.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl c
+Output is formatted for a display
+.Ar columns
+wide.
+.It Fl s
+Specify a set of characters to be used to delimit columns for the
+.Fl t
+option.
+.It Fl t
+Determine the number of columns the input contains and create a table.
+Columns are delimited with whitespace, by default, or with the characters
+supplied using the
+.Fl s
+option.
+Useful for pretty-printing displays.
+.It Fl x
+Fill columns before filling rows.
+.El
+.Sh ENVIRONMENT
+The
+.Ev COLUMNS , LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Dl (printf \&"PERM LINKS OWNER GROUP SIZE MONTH DAY \&"\ \&;\ \&\e
+.Dl printf \&"HH:MM/YEAR NAME\en\&"\ \&;\ \&\e
+.Dl ls -l \&| sed 1d) \&| column -t
+.Sh SEE ALSO
+.Xr colrm 1 ,
+.Xr ls 1 ,
+.Xr paste 1 ,
+.Xr sort 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 Reno .
+.Sh BUGS
+Input lines are limited to
+.Dv LINE_MAX
+(2048) bytes in length.
diff --git a/usr.bin/column/column.c b/usr.bin/column/column.c
new file mode 100644
index 000000000000..d1322312f8fa
--- /dev/null
+++ b/usr.bin/column/column.c
@@ -0,0 +1,326 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define TAB 8
+
+static void c_columnate(void);
+static void input(FILE *);
+static void maketbl(void);
+static void print(void);
+static void r_columnate(void);
+static void usage(void);
+static int width(const wchar_t *);
+
+static int termwidth = 80; /* default terminal width */
+
+static int entries; /* number of records */
+static int eval; /* exit value */
+static int maxlength; /* longest record */
+static wchar_t **list; /* array of pointers to records */
+static const wchar_t *separator = L"\t "; /* field separator for table option */
+
+int
+main(int argc, char **argv)
+{
+ struct winsize win;
+ FILE *fp;
+ int ch, tflag, xflag;
+ char *p;
+ const char *src;
+ wchar_t *newsep;
+ size_t seplen;
+
+ setlocale(LC_ALL, "");
+
+ if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
+ if ((p = getenv("COLUMNS")))
+ termwidth = atoi(p);
+ } else
+ termwidth = win.ws_col;
+
+ tflag = xflag = 0;
+ while ((ch = getopt(argc, argv, "c:s:tx")) != -1)
+ switch(ch) {
+ case 'c':
+ termwidth = atoi(optarg);
+ break;
+ case 's':
+ src = optarg;
+ seplen = mbsrtowcs(NULL, &src, 0, NULL);
+ if (seplen == (size_t)-1)
+ err(1, "bad separator");
+ newsep = malloc((seplen + 1) * sizeof(wchar_t));
+ if (newsep == NULL)
+ err(1, NULL);
+ mbsrtowcs(newsep, &src, seplen + 1, NULL);
+ separator = newsep;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!*argv)
+ input(stdin);
+ else for (; *argv; ++argv)
+ if ((fp = fopen(*argv, "r"))) {
+ input(fp);
+ (void)fclose(fp);
+ } else {
+ warn("%s", *argv);
+ eval = 1;
+ }
+
+ if (!entries)
+ exit(eval);
+
+ maxlength = roundup(maxlength + 1, TAB);
+ if (tflag)
+ maketbl();
+ else if (maxlength >= termwidth)
+ print();
+ else if (xflag)
+ c_columnate();
+ else
+ r_columnate();
+ exit(eval);
+}
+
+static void
+c_columnate(void)
+{
+ int chcnt, col, cnt, endcol, numcols;
+ wchar_t **lp;
+
+ numcols = termwidth / maxlength;
+ endcol = maxlength;
+ for (chcnt = col = 0, lp = list;; ++lp) {
+ wprintf(L"%ls", *lp);
+ chcnt += width(*lp);
+ if (!--entries)
+ break;
+ if (++col == numcols) {
+ chcnt = col = 0;
+ endcol = maxlength;
+ putwchar('\n');
+ } else {
+ while ((cnt = roundup(chcnt + 1, TAB)) <= endcol) {
+ (void)putwchar('\t');
+ chcnt = cnt;
+ }
+ endcol += maxlength;
+ }
+ }
+ if (chcnt)
+ putwchar('\n');
+}
+
+static void
+r_columnate(void)
+{
+ int base, chcnt, cnt, col, endcol, numcols, numrows, row;
+
+ numcols = termwidth / maxlength;
+ numrows = entries / numcols;
+ if (entries % numcols)
+ ++numrows;
+
+ for (row = 0; row < numrows; ++row) {
+ endcol = maxlength;
+ for (base = row, chcnt = col = 0; col < numcols; ++col) {
+ wprintf(L"%ls", list[base]);
+ chcnt += width(list[base]);
+ if ((base += numrows) >= entries)
+ break;
+ while ((cnt = roundup(chcnt + 1, TAB)) <= endcol) {
+ (void)putwchar('\t');
+ chcnt = cnt;
+ }
+ endcol += maxlength;
+ }
+ putwchar('\n');
+ }
+}
+
+static void
+print(void)
+{
+ int cnt;
+ wchar_t **lp;
+
+ for (cnt = entries, lp = list; cnt--; ++lp)
+ (void)wprintf(L"%ls\n", *lp);
+}
+
+typedef struct _tbl {
+ wchar_t **list;
+ int cols, *len;
+} TBL;
+#define DEFCOLS 25
+
+static void
+maketbl(void)
+{
+ TBL *t;
+ int coloff, cnt;
+ wchar_t *p, **lp;
+ int *lens, maxcols;
+ TBL *tbl;
+ wchar_t **cols;
+ wchar_t *last;
+
+ if ((t = tbl = calloc(entries, sizeof(TBL))) == NULL)
+ err(1, NULL);
+ if ((cols = calloc((maxcols = DEFCOLS), sizeof(*cols))) == NULL)
+ err(1, NULL);
+ if ((lens = calloc(maxcols, sizeof(int))) == NULL)
+ err(1, NULL);
+ for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
+ for (coloff = 0, p = *lp;
+ (cols[coloff] = wcstok(p, separator, &last));
+ p = NULL)
+ if (++coloff == maxcols) {
+ if (!(cols = realloc(cols, ((u_int)maxcols +
+ DEFCOLS) * sizeof(wchar_t *))) ||
+ !(lens = realloc(lens,
+ ((u_int)maxcols + DEFCOLS) * sizeof(int))))
+ err(1, NULL);
+ memset((char *)lens + maxcols * sizeof(int),
+ 0, DEFCOLS * sizeof(int));
+ maxcols += DEFCOLS;
+ }
+ if ((t->list = calloc(coloff, sizeof(*t->list))) == NULL)
+ err(1, NULL);
+ if ((t->len = calloc(coloff, sizeof(int))) == NULL)
+ err(1, NULL);
+ for (t->cols = coloff; --coloff >= 0;) {
+ t->list[coloff] = cols[coloff];
+ t->len[coloff] = width(cols[coloff]);
+ if (t->len[coloff] > lens[coloff])
+ lens[coloff] = t->len[coloff];
+ }
+ }
+ for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
+ for (coloff = 0; coloff < t->cols - 1; ++coloff)
+ (void)wprintf(L"%ls%*ls", t->list[coloff],
+ lens[coloff] - t->len[coloff] + 2, L" ");
+ (void)wprintf(L"%ls\n", t->list[coloff]);
+ free(t->list);
+ free(t->len);
+ }
+ free(lens);
+ free(cols);
+ free(tbl);
+}
+
+#define DEFNUM 1000
+#define MAXLINELEN (LINE_MAX + 1)
+
+static void
+input(FILE *fp)
+{
+ static int maxentry;
+ int len;
+ wchar_t *p, buf[MAXLINELEN];
+
+ if (!list)
+ if ((list = calloc((maxentry = DEFNUM), sizeof(*list))) ==
+ NULL)
+ err(1, NULL);
+ while (fgetws(buf, MAXLINELEN, fp)) {
+ for (p = buf; *p && iswspace(*p); ++p);
+ if (!*p)
+ continue;
+ if (!(p = wcschr(p, L'\n'))) {
+ warnx("line too long");
+ eval = 1;
+ continue;
+ }
+ *p = L'\0';
+ len = width(buf);
+ if (maxlength < len)
+ maxlength = len;
+ if (entries == maxentry) {
+ maxentry += DEFNUM;
+ if (!(list = realloc(list,
+ (u_int)maxentry * sizeof(*list))))
+ err(1, NULL);
+ }
+ list[entries] = malloc((wcslen(buf) + 1) * sizeof(wchar_t));
+ if (list[entries] == NULL)
+ err(1, NULL);
+ wcscpy(list[entries], buf);
+ entries++;
+ }
+}
+
+/* Like wcswidth(), but ignores non-printing characters. */
+static int
+width(const wchar_t *wcs)
+{
+ int w, cw;
+
+ for (w = 0; *wcs != L'\0'; wcs++)
+ if ((cw = wcwidth(*wcs)) > 0)
+ w += cw;
+ return (w);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: column [-tx] [-c columns] [-s sep] [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/comm/Makefile b/usr.bin/comm/Makefile
new file mode 100644
index 000000000000..03eabaf8704b
--- /dev/null
+++ b/usr.bin/comm/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= comm
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/comm/Makefile.depend b/usr.bin/comm/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/comm/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/comm/comm.1 b/usr.bin/comm/comm.1
new file mode 100644
index 000000000000..8130381e3ac4
--- /dev/null
+++ b/usr.bin/comm/comm.1
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd July 27, 2020
+.Dt COMM 1
+.Os
+.Sh NAME
+.Nm comm
+.Nd select or reject lines common to two files
+.Sh SYNOPSIS
+.Nm
+.Op Fl 123i
+.Ar file1 file2
+.Sh DESCRIPTION
+The
+.Nm
+utility reads
+.Ar file1
+and
+.Ar file2 ,
+which should be
+sorted lexically, and produces three text
+columns as output: lines only in
+.Ar file1 ;
+lines only in
+.Ar file2 ;
+and lines in both files.
+.Pp
+The filename ``-'' means the standard input.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl 1
+Suppress printing of column 1, lines only in
+.Ar file1 .
+.It Fl 2
+Suppress printing of column 2, lines only in
+.Ar file2 .
+.It Fl 3
+Suppress printing of column 3, lines common to both.
+.It Fl i
+Case insensitive comparison of lines.
+.El
+.Pp
+Each column will have a number of tab characters prepended to it
+equal to the number of lower numbered columns that are being printed.
+For example, if column number two is being suppressed, lines printed
+in column number one will not have any tabs preceding them, and lines
+printed in column number three will have one.
+.Pp
+The
+.Nm
+utility assumes that the files are lexically sorted; all characters
+participate in line comparisons.
+.Sh ENVIRONMENT
+The
+.Ev LANG ,
+.Ev LC_ALL ,
+.Ev LC_COLLATE ,
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Assuming a file named
+.Pa example.txt
+with the following contents:
+.Bd -literal -offset indent
+a
+b
+c
+d
+.Ed
+.Pp
+Show lines only in
+.Pa example.txt ,
+lines only in stdin and common lines:
+.Bd -literal -offset indent
+$ echo -e "B\enc" | comm example.txt -
+ B
+a
+b
+ c
+d
+.Ed
+.Pp
+Show only common lines doing case insensitive comparisons:
+.Bd -literal -offset indent
+$ echo -e "B\enc" | comm -1 -2 -i example.txt -
+b
+c
+.Ed
+.Sh SEE ALSO
+.Xr cmp 1 ,
+.Xr diff 1 ,
+.Xr sort 1 ,
+.Xr uniq 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.2-92 .
+.Pp
+The
+.Fl i
+option is an extension to the POSIX standard.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v4 .
diff --git a/usr.bin/comm/comm.c b/usr.bin/comm/comm.c
new file mode 100644
index 000000000000..4dcd7cc9a2dd
--- /dev/null
+++ b/usr.bin/comm/comm.c
@@ -0,0 +1,239 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Case Larsen.
+ *
+ * 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 <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+static int iflag;
+static const char *tabs[] = { "", "\t", "\t\t" };
+
+static FILE *file(const char *);
+static wchar_t *convert(const char *);
+static void show(FILE *, const char *, const char *, char **, size_t *);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int comp, read1, read2;
+ int ch, flag1, flag2, flag3;
+ FILE *fp1, *fp2;
+ const char *col1, *col2, *col3;
+ size_t line1len, line2len;
+ char *line1, *line2;
+ ssize_t n1, n2;
+ wchar_t *tline1, *tline2;
+ const char **p;
+
+ (void) setlocale(LC_ALL, "");
+
+ flag1 = flag2 = flag3 = 1;
+
+ while ((ch = getopt(argc, argv, "123i")) != -1)
+ switch(ch) {
+ case '1':
+ flag1 = 0;
+ break;
+ case '2':
+ flag2 = 0;
+ break;
+ case '3':
+ flag3 = 0;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ fp1 = file(argv[0]);
+ fp2 = file(argv[1]);
+
+ /* for each column printed, add another tab offset */
+ p = tabs;
+ col1 = col2 = col3 = NULL;
+ if (flag1)
+ col1 = *p++;
+ if (flag2)
+ col2 = *p++;
+ if (flag3)
+ col3 = *p;
+
+ line1len = line2len = 0;
+ line1 = line2 = NULL;
+ n1 = n2 = -1;
+
+ for (read1 = read2 = 1;;) {
+ /* read next line, check for EOF */
+ if (read1) {
+ n1 = getline(&line1, &line1len, fp1);
+ if (n1 < 0 && ferror(fp1))
+ err(1, "%s", argv[0]);
+ if (n1 > 0 && line1[n1 - 1] == '\n')
+ line1[n1 - 1] = '\0';
+
+ }
+ if (read2) {
+ n2 = getline(&line2, &line2len, fp2);
+ if (n2 < 0 && ferror(fp2))
+ err(1, "%s", argv[1]);
+ if (n2 > 0 && line2[n2 - 1] == '\n')
+ line2[n2 - 1] = '\0';
+ }
+
+ /* if one file done, display the rest of the other file */
+ if (n1 < 0) {
+ if (n2 >= 0)
+ show(fp2, argv[1], col2, &line2, &line2len);
+ break;
+ }
+ if (n2 < 0) {
+ if (n1 >= 0)
+ show(fp1, argv[0], col1, &line1, &line1len);
+ break;
+ }
+
+ tline2 = NULL;
+ if ((tline1 = convert(line1)) != NULL)
+ tline2 = convert(line2);
+ if (tline1 == NULL || tline2 == NULL)
+ comp = strcmp(line1, line2);
+ else
+ comp = wcscoll(tline1, tline2);
+ if (tline1 != NULL)
+ free(tline1);
+ if (tline2 != NULL)
+ free(tline2);
+
+ /* lines are the same */
+ if (!comp) {
+ read1 = read2 = 1;
+ if (col3 != NULL)
+ (void)printf("%s%s\n", col3, line1);
+ continue;
+ }
+
+ /* lines are different */
+ if (comp < 0) {
+ read1 = 1;
+ read2 = 0;
+ if (col1 != NULL)
+ (void)printf("%s%s\n", col1, line1);
+ } else {
+ read1 = 0;
+ read2 = 1;
+ if (col2 != NULL)
+ (void)printf("%s%s\n", col2, line2);
+ }
+ }
+ if (ferror(stdout) != 0 || fflush(stdout) != 0)
+ err(1, "stdout");
+ exit(0);
+}
+
+static wchar_t *
+convert(const char *str)
+{
+ size_t n;
+ wchar_t *buf, *p;
+
+ if ((n = mbstowcs(NULL, str, 0)) == (size_t)-1)
+ return (NULL);
+ if (SIZE_MAX / sizeof(*buf) < n + 1)
+ errx(1, "conversion buffer length overflow");
+ if ((buf = malloc((n + 1) * sizeof(*buf))) == NULL)
+ err(1, "malloc");
+ if (mbstowcs(buf, str, n + 1) != n)
+ errx(1, "internal mbstowcs() error");
+
+ if (iflag) {
+ for (p = buf; *p != L'\0'; p++)
+ *p = towlower(*p);
+ }
+
+ return (buf);
+}
+
+static void
+show(FILE *fp, const char *fn, const char *offset, char **bufp, size_t *buflenp)
+{
+ ssize_t n;
+
+ do {
+ /* offset is NULL when draining fp, not printing */
+ if (offset != NULL)
+ (void)printf("%s%s\n", offset, *bufp);
+ if ((n = getline(bufp, buflenp, fp)) < 0)
+ break;
+ if (n > 0 && offset != NULL && (*bufp)[n - 1] == '\n')
+ (*bufp)[n - 1] = '\0';
+ } while (1);
+ if (ferror(fp))
+ err(1, "%s", fn);
+}
+
+static FILE *
+file(const char *name)
+{
+ FILE *fp;
+
+ if (!strcmp(name, "-"))
+ return (stdin);
+ if ((fp = fopen(name, "r")) == NULL) {
+ err(1, "%s", name);
+ }
+ return (fp);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: comm [-123i] file1 file2\n");
+ exit(1);
+}
diff --git a/usr.bin/comm/tests/Makefile b/usr.bin/comm/tests/Makefile
new file mode 100644
index 000000000000..85ba59ad4ccb
--- /dev/null
+++ b/usr.bin/comm/tests/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.00.out
+${PACKAGE}FILES+= regress.00a.in
+${PACKAGE}FILES+= regress.00b.in
+${PACKAGE}FILES+= regress.01.out
+${PACKAGE}FILES+= regress.01a.in
+${PACKAGE}FILES+= regress.01b.in
+${PACKAGE}FILES+= regress.02.out
+${PACKAGE}FILES+= regress.02a.in
+${PACKAGE}FILES+= regress.02b.in
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/comm/tests/Makefile.depend b/usr.bin/comm/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/comm/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/comm/tests/legacy_test.sh b/usr.bin/comm/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/comm/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/comm/tests/regress.00.out b/usr.bin/comm/tests/regress.00.out
new file mode 100644
index 000000000000..89a65daab380
--- /dev/null
+++ b/usr.bin/comm/tests/regress.00.out
@@ -0,0 +1,2 @@
+a b
+e f g
diff --git a/usr.bin/comm/tests/regress.00a.in b/usr.bin/comm/tests/regress.00a.in
new file mode 100644
index 000000000000..85b5cd53a6bf
--- /dev/null
+++ b/usr.bin/comm/tests/regress.00a.in
@@ -0,0 +1,5 @@
+a b
+c d
+e f
+e f g
+h i
diff --git a/usr.bin/comm/tests/regress.00b.in b/usr.bin/comm/tests/regress.00b.in
new file mode 100644
index 000000000000..89a65daab380
--- /dev/null
+++ b/usr.bin/comm/tests/regress.00b.in
@@ -0,0 +1,2 @@
+a b
+e f g
diff --git a/usr.bin/comm/tests/regress.01.out b/usr.bin/comm/tests/regress.01.out
new file mode 100644
index 000000000000..05ab154ecba2
--- /dev/null
+++ b/usr.bin/comm/tests/regress.01.out
@@ -0,0 +1,2 @@
+a b
+e f g
diff --git a/usr.bin/comm/tests/regress.01a.in b/usr.bin/comm/tests/regress.01a.in
new file mode 100644
index 000000000000..78c410b7d759
--- /dev/null
+++ b/usr.bin/comm/tests/regress.01a.in
@@ -0,0 +1,5 @@
+a b
+c d
+e f
+e f g
+h i
diff --git a/usr.bin/comm/tests/regress.01b.in b/usr.bin/comm/tests/regress.01b.in
new file mode 100644
index 000000000000..05ab154ecba2
--- /dev/null
+++ b/usr.bin/comm/tests/regress.01b.in
@@ -0,0 +1,2 @@
+a b
+e f g
diff --git a/usr.bin/comm/tests/regress.02.out b/usr.bin/comm/tests/regress.02.out
new file mode 100644
index 000000000000..a451adbbb245
--- /dev/null
+++ b/usr.bin/comm/tests/regress.02.out
@@ -0,0 +1,5 @@
+a
+b
+ c
+ d
+ e
diff --git a/usr.bin/comm/tests/regress.02a.in b/usr.bin/comm/tests/regress.02a.in
new file mode 100644
index 000000000000..1c943a988877
--- /dev/null
+++ b/usr.bin/comm/tests/regress.02a.in
@@ -0,0 +1,3 @@
+a
+b
+c \ No newline at end of file
diff --git a/usr.bin/comm/tests/regress.02b.in b/usr.bin/comm/tests/regress.02b.in
new file mode 100644
index 000000000000..36019ee78df9
--- /dev/null
+++ b/usr.bin/comm/tests/regress.02b.in
@@ -0,0 +1,3 @@
+c
+d
+e \ No newline at end of file
diff --git a/usr.bin/comm/tests/regress.sh b/usr.bin/comm/tests/regress.sh
new file mode 100644
index 000000000000..b5f6808a62d9
--- /dev/null
+++ b/usr.bin/comm/tests/regress.sh
@@ -0,0 +1,10 @@
+
+echo 1..3
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`00', `comm -12 ${SRCDIR}/regress.00a.in ${SRCDIR}/regress.00b.in')
+REGRESSION_TEST(`01', `comm -12 ${SRCDIR}/regress.01a.in ${SRCDIR}/regress.01b.in')
+REGRESSION_TEST(`02', `comm ${SRCDIR}/regress.02a.in ${SRCDIR}/regress.02b.in')
+
+REGRESSION_END()
diff --git a/usr.bin/compile_et/Makefile b/usr.bin/compile_et/Makefile
new file mode 100644
index 000000000000..621ba3dd101d
--- /dev/null
+++ b/usr.bin/compile_et/Makefile
@@ -0,0 +1,23 @@
+.PATH: ${SRCTOP}/contrib/com_err
+
+PACKAGE= kerberos
+
+PROG= compile_et
+SRCS= compile_et.c parse.y lex.l
+.if defined(BOOTSTRAPPING)
+# compiler_et does not need the full libroken but just a bunch of the file
+# in there, the buildsystem we have will trigger the full dependency chain
+# when linking statically including libcrypt, which is a ldscript, not
+# supported by macOS ar(1).
+LIBROKEN_A= ${.OBJDIR:H:H}/kerberos5/lib/libroken/libroken.a
+LDADD= ${LIBROKEN_A}
+DPADD= ${LIBROKEN_A}
+.else
+LIBADD= roken
+.endif
+LIBADD+= vers
+CFLAGS+=-I. -I${SRCTOP}/contrib/com_err
+
+WARNS?= 0
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/compile_et/Makefile.depend b/usr.bin/compile_et/Makefile.depend
new file mode 100644
index 000000000000..33410513c3d3
--- /dev/null
+++ b/usr.bin/compile_et/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ kerberos5/lib/libroken \
+ kerberos5/lib/libvers \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/compress/Makefile b/usr.bin/compress/Makefile
new file mode 100644
index 000000000000..1c62ad96a74e
--- /dev/null
+++ b/usr.bin/compress/Makefile
@@ -0,0 +1,14 @@
+.include <src.opts.mk>
+
+PROG= compress
+SRCS= compress.c zopen.c
+LINKS= ${BINDIR}/compress ${BINDIR}/uncompress
+MLINKS= compress.1 uncompress.1
+
+# XXX zopen is not part of libc
+# MAN=zopen.3
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/compress/Makefile.depend b/usr.bin/compress/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/compress/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/compress/compress.1 b/usr.bin/compress/compress.1
new file mode 100644
index 000000000000..4d687b9e8492
--- /dev/null
+++ b/usr.bin/compress/compress.1
@@ -0,0 +1,293 @@
+.\" Copyright (c) 1986, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" James A. Woods, derived from original work by Spencer Thomas
+.\" and Joseph Orost.
+.\"
+.\" 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.
+.\"
+.Dd March 4, 2021
+.Dt COMPRESS 1
+.Os
+.Sh NAME
+.Nm compress ,
+.Nm uncompress
+.Nd compress and expand data
+.Sh SYNOPSIS
+.Nm
+.Op Fl fv
+.Op Fl b Ar bits
+.Op Ar
+.Nm
+.Fl c
+.Op Fl b Ar bits
+.Op Ar file
+.Nm uncompress
+.Op Fl f
+.Op Ar
+.Nm uncompress
+.Fl c
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility reduces the size of files using adaptive Lempel-Ziv coding.
+Each
+.Ar file
+is renamed to the same name plus the extension
+.Pa .Z .
+A
+.Ar file
+argument with a
+.Pa .Z
+extension will be ignored except it will cause an
+error exit after other arguments are processed.
+If compression would not reduce the size of a
+.Ar file ,
+the file is ignored.
+.Pp
+The
+.Nm uncompress
+utility restores compressed files to their original form, renaming the
+files by deleting the
+.Pa .Z
+extensions.
+A file specification need not include the file's
+.Pa .Z
+extension.
+If a file's name in its file system does not have a
+.Pa .Z
+extension, it will not be uncompressed and it will cause
+an error exit after other arguments are processed.
+.Pp
+If renaming the files would cause files to be overwritten and the standard
+input device is a terminal, the user is prompted (on the standard error
+output) for confirmation.
+If prompting is not possible or confirmation is not received, the files
+are not overwritten.
+.Pp
+As many of the modification time, access time, file flags, file mode,
+user ID, and group ID as allowed by permissions are retained in the
+new file.
+.Pp
+If no files are specified or a
+.Ar file
+argument is a single dash
+.Pq Sq Fl ,
+the standard input is compressed or uncompressed to the standard output.
+If either the input and output files are not regular files, the checks for
+reduction in size and file overwriting are not performed, the input file is
+not removed, and the attributes of the input file are not retained
+in the output file.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl b Ar bits"
+.It Fl b Ar bits
+The code size (see below) is limited to
+.Ar bits ,
+which must be in the range 9..16.
+The default is 16.
+.It Fl c
+Compressed or uncompressed output is written to the standard output.
+No files are modified.
+The
+.Fl v
+option is ignored.
+Compression is attempted even if the results will be larger than the
+original.
+.It Fl f
+Files are overwritten without prompting for confirmation.
+Also, for
+.Nm compress ,
+files are compressed even if they are not actually reduced in size.
+.It Fl v
+Print the percentage reduction of each file.
+Ignored by
+.Nm uncompress
+or if the
+.Fl c
+option is also used.
+.El
+.Pp
+The
+.Nm
+utility uses a modified Lempel-Ziv algorithm.
+Common substrings in the file are first replaced by 9-bit codes 257 and up.
+When code 512 is reached, the algorithm switches to 10-bit codes and
+continues to use more bits until the
+limit specified by the
+.Fl b
+option or its default is reached.
+.Pp
+After the limit is reached,
+.Nm
+periodically checks the compression ratio.
+If it is increasing,
+.Nm
+continues to use the existing code dictionary.
+However, if the compression ratio decreases,
+.Nm
+discards the table of substrings and rebuilds it from scratch.
+This allows
+the algorithm to adapt to the next "block" of the file.
+.Pp
+The
+.Fl b
+option is unavailable for
+.Nm uncompress
+since the
+.Ar bits
+parameter specified during compression
+is encoded within the output, along with
+a magic number to ensure that neither decompression of random data nor
+recompression of compressed data is attempted.
+.Pp
+The amount of compression obtained depends on the size of the
+input, the number of
+.Ar bits
+per code, and the distribution of common substrings.
+Typically, text such as source code or English is reduced by 50\-60%.
+Compression is generally much better than that achieved by Huffman
+coding (as used in the historical command pack), or adaptive Huffman
+coding (as used in the historical command compact), and takes less
+time to compute.
+.Pp
+If
+.Ar file
+is a soft or hard link
+.Nm
+will replace it with a compressed copy of the file pointed to by the link.
+The link's target file is left uncompressed.
+.Sh EXIT STATUS
+.Ex -std compress uncompress
+.Pp
+The
+.Nm compress
+utility exits 2 if attempting to compress a file would not reduce its size
+and the
+.Fl f
+option was not specified and if no other error occurs.
+.Sh EXAMPLES
+Create a file
+.Pa test_file
+with a single line of text:
+.Bd -literal -offset indent
+echo "This is a test" > test_file
+.Ed
+.Pp
+Try to reduce the size of the file using a 10-bit code and show the exit status:
+.Bd -literal -offset indent
+$ compress -b 10 test_file
+$ echo $?
+2
+.Ed
+.Pp
+Try to compress the file and show compression percentage:
+.Bd -literal -offset indent
+$ compress -v test_file
+test_file: file would grow; left unmodified
+.Ed
+.Pp
+Same as above but forcing compression:
+.Bd -literal -offset indent
+$ compress -f -v test_file
+test_file.Z: 79% expansion
+.Ed
+.Pp
+Compress and uncompress the string
+.Ql hello
+on the fly:
+.Bd -literal -offset indent
+$ echo "hello" | compress | uncompress
+hello
+.Ed
+.Sh SEE ALSO
+.Xr gunzip 1 ,
+.Xr gzexe 1 ,
+.Xr gzip 1 ,
+.Xr zcat 1 ,
+.Xr zmore 1 ,
+.Xr znew 1
+.Rs
+.%A Welch, Terry A.
+.%D June, 1984
+.%T "A Technique for High Performance Data Compression"
+.%J "IEEE Computer"
+.%V 17:6
+.%P pp. 8-19
+.Re
+.Sh STANDARDS
+The
+.Nm compress
+and
+.Nm uncompress
+utilities conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Sh BUGS
+The program does not handle links well and has no link-handling options.
+.Pp
+Some of these might be considered otherwise-undocumented features.
+.Pp
+.Nm compress :
+If the utility does not compress a file because doing so would not
+reduce its size, and a file of the same name except with an
+.Pa .Z
+extension exists, the named file is not really ignored as stated above;
+it causes a prompt to confirm the overwriting of the file with the extension.
+If the operation is confirmed, that file is deleted.
+.Pp
+.Nm uncompress :
+If an empty file is compressed (using
+.Fl f ) ,
+the resulting
+.Pa .Z
+file is also empty.
+That seems right, but if
+.Nm uncompress
+is then used on that file, an error will occur.
+.Pp
+Both utilities: If a
+.Sq Fl
+argument is used and the utility prompts the user, the standard input
+is taken as the user's reply to the prompt.
+.Pp
+Both utilities:
+If the specified file does not exist, but a similarly-named one with (for
+.Nm compress )
+or without (for
+.Nm uncompress )
+a
+.Pa .Z
+extension does exist, the utility will waste the user's time by not
+immediately emitting an error message about the missing file and
+continuing.
+Instead, it first asks for confirmation to overwrite
+the existing file and then does not overwrite it.
diff --git a/usr.bin/compress/compress.c b/usr.bin/compress/compress.c
new file mode 100644
index 000000000000..005f1b5a97e1
--- /dev/null
+++ b/usr.bin/compress/compress.c
@@ -0,0 +1,426 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "zopen.h"
+
+static void compress(const char *, const char *, int);
+static void cwarn(const char *, ...) __printflike(1, 2);
+static void cwarnx(const char *, ...) __printflike(1, 2);
+static void decompress(const char *, const char *, int);
+static int permission(const char *);
+static void setfile(const char *, struct stat *);
+static void usage(int);
+
+static int eval, force, verbose;
+
+int
+main(int argc, char *argv[])
+{
+ enum {COMPRESS, DECOMPRESS} style;
+ size_t len;
+ int bits, cat, ch;
+ char *p, newname[MAXPATHLEN];
+
+ cat = 0;
+ if ((p = strrchr(argv[0], '/')) == NULL)
+ p = argv[0];
+ else
+ ++p;
+ if (!strcmp(p, "uncompress"))
+ style = DECOMPRESS;
+ else if (!strcmp(p, "compress"))
+ style = COMPRESS;
+ else if (!strcmp(p, "zcat")) {
+ cat = 1;
+ style = DECOMPRESS;
+ } else
+ errx(1, "unknown program name");
+
+ bits = 0;
+ while ((ch = getopt(argc, argv, "b:cdfv")) != -1)
+ switch(ch) {
+ case 'b':
+ bits = strtol(optarg, &p, 10);
+ if (*p)
+ errx(1, "illegal bit count -- %s", optarg);
+ break;
+ case 'c':
+ cat = 1;
+ break;
+ case 'd': /* Backward compatible. */
+ style = DECOMPRESS;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage(style == COMPRESS);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ switch(style) {
+ case COMPRESS:
+ (void)compress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ case DECOMPRESS:
+ (void)decompress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ }
+ exit (eval);
+ }
+
+ if (cat == 1 && style == COMPRESS && argc > 1)
+ errx(1, "the -c option permits only a single file argument");
+
+ for (; *argv; ++argv)
+ switch(style) {
+ case COMPRESS:
+ if (strcmp(*argv, "-") == 0) {
+ compress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ } else if (cat) {
+ compress(*argv, "/dev/stdout", bits);
+ break;
+ }
+ if ((p = strrchr(*argv, '.')) != NULL &&
+ !strcmp(p, ".Z")) {
+ cwarnx("%s: name already has trailing .Z",
+ *argv);
+ break;
+ }
+ len = strlen(*argv);
+ if (len > sizeof(newname) - 3) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len);
+ newname[len] = '.';
+ newname[len + 1] = 'Z';
+ newname[len + 2] = '\0';
+ compress(*argv, newname, bits);
+ break;
+ case DECOMPRESS:
+ if (strcmp(*argv, "-") == 0) {
+ decompress("/dev/stdin", "/dev/stdout", bits);
+ break;
+ }
+ len = strlen(*argv);
+ if ((p = strrchr(*argv, '.')) == NULL ||
+ strcmp(p, ".Z")) {
+ if (len > sizeof(newname) - 3) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len);
+ newname[len] = '.';
+ newname[len + 1] = 'Z';
+ newname[len + 2] = '\0';
+ decompress(newname,
+ cat ? "/dev/stdout" : *argv, bits);
+ } else {
+ if (len - 2 > sizeof(newname) - 1) {
+ cwarnx("%s: name too long", *argv);
+ break;
+ }
+ memmove(newname, *argv, len - 2);
+ newname[len - 2] = '\0';
+ decompress(*argv,
+ cat ? "/dev/stdout" : newname, bits);
+ }
+ break;
+ }
+ exit (eval);
+}
+
+static void
+compress(const char *in, const char *out, int bits)
+{
+ size_t nr;
+ struct stat isb, sb;
+ FILE *ifp, *ofp;
+ int exists, isreg, oreg;
+ u_char buf[1024];
+
+ exists = !stat(out, &sb);
+ if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
+ return;
+ isreg = oreg = !exists || S_ISREG(sb.st_mode);
+
+ ifp = ofp = NULL;
+ if ((ifp = fopen(in, "r")) == NULL) {
+ cwarn("%s", in);
+ return;
+ }
+ if (stat(in, &isb)) { /* DON'T FSTAT! */
+ cwarn("%s", in);
+ goto err;
+ }
+ if (!S_ISREG(isb.st_mode))
+ isreg = 0;
+
+ if ((ofp = zopen(out, "w", bits)) == NULL) {
+ cwarn("%s", out);
+ goto err;
+ }
+ while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
+ if (fwrite(buf, 1, nr, ofp) != nr) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (ferror(ifp) || fclose(ifp)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ ifp = NULL;
+
+ if (fclose(ofp)) {
+ cwarn("%s", out);
+ goto err;
+ }
+ ofp = NULL;
+
+ if (isreg) {
+ if (stat(out, &sb)) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (!force && sb.st_size >= isb.st_size) {
+ if (verbose)
+ (void)fprintf(stderr, "%s: file would grow; left unmodified\n",
+ in);
+ eval = 2;
+ if (unlink(out))
+ cwarn("%s", out);
+ goto err;
+ }
+
+ setfile(out, &isb);
+
+ if (unlink(in))
+ cwarn("%s", in);
+
+ if (verbose) {
+ (void)fprintf(stderr, "%s: ", out);
+ if (isb.st_size > sb.st_size)
+ (void)fprintf(stderr, "%.0f%% compression\n",
+ ((float)sb.st_size / isb.st_size) * 100.0);
+ else
+ (void)fprintf(stderr, "%.0f%% expansion\n",
+ ((float)isb.st_size / sb.st_size) * 100.0);
+ }
+ }
+ return;
+
+err: if (ofp) {
+ if (oreg)
+ (void)unlink(out);
+ (void)fclose(ofp);
+ }
+ if (ifp)
+ (void)fclose(ifp);
+}
+
+static void
+decompress(const char *in, const char *out, int bits)
+{
+ size_t nr;
+ struct stat sb;
+ FILE *ifp, *ofp;
+ int exists, isreg, oreg;
+ u_char buf[1024];
+
+ exists = !stat(out, &sb);
+ if (!force && exists && S_ISREG(sb.st_mode) && !permission(out))
+ return;
+ isreg = oreg = !exists || S_ISREG(sb.st_mode);
+
+ ifp = ofp = NULL;
+ if ((ifp = zopen(in, "r", bits)) == NULL) {
+ cwarn("%s", in);
+ return;
+ }
+ if (stat(in, &sb)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ if (!S_ISREG(sb.st_mode))
+ isreg = 0;
+
+ /*
+ * Try to read the first few uncompressed bytes from the input file
+ * before blindly truncating the output file.
+ */
+ if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) {
+ cwarn("%s", in);
+ (void)fclose(ifp);
+ return;
+ }
+ if ((ofp = fopen(out, "w")) == NULL ||
+ (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) {
+ cwarn("%s", out);
+ if (ofp)
+ (void)fclose(ofp);
+ (void)fclose(ifp);
+ return;
+ }
+
+ while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0)
+ if (fwrite(buf, 1, nr, ofp) != nr) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (ferror(ifp) || fclose(ifp)) {
+ cwarn("%s", in);
+ goto err;
+ }
+ ifp = NULL;
+
+ if (fclose(ofp)) {
+ cwarn("%s", out);
+ goto err;
+ }
+
+ if (isreg) {
+ setfile(out, &sb);
+
+ if (unlink(in))
+ cwarn("%s", in);
+ }
+ return;
+
+err: if (ofp) {
+ if (oreg)
+ (void)unlink(out);
+ (void)fclose(ofp);
+ }
+ if (ifp)
+ (void)fclose(ifp);
+}
+
+static void
+setfile(const char *name, struct stat *fs)
+{
+ static struct timespec tspec[2];
+
+ fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+
+ tspec[0] = fs->st_atim;
+ tspec[1] = fs->st_mtim;
+ if (utimensat(AT_FDCWD, name, tspec, 0))
+ cwarn("utimensat: %s", name);
+
+ /*
+ * Changing the ownership probably won't succeed, unless we're root
+ * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting
+ * the mode; current BSD behavior is to remove all setuid bits on
+ * chown. If chown fails, lose setuid/setgid bits.
+ */
+ if (chown(name, fs->st_uid, fs->st_gid)) {
+ if (errno != EPERM)
+ cwarn("chown: %s", name);
+ fs->st_mode &= ~(S_ISUID|S_ISGID);
+ }
+ if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP)
+ cwarn("chmod: %s", name);
+
+ if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP)
+ cwarn("chflags: %s", name);
+}
+
+static int
+permission(const char *fname)
+{
+ int ch, first;
+
+ if (!isatty(fileno(stderr)))
+ return (0);
+ (void)fprintf(stderr, "overwrite %s? ", fname);
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ return (first == 'y');
+}
+
+static void
+usage(int iscompress)
+{
+ if (iscompress)
+ (void)fprintf(stderr,
+ "usage: compress [-cfv] [-b bits] [file ...]\n");
+ else
+ (void)fprintf(stderr,
+ "usage: uncompress [-c] [-b bits] [file ...]\n");
+ exit(1);
+}
+
+static void
+cwarnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ eval = 1;
+}
+
+static void
+cwarn(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+ eval = 1;
+}
diff --git a/usr.bin/compress/doc/NOTES b/usr.bin/compress/doc/NOTES
new file mode 100644
index 000000000000..dbc0857727ca
--- /dev/null
+++ b/usr.bin/compress/doc/NOTES
@@ -0,0 +1,140 @@
+
+From: James A. Woods <jaw@eos.arc.nasa.gov>
+
+>From vn Fri Dec 2 18:05:27 1988
+Subject: Re: Looking for C source for RSA
+Newsgroups: sci.crypt
+
+# Illegitimi noncarborundum
+
+Patents are a tar pit.
+
+A good case can be made that most are just a license to sue, and nothing
+is illegal until a patent is upheld in court.
+
+For example, if you receive netnews by means other than 'nntp',
+these very words are being modulated by 'compress',
+a variation on the patented Lempel-Ziv-Welch algorithm.
+
+Original Ziv-Lempel is patent number 4,464,650, and the more powerful
+LZW method is #4,558,302. Yet despite any similarities between 'compress'
+and LZW (the public-domain 'compress' code was designed and given to the
+world before the ink on the Welch patent was dry), no attorneys from Sperry
+(the assignee) have asked you to unplug your Usenet connection.
+
+Why? I can't speak for them, but it is possible the claims are too broad,
+or, just as bad, not broad enough. ('compress' does things not mentioned
+in the Welch patent.) Maybe they realize that they can commercialize
+LZW better by selling hardware implementations rather than by licensing
+software. Again, the LZW software delineated in the patent is *not*
+the same as that of 'compress'.
+
+At any rate, court-tested software patents are a different animal;
+corporate patents in a portfolio are usually traded like baseball cards
+to shut out small fry rather than actually be defended before
+non-technical juries. Perhaps RSA will undergo this test successfully,
+although the grant to "exclude others from making, using, or selling"
+the invention would then only apply to the U.S. (witness the
+Genentech patent of the TPA molecule in the U.S. but struck down
+in Great Britain as too broad.)
+
+The concept is still exotic for those who learned in school the rule of thumb
+that one may patent "apparatus" but not an "idea".
+Apparently this all changed in Diamond v. Diehr (1981) when the U. S. Supreme
+Court reversed itself.
+
+Scholars should consult the excellent article in the Washington and Lee
+Law Review (fall 1984, vol. 41, no. 4) by Anthony and Colwell for a
+comprehensive survey of an area which will remain murky for some time.
+
+Until the dust clears, how you approach ideas which are patented depends
+on how paranoid you are of a legal onslaught. Arbitrary? Yes. But
+the patent bar of the CCPA (Court of Customs and Patent Appeals)
+thanks you for any uncertainty as they, at least, stand to gain
+from any trouble.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+From: James A. Woods <jaw@eos.arc.nasa.gov>
+Subject: Re: Looking for C source for RSA (actually 'compress' patents)
+
+ In article <2042@eos.UUCP> you write:
+ >The concept is still exotic for those who learned in school the rule of thumb
+ >that one may patent "apparatus" but not an "idea".
+
+A rule of thumb that has never been completely valid, as any chemical
+engineer can tell you. (Chemical processes were among the earliest patents,
+as I recall.)
+
+ ah yes -- i date myself when relaying out-of-date advice from elderly
+ attorneys who don't even specialize in patents. one other interesting
+ class of patents include the output of optical lens design programs,
+ which yield formulae which can then fairly directly can be molded
+ into glass. although there are restrictions on patenting equations,
+ the "embedded systems" seem to fly past the legal gauntlets.
+
+ anyway, I'm still learning about intellectual property law after
+ several conversations from a Unisys (nee sperry) lawyer re 'compress'.
+
+ it's more complicated than this, but they're letting (oral
+ communication only) software versions of 'compress' slide
+ as far as licensing fees go. this includes 'arc', 'stuffit',
+ and other commercial wrappers for 'compress'. yet they are
+ signing up licensees for hardware chips. Hewlett-Packard
+ supposedly has an active vlsi project, and Unisys has
+ board-level LZW-based tape controllers. (to build LZW into
+ a disk controller would be strange, as you'd have to build
+ in a filesystem too!)
+
+ it's byzantine
+ that Unisys is in a tiff with HP regarding the patents,
+ after discovering some sort of "compress" button on some
+ HP terminal product. why? well, professor Abraham Lempel jumped
+ from being department chairman of computer science at technion in
+ Israel to sperry (where he got the first patent), but then to work
+ at Hewlett-Packard on sabbatical. the second Welch patent
+ is only weakly derivative of the first, so they want chip
+ licenses and HP relented. however, everyone agrees something
+ like the current Unix implementation is the way to go with
+ software, so HP (and UCB) long ago asked spencer Thomas and i to sign
+ off on copyright permission (although they didn't need to, it being pd).
+ Lempel, HP, and Unisys grumbles they can't make money off the
+ software since a good free implementation (not the best --
+ i have more ideas!) escaped via Usenet. (Lempel's own pascal
+ code was apparently horribly slow.)
+ i don't follow the IBM 'arc' legal bickering; my impression
+ is that the pc folks are making money off the archiver/wrapper
+ look/feel of the thing [if ms-dos can be said to have a look and feel].
+
+ now where is telebit with the compress firmware? in a limbo
+ netherworld, probably, with sperry still welcoming outfits
+ to sign patent licenses, a common tactic to bring other small fry
+ into the fold. the guy who crammed 12-bit compress into the modem
+ there left. also what is transpiring with 'compress' and sys 5 rel 4?
+ beats me, but if sperry got a hold of them on these issues,
+ at&t would likely re-implement another algorithm if they
+ thought 'compress' infringes. needful to say, i don't think
+ it does after the above mentioned legal conversation.
+ my own beliefs on whether algorithms should be patentable at all
+ change with the weather. if the courts finally nail down
+ patent protection for algorithms, academic publication in
+ textbooks will be somewhat at odds with the engineering world,
+ where the textbook codes will simply be a big tease to get
+ money into the patent holder coffers...
+
+ oh, if you implement LZW from the patent, you won't get
+ good rates because it doesn't mention adaptive table reset,
+ lack thereof being *the* serious deficiency of Thomas' first version.
+
+ now i know that patent law generally protects against independent
+ re-invention (like the 'xor' hash function pleasantly mentioned
+ in the patent [but not the paper]).
+ but the upshot is that if anyone ever wanted to sue us,
+ we're partially covered with
+ independently-developed twists, plus the fact that some of us work
+ in a bureaucratic morass (as contractor to a public agency in my case).
+
+ quite a mess, huh? I've wanted to tell someone this stuff
+ for a long time, for posterity if nothing else.
+
+james
+
diff --git a/usr.bin/compress/doc/README b/usr.bin/compress/doc/README
new file mode 100644
index 000000000000..cae983721c6f
--- /dev/null
+++ b/usr.bin/compress/doc/README
@@ -0,0 +1,280 @@
+Compress version 4.0 improvements over 3.0:
+ o compress() speedup (10-50%) by changing division hash to xor
+ o decompress() speedup (5-10%)
+ o Memory requirements reduced (3-30%)
+ o Stack requirements reduced to less than 4kb
+ o Removed 'Big+Fast' compress code (FBITS) because of compress speedup
+ o Portability mods for Z8000 and PC/XT (but not zeus 3.2)
+ o Default to 'quiet' mode
+ o Unification of 'force' flags
+ o Manual page overhaul
+ o Portability enhancement for M_XENIX
+ o Removed text on #else and #endif
+ o Added "-V" switch to print version and options
+ o Added #defines for SIGNED_COMPARE_SLOW
+ o Added Makefile and "usermem" program
+ o Removed all floating point computations
+ o New programs: [deleted]
+
+The "usermem" script attempts to determine the maximum process size. Some
+editing of the script may be necessary (see the comments). [It should work
+fine on 4.3 BSD.] If you can't get it to work at all, just create file
+"USERMEM" containing the maximum process size in decimal.
+
+The following preprocessor symbols control the compilation of "compress.c":
+
+ o USERMEM Maximum process memory on the system
+ o SACREDMEM Amount to reserve for other processes
+ o SIGNED_COMPARE_SLOW Unsigned compare instructions are faster
+ o NO_UCHAR Don't use "unsigned char" types
+ o BITS Overrules default set by USERMEM-SACREDMEM
+ o vax Generate inline assembler
+ o interdata Defines SIGNED_COMPARE_SLOW
+ o M_XENIX Makes arrays < 65536 bytes each
+ o pdp11 BITS=12, NO_UCHAR
+ o z8000 BITS=12
+ o pcxt BITS=12
+ o BSD4_2 Allow long filenames ( > 14 characters) &
+ Call setlinebuf(stderr)
+
+The difference "usermem-sacredmem" determines the maximum BITS that can be
+specified with the "-b" flag.
+
+memory: at least BITS
+------ -- ----- ----
+ 433,484 16
+ 229,600 15
+ 127,536 14
+ 73,464 13
+ 0 12
+
+The default is BITS=16.
+
+The maximum bits can be overruled by specifying "-DBITS=bits" at
+compilation time.
+
+WARNING: files compressed on a large machine with more bits than allowed by
+a version of compress on a smaller machine cannot be decompressed! Use the
+"-b12" flag to generate a file on a large machine that can be uncompressed
+on a 16-bit machine.
+
+The output of compress 4.0 is fully compatible with that of compress 3.0.
+In other words, the output of compress 4.0 may be fed into uncompress 3.0 or
+the output of compress 3.0 may be fed into uncompress 4.0.
+
+The output of compress 4.0 not compatible with that of
+compress 2.0. However, compress 4.0 still accepts the output of
+compress 2.0. To generate output that is compatible with compress
+2.0, use the undocumented "-C" flag.
+
+ -from mod.sources, submitted by vax135!petsd!joe (Joe Orost), 8/1/85
+--------------------------------
+
+Enclosed is compress version 3.0 with the following changes:
+
+1. "Block" compression is performed. After the BITS run out, the
+ compression ratio is checked every so often. If it is decreasing,
+ the table is cleared and a new set of substrings are generated.
+
+ This makes the output of compress 3.0 not compatible with that of
+ compress 2.0. However, compress 3.0 still accepts the output of
+ compress 2.0. To generate output that is compatible with compress
+ 2.0, use the undocumented "-C" flag.
+
+2. A quiet "-q" flag has been added for use by the news system.
+
+3. The character chaining has been deleted and the program now uses
+ hashing. This improves the speed of the program, especially
+ during decompression. Other speed improvements have been made,
+ such as using putc() instead of fwrite().
+
+4. A large table is used on large machines when a relatively small
+ number of bits is specified. This saves much time when compressing
+ for a 16-bit machine on a 32-bit virtual machine. Note that the
+ speed improvement only occurs when the input file is > 30000
+ characters, and the -b BITS is less than or equal to the cutoff
+ described below.
+
+Most of these changes were made by James A. Woods (ames!jaw). Thank you
+James!
+
+To compile compress:
+
+ cc -O -DUSERMEM=usermem -o compress compress.c
+
+Where "usermem" is the amount of physical user memory available (in bytes).
+If any physical memory is to be reserved for other processes, put in
+"-DSACREDMEM sacredmem", where "sacredmem" is the amount to be reserved.
+
+The difference "usermem-sacredmem" determines the maximum BITS that can be
+specified, and the cutoff bits where the large+fast table is used.
+
+memory: at least BITS cutoff
+------ -- ----- ---- ------
+ 4,718,592 16 13
+ 2,621,440 16 12
+ 1,572,864 16 11
+ 1,048,576 16 10
+ 631,808 16 --
+ 329,728 15 --
+ 178,176 14 --
+ 99,328 13 --
+ 0 12 --
+
+The default memory size is 750,000 which gives a maximum BITS=16 and no
+large+fast table.
+
+The maximum bits can be overruled by specifying "-DBITS=bits" at
+compilation time.
+
+If your machine doesn't support unsigned characters, define "NO_UCHAR"
+when compiling.
+
+If your machine has "int" as 16-bits, define "SHORT_INT" when compiling.
+
+After compilation, move "compress" to a standard executable location, such
+as /usr/local. Then:
+ cd /usr/local
+ ln compress uncompress
+ ln compress zcat
+
+On machines that have a fixed stack size (such as Perkin-Elmer), set the
+stack to at least 12kb. ("setstack compress 12" on Perkin-Elmer).
+
+Next, install the manual (compress.l).
+ cp compress.l /usr/man/manl
+ cd /usr/man/manl
+ ln compress.l uncompress.l
+ ln compress.l zcat.l
+
+ - or -
+
+ cp compress.l /usr/man/man1/compress.1
+ cd /usr/man/man1
+ ln compress.1 uncompress.1
+ ln compress.1 zcat.1
+
+ regards,
+ petsd!joe
+
+Here is a note from the net:
+
+>From hplabs!pesnta!amd!turtlevax!ken Sat Jan 5 03:35:20 1985
+Path: ames!hplabs!pesnta!amd!turtlevax!ken
+From: ken@turtlevax.UUCP (Ken Turkowski)
+Newsgroups: net.sources
+Subject: Re: Compress release 3.0 : sample Makefile
+Organization: CADLINC, Inc. @ Menlo Park, CA
+
+In the compress 3.0 source recently posted to mod.sources, there is a
+#define variable which can be set for optimum performance on a machine
+with a large amount of memory. A program (usermem) to calculate the
+usable amount of physical user memory is enclosed, as well as a sample
+4.2BSD Vax Makefile for compress.
+
+Here is the README file from the previous version of compress (2.0):
+
+>Enclosed is compress.c version 2.0 with the following bugs fixed:
+>
+>1. The packed files produced by compress are different on different
+> machines and dependent on the vax sysgen option.
+> The bug was in the different byte/bit ordering on the
+> various machines. This has been fixed.
+>
+> This version is NOT compatible with the original vax posting
+> unless the '-DCOMPATIBLE' option is specified to the C
+> compiler. The original posting has a bug which I fixed,
+> causing incompatible files. I recommend you NOT to use this
+> option unless you already have a lot of packed files from
+> the original posting by Thomas.
+>2. The exit status is not well defined (on some machines) causing the
+> scripts to fail.
+> The exit status is now 0,1 or 2 and is documented in
+> compress.l.
+>3. The function getopt() is not available in all C libraries.
+> The function getopt() is no longer referenced by the
+> program.
+>4. Error status is not being checked on the fwrite() and fflush() calls.
+> Fixed.
+>
+>The following enhancements have been made:
+>
+>1. Added facilities of "compact" into the compress program. "Pack",
+> "Unpack", and "Pcat" are no longer required (no longer supplied).
+>2. Installed work around for C compiler bug with "-O".
+>3. Added a magic number header (\037\235). Put the bits specified
+> in the file.
+>4. Added "-f" flag to force overwrite of output file.
+>5. Added "-c" flag and "zcat" program. 'ln compress zcat' after you
+> compile.
+>6. The 'uncompress' script has been deleted; simply
+> 'ln compress uncompress' after you compile and it will work.
+>7. Removed extra bit masking for machines that support unsigned
+> characters. If your machine doesn't support unsigned characters,
+> define "NO_UCHAR" when compiling.
+>
+>Compile "compress.c" with "-O -o compress" flags. Move "compress" to a
+>standard executable location, such as /usr/local. Then:
+> cd /usr/local
+> ln compress uncompress
+> ln compress zcat
+>
+>On machines that have a fixed stack size (such as Perkin-Elmer), set the
+>stack to at least 12kb. ("setstack compress 12" on Perkin-Elmer).
+>
+>Next, install the manual (compress.l).
+> cp compress.l /usr/man/manl - or -
+> cp compress.l /usr/man/man1/compress.1
+>
+>Here is the README that I sent with my first posting:
+>
+>>Enclosed is a modified version of compress.c, along with scripts to make it
+>>run identically to pack(1), unpack(1), and pcat(1). Here is what I
+>>(petsd!joe) and a colleague (petsd!peora!srd) did:
+>>
+>>1. Removed VAX dependencies.
+>>2. Changed the struct to separate arrays; saves mucho memory.
+>>3. Did comparisons in unsigned, where possible. (Faster on Perkin-Elmer.)
+>>4. Sorted the character next chain and changed the search to stop
+>>prematurely. This saves a lot on the execution time when compressing.
+>>
+>>This version is totally compatible with the original version. Even though
+>>lint(1) -p has no complaints about compress.c, it won't run on a 16-bit
+>>machine, due to the size of the arrays.
+>>
+>>Here is the README file from the original author:
+>>
+>>>Well, with all this discussion about file compression (for news batching
+>>>in particular) going around, I decided to implement the text compression
+>>>algorithm described in the June Computer magazine. The author claimed
+>>>blinding speed and good compression ratios. It's certainly faster than
+>>>compact (but, then, what wouldn't be), but it's also the same speed as
+>>>pack, and gets better compression than both of them. On 350K bytes of
+>>>Unix-wizards, compact took about 8 minutes of CPU, pack took about 80
+>>>seconds, and compress (herein) also took 80 seconds. But, compact and
+>>>pack got about 30% compression, whereas compress got over 50%. So, I
+>>>decided I had something, and that others might be interested, too.
+>>>
+>>>As is probably true of compact and pack (although I haven't checked),
+>>>the byte order within a word is probably relevant here, but as long as
+>>>you stay on a single machine type, you should be ok. (Can anybody
+>>>elucidate on this?) There are a couple of asm's in the code (extv and
+>>>insv instructions), so anyone porting it to another machine will have to
+>>>deal with this anyway (and could probably make it compatible with Vax
+>>>byte order at the same time). Anyway, I've linted the code (both with
+>>>and without -p), so it should run elsewhere. Note the longs in the
+>>>code, you can take these out if you reduce BITS to <= 15.
+>>>
+>>>Have fun, and as always, if you make good enhancements, or bug fixes,
+>>>I'd like to see them.
+>>>
+>>>=Spencer (thomas@utah-20, {harpo,hplabs,arizona}!utah-cs!thomas)
+>>
+>> regards,
+>> joe
+>>
+>>--
+>>Full-Name: Joseph M. Orost
+>>UUCP: ..!{decvax,ucbvax,ihnp4}!vax135!petsd!joe
+>>US Mail: MS 313; Perkin-Elmer; 106 Apple St; Tinton Falls, NJ 07724
+>>Phone: (201) 870-5844
diff --git a/usr.bin/compress/doc/revision.log b/usr.bin/compress/doc/revision.log
new file mode 100644
index 000000000000..8fbaa00f1c46
--- /dev/null
+++ b/usr.bin/compress/doc/revision.log
@@ -0,0 +1,117 @@
+
+/*
+ * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $
+ *
+ * Revision 4.0 85/07/30 12:50:00 joe
+ * Removed ferror() calls in output routine on every output except first.
+ * Prepared for release to the world.
+ *
+ * Revision 3.6 85/07/04 01:22:21 joe
+ * Remove much wasted storage by overlaying hash table with the tables
+ * used by decompress: tab_suffix[1<<BITS], stack[8000]. Updated USERMEM
+ * computations. Fixed dump_tab() DEBUG routine.
+ *
+ * Revision 3.5 85/06/30 20:47:21 jaw
+ * Change hash function to use exclusive-or. Rip out hash cache. These
+ * speedups render the megamemory version defunct, for now. Make decoder
+ * stack global. Parts of the RCS trunks 2.7, 2.6, and 2.1 no longer apply.
+ *
+ * Revision 3.4 85/06/27 12:00:00 ken
+ * Get rid of all floating-point calculations by doing all compression ratio
+ * calculations in fixed point.
+ *
+ * Revision 3.3 85/06/24 21:53:24 joe
+ * Incorporate portability suggestion for M_XENIX. Got rid of text on #else
+ * and #endif lines. Cleaned up #ifdefs for vax and interdata.
+ *
+ * Revision 3.2 85/06/06 21:53:24 jaw
+ * Incorporate portability suggestions for Z8000, IBM PC/XT from mailing list.
+ * Default to "quiet" output (no compression statistics).
+ *
+ * Revision 3.1 85/05/12 18:56:13 jaw
+ * Integrate decompress() stack speedups (from early pointer mods by McKie).
+ * Repair multi-file USERMEM gaffe. Unify 'force' flags to mimic semantics
+ * of SVR2 'pack'. Streamline block-compress table clear logic. Increase
+ * output byte count by magic number size.
+ *
+ * Revision 3.0 84/11/27 11:50:00 petsd!joe
+ * Set HSIZE depending on BITS. Set BITS depending on USERMEM. Unrolled
+ * loops in clear routines. Added "-C" flag for 2.0 compatibility. Used
+ * unsigned compares on Perkin-Elmer. Fixed foreground check.
+ *
+ * Revision 2.7 84/11/16 19:35:39 ames!jaw
+ * Cache common hash codes based on input statistics; this improves
+ * performance for low-density raster images. Pass on #ifdef bundle
+ * from Turkowski.
+ *
+ * Revision 2.6 84/11/05 19:18:21 ames!jaw
+ * Vary size of hash tables to reduce time for small files.
+ * Tune PDP-11 hash function.
+ *
+ * Revision 2.5 84/10/30 20:15:14 ames!jaw
+ * Junk chaining; replace with the simpler (and, on the VAX, faster)
+ * double hashing, discussed within. Make block compression standard.
+ *
+ * Revision 2.4 84/10/16 11:11:11 ames!jaw
+ * Introduce adaptive reset for block compression, to boost the rate
+ * another several percent. (See mailing list notes.)
+ *
+ * Revision 2.3 84/09/22 22:00:00 petsd!joe
+ * Implemented "-B" block compress. Implemented REVERSE sorting of tab_next.
+ * Bug fix for last bits. Changed fwrite to putchar loop everywhere.
+ *
+ * Revision 2.2 84/09/18 14:12:21 ames!jaw
+ * Fold in news changes, small machine typedef from thomas,
+ * #ifdef interdata from joe.
+ *
+ * Revision 2.1 84/09/10 12:34:56 ames!jaw
+ * Configured fast table lookup for 32-bit machines.
+ * This cuts user time in half for b <= FBITS, and is useful for news batching
+ * from VAX to PDP sites. Also sped up decompress() [fwrite->putc] and
+ * added signal catcher [plus beef in writeerr()] to delete effluvia.
+ *
+ * Revision 2.0 84/08/28 22:00:00 petsd!joe
+ * Add check for foreground before prompting user. Insert maxbits into
+ * compressed file. Force file being uncompressed to end with ".Z".
+ * Added "-c" flag and "zcat". Prepared for release.
+ *
+ * Revision 1.10 84/08/24 18:28:00 turtlevax!ken
+ * Will only compress regular files (no directories), added a magic number
+ * header (plus an undocumented -n flag to handle old files without headers),
+ * added -f flag to force overwriting of possibly existing destination file,
+ * otherwise the user is prompted for a response. Will tack on a .Z to a
+ * filename if it doesn't have one when decompressing. Will only replace
+ * file if it was compressed.
+ *
+ * Revision 1.9 84/08/16 17:28:00 turtlevax!ken
+ * Removed scanargs(), getopt(), added .Z extension and unlimited number of
+ * filenames to compress. Flags may be clustered (-Ddvb12) or separated
+ * (-D -d -v -b 12), or combination thereof. Modes and other status is
+ * copied with copystat(). -O bug for 4.2 seems to have disappeared with
+ * 1.8.
+ *
+ * Revision 1.8 84/08/09 23:15:00 joe
+ * Made it compatible with vax version, installed jim's fixes/enhancements
+ *
+ * Revision 1.6 84/08/01 22:08:00 joe
+ * Sped up algorithm significantly by sorting the compress chain.
+ *
+ * Revision 1.5 84/07/13 13:11:00 srd
+ * Added C version of vax asm routines. Changed structure to arrays to
+ * save much memory. Do unsigned compares where possible (faster on
+ * Perkin-Elmer)
+ *
+ * Revision 1.4 84/07/05 03:11:11 thomas
+ * Clean up the code a little and lint it. (Lint complains about all
+ * the regs used in the asm, but I'm not going to "fix" this.)
+ *
+ * Revision 1.3 84/07/05 02:06:54 thomas
+ * Minor fixes.
+ *
+ * Revision 1.2 84/07/05 00:27:27 thomas
+ * Add variable bit length output.
+ *
+ */
+
+static char rcs_ident[] =
+ "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
diff --git a/usr.bin/compress/tests/Makefile b/usr.bin/compress/tests/Makefile
new file mode 100644
index 000000000000..a981110d2981
--- /dev/null
+++ b/usr.bin/compress/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= compress_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/compress/tests/Makefile.depend b/usr.bin/compress/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/compress/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/compress/tests/compress_test.sh b/usr.bin/compress/tests/compress_test.sh
new file mode 100755
index 000000000000..432d1c05c7f9
--- /dev/null
+++ b/usr.bin/compress/tests/compress_test.sh
@@ -0,0 +1,195 @@
+# Copyright (c) 2017 Jilles Tjoelker <jilles@FreeBSD.org>
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case uncompress_file_1
+uncompress_file_1_head()
+{
+ atf_set "descr" \
+ "Test uncompress without options, filename with .Z"
+}
+uncompress_file_1_body()
+{
+ printf '%01000d\n' 7 >expectfile1
+ printf "\
+\037\235\220\060\002\012\034\110\260\240\301\203\010\023\052\134\
+\310\260\241\303\207\020\043\112\234\110\261\242\305\213\030\063\
+\152\334\310\261\243\307\217\040\103\212\034\111\262\244\311\223\
+\050\123\252\134\211\360\206\002" >file1.Z
+ atf_check uncompress file1.Z
+ atf_check cmp file1 expectfile1
+ atf_check test ! -e file1.Z
+}
+
+atf_test_case uncompress_file_2
+uncompress_file_2_head()
+{
+ atf_set "descr" \
+ "Test uncompress without options, filename without .Z"
+}
+uncompress_file_2_body()
+{
+ printf '%01000d\n' 7 >expectfile1
+ printf "\
+\037\235\220\060\002\012\034\110\260\240\301\203\010\023\052\134\
+\310\260\241\303\207\020\043\112\234\110\261\242\305\213\030\063\
+\152\334\310\261\243\307\217\040\103\212\034\111\262\244\311\223\
+\050\123\252\134\211\360\206\002" >file1.Z
+ atf_check uncompress file1
+ atf_check cmp file1 expectfile1
+ atf_check test ! -e file1.Z
+}
+
+atf_test_case uncompress_stdio_1
+uncompress_stdio_1_head()
+{
+ atf_set "descr" \
+ "Test uncompress without parameters"
+}
+uncompress_stdio_1_body()
+{
+ printf '%01000d\n' 7 >expectfile1
+ printf "\
+\037\235\220\060\002\012\034\110\260\240\301\203\010\023\052\134\
+\310\260\241\303\207\020\043\112\234\110\261\242\305\213\030\063\
+\152\334\310\261\243\307\217\040\103\212\034\111\262\244\311\223\
+\050\123\252\134\211\360\206\002" >file1.Z
+ atf_check -o file:expectfile1 -x 'uncompress <file1.Z'
+}
+
+atf_test_case uncompress_minusc_1
+uncompress_minusc_1_head()
+{
+ atf_set "descr" \
+ "Test uncompress with -c"
+}
+uncompress_minusc_1_body()
+{
+ printf '%01000d\n' 7 >expectfile1
+ printf "\
+\037\235\220\060\002\012\034\110\260\240\301\203\010\023\052\134\
+\310\260\241\303\207\020\043\112\234\110\261\242\305\213\030\063\
+\152\334\310\261\243\307\217\040\103\212\034\111\262\244\311\223\
+\050\123\252\134\211\360\206\002" >file1.Z
+ atf_check -o file:expectfile1 uncompress -c file1.Z
+ atf_check test -e file1.Z
+ atf_check test ! -e file1
+}
+
+atf_test_case compress_uncompress_stdio_1
+compress_uncompress_stdio_1_head()
+{
+ atf_set "descr" \
+ "Test compressing and uncompressing some data, using stdio"
+}
+compress_uncompress_stdio_1_body()
+{
+ printf '%01000d\n' 7 8 >expectfile1
+ atf_check -x 'compress <expectfile1 >file1.Z'
+ atf_check -o file:expectfile1 uncompress -c file1.Z
+}
+
+atf_test_case compress_uncompress_minusc_1
+compress_uncompress_minusc_1_head()
+{
+ atf_set "descr" \
+ "Test compressing and uncompressing some data, using -c"
+}
+compress_uncompress_minusc_1_body()
+{
+ printf '%01000d\n' 7 8 >expectfile1
+ atf_check -x 'compress -c expectfile1 >file1.Z'
+ atf_check -o file:expectfile1 uncompress -c file1.Z
+}
+
+atf_test_case compress_uncompress_file_1
+compress_uncompress_file_1_head()
+{
+ atf_set "descr" \
+ "Test compressing and uncompressing some data, passing one filename"
+}
+compress_uncompress_file_1_body()
+{
+ printf '%01000d\n' 7 8 >expectfile1
+ cp expectfile1 file1
+ atf_check compress file1
+ atf_check -s exit:1 cmp -s file1.Z expectfile1
+ atf_check uncompress file1.Z
+ atf_check cmp file1 expectfile1
+}
+
+atf_test_case compress_uncompress_file_2
+compress_uncompress_file_2_head()
+{
+ atf_set "descr" \
+ "Test compressing and uncompressing some data, passing two filenames"
+}
+compress_uncompress_file_2_body()
+{
+ printf '%01000d\n' 7 8 >expectfile1
+ printf '%01000d\n' 8 7 >expectfile2
+ cp expectfile1 file1
+ cp expectfile2 file2
+ atf_check compress file1 file2
+ atf_check -s exit:1 cmp -s file1.Z expectfile1
+ atf_check -s exit:1 cmp -s file2.Z expectfile2
+ atf_check -s exit:1 cmp -s file1.Z file2.Z
+ atf_check uncompress file1.Z file2.Z
+ atf_check cmp file1 expectfile1
+ atf_check cmp file2 expectfile2
+}
+
+atf_test_case compress_uncompress_file_minusc_1
+compress_uncompress_file_minusc_1_head()
+{
+ atf_set "descr" \
+ "Test compressing and uncompressing some data, passing two filenames to uncompress -c"
+}
+compress_uncompress_file_minusc_1_body()
+{
+ printf '%01000d\n' 7 8 >expectfile1
+ printf '%01000d\n' 8 7 >expectfile2
+ cp expectfile1 file1
+ cp expectfile2 file2
+ atf_check compress file1 file2
+ atf_check -s exit:1 cmp -s file1.Z expectfile1
+ atf_check -s exit:1 cmp -s file2.Z expectfile2
+ atf_check -s exit:1 cmp -s file1.Z file2.Z
+ atf_check -x 'uncompress -c file1.Z file2.Z >all'
+ atf_check -x 'cat expectfile1 expectfile2 >expectall'
+ atf_check cmp all expectall
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case uncompress_file_1
+ atf_add_test_case uncompress_file_2
+ atf_add_test_case uncompress_stdio_1
+ atf_add_test_case uncompress_minusc_1
+ atf_add_test_case compress_uncompress_stdio_1
+ atf_add_test_case compress_uncompress_minusc_1
+ atf_add_test_case compress_uncompress_file_1
+ atf_add_test_case compress_uncompress_file_2
+ atf_add_test_case compress_uncompress_file_minusc_1
+}
diff --git a/usr.bin/compress/zopen.3 b/usr.bin/compress/zopen.3
new file mode 100644
index 000000000000..240763d25e5c
--- /dev/null
+++ b/usr.bin/compress/zopen.3
@@ -0,0 +1,134 @@
+.\" 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.
+.\"
+.Dd June 9, 1993
+.Dt ZOPEN 3
+.Os
+.Sh NAME
+.Nm zopen
+.Nd compressed stream open function
+.Sh SYNOPSIS
+.Fd #include \&"zopen.h\&"
+.Ft FILE *
+.Fn zopen "const char *path" "const char *mode" "int bits"
+.Sh DESCRIPTION
+The
+.Fn zopen
+function
+opens the compressed file whose name is the string pointed to by
+.Fa path
+and associates a stream with it.
+.Pp
+The argument
+.Fa mode
+points to one of the following one-character strings:
+.Bl -tag -width indent
+.It Dq Li r
+Open compressed file for reading.
+The stream is positioned at the beginning of the file.
+.It Dq Li w
+Truncate file to zero length or create compressed file for writing.
+The stream is positioned at the beginning of the file.
+.El
+.Pp
+Any created files will have mode
+.Pf \\*q Dv S_IRUSR
+\&|
+.Dv S_IWUSR
+\&|
+.Dv S_IRGRP
+\&|
+.Dv S_IWGRP
+\&|
+.Dv S_IROTH
+\&|
+.Dv S_IWOTH Ns \\*q
+.Pq Li 0666 ,
+as modified by the process'
+umask value (see
+.Xr umask 2 ) .
+.Pp
+Files may only be read or written.
+Seek operations are not allowed.
+.Pp
+The
+.Fa bits
+argument, if non-zero, is set to the bits code limit.
+If zero, the default is 16.
+See
+.Xr compress 1
+for more information.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn zopen
+returns a
+.Tn FILE
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width [EINVAL]
+.It Bq Er EINVAL
+The
+.Fa mode
+or
+.Fa bits
+arguments specified to
+.Fn zopen
+were invalid.
+.It Bq Er EFTYPE
+The compressed file starts with an invalid header, or the compressed
+file is compressed with more bits than can be handled.
+.El
+.Pp
+The
+.Fn zopen
+function may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fopen 3
+or
+.Xr funopen 3 .
+.Sh SEE ALSO
+.Xr compress 1 ,
+.Xr fopen 3 ,
+.Xr funopen 3
+.Sh HISTORY
+The
+.Nm
+function
+first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Fn zopen
+function
+may not be portable to systems other than
+.Bx .
diff --git a/usr.bin/compress/zopen.c b/usr.bin/compress/zopen.c
new file mode 100644
index 000000000000..cb7e6e9eb10a
--- /dev/null
+++ b/usr.bin/compress/zopen.c
@@ -0,0 +1,736 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1985, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis and James A. Woods, derived from original
+ * work by Spencer Thomas and Joseph Orost.
+ *
+ * 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/cdefs.h>
+/*-
+ * fcompress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * Compress authors:
+ * Spencer W. Thomas (decvax!utah-cs!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *
+ * Cleaned up and converted to library returning I/O streams by
+ * Diomidis Spinellis <dds@doc.ic.ac.uk>.
+ *
+ * zopen(filename, mode, bits)
+ * Returns a FILE * that can be used for read or write. The modes
+ * supported are only "r" and "w". Seeking is not allowed. On
+ * reading the file is decompressed, on writing it is compressed.
+ * The output is compatible with compress(1) with 16 bit tables.
+ * Any file produced by compress(1) can be read.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "zopen.h"
+
+#define BITS 16 /* Default bits. */
+#define HSIZE 69001 /* 95% occupancy */
+
+/* A code_int must be able to hold 2**BITS values of type int, and also -1. */
+typedef long code_int;
+typedef long count_int;
+
+typedef u_char char_type;
+static char_type magic_header[] =
+ {'\037', '\235'}; /* 1F 9D */
+
+#define BIT_MASK 0x1f /* Defines for third byte of header. */
+#define BLOCK_MASK 0x80
+
+/*
+ * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
+ * a fourth header byte (for expansion).
+ */
+#define INIT_BITS 9 /* Initial number of bits/code. */
+
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+struct s_zstate {
+ FILE *zs_fp; /* File stream for I/O */
+ char zs_mode; /* r or w */
+ enum {
+ S_START, S_MIDDLE, S_EOF
+ } zs_state; /* State of computation */
+ u_int zs_n_bits; /* Number of bits/code. */
+ u_int zs_maxbits; /* User settable max # bits/code. */
+ code_int zs_maxcode; /* Maximum code, given n_bits. */
+ code_int zs_maxmaxcode; /* Should NEVER generate this code. */
+ count_int zs_htab [HSIZE];
+ u_short zs_codetab [HSIZE];
+ code_int zs_hsize; /* For dynamic table sizing. */
+ code_int zs_free_ent; /* First unused entry. */
+ /*
+ * Block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+ int zs_block_compress;
+ int zs_clear_flg;
+ long zs_ratio;
+ count_int zs_checkpoint;
+ u_int zs_offset;
+ long zs_in_count; /* Length of input. */
+ long zs_bytes_out; /* Length of compressed output. */
+ long zs_out_count; /* # of codes output (for debugging). */
+ char_type zs_buf[BITS];
+ union {
+ struct {
+ long zs_fcode;
+ code_int zs_ent;
+ code_int zs_hsize_reg;
+ int zs_hshift;
+ } w; /* Write parameters */
+ struct {
+ char_type *zs_stackp;
+ int zs_finchar;
+ code_int zs_code, zs_oldcode, zs_incode;
+ int zs_roffset, zs_size;
+ char_type zs_gbuf[BITS];
+ } r; /* Read parameters */
+ } u;
+};
+
+/* Definitions to retain old variable names */
+#define fp zs->zs_fp
+#define zmode zs->zs_mode
+#define state zs->zs_state
+#define n_bits zs->zs_n_bits
+#define maxbits zs->zs_maxbits
+#define maxcode zs->zs_maxcode
+#define maxmaxcode zs->zs_maxmaxcode
+#define htab zs->zs_htab
+#define codetab zs->zs_codetab
+#define hsize zs->zs_hsize
+#define free_ent zs->zs_free_ent
+#define block_compress zs->zs_block_compress
+#define clear_flg zs->zs_clear_flg
+#define ratio zs->zs_ratio
+#define checkpoint zs->zs_checkpoint
+#define offset zs->zs_offset
+#define in_count zs->zs_in_count
+#define bytes_out zs->zs_bytes_out
+#define out_count zs->zs_out_count
+#define buf zs->zs_buf
+#define fcode zs->u.w.zs_fcode
+#define hsize_reg zs->u.w.zs_hsize_reg
+#define ent zs->u.w.zs_ent
+#define hshift zs->u.w.zs_hshift
+#define stackp zs->u.r.zs_stackp
+#define finchar zs->u.r.zs_finchar
+#define code zs->u.r.zs_code
+#define oldcode zs->u.r.zs_oldcode
+#define incode zs->u.r.zs_incode
+#define roffset zs->u.r.zs_roffset
+#define size zs->u.r.zs_size
+#define gbuf zs->u.r.zs_gbuf
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type as
+ * the codetab. The tab_suffix table needs 2**BITS characters. We get this
+ * from the beginning of htab. The output stack uses the rest of htab, and
+ * contains characters. There is plenty of room for any possible stack
+ * (stack used to be 8000 characters).
+ */
+
+#define htabof(i) htab[i]
+#define codetabof(i) codetab[i]
+
+#define tab_prefixof(i) codetabof(i)
+#define tab_suffixof(i) ((char_type *)(htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1 << BITS))
+
+#define CHECK_GAP 10000 /* Ratio check interval. */
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* First free entry. */
+#define CLEAR 256 /* Table clear output code. */
+
+static int cl_block(struct s_zstate *);
+static void cl_hash(struct s_zstate *, count_int);
+static code_int getcode(struct s_zstate *);
+static int output(struct s_zstate *, code_int);
+static int zclose(void *);
+static int zread(void *, char *, int);
+static int zwrite(void *, const char *, int);
+
+/*-
+ * Algorithm from "A Technique for High Performance Data Compression",
+ * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
+ *
+ * Algorithm:
+ * Modified Lempel-Ziv method (LZW). Basically finds common
+ * substrings and replaces them with a variable size code. This is
+ * deterministic, and can be done on the fly. Thus, the decompression
+ * procedure needs no input table, but tracks the way the table was built.
+ */
+
+/*-
+ * compress write
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+static int
+zwrite(void *cookie, const char *wbp, int num)
+{
+ code_int i;
+ int c, disp;
+ struct s_zstate *zs;
+ const u_char *bp;
+ u_char tmp;
+ int count;
+
+ if (num == 0)
+ return (0);
+
+ zs = cookie;
+ count = num;
+ bp = (const u_char *)wbp;
+ if (state == S_MIDDLE)
+ goto middle;
+ state = S_MIDDLE;
+
+ maxmaxcode = 1L << maxbits;
+ if (fwrite(magic_header,
+ sizeof(char), sizeof(magic_header), fp) != sizeof(magic_header))
+ return (-1);
+ tmp = (u_char)((maxbits) | block_compress);
+ if (fwrite(&tmp, sizeof(char), sizeof(tmp), fp) != sizeof(tmp))
+ return (-1);
+
+ offset = 0;
+ bytes_out = 3; /* Includes 3-byte header mojo. */
+ out_count = 0;
+ clear_flg = 0;
+ ratio = 0;
+ in_count = 1;
+ checkpoint = CHECK_GAP;
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ free_ent = ((block_compress) ? FIRST : 256);
+
+ ent = *bp++;
+ --count;
+
+ hshift = 0;
+ for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L)
+ hshift++;
+ hshift = 8 - hshift; /* Set hash code range bound. */
+
+ hsize_reg = hsize;
+ cl_hash(zs, (count_int)hsize_reg); /* Clear hash table. */
+
+middle: for (i = 0; count--;) {
+ c = *bp++;
+ in_count++;
+ fcode = (long)(((long)c << maxbits) + ent);
+ i = ((c << hshift) ^ ent); /* Xor hashing. */
+
+ if (htabof(i) == fcode) {
+ ent = codetabof(i);
+ continue;
+ } else if ((long)htabof(i) < 0) /* Empty slot. */
+ goto nomatch;
+ disp = hsize_reg - i; /* Secondary hash (after G. Knott). */
+ if (i == 0)
+ disp = 1;
+probe: if ((i -= disp) < 0)
+ i += hsize_reg;
+
+ if (htabof(i) == fcode) {
+ ent = codetabof(i);
+ continue;
+ }
+ if ((long)htabof(i) >= 0)
+ goto probe;
+nomatch: if (output(zs, (code_int) ent) == -1)
+ return (-1);
+ out_count++;
+ ent = c;
+ if (free_ent < maxmaxcode) {
+ codetabof(i) = free_ent++; /* code -> hashtable */
+ htabof(i) = fcode;
+ } else if ((count_int)in_count >=
+ checkpoint && block_compress) {
+ if (cl_block(zs) == -1)
+ return (-1);
+ }
+ }
+ return (num);
+}
+
+static int
+zclose(void *cookie)
+{
+ struct s_zstate *zs;
+ int rval;
+
+ zs = cookie;
+ if (zmode == 'w') { /* Put out the final code. */
+ if (output(zs, (code_int) ent) == -1) {
+ (void)fclose(fp);
+ free(zs);
+ return (-1);
+ }
+ out_count++;
+ if (output(zs, (code_int) - 1) == -1) {
+ (void)fclose(fp);
+ free(zs);
+ return (-1);
+ }
+ }
+ rval = fclose(fp) == EOF ? -1 : 0;
+ free(zs);
+ return (rval);
+}
+
+/*-
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a BITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static char_type lmask[9] =
+ {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+static char_type rmask[9] =
+ {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+static int
+output(struct s_zstate *zs, code_int ocode)
+{
+ int r_off;
+ u_int bits;
+ char_type *bp;
+
+ r_off = offset;
+ bits = n_bits;
+ bp = buf;
+ if (ocode >= 0) {
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+ /*
+ * Since ocode is always >= 8 bits, only need to mask the first
+ * hunk on the left.
+ */
+ *bp = (*bp & rmask[r_off]) | ((ocode << r_off) & lmask[r_off]);
+ bp++;
+ bits -= (8 - r_off);
+ ocode >>= 8 - r_off;
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ *bp++ = ocode;
+ ocode >>= 8;
+ bits -= 8;
+ }
+ /* Last bits. */
+ if (bits)
+ *bp = ocode;
+ offset += n_bits;
+ if (offset == (n_bits << 3)) {
+ bp = buf;
+ bits = n_bits;
+ bytes_out += bits;
+ if (fwrite(bp, sizeof(char), bits, fp) != bits)
+ return (-1);
+ bp += bits;
+ bits = 0;
+ offset = 0;
+ }
+ /*
+ * If the next entry is going to be too big for the ocode size,
+ * then increase it, if possible.
+ */
+ if (free_ent > maxcode || (clear_flg > 0)) {
+ /*
+ * Write the whole buffer, because the input side won't
+ * discover the size increase until after it has read it.
+ */
+ if (offset > 0) {
+ if (fwrite(buf, 1, n_bits, fp) != n_bits)
+ return (-1);
+ bytes_out += n_bits;
+ }
+ offset = 0;
+
+ if (clear_flg) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ } else {
+ n_bits++;
+ if (n_bits == maxbits)
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+ } else {
+ /* At EOF, write the rest of the buffer. */
+ if (offset > 0) {
+ offset = (offset + 7) / 8;
+ if (fwrite(buf, 1, offset, fp) != offset)
+ return (-1);
+ bytes_out += offset;
+ }
+ offset = 0;
+ }
+ return (0);
+}
+
+/*
+ * Decompress read. This routine adapts to the codes in the file building
+ * the "string" table on-the-fly; requiring no table to be stored in the
+ * compressed file. The tables used herein are shared with those of the
+ * compress() routine. See the definitions above.
+ */
+static int
+zread(void *cookie, char *rbp, int num)
+{
+ u_int count;
+ struct s_zstate *zs;
+ u_char *bp, header[3];
+
+ if (num == 0)
+ return (0);
+
+ zs = cookie;
+ count = num;
+ bp = (u_char *)rbp;
+ switch (state) {
+ case S_START:
+ state = S_MIDDLE;
+ break;
+ case S_MIDDLE:
+ goto middle;
+ case S_EOF:
+ goto eof;
+ }
+
+ /* Check the magic number */
+ if (fread(header,
+ sizeof(char), sizeof(header), fp) != sizeof(header) ||
+ memcmp(header, magic_header, sizeof(magic_header)) != 0) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ maxbits = header[2]; /* Set -b from file. */
+ block_compress = maxbits & BLOCK_MASK;
+ maxbits &= BIT_MASK;
+ maxmaxcode = 1L << maxbits;
+ if (maxbits > BITS || maxbits < 12) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ /* As above, initialize the first 256 entries in the table. */
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ for (code = 255; code >= 0; code--) {
+ tab_prefixof(code) = 0;
+ tab_suffixof(code) = (char_type) code;
+ }
+ free_ent = block_compress ? FIRST : 256;
+
+ finchar = oldcode = getcode(zs);
+ if (oldcode == -1) /* EOF already? */
+ return (0); /* Get out of here */
+
+ /* First code must be 8 bits = char. */
+ *bp++ = (u_char)finchar;
+ count--;
+ stackp = de_stack;
+
+ while ((code = getcode(zs)) > -1) {
+
+ if ((code == CLEAR) && block_compress) {
+ for (code = 255; code >= 0; code--)
+ tab_prefixof(code) = 0;
+ clear_flg = 1;
+ free_ent = FIRST;
+ oldcode = -1;
+ continue;
+ }
+ incode = code;
+
+ /* Special case for kWkWk string. */
+ if (code >= free_ent) {
+ if (code > free_ent || oldcode == -1) {
+ /* Bad stream. */
+ errno = EINVAL;
+ return (-1);
+ }
+ *stackp++ = finchar;
+ code = oldcode;
+ }
+ /*
+ * The above condition ensures that code < free_ent.
+ * The construction of tab_prefixof in turn guarantees that
+ * each iteration decreases code and therefore stack usage is
+ * bound by 1 << BITS - 256.
+ */
+
+ /* Generate output characters in reverse order. */
+ while (code >= 256) {
+ *stackp++ = tab_suffixof(code);
+ code = tab_prefixof(code);
+ }
+ *stackp++ = finchar = tab_suffixof(code);
+
+ /* And put them out in forward order. */
+middle: do {
+ if (count-- == 0)
+ return (num);
+ *bp++ = *--stackp;
+ } while (stackp > de_stack);
+
+ /* Generate the new entry. */
+ if ((code = free_ent) < maxmaxcode && oldcode != -1) {
+ tab_prefixof(code) = (u_short) oldcode;
+ tab_suffixof(code) = finchar;
+ free_ent = code + 1;
+ }
+
+ /* Remember previous code. */
+ oldcode = incode;
+ }
+ state = S_EOF;
+eof: return (num - count);
+}
+
+/*-
+ * Read one code from the standard input. If EOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+static code_int
+getcode(struct s_zstate *zs)
+{
+ code_int gcode;
+ int r_off, bits;
+ char_type *bp;
+
+ bp = gbuf;
+ if (clear_flg > 0 || roffset >= size || free_ent > maxcode) {
+ /*
+ * If the next entry will be too big for the current gcode
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if (free_ent > maxcode) {
+ n_bits++;
+ if (n_bits == maxbits) /* Won't get any bigger now. */
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ if (clear_flg > 0) {
+ maxcode = MAXCODE(n_bits = INIT_BITS);
+ clear_flg = 0;
+ }
+ size = fread(gbuf, 1, n_bits, fp);
+ if (size <= 0) /* End of file. */
+ return (-1);
+ roffset = 0;
+ /* Round size down to integral number of codes. */
+ size = (size << 3) - (n_bits - 1);
+ }
+ r_off = roffset;
+ bits = n_bits;
+
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+
+ /* Get first part (low order bits). */
+ gcode = (*bp++ >> r_off);
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* Now, roffset into gcode word. */
+
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ gcode |= *bp++ << r_off;
+ r_off += 8;
+ bits -= 8;
+ }
+
+ /* High order bits. */
+ if (bits > 0)
+ gcode |= (*bp & rmask[bits]) << r_off;
+ roffset += n_bits;
+
+ return (gcode);
+}
+
+static int
+cl_block(struct s_zstate *zs) /* Table clear for block compress. */
+{
+ long rat;
+
+ checkpoint = in_count + CHECK_GAP;
+
+ if (in_count > 0x007fffff) { /* Shift will overflow. */
+ rat = bytes_out >> 8;
+ if (rat == 0) /* Don't divide by zero. */
+ rat = 0x7fffffff;
+ else
+ rat = in_count / rat;
+ } else
+ rat = (in_count << 8) / bytes_out; /* 8 fractional bits. */
+ if (rat > ratio)
+ ratio = rat;
+ else {
+ ratio = 0;
+ cl_hash(zs, (count_int) hsize);
+ free_ent = FIRST;
+ clear_flg = 1;
+ if (output(zs, (code_int) CLEAR) == -1)
+ return (-1);
+ }
+ return (0);
+}
+
+static void
+cl_hash(struct s_zstate *zs, count_int cl_hsize) /* Reset code table. */
+{
+ count_int *htab_p;
+ long i, m1;
+
+ m1 = -1;
+ htab_p = htab + cl_hsize;
+ i = cl_hsize - 16;
+ do { /* Might use Sys V memset(3) here. */
+ *(htab_p - 16) = m1;
+ *(htab_p - 15) = m1;
+ *(htab_p - 14) = m1;
+ *(htab_p - 13) = m1;
+ *(htab_p - 12) = m1;
+ *(htab_p - 11) = m1;
+ *(htab_p - 10) = m1;
+ *(htab_p - 9) = m1;
+ *(htab_p - 8) = m1;
+ *(htab_p - 7) = m1;
+ *(htab_p - 6) = m1;
+ *(htab_p - 5) = m1;
+ *(htab_p - 4) = m1;
+ *(htab_p - 3) = m1;
+ *(htab_p - 2) = m1;
+ *(htab_p - 1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+ for (i += 16; i > 0; i--)
+ *--htab_p = m1;
+}
+
+FILE *
+zopen(const char *fname, const char *mode, int bits)
+{
+ struct s_zstate *zs;
+
+ if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
+ bits < 0 || bits > BITS) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)
+ return (NULL);
+
+ maxbits = bits ? bits : BITS; /* User settable max # bits/code. */
+ maxmaxcode = 1L << maxbits; /* Should NEVER generate this code. */
+ hsize = HSIZE; /* For dynamic table sizing. */
+ free_ent = 0; /* First unused entry. */
+ block_compress = BLOCK_MASK;
+ clear_flg = 0;
+ ratio = 0;
+ checkpoint = CHECK_GAP;
+ in_count = 1; /* Length of input. */
+ out_count = 0; /* # of codes output (for debugging). */
+ state = S_START;
+ roffset = 0;
+ size = 0;
+
+ /*
+ * Layering compress on top of stdio in order to provide buffering,
+ * and ensure that reads and write work with the data specified.
+ */
+ if ((fp = fopen(fname, mode)) == NULL) {
+ free(zs);
+ return (NULL);
+ }
+ switch (*mode) {
+ case 'r':
+ zmode = 'r';
+ return (funopen(zs, zread, NULL, NULL, zclose));
+ case 'w':
+ zmode = 'w';
+ return (funopen(zs, NULL, zwrite, NULL, zclose));
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
diff --git a/usr.bin/compress/zopen.h b/usr.bin/compress/zopen.h
new file mode 100644
index 000000000000..f8c7560e9b3a
--- /dev/null
+++ b/usr.bin/compress/zopen.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1996
+ * FreeBSD Inc. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY FreeBSD 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 [your name] 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 _ZOPEN_H_
+#define _ZOPEN_H_
+
+FILE *zopen(const char *, const char *, int);
+
+#endif /* _ZOPEN_H_ */
diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile
new file mode 100644
index 000000000000..46fe36d8c18e
--- /dev/null
+++ b/usr.bin/cpio/Makefile
@@ -0,0 +1,32 @@
+.include <src.opts.mk>
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+_LIBARCHIVECONFDIR= ${SRCTOP}/lib/libarchive
+
+PROG= bsdcpio
+BSDCPIO_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.],,gp;q;}' \
+ ${_LIBARCHIVEDIR}/libarchive/archive.h
+
+.PATH: ${_LIBARCHIVEDIR}/cpio
+SRCS= cpio.c cmdline.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+SRCS+= err.c line_reader.c passphrase.c
+
+CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\"
+CFLAGS+= -I${_LIBARCHIVEDIR}/cpio -I${_LIBARCHIVEDIR}/libarchive_fe
+
+LIBADD= archive
+
+.if ${MK_ICONV} != "no"
+CFLAGS+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DICONV_CONST=const
+.endif
+
+SYMLINKS=bsdcpio ${BINDIR}/cpio
+MLINKS= bsdcpio.1 cpio.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cpio/Makefile.depend b/usr.bin/cpio/Makefile.depend
new file mode 100644
index 000000000000..850d785a03af
--- /dev/null
+++ b/usr.bin/cpio/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cpio/tests/Makefile b/usr.bin/cpio/tests/Makefile
new file mode 100644
index 000000000000..9e1028c7eb58
--- /dev/null
+++ b/usr.bin/cpio/tests/Makefile
@@ -0,0 +1,126 @@
+PACKAGE= tests
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR= ${TESTSDIR}
+
+PROGS+= bsdcpio_test
+
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
+
+CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${_LIBARCHIVEDIR}/cpio -I${_LIBARCHIVEDIR}/cpio/test
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
+
+# Uncomment to link against dmalloc
+#LDADD+= -L/usr/local/lib -ldmalloc
+#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+
+CFLAGS.test_utils.c+= -Wno-cast-align
+
+.PATH: ${_LIBARCHIVEDIR}/cpio
+CPIO_SRCS= cmdline.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+CPIO_SRCS+= err.c
+
+.PATH: ${_LIBARCHIVEDIR}/cpio/test
+TESTS_SRCS= \
+ test_0.c \
+ test_basic.c \
+ test_cmdline.c \
+ test_extract_cpio_absolute_paths.c \
+ test_extract_cpio_Z.c \
+ test_extract_cpio_bz2.c \
+ test_extract_cpio_grz.c \
+ test_extract_cpio_gz.c \
+ test_extract_cpio_lrz.c \
+ test_extract_cpio_lz.c \
+ test_extract_cpio_lz4.c \
+ test_extract_cpio_lzma.c \
+ test_extract_cpio_lzo.c \
+ test_extract_cpio_xz.c \
+ test_extract_cpio_zstd.c \
+ test_format_newc.c \
+ test_gcpio_compat.c \
+ test_missing_file.c \
+ test_option_0.c \
+ test_option_B_upper.c \
+ test_option_C_upper.c \
+ test_option_J_upper.c \
+ test_option_L_upper.c \
+ test_option_Z_upper.c \
+ test_option_a.c \
+ test_option_b64encode.c \
+ test_option_c.c \
+ test_option_d.c \
+ test_option_f.c \
+ test_option_grzip.c \
+ test_option_help.c \
+ test_option_l.c \
+ test_option_lrzip.c \
+ test_option_lz4.c \
+ test_option_lzma.c \
+ test_option_lzop.c \
+ test_option_m.c \
+ test_option_passphrase.c \
+ test_option_t.c \
+ test_option_u.c \
+ test_option_uuencode.c \
+ test_option_version.c \
+ test_option_xz.c \
+ test_option_y.c \
+ test_option_z.c \
+ test_option_zstd.c \
+ test_owner_parse.c \
+ test_passthrough_dotdot.c \
+ test_passthrough_reverse.c
+
+SRCS.bsdcpio_test= list.h \
+ ${CPIO_SRCS} \
+ ${TESTS_SRCS}
+
+.PATH: ${_LIBARCHIVEDIR}/test_utils
+SRCS.bsdcpio_test+= test_main.c \
+ test_utils.c
+
+LIBADD.bsdcpio_test= archive
+
+list.h: ${TESTS_SRCS} Makefile
+ @(cd ${_LIBARCHIVEDIR}/tar/test && \
+ grep -h DEFINE_TEST ${.ALLSRC:N*Makefile}) > ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+CLEANFILES+= list.h list.h.tmp
+
+${PACKAGE}FILES+= test_extract.cpio.Z.uu
+${PACKAGE}FILES+= test_extract.cpio.bz2.uu
+${PACKAGE}FILES+= test_extract.cpio.grz.uu
+${PACKAGE}FILES+= test_extract.cpio.gz.uu
+${PACKAGE}FILES+= test_extract.cpio.lrz.uu
+${PACKAGE}FILES+= test_extract.cpio.lz.uu
+${PACKAGE}FILES+= test_extract.cpio.lz4.uu
+${PACKAGE}FILES+= test_extract.cpio.lzma.uu
+${PACKAGE}FILES+= test_extract.cpio.lzo.uu
+${PACKAGE}FILES+= test_extract.cpio.xz.uu
+${PACKAGE}FILES+= test_extract.cpio.zst.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref.bin.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref.crc.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref.newc.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref.ustar.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref_nosym.bin.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref_nosym.crc.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref_nosym.newc.uu
+${PACKAGE}FILES+= test_gcpio_compat_ref_nosym.ustar.uu
+${PACKAGE}FILES+= test_option_f.cpio.uu
+${PACKAGE}FILES+= test_option_m.cpio.uu
+${PACKAGE}FILES+= test_option_passphrase.zip.uu
+${PACKAGE}FILES+= test_option_t.cpio.uu
+${PACKAGE}FILES+= test_option_t.stdout.uu
+${PACKAGE}FILES+= test_option_tv.stdout.uu
+
+.include <bsd.test.mk>
diff --git a/usr.bin/cpio/tests/Makefile.depend b/usr.bin/cpio/tests/Makefile.depend
new file mode 100644
index 000000000000..5f5ceeb3eee7
--- /dev/null
+++ b/usr.bin/cpio/tests/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cpio/tests/functional_test.sh b/usr.bin/cpio/tests/functional_test.sh
new file mode 100755
index 000000000000..a915cc91faea
--- /dev/null
+++ b/usr.bin/cpio/tests/functional_test.sh
@@ -0,0 +1,55 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+SRCDIR=$(atf_get_srcdir)
+TESTER="${SRCDIR}/bsdcpio_test"
+export BSDCPIO=$(which cpio)
+
+check()
+{
+ local testcase=${1}; shift
+
+ # For some odd reason /bin/sh spuriously writes
+ # "write error on stdout" with some of the testcases
+ #
+ # Probably an issue with how they're written as it calls system(3) to
+ # clean up directories..
+ atf_check -e ignore -o ignore -s exit:0 ${TESTER} -d -r "${SRCDIR}" -v "${testcase}"
+}
+
+atf_init_test_cases()
+{
+ # Redirect stderr to stdout for the usage message because if you don't
+ # kyua list/kyua test will break:
+ # https://github.com/jmmv/kyua/issues/149
+ testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }')
+ for testcase in ${testcases}; do
+ atf_test_case ${testcase}
+ eval "${testcase}_body() { check ${testcase}; }"
+ atf_add_test_case ${testcase}
+ done
+}
diff --git a/usr.bin/csplit/Makefile b/usr.bin/csplit/Makefile
new file mode 100644
index 000000000000..4b577b7edf6f
--- /dev/null
+++ b/usr.bin/csplit/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= csplit
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/csplit/Makefile.depend b/usr.bin/csplit/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/csplit/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/csplit/csplit.1 b/usr.bin/csplit/csplit.1
new file mode 100644
index 000000000000..877399edf114
--- /dev/null
+++ b/usr.bin/csplit/csplit.1
@@ -0,0 +1,167 @@
+.\" Copyright (c) 2002 Tim J. Robbins.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 February 6, 2014
+.Dt CSPLIT 1
+.Os
+.Sh NAME
+.Nm csplit
+.Nd split files based on context
+.Sh SYNOPSIS
+.Nm
+.Op Fl ks
+.Op Fl f Ar prefix
+.Op Fl n Ar number
+.Ar file args ...
+.Sh DESCRIPTION
+The
+.Nm
+utility splits
+.Ar file
+into pieces using the patterns
+.Ar args .
+If
+.Ar file
+is
+a dash
+.Pq Sq Fl ,
+.Nm
+reads from standard input.
+.Pp
+Files are created with a prefix of
+.Dq xx
+and two decimal digits.
+The size of each file is written to standard output
+as it is created.
+If an error occurs whilst files are being created,
+or a
+.Dv HUP ,
+.Dv INT ,
+or
+.Dv TERM
+signal is received,
+all files previously written are removed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f Ar prefix
+Create file names beginning with
+.Ar prefix ,
+instead of
+.Dq Pa xx .
+.It Fl k
+Do not remove previously created files if an error occurs or a
+.Dv HUP ,
+.Dv INT ,
+or
+.Dv TERM
+signal is received.
+.It Fl n Ar number
+Create file names beginning with
+.Ar number
+of decimal digits after the prefix,
+instead of 2.
+.It Fl s
+Do not write the size of each output file to standard output as it is
+created.
+.El
+.Pp
+The
+.Ar args
+operands may be a combination of the following patterns:
+.Bl -tag -width indent
+.It Xo
+.Sm off
+.Cm / Ar regexp Cm / Op Oo Cm + | - Oc Ar offset
+.Sm on
+.Xc
+Create a file containing the input from the current line to (but not including)
+the next line matching the given basic regular expression.
+An optional
+.Ar offset
+from the line that matched may be specified.
+.It Xo
+.Sm off
+.Cm % Ar regexp Cm % Op Oo Cm + | - Oc Ar offset
+.Sm on
+.Xc
+Same as above but a file is not created for the output.
+.It Ar line_no
+Create containing the input from the current line to (but not including)
+the specified line number.
+.It Cm { Ns Ar num Ns Cm }
+Repeat the previous pattern the specified number of times.
+If it follows a line number pattern, a new file will be created for each
+.Ar line_no
+lines,
+.Ar num
+times.
+The first line of the file is line number 1 for historic reasons.
+.El
+.Pp
+After all the patterns have been processed, the remaining input data
+(if there is any) will be written to a new file.
+.Pp
+Requesting to split at a line before the current line number or past the
+end of the file will result in an error.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_COLLATE
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Split the
+.Xr mdoc 7
+file
+.Pa foo.1
+into one file for each section (up to 21 plus one for the rest, if any):
+.Pp
+.Dl "csplit -k foo.1 '%^\e.Sh%' '/^\e.Sh/' '{20}'"
+.Pp
+Split standard input after the first 99 lines and every 100 lines thereafter:
+.Pp
+.Dl "csplit -k - 100 '{19}'"
+.Sh SEE ALSO
+.Xr sed 1 ,
+.Xr split 1 ,
+.Xr re_format 7
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+command appeared in PWB UNIX.
+.Sh BUGS
+Input lines are limited to
+.Dv LINE_MAX
+(2048) bytes in length.
diff --git a/usr.bin/csplit/csplit.c b/usr.bin/csplit/csplit.c
new file mode 100644
index 000000000000..59aa7eb3d2d9
--- /dev/null
+++ b/usr.bin/csplit/csplit.c
@@ -0,0 +1,468 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * csplit -- split files based on context
+ *
+ * This utility splits its input into numbered output files by line number
+ * or by a regular expression. Regular expression matches have an optional
+ * offset with them, allowing the split to occur a specified number of
+ * lines before or after the match.
+ *
+ * To handle negative offsets, we stop reading when the match occurs and
+ * store the offset that the file should have been split at, then use
+ * this output file as input until all the "overflowed" lines have been read.
+ * The file is then closed and truncated to the correct length.
+ *
+ * We assume that the output files can be seeked upon (ie. they cannot be
+ * symlinks to named pipes or character devices), but make no such
+ * assumption about the input.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <regex.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void cleanup(void);
+static void do_lineno(const char *);
+static void do_rexp(const char *);
+static char *get_line(void);
+static void handlesig(int);
+static FILE *newfile(void);
+static void toomuch(FILE *, long);
+static void usage(void);
+
+/*
+ * Command line options
+ */
+static const char *prefix; /* File name prefix */
+static long sufflen; /* Number of decimal digits for suffix */
+static int sflag; /* Suppress output of file names */
+static int kflag; /* Keep output if error occurs */
+
+/*
+ * Other miscellaneous globals (XXX too many)
+ */
+static long lineno; /* Current line number in input file */
+static long reps; /* Number of repetitions for this pattern */
+static long nfiles; /* Number of files output so far */
+static long maxfiles; /* Maximum number of files we can create */
+static char currfile[PATH_MAX]; /* Current output file */
+static const char *infn; /* Name of the input file */
+static FILE *infile; /* Input file handle */
+static FILE *overfile; /* Overflow file for toomuch() */
+static off_t truncofs; /* Offset this file should be truncated at */
+static int doclean; /* Should cleanup() remove output? */
+
+int
+main(int argc, char *argv[])
+{
+ struct sigaction sa;
+ long i;
+ int ch;
+ const char *expr;
+ char *ep, *p;
+ FILE *ofp;
+
+ setlocale(LC_ALL, "");
+
+ kflag = sflag = 0;
+ prefix = "xx";
+ sufflen = 2;
+ while ((ch = getopt(argc, argv, "ksf:n:")) > 0) {
+ switch (ch) {
+ case 'f':
+ prefix = optarg;
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'n':
+ errno = 0;
+ sufflen = strtol(optarg, &ep, 10);
+ if (sufflen <= 0 || *ep != '\0' || errno != 0)
+ errx(1, "%s: bad suffix length", optarg);
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+
+ if (sufflen + strlen(prefix) >= PATH_MAX)
+ errx(1, "name too long");
+
+ argc -= optind;
+ argv += optind;
+
+ if ((infn = *argv++) == NULL)
+ usage();
+ if (strcmp(infn, "-") == 0) {
+ infile = stdin;
+ infn = "stdin";
+ } else if ((infile = fopen(infn, "r")) == NULL)
+ err(1, "%s", infn);
+
+ if (!kflag) {
+ doclean = 1;
+ atexit(cleanup);
+ sa.sa_flags = 0;
+ sa.sa_handler = handlesig;
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGHUP);
+ sigaddset(&sa.sa_mask, SIGINT);
+ sigaddset(&sa.sa_mask, SIGTERM);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ }
+
+ lineno = 0;
+ nfiles = 0;
+ truncofs = 0;
+ overfile = NULL;
+
+ /* Ensure 10^sufflen < LONG_MAX. */
+ for (maxfiles = 1, i = 0; i < sufflen; i++) {
+ if (maxfiles > LONG_MAX / 10)
+ errx(1, "%ld: suffix too long (limit %ld)",
+ sufflen, i);
+ maxfiles *= 10;
+ }
+
+ /* Create files based on supplied patterns. */
+ while (nfiles < maxfiles - 1 && (expr = *argv++) != NULL) {
+ /* Look ahead & see if this pattern has any repetitions. */
+ if (*argv != NULL && **argv == '{') {
+ errno = 0;
+ reps = strtol(*argv + 1, &ep, 10);
+ if (reps < 0 || *ep != '}' || errno != 0)
+ errx(1, "%s: bad repetition count", *argv + 1);
+ argv++;
+ } else
+ reps = 0;
+
+ if (*expr == '/' || *expr == '%') {
+ do
+ do_rexp(expr);
+ while (reps-- != 0 && nfiles < maxfiles - 1);
+ } else if (isdigit((unsigned char)*expr))
+ do_lineno(expr);
+ else
+ errx(1, "%s: unrecognised pattern", expr);
+ }
+
+ /* Copy the rest into a new file. */
+ if (!feof(infile)) {
+ ofp = newfile();
+ while ((p = get_line()) != NULL && fputs(p, ofp) != EOF)
+ ;
+ if (!sflag)
+ printf("%jd\n", (intmax_t)ftello(ofp));
+ if (fclose(ofp) != 0)
+ err(1, "%s", currfile);
+ }
+
+ toomuch(NULL, 0);
+ doclean = 0;
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+"usage: csplit [-ks] [-f prefix] [-n number] file args ...\n");
+ exit(1);
+}
+
+static void
+handlesig(int sig __unused)
+{
+ const char msg[] = "csplit: caught signal, cleaning up\n";
+
+ write(STDERR_FILENO, msg, sizeof(msg) - 1);
+ cleanup();
+ _exit(2);
+}
+
+/* Create a new output file. */
+static FILE *
+newfile(void)
+{
+ FILE *fp;
+
+ if ((size_t)snprintf(currfile, sizeof(currfile), "%s%0*ld", prefix,
+ (int)sufflen, nfiles) >= sizeof(currfile))
+ errc(1, ENAMETOOLONG, NULL);
+ if ((fp = fopen(currfile, "w+")) == NULL)
+ err(1, "%s", currfile);
+ nfiles++;
+
+ return (fp);
+}
+
+/* Remove partial output, called before exiting. */
+static void
+cleanup(void)
+{
+ char fnbuf[PATH_MAX];
+ long i;
+
+ if (!doclean)
+ return;
+
+ /*
+ * NOTE: One cannot portably assume to be able to call snprintf()
+ * from inside a signal handler. It does, however, appear to be safe
+ * to do on FreeBSD. The solution to this problem is worse than the
+ * problem itself.
+ */
+
+ for (i = 0; i < nfiles; i++) {
+ snprintf(fnbuf, sizeof(fnbuf), "%s%0*ld", prefix,
+ (int)sufflen, i);
+ unlink(fnbuf);
+ }
+}
+
+/* Read a line from the input into a static buffer. */
+static char *
+get_line(void)
+{
+ static char lbuf[LINE_MAX];
+ FILE *src;
+
+ src = overfile != NULL ? overfile : infile;
+
+again: if (fgets(lbuf, sizeof(lbuf), src) == NULL) {
+ if (src == overfile) {
+ src = infile;
+ goto again;
+ }
+ return (NULL);
+ }
+ if (ferror(src))
+ err(1, "%s", infn);
+ lineno++;
+
+ return (lbuf);
+}
+
+/* Conceptually rewind the input (as obtained by get_line()) back `n' lines. */
+static void
+toomuch(FILE *ofp, long n)
+{
+ char buf[BUFSIZ];
+ size_t i, nread;
+
+ if (overfile != NULL) {
+ /*
+ * Truncate the previous file we overflowed into back to
+ * the correct length, close it.
+ */
+ if (fflush(overfile) != 0)
+ err(1, "overflow");
+ if (ftruncate(fileno(overfile), truncofs) != 0)
+ err(1, "overflow");
+ if (fclose(overfile) != 0)
+ err(1, "overflow");
+ overfile = NULL;
+ }
+
+ if (n == 0)
+ /* Just tidying up */
+ return;
+
+ lineno -= n;
+
+ /*
+ * Wind the overflow file backwards to `n' lines before the
+ * current one.
+ */
+ do {
+ if (ftello(ofp) < (off_t)sizeof(buf))
+ rewind(ofp);
+ else
+ fseeko(ofp, -(off_t)sizeof(buf), SEEK_CUR);
+ if (ferror(ofp))
+ errx(1, "%s: can't seek", currfile);
+ if ((nread = fread(buf, 1, sizeof(buf), ofp)) == 0)
+ errx(1, "can't read overflowed output");
+ if (fseeko(ofp, -(off_t)nread, SEEK_CUR) != 0)
+ err(1, "%s", currfile);
+ for (i = 1; i <= nread; i++)
+ if (buf[nread - i] == '\n' && n-- == 0)
+ break;
+ if (ftello(ofp) == 0)
+ break;
+ } while (n > 0);
+ if (fseeko(ofp, nread - i + 1, SEEK_CUR) != 0)
+ err(1, "%s", currfile);
+
+ /*
+ * get_line() will read from here. Next call will truncate to
+ * truncofs in this file.
+ */
+ overfile = ofp;
+ truncofs = ftello(overfile);
+}
+
+/* Handle splits for /regexp/ and %regexp% patterns. */
+static void
+do_rexp(const char *expr)
+{
+ regex_t cre;
+ intmax_t nwritten;
+ long ofs;
+ int first;
+ char *ecopy, *ep, *p, *pofs, *re;
+ FILE *ofp;
+
+ if ((ecopy = strdup(expr)) == NULL)
+ err(1, "strdup");
+
+ re = ecopy + 1;
+ if ((pofs = strrchr(ecopy, *expr)) == NULL || pofs[-1] == '\\')
+ errx(1, "%s: missing trailing %c", expr, *expr);
+ *pofs++ = '\0';
+
+ if (*pofs != '\0') {
+ errno = 0;
+ ofs = strtol(pofs, &ep, 10);
+ if (*ep != '\0' || errno != 0)
+ errx(1, "%s: bad offset", pofs);
+ } else
+ ofs = 0;
+
+ if (regcomp(&cre, re, REG_BASIC|REG_NOSUB) != 0)
+ errx(1, "%s: bad regular expression", re);
+
+ if (*expr == '/')
+ /* /regexp/: Save results to a file. */
+ ofp = newfile();
+ else {
+ /* %regexp%: Make a temporary file for overflow. */
+ if ((ofp = tmpfile()) == NULL)
+ err(1, "tmpfile");
+ }
+
+ /* Read and output lines until we get a match. */
+ first = 1;
+ while ((p = get_line()) != NULL) {
+ if (fputs(p, ofp) == EOF)
+ break;
+ if (!first && regexec(&cre, p, 0, NULL, 0) == 0)
+ break;
+ first = 0;
+ }
+
+ if (p == NULL) {
+ toomuch(NULL, 0);
+ errx(1, "%s: no match", re);
+ }
+
+ if (ofs <= 0) {
+ /*
+ * Negative (or zero) offset: throw back any lines we should
+ * not have read yet.
+ */
+ if (p != NULL) {
+ toomuch(ofp, -ofs + 1);
+ nwritten = (intmax_t)truncofs;
+ } else
+ nwritten = (intmax_t)ftello(ofp);
+ } else {
+ /*
+ * Positive offset: copy the requested number of lines
+ * after the match.
+ */
+ while (--ofs > 0 && (p = get_line()) != NULL)
+ fputs(p, ofp);
+ toomuch(NULL, 0);
+ nwritten = (intmax_t)ftello(ofp);
+ if (fclose(ofp) != 0)
+ err(1, "%s", currfile);
+ }
+
+ if (!sflag && *expr == '/')
+ printf("%jd\n", nwritten);
+
+ regfree(&cre);
+ free(ecopy);
+}
+
+/* Handle splits based on line number. */
+static void
+do_lineno(const char *expr)
+{
+ long lastline, tgtline;
+ char *ep, *p;
+ FILE *ofp;
+
+ errno = 0;
+ tgtline = strtol(expr, &ep, 10);
+ if (tgtline <= 0 || errno != 0 || *ep != '\0')
+ errx(1, "%s: bad line number", expr);
+ lastline = tgtline;
+ if (lastline <= lineno)
+ errx(1, "%s: can't go backwards", expr);
+
+ while (nfiles < maxfiles - 1) {
+ ofp = newfile();
+ while (lineno + 1 != lastline) {
+ if ((p = get_line()) == NULL)
+ errx(1, "%ld: out of range", lastline);
+ if (fputs(p, ofp) == EOF)
+ break;
+ }
+ if (!sflag)
+ printf("%jd\n", (intmax_t)ftello(ofp));
+ if (fclose(ofp) != 0)
+ err(1, "%s", currfile);
+ if (reps-- == 0)
+ break;
+ lastline += tgtline;
+ }
+}
diff --git a/usr.bin/csplit/tests/Makefile b/usr.bin/csplit/tests/Makefile
new file mode 100644
index 000000000000..498f68544f6e
--- /dev/null
+++ b/usr.bin/csplit/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= csplit_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/csplit/tests/Makefile.depend b/usr.bin/csplit/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/csplit/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/csplit/tests/csplit_test.sh b/usr.bin/csplit/tests/csplit_test.sh
new file mode 100755
index 000000000000..4a47245813e0
--- /dev/null
+++ b/usr.bin/csplit/tests/csplit_test.sh
@@ -0,0 +1,59 @@
+# Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org>
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case lines_lt_count
+lines_lt_count_head()
+{
+ atf_set "descr" \
+ "Test an edge case where input has fewer lines than count"
+}
+lines_lt_count_body()
+{
+ cat > expectfile00 << HERE
+one
+two
+HERE
+ cat > expectfile01 << HERE
+xxx 1
+three
+four
+HERE
+ cat > expectfile02 << HERE
+xxx 2
+five
+six
+HERE
+ echo -e "one\ntwo\nxxx 1\nthree\nfour\nxxx 2\nfive\nsix" | \
+ csplit -k - '/xxx/' '{10}'
+
+ atf_check cmp expectfile00 xx00
+ atf_check cmp expectfile01 xx01
+ atf_check cmp expectfile02 xx02
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case lines_lt_count
+}
diff --git a/usr.bin/ctags/C.c b/usr.bin/ctags/C.c
new file mode 100644
index 000000000000..20a2cf072aa9
--- /dev/null
+++ b/usr.bin/ctags/C.c
@@ -0,0 +1,557 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static bool func_entry(void);
+static void hash_entry(void);
+static void skip_string(int);
+static bool str_entry(int);
+
+/*
+ * c_entries --
+ * read .c and .h files and call appropriate routines
+ */
+void
+c_entries(void)
+{
+ int c; /* current character */
+ int level; /* brace level */
+ int token; /* if reading a token */
+ bool t_def; /* if reading a typedef */
+ int t_level; /* typedef's brace level */
+ char *sp; /* buffer pointer */
+ char tok[MAXTOKEN]; /* token buffer */
+
+ lineftell = ftell(inf);
+ sp = tok; token = t_def = false; t_level = -1; level = 0; lineno = 1;
+ while (GETC(!=, EOF)) {
+ switch (c) {
+ /*
+ * Here's where it DOESN'T handle: {
+ * foo(a)
+ * {
+ * #ifdef notdef
+ * }
+ * #endif
+ * if (a)
+ * puts("hello, world");
+ * }
+ */
+ case '{':
+ ++level;
+ goto endtok;
+ case '}':
+ /*
+ * if level goes below zero, try and fix
+ * it, even though we've already messed up
+ */
+ if (--level < 0)
+ level = 0;
+ goto endtok;
+
+ case '\n':
+ SETLINE;
+ /*
+ * the above 3 cases are similar in that they
+ * are special characters that also end tokens.
+ */
+ endtok: if (sp > tok) {
+ *sp = EOS;
+ token = true;
+ sp = tok;
+ }
+ else
+ token = false;
+ continue;
+
+ /*
+ * We ignore quoted strings and character constants
+ * completely.
+ */
+ case '"':
+ case '\'':
+ skip_string(c);
+ break;
+
+ /*
+ * comments can be fun; note the state is unchanged after
+ * return, in case we found:
+ * "foo() XX comment XX { int bar; }"
+ */
+ case '/':
+ if (GETC(==, '*') || c == '/') {
+ skip_comment(c);
+ continue;
+ }
+ (void)ungetc(c, inf);
+ c = '/';
+ goto storec;
+
+ /* hash marks flag #define's. */
+ case '#':
+ if (sp == tok) {
+ hash_entry();
+ break;
+ }
+ goto storec;
+
+ /*
+ * if we have a current token, parenthesis on
+ * level zero indicates a function.
+ */
+ case '(':
+ if (!level && token) {
+ int curline;
+
+ if (sp != tok)
+ *sp = EOS;
+ /*
+ * grab the line immediately, we may
+ * already be wrong, for example,
+ * foo\n
+ * (arg1,
+ */
+ get_line();
+ curline = lineno;
+ if (func_entry()) {
+ ++level;
+ pfnote(tok, curline);
+ }
+ break;
+ }
+ goto storec;
+
+ /*
+ * semi-colons indicate the end of a typedef; if we find a
+ * typedef we search for the next semi-colon of the same
+ * level as the typedef. Ignoring "structs", they are
+ * tricky, since you can find:
+ *
+ * "typedef long time_t;"
+ * "typedef unsigned int u_int;"
+ * "typedef unsigned int u_int [10];"
+ *
+ * If looking at a typedef, we save a copy of the last token
+ * found. Then, when we find the ';' we take the current
+ * token if it starts with a valid token name, else we take
+ * the one we saved. There's probably some reasonable
+ * alternative to this...
+ */
+ case ';':
+ if (t_def && level == t_level) {
+ t_def = false;
+ get_line();
+ if (sp != tok)
+ *sp = EOS;
+ pfnote(tok, lineno);
+ break;
+ }
+ goto storec;
+
+ /*
+ * store characters until one that can't be part of a token
+ * comes along; check the current token against certain
+ * reserved words.
+ */
+ default:
+ /* ignore whitespace */
+ if (c == ' ' || c == '\t') {
+ int save = c;
+ while (GETC(!=, EOF) && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ return;
+ (void)ungetc(c, inf);
+ c = save;
+ }
+ storec: if (!intoken(c)) {
+ if (sp == tok)
+ break;
+ *sp = EOS;
+ if (tflag) {
+ /* no typedefs inside typedefs */
+ if (!t_def &&
+ !memcmp(tok, "typedef",8)) {
+ t_def = true;
+ t_level = level;
+ break;
+ }
+ /* catch "typedef struct" */
+ if ((!t_def || t_level < level)
+ && (!memcmp(tok, "struct", 7)
+ || !memcmp(tok, "union", 6)
+ || !memcmp(tok, "enum", 5))) {
+ /*
+ * get line immediately;
+ * may change before '{'
+ */
+ get_line();
+ if (str_entry(c))
+ ++level;
+ break;
+ /* } */
+ }
+ }
+ sp = tok;
+ }
+ else if (sp != tok || begtoken(c)) {
+ if (sp == tok + sizeof tok - 1)
+ /* Too long -- truncate it */
+ *sp = EOS;
+ else
+ *sp++ = c;
+ token = true;
+ }
+ continue;
+ }
+
+ sp = tok;
+ token = false;
+ }
+}
+
+/*
+ * func_entry --
+ * handle a function reference
+ */
+static bool
+func_entry(void)
+{
+ int c; /* current character */
+ int level = 0; /* for matching '()' */
+ static char attribute[] = "__attribute__";
+ char maybe_attribute[sizeof attribute + 1],
+ *anext;
+
+ /*
+ * Find the end of the assumed function declaration.
+ * Note that ANSI C functions can have type definitions so keep
+ * track of the parentheses nesting level.
+ */
+ while (GETC(!=, EOF)) {
+ switch (c) {
+ case '\'':
+ case '"':
+ /* skip strings and character constants */
+ skip_string(c);
+ break;
+ case '/':
+ /* skip comments */
+ if (GETC(==, '*') || c == '/')
+ skip_comment(c);
+ break;
+ case '(':
+ level++;
+ break;
+ case ')':
+ if (level == 0)
+ goto fnd;
+ level--;
+ break;
+ case '\n':
+ SETLINE;
+ }
+ }
+ return (false);
+fnd:
+ /*
+ * we assume that the character after a function's right paren
+ * is a token character if it's a function and a non-token
+ * character if it's a declaration. Comments don't count...
+ */
+ for (anext = maybe_attribute;;) {
+ while (GETC(!=, EOF) && iswhite(c))
+ if (c == '\n')
+ SETLINE;
+ if (c == EOF)
+ return false;
+ /*
+ * Recognize the gnu __attribute__ extension, which would
+ * otherwise make the heuristic test DTWT
+ */
+ if (anext == maybe_attribute) {
+ if (intoken(c)) {
+ *anext++ = c;
+ continue;
+ }
+ } else {
+ if (intoken(c)) {
+ if (anext - maybe_attribute
+ < (ptrdiff_t)(sizeof attribute - 1))
+ *anext++ = c;
+ else break;
+ continue;
+ } else {
+ *anext++ = '\0';
+ if (strcmp(maybe_attribute, attribute) == 0) {
+ (void)ungetc(c, inf);
+ return false;
+ }
+ break;
+ }
+ }
+ if (intoken(c) || c == '{')
+ break;
+ if (c == '/' && (GETC(==, '*') || c == '/'))
+ skip_comment(c);
+ else { /* don't ever "read" '/' */
+ (void)ungetc(c, inf);
+ return (false);
+ }
+ }
+ if (c != '{')
+ (void)skip_key('{');
+ return (true);
+}
+
+/*
+ * hash_entry --
+ * handle a line starting with a '#'
+ */
+static void
+hash_entry(void)
+{
+ int c; /* character read */
+ int curline; /* line started on */
+ char *sp; /* buffer pointer */
+ char tok[MAXTOKEN]; /* storage buffer */
+
+ /* ignore leading whitespace */
+ while (GETC(!=, EOF) && (c == ' ' || c == '\t'))
+ ;
+ (void)ungetc(c, inf);
+
+ curline = lineno;
+ for (sp = tok;;) { /* get next token */
+ if (GETC(==, EOF))
+ return;
+ if (iswhite(c))
+ break;
+ if (sp == tok + sizeof tok - 1)
+ /* Too long -- truncate it */
+ *sp = EOS;
+ else
+ *sp++ = c;
+ }
+ *sp = EOS;
+ if (memcmp(tok, "define", 6)) /* only interested in #define's */
+ goto skip;
+ for (;;) { /* this doesn't handle "#define \n" */
+ if (GETC(==, EOF))
+ return;
+ if (!iswhite(c))
+ break;
+ }
+ for (sp = tok;;) { /* get next token */
+ if (sp == tok + sizeof tok - 1)
+ /* Too long -- truncate it */
+ *sp = EOS;
+ else
+ *sp++ = c;
+ if (GETC(==, EOF))
+ return;
+ /*
+ * this is where it DOESN'T handle
+ * "#define \n"
+ */
+ if (!intoken(c))
+ break;
+ }
+ *sp = EOS;
+ if (dflag || c == '(') { /* only want macros */
+ get_line();
+ pfnote(tok, curline);
+ }
+skip: if (c == '\n') { /* get rid of rest of define */
+ SETLINE
+ if (*(sp - 1) != '\\')
+ return;
+ }
+ (void)skip_key('\n');
+}
+
+/*
+ * str_entry --
+ * handle a struct, union or enum entry
+ */
+static bool
+str_entry(int c) /* c is current character */
+{
+ int curline; /* line started on */
+ char *sp; /* buffer pointer */
+ char tok[LINE_MAX]; /* storage buffer */
+
+ curline = lineno;
+ while (iswhite(c))
+ if (GETC(==, EOF))
+ return (false);
+ if (c == '{') /* it was "struct {" */
+ return (true);
+ for (sp = tok;;) { /* get next token */
+ if (sp == tok + sizeof tok - 1)
+ /* Too long -- truncate it */
+ *sp = EOS;
+ else
+ *sp++ = c;
+ if (GETC(==, EOF))
+ return (false);
+ if (!intoken(c))
+ break;
+ }
+ switch (c) {
+ case '{': /* it was "struct foo{" */
+ --sp;
+ break;
+ case '\n': /* it was "struct foo\n" */
+ SETLINE;
+ /*FALLTHROUGH*/
+ default: /* probably "struct foo " */
+ while (GETC(!=, EOF))
+ if (!iswhite(c))
+ break;
+ if (c != '{') {
+ (void)ungetc(c, inf);
+ return (false);
+ }
+ }
+ *sp = EOS;
+ pfnote(tok, curline);
+ return (true);
+}
+
+/*
+ * skip_comment --
+ * skip over comment
+ */
+void
+skip_comment(int t) /* t is comment character */
+{
+ int c; /* character read */
+ int star; /* '*' flag */
+
+ for (star = 0; GETC(!=, EOF);)
+ switch(c) {
+ /* comments don't nest, nor can they be escaped. */
+ case '*':
+ star = true;
+ break;
+ case '/':
+ if (star && t == '*')
+ return;
+ break;
+ case '\n':
+ SETLINE;
+ if (t == '/')
+ return;
+ /*FALLTHROUGH*/
+ default:
+ star = false;
+ break;
+ }
+}
+
+/*
+ * skip_string --
+ * skip to the end of a string or character constant.
+ */
+void
+skip_string(int key)
+{
+ int c,
+ skip;
+
+ for (skip = false; GETC(!=, EOF); )
+ switch (c) {
+ case '\\': /* a backslash escapes anything */
+ skip = !skip; /* we toggle in case it's "\\" */
+ break;
+ case '\n':
+ SETLINE;
+ /*FALLTHROUGH*/
+ default:
+ if (c == key && !skip)
+ return;
+ skip = false;
+ }
+}
+
+/*
+ * skip_key --
+ * skip to next char "key"
+ */
+bool
+skip_key(int key)
+{
+ int c;
+ bool skip;
+ bool retval;
+
+ for (skip = retval = false; GETC(!=, EOF);)
+ switch(c) {
+ case '\\': /* a backslash escapes anything */
+ skip = !skip; /* we toggle in case it's "\\" */
+ break;
+ case ';': /* special case for yacc; if one */
+ case '|': /* of these chars occurs, we may */
+ retval = true; /* have moved out of the rule */
+ break; /* not used by C */
+ case '\'':
+ case '"':
+ /* skip strings and character constants */
+ skip_string(c);
+ break;
+ case '/':
+ /* skip comments */
+ if (GETC(==, '*') || c == '/') {
+ skip_comment(c);
+ break;
+ }
+ (void)ungetc(c, inf);
+ c = '/';
+ goto norm;
+ case '\n':
+ SETLINE;
+ /*FALLTHROUGH*/
+ default:
+ norm:
+ if (c == key && !skip)
+ return (retval);
+ skip = false;
+ }
+ return (retval);
+}
diff --git a/usr.bin/ctags/Makefile b/usr.bin/ctags/Makefile
new file mode 100644
index 000000000000..a0d0c8522914
--- /dev/null
+++ b/usr.bin/ctags/Makefile
@@ -0,0 +1,5 @@
+PROG= ctags
+SRCS= C.c ctags.c fortran.c lisp.c print.c tree.c yacc.c
+CFLAGS+=-I${.CURDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ctags/Makefile.depend b/usr.bin/ctags/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/ctags/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ctags/ctags.1 b/usr.bin/ctags/ctags.1
new file mode 100644
index 000000000000..c9745f407575
--- /dev/null
+++ b/usr.bin/ctags/ctags.1
@@ -0,0 +1,258 @@
+.\" Copyright (c) 1987, 1990, 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.
+.\"
+.Dd May 23, 2023
+.Dt CTAGS 1
+.Os
+.Sh NAME
+.Nm ctags
+.Nd create a
+.Pa tags
+file
+.Sh SYNOPSIS
+.Nm
+.Op Fl BFTaduwvx
+.Op Fl f Ar tagsfile
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility makes a
+.Pa tags
+file for
+.Xr ex 1
+from the specified C,
+Pascal, Fortran,
+.Xr yacc 1 ,
+.Xr lex 1 ,
+and Lisp sources.
+A tags file gives the locations of specified objects in a group of files.
+Each line of the tags file contains the object name, the file in which it
+is defined, and a search pattern for the object definition, separated by
+white-space.
+Using the
+.Pa tags
+file,
+.Xr ex 1
+can quickly locate these object definitions.
+Depending upon the options provided to
+.Nm ,
+objects will consist of subroutines, typedefs, defines, structs,
+enums and unions.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl B
+Use backward searching patterns
+.Pq Li ?...? .
+.It Fl F
+Use forward searching patterns
+.Pq Li /.../
+(the default).
+.It Fl T
+Do not create tags for typedefs, structs, unions, and enums.
+.It Fl a
+Append to
+.Pa tags
+file.
+.It Fl d
+Create tags for
+.Li #defines
+that do not take arguments;
+.Li #defines
+that take arguments are tagged automatically.
+.It Fl f
+Place the tag descriptions in a file called
+.Ar tagsfile .
+The default behaviour is to place them in a file called
+.Pa tags .
+If
+.Ar tagsfile
+is
+.Dq - ,
+the tags will be written to standard output instead.
+.It Fl u
+Update the specified files in the
+.Pa tags
+file, that is, all
+references to them are deleted, and the new values are appended to the
+file.
+This is ignored if the tags file does not exist or is not a regular
+file (e.g.
+.Fl f Ns -
+was used to write to standard output).
+.Pp
+Beware: this option is implemented in a way which is rather
+slow; it is usually faster to simply rebuild the
+.Pa tags
+file.
+.It Fl v
+An index of the form expected by
+.Xr vgrind 1
+is produced on the standard output.
+This listing
+contains the object name, file name, and page number (assuming 64
+line pages).
+Since the output will be sorted into lexicographic order,
+it may be desired to run the output through
+.Xr sort 1 .
+Sample use:
+.Bd -literal -offset indent
+ctags -v files | sort -f > index
+vgrind -x index
+.Ed
+.It Fl w
+Suppress warning diagnostics.
+.It Fl x
+.Nm
+produces a list of object
+names, the line number and file name on which each is defined, as well
+as the text of that line and prints this on the standard output.
+This
+is a simple index which can be printed out as an off-line readable
+function index.
+.El
+.Pp
+Files whose names end in
+.Pa .c
+or
+.Pa .h
+are assumed to be C
+source files and are searched for C style routine and macro definitions.
+Files whose names end in
+.Pa .y
+are assumed to be
+.Xr yacc 1
+source files.
+Files whose names end in
+.Pa .l
+are assumed to be Lisp files if their
+first non-blank character is
+.Ql \&; ,
+.Ql \&( ,
+or
+.Ql \&[ ,
+otherwise, they are
+treated as
+.Xr lex 1
+files.
+Other files are first examined to see if they
+contain any Pascal or Fortran routine definitions, and, if not, are
+searched for C style definitions.
+.Pp
+The tag
+.Dq Li main
+is treated specially in C programs.
+The tag formed
+is created by prepending
+.Ql M
+to the name of the file, with the
+trailing
+.Pa .c
+and any leading pathname components removed.
+This makes use of
+.Nm
+practical in directories with more than one
+program.
+.Pp
+The
+.Xr yacc 1
+and
+.Xr lex 1
+files each have a special tag.
+.Dq Li yyparse
+is the start
+of the second section of the
+.Xr yacc 1
+file, and
+.Dq Li yylex
+is the start of
+the second section of the
+.Xr lex 1
+file.
+.Sh FILES
+.Bl -tag -width ".Pa tags" -compact
+.It Pa tags
+default output tags file
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with a value of 1 if an error occurred, 0 otherwise.
+Duplicate objects are not considered errors.
+.Sh COMPATIBILITY
+The
+.Fl t
+option is a no-op for compatibility with previous versions of
+.Nm
+that did not create tags for typedefs, enums, structs and unions
+by default.
+.Sh SEE ALSO
+.Xr ex 1 ,
+.Xr vi 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 3.0 .
+.Sh BUGS
+Recognition of functions, subroutines and procedures
+for Fortran and Pascal is done in a very simpleminded way.
+No attempt
+is made to deal with block structure; if you have two Pascal procedures
+in different blocks with the same name you lose.
+The
+.Nm
+utility does not
+understand about Pascal types.
+.Pp
+The method of deciding whether to look for C, Pascal or
+Fortran
+functions is a hack.
+.Pp
+The
+.Nm
+utility relies on the input being well formed, and any syntactical
+errors will completely confuse it.
+It also finds some legal syntax
+confusing; for example, since it does not understand
+.Li #ifdef Ns 's
+(incidentally, that is a feature, not a bug), any code with unbalanced
+braces inside
+.Li #ifdef Ns 's
+will cause it to become somewhat disoriented.
+In a similar fashion, multiple line changes within a definition will
+cause it to enter the last line of the object, rather than the first, as
+the searching pattern.
+The last line of multiple line
+.Li typedef Ns 's
+will similarly be noted.
diff --git a/usr.bin/ctags/ctags.c b/usr.bin/ctags/ctags.c
new file mode 100644
index 000000000000..b8d642520466
--- /dev/null
+++ b/usr.bin/ctags/ctags.c
@@ -0,0 +1,330 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994, 1995
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * ctags: create a tags file
+ */
+
+NODE *head; /* head of the sorted binary tree */
+
+ /* boolean "func" (see init()) */
+bool _wht[256], _etk[256], _itk[256], _btk[256], _gd[256];
+
+FILE *inf; /* ioptr for current input file */
+FILE *outf; /* ioptr for tags file */
+
+long lineftell; /* ftell after getc( inf ) == '\n' */
+
+int lineno; /* line number of current line */
+int dflag; /* -d: non-macro defines */
+int tflag; /* -t: create tags for typedefs */
+int vflag; /* -v: vgrind style index output */
+int wflag; /* -w: suppress warnings */
+int xflag; /* -x: cxref style output */
+
+char *curfile; /* current input file name */
+char searchar = '/'; /* use /.../ searches by default */
+char lbuf[LINE_MAX];
+
+void init(void);
+void find_entries(char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ static const char *outfile = "tags"; /* output file */
+ int aflag; /* -a: append to tags */
+ int uflag; /* -u: update tags */
+ int exit_val; /* exit value */
+ int step; /* step through args */
+ int ch; /* getopts char */
+
+ setlocale(LC_ALL, "");
+
+ aflag = uflag = false;
+ tflag = true;
+ while ((ch = getopt(argc, argv, "BFTadf:tuwvx")) != -1)
+ switch(ch) {
+ case 'B':
+ searchar = '?';
+ break;
+ case 'F':
+ searchar = '/';
+ break;
+ case 'T':
+ tflag = false;
+ break;
+ case 'a':
+ aflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+ case 'f':
+ outfile = optarg;
+ break;
+ case 't':
+ tflag = true;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'v':
+ vflag++;
+ case 'x':
+ xflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+ if (!argc)
+ usage();
+
+ if (strcmp(outfile, "-") == 0)
+ outfile = "/dev/stdout";
+
+ if (!xflag)
+ setlocale(LC_COLLATE, "C");
+
+ init();
+
+ for (exit_val = step = 0; step < argc; ++step)
+ if (!(inf = fopen(argv[step], "r"))) {
+ warn("%s", argv[step]);
+ exit_val = 1;
+ }
+ else {
+ curfile = argv[step];
+ find_entries(argv[step]);
+ (void)fclose(inf);
+ }
+
+ if (head) {
+ if (xflag)
+ put_entries(head);
+ else {
+ if (uflag) {
+ struct stat sb;
+ FILE *oldf;
+ regex_t *regx;
+
+ if ((oldf = fopen(outfile, "r")) == NULL) {
+ if (errno == ENOENT) {
+ uflag = 0;
+ goto udone;
+ }
+ err(1, "opening %s", outfile);
+ }
+ if (fstat(fileno(oldf), &sb) != 0 ||
+ !S_ISREG(sb.st_mode)) {
+ fclose(oldf);
+ uflag = 0;
+ goto udone;
+ }
+ if (unlink(outfile))
+ err(1, "unlinking %s", outfile);
+ if ((outf = fopen(outfile, "w")) == NULL)
+ err(1, "recreating %s", outfile);
+ if ((regx = calloc(argc, sizeof(regex_t))) == NULL)
+ err(1, "RE alloc");
+ for (step = 0; step < argc; step++) {
+ (void)strcpy(lbuf, "\t");
+ (void)strlcat(lbuf, argv[step], LINE_MAX);
+ (void)strlcat(lbuf, "\t", LINE_MAX);
+ if (regcomp(regx + step, lbuf,
+ REG_NOSPEC))
+ warn("RE compilation failed");
+ }
+nextline:
+ while (fgets(lbuf, LINE_MAX, oldf)) {
+ for (step = 0; step < argc; step++)
+ if (regexec(regx + step,
+ lbuf, 0, NULL, 0) == 0)
+ goto nextline;
+ fputs(lbuf, outf);
+ }
+ for (step = 0; step < argc; step++)
+ regfree(regx + step);
+ free(regx);
+ fclose(oldf);
+ fclose(outf);
+ ++aflag;
+ }
+udone:
+ if (!(outf = fopen(outfile, aflag ? "a" : "w")))
+ err(1, "%s", outfile);
+ put_entries(head);
+ (void)fclose(outf);
+ if (uflag) {
+ pid_t pid;
+
+ if ((pid = fork()) == -1)
+ err(1, "fork failed");
+ else if (pid == 0) {
+ execlp("sort", "sort", "-o", outfile,
+ outfile, NULL);
+ err(1, "exec of sort failed");
+ }
+ /* Just assume the sort went OK. The old code
+ did not do any checks either. */
+ (void)wait(NULL);
+ }
+ }
+ }
+ if (ferror(stdout) != 0 || fflush(stdout) != 0)
+ err(1, "stdout");
+ exit(exit_val);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: ctags [-BFTaduwvx] [-f tagsfile] file ...\n");
+ exit(1);
+}
+
+/*
+ * init --
+ * this routine sets up the boolean pseudo-functions which work by
+ * setting boolean flags dependent upon the corresponding character.
+ * Every char which is NOT in that string is false with respect to
+ * the pseudo-function. Therefore, all of the array "_wht" is NO
+ * by default and then the elements subscripted by the chars in
+ * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
+ * the string CWHITE, else NO.
+ */
+void
+init(void)
+{
+ int i;
+ const unsigned char *sp;
+
+ for (i = 0; i < 256; i++) {
+ _wht[i] = _etk[i] = _itk[i] = _btk[i] = false;
+ _gd[i] = true;
+ }
+#define CWHITE " \f\t\n"
+ for (sp = CWHITE; *sp; sp++) /* white space chars */
+ _wht[*sp] = true;
+#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
+ for (sp = CTOKEN; *sp; sp++) /* token ending chars */
+ _etk[*sp] = true;
+#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
+ for (sp = CINTOK; *sp; sp++) /* valid in-token chars */
+ _itk[*sp] = true;
+#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+ for (sp = CBEGIN; *sp; sp++) /* token starting chars */
+ _btk[*sp] = true;
+#define CNOTGD ",;"
+ for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */
+ _gd[*sp] = false;
+}
+
+/*
+ * find_entries --
+ * this routine opens the specified file and calls the function
+ * which searches the file.
+ */
+void
+find_entries(char *file)
+{
+ char *cp;
+
+ lineno = 0; /* should be 1 ?? KB */
+ if ((cp = strrchr(file, '.'))) {
+ if (cp[1] == 'l' && !cp[2]) {
+ int c;
+
+ for (;;) {
+ if (GETC(==, EOF))
+ return;
+ if (!iswhite(c)) {
+ rewind(inf);
+ break;
+ }
+ }
+#define LISPCHR ";(["
+/* lisp */ if (strchr(LISPCHR, c)) {
+ l_entries();
+ return;
+ }
+/* lex */ else {
+ /*
+ * we search all 3 parts of a lex file
+ * for C references. This may be wrong.
+ */
+ toss_yysec();
+ (void)strcpy(lbuf, "%%$");
+ pfnote("yylex", lineno);
+ rewind(inf);
+ }
+ }
+/* yacc */ else if (cp[1] == 'y' && !cp[2]) {
+ /*
+ * we search only the 3rd part of a yacc file
+ * for C references. This may be wrong.
+ */
+ toss_yysec();
+ (void)strcpy(lbuf, "%%$");
+ pfnote("yyparse", lineno);
+ y_entries();
+ }
+/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
+ if (PF_funcs())
+ return;
+ rewind(inf);
+ }
+ }
+/* C */ c_entries();
+}
diff --git a/usr.bin/ctags/ctags.h b/usr.bin/ctags/ctags.h
new file mode 100644
index 000000000000..b74bf7ea7602
--- /dev/null
+++ b/usr.bin/ctags/ctags.h
@@ -0,0 +1,93 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ *
+ */
+
+/* This header requires bool for some externed symbols. */
+#include <stdbool.h>
+
+#define EOS '\0'
+
+#define ENDLINE 50 /* max length of pattern */
+#define MAXTOKEN 250 /* max size of single token */
+
+#define SETLINE {++lineno;lineftell = ftell(inf);}
+#define GETC(op,exp) ((c = getc(inf)) op (int)exp)
+
+/*
+ * These character classification macros assume that the (EOF & 0xff) element
+ * of the arrays is always 'NO', as the EOF return from getc() gets masked
+ * to that value. Masking with 0xff has no effect for normal characters
+ * returned by getc() provided chars have 8 bits.
+ */
+
+#define iswhite(arg) _wht[arg & 0xff] /* T if char is white */
+#define begtoken(arg) _btk[arg & 0xff] /* T if char can start token */
+#define intoken(arg) _itk[arg & 0xff] /* T if char can be in token */
+#define endtoken(arg) _etk[arg & 0xff] /* T if char ends tokens */
+#define isgood(arg) _gd[arg & 0xff] /* T if char can be after ')' */
+
+typedef struct nd_st { /* sorting structure */
+ struct nd_st *left,
+ *right; /* left and right sons */
+ char *entry, /* function or type name */
+ *file, /* file name */
+ *pat; /* search pattern */
+ int lno; /* for -x option */
+ bool been_warned; /* set if noticed dup */
+} NODE;
+
+extern char *curfile; /* current input file name */
+extern NODE *head; /* head of the sorted binary tree */
+extern FILE *inf; /* ioptr for current input file */
+extern FILE *outf; /* ioptr for current output file */
+extern long lineftell; /* ftell after getc( inf ) == '\n' */
+extern int lineno; /* line number of current line */
+extern int dflag; /* -d: non-macro defines */
+extern int tflag; /* -t: create tags for typedefs */
+extern int vflag; /* -v: vgrind style index output */
+extern int wflag; /* -w: suppress warnings */
+extern int xflag; /* -x: cxref style output */
+extern bool _wht[], _etk[], _itk[], _btk[], _gd[];
+extern char lbuf[LINE_MAX];
+extern char *lbp;
+extern char searchar; /* ex search character */
+
+extern bool cicmp(const char *);
+extern void get_line(void);
+extern void pfnote(const char *, int);
+extern bool skip_key(int);
+extern void put_entries(NODE *);
+extern void toss_yysec(void);
+extern void l_entries(void);
+extern void y_entries(void);
+extern bool PF_funcs(void);
+extern void c_entries(void);
+extern void skip_comment(int);
diff --git a/usr.bin/ctags/fortran.c b/usr.bin/ctags/fortran.c
new file mode 100644
index 000000000000..4375076f5914
--- /dev/null
+++ b/usr.bin/ctags/fortran.c
@@ -0,0 +1,162 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void takeprec(void);
+
+char *lbp; /* line buffer pointer */
+
+bool
+PF_funcs(void)
+{
+ bool pfcnt; /* pascal/fortran functions found */
+ char *cp;
+ char tok[MAXTOKEN];
+
+ for (pfcnt = false;;) {
+ lineftell = ftell(inf);
+ if (!fgets(lbuf, sizeof(lbuf), inf))
+ return (pfcnt);
+ ++lineno;
+ lbp = lbuf;
+ if (*lbp == '%') /* Ratfor escape to fortran */
+ ++lbp;
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ switch (*lbp | ' ') { /* convert to lower-case */
+ case 'c':
+ if (cicmp("complex") || cicmp("character"))
+ takeprec();
+ break;
+ case 'd':
+ if (cicmp("double")) {
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ if (cicmp("precision"))
+ break;
+ continue;
+ }
+ break;
+ case 'i':
+ if (cicmp("integer"))
+ takeprec();
+ break;
+ case 'l':
+ if (cicmp("logical"))
+ takeprec();
+ break;
+ case 'r':
+ if (cicmp("real"))
+ takeprec();
+ break;
+ }
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ switch (*lbp | ' ') {
+ case 'f':
+ if (cicmp("function"))
+ break;
+ continue;
+ case 'p':
+ if (cicmp("program") || cicmp("procedure"))
+ break;
+ continue;
+ case 's':
+ if (cicmp("subroutine"))
+ break;
+ default:
+ continue;
+ }
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (!*lbp)
+ continue;
+ for (cp = lbp + 1; *cp && intoken(*cp); ++cp)
+ continue;
+ if (cp == lbp + 1)
+ continue;
+ *cp = EOS;
+ (void)strlcpy(tok, lbp, sizeof(tok)); /* possible trunc */
+ get_line(); /* process line for ex(1) */
+ pfnote(tok, lineno);
+ pfcnt = true;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * cicmp --
+ * do case-independent strcmp
+ */
+bool
+cicmp(const char *cp)
+{
+ int len;
+ char *bp;
+
+ for (len = 0, bp = lbp; *cp && (*cp &~ ' ') == (*bp++ &~ ' ');
+ ++cp, ++len)
+ continue;
+ if (!*cp) {
+ lbp += len;
+ return (true);
+ }
+ return (false);
+}
+
+static void
+takeprec(void)
+{
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ if (*lbp == '*') {
+ for (++lbp; isspace(*lbp); ++lbp)
+ continue;
+ if (!isdigit(*lbp))
+ --lbp; /* force failure */
+ else
+ while (isdigit(*++lbp))
+ continue;
+ }
+}
diff --git a/usr.bin/ctags/lisp.c b/usr.bin/ctags/lisp.c
new file mode 100644
index 000000000000..e721bf8f757d
--- /dev/null
+++ b/usr.bin/ctags/lisp.c
@@ -0,0 +1,100 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ctags.h"
+
+/*
+ * lisp tag functions
+ * just look for (def or (DEF
+ */
+void
+l_entries(void)
+{
+ bool special;
+ char *cp;
+ char savedc;
+ char tok[MAXTOKEN];
+
+ for (;;) {
+ lineftell = ftell(inf);
+ if (!fgets(lbuf, sizeof(lbuf), inf))
+ return;
+ ++lineno;
+ lbp = lbuf;
+ if (!cicmp("(def"))
+ continue;
+ special = false;
+ switch(*lbp | ' ') {
+ case 'm':
+ if (cicmp("method"))
+ special = true;
+ break;
+ case 'w':
+ if (cicmp("wrapper") || cicmp("whopper"))
+ special = true;
+ }
+ for (; !isspace(*lbp); ++lbp)
+ continue;
+ for (; isspace(*lbp); ++lbp)
+ continue;
+ for (cp = lbp; *cp && *cp != '\n'; ++cp)
+ continue;
+ *cp = EOS;
+ if (special) {
+ if (!(cp = strchr(lbp, ')')))
+ continue;
+ for (; cp >= lbp && *cp != ':'; --cp)
+ continue;
+ if (cp < lbp)
+ continue;
+ lbp = cp;
+ for (; *cp && *cp != ')' && *cp != ' '; ++cp)
+ continue;
+ }
+ else
+ for (cp = lbp + 1;
+ *cp && *cp != '(' && *cp != ' '; ++cp)
+ continue;
+ savedc = *cp;
+ *cp = EOS;
+ (void)strlcpy(tok, lbp, sizeof(tok)); /* possible trunc */
+ *cp = savedc;
+ get_line();
+ pfnote(tok, lineno);
+ }
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/ctags/print.c b/usr.bin/ctags/print.c
new file mode 100644
index 000000000000..e1b0957104c0
--- /dev/null
+++ b/usr.bin/ctags/print.c
@@ -0,0 +1,107 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "ctags.h"
+
+/*
+ * get_line --
+ * get the line the token of interest occurred on,
+ * prepare it for printing.
+ */
+void
+get_line(void)
+{
+ long saveftell;
+ int c;
+ int cnt;
+ char *cp;
+
+ saveftell = ftell(inf);
+ (void)fseek(inf, lineftell, L_SET);
+ if (xflag)
+ for (cp = lbuf; GETC(!=, EOF) && c != '\n'; *cp++ = c)
+ continue;
+ /*
+ * do all processing here, so we don't step through the
+ * line more than once; means you don't call this routine
+ * unless you're sure you've got a keeper.
+ */
+ else for (cnt = 0, cp = lbuf; GETC(!=, EOF) && cnt < ENDLINE; ++cnt) {
+ if (c == '\\') { /* backslashes */
+ if (cnt > ENDLINE - 2)
+ break;
+ *cp++ = '\\'; *cp++ = '\\';
+ ++cnt;
+ }
+ else if (c == (int)searchar) { /* search character */
+ if (cnt > ENDLINE - 2)
+ break;
+ *cp++ = '\\'; *cp++ = c;
+ ++cnt;
+ }
+ else if (c == '\n') { /* end of keep */
+ *cp++ = '$'; /* can find whole line */
+ break;
+ }
+ else
+ *cp++ = c;
+ }
+ *cp = EOS;
+ (void)fseek(inf, saveftell, L_SET);
+}
+
+/*
+ * put_entries --
+ * write out the tags
+ */
+void
+put_entries(NODE *node)
+{
+
+ if (node->left)
+ put_entries(node->left);
+ if (vflag)
+ printf("%s %s %d\n",
+ node->entry, node->file, (node->lno + 63) / 64);
+ else if (xflag)
+ printf("%-16s %4d %-16s %s\n",
+ node->entry, node->lno, node->file, node->pat);
+ else
+ fprintf(outf, "%s\t%s\t%c^%s%c\n",
+ node->entry, node->file, searchar, node->pat, searchar);
+ if (node->right)
+ put_entries(node->right);
+}
diff --git a/usr.bin/ctags/test/ctags.test b/usr.bin/ctags/test/ctags.test
new file mode 100644
index 000000000000..1f334ac2b8b1
--- /dev/null
+++ b/usr.bin/ctags/test/ctags.test
@@ -0,0 +1,67 @@
+int bar = (1 + 5);
+
+FOO("here is a #define test: ) {");
+char sysent[20];
+int nsysent = sizeof (sysent) / sizeof (sysent[0]);
+/*
+ * now is the time for a comment.
+ * four lines in length...
+ */struct struct_xtra{int list;};r4(x,y){};typedef struct{int bar;}struct_xxe;
+#define FOO BAR
+struct struct_three {
+ int list;
+};
+#define SINGLE
+int BAD();
+enum color {red, green, gold, brown};
+char qq[] = " quote(one,two) {int bar;} ";
+typedef struct {
+ int bar;
+ struct struct_two {
+ int foo;
+ union union_3 {
+ struct struct_three entry;
+ char size[25];
+ };
+ struct last {
+ struct struct_three xentry;
+ char list[34];
+ };
+ };
+} struct_one;
+#define TWOLINE ((MAXLIST + FUTURE + 15) \
+ / (time_to_live ? 3 : 4))
+#if (defined(BAR))
+int bar;
+#endif
+#define MULTIPLE {\
+ multiple(one,two); \
+ lineno++; \
+ callroute(one,two); \
+}
+#if defined(BAR)
+int bar;
+#endif
+union union_one {
+ struct struct_three s3;
+ char foo[25];
+};
+#define XYZ(A,B) (A + B / 2) * (3 - 26 + l_lineno)
+routine1(one,two) /* comments here are fun... */
+ struct {
+ int entry;
+ char bar[34];
+ } *one;
+ char two[10];
+{
+typedef unsigned char u_char;
+ register struct buf *bp;
+ five(one,two);
+}
+ routine2 (one,two) { puts("hello\n"); }
+ routine3
+(one,
+two) { puts("world\n"); }
+routine4(int one, char (*two)(void)) /* test ANSI arguments */
+{
+}
diff --git a/usr.bin/ctags/tree.c b/usr.bin/ctags/tree.c
new file mode 100644
index 000000000000..7643d1895b93
--- /dev/null
+++ b/usr.bin/ctags/tree.c
@@ -0,0 +1,127 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ctags.h"
+
+static void add_node(NODE *, NODE *);
+static void free_tree(NODE *);
+
+/*
+ * pfnote --
+ * enter a new node in the tree
+ */
+void
+pfnote(const char *name, int ln)
+{
+ NODE *np;
+ char *fp;
+ char nbuf[MAXTOKEN];
+
+ /*NOSTRICT*/
+ if (!(np = (NODE *)malloc(sizeof(NODE)))) {
+ warnx("too many entries to sort");
+ put_entries(head);
+ free_tree(head);
+ /*NOSTRICT*/
+ if (!(head = np = (NODE *)malloc(sizeof(NODE))))
+ errx(1, "out of space");
+ }
+ if (!xflag && !strcmp(name, "main")) {
+ if (!(fp = strrchr(curfile, '/')))
+ fp = curfile;
+ else
+ ++fp;
+ (void)snprintf(nbuf, sizeof(nbuf), "M%s", fp);
+ fp = strrchr(nbuf, '.');
+ if (fp && !fp[2])
+ *fp = EOS;
+ name = nbuf;
+ }
+ if (!(np->entry = strdup(name)))
+ err(1, NULL);
+ np->file = curfile;
+ np->lno = ln;
+ np->left = np->right = 0;
+ if (!(np->pat = strdup(lbuf)))
+ err(1, NULL);
+ if (!head)
+ head = np;
+ else
+ add_node(np, head);
+}
+
+static void
+add_node(NODE *node, NODE *cur_node)
+{
+ int dif;
+
+ dif = strcoll(node->entry, cur_node->entry);
+ if (!dif) {
+ if (node->file == cur_node->file) {
+ if (!wflag)
+ fprintf(stderr, "Duplicate entry in file %s, line %d: %s\nSecond entry ignored\n", node->file, lineno, node->entry);
+ return;
+ }
+ if (!cur_node->been_warned)
+ if (!wflag)
+ fprintf(stderr, "Duplicate entry in files %s and %s: %s (Warning only)\n", node->file, cur_node->file, node->entry);
+ cur_node->been_warned = true;
+ }
+ else if (dif < 0)
+ if (cur_node->left)
+ add_node(node, cur_node->left);
+ else
+ cur_node->left = node;
+ else if (cur_node->right)
+ add_node(node, cur_node->right);
+ else
+ cur_node->right = node;
+}
+
+static void
+free_tree(NODE *node)
+{
+ NODE *node_next;
+ while (node) {
+ if (node->right)
+ free_tree(node->right);
+ node_next = node->left;
+ free(node);
+ node = node_next;
+ }
+}
diff --git a/usr.bin/ctags/yacc.c b/usr.bin/ctags/yacc.c
new file mode 100644
index 000000000000..71dddaa36f67
--- /dev/null
+++ b/usr.bin/ctags/yacc.c
@@ -0,0 +1,145 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "ctags.h"
+
+/*
+ * y_entries:
+ * find the yacc tags and put them in.
+ */
+void
+y_entries(void)
+{
+ int c;
+ char *sp;
+ bool in_rule;
+ char tok[MAXTOKEN];
+
+ in_rule = false;
+
+ while (GETC(!=, EOF))
+ switch (c) {
+ case '\n':
+ SETLINE;
+ /* FALLTHROUGH */
+ case ' ':
+ case '\f':
+ case '\r':
+ case '\t':
+ break;
+ case '{':
+ if (skip_key('}'))
+ in_rule = false;
+ break;
+ case '\'':
+ case '"':
+ if (skip_key(c))
+ in_rule = false;
+ break;
+ case '%':
+ if (GETC(==, '%'))
+ return;
+ (void)ungetc(c, inf);
+ break;
+ case '/':
+ if (GETC(==, '*') || c == '/')
+ skip_comment(c);
+ else
+ (void)ungetc(c, inf);
+ break;
+ case '|':
+ case ';':
+ in_rule = false;
+ break;
+ default:
+ if (in_rule || (!isalpha(c) && c != '.' && c != '_'))
+ break;
+ sp = tok;
+ *sp++ = c;
+ while (GETC(!=, EOF) && (intoken(c) || c == '.'))
+ *sp++ = c;
+ *sp = EOS;
+ get_line(); /* may change before ':' */
+ while (iswhite(c)) {
+ if (c == '\n')
+ SETLINE;
+ if (GETC(==, EOF))
+ return;
+ }
+ if (c == ':') {
+ pfnote(tok, lineno);
+ in_rule = true;
+ }
+ else
+ (void)ungetc(c, inf);
+ }
+}
+
+/*
+ * toss_yysec --
+ * throw away lines up to the next "\n%%\n"
+ */
+void
+toss_yysec(void)
+{
+ int c; /* read character */
+ int state;
+
+ /*
+ * state == 0 : waiting
+ * state == 1 : received a newline
+ * state == 2 : received first %
+ * state == 3 : received second %
+ */
+ lineftell = ftell(inf);
+ for (state = 0; GETC(!=, EOF);)
+ switch (c) {
+ case '\n':
+ ++lineno;
+ lineftell = ftell(inf);
+ if (state == 3) /* done! */
+ return;
+ state = 1; /* start over */
+ break;
+ case '%':
+ if (state) /* if 1 or 2 */
+ ++state; /* goto 3 */
+ break;
+ default:
+ state = 0; /* reset */
+ break;
+ }
+}
diff --git a/usr.bin/ctlstat/Makefile b/usr.bin/ctlstat/Makefile
new file mode 100644
index 000000000000..aa7c6f2a2641
--- /dev/null
+++ b/usr.bin/ctlstat/Makefile
@@ -0,0 +1,8 @@
+PROG= ctlstat
+MAN= ctlstat.8
+SDIR= ${SRCTOP}/sys
+CFLAGS+= -I${SDIR}
+
+LIBADD= sbuf bsdxml
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ctlstat/Makefile.depend b/usr.bin/ctlstat/Makefile.depend
new file mode 100644
index 000000000000..9a89b5f28736
--- /dev/null
+++ b/usr.bin/ctlstat/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libexpat \
+ lib/libsbuf \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ctlstat/ctlstat.8 b/usr.bin/ctlstat/ctlstat.8
new file mode 100644
index 000000000000..929e29b86d06
--- /dev/null
+++ b/usr.bin/ctlstat/ctlstat.8
@@ -0,0 +1,142 @@
+.\"
+.\" Copyright (c) 2010 Silicon Graphics International Corp.
+.\" 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,
+.\" without modification.
+.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
+.\" substantially similar to the "NO WARRANTY" disclaimer below
+.\" ("Disclaimer") and any redistribution must be conditioned upon
+.\" including a substantially similar Disclaimer requirement for further
+.\" binary redistribution.
+.\"
+.\" NO WARRANTY
+.\" 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 MERCHANTIBILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+.\"
+.\" ctlstat utility man page.
+.\"
+.\" Author: Ken Merry <ken@FreeBSD.org>
+.\"
+.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.bin/ctlstat/ctlstat.8#2 $
+.\"
+.Dd April 22, 2021
+.Dt CTLSTAT 8
+.Os
+.Sh NAME
+.Nm ctlstat
+.Nd CAM Target Layer statistics utility
+.Sh SYNOPSIS
+.Nm
+.Op Fl t
+.Op Fl c Ar count
+.Op Fl C
+.Op Fl d
+.Op Fl D
+.Op Fl j
+.Op Fl P
+.Op Fl l Ar lun
+.Op Fl n Ar numdevs
+.Op Fl p Ar port
+.Op Fl w Ar wait
+.Sh DESCRIPTION
+The
+.Nm
+utility provides statistics information for the CAM Target Layer.
+The first display (except for dump and JSON modes) shows average statistics
+since system startup.
+Subsequent displays show average statistics during the measurement
+interval.
+.Pp
+The options are as follows:
+.Bl -tag -width 10n
+.It Fl t
+Total mode.
+This displays separate columns with the total read and write output,
+and a combined total column that also includes non I/O operations.
+.It Fl c Ar count
+Display statistics this many times.
+.It Fl C
+Disable CPU statistics display.
+.It Fl d
+Display DMA operation time (latency) instead of overall I/O time (latency).
+.It Fl D
+Text dump mode.
+Dump statistics every 30 seconds in a text format suitable for parsing.
+No statistics are computed in this mode, only raw numbers are displayed.
+.It Fl h
+Suppress display of the header.
+.It Fl j
+JSON dump mode.
+Dump statistics every 30 seconds in JavaScript Object Notation (JSON) format.
+No statistics are computed in this mode, only raw numbers are displayed.
+.It Fl P
+Prometheus dump mode.
+Dump statistics in a format suitable for ingestion into Prometheus.
+When invoked with this option,
+.Nm
+dumps once, regardless of the
+.Fl t
+option.
+This option is especially useful when invoked by
+.Xr inetd 8 .
+See the comments in
+.Pa /etc/inetd.conf
+for an example configuration.
+.It Fl l Ar lun
+Request statistics for the specified LUN.
+.It Fl n Ar numdevs
+Display statistics for this many devices.
+.It Fl p Ar port
+Request statistics for the specified port.
+.It Fl w Ar wait
+Wait this many seconds in between displays.
+If this option is not specified,
+.Nm
+defaults to a 1 second interval.
+.El
+.Sh EXAMPLES
+.Dl ctlstat -t
+.Pp
+Display total statistics for the system with a one second interval.
+.Pp
+.Dl ctlstat -d -l 5 -C
+.Pp
+Display average DMA time for LUN 5 and omit CPU utilization.
+.Pp
+.Dl ctlstat -n 7 -w 10
+.Pp
+Display statistics for the first 7 LUNs, and display average statistics
+every 10 seconds.
+.Sh SEE ALSO
+.Xr cam 3 ,
+.Xr cam 4 ,
+.Xr ctl 4 ,
+.Xr xpt 4 ,
+.Xr camcontrol 8 ,
+.Xr ctladm 8 ,
+.Xr ctld 8 ,
+.Xr iostat 8 ,
+.Lk
+Prometheus project:
+.Pa https://prometheus.io/ .
+.Pp
+Prometheus exposition formats:
+.Lk https://prometheus.io/docs/instrumenting/exposition_formats/ .
+.Sh AUTHORS
+.An Ken Merry Aq Mt ken@FreeBSD.org
+.An Will Andrews Aq Mt will@FreeBSD.org
+.An Alexander Motin Aq Mt mav@FreeBSD.org
diff --git a/usr.bin/ctlstat/ctlstat.c b/usr.bin/ctlstat/ctlstat.c
new file mode 100644
index 000000000000..3a2f9b7a0939
--- /dev/null
+++ b/usr.bin/ctlstat/ctlstat.c
@@ -0,0 +1,1011 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004, 2008, 2009 Silicon Graphics International Corp.
+ * Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org>
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * $Id: //depot/users/kenm/FreeBSD-test2/usr.bin/ctlstat/ctlstat.c#4 $
+ */
+/*
+ * CAM Target Layer statistics program
+ *
+ * Authors: Ken Merry <ken@FreeBSD.org>, Will Andrews <will@FreeBSD.org>
+ */
+
+#include <sys/param.h>
+#include <sys/callout.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/resource.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <assert.h>
+#include <bsdxml.h>
+#include <malloc_np.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <ctype.h>
+#include <bitstring.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/ctl/ctl.h>
+#include <cam/ctl/ctl_io.h>
+#include <cam/ctl/ctl_scsi_all.h>
+#include <cam/ctl/ctl_util.h>
+#include <cam/ctl/ctl_backend.h>
+#include <cam/ctl/ctl_ioctl.h>
+
+/*
+ * The default amount of space we allocate for stats storage space.
+ * We dynamically allocate more if needed.
+ */
+#define CTL_STAT_NUM_ITEMS 256
+
+static int ctl_stat_bits;
+
+static const char *ctlstat_opts = "Cc:DPdhjl:n:p:tw:";
+static const char *ctlstat_usage = "Usage: ctlstat [-CDPdjht] [-l lunnum]"
+ "[-c count] [-n numdevs] [-w wait]\n";
+
+struct ctl_cpu_stats {
+ uint64_t user;
+ uint64_t nice;
+ uint64_t system;
+ uint64_t intr;
+ uint64_t idle;
+};
+
+typedef enum {
+ CTLSTAT_MODE_STANDARD,
+ CTLSTAT_MODE_DUMP,
+ CTLSTAT_MODE_JSON,
+ CTLSTAT_MODE_PROMETHEUS,
+} ctlstat_mode_types;
+
+#define CTLSTAT_FLAG_CPU (1 << 0)
+#define CTLSTAT_FLAG_HEADER (1 << 1)
+#define CTLSTAT_FLAG_FIRST_RUN (1 << 2)
+#define CTLSTAT_FLAG_TOTALS (1 << 3)
+#define CTLSTAT_FLAG_DMA_TIME (1 << 4)
+#define CTLSTAT_FLAG_TIME_VALID (1 << 5)
+#define CTLSTAT_FLAG_MASK (1 << 6)
+#define CTLSTAT_FLAG_LUNS (1 << 7)
+#define CTLSTAT_FLAG_PORTS (1 << 8)
+#define F_CPU(ctx) ((ctx)->flags & CTLSTAT_FLAG_CPU)
+#define F_HDR(ctx) ((ctx)->flags & CTLSTAT_FLAG_HEADER)
+#define F_FIRST(ctx) ((ctx)->flags & CTLSTAT_FLAG_FIRST_RUN)
+#define F_TOTALS(ctx) ((ctx)->flags & CTLSTAT_FLAG_TOTALS)
+#define F_DMA(ctx) ((ctx)->flags & CTLSTAT_FLAG_DMA_TIME)
+#define F_TIMEVAL(ctx) ((ctx)->flags & CTLSTAT_FLAG_TIME_VALID)
+#define F_MASK(ctx) ((ctx)->flags & CTLSTAT_FLAG_MASK)
+#define F_LUNS(ctx) ((ctx)->flags & CTLSTAT_FLAG_LUNS)
+#define F_PORTS(ctx) ((ctx)->flags & CTLSTAT_FLAG_PORTS)
+
+struct ctlstat_context {
+ ctlstat_mode_types mode;
+ int flags;
+ struct ctl_io_stats *cur_stats, *prev_stats;
+ struct ctl_io_stats cur_total_stats[3], prev_total_stats[3];
+ struct timespec cur_time, prev_time;
+ struct ctl_cpu_stats cur_cpu, prev_cpu;
+ uint64_t cur_total_jiffies, prev_total_jiffies;
+ uint64_t cur_idle, prev_idle;
+ bitstr_t *item_mask;
+ int cur_items, prev_items;
+ int cur_alloc, prev_alloc;
+ int numdevs;
+ int header_interval;
+};
+
+struct cctl_portlist_data {
+ int level;
+ struct sbuf *cur_sb[32];
+ int id;
+ int lun;
+ int ntargets;
+ char *target;
+ char **targets;
+};
+
+#ifndef min
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+#endif
+
+static void usage(int error);
+static int getstats(int fd, int *alloc_items, int *num_items,
+ struct ctl_io_stats **xstats, struct timespec *cur_time, int *time_valid,
+ bool ports);
+static int getcpu(struct ctl_cpu_stats *cpu_stats);
+static void compute_stats(struct ctl_io_stats *cur_stats,
+ struct ctl_io_stats *prev_stats,
+ long double etime, long double *mbsec,
+ long double *kb_per_transfer,
+ long double *transfers_per_second,
+ long double *ms_per_transfer,
+ long double *ms_per_dma,
+ long double *dmas_per_second);
+
+static void
+usage(int error)
+{
+ fputs(ctlstat_usage, error ? stderr : stdout);
+}
+
+static int
+getstats(int fd, int *alloc_items, int *num_items, struct ctl_io_stats **stats,
+ struct timespec *cur_time, int *flags, bool ports)
+{
+ struct ctl_get_io_stats get_stats;
+ int more_space_count = 0;
+
+ if (*alloc_items == 0)
+ *alloc_items = CTL_STAT_NUM_ITEMS;
+retry:
+ if (*stats == NULL)
+ *stats = malloc(sizeof(**stats) * *alloc_items);
+
+ memset(&get_stats, 0, sizeof(get_stats));
+ get_stats.alloc_len = *alloc_items * sizeof(**stats);
+ memset(*stats, 0, get_stats.alloc_len);
+ get_stats.stats = *stats;
+
+ if (ioctl(fd, ports ? CTL_GET_PORT_STATS : CTL_GET_LUN_STATS,
+ &get_stats) == -1)
+ err(1, "CTL_GET_*_STATS ioctl returned error");
+
+ switch (get_stats.status) {
+ case CTL_SS_OK:
+ break;
+ case CTL_SS_ERROR:
+ err(1, "CTL_GET_*_STATS ioctl returned CTL_SS_ERROR");
+ break;
+ case CTL_SS_NEED_MORE_SPACE:
+ if (more_space_count >= 2)
+ errx(1, "CTL_GET_*_STATS returned NEED_MORE_SPACE again");
+ *alloc_items = get_stats.num_items * 5 / 4;
+ free(*stats);
+ *stats = NULL;
+ more_space_count++;
+ goto retry;
+ break; /* NOTREACHED */
+ default:
+ errx(1, "CTL_GET_*_STATS ioctl returned unknown status %d",
+ get_stats.status);
+ break;
+ }
+
+ *num_items = get_stats.fill_len / sizeof(**stats);
+ cur_time->tv_sec = get_stats.timestamp.tv_sec;
+ cur_time->tv_nsec = get_stats.timestamp.tv_nsec;
+ if (get_stats.flags & CTL_STATS_FLAG_TIME_VALID)
+ *flags |= CTLSTAT_FLAG_TIME_VALID;
+ else
+ *flags &= ~CTLSTAT_FLAG_TIME_VALID;
+
+ return (0);
+}
+
+static int
+getcpu(struct ctl_cpu_stats *cpu_stats)
+{
+ long cp_time[CPUSTATES];
+ size_t cplen;
+
+ cplen = sizeof(cp_time);
+
+ if (sysctlbyname("kern.cp_time", &cp_time, &cplen, NULL, 0) == -1) {
+ warn("sysctlbyname(kern.cp_time...) failed");
+ return (1);
+ }
+
+ cpu_stats->user = cp_time[CP_USER];
+ cpu_stats->nice = cp_time[CP_NICE];
+ cpu_stats->system = cp_time[CP_SYS];
+ cpu_stats->intr = cp_time[CP_INTR];
+ cpu_stats->idle = cp_time[CP_IDLE];
+
+ return (0);
+}
+
+static void
+compute_stats(struct ctl_io_stats *cur_stats,
+ struct ctl_io_stats *prev_stats, long double etime,
+ long double *mbsec, long double *kb_per_transfer,
+ long double *transfers_per_second, long double *ms_per_transfer,
+ long double *ms_per_dma, long double *dmas_per_second)
+{
+ uint64_t total_bytes = 0, total_operations = 0, total_dmas = 0;
+ struct bintime total_time_bt, total_dma_bt;
+ struct timespec total_time_ts, total_dma_ts;
+ int i;
+
+ bzero(&total_time_bt, sizeof(total_time_bt));
+ bzero(&total_dma_bt, sizeof(total_dma_bt));
+ bzero(&total_time_ts, sizeof(total_time_ts));
+ bzero(&total_dma_ts, sizeof(total_dma_ts));
+ for (i = 0; i < CTL_STATS_NUM_TYPES; i++) {
+ total_bytes += cur_stats->bytes[i];
+ total_operations += cur_stats->operations[i];
+ total_dmas += cur_stats->dmas[i];
+ bintime_add(&total_time_bt, &cur_stats->time[i]);
+ bintime_add(&total_dma_bt, &cur_stats->dma_time[i]);
+ if (prev_stats != NULL) {
+ total_bytes -= prev_stats->bytes[i];
+ total_operations -= prev_stats->operations[i];
+ total_dmas -= prev_stats->dmas[i];
+ bintime_sub(&total_time_bt, &prev_stats->time[i]);
+ bintime_sub(&total_dma_bt, &prev_stats->dma_time[i]);
+ }
+ }
+
+ *mbsec = total_bytes;
+ *mbsec /= 1024 * 1024;
+ if (etime > 0.0)
+ *mbsec /= etime;
+ else
+ *mbsec = 0;
+ *kb_per_transfer = total_bytes;
+ *kb_per_transfer /= 1024;
+ if (total_operations > 0)
+ *kb_per_transfer /= total_operations;
+ else
+ *kb_per_transfer = 0;
+ *transfers_per_second = total_operations;
+ *dmas_per_second = total_dmas;
+ if (etime > 0.0) {
+ *transfers_per_second /= etime;
+ *dmas_per_second /= etime;
+ } else {
+ *transfers_per_second = 0;
+ *dmas_per_second = 0;
+ }
+
+ bintime2timespec(&total_time_bt, &total_time_ts);
+ bintime2timespec(&total_dma_bt, &total_dma_ts);
+ if (total_operations > 0) {
+ /*
+ * Convert the timespec to milliseconds.
+ */
+ *ms_per_transfer = total_time_ts.tv_sec * 1000;
+ *ms_per_transfer += total_time_ts.tv_nsec / 1000000;
+ *ms_per_transfer /= total_operations;
+ } else
+ *ms_per_transfer = 0;
+
+ if (total_dmas > 0) {
+ /*
+ * Convert the timespec to milliseconds.
+ */
+ *ms_per_dma = total_dma_ts.tv_sec * 1000;
+ *ms_per_dma += total_dma_ts.tv_nsec / 1000000;
+ *ms_per_dma /= total_dmas;
+ } else
+ *ms_per_dma = 0;
+}
+
+/* The dump_stats() and json_stats() functions perform essentially the same
+ * purpose, but dump the statistics in different formats. JSON is more
+ * conducive to programming, however.
+ */
+
+#define PRINT_BINTIME(bt) \
+ printf("%jd.%06ju", (intmax_t)(bt).sec, \
+ (uintmax_t)(((bt).frac >> 32) * 1000000 >> 32))
+static const char *iotypes[] = {"NO IO", "READ", "WRITE"};
+
+static void
+ctlstat_dump(struct ctlstat_context *ctx)
+{
+ int iotype, i, n;
+ struct ctl_io_stats *stats = ctx->cur_stats;
+
+ for (i = n = 0; i < ctx->cur_items;i++) {
+ if (F_MASK(ctx) && bit_test(ctx->item_mask,
+ (int)stats[i].item) == 0)
+ continue;
+ printf("%s %d\n", F_PORTS(ctx) ? "port" : "lun", stats[i].item);
+ for (iotype = 0; iotype < CTL_STATS_NUM_TYPES; iotype++) {
+ printf(" io type %d (%s)\n", iotype, iotypes[iotype]);
+ printf(" bytes %ju\n", (uintmax_t)
+ stats[i].bytes[iotype]);
+ printf(" operations %ju\n", (uintmax_t)
+ stats[i].operations[iotype]);
+ printf(" dmas %ju\n", (uintmax_t)
+ stats[i].dmas[iotype]);
+ printf(" io time ");
+ PRINT_BINTIME(stats[i].time[iotype]);
+ printf("\n dma time ");
+ PRINT_BINTIME(stats[i].dma_time[iotype]);
+ printf("\n");
+ }
+ if (++n >= ctx->numdevs)
+ break;
+ }
+}
+
+static void
+ctlstat_json(struct ctlstat_context *ctx) {
+ int iotype, i, n;
+ struct ctl_io_stats *stats = ctx->cur_stats;
+
+ printf("{\"%s\":[", F_PORTS(ctx) ? "ports" : "luns");
+ for (i = n = 0; i < ctx->cur_items; i++) {
+ if (F_MASK(ctx) && bit_test(ctx->item_mask,
+ (int)stats[i].item) == 0)
+ continue;
+ printf("{\"num\":%d,\"io\":[",
+ stats[i].item);
+ for (iotype = 0; iotype < CTL_STATS_NUM_TYPES; iotype++) {
+ printf("{\"type\":\"%s\",", iotypes[iotype]);
+ printf("\"bytes\":%ju,", (uintmax_t)
+ stats[i].bytes[iotype]);
+ printf("\"operations\":%ju,", (uintmax_t)
+ stats[i].operations[iotype]);
+ printf("\"dmas\":%ju,", (uintmax_t)
+ stats[i].dmas[iotype]);
+ printf("\"io time\":");
+ PRINT_BINTIME(stats[i].time[iotype]);
+ printf(",\"dma time\":");
+ PRINT_BINTIME(stats[i].dma_time[iotype]);
+ printf("}");
+ if (iotype < (CTL_STATS_NUM_TYPES - 1))
+ printf(","); /* continue io array */
+ }
+ printf("]}");
+ if (++n >= ctx->numdevs)
+ break;
+ if (i < (ctx->cur_items - 1))
+ printf(","); /* continue lun array */
+ }
+ printf("]}");
+}
+
+#define CTLSTAT_PROMETHEUS_LOOP(field, collector) \
+ for (i = n = 0; i < ctx->cur_items; i++) { \
+ if (F_MASK(ctx) && bit_test(ctx->item_mask, \
+ (int)stats[i].item) == 0) \
+ continue; \
+ for (iotype = 0; iotype < CTL_STATS_NUM_TYPES; iotype++) { \
+ int idx = stats[i].item; \
+ /* \
+ * Note that Prometheus considers a label value of "" \
+ * to be the same as no label at all \
+ */ \
+ const char *target = ""; \
+ if (strcmp(collector, "port") == 0 && \
+ targdata.targets[idx] != NULL) \
+ { \
+ target = targdata.targets[idx]; \
+ } \
+ printf("iscsi_%s_" #field "{" \
+ "%s=\"%u\",target=\"%s\",type=\"%s\"} %" PRIu64 \
+ "\n", \
+ collector, collector, \
+ idx, target, iotypes[iotype], \
+ stats[i].field[iotype]); \
+ } \
+ } \
+
+#define CTLSTAT_PROMETHEUS_TIMELOOP(field, collector) \
+ for (i = n = 0; i < ctx->cur_items; i++) { \
+ if (F_MASK(ctx) && bit_test(ctx->item_mask, \
+ (int)stats[i].item) == 0) \
+ continue; \
+ for (iotype = 0; iotype < CTL_STATS_NUM_TYPES; iotype++) { \
+ uint64_t us; \
+ struct timespec ts; \
+ int idx = stats[i].item; \
+ /* \
+ * Note that Prometheus considers a label value of "" \
+ * to be the same as no label at all \
+ */ \
+ const char *target = ""; \
+ if (strcmp(collector, "port") == 0 && \
+ targdata.targets[idx] != NULL) \
+ { \
+ target = targdata.targets[idx]; \
+ } \
+ bintime2timespec(&stats[i].field[iotype], &ts); \
+ us = ts.tv_sec * 1000000 + ts.tv_nsec / 1000; \
+ printf("iscsi_%s_" #field "{" \
+ "%s=\"%u\",target=\"%s\",type=\"%s\"} %" PRIu64 \
+ "\n", \
+ collector, collector, \
+ idx, target, iotypes[iotype], us); \
+ } \
+ } \
+
+static void
+cctl_start_pelement(void *user_data, const char *name, const char **attr)
+{
+ struct cctl_portlist_data* targdata = user_data;
+
+ targdata->level++;
+ if ((u_int)targdata->level >= (sizeof(targdata->cur_sb) /
+ sizeof(targdata->cur_sb[0])))
+ errx(1, "%s: too many nesting levels, %zd max", __func__,
+ sizeof(targdata->cur_sb) / sizeof(targdata->cur_sb[0]));
+
+ targdata->cur_sb[targdata->level] = sbuf_new_auto();
+ if (targdata->cur_sb[targdata->level] == NULL)
+ err(1, "%s: Unable to allocate sbuf", __func__);
+
+ if (strcmp(name, "targ_port") == 0) {
+ int i = 0;
+
+ targdata->lun = -1;
+ targdata->id = -1;
+ free(targdata->target);
+ targdata->target = NULL;
+ while (attr[i]) {
+ if (strcmp(attr[i], "id") == 0) {
+ /*
+ * Well-formed XML always pairs keys with
+ * values in attr
+ */
+ assert(attr[i + 1]);
+ targdata->id = atoi(attr[i + 1]);
+ }
+ i += 2;
+ }
+
+ }
+}
+
+static void
+cctl_char_phandler(void *user_data, const XML_Char *str, int len)
+{
+ struct cctl_portlist_data *targdata = user_data;
+
+ sbuf_bcat(targdata->cur_sb[targdata->level], str, len);
+}
+
+static void
+cctl_end_pelement(void *user_data, const char *name)
+{
+ struct cctl_portlist_data* targdata = user_data;
+ char *str;
+
+ if (targdata->cur_sb[targdata->level] == NULL)
+ errx(1, "%s: no valid sbuf at level %d (name %s)", __func__,
+ targdata->level, name);
+
+ if (sbuf_finish(targdata->cur_sb[targdata->level]) != 0)
+ err(1, "%s: sbuf_finish", __func__);
+ str = strdup(sbuf_data(targdata->cur_sb[targdata->level]));
+ if (str == NULL)
+ err(1, "%s can't allocate %zd bytes for string", __func__,
+ sbuf_len(targdata->cur_sb[targdata->level]));
+
+ sbuf_delete(targdata->cur_sb[targdata->level]);
+ targdata->cur_sb[targdata->level] = NULL;
+ targdata->level--;
+
+ if (strcmp(name, "target") == 0) {
+ free(targdata->target);
+ targdata->target = str;
+ } else if (strcmp(name, "targ_port") == 0) {
+ if (targdata->id >= 0 && targdata->target != NULL) {
+ if (targdata->id >= targdata->ntargets) {
+ /*
+ * This can happen for example if there are
+ * targets with no LUNs.
+ */
+ targdata->ntargets = MAX(targdata->ntargets * 2,
+ targdata->id + 1);
+ size_t newsize = targdata->ntargets *
+ sizeof(char*);
+ targdata->targets = rallocx(targdata->targets,
+ newsize, MALLOCX_ZERO);
+ }
+ free(targdata->targets[targdata->id]);
+ targdata->targets[targdata->id] = targdata->target;
+ targdata->target = NULL;
+ }
+ free(str);
+ } else {
+ free(str);
+ }
+}
+
+static void
+ctlstat_prometheus(int fd, struct ctlstat_context *ctx, bool ports) {
+ struct ctl_io_stats *stats = ctx->cur_stats;
+ struct ctl_lun_list list;
+ struct cctl_portlist_data targdata;
+ XML_Parser parser;
+ char *port_str = NULL;
+ int iotype, i, n, retval;
+ int port_len = 4096;
+ const char *collector;
+
+ bzero(&targdata, sizeof(targdata));
+ targdata.ntargets = ctx->cur_items;
+ targdata.targets = calloc(targdata.ntargets, sizeof(char*));
+retry:
+ port_str = (char *)realloc(port_str, port_len);
+ bzero(&list, sizeof(list));
+ list.alloc_len = port_len;
+ list.status = CTL_LUN_LIST_NONE;
+ list.lun_xml = port_str;
+ if (ioctl(fd, CTL_PORT_LIST, &list) == -1)
+ err(1, "%s: error issuing CTL_PORT_LIST ioctl", __func__);
+ if (list.status == CTL_LUN_LIST_ERROR) {
+ warnx("%s: error returned from CTL_PORT_LIST ioctl:\n%s",
+ __func__, list.error_str);
+ } else if (list.status == CTL_LUN_LIST_NEED_MORE_SPACE) {
+ port_len <<= 1;
+ goto retry;
+ }
+
+ parser = XML_ParserCreate(NULL);
+ if (parser == NULL)
+ err(1, "%s: Unable to create XML parser", __func__);
+ XML_SetUserData(parser, &targdata);
+ XML_SetElementHandler(parser, cctl_start_pelement, cctl_end_pelement);
+ XML_SetCharacterDataHandler(parser, cctl_char_phandler);
+
+ retval = XML_Parse(parser, port_str, strlen(port_str), 1);
+ if (retval != 1) {
+ errx(1, "%s: Unable to parse XML: Error %d", __func__,
+ XML_GetErrorCode(parser));
+ }
+ XML_ParserFree(parser);
+
+ collector = ports ? "port" : "lun";
+
+ printf("# HELP iscsi_%s_bytes Number of bytes\n"
+ "# TYPE iscsi_%s_bytes counter\n", collector, collector);
+ CTLSTAT_PROMETHEUS_LOOP(bytes, collector);
+ printf("# HELP iscsi_%s_dmas Number of DMA\n"
+ "# TYPE iscsi_%s_dmas counter\n", collector, collector);
+ CTLSTAT_PROMETHEUS_LOOP(dmas, collector);
+ printf("# HELP iscsi_%s_operations Number of operations\n"
+ "# TYPE iscsi_%s_operations counter\n", collector, collector);
+ CTLSTAT_PROMETHEUS_LOOP(operations, collector);
+ printf("# HELP iscsi_%s_time Cumulative operation time in us\n"
+ "# TYPE iscsi_%s_time counter\n", collector, collector);
+ CTLSTAT_PROMETHEUS_TIMELOOP(time, collector);
+ printf("# HELP iscsi_%s_dma_time Cumulative DMA time in us\n"
+ "# TYPE iscsi_%s_dma_time counter\n", collector, collector);
+ CTLSTAT_PROMETHEUS_TIMELOOP(dma_time, collector);
+
+ for (i = 0; i < targdata.ntargets; i++)
+ free(targdata.targets[i]);
+ free(targdata.target);
+ free(targdata.targets);
+
+ fflush(stdout);
+}
+
+static void
+ctlstat_standard(struct ctlstat_context *ctx) {
+ long double etime;
+ uint64_t delta_jiffies, delta_idle;
+ long double cpu_percentage;
+ int i, j, n;
+
+ cpu_percentage = 0;
+
+ if (F_CPU(ctx) && (getcpu(&ctx->cur_cpu) != 0))
+ errx(1, "error returned from getcpu()");
+
+ etime = ctx->cur_time.tv_sec - ctx->prev_time.tv_sec +
+ (ctx->prev_time.tv_nsec - ctx->cur_time.tv_nsec) * 1e-9;
+
+ if (F_CPU(ctx)) {
+ ctx->prev_total_jiffies = ctx->cur_total_jiffies;
+ ctx->cur_total_jiffies = ctx->cur_cpu.user +
+ ctx->cur_cpu.nice + ctx->cur_cpu.system +
+ ctx->cur_cpu.intr + ctx->cur_cpu.idle;
+ delta_jiffies = ctx->cur_total_jiffies;
+ if (F_FIRST(ctx) == 0)
+ delta_jiffies -= ctx->prev_total_jiffies;
+ ctx->prev_idle = ctx->cur_idle;
+ ctx->cur_idle = ctx->cur_cpu.idle;
+ delta_idle = ctx->cur_idle - ctx->prev_idle;
+
+ cpu_percentage = delta_jiffies - delta_idle;
+ cpu_percentage /= delta_jiffies;
+ cpu_percentage *= 100;
+ }
+
+ if (F_HDR(ctx)) {
+ ctx->header_interval--;
+ if (ctx->header_interval <= 0) {
+ if (F_CPU(ctx))
+ fprintf(stdout, " CPU");
+ if (F_TOTALS(ctx)) {
+ fprintf(stdout, "%s Read %s"
+ " Write %s Total\n",
+ (F_TIMEVAL(ctx) != 0) ? " " : "",
+ (F_TIMEVAL(ctx) != 0) ? " " : "",
+ (F_TIMEVAL(ctx) != 0) ? " " : "");
+ n = 3;
+ } else {
+ for (i = n = 0; i < min(ctl_stat_bits,
+ ctx->cur_items); i++) {
+ int item;
+
+ /*
+ * Obviously this won't work with
+ * LUN numbers greater than a signed
+ * integer.
+ */
+ item = (int)ctx->cur_stats[i].item;
+
+ if (F_MASK(ctx) &&
+ bit_test(ctx->item_mask, item) == 0)
+ continue;
+ fprintf(stdout, "%15.6s%d %s",
+ F_PORTS(ctx) ? "port" : "lun", item,
+ (F_TIMEVAL(ctx) != 0) ? " " : "");
+ if (++n >= ctx->numdevs)
+ break;
+ }
+ fprintf(stdout, "\n");
+ }
+ if (F_CPU(ctx))
+ fprintf(stdout, " ");
+ for (i = 0; i < n; i++)
+ fprintf(stdout, "%s KB/t %s MB/s",
+ (F_TIMEVAL(ctx) != 0) ? " ms" : "",
+ (F_DMA(ctx) == 0) ? "tps" : "dps");
+ fprintf(stdout, "\n");
+ ctx->header_interval = 20;
+ }
+ }
+
+ if (F_CPU(ctx))
+ fprintf(stdout, "%3.0Lf%%", cpu_percentage);
+ if (F_TOTALS(ctx) != 0) {
+ long double mbsec[3];
+ long double kb_per_transfer[3];
+ long double transfers_per_sec[3];
+ long double ms_per_transfer[3];
+ long double ms_per_dma[3];
+ long double dmas_per_sec[3];
+
+ for (i = 0; i < 3; i++)
+ ctx->prev_total_stats[i] = ctx->cur_total_stats[i];
+
+ memset(&ctx->cur_total_stats, 0, sizeof(ctx->cur_total_stats));
+
+ /* Use macros to make the next loop more readable. */
+#define ADD_STATS_BYTES(st, i, j) \
+ ctx->cur_total_stats[st].bytes[j] += \
+ ctx->cur_stats[i].bytes[j]
+#define ADD_STATS_OPERATIONS(st, i, j) \
+ ctx->cur_total_stats[st].operations[j] += \
+ ctx->cur_stats[i].operations[j]
+#define ADD_STATS_DMAS(st, i, j) \
+ ctx->cur_total_stats[st].dmas[j] += \
+ ctx->cur_stats[i].dmas[j]
+#define ADD_STATS_TIME(st, i, j) \
+ bintime_add(&ctx->cur_total_stats[st].time[j], \
+ &ctx->cur_stats[i].time[j])
+#define ADD_STATS_DMA_TIME(st, i, j) \
+ bintime_add(&ctx->cur_total_stats[st].dma_time[j], \
+ &ctx->cur_stats[i].dma_time[j])
+
+ for (i = 0; i < ctx->cur_items; i++) {
+ if (F_MASK(ctx) && bit_test(ctx->item_mask,
+ (int)ctx->cur_stats[i].item) == 0)
+ continue;
+ for (j = 0; j < CTL_STATS_NUM_TYPES; j++) {
+ ADD_STATS_BYTES(2, i, j);
+ ADD_STATS_OPERATIONS(2, i, j);
+ ADD_STATS_DMAS(2, i, j);
+ ADD_STATS_TIME(2, i, j);
+ ADD_STATS_DMA_TIME(2, i, j);
+ }
+ ADD_STATS_BYTES(0, i, CTL_STATS_READ);
+ ADD_STATS_OPERATIONS(0, i, CTL_STATS_READ);
+ ADD_STATS_DMAS(0, i, CTL_STATS_READ);
+ ADD_STATS_TIME(0, i, CTL_STATS_READ);
+ ADD_STATS_DMA_TIME(0, i, CTL_STATS_READ);
+
+ ADD_STATS_BYTES(1, i, CTL_STATS_WRITE);
+ ADD_STATS_OPERATIONS(1, i, CTL_STATS_WRITE);
+ ADD_STATS_DMAS(1, i, CTL_STATS_WRITE);
+ ADD_STATS_TIME(1, i, CTL_STATS_WRITE);
+ ADD_STATS_DMA_TIME(1, i, CTL_STATS_WRITE);
+ }
+
+ for (i = 0; i < 3; i++) {
+ compute_stats(&ctx->cur_total_stats[i],
+ F_FIRST(ctx) ? NULL : &ctx->prev_total_stats[i],
+ etime, &mbsec[i], &kb_per_transfer[i],
+ &transfers_per_sec[i],
+ &ms_per_transfer[i], &ms_per_dma[i],
+ &dmas_per_sec[i]);
+ if (F_DMA(ctx) != 0)
+ fprintf(stdout, " %5.1Lf",
+ ms_per_dma[i]);
+ else if (F_TIMEVAL(ctx) != 0)
+ fprintf(stdout, " %5.1Lf",
+ ms_per_transfer[i]);
+ fprintf(stdout, " %4.0Lf %5.0Lf %4.0Lf",
+ kb_per_transfer[i],
+ (F_DMA(ctx) == 0) ? transfers_per_sec[i] :
+ dmas_per_sec[i], mbsec[i]);
+ }
+ } else {
+ for (i = n = 0; i < min(ctl_stat_bits, ctx->cur_items); i++) {
+ long double mbsec, kb_per_transfer;
+ long double transfers_per_sec;
+ long double ms_per_transfer;
+ long double ms_per_dma;
+ long double dmas_per_sec;
+
+ if (F_MASK(ctx) && bit_test(ctx->item_mask,
+ (int)ctx->cur_stats[i].item) == 0)
+ continue;
+ for (j = 0; j < ctx->prev_items; j++) {
+ if (ctx->prev_stats[j].item ==
+ ctx->cur_stats[i].item)
+ break;
+ }
+ if (j >= ctx->prev_items)
+ j = -1;
+ compute_stats(&ctx->cur_stats[i],
+ j >= 0 ? &ctx->prev_stats[j] : NULL,
+ etime, &mbsec, &kb_per_transfer,
+ &transfers_per_sec, &ms_per_transfer,
+ &ms_per_dma, &dmas_per_sec);
+ if (F_DMA(ctx))
+ fprintf(stdout, " %5.1Lf",
+ ms_per_dma);
+ else if (F_TIMEVAL(ctx) != 0)
+ fprintf(stdout, " %5.1Lf",
+ ms_per_transfer);
+ fprintf(stdout, " %4.0Lf %5.0Lf %4.0Lf",
+ kb_per_transfer, (F_DMA(ctx) == 0) ?
+ transfers_per_sec : dmas_per_sec, mbsec);
+ if (++n >= ctx->numdevs)
+ break;
+ }
+ }
+}
+
+static void
+get_and_print_stats(int fd, struct ctlstat_context *ctx, bool ports)
+{
+ struct ctl_io_stats *tmp_stats;
+ int c;
+
+ tmp_stats = ctx->prev_stats;
+ ctx->prev_stats = ctx->cur_stats;
+ ctx->cur_stats = tmp_stats;
+ c = ctx->prev_alloc;
+ ctx->prev_alloc = ctx->cur_alloc;
+ ctx->cur_alloc = c;
+ c = ctx->prev_items;
+ ctx->prev_items = ctx->cur_items;
+ ctx->cur_items = c;
+ ctx->prev_time = ctx->cur_time;
+ ctx->prev_cpu = ctx->cur_cpu;
+ if (getstats(fd, &ctx->cur_alloc, &ctx->cur_items,
+ &ctx->cur_stats, &ctx->cur_time, &ctx->flags, ports) != 0)
+ errx(1, "error returned from getstats()");
+
+ switch(ctx->mode) {
+ case CTLSTAT_MODE_STANDARD:
+ ctlstat_standard(ctx);
+ break;
+ case CTLSTAT_MODE_DUMP:
+ ctlstat_dump(ctx);
+ break;
+ case CTLSTAT_MODE_JSON:
+ ctlstat_json(ctx);
+ break;
+ case CTLSTAT_MODE_PROMETHEUS:
+ ctlstat_prometheus(fd, ctx, ports);
+ break;
+ default:
+ break;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ int count, waittime;
+ int fd, retval;
+ size_t size;
+ struct ctlstat_context ctx;
+
+ /* default values */
+ retval = 0;
+ waittime = 1;
+ count = -1;
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.numdevs = 3;
+ ctx.mode = CTLSTAT_MODE_STANDARD;
+ ctx.flags |= CTLSTAT_FLAG_CPU;
+ ctx.flags |= CTLSTAT_FLAG_FIRST_RUN;
+ ctx.flags |= CTLSTAT_FLAG_HEADER;
+
+ size = sizeof(ctl_stat_bits);
+ if (sysctlbyname("kern.cam.ctl.max_luns", &ctl_stat_bits, &size, NULL,
+ 0) == -1) {
+ /* Backward compatibility for where the sysctl wasn't exposed */
+ ctl_stat_bits = 1024;
+ }
+ ctx.item_mask = bit_alloc(ctl_stat_bits);
+ if (ctx.item_mask == NULL)
+ err(1, "bit_alloc() failed");
+
+ while ((c = getopt(argc, argv, ctlstat_opts)) != -1) {
+ switch (c) {
+ case 'C':
+ ctx.flags &= ~CTLSTAT_FLAG_CPU;
+ break;
+ case 'c':
+ count = atoi(optarg);
+ break;
+ case 'd':
+ ctx.flags |= CTLSTAT_FLAG_DMA_TIME;
+ break;
+ case 'D':
+ ctx.mode = CTLSTAT_MODE_DUMP;
+ waittime = 30;
+ break;
+ case 'h':
+ ctx.flags &= ~CTLSTAT_FLAG_HEADER;
+ break;
+ case 'j':
+ ctx.mode = CTLSTAT_MODE_JSON;
+ waittime = 30;
+ break;
+ case 'l': {
+ int cur_lun;
+
+ cur_lun = atoi(optarg);
+ if (cur_lun > ctl_stat_bits)
+ errx(1, "Invalid LUN number %d", cur_lun);
+
+ if (!F_MASK(&ctx))
+ ctx.numdevs = 1;
+ else
+ ctx.numdevs++;
+ bit_set(ctx.item_mask, cur_lun);
+ ctx.flags |= CTLSTAT_FLAG_MASK;
+ ctx.flags |= CTLSTAT_FLAG_LUNS;
+ break;
+ }
+ case 'n':
+ ctx.numdevs = atoi(optarg);
+ break;
+ case 'p': {
+ int cur_port;
+
+ cur_port = atoi(optarg);
+ if (cur_port > ctl_stat_bits)
+ errx(1, "Invalid port number %d", cur_port);
+
+ if (!F_MASK(&ctx))
+ ctx.numdevs = 1;
+ else
+ ctx.numdevs++;
+ bit_set(ctx.item_mask, cur_port);
+ ctx.flags |= CTLSTAT_FLAG_MASK;
+ ctx.flags |= CTLSTAT_FLAG_PORTS;
+ break;
+ }
+ case 'P':
+ ctx.mode = CTLSTAT_MODE_PROMETHEUS;
+ break;
+ case 't':
+ ctx.flags |= CTLSTAT_FLAG_TOTALS;
+ break;
+ case 'w':
+ waittime = atoi(optarg);
+ break;
+ default:
+ retval = 1;
+ usage(retval);
+ exit(retval);
+ break;
+ }
+ }
+
+ if (F_LUNS(&ctx) && F_PORTS(&ctx))
+ errx(1, "Options -p and -l are exclusive.");
+
+ if (ctx.mode == CTLSTAT_MODE_PROMETHEUS) {
+ if ((count != -1) ||
+ (waittime != 1) ||
+ (F_PORTS(&ctx)) ||
+ /* NB: -P could be compatible with -t in the future */
+ (ctx.flags & CTLSTAT_FLAG_TOTALS))
+ {
+ errx(1, "Option -P is exclusive with -p, -c, -w, and -t");
+ }
+ count = 1;
+ }
+
+ if (!F_LUNS(&ctx) && !F_PORTS(&ctx)) {
+ if (F_TOTALS(&ctx))
+ ctx.flags |= CTLSTAT_FLAG_PORTS;
+ else
+ ctx.flags |= CTLSTAT_FLAG_LUNS;
+ }
+
+ if ((fd = open(CTL_DEFAULT_DEV, O_RDWR)) == -1)
+ err(1, "cannot open %s", CTL_DEFAULT_DEV);
+
+ if (ctx.mode == CTLSTAT_MODE_PROMETHEUS) {
+ /*
+ * NB: Some clients will print a warning if we don't set
+ * Content-Length, but they still work. And the data still
+ * gets into Prometheus.
+ */
+ printf("HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/plain; version=0.0.4\r\n"
+ "\r\n");
+ }
+
+ for (;count != 0;) {
+ bool ports;
+
+ if (ctx.mode == CTLSTAT_MODE_PROMETHEUS) {
+ get_and_print_stats(fd, &ctx, false);
+ get_and_print_stats(fd, &ctx, true);
+ } else {
+ ports = ctx.flags & CTLSTAT_FLAG_PORTS;
+ get_and_print_stats(fd, &ctx, ports);
+ }
+
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ ctx.flags &= ~CTLSTAT_FLAG_FIRST_RUN;
+ if (count != 1)
+ sleep(waittime);
+ if (count > 0)
+ count--;
+ }
+
+ exit (retval);
+}
+
+/*
+ * vim: ts=8
+ */
diff --git a/usr.bin/cut/Makefile b/usr.bin/cut/Makefile
new file mode 100644
index 000000000000..bdb5040c21d8
--- /dev/null
+++ b/usr.bin/cut/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= cut
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cut/Makefile.depend b/usr.bin/cut/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/cut/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cut/cut.1 b/usr.bin/cut/cut.1
new file mode 100644
index 000000000000..4f5b7b9bb9a5
--- /dev/null
+++ b/usr.bin/cut/cut.1
@@ -0,0 +1,170 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd November 6, 2022
+.Dt CUT 1
+.Os
+.Sh NAME
+.Nm cut
+.Nd cut out selected portions of each line of a file
+.Sh SYNOPSIS
+.Nm
+.Fl b Ar list
+.Op Fl n
+.Op Ar
+.Nm
+.Fl c Ar list
+.Op Ar
+.Nm
+.Fl f Ar list
+.Op Fl w | Fl d Ar delim
+.Op Fl s
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility cuts out selected portions of each line (as specified by
+.Ar list )
+from each
+.Ar file
+and writes them to the standard output.
+If no
+.Ar file
+arguments are specified, or a file argument is a single dash
+.Pq Sq Fl ,
+.Nm
+reads from the standard input.
+The items specified by
+.Ar list
+can be in terms of column position or in terms of fields delimited
+by a special character.
+Column and field numbering start from 1.
+.Pp
+The
+.Ar list
+option argument
+is a comma or whitespace separated set of increasing numbers and/or
+number ranges.
+Number ranges consist of a number, a dash
+.Pq Sq \- ,
+and a second number
+and select the columns or fields from the first number to the second,
+inclusive.
+Numbers or number ranges may be preceded by a dash, which selects all
+columns or fields from 1 to the last number.
+Numbers or number ranges may be followed by a dash, which selects all
+columns or fields from the last number to the end of the line.
+Numbers and number ranges may be repeated, overlapping, and in any order.
+It is not an error to select columns or fields not present in the
+input line.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b Ar list
+The
+.Ar list
+specifies byte positions.
+.It Fl c Ar list
+The
+.Ar list
+specifies character positions.
+.It Fl d Ar delim
+Use
+.Ar delim
+as the field delimiter character instead of the tab character.
+.It Fl f Ar list
+The
+.Ar list
+specifies fields, separated in the input by the field delimiter character
+(see the
+.Fl d
+option).
+Output fields are separated by a single occurrence of the field delimiter
+character.
+.It Fl n
+Do not split multi-byte characters.
+Characters will only be output if at least one byte is selected, and,
+after a prefix of zero or more unselected bytes, the rest of the bytes
+that form the character are selected.
+.It Fl s
+Suppress lines with no field delimiter characters.
+Unless specified, lines with no delimiters are passed through unmodified.
+.It Fl w
+Use whitespace (spaces and tabs) as the delimiter.
+Consecutive spaces and tabs count as one single field separator.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Extract users' login names and shells from the system
+.Xr passwd 5
+file as
+.Dq name:shell
+pairs:
+.Pp
+.Dl "cut -d : -f 1,7 /etc/passwd"
+.Pp
+Show the names and login times of the currently logged in users:
+.Pp
+.Dl "who | cut -c 1-16,26-38"
+.Sh SEE ALSO
+.Xr colrm 1 ,
+.Xr paste 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.2-92 .
+.Pp
+The
+.Fl w
+flag is an extension to the specification.
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.Bx 4.3 Reno .
+.Sh AUTHORS
+.An -nosplit
+The original Bell Labs version was written by
+.An Gottfried W. R. Luderer
+and the
+.Bx
+version by
+.An Adam S. Moskowitz .
diff --git a/usr.bin/cut/cut.c b/usr.bin/cut/cut.c
new file mode 100644
index 000000000000..60ff5a31062a
--- /dev/null
+++ b/usr.bin/cut/cut.c
@@ -0,0 +1,481 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue.
+ *
+ * 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 <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+static int bflag;
+static int cflag;
+static wchar_t dchar;
+static char dcharmb[MB_LEN_MAX + 1];
+static int dflag;
+static int fflag;
+static int nflag;
+static int sflag;
+static int wflag;
+
+static size_t autostart, autostop, maxval;
+static char * positions;
+
+static int b_cut(FILE *, const char *);
+static int b_n_cut(FILE *, const char *);
+static int c_cut(FILE *, const char *);
+static int f_cut(FILE *, const char *);
+static void get_list(char *);
+static int is_delim(wchar_t);
+static void needpos(size_t);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp;
+ int (*fcn)(FILE *, const char *);
+ int ch, rval;
+ size_t n;
+
+ setlocale(LC_ALL, "");
+
+ fcn = NULL;
+ dchar = '\t'; /* default delimiter is \t */
+ strcpy(dcharmb, "\t");
+
+ while ((ch = getopt(argc, argv, "b:c:d:f:snw")) != -1)
+ switch(ch) {
+ case 'b':
+ get_list(optarg);
+ bflag = 1;
+ break;
+ case 'c':
+ get_list(optarg);
+ cflag = 1;
+ break;
+ case 'd':
+ n = mbrtowc(&dchar, optarg, MB_LEN_MAX, NULL);
+ if (dchar == '\0' || n != strlen(optarg))
+ errx(1, "bad delimiter");
+ strcpy(dcharmb, optarg);
+ dflag = 1;
+ break;
+ case 'f':
+ get_list(optarg);
+ fflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'w':
+ wflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (fflag) {
+ if (bflag || cflag || nflag || (wflag && dflag))
+ usage();
+ } else if (!(bflag || cflag) || dflag || sflag || wflag)
+ usage();
+ else if (!bflag && nflag)
+ usage();
+
+ if (fflag)
+ fcn = f_cut;
+ else if (cflag)
+ fcn = MB_CUR_MAX > 1 ? c_cut : b_cut;
+ else if (bflag)
+ fcn = nflag && MB_CUR_MAX > 1 ? b_n_cut : b_cut;
+
+ rval = 0;
+ if (*argv)
+ for (; *argv; ++argv) {
+ if (strcmp(*argv, "-") == 0)
+ rval |= fcn(stdin, "stdin");
+ else {
+ if (!(fp = fopen(*argv, "r"))) {
+ warn("%s", *argv);
+ rval = 1;
+ continue;
+ }
+ fcn(fp, *argv);
+ (void)fclose(fp);
+ }
+ }
+ else
+ rval = fcn(stdin, "stdin");
+ exit(rval);
+}
+
+static void
+get_list(char *list)
+{
+ size_t setautostart, start, stop;
+ char *pos;
+ char *p;
+
+ /*
+ * set a byte in the positions array to indicate if a field or
+ * column is to be selected; use +1, it's 1-based, not 0-based.
+ * Numbers and number ranges may be overlapping, repeated, and in
+ * any order. We handle "-3-5" although there's no real reason to.
+ */
+ for (; (p = strsep(&list, ", \t")) != NULL;) {
+ setautostart = start = stop = 0;
+ if (*p == '-') {
+ ++p;
+ setautostart = 1;
+ }
+ if (isdigit((unsigned char)*p)) {
+ start = stop = strtol(p, &p, 10);
+ if (setautostart && start > autostart)
+ autostart = start;
+ }
+ if (*p == '-') {
+ if (isdigit((unsigned char)p[1]))
+ stop = strtol(p + 1, &p, 10);
+ if (*p == '-') {
+ ++p;
+ if (!autostop || autostop > stop)
+ autostop = stop;
+ }
+ }
+ if (*p)
+ errx(1, "[-bcf] list: illegal list value");
+ if (!stop || !start)
+ errx(1, "[-bcf] list: values may not include zero");
+ if (maxval < stop) {
+ maxval = stop;
+ needpos(maxval + 1);
+ }
+ for (pos = positions + start; start++ <= stop; *pos++ = 1);
+ }
+
+ /* overlapping ranges */
+ if (autostop && maxval > autostop) {
+ maxval = autostop;
+ needpos(maxval + 1);
+ }
+
+ /* reversed range with autostart */
+ if (maxval < autostart) {
+ maxval = autostart;
+ needpos(maxval + 1);
+ }
+
+ /* set autostart */
+ if (autostart)
+ memset(positions + 1, '1', autostart);
+}
+
+static void
+needpos(size_t n)
+{
+ static size_t npos;
+ size_t oldnpos;
+
+ /* Grow the positions array to at least the specified size. */
+ if (n > npos) {
+ oldnpos = npos;
+ if (npos == 0)
+ npos = n;
+ while (n > npos)
+ npos *= 2;
+ if ((positions = realloc(positions, npos)) == NULL)
+ err(1, "realloc");
+ memset((char *)positions + oldnpos, 0, npos - oldnpos);
+ }
+}
+
+static int
+b_cut(FILE *fp, const char *fname __unused)
+{
+ int ch, col;
+ char *pos;
+
+ ch = 0;
+ for (;;) {
+ pos = positions + 1;
+ for (col = maxval; col; --col) {
+ if ((ch = getc(fp)) == EOF)
+ return (0);
+ if (ch == '\n')
+ break;
+ if (*pos++)
+ (void)putchar(ch);
+ }
+ if (ch != '\n') {
+ if (autostop)
+ while ((ch = getc(fp)) != EOF && ch != '\n')
+ (void)putchar(ch);
+ else
+ while ((ch = getc(fp)) != EOF && ch != '\n');
+ }
+ (void)putchar('\n');
+ }
+ return (0);
+}
+
+/*
+ * Cut based on byte positions, taking care not to split multibyte characters.
+ * Although this function also handles the case where -n is not specified,
+ * b_cut() ought to be much faster.
+ */
+static int
+b_n_cut(FILE *fp, const char *fname)
+{
+ size_t col, i, bufsize = 0;
+ ssize_t lbuflen;
+ char *lbuf = NULL;
+ int canwrite, clen, warned;
+ mbstate_t mbs;
+
+ memset(&mbs, 0, sizeof(mbs));
+ warned = 0;
+ while ((lbuflen = getline(&lbuf, &bufsize, fp)) >= 0) {
+ for (col = 0; lbuflen > 0; col += clen) {
+ if ((clen = mbrlen(lbuf, lbuflen, &mbs)) < 0) {
+ if (!warned) {
+ warn("%s", fname);
+ warned = 1;
+ }
+ memset(&mbs, 0, sizeof(mbs));
+ clen = 1;
+ }
+ if (clen == 0 || *lbuf == '\n')
+ break;
+ if (col < maxval && !positions[1 + col]) {
+ /*
+ * Print the character if (1) after an initial
+ * segment of un-selected bytes, the rest of
+ * it is selected, and (2) the last byte is
+ * selected.
+ */
+ i = col;
+ while (i < col + clen && i < maxval &&
+ !positions[1 + i])
+ i++;
+ canwrite = i < col + clen;
+ for (; i < col + clen && i < maxval; i++)
+ canwrite &= positions[1 + i];
+ if (canwrite)
+ fwrite(lbuf, 1, clen, stdout);
+ } else {
+ /*
+ * Print the character if all of it has
+ * been selected.
+ */
+ canwrite = 1;
+ for (i = col; i < col + clen; i++)
+ if ((i >= maxval && !autostop) ||
+ (i < maxval && !positions[1 + i])) {
+ canwrite = 0;
+ break;
+ }
+ if (canwrite)
+ fwrite(lbuf, 1, clen, stdout);
+ }
+ lbuf += clen;
+ lbuflen -= clen;
+ }
+ if (lbuflen > 0)
+ putchar('\n');
+ }
+ free(lbuf);
+ return (warned);
+}
+
+static int
+c_cut(FILE *fp, const char *fname)
+{
+ wint_t ch;
+ int col;
+ char *pos;
+
+ ch = 0;
+ for (;;) {
+ pos = positions + 1;
+ for (col = maxval; col; --col) {
+ if ((ch = getwc(fp)) == WEOF)
+ goto out;
+ if (ch == '\n')
+ break;
+ if (*pos++)
+ (void)putwchar(ch);
+ }
+ if (ch != '\n') {
+ if (autostop)
+ while ((ch = getwc(fp)) != WEOF && ch != '\n')
+ (void)putwchar(ch);
+ else
+ while ((ch = getwc(fp)) != WEOF && ch != '\n');
+ }
+ (void)putwchar('\n');
+ }
+out:
+ if (ferror(fp)) {
+ warn("%s", fname);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+is_delim(wchar_t ch)
+{
+ if (wflag) {
+ if (ch == ' ' || ch == '\t')
+ return 1;
+ } else {
+ if (ch == dchar)
+ return 1;
+ }
+ return 0;
+}
+
+static int
+f_cut(FILE *fp, const char *fname)
+{
+ wchar_t ch;
+ int field, i, isdelim;
+ char *pos, *p;
+ int output;
+ char *lbuf = NULL;
+ size_t clen, bufsize = 0, reallen;
+ ssize_t lbuflen;
+
+ while ((lbuflen = getline(&lbuf, &bufsize, fp)) >= 0) {
+ reallen = lbuflen;
+ /* Assert EOL has a newline. */
+ if (lbuflen > 0 && *(lbuf + lbuflen - 1) != '\n') {
+ /* Can't have > 1 line with no trailing newline. */
+ if ((ssize_t)bufsize < (lbuflen + 1)) {
+ bufsize = lbuflen + 1;
+ lbuf = realloc(lbuf, bufsize);
+ }
+ if (lbuf == NULL)
+ err(1, "realloc");
+ lbuf[lbuflen] = '\n';
+ reallen++;
+ }
+ output = 0;
+ for (isdelim = 0, p = lbuf;; p += clen) {
+ clen = mbrtowc(&ch, p, lbuf + reallen - p, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ warnc(EILSEQ, "%s", fname);
+ free(lbuf);
+ return (1);
+ }
+ if (clen == 0)
+ clen = 1;
+ /* this should work if newline is delimiter */
+ if (is_delim(ch))
+ isdelim = 1;
+ if (ch == '\n') {
+ if (!isdelim && !sflag)
+ (void)fwrite(lbuf, lbuflen, 1, stdout);
+ break;
+ }
+ }
+ if (!isdelim)
+ continue;
+
+ pos = positions + 1;
+ for (field = maxval, p = lbuf; field; --field, ++pos) {
+ if (*pos && output++)
+ for (i = 0; dcharmb[i] != '\0'; i++)
+ putchar(dcharmb[i]);
+ for (;;) {
+ clen = mbrtowc(&ch, p, lbuf + reallen - p,
+ NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ warnc(EILSEQ, "%s", fname);
+ free(lbuf);
+ return (1);
+ }
+ if (clen == 0)
+ clen = 1;
+ p += clen;
+ if (ch == '\n' || is_delim(ch)) {
+ /* compress whitespace */
+ if (wflag && ch != '\n')
+ while (is_delim(*p))
+ p++;
+ break;
+ }
+ if (*pos)
+ for (i = 0; i < (int)clen; i++)
+ putchar(p[i - clen]);
+ }
+ if (ch == '\n')
+ break;
+ }
+ if (ch != '\n') {
+ if (autostop) {
+ if (output)
+ for (i = 0; dcharmb[i] != '\0'; i++)
+ putchar(dcharmb[i]);
+ for (; (ch = *p) != '\n'; ++p)
+ (void)putchar(ch);
+ } else
+ for (; (ch = *p) != '\n'; ++p);
+ }
+ (void)putchar('\n');
+ }
+ free(lbuf);
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n",
+ "usage: cut -b list [-n] [file ...]",
+ " cut -c list [file ...]",
+ " cut -f list [-s] [-w | -d delim] [file ...]");
+ exit(1);
+}
diff --git a/usr.bin/cut/tests/Makefile b/usr.bin/cut/tests/Makefile
new file mode 100644
index 000000000000..bd02245ced1f
--- /dev/null
+++ b/usr.bin/cut/tests/Makefile
@@ -0,0 +1,16 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= cut2_test
+NETBSD_ATF_TESTS_SH= cut_test
+
+${PACKAGE}FILES= d_basic.out
+${PACKAGE}FILES+= d_cut.in
+${PACKAGE}FILES+= d_dflag.out
+${PACKAGE}FILES+= d_dsflag.out
+${PACKAGE}FILES+= d_latin1.in
+${PACKAGE}FILES+= d_sflag.out
+${PACKAGE}FILES+= d_utf8.in
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/cut/tests/Makefile.depend b/usr.bin/cut/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/cut/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/cut/tests/cut2_test.sh b/usr.bin/cut/tests/cut2_test.sh
new file mode 100755
index 000000000000..ffb9f9fee963
--- /dev/null
+++ b/usr.bin/cut/tests/cut2_test.sh
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2017 Dell EMC
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case s_flag
+s_flag_head()
+{
+ atf_set "descr" "Check -s flag"
+}
+
+s_flag_body()
+{
+ cat >input<<EOF
+a,b,c,d
+b,c,d
+c,d
+d
+EOF
+ atf_check -o inline:'a\nb\nc\n' cut -d, -f 1 -s < input
+ atf_check -o inline:'d\n\n\n' cut -d, -f 4 -s < input
+ atf_check -o inline:'a,b,\nb,\n\n' cut -d 'c' -f 1 -s < input
+ atf_check -o empty cut -d'!' -f 1 -s < input
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case s_flag
+}
diff --git a/usr.bin/cxxfilt/Makefile b/usr.bin/cxxfilt/Makefile
new file mode 100644
index 000000000000..fe7fe2d579e5
--- /dev/null
+++ b/usr.bin/cxxfilt/Makefile
@@ -0,0 +1,17 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+SRCDIR= ${ELFTCDIR}/cxxfilt
+
+.PATH: ${SRCDIR}
+
+PROG= c++filt
+SRCS= cxxfilt.c
+
+LIBADD= elftc
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/cxxfilt/Makefile.depend b/usr.bin/cxxfilt/Makefile.depend
new file mode 100644
index 000000000000..d2870652b0bf
--- /dev/null
+++ b/usr.bin/cxxfilt/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libelf \
+ lib/libelftc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dc/tests/Makefile.depend b/usr.bin/dc/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/dc/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/diff/Makefile b/usr.bin/diff/Makefile
new file mode 100644
index 000000000000..20eaaf8e1dff
--- /dev/null
+++ b/usr.bin/diff/Makefile
@@ -0,0 +1,12 @@
+.include <src.opts.mk>
+
+PROG= diff
+SRCS= diff.c diffdir.c diffreg.c xmalloc.c pr.c diffreg_new.c
+
+LIBADD= m diff
+CFLAGS+= -I${.CURDIR} -I${SRCTOP}/contrib/libdiff/lib -I${SRCTOP}/contrib/libdiff/include
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/diff/TODO b/usr.bin/diff/TODO
new file mode 100644
index 000000000000..c958ee2c2826
--- /dev/null
+++ b/usr.bin/diff/TODO
@@ -0,0 +1,9 @@
+to be implemented:
+--horizon-lines
+--ignore-tab-expansion
+--line-format
+
+Will probably be not implemented:
+--GTYPE-group-format (partially implement - minimal)
+--LTYPE-line-format
+--help (We have a manpage already)
diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1
new file mode 100644
index 000000000000..559434d8e4fb
--- /dev/null
+++ b/usr.bin/diff/diff.1
@@ -0,0 +1,821 @@
+.\" $OpenBSD: diff.1,v 1.47 2015/11/24 19:35:41 jmc Exp $
+.\"
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd July 26, 2024
+.Dt DIFF 1
+.Os
+.Sh NAME
+.Nm diff
+.Nd differential file and directory comparator
+.Sh SYNOPSIS
+.Nm diff
+.Op Fl aBbdipTtw
+.Oo
+.Fl c | e | f |
+.Fl n | q | u | y
+.Oc
+.Op Fl A Ar algo | Fl -algorithm Ar algo
+.Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -changed-group-format Ar GFMT
+.Op Fl -ed
+.Op Fl -expand-tabs
+.Op Fl -forward-ed
+.Op Fl -ignore-all-space
+.Op Fl -ignore-case
+.Op Fl -ignore-space-change
+.Op Fl -initial-tab
+.Op Fl -minimal
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -normal
+.Op Fl -rcs
+.Op Fl -show-c-function
+.Op Fl -starting-file
+.Op Fl -speed-large-files
+.Op Fl -strip-trailing-cr
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Op Fl -unified
+.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
+.Op Fl F Ar pattern | Fl -show-function-line Ar pattern
+.Op Fl L Ar label | Fl -label Ar label
+.Ar file1 file2
+.Nm diff
+.Op Fl aBbdilpTtw
+.Op Fl A Ar algo | Fl -algorithm Ar algo
+.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
+.Op Fl F Ar pattern | Fl -show-function-line Ar pattern
+.Op Fl L Ar label | Fl -label Ar label
+.Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -changed-group-format Ar GFMT
+.Op Fl -ed
+.Op Fl -expand-tabs
+.Op Fl -forward-ed
+.Op Fl -ignore-all-space
+.Op Fl -ignore-case
+.Op Fl -ignore-space-change
+.Op Fl -initial-tab
+.Op Fl -minimal
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -normal
+.Op Fl -paginate
+.Op Fl -rcs
+.Op Fl -show-c-function
+.Op Fl -speed-large-files
+.Op Fl -starting-file
+.Op Fl -strip-trailing-cr
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Fl C Ar number | -context Ar number
+.Ar file1 file2
+.Nm diff
+.Op Fl aBbdiltw
+.Op Fl A Ar algo | Fl -algorithm Ar algo
+.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
+.Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -changed-group-format Ar GFMT
+.Op Fl -ed
+.Op Fl -expand-tabs
+.Op Fl -forward-ed
+.Op Fl -ignore-all-space
+.Op Fl -ignore-case
+.Op Fl -ignore-space-change
+.Op Fl -initial-tab
+.Op Fl -minimal
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -normal
+.Op Fl -paginate
+.Op Fl -rcs
+.Op Fl -show-c-function
+.Op Fl -speed-large-files
+.Op Fl -starting-file
+.Op Fl -strip-trailing-cr
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Fl D Ar string | Fl -ifdef Ar string
+.Ar file1 file2
+.Nm diff
+.Op Fl aBbdilpTtw
+.Op Fl A Ar algo | Fl -algorithm Ar algo
+.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
+.Op Fl F Ar pattern | Fl -show-function-line Ar pattern
+.Op Fl L Ar label | Fl -label Ar label
+.Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -changed-group-format Ar GFMT
+.Op Fl -ed
+.Op Fl -expand-tabs
+.Op Fl -forward-ed
+.Op Fl -ignore-all-space
+.Op Fl -ignore-case
+.Op Fl -ignore-space-change
+.Op Fl -initial-tab
+.Op Fl -minimal
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -normal
+.Op Fl -paginate
+.Op Fl -rcs
+.Op Fl -show-c-function
+.Op Fl -speed-large-files
+.Op Fl -starting-file
+.Op Fl -strip-trailing-cr
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Fl U Ar number | Fl -unified Ar number
+.Ar file1 file2
+.Nm diff
+.Op Fl aBbdilNPprsTtw
+.Oo
+.Fl c | e | f |
+.Fl n | q | u
+.Oc
+.Op Fl A Ar algo | Fl -algorithm Ar algo
+.Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -changed-group-format Ar GFMT
+.Op Fl -context
+.Op Fl -ed
+.Op Fl -expand-tabs
+.Op Fl -forward-ed
+.Op Fl -ignore-all-space
+.Op Fl -ignore-case
+.Op Fl -ignore-space-change
+.Op Fl -initial-tab
+.Op Fl -minimal
+.Op Fl -new-file
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -normal
+.Op Fl -paginate
+.Op Fl -rcs
+.Op Fl -recursive
+.Op Fl -report-identical-files
+.Op Fl -show-c-function
+.Op Fl -speed-large-files
+.Op Fl -strip-trailing-cr
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Op Fl -unidirectional-new-file
+.Op Fl -unified
+.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
+.Op Fl F Ar pattern | Fl -show-function-line Ar pattern
+.Bk -words
+.Op Fl L Ar label | Fl -label Ar label
+.Op Fl S Ar name | Fl -starting-file Ar name
+.Op Fl X Ar file | Fl -exclude-from Ar file
+.Op Fl x Ar pattern | Fl -exclude Ar pattern
+.Ek
+.Ar dir1 dir2
+.Nm diff
+.Op Fl aBbditwW
+.Op Fl -color Ns = Ns Ar when
+.Op Fl -expand-tabs
+.Op Fl -ignore-all-space
+.Op Fl -ignore-blank-lines
+.Op Fl -ignore-case
+.Op Fl -minimal
+.Op Fl -no-dereference
+.Op Fl -no-ignore-file-name-case
+.Op Fl -strip-trailing-cr
+.Op Fl -suppress-common-lines
+.Op Fl -tabsize Ar number
+.Op Fl -text
+.Op Fl -width
+.Fl y | Fl -side-by-side
+.Ar file1 file2
+.Nm diff
+.Op Fl -help
+.Op Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+utility compares the contents of
+.Ar file1
+and
+.Ar file2
+and writes to the standard output the list of changes necessary to
+convert one file into the other.
+No output is produced if the files are identical.
+.Pp
+Output options (mutually exclusive):
+.Bl -tag -width Ds
+.It Fl C Ar number Fl -context Ar number
+Like
+.Fl c
+but produces a diff with
+.Ar number
+lines of context.
+.It Fl c
+Produces a diff with 3 lines of context.
+With
+.Fl c
+the output format is modified slightly:
+the output begins with identification of the files involved and
+their creation dates and then each change is separated
+by a line with fifteen
+.Li * Ns 's .
+The lines removed from
+.Ar file1
+are marked with
+.Sq \&-\ \& ;
+those added to
+.Ar file2
+are marked
+.Sq +\ \& .
+Lines which are changed from one file to the other are marked in
+both files with
+.Sq !\ \& .
+Changes which lie within 3 lines of each other are grouped together on
+output.
+.It Fl D Ar string Fl -ifdef Ar string
+Creates a merged version of
+.Ar file1
+and
+.Ar file2
+on the standard output, with C preprocessor controls included so that
+a compilation of the result without defining
+.Ar string
+is equivalent to compiling
+.Ar file1 ,
+while defining
+.Ar string
+will yield
+.Ar file2 .
+.It Fl e -ed
+Produces output in a form suitable as input for the editor utility,
+.Xr ed 1 ,
+which can then be used to convert file1 into file2.
+.Pp
+Extra commands are added to the output when comparing directories with
+.Fl e ,
+so that the result is a
+.Xr sh 1
+script for converting text files which are common to the two directories
+from their state in
+.Ar dir1
+to their state in
+.Ar dir2 .
+Note that when comparing directories with
+.Fl e ,
+the resulting file may no longer be interpreted as an
+.Xr ed 1
+script.
+Output is added to indicate which file each set of
+.Xr ed 1
+commands applies to.
+These hunks can be manually extracted to produce an
+.Xr ed 1
+script, which can also be applied with
+.Xr patch 1 .
+.It Fl f -forward-ed
+Identical output to that of the
+.Fl e
+flag, but in reverse order.
+It cannot be digested by
+.Xr ed 1 .
+.It Fl -help
+This option prints a summary to stdout and exits with status 0.
+.It Fl n
+Produces a script similar to that of
+.Fl e ,
+but in the opposite order and with a count of changed lines on each
+insert or delete command.
+This is the form used by rcsdiff.
+.It Fl q -brief
+Just print a line when the files differ.
+Does not output a list of changes.
+.It Fl U Ar number Fl -unified Ar number
+Like
+.Fl u
+but produces a diff with
+.Ar number
+lines of context.
+.It Fl u
+Produces a
+.Em unified
+diff with 3 lines of context.
+A unified diff is similar to the context diff produced by the
+.Fl c
+option.
+However, unlike with
+.Fl c ,
+all lines to be changed (added and/or removed) are present in
+a single section.
+.It Fl -version
+This option prints a version string to stdout and exits with status 0.
+.It Fl y Fl -side-by-side
+Output in two columns with a marker between them.
+The marker can be one
+of the following:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It space
+Corresponding lines are identical.
+.It '|'
+Corresponding lines are different.
+.It '<'
+Files differ and only the first file contains the line.
+.It '>'
+Files differ and only the second file contains the line.
+.El
+.El
+.Pp
+Comparison options:
+.Bl -tag -width Ds
+.It Fl A Ar algo, Fl -algorithm Ar algo
+Configure the algorithm used when comparing files.
+.Nm
+supports 3 algorithms:
+.Pp
+.Bl -tag -width Ds -compact
+.It Cm myers
+The Myers diff algorithm finds the shortest edit which transforms one
+input into the other.
+It generally runs in O(N+D\(S2) time, requiring O(N) space, where N is
+the sum of the lengths of the inputs and D is the length of the
+difference between them, with a theoretical O(N\(pcD) worst case.
+If it encounters worst-case input, the implementation used by
+.Nm
+falls back to a less optimal but faster algorithm.
+.It Cm patience
+The Patience variant of the Myers algorithm attempts to create more
+aesthetically pleasing diff output by logically grouping lines.
+.It Cm stone
+The Stone algorithm (commonly known as Hunt-McIlroy or Hunt-Szymanski)
+looks for the longest common subsequence between compared files.
+Stone encounters worst case performance when there are long common
+subsequences.
+In large files this can lead to a significant performance impact.
+The Stone algorithm is maintained for compatibility.
+.El
+.Pp
+The
+.Nm
+utility defaults to the Myers algorithm, but will fall back to the
+Stone algorithm if the input or output options are not supported by
+the Myers implementation.
+.It Fl a -text
+Treat all files as ASCII text.
+Normally
+.Nm
+will simply print
+.Dq Binary files ... differ
+if files contain binary characters.
+Use of this option forces
+.Nm
+to produce a diff.
+.It Fl B Fl -ignore-blank-lines
+Causes chunks that include only blank lines to be ignored.
+.It Fl b -ignore-space-change
+Causes trailing blanks (spaces and tabs) to be ignored, and other
+strings of blanks to compare equal.
+.It Fl -color= Ns Oo Ar when Oc
+Color the additions green, and removals red, or the value in the
+.Ev DIFFCOLORS
+environment variable.
+The possible values of
+.Ar when
+are
+.Dq Cm never ,
+.Dq Cm always
+and
+.Dq Cm auto .
+.Cm auto
+will use color if the output is a tty and the
+.Ev COLORTERM
+environment variable is set to a non-empty string.
+.It Fl d -minimal
+Try very hard to produce a diff as small as possible.
+This may consume a lot of processing power and memory when processing
+large files with many changes.
+.It Fl F Ar pattern, Fl -show-function-line Ar pattern
+Like
+.Fl p,
+but display the last line that matches provided pattern.
+.It Fl I Ar pattern Fl -ignore-matching-lines Ar pattern
+Ignores changes, insertions, and deletions whose lines match the
+extended regular expression
+.Ar pattern .
+Multiple
+.Fl I
+patterns may be specified.
+All lines in the change must match some pattern for the change to be
+ignored.
+See
+.Xr re_format 7
+for more information on regular expression patterns.
+.It Fl i -ignore-case
+Ignores the case of letters.
+E.g.,
+.Dq A
+will compare equal to
+.Dq a .
+.It Fl l -paginate
+Pass the output through
+.Xr pr 1
+to paginate it.
+.It Fl L Ar label Fl -label Ar label
+Print
+.Ar label
+instead of the first (and second, if this option is specified twice)
+file name and time in the context or unified diff header.
+.It Fl p -show-c-function
+With unified and context diffs, show with each change
+the first 40 characters of the last line before the context beginning
+with a letter, an underscore or a dollar sign.
+For C and Objective-C source code following standard layout conventions, this
+will show the prototype of the function the change applies to.
+.It Fl T -initial-tab
+Print a tab rather than a space before the rest of the line for the
+normal, context or unified output formats.
+This makes the alignment of tabs in the line consistent.
+.It Fl t -expand-tabs
+Will expand tabs in output lines.
+Normal or
+.Fl c
+output adds character(s) to the front of each line which may screw up
+the indentation of the original source lines and make the output listing
+difficult to interpret.
+This option will preserve the original source's indentation.
+.It Fl w -ignore-all-space
+Is similar to
+.Fl b -ignore-space-change
+but causes whitespace (blanks and tabs) to be totally ignored.
+E.g.,
+.Dq if (\ \&a == b \&)
+will compare equal to
+.Dq if(a==b) .
+.It Fl W Ar number Fl -width Ar number
+Output at most
+.Ar number
+columns when using side by side format.
+The default value is 130.
+Note that unless
+.It Fl t
+was specified,
+.Nm
+will always align the second column to a tab stop, so values of
+.Fl -width
+smaller than approximately five times the value of
+.Fl -tabsize
+may yield surprising results.
+.It Fl -changed-group-format Ar GFMT
+Format input groups in the provided
+.Pp
+the format is a string with special keywords:
+.Bl -tag -width %<
+.It %<
+lines from FILE1
+.It %<
+lines from FILE2
+.El
+.It Fl -ignore-file-name-case
+ignore case when comparing file names
+.It Fl -no-dereference
+do not follow symbolic links
+.It Fl -no-ignore-file-name-case
+do not ignore case when comparing file names (default)
+.It Fl -normal
+default diff output
+.It Fl -speed-large-files
+stub option for compatibility with GNU diff
+.It Fl -strip-trailing-cr
+strip carriage return on input files
+.It Fl -suppress-common-lines
+Do not output common lines when using the side by side format
+.It Fl -tabsize Ar number
+Number of spaces representing a tab (default 8)
+.El
+.Pp
+Directory comparison options:
+.Bl -tag -width Ds
+.It Fl N -new-file
+If a file is found in only one directory, act as if it was found in the
+other directory too but was of zero size.
+.It Fl P -unidirectional-new-file
+If a file is found only in
+.Ar dir2 ,
+act as if it was found in
+.Ar dir1
+too but was of zero size.
+.It Fl r -recursive
+Causes application of
+.Nm
+recursively to common subdirectories encountered.
+.It Fl S Ar name Fl -starting-file Ar name
+Re-starts a directory
+.Nm
+in the middle, beginning with file
+.Ar name .
+.It Fl s -report-identical-files
+Causes
+.Nm
+to report files which are the same, which are otherwise not mentioned.
+.It Fl X Ar file Fl -exclude-from Ar file
+Exclude files and subdirectories from comparison whose basenames match
+lines in
+.Ar file .
+Multiple
+.Fl X
+options may be specified.
+.It Fl x Ar pattern Fl -exclude Ar pattern
+Exclude files and subdirectories from comparison whose basenames match
+.Ar pattern .
+Patterns are matched using shell-style globbing via
+.Xr fnmatch 3 .
+Multiple
+.Fl x
+options may be specified.
+.El
+.Pp
+If both arguments are directories,
+.Nm
+sorts the contents of the directories by name, and then runs the
+regular file
+.Nm
+algorithm, producing a change list,
+on text files which are different.
+Binary files which differ,
+common subdirectories, and files which appear in only one directory
+are described as such.
+In directory mode only regular files and directories are compared.
+If a non-regular file such as a device special file or FIFO is encountered,
+a diagnostic message is printed.
+.Pp
+If only one of
+.Ar file1
+and
+.Ar file2
+is a directory,
+.Nm
+is applied to the non-directory file and the file contained in
+the directory file with a filename that is the same as the
+last component of the non-directory file.
+.Pp
+If either
+.Ar file1
+or
+.Ar file2
+is
+.Sq - ,
+the standard input is
+used in its place.
+.Ss Output Style
+The default (without
+.Fl e ,
+.Fl c ,
+or
+.Fl n -rcs
+.\" -C
+options)
+output contains lines of these forms, where
+.Va XX , YY , ZZ , QQ
+are line numbers respective of file order.
+.Pp
+.Bl -tag -width "XX,YYcZZ,QQ" -compact
+.It Li XX Ns Ic a Ns Li YY
+At (the end of) line
+.Va XX
+of
+.Ar file1 ,
+append the contents
+of line
+.Va YY
+of
+.Ar file2
+to make them equal.
+.It Li XX Ns Ic a Ns Li YY,ZZ
+Same as above, but append the range of lines,
+.Va YY
+through
+.Va ZZ
+of
+.Ar file2
+to line
+.Va XX
+of file1.
+.It Li XX Ns Ic d Ns Li YY
+At line
+.Va XX
+delete
+the line.
+The value
+.Va YY
+tells to which line the change would bring
+.Ar file1
+in line with
+.Ar file2 .
+.It Li XX,YY Ns Ic d Ns Li ZZ
+Delete the range of lines
+.Va XX
+through
+.Va YY
+in
+.Ar file1 .
+.It Li XX Ns Ic c Ns Li YY
+Change the line
+.Va XX
+in
+.Ar file1
+to the line
+.Va YY
+in
+.Ar file2 .
+.It Li XX,YY Ns Ic c Ns Li ZZ
+Replace the range of specified lines with the line
+.Va ZZ .
+.It Li XX,YY Ns Ic c Ns Li ZZ,QQ
+Replace the range
+.Va XX , Ns Va YY
+from
+.Ar file1
+with the range
+.Va ZZ , Ns Va QQ
+from
+.Ar file2 .
+.El
+.Pp
+These lines resemble
+.Xr ed 1
+subcommands to convert
+.Ar file1
+into
+.Ar file2 .
+The line numbers before the action letters pertain to
+.Ar file1 ;
+those after pertain to
+.Ar file2 .
+Thus, by exchanging
+.Ic a
+for
+.Ic d
+and reading the line in reverse order, one can also
+determine how to convert
+.Ar file2
+into
+.Ar file1 .
+As in
+.Xr ed 1 ,
+identical
+pairs (where num1 = num2) are abbreviated as a single
+number.
+.Sh ENVIRONMENT
+.Bl -tag -width DIFFCOLORS
+.It Ev DIFFCOLORS
+The value of this variable is the form
+.Ar add Ns : Ns Ar rm ,
+where
+.Ar add
+is the ASCII escape sequence for additions and
+.Ar rm
+is the ASCII escape sequence for deletions.
+If this is unset,
+.Nm
+uses green for additions and red for removals.
+.El
+.Sh FILES
+.Bl -tag -width /tmp/diff.XXXXXXXX -compact
+.It Pa /tmp/diff.XXXXXXXX
+Temporary file used when comparing a device or the standard input.
+Note that the temporary file is unlinked as soon as it is created
+so it will not show up in a directory listing.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It 0
+No differences were found.
+.It 1
+Differences were found.
+.It >1
+An error occurred.
+.El
+.Pp
+The
+.Fl -help
+and
+.Fl -version
+options exit with a status of 0.
+.Sh EXAMPLES
+Compare
+.Pa old_dir
+and
+.Pa new_dir
+recursively generating an unified diff and treating files found only in one
+of those directories as new files:
+.Bd -literal -offset indent
+$ diff -ruN /path/to/old_dir /path/to/new_dir
+.Ed
+.Pp
+Same as above but excluding files matching the expressions
+.Dq *.h
+and
+.Dq *.c :
+.Bd -literal -offset indent
+$ diff -ruN -x '*.h' -x '*.c' /path/to/old_dir /path/to/new_dir
+.Ed
+.Pp
+Show a single line indicating if the files differ:
+.Bd -literal -offset indent
+$ diff -q /boot/loader.conf /boot/defaults/loader.conf
+Files /boot/loader.conf and /boot/defaults/loader.conf differ
+.Ed
+.Pp
+Assuming a file named
+.Pa example.txt
+with the following contents:
+.Bd -literal -offset indent
+FreeBSD is an operating system
+Linux is a kernel
+OpenBSD is an operating system
+.Ed
+.Pp
+Compare stdin with
+.Pa example.txt
+excluding from the comparison those lines containing either
+.Qq Linux
+or
+.Qq Open :
+.Bd -literal -offset indent
+$ echo "FreeBSD is an operating system" | diff -q -I 'Linux|Open' example.txt -
+.Ed
+.Sh SEE ALSO
+.Xr cmp 1 ,
+.Xr comm 1 ,
+.Xr diff3 1 ,
+.Xr ed 1 ,
+.Xr patch 1 ,
+.Xr pr 1 ,
+.Xr sdiff 1
+.Rs
+.%A James W. Hunt
+.%A M. Douglas McIlroy
+.%T "An Algorithm for Differential File Comparison"
+.%J Computing Science Technical Report
+.%Q Bell Laboratories 41
+.%D June 1976
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl AaDdIiLlNnPpqSsTtwXxy
+are extensions to that specification.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v6 .
+The
+.Nm
+implementation used in
+.Fx
+was GNU diff until
+.Fx 11.4 .
+This was replaced in
+.Fx 12.0
+by a BSD-licensed implementation written by
+.An Todd Miller .
+Some GNUisms were lost in the process.
+.Pp
+libdiff was imported from the Game of Trees version control system and default
+algorithm was changed to Myers for FreeBSD 15.
diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c
new file mode 100644
index 000000000000..83aa20c52cf3
--- /dev/null
+++ b/usr.bin/diff/diff.c
@@ -0,0 +1,689 @@
+/* $OpenBSD: diff.c,v 1.67 2019/06/28 13:35:00 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "diff.h"
+#include "xmalloc.h"
+
+static const char diff_version[] = "FreeBSD diff 20240307";
+bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
+bool ignore_file_case, suppress_common, color, noderef;
+static bool help = false;
+int diff_format, diff_context, diff_algorithm, status;
+bool diff_algorithm_set;
+int tabsize = 8, width = 130;
+static int colorflag = COLORFLAG_NEVER;
+char *start, *ifdefname, *diffargs, *label[2];
+char *ignore_pats, *most_recent_pat;
+char *group_format = NULL;
+const char *add_code, *del_code;
+struct stat stb1, stb2;
+struct excludes *excludes_list;
+regex_t ignore_re, most_recent_re;
+
+static struct algorithm {
+ const char *name;
+ int id;
+} algorithms[] = {
+ {"stone", D_DIFFSTONE},
+ {"myers", D_DIFFMYERS},
+ {"patience", D_DIFFPATIENCE},
+ {NULL, D_DIFFNONE}
+};
+
+#define OPTIONS "0123456789A:aBbC:cdD:efF:HhI:iL:lnNPpqrS:sTtU:uwW:X:x:y"
+enum {
+ OPT_TSIZE = CHAR_MAX + 1,
+ OPT_STRIPCR,
+ OPT_IGN_FN_CASE,
+ OPT_NO_IGN_FN_CASE,
+ OPT_NORMAL,
+ OPT_HELP,
+ OPT_HORIZON_LINES,
+ OPT_CHANGED_GROUP_FORMAT,
+ OPT_SUPPRESS_COMMON,
+ OPT_COLOR,
+ OPT_NO_DEREFERENCE,
+ OPT_VERSION,
+};
+
+static struct option longopts[] = {
+ { "algorithm", required_argument, 0, 'A' },
+ { "text", no_argument, 0, 'a' },
+ { "ignore-space-change", no_argument, 0, 'b' },
+ { "context", optional_argument, 0, 'C' },
+ { "ifdef", required_argument, 0, 'D' },
+ { "minimal", no_argument, 0, 'd' },
+ { "ed", no_argument, 0, 'e' },
+ { "forward-ed", no_argument, 0, 'f' },
+ { "show-function-line", required_argument, 0, 'F' },
+ { "speed-large-files", no_argument, NULL, 'H' },
+ { "ignore-blank-lines", no_argument, 0, 'B' },
+ { "ignore-matching-lines", required_argument, 0, 'I' },
+ { "ignore-case", no_argument, 0, 'i' },
+ { "paginate", no_argument, NULL, 'l' },
+ { "label", required_argument, 0, 'L' },
+ { "new-file", no_argument, 0, 'N' },
+ { "rcs", no_argument, 0, 'n' },
+ { "unidirectional-new-file", no_argument, 0, 'P' },
+ { "show-c-function", no_argument, 0, 'p' },
+ { "brief", no_argument, 0, 'q' },
+ { "recursive", no_argument, 0, 'r' },
+ { "report-identical-files", no_argument, 0, 's' },
+ { "starting-file", required_argument, 0, 'S' },
+ { "expand-tabs", no_argument, 0, 't' },
+ { "initial-tab", no_argument, 0, 'T' },
+ { "unified", optional_argument, 0, 'U' },
+ { "ignore-all-space", no_argument, 0, 'w' },
+ { "width", required_argument, 0, 'W' },
+ { "exclude", required_argument, 0, 'x' },
+ { "exclude-from", required_argument, 0, 'X' },
+ { "side-by-side", no_argument, NULL, 'y' },
+ { "ignore-file-name-case", no_argument, NULL, OPT_IGN_FN_CASE },
+ { "help", no_argument, NULL, OPT_HELP},
+ { "horizon-lines", required_argument, NULL, OPT_HORIZON_LINES },
+ { "no-dereference", no_argument, NULL, OPT_NO_DEREFERENCE},
+ { "no-ignore-file-name-case", no_argument, NULL, OPT_NO_IGN_FN_CASE },
+ { "normal", no_argument, NULL, OPT_NORMAL },
+ { "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
+ { "tabsize", required_argument, NULL, OPT_TSIZE },
+ { "changed-group-format", required_argument, NULL, OPT_CHANGED_GROUP_FORMAT},
+ { "suppress-common-lines", no_argument, NULL, OPT_SUPPRESS_COMMON },
+ { "color", optional_argument, NULL, OPT_COLOR },
+ { "version", no_argument, NULL, OPT_VERSION},
+ { NULL, 0, 0, '\0'}
+};
+
+static void checked_regcomp(char const *, regex_t *);
+static void usage(void) __dead2;
+static void conflicting_format(void) __dead2;
+static void push_excludes(char *);
+static void push_ignore_pats(char *);
+static void read_excludes_file(char *file);
+static void set_argstr(char **, char **);
+static char *splice(char *, char *);
+static bool do_color(void);
+
+int
+main(int argc, char **argv)
+{
+ const char *errstr = NULL;
+ char *ep, **oargv;
+ long l;
+ int ch, dflags, lastch, gotstdin, prevoptind, newarg;
+
+ oargv = argv;
+ gotstdin = 0;
+ dflags = 0;
+ lastch = '\0';
+ prevoptind = 1;
+ newarg = 1;
+ diff_context = 3;
+ diff_format = D_UNSET;
+ diff_algorithm = D_DIFFMYERS;
+ diff_algorithm_set = false;
+#define FORMAT_MISMATCHED(type) \
+ (diff_format != D_UNSET && diff_format != (type))
+ while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (newarg)
+ usage(); /* disallow -[0-9]+ */
+ else if (lastch == 'c' || lastch == 'u')
+ diff_context = 0;
+ else if (!isdigit(lastch) || diff_context > INT_MAX / 10)
+ usage();
+ diff_context = (diff_context * 10) + (ch - '0');
+ break;
+ case 'A':
+ diff_algorithm = D_DIFFNONE;
+ for (struct algorithm *a = algorithms; a->name;a++) {
+ if(strcasecmp(optarg, a->name) == 0) {
+ diff_algorithm = a->id;
+ diff_algorithm_set = true;
+ break;
+ }
+ }
+
+ if (diff_algorithm == D_DIFFNONE) {
+ printf("unknown algorithm: %s\n", optarg);
+ usage();
+ }
+ break;
+ case 'a':
+ dflags |= D_FORCEASCII;
+ break;
+ case 'b':
+ dflags |= D_FOLDBLANKS;
+ break;
+ case 'C':
+ case 'c':
+ if (FORMAT_MISMATCHED(D_CONTEXT))
+ conflicting_format();
+ cflag = true;
+ diff_format = D_CONTEXT;
+ if (optarg != NULL) {
+ l = strtol(optarg, &ep, 10);
+ if (*ep != '\0' || l < 0 || l >= INT_MAX)
+ usage();
+ diff_context = (int)l;
+ }
+ break;
+ case 'd':
+ dflags |= D_MINIMAL;
+ break;
+ case 'D':
+ if (FORMAT_MISMATCHED(D_IFDEF))
+ conflicting_format();
+ diff_format = D_IFDEF;
+ ifdefname = optarg;
+ break;
+ case 'e':
+ if (FORMAT_MISMATCHED(D_EDIT))
+ conflicting_format();
+ diff_format = D_EDIT;
+ break;
+ case 'f':
+ if (FORMAT_MISMATCHED(D_REVERSE))
+ conflicting_format();
+ diff_format = D_REVERSE;
+ break;
+ case 'H':
+ /* ignore but needed for compatibility with GNU diff */
+ break;
+ case 'h':
+ /* silently ignore for backwards compatibility */
+ break;
+ case 'B':
+ dflags |= D_SKIPBLANKLINES;
+ break;
+ case 'F':
+ if (dflags & D_PROTOTYPE)
+ conflicting_format();
+ dflags |= D_MATCHLAST;
+ most_recent_pat = xstrdup(optarg);
+ break;
+ case 'I':
+ push_ignore_pats(optarg);
+ break;
+ case 'i':
+ dflags |= D_IGNORECASE;
+ break;
+ case 'L':
+ if (label[0] == NULL)
+ label[0] = optarg;
+ else if (label[1] == NULL)
+ label[1] = optarg;
+ else
+ usage();
+ break;
+ case 'l':
+ lflag = true;
+ break;
+ case 'N':
+ Nflag = true;
+ break;
+ case 'n':
+ if (FORMAT_MISMATCHED(D_NREVERSE))
+ conflicting_format();
+ diff_format = D_NREVERSE;
+ break;
+ case 'p':
+ if (dflags & D_MATCHLAST)
+ conflicting_format();
+ dflags |= D_PROTOTYPE;
+ break;
+ case 'P':
+ Pflag = true;
+ break;
+ case 'r':
+ rflag = true;
+ break;
+ case 'q':
+ if (FORMAT_MISMATCHED(D_BRIEF))
+ conflicting_format();
+ diff_format = D_BRIEF;
+ break;
+ case 'S':
+ start = optarg;
+ break;
+ case 's':
+ sflag = true;
+ break;
+ case 'T':
+ Tflag = true;
+ break;
+ case 't':
+ dflags |= D_EXPANDTABS;
+ break;
+ case 'U':
+ case 'u':
+ if (FORMAT_MISMATCHED(D_UNIFIED))
+ conflicting_format();
+ diff_format = D_UNIFIED;
+ if (optarg != NULL) {
+ l = strtol(optarg, &ep, 10);
+ if (*ep != '\0' || l < 0 || l >= INT_MAX)
+ usage();
+ diff_context = (int)l;
+ }
+ break;
+ case 'w':
+ dflags |= D_IGNOREBLANKS;
+ break;
+ case 'W':
+ width = (int) strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr) {
+ warnx("Invalid argument for width");
+ usage();
+ }
+ break;
+ case 'X':
+ read_excludes_file(optarg);
+ break;
+ case 'x':
+ push_excludes(optarg);
+ break;
+ case 'y':
+ if (FORMAT_MISMATCHED(D_SIDEBYSIDE))
+ conflicting_format();
+ diff_format = D_SIDEBYSIDE;
+ break;
+ case OPT_CHANGED_GROUP_FORMAT:
+ if (FORMAT_MISMATCHED(D_GFORMAT))
+ conflicting_format();
+ diff_format = D_GFORMAT;
+ group_format = optarg;
+ break;
+ case OPT_HELP:
+ help = true;
+ usage();
+ break;
+ case OPT_HORIZON_LINES:
+ break; /* XXX TODO for compatibility with GNU diff3 */
+ case OPT_IGN_FN_CASE:
+ ignore_file_case = true;
+ break;
+ case OPT_NO_IGN_FN_CASE:
+ ignore_file_case = false;
+ break;
+ case OPT_NORMAL:
+ if (FORMAT_MISMATCHED(D_NORMAL))
+ conflicting_format();
+ diff_format = D_NORMAL;
+ break;
+ case OPT_TSIZE:
+ tabsize = (int) strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr) {
+ warnx("Invalid argument for tabsize");
+ usage();
+ }
+ break;
+ case OPT_STRIPCR:
+ dflags |= D_STRIPCR;
+ break;
+ case OPT_SUPPRESS_COMMON:
+ suppress_common = 1;
+ break;
+ case OPT_COLOR:
+ if (optarg == NULL || strncmp(optarg, "auto", 4) == 0)
+ colorflag = COLORFLAG_AUTO;
+ else if (strncmp(optarg, "always", 6) == 0)
+ colorflag = COLORFLAG_ALWAYS;
+ else if (strncmp(optarg, "never", 5) == 0)
+ colorflag = COLORFLAG_NEVER;
+ else
+ errx(2, "unsupported --color value '%s' (must be always, auto, or never)",
+ optarg);
+ break;
+ case OPT_NO_DEREFERENCE:
+ noderef = true;
+ break;
+ case OPT_VERSION:
+ printf("%s\n", diff_version);
+ exit(0);
+ default:
+ usage();
+ break;
+ }
+ lastch = ch;
+ newarg = optind != prevoptind;
+ prevoptind = optind;
+ }
+ if (diff_format == D_UNSET && (dflags & D_PROTOTYPE) != 0)
+ diff_format = D_CONTEXT;
+ if (diff_format == D_UNSET)
+ diff_format = D_NORMAL;
+ argc -= optind;
+ argv += optind;
+
+ if (do_color()) {
+ char *p;
+ const char *env;
+
+ color = true;
+ add_code = "32";
+ del_code = "31";
+ env = getenv("DIFFCOLORS");
+ if (env != NULL && *env != '\0' && (p = strdup(env))) {
+ add_code = p;
+ strsep(&p, ":");
+ if (p != NULL)
+ del_code = p;
+ }
+ }
+
+#ifdef __OpenBSD__
+ if (pledge("stdio rpath tmppath", NULL) == -1)
+ err(2, "pledge");
+#endif
+
+ /*
+ * Do sanity checks, fill in stb1 and stb2 and call the appropriate
+ * driver routine. Both drivers use the contents of stb1 and stb2.
+ */
+ if (argc != 2)
+ usage();
+ checked_regcomp(ignore_pats, &ignore_re);
+ checked_regcomp(most_recent_pat, &most_recent_re);
+ if (strcmp(argv[0], "-") == 0) {
+ fstat(STDIN_FILENO, &stb1);
+ gotstdin = 1;
+ } else if (stat(argv[0], &stb1) != 0) {
+ if (!Nflag || errno != ENOENT)
+ err(2, "%s", argv[0]);
+ dflags |= D_EMPTY1;
+ memset(&stb1, 0, sizeof(struct stat));
+ }
+
+ if (strcmp(argv[1], "-") == 0) {
+ fstat(STDIN_FILENO, &stb2);
+ gotstdin = 1;
+ } else if (stat(argv[1], &stb2) != 0) {
+ if (!Nflag || errno != ENOENT)
+ err(2, "%s", argv[1]);
+ dflags |= D_EMPTY2;
+ memset(&stb2, 0, sizeof(stb2));
+ stb2.st_mode = stb1.st_mode;
+ }
+
+ if (dflags & D_EMPTY1 && dflags & D_EMPTY2){
+ warn("%s", argv[0]);
+ warn("%s", argv[1]);
+ exit(2);
+ }
+
+ if (stb1.st_mode == 0)
+ stb1.st_mode = stb2.st_mode;
+
+ if (gotstdin && (S_ISDIR(stb1.st_mode) || S_ISDIR(stb2.st_mode)))
+ errx(2, "can't compare - to a directory");
+ set_argstr(oargv, argv);
+ if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
+ if (diff_format == D_IFDEF)
+ errx(2, "-D option not supported with directories");
+ diffdir(argv[0], argv[1], dflags);
+ } else {
+ if (S_ISDIR(stb1.st_mode)) {
+ argv[0] = splice(argv[0], argv[1]);
+ if (stat(argv[0], &stb1) == -1)
+ err(2, "%s", argv[0]);
+ }
+ if (S_ISDIR(stb2.st_mode)) {
+ argv[1] = splice(argv[1], argv[0]);
+ if (stat(argv[1], &stb2) == -1)
+ err(2, "%s", argv[1]);
+ }
+ print_status(diffreg(argv[0], argv[1], dflags, 1), argv[0],
+ argv[1], "");
+ }
+ if (fflush(stdout) != 0)
+ err(2, "stdout");
+ exit(status);
+}
+
+static void
+checked_regcomp(char const *pattern, regex_t *comp)
+{
+ char buf[BUFSIZ];
+ int error;
+
+ if (pattern == NULL)
+ return;
+
+ error = regcomp(comp, pattern, REG_NEWLINE | REG_EXTENDED);
+ if (error != 0) {
+ regerror(error, comp, buf, sizeof(buf));
+ if (*pattern != '\0')
+ errx(2, "%s: %s", pattern, buf);
+ else
+ errx(2, "%s", buf);
+ }
+}
+
+static void
+set_argstr(char **av, char **ave)
+{
+ size_t argsize;
+ char **ap;
+
+ argsize = 4 + *ave - *av + 1;
+ diffargs = xmalloc(argsize);
+ strlcpy(diffargs, "diff", argsize);
+ for (ap = av + 1; ap < ave; ap++) {
+ if (strcmp(*ap, "--") != 0) {
+ strlcat(diffargs, " ", argsize);
+ strlcat(diffargs, *ap, argsize);
+ }
+ }
+}
+
+/*
+ * Read in an excludes file and push each line.
+ */
+static void
+read_excludes_file(char *file)
+{
+ FILE *fp;
+ char *pattern = NULL;
+ size_t blen = 0;
+ ssize_t len;
+
+ if (strcmp(file, "-") == 0)
+ fp = stdin;
+ else if ((fp = fopen(file, "r")) == NULL)
+ err(2, "%s", file);
+ while ((len = getline(&pattern, &blen, fp)) >= 0) {
+ if ((len > 0) && (pattern[len - 1] == '\n'))
+ pattern[len - 1] = '\0';
+ push_excludes(pattern);
+ /* we allocate a new string per line */
+ pattern = NULL;
+ blen = 0;
+ }
+ free(pattern);
+ if (strcmp(file, "-") != 0)
+ fclose(fp);
+}
+
+/*
+ * Push a pattern onto the excludes list.
+ */
+static void
+push_excludes(char *pattern)
+{
+ struct excludes *entry;
+
+ entry = xmalloc(sizeof(*entry));
+ entry->pattern = pattern;
+ entry->next = excludes_list;
+ excludes_list = entry;
+}
+
+static void
+push_ignore_pats(char *pattern)
+{
+ size_t len;
+
+ if (ignore_pats == NULL)
+ ignore_pats = xstrdup(pattern);
+ else {
+ /* old + "|" + new + NUL */
+ len = strlen(ignore_pats) + strlen(pattern) + 2;
+ ignore_pats = xreallocarray(ignore_pats, 1, len);
+ strlcat(ignore_pats, "|", len);
+ strlcat(ignore_pats, pattern, len);
+ }
+}
+
+void
+print_status(int val, char *path1, char *path2, const char *entry)
+{
+ if (label[0] != NULL)
+ path1 = label[0];
+ if (label[1] != NULL)
+ path2 = label[1];
+
+ switch (val) {
+ case D_BINARY:
+ printf("Binary files %s%s and %s%s differ\n",
+ path1, entry, path2, entry);
+ break;
+ case D_DIFFER:
+ if (diff_format == D_BRIEF)
+ printf("Files %s%s and %s%s differ\n",
+ path1, entry, path2, entry);
+ break;
+ case D_SAME:
+ if (sflag)
+ printf("Files %s%s and %s%s are identical\n",
+ path1, entry, path2, entry);
+ break;
+ case D_MISMATCH1:
+ printf("File %s%s is a directory while file %s%s is a regular file\n",
+ path1, entry, path2, entry);
+ break;
+ case D_MISMATCH2:
+ printf("File %s%s is a regular file while file %s%s is a directory\n",
+ path1, entry, path2, entry);
+ break;
+ case D_SKIPPED1:
+ printf("File %s%s is not a regular file or directory and was skipped\n",
+ path1, entry);
+ break;
+ case D_SKIPPED2:
+ printf("File %s%s is not a regular file or directory and was skipped\n",
+ path2, entry);
+ break;
+ case D_ERROR:
+ break;
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(help ? stdout : stderr,
+ "usage: diff [-aBbdilpTtw] [-c | -e | -f | -n | -q | -u] [--ignore-case]\n"
+ " [--no-ignore-case] [--normal] [--strip-trailing-cr] [--tabsize]\n"
+ " [-I pattern] [-F pattern] [-L label] file1 file2\n"
+ " diff [-aBbdilpTtw] [-I pattern] [-L label] [--ignore-case]\n"
+ " [--no-ignore-case] [--normal] [--strip-trailing-cr] [--tabsize]\n"
+ " [-F pattern] -C number file1 file2\n"
+ " diff [-aBbdiltw] [-I pattern] [--ignore-case] [--no-ignore-case]\n"
+ " [--normal] [--strip-trailing-cr] [--tabsize] -D string file1 file2\n"
+ " diff [-aBbdilpTtw] [-I pattern] [-L label] [--ignore-case]\n"
+ " [--no-ignore-case] [--normal] [--tabsize] [--strip-trailing-cr]\n"
+ " [-F pattern] -U number file1 file2\n"
+ " diff [-aBbdilNPprsTtw] [-c | -e | -f | -n | -q | -u] [--ignore-case]\n"
+ " [--no-ignore-case] [--normal] [--tabsize] [-I pattern] [-L label]\n"
+ " [-F pattern] [-S name] [-X file] [-x pattern] dir1 dir2\n"
+ " diff [-aBbditwW] [--expand-tabs] [--ignore-all-space]\n"
+ " [--ignore-blank-lines] [--ignore-case] [--minimal]\n"
+ " [--no-ignore-file-name-case] [--strip-trailing-cr]\n"
+ " [--suppress-common-lines] [--tabsize] [--text] [--width]\n"
+ " -y | --side-by-side file1 file2\n"
+ " diff [--help] [--version]\n");
+
+ if (help)
+ exit(0);
+ else
+ exit(2);
+}
+
+static void
+conflicting_format(void)
+{
+
+ fprintf(stderr, "error: conflicting output format options.\n");
+ usage();
+}
+
+static bool
+do_color(void)
+{
+ const char *p, *p2;
+
+ switch (colorflag) {
+ case COLORFLAG_AUTO:
+ p = getenv("CLICOLOR");
+ p2 = getenv("COLORTERM");
+ if ((p != NULL && *p != '\0') || (p2 != NULL && *p2 != '\0'))
+ return isatty(STDOUT_FILENO);
+ break;
+ case COLORFLAG_ALWAYS:
+ return (true);
+ case COLORFLAG_NEVER:
+ return (false);
+ }
+
+ return (false);
+}
+
+static char *
+splice(char *dir, char *path)
+{
+ char *tail, *buf;
+ size_t dirlen;
+
+ dirlen = strlen(dir);
+ while (dirlen != 0 && dir[dirlen - 1] == '/')
+ dirlen--;
+ if ((tail = strrchr(path, '/')) == NULL)
+ tail = path;
+ else
+ tail++;
+ xasprintf(&buf, "%.*s/%s", (int)dirlen, dir, tail);
+ return (buf);
+}
diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h
new file mode 100644
index 000000000000..679b95e7ca94
--- /dev/null
+++ b/usr.bin/diff/diff.h
@@ -0,0 +1,128 @@
+/* $OpenBSD: diff.h,v 1.34 2020/11/01 18:16:08 jcs Exp $ */
+
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <regex.h>
+
+/*
+ * Output format options
+ */
+#define D_NORMAL 0 /* Normal output */
+#define D_EDIT -1 /* Editor script out */
+#define D_REVERSE 1 /* Reverse editor script */
+#define D_CONTEXT 2 /* Diff with context */
+#define D_UNIFIED 3 /* Unified context diff */
+#define D_IFDEF 4 /* Diff with merged #ifdef's */
+#define D_NREVERSE 5 /* Reverse ed script with numbered
+ lines and no trailing . */
+#define D_BRIEF 6 /* Say if the files differ */
+#define D_GFORMAT 7 /* Diff with defined changed group format */
+#define D_SIDEBYSIDE 8 /* Side by side */
+
+#define D_UNSET -2
+
+/*
+ * Algorithms
+ */
+
+#define D_DIFFNONE 0
+#define D_DIFFSTONE 1 /* Stone or 'old diff' algorithm */
+#define D_DIFFMYERS 2 /* Myers diff algorithm */
+#define D_DIFFPATIENCE 3 /* Patience diff algorithm */
+
+/*
+ * Output flags
+ */
+#define D_HEADER 0x001 /* Print a header/footer between files */
+#define D_EMPTY1 0x002 /* Treat first file as empty (/dev/null) */
+#define D_EMPTY2 0x004 /* Treat second file as empty (/dev/null) */
+
+/*
+ * Command line flags
+ */
+#define D_FORCEASCII 0x008 /* Treat file as ascii regardless of content */
+#define D_FOLDBLANKS 0x010 /* Treat all white space as equal */
+#define D_MINIMAL 0x020 /* Make diff as small as possible */
+#define D_IGNORECASE 0x040 /* Case-insensitive matching */
+#define D_PROTOTYPE 0x080 /* Display C function prototype */
+#define D_EXPANDTABS 0x100 /* Expand tabs to spaces */
+#define D_IGNOREBLANKS 0x200 /* Ignore white space changes */
+#define D_STRIPCR 0x400 /* Strip trailing cr */
+#define D_SKIPBLANKLINES 0x800 /* Skip blank lines */
+#define D_MATCHLAST 0x1000 /* Display last line matching provided regex */
+
+/* Features supported by new algorithms */
+#define D_NEWALGO_FLAGS (D_FORCEASCII | D_PROTOTYPE | D_IGNOREBLANKS)
+
+/*
+ * Status values for print_status() and diffreg() return values
+ */
+#define D_SAME 0 /* Files are the same */
+#define D_DIFFER 1 /* Files are different */
+#define D_BINARY 2 /* Binary files are different */
+#define D_MISMATCH1 3 /* path1 was a dir, path2 a file */
+#define D_MISMATCH2 4 /* path1 was a file, path2 a dir */
+#define D_SKIPPED1 5 /* path1 was a special file */
+#define D_SKIPPED2 6 /* path2 was a special file */
+#define D_ERROR 7 /* A file access error occurred */
+
+/*
+ * Color options
+ */
+#define COLORFLAG_NEVER 0
+#define COLORFLAG_AUTO 1
+#define COLORFLAG_ALWAYS 2
+
+struct excludes {
+ char *pattern;
+ struct excludes *next;
+};
+
+extern bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
+extern bool ignore_file_case, suppress_common, color, noderef, algorithm_set;
+extern int diff_format, diff_context, diff_algorithm, status;
+extern bool diff_algorithm_set;
+extern int tabsize, width;
+extern char *start, *ifdefname, *diffargs, *label[2];
+extern char *ignore_pats, *most_recent_pat;
+extern char *group_format;
+extern const char *add_code, *del_code;
+extern struct stat stb1, stb2;
+extern struct excludes *excludes_list;
+extern regex_t ignore_re, most_recent_re;
+
+int diffreg(char *, char *, int, int);
+int diffreg_new(char *, char *, int, int);
+bool can_libdiff(int);
+void diffdir(char *, char *, int);
+void print_status(int, char *, char *, const char *);
diff --git a/usr.bin/diff/diffdir.c b/usr.bin/diff/diffdir.c
new file mode 100644
index 000000000000..8d12e868f90e
--- /dev/null
+++ b/usr.bin/diff/diffdir.c
@@ -0,0 +1,314 @@
+/* $OpenBSD: diffdir.c,v 1.45 2015/10/05 20:15:00 millert Exp $ */
+
+/*
+ * Copyright (c) 2003, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "diff.h"
+
+static int selectfile(const struct dirent *);
+static void diffit(struct dirent *, char *, size_t, struct dirent *,
+ char *, size_t, int);
+static void print_only(const char *, size_t, const char *);
+
+#define d_status d_type /* we need to store status for -l */
+
+/*
+ * Diff directory traversal. Will be called recursively if -r was specified.
+ */
+void
+diffdir(char *p1, char *p2, int flags)
+{
+ struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL;
+ struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL;
+ size_t dirlen1, dirlen2;
+ char path1[PATH_MAX], path2[PATH_MAX];
+ int pos;
+
+ edp1 = edp2 = NULL;
+
+ dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1));
+ if (dirlen1 >= sizeof(path1) - 1) {
+ warnc(ENAMETOOLONG, "%s", p1);
+ status |= 2;
+ return;
+ }
+ if (path1[dirlen1 - 1] != '/') {
+ path1[dirlen1++] = '/';
+ path1[dirlen1] = '\0';
+ }
+ dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2));
+ if (dirlen2 >= sizeof(path2) - 1) {
+ warnc(ENAMETOOLONG, "%s", p2);
+ status |= 2;
+ return;
+ }
+ if (path2[dirlen2 - 1] != '/') {
+ path2[dirlen2++] = '/';
+ path2[dirlen2] = '\0';
+ }
+
+ /*
+ * Get a list of entries in each directory, skipping "excluded" files
+ * and sorting alphabetically.
+ */
+ pos = scandir(path1, &dirp1, selectfile, alphasort);
+ if (pos == -1) {
+ if (errno == ENOENT && (Nflag || Pflag)) {
+ pos = 0;
+ } else {
+ warn("%s", path1);
+ goto closem;
+ }
+ }
+ dp1 = dirp1;
+ edp1 = dirp1 + pos;
+
+ pos = scandir(path2, &dirp2, selectfile, alphasort);
+ if (pos == -1) {
+ if (errno == ENOENT && Nflag) {
+ pos = 0;
+ } else {
+ warn("%s", path2);
+ goto closem;
+ }
+ }
+ dp2 = dirp2;
+ edp2 = dirp2 + pos;
+
+ /*
+ * If we were given a starting point, find it.
+ */
+ if (start != NULL) {
+ while (dp1 != edp1 && strcmp((*dp1)->d_name, start) < 0)
+ dp1++;
+ while (dp2 != edp2 && strcmp((*dp2)->d_name, start) < 0)
+ dp2++;
+ }
+
+ /*
+ * Iterate through the two directory lists, diffing as we go.
+ */
+ while (dp1 != edp1 || dp2 != edp2) {
+ dent1 = dp1 != edp1 ? *dp1 : NULL;
+ dent2 = dp2 != edp2 ? *dp2 : NULL;
+
+ pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 :
+ ignore_file_case ? strcasecmp(dent1->d_name, dent2->d_name) :
+ strcmp(dent1->d_name, dent2->d_name) ;
+ if (pos == 0) {
+ /* file exists in both dirs, diff it */
+ diffit(dent1, path1, dirlen1, dent2, path2, dirlen2, flags);
+ dp1++;
+ dp2++;
+ } else if (pos < 0) {
+ /* file only in first dir, only diff if -N */
+ if (Nflag) {
+ diffit(dent1, path1, dirlen1, dent2, path2,
+ dirlen2, flags);
+ } else {
+ print_only(path1, dirlen1, dent1->d_name);
+ status |= 1;
+ }
+ dp1++;
+ } else {
+ /* file only in second dir, only diff if -N or -P */
+ if (Nflag || Pflag)
+ diffit(dent2, path1, dirlen1, dent1, path2,
+ dirlen2, flags);
+ else {
+ print_only(path2, dirlen2, dent2->d_name);
+ status |= 1;
+ }
+ dp2++;
+ }
+ }
+
+closem:
+ if (dirp1 != NULL) {
+ for (dp1 = dirp1; dp1 < edp1; dp1++)
+ free(*dp1);
+ free(dirp1);
+ }
+ if (dirp2 != NULL) {
+ for (dp2 = dirp2; dp2 < edp2; dp2++)
+ free(*dp2);
+ free(dirp2);
+ }
+}
+
+/*
+ * Do the actual diff by calling either diffreg() or diffdir().
+ */
+static void
+diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2,
+ char *path2, size_t plen2, int flags)
+{
+ flags |= D_HEADER;
+ strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1);
+
+ /*
+ * If we are ignoring file case, use dent2s name here if both names are
+ * the same apart from case.
+ */
+ if (ignore_file_case && strcasecmp(dp2->d_name, dp2->d_name) == 0)
+ strlcpy(path2 + plen2, dp2->d_name, PATH_MAX - plen2);
+ else
+ strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2);
+
+ if (noderef) {
+ if (lstat(path1, &stb1) != 0) {
+ if (!(Nflag || Pflag) || errno != ENOENT) {
+ warn("%s", path1);
+ return;
+ }
+ flags |= D_EMPTY1;
+ memset(&stb1, 0, sizeof(stb1));
+ }
+
+ if (lstat(path2, &stb2) != 0) {
+ if (!Nflag || errno != ENOENT) {
+ warn("%s", path2);
+ return;
+ }
+ flags |= D_EMPTY2;
+ memset(&stb2, 0, sizeof(stb2));
+ stb2.st_mode = stb1.st_mode;
+ }
+ if (stb1.st_mode == 0)
+ stb1.st_mode = stb2.st_mode;
+ if (S_ISLNK(stb1.st_mode) || S_ISLNK(stb2.st_mode)) {
+ if (S_ISLNK(stb1.st_mode) && S_ISLNK(stb2.st_mode)) {
+ char buf1[PATH_MAX];
+ char buf2[PATH_MAX];
+ ssize_t len1 = 0;
+ ssize_t len2 = 0;
+
+ len1 = readlink(path1, buf1, sizeof(buf1));
+ len2 = readlink(path2, buf2, sizeof(buf2));
+
+ if (len1 < 0 || len2 < 0) {
+ perror("reading links");
+ return;
+ }
+ buf1[len1] = '\0';
+ buf2[len2] = '\0';
+
+ if (len1 != len2 || strncmp(buf1, buf2, len1) != 0) {
+ printf("Symbolic links %s and %s differ\n",
+ path1, path2);
+ status |= 1;
+ }
+
+ return;
+ }
+
+ printf("File %s is a %s while file %s is a %s\n",
+ path1, S_ISLNK(stb1.st_mode) ? "symbolic link" :
+ (S_ISDIR(stb1.st_mode) ? "directory" :
+ (S_ISREG(stb1.st_mode) ? "file" : "error")),
+ path2, S_ISLNK(stb2.st_mode) ? "symbolic link" :
+ (S_ISDIR(stb2.st_mode) ? "directory" :
+ (S_ISREG(stb2.st_mode) ? "file" : "error")));
+ status |= 1;
+ return;
+ }
+ } else {
+ if (stat(path1, &stb1) != 0) {
+ if (!(Nflag || Pflag) || errno != ENOENT) {
+ warn("%s", path1);
+ return;
+ }
+ flags |= D_EMPTY1;
+ memset(&stb1, 0, sizeof(stb1));
+ }
+
+ if (stat(path2, &stb2) != 0) {
+ if (!Nflag || errno != ENOENT) {
+ warn("%s", path2);
+ return;
+ }
+ flags |= D_EMPTY2;
+ memset(&stb2, 0, sizeof(stb2));
+ stb2.st_mode = stb1.st_mode;
+ }
+ if (stb1.st_mode == 0)
+ stb1.st_mode = stb2.st_mode;
+ }
+ if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) {
+ if (rflag)
+ diffdir(path1, path2, flags);
+ else
+ printf("Common subdirectories: %s and %s\n",
+ path1, path2);
+ return;
+ }
+ if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode))
+ dp->d_status = D_SKIPPED1;
+ else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode))
+ dp->d_status = D_SKIPPED2;
+ else
+ dp->d_status = diffreg(path1, path2, flags, 0);
+ print_status(dp->d_status, path1, path2, "");
+}
+
+/*
+ * Returns 1 if the directory entry should be included in the
+ * diff, else 0. Checks the excludes list.
+ */
+static int
+selectfile(const struct dirent *dp)
+{
+ struct excludes *excl;
+
+ if (dp->d_fileno == 0)
+ return (0);
+
+ /* always skip "." and ".." */
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ return (0);
+
+ /* check excludes list */
+ for (excl = excludes_list; excl != NULL; excl = excl->next)
+ if (fnmatch(excl->pattern, dp->d_name, FNM_PATHNAME) == 0)
+ return (0);
+
+ return (1);
+}
+
+void
+print_only(const char *path, size_t dirlen, const char *entry)
+{
+ if (dirlen > 1)
+ dirlen--;
+ printf("Only in %.*s: %s\n", (int)dirlen, path, entry);
+}
diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c
new file mode 100644
index 000000000000..ffa5568bf442
--- /dev/null
+++ b/usr.bin/diff/diffreg.c
@@ -0,0 +1,1736 @@
+/* $OpenBSD: diffreg.c,v 1.93 2019/06/28 13:35:00 deraadt Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (C) Caldera International Inc. 2001-2002.
+ * 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 and documentation 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * 4. Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, 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 CALDERA INTERNATIONAL, INC. 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.
+ */
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <math.h>
+#include <paths.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pr.h"
+#include "diff.h"
+#include "xmalloc.h"
+
+/*
+ * diff - compare two files.
+ */
+
+/*
+ * Uses an algorithm due to Harold Stone, which finds a pair of longest
+ * identical subsequences in the two files.
+ *
+ * The major goal is to generate the match vector J. J[i] is the index of
+ * the line in file1 corresponding to line i file0. J[i] = 0 if there is no
+ * such line in file1.
+ *
+ * Lines are hashed so as to work in core. All potential matches are
+ * located by sorting the lines of each file on the hash (called
+ * ``value''). In particular, this collects the equivalence classes in
+ * file1 together. Subroutine equiv replaces the value of each line in
+ * file0 by the index of the first element of its matching equivalence in
+ * (the reordered) file1. To save space equiv squeezes file1 into a single
+ * array member in which the equivalence classes are simply concatenated,
+ * except that their first members are flagged by changing sign.
+ *
+ * Next the indices that point into member are unsorted into array class
+ * according to the original order of file0.
+ *
+ * The cleverness lies in routine stone. This marches through the lines of
+ * file0, developing a vector klist of "k-candidates". At step i
+ * a k-candidate is a matched pair of lines x,y (x in file0 y in file1)
+ * such that there is a common subsequence of length k between the first
+ * i lines of file0 and the first y lines of file1, but there is no such
+ * subsequence for any smaller y. x is the earliest possible mate to y that
+ * occurs in such a subsequence.
+ *
+ * Whenever any of the members of the equivalence class of lines in file1
+ * matable to a line in file0 has serial number less than the y of some
+ * k-candidate, that k-candidate with the smallest such y is replaced. The
+ * new k-candidate is chained (via pred) to the current k-1 candidate so
+ * that the actual subsequence can be recovered. When a member has serial
+ * number greater that the y of all k-candidates, the klist is extended. At
+ * the end, the longest subsequence is pulled out and placed in the array J
+ * by unravel.
+ *
+ * With J in hand, the matches there recorded are check'ed against reality
+ * to assure that no spurious matches have crept in due to hashing. If they
+ * have, they are broken, and "jackpot" is recorded -- a harmless matter
+ * except that a true match for a spuriously mated line may now be
+ * unnecessarily reported as a change.
+ *
+ * Much of the complexity of the program comes simply from trying to
+ * minimize core utilization and maximize the range of doable problems by
+ * dynamically allocating what is needed and reusing what is not. The core
+ * requirements for problems larger than somewhat are (in words)
+ * 2*length(file0) + length(file1) + 3*(number of k-candidates installed),
+ * typically about 6n words for files of length n.
+ */
+
+struct cand {
+ int x;
+ int y;
+ int pred;
+};
+
+static struct line {
+ int serial;
+ int value;
+} *file[2];
+
+/*
+ * The following struct is used to record change information when
+ * doing a "context" or "unified" diff. (see routine "change" to
+ * understand the highly mnemonic field names)
+ */
+struct context_vec {
+ int a; /* start line in old file */
+ int b; /* end line in old file */
+ int c; /* start line in new file */
+ int d; /* end line in new file */
+};
+
+enum readhash { RH_BINARY, RH_OK, RH_EOF };
+
+static int diffreg_stone(char *, char *, int, int);
+static FILE *opentemp(const char *);
+static void output(char *, FILE *, char *, FILE *, int);
+static void check(FILE *, FILE *, int);
+static void range(int, int, const char *);
+static void uni_range(int, int);
+static void dump_context_vec(FILE *, FILE *, int);
+static void dump_unified_vec(FILE *, FILE *, int);
+static bool prepare(int, FILE *, size_t, int);
+static void prune(void);
+static void equiv(struct line *, int, struct line *, int, int *);
+static void unravel(int);
+static void unsort(struct line *, int, int *);
+static void change(char *, FILE *, char *, FILE *, int, int, int, int, int *);
+static void sort(struct line *, int);
+static void print_header(const char *, const char *);
+static void print_space(int, int, int);
+static bool ignoreline_pattern(char *);
+static bool ignoreline(char *, bool);
+static int asciifile(FILE *);
+static int fetch(long *, int, int, FILE *, int, int, int);
+static int newcand(int, int, int);
+static int search(int *, int, int);
+static int skipline(FILE *);
+static int stone(int *, int, int *, int *, int);
+static enum readhash readhash(FILE *, int, unsigned *);
+static int files_differ(FILE *, FILE *, int);
+static char *match_function(const long *, int, FILE *);
+static char *preadline(int, size_t, off_t);
+
+static int *J; /* will be overlaid on class */
+static int *class; /* will be overlaid on file[0] */
+static int *klist; /* will be overlaid on file[0] after class */
+static int *member; /* will be overlaid on file[1] */
+static int clen;
+static int inifdef; /* whether or not we are in a #ifdef block */
+static size_t len[2]; /* lengths of files in lines */
+static size_t pref, suff; /* lengths of prefix and suffix */
+static size_t slen[2]; /* lengths of files minus pref / suff */
+static int anychange;
+static int hw, lpad,rpad; /* half width and padding */
+static int edoffset;
+static long *ixnew; /* will be overlaid on file[1] */
+static long *ixold; /* will be overlaid on klist */
+static struct cand *clist; /* merely a free storage pot for candidates */
+static int clistlen; /* the length of clist */
+static struct line *sfile[2]; /* shortened by pruning common prefix/suffix */
+static int (*chrtran)(int); /* translation table for case-folding */
+static struct context_vec *context_vec_start;
+static struct context_vec *context_vec_end;
+static struct context_vec *context_vec_ptr;
+
+#define FUNCTION_CONTEXT_SIZE 55
+static char lastbuf[FUNCTION_CONTEXT_SIZE];
+static int lastline;
+static int lastmatchline;
+
+int
+diffreg(char *file1, char *file2, int flags, int capsicum)
+{
+ /*
+ * If we have set the algorithm with -A or --algorithm use that if we
+ * can and if not print an error.
+ */
+ if (diff_algorithm_set) {
+ if (diff_algorithm == D_DIFFMYERS ||
+ diff_algorithm == D_DIFFPATIENCE) {
+ if (can_libdiff(flags))
+ return diffreg_new(file1, file2, flags, capsicum);
+ else
+ errx(2, "cannot use Myers algorithm with selected options");
+ } else {
+ /* Fallback to using stone. */
+ return diffreg_stone(file1, file2, flags, capsicum);
+ }
+ } else {
+ if (can_libdiff(flags))
+ return diffreg_new(file1, file2, flags, capsicum);
+ else
+ return diffreg_stone(file1, file2, flags, capsicum);
+ }
+}
+
+static int
+clow2low(int c)
+{
+
+ return (c);
+}
+
+static int
+cup2low(int c)
+{
+
+ return (tolower(c));
+}
+
+int
+diffreg_stone(char *file1, char *file2, int flags, int capsicum)
+{
+ FILE *f1, *f2;
+ int i, rval;
+ struct pr *pr = NULL;
+ cap_rights_t rights_ro;
+
+ f1 = f2 = NULL;
+ rval = D_SAME;
+ anychange = 0;
+ lastline = 0;
+ lastmatchline = 0;
+
+ /*
+ * In side-by-side mode, we need to print the left column, a
+ * change marker surrounded by padding, and the right column.
+ *
+ * If expanding tabs, we don't care about alignment, so we simply
+ * subtract 3 from the width and divide by two.
+ *
+ * If not expanding tabs, we need to ensure that the right column
+ * is aligned to a tab stop. We start with the same formula, then
+ * decrement until we reach a size that lets us tab-align the
+ * right column. We then adjust the width down if necessary for
+ * the padding calculation to work.
+ *
+ * Left padding is half the space left over, rounded down; right
+ * padding is whatever is needed to match the width.
+ */
+ if (diff_format == D_SIDEBYSIDE) {
+ if (flags & D_EXPANDTABS) {
+ if (width > 3) {
+ hw = (width - 3) / 2;
+ } else {
+ /* not enough space */
+ hw = 0;
+ }
+ } else if (width <= 3 || width <= tabsize) {
+ /* not enough space */
+ hw = 0;
+ } else {
+ hw = (width - 3) / 2;
+ while (hw > 0 && roundup(hw + 3, tabsize) + hw > width)
+ hw--;
+ if (width - (roundup(hw + 3, tabsize) + hw) < tabsize)
+ width = roundup(hw + 3, tabsize) + hw;
+ }
+ lpad = (width - hw * 2 - 1) / 2;
+ rpad = (width - hw * 2 - 1) - lpad;
+ }
+
+ if (flags & D_IGNORECASE)
+ chrtran = cup2low;
+ else
+ chrtran = clow2low;
+ if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode))
+ return (S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2);
+ if (strcmp(file1, "-") == 0 && strcmp(file2, "-") == 0)
+ goto closem;
+
+ if (flags & D_EMPTY1)
+ f1 = fopen(_PATH_DEVNULL, "r");
+ else {
+ if (!S_ISREG(stb1.st_mode)) {
+ if ((f1 = opentemp(file1)) == NULL ||
+ fstat(fileno(f1), &stb1) == -1) {
+ warn("%s", file1);
+ rval = D_ERROR;
+ status |= 2;
+ goto closem;
+ }
+ } else if (strcmp(file1, "-") == 0)
+ f1 = stdin;
+ else
+ f1 = fopen(file1, "r");
+ }
+ if (f1 == NULL) {
+ warn("%s", file1);
+ rval = D_ERROR;
+ status |= 2;
+ goto closem;
+ }
+
+ if (flags & D_EMPTY2)
+ f2 = fopen(_PATH_DEVNULL, "r");
+ else {
+ if (!S_ISREG(stb2.st_mode)) {
+ if ((f2 = opentemp(file2)) == NULL ||
+ fstat(fileno(f2), &stb2) == -1) {
+ warn("%s", file2);
+ rval = D_ERROR;
+ status |= 2;
+ goto closem;
+ }
+ } else if (strcmp(file2, "-") == 0)
+ f2 = stdin;
+ else
+ f2 = fopen(file2, "r");
+ }
+ if (f2 == NULL) {
+ warn("%s", file2);
+ rval = D_ERROR;
+ status |= 2;
+ goto closem;
+ }
+
+ if (lflag)
+ pr = start_pr(file1, file2);
+
+ if (capsicum) {
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
+ if (caph_rights_limit(fileno(f1), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file1);
+ if (caph_rights_limit(fileno(f2), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file2);
+ if (fileno(f1) == STDIN_FILENO || fileno(f2) == STDIN_FILENO) {
+ /* stdin has already been limited */
+ if (caph_limit_stderr() == -1)
+ err(2, "unable to limit stderr");
+ if (caph_limit_stdout() == -1)
+ err(2, "unable to limit stdout");
+ } else if (caph_limit_stdio() == -1)
+ err(2, "unable to limit stdio");
+
+ caph_cache_catpages();
+ caph_cache_tzdata();
+ if (caph_enter() < 0)
+ err(2, "unable to enter capability mode");
+ }
+
+ switch (files_differ(f1, f2, flags)) {
+ case 0:
+ goto closem;
+ case 1:
+ break;
+ default:
+ /* error */
+ rval = D_ERROR;
+ status |= 2;
+ goto closem;
+ }
+
+ if (diff_format == D_BRIEF && ignore_pats == NULL &&
+ (flags & (D_FOLDBLANKS|D_IGNOREBLANKS|D_IGNORECASE|
+ D_SKIPBLANKLINES|D_STRIPCR)) == 0)
+ {
+ rval = D_DIFFER;
+ status |= 1;
+ goto closem;
+ }
+ if ((flags & D_FORCEASCII) != 0) {
+ (void)prepare(0, f1, stb1.st_size, flags);
+ (void)prepare(1, f2, stb2.st_size, flags);
+ } else if (!asciifile(f1) || !asciifile(f2) ||
+ !prepare(0, f1, stb1.st_size, flags) ||
+ !prepare(1, f2, stb2.st_size, flags)) {
+ rval = D_BINARY;
+ status |= 1;
+ goto closem;
+ }
+ if (len[0] > INT_MAX - 2)
+ errc(1, EFBIG, "%s", file1);
+ if (len[1] > INT_MAX - 2)
+ errc(1, EFBIG, "%s", file2);
+
+ prune();
+ sort(sfile[0], slen[0]);
+ sort(sfile[1], slen[1]);
+
+ member = (int *)file[1];
+ equiv(sfile[0], slen[0], sfile[1], slen[1], member);
+ member = xreallocarray(member, slen[1] + 2, sizeof(*member));
+
+ class = (int *)file[0];
+ unsort(sfile[0], slen[0], class);
+ class = xreallocarray(class, slen[0] + 2, sizeof(*class));
+
+ klist = xcalloc(slen[0] + 2, sizeof(*klist));
+ clen = 0;
+ clistlen = 100;
+ clist = xcalloc(clistlen, sizeof(*clist));
+ i = stone(class, slen[0], member, klist, flags);
+ free(member);
+ free(class);
+
+ J = xreallocarray(J, len[0] + 2, sizeof(*J));
+ unravel(klist[i]);
+ free(clist);
+ free(klist);
+
+ ixold = xreallocarray(ixold, len[0] + 2, sizeof(*ixold));
+ ixnew = xreallocarray(ixnew, len[1] + 2, sizeof(*ixnew));
+ check(f1, f2, flags);
+ output(file1, f1, file2, f2, flags);
+
+closem:
+ if (pr != NULL)
+ stop_pr(pr);
+ if (anychange) {
+ status |= 1;
+ if (rval == D_SAME)
+ rval = D_DIFFER;
+ }
+ if (f1 != NULL)
+ fclose(f1);
+ if (f2 != NULL)
+ fclose(f2);
+
+ return (rval);
+}
+
+/*
+ * Check to see if the given files differ.
+ * Returns 0 if they are the same, 1 if different, and -1 on error.
+ * XXX - could use code from cmp(1) [faster]
+ */
+static int
+files_differ(FILE *f1, FILE *f2, int flags)
+{
+ char buf1[BUFSIZ], buf2[BUFSIZ];
+ size_t i, j;
+
+ if ((flags & (D_EMPTY1|D_EMPTY2)) || stb1.st_size != stb2.st_size ||
+ (stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT))
+ return (1);
+
+ if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino)
+ return (0);
+
+ for (;;) {
+ i = fread(buf1, 1, sizeof(buf1), f1);
+ j = fread(buf2, 1, sizeof(buf2), f2);
+ if ((!i && ferror(f1)) || (!j && ferror(f2)))
+ return (-1);
+ if (i != j)
+ return (1);
+ if (i == 0)
+ return (0);
+ if (memcmp(buf1, buf2, i) != 0)
+ return (1);
+ }
+}
+
+static FILE *
+opentemp(const char *f)
+{
+ char buf[BUFSIZ], tempfile[PATH_MAX];
+ ssize_t nread;
+ int ifd, ofd;
+
+ if (strcmp(f, "-") == 0)
+ ifd = STDIN_FILENO;
+ else if ((ifd = open(f, O_RDONLY, 0644)) == -1)
+ return (NULL);
+
+ (void)strlcpy(tempfile, _PATH_TMP "/diff.XXXXXXXX", sizeof(tempfile));
+
+ if ((ofd = mkstemp(tempfile)) == -1) {
+ close(ifd);
+ return (NULL);
+ }
+ unlink(tempfile);
+ while ((nread = read(ifd, buf, BUFSIZ)) > 0) {
+ if (write(ofd, buf, nread) != nread) {
+ close(ifd);
+ close(ofd);
+ return (NULL);
+ }
+ }
+ close(ifd);
+ lseek(ofd, (off_t)0, SEEK_SET);
+ return (fdopen(ofd, "r"));
+}
+
+static bool
+prepare(int i, FILE *fd, size_t filesize, int flags)
+{
+ struct line *p;
+ unsigned h;
+ size_t sz, j = 0;
+ enum readhash r;
+
+ rewind(fd);
+
+ sz = MIN(filesize, SIZE_MAX) / 25;
+ if (sz < 100)
+ sz = 100;
+
+ p = xcalloc(sz + 3, sizeof(*p));
+ while ((r = readhash(fd, flags, &h)) != RH_EOF) {
+ if (r == RH_BINARY)
+ return (false);
+ if (j == SIZE_MAX)
+ break;
+ if (j == sz) {
+ sz = sz * 3 / 2;
+ p = xreallocarray(p, sz + 3, sizeof(*p));
+ }
+ p[++j].value = h;
+ }
+
+ len[i] = j;
+ file[i] = p;
+
+ return (true);
+}
+
+static void
+prune(void)
+{
+ size_t i, j;
+
+ for (pref = 0; pref < len[0] && pref < len[1] &&
+ file[0][pref + 1].value == file[1][pref + 1].value;
+ pref++)
+ ;
+ for (suff = 0; suff < len[0] - pref && suff < len[1] - pref &&
+ file[0][len[0] - suff].value == file[1][len[1] - suff].value;
+ suff++)
+ ;
+ for (j = 0; j < 2; j++) {
+ sfile[j] = file[j] + pref;
+ slen[j] = len[j] - pref - suff;
+ for (i = 0; i <= slen[j]; i++)
+ sfile[j][i].serial = i;
+ }
+}
+
+static void
+equiv(struct line *a, int n, struct line *b, int m, int *c)
+{
+ int i, j;
+
+ i = j = 1;
+ while (i <= n && j <= m) {
+ if (a[i].value < b[j].value)
+ a[i++].value = 0;
+ else if (a[i].value == b[j].value)
+ a[i++].value = j;
+ else
+ j++;
+ }
+ while (i <= n)
+ a[i++].value = 0;
+ b[m + 1].value = 0;
+ j = 0;
+ while (++j <= m) {
+ c[j] = -b[j].serial;
+ while (b[j + 1].value == b[j].value) {
+ j++;
+ c[j] = b[j].serial;
+ }
+ }
+ c[j] = -1;
+}
+
+static int
+stone(int *a, int n, int *b, int *c, int flags)
+{
+ int i, k, y, j, l;
+ int oldc, tc, oldl, sq;
+ unsigned numtries, bound;
+
+ if (flags & D_MINIMAL)
+ bound = UINT_MAX;
+ else {
+ sq = sqrt(n);
+ bound = MAX(256, sq);
+ }
+
+ k = 0;
+ c[0] = newcand(0, 0, 0);
+ for (i = 1; i <= n; i++) {
+ j = a[i];
+ if (j == 0)
+ continue;
+ y = -b[j];
+ oldl = 0;
+ oldc = c[0];
+ numtries = 0;
+ do {
+ if (y <= clist[oldc].y)
+ continue;
+ l = search(c, k, y);
+ if (l != oldl + 1)
+ oldc = c[l - 1];
+ if (l <= k) {
+ if (clist[c[l]].y <= y)
+ continue;
+ tc = c[l];
+ c[l] = newcand(i, y, oldc);
+ oldc = tc;
+ oldl = l;
+ numtries++;
+ } else {
+ c[l] = newcand(i, y, oldc);
+ k++;
+ break;
+ }
+ } while ((y = b[++j]) > 0 && numtries < bound);
+ }
+ return (k);
+}
+
+static int
+newcand(int x, int y, int pred)
+{
+ struct cand *q;
+
+ if (clen == clistlen) {
+ clistlen = clistlen * 11 / 10;
+ clist = xreallocarray(clist, clistlen, sizeof(*clist));
+ }
+ q = clist + clen;
+ q->x = x;
+ q->y = y;
+ q->pred = pred;
+ return (clen++);
+}
+
+static int
+search(int *c, int k, int y)
+{
+ int i, j, l, t;
+
+ if (clist[c[k]].y < y) /* quick look for typical case */
+ return (k + 1);
+ i = 0;
+ j = k + 1;
+ for (;;) {
+ l = (i + j) / 2;
+ if (l <= i)
+ break;
+ t = clist[c[l]].y;
+ if (t > y)
+ j = l;
+ else if (t < y)
+ i = l;
+ else
+ return (l);
+ }
+ return (l + 1);
+}
+
+static void
+unravel(int p)
+{
+ struct cand *q;
+ size_t i;
+
+ for (i = 0; i <= len[0]; i++)
+ J[i] = i <= pref ? i :
+ i > len[0] - suff ? i + len[1] - len[0] : 0;
+ for (q = clist + p; q->y != 0; q = clist + q->pred)
+ J[q->x + pref] = q->y + pref;
+}
+
+/*
+ * Check does double duty:
+ * 1. ferret out any fortuitous correspondences due to confounding by
+ * hashing (which result in "jackpot")
+ * 2. collect random access indexes to the two files
+ */
+static void
+check(FILE *f1, FILE *f2, int flags)
+{
+ int i, j, /* jackpot, */ c, d;
+ long ctold, ctnew;
+
+ rewind(f1);
+ rewind(f2);
+ j = 1;
+ ixold[0] = ixnew[0] = 0;
+ /* jackpot = 0; */
+ ctold = ctnew = 0;
+ for (i = 1; i <= (int)len[0]; i++) {
+ if (J[i] == 0) {
+ ixold[i] = ctold += skipline(f1);
+ continue;
+ }
+ while (j < J[i]) {
+ ixnew[j] = ctnew += skipline(f2);
+ j++;
+ }
+ if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS | D_IGNORECASE | D_STRIPCR)) {
+ for (;;) {
+ c = getc(f1);
+ d = getc(f2);
+ /*
+ * GNU diff ignores a missing newline
+ * in one file for -b or -w.
+ */
+ if (flags & (D_FOLDBLANKS | D_IGNOREBLANKS)) {
+ if (c == EOF && isspace(d)) {
+ ctnew++;
+ break;
+ } else if (isspace(c) && d == EOF) {
+ ctold++;
+ break;
+ }
+ }
+ ctold++;
+ ctnew++;
+ if (flags & D_STRIPCR && (c == '\r' || d == '\r')) {
+ if (c == '\r') {
+ if ((c = getc(f1)) == '\n') {
+ ctold++;
+ } else {
+ ungetc(c, f1);
+ }
+ }
+ if (d == '\r') {
+ if ((d = getc(f2)) == '\n') {
+ ctnew++;
+ } else {
+ ungetc(d, f2);
+ }
+ }
+ break;
+ }
+ if ((flags & D_FOLDBLANKS) && isspace(c) &&
+ isspace(d)) {
+ do {
+ if (c == '\n')
+ break;
+ ctold++;
+ } while (isspace(c = getc(f1)));
+ do {
+ if (d == '\n')
+ break;
+ ctnew++;
+ } while (isspace(d = getc(f2)));
+ } else if (flags & D_IGNOREBLANKS) {
+ while (isspace(c) && c != '\n') {
+ c = getc(f1);
+ ctold++;
+ }
+ while (isspace(d) && d != '\n') {
+ d = getc(f2);
+ ctnew++;
+ }
+ }
+ if (chrtran(c) != chrtran(d)) {
+ /* jackpot++; */
+ J[i] = 0;
+ if (c != '\n' && c != EOF)
+ ctold += skipline(f1);
+ if (d != '\n' && c != EOF)
+ ctnew += skipline(f2);
+ break;
+ }
+ if (c == '\n' || c == EOF)
+ break;
+ }
+ } else {
+ for (;;) {
+ ctold++;
+ ctnew++;
+ if ((c = getc(f1)) != (d = getc(f2))) {
+ /* jackpot++; */
+ J[i] = 0;
+ if (c != '\n' && c != EOF)
+ ctold += skipline(f1);
+ if (d != '\n' && c != EOF)
+ ctnew += skipline(f2);
+ break;
+ }
+ if (c == '\n' || c == EOF)
+ break;
+ }
+ }
+ ixold[i] = ctold;
+ ixnew[j] = ctnew;
+ j++;
+ }
+ for (; j <= (int)len[1]; j++) {
+ ixnew[j] = ctnew += skipline(f2);
+ }
+ /*
+ * if (jackpot)
+ * fprintf(stderr, "jackpot\n");
+ */
+}
+
+/* shellsort CACM #201 */
+static void
+sort(struct line *a, int n)
+{
+ struct line *ai, *aim, w;
+ int j, m = 0, k;
+
+ if (n == 0)
+ return;
+ for (j = 1; j <= n; j *= 2)
+ m = 2 * j - 1;
+ for (m /= 2; m != 0; m /= 2) {
+ k = n - m;
+ for (j = 1; j <= k; j++) {
+ for (ai = &a[j]; ai > a; ai -= m) {
+ aim = &ai[m];
+ if (aim < ai)
+ break; /* wraparound */
+ if (aim->value > ai[0].value ||
+ (aim->value == ai[0].value &&
+ aim->serial > ai[0].serial))
+ break;
+ w.value = ai[0].value;
+ ai[0].value = aim->value;
+ aim->value = w.value;
+ w.serial = ai[0].serial;
+ ai[0].serial = aim->serial;
+ aim->serial = w.serial;
+ }
+ }
+ }
+}
+
+static void
+unsort(struct line *f, int l, int *b)
+{
+ int *a, i;
+
+ a = xcalloc(l + 1, sizeof(*a));
+ for (i = 1; i <= l; i++)
+ a[f[i].serial] = f[i].value;
+ for (i = 1; i <= l; i++)
+ b[i] = a[i];
+ free(a);
+}
+
+static int
+skipline(FILE *f)
+{
+ int i, c;
+
+ for (i = 1; (c = getc(f)) != '\n' && c != EOF; i++)
+ continue;
+ return (i);
+}
+
+static void
+output(char *file1, FILE *f1, char *file2, FILE *f2, int flags)
+{
+ int i, j, m, i0, i1, j0, j1, nc;
+
+ rewind(f1);
+ rewind(f2);
+ m = len[0];
+ J[0] = 0;
+ J[m + 1] = len[1] + 1;
+ if (diff_format != D_EDIT) {
+ for (i0 = 1; i0 <= m; i0 = i1 + 1) {
+ while (i0 <= m && J[i0] == J[i0 - 1] + 1) {
+ if (diff_format == D_SIDEBYSIDE && suppress_common != 1) {
+ nc = fetch(ixold, i0, i0, f1, '\0', 1, flags);
+ print_space(nc, hw - nc + lpad + 1 + rpad, flags);
+ fetch(ixnew, J[i0], J[i0], f2, '\0', 0, flags);
+ printf("\n");
+ }
+ i0++;
+ }
+ j0 = J[i0 - 1] + 1;
+ i1 = i0 - 1;
+ while (i1 < m && J[i1 + 1] == 0)
+ i1++;
+ j1 = J[i1 + 1] - 1;
+ J[i1] = j1;
+
+ /*
+ * When using side-by-side, lines from both of the files are
+ * printed. The algorithm used by diff(1) identifies the ranges
+ * in which two files differ.
+ * See the change() function below.
+ * The for loop below consumes the shorter range, whereas one of
+ * the while loops deals with the longer one.
+ */
+ if (diff_format == D_SIDEBYSIDE) {
+ for (i = i0, j = j0; i <= i1 && j <= j1; i++, j++)
+ change(file1, f1, file2, f2, i, i, j, j, &flags);
+
+ while (i <= i1) {
+ change(file1, f1, file2, f2, i, i, j + 1, j, &flags);
+ i++;
+ }
+
+ while (j <= j1) {
+ change(file1, f1, file2, f2, i + 1, i, j, j, &flags);
+ j++;
+ }
+ } else
+ change(file1, f1, file2, f2, i0, i1, j0, j1, &flags);
+ }
+ } else {
+ for (i0 = m; i0 >= 1; i0 = i1 - 1) {
+ while (i0 >= 1 && J[i0] == J[i0 + 1] - 1 && J[i0] != 0)
+ i0--;
+ j0 = J[i0 + 1] - 1;
+ i1 = i0 + 1;
+ while (i1 > 1 && J[i1 - 1] == 0)
+ i1--;
+ j1 = J[i1 - 1] + 1;
+ J[i1] = j1;
+ change(file1, f1, file2, f2, i1, i0, j1, j0, &flags);
+ }
+ }
+ if (m == 0)
+ change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags);
+ if (diff_format == D_IFDEF || diff_format == D_GFORMAT) {
+ for (;;) {
+#define c i0
+ if ((c = getc(f1)) == EOF)
+ return;
+ printf("%c", c);
+ }
+#undef c
+ }
+ if (anychange != 0) {
+ if (diff_format == D_CONTEXT)
+ dump_context_vec(f1, f2, flags);
+ else if (diff_format == D_UNIFIED)
+ dump_unified_vec(f1, f2, flags);
+ }
+}
+
+static void
+range(int a, int b, const char *separator)
+{
+ printf("%d", a > b ? b : a);
+ if (a < b)
+ printf("%s%d", separator, b);
+}
+
+static void
+uni_range(int a, int b)
+{
+ if (a < b)
+ printf("%d,%d", a, b - a + 1);
+ else if (a == b)
+ printf("%d", b);
+ else
+ printf("%d,0", b);
+}
+
+static char *
+preadline(int fd, size_t rlen, off_t off)
+{
+ char *line;
+ ssize_t nr;
+
+ line = xmalloc(rlen + 1);
+ if ((nr = pread(fd, line, rlen, off)) == -1)
+ err(2, "preadline");
+ if (nr > 0 && line[nr-1] == '\n')
+ nr--;
+ line[nr] = '\0';
+ return (line);
+}
+
+static bool
+ignoreline_pattern(char *line)
+{
+ int ret;
+
+ ret = regexec(&ignore_re, line, 0, NULL, 0);
+ return (ret == 0); /* if it matched, it should be ignored. */
+}
+
+static bool
+ignoreline(char *line, bool skip_blanks)
+{
+
+ if (skip_blanks && *line == '\0')
+ return (true);
+ if (ignore_pats != NULL && ignoreline_pattern(line))
+ return (true);
+ return (false);
+}
+
+/*
+ * Indicate that there is a difference between lines a and b of the from file
+ * to get to lines c to d of the to file. If a is greater then b then there
+ * are no lines in the from file involved and this means that there were
+ * lines appended (beginning at b). If c is greater than d then there are
+ * lines missing from the to file.
+ */
+static void
+change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d,
+ int *pflags)
+{
+ static size_t max_context = 64;
+ long curpos;
+ int i, nc;
+ const char *walk;
+ bool skip_blanks, ignore;
+
+ skip_blanks = (*pflags & D_SKIPBLANKLINES);
+restart:
+ if ((diff_format != D_IFDEF || diff_format == D_GFORMAT) &&
+ a > b && c > d)
+ return;
+ if (ignore_pats != NULL || skip_blanks) {
+ char *line;
+ /*
+ * All lines in the change, insert, or delete must match an ignore
+ * pattern for the change to be ignored.
+ */
+ if (a <= b) { /* Changes and deletes. */
+ for (i = a; i <= b; i++) {
+ line = preadline(fileno(f1),
+ ixold[i] - ixold[i - 1], ixold[i - 1]);
+ ignore = ignoreline(line, skip_blanks);
+ free(line);
+ if (!ignore)
+ goto proceed;
+ }
+ }
+ if (a > b || c <= d) { /* Changes and inserts. */
+ for (i = c; i <= d; i++) {
+ line = preadline(fileno(f2),
+ ixnew[i] - ixnew[i - 1], ixnew[i - 1]);
+ ignore = ignoreline(line, skip_blanks);
+ free(line);
+ if (!ignore)
+ goto proceed;
+ }
+ }
+ return;
+ }
+proceed:
+ if (*pflags & D_HEADER && diff_format != D_BRIEF) {
+ printf("%s %s %s\n", diffargs, file1, file2);
+ *pflags &= ~D_HEADER;
+ }
+ if (diff_format == D_CONTEXT || diff_format == D_UNIFIED) {
+ /*
+ * Allocate change records as needed.
+ */
+ if (context_vec_start == NULL ||
+ context_vec_ptr == context_vec_end - 1) {
+ ptrdiff_t offset = -1;
+
+ if (context_vec_start != NULL)
+ offset = context_vec_ptr - context_vec_start;
+ max_context <<= 1;
+ context_vec_start = xreallocarray(context_vec_start,
+ max_context, sizeof(*context_vec_start));
+ context_vec_end = context_vec_start + max_context;
+ context_vec_ptr = context_vec_start + offset;
+ }
+ if (anychange == 0) {
+ /*
+ * Print the context/unidiff header first time through.
+ */
+ print_header(file1, file2);
+ anychange = 1;
+ } else if (a > context_vec_ptr->b + (2 * diff_context) + 1 &&
+ c > context_vec_ptr->d + (2 * diff_context) + 1) {
+ /*
+ * If this change is more than 'diff_context' lines from the
+ * previous change, dump the record and reset it.
+ */
+ if (diff_format == D_CONTEXT)
+ dump_context_vec(f1, f2, *pflags);
+ else
+ dump_unified_vec(f1, f2, *pflags);
+ }
+ context_vec_ptr++;
+ context_vec_ptr->a = a;
+ context_vec_ptr->b = b;
+ context_vec_ptr->c = c;
+ context_vec_ptr->d = d;
+ return;
+ }
+ if (anychange == 0)
+ anychange = 1;
+ switch (diff_format) {
+ case D_BRIEF:
+ return;
+ case D_NORMAL:
+ case D_EDIT:
+ range(a, b, ",");
+ printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
+ if (diff_format == D_NORMAL)
+ range(c, d, ",");
+ printf("\n");
+ break;
+ case D_REVERSE:
+ printf("%c", a > b ? 'a' : c > d ? 'd' : 'c');
+ range(a, b, " ");
+ printf("\n");
+ break;
+ case D_NREVERSE:
+ if (a > b)
+ printf("a%d %d\n", b, d - c + 1);
+ else {
+ printf("d%d %d\n", a, b - a + 1);
+ if (!(c > d))
+ /* add changed lines */
+ printf("a%d %d\n", b, d - c + 1);
+ }
+ break;
+ }
+ if (diff_format == D_GFORMAT) {
+ curpos = ftell(f1);
+ /* print through if append (a>b), else to (nb: 0 vs 1 orig) */
+ nc = ixold[a > b ? b : a - 1] - curpos;
+ for (i = 0; i < nc; i++)
+ printf("%c", getc(f1));
+ for (walk = group_format; *walk != '\0'; walk++) {
+ if (*walk == '%') {
+ walk++;
+ switch (*walk) {
+ case '<':
+ fetch(ixold, a, b, f1, '<', 1, *pflags);
+ break;
+ case '>':
+ fetch(ixnew, c, d, f2, '>', 0, *pflags);
+ break;
+ default:
+ printf("%%%c", *walk);
+ break;
+ }
+ continue;
+ }
+ printf("%c", *walk);
+ }
+ }
+ if (diff_format == D_SIDEBYSIDE) {
+ if (color && a > b)
+ printf("\033[%sm", add_code);
+ else if (color && c > d)
+ printf("\033[%sm", del_code);
+ if (a > b) {
+ print_space(0, hw + lpad, *pflags);
+ } else {
+ nc = fetch(ixold, a, b, f1, '\0', 1, *pflags);
+ print_space(nc, hw - nc + lpad, *pflags);
+ }
+ if (color && a > b)
+ printf("\033[%sm", add_code);
+ else if (color && c > d)
+ printf("\033[%sm", del_code);
+ printf("%c", (a > b) ? '>' : ((c > d) ? '<' : '|'));
+ if (color && c > d)
+ printf("\033[m");
+ print_space(hw + lpad + 1, rpad, *pflags);
+ fetch(ixnew, c, d, f2, '\0', 0, *pflags);
+ printf("\n");
+ }
+ if (diff_format == D_NORMAL || diff_format == D_IFDEF) {
+ fetch(ixold, a, b, f1, '<', 1, *pflags);
+ if (a <= b && c <= d && diff_format == D_NORMAL)
+ printf("---\n");
+ }
+ if (diff_format != D_GFORMAT && diff_format != D_SIDEBYSIDE)
+ fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags);
+ if (edoffset != 0 && diff_format == D_EDIT) {
+ /*
+ * A non-zero edoffset value for D_EDIT indicates that the last line
+ * printed was a bare dot (".") that has been escaped as ".." to
+ * prevent ed(1) from misinterpreting it. We have to add a
+ * substitute command to change this back and restart where we left
+ * off.
+ */
+ printf(".\n");
+ printf("%ds/.//\n", a + edoffset - 1);
+ b = a + edoffset - 1;
+ a = b + 1;
+ c += edoffset;
+ goto restart;
+ }
+ if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d)
+ printf(".\n");
+ if (inifdef) {
+ printf("#endif /* %s */\n", ifdefname);
+ inifdef = 0;
+ }
+}
+
+static int
+fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags)
+{
+ int i, j, c, lastc, col, nc, newcol;
+
+ edoffset = 0;
+ nc = 0;
+ col = 0;
+ /*
+ * When doing #ifdef's, copy down to current line
+ * if this is the first file, so that stuff makes it to output.
+ */
+ if ((diff_format == D_IFDEF) && oldfile) {
+ long curpos = ftell(lb);
+ /* print through if append (a>b), else to (nb: 0 vs 1 orig) */
+ nc = f[a > b ? b : a - 1] - curpos;
+ for (i = 0; i < nc; i++)
+ printf("%c", getc(lb));
+ }
+ if (a > b)
+ return (0);
+ if (diff_format == D_IFDEF) {
+ if (inifdef) {
+ printf("#else /* %s%s */\n",
+ oldfile == 1 ? "!" : "", ifdefname);
+ } else {
+ if (oldfile)
+ printf("#ifndef %s\n", ifdefname);
+ else
+ printf("#ifdef %s\n", ifdefname);
+ }
+ inifdef = 1 + oldfile;
+ }
+ for (i = a; i <= b; i++) {
+ fseek(lb, f[i - 1], SEEK_SET);
+ nc = f[i] - f[i - 1];
+ if (diff_format == D_SIDEBYSIDE && hw < nc)
+ nc = hw;
+ if (diff_format != D_IFDEF && diff_format != D_GFORMAT &&
+ ch != '\0') {
+ if (color && (ch == '>' || ch == '+'))
+ printf("\033[%sm", add_code);
+ else if (color && (ch == '<' || ch == '-'))
+ printf("\033[%sm", del_code);
+ printf("%c", ch);
+ if (Tflag && (diff_format == D_NORMAL ||
+ diff_format == D_CONTEXT ||
+ diff_format == D_UNIFIED))
+ printf("\t");
+ else if (diff_format != D_UNIFIED)
+ printf(" ");
+ }
+ col = j = 0;
+ lastc = '\0';
+ while (j < nc && (hw == 0 || col < hw)) {
+ c = getc(lb);
+ if (flags & D_STRIPCR && c == '\r') {
+ if ((c = getc(lb)) == '\n')
+ j++;
+ else {
+ ungetc(c, lb);
+ c = '\r';
+ }
+ }
+ if (c == EOF) {
+ if (diff_format == D_EDIT ||
+ diff_format == D_REVERSE ||
+ diff_format == D_NREVERSE)
+ warnx("No newline at end of file");
+ else
+ printf("\n\\ No newline at end of file\n");
+ return (col);
+ }
+ /*
+ * when using --side-by-side, col needs to be increased
+ * in any case to keep the columns aligned
+ */
+ if (c == '\t') {
+ /*
+ * Calculate where the tab would bring us.
+ * If it would take us to the end of the
+ * column, either clip it (if expanding
+ * tabs) or return right away (if not).
+ */
+ newcol = roundup(col + 1, tabsize);
+ if ((flags & D_EXPANDTABS) == 0) {
+ if (hw > 0 && newcol >= hw)
+ return (col);
+ printf("\t");
+ } else {
+ if (hw > 0 && newcol > hw)
+ newcol = hw;
+ printf("%*s", newcol - col, "");
+ }
+ col = newcol;
+ } else {
+ if (diff_format == D_EDIT && j == 1 && c == '\n' &&
+ lastc == '.') {
+ /*
+ * Don't print a bare "." line since that will confuse
+ * ed(1). Print ".." instead and set the, global variable
+ * edoffset to an offset from which to restart. The
+ * caller must check the value of edoffset
+ */
+ printf(".\n");
+ edoffset = i - a + 1;
+ return (edoffset);
+ }
+ /* when side-by-side, do not print a newline */
+ if (diff_format != D_SIDEBYSIDE || c != '\n') {
+ if (color && c == '\n')
+ printf("\033[m%c", c);
+ else
+ printf("%c", c);
+ col++;
+ }
+ }
+
+ j++;
+ lastc = c;
+ }
+ }
+ if (color && diff_format == D_SIDEBYSIDE)
+ printf("\033[m");
+ return (col);
+}
+
+/*
+ * Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578.
+ */
+static enum readhash
+readhash(FILE *f, int flags, unsigned *hash)
+{
+ int i, t, space;
+ unsigned sum;
+
+ sum = 1;
+ space = 0;
+ for (i = 0;;) {
+ switch (t = getc(f)) {
+ case '\0':
+ if ((flags & D_FORCEASCII) == 0)
+ return (RH_BINARY);
+ goto hashchar;
+ case '\r':
+ if (flags & D_STRIPCR) {
+ t = getc(f);
+ if (t == '\n')
+ break;
+ ungetc(t, f);
+ }
+ /* FALLTHROUGH */
+ case '\t':
+ case '\v':
+ case '\f':
+ case ' ':
+ if ((flags & (D_FOLDBLANKS|D_IGNOREBLANKS)) != 0) {
+ space++;
+ continue;
+ }
+ /* FALLTHROUGH */
+ default:
+ hashchar:
+ if (space && (flags & D_IGNOREBLANKS) == 0) {
+ i++;
+ space = 0;
+ }
+ sum = sum * 127 + chrtran(t);
+ i++;
+ continue;
+ case EOF:
+ if (i == 0)
+ return (RH_EOF);
+ /* FALLTHROUGH */
+ case '\n':
+ break;
+ }
+ break;
+ }
+ *hash = sum;
+ return (RH_OK);
+}
+
+static int
+asciifile(FILE *f)
+{
+ unsigned char buf[BUFSIZ];
+ size_t cnt;
+
+ if (f == NULL)
+ return (1);
+
+ rewind(f);
+ cnt = fread(buf, 1, sizeof(buf), f);
+ return (memchr(buf, '\0', cnt) == NULL);
+}
+
+#define begins_with(s, pre) (strncmp(s, pre, sizeof(pre) - 1) == 0)
+
+static char *
+match_function(const long *f, int pos, FILE *fp)
+{
+ unsigned char buf[FUNCTION_CONTEXT_SIZE];
+ size_t nc;
+ int last = lastline;
+ const char *state = NULL;
+
+ lastline = pos;
+ for (; pos > last; pos--) {
+ fseek(fp, f[pos - 1], SEEK_SET);
+ nc = f[pos] - f[pos - 1];
+ if (nc >= sizeof(buf))
+ nc = sizeof(buf) - 1;
+ nc = fread(buf, 1, nc, fp);
+ if (nc == 0)
+ continue;
+ buf[nc] = '\0';
+ buf[strcspn(buf, "\n")] = '\0';
+ if (most_recent_pat != NULL) {
+ int ret = regexec(&most_recent_re, buf, 0, NULL, 0);
+
+ if (ret != 0)
+ continue;
+ strlcpy(lastbuf, buf, sizeof(lastbuf));
+ lastmatchline = pos;
+ return (lastbuf);
+ } else if (isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$'
+ || buf[0] == '-' || buf[0] == '+') {
+ if (begins_with(buf, "private:")) {
+ if (!state)
+ state = " (private)";
+ } else if (begins_with(buf, "protected:")) {
+ if (!state)
+ state = " (protected)";
+ } else if (begins_with(buf, "public:")) {
+ if (!state)
+ state = " (public)";
+ } else {
+ strlcpy(lastbuf, buf, sizeof(lastbuf));
+ if (state)
+ strlcat(lastbuf, state, sizeof(lastbuf));
+ lastmatchline = pos;
+ return (lastbuf);
+ }
+ }
+ }
+ return (lastmatchline > 0 ? lastbuf : NULL);
+}
+
+/* dump accumulated "context" diff changes */
+static void
+dump_context_vec(FILE *f1, FILE *f2, int flags)
+{
+ struct context_vec *cvp = context_vec_start;
+ int lowa, upb, lowc, upd, do_output;
+ int a, b, c, d;
+ char ch, *f;
+
+ if (context_vec_start > context_vec_ptr)
+ return;
+
+ b = d = 0; /* gcc */
+ lowa = MAX(1, cvp->a - diff_context);
+ upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
+ lowc = MAX(1, cvp->c - diff_context);
+ upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
+
+ printf("***************");
+ if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
+ f = match_function(ixold, cvp->a - 1, f1);
+ if (f != NULL)
+ printf(" %s", f);
+ }
+ printf("\n*** ");
+ range(lowa, upb, ",");
+ printf(" ****\n");
+
+ /*
+ * Output changes to the "old" file. The first loop suppresses
+ * output if there were no changes to the "old" file (we'll see
+ * the "old" lines as context in the "new" list).
+ */
+ do_output = 0;
+ for (; cvp <= context_vec_ptr; cvp++)
+ if (cvp->a <= cvp->b) {
+ cvp = context_vec_start;
+ do_output++;
+ break;
+ }
+ if (do_output) {
+ while (cvp <= context_vec_ptr) {
+ a = cvp->a;
+ b = cvp->b;
+ c = cvp->c;
+ d = cvp->d;
+
+ if (a <= b && c <= d)
+ ch = 'c';
+ else
+ ch = (a <= b) ? 'd' : 'a';
+
+ if (ch == 'a')
+ fetch(ixold, lowa, b, f1, ' ', 0, flags);
+ else {
+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
+ fetch(ixold, a, b, f1,
+ ch == 'c' ? '!' : '-', 0, flags);
+ }
+ lowa = b + 1;
+ cvp++;
+ }
+ fetch(ixold, b + 1, upb, f1, ' ', 0, flags);
+ }
+ /* output changes to the "new" file */
+ printf("--- ");
+ range(lowc, upd, ",");
+ printf(" ----\n");
+
+ do_output = 0;
+ for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++)
+ if (cvp->c <= cvp->d) {
+ cvp = context_vec_start;
+ do_output++;
+ break;
+ }
+ if (do_output) {
+ while (cvp <= context_vec_ptr) {
+ a = cvp->a;
+ b = cvp->b;
+ c = cvp->c;
+ d = cvp->d;
+
+ if (a <= b && c <= d)
+ ch = 'c';
+ else
+ ch = (a <= b) ? 'd' : 'a';
+
+ if (ch == 'd')
+ fetch(ixnew, lowc, d, f2, ' ', 0, flags);
+ else {
+ fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
+ fetch(ixnew, c, d, f2,
+ ch == 'c' ? '!' : '+', 0, flags);
+ }
+ lowc = d + 1;
+ cvp++;
+ }
+ fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
+ }
+ context_vec_ptr = context_vec_start - 1;
+}
+
+/* dump accumulated "unified" diff changes */
+static void
+dump_unified_vec(FILE *f1, FILE *f2, int flags)
+{
+ struct context_vec *cvp = context_vec_start;
+ int lowa, upb, lowc, upd;
+ int a, b, c, d;
+ char ch, *f;
+
+ if (context_vec_start > context_vec_ptr)
+ return;
+
+ b = d = 0; /* gcc */
+ lowa = MAX(1, cvp->a - diff_context);
+ upb = MIN((int)len[0], context_vec_ptr->b + diff_context);
+ lowc = MAX(1, cvp->c - diff_context);
+ upd = MIN((int)len[1], context_vec_ptr->d + diff_context);
+
+ printf("@@ -");
+ uni_range(lowa, upb);
+ printf(" +");
+ uni_range(lowc, upd);
+ printf(" @@");
+ if (flags & (D_PROTOTYPE | D_MATCHLAST)) {
+ f = match_function(ixold, cvp->a - 1, f1);
+ if (f != NULL)
+ printf(" %s", f);
+ }
+ printf("\n");
+
+ /*
+ * Output changes in "unified" diff format--the old and new lines
+ * are printed together.
+ */
+ for (; cvp <= context_vec_ptr; cvp++) {
+ a = cvp->a;
+ b = cvp->b;
+ c = cvp->c;
+ d = cvp->d;
+
+ /*
+ * c: both new and old changes
+ * d: only changes in the old file
+ * a: only changes in the new file
+ */
+ if (a <= b && c <= d)
+ ch = 'c';
+ else
+ ch = (a <= b) ? 'd' : 'a';
+
+ switch (ch) {
+ case 'c':
+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
+ fetch(ixold, a, b, f1, '-', 0, flags);
+ fetch(ixnew, c, d, f2, '+', 0, flags);
+ break;
+ case 'd':
+ fetch(ixold, lowa, a - 1, f1, ' ', 0, flags);
+ fetch(ixold, a, b, f1, '-', 0, flags);
+ break;
+ case 'a':
+ fetch(ixnew, lowc, c - 1, f2, ' ', 0, flags);
+ fetch(ixnew, c, d, f2, '+', 0, flags);
+ break;
+ }
+ lowa = b + 1;
+ lowc = d + 1;
+ }
+ fetch(ixnew, d + 1, upd, f2, ' ', 0, flags);
+
+ context_vec_ptr = context_vec_start - 1;
+}
+
+static void
+print_header(const char *file1, const char *file2)
+{
+ const char *time_format;
+ char buf[256];
+ struct tm tm1, tm2, *tm_ptr1, *tm_ptr2;
+ int nsec1 = stb1.st_mtim.tv_nsec;
+ int nsec2 = stb2.st_mtim.tv_nsec;
+
+ time_format = "%Y-%m-%d %H:%M:%S";
+
+ if (cflag)
+ time_format = "%c";
+ tm_ptr1 = localtime_r(&stb1.st_mtime, &tm1);
+ tm_ptr2 = localtime_r(&stb2.st_mtime, &tm2);
+ if (label[0] != NULL)
+ printf("%s %s\n", diff_format == D_CONTEXT ? "***" : "---",
+ label[0]);
+ else {
+ strftime(buf, sizeof(buf), time_format, tm_ptr1);
+ printf("%s %s\t%s", diff_format == D_CONTEXT ? "***" : "---",
+ file1, buf);
+ if (!cflag) {
+ strftime(buf, sizeof(buf), "%z", tm_ptr1);
+ printf(".%.9d %s", nsec1, buf);
+ }
+ printf("\n");
+ }
+ if (label[1] != NULL)
+ printf("%s %s\n", diff_format == D_CONTEXT ? "---" : "+++",
+ label[1]);
+ else {
+ strftime(buf, sizeof(buf), time_format, tm_ptr2);
+ printf("%s %s\t%s", diff_format == D_CONTEXT ? "---" : "+++",
+ file2, buf);
+ if (!cflag) {
+ strftime(buf, sizeof(buf), "%z", tm_ptr2);
+ printf(".%.9d %s", nsec2, buf);
+ }
+ printf("\n");
+ }
+}
+
+/*
+ * Prints n number of space characters either by using tab
+ * or single space characters.
+ * nc is the preceding number of characters
+ */
+static void
+print_space(int nc, int n, int flags)
+{
+ int col, newcol, tabstop;
+
+ col = nc;
+ newcol = nc + n;
+ /* first, use tabs if allowed */
+ if ((flags & D_EXPANDTABS) == 0) {
+ while ((tabstop = roundup(col + 1, tabsize)) <= newcol) {
+ printf("\t");
+ col = tabstop;
+ }
+ }
+ /* finish with spaces */
+ printf("%*s", newcol - col, "");
+}
diff --git a/usr.bin/diff/diffreg_new.c b/usr.bin/diff/diffreg_new.c
new file mode 100644
index 000000000000..f54cd554ccad
--- /dev/null
+++ b/usr.bin/diff/diffreg_new.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2018 Martin Pieuchot
+ * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/capsicum.h>
+#ifndef DIFF_NO_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "diff.h"
+#include <arraylist.h>
+#include <diff_main.h>
+#include <diff_output.h>
+
+const char *format_label(const char *, struct stat *);
+
+enum diffreg_algo {
+ DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE = 0,
+ DIFFREG_ALGO_MYERS_THEN_PATIENCE = 1,
+ DIFFREG_ALGO_PATIENCE = 2,
+ DIFFREG_ALGO_NONE = 3,
+};
+
+int diffreg_new(char *, char *, int, int);
+FILE * openfile(const char *, char **, struct stat *);
+
+static const struct diff_algo_config myers_then_patience;
+static const struct diff_algo_config myers_then_myers_divide;
+static const struct diff_algo_config patience;
+static const struct diff_algo_config myers_divide;
+
+static const struct diff_algo_config myers_then_patience = (struct diff_algo_config){
+ .impl = diff_algo_myers,
+ .permitted_state_size = 1024 * 1024 * sizeof(int),
+ .fallback_algo = &patience,
+};
+
+static const struct diff_algo_config myers_then_myers_divide =
+ (struct diff_algo_config){
+ .impl = diff_algo_myers,
+ .permitted_state_size = 1024 * 1024 * sizeof(int),
+ .fallback_algo = &myers_divide,
+};
+
+static const struct diff_algo_config patience = (struct diff_algo_config){
+ .impl = diff_algo_patience,
+ /* After subdivision, do Patience again: */
+ .inner_algo = &patience,
+ /* If subdivision failed, do Myers Divide et Impera: */
+ .fallback_algo = &myers_then_myers_divide,
+};
+
+static const struct diff_algo_config myers_divide = (struct diff_algo_config){
+ .impl = diff_algo_myers_divide,
+ /* When division succeeded, start from the top: */
+ .inner_algo = &myers_then_myers_divide,
+ /* (fallback_algo = NULL implies diff_algo_none). */
+};
+
+static const struct diff_algo_config no_algo = (struct diff_algo_config){
+ .impl = diff_algo_none,
+};
+
+/* If the state for a forward-Myers is small enough, use Myers, otherwise first
+ * do a Myers-divide. */
+static const struct diff_config diff_config_myers_then_myers_divide = {
+ .atomize_func = diff_atomize_text_by_line,
+ .algo = &myers_then_myers_divide,
+};
+
+/* If the state for a forward-Myers is small enough, use Myers, otherwise first
+ * do a Patience. */
+static const struct diff_config diff_config_myers_then_patience = {
+ .atomize_func = diff_atomize_text_by_line,
+ .algo = &myers_then_patience,
+};
+
+/* Directly force Patience as a first divider of the source file. */
+static const struct diff_config diff_config_patience = {
+ .atomize_func = diff_atomize_text_by_line,
+ .algo = &patience,
+};
+
+/* Directly force Patience as a first divider of the source file. */
+static const struct diff_config diff_config_no_algo = {
+ .atomize_func = diff_atomize_text_by_line,
+};
+
+const char *
+format_label(const char *oldlabel, struct stat *stb)
+{
+ const char *time_format = "%Y-%m-%d %H:%M:%S";
+ char *newlabel;
+ char buf[256];
+ char end[10];
+ struct tm tm, *tm_ptr;
+ int nsec = stb->st_mtim.tv_nsec;
+ size_t newlabellen, timelen, endlen;
+ tm_ptr = localtime_r(&stb->st_mtime, &tm);
+
+ timelen = strftime(buf, 256, time_format, tm_ptr);
+ endlen = strftime(end, 10, "%z", tm_ptr);
+
+ /*
+ * The new label is the length of the time, old label, timezone,
+ * 9 characters for nanoseconds, and 4 characters for a period
+ * and for formatting.
+ */
+ newlabellen = timelen + strlen(oldlabel) + endlen + 9 + 4;
+ newlabel = calloc(newlabellen, sizeof(char));
+
+ snprintf(newlabel, newlabellen ,"%s\t%s.%.9d %s\n",
+ oldlabel, buf, nsec, end);
+
+ return newlabel;
+}
+
+int
+diffreg_new(char *file1, char *file2, int flags, int capsicum)
+{
+ char *str1, *str2;
+ FILE *f1, *f2;
+ struct stat st1, st2;
+ struct diff_input_info info;
+ struct diff_data left = {}, right = {};
+ struct diff_result *result = NULL;
+ bool force_text, have_binary;
+ int rc, atomizer_flags, rflags, diff_flags = 0;
+ int context_lines = diff_context;
+ const struct diff_config *cfg;
+ enum diffreg_algo algo;
+ cap_rights_t rights_ro;
+
+ algo = DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE;
+
+ switch (algo) {
+ default:
+ case DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE:
+ cfg = &diff_config_myers_then_myers_divide;
+ break;
+ case DIFFREG_ALGO_MYERS_THEN_PATIENCE:
+ cfg = &diff_config_myers_then_patience;
+ break;
+ case DIFFREG_ALGO_PATIENCE:
+ cfg = &diff_config_patience;
+ break;
+ case DIFFREG_ALGO_NONE:
+ cfg = &diff_config_no_algo;
+ break;
+ }
+
+ f1 = openfile(file1, &str1, &st1);
+ f2 = openfile(file2, &str2, &st2);
+
+ if (capsicum) {
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
+ if (caph_rights_limit(fileno(f1), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file1);
+ if (caph_rights_limit(fileno(f2), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file2);
+ if (fileno(f1) == STDIN_FILENO || fileno(f2) == STDIN_FILENO) {
+ /* stdin has already been limited */
+ if (caph_limit_stderr() == -1)
+ err(2, "unable to limit stderr");
+ if (caph_limit_stdout() == -1)
+ err(2, "unable to limit stdout");
+ } else if (caph_limit_stdio() == -1)
+ err(2, "unable to limit stdio");
+ caph_cache_catpages();
+ caph_cache_tzdata();
+ if (caph_enter() < 0)
+ err(2, "unable to enter capability mode");
+ }
+ /*
+ * If we have been given a label use that for the paths, if not format
+ * the path with the files modification time.
+ */
+ info.flags = 0;
+ info.left_path = (label[0] != NULL) ?
+ label[0] : format_label(file1, &stb1);
+ info.right_path = (label[1] != NULL) ?
+ label[1] : format_label(file2, &stb2);
+
+ if (flags & D_FORCEASCII)
+ diff_flags |= DIFF_FLAG_FORCE_TEXT_DATA;
+ if (flags & D_IGNOREBLANKS)
+ diff_flags |= DIFF_FLAG_IGNORE_WHITESPACE;
+ if (flags & D_PROTOTYPE)
+ diff_flags |= DIFF_FLAG_SHOW_PROTOTYPES;
+
+ if (diff_atomize_file(&left, cfg, f1, (uint8_t *)str1, st1.st_size, diff_flags)) {
+ rc = D_ERROR;
+ goto done;
+ }
+ if (left.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED)
+ warnx("%s truncated", file1);
+ if (diff_atomize_file(&right, cfg, f2, (uint8_t *)str2, st2.st_size, diff_flags)) {
+ rc = D_ERROR;
+ goto done;
+ }
+ if (right.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED)
+ warnx("%s truncated", file2);
+
+ result = diff_main(cfg, &left, &right);
+ if (result->rc != DIFF_RC_OK) {
+ rc = D_ERROR;
+ status |= 2;
+ goto done;
+ }
+ /*
+ * If there wasn't an error, but we don't have any printable chunks
+ * then the files must match.
+ */
+ if (!diff_result_contains_printable_chunks(result)) {
+ rc = D_SAME;
+ goto done;
+ }
+
+ atomizer_flags = (result->left->atomizer_flags | result->right->atomizer_flags);
+ rflags = (result->left->root->diff_flags | result->right->root->diff_flags);
+ force_text = (rflags & DIFF_FLAG_FORCE_TEXT_DATA);
+ have_binary = (atomizer_flags & DIFF_ATOMIZER_FOUND_BINARY_DATA);
+
+ if (have_binary && !force_text) {
+ rc = D_BINARY;
+ status |= 1;
+ goto done;
+ }
+
+ if (color)
+ diff_output_set_colors(color, del_code, add_code);
+ if (diff_format == D_NORMAL) {
+ rc = diff_output_plain(NULL, stdout, &info, result, false);
+ } else if (diff_format == D_EDIT) {
+ rc = diff_output_edscript(NULL, stdout, &info, result);
+ } else {
+ rc = diff_output_unidiff(NULL, stdout, &info, result,
+ context_lines);
+ }
+ if (rc != DIFF_RC_OK) {
+ rc = D_ERROR;
+ status |= 2;
+ } else {
+ rc = D_DIFFER;
+ status |= 1;
+ }
+done:
+ diff_result_free(result);
+ diff_data_free(&left);
+ diff_data_free(&right);
+#ifndef DIFF_NO_MMAP
+ if (str1)
+ munmap(str1, st1.st_size);
+ if (str2)
+ munmap(str2, st2.st_size);
+#endif
+ fclose(f1);
+ fclose(f2);
+
+ return rc;
+}
+
+FILE *
+openfile(const char *path, char **p, struct stat *st)
+{
+ FILE *f = NULL;
+
+ if (strcmp(path, "-") == 0)
+ f = stdin;
+ else
+ f = fopen(path, "r");
+
+ if (f == NULL)
+ err(2, "%s", path);
+
+ if (fstat(fileno(f), st) == -1)
+ err(2, "%s", path);
+
+#ifndef DIFF_NO_MMAP
+ *p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
+ if (*p == MAP_FAILED)
+#endif
+ *p = NULL; /* fall back on file I/O */
+
+ return f;
+}
+
+bool
+can_libdiff(int flags)
+{
+ /* libdiff's atomizer can only deal with files */
+ if (!S_ISREG(stb1.st_mode) || !S_ISREG(stb2.st_mode))
+ return false;
+
+ /* Is this one of the supported input/output modes for diffreg_new? */
+ if ((flags == 0 || !(flags & ~D_NEWALGO_FLAGS)) &&
+ ignore_pats == NULL && (
+ diff_format == D_NORMAL ||
+#if 0
+ diff_format == D_EDIT ||
+#endif
+ diff_format == D_UNIFIED) &&
+ (diff_algorithm == D_DIFFMYERS || diff_algorithm == D_DIFFPATIENCE)) {
+ return true;
+ }
+
+ /* Fallback to using stone. */
+ return false;
+}
diff --git a/usr.bin/diff/pr.c b/usr.bin/diff/pr.c
new file mode 100644
index 000000000000..c3ea280073af
--- /dev/null
+++ b/usr.bin/diff/pr.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org>
+ * 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
+ * in this position and unchanged.
+ * 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 AUTHOR(S) ``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(S) 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/procdesc.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pr.h"
+#include "diff.h"
+#include "xmalloc.h"
+
+#define _PATH_PR "/usr/bin/pr"
+
+struct pr *
+start_pr(char *file1, char *file2)
+{
+ int pfd[2];
+ int pr_pd;
+ pid_t pid;
+ char *header;
+ struct pr *pr;
+
+ pr = xcalloc(1, sizeof(*pr));
+
+ xasprintf(&header, "%s %s %s", diffargs, file1, file2);
+ signal(SIGPIPE, SIG_IGN);
+ fflush(stdout);
+ rewind(stdout);
+ if (pipe(pfd) == -1)
+ err(2, "pipe");
+ switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) {
+ case -1:
+ status |= 2;
+ free(header);
+ err(2, "No more processes");
+ case 0:
+ /* child */
+ if (pfd[0] != STDIN_FILENO) {
+ dup2(pfd[0], STDIN_FILENO);
+ close(pfd[0]);
+ }
+ close(pfd[1]);
+ execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0);
+ _exit(127);
+ default:
+
+ /* parent */
+ if (pfd[1] != STDOUT_FILENO) {
+ pr->ostdout = dup(STDOUT_FILENO);
+ dup2(pfd[1], STDOUT_FILENO);
+ close(pfd[1]);
+ }
+ close(pfd[0]);
+ rewind(stdout);
+ free(header);
+ pr->kq = kqueue();
+ if (pr->kq == -1)
+ err(2, "kqueue");
+ pr->e = xmalloc(sizeof(struct kevent));
+ EV_SET(pr->e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0,
+ NULL);
+ if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1)
+ err(2, "kevent");
+ }
+ return (pr);
+}
+
+/* close the pipe to pr and restore stdout */
+void
+stop_pr(struct pr *pr)
+{
+ int wstatus;
+
+ if (pr == NULL)
+ return;
+
+ fflush(stdout);
+ if (pr->ostdout != STDOUT_FILENO) {
+ close(STDOUT_FILENO);
+ dup2(pr->ostdout, STDOUT_FILENO);
+ close(pr->ostdout);
+ }
+ if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1)
+ err(2, "kevent");
+ wstatus = pr->e[0].data;
+ close(pr->kq);
+ free(pr);
+ if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0)
+ errx(2, "pr exited abnormally");
+ else if (WIFSIGNALED(wstatus))
+ errx(2, "pr killed by signal %d",
+ WTERMSIG(wstatus));
+}
diff --git a/usr.bin/diff/pr.h b/usr.bin/diff/pr.h
new file mode 100644
index 000000000000..2ff5949f282f
--- /dev/null
+++ b/usr.bin/diff/pr.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org>
+ * 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
+ * in this position and unchanged.
+ * 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 AUTHOR(S) ``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(S) 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/event.h>
+
+struct pr {
+ int ostdout;
+ int kq;
+ struct kevent *e;
+};
+
+struct pr *start_pr(char *file1, char *file2);
+void stop_pr(struct pr *);
diff --git a/usr.bin/diff/tests/Bflag_C.out b/usr.bin/diff/tests/Bflag_C.out
new file mode 100644
index 000000000000..c7f130aff396
--- /dev/null
+++ b/usr.bin/diff/tests/Bflag_C.out
@@ -0,0 +1,2 @@
+1a2
+>
diff --git a/usr.bin/diff/tests/Bflag_D.out b/usr.bin/diff/tests/Bflag_D.out
new file mode 100644
index 000000000000..4c1170334935
--- /dev/null
+++ b/usr.bin/diff/tests/Bflag_D.out
@@ -0,0 +1,2 @@
+1a2
+> C
diff --git a/usr.bin/diff/tests/Bflag_F.out b/usr.bin/diff/tests/Bflag_F.out
new file mode 100644
index 000000000000..9dc5e5694048
--- /dev/null
+++ b/usr.bin/diff/tests/Bflag_F.out
@@ -0,0 +1,4 @@
+7c8
+< G
+---
+> X
diff --git a/usr.bin/diff/tests/Makefile b/usr.bin/diff/tests/Makefile
new file mode 100644
index 000000000000..242e76260249
--- /dev/null
+++ b/usr.bin/diff/tests/Makefile
@@ -0,0 +1,50 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= diff_test
+
+${PACKAGE}FILES+= \
+ Bflag_C.out \
+ Bflag_D.out \
+ Bflag_F.out \
+ input1.in \
+ input2.in \
+ input_c1.in \
+ input_c2.in \
+ side_by_side_tabbed_a.in \
+ side_by_side_tabbed_b.in \
+ simple.out \
+ simple_e.out \
+ simple_n.out \
+ simple_u.out \
+ simple_i.out \
+ simple_w.out \
+ simple_b.out \
+ simple_p.out \
+ unified_p.out \
+ unified_c9999.out \
+ unified_9999.out \
+ header.out \
+ header_ns.out \
+ ifdef.out \
+ group-format.out \
+ strip_o.out \
+ functionname.in \
+ functionname_c.in \
+ functionname_c.out \
+ functionname_objcclassm.in \
+ functionname_objcclassm.out \
+ functionname_objcm.in \
+ functionname_objcm.out
+
+NETBSD_ATF_TESTS_SH+= netbsd_diff_test
+
+${PACKAGE}FILES+= \
+ d_mallocv1.in \
+ d_mallocv2.in
+
+ATF_TESTS_SH_SED_netbsd_diff_test+= -e 's/t_diff/`basename $$0`/g'
+ATF_TESTS_SH_SRC_netbsd_diff_test= t_diff.sh
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/diff/tests/Makefile.depend b/usr.bin/diff/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/diff/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/diff/tests/diff_test.sh b/usr.bin/diff/tests/diff_test.sh
new file mode 100755
index 000000000000..ab731fa32d26
--- /dev/null
+++ b/usr.bin/diff/tests/diff_test.sh
@@ -0,0 +1,393 @@
+
+atf_test_case simple
+atf_test_case unified
+atf_test_case header
+atf_test_case header_ns
+atf_test_case ifdef
+atf_test_case group_format
+atf_test_case side_by_side
+atf_test_case side_by_side_tabbed
+atf_test_case brief_format
+atf_test_case b230049
+atf_test_case stripcr_o
+atf_test_case b252515
+atf_test_case b278988
+atf_test_case Bflag
+atf_test_case Nflag
+atf_test_case tabsize
+atf_test_case conflicting_format
+atf_test_case label
+atf_test_case report_identical
+atf_test_case non_regular_file
+atf_test_case binary
+atf_test_case functionname
+atf_test_case noderef
+atf_test_case ignorecase
+
+simple_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/simple.out -s eq:1 \
+ diff "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_e.out -s eq:1 \
+ diff -e "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_u.out -s eq:1 \
+ diff -u -L input1 -L input2 "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_n.out -s eq:1 \
+ diff -n "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input2.in"
+
+ atf_check -o inline:"Files $(atf_get_srcdir)/input1.in and $(atf_get_srcdir)/input2.in differ\n" -s eq:1 \
+ diff -q "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input2.in"
+
+ atf_check \
+ diff -q "$(atf_get_srcdir)/input1.in" "$(atf_get_srcdir)/input1.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_i.out -s eq:1 \
+ diff -i "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_w.out -s eq:1 \
+ diff -w "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_b.out -s eq:1 \
+ diff -b "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+
+ atf_check -o file:$(atf_get_srcdir)/simple_p.out -s eq:1 \
+ diff --label input_c1.in --label input_c2.in -p "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+}
+
+unified_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/unified_p.out -s eq:1 \
+ diff -up -L input_c1.in -L input_c2.in "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+ atf_check -o file:$(atf_get_srcdir)/unified_9999.out -s eq:1 \
+ diff -u9999 -L input_c1.in -L input_c2.in "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+}
+
+b230049_body()
+{
+ printf 'a\nb\r\nc\n' > b230049_a.in
+ printf 'a\r\nb\r\nc\r\n' > b230049_b.in
+ atf_check -o empty -s eq:0 \
+ diff -up --strip-trailing-cr -L b230049_a.in -L b230049_b.in \
+ b230049_a.in b230049_b.in
+}
+
+stripcr_o_body()
+{
+ printf 'a\nX\nc\n' > stripcr_o_X.in
+ printf 'a\r\nY\r\nc\r\n' > stripcr_o_Y.in
+ atf_check -o "file:$(atf_get_srcdir)/strip_o.out" -s eq:1 \
+ diff -L1 -L2 -u --strip-trailing-cr stripcr_o_X.in stripcr_o_Y.in
+}
+
+b252515_body()
+{
+ printf 'a b\n' > b252515_a.in
+ printf 'a b\n' > b252515_b.in
+ atf_check -o empty -s eq:0 \
+ diff -qw b252515_a.in b252515_b.in
+}
+
+b278988_body()
+{
+ printf 'a\nb\nn' > b278988.a.in
+ printf 'a\n\nb\nn' > b278988.b.in
+ atf_check -o empty -s eq:0 \
+ diff -Bw b278988.a.in b278988.b.in
+}
+
+header_body()
+{
+ export TZ=UTC
+ : > empty
+ echo hello > hello
+ touch -d 2015-04-03T01:02:03 empty
+ touch -d 2016-12-22T11:22:33 hello
+ atf_check -o "file:$(atf_get_srcdir)/header.out" -s eq:1 \
+ diff -u empty hello
+}
+
+header_ns_body()
+{
+ export TZ=UTC
+ : > empty
+ echo hello > hello
+ touch -d 2015-04-03T01:02:03.123456789 empty
+ touch -d 2016-12-22T11:22:33.987654321 hello
+ atf_check -o "file:$(atf_get_srcdir)/header_ns.out" -s eq:1 \
+ diff -u empty hello
+}
+
+ifdef_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/ifdef.out -s eq:1 \
+ diff -D PLOP "$(atf_get_srcdir)/input_c1.in" \
+ "$(atf_get_srcdir)/input_c2.in"
+}
+
+group_format_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/group-format.out -s eq:1 \
+ diff --changed-group-format='<<<<<<< (local)
+%<=======
+%>>>>>>>> (stock)
+' "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
+}
+
+side_by_side_body()
+{
+ atf_check -o save:A printf "A\nB\nC\n"
+ atf_check -o save:B printf "D\nB\nE\n"
+
+ exp_output=$(printf "A[[:space:]]+|[[:space:]]+D\nB[[:space:]]+B\nC[[:space:]]+|[[:space:]]+E")
+ exp_output_suppressed=$(printf "A[[:space:]]+|[[:space:]]+D\nC[[:space:]]+|[[:space:]]+E")
+
+ atf_check -o match:"$exp_output" -s exit:1 \
+ diff --side-by-side A B
+ atf_check -o match:"$exp_output" -s exit:1 \
+ diff -y A B
+ atf_check -o match:"$exp_output_suppressed" -s exit:1 \
+ diff -y --suppress-common-lines A B
+ atf_check -o match:"$exp_output_suppressed" -s exit:1 \
+ diff -W 65 -y --suppress-common-lines A B
+}
+
+side_by_side_tabbed_body()
+{
+ file_a=$(atf_get_srcdir)/side_by_side_tabbed_a.in
+ file_b=$(atf_get_srcdir)/side_by_side_tabbed_b.in
+
+ atf_check -o save:diffout -s not-exit:0 \
+ diff -y ${file_a} ${file_b}
+ atf_check -o save:diffout_expanded -s not-exit:0 \
+ diff -yt ${file_a} ${file_b}
+
+ atf_check -o not-empty grep -Ee 'file A.+file B' diffout
+ atf_check -o not-empty grep -Ee 'file A.+file B' diffout_expanded
+
+ atf_check -o not-empty grep -Ee 'tabs.+tabs' diffout
+ atf_check -o not-empty grep -Ee 'tabs.+tabs' diffout_expanded
+}
+
+brief_format_body()
+{
+ atf_check mkdir A B
+
+ atf_check -x "echo 1 > A/test-file"
+ atf_check -x "echo 2 > B/test-file"
+
+ atf_check cp -Rf A C
+ atf_check cp -Rf A D
+
+ atf_check -x "echo 3 > D/another-test-file"
+
+ atf_check \
+ -s exit:1 \
+ -o inline:"Files A/test-file and B/test-file differ\n" \
+ diff -rq A B
+
+ atf_check diff -rq A C
+
+ atf_check \
+ -s exit:1 \
+ -o inline:"Only in D: another-test-file\n" \
+ diff -rq A D
+
+ atf_check \
+ -s exit:1 \
+ -o inline:"Files A/another-test-file and D/another-test-file differ\n" \
+ diff -Nrq A D
+}
+
+Bflag_body()
+{
+ atf_check -x 'printf "A\nB\n" > A'
+ atf_check -x 'printf "A\n\nB\n" > B'
+ atf_check -x 'printf "A\n \nB\n" > C'
+ atf_check -x 'printf "A\nC\nB\n" > D'
+ atf_check -x 'printf "A\nB\nC\nD\nE\nF\nG\nH" > E'
+ atf_check -x 'printf "A\n\nB\nC\nD\nE\nF\nX\nH" > F'
+
+ atf_check -s exit:0 -o inline:"" diff -B A B
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)/Bflag_C.out" diff -B A C
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)/Bflag_D.out" diff -B A D
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)/Bflag_F.out" diff -B E F
+}
+
+Nflag_body()
+{
+ atf_check -x 'printf "foo" > A'
+
+ atf_check -s exit:1 -o ignore -e ignore diff -N A NOFILE
+ atf_check -s exit:1 -o ignore -e ignore diff -N NOFILE A
+ atf_check -s exit:2 -o ignore -e ignore diff -N NOFILE1 NOFILE2
+}
+
+tabsize_body()
+{
+ printf "\tA\n" > A
+ printf "\tB\n" > B
+
+ atf_check -s exit:1 \
+ -o inline:"1c1\n< A\n---\n> B\n" \
+ diff -t --tabsize 1 A B
+}
+
+conflicting_format_body()
+{
+ printf "\tA\n" > A
+ printf "\tB\n" > B
+
+ atf_check -s exit:2 -e ignore diff -c -u A B
+ atf_check -s exit:2 -e ignore diff -e -f A B
+ atf_check -s exit:2 -e ignore diff -y -q A B
+ atf_check -s exit:2 -e ignore diff -q -u A B
+ atf_check -s exit:2 -e ignore diff -q -c A B
+ atf_check -s exit:2 -e ignore diff --normal -c A B
+ atf_check -s exit:2 -e ignore diff -c --normal A B
+
+ atf_check -s exit:1 -o ignore -e ignore diff -u -u A B
+ atf_check -s exit:1 -o ignore -e ignore diff -e -e A B
+ atf_check -s exit:1 -o ignore -e ignore diff -y -y A B
+ atf_check -s exit:1 -o ignore -e ignore diff -q -q A B
+ atf_check -s exit:1 -o ignore -e ignore diff -c -c A B
+ atf_check -s exit:1 -o ignore -e ignore diff --normal --normal A B
+}
+
+label_body()
+{
+ printf "\tA\n" > A
+
+ atf_check -o inline:"Files hello and world are identical\n" \
+ -s exit:0 diff --label hello --label world -s A A
+
+ atf_check -o inline:"Binary files hello and world differ\n" \
+ -s exit:1 diff --label hello --label world `which diff` `which ls`
+}
+
+report_identical_head()
+{
+ atf_set "require.user" unprivileged
+}
+report_identical_body()
+{
+ printf "\tA\n" > A
+ printf "\tB\n" > B
+ atf_check -s exit:0 -o match:"are identical" \
+ diff -s A A
+ atf_check -s exit:1 -o not-match:"are identical" \
+ diff -s A B
+ chmod -r B
+ atf_check -s exit:2 -e inline:"diff: B: Permission denied\n" \
+ -o empty diff -s A B
+}
+
+non_regular_file_body()
+{
+ printf "\tA\n" > A
+ mkfifo B
+ printf "\tA\n" > B &
+
+ atf_check diff A B
+ printf "\tB\n" > B &
+ atf_check -s exit:1 \
+ -o inline:"--- A\n+++ B\n@@ -1 +1 @@\n-\tA\n+\tB\n" \
+ diff --label A --label B -u A B
+}
+
+binary_body()
+{
+ # the NUL byte has to be after at least BUFSIZ bytes to trick asciifile()
+ yes 012345678901234567890123456789012345678901234567890 | head -n 174 > A
+ cp A B
+ printf '\n\0\n' >> A
+ printf '\nx\n' >> B
+
+ atf_check -o inline:"Binary files A and B differ\n" -s exit:1 diff A B
+ atf_check -o inline:"176c\nx\n.\n" -s exit:1 diff -ae A B
+}
+
+functionname_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/functionname_c.out -s exit:1 \
+ diff -u -p -L functionname.in -L functionname_c.in \
+ "$(atf_get_srcdir)/functionname.in" "$(atf_get_srcdir)/functionname_c.in"
+
+ atf_check -o file:$(atf_get_srcdir)/functionname_objcm.out -s exit:1 \
+ diff -u -p -L functionname.in -L functionname_objcm.in \
+ "$(atf_get_srcdir)/functionname.in" "$(atf_get_srcdir)/functionname_objcm.in"
+
+ atf_check -o file:$(atf_get_srcdir)/functionname_objcclassm.out -s exit:1 \
+ diff -u -p -L functionname.in -L functionname_objcclassm.in \
+ "$(atf_get_srcdir)/functionname.in" "$(atf_get_srcdir)/functionname_objcclassm.in"
+}
+
+noderef_body()
+{
+ atf_check mkdir A B
+
+ atf_check -x "echo 1 > A/test-file"
+ atf_check -x "echo 1 > test-file"
+ atf_check -x "echo 1 > test-file2"
+
+ atf_check ln -s $(pwd)/test-file B/test-file
+
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o inline:"File A/test-file is a file while file B/test-file is a symbolic link\n" \
+ -s exit:1 diff -r --no-dereference A B
+
+ # both test files are now the same symbolic link
+ atf_check rm A/test-file
+
+ atf_check ln -s $(pwd)/test-file A/test-file
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o empty -s exit:0 diff -r --no-dereference A B
+
+ # make test files different symbolic links, but same contents
+ atf_check unlink A/test-file
+ atf_check ln -s $(pwd)/test-file2 A/test-file
+
+ atf_check -o empty -s exit:0 diff -r A B
+ atf_check -o inline:"Symbolic links A/test-file and B/test-file differ\n" -s exit:1 diff -r --no-dereference A B
+}
+
+ignorecase_body()
+{
+ atf_check mkdir A
+ atf_check mkdir B
+
+ atf_check -x "echo hello > A/foo"
+ atf_check -x "echo hello > B/FOO"
+
+ atf_check -o empty -s exit:0 diff -u -r --ignore-file-name-case A B
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case simple
+ atf_add_test_case unified
+ atf_add_test_case header
+ atf_add_test_case header_ns
+ atf_add_test_case ifdef
+ atf_add_test_case group_format
+ atf_add_test_case side_by_side
+ atf_add_test_case side_by_side_tabbed
+ atf_add_test_case brief_format
+ atf_add_test_case b230049
+ atf_add_test_case stripcr_o
+ atf_add_test_case b252515
+ atf_add_test_case b278988
+ atf_add_test_case Bflag
+ atf_add_test_case Nflag
+ atf_add_test_case tabsize
+ atf_add_test_case conflicting_format
+ atf_add_test_case label
+ atf_add_test_case report_identical
+ atf_add_test_case non_regular_file
+ atf_add_test_case binary
+ atf_add_test_case functionname
+ atf_add_test_case noderef
+ atf_add_test_case ignorecase
+}
diff --git a/usr.bin/diff/tests/functionname.in b/usr.bin/diff/tests/functionname.in
new file mode 100644
index 000000000000..7b4c50c86cd9
--- /dev/null
+++ b/usr.bin/diff/tests/functionname.in
@@ -0,0 +1,29 @@
+static void
+doSomethingThenPrintHello(int test)
+{
+ test = test << 4;
+ if (test % 8 == 6) {
+ return;
+ }
+
+ print("goodbye\n");
+}
+
+
+- (long) readOffset:(FILE*)file
+{
+ if( version >= 11){
+ long offset;
+ fread(&offset, sizeof(long), 1, file);
+ return offset;
+ } else {
+ int offset;
+ fread(&offset, sizeof(int), 1, file);
+ return offset;
+ }
+}
+
++ (BOOL) isEdible:(NSString *)mushroom
+{
+ return TRUE;
+}
diff --git a/usr.bin/diff/tests/functionname_c.in b/usr.bin/diff/tests/functionname_c.in
new file mode 100644
index 000000000000..84f6846783ca
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_c.in
@@ -0,0 +1,29 @@
+static void
+doSomethingThenPrintHello(int test)
+{
+ test = test << 4;
+ if (test % 8 == 6) {
+ return;
+ }
+
+ print("hello\n");
+}
+
+
+- (long) readOffset:(FILE*)file
+{
+ if( version >= 11){
+ long offset;
+ fread(&offset, sizeof(long), 1, file);
+ return offset;
+ } else {
+ int offset;
+ fread(&offset, sizeof(int), 1, file);
+ return offset;
+ }
+}
+
++ (BOOL) isEdible:(NSString *)mushroom
+{
+ return TRUE;
+}
diff --git a/usr.bin/diff/tests/functionname_c.out b/usr.bin/diff/tests/functionname_c.out
new file mode 100644
index 000000000000..b17ce05d04ca
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_c.out
@@ -0,0 +1,11 @@
+--- functionname.in
++++ functionname_c.in
+@@ -6,7 +6,7 @@ doSomethingThenPrintHello(int test)
+ return;
+ }
+
+- print("goodbye\n");
++ print("hello\n");
+ }
+
+
diff --git a/usr.bin/diff/tests/functionname_objcclassm.in b/usr.bin/diff/tests/functionname_objcclassm.in
new file mode 100644
index 000000000000..37a9a76c6e6a
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_objcclassm.in
@@ -0,0 +1,31 @@
+static void
+doSomethingThenPrintHello(int test)
+{
+ test = test << 4;
+ if (test % 8 == 6) {
+ return;
+ }
+
+ print("goodbye\n");
+}
+
+
+- (long) readOffset:(FILE*)file
+{
+ if( version >= 11){
+ long offset;
+ fread(&offset, sizeof(long), 1, file);
+ return offset;
+ } else {
+ int offset;
+ fread(&offset, sizeof(int), 1, file);
+ return offset;
+ }
+}
+
++ (BOOL) isEdible:(NSString *)mushroom
+{
+ /* With a solid guide book (such as Phillips 2006) assume we can't eat
+ * the fungus */
+ return FALSE;
+}
diff --git a/usr.bin/diff/tests/functionname_objcclassm.out b/usr.bin/diff/tests/functionname_objcclassm.out
new file mode 100644
index 000000000000..b68b732fb7c3
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_objcclassm.out
@@ -0,0 +1,11 @@
+--- functionname.in
++++ functionname_objcclassm.in
+@@ -25,5 +25,7 @@ + (BOOL) isEdible:(NSString *)mushroom
+
+ + (BOOL) isEdible:(NSString *)mushroom
+ {
+- return TRUE;
++ /* With a solid guide book (such as Phillips 2006) assume we can't eat
++ * the fungus */
++ return FALSE;
+ }
diff --git a/usr.bin/diff/tests/functionname_objcm.in b/usr.bin/diff/tests/functionname_objcm.in
new file mode 100644
index 000000000000..06c3e9b2722d
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_objcm.in
@@ -0,0 +1,29 @@
+static void
+doSomethingThenPrintHello(int test)
+{
+ test = test << 4;
+ if (test % 8 == 6) {
+ return;
+ }
+
+ print("goodbye\n");
+}
+
+
+- (long) readOffset:(FILE*)file
+{
+ if( version >= 11){
+ long offset;
+ fread(&offset, sizeof(long), 1, file);
+ return offset;
+ } else {
+ int offset;
+ fread(&offset-1, sizeof(int), 1, file);
+ return offset;
+ }
+}
+
++ (BOOL) isEdible:(NSString *)mushroom
+{
+ return TRUE;
+}
diff --git a/usr.bin/diff/tests/functionname_objcm.out b/usr.bin/diff/tests/functionname_objcm.out
new file mode 100644
index 000000000000..cb29b0892115
--- /dev/null
+++ b/usr.bin/diff/tests/functionname_objcm.out
@@ -0,0 +1,11 @@
+--- functionname.in
++++ functionname_objcm.in
+@@ -18,7 +18,7 @@ - (long) readOffset:(FILE*)file
+ return offset;
+ } else {
+ int offset;
+- fread(&offset, sizeof(int), 1, file);
++ fread(&offset-1, sizeof(int), 1, file);
+ return offset;
+ }
+ }
diff --git a/usr.bin/diff/tests/group-format.out b/usr.bin/diff/tests/group-format.out
new file mode 100644
index 000000000000..4e1bf85fbba7
--- /dev/null
+++ b/usr.bin/diff/tests/group-format.out
@@ -0,0 +1,27 @@
+/*
+ * A comment
+ *
+<<<<<<< (local)
+ * And another bla
+=======
+ * And another bla
+>>>>>>> (stock)
+ *
+<<<<<<< (local)
+ * And yet another
+=======
+ * and yet another
+>>>>>>> (stock)
+ */
+
+int
+main(void)
+{
+<<<<<<< (local)
+=======
+
+>>>>>>> (stock)
+ printf("something");
+
+ return (0);
+}
diff --git a/usr.bin/diff/tests/header.out b/usr.bin/diff/tests/header.out
new file mode 100644
index 000000000000..2e1665a30e6d
--- /dev/null
+++ b/usr.bin/diff/tests/header.out
@@ -0,0 +1,4 @@
+--- empty 2015-04-03 01:02:03.000000000 +0000
++++ hello 2016-12-22 11:22:33.000000000 +0000
+@@ -0,0 +1 @@
++hello
diff --git a/usr.bin/diff/tests/header_ns.out b/usr.bin/diff/tests/header_ns.out
new file mode 100644
index 000000000000..b1316dfc12b9
--- /dev/null
+++ b/usr.bin/diff/tests/header_ns.out
@@ -0,0 +1,4 @@
+--- empty 2015-04-03 01:02:03.123456789 +0000
++++ hello 2016-12-22 11:22:33.987654321 +0000
+@@ -0,0 +1 @@
++hello
diff --git a/usr.bin/diff/tests/ifdef.out b/usr.bin/diff/tests/ifdef.out
new file mode 100644
index 000000000000..cc72cac08635
--- /dev/null
+++ b/usr.bin/diff/tests/ifdef.out
@@ -0,0 +1,26 @@
+/*
+ * A comment
+ *
+#ifndef PLOP
+ * And another bla
+#else /* PLOP */
+ * And another bla
+#endif /* PLOP */
+ *
+#ifndef PLOP
+ * And yet another
+#else /* PLOP */
+ * and yet another
+#endif /* PLOP */
+ */
+
+int
+main(void)
+{
+#ifdef PLOP
+
+#endif /* PLOP */
+ printf("something");
+
+ return (0);
+}
diff --git a/usr.bin/diff/tests/input1.in b/usr.bin/diff/tests/input1.in
new file mode 100644
index 000000000000..3892e8400f86
--- /dev/null
+++ b/usr.bin/diff/tests/input1.in
@@ -0,0 +1,2 @@
+Simple input file designed
+to be able to test diff
diff --git a/usr.bin/diff/tests/input2.in b/usr.bin/diff/tests/input2.in
new file mode 100644
index 000000000000..c38b487353a7
--- /dev/null
+++ b/usr.bin/diff/tests/input2.in
@@ -0,0 +1,3 @@
+Simple input file designed
+and written
+to be able to test diff utility
diff --git a/usr.bin/diff/tests/input_c1.in b/usr.bin/diff/tests/input_c1.in
new file mode 100644
index 000000000000..d39dfbdc511b
--- /dev/null
+++ b/usr.bin/diff/tests/input_c1.in
@@ -0,0 +1,15 @@
+/*
+ * A comment
+ *
+ * And another bla
+ *
+ * And yet another
+ */
+
+int
+main(void)
+{
+ printf("something");
+
+ return (0);
+}
diff --git a/usr.bin/diff/tests/input_c2.in b/usr.bin/diff/tests/input_c2.in
new file mode 100644
index 000000000000..933ec67dc175
--- /dev/null
+++ b/usr.bin/diff/tests/input_c2.in
@@ -0,0 +1,16 @@
+/*
+ * A comment
+ *
+ * And another bla
+ *
+ * and yet another
+ */
+
+int
+main(void)
+{
+
+ printf("something");
+
+ return (0);
+}
diff --git a/usr.bin/diff/tests/side_by_side_tabbed_a.in b/usr.bin/diff/tests/side_by_side_tabbed_a.in
new file mode 100644
index 000000000000..3198d29f9203
--- /dev/null
+++ b/usr.bin/diff/tests/side_by_side_tabbed_a.in
@@ -0,0 +1,4 @@
+This
+ is my test file A
+ it has tabs
+Thanks
diff --git a/usr.bin/diff/tests/side_by_side_tabbed_b.in b/usr.bin/diff/tests/side_by_side_tabbed_b.in
new file mode 100644
index 000000000000..6698182a8c5d
--- /dev/null
+++ b/usr.bin/diff/tests/side_by_side_tabbed_b.in
@@ -0,0 +1,4 @@
+This
+ is my test file B
+ it has tabs
+Thanks
diff --git a/usr.bin/diff/tests/simple.out b/usr.bin/diff/tests/simple.out
new file mode 100644
index 000000000000..fcbcaa041e8c
--- /dev/null
+++ b/usr.bin/diff/tests/simple.out
@@ -0,0 +1,5 @@
+2c2,3
+< to be able to test diff
+---
+> and written
+> to be able to test diff utility
diff --git a/usr.bin/diff/tests/simple_b.out b/usr.bin/diff/tests/simple_b.out
new file mode 100644
index 000000000000..704be9d621a8
--- /dev/null
+++ b/usr.bin/diff/tests/simple_b.out
@@ -0,0 +1,6 @@
+6c6
+< * And yet another
+---
+> * and yet another
+11a12
+>
diff --git a/usr.bin/diff/tests/simple_e.out b/usr.bin/diff/tests/simple_e.out
new file mode 100644
index 000000000000..0c7e2b5c752b
--- /dev/null
+++ b/usr.bin/diff/tests/simple_e.out
@@ -0,0 +1,4 @@
+2c
+and written
+to be able to test diff utility
+.
diff --git a/usr.bin/diff/tests/simple_i.out b/usr.bin/diff/tests/simple_i.out
new file mode 100644
index 000000000000..9edc1f98d72d
--- /dev/null
+++ b/usr.bin/diff/tests/simple_i.out
@@ -0,0 +1,6 @@
+4c4
+< * And another bla
+---
+> * And another bla
+11a12
+>
diff --git a/usr.bin/diff/tests/simple_n.out b/usr.bin/diff/tests/simple_n.out
new file mode 100644
index 000000000000..33ca7090cf97
--- /dev/null
+++ b/usr.bin/diff/tests/simple_n.out
@@ -0,0 +1,4 @@
+d2 1
+a2 2
+and written
+to be able to test diff utility
diff --git a/usr.bin/diff/tests/simple_p.out b/usr.bin/diff/tests/simple_p.out
new file mode 100644
index 000000000000..f5aebb0d1199
--- /dev/null
+++ b/usr.bin/diff/tests/simple_p.out
@@ -0,0 +1,34 @@
+*** input_c1.in
+--- input_c2.in
+***************
+*** 1,14 ****
+ /*
+ * A comment
+ *
+! * And another bla
+ *
+! * And yet another
+ */
+
+ int
+ main(void)
+ {
+ printf("something");
+
+ return (0);
+--- 1,15 ----
+ /*
+ * A comment
+ *
+! * And another bla
+ *
+! * and yet another
+ */
+
+ int
+ main(void)
+ {
++
+ printf("something");
+
+ return (0);
diff --git a/usr.bin/diff/tests/simple_u.out b/usr.bin/diff/tests/simple_u.out
new file mode 100644
index 000000000000..f341987ebec6
--- /dev/null
+++ b/usr.bin/diff/tests/simple_u.out
@@ -0,0 +1,7 @@
+--- input1
++++ input2
+@@ -1,2 +1,3 @@
+ Simple input file designed
+-to be able to test diff
++and written
++to be able to test diff utility
diff --git a/usr.bin/diff/tests/simple_w.out b/usr.bin/diff/tests/simple_w.out
new file mode 100644
index 000000000000..704be9d621a8
--- /dev/null
+++ b/usr.bin/diff/tests/simple_w.out
@@ -0,0 +1,6 @@
+6c6
+< * And yet another
+---
+> * and yet another
+11a12
+>
diff --git a/usr.bin/diff/tests/strip_o.out b/usr.bin/diff/tests/strip_o.out
new file mode 100644
index 000000000000..47bbfbd4e921
--- /dev/null
+++ b/usr.bin/diff/tests/strip_o.out
@@ -0,0 +1,7 @@
+--- 1
++++ 2
+@@ -1,3 +1,3 @@
+ a
+-X
++Y
+ c
diff --git a/usr.bin/diff/tests/unified_9999.out b/usr.bin/diff/tests/unified_9999.out
new file mode 100644
index 000000000000..0f9303fbdc7c
--- /dev/null
+++ b/usr.bin/diff/tests/unified_9999.out
@@ -0,0 +1,21 @@
+--- input_c1.in
++++ input_c2.in
+@@ -1,15 +1,16 @@
+ /*
+ * A comment
+ *
+- * And another bla
++ * And another bla
+ *
+- * And yet another
++ * and yet another
+ */
+
+ int
+ main(void)
+ {
++
+ printf("something");
+
+ return (0);
+ }
diff --git a/usr.bin/diff/tests/unified_c9999.out b/usr.bin/diff/tests/unified_c9999.out
new file mode 100644
index 000000000000..87f439463e5d
--- /dev/null
+++ b/usr.bin/diff/tests/unified_c9999.out
@@ -0,0 +1,36 @@
+*** input_c1.in
+--- input_c2.in
+***************
+*** 1,15 ****
+ /*
+ * A comment
+ *
+! * And another bla
+ *
+! * And yet another
+ */
+
+ int
+ main(void)
+ {
+ printf("something");
+
+ return (0);
+ }
+--- 1,16 ----
+ /*
+ * A comment
+ *
+! * And another bla
+ *
+! * and yet another
+ */
+
+ int
+ main(void)
+ {
++
+ printf("something");
+
+ return (0);
+ }
diff --git a/usr.bin/diff/tests/unified_p.out b/usr.bin/diff/tests/unified_p.out
new file mode 100644
index 000000000000..938b07890fbc
--- /dev/null
+++ b/usr.bin/diff/tests/unified_p.out
@@ -0,0 +1,20 @@
+--- input_c1.in
++++ input_c2.in
+@@ -1,14 +1,15 @@
+ /*
+ * A comment
+ *
+- * And another bla
++ * And another bla
+ *
+- * And yet another
++ * and yet another
+ */
+
+ int
+ main(void)
+ {
++
+ printf("something");
+
+ return (0);
diff --git a/usr.bin/diff/xmalloc.c b/usr.bin/diff/xmalloc.c
new file mode 100644
index 000000000000..ce0f4545aee8
--- /dev/null
+++ b/usr.bin/diff/xmalloc.c
@@ -0,0 +1,85 @@
+/* $OpenBSD: xmalloc.c,v 1.10 2019/06/28 05:44:09 deraadt Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ * All rights reserved
+ * Versions of malloc and friends that check their results, and never return
+ * failure (they call fatal if they encounter an error).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose. Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include <err.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmalloc.h"
+
+void *
+xmalloc(size_t size)
+{
+ void *ptr;
+
+ if (size == 0)
+ errx(2, "xmalloc: zero size");
+ ptr = malloc(size);
+ if (ptr == NULL)
+ err(2, "xmalloc: allocating %zu bytes", size);
+ return ptr;
+}
+
+void *
+xcalloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+
+ ptr = calloc(nmemb, size);
+ if (ptr == NULL)
+ err(2, "xcalloc: allocating %zu * %zu bytes", nmemb, size);
+ return ptr;
+}
+
+void *
+xreallocarray(void *ptr, size_t nmemb, size_t size)
+{
+ void *new_ptr;
+
+ new_ptr = reallocarray(ptr, nmemb, size);
+ if (new_ptr == NULL)
+ err(2, "xreallocarray: allocating %zu * %zu bytes",
+ nmemb, size);
+ return new_ptr;
+}
+
+char *
+xstrdup(const char *str)
+{
+ char *cp;
+
+ if ((cp = strdup(str)) == NULL)
+ err(2, "xstrdup");
+ return cp;
+}
+
+int
+xasprintf(char **ret, const char *fmt, ...)
+{
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ i = vasprintf(ret, fmt, ap);
+ va_end(ap);
+
+ if (i == -1)
+ err(2, "xasprintf");
+
+ return i;
+}
diff --git a/usr.bin/diff/xmalloc.h b/usr.bin/diff/xmalloc.h
new file mode 100644
index 000000000000..21396717fa48
--- /dev/null
+++ b/usr.bin/diff/xmalloc.h
@@ -0,0 +1,30 @@
+/* $OpenBSD: xmalloc.h,v 1.4 2015/11/12 16:30:30 mmcc Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ * All rights reserved
+ * Created: Mon Mar 20 22:09:17 1995 ylo
+ *
+ * Versions of malloc and friends that check their results, and never return
+ * failure (they call fatal if they encounter an error).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose. Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+void *xmalloc(size_t);
+void *xcalloc(size_t, size_t);
+void *xreallocarray(void *, size_t, size_t);
+char *xstrdup(const char *);
+int xasprintf(char **, const char *, ...)
+ __attribute__((__format__ (printf, 2, 3)))
+ __attribute__((__nonnull__ (2)));
+
+#endif /* XMALLOC_H */
diff --git a/usr.bin/diff3/Makefile b/usr.bin/diff3/Makefile
new file mode 100644
index 000000000000..828743d092c7
--- /dev/null
+++ b/usr.bin/diff3/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= diff3
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/diff3/diff3.1 b/usr.bin/diff3/diff3.1
new file mode 100644
index 000000000000..9286a79e6ec6
--- /dev/null
+++ b/usr.bin/diff3/diff3.1
@@ -0,0 +1,221 @@
+.\" $OpenBSD: diff3.1,v 1.7 2007/05/31 19:20:09 jmc Exp $
+.\"
+.\" Copyright (c) 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd June 23, 2022
+.Dt DIFF3 1
+.Os
+.Sh NAME
+.Nm diff3
+.Nd 3-way differential file comparison
+.Sh SYNOPSIS
+.Nm
+.Op Fl 3AaEeimTXx
+.Op Fl Fl diff-program Ar program
+.Op Fl Fl strip-trailing-cr
+.Op Fl L | Fl Fl label Ar label1
+.Op Fl L | Fl Fl label Ar label2
+.Op Fl L | Fl Fl label Ar label3
+.Ar file1 file2 file3
+.Nm
+.Op Fl Fl help
+.Op Fl Fl version
+.Sh DESCRIPTION
+The
+.Nm
+utility compares the contents of three different versions of a file,
+.Ar file1 ,
+.Ar file2
+and
+.Ar file3 ,
+writing the result to the standard output.
+The options describe different methods of merging and
+purging
+the separate versions into a new file.
+.Nm
+is used by
+.Xr rcs 1
+to merge specific versions or create
+new versions.
+.Pp
+The options are as follows:
+.Bl -tag -width "-E, -X"
+.It Fl 3 , Fl Fl easy-only
+Produces an output script suitable for
+.Xr ed 1
+with changes
+specific only to
+.Ar file3 .
+.It Fl A Fl Fl show-all
+Output all changes, bracketing conflicts.
+.It Fl a , Fl Fl text
+Treat all files as ASCII.
+.It Fl E , Fl Fl show-overlap
+.It Fl X
+Similar to
+.Fl e
+and
+.Fl x ,
+respectively, but treat overlapping changes (i.e., changes that would
+be noted with ==== in the normal listing) differently.
+The overlapping lines from both files will be inserted by the edit script,
+bracketed by "<<<<<<" and ">>>>>>" lines.
+.It Fl e , Fl Fl ed
+Produces output in a form suitable as an input script for the
+.Xr ed 1
+utility.
+The script may then be used to merge differences common between all
+three files and differences specific to
+.Ar file1
+and
+.Ar file3 .
+In other words, the
+.Fl e
+option ignores differences specific to
+.Ar file1
+and
+.Ar file2 ,
+and those specific to
+.Ar file2
+and
+.Ar file3 .
+It is useful for backing out changes specific to
+.Ar file2
+only.
+.It Fl Fl help
+Prints usage information and exits.
+.It Fl i
+Appends 'w' and 'q'
+.Xr ed 1
+commands.
+.It Fl L , Fl Fl label
+Defines labels to print instead of file names
+.Ar file1 ,
+.Ar file2
+and
+.Ar file3 .
+.It Fl m, Fl Fl merge
+Merge output instead of generating ed script.
+.It Fl T, Fl Fl initial-tab
+In the normal listing,
+use a tab instead of two spaces
+at the beginning of each line.
+In modes that produce an
+.Xr ed 1
+script, this option changes nothing.
+.It Fl x, Fl Fl overlap-only
+Produces an output script suitable for
+.Xr ed 1
+with changes
+specific only to all three versions.
+.It Fl Fl diff-program Ar program
+Use
+.Ar program
+instead of the default
+.Xr diff 1
+to compare files.
+.It Fl Fl strip-trailing-cr
+Strip trailing carriage return on input files.
+.It Fl Fl version
+Prints version information and exits.
+.El
+.Pp
+The
+.Fl E
+option is used by
+.Tn RCS
+.Xr merge 1
+to ensure that overlapping changes in the merged files are preserved
+and brought to someone's attention.
+.Pp
+For example, suppose lines 7-8 are changed in both
+.Ar file1
+and
+.Ar file2 .
+Applying the edit script generated by the command
+.Pp
+.Dl $ diff3 -E file1 file2 file3
+.Pp
+to
+.Ar file1
+results in the file:
+.Bd -literal -offset indent
+lines 1-6
+of file1
+<<<<<<< file1
+lines 7-8
+of file1
+=======
+lines 7-8
+of file3
+>>>>>>> file3
+rest of file1
+.Ed
+.Pp
+The default output of
+.Nm
+makes notation of the differences between all files, and those
+differences specific to each pair of files.
+The changes are described by the commands necessary for
+.Xr ed 1
+to create the desired target from the different versions.
+See
+.Xr diff 1
+for a description of the commands.
+.Bl -tag -width "====="
+.It Li \&====
+The lines beneath this notation are ranges of lines which are different
+between all files.
+.It \&==== Ns Va n
+The lines beneath this notation are ranges of lines which are exclusively
+different in file
+.Va n .
+.El
+.Sh SEE ALSO
+.Xr diff 1 ,
+.Xr ed 1 ,
+.Xr merge 1 ,
+.Xr rcs 1 ,
+.Xr sdiff 1
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v7 .
+.Sh BUGS
+The
+.Fl e
+option cannot catch and change lines which have
+.Ql \&.
+as the first and only character on the line.
+The resulting script will fail on that line
+as
+.Ql \&.
+is an
+.Xr ed 1
+editing command.
diff --git a/usr.bin/diff3/diff3.c b/usr.bin/diff3/diff3.c
new file mode 100644
index 000000000000..39523f6e6b38
--- /dev/null
+++ b/usr.bin/diff3/diff3.c
@@ -0,0 +1,1115 @@
+/* $OpenBSD: diff3prog.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $ */
+
+/*
+ * Copyright (C) Caldera International Inc. 2001-2002.
+ * 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 and documentation 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed or owned by Caldera
+ * International, Inc.
+ * 4. Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, 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 CALDERA INTERNATIONAL, INC. 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.
+ */
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/procdesc.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/wait.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * "from" is first in range of changed lines; "to" is last+1
+ * from=to=line after point of insertion for added lines.
+ */
+struct range {
+ int from;
+ int to;
+};
+
+struct diff {
+#define DIFF_TYPE1 1
+#define DIFF_TYPE2 2
+#define DIFF_TYPE3 3
+ int type;
+#if DEBUG
+ char *line;
+#endif /* DEBUG */
+
+ /* Ranges as lines */
+ struct range old;
+ struct range new;
+};
+
+#define EFLAG_NONE 0
+#define EFLAG_OVERLAP 1
+#define EFLAG_NOOVERLAP 2
+#define EFLAG_UNMERGED 3
+
+static size_t szchanges;
+
+static struct diff *d13;
+static struct diff *d23;
+/*
+ * "de" is used to gather editing scripts. These are later spewed out in
+ * reverse order. Its first element must be all zero, the "old" and "new"
+ * components of "de" contain line positions. Array overlap indicates which
+ * sections in "de" correspond to lines that are different in all three files.
+ */
+static struct diff *de;
+static char *overlap;
+static int overlapcnt;
+static FILE *fp[3];
+static int cline[3]; /* # of the last-read line in each file (0-2) */
+/*
+ * The latest known correspondence between line numbers of the 3 files
+ * is stored in last[1-3];
+ */
+static int last[4];
+static int Aflag, eflag, iflag, mflag, Tflag;
+static int oflag; /* indicates whether to mark overlaps (-E or -X) */
+static int strip_cr;
+static char *f1mark, *f2mark, *f3mark;
+static const char *oldmark = "<<<<<<<";
+static const char *orgmark = "|||||||";
+static const char *newmark = ">>>>>>>";
+static const char *divider = "=======";
+
+static bool duplicate(struct range *, struct range *);
+static int edit(struct diff *, bool, int, int);
+static char *getchange(FILE *);
+static char *get_line(FILE *, size_t *);
+static int readin(int fd, struct diff **);
+static int skip(int, int, const char *);
+static void change(int, struct range *, bool);
+static void keep(int, struct range *);
+static void merge(int, int);
+static void prange(struct range *, bool);
+static void repos(int);
+static void separate(const char *);
+static void edscript(int) __dead2;
+static void Ascript(int) __dead2;
+static void mergescript(int) __dead2;
+static void increase(void);
+static void usage(void);
+static void printrange(FILE *, struct range *);
+
+static const char diff3_version[] = "FreeBSD diff3 20240925";
+
+enum {
+ DIFFPROG_OPT,
+ STRIPCR_OPT,
+ HELP_OPT,
+ VERSION_OPT
+};
+
+#define DIFF_PATH "/usr/bin/diff"
+
+#define OPTIONS "3aAeEiL:mTxX"
+static struct option longopts[] = {
+ { "ed", no_argument, NULL, 'e' },
+ { "show-overlap", no_argument, NULL, 'E' },
+ { "overlap-only", no_argument, NULL, 'x' },
+ { "initial-tab", no_argument, NULL, 'T' },
+ { "text", no_argument, NULL, 'a' },
+ { "strip-trailing-cr", no_argument, NULL, STRIPCR_OPT },
+ { "show-all", no_argument, NULL, 'A' },
+ { "easy-only", no_argument, NULL, '3' },
+ { "merge", no_argument, NULL, 'm' },
+ { "label", required_argument, NULL, 'L' },
+ { "diff-program", required_argument, NULL, DIFFPROG_OPT },
+ { "help", no_argument, NULL, HELP_OPT},
+ { "version", no_argument, NULL, VERSION_OPT}
+};
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: diff3 [-3aAeEimTxX] [-L label1] [-L label2] "
+ "[-L label3] file1 file2 file3\n");
+}
+
+static int
+strtoi(char *str, char **end)
+{
+ intmax_t num;
+
+ errno = 0;
+ num = strtoimax(str, end, 10);
+ if ((end != NULL && *end == str) ||
+ num < 0 || num > INT_MAX ||
+ errno == EINVAL || errno == ERANGE)
+ err(1, "error in diff output");
+ return (int)num;
+}
+
+/*
+ * Read diff hunks into the array pointed to by *dd.
+ *
+ * The output from `diff foo bar` consists of a series of hunks describing
+ * an addition (lines in bar not present in foo), change (lines in bar
+ * different from lines in foo), or deletion (lines in foo not present in
+ * bar). Each record starts with a line of the form:
+ *
+ * a[,b]xc[,d]
+ *
+ * where a, b, c, and d are nonnegative integers (b and d are printed only
+ * if they differ from a and c, respectively), and x is either 'a' for an
+ * addition, 'c' for a change, or 'd' for a deletion. This is then
+ * followed by a series of lines (which we ignore) giving the added,
+ * changed, or deleted text.
+ *
+ * For an addition, a == b is the last line in 'foo' before the addition,
+ * while c through d is the range of lines in 'bar' to be added to 'foo'.
+ *
+ * For a change, a through b is the range of lines in 'foo' to be replaced
+ * and c through d is the range of lines in 'bar' to replace them with.
+ *
+ * For a deletion, a through b is the range of lines in 'foo' to remove
+ * and c == d is the line in 'bar' which corresponds to the last line
+ * before the deletion.
+ *
+ * The observant reader will have noticed that x is not really needed and
+ * that we can fully describe any hunk using only a, b, c, and d:
+ *
+ * - an addition replaces a zero-length range in one file with a
+ * non-zero-length range from the other
+ *
+ * - a change replaces a non-zero-length range in one file with a
+ * non-zero-length range from the other
+ *
+ * - a deletion replaces a non-zero-length range in one file with a
+ * zero-length range from the other
+ */
+static int
+readin(int fd, struct diff **dd)
+{
+ int a, b, c, d;
+ int i;
+ char kind, *p;
+ FILE *f;
+
+ f = fdopen(fd, "r");
+ if (f == NULL)
+ err(2, "fdopen");
+ for (i = 0; (p = getchange(f)) != NULL; i++) {
+ if ((size_t)i >= szchanges - 1)
+ increase();
+#if DEBUG
+ (*dd)[i].line = strdup(p);
+#endif /* DEBUG */
+
+ a = b = strtoi(p, &p);
+ if (*p == ',')
+ b = strtoi(p + 1, &p);
+ kind = *p++;
+ c = d = strtoi(p, &p);
+ if (*p == ',')
+ d = strtoi(p + 1, &p);
+ if (*p != '\n')
+ errx(1, "error in diff output");
+ if (kind == 'a')
+ a++;
+ else if (kind == 'c')
+ /* nothing */ ;
+ else if (kind == 'd')
+ c++;
+ else
+ errx(1, "error in diff output");
+ b++;
+ d++;
+ if (b < a || d < c)
+ errx(1, "error in diff output");
+ (*dd)[i].old.from = a;
+ (*dd)[i].old.to = b;
+ (*dd)[i].new.from = c;
+ (*dd)[i].new.to = d;
+ if (i > 0) {
+ if ((*dd)[i].old.from < (*dd)[i - 1].old.to ||
+ (*dd)[i].new.from < (*dd)[i - 1].new.to)
+ errx(1, "diff output out of order");
+ }
+ }
+ if (i > 0) {
+ (*dd)[i].old.from = (*dd)[i].old.to = (*dd)[i - 1].old.to;
+ (*dd)[i].new.from = (*dd)[i].new.to = (*dd)[i - 1].new.to;
+ }
+ fclose(f);
+ return (i);
+}
+
+static int
+diffexec(const char *diffprog, char **diffargv, int fd[])
+{
+ int pd;
+
+ switch (pdfork(&pd, PD_CLOEXEC)) {
+ case 0:
+ close(fd[0]);
+ if (dup2(fd[1], STDOUT_FILENO) == -1)
+ err(2, "child could not duplicate descriptor");
+ close(fd[1]);
+ execvp(diffprog, diffargv);
+ err(2, "could not execute diff: %s", diffprog);
+ break;
+ case -1:
+ err(2, "could not fork");
+ break;
+ }
+ close(fd[1]);
+ return (pd);
+}
+
+static char *
+getchange(FILE *b)
+{
+ char *line;
+
+ while ((line = get_line(b, NULL)) != NULL) {
+ if (isdigit((unsigned char)line[0]))
+ return (line);
+ }
+ return (NULL);
+}
+
+
+static char *
+get_line(FILE *b, size_t *n)
+{
+ ssize_t len;
+ static char *buf = NULL;
+ static size_t bufsize = 0;
+
+ if ((len = getline(&buf, &bufsize, b)) < 0)
+ return (NULL);
+
+ if (strip_cr && len >= 2 && strcmp("\r\n", &(buf[len - 2])) == 0) {
+ buf[len - 2] = '\n';
+ buf[len - 1] = '\0';
+ len--;
+ }
+
+ if (n != NULL)
+ *n = len;
+
+ return (buf);
+}
+
+static void
+merge(int m1, int m2)
+{
+ struct diff *d1, *d2, *d3;
+ int j, t1, t2;
+ bool dup = false;
+
+ d1 = d13;
+ d2 = d23;
+ j = 0;
+
+ for (;;) {
+ t1 = (d1 < d13 + m1);
+ t2 = (d2 < d23 + m2);
+ if (!t1 && !t2)
+ break;
+
+ /* first file is different from the others */
+ if (!t2 || (t1 && d1->new.to < d2->new.from)) {
+ /* stuff peculiar to 1st file */
+ if (eflag == EFLAG_NONE) {
+ separate("1");
+ change(1, &d1->old, false);
+ keep(2, &d1->new);
+ change(3, &d1->new, false);
+ } else if (eflag == EFLAG_OVERLAP) {
+ j = edit(d2, dup, j, DIFF_TYPE1);
+ }
+ d1++;
+ continue;
+ }
+ /* second file is different from others */
+ if (!t1 || (t2 && d2->new.to < d1->new.from)) {
+ if (eflag == EFLAG_NONE) {
+ separate("2");
+ keep(1, &d2->new);
+ change(3, &d2->new, false);
+ change(2, &d2->old, false);
+ } else if (Aflag || mflag) {
+ // XXX-THJ: What does it mean for the second file to differ?
+ if (eflag == EFLAG_UNMERGED)
+ j = edit(d2, dup, j, DIFF_TYPE2);
+ }
+ d2++;
+ continue;
+ }
+ /*
+ * Merge overlapping changes in first file
+ * this happens after extension (see below).
+ */
+ if (d1 + 1 < d13 + m1 && d1->new.to >= d1[1].new.from) {
+ d1[1].old.from = d1->old.from;
+ d1[1].new.from = d1->new.from;
+ d1++;
+ continue;
+ }
+
+ /* merge overlapping changes in second */
+ if (d2 + 1 < d23 + m2 && d2->new.to >= d2[1].new.from) {
+ d2[1].old.from = d2->old.from;
+ d2[1].new.from = d2->new.from;
+ d2++;
+ continue;
+ }
+ /* stuff peculiar to third file or different in all */
+ if (d1->new.from == d2->new.from && d1->new.to == d2->new.to) {
+ dup = duplicate(&d1->old, &d2->old);
+ /*
+ * dup = 0 means all files differ
+ * dup = 1 means files 1 and 2 identical
+ */
+ if (eflag == EFLAG_NONE) {
+ separate(dup ? "3" : "");
+ change(1, &d1->old, dup);
+ change(2, &d2->old, false);
+ d3 = d1->old.to > d1->old.from ? d1 : d2;
+ change(3, &d3->new, false);
+ } else {
+ j = edit(d1, dup, j, DIFF_TYPE3);
+ }
+ dup = false;
+ d1++;
+ d2++;
+ continue;
+ }
+ /*
+ * Overlapping changes from file 1 and 2; extend changes
+ * appropriately to make them coincide.
+ */
+ if (d1->new.from < d2->new.from) {
+ d2->old.from -= d2->new.from - d1->new.from;
+ d2->new.from = d1->new.from;
+ } else if (d2->new.from < d1->new.from) {
+ d1->old.from -= d1->new.from - d2->new.from;
+ d1->new.from = d2->new.from;
+ }
+ if (d1->new.to > d2->new.to) {
+ d2->old.to += d1->new.to - d2->new.to;
+ d2->new.to = d1->new.to;
+ } else if (d2->new.to > d1->new.to) {
+ d1->old.to += d2->new.to - d1->new.to;
+ d1->new.to = d2->new.to;
+ }
+ }
+
+ if (mflag)
+ mergescript(j);
+ else if (Aflag)
+ Ascript(j);
+ else if (eflag)
+ edscript(j);
+}
+
+static void
+separate(const char *s)
+{
+ printf("====%s\n", s);
+}
+
+/*
+ * The range of lines rold.from thru rold.to in file i is to be changed.
+ * It is to be printed only if it does not duplicate something to be
+ * printed later.
+ */
+static void
+change(int i, struct range *rold, bool dup)
+{
+
+ printf("%d:", i);
+ last[i] = rold->to;
+ prange(rold, false);
+ if (dup)
+ return;
+ i--;
+ skip(i, rold->from, NULL);
+ skip(i, rold->to, " ");
+}
+
+/*
+ * Print the range of line numbers, rold.from thru rold.to, as n1,n2 or
+ * n1.
+ */
+static void
+prange(struct range *rold, bool delete)
+{
+
+ if (rold->to <= rold->from)
+ printf("%da\n", rold->from - 1);
+ else {
+ printf("%d", rold->from);
+ if (rold->to > rold->from + 1)
+ printf(",%d", rold->to - 1);
+ if (delete)
+ printf("d\n");
+ else
+ printf("c\n");
+ }
+}
+
+/*
+ * No difference was reported by diff between file 1 (or 2) and file 3,
+ * and an artificial dummy difference (trange) must be ginned up to
+ * correspond to the change reported in the other file.
+ */
+static void
+keep(int i, struct range *rnew)
+{
+ int delta;
+ struct range trange;
+
+ delta = last[3] - last[i];
+ trange.from = rnew->from - delta;
+ trange.to = rnew->to - delta;
+ change(i, &trange, true);
+}
+
+/*
+ * skip to just before line number from in file "i". If "pr" is non-NULL,
+ * print all skipped stuff with string pr as a prefix.
+ */
+static int
+skip(int i, int from, const char *pr)
+{
+ size_t j, n;
+ char *line;
+
+ for (n = 0; cline[i] < from - 1; n += j) {
+ if ((line = get_line(fp[i], &j)) == NULL)
+ errx(EXIT_FAILURE, "logic error");
+ if (pr != NULL)
+ printf("%s%s", Tflag == 1 ? "\t" : pr, line);
+ cline[i]++;
+ }
+ return ((int) n);
+}
+
+/*
+ * Return 1 or 0 according as the old range (in file 1) contains exactly
+ * the same data as the new range (in file 2).
+ */
+static bool
+duplicate(struct range *r1, struct range *r2)
+{
+ int c, d;
+ int nchar;
+ int nline;
+
+ if (r1->to-r1->from != r2->to-r2->from)
+ return (0);
+ skip(0, r1->from, NULL);
+ skip(1, r2->from, NULL);
+ nchar = 0;
+ for (nline = 0; nline < r1->to - r1->from; nline++) {
+ do {
+ c = getc(fp[0]);
+ d = getc(fp[1]);
+ if (c == -1 && d == -1)
+ break;
+ if (c == -1 || d == -1)
+ errx(EXIT_FAILURE, "logic error");
+ nchar++;
+ if (c != d) {
+ repos(nchar);
+ return (0);
+ }
+ } while (c != '\n');
+ }
+ repos(nchar);
+ return (1);
+}
+
+static void
+repos(int nchar)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ (void)fseek(fp[i], (long)-nchar, SEEK_CUR);
+}
+
+/*
+ * collect an editing script for later regurgitation
+ */
+static int
+edit(struct diff *diff, bool dup, int j, int difftype)
+{
+ if (!(eflag == EFLAG_UNMERGED ||
+ (!dup && eflag == EFLAG_OVERLAP ) ||
+ (dup && eflag == EFLAG_NOOVERLAP))) {
+ return (j);
+ }
+ j++;
+ overlap[j] = !dup;
+ if (!dup)
+ overlapcnt++;
+
+ de[j].type = difftype;
+#if DEBUG
+ de[j].line = strdup(diff->line);
+#endif /* DEBUG */
+
+ de[j].old.from = diff->old.from;
+ de[j].old.to = diff->old.to;
+ de[j].new.from = diff->new.from;
+ de[j].new.to = diff->new.to;
+ return (j);
+}
+
+static void
+printrange(FILE *p, struct range *r)
+{
+ char *line = NULL;
+ size_t len = 0;
+ int i = 1;
+
+ /* We haven't been asked to print anything */
+ if (r->from == r->to)
+ return;
+
+ if (r->from > r->to)
+ errx(EXIT_FAILURE, "invalid print range");
+
+ /*
+ * XXX-THJ: We read through all of the file for each range printed.
+ * This duplicates work and will probably impact performance on large
+ * files with lots of ranges.
+ */
+ fseek(p, 0L, SEEK_SET);
+ while (getline(&line, &len, p) > 0) {
+ if (i >= r->from)
+ printf("%s", line);
+ if (++i > r->to - 1)
+ break;
+ }
+ free(line);
+}
+
+/* regurgitate */
+static void
+edscript(int n)
+{
+ bool delete;
+ struct range *new, *old;
+
+ for (; n > 0; n--) {
+ new = &de[n].new;
+ old = &de[n].old;
+
+ delete = (new->from == new->to);
+ if (de[n].type == DIFF_TYPE1) {
+ if (delete)
+ printf("%dd\n", new->from - 1);
+ else if (old->from == new->from && old->to == new->to) {
+ printf("%dc\n", old->from);
+ printrange(fp[2], old);
+ printf(".\n");
+ }
+ continue;
+ } else {
+ if (!oflag || !overlap[n]) {
+ prange(old, delete);
+ } else {
+ printf("%da\n", old->to - 1);
+ printf("%s\n", divider);
+ }
+ printrange(fp[2], new);
+ if (!oflag || !overlap[n]) {
+ if (!delete)
+ printf(".\n");
+ } else {
+ printf("%s %s\n.\n", newmark, f3mark);
+ printf("%da\n%s %s\n.\n", old->from - 1,
+ oldmark, f1mark);
+ }
+ }
+ }
+ if (iflag)
+ printf("w\nq\n");
+
+ exit(eflag == EFLAG_NONE ? overlapcnt : 0);
+}
+
+/*
+ * Output an edit script to turn mine into yours, when there is a conflict
+ * between the 3 files bracket the changes. Regurgitate the diffs in reverse
+ * order to allow the ed script to track down where the lines are as changes
+ * are made.
+ */
+static void
+Ascript(int n)
+{
+ int startmark;
+ bool deletenew;
+ bool deleteold;
+
+ struct range *new, *old;
+
+ for (; n > 0; n--) {
+ new = &de[n].new;
+ old = &de[n].old;
+ deletenew = (new->from == new->to);
+ deleteold = (old->from == old->to);
+
+ if (de[n].type == DIFF_TYPE2) {
+ if (!oflag || !overlap[n]) {
+ prange(old, deletenew);
+ printrange(fp[2], new);
+ } else {
+ startmark = new->to - 1;
+
+ printf("%da\n", startmark);
+ printf("%s %s\n", newmark, f3mark);
+
+ printf(".\n");
+
+ printf("%da\n", startmark -
+ (new->to - new->from));
+ printf("%s %s\n", oldmark, f2mark);
+ if (!deleteold)
+ printrange(fp[1], old);
+ printf("%s\n.\n", divider);
+ }
+
+ } else if (de[n].type == DIFF_TYPE3) {
+ startmark = old->to - 1;
+
+ if (!oflag || !overlap[n]) {
+ prange(old, deletenew);
+ printrange(fp[2], new);
+ } else {
+ printf("%da\n", startmark);
+ printf("%s %s\n", orgmark, f2mark);
+
+ if (deleteold) {
+ struct range r;
+ r.from = old->from-1;
+ r.to = new->to;
+ printrange(fp[1], &r);
+ } else
+ printrange(fp[1], old);
+
+ printf("%s\n", divider);
+ printrange(fp[2], new);
+ }
+
+ if (!oflag || !overlap[n]) {
+ if (!deletenew)
+ printf(".\n");
+ } else {
+ printf("%s %s\n.\n", newmark, f3mark);
+
+ /*
+ * Go to the start of the conflict in original
+ * file and append lines
+ */
+ printf("%da\n%s %s\n.\n",
+ startmark - (old->to - old->from),
+ oldmark, f1mark);
+ }
+ }
+ }
+ if (iflag)
+ printf("w\nq\n");
+
+ exit(overlapcnt > 0);
+}
+
+/*
+ * Output the merged file directly (don't generate an ed script). When
+ * regurgitating diffs we need to walk forward through the file and print any
+ * inbetween lines.
+ */
+static void
+mergescript(int i)
+{
+ struct range r, *new, *old;
+ int n;
+ bool delete = false;
+
+ r.from = 1;
+ r.to = 1;
+
+ for (n = 1; n <= i; n++) {
+ new = &de[n].new;
+ old = &de[n].old;
+
+ /*
+ * Print any lines leading up to here. If we are merging don't
+ * print deleted ranges.
+ */
+ delete = (new->from == new->to);
+ if (de[n].type == DIFF_TYPE1 && delete)
+ r.to = new->from - 1;
+ else if (de[n].type == DIFF_TYPE3 && (old->from == old->to)) {
+ r.from = old->from - 1;
+ r.to = new->from;
+ } else
+ r.to = old->from;
+
+ printrange(fp[0], &r);
+ switch (de[n].type) {
+ case DIFF_TYPE1:
+ /* If this isn't a delete print it */
+ if (!delete)
+ printrange(fp[2], new);
+ break;
+ case DIFF_TYPE2:
+ printf("%s %s\n", oldmark, f2mark);
+ printrange(fp[1], old);
+ printf("%s\n", divider);
+ printrange(fp[2], new);
+ printf("%s %s\n", newmark, f3mark);
+ break;
+ case DIFF_TYPE3:
+ if (!oflag || !overlap[n]) {
+ printrange(fp[2], new);
+ } else {
+
+ printf("%s %s\n", oldmark, f1mark);
+ printrange(fp[0], old);
+
+ if (eflag != EFLAG_OVERLAP) {
+ printf("%s %s\n", orgmark, f2mark);
+ if (old->from == old->to) {
+ struct range or;
+ or.from = old->from - 1;
+ or.to = new->to;
+ printrange(fp[1], &or);
+ } else {
+ printrange(fp[1], old);
+ }
+ }
+
+ printf("%s\n", divider);
+
+ printrange(fp[2], new);
+ printf("%s %s\n", newmark, f3mark);
+ }
+ break;
+ default:
+ printf("Error: Unhandled diff type - exiting\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (old->from == old->to)
+ r.from = new->to;
+ else
+ r.from = old->to;
+ }
+
+ /*
+ * Print from the final range to the end of 'myfile'. Any deletions or
+ * additions to this file should have been handled by now.
+ *
+ * If the ranges are the same we need to rewind a line.
+ * If the new range is 0 length (from == to), we need to use the old
+ * range.
+ */
+ new = &de[n-1].new;
+ old = &de[n-1].old;
+
+ if (old->from == new->from && old->to == new->to)
+ r.from--;
+ else if (new->from == new->to)
+ r.from = old->from;
+
+ r.to = INT_MAX;
+ printrange(fp[2], &r);
+ exit(overlapcnt > 0);
+}
+
+static void
+increase(void)
+{
+ struct diff *p;
+ char *q;
+ size_t newsz, incr;
+
+ /* are the memset(3) calls needed? */
+ newsz = szchanges == 0 ? 64 : 2 * szchanges;
+ incr = newsz - szchanges;
+
+ p = reallocarray(d13, newsz, sizeof(*p));
+ if (p == NULL)
+ err(1, NULL);
+ memset(p + szchanges, 0, incr * sizeof(*p));
+ d13 = p;
+ p = reallocarray(d23, newsz, sizeof(*p));
+ if (p == NULL)
+ err(1, NULL);
+ memset(p + szchanges, 0, incr * sizeof(*p));
+ d23 = p;
+ p = reallocarray(de, newsz, sizeof(*p));
+ if (p == NULL)
+ err(1, NULL);
+ memset(p + szchanges, 0, incr * sizeof(*p));
+ de = p;
+ q = reallocarray(overlap, newsz, 1);
+ if (q == NULL)
+ err(1, NULL);
+ memset(q + szchanges, 0, incr * 1);
+ overlap = q;
+ szchanges = newsz;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int ch, nblabels, status, m, n, kq, nke, nleft, i;
+ char *labels[] = { NULL, NULL, NULL };
+ const char *diffprog = DIFF_PATH;
+ char *file1, *file2, *file3;
+ char *diffargv[7];
+ int diffargc = 0;
+ int fd13[2], fd23[2];
+ int pd13, pd23;
+ cap_rights_t rights_ro;
+ struct kevent *e;
+
+ nblabels = 0;
+ eflag = EFLAG_NONE;
+ oflag = 0;
+ diffargv[diffargc++] = __DECONST(char *, diffprog);
+ while ((ch = getopt_long(argc, argv, OPTIONS, longopts, NULL)) != -1) {
+ switch (ch) {
+ case '3':
+ eflag = EFLAG_NOOVERLAP;
+ break;
+ case 'a':
+ diffargv[diffargc++] = __DECONST(char *, "-a");
+ break;
+ case 'A':
+ Aflag = 1;
+ break;
+ case 'e':
+ eflag = EFLAG_UNMERGED;
+ break;
+ case 'E':
+ eflag = EFLAG_OVERLAP;
+ oflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'L':
+ oflag = 1;
+ if (nblabels >= 3)
+ errx(2, "too many file label options");
+ labels[nblabels++] = optarg;
+ break;
+ case 'm':
+ Aflag = 1;
+ oflag = 1;
+ mflag = 1;
+ break;
+ case 'T':
+ Tflag = 1;
+ break;
+ case 'x':
+ eflag = EFLAG_OVERLAP;
+ break;
+ case 'X':
+ oflag = 1;
+ eflag = EFLAG_OVERLAP;
+ break;
+ case DIFFPROG_OPT:
+ diffprog = optarg;
+ break;
+ case STRIPCR_OPT:
+ strip_cr = 1;
+ diffargv[diffargc++] = __DECONST(char *, "--strip-trailing-cr");
+ break;
+ case HELP_OPT:
+ usage();
+ exit(0);
+ case VERSION_OPT:
+ printf("%s\n", diff3_version);
+ exit(0);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (Aflag) {
+ if (eflag == EFLAG_NONE)
+ eflag = EFLAG_UNMERGED;
+ oflag = 1;
+ }
+
+ if (argc != 3) {
+ usage();
+ exit(2);
+ }
+
+ if (caph_limit_stdio() == -1)
+ err(2, "unable to limit stdio");
+
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
+
+ kq = kqueue();
+ if (kq == -1)
+ err(2, "kqueue");
+
+ e = malloc(2 * sizeof(*e));
+ if (e == NULL)
+ err(2, "malloc");
+
+ /* TODO stdio */
+ file1 = argv[0];
+ file2 = argv[1];
+ file3 = argv[2];
+
+ if (oflag) {
+ asprintf(&f1mark, "%s",
+ labels[0] != NULL ? labels[0] : file1);
+ if (f1mark == NULL)
+ err(2, "asprintf");
+ asprintf(&f2mark, "%s",
+ labels[1] != NULL ? labels[1] : file2);
+ if (f2mark == NULL)
+ err(2, "asprintf");
+ asprintf(&f3mark, "%s",
+ labels[2] != NULL ? labels[2] : file3);
+ if (f3mark == NULL)
+ err(2, "asprintf");
+ }
+ fp[0] = fopen(file1, "r");
+ if (fp[0] == NULL)
+ err(2, "Can't open %s", file1);
+ if (caph_rights_limit(fileno(fp[0]), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file1);
+
+ fp[1] = fopen(file2, "r");
+ if (fp[1] == NULL)
+ err(2, "Can't open %s", file2);
+ if (caph_rights_limit(fileno(fp[1]), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file2);
+
+ fp[2] = fopen(file3, "r");
+ if (fp[2] == NULL)
+ err(2, "Can't open %s", file3);
+ if (caph_rights_limit(fileno(fp[2]), &rights_ro) < 0)
+ err(2, "unable to limit rights on: %s", file3);
+
+ if (pipe(fd13))
+ err(2, "pipe");
+ if (pipe(fd23))
+ err(2, "pipe");
+
+ diffargv[diffargc] = file1;
+ diffargv[diffargc + 1] = file3;
+ diffargv[diffargc + 2] = NULL;
+
+ nleft = 0;
+ pd13 = diffexec(diffprog, diffargv, fd13);
+ EV_SET(e + nleft , pd13, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, NULL);
+ if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
+ err(2, "kevent1");
+ nleft++;
+
+ diffargv[diffargc] = file2;
+ pd23 = diffexec(diffprog, diffargv, fd23);
+ EV_SET(e + nleft , pd23, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, NULL);
+ if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
+ err(2, "kevent2");
+ nleft++;
+
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(2, "unable to enter capability mode");
+
+ /* parse diffs */
+ increase();
+ m = readin(fd13[0], &d13);
+ n = readin(fd23[0], &d23);
+
+ /* waitpid cooked over pdforks */
+ while (nleft > 0) {
+ nke = kevent(kq, NULL, 0, e, nleft, NULL);
+ if (nke == -1)
+ err(2, "kevent");
+ for (i = 0; i < nke; i++) {
+ status = e[i].data;
+ if (WIFEXITED(status) && WEXITSTATUS(status) >= 2)
+ errx(2, "diff exited abnormally");
+ else if (WIFSIGNALED(status))
+ errx(2, "diff killed by signal %d",
+ WTERMSIG(status));
+ }
+ nleft -= nke;
+ }
+ free(e);
+ merge(m, n);
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr.bin/diff3/tests/1.out b/usr.bin/diff3/tests/1.out
new file mode 100644
index 000000000000..9b872bf3a880
--- /dev/null
+++ b/usr.bin/diff3/tests/1.out
@@ -0,0 +1,14 @@
+====
+1:2,3c
+ which multiple lines
+ and a few typ0s to fix
+2:2,3c
+ which multiple lines
+ and a few typos to fix
+3:2c
+ and a few typ0s to fix
+====2
+1:4a
+3:3a
+2:5c
+ New line
diff --git a/usr.bin/diff3/tests/1.txt b/usr.bin/diff3/tests/1.txt
new file mode 100644
index 000000000000..f0cd8062a6f1
--- /dev/null
+++ b/usr.bin/diff3/tests/1.txt
@@ -0,0 +1,6 @@
+This is a more complete test
+which multiple lines
+and a few typ0s to fix
+also I plan to add few lines
+ and to remove
+other lines
diff --git a/usr.bin/diff3/tests/1cr.txt b/usr.bin/diff3/tests/1cr.txt
new file mode 100644
index 000000000000..c24bf241e68a
--- /dev/null
+++ b/usr.bin/diff3/tests/1cr.txt
@@ -0,0 +1,6 @@
+This is a more complete test
+which multiple lines
+and a few typ0s to fix
+also I plan to add few lines
+ and to remove
+other lines
diff --git a/usr.bin/diff3/tests/1t.out b/usr.bin/diff3/tests/1t.out
new file mode 100644
index 000000000000..fc54ce50286f
--- /dev/null
+++ b/usr.bin/diff3/tests/1t.out
@@ -0,0 +1,14 @@
+====
+1:2,3c
+ which multiple lines
+ and a few typ0s to fix
+2:2,3c
+ which multiple lines
+ and a few typos to fix
+3:2c
+ and a few typ0s to fix
+====2
+1:4a
+3:3a
+2:5c
+ New line
diff --git a/usr.bin/diff3/tests/2.out b/usr.bin/diff3/tests/2.out
new file mode 100644
index 000000000000..420dc4784b80
--- /dev/null
+++ b/usr.bin/diff3/tests/2.out
@@ -0,0 +1,3 @@
+2,3c
+and a few typ0s to fix
+.
diff --git a/usr.bin/diff3/tests/2.txt b/usr.bin/diff3/tests/2.txt
new file mode 100644
index 000000000000..990aa6f345c6
--- /dev/null
+++ b/usr.bin/diff3/tests/2.txt
@@ -0,0 +1,7 @@
+This is a more complete test
+which multiple lines
+and a few typos to fix
+also I plan to add few lines
+New line
+ and to remove
+other lines
diff --git a/usr.bin/diff3/tests/3.out b/usr.bin/diff3/tests/3.out
new file mode 100644
index 000000000000..81509d4ca510
--- /dev/null
+++ b/usr.bin/diff3/tests/3.out
@@ -0,0 +1,8 @@
+3a
+=======
+and a few typ0s to fix
+>>>>>>> 3
+.
+1a
+<<<<<<< 1
+.
diff --git a/usr.bin/diff3/tests/3.txt b/usr.bin/diff3/tests/3.txt
new file mode 100644
index 000000000000..104466e49690
--- /dev/null
+++ b/usr.bin/diff3/tests/3.txt
@@ -0,0 +1,5 @@
+This is a more complete test
+and a few typ0s to fix
+also I plan to add few lines
+ and to remove
+other lines
diff --git a/usr.bin/diff3/tests/4.out b/usr.bin/diff3/tests/4.out
new file mode 100644
index 000000000000..81509d4ca510
--- /dev/null
+++ b/usr.bin/diff3/tests/4.out
@@ -0,0 +1,8 @@
+3a
+=======
+and a few typ0s to fix
+>>>>>>> 3
+.
+1a
+<<<<<<< 1
+.
diff --git a/usr.bin/diff3/tests/5.out b/usr.bin/diff3/tests/5.out
new file mode 100644
index 000000000000..420dc4784b80
--- /dev/null
+++ b/usr.bin/diff3/tests/5.out
@@ -0,0 +1,3 @@
+2,3c
+and a few typ0s to fix
+.
diff --git a/usr.bin/diff3/tests/6.out b/usr.bin/diff3/tests/6.out
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/diff3/tests/6.out
diff --git a/usr.bin/diff3/tests/7.out b/usr.bin/diff3/tests/7.out
new file mode 100644
index 000000000000..9b872bf3a880
--- /dev/null
+++ b/usr.bin/diff3/tests/7.out
@@ -0,0 +1,14 @@
+====
+1:2,3c
+ which multiple lines
+ and a few typ0s to fix
+2:2,3c
+ which multiple lines
+ and a few typos to fix
+3:2c
+ and a few typ0s to fix
+====2
+1:4a
+3:3a
+2:5c
+ New line
diff --git a/usr.bin/diff3/tests/8.out b/usr.bin/diff3/tests/8.out
new file mode 100644
index 000000000000..5d02326ed7d1
--- /dev/null
+++ b/usr.bin/diff3/tests/8.out
@@ -0,0 +1,19 @@
+4a
+>>>>>>> 3
+.
+4a
+<<<<<<< 2
+New line
+=======
+.
+3a
+||||||| 2
+which multiple lines
+and a few typos to fix
+=======
+and a few typ0s to fix
+>>>>>>> 3
+.
+1a
+<<<<<<< 1
+.
diff --git a/usr.bin/diff3/tests/9.out b/usr.bin/diff3/tests/9.out
new file mode 100644
index 000000000000..2071bab4ce07
--- /dev/null
+++ b/usr.bin/diff3/tests/9.out
@@ -0,0 +1,17 @@
+This is a more complete test
+<<<<<<< 1
+which multiple lines
+and a few typ0s to fix
+||||||| 2
+which multiple lines
+and a few typos to fix
+=======
+and a few typ0s to fix
+>>>>>>> 3
+also I plan to add few lines
+<<<<<<< 2
+New line
+=======
+>>>>>>> 3
+ and to remove
+other lines
diff --git a/usr.bin/diff3/tests/Makefile b/usr.bin/diff3/tests/Makefile
new file mode 100644
index 000000000000..864f27beede8
--- /dev/null
+++ b/usr.bin/diff3/tests/Makefile
@@ -0,0 +1,28 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= diff3_test
+${PACKAGE}FILES+= \
+ 1.txt \
+ 1cr.txt \
+ 2.txt \
+ 3.txt \
+ long-m.txt \
+ long-o.txt \
+ long-y.txt \
+ 1.out \
+ 1t.out \
+ 2.out \
+ 3.out \
+ 4.out \
+ 5.out \
+ 6.out \
+ 7.out \
+ 8.out \
+ 9.out \
+ long-ed.out \
+ long-A.out \
+ long-merge.out \
+ fbsdid1.txt \
+ fbsdid2.txt
+
+.include <bsd.test.mk>
diff --git a/usr.bin/diff3/tests/Makefile.depend b/usr.bin/diff3/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/diff3/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/diff3/tests/diff3_test.sh b/usr.bin/diff3/tests/diff3_test.sh
new file mode 100755
index 000000000000..3cbd7dac1ed9
--- /dev/null
+++ b/usr.bin/diff3/tests/diff3_test.sh
@@ -0,0 +1,108 @@
+
+atf_test_case diff3
+atf_test_case diff3_lesssimple
+atf_test_case diff3_ed
+atf_test_case diff3_A
+atf_test_case diff3_merge
+atf_test_case diff3_E_merge
+
+diff3_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/1.out \
+ diff3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/1.out \
+ diff3 --strip-trailing-cr $(atf_get_srcdir)/1cr.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/1t.out \
+ diff3 -T $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/2.out \
+ diff3 -e $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/3.out \
+ diff3 -E -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/4.out \
+ diff3 -X -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/5.out \
+ diff3 -x $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/6.out \
+ diff3 -3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -o file:$(atf_get_srcdir)/7.out \
+ diff3 -i $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+}
+
+diff3_lesssimple_body()
+{
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/10.out \
+ diff3 -m -L 1 -L 2 -L 3 $(atf_get_srcdir)/4.txt $(atf_get_srcdir)/5.txt $(atf_get_srcdir)/6.txt
+}
+
+diff3_ed_body()
+{
+ atf_check -s exit:0 -o file:$(atf_get_srcdir)/long-ed.out \
+ diff3 -e $(atf_get_srcdir)/long-m.txt $(atf_get_srcdir)/long-o.txt $(atf_get_srcdir)/long-y.txt
+}
+
+diff3_A_body()
+{
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/8.out \
+ diff3 -A -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/long-A.out \
+ diff3 -A -L long-m.txt -L long-o.txt -L long-y.txt $(atf_get_srcdir)/long-m.txt $(atf_get_srcdir)/long-o.txt $(atf_get_srcdir)/long-y.txt
+}
+
+
+diff3_merge_body()
+{
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/9.out \
+ diff3 -m -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt
+
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/long-merge.out \
+ diff3 -m -L long-m.txt -L long-o.txt -L long-y.txt $(atf_get_srcdir)/long-m.txt $(atf_get_srcdir)/long-o.txt $(atf_get_srcdir)/long-y.txt
+}
+
+diff3_E_merge_body()
+{
+
+expected="<<<<<<< 2
+# \$FreeBSD: head/local 12000 jhb \$
+=======
+# \$FreeBSD: head/local 12345 jhb \$
+>>>>>>> 3
+# \$FreeBSD: head/local 12345 jhb \$
+
+this is a file
+
+these are some local mods to the file
+"
+ # first test the regular test
+ cp $(atf_get_srcdir)/fbsdid2.txt out.txt
+ atf_check -s exit:1 -o inline:"${expected}" \
+ diff3 -m -L 1 -L 2 -L 3 out.txt $(atf_get_srcdir)/fbsdid1.txt $(atf_get_srcdir)/fbsdid2.txt
+
+merged="# \$FreeBSD: head/local 12345 jhb \$
+
+this is a file
+
+these are some local mods to the file
+"
+ atf_check -s exit:0 -o inline:"${merged}" \
+ diff3 -E -m out.txt $(atf_get_srcdir)/fbsdid1.txt $(atf_get_srcdir)/fbsdid2.txt
+}
+
+
+atf_init_test_cases()
+{
+ atf_add_test_case diff3
+# atf_add_test_case diff3_lesssimple
+ atf_add_test_case diff3_ed
+ atf_add_test_case diff3_A
+ atf_add_test_case diff3_merge
+ atf_add_test_case diff3_E_merge
+}
diff --git a/usr.bin/diff3/tests/fbsdid1.txt b/usr.bin/diff3/tests/fbsdid1.txt
new file mode 100644
index 000000000000..9f94660bda97
--- /dev/null
+++ b/usr.bin/diff3/tests/fbsdid1.txt
@@ -0,0 +1,5 @@
+# $FreeBSD: head/local 12000 jhb $
+
+this is a file
+
+these are some local mods to the file
diff --git a/usr.bin/diff3/tests/fbsdid2.txt b/usr.bin/diff3/tests/fbsdid2.txt
new file mode 100644
index 000000000000..420ad975868b
--- /dev/null
+++ b/usr.bin/diff3/tests/fbsdid2.txt
@@ -0,0 +1,5 @@
+# $FreeBSD: head/local 12345 jhb $
+
+this is a file
+
+these are some local mods to the file
diff --git a/usr.bin/diff3/tests/long-A.out b/usr.bin/diff3/tests/long-A.out
new file mode 100644
index 000000000000..2a2e4cbb112d
--- /dev/null
+++ b/usr.bin/diff3/tests/long-A.out
@@ -0,0 +1,22 @@
+24d
+16a
+||||||| long-o.txt
+This line is different in yours and mine, but the different in each
+=======
+This line is different in yours and mine, but the best in yours
+>>>>>>> long-y.txt
+.
+15a
+<<<<<<< long-m.txt
+.
+11a
+>>>>>>> long-y.txt
+.
+10a
+<<<<<<< long-o.txt
+This line is different in yours and mine, but the same
+=======
+.
+8c
+This line is different in yours, much butter
+.
diff --git a/usr.bin/diff3/tests/long-ed.out b/usr.bin/diff3/tests/long-ed.out
new file mode 100644
index 000000000000..8814a3518d60
--- /dev/null
+++ b/usr.bin/diff3/tests/long-ed.out
@@ -0,0 +1,7 @@
+24d
+16c
+This line is different in yours and mine, but the best in yours
+.
+8c
+This line is different in yours, much butter
+.
diff --git a/usr.bin/diff3/tests/long-m.txt b/usr.bin/diff3/tests/long-m.txt
new file mode 100644
index 000000000000..327bf8c225f7
--- /dev/null
+++ b/usr.bin/diff3/tests/long-m.txt
@@ -0,0 +1,26 @@
+This is a long file
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in mine, not better
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, the same is in both
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, best change in mine
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is deleted in yours
+These lines are the same in all three files
+These lines are the same in all three files
diff --git a/usr.bin/diff3/tests/long-merge.out b/usr.bin/diff3/tests/long-merge.out
new file mode 100644
index 000000000000..5139a48fa429
--- /dev/null
+++ b/usr.bin/diff3/tests/long-merge.out
@@ -0,0 +1,35 @@
+This is a long file
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in mine, not better
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours, much butter
+These lines are the same in all three files
+These lines are the same in all three files
+<<<<<<< long-o.txt
+This line is different in yours and mine, but the same
+=======
+This line is different in yours and mine, the same is in both
+>>>>>>> long-y.txt
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+<<<<<<< long-m.txt
+This line is different in yours and mine, best change in mine
+||||||| long-o.txt
+This line is different in yours and mine, but the different in each
+=======
+This line is different in yours and mine, but the best in yours
+>>>>>>> long-y.txt
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
diff --git a/usr.bin/diff3/tests/long-o.txt b/usr.bin/diff3/tests/long-o.txt
new file mode 100644
index 000000000000..b4085d1d98c0
--- /dev/null
+++ b/usr.bin/diff3/tests/long-o.txt
@@ -0,0 +1,27 @@
+This is a long file
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in mine
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, but the same
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, but the different in each
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is deleted in mine
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is deleted in yours
+These lines are the same in all three files
+These lines are the same in all three files
diff --git a/usr.bin/diff3/tests/long-y.txt b/usr.bin/diff3/tests/long-y.txt
new file mode 100644
index 000000000000..1bb25004924e
--- /dev/null
+++ b/usr.bin/diff3/tests/long-y.txt
@@ -0,0 +1,26 @@
+This is a long file
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in mine
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours, much butter
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, the same is in both
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours and mine, but the best in yours
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is deleted in mine
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
diff --git a/usr.bin/dirname/Makefile b/usr.bin/dirname/Makefile
new file mode 100644
index 000000000000..cc7d1a1b16b9
--- /dev/null
+++ b/usr.bin/dirname/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= dirname
+MAN=
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/dirname/Makefile.depend b/usr.bin/dirname/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/dirname/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dirname/dirname.c b/usr.bin/dirname/dirname.c
new file mode 100644
index 000000000000..ff2310b4bb27
--- /dev/null
+++ b/usr.bin/dirname/dirname.c
@@ -0,0 +1,77 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ char *p;
+ int ch;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ while (argc--) {
+ if ((p = dirname(*argv)) == NULL)
+ err(1, "%s", *argv);
+ argv++;
+ (void)printf("%s\n", p);
+ }
+ exit(0);
+}
+
+void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: dirname string [...]\n");
+ exit(1);
+}
diff --git a/usr.bin/dirname/tests/Makefile b/usr.bin/dirname/tests/Makefile
new file mode 100644
index 000000000000..d254264c8990
--- /dev/null
+++ b/usr.bin/dirname/tests/Makefile
@@ -0,0 +1,5 @@
+NETBSD_ATF_TESTS_SH= dirname_test
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/dirname/tests/Makefile.depend b/usr.bin/dirname/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/dirname/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dpv/Makefile b/usr.bin/dpv/Makefile
new file mode 100644
index 000000000000..104c865626b9
--- /dev/null
+++ b/usr.bin/dpv/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= dpv
+
+PROG= dpv
+
+CFLAGS+= -I${.CURDIR}
+
+LIBADD= dpv dialog
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/dpv/Makefile.depend b/usr.bin/dpv/Makefile.depend
new file mode 100644
index 000000000000..2313ff2ff894
--- /dev/null
+++ b/usr.bin/dpv/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/libdialog \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libdpv \
+ lib/libfigpar \
+ lib/msun \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dpv/dpv.1 b/usr.bin/dpv/dpv.1
new file mode 100644
index 000000000000..5d91a5ef379e
--- /dev/null
+++ b/usr.bin/dpv/dpv.1
@@ -0,0 +1,448 @@
+.\" Copyright (c) 2013-2016 Devin Teske
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 November 2, 2021
+.Dt DPV 1
+.Os
+.Sh NAME
+.Nm dpv
+.Nd stream data from stdin or multiple paths with dialog progress view
+.Sh SYNOPSIS
+.Nm
+.Op options
+.Sm off
+.Op Ar bytes Cm \&:
+.Ar label
+.Sm on
+.Nm
+.Op options
+.Fl m
+.Sm off
+.Op Ar bytes1 Cm \& :
+. Ar label1
+.Sm on
+.Ar path1
+.Oo
+.Sm off
+.Op Ar bytes2 Cm \&:
+.Ar label2
+.Sm on
+.Ar path2
+.Ar ...
+.Oc
+.Sh DESCRIPTION
+.Nm
+provides a dialog progress view, allowing a user to see current throughput rate
+and total data transferred for one or more streams.
+.Pp
+The
+.Nm
+utility has two main modes for processing input.
+.Pp
+The default input mode, without
+.Ql Fl m ,
+.Nm
+reads bytes from standard input.
+A label for the data must be provided.
+.Pp
+The secondary input mode, with
+.Ql Fl m ,
+.Nm
+reads multiple paths
+.Pq up to 2047 or Dq ARG_MAX/2-1 ,
+sequentially.
+.Pp
+Data read in either mode is either thrown away
+.Pq default ,
+sent to a spawned instance of the program specified via
+.Ql Fl x Ar cmd ,
+or sent to a unique file specified by
+.Ql Fl o Ar file .
+.Pp
+With or without
+.Ql Fl m ,
+progress is displayed using one of
+.Xr dialog 3
+.Pq default ,
+.Xr dialog 1
+.Pq see Ql Fl D ,
+or instead
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog
+.Pq see Ql Fl X .
+.Pp
+The following options are available:
+.Bl -tag -width "-b backtitle"
+.It Fl a Ar text
+Display
+.Ar text
+below the file progress indicator(s).
+.It Fl b Ar backtitle
+Display
+.Ar backtitle
+on the backdrop, at top-left, behind the dialog widget.
+When using
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog ,
+this is displayed inside the window
+.Pq at the top
+followed by a separator line.
+.It Fl D
+Do not use the default interface of
+.Xr dialog 3 ,
+but instead spawn an instance of
+.Xr dialog 1 .
+The path to
+.Xr dialog 1
+is taken from the
+.Ev DIALOG
+environment variable or simply
+.Dq Li dialog
+if unset or NULL.
+.It Fl d
+Debug mode.
+Print dialog prompt data to standard out and provide additional debugging on
+standard error.
+.It Fl h
+Produce a short syntax usage with brief option descriptions and exit.
+Output is produced on standard error.
+.It Fl I Ar format
+Customize the multi-file format string used to update the status line.
+Ignored when using either
+.Ql Fl D
+or
+.Ql Fl X
+which lack the ability to display the status line
+.Pq containing bytes/rate/thread information .
+Default value
+is
+.Dq Li %'10lli bytes read @ %'9.1f bytes/sec. [%i/%i busy/wait] .
+This format is used when handling more than one file.
+.It Fl i Ar format
+Customize the single-file format string used to update the status line.
+Ignored when using either
+.Ql Fl D
+or
+.Ql Fl X
+which lack the ability to display the status line
+.Pq containing bytes/rate/thread information .
+Default value
+is
+.Dq Li %'10lli bytes read @ %'9.1f bytes/sec. .
+This format is used when handling one file.
+.It Fl k
+Keep tite.
+Prevent visually distracting initialization/exit routines for scripts running
+.Xr dialog 1
+several times.
+.It Fl L Ar size
+Label size.
+If negative, shrink to longest label width.
+.It Fl l
+Line mode.
+Read lines from input instead of bytes.
+.It Fl m
+Multi-input mode.
+Instead of reading bytes from standard input, read from a set of paths
+.Pq one for each label .
+By default, each path is processed sequentially in the order given.
+.It Fl N
+No overrun.
+If enabled, stop reading known-length inputs when input reaches stated length.
+.It Fl n Ar num
+Display at-most
+.Ar num
+progress indicators per screen.
+If zero, display as many as possible.
+If negative, only display the main progress indicator.
+Default is 0.
+Maximum value is 10.
+.It Fl o Ar file
+Output data to
+.Ar file .
+The first occurrence of
+.Ql %s
+.Pq if any
+in
+.Ql Ar file
+will be replaced with the
+.Ar label
+text.
+.It Fl P Ar size
+Mini-progressbar size.
+If negative, don't display mini-progressbars
+.Pq only the large overall progress indicator is shown .
+If zero, auto-adjust based on number of files to read.
+When zero and only one file to read, defaults to -1.
+When zero and more than one file to read, defaults to 17.
+.It Fl p Ar text
+Display
+.Ar text
+above the file progress indicator(s).
+.It Fl T
+Test mode.
+Simulate reading a number of bytes, divided evenly across the number of files,
+while stepping through each percent value of each file to process.
+Appends
+.Dq Li [TEST MODE]
+to the status line
+.Pq to override, use Ql Fl u Ar format .
+No data is actually read.
+.It Fl t Ar title
+Display
+.Ar title
+atop the dialog box.
+Note that if you use this option at the same time as
+.Ql Fl X
+and
+.Ql Fl b Ar backtitle ,
+the
+.Ar backtitle
+and
+.Ar title
+are effectively switched
+.Pq see BUGS section below .
+.It Fl U Ar num
+Update status line
+.Ar num
+times per-second.
+Default value is
+.Ql Li 2 .
+A value of
+.Ql Li 0
+disables status line updates.
+If negative, update the status line as fast as possible.
+Ignored when using either
+.Ql Fl D
+or
+.Ql Fl X
+which lack the ability to display the status line
+.Pq containing bytes/rate/thread information .
+.It Fl w
+Wide mode.
+Allows long
+.Ar text
+arguments used with
+.Ql Fl p
+and
+.Ql Fl a
+to bump the dialog width.
+Prompts wider than the maximum width will wrap
+unless using
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog ;
+see BUGS section below.
+.It Fl X
+Enable X11 mode by using
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog
+instead of
+.Xr dialog 1
+or
+.Xr dialog 3 .
+.It Fl x Ar cmd
+Execute
+.Ar cmd
+.Pq via Xr sh 1
+and send it data that has been read.
+Data is available to
+.Ar cmd
+on standard input.
+With
+.Ql Fl m ,
+.Ar cmd
+is executed once for each
+.Ar path
+argument.
+The first occurrence of
+.Ql %s
+.Pq if any
+in
+.Ql Ar cmd
+will be replaced with the
+.Ar label
+text.
+.El
+.Sh ENVIRONMENT
+The following environment variables are referenced by
+.Nm :
+.Bl -tag -width ".Ev USE_COLOR"
+.It Ev DIALOG
+Override command string used to launch
+.Xr dialog 1
+.Pq requires Ql Fl D
+or
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog
+.Pq requires Ql Fl X ;
+default is either
+.Ql dialog
+.Pq for Ql Fl D
+or
+.Ql Xdialog
+.Pq for Ql Fl X .
+.It Ev DIALOGRC
+If set and non-NULL, path to
+.Ql .dialogrc
+file.
+.It Ev HOME
+If
+.Ql Ev $DIALOGRC
+is either not set or NULL, used as a prefix to
+.Ql .dialogrc
+.Pq i.e., Ql $HOME/.dialogrc .
+.It Ev USE_COLOR
+If set and NULL, disables the use of color when using
+.Xr dialog 1 .
+Does not apply to
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog .
+.El
+.Sh DEPENDENCIES
+If using
+.Ql Fl D ,
+.Xr dialog 1
+is required.
+.Pp
+If using
+.Ql Fl X ,
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog
+is required.
+.Sh FILES
+.Bl -tag -width "$HOME/.dialogrc" -compact
+.It Pa $HOME/.dialogrc
+.El
+.Sh EXAMPLES
+Simple example to show how fast
+.Xr yes 1
+produces lines
+.Pq usually about ten-million per-second; your results may vary :
+.Bd -literal -offset indent
+yes | dpv -l yes
+.Ed
+.Pp
+Display progress while timing how long it takes
+.Xr yes 1
+to produce a half-billion lines
+.Pq usually under one minute; your results may vary :
+.Bd -literal -offset indent
+time yes | dpv -Nl 500000000:yes
+.Ed
+.Pp
+An example to watch how quickly a file is transferred using
+.Xr nc 1 :
+.Bd -literal -offset indent
+dpv -x "nc -w 1 somewhere.com 3000" -m label file
+.Ed
+.Pp
+A similar example, transferring a file from another process and passing the
+expected size to
+.Nm :
+.Bd -literal -offset indent
+cat file | dpv -x "nc -w 1 somewhere.com 3000" 12345:label
+.Ed
+.Pp
+A more complicated example:
+.Bd -literal -offset indent
+tar cf - . | dpv -x "gzip -9 > out.tgz" \\
+ $( du -s . | awk '{print $1 * 1024}' ):label
+.Ed
+.Pp
+Taking an image of a disk:
+.Bd -literal -offset indent
+dpv -o disk-image.img -m label /dev/ada0
+.Ed
+.Pp
+Writing an image back to a disk:
+.Bd -literal -offset indent
+dpv -o /dev/ada0 -m label disk-image.img
+.Ed
+.Pp
+Zeroing a disk:
+.Bd -literal -offset indent
+dpv -o /dev/md42 "Zeroing md42" < /dev/zero
+.Ed
+.Sh SEE ALSO
+.Xr dialog 1 ,
+.Xr sh 1 ,
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog ,
+.Xr dialog 3
+.Sh HISTORY
+A
+.Nm
+utility first appeared in
+.Fx 10.2 .
+.Sh AUTHORS
+.An Devin Teske Aq dteske@FreeBSD.org
+.Sh BUGS
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog ,
+when given both
+.Ql Fl -title Ar title
+.Pq see above Ql Fl t Ar title
+and
+.Ql Fl -backtitle Ar backtitle
+.Pq see above Ql Fl b Ar backtitle ,
+displays the backtitle in place of the title and vice-versa.
+.Pp
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog
+does not wrap long prompt texts received after initial launch.
+This is a known issue with the
+.Ql --gauge
+widget in
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog .
+.Pp
+.Xr dialog 1
+does not display the first character after a series of escaped escape-sequences
+(e.g., ``\\\\n'' produces ``\\'' instead of ``\\n'').
+This is a known issue with
+.Xr dialog 1
+and does not affect
+.Xr dialog 3
+or
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog .
+.Pp
+If your application ignores
+.Ev USE_COLOR
+when set and NULL before calling
+.Xr dpv 1
+with color escape sequences anyway,
+.Xr dialog 3
+and
+.Xr dialog 1
+may not render properly.
+Workaround is to detect when
+.Ev USE_COLOR
+is set and NULL and either not use color escape sequences at that time or use
+.Xr unset 1
+.Xr [ sh 1 ]
+or
+.Xr unsetenv 1
+.Xr [ csh 1 ]
+to unset
+.Ev USE_COLOR ,
+forcing interpretation of color sequences.
+This does not effect
+.Xr Xdialog 1 Pq Pa ports/x11/xdialog ,
+which renders the color escape sequences as plain text.
+See
+.Do
+embedded "\\Z" sequences
+.Dc
+in
+.Xr dialog 1
+for additional information.
diff --git a/usr.bin/dpv/dpv.c b/usr.bin/dpv/dpv.c
new file mode 100644
index 000000000000..1fd89eca77c8
--- /dev/null
+++ b/usr.bin/dpv/dpv.c
@@ -0,0 +1,543 @@
+/*-
+ * Copyright (c) 2013-2016 Devin Teske <dteske@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define _BSD_SOURCE /* to get dprintf() prototype in stdio.h below */
+#include <dialog.h>
+#include <dpv.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_m.h>
+#include <unistd.h>
+
+#include "dpv_util.h"
+
+/* Debugging */
+static uint8_t debug = FALSE;
+
+/* Data to process */
+static struct dpv_file_node *file_list = NULL;
+static unsigned int nfiles = 0;
+
+/* Data processing */
+static uint8_t line_mode = FALSE;
+static uint8_t no_overrun = FALSE;
+static char *buf = NULL;
+static int fd = -1;
+static int output_type = DPV_OUTPUT_NONE;
+static size_t bsize;
+static char rpath[PATH_MAX];
+
+/* Extra display information */
+static uint8_t multiple = FALSE; /* `-m' */
+static char *pgm; /* set to argv[0] by main() */
+
+/* Function prototypes */
+static void sig_int(int sig);
+static void usage(void);
+int main(int argc, char *argv[]);
+static int operate_common(struct dpv_file_node *file, int out);
+static int operate_on_bytes(struct dpv_file_node *file, int out);
+static int operate_on_lines(struct dpv_file_node *file, int out);
+
+static int
+operate_common(struct dpv_file_node *file, int out)
+{
+ struct stat sb;
+
+ /* Open the file if necessary */
+ if (fd < 0) {
+ if (multiple) {
+ /* Resolve the file path and attempt to open it */
+ if (realpath(file->path, rpath) == 0 ||
+ (fd = open(rpath, O_RDONLY)) < 0) {
+ warn("%s", file->path);
+ file->status = DPV_STATUS_FAILED;
+ return (-1);
+ }
+ } else {
+ /* Assume stdin, but if that's a TTY instead use the
+ * highest numbered file descriptor (obtained by
+ * generating new fd and then decrementing).
+ *
+ * NB: /dev/stdin should always be open(2)'able
+ */
+ fd = STDIN_FILENO;
+ if (isatty(fd)) {
+ fd = open("/dev/stdin", O_RDONLY);
+ close(fd--);
+ }
+
+ /* This answer might be wrong, if dpv(3) has (by
+ * request) opened an output file or pipe. If we
+ * told dpv(3) to open a file, subtract one from
+ * previous answer. If instead we told dpv(3) to
+ * prepare a pipe output, subtract two.
+ */
+ switch(output_type) {
+ case DPV_OUTPUT_FILE:
+ fd -= 1;
+ break;
+ case DPV_OUTPUT_SHELL:
+ fd -= 2;
+ break;
+ }
+ }
+ }
+
+ /* Allocate buffer if necessary */
+ if (buf == NULL) {
+ /* Use output block size as buffer size if available */
+ if (out >= 0) {
+ if (fstat(out, &sb) != 0) {
+ warn("%i", out);
+ file->status = DPV_STATUS_FAILED;
+ return (-1);
+ }
+ if (S_ISREG(sb.st_mode)) {
+ if (sysconf(_SC_PHYS_PAGES) >
+ PHYSPAGES_THRESHOLD)
+ bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+ else
+ bsize = BUFSIZE_SMALL;
+ } else
+ bsize = MAX(sb.st_blksize,
+ (blksize_t)sysconf(_SC_PAGESIZE));
+ } else
+ bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+
+ /* Attempt to allocate */
+ if ((buf = malloc(bsize+1)) == NULL) {
+ end_dialog();
+ err(EXIT_FAILURE, "Out of memory?!");
+ }
+ }
+
+ return (0);
+}
+
+static int
+operate_on_bytes(struct dpv_file_node *file, int out)
+{
+ int progress;
+ ssize_t r, w;
+
+ if (operate_common(file, out) < 0)
+ return (-1);
+
+ /* [Re-]Fill the buffer */
+ if ((r = read(fd, buf, bsize)) <= 0) {
+ if (fd != STDIN_FILENO)
+ close(fd);
+ fd = -1;
+ file->status = DPV_STATUS_DONE;
+ return (100);
+ }
+
+ /* [Re-]Dump the buffer */
+ if (out >= 0) {
+ if ((w = write(out, buf, r)) < 0) {
+ end_dialog();
+ err(EXIT_FAILURE, "output");
+ }
+ fsync(out);
+ }
+
+ dpv_overall_read += r;
+ file->read += r;
+
+ /* Calculate percentage of completion (if possible) */
+ if (file->length >= 0) {
+ progress = (file->read * 100 / (file->length > 0 ?
+ file->length : 1));
+
+ /* If no_overrun, do not return 100% until read >= length */
+ if (no_overrun && progress == 100 && file->read < file->length)
+ progress--;
+
+ return (progress);
+ } else
+ return (-1);
+}
+
+static int
+operate_on_lines(struct dpv_file_node *file, int out)
+{
+ char *p;
+ int progress;
+ ssize_t r, w;
+
+ if (operate_common(file, out) < 0)
+ return (-1);
+
+ /* [Re-]Fill the buffer */
+ if ((r = read(fd, buf, bsize)) <= 0) {
+ if (fd != STDIN_FILENO)
+ close(fd);
+ fd = -1;
+ file->status = DPV_STATUS_DONE;
+ return (100);
+ }
+ buf[r] = '\0';
+
+ /* [Re-]Dump the buffer */
+ if (out >= 0) {
+ if ((w = write(out, buf, r)) < 0) {
+ end_dialog();
+ err(EXIT_FAILURE, "output");
+ }
+ fsync(out);
+ }
+
+ /* Process the buffer for number of lines */
+ for (p = buf; p != NULL && *p != '\0';)
+ if ((p = strchr(p, '\n')) != NULL)
+ dpv_overall_read++, p++, file->read++;
+
+ /* Calculate percentage of completion (if possible) */
+ if (file->length >= 0) {
+ progress = (file->read * 100 / file->length);
+
+ /* If no_overrun, do not return 100% until read >= length */
+ if (no_overrun && progress == 100 && file->read < file->length)
+ progress--;
+
+ return (progress);
+ } else
+ return (-1);
+}
+
+/*
+ * Takes a list of names that are to correspond to input streams coming from
+ * stdin or fifos and produces necessary config to drive dpv(3) `--gauge'
+ * widget. If the `-d' flag is used, output is instead send to terminal
+ * standard output (and the output can then be saved to a file, piped into
+ * custom [X]dialog(1) invocation, or whatever.
+ */
+int
+main(int argc, char *argv[])
+{
+ char dummy;
+ int ch;
+ int n = 0;
+ size_t config_size = sizeof(struct dpv_config);
+ size_t file_node_size = sizeof(struct dpv_file_node);
+ struct dpv_config *config;
+ struct dpv_file_node *curfile;
+ struct sigaction act;
+
+ pgm = argv[0]; /* store a copy of invocation name */
+
+ /* Allocate config structure */
+ if ((config = malloc(config_size)) == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ memset((void *)(config), '\0', config_size);
+
+ /*
+ * Process command-line options
+ */
+ while ((ch = getopt(argc, argv,
+ "a:b:dDhi:I:klL:mn:No:p:P:t:TU:wx:X")) != -1) {
+ switch(ch) {
+ case 'a': /* additional message text to append */
+ if (config->aprompt == NULL) {
+ config->aprompt = malloc(DPV_APROMPT_MAX);
+ if (config->aprompt == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ }
+ snprintf(config->aprompt, DPV_APROMPT_MAX, "%s",
+ optarg);
+ break;
+ case 'b': /* [X]dialog(1) backtitle */
+ if (config->backtitle != NULL)
+ free((char *)config->backtitle);
+ config->backtitle = malloc(strlen(optarg) + 1);
+ if (config->backtitle == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ *(config->backtitle) = '\0';
+ strcat(config->backtitle, optarg);
+ break;
+ case 'd': /* debugging */
+ debug = TRUE;
+ config->debug = debug;
+ break;
+ case 'D': /* use dialog(1) instead of libdialog */
+ config->display_type = DPV_DISPLAY_DIALOG;
+ break;
+ case 'h': /* help/usage */
+ usage();
+ break; /* NOTREACHED */
+ case 'i': /* status line format string for single-file */
+ config->status_solo = optarg;
+ break;
+ case 'I': /* status line format string for many-files */
+ config->status_many = optarg;
+ break;
+ case 'k': /* keep tite */
+ config->keep_tite = TRUE;
+ break;
+ case 'l': /* Line mode */
+ line_mode = TRUE;
+ break;
+ case 'L': /* custom label size */
+ config->label_size =
+ (int)strtol(optarg, (char **)NULL, 10);
+ if (config->label_size == 0 && errno == EINVAL)
+ errx(EXIT_FAILURE,
+ "`-L' argument must be numeric");
+ else if (config->label_size < -1)
+ config->label_size = -1;
+ break;
+ case 'm': /* enable multiple file arguments */
+ multiple = TRUE;
+ break;
+ case 'o': /* `-o path' for sending data-read to file */
+ output_type = DPV_OUTPUT_FILE;
+ config->output_type = DPV_OUTPUT_FILE;
+ config->output = optarg;
+ break;
+ case 'n': /* custom number of files per `page' */
+ config->display_limit =
+ (int)strtol(optarg, (char **)NULL, 10);
+ if (config->display_limit == 0 && errno == EINVAL)
+ errx(EXIT_FAILURE,
+ "`-n' argument must be numeric");
+ else if (config->display_limit < 0)
+ config->display_limit = -1;
+ break;
+ case 'N': /* No overrun (truncate reads of known-length) */
+ no_overrun = TRUE;
+ config->options |= DPV_NO_OVERRUN;
+ break;
+ case 'p': /* additional message text to use as prefix */
+ if (config->pprompt == NULL) {
+ config->pprompt = malloc(DPV_PPROMPT_MAX + 2);
+ if (config->pprompt == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ /* +2 is for implicit "\n" appended later */
+ }
+ snprintf(config->pprompt, DPV_PPROMPT_MAX, "%s",
+ optarg);
+ break;
+ case 'P': /* custom size for mini-progressbar */
+ config->pbar_size =
+ (int)strtol(optarg, (char **)NULL, 10);
+ if (config->pbar_size == 0 && errno == EINVAL)
+ errx(EXIT_FAILURE,
+ "`-P' argument must be numeric");
+ else if (config->pbar_size < -1)
+ config->pbar_size = -1;
+ break;
+ case 't': /* [X]dialog(1) title */
+ if (config->title != NULL)
+ free(config->title);
+ config->title = malloc(strlen(optarg) + 1);
+ if (config->title == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ *(config->title) = '\0';
+ strcat(config->title, optarg);
+ break;
+ case 'T': /* test mode (don't read data, fake it) */
+ config->options |= DPV_TEST_MODE;
+ break;
+ case 'U': /* updates per second */
+ config->status_updates_per_second =
+ (int)strtol(optarg, (char **)NULL, 10);
+ if (config->status_updates_per_second == 0 &&
+ errno == EINVAL)
+ errx(EXIT_FAILURE,
+ "`-U' argument must be numeric");
+ break;
+ case 'w': /* `-p' and `-a' widths bump [X]dialog(1) width */
+ config->options |= DPV_WIDE_MODE;
+ break;
+ case 'x': /* `-x cmd' for sending data-read to sh(1) code */
+ output_type = DPV_OUTPUT_SHELL;
+ config->output_type = DPV_OUTPUT_SHELL;
+ config->output = optarg;
+ break;
+ case 'X': /* X11 support through x11/xdialog */
+ config->display_type = DPV_DISPLAY_XDIALOG;
+ break;
+ case '?': /* unknown argument (based on optstring) */
+ /* FALLTHROUGH */
+ default: /* unhandled argument (based on switch) */
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Process remaining arguments as list of names to display */
+ for (curfile = file_list; n < argc; n++) {
+ nfiles++;
+
+ /* Allocate a new struct for the file argument */
+ if (curfile == NULL) {
+ if ((curfile = malloc(file_node_size)) == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ memset((void *)(curfile), '\0', file_node_size);
+ file_list = curfile;
+ } else {
+ if ((curfile->next = malloc(file_node_size)) == NULL)
+ errx(EXIT_FAILURE, "Out of memory?!");
+ memset((void *)(curfile->next), '\0', file_node_size);
+ curfile = curfile->next;
+ }
+ curfile->name = argv[n];
+
+ /* Read possible `lines:' prefix from label syntax */
+ if (sscanf(curfile->name, "%lli:%c", &(curfile->length),
+ &dummy) == 2)
+ curfile->name = strchr(curfile->name, ':') + 1;
+ else
+ curfile->length = -1;
+
+ /* Read path argument if enabled */
+ if (multiple) {
+ if (++n >= argc)
+ errx(EXIT_FAILURE, "Missing path argument "
+ "for label number %i", nfiles);
+ curfile->path = argv[n];
+ } else
+ break;
+ }
+
+ /* Display usage and exit if not given at least one name */
+ if (nfiles == 0) {
+ warnx("no labels provided");
+ usage();
+ /* NOTREACHED */
+ }
+
+ /*
+ * Set cleanup routine for Ctrl-C action
+ */
+ if (config->display_type == DPV_DISPLAY_LIBDIALOG) {
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, 0);
+ }
+
+ /* Set status formats and action */
+ if (line_mode) {
+ config->status_solo = LINE_STATUS_SOLO;
+ config->status_many = LINE_STATUS_SOLO;
+ config->action = operate_on_lines;
+ } else {
+ config->status_solo = BYTE_STATUS_SOLO;
+ config->status_many = BYTE_STATUS_SOLO;
+ config->action = operate_on_bytes;
+ }
+
+ /*
+ * Hand off to dpv(3)...
+ */
+ if (dpv(config, file_list) != 0 && debug)
+ warnx("dpv(3) returned error!?");
+
+ if (!config->keep_tite)
+ end_dialog();
+ dpv_free();
+
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * Interrupt handler to indicate we received a Ctrl-C interrupt.
+ */
+static void
+sig_int(int sig __unused)
+{
+ dpv_interrupt = TRUE;
+}
+
+/*
+ * Print short usage statement to stderr and exit with error status.
+ */
+static void
+usage(void)
+{
+
+ if (debug) /* No need for usage */
+ exit(EXIT_FAILURE);
+
+ fprintf(stderr, "Usage: %s [options] [bytes:]label\n", pgm);
+ fprintf(stderr, " %s [options] -m [bytes1:]label1 path1 "
+ "[[bytes2:]label2 path2 ...]\n", pgm);
+ fprintf(stderr, "OPTIONS:\n");
+#define OPTFMT "\t%-14s %s\n"
+ fprintf(stderr, OPTFMT, "-a text",
+ "Append text. Displayed below file progress indicators.");
+ fprintf(stderr, OPTFMT, "-b backtitle",
+ "String to be displayed on the backdrop, at top-left.");
+ fprintf(stderr, OPTFMT, "-D",
+ "Use dialog(1) instead of dialog(3) [default].");
+ fprintf(stderr, OPTFMT, "-d",
+ "Debug. Write to standard output instead of dialog.");
+ fprintf(stderr, OPTFMT, "-h",
+ "Produce this output on standard error and exit.");
+ fprintf(stderr, OPTFMT, "-I format",
+ "Customize status line format. See fdpv(1) for details.");
+ fprintf(stderr, OPTFMT, "-i format",
+ "Customize status line format. See fdpv(1) for details.");
+ fprintf(stderr, OPTFMT, "-L size",
+ "Label size. Must be a number greater than 0, or -1.");
+ fprintf(stderr, OPTFMT, "-m",
+ "Enable processing of multiple file argiments.");
+ fprintf(stderr, OPTFMT, "-N",
+ "No overrun. Stop reading input at stated length, if any.");
+ fprintf(stderr, OPTFMT, "-n num",
+ "Display at-most num files per screen. Default is -1.");
+ fprintf(stderr, OPTFMT, "-o file",
+ "Output data to file. First %s replaced with label text.");
+ fprintf(stderr, OPTFMT, "-P size",
+ "Mini-progressbar size. Must be a number greater than 3.");
+ fprintf(stderr, OPTFMT, "-p text",
+ "Prefix text. Displayed above file progress indicators.");
+ fprintf(stderr, OPTFMT, "-T",
+ "Test mode. Don't actually read any data, but fake it.");
+ fprintf(stderr, OPTFMT, "-t title",
+ "Title string to be displayed at top of dialog(1) box.");
+ fprintf(stderr, OPTFMT, "-U num",
+ "Update status line num times per-second. Default is 2.");
+ fprintf(stderr, OPTFMT, "-w",
+ "Wide. Width of `-p' and `-a' text bump dialog(1) width.");
+ fprintf(stderr, OPTFMT, "-X",
+ "X11. Use Xdialog(1) instead of dialog(1).");
+ fprintf(stderr, OPTFMT, "-x cmd",
+ "Send data to executed cmd. First %s replaced with label.");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/dpv/dpv_util.h b/usr.bin/dpv/dpv_util.h
new file mode 100644
index 000000000000..98f7a55ced67
--- /dev/null
+++ b/usr.bin/dpv/dpv_util.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2013-2014 Devin Teske <dteske@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _DPV_UTIL_H_
+#define _DPV_UTIL_H_
+
+/* Limits */
+#define BUFSIZE_MAX (2 * 1024 * 1024)
+ /* Buffer size for read(2) input */
+#ifndef MAXPHYS
+#define MAXPHYS (128 * 1024)
+ /* max raw I/O transfer size */
+#endif
+
+/*
+ * Memory strategry threshold, in pages: if physmem is larger than this,
+ * use a large buffer.
+ */
+#define PHYSPAGES_THRESHOLD (32 * 1024)
+
+/*
+ * Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS.
+ */
+#define BUFSIZE_SMALL (MAXPHYS)
+
+/*
+ * Math macros
+ */
+#undef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#undef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+/*
+ * Extra display information
+ */
+#define BYTE_STATUS_SOLO "%'10lli bytes read @ %'9.1f bytes/sec."
+#define BYTE_STATUS_MANY (BYTE_STATUS_SOLO " [%i/%i busy/wait]")
+#define LINE_STATUS_SOLO "%'10lli lines read @ %'9.1f lines/sec."
+#define LINE_STATUS_MANY (LINE_STATUS_SOLO " [%i/%i busy/wait]")
+
+#endif /* !_DPV_UTIL_H_ */
diff --git a/usr.bin/drill/Makefile b/usr.bin/drill/Makefile
new file mode 100644
index 000000000000..0b321765c054
--- /dev/null
+++ b/usr.bin/drill/Makefile
@@ -0,0 +1,15 @@
+# Vendor sources and generated files
+LDNSDIR= ${SRCTOP}/contrib/ldns
+
+.PATH: ${LDNSDIR}/drill
+
+PROG= drill
+SRCS= drill.c drill_util.c error.c root.c work.c \
+ chasetrace.c dnssec.c securetrace.c
+CFLAGS+= -I${LDNSDIR} -I${LDNSDIR}/ldns
+CFLAGS+= -DLDNS_TRUST_ANCHOR_FILE='"/etc/unbound/root.key"'
+MAN= drill.1
+
+LIBADD= ldns crypto
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/drill/Makefile.depend b/usr.bin/drill/Makefile.depend
new file mode 100644
index 000000000000..31cfaba97873
--- /dev/null
+++ b/usr.bin/drill/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libldns \
+ secure/lib/libcrypto \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dtc/HACKING b/usr.bin/dtc/HACKING
new file mode 100644
index 000000000000..ef858c8885c0
--- /dev/null
+++ b/usr.bin/dtc/HACKING
@@ -0,0 +1,61 @@
+Notes for people hacking on dtc
+===============================
+
+This file contains some notes for people wishing to hack on dtc.
+
+Upstreaming
+-----------
+
+This code is developed in the git repository:
+
+https://github.com/davidchisnall/dtc
+
+If you got the source from anywhere else and wish to make changes, please
+ensure that you are working against the latest version, or you may end up
+fixing bugs that are already fixed upstream. Although the license makes no
+requirement that you share any improvements that you make, patches are very
+welcome.
+
+C++11
+-----
+
+This project uses C++11, as the goal for FreeBSD 11 is to require C/C++11 as a
+minimum, either from clang or an external toolchain. In particular, it uses
+`std::unique_ptr` extensively for memory management within the tree. Unique
+pointers are also used in several other places to track ownership.
+
+Most iterator loops use the new loop syntax and the `auto` type for type
+deduction. Range-based `for` loops generally improve the readability of the
+code, though `auto` should only be used in places where the type can be deduced
+as easily by the reader as by the compiler.
+
+The code also makes use of `static_assert()` to track compile-time invariants.
+
+Adding New Checks
+-----------------
+
+Currently, the biggest weakness of this version of the tool is that it lacks
+most of the semantic checkers that can be implemented by simply reading the
+ePAPR spec. The `checker` class provides a simple superclass for implementing
+these quite easily. There are also helper methods on `device_tree` for finding
+specific nodes, for checks that require some understanding of the structure of
+the tree.
+
+We should probably add a parent pointer to the `node` class for easily walking
+up the tree.
+
+Adding Direct C Output
+----------------------
+
+The FreeBSD build system currently uses dtc to generate a blob and then
+converts this to C source code. A new `output_writer` subclass could easily
+generate the C directly.
+
+Parser Improvements
+-------------------
+
+There are a few FIXME lines in the parser for some corner cases that are not
+currently used by FreeBSD. These are mainly related to labels in the middle of
+values. These can be fixed by creating a new `property_value` with the
+specified label, starting at the location of the label. Don't forget to remove
+the associated comments from the BUGS section of the man page if you fix this.
diff --git a/usr.bin/dtc/Makefile b/usr.bin/dtc/Makefile
new file mode 100644
index 000000000000..9b1aff13511f
--- /dev/null
+++ b/usr.bin/dtc/Makefile
@@ -0,0 +1,13 @@
+PROG_CXX=dtc
+SRCS= dtc.cc input_buffer.cc string.cc dtb.cc fdt.cc checking.cc
+MAN= dtc.1
+
+WARNS?= 3
+
+CXXFLAGS+= -fno-rtti -fno-exceptions
+
+CXXSTD= c++17
+
+NO_SHARED?=NO
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/dtc/Makefile.depend b/usr.bin/dtc/Makefile.depend
new file mode 100644
index 000000000000..76a8d2cdc8ca
--- /dev/null
+++ b/usr.bin/dtc/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/dtc/checking.cc b/usr.bin/dtc/checking.cc
new file mode 100644
index 000000000000..8c44fa181489
--- /dev/null
+++ b/usr.bin/dtc/checking.cc
@@ -0,0 +1,285 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "checking.hh"
+#include <stdio.h>
+
+using std::string;
+
+namespace dtc
+{
+namespace fdt
+{
+namespace checking
+{
+
+namespace
+{
+ struct deleted_node_checker : public checker
+ {
+ deleted_node_checker(const char *name) : checker(name) {}
+ virtual bool check_node(device_tree *, const node_ptr &n)
+ {
+ auto &deleted = n->deleted_child_nodes();
+ if (deleted.empty())
+ {
+ return true;
+ }
+ bool plural = deleted.size() > 1;
+ string errmsg("Attempts to delete ");
+ errmsg += plural ? "nodes" : "node";
+ errmsg += " that ";
+ errmsg += plural ? "were" : "was";
+ errmsg += " not added in merge: ";
+ for (auto &d : deleted)
+ {
+ errmsg += d;
+ }
+ report_error(errmsg.c_str());
+ return false;
+ }
+ };
+ /**
+ * Checker that verifies that every node that has children has
+ * #address-cells and #size-cells properties.
+ */
+ struct address_cells_checker : public checker
+ {
+ address_cells_checker(const char *name) : checker(name) {}
+ virtual bool check_node(device_tree *, const node_ptr &n)
+ {
+ // If this has no children, it trivially meets the
+ // conditions.
+ if (n->child_begin() == n->child_end())
+ {
+ return true;
+ }
+ bool found_address = false;
+ bool found_size = false;
+ for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
+ {
+ if (!found_address)
+ {
+ found_address = ((*i)->get_key() == "#address-cells");
+ }
+ if (!found_size)
+ {
+ found_size = ((*i)->get_key() == "#size-cells");
+ }
+ if (found_size && found_address)
+ {
+ break;
+ }
+ }
+ if (!found_address)
+ {
+ report_error("Missing #address-cells property");
+ }
+ if (!found_size)
+ {
+ report_error("Missing #size-cells property");
+ }
+ return found_address && found_size;
+ }
+ };
+} // anonymous namespace
+
+bool
+checker::visit_node(device_tree *tree, const node_ptr &n)
+{
+ path.push_back(std::make_pair(n->name, n->unit_address));
+ // Check this node
+ if (!check_node(tree, n))
+ {
+ return false;
+ }
+ // Now check its properties
+ for (auto i=n->property_begin(), e=n->property_end() ; i!=e ; ++i)
+ {
+ if (!check_property(tree, n, *i))
+ {
+ return false;
+ }
+ }
+ // And then recursively check the children
+ for (node::child_iterator i=n->child_begin(), e=n->child_end() ; i!=e ;
+ ++i)
+ {
+ if (!visit_node(tree, *i))
+ {
+ return false;
+ }
+ }
+ path.pop_back();
+ return true;
+}
+
+void
+checker::report_error(const char *errmsg)
+{
+ fprintf(stderr, "Error: %s, while checking node: ", errmsg);
+ for (auto &p : path)
+ {
+ putc('/', stderr);
+ puts(p.first.c_str());
+ if (!(p.second.empty()))
+ {
+ putc('@', stderr);
+ puts(p.second.c_str());
+ }
+ }
+ fprintf(stderr, " [-W%s]\n", checker_name);
+}
+
+bool
+property_checker::check_property(device_tree *tree, const node_ptr &n, property_ptr p)
+{
+ if (p->get_key() == key)
+ {
+ if (!check(tree, n, p))
+ {
+ report_error("property check failed");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+property_size_checker::check(device_tree *, const node_ptr &, property_ptr p)
+{
+ uint32_t psize = 0;
+ for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ; ++i)
+ {
+ if (!i->is_binary())
+ {
+ return false;
+ }
+ psize += i->byte_data.size();
+ }
+ return psize == size;
+}
+
+template<property_value::value_type T>
+void
+check_manager::add_property_type_checker(const char *name, const string &prop)
+{
+ checkers.insert(std::make_pair(string(name),
+ new property_type_checker<T>(name, prop)));
+}
+
+void
+check_manager::add_property_size_checker(const char *name,
+ const string &prop,
+ uint32_t size)
+{
+ checkers.insert(std::make_pair(string(name),
+ new property_size_checker(name, prop, size)));
+}
+
+check_manager::~check_manager()
+{
+ while (checkers.begin() != checkers.end())
+ {
+ delete checkers.begin()->second;
+ checkers.erase(checkers.begin());
+ }
+ while (disabled_checkers.begin() != disabled_checkers.end())
+ {
+ delete disabled_checkers.begin()->second;
+ disabled_checkers.erase(disabled_checkers.begin());
+ }
+}
+
+check_manager::check_manager()
+{
+ // NOTE: All checks listed here MUST have a corresponding line
+ // in the man page!
+ add_property_type_checker<property_value::STRING_LIST>(
+ "type-compatible", string("compatible"));
+ add_property_type_checker<property_value::STRING>(
+ "type-model", string("model"));
+ add_property_size_checker("type-phandle", string("phandle"), 4);
+ disabled_checkers.insert(std::make_pair(string("cells-attributes"),
+ new address_cells_checker("cells-attributes")));
+ checkers.insert(std::make_pair(string("deleted-nodes"),
+ new deleted_node_checker("deleted-nodes")));
+}
+
+bool
+check_manager::run_checks(device_tree *tree, bool keep_going)
+{
+ bool success = true;
+ for (auto &i : checkers)
+ {
+ success &= i.second->check_tree(tree);
+ if (!(success || keep_going))
+ {
+ break;
+ }
+ }
+ return success;
+}
+
+bool
+check_manager::disable_checker(const string &name)
+{
+ auto checker = checkers.find(name);
+ if (checker != checkers.end())
+ {
+ disabled_checkers.insert(std::make_pair(name,
+ checker->second));
+ checkers.erase(checker);
+ return true;
+ }
+ return false;
+}
+
+bool
+check_manager::enable_checker(const string &name)
+{
+ auto checker = disabled_checkers.find(name);
+ if (checker != disabled_checkers.end())
+ {
+ checkers.insert(std::make_pair(name, checker->second));
+ disabled_checkers.erase(checker);
+ return true;
+ }
+ return false;
+}
+
+} // namespace checking
+
+} // namespace fdt
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/checking.hh b/usr.bin/dtc/checking.hh
new file mode 100644
index 000000000000..c65450fac424
--- /dev/null
+++ b/usr.bin/dtc/checking.hh
@@ -0,0 +1,310 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _CHECKING_HH_
+#define _CHECKING_HH_
+#include <string>
+#include "fdt.hh"
+
+namespace dtc
+{
+namespace fdt
+{
+namespace checking
+{
+/**
+ * Base class for all checkers. This will visit the entire tree and perform
+ * semantic checks defined in subclasses. Note that device trees are generally
+ * small (a few dozen nodes at most) and so we optimise for flexibility and
+ * extensibility here, not for performance. Each checker will visit the entire
+ * tree.
+ */
+class checker
+{
+ /**
+ * The path to the current node being checked. This is used for
+ * printing error messages.
+ */
+ device_tree::node_path path;
+ /**
+ * The name of the checker. This is used for printing error messages
+ * and for enabling / disabling specific checkers from the command
+ * line.
+ */
+ const char *checker_name;
+ /**
+ * Visits each node, calling the checker functions on properties and
+ * nodes.
+ */
+ bool visit_node(device_tree *tree, const node_ptr &n);
+ protected:
+ /**
+ * Prints the error message, along with the path to the node that
+ * caused the error and the name of the checker.
+ */
+ void report_error(const char *errmsg);
+ public:
+ /**
+ * Constructor. Takes the name of this checker, which is which is used
+ * when reporting errors.
+ */
+ checker(const char *name) : checker_name(name) {}
+ /**
+ * Virtual destructor in case any subclasses need to do cleanup.
+ */
+ virtual ~checker() {}
+ /**
+ * Method for checking that a node is valid. The root class version
+ * does nothing, subclasses should override this.
+ */
+ virtual bool check_node(device_tree *, const node_ptr &)
+ {
+ return true;
+ }
+ /**
+ * Method for checking that a property is valid. The root class
+ * version does nothing, subclasses should override this.
+ */
+ virtual bool check_property(device_tree *, const node_ptr &, property_ptr )
+ {
+ return true;
+ }
+ /**
+ * Runs the checker on the specified device tree.
+ */
+ bool check_tree(fdt::device_tree *tree)
+ {
+ return visit_node(tree, tree->get_root());
+ }
+};
+
+/**
+ * Abstract base class for simple property checks. This class defines a check
+ * method for subclasses, which is invoked only when it finds a property with
+ * the matching name. To define simple property checkers, just subclass this
+ * and override the check() method.
+ */
+class property_checker : public checker
+{
+ /**
+ * The name of the property that this checker is looking for.
+ */
+ std::string key;
+ public:
+ /**
+ * Implementation of the generic property-checking method that checks
+ * for a property with the name specified in the constructor.
+ */
+ virtual bool check_property(device_tree *tree, const node_ptr &n, property_ptr p);
+ /**
+ * Constructor. Takes the name of the checker and the name of the
+ * property to check.
+ */
+ property_checker(const char* name, const std::string &property_name)
+ : checker(name), key(property_name) {}
+ /**
+ * The check method, which subclasses should implement.
+ */
+ virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0;
+};
+
+/**
+ * Property type checker.
+ */
+template<property_value::value_type T>
+struct property_type_checker : public property_checker
+{
+ /**
+ * Constructor, takes the name of the checker and the name of the
+ * property to check as arguments.
+ */
+ property_type_checker(const char* name, const std::string &property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p) = 0;
+};
+
+/**
+ * Empty property checker. This checks that the property has no value.
+ */
+template<>
+struct property_type_checker <property_value::EMPTY> : public property_checker
+{
+ property_type_checker(const char* name, const std::string &property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *, const node_ptr &, property_ptr p)
+ {
+ return p->begin() == p->end();
+ }
+};
+
+/**
+ * String property checker. This checks that the property has exactly one
+ * value, which is a string.
+ */
+template<>
+struct property_type_checker <property_value::STRING> : public property_checker
+{
+ property_type_checker(const char* name, const std::string &property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *, const node_ptr &, property_ptr p)
+ {
+ return (p->begin() + 1 == p->end()) && p->begin()->is_string();
+ }
+};
+/**
+ * String list property checker. This checks that the property has at least
+ * one value, all of which are strings.
+ */
+template<>
+struct property_type_checker <property_value::STRING_LIST> :
+ public property_checker
+{
+ property_type_checker(const char* name, const std::string &property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *, const node_ptr &, property_ptr p)
+ {
+ for (property::value_iterator i=p->begin(),e=p->end() ; i!=e ;
+ ++i)
+ {
+ if (!(i->is_string() || i->is_string_list()))
+ {
+ return false;
+ }
+ }
+ return p->begin() != p->end();
+ }
+};
+
+/**
+ * Phandle property checker. This checks that the property has exactly one
+ * value, which is a valid phandle.
+ */
+template<>
+struct property_type_checker <property_value::PHANDLE> : public property_checker
+{
+ property_type_checker(const char* name, const std::string &property_name) :
+ property_checker(name, property_name) {}
+ virtual bool check(device_tree *tree, const node_ptr &, property_ptr p)
+ {
+ return (p->begin() + 1 == p->end()) &&
+ (tree->referenced_node(*p->begin()) != 0);
+ }
+};
+
+/**
+ * Check that a property has the correct size.
+ */
+struct property_size_checker : public property_checker
+{
+ /**
+ * The expected size of the property.
+ */
+ uint32_t size;
+ public:
+ /**
+ * Constructor, takes the name of the checker, the name of the property
+ * to check, and its expected size as arguments.
+ */
+ property_size_checker(const char* name,
+ const std::string &property_name,
+ uint32_t bytes)
+ : property_checker(name, property_name), size(bytes) {}
+ /**
+ * Check, validates that the property has the correct size.
+ */
+ virtual bool check(device_tree *tree, const node_ptr &n, property_ptr p);
+};
+
+
+/**
+ * The check manager is the interface to running the checks. This allows
+ * default checks to be enabled, non-default checks to be enabled, and so on.
+ */
+class check_manager
+{
+ /**
+ * The enabled checkers, indexed by their names. The name is used when
+ * disabling checkers from the command line. When this manager runs,
+ * it will only run the checkers from this map.
+ */
+ std::unordered_map<std::string, checker*> checkers;
+ /**
+ * The disabled checkers. Moving checkers to this list disables them,
+ * but allows them to be easily moved back.
+ */
+ std::unordered_map<std::string, checker*> disabled_checkers;
+ /**
+ * Helper function for adding a property value checker.
+ */
+ template<property_value::value_type T>
+ void add_property_type_checker(const char *name, const std::string &prop);
+ /**
+ * Helper function for adding a simple type checker.
+ */
+ void add_property_type_checker(const char *name, const std::string &prop);
+ /**
+ * Helper function for adding a property value checker.
+ */
+ void add_property_size_checker(const char *name,
+ const std::string &prop,
+ uint32_t size);
+ public:
+ /**
+ * Delete all of the checkers that are part of this checker manager.
+ */
+ ~check_manager();
+ /**
+ * Default constructor, creates check manager containing all of the
+ * default checks.
+ */
+ check_manager();
+ /**
+ * Run all of the checks on the specified tree.
+ */
+ bool run_checks(device_tree *tree, bool keep_going);
+ /**
+ * Disables the named checker.
+ */
+ bool disable_checker(const std::string &name);
+ /**
+ * Enables the named checker.
+ */
+ bool enable_checker(const std::string &name);
+};
+
+} // namespace checking
+
+} // namespace fdt
+
+} // namespace dtc
+
+#endif // !_CHECKING_HH_
diff --git a/usr.bin/dtc/dtb.cc b/usr.bin/dtc/dtb.cc
new file mode 100644
index 000000000000..e2e73600a7c3
--- /dev/null
+++ b/usr.bin/dtc/dtb.cc
@@ -0,0 +1,341 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "dtb.hh"
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+using std::string;
+
+namespace {
+
+void write(dtc::byte_buffer &buffer, int fd)
+{
+ size_t size = buffer.size();
+ uint8_t *data = buffer.data();
+ while (size > 0)
+ {
+ ssize_t r = ::write(fd, data, size);
+ if (r >= 0)
+ {
+ data += r;
+ size -= r;
+ }
+ else if (errno != EAGAIN)
+ {
+ fprintf(stderr, "Writing to file failed\n");
+ exit(-1);
+ }
+ }
+}
+}
+
+namespace dtc
+{
+namespace dtb
+{
+
+void output_writer::write_data(byte_buffer b)
+{
+ for (auto i : b)
+ {
+ write_data(i);
+ }
+}
+
+void
+binary_writer::write_string(const string &name)
+{
+ push_string(buffer, name);
+ // Trailing nul
+ buffer.push_back(0);
+}
+
+void
+binary_writer::write_data(uint8_t v)
+{
+ buffer.push_back(v);
+}
+
+void
+binary_writer::write_data(uint32_t v)
+{
+ while (buffer.size() % 4 != 0)
+ {
+ buffer.push_back(0);
+ }
+ push_big_endian(buffer, v);
+}
+
+void
+binary_writer::write_data(uint64_t v)
+{
+ while (buffer.size() % 8 != 0)
+ {
+ buffer.push_back(0);
+ }
+ push_big_endian(buffer, v);
+}
+
+void
+binary_writer::write_to_file(int fd)
+{
+ write(buffer, fd);
+}
+
+uint32_t
+binary_writer::size()
+{
+ return buffer.size();
+}
+
+void
+asm_writer::write_line(const char *c)
+{
+ if (byte_count != 0)
+ {
+ byte_count = 0;
+ buffer.push_back('\n');
+ }
+ write_string(c);
+}
+
+void
+asm_writer::write_byte(uint8_t b)
+{
+ char out[3] = {0};
+ if (byte_count++ == 0)
+ {
+ buffer.push_back('\t');
+ }
+ write_string(".byte 0x");
+ snprintf(out, 3, "%.2hhx", b);
+ buffer.push_back(out[0]);
+ buffer.push_back(out[1]);
+ if (byte_count == 4)
+ {
+ buffer.push_back('\n');
+ byte_count = 0;
+ }
+ else
+ {
+ buffer.push_back(';');
+ buffer.push_back(' ');
+ }
+}
+
+void
+asm_writer::write_label(const string &name)
+{
+ write_line("\t.globl ");
+ push_string(buffer, name);
+ buffer.push_back('\n');
+ push_string(buffer, name);
+ buffer.push_back(':');
+ buffer.push_back('\n');
+ buffer.push_back('_');
+ push_string(buffer, name);
+ buffer.push_back(':');
+ buffer.push_back('\n');
+
+}
+
+void
+asm_writer::write_comment(const string &name)
+{
+ write_line("\t/* ");
+ push_string(buffer, name);
+ write_string(" */\n");
+}
+
+void
+asm_writer::write_string(const char *c)
+{
+ while (*c)
+ {
+ buffer.push_back((uint8_t)*(c++));
+ }
+}
+
+
+void
+asm_writer::write_string(const string &name)
+{
+ write_line("\t.string \"");
+ push_string(buffer, name);
+ write_line("\"\n");
+ bytes_written += name.size() + 1;
+}
+
+void
+asm_writer::write_data(uint8_t v)
+{
+ write_byte(v);
+ bytes_written++;
+}
+
+void
+asm_writer::write_data(uint32_t v)
+{
+ if (bytes_written % 4 != 0)
+ {
+ write_line("\t.balign 4\n");
+ bytes_written += (4 - (bytes_written % 4));
+ }
+ write_byte((v >> 24) & 0xff);
+ write_byte((v >> 16) & 0xff);
+ write_byte((v >> 8) & 0xff);
+ write_byte((v >> 0) & 0xff);
+ bytes_written += 4;
+}
+
+void
+asm_writer::write_data(uint64_t v)
+{
+ if (bytes_written % 8 != 0)
+ {
+ write_line("\t.balign 8\n");
+ bytes_written += (8 - (bytes_written % 8));
+ }
+ write_byte((v >> 56) & 0xff);
+ write_byte((v >> 48) & 0xff);
+ write_byte((v >> 40) & 0xff);
+ write_byte((v >> 32) & 0xff);
+ write_byte((v >> 24) & 0xff);
+ write_byte((v >> 16) & 0xff);
+ write_byte((v >> 8) & 0xff);
+ write_byte((v >> 0) & 0xff);
+ bytes_written += 8;
+}
+
+void
+asm_writer::write_to_file(int fd)
+{
+ write(buffer, fd);
+}
+
+uint32_t
+asm_writer::size()
+{
+ return bytes_written;
+}
+
+void
+header::write(output_writer &out)
+{
+ out.write_label("dt_blob_start");
+ out.write_label("dt_header");
+ out.write_comment("magic");
+ out.write_data(magic);
+ out.write_comment("totalsize");
+ out.write_data(totalsize);
+ out.write_comment("off_dt_struct");
+ out.write_data(off_dt_struct);
+ out.write_comment("off_dt_strings");
+ out.write_data(off_dt_strings);
+ out.write_comment("off_mem_rsvmap");
+ out.write_data(off_mem_rsvmap);
+ out.write_comment("version");
+ out.write_data(version);
+ out.write_comment("last_comp_version");
+ out.write_data(last_comp_version);
+ out.write_comment("boot_cpuid_phys");
+ out.write_data(boot_cpuid_phys);
+ out.write_comment("size_dt_strings");
+ out.write_data(size_dt_strings);
+ out.write_comment("size_dt_struct");
+ out.write_data(size_dt_struct);
+}
+
+bool
+header::read_dtb(input_buffer &input)
+{
+ if (!input.consume_binary(magic))
+ {
+ fprintf(stderr, "Missing magic token in header.");
+ return false;
+ }
+ if (magic != 0xd00dfeed)
+ {
+ fprintf(stderr, "Bad magic token in header. Got %" PRIx32
+ " expected 0xd00dfeed\n", magic);
+ return false;
+ }
+ return input.consume_binary(totalsize) &&
+ input.consume_binary(off_dt_struct) &&
+ input.consume_binary(off_dt_strings) &&
+ input.consume_binary(off_mem_rsvmap) &&
+ input.consume_binary(version) &&
+ input.consume_binary(last_comp_version) &&
+ input.consume_binary(boot_cpuid_phys) &&
+ input.consume_binary(size_dt_strings) &&
+ input.consume_binary(size_dt_struct);
+}
+uint32_t
+string_table::add_string(const string &str)
+{
+ auto old = string_offsets.find(str);
+ if (old == string_offsets.end())
+ {
+ uint32_t start = size;
+ // Don't forget the trailing nul
+ size += str.size() + 1;
+ string_offsets.insert(std::make_pair(str, start));
+ strings.push_back(str);
+ return start;
+ }
+ else
+ {
+ return old->second;
+ }
+}
+
+void
+string_table::write(dtb::output_writer &writer)
+{
+ writer.write_comment("Strings table.");
+ writer.write_label("dt_strings_start");
+ for (auto &i : strings)
+ {
+ writer.write_string(i);
+ }
+ writer.write_label("dt_strings_end");
+}
+
+} // namespace dtb
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/dtb.hh b/usr.bin/dtc/dtb.hh
new file mode 100644
index 000000000000..410ec98569be
--- /dev/null
+++ b/usr.bin/dtc/dtb.hh
@@ -0,0 +1,373 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _DTB_HH_
+#define _DTB_HH_
+#include <map>
+#include <string>
+
+#include <assert.h>
+
+#include "input_buffer.hh"
+#include "util.hh"
+
+namespace dtc
+{
+/**
+ * The dtb namespace contains code related to the generation of device tree
+ * blobs, the binary representation of flattened device trees. The abstract
+ * tree representation calls into this code to generate the output.
+ */
+namespace dtb
+{
+/** The token types in the DTB, as defined by §7.4.1 of the ePAPR
+ * specification. All of these values are written in big-endian format in the
+ * output.
+ */
+enum token_type
+{
+ /**
+ * Marker indicating the start of a node in the tree. This is followed
+ * by the nul-terminated name. If a unit address is specified, then
+ * the name also contains the address, with an @ symbol between the end
+ * of the name and the start of the address.
+ *
+ * The name is then padded such that the next token begins on a 4-byte
+ * boundary. The node may contain properties, other nodes, both, or be
+ * empty.
+ */
+ FDT_BEGIN_NODE = 0x00000001,
+ /**
+ * Marker indicating the end of a node.
+ */
+ FDT_END_NODE = 0x00000002,
+ /**
+ * The start of a property. This is followed by two 32-bit big-endian
+ * values. The first indicates the length of the property value, the
+ * second its index in the strings table. It is then followed by the
+ * property value, if the value is of non-zero length.
+ */
+ FDT_PROP = 0x00000003,
+ /**
+ * Ignored token. May be used for padding inside DTB nodes.
+ */
+ FDT_NOP = 0x00000004,
+ /**
+ * Marker indicating the end of the tree.
+ */
+ FDT_END = 0x00000009
+};
+
+/**
+ * Returns the token as a string. This is used for debugging and for printing
+ * human-friendly error messages about malformed DTB input.
+ */
+inline const char *token_type_name(token_type t)
+{
+ switch(t)
+ {
+ case FDT_BEGIN_NODE:
+ return "FDT_BEGIN_NODE";
+ case FDT_END_NODE:
+ return "FDT_END_NODE";
+ case FDT_PROP:
+ return "FDT_PROP";
+ case FDT_NOP:
+ return "FDT_NOP";
+ case FDT_END:
+ return "FDT_END";
+ }
+ assert(0);
+ // Not reached.
+ return nullptr;
+}
+
+/**
+ * Abstract class for writing a section of the output. We create one
+ * of these for each section that needs to be written. It is intended to build
+ * a temporary buffer of the output in memory and then write it to a file
+ * stream. The size can be returned after all of the data has been written
+ * into the internal buffer, so the sizes of the three tables can be calculated
+ * before storing them in the buffer.
+ */
+struct output_writer
+{
+ /**
+ * Writes a label into the output stream. This is only applicable for
+ * assembly output, where the labels become symbols that can be
+ * resolved at link time.
+ */
+ virtual void write_label(const std::string &name) = 0;
+ /**
+ * Writes a comment into the output stream. Useful only when debugging
+ * the output.
+ */
+ virtual void write_comment(const std::string &name) = 0;
+ /**
+ * Writes a string. A nul terminator is implicitly added.
+ */
+ virtual void write_string(const std::string &name) = 0;
+ /**
+ * Writes a single 8-bit value.
+ */
+ virtual void write_data(uint8_t) = 0;
+ /**
+ * Writes a single 32-bit value. The value is written in big-endian
+ * format, but should be passed in the host's native endian.
+ */
+ virtual void write_data(uint32_t) = 0;
+ /**
+ * Writes a single 64-bit value. The value is written in big-endian
+ * format, but should be passed in the host's native endian.
+ */
+ virtual void write_data(uint64_t) = 0;
+ /**
+ * Writes the collected output to the specified file descriptor.
+ */
+ virtual void write_to_file(int fd) = 0;
+ /**
+ * Returns the number of bytes.
+ */
+ virtual uint32_t size() = 0;
+ /**
+ * Helper for writing tokens to the output stream. This writes a
+ * comment above the token describing its value, for easier debugging
+ * of the output.
+ */
+ inline void write_token(token_type t)
+ {
+ write_comment(token_type_name(t));
+ write_data((uint32_t)t);
+ }
+ /**
+ * Helper function that writes a byte buffer to the output, one byte at
+ * a time.
+ */
+ void write_data(byte_buffer b);
+};
+
+/**
+ * Binary file writer. This class is responsible for writing the DTB output
+ * directly in blob format.
+ */
+class binary_writer : public output_writer
+{
+ /**
+ * The internal buffer used to store the blob while it is being
+ * constructed.
+ */
+ byte_buffer buffer;
+ public:
+ /**
+ * The binary format does not support labels, so this method
+ * does nothing.
+ */
+ void write_label(const std::string &) override {}
+ /**
+ * Comments are ignored by the binary writer.
+ */
+ void write_comment(const std::string&) override {}
+ void write_string(const std::string &name) override;
+ void write_data(uint8_t v) override;
+ void write_data(uint32_t v) override;
+ void write_data(uint64_t v) override;
+ void write_to_file(int fd) override;
+ uint32_t size() override;
+};
+/**
+ * Assembly writer. This class is responsible for writing the output in an
+ * assembly format that is suitable for linking into a kernel, loader, and so
+ * on.
+ */
+class asm_writer : public output_writer
+{
+ /**
+ * The internal buffer for temporary values. Note that this actually
+ * contains ASCII text, but it is a byte buffer so that we can just
+ * copy strings across as-is.
+ */
+ byte_buffer buffer;
+ /**
+ * The number of bytes written to the current line. This is used to
+ * allow line wrapping, where we aim to write four .byte directives to
+ * make the alignment clearer.
+ */
+ int byte_count;
+ /**
+ * The current number of bytes written. This is the number in binary
+ * format, not the number of bytes in the buffer.
+ */
+ uint32_t bytes_written;
+
+ /**
+ * Writes a string directly to the output as-is. This is the function that
+ * performs the real output.
+ */
+ void write_string(const char *c);
+ /**
+ * Write a string to the output.
+ */
+ void write_string(const std::string &c) override;
+ /**
+ * Writes the string, starting on a new line.
+ */
+ void write_line(const char *c);
+ /**
+ * Writes a byte in binary format. This will emit a single .byte
+ * directive, with up to four per line.
+ */
+ void write_byte(uint8_t b);
+ public:
+ asm_writer() : byte_count(0), bytes_written(0) {}
+ void write_label(const std::string &name) override;
+ void write_comment(const std::string &name) override;
+ void write_data(uint8_t v) override;
+ void write_data(uint32_t v) override;
+ void write_data(uint64_t v) override;
+ void write_to_file(int fd) override;
+ uint32_t size() override;
+};
+
+/**
+ * Class encapsulating the device tree blob header. This class stores all of
+ * the values found in the header and is responsible for writing them to the
+ * output.
+ */
+struct header
+{
+ /**
+ * Magic value, used to validate that this really is a device tree
+ * blob. Should always be set to 0xd00dfeed.
+ */
+ uint32_t magic;
+ /**
+ * The total size of the blob, including header, reservations, strings
+ * table, and padding.
+ */
+ uint32_t totalsize;
+ /**
+ * The offset from the start of the blob of the struct table (i.e. the
+ * part of the blob containing the entire device tree).
+ */
+ uint32_t off_dt_struct;
+ /**
+ * The offset from the start of the blob of the strings table.
+ */
+ uint32_t off_dt_strings;
+ /**
+ * The offset of the reservation map from the start of the blob.
+ */
+ uint32_t off_mem_rsvmap;
+ /**
+ * The version of the blob. This should always be 17.
+ */
+ uint32_t version;
+ /**
+ * The earliest version of the DTB specification with which this blob
+ * is backwards compatible. This should always be 16.
+ */
+ uint32_t last_comp_version;
+ /**
+ * The ID of the CPU where this boots.
+ */
+ uint32_t boot_cpuid_phys;
+ /**
+ * The size of the strings table.
+ */
+ uint32_t size_dt_strings;
+ /**
+ * The size of the struct table.
+ */
+ uint32_t size_dt_struct;
+ /**
+ * Writes the entire header to the specified output buffer.
+ */
+ void write(output_writer &out);
+ /**
+ * Reads the header from bits binary representation in a blob.
+ */
+ bool read_dtb(input_buffer &input);
+ /**
+ * Default constructor. Initialises the values that have sensible
+ * defaults, leaves the others blank.
+ */
+ header() : magic(0xd00dfeed), version(17), last_comp_version(16),
+ boot_cpuid_phys(0) {}
+};
+
+/**
+ * Class encapsulating the string table. FDT strings are stored in a string
+ * section. This maintains a map from strings to their offsets in the strings
+ * section.
+ *
+ * Note: We don't currently do suffix matching, which may save a small amount
+ * of space.
+ */
+class string_table {
+ /**
+ * Map from strings to their offset.
+ */
+ std::map<std::string, uint32_t> string_offsets;
+ /**
+ * The strings, in the order in which they should be written to the
+ * output. The order must be stable - adding another string must not
+ * change the offset of any that we have already referenced - and so we
+ * simply write the strings in the order that they are passed.
+ */
+ std::vector<std::string> strings;
+ /**
+ * The current size of the strings section.
+ */
+ uint32_t size;
+ public:
+ /**
+ * Default constructor, creates an empty strings table.
+ */
+ string_table() : size(0) {}
+ /**
+ * Adds a string to the table, returning the offset from the start
+ * where it will be written. If the string is already present, this
+ * will return its existing offset, otherwise it will return a new
+ * offset.
+ */
+ uint32_t add_string(const std::string &str);
+ /**
+ * Writes the strings table to the specified output.
+ */
+ void write(dtb::output_writer &writer);
+};
+
+} // namespace dtb
+
+} // namespace dtc
+
+#endif // !_DTB_HH_
diff --git a/usr.bin/dtc/dtc.1 b/usr.bin/dtc/dtc.1
new file mode 100644
index 000000000000..d10759c5b0e9
--- /dev/null
+++ b/usr.bin/dtc/dtc.1
@@ -0,0 +1,445 @@
+.\"-
+.\" Copyright (c) 2013 David Chisnall
+.\" All rights reserved.
+.\"
+.\" This software was developed by SRI International and the University of
+.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+.\" ("CTSRD"), as part of the DARPA CRASH research programme.
+.\"
+.\" This software was developed by SRI International and the University of
+.\" 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 AUTHOR 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 AUTHOR 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 February 26, 2022
+.Dt DTC 1
+.Os
+.Sh NAME
+.Nm dtc
+.Nd device tree compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl @fhsv
+.Op Fl b Ar boot_cpu_id
+.Op Fl d Ar dependency_file
+.Op Fl i Ar include_path
+.Op Fl E Ar [no-]checker_name
+.Op Fl H Ar phandle_format
+.Op Fl I Ar input_format
+.Op Fl O Ar output_format
+.Op Fl o Ar output_file
+.Op Fl R Ar entries
+.Op Fl S Ar bytes
+.Op Fl p Ar bytes
+.Op Fl V Ar blob_version
+.Op Fl W Ar [no-]checker_name
+.Op Fl P Ar predefined_properties
+.Ar input_file
+.Sh DESCRIPTION
+The
+.Nm
+utility converts between flattened device tree (FDT) representations.
+It is most commonly used to generate device tree blobs (DTB), the binary
+representation of an FDT, from device tree sources (DTS), the ASCII text source
+representation.
+.Pp
+The binary can be written in two formats, binary and assembly.
+The binary is identical to the in-memory representation and can be used
+directly by firmware, loaders, and so on.
+The assembly format, documented in
+.Sx "ASM FORMAT" ,
+will produce the same binary format when assembled, but also includes some
+global variables that refer to parts of the table.
+This format is most commonly used to produce a kernel specific to a device,
+with the device tree blob compiled in.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar dependency_file
+Writes a dependency file understandable by make to the specified file.
+This file can be included in a Makefile and will ensure that the output file
+depends on the input file and any files that it includes.
+This argument is only useful when the input is DTS, as only the source format
+has a notion of inclusions.
+.It Fl i Ar include_path
+Adds a path to search for include files.
+.It Fl E Ar [no-]checker_name
+Enable or disable a specified checker.
+The argument is the name of the checker.
+The full list of checkers is given in
+.Sx CHECKERS .
+.It Fl @
+Emit a __symbols__ node to allow plugins to be loaded.
+.It Fl f
+Force the tool to attempt to generate the output, even if the input had errors.
+.It Fl h
+Display the help text and exit.
+.It Fl H Ar phandle_format
+Specifies the type of phandle nodes to generate in the output.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar linux
+Generate the legacy linux,phandle nodes expected by older systems.
+.It Ar epapr
+Generate the phandle nodes, as described in the ePAPR specification.
+This is the most sensible option for device trees being used with
+.Fx .
+.It Ar both
+Generate both, for maximum compatibility.
+.El
+.It Fl I Ar input_format
+Specifies the input format.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar dtb
+Device tree blob.
+The binary representation of the FDT.
+.It Ar dts
+Device tree source.
+The ASCII representation of the FDT.
+This is the default if the input format is not explicitly stated.
+.El
+.It Fl O Ar output_format
+Specifies the output format.
+Valid values are:
+.Pp
+.Bl -tag -width indent -compact
+.It Ar asm
+Assembler source for generating a device tree blob, as described in
+.Sx "ASM FORMAT" .
+.It Ar dtb
+Device tree blob.
+The binary representation of the FDT.
+This is the default if the output format is not explicitly stated.
+.It Ar dts
+Device tree source.
+The ASCII representation of the FDT.
+.El
+.It Fl o Ar output_file
+The file to which to write the output.
+.It Fl P Ar predefined_macro
+Defines a macro, in the form
+.Ar name=value
+or
+.Ar name
+to be used for device tree source files that contain conditional components.
+This tool supports two extensions to the standard to support conditional
+compilation of device trees.
+The first is an
+.Ar /include/if [property]/ "file.dts"
+directive that is allowed at the start of a file and which will only include
+the specified file if it the specified property is passed with this flag.
+The second is the
+.Ar $NAME
+format for property values.
+These allow property value to be specified on the command line.
+.It Fl R Ar entries
+The number of empty reservation table entries to pad the table with.
+This is useful if you are generating a device tree blob for bootloader or
+similar that needs to reserve some memory before passing control to the
+operating system.
+.It Fl S Ar bytes
+The minimum size in bytes of the blob.
+The blob will be padded after the strings table to ensure that it is the
+correct size.
+This is useful for environments where the device tree blob must be modified in
+place.
+.It Fl p Ar bytes
+The number of bytes of padding to add to the blob.
+The blob will be padded after the strings table to ensure that it is the
+correct size.
+This is useful for environments where the device tree blob must be modified in
+place.
+.It Fl W Ar [no-]checker_name
+Enable or disable a specified checker.
+This is an alias for
+.Fl E .
+.It Fl s
+Sorts the properties and nodes in the tree.
+This is mainly useful when using tools like
+.Xr diff 1
+to compare two device tree sources.
+.It Fl V Ar output_version
+The version of the format to output.
+This is only relevant for binary outputs, and only a value of 17 is currently
+supported.
+.It Fl v
+Display the tool version and exit.
+.It Ar input_file
+The source file.
+.El
+.Sh "ASM FORMAT"
+The assembly format defines several globals that can be referred to from other
+compilation units, in addition to any labels specified in the source.
+These are:
+.Pp
+.Bl -tag -width "dt_strings_start" -compact -offset indent
+.It dt_blob_start
+start of the device tree blob.
+.It dt_header
+start of the header, usually identical to the start of the blob.
+.It dt_reserve_map
+start of the reservation map.
+.It dt_struct_start
+start of the structure table.
+.It dt_struct_end
+end of the structure table.
+.It dt_strings_start
+start of the strings table.
+.It dt_strings_end
+end of the strings table.
+.It dt_blob_end
+end of the device tree blob.
+.El
+.Sh CHECKERS
+The utility provides a number of semantic checks on the correctness of the
+tree.
+These can be disabled with the
+.Fl W
+flag.
+For example,
+.Fl W Ar no-type-phandle
+will disable the phandle type check.
+The supported checks are:
+.Pp
+.Bl -tag -width "no-type-phandle" -compact -offset indent
+.It type-compatible
+Checks the type of the
+.Va compatible
+property.
+.It type-model
+Checks the type of the
+.Va model
+property.
+.It type-compatible
+Checks the type of the
+.Va compatible
+property.
+.It cells-attributes
+Checks that all nodes with children have both
+.Va #address-cells
+and
+.Va #size-cells
+properties.
+.It deleted-nodes
+Checks that all
+.Va /delete-node/
+statements refer to nodes that are merged.
+.El
+.Sh OVERLAYS
+The utility provides support for generating overlays, also known as plugins.
+Overlays are a method of patching a base device tree that has been compiled with
+the
+.Fl @
+flag, with some limited support for patching device trees that were not compiled
+with the
+.Fl @
+flag.
+.Pp
+To denote that a DTS is intended to be used as an overlay,
+.Va /plugin/\&;
+should be included in the header, following any applicable
+.Va /dts-v1/\&;
+tag.
+.Pp
+Conventional overlays are crafted by creating
+.Va fragment
+nodes in a root.
+Each fragment node must have either a
+.Va target
+property set to a label reference, or a
+.Va target-path
+string property set to a path.
+It must then have an
+.Va __overlay__
+child node, whose properties and child nodes are merged into the base device
+tree when the overlay is applied.
+.Pp
+Much simpler syntactic sugar was later invented to simplify generating overlays.
+Instead of creating targeted fragments manually, one can instead create a root
+node that targets a label in the base FDT using the
+.Va &label
+syntax supported in conventional DTS.
+This will indicate that a fragment should be generated for the node, with the
+given
+.Va label
+being the target, and the properties and child nodes will be used as the
+__overlay__.
+.Pp
+Additionally, a path-based version of this syntactic sugar is supported.
+A root node may target a path in the base FDT using a name of the form
+.Va &{/path} .
+A fragment will be generated for the node as it is in the
+.Va &label
+case, except the
+.Va target-path
+property will be set to
+.Va /path
+and no
+.Va target
+will be set.
+.Pp
+Both conventional overlays and the later-added syntactic sugar are supported.
+.Pp
+Overlay blobs can be applied at boot time by setting
+.Va fdt_overlays
+in
+.Xr loader.conf 5 .
+Multiple overlays may be specified, and they will be applied in the order given.
+.Sh NODE OMISSION
+This utility supports the
+.Va /omit-if-no-ref/
+statement to mark nodes for omission if they are ultimately not referenced
+elsewhere in the device tree.
+This may be used in more space-constrained environments to remove nodes that may
+not be applicable to the specific device the tree is being compiled for.
+.Pp
+When the
+.Fl @
+flag is used to write symbols, nodes with labels will be considered referenced
+and will not be removed from the tree.
+.Sh EXAMPLES
+The command:
+.Pp
+.Dl "dtc -o blob.S -O asm device.dts"
+.Pp
+will generate a
+.Pa blob.S
+file from the device tree source
+.Pa device.dts
+and print errors if any occur during parsing or property checking.
+The resulting file can be assembled and linked into a binary.
+.Pp
+The command:
+.Pp
+.Dl "dtc -o - -O dts -I dtb device.dtb"
+.Pp
+will write the device tree source for the device tree blob
+.Pa device.dtb
+to the standard output.
+This is useful when debugging device trees.
+.Pp
+The command:
+.Pp
+.Dl "dtc -@ -O dtb -I dts -o device.dtb device.dts"
+.Pp
+will generate a
+.Pa device.dtb
+file from the device tree source
+.Pa device.dts
+with a __symbols__ node included so that overlays may be applied to it.
+.Pp
+The command:
+.Pp
+.Dl "dtc -@ -O dtb -I dts -o device_overlay.dtbo device_overlay.dts"
+.Pp
+will generate a
+.Pa device_overlay.dtbo
+file, using the standard extension for a device tree overlay, from the device
+tree source
+.Pa device_overlay.dts .
+A __symbols__ node will be included so that overlays may be applied to it.
+The presence of a
+.Va /plugin/\&;
+directive in
+.Pa device_overlay.dts
+will indicate to the utility that it should also generate the underlying
+metadata required in overlays.
+.Sh COMPATIBILITY
+This utility is intended to be compatible with the device tree compiler
+provided by elinux.org.
+Currently, it implements the subset of features
+required to build
+.Fx
+and others that have been requested by
+.Fx
+developers.
+.Pp
+The
+.Ar fs
+input format is not supported.
+This builds a tree from a Linux
+.Pa /proc/device-tree ,
+a file system hierarchy not found in
+.Fx ,
+which instead exposes the DTB directly via a sysctl.
+.Pp
+The warnings and errors supported by the elinux.org tool are not documented.
+This tool supports the warnings described in the
+.Sx CHECKERS
+section.
+.Sh SEE ALSO
+.Xr fdt 4
+.Sh STANDARDS
+The device tree formats understood by this tool conform to the Power.org
+Standard for Embedded Power Architecture Platform Requirements
+.Pq Vt ePAPR ,
+except as noted in the
+.Sx BUGS
+section and with the following exceptions for compatibility with the elinux.org
+tool:
+.Pp
+.Bl -bullet -compact
+.It
+The target of cross references is defined to be a node name in the
+specification, but is in fact a label.
+.El
+.Pp
+The /include/ directive is not part of the standard, however it is implemented
+with the semantics compatible with the elinux.org tool.
+It must appear in the top level of a file, and imports a new root definition.
+If a file, plus all of its inclusions, contains multiple roots then they are
+merged.
+All nodes that are present in the second but not the first are imported.
+Any that appear in both are recursively merged, with properties from the second
+replacing those from the first and properties child nodes being recursively
+merged.
+.Sh HISTORY
+A dtc tool first appeared in
+.Fx 9.0 .
+This version of the tool first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.Nm
+was written by
+.An David T. Chisnall .
+Some features were added later by
+.An Kyle Evans .
+.Pp
+Note: The fact that the tool and the author share the same initials is entirely
+coincidental.
+.Sh BUGS
+The device tree compiler does not yet support the following features:
+.Pp
+.Bl -bullet -compact
+.It
+Labels in the middle of property values.
+This is only useful in the assembly output, and only vaguely useful there, so
+is unlikely to be added soon.
+.It
+Full paths, rather than labels, as the targets for phandles.
+This is not very hard to add, but will probably not be added until something
+actually needs it.
+.El
+.Pp
+The current version performs a very limited set of semantic checks on the tree.
+This will be improved in future versions.
diff --git a/usr.bin/dtc/dtc.cc b/usr.bin/dtc/dtc.cc
new file mode 100644
index 000000000000..22b2d000c129
--- /dev/null
+++ b/usr.bin/dtc/dtc.cc
@@ -0,0 +1,382 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/resource.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#include "fdt.hh"
+#include "checking.hh"
+#include "util.hh"
+
+using namespace dtc;
+using std::string;
+
+namespace {
+
+/**
+ * The current major version of the tool.
+ */
+int version_major = 0;
+int version_major_compatible = 1;
+/**
+ * The current minor version of the tool.
+ */
+int version_minor = 5;
+int version_minor_compatible = 4;
+/**
+ * The current patch level of the tool.
+ */
+int version_patch = 0;
+int version_patch_compatible = 7;
+
+void usage(const string &argv0)
+{
+ fprintf(stderr, "Usage:\n"
+ "\t%s\t[-fhsv@] [-b boot_cpu_id] [-d dependency_file]"
+ "[-E [no-]checker_name]\n"
+ "\t\t[-H phandle_format] [-I input_format]"
+ "[-O output_format]\n"
+ "\t\t[-o output_file] [-R entries] [-S bytes] [-p bytes]"
+ "[-V blob_version]\n"
+ "\t\t-W [no-]checker_name] input_file\n", basename(argv0).c_str());
+}
+
+/**
+ * Prints the current version of this program..
+ */
+void version(const char* progname)
+{
+ fprintf(stdout, "Version: %s %d.%d.%d compatible with gpl dtc %d.%d.%d\n", progname,
+ version_major, version_minor, version_patch,
+ version_major_compatible, version_minor_compatible,
+ version_patch_compatible);
+}
+
+} // Anonymous namespace
+
+using fdt::device_tree;
+using fdt::tree_write_fn_ptr;
+using fdt::tree_read_fn_ptr;
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ int outfile = fileno(stdout);
+ const char *outfile_name = "-";
+ const char *in_file = "-";
+ FILE *depfile = 0;
+ bool debug_mode = false;
+ tree_write_fn_ptr write_fn = nullptr;
+ tree_read_fn_ptr read_fn = nullptr;
+ uint32_t boot_cpu = 0;
+ bool boot_cpu_specified = false;
+ bool keep_going = false;
+ bool sort = false;
+ clock_t c0 = clock();
+ class device_tree tree;
+ fdt::checking::check_manager checks;
+ const char *options = "@hqI:O:o:V:d:R:S:p:b:fi:svH:W:E:DP:";
+
+ // Don't forget to update the man page if any more options are added.
+ while ((ch = getopt(argc, argv, options)) != -1)
+ {
+ switch (ch)
+ {
+ case 'h':
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ case 'v':
+ version(argv[0]);
+ return EXIT_SUCCESS;
+ case '@':
+ tree.write_symbols = true;
+ break;
+ case 'I':
+ {
+ string arg(optarg);
+ if (arg == "dtb")
+ {
+ read_fn = &device_tree::parse_dtb;
+ if (write_fn == nullptr)
+ {
+ write_fn = &device_tree::write_dts;
+ }
+ }
+ else if (arg == "dts")
+ {
+ read_fn = &device_tree::parse_dts;
+ }
+ else
+ {
+ fprintf(stderr, "Unknown input format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'O':
+ {
+ string arg(optarg);
+ if (arg == "dtb")
+ {
+ write_fn = &device_tree::write_binary;
+ }
+ else if (arg == "asm")
+ {
+ write_fn = &device_tree::write_asm;
+ }
+ else if (arg == "dts")
+ {
+ write_fn = &device_tree::write_dts;
+ if (read_fn == nullptr)
+ {
+ read_fn = &device_tree::parse_dtb;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Unknown output format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'o':
+ {
+ outfile_name = optarg;
+ if (strcmp(outfile_name, "-") != 0)
+ {
+ outfile = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (outfile == -1)
+ {
+ perror("Unable to open output file");
+ return EXIT_FAILURE;
+ }
+ }
+ break;
+ }
+ case 'D':
+ debug_mode = true;
+ break;
+ case 'V':
+ if (string(optarg) != "17")
+ {
+ fprintf(stderr, "Unknown output format version: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'd':
+ {
+ if (depfile != 0)
+ {
+ fclose(depfile);
+ }
+ if (string(optarg) == "-")
+ {
+ depfile = stdout;
+ }
+ else
+ {
+ depfile = fdopen(open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 0666), "w");
+ if (depfile == 0)
+ {
+ perror("Unable to open dependency file");
+ return EXIT_FAILURE;
+ }
+ }
+ break;
+ }
+ case 'H':
+ {
+ string arg(optarg);
+ if (arg == "both")
+ {
+ tree.set_phandle_format(device_tree::BOTH);
+ }
+ else if (arg == "epapr")
+ {
+ tree.set_phandle_format(device_tree::EPAPR);
+ }
+ else if (arg == "linux")
+ {
+ tree.set_phandle_format(device_tree::LINUX);
+ }
+ else
+ {
+ fprintf(stderr, "Unknown phandle format: %s\n", optarg);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ case 'b':
+ // Don't bother to check if strtoll fails, just
+ // use the 0 it returns.
+ boot_cpu = (uint32_t)strtoll(optarg, 0, 10);
+ boot_cpu_specified = true;
+ break;
+ case 'f':
+ keep_going = true;
+ break;
+ case 'W':
+ case 'E':
+ {
+ string arg(optarg);
+ if ((arg.size() > 3) && (strncmp(optarg, "no-", 3) == 0))
+ {
+ arg = string(optarg+3);
+ if (!checks.disable_checker(arg))
+ {
+ fprintf(stderr, "Checker %s either does not exist or is already disabled\n", optarg+3);
+ }
+ break;
+ }
+ if (!checks.enable_checker(arg))
+ {
+ fprintf(stderr, "Checker %s either does not exist or is already enabled\n", optarg);
+ }
+ break;
+ }
+ case 's':
+ {
+ sort = true;
+ break;
+ }
+ case 'i':
+ {
+ tree.add_include_path(optarg);
+ break;
+ }
+ // Should quiet warnings, but for now is silently ignored.
+ case 'q':
+ break;
+ case 'R':
+ tree.set_empty_reserve_map_entries(strtoll(optarg, 0, 10));
+ break;
+ case 'S':
+ tree.set_blob_minimum_size(strtoll(optarg, 0, 10));
+ break;
+ case 'p':
+ tree.set_blob_padding(strtoll(optarg, 0, 10));
+ break;
+ case 'P':
+ if (!tree.parse_define(optarg))
+ {
+ fprintf(stderr, "Invalid predefine value %s\n",
+ optarg);
+ }
+ break;
+ default:
+ /*
+ * Since opterr is non-zero, getopt will have
+ * already printed an error message.
+ */
+ return EXIT_FAILURE;
+ }
+ }
+ if (read_fn == nullptr)
+ {
+ read_fn = &device_tree::parse_dts;
+ }
+ if (write_fn == nullptr)
+ {
+ write_fn = &device_tree::write_binary;
+ }
+ if (optind < argc)
+ {
+ in_file = argv[optind];
+ }
+ if (depfile != 0)
+ {
+ fputs(outfile_name, depfile);
+ fputs(": ", depfile);
+ fputs(in_file, depfile);
+ }
+ clock_t c1 = clock();
+ (tree.*read_fn)(in_file, depfile);
+ // Override the boot CPU found in the header, if we're loading from dtb
+ if (boot_cpu_specified)
+ {
+ tree.set_boot_cpu(boot_cpu);
+ }
+ if (sort)
+ {
+ tree.sort();
+ }
+ if (depfile != 0)
+ {
+ putc('\n', depfile);
+ fclose(depfile);
+ }
+ if (!(tree.is_valid() || keep_going))
+ {
+ fprintf(stderr, "Failed to parse tree.\n");
+ return EXIT_FAILURE;
+ }
+ clock_t c2 = clock();
+ if (!(checks.run_checks(&tree, true) || keep_going))
+ {
+ return EXIT_FAILURE;
+ }
+ clock_t c3 = clock();
+ (tree.*write_fn)(outfile);
+ close(outfile);
+ clock_t c4 = clock();
+
+ if (debug_mode)
+ {
+ struct rusage r;
+
+ getrusage(RUSAGE_SELF, &r);
+ fprintf(stderr, "Peak memory usage: %ld bytes\n", r.ru_maxrss);
+ fprintf(stderr, "Setup and option parsing took %f seconds\n",
+ ((double)(c1-c0))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Parsing took %f seconds\n",
+ ((double)(c2-c1))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Checking took %f seconds\n",
+ ((double)(c3-c2))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Generating output took %f seconds\n",
+ ((double)(c4-c3))/CLOCKS_PER_SEC);
+ fprintf(stderr, "Total time: %f seconds\n",
+ ((double)(c4-c0))/CLOCKS_PER_SEC);
+ // This is not needed, but keeps valgrind quiet.
+ fclose(stdin);
+ }
+ return EXIT_SUCCESS;
+}
+
diff --git a/usr.bin/dtc/fdt.cc b/usr.bin/dtc/fdt.cc
new file mode 100644
index 000000000000..f0b98cfe720c
--- /dev/null
+++ b/usr.bin/dtc/fdt.cc
@@ -0,0 +1,2304 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 __STDC_LIMIT_MACROS 1
+
+#include "fdt.hh"
+#include "dtb.hh"
+
+#include <algorithm>
+#include <limits>
+#include <sstream>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+using std::string;
+
+namespace dtc
+{
+
+namespace fdt
+{
+
+uint32_t
+property_value::get_as_uint32()
+{
+ if (byte_data.size() != 4)
+ {
+ return 0;
+ }
+ uint32_t v = 0;
+ v &= byte_data[0] << 24;
+ v &= byte_data[1] << 16;
+ v &= byte_data[2] << 8;
+ v &= byte_data[3] << 0;
+ return v;
+}
+
+void
+property_value::push_to_buffer(byte_buffer &buffer)
+{
+ if (!byte_data.empty())
+ {
+ buffer.insert(buffer.end(), byte_data.begin(), byte_data.end());
+ }
+ else
+ {
+ push_string(buffer, string_data, true);
+ // Trailing nul
+ buffer.push_back(0);
+ }
+}
+
+void
+property_value::write_dts(FILE *file)
+{
+ resolve_type();
+ switch (type)
+ {
+ default:
+ assert(0 && "Invalid type");
+ case STRING:
+ case STRING_LIST:
+ case CROSS_REFERENCE:
+ write_as_string(file);
+ break;
+ case PHANDLE:
+ write_as_cells(file);
+ break;
+ case BINARY:
+ if (byte_data.size() % 4 == 0)
+ {
+ write_as_cells(file);
+ break;
+ }
+ write_as_bytes(file);
+ break;
+ }
+}
+
+void
+property_value::resolve_type()
+{
+ if (type != UNKNOWN)
+ {
+ return;
+ }
+ if (byte_data.empty())
+ {
+ type = STRING;
+ return;
+ }
+ if (byte_data.back() == 0)
+ {
+ bool is_all_printable = true;
+ int nuls = 0;
+ int bytes = 0;
+ bool lastWasNull = false;
+ for (auto i : byte_data)
+ {
+ bytes++;
+ is_all_printable &= (i == '\0') || isprint(i);
+ if (i == '\0')
+ {
+ // If there are two nulls in a row, then we're probably binary.
+ if (lastWasNull)
+ {
+ type = BINARY;
+ return;
+ }
+ nuls++;
+ lastWasNull = true;
+ }
+ else
+ {
+ lastWasNull = false;
+ }
+ if (!is_all_printable)
+ {
+ break;
+ }
+ }
+ if ((is_all_printable && (bytes > nuls)) || bytes == 0)
+ {
+ type = STRING;
+ if (nuls > 1)
+ {
+ type = STRING_LIST;
+ }
+ return;
+ }
+ }
+ type = BINARY;
+}
+
+size_t
+property_value::size()
+{
+ if (!byte_data.empty())
+ {
+ return byte_data.size();
+ }
+ return string_data.size() + 1;
+}
+
+void
+property_value::write_as_string(FILE *file)
+{
+ putc('"', file);
+ if (byte_data.empty())
+ {
+ fputs(string_data.c_str(), file);
+ }
+ else
+ {
+ bool hasNull = (byte_data.back() == '\0');
+ // Remove trailing null bytes from the string before printing as dts.
+ if (hasNull)
+ {
+ byte_data.pop_back();
+ }
+ for (auto i : byte_data)
+ {
+ // FIXME Escape tabs, newlines, and so on.
+ if (i == '\0')
+ {
+ fputs("\", \"", file);
+ continue;
+ }
+ putc(i, file);
+ }
+ if (hasNull)
+ {
+ byte_data.push_back('\0');
+ }
+ }
+ putc('"', file);
+}
+
+void
+property_value::write_as_cells(FILE *file)
+{
+ putc('<', file);
+ assert((byte_data.size() % 4) == 0);
+ for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; ++i)
+ {
+ uint32_t v = 0;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ ++i;
+ v = (v << 8) | *i;
+ fprintf(file, "0x%" PRIx32, v);
+ if (i+1 != e)
+ {
+ putc(' ', file);
+ }
+ }
+ putc('>', file);
+}
+
+void
+property_value::write_as_bytes(FILE *file)
+{
+ putc('[', file);
+ for (auto i=byte_data.begin(), e=byte_data.end(); i!=e ; i++)
+ {
+ fprintf(file, "%02hhx", *i);
+ if (i+1 != e)
+ {
+ putc(' ', file);
+ }
+ }
+ putc(']', file);
+}
+
+void
+property::parse_string(text_input_buffer &input)
+{
+ property_value v;
+ assert(*input == '"');
+ ++input;
+ std::vector<char> bytes;
+ bool isEscaped = false;
+ while (char c = *input)
+ {
+ if (c == '"' && !isEscaped)
+ {
+ input.consume('"');
+ break;
+ }
+ isEscaped = (c == '\\');
+ bytes.push_back(c);
+ ++input;
+ }
+ v.string_data = string(bytes.begin(), bytes.end());
+ values.push_back(v);
+}
+
+void
+property::parse_cells(text_input_buffer &input, int cell_size)
+{
+ assert(*input == '<');
+ ++input;
+ property_value v;
+ input.next_token();
+ while (!input.consume('>'))
+ {
+ input.next_token();
+ // If this is a phandle then we need to get the name of the
+ // referenced node
+ if (input.consume('&'))
+ {
+ if (cell_size != 32)
+ {
+ input.parse_error("reference only permitted in 32-bit arrays");
+ valid = false;
+ return;
+ }
+ input.next_token();
+ string referenced;
+ if (!input.consume('{'))
+ {
+ referenced = input.parse_node_name();
+ }
+ else
+ {
+ referenced = input.parse_to('}');
+ input.consume('}');
+ }
+ if (referenced.empty())
+ {
+ input.parse_error("Expected node name");
+ valid = false;
+ return;
+ }
+ input.next_token();
+ // If we already have some bytes, make the phandle a
+ // separate component.
+ if (!v.byte_data.empty())
+ {
+ values.push_back(v);
+ v = property_value();
+ }
+ v.string_data = referenced;
+ v.type = property_value::PHANDLE;
+ values.push_back(v);
+ v = property_value();
+ }
+ else
+ {
+ //FIXME: We should support labels in the middle
+ //of these, but we don't.
+ unsigned long long val;
+ if (!input.consume_integer_expression(val))
+ {
+ // FIXME: Distinguish invalid syntax from a
+ // number that cannot be represented in an
+ // unsigned long long.
+ input.parse_error("Expected numbers in array of cells");
+ valid = false;
+ return;
+ }
+ // FIXME: No sign information available, so cannot
+ // distinguish small negative values from large
+ // positive ones, and thus we have to conservatively
+ // permit anything that looks like a sign-extended
+ // negative integer.
+ if (cell_size < 64 && val >= (1ull << cell_size) &&
+ (val | ((1ull << (cell_size - 1)) - 1)) !=
+ std::numeric_limits<unsigned long long>::max())
+ {
+ std::string msg = "Value does not fit in a " +
+ std::to_string(cell_size) + "-bit cell";
+ input.parse_error(msg.c_str());
+ valid = false;
+ return;
+ }
+ switch (cell_size)
+ {
+ case 8:
+ v.byte_data.push_back(val);
+ break;
+ case 16:
+ push_big_endian(v.byte_data, (uint16_t)val);
+ break;
+ case 32:
+ push_big_endian(v.byte_data, (uint32_t)val);
+ break;
+ case 64:
+ push_big_endian(v.byte_data, (uint64_t)val);
+ break;
+ default:
+ assert(0 && "Invalid cell size!");
+ }
+ input.next_token();
+ }
+ }
+ // Don't store an empty string value here.
+ if (v.byte_data.size() > 0)
+ {
+ values.push_back(v);
+ }
+}
+
+void
+property::parse_bytes(text_input_buffer &input)
+{
+ assert(*input == '[');
+ ++input;
+ property_value v;
+ input.next_token();
+ while (!input.consume(']'))
+ {
+ {
+ //FIXME: We should support
+ //labels in the middle of
+ //these, but we don't.
+ uint8_t val;
+ if (!input.consume_hex_byte(val))
+ {
+ input.parse_error("Expected hex bytes in array of bytes");
+ valid = false;
+ return;
+ }
+ v.byte_data.push_back(val);
+ input.next_token();
+ }
+ }
+ values.push_back(v);
+}
+
+void
+property::parse_reference(text_input_buffer &input)
+{
+ assert(*input == '&');
+ ++input;
+ input.next_token();
+ property_value v;
+ v.string_data = input.parse_node_name();
+ if (v.string_data.empty())
+ {
+ input.parse_error("Expected node name");
+ valid = false;
+ return;
+ }
+ v.type = property_value::CROSS_REFERENCE;
+ values.push_back(v);
+}
+
+property::property(input_buffer &structs, input_buffer &strings)
+{
+ uint32_t name_offset;
+ uint32_t length;
+ valid = structs.consume_binary(length) &&
+ structs.consume_binary(name_offset);
+ if (!valid)
+ {
+ fprintf(stderr, "Failed to read property\n");
+ return;
+ }
+ // Find the name
+ input_buffer name_buffer = strings.buffer_from_offset(name_offset);
+ if (name_buffer.finished())
+ {
+ fprintf(stderr, "Property name offset %" PRIu32
+ " is past the end of the strings table\n",
+ name_offset);
+ valid = false;
+ return;
+ }
+ key = name_buffer.parse_to(0);
+
+ // If we're empty, do not push anything as value.
+ if (!length)
+ return;
+
+ // Read the value
+ uint8_t byte;
+ property_value v;
+ for (uint32_t i=0 ; i<length ; i++)
+ {
+ if (!(valid = structs.consume_binary(byte)))
+ {
+ fprintf(stderr, "Failed to read property value\n");
+ return;
+ }
+ v.byte_data.push_back(byte);
+ }
+ values.push_back(v);
+}
+
+void property::parse_define(text_input_buffer &input, define_map *defines)
+{
+ input.consume('$');
+ if (!defines)
+ {
+ input.parse_error("No predefined properties to match name\n");
+ valid = false;
+ return;
+ }
+ string name = input.parse_property_name();
+ define_map::iterator found;
+ if ((name == string()) ||
+ ((found = defines->find(name)) == defines->end()))
+ {
+ input.parse_error("Undefined property name\n");
+ valid = false;
+ return;
+ }
+ values.push_back((*found).second->values[0]);
+}
+
+property::property(text_input_buffer &input,
+ string &&k,
+ string_set &&l,
+ bool semicolonTerminated,
+ define_map *defines) : key(k), labels(l), valid(true)
+{
+ do {
+ input.next_token();
+ switch (*input)
+ {
+ case '$':
+ {
+ parse_define(input, defines);
+ if (valid)
+ {
+ break;
+ }
+ }
+ [[fallthrough]];
+ default:
+ input.parse_error("Invalid property value.");
+ valid = false;
+ return;
+ case '/':
+ {
+ if (input.consume("/incbin/(\""))
+ {
+ auto loc = input.location();
+ std::string filename = input.parse_to('"');
+ if (!(valid = input.consume('"')))
+ {
+ loc.report_error("Syntax error, expected '\"' to terminate /incbin/(");
+ return;
+ }
+ property_value v;
+ if (!(valid = input.read_binary_file(filename, v.byte_data)))
+ {
+ input.parse_error("Cannot open binary include file");
+ return;
+ }
+ if (!(valid &= input.consume(')')))
+ {
+ input.parse_error("Syntax error, expected ')' to terminate /incbin/(");
+ return;
+ }
+ values.push_back(v);
+ break;
+ }
+ unsigned long long bits = 0;
+ valid = input.consume("/bits/");
+ input.next_token();
+ valid &= input.consume_integer(bits);
+ if ((bits != 8) &&
+ (bits != 16) &&
+ (bits != 32) &&
+ (bits != 64)) {
+ input.parse_error("Invalid size for elements");
+ valid = false;
+ }
+ if (!valid) return;
+ input.next_token();
+ if (*input != '<')
+ {
+ input.parse_error("/bits/ directive is only valid on arrays");
+ valid = false;
+ return;
+ }
+ parse_cells(input, bits);
+ break;
+ }
+ case '"':
+ parse_string(input);
+ break;
+ case '<':
+ parse_cells(input, 32);
+ break;
+ case '[':
+ parse_bytes(input);
+ break;
+ case '&':
+ parse_reference(input);
+ break;
+ case ';':
+ {
+ break;
+ }
+ }
+ input.next_token();
+ } while (input.consume(','));
+ if (semicolonTerminated && !input.consume(';'))
+ {
+ input.parse_error("Expected ; at end of property");
+ valid = false;
+ }
+}
+
+property_ptr
+property::parse_dtb(input_buffer &structs, input_buffer &strings)
+{
+ property_ptr p(new property(structs, strings));
+ if (!p->valid)
+ {
+ p = nullptr;
+ }
+ return p;
+}
+
+property_ptr
+property::parse(text_input_buffer &input, string &&key, string_set &&label,
+ bool semicolonTerminated, define_map *defines)
+{
+ property_ptr p(new property(input,
+ std::move(key),
+ std::move(label),
+ semicolonTerminated,
+ defines));
+ if (!p->valid)
+ {
+ p = nullptr;
+ }
+ return p;
+}
+
+void
+property::write(dtb::output_writer &writer, dtb::string_table &strings)
+{
+ writer.write_token(dtb::FDT_PROP);
+ byte_buffer value_buffer;
+ for (value_iterator i=begin(), e=end() ; i!=e ; ++i)
+ {
+ i->push_to_buffer(value_buffer);
+ }
+ writer.write_data((uint32_t)value_buffer.size());
+ writer.write_comment(key);
+ writer.write_data(strings.add_string(key));
+ writer.write_data(value_buffer);
+}
+
+bool
+property_value::try_to_merge(property_value &other)
+{
+ resolve_type();
+ switch (type)
+ {
+ case UNKNOWN:
+ __builtin_unreachable();
+ assert(0);
+ return false;
+ case EMPTY:
+ *this = other;
+ [[fallthrough]];
+ case STRING:
+ case STRING_LIST:
+ case CROSS_REFERENCE:
+ return false;
+ case PHANDLE:
+ case BINARY:
+ if (other.type == PHANDLE || other.type == BINARY)
+ {
+ type = BINARY;
+ byte_data.insert(byte_data.end(), other.byte_data.begin(),
+ other.byte_data.end());
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+property::write_dts(FILE *file, int indent)
+{
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+#ifdef PRINT_LABELS
+ for (auto &l : labels)
+ {
+ fputs(l.c_str(), file);
+ fputs(": ", file);
+ }
+#endif
+ if (key != string())
+ {
+ fputs(key.c_str(), file);
+ }
+ if (!values.empty())
+ {
+ std::vector<property_value> *vals = &values;
+ std::vector<property_value> v;
+ // If we've got multiple values then try to merge them all together.
+ if (values.size() > 1)
+ {
+ vals = &v;
+ v.push_back(values.front());
+ for (auto i=(++begin()), e=end() ; i!=e ; ++i)
+ {
+ if (!v.back().try_to_merge(*i))
+ {
+ v.push_back(*i);
+ }
+ }
+ }
+ fputs(" = ", file);
+ for (auto i=vals->begin(), e=vals->end() ; i!=e ; ++i)
+ {
+ i->write_dts(file);
+ if (i+1 != e)
+ {
+ putc(',', file);
+ putc(' ', file);
+ }
+ }
+ }
+ fputs(";\n", file);
+}
+
+size_t
+property::offset_of_value(property_value &val)
+{
+ size_t off = 0;
+ for (auto &v : values)
+ {
+ if (&v == &val)
+ {
+ return off;
+ }
+ off += v.size();
+ }
+ return -1;
+}
+
+string
+node::parse_name(text_input_buffer &input, bool &is_property, const char *error)
+{
+ if (!valid)
+ {
+ return string();
+ }
+ input.next_token();
+ if (is_property)
+ {
+ return input.parse_property_name();
+ }
+ string n = input.parse_node_or_property_name(is_property);
+ if (n.empty())
+ {
+ if (n.empty())
+ {
+ input.parse_error(error);
+ valid = false;
+ }
+ }
+ return n;
+}
+
+node::visit_behavior
+node::visit(std::function<visit_behavior(node&, node*)> fn, node *parent)
+{
+ visit_behavior behavior;
+ behavior = fn(*this, parent);
+ if (behavior == VISIT_BREAK)
+ {
+ return VISIT_BREAK;
+ }
+ else if (behavior != VISIT_CONTINUE)
+ {
+ for (auto &&c : children)
+ {
+ behavior = c->visit(fn, this);
+ // Any status other than VISIT_RECURSE stops our execution and
+ // bubbles up to our caller. The caller may then either continue
+ // visiting nodes that are siblings to this one or completely halt
+ // visiting.
+ if (behavior != VISIT_RECURSE)
+ {
+ return behavior;
+ }
+ }
+ }
+ // Continue recursion by default
+ return VISIT_RECURSE;
+}
+
+node::node(input_buffer &structs, input_buffer &strings) : valid(true)
+{
+ std::vector<char> bytes;
+ while (structs[0] != '\0' && structs[0] != '@')
+ {
+ bytes.push_back(structs[0]);
+ ++structs;
+ }
+ name = string(bytes.begin(), bytes.end());
+ bytes.clear();
+ if (structs[0] == '@')
+ {
+ ++structs;
+ while (structs[0] != '\0')
+ {
+ bytes.push_back(structs[0]);
+ ++structs;
+ }
+ unit_address = string(bytes.begin(), bytes.end());
+ }
+ ++structs;
+ uint32_t token;
+ while (structs.consume_binary(token))
+ {
+ switch (token)
+ {
+ default:
+ fprintf(stderr, "Unexpected token 0x%" PRIx32
+ " while parsing node.\n", token);
+ valid = false;
+ return;
+ // Child node, parse it.
+ case dtb::FDT_BEGIN_NODE:
+ {
+ node_ptr child = node::parse_dtb(structs, strings);
+ if (child == 0)
+ {
+ valid = false;
+ return;
+ }
+ children.push_back(std::move(child));
+ break;
+ }
+ // End of this node, no errors.
+ case dtb::FDT_END_NODE:
+ return;
+ // Property, parse it.
+ case dtb::FDT_PROP:
+ {
+ property_ptr prop = property::parse_dtb(structs, strings);
+ if (prop == 0)
+ {
+ valid = false;
+ return;
+ }
+ props.push_back(prop);
+ break;
+ }
+ break;
+ // End of structs table. Should appear after
+ // the end of the last node.
+ case dtb::FDT_END:
+ fprintf(stderr, "Unexpected FDT_END token while parsing node.\n");
+ valid = false;
+ return;
+ // NOPs are padding. Ignore them.
+ case dtb::FDT_NOP:
+ break;
+ }
+ }
+ fprintf(stderr, "Failed to read token from structs table while parsing node.\n");
+ valid = false;
+ return;
+}
+
+
+node::node(const string &n,
+ const std::vector<property_ptr> &p)
+ : name(n)
+{
+ props.insert(props.begin(), p.begin(), p.end());
+}
+
+node_ptr node::create_special_node(const string &name,
+ const std::vector<property_ptr> &props)
+{
+ // Work around for the fact that we can't call make_shared on something
+ // with a private constructor. Instead create a subclass with a public
+ // constructor that is visible only in this function and construct that
+ // instead.
+ struct constructable_node : public node
+ {
+ constructable_node(const string &n, const std::vector<property_ptr> &p) : node(n, p) {}
+ };
+ node_ptr n{std::make_shared<constructable_node>(name, props)};
+ return n;
+}
+
+node::node(text_input_buffer &input,
+ device_tree &tree,
+ string &&n,
+ std::unordered_set<string> &&l,
+ string &&a,
+ define_map *defines)
+ : labels(l), name(n), unit_address(a), valid(true)
+{
+ if (!input.consume('{'))
+ {
+ input.parse_error("Expected { to start new device tree node.\n");
+ }
+ input.next_token();
+ while (valid && !input.consume('}'))
+ {
+ // flag set if we find any characters that are only in
+ // the property name character set, not the node
+ bool is_property = false;
+ // flag set if our node is marked as /omit-if-no-ref/ to be
+ // garbage collected later if nothing references it
+ bool marked_omit_if_no_ref = false;
+ string child_name, child_address;
+ std::unordered_set<string> child_labels;
+ auto parse_delete = [&](const char *expected, bool at)
+ {
+ if (child_name == string())
+ {
+ input.parse_error(expected);
+ valid = false;
+ return;
+ }
+ input.next_token();
+ if (at && input.consume('@'))
+ {
+ child_name += '@';
+ child_name += parse_name(input, is_property, "Expected unit address");
+ }
+ if (!input.consume(';'))
+ {
+ input.parse_error("Expected semicolon");
+ valid = false;
+ return;
+ }
+ input.next_token();
+ };
+ if (input.consume("/delete-node/"))
+ {
+ input.next_token();
+ child_name = input.parse_node_name();
+ parse_delete("Expected node name", true);
+ if (valid)
+ {
+ deleted_children.insert(child_name);
+ }
+ continue;
+ }
+ if (input.consume("/delete-property/"))
+ {
+ input.next_token();
+ child_name = input.parse_property_name();
+ parse_delete("Expected property name", false);
+ if (valid)
+ {
+ deleted_props.insert(child_name);
+ }
+ continue;
+ }
+ if (input.consume("/omit-if-no-ref/"))
+ {
+ input.next_token();
+ marked_omit_if_no_ref = true;
+ tree.set_needs_garbage_collection();
+ }
+ child_name = parse_name(input, is_property,
+ "Expected property or node name");
+ while (input.consume(':'))
+ {
+ // Node labels can contain any characters? The
+ // spec doesn't say, so we guess so...
+ is_property = false;
+ child_labels.insert(std::move(child_name));
+ child_name = parse_name(input, is_property, "Expected property or node name");
+ }
+ if (input.consume('@'))
+ {
+ child_address = parse_name(input, is_property, "Expected unit address");
+ }
+ if (!valid)
+ {
+ return;
+ }
+ input.next_token();
+ // If we're parsing a property, then we must actually do that.
+ if (input.consume('='))
+ {
+ property_ptr p = property::parse(input, std::move(child_name),
+ std::move(child_labels), true, defines);
+ if (p == 0)
+ {
+ valid = false;
+ }
+ else
+ {
+ props.push_back(p);
+ }
+ }
+ else if (!is_property && *input == ('{'))
+ {
+ node_ptr child = node::parse(input, tree, std::move(child_name),
+ std::move(child_labels), std::move(child_address), defines);
+ if (child)
+ {
+ child->omit_if_no_ref = marked_omit_if_no_ref;
+ children.push_back(std::move(child));
+ }
+ else
+ {
+ valid = false;
+ }
+ }
+ else if (input.consume(';'))
+ {
+ props.push_back(property_ptr(new property(std::move(child_name), std::move(child_labels))));
+ }
+ else
+ {
+ input.parse_error("Error parsing property. Expected property value");
+ valid = false;
+ }
+ input.next_token();
+ }
+ input.next_token();
+ input.consume(';');
+}
+
+bool
+node::cmp_properties(property_ptr &p1, property_ptr &p2)
+{
+ return p1->get_key() < p2->get_key();
+}
+
+bool
+node::cmp_children(node_ptr &c1, node_ptr &c2)
+{
+ if (c1->name == c2->name)
+ {
+ return c1->unit_address < c2->unit_address;
+ }
+ return c1->name < c2->name;
+}
+
+void
+node::sort()
+{
+ std::sort(property_begin(), property_end(), cmp_properties);
+ std::sort(child_begin(), child_end(), cmp_children);
+ for (auto &c : child_nodes())
+ {
+ c->sort();
+ }
+}
+
+node_ptr
+node::parse(text_input_buffer &input,
+ device_tree &tree,
+ string &&name,
+ string_set &&label,
+ string &&address,
+ define_map *defines)
+{
+ // Work around for the fact that we can't call make_shared on something
+ // with a private constructor. Instead create a subclass with a public
+ // constructor that is visible only in this function and construct that
+ // instead.
+ struct constructable_node : public node
+ {
+ constructable_node(text_input_buffer &input,
+ device_tree &tree,
+ std::string &&n,
+ std::unordered_set<std::string> &&l,
+ std::string &&a,
+ define_map*m) : node(input,
+ tree,
+ std::move(n),
+ std::move(l),
+ std::move(a),
+ m)
+ {}
+ };
+ node_ptr n{std::make_shared<constructable_node>(input,
+ tree,
+ std::move(name),
+ std::move(label),
+ std::move(address),
+ defines)};
+ if (!n->valid)
+ {
+ n = 0;
+ }
+ return n;
+}
+
+node_ptr
+node::parse_dtb(input_buffer &structs, input_buffer &strings)
+{
+ node_ptr n(new node(structs, strings));
+ if (!n->valid)
+ {
+ n = 0;
+ }
+ return n;
+}
+
+property_ptr
+node::get_property(const string &key)
+{
+ for (auto &i : props)
+ {
+ if (i->get_key() == key)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+void
+node::merge_node(node_ptr &other)
+{
+ for (auto &l : other->labels)
+ {
+ labels.insert(l);
+ }
+ children.erase(std::remove_if(children.begin(), children.end(),
+ [&](const node_ptr &p) {
+ string full_name = p->name;
+ if (p->unit_address != string())
+ {
+ full_name += '@';
+ full_name += p->unit_address;
+ }
+ if (other->deleted_children.count(full_name) > 0)
+ {
+ other->deleted_children.erase(full_name);
+ return true;
+ }
+ return false;
+ }), children.end());
+ props.erase(std::remove_if(props.begin(), props.end(),
+ [&](const property_ptr &p) {
+ if (other->deleted_props.count(p->get_key()) > 0)
+ {
+ other->deleted_props.erase(p->get_key());
+ return true;
+ }
+ return false;
+ }), props.end());
+ // Note: this is an O(n*m) operation. It might be sensible to
+ // optimise this if we find that there are nodes with very
+ // large numbers of properties, but for typical usage the
+ // entire vector will fit (easily) into cache, so iterating
+ // over it repeatedly isn't that expensive.
+ for (auto &p : other->properties())
+ {
+ bool found = false;
+ for (auto &mp : properties())
+ {
+ if (mp->get_key() == p->get_key())
+ {
+ mp = p;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ add_property(p);
+ }
+ }
+ for (auto &c : other->children)
+ {
+ bool found = false;
+ for (auto &i : children)
+ {
+ if (i->name == c->name && i->unit_address == c->unit_address)
+ {
+ i->merge_node(c);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ children.push_back(std::move(c));
+ }
+ }
+}
+
+void
+node::write(dtb::output_writer &writer, dtb::string_table &strings)
+{
+ writer.write_token(dtb::FDT_BEGIN_NODE);
+ byte_buffer name_buffer;
+ push_string(name_buffer, name);
+ if (unit_address != string())
+ {
+ name_buffer.push_back('@');
+ push_string(name_buffer, unit_address);
+ }
+ writer.write_comment(name);
+ writer.write_data(name_buffer);
+ writer.write_data((uint8_t)0);
+ for (auto p : properties())
+ {
+ p->write(writer, strings);
+ }
+ for (auto &c : child_nodes())
+ {
+ c->write(writer, strings);
+ }
+ writer.write_token(dtb::FDT_END_NODE);
+}
+
+void
+node::write_dts(FILE *file, int indent)
+{
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+#ifdef PRINT_LABELS
+ for (auto &label : labels)
+ {
+ fprintf(file, "%s: ", label.c_str());
+ }
+#endif
+ if (name != string())
+ {
+ fputs(name.c_str(), file);
+ }
+ if (unit_address != string())
+ {
+ putc('@', file);
+ fputs(unit_address.c_str(), file);
+ }
+ fputs(" {\n\n", file);
+ for (auto p : properties())
+ {
+ p->write_dts(file, indent+1);
+ }
+ for (auto &c : child_nodes())
+ {
+ c->write_dts(file, indent+1);
+ }
+ for (int i=0 ; i<indent ; i++)
+ {
+ putc('\t', file);
+ }
+ fputs("};\n", file);
+}
+
+void
+device_tree::collect_names_recursive(node_ptr parent, node_ptr n, node_path &path)
+{
+ path.push_back(std::make_pair(n->name, n->unit_address));
+ for (const string &name : n->labels)
+ {
+ if (name != string())
+ {
+ auto iter = node_names.find(name);
+ if (iter == node_names.end())
+ {
+ node_names.insert(std::make_pair(name, n));
+ node_paths.insert(std::make_pair(name, path));
+ ordered_node_paths.push_back({name, path});
+ if (parent)
+ {
+ node_name_parents.insert({name, parent});
+ }
+ }
+ else
+ {
+ node_names.erase(iter);
+ auto i = node_paths.find(name);
+ if (i != node_paths.end())
+ {
+ node_paths.erase(name);
+ }
+ fprintf(stderr, "Label not unique: %s. References to this label will not be resolved.\n", name.c_str());
+ }
+ }
+ }
+ for (auto &c : n->child_nodes())
+ {
+ collect_names_recursive(n, c, path);
+ }
+ // Now we collect the phandles and properties that reference
+ // other nodes.
+ for (auto &p : n->properties())
+ {
+ for (auto &v : *p)
+ {
+ if (v.is_phandle())
+ {
+ fixups.push_back({path, p, v});
+ }
+ if (v.is_cross_reference())
+ {
+ cross_references.push_back(&v);
+ }
+ }
+ if ((p->get_key() == "phandle") ||
+ (p->get_key() == "linux,phandle"))
+ {
+ if (p->begin()->byte_data.size() != 4)
+ {
+ fprintf(stderr, "Invalid phandle value for node %s. Should be a 4-byte value.\n", n->name.c_str());
+ valid = false;
+ }
+ else
+ {
+ uint32_t phandle = p->begin()->get_as_uint32();
+ used_phandles.insert(std::make_pair(phandle, n));
+ }
+ }
+ }
+ path.pop_back();
+}
+
+void
+device_tree::collect_names()
+{
+ node_path p;
+ node_names.clear();
+ node_paths.clear();
+ ordered_node_paths.clear();
+ cross_references.clear();
+ fixups.clear();
+ collect_names_recursive(nullptr, root, p);
+}
+
+property_ptr
+device_tree::assign_phandle(node_ptr n, uint32_t &phandle)
+{
+ // If there is an existing phandle, use it
+ property_ptr p = n->get_property("phandle");
+ if (p == 0)
+ {
+ p = n->get_property("linux,phandle");
+ }
+ if (p == 0)
+ {
+ // Otherwise insert a new phandle node
+ property_value v;
+ while (used_phandles.find(phandle) != used_phandles.end())
+ {
+ // Note that we only don't need to
+ // store this phandle in the set,
+ // because we are monotonically
+ // increasing the value of phandle and
+ // so will only ever revisit this value
+ // if we have used 2^32 phandles, at
+ // which point our blob won't fit in
+ // any 32-bit system and we've done
+ // something badly wrong elsewhere
+ // already.
+ phandle++;
+ }
+ push_big_endian(v.byte_data, phandle++);
+ if (phandle_node_name == BOTH || phandle_node_name == LINUX)
+ {
+ p.reset(new property("linux,phandle"));
+ p->add_value(v);
+ n->add_property(p);
+ }
+ if (phandle_node_name == BOTH || phandle_node_name == EPAPR)
+ {
+ p.reset(new property("phandle"));
+ p->add_value(v);
+ n->add_property(p);
+ }
+ }
+
+ return (p);
+}
+
+void
+device_tree::assign_phandles(node_ptr n, uint32_t &next)
+{
+ if (!n->labels.empty())
+ {
+ assign_phandle(n, next);
+ }
+
+ for (auto &c : n->child_nodes())
+ {
+ assign_phandles(c, next);
+ }
+}
+
+void
+device_tree::resolve_cross_references(uint32_t &phandle)
+{
+ for (auto *pv : cross_references)
+ {
+ node_path path = node_paths[pv->string_data];
+ auto p = path.begin();
+ auto pe = path.end();
+ if (p != pe)
+ {
+ // Skip the first name in the path. It's always "", and implicitly /
+ for (++p ; p!=pe ; ++p)
+ {
+ pv->byte_data.push_back('/');
+ push_string(pv->byte_data, p->first);
+ if (!(p->second.empty()))
+ {
+ pv->byte_data.push_back('@');
+ push_string(pv->byte_data, p->second);
+ }
+ }
+ pv->byte_data.push_back(0);
+ }
+ }
+ std::unordered_map<property_value*, fixup&> phandle_set;
+ for (auto &i : fixups)
+ {
+ phandle_set.insert({&i.val, i});
+ }
+ std::vector<std::reference_wrapper<fixup>> sorted_phandles;
+ root->visit([&](node &n, node *) {
+ for (auto &p : n.properties())
+ {
+ for (auto &v : *p)
+ {
+ auto i = phandle_set.find(&v);
+ if (i != phandle_set.end())
+ {
+ sorted_phandles.push_back(i->second);
+ }
+ }
+ }
+ // Allow recursion
+ return node::VISIT_RECURSE;
+ }, nullptr);
+ assert(sorted_phandles.size() == fixups.size());
+ for (auto &i : sorted_phandles)
+ {
+ string target_name = i.get().val.string_data;
+ node_ptr target;
+ string possible;
+ // If the node name is a path, then look it up by following the path,
+ // otherwise jump directly to the named node.
+ if (target_name[0] == '/')
+ {
+ string path;
+ target = root;
+ std::istringstream ss(target_name);
+ string path_element;
+ // Read the leading /
+ std::getline(ss, path_element, '/');
+ // Iterate over path elements
+ while (!ss.eof())
+ {
+ path += '/';
+ std::getline(ss, path_element, '/');
+ std::istringstream nss(path_element);
+ string node_name, node_address;
+ std::getline(nss, node_name, '@');
+ std::getline(nss, node_address, '@');
+ node_ptr next;
+ for (auto &c : target->child_nodes())
+ {
+ if (c->name == node_name)
+ {
+ if (c->unit_address == node_address)
+ {
+ next = c;
+ break;
+ }
+ else
+ {
+ possible = path + c->name;
+ if (c->unit_address != string())
+ {
+ possible += '@';
+ possible += c->unit_address;
+ }
+ }
+ }
+ }
+ path += node_name;
+ if (node_address != string())
+ {
+ path += '@';
+ path += node_address;
+ }
+ target = next;
+ if (target == nullptr)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ target = node_names[target_name];
+ }
+ if (target == nullptr)
+ {
+ if (is_plugin)
+ {
+ unresolved_fixups.push_back(i);
+ continue;
+ }
+ else
+ {
+ fprintf(stderr, "Failed to find node with label: %s\n", target_name.c_str());
+ if (possible != string())
+ {
+ fprintf(stderr, "Possible intended match: %s\n", possible.c_str());
+ }
+ valid = 0;
+ return;
+ }
+ }
+ // If there is an existing phandle, use it
+ property_ptr p = assign_phandle(target, phandle);
+ p->begin()->push_to_buffer(i.get().val.byte_data);
+ assert(i.get().val.byte_data.size() == 4);
+ }
+}
+
+bool
+device_tree::garbage_collect_marked_nodes()
+{
+ std::unordered_set<node_ptr> previously_referenced_nodes;
+ std::unordered_set<node_ptr> newly_referenced_nodes;
+
+ auto mark_referenced_nodes_used = [&](node &n)
+ {
+ for (auto &p : n.properties())
+ {
+ for (auto &v : *p)
+ {
+ if (v.is_phandle())
+ {
+ node_ptr nx = node_names[v.string_data];
+ if (nx == nullptr)
+ {
+ // Try it again, but as a path
+ for (auto &s : node_paths)
+ {
+ if (v.string_data == s.second.to_string())
+ {
+ nx = node_names[s.first];
+ break;
+ }
+ }
+ }
+ if (nx == nullptr)
+ {
+ // Couldn't resolve this one?
+ continue;
+ }
+ // Only mark those currently unmarked
+ if (!nx->used)
+ {
+ nx->used = 1;
+ newly_referenced_nodes.insert(nx);
+ }
+ }
+ }
+ }
+ };
+
+ // Seed our referenced nodes with those that have been seen by a node that
+ // either will not be omitted if it's unreferenced or has a symbol.
+ // Nodes with symbols are explicitly not garbage collected because they may
+ // be expected for referencing by an overlay, and we do not want surprises
+ // there.
+ root->visit([&](node &n, node *) {
+ if (!n.omit_if_no_ref || (write_symbols && !n.labels.empty()))
+ {
+ mark_referenced_nodes_used(n);
+ }
+ // Recurse as normal
+ return node::VISIT_RECURSE;
+ }, nullptr);
+
+ while (!newly_referenced_nodes.empty())
+ {
+ previously_referenced_nodes = newly_referenced_nodes;
+ newly_referenced_nodes.clear();
+ for (auto &n : previously_referenced_nodes)
+ {
+ mark_referenced_nodes_used(*n);
+ }
+ }
+
+ previously_referenced_nodes.clear();
+ bool children_deleted = false;
+
+ // Delete
+ root->visit([&](node &n, node *) {
+ bool gc_children = false;
+
+ for (auto &cn : n.child_nodes())
+ {
+ if (cn->omit_if_no_ref && !cn->used)
+ {
+ gc_children = true;
+ break;
+ }
+ }
+
+ if (gc_children)
+ {
+ children_deleted = true;
+ n.delete_children_if([](node_ptr &nx) {
+ return (nx->omit_if_no_ref && !nx->used);
+ });
+
+ return node::VISIT_CONTINUE;
+ }
+
+ return node::VISIT_RECURSE;
+ }, nullptr);
+
+ return children_deleted;
+}
+
+void
+device_tree::parse_file(text_input_buffer &input,
+ std::vector<node_ptr> &roots,
+ bool &read_header)
+{
+ input.next_token();
+ // Read the header
+ while (input.consume("/dts-v1/;"))
+ {
+ read_header = true;
+ input.next_token();
+ }
+ if (input.consume("/plugin/;"))
+ {
+ is_plugin = true;
+ }
+ input.next_token();
+ if (!read_header)
+ {
+ input.parse_error("Expected /dts-v1/; version string");
+ }
+ // Read any memory reservations
+ while (input.consume("/memreserve/"))
+ {
+ unsigned long long start, len;
+ input.next_token();
+ // Read the start and length.
+ if (!(input.consume_integer_expression(start) &&
+ (input.next_token(),
+ input.consume_integer_expression(len))))
+ {
+ input.parse_error("Expected size on /memreserve/ node.");
+ }
+ else
+ {
+ reservations.push_back(reservation(start, len));
+ }
+ input.next_token();
+ input.consume(';');
+ input.next_token();
+ }
+ while (valid && !input.finished())
+ {
+ node_ptr n;
+ if (input.consume("/delete-node/"))
+ {
+ // Top-level /delete-node/ directives refer to references that must
+ // be deleted later.
+ input.next_token();
+ auto expect = [&](auto token, const char *msg)
+ {
+ if (!input.consume(token))
+ {
+ input.parse_error(msg);
+ valid = false;
+ }
+ input.next_token();
+ return valid;
+ };
+ if (expect('&', "Expected reference after top-level /delete-node/."))
+ {
+ string ref = input.parse_node_name();
+ if (ref == string())
+ {
+ input.parse_error("Expected label name for top-level /delete-node/.");
+ valid = false;
+ }
+ else
+ {
+ deletions.push_back(std::move(ref));
+ }
+ expect(';', "Missing semicolon.");
+ }
+ continue;
+ }
+ else if (input.consume('/'))
+ {
+ input.next_token();
+ n = node::parse(input, *this, string(), string_set(), string(), &defines);
+ }
+ else if (input.consume('&'))
+ {
+ input.next_token();
+ string name;
+ bool name_is_path_reference = false;
+ // This is to deal with names intended as path references, e.g. &{/path}.
+ // While it may make sense in a non-plugin context, we don't support such
+ // usage at this time.
+ if (input.consume('{') && is_plugin)
+ {
+ name = input.parse_to('}');
+ input.consume('}');
+ name_is_path_reference = true;
+ }
+ else
+ {
+ name = input.parse_node_name();
+ }
+ input.next_token();
+ n = node::parse(input, *this, std::move(name), string_set(), string(), &defines);
+ if (n)
+ {
+ n->name_is_path_reference = name_is_path_reference;
+ }
+ }
+ else
+ {
+ input.parse_error("Failed to find root node /.");
+ }
+ if (n)
+ {
+ roots.push_back(std::move(n));
+ }
+ else
+ {
+ valid = false;
+ }
+ input.next_token();
+ }
+}
+
+template<class writer> void
+device_tree::write(int fd)
+{
+ dtb::string_table st;
+ dtb::header head;
+ writer head_writer;
+ writer reservation_writer;
+ writer struct_writer;
+ writer strings_writer;
+
+ // Build the reservation table
+ reservation_writer.write_comment(string("Memory reservations"));
+ reservation_writer.write_label(string("dt_reserve_map"));
+ for (auto &i : reservations)
+ {
+ reservation_writer.write_comment(string("Reservation start"));
+ reservation_writer.write_data(i.first);
+ reservation_writer.write_comment(string("Reservation length"));
+ reservation_writer.write_data(i.second);
+ }
+ // Write n spare reserve map entries, plus the trailing 0.
+ for (uint32_t i=0 ; i<=spare_reserve_map_entries ; i++)
+ {
+ reservation_writer.write_data((uint64_t)0);
+ reservation_writer.write_data((uint64_t)0);
+ }
+
+
+ struct_writer.write_comment(string("Device tree"));
+ struct_writer.write_label(string("dt_struct_start"));
+ root->write(struct_writer, st);
+ struct_writer.write_token(dtb::FDT_END);
+ struct_writer.write_label(string("dt_struct_end"));
+
+ st.write(strings_writer);
+ // Find the strings size before we stick padding on the end.
+ // Note: We should possibly use a new writer for the padding.
+ head.size_dt_strings = strings_writer.size();
+
+ // Stick the padding in the strings writer, but after the
+ // marker indicating that it's the end.
+ // Note: We probably should add a padding call to the writer so
+ // that the asm back end can write padding directives instead
+ // of a load of 0 bytes.
+ for (uint32_t i=0 ; i<blob_padding ; i++)
+ {
+ strings_writer.write_data((uint8_t)0);
+ }
+ head.totalsize = sizeof(head) + strings_writer.size() +
+ struct_writer.size() + reservation_writer.size();
+ while (head.totalsize < minimum_blob_size)
+ {
+ head.totalsize++;
+ strings_writer.write_data((uint8_t)0);
+ }
+ head.off_dt_struct = sizeof(head) + reservation_writer.size();;
+ head.off_dt_strings = head.off_dt_struct + struct_writer.size();
+ head.off_mem_rsvmap = sizeof(head);
+ head.boot_cpuid_phys = boot_cpu;
+ head.size_dt_struct = struct_writer.size();
+ head.write(head_writer);
+
+ head_writer.write_to_file(fd);
+ reservation_writer.write_to_file(fd);
+ struct_writer.write_to_file(fd);
+ strings_writer.write_label(string("dt_blob_end"));
+ strings_writer.write_to_file(fd);
+}
+
+node_ptr
+device_tree::referenced_node(property_value &v)
+{
+ if (v.is_phandle())
+ {
+ return node_names[v.string_data];
+ }
+ if (v.is_binary())
+ {
+ return used_phandles[v.get_as_uint32()];
+ }
+ return 0;
+}
+
+void
+device_tree::write_binary(int fd)
+{
+ write<dtb::binary_writer>(fd);
+}
+
+void
+device_tree::write_asm(int fd)
+{
+ write<dtb::asm_writer>(fd);
+}
+
+void
+device_tree::write_dts(int fd)
+{
+ FILE *file = fdopen(fd, "w");
+ fputs("/dts-v1/;\n\n", file);
+
+ if (!reservations.empty())
+ {
+ const char msg[] = "/memreserve/";
+ // Exclude the null byte when we're writing it out to the file.
+ fwrite(msg, sizeof(msg) - 1, 1, file);
+ for (auto &i : reservations)
+ {
+ fprintf(file, " 0x%" PRIx64 " 0x%" PRIx64, i.first, i.second);
+ }
+ fputs(";\n\n", file);
+ }
+ putc('/', file);
+ putc(' ', file);
+ root->write_dts(file, 0);
+ fclose(file);
+}
+
+void
+device_tree::parse_dtb(const string &fn, FILE *)
+{
+ auto in = input_buffer::buffer_for_file(fn);
+ if (in == 0)
+ {
+ valid = false;
+ return;
+ }
+ input_buffer &input = *in;
+ dtb::header h;
+ valid = h.read_dtb(input);
+ boot_cpu = h.boot_cpuid_phys;
+ if (h.last_comp_version > 17)
+ {
+ fprintf(stderr, "Don't know how to read this version of the device tree blob");
+ valid = false;
+ }
+ if (!valid)
+ {
+ return;
+ }
+ input_buffer reservation_map =
+ input.buffer_from_offset(h.off_mem_rsvmap, 0);
+ uint64_t start, length;
+ do
+ {
+ if (!(reservation_map.consume_binary(start) &&
+ reservation_map.consume_binary(length)))
+ {
+ fprintf(stderr, "Failed to read memory reservation table\n");
+ valid = false;
+ return;
+ }
+ if (start != 0 || length != 0)
+ {
+ reservations.push_back(reservation(start, length));
+ }
+ } while (!((start == 0) && (length == 0)));
+ input_buffer struct_table =
+ input.buffer_from_offset(h.off_dt_struct, h.size_dt_struct);
+ input_buffer strings_table =
+ input.buffer_from_offset(h.off_dt_strings, h.size_dt_strings);
+ uint32_t token;
+ if (!(struct_table.consume_binary(token) &&
+ (token == dtb::FDT_BEGIN_NODE)))
+ {
+ fprintf(stderr, "Expected FDT_BEGIN_NODE token.\n");
+ valid = false;
+ return;
+ }
+ root = node::parse_dtb(struct_table, strings_table);
+ if (!(struct_table.consume_binary(token) && (token == dtb::FDT_END)))
+ {
+ fprintf(stderr, "Expected FDT_END token after parsing root node.\n");
+ valid = false;
+ return;
+ }
+ valid = (root != 0);
+}
+
+string
+device_tree::node_path::to_string() const
+{
+ string path;
+ auto p = begin();
+ auto pe = end();
+ if ((p == pe) || (p+1 == pe))
+ {
+ return string("/");
+ }
+ // Skip the first name in the path. It's always "", and implicitly /
+ for (++p ; p!=pe ; ++p)
+ {
+ path += '/';
+ path += p->first;
+ if (!(p->second.empty()))
+ {
+ path += '@';
+ path += p->second;
+ }
+ }
+ return path;
+}
+
+node_ptr
+device_tree::create_fragment_wrapper(node_ptr &node, int &fragnum)
+{
+ // In a plugin, we can massage these non-/ root nodes into into a fragment
+ std::string fragment_address = "fragment@" + std::to_string(fragnum);
+ ++fragnum;
+
+ std::vector<property_ptr> symbols;
+
+ // Intentionally left empty
+ node_ptr newroot = node::create_special_node("", symbols);
+ node_ptr wrapper = node::create_special_node("__overlay__", symbols);
+
+ // Generate the fragment with $propname = <&name>
+ property_value v;
+ std::string propname;
+ v.string_data = node->name;
+ if (!node->name_is_path_reference)
+ {
+ propname = "target";
+ v.type = property_value::PHANDLE;
+ }
+ else
+ {
+ propname = "target-path";
+ v.type = property_value::STRING;
+ }
+ auto prop = std::make_shared<property>(std::string(propname));
+ prop->add_value(v);
+ symbols.push_back(prop);
+
+ node_ptr fragment = node::create_special_node(fragment_address, symbols);
+
+ wrapper->merge_node(node);
+ fragment->add_child(std::move(wrapper));
+ newroot->add_child(std::move(fragment));
+ return newroot;
+}
+
+node_ptr
+device_tree::generate_root(node_ptr &node, int &fragnum)
+{
+
+ string name = node->name;
+ if (name == string())
+ {
+ return std::move(node);
+ }
+ else if (!is_plugin)
+ {
+ return nullptr;
+ }
+
+ return create_fragment_wrapper(node, fragnum);
+}
+
+void
+device_tree::reassign_fragment_numbers(node_ptr &node, int &delta)
+{
+
+ for (auto &c : node->child_nodes())
+ {
+ if (c->name == std::string("fragment"))
+ {
+ int current_address = std::stoi(c->unit_address, nullptr, 16);
+ std::ostringstream new_address;
+ current_address += delta;
+ // It's possible that we hopped more than one somewhere, so just reset
+ // delta to the next in sequence.
+ delta = current_address + 1;
+ new_address << std::hex << current_address;
+ c->unit_address = new_address.str();
+ }
+ }
+}
+
+void
+device_tree::parse_dts(const string &fn, FILE *depfile)
+{
+ auto in = input_buffer::buffer_for_file(fn);
+ if (!in)
+ {
+ valid = false;
+ return;
+ }
+ std::vector<node_ptr> roots;
+ std::unordered_set<string> defnames;
+ for (auto &i : defines)
+ {
+ defnames.insert(i.first);
+ }
+ text_input_buffer input(std::move(in),
+ std::move(defnames),
+ std::vector<string>(include_paths),
+ dirname(fn),
+ depfile);
+ bool read_header = false;
+ int fragnum = 0;
+ parse_file(input, roots, read_header);
+ switch (roots.size())
+ {
+ case 0:
+ valid = false;
+ input.parse_error("Failed to find root node /.");
+ return;
+ case 1:
+ root = generate_root(roots[0], fragnum);
+ if (!root)
+ {
+ valid = false;
+ input.parse_error("Failed to find root node /.");
+ return;
+ }
+ break;
+ default:
+ {
+ root = generate_root(roots[0], fragnum);
+ if (!root)
+ {
+ valid = false;
+ input.parse_error("Failed to find root node /.");
+ return;
+ }
+ for (auto i=++(roots.begin()), e=roots.end() ; i!=e ; ++i)
+ {
+ auto &node = *i;
+ string name = node->name;
+ if (name == string())
+ {
+ if (is_plugin)
+ {
+ // Re-assign any fragment numbers based on a delta of
+ // fragnum before we merge it
+ reassign_fragment_numbers(node, fragnum);
+ }
+ root->merge_node(node);
+ }
+ else
+ {
+ auto existing = node_names.find(name);
+ if (existing == node_names.end())
+ {
+ collect_names();
+ existing = node_names.find(name);
+ }
+ if (existing == node_names.end())
+ {
+ if (is_plugin)
+ {
+ auto fragment = create_fragment_wrapper(node, fragnum);
+ root->merge_node(fragment);
+ }
+ else
+ {
+ fprintf(stderr, "Unable to merge node: %s\n", name.c_str());
+ }
+ }
+ else
+ {
+ existing->second->merge_node(node);
+ }
+ }
+ }
+ }
+ }
+ collect_names();
+ for (auto &ref : deletions)
+ {
+ auto parent = node_name_parents[ref];
+ auto node = node_names[ref];
+ if (!parent)
+ {
+ fprintf(stderr, "Top-level /delete-node/ directive refers to label %s, which is not found.\n", ref.c_str());
+ }
+ else
+ {
+ parent->delete_children_if([&](node_ptr &child) { return child == node; });
+ }
+ }
+ // Return value indicates whether we've dirtied the tree or not and need to
+ // recollect names
+ if (garbage_collect && garbage_collect_marked_nodes())
+ {
+ collect_names();
+ }
+ uint32_t phandle = 1;
+ // If we're writing symbols, go ahead and assign phandles to the entire
+ // tree. We'll do this before we resolve cross references, just to keep
+ // order semi-predictable and stable.
+ if (write_symbols)
+ {
+ assign_phandles(root, phandle);
+ }
+ resolve_cross_references(phandle);
+ if (write_symbols)
+ {
+ std::vector<property_ptr> symbols;
+ // Create a symbol table. Each label in this device tree may be
+ // referenced by other plugins, so we create a __symbols__ node inside
+ // the root that contains mappings (properties) from label names to
+ // paths.
+ for (auto i=ordered_node_paths.rbegin(), e=ordered_node_paths.rend() ; i!=e ; ++i)
+ {
+ auto &s = *i;
+ if (node_paths.find(s.first) == node_paths.end())
+ {
+ // Erased node, skip it.
+ continue;
+ }
+ property_value v;
+ v.string_data = s.second.to_string();
+ v.type = property_value::STRING;
+ string name = s.first;
+ auto prop = std::make_shared<property>(std::move(name));
+ prop->add_value(v);
+ symbols.push_back(prop);
+ }
+ root->add_child(node::create_special_node("__symbols__", symbols));
+ }
+ // If this is a plugin, then we also need to create two extra nodes.
+ // Internal phandles will need to be renumbered to avoid conflicts with
+ // already-loaded nodes and external references will need to be
+ // resolved.
+ if (is_plugin)
+ {
+ std::vector<property_ptr> symbols;
+ // Create the fixups entry. This is of the form:
+ // {target} = {path}:{property name}:{offset}
+ auto create_fixup_entry = [&](fixup &i, string target)
+ {
+ string value = i.path.to_string();
+ value += ':';
+ value += i.prop->get_key();
+ value += ':';
+ value += std::to_string(i.prop->offset_of_value(i.val));
+ property_value v;
+ v.string_data = value;
+ v.type = property_value::STRING;
+ auto prop = std::make_shared<property>(std::move(target));
+ prop->add_value(v);
+ return prop;
+ };
+ // If we have any unresolved phandle references in this plugin,
+ // then we must update them to 0xdeadbeef and leave a property in
+ // the /__fixups__ node whose key is the label and whose value is
+ // as described above.
+ if (!unresolved_fixups.empty())
+ {
+ for (auto &i : unresolved_fixups)
+ {
+ auto &val = i.get().val;
+ symbols.push_back(create_fixup_entry(i, val.string_data));
+ val.byte_data.push_back(0xde);
+ val.byte_data.push_back(0xad);
+ val.byte_data.push_back(0xbe);
+ val.byte_data.push_back(0xef);
+ val.type = property_value::BINARY;
+ }
+ root->add_child(node::create_special_node("__fixups__", symbols));
+ }
+ symbols.clear();
+ // If we have any resolved phandle references in this plugin, then
+ // we must create a child in the __local_fixups__ node whose path
+ // matches the node path from the root and whose value contains the
+ // location of the reference within a property.
+
+ // Create a local_fixups node that is initially empty.
+ node_ptr local_fixups = node::create_special_node("__local_fixups__", symbols);
+ for (auto &i : fixups)
+ {
+ if (!i.val.is_phandle())
+ {
+ continue;
+ }
+ node_ptr n = local_fixups;
+ for (auto &p : i.path)
+ {
+ // Skip the implicit root
+ if (p.first.empty())
+ {
+ continue;
+ }
+ bool found = false;
+ for (auto &c : n->child_nodes())
+ {
+ if (c->name == p.first)
+ {
+ if (c->unit_address == p.second)
+ {
+ n = c;
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ string path = p.first;
+ if (!(p.second.empty()))
+ {
+ path += '@';
+ path += p.second;
+ }
+ n->add_child(node::create_special_node(path, symbols));
+ n = *(--(n->child_end()));
+ }
+ }
+ assert(n);
+ property_value pv;
+ push_big_endian(pv.byte_data, static_cast<uint32_t>(i.prop->offset_of_value(i.val)));
+ pv.type = property_value::BINARY;
+ auto key = i.prop->get_key();
+ property_ptr prop = n->get_property(key);
+ // If we don't have an existing property then create one and
+ // use this property value
+ if (!prop)
+ {
+ prop = std::make_shared<property>(std::move(key));
+ n->add_property(prop);
+ prop->add_value(pv);
+ }
+ else
+ {
+ // If we do have an existing property value, try to append
+ // this value.
+ property_value &old_val = *(--prop->end());
+ if (!old_val.try_to_merge(pv))
+ {
+ prop->add_value(pv);
+ }
+ }
+ }
+ // We've iterated over all fixups, but only emit the
+ // __local_fixups__ if we found some that were resolved internally.
+ if (local_fixups->child_begin() != local_fixups->child_end())
+ {
+ root->add_child(std::move(local_fixups));
+ }
+ }
+}
+
+bool device_tree::parse_define(const char *def)
+{
+ const char *val = strchr(def, '=');
+ if (!val)
+ {
+ if (strlen(def) != 0)
+ {
+ string name(def);
+ defines[name];
+ return true;
+ }
+ return false;
+ }
+ string name(def, val-def);
+ string name_copy = name;
+ val++;
+ std::unique_ptr<input_buffer> raw(new input_buffer(val, strlen(val)));
+ text_input_buffer in(std::move(raw),
+ std::unordered_set<string>(),
+ std::vector<string>(),
+ string(),
+ nullptr);
+ property_ptr p = property::parse(in, std::move(name_copy), string_set(), false);
+ if (p)
+ defines[name] = p;
+ return (bool)p;
+}
+
+} // namespace fdt
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/fdt.hh b/usr.bin/dtc/fdt.hh
new file mode 100644
index 000000000000..fad9609d40bb
--- /dev/null
+++ b/usr.bin/dtc/fdt.hh
@@ -0,0 +1,1074 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _FDT_HH_
+#define _FDT_HH_
+#include <algorithm>
+#include <unordered_map>
+#include <unordered_set>
+#include <memory>
+#include <string>
+#include <functional>
+
+#include "util.hh"
+#include "input_buffer.hh"
+
+namespace dtc
+{
+
+namespace dtb
+{
+struct output_writer;
+class string_table;
+}
+
+namespace fdt
+{
+class property;
+class node;
+class device_tree;
+/**
+ * Type for device tree write functions.
+ */
+typedef void (device_tree::* tree_write_fn_ptr)(int);
+/**
+ * Type for device tree read functions.
+ */
+typedef void (device_tree::* tree_read_fn_ptr)(const std::string &, FILE *);
+/**
+ * Type for (owned) pointers to properties.
+ */
+typedef std::shared_ptr<property> property_ptr;
+/**
+ * Owning pointer to a node.
+ */
+typedef std::shared_ptr<node> node_ptr;
+/**
+ * Map from macros to property pointers.
+ */
+typedef std::unordered_map<std::string, property_ptr> define_map;
+/**
+ * Set of strings used for label names.
+ */
+typedef std::unordered_set<std::string> string_set;
+/**
+ * Properties may contain a number of different value, each with a different
+ * label. This class encapsulates a single value.
+ */
+struct property_value
+{
+ /**
+ * The label for this data. This is usually empty.
+ */
+ std::string label;
+ /**
+ * If this value is a string, or something resolved from a string (a
+ * reference) then this contains the source string.
+ */
+ std::string string_data;
+ /**
+ * The data that should be written to the final output.
+ */
+ byte_buffer byte_data;
+ /**
+ * Enumeration describing the possible types of a value. Note that
+ * property-coded arrays will appear simply as binary (or possibly
+ * string, if they happen to be nul-terminated and printable), and must
+ * be checked separately.
+ */
+ enum value_type
+ {
+ /**
+ * This is a list of strings. When read from source, string
+ * lists become one property value for each string, however
+ * when read from binary we have a single property value
+ * incorporating the entire text, with nul bytes separating the
+ * strings.
+ */
+ STRING_LIST,
+ /**
+ * This property contains a single string.
+ */
+ STRING,
+ /**
+ * This is a binary value. Check the size of byte_data to
+ * determine how many bytes this contains.
+ */
+ BINARY,
+ /** This contains a short-form address that should be replaced
+ * by a fully-qualified version. This will only appear when
+ * the input is a device tree source. When parsed from a
+ * device tree blob, the cross reference will have already been
+ * resolved and the property value will be a string containing
+ * the full path of the target node. */
+ CROSS_REFERENCE,
+ /**
+ * This is a phandle reference. When parsed from source, the
+ * string_data will contain the node label for the target and,
+ * after cross references have been resolved, the binary data
+ * will contain a 32-bit integer that should match the phandle
+ * property of the target node.
+ */
+ PHANDLE,
+ /**
+ * An empty property value. This will never appear on a real
+ * property value, it is used by checkers to indicate that no
+ * property values should exist for a property.
+ */
+ EMPTY,
+ /**
+ * The type of this property has not yet been determined.
+ */
+ UNKNOWN
+ };
+ /**
+ * The type of this property.
+ */
+ value_type type;
+ /**
+ * Returns true if this value is a cross reference, false otherwise.
+ */
+ inline bool is_cross_reference()
+ {
+ return is_type(CROSS_REFERENCE);
+ }
+ /**
+ * Returns true if this value is a phandle reference, false otherwise.
+ */
+ inline bool is_phandle()
+ {
+ return is_type(PHANDLE);
+ }
+ /**
+ * Returns true if this value is a string, false otherwise.
+ */
+ inline bool is_string()
+ {
+ return is_type(STRING);
+ }
+ /**
+ * Returns true if this value is a string list (a nul-separated
+ * sequence of strings), false otherwise.
+ */
+ inline bool is_string_list()
+ {
+ return is_type(STRING_LIST);
+ }
+ /**
+ * Returns true if this value is binary, false otherwise.
+ */
+ inline bool is_binary()
+ {
+ return is_type(BINARY);
+ }
+ /**
+ * Returns this property value as a 32-bit integer. Returns 0 if this
+ * property value is not 32 bits long. The bytes in the property value
+ * are assumed to be in big-endian format, but the return value is in
+ * the host native endian.
+ */
+ uint32_t get_as_uint32();
+ /**
+ * Default constructor, specifying the label of the value.
+ */
+ property_value(std::string l=std::string()) : label(l), type(UNKNOWN) {}
+ /**
+ * Writes the data for this value into an output buffer.
+ */
+ void push_to_buffer(byte_buffer &buffer);
+
+ /**
+ * Writes the property value to the standard output. This uses the
+ * following heuristics for deciding how to print the output:
+ *
+ * - If the value is nul-terminated and only contains printable
+ * characters, it is written as a string.
+ * - If it is a multiple of 4 bytes long, then it is printed as cells.
+ * - Otherwise, it is printed as a byte buffer.
+ */
+ void write_dts(FILE *file);
+ /**
+ * Tries to merge adjacent property values, returns true if it succeeds and
+ * false otherwise.
+ */
+ bool try_to_merge(property_value &other);
+ /**
+ * Returns the size (in bytes) of this property value.
+ */
+ size_t size();
+ private:
+ /**
+ * Returns whether the value is of the specified type. If the type of
+ * the value has not yet been determined, then this calculates it.
+ */
+ inline bool is_type(value_type v)
+ {
+ if (type == UNKNOWN)
+ {
+ resolve_type();
+ }
+ return type == v;
+ }
+ /**
+ * Determines the type of the value based on its contents.
+ */
+ void resolve_type();
+ /**
+ * Writes the property value to the specified file as a quoted string.
+ * This is used when generating DTS.
+ */
+ void write_as_string(FILE *file);
+ /**
+ * Writes the property value to the specified file as a sequence of
+ * 32-bit big-endian cells. This is used when generating DTS.
+ */
+ void write_as_cells(FILE *file);
+ /**
+ * Writes the property value to the specified file as a sequence of
+ * bytes. This is used when generating DTS.
+ */
+ void write_as_bytes(FILE *file);
+};
+
+/**
+ * A value encapsulating a single property. This contains a key, optionally a
+ * label, and optionally one or more values.
+ */
+class property
+{
+ /**
+ * The name of this property.
+ */
+ std::string key;
+ /**
+ * Zero or more labels.
+ */
+ string_set labels;
+ /**
+ * The values in this property.
+ */
+ std::vector<property_value> values;
+ /**
+ * Value indicating that this is a valid property. If a parse error
+ * occurs, then this value is false.
+ */
+ bool valid;
+ /**
+ * Parses a string property value, i.e. a value enclosed in double quotes.
+ */
+ void parse_string(text_input_buffer &input);
+ /**
+ * Parses one or more 32-bit values enclosed in angle brackets.
+ */
+ void parse_cells(text_input_buffer &input, int cell_size);
+ /**
+ * Parses an array of bytes, contained within square brackets.
+ */
+ void parse_bytes(text_input_buffer &input);
+ /**
+ * Parses a reference. This is a node label preceded by an ampersand
+ * symbol, which should expand to the full path to that node.
+ *
+ * Note: The specification says that the target of such a reference is
+ * a node name, however dtc assumes that it is a label, and so we
+ * follow their interpretation for compatibility.
+ */
+ void parse_reference(text_input_buffer &input);
+ /**
+ * Parse a predefined macro definition for a property.
+ */
+ void parse_define(text_input_buffer &input, define_map *defines);
+ /**
+ * Constructs a new property from two input buffers, pointing to the
+ * struct and strings tables in the device tree blob, respectively.
+ * The structs input buffer is assumed to have just consumed the
+ * FDT_PROP token.
+ */
+ property(input_buffer &structs, input_buffer &strings);
+ /**
+ * Parses a new property from the input buffer.
+ */
+ property(text_input_buffer &input,
+ std::string &&k,
+ string_set &&l,
+ bool terminated,
+ define_map *defines);
+ public:
+ /**
+ * Creates an empty property.
+ */
+ property(std::string &&k, string_set &&l=string_set())
+ : key(k), labels(l), valid(true) {}
+ /**
+ * Copy constructor.
+ */
+ property(property &p) : key(p.key), labels(p.labels), values(p.values),
+ valid(p.valid) {}
+ /**
+ * Factory method for constructing a new property. Attempts to parse a
+ * property from the input, and returns it on success. On any parse
+ * error, this will return 0.
+ */
+ static property_ptr parse_dtb(input_buffer &structs,
+ input_buffer &strings);
+ /**
+ * Factory method for constructing a new property. Attempts to parse a
+ * property from the input, and returns it on success. On any parse
+ * error, this will return 0.
+ */
+ static property_ptr parse(text_input_buffer &input,
+ std::string &&key,
+ string_set &&labels=string_set(),
+ bool semicolonTerminated=true,
+ define_map *defines=0);
+ /**
+ * Iterator type used for accessing the values of a property.
+ */
+ typedef std::vector<property_value>::iterator value_iterator;
+ /**
+ * Returns an iterator referring to the first value in this property.
+ */
+ inline value_iterator begin()
+ {
+ return values.begin();
+ }
+ /**
+ * Returns an iterator referring to the last value in this property.
+ */
+ inline value_iterator end()
+ {
+ return values.end();
+ }
+ /**
+ * Adds a new value to an existing property.
+ */
+ inline void add_value(property_value v)
+ {
+ values.push_back(v);
+ }
+ /**
+ * Returns the key for this property.
+ */
+ inline const std::string &get_key()
+ {
+ return key;
+ }
+ /**
+ * Writes the property to the specified writer. The property name is a
+ * reference into the strings table.
+ */
+ void write(dtb::output_writer &writer, dtb::string_table &strings);
+ /**
+ * Writes in DTS format to the specified file, at the given indent
+ * level. This will begin the line with the number of tabs specified
+ * as the indent level and then write the property in the most
+ * applicable way that it can determine.
+ */
+ void write_dts(FILE *file, int indent);
+ /**
+ * Returns the byte offset of the specified property value.
+ */
+ size_t offset_of_value(property_value &val);
+};
+
+/**
+ * Class encapsulating a device tree node. Nodes may contain properties and
+ * other nodes.
+ */
+class node
+{
+ public:
+ /**
+ * The labels for this node, if any. Node labels are used as the
+ * targets for cross references.
+ */
+ std::unordered_set<std::string> labels;
+ /**
+ * The name of the node.
+ */
+ std::string name;
+ /**
+ * The name of the node is a path reference.
+ */
+ bool name_is_path_reference = false;
+ /**
+ * The unit address of the node, which is optionally written after the
+ * name followed by an at symbol.
+ */
+ std::string unit_address;
+ /**
+ * A flag indicating that this node has been marked /omit-if-no-ref/ and
+ * will be omitted if it is not referenced, either directly or indirectly,
+ * by a node that is not similarly denoted.
+ */
+ bool omit_if_no_ref = false;
+ /**
+ * A flag indicating that this node has been referenced, either directly
+ * or indirectly, by a node that is not marked /omit-if-no-ref/.
+ */
+ bool used = false;
+ /**
+ * The type for the property vector.
+ */
+ typedef std::vector<property_ptr> property_vector;
+ /**
+ * Iterator type for child nodes.
+ */
+ typedef std::vector<node_ptr>::iterator child_iterator;
+ /**
+ * Recursion behavior to be observed for visiting
+ */
+ enum visit_behavior
+ {
+ /**
+ * Recurse as normal through the rest of the tree.
+ */
+ VISIT_RECURSE,
+ /**
+ * Continue recursing through the device tree, but do not
+ * recurse through this branch of the tree any further.
+ */
+ VISIT_CONTINUE,
+ /**
+ * Immediately halt the visit. No further nodes will be visited.
+ */
+ VISIT_BREAK
+ };
+ private:
+ /**
+ * Adaptor to use children in range-based for loops.
+ */
+ struct child_range
+ {
+ child_range(node &nd) : n(nd) {}
+ child_iterator begin() { return n.child_begin(); }
+ child_iterator end() { return n.child_end(); }
+ private:
+ node &n;
+ };
+ /**
+ * Adaptor to use properties in range-based for loops.
+ */
+ struct property_range
+ {
+ property_range(node &nd) : n(nd) {}
+ property_vector::iterator begin() { return n.property_begin(); }
+ property_vector::iterator end() { return n.property_end(); }
+ private:
+ node &n;
+ };
+ /**
+ * The properties contained within this node.
+ */
+ property_vector props;
+ /**
+ * The children of this node.
+ */
+ std::vector<node_ptr> children;
+ /**
+ * Children that should be deleted from this node when merging.
+ */
+ std::unordered_set<std::string> deleted_children;
+ /**
+ * Properties that should be deleted from this node when merging.
+ */
+ std::unordered_set<std::string> deleted_props;
+ /**
+ * A flag indicating whether this node is valid. This is set to false
+ * if an error occurs during parsing.
+ */
+ bool valid;
+ /**
+ * Parses a name inside a node, writing the string passed as the last
+ * argument as an error if it fails.
+ */
+ std::string parse_name(text_input_buffer &input,
+ bool &is_property,
+ const char *error);
+ /**
+ * Constructs a new node from two input buffers, pointing to the struct
+ * and strings tables in the device tree blob, respectively.
+ */
+ node(input_buffer &structs, input_buffer &strings);
+ /**
+ * Parses a new node from the specified input buffer. This is called
+ * when the input cursor is on the open brace for the start of the
+ * node. The name, and optionally label and unit address, should have
+ * already been parsed.
+ */
+ node(text_input_buffer &input,
+ device_tree &tree,
+ std::string &&n,
+ std::unordered_set<std::string> &&l,
+ std::string &&a,
+ define_map*);
+ /**
+ * Creates a special node with the specified name and properties.
+ */
+ node(const std::string &n, const std::vector<property_ptr> &p);
+ /**
+ * Comparison function for properties, used when sorting the properties
+ * vector. Orders the properties based on their names.
+ */
+ static inline bool cmp_properties(property_ptr &p1, property_ptr &p2);
+ /*
+ {
+ return p1->get_key() < p2->get_key();
+ }
+ */
+ /**
+ * Comparison function for nodes, used when sorting the children
+ * vector. Orders the nodes based on their names or, if the names are
+ * the same, by the unit addresses.
+ */
+ static inline bool cmp_children(node_ptr &c1, node_ptr &c2);
+ public:
+ /**
+ * Sorts the node's properties and children into alphabetical order and
+ * recursively sorts the children.
+ */
+ void sort();
+ /**
+ * Returns an iterator for the first child of this node.
+ */
+ inline child_iterator child_begin()
+ {
+ return children.begin();
+ }
+ /**
+ * Returns an iterator after the last child of this node.
+ */
+ inline child_iterator child_end()
+ {
+ return children.end();
+ }
+ /**
+ * Returns a range suitable for use in a range-based for loop describing
+ * the children of this node.
+ */
+ inline child_range child_nodes()
+ {
+ return child_range(*this);
+ }
+ /**
+ * Accessor for the deleted children.
+ */
+ inline const std::unordered_set<std::string> &deleted_child_nodes()
+ {
+ return deleted_children;
+ }
+ /**
+ * Accessor for the deleted properties
+ */
+ inline const std::unordered_set<std::string> &deleted_properties()
+ {
+ return deleted_props;
+ }
+ /**
+ * Returns a range suitable for use in a range-based for loop describing
+ * the properties of this node.
+ */
+ inline property_range properties()
+ {
+ return property_range(*this);
+ }
+ /**
+ * Returns an iterator after the last property of this node.
+ */
+ inline property_vector::iterator property_begin()
+ {
+ return props.begin();
+ }
+ /**
+ * Returns an iterator for the first property of this node.
+ */
+ inline property_vector::iterator property_end()
+ {
+ return props.end();
+ }
+ /**
+ * Factory method for constructing a new node. Attempts to parse a
+ * node in DTS format from the input, and returns it on success. On
+ * any parse error, this will return 0. This should be called with the
+ * cursor on the open brace of the property, after the name and so on
+ * have been parsed.
+ */
+ static node_ptr parse(text_input_buffer &input,
+ device_tree &tree,
+ std::string &&name,
+ std::unordered_set<std::string> &&label=std::unordered_set<std::string>(),
+ std::string &&address=std::string(),
+ define_map *defines=0);
+ /**
+ * Factory method for constructing a new node. Attempts to parse a
+ * node in DTB format from the input, and returns it on success. On
+ * any parse error, this will return 0. This should be called with the
+ * cursor on the open brace of the property, after the name and so on
+ * have been parsed.
+ */
+ static node_ptr parse_dtb(input_buffer &structs, input_buffer &strings);
+ /**
+ * Construct a new special node from a name and set of properties.
+ */
+ static node_ptr create_special_node(const std::string &name,
+ const std::vector<property_ptr> &props);
+ /**
+ * Returns a property corresponding to the specified key, or 0 if this
+ * node does not contain a property of that name.
+ */
+ property_ptr get_property(const std::string &key);
+ /**
+ * Adds a new property to this node.
+ */
+ inline void add_property(property_ptr &p)
+ {
+ props.push_back(p);
+ }
+ /**
+ * Adds a new child to this node.
+ */
+ inline void add_child(node_ptr &&n)
+ {
+ children.push_back(std::move(n));
+ }
+ /**
+ * Deletes any children from this node.
+ */
+ inline void delete_children_if(std::function<bool(node_ptr &)> predicate)
+ {
+ children.erase(std::remove_if(children.begin(), children.end(), predicate), children.end());
+ }
+ /**
+ * Merges a node into this one. Any properties present in both are
+ * overridden, any properties present in only one are preserved.
+ */
+ void merge_node(node_ptr &other);
+ /**
+ * Write this node to the specified output. Although nodes do not
+ * refer to a string table directly, their properties do. The string
+ * table passed as the second argument is used for the names of
+ * properties within this node and its children.
+ */
+ void write(dtb::output_writer &writer, dtb::string_table &strings);
+ /**
+ * Writes the current node as DTS to the specified file. The second
+ * parameter is the indent level. This function will start every line
+ * with this number of tabs.
+ */
+ void write_dts(FILE *file, int indent);
+ /**
+ * Recursively visit this node and then its children based on the
+ * callable's return value. The callable may return VISIT_BREAK
+ * immediately halt all recursion and end the visit, VISIT_CONTINUE to
+ * not recurse into the current node's children, or VISIT_RECURSE to recurse
+ * through children as expected. parent will be passed to the callable.
+ */
+ visit_behavior visit(std::function<visit_behavior(node&, node*)>, node *parent);
+};
+
+/**
+ * Class encapsulating the entire parsed FDT. This is the top-level class,
+ * which parses the entire DTS representation and write out the finished
+ * version.
+ */
+class device_tree
+{
+ public:
+ /**
+ * Type used for node paths. A node path is sequence of names and unit
+ * addresses.
+ */
+ class node_path : public std::vector<std::pair<std::string,std::string>>
+ {
+ public:
+ /**
+ * Converts this to a string representation.
+ */
+ std::string to_string() const;
+ };
+ /**
+ * Name that we should use for phandle nodes.
+ */
+ enum phandle_format
+ {
+ /** linux,phandle */
+ LINUX,
+ /** phandle */
+ EPAPR,
+ /** Create both nodes. */
+ BOTH
+ };
+ private:
+ /**
+ * The format that we should use for writing phandles.
+ */
+ phandle_format phandle_node_name = EPAPR;
+ /**
+ * Flag indicating that this tree is valid. This will be set to false
+ * on parse errors.
+ */
+ bool valid = true;
+ /**
+ * Flag indicating that this tree requires garbage collection. This will be
+ * set to true if a node marked /omit-if-no-ref/ is encountered.
+ */
+ bool garbage_collect = false;
+ /**
+ * Type used for memory reservations. A reservation is two 64-bit
+ * values indicating a base address and length in memory that the
+ * kernel should not use. The high 32 bits are ignored on 32-bit
+ * platforms.
+ */
+ typedef std::pair<uint64_t, uint64_t> reservation;
+ /**
+ * The memory reserves table.
+ */
+ std::vector<reservation> reservations;
+ /**
+ * Root node. All other nodes are children of this node.
+ */
+ node_ptr root;
+ /**
+ * Mapping from names to nodes. Only unambiguous names are recorded,
+ * duplicate names are stored as (node*)-1.
+ */
+ std::unordered_map<std::string, node_ptr> node_names;
+ /**
+ * Mapping from names to the nodes that contain them.
+ */
+ std::unordered_map<std::string, node_ptr> node_name_parents;
+ /**
+ * A map from labels to node paths. When resolving cross references,
+ * we look up referenced nodes in this and replace the cross reference
+ * with the full path to its target.
+ */
+ std::unordered_map<std::string, node_path> node_paths;
+ /**
+ * All of the elements in `node_paths` in the order that they were
+ * created. This is used for emitting the `__symbols__` section, where
+ * we want to guarantee stable ordering.
+ */
+ std::vector<std::pair<std::string, node_path>> ordered_node_paths;
+ /**
+ * A collection of property values that are references to other nodes.
+ * These should be expanded to the full path of their targets.
+ */
+ std::vector<property_value*> cross_references;
+ /**
+ * Labels collected from top-level /delete-node/ directives.
+ */
+ std::vector<std::string> deletions;
+ /**
+ * The location of something requiring a fixup entry.
+ */
+ struct fixup
+ {
+ /**
+ * The path to the node.
+ */
+ node_path path;
+ /**
+ * The property containing the reference.
+ */
+ property_ptr prop;
+ /**
+ * The property value that contains the reference.
+ */
+ property_value &val;
+ };
+ /**
+ * A collection of property values that refer to phandles. These will
+ * be replaced by the value of the phandle property in their
+ * destination.
+ */
+ std::vector<fixup> fixups;
+ /**
+ * The locations of all of the values that are supposed to become phandle
+ * references, but refer to things outside of this file.
+ */
+ std::vector<std::reference_wrapper<fixup>> unresolved_fixups;
+ /**
+ * The names of nodes that target phandles.
+ */
+ std::unordered_set<std::string> phandle_targets;
+ /**
+ * A collection of input buffers that we are using. These input
+ * buffers are the ones that own their memory, and so we must preserve
+ * them for the lifetime of the device tree.
+ */
+ std::vector<std::unique_ptr<input_buffer>> buffers;
+ /**
+ * A map of used phandle values to nodes. All phandles must be unique,
+ * so we keep a set of ones that the user explicitly provides in the
+ * input to ensure that we don't reuse them.
+ *
+ * This is a map, rather than a set, because we also want to be able to
+ * find phandles that were provided by the user explicitly when we are
+ * doing checking.
+ */
+ std::unordered_map<uint32_t, node_ptr> used_phandles;
+ /**
+ * Paths to search for include files. This contains a set of
+ * nul-terminated strings, which are not owned by this class and so
+ * must be freed separately.
+ */
+ std::vector<std::string> include_paths;
+ /**
+ * Dictionary of predefined macros provided on the command line.
+ */
+ define_map defines;
+ /**
+ * The default boot CPU, specified in the device tree header.
+ */
+ uint32_t boot_cpu = 0;
+ /**
+ * The number of empty reserve map entries to generate in the blob.
+ */
+ uint32_t spare_reserve_map_entries = 0;
+ /**
+ * The minimum size in bytes of the blob.
+ */
+ uint32_t minimum_blob_size = 0;
+ /**
+ * The number of bytes of padding to add to the end of the blob.
+ */
+ uint32_t blob_padding = 0;
+ /**
+ * Is this tree a plugin?
+ */
+ bool is_plugin = false;
+ /**
+ * Visit all of the nodes recursively, and if they have labels then add
+ * them to the node_paths and node_names vectors so that they can be
+ * used in resolving cross references. Also collects phandle
+ * properties that have been explicitly added.
+ */
+ void collect_names_recursive(node_ptr parent, node_ptr n, node_path &path);
+ /**
+ * Assign a phandle property to a single node. The next parameter
+ * holds the phandle to be assigned, and will be incremented upon
+ * assignment.
+ */
+ property_ptr assign_phandle(node_ptr n, uint32_t &next);
+ /**
+ * Assign phandle properties to all nodes that have been referenced and
+ * require one. This method will recursively visit the tree starting at
+ * the node that it is passed.
+ */
+ void assign_phandles(node_ptr n, uint32_t &next);
+ /**
+ * Calls the recursive version of this method on every root node.
+ */
+ void collect_names();
+ /**
+ * Resolves all cross references. Any properties that refer to another
+ * node must have their values replaced by either the node path or
+ * phandle value. The phandle parameter holds the next phandle to be
+ * assigned, should the need arise. It will be incremented upon each
+ * assignment of a phandle. Garbage collection of unreferenced nodes
+ * marked for "delete if unreferenced" will also occur here.
+ */
+ void resolve_cross_references(uint32_t &phandle);
+ /**
+ * Garbage collects nodes that have been marked /omit-if-no-ref/ and do not
+ * have any references to them from nodes that are similarly marked. This
+ * is a fairly expensive operation. The return value indicates whether the
+ * tree has been dirtied as a result of this operation, so that the caller
+ * may take appropriate measures to bring the device tree into a consistent
+ * state as needed.
+ */
+ bool garbage_collect_marked_nodes();
+ /**
+ * Parses a dts file in the given buffer and adds the roots to the parsed
+ * set. The `read_header` argument indicates whether the header has
+ * already been read. Some dts files place the header in an include,
+ * rather than in the top-level file.
+ */
+ void parse_file(text_input_buffer &input,
+ std::vector<node_ptr> &roots,
+ bool &read_header);
+ /**
+ * Template function that writes a dtb blob using the specified writer.
+ * The writer defines the output format (assembly, blob).
+ */
+ template<class writer>
+ void write(int fd);
+ public:
+ /**
+ * Should we write the __symbols__ node (to allow overlays to be linked
+ * against this blob)?
+ */
+ bool write_symbols = false;
+ /**
+ * Returns the node referenced by the property. If this is a tree that
+ * is in source form, then we have a string that we can use to index
+ * the cross_references array and so we can just look that up.
+ */
+ node_ptr referenced_node(property_value &v);
+ /**
+ * Writes this FDT as a DTB to the specified output.
+ */
+ void write_binary(int fd);
+ /**
+ * Writes this FDT as an assembly representation of the DTB to the
+ * specified output. The result can then be assembled and linked into
+ * a program.
+ */
+ void write_asm(int fd);
+ /**
+ * Writes the tree in DTS (source) format.
+ */
+ void write_dts(int fd);
+ /**
+ * Default constructor. Creates a valid, but empty FDT.
+ */
+ device_tree() {}
+ /**
+ * Constructs a device tree from the specified file name, referring to
+ * a file that contains a device tree blob.
+ */
+ void parse_dtb(const std::string &fn, FILE *depfile);
+ /**
+ * Construct a fragment wrapper around node. This will assume that node's
+ * name may be used as the target of the fragment, and the contents are to
+ * be wrapped in an __overlay__ node. The fragment wrapper will be assigned
+ * fragnumas its fragment number, and fragment number will be incremented.
+ */
+ node_ptr create_fragment_wrapper(node_ptr &node, int &fragnum);
+ /**
+ * Generate a root node from the node passed in. This is sensitive to
+ * whether we're in a plugin context or not, so that if we're in a plugin we
+ * can circumvent any errors that might normally arise from a non-/ root.
+ * fragnum will be assigned to any fragment wrapper generated as a result
+ * of the call, and fragnum will be incremented.
+ */
+ node_ptr generate_root(node_ptr &node, int &fragnum);
+ /**
+ * Reassign any fragment numbers from this new node, based on the given
+ * delta.
+ */
+ void reassign_fragment_numbers(node_ptr &node, int &delta);
+ /*
+ * Constructs a device tree from the specified file name, referring to
+ * a file that contains device tree source.
+ */
+ void parse_dts(const std::string &fn, FILE *depfile);
+ /**
+ * Returns whether this tree is valid.
+ */
+ inline bool is_valid()
+ {
+ return valid;
+ }
+ /**
+ * Mark this tree as needing garbage collection, because an /omit-if-no-ref/
+ * node has been encountered.
+ */
+ void set_needs_garbage_collection()
+ {
+ garbage_collect = true;
+ }
+ /**
+ * Sets the format for writing phandle properties.
+ */
+ inline void set_phandle_format(phandle_format f)
+ {
+ phandle_node_name = f;
+ }
+ /**
+ * Returns a pointer to the root node of this tree. No ownership
+ * transfer.
+ */
+ inline const node_ptr &get_root() const
+ {
+ return root;
+ }
+ /**
+ * Sets the physical boot CPU.
+ */
+ void set_boot_cpu(uint32_t cpu)
+ {
+ boot_cpu = cpu;
+ }
+ /**
+ * Sorts the tree. Useful for debugging device trees.
+ */
+ void sort()
+ {
+ if (root)
+ {
+ root->sort();
+ }
+ }
+ /**
+ * Adds a path to search for include files. The argument must be a
+ * nul-terminated string representing the path. The device tree keeps
+ * a pointer to this string, but does not own it: the caller is
+ * responsible for freeing it if required.
+ */
+ void add_include_path(const char *path)
+ {
+ std::string p(path);
+ include_paths.push_back(std::move(p));
+ }
+ /**
+ * Sets the number of empty reserve map entries to add.
+ */
+ void set_empty_reserve_map_entries(uint32_t e)
+ {
+ spare_reserve_map_entries = e;
+ }
+ /**
+ * Sets the minimum size, in bytes, of the blob.
+ */
+ void set_blob_minimum_size(uint32_t s)
+ {
+ minimum_blob_size = s;
+ }
+ /**
+ * Sets the amount of padding to add to the blob.
+ */
+ void set_blob_padding(uint32_t p)
+ {
+ blob_padding = p;
+ }
+ /**
+ * Parses a predefined macro value.
+ */
+ bool parse_define(const char *def);
+};
+
+} // namespace fdt
+
+} // namespace dtc
+
+#endif // !_FDT_HH_
diff --git a/usr.bin/dtc/input_buffer.cc b/usr.bin/dtc/input_buffer.cc
new file mode 100644
index 000000000000..278dd42b5ac6
--- /dev/null
+++ b/usr.bin/dtc/input_buffer.cc
@@ -0,0 +1,1269 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "input_buffer.hh"
+#include <ctype.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <functional>
+#ifndef NDEBUG
+#include <iostream>
+#endif
+#include <limits>
+
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef MAP_PREFAULT_READ
+#define MAP_PREFAULT_READ 0
+#endif
+
+using std::string;
+
+namespace
+{
+/**
+ * Subclass of input_buffer that mmap()s a file and owns the resulting memory.
+ * When this object is destroyed, the memory is unmapped.
+ */
+struct mmap_input_buffer : public dtc::input_buffer
+{
+ string fn;
+ const string &filename() const override
+ {
+ return fn;
+ }
+ /**
+ * Constructs a new buffer from the file passed in as a file
+ * descriptor.
+ */
+ mmap_input_buffer(int fd, string &&filename);
+ /**
+ * Unmaps the buffer, if one exists.
+ */
+ virtual ~mmap_input_buffer();
+};
+/**
+ * Input buffer read from standard input. This is used for reading device tree
+ * blobs and source from standard input. It reads the entire input into
+ * malloc'd memory, so will be very slow for large inputs. DTS and DTB files
+ * are very rarely more than 10KB though, so this is probably not a problem.
+ */
+struct stream_input_buffer : public dtc::input_buffer
+{
+ const string &filename() const override
+ {
+ static string n = "<standard input>";
+ return n;
+ }
+ /**
+ * The buffer that will store the data read from the standard input.
+ */
+ std::vector<char> b;
+ /**
+ * Constructs a new buffer from the standard input.
+ */
+ stream_input_buffer();
+};
+
+mmap_input_buffer::mmap_input_buffer(int fd, string &&filename)
+ : input_buffer(0, 0), fn(filename)
+{
+ struct stat sb;
+ if (fstat(fd, &sb))
+ {
+ perror("Failed to stat file");
+ }
+ size = sb.st_size;
+ buffer = (const char*)mmap(0, size, PROT_READ, MAP_PRIVATE |
+ MAP_PREFAULT_READ, fd, 0);
+ if (buffer == MAP_FAILED)
+ {
+ perror("Failed to mmap file");
+ exit(EXIT_FAILURE);
+ }
+}
+
+mmap_input_buffer::~mmap_input_buffer()
+{
+ if (buffer != 0)
+ {
+ munmap(const_cast<char*>(buffer), size);
+ }
+}
+
+stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
+{
+ int c;
+ while ((c = fgetc(stdin)) != EOF)
+ {
+ b.push_back(c);
+ }
+ buffer = b.data();
+ size = b.size();
+}
+
+} // Anonymous namespace
+
+
+namespace dtc
+{
+
+void
+input_buffer::skip_to(char c)
+{
+ while ((cursor < size) && (buffer[cursor] != c))
+ {
+ cursor++;
+ }
+}
+
+void
+text_input_buffer::skip_to(char c)
+{
+ while (!finished() && (*(*this) != c))
+ {
+ ++(*this);
+ }
+}
+
+void
+text_input_buffer::skip_spaces()
+{
+ if (finished()) { return; }
+ char c = *(*this);
+ bool last_nl = false;
+ while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
+ || (c == '\v') || (c == '\r'))
+ {
+ last_nl = ((c == '\n') || (c == '\r'));
+ ++(*this);
+ if (finished())
+ {
+ c = '\0';
+ }
+ else
+ {
+ c = *(*this);
+ }
+ }
+ // Skip C preprocessor leftovers
+ if ((c == '#') && ((cursor == 0) || last_nl))
+ {
+ skip_to('\n');
+ skip_spaces();
+ }
+ if (consume("/include/"))
+ {
+ handle_include();
+ skip_spaces();
+ }
+}
+
+void
+text_input_buffer::handle_include()
+{
+ bool reallyInclude = true;
+ if (consume("if "))
+ {
+ next_token();
+ string name = parse_property_name();
+ if (defines.count(name) == 0)
+ {
+ reallyInclude = false;
+ }
+ consume('/');
+ }
+ next_token();
+ if (!consume('"'))
+ {
+ parse_error("Expected quoted filename");
+ return;
+ }
+ auto loc = location();
+ string file = parse_to('"');
+ consume('"');
+ if (!reallyInclude)
+ {
+ return;
+ }
+ string include_file = dir + '/' + file;
+ auto include_buffer = input_buffer::buffer_for_file(include_file, false);
+ if (include_buffer == 0)
+ {
+ for (auto i : include_paths)
+ {
+ include_file = i + '/' + file;
+ include_buffer = input_buffer::buffer_for_file(include_file, false);
+ if (include_buffer != 0)
+ {
+ break;
+ }
+ }
+ }
+ if (depfile)
+ {
+ putc(' ', depfile);
+ fputs(include_file.c_str(), depfile);
+ }
+ if (!include_buffer)
+ {
+ loc.report_error("Unable to locate input file");
+ return;
+ }
+ input_stack.push(std::move(include_buffer));
+}
+
+bool text_input_buffer::read_binary_file(const std::string &filename, byte_buffer &b)
+{
+ bool try_include_paths = true;
+ string include_file;
+ if (filename[0] == '/')
+ {
+ include_file = filename;
+ // Don't try include paths if we're given an absolute path.
+ // Failing is better so that we don't accidentally do the wrong thing,
+ // but make it seem like everything is alright.
+ try_include_paths = false;
+ }
+ else
+ {
+ include_file = dir + '/' + filename;
+ }
+ auto include_buffer = input_buffer::buffer_for_file(include_file, false);
+ if (include_buffer == 0 && try_include_paths)
+ {
+ for (auto i : include_paths)
+ {
+ include_file = i + '/' + filename;
+ include_buffer = input_buffer::buffer_for_file(include_file, false);
+ if (include_buffer != 0)
+ {
+ break;
+ }
+ }
+ }
+ if (!include_buffer)
+ {
+ return false;
+ }
+ if (depfile)
+ {
+ putc(' ', depfile);
+ fputs(include_file.c_str(), depfile);
+ }
+ b.insert(b.begin(), include_buffer->begin(), include_buffer->end());
+ return true;
+}
+
+input_buffer
+input_buffer::buffer_from_offset(int offset, int s)
+{
+ if (offset < 0)
+ {
+ return input_buffer();
+ }
+ if (s == 0)
+ {
+ s = size - offset;
+ }
+ if (offset > size)
+ {
+ return input_buffer();
+ }
+ if (s > (size-offset))
+ {
+ return input_buffer();
+ }
+ return input_buffer(&buffer[offset], s);
+}
+
+bool
+input_buffer::consume(const char *str)
+{
+ int len = strlen(str);
+ if (len > size - cursor)
+ {
+ return false;
+ }
+ else
+ {
+ for (int i=0 ; i<len ; ++i)
+ {
+ if (str[i] != (*this)[i])
+ {
+ return false;
+ }
+ }
+ cursor += len;
+ return true;
+ }
+ return false;
+}
+
+bool
+input_buffer::consume_integer(unsigned long long &outInt)
+{
+ // The first character must be a digit. Hex and octal strings
+ // are prefixed by 0 and 0x, respectively.
+ if (!isdigit((*this)[0]))
+ {
+ return false;
+ }
+ char *end= const_cast<char*>(&buffer[size]);
+ errno = 0;
+ outInt = strtoull(&buffer[cursor], &end, 0);
+ if (end == &buffer[cursor] ||
+ (outInt == std::numeric_limits<unsigned long long>::max() &&
+ errno == ERANGE))
+ {
+ return false;
+ }
+ cursor = end - buffer;
+ return true;
+}
+
+namespace {
+
+/**
+ * Convenience typedef for the type that we use for all values.
+ */
+typedef unsigned long long valty;
+
+/**
+ * Expression tree currently being parsed.
+ */
+struct expression
+{
+ typedef text_input_buffer::source_location source_location;
+ /**
+ * The type that is returned when computing the result. The boolean value
+ * indicates whether this is a valid expression.
+ *
+ * FIXME: Once we can use C++17, this should be `std::optional`.
+ */
+ typedef std::pair<valty, bool> result;
+ /**
+ * Evaluate this node, taking into account operator precedence.
+ */
+ virtual result operator()() = 0;
+ /**
+ * Returns the precedence of this node. Lower values indicate higher
+ * precedence.
+ */
+ virtual int precedence() = 0;
+ /**
+ * Constructs an expression, storing the location where it was created.
+ */
+ expression(source_location l) : loc(l) {}
+ virtual ~expression() {}
+#ifndef NDEBUG
+ /**
+ * Dumps this expression to `std::cerr`, appending a newline if `nl` is
+ * `true`.
+ */
+ void dump(bool nl=false)
+ {
+ void *ptr = this;
+ if (ptr == nullptr)
+ {
+ std::cerr << "{nullptr}\n";
+ return;
+ }
+ dump_impl();
+ if (nl)
+ {
+ std::cerr << '\n';
+ }
+ }
+ private:
+ /**
+ * Method that sublcasses override to implement the behaviour of `dump()`.
+ */
+ virtual void dump_impl() = 0;
+#endif
+ protected:
+ source_location loc;
+};
+
+/**
+ * Expression wrapping a single integer. Leaf nodes in the expression tree.
+ */
+class terminal_expr : public expression
+{
+ /**
+ * The value that this wraps.
+ */
+ valty val;
+ /**
+ * Evaluate. Trivially returns the value that this class wraps.
+ */
+ result operator()() override
+ {
+ return {val, true};
+ }
+ int precedence() override
+ {
+ return 0;
+ }
+ public:
+ /**
+ * Constructor.
+ */
+ terminal_expr(source_location l, valty v) : expression(l), val(v) {}
+#ifndef NDEBUG
+ void dump_impl() override { std::cerr << val; }
+#endif
+};
+
+/**
+ * Parenthetical expression. Exists to make the contents opaque.
+ */
+struct paren_expression : public expression
+{
+ /**
+ * The expression within the parentheses.
+ */
+ expression_ptr subexpr;
+ /**
+ * Constructor. Takes the child expression as the only argument.
+ */
+ paren_expression(source_location l, expression_ptr p) : expression(l),
+ subexpr(std::move(p)) {}
+ int precedence() override
+ {
+ return 0;
+ }
+ /**
+ * Evaluate - just forwards to the underlying expression.
+ */
+ result operator()() override
+ {
+ return (*subexpr)();
+ }
+#ifndef NDEBUG
+ void dump_impl() override
+ {
+ std::cerr << " (";
+ subexpr->dump();
+ std::cerr << ") ";
+ }
+#endif
+};
+
+/**
+ * Template class for unary operators. The `OpChar` template parameter is
+ * solely for debugging and makes it easy to print the expression. The `Op`
+ * template parameter is a function object that implements the operator that
+ * this class provides. Most of these are provided by the `<functional>`
+ * header.
+ */
+template<char OpChar, class Op>
+class unary_operator : public expression
+{
+ /**
+ * The subexpression for this unary operator.
+ */
+ expression_ptr subexpr;
+ result operator()() override
+ {
+ Op op;
+ result s = (*subexpr)();
+ if (!s.second)
+ {
+ return s;
+ }
+ return {op(s.first), true};
+ }
+ /**
+ * All unary operators have the same precedence. They are all evaluated
+ * before binary expressions, but after parentheses.
+ */
+ int precedence() override
+ {
+ return 3;
+ }
+ public:
+ unary_operator(source_location l, expression_ptr p) :
+ expression(l), subexpr(std::move(p)) {}
+#ifndef NDEBUG
+ void dump_impl() override
+ {
+ std::cerr << OpChar;
+ subexpr->dump();
+ }
+#endif
+};
+
+/**
+ * Abstract base class for binary operators. Allows the tree to be modified
+ * without knowing what the operations actually are.
+ */
+struct binary_operator_base : public expression
+{
+ using expression::expression;
+ /**
+ * The left side of the expression.
+ */
+ expression_ptr lhs;
+ /**
+ * The right side of the expression.
+ */
+ expression_ptr rhs;
+ /**
+ * Insert a node somewhere down the path of left children, until it would
+ * be preempting something that should execute first.
+ */
+ void insert_left(binary_operator_base *new_left)
+ {
+ if (lhs->precedence() < new_left->precedence())
+ {
+ new_left->rhs = std::move(lhs);
+ lhs.reset(new_left);
+ }
+ else
+ {
+ static_cast<binary_operator_base*>(lhs.get())->insert_left(new_left);
+ }
+ }
+};
+
+/**
+ * Template class for binary operators. The precedence and the operation are
+ * provided as template parameters.
+ */
+template<int Precedence, class Op>
+struct binary_operator : public binary_operator_base
+{
+ result operator()() override
+ {
+ Op op;
+ result l = (*lhs)();
+ result r = (*rhs)();
+ if (!(l.second && r.second))
+ {
+ return {0, false};
+ }
+ return {op(l.first, r.first), true};
+ }
+ int precedence() override
+ {
+ return Precedence;
+ }
+#ifdef NDEBUG
+ /**
+ * Constructor. Takes the name of the operator as an argument, for
+ * debugging. Only stores it in debug mode.
+ */
+ binary_operator(source_location l, const char *) :
+ binary_operator_base(l) {}
+#else
+ const char *opName;
+ binary_operator(source_location l, const char *o) :
+ binary_operator_base(l), opName(o) {}
+ void dump_impl() override
+ {
+ lhs->dump();
+ std::cerr << opName;
+ rhs->dump();
+ }
+#endif
+};
+
+/**
+ * Ternary conditional operators (`cond ? true : false`) are a special case -
+ * there are no other ternary operators.
+ */
+class ternary_conditional_operator : public expression
+{
+ /**
+ * The condition for the clause.
+ */
+ expression_ptr cond;
+ /**
+ * The expression that this evaluates to if the condition is true.
+ */
+ expression_ptr lhs;
+ /**
+ * The expression that this evaluates to if the condition is false.
+ */
+ expression_ptr rhs;
+ result operator()() override
+ {
+ result c = (*cond)();
+ result l = (*lhs)();
+ result r = (*rhs)();
+ if (!(l.second && r.second && c.second))
+ {
+ return {0, false};
+ }
+ return c.first ? l : r;
+ }
+ int precedence() override
+ {
+ // The actual precedence of a ternary conditional operator is 15, but
+ // its associativity is the opposite way around to the other operators,
+ // so we fudge it slightly.
+ return 3;
+ }
+#ifndef NDEBUG
+ void dump_impl() override
+ {
+ cond->dump();
+ std::cerr << " ? ";
+ lhs->dump();
+ std::cerr << " : ";
+ rhs->dump();
+ }
+#endif
+ public:
+ ternary_conditional_operator(source_location sl,
+ expression_ptr c,
+ expression_ptr l,
+ expression_ptr r) :
+ expression(sl), cond(std::move(c)), lhs(std::move(l)),
+ rhs(std::move(r)) {}
+};
+
+template<typename T>
+struct lshift
+{
+ constexpr T operator()(const T &lhs, const T &rhs) const
+ {
+ return lhs << rhs;
+ }
+};
+template<typename T>
+struct rshift
+{
+ constexpr T operator()(const T &lhs, const T &rhs) const
+ {
+ return lhs >> rhs;
+ }
+};
+template<typename T>
+struct unary_plus
+{
+ constexpr T operator()(const T &val) const
+ {
+ return +val;
+ }
+};
+// TODO: Replace with std::bit_not once we can guarantee C++14 as a baseline.
+template<typename T>
+struct bit_not
+{
+ constexpr T operator()(const T &val) const
+ {
+ return ~val;
+ }
+};
+
+template<typename T>
+struct divmod : public binary_operator<5, T>
+{
+ using binary_operator<5, T>::binary_operator;
+ using typename binary_operator_base::result;
+ result operator()() override
+ {
+ result r = (*binary_operator_base::rhs)();
+ if (r.second && (r.first == 0))
+ {
+ expression::loc.report_error("Division by zero");
+ return {0, false};
+ }
+ return binary_operator<5, T>::operator()();
+ }
+};
+
+} // anonymous namespace
+
+
+expression_ptr text_input_buffer::parse_binary_expression(expression_ptr lhs)
+{
+ next_token();
+ binary_operator_base *expr = nullptr;
+ char op = *(*this);
+ source_location l = location();
+ switch (op)
+ {
+ default:
+ return lhs;
+ case '+':
+ expr = new binary_operator<6, std::plus<valty>>(l, "+");
+ break;
+ case '-':
+ expr = new binary_operator<6, std::minus<valty>>(l, "-");
+ break;
+ case '%':
+ expr = new divmod<std::modulus<valty>>(l, "/");
+ break;
+ case '*':
+ expr = new binary_operator<5, std::multiplies<valty>>(l, "*");
+ break;
+ case '/':
+ expr = new divmod<std::divides<valty>>(l, "/");
+ break;
+ case '<':
+ switch (peek())
+ {
+ default:
+ parse_error("Invalid operator");
+ return nullptr;
+ case ' ':
+ case '(':
+ case '0'...'9':
+ expr = new binary_operator<8, std::less<valty>>(l, "<");
+ break;
+ case '=':
+ ++(*this);
+ expr = new binary_operator<8, std::less_equal<valty>>(l, "<=");
+ break;
+ case '<':
+ ++(*this);
+ expr = new binary_operator<7, lshift<valty>>(l, "<<");
+ break;
+ }
+ break;
+ case '>':
+ switch (peek())
+ {
+ default:
+ parse_error("Invalid operator");
+ return nullptr;
+ case '(':
+ case ' ':
+ case '0'...'9':
+ expr = new binary_operator<8, std::greater<valty>>(l, ">");
+ break;
+ case '=':
+ ++(*this);
+ expr = new binary_operator<8, std::greater_equal<valty>>(l, ">=");
+ break;
+ case '>':
+ ++(*this);
+ expr = new binary_operator<7, rshift<valty>>(l, ">>");
+ break;
+ return lhs;
+ }
+ break;
+ case '=':
+ if (peek() != '=')
+ {
+ parse_error("Invalid operator");
+ return nullptr;
+ }
+ expr = new binary_operator<9, std::equal_to<valty>>(l, "==");
+ break;
+ case '!':
+ if (peek() != '=')
+ {
+ parse_error("Invalid operator");
+ return nullptr;
+ }
+ cursor++;
+ expr = new binary_operator<9, std::not_equal_to<valty>>(l, "!=");
+ break;
+ case '&':
+ if (peek() == '&')
+ {
+ expr = new binary_operator<13, std::logical_and<valty>>(l, "&&");
+ }
+ else
+ {
+ expr = new binary_operator<10, std::bit_and<valty>>(l, "&");
+ }
+ break;
+ case '|':
+ if (peek() == '|')
+ {
+ expr = new binary_operator<12, std::logical_or<valty>>(l, "||");
+ }
+ else
+ {
+ expr = new binary_operator<14, std::bit_or<valty>>(l, "|");
+ }
+ break;
+ case '?':
+ {
+ consume('?');
+ expression_ptr true_case = parse_expression();
+ next_token();
+ if (!true_case || !consume(':'))
+ {
+ parse_error("Expected : in ternary conditional operator");
+ return nullptr;
+ }
+ expression_ptr false_case = parse_expression();
+ if (!false_case)
+ {
+ parse_error("Expected false condition for ternary operator");
+ return nullptr;
+ }
+ return expression_ptr(new ternary_conditional_operator(l, std::move(lhs),
+ std::move(true_case), std::move(false_case)));
+ }
+ }
+ ++(*this);
+ next_token();
+ expression_ptr e(expr);
+ expression_ptr rhs(parse_expression());
+ if (!rhs)
+ {
+ return nullptr;
+ }
+ expr->lhs = std::move(lhs);
+ if (rhs->precedence() < expr->precedence())
+ {
+ expr->rhs = std::move(rhs);
+ }
+ else
+ {
+ // If we're a normal left-to-right expression, then we need to insert
+ // this as the far-left child node of the rhs expression
+ binary_operator_base *rhs_op =
+ static_cast<binary_operator_base*>(rhs.get());
+ rhs_op->insert_left(expr);
+ e.release();
+ return rhs;
+ }
+ return e;
+}
+
+expression_ptr text_input_buffer::parse_expression(bool stopAtParen)
+{
+ next_token();
+ unsigned long long leftVal;
+ expression_ptr lhs;
+ source_location l = location();
+ switch (*(*this))
+ {
+ case '0'...'9':
+ if (!consume_integer(leftVal))
+ {
+ return nullptr;
+ }
+ lhs.reset(new terminal_expr(l, leftVal));
+ break;
+ case '(':
+ {
+ consume('(');
+ expression_ptr &&subexpr = parse_expression();
+ if (!subexpr)
+ {
+ return nullptr;
+ }
+ lhs.reset(new paren_expression(l, std::move(subexpr)));
+ if (!consume(')'))
+ {
+ return nullptr;
+ }
+ if (stopAtParen)
+ {
+ return lhs;
+ }
+ break;
+ }
+ case '+':
+ {
+ consume('+');
+ expression_ptr &&subexpr = parse_expression();
+ if (!subexpr)
+ {
+ return nullptr;
+ }
+ lhs.reset(new unary_operator<'+', unary_plus<valty>>(l, std::move(subexpr)));
+ break;
+ }
+ case '-':
+ {
+ consume('-');
+ expression_ptr &&subexpr = parse_expression();
+ if (!subexpr)
+ {
+ return nullptr;
+ }
+ lhs.reset(new unary_operator<'-', std::negate<valty>>(l, std::move(subexpr)));
+ break;
+ }
+ case '!':
+ {
+ consume('!');
+ expression_ptr &&subexpr = parse_expression();
+ if (!subexpr)
+ {
+ return nullptr;
+ }
+ lhs.reset(new unary_operator<'!', std::logical_not<valty>>(l, std::move(subexpr)));
+ break;
+ }
+ case '~':
+ {
+ consume('~');
+ expression_ptr &&subexpr = parse_expression();
+ if (!subexpr)
+ {
+ return nullptr;
+ }
+ lhs.reset(new unary_operator<'~', bit_not<valty>>(l, std::move(subexpr)));
+ break;
+ }
+ }
+ if (!lhs)
+ {
+ return nullptr;
+ }
+ return parse_binary_expression(std::move(lhs));
+}
+
+bool
+text_input_buffer::consume_integer_expression(unsigned long long &outInt)
+{
+ switch (*(*this))
+ {
+ case '(':
+ {
+ expression_ptr e(parse_expression(true));
+ if (!e)
+ {
+ return false;
+ }
+ auto r = (*e)();
+ if (r.second)
+ {
+ outInt = r.first;
+ return true;
+ }
+ return false;
+ }
+ case '0'...'9':
+ return consume_integer(outInt);
+ default:
+ return false;
+ }
+}
+
+bool
+input_buffer::consume_hex_byte(uint8_t &outByte)
+{
+ if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
+ {
+ return false;
+ }
+ outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
+ cursor += 2;
+ return true;
+}
+
+text_input_buffer&
+text_input_buffer::next_token()
+{
+ auto &self = *this;
+ int start;
+ do {
+ start = cursor;
+ skip_spaces();
+ if (finished())
+ {
+ return self;
+ }
+ // Parse /* comments
+ if (*self == '/' && peek() == '*')
+ {
+ // eat the start of the comment
+ ++self;
+ ++self;
+ do {
+ // Find the ending * of */
+ while ((*self != '\0') && (*self != '*') && !finished())
+ {
+ ++self;
+ }
+ // Eat the *
+ ++self;
+ } while ((*self != '\0') && (*self != '/') && !finished());
+ // Eat the /
+ ++self;
+ }
+ // Parse // comments
+ if ((*self == '/' && peek() == '/'))
+ {
+ // eat the start of the comment
+ ++self;
+ ++self;
+ // Find the ending of the line
+ while (*self != '\n' && !finished())
+ {
+ ++self;
+ }
+ // Eat the \n
+ ++self;
+ }
+ } while (start != cursor);
+ return self;
+}
+
+void
+text_input_buffer::parse_error(const char *msg)
+{
+ if (input_stack.empty())
+ {
+ fprintf(stderr, "Error: %s\n", msg);
+ return;
+ }
+ input_buffer &b = *input_stack.top();
+ parse_error(msg, b, b.cursor);
+}
+void
+text_input_buffer::parse_error(const char *msg,
+ input_buffer &b,
+ int loc)
+{
+ int line_count = 1;
+ int line_start = 0;
+ int line_end = loc;
+ if (loc < 0 || loc > b.size)
+ {
+ return;
+ }
+ for (int i=loc ; i>0 ; --i)
+ {
+ if (b.buffer[i] == '\n')
+ {
+ line_count++;
+ if (line_start == 0)
+ {
+ line_start = i+1;
+ }
+ }
+ }
+ for (int i=loc+1 ; i<b.size ; ++i)
+ {
+ if (b.buffer[i] == '\n')
+ {
+ line_end = i;
+ break;
+ }
+ }
+ fprintf(stderr, "Error at %s:%d:%d: %s\n", b.filename().c_str(), line_count, loc - line_start, msg);
+ fwrite(&b.buffer[line_start], line_end-line_start, 1, stderr);
+ putc('\n', stderr);
+ for (int i=0 ; i<(loc-line_start) ; ++i)
+ {
+ char c = (b.buffer[i+line_start] == '\t') ? '\t' : ' ';
+ putc(c, stderr);
+ }
+ putc('^', stderr);
+ putc('\n', stderr);
+}
+#ifndef NDEBUG
+void
+input_buffer::dump()
+{
+ fprintf(stderr, "Current cursor: %d\n", cursor);
+ fwrite(&buffer[cursor], size-cursor, 1, stderr);
+}
+#endif
+
+
+namespace
+{
+/**
+ * The source files are ASCII, so we provide a non-locale-aware version of
+ * isalpha. This is a class so that it can be used with a template function
+ * for parsing strings.
+ */
+struct is_alpha
+{
+ static inline bool check(const char c)
+ {
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') &&
+ (c <= 'Z'));
+ }
+};
+/**
+ * Check whether a character is in the set allowed for node names. This is a
+ * class so that it can be used with a template function for parsing strings.
+ */
+struct is_node_name_character
+{
+ static inline bool check(const char c)
+ {
+ switch(c)
+ {
+ default:
+ return false;
+ case 'a'...'z': case 'A'...'Z': case '0'...'9':
+ case ',': case '.': case '+': case '-':
+ case '_':
+ return true;
+ }
+ }
+};
+/**
+ * Check whether a character is in the set allowed for property names. This is
+ * a class so that it can be used with a template function for parsing strings.
+ */
+struct is_property_name_character
+{
+ static inline bool check(const char c)
+ {
+ switch(c)
+ {
+ default:
+ return false;
+ case 'a'...'z': case 'A'...'Z': case '0'...'9':
+ case ',': case '.': case '+': case '-':
+ case '_': case '#':
+ return true;
+ }
+ }
+};
+
+template<class T>
+string parse(text_input_buffer &s)
+{
+ std::vector<char> bytes;
+ for (char c=*s ; T::check(c) ; c=*(++s))
+ {
+ bytes.push_back(c);
+ }
+ return string(bytes.begin(), bytes.end());
+}
+
+}
+
+string
+text_input_buffer::parse_node_name()
+{
+ return parse<is_node_name_character>(*this);
+}
+
+string
+text_input_buffer::parse_property_name()
+{
+ return parse<is_property_name_character>(*this);
+}
+
+string
+text_input_buffer::parse_node_or_property_name(bool &is_property)
+{
+ if (is_property)
+ {
+ return parse_property_name();
+ }
+ std::vector<char> bytes;
+ for (char c=*(*this) ; is_node_name_character::check(c) ; c=*(++(*this)))
+ {
+ bytes.push_back(c);
+ }
+ for (char c=*(*this) ; is_property_name_character::check(c) ; c=*(++(*this)))
+ {
+ bytes.push_back(c);
+ is_property = true;
+ }
+ return string(bytes.begin(), bytes.end());
+}
+
+string
+input_buffer::parse_to(char stop)
+{
+ std::vector<char> bytes;
+ for (char c=*(*this) ; c != stop ; c=*(++(*this)))
+ {
+ bytes.push_back(c);
+ }
+ return string(bytes.begin(), bytes.end());
+}
+
+string
+text_input_buffer::parse_to(char stop)
+{
+ std::vector<char> bytes;
+ for (char c=*(*this) ; c != stop ; c=*(++(*this)))
+ {
+ if (finished())
+ {
+ break;
+ }
+ bytes.push_back(c);
+ }
+ return string(bytes.begin(), bytes.end());
+}
+
+char
+text_input_buffer::peek()
+{
+ return (*input_stack.top())[1];
+}
+
+std::unique_ptr<input_buffer>
+input_buffer::buffer_for_file(const string &path, bool warn)
+{
+ if (path == "-")
+ {
+ std::unique_ptr<input_buffer> b(new stream_input_buffer());
+ return b;
+ }
+ int source = open(path.c_str(), O_RDONLY);
+ if (source == -1)
+ {
+ if (warn)
+ {
+ fprintf(stderr, "Unable to open file '%s'. %s\n", path.c_str(), strerror(errno));
+ }
+ return 0;
+ }
+ struct stat st;
+ if (fstat(source, &st) == 0 && S_ISDIR(st.st_mode))
+ {
+ if (warn)
+ {
+ fprintf(stderr, "File %s is a directory\n", path.c_str());
+ }
+ close(source);
+ return 0;
+ }
+ std::unique_ptr<input_buffer> b(new mmap_input_buffer(source, string(path)));
+ close(source);
+ return b;
+}
+
+} // namespace dtc
+
diff --git a/usr.bin/dtc/input_buffer.hh b/usr.bin/dtc/input_buffer.hh
new file mode 100644
index 000000000000..d6b033952bad
--- /dev/null
+++ b/usr.bin/dtc/input_buffer.hh
@@ -0,0 +1,552 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _INPUT_BUFFER_HH_
+#define _INPUT_BUFFER_HH_
+#include "util.hh"
+#include <assert.h>
+#include <stack>
+#include <string>
+#include <unordered_set>
+
+namespace dtc
+{
+
+namespace {
+struct expression;
+typedef std::unique_ptr<expression> expression_ptr;
+}
+
+/**
+ * Class encapsulating the input file. Can be used as a const char*, but has
+ * range checking. Attempting to access anything out of range will return a 0
+ * byte. The input buffer can be cheaply copied, without copying the
+ * underlying memory, however it is the user's responsibility to ensure that
+ * such copies do not persist beyond the lifetime of the underlying memory.
+ *
+ * This also contains methods for reporting errors and for consuming the token
+ * stream.
+ */
+class input_buffer
+{
+ friend class text_input_buffer;
+ protected:
+ /**
+ * The buffer. This class doesn't own the buffer, but the
+ * mmap_input_buffer subclass does.
+ */
+ const char* buffer;
+ /**
+ * The size of the buffer.
+ */
+ int size;
+ private:
+ /**
+ * The current place in the buffer where we are reading. This class
+ * keeps a separate size, pointer, and cursor so that we can move
+ * forwards and backwards and still have checks that we haven't fallen
+ * off either end.
+ */
+ int cursor;
+ /**
+ * Private constructor. This is used to create input buffers that
+ * refer to the same memory, but have different cursors.
+ */
+ input_buffer(const char* b, int s, int c) : buffer(b), size(s),
+ cursor(c) {}
+ public:
+ /**
+ * Returns the file name associated with this buffer.
+ */
+ virtual const std::string &filename() const
+ {
+ static std::string s;
+ return s;
+ }
+ static std::unique_ptr<input_buffer> buffer_for_file(const std::string &path,
+ bool warn=true);
+ /**
+ * Skips all characters in the input until the specified character is
+ * encountered.
+ */
+ void skip_to(char);
+ /**
+ * Parses up to a specified character and returns the intervening
+ * characters as a string.
+ */
+ std::string parse_to(char);
+ /**
+ * Return whether all input has been consumed.
+ */
+ bool finished() { return cursor >= size; }
+ /**
+ * Virtual destructor. Does nothing, but exists so that subclasses
+ * that own the memory can run cleanup code for deallocating it.
+ */
+ virtual ~input_buffer() {};
+ /**
+ * Constructs an empty buffer.
+ */
+ input_buffer() : buffer(0), size(0), cursor(0) {}
+ /**
+ * Constructs a new buffer with a specified memory region and size.
+ */
+ input_buffer(const char* b, int s) : buffer(b), size(s), cursor(0){}
+ /**
+ * Returns a new input buffer referring into this input, clamped to the
+ * specified size. If the requested buffer would fall outside the
+ * range of this one, then it returns an empty buffer.
+ *
+ * The returned buffer shares the same underlying storage as the
+ * original. This is intended to be used for splitting up the various
+ * sections of a device tree blob. Requesting a size of 0 will give a
+ * buffer that extends to the end of the available memory.
+ */
+ input_buffer buffer_from_offset(int offset, int s=0);
+ /**
+ * Dereferencing operator, allows the buffer to be treated as a char*
+ * and dereferenced to give a character. This returns a null byte if
+ * the cursor is out of range.
+ */
+ inline char operator*()
+ {
+ if (cursor >= size) { return '\0'; }
+ if (cursor < 0) { return '\0'; }
+ return buffer[cursor];
+ }
+ /**
+ * Array subscripting operator, returns a character at the specified
+ * index offset from the current cursor. The offset may be negative,
+ * to reread characters that have already been read. If the current
+ * cursor plus offset is outside of the range, this returns a nul
+ * byte.
+ */
+ inline char operator[](int offset)
+ {
+ if (cursor + offset >= size) { return '\0'; }
+ if (cursor + offset < 0) { return '\0'; }
+ return buffer[cursor + offset];
+ }
+ /**
+ * Increments the cursor, iterating forward in the buffer.
+ */
+ inline input_buffer &operator++()
+ {
+ cursor++;
+ return *this;
+ }
+ const char *begin()
+ {
+ return buffer;
+ }
+ const char *end()
+ {
+ return buffer + size;
+ }
+ /**
+ * Consumes a character. Moves the cursor one character forward if the
+ * next character matches the argument, returning true. If the current
+ * character does not match the argument, returns false.
+ */
+ inline bool consume(char c)
+ {
+ if (*(*this) == c)
+ {
+ ++(*this);
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Consumes a string. If the (null-terminated) string passed as the
+ * argument appears in the input, advances the cursor to the end and
+ * returns true. Returns false if the string does not appear at the
+ * current point in the input.
+ */
+ bool consume(const char *str);
+ /**
+ * Reads an integer in base 8, 10, or 16. Returns true and advances
+ * the cursor to the end of the integer if the cursor points to an
+ * integer, returns false and does not move the cursor otherwise.
+ *
+ * The parsed value is returned via the argument.
+ */
+ bool consume_integer(unsigned long long &outInt);
+ /**
+ * Reads an arithmetic expression (containing any of the normal C
+ * operators), evaluates it, and returns the result.
+ */
+ bool consume_integer_expression(unsigned long long &outInt);
+ /**
+ * Consumes two hex digits and return the resulting byte via the first
+ * argument. If the next two characters are hex digits, returns true
+ * and advances the cursor. If not, then returns false and leaves the
+ * cursor in place.
+ */
+ bool consume_hex_byte(uint8_t &outByte);
+ /**
+ * Template function that consumes a binary value in big-endian format
+ * from the input stream. Returns true and advances the cursor if
+ * there is a value of the correct size. This function assumes that
+ * all values must be natively aligned, and so advances the cursor to
+ * the correct alignment before reading.
+ */
+ template<typename T>
+ bool consume_binary(T &out)
+ {
+ int align = 0;
+ int type_size = sizeof(T);
+ if (cursor % type_size != 0)
+ {
+ align = type_size - (cursor % type_size);
+ }
+ if (size < cursor + align + type_size)
+ {
+ return false;
+ }
+ cursor += align;
+ assert(cursor % type_size == 0);
+ out = 0;
+ for (int i=0 ; i<type_size ; ++i)
+ {
+ if (size < cursor)
+ {
+ return false;
+ }
+ out <<= 8;
+ out |= (((T)buffer[cursor++]) & 0xff);
+ }
+ return true;
+ }
+#ifndef NDEBUG
+ /**
+ * Dumps the current cursor value and the unconsumed values in the
+ * input buffer to the standard error. This method is intended solely
+ * for debugging.
+ */
+ void dump();
+#endif
+};
+/**
+ * Explicit specialisation for reading a single byte.
+ */
+template<>
+inline bool input_buffer::consume_binary(uint8_t &out)
+{
+ if (size < cursor + 1)
+ {
+ return false;
+ }
+ out = buffer[cursor++];
+ return true;
+}
+
+/**
+ * An input buffer subclass used for parsing DTS files. This manages a stack
+ * of input buffers to handle /input/ operations.
+ */
+class text_input_buffer
+{
+ std::unordered_set<std::string> defines;
+ /**
+ * The cursor is the input into the input stream where we are currently reading.
+ */
+ int cursor = 0;
+ /**
+ * The current stack of includes. The current input is always from the top
+ * of the stack.
+ */
+ std::stack<std::shared_ptr<input_buffer>> input_stack;
+ /**
+ *
+ */
+ const std::vector<std::string> include_paths;
+ /**
+ * Reads forward past any spaces. The DTS format is not whitespace
+ * sensitive and so we want to scan past whitespace when reading it.
+ */
+ void skip_spaces();
+ /**
+ * Returns the character immediately after the current one.
+ *
+ * This method does not look between files.
+ */
+ char peek();
+ /**
+ * If a /include/ token is encountered, then look up the corresponding
+ * input file, push it onto the input stack, and continue.
+ */
+ void handle_include();
+ /**
+ * The base directory for this file.
+ */
+ const std::string dir;
+ /**
+ * The file where dependencies should be output.
+ */
+ FILE *depfile;
+ public:
+ /**
+ * Construct a new text input buffer with the specified buffer as the start
+ * of parsing and the specified set of input paths for handling new
+ * inclusions.
+ */
+ text_input_buffer(std::unique_ptr<input_buffer> &&b,
+ std::unordered_set<std::string> &&d,
+ std::vector<std::string> &&i,
+ const std::string directory,
+ FILE *deps)
+ : defines(d), include_paths(i), dir(directory), depfile(deps)
+ {
+ input_stack.push(std::move(b));
+ }
+ /**
+ * Skips all characters in the input until the specified character is
+ * encountered.
+ */
+ void skip_to(char);
+ /**
+ * Parse an expression. If `stopAtParen` is set, then only parse a number
+ * or a parenthetical expression, otherwise assume that either is the
+ * left-hand side of a binary expression and try to parse the right-hand
+ * side.
+ */
+ expression_ptr parse_expression(bool stopAtParen=false);
+ /**
+ * Parse a binary expression, having already parsed the right-hand side.
+ */
+ expression_ptr parse_binary_expression(expression_ptr lhs);
+ /**
+ * Return whether all input has been consumed.
+ */
+ bool finished()
+ {
+ return input_stack.empty() ||
+ ((input_stack.size() == 1) && input_stack.top()->finished());
+ }
+ /**
+ * Dereferencing operator. Returns the current character in the top input buffer.
+ */
+ inline char operator*()
+ {
+ if (input_stack.empty())
+ {
+ return 0;
+ }
+ return *(*input_stack.top());
+ }
+ /**
+ * Increments the cursor, iterating forward in the buffer.
+ */
+ inline text_input_buffer &operator++()
+ {
+ if (input_stack.empty())
+ {
+ return *this;
+ }
+ cursor++;
+ auto &top = *input_stack.top();
+ ++top;
+ if (top.finished())
+ {
+ input_stack.pop();
+ }
+ return *this;
+ }
+ /**
+ * Consumes a character. Moves the cursor one character forward if the
+ * next character matches the argument, returning true. If the current
+ * character does not match the argument, returns false.
+ */
+ inline bool consume(char c)
+ {
+ if (*(*this) == c)
+ {
+ ++(*this);
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Consumes a string. If the (null-terminated) string passed as the
+ * argument appears in the input, advances the cursor to the end and
+ * returns true. Returns false if the string does not appear at the
+ * current point in the input.
+ *
+ * This method does not scan between files.
+ */
+ bool consume(const char *str)
+ {
+ if (input_stack.empty())
+ {
+ return false;
+ }
+ return input_stack.top()->consume(str);
+ }
+ /**
+ * Reads an integer in base 8, 10, or 16. Returns true and advances
+ * the cursor to the end of the integer if the cursor points to an
+ * integer, returns false and does not move the cursor otherwise.
+ *
+ * The parsed value is returned via the argument.
+ *
+ * This method does not scan between files.
+ */
+ bool consume_integer(unsigned long long &outInt)
+ {
+ if (input_stack.empty())
+ {
+ return false;
+ }
+ return input_stack.top()->consume_integer(outInt);
+ }
+ /**
+ * Reads an arithmetic expression (containing any of the normal C
+ * operators), evaluates it, and returns the result.
+ */
+ bool consume_integer_expression(unsigned long long &outInt);
+ /**
+ * Consumes two hex digits and return the resulting byte via the first
+ * argument. If the next two characters are hex digits, returns true
+ * and advances the cursor. If not, then returns false and leaves the
+ * cursor in place.
+ *
+ * This method does not scan between files.
+ */
+ bool consume_hex_byte(uint8_t &outByte)
+ {
+ if (input_stack.empty())
+ {
+ return false;
+ }
+ return input_stack.top()->consume_hex_byte(outByte);
+ }
+ /**
+ * Returns the longest string in the input buffer starting at the
+ * current cursor and composed entirely of characters that are valid in
+ * node names.
+ */
+ std::string parse_node_name();
+ /**
+ * Returns the longest string in the input buffer starting at the
+ * current cursor and composed entirely of characters that are valid in
+ * property names.
+ */
+ std::string parse_property_name();
+ /**
+ * Parses either a node or a property name. If is_property is true on
+ * entry, then only property names are parsed. If it is false, then it
+ * will be set, on return, to indicate whether the parsed name is only
+ * valid as a property.
+ */
+ std::string parse_node_or_property_name(bool &is_property);
+ /**
+ * Parses up to a specified character and returns the intervening
+ * characters as a string.
+ */
+ std::string parse_to(char);
+ /**
+ * Advances the cursor to the start of the next token, skipping
+ * comments and whitespace. If the cursor already points to the start
+ * of a token, then this function does nothing.
+ */
+ text_input_buffer &next_token();
+ /**
+ * Location in the source file. This should never be interpreted by
+ * anything other than error reporting functions of this class. It will
+ * eventually become something more complex than an `int`.
+ */
+ class source_location
+ {
+ friend class text_input_buffer;
+ /**
+ * The text buffer object that included `b`.
+ */
+ text_input_buffer &buffer;
+ /**
+ * The underlying buffer that contains this location.
+ */
+ std::shared_ptr<input_buffer> b;
+ /**
+ * The offset within the current buffer of the source location.
+ */
+ int cursor;
+ source_location(text_input_buffer &buf)
+ : buffer(buf),
+ b(buf.input_stack.empty() ? nullptr : buf.input_stack.top()),
+ cursor(b ? b->cursor : 0) {}
+ public:
+ /**
+ * Report an error at this location.
+ */
+ void report_error(const char *msg)
+ {
+ if (b)
+ {
+ buffer.parse_error(msg, *b, cursor);
+ }
+ else
+ {
+ buffer.parse_error(msg);
+ }
+ }
+ };
+ /**
+ * Returns the current source location.
+ */
+ source_location location()
+ {
+ return { *this };
+ }
+ /**
+ * Prints a message indicating the location of a parse error.
+ */
+ void parse_error(const char *msg);
+ /**
+ * Reads the contents of a binary file into `b`. The file name is assumed
+ * to be relative to one of the include paths.
+ *
+ * Returns true if the file exists and can be read, false otherwise.
+ */
+ bool read_binary_file(const std::string &filename, byte_buffer &b);
+ private:
+ /**
+ * Prints a message indicating the location of a parse error, given a
+ * specified location. This is used when input has already moved beyond
+ * the location that caused the failure.
+ */
+ void parse_error(const char *msg, input_buffer &b, int loc);
+};
+
+} // namespace dtc
+
+#endif // !_INPUT_BUFFER_HH_
diff --git a/usr.bin/dtc/string.cc b/usr.bin/dtc/string.cc
new file mode 100644
index 000000000000..9179394c509b
--- /dev/null
+++ b/usr.bin/dtc/string.cc
@@ -0,0 +1,150 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 <string>
+#include <functional>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctype.h>
+#include <libgen.h>
+
+#include "util.hh"
+
+using std::string;
+
+namespace dtc
+{
+
+void
+push_string(byte_buffer &buffer, const string &s, bool escapes)
+{
+ size_t length = s.size();
+ for (size_t i=0 ; i<length ; ++i)
+ {
+ uint8_t c = s[i];
+ if (escapes && c == '\\' && i+1 < length)
+ {
+ c = s[++i];
+ switch (c)
+ {
+ // For now, we just ignore invalid escape sequences.
+ default:
+ case '"':
+ case '\'':
+ case '\\':
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case '0'...'7':
+ {
+ int v = digittoint(c);
+ if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
+ {
+ v <<= 3;
+ v |= digittoint(s[i+1]);
+ i++;
+ if (i+1 < length && s[i+1] <= '7' && s[i+1] >= '0')
+ {
+ v <<= 3;
+ v |= digittoint(s[i+1]);
+ }
+ }
+ c = (uint8_t)v;
+ break;
+ }
+ case 'x':
+ {
+ ++i;
+ if (i >= length)
+ {
+ break;
+ }
+ int v = digittoint(s[i]);
+ if (i+1 < length && ishexdigit(s[i+1]))
+ {
+ v <<= 4;
+ v |= digittoint(s[++i]);
+ }
+ c = (uint8_t)v;
+ break;
+ }
+ }
+ }
+ buffer.push_back(c);
+ }
+}
+
+namespace {
+string
+dirbasename(std::function<char*(char*)> fn, const string &s)
+{
+ if (s == string())
+ {
+ return string();
+ }
+ std::unique_ptr<char, decltype(free)*> str = {strdup(s.c_str()), free};
+ string dn(fn(str.get()));
+ return dn;
+}
+}
+
+string dirname(const string &s)
+{
+ return dirbasename(::dirname, s);
+}
+
+string basename(const string &s)
+{
+ return dirbasename(::basename, s);
+}
+} // namespace dtc
+
diff --git a/usr.bin/dtc/util.hh b/usr.bin/dtc/util.hh
new file mode 100644
index 000000000000..3a67a48829c6
--- /dev/null
+++ b/usr.bin/dtc/util.hh
@@ -0,0 +1,150 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 David Chisnall
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _UTIL_HH_
+#define _UTIL_HH_
+
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+// If we aren't using C++11, then just ignore static asserts.
+#if __cplusplus < 201103L
+#ifndef static_assert
+#define static_assert(x, y) ((void)0)
+#endif
+#endif
+
+#ifdef MISSING_DIGITTOINT
+namespace
+{
+ /**
+ * Glibc doesn't have a definition of digittoint, so provide our own.
+ */
+ inline int digittoint(int c)
+ {
+ switch (c)
+ {
+ default:
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a': return 10;
+ case 'b': return 11;
+ case 'c': return 12;
+ case 'd': return 13;
+ case 'e': return 14;
+ case 'f': return 15;
+ }
+ }
+}
+#endif
+
+namespace dtc {
+
+/**
+ * Type for a buffer of bytes. This is used for a lot of short-lived temporary
+ * variables, so may eventually be changed to something like LLVM's
+ * SmallVector, but currently the program runs in a tiny fraction of a second,
+ * so this is not an issue.
+ */
+typedef std::vector<uint8_t> byte_buffer;
+
+/**
+ * Helper function to push a big endian value into a byte buffer. We use
+ * native-endian values for all of the in-memory data structures and only
+ * transform them into big endian form for output.
+ */
+template<typename T>
+inline void push_big_endian(byte_buffer &v, T val)
+{
+ static_assert(sizeof(T) > 1,
+ "Big endian doesn't make sense for single-byte values");
+ for (int bit=(sizeof(T) - 1)*8 ; bit>=0 ; bit-= 8)
+ {
+ v.push_back((val >> bit) & 0xff);
+ }
+}
+
+void push_string(byte_buffer &v, const std::string &s, bool escapes=false);
+
+/**
+ * Simple inline non-locale-aware check that this is a valid ASCII
+ * digit.
+ */
+inline bool isdigit(char c)
+{
+ return (c >= '0') && (c <= '9');
+}
+
+/**
+ * Simple inline non-locale-aware check that this is a valid ASCII
+ * hex digit.
+ */
+inline bool ishexdigit(char c)
+{
+ return ((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) ||
+ ((c >= 'A') && (c <= 'F'));
+}
+
+/**
+ * Simple inline non-locale-aware check that this is a valid ASCII
+ * letter.
+ */
+inline bool isalpha(char c)
+{
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+}
+
+/**
+ * A wrapper around dirname(3) that handles inconsistencies relating to memory
+ * management between platforms and provides a std::string interface.
+ */
+std::string dirname(const std::string&);
+
+/**
+ * A wrapper around basename(3) that handles inconsistencies relating to memory
+ * management between platforms and provides a std::string interface.
+ */
+std::string basename(const std::string&);
+
+}// namespace dtc
+
+#endif // !_UTIL_HH_
diff --git a/usr.bin/du/Makefile b/usr.bin/du/Makefile
new file mode 100644
index 000000000000..b12a05447999
--- /dev/null
+++ b/usr.bin/du/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+PROG= du
+LIBADD= xo util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/du/Makefile.depend b/usr.bin/du/Makefile.depend
new file mode 100644
index 000000000000..b915f0b12d3b
--- /dev/null
+++ b/usr.bin/du/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1
new file mode 100644
index 000000000000..568fded38073
--- /dev/null
+++ b/usr.bin/du/du.1
@@ -0,0 +1,305 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd April 29, 2024
+.Dt DU 1
+.Os
+.Sh NAME
+.Nm du
+.Nd display disk usage statistics
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl Aclnx
+.Op Fl H | L | P
+.Op Fl g | h | k | m
+.Op Fl a | s | d Ar depth
+.Op Fl B Ar blocksize
+.Op Fl I Ar mask
+.Op Fl t Ar threshold
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the file system block usage for each file argument
+and for each directory in the file hierarchy rooted in each directory
+argument.
+If no file is specified, the block usage of the hierarchy rooted in
+the current directory is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl A
+Display the apparent size instead of the disk usage.
+This can be helpful when operating on compressed volumes or sparse files.
+.It Fl B Ar blocksize
+Calculate block counts in
+.Ar blocksize
+byte blocks.
+This is different from the
+.Fl h , k , m ,
+.Fl Fl si
+and
+.Fl g
+options or setting
+.Ev BLOCKSIZE
+and gives an estimate of how much space the examined file hierarchy would
+require on a filesystem with the given
+.Ar blocksize .
+Unless in
+.Fl A
+mode,
+.Ar blocksize
+is rounded up to the next multiple of 512.
+.It Fl H
+Symbolic links on the command line are followed, symbolic links in file
+hierarchies are not followed.
+.It Fl I Ar mask
+Ignore files and directories matching the specified
+.Ar mask .
+.It Fl L
+Symbolic links on the command line and in file hierarchies are followed.
+.It Fl P
+No symbolic links are followed.
+This is the default.
+.It Fl a
+Display an entry for each file in a file hierarchy.
+.It Fl c
+Display a grand total.
+.It Fl d Ar depth
+Display an entry for all files and directories
+.Ar depth
+directories deep.
+.It Fl g
+Display block counts in 1073741824-byte (1 GiB) blocks.
+.It Fl h
+.Dq Human-readable
+output.
+Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte based on powers of 1024.
+.It Fl k
+Display block counts in 1024-byte (1 kiB) blocks.
+.It Fl l
+If a file has multiple hard links, count its size multiple times.
+The default behavior of
+.Nm
+is to count files with multiple hard links only once.
+When the
+.Fl l
+option is specified, the hard link checks are disabled, and these files
+are counted (and displayed) as many times as they are found.
+.It Fl m
+Display block counts in 1048576-byte (1 MiB) blocks.
+.It Fl n
+Ignore files and directories with user
+.Dq nodump
+flag
+.Pq Dv UF_NODUMP
+set.
+.It Fl r
+Generate messages about directories that cannot be read, files
+that cannot be opened, and so on.
+This is the default case.
+This option exists solely for conformance with
+.St -xpg4 .
+.It Fl s
+Display an entry for each specified file.
+(Equivalent to
+.Fl d Li 0 )
+.It Fl Fl si
+.Dq Human-readable
+output.
+Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte based on powers of 1000.
+.It Fl t Ar threshold
+Display only entries for which size exceeds
+.Ar threshold .
+If
+.Ar threshold
+is negative, display only entries for which size is less than the absolute
+value of
+.Ar threshold .
+.It Fl x
+File system mount points are not traversed.
+.El
+.Pp
+The
+.Nm
+utility counts the storage used by symbolic links and not the files they
+reference unless the
+.Fl H
+or
+.Fl L
+option is specified.
+If either the
+.Fl H
+or
+.Fl L
+option is specified, storage used by any symbolic links which are
+followed is not counted (or displayed).
+The
+.Fl H ,
+.Fl L
+and
+.Fl P
+options override each other and the command's actions are determined
+by the last one specified.
+.Pp
+The
+.Fl h , k , m
+and
+.Fl Fl si
+options all override each other; the last one specified determines
+the block counts used.
+.Sh ENVIRONMENT
+.Bl -tag -width BLOCKSIZE
+.It Ev BLOCKSIZE
+If the environment variable
+.Ev BLOCKSIZE
+is set, and the
+.Fl h , k , m
+or
+.Fl Fl si
+options are not specified, the block counts will be displayed in units of
+that block size.
+If
+.Ev BLOCKSIZE
+is not set, and the
+.Fl h , k , m
+or
+.Fl Fl si
+options are not specified, the block counts will be displayed in 512-byte
+blocks.
+.El
+.Sh EXAMPLES
+Show disk usage for all files in the current directory.
+Output is in human-readable form:
+.Pp
+.Dl # du -ah
+.Pp
+Summarize disk usage in the current directory:
+.Pp
+.Dl # du -hs
+.Pp
+Summarize disk usage for a specific directory:
+.Pp
+.Dl # du -hs /home
+.Pp
+Show name and size of all C files in a specific directory.
+Also display a grand total at the end:
+.Pp
+.Dl # du -ch /usr/src/sys/kern/*.c
+.Sh SEE ALSO
+.Xr df 1 ,
+.Xr chflags 2 ,
+.Xr fts 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
+.Xr symlink 7 ,
+.Xr quot 8
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl cdhP ,
+as well as the
+.Ev BLOCKSIZE
+environment variable,
+are extensions to that specification.
+.Pp
+The flag
+.Op Fl r
+is accepted but ignored, for compatibility with systems implementing
+the obsolete
+.St -xcu5
+standard.
+.Sh HISTORY
+The
+.Nm
+utility and its
+.Fl a
+and
+.Fl s
+options first appeared in
+.At v1 .
+.Pp
+The
+.Fl r
+option first appeared in
+.At III
+and is available since
+.Fx 3.5 .
+The
+.Fl k
+and
+.Fl x
+options first appeared in
+.Bx 4.3 Reno
+and
+.Fl H
+in
+.Bx 4.4 .
+The
+.Fl c
+and
+.Fl L
+options first appeared in the GNU fileutils;
+.Fl L
+and
+.Fl P
+are available since
+.Bx 4.4 Lite1 ,
+.Fl c
+since
+.Fx 2.2.6 .
+The
+.Fl d
+option first appeared in
+.Fx 2.2 ,
+.Fl h
+first appeared in
+.Fx 4.0 .
+.Sh AUTHORS
+.An -nosplit
+This version of
+.Nm
+was written by
+.An Chris Newcomb
+for
+.Bx 4.3 Reno
+in 1989.
diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c
new file mode 100644
index 000000000000..185a5cbe4465
--- /dev/null
+++ b/usr.bin/du/du.c
@@ -0,0 +1,570 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Newcomb.
+ *
+ * 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>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <fts.h>
+#include <getopt.h>
+#include <libutil.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+
+#define SI_OPT (CHAR_MAX + 1)
+
+#define UNITS_2 1
+#define UNITS_SI 2
+
+#define DU_XO_VERSION "1"
+
+static SLIST_HEAD(ignhead, ignentry) ignores;
+struct ignentry {
+ char *mask;
+ SLIST_ENTRY(ignentry) next;
+};
+
+static int linkchk(FTSENT *);
+static void usage(void);
+static void prthumanval(const char *, int64_t);
+static void ignoreadd(const char *);
+static void ignoreclean(void);
+static int ignorep(FTSENT *);
+static void siginfo(int __unused);
+
+static int nodumpflag = 0;
+static int Aflag, hflag;
+static long blocksize, cblocksize;
+static volatile sig_atomic_t info;
+
+static const struct option long_options[] =
+{
+ { "si", no_argument, NULL, SI_OPT },
+ { NULL, no_argument, NULL, 0 },
+};
+
+int
+main(int argc, char *argv[])
+{
+ FTS *fts;
+ FTSENT *p;
+ off_t savednumber, curblocks;
+ off_t threshold, threshold_sign;
+ int ftsoptions;
+ int depth;
+ int Hflag, Lflag, aflag, sflag, dflag, cflag;
+ int lflag, ch, notused, rval;
+ char **save;
+ static char dot[] = ".";
+
+ setlocale(LC_ALL, "");
+
+ Hflag = Lflag = aflag = sflag = dflag = cflag = lflag = Aflag = 0;
+
+ save = argv;
+ ftsoptions = FTS_PHYSICAL;
+ savednumber = 0;
+ threshold = 0;
+ threshold_sign = 1;
+ cblocksize = DEV_BSIZE;
+ blocksize = 0;
+ depth = INT_MAX;
+ SLIST_INIT(&ignores);
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(EX_USAGE);
+
+ while ((ch = getopt_long(argc, argv, "+AB:HI:LPasd:cghklmnrt:x",
+ long_options, NULL)) != -1)
+ switch (ch) {
+ case 'A':
+ Aflag = 1;
+ break;
+ case 'B':
+ errno = 0;
+ cblocksize = atoi(optarg);
+ if (errno == ERANGE || cblocksize <= 0) {
+ xo_warnx("invalid argument to option B: %s",
+ optarg);
+ usage();
+ }
+ break;
+ case 'H':
+ Hflag = 1;
+ Lflag = 0;
+ break;
+ case 'I':
+ ignoreadd(optarg);
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = 0;
+ break;
+ case 'P':
+ Hflag = Lflag = 0;
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ errno = 0;
+ depth = atoi(optarg);
+ if (errno == ERANGE || depth < 0) {
+ xo_warnx("invalid argument to option d: %s",
+ optarg);
+ usage();
+ }
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'g':
+ hflag = 0;
+ blocksize = 1073741824;
+ break;
+ case 'h':
+ hflag = UNITS_2;
+ break;
+ case 'k':
+ hflag = 0;
+ blocksize = 1024;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'm':
+ hflag = 0;
+ blocksize = 1048576;
+ break;
+ case 'n':
+ nodumpflag = 1;
+ break;
+ case 'r': /* Compatibility. */
+ break;
+ case 't' :
+ if (expand_number(optarg, &threshold) != 0 ||
+ threshold == 0) {
+ xo_warnx("invalid threshold: %s", optarg);
+ usage();
+ } else if (threshold < 0)
+ threshold_sign = -1;
+ break;
+ case 'x':
+ ftsoptions |= FTS_XDEV;
+ break;
+ case SI_OPT:
+ hflag = UNITS_SI;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * XXX
+ * Because of the way that fts(3) works, logical walks will not count
+ * the blocks actually used by symbolic links. We rationalize this by
+ * noting that users computing logical sizes are likely to do logical
+ * copies, so not counting the links is correct. The real reason is
+ * that we'd have to re-implement the kernel's symbolic link traversing
+ * algorithm to get this right. If, for example, you have relative
+ * symbolic links referencing other relative symbolic links, it gets
+ * very nasty, very fast. The bottom line is that it's documented in
+ * the man page, so it's a feature.
+ */
+
+ if (Hflag)
+ ftsoptions |= FTS_COMFOLLOW;
+ if (Lflag) {
+ ftsoptions &= ~FTS_PHYSICAL;
+ ftsoptions |= FTS_LOGICAL;
+ }
+
+ if (!Aflag && (cblocksize % DEV_BSIZE) != 0)
+ cblocksize = howmany(cblocksize, DEV_BSIZE) * DEV_BSIZE;
+
+ if (aflag + dflag + sflag > 1)
+ usage();
+ if (sflag)
+ depth = 0;
+
+ if (!*argv) {
+ argv = save;
+ argv[0] = dot;
+ argv[1] = NULL;
+ }
+
+ if (blocksize == 0)
+ (void)getbsize(&notused, &blocksize);
+
+ if (!Aflag) {
+ cblocksize /= DEV_BSIZE;
+ blocksize /= DEV_BSIZE;
+ }
+
+ if (threshold != 0)
+ threshold = howmany(threshold / DEV_BSIZE * cblocksize,
+ blocksize);
+
+ rval = 0;
+
+ (void)signal(SIGINFO, siginfo);
+
+ if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
+ err(1, "fts_open");
+
+
+ xo_set_version(DU_XO_VERSION);
+ xo_open_container("disk-usage-information");
+ xo_open_list("paths");
+ while (errno = 0, (p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_D: /* Ignore. */
+ if (ignorep(p))
+ fts_set(fts, p, FTS_SKIP);
+ break;
+ case FTS_DP:
+ if (ignorep(p))
+ break;
+
+ curblocks = Aflag ?
+ howmany(p->fts_statp->st_size, cblocksize) :
+ howmany(p->fts_statp->st_blocks, cblocksize);
+ p->fts_parent->fts_bignum += p->fts_bignum +=
+ curblocks;
+
+ if (p->fts_level <= depth && threshold <=
+ threshold_sign * howmany(p->fts_bignum *
+ cblocksize, blocksize)) {
+ xo_open_instance("paths");
+ if (hflag > 0) {
+ prthumanval("{:blocks/%4s}",
+ p->fts_bignum);
+ xo_emit("\t{:path/%s}\n", p->fts_path);
+ } else {
+ xo_emit("{:blocks/%jd}\t{:path/%s}\n",
+ (intmax_t)howmany(p->fts_bignum *
+ cblocksize, blocksize),
+ p->fts_path);
+ }
+ xo_close_instance("paths");
+ }
+ if (info) {
+ info = 0;
+ (void)printf("\t%s\n", p->fts_path);
+ }
+ break;
+ case FTS_DC: /* Ignore. */
+ break;
+ case FTS_DNR: /* Warn, continue. */
+ case FTS_ERR:
+ case FTS_NS:
+ xo_warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ rval = 1;
+ break;
+ default:
+ if (ignorep(p))
+ break;
+
+ if (lflag == 0 && p->fts_statp->st_nlink > 1 &&
+ linkchk(p))
+ break;
+
+ curblocks = Aflag ?
+ howmany(p->fts_statp->st_size, cblocksize) :
+ howmany(p->fts_statp->st_blocks, cblocksize);
+
+ if (aflag || p->fts_level == 0) {
+ xo_open_instance("paths");
+ if (hflag > 0) {
+ prthumanval("{:blocks/%4s}", curblocks);
+ xo_emit("\t{:path/%s}\n", p->fts_path);
+ } else {
+ xo_emit("{:blocks/%jd}\t{:path/%s}\n",
+ (intmax_t)howmany(curblocks *
+ cblocksize, blocksize),
+ p->fts_path);
+ }
+ xo_close_instance("paths");
+ }
+
+ p->fts_parent->fts_bignum += curblocks;
+ }
+ savednumber = p->fts_parent->fts_bignum;
+ }
+ xo_close_list("paths");
+
+ if (errno)
+ xo_err(1, "fts_read");
+
+ if (cflag) {
+ if (hflag > 0) {
+ prthumanval("{:total-blocks/%4s}\ttotal\n",
+ savednumber);
+ } else {
+ xo_emit("{:total-blocks/%jd}\ttotal\n",
+ (intmax_t)howmany(
+ savednumber * cblocksize, blocksize));
+ }
+ }
+
+ ignoreclean();
+ xo_close_container("disk-usage-information");
+ if (xo_finish() < 0)
+ xo_err(1, "stdout");
+ exit(rval);
+}
+
+static int
+linkchk(FTSENT *p)
+{
+ struct links_entry {
+ struct links_entry *next;
+ struct links_entry *previous;
+ int links;
+ dev_t dev;
+ ino_t ino;
+ };
+ static const size_t links_hash_initial_size = 8192;
+ static struct links_entry **buckets;
+ static struct links_entry *free_list;
+ static size_t number_buckets;
+ static unsigned long number_entries;
+ static char stop_allocating;
+ struct links_entry *le, **new_buckets;
+ struct stat *st;
+ size_t i, new_size;
+ int hash;
+
+ st = p->fts_statp;
+
+ /* If necessary, initialize the hash table. */
+ if (buckets == NULL) {
+ number_buckets = links_hash_initial_size;
+ buckets = malloc(number_buckets * sizeof(buckets[0]));
+ if (buckets == NULL)
+ errx(1, "No memory for hardlink detection");
+ for (i = 0; i < number_buckets; i++)
+ buckets[i] = NULL;
+ }
+
+ /* If the hash table is getting too full, enlarge it. */
+ if (number_entries > number_buckets * 10 && !stop_allocating) {
+ new_size = number_buckets * 2;
+ new_buckets = calloc(new_size, sizeof(struct links_entry *));
+
+ /* Try releasing the free list to see if that helps. */
+ if (new_buckets == NULL && free_list != NULL) {
+ while (free_list != NULL) {
+ le = free_list;
+ free_list = le->next;
+ free(le);
+ }
+ new_buckets = calloc(new_size, sizeof(new_buckets[0]));
+ }
+
+ if (new_buckets == NULL) {
+ stop_allocating = 1;
+ xo_warnx("No more memory for tracking hard links");
+ } else {
+ for (i = 0; i < number_buckets; i++) {
+ while (buckets[i] != NULL) {
+ /* Remove entry from old bucket. */
+ le = buckets[i];
+ buckets[i] = le->next;
+
+ /* Add entry to new bucket. */
+ hash = (le->dev ^ le->ino) % new_size;
+
+ if (new_buckets[hash] != NULL)
+ new_buckets[hash]->previous =
+ le;
+ le->next = new_buckets[hash];
+ le->previous = NULL;
+ new_buckets[hash] = le;
+ }
+ }
+ free(buckets);
+ buckets = new_buckets;
+ number_buckets = new_size;
+ }
+ }
+
+ /* Try to locate this entry in the hash table. */
+ hash = ( st->st_dev ^ st->st_ino ) % number_buckets;
+ for (le = buckets[hash]; le != NULL; le = le->next) {
+ if (le->dev == st->st_dev && le->ino == st->st_ino) {
+ /*
+ * Save memory by releasing an entry when we've seen
+ * all of its links.
+ */
+ if (--le->links <= 0) {
+ if (le->previous != NULL)
+ le->previous->next = le->next;
+ if (le->next != NULL)
+ le->next->previous = le->previous;
+ if (buckets[hash] == le)
+ buckets[hash] = le->next;
+ number_entries--;
+ /* Recycle this node through the free list */
+ if (stop_allocating) {
+ free(le);
+ } else {
+ le->next = free_list;
+ free_list = le;
+ }
+ }
+ return (1);
+ }
+ }
+
+ if (stop_allocating)
+ return (0);
+
+ /* Add this entry to the links cache. */
+ if (free_list != NULL) {
+ /* Pull a node from the free list if we can. */
+ le = free_list;
+ free_list = le->next;
+ } else
+ /* Malloc one if we have to. */
+ le = malloc(sizeof(struct links_entry));
+ if (le == NULL) {
+ stop_allocating = 1;
+ xo_warnx("No more memory for tracking hard links");
+ return (0);
+ }
+ le->dev = st->st_dev;
+ le->ino = st->st_ino;
+ le->links = st->st_nlink - 1;
+ number_entries++;
+ le->next = buckets[hash];
+ le->previous = NULL;
+ if (buckets[hash] != NULL)
+ buckets[hash]->previous = le;
+ buckets[hash] = le;
+ return (0);
+}
+
+static void
+prthumanval(const char *fmt, int64_t bytes)
+{
+ char buf[5];
+ int flags;
+
+ bytes *= cblocksize;
+ flags = HN_B | HN_NOSPACE | HN_DECIMAL;
+ if (!Aflag)
+ bytes *= DEV_BSIZE;
+ if (hflag == UNITS_SI)
+ flags |= HN_DIVISOR_1000;
+
+ humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE, flags);
+
+ xo_emit(fmt, buf);
+}
+
+static void
+usage(void)
+{
+ xo_error(
+ "usage: du [-Aclnx] [-H | -L | -P] [-g | -h | -k | -m] "
+ "[-a | -s | -d depth] [-B blocksize] [-I mask] "
+ "[-t threshold] [file ...]\n");
+ exit(EX_USAGE);
+}
+
+static void
+ignoreadd(const char *mask)
+{
+ struct ignentry *ign;
+
+ ign = calloc(1, sizeof(*ign));
+ if (ign == NULL)
+ errx(1, "cannot allocate memory");
+ ign->mask = strdup(mask);
+ if (ign->mask == NULL)
+ errx(1, "cannot allocate memory");
+ SLIST_INSERT_HEAD(&ignores, ign, next);
+}
+
+static void
+ignoreclean(void)
+{
+ struct ignentry *ign;
+
+ while (!SLIST_EMPTY(&ignores)) {
+ ign = SLIST_FIRST(&ignores);
+ SLIST_REMOVE_HEAD(&ignores, next);
+ free(ign->mask);
+ free(ign);
+ }
+}
+
+static int
+ignorep(FTSENT *ent)
+{
+ struct ignentry *ign;
+
+ if (nodumpflag && (ent->fts_statp->st_flags & UF_NODUMP))
+ return 1;
+ SLIST_FOREACH(ign, &ignores, next)
+ if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH)
+ return 1;
+ return 0;
+}
+
+static void
+siginfo(int sig __unused)
+{
+
+ info = 1;
+}
diff --git a/usr.bin/du/tests/Makefile b/usr.bin/du/tests/Makefile
new file mode 100644
index 000000000000..678bd616c729
--- /dev/null
+++ b/usr.bin/du/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH+= du_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/du/tests/Makefile.depend b/usr.bin/du/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/du/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/du/tests/du_test.sh b/usr.bin/du/tests/du_test.sh
new file mode 100755
index 000000000000..0d7fc404b437
--- /dev/null
+++ b/usr.bin/du/tests/du_test.sh
@@ -0,0 +1,189 @@
+#
+# Copyright (c) 2017 Enji Cooper <ngie@FreeBSD.org>
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+require_sparse_file_support()
+{
+ if ! getconf MIN_HOLE_SIZE "$(pwd)"; then
+ echo "getconf MIN_HOLE_SIZE $(pwd) failed; sparse files " \
+ "probably not supported by file system"
+ mount
+ atf_skip "Test's work directory does not support sparse files;" \
+ "try with a different TMPDIR?"
+ fi
+}
+
+atf_test_case A_flag
+A_flag_head()
+{
+ atf_set "descr" "Verify -A behavior"
+}
+A_flag_body()
+{
+ require_sparse_file_support
+ # XXX: compressed volumes?
+ atf_check truncate -s 10g sparse.file
+ atf_check -o inline:'1\tsparse.file\n' du -g sparse.file
+ atf_check -o inline:'10\tsparse.file\n' du -A -g sparse.file
+}
+
+atf_test_case H_flag
+H_flag_head()
+{
+ atf_set "descr" "Verify -H behavior"
+}
+H_flag_body()
+{
+ local paths1='testdir/A/B testdir/A testdir/C testdir'
+ local paths2='testdir/C/B testdir/C'
+ local lineprefix=$'^[0-9]+\t'
+ local sep="\$\n${lineprefix}"
+
+ atf_check mkdir testdir
+ atf_check -x "cd testdir && mkdir A && touch A/B && ln -s A C"
+
+ atf_check -o save:du.out du -aAH testdir
+ atf_check egrep -q "${lineprefix}$(echo $paths1 | sed -e "s/ /$sep/g")$" du.out
+ # Check that the output doesn't contain any lines (i.e. paths) that we
+ # did not expect it to contain from $paths1.
+ atf_check -s exit:1 egrep -vq "${lineprefix}$(echo $paths1 | sed -e "s/ /$sep/g")$" du.out
+
+ atf_check -o save:du_C.out du -aAH testdir/C
+ atf_check egrep -q "${lineprefix}$(echo $paths2 | sed -e "s/ /$sep/g")$" du_C.out
+
+ # Check that the output doesn't contain any lines (i.e. paths) that we
+ # did not expect it to contain from $paths2.
+ atf_check -s exit:1 egrep -vq "${lineprefix}$(echo $paths2 | sed -e "s/ /$sep/g")$" du_C.out
+}
+
+atf_test_case I_flag
+I_flag_head()
+{
+ atf_set "descr" "Verify -I behavior"
+}
+I_flag_body()
+{
+ paths_sans_foo_named="a/motley/fool/of/sorts fool/parts/with/their/cache bar baz"
+ paths_foo_named="foo foobar"
+ paths="$paths_sans_foo_named $paths_foo_named"
+
+ # cd'ing to testdir helps ensure that files from atf/kyua don't
+ # pollute the results.
+ atf_check -x "mkdir testdir && cd testdir && mkdir -p $paths"
+ atf_check -o save:du.out -x "cd testdir && du -s $paths_sans_foo_named"
+ atf_check -o save:du_I.out -x "cd testdir && du -I '*foo*' -s $paths"
+
+ atf_check diff -u du.out du_I.out
+}
+
+atf_test_case c_flag
+c_flag_head()
+{
+ atf_set "descr" "Verify -c output"
+}
+c_flag_body()
+{
+ atf_check truncate -s 0 foo bar
+}
+
+atf_test_case g_flag
+g_flag_head()
+{
+ atf_set "descr" "Verify -g output"
+}
+g_flag_body()
+{
+ require_sparse_file_support
+ atf_check truncate -s 1k A
+ atf_check truncate -s 1m B
+ atf_check truncate -s 1g C
+ atf_check truncate -s 1t D
+ atf_check -o inline:'1\tA\n1\tB\n1\tC\n1024\tD\n' du -Ag A B C D
+}
+
+atf_test_case h_flag
+h_flag_head()
+{
+ atf_set "descr" "Verify -h output"
+}
+h_flag_body()
+{
+ require_sparse_file_support
+ atf_check truncate -s 1k A
+ atf_check truncate -s 1m B
+ atf_check truncate -s 1g C
+ atf_check truncate -s 1t D
+ atf_check -o inline:'1.0K\tA\n1.0M\tB\n1.0G\tC\n1.0T\tD\n' du -Ah A B C D
+}
+
+atf_test_case k_flag
+k_flag_head()
+{
+ atf_set "descr" "Verify -k output"
+}
+k_flag_body()
+{
+ atf_check truncate -s 1k A
+ atf_check truncate -s 1m B
+ atf_check -o inline:'1\tA\n1024\tB\n' du -Ak A B
+}
+
+atf_test_case m_flag
+m_flag_head()
+{
+ atf_set "descr" "Verify -m output"
+}
+m_flag_body()
+{
+ atf_check truncate -s 1k A
+ atf_check truncate -s 1m B
+ atf_check truncate -s 1g C
+ atf_check -o inline:'1\tA\n1\tB\n1024\tC\n' du -Am A B C
+}
+
+atf_test_case si_flag
+si_flag_head()
+{
+ atf_set "descr" "Verify --si output"
+}
+si_flag_body()
+{
+ atf_check truncate -s 1500000 A
+ atf_check truncate -s 1572864 B
+
+ atf_check -o inline:'1.4M\tA\n1.5M\tB\n' du -Ah A B
+ atf_check -o inline:'1.5M\tA\n1.6M\tB\n' du -A --si A B
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case A_flag
+ atf_add_test_case H_flag
+ atf_add_test_case I_flag
+ atf_add_test_case g_flag
+ atf_add_test_case h_flag
+ atf_add_test_case k_flag
+ atf_add_test_case m_flag
+ atf_add_test_case si_flag
+}
diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile
new file mode 100644
index 000000000000..5f83bf775e4d
--- /dev/null
+++ b/usr.bin/ee/Makefile
@@ -0,0 +1,34 @@
+.PATH: ${SRCTOP}/contrib/ee
+
+CFLAGS+= -DHAS_NCURSES -DHAS_UNISTD -DHAS_STDARG -DHAS_STDLIB \
+ -DHAS_SYS_WAIT
+
+PACKAGE=ee
+PROG= ee
+LINKS= ${BINDIR}/ee ${BINDIR}/ree ${BINDIR}/ee ${BINDIR}/edit
+MLINKS= ee.1 ree.1 ee.1 edit.1
+LIBADD= tinfow ncursesw
+
+WARNS?= 2
+
+NLS= C fr_FR.ISO8859-1 de_DE.ISO8859-1 pl_PL.ISO8859-2 \
+ uk_UA.KOI8-U pt_BR.ISO8859-1 ru_RU.KOI8-R hu_HU.ISO8859-2
+
+NLSLINKS_C= en_US.ISO8859-1 en_US.ISO8859-15
+NLSLINKS_fr_FR.ISO8859-1= fr_BE.ISO8859-1 fr_BE.ISO8859-15 \
+ fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 fr_CH.ISO8859-15 \
+ fr_FR.ISO8859-15
+NLSLINKS_de_DE.ISO8859-1= de_AT.ISO8859-1 de_AT.ISO8859-15 de_CH.ISO8859-1 \
+ de_CH.ISO8859-15 de_DE.ISO8859-15
+NLSLINKS_pt_BR.ISO8859-1= pt_PT.ISO8859-1
+
+NLSSRCFILES=ee.msg
+.for lang in ${NLS}
+. if exists(${.CURDIR}/nls/${lang}/ee.msg)
+NLSSRCDIR_${lang}= ${.CURDIR}/nls/${lang}
+. else
+NLSSRCDIR_${lang}= ${SRCTOP}/contrib/ee
+. endif
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ee/Makefile.depend b/usr.bin/ee/Makefile.depend
new file mode 100644
index 000000000000..04dbb4f44313
--- /dev/null
+++ b/usr.bin/ee/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ee/nls/de_DE.ISO8859-1/ee.msg b/usr.bin/ee/nls/de_DE.ISO8859-1/ee.msg
new file mode 100644
index 000000000000..5574a2fcab89
--- /dev/null
+++ b/usr.bin/ee/nls/de_DE.ISO8859-1/ee.msg
@@ -0,0 +1,184 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "Modus-Menü"
+2 "Tab -> Leerzeichen "
+3 "Suche ohne Groß/Klein"
+4 "Ränder beachten "
+5 "Automatische Absätze "
+6 "8-Bit Zeichen (Uml.) "
+7 "Hilfefenster "
+8 "rechter Rand "
+9 "Ende-Menü"
+10 "Speichern"
+11 "Verwerfen"
+12 "Dateimenü"
+13 "Öffnen"
+14 "Schreiben in Datei"
+15 "Speichern"
+16 "Aktuellen Inhalt drucken"
+17 "Textsuche"
+18 "Suche nach ..."
+19 "Suchen"
+20 "Rechtschreibung"
+21 "'spell' benutzen"
+22 "'ispell' benutzen"
+23 "Verschiedenes"
+24 "Absatz formatieren"
+25 "Unix-Kommando"
+26 "Rechtschreibung prüfen"
+27 "Hauptmenü"
+28 "Editor beenden"
+29 "Hilfe"
+30 "Dateioperationen"
+31 "Bildschirm regenerieren"
+32 "Einstellungen"
+33 "Suche"
+34 "Verschiedenes"
+35 "Steuertasten: "
+36 "^a ASCII-Code direkt ^i Tabulator ^r nach rechts "
+37 "^b Ende des Textes ^j neue Zeile ^t Anfang des Textes "
+38 "^c Befehl ^k Zeichen löschen ^u hoch "
+39 "^d runter ^l nach links ^v Wort zurückholen "
+40 "^e Textsuche (Menü) ^m neue Zeile ^w Wort löschen "
+41 "^f Zeichen zurückholen ^n nächste Seite ^x Weitersuchen "
+42 "^g zum Zeilenanfang ^o zum Zeilenende ^y Zeile löschen "
+43 "^h Rückschritt ^p vorige Seite ^z Zeile zurückholen "
+44 "^[ (Escape) Menü ESC-Enter: ee beenden "
+45 " "
+46 "Befehle: "
+47 "hilfe : diese Hilfe anzeigen datei : Dateinamen anzeigen "
+48 "lesen : Datei öffnen zeichen : ASCII-Code anzeigen "
+49 "schreiben:Datei schreiben grosskl : Suche mit Groß/Kleinschr."
+50 "ende : Sichern und Beenden klein : Suche ohne Groß/Klein. "
+51 "abbruch : Abbruch ohne Sichern !bef : Unix-Befehl \"bef\" ausf. "
+52 "zeile : Zeilennummer anzeigen 0-9 : Zur angegebenen Zeile "
+53 "leer : Tabulat. in Leerz. wandeln tabs : Tabulatoren belassen "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [datei(en)] "
+56 "+#: zu Zeile # -i: k. Hilfefenster -e: Tabulatoren lassen -h: k. Hervorheb."
+57 "^[ (Escape) Menü ^e Textsuche ^y Zeile löschen ^u hoch ^p Seite zur. "
+58 "^a ASCII-Code ^x Weitersuchen ^z Zeile rückhl. ^d runter ^n Seite vor "
+59 "^b Textende ^g Zeilenanfang ^w Wort löschen ^l links "
+60 "^t Textanfang ^o Zeilenende ^v Wort rückhol. ^r rechts "
+61 "^c Befehl ^k Zeichen lösch. ^f Zeichen rückholen ESC-Enter: Ende ee "
+62 "hilfe: Hilfe |datei : Dateiname anzeigen |zeile: Zeilennumer "
+63 "lesen: Datei lesen |zeichen:ASCII-Code des Zeichens |0-9 : zur Zeile "
+64 "schre: Datei schreib. |grosskl:Suche mit Groß/Klein |ende : Speichern,Ende "
+65 "!bef : Unix-\"bef\" |klein: Suche ohne Groß/Klein |abbr : Abbruch "
+66 "leer : Tab -> Leerz. |tabs : Tabulatoren belassen "
+67 " Escape (^[) drücken für Menü"
+68 "Keine Datei"
+69 "ASCII-Code: "
+70 "Pufferinhalt nach \"%s\" schreiben "
+71 "Befehl: "
+72 "Dateiname zum Schreiben: "
+73 "Dateiname zum Lesen: "
+74 "Zeichen = %d"
+75 "Unbekannter Befehl \"%s\""
+76 "Angegebener Befehl ist nicht eindeutig"
+77 "Zeile %d "
+78 "Länge = %d"
+79 "Aktuelle Datei ist \"%s\" "
+80 "Benutzung: %s [-i] [-e] [-h] [+zeilennummer] [dateien]\n"
+81 " -i Hilfefenster ausschalten\n"
+82 " -e Tabulatoren nicht in Leerzeichen wandeln\n"
+83 " -h keine Hervorhebungen\n"
+84 "Datei \"%s\" ist ein Verzeichnis"
+85 "Neue Datei \"%s\""
+86 "Datei \"%s\" kann nicht geöffnet werden"
+87 "Datei \"%s\", %d Zeilen"
+88 "Lesen der Datei \"%s\" beendet"
+89 "Lese die Datei \"%s\""
+90 ", schreibgeschützt"
+91 "Datei \"%s\", %d Zeilen"
+92 "Dateinamen eingeben: "
+93 "Kein Name angegeben; Datei nicht gespeichert"
+94 "Pufferinhalt geändert, wirklich verlassen? (j/n [n]) "
+95 "j"
+96 "Datei existiert bereits, überschreiben? (j/n) [n] "
+97 "Datei \"%s\" kann nicht erzeugt werden"
+98 "Schreibe Datei \"%s\""
+99 "\"%s\" %d Zeilen, %d Zeichen"
+100 " ...Suche läuft"
+101 "Zeichenfolge \"%s\" nicht gefunden"
+102 "Suchen nach: "
+103 "Kann %s nicht ausführen\n"
+104 "Bitte die Eingabetaste drücken "
+105 "Escape zum Beenden"
+106 "Menü ist zu groß für das Fenster"
+107 "eine beliebige Taste drücken "
+108 "Unix-Befehl: "
+109 "...formatiere Absatz..."
+110 "<!echo 'Liste der nicht gefundenen Wörter'; echo -=-=-=-=-=-"
+111 "Sende den Pufferinhalt an 'spell'"
+112 "Rechter Rand: "
+113 "Eingeschränkter Modus: gewünschte Operation unzulässig"
+114 "EIN"
+115 "AUS"
+116 "HILFE"
+117 "SCHREIBEN"
+118 "LESEN"
+119 "ZEILE"
+120 "DATEI"
+121 "ZEICHEN"
+122 "REGENERIEREN"
+123 "UMNUMERIEREN"
+124 "AUTOR"
+125 "VERSION"
+126 "GROSSKL"
+127 "KLEIN"
+128 "LEER"
+129 "TABS"
+130 "ENDE"
+131 "ABBRUCH"
+132 "INFO"
+133 "[INFO]"
+134 "RAND"
+135 "[RAND]"
+136 "FORMAT."
+137 "[FORMAT.]"
+138 "ECHO"
+139 "DRUCKBEFEHL"
+140 "RECHTERRAND"
+141 "HERVORHEB."
+142 "[HERVORHEB.]"
+143 "8-BIT"
+144 "[8-BIT]"
+145 "Emacs-Tastenbelegung "
+146 "^a Zeilenanfang ^i Tabulator ^r Wort zurückholen "
+147 "^b ein Zeichen zurück ^j Zeichen zurückholen ^t Textanfang "
+148 "^c Befehl ^k Zeile löschen ^u Textende "
+149 "^d Zeichen löschen ^l Zeile zurückholen ^v nächste Seite "
+150 "^e Zeilenendee ^m neue Zeile ^w Wort löschen "
+151 "^f ein Zeichen vorwärts ^n neue Zeile ^x Weitersuchen "
+152 "^g vorige Seite ^o ASCII-Zeichen einfü. ^y Textsuche "
+153 "^h Rückschritt ^p vorige Zeile ^z nächstes Wort "
+154 "^[ (Escape) Menü ^y Suchtext eing. ^k Zeile löschen ^p vor.Zeile ^g vor.Seite"
+155 "^o ASCII-Zeichen ^x Weitersuchen ^l Zeile rückhol ^n nä. Zeile ^v nä. Seite"
+156 "^u Textende ^a Zeilenanfang ^w Wort löschen ^b ein Zeichen zurück "
+157 "^t Textanfang ^e Zeilenende ^r Wort rückhol. ^f ein Zeichen vor "
+158 "^c Befehl ^d Zeichen lösch. ^j Zeich. rückh. ^z nächstes Wort "
+159 "EMACS"
+160 "[EMACS]"
+161 " +<zahl> Zeiger auf Zeile <zahl> setzen"
+162 "Kann die Datei .init.ee nicht schreiben, Konfiguration nicht gespeichert!"
+163 "ee-Konfiguration in Datei %s gespeichert"
+164 "speichere Editor-Konfiguration"
+165 "speichere ee-Konfiguration"
+166 "speichern im aktuellen Verzeichnis"
+167 "speichern im Home-Verzeichnis"
+168 "ee-Konfiguration nicht gespeichert"
+169 "beim Aufruf von ree muß ein Dateiname angegeben werden"
+180 "Menü zu groß für den Bildschirm"
+181 "^^weiter^^"
+182 "VVweiterVV"
+183 "16-bit Zeichen "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/usr.bin/ee/nls/fr_FR.ISO8859-1/ee.msg b/usr.bin/ee/nls/fr_FR.ISO8859-1/ee.msg
new file mode 100644
index 000000000000..8bd0e3eb5f11
--- /dev/null
+++ b/usr.bin/ee/nls/fr_FR.ISO8859-1/ee.msg
@@ -0,0 +1,184 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "menu de configuration "
+2 "tabulation -> espaces "
+3 "recherche sensible aux maj/min "
+4 "respect des marges "
+5 "formattage automatique des paragraphes"
+6 "caractères 8 bits "
+7 "fenêtre d'informations "
+8 "marge de droite "
+9 "menu de sortie"
+10 "enregistrer les modifications"
+11 "ne pas enregistrer"
+12 "menu fichiers"
+13 "lire un fichier"
+14 "écrire un fichier"
+15 "enregistrer un fichier"
+16 "imprimer le contenu de l'éditeur"
+17 "menu recherche"
+18 "recherche de..."
+19 "rechercher"
+20 "menu correcteur orthographique"
+21 "utiliser 'spell'"
+22 "utiliser 'ispell'"
+23 "menu divers"
+24 "formatter le paragraphe"
+25 "commande du shell"
+26 "vérifier l'orthographe"
+27 "menu principal"
+28 "quitter l'éditeur"
+29 "aide"
+30 "opérations sur les fichiers"
+31 "rafraîchir l'écran"
+32 "configuration"
+33 "recherche"
+34 "divers"
+35 "Contrôle + touche: "
+36 "^a code ascii ^i tabulation ^r droite "
+37 "^b fin du texte ^j nouvelle ligne ^t début du texte "
+38 "^c commande ^k effacer caractère ^u haut "
+39 "^d bas ^l gauche ^v annuler effacement mot "
+40 "^e entrer recherche ^m nouvelle ligne ^w effacer un mot "
+41 "^f annuler eff. caract. ^n page suivante ^x recherche "
+42 "^g début de ligne ^o fin de ligne ^y effacer ligne "
+43 "^h arrière ^p page précédente ^z annuler effacement ligne"
+44 "^[ (échappement) menu ESC-Enter: quitter ee "
+45 " "
+46 "Commandes: "
+47 "aide : pour cet écran d'info fichier: donne le nom du fichier "
+48 "lire : lire un fichier caract : code ascii d'un caractère"
+49 "écrire : créer un fichier minmaj : recherche sensible aux maj/min"
+50 "fin : quitter et enregistrer pasmin : recherche insensible aux maj/min"
+51 "quitter: quitter, ne pas enregistrer !cmd : exécute \"cmd\" par le shell"
+52 "ligne : indique le numéro de ligne 0-9 : aller à la ligne \"#\" "
+53 "tabs : étendre les tabulations pastabs: ne pas étendre les tabulations"
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [fichier(s)] "
+56 " -i : pas de fenêtre d'info -e : ne pas étendre les tabs -h : pas de surbrillance"
+57 "^[ (échap.) menu ^e rechercher... ^y efface ligne ^u haut ^p page préc."
+58 "^a code ascii ^x rechercher ^z annul. eff. ligne ^d bas ^n page suiv."
+59 "^b fin du texte ^g début de ligne ^w efface mot ^l gauche "
+60 "^t début du texte ^o fin de ligne ^v annul. eff. mot ^r droite "
+61 "^c commande ^k efface caract. ^f annul. eff. caract. ESC-Enter: quitter "
+62 "aide: fenêtre d'aide |fichier: nom du fichier |ligne: numéro de ligne"
+63 "lire: lecture fichier|caract : code ascii du car. |0-9: aller ligne \"#\""
+64 "écrire: crée un fich. |minmaj: rech. sensible min/maj|fin: quitte et sauve"
+65 "!cmd: shell \"cmd\" |pasmin: rech. insens. min/maj |quitte: quitte sans sauver"
+66 "tabs: étend les tabs |pastabs: n'étend pas les tabulations"
+67 " pressez sur échap. (^[) pour le menu"
+68 "pas de fichier"
+69 "code ascii : "
+70 "le contenu du buffer est imprimé sur \"%s\" "
+71 "commande : "
+72 "nom du fichier à créer : "
+73 "nom du fichier à lire : "
+74 "caractère = %d"
+75 "commande inconnue : \"%s\""
+76 "la commande tapée est ambiguë"
+77 "ligne %d "
+78 "longueur = %d"
+79 "le fichier courant est \"%s\" "
+80 "utilisation : %s [-i] [-e] [-h] [+numéro_de_ligne] [fichier(s)]\n"
+81 " -i supprime la fenêtre d'informations\n"
+82 " -e ne convertit pas les tabs en espaces\n"
+83 " -h n'utilise pas de surbrillance\n"
+84 "le fichier \"%s\" est un répertoire"
+85 "nouveau fichier \"%s\""
+86 "impossible de d'ouvrir \"%s\""
+87 "fichier \"%s\", %d lignes"
+88 "le fichier \"%s\" a été lu"
+89 "lecture du fichier \"%s\""
+90 ", lecture seule"
+91 "fichier \"%s\", %d lignes"
+92 "entrez un nom de fichier : "
+93 "pas de nom de fichier donné : fichier non enregistré"
+94 "des changements ont été effectués, êtes vous sûr ? (o/n [n]) "
+95 "o"
+96 "le fichier existe déjà, réécrire ? (o/n) [n] "
+97 "impossible de créer le fichier \"%s\""
+98 "écriture du fichier \"%s\""
+99 "\"%s\" %d lignes, %d caractères"
+100 " ...recherche"
+101 "chaîne \"%s\" non trouvée"
+102 "rechercher : "
+103 "impossible d'exécuter %s\n"
+104 "tapez entrée pour continuer "
+105 "pressez sur échap. pour annuler"
+106 "menu trop grand pour la fenêtre"
+107 "appuyez sur une touche pour continuer "
+108 "commande du shell : "
+109 "...formattage du paragraphe..."
+110 "<!echo 'liste des mots non reconnus'; echo -=-=-=-=-=-"
+111 "envoi du contenu du buffer à 'spell'"
+112 "colonne de la marge de droite : "
+113 "mode restreint : impossible d'effectuer l'opération demandée"
+114 "OUI"
+115 "NON"
+116 "AIDE"
+117 "ECRIRE"
+118 "LIRE"
+119 "LIGNE"
+120 "FICHIER"
+121 "CARACTERE"
+122 "RAFRAICHIR"
+123 "RENUMEROTER"
+124 "AUTEUR"
+125 "VERSION"
+126 "MINMAJ"
+127 "PASMINMAJ"
+128 "TABS"
+129 "PASTABS"
+130 "FIN"
+131 "QUITTE"
+132 "INFO"
+133 "PASINFO"
+134 "MARGES"
+135 "PASMARGES"
+136 "AUTOFORMAT"
+137 "PASAUTOFORMAT"
+138 "ECHO"
+139 "COMMANDEIMPRESSION"
+140 "MARGEDROITE"
+141 "SURBRILLANT"
+142 "PASSURBRILLANT"
+143 "8BIT"
+144 "PAS8BIT"
+145 "caractères de contrôle comme emacs "
+146 "^a début de ligne ^i tabulation ^r annule effacement mot "
+147 "^b arrière ^j annule eff. caract. ^t début du texte "
+148 "^c commande ^k efface ligne ^u fin du texte "
+149 "^d efface caractère ^l annule eff. ligne ^v page suivante "
+150 "^e fin de ligne ^m nouvelle ligne ^w effacer un mot "
+151 "^f caractère suivant ^n ligne suivante ^x recherche "
+152 "^g page précédente ^o insère caract. ascii ^y rechercher... "
+153 "^h efface en arrière ^p ligne précédente ^z mot suivant "
+154 "^[ (échap.) menu ^y rechercher... ^k efface ligne ^p ligne préc ^g page préc"
+155 "^o code ascii ^x recherche ^l annul. eff.li ^n ligne suiv ^v page suiv"
+156 "^u fin du fichier ^a début de ligne ^w efface mot ^b arrière "
+157 "^t début du texte ^e fin de ligne ^r annul.eff.mot ^f avance 1 caractère "
+158 "^c commande ^d efface caract. ^j annul.eff.car ^z mot suivant "
+159 "EMACS"
+160 "PASEMACS"
+161 " +# positionne le curseur sur la ligne #\n"
+162 "impossible d'écrire .init.ee, configuration non sauvée !"
+163 "configuration de ee sauvée en %s"
+164 "sauvegarde configuration de l'éditeur"
+165 "sauvegarde configuration de ee"
+166 "sauvegarde dans le répertoire courant"
+167 "sauvegarde dans le répertoire d'accueil"
+168 "configuration de ee non sauvée"
+169 "nom de fichier manquant pour ree"
+180 "menu trop large pour la fenêtre"
+181 "^^encore^^"
+182 "VVencoreVV"
+183 "16 bit characters "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/usr.bin/ee/nls/hu_HU.ISO8859-2/ee.msg b/usr.bin/ee/nls/hu_HU.ISO8859-2/ee.msg
new file mode 100644
index 000000000000..f313ba3a629d
--- /dev/null
+++ b/usr.bin/ee/nls/hu_HU.ISO8859-2/ee.msg
@@ -0,0 +1,184 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "üzemmód menü"
+2 "tabulátorok szóközzé "
+3 "kis- és nagybetû érzékeny keresés "
+4 "margók megfigyelésre "
+5 "automatikus bekezdésformázás "
+6 "nyolcbites karakterek "
+7 "info ablak "
+8 "jobb margó "
+9 "kilépés a menübõl "
+10 "változtatások mentése"
+11 "nincs mentés"
+12 "fájl menü"
+13 "fájl olvasása"
+14 "fájl írása"
+15 "fájl mentése"
+16 "a szerkesztõ tartalmának nyomtatása"
+17 "keresés menü"
+18 "keresés erre"
+19 "keresés"
+20 "helyesírás menü"
+21 "'spell' használata"
+22 "'ispell' használata"
+23 "egyéb menü"
+24 "bekezdés formázása"
+25 "shell parancs"
+26 "helyesírás-ellenõrzés"
+27 "fõmenü"
+28 "kilépés a szerkesztõbõl"
+29 "súgó"
+30 "fájlmûveletek"
+31 "képernyõ újrarajzolása"
+32 "beállítások"
+33 "keresés"
+34 "egyéb"
+35 "Vezérlõbillentyûk: "
+36 "^a ascii kód ^i tabulátor ^r jobb "
+37 "^b szöveg alja ^j újsor ^t szöveg teteje "
+38 "^c parancs ^k karakter törlése ^u fel "
+39 "^d le ^l balra ^v szótörlés vissza "
+40 "^e keresés prompt ^m újsor ^w szó törlése "
+41 "^f karaktertörlés vissza ^n következõ oldal ^x keresés "
+42 "^g sor eleje ^o sor vége ^y sor törlése "
+43 "^h visszatörlés ^p elõzõ oldal ^z sortörlés vissza "
+44 "^[ (escape) menü "
+45 " "
+46 "Parancsok: "
+47 "help : ez az info file : fájlnév megjelenítése "
+48 "read : fájl olvasása char : karakter ascii kódja "
+49 "write : fájl írása case : k/n betû érzékeny keresés"
+50 "exit : kilépés és mentés nocase : nem betûérzékeny keresés "
+51 "quit : kilépés mentés nélkül !cmd : \"cmd\" shell parancs "
+52 "line : #. sor megjelenítése 0-9 : \"#\" sorra ugrás "
+53 "expand : tabok kifejtése noexpand: ne fejtse ki a tabokat "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [fájl(ok) "
+56 "+# :ugrás sorra # -i :info ablak ki -e :tabkifejtés ki -h :kiemelés ki"
+57 "^[ (escape) menü ^e keresés prompt ^y sor törlése ^u fel ^p elõzõ old "
+58 "^a ascii kód ^x keresés ^z sortörl vissza ^d le ^n köv old "
+59 "^b szöve alja ^g sor eleje ^w szó törlése ^l bal "
+60 "^t szöveg teteje ^o sor vége ^v szótörl vissza ^r jobb "
+61 "^c parancs ^k karalter törl ^f kartörl vissza "
+62 "help : súgó |file : fájlnév megjelenítése |line : sor # kiírása "
+63 "read : fájl olvasása |char : ascii kód |0-9 : # sorra ugrás "
+64 "write: fájl írása |case : k/n érzékeny keresés |exit : kilép és ment "
+65 "!cmd : shell parancs |nocase: nem érzékeny keresés |quit : kilép, nem ment"
+66 "expand: tabkifejtés |noexpand: ne legyen tabkifejtés "
+67 " nyomja le az Escape billentyût (^[) a menü eléréséhez"
+68 "nincs fájl"
+69 "ascii kód: "
+70 "a puffer tartalmának küldése -> \"%s\" "
+71 "parancs: "
+72 "a mentendõ fájl neve: "
+73 "az olvasandó fájl neve: "
+74 "karakter = %d"
+75 "ismeretlen parancs: \"%s\""
+76 "a megadott parancs nem egyéni"
+77 "sor %d "
+78 "hossz = %d"
+79 "az aktuális fájl \"%s\" "
+80 "használat: %s [-i] [-e] [-h] [+sor_száma] [fájl(ok)]\n"
+81 " -i info ablak kikapcsolása\n"
+82 " -e ne konvertálja a tabokat szóközzé\n"
+83 " -h ne használjon kiemelést\n"
+84 "\"%s\" egy könyvtár"
+85 "új fájl: \"%s\""
+86 "\"%s\" nem nyitható meg"
+87 "\"%s\" fájl, %d sor"
+88 "\"%s\" fájl olvasása befejezõdött"
+89 "\"%s\" fájl olvasása"
+90 ", csak olvasható"
+91 "\"%s\" fájl, %d sor"
+92 "adja meg a fájlnevet: "
+93 "nem adott meg fájlnevet: a fájl nem lett elmentve"
+94 "változások történtek, biztos benne? (i/n [n]) "
+95 "i"
+96 "a fájl már létezik, felülírjam? (i/n) [n] "
+97 "\"%s\" fájl nem hozható létre"
+98 "\"%s\" fájl írása"
+99 "\"%s\" %d sor, %d karakter"
+100 " ...keresés"
+101 "\"%s\" karakterlánc nem található"
+102 "keresés erre: "
+103 "%s nem hajtható végre\n"
+104 "nyomjon entert a folytatáshoz"
+105 "nyomja le az Esc billentyût a visszalépéshez"
+106 "a menü túl nagy az ablakhoz"
+107 "nyomjon le egy billentyût a folytatáshoz"
+108 "shell parancs: "
+109 "...bekezdés formázása..."
+110 "<!echo 'felismerhetetlen szavak listája'; echo -=-=-=-=-=-"
+111 "a szerkesztési puffer küldése a 'spell' programhoz"
+112 "jobb margó: "
+113 "korlátozott mód: a kért mûvelet nem hajtható végre"
+114 "ON"
+115 "OFF"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "emacs gomb kiosztás "
+146 "^a sor eleje ^i tab ^r szó visszaállítása "
+147 "^b vissza 1 karaktert ^j karaktertörl vissza ^t fájl eleje "
+148 "^c parancs ^k sor törlése ^u fájl vége "
+149 "^d karakter törlése ^l sortérlés vissza ^v következõ oldal "
+150 "^e sor vége ^m újsor ^w szó törlése "
+151 "^f elõre 1 karaktert ^n következõ sor ^x keresés "
+152 "^g vissza 1 oldalt ^o ascii kar beszúrása ^y keresés prompt "
+153 "^h visszatörlés ^p elõzõ sor ^z következõ sor "
+154 "^[ (escape) menü ^y keresés prompt ^k sor törlése ^p el sor ^g elõzõ old"
+155 "^o ascii kód ^x keresés ^l sortörl vissz ^n köv sor ^v köv old "
+156 "^u fájl vége ^a sor eleje ^w szó törlése ^b vissza 1 kar "
+157 "^t fájl eleje ^e sor vége ^r szótörl vissz ^f elõre 1 kar "
+158 "^c parancs ^d kar törlése ^j kartörl vissz ^z köv szó "
+159 "EMACS"
+160 "NOEMACS"
+161 " +# kurzor mozgatása a sorra #\n"
+162 ".init.ee nem nyitható meg írásra, konfiguráció nem lett mentve!"
+163 "ee konfiguráció elmentve a %s fájlban"
+164 "szerkesztõ konfigurációjának mentése"
+165 "ee konfiguráció mentése"
+166 "mentés az aktuális könyvtárba"
+167 "mentés a home könyvtárba"
+168 "ee konfiguráció nem lett mentve"
+169 "ree hívásához meg kell adni egy fájlnevet"
+180 "a menü túl nagy az ablakhoz"
+181 "^^több^^"
+182 "VVtöbbVV"
+183 "16 bites karakterek "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/usr.bin/ee/nls/pl_PL.ISO8859-2/ee.msg b/usr.bin/ee/nls/pl_PL.ISO8859-2/ee.msg
new file mode 100644
index 000000000000..13f5cc0e2095
--- /dev/null
+++ b/usr.bin/ee/nls/pl_PL.ISO8859-2/ee.msg
@@ -0,0 +1,184 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "menu Tryb pracy"
+2 "tabulacje na spacje "
+3 "szukaj (ma³e!=du¿e) "
+4 "ustawiony margines "
+5 "auto-formatuj akapit "
+6 "znaki o¶miobitowe "
+7 "okno informacyjne "
+8 "prawy margines "
+9 "wyjd¼ z menu"
+10 "zachowaj zmiany"
+11 "brak zachowania"
+12 "menu Plik"
+13 "wczytaj plik"
+14 "zapisz do pliku"
+15 "zachowaj plik"
+16 "drukuj zawarto¶æ edytora"
+17 "menu Szukanie"
+18 "szukaj ..."
+19 "szukanie"
+20 "menu Pisownia"
+21 "u¿yj 'spell'"
+22 "u¿yj 'ispell'"
+23 "menu Inne"
+24 "formatuj akapit"
+25 "polecenie shell"
+26 "sprawd¼ pisowniê"
+27 "menu g³ówne"
+28 "wyjd¼ z edytora"
+29 "pomoc"
+30 "operacje na plikach"
+31 "od¶wie¿ ekran"
+32 "ustawienia"
+33 "szukanie"
+34 "inne"
+35 "Klawisze kontrolne: "
+36 "^a kod ASCII ^i tabulator ^r w prawo "
+37 "^b na dó³ tekstu ^j nowy wiersz ^t do góry tekstu "
+38 "^c polecenie ^k usuñ znak ^u do góry "
+39 "^d do do³u ^l w lewo ^v przywróæ s³owo "
+40 "^e szukanie ^m nowy wiersz ^w usuñ s³owo "
+41 "^f przywróæ znak ^n nastêpna strona ^x szukaj "
+42 "^g na pocz±tek wiersza ^o na koniec wiersza ^y usuñ wiersz "
+43 "^h backspace ^p poprzednia strona ^z przywróæ wiersz "
+44 "^[ (escape) menu ESC-Enter: wyj¶cie z ee "
+45 " "
+46 "Polecenia: "
+47 "help : wy¶wietl tê informacjê file : wy¶wietl nazwê pliku "
+48 "read : wczytaj plik char : kod ASCII znaku "
+49 "write : zapisz do pliku case : szukaj (ma³e!=du¿e) "
+50 "exit : zachowaj i wyjd¼ nocase : szukaj (ma³e==du¿e) "
+51 "quit : wyjd¼ bez zachowania !cmd : wykonaj \"cmd\" w shellu "
+52 "line : wy¶wietl numer wiersza 0-9 : id¼ do wiersza \"#\" "
+53 "expand : rozwiñ tabulacje na spacje noexpand: nie rozwijaj tabulacji "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [plik(i)] "
+56 " -i : bez okna inform. -e : nie rozwijaj tab. -h : bez pod¶wietl."
+57 "^[ (escape) menu ^e szukanie ^y usuñ wiersz ^u do góry ^p poprz. str "
+58 "^a kod ASCII ^x szukaj ^z przywróæ wiersz ^d do do³u ^n nast. str. "
+59 "^b na dó³ tekstu ^g na pocz. wiersza ^w usuñ s³owo ^l w lewo "
+60 "^t do góry tekstu ^o na koniec wiersza ^v przywróæ s³owo ^r w prawo "
+61 "^c polecenie ^k usuñ znak ^f przywróæ znak ESC-Enter: wyj¶cie "
+62 "help : pomoc |file : podaj nazwê pliku |line : numer wiersza"
+63 "read : wczytaj plik |char : kod ASCII znaku |0-9 : id¼ do wr \"#\""
+64 "write: zapisz plik |case : szukaj (ma³e!=du¿e) |exit : zpisz i wyjd¼"
+65 "!cmd : \"cmd\" w shellu |nocase: ma³e==du¿e w szukaniu |quit : wyjd¼, nie zapisuj"
+66 "expand: rozwiñ tabulacje na spacje |noexpand: nie rozwijaj tabulacji "
+67 " naci¶nij Escape (^[) do menu"
+68 "brak pliku"
+69 "kod ASCII: "
+70 "wysy³am zawarto¶æ bufora do \"%s\" "
+71 "polecenie: "
+72 "nazwa pliku do zapisania: "
+73 "nazwa pliku do wczytania: "
+74 "znak = %d"
+75 "nieznane polecenie \"%s\""
+76 "podane polecenie nie jest jednoznaczne"
+77 "wiersz %d "
+78 "d³ugo¶æ = %d"
+79 "aktualny plik to \"%s\" "
+80 "sposób u¿ycia: %s [-i] [-e] [-h] [+numer_wiersza] [plik(i)]\n"
+81 " -i zamknij okno informacyjne\n"
+82 " -e nie rozwijaj tabulacji na spacje\n"
+83 " -h nie u¿ywaj pod¶wietleñ\n"
+84 "plik \"%s\" jest katalogiem"
+85 "nowy plik \"%s\""
+86 "nie mogê otworzyæ \"%s\""
+87 "plik \"%s\", %d wierszy"
+88 "koniec wczytywania pliku \"%s\""
+89 "wczytywanie pliku \"%s\""
+90 ", tylko do odczytu"
+91 "plik \"%s\", %d wierszy"
+92 "podaj nazwê pliku: "
+93 "nie podano nazwy pliku: plik nie zosta³ zachowany"
+94 "plik zosta³ zmieniony, jeste¶ pewien? (t/n [n]) "
+95 "t"
+96 "plik ju¿ istnieje, zast±piæ? (t/n) [n] "
+97 "nie mo¿na utworzyæ pliku \"%s\""
+98 "zapisywanie pliku \"%s\""
+99 "\"%s\" %d wierszy, %d znaków"
+100 " ...szukam"
+101 "napis \"%s\" nie zosta³ znaleziony"
+102 "szukaj: "
+103 "nie mo¿na wykonaæ %s\n"
+104 "naci¶nij Enter ¿eby kontynuowaæ "
+105 "naci¶nij Esc ¿eby anulowaæ"
+106 "menu zbyt du¿e dla tego okna"
+107 "naci¶nij dowolny klawisz "
+108 "polecenie shella: "
+109 "...formatowanie akapitu..."
+110 "<!echo 'lista nieznalezionych s³ów'; echo -=-=-=-=-=-"
+111 "wysy³am zawarto¶æ edytora do programu 'spell'"
+112 "prawy margines: "
+113 "tryb ograniczony: nie mo¿na przeprowadziæ tej operacji"
+114 "ON"
+115 "OFF"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "klawisze emacs "
+146 "^a pocz±tek wiersza ^i tabulacja ^r przywróæ s³owo "
+147 "^b jeden znak wstecz ^j przywróæ znak ^t do góry tekstu "
+148 "^c polecenie ^k usuñ wiersz ^u na dó³ tekstu "
+149 "^d usuñ znak ^l przywróæ wiersz ^v nastêpna strona "
+150 "^e na koniec wiersza ^m nowy wiersz ^w usuñ s³owo "
+151 "^f 1 znak do przodu ^n nastêpny wiersz ^x szukaj "
+152 "^g 1 strona wstecz ^o wstaw znak ASCII ^y szukanie "
+153 "^h backspace ^p poprzedni wiersz ^z nastêpne s³owo "
+154 "^[ (escape) menu ^y szukanie ^k usuñ wiersz ^p <-wiersz ^g <-strona "
+155 "^o kod ASCII ^x szukaj ^l przywr wiersz ^n wiersz-> ^v strona-> "
+156 "^u koniec pliku ^a pocz. wiersza ^w usuñ s³owo ^b 1 znak wstecz "
+157 "^t pocz. tekstu ^e koniec wiersza ^r przywr s³owo ^f 1 znak do przodu "
+158 "^c polecenie ^d usuñ znak ^j przywróæ znak ^z nastêpne s³owo "
+159 "EMACS"
+160 "NIE-EMACS"
+161 " +# umie¶æ kursor w wierszu #\n"
+162 "nie mo¿na otworzyæ .init.ee do zapisu, nie zachowano konfiguracji!"
+163 "konfiguracja ee zachowana do pliku %s"
+164 "zachowaj konfiguracjê edytora"
+165 "zachowaj konfiguracjê ee"
+166 "zachowaj w bie¿±cym katalogu"
+167 "zachowaj w katalogu home"
+168 "nie zachowano konfiguracji ee"
+169 "musisz podaæ nazwê pliku przy wywo³aniu ree"
+180 "menu zbyt du¿e dla tego okna"
+181 "^^dalej^^"
+182 "VVdalejVV"
+183 "16 bit characters "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/usr.bin/ee/nls/pt_BR.ISO8859-1/ee.msg b/usr.bin/ee/nls/pt_BR.ISO8859-1/ee.msg
new file mode 100644
index 000000000000..80adc64e1b38
--- /dev/null
+++ b/usr.bin/ee/nls/pt_BR.ISO8859-1/ee.msg
@@ -0,0 +1,185 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$ $Header: /home/hugh/sources/old_ae/RCS/ee.msg,v 1.8 1996/11/30 03:23:40 hugh Exp $
+$
+$
+$set 1
+$quote "
+1 "modo menu"
+2 "tabs para espaços "
+3 "busca com case sensitive "
+4 "observar margens "
+5 "formatação de auto-parágrafo"
+6 "caracteres de oito bits "
+7 "informação da janela "
+8 "margem direita "
+9 "deixar o menu"
+10 "salvar mudanças"
+11 "sem salvar"
+12 "menu arquivo"
+13 "ler um arquivo"
+14 "escrever uma arquivo"
+15 "salvar arquivo"
+16 "editar conteúdo de impressão"
+17 "menu localizar"
+18 "localizar por ..."
+19 "localizar"
+20 "menu dicionário"
+21 "usar 'spell'"
+22 "usar 'ispell'"
+23 "menu diversos"
+24 "formatação de parágrafo"
+25 "comando shell"
+26 "checar dicionário"
+27 "menu principal"
+28 "deixar editor"
+29 "ajuda"
+30 "operações com arquivos"
+31 "redesenhar tela"
+32 "configurações"
+33 "localizar"
+34 "diversos"
+35 "Teclas de controle: "
+36 "^a código ascii ^i tab ^r direita "
+37 "^b botão de texto ^j nova linha ^t início do texto "
+38 "^c comando ^k deletar caracter ^u para acima "
+39 "^d para baixo ^l esquerda ^v restaurar palavra "
+40 "^e localizar prompt ^m nova linha ^w deletar palavra "
+41 "^f restaurar caracter ^n próxima página ^x localizar "
+42 "^g início da linha ^o fim da linha ^y deletar linha "
+43 "^h backspace ^p página anterior ^z restaurar linha "
+44 "^[ (escape) menu "
+45 " "
+46 "Comandos: "
+47 "help : obter esta informação file : imprimir nome do arquivo "
+48 "read : ler um arquivo char : código ascii de caracter "
+49 "write : escrever a arquivo case : localizar com case sensitive "
+50 "exit : salva e sair nocase : localizar sem case insensitive "
+51 "quit : sair, sem salvar !cmd : executar \"cmd\" no shell "
+52 "line : visualizar linhas # 0-9 : ir para linha \"#\" "
+53 "expand : expandir tabs noexpand: não expande tabs "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [arquivos(s)] "
+56 "+# :ir para linha # -i :sem informação da janela -e : não expandir tabs -h :sem destaque "
+57 "^[ (escape) menu ^e prompt localizar ^y deletar linha ^u para cima ^p página anterior "
+58 "^a código ascii ^x localizar ^z restaurar linha ^d para baixo ^n próxima página "
+59 "^b botão de texto ^g início da linha ^w deletar palavra ^l esquerda "
+60 "^t início do texto ^o fim da linha ^v restaurar palavra ^r direita "
+61 "^c comando ^k deletar caracter ^f restaurar caracter "
+62 "help : obter ajuda |file : imprimir nome do arquivo |line : imprimir linha # "
+63 "read : ler um arquivo |char : código ascii de caracter |0-9 : ir para linha \"#\""
+64 "write: escrever um arquivo |case : localizar com case sensitive |exit : salvar e sair "
+65 "!cmd : shell \"cmd\" |nocase: ignorar case na busca |quit : sair, sem salvar"
+66 "expand: expandir tabs |noexpand: não expandir tabs "
+67 " pressione Escape (^[) para menu"
+68 "sem arquivo"
+69 "código ascii: "
+70 "enviar conteúdo do buffer para \"%s\" "
+71 "comando: "
+72 "nome do arquivo para escrever: "
+73 "nome do arquivo para leitura: "
+74 "caracter = %d"
+75 "comando desconhecido \"%s\""
+76 "mais de um comando digitado"
+77 "linha %d "
+78 "comprimento = %d"
+79 "arquivo atual \"%s\" "
+80 "uso: %s [-i] [-e] [-h] [+número_da_linha] [arquivo(s)]\n"
+81 " -i desligar informações da janela\n"
+82 " -e não converter tabs para espaços\n"
+83 " -h não usar destaque\n"
+84 "arquivo \"%s\" é um diretório"
+85 "novo arquivo \"%s\""
+86 "não posso abrir \"%s\""
+87 "arquivos \"%s\", %d linhas"
+88 "finalizar leitura de arquivo \"%s\""
+89 "lendo arquivo \"%s\""
+90 ", somente leitura"
+91 "arquivo \"%s\", %d linhas"
+92 "digite o nome do arquivo: "
+93 "nenhum arquivo digitado: arquivo não foi salvo"
+94 "Foram feitas alterações, você tem certeza? (y/n [n]) "
+95 "y"
+96 "arquivo já existe, sobrescrever? (y/n) [n] "
+97 "impossível criar arquivo \"%s\""
+98 "escrevendo arquivo \"%s\""
+99 "\"%s\" %d linhas, %d caracteres"
+100 " ...localizando"
+101 "string \"%s\" não encontrada"
+102 "localizar por: "
+103 "execução não permitida %s\n"
+104 "pressione enter para continuar "
+105 "pressione Esc para cancelar"
+106 "menu muito grande para a janela"
+107 "pressione qualquer tecla para continuar "
+108 "comando shell: "
+109 "...formatando parágrafo..."
+110 "<!echo 'lista de palavras não reconhecidas'; echo -=-=-=-=-=-"
+111 "enviando conteúdo no buffer do editor para 'correção'"
+112 "margem direita é: "
+113 "modo restrito: incapaz de executar a operação solicitada"
+114 "LIGADO"
+115 "DESLIGADO"
+116 "AJUDA"
+117 "ESCRITA"
+118 "LEITURA"
+119 "LINHA"
+120 "ARQUIVO"
+121 "CARACTER"
+122 "REDESENHAR"
+123 "RESEQUENCIA"
+124 "AUTOR"
+125 "VERSÃO"
+126 "CASE"
+127 "SEMCASE"
+128 "EXPANDIR"
+129 "NÃOEXPANDIR"
+130 "SAIRSALVANDO"
+131 "SAIRSEMSALVAR"
+132 "INFO"
+133 "SEMINFO"
+134 "MARGENS"
+135 "SEMMARGENS"
+136 "AUTOFORMATAÇÃO"
+137 "SEMAUTOFORMATAÇÃO"
+138 "ECHO"
+139 "IMPRIMIRCOMANDO"
+140 "MARGEMDIREITA"
+141 "DESTAQUE"
+142 "SEMDESTAQUE"
+143 "OITOBIT"
+144 "SEMOITOBIT"
+145 "vínculo com teclas emacs "
+146 "^a início da linha ^i tab ^r restaurar palavra "
+147 "^b voltar 1 caracter ^j resturar caracter ^t início do texto "
+148 "^c comando ^k deletar linha ^u botão de texto "
+149 "^d deletar caracter ^l restaurar linha ^v próxima página "
+150 "^e fim da linha ^m nova linha ^w deletar palavra "
+151 "^f avançar 1 caracter ^n próxima linha ^x localizar "
+152 "^g voltar 1 página ^o inserir caracter ascii ^y prompt localizar "
+153 "^h backspace ^p linha anterior ^z próxima palavra "
+154 "^[ (escape) menu ^y prompt localizar ^k deletar linha ^p linha anterior ^g página anterior"
+155 "^o código ascii ^x localizar ^l restaurar linha ^n próxima linha ^v próxima página "
+156 "^u fim do arquivo ^a início da linha ^w deletar palavra ^b regressar 1 caracter "
+157 "^t início do texto ^e fim da linha ^r restaurar palavra ^f avançar 1 caracter "
+158 "^c comando ^d deletar caracter ^j restaurar caracter ^z próxima palavra "
+159 "EMACS"
+160 "SEMEMACS"
+161 " +# colocar cursor na linha #\n"
+162 "impossível abrir .init.ee para escrita, nenhuma configuração salva!"
+163 "ee configuração salva no arquivo %s"
+164 "salvar configurações do editor"
+165 "salvar configurações do ee"
+166 "salvar no diretório corrente"
+167 "salvar no diretório home"
+168 "configurações do ee não salvas"
+169 "ao invocar ree, deve-se especificar um arquivo"
+180 "menu muito grande para a janela"
+181 "^^mais^^"
+182 "VVmaisVV"
+183 "caracteres de 16 bit "
+184 "16BIT"
+185 "SEM16BIT"
diff --git a/usr.bin/ee/nls/ru_RU.KOI8-R/ee.msg b/usr.bin/ee/nls/ru_RU.KOI8-R/ee.msg
new file mode 100644
index 000000000000..21f787b989b0
--- /dev/null
+++ b/usr.bin/ee/nls/ru_RU.KOI8-R/ee.msg
@@ -0,0 +1,186 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ Based on uk_UA.KOI8-U translation by Olexander Kunytsa <kunia@istc.kiev.ua>
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "íÅÎÀ ÐÁÒÁÍÅÔÒÏ×"
+2 "ÔÁÂÕÌÑÃÉÑ ÐÒÏÂÅÌÁÍÉ "
+3 "ÐÏÉÓË Ó ÕÞ£ÔÏÍ ÒÅÇÉÓÔÒÁ "
+4 "Á×ÔÏ-ÐÅÒÅ×ÏÄ ÓÔÒÏËÉ "
+5 "Á×ÔÏ-ÆÏÒÍÁÔ ÁÂÚÁÃÁ "
+6 "8-ÂÉÔÎÙÅ ÓÉÍ×ÏÌÙ "
+7 "ÏËÎÏ ÐÏÄÓËÁÚËÉ "
+8 "ÛÉÒÉÎÁ ÔÅËÓÔÁ "
+9 "æÁÊÌ ÉÚÍÅΣÎ!"
+10 "ÓÏÈÒÁÎÉÔØ É ×ÙÊÔÉ"
+11 "ÎÅ ÓÏÈÒÁÎÑÔØ"
+12 "íÅÎÀ ÆÁÊÌÏ×ÙÈ ÏÐÅÒÁÃÉÊ"
+13 "ÐÒÏÞÅÓÔØ ÆÁÊÌ"
+14 "ÚÁÐÉÓÁÔØ × ÆÁÊÌ"
+15 "ÓÏÈÒÁÎÉÔØ ÆÁÊÌ"
+16 "ÒÁÓÐÅÞÁÔÁÔØ"
+17 "íÅÎÀ ÐÏÉÓËÁ"
+18 "ÞÔÏ ÉÓËÁÔØ..."
+19 "ÐÏ×ÔÏÒÉÔØ ÐÏÉÓË"
+20 "íÅÎÀ ÐÒÏ×ÅÒËÉ ÐÒÁ×ÏÐÉÓÁÎÉÑ"
+21 "ÚÁÐÕÓÔÉÔØ 'spell'"
+22 "ÚÁÐÕÓÔÉÔØ 'ispell'"
+23 "äÏÐÏÌÎÉÔÅÌØÎÙÅ ÏÐÅÒÁÃÉÉ"
+24 "ÆÏÒÍÁÔÉÒÏ×ÁÔØ ÁÂÚÁÃ"
+25 "ËÏÍÁÎÄÁ ÏÂÏÌÏÞËÉ"
+26 "ÐÒÏ×ÅÒÉÔØ ÐÒÁ×ÏÐÉÓÁÎÉÅ"
+27 "çÌÁ×ÎÏÅ ÍÅÎÀ"
+28 "×ÙÊÔÉ ÉÚ ÒÅÄÁËÔÏÒÁ"
+29 "ÐÏÄÓËÁÚËÁ"
+30 "ÏÐÅÒÁÃÉÉ Ó ÆÁÊÌÁÍÉ"
+31 "ÏÂÎÏ×ÉÔØ ÜËÒÁÎ"
+32 "ÐÁÒÁÍÅÔÒÙ"
+33 "ÐÏÉÓË"
+34 "ÒÁÚÎÏÅ"
+35 "ëÌÁ×ÉÛÉ ÕÐÒÁ×ÌÅÎÉÑ: "
+36 "^a ascii-ËÏÄ ^i ÔÁÂÕÌÑÃÉÑ ^r ×ÐÒÁ×Ï "
+37 "^b × ÓÁÍÙÊ ÎÉÚ ^j ÎÏ×ÁÑ ÓÔÒÏËÁ ^t × ÓÁÍÙÊ ×ÅÒÈ "
+38 "^c ËÏÍÁÎÄÁ ^k ÕÄÁÌÉÔØ ÓÉÍ×ÏÌ ^u ××ÅÒÈ "
+39 "^d ×ÎÉÚ ^l ×ÌÅ×Ï ^v ×ÅÒÎÕÔØ ÓÌÏ×Ï "
+40 "^e ÐÏÉÓË... ^m ÎÏ×ÁÑ ÓÔÒÏËÁ ^w ÕÄÁÌÉÔØ ÓÌÏ×Ï "
+41 "^f ×ÅÒÎÕÔØ ÓÉÍ×ÏÌ ^n ÓÌÅÄÕÀÝÁÑ ÓÔÒÁÎÉÃÁ ^x ÐÏ×ÔÏÒ ÐÏÉÓËÁ "
+42 "^g × ÎÁÞÁÌÏ ÓÔÒÏËÉ ^o × ËÏÎÅÃ ÓÔÒÏËÉ ^y ÕÄÁÌÉÔØ ÓÔÒÏËÕ "
+43 "^h ÚÁÂÏÊ ^p ÐÒÅÄÙÄÕÝÁÑ ÓÔÒÁÎÉÃÁ ^z ×ÅÒÎÕÔØ ÓÔÒÏËÕ "
+44 "^[ (Esc) ×ÙÚÏ× ÍÅÎÀ Esc-Enter: ×ÙÊÔÉ ÉÚ ÒÅÄÁËÔÏÒÁ "
+45 " "
+46 "ëÏÍÁÎÄÙ: "
+47 "help : ÜÔÁ ÐÏÄÓËÁÚËÁ file : ÐÏËÁÚÁÔØ ÉÍÑ ÆÁÊÌÁ "
+48 "read : ÐÒÏÞÅÓÔØ ÆÁÊÌ char : ascii-ËÏÄ ÓÉÍ×ÏÌÁ "
+49 "write : ÚÁÐÉÓÁÔØ × ÆÁÊÌ case : ÐÏÉÓË Ó ÕÞ£ÔÏÍ ÒÅÇÉÓÔÒÁ "
+50 "exit : ×ÙÊÔÉ Ó ÓÏÈÒÁÎÅÎÉÅÍ nocase : ÐÏÉÓË ÂÅÚ ÕÞ£ÔÁ ÒÅÇÉÓÔÒÁ "
+51 "quit : ×ÙÊÔÉ ÂÅÚ ÓÏÈÒÁÎÅÎÉÑ !ËÏÍÁÎÄÁ: ×ÙÚ×ÁÔØ ËÏÍÁÎÄÕ ÏÂÏÌÏÞËÉ "
+52 "line : ÐÏËÁÚÁÔØ ÎÏÍÅÒ ÓÔÒÏËÉ 0-9 : ÐÅÒÅÊÔÉ Ë ÓÔÒÏËÅ N "
+53 "expand : ÚÁÍÅÎÑÔØ ÔÁÂÕÌÑÃÉÀ ÐÒÏÂÅÌÁÍÉ noexpand: ÎÅ ÚÁÍÅÎÑÔØ ÔÁÂÕÌÑÃÉÀ "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [ÆÁÊÌ(Ù)] "
+56 "+# :Ë ÓÔÒÏËÅ N -i :ÂÅÚ ÉÎÆÏ-ÏËÎÁ -e :ÎÅ ÚÁÍÅÎÑÔØ ÔÁÂÙ -h :ÂÅÚ ×ÙÄÅÌÅÎÉÑ ÒÁÍÏË "
+57 "^[ (Esc) ÍÅÎÀ ^e ÐÏÉÓË ^y ÕÄÁÌÉÔØ ÓÔÒÏËÕ ^u ××ÅÒÈ ^p ÐÒÅÄ. ÓÔÒ. "
+58 "^a ascii-ËÏÄ ^x ÐÏ×ÔÏÒ ÐÏÉÓËÁ ^z ×ÅÒÎÕÔØ ÓÔÒÏËÕ ^d ×ÎÉÚ ^n ÓÌÅÄ. ÓÔÒ. "
+59 "^b × ÓÁÍÙÊ ÎÉÚ ^g × ÎÁÞÁÌÏ ÓÔÒÏËÉ ^w ÕÄÁÌÉÔØ ÓÌÏ×Ï ^l ×ÌÅ×Ï "
+60 "^t × ÓÁÍÙÊ ×ÅÒÈ ^o × ËÏÎÅà ÓÔÒÏËÉ ^v ×ÅÒÎÕÔØ ÓÌÏ×Ï ^r ×ÐÒÁ×Ï "
+61 "^c ËÏÍÁÎÄÁ ^k ÕÄÁÌÉÔØ ÓÉÍ×ÏÌ ^f ×ÅÒÎÕÔØ ÓÉÍ×ÏÌ Esc-Enter ×ÙÈÏÄ ÉÚ 'ee'"
+62 "help : ÐÏÄÓËÁÚËÁ |file : ÐÏËÁÚÁÔØ ÉÍÑ ÆÁÊÌÁ |line: ÎÏÍÅÒ ÓÔÒÏËÉ "
+63 "read : ÐÒÏÞÅÓÔØ ÆÁÊÌ |char : ascii-ËÏÄ ÓÉÍ×ÏÌÁ |0-9 : ÐÅÒÅÊÔÉ Ë ÓÔÒÏËÅ "
+64 "write: ÚÁÐÉÓÁÔØ ÆÁÊÌ |case : ÐÏÉÓË Ó ÕÞ£ÔÏÍ ÒÅÇÉÓÔÒÁ |exit: ÓÏÈÒÁÎÉÔØ É ×ÙÊÔÉ"
+65 "!ËÍÄ : ×ÙÐÏÌÎÉÔØ ËÍÄ. |nocase:ÐÏÉÓË ÂÅÚ ÕÞ£ÔÁ ÒÅÇÉÓÔÒÁ |quit: ÏÔÍÅÎÉÔØ É ×ÙÊÔÉ"
+66 "expand: ÚÁÍÅÎÑÔØ ÔÁÂÙ |noexpand: ÎÅ ÚÁÍÅÎÑÔØ ÔÁÂÙ ÐÒÏÂÅÌÁÍÉ "
+67 " ÎÁÖÍÉÔÅ Esc (^[) ÄÌÑ ×ÙÚÏ×Á ÍÅÎÀ"
+68 "ÆÁÊÌ ÎÅ ÕËÁÚÁÎ"
+69 "ascii-ËÏÄ: "
+70 "ÐÅÒÅÄÁÀ ÓÏÄÅÒÖÉÍÏÅ ÂÕÆÅÒÁ × \"%s\" "
+71 "ËÏÍÁÎÄÁ: "
+72 "ÚÁÐÉÓÁÔØ × ÆÁÊÌ: "
+73 "ÐÒÏÞÅÓÔØ ÆÁÊÌ: "
+74 "ascii-ËÏÄ ÓÉÍ×ÏÌÁ = %d"
+75 "ÎÅ×ÅÒÎÁÑ ËÏÍÁÎÄÁ \"%s\""
+76 "ÎÅÏÄÎÏÚÎÁÞÎÏÅ ÓÏËÒÁÝÅÎÉÅ ËÏÍÁÎÄÙ"
+77 "ÓÔÒÏËÁ %d "
+78 "ÄÌÉÎÁ = %d ÓÉÍ×."
+79 "ÔÅËÕÝÉÊ ÆÁÊÌ: \"%s\" "
+80 "ÉÓÐÏÌØÚÏ×ÁÎÉÅ: %s [-i] [-e] [-h] [+ÎÏÍÅÒ_ÓÔÒÏËÉ] [ÆÁÊÌ(Ù)]\n"
+81 " -i ÏÔËÌÀÞÉÔØ ÏËÎÏ ÐÏÄÓËÁÚËÉ\n"
+82 " -e ÎÅ ÚÁÍÅÎÑÔØ ÔÁÂÕÌÑÃÉÀ ÐÒÏÂÅÌÁÍÉ\n"
+83 " -h ÎÅ ×ÙÄÅÌÑÔØ ÒÁÍËÉ\n"
+84 "\"%s\" Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ"
+85 "ÎÏ×ÙÊ ÆÁÊÌ \"%s\""
+86 "ÎÅ ÍÏÇÕ ÏÔËÒÙÔØ \"%s\""
+87 "ÆÁÊÌ \"%s\", %d ÓÔÒÏË"
+88 "ÆÁÊÌ \"%s\" ÐÒÏÞÉÔÁÎ"
+89 "ÞÉÔÁÅÍ ÆÁÊÌ \"%s\""
+90 ", ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ"
+91 "ÆÁÊÌ \"%s\", %d ÓÔÒÏË"
+92 "××ÅÄÉÔÅ ÉÍÑ ÆÁÊÌÁ: "
+93 "ÉÍÑ ÆÁÊÌÁ ÎÅ ÚÁÄÁÎÏ: ÆÁÊÌ ÎÅ ÓÏÈÒÁΣÎ"
+94 "÷Ù Õ×ÅÒÅÎÙ, ÞÔÏ ÈÏÔÉÔÅ ÏÔÍÅÎÉÔØ Ó×ÏÉ ÉÚÍÅÎÅÎÉÑ? (y/n [n]) "
+95 "y"
+96 "ÆÁÊÌ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ, ÐÅÒÅÐÉÓÁÔØ ÐÏ×ÅÒÈ? (y/n) [n] "
+97 "ÎÅ ÍÏÇÕ ÓÏÚÄÁÔØ ÆÁÊÌ \"%s\""
+98 "ÚÁÐÉÓÙ×ÁÀ ÆÁÊÌ \"%s\""
+99 "\"%s\" %d ÓÔÒÏË, %d ÓÉÍ×ÏÌÏ×"
+100 " ...ÉÄ£Ô ÐÏÉÓË"
+101 "ÐÏÄÓÔÒÏËÁ \"%s\" ÎÅ ÎÁÊÄÅÎÁ"
+102 "ÞÔÏ ÉÓËÁÔØ: "
+103 "ÎÅ ÍÏÇÕ ÚÁÐÕÓÔÉÔØ %s\n"
+104 "ÄÌÑ ÐÒÏÄÏÌÖÅÎÉÑ ÎÁÖÍÉÔÅ Enter"
+105 "ÄÌÑ ÏÔÍÅÎÙ ÎÁÖÍÉÔÅ Esc"
+106 "ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ ÍÅÎÀ - ÎÅ ÐÏÍÅÝÁÅÔÓÑ × ÜËÒÁÎ"
+107 "ÄÌÑ ÐÒÏÄÏÌÖÅÎÉÑ ÎÁÖÍÉÔÅ ÌÀÂÕÀ ËÌÁ×ÉÛÕ"
+108 "ËÏÍÁÎÄÁ ÏÂÏÌÏÞËÉ: "
+109 "...ÆÏÒÍÁÔÉÒÕÀ ÁÂÚÁÃ..."
+110 "<!echo 'ÓÐÉÓÏË ÐÏÄÏÚÒÉÔÅÌØÎÙÈ ÓÌÏ×'; echo -=-=-=-=-=-"
+111 "ÐÒÏ×ÅÒÑÀ ÐÒÁ×ÏÐÉÓÁÎÉÅ Ó ÐÏÍÏÝØÀ 'spell'"
+112 "ÛÉÒÉÎÁ ÔÅËÓÔÁ: "
+113 "äÅÊÓÔ×ÕÅÔ ÓÔÒÏÇÉÊ ÒÅÖÉÍ: ÎÅ ÉÍÅÀ ÐÒÁ×Á ×ÙÐÏÌÎÑÔØ ÜÔÕ ÏÐÅÒÁÃÉÀ"
+114 " äá"
+115 "îåô"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "ËÌÁ×ÉÛÉ ËÁË × Emacs "
+146 "^a × ÎÁÞÁÌÏ ÓÔÒÏËÉ ^i ÔÁÂÕÌÑÃÉÑ ^r ×ÅÒÎÕÔØ ÓÌÏ×Ï "
+147 "^b ×ÌÅ×Ï ^j ×ÅÒÎÕÔØ ÓÉÍ×ÏÌ ^t × ÓÁÍÙÊ ×ÅÒÈ "
+148 "^c ËÏÍÁÎÄÁ ^k ÕÄÁÌÉÔØ ÓÔÒÏËÕ ^u × ÓÁÍÙÊ ÎÉÚ "
+149 "^d ÕÄÁÌÉÔØ ÓÉÍ×ÏÌ ^l ×ÅÒÎÕÔØ ÓÔÒÏËÕ ^v ÓÌÅÄÕÀÝÁÑ ÓÔÒÁÎÉÃÁ "
+150 "^e × ËÏÎÅà ÓÔÒÏËÉ ^m ÎÏ×ÁÑ ÓÔÒÏËÁ ^w ÕÄÁÌÉÔØ ÓÌÏ×Ï "
+151 "^f ×ÐÒÁ×Ï ^n ×ÎÉÚ ^x ÐÏ×ÔÏÒ ÐÏÉÓËÁ "
+152 "^g ÐÒÅÄ. ÓÔÒÁÎÉÃÁ ^o ÓÉÍ×ÏÌ ÐÏ ascii-ËÏÄÕ ^y ÐÏÉÓË... "
+153 "^h ÚÁÂÏÊ ^p ××ÅÒÈ ^z ÓÌÅÄÕÀÝÅÅ ÓÌÏ×Ï "
+154 "^[ (Esc) ÍÅÎÀ ^y ÐÏÉÓË... ^k ÕÄÁÌÉÔØ ÓÔÒÏËÕ ^p ××ÅÒÈ ^g ÐÒÅÄ. ÓÔÒ."
+155 "^o ascii-ËÏÄ ^x ÐÏ×ÔÏÒ ÐÏÉÓËÁ ^l ×ÅÒÎÕÔØ ÓÔÒÏËÕ ^n ×ÎÉÚ ^v ÓÌÅÄ. ÓÔÒ."
+156 "^u × ÓÁÍÙÊ ÎÉÚ ^a × ÎÁÞÁÌÏ ÓÔÒÏËÉ ^w ÕÄÁÌÉÔØ ÓÌÏ×Ï ^b ×ÌÅ×Ï "
+157 "^t × ÓÁÍÙÊ ×ÅÒÈ ^e × ËÏÎÅà ÓÔÒÏËÉ ^r ×ÅÒÎÕÔØ ÓÌÏ×Ï ^f ×ÐÒÁ×Ï "
+158 "^c ËÏÍÁÎÄÁ ^d ÕÄÁÌÉÔØ ÓÉÍ×ÏÌ ^j ×ÅÒÎÕÔØ ÓÉÍ×ÏÌ ^z ÓÌÅÄÕÀÝÅÅ ÓÌÏ×Ï "
+159 "EMACS"
+160 "NOEMACS"
+161 " +# ÐÅÒÅÊÔÉ Ë ÓÔÒÏËÅ #\n"
+162 "ÎÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÕÓÔÁÎÏ×ËÉ ÐÁÒÁÍÅÔÒÏ× × ÆÁÊÌ .init.ee!"
+163 "ÐÁÒÁÍÅÔÒÙ 'ee' ÓÏÈÒÁÎÅÎÙ × ÆÁÊÌÅ %s"
+164 "ÓÏÈÒÁÎÉÔØ ÕÓÔÁÎÏ×ËÉ"
+165 "õÓÔÁÎÏ×ËÉ ÐÁÒÁÍÅÔÒÏ× 'ee'"
+166 "ÓÏÈÒÁÎÉÔØ × ÔÅËÕÝÅÍ ËÁÔÁÌÏÇÅ"
+167 "ÓÏÈÒÁÎÉÔØ × ÄÏÍÁÛÎÅÍ ËÁÔÁÌÏÇÅ"
+168 "ÕÓÔÁÎÏ×ËÉ ÐÁÒÁÍÅÔÒÏ× 'ee' ÎÅ ÓÏÈÒÁÎÅÎÙ"
+169 "ÐÒÉ ÚÁÐÕÓËÅ 'ree' ÎÅÏÂÈÏÄÉÍÏ ÕËÁÚÁÔØ ÆÁÊÌ ÄÌÑ ÒÅÄÁËÔÉÒÏ×ÁÎÉÑ"
+180 "ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ ÍÅÎÀ - ÎÅ ÐÏÍÅÝÁÅÔÓÑ × ÜËÒÁÎ"
+181 "^^ÄÁÌØÛÅ^^"
+182 "VVÄÁÌØÛÅVV"
+183 "16-ÂÉÔÎÙÅ ÓÉÍ×ÏÌÙ "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/usr.bin/ee/nls/uk_UA.KOI8-U/ee.msg b/usr.bin/ee/nls/uk_UA.KOI8-U/ee.msg
new file mode 100644
index 000000000000..c97de5faf239
--- /dev/null
+++ b/usr.bin/ee/nls/uk_UA.KOI8-U/ee.msg
@@ -0,0 +1,184 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$
+$
+$set 1
+$quote "
+1 "ÍÅÎÀ ÒÅÖÉͦ×"
+2 "ÔÁÂÕÌÑæÑ->ÐÒϦÌÉ "
+3 "ÒÅ­¦ÓÔÒÏ-ÚÁÌÅÖÎÉÊ ÐÏÛÕË "
+4 "Á×ÔÏ-ÐÅÒÅ×ÅÄÅÎÎÑ ÒÑÄËÕ "
+5 "Á×ÔÏ-ÆÏÒÍÁÔ ÐÁÒÁÇÒÁÆÕ "
+6 "8-¦ÔΦ ÓÉÍ×ÏÌÉ "
+7 "¦ÎÆÏÒÍÁæÊΊצËÎÏ "
+8 "ÐÒÁ×Á ÍÅÖÁ "
+9 "ÍÅÎÀ ×ÉÈÏÄÕ"
+10 "ÚÂÅÒÅÇÔÉ ÚͦÎÉ"
+11 "ÎÅ ÚÂÅÒ¦ÇÁÔÉ"
+12 "ÆÁÊÌÏ×Å ÍÅÎÀ"
+13 "ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ"
+14 "ÚÁÐÉÓÁÔÉ ÆÁÊÌ"
+15 "ÚÂÅÒÅÇÔÉ ÆÁÊÌ"
+16 "ÒÏÚÄÒÕËÕ×ÁÔÉ ×ͦÓÔ ÒÅÄÁËÔÏÒÁ"
+17 "ÍÅÎÀ ÐÏÛÕËÕ"
+18 "ÝÏ ÛÕËÁÔÉ..."
+19 "ÐÏÛÕË"
+20 "íÅÎÀ ÐÅÒÅצÒËÉ ÐÒÁ×ÏÐÉÓÕ"
+21 "×ÉËÏÒÉÓÔÕ×Õ×ÁÔÉ 'spell'"
+22 "×ÉËÏÒÉÓÔÕ×Õ×ÁÔÉ 'ispell'"
+23 "Ò¦ÚÎÅ..."
+24 "ÆÏÒÍÁÔÕ×ÁÎÎÑ ÐÁÒÁÇÒÁÆÕ"
+25 "ËÏÍÁÎÄÁ ÏÂÏÌÏÎËÉ"
+26 "ÐÅÒÅצÒËÁ ÐÒÁ×ÏÐÉÓÕ"
+27 "ÇÏÌÏ×ÎÅ ÍÅÎÀ"
+28 "×ÉÊÔÉ Ú ÒÅÄÁËÔÏÒÕ"
+29 "ÄÏצÄËÁ"
+30 "ÏÐÅÒÁæ§ Ú ÆÁÊÌÁÍÉ"
+31 "ÏÎÏ×ÉÔÉ ÅËÒÁÎ"
+32 "ËÏÎƦÇÕÒÁæÑ"
+33 "ÐÏÛÕË"
+34 "Ò¦ÚÎÅ"
+35 "ëÌÁצۦ ËÅÒÕ×ÁÎÎÑ: "
+36 "^a ascii-ËÏÄ ^i ÔÁÂÕÌÑÃ¦Ñ ^r ×ÐÒÁ×Ï "
+37 "^b ÎÉÚ ÔÅËÓÔÕ ^j ÎÏ×ÉÊ ÒÑÄÏË ^t ×ÅÒÈ ÔÅËÓÔÕ "
+38 "^c ËÏÍÁÎÄÁ ^k ÓÔÅÒÔÉ ÓÉÍ×ÏÌ ^u ××ÅÒÈ "
+39 "^d ×ÎÉÚ ^l ×̦×Ï ^v צÄÎÏ×ÉÔÉ ÓÌÏ×Ï "
+40 "^e ÝÏ ÛÕËÁÔÉ... ^m ÎÏ×ÉÊ ÒÑÄÏË ^w ÓÔÅÒÔÉ ÓÌÏ×Ï "
+41 "^f צÄÎÏ×ÉÔÉ ÓÉÍ×ÏÌ ^n ÎÁÓÔÕÐÎÁ ÓÔÏÒ¦ÎËÁ ^x ÛÕËÁÔÉ "
+42 "^g ÐÏÞÁÔÏË ÒÑÄËÕ ^o ˦ÎÅÃØ ÒÑÄËÕ ^y ÓÔÅÒÔÉ ÒÑÄÏË "
+43 "^h ÚÁÔÅÒÔÉ ^p ÐÏÐÅÒÅÄÎÑ ÓÔÏÒ¦ÎËÁ ^z צÄÎÏ×ÉÔÉ ÒÑÄÏË "
+44 "^[ (escape) ÍÅÎÀ ESC-Enter: ×ÉÊÔÉ Ú ee "
+45 " "
+46 "ëÏÍÁÎÄÉ: "
+47 "help : ÃÑ ÄÏצÄËÁ file : ÐÏËÁÚÁÔÉ ¦Í'Ñ ÆÁÊÌÕ "
+48 "read : ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ char : ascii-ËÏÄ ÓÉÍ×ÏÌÕ "
+49 "write : ÚÁÐÉÓÁÔÉ ÆÁÊÌ case : ÒÅ­¦ÓÔÒÏ-ÚÁÌÅÖÎÉÊ ÐÏÛÕË "
+50 "exit : ÚÂÅÒÅÇÔÉ +×ÉÈ¦Ä nocase : ÒÅ­¦ÓÔÒÏ-ÎÅÚÁÌÅÖÎÉÊ ÐÏÛÕË"
+51 "quit : ×ÉÊÔÉ ÂÅÚ ÚͦΠ!ËÏÍÁÎÄÁ: ×ÉËÏÎÁÔÉ ËÏÍÁÎÄÕ ÏÂÏÌÏÎËÉ "
+52 "line : ÐÏËÁÚÁÔÉ ÎÏÍÅÒ ÒÑÄËÕ 0-9 : ÐÅÒÅÊÔÉ ÄÏ ÒÑÄËÕ "
+53 "expand : ÒÏÚÛÉÒÀ×ÁÔÉ ÔÁÂÕÌÑæÀ noexpand: ÎÅ ÒÏÚÛÉÒÀ×ÁÔÉ ÔÁÂÕÌÑæÀ "
+54 " "
+55 " ee [+#] [-i] [-e] [-h] [ÆÁÊÌ(É)] "
+56 "+# ËÕÒÓÏÒ ÎÁ ÒÑÄÏË -i:ÂÅÚ ¦ÎÆÏ-צËÎÁ -e:ÎÅ ÒÏÚÛÉÒÀ×ÁÔÉ ôáâÉ -h:ÂÅÚ Ð¦ÄÓצÔËÉ"
+57 "^[ (ESC) ÍÅÎÀ ^e ÝÏ ÛÕËÁÔÉ... ^y ÓÔÅÒÔÉ ÒÑÄÏË ^u ××ÅÒÈ ^p -ÓÔÏÒ¦ÎËÁ "
+58 "^a ascii-ËÏÄ ^x ÐÏÛÕË ^z צÄÎÏ×. ÒÑÄÏË ^d ×ÎÉÚ ^n +ÓÔÏÒ¦ÎËÁ "
+59 "^b ÎÉÚ ÔÅËÓÔÕ ^g ÐÏÞÁÔÏË ÒÑÄËÕ ^w ÓÔÅÒÔÉ ÓÌÏ×Ï ^l ×̦×Ï "
+60 "^t ×ÅÒÈ ÔÅËÓÔÕ ^o ˦ÎÅÃØ ÒÑÄËÕ ^v צÄÎÏ×. ÓÌÏ×Ï ^r ×ÐÒÁ×Ï "
+61 "^c ËÏÍÁÎÄÁ ^k ÓÔÅÒÔÉ ÓÉÍ×ÏÌ ^f צÄÎÏ×ÉÔÉ ÓÉÍ×ÏÌ ESC-Enter: ×ÉÊÔÉ Ú ee"
+62 "help : ÄÏצÄËÁ |file : ÐÏËÁÚÁÔÉ ¦'ÍÑ ÆÁÊÌÕ |line : ÎÏÍÅÒ ÒÑÄËÕ "
+63 "read : ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ |char : ascii-ËÏÄ ÓÉÍ×ÏÌÕ |0-9 : ÐÅÒÅÊÔÉ ÄÏ ÒÑÄËÕ"
+64 "write: ÚÁÐÉÓÁÔÉ ÆÁÊÌ |case : ÒÅ­¦ÓÔÒÏ-ÚÁÌÅÖÎÉÊ ÐÏÛÕË |exit : ÚÂÅÒÅÇÔÉ +×ÉȦÄ"
+65 "!ËÍÄ : ÚÏ×Î. ËÏÍÁÎÄÁ |nocase: ÒÅ­¦ÓÔÒÏ-ÎÅÚÁÌ. ÐÏÛÕË |quit : ×ÉÊÔÉ ÂÅÚ ÚͦÎ"
+66 "expand: ÒÏÚÛÉÒÀ×ÁÔÉ |noexpand: ÎÅ ÒÏÚÛÉÒÀ×ÁÔÉ ôáâÉ × ÐÒϦÌÉ "
+67 " ÎÁÔÉÓΦÔØ Esc (^[) ÝÏ ×ÉËÌÉËÁÔÉ ÍÅÎÀ"
+68 "ÎÅÍÁ¤ ÆÁÊÌÕ"
+69 "ascii-ËÏÄ: "
+70 "צÄÓÉÌÁÎÎÑ ×ͦÓÔÕ ÂÕÆÅÒÕ ÄÏ \"%s\" "
+71 "ËÏÍÁÎÄÁ: "
+72 "¦Í'Ñ ÆÁÊÌÕ ÄÌÑ ÚÁÐÉÓÕ: "
+73 "¦Í'Ñ ÆÁÊÌÕ ÄÌÑ ÞÉÔÁÎÎÑ: "
+74 "ÓÉÍ×ÏÌ = %d"
+75 "ÎÅצÄÏÍÁ ËÏÍÁÎÄÁ \"%s\""
+76 "ÃÑ ËÏÍÁÎÄÁ ÎÅ ÕΦËÁÌØÎÁ"
+77 "ÒÑÄÏË %d "
+78 "ÄÏ×ÖÉÎÁ = %d"
+79 "ÐÏÔÏÞÎÉÊ ÆÁÊÌ: \"%s\" "
+80 "÷ÉËÏÒÉÓÔÁÎÎÑ: %s [-i] [-e] [-h] [+ÎÏÍÅÒ_ÒÑÄËÕ] [ÆÁÊÌ(É)]\n"
+81 " -i ÎÅ ÐÏËÁÚÕ×ÁÔÉ ¦ÎÆÏÒÍÁæÊΊצËÎÏ\n"
+82 " -e ÎÅ ÐÅÒÅÔ×ÏÒÀ×ÁÔÉ ÔÁÂÕÌÑæÀ × ÐÒϦÌÉ\n"
+83 " -h ÎÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ Ð¦ÄÓצÔËÕ\n"
+84 " ÆÁÊÌ \"%s\" - ÎÁÓÐÒÁ×Ħ ËÁÔÁÌÏÇ"
+85 "ÎÏ×ÉÊ ÆÁÊÌ \"%s\""
+86 "ÎÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ \"%s\""
+87 "ÆÁÊÌ \"%s\", ÒÑÄ˦×: %d"
+88 "ÆÁÊÌ \"%s\" ÐÒÏÞÉÔÁÎÏ"
+89 "ÞÉÔÁÎÎÑ ÆÁÊÌÕ \"%s\""
+90 ", ÔiÌØËu ÄÌÑ ÞÉÔÁÎÎÑ"
+91 "ÆÁÊÌ \"%s\", ÒÑÄ˦×: %d"
+92 "××ÅĦÔØ ¦Í'Ñ ÆÁÊÌÕ: "
+93 "¦Í'Ñ ÆÁÊÌÕ ÎÅ ÚÁÄÁÎÏ: ÆÁÊÌ ÎÅ ÚÁÐÉÓÁÎÏ "
+94 "×ÎÅÓÅÎÏ ÚͦÎÉ, ×É ×ÐÅ×ÎÅΦ? (y/n [n]) "
+95 "y"
+96 "ÆÁÊÌ ×ÖÅ ¦ÓÎÕ¤, ÐÅÒÅÚÁÐÉÓÁÔÉ? (y/n) [n] "
+97 "ÎÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ \"%s\""
+98 "ÚÁÐÉÓ ÆÁÊÌÕ \"%s\""
+99 "\"%s\", ÒÑÄ˦×: %d, ÓÉÍ×Ï̦×: %d"
+100 " ...ÐÏÛÕË"
+101 "ÒÑÄÏË \"%s\" ÎÅ ÚÎÁÊÄÅÎÏ"
+102 "ÝÏ ÛÕËÁÔÉ: "
+103 "ÎÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ %s\n"
+104 "ÎÁÔÉÓΦÔØ <enter> ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ..."
+105 "Esc - צÄͦÎÁ"
+106 "ÍÅÎÀ ÚÁ×ÅÌÉËÅ ÄÌÑ ÅËÒÁÎÕ"
+107 "ÎÁÔÉÓΦÔØ ÂÕÄØ-ÑËÕ ËÌÁצÛÕ ÄÌÑ ÐÒÏÄÏ×ÖÅÎÎÑ..."
+108 "ËÏÍÁÎÄÁ ÏÂÏÌÏÎËÉ: "
+109 "...ÆÏÒÍÁÔÕÀ ÐÁÒÁÇÒÁÆ..."
+110 "<!echo 'ÓÐÉÓÏË ÎÅÒÏÚЦÚÎÁÎÉÈ Ó̦×'; echo -=-=-=-=-=-"
+111 "צÄÓÉÌÁÎÎÑ ×ͦÓÔÕ ÂÕÆÅÒÕ ÄÏ 'spell'"
+112 "ÐÒÁ×Á ÍÅÖÁ: "
+113 "ïÂÍÅÖÅÎÉÊ ÒÅÖÉÍ: ÎÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÃÀ ÏÐÅÒÁæÀ"
+114 "ON"
+115 "OFF"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "ÐÒÉ×'ÑÚËÁ ËÌÁ×¦Û Emacs "
+146 "^a ÐÏÞÁÔÏË ÒÑÄËÕ ^i ÔÁÂÕÌÑÃ¦Ñ ^r צÄÎÏ×ÉÔÉ ÓÌÏ×Ï "
+147 "^b ÎÁÚÁÄ 1 ÓÉÍ×ÏÌ ^j צÄÎÏ×ÉÔÉ ÓÉÍ×ÏÌ ^t ÐÏÞÁÔÏË ÆÁÊÌÕ "
+148 "^c ËÏÍÁÎÄÁ ^k ÓÔÅÒÔÉ ÒÑÄÏË ^u ˦ÎÅÃØ ÆÁÊÌÕ "
+149 "^d ÓÔÅÒÔÉ ÓÉÍ×ÏÌ ^l צÄÎÏ×ÉÔÉ ÓÉÍ×ÏÌ ^v ÎÁÓÔÕÐÎÁ ÓÔÏÒ¦ÎËÁ "
+150 "^e ˦ÎÅÃØ ÒÑÄËÕ ^m ÎÏ×ÉÊ ÒÑÄÏË ^w ÓÔÅÒÔÉ ÓÌÏ×Ï "
+151 "^f ×ÐÅÒÅÄ 1 ÓÉÍ×ÏÌ ^n ÎÁÓÔÕÐÎÉÊ ÒÑÄÏË ^x ÐÏÛÕË "
+152 "^g ÎÁÚÁÄ 1 ÓÔÏÒ¦ÎËÕ ^o ×ÓÔÁ×ÉÔÉ ASCII ^y ÝÏ ÛÕËÁÔÉ... "
+153 "^h ÚÁÔÅÒÔÉ ^p ÐÏÐÅÒÅÄÎ¦Ê ÒÑÄÏË ^z ÎÁÓÔÕÐÎÅ ÓÌÏ×Ï "
+154 "^[ (ESC) ÍÅÎÀ ^y ÝÏ ÛÕËÁÔÉ ^k ÓÔÅÒÔÉ ÒÑÄÏË ^p -ÒÑÄÏË ^g -ÓÔÏÒ¦ÎËÁ"
+155 "^o ascii-ËÏÄ ^x ÐÏÛÕË ^l צÄÎÏ×. ÒÑÄÏË ^n +ÒÑÄÏË ^v +ÓÔÏÒ¦ÎËÁ"
+156 "^u ˦ÎÅÃØ ÆÁÊÌÕ ^a ÐÏÞÁÔÏË ÒÑÄËÕ ^w ÓÔÅÒÔÉ ÓÌÏ×Ï ^b ÎÁÚÁÄ 1 ÓÉÍ×ÏÌ "
+157 "^t ÐÏÞÁÔÏË ÆÁÊÌÕ ^e ˦ÎÅÃØ ÒÑÄËÕ ^r צÄÎÏ×. ÓÌÏ×Ï ^f ×ÐÅÒÅÄ 1 ÓÉÍ×ÏÌ "
+158 "^c ËÏÍÁÎÄÁ ^d ÓÔÅÒÔÉ ÓÉÍ×ÏÌ ^j צÄÎ. ÓÉÍ×ÏÌ ^z ÎÁÓÔÕÐÎÅ ÓÌÏ×Ï "
+159 "EMACS"
+160 "NOEMACS"
+161 " +# ÐÏÓÔÁ×ÉÔÉ ËÕÒÓÏÒ × ÒÑÄÏË Ú ÎÏÍÅÒÏÍ\n"
+162 "ÎÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ .init.ee ÄÌÑ ÚÁÐÉÓÕ, ËÏÎƦÇÕÒÁæÀ Îe ÚÁÐÉÓÁÎÏ!"
+163 "ËÏÎƦÇÕÒÁæÀ ee ÚÁÐÉÓÁÎÏ Õ ÆÁÊÌ %s"
+164 "ÚÂÅÒÅÇÔÉ ËÏÎƦÇÕÒÁæÀ "
+165 "ÚÂÅÒÅÇÔÉ ËÏÎƦÇÕÒÁæÀ ee"
+166 "ÚÂÅÒÅÇÔÉ × ÐÏÔÏÞÎÏÍÕ ËÁÔÁÌÏÚ¦"
+167 "ÚÂÅÒÅÇÔÉ × ÄÏÍÁÛÎØÏÍÕ ËÁÔÁÌÏÚ¦"
+168 "ËÏÎƦÇÕÒÁæÀ ee Îe ÚÁÐÉÓÁÎÏ"
+169 "Ð¦Ä ÞÁÓ ÚÁÐÕÓËÕ ree ÓÌ¦Ä ×ËÁÚÕ×ÁÔÉ ¦Í'Ñ ÆÁÊÌÕ"
+180 "ÍÅÎÀ ÚÁ×ÅÌÉËÅ ÄÌÑ ÅËÒÁÎÕ"
+181 "^^ÄÁ̦^^"
+182 "VVÄÁ̦VV"
+183 "16-¦ÔÏצ ÓÉÍ×ÏÌÉ "
+184 "16â¶ô"
+185 "ÎÅ16â¶ô"
diff --git a/usr.bin/elfctl/Makefile b/usr.bin/elfctl/Makefile
new file mode 100644
index 000000000000..82d5f3e7c4fb
--- /dev/null
+++ b/usr.bin/elfctl/Makefile
@@ -0,0 +1,9 @@
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+
+PROG= elfctl
+
+LIBADD= elftc elf
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/elfctl/elfctl.1 b/usr.bin/elfctl/elfctl.1
new file mode 100644
index 000000000000..5ba016b664a3
--- /dev/null
+++ b/usr.bin/elfctl/elfctl.1
@@ -0,0 +1,109 @@
+.\" Copyright 2019 The FreeBSD Foundation.
+.\"
+.\" This software was developed by Bora Ozarslan under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 October 5, 2023
+.Dt ELFCTL 1
+.Os
+.Sh NAME
+.Nm elfctl
+.Nd change an ELF binary's feature control note
+.Sh SYNOPSIS
+.Nm
+.Op Fl h | Fl -help
+.Op Fl i
+.Op Fl l
+.Op Fl e Ar featurelist
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility modifies feature flags in the feature control note in an ELF binary.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl h | Fl -help
+Print a usage message and exit.
+.It Fl i
+Ignore unknown feature flags in
+.Ar featurelist .
+.It Fl l
+List known ELF feature flags.
+.It Fl e Ar featurelist
+Edit features from the given comma separated list
+.Ar featurelist .
+.Ar featurelist
+starts with one of the three operations:
+.Dq Li +
+to turn on the features,
+.Dq Li -
+to turn off the features,
+.Dq Li =
+to only turn on the given features.
+A comma separated list of feature names or numeric values follows the
+operation.
+.El
+.Pp
+If
+.Fl e
+is not specified
+.Nm
+displays the status of each feature in the ELF note in each
+.Ar .
+.Sh EXIT STATUS
+Exit status is 0 on success, and 1 if the command
+fails if a file does not exist, is too short,
+or fails to find or edit features note.
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Bd -literal -offset indent
+elfctl file
+elfctl -e +noaslr file
+.Ed
+.Pp
+Features may be specified as numerical values:
+.Bd -literal -offset indent
+elfctl -e =0x0001,0x0004 file
+.Ed
+.Pp
+Features may also be specified as a single combined value:
+.Bd -literal -offset indent
+elfctl -e =0x5 file
+.Ed
+.Sh SEE ALSO
+.Xr mitigations 7
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 12.2 .
+.Sh AUTHORS
+.Nm
+was written by
+.An Bora Ozarslan Mt borako.ozarslan@gmail.com
+under sponsorship from the
+.Fx Foundation.
diff --git a/usr.bin/elfctl/elfctl.c b/usr.bin/elfctl/elfctl.c
new file mode 100644
index 000000000000..d9cb557bbad4
--- /dev/null
+++ b/usr.bin/elfctl/elfctl.c
@@ -0,0 +1,466 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 The FreeBSD Foundation.
+ *
+ * This software was developed by Bora Ozarslan under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/elf_common.h>
+#include <sys/endian.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelf.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+static bool convert_to_feature_val(const char *, uint32_t *);
+static bool edit_file_features(Elf *, int, int, char *, bool);
+static bool get_file_features(Elf *, int, int, uint32_t *, uint64_t *, bool);
+static void print_features(void);
+static bool print_file_features(Elf *, int, int, char *, bool);
+static void usage(void) __dead2;
+
+struct ControlFeatures {
+ const char *alias;
+ unsigned long value;
+ const char *desc;
+};
+
+static struct ControlFeatures featurelist[] = {
+ { "noaslr", NT_FREEBSD_FCTL_ASLR_DISABLE, "Disable ASLR" },
+ { "noprotmax", NT_FREEBSD_FCTL_PROTMAX_DISABLE,
+ "Disable implicit PROT_MAX" },
+ { "nostackgap", NT_FREEBSD_FCTL_STKGAP_DISABLE, "Disable stack gap" },
+ { "wxneeded", NT_FREEBSD_FCTL_WXNEEDED, "Requires W+X mappings" },
+ { "la48", NT_FREEBSD_FCTL_LA48, "amd64: Limit user VA to 48bit" },
+};
+
+static struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, NULL, 0 }
+};
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define HOST_ENDIAN ELFDATA2LSB
+#define SWAP_ENDIAN ELFDATA2MSB
+#else
+#define HOST_ENDIAN ELFDATA2MSB
+#define SWAP_ENDIAN ELFDATA2LSB
+#endif
+
+static bool iflag;
+
+int
+main(int argc, char **argv)
+{
+ GElf_Ehdr ehdr;
+ Elf *elf;
+ Elf_Kind kind;
+ int ch, fd, retval;
+ char *features;
+ bool editfeatures, lflag, endian_swap;
+
+ lflag = 0;
+ editfeatures = false;
+ retval = 0;
+ features = NULL;
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ errx(EXIT_FAILURE, "elf_version error");
+
+ while ((ch = getopt_long(argc, argv, "hile:", long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'i':
+ iflag = true;
+ break;
+ case 'l':
+ print_features();
+ lflag = true;
+ break;
+ case 'e':
+ if (features != NULL)
+ errx(1, "-e may be specified only once");
+ features = optarg;
+ editfeatures = true;
+ break;
+ case 'h':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0) {
+ if (lflag)
+ exit(0);
+ else {
+ warnx("no file(s) specified");
+ usage();
+ }
+ }
+
+ while (argc) {
+ elf = NULL;
+
+ if ((fd = open(argv[0],
+ editfeatures ? O_RDWR : O_RDONLY, 0)) < 0) {
+ warn("error opening file %s", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+
+ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+ warnx("elf_begin failed: %s", elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ if ((kind = elf_kind(elf)) != ELF_K_ELF) {
+ if (kind == ELF_K_AR)
+ warnx("file '%s' is an archive", argv[0]);
+ else
+ warnx("file '%s' is not an ELF file", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+
+ if (gelf_getehdr(elf, &ehdr) == NULL) {
+ warnx("gelf_getehdr: %s", elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ if (ehdr.e_ident[EI_DATA] == HOST_ENDIAN) {
+ endian_swap = false;
+ } else if (ehdr.e_ident[EI_DATA] == SWAP_ENDIAN) {
+ endian_swap = true;
+ } else {
+ warnx("file endianness unknown");
+ retval = 1;
+ goto fail;
+ }
+
+ if (!editfeatures) {
+ if (!print_file_features(elf, ehdr.e_phnum, fd,
+ argv[0], endian_swap)) {
+ retval = 1;
+ goto fail;
+ }
+ } else if (!edit_file_features(elf, ehdr.e_phnum, fd,
+ features, endian_swap)) {
+ retval = 1;
+ goto fail;
+ }
+fail:
+ if (elf != NULL)
+ elf_end(elf);
+
+ if (fd >= 0)
+ close(fd);
+
+ argc--;
+ argv++;
+ }
+
+ return (retval);
+}
+
+#define USAGE_MESSAGE \
+ "\
+Usage: %s [options] file...\n\
+ Set or display the control features for an ELF object.\n\n\
+ Supported options are:\n\
+ -l List known control features.\n\
+ -i Ignore unknown features.\n\
+ -e [+-=]feature,list Edit features from a comma separated list.\n\
+ -h | --help Print a usage message and exit.\n"
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(1);
+}
+
+static bool
+convert_to_feature_val(const char *feature_str, uint32_t *feature_val)
+{
+ char *feature, *feature_tmp;
+ int i, len;
+ uint32_t input;
+ char operation;
+
+ input = 0;
+ operation = *feature_str;
+ feature_str++;
+
+ if (operation != '+' && operation != '-' && operation != '=')
+ errx(1, "'%c' not an operator - use '+', '-', '='", operation);
+
+ if ((feature_tmp = strdup(feature_str)) == NULL)
+ err(1, "strdup");
+ len = nitems(featurelist);
+ while ((feature = strsep(&feature_tmp, ",")) != NULL) {
+ for (i = 0; i < len; ++i) {
+ if (strcmp(featurelist[i].alias, feature) == 0) {
+ input |= featurelist[i].value;
+ break;
+ }
+ /* XXX Backwards compatibility for "no"-prefix flags. */
+ if (strncmp(featurelist[i].alias, "no", 2) == 0 &&
+ strcmp(featurelist[i].alias + 2, feature) == 0) {
+ input |= featurelist[i].value;
+ warnx(
+ "interpreting %s as %s; please specify %s",
+ feature, featurelist[i].alias,
+ featurelist[i].alias);
+ break;
+ }
+ }
+ if (i == len) {
+ if (isdigit(feature[0])) {
+ char *eptr;
+ unsigned long long val;
+
+ errno = 0;
+ val = strtoll(feature, &eptr, 0);
+ if (eptr == feature || *eptr != '\0')
+ errno = EINVAL;
+ else if (val > UINT32_MAX)
+ errno = ERANGE;
+ if (errno != 0) {
+ warn("%s invalid", feature);
+ free(feature_tmp);
+ return (false);
+ }
+ input |= val;
+ } else {
+ warnx("%s is not a valid feature", feature);
+ if (!iflag) {
+ free(feature_tmp);
+ return (false);
+ }
+ }
+ }
+ }
+
+ if (operation == '+') {
+ *feature_val |= input;
+ } else if (operation == '=') {
+ *feature_val = input;
+ } else if (operation == '-') {
+ *feature_val &= ~input;
+ }
+ free(feature_tmp);
+ return (true);
+}
+
+static bool
+edit_file_features(Elf *elf, int phcount, int fd, char *val, bool endian_swap)
+{
+ uint32_t features, prev_features;
+ uint64_t off;
+
+ if (!get_file_features(elf, phcount, fd, &features, &off,
+ endian_swap)) {
+ warnx("NT_FREEBSD_FEATURE_CTL note not found");
+ return (false);
+ }
+
+ prev_features = features;
+ if (!convert_to_feature_val(val, &features))
+ return (false);
+ /* Avoid touching file if no change. */
+ if (features == prev_features)
+ return (true);
+
+ if (endian_swap)
+ features = bswap32(features);
+
+ if (lseek(fd, off, SEEK_SET) == -1 ||
+ write(fd, &features, sizeof(features)) <
+ (ssize_t)sizeof(features)) {
+ warnx("error writing feature value");
+ return (false);
+ }
+ return (true);
+}
+
+static void
+print_features(void)
+{
+ size_t i;
+
+ printf("Known features are:\n");
+ for (i = 0; i < nitems(featurelist); ++i)
+ printf("%-16s%s\n", featurelist[i].alias,
+ featurelist[i].desc);
+}
+
+static bool
+print_file_features(Elf *elf, int phcount, int fd, char *filename,
+ bool endian_swap)
+{
+ uint32_t features;
+ unsigned long i;
+
+ if (!get_file_features(elf, phcount, fd, &features, NULL,
+ endian_swap)) {
+ return (false);
+ }
+
+ printf("File '%s' features:\n", filename);
+ for (i = 0; i < nitems(featurelist); ++i) {
+ printf("%-16s'%s' is ", featurelist[i].alias,
+ featurelist[i].desc);
+
+ if ((featurelist[i].value & features) == 0)
+ printf("un");
+
+ printf("set.\n");
+ }
+ return (true);
+}
+
+static bool
+get_file_features(Elf *elf, int phcount, int fd, uint32_t *features,
+ uint64_t *off, bool endian_swap)
+{
+ GElf_Phdr phdr;
+ Elf_Note note;
+ unsigned long read_total;
+ int namesz, descsz, i;
+ char *name;
+
+ /*
+ * Go through each program header to find one that is of type PT_NOTE
+ * and has a note for feature control.
+ */
+ for (i = 0; i < phcount; ++i) {
+ if (gelf_getphdr(elf, i, &phdr) == NULL) {
+ warnx("gelf_getphdr failed: %s", elf_errmsg(-1));
+ return (false);
+ }
+
+ if (phdr.p_type != PT_NOTE)
+ continue;
+
+ if (lseek(fd, phdr.p_offset, SEEK_SET) < 0) {
+ warn("lseek() failed:");
+ return (false);
+ }
+
+ read_total = 0;
+ while (read_total < phdr.p_filesz) {
+ if (read(fd, &note, sizeof(note)) <
+ (ssize_t)sizeof(note)) {
+ warnx("elf note header too short");
+ return (false);
+ }
+ read_total += sizeof(note);
+
+ if (endian_swap) {
+ note.n_namesz = bswap32(note.n_namesz);
+ note.n_descsz = bswap32(note.n_descsz);
+ note.n_type = bswap32(note.n_type);
+ }
+
+ /*
+ * XXX: Name and descriptor are 4 byte aligned, however,
+ * the size given doesn't include the padding.
+ */
+ namesz = roundup2(note.n_namesz, 4);
+ name = malloc(namesz);
+ if (name == NULL) {
+ warn("malloc() failed.");
+ return (false);
+ }
+ descsz = roundup2(note.n_descsz, 4);
+ if (read(fd, name, namesz) < namesz) {
+ warnx("elf note name too short");
+ free(name);
+ return (false);
+ }
+ read_total += namesz;
+
+ if (note.n_namesz != 8 ||
+ strncmp("FreeBSD", name, 7) != 0 ||
+ note.n_type != NT_FREEBSD_FEATURE_CTL) {
+ /* Not the right note. Skip the description */
+ if (lseek(fd, descsz, SEEK_CUR) < 0) {
+ warn("lseek() failed.");
+ free(name);
+ return (false);
+ }
+ read_total += descsz;
+ free(name);
+ continue;
+ }
+
+ if (note.n_descsz < sizeof(uint32_t)) {
+ warnx("Feature descriptor can't "
+ "be less than 4 bytes");
+ free(name);
+ return (false);
+ }
+
+ /*
+ * XXX: For now we look at only 4 bytes of the
+ * descriptor. This should respect descsz.
+ */
+ if (note.n_descsz > sizeof(uint32_t))
+ warnx("Feature note is bigger than expected");
+ if (read(fd, features, sizeof(uint32_t)) <
+ (ssize_t)sizeof(uint32_t)) {
+ warnx("feature note data too short");
+ free(name);
+ return (false);
+ }
+ if (endian_swap)
+ *features = bswap32(*features);
+ if (off != NULL)
+ *off = phdr.p_offset + read_total;
+ free(name);
+ return (true);
+ }
+ }
+
+ warnx("NT_FREEBSD_FEATURE_CTL note not found");
+ return (false);
+}
diff --git a/usr.bin/elfdump/Makefile b/usr.bin/elfdump/Makefile
new file mode 100644
index 000000000000..5b48a8b6174d
--- /dev/null
+++ b/usr.bin/elfdump/Makefile
@@ -0,0 +1,3 @@
+PROG= elfdump
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/elfdump/Makefile.depend b/usr.bin/elfdump/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/elfdump/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/elfdump/elfdump.1 b/usr.bin/elfdump/elfdump.1
new file mode 100644
index 000000000000..03b2ec1c61e3
--- /dev/null
+++ b/usr.bin/elfdump/elfdump.1
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2003 David O'Brien
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 November 5, 2018
+.Dt ELFDUMP 1
+.Os
+.Sh NAME
+.Nm elfdump
+.Nd "display information about"
+.Tn ELF
+files
+.Sh SYNOPSIS
+.Nm
+.Fl a | E | cdeGhinprs
+.Op Fl w Ar file
+.Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility
+dumps various information about the specified
+.Tn ELF
+.Ar file .
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl w Ar file"
+.It Fl a
+Dump all information.
+.It Fl c
+Dump section headers.
+.It Fl d
+Dump dynamic symbols.
+.It Fl e
+Dump ELF header.
+.It Fl E
+Return success if
+.Ar file
+is an ELF file and failure if it is not.
+This option is exclusive with other options.
+.It Fl G
+Dump the GOT.
+.It Fl h
+Dump the hash values.
+.It Fl i
+Dump the dynamic interpreter.
+.It Fl n
+Dump note sections.
+.It Fl p
+Dump the program header.
+.It Fl r
+Dump relocations.
+.It Fl s
+Dump the symbol table.
+.It Fl w Ar file
+Write output to a
+.Ar file
+instead of the standard output.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Pp
+.Dl "elfdump -a -w output /bin/ls"
+.Sh SEE ALSO
+.Xr objdump 1 ,
+.Xr readelf 1
+.Rs
+.%A "AT&T Unix Systems Labs"
+.%T "System V Application Binary Interface"
+.%U http://www.sco.com/developers/gabi/
+.Re
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility
+was written by
+.An Jake Burkholder Aq Mt jake@FreeBSD.org .
+This
+manual page was written by
+.An David O'Brien Aq Mt obrien@FreeBSD.org .
+.Sh BUGS
+Does not fully implement the
+.Tn ELF
+gABI.
diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c
new file mode 100644
index 000000000000..49704cde1b08
--- /dev/null
+++ b/usr.bin/elfdump/elfdump.c
@@ -0,0 +1,1287 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003 David O'Brien. All rights reserved.
+ * Copyright (c) 2001 Jake Burkholder
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/capsicum.h>
+#include <sys/elf32.h>
+#include <sys/elf64.h>
+#include <sys/endian.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ED_DYN (1<<0)
+#define ED_EHDR (1<<1)
+#define ED_GOT (1<<2)
+#define ED_HASH (1<<3)
+#define ED_INTERP (1<<4)
+#define ED_NOTE (1<<5)
+#define ED_PHDR (1<<6)
+#define ED_REL (1<<7)
+#define ED_SHDR (1<<8)
+#define ED_SYMTAB (1<<9)
+#define ED_ALL ((1<<10)-1)
+#define ED_IS_ELF (1<<10) /* Exclusive with other flags */
+
+#define elf_get_addr elf_get_quad
+#define elf_get_off elf_get_quad
+#define elf_get_size elf_get_quad
+
+enum elf_member {
+ D_TAG = 1, D_PTR, D_VAL,
+
+ E_CLASS, E_DATA, E_OSABI, E_TYPE, E_MACHINE, E_VERSION, E_ENTRY,
+ E_PHOFF, E_SHOFF, E_FLAGS, E_EHSIZE, E_PHENTSIZE, E_PHNUM, E_SHENTSIZE,
+ E_SHNUM, E_SHSTRNDX,
+
+ N_NAMESZ, N_DESCSZ, N_TYPE,
+
+ P_TYPE, P_OFFSET, P_VADDR, P_PADDR, P_FILESZ, P_MEMSZ, P_FLAGS,
+ P_ALIGN,
+
+ SH_NAME, SH_TYPE, SH_FLAGS, SH_ADDR, SH_OFFSET, SH_SIZE, SH_LINK,
+ SH_INFO, SH_ADDRALIGN, SH_ENTSIZE,
+
+ ST_NAME, ST_VALUE, ST_SIZE, ST_INFO, ST_SHNDX,
+
+ R_OFFSET, R_INFO,
+
+ RA_OFFSET, RA_INFO, RA_ADDEND
+};
+
+typedef enum elf_member elf_member_t;
+
+static int elf32_offsets[] = {
+ 0,
+
+ offsetof(Elf32_Dyn, d_tag), offsetof(Elf32_Dyn, d_un.d_ptr),
+ offsetof(Elf32_Dyn, d_un.d_val),
+
+ offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
+ offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
+ offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
+ offsetof(Elf32_Ehdr, e_type), offsetof(Elf32_Ehdr, e_machine),
+ offsetof(Elf32_Ehdr, e_version), offsetof(Elf32_Ehdr, e_entry),
+ offsetof(Elf32_Ehdr, e_phoff), offsetof(Elf32_Ehdr, e_shoff),
+ offsetof(Elf32_Ehdr, e_flags), offsetof(Elf32_Ehdr, e_ehsize),
+ offsetof(Elf32_Ehdr, e_phentsize), offsetof(Elf32_Ehdr, e_phnum),
+ offsetof(Elf32_Ehdr, e_shentsize), offsetof(Elf32_Ehdr, e_shnum),
+ offsetof(Elf32_Ehdr, e_shstrndx),
+
+ offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
+ offsetof(Elf_Note, n_type),
+
+ offsetof(Elf32_Phdr, p_type), offsetof(Elf32_Phdr, p_offset),
+ offsetof(Elf32_Phdr, p_vaddr), offsetof(Elf32_Phdr, p_paddr),
+ offsetof(Elf32_Phdr, p_filesz), offsetof(Elf32_Phdr, p_memsz),
+ offsetof(Elf32_Phdr, p_flags), offsetof(Elf32_Phdr, p_align),
+
+ offsetof(Elf32_Shdr, sh_name), offsetof(Elf32_Shdr, sh_type),
+ offsetof(Elf32_Shdr, sh_flags), offsetof(Elf32_Shdr, sh_addr),
+ offsetof(Elf32_Shdr, sh_offset), offsetof(Elf32_Shdr, sh_size),
+ offsetof(Elf32_Shdr, sh_link), offsetof(Elf32_Shdr, sh_info),
+ offsetof(Elf32_Shdr, sh_addralign), offsetof(Elf32_Shdr, sh_entsize),
+
+ offsetof(Elf32_Sym, st_name), offsetof(Elf32_Sym, st_value),
+ offsetof(Elf32_Sym, st_size), offsetof(Elf32_Sym, st_info),
+ offsetof(Elf32_Sym, st_shndx),
+
+ offsetof(Elf32_Rel, r_offset), offsetof(Elf32_Rel, r_info),
+
+ offsetof(Elf32_Rela, r_offset), offsetof(Elf32_Rela, r_info),
+ offsetof(Elf32_Rela, r_addend)
+};
+
+static int elf64_offsets[] = {
+ 0,
+
+ offsetof(Elf64_Dyn, d_tag), offsetof(Elf64_Dyn, d_un.d_ptr),
+ offsetof(Elf64_Dyn, d_un.d_val),
+
+ offsetof(Elf32_Ehdr, e_ident[EI_CLASS]),
+ offsetof(Elf32_Ehdr, e_ident[EI_DATA]),
+ offsetof(Elf32_Ehdr, e_ident[EI_OSABI]),
+ offsetof(Elf64_Ehdr, e_type), offsetof(Elf64_Ehdr, e_machine),
+ offsetof(Elf64_Ehdr, e_version), offsetof(Elf64_Ehdr, e_entry),
+ offsetof(Elf64_Ehdr, e_phoff), offsetof(Elf64_Ehdr, e_shoff),
+ offsetof(Elf64_Ehdr, e_flags), offsetof(Elf64_Ehdr, e_ehsize),
+ offsetof(Elf64_Ehdr, e_phentsize), offsetof(Elf64_Ehdr, e_phnum),
+ offsetof(Elf64_Ehdr, e_shentsize), offsetof(Elf64_Ehdr, e_shnum),
+ offsetof(Elf64_Ehdr, e_shstrndx),
+
+ offsetof(Elf_Note, n_namesz), offsetof(Elf_Note, n_descsz),
+ offsetof(Elf_Note, n_type),
+
+ offsetof(Elf64_Phdr, p_type), offsetof(Elf64_Phdr, p_offset),
+ offsetof(Elf64_Phdr, p_vaddr), offsetof(Elf64_Phdr, p_paddr),
+ offsetof(Elf64_Phdr, p_filesz), offsetof(Elf64_Phdr, p_memsz),
+ offsetof(Elf64_Phdr, p_flags), offsetof(Elf64_Phdr, p_align),
+
+ offsetof(Elf64_Shdr, sh_name), offsetof(Elf64_Shdr, sh_type),
+ offsetof(Elf64_Shdr, sh_flags), offsetof(Elf64_Shdr, sh_addr),
+ offsetof(Elf64_Shdr, sh_offset), offsetof(Elf64_Shdr, sh_size),
+ offsetof(Elf64_Shdr, sh_link), offsetof(Elf64_Shdr, sh_info),
+ offsetof(Elf64_Shdr, sh_addralign), offsetof(Elf64_Shdr, sh_entsize),
+
+ offsetof(Elf64_Sym, st_name), offsetof(Elf64_Sym, st_value),
+ offsetof(Elf64_Sym, st_size), offsetof(Elf64_Sym, st_info),
+ offsetof(Elf64_Sym, st_shndx),
+
+ offsetof(Elf64_Rel, r_offset), offsetof(Elf64_Rel, r_info),
+
+ offsetof(Elf64_Rela, r_offset), offsetof(Elf64_Rela, r_info),
+ offsetof(Elf64_Rela, r_addend)
+};
+
+/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
+static const char *
+d_tags(u_int64_t tag)
+{
+ static char unknown_tag[48];
+
+ switch (tag) {
+ case DT_NULL: return "DT_NULL";
+ case DT_NEEDED: return "DT_NEEDED";
+ case DT_PLTRELSZ: return "DT_PLTRELSZ";
+ case DT_PLTGOT: return "DT_PLTGOT";
+ case DT_HASH: return "DT_HASH";
+ case DT_STRTAB: return "DT_STRTAB";
+ case DT_SYMTAB: return "DT_SYMTAB";
+ case DT_RELA: return "DT_RELA";
+ case DT_RELASZ: return "DT_RELASZ";
+ case DT_RELAENT: return "DT_RELAENT";
+ case DT_STRSZ: return "DT_STRSZ";
+ case DT_SYMENT: return "DT_SYMENT";
+ case DT_INIT: return "DT_INIT";
+ case DT_FINI: return "DT_FINI";
+ case DT_SONAME: return "DT_SONAME";
+ case DT_RPATH: return "DT_RPATH";
+ case DT_SYMBOLIC: return "DT_SYMBOLIC";
+ case DT_REL: return "DT_REL";
+ case DT_RELSZ: return "DT_RELSZ";
+ case DT_RELENT: return "DT_RELENT";
+ case DT_PLTREL: return "DT_PLTREL";
+ case DT_DEBUG: return "DT_DEBUG";
+ case DT_TEXTREL: return "DT_TEXTREL";
+ case DT_JMPREL: return "DT_JMPREL";
+ case DT_BIND_NOW: return "DT_BIND_NOW";
+ case DT_INIT_ARRAY: return "DT_INIT_ARRAY";
+ case DT_FINI_ARRAY: return "DT_FINI_ARRAY";
+ case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ";
+ case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ";
+ case DT_RUNPATH: return "DT_RUNPATH";
+ case DT_FLAGS: return "DT_FLAGS";
+ case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */
+ case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ";
+ /* 0x6000000D - 0x6ffff000 operating system-specific semantics */
+ case 0x6ffffdf5: return "DT_GNU_PRELINKED";
+ case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
+ case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
+ case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
+ case DT_PLTPADSZ: return "DT_PLTPADSZ";
+ case DT_MOVEENT: return "DT_MOVEENT";
+ case DT_MOVESZ: return "DT_MOVESZ";
+ case DT_FEATURE: return "DT_FEATURE";
+ case DT_POSFLAG_1: return "DT_POSFLAG_1";
+ case DT_SYMINSZ: return "DT_SYMINSZ";
+ case DT_SYMINENT : return "DT_SYMINENT (DT_VALRNGHI)";
+ case DT_ADDRRNGLO: return "DT_ADDRRNGLO";
+ case DT_GNU_HASH: return "DT_GNU_HASH";
+ case 0x6ffffef8: return "DT_GNU_CONFLICT";
+ case 0x6ffffef9: return "DT_GNU_LIBLIST";
+ case DT_CONFIG: return "DT_CONFIG";
+ case DT_DEPAUDIT: return "DT_DEPAUDIT";
+ case DT_AUDIT: return "DT_AUDIT";
+ case DT_PLTPAD: return "DT_PLTPAD";
+ case DT_MOVETAB: return "DT_MOVETAB";
+ case DT_SYMINFO : return "DT_SYMINFO (DT_ADDRRNGHI)";
+ case DT_RELACOUNT: return "DT_RELACOUNT";
+ case DT_RELCOUNT: return "DT_RELCOUNT";
+ case DT_FLAGS_1: return "DT_FLAGS_1";
+ case DT_VERDEF: return "DT_VERDEF";
+ case DT_VERDEFNUM: return "DT_VERDEFNUM";
+ case DT_VERNEED: return "DT_VERNEED";
+ case DT_VERNEEDNUM: return "DT_VERNEEDNUM";
+ case 0x6ffffff0: return "DT_GNU_VERSYM";
+ /* 0x70000000 - 0x7fffffff processor-specific semantics */
+ case 0x70000000: return "DT_IA_64_PLT_RESERVE";
+ case DT_AUXILIARY: return "DT_AUXILIARY";
+ case DT_USED: return "DT_USED";
+ case DT_FILTER: return "DT_FILTER";
+ }
+ snprintf(unknown_tag, sizeof(unknown_tag),
+ "ERROR: TAG NOT DEFINED -- tag 0x%jx", (uintmax_t)tag);
+ return (unknown_tag);
+}
+
+static const char *
+e_machines(u_int mach)
+{
+ static char machdesc[64];
+
+ switch (mach) {
+ case EM_NONE: return "EM_NONE";
+ case EM_M32: return "EM_M32";
+ case EM_SPARC: return "EM_SPARC";
+ case EM_386: return "EM_386";
+ case EM_68K: return "EM_68K";
+ case EM_88K: return "EM_88K";
+ case EM_IAMCU: return "EM_IAMCU";
+ case EM_860: return "EM_860";
+ case EM_MIPS: return "EM_MIPS";
+ case EM_PPC: return "EM_PPC";
+ case EM_PPC64: return "EM_PPC64";
+ case EM_ARM: return "EM_ARM";
+ case EM_ALPHA: return "EM_ALPHA (legacy)";
+ case EM_SPARCV9:return "EM_SPARCV9";
+ case EM_IA_64: return "EM_IA_64";
+ case EM_X86_64: return "EM_X86_64";
+ case EM_AARCH64:return "EM_AARCH64";
+ case EM_RISCV: return "EM_RISCV";
+ }
+ snprintf(machdesc, sizeof(machdesc),
+ "(unknown machine) -- type 0x%x", mach);
+ return (machdesc);
+}
+
+static const char *e_types[] = {
+ "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
+};
+
+static const char *ei_versions[] = {
+ "EV_NONE", "EV_CURRENT"
+};
+
+static const char *ei_classes[] = {
+ "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
+};
+
+static const char *ei_data[] = {
+ "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
+};
+
+static const char *ei_abis[256] = {
+ "ELFOSABI_NONE", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
+ "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS", "ELFOSABI_AIX",
+ "ELFOSABI_IRIX", "ELFOSABI_FREEBSD", "ELFOSABI_TRU64",
+ "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD",
+ [255] = "ELFOSABI_STANDALONE"
+};
+
+static const char *p_types[] = {
+ "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
+ "PT_SHLIB", "PT_PHDR", "PT_TLS"
+};
+
+static const char *p_flags[] = {
+ "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
+ "PF_X|PF_W|PF_R"
+};
+
+#define NT_ELEM(x) [x] = #x,
+static const char *nt_types[] = {
+ "",
+ NT_ELEM(NT_FREEBSD_ABI_TAG)
+ NT_ELEM(NT_FREEBSD_NOINIT_TAG)
+ NT_ELEM(NT_FREEBSD_ARCH_TAG)
+ NT_ELEM(NT_FREEBSD_FEATURE_CTL)
+};
+
+/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
+static const char *
+sh_types(uint64_t machine, uint64_t sht) {
+ static char unknown_buf[64];
+
+ if (sht < 0x60000000) {
+ switch (sht) {
+ case SHT_NULL: return "SHT_NULL";
+ case SHT_PROGBITS: return "SHT_PROGBITS";
+ case SHT_SYMTAB: return "SHT_SYMTAB";
+ case SHT_STRTAB: return "SHT_STRTAB";
+ case SHT_RELA: return "SHT_RELA";
+ case SHT_HASH: return "SHT_HASH";
+ case SHT_DYNAMIC: return "SHT_DYNAMIC";
+ case SHT_NOTE: return "SHT_NOTE";
+ case SHT_NOBITS: return "SHT_NOBITS";
+ case SHT_REL: return "SHT_REL";
+ case SHT_SHLIB: return "SHT_SHLIB";
+ case SHT_DYNSYM: return "SHT_DYNSYM";
+ case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY";
+ case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY";
+ case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY";
+ case SHT_GROUP: return "SHT_GROUP";
+ case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX";
+ }
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "ERROR: SHT %ju NOT DEFINED", (uintmax_t)sht);
+ return (unknown_buf);
+ } else if (sht < 0x70000000) {
+ /* 0x60000000-0x6fffffff operating system-specific semantics */
+ switch (sht) {
+ case 0x6ffffff0: return "XXX:VERSYM";
+ case SHT_SUNW_dof: return "SHT_SUNW_dof";
+ case SHT_GNU_HASH: return "SHT_GNU_HASH";
+ case 0x6ffffff7: return "SHT_GNU_LIBLIST";
+ case 0x6ffffffc: return "XXX:VERDEF";
+ case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef";
+ case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed";
+ case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym";
+ }
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "ERROR: OS-SPECIFIC SHT 0x%jx NOT DEFINED",
+ (uintmax_t)sht);
+ return (unknown_buf);
+ } else if (sht < 0x80000000) {
+ /* 0x70000000-0x7fffffff processor-specific semantics */
+ switch (machine) {
+ case EM_ARM:
+ switch (sht) {
+ case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";
+ case SHT_ARM_PREEMPTMAP:return "SHT_ARM_PREEMPTMAP";
+ case SHT_ARM_ATTRIBUTES:return "SHT_ARM_ATTRIBUTES";
+ case SHT_ARM_DEBUGOVERLAY:
+ return "SHT_ARM_DEBUGOVERLAY";
+ case SHT_ARM_OVERLAYSECTION:
+ return "SHT_ARM_OVERLAYSECTION";
+ }
+ break;
+ case EM_IA_64:
+ switch (sht) {
+ case 0x70000000: return "SHT_IA_64_EXT";
+ case 0x70000001: return "SHT_IA_64_UNWIND";
+ }
+ break;
+ case EM_MIPS:
+ switch (sht) {
+ case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
+ case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
+ case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
+ }
+ break;
+ }
+ switch (sht) {
+ case 0x7ffffffd: return "XXX:AUXILIARY";
+ case 0x7fffffff: return "XXX:FILTER";
+ }
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "ERROR: PROCESSOR-SPECIFIC SHT 0x%jx NOT DEFINED",
+ (uintmax_t)sht);
+ return (unknown_buf);
+ } else {
+ /* 0x80000000-0xffffffff application programs */
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "ERROR: SHT 0x%jx NOT DEFINED",
+ (uintmax_t)sht);
+ return (unknown_buf);
+ }
+}
+
+static const char *sh_flags[] = {
+ "", "SHF_WRITE", "SHF_ALLOC", "SHF_WRITE|SHF_ALLOC", "SHF_EXECINSTR",
+ "SHF_WRITE|SHF_EXECINSTR", "SHF_ALLOC|SHF_EXECINSTR",
+ "SHF_WRITE|SHF_ALLOC|SHF_EXECINSTR"
+};
+
+static const char *
+st_type(unsigned int mach, unsigned int type)
+{
+ static char s_type[32];
+
+ switch (type) {
+ case STT_NOTYPE: return "STT_NOTYPE";
+ case STT_OBJECT: return "STT_OBJECT";
+ case STT_FUNC: return "STT_FUNC";
+ case STT_SECTION: return "STT_SECTION";
+ case STT_FILE: return "STT_FILE";
+ case STT_COMMON: return "STT_COMMON";
+ case STT_TLS: return "STT_TLS";
+ case 13:
+ if (mach == EM_SPARCV9)
+ return "STT_SPARC_REGISTER";
+ break;
+ }
+ snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+ return (s_type);
+}
+
+static const char *st_bindings[] = {
+ "STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
+};
+
+static char *dynstr;
+static char *shstrtab;
+static char *strtab;
+static FILE *out;
+
+static u_int64_t elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member);
+static u_int64_t elf_get_quarter(Elf32_Ehdr *e, void *base,
+ elf_member_t member);
+#if 0
+static u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member);
+#endif
+static u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member);
+static u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member);
+
+static void elf_print_ehdr(Elf32_Ehdr *e, void *sh);
+static void elf_print_phdr(Elf32_Ehdr *e, void *p);
+static void elf_print_shdr(Elf32_Ehdr *e, void *sh);
+static void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str);
+static void elf_print_dynamic(Elf32_Ehdr *e, void *sh);
+static void elf_print_rel(Elf32_Ehdr *e, void *r);
+static void elf_print_rela(Elf32_Ehdr *e, void *ra);
+static void elf_print_interp(Elf32_Ehdr *e, void *p);
+static void elf_print_got(Elf32_Ehdr *e, void *sh);
+static void elf_print_hash(Elf32_Ehdr *e, void *sh);
+static void elf_print_note(Elf32_Ehdr *e, void *sh);
+
+static void usage(void) __dead2;
+
+/*
+ * Helpers for ELF files with shnum or shstrndx values that don't fit in the
+ * ELF header. If the values are too large then an escape value is used to
+ * indicate that the actual value is found in one of section 0's fields.
+ */
+static uint64_t
+elf_get_shnum(Elf32_Ehdr *e, void *sh)
+{
+ uint64_t shnum;
+
+ shnum = elf_get_quarter(e, e, E_SHNUM);
+ if (shnum == 0)
+ shnum = elf_get_word(e, (char *)sh, SH_SIZE);
+ return shnum;
+}
+
+static uint64_t
+elf_get_shstrndx(Elf32_Ehdr *e, void *sh)
+{
+ uint64_t shstrndx;
+
+ shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
+ if (shstrndx == SHN_XINDEX)
+ shstrndx = elf_get_word(e, (char *)sh, SH_LINK);
+ return shstrndx;
+}
+
+int
+main(int ac, char **av)
+{
+ cap_rights_t rights;
+ u_int64_t phoff;
+ u_int64_t shoff;
+ u_int64_t phentsize;
+ u_int64_t phnum;
+ u_int64_t shentsize;
+ u_int64_t shnum;
+ u_int64_t shstrndx;
+ u_int64_t offset;
+ u_int64_t name;
+ u_int64_t type;
+ struct stat sb;
+ u_int flags;
+ Elf32_Ehdr *e;
+ void *p;
+ void *sh;
+ void *v;
+ int fd;
+ int ch;
+ int i;
+
+ out = stdout;
+ flags = 0;
+ while ((ch = getopt(ac, av, "acdEeiGhnprsw:")) != -1)
+ switch (ch) {
+ case 'a':
+ flags = ED_ALL;
+ break;
+ case 'c':
+ flags |= ED_SHDR;
+ break;
+ case 'd':
+ flags |= ED_DYN;
+ break;
+ case 'E':
+ flags = ED_IS_ELF;
+ break;
+ case 'e':
+ flags |= ED_EHDR;
+ break;
+ case 'i':
+ flags |= ED_INTERP;
+ break;
+ case 'G':
+ flags |= ED_GOT;
+ break;
+ case 'h':
+ flags |= ED_HASH;
+ break;
+ case 'n':
+ flags |= ED_NOTE;
+ break;
+ case 'p':
+ flags |= ED_PHDR;
+ break;
+ case 'r':
+ flags |= ED_REL;
+ break;
+ case 's':
+ flags |= ED_SYMTAB;
+ break;
+ case 'w':
+ if ((out = fopen(optarg, "w")) == NULL)
+ err(1, "%s", optarg);
+ cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
+ if (caph_rights_limit(fileno(out), &rights) < 0)
+ err(1, "unable to limit rights for %s", optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ ac -= optind;
+ av += optind;
+ if (ac == 0 || flags == 0 || ((flags & ED_IS_ELF) &&
+ (ac != 1 || (flags & ~ED_IS_ELF) || out != stdout)))
+ usage();
+ if ((fd = open(*av, O_RDONLY)) < 0 ||
+ fstat(fd, &sb) < 0)
+ err(1, "%s", *av);
+ if ((size_t)sb.st_size < sizeof(Elf32_Ehdr)) {
+ if (flags & ED_IS_ELF)
+ exit(1);
+ errx(1, "not an elf file");
+ }
+ cap_rights_init(&rights, CAP_MMAP_R);
+ if (caph_rights_limit(fd, &rights) < 0)
+ err(1, "unable to limit rights for %s", *av);
+ cap_rights_init(&rights);
+ if (caph_rights_limit(STDIN_FILENO, &rights) < 0 ||
+ caph_limit_stdout() < 0 || caph_limit_stderr() < 0) {
+ err(1, "unable to limit rights for stdio");
+ }
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+ e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (e == MAP_FAILED)
+ err(1, NULL);
+ if (!IS_ELF(*e)) {
+ if (flags & ED_IS_ELF)
+ exit(1);
+ errx(1, "not an elf file");
+ } else if (flags & ED_IS_ELF)
+ exit (0);
+ phoff = elf_get_off(e, e, E_PHOFF);
+ shoff = elf_get_off(e, e, E_SHOFF);
+ phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
+ phnum = elf_get_quarter(e, e, E_PHNUM);
+ shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
+ p = (char *)e + phoff;
+ if (shoff > 0) {
+ sh = (char *)e + shoff;
+ shnum = elf_get_shnum(e, sh);
+ shstrndx = elf_get_shstrndx(e, sh);
+ offset = elf_get_off(e, (char *)sh + shstrndx * shentsize,
+ SH_OFFSET);
+ shstrtab = (char *)e + offset;
+ } else {
+ sh = NULL;
+ shnum = 0;
+ shstrndx = 0;
+ shstrtab = NULL;
+ }
+ for (i = 0; (u_int64_t)i < shnum; i++) {
+ name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
+ offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
+ if (strcmp(shstrtab + name, ".strtab") == 0)
+ strtab = (char *)e + offset;
+ if (strcmp(shstrtab + name, ".dynstr") == 0)
+ dynstr = (char *)e + offset;
+ }
+ if (flags & ED_EHDR)
+ elf_print_ehdr(e, sh);
+ if (flags & ED_PHDR)
+ elf_print_phdr(e, p);
+ if (flags & ED_SHDR)
+ elf_print_shdr(e, sh);
+ for (i = 0; (u_int64_t)i < phnum; i++) {
+ v = (char *)p + i * phentsize;
+ type = elf_get_word(e, v, P_TYPE);
+ switch (type) {
+ case PT_INTERP:
+ if (flags & ED_INTERP)
+ elf_print_interp(e, v);
+ break;
+ case PT_NULL:
+ case PT_LOAD:
+ case PT_DYNAMIC:
+ case PT_NOTE:
+ case PT_SHLIB:
+ case PT_PHDR:
+ break;
+ }
+ }
+ for (i = 0; (u_int64_t)i < shnum; i++) {
+ v = (char *)sh + i * shentsize;
+ type = elf_get_word(e, v, SH_TYPE);
+ switch (type) {
+ case SHT_SYMTAB:
+ if (flags & ED_SYMTAB)
+ elf_print_symtab(e, v, strtab);
+ break;
+ case SHT_DYNAMIC:
+ if (flags & ED_DYN)
+ elf_print_dynamic(e, v);
+ break;
+ case SHT_RELA:
+ if (flags & ED_REL)
+ elf_print_rela(e, v);
+ break;
+ case SHT_REL:
+ if (flags & ED_REL)
+ elf_print_rel(e, v);
+ break;
+ case SHT_NOTE:
+ name = elf_get_word(e, v, SH_NAME);
+ if (flags & ED_NOTE &&
+ strcmp(shstrtab + name, ".note.tag") == 0)
+ elf_print_note(e, v);
+ break;
+ case SHT_DYNSYM:
+ if (flags & ED_SYMTAB)
+ elf_print_symtab(e, v, dynstr);
+ break;
+ case SHT_PROGBITS:
+ name = elf_get_word(e, v, SH_NAME);
+ if (flags & ED_GOT &&
+ strcmp(shstrtab + name, ".got") == 0)
+ elf_print_got(e, v);
+ break;
+ case SHT_HASH:
+ if (flags & ED_HASH)
+ elf_print_hash(e, v);
+ break;
+ case SHT_NULL:
+ case SHT_STRTAB:
+ case SHT_NOBITS:
+ case SHT_SHLIB:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void
+elf_print_ehdr(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t class;
+ u_int64_t data;
+ u_int64_t osabi;
+ u_int64_t type;
+ u_int64_t machine;
+ u_int64_t version;
+ u_int64_t entry;
+ u_int64_t phoff;
+ u_int64_t shoff;
+ u_int64_t flags;
+ u_int64_t ehsize;
+ u_int64_t phentsize;
+ u_int64_t phnum;
+ u_int64_t shentsize;
+ u_int64_t shnum;
+ u_int64_t shstrndx;
+
+ class = elf_get_byte(e, e, E_CLASS);
+ data = elf_get_byte(e, e, E_DATA);
+ osabi = elf_get_byte(e, e, E_OSABI);
+ type = elf_get_quarter(e, e, E_TYPE);
+ machine = elf_get_quarter(e, e, E_MACHINE);
+ version = elf_get_word(e, e, E_VERSION);
+ entry = elf_get_addr(e, e, E_ENTRY);
+ phoff = elf_get_off(e, e, E_PHOFF);
+ shoff = elf_get_off(e, e, E_SHOFF);
+ flags = elf_get_word(e, e, E_FLAGS);
+ ehsize = elf_get_quarter(e, e, E_EHSIZE);
+ phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
+ phnum = elf_get_quarter(e, e, E_PHNUM);
+ shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
+ fprintf(out, "\nelf header:\n");
+ fprintf(out, "\n");
+ fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
+ ei_abis[osabi]);
+ fprintf(out, "\te_type: %s\n", e_types[type]);
+ fprintf(out, "\te_machine: %s\n", e_machines(machine));
+ fprintf(out, "\te_version: %s\n", ei_versions[version]);
+ fprintf(out, "\te_entry: %#jx\n", (intmax_t)entry);
+ fprintf(out, "\te_phoff: %jd\n", (intmax_t)phoff);
+ fprintf(out, "\te_shoff: %jd\n", (intmax_t)shoff);
+ fprintf(out, "\te_flags: %jd\n", (intmax_t)flags);
+ fprintf(out, "\te_ehsize: %jd\n", (intmax_t)ehsize);
+ fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize);
+ fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum);
+ fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize);
+ if (sh != NULL) {
+ shnum = elf_get_shnum(e, sh);
+ shstrndx = elf_get_shstrndx(e, sh);
+ fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
+ fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
+ }
+}
+
+static void
+elf_print_phdr(Elf32_Ehdr *e, void *p)
+{
+ u_int64_t phentsize;
+ u_int64_t phnum;
+ u_int64_t type;
+ u_int64_t offset;
+ u_int64_t vaddr;
+ u_int64_t paddr;
+ u_int64_t filesz;
+ u_int64_t memsz;
+ u_int64_t flags;
+ u_int64_t align;
+ void *v;
+ int i;
+
+ phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
+ phnum = elf_get_quarter(e, e, E_PHNUM);
+ fprintf(out, "\nprogram header:\n");
+ for (i = 0; (u_int64_t)i < phnum; i++) {
+ v = (char *)p + i * phentsize;
+ type = elf_get_word(e, v, P_TYPE);
+ offset = elf_get_off(e, v, P_OFFSET);
+ vaddr = elf_get_addr(e, v, P_VADDR);
+ paddr = elf_get_addr(e, v, P_PADDR);
+ filesz = elf_get_size(e, v, P_FILESZ);
+ memsz = elf_get_size(e, v, P_MEMSZ);
+ flags = elf_get_word(e, v, P_FLAGS);
+ align = elf_get_size(e, v, P_ALIGN);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\tp_type: %s\n", p_types[type & 0x7]);
+ fprintf(out, "\tp_offset: %jd\n", (intmax_t)offset);
+ fprintf(out, "\tp_vaddr: %#jx\n", (intmax_t)vaddr);
+ fprintf(out, "\tp_paddr: %#jx\n", (intmax_t)paddr);
+ fprintf(out, "\tp_filesz: %jd\n", (intmax_t)filesz);
+ fprintf(out, "\tp_memsz: %jd\n", (intmax_t)memsz);
+ fprintf(out, "\tp_flags: %s\n", p_flags[flags]);
+ fprintf(out, "\tp_align: %jd\n", (intmax_t)align);
+ }
+}
+
+static void
+elf_print_shdr(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t shentsize;
+ u_int64_t shnum;
+ u_int64_t name;
+ u_int64_t type;
+ u_int64_t flags;
+ u_int64_t addr;
+ u_int64_t offset;
+ u_int64_t size;
+ u_int64_t shlink;
+ u_int64_t info;
+ u_int64_t addralign;
+ u_int64_t entsize;
+ u_int64_t machine;
+ void *v;
+ int i;
+
+ if (sh == NULL) {
+ fprintf(out, "\nNo section headers\n");
+ return;
+ }
+
+ machine = elf_get_quarter(e, e, E_MACHINE);
+ shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
+ shnum = elf_get_shnum(e, sh);
+ fprintf(out, "\nsection header:\n");
+ for (i = 0; (u_int64_t)i < shnum; i++) {
+ v = (char *)sh + i * shentsize;
+ name = elf_get_word(e, v, SH_NAME);
+ type = elf_get_word(e, v, SH_TYPE);
+ flags = elf_get_word(e, v, SH_FLAGS);
+ addr = elf_get_addr(e, v, SH_ADDR);
+ offset = elf_get_off(e, v, SH_OFFSET);
+ size = elf_get_size(e, v, SH_SIZE);
+ shlink = elf_get_word(e, v, SH_LINK);
+ info = elf_get_word(e, v, SH_INFO);
+ addralign = elf_get_size(e, v, SH_ADDRALIGN);
+ entsize = elf_get_size(e, v, SH_ENTSIZE);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\tsh_name: %s\n", shstrtab + name);
+ fprintf(out, "\tsh_type: %s\n", sh_types(machine, type));
+ fprintf(out, "\tsh_flags: %s\n", sh_flags[flags & 0x7]);
+ fprintf(out, "\tsh_addr: %#jx\n", addr);
+ fprintf(out, "\tsh_offset: %jd\n", (intmax_t)offset);
+ fprintf(out, "\tsh_size: %jd\n", (intmax_t)size);
+ fprintf(out, "\tsh_link: %jd\n", (intmax_t)shlink);
+ fprintf(out, "\tsh_info: %jd\n", (intmax_t)info);
+ fprintf(out, "\tsh_addralign: %jd\n", (intmax_t)addralign);
+ fprintf(out, "\tsh_entsize: %jd\n", (intmax_t)entsize);
+ }
+}
+
+static void
+elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str)
+{
+ u_int64_t machine;
+ u_int64_t offset;
+ u_int64_t entsize;
+ u_int64_t size;
+ u_int64_t name;
+ u_int64_t value;
+ u_int64_t info;
+ u_int64_t shndx;
+ void *st;
+ int len;
+ int i;
+
+ machine = elf_get_quarter(e, e, E_MACHINE);
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ entsize = elf_get_size(e, sh, SH_ENTSIZE);
+ size = elf_get_size(e, sh, SH_SIZE);
+ name = elf_get_word(e, sh, SH_NAME);
+ len = size / entsize;
+ fprintf(out, "\nsymbol table (%s):\n", shstrtab + name);
+ for (i = 0; i < len; i++) {
+ st = (char *)e + offset + i * entsize;
+ name = elf_get_word(e, st, ST_NAME);
+ value = elf_get_addr(e, st, ST_VALUE);
+ size = elf_get_size(e, st, ST_SIZE);
+ info = elf_get_byte(e, st, ST_INFO);
+ shndx = elf_get_quarter(e, st, ST_SHNDX);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\tst_name: %s\n", str + name);
+ fprintf(out, "\tst_value: %#jx\n", value);
+ fprintf(out, "\tst_size: %jd\n", (intmax_t)size);
+ fprintf(out, "\tst_info: %s %s\n",
+ st_type(machine, ELF32_ST_TYPE(info)),
+ st_bindings[ELF32_ST_BIND(info)]);
+ fprintf(out, "\tst_shndx: %jd\n", (intmax_t)shndx);
+ }
+}
+
+static void
+elf_print_dynamic(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t offset;
+ u_int64_t entsize;
+ u_int64_t size;
+ int64_t tag;
+ u_int64_t ptr;
+ u_int64_t val;
+ void *d;
+ int i;
+
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ entsize = elf_get_size(e, sh, SH_ENTSIZE);
+ size = elf_get_size(e, sh, SH_SIZE);
+ fprintf(out, "\ndynamic:\n");
+ for (i = 0; (u_int64_t)i < size / entsize; i++) {
+ d = (char *)e + offset + i * entsize;
+ tag = elf_get_size(e, d, D_TAG);
+ ptr = elf_get_size(e, d, D_PTR);
+ val = elf_get_addr(e, d, D_VAL);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\td_tag: %s\n", d_tags(tag));
+ switch (tag) {
+ case DT_NEEDED:
+ case DT_SONAME:
+ case DT_RPATH:
+ fprintf(out, "\td_val: %s\n", dynstr + val);
+ break;
+ case DT_PLTRELSZ:
+ case DT_RELA:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_RELSZ:
+ case DT_RELENT:
+ case DT_PLTREL:
+ fprintf(out, "\td_val: %jd\n", (intmax_t)val);
+ break;
+ case DT_PLTGOT:
+ case DT_HASH:
+ case DT_STRTAB:
+ case DT_SYMTAB:
+ case DT_INIT:
+ case DT_FINI:
+ case DT_REL:
+ case DT_JMPREL:
+ fprintf(out, "\td_ptr: %#jx\n", ptr);
+ break;
+ case DT_NULL:
+ case DT_SYMBOLIC:
+ case DT_DEBUG:
+ case DT_TEXTREL:
+ break;
+ }
+ }
+}
+
+static void
+elf_print_rela(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t offset;
+ u_int64_t entsize;
+ u_int64_t size;
+ u_int64_t name;
+ u_int64_t info;
+ int64_t addend;
+ void *ra;
+ void *v;
+ int i;
+
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ entsize = elf_get_size(e, sh, SH_ENTSIZE);
+ size = elf_get_size(e, sh, SH_SIZE);
+ name = elf_get_word(e, sh, SH_NAME);
+ v = (char *)e + offset;
+ fprintf(out, "\nrelocation with addend (%s):\n", shstrtab + name);
+ for (i = 0; (u_int64_t)i < size / entsize; i++) {
+ ra = (char *)v + i * entsize;
+ offset = elf_get_addr(e, ra, RA_OFFSET);
+ info = elf_get_word(e, ra, RA_INFO);
+ addend = elf_get_off(e, ra, RA_ADDEND);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\tr_offset: %#jx\n", offset);
+ fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
+ fprintf(out, "\tr_addend: %jd\n", (intmax_t)addend);
+ }
+}
+
+static void
+elf_print_rel(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t offset;
+ u_int64_t entsize;
+ u_int64_t size;
+ u_int64_t name;
+ u_int64_t info;
+ void *r;
+ void *v;
+ int i;
+
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ entsize = elf_get_size(e, sh, SH_ENTSIZE);
+ size = elf_get_size(e, sh, SH_SIZE);
+ name = elf_get_word(e, sh, SH_NAME);
+ v = (char *)e + offset;
+ fprintf(out, "\nrelocation (%s):\n", shstrtab + name);
+ for (i = 0; (u_int64_t)i < size / entsize; i++) {
+ r = (char *)v + i * entsize;
+ offset = elf_get_addr(e, r, R_OFFSET);
+ info = elf_get_word(e, r, R_INFO);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\tr_offset: %#jx\n", offset);
+ fprintf(out, "\tr_info: %jd\n", (intmax_t)info);
+ }
+}
+
+static void
+elf_print_interp(Elf32_Ehdr *e, void *p)
+{
+ u_int64_t offset;
+ char *s;
+
+ offset = elf_get_off(e, p, P_OFFSET);
+ s = (char *)e + offset;
+ fprintf(out, "\ninterp:\n");
+ fprintf(out, "\t%s\n", s);
+}
+
+static void
+elf_print_got(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t offset;
+ u_int64_t addralign;
+ u_int64_t size;
+ u_int64_t addr;
+ void *v;
+ int i;
+
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ addralign = elf_get_size(e, sh, SH_ADDRALIGN);
+ size = elf_get_size(e, sh, SH_SIZE);
+ v = (char *)e + offset;
+ fprintf(out, "\nglobal offset table:\n");
+ for (i = 0; (u_int64_t)i < size / addralign; i++) {
+ addr = elf_get_addr(e, (char *)v + i * addralign, 0);
+ fprintf(out, "\n");
+ fprintf(out, "entry: %d\n", i);
+ fprintf(out, "\t%#jx\n", addr);
+ }
+}
+
+static void
+elf_print_hash(Elf32_Ehdr *e __unused, void *sh __unused)
+{
+}
+
+static void
+elf_print_note(Elf32_Ehdr *e, void *sh)
+{
+ u_int64_t offset;
+ u_int64_t size;
+ u_int64_t name;
+ u_int32_t namesz;
+ u_int32_t descsz;
+ u_int32_t desc;
+ u_int32_t type;
+ char *n, *s;
+ const char *nt_type;
+
+ offset = elf_get_off(e, sh, SH_OFFSET);
+ size = elf_get_size(e, sh, SH_SIZE);
+ name = elf_get_word(e, sh, SH_NAME);
+ n = (char *)e + offset;
+ fprintf(out, "\nnote (%s):\n", shstrtab + name);
+ while (n < ((char *)e + offset + size)) {
+ namesz = elf_get_word(e, n, N_NAMESZ);
+ descsz = elf_get_word(e, n, N_DESCSZ);
+ type = elf_get_word(e, n, N_TYPE);
+ if (type < nitems(nt_types) && nt_types[type] != NULL)
+ nt_type = nt_types[type];
+ else
+ nt_type = "Unknown type";
+ s = n + sizeof(Elf_Note);
+ desc = elf_get_word(e, n + sizeof(Elf_Note) + namesz, 0);
+ fprintf(out, "\t%s %d (%s)\n", s, desc, nt_type);
+ n += sizeof(Elf_Note) + namesz + descsz;
+ }
+}
+
+static u_int64_t
+elf_get_byte(Elf32_Ehdr *e, void *base, elf_member_t member)
+{
+ u_int64_t val;
+
+ val = 0;
+ switch (e->e_ident[EI_CLASS]) {
+ case ELFCLASS32:
+ val = ((uint8_t *)base)[elf32_offsets[member]];
+ break;
+ case ELFCLASS64:
+ val = ((uint8_t *)base)[elf64_offsets[member]];
+ break;
+ case ELFCLASSNONE:
+ errx(1, "invalid class");
+ }
+
+ return val;
+}
+
+static u_int64_t
+elf_get_quarter(Elf32_Ehdr *e, void *base, elf_member_t member)
+{
+ u_int64_t val;
+
+ val = 0;
+ switch (e->e_ident[EI_CLASS]) {
+ case ELFCLASS32:
+ base = (char *)base + elf32_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be16dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le16dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASS64:
+ base = (char *)base + elf64_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be16dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le16dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASSNONE:
+ errx(1, "invalid class");
+ }
+
+ return val;
+}
+
+#if 0
+static u_int64_t
+elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member)
+{
+ u_int64_t val;
+
+ val = 0;
+ switch (e->e_ident[EI_CLASS]) {
+ case ELFCLASS32:
+ base = (char *)base + elf32_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be16dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le16dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASS64:
+ base = (char *)base + elf64_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be32dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le32dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASSNONE:
+ errx(1, "invalid class");
+ }
+
+ return val;
+}
+#endif
+
+static u_int64_t
+elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member)
+{
+ u_int64_t val;
+
+ val = 0;
+ switch (e->e_ident[EI_CLASS]) {
+ case ELFCLASS32:
+ base = (char *)base + elf32_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be32dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le32dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASS64:
+ base = (char *)base + elf64_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be32dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le32dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASSNONE:
+ errx(1, "invalid class");
+ }
+
+ return val;
+}
+
+static u_int64_t
+elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member)
+{
+ u_int64_t val;
+
+ val = 0;
+ switch (e->e_ident[EI_CLASS]) {
+ case ELFCLASS32:
+ base = (char *)base + elf32_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be32dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le32dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASS64:
+ base = (char *)base + elf64_offsets[member];
+ switch (e->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ val = be64dec(base);
+ break;
+ case ELFDATA2LSB:
+ val = le64dec(base);
+ break;
+ case ELFDATANONE:
+ errx(1, "invalid data format");
+ }
+ break;
+ case ELFCLASSNONE:
+ errx(1, "invalid class");
+ }
+
+ return val;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: elfdump -a | -E | -cdeGhinprs [-w file] file\n");
+ exit(1);
+}
diff --git a/usr.bin/enigma/Makefile b/usr.bin/enigma/Makefile
new file mode 100644
index 000000000000..d3625d18354c
--- /dev/null
+++ b/usr.bin/enigma/Makefile
@@ -0,0 +1,8 @@
+PROG= enigma
+
+LINKS= ${BINDIR}/enigma ${BINDIR}/crypt
+MLINKS= enigma.1 crypt.1
+
+LIBADD= crypt
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/enigma/Makefile.depend b/usr.bin/enigma/Makefile.depend
new file mode 100644
index 000000000000..1c3b2f9abb62
--- /dev/null
+++ b/usr.bin/enigma/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libcrypt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/enigma/enigma.1 b/usr.bin/enigma/enigma.1
new file mode 100644
index 000000000000..db62808d5871
--- /dev/null
+++ b/usr.bin/enigma/enigma.1
@@ -0,0 +1,122 @@
+.\"
+.\" enigma (aka. crypt) man page written by Joerg Wunsch.
+.\"
+.\" Since enigma itself is distributed in the Public Domain, this file
+.\" is also.
+.\" "
+.Dd May 8, 2018
+.Dt ENIGMA 1
+.Os
+.Sh NAME
+.Nm enigma ,
+.Nm crypt
+.Nd very simple file encryption
+.Sh SYNOPSIS
+.Nm
+.Op Fl s
+.Op Fl k
+.Op Ar password
+.Nm crypt
+.Op Fl s
+.Op Fl k
+.Op Ar password
+.Sh DESCRIPTION
+The
+.Nm
+utility, also known as
+.Nm crypt
+is a
+.Em very
+simple encryption program, working on a
+.Dq secret-key
+basis.
+It operates as a filter, i.e.,
+it encrypts or decrypts a
+stream of data from standard input, and writes the result to standard
+output.
+Since its operation is fully symmetrical, feeding the encrypted data
+stream again through the engine (using the same secret key) will
+decrypt it.
+.Pp
+There are several ways to provide the secret key to the program.
+By
+default, the program prompts the user on the controlling terminal for
+the key, using
+.Xr getpass 3 .
+This is the only safe way of providing it.
+.Pp
+Alternatively, the key can be provided as the sole command-line
+argument
+.Ar password
+when starting the program.
+Obviously, this way the key can easily be
+spotted by other users running
+.Xr ps 1 .
+As yet another alternative,
+.Nm
+can be given the option
+.Fl k ,
+and it will take the key from the environment variable
+.Ev CrYpTkEy .
+While this at a first glance seems to be more secure than the previous
+option, it actually is not since environment variables can also be
+examined with
+.Xr ps 1 .
+Thus this option is mainly provided for compatibility with other
+implementations of
+.Nm .
+.Pp
+When specifying the option
+.Fl s ,
+.Nm
+modifies the encryption engine in a way that is supposed to make it a
+little more secure, but incompatible with other implementations.
+.Pp
+.Ss Warning
+The cryptographic value of
+.Nm
+is rather small.
+This program is only provided here for compatibility
+with other operating systems that also provide an implementation
+(usually called
+.Xr crypt 1
+there).
+For real encryption, refer to
+.Xr openssl 1 ,
+or
+.Xr gpg 1 Pq Pa ports/security/gnupg1 .
+.Sh ENVIRONMENT
+.Bl -tag -offset indent -width ".Ev CrYpTkEy"
+.It Ev CrYpTkEy
+used to obtain the secret key when option
+.Fl k
+has been given
+.El
+.Sh EXAMPLES
+.Bd -literal -offset indent
+man enigma | enigma > encrypted
+Enter key: (XXX \(em key not echoed)
+.Ed
+.Pp
+This will create an encrypted form of this man page, and store it in
+the file
+.Pa encrypted .
+.Bd -literal -offset indent
+enigma XXX < encrypted
+.Ed
+.Pp
+This displays the previously created file on the terminal.
+.Sh SEE ALSO
+.Xr gpg 1 Pq Pa ports/security/gnupg1 ,
+.Xr openssl 1 ,
+.Xr ps 1 ,
+.Xr getpass 3
+.Sh HISTORY
+Implementations of
+.Nm crypt
+are very common among
+.Ux
+operating systems.
+This implementation has been taken from the
+.Em Cryptbreakers Workbench
+which is in the public domain.
diff --git a/usr.bin/enigma/enigma.c b/usr.bin/enigma/enigma.c
new file mode 100644
index 000000000000..b985163476c4
--- /dev/null
+++ b/usr.bin/enigma/enigma.c
@@ -0,0 +1,154 @@
+/*-
+ * "enigma.c" is in file cbw.tar from
+ * anonymous FTP host watmsg.waterloo.edu: pub/crypt/cbw.tar.Z
+ *
+ * A one-rotor machine designed along the lines of Enigma
+ * but considerably trivialized.
+ *
+ * A public-domain replacement for the UNIX "crypt" command.
+ *
+ * Upgraded to function properly on 64-bit machines.
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MINUSKVAR "CrYpTkEy"
+
+#define ROTORSZ 256
+#define MASK 0377
+static char t1[ROTORSZ];
+static char t2[ROTORSZ];
+static char t3[ROTORSZ];
+static char deck[ROTORSZ];
+static char buf[13];
+
+static void shuffle(char *);
+static void setup(char *);
+
+static void
+setup(char *pw)
+{
+ int ic, i, k, temp;
+ char salt[3];
+ unsigned rnd;
+ int32_t seed;
+ char *cryptpw;
+
+ if (crypt_set_format("des") == 0) {
+ fprintf(stderr, "crypt_set_format(\"des\") failed.\n");
+ exit(1);
+ }
+
+ strlcpy(salt, pw, sizeof(salt));
+ cryptpw = crypt(pw, salt);
+ if (cryptpw == NULL) {
+ fprintf(stderr, "crypt(3) failure\n");
+ exit(1);
+ }
+ memcpy(buf, cryptpw, sizeof(buf));
+ seed = 123;
+ for (i=0; i<13; i++)
+ seed = seed*buf[i] + i;
+ for(i=0;i<ROTORSZ;i++) {
+ t1[i] = i;
+ deck[i] = i;
+ }
+ for(i=0;i<ROTORSZ;i++) {
+ seed = 5*seed + buf[i%13];
+ rnd = seed % 65521;
+ k = ROTORSZ-1 - i;
+ ic = (rnd&MASK)%(k+1);
+ rnd >>= 8;
+ temp = t1[k];
+ t1[k] = t1[ic];
+ t1[ic] = temp;
+ if(t3[k]!=0) continue;
+ ic = (rnd&MASK) % k;
+ while(t3[ic]!=0) ic = (ic+1) % k;
+ t3[k] = ic;
+ t3[ic] = k;
+ }
+ for(i=0;i<ROTORSZ;i++)
+ t2[t1[i]&MASK] = i;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i, n1, n2, nr1, nr2;
+ int secureflg = 0, kflag = 0;
+ char *cp;
+
+ if (argc > 1 && argv[1][0] == '-') {
+ if (argv[1][1] == 's') {
+ argc--;
+ argv++;
+ secureflg = 1;
+ } else if (argv[1][1] == 'k') {
+ argc--;
+ argv++;
+ kflag = 1;
+ }
+ }
+ if (kflag) {
+ if ((cp = getenv(MINUSKVAR)) == NULL) {
+ fprintf(stderr, "%s not set\n", MINUSKVAR);
+ exit(1);
+ }
+ setup(cp);
+ } else if (argc != 2) {
+ setup(getpass("Enter key:"));
+ }
+ else
+ setup(argv[1]);
+ n1 = 0;
+ n2 = 0;
+ nr2 = 0;
+
+ while((i=getchar()) != -1) {
+ if (secureflg) {
+ nr1 = deck[n1]&MASK;
+ nr2 = deck[nr1]&MASK;
+ } else {
+ nr1 = n1;
+ }
+ i = t2[(t3[(t1[(i+nr1)&MASK]+nr2)&MASK]-nr2)&MASK]-nr1;
+ putchar(i);
+ n1++;
+ if(n1==ROTORSZ) {
+ n1 = 0;
+ n2++;
+ if(n2==ROTORSZ) n2 = 0;
+ if (secureflg) {
+ shuffle(deck);
+ } else {
+ nr2 = n2;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void
+shuffle(char deckary[])
+{
+ int i, ic, k, temp;
+ unsigned rnd;
+ static int32_t seed = 123;
+
+ for(i=0;i<ROTORSZ;i++) {
+ seed = 5*seed + buf[i%13];
+ rnd = seed % 65521;
+ k = ROTORSZ-1 - i;
+ ic = (rnd&MASK)%(k+1);
+ temp = deckary[k];
+ deckary[k] = deckary[ic];
+ deckary[ic] = temp;
+ }
+}
diff --git a/usr.bin/env/Makefile b/usr.bin/env/Makefile
new file mode 100644
index 000000000000..f284770af5bb
--- /dev/null
+++ b/usr.bin/env/Makefile
@@ -0,0 +1,12 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+PROG= env
+SRCS= env.c envopts.c
+
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/env/Makefile.depend b/usr.bin/env/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/env/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/env/env.1 b/usr.bin/env/env.1
new file mode 100644
index 000000000000..bdf920eabb42
--- /dev/null
+++ b/usr.bin/env/env.1
@@ -0,0 +1,549 @@
+.\" Copyright (c) 1980, 1990, 1993
+.\" The Regents of the University of California. 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 FreeBSD: src/usr.bin/printenv/printenv.1,v 1.17 2002/11/26 17:33:35 ru Exp
+.\"
+.Dd October 8, 2024
+.Dt ENV 1
+.Os
+.Sh NAME
+.Nm env
+.Nd set environment and execute command, or print environment
+.Sh SYNOPSIS
+.Nm
+.Op Fl 0iv
+.Op Fl L Ns | Ns Fl U Ar user Ns Op / Ns Ar class
+.Op Fl u Ar name
+.Op Ar name Ns = Ns Ar value ...
+.Nm
+.Op Fl iv
+.Op Fl C Ar altwd
+.Op Fl L Ns | Ns Fl U Ar user Ns Op / Ns Ar class
+.Op Fl P Ar altpath
+.Op Fl S Ar string
+.Op Fl u Ar name
+.Op Ar name Ns = Ns Ar value ...
+.Ar utility Op Ar argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility executes another
+.Ar utility
+after modifying the environment as
+specified on the command line.
+Each
+.Ar name Ns = Ns Ar value
+option specifies the setting of an environment variable,
+.Ar name ,
+with a value of
+.Ar value .
+All such environment variables are set before the
+.Ar utility
+is executed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl 0
+End each output line with NUL, not newline.
+.It Fl i
+Execute the
+.Ar utility
+with only those environment variables specified by
+.Ar name Ns = Ns Ar value
+options.
+The environment inherited
+by
+.Nm
+is ignored completely.
+.\" -C
+.It Fl C Ar altwd
+Change to the specified alternate working directory before executing
+the specified
+.Ar utility
+program.
+.\" -L | -U
+.It Fl L | Fl U Ar user Ns Op / Ns Ar class
+Add the environment variable definitions from
+.Xr login.conf 5
+for the specified user and login class to the environment, after
+processing any
+.Fl i
+or
+.Fl u
+options, but before processing any
+.Ar name Ns = Ns Ar value
+options.
+If
+.Fl L
+is used, only the system-wide
+.Pa /etc/login.conf.db
+file is read; if
+.Fl U
+is used, then the specified user's
+.Pa ~/.login_conf
+is read as well.
+The user may be specified by name or by uid.
+If a username of
+.Sq Li \&-
+is given, then no user lookup will be done, the login class will default to
+.Sq Li default
+if not explicitly given, and no substitutions will be done on the values.
+.\" -P
+.It Fl P Ar altpath
+Search the set of directories as specified by
+.Ar altpath
+to locate the specified
+.Ar utility
+program, instead of using the value of the
+.Ev PATH
+environment variable.
+.\" -S
+.It Fl S Ar string
+Split apart the given
+.Ar string
+into multiple strings, and process each of the resulting strings
+as separate arguments to the
+.Nm
+utility.
+The
+.Fl S
+option recognizes some special character escape sequences and
+also supports environment-variable substitution, as described
+below.
+.\" -u
+.It Fl u Ar name
+If the environment variable
+.Ar name
+is in the environment, then remove it before processing the
+remaining options.
+This is similar to the
+.Ic unset
+command in
+.Xr sh 1 .
+The value for
+.Ar name
+must not include the
+.Ql =
+character.
+.\" -v
+.It Fl v
+Print verbose information for each step of processing done by the
+.Nm
+utility.
+Additional information will be printed if
+.Fl v
+is specified multiple times.
+.El
+.Pp
+The above options are only recognized when they are specified
+before any
+.Ar name Ns = Ns Ar value
+options.
+.Pp
+If no
+.Ar utility
+is specified,
+.Nm
+prints out the names and values of the variables in the environment.
+Each name/value pair is separated by a new line unless
+.Fl 0
+is specified, in which case name/value pairs are separated by NUL.
+Both
+.Fl 0
+and
+.Ar utility
+may not be specified together.
+.Pp
+The
+.Nm
+utility does not handle values of
+.Ar utility
+which have an equals sign
+.Pq Ql =
+in their name, for obvious reasons.
+This can easily be worked around by interposing the
+.Xr command 1
+utility, which simply executes its arguments; see
+.Sx EXAMPLES
+below.
+.\"
+.Ss Details of -S (split-string) processing
+The processing of the
+.Fl S
+option will split the given
+.Ar string
+into separate arguments based on any space or <tab> characters found in the
+.Ar string .
+Each of those new arguments will then be treated as if it had been
+specified as a separate argument on the original
+.Nm
+command.
+.Pp
+Spaces and tabs may be embedded in one of those new arguments by using
+single
+.Pq Dq Li '
+or double
+.Pq Ql \&"
+quotes, or backslashes
+.Pq Ql \e .
+Single quotes will escape all non-single quote characters, up to
+the matching single quote.
+Double quotes will escape all non-double quote characters, up to
+the matching double quote.
+It is an error if the end of the
+.Ar string
+is reached before the matching quote character.
+.Pp
+If
+.Fl S
+would create a new argument that starts with the
+.Ql #
+character, then that argument and the remainder of the
+.Ar string
+will be ignored.
+The
+.Ql \e#
+sequence can be used when you want a new argument to start
+with a
+.Ql #
+character, without causing the remainder of the
+.Ar string
+to be skipped.
+.Pp
+While processing the
+.Ar string
+value,
+.Fl S
+processing will treat certain character combinations as escape
+sequences which represent some action to take.
+The character escape sequences are in backslash notation.
+The characters and their meanings are as follows:
+.Pp
+.Bl -tag -width indent -offset indent -compact
+.It Cm \ec
+Ignore the remaining characters in the
+.Ar string .
+This must not appear inside a double-quoted string.
+.It Cm \ef
+Replace with a <form-feed> character.
+.It Cm \en
+Replace with a <new-line> character.
+.It Cm \er
+Replace with a <carriage return> character.
+.It Cm \et
+Replace with a <tab> character.
+.It Cm \ev
+Replace with a <vertical tab> character.
+.It Cm \e#
+Replace with a
+.Ql #
+character.
+This would be useful when you need a
+.Ql #
+as the first character in one of the arguments created
+by splitting apart the given
+.Ar string .
+.It Cm \e$
+Replace with a
+.Ql $
+character.
+.It Cm \e_
+If this is found inside of a double-quoted string, then replace it
+with a single blank.
+If this is found outside of a quoted string, then treat this as the
+separator character between new arguments in the original
+.Ar string .
+.It Cm \e"
+Replace with a <double quote> character.
+.It Cm \e\'
+Replace with a <single quote> character.
+.It Cm \e\e
+Replace with a backslash character.
+.El
+.Pp
+The sequences for <single-quote> and backslash are the only sequences
+which are recognized inside of a single-quoted string.
+The other sequences have no special meaning inside a single-quoted
+string.
+All escape sequences are recognized inside of a double-quoted string.
+It is an error if a single
+.Ql \e
+character is followed by a character other than the ones listed above.
+.Pp
+The processing of
+.Fl S
+also supports substitution of values from environment variables.
+To do this, the name of the environment variable must be inside of
+.Ql ${} ,
+such as:
+.Li ${SOMEVAR} .
+The common shell syntax of
+.Li $SOMEVAR
+is not supported.
+All values substituted will be the values of the environment variables
+as they were when the
+.Nm
+utility was originally invoked.
+Those values will not be checked for any of the escape sequences as
+described above.
+And any settings of
+.Ar name Ns = Ns Ar value
+will not effect the values used for substitution in
+.Fl S
+processing.
+.Pp
+Also,
+.Fl S
+processing cannot reference the value of the special parameters
+which are defined by most shells.
+For instance,
+.Fl S
+cannot recognize special parameters such as:
+.Ql $* ,
+.Ql $@ ,
+.Ql $# ,
+.Ql $?
+or
+.Ql $$
+if they appear inside the given
+.Ar string .
+.\"
+.Ss Use in shell-scripts
+The
+.Nm
+utility is often used as the
+.Ar interpreter
+on the first line of interpreted scripts, as
+described in
+.Xr execve 2 .
+.Pp
+Note that the way the kernel parses the
+.Ql #!
+(first line) of an interpreted script has changed as of
+.Fx 6.0 .
+Prior to that, the
+.Fx
+kernel would split that first line into separate arguments based
+on any whitespace (space or <tab> characters) found in the line.
+So, if a script named
+.Pa /usr/local/bin/someport
+had a first line of:
+.Pp
+.Dl "#!/usr/local/bin/php -n -q -dsafe_mode=0"
+.Pp
+then the
+.Pa /usr/local/bin/php
+program would have been started with the arguments of:
+.Bd -literal -offset indent
+arg[0] = '/usr/local/bin/php'
+arg[1] = '-n'
+arg[2] = '-q'
+arg[3] = '-dsafe_mode=0'
+arg[4] = '/usr/local/bin/someport'
+.Ed
+.Pp
+plus any arguments the user specified when executing
+.Pa someport .
+However, this processing of multiple options on the
+.Ql #!
+line is not the way any other operating system parses the
+first line of an interpreted script.
+So after a change which was made for
+.Fx 6.0
+release, that script will result in
+.Pa /usr/local/bin/php
+being started with the arguments of:
+.Bd -literal -offset indent
+arg[0] = '/usr/local/bin/php'
+arg[1] = '-n -q -dsafe_mode=0'
+arg[2] = '/usr/local/bin/someport'
+.Ed
+.Pp
+plus any arguments the user specified.
+This caused a significant change in the behavior of a few scripts.
+In the case of above script, to have it behave the same way under
+.Fx 6.0
+as it did under earlier releases, the first line should be
+changed to:
+.Pp
+.Dl "#!/usr/bin/env -S /usr/local/bin/php -n -q -dsafe_mode=0"
+.Pp
+The
+.Nm
+utility will be started with the entire line as a single
+argument:
+.Pp
+.Dl "arg[1] = '-S /usr/local/bin/php -n -q -dsafe_mode=0'"
+.Pp
+and then
+.Fl S
+processing will split that line into separate arguments before
+executing
+.Pa /usr/local/bin/php .
+.\"
+.Sh ENVIRONMENT
+The
+.Nm
+utility uses the
+.Ev PATH
+environment variable to locate the requested
+.Ar utility
+if the name contains no
+.Ql /
+characters, unless the
+.Fl P
+option has been specified.
+.Sh EXIT STATUS
+.Ex -std
+An exit status of 126 indicates that
+.Ar utility
+was found, but could not be executed.
+An exit status of 127 indicates that
+.Ar utility
+could not be found.
+.Sh EXAMPLES
+Since the
+.Nm
+utility is often used as part of the first line of an interpreted script,
+the following examples show a number of ways that the
+.Nm
+utility can be useful in scripts.
+.Pp
+The kernel processing of an interpreted script does not allow a script
+to directly reference some other script as its own interpreter.
+As a way around this, the main difference between
+.Pp
+.Dl #!/usr/local/bin/foo
+and
+.Dl "#!/usr/bin/env /usr/local/bin/foo"
+.Pp
+is that the latter works even if
+.Pa /usr/local/bin/foo
+is itself an interpreted script.
+.Pp
+Probably the most common use of
+.Nm
+is to find the correct interpreter for a script, when the interpreter
+may be in different directories on different systems.
+The following example will find the
+.Ql perl
+interpreter by searching through the directories specified by
+.Ev PATH .
+.Pp
+.Dl "#!/usr/bin/env perl"
+.Pp
+One limitation of that example is that it assumes the user's value
+for
+.Ev PATH
+is set to a value which will find the interpreter you want
+to execute.
+The
+.Fl P
+option can be used to make sure a specific list of directories is
+used in the search for
+.Ar utility .
+Note that the
+.Fl S
+option is also required for this example to work correctly.
+.Pp
+.Dl "#!/usr/bin/env -S -P/usr/local/bin:/usr/bin perl"
+.Pp
+The above finds
+.Ql perl
+only if it is in
+.Pa /usr/local/bin
+or
+.Pa /usr/bin .
+That could be combined with the present value of
+.Ev PATH ,
+to provide more flexibility.
+Note that spaces are not required between the
+.Fl S
+and
+.Fl P
+options:
+.Pp
+.Dl "#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl"
+.Pp
+To execute a utility with an equal sign in its name:
+.Bd -literal -offset indent
+env name=value ... command foo=bar arg ...
+.Ed
+.Sh COMPATIBILITY
+The
+.Nm
+utility accepts the
+.Fl
+option as a synonym for
+.Fl i .
+.Sh SEE ALSO
+.Xr printenv 1 ,
+.Xr sh 1 ,
+.Xr execvp 3 ,
+.Xr login.conf 5 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+The
+.Fl 0 , C , L , P , S , U , u
+and
+.Fl v
+options are non-standard extensions supported by
+.Fx ,
+but which may not be available on other operating systems.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
+The
+.Fl P , S
+and
+.Fl v
+options were added in
+.Fx 6.0 .
+The
+.Fl 0 , L
+and
+.Fl U
+options were added in
+.Fx 13.0 .
+The
+.Fl C
+option was added in
+.Fx 14.2 .
+.Sh BUGS
+The
+.Nm
+utility does not take multibyte characters into account when
+processing the
+.Fl S
+option, which may lead to incorrect results in some locales.
diff --git a/usr.bin/env/env.c b/usr.bin/env/env.c
new file mode 100644
index 000000000000..10e333602ee8
--- /dev/null
+++ b/usr.bin/env/env.c
@@ -0,0 +1,229 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <login_cap.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "envopts.h"
+
+extern char **environ;
+
+int env_verbosity;
+
+static void usage(void) __dead2;
+
+/*
+ * Exit codes.
+ */
+#define EXIT_CANCELED 125 /* Internal error prior to exec attempt. */
+#define EXIT_CANNOT_INVOKE 126 /* Program located, but not usable. */
+#define EXIT_ENOENT 127 /* Could not find program to exec. */
+
+int
+main(int argc, char **argv)
+{
+ char *altpath, *altwd, **ep, *p, **parg, term;
+ char *cleanenv[1];
+ char *login_class, *login_name;
+ struct passwd *pw;
+ login_cap_t *lc;
+ bool login_as_user;
+ uid_t uid;
+ int ch, want_clear;
+ int rtrn;
+
+ altpath = NULL;
+ altwd = NULL;
+ login_class = NULL;
+ login_name = NULL;
+ pw = NULL;
+ lc = NULL;
+ login_as_user = false;
+ want_clear = 0;
+ term = '\n';
+ while ((ch = getopt(argc, argv, "-0C:iL:P:S:U:u:v")) != -1)
+ switch(ch) {
+ case '-':
+ case 'i':
+ want_clear = 1;
+ break;
+ case '0':
+ term = '\0';
+ break;
+ case 'C':
+ altwd = optarg;
+ break;
+ case 'U':
+ login_as_user = true;
+ /* FALLTHROUGH */
+ case 'L':
+ login_name = optarg;
+ break;
+ case 'P':
+ altpath = optarg;
+ break;
+ case 'S':
+ /*
+ * The -S option, for "split string on spaces, with
+ * support for some simple substitutions"...
+ */
+ split_spaces(optarg, &optind, &argc, &argv);
+ break;
+ case 'u':
+ if (env_verbosity)
+ fprintf(stderr, "#env unset:\t%s\n", optarg);
+ rtrn = unsetenv(optarg);
+ if (rtrn == -1)
+ err(EXIT_FAILURE, "unsetenv %s", optarg);
+ break;
+ case 'v':
+ env_verbosity++;
+ if (env_verbosity > 1)
+ fprintf(stderr, "#env verbosity now at %d\n",
+ env_verbosity);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ if (want_clear) {
+ environ = cleanenv;
+ cleanenv[0] = NULL;
+ if (env_verbosity)
+ fprintf(stderr, "#env clearing environ\n");
+ }
+ if (login_name != NULL) {
+ login_class = strchr(login_name, '/');
+ if (login_class)
+ *login_class++ = '\0';
+ if (*login_name != '\0' && strcmp(login_name, "-") != 0) {
+ pw = getpwnam(login_name);
+ if (pw == NULL) {
+ char *endp = NULL;
+ errno = 0;
+ uid = strtoul(login_name, &endp, 10);
+ if (errno == 0 && *endp == '\0')
+ pw = getpwuid(uid);
+ }
+ if (pw == NULL)
+ errx(EXIT_FAILURE, "no such user: %s", login_name);
+ }
+ /*
+ * Note that it is safe for pw to be null here; the libutil
+ * code handles that, bypassing substitution of $ and using
+ * the class "default" if no class name is given either.
+ */
+ if (login_class != NULL) {
+ lc = login_getclass(login_class);
+ if (lc == NULL)
+ errx(EXIT_FAILURE, "no such login class: %s",
+ login_class);
+ } else {
+ lc = login_getpwclass(pw);
+ if (lc == NULL)
+ errx(EXIT_FAILURE, "login_getpwclass failed");
+ }
+
+ /*
+ * This is not done with setusercontext() because that will
+ * try and use ~/.login_conf even when we don't want it to.
+ */
+ setclassenvironment(lc, pw, 1);
+ setclassenvironment(lc, pw, 0);
+ if (login_as_user) {
+ login_close(lc);
+ if ((lc = login_getuserclass(pw)) != NULL) {
+ setclassenvironment(lc, pw, 1);
+ setclassenvironment(lc, pw, 0);
+ }
+ }
+ endpwent();
+ if (lc != NULL)
+ login_close(lc);
+ }
+ for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) {
+ if (env_verbosity)
+ fprintf(stderr, "#env setenv:\t%s\n", *argv);
+ *p = '\0';
+ rtrn = setenv(*argv, p + 1, 1);
+ *p = '=';
+ if (rtrn == -1)
+ err(EXIT_FAILURE, "setenv %s", *argv);
+ }
+ if (*argv) {
+ if (term == '\0')
+ errx(EXIT_CANCELED, "cannot specify command with -0");
+ if (altwd && chdir(altwd) != 0)
+ err(EXIT_CANCELED, "cannot change directory to '%s'",
+ altwd);
+ if (altpath)
+ search_paths(altpath, argv);
+ if (env_verbosity) {
+ fprintf(stderr, "#env executing:\t%s\n", *argv);
+ for (parg = argv, argc = 0; *parg; parg++, argc++)
+ fprintf(stderr, "#env arg[%d]=\t'%s'\n",
+ argc, *parg);
+ if (env_verbosity > 1)
+ sleep(1);
+ }
+ execvp(*argv, argv);
+ err(errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE,
+ "%s", *argv);
+ } else {
+ if (altwd)
+ errx(EXIT_CANCELED, "must specify command with -C");
+ if (altpath)
+ errx(EXIT_CANCELED, "must specify command with -P");
+ }
+ for (ep = environ; *ep; ep++)
+ (void)printf("%s%c", *ep, term);
+ if (fflush(stdout) != 0)
+ err(1, "stdout");
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: env [-0iv] [-C workdir] [-L|-U user[/class]] [-P utilpath] [-S string]\n"
+ " [-u name] [name=value ...] [utility [argument ...]]\n");
+ exit(1);
+}
diff --git a/usr.bin/env/envopts.c b/usr.bin/env/envopts.c
new file mode 100644
index 000000000000..8b8df5b47e71
--- /dev/null
+++ b/usr.bin/env/envopts.c
@@ -0,0 +1,468 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the FreeBSD Project.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <err.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "envopts.h"
+
+static const char *
+ expand_vars(int in_thisarg, char **thisarg_p, char **dest_p,
+ const char **src_p);
+static int is_there(char *candidate);
+
+/*
+ * The is*() routines take a parameter of 'int', but expect values in the range
+ * of unsigned char. Define some wrappers which take a value of type 'char',
+ * whether signed or unsigned, and ensure the value ends up in the right range.
+ */
+#define isalnumch(Anychar) isalnum((u_char)(Anychar))
+#define isalphach(Anychar) isalpha((u_char)(Anychar))
+#define isspacech(Anychar) isspace((u_char)(Anychar))
+
+/*
+ * Routine to determine if a given fully-qualified filename is executable.
+ * This is copied almost verbatim from FreeBSD's usr.bin/which/which.c.
+ */
+static int
+is_there(char *candidate)
+{
+ struct stat fin;
+
+ /* XXX work around access(2) false positives for superuser */
+ if (access(candidate, X_OK) == 0 &&
+ stat(candidate, &fin) == 0 &&
+ S_ISREG(fin.st_mode) &&
+ (getuid() != 0 ||
+ (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+ if (env_verbosity > 1)
+ fprintf(stderr, "#env matched:\t'%s'\n", candidate);
+ return (1);
+ }
+ return (0);
+}
+
+/**
+ * Routine to search through an alternate path-list, looking for a given
+ * filename to execute. If the file is found, replace the original
+ * unqualified name with a fully-qualified path. This allows `env' to
+ * execute programs from a specific strict list of possible paths, without
+ * changing the value of PATH seen by the program which will be executed.
+ * E.G.:
+ * #!/usr/bin/env -S-P/usr/local/bin:/usr/bin perl
+ * will execute /usr/local/bin/perl or /usr/bin/perl (whichever is found
+ * first), no matter what the current value of PATH is, and without
+ * changing the value of PATH that the script will see when it runs.
+ *
+ * This is similar to the print_matches() routine in usr.bin/which/which.c.
+ */
+void
+search_paths(char *path, char **argv)
+{
+ char candidate[PATH_MAX];
+ const char *d;
+ char *filename, *fqname;
+
+ /* If the file has a `/' in it, then no search is done */
+ filename = *argv;
+ if (strchr(filename, '/') != NULL)
+ return;
+
+ if (env_verbosity > 1) {
+ fprintf(stderr, "#env Searching:\t'%s'\n", path);
+ fprintf(stderr, "#env for file:\t'%s'\n", filename);
+ }
+
+ fqname = NULL;
+ while ((d = strsep(&path, ":")) != NULL) {
+ if (*d == '\0')
+ d = ".";
+ if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
+ filename) >= (int)sizeof(candidate))
+ continue;
+ if (is_there(candidate)) {
+ fqname = candidate;
+ break;
+ }
+ }
+
+ if (fqname == NULL) {
+ errno = ENOENT;
+ err(127, "%s", filename);
+ }
+ *argv = strdup(candidate);
+}
+
+/**
+ * Routine to split a string into multiple parameters, while recognizing a
+ * few special characters. It recognizes both single and double-quoted
+ * strings. This processing is designed entirely for the benefit of the
+ * parsing of "#!"-lines (aka "shebang" lines == the first line of an
+ * executable script). Different operating systems parse that line in very
+ * different ways, and this split-on-spaces processing is meant to provide
+ * ways to specify arbitrary arguments on that line, no matter how the OS
+ * parses it.
+ *
+ * Within a single-quoted string, the two characters "\'" are treated as
+ * a literal "'" character to add to the string, and "\\" are treated as
+ * a literal "\" character to add. Other than that, all characters are
+ * copied until the processing gets to a terminating "'".
+ *
+ * Within a double-quoted string, many more "\"-style escape sequences
+ * are recognized, mostly copied from what is recognized in the `printf'
+ * command. Some OS's will not allow a literal blank character to be
+ * included in the one argument that they recognize on a shebang-line,
+ * so a few additional escape-sequences are defined to provide ways to
+ * specify blanks.
+ *
+ * Within a double-quoted string "\_" is turned into a literal blank.
+ * (Inside of a single-quoted string, the two characters are just copied)
+ * Outside of a quoted string, "\_" is treated as both a blank, and the
+ * end of the current argument. So with a shelbang-line of:
+ * #!/usr/bin/env -SA=avalue\_perl
+ * the -S value would be broken up into arguments "A=avalue" and "perl".
+ */
+void
+split_spaces(const char *str, int *origind, int *origc, char ***origv)
+{
+ static const char *nullarg = "";
+ const char *bq_src, *copystr, *src;
+ char *dest, **newargv, *newstr, **nextarg, **oldarg;
+ int addcount, bq_destlen, copychar, found_sep, in_arg, in_dq, in_sq;
+
+ /*
+ * Ignore leading space on the string, and then malloc enough room
+ * to build a copy of it. The copy might end up shorter than the
+ * original, due to quoted strings and '\'-processing.
+ */
+ while (isspacech(*str))
+ str++;
+ if (*str == '\0')
+ return;
+ newstr = malloc(strlen(str) + 1);
+
+ /*
+ * Allocate plenty of space for the new array of arg-pointers,
+ * and start that array off with the first element of the old
+ * array.
+ */
+ newargv = malloc((*origc + (strlen(str) / 2) + 2) * sizeof(char *));
+ nextarg = newargv;
+ *nextarg++ = **origv;
+
+ /* Come up with the new args by splitting up the given string. */
+ addcount = 0;
+ bq_destlen = in_arg = in_dq = in_sq = 0;
+ bq_src = NULL;
+ for (src = str, dest = newstr; *src != '\0'; src++) {
+ /*
+ * This switch will look at a character in *src, and decide
+ * what should be copied to *dest. It only decides what
+ * character(s) to copy, it should not modify *dest. In some
+ * cases, it will look at multiple characters from *src.
+ */
+ copychar = found_sep = 0;
+ copystr = NULL;
+ switch (*src) {
+ case '"':
+ if (in_sq)
+ copychar = *src;
+ else if (in_dq)
+ in_dq = 0;
+ else {
+ /*
+ * Referencing nullarg ensures that a new
+ * argument is created, even if this quoted
+ * string ends up with zero characters.
+ */
+ copystr = nullarg;
+ in_dq = 1;
+ bq_destlen = dest - *(nextarg - 1);
+ bq_src = src;
+ }
+ break;
+ case '$':
+ if (in_sq)
+ copychar = *src;
+ else {
+ copystr = expand_vars(in_arg, (nextarg - 1),
+ &dest, &src);
+ }
+ break;
+ case '\'':
+ if (in_dq)
+ copychar = *src;
+ else if (in_sq)
+ in_sq = 0;
+ else {
+ /*
+ * Referencing nullarg ensures that a new
+ * argument is created, even if this quoted
+ * string ends up with zero characters.
+ */
+ copystr = nullarg;
+ in_sq = 1;
+ bq_destlen = dest - *(nextarg - 1);
+ bq_src = src;
+ }
+ break;
+ case '\\':
+ if (in_sq) {
+ /*
+ * Inside single-quoted strings, only the
+ * "\'" and "\\" are recognized as special
+ * strings.
+ */
+ copychar = *(src + 1);
+ if (copychar == '\'' || copychar == '\\')
+ src++;
+ else
+ copychar = *src;
+ break;
+ }
+ src++;
+ switch (*src) {
+ case '"':
+ case '#':
+ case '$':
+ case '\'':
+ case '\\':
+ copychar = *src;
+ break;
+ case '_':
+ /*
+ * Alternate way to get a blank, which allows
+ * that blank be used to separate arguments
+ * when it is not inside a quoted string.
+ */
+ if (in_dq)
+ copychar = ' ';
+ else {
+ found_sep = 1;
+ src++;
+ }
+ break;
+ case 'c':
+ /*
+ * Ignore remaining characters in the -S string.
+ * This would not make sense if found in the
+ * middle of a quoted string.
+ */
+ if (in_dq)
+ errx(1, "Sequence '\\%c' is not allowed"
+ " in quoted strings", *src);
+ goto str_done;
+ case 'f':
+ copychar = '\f';
+ break;
+ case 'n':
+ copychar = '\n';
+ break;
+ case 'r':
+ copychar = '\r';
+ break;
+ case 't':
+ copychar = '\t';
+ break;
+ case 'v':
+ copychar = '\v';
+ break;
+ default:
+ if (isspacech(*src))
+ copychar = *src;
+ else
+ errx(1, "Invalid sequence '\\%c' in -S",
+ *src);
+ }
+ break;
+ default:
+ if ((in_dq || in_sq) && in_arg)
+ copychar = *src;
+ else if (isspacech(*src))
+ found_sep = 1;
+ else {
+ /*
+ * If the first character of a new argument
+ * is `#', then ignore the remaining chars.
+ */
+ if (!in_arg && *src == '#')
+ goto str_done;
+ copychar = *src;
+ }
+ }
+ /*
+ * Now that the switch has determined what (if anything)
+ * needs to be copied, copy whatever that is to *dest.
+ */
+ if (copychar || copystr != NULL) {
+ if (!in_arg) {
+ /* This is the first byte of a new argument */
+ *nextarg++ = dest;
+ addcount++;
+ in_arg = 1;
+ }
+ if (copychar)
+ *dest++ = (char)copychar;
+ else if (copystr != NULL)
+ while (*copystr != '\0')
+ *dest++ = *copystr++;
+ } else if (found_sep) {
+ *dest++ = '\0';
+ while (isspacech(*src))
+ src++;
+ --src;
+ in_arg = 0;
+ }
+ }
+str_done:
+ *dest = '\0';
+ *nextarg = NULL;
+ if (in_dq || in_sq) {
+ errx(1, "No terminating quote for string: %.*s%s",
+ bq_destlen, *(nextarg - 1), bq_src);
+ }
+ if (env_verbosity > 1) {
+ fprintf(stderr, "#env split -S:\t'%s'\n", str);
+ oldarg = newargv + 1;
+ fprintf(stderr, "#env into:\t'%s'\n", *oldarg);
+ for (oldarg++; *oldarg; oldarg++)
+ fprintf(stderr, "#env &\t'%s'\n", *oldarg);
+ }
+
+ /* Copy the unprocessed arg-pointers from the original array */
+ for (oldarg = *origv + *origind; *oldarg; oldarg++)
+ *nextarg++ = *oldarg;
+ *nextarg = NULL;
+
+ /* Update optind/argc/argv in the calling routine */
+ *origc += addcount - *origind + 1;
+ *origv = newargv;
+ *origind = 1;
+}
+
+/**
+ * Routine to split expand any environment variables referenced in the string
+ * that -S is processing. For now it only supports the form ${VARNAME}. It
+ * explicitly does not support $VARNAME, and obviously can not handle special
+ * shell-variables such as $?, $*, $1, etc. It is called with *src_p pointing
+ * at the initial '$', and if successful it will update *src_p, *dest_p, and
+ * possibly *thisarg_p in the calling routine.
+ */
+static const char *
+expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, const char **src_p)
+{
+ const char *vbegin, *vend, *vvalue;
+ char *newstr, *vname;
+ int bad_reference;
+ size_t namelen, newlen;
+
+ bad_reference = 1;
+ vbegin = vend = (*src_p) + 1;
+ if (*vbegin++ == '{')
+ if (*vbegin == '_' || isalphach(*vbegin)) {
+ vend = vbegin + 1;
+ while (*vend == '_' || isalnumch(*vend))
+ vend++;
+ if (*vend == '}')
+ bad_reference = 0;
+ }
+ if (bad_reference)
+ errx(1, "Only ${VARNAME} expansion is supported, error at: %s",
+ *src_p);
+
+ /*
+ * We now know we have a valid environment variable name, so update
+ * the caller's source-pointer to the last character in that reference,
+ * and then pick up the matching value. If the variable is not found,
+ * or if it has a null value, then our work here is done.
+ */
+ *src_p = vend;
+ namelen = vend - vbegin + 1;
+ vname = malloc(namelen);
+ strlcpy(vname, vbegin, namelen);
+ vvalue = getenv(vname);
+ if (vvalue == NULL || *vvalue == '\0') {
+ if (env_verbosity > 2)
+ fprintf(stderr,
+ "#env replacing ${%s} with null string\n",
+ vname);
+ free(vname);
+ return (NULL);
+ }
+
+ if (env_verbosity > 2)
+ fprintf(stderr, "#env expanding ${%s} into '%s'\n", vname,
+ vvalue);
+
+ /*
+ * There is some value to copy to the destination. If the value is
+ * shorter than the ${VARNAME} reference that it replaces, then our
+ * caller can just copy the value to the existing destination.
+ */
+ if (strlen(vname) + 3 >= strlen(vvalue)) {
+ free(vname);
+ return (vvalue);
+ }
+
+ /*
+ * The value is longer than the string it replaces, which means the
+ * present destination area is too small to hold it. Create a new
+ * destination area, and update the caller's 'dest' variable to match.
+ * If the caller has already started copying some info for 'thisarg'
+ * into the present destination, then the new destination area must
+ * include a copy of that data, and the pointer to 'thisarg' must also
+ * be updated. Note that it is still the caller which copies this
+ * vvalue to the new *dest.
+ */
+ newlen = strlen(vvalue) + strlen(*src_p) + 1;
+ if (in_thisarg) {
+ **dest_p = '\0'; /* Provide terminator for 'thisarg' */
+ newlen += strlen(*thisarg_p);
+ newstr = malloc(newlen);
+ strcpy(newstr, *thisarg_p);
+ *thisarg_p = newstr;
+ } else {
+ newstr = malloc(newlen);
+ *newstr = '\0';
+ }
+ *dest_p = strchr(newstr, '\0');
+ free(vname);
+ return (vvalue);
+}
diff --git a/usr.bin/env/envopts.h b/usr.bin/env/envopts.h
new file mode 100644
index 000000000000..12588523ec66
--- /dev/null
+++ b/usr.bin/env/envopts.h
@@ -0,0 +1,37 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the FreeBSD Project.
+ */
+
+void search_paths(char *path, char **argv);
+void split_spaces(const char *str, int *origind, int *origc,
+ char ***origv);
+
+extern int env_verbosity;
diff --git a/usr.bin/env/tests/Makefile b/usr.bin/env/tests/Makefile
new file mode 100644
index 000000000000..3d2f77b34b67
--- /dev/null
+++ b/usr.bin/env/tests/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= env_test
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/env/tests/Makefile.depend b/usr.bin/env/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/env/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/env/tests/env_test.sh b/usr.bin/env/tests/env_test.sh
new file mode 100644
index 000000000000..3210361eb223
--- /dev/null
+++ b/usr.bin/env/tests/env_test.sh
@@ -0,0 +1,161 @@
+#
+# Copyright (c) 2024 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+magic_words="Squeamish $$ Ossifrage"
+
+atf_test_case basic
+basic_head()
+{
+ atf_set "descr" "Basic test case"
+}
+basic_body()
+{
+ atf_check -o match:"^magic_words=${magic_words}\$" \
+ env magic_words="${magic_words}"
+ export MAGIC_WORDS="${magic_words}"
+ atf_check -o match:"^MAGIC_WORDS=${magic_words}\$" \
+ env
+ unset MAGIC_WORDS
+}
+
+atf_test_case unset
+unset_head()
+{
+ atf_set "descr" "Unset a variable"
+}
+unset_body()
+{
+ export MAGIC_WORDS="${magic_words}"
+ atf_check -o not-match:"^MAGIC_WORDS=" \
+ env -u MAGIC_WORDS
+ unset MAGIC_WORDS
+}
+
+atf_test_case empty
+empty_head()
+{
+ atf_set "descr" "Empty environment"
+}
+empty_body()
+{
+ atf_check env -i
+}
+
+atf_test_case true
+true_head()
+{
+ atf_set "descr" "Run true"
+}
+true_body()
+{
+ atf_check env true
+}
+
+atf_test_case false
+false_head()
+{
+ atf_set "descr" "Run false"
+}
+false_body()
+{
+ atf_check -s exit:1 env false
+}
+
+atf_test_case false
+false_head()
+{
+ atf_set "descr" "Run false"
+}
+false_body()
+{
+ atf_check -s exit:1 env false
+}
+
+atf_test_case altpath
+altpath_head()
+{
+ atf_set "descr" "Use alternate path"
+}
+altpath_body()
+{
+ echo "echo ${magic_words}" >magic_words
+ chmod 0755 magic_words
+ atf_check -s exit:125 -e match:"must specify command" \
+ env -P "${PWD}"
+ atf_check -s exit:127 -e match:"No such file" \
+ env magic_words
+ atf_check -o inline:"${magic_words}\n" \
+ env -P "${PWD}" magic_words
+}
+
+atf_test_case equal
+equal_head()
+{
+ atf_set "descr" "Command name contains equal sign"
+}
+equal_body()
+{
+ echo "echo ${magic_words}" >"magic=words"
+ chmod 0755 "magic=words"
+ atf_check -o match:"^${PWD}/magic=words$" \
+ env "${PWD}/magic=words"
+ atf_check -s exit:125 -e match:"must specify command" \
+ env -P "${PATH}:${PWD}" "magic=words"
+ atf_check -o inline:"${magic_words}\n" \
+ env command "${PWD}/magic=words"
+ atf_check -o inline:"${magic_words}\n" \
+ env PATH="${PATH}:${PWD}" command "magic=words"
+}
+
+atf_test_case chdir
+chdir_head()
+{
+ atf_set "descr" "Change working directory"
+}
+chdir_body()
+{
+ local subdir="dir.$$"
+ atf_check -o inline:"${PWD}\n" \
+ env pwd
+ atf_check -s exit:125 -e match:"must specify command" \
+ env -C "${subdir}"
+ atf_check -s exit:125 \
+ -e match:"cannot change directory to '${subdir}':" \
+ env -C "${subdir}" pwd
+ atf_check mkdir "${subdir}"
+ atf_check -o inline:"${PWD}/${subdir}\n" \
+ env -C "${subdir}" pwd
+}
+
+atf_test_case stdout
+stdout_head()
+{
+ atf_set descr "Failure to write to stdout"
+}
+stdout_body()
+{
+ (
+ trap "" PIPE
+ sleep 1
+ env 2>stderr
+ echo $? >result
+ ) | true
+ atf_check -o inline:"1\n" cat result
+ atf_check -o match:"stdout" cat stderr
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case unset
+ atf_add_test_case empty
+ atf_add_test_case true
+ atf_add_test_case false
+ atf_add_test_case altpath
+ atf_add_test_case equal
+ atf_add_test_case chdir
+ atf_add_test_case stdout
+}
diff --git a/usr.bin/etdump/Makefile b/usr.bin/etdump/Makefile
new file mode 100644
index 000000000000..8c451bf2c574
--- /dev/null
+++ b/usr.bin/etdump/Makefile
@@ -0,0 +1,12 @@
+PROG= etdump
+
+MAKEFS_SRC= ${SRCTOP}/usr.sbin/makefs
+
+CFLAGS+= -I${SRCTOP}/sys/fs/cd9660 -I${MAKEFS_SRC} \
+ -I${MAKEFS_SRC}/cd9660
+
+.PATH: ${MAKEFS_SRC}/cd9660
+
+SRCS= etdump.c output_shell.c output_text.c cd9660_conversion.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/etdump/etdump.1 b/usr.bin/etdump/etdump.1
new file mode 100644
index 000000000000..bec8d201eb4f
--- /dev/null
+++ b/usr.bin/etdump/etdump.1
@@ -0,0 +1,102 @@
+.\" Copyright (c) 2018 iXsystems, Inc
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 April 25, 2018
+.Dt ETDUMP 8
+.Os
+.Sh NAME
+.Nm etdump
+.Nd Dump El Torito boot catalog information from ISO images
+.Sh SYNOPSIS
+.Nm
+.Op Fl f Ar format
+.Op Fl o Ar file
+.Ar
+.Sh DESCRIPTION
+This program reads El Torito boot catalog information from an ISO image and
+outputs it in various formats.
+It can be used to check the catalog in an image or to output catalog data in
+a format that can be used by other tools such as shell scripts.
+.Pp
+Supported options are:
+.Bl -tag -width flag
+.It Fl f Ar format Fl -format Ar format
+Select the output format.
+Supported output formats are:
+.Bl -tag -width shell -offset indent
+.It Sy text
+Human-readable text (default)
+.It Sy shell
+Each boot entry is emitted as a string suitable for passing to a sh-compatible
+eval command.
+The variables emitted are:
+.Bl -tag -width et_platform -offset indent
+.It et_platform
+The platform ID from the section header.
+Set to 'default' for the initial (default) entry.
+.It et_system
+The system ID from the boot entry.
+.It et_lba
+The starting LBA (2048-byte blocks) of the boot image.
+.It et_sectors
+The number of sectors (512-byte sectors) that comprise the boot image.
+.El
+.El
+.It Fl o Ar file Fl -output Ar file
+Write output to
+.Ar file .
+If '-' is specified then standard out is used.
+.El
+.Sh EXAMPLES
+To see what entries are in a given boot catalog run
+.Nm
+passing the filename of the image as an argument like so:
+.Bd -literal -offset indent
+% etdump bootonly.iso
+Image in bootonly.iso
+Default entry
+ System i386
+ Start LBA 420 (0x1a4), sector count 4 (0x4)
+ Media type: no emulation
+
+Section header: efi, final
+ Section entry
+ System i386
+ Start LBA 20 (0x14), sector count 1600 (0x640)
+ Media type: no emulation
+.Ed
+.Pp
+To use the output in a shell script a for loop can be used to iterate over the
+entries returned using eval:
+.Bd -literal -offset indent
+for entry in `etdump --format shell bootonly.iso`; do
+ eval $entry
+ echo $et_platform $et_system $et_lba $et_sectors
+done
+.Ed
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 11.2
diff --git a/usr.bin/etdump/etdump.c b/usr.bin/etdump/etdump.c
new file mode 100644
index 000000000000..6c4a256e15f5
--- /dev/null
+++ b/usr.bin/etdump/etdump.c
@@ -0,0 +1,272 @@
+/*-
+ * Copyright (c) 2018 iXsystems, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "cd9660.h"
+#include "cd9660_eltorito.h"
+
+#include "etdump.h"
+
+const char *
+system_id_string(u_char system_id)
+{
+
+ switch (system_id) {
+ case ET_SYS_X86:
+ return ("i386");
+ case ET_SYS_PPC:
+ return ("powerpc");
+ case ET_SYS_MAC:
+ return ("mac");
+ case ET_SYS_EFI:
+ return ("efi");
+ default:
+ return ("invalid");
+ }
+}
+
+const char *
+media_type_string(u_char media_type)
+{
+
+ switch (media_type) {
+ case ET_MEDIA_NOEM:
+ return ("no emulation");
+ case ET_MEDIA_12FDD:
+ return ("1.2MB FDD");
+ case ET_MEDIA_144FDD:
+ return ("1.44MB FDD");
+ case ET_MEDIA_288FDD:
+ return ("2.88MB FDD");
+ case ET_MEDIA_HDD:
+ return ("HDD");
+ default:
+ return ("invalid");
+ }
+}
+
+static int
+read_sector(FILE *iso, daddr_t sector, char *buffer)
+{
+
+ if (fseek(iso, sector * ISO_DEFAULT_BLOCK_SIZE, SEEK_SET) != 0) {
+ return (errno);
+ }
+ if (fread(buffer, ISO_DEFAULT_BLOCK_SIZE, 1, iso) != 1) {
+ return (errno);
+ }
+ return (0);
+}
+
+static bool
+boot_catalog_valid(char *entry)
+{
+ boot_catalog_validation_entry *ve;
+ int16_t checksum, sum;
+ unsigned char *csptr;
+ size_t i;
+
+ ve = (boot_catalog_validation_entry *)entry;
+
+ checksum = isonum_721(ve->checksum);
+ cd9660_721(0, ve->checksum);
+ csptr = (unsigned char *)ve;
+
+ for (i = sum = 0; i < sizeof(*ve); i += 2) {
+ sum += (int16_t)csptr[i];
+ sum += 256 * (int16_t)csptr[i + 1];
+ }
+ if (sum + checksum != 0) {
+ return (false);
+ }
+
+ cd9660_721(checksum, ve->checksum);
+ return (true);
+}
+
+static int
+dump_section(char *buffer, size_t bufsize, size_t offset, FILE *outfile,
+ const char *filename, struct outputter *outputter)
+{
+ boot_catalog_section_header *sh;
+ u_char platform_id;
+ int i;
+ size_t entry_offset;
+ boot_catalog_section_entry *entry;
+
+ if (offset + sizeof(boot_catalog_section_header) > bufsize)
+ errx(1, "%s: section header out of bounds", filename);
+ sh = (boot_catalog_section_header *)&buffer[offset];
+ if (outputter->output_section != NULL) {
+ outputter->output_section(outfile, filename, sh);
+ }
+
+ platform_id = sh->platform_id[0];
+
+ if (outputter->output_entry != NULL) {
+ for (i = 1; i <= (int)sh->num_section_entries[0]; i++) {
+ entry_offset = offset + i * ET_BOOT_ENTRY_SIZE;
+ if (entry_offset + sizeof(boot_catalog_section_entry) >
+ bufsize)
+ errx(1, "%s: section entry out of bounds",
+ filename);
+ entry =
+ (boot_catalog_section_entry *)&buffer[entry_offset];
+ outputter->output_entry(outfile, filename, entry,
+ platform_id, false);
+ }
+ }
+
+ return (1 + (int)sh->num_section_entries[0]);
+}
+
+static void
+dump_eltorito(FILE *iso, const char *filename, FILE *outfile,
+ struct outputter *outputter)
+{
+ char buffer[ISO_DEFAULT_BLOCK_SIZE], *entry;
+ boot_volume_descriptor *bvd;
+ daddr_t boot_catalog;
+ size_t offset;
+ int entry_count;
+
+ if (read_sector(iso, 17, buffer) != 0)
+ err(1, "failed to read from image");
+
+ bvd = (boot_volume_descriptor *)buffer;
+ if (memcmp(bvd->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID, 5) != 0)
+ warnx("%s: not a valid ISO", filename);
+ if (bvd->boot_record_indicator[0] != ISO_VOLUME_DESCRIPTOR_BOOT ||
+ memcmp(bvd->boot_system_identifier, ET_ID, 23) != 0)
+ warnx("%s: not an El Torito bootable ISO", filename);
+
+ boot_catalog = isonum_731(bvd->boot_catalog_pointer);
+
+ if (read_sector(iso, boot_catalog, buffer) != 0)
+ err(1, "failed to read from image");
+
+ entry = buffer;
+ offset = 0;
+
+ if (!boot_catalog_valid(entry))
+ warnx("%s: boot catalog checksum is invalid", filename);
+
+ if (outputter->output_image != NULL)
+ outputter->output_image(outfile, filename, bvd);
+
+ offset += ET_BOOT_ENTRY_SIZE;
+ entry = &buffer[offset];
+ if (outputter->output_entry != NULL)
+ outputter->output_entry(outfile, filename,
+ (boot_catalog_section_entry *)entry, 0, true);
+
+ offset += ET_BOOT_ENTRY_SIZE;
+
+ while (offset < ISO_DEFAULT_BLOCK_SIZE) {
+ entry = &buffer[offset];
+
+ if ((uint8_t)entry[0] != ET_SECTION_HEADER_MORE &&
+ (uint8_t)entry[0] != ET_SECTION_HEADER_LAST)
+ break;
+
+ entry_count = dump_section(buffer, sizeof(buffer), offset,
+ outfile, filename, outputter);
+
+ offset += entry_count * ET_BOOT_ENTRY_SIZE;
+ }
+}
+
+static void
+usage(const char *progname)
+{
+ char *path;
+
+ path = strdup(progname);
+
+ fprintf(stderr, "usage: %s [-f format] [-o filename] filename [...]\n",
+ basename(path));
+ fprintf(stderr, "\tsupported output formats: shell, text\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch, i;
+ FILE *outfile, *iso;
+ struct outputter *outputter;
+
+ outfile = stdout;
+ outputter = output_text;
+
+ static struct option longopts[] = {
+ { "format", required_argument, NULL, 'f' },
+ { "output", required_argument, NULL, 'o' },
+ { NULL, 0, NULL, 0 },
+ };
+
+ while ((ch = getopt_long(argc, argv, "f:o:", longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'f':
+ if (strcmp(optarg, "shell") == 0)
+ outputter = output_shell;
+ else if (strcmp(optarg, "text") == 0)
+ outputter = output_text;
+ else
+ usage(argv[0]);
+ break;
+ case 'o':
+ if (strcmp(optarg, "-") == 0) {
+ outfile = stdout;
+ } else if ((outfile = fopen(optarg, "w")) == NULL) {
+ err(1, "unable to open %s for output", optarg);
+ }
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "-") == 0) {
+ iso = stdin;
+ } else {
+ iso = fopen(argv[i], "r");
+ if (iso == NULL)
+ err(1, "could not open %s", argv[i]);
+ }
+ dump_eltorito(iso, argv[i], outfile, outputter);
+ }
+}
diff --git a/usr.bin/etdump/etdump.h b/usr.bin/etdump/etdump.h
new file mode 100644
index 000000000000..c61070d05018
--- /dev/null
+++ b/usr.bin/etdump/etdump.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2018 iXsystems, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _ETDUMP_H_
+#define _ETDUMP_H_
+
+struct outputter {
+ void (*output_image)(FILE *outfile, const char *filename,
+ boot_volume_descriptor *bvd);
+ void (*output_section)(FILE *outfile, const char *filename,
+ boot_catalog_section_header *bcsh);
+ void (*output_entry)(FILE *outfile, const char *filename,
+ boot_catalog_section_entry *bcse,
+ u_char platform_id, bool initial);
+};
+
+extern struct outputter *output_text;
+extern struct outputter *output_shell;
+
+const char *system_id_string(u_char system_id);
+const char *media_type_string(u_char media_type);
+
+#endif /* _ETDUMP_H_ */
+
diff --git a/usr.bin/etdump/output_shell.c b/usr.bin/etdump/output_shell.c
new file mode 100644
index 000000000000..d709684c02dc
--- /dev/null
+++ b/usr.bin/etdump/output_shell.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2018 iXsystems, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "cd9660.h"
+#include "cd9660_eltorito.h"
+
+#include "etdump.h"
+
+static void
+output_entry(FILE *outfile, const char *filename __unused,
+ boot_catalog_section_entry *bcse, u_char platform_id, bool initial)
+{
+ const char *platform;
+
+ switch (bcse->boot_indicator[0]) {
+ case ET_BOOTABLE:
+ break;
+ case ET_NOT_BOOTABLE:
+ default:
+ return;
+ }
+
+ if (initial)
+ platform = "default";
+ else
+ platform = system_id_string(platform_id);
+
+ fprintf(outfile,
+ "et_platform=%s;et_system=%s;et_lba=%d;et_sectors=%d\n",
+ platform, system_id_string(bcse->system_type[0]),
+ isonum_731(bcse->load_rba), isonum_721(bcse->sector_count));
+}
+
+static struct outputter _output_shell = {
+ .output_image = NULL,
+ .output_section = NULL,
+ .output_entry = output_entry,
+};
+
+struct outputter *output_shell = &_output_shell;
diff --git a/usr.bin/etdump/output_text.c b/usr.bin/etdump/output_text.c
new file mode 100644
index 000000000000..aafc6d702a54
--- /dev/null
+++ b/usr.bin/etdump/output_text.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2018 iXsystems, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "cd9660.h"
+#include "cd9660_eltorito.h"
+
+#include "etdump.h"
+
+static void
+output_image(FILE *outfile, const char *filename, boot_volume_descriptor *bvd __unused)
+{
+
+ fprintf(outfile, "Image in %s\n", filename);
+}
+
+static void
+output_section(FILE *outfile, const char *filename __unused,
+ boot_catalog_section_header *bcsh)
+{
+
+ fprintf(outfile, "\nSection header: %s",
+ system_id_string(bcsh->platform_id[0]));
+
+ if (bcsh->header_indicator[0] == ET_SECTION_HEADER_LAST)
+ fprintf(outfile, ", final\n");
+ else
+ fprintf(outfile, "\n");
+}
+
+static void
+output_entry(FILE *outfile, const char *filename __unused,
+ boot_catalog_section_entry *bcse, u_char platform_id __unused,
+ bool initial)
+{
+ const char *indent;
+
+ switch (bcse->boot_indicator[0]) {
+ case ET_BOOTABLE:
+ break;
+ case ET_NOT_BOOTABLE:
+ default:
+ return;
+ }
+
+ if (initial) {
+ fprintf(outfile, "Default entry\n");
+ indent = "\t";
+ } else {
+ fprintf(outfile, "\tSection entry\n");
+ indent = "\t\t";
+ }
+
+ fprintf(outfile, "%sSystem %s\n", indent,
+ system_id_string(bcse->system_type[0]));
+ fprintf(outfile, "%sStart LBA %d (0x%x), sector count %d (0x%x)\n",
+ indent, isonum_731(bcse->load_rba), isonum_731(bcse->load_rba),
+ isonum_721(bcse->sector_count), isonum_721(bcse->sector_count));
+ fprintf(outfile, "%sMedia type: %s\n", indent,
+ media_type_string(bcse->media_type[0]));
+}
+
+static struct outputter _output_text = {
+ .output_image = output_image,
+ .output_section = output_section,
+ .output_entry = output_entry,
+};
+
+struct outputter *output_text = &_output_text;
diff --git a/usr.bin/expand/Makefile b/usr.bin/expand/Makefile
new file mode 100644
index 000000000000..bba5bd3e5065
--- /dev/null
+++ b/usr.bin/expand/Makefile
@@ -0,0 +1,4 @@
+PROG= expand
+MLINKS= expand.1 unexpand.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/expand/Makefile.depend b/usr.bin/expand/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/expand/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/expand/expand.1 b/usr.bin/expand/expand.1
new file mode 100644
index 000000000000..68a7a57eb77e
--- /dev/null
+++ b/usr.bin/expand/expand.1
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd June 6, 2015
+.Dt EXPAND 1
+.Os
+.Sh NAME
+.Nm expand ,
+.Nm unexpand
+.Nd expand tabs to spaces, and vice versa
+.Sh SYNOPSIS
+.Nm
+.Oo
+.Fl t
+.Sm off
+.Ar tab1 , tab2 , ... , tabn
+.Sm on
+.Oc
+.Op Ar
+.Nm unexpand
+.Oo
+.Fl a | t
+.Sm off
+.Ar tab1 , tab2 , ... , tabn
+.Sm on
+.Oc
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility processes the named files or the standard input writing
+the standard output with tabs changed into blanks.
+Backspace characters are preserved into the output and decrement
+the column count for tab calculations.
+The
+.Nm
+utility is useful for pre-processing character files
+(before sorting, looking at specific columns, etc.) that
+contain tabs.
+.Pp
+The
+.Nm unexpand
+utility puts tabs back into the data from the standard input or the named
+files and writes the result on the standard output.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+.Nm ( unexpand
+only.)
+By default, only leading blanks and tabs
+are reconverted to maximal strings of tabs.
+If the
+.Fl a
+option is given, then tabs are inserted whenever they would compress the
+resultant file by replacing two or more characters.
+.It Fl t Xo
+.Sm off
+.Ar tab1 , tab2 , ... , tabn
+.Sm on
+.Xc
+Set tab stops at column positions
+.Sm off
+.Ar tab1 , tab2 , ... , tabn .
+.Sm on
+If only a single number is given, tab stops are set that number of
+column positions apart instead of the default number of 8.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+and
+.Nm unexpand
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std expand unexpand
+.Sh STANDARDS
+The
+.Nm
+and
+.Nm unexpand
+utilities conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 1 .
diff --git a/usr.bin/expand/expand.c b/usr.bin/expand/expand.c
new file mode 100644
index 000000000000..08104926a78d
--- /dev/null
+++ b/usr.bin/expand/expand.c
@@ -0,0 +1,184 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * expand - expand tabs to equivalent spaces
+ */
+static int nstops;
+static int tabstops[100];
+
+static void getstops(char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ const char *curfile;
+ wint_t wc;
+ int c, column;
+ int n;
+ int rval;
+ int width;
+
+ setlocale(LC_CTYPE, "");
+
+ /* handle obsolete syntax */
+ while (argc > 1 && argv[1][0] == '-' &&
+ isdigit((unsigned char)argv[1][1])) {
+ getstops(&argv[1][1]);
+ argc--; argv++;
+ }
+
+ while ((c = getopt (argc, argv, "t:")) != -1) {
+ switch (c) {
+ case 't':
+ getstops(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ rval = 0;
+ do {
+ if (argc > 0) {
+ if (freopen(argv[0], "r", stdin) == NULL) {
+ warn("%s", argv[0]);
+ rval = 1;
+ argc--, argv++;
+ continue;
+ }
+ curfile = argv[0];
+ argc--, argv++;
+ } else
+ curfile = "stdin";
+ column = 0;
+ while ((wc = getwchar()) != WEOF) {
+ switch (wc) {
+ case '\t':
+ if (nstops == 0) {
+ do {
+ putwchar(' ');
+ column++;
+ } while (column & 07);
+ continue;
+ }
+ if (nstops == 1) {
+ do {
+ putwchar(' ');
+ column++;
+ } while (((column - 1) % tabstops[0]) != (tabstops[0] - 1));
+ continue;
+ }
+ for (n = 0; n < nstops; n++)
+ if (tabstops[n] > column)
+ break;
+ if (n == nstops) {
+ putwchar(' ');
+ column++;
+ continue;
+ }
+ while (column < tabstops[n]) {
+ putwchar(' ');
+ column++;
+ }
+ continue;
+
+ case '\b':
+ if (column)
+ column--;
+ putwchar('\b');
+ continue;
+
+ default:
+ putwchar(wc);
+ if ((width = wcwidth(wc)) > 0)
+ column += width;
+ continue;
+
+ case '\n':
+ putwchar(wc);
+ column = 0;
+ continue;
+ }
+ }
+ if (ferror(stdin)) {
+ warn("%s", curfile);
+ rval = 1;
+ }
+ } while (argc > 0);
+ exit(rval);
+}
+
+static void
+getstops(char *cp)
+{
+ int i;
+
+ nstops = 0;
+ for (;;) {
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + *cp++ - '0';
+ if (i <= 0)
+ errx(1, "bad tab stop spec");
+ if (nstops > 0 && i <= tabstops[nstops-1])
+ errx(1, "bad tab stop spec");
+ if (nstops == sizeof(tabstops) / sizeof(*tabstops))
+ errx(1, "too many tab stops");
+ tabstops[nstops++] = i;
+ if (*cp == 0)
+ break;
+ if (*cp != ',' && !isblank((unsigned char)*cp))
+ errx(1, "bad tab stop spec");
+ cp++;
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf (stderr, "usage: expand [-t tablist] [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/factor/Makefile b/usr.bin/factor/Makefile
new file mode 100644
index 000000000000..a0109462fcb3
--- /dev/null
+++ b/usr.bin/factor/Makefile
@@ -0,0 +1,19 @@
+.include <src.opts.mk>
+
+PROG= factor
+SRCS= factor.c pr_tbl.c
+CFLAGS+=-I${SRCTOP}/usr.bin/primes
+
+.if ${MK_OPENSSL} != "no"
+CFLAGS+=-DHAVE_OPENSSL
+LIBADD+=crypto
+.endif
+
+MAN= factor.6
+MLINKS+=factor.6 primes.6
+.PATH: ${SRCTOP}/usr.bin/primes
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/factor/Makefile.depend b/usr.bin/factor/Makefile.depend
new file mode 100644
index 000000000000..577dc5747f1e
--- /dev/null
+++ b/usr.bin/factor/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/factor/Makefile.depend.options b/usr.bin/factor/Makefile.depend.options
new file mode 100644
index 000000000000..b374d7a1fd52
--- /dev/null
+++ b/usr.bin/factor/Makefile.depend.options
@@ -0,0 +1,5 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= OPENSSL
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/factor/factor.6 b/usr.bin/factor/factor.6
new file mode 100644
index 000000000000..c3d00eb744a0
--- /dev/null
+++ b/usr.bin/factor/factor.6
@@ -0,0 +1,128 @@
+.\" Copyright (c) 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Landon Curt Noll.
+.\"
+.\" 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.
+.\"
+.\" By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
+.\"
+.\" chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+.\"
+.Dd January 12, 2020
+.Dt FACTOR 6
+.Os
+.Sh NAME
+.Nm factor , primes
+.Nd factor a number, generate primes
+.Sh SYNOPSIS
+.Nm
+.Op Fl h
+.Op Ar number ...
+.Nm primes
+.Op Fl h
+.Op Ar start Op Ar stop
+.Sh DESCRIPTION
+The
+.Nm
+utility will factor positive integers.
+When a number is factored, it is printed, followed by a
+.Ql \&: ,
+and the list of factors on a single line.
+Factors are listed in ascending order, and are preceded by a space.
+If a factor divides a value more than once, it will be printed more than once.
+.Pp
+When
+.Nm
+is invoked with one or more arguments, each argument will be factored.
+.Pp
+When
+.Nm
+is invoked with no arguments,
+.Nm
+reads numbers, one per line, from standard input until end of file or 0
+is entered or an error occurs.
+Leading white-space and empty lines are ignored.
+.Pp
+Numbers may be preceded by a single
+.Ql + .
+Numbers can be either decimal or hexadecimal strings where the longest
+leading substring is used.
+Numbers are terminated by a non-digit character (such as a newline).
+If the string contains only decimal digits, it is treated as a
+decimal representation for a number.
+A hexadecimal string can contain an optional
+.Em 0x
+or
+.Em 0X
+prefix.
+After a number is read, it is factored.
+.Pp
+The
+.Nm primes
+utility prints primes in ascending order, one per line, starting at or above
+.Ar start
+and continuing until, but not including
+.Ar stop .
+The
+.Ar start
+value must be at least 0 and not greater than
+.Ar stop .
+The
+.Ar stop
+value must not be greater than the maximum.
+The default and maximum value of
+.Ar stop
+is 18446744073709551615.
+.Pp
+When the
+.Nm primes
+utility is invoked with no arguments,
+.Ar start
+is read from standard input and
+.Ar stop
+is taken to be the maximum.
+The
+.Ar start
+value may be preceded by a single
+.Ql + .
+The
+.Ar start
+value is terminated by a non-digit character (such as a newline).
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "negative numbers aren't permitted"
+.It "illegal numeric format"
+.It "start value must be less than stop value"
+.It "Result too large"
+.El
+.Sh BUGS
+.Nm
+cannot handle the
+.Dq "10 most wanted"
+factor list,
+.Nm primes
+will not get you a world record.
diff --git a/usr.bin/factor/factor.c b/usr.bin/factor/factor.c
new file mode 100644
index 000000000000..9d8fdbe1fb0f
--- /dev/null
+++ b/usr.bin/factor/factor.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Landon Curt Noll.
+ *
+ * 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.
+ */
+
+/*
+ * factor - factor a number into primes
+ *
+ * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
+ *
+ * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+ *
+ * usage:
+ * factor [-h] [number] ...
+ *
+ * The form of the output is:
+ *
+ * number: factor1 factor1 factor2 factor3 factor3 factor3 ...
+ *
+ * where factor1 <= factor2 <= factor3 <= ...
+ *
+ * If no args are given, the list of numbers are read from stdin.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "primes.h"
+
+#ifdef HAVE_OPENSSL
+
+#include <openssl/bn.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x30000000L
+static inline int
+BN_check_prime(BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb)
+{
+ const int nchecks = 5;
+
+ return BN_is_prime_ex(p, nchecks, ctx, cb);
+}
+#endif
+
+static void pollard_pminus1(BIGNUM *); /* print factors for big numbers */
+
+#else
+
+typedef ubig BIGNUM;
+typedef u_long BN_ULONG;
+
+#define BN_CTX int
+#define BN_CTX_new() NULL
+#define BN_new() ((BIGNUM *)calloc(sizeof(BIGNUM), 1))
+#define BN_is_zero(v) (*(v) == 0)
+#define BN_is_one(v) (*(v) == 1)
+#define BN_mod_word(a, b) (*(a) % (b))
+
+static int BN_dec2bn(BIGNUM **, const char *);
+static int BN_hex2bn(BIGNUM **, const char *);
+static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
+static void BN_print_fp(FILE *, const BIGNUM *);
+
+#endif
+
+static void BN_print_dec_fp(FILE *, const BIGNUM *);
+static void convert_str2bn(BIGNUM **, char *);
+static bool is_hex_str(char *);
+static void pr_fact(BIGNUM *); /* print factors of a value */
+static void pr_print(BIGNUM *); /* print a prime */
+static void usage(void);
+
+static BN_CTX *ctx; /* just use a global context */
+static int hflag;
+
+int
+main(int argc, char *argv[])
+{
+ BIGNUM *val;
+ int ch;
+ char *p, buf[LINE_MAX]; /* > max number of digits. */
+
+ ctx = BN_CTX_new();
+ val = BN_new();
+ if (val == NULL)
+ errx(1, "can't initialise bignum");
+
+ while ((ch = getopt(argc, argv, "h")) != -1)
+ switch (ch) {
+ case 'h':
+ hflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* No args supplied, read numbers from stdin. */
+ if (argc == 0)
+ for (;;) {
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ if (ferror(stdin))
+ err(1, "stdin");
+ exit (0);
+ }
+ for (p = buf; isblank(*p); ++p);
+ if (*p == '\n' || *p == '\0')
+ continue;
+ convert_str2bn(&val, p);
+ pr_fact(val);
+ }
+ /* Factor the arguments. */
+ else
+ for (p = *argv; p != NULL; p = *++argv) {
+ convert_str2bn(&val, p);
+ pr_fact(val);
+ }
+ exit(0);
+}
+
+/*
+ * pr_fact - print the factors of a number
+ *
+ * Print the factors of the number, from the lowest to the highest.
+ * A factor will be printed multiple times if it divides the value
+ * multiple times.
+ *
+ * Factors are printed with leading tabs.
+ */
+static void
+pr_fact(BIGNUM *val)
+{
+ const ubig *fact; /* The factor found. */
+
+ /* Firewall - catch 0 and 1. */
+ if (BN_is_zero(val)) /* Historical practice; 0 just exits. */
+ exit(0);
+ if (BN_is_one(val)) {
+ printf("1: 1\n");
+ return;
+ }
+
+ /* Factor value. */
+
+ if (hflag) {
+ fputs("0x", stdout);
+ BN_print_fp(stdout, val);
+ } else
+ BN_print_dec_fp(stdout, val);
+ putchar(':');
+ for (fact = &prime[0]; !BN_is_one(val); ++fact) {
+ /* Look for the smallest factor. */
+ do {
+ if (BN_mod_word(val, (BN_ULONG)*fact) == 0)
+ break;
+ } while (++fact <= pr_limit);
+
+ /* Watch for primes larger than the table. */
+ if (fact > pr_limit) {
+#ifdef HAVE_OPENSSL
+ BIGNUM *bnfact;
+
+ bnfact = BN_new();
+ BN_set_word(bnfact, *(fact - 1));
+ if (!BN_sqr(bnfact, bnfact, ctx))
+ errx(1, "error in BN_sqr()");
+ if (BN_cmp(bnfact, val) > 0 ||
+ BN_check_prime(val, NULL, NULL) == 1)
+ pr_print(val);
+ else
+ pollard_pminus1(val);
+#else
+ pr_print(val);
+#endif
+ break;
+ }
+
+ /* Divide factor out until none are left. */
+ do {
+ printf(hflag ? " 0x%" PRIx64 "" : " %" PRIu64 "", *fact);
+ BN_div_word(val, (BN_ULONG)*fact);
+ } while (BN_mod_word(val, (BN_ULONG)*fact) == 0);
+
+ /* Let the user know we're doing something. */
+ fflush(stdout);
+ }
+ putchar('\n');
+}
+
+static void
+pr_print(BIGNUM *val)
+{
+ if (hflag) {
+ fputs(" 0x", stdout);
+ BN_print_fp(stdout, val);
+ } else {
+ putchar(' ');
+ BN_print_dec_fp(stdout, val);
+ }
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: factor [-h] [value ...]\n");
+ exit(1);
+}
+
+#ifdef HAVE_OPENSSL
+
+/* pollard p-1, algorithm from Jim Gillogly, May 2000 */
+static void
+pollard_pminus1(BIGNUM *val)
+{
+ BIGNUM *base, *rbase, *num, *i, *x;
+
+ base = BN_new();
+ rbase = BN_new();
+ num = BN_new();
+ i = BN_new();
+ x = BN_new();
+
+ BN_set_word(rbase, 1);
+newbase:
+ if (!BN_add_word(rbase, 1))
+ errx(1, "error in BN_add_word()");
+ BN_set_word(i, 2);
+ BN_copy(base, rbase);
+
+ for (;;) {
+ BN_mod_exp(base, base, i, val, ctx);
+ if (BN_is_one(base))
+ goto newbase;
+
+ BN_copy(x, base);
+ BN_sub_word(x, 1);
+ if (!BN_gcd(x, x, val, ctx))
+ errx(1, "error in BN_gcd()");
+
+ if (!BN_is_one(x)) {
+ if (BN_check_prime(x, NULL, NULL) == 1)
+ pr_print(x);
+ else
+ pollard_pminus1(x);
+ fflush(stdout);
+
+ BN_div(num, NULL, val, x, ctx);
+ if (BN_is_one(num))
+ return;
+ if (BN_check_prime(num, NULL, NULL) == 1) {
+ pr_print(num);
+ fflush(stdout);
+ return;
+ }
+ BN_copy(val, num);
+ }
+ if (!BN_add_word(i, 1))
+ errx(1, "error in BN_add_word()");
+ }
+}
+
+/*
+ * Sigh.. No _decimal_ output to file functions in BN.
+ */
+static void
+BN_print_dec_fp(FILE *fp, const BIGNUM *num)
+{
+ char *buf;
+
+ buf = BN_bn2dec(num);
+ if (buf == NULL)
+ return; /* XXX do anything here? */
+ fprintf(fp, "%s", buf);
+ free(buf);
+}
+
+#else
+
+static void
+BN_print_fp(FILE *fp, const BIGNUM *num)
+{
+ fprintf(fp, "%lx", (unsigned long)*num);
+}
+
+static void
+BN_print_dec_fp(FILE *fp, const BIGNUM *num)
+{
+ fprintf(fp, "%lu", (unsigned long)*num);
+}
+
+static int
+BN_dec2bn(BIGNUM **a, const char *str)
+{
+ char *p;
+
+ errno = 0;
+ **a = strtoul(str, &p, 10);
+ return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
+}
+
+static int
+BN_hex2bn(BIGNUM **a, const char *str)
+{
+ char *p;
+
+ errno = 0;
+ **a = strtoul(str, &p, 16);
+ return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
+}
+
+static BN_ULONG
+BN_div_word(BIGNUM *a, BN_ULONG b)
+{
+ BN_ULONG mod;
+
+ mod = *a % b;
+ *a /= b;
+ return mod;
+}
+
+#endif
+
+/*
+ * Scan the string from left-to-right to see if the longest substring
+ * is a valid hexadecimal number.
+ */
+static bool
+is_hex_str(char *str)
+{
+ char c, *p;
+ bool saw_hex = false;
+
+ for (p = str; *p; p++) {
+ if (isdigit(*p))
+ continue;
+ c = tolower(*p);
+ if (c >= 'a' && c <= 'f') {
+ saw_hex = true;
+ continue;
+ }
+ break; /* Not a hexadecimal digit. */
+ }
+ return saw_hex;
+}
+
+/* Convert string pointed to by *str to a bignum. */
+static void
+convert_str2bn(BIGNUM **val, char *p)
+{
+ int n = 0;
+
+ if (*p == '+') p++;
+ if (*p == '-')
+ errx(1, "negative numbers aren't permitted.");
+ if (*p == '0') {
+ p++;
+ if (*p == 'x' || *p == 'X')
+ n = BN_hex2bn(val, ++p);
+ } else {
+ n = is_hex_str(p) ? BN_hex2bn(val, p) : BN_dec2bn(val, p);
+ }
+ if (n == 0)
+ errx(1, "%s: illegal numeric format.", p);
+}
diff --git a/usr.bin/factor/tests/Makefile b/usr.bin/factor/tests/Makefile
new file mode 100644
index 000000000000..f9b13443ae92
--- /dev/null
+++ b/usr.bin/factor/tests/Makefile
@@ -0,0 +1,4 @@
+ATF_TESTS_SH+= factor_tests
+ATF_TESTS_SH+= primes_tests
+
+.include <bsd.test.mk>
diff --git a/usr.bin/factor/tests/factor_tests.sh b/usr.bin/factor/tests/factor_tests.sh
new file mode 100755
index 000000000000..0d9156673582
--- /dev/null
+++ b/usr.bin/factor/tests/factor_tests.sh
@@ -0,0 +1,85 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2023 (C) Enji Cooper
+#
+# 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 AUTHOR 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 AUTHOR 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.
+
+atf_test_case float_non_prime
+float_non_prime_head()
+{
+ atf_set "descr" "Test with a float non-prime number"
+}
+float_non_prime_body()
+{
+ atf_check -o inline:"1: 1\n" factor 1.44
+}
+
+atf_test_case float_prime
+float_prime_head()
+{
+ atf_set "descr" "Test with a float prime number"
+}
+float_prime_body()
+{
+ pi="3.141592653589793238462643383279502884197"
+ atf_check -o inline:"3: 3\n" factor $pi
+}
+
+atf_test_case int_non_prime
+int_non_prime_head()
+{
+ atf_set "descr" "Test with an integral prime number"
+}
+int_non_prime_body()
+{
+ atf_check -o inline:"8: 2 2 2\n" factor 8
+}
+
+atf_test_case int_prime
+int_prime_head()
+{
+ atf_set "descr" "Test with an integral prime number"
+}
+int_prime_body()
+{
+ atf_check -o inline:"31: 31\n" factor 31
+}
+
+atf_test_case negative_numbers_not_allowed
+negative_numbers_not_allowed_head()
+{
+ atf_set "descr" "Verify that negative numbers are not allowed."
+}
+negative_numbers_not_allowed_body()
+{
+ atf_check -s not-exit:0 -e inline:"factor: negative numbers aren't permitted.\n" factor -- -4
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case float_non_prime
+ atf_add_test_case float_prime
+ atf_add_test_case int_non_prime
+ atf_add_test_case int_prime
+ atf_add_test_case negative_numbers_not_allowed
+}
diff --git a/usr.bin/factor/tests/primes_tests.sh b/usr.bin/factor/tests/primes_tests.sh
new file mode 100755
index 000000000000..2b00e9ba34c8
--- /dev/null
+++ b/usr.bin/factor/tests/primes_tests.sh
@@ -0,0 +1,75 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2023 (C) Enji Cooper
+#
+# 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 AUTHOR 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 AUTHOR 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.
+
+atf_test_case invalid_range
+invalid_range_head()
+{
+ atf_set "descr" "Verify that invalid ranges are not allowed."
+}
+invalid_range_body()
+{
+ atf_check -s not-exit:0 -e inline:"primes: start value must be less than stop value.\n" primes -- 2 1
+}
+
+atf_test_case negative_numbers_not_allowed
+negative_numbers_not_allowed_head()
+{
+ atf_set "descr" "Verify that negative numbers are not allowed."
+}
+negative_numbers_not_allowed_body()
+{
+ atf_check -s not-exit:0 -e inline:"primes: negative numbers aren't permitted.\n" primes -- -1 0
+}
+
+atf_test_case no_primes_between_between_20_and_22
+no_primes_between_between_20_and_22_head()
+{
+ atf_set "descr" "Show that no primes exist between [20, 22]."
+}
+
+no_primes_between_between_20_and_22_body()
+{
+ atf_check primes 20 22
+}
+
+atf_test_case primes_in_20_to_50_range
+primes_in_20_to_50_range_head()
+{
+ atf_set "descr" "Find all primes between [20, 50]."
+}
+
+primes_in_20_to_50_range_body()
+{
+ atf_check -o inline:"23\n29\n31\n37\n41\n43\n47\n" primes 20 50
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case invalid_range
+ atf_add_test_case negative_numbers_not_allowed
+ atf_add_test_case no_primes_between_between_20_and_22
+ atf_add_test_case primes_in_20_to_50_range
+}
diff --git a/usr.bin/false/Makefile b/usr.bin/false/Makefile
new file mode 100644
index 000000000000..79221864a4aa
--- /dev/null
+++ b/usr.bin/false/Makefile
@@ -0,0 +1,3 @@
+PROG= false
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/false/Makefile.depend b/usr.bin/false/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/false/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/false/false.1 b/usr.bin/false/false.1
new file mode 100644
index 000000000000..d962ec350db5
--- /dev/null
+++ b/usr.bin/false/false.1
@@ -0,0 +1,60 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 6, 1993
+.Dt FALSE 1
+.Os
+.Sh NAME
+.Nm false
+.Nd return false value
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility always returns with a non-zero exit code.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr sh 1 ,
+.Xr true 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
diff --git a/usr.bin/false/false.c b/usr.bin/false/false.c
new file mode 100644
index 000000000000..2a0129159755
--- /dev/null
+++ b/usr.bin/false/false.c
@@ -0,0 +1,36 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+int
+main(void)
+{
+ return 1;
+}
diff --git a/usr.bin/fetch/Makefile b/usr.bin/fetch/Makefile
new file mode 100644
index 000000000000..a4d501075324
--- /dev/null
+++ b/usr.bin/fetch/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= fetch
+PROG= fetch
+LIBADD= fetch
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fetch/Makefile.depend b/usr.bin/fetch/Makefile.depend
new file mode 100644
index 000000000000..df40deaa3dac
--- /dev/null
+++ b/usr.bin/fetch/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libfetch \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1
new file mode 100644
index 000000000000..7238226998fc
--- /dev/null
+++ b/usr.bin/fetch/fetch.1
@@ -0,0 +1,461 @@
+.\"-
+.\" Copyright (c) 2000-2014 Dag-Erling Smørgrav
+.\" Copyright (c) 2013-2016 Michael Gmelin <freebsd@grem.de>
+.\" All rights reserved.
+.\" Portions Copyright (c) 1999 Massachusetts Institute of Technology; used
+.\" by permission.
+.\"
+.\" 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
+.\" in this position and unchanged.
+.\" 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.
+.\"
+.Dd October 7, 2023
+.Dt FETCH 1
+.Os
+.Sh NAME
+.Nm fetch
+.Nd retrieve a file by Uniform Resource Locator
+.Sh SYNOPSIS
+.Nm
+.Op Fl 146AadFlMmnPpqRrsUv
+.Op Fl B Ar bytes
+.Op Fl -bind-address= Ns Ar host
+.Op Fl -ca-cert= Ns Ar file
+.Op Fl -ca-path= Ns Ar dir
+.Op Fl -cert= Ns Ar file
+.Op Fl -crl= Ns Ar file
+.Op Fl i Ar file
+.Op Fl -key= Ns Ar file
+.Op Fl N Ar file
+.Op Fl -no-passive
+.Op Fl -no-proxy= Ns Ar list
+.Op Fl -no-sslv3
+.Op Fl -no-tlsv1
+.Op Fl -no-verify-hostname
+.Op Fl -no-verify-peer
+.Op Fl o Ar file
+.Op Fl -referer= Ns Ar URL
+.Op Fl S Ar bytes
+.Op Fl T Ar seconds
+.Op Fl -user-agent= Ns Ar agent-string
+.Op Fl w Ar seconds
+.Ar URL ...
+.Nm
+.Op Fl 146AadFlMmnPpqRrsUv
+.Op Fl B Ar bytes
+.Op Fl -bind-address= Ns Ar host
+.Op Fl -ca-cert= Ns Ar file
+.Op Fl -ca-path= Ns Ar dir
+.Op Fl -cert= Ns Ar file
+.Op Fl -crl= Ns Ar file
+.Op Fl i Ar file
+.Op Fl -key= Ns Ar file
+.Op Fl N Ar file
+.Op Fl -no-passive
+.Op Fl -no-proxy= Ns Ar list
+.Op Fl -no-sslv3
+.Op Fl -no-tlsv1
+.Op Fl -no-verify-hostname
+.Op Fl -no-verify-peer
+.Op Fl o Ar file
+.Op Fl -referer= Ns Ar URL
+.Op Fl S Ar bytes
+.Op Fl T Ar seconds
+.Op Fl -user-agent= Ns Ar agent-string
+.Op Fl w Ar seconds
+.Fl h Ar host Fl f Ar file Oo Fl c Ar dir Oc
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a command-line interface to the
+.Xr fetch 3
+library.
+Its purpose is to retrieve the file(s) pointed to by the URL(s) on the
+command line.
+.Pp
+The following options are available:
+.Bl -tag -width Fl
+.It Fl 1 , -one-file
+Stop and return exit code 0 at the first successfully retrieved file.
+.It Fl 4 , -ipv4-only
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6 , -ipv6-only
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl A , -no-redirect
+Do not automatically follow ``temporary'' (302) redirects.
+Some broken Web sites will return a redirect instead of a not-found
+error when the requested object does not exist.
+.It Fl a , -retry
+Automatically retry the transfer upon soft failures.
+.It Fl B Ar bytes , Fl -buffer-size= Ns Ar bytes
+Specify the read buffer size in bytes.
+The default is 16,384 bytes.
+Attempts to set a buffer size lower than this will be silently
+ignored.
+The number of reads actually performed is reported at verbosity level
+two or higher (see the
+.Fl v
+flag).
+.It Fl -bind-address= Ns Ar host
+Specifies a hostname or IP address to which sockets used for outgoing
+connections will be bound.
+.It Fl c Ar dir
+The file to retrieve is in directory
+.Ar dir
+on the remote host.
+This option is deprecated and is provided for backward compatibility
+only.
+.It Fl -ca-cert= Ns Ar file
+[SSL]
+Path to certificate bundle containing trusted CA certificates.
+Otherwise,
+OpenSSL's default CA cert and path settings apply.
+.It Fl -ca-path= Ns Ar dir
+[SSL]
+The directory
+.Ar dir
+contains trusted CA hashes.
+.It Fl -cert= Ns Ar file
+[SSL]
+.Ar file
+is a PEM encoded client certificate/key which will be used in
+client certificate authentication.
+.It Fl -crl= Ns Ar file
+[SSL]
+Points to certificate revocation list
+.Ar file ,
+which has to be in PEM format and may contain peer certificates that have
+been revoked.
+.It Fl d , -direct
+Use a direct connection even if a proxy is configured.
+.It Fl F , -force-restart
+In combination with the
+.Fl r
+flag, forces a restart even if the local and remote files have
+different modification times.
+Implies
+.Fl R .
+.It Fl f Ar file
+The file to retrieve is named
+.Ar file
+on the remote host.
+This option is deprecated and is provided for backward compatibility
+only.
+.It Fl h Ar host
+The file to retrieve is located on the host
+.Ar host .
+This option is deprecated and is provided for backward compatibility
+only.
+.It Fl i Ar file , Fl -if-modified-since= Ns Ar file
+If-Modified-Since mode: the remote file will only be retrieved if it
+is newer than
+.Ar file
+on the local host.
+(HTTP only)
+.It Fl -key= Ns Ar file
+[SSL]
+.Ar file
+is a PEM encoded client key that will be used in client certificate
+authentication in case key and client certificate are stored separately.
+.It Fl l , -symlink
+If the target is a file-scheme URL, make a symbolic link to the target
+rather than trying to copy it.
+.It Fl M
+.It Fl m , -mirror
+Mirror mode: if the file already exists locally and has the same size
+and modification time as the remote file, it will not be fetched.
+Note that the
+.Fl m
+and
+.Fl r
+flags are mutually exclusive.
+.It Fl N Ar file , Fl -netrc= Ns Ar file
+Use
+.Ar file
+instead of
+.Pa ~/.netrc
+to look up login names and passwords for FTP sites.
+See
+.Xr ftp 1
+for a description of the file format.
+This feature is experimental.
+.It Fl n , -no-mtime
+Do not preserve the modification time of the transferred file.
+.It Fl -no-passive
+Forces the FTP code to use active mode.
+.It Fl -no-proxy= Ns Ar list
+Either a single asterisk, which disables the use of proxies
+altogether, or a comma- or whitespace-separated list of hosts for
+which proxies should not be used.
+.It Fl -no-sslv3
+[SSL]
+Do not allow SSL version 3 when negotiating the connection.
+This option is deprecated and is provided for backward compatibility
+only.
+SSLv3 is disabled by default.
+Set
+.Ev SSL_ALLOW_SSL3
+to change this behavior.
+.It Fl -no-tlsv1
+[SSL]
+Do not allow TLS version 1 when negotiating the connection.
+.It Fl -no-verify-hostname
+[SSL]
+Do not verify that the hostname matches the subject of the
+certificate presented by the server.
+.It Fl -no-verify-peer
+[SSL]
+Do not verify the peer certificate against trusted CAs.
+.It Fl o Ar file , Fl -output= Ns Ar file
+Set the output file name to
+.Ar file .
+By default, a ``pathname'' is extracted from the specified URI, and
+its basename is used as the name of the output file.
+A
+.Ar file
+argument of
+.Sq Li \&-
+indicates that results are to be directed to the standard output.
+If the
+.Ar file
+argument is a directory, fetched file(s) will be placed within the
+directory, with name(s) selected as in the default behaviour.
+.It Fl P
+.It Fl p , -passive
+Use passive FTP.
+These flags have no effect, since passive FTP is the default, but are
+provided for compatibility with earlier versions where active FTP was
+the default.
+To force active mode, use the
+.Fl -no-passive
+flag or set the
+.Ev FTP_PASSIVE_MODE
+environment variable to
+.Ql NO .
+.It Fl -referer= Ns Ar URL
+Specifies the referrer URL to use for HTTP requests.
+If
+.Ar URL
+is set to
+.Dq auto ,
+the document URL will be used as referrer URL.
+.It Fl q , -quiet
+Quiet mode.
+.It Fl R , -keep-output
+The output files are precious, and should not be deleted under any
+circumstances, even if the transfer failed or was incomplete.
+.It Fl r , -restart
+Restart a previously interrupted transfer.
+Note that the
+.Fl m
+and
+.Fl r
+flags are mutually exclusive.
+.It Fl S Ar bytes , Fl -require-size= Ns Ar bytes
+Require the file size reported by the server to match the specified
+value.
+If it does not, a message is printed and the file is not fetched.
+If the server does not support reporting file sizes, this option is
+ignored and the file is fetched unconditionally.
+.It Fl s , -print-size
+Print the size in bytes of each requested file, without fetching it.
+.It Fl T Ar seconds , Fl -timeout= Ns Ar seconds
+Set timeout value to
+.Ar seconds .
+Overrides the environment variables
+.Ev FTP_TIMEOUT
+for FTP transfers or
+.Ev HTTP_TIMEOUT
+for HTTP transfers if set.
+.It Fl U , -passive-portrange-default
+When using passive FTP, allocate the port for the data connection from
+the low (default) port range.
+See
+.Xr ip 4
+for details on how to specify which port range this corresponds to.
+.It Fl -user-agent= Ns Ar agent-string
+Specifies the User-Agent string to use for HTTP requests.
+This can be useful when working with HTTP origin or proxy servers that
+differentiate between user agents.
+.It Fl v , -verbose
+Increase verbosity level.
+.It Fl w Ar seconds , Fl -retry-delay= Ns Ar seconds
+When the
+.Fl a
+flag is specified, wait this many seconds between successive retries.
+.El
+.Pp
+If
+.Nm
+receives a
+.Dv SIGINFO
+signal (see the
+.Cm status
+argument for
+.Xr stty 1 ) ,
+the current transfer rate statistics will be written to the
+standard error output, in the same format as the standard completion
+message.
+.Sh ENVIRONMENT
+.Bl -tag -width HTTP_TIMEOUT
+.It Ev FTP_TIMEOUT
+Maximum time, in seconds, to wait before aborting an FTP connection.
+.It Ev HTTP_TIMEOUT
+Maximum time, in seconds, to wait before aborting an HTTP connection.
+.El
+.Pp
+See
+.Xr fetch 3
+for a description of additional environment variables, including
+.Ev FETCH_BIND_ADDRESS ,
+.Ev FTP_LOGIN ,
+.Ev FTP_PASSIVE_MODE ,
+.Ev FTP_PASSWORD ,
+.Ev FTP_PROXY ,
+.Ev ftp_proxy ,
+.Ev HTTP_ACCEPT ,
+.Ev HTTP_AUTH ,
+.Ev HTTP_PROXY ,
+.Ev http_proxy ,
+.Ev HTTP_PROXY_AUTH ,
+.Ev HTTP_REFERER ,
+.Ev HTTP_USER_AGENT ,
+.Ev NETRC ,
+.Ev NO_PROXY ,
+.Ev no_proxy ,
+.Ev SSL_CA_CERT_FILE ,
+.Ev SSL_CA_CERT_PATH ,
+.Ev SSL_CLIENT_CERT_FILE ,
+.Ev SSL_CLIENT_KEY_FILE ,
+.Ev SSL_CRL_FILE ,
+.Ev SSL_ALLOW_SSL3 ,
+.Ev SSL_NO_TLS1 ,
+.Ev SSL_NO_TLS1_1 ,
+.Ev SSL_NO_TLS1_2 ,
+.Ev SSL_NO_VERIFY_HOSTNAME
+and
+.Ev SSL_NO_VERIFY_PEER .
+.Sh EXIT STATUS
+The
+.Nm
+command returns zero on success, or one on failure.
+If multiple URLs are listed on the command line,
+.Nm
+will attempt to retrieve each one of them in turn, and will return
+zero only if they were all successfully retrieved.
+.Pp
+If the
+.Fl i
+argument is used and the remote file is not newer than the
+specified file then the command will still return success,
+although no file is transferred.
+.Sh EXAMPLES
+Silently try to fetch the URLs passed as parameters.
+The first one will fail.
+If the second URL succeeds the third one will not be tried:
+.Bd -literal -offset indent
+$ fetch -1 -q https://www.freebsd.org/bad.html \e
+ ftp.freebsd.org/pub/FreeBSD/README.TXT \e
+ https://www.fake.url
+fetch: https://www.freebsd.org/bad.html: Not Found
+.Ed
+.Pp
+Be verbose when retrieving the
+.Pa README.TXT
+file:
+.Bd -literal -offset indent
+$ fetch -v ftp.freebsd.org/pub/FreeBSD/README.TXT
+resolving server address: ftp.freebsd.org:80
+requesting http://ftp.freebsd.org/pub/FreeBSD/README.TXT
+local size / mtime: 4259 / 1431015519
+remote size / mtime: 4259 / 1431015519
+README.TXT 4259 B 44 MBps 00s
+.Ed
+.Pp
+Quietly save the
+.Pa README.TXT
+file as
+.Pa myreadme.txt
+and do not delete the output file under any circumstances:
+.Bd -literal -offset indent
+fetch -o myreadme.txt -q -R ftp.freebsd.org/pub/FreeBSD/README.TXT
+.Ed
+.Pp
+Print the size of the requested file and identify the request with a custom user
+agent string:
+.Bd -literal -offset indent
+$ fetch -s ftp.freebsd.org/pub/FreeBSD/README.TXT
+--user-agent="Mozilla/5.0 (X11; FreeBSD x86_64; rv:78.0) Gecko/20100101"
+3513231
+.Ed
+.Pp
+Restart the transfer of the
+.Pa README.TXT
+file and retry the transfer upon soft failures:
+.Bd -literal -offset indent
+$ fetch -a -r http://ftp.freebsd.org/pub/FreeBSD/README.TXT
+.Ed
+.Sh SEE ALSO
+.Xr fetch 3 ,
+.Xr phttpget 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 2.1.5 .
+This implementation first appeared in
+.Fx 4.1 .
+.Sh AUTHORS
+.An -nosplit
+The original implementation of
+.Nm
+was done by
+.An Jean-Marc Zucconi Aq Mt jmz@FreeBSD.org .
+It was extensively re-worked for
+.Fx 2.2
+by
+.An Garrett Wollman Aq Mt wollman@FreeBSD.org ,
+and later completely rewritten to use the
+.Xr fetch 3
+library by
+.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org
+and
+.An Michael Gmelin Aq Mt freebsd@grem.de .
+.Sh NOTES
+The
+.Fl b
+and
+.Fl t
+options are no longer supported and will generate warnings.
+They were workarounds for bugs in other OSes which this implementation
+does not trigger.
+.Pp
+One cannot both use the
+.Fl h ,
+.Fl c
+and
+.Fl f
+options and specify URLs on the command line.
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
new file mode 100644
index 000000000000..5e4b14289ca7
--- /dev/null
+++ b/usr.bin/fetch/fetch.c
@@ -0,0 +1,1227 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2000-2014 Dag-Erling Smørgrav
+ * Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
+ * 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
+ * in this position and unchanged.
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <fetch.h>
+
+#define MINBUFSIZE 16384
+#define TIMEOUT 120
+
+/* Option flags */
+static int A_flag; /* -A: do not follow 302 redirects */
+static int a_flag; /* -a: auto retry */
+static off_t B_size; /* -B: buffer size */
+static int b_flag; /*! -b: workaround TCP bug */
+static char *c_dirname; /* -c: remote directory */
+static int d_flag; /* -d: direct connection */
+static int F_flag; /* -F: restart without checking mtime */
+static char *f_filename; /* -f: file to fetch */
+static char *h_hostname; /* -h: host to fetch from */
+static int i_flag; /* -i: specify file for mtime comparison */
+static char *i_filename; /* name of input file */
+static int l_flag; /* -l: link rather than copy file: URLs */
+static int m_flag; /* -[Mm]: mirror mode */
+static char *N_filename; /* -N: netrc file name */
+static int n_flag; /* -n: do not preserve modification time */
+static int o_flag; /* -o: specify output file */
+static int o_directory; /* output file is a directory */
+static char *o_filename; /* name of output file */
+static int o_stdout; /* output file is stdout */
+static int once_flag; /* -1: stop at first successful file */
+static int p_flag; /* -[Pp]: use passive FTP */
+static int R_flag; /* -R: don't delete partial files */
+static int r_flag; /* -r: restart previous transfer */
+static off_t S_size; /* -S: require size to match */
+static int s_flag; /* -s: show size, don't fetch */
+static long T_secs; /* -T: transfer timeout in seconds */
+static int t_flag; /*! -t: workaround TCP bug */
+static int U_flag; /* -U: do not use high ports */
+static int v_level = 1; /* -v: verbosity level */
+static int v_tty; /* stdout is a tty */
+static int v_progress; /* whether to display progress */
+static pid_t pgrp; /* our process group */
+static long w_secs; /* -w: retry delay */
+static int family = PF_UNSPEC; /* -[46]: address family to use */
+
+static int sigalrm; /* SIGALRM received */
+static int siginfo; /* SIGINFO received */
+static int sigint; /* SIGINT received */
+
+static long ftp_timeout = TIMEOUT; /* default timeout for FTP transfers */
+static long http_timeout = TIMEOUT;/* default timeout for HTTP transfers */
+static char *buf; /* transfer buffer */
+
+enum options
+{
+ OPTION_BIND_ADDRESS,
+ OPTION_NO_FTP_PASSIVE_MODE,
+ OPTION_HTTP_REFERER,
+ OPTION_HTTP_USER_AGENT,
+ OPTION_NO_PROXY,
+ OPTION_SSL_CA_CERT_FILE,
+ OPTION_SSL_CA_CERT_PATH,
+ OPTION_SSL_CLIENT_CERT_FILE,
+ OPTION_SSL_CLIENT_KEY_FILE,
+ OPTION_SSL_CRL_FILE,
+ OPTION_SSL_NO_SSL3,
+ OPTION_SSL_NO_TLS1,
+ OPTION_SSL_NO_VERIFY_HOSTNAME,
+ OPTION_SSL_NO_VERIFY_PEER
+};
+
+
+static struct option longopts[] =
+{
+ /* mapping to single character argument */
+ { "one-file", no_argument, NULL, '1' },
+ { "ipv4-only", no_argument, NULL, '4' },
+ { "ipv6-only", no_argument, NULL, '6' },
+ { "no-redirect", no_argument, NULL, 'A' },
+ { "retry", no_argument, NULL, 'a' },
+ { "buffer-size", required_argument, NULL, 'B' },
+ /* -c not mapped, since it's deprecated */
+ { "direct", no_argument, NULL, 'd' },
+ { "force-restart", no_argument, NULL, 'F' },
+ /* -f not mapped, since it's deprecated */
+ /* -h not mapped, since it's deprecated */
+ { "if-modified-since", required_argument, NULL, 'i' },
+ { "symlink", no_argument, NULL, 'l' },
+ /* -M not mapped since it's the same as -m */
+ { "mirror", no_argument, NULL, 'm' },
+ { "netrc", required_argument, NULL, 'N' },
+ { "no-mtime", no_argument, NULL, 'n' },
+ { "output", required_argument, NULL, 'o' },
+ /* -P not mapped since it's the same as -p */
+ { "passive", no_argument, NULL, 'p' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "keep-output", no_argument, NULL, 'R' },
+ { "restart", no_argument, NULL, 'r' },
+ { "require-size", required_argument, NULL, 'S' },
+ { "print-size", no_argument, NULL, 's' },
+ { "timeout", required_argument, NULL, 'T' },
+ { "passive-portrange-default", no_argument, NULL, 'T' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "retry-delay", required_argument, NULL, 'w' },
+
+ /* options without a single character equivalent */
+ { "bind-address", required_argument, NULL, OPTION_BIND_ADDRESS },
+ { "no-passive", no_argument, NULL, OPTION_NO_FTP_PASSIVE_MODE },
+ { "referer", required_argument, NULL, OPTION_HTTP_REFERER },
+ { "user-agent", required_argument, NULL, OPTION_HTTP_USER_AGENT },
+ { "no-proxy", required_argument, NULL, OPTION_NO_PROXY },
+ { "ca-cert", required_argument, NULL, OPTION_SSL_CA_CERT_FILE },
+ { "ca-path", required_argument, NULL, OPTION_SSL_CA_CERT_PATH },
+ { "cert", required_argument, NULL, OPTION_SSL_CLIENT_CERT_FILE },
+ { "key", required_argument, NULL, OPTION_SSL_CLIENT_KEY_FILE },
+ { "crl", required_argument, NULL, OPTION_SSL_CRL_FILE },
+ { "no-sslv3", no_argument, NULL, OPTION_SSL_NO_SSL3 },
+ { "no-tlsv1", no_argument, NULL, OPTION_SSL_NO_TLS1 },
+ { "no-verify-hostname", no_argument, NULL, OPTION_SSL_NO_VERIFY_HOSTNAME },
+ { "no-verify-peer", no_argument, NULL, OPTION_SSL_NO_VERIFY_PEER },
+
+ { NULL, 0, NULL, 0 }
+};
+
+/*
+ * Signal handler
+ */
+static void
+sig_handler(int sig)
+{
+ switch (sig) {
+ case SIGALRM:
+ sigalrm = 1;
+ break;
+ case SIGINFO:
+ siginfo = 1;
+ break;
+ case SIGINT:
+ sigint = 1;
+ break;
+ }
+}
+
+struct xferstat {
+ char name[64];
+ struct timeval start; /* start of transfer */
+ struct timeval last; /* time of last update */
+ struct timeval last2; /* time of previous last update */
+ off_t size; /* size of file per HTTP hdr */
+ off_t offset; /* starting offset in file */
+ off_t rcvd; /* bytes already received */
+ off_t lastrcvd; /* bytes received since last update */
+};
+
+/*
+ * Format a number of seconds as either XXdYYh, XXhYYm, XXmYYs, or XXs
+ * depending on its magnitude
+ */
+static void
+stat_seconds(char *str, size_t strsz, long seconds)
+{
+
+ if (seconds > 86400)
+ snprintf(str, strsz, "%02ldd%02ldh",
+ seconds / 86400, (seconds % 86400) / 3600);
+ else if (seconds > 3600)
+ snprintf(str, strsz, "%02ldh%02ldm",
+ seconds / 3600, (seconds % 3600) / 60);
+ else if (seconds > 60)
+ snprintf(str, strsz, "%02ldm%02lds",
+ seconds / 60, seconds % 60);
+ else
+ snprintf(str, strsz, " %02lds",
+ seconds);
+}
+
+/*
+ * Compute and display ETA
+ */
+static void
+stat_eta(char *str, size_t strsz, const struct xferstat *xs)
+{
+ long elapsed, eta;
+ off_t received, expected;
+
+ elapsed = xs->last.tv_sec - xs->start.tv_sec;
+ received = xs->rcvd - xs->offset;
+ expected = xs->size - xs->rcvd;
+ eta = (long)((double)elapsed * expected / received);
+ if (eta > 0)
+ stat_seconds(str, strsz, eta);
+ else
+ stat_seconds(str, strsz, elapsed);
+}
+
+/*
+ * Format a number as "xxxx YB" where Y is ' ', 'k', 'M'...
+ */
+static const char *prefixes = " kMGTP";
+static void
+stat_bytes(char *str, size_t strsz, off_t bytes)
+{
+ const char *prefix = prefixes;
+
+ while (bytes > 9999 && prefix[1] != '\0') {
+ bytes /= 1024;
+ prefix++;
+ }
+ snprintf(str, strsz, "%4ju %cB", (uintmax_t)bytes, *prefix);
+}
+
+/*
+ * Compute and display transfer rate
+ */
+static void
+stat_bps(char *str, size_t strsz, struct xferstat *xs)
+{
+ char bytes[16];
+ double delta, bps;
+
+ delta = ((double)xs->last.tv_sec + (xs->last.tv_usec / 1.e6))
+ - ((double)xs->last2.tv_sec + (xs->last2.tv_usec / 1.e6));
+
+ if (delta == 0.0) {
+ snprintf(str, strsz, "?? Bps");
+ } else {
+ bps = (xs->rcvd - xs->lastrcvd) / delta;
+ stat_bytes(bytes, sizeof bytes, (off_t)bps);
+ snprintf(str, strsz, "%sps", bytes);
+ }
+}
+
+/*
+ * Update the stats display
+ */
+static void
+stat_display(struct xferstat *xs, int force)
+{
+ char bytes[16], bps[16], eta[16];
+ struct timeval now;
+ int ctty_pgrp;
+
+ /* check if we're the foreground process */
+ if (ioctl(STDERR_FILENO, TIOCGPGRP, &ctty_pgrp) != 0 ||
+ (pid_t)ctty_pgrp != pgrp)
+ return;
+
+ gettimeofday(&now, NULL);
+ if (!force && now.tv_sec <= xs->last.tv_sec)
+ return;
+ xs->last2 = xs->last;
+ xs->last = now;
+
+ fprintf(stderr, "\r%-46.46s", xs->name);
+ if (xs->rcvd >= xs->size) {
+ stat_bytes(bytes, sizeof bytes, xs->rcvd);
+ setproctitle("%s [%s]", xs->name, bytes);
+ fprintf(stderr, " %s", bytes);
+ } else {
+ stat_bytes(bytes, sizeof bytes, xs->size);
+ setproctitle("%s [%d%% of %s]", xs->name,
+ (int)((100.0 * xs->rcvd) / xs->size),
+ bytes);
+ fprintf(stderr, "%3d%% of %s",
+ (int)((100.0 * xs->rcvd) / xs->size),
+ bytes);
+ }
+ if (force == 2) {
+ xs->lastrcvd = xs->offset;
+ xs->last2 = xs->start;
+ }
+ stat_bps(bps, sizeof bps, xs);
+ fprintf(stderr, " %s", bps);
+ if ((xs->size > 0 && xs->rcvd > 0 &&
+ xs->last.tv_sec >= xs->start.tv_sec + 3) ||
+ force == 2) {
+ stat_eta(eta, sizeof eta, xs);
+ fprintf(stderr, " %s", eta);
+ }
+ xs->lastrcvd = xs->rcvd;
+}
+
+/*
+ * Initialize the transfer statistics
+ */
+static void
+stat_start(struct xferstat *xs, const char *name, off_t size, off_t offset)
+{
+
+ memset(xs, 0, sizeof *xs);
+ snprintf(xs->name, sizeof xs->name, "%s", name);
+ gettimeofday(&xs->start, NULL);
+ xs->last2 = xs->last = xs->start;
+ xs->size = size;
+ xs->offset = offset;
+ xs->rcvd = offset;
+ xs->lastrcvd = offset;
+ if (v_progress)
+ stat_display(xs, 1);
+ else if (v_level > 0)
+ fprintf(stderr, "%-46s", xs->name);
+}
+
+/*
+ * Update the transfer statistics
+ */
+static void
+stat_update(struct xferstat *xs, off_t rcvd)
+{
+
+ xs->rcvd = rcvd;
+ if (v_progress)
+ stat_display(xs, 0);
+}
+
+/*
+ * Finalize the transfer statistics
+ */
+static void
+stat_end(struct xferstat *xs)
+{
+ char bytes[16], bps[16], eta[16];
+
+ gettimeofday(&xs->last, NULL);
+ if (v_progress) {
+ stat_display(xs, 2);
+ putc('\n', stderr);
+ } else if (v_level > 0) {
+ stat_bytes(bytes, sizeof bytes, xs->rcvd);
+ stat_bps(bps, sizeof bps, xs);
+ stat_eta(eta, sizeof eta, xs);
+ fprintf(stderr, " %s %s %s\n", bytes, bps, eta);
+ }
+}
+
+/*
+ * Ask the user for authentication details
+ */
+static int
+query_auth(struct url *URL)
+{
+ struct termios tios;
+ tcflag_t saved_flags;
+ int i, nopwd;
+
+ fprintf(stderr, "Authentication required for <%s://%s:%d/>!\n",
+ URL->scheme, URL->host, URL->port);
+
+ fprintf(stderr, "Login: ");
+ if (fgets(URL->user, sizeof URL->user, stdin) == NULL)
+ return (-1);
+ for (i = strlen(URL->user); i >= 0; --i)
+ if (URL->user[i] == '\r' || URL->user[i] == '\n')
+ URL->user[i] = '\0';
+
+ fprintf(stderr, "Password: ");
+ if (tcgetattr(STDIN_FILENO, &tios) == 0) {
+ saved_flags = tios.c_lflag;
+ tios.c_lflag &= ~ECHO;
+ tios.c_lflag |= ECHONL|ICANON;
+ tcsetattr(STDIN_FILENO, TCSAFLUSH|TCSASOFT, &tios);
+ nopwd = (fgets(URL->pwd, sizeof URL->pwd, stdin) == NULL);
+ tios.c_lflag = saved_flags;
+ tcsetattr(STDIN_FILENO, TCSANOW|TCSASOFT, &tios);
+ } else {
+ nopwd = (fgets(URL->pwd, sizeof URL->pwd, stdin) == NULL);
+ }
+ if (nopwd)
+ return (-1);
+ for (i = strlen(URL->pwd); i >= 0; --i)
+ if (URL->pwd[i] == '\r' || URL->pwd[i] == '\n')
+ URL->pwd[i] = '\0';
+
+ return (0);
+}
+
+/*
+ * Fetch a file
+ */
+static int
+fetch(char *URL, const char *path, int *is_http)
+{
+ struct url *url;
+ struct url_stat us;
+ struct stat sb, nsb;
+ struct xferstat xs;
+ FILE *f, *of;
+ size_t size, readcnt, wr;
+ off_t count, size_prev;
+ char flags[8];
+ const char *slash;
+ char *tmppath;
+ int r, tries;
+ unsigned timeout;
+ char *ptr;
+
+ f = of = NULL;
+ tmppath = NULL;
+
+ timeout = 0;
+ *flags = 0;
+ count = 0;
+
+ /* set verbosity level */
+ if (v_level > 1)
+ strcat(flags, "v");
+ if (v_level > 2)
+ fetchDebug = 1;
+
+ /* parse URL */
+ url = NULL;
+ if (*URL == '\0') {
+ warnx("empty URL");
+ goto failure;
+ }
+ if ((url = fetchParseURL(URL)) == NULL) {
+ warnx("%s: parse error", URL);
+ goto failure;
+ }
+
+ /* if no scheme was specified, take a guess */
+ if (!*url->scheme) {
+ if (!*url->host)
+ strcpy(url->scheme, SCHEME_FILE);
+ else if (strncasecmp(url->host, "ftp.", 4) == 0)
+ strcpy(url->scheme, SCHEME_FTP);
+ else if (strncasecmp(url->host, "www.", 4) == 0)
+ strcpy(url->scheme, SCHEME_HTTP);
+ }
+
+ /* for both of http and https */
+ *is_http = strncmp(url->scheme, "http", 4) == 0;
+
+ /* common flags */
+ switch (family) {
+ case PF_INET:
+ strcat(flags, "4");
+ break;
+ case PF_INET6:
+ strcat(flags, "6");
+ break;
+ }
+
+ /* FTP specific flags */
+ if (strcmp(url->scheme, SCHEME_FTP) == 0) {
+ if (p_flag)
+ strcat(flags, "p");
+ if (d_flag)
+ strcat(flags, "d");
+ if (U_flag)
+ strcat(flags, "l");
+ timeout = T_secs ? T_secs : ftp_timeout;
+ }
+
+ /* HTTP specific flags */
+ if (strcmp(url->scheme, SCHEME_HTTP) == 0 ||
+ strcmp(url->scheme, SCHEME_HTTPS) == 0) {
+ if (d_flag)
+ strcat(flags, "d");
+ if (A_flag)
+ strcat(flags, "A");
+ timeout = T_secs ? T_secs : http_timeout;
+ if (i_flag) {
+ if (stat(i_filename, &sb)) {
+ warn("%s: stat()", i_filename);
+ goto failure;
+ }
+ url->ims_time = sb.st_mtime;
+ strcat(flags, "i");
+ }
+ }
+
+ /* set the protocol timeout. */
+ fetchTimeout = timeout;
+
+ /* just print size */
+ if (s_flag) {
+ if (timeout)
+ alarm(timeout);
+ r = fetchStat(url, &us, flags);
+ if (timeout)
+ alarm(0);
+ if (sigalrm || sigint)
+ goto signal;
+ if (r == -1) {
+ warnx("%s", fetchLastErrString);
+ goto failure;
+ }
+ if (us.size == -1)
+ printf("Unknown\n");
+ else
+ printf("%jd\n", (intmax_t)us.size);
+ goto success;
+ }
+
+ tries = 1;
+again:
+ r = 0;
+ /*
+ * If the -r flag was specified, we have to compare the local
+ * and remote files, so we should really do a fetchStat()
+ * first, but I know of at least one HTTP server that only
+ * sends the content size in response to GET requests, and
+ * leaves it out of replies to HEAD requests. Also, in the
+ * (frequent) case that the local and remote files match but
+ * the local file is truncated, we have sufficient information
+ * before the compare to issue a correct request. Therefore,
+ * we always issue a GET request as if we were sure the local
+ * file was a truncated copy of the remote file; we can drop
+ * the connection later if we change our minds.
+ */
+ sb.st_size = -1;
+ if (!o_stdout) {
+ r = stat(path, &sb);
+ if (r == 0 && (r_flag || tries > 1) && S_ISREG(sb.st_mode)) {
+ url->offset = sb.st_size;
+ } else if (r == -1 || !S_ISREG(sb.st_mode)) {
+ /*
+ * Whatever value sb.st_size has now is either
+ * wrong (if stat(2) failed) or irrelevant (if the
+ * path does not refer to a regular file)
+ */
+ sb.st_size = -1;
+ }
+ if (r == -1 && errno != ENOENT) {
+ warnx("%s: stat()", path);
+ goto failure;
+ }
+ }
+ size_prev = sb.st_size;
+
+ /* start the transfer */
+ if (timeout)
+ alarm(timeout);
+ f = fetchXGet(url, &us, flags);
+ if (timeout)
+ alarm(0);
+ if (sigalrm || sigint)
+ goto signal;
+ if (f == NULL) {
+ if (i_flag && *is_http && fetchLastErrCode == FETCH_OK &&
+ strcmp(fetchLastErrString, "Not Modified") == 0) {
+ /* HTTP Not Modified Response, return OK. */
+ if (v_level > 0)
+ warnx("%s: %s", URL, fetchLastErrString);
+ r = 0;
+ goto done;
+ } else {
+ warnx("%s: %s", URL, fetchLastErrString);
+ goto failure;
+ }
+ }
+ if (sigint)
+ goto signal;
+
+ /* check that size is as expected */
+ if (S_size) {
+ if (us.size == -1) {
+ warnx("%s: size unknown", URL);
+ } else if (us.size != S_size) {
+ warnx("%s: size mismatch: expected %jd, actual %jd",
+ URL, (intmax_t)S_size, (intmax_t)us.size);
+ goto failure;
+ }
+ }
+
+ /* symlink instead of copy */
+ if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) {
+ if (symlink(url->doc, path) == -1) {
+ warn("%s: symlink()", path);
+ goto failure;
+ }
+ goto success;
+ }
+
+ if (us.size == -1 && !o_stdout && v_level > 0)
+ warnx("%s: size of remote file is not known", URL);
+ if (v_level > 1) {
+ if (sb.st_size != -1)
+ fprintf(stderr, "local size / mtime: %jd / %ld\n",
+ (intmax_t)sb.st_size, (long)sb.st_mtime);
+ if (us.size != -1)
+ fprintf(stderr, "remote size / mtime: %jd / %ld\n",
+ (intmax_t)us.size, (long)us.mtime);
+ }
+
+ /* open output file */
+ if (o_stdout) {
+ /* output to stdout */
+ of = stdout;
+ } else if (r_flag && sb.st_size != -1) {
+ /* resume mode, local file exists */
+ if (!F_flag && us.mtime && sb.st_mtime != us.mtime && tries == 1) {
+ /* no match! have to refetch */
+ fclose(f);
+ /* if precious, warn the user and give up */
+ if (R_flag) {
+ warnx("%s: local modification time "
+ "does not match remote", path);
+ goto failure_keep;
+ }
+ } else if (url->offset > sb.st_size) {
+ /* gap between what we asked for and what we got */
+ warnx("%s: gap in resume mode", URL);
+ fclose(of);
+ of = NULL;
+ /* picked up again later */
+ } else if (us.size != -1) {
+ if (us.size == sb.st_size)
+ /* nothing to do */
+ goto success;
+ if (sb.st_size > us.size) {
+ /* local file too long! */
+ warnx("%s: local file (%jd bytes) is longer "
+ "than remote file (%jd bytes)", path,
+ (intmax_t)sb.st_size, (intmax_t)us.size);
+ goto failure;
+ }
+ /* we got it, open local file */
+ if ((of = fopen(path, "r+")) == NULL) {
+ warn("%s: fopen()", path);
+ goto failure;
+ }
+ /* check that it didn't move under our feet */
+ if (fstat(fileno(of), &nsb) == -1) {
+ /* can't happen! */
+ warn("%s: fstat()", path);
+ goto failure;
+ }
+ if (nsb.st_dev != sb.st_dev ||
+ nsb.st_ino != sb.st_ino ||
+ nsb.st_size != sb.st_size) {
+ warnx("%s: file has changed", URL);
+ fclose(of);
+ of = NULL;
+ sb = nsb;
+ /* picked up again later */
+ }
+ }
+ /* seek to where we left off */
+ if (of != NULL && fseeko(of, url->offset, SEEK_SET) != 0) {
+ warn("%s: fseeko()", path);
+ fclose(of);
+ of = NULL;
+ /* picked up again later */
+ }
+ } else if (m_flag && sb.st_size != -1) {
+ /* mirror mode, local file exists */
+ if (sb.st_size == us.size && sb.st_mtime == us.mtime)
+ goto success;
+ }
+
+ if (of == NULL) {
+ /*
+ * We don't yet have an output file; either this is a
+ * vanilla run with no special flags, or the local and
+ * remote files didn't match.
+ */
+
+ if (url->offset > 0) {
+ /*
+ * We tried to restart a transfer, but for
+ * some reason gave up - so we have to restart
+ * from scratch if we want the whole file
+ */
+ url->offset = 0;
+ if ((f = fetchXGet(url, &us, flags)) == NULL) {
+ warnx("%s: %s", URL, fetchLastErrString);
+ goto failure;
+ }
+ if (sigint)
+ goto signal;
+ }
+
+ /* construct a temp file name */
+ if (sb.st_size != -1 && S_ISREG(sb.st_mode)) {
+ if ((slash = strrchr(path, '/')) == NULL)
+ slash = path;
+ else
+ ++slash;
+ if(tmppath != NULL)
+ free(tmppath);
+ asprintf(&tmppath, "%.*s.fetch.XXXXXX.%s",
+ (int)(slash - path), path, slash);
+ if (tmppath != NULL) {
+ if (mkstemps(tmppath, strlen(slash) + 1) == -1) {
+ warn("%s: mkstemps()", path);
+ goto failure;
+ }
+ of = fopen(tmppath, "w");
+ chown(tmppath, sb.st_uid, sb.st_gid);
+ chmod(tmppath, sb.st_mode & ALLPERMS);
+ }
+ }
+ if (of == NULL)
+ of = fopen(path, "w");
+ if (of == NULL) {
+ warn("%s: open()", path);
+ goto failure;
+ }
+ }
+ count = url->offset;
+
+ /* start the counter */
+ stat_start(&xs, path, us.size, count);
+
+ sigalrm = siginfo = sigint = 0;
+
+ /* suck in the data */
+ setvbuf(f, NULL, _IOFBF, B_size);
+ signal(SIGINFO, sig_handler);
+ while (!sigint) {
+ if (us.size != -1 && us.size - count < B_size &&
+ us.size - count >= 0)
+ size = us.size - count;
+ else
+ size = B_size;
+ if (siginfo) {
+ stat_end(&xs);
+ siginfo = 0;
+ }
+
+ if (size == 0)
+ break;
+
+ if ((readcnt = fread(buf, 1, size, f)) < size) {
+ if (ferror(f) && errno == EINTR && !sigint)
+ clearerr(f);
+ else if (readcnt == 0)
+ break;
+ }
+
+ stat_update(&xs, count += readcnt);
+ for (ptr = buf; readcnt > 0; ptr += wr, readcnt -= wr)
+ if ((wr = fwrite(ptr, 1, readcnt, of)) < readcnt) {
+ if (ferror(of) && errno == EINTR && !sigint)
+ clearerr(of);
+ else
+ break;
+ }
+ if (readcnt != 0)
+ break;
+ }
+ if (!sigalrm)
+ sigalrm = ferror(f) && errno == ETIMEDOUT;
+ signal(SIGINFO, SIG_DFL);
+
+ stat_end(&xs);
+
+ /*
+ * If the transfer timed out or was interrupted, we still want to
+ * set the mtime in case the file is not removed (-r or -R) and
+ * the user later restarts the transfer.
+ */
+ signal:
+ /* set mtime of local file */
+ if (!n_flag && us.mtime && !o_stdout && of != NULL &&
+ (stat(path, &sb) != -1) && sb.st_mode & S_IFREG) {
+ struct timeval tv[2];
+
+ fflush(of);
+ tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime);
+ tv[1].tv_sec = (long)us.mtime;
+ tv[0].tv_usec = tv[1].tv_usec = 0;
+ if (utimes(tmppath ? tmppath : path, tv))
+ warn("%s: utimes()", tmppath ? tmppath : path);
+ }
+
+ /* timed out or interrupted? */
+ if (sigalrm)
+ warnx("transfer timed out");
+ if (sigint) {
+ warnx("transfer interrupted");
+ goto failure;
+ }
+
+ /* timeout / interrupt before connection completley established? */
+ if (f == NULL)
+ goto failure;
+
+ if (!sigalrm) {
+ /* check the status of our files */
+ if (ferror(f))
+ warn("%s", URL);
+ if (ferror(of))
+ warn("%s", path);
+ if (ferror(f) || ferror(of))
+ goto failure;
+ }
+
+ /* did the transfer complete normally? */
+ if (us.size != -1 && count < us.size) {
+ warnx("%s appears to be truncated: %jd/%jd bytes",
+ path, (intmax_t)count, (intmax_t)us.size);
+ if(!o_stdout && a_flag && count > size_prev) {
+ fclose(f);
+ if (w_secs)
+ sleep(w_secs);
+ tries++;
+ goto again;
+ }
+ goto failure_keep;
+ }
+
+ /*
+ * If the transfer timed out and we didn't know how much to
+ * expect, assume the worst (i.e. we didn't get all of it)
+ */
+ if (sigalrm && us.size == -1) {
+ warnx("%s may be truncated", path);
+ goto failure_keep;
+ }
+
+ success:
+ r = 0;
+ if (tmppath != NULL && rename(tmppath, path) == -1) {
+ warn("%s: rename()", path);
+ goto failure_keep;
+ }
+ goto done;
+ failure:
+ if (of && of != stdout && !R_flag && !r_flag)
+ if (stat(path, &sb) != -1 && (sb.st_mode & S_IFREG))
+ unlink(tmppath ? tmppath : path);
+ if (R_flag && tmppath != NULL && sb.st_size == -1)
+ rename(tmppath, path); /* ignore errors here */
+ failure_keep:
+ r = -1;
+ goto done;
+ done:
+ if (f)
+ fclose(f);
+ if (of && of != stdout)
+ fclose(of);
+ if (url)
+ fetchFreeURL(url);
+ if (tmppath != NULL)
+ free(tmppath);
+ return (r);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [--bind-address=host]",
+" [--ca-cert=file] [--ca-path=dir] [--cert=file] [--crl=file]",
+" [-i file] [--key=file] [-N file] [--no-passive] [--no-proxy=list]",
+" [--no-sslv3] [--no-tlsv1] [--no-verify-hostname] [--no-verify-peer]",
+" [-o file] [--referer=URL] [-S bytes] [-T seconds]",
+" [--user-agent=agent-string] [-w seconds] URL ...",
+" fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [--bind-address=host]",
+" [--ca-cert=file] [--ca-path=dir] [--cert=file] [--crl=file]",
+" [-i file] [--key=file] [-N file] [--no-passive] [--no-proxy=list]",
+" [--no-sslv3] [--no-tlsv1] [--no-verify-hostname] [--no-verify-peer]",
+" [-o file] [--referer=URL] [-S bytes] [-T seconds]",
+" [--user-agent=agent-string] [-w seconds] -h host -f file [-c dir]");
+}
+
+
+/*
+ * Entry point
+ */
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ struct sigaction sa;
+ const char *p, *s;
+ char *end, *q;
+ int c, e, is_http, r;
+
+
+ while ((c = getopt_long(argc, argv,
+ "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:",
+ longopts, NULL)) != -1)
+ switch (c) {
+ case '1':
+ once_flag = 1;
+ break;
+ case '4':
+ family = PF_INET;
+ break;
+ case '6':
+ family = PF_INET6;
+ break;
+ case 'A':
+ A_flag = 1;
+ break;
+ case 'a':
+ a_flag = 1;
+ break;
+ case 'B':
+ B_size = (off_t)strtol(optarg, &end, 10);
+ if (*optarg == '\0' || *end != '\0')
+ errx(1, "invalid buffer size (%s)", optarg);
+ break;
+ case 'b':
+ warnx("warning: the -b option is deprecated");
+ b_flag = 1;
+ break;
+ case 'c':
+ c_dirname = optarg;
+ break;
+ case 'd':
+ d_flag = 1;
+ break;
+ case 'F':
+ F_flag = 1;
+ break;
+ case 'f':
+ f_filename = optarg;
+ break;
+ case 'H':
+ warnx("the -H option is now implicit, "
+ "use -U to disable");
+ break;
+ case 'h':
+ h_hostname = optarg;
+ break;
+ case 'i':
+ i_flag = 1;
+ i_filename = optarg;
+ break;
+ case 'l':
+ l_flag = 1;
+ break;
+ case 'o':
+ o_flag = 1;
+ o_filename = optarg;
+ break;
+ case 'M':
+ case 'm':
+ if (r_flag)
+ errx(1, "the -m and -r flags "
+ "are mutually exclusive");
+ m_flag = 1;
+ break;
+ case 'N':
+ N_filename = optarg;
+ break;
+ case 'n':
+ n_flag = 1;
+ break;
+ case 'P':
+ case 'p':
+ p_flag = 1;
+ break;
+ case 'q':
+ v_level = 0;
+ break;
+ case 'R':
+ R_flag = 1;
+ break;
+ case 'r':
+ if (m_flag)
+ errx(1, "the -m and -r flags "
+ "are mutually exclusive");
+ r_flag = 1;
+ break;
+ case 'S':
+ S_size = strtoll(optarg, &end, 10);
+ if (*optarg == '\0' || *end != '\0')
+ errx(1, "invalid size (%s)", optarg);
+ break;
+ case 's':
+ s_flag = 1;
+ break;
+ case 'T':
+ T_secs = strtol(optarg, &end, 10);
+ if (*optarg == '\0' || *end != '\0')
+ errx(1, "invalid timeout (%s)", optarg);
+ break;
+ case 't':
+ t_flag = 1;
+ warnx("warning: the -t option is deprecated");
+ break;
+ case 'U':
+ U_flag = 1;
+ break;
+ case 'v':
+ v_level++;
+ break;
+ case 'w':
+ a_flag = 1;
+ w_secs = strtol(optarg, &end, 10);
+ if (*optarg == '\0' || *end != '\0')
+ errx(1, "invalid delay (%s)", optarg);
+ break;
+ case OPTION_BIND_ADDRESS:
+ setenv("FETCH_BIND_ADDRESS", optarg, 1);
+ break;
+ case OPTION_NO_FTP_PASSIVE_MODE:
+ setenv("FTP_PASSIVE_MODE", "no", 1);
+ break;
+ case OPTION_HTTP_REFERER:
+ setenv("HTTP_REFERER", optarg, 1);
+ break;
+ case OPTION_HTTP_USER_AGENT:
+ setenv("HTTP_USER_AGENT", optarg, 1);
+ break;
+ case OPTION_NO_PROXY:
+ setenv("NO_PROXY", optarg, 1);
+ break;
+ case OPTION_SSL_CA_CERT_FILE:
+ setenv("SSL_CA_CERT_FILE", optarg, 1);
+ break;
+ case OPTION_SSL_CA_CERT_PATH:
+ setenv("SSL_CA_CERT_PATH", optarg, 1);
+ break;
+ case OPTION_SSL_CLIENT_CERT_FILE:
+ setenv("SSL_CLIENT_CERT_FILE", optarg, 1);
+ break;
+ case OPTION_SSL_CLIENT_KEY_FILE:
+ setenv("SSL_CLIENT_KEY_FILE", optarg, 1);
+ break;
+ case OPTION_SSL_CRL_FILE:
+ setenv("SSL_CRL_FILE", optarg, 1);
+ break;
+ case OPTION_SSL_NO_SSL3:
+ setenv("SSL_NO_SSL3", "", 1);
+ break;
+ case OPTION_SSL_NO_TLS1:
+ setenv("SSL_NO_TLS1", "", 1);
+ break;
+ case OPTION_SSL_NO_VERIFY_HOSTNAME:
+ setenv("SSL_NO_VERIFY_HOSTNAME", "", 1);
+ break;
+ case OPTION_SSL_NO_VERIFY_PEER:
+ setenv("SSL_NO_VERIFY_PEER", "", 1);
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (h_hostname || f_filename || c_dirname) {
+ if (!h_hostname || !f_filename || argc) {
+ usage();
+ exit(1);
+ }
+ /* XXX this is a hack. */
+ if (strcspn(h_hostname, "@:/") != strlen(h_hostname))
+ errx(1, "invalid hostname");
+ if (asprintf(argv, "ftp://%s/%s/%s", h_hostname,
+ c_dirname ? c_dirname : "", f_filename) == -1)
+ errx(1, "%s", strerror(ENOMEM));
+ argc++;
+ }
+
+ if (!argc) {
+ usage();
+ exit(1);
+ }
+
+ /* allocate buffer */
+ if (B_size < MINBUFSIZE)
+ B_size = MINBUFSIZE;
+ if ((buf = malloc(B_size)) == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+
+ /* timeouts */
+ if ((s = getenv("FTP_TIMEOUT")) != NULL) {
+ ftp_timeout = strtol(s, &end, 10);
+ if (*s == '\0' || *end != '\0' || ftp_timeout < 0) {
+ warnx("FTP_TIMEOUT (%s) is not a positive integer", s);
+ ftp_timeout = 0;
+ }
+ }
+ if ((s = getenv("HTTP_TIMEOUT")) != NULL) {
+ http_timeout = strtol(s, &end, 10);
+ if (*s == '\0' || *end != '\0' || http_timeout < 0) {
+ warnx("HTTP_TIMEOUT (%s) is not a positive integer", s);
+ http_timeout = 0;
+ }
+ }
+
+ /* signal handling */
+ sa.sa_flags = 0;
+ sa.sa_handler = sig_handler;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGALRM, &sa, NULL);
+ sa.sa_flags = SA_RESETHAND;
+ sigaction(SIGINT, &sa, NULL);
+ fetchRestartCalls = 0;
+
+ /* output file */
+ if (o_flag) {
+ if (strcmp(o_filename, "-") == 0) {
+ o_stdout = 1;
+ } else if (stat(o_filename, &sb) == -1) {
+ if (errno == ENOENT) {
+ if (argc > 1)
+ errx(1, "%s is not a directory",
+ o_filename);
+ } else {
+ err(1, "%s", o_filename);
+ }
+ } else {
+ if (sb.st_mode & S_IFDIR)
+ o_directory = 1;
+ }
+ }
+
+ /* check if output is to a tty (for progress report) */
+ v_tty = isatty(STDERR_FILENO);
+ v_progress = v_tty && v_level > 0;
+ if (v_progress)
+ pgrp = getpgrp();
+
+ r = 0;
+
+ /* authentication */
+ if (v_tty)
+ fetchAuthMethod = query_auth;
+ if (N_filename != NULL)
+ if (setenv("NETRC", N_filename, 1) == -1)
+ err(1, "setenv: cannot set NETRC=%s", N_filename);
+
+ while (argc) {
+ if ((p = strrchr(*argv, '/')) == NULL)
+ p = *argv;
+ else
+ p++;
+
+ if (!*p)
+ p = "fetch.out";
+
+ fetchLastErrCode = 0;
+
+ if (o_flag) {
+ if (o_stdout) {
+ e = fetch(*argv, "-", &is_http);
+ } else if (o_directory) {
+ asprintf(&q, "%s/%s", o_filename, p);
+ e = fetch(*argv, q, &is_http);
+ free(q);
+ } else {
+ e = fetch(*argv, o_filename, &is_http);
+ }
+ } else {
+ e = fetch(*argv, p, &is_http);
+ }
+
+ if (sigint)
+ kill(getpid(), SIGINT);
+
+ if (e == 0 && once_flag)
+ exit(0);
+
+ if (e) {
+ r = 1;
+ if ((fetchLastErrCode
+ && fetchLastErrCode != FETCH_AUTH
+ && fetchLastErrCode != FETCH_UNAVAIL
+ && fetchLastErrCode != FETCH_MOVED
+ && fetchLastErrCode != FETCH_URL
+ && fetchLastErrCode != FETCH_RESOLV
+ && fetchLastErrCode != FETCH_UNKNOWN
+ && (!is_http || (
+ fetchLastErrCode != FETCH_PROTO
+ && fetchLastErrCode != FETCH_SERVER
+ && fetchLastErrCode != FETCH_TEMP
+ && fetchLastErrCode != FETCH_TIMEOUT
+ )))) {
+ if (w_secs && v_level)
+ fprintf(stderr, "Waiting %ld seconds "
+ "before retrying\n", w_secs);
+ if (w_secs)
+ sleep(w_secs);
+ if (a_flag)
+ continue;
+ }
+ }
+
+ argc--, argv++;
+ }
+
+ exit(r);
+}
diff --git a/usr.bin/file/Makefile b/usr.bin/file/Makefile
new file mode 100644
index 000000000000..bfea23feca88
--- /dev/null
+++ b/usr.bin/file/Makefile
@@ -0,0 +1,52 @@
+# Makefile for file(1) cmd.
+# Copyright (c) David E. O'Brien, 2000-2004, 2009
+# Copyright (c) Ian F. Darwin 86/09/01 - see LEGAL.NOTICE.
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or of the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+#
+# 1. The author is not responsible for the consequences of use of this
+# software, no matter how awful, even if they arise from flaws in it.
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Since few users ever read sources,
+# credits must appear in the documentation.
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software. Since few users
+# ever read sources, credits must appear in the documentation.
+# 4. This notice may not be removed or altered.
+
+.include <src.opts.mk>
+
+SRCDIR= ${SRCTOP}/contrib/file
+.PATH: ${SRCDIR}/src
+.PATH: ${SRCDIR}/doc
+
+PROG= file
+
+MAGICPATH?= /usr/share/misc
+
+CFLAGS+= -DMAGIC='"${MAGICPATH}/magic"' -DHAVE_CONFIG_H
+CFLAGS+= -I${SRCTOP}/lib/libmagic
+
+LIBADD= magic
+
+FILEVER!= awk '$$1 == "\#define" && $$2 == "VERSION" { print $$3; exit }' \
+ ${SRCTOP}/lib/libmagic/config.h
+
+CLEANFILES+= ${MAN}
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
+
+.for mp in ${MAN}
+${mp}: ${mp:C/[0-9]/man/}
+ sed -e 's/__FSECTION__/5/g' -e 's/__CSECTION__/1/g' \
+ -e 's/__VERSION__/${FILEVER}/g' \
+ -e 's,__MAGIC__,${MAGICPATH}/magic,g' ${.ALLSRC} > ${.TARGET}
+.endfor
diff --git a/usr.bin/file/Makefile.depend b/usr.bin/file/Makefile.depend
new file mode 100644
index 000000000000..7c3d07226de4
--- /dev/null
+++ b/usr.bin/file/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libmagic \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/file/tests/Makefile b/usr.bin/file/tests/Makefile
new file mode 100644
index 000000000000..cd3d00ae742c
--- /dev/null
+++ b/usr.bin/file/tests/Makefile
@@ -0,0 +1,8 @@
+PACKAGE= tests
+ATF_TESTS_SH= file_test
+
+SRCDIR= ${SRCTOP}/contrib/file/tests
+_files!= echo ${SRCDIR}/*.testfile ${SRCDIR}/*.flags ${SRCDIR}/*.result ${SRCDIR}/*.magic
+${PACKAGE}FILES+=${_files}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/file/tests/Makefile.depend b/usr.bin/file/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/file/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/file/tests/file_test.sh b/usr.bin/file/tests/file_test.sh
new file mode 100644
index 000000000000..490274c05892
--- /dev/null
+++ b/usr.bin/file/tests/file_test.sh
@@ -0,0 +1,65 @@
+#!/usr/libexec/atf-sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022 Eric van Gyzen
+#
+# 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 AUTHOR 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 AUTHOR 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.
+
+atf_test_case contrib_file_tests cleanup
+contrib_file_tests_body() {
+ srcdir="$(atf_get_srcdir)"
+
+ for testfile in "${srcdir}"/*.testfile; do
+ test_name="${testfile%.testfile}"
+ result_file="${test_name}.result"
+ file_args=
+ magic_files=
+ for magic_file in ${test_name}*.magic; do
+ if [ -f "${magic_file}" ]; then
+ if [ -z "${magic_files}" ]; then
+ magic_files="${magic_file}"
+ else
+ magic_files="${magic_files}:${magic_file}"
+ fi
+ fi
+ done
+ if [ -z "${magic_files}" ]; then
+ magic_files=/usr/share/misc/magic
+ fi
+ if [ -f "${test_name}.flags" ]; then
+ file_args="${file_args} -$(cat "${test_name}.flags")"
+ fi
+ # The result files were created in UTC.
+ atf_check -o save:actual_output -e ignore env TZ=Z MAGIC="${magic_files}" \
+ file ${file_args} --brief "$testfile"
+ atf_check cmp actual_output "$result_file"
+ done
+}
+
+contrib_file_tests_cleanup() {
+ rm -f actual_output trimmed_output
+}
+
+atf_init_test_cases() {
+ atf_add_test_case contrib_file_tests
+}
diff --git a/usr.bin/file2c/Makefile b/usr.bin/file2c/Makefile
new file mode 100644
index 000000000000..b71834e10035
--- /dev/null
+++ b/usr.bin/file2c/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= file2c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/file2c/Makefile.depend b/usr.bin/file2c/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/file2c/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/file2c/Makefile.depend.host b/usr.bin/file2c/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/file2c/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/file2c/Makefile.depend.options b/usr.bin/file2c/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/file2c/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/file2c/file2c.1 b/usr.bin/file2c/file2c.1
new file mode 100644
index 000000000000..52cbe00ab00a
--- /dev/null
+++ b/usr.bin/file2c/file2c.1
@@ -0,0 +1,73 @@
+.\"----------------------------------------------------------------------------
+.\" "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
+.\" ---------------------------------------------------------------------------
+.\"
+.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/usr.bin/file2c/file2c.c b/usr.bin/file2c/file2c.c
new file mode 100644
index 000000000000..3f9b81aaf834
--- /dev/null
+++ b/usr.bin/file2c/file2c.c
@@ -0,0 +1,90 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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>
+#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",
+ getprogname());
+ 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/usr.bin/file2c/tests/Makefile b/usr.bin/file2c/tests/Makefile
new file mode 100644
index 000000000000..f54e3c5cf275
--- /dev/null
+++ b/usr.bin/file2c/tests/Makefile
@@ -0,0 +1,17 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.1.out
+${PACKAGE}FILES+= regress.2.out
+${PACKAGE}FILES+= regress.3.out
+${PACKAGE}FILES+= regress.4.out
+${PACKAGE}FILES+= regress.5.out
+${PACKAGE}FILES+= regress.6.out
+${PACKAGE}FILES+= regress.7.out
+${PACKAGE}FILES+= regress.8.out
+${PACKAGE}FILES+= regress.9.out
+${PACKAGE}FILES+= regress.in
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/file2c/tests/Makefile.depend b/usr.bin/file2c/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/file2c/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/file2c/tests/legacy_test.sh b/usr.bin/file2c/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/file2c/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/file2c/tests/regress.1.out b/usr.bin/file2c/tests/regress.1.out
new file mode 100644
index 000000000000..6b760fecc10a
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.1.out
@@ -0,0 +1 @@
+175,212,59,239,227,234,192,22,186,113,52,204,195
diff --git a/usr.bin/file2c/tests/regress.2.out b/usr.bin/file2c/tests/regress.2.out
new file mode 100644
index 000000000000..07acb2138f58
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.2.out
@@ -0,0 +1,3 @@
+PREFIX
+175,212,59,239,227,234,192,22,186,113,52,204,195,81,240,223,173,115,109,
+102,175,183,24,185,173,137
diff --git a/usr.bin/file2c/tests/regress.3.out b/usr.bin/file2c/tests/regress.3.out
new file mode 100644
index 000000000000..55502dfb4355
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.3.out
@@ -0,0 +1,5 @@
+PREFIX
+175,212,59,239,227,234,192,22,186,113,52,204,195,81,240,223,173,115,109,
+102,175,183,24,185,173,137,107,116,77,142,217,172,196,45,62,228,41,174,
+134
+SUFFIX
diff --git a/usr.bin/file2c/tests/regress.4.out b/usr.bin/file2c/tests/regress.4.out
new file mode 100644
index 000000000000..dc21fd010b94
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.4.out
@@ -0,0 +1,4 @@
+0xaf,0xd4,0x3b,0xef,0xe3,0xea,0xc0,0x16,0xba,0x71,0x34,0xcc,0xc3,0x51,0xf0,
+0xdf,0xad,0x73,0x6d,0x66,0xaf,0xb7,0x18,0xb9,0xad,0x89,0x6b,0x74,0x4d,0x8e,
+0xd9,0xac,0xc4,0x2d,0x3e,0xe4,0x29,0xae,0x86,0x36,0xbb,0xe7,0x35,0x7c,0x92,
+0x88,0xcb,0x34,0x5b,0xae,0xd4,0x73
diff --git a/usr.bin/file2c/tests/regress.5.out b/usr.bin/file2c/tests/regress.5.out
new file mode 100644
index 000000000000..8210ab5ca3a4
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.5.out
@@ -0,0 +1 @@
+175,212,59,239,227,234,192,22,186,113,52,204,195,81,240,223,173,115,109,102,175,183,24,185,173,137,107,116,77,142,217,172,196,45,62,228,41,174,134,54,187,231,53,124,146,136,203,52,91,174,212,115,254,86,214,31,196,19,159,213,217,170,247,32,69
diff --git a/usr.bin/file2c/tests/regress.6.out b/usr.bin/file2c/tests/regress.6.out
new file mode 100644
index 000000000000..0f2bb747baf2
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.6.out
@@ -0,0 +1,9 @@
+P
+175,
+212,
+59,
+239,
+227,
+234,
+192
+S
diff --git a/usr.bin/file2c/tests/regress.7.out b/usr.bin/file2c/tests/regress.7.out
new file mode 100644
index 000000000000..f94ac55e7db7
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.7.out
@@ -0,0 +1,8 @@
+P S
+0xaf,0xd4,
+0x3b,0xef,
+0xe3,0xea,
+0xc0,0x16,
+0xba,0x71,
+0x34,0xcc,
+0xc3,0x51
diff --git a/usr.bin/file2c/tests/regress.8.out b/usr.bin/file2c/tests/regress.8.out
new file mode 100644
index 000000000000..5f5ce9de5a43
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.8.out
@@ -0,0 +1,4 @@
+P
+175,212,59,239,227,234,192,22,186,113,52,204,195,81,240,223,
+173,115,109,102,175
+-x
diff --git a/usr.bin/file2c/tests/regress.9.out b/usr.bin/file2c/tests/regress.9.out
new file mode 100644
index 000000000000..91f5e00860b7
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.9.out
@@ -0,0 +1,104 @@
+const char data[] = {
+175,212,59,239,227,234,192,22,186,113,52,204,195,81,240,223,173,115,109,
+102,175,183,24,185,173,137,107,116,77,142,217,172,196,45,62,228,41,174,
+134,54,187,231,53,124,146,136,203,52,91,174,212,115,254,86,214,31,196,19,
+159,213,217,170,247,32,69,15,231,52,136,125,195,84,63,231,94,73,173,8,93,
+21,246,118,130,218,200,68,1,213,178,88,162,39,161,153,54,177,161,114,188,
+55,163,166,158,218,151,163,44,7,42,25,221,143,194,40,129,228,100,128,87,
+22,76,210,109,149,64,61,169,252,1,10,61,78,17,233,29,222,247,155,156,34,
+151,186,171,39,111,169,87,194,186,102,95,11,205,207,209,111,83,167,166,
+29,172,60,135,178,208,166,219,38,228,105,200,239,180,184,232,11,1,81,233,
+107,45,73,109,94,17,10,51,91,47,89,38,253,42,224,111,143,244,243,132,225,
+236,187,30,9,241,233,210,161,200,236,249,21,197,176,161,185,240,15,155,
+73,244,186,255,214,180,122,15,206,205,35,217,58,112,50,82,199,35,150,232,
+96,54,67,77,248,243,17,96,131,221,212,44,236,137,88,213,20,21,87,89,238,
+199,156,82,77,167,123,2,92,199,167,190,74,59,80,50,196,105,153,40,27,93,
+170,194,85,110,39,185,21,155,221,105,44,156,220,30,29,17,220,26,54,30,167,
+42,77,239,74,240,203,94,63,221,148,49,14,107,117,66,1,105,243,79,165,175,
+174,213,130,57,187,168,91,229,107,49,55,120,144,120,93,89,120,60,127,84,
+152,194,184,102,115,33,8,221,63,46,181,152,83,62,45,231,162,173,228,103,
+103,116,248,51,141,21,236,8,30,123,30,234,59,188,86,232,101,106,153,116,
+200,64,175,52,18,186,152,60,255,171,132,173,173,176,60,246,21,85,51,240,
+237,224,250,22,33,89,89,204,108,107,121,119,120,215,207,179,181,142,127,
+78,131,95,195,100,48,166,135,170,195,247,111,185,202,47,151,74,62,32,174,
+242,230,104,193,252,28,115,187,212,110,41,39,170,27,167,229,36,31,192,214,
+209,35,149,83,44,7,74,16,6,162,164,171,21,48,68,19,137,29,115,225,31,97,
+226,39,220,241,118,3,172,249,17,144,45,171,247,34,124,160,136,171,7,165,
+127,186,207,150,30,115,162,6,75,153,114,65,146,59,93,162,184,197,81,160,
+173,244,205,8,84,76,85,214,195,73,70,6,38,135,198,111,48,242,129,24,202,
+183,227,77,62,92,136,58,149,235,155,34,100,63,248,185,247,103,12,117,135,
+218,116,114,185,35,11,178,217,192,11,184,239,201,107,24,187,32,183,149,
+180,103,191,36,72,152,129,204,108,46,14,187,236,222,134,28,158,81,41,15,
+83,148,165,165,16,50,134,119,162,211,103,6,28,182,225,13,67,165,25,110,
+51,141,158,80,112,27,2,163,34,96,55,223,171,108,115,119,191,29,45,48,176,
+93,63,123,252,132,121,238,116,180,217,185,178,213,86,194,197,122,13,159,
+70,109,151,247,182,134,65,76,155,189,174,220,28,38,253,222,56,102,50,221,
+183,255,234,113,240,24,149,76,227,18,188,10,201,110,148,51,108,253,37,32,
+192,136,135,149,253,77,23,99,213,12,35,25,219,234,9,251,145,90,23,111,223,
+251,54,16,217,91,116,214,175,95,87,116,228,191,226,227,72,67,72,227,52,
+91,237,107,6,20,30,67,179,215,177,9,138,235,14,83,23,37,127,111,36,122,
+165,179,81,247,230,81,106,89,85,62,188,48,49,122,155,172,71,129,167,98,
+25,108,23,89,100,251,85,108,114,163,179,40,40,129,67,78,165,71,126,55,35,
+108,168,86,141,242,16,178,196,234,255,243,10,170,84,201,160,243,153,12,
+246,112,87,172,229,154,154,231,225,154,62,78,50,100,211,194,225,50,14,134,
+198,5,48,174,154,213,62,249,2,77,18,179,154,27,244,32,44,73,74,150,48,103,
+186,212,126,48,213,41,240,21,209,94,239,111,157,235,120,194,179,15,45,110,
+74,114,107,248,124,221,42,1,248,115,14,20,76,219,51,178,87,83,74,81,179,
+10,188,233,36,90,123,175,106,85,72,85,247,247,150,22,127,238,219,156,230,
+141,108,80,92,226,205,250,61,57,23,128,120,138,195,61,50,48,40,89,57,0,
+108,138,179,29,182,118,58,232,220,199,228,56,184,194,86,244,239,16,198,
+172,248,114,100,209,210,74,246,210,215,83,149,65,151,36,215,64,148,13,198,
+151,160,109,43,109,176,149,187,55,216,239,227,157,71,1,137,235,100,30,155,
+160,6,153,19,17,57,45,17,211,240,230,117,98,228,16,148,211,217,183,210,
+224,126,134,129,133,59,238,108,128,55,9,53,63,209,219,15,241,210,179,126,
+209,237,226,31,168,14,244,84,15,178,156,207,52,183,238,75,46,198,222,199,
+187,122,236,157,216,200,186,206,232,178,139,180,48,172,179,64,255,173,117,
+56,187,111,51,164,176,81,74,18,223,195,241,215,110,118,170,10,85,42,118,
+207,167,76,52,10,223,217,199,21,148,132,227,122,89,95,50,196,35,113,250,
+140,131,221,33,214,61,172,16,167,189,85,183,33,99,28,255,105,45,230,252,
+78,58,141,63,233,184,227,150,177,23,124,88,77,152,224,53,47,208,156,141,
+227,80,76,93,97,205,63,126,216,128,43,234,86,241,35,225,209,53,194,40,228,
+135,97,224,135,136,209,172,124,127,193,198,125,70,219,251,134,56,110,128,
+134,235,20,184,170,1,178,173,176,236,18,79,83,60,110,117,154,242,5,254,
+212,231,224,203,236,117,245,92,109,193,45,187,32,223,184,174,68,68,7,21,
+83,150,227,254,117,189,137,53,47,194,235,84,106,158,96,253,148,233,20,219,
+47,195,115,90,131,219,109,94,179,197,153,117,170,201,115,217,52,34,242,
+177,36,163,172,89,31,237,128,202,79,206,95,232,250,245,250,248,85,205,18,
+42,255,89,27,253,151,196,70,111,223,210,133,43,141,220,38,164,115,97,253,
+143,14,110,111,161,180,120,180,10,67,159,159,131,78,250,171,117,254,102,
+180,19,191,64,121,234,124,209,6,99,115,126,62,6,180,117,63,96,47,252,91,
+238,92,31,161,23,148,54,247,17,114,8,109,120,173,236,230,16,160,52,172,
+135,100,28,109,74,112,236,30,120,44,179,241,226,128,86,36,25,43,0,131,174,
+39,71,145,42,145,57,134,49,119,186,21,71,227,7,143,23,129,207,212,68,86,
+189,223,128,210,13,244,134,154,21,247,229,135,56,126,130,64,24,129,97,170,
+179,60,2,251,235,7,146,54,168,51,205,241,176,243,18,112,166,154,11,185,
+34,2,74,34,112,80,194,44,31,79,148,22,126,184,143,164,65,185,118,97,137,
+197,195,71,201,124,30,189,16,222,168,96,21,114,25,135,66,61,52,196,6,103,
+156,174,43,155,156,146,168,129,221,31,38,17,84,177,13,182,35,86,148,68,
+216,182,162,189,162,229,124,99,43,181,175,191,21,89,116,76,18,120,112,167,
+160,199,230,54,159,75,205,231,34,123,227,122,40,228,137,194,91,15,83,32,
+161,238,160,158,81,254,235,51,181,128,169,77,75,128,9,221,244,167,92,168,
+132,102,155,20,17,0,115,64,13,198,187,22,66,80,133,155,139,35,77,184,50,
+31,108,46,113,132,129,105,10,38,109,158,217,152,252,106,137,70,214,109,
+142,23,193,78,47,157,63,199,246,92,213,249,158,193,196,65,53,159,48,43,
+139,17,210,33,122,153,199,184,146,155,64,139,233,170,2,81,2,116,140,134,
+148,214,138,6,54,223,45,254,180,208,72,255,191,65,129,138,27,28,48,41,125,
+203,72,62,184,117,59,124,59,156,127,22,130,200,25,188,17,87,87,71,180,203,
+126,37,171,228,197,213,193,24,95,185,8,33,6,135,150,88,215,49,121,249,249,
+126,93,145,33,48,231,203,214,171,53,189,190,186,69,74,78,226,152,46,73,
+97,132,93,57,243,62,8,23,160,48,143,26,243,244,69,223,70,9,4,61,104,204,
+57,82,28,232,205,45,164,252,49,24,192,241,200,120,32,90,181,153,234,105,
+124,201,101,91,145,121,236,41,0,73,54,204,145,93,72,105,203,59,118,155,
+173,58,37,137,45,50,207,33,83,188,236,149,223,23,55,24,140,220,235,248,
+224,145,15,225,11,88,85,101,138,235,92,38,59,58,179,203,8,44,28,225,1,147,
+217,197,33,237,115,216,55,178,154,74,207,199,158,198,39,180,203,103,52,
+132,48,98,243,121,32,210,6,119,180,225,230,79,227,207,190,151,119,209,155,
+216,34,156,47,179,133,184,77,108,199,243,170,14,43,166,203,191,43,209,144,
+37,246,211,139,52,133,37,75,31,6,103,246,112,230,134,120,239,33,136,82,
+40,158,0,11,62,156,209,141,170,166,191,34,201,17,115,227,161,89,21,53,200,
+239,123,153,200,115,87,10,4,203,69,132,33,245,27,237,253,86,90,38,51,139,
+117,223,46,112,206,251,91,230,219,203,46,194,226,218,192,8,24,104,111,102,
+55,241,73,26,49,35,15,35,55,48,3,151,212,63,105,195,186,42,7,221,56,14,
+122,92,188,17,179,185,199,165,231,154,149,231,102,135,64,192,7,54,233,13,
+191,88,180,161,11,154,175
+, 0};
diff --git a/usr.bin/file2c/tests/regress.in b/usr.bin/file2c/tests/regress.in
new file mode 100644
index 000000000000..405465ac3117
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.in
Binary files differ
diff --git a/usr.bin/file2c/tests/regress.sh b/usr.bin/file2c/tests/regress.sh
new file mode 100644
index 000000000000..fed92e36aa0a
--- /dev/null
+++ b/usr.bin/file2c/tests/regress.sh
@@ -0,0 +1,18 @@
+
+echo 1..9
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`1', `head -c 13 ${SRCDIR}/regress.in | file2c')
+REGRESSION_TEST(`2', `head -c 26 ${SRCDIR}/regress.in | file2c PREFIX')
+REGRESSION_TEST(`3', `head -c 39 ${SRCDIR}/regress.in | file2c PREFIX SUFFIX')
+REGRESSION_TEST(`4', `head -c 52 ${SRCDIR}/regress.in | file2c -x')
+REGRESSION_TEST(`5', `head -c 65 ${SRCDIR}/regress.in | file2c -n -1')
+
+REGRESSION_TEST(`6', `head -c 7 ${SRCDIR}/regress.in | file2c -n 1 P S')
+REGRESSION_TEST(`7', `head -c 14 ${SRCDIR}/regress.in | file2c -n 2 -x "P S"')
+REGRESSION_TEST(`8', `head -c 21 ${SRCDIR}/regress.in | file2c -n 16 P -x S')
+
+REGRESSION_TEST(`9', `file2c "const char data[] = {" ", 0};" <${SRCDIR}/regress.in')
+
+REGRESSION_END()
diff --git a/usr.bin/find/Makefile b/usr.bin/find/Makefile
new file mode 100644
index 000000000000..904c08620833
--- /dev/null
+++ b/usr.bin/find/Makefile
@@ -0,0 +1,16 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= find
+SRCS= find.c function.c ls.c main.c misc.c operator.c option.c \
+ getdate.y
+YFLAGS=
+CFLAGS.clang+= -Werror=undef
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/find/Makefile.depend b/usr.bin/find/Makefile.depend
new file mode 100644
index 000000000000..c2fea3d32305
--- /dev/null
+++ b/usr.bin/find/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
new file mode 100644
index 000000000000..feb2e0202056
--- /dev/null
+++ b/usr.bin/find/extern.h
@@ -0,0 +1,127 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+
+void brace_subst(char *, char **, char *, size_t);
+PLAN *find_create(char ***);
+int find_execute(PLAN *, char **);
+PLAN *find_formplan(char **);
+PLAN *not_squish(PLAN *);
+PLAN *or_squish(PLAN *);
+PLAN *paren_squish(PLAN *);
+time_t get_date(char *);
+struct stat;
+void printlong(char *, char *, struct stat *);
+int queryuser(char **);
+OPTION *lookup_option(const char *);
+void finish_execplus(void);
+
+creat_f c_Xmin;
+creat_f c_Xtime;
+creat_f c_acl;
+creat_f c_and;
+creat_f c_delete;
+creat_f c_depth;
+creat_f c_empty;
+creat_f c_exec;
+creat_f c_flags;
+creat_f c_follow;
+creat_f c_fstype;
+creat_f c_group;
+creat_f c_ignore_readdir_race;
+creat_f c_inum;
+creat_f c_links;
+creat_f c_ls;
+creat_f c_mXXdepth;
+creat_f c_name;
+creat_f c_newer;
+creat_f c_nogroup;
+creat_f c_nouser;
+creat_f c_perm;
+creat_f c_print;
+creat_f c_regex;
+creat_f c_samefile;
+creat_f c_simple;
+creat_f c_size;
+creat_f c_sparse;
+creat_f c_type;
+creat_f c_user;
+creat_f c_xdev;
+
+exec_f f_Xmin;
+exec_f f_Xtime;
+exec_f f_acl;
+exec_f f_always_true;
+exec_f f_closeparen;
+exec_f f_delete;
+exec_f f_depth;
+exec_f f_empty;
+exec_f f_exec;
+exec_f f_executable;
+exec_f f_expr;
+exec_f f_false;
+exec_f f_flags;
+exec_f f_fstype;
+exec_f f_group;
+exec_f f_inum;
+exec_f f_links;
+exec_f f_ls;
+exec_f f_name;
+exec_f f_newer;
+exec_f f_nogroup;
+exec_f f_not;
+exec_f f_nouser;
+exec_f f_openparen;
+exec_f f_or;
+exec_f f_path;
+exec_f f_perm;
+exec_f f_print;
+exec_f f_print0;
+exec_f f_prune;
+exec_f f_quit;
+exec_f f_readable;
+exec_f f_regex;
+exec_f f_size;
+exec_f f_sparse;
+exec_f f_type;
+exec_f f_user;
+exec_f f_writable;
+
+extern int ftsoptions, ignore_readdir_race, isdepth, isoutput;
+extern int issort, isxargs;
+extern int mindepth, maxdepth;
+extern int regexp_flags;
+extern int exitstatus;
+extern time_t now;
+extern int dotfd;
+extern FTS *tree;
+extern volatile sig_atomic_t showinfo;
diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1
new file mode 100644
index 000000000000..eb3fd4d0dbde
--- /dev/null
+++ b/usr.bin/find/find.1
@@ -0,0 +1,1204 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd November 23, 2024
+.Dt FIND 1
+.Os
+.Sh NAME
+.Nm find
+.Nd walk a file hierarchy
+.Sh SYNOPSIS
+.Nm
+.Op Fl H | Fl L | Fl P
+.Op Fl EXdsx
+.Op Fl f Ar path
+.Ar path ...
+.Op Ar expression
+.Nm
+.Op Fl H | Fl L | Fl P
+.Op Fl EXdsx
+.Fl f Ar path
+.Op Ar path ...
+.Op Ar expression
+.Sh DESCRIPTION
+The
+.Nm
+utility recursively descends the directory tree for each
+.Ar path
+listed, evaluating an
+.Ar expression
+(composed of the
+.Dq primaries
+and
+.Dq operands
+listed below) in terms
+of each file in the tree.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl E
+Interpret regular expressions following the
+.Ic -regex
+and
+.Ic -iregex
+primaries as extended (modern) regular expressions rather than basic
+regular expressions (BRE's).
+The
+.Xr re_format 7
+manual page fully describes both formats.
+.It Fl H
+Cause the file information and file type (see
+.Xr stat 2 )
+returned for each symbolic link specified on the command line to be
+those of the file referenced by the link, not the link itself.
+If the referenced file does not exist, the file information and type will
+be for the link itself.
+File information of all symbolic links not on
+the command line is that of the link itself.
+.It Fl L
+Cause the file information and file type (see
+.Xr stat 2 )
+returned for each symbolic link to be those of the file referenced by the
+link, not the link itself.
+If the referenced file does not exist, the file information and type will
+be for the link itself.
+.Pp
+This option is equivalent to the deprecated
+.Ic -follow
+primary.
+.It Fl P
+Cause the file information and file type (see
+.Xr stat 2 )
+returned for each symbolic link to be those of the link itself.
+This is the default.
+.It Fl X
+Permit
+.Nm
+to be safely used in conjunction with
+.Xr xargs 1 .
+If a file name contains any of the delimiting characters used by
+.Xr xargs 1 ,
+a diagnostic message is displayed on standard error, and the file
+is skipped.
+The delimiting characters include single
+.Pq Dq Li " ' "
+and double
+.Pq Dq Li " \*q "
+quotes, backslash
+.Pq Dq Li \e ,
+space, tab and newline characters.
+.Pp
+However, you may wish to consider the
+.Fl print0
+primary in conjunction with
+.Dq Nm xargs Fl 0
+as an effective alternative.
+.It Fl d
+Cause
+.Nm
+to perform a depth-first traversal.
+.Pp
+This option is a BSD-specific equivalent of the
+.Ic -depth
+primary specified by
+.St -p1003.1-2001 .
+Refer to its description under
+.Sx PRIMARIES
+for more information.
+.It Fl f Ar path
+Add
+.Ar path
+to the list of paths that will be recursed into.
+This is useful when
+.Ar path
+begins with a character that would otherwise be interpreted as an
+.Ar expression ,
+namely
+.Dq Li "!" ,
+.Dq Li "("
+and
+.Dq Li - .
+.It Fl s
+Cause
+.Nm
+to traverse the file hierarchies in lexicographical order,
+i.e., alphabetical order within each directory.
+Note:
+.Ql find -s
+and
+.Ql "find | sort"
+may give different results.
+.Pp
+For example,
+.Ql find -s
+puts a directory
+.Ql Ar foo
+with all its contents before a directory
+.Ql Ar foo .
+but
+.Ql "find | sort"
+puts the directory name
+.Ql Ar foo .
+before any string like
+.Ql Ar foo/bar
+because
+.Ql .\&
+goes before
+.Ql /
+in ASCII.
+In locales other than
+.Ar C
+results may vary more due to collation differences.
+.It Fl x
+Prevent
+.Nm
+from descending into directories that have a device number different
+than that of the file from which the descent began.
+.Pp
+This option is equivalent to the deprecated
+.Ic -xdev
+primary.
+.El
+.Sh PRIMARIES
+All primaries which take a numeric argument allow the number to be
+preceded by a plus sign
+.Pq Dq Li +
+or a minus sign
+.Pq Dq Li - .
+A preceding plus sign means
+.Dq more than n ,
+a preceding minus sign means
+.Dq less than n
+and neither means
+.Dq exactly n .
+.Bl -tag -width indent
+.It Ic -Bmin Ar n
+True if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started, rounded up to the next full minute, is
+.Ar n
+minutes.
+.It Ic -Bnewer Ar file
+Same as
+.Ic -newerBm .
+.It Ic -Btime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the time of a file's inode creation
+and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
+.It Ic -acl
+May be used in conjunction with other primaries to locate
+files with extended ACLs.
+See
+.Xr acl 3
+for more information.
+.It Ic -amin Oo Cm - Ns | Ns Cm + Oc Ns Ar n
+True if the difference between the file last access time and the time
+.Nm
+was started, rounded up to the next full minute, is
+more than
+.Ar n
+.Pq + Ns Ar n ,
+less than
+.Ar n
+.Pq - Ns Ar n ,
+or exactly
+.Ar n
+minutes ago.
+.It Ic -anewer Ar file
+Same as
+.Ic -neweram .
+.It Ic -atime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the file last access time and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the file last access time and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Possible time units are as follows:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm s
+second
+.It Cm m
+minute (60 seconds)
+.It Cm h
+hour (60 minutes)
+.It Cm d
+day (24 hours)
+.It Cm w
+week (7 days)
+.El
+.Pp
+Any number of units may be combined in one
+.Ic -atime
+argument, for example,
+.Dq Li "-atime -1h30m" .
+Units are probably only useful when used in conjunction with the
+.Cm +
+or
+.Cm -
+modifier.
+.It Ic -cmin Oo Cm - Ns | Ns Cm + Oc Ns Ar n
+True if the difference between the time of last change of file status
+information and the time
+.Nm
+was started, rounded up to the next full minute, is
+more than
+.Ar n
+.Pq + Ns Ar n ,
+less than
+.Ar n
+.Pq - Ns Ar n ,
+or exactly
+.Ar n
+minutes ago.
+.It Ic -cnewer Ar file
+Same as
+.Ic -newercm .
+.It Ic -ctime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the time of last change of file status
+information and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the time of last change of file status
+information and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
+.It Ic -d
+Non-portable, BSD-specific version of
+.Ic depth .
+GNU find implements this as a primary in mistaken emulation of
+.Fx
+.Nm .
+.It Ic -delete
+Delete found files and/or directories.
+Always returns true.
+This executes
+from the current working directory as
+.Nm
+recurses down the tree.
+It will not attempt to delete a filename with a
+.Dq Pa /
+character in its pathname relative to
+.Dq Pa \&.
+for security reasons.
+Depth-first traversal processing is implied by this option.
+The
+.Ic -delete
+primary will fail to delete a directory if it is not empty.
+Following symlinks is incompatible with this option.
+.Pp
+.Em WARNING :
+The
+.Ic -delete
+primary will immediately attempt to delete the current path when
+evaluated.
+Be mindful of its place in the expression; as a general rule, it
+should almost always come last.
+If in doubt, try running with
+.Ic -print
+in place of
+.Ic -delete
+first.
+See
+.Sx OPERATORS
+below for additional information on the order of evaluation.
+.It Ic -depth
+Always true;
+same as the non-portable
+.Fl d
+option.
+Cause
+.Nm
+to perform a depth-first traversal, i.e., directories
+are visited in post-order and all entries in a directory will be acted
+on before the directory itself.
+By default,
+.Nm
+visits directories in pre-order, i.e., before their contents.
+Note, the default is
+.Em not
+a breadth-first traversal.
+.Pp
+The
+.Ic -depth
+primary
+can be useful when
+.Nm
+is used with
+.Xr cpio 1
+to process files that are contained in directories with unusual permissions.
+It ensures that you have write permission while you are placing files in a
+directory, then sets the directory's permissions as the last thing.
+.It Ic -depth Ar n
+True if the depth of the file relative to the starting point of the traversal
+is
+.Ar n .
+.It Ic -empty
+True if the current file or directory is empty.
+.It Ic -exec Ar utility Oo Ar argument ... Oc Li \&;
+True if the program named
+.Ar utility
+returns a zero value as its exit status.
+Optional
+.Ar arguments
+may be passed to the utility.
+The expression must be terminated by a semicolon
+.Pq Dq Li \&; .
+If you invoke
+.Nm
+from a shell you may need to quote the semicolon if the shell would
+otherwise treat it as a control operator.
+If the string
+.Dq Li {}
+appears anywhere in the utility name or the
+arguments it is replaced by the pathname of the current file.
+.Ar Utility
+will be executed from the directory from which
+.Nm
+was executed.
+.Ar Utility
+and
+.Ar arguments
+are not subject to the further expansion of shell patterns
+and constructs.
+.It Ic -exec Ar utility Oo Ar argument ... Oc Li {} +
+Same as
+.Ic -exec ,
+except that
+.Dq Li {}
+is replaced with as many pathnames as possible for each invocation of
+.Ar utility .
+This behaviour is similar to that of
+.Xr xargs 1 .
+The primary always returns true;
+if at least one invocation of
+.Ar utility
+returns a non-zero exit status,
+.Nm
+will return a non-zero exit status.
+.It Ic -execdir Ar utility Oo Ar argument ... Oc Li \&;
+The
+.Ic -execdir
+primary is identical to the
+.Ic -exec
+primary with the exception that
+.Ar utility
+will be executed from the directory that holds
+the current file.
+The filename substituted for
+the string
+.Dq Li {}
+is not qualified.
+.It Ic -execdir Ar utility Oo Ar argument ... Oc Li {} +
+Same as
+.Ic -execdir ,
+except that
+.Dq Li {}
+is replaced with as many pathnames as possible for each invocation of
+.Ar utility .
+This behaviour is similar to that of
+.Xr xargs 1 .
+The primary always returns true;
+if at least one invocation of
+.Ar utility
+returns a non-zero exit status,
+.Nm
+will return a non-zero exit status.
+.It Ic -executable
+Matches files which are executable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
+.It Ic -flags Oo Cm - Ns | Ns Cm + Oc Ns Ar flags , Ns Ar notflags
+The flags are specified using symbolic names (see
+.Xr chflags 1 ) .
+Those with the
+.Qq Li no
+prefix (except
+.Qq Li nodump )
+are said to be
+.Ar notflags .
+Flags in
+.Ar flags
+are checked to be set, and flags in
+.Ar notflags
+are checked to be not set.
+Note that this is different from
+.Ic -perm ,
+which only allows the user to specify mode bits that are set.
+.Pp
+If flags are preceded by a dash
+.Pq Dq Li - ,
+this primary evaluates to true
+if at least all of the bits in
+.Ar flags
+and none of the bits in
+.Ar notflags
+are set in the file's flags bits.
+If flags are preceded by a plus
+.Pq Dq Li + ,
+this primary evaluates to true
+if any of the bits in
+.Ar flags
+is set in the file's flags bits,
+or any of the bits in
+.Ar notflags
+is not set in the file's flags bits.
+Otherwise,
+this primary evaluates to true
+if the bits in
+.Ar flags
+exactly match the file's flags bits,
+and none of the
+.Ar flags
+bits match those of
+.Ar notflags .
+.It Ic -fstype Ar type
+True if the file is contained in a file system of type
+.Ar type .
+The
+.Xr lsvfs 1
+command can be used to find out the types of file systems
+that are available on the system.
+In addition, there are two pseudo-types,
+.Dq Li local
+and
+.Dq Li rdonly .
+The former matches any file system physically mounted on the system where
+the
+.Nm
+is being executed and the latter matches any file system which is
+mounted read-only.
+.It Ic -gid Ar gname
+The same thing as
+.Ic -group Ar gname
+for compatibility with GNU find.
+GNU find imposes a restriction that
+.Ar gname
+is numeric, while
+.Nm
+does not.
+.It Ic -group Ar gname
+True if the file belongs to the group
+.Ar gname .
+If
+.Ar gname
+is numeric and there is no such group name, then
+.Ar gname
+is treated as a group ID.
+.It Ic -ignore_readdir_race
+Ignore errors because a file or a directory is deleted
+after reading the name from a directory.
+This option does not affect errors occurring on starting points.
+.It Ic -ilname Ar pattern
+Like
+.Ic -lname ,
+but the match is case insensitive.
+This is a GNU find extension.
+.It Ic -iname Ar pattern
+Like
+.Ic -name ,
+but the match is case insensitive.
+.It Ic -inum Ar n
+True if the file has inode number
+.Ar n .
+.It Ic -ipath Ar pattern
+Like
+.Ic -path ,
+but the match is case insensitive.
+.It Ic -iregex Ar pattern
+Like
+.Ic -regex ,
+but the match is case insensitive.
+.It Ic -iwholename Ar pattern
+The same thing as
+.Ic -ipath ,
+for GNU find compatibility.
+.It Ic -links Ar n
+True if the file has
+.Ar n
+links.
+.It Ic -lname Ar pattern
+Like
+.Ic -name ,
+but the contents of the symbolic link are matched instead of the file
+name.
+Note that this only matches broken symbolic links
+if symbolic links are being followed.
+This is a GNU find extension.
+.It Ic -ls
+This primary always evaluates to true.
+The following information for the current file is written to standard output:
+its inode number, size in 512-byte blocks, file permissions, number of hard
+links, owner, group, size in bytes, last modification time, and pathname.
+If the file is a block or character special file, the device number
+will be displayed instead of the size in bytes.
+If the file is a symbolic link, the pathname of the linked-to file will be
+displayed preceded by
+.Dq Li -> .
+The format is identical to that produced by
+.Bk -words
+.Dq Nm ls Fl dils .
+.Ek
+.It Ic -maxdepth Ar n
+Always true; descend at most
+.Ar n
+directory levels below the command line arguments.
+If any
+.Ic -maxdepth
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
+.Dq Ic -maxdepth Li 0
+limits the whole search to the command line arguments.
+.It Ic -mindepth Ar n
+Always true; do not apply any tests or actions at levels less than
+.Ar n .
+If any
+.Ic -mindepth
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
+.Dq Ic -mindepth Li 1
+processes all but the command line arguments.
+.It Ic -mmin Oo Cm - Ns | Ns Cm + Oc Ns Ar n
+True if the difference between the file last modification time and the time
+.Nm
+was started, rounded up to the next full minute, is
+more than
+.Ar n
+.Pq + Ns Ar n ,
+less than
+.Ar n
+.Pq - Ns Ar n ,
+or exactly
+.Ar n
+minutes ago.
+.It Ic -mnewer Ar file
+Same as
+.Ic -newer .
+.It Ic -mount
+The same thing as
+.Ic -xdev ,
+for GNU find compatibility.
+.It Ic -mtime Ar n Ns Op Cm smhdw
+If no units are specified, this primary evaluates to
+true if the difference between the file last modification time and the time
+.Nm
+was started, rounded up to the next full 24-hour period, is
+.Ar n
+24-hour periods.
+.Pp
+If units are specified, this primary evaluates to
+true if the difference between the file last modification time and the time
+.Nm
+was started is exactly
+.Ar n
+units.
+Please refer to the
+.Ic -atime
+primary description for information on supported time units.
+.It Ic -name Ar pattern
+True if the last component of the pathname being examined matches
+.Ar pattern .
+Special shell pattern matching characters
+.Dq ( Li \&[ ,
+.Dq Li \&] ,
+.Dq Li * ,
+and
+.Dq Li \&? )
+may be used as part of
+.Ar pattern .
+These characters may be matched explicitly by escaping them with a
+backslash
+.Pq Dq Li \e .
+.It Ic -newer Ar file
+True if the current file has a more recent last modification time than
+.Ar file .
+.It Ic -newer Ns Ar X Ns Ar Y Ar file
+True if the current file has a more recent last access time
+.Pq Ar X Ns = Ns Cm a ,
+inode creation time
+.Pq Ar X Ns = Ns Cm B ,
+change time
+.Pq Ar X Ns = Ns Cm c ,
+or modification time
+.Pq Ar X Ns = Ns Cm m
+than the last access time
+.Pq Ar Y Ns = Ns Cm a ,
+inode creation time
+.Pq Ar Y Ns = Ns Cm B ,
+change time
+.Pq Ar Y Ns = Ns Cm c ,
+or modification time
+.Pq Ar Y Ns = Ns Cm m
+of
+.Ar file .
+In addition, if
+.Ar Y Ns = Ns Cm t ,
+then
+.Ar file
+is instead interpreted as a direct date specification of the form
+understood by ISO8601 or RFC822.
+Note that
+.Ic -newermm
+is equivalent to
+.Ic -newer .
+.It Ic -nogroup
+True if the file belongs to an unknown group.
+.It Ic -noignore_readdir_race
+Turn off the effect of
+.Ic -ignore_readdir_race .
+This is default behaviour.
+.It Ic -noleaf
+This option is for GNU find compatibility.
+In GNU find it disables an optimization not relevant to
+.Nm ,
+so it is ignored.
+.It Ic -nouser
+True if the file belongs to an unknown user.
+.It Ic -ok Ar utility Oo Ar argument ... Oc Li \&;
+The
+.Ic -ok
+primary is identical to the
+.Ic -exec
+primary with the exception that
+.Nm
+requests user affirmation for the execution of the
+.Ar utility
+by printing
+a message to the terminal and reading a response.
+If the response is not affirmative
+.Ql ( y
+in the
+.Dq Li POSIX
+locale),
+the command is not executed and the
+value of the
+.Ic -ok
+expression is false.
+.It Ic -okdir Ar utility Oo Ar argument ... Oc Li \&;
+The
+.Ic -okdir
+primary is identical to the
+.Ic -execdir
+primary with the same exception as described for the
+.Ic -ok
+primary.
+.It Ic -path Ar pattern
+True if the pathname being examined matches
+.Ar pattern .
+Special shell pattern matching characters
+.Dq ( Li \&[ ,
+.Dq Li \&] ,
+.Dq Li * ,
+and
+.Dq Li \&? )
+may be used as part of
+.Ar pattern .
+These characters may be matched explicitly by escaping them with a
+backslash
+.Pq Dq Li \e .
+Slashes
+.Pq Dq Li /
+are treated as normal characters and do not have to be
+matched explicitly.
+.It Ic -perm Oo Cm - Ns | Ns Cm + Ns | Ns Cm / Oc Ns Ar mode
+The
+.Ar mode
+may be either symbolic (see
+.Xr chmod 1 )
+or an octal number.
+If the
+.Ar mode
+is symbolic, a starting value of zero is assumed and the
+.Ar mode
+sets or clears permissions without regard to the process' file mode
+creation mask.
+If the
+.Ar mode
+is octal, only bits 07777
+.Pq Dv S_ISUID | S_ISGID | S_ISTXT | S_IRWXU | S_IRWXG | S_IRWXO
+of the file's mode bits participate
+in the comparison.
+If the
+.Ar mode
+is preceded by a dash
+.Pq Dq Li - ,
+this primary evaluates to true
+if at least all of the bits in the
+.Ar mode
+are set in the file's mode bits.
+If the
+.Ar mode
+is preceded by a plus
+.Pq Dq Li +
+this primary evaluates to true
+if any of the bits in the
+.Ar mode
+are set in the file's mode bits.
+A slash
+.Pq Dq Li /
+is also accepted with the same meaning as plus for compatibility with GNU find.
+Otherwise, this primary evaluates to true if
+the bits in the
+.Ar mode
+exactly match the file's mode bits.
+Note, the first character of a symbolic mode may not be a dash
+.Pq Dq Li - .
+.It Ic -print
+This primary always evaluates to true.
+It prints the pathname of the current file to standard output.
+If none of
+.Ic -exec , -ls , -print0 ,
+or
+.Ic -ok
+is specified, the given expression shall be effectively replaced by
+.Cm \&( Ar "given expression" Cm \&) Ic -print .
+.It Ic -print0
+This primary always evaluates to true.
+It prints the pathname of the current file to standard output, followed by an
+ASCII
+.Dv NUL
+character (character code 0).
+.It Ic -prune
+This primary always evaluates to true.
+It causes
+.Nm
+to not descend into the current file.
+Note, the
+.Ic -prune
+primary has no effect if the
+.Fl d
+option was specified.
+.It Ic -quit
+Causes
+.Nm
+to terminate immediately.
+.It Ic -readable
+Matches files which are readable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
+.It Ic -regex Ar pattern
+True if the whole path of the file matches
+.Ar pattern
+using regular expression.
+To match a file named
+.Dq Pa ./foo/xyzzy ,
+you can use the regular expression
+.Dq Li ".*/[xyz]*"
+or
+.Dq Li ".*/foo/.*" ,
+but not
+.Dq Li xyzzy
+or
+.Dq Li /foo/ .
+.It Ic -samefile Ar name
+True if the file is a hard link to
+.Ar name .
+If the command option
+.Ic -L
+is specified, it is also true if the file is a symbolic link and
+points to
+.Ar name .
+.It Ic -size Ar n Ns Op Cm ckMGTP
+True if the file's size, rounded up, in 512-byte blocks is
+.Ar n .
+If
+.Ar n
+is followed by a
+.Cm c ,
+then the primary is true if the
+file's size is
+.Ar n
+bytes (characters).
+Similarly if
+.Ar n
+is followed by a scale indicator then the file's size is compared to
+.Ar n
+scaled as:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm k
+kilobytes (1024 bytes)
+.It Cm M
+megabytes (1024 kilobytes)
+.It Cm G
+gigabytes (1024 megabytes)
+.It Cm T
+terabytes (1024 gigabytes)
+.It Cm P
+petabytes (1024 terabytes)
+.El
+.It Ic -sparse
+True if the current file is sparse,
+i.e. has fewer blocks allocated than expected based on its size in bytes.
+This might also match files that have been compressed by the filesystem.
+.It Ic -type Ar t
+True if the file is of the specified type.
+Possible file types are as follows:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm b
+block special
+.It Cm c
+character special
+.It Cm d
+directory
+.It Cm f
+regular file
+.It Cm l
+symbolic link
+.It Cm p
+FIFO
+.It Cm s
+socket
+.El
+.It Ic -uid Ar uname
+The same thing as
+.Ar -user Ar uname
+for compatibility with GNU find.
+GNU find imposes a restriction that
+.Ar uname
+is numeric, while
+.Nm
+does not.
+.It Ic -user Ar uname
+True if the file belongs to the user
+.Ar uname .
+If
+.Ar uname
+is numeric and there is no such user name, then
+.Ar uname
+is treated as a user ID.
+.It Ic -wholename Ar pattern
+The same thing as
+.Ic -path ,
+for GNU find compatibility.
+.It Ic -writable
+Matches files which are writable by the current user.
+This test makes use of the
+.Xr access 2
+system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing).
+This is a GNU find extension.
+.El
+.Sh OPERATORS
+The primaries may be combined using the following operators.
+The operators are listed in order of decreasing precedence.
+.Pp
+.Bl -tag -width indent -compact
+.It Cm \&( Ar expression Cm \&)
+This evaluates to true if the parenthesized expression evaluates to
+true.
+.Pp
+.It Cm \&! Ar expression
+.It Cm -not Ar expression
+This is the unary
+.Tn NOT
+operator.
+It evaluates to true if the expression is false.
+.Pp
+.It Cm -false
+Always false.
+.It Cm -true
+Always true.
+.Pp
+.It Ar expression Cm -and Ar expression
+.It Ar expression expression
+The
+.Cm -and
+operator is the logical
+.Tn AND
+operator.
+As it is implied by the juxtaposition of two expressions it does not
+have to be specified.
+The expression evaluates to true if both expressions are true.
+The second expression is not evaluated if the first expression is false.
+.Pp
+.It Ar expression Cm -or Ar expression
+The
+.Cm -or
+operator is the logical
+.Tn OR
+operator.
+The expression evaluates to true if either the first or the second expression
+is true.
+The second expression is not evaluated if the first expression is true.
+.El
+.Pp
+All operands and primaries must be separate arguments to
+.Nm .
+Primaries which themselves take arguments expect each argument
+to be a separate argument to
+.Nm .
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_COLLATE , LC_CTYPE , LC_MESSAGES
+and
+.Ev LC_TIME
+environment variables affect the execution of the
+.Nm
+utility as described in
+.Xr environ 7 .
+.Sh EXAMPLES
+The following examples are shown as given to the shell:
+.Bl -tag -width indent
+.It Li "find / \e! -name \*q*.c\*q -print"
+Print out a list of all the files whose names do not end in
+.Pa .c .
+.It Li "find / -newer ttt -user wnj -print"
+Print out a list of all the files owned by user
+.Dq wnj
+that are newer
+than the file
+.Pa ttt .
+.It Li "find / \e! \e( -newer ttt -user wnj \e) -print"
+Print out a list of all the files which are not both newer than
+.Pa ttt
+and owned by
+.Dq wnj .
+.It Li "find / \e( -newer ttt -or -user wnj \e) -print"
+Print out a list of all the files that are either owned by
+.Dq wnj
+or that are newer than
+.Pa ttt .
+.It Li "find / -newerct '1 minute ago' -print"
+Print out a list of all the files whose inode change time is more
+recent than the current time minus one minute.
+.It Li "find / -type f -exec echo {} \e;"
+Use the
+.Xr echo 1
+command to print out a list of all the files.
+.It Li "find -L /usr/ports/packages -type l -exec rm -- {} +"
+Delete all broken symbolic links in
+.Pa /usr/ports/packages .
+.It Li "find /usr/src -name CVS -prune -o -depth +6 -print"
+Find files and directories that are at least seven levels deep
+in the working directory
+.Pa /usr/src .
+.It Li "find /usr/src -name CVS -prune -o -mindepth 7 -print"
+Is not equivalent to the previous example, since
+.Ic -prune
+is not evaluated below level seven.
+.El
+.Sh COMPATIBILITY
+The
+.Ic -follow
+primary is deprecated; the
+.Fl L
+option should be used instead.
+See the
+.Sx STANDARDS
+section below for details.
+.Sh SEE ALSO
+.Xr chflags 1 ,
+.Xr chmod 1 ,
+.Xr locate 1 ,
+.Xr lsvfs 1 ,
+.Xr whereis 1 ,
+.Xr which 1 ,
+.Xr xargs 1 ,
+.Xr stat 2 ,
+.Xr acl 3 ,
+.Xr fts 3 ,
+.Xr getgrent 3 ,
+.Xr getpwent 3 ,
+.Xr strmode 3 ,
+.Xr ascii 7 ,
+.Xr re_format 7 ,
+.Xr symlink 7
+.Sh STANDARDS
+The
+.Nm
+utility syntax is a superset of the syntax specified by the
+.St -p1003.1-2001
+standard.
+.Pp
+All the single character options except
+.Fl H
+and
+.Fl L
+as well as
+.Ic -amin , -anewer , -cmin , -cnewer , -delete , -empty , -fstype ,
+.Ic -iname , -inum , -iregex , -ls , -maxdepth , -mindepth , -mmin ,
+.Ic -not , -path , -print0 , -regex , -sparse
+and all of the
+.Fl B*
+birthtime related primaries are extensions to
+.St -p1003.1-2001 .
+.Pp
+Historically, the
+.Fl d , L
+and
+.Fl x
+options were implemented using the primaries
+.Ic -depth , -follow ,
+and
+.Ic -xdev .
+These primaries always evaluated to true.
+As they were really global variables that took effect before the traversal
+began, some legal expressions could have unexpected results.
+An example is the expression
+.Ic -print Cm -o Ic -depth .
+As
+.Ic -print
+always evaluates to true, the standard order of evaluation
+implies that
+.Ic -depth
+would never be evaluated.
+This is not the case.
+.Pp
+The operator
+.Cm -or
+was implemented as
+.Cm -o ,
+and the operator
+.Cm -and
+was implemented as
+.Cm -a .
+.Pp
+Historic implementations of the
+.Ic -exec
+and
+.Ic -ok
+primaries did not replace the string
+.Dq Li {}
+in the utility name or the
+utility arguments if it had preceding or following non-whitespace characters.
+This version replaces it no matter where in the utility name or arguments
+it appears.
+.Pp
+The
+.Fl E
+option was inspired by the equivalent
+.Xr grep 1
+and
+.Xr sed 1
+options.
+.Pp
+The
+.Ic -perm
+primary accepts a leading slash
+.Pq Dq Li /
+as an alias for a leading plus
+.Pq Dq Li +
+for its argument as an extension of
+.St -p1003.1-2001
+to be compatible with GNU find.
+.Sh HISTORY
+A simple
+.Nm
+command appeared in
+.At v1
+and was removed in
+.At v3 .
+It was rewritten for
+.At v5
+and later be enhanced for the Programmer's Workbench (PWB).
+These changes were later incorporated in
+.At v7 .
+.Sh BUGS
+The special characters used by
+.Nm
+are also special characters to many shell programs.
+In particular, the characters
+.Dq Li * ,
+.Dq Li \&[ ,
+.Dq Li \&] ,
+.Dq Li \&? ,
+.Dq Li \&( ,
+.Dq Li \&) ,
+.Dq Li \&! ,
+.Dq Li \e
+and
+.Dq Li \&;
+may have to be escaped from the shell.
+.Pp
+As there is no delimiter separating options and file names or file
+names and the
+.Ar expression ,
+it is difficult to specify files named
+.Pa -xdev
+or
+.Pa \&! .
+These problems are handled by the
+.Fl f
+option and the
+.Xr getopt 3
+.Dq Fl Fl
+construct.
+.Pp
+The
+.Ic -delete
+primary does not interact well with other options that cause the file system
+tree traversal options to be changed.
+.Pp
+The
+.Ic -mindepth
+and
+.Ic -maxdepth
+primaries are actually global options (as documented above).
+They should
+probably be replaced by options which look like options.
diff --git a/usr.bin/find/find.c b/usr.bin/find/find.c
new file mode 100644
index 000000000000..8b24ecd6a306
--- /dev/null
+++ b/usr.bin/find/find.c
@@ -0,0 +1,243 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "find.h"
+
+static int find_compare(const FTSENT * const *s1, const FTSENT * const *s2);
+
+/*
+ * find_compare --
+ * tell fts_open() how to order the traversal of the hierarchy.
+ * This variant gives lexicographical order, i.e., alphabetical
+ * order within each directory.
+ */
+static int
+find_compare(const FTSENT * const *s1, const FTSENT * const *s2)
+{
+
+ return (strcoll((*s1)->fts_name, (*s2)->fts_name));
+}
+
+/*
+ * find_formplan --
+ * process the command line and create a "plan" corresponding to the
+ * command arguments.
+ */
+PLAN *
+find_formplan(char *argv[])
+{
+ PLAN *plan, *tail, *new;
+
+ /*
+ * for each argument in the command line, determine what kind of node
+ * it is, create the appropriate node type and add the new plan node
+ * to the end of the existing plan. The resulting plan is a linked
+ * list of plan nodes. For example, the string:
+ *
+ * % find . -name foo -newer bar -print
+ *
+ * results in the plan:
+ *
+ * [-name foo]--> [-newer bar]--> [-print]
+ *
+ * in this diagram, `[-name foo]' represents the plan node generated
+ * by c_name() with an argument of foo and `-->' represents the
+ * plan->next pointer.
+ */
+ for (plan = tail = NULL; *argv;) {
+ if (!(new = find_create(&argv)))
+ continue;
+ if (plan == NULL)
+ tail = plan = new;
+ else {
+ tail->next = new;
+ tail = new;
+ }
+ }
+
+ /*
+ * if the user didn't specify one of -print, -ok or -exec, then -print
+ * is assumed so we bracket the current expression with parens, if
+ * necessary, and add a -print node on the end.
+ */
+ if (!isoutput) {
+ OPTION *p;
+ char **argv1 = 0;
+
+ if (plan == NULL) {
+ p = lookup_option("-print");
+ new = (p->create)(p, &argv1);
+ tail = plan = new;
+ } else {
+ p = lookup_option("(");
+ new = (p->create)(p, &argv1);
+ new->next = plan;
+ plan = new;
+ p = lookup_option(")");
+ new = (p->create)(p, &argv1);
+ tail->next = new;
+ tail = new;
+ p = lookup_option("-print");
+ new = (p->create)(p, &argv1);
+ tail->next = new;
+ tail = new;
+ }
+ }
+
+ /*
+ * the command line has been completely processed into a search plan
+ * except for the (, ), !, and -o operators. Rearrange the plan so
+ * that the portions of the plan which are affected by the operators
+ * are moved into operator nodes themselves. For example:
+ *
+ * [!]--> [-name foo]--> [-print]
+ *
+ * becomes
+ *
+ * [! [-name foo] ]--> [-print]
+ *
+ * and
+ *
+ * [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
+ *
+ * becomes
+ *
+ * [expr [-depth]-->[-name foo] ]--> [-print]
+ *
+ * operators are handled in order of precedence.
+ */
+
+ plan = paren_squish(plan); /* ()'s */
+ plan = not_squish(plan); /* !'s */
+ plan = or_squish(plan); /* -o's */
+ return (plan);
+}
+
+FTS *tree; /* pointer to top of FTS hierarchy */
+
+/*
+ * find_execute --
+ * take a search plan and an array of search paths and executes the plan
+ * over all FTSENT's returned for the given search paths.
+ */
+int
+find_execute(PLAN *plan, char *paths[])
+{
+ FTSENT *entry;
+ PLAN *p;
+ size_t counter = 0;
+ int e;
+
+ tree = fts_open(paths, ftsoptions, (issort ? find_compare : NULL));
+ if (tree == NULL)
+ err(1, "ftsopen");
+
+ exitstatus = 0;
+ while (errno = 0, (entry = fts_read(tree)) != NULL) {
+ if (maxdepth != -1 && entry->fts_level >= maxdepth) {
+ if (fts_set(tree, entry, FTS_SKIP))
+ err(1, "%s", entry->fts_path);
+ }
+
+ switch (entry->fts_info) {
+ case FTS_D:
+ if (isdepth)
+ continue;
+ break;
+ case FTS_DP:
+ if (!isdepth)
+ continue;
+ break;
+ case FTS_DNR:
+ case FTS_NS:
+ if (ignore_readdir_race &&
+ entry->fts_errno == ENOENT && entry->fts_level > 0)
+ continue;
+ /* FALLTHROUGH */
+ case FTS_ERR:
+ (void)fflush(stdout);
+ warnx("%s: %s",
+ entry->fts_path, strerror(entry->fts_errno));
+ exitstatus = 1;
+ continue;
+#if defined(FTS_W) && defined(FTS_WHITEOUT)
+ case FTS_W:
+ if (ftsoptions & FTS_WHITEOUT)
+ break;
+ continue;
+#endif /* FTS_W */
+ }
+
+ if (showinfo) {
+ fprintf(stderr, "Scanning: %s/%s\n", entry->fts_path, entry->fts_name);
+ fprintf(stderr, "Scanned: %zu\n\n", counter);
+ showinfo = 0;
+ }
+ ++counter;
+
+#define BADCH " \t\n\\'\""
+ if (isxargs && strpbrk(entry->fts_path, BADCH)) {
+ (void)fflush(stdout);
+ warnx("%s: illegal path", entry->fts_path);
+ exitstatus = 1;
+ continue;
+ }
+
+ if (mindepth != -1 && entry->fts_level < mindepth)
+ continue;
+
+ /*
+ * Call all the functions in the execution plan until one is
+ * false or all have been executed. This is where we do all
+ * the work specified by the user on the command line.
+ */
+ for (p = plan; p && (p->execute)(p, entry); p = p->next);
+ }
+ e = errno;
+ finish_execplus();
+ if (e && (!ignore_readdir_race || e != ENOENT))
+ errc(1, e, "fts_read");
+ return (exitstatus);
+}
diff --git a/usr.bin/find/find.h b/usr.bin/find/find.h
new file mode 100644
index 000000000000..1664eeb9a93f
--- /dev/null
+++ b/usr.bin/find/find.h
@@ -0,0 +1,171 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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 <regex.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+/*
+ * We need to build find during the bootstrap stage when building on a
+ * non-FreeBSD system. Linux does not have the st_flags and st_birthtime
+ * members in struct stat so we need to omit support for tests that depend
+ * on these members. This works fine since none of these flags are used
+ * during the build of world and kernel.
+ */
+#ifdef UF_SETTABLE
+#define HAVE_STRUCT_STAT_ST_FLAGS 1
+#else
+#define HAVE_STRUCT_STAT_ST_FLAGS 0
+#endif
+#if defined(st_birthtime) || defined(st_birthtimespec)
+#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
+#else
+#define HAVE_STRUCT_STAT_ST_BIRTHTIME 0
+#endif
+#if defined(MFSNAMELEN) || defined(MFSTYPENAMELEN)
+#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1
+#else
+#define HAVE_STRUCT_STATFS_F_FSTYPENAME 0
+#endif
+
+/* forward declarations */
+struct _plandata;
+struct _option;
+
+/* execute function */
+typedef int exec_f(struct _plandata *, FTSENT *);
+/* create function */
+typedef struct _plandata *creat_f(struct _option *, char ***);
+
+/* function modifiers */
+#define F_NEEDOK 0x00000001 /* -ok vs. -exec */
+#define F_EXECDIR 0x00000002 /* -execdir vs. -exec */
+#define F_TIME_A 0x00000004 /* one of -atime, -anewer, -newera* */
+#define F_TIME_C 0x00000008 /* one of -ctime, -cnewer, -newerc* */
+#define F_TIME2_A 0x00000010 /* one of -newer?a */
+#define F_TIME2_C 0x00000020 /* one of -newer?c */
+#define F_TIME2_T 0x00000040 /* one of -newer?t */
+#define F_MAXDEPTH F_TIME_A /* maxdepth vs. mindepth */
+#define F_DEPTH F_TIME_A /* -depth n vs. -d */
+/* command line function modifiers */
+#define F_EQUAL 0x00000000 /* [acm]min [acm]time inum links size */
+#define F_LESSTHAN 0x00000100
+#define F_GREATER 0x00000200
+#define F_ELG_MASK 0x00000300
+#define F_ATLEAST 0x00000400 /* flags perm */
+#define F_ANY 0x00000800 /* perm */
+#define F_MTMASK 0x00003000
+#define F_MTFLAG 0x00000000 /* fstype */
+#define F_MTTYPE 0x00001000
+#define F_MTUNKNOWN 0x00002000
+#define F_IGNCASE 0x00010000 /* iname ipath iregex */
+#define F_EXACTTIME F_IGNCASE /* -[acm]time units syntax */
+#define F_EXECPLUS 0x00020000 /* -exec ... {} + */
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+#define F_TIME_B 0x00040000 /* one of -Btime, -Bnewer, -newerB* */
+#define F_TIME2_B 0x00080000 /* one of -newer?B */
+#endif
+#define F_LINK 0x00100000 /* lname or ilname */
+
+/* node definition */
+typedef struct _plandata {
+ struct _plandata *next; /* next node */
+ exec_f *execute; /* node evaluation function */
+ int flags; /* private flags */
+ union {
+ gid_t _g_data; /* gid */
+ ino_t _i_data; /* inode */
+ mode_t _m_data; /* mode mask */
+ struct {
+ u_long _f_flags;
+ u_long _f_notflags;
+ } fl;
+ nlink_t _l_data; /* link count */
+ short _d_data; /* level depth (-1 to N) */
+ off_t _o_data; /* file size */
+ struct timespec _t_data; /* time value */
+ uid_t _u_data; /* uid */
+ short _mt_data; /* mount flags */
+ struct _plandata *_p_data[2]; /* PLAN trees */
+ struct _ex {
+ char **_e_argv; /* argv array */
+ char **_e_orig; /* original strings */
+ int *_e_len; /* allocated length */
+ int _e_pbnum; /* base num. of args. used */
+ int _e_ppos; /* number of arguments used */
+ int _e_pnummax; /* max. number of arguments */
+ int _e_psize; /* number of bytes of args. */
+ int _e_pbsize; /* base num. of bytes of args */
+ int _e_psizemax; /* max num. of bytes of args */
+ struct _plandata *_e_next;/* next F_EXECPLUS in tree */
+ } ex;
+ char *_a_data[2]; /* array of char pointers */
+ char *_c_data; /* char pointer */
+ regex_t *_re_data; /* regex */
+ } p_un;
+} PLAN;
+#define a_data p_un._a_data
+#define c_data p_un._c_data
+#define d_data p_un._d_data
+#define fl_flags p_un.fl._f_flags
+#define fl_notflags p_un.fl._f_notflags
+#define g_data p_un._g_data
+#define i_data p_un._i_data
+#define l_data p_un._l_data
+#define m_data p_un._m_data
+#define mt_data p_un._mt_data
+#define o_data p_un._o_data
+#define p_data p_un._p_data
+#define t_data p_un._t_data
+#define u_data p_un._u_data
+#define re_data p_un._re_data
+#define e_argv p_un.ex._e_argv
+#define e_orig p_un.ex._e_orig
+#define e_len p_un.ex._e_len
+#define e_pbnum p_un.ex._e_pbnum
+#define e_ppos p_un.ex._e_ppos
+#define e_pnummax p_un.ex._e_pnummax
+#define e_psize p_un.ex._e_psize
+#define e_pbsize p_un.ex._e_pbsize
+#define e_psizemax p_un.ex._e_psizemax
+#define e_next p_un.ex._e_next
+
+typedef struct _option {
+ const char *name; /* option name */
+ creat_f *create; /* create function */
+ exec_f *execute; /* execute function */
+ int flags;
+} OPTION;
+
+#include "extern.h"
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
new file mode 100644
index 000000000000..ef610903cc00
--- /dev/null
+++ b/usr.bin/find/function.c
@@ -0,0 +1,1849 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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>
+#include <sys/ucred.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <fts.h>
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "find.h"
+
+static PLAN *palloc(OPTION *);
+static long long find_parsenum(PLAN *, const char *, char *, char *);
+static long long find_parsetime(PLAN *, const char *, char *);
+static char *nextarg(OPTION *, char ***);
+
+extern char **environ;
+
+static PLAN *lastexecplus = NULL;
+
+#define COMPARE(a, b) do { \
+ switch (plan->flags & F_ELG_MASK) { \
+ case F_EQUAL: \
+ return (a == b); \
+ case F_LESSTHAN: \
+ return (a < b); \
+ case F_GREATER: \
+ return (a > b); \
+ default: \
+ abort(); \
+ } \
+} while(0)
+
+static PLAN *
+palloc(OPTION *option)
+{
+ PLAN *new;
+
+ if ((new = malloc(sizeof(PLAN))) == NULL)
+ err(1, NULL);
+ new->execute = option->execute;
+ new->flags = option->flags;
+ new->next = NULL;
+ return new;
+}
+
+/*
+ * find_parsenum --
+ * Parse a string of the form [+-]# and return the value.
+ */
+static long long
+find_parsenum(PLAN *plan, const char *option, char *vp, char *endch)
+{
+ long long value;
+ char *endchar, *str; /* Pointer to character ending conversion. */
+
+ /* Determine comparison from leading + or -. */
+ str = vp;
+ switch (*str) {
+ case '+':
+ ++str;
+ plan->flags |= F_GREATER;
+ break;
+ case '-':
+ ++str;
+ plan->flags |= F_LESSTHAN;
+ break;
+ default:
+ plan->flags |= F_EQUAL;
+ break;
+ }
+
+ /*
+ * Convert the string with strtoq(). Note, if strtoq() returns zero
+ * and endchar points to the beginning of the string we know we have
+ * a syntax error.
+ */
+ value = strtoq(str, &endchar, 10);
+ if (value == 0 && endchar == str)
+ errx(1, "%s: %s: illegal numeric value", option, vp);
+ if (endchar[0] && endch == NULL)
+ errx(1, "%s: %s: illegal trailing character", option, vp);
+ if (endch)
+ *endch = endchar[0];
+ return value;
+}
+
+/*
+ * find_parsetime --
+ * Parse a string of the form [+-]([0-9]+[smhdw]?)+ and return the value.
+ */
+static long long
+find_parsetime(PLAN *plan, const char *option, char *vp)
+{
+ long long secs, value;
+ char *str, *unit; /* Pointer to character ending conversion. */
+
+ /* Determine comparison from leading + or -. */
+ str = vp;
+ switch (*str) {
+ case '+':
+ ++str;
+ plan->flags |= F_GREATER;
+ break;
+ case '-':
+ ++str;
+ plan->flags |= F_LESSTHAN;
+ break;
+ default:
+ plan->flags |= F_EQUAL;
+ break;
+ }
+
+ value = strtoq(str, &unit, 10);
+ if (value == 0 && unit == str) {
+ errx(1, "%s: %s: illegal time value", option, vp);
+ /* NOTREACHED */
+ }
+ if (*unit == '\0')
+ return value;
+
+ /* Units syntax. */
+ secs = 0;
+ for (;;) {
+ switch(*unit) {
+ case 's': /* seconds */
+ secs += value;
+ break;
+ case 'm': /* minutes */
+ secs += value * 60;
+ break;
+ case 'h': /* hours */
+ secs += value * 3600;
+ break;
+ case 'd': /* days */
+ secs += value * 86400;
+ break;
+ case 'w': /* weeks */
+ secs += value * 604800;
+ break;
+ default:
+ errx(1, "%s: %s: bad unit '%c'", option, vp, *unit);
+ /* NOTREACHED */
+ }
+ str = unit + 1;
+ if (*str == '\0') /* EOS */
+ break;
+ value = strtoq(str, &unit, 10);
+ if (value == 0 && unit == str) {
+ errx(1, "%s: %s: illegal time value", option, vp);
+ /* NOTREACHED */
+ }
+ if (*unit == '\0') {
+ errx(1, "%s: %s: missing trailing unit", option, vp);
+ /* NOTREACHED */
+ }
+ }
+ plan->flags |= F_EXACTTIME;
+ return secs;
+}
+
+/*
+ * nextarg --
+ * Check that another argument still exists, return a pointer to it,
+ * and increment the argument vector pointer.
+ */
+static char *
+nextarg(OPTION *option, char ***argvp)
+{
+ char *arg;
+
+ if ((arg = **argvp) == NULL)
+ errx(1, "%s: requires additional arguments", option->name);
+ (*argvp)++;
+ return arg;
+} /* nextarg() */
+
+/*
+ * The value of n for the inode times (atime, birthtime, ctime, mtime) is a
+ * range, i.e. n matches from (n - 1) to n 24 hour periods. This interacts
+ * with -n, such that "-mtime -1" would be less than 0 days, which isn't what
+ * the user wanted. Correct so that -1 is "less than 1".
+ */
+#define TIME_CORRECT(p) \
+ if (((p)->flags & F_ELG_MASK) == F_LESSTHAN) \
+ ++((p)->t_data.tv_sec);
+
+/*
+ * -[acm]min n functions --
+ *
+ * True if the difference between the
+ * file access time (-amin)
+ * file birth time (-Bmin)
+ * last change of file status information (-cmin)
+ * file modification time (-mmin)
+ * and the current time is n min periods.
+ */
+int
+f_Xmin(PLAN *plan, FTSENT *entry)
+{
+ if (plan->flags & F_TIME_C) {
+ COMPARE((now - entry->fts_statp->st_ctime +
+ 60 - 1) / 60, plan->t_data.tv_sec);
+ } else if (plan->flags & F_TIME_A) {
+ COMPARE((now - entry->fts_statp->st_atime +
+ 60 - 1) / 60, plan->t_data.tv_sec);
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ } else if (plan->flags & F_TIME_B) {
+ COMPARE((now - entry->fts_statp->st_birthtime +
+ 60 - 1) / 60, plan->t_data.tv_sec);
+#endif
+ } else {
+ COMPARE((now - entry->fts_statp->st_mtime +
+ 60 - 1) / 60, plan->t_data.tv_sec);
+ }
+}
+
+PLAN *
+c_Xmin(OPTION *option, char ***argvp)
+{
+ char *nmins;
+ PLAN *new;
+
+ nmins = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ new->t_data.tv_sec = find_parsenum(new, option->name, nmins, NULL);
+ new->t_data.tv_nsec = 0;
+ TIME_CORRECT(new);
+ return new;
+}
+
+/*
+ * -[acm]time n functions --
+ *
+ * True if the difference between the
+ * file access time (-atime)
+ * file birth time (-Btime)
+ * last change of file status information (-ctime)
+ * file modification time (-mtime)
+ * and the current time is n 24 hour periods.
+ */
+
+int
+f_Xtime(PLAN *plan, FTSENT *entry)
+{
+ time_t xtime;
+
+ if (plan->flags & F_TIME_A)
+ xtime = entry->fts_statp->st_atime;
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ else if (plan->flags & F_TIME_B)
+ xtime = entry->fts_statp->st_birthtime;
+#endif
+ else if (plan->flags & F_TIME_C)
+ xtime = entry->fts_statp->st_ctime;
+ else
+ xtime = entry->fts_statp->st_mtime;
+
+ if (plan->flags & F_EXACTTIME)
+ COMPARE(now - xtime, plan->t_data.tv_sec);
+ else
+ COMPARE((now - xtime + 86400 - 1) / 86400, plan->t_data.tv_sec);
+}
+
+PLAN *
+c_Xtime(OPTION *option, char ***argvp)
+{
+ char *value;
+ PLAN *new;
+
+ value = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ new->t_data.tv_sec = find_parsetime(new, option->name, value);
+ new->t_data.tv_nsec = 0;
+ if (!(new->flags & F_EXACTTIME))
+ TIME_CORRECT(new);
+ return new;
+}
+
+/*
+ * -maxdepth/-mindepth n functions --
+ *
+ * Does the same as -prune if the level of the current file is
+ * greater/less than the specified maximum/minimum depth.
+ *
+ * Note that -maxdepth and -mindepth are handled specially in
+ * find_execute() so their f_* functions are set to f_always_true().
+ */
+PLAN *
+c_mXXdepth(OPTION *option, char ***argvp)
+{
+ char *dstr;
+ PLAN *new;
+
+ dstr = nextarg(option, argvp);
+ if (dstr[0] == '-')
+ /* all other errors handled by find_parsenum() */
+ errx(1, "%s: %s: value must be positive", option->name, dstr);
+
+ new = palloc(option);
+ if (option->flags & F_MAXDEPTH)
+ maxdepth = find_parsenum(new, option->name, dstr, NULL);
+ else
+ mindepth = find_parsenum(new, option->name, dstr, NULL);
+ return new;
+}
+
+#ifdef ACL_TYPE_NFS4
+/*
+ * -acl function --
+ *
+ * Show files with EXTENDED ACL attributes.
+ */
+int
+f_acl(PLAN *plan __unused, FTSENT *entry)
+{
+ acl_t facl;
+ acl_type_t acl_type;
+ int acl_supported = 0, ret, trivial;
+
+ if (S_ISLNK(entry->fts_statp->st_mode))
+ return 0;
+ ret = pathconf(entry->fts_accpath, _PC_ACL_NFS4);
+ if (ret > 0) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_NFS4;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("%s", entry->fts_accpath);
+ return (0);
+ }
+ if (acl_supported == 0) {
+ ret = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED);
+ if (ret > 0) {
+ acl_supported = 1;
+ acl_type = ACL_TYPE_ACCESS;
+ } else if (ret < 0 && errno != EINVAL) {
+ warn("%s", entry->fts_accpath);
+ return (0);
+ }
+ }
+ if (acl_supported == 0)
+ return (0);
+
+ facl = acl_get_file(entry->fts_accpath, acl_type);
+ if (facl == NULL) {
+ warn("%s", entry->fts_accpath);
+ return (0);
+ }
+ ret = acl_is_trivial_np(facl, &trivial);
+ acl_free(facl);
+ if (ret) {
+ warn("%s", entry->fts_accpath);
+ return (0);
+ }
+ if (trivial)
+ return (0);
+ return (1);
+}
+#endif
+
+PLAN *
+c_acl(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+ return (palloc(option));
+}
+
+/*
+ * -delete functions --
+ *
+ * True always. Makes its best shot and continues on regardless.
+ */
+int
+f_delete(PLAN *plan __unused, FTSENT *entry)
+{
+ /* ignore these from fts */
+ if (strcmp(entry->fts_accpath, ".") == 0 ||
+ strcmp(entry->fts_accpath, "..") == 0)
+ return 1;
+
+ /* sanity check */
+ if (isdepth == 0 || /* depth off */
+ (ftsoptions & FTS_NOSTAT)) /* not stat()ing */
+ errx(1, "-delete: insecure options got turned on");
+
+ if (!(ftsoptions & FTS_PHYSICAL) || /* physical off */
+ (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */
+ errx(1, "-delete: forbidden when symlinks are followed");
+
+ /* Potentially unsafe - do not accept relative paths whatsoever */
+ if (entry->fts_level > FTS_ROOTLEVEL &&
+ strchr(entry->fts_accpath, '/') != NULL)
+ errx(1, "-delete: %s: relative path potentially not safe",
+ entry->fts_accpath);
+
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ /* Turn off user immutable bits if running as root */
+ if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
+ !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ geteuid() == 0)
+ lchflags(entry->fts_accpath,
+ entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
+#endif
+
+ /* rmdir directories, unlink everything else */
+ if (S_ISDIR(entry->fts_statp->st_mode)) {
+ if (rmdir(entry->fts_accpath) < 0 && errno != ENOTEMPTY)
+ warn("-delete: rmdir(%s)", entry->fts_path);
+ } else {
+ if (unlink(entry->fts_accpath) < 0)
+ warn("-delete: unlink(%s)", entry->fts_path);
+ }
+
+ /* "succeed" */
+ return 1;
+}
+
+PLAN *
+c_delete(OPTION *option, char ***argvp __unused)
+{
+
+ ftsoptions &= ~FTS_NOSTAT; /* no optimise */
+ isoutput = 1; /* possible output */
+ isdepth = 1; /* -depth implied */
+
+ /*
+ * Try to avoid the confusing error message about relative paths
+ * being potentially not safe.
+ */
+ if (ftsoptions & FTS_NOCHDIR)
+ errx(1, "%s: forbidden when the current directory cannot be opened",
+ "-delete");
+
+ return palloc(option);
+}
+
+
+/*
+ * always_true --
+ *
+ * Always true, used for -maxdepth, -mindepth, -xdev, -follow, and -true
+ */
+int
+f_always_true(PLAN *plan __unused, FTSENT *entry __unused)
+{
+ return 1;
+}
+
+/*
+ * -depth functions --
+ *
+ * With argument: True if the file is at level n.
+ * Without argument: Always true, causes descent of the directory hierarchy
+ * to be done so that all entries in a directory are acted on before the
+ * directory itself.
+ */
+int
+f_depth(PLAN *plan, FTSENT *entry)
+{
+ if (plan->flags & F_DEPTH)
+ COMPARE(entry->fts_level, plan->d_data);
+ else
+ return 1;
+}
+
+PLAN *
+c_depth(OPTION *option, char ***argvp)
+{
+ PLAN *new;
+ char *str;
+
+ new = palloc(option);
+
+ str = **argvp;
+ if (str && !(new->flags & F_DEPTH)) {
+ /* skip leading + or - */
+ if (*str == '+' || *str == '-')
+ str++;
+ /* skip sign */
+ if (*str == '+' || *str == '-')
+ str++;
+ if (isdigit(*str))
+ new->flags |= F_DEPTH;
+ }
+
+ if (new->flags & F_DEPTH) { /* -depth n */
+ char *ndepth;
+
+ ndepth = nextarg(option, argvp);
+ new->d_data = find_parsenum(new, option->name, ndepth, NULL);
+ } else { /* -d */
+ isdepth = 1;
+ }
+
+ return new;
+}
+
+/*
+ * -empty functions --
+ *
+ * True if the file or directory is empty
+ */
+int
+f_empty(PLAN *plan __unused, FTSENT *entry)
+{
+ if (S_ISREG(entry->fts_statp->st_mode) &&
+ entry->fts_statp->st_size == 0)
+ return 1;
+ if (S_ISDIR(entry->fts_statp->st_mode)) {
+ struct dirent *dp;
+ int empty;
+ DIR *dir;
+
+ empty = 1;
+ dir = opendir(entry->fts_accpath);
+ if (dir == NULL)
+ return 0;
+ for (dp = readdir(dir); dp; dp = readdir(dir))
+ if (dp->d_name[0] != '.' ||
+ (dp->d_name[1] != '\0' &&
+ (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) {
+ empty = 0;
+ break;
+ }
+ closedir(dir);
+ return empty;
+ }
+ return 0;
+}
+
+PLAN *
+c_empty(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+
+ return palloc(option);
+}
+
+/*
+ * [-exec | -execdir | -ok] utility [arg ... ] ; functions --
+ *
+ * True if the executed utility returns a zero value as exit status.
+ * The end of the primary expression is delimited by a semicolon. If
+ * "{}" occurs anywhere, it gets replaced by the current pathname,
+ * or, in the case of -execdir, the current basename (filename
+ * without leading directory prefix). For -exec and -ok,
+ * the current directory for the execution of utility is the same as
+ * the current directory when the find utility was started, whereas
+ * for -execdir, it is the directory the file resides in.
+ *
+ * The primary -ok differs from -exec in that it requests affirmation
+ * of the user before executing the utility.
+ */
+int
+f_exec(PLAN *plan, FTSENT *entry)
+{
+ int cnt;
+ pid_t pid;
+ int status;
+ char *file;
+
+ if (entry == NULL && plan->flags & F_EXECPLUS) {
+ if (plan->e_ppos == plan->e_pbnum)
+ return (1);
+ plan->e_argv[plan->e_ppos] = NULL;
+ goto doexec;
+ }
+
+ /* XXX - if file/dir ends in '/' this will not work -- can it? */
+ if ((plan->flags & F_EXECDIR) && \
+ (file = strrchr(entry->fts_path, '/')))
+ file++;
+ else
+ file = entry->fts_path;
+
+ if (plan->flags & F_EXECPLUS) {
+ if ((plan->e_argv[plan->e_ppos] = strdup(file)) == NULL)
+ err(1, NULL);
+ plan->e_len[plan->e_ppos] = strlen(file);
+ plan->e_psize += plan->e_len[plan->e_ppos];
+ if (++plan->e_ppos < plan->e_pnummax &&
+ plan->e_psize < plan->e_psizemax)
+ return (1);
+ plan->e_argv[plan->e_ppos] = NULL;
+ } else {
+ for (cnt = 0; plan->e_argv[cnt]; ++cnt)
+ if (plan->e_len[cnt])
+ brace_subst(plan->e_orig[cnt],
+ &plan->e_argv[cnt], file,
+ plan->e_len[cnt]);
+ }
+
+doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
+ return 0;
+
+ /* make sure find output is interspersed correctly with subprocesses */
+ fflush(stdout);
+ fflush(stderr);
+
+ switch (pid = fork()) {
+ case -1:
+ err(1, "fork");
+ /* NOTREACHED */
+ case 0:
+ /* change dir back from where we started */
+ if (!(plan->flags & F_EXECDIR) &&
+ !(ftsoptions & FTS_NOCHDIR) && fchdir(dotfd)) {
+ warn("chdir");
+ _exit(1);
+ }
+ execvp(plan->e_argv[0], plan->e_argv);
+ warn("%s", plan->e_argv[0]);
+ _exit(1);
+ }
+ if (plan->flags & F_EXECPLUS) {
+ while (--plan->e_ppos >= plan->e_pbnum)
+ free(plan->e_argv[plan->e_ppos]);
+ plan->e_ppos = plan->e_pbnum;
+ plan->e_psize = plan->e_pbsize;
+ }
+ pid = waitpid(pid, &status, 0);
+ if (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status))
+ return (1);
+ if (plan->flags & F_EXECPLUS) {
+ exitstatus = 1;
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * c_exec, c_execdir, c_ok --
+ * build three parallel arrays, one with pointers to the strings passed
+ * on the command line, one with (possibly duplicated) pointers to the
+ * argv array, and one with integer values that are lengths of the
+ * strings, but also flags meaning that the string has to be massaged.
+ */
+PLAN *
+c_exec(OPTION *option, char ***argvp)
+{
+ PLAN *new; /* node returned */
+ long argmax;
+ int cnt, i;
+ char **argv, **ap, **ep, *p;
+
+ /* This would defeat -execdir's intended security. */
+ if (option->flags & F_EXECDIR && ftsoptions & FTS_NOCHDIR)
+ errx(1, "%s: forbidden when the current directory cannot be opened",
+ "-execdir");
+
+ /* XXX - was in c_execdir, but seems unnecessary!?
+ ftsoptions &= ~FTS_NOSTAT;
+ */
+ isoutput = 1;
+
+ /* XXX - this is a change from the previous coding */
+ new = palloc(option);
+
+ for (ap = argv = *argvp;; ++ap) {
+ if (!*ap)
+ errx(1,
+ "%s: no terminating \";\" or \"+\"", option->name);
+ if (**ap == ';')
+ break;
+ if (**ap == '+' && ap != argv && strcmp(*(ap - 1), "{}") == 0) {
+ new->flags |= F_EXECPLUS;
+ break;
+ }
+ }
+
+ if (ap == argv)
+ errx(1, "%s: no command specified", option->name);
+
+ cnt = ap - *argvp + 1;
+ if (new->flags & F_EXECPLUS) {
+ new->e_ppos = new->e_pbnum = cnt - 2;
+ if ((argmax = sysconf(_SC_ARG_MAX)) == -1) {
+ warn("sysconf(_SC_ARG_MAX)");
+ argmax = _POSIX_ARG_MAX;
+ }
+ argmax -= 1024;
+ for (ep = environ; *ep != NULL; ep++)
+ argmax -= strlen(*ep) + 1 + sizeof(*ep);
+ argmax -= 1 + sizeof(*ep);
+ /*
+ * Ensure that -execdir ... {} + does not mix files
+ * from different directories in one invocation.
+ * Files from the same directory should be handled
+ * in one invocation but there is no code for it.
+ */
+ new->e_pnummax = new->flags & F_EXECDIR ? 1 : argmax / 16;
+ argmax -= sizeof(char *) * new->e_pnummax;
+ if (argmax <= 0)
+ errx(1, "no space for arguments");
+ new->e_psizemax = argmax;
+ new->e_pbsize = 0;
+ cnt += new->e_pnummax + 1;
+ new->e_next = lastexecplus;
+ lastexecplus = new;
+ }
+ if ((new->e_argv = malloc(cnt * sizeof(char *))) == NULL)
+ err(1, NULL);
+ if ((new->e_orig = malloc(cnt * sizeof(char *))) == NULL)
+ err(1, NULL);
+ if ((new->e_len = malloc(cnt * sizeof(int))) == NULL)
+ err(1, NULL);
+
+ for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
+ new->e_orig[cnt] = *argv;
+ if (new->flags & F_EXECPLUS)
+ new->e_pbsize += strlen(*argv) + 1;
+ for (p = *argv; *p; ++p)
+ if (!(new->flags & F_EXECPLUS) && p[0] == '{' &&
+ p[1] == '}') {
+ if ((new->e_argv[cnt] =
+ malloc(MAXPATHLEN)) == NULL)
+ err(1, NULL);
+ new->e_len[cnt] = MAXPATHLEN;
+ break;
+ }
+ if (!*p) {
+ new->e_argv[cnt] = *argv;
+ new->e_len[cnt] = 0;
+ }
+ }
+ if (new->flags & F_EXECPLUS) {
+ new->e_psize = new->e_pbsize;
+ cnt--;
+ for (i = 0; i < new->e_pnummax; i++) {
+ new->e_argv[cnt] = NULL;
+ new->e_len[cnt] = 0;
+ cnt++;
+ }
+ argv = ap;
+ goto done;
+ }
+ new->e_argv[cnt] = new->e_orig[cnt] = NULL;
+
+done: *argvp = argv + 1;
+ return new;
+}
+
+/* Finish any pending -exec ... {} + functions. */
+void
+finish_execplus(void)
+{
+ PLAN *p;
+
+ p = lastexecplus;
+ while (p != NULL) {
+ (p->execute)(p, NULL);
+ p = p->e_next;
+ }
+}
+
+#if HAVE_STRUCT_STAT_ST_FLAGS
+int
+f_flags(PLAN *plan, FTSENT *entry)
+{
+ u_long flags;
+
+ flags = entry->fts_statp->st_flags;
+ if (plan->flags & F_ATLEAST)
+ return (flags | plan->fl_flags) == flags &&
+ !(flags & plan->fl_notflags);
+ else if (plan->flags & F_ANY)
+ return (flags & plan->fl_flags) ||
+ (flags | plan->fl_notflags) != flags;
+ else
+ return flags == plan->fl_flags &&
+ !(plan->fl_flags & plan->fl_notflags);
+}
+
+PLAN *
+c_flags(OPTION *option, char ***argvp)
+{
+ char *flags_str;
+ PLAN *new;
+ u_long flags, notflags;
+
+ flags_str = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+
+ if (*flags_str == '-') {
+ new->flags |= F_ATLEAST;
+ flags_str++;
+ } else if (*flags_str == '+') {
+ new->flags |= F_ANY;
+ flags_str++;
+ }
+ if (strtofflags(&flags_str, &flags, &notflags) == 1)
+ errx(1, "%s: %s: illegal flags string", option->name, flags_str);
+
+ new->fl_flags = flags;
+ new->fl_notflags = notflags;
+ return new;
+}
+#endif
+
+/*
+ * -follow functions --
+ *
+ * Always true, causes symbolic links to be followed on a global
+ * basis.
+ */
+PLAN *
+c_follow(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_PHYSICAL;
+ ftsoptions |= FTS_LOGICAL;
+
+ return palloc(option);
+}
+
+#if HAVE_STRUCT_STATFS_F_FSTYPENAME
+/*
+ * -fstype functions --
+ *
+ * True if the file is of a certain type.
+ */
+int
+f_fstype(PLAN *plan, FTSENT *entry)
+{
+ static dev_t curdev; /* need a guaranteed illegal dev value */
+ static int first = 1;
+ struct statfs sb;
+ static int val_flags;
+ static char fstype[sizeof(sb.f_fstypename)];
+ char *p, save[2] = {0,0};
+
+ if ((plan->flags & F_MTMASK) == F_MTUNKNOWN)
+ return 0;
+
+ /* Only check when we cross mount point. */
+ if (first || curdev != entry->fts_statp->st_dev) {
+ curdev = entry->fts_statp->st_dev;
+
+ /*
+ * Statfs follows symlinks; find wants the link's filesystem,
+ * not where it points.
+ */
+ if (entry->fts_info == FTS_SL ||
+ entry->fts_info == FTS_SLNONE) {
+ if ((p = strrchr(entry->fts_accpath, '/')) != NULL)
+ ++p;
+ else
+ p = entry->fts_accpath;
+ save[0] = p[0];
+ p[0] = '.';
+ save[1] = p[1];
+ p[1] = '\0';
+ } else
+ p = NULL;
+
+ if (statfs(entry->fts_accpath, &sb)) {
+ if (!ignore_readdir_race || errno != ENOENT) {
+ warn("statfs: %s", entry->fts_accpath);
+ exitstatus = 1;
+ }
+ return 0;
+ }
+
+ if (p) {
+ p[0] = save[0];
+ p[1] = save[1];
+ }
+
+ first = 0;
+
+ /*
+ * Further tests may need both of these values, so
+ * always copy both of them.
+ */
+ val_flags = sb.f_flags;
+ strlcpy(fstype, sb.f_fstypename, sizeof(fstype));
+ }
+ switch (plan->flags & F_MTMASK) {
+ case F_MTFLAG:
+ return val_flags & plan->mt_data;
+ case F_MTTYPE:
+ return (strncmp(fstype, plan->c_data, sizeof(fstype)) == 0);
+ default:
+ abort();
+ }
+}
+
+PLAN *
+c_fstype(OPTION *option, char ***argvp)
+{
+ char *fsname;
+ PLAN *new;
+
+ fsname = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ switch (*fsname) {
+ case 'l':
+ if (!strcmp(fsname, "local")) {
+ new->flags |= F_MTFLAG;
+ new->mt_data = MNT_LOCAL;
+ return new;
+ }
+ break;
+ case 'r':
+ if (!strcmp(fsname, "rdonly")) {
+ new->flags |= F_MTFLAG;
+ new->mt_data = MNT_RDONLY;
+ return new;
+ }
+ break;
+ }
+
+ new->flags |= F_MTTYPE;
+ new->c_data = fsname;
+ return new;
+}
+#endif
+
+/*
+ * -group gname functions --
+ *
+ * True if the file belongs to the group gname. If gname is numeric and
+ * an equivalent of the getgrnam() function does not return a valid group
+ * name, gname is taken as a group ID.
+ */
+int
+f_group(PLAN *plan, FTSENT *entry)
+{
+ COMPARE(entry->fts_statp->st_gid, plan->g_data);
+}
+
+PLAN *
+c_group(OPTION *option, char ***argvp)
+{
+ char *gname;
+ PLAN *new;
+ struct group *g;
+ gid_t gid;
+
+ gname = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ g = getgrnam(gname);
+ if (g == NULL) {
+ char* cp = gname;
+ if (gname[0] == '-' || gname[0] == '+')
+ gname++;
+ gid = atoi(gname);
+ if (gid == 0 && gname[0] != '0')
+ errx(1, "%s: %s: no such group", option->name, gname);
+ gid = find_parsenum(new, option->name, cp, NULL);
+ } else
+ gid = g->gr_gid;
+
+ new->g_data = gid;
+ return new;
+}
+
+/*
+ * -ignore_readdir_race functions --
+ *
+ * Always true. Ignore errors which occur if a file or a directory
+ * in a starting point gets deleted between reading the name and calling
+ * stat on it while find is traversing the starting point.
+ */
+
+PLAN *
+c_ignore_readdir_race(OPTION *option, char ***argvp __unused)
+{
+ if (strcmp(option->name, "-ignore_readdir_race") == 0)
+ ignore_readdir_race = 1;
+ else
+ ignore_readdir_race = 0;
+
+ return palloc(option);
+}
+
+/*
+ * -inum n functions --
+ *
+ * True if the file has inode # n.
+ */
+int
+f_inum(PLAN *plan, FTSENT *entry)
+{
+ COMPARE(entry->fts_statp->st_ino, plan->i_data);
+}
+
+PLAN *
+c_inum(OPTION *option, char ***argvp)
+{
+ char *inum_str;
+ PLAN *new;
+
+ inum_str = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ new->i_data = find_parsenum(new, option->name, inum_str, NULL);
+ return new;
+}
+
+/*
+ * -samefile FN
+ *
+ * True if the file has the same inode (eg hard link) FN
+ */
+
+/* f_samefile is just f_inum */
+PLAN *
+c_samefile(OPTION *option, char ***argvp)
+{
+ char *fn;
+ PLAN *new;
+ struct stat sb;
+ int error;
+
+ fn = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ if (ftsoptions & FTS_PHYSICAL)
+ error = lstat(fn, &sb);
+ else
+ error = stat(fn, &sb);
+ if (error != 0)
+ err(1, "%s", fn);
+ new->i_data = sb.st_ino;
+ return new;
+}
+
+/*
+ * -links n functions --
+ *
+ * True if the file has n links.
+ */
+int
+f_links(PLAN *plan, FTSENT *entry)
+{
+ COMPARE(entry->fts_statp->st_nlink, plan->l_data);
+}
+
+PLAN *
+c_links(OPTION *option, char ***argvp)
+{
+ char *nlinks;
+ PLAN *new;
+
+ nlinks = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ new->l_data = (nlink_t)find_parsenum(new, option->name, nlinks, NULL);
+ return new;
+}
+
+/*
+ * -ls functions --
+ *
+ * Always true - prints the current entry to stdout in "ls" format.
+ */
+int
+f_ls(PLAN *plan __unused, FTSENT *entry)
+{
+ printlong(entry->fts_path, entry->fts_accpath, entry->fts_statp);
+ return 1;
+}
+
+PLAN *
+c_ls(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+ isoutput = 1;
+
+ return palloc(option);
+}
+
+/*
+ * -name functions --
+ *
+ * True if the basename of the filename being examined
+ * matches pattern using Pattern Matching Notation S3.14
+ */
+int
+f_name(PLAN *plan, FTSENT *entry)
+{
+ char fn[PATH_MAX];
+ const char *name;
+ ssize_t len;
+
+ if (plan->flags & F_LINK) {
+ /*
+ * The below test both avoids obviously useless readlink()
+ * calls and ensures that symlinks with existent target do
+ * not match if symlinks are being followed.
+ * Assumption: fts will stat all symlinks that are to be
+ * followed and will return the stat information.
+ */
+ if (entry->fts_info != FTS_NSOK && entry->fts_info != FTS_SL &&
+ entry->fts_info != FTS_SLNONE)
+ return 0;
+ len = readlink(entry->fts_accpath, fn, sizeof(fn) - 1);
+ if (len == -1)
+ return 0;
+ fn[len] = '\0';
+ name = fn;
+ } else
+ name = entry->fts_name;
+ return !fnmatch(plan->c_data, name,
+ plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
+}
+
+PLAN *
+c_name(OPTION *option, char ***argvp)
+{
+ char *pattern;
+ PLAN *new;
+
+ pattern = nextarg(option, argvp);
+ new = palloc(option);
+ new->c_data = pattern;
+ return new;
+}
+
+/*
+ * -newer file functions --
+ *
+ * True if the current file has been modified more recently
+ * then the modification time of the file named by the pathname
+ * file.
+ */
+int
+f_newer(PLAN *plan, FTSENT *entry)
+{
+ struct timespec ft;
+
+ if (plan->flags & F_TIME_C)
+ ft = entry->fts_statp->st_ctim;
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ else if (plan->flags & F_TIME_A)
+ ft = entry->fts_statp->st_atim;
+ else if (plan->flags & F_TIME_B)
+ ft = entry->fts_statp->st_birthtim;
+#endif
+ else
+ ft = entry->fts_statp->st_mtim;
+ return (ft.tv_sec > plan->t_data.tv_sec ||
+ (ft.tv_sec == plan->t_data.tv_sec &&
+ ft.tv_nsec > plan->t_data.tv_nsec));
+}
+
+PLAN *
+c_newer(OPTION *option, char ***argvp)
+{
+ char *fn_or_tspec;
+ PLAN *new;
+ struct stat sb;
+ int error;
+
+ fn_or_tspec = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ /* compare against what */
+ if (option->flags & F_TIME2_T) {
+ new->t_data.tv_sec = get_date(fn_or_tspec);
+ if (new->t_data.tv_sec == (time_t) -1)
+ errx(1, "Can't parse date/time: %s", fn_or_tspec);
+ /* Use the seconds only in the comparison. */
+ new->t_data.tv_nsec = 999999999;
+ } else {
+ if (ftsoptions & FTS_PHYSICAL)
+ error = lstat(fn_or_tspec, &sb);
+ else
+ error = stat(fn_or_tspec, &sb);
+ if (error != 0)
+ err(1, "%s", fn_or_tspec);
+ if (option->flags & F_TIME2_C)
+ new->t_data = sb.st_ctim;
+ else if (option->flags & F_TIME2_A)
+ new->t_data = sb.st_atim;
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ else if (option->flags & F_TIME2_B)
+ new->t_data = sb.st_birthtim;
+#endif
+ else
+ new->t_data = sb.st_mtim;
+ }
+ return new;
+}
+
+/*
+ * -nogroup functions --
+ *
+ * True if file belongs to a user ID for which the equivalent
+ * of the getgrnam() 9.2.1 [POSIX.1] function returns NULL.
+ */
+int
+f_nogroup(PLAN *plan __unused, FTSENT *entry)
+{
+ return group_from_gid(entry->fts_statp->st_gid, 1) == NULL;
+}
+
+PLAN *
+c_nogroup(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+
+ return palloc(option);
+}
+
+/*
+ * -nouser functions --
+ *
+ * True if file belongs to a user ID for which the equivalent
+ * of the getpwuid() 9.2.2 [POSIX.1] function returns NULL.
+ */
+int
+f_nouser(PLAN *plan __unused, FTSENT *entry)
+{
+ return user_from_uid(entry->fts_statp->st_uid, 1) == NULL;
+}
+
+PLAN *
+c_nouser(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+
+ return palloc(option);
+}
+
+/*
+ * -path functions --
+ *
+ * True if the path of the filename being examined
+ * matches pattern using Pattern Matching Notation S3.14
+ */
+int
+f_path(PLAN *plan, FTSENT *entry)
+{
+ return !fnmatch(plan->c_data, entry->fts_path,
+ plan->flags & F_IGNCASE ? FNM_CASEFOLD : 0);
+}
+
+/* c_path is the same as c_name */
+
+/*
+ * -perm functions --
+ *
+ * The mode argument is used to represent file mode bits. If it starts
+ * with a leading digit, it's treated as an octal mode, otherwise as a
+ * symbolic mode.
+ */
+int
+f_perm(PLAN *plan, FTSENT *entry)
+{
+ mode_t mode;
+
+ mode = entry->fts_statp->st_mode &
+ (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO);
+ if (plan->flags & F_ATLEAST)
+ return (plan->m_data | mode) == mode;
+ else if (plan->flags & F_ANY)
+ return (mode & plan->m_data);
+ else
+ return mode == plan->m_data;
+ /* NOTREACHED */
+}
+
+PLAN *
+c_perm(OPTION *option, char ***argvp)
+{
+ char *perm;
+ PLAN *new;
+ mode_t *set;
+
+ perm = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+
+ if (*perm == '-') {
+ new->flags |= F_ATLEAST;
+ ++perm;
+ } else if (*perm == '+' || *perm == '/') {
+ new->flags |= F_ANY;
+ ++perm;
+ }
+
+ if ((set = setmode(perm)) == NULL)
+ errx(1, "%s: %s: illegal mode string", option->name, perm);
+
+ new->m_data = getmode(set, 0);
+ free(set);
+ return new;
+}
+
+/*
+ * -print functions --
+ *
+ * Always true, causes the current pathname to be written to
+ * standard output.
+ */
+int
+f_print(PLAN *plan __unused, FTSENT *entry)
+{
+ (void)puts(entry->fts_path);
+ return 1;
+}
+
+PLAN *
+c_print(OPTION *option, char ***argvp __unused)
+{
+ isoutput = 1;
+
+ return palloc(option);
+}
+
+/*
+ * -print0 functions --
+ *
+ * Always true, causes the current pathname to be written to
+ * standard output followed by a NUL character
+ */
+int
+f_print0(PLAN *plan __unused, FTSENT *entry)
+{
+ fputs(entry->fts_path, stdout);
+ fputc('\0', stdout);
+ return 1;
+}
+
+/* c_print0 is the same as c_print */
+
+/*
+ * -prune functions --
+ *
+ * Prune a portion of the hierarchy.
+ */
+int
+f_prune(PLAN *plan __unused, FTSENT *entry)
+{
+ if (fts_set(tree, entry, FTS_SKIP))
+ err(1, "%s", entry->fts_path);
+ return 1;
+}
+
+/* c_prune == c_simple */
+
+/*
+ * -regex functions --
+ *
+ * True if the whole path of the file matches pattern using
+ * regular expression.
+ */
+int
+f_regex(PLAN *plan, FTSENT *entry)
+{
+ char *str;
+ int len;
+ regex_t *pre;
+ regmatch_t pmatch;
+ int errcode;
+ char errbuf[LINE_MAX];
+ int matched;
+
+ pre = plan->re_data;
+ str = entry->fts_path;
+ len = strlen(str);
+ matched = 0;
+
+ pmatch.rm_so = 0;
+ pmatch.rm_eo = len;
+
+ errcode = regexec(pre, str, 1, &pmatch, REG_STARTEND);
+
+ if (errcode != 0 && errcode != REG_NOMATCH) {
+ regerror(errcode, pre, errbuf, sizeof errbuf);
+ errx(1, "%s: %s",
+ plan->flags & F_IGNCASE ? "-iregex" : "-regex", errbuf);
+ }
+
+ if (errcode == 0 && pmatch.rm_so == 0 && pmatch.rm_eo == len)
+ matched = 1;
+
+ return matched;
+}
+
+PLAN *
+c_regex(OPTION *option, char ***argvp)
+{
+ PLAN *new;
+ char *pattern;
+ regex_t *pre;
+ int errcode;
+ char errbuf[LINE_MAX];
+
+ if ((pre = malloc(sizeof(regex_t))) == NULL)
+ err(1, NULL);
+
+ pattern = nextarg(option, argvp);
+
+ if ((errcode = regcomp(pre, pattern,
+ regexp_flags | (option->flags & F_IGNCASE ? REG_ICASE : 0))) != 0) {
+ regerror(errcode, pre, errbuf, sizeof errbuf);
+ errx(1, "%s: %s: %s",
+ option->flags & F_IGNCASE ? "-iregex" : "-regex",
+ pattern, errbuf);
+ }
+
+ new = palloc(option);
+ new->re_data = pre;
+
+ return new;
+}
+
+/* c_simple covers c_prune, c_openparen, c_closeparen, c_not, c_or, c_true, c_false */
+
+PLAN *
+c_simple(OPTION *option, char ***argvp __unused)
+{
+ return palloc(option);
+}
+
+/*
+ * -size n[c] functions --
+ *
+ * True if the file size in bytes, divided by an implementation defined
+ * value and rounded up to the next integer, is n. If n is followed by
+ * one of c k M G T P, the size is in bytes, kilobytes,
+ * megabytes, gigabytes, terabytes or petabytes respectively.
+ */
+#define FIND_SIZE 512
+static int divsize = 1;
+
+int
+f_size(PLAN *plan, FTSENT *entry)
+{
+ off_t size;
+
+ size = divsize ? (entry->fts_statp->st_size + FIND_SIZE - 1) /
+ FIND_SIZE : entry->fts_statp->st_size;
+ COMPARE(size, plan->o_data);
+}
+
+PLAN *
+c_size(OPTION *option, char ***argvp)
+{
+ char *size_str;
+ PLAN *new;
+ char endch;
+ off_t scale;
+
+ size_str = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ endch = 'c';
+ new->o_data = find_parsenum(new, option->name, size_str, &endch);
+ if (endch != '\0') {
+ divsize = 0;
+
+ switch (endch) {
+ case 'c': /* characters */
+ scale = 0x1LL;
+ break;
+ case 'k': /* kilobytes 1<<10 */
+ scale = 0x400LL;
+ break;
+ case 'M': /* megabytes 1<<20 */
+ scale = 0x100000LL;
+ break;
+ case 'G': /* gigabytes 1<<30 */
+ scale = 0x40000000LL;
+ break;
+ case 'T': /* terabytes 1<<40 */
+ scale = 0x10000000000LL;
+ break;
+ case 'P': /* petabytes 1<<50 */
+ scale = 0x4000000000000LL;
+ break;
+ default:
+ errx(1, "%s: %s: illegal trailing character",
+ option->name, size_str);
+ break;
+ }
+ if (new->o_data > QUAD_MAX / scale)
+ errx(1, "%s: %s: value too large",
+ option->name, size_str);
+ new->o_data *= scale;
+ }
+ return new;
+}
+
+/*
+ * -sparse functions --
+ *
+ * Check if a file is sparse by finding if it occupies fewer blocks
+ * than we expect based on its size.
+ */
+int
+f_sparse(PLAN *plan __unused, FTSENT *entry)
+{
+ off_t expected_blocks;
+
+ expected_blocks = (entry->fts_statp->st_size + 511) / 512;
+ return entry->fts_statp->st_blocks < expected_blocks;
+}
+
+PLAN *
+c_sparse(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions &= ~FTS_NOSTAT;
+
+ return palloc(option);
+}
+
+/*
+ * -type c functions --
+ *
+ * True if the type of the file is c, where c is b, c, d, p, f or w
+ * for block special file, character special file, directory, FIFO,
+ * regular file or whiteout respectively.
+ */
+int
+f_type(PLAN *plan, FTSENT *entry)
+{
+ if (plan->m_data == S_IFDIR)
+ return (entry->fts_info == FTS_D || entry->fts_info == FTS_DC ||
+ entry->fts_info == FTS_DNR || entry->fts_info == FTS_DOT ||
+ entry->fts_info == FTS_DP);
+ else
+ return (entry->fts_statp->st_mode & S_IFMT) == plan->m_data;
+}
+
+PLAN *
+c_type(OPTION *option, char ***argvp)
+{
+ char *typestring;
+ PLAN *new;
+ mode_t mask;
+
+ typestring = nextarg(option, argvp);
+ if (typestring[0] != 'd')
+ ftsoptions &= ~FTS_NOSTAT;
+
+ switch (typestring[0]) {
+ case 'b':
+ mask = S_IFBLK;
+ break;
+ case 'c':
+ mask = S_IFCHR;
+ break;
+ case 'd':
+ mask = S_IFDIR;
+ break;
+ case 'f':
+ mask = S_IFREG;
+ break;
+ case 'l':
+ mask = S_IFLNK;
+ break;
+ case 'p':
+ mask = S_IFIFO;
+ break;
+ case 's':
+ mask = S_IFSOCK;
+ break;
+#if defined(FTS_WHITEOUT) && defined(S_IFWHT)
+ case 'w':
+ mask = S_IFWHT;
+ ftsoptions |= FTS_WHITEOUT;
+ break;
+#endif /* FTS_WHITEOUT */
+ default:
+ errx(1, "%s: %s: unknown type", option->name, typestring);
+ }
+
+ new = palloc(option);
+ new->m_data = mask;
+ return new;
+}
+
+/*
+ * -user uname functions --
+ *
+ * True if the file belongs to the user uname. If uname is numeric and
+ * an equivalent of the getpwnam() S9.2.2 [POSIX.1] function does not
+ * return a valid user name, uname is taken as a user ID.
+ */
+int
+f_user(PLAN *plan, FTSENT *entry)
+{
+ COMPARE(entry->fts_statp->st_uid, plan->u_data);
+}
+
+PLAN *
+c_user(OPTION *option, char ***argvp)
+{
+ char *username;
+ PLAN *new;
+ struct passwd *p;
+ uid_t uid;
+
+ username = nextarg(option, argvp);
+ ftsoptions &= ~FTS_NOSTAT;
+
+ new = palloc(option);
+ p = getpwnam(username);
+ if (p == NULL) {
+ char* cp = username;
+ if( username[0] == '-' || username[0] == '+' )
+ username++;
+ uid = atoi(username);
+ if (uid == 0 && username[0] != '0')
+ errx(1, "%s: %s: no such user", option->name, username);
+ uid = find_parsenum(new, option->name, cp, NULL);
+ } else
+ uid = p->pw_uid;
+
+ new->u_data = uid;
+ return new;
+}
+
+/*
+ * -xdev functions --
+ *
+ * Always true, causes find not to descend past directories that have a
+ * different device ID (st_dev, see stat() S5.6.2 [POSIX.1])
+ */
+PLAN *
+c_xdev(OPTION *option, char ***argvp __unused)
+{
+ ftsoptions |= FTS_XDEV;
+
+ return palloc(option);
+}
+
+/*
+ * ( expression ) functions --
+ *
+ * True if expression is true.
+ */
+int
+f_expr(PLAN *plan, FTSENT *entry)
+{
+ PLAN *p;
+ int state = 0;
+
+ for (p = plan->p_data[0];
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return state;
+}
+
+/*
+ * f_openparen and f_closeparen nodes are temporary place markers. They are
+ * eliminated during phase 2 of find_formplan() --- the '(' node is converted
+ * to a f_expr node containing the expression and the ')' node is discarded.
+ * The functions themselves are only used as constants.
+ */
+
+int
+f_openparen(PLAN *plan __unused, FTSENT *entry __unused)
+{
+ abort();
+}
+
+int
+f_closeparen(PLAN *plan __unused, FTSENT *entry __unused)
+{
+ abort();
+}
+
+/* c_openparen == c_simple */
+/* c_closeparen == c_simple */
+
+/*
+ * AND operator. Since AND is implicit, no node is allocated.
+ */
+PLAN *
+c_and(OPTION *option __unused, char ***argvp __unused)
+{
+ return NULL;
+}
+
+/*
+ * ! expression functions --
+ *
+ * Negation of a primary; the unary NOT operator.
+ */
+int
+f_not(PLAN *plan, FTSENT *entry)
+{
+ PLAN *p;
+ int state = 0;
+
+ for (p = plan->p_data[0];
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return !state;
+}
+
+/* c_not == c_simple */
+
+/*
+ * expression -o expression functions --
+ *
+ * Alternation of primaries; the OR operator. The second expression is
+ * not evaluated if the first expression is true.
+ */
+int
+f_or(PLAN *plan, FTSENT *entry)
+{
+ PLAN *p;
+ int state = 0;
+
+ for (p = plan->p_data[0];
+ p && (state = (p->execute)(p, entry)); p = p->next);
+
+ if (state)
+ return 1;
+
+ for (p = plan->p_data[1];
+ p && (state = (p->execute)(p, entry)); p = p->next);
+ return state;
+}
+
+/* c_or == c_simple */
+
+/*
+ * -false
+ *
+ * Always false.
+ */
+int
+f_false(PLAN *plan __unused, FTSENT *entry __unused)
+{
+ return 0;
+}
+
+/* c_false == c_simple */
+
+/*
+ * -quit
+ *
+ * Exits the program
+ */
+int
+f_quit(PLAN *plan __unused, FTSENT *entry __unused)
+{
+ finish_execplus();
+ exit(exitstatus);
+}
+
+/* c_quit == c_simple */
+
+/*
+ * -readable
+ *
+ * File is readable
+ */
+int
+f_readable(PLAN *plan __unused, FTSENT *entry)
+{
+ return (access(entry->fts_path, R_OK) == 0);
+}
+
+/* c_readable == c_simple */
+
+/*
+ * -writable
+ *
+ * File is writable
+ */
+int
+f_writable(PLAN *plan __unused, FTSENT *entry)
+{
+ return (access(entry->fts_path, W_OK) == 0);
+}
+
+/* c_writable == c_simple */
+
+/*
+ * -executable
+ *
+ * File is executable
+ */
+int
+f_executable(PLAN *plan __unused, FTSENT *entry)
+{
+ return (access(entry->fts_path, X_OK) == 0);
+}
+
+/* c_executable == c_simple */
diff --git a/usr.bin/find/getdate.y b/usr.bin/find/getdate.y
new file mode 100644
index 000000000000..a1aeaf0cacd6
--- /dev/null
+++ b/usr.bin/find/getdate.y
@@ -0,0 +1,946 @@
+%{
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/* The code at the top of get_date which figures out the offset of the
+ current time zone checks various CPP symbols to see if special
+ tricks are need, but defaults to using the gettimeofday system call.
+ Include <sys/time.h> if that will be used. */
+
+# include <sys/types.h>
+# include <sys/time.h>
+
+#if defined (__STDC__) || defined (USG)
+#include <string.h>
+#endif
+
+#if defined (__STDC__)
+#include <stdlib.h>
+#endif
+
+/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
+ releases):
+
+ We don't want to mess with all the portability hassles of alloca.
+ In particular, most (all?) versions of bison will use alloca in
+ their parser. If bison works on your system (e.g. it should work
+ with gcc), then go ahead and use it, but the more general solution
+ is to use byacc instead of bison, which should generate a portable
+ parser. I played with adding "#define alloca dont_use_alloca", to
+ give an error if the parser generator uses alloca (and thus detect
+ unportable getdate.c's), but that seems to cause as many problems
+ as it solves. */
+
+#include <time.h>
+
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yylex(void);
+static int yyerror(const char *);
+
+time_t get_date(char *);
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ const char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+%}
+
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type <Meridian> tMERIDIAN o_merid
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | rel {
+ yyHaveRel++;
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ |
+ tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ if ($1 >= 100) {
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ }
+ | tUNUMBER tSNUMBER tSNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = $1;
+ yyMonth = -$2;
+ yyDay = -$3;
+ }
+ | tUNUMBER tMONTH tSNUMBER {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = -$3;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : tUNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tSNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tMINUTE_UNIT {
+ yyRelSeconds += $1 * 60L;
+ }
+ | tSNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tUNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tSEC_UNIT {
+ yyRelSeconds++;
+ }
+ | tSNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ }
+ ;
+
+o_merid : /* NULL */ {
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL, 0, 0 }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
+ { "week", tMINUTE_UNIT, 7 * 24 * 60 },
+ { "day", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "hour", tMINUTE_UNIT, 60 },
+ { "minute", tMINUTE_UNIT, 1 },
+ { "min", tMINUTE_UNIT, 1 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL, 0, 0 }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
+ { "today", tMINUTE_UNIT, 0 },
+ { "now", tMINUTE_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tMINUTE_UNIT, 0 },
+ { "next", tUNUMBER, 2 },
+ { "first", tUNUMBER, 1 },
+/* { "second", tUNUMBER, 2 }, */
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+ { "ago", tAGO, 1 },
+ { NULL, 0, 0 }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL, 0, 0 }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL, 0, 0 }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(const char *s __unused)
+{
+ return 0;
+}
+
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+/* Year is either
+ * A negative number, which means to use its absolute value (why?)
+ * A number from 0 to 99, which means a year from 1900 to 1999, or
+ * The actual year (>=100). */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ MERIDIAN Meridian, DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
+ I'm too lazy to try to check for time_t overflow in another way. */
+ if (Year < EPOCH || Year > 2038
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(char *buff)
+{
+ char *p;
+ char *q;
+ const TABLE *tp;
+ int i;
+ int abbrev;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (strlen(buff) == 3)
+ abbrev = 1;
+ else if (strlen(buff) == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = strlen(buff) - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha(*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex(void)
+{
+ char c;
+ char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit(*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha(c)) {
+ for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(char *p)
+{
+ struct tm *tm, *gmt_ptr, gmt;
+ int tzoff;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+
+ bzero (&gmt, sizeof(struct tm));
+ yyInput = p;
+
+ (void)time (&nowtime);
+
+ gmt_ptr = gmtime (&nowtime);
+ if (gmt_ptr != NULL)
+ {
+ /* Make a copy, in case localtime modifies *tm (I think
+ that comment now applies to *gmt_ptr, but I am too
+ lazy to dig into how gmtime and locatime allocate the
+ structures they return pointers to). */
+ gmt = *gmt_ptr;
+ }
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
+
+ if (gmt_ptr != NULL)
+ tzoff = difftm (&gmt, tm) / 60;
+ else
+ /* We are on a system like VMS, where the system clock is
+ in local time and the system has no concept of timezones.
+ Hopefully we can fake this out (for the case in which the
+ user specifies no timezone) by just saying the timezone
+ is zero. */
+ tzoff = 0;
+
+ if(tm->tm_isdst)
+ tzoff += 60;
+
+ tm = localtime(&nowtime);
+ yyYear = tm->tm_year + 1900;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = tzoff;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(int ac, char *av[])
+{
+ char buff[128];
+ time_t d;
+
+ (void)printf("Enter date, or blank line to exit.\n\t> ");
+ (void)fflush(stdout);
+ while (gets(buff) && buff[0]) {
+ d = get_date(buff);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("%s", ctime(&d));
+ (void)printf("\t> ");
+ (void)fflush(stdout);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/usr.bin/find/ls.c b/usr.bin/find/ls.c
new file mode 100644
index 000000000000..86434f53e9fd
--- /dev/null
+++ b/usr.bin/find/ls.c
@@ -0,0 +1,119 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <langinfo.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "find.h"
+
+/* Derived from the print routines in the ls(1) source code. */
+
+static void printlink(char *);
+static void printtime(time_t);
+
+void
+printlong(char *name, char *accpath, struct stat *sb)
+{
+ char modep[15];
+
+ (void)printf("%6ju %8"PRId64" ", (uintmax_t)sb->st_ino, sb->st_blocks);
+ (void)strmode(sb->st_mode, modep);
+ (void)printf("%s %3ju %-*s %-*s ", modep, (uintmax_t)sb->st_nlink,
+ MAXLOGNAME - 1,
+ user_from_uid(sb->st_uid, 0), MAXLOGNAME - 1,
+ group_from_gid(sb->st_gid, 0));
+
+ if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
+ (void)printf("%#8jx ", (uintmax_t)sb->st_rdev);
+ else
+ (void)printf("%8"PRId64" ", sb->st_size);
+ printtime(sb->st_mtime);
+ (void)printf("%s", name);
+ if (S_ISLNK(sb->st_mode))
+ printlink(accpath);
+ (void)putchar('\n');
+}
+
+static void
+printtime(time_t ftime)
+{
+ char longstring[80];
+ static time_t lnow;
+ const char *format;
+ static int d_first = -1;
+ struct tm *tm;
+
+#ifdef D_MD_ORDER
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+#endif
+ if (lnow == 0)
+ lnow = time(NULL);
+
+#define SIXMONTHS ((365 / 2) * 86400)
+ if (ftime + SIXMONTHS > lnow && ftime < lnow + SIXMONTHS)
+ /* mmm dd hh:mm || dd mmm hh:mm */
+ format = d_first ? "%e %b %R " : "%b %e %R ";
+ else
+ /* mmm dd yyyy || dd mmm yyyy */
+ format = d_first ? "%e %b %Y " : "%b %e %Y ";
+ if ((tm = localtime(&ftime)) != NULL)
+ strftime(longstring, sizeof(longstring), format, tm);
+ else
+ strlcpy(longstring, "bad date val ", sizeof(longstring));
+ fputs(longstring, stdout);
+}
+
+static void
+printlink(char *name)
+{
+ ssize_t lnklen;
+ char path[MAXPATHLEN];
+
+ if ((lnklen = readlink(name, path, MAXPATHLEN - 1)) == -1) {
+ warn("%s", name);
+ return;
+ }
+ path[lnklen] = '\0';
+ (void)printf(" -> %s", path);
+}
diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c
new file mode 100644
index 000000000000..0738da4071c8
--- /dev/null
+++ b/usr.bin/find/main.c
@@ -0,0 +1,164 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "find.h"
+
+time_t now; /* time find was run */
+int dotfd; /* starting directory */
+int ftsoptions; /* options for the ftsopen(3) call */
+int ignore_readdir_race; /* ignore readdir race */
+int isdepth; /* do directories on post-order visit */
+int isoutput; /* user specified output operator */
+int issort; /* do hierarchies in lexicographical order */
+int isxargs; /* don't permit xargs delimiting chars */
+int mindepth = -1, maxdepth = -1; /* minimum and maximum depth */
+int regexp_flags = REG_BASIC; /* use the "basic" regexp by default*/
+int exitstatus;
+volatile sig_atomic_t showinfo = 0;
+
+static void usage(void) __dead2;
+static void siginfo_handler(int sig __unused);
+
+int
+main(int argc, char *argv[])
+{
+ char **p, **start;
+ int Hflag, Lflag, ch;
+
+ (void)setlocale(LC_ALL, "");
+
+ (void)time(&now); /* initialize the time-of-day */
+
+ (void)signal(SIGINFO, siginfo_handler);
+
+ p = start = argv;
+ Hflag = Lflag = 0;
+ ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
+ while ((ch = getopt(argc, argv, "EHLPXdf:sx")) != -1)
+ switch (ch) {
+ case 'E':
+ regexp_flags |= REG_EXTENDED;
+ break;
+ case 'H':
+ Hflag = 1;
+ Lflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ Hflag = 0;
+ break;
+ case 'P':
+ Hflag = Lflag = 0;
+ break;
+ case 'X':
+ isxargs = 1;
+ break;
+ case 'd':
+ isdepth = 1;
+ break;
+ case 'f':
+ *p++ = optarg;
+ break;
+ case 's':
+ issort = 1;
+ break;
+ case 'x':
+ ftsoptions |= FTS_XDEV;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (Hflag)
+ ftsoptions |= FTS_COMFOLLOW;
+ if (Lflag) {
+ ftsoptions &= ~FTS_PHYSICAL;
+ ftsoptions |= FTS_LOGICAL;
+ }
+
+ /*
+ * Find first option to delimit the file list. The first argument
+ * that starts with a -, or is a ! or a ( must be interpreted as a
+ * part of the find expression, according to POSIX .2.
+ */
+ for (; *argv != NULL; *p++ = *argv++) {
+ if (argv[0][0] == '-')
+ break;
+ if ((argv[0][0] == '!' || argv[0][0] == '(') &&
+ argv[0][1] == '\0')
+ break;
+ }
+
+ if (p == start)
+ usage();
+ *p = NULL;
+
+ if ((dotfd = open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
+ ftsoptions |= FTS_NOCHDIR;
+
+ exit(find_execute(find_formplan(argv), start));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n",
+"usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]",
+" find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]");
+ exit(1);
+}
+
+static void
+siginfo_handler(int sig __unused)
+{
+ showinfo = 1;
+}
diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c
new file mode 100644
index 000000000000..7963e3baa4d3
--- /dev/null
+++ b/usr.bin/find/misc.c
@@ -0,0 +1,107 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <fts.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "find.h"
+
+/*
+ * brace_subst --
+ * Replace occurrences of {} in s1 with s2 and return the result string.
+ */
+void
+brace_subst(char *orig, char **store, char *path, size_t len)
+{
+ const char *pastorigend, *p, *q;
+ char *dst;
+ size_t newlen, plen;
+
+ plen = strlen(path);
+ newlen = strlen(orig) + 1;
+ pastorigend = orig + newlen;
+ for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+ if (plen > 2 && newlen + plen - 2 < newlen)
+ errx(2, "brace_subst overflow");
+ newlen += plen - 2;
+ }
+ if (newlen > len) {
+ *store = reallocf(*store, newlen);
+ if (*store == NULL)
+ err(2, NULL);
+ }
+ dst = *store;
+ for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+ memcpy(dst, p, q - p);
+ dst += q - p;
+ memcpy(dst, path, plen);
+ dst += plen;
+ }
+ memcpy(dst, p, pastorigend - p);
+}
+
+/*
+ * queryuser --
+ * print a message to standard error and then read input from standard
+ * input. If the input is an affirmative response (according to the
+ * current locale) then 1 is returned.
+ */
+int
+queryuser(char *argv[])
+{
+ char *p, resp[256];
+
+ (void)fprintf(stderr, "\"%s", *argv);
+ while (*++argv)
+ (void)fprintf(stderr, " %s", *argv);
+ (void)fprintf(stderr, "\"? ");
+ (void)fflush(stderr);
+
+ if (fgets(resp, sizeof(resp), stdin) == NULL)
+ *resp = '\0';
+ if ((p = strchr(resp, '\n')) != NULL)
+ *p = '\0';
+ else {
+ (void)fprintf(stderr, "\n");
+ (void)fflush(stderr);
+ }
+ return (rpmatch(resp) == 1);
+}
diff --git a/usr.bin/find/operator.c b/usr.bin/find/operator.c
new file mode 100644
index 000000000000..3b4936fe055b
--- /dev/null
+++ b/usr.bin/find/operator.c
@@ -0,0 +1,267 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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 <err.h>
+#include <fts.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "find.h"
+
+static PLAN *yanknode(PLAN **);
+static PLAN *yankexpr(PLAN **);
+
+/*
+ * yanknode --
+ * destructively removes the top from the plan
+ */
+static PLAN *
+yanknode(PLAN **planp)
+{
+ PLAN *node; /* top node removed from the plan */
+
+ if ((node = (*planp)) == NULL)
+ return (NULL);
+ (*planp) = (*planp)->next;
+ node->next = NULL;
+ return (node);
+}
+
+/*
+ * yankexpr --
+ * Removes one expression from the plan. This is used mainly by
+ * paren_squish. In comments below, an expression is either a
+ * simple node or a f_expr node containing a list of simple nodes.
+ */
+static PLAN *
+yankexpr(PLAN **planp)
+{
+ PLAN *next; /* temp node holding subexpression results */
+ PLAN *node; /* pointer to returned node or expression */
+ PLAN *tail; /* pointer to tail of subplan */
+ PLAN *subplan; /* pointer to head of ( ) expression */
+
+ /* first pull the top node from the plan */
+ if ((node = yanknode(planp)) == NULL)
+ return (NULL);
+
+ /*
+ * If the node is an '(' then we recursively slurp up expressions
+ * until we find its associated ')'. If it's a closing paren we
+ * just return it and unwind our recursion; all other nodes are
+ * complete expressions, so just return them.
+ */
+ if (node->execute == f_openparen)
+ for (tail = subplan = NULL;;) {
+ if ((next = yankexpr(planp)) == NULL)
+ errx(1, "(: missing closing ')'");
+ /*
+ * If we find a closing ')' we store the collected
+ * subplan in our '(' node and convert the node to
+ * a f_expr. The ')' we found is ignored. Otherwise,
+ * we just continue to add whatever we get to our
+ * subplan.
+ */
+ if (next->execute == f_closeparen) {
+ if (subplan == NULL)
+ errx(1, "(): empty inner expression");
+ node->p_data[0] = subplan;
+ node->execute = f_expr;
+ break;
+ } else {
+ if (subplan == NULL)
+ tail = subplan = next;
+ else {
+ tail->next = next;
+ tail = next;
+ }
+ tail->next = NULL;
+ }
+ }
+ return (node);
+}
+
+/*
+ * paren_squish --
+ * replaces "parenthesized" plans in our search plan with "expr" nodes.
+ */
+PLAN *
+paren_squish(PLAN *plan)
+{
+ PLAN *expr; /* pointer to next expression */
+ PLAN *tail; /* pointer to tail of result plan */
+ PLAN *result; /* pointer to head of result plan */
+
+ result = tail = NULL;
+
+ /*
+ * the basic idea is to have yankexpr do all our work and just
+ * collect its results together.
+ */
+ while ((expr = yankexpr(&plan)) != NULL) {
+ /*
+ * if we find an unclaimed ')' it means there is a missing
+ * '(' someplace.
+ */
+ if (expr->execute == f_closeparen)
+ errx(1, "): no beginning '('");
+
+ /* add the expression to our result plan */
+ if (result == NULL)
+ tail = result = expr;
+ else {
+ tail->next = expr;
+ tail = expr;
+ }
+ tail->next = NULL;
+ }
+ return (result);
+}
+
+/*
+ * not_squish --
+ * compresses "!" expressions in our search plan.
+ */
+PLAN *
+not_squish(PLAN *plan)
+{
+ PLAN *next; /* next node being processed */
+ PLAN *node; /* temporary node used in f_not processing */
+ PLAN *tail; /* pointer to tail of result plan */
+ PLAN *result; /* pointer to head of result plan */
+
+ tail = result = NULL;
+
+ while ((next = yanknode(&plan))) {
+ /*
+ * if we encounter a ( expression ) then look for nots in
+ * the expr subplan.
+ */
+ if (next->execute == f_expr)
+ next->p_data[0] = not_squish(next->p_data[0]);
+
+ /*
+ * if we encounter a not, then snag the next node and place
+ * it in the not's subplan. As an optimization we compress
+ * several not's to zero or one not.
+ */
+ if (next->execute == f_not) {
+ int notlevel = 1;
+
+ node = yanknode(&plan);
+ while (node != NULL && node->execute == f_not) {
+ ++notlevel;
+ node = yanknode(&plan);
+ }
+ if (node == NULL)
+ errx(1, "!: no following expression");
+ if (node->execute == f_or)
+ errx(1, "!: nothing between ! and -o");
+ /*
+ * If we encounter ! ( expr ) then look for nots in
+ * the expr subplan.
+ */
+ if (node->execute == f_expr)
+ node->p_data[0] = not_squish(node->p_data[0]);
+ if (notlevel % 2 != 1)
+ next = node;
+ else
+ next->p_data[0] = node;
+ }
+
+ /* add the node to our result plan */
+ if (result == NULL)
+ tail = result = next;
+ else {
+ tail->next = next;
+ tail = next;
+ }
+ tail->next = NULL;
+ }
+ return (result);
+}
+
+/*
+ * or_squish --
+ * compresses -o expressions in our search plan.
+ */
+PLAN *
+or_squish(PLAN *plan)
+{
+ PLAN *next; /* next node being processed */
+ PLAN *tail; /* pointer to tail of result plan */
+ PLAN *result; /* pointer to head of result plan */
+
+ tail = result = next = NULL;
+
+ while ((next = yanknode(&plan)) != NULL) {
+ /*
+ * if we encounter a ( expression ) then look for or's in
+ * the expr subplan.
+ */
+ if (next->execute == f_expr)
+ next->p_data[0] = or_squish(next->p_data[0]);
+
+ /* if we encounter a not then look for or's in the subplan */
+ if (next->execute == f_not)
+ next->p_data[0] = or_squish(next->p_data[0]);
+
+ /*
+ * if we encounter an or, then place our collected plan in the
+ * or's first subplan and then recursively collect the
+ * remaining stuff into the second subplan and return the or.
+ */
+ if (next->execute == f_or) {
+ if (result == NULL)
+ errx(1, "-o: no expression before -o");
+ next->p_data[0] = result;
+ next->p_data[1] = or_squish(plan);
+ if (next->p_data[1] == NULL)
+ errx(1, "-o: no expression after -o");
+ return (next);
+ }
+
+ /* add the node to our result plan */
+ if (result == NULL)
+ tail = result = next;
+ else {
+ tail->next = next;
+ tail = next;
+ }
+ tail->next = NULL;
+ }
+ return (result);
+}
diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c
new file mode 100644
index 000000000000..268803343a8d
--- /dev/null
+++ b/usr.bin/find/option.c
@@ -0,0 +1,209 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Cimarron D. Taylor of the University of California, Berkeley.
+ *
+ * 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/acl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fts.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "find.h"
+
+static int typecompare(const void *, const void *);
+
+/* NB: the following table must be sorted lexically. */
+/* Options listed with C++ comments are in gnu find, but not our find */
+static OPTION const options[] = {
+ { "!", c_simple, f_not, 0 },
+ { "(", c_simple, f_openparen, 0 },
+ { ")", c_simple, f_closeparen, 0 },
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ { "-Bmin", c_Xmin, f_Xmin, F_TIME_B },
+ { "-Bnewer", c_newer, f_newer, F_TIME_B },
+ { "-Btime", c_Xtime, f_Xtime, F_TIME_B },
+#endif
+ { "-a", c_and, NULL, 0 },
+#ifdef ACL_TYPE_NFS4
+ { "-acl", c_acl, f_acl, 0 },
+#endif
+ { "-amin", c_Xmin, f_Xmin, F_TIME_A },
+ { "-and", c_and, NULL, 0 },
+ { "-anewer", c_newer, f_newer, F_TIME_A },
+ { "-atime", c_Xtime, f_Xtime, F_TIME_A },
+ { "-cmin", c_Xmin, f_Xmin, F_TIME_C },
+ { "-cnewer", c_newer, f_newer, F_TIME_C },
+ { "-ctime", c_Xtime, f_Xtime, F_TIME_C },
+ { "-d", c_depth, f_depth, 0 },
+// -daystart
+ { "-delete", c_delete, f_delete, 0 },
+ { "-depth", c_depth, f_depth, 0 },
+ { "-empty", c_empty, f_empty, 0 },
+ { "-exec", c_exec, f_exec, 0 },
+ { "-execdir", c_exec, f_exec, F_EXECDIR },
+ { "-executable", c_simple, f_executable, 0 },
+ { "-false", c_simple, f_false, 0 },
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ { "-flags", c_flags, f_flags, 0 },
+#endif
+// -fls
+ { "-follow", c_follow, f_always_true, 0 },
+// -fprint
+// -fprint0
+// -fprintf
+#if HAVE_STRUCT_STATFS_F_FSTYPENAME
+ { "-fstype", c_fstype, f_fstype, 0 },
+#endif
+ { "-gid", c_group, f_group, 0 },
+ { "-group", c_group, f_group, 0 },
+ { "-ignore_readdir_race",c_ignore_readdir_race, f_always_true,0 },
+ { "-ilname", c_name, f_name, F_LINK | F_IGNCASE },
+ { "-iname", c_name, f_name, F_IGNCASE },
+ { "-inum", c_inum, f_inum, 0 },
+ { "-ipath", c_name, f_path, F_IGNCASE },
+ { "-iregex", c_regex, f_regex, F_IGNCASE },
+ { "-iwholename",c_name, f_path, F_IGNCASE },
+ { "-links", c_links, f_links, 0 },
+ { "-lname", c_name, f_name, F_LINK },
+ { "-ls", c_ls, f_ls, 0 },
+ { "-maxdepth", c_mXXdepth, f_always_true, F_MAXDEPTH },
+ { "-mindepth", c_mXXdepth, f_always_true, 0 },
+ { "-mmin", c_Xmin, f_Xmin, 0 },
+ { "-mnewer", c_newer, f_newer, 0 },
+ { "-mount", c_xdev, f_always_true, 0 },
+ { "-mtime", c_Xtime, f_Xtime, 0 },
+ { "-name", c_name, f_name, 0 },
+ { "-newer", c_newer, f_newer, 0 },
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ { "-newerBB", c_newer, f_newer, F_TIME_B | F_TIME2_B },
+ { "-newerBa", c_newer, f_newer, F_TIME_B | F_TIME2_A },
+ { "-newerBc", c_newer, f_newer, F_TIME_B | F_TIME2_C },
+ { "-newerBm", c_newer, f_newer, F_TIME_B },
+ { "-newerBt", c_newer, f_newer, F_TIME_B | F_TIME2_T },
+ { "-neweraB", c_newer, f_newer, F_TIME_A | F_TIME2_B },
+#endif
+ { "-neweraa", c_newer, f_newer, F_TIME_A | F_TIME2_A },
+ { "-newerac", c_newer, f_newer, F_TIME_A | F_TIME2_C },
+ { "-neweram", c_newer, f_newer, F_TIME_A },
+ { "-newerat", c_newer, f_newer, F_TIME_A | F_TIME2_T },
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ { "-newercB", c_newer, f_newer, F_TIME_C | F_TIME2_B },
+#endif
+ { "-newerca", c_newer, f_newer, F_TIME_C | F_TIME2_A },
+ { "-newercc", c_newer, f_newer, F_TIME_C | F_TIME2_C },
+ { "-newercm", c_newer, f_newer, F_TIME_C },
+ { "-newerct", c_newer, f_newer, F_TIME_C | F_TIME2_T },
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ { "-newermB", c_newer, f_newer, F_TIME2_B },
+#endif
+ { "-newerma", c_newer, f_newer, F_TIME2_A },
+ { "-newermc", c_newer, f_newer, F_TIME2_C },
+ { "-newermm", c_newer, f_newer, 0 },
+ { "-newermt", c_newer, f_newer, F_TIME2_T },
+ { "-nogroup", c_nogroup, f_nogroup, 0 },
+ { "-noignore_readdir_race",c_ignore_readdir_race, f_always_true,0 },
+ { "-noleaf", c_simple, f_always_true, 0 },
+ { "-not", c_simple, f_not, 0 },
+ { "-nouser", c_nouser, f_nouser, 0 },
+ { "-o", c_simple, f_or, 0 },
+ { "-ok", c_exec, f_exec, F_NEEDOK },
+ { "-okdir", c_exec, f_exec, F_NEEDOK | F_EXECDIR },
+ { "-or", c_simple, f_or, 0 },
+ { "-path", c_name, f_path, 0 },
+ { "-perm", c_perm, f_perm, 0 },
+ { "-print", c_print, f_print, 0 },
+ { "-print0", c_print, f_print0, 0 },
+// -printf
+ { "-prune", c_simple, f_prune, 0 },
+ { "-quit", c_simple, f_quit, 0 },
+ { "-readable", c_simple, f_readable, 0 },
+ { "-regex", c_regex, f_regex, 0 },
+ { "-samefile", c_samefile, f_inum, 0 },
+ { "-size", c_size, f_size, 0 },
+ { "-sparse", c_sparse, f_sparse, 0 },
+ { "-true", c_simple, f_always_true, 0 },
+ { "-type", c_type, f_type, 0 },
+ { "-uid", c_user, f_user, 0 },
+ { "-user", c_user, f_user, 0 },
+ { "-wholename", c_name, f_path, 0 },
+ { "-writable", c_simple, f_writable, 0 },
+ { "-xdev", c_xdev, f_always_true, 0 },
+// -xtype
+};
+
+/*
+ * find_create --
+ * create a node corresponding to a command line argument.
+ *
+ * TODO:
+ * add create/process function pointers to node, so we can skip
+ * this switch stuff.
+ */
+PLAN *
+find_create(char ***argvp)
+{
+ OPTION *p;
+ PLAN *new;
+ char **argv;
+
+ argv = *argvp;
+
+ if ((p = lookup_option(*argv)) == NULL)
+ errx(1, "%s: unknown primary or operator", *argv);
+ ++argv;
+
+ new = (p->create)(p, &argv);
+ *argvp = argv;
+ return (new);
+}
+
+OPTION *
+lookup_option(const char *name)
+{
+ OPTION tmp;
+
+ tmp.name = name;
+ return ((OPTION *)bsearch(&tmp, options,
+ sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare));
+}
+
+static int
+typecompare(const void *a, const void *b)
+{
+ return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
+}
diff --git a/usr.bin/find/tests/Makefile b/usr.bin/find/tests/Makefile
new file mode 100644
index 000000000000..be688347c11b
--- /dev/null
+++ b/usr.bin/find/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH= find_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/find/tests/find_test.sh b/usr.bin/find/tests/find_test.sh
new file mode 100755
index 000000000000..8b8c23688018
--- /dev/null
+++ b/usr.bin/find/tests/find_test.sh
@@ -0,0 +1,71 @@
+#
+# Copyright 2017, Conrad Meyer <cem@FreeBSD.org>.
+#
+# 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.
+#
+# 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.
+#
+#
+
+atf_test_case find_newer_link
+find_newer_link_head()
+{
+ atf_set "descr" "Verifies that -newer correctly uses a symlink, " \
+ "rather than its target, for comparison"
+}
+find_newer_link_body()
+{
+ atf_check -s exit:0 mkdir test
+ atf_check -s exit:0 ln -s file1 test/link
+ atf_check -s exit:0 touch -d 2017-12-31T10:00:00Z -h test/link
+ atf_check -s exit:0 touch -d 2017-12-31T11:00:00Z test/file2
+ atf_check -s exit:0 touch -d 2017-12-31T12:00:00Z test/file1
+
+ # find(1) should evaluate 'link' as a symlink rather than its target
+ # (with -P / without -L flags). Since link was created first, the
+ # other two files should be newer.
+ echo -e "test\ntest/file1\ntest/file2" > expout
+ atf_check -s exit:0 -o save:output find test -newer test/link
+ atf_check -s exit:0 -o file:expout sort < output
+}
+
+atf_test_case find_samefile_link
+find_samefile_link_head()
+{
+ atf_set "descr" "Verifies that -samefile correctly uses a symlink, " \
+ "rather than its target, for comparison"
+}
+find_samefile_link_body()
+{
+ atf_check -s exit:0 mkdir test
+ atf_check -s exit:0 touch test/file3
+ atf_check -s exit:0 ln -s file3 test/link2
+
+ # find(1) should evaluate 'link' as a symlink rather than its target
+ # (with -P / without -L flags).
+ atf_check -s exit:0 -o "inline:test/link2\n" find test -samefile test/link2
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case find_newer_link
+ atf_add_test_case find_samefile_link
+}
diff --git a/usr.bin/finger/Makefile b/usr.bin/finger/Makefile
new file mode 100644
index 000000000000..638a603f9ed6
--- /dev/null
+++ b/usr.bin/finger/Makefile
@@ -0,0 +1,5 @@
+PROG= finger
+SRCS= finger.c lprint.c net.c sprint.c util.c
+MAN= finger.1 finger.conf.5
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/finger/Makefile.depend b/usr.bin/finger/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/finger/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/finger/extern.h b/usr.bin/finger/extern.h
new file mode 100644
index 000000000000..377f6f481f17
--- /dev/null
+++ b/usr.bin/finger/extern.h
@@ -0,0 +1,60 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#ifndef _EXTERN_H_
+#define _EXTERN_H_
+
+extern char tbuf[1024]; /* Temp buffer for anybody. */
+extern int entries; /* Number of people. */
+extern DB *db; /* Database. */
+extern int d_first;
+extern sa_family_t family;
+extern int gflag;
+extern int lflag;
+extern time_t now;
+extern int oflag;
+extern int pplan; /* don't show .plan/.project */
+extern int invoker_root; /* Invoked by root */
+
+void enter_lastlog(PERSON *);
+PERSON *enter_person(struct passwd *);
+void enter_where(struct utmpx *, PERSON *);
+PERSON *find_person(char *);
+int hide(struct passwd *);
+void lflag_print(void);
+int match(struct passwd *, const char *);
+void netfinger(char *);
+PERSON *palloc(void);
+char *prphone(char *);
+void sflag_print(void);
+int show_text(const char *, const char *, const char *);
+
+#endif /* !_EXTERN_H_ */
diff --git a/usr.bin/finger/finger.1 b/usr.bin/finger/finger.1
new file mode 100644
index 000000000000..b68846b4ea60
--- /dev/null
+++ b/usr.bin/finger/finger.1
@@ -0,0 +1,242 @@
+.\" Copyright (c) 1989, 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd January 21, 2010
+.Dt FINGER 1
+.Os
+.Sh NAME
+.Nm finger
+.Nd user information lookup program
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46gklmpsho
+.Op Ar user ...\&
+.Op Ar user@host ...\&
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about the system users.
+.Pp
+Options are:
+.Bl -tag -width indent
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl s
+Display the user's login name, real name, terminal name and write
+status (as a ``*'' before the terminal name if write permission is
+denied), idle time, login time, and either office location and office
+phone number, or the remote host.
+If
+.Fl o
+is given, the office location and office phone number is printed
+(the default).
+If
+.Fl h
+is given, the remote host is printed instead.
+.Pp
+Idle time is in minutes if it is a single integer, hours and minutes
+if a ``:'' is present, or days if a ``d'' is present.
+If it is an
+.Dq * ,
+the login time indicates the time of last login.
+Login time is displayed as the day name if less than 6 days, else month, day;
+hours and minutes, unless more than six months ago, in which case the year
+is displayed rather than the hours and minutes.
+.Pp
+Unknown devices as well as nonexistent idle and login times are
+displayed as single asterisks.
+.It Fl h
+When used in conjunction with the
+.Fl s
+option, the name of the remote host is displayed instead of the office
+location and office phone.
+.It Fl o
+When used in conjunction with the
+.Fl s
+option, the office location and office phone information is displayed
+instead of the name of the remote host.
+.It Fl g
+This option restricts the gecos output to only the users' real
+name.
+It also has the side-effect of restricting the output
+of the remote host when used in conjunction with the
+.Fl h
+option.
+.It Fl k
+Disable all use of the user accounting database.
+.It Fl l
+Produce a multi-line format displaying all of the information
+described for the
+.Fl s
+option as well as the user's home directory, home phone number, login
+shell, mail status, and the contents of the files
+.Pa .forward ,
+.Pa .plan ,
+.Pa .project
+and
+.Pa .pubkey
+from the user's home directory.
+.Pp
+If idle time is at least a minute and less than a day, it is
+presented in the form ``hh:mm''.
+Idle times greater than a day are presented as ``d day[s]hh:mm''.
+.Pp
+Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''.
+Numbers specified as ten or seven digits are printed as the appropriate
+subset of that string.
+Numbers specified as five digits are printed as ``xN-NNNN''.
+Numbers specified as four digits are printed as ``xNNNN''.
+.Pp
+If write permission is denied to the device, the phrase ``(messages off)''
+is appended to the line containing the device name.
+One entry per user is displayed with the
+.Fl l
+option; if a user is logged on multiple times, terminal information
+is repeated once per login.
+.Pp
+Mail status is shown as ``No Mail.'' if there is no mail at all, ``Mail
+last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked at their
+mailbox since new mail arriving, or ``New mail received ...'', ``Unread
+since ...'' if they have new mail.
+.It Fl p
+Prevent
+the
+.Fl l
+option of
+.Nm
+from displaying the contents of the
+.Pa .forward ,
+.Pa .plan ,
+.Pa .project
+and
+.Pa .pubkey
+files.
+.It Fl m
+Prevent matching of
+.Ar user
+names.
+.Ar User
+is usually a login name; however, matching will also be done on the
+users' real names, unless the
+.Fl m
+option is supplied.
+All name matching performed by
+.Nm
+is case insensitive.
+.El
+.Pp
+If no options are specified,
+.Nm
+defaults to the
+.Fl l
+style output if operands are provided, otherwise to the
+.Fl s
+style.
+Note that some fields may be missing, in either format, if information
+is not available for them.
+.Pp
+If no arguments are specified,
+.Nm
+will print an entry for each user currently logged into the system.
+.Pp
+The
+.Nm
+utility may be used to look up users on a remote machine.
+The format is to specify a
+.Ar user
+as
+.Dq Li user@host ,
+or
+.Dq Li @host ,
+where the default output
+format for the former is the
+.Fl l
+style, and the default output format for the latter is the
+.Fl s
+style.
+The
+.Fl l
+option is the only option that may be passed to a remote machine.
+.Pp
+If the file
+.Pa .nofinger
+exists in the user's home directory,
+and the program is not run with superuser privileges,
+.Nm
+behaves as if the user in question does not exist.
+.Pp
+The optional
+.Xr finger.conf 5
+configuration file can be used to specify aliases.
+Since
+.Nm
+is invoked by
+.Xr fingerd 8 ,
+aliases will work for both local and network queries.
+.Sh ENVIRONMENT
+The
+.Nm
+utility utilizes the following environment variable, if it exists:
+.Bl -tag -width Fl
+.It Ev FINGER
+This variable may be set with favored options to
+.Nm .
+.El
+.Sh FILES
+.Bl -tag -width /var/log/utx.lastlogin -compact
+.It Pa /etc/finger.conf
+alias definition data base
+.It Pa /var/log/utx.lastlogin
+last login data base
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr w 1 ,
+.Xr who 1 ,
+.Xr finger.conf 5 ,
+.Xr fingerd 8
+.Rs
+.%A D. Zimmerman
+.%T The Finger User Information Protocol
+.%R RFC 1288
+.%D December, 1991
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh BUGS
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/finger/finger.c b/usr.bin/finger/finger.c
new file mode 100644
index 000000000000..406d65541df4
--- /dev/null
+++ b/usr.bin/finger/finger.c
@@ -0,0 +1,394 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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.
+ */
+
+/*
+ * Luke Mewburn <lm@rmit.edu.au> added the following on 940622:
+ * - mail status ("No Mail", "Mail read:...", or "New Mail ...,
+ * Unread since ...".)
+ * - 4 digit phone extensions (3210 is printed as x3210.)
+ * - host/office toggling in short format with -h & -o.
+ * - short day names (`Tue' printed instead of `Jun 21' if the
+ * login time is < 6 days.
+ */
+
+/*
+ * Finger prints out information about users. It is not portable since
+ * certain fields (e.g. the full user name, office, and phone numbers) are
+ * extracted from the gecos field of the passwd file which other UNIXes
+ * may not have or may use for other things.
+ *
+ * There are currently two output formats; the short format is one line
+ * per user and displays login name, tty, login time, real name, idle time,
+ * and either remote host information (default) or office location/phone
+ * number, depending on if -h or -o is used respectively.
+ * The long format gives the same information (in a more legible format) as
+ * well as home directory, shell, mail info, and .plan/.project files.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <db.h>
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <locale.h>
+
+#include "finger.h"
+#include "pathnames.h"
+
+DB *db;
+time_t now;
+static int kflag, mflag, sflag;
+int entries, gflag, lflag, pplan, oflag;
+sa_family_t family = PF_UNSPEC;
+int d_first = -1;
+char tbuf[1024];
+int invoker_root = 0;
+
+static void loginlist(void);
+static int option(int, char **);
+static void usage(void) __dead2;
+static void userlist(int, char **);
+
+static int
+option(int argc, char **argv)
+{
+ int ch;
+
+ optind = 1; /* reset getopt */
+
+ while ((ch = getopt(argc, argv, "46gklmpsho")) != -1)
+ switch(ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'g':
+ gflag = 1;
+ break;
+ case 'k':
+ kflag = 1; /* keep going without utmp */
+ break;
+ case 'l':
+ lflag = 1; /* long format */
+ break;
+ case 'm':
+ mflag = 1; /* force exact match of names */
+ break;
+ case 'p':
+ pplan = 1; /* don't show .plan/.project */
+ break;
+ case 's':
+ sflag = 1; /* short format */
+ break;
+ case 'h':
+ oflag = 0; /* remote host info */
+ break;
+ case 'o':
+ oflag = 1; /* office info */
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ return optind;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: finger [-46gklmpsho] [user ...] [user@host ...]\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int envargc, argcnt;
+ char *envargv[3];
+ struct passwd *pw;
+ static char myname[] = "finger";
+
+ if (getuid() == 0 || geteuid() == 0) {
+ invoker_root = 1;
+ if ((pw = getpwnam(UNPRIV_NAME)) && pw->pw_uid > 0) {
+ if (setgid(pw->pw_gid) != 0)
+ err(1, "setgid()");
+ if (setuid(pw->pw_uid) != 0)
+ err(1, "setuid()");
+ } else {
+ if (setgid(UNPRIV_UGID) != 0)
+ err(1, "setgid()");
+ if (setuid(UNPRIV_UGID) != 0)
+ err(1, "setuid()");
+ }
+ }
+
+ (void) setlocale(LC_ALL, "");
+
+ /* remove this line to get remote host */
+ oflag = 1; /* default to old "office" behavior */
+
+ /*
+ * Process environment variables followed by command line arguments.
+ */
+ if ((envargv[1] = getenv("FINGER"))) {
+ envargc = 2;
+ envargv[0] = myname;
+ envargv[2] = NULL;
+ (void) option(envargc, envargv);
+ }
+
+ argcnt = option(argc, argv);
+ argc -= argcnt;
+ argv += argcnt;
+
+ (void)time(&now);
+ setpassent(1);
+ if (!*argv) {
+ /*
+ * Assign explicit "small" format if no names given and -l
+ * not selected. Force the -s BEFORE we get names so proper
+ * screening will be done.
+ */
+ if (!lflag)
+ sflag = 1; /* if -l not explicit, force -s */
+ loginlist();
+ if (entries == 0)
+ (void)printf("No one logged on.\n");
+ } else {
+ userlist(argc, argv);
+ /*
+ * Assign explicit "large" format if names given and -s not
+ * explicitly stated. Force the -l AFTER we get names so any
+ * remote finger attempts specified won't be mishandled.
+ */
+ if (!sflag)
+ lflag = 1; /* if -s not explicit, force -l */
+ }
+ if (entries) {
+ if (lflag)
+ lflag_print();
+ else
+ sflag_print();
+ }
+ return (0);
+}
+
+static void
+loginlist(void)
+{
+ PERSON *pn;
+ DBT data, key;
+ struct passwd *pw;
+ struct utmpx *user;
+ int r, sflag1;
+
+ if (kflag)
+ errx(1, "can't list logins without reading utmp");
+
+ setutxent();
+ while ((user = getutxent()) != NULL) {
+ if (user->ut_type != USER_PROCESS)
+ continue;
+ if ((pn = find_person(user->ut_user)) == NULL) {
+ if ((pw = getpwnam(user->ut_user)) == NULL)
+ continue;
+ if (hide(pw))
+ continue;
+ pn = enter_person(pw);
+ }
+ enter_where(user, pn);
+ }
+ endutxent();
+ if (db && lflag)
+ for (sflag1 = R_FIRST;; sflag1 = R_NEXT) {
+ PERSON *tmp;
+
+ r = (*db->seq)(db, &key, &data, sflag1);
+ if (r == -1)
+ err(1, "db seq");
+ if (r == 1)
+ break;
+ memmove(&tmp, data.data, sizeof tmp);
+ enter_lastlog(tmp);
+ }
+}
+
+static void
+userlist(int argc, char **argv)
+{
+ PERSON *pn;
+ DBT data, key;
+ struct utmpx *user;
+ struct passwd *pw;
+ int r, sflag1, *used, *ip;
+ char **ap, **nargv, **np, **p;
+ FILE *conf_fp;
+ char conf_alias[LINE_MAX];
+ char *conf_realname;
+ int conf_length;
+
+ if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL ||
+ (used = calloc(argc, sizeof(int))) == NULL)
+ err(1, NULL);
+
+ /* Pull out all network requests. */
+ for (ap = p = argv, np = nargv; *p; ++p)
+ if (strchr(*p, '@'))
+ *np++ = *p;
+ else
+ *ap++ = *p;
+
+ *np++ = NULL;
+ *ap++ = NULL;
+
+ if (!*argv)
+ goto net;
+
+ /*
+ * Mark any arguments beginning with '/' as invalid so that we
+ * don't accidentally confuse them with expansions from finger.conf
+ */
+ for (p = argv, ip = used; *p; ++p, ++ip)
+ if (**p == '/') {
+ *ip = 1;
+ warnx("%s: no such user", *p);
+ }
+
+ /*
+ * Traverse the finger alias configuration file of the form
+ * alias:(user|alias), ignoring comment lines beginning '#'.
+ */
+ if ((conf_fp = fopen(_PATH_FINGERCONF, "r")) != NULL) {
+ while(fgets(conf_alias, sizeof(conf_alias), conf_fp) != NULL) {
+ conf_length = strlen(conf_alias);
+ if (*conf_alias == '#' || conf_alias[--conf_length] != '\n')
+ continue;
+ conf_alias[conf_length] = '\0'; /* Remove trailing LF */
+ if ((conf_realname = strchr(conf_alias, ':')) == NULL)
+ continue;
+ *conf_realname = '\0'; /* Replace : with NUL */
+ for (p = argv; *p; ++p) {
+ if (strcmp(*p, conf_alias) == 0) {
+ if ((*p = strdup(conf_realname+1)) == NULL) {
+ err(1, NULL);
+ }
+ }
+ }
+ }
+ (void)fclose(conf_fp);
+ }
+
+ /*
+ * Traverse the list of possible login names and check the login name
+ * and real name against the name specified by the user. If the name
+ * begins with a '/', try to read the file of that name instead of
+ * gathering the traditional finger information.
+ */
+ if (mflag)
+ for (p = argv, ip = used; *p; ++p, ++ip) {
+ if (**p != '/' || *ip == 1 || !show_text("", *p, "")) {
+ if (((pw = getpwnam(*p)) != NULL) && !hide(pw))
+ enter_person(pw);
+ else if (!*ip)
+ warnx("%s: no such user", *p);
+ }
+ }
+ else {
+ while ((pw = getpwent()) != NULL) {
+ for (p = argv, ip = used; *p; ++p, ++ip)
+ if (**p == '/' && *ip != 1
+ && show_text("", *p, ""))
+ *ip = 1;
+ else if (match(pw, *p) && !hide(pw)) {
+ enter_person(pw);
+ *ip = 1;
+ }
+ }
+ for (p = argv, ip = used; *p; ++p, ++ip)
+ if (!*ip)
+ warnx("%s: no such user", *p);
+ }
+
+ /* Handle network requests. */
+net: for (p = nargv; *p;) {
+ netfinger(*p++);
+ if (*p || entries)
+ printf("\n");
+ }
+
+ free(nargv);
+ free(used);
+ if (entries == 0)
+ return;
+
+ if (kflag)
+ return;
+
+ /*
+ * Scan thru the list of users currently logged in, saving
+ * appropriate data whenever a match occurs.
+ */
+ setutxent();
+ while ((user = getutxent()) != NULL) {
+ if (user->ut_type != USER_PROCESS)
+ continue;
+ if ((pn = find_person(user->ut_user)) == NULL)
+ continue;
+ enter_where(user, pn);
+ }
+ endutxent();
+ if (db)
+ for (sflag1 = R_FIRST;; sflag1 = R_NEXT) {
+ PERSON *tmp;
+
+ r = (*db->seq)(db, &key, &data, sflag1);
+ if (r == -1)
+ err(1, "db seq");
+ if (r == 1)
+ break;
+ memmove(&tmp, data.data, sizeof tmp);
+ enter_lastlog(tmp);
+ }
+}
diff --git a/usr.bin/finger/finger.conf.5 b/usr.bin/finger/finger.conf.5
new file mode 100644
index 000000000000..d26dce7c0275
--- /dev/null
+++ b/usr.bin/finger/finger.conf.5
@@ -0,0 +1,89 @@
+.\" Copyright (c) 2000 Mark Knight <markk@knigma.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 16, 2000
+.Dt FINGER.CONF 5
+.Os
+.Sh NAME
+.Nm finger.conf
+.Nd
+.Xr finger 1
+alias configuration file
+.Sh DESCRIPTION
+The optional
+.Nm
+file is used to provide aliases that can be fingered by local
+and network users.
+This may be useful where a user's login name is not the same
+as their preferred mail address, or for providing virtual login names
+than can be fingered.
+.Pp
+Lines beginning with ``#'' are comments.
+Other lines must consist of an
+alias name and a target name separated by a colon.
+A target name should be either a user, a forward
+reference to another alias or the path of a world readable file.
+.Pp
+Where an alias points to a file, the contents of that file will be displayed
+when the alias is fingered.
+.Sh FILES
+.Bl -tag -width /etc/finger.conf -compact
+.It Pa /etc/finger.conf
+.Xr finger 1
+alias definition data base
+.El
+.Sh EXAMPLES
+.Bd -literal
+# /etc/finger.conf alias definition file
+#
+# Format alias:(user|alias)
+#
+# Individual aliases
+#
+markk:mkn
+john.smith:dev329
+john:dev329
+sue:/etc/finger/sue.txt
+#
+# Network status message
+#
+status:/usr/local/etc/status.txt
+#
+# Administrative redirects
+#
+root:admin
+postmaster:admin
+abuse:admin
+#
+# For the time being, 'sod' is sysadmin.
+#
+admin:sod
+.Ed
+.Sh SEE ALSO
+.Xr finger 1
+.Sh HISTORY
+Support for the
+.Nm
+file was submitted by Mark Knight <markk@knigma.org> and first appeared in
+.Fx 4.2 .
diff --git a/usr.bin/finger/finger.h b/usr.bin/finger/finger.h
new file mode 100644
index 000000000000..96e7987e7d27
--- /dev/null
+++ b/usr.bin/finger/finger.h
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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.
+ */
+
+#ifndef _FINGER_H_
+#define _FINGER_H_
+
+typedef struct person {
+ uid_t uid; /* user id */
+ char *dir; /* user's home directory */
+ char *homephone; /* pointer to home phone no. */
+ char *name; /* login name */
+ char *office; /* pointer to office name */
+ char *officephone; /* pointer to office phone no. */
+ char *realname; /* pointer to full name */
+ char *shell; /* user's shell */
+ time_t mailread; /* last time mail was read */
+ time_t mailrecv; /* last time mail was received */
+ struct where *whead, *wtail; /* list of where user is or has been */
+} PERSON;
+
+enum status { LASTLOG, LOGGEDIN };
+
+typedef struct where {
+ struct where *next; /* next place user is or has been */
+ enum status info; /* type/status of request */
+ short writable; /* tty is writable */
+ time_t loginat; /* time of (last) login */
+ time_t idletime; /* how long idle (if logged in) */
+ char tty[sizeof ((struct utmpx *)0)->ut_line]; /* tty line */
+ char host[sizeof ((struct utmpx *)0)->ut_host]; /* host name */
+} WHERE;
+
+#define UNPRIV_NAME "nobody" /* Preferred privilege level */
+#define UNPRIV_UGID 32767 /* Default uid and gid */
+#define OUTPUT_MAX 100000 /* Do not keep listinging forever */
+#define TIME_LIMIT 360 /* Do not keep listinging forever */
+
+#include "extern.h"
+
+#endif /* !_FINGER_H_ */
diff --git a/usr.bin/finger/lprint.c b/usr.bin/finger/lprint.c
new file mode 100644
index 000000000000..6d5e828eb274
--- /dev/null
+++ b/usr.bin/finger/lprint.c
@@ -0,0 +1,356 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <ctype.h>
+#include <db.h>
+#include <err.h>
+#include <fcntl.h>
+#include <langinfo.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include "finger.h"
+#include "pathnames.h"
+
+#define LINE_LEN 80
+#define TAB_LEN 8 /* 8 spaces between tabs */
+
+static int demi_print(char *, int);
+static void lprint(PERSON *);
+static void vputc(unsigned char);
+
+void
+lflag_print(void)
+{
+ PERSON *pn;
+ int sflag, r;
+ PERSON *tmp;
+ DBT data, key;
+
+ for (sflag = R_FIRST;; sflag = R_NEXT) {
+ r = (*db->seq)(db, &key, &data, sflag);
+ if (r == -1)
+ err(1, "db seq");
+ if (r == 1)
+ break;
+ memmove(&tmp, data.data, sizeof tmp);
+ pn = tmp;
+ if (sflag != R_FIRST)
+ putchar('\n');
+ lprint(pn);
+ if (!pplan) {
+ (void)show_text(pn->dir,
+ _PATH_FORWARD, "Mail forwarded to");
+ (void)show_text(pn->dir, _PATH_PROJECT, "Project");
+ if (!show_text(pn->dir, _PATH_PLAN, "Plan"))
+ (void)printf("No Plan.\n");
+ (void)show_text(pn->dir,
+ _PATH_PUBKEY, "Public key");
+ }
+ }
+}
+
+static void
+lprint(PERSON *pn)
+{
+ struct tm *delta;
+ WHERE *w;
+ int cpr, len, maxlen;
+ struct tm *tp;
+ int oddfield;
+ char t[80];
+
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+ /*
+ * long format --
+ * login name
+ * real name
+ * home directory
+ * shell
+ * office, office phone, home phone if available
+ * mail status
+ */
+ (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s",
+ pn->name, pn->realname, pn->dir);
+ (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL);
+
+ if (gflag)
+ goto no_gecos;
+ /*
+ * try and print office, office phone, and home phone on one line;
+ * if that fails, do line filling so it looks nice.
+ */
+#define OFFICE_TAG "Office"
+#define OFFICE_PHONE_TAG "Office Phone"
+ oddfield = 0;
+ if (pn->office && pn->officephone &&
+ strlen(pn->office) + strlen(pn->officephone) +
+ sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) {
+ (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s",
+ OFFICE_TAG, pn->office, prphone(pn->officephone));
+ oddfield = demi_print(tbuf, oddfield);
+ } else {
+ if (pn->office) {
+ (void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
+ OFFICE_TAG, pn->office);
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ if (pn->officephone) {
+ (void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
+ OFFICE_PHONE_TAG, prphone(pn->officephone));
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ }
+ if (pn->homephone) {
+ (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone",
+ prphone(pn->homephone));
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ if (oddfield)
+ putchar('\n');
+
+no_gecos:
+ /*
+ * long format con't:
+ * if logged in
+ * terminal
+ * idle time
+ * if messages allowed
+ * where logged in from
+ * if not logged in
+ * when last logged in
+ */
+ /* find out longest device name for this user for formatting */
+ for (w = pn->whead, maxlen = -1; w != NULL; w = w->next)
+ if ((len = strlen(w->tty)) > maxlen)
+ maxlen = len;
+ /* find rest of entries for user */
+ for (w = pn->whead; w != NULL; w = w->next) {
+ if (w->info == LOGGEDIN) {
+ tp = localtime(&w->loginat);
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R (%Z)" : "%a %b %e %R (%Z)",
+ tp);
+ cpr = printf("On since %s on %s", t, w->tty);
+ /*
+ * idle time is tough; if have one, print a comma,
+ * then spaces to pad out the device name, then the
+ * idle time. Follow with a comma if a remote login.
+ */
+ delta = gmtime(&w->idletime);
+ if (w->idletime != -1 && (delta->tm_yday ||
+ delta->tm_hour || delta->tm_min)) {
+ cpr += printf("%-*s idle ",
+ maxlen - (int)strlen(w->tty) + 1, ",");
+ if (delta->tm_yday > 0) {
+ cpr += printf("%d day%s ",
+ delta->tm_yday,
+ delta->tm_yday == 1 ? "" : "s");
+ }
+ cpr += printf("%d:%02d",
+ delta->tm_hour, delta->tm_min);
+ if (*w->host) {
+ putchar(',');
+ ++cpr;
+ }
+ }
+ if (!w->writable)
+ cpr += printf(" (messages off)");
+ } else if (w->loginat == 0) {
+ cpr = printf("Never logged in.");
+ } else {
+ tp = localtime(&w->loginat);
+ if (now - w->loginat > 86400 * 365 / 2) {
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R %Y (%Z)" :
+ "%a %b %e %R %Y (%Z)",
+ tp);
+ } else {
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R (%Z)" :
+ "%a %b %e %R (%Z)",
+ tp);
+ }
+ cpr = printf("Last login %s on %s", t, w->tty);
+ }
+ if (*w->host) {
+ if (LINE_LEN < (cpr + 6 + strlen(w->host)))
+ (void)printf("\n ");
+ (void)printf(" from %s", w->host);
+ }
+ putchar('\n');
+ }
+ if (pn->mailrecv == -1)
+ printf("No Mail.\n");
+ else if (pn->mailrecv > pn->mailread) {
+ tp = localtime(&pn->mailrecv);
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R %Y (%Z)" :
+ "%a %b %e %R %Y (%Z)",
+ tp);
+ printf("New mail received %s\n", t);
+ tp = localtime(&pn->mailread);
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R %Y (%Z)" :
+ "%a %b %e %R %Y (%Z)",
+ tp);
+ printf(" Unread since %s\n", t);
+ } else {
+ tp = localtime(&pn->mailread);
+ strftime(t, sizeof(t),
+ d_first ? "%a %e %b %R %Y (%Z)" :
+ "%a %b %e %R %Y (%Z)",
+ tp);
+ printf("Mail last read %s\n", t);
+ }
+}
+
+static int
+demi_print(char *str, int oddfield)
+{
+ static int lenlast;
+ int lenthis, maxlen;
+
+ lenthis = strlen(str);
+ if (oddfield) {
+ /*
+ * We left off on an odd number of fields. If we haven't
+ * crossed the midpoint of the screen, and we have room for
+ * the next field, print it on the same line; otherwise,
+ * print it on a new line.
+ *
+ * Note: we insist on having the right hand fields start
+ * no less than 5 tabs out.
+ */
+ maxlen = 5 * TAB_LEN;
+ if (maxlen < lenlast)
+ maxlen = lenlast;
+ if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) +
+ lenthis) <= LINE_LEN) {
+ while(lenlast < (4 * TAB_LEN)) {
+ putchar('\t');
+ lenlast += TAB_LEN;
+ }
+ (void)printf("\t%s\n", str); /* force one tab */
+ } else {
+ (void)printf("\n%s", str); /* go to next line */
+ oddfield = !oddfield; /* this'll be undone below */
+ }
+ } else
+ (void)printf("%s", str);
+ oddfield = !oddfield; /* toggle odd/even marker */
+ lenlast = lenthis;
+ return(oddfield);
+}
+
+int
+show_text(const char *directory, const char *file_name, const char *header)
+{
+ struct stat sb;
+ FILE *fp;
+ int ch, cnt;
+ char *p, lastc;
+ int fd, nr;
+
+ lastc = '\0';
+
+ (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name);
+ if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) ||
+ sb.st_size == 0)
+ return(0);
+
+ /* If short enough, and no newlines, show it on a single line.*/
+ if (sb.st_size <= (off_t)(LINE_LEN - strlen(header) - 5)) {
+ nr = read(fd, tbuf, sizeof(tbuf));
+ if (nr <= 0) {
+ (void)close(fd);
+ return(0);
+ }
+ for (p = tbuf, cnt = nr; cnt--; ++p)
+ if (*p == '\n')
+ break;
+ if (cnt <= 1) {
+ if (*header != '\0')
+ (void)printf("%s: ", header);
+ for (p = tbuf, cnt = nr; cnt--; ++p)
+ if (*p != '\r')
+ vputc(lastc = *p);
+ if (lastc != '\n')
+ (void)putchar('\n');
+ (void)close(fd);
+ return(1);
+ }
+ else
+ (void)lseek(fd, 0L, SEEK_SET);
+ }
+ if ((fp = fdopen(fd, "r")) == NULL)
+ return(0);
+ if (*header != '\0')
+ (void)printf("%s:\n", header);
+ while ((ch = getc(fp)) != EOF)
+ if (ch != '\r')
+ vputc(lastc = ch);
+ if (lastc != '\n')
+ (void)putchar('\n');
+ (void)fclose(fp);
+ return(1);
+}
+
+static void
+vputc(unsigned char ch)
+{
+ int meta;
+
+ if (!isprint(ch) && !isascii(ch)) {
+ (void)putchar('M');
+ (void)putchar('-');
+ ch = toascii(ch);
+ meta = 1;
+ } else
+ meta = 0;
+ if (isprint(ch) || (!meta && (ch == ' ' || ch == '\t' || ch == '\n')))
+ (void)putchar(ch);
+ else {
+ (void)putchar('^');
+ (void)putchar(ch == '\177' ? '?' : ch | 0100);
+ }
+}
diff --git a/usr.bin/finger/net.c b/usr.bin/finger/net.c
new file mode 100644
index 000000000000..e2f1eb99d623
--- /dev/null
+++ b/usr.bin/finger/net.c
@@ -0,0 +1,230 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <wctype.h>
+#include <db.h>
+#include <err.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <wchar.h>
+#include "finger.h"
+
+static void cleanup(int sig);
+static int do_protocol(const char *name, const struct addrinfo *ai);
+static void trying(const struct addrinfo *ai);
+
+void
+netfinger(char *name)
+{
+ int error, multi;
+ char *host;
+ struct addrinfo *ai, *ai0;
+ static struct addrinfo hint;
+
+ host = strrchr(name, '@');
+ if (host == NULL)
+ return;
+ *host++ = '\0';
+ signal(SIGALRM, cleanup);
+ alarm(TIME_LIMIT);
+
+ hint.ai_flags = AI_CANONNAME;
+ hint.ai_family = family;
+ hint.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(host, "finger", &hint, &ai0);
+ if (error) {
+ warnx("%s: %s", host, gai_strerror(error));
+ return;
+ }
+
+ multi = (ai0->ai_next) != 0;
+
+ /* ai_canonname may not be filled in if the user specified an IP. */
+ if (ai0->ai_canonname == 0)
+ printf("[%s]\n", host);
+ else
+ printf("[%s]\n", ai0->ai_canonname);
+
+ for (ai = ai0; ai != NULL; ai = ai->ai_next) {
+ if (multi)
+ trying(ai);
+
+ error = do_protocol(name, ai);
+ if (!error)
+ break;
+ }
+ alarm(0);
+ freeaddrinfo(ai0);
+}
+
+static int
+do_protocol(const char *name, const struct addrinfo *ai)
+{
+ int cnt, line_len, s;
+ FILE *fp;
+ wint_t c, lastc;
+ struct iovec iov[3];
+ struct msghdr msg;
+ static char slash_w[] = "/W ";
+ static char neteol[] = "\r\n";
+
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s < 0) {
+ warn("socket(%d, %d, %d)", ai->ai_family, ai->ai_socktype,
+ ai->ai_protocol);
+ return -1;
+ }
+
+ msg.msg_name = (void *)ai->ai_addr;
+ msg.msg_namelen = ai->ai_addrlen;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 0;
+ msg.msg_control = 0;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ /* -l flag for remote fingerd */
+ if (lflag) {
+ iov[msg.msg_iovlen].iov_base = slash_w;
+ iov[msg.msg_iovlen++].iov_len = 3;
+ }
+ /* send the name followed by <CR><LF> */
+ iov[msg.msg_iovlen].iov_base = strdup(name);
+ iov[msg.msg_iovlen++].iov_len = strlen(name);
+ iov[msg.msg_iovlen].iov_base = neteol;
+ iov[msg.msg_iovlen++].iov_len = 2;
+
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+ warn("connect");
+ close(s);
+ return -1;
+ }
+
+ if (sendmsg(s, &msg, 0) < 0) {
+ warn("sendmsg");
+ close(s);
+ return -1;
+ }
+
+ /*
+ * Read from the remote system; once we're connected, we assume some
+ * data. If none arrives, we hang until the user interrupts.
+ *
+ * If we see a <CR> or a <CR> with the high bit set, treat it as
+ * a newline; if followed by a newline character, only output one
+ * newline.
+ *
+ * Otherwise, all high bits are stripped; if it isn't printable and
+ * it isn't a space, we can simply set the 7th bit. Every ASCII
+ * character with bit 7 set is printable.
+ */
+ lastc = 0;
+ if ((fp = fdopen(s, "r")) != NULL) {
+ cnt = 0;
+ line_len = 0;
+ while ((c = getwc(fp)) != EOF) {
+ if (++cnt > OUTPUT_MAX) {
+ printf("\n\n Output truncated at %d bytes...\n",
+ cnt - 1);
+ break;
+ }
+ if (c == 0x0d) {
+ if (lastc == '\r') /* ^M^M - skip dupes */
+ continue;
+ c = '\n';
+ lastc = '\r';
+ } else {
+ if (!iswprint(c) && !iswspace(c)) {
+ c &= 0x7f;
+ c |= 0x40;
+ }
+ if (lastc != '\r' || c != '\n')
+ lastc = c;
+ else {
+ lastc = '\n';
+ continue;
+ }
+ }
+ putwchar(c);
+ if (c != '\n' && ++line_len > _POSIX2_LINE_MAX) {
+ putchar('\\');
+ putchar('\n');
+ lastc = '\r';
+ }
+ if (lastc == '\n' || lastc == '\r')
+ line_len = 0;
+ }
+ if (ferror(fp)) {
+ /*
+ * Assume that whatever it was set errno...
+ */
+ warn("reading from network");
+ }
+ if (lastc != L'\n')
+ putchar('\n');
+
+ fclose(fp);
+ }
+ return 0;
+}
+
+static void
+trying(const struct addrinfo *ai)
+{
+ char buf[NI_MAXHOST];
+
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, buf, sizeof buf,
+ (char *)0, 0, NI_NUMERICHOST) != 0)
+ return; /* XXX can't happen */
+
+ printf("Trying %s...\n", buf);
+}
+
+static void
+cleanup(int sig __unused)
+{
+#define ERRSTR "Timed out.\n"
+ write(STDERR_FILENO, ERRSTR, sizeof ERRSTR);
+ exit(1);
+}
+
diff --git a/usr.bin/finger/pathnames.h b/usr.bin/finger/pathnames.h
new file mode 100644
index 000000000000..5f5c65243e10
--- /dev/null
+++ b/usr.bin/finger/pathnames.h
@@ -0,0 +1,41 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 Mark Knight <markk@knigma.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 PATHNAMES_H
+
+#define _PATH_FORWARD ".forward"
+#define _PATH_NOFINGER ".nofinger"
+#define _PATH_PLAN ".plan"
+#define _PATH_PROJECT ".project"
+#define _PATH_PUBKEY ".pubkey"
+
+#ifndef _PATH_FINGERCONF
+#define _PATH_FINGERCONF "/etc/finger.conf"
+#endif /* _PATH_FINGERCONF */
+
+#endif /* PATHNAMES_H */
diff --git a/usr.bin/finger/sprint.c b/usr.bin/finger/sprint.c
new file mode 100644
index 000000000000..d8649a1f57f6
--- /dev/null
+++ b/usr.bin/finger/sprint.c
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <db.h>
+#include <err.h>
+#include <langinfo.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <utmpx.h>
+#include "finger.h"
+
+static void stimeprint(WHERE *);
+
+void
+sflag_print(void)
+{
+ PERSON *pn;
+ WHERE *w;
+ int sflag, r, namelen;
+ char p[80];
+ PERSON *tmp;
+ DBT data, key;
+ struct tm *lc;
+
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+ /*
+ * short format --
+ * login name
+ * real name
+ * terminal name (the XX of ttyXX)
+ * if terminal writeable (add an '*' to the terminal name
+ * if not)
+ * if logged in show idle time and day logged in, else
+ * show last login date and time.
+ * If > 6 months, show year instead of time.
+ * if (-o)
+ * office location
+ * office phone
+ * else
+ * remote host
+ */
+#define MAXREALNAME 16
+#define MAXHOSTNAME 17 /* in reality, hosts are never longer than 16 */
+ (void)printf("%-*s %-*s%s %s\n", MAXLOGNAME, "Login", MAXREALNAME,
+ "Name", " TTY Idle Login Time ", (gflag) ? "" :
+ oflag ? "Office Phone" : "Where");
+
+ for (sflag = R_FIRST;; sflag = R_NEXT) {
+ r = (*db->seq)(db, &key, &data, sflag);
+ if (r == -1)
+ err(1, "db seq");
+ if (r == 1)
+ break;
+ memmove(&tmp, data.data, sizeof tmp);
+ pn = tmp;
+
+ for (w = pn->whead; w != NULL; w = w->next) {
+ namelen = MAXREALNAME;
+ if (w->info == LOGGEDIN && !w->writable)
+ --namelen; /* leave space before `*' */
+ (void)printf("%-*.*s %-*.*s", MAXLOGNAME, MAXLOGNAME,
+ pn->name, MAXREALNAME, namelen,
+ pn->realname ? pn->realname : "");
+ if (!w->loginat) {
+ (void)printf(" * * No logins ");
+ goto office;
+ }
+ (void)putchar(w->info == LOGGEDIN && !w->writable ?
+ '*' : ' ');
+ if (*w->tty)
+ (void)printf("%-7.7s ",
+ (strncmp(w->tty, "tty", 3)
+ && strncmp(w->tty, "cua", 3))
+ ? w->tty : w->tty + 3);
+ else
+ (void)printf(" ");
+ if (w->info == LOGGEDIN) {
+ stimeprint(w);
+ (void)printf(" ");
+ } else
+ (void)printf(" * ");
+ lc = localtime(&w->loginat);
+#define SECSPERDAY 86400
+#define DAYSPERWEEK 7
+#define DAYSPERNYEAR 365
+ if (now - w->loginat < SECSPERDAY * (DAYSPERWEEK - 1)) {
+ (void)strftime(p, sizeof(p), "%a", lc);
+ } else {
+ (void)strftime(p, sizeof(p),
+ d_first ? "%e %b" : "%b %e", lc);
+ }
+ (void)printf("%-6.6s", p);
+ if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) {
+ (void)strftime(p, sizeof(p), "%Y", lc);
+ } else {
+ (void)strftime(p, sizeof(p), "%R", lc);
+ }
+ (void)printf(" %-5.5s", p);
+office:
+ if (gflag)
+ goto no_gecos;
+ if (oflag) {
+ if (pn->office)
+ (void)printf(" %-7.7s", pn->office);
+ else if (pn->officephone)
+ (void)printf(" %-7.7s", " ");
+ if (pn->officephone)
+ (void)printf(" %-.15s",
+ prphone(pn->officephone));
+ } else
+ (void)printf(" %.*s", MAXHOSTNAME, w->host);
+no_gecos:
+ putchar('\n');
+ }
+ }
+}
+
+static void
+stimeprint(WHERE *w)
+{
+ struct tm *delta;
+
+ if (w->idletime == -1) {
+ (void)printf(" ");
+ return;
+ }
+
+ delta = gmtime(&w->idletime);
+ if (!delta->tm_yday)
+ if (!delta->tm_hour)
+ if (!delta->tm_min)
+ (void)printf(" ");
+ else
+ (void)printf("%5d", delta->tm_min);
+ else
+ (void)printf("%2d:%02d",
+ delta->tm_hour, delta->tm_min);
+ else
+ (void)printf("%4dd", delta->tm_yday);
+}
diff --git a/usr.bin/finger/util.c b/usr.bin/finger/util.c
new file mode 100644
index 000000000000..183e46290013
--- /dev/null
+++ b/usr.bin/finger/util.c
@@ -0,0 +1,398 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include "finger.h"
+#include "pathnames.h"
+
+static void find_idle_and_ttywrite(WHERE *);
+static void userinfo(PERSON *, struct passwd *);
+static WHERE *walloc(PERSON *);
+
+int
+match(struct passwd *pw, const char *user)
+{
+ char *p, *t;
+ char name[1024];
+
+ if (!strcasecmp(pw->pw_name, user))
+ return(1);
+
+ /*
+ * XXX
+ * Why do we skip asterisks!?!?
+ */
+ (void)strncpy(p = tbuf, pw->pw_gecos, sizeof(tbuf));
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ if (*p == '*')
+ ++p;
+
+ /* Ampersands get replaced by the login name. */
+ if ((p = strtok(p, ",")) == NULL)
+ return(0);
+
+ for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) {
+ if (*t == '&') {
+ (void)strncpy(t, pw->pw_name,
+ sizeof(name) - (t - name));
+ name[sizeof(name) - 1] = '\0';
+ while (t < &name[sizeof(name) - 1] && *++t)
+ continue;
+ } else {
+ ++t;
+ }
+ }
+ *t = '\0';
+ for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL)
+ if (!strcasecmp(p, user))
+ return(1);
+ return(0);
+}
+
+void
+enter_lastlog(PERSON *pn)
+{
+ WHERE *w;
+ struct utmpx *ut = NULL;
+ char doit = 0;
+
+ if (setutxdb(UTXDB_LASTLOGIN, NULL) == 0)
+ ut = getutxuser(pn->name);
+ if ((w = pn->whead) == NULL)
+ doit = 1;
+ else if (ut != NULL && ut->ut_type == USER_PROCESS) {
+ /* if last login is earlier than some current login */
+ for (; !doit && w != NULL; w = w->next)
+ if (w->info == LOGGEDIN &&
+ w->loginat < ut->ut_tv.tv_sec)
+ doit = 1;
+ /*
+ * and if it's not any of the current logins
+ * can't use time comparison because there may be a small
+ * discrepancy since login calls time() twice
+ */
+ for (w = pn->whead; doit && w != NULL; w = w->next)
+ if (w->info == LOGGEDIN &&
+ strcmp(w->tty, ut->ut_line) == 0)
+ doit = 0;
+ }
+ if (ut != NULL && doit) {
+ w = walloc(pn);
+ w->info = LASTLOG;
+ strcpy(w->tty, ut->ut_line);
+ strcpy(w->host, ut->ut_host);
+ w->loginat = ut->ut_tv.tv_sec;
+ }
+ endutxent();
+}
+
+void
+enter_where(struct utmpx *ut, PERSON *pn)
+{
+ WHERE *w;
+
+ w = walloc(pn);
+ w->info = LOGGEDIN;
+ strcpy(w->tty, ut->ut_line);
+ strcpy(w->host, ut->ut_host);
+ w->loginat = ut->ut_tv.tv_sec;
+ find_idle_and_ttywrite(w);
+}
+
+PERSON *
+enter_person(struct passwd *pw)
+{
+ DBT data, key;
+ PERSON *pn;
+
+ if (db == NULL &&
+ (db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL)
+ err(1, NULL);
+
+ key.data = pw->pw_name;
+ key.size = strlen(pw->pw_name);
+
+ switch ((*db->get)(db, &key, &data, 0)) {
+ case 0:
+ memmove(&pn, data.data, sizeof pn);
+ return (pn);
+ default:
+ case -1:
+ err(1, "db get");
+ /* NOTREACHED */
+ case 1:
+ ++entries;
+ pn = palloc();
+ userinfo(pn, pw);
+ pn->whead = NULL;
+
+ data.size = sizeof(PERSON *);
+ data.data = &pn;
+ if ((*db->put)(db, &key, &data, 0))
+ err(1, "db put");
+ return (pn);
+ }
+}
+
+PERSON *
+find_person(char *name)
+{
+ struct passwd *pw;
+
+ DBT data, key;
+ PERSON *p;
+
+ if (!db)
+ return(NULL);
+
+ if ((pw = getpwnam(name)) && hide(pw))
+ return(NULL);
+
+ key.data = name;
+ key.size = strlen(name);
+
+ if ((*db->get)(db, &key, &data, 0))
+ return (NULL);
+ memmove(&p, data.data, sizeof p);
+ return (p);
+}
+
+PERSON *
+palloc(void)
+{
+ PERSON *p;
+
+ if ((p = malloc(sizeof(PERSON))) == NULL)
+ err(1, NULL);
+ return(p);
+}
+
+static WHERE *
+walloc(PERSON *pn)
+{
+ WHERE *w;
+
+ if ((w = malloc(sizeof(WHERE))) == NULL)
+ err(1, NULL);
+ if (pn->whead == NULL)
+ pn->whead = pn->wtail = w;
+ else {
+ pn->wtail->next = w;
+ pn->wtail = w;
+ }
+ w->next = NULL;
+ return(w);
+}
+
+char *
+prphone(char *num)
+{
+ char *p;
+ int len;
+ static char pbuf[20];
+
+ /* don't touch anything if the user has their own formatting */
+ for (p = num; *p; ++p)
+ if (!isdigit(*p))
+ return(num);
+ len = p - num;
+ p = pbuf;
+ switch(len) {
+ case 11: /* +0-123-456-7890 */
+ *p++ = '+';
+ *p++ = *num++;
+ *p++ = '-';
+ /* FALLTHROUGH */
+ case 10: /* 012-345-6789 */
+ *p++ = *num++;
+ *p++ = *num++;
+ *p++ = *num++;
+ *p++ = '-';
+ /* FALLTHROUGH */
+ case 7: /* 012-3456 */
+ *p++ = *num++;
+ *p++ = *num++;
+ *p++ = *num++;
+ break;
+ case 5: /* x0-1234 */
+ case 4: /* x1234 */
+ *p++ = 'x';
+ *p++ = *num++;
+ break;
+ default:
+ return(num);
+ }
+ if (len != 4) {
+ *p++ = '-';
+ *p++ = *num++;
+ }
+ *p++ = *num++;
+ *p++ = *num++;
+ *p++ = *num++;
+ *p = '\0';
+ return(pbuf);
+}
+
+static void
+find_idle_and_ttywrite(WHERE *w)
+{
+ struct stat sb;
+ time_t touched;
+ int error;
+
+ (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty);
+
+ error = stat(tbuf, &sb);
+ if (error < 0 && errno == ENOENT) {
+ /*
+ * The terminal listed is not actually a terminal (i.e.,
+ * ":0"). This is a failure, so we'll skip printing
+ * out the idle time, which is non-ideal but better
+ * than a bogus warning and idle time.
+ */
+ w->idletime = -1;
+ return;
+ } else if (error < 0) {
+ warn("%s", tbuf);
+ w->idletime = -1;
+ return;
+ }
+ touched = sb.st_atime;
+ if (touched < w->loginat) {
+ /* tty untouched since before login */
+ touched = w->loginat;
+ }
+ w->idletime = now < touched ? 0 : now - touched;
+
+#define TALKABLE 0220 /* tty is writable if 220 mode */
+ w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
+}
+
+static void
+userinfo(PERSON *pn, struct passwd *pw)
+{
+ char *p, *t;
+ char *bp, name[1024];
+ struct stat sb;
+
+ pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
+
+ pn->uid = pw->pw_uid;
+ if ((pn->name = strdup(pw->pw_name)) == NULL)
+ err(1, "strdup failed");
+ if ((pn->dir = strdup(pw->pw_dir)) == NULL)
+ err(1, "strdup failed");
+ if ((pn->shell = strdup(pw->pw_shell)) == NULL)
+ err(1, "strdup failed");
+
+ /* why do we skip asterisks!?!? */
+ (void)strncpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf));
+ tbuf[sizeof(tbuf) - 1] = '\0';
+ if (*bp == '*')
+ ++bp;
+
+ /* ampersands get replaced by the login name */
+ if (!(p = strsep(&bp, ",")))
+ return;
+ for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) {
+ if (*t == '&') {
+ (void)strncpy(t, pw->pw_name,
+ sizeof(name) - (t - name));
+ name[sizeof(name) - 1] = '\0';
+ if (islower(*t))
+ *t = toupper(*t);
+ while (t < &name[sizeof(name) - 1] && *++t)
+ continue;
+ } else {
+ ++t;
+ }
+ }
+ *t = '\0';
+ if ((pn->realname = strdup(name)) == NULL)
+ err(1, "strdup failed");
+ pn->office = ((p = strsep(&bp, ",")) && *p) ?
+ strdup(p) : NULL;
+ pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
+ strdup(p) : NULL;
+ pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
+ strdup(p) : NULL;
+ (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pw->pw_name);
+ pn->mailrecv = -1; /* -1 == not_valid */
+ if (stat(tbuf, &sb) < 0) {
+ if (errno != ENOENT) {
+ warn("%s", tbuf);
+ return;
+ }
+ } else if (sb.st_size != 0) {
+ pn->mailrecv = sb.st_mtime;
+ pn->mailread = sb.st_atime;
+ }
+}
+
+/*
+ * Is this user hiding from finger?
+ * If ~<user>/.nofinger exists, return 1 (hide), else return 0 (nohide).
+ * Nobody can hide from root.
+ */
+
+int
+hide(struct passwd *pw)
+{
+ struct stat st;
+ char buf[MAXPATHLEN];
+
+ if (invoker_root || !pw->pw_dir)
+ return 0;
+
+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, _PATH_NOFINGER);
+
+ if (stat(buf, &st) == 0)
+ return 1;
+
+ return 0;
+}
diff --git a/usr.bin/fmt/Makefile b/usr.bin/fmt/Makefile
new file mode 100644
index 000000000000..48f96db9ad42
--- /dev/null
+++ b/usr.bin/fmt/Makefile
@@ -0,0 +1,3 @@
+PROG= fmt
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fmt/Makefile.depend b/usr.bin/fmt/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/fmt/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fmt/fmt.1 b/usr.bin/fmt/fmt.1
new file mode 100644
index 000000000000..82678226cd43
--- /dev/null
+++ b/usr.bin/fmt/fmt.1
@@ -0,0 +1,198 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.\" Modified by Gareth McCaughan to describe the new version of `fmt'
+.\" rather than the old one.
+.Dd October 29, 2020
+.Dt FMT 1
+.Os
+.Sh NAME
+.Nm fmt
+.Nd simple text formatter
+.Sh SYNOPSIS
+.Nm
+.Op Fl cmnps
+.Op Fl d Ar chars
+.Op Fl l Ar num
+.Op Fl t Ar num
+.Op Ar goal Oo Ar maximum Oc | Fl Ns Ar width | Fl w Ar width
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a simple text formatter which reads the concatenation of input
+files (or standard input if none are given) and produces on standard
+output a version of its input with lines as close to the
+.Ar goal
+length
+as possible without exceeding the
+.Ar maximum .
+The
+.Ar goal
+length defaults
+to 65 and the
+.Ar maximum
+to 10 more than the
+.Ar goal
+length.
+Alternatively, a single
+.Ar width
+parameter can be specified either by prepending a hyphen to it or by using
+.Fl w .
+For example,
+.Dq Li fmt -w 72 ,
+.Dq Li fmt -72 ,
+and
+.Dq Li fmt 72 72
+all produce identical output.
+The spacing at the beginning of the input lines is preserved in the output,
+as are blank lines and interword spacing.
+Lines are joined or split only at white space; that is, words are never
+joined or hyphenated.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl c
+Center the text, line by line.
+In this case, most of the other
+options are ignored; no splitting or joining of lines is done.
+.It Fl m
+Try to format mail header lines contained in the input sensibly.
+.It Fl n
+Format lines beginning with a
+.Ql \&.
+(dot) character.
+.It Fl p
+Allow indented paragraphs.
+Without the
+.Fl p
+flag, any change in the amount of whitespace at the start of a line
+results in a new paragraph being begun.
+.It Fl s
+Collapse whitespace inside lines, so that multiple whitespace
+characters are turned into a single space.
+(Or, at the end of a
+sentence, a double space.)
+.It Fl d Ar chars
+Treat the
+.Ar chars
+(and no others) as sentence-ending characters.
+By default the
+sentence-ending characters are full stop
+.Pq Ql \&. ,
+question mark
+.Pq Ql \&?
+and exclamation mark
+.Pq Ql \&! .
+Remember that some characters may need to be
+escaped to protect them from your shell.
+.It Fl l Ar number
+Replace multiple spaces with tabs at the start of each output
+line, if possible.
+Each
+.Ar number
+spaces will be replaced with one tab.
+The default is 8.
+If
+.Ar number
+is 0, spaces are preserved.
+.It Fl t Ar number
+Assume that the input files' tabs assume
+.Ar number
+spaces per tab stop.
+The default is 8.
+.El
+.Pp
+The
+.Nm
+utility
+is meant to format mail messages prior to sending, but may also be useful
+for other simple tasks.
+For instance,
+within visual mode of the
+.Xr ex 1
+editor (e.g.,
+.Xr vi 1 )
+the command
+.Pp
+.Dl \&!}fmt
+.Pp
+will reformat a paragraph,
+evening the lines.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXAMPLES
+Center the text in standard input:
+.Bd -literal -offset indent
+$ echo -e 'The merit of all things\enlies\enin their difficulty' | fmt -c
+ The merit of all things
+ lies
+ in their difficulty
+.Ed
+.Pp
+Format the text in standard input collapsing spaces:
+.Bd -literal -offset indent
+$ echo -e 'Multiple spaces will be collapsed' | fmt -s
+Multiple spaces will be collapsed
+.Ed
+.Sh SEE ALSO
+.Xr fold 1 ,
+.Xr mail 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3 .
+.Pp
+The version described herein is a complete rewrite and appeared in
+.Fx 4.4 .
+.Sh AUTHORS
+.An Kurt Shoens
+.An Liz Allen
+(added
+.Ar goal
+length concept)
+.An Gareth McCaughan
+.Sh BUGS
+The program was designed to be simple and fast \- for more complex
+operations, the standard text processors are likely to be more appropriate.
+.Pp
+When the first line of an indented paragraph is very long (more than
+about twice the goal length), the indentation in the output can be
+wrong.
+.Pp
+The
+.Nm
+utility is not infallible in guessing what lines are mail headers and what
+lines are not.
diff --git a/usr.bin/fmt/fmt.c b/usr.bin/fmt/fmt.c
new file mode 100644
index 000000000000..78646f4e37a2
--- /dev/null
+++ b/usr.bin/fmt/fmt.c
@@ -0,0 +1,784 @@
+/* $OpenBSD: fmt.c,v 1.21 2004/04/01 23:14:19 tedu Exp $ */
+
+/* Sensible version of fmt
+ *
+ * Syntax: fmt [ options ] [ goal [ max ] ] [ filename ... ]
+ *
+ * Since the documentation for the original fmt is so poor, here
+ * is an accurate description of what this one does. It's usually
+ * the same. The *mechanism* used may differ from that suggested
+ * here. Note that we are *not* entirely compatible with fmt,
+ * because fmt gets so many things wrong.
+ *
+ * 1. Tabs are expanded, assuming 8-space tab stops.
+ * If the `-t <n>' option is given, we assume <n>-space
+ * tab stops instead.
+ * Trailing blanks are removed from all lines.
+ * x\b == nothing, for any x other than \b.
+ * Other control characters are simply stripped. This
+ * includes \r.
+ * 2. Each line is split into leading whitespace and
+ * everything else. Maximal consecutive sequences of
+ * lines with the same leading whitespace are considered
+ * to form paragraphs, except that a blank line is always
+ * a paragraph to itself.
+ * If the `-p' option is given then the first line of a
+ * paragraph is permitted to have indentation different
+ * from that of the other lines.
+ * If the `-m' option is given then a line that looks
+ * like a mail message header, if it is not immediately
+ * preceded by a non-blank non-message-header line, is
+ * taken to start a new paragraph, which also contains
+ * any subsequent lines with non-empty leading whitespace.
+ * Unless the `-n' option is given, lines beginning with
+ * a . (dot) are not formatted.
+ * 3. The "everything else" is split into words; a word
+ * includes its trailing whitespace, and a word at the
+ * end of a line is deemed to be followed by a single
+ * space, or two spaces if it ends with a sentence-end
+ * character. (See the `-d' option for how to change that.)
+ * If the `-s' option has been given, then a word's trailing
+ * whitespace is replaced by what it would have had if it
+ * had occurred at end of line.
+ * 4. Each paragraph is sent to standard output as follows.
+ * We output the leading whitespace, and then enough words
+ * to make the line length as near as possible to the goal
+ * without exceeding the maximum. (If a single word would
+ * exceed the maximum, we output that anyway.) Of course
+ * the trailing whitespace of the last word is ignored.
+ * We then emit a newline and start again if there are any
+ * words left.
+ * Note that for a blank line this translates as "We emit
+ * a newline".
+ * If the `-l <n>' option is given, then leading whitespace
+ * is modified slightly: <n> spaces are replaced by a tab.
+ * Indented paragraphs (see above under `-p') make matters
+ * more complicated than this suggests. Actually every paragraph
+ * has two `leading whitespace' values; the value for the first
+ * line, and the value for the most recent line. (While processing
+ * the first line, the two are equal. When `-p' has not been
+ * given, they are always equal.) The leading whitespace
+ * actually output is that of the first line (for the first
+ * line of *output*) or that of the most recent line (for
+ * all other lines of output).
+ * When `-m' has been given, message header paragraphs are
+ * taken as having first-leading-whitespace empty and
+ * subsequent-leading-whitespace two spaces.
+ *
+ * Multiple input files are formatted one at a time, so that a file
+ * never ends in the middle of a line.
+ *
+ * There's an alternative mode of operation, invoked by giving
+ * the `-c' option. In that case we just center every line,
+ * and most of the other options are ignored. This should
+ * really be in a separate program, but we must stay compatible
+ * with old `fmt'.
+ *
+ * QUERY: Should `-m' also try to do the right thing with quoted text?
+ * QUERY: `-b' to treat backslashed whitespace as old `fmt' does?
+ * QUERY: Option meaning `never join lines'?
+ * QUERY: Option meaning `split in mid-word to avoid overlong lines'?
+ * (Those last two might not be useful, since we have `fold'.)
+ *
+ * Differences from old `fmt':
+ *
+ * - We have many more options. Options that aren't understood
+ * generate a lengthy usage message, rather than being
+ * treated as filenames.
+ * - Even with `-m', our handling of message headers is
+ * significantly different. (And much better.)
+ * - We don't treat `\ ' as non-word-breaking.
+ * - Downward changes of indentation start new paragraphs
+ * for us, as well as upward. (I think old `fmt' behaves
+ * in the way it does in order to allow indented paragraphs,
+ * but this is a broken way of making indented paragraphs
+ * behave right.)
+ * - Given the choice of going over or under |goal_length|
+ * by the same amount, we go over; old `fmt' goes under.
+ * - We treat `?' as ending a sentence, and not `:'. Old `fmt'
+ * does the reverse.
+ * - We return approved return codes. Old `fmt' returns
+ * 1 for some errors, and *the number of unopenable files*
+ * when that was all that went wrong.
+ * - We have fewer crashes and more helpful error messages.
+ * - We don't turn spaces into tabs at starts of lines unless
+ * specifically requested.
+ * - New `fmt' is somewhat smaller and slightly faster than
+ * old `fmt'.
+ *
+ * Bugs:
+ *
+ * None known. There probably are some, though.
+ *
+ * Portability:
+ *
+ * I believe this code to be pretty portable. It does require
+ * that you have `getopt'. If you need to include "getopt.h"
+ * for this (e.g., if your system didn't come with `getopt'
+ * and you installed it yourself) then you should arrange for
+ * NEED_getopt_h to be #defined.
+ *
+ * Everything here should work OK even on nasty 16-bit
+ * machines and nice 64-bit ones. However, it's only really
+ * been tested on my FreeBSD machine. Your mileage may vary.
+ */
+
+/* Copyright (c) 1997 Gareth McCaughan. All rights reserved.
+ *
+ * Redistribution and use of this code, in source or binary forms,
+ * with or without modification, are permitted subject to the following
+ * conditions:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - If you distribute modified source code it must also include
+ * a notice saying that it has been modified, and giving a brief
+ * description of what changes have been made.
+ *
+ * Disclaimer: I am not responsible for the results of using this code.
+ * If it formats your hard disc, sends obscene messages to
+ * your boss and kills your children then that's your problem
+ * not mine. I give absolutely no warranty of any sort as to
+ * what the program will do, and absolutely refuse to be held
+ * liable for any consequences of your using it.
+ * Thank you. Have a nice day.
+ */
+
+/* RCS change log:
+ * Revision 1.5 1998/03/02 18:02:21 gjm11
+ * Minor changes for portability.
+ *
+ * Revision 1.4 1997/10/01 11:51:28 gjm11
+ * Repair broken indented-paragraph handling.
+ * Add mail message header stuff.
+ * Improve comments and layout.
+ * Make usable with non-BSD systems.
+ * Add revision display to usage message.
+ *
+ * Revision 1.3 1997/09/30 16:24:47 gjm11
+ * Add copyright notice, rcsid string and log message.
+ *
+ * Revision 1.2 1997/09/30 16:13:39 gjm11
+ * Add options: -d <chars>, -l <width>, -p, -s, -t <width>, -h .
+ * Parse options with `getopt'. Clean up code generally.
+ * Make comments more accurate.
+ *
+ * Revision 1.1 1997/09/30 11:29:57 gjm11
+ * Initial revision
+ */
+
+#ifndef lint
+static const char copyright[] =
+"Copyright (c) 1997 Gareth McCaughan. All rights reserved.\n";
+#endif /* not lint */
+#include <sys/cdefs.h>
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/* Something that, we hope, will never be a genuine line length,
+ * indentation etc.
+ */
+#define SILLY ((size_t)-1)
+
+/* I used to use |strtoul| for this, but (1) not all systems have it
+ * and (2) it's probably better to use |strtol| to detect negative
+ * numbers better.
+ * If |fussyp==0| then we don't complain about non-numbers
+ * (returning 0 instead), but we do complain about bad numbers.
+ */
+static size_t
+get_positive(const char *s, const char *err_mess, int fussyP)
+{
+ char *t;
+ long result = strtol(s, &t, 0);
+
+ if (*t) {
+ if (fussyP)
+ goto Lose;
+ else
+ return 0;
+ }
+ if (result <= 0) {
+Lose: errx(EX_USAGE, "%s", err_mess);
+ }
+ return (size_t)result;
+}
+
+static size_t
+get_nonnegative(const char *s, const char *err_mess, int fussyP)
+{
+ char *t;
+ long result = strtol(s, &t, 0);
+
+ if (*t) {
+ if (fussyP)
+ goto Lose;
+ else
+ return 0;
+ }
+ if (result < 0) {
+Lose: errx(EX_USAGE, "%s", err_mess);
+ }
+ return (size_t)result;
+}
+
+/* Global variables */
+
+static int centerP = 0; /* Try to center lines? */
+static size_t goal_length = 0; /* Target length for output lines */
+static size_t max_length = 0; /* Maximum length for output lines */
+static int coalesce_spaces_P = 0; /* Coalesce multiple whitespace -> ' ' ? */
+static int allow_indented_paragraphs = 0; /* Can first line have diff. ind.? */
+static int tab_width = 8; /* Number of spaces per tab stop */
+static size_t output_tab_width = 8; /* Ditto, when squashing leading spaces */
+static const wchar_t *sentence_enders = L".?!"; /* Double-space after these */
+static int grok_mail_headers = 0; /* treat embedded mail headers magically? */
+static int format_troff = 0; /* Format troff? */
+
+static int n_errors = 0; /* Number of failed files. Return on exit. */
+static wchar_t *output_buffer = NULL; /* Output line will be built here */
+static size_t x; /* Horizontal position in output line */
+static size_t x0; /* Ditto, ignoring leading whitespace */
+static size_t output_buffer_length = 0;
+static size_t pending_spaces; /* Spaces to add before next word */
+static int output_in_paragraph = 0; /* Any of current para written out yet? */
+
+/* Prototypes */
+
+static void process_named_file(const char *);
+static void process_stream(FILE *, const char *);
+static size_t indent_length(const wchar_t *, size_t);
+static int might_be_header(const wchar_t *);
+static void new_paragraph(size_t, size_t);
+static void output_word(size_t, size_t, const wchar_t *, size_t, size_t);
+static void output_indent(size_t);
+static void center_stream(FILE *, const char *);
+static wchar_t *get_line(FILE *, size_t *);
+static void *xrealloc(void *, size_t);
+
+#define XMALLOC(x) xrealloc(0,x)
+
+/* Here is perhaps the right place to mention that this code is
+ * all in top-down order. Hence, |main| comes first.
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch; /* used for |getopt| processing */
+ wchar_t *tmp;
+ size_t len;
+ const char *src;
+
+ (void)setlocale(LC_CTYPE, "");
+
+ /* 1. Grok parameters. */
+
+ while ((ch = getopt(argc, argv, "0123456789cd:hl:mnpst:w:")) != -1)
+ switch (ch) {
+ case 'c':
+ centerP = 1;
+ format_troff = 1;
+ continue;
+ case 'd':
+ src = optarg;
+ len = mbsrtowcs(NULL, &src, 0, NULL);
+ if (len == (size_t)-1)
+ err(EX_USAGE, "bad sentence-ending character set");
+ tmp = XMALLOC((len + 1) * sizeof(wchar_t));
+ mbsrtowcs(tmp, &src, len + 1, NULL);
+ sentence_enders = tmp;
+ continue;
+ case 'l':
+ output_tab_width
+ = get_nonnegative(optarg, "output tab width must be non-negative", 1);
+ continue;
+ case 'm':
+ grok_mail_headers = 1;
+ continue;
+ case 'n':
+ format_troff = 1;
+ continue;
+ case 'p':
+ allow_indented_paragraphs = 1;
+ continue;
+ case 's':
+ coalesce_spaces_P = 1;
+ continue;
+ case 't':
+ tab_width = get_positive(optarg, "tab width must be positive", 1);
+ continue;
+ case 'w':
+ goal_length = get_positive(optarg, "width must be positive", 1);
+ max_length = goal_length;
+ continue;
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ /*
+ * XXX this is not a stylistically approved use of
+ * getopt()
+ */
+ if (goal_length == 0) {
+ char *p;
+
+ p = argv[optind - 1];
+ if (p[0] == '-' && p[1] == ch && !p[2])
+ goal_length = get_positive(++p, "width must be nonzero", 1);
+ else
+ goal_length = get_positive(argv[optind] + 1,
+ "width must be nonzero", 1);
+ max_length = goal_length;
+ }
+ continue;
+ case 'h':
+ default:
+ fprintf(stderr,
+ "usage: fmt [-cmps] [-d chars] [-l num] [-t num]\n"
+ " [-w width | -width | goal [maximum]] [file ...]\n"
+ "Options: -c center each line instead of formatting\n"
+ " -d <chars> double-space after <chars> at line end\n"
+ " -l <n> turn each <n> spaces at start of line into a tab\n"
+ " -m try to make sure mail header lines stay separate\n"
+ " -n format lines beginning with a dot\n"
+ " -p allow indented paragraphs\n"
+ " -s coalesce whitespace inside lines\n"
+ " -t <n> have tabs every <n> columns\n"
+ " -w <n> set maximum width to <n>\n"
+ " goal set target width to goal\n");
+ exit(ch == 'h' ? 0 : EX_USAGE);
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* [ goal [ maximum ] ] */
+
+ if (argc > 0 && goal_length == 0
+ && (goal_length = get_positive(*argv, "goal length must be positive", 0))
+ != 0) {
+ --argc;
+ ++argv;
+ if (argc > 0
+ && (max_length = get_positive(*argv, "max length must be positive", 0))
+ != 0) {
+ --argc;
+ ++argv;
+ if (max_length < goal_length)
+ errx(EX_USAGE, "max length must be >= goal length");
+ }
+ }
+ if (goal_length == 0)
+ goal_length = 65;
+ if (max_length == 0)
+ max_length = goal_length + 10;
+ if (max_length >= SIZE_T_MAX / sizeof(wchar_t))
+ errx(EX_USAGE, "max length too large");
+ /* really needn't be longer */
+ output_buffer = XMALLOC((max_length + 1) * sizeof(wchar_t));
+
+ /* 2. Process files. */
+
+ if (argc > 0) {
+ while (argc-- > 0)
+ process_named_file(*argv++);
+ } else {
+ process_stream(stdin, "standard input");
+ }
+
+ /* We're done. */
+
+ return n_errors ? EX_NOINPUT : 0;
+
+}
+
+/* Process a single file, given its name.
+ */
+static void
+process_named_file(const char *name)
+{
+ FILE *f = fopen(name, "r");
+
+ if (!f) {
+ warn("%s", name);
+ ++n_errors;
+ } else {
+ process_stream(f, name);
+ if (ferror(f)) {
+ warn("%s", name);
+ ++n_errors;
+ }
+ fclose(f);
+ }
+}
+
+/* Types of mail header continuation lines:
+ */
+typedef enum {
+ hdr_ParagraphStart = -1,
+ hdr_NonHeader = 0,
+ hdr_Header = 1,
+ hdr_Continuation = 2
+} HdrType;
+
+/* Process a stream. This is where the real work happens,
+ * except that centering is handled separately.
+ */
+static void
+process_stream(FILE *stream, const char *name)
+{
+ size_t last_indent = SILLY; /* how many spaces in last indent? */
+ size_t para_line_number = 0; /* how many lines already read in this para? */
+ size_t first_indent = SILLY; /* indentation of line 0 of paragraph */
+ HdrType prev_header_type = hdr_ParagraphStart;
+
+ /* ^-- header_type of previous line; -1 at para start */
+ wchar_t *line;
+ size_t length;
+
+ if (centerP) {
+ center_stream(stream, name);
+ return;
+ }
+ while ((line = get_line(stream, &length)) != NULL) {
+ size_t np = indent_length(line, length);
+
+ {
+ HdrType header_type = hdr_NonHeader;
+
+ if (grok_mail_headers && prev_header_type != hdr_NonHeader) {
+ if (np == 0 && might_be_header(line))
+ header_type = hdr_Header;
+ else if (np > 0 && prev_header_type > hdr_NonHeader)
+ header_type = hdr_Continuation;
+ }
+ /*
+ * We need a new paragraph if and only if: this line
+ * is blank, OR it's a troff request (and we don't
+ * format troff), OR it's a mail header, OR it's not
+ * a mail header AND the last line was one, OR the
+ * indentation has changed AND the line isn't a mail
+ * header continuation line AND this isn't the
+ * second line of an indented paragraph.
+ */
+ if (length == 0
+ || (line[0] == '.' && !format_troff)
+ || header_type == hdr_Header
+ || (header_type == hdr_NonHeader && prev_header_type > hdr_NonHeader)
+ || (np != last_indent
+ && header_type != hdr_Continuation
+ && (!allow_indented_paragraphs || para_line_number != 1))) {
+ new_paragraph(output_in_paragraph ? last_indent : first_indent, np);
+ para_line_number = 0;
+ first_indent = np;
+ last_indent = np;
+ if (header_type == hdr_Header)
+ last_indent = 2; /* for cont. lines */
+ if (length == 0 || (line[0] == '.' && !format_troff)) {
+ if (length == 0)
+ putwchar('\n');
+ else
+ wprintf(L"%.*ls\n", (int)length,
+ line);
+ prev_header_type = hdr_ParagraphStart;
+ continue;
+ }
+ } else {
+ /*
+ * If this is an indented paragraph other
+ * than a mail header continuation, set
+ * |last_indent|.
+ */
+ if (np != last_indent &&
+ header_type != hdr_Continuation)
+ last_indent = np;
+ }
+ prev_header_type = header_type;
+ }
+
+ {
+ size_t n = np;
+
+ while (n < length) {
+ /* Find word end and count spaces after it */
+ size_t word_length = 0, space_length = 0;
+
+ while (n + word_length < length &&
+ line[n + word_length] != ' ')
+ ++word_length;
+ space_length = word_length;
+ while (n + space_length < length &&
+ line[n + space_length] == ' ')
+ ++space_length;
+ /* Send the word to the output machinery. */
+ output_word(first_indent, last_indent,
+ line + n, word_length,
+ space_length - word_length);
+ n += space_length;
+ }
+ }
+ ++para_line_number;
+ }
+ new_paragraph(output_in_paragraph ? last_indent : first_indent, 0);
+ if (ferror(stream)) {
+ warn("%s", name);
+ ++n_errors;
+ }
+}
+
+/* How long is the indent on this line?
+ */
+static size_t
+indent_length(const wchar_t *line, size_t length)
+{
+ size_t n = 0;
+
+ while (n < length && *line++ == ' ')
+ ++n;
+ return n;
+}
+
+/* Might this line be a mail header?
+ * We deem a line to be a possible header if it matches the
+ * Perl regexp /^[A-Z][-A-Za-z0-9]*:\s/. This is *not* the same
+ * as in RFC whatever-number-it-is; we want to be gratuitously
+ * conservative to avoid mangling ordinary civilised text.
+ */
+static int
+might_be_header(const wchar_t *line)
+{
+ if (!iswupper(*line++))
+ return 0;
+ while (*line && (iswalnum(*line) || *line == '-'))
+ ++line;
+ return (*line == ':' && iswspace(line[1]));
+}
+
+/* Begin a new paragraph with an indent of |indent| spaces.
+ */
+static void
+new_paragraph(size_t old_indent, size_t indent)
+{
+ if (output_buffer_length) {
+ if (old_indent > 0)
+ output_indent(old_indent);
+ wprintf(L"%.*ls\n", (int)output_buffer_length, output_buffer);
+ }
+ x = indent;
+ x0 = 0;
+ output_buffer_length = 0;
+ pending_spaces = 0;
+ output_in_paragraph = 0;
+}
+
+/* Output spaces or tabs for leading indentation.
+ */
+static void
+output_indent(size_t n_spaces)
+{
+ if (output_tab_width) {
+ while (n_spaces >= output_tab_width) {
+ putwchar('\t');
+ n_spaces -= output_tab_width;
+ }
+ }
+ while (n_spaces-- > 0)
+ putwchar(' ');
+}
+
+/* Output a single word, or add it to the buffer.
+ * indent0 and indent1 are the indents to use on the first and subsequent
+ * lines of a paragraph. They'll often be the same, of course.
+ */
+static void
+output_word(size_t indent0, size_t indent1, const wchar_t *word, size_t length, size_t spaces)
+{
+ size_t new_x;
+ size_t indent = output_in_paragraph ? indent1 : indent0;
+ size_t width;
+ const wchar_t *p;
+ int cwidth;
+
+ for (p = word, width = 0; p < &word[length]; p++)
+ width += (cwidth = wcwidth(*p)) > 0 ? cwidth : 1;
+
+ new_x = x + pending_spaces + width;
+
+ /*
+ * If either |spaces==0| (at end of line) or |coalesce_spaces_P|
+ * (squashing internal whitespace), then add just one space; except
+ * that if the last character was a sentence-ender we actually add
+ * two spaces.
+ */
+ if (coalesce_spaces_P || spaces == 0)
+ spaces = wcschr(sentence_enders, word[length - 1]) ? 2 : 1;
+
+ if (new_x <= goal_length) {
+ /*
+ * After adding the word we still aren't at the goal length,
+ * so clearly we add it to the buffer rather than outputting
+ * it.
+ */
+ wmemset(output_buffer + output_buffer_length, L' ',
+ pending_spaces);
+ x0 += pending_spaces;
+ x += pending_spaces;
+ output_buffer_length += pending_spaces;
+ wmemcpy(output_buffer + output_buffer_length, word, length);
+ x0 += width;
+ x += width;
+ output_buffer_length += length;
+ pending_spaces = spaces;
+ } else {
+ /*
+ * Adding the word takes us past the goal. Print the
+ * line-so-far, and the word too iff either (1) the lsf is
+ * empty or (2) that makes us nearer the goal but doesn't
+ * take us over the limit, or (3) the word on its own takes
+ * us over the limit. In case (3) we put a newline in
+ * between.
+ */
+ if (indent > 0)
+ output_indent(indent);
+ wprintf(L"%.*ls", (int)output_buffer_length, output_buffer);
+ if (x0 == 0 || (new_x <= max_length &&
+ new_x - goal_length <= goal_length - x)) {
+ wprintf(L"%*ls", (int)pending_spaces, L"");
+ goto write_out_word;
+ } else {
+ /*
+ * If the word takes us over the limit on its own,
+ * just spit it out and don't bother buffering it.
+ */
+ if (indent + width > max_length) {
+ putwchar('\n');
+ if (indent > 0)
+ output_indent(indent);
+ write_out_word:
+ wprintf(L"%.*ls", (int)length, word);
+ x0 = 0;
+ x = indent1;
+ pending_spaces = 0;
+ output_buffer_length = 0;
+ } else {
+ wmemcpy(output_buffer, word, length);
+ x0 = width;
+ x = width + indent1;
+ pending_spaces = spaces;
+ output_buffer_length = length;
+ }
+ }
+ putwchar('\n');
+ output_in_paragraph = 1;
+ }
+}
+
+/* Process a stream, but just center its lines rather than trying to
+ * format them neatly.
+ */
+static void
+center_stream(FILE *stream, const char *name)
+{
+ wchar_t *line, *p;
+ size_t length;
+ size_t width;
+ int cwidth;
+
+ while ((line = get_line(stream, &length)) != NULL) {
+ size_t l = length;
+
+ while (l > 0 && iswspace(*line)) {
+ ++line;
+ --l;
+ }
+ length = l;
+ for (p = line, width = 0; p < &line[length]; p++)
+ width += (cwidth = wcwidth(*p)) > 0 ? cwidth : 1;
+ l = width;
+ while (l < goal_length) {
+ putwchar(' ');
+ l += 2;
+ }
+ wprintf(L"%.*ls\n", (int)length, line);
+ }
+ if (ferror(stream)) {
+ warn("%s", name);
+ ++n_errors;
+ }
+}
+
+/* Get a single line from a stream. Expand tabs, strip control
+ * characters and trailing whitespace, and handle backspaces.
+ * Return the address of the buffer containing the line, and
+ * put the length of the line in |lengthp|.
+ * This can cope with arbitrarily long lines, and with lines
+ * without terminating \n.
+ * If there are no characters left or an error happens, we
+ * return 0.
+ * Don't confuse |spaces_pending| here with the global
+ * |pending_spaces|.
+ */
+static wchar_t *
+get_line(FILE *stream, size_t *lengthp)
+{
+ static wchar_t *buf = NULL;
+ static size_t length = 0;
+ size_t len = 0;
+ wint_t ch;
+ size_t spaces_pending = 0;
+ int troff = 0;
+ size_t col = 0;
+ int cwidth;
+
+ if (buf == NULL) {
+ length = 100;
+ buf = XMALLOC(length * sizeof(wchar_t));
+ }
+ while ((ch = getwc(stream)) != '\n' && ch != WEOF) {
+ if (len + spaces_pending == 0 && ch == '.' && !format_troff)
+ troff = 1;
+ if (ch == ' ')
+ ++spaces_pending;
+ else if (troff || iswprint(ch)) {
+ while (len + spaces_pending >= length) {
+ length *= 2;
+ buf = xrealloc(buf, length * sizeof(wchar_t));
+ }
+ while (spaces_pending > 0) {
+ --spaces_pending;
+ buf[len++] = ' ';
+ col++;
+ }
+ buf[len++] = ch;
+ col += (cwidth = wcwidth(ch)) > 0 ? cwidth : 1;
+ } else if (ch == '\t')
+ spaces_pending += tab_width -
+ (col + spaces_pending) % tab_width;
+ else if (ch == '\b') {
+ if (len)
+ --len;
+ if (col)
+ --col;
+ }
+ }
+ *lengthp = len;
+ return (len > 0 || ch != WEOF) ? buf : 0;
+}
+
+/* (Re)allocate some memory, exiting with an error if we can't.
+ */
+static void *
+xrealloc(void *ptr, size_t nbytes)
+{
+ void *p = realloc(ptr, nbytes);
+
+ if (p == NULL)
+ errx(EX_OSERR, "out of memory");
+ return p;
+}
diff --git a/usr.bin/fold/Makefile b/usr.bin/fold/Makefile
new file mode 100644
index 000000000000..e7509f024c53
--- /dev/null
+++ b/usr.bin/fold/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= fold
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fold/Makefile.depend b/usr.bin/fold/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/fold/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fold/fold.1 b/usr.bin/fold/fold.1
new file mode 100644
index 000000000000..bffe9dae0fbc
--- /dev/null
+++ b/usr.bin/fold/fold.1
@@ -0,0 +1,130 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd October 29, 2020
+.Dt FOLD 1
+.Os
+.Sh NAME
+.Nm fold
+.Nd "fold long lines for finite width output device"
+.Sh SYNOPSIS
+.Nm
+.Op Fl bs
+.Op Fl w Ar width
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a filter which folds the contents of the specified files,
+or the standard input if no files are specified,
+breaking the lines to have a maximum of 80 columns.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b
+Count
+.Ar width
+in bytes rather than column positions.
+.It Fl s
+Fold line after the last blank character within the first
+.Ar width
+column positions (or bytes).
+.It Fl w Ar width
+Specify a line width to use instead of the default 80 columns.
+The
+.Ar width
+value
+should be a multiple of 8 if tabs are present, or the tabs should
+be expanded using
+.Xr expand 1
+before using
+.Nm .
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXAMPLES
+Fold text in standard input with a width of 20 columns:
+.Bd -literal -offset indent
+$ echo "I am smart enough to know that I am dumb" | fold -w 15
+I am smart enou
+gh to know that
+ I am dumb
+.Ed
+.Pp
+Same as above but breaking lines after the last blank character:
+.Bd -literal -offset indent
+$ echo "I am smart enough to know that I am dumb" | fold -s -w 15
+I am smart
+enough to know
+that I am dumb
+.Ed
+.Sh SEE ALSO
+.Xr expand 1 ,
+.Xr fmt 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 1 .
+It was rewritten for
+.Bx 4.3 Reno
+to improve speed and modernize style.
+The
+.Fl b
+and
+.Fl s
+options were added to
+.Nx 1.0
+for
+.St -p1003.2
+compliance.
+.Sh AUTHORS
+.An -nosplit
+.An Bill Joy
+wrote the original version of
+.Nm
+on June 28, 1977.
+.An Kevin Ruddy
+rewrote the command in 1990, and
+.An J. T. Conklin
+added the missing options in 1993.
+.Sh BUGS
+If underlining (see
+.Xr ul 1 )
+is present it may be messed up by folding.
diff --git a/usr.bin/fold/fold.c b/usr.bin/fold/fold.c
new file mode 100644
index 000000000000..4487a21485c3
--- /dev/null
+++ b/usr.bin/fold/fold.c
@@ -0,0 +1,222 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kevin Ruddy.
+ *
+ * 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 <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define DEFLINEWIDTH 80
+
+void fold(int);
+static int newpos(int, wint_t);
+static void usage(void) __dead2;
+
+static int bflag; /* Count bytes, not columns */
+static int sflag; /* Split on word boundaries */
+
+int
+main(int argc, char **argv)
+{
+ int ch, previous_ch;
+ int rval, width;
+
+ (void) setlocale(LC_CTYPE, "");
+
+ width = -1;
+ previous_ch = 0;
+ while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) {
+ switch (ch) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'w':
+ if ((width = atoi(optarg)) <= 0) {
+ errx(1, "illegal width value");
+ }
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* Accept a width as eg. -30. Note that a width
+ * specified using the -w option is always used prior
+ * to this undocumented option. */
+ switch (previous_ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* The width is a number with multiple digits:
+ * add the last one. */
+ width = width * 10 + (ch - '0');
+ break;
+ default:
+ /* Set the width, unless it was previously
+ * set. For instance, the following options
+ * would all give a width of 5 and not 10:
+ * -10 -w5
+ * -5b10
+ * -5 -10b */
+ if (width == -1)
+ width = ch - '0';
+ break;
+ }
+ break;
+ default:
+ usage();
+ }
+ previous_ch = ch;
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (width == -1)
+ width = DEFLINEWIDTH;
+ rval = 0;
+ if (!*argv)
+ fold(width);
+ else for (; *argv; ++argv)
+ if (!freopen(*argv, "r", stdin)) {
+ warn("%s", *argv);
+ rval = 1;
+ } else
+ fold(width);
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n");
+ exit(1);
+}
+
+/*
+ * Fold the contents of standard input to fit within WIDTH columns (or bytes)
+ * and write to standard output.
+ *
+ * If sflag is set, split the line at the last space character on the line.
+ * This flag necessitates storing the line in a buffer until the current
+ * column > width, or a newline or EOF is read.
+ *
+ * The buffer can grow larger than WIDTH due to backspaces and carriage
+ * returns embedded in the input stream.
+ */
+void
+fold(int width)
+{
+ static wchar_t *buf;
+ static int buf_max;
+ int col, i, indx, space;
+ wint_t ch;
+
+ col = indx = 0;
+ while ((ch = getwchar()) != WEOF) {
+ if (ch == '\n') {
+ wprintf(L"%.*ls\n", indx, buf);
+ col = indx = 0;
+ continue;
+ }
+ if ((col = newpos(col, ch)) > width) {
+ if (sflag) {
+ i = indx;
+ while (--i >= 0 && !iswblank(buf[i]))
+ ;
+ space = i;
+ }
+ if (sflag && space != -1) {
+ space++;
+ wprintf(L"%.*ls\n", space, buf);
+ wmemmove(buf, buf + space, indx - space);
+ indx -= space;
+ col = 0;
+ for (i = 0; i < indx; i++)
+ col = newpos(col, buf[i]);
+ } else {
+ wprintf(L"%.*ls\n", indx, buf);
+ col = indx = 0;
+ }
+ col = newpos(col, ch);
+ }
+ if (indx + 1 > buf_max) {
+ buf_max += LINE_MAX;
+ buf = realloc(buf, sizeof(*buf) * buf_max);
+ if (buf == NULL)
+ err(1, "realloc()");
+ }
+ buf[indx++] = ch;
+ }
+
+ if (indx != 0)
+ wprintf(L"%.*ls", indx, buf);
+}
+
+/*
+ * Update the current column position for a character.
+ */
+static int
+newpos(int col, wint_t ch)
+{
+ char buf[MB_LEN_MAX];
+ size_t len;
+ int w;
+
+ if (bflag) {
+ len = wcrtomb(buf, ch, NULL);
+ col += len;
+ } else
+ switch (ch) {
+ case '\b':
+ if (col > 0)
+ --col;
+ break;
+ case '\r':
+ col = 0;
+ break;
+ case '\t':
+ col = (col + 8) & ~7;
+ break;
+ default:
+ if ((w = wcwidth(ch)) > 0)
+ col += w;
+ break;
+ }
+
+ return (col);
+}
diff --git a/usr.bin/fold/tests/Makefile b/usr.bin/fold/tests/Makefile
new file mode 100644
index 000000000000..13965aabd0ba
--- /dev/null
+++ b/usr.bin/fold/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH+= fold_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/fold/tests/fold_test.sh b/usr.bin/fold/tests/fold_test.sh
new file mode 100644
index 000000000000..d2d6f37b4a94
--- /dev/null
+++ b/usr.bin/fold/tests/fold_test.sh
@@ -0,0 +1,80 @@
+#
+# Copyright 2017 Shivansh
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+
+atf_test_case b_flag
+b_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'b'"
+}
+
+b_flag_body()
+{
+ atf_check -s exit:0 -o empty fold -b < /dev/null
+}
+
+atf_test_case s_flag
+s_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 's'"
+}
+
+s_flag_body()
+{
+ atf_check -s exit:0 -o empty fold -s < /dev/null
+}
+
+atf_test_case invalid_usage
+invalid_usage_head()
+{
+ atf_set "descr" "Verify that an invalid usage with a supported option produces a valid error message"
+}
+
+invalid_usage_body()
+{
+ atf_check -s not-exit:0 -e inline:"fold: option requires an argument -- w
+usage: fold [-bs] [-w width] [file ...]
+" fold -w
+}
+
+atf_test_case no_arguments
+no_arguments_head()
+{
+ atf_set "descr" "Verify that fold(1) executes successfully and silently when invoked without any arguments"
+}
+
+no_arguments_body()
+{
+ atf_check -s exit:0 -o empty fold < /dev/null
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case b_flag
+ atf_add_test_case s_flag
+ atf_add_test_case invalid_usage
+ atf_add_test_case no_arguments
+}
diff --git a/usr.bin/fortune/Makefile b/usr.bin/fortune/Makefile
new file mode 100644
index 000000000000..0499a0fa1da3
--- /dev/null
+++ b/usr.bin/fortune/Makefile
@@ -0,0 +1,7 @@
+SUBDIR= fortune strfile datfiles unstr
+
+SUBDIR_DEPEND_datfiles= strfile
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/fortune/Makefile.inc b/usr.bin/fortune/Makefile.inc
new file mode 100644
index 000000000000..cc361d4cf070
--- /dev/null
+++ b/usr.bin/fortune/Makefile.inc
@@ -0,0 +1,4 @@
+FORTUNE_SRC= ${SRCTOP}/usr.bin/fortune
+FORTUNE_OBJ= ${OBJTOP}/usr.bin/fortune
+
+.include "${SRCTOP}/usr.bin/Makefile.inc"
diff --git a/usr.bin/fortune/Notes b/usr.bin/fortune/Notes
new file mode 100644
index 000000000000..6121e5073720
--- /dev/null
+++ b/usr.bin/fortune/Notes
@@ -0,0 +1,176 @@
+
+Warning:
+ The fortunes contained in the fortune database have been collected
+ haphazardly from a cacophony of sources, in number so huge it
+ boggles the mind. It is impossible to do any meaningful quality
+ control on attributions, or lack thereof, or exactness of the quote.
+ Since this database is not used for profit, and since entire works
+ are not published, it falls under fair use, as we understand it.
+ However, if any half-assed idiot decides to make a profit off of
+ this, they will need to double check it all, and nobody not involved
+ of such an effort makes any warranty that anything in the database
+ bears any relation to the real world of literature, law, or other
+ bizzarrity.
+
+==> GENERAL INFORMATION
+ By default, fortune retrieves its fortune files from the directory
+/usr/share/games/fortune. A fortune file has two parts: the source file
+(which contains the fortunes themselves) and the data file which describes
+the fortunes. The data file always has the same name as the fortune file
+with the string ".dat" concatenated, i.e. "fortunes" is the standard fortune
+database, and "fortunes.dat" is the data file which describes it. See
+strfile(8) for more information on creating the data files.
+ Fortunes are split into potentially offensive and not potentially
+offensive parts. The offensive version of a file has the same name as the
+non-offensive version with "-o" concatenated, i.e. "fortunes" is the standard
+fortune database, and "fortunes-o" is the standard offensive database. The
+fortune program automatically assumes that any file with a name ending in
+"-o" is potentially offensive, and should therefore only be displayed if
+explicitly requested, either with the -o option or by specifying a file name
+on the command line.
+ Potentially offensive fortune files should NEVER be maintained in
+clear text on the system. They are rotated (see caesar(6)) 13 positions.
+To create a new, potentially offensive database, use caesar to rotate it,
+and then create its data file with the -x option to strfile(8). The fortune
+program automatically decrypts the text when it prints entries from such
+databases.
+ Anything which would not make it onto network prime time programming
+(or which would only be broadcast if some discredited kind of guy said it)
+MUST be in the potentially offensive database. Fortunes containing any
+explicit language (see George Carlin's recent updated list) MUST be in the
+potentially offensive database. Political and religious opinions are often
+sequestered in the potentially offensive section as well. Anything which
+assumes as a world view blatantly racist, misogynist (sexist), or homophobic
+ideas should not be in either, since they are not really funny unless *you*
+are racist, misogynist, or homophobic.
+ The point of this is that people should have a reasonable
+expectation that, should they just run "fortune", they will not be offended.
+We know that some people take offense at anything, but normal people do have
+opinions, too, and have a right not to have their sensibilities offended by
+a program which is supposed to be entertaining. People who run "fortune
+-o" or "fortune -a" are saying, in effect, that they are willing to have
+their sensibilities tweaked. However, they should not have their personal
+worth seriously (i.e., not in jest) assaulted. Jokes which depend for their
+humor on racist, misogynist, or homophobic stereotypes *do* seriously
+assault individual personal worth, and in a general entertainment medium
+we should be able to get by without it.
+
+==> FORMATTING
+ This file describes the format for fortunes in the database. This
+is done in detail to make it easier to keep track of things. Any rule given
+here may be broken to make a better joke.
+
+[All examples are indented by one tab stop -- KCRCA]
+
+Numbers should be given in parentheses, e.g.,
+
+ (1) Everything depends.
+ (2) Nothing is always.
+ (3) Everything is sometimes.
+
+Attributions are two tab stops, followed by two hyphens, followed by a
+space, followed by the attribution, and are *not* preceded by blank
+lines. Book, journal, movie, and all other titles are in quotes, e.g.,
+
+ $100 invested at 7% interest for 100 years will become $100,000, at
+ which time it will be worth absolutely nothing.
+ -- Lazarus Long, "Time Enough for Love"
+
+Attributions which do not fit on one (72 char) line should be continued
+on a line which lines up below the first text of the attribution, e.g.,
+
+ -- A very long attribution which might not fit on one
+ line, "Ken Arnold's Stupid Sayings"
+
+Single paragraph fortunes are in left justified (non-indented) paragraphs
+unless they fall into another category listed below (see example above).
+Longer fortunes should also be in left justified paragraphs, but if this
+makes it too long, try indented paragraphs, with indentations of either one
+tab stop or 5 chars. Indentations of less than 5 are too hard to read.
+
+Laws have the title left justified and capitalized, followed by a colon,
+with all the text of the law itself indented one tab stop, initially
+capitalized, e.g.,
+
+ A Law of Computer Programming:
+ Make it possible for programmers to write in English and
+ you will find the programmers cannot write in English.
+
+Limericks are indented as follows, all lines capitalized:
+
+ A computer, to print out a fact,
+ Will divide, multiply, and subtract.
+ But this output can be
+ No more than debris,
+ If the input was short of exact.
+
+Accents precede the letter they are over, e.g., "`^He" for e with a grave
+accent. Underlining is done on a word-by-word basis, with the underlines
+preceding the word, e.g., "__^H^Hhi ____^H^H^H^Hthere".
+
+No fortune should run beyond 72 characters on a single line without good
+justification (er, no pun intended). And no right margin justification,
+either. Sorry. For BSD people, there is a program called "fmt" which can
+make this kind of formatting easier.
+
+Definitions are given with the word or phrase left justified, followed by
+the part of speech (if appropriate) and a colon. The definition starts
+indented by one tab stop, with subsequent lines left justified, e.g.,
+
+ Afternoon, n.:
+ That part of the day we spend worrying about how we wasted
+ the morning.
+
+Quotes are sometimes put around statements which are funnier or make more
+sense if they are understood as being spoken, rather than written,
+communication, e.g.,
+
+ "All my friends and I are crazy. That's the only thing that
+ keeps us sane."
+
+Ellipses are always surrounded by spaces, except when next to punctuation,
+and are three dots long.
+
+ "... all the modern inconveniences ..."
+ -- Mark Twain
+
+Human initials always have spaces after the periods, e.g, "P. T. Barnum",
+not "P.T. Barnum". However, "P.T.A.", not "P. T. A.".
+
+All fortunes should be attributed, but if and only if they are original with
+somebody. Many people have said things that are folk sayings (i.e., are
+common among the folk (i.e., us common slobs)). There is nothing wrong with
+this, of course, but such statements should not be attributed to individuals
+who did not invent them.
+
+Horoscopes should have the sign indented by one tab stop, followed by the
+dates of the sign, with the text left justified below it, e.g.,
+
+ AQUARIUS (Jan 20 - Feb 18)
+ You have an inventive mind and are inclined to be progressive. You
+ lie a great deal. On the other hand, you are inclined to be
+ careless and impractical, causing you to make the same mistakes over
+ and over again. People think you are stupid.
+
+Single quotes should not be used except as quotes within quotes. Not even
+single quotes masquerading as double quotes are to be used, e.g., don't say
+``hi there'' or `hi there' or 'hi there', but "hi there". However, you
+*can* say "I said, `hi there'".
+
+A long poem or song can be ordered as follows in order to make it fit on a
+screen (fortunes should be 19 lines or less if at all possible) (numbers
+here are stanza numbers):
+
+ 11111111111111111111
+ 11111111111111111111
+ 11111111111111111111 22222222222222222222
+ 11111111111111111111 22222222222222222222
+ 22222222222222222222
+ 33333333333333333333 22222222222222222222
+ 33333333333333333333
+ 33333333333333333333 44444444444444444444
+ 33333333333333333333 44444444444444444444
+ 44444444444444444444
+ 44444444444444444444
+
+
diff --git a/usr.bin/fortune/README b/usr.bin/fortune/README
new file mode 100644
index 000000000000..4133a547fba3
--- /dev/null
+++ b/usr.bin/fortune/README
@@ -0,0 +1,33 @@
+
+ Some years ago, my neighbor Avery said to me: "There has not been an
+adequate jokebook published since "Joe_Miller", which came out in 1739 and
+which, incidentally, was the most miserable no-good ... jokebook in the
+history of the printed word."
+ In a subsequent conversation, Avery said: "A funny story is a funny
+story, no matter who is in it - whether it's about Catholics or Protestants,
+Jews or Gentiles, blacks or whites, browns or yellows. If a story is genuinely
+funny it makes no difference how dirty it is. Shout it from the rooftops.
+Let the chips fall all over the prairie and let the bonehead wowsers yelp.
+... on them."
+ It is a nice thing to have a neighbor of Avery's grain. He has
+believed in the aforestated principles all his life. A great many other
+people nowadays are casting aside the pietistic attitude that has led them
+to plug up their ears against the facts of life. We of The Brotherhood
+believe as Avery believes; we have never been intimidated by the pharisaical
+meddlers who have been smelling up the American landscape since the time of
+the bundling board. Neither has any one of our members ever been called a
+racist. Still, we have been in unremitting revolt against the ignorant
+propensity which ordains, in effect, that "The Green Pastures" should never
+have been written; the idiot attitude which compelled Arthur Kober to abandon
+his delightful Bella Gross, and Octavius Roy Cohen to quit writing about the
+splendiferous Florian Slappey; the moronic frame of mind which, if carried
+to its logical end, would have forbidden Ring Lardner from writing in the
+language of the masses.
+ -- H. Allen Smith, "Rude Jokes"
+
+ ... let us keep in mind the basic governing philosophy of The
+Brotherhood, as handsomely summarized in these words: we believe in
+healthy, hearty laughter -- at the expense of the whole human race, if
+needs be.
+ Needs be.
+ -- H. Allen Smith, "Rude Jokes"
diff --git a/usr.bin/fortune/datfiles/Makefile b/usr.bin/fortune/datfiles/Makefile
new file mode 100644
index 000000000000..7bf545e298d7
--- /dev/null
+++ b/usr.bin/fortune/datfiles/Makefile
@@ -0,0 +1,15 @@
+DB= freebsd-tips
+
+BLDS= ${DB:S/$/.dat/}
+FILES= ${DB} ${BLDS}
+CLEANFILES+=${BLDS}
+
+FILESDIR= ${SHAREDIR}/games/fortune
+
+.for f in ${DB}
+$f.dat: $f
+ PATH=$$PATH:/usr/bin:${FORTUNE_OBJ}/strfile \
+ strfile -Cs ${.ALLSRC} ${.TARGET}
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fortune/datfiles/Makefile.depend b/usr.bin/fortune/datfiles/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/fortune/datfiles/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fortune/datfiles/freebsd-tips b/usr.bin/fortune/datfiles/freebsd-tips
new file mode 100644
index 000000000000..1e9501e3a6fb
--- /dev/null
+++ b/usr.bin/fortune/datfiles/freebsd-tips
@@ -0,0 +1,862 @@
+Any user that is a member of the wheel group can use "su -" to simulate
+a root login. You can add a user to the wheel group with:
+pw groupmod -n wheel -m user_name
+ -- Konstantinos Konstantinidis <kkonstan@duth.gr>
+%
+By pressing "Scroll Lock" you can use the arrow keys to scroll backward
+through the console output. Press "Scroll Lock" again to turn it off.
+Don't have a "Scroll Lock" key? The "Pause / Break" key acts alike.
+%
+Can't remember if you've installed a certain port or not? Try "pkg info
+-x port_name".
+%
+Ever wonder what those numbers after command names were, as in cat(1)? It's
+the section of the manual the man page is in. "man man" will tell you more.
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+Forget how to spell a word or a variation of a word? Use
+
+ look portion_of_word_you_know
+ -- Dru <genesis@istar.ca>
+%
+Forget what directory you are in? Type "pwd".
+ -- Dru <genesis@istar.ca>
+%
+Forget when Easter is? Try "ncal -e". If you need the date for Orthodox
+Easter, use "ncal -o" instead.
+ -- Dru <genesis@istar.ca>
+%
+FreeBSD is started up by the program 'init'. The first thing init does when
+starting multiuser mode (ie, starting the computer up for normal use) is to
+run the shell script /etc/rc. By reading /etc/rc and the /etc/rc.d/ scripts,
+you can learn a lot about how the system is put together, which again will
+make you more confident about what happens when you do something with it.
+%
+Handy bash(1) prompt: PS1="\u@\h \w \!$ "
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+Having trouble using fetch through a firewall? Try setting the environment
+variable FTP_PASSIVE_MODE to yes, and see fetch(3) for more details.
+%
+If other operating systems have damaged your Master Boot Record, you can
+reinstall it with gpart(8). See
+"man gpart" for details.
+%
+If you accidentally end up inside vi, you can quit it by pressing Escape, colon
+(:), q (q), bang (!) and pressing return.
+%
+If you do not want to get beeps in X11 (X Windows), you can turn them off with
+
+ xset b off
+%
+If you have a CD-ROM drive in your machine, you can make the CD-ROM that is
+presently inserted available by typing 'mount /cdrom' as root. The CD-ROM
+will be available under /cdrom/. Remember to do 'umount /cdrom' before
+removing the CD-ROM (it will usually not be possible to remove the CD-ROM
+without doing this.)
+
+Note: This tip may not work in all configurations.
+%
+If you need a reminder to leave your terminal, type "leave +hhmm" where
+"hhmm" represents in how many hours and minutes you need to leave.
+ -- Dru <genesis@istar.ca>
+%
+If you need to ask a question on the FreeBSD-questions mailing list then
+
+ https://docs.freebsd.org/en/articles/freebsd-questions
+
+contains lots of useful advice to help you get the best results.
+%
+If you write part of a filename in tcsh,
+pressing TAB will show you the available choices when there
+is more than one, or complete the filename if there's only one match.
+%
+If you `set watch = (0 any any)' in tcsh, you will be notified when
+someone logs in or out of your system.
+%
+If you use the C shell, add the following line to the .cshrc file in your
+home directory to prevent core files from being written to disk:
+
+ limit coredumpsize 0
+ -- Dru <genesis@istar.ca>
+%
+If you want df(1) and other commands to display disk sizes in
+kilobytes instead of 512-byte blocks, set BLOCKSIZE in your
+environment to 'K'. You can also use 'M' for Megabytes or 'G' for
+Gigabytes. If you want df(1) to automatically select the best size
+then use 'df -h'.
+%
+If you want to play CDs with FreeBSD, a utility for this is already included.
+Type 'cdcontrol' then 'help' to learn more. (You may need to set the CDROM
+environment variable in order to make cdcontrol want to start.)
+%
+If you'd like to keep track of applications in the FreeBSD ports tree, take a
+look at FreshPorts;
+
+ https://www.freshports.org/
+%
+In order to make fetch (the FreeBSD downloading tool) ask for
+username/password when it encounters a password-protected web page, you can set
+the environment variable HTTP_AUTH to 'basic:*'.
+%
+In order to search for a string in some files, use 'grep' like this:
+
+ grep "string" filename1 [filename2 filename3 ...]
+
+This will print out the lines in the files that contain the string. grep can
+also do a lot more advanced searches - type 'man grep' for details.
+%
+In order to support national characters for European languages in tools like
+less without creating other nationalisation aspects, set the environment
+variable LC_ALL to 'en_US.UTF-8'.
+%
+"man firewall" will give advice for building a FreeBSD firewall using ipfw(8).
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+"man hier" will explain the way FreeBSD filesystems are normally laid out.
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+Man pages are divided into section depending on topic. There are 9 different
+sections numbered from 1 (General Commands) to 9 (Kernel Developer's Manual).
+You can get an introduction to each topic by typing
+
+ man <number> intro
+
+In other words, to get the intro to general commands, type
+
+ man 1 intro
+%
+"man ports" gives many useful hints about installing FreeBSD ports.
+%
+"man security" gives very good advice on how to tune the security of your
+FreeBSD system.
+%
+"man tuning" gives some tips how to tune performance of your FreeBSD system.
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+Need to do a search in a manpage or in a file you've sent to a pager? Use
+"/search_word". To repeat the same search, type "n" for next or "p" for
+previous.
+ -- Dru <genesis@istar.ca>
+%
+Need to find the location of a program? Use "locate program_name".
+ -- Dru <genesis@istar.ca>
+%
+Need to leave your terminal for a few minutes and don't want to logout?
+Use "lock -p". When you return, use your password as the key to unlock the
+terminal.
+ -- Dru <genesis@istar.ca>
+%
+Need to quickly empty a file? Use ": > filename".
+ -- Dru <genesis@istar.ca>
+%
+Need to quickly return to your home directory? Type "cd".
+ -- Dru <genesis@istar.ca>
+%
+Need to remove all those ^M characters from a DOS file? Try
+
+ tr -d \\r < dosfile > newfile
+ -- Originally by Dru <genesis@istar.ca>
+%
+Need to see the calendar for this month? Simply type "cal". To see the
+whole year, type "cal -y".
+ -- Dru <genesis@istar.ca>
+%
+Need to see which daemons are listening for connection requests? Use
+"sockstat -4l" for IPv4, and "sockstat -l" for IPv4 and IPv6.
+ -- Dru <genesis@istar.ca>
+%
+Need to see your routing table? Type "netstat -rn". The entry with the G
+flag is your gateway.
+ -- Dru <genesis@istar.ca>
+%
+Nice bash prompt: PS1='(\[$(tput md)\]\t <\w>\[$(tput me)\]) $(echo $?) \$ '
+ -- Mathieu <mathieu@hal.interactionvirtuelle.com>
+%
+Over quota? "du -sh * | sort -h " will give you a sorted list of your
+directory sizes.
+ -- David Scheidt <dscheidt@tumbolia.com>
+%
+nc(1) (or netcat) is useful not only for redirecting input/output to
+TCP or UDP connections, but also for proxying them with inetd(8).
+%
+sh (the default Bourne shell in FreeBSD) supports command-line editing. Just
+``set -o emacs'' or ``set -o vi'' to enable it. Use "<TAB>" key to complete
+paths.
+%
+Simple tcsh prompt: set prompt = '%# '
+%
+The default editor in FreeBSD is vi, which is efficient to use when you have
+learned it, but somewhat user-unfriendly. To use ee (an easier but less
+powerful editor) instead, set the environment variable EDITOR to /usr/bin/ee
+%
+Time to change your password? Type "passwd" and follow the prompts.
+ -- Dru <genesis@istar.ca>
+%
+To change an environment variable in /bin/sh use:
+
+ $ VARIABLE="value"
+ $ export VARIABLE
+%
+To change an environment variable in tcsh you use: setenv NAME "value"
+where NAME is the name of the variable and "value" its new value.
+%
+To clear the screen, use "clear". To re-display your screen buffer, press
+the scroll lock key and use your page up button. When you're finished,
+press the scroll lock key again to get your prompt back.
+ -- Dru <genesis@istar.ca>
+%
+You can press Ctrl-L while in the shell to clear the screen.
+%
+To determine whether a file is a text file, executable, or some other type
+of file, use
+
+ file filename
+ -- Dru <genesis@istar.ca>
+%
+To do a fast search for a file, try
+
+ locate filename
+
+locate uses a database that is updated every Saturday (assuming your computer
+is running FreeBSD at the time) to quickly find files based on name only.
+%
+To erase a line you've written at the command prompt, use "Ctrl-U".
+ -- Dru <genesis@istar.ca>
+%
+To find out the hostname associated with an IP address, use
+
+ drill -x IP_address
+ -- Dru <genesis@istar.ca>
+%
+To obtain a neat PostScript rendering of a manual page, use ``-t'' switch
+of the man(1) utility: ``man -t <topic>''. For example:
+
+ man -t grep > grep.ps # Save the PostScript version to a file
+or
+ man -t printf | lp # Send the PostScript directly to printer
+%
+To quickly create an empty file, use "touch filename".
+ -- Dru <genesis@istar.ca>
+%
+To read a compressed file without having to first uncompress it, use
+"zcat" or "zless" to view it. There is also "bzcat", "bzless", "xzcat"
+and "xzless".
+ -- Dru <genesis@istar.ca>
+%
+To save disk space in your home directory, compress files you rarely
+use with "gzip filename".
+ -- Dru <genesis@istar.ca>
+%
+To search for files that match a particular name, use find(1); for example
+
+ find / -name "*GENERIC*" -ls
+
+will search '/', and all subdirectories, for files with 'GENERIC' in the name.
+ -- Stephen Hilton <nospam@hiltonbsd.com>
+%
+To see all of the directories on your FreeBSD system, type
+
+ find / -type d | less
+
+All the files?
+
+ find / -type f | less
+%
+To see how long it takes a command to run, type the word "time" before the
+command name.
+ -- Dru <genesis@istar.ca>
+%
+To see how much disk space is left on your UFS partitions, use
+
+ df -h
+ -- Dru <genesis@istar.ca>
+%
+To see the 10 largest files in a directory or on a UFS partition, use
+
+ du -h /partition_or_directory_name | sort -rh | head
+ -- Dru <genesis@istar.ca>
+%
+To see the IP addresses currently set on your active interfaces, type
+"ifconfig -u".
+ -- Dru <genesis@istar.ca>
+%
+To see the last 10 lines of a long file, use "tail filename". To see the
+first 10 lines, use "head filename". To see new lines as they're appended
+to a file, use "tail -f filename".
+ -- Dru <genesis@istar.ca>
+%
+To see the last time that you logged in, use lastlogin(8).
+ -- Dru <genesis@istar.ca>
+%
+To see the MAC addresses of the NICs on your system, type
+
+ ifconfig -a
+ -- Dru <genesis@istar.ca>
+%
+To see the output from when your computer started, run dmesg(8). If it has
+been replaced with other messages, look at /var/run/dmesg.boot.
+ -- Francisco Reyes <lists@natserv.com>
+%
+Want colour in your directory listings? Use "ls -G". "ls -F" is also useful,
+and they can be combined as "ls -FG".
+%
+Want to find a specific port? Just type the following under /usr/ports
+or one of its subdirectories:
+
+ make search name=<port-name>
+ or
+ make search key=<keyword>
+%
+Want to know how many words, lines, or bytes are contained in a file? Type
+"wc filename".
+ -- Dru <genesis@istar.ca>
+%
+Want to see how much virtual memory you're using? Just type "swapinfo" to
+be shown information about the usage of your swap partitions.
+%
+Want to strip UTF-8 BOM(Byte Order Mark) from given files?
+
+ sed -e '1s/^\xef\xbb\xbf//' < bomfile > newfile
+%
+Want to use sed(1) to edit a file in place? Well, to replace every 'e' with
+an 'o', in a file named 'foo', you can do:
+
+ sed -i.bak s/e/o/g foo
+
+And you'll get a backup of the original in a file named 'foo.bak', but if you
+want no backup:
+
+ sed -i '' s/e/o/g foo
+%
+When you've made modifications to a file in vi(1) and then find that
+you can't write it, type ``<ESC>!rm -f %'' then ``:w!'' to force the
+write
+
+This won't work if you don't have write permissions to the directory
+and probably won't be suitable if you're editing through a symbolic link.
+
+If you have sudo(8) installed and permissions to use it, type
+``<ESC>w ! sudo tee %'' to force a write.
+%
+You can adjust the volume of various parts of the sound system in your
+computer by typing 'mixer <type>.volume=<volume>%'. To get a list of what
+you can adjust, just type 'mixer'.
+%
+You can automatically download and install binary packages by doing
+
+ pkg install <package>
+
+This will also automatically install the packages that are dependencies
+for the package you install (ie, the packages it needs in order to work.)
+%
+You can change the video mode on all consoles by adding something like
+the following to /etc/rc.conf:
+
+ allscreens="80x30"
+
+You can use "vidcontrol -i mode | grep T" for a list of supported text
+modes.
+ -- Konstantinos Konstantinidis <kkonstan@duth.gr>
+%
+You can disable tcsh's terminal beep if you `set nobeep'.
+%
+You can install extra packages for FreeBSD by using the ports system.
+If you have installed it, you can download, compile, and install software by
+just typing
+
+ # cd /usr/ports/<category>/<portname>
+ # make install && make clean
+
+as root. The ports infrastructure will download the software, change it so
+it works on FreeBSD, compile it, install it, register the installation so it
+will be possible to automatically uninstall it, and clean out the temporary
+working space it used. You can remove an installed port you decide you do not
+want after all by typing
+
+ # cd /usr/ports/<category>/<portname>
+ # make deinstall
+
+as root.
+%
+You can look through a file in a nice text-based interface by typing
+
+ less filename
+%
+You can make a log of your terminal session with script(1).
+%
+You can often get answers to your questions about FreeBSD by searching in the
+FreeBSD mailing list archives at
+
+ https://lists.freebsd.org/search
+%
+You can open up a new split-screen window in (n)vi with :N or :E and then
+use ^w to switch between the two.
+%
+You can permanently set environment variables for your shell by putting them
+in a startup file for the shell. The name of the startup file varies
+depending on the shell - csh and tcsh uses .login, bash, sh, ksh and zsh use
+.profile. When using bash, sh, ksh or zsh, don't forget to export the
+variable.
+%
+You can press Ctrl-D to quickly exit from a shell, or logout from a
+login shell.
+ -- Konstantinos Konstantinidis <kkonstan@duth.gr>
+%
+You can press up-arrow or down-arrow to walk through a list of
+previous commands in tcsh.
+%
+You can search for documentation on a keyword by typing
+
+ apropos keyword
+%
+You can `set autologout = 30' to have tcsh log you off automatically
+if you leave the shell idle for more than 30 minutes.
+%
+You can use aliases to decrease the amount of typing you need to do to get
+commands you commonly use. Examples of fairly popular aliases include (in
+Bourne shell style, as in /bin/sh, bash, ksh, and zsh):
+
+ alias lf="ls -FA"
+ alias ll="ls -lA"
+ alias su="su -m"
+
+In csh or tcsh, these would be
+
+ alias lf ls -FA
+ alias ll ls -lA
+ alias su su -m
+
+To remove an alias, you can usually use 'unalias aliasname'. To list all
+aliases, you can usually type just 'alias'.
+%
+You can use /etc/make.conf to control the options used to compile software
+on this system. Example entries are in
+/usr/share/examples/etc/make.conf and in make.conf(5).
+For options that are set for building FreeBSD's kernel and its world, see
+src.conf(5).
+%
+You can use "pkg info" to see a list of packages you have installed.
+%
+You can use the 'fetch' command to retrieve files over ftp, http or https.
+
+ fetch https://www.FreeBSD.org/images/beastie.png
+
+will download the beastie image from the FreeBSD web site.
+%
+You can use "whereis" to search standard binary, manual page and source
+directories for the specified programs. This can be particularly handy
+when you are trying to find where in the ports tree an application is.
+
+Try "whereis firefox" and "whereis whereis".
+ -- Konstantinos Konstantinidis <kkonstan@duth.gr>
+%
+Want to run the same command again?
+In many shells (e.g., tcsh, zsh, bash) you can type "!!".
+%
+Want to go the directory you were just in?
+Type "cd -"
+%
+Can't delete /usr/obj? Enter "chflags -R noschg /usr/obj" to remove the
+system immutable flag for all files in /usr/obj.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Want to list all files of an installed package? Enter
+"pkg info -l packagename".
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Are you looking for a package? Search for it with
+"pkg search part_of_package_name"
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+If you want to recursively copy a directory preserving file and directory
+attributes use
+"cp -a source target"
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Do you wonder what a terminal program is doing at the moment? dd(1) does not
+show any throughput? Hit "^T" (Control + t) to send SIGINFO to the process
+and see what it is doing.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Do you want to know which version of FreeBSD you are running? Enter
+"freebsd-version -ku" to display kernel and userland version.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+If you want to end one or more processes at a time using a regular expression
+enter "pkill regex".
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Do you want to run a program directly after some other process has ended? Use
+"pwait pid && new_program"
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+When you want your users to be able to reboot or shutdown FreeBSD, add them
+to the group "operator" and they are allowed to use shutdown(8) and poweroff(8).
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+If you need to create a FAT32 formatted USB thumb drive, find out its devicename
+running dmesg(8) after inserting it. Then create an MBR schema, a single slice and
+format it:
+
+# gpart create -s MBR ${devicename}
+# gpart add -t fat32 ${devicename}
+# newfs_msdos -F 32 -L thumbdrive ${devicename}s1
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+If you want to get a sorted list of all services that are started when FreeBSD boots,
+enter "service -e".
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+To easily configure your installed FreeBSD use bsdconfig(8).
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+After you compiled and installed a new version of FreeBSD, use etcupdate(8) to merge
+configuration updates.
+Run "etcupdate extract" once when your sources match your running system, then run
+"etcupdate" after every upgrade and "etcupdate resolve" to resolve any conflicts.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+Do you want to do a binary upgrade of your running FreeBSD installation? Use freebsd-update(8).
+
+To install updates and patches for the running branch use
+# freebsd-update fetch
+# freebsd-update install
+
+Then, to upgrade to a newer release use
+# freebsd-update upgrade -r ${name_of_release}
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+To run rc scripts in /etc/rc.d and /usr/local/etc/rc.d use service(8).
+Run "service ${name_of_rc_script} start" to start a daemon and
+"service ${name_of_rc_script} stop" to stop it.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+If you don't want to edit /etc/rc.conf directly, use sysrc(8) to add and remove entries.
+Use "sysrc name=value" to add an entry and "sysrc -x name" to delete an entry.
+
+ -- Lars Engels <lme@FreeBSD.org>
+%
+You can upload the dmesg of your system to help developers get an overview of commonly
+used hardware and peripherals for FreeBSD. Use the curl package to upload it like this:
+curl -v -d "nickname=$USER" -d "description=FreeBSD/$(uname -m) on \
+$(kenv smbios.system.maker) $(kenv smbios.system.product)" -d "do=addd" \
+--data-urlencode 'dmesg@/var/run/dmesg.boot' http://dmesgd.nycbug.org/index.cgi
+%
+Want to know how much memory (in bytes) your machine has installed? Let
+sysctl(8) tell you with the following command:
+
+sysctl hw.realmem
+
+The realmem value is memory before the kernel and modules are loaded, whereas
+hw.physmem is what is left after they were loaded.
+
+The number of active CPUs is displayed using this command:
+
+sysctl hw.ncpu
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+When using ZFS as the file system the "df" command is reporting the pool size
+and not file system sizes. It also does not know about descendent ZFS
+datasets, snapshots, quotas, and reservations with their individual space usage.
+Use the built-in "zfs list" command to get a better overview of space usage:
+
+zfs list -o space
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To learn more about what your system is doing, take a look at systat(1). For
+example, to get various statistics related to virtual memory usage, process
+scheduling, device interrupts, system name translation caching, and disk I/O,
+enter the following:
+
+systat -vmstat
+
+Other values are icmp, icmp6, ifstat, iostat, ip, ip6, netstat, pigs, sctp,
+swap, tcp, or zarc. You can switch between displays using :<display> and exit
+back to your shell by typing
+
+:quit
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To set a quota of 10 GB for the user named foo on a ZFS dataset, run the
+following command:
+
+# zfs set userquota@foo=10G pool/home/foo
+
+The zfs userspace command can display the quota and current space usage:
+
+# zfs userspace pool/home/foo
+
+To unset a quota, assign "none" as the value.
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+ZFS can display I/O statistics for a given pool using the iostat subcommand.
+By default, it will display one line of current activity. To display stats
+every 5 seconds run the following command (cancel with CTRL+C):
+
+zpool iostat 5
+
+To view individual disk activities, specify the -v parameter:
+
+zpool iostat -v
+
+Of course, both can be combined. For more options, see zpool(8).
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+FreeBSD's top(1) utility displays CPU statistics by default.
+To display I/O activity for each process instead, run top like this:
+
+top -m io
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+ZFS keeps a history of commands run against a specific pool using the
+history subcommand to zpool:
+
+zpool history
+
+More details are available using the -i and -l parameters. Note that ZFS
+will not keep the complete pool history forever and will remove older
+events in favor of never ones.
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To display the compression ratio for the ZFS dataset /var/log on the pool
+mypool, run the following command:
+
+zfs get refcompressratio mypool/var/log
+
+The refcompressratio will only display the compression ratio for that specific
+dataset, not the descendant datasets. To include the child datasets, the
+command looks like this:
+
+zfs get compressratio mypool/var
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+You can limit the depth of the displayed datasets in the "zfs list" output
+using the -d parameter. To display only the first level of datasets below
+mypool/usr and not the ones deeper than those, run this command:
+
+zfs list -d 1 mypool/usr
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+The "zfs list" command can be filtered in multiple ways. To display just
+the dataset name, use the -o parameter:
+
+zfs list -o name mypool/usr
+
+More columns and their order can be defined by separating them with commas:
+
+zfs list -o mountpoint,name,avail
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+The output of "zfs list" can be sorted by a specific column using -s. To
+sort the datasets by the "used" column in ascending order, run this command:
+
+zfs list -s used
+
+To sort in descending order instead, use -S:
+
+zfs list -S used
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To make the "zfs list" output more script-friendly, you can suppress the
+output of the headers for each column by passing the -H parameter:
+
+zfs list -H
+
+Another helpful option for script writers is -p, which displays the numbers
+in non-rounded, exact values:
+
+zfs list -p
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+Before deleting a dataset or snapshot, perform a dry run using the -n
+parameter. This is to make sure you really want to delete just that
+dataset/snapshot and not any dependent ones. ZFS will display the resulting
+action when -n is combined with the -v option without actually performing
+it:
+
+zfs destroy -nrv mypool@mysnap
+
+Once you are sure this is exactly what you intend to do, remove the -n
+parameter to execute the destroy operation.
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+You can delete a range of ZFS snapshots (a-z) in multiple ways.
+The following will delete d and all earlier snapshots:
+
+zfs destroy mypool/data@%d
+
+To delete d and all later snapshots:
+
+zfs destroy mypool/data@d%
+
+To delete all dataset snapshots:
+
+zfs destroy mypool/data@%
+
+Make sure to let ZFS perform a dry run (-n option) first and display (-v) what
+it would do to confirm that the delete operation is removing exactly what you
+intended.
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To set a custom ZFS property on the mypool pool, you need to provide it
+using the "key1:key2=value" syntax, where the colon (:) is used as the
+separator and identifier from the built-in ZFS properties:
+
+# zfs set warranty:expires=2038-01-19 mypool
+
+The custom property is applied to all datasets and can be queried like any
+built-in properties using zfs get:
+
+zfs get warranty:expires mypool
+
+To reset the value of a custom property, use the inherit subcommand:
+
+# zfs inherit warranty:expires mypool
+
+Removing a custom property from a pool is done using the -r flag to the
+"zfs inherit" command:
+
+# zfs inherit -r warranty:expires mypool
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+To delete a range of ZFS snapshots, use the % (percent) character after the
+full path to the first snapshot that should be included. For example, to
+simulate deleting snapshots a through (including) d, use this command:
+
+# zfs destroy -rvn mypool/tmp@a%d
+
+Once you are sure that this is what you want, remove the -n option:
+
+# zfs destroy -rv mypool/tmp@a%d
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+You can prevent the removal of a ZFS snapshot by using the hold subcommand.
+For example, to prevent the snapshot called milestone from deletion, run the
+following command:
+
+# zfs hold milestone_hold mypool/projects@my_milestone
+
+The "zfs holds" command will list all current snapshots that are protected
+this way (-r for a recursive list):
+
+# zfs holds -r mypool
+
+The TIMESTAMP column in the output of the above command is from when the
+hold was created, not the snapshot it holds. The "zfs destroy" command will
+echo a "dataset is busy" message on the console when it encounters a hold.
+Use "zfs release" to release the hold on the snapshot:
+
+# zfs release milestone_hold mypool/projects@my_milestone
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+A user "sender" needs the following permissions set to send a ZFS dataset:
+
+# zfs allow -u sender send,snapshot txpool
+
+On the receiving side, the user "receiver" requires these permissions:
+
+# zfs allow -u receiver compression,mountpoint,mount,create,receive rxpool
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+Don't let your zpool fill up completely by creating a dataset with
+reservation.
+
+# zfs create -o refreservation=<5% of total pool space> <poolname>/reserved
+
+You can always shrink the reserve if you need the space, but your pool will
+always have space left this way.
+
+ -- Benedict Reuschling <bcr@FreeBSD.org>
+%
+Sometimes a single slow HDD can cripple the performance of your entire system.
+You can spot one like this:
+
+# gstat -I5s | sort -rn -k9 | head
+
+ -- Alan Somers <asomers@FreeBSD.org>
+%
+FreeBSD's ps(1) can create a dependency tree based on parent/child
+relationships between processes, like this:
+
+$ ps -d
+
+ -- Daniel Ebdrup Jensen <debdrup@FreeBSD.org>
+%
+It is possible to measure the resident memory set:
+
+$ vmstat -o | awk 'NR>1 { t[$7] += $1 } \
+END { for (i in t) printf "%s %d\n",i,t[i] }'
+
+The rows have the following meaning:
+df = default (not assigned a specific pager)
+sw = swap
+df = virtual
+vn = vnode
+ph = heap
+md = memory device
+
+This will be reported in number of pages, so it needs to be multiplied by the
+page size of the architecture which can be found via:
+
+$ sysctl -n hw.pagesize
+
+ -- Daniel Ebdrup Jensen <debdrup@FreeBSD.org>
+%
+To establish a serial connection to anything including a USB device,
+nothing more than cu(1) is needed:
+
+$ cu -s 115200 -l /dev/ttyU0
+
+ -- Daniel Ebdrup Jensen <debdrup@FreeBSD.org>
+%
+You can control kernel stack(9) traces on ^T (tty info) by setting
+kern.tty_info_kstacks to 0 (off), 1 (on), or 2 (verbose), e.g.:
+
+# sysctl kern.tty_info_kstacks=2
+
+ -- Michael Gmelin <grembo@FreeBSD.org>
+%
+To determine which fonts provide a particular Unicode character, fc-list from
+the fontconfig package may be helpful. For example, if your friend complains
+that the emoji you sent won't display, run fc-list with the hex value of the
+character to determine which font your friend should install.
+
+$ fc-list ':charset=0x1F4A1'
+/usr/local/share/fonts/noto/NotoColorEmoji.ttf: Noto Color Emoji:style=Regular
+
+$ pkg which /usr/local/share/fonts/noto/NotoColorEmoji.ttf
+/usr/local/share/fonts/noto/NotoColorEmoji.ttf was installed by package noto-emoji-2.042
+%
+When netstat reports every 8 seconds, it tells traffic in bits per second:
+
+$ netstat -I bge0 8
+%
diff --git a/usr.bin/fortune/datfiles/freebsd-tips.sp.ok b/usr.bin/fortune/datfiles/freebsd-tips.sp.ok
new file mode 100644
index 000000000000..31bd76c03b05
--- /dev/null
+++ b/usr.bin/fortune/datfiles/freebsd-tips.sp.ok
@@ -0,0 +1,86 @@
+aliasname
+allscreens
+AUTH
+autolist
+autologout
+BLOCKSIZE
+bomfile
+cdcontrol
+cdrom
+CDs
+cfg
+conf
+coredumpsize
+csh
+cshrc
+Ctrl
+deinstall
+dmesg
+dosfile
+dscheidt
+duth
+ESC
+filec
+FreeBSD
+grep
+gzip
+hiltonbsd
+html
+http
+ifconfig
+inetd
+init
+interactionvirtuelle
+IPv
+istar
+kkonstan
+Konstantinidis
+ksh
+lastlogin
+lpr
+manpage
+mathieu
+misc
+natserv
+ncal
+netcat
+netstat
+newfile
+NICs
+nobeep
+nospam
+org
+passwd
+pkg
+portname
+PostScript
+printf
+proxying
+PS
+pwd
+Reyes
+sbin
+Scheidt
+setenv
+sockstat
+swapinfo
+sysinstall
+tcsh
+tcsh's
+tput
+tumbolia
+UDP
+umount
+unalias
+uninstall
+uniq
+username
+usr
+UTF
+vidcontrol
+whereis
+www
+xset
+zcat
+zmore
+zsh
diff --git a/usr.bin/fortune/fortune/Makefile b/usr.bin/fortune/fortune/Makefile
new file mode 100644
index 000000000000..c33a68f2295e
--- /dev/null
+++ b/usr.bin/fortune/fortune/Makefile
@@ -0,0 +1,8 @@
+PROG= fortune
+MAN= fortune.6
+CFLAGS+=-DDEBUG -I${FORTUNE_SRC}/strfile
+
+.include <bsd.prog.mk>
+
+test: ${PROG}
+ ./${PROG} -m brass
diff --git a/usr.bin/fortune/fortune/Makefile.depend b/usr.bin/fortune/fortune/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/fortune/fortune/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fortune/fortune/fortune.6 b/usr.bin/fortune/fortune/fortune.6
new file mode 100644
index 000000000000..6c2a677d24b6
--- /dev/null
+++ b/usr.bin/fortune/fortune/fortune.6
@@ -0,0 +1,201 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Ken Arnold.
+.\"
+.\" 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.
+.\"
+.Dd July 1, 2021
+.Dt FORTUNE 6
+.Os
+.Sh NAME
+.Nm fortune
+.Nd "print a random, hopefully interesting, adage"
+.Sh SYNOPSIS
+.Nm
+.Op Fl aDefilosw
+.Op Fl m Ar pattern
+.Oo
+.Op Ar \&N%
+.Ar file Ns / Ns Ar directory Ns / Ns Cm all
+.Oc
+.Sh DESCRIPTION
+When
+.Nm
+is run with no arguments it prints out a random epigram.
+Epigrams are divided into several categories, where each category
+is subdivided into those which are potentially offensive and those
+which are not.
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Choose from all lists of maxims, both offensive and not.
+(See the
+.Fl o
+option for more information on offensive fortunes.)
+.It Fl D
+Enable additional debugging output.
+Specify this option multiple times for more verbose output.
+Only available if compiled with
+.Li -DDEBUG .
+.It Fl e
+Consider all fortune files to be of equal size (see discussion below
+on multiple files).
+.It Fl f
+Print out the list of files which would be searched, but do not
+print a fortune.
+.It Fl l
+Long dictums only.
+.It Fl m Ar pattern
+Print out all fortunes which match the regular expression
+.Ar pattern .
+See
+.Xr regex 3
+for a description of patterns.
+.It Fl o
+Choose only from potentially offensive aphorisms.
+.Bf -symbolic
+Please, please, please request a potentially offensive fortune if and
+only if you believe, deep down in your heart, that you are willing
+to be offended.
+(And that if you are not willing, you will just quit using
+.Fl o
+rather than give us
+grief about it, okay?)
+.Ef
+.Bd -unfilled -offset indent
+\&... let us keep in mind the basic governing philosophy
+of The Brotherhood, as handsomely summarized in these words:
+we believe in healthy, hearty laughter -- at the expense of
+the whole human race, if needs be.
+Needs be.
+ --H. Allen Smith, "Rude Jokes"
+.Ed
+.It Fl s
+Short apothegms only.
+.It Fl i
+Ignore case for
+.Fl m
+patterns.
+.It Fl w
+Wait before termination for an amount of time calculated from the
+number of characters in the message.
+This is useful if it is executed as part of the logout procedure
+to guarantee that the message can be read before the screen is cleared.
+.El
+.Pp
+The user may specify alternate sayings.
+You can specify a specific file, a directory which contains one or
+more files, or the special word
+.Cm all
+which says to use all the standard databases.
+Any of these may be preceded by a percentage, which is a number
+.Ar N
+between 0 and 100 inclusive, followed by a
+.Ql % .
+If it is, there will be an
+.Ar N
+percent probability that an adage will be picked from that file
+or directory.
+If the percentages do not sum to 100, and there are specifications
+without percentages, the remaining percent will apply to those files
+and/or directories, in which case the probability of selecting from
+one of them will be based on their relative sizes.
+.Pp
+As an example, given two databases
+.Pa funny
+and
+.Pa not-funny ,
+with
+.Pa funny
+twice as big, saying
+.Pp
+.Dl "fortune funny not-funny"
+.Pp
+will get you fortunes out of
+.Pa funny
+two-thirds of the time.
+The command
+.Pp
+.Dl "fortune 90% funny 10% not-funny"
+.Pp
+will pick out 90% of its fortunes from
+.Pa funny
+(the
+.Dq Li "10% not-funny"
+is unnecessary, since 10% is all that is left).
+The
+.Fl e
+option says to consider all files equal;
+thus
+.Pp
+.Dl "fortune -e funny not-funny"
+.Pp
+is equivalent to
+.Pp
+.Dl "fortune 50% funny 50% not-funny"
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev FORTUNE_PATH"
+.It Ev FORTUNE_PATH
+The search path for the data files.
+It is a colon-separated list of directories in which
+.Nm
+looks for data files.
+If not set it will default to
+.Pa /usr/share/games/fortune:/usr/local/share/games/fortune .
+If none of the directories specified exist, it will print a warning and exit.
+.It Ev FORTUNE_SAVESTATE
+If set, fortune will save some state about what fortune
+it was up to on disk.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /usr/share/games/fortune/*"
+.It Pa /usr/share/games/fortune/*
+the fortunes databases (those files ending
+.Dq Pa -o
+contain the
+.Sy offensive
+fortunes)
+.El
+.Sh EXIT STATUS
+.Ex -std
+In particular, if
+.Fl l ,
+.Fl m ,
+or
+.Fl s
+is specified, failure to find a matching citation in the selected
+files counts as an error.
+.Sh SEE ALSO
+.Xr arc4random_uniform 3 ,
+.Xr regcomp 3 ,
+.Xr regex 3 ,
+.Xr strfile 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared
+.At v7 .
diff --git a/usr.bin/fortune/fortune/fortune.c b/usr.bin/fortune/fortune/fortune.c
new file mode 100644
index 000000000000..4989f11f1085
--- /dev/null
+++ b/usr.bin/fortune/fortune/fortune.c
@@ -0,0 +1,1415 @@
+/*-
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Arnold.
+ *
+ * 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/endian.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "strfile.h"
+#include "pathnames.h"
+
+#define TRUE true
+#define FALSE false
+
+#define MINW 6 /* minimum wait if desired */
+#define CPERS 20 /* # of chars for each sec */
+#define SLEN 160 /* # of chars in short fortune */
+
+#define POS_UNKNOWN ((uint32_t) -1) /* pos for file unknown */
+#define NO_PROB (-1) /* no prob specified for file */
+
+#ifdef DEBUG
+#define DPRINTF(l,x) { if (Debug >= l) fprintf x; }
+#undef NDEBUG
+#else
+#define DPRINTF(l,x)
+#define NDEBUG 1
+#endif
+
+typedef struct fd {
+ int percent;
+ int fd, datfd;
+ uint32_t pos;
+ FILE *inf;
+ const char *name;
+ const char *path;
+ char *datfile, *posfile;
+ bool read_tbl;
+ bool was_pos_file;
+ STRFILE tbl;
+ int num_children;
+ struct fd *child, *parent;
+ struct fd *next, *prev;
+} FILEDESC;
+
+static bool Found_one; /* did we find a match? */
+static bool Find_files = FALSE; /* just find a list of proper fortune files */
+static bool Fortunes_only = FALSE; /* check only "fortunes" files */
+static bool Wait = FALSE; /* wait desired after fortune */
+static bool Short_only = FALSE; /* short fortune desired */
+static bool Long_only = FALSE; /* long fortune desired */
+static bool Offend = FALSE; /* offensive fortunes only */
+static bool All_forts = FALSE; /* any fortune allowed */
+static bool Equal_probs = FALSE; /* scatter un-allocted prob equally */
+static bool Match = FALSE; /* dump fortunes matching a pattern */
+static bool WriteToDisk = false; /* use files on disk to save state */
+#ifdef DEBUG
+static int Debug = 0; /* print debug messages */
+#endif
+
+static char *Fortbuf = NULL; /* fortune buffer for -m */
+
+static int Fort_len = 0;
+
+static off_t Seekpts[2]; /* seek pointers to fortunes */
+
+static FILEDESC *File_list = NULL, /* Head of file list */
+ *File_tail = NULL; /* Tail of file list */
+static FILEDESC *Fortfile; /* Fortune file to use */
+
+static STRFILE Noprob_tbl; /* sum of data for all no prob files */
+
+static const char *Fortune_path;
+static char **Fortune_path_arr;
+
+static int add_dir(FILEDESC *);
+static int add_file(int, const char *, const char *, FILEDESC **,
+ FILEDESC **, FILEDESC *);
+static void all_forts(FILEDESC *, char *);
+static char *copy(const char *, u_int);
+static void display(FILEDESC *);
+static void do_free(void *);
+static void *do_malloc(u_int);
+static int form_file_list(char **, int);
+static int fortlen(void);
+static void get_fort(void);
+static void get_pos(FILEDESC *);
+static void get_tbl(FILEDESC *);
+static void getargs(int, char *[]);
+static void getpath(void);
+static void init_prob(void);
+static int is_dir(const char *);
+static int is_fortfile(const char *, char **, char **, int);
+static int is_off_name(const char *);
+static int max(int, int);
+static FILEDESC *new_fp(void);
+static char *off_name(const char *);
+static void open_dat(FILEDESC *);
+static void open_fp(FILEDESC *);
+static FILEDESC *pick_child(FILEDESC *);
+static void print_file_list(void);
+static void print_list(FILEDESC *, int);
+static void sum_noprobs(FILEDESC *);
+static void sum_tbl(STRFILE *, STRFILE *);
+static void usage(void);
+static void zero_tbl(STRFILE *);
+
+static char *conv_pat(char *);
+static int find_matches(void);
+static void matches_in_list(FILEDESC *);
+static int maxlen_in_list(FILEDESC *);
+
+static regex_t Re_pat;
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+
+ if (getenv("FORTUNE_SAVESTATE") != NULL)
+ WriteToDisk = true;
+
+ (void) setlocale(LC_ALL, "");
+
+ getpath();
+ getargs(argc, argv);
+
+ if (Match)
+ exit(find_matches() != 0);
+
+ init_prob();
+ do {
+ get_fort();
+ } while ((Short_only && fortlen() > SLEN) ||
+ (Long_only && fortlen() <= SLEN));
+
+ display(Fortfile);
+
+ if (WriteToDisk) {
+ if ((fd = creat(Fortfile->posfile, 0666)) < 0) {
+ perror(Fortfile->posfile);
+ exit(1);
+ }
+ /*
+ * if we can, we exclusive lock, but since it isn't very
+ * important, we just punt if we don't have easy locking
+ * available.
+ */
+ flock(fd, LOCK_EX);
+ write(fd, (char *) &Fortfile->pos, sizeof Fortfile->pos);
+ if (!Fortfile->was_pos_file)
+ chmod(Fortfile->path, 0666);
+ flock(fd, LOCK_UN);
+ }
+ if (Wait) {
+ if (Fort_len == 0)
+ (void) fortlen();
+ sleep((unsigned int) max(Fort_len / CPERS, MINW));
+ }
+
+ exit(0);
+}
+
+static void
+display(FILEDESC *fp)
+{
+ char *p;
+ unsigned char ch;
+ char line[BUFSIZ];
+
+ open_fp(fp);
+ fseeko(fp->inf, Seekpts[0], SEEK_SET);
+ for (Fort_len = 0; fgets(line, sizeof line, fp->inf) != NULL &&
+ !STR_ENDSTRING(line, fp->tbl); Fort_len++) {
+ if (fp->tbl.str_flags & STR_ROTATED)
+ for (p = line; (ch = *p) != '\0'; ++p) {
+ if (isascii(ch)) {
+ if (isupper(ch))
+ *p = 'A' + (ch - 'A' + 13) % 26;
+ else if (islower(ch))
+ *p = 'a' + (ch - 'a' + 13) % 26;
+ }
+ }
+ if (fp->tbl.str_flags & STR_COMMENTS
+ && line[0] == fp->tbl.str_delim
+ && line[1] == fp->tbl.str_delim)
+ continue;
+ fputs(line, stdout);
+ }
+ (void) fflush(stdout);
+}
+
+/*
+ * fortlen:
+ * Return the length of the fortune.
+ */
+static int
+fortlen(void)
+{
+ int nchar;
+ char line[BUFSIZ];
+
+ if (!(Fortfile->tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
+ nchar = (int)(Seekpts[1] - Seekpts[0]);
+ else {
+ open_fp(Fortfile);
+ fseeko(Fortfile->inf, Seekpts[0], SEEK_SET);
+ nchar = 0;
+ while (fgets(line, sizeof line, Fortfile->inf) != NULL &&
+ !STR_ENDSTRING(line, Fortfile->tbl))
+ nchar += strlen(line);
+ }
+ Fort_len = nchar;
+
+ return (nchar);
+}
+
+/*
+ * This routine evaluates the arguments on the command line
+ */
+static void
+getargs(int argc, char *argv[])
+{
+ int ignore_case;
+ char *pat;
+ int ch;
+
+ ignore_case = FALSE;
+ pat = NULL;
+
+#ifdef DEBUG
+ while ((ch = getopt(argc, argv, "aDefilm:osw")) != -1)
+#else
+ while ((ch = getopt(argc, argv, "aefilm:osw")) != -1)
+#endif /* DEBUG */
+ switch(ch) {
+ case 'a': /* any fortune */
+ All_forts = TRUE;
+ break;
+#ifdef DEBUG
+ case 'D':
+ Debug++;
+ break;
+#endif /* DEBUG */
+ case 'e': /* scatter un-allocted prob equally */
+ Equal_probs = TRUE;
+ break;
+ case 'f': /* find fortune files */
+ Find_files = TRUE;
+ break;
+ case 'l': /* long ones only */
+ Long_only = TRUE;
+ Short_only = FALSE;
+ break;
+ case 'o': /* offensive ones only */
+ Offend = TRUE;
+ break;
+ case 's': /* short ones only */
+ Short_only = TRUE;
+ Long_only = FALSE;
+ break;
+ case 'w': /* give time to read */
+ Wait = TRUE;
+ break;
+ case 'm': /* dump out the fortunes */
+ Match = TRUE;
+ pat = optarg;
+ break;
+ case 'i': /* case-insensitive match */
+ ignore_case++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!form_file_list(argv, argc))
+ exit(1); /* errors printed through form_file_list() */
+ if (Find_files) {
+ print_file_list();
+ exit(0);
+ }
+#ifdef DEBUG
+ else if (Debug >= 1)
+ print_file_list();
+#endif /* DEBUG */
+
+ if (pat != NULL) {
+ int error;
+
+ if (ignore_case)
+ pat = conv_pat(pat);
+ error = regcomp(&Re_pat, pat, REG_BASIC);
+ if (error) {
+ fprintf(stderr, "regcomp(%s) fails\n", pat);
+ exit(1);
+ }
+ }
+}
+
+/*
+ * form_file_list:
+ * Form the file list from the file specifications.
+ */
+static int
+form_file_list(char **files, int file_cnt)
+{
+ int i, percent;
+ char *sp;
+ char **pstr;
+
+ if (file_cnt == 0) {
+ if (Find_files) {
+ Fortunes_only = TRUE;
+ pstr = Fortune_path_arr;
+ i = 0;
+ while (*pstr) {
+ i += add_file(NO_PROB, *pstr++, NULL,
+ &File_list, &File_tail, NULL);
+ }
+ Fortunes_only = FALSE;
+ if (!i) {
+ fprintf(stderr, "No fortunes found in %s.\n",
+ Fortune_path);
+ }
+ return (i != 0);
+ } else {
+ pstr = Fortune_path_arr;
+ i = 0;
+ while (*pstr) {
+ i += add_file(NO_PROB, "fortunes", *pstr++,
+ &File_list, &File_tail, NULL);
+ }
+ if (!i) {
+ fprintf(stderr, "No fortunes found in %s.\n",
+ Fortune_path);
+ }
+ return (i != 0);
+ }
+ }
+ for (i = 0; i < file_cnt; i++) {
+ percent = NO_PROB;
+ if (!isdigit((unsigned char)files[i][0]))
+ sp = files[i];
+ else {
+ percent = 0;
+ for (sp = files[i]; isdigit((unsigned char)*sp); sp++) {
+ percent = percent * 10 + *sp - '0';
+ if (percent > 100) {
+ fprintf(stderr, "percentages must be <= 100\n");
+ return (FALSE);
+ }
+ }
+ if (*sp == '.') {
+ fprintf(stderr, "percentages must be integers\n");
+ return (FALSE);
+ }
+ /*
+ * If the number isn't followed by a '%', then
+ * it was not a percentage, just the first part
+ * of a file name which starts with digits.
+ */
+ if (*sp != '%') {
+ percent = NO_PROB;
+ sp = files[i];
+ }
+ else if (*++sp == '\0') {
+ if (++i >= file_cnt) {
+ fprintf(stderr, "percentages must precede files\n");
+ return (FALSE);
+ }
+ sp = files[i];
+ }
+ }
+ if (strcmp(sp, "all") == 0) {
+ pstr = Fortune_path_arr;
+ i = 0;
+ while (*pstr) {
+ i += add_file(NO_PROB, *pstr++, NULL,
+ &File_list, &File_tail, NULL);
+ }
+ if (!i) {
+ fprintf(stderr, "No fortunes found in %s.\n",
+ Fortune_path);
+ return (FALSE);
+ }
+ } else if (!add_file(percent, sp, NULL, &File_list,
+ &File_tail, NULL)) {
+ return (FALSE);
+ }
+ }
+
+ return (TRUE);
+}
+
+/*
+ * add_file:
+ * Add a file to the file list.
+ */
+static int
+add_file(int percent, const char *file, const char *dir, FILEDESC **head,
+ FILEDESC **tail, FILEDESC *parent)
+{
+ FILEDESC *fp;
+ int fd;
+ const char *path;
+ char *tpath, *offensive;
+ bool was_malloc;
+ bool isdir;
+
+ if (dir == NULL) {
+ path = file;
+ tpath = NULL;
+ was_malloc = FALSE;
+ }
+ else {
+ tpath = do_malloc((unsigned int)(strlen(dir) + strlen(file) + 2));
+ strcat(strcat(strcpy(tpath, dir), "/"), file);
+ path = tpath;
+ was_malloc = TRUE;
+ }
+ if ((isdir = is_dir(path)) && parent != NULL) {
+ if (was_malloc)
+ free(tpath);
+ return (FALSE); /* don't recurse */
+ }
+ offensive = NULL;
+ if (!isdir && parent == NULL && (All_forts || Offend) &&
+ !is_off_name(path)) {
+ offensive = off_name(path);
+ if (Offend) {
+ if (was_malloc)
+ free(tpath);
+ path = tpath = offensive;
+ offensive = NULL;
+ was_malloc = TRUE;
+ DPRINTF(1, (stderr, "\ttrying \"%s\"\n", path));
+ file = off_name(file);
+ }
+ }
+
+ DPRINTF(1, (stderr, "adding file \"%s\"\n", path));
+over:
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ /*
+ * This is a sneak. If the user said -a, and if the
+ * file we're given isn't a file, we check to see if
+ * there is a -o version. If there is, we treat it as
+ * if *that* were the file given. We only do this for
+ * individual files -- if we're scanning a directory,
+ * we'll pick up the -o file anyway.
+ */
+ if (All_forts && offensive != NULL) {
+ if (was_malloc)
+ free(tpath);
+ path = tpath = offensive;
+ offensive = NULL;
+ was_malloc = TRUE;
+ DPRINTF(1, (stderr, "\ttrying \"%s\"\n", path));
+ file = off_name(file);
+ goto over;
+ }
+ if (dir == NULL && file[0] != '/') {
+ int i = 0;
+ char **pstr = Fortune_path_arr;
+
+ while (*pstr) {
+ i += add_file(percent, file, *pstr++,
+ head, tail, parent);
+ }
+ if (!i) {
+ fprintf(stderr, "No '%s' found in %s.\n",
+ file, Fortune_path);
+ }
+ return (i != 0);
+ }
+ /*
+ if (parent == NULL)
+ perror(path);
+ */
+ if (was_malloc)
+ free(tpath);
+ return (FALSE);
+ }
+
+ DPRINTF(2, (stderr, "path = \"%s\"\n", path));
+
+ fp = new_fp();
+ fp->fd = fd;
+ fp->percent = percent;
+ fp->name = file;
+ fp->path = path;
+ fp->parent = parent;
+
+ if ((isdir && !add_dir(fp)) ||
+ (!isdir &&
+ !is_fortfile(path, &fp->datfile, &fp->posfile, (parent != NULL))))
+ {
+ if (parent == NULL)
+ fprintf(stderr,
+ "fortune:%s not a fortune file or directory\n",
+ path);
+ if (was_malloc)
+ free(tpath);
+ do_free(fp->datfile);
+ do_free(fp->posfile);
+ free(fp);
+ do_free(offensive);
+ return (FALSE);
+ }
+ /*
+ * If the user said -a, we need to make this node a pointer to
+ * both files, if there are two. We don't need to do this if
+ * we are scanning a directory, since the scan will pick up the
+ * -o file anyway.
+ */
+ if (All_forts && parent == NULL && !is_off_name(path))
+ all_forts(fp, offensive);
+ if (*head == NULL)
+ *head = *tail = fp;
+ else if (fp->percent == NO_PROB) {
+ (*tail)->next = fp;
+ fp->prev = *tail;
+ *tail = fp;
+ }
+ else {
+ (*head)->prev = fp;
+ fp->next = *head;
+ *head = fp;
+ }
+ if (WriteToDisk)
+ fp->was_pos_file = (access(fp->posfile, W_OK) >= 0);
+
+ return (TRUE);
+}
+
+/*
+ * new_fp:
+ * Return a pointer to an initialized new FILEDESC.
+ */
+static FILEDESC *
+new_fp(void)
+{
+ FILEDESC *fp;
+
+ fp = do_malloc(sizeof(*fp));
+ fp->datfd = -1;
+ fp->pos = POS_UNKNOWN;
+ fp->inf = NULL;
+ fp->fd = -1;
+ fp->percent = NO_PROB;
+ fp->read_tbl = FALSE;
+ fp->next = NULL;
+ fp->prev = NULL;
+ fp->child = NULL;
+ fp->parent = NULL;
+ fp->datfile = NULL;
+ fp->posfile = NULL;
+
+ return (fp);
+}
+
+/*
+ * off_name:
+ * Return a pointer to the offensive version of a file of this name.
+ */
+static char *
+off_name(const char *file)
+{
+ char *new;
+
+ new = copy(file, (unsigned int) (strlen(file) + 2));
+
+ return (strcat(new, "-o"));
+}
+
+/*
+ * is_off_name:
+ * Is the file an offensive-style name?
+ */
+static int
+is_off_name(const char *file)
+{
+ int len;
+
+ len = strlen(file);
+
+ return (len >= 3 && file[len - 2] == '-' && file[len - 1] == 'o');
+}
+
+/*
+ * all_forts:
+ * Modify a FILEDESC element to be the parent of two children if
+ * there are two children to be a parent of.
+ */
+static void
+all_forts(FILEDESC *fp, char *offensive)
+{
+ char *sp;
+ FILEDESC *scene, *obscene;
+ int fd;
+ char *datfile, *posfile;
+
+ if (fp->child != NULL) /* this is a directory, not a file */
+ return;
+ if (!is_fortfile(offensive, &datfile, &posfile, FALSE))
+ return;
+ if ((fd = open(offensive, O_RDONLY)) < 0)
+ return;
+ DPRINTF(1, (stderr, "adding \"%s\" because of -a\n", offensive));
+ scene = new_fp();
+ obscene = new_fp();
+ *scene = *fp;
+
+ fp->num_children = 2;
+ fp->child = scene;
+ scene->next = obscene;
+ obscene->next = NULL;
+ scene->child = obscene->child = NULL;
+ scene->parent = obscene->parent = fp;
+
+ fp->fd = -1;
+ scene->percent = obscene->percent = NO_PROB;
+
+ obscene->fd = fd;
+ obscene->inf = NULL;
+ obscene->path = offensive;
+ if ((sp = strrchr(offensive, '/')) == NULL)
+ obscene->name = offensive;
+ else
+ obscene->name = ++sp;
+ obscene->datfile = datfile;
+ obscene->posfile = posfile;
+ obscene->read_tbl = false;
+ if (WriteToDisk)
+ obscene->was_pos_file = (access(obscene->posfile, W_OK) >= 0);
+}
+
+/*
+ * add_dir:
+ * Add the contents of an entire directory.
+ */
+static int
+add_dir(FILEDESC *fp)
+{
+ DIR *dir;
+ struct dirent *dirent;
+ FILEDESC *tailp;
+ char *name;
+
+ (void) close(fp->fd);
+ fp->fd = -1;
+ if ((dir = opendir(fp->path)) == NULL) {
+ perror(fp->path);
+ return (FALSE);
+ }
+ tailp = NULL;
+ DPRINTF(1, (stderr, "adding dir \"%s\"\n", fp->path));
+ fp->num_children = 0;
+ while ((dirent = readdir(dir)) != NULL) {
+ if (dirent->d_namlen == 0)
+ continue;
+ name = copy(dirent->d_name, dirent->d_namlen);
+ if (add_file(NO_PROB, name, fp->path, &fp->child, &tailp, fp))
+ fp->num_children++;
+ else
+ free(name);
+ }
+ if (fp->num_children == 0) {
+ (void) fprintf(stderr,
+ "fortune: %s: No fortune files in directory.\n", fp->path);
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+/*
+ * is_dir:
+ * Return TRUE if the file is a directory, FALSE otherwise.
+ */
+static int
+is_dir(const char *file)
+{
+ struct stat sbuf;
+
+ if (stat(file, &sbuf) < 0)
+ return (FALSE);
+
+ return (sbuf.st_mode & S_IFDIR);
+}
+
+/*
+ * is_fortfile:
+ * Return TRUE if the file is a fortune database file. We try and
+ * exclude files without reading them if possible to avoid
+ * overhead. Files which start with ".", or which have "illegal"
+ * suffixes, as contained in suflist[], are ruled out.
+ */
+/* ARGSUSED */
+static int
+is_fortfile(const char *file, char **datp, char **posp, int check_for_offend)
+{
+ int i;
+ const char *sp;
+ char *datfile;
+ static const char *suflist[] = {
+ /* list of "illegal" suffixes" */
+ "dat", "pos", "c", "h", "p", "i", "f",
+ "pas", "ftn", "ins.c", "ins,pas",
+ "ins.ftn", "sml",
+ NULL
+ };
+
+ DPRINTF(2, (stderr, "is_fortfile(%s) returns ", file));
+
+ /*
+ * Preclude any -o files for offendable people, and any non -o
+ * files for completely offensive people.
+ */
+ if (check_for_offend && !All_forts) {
+ i = strlen(file);
+ if (Offend ^ (file[i - 2] == '-' && file[i - 1] == 'o')) {
+ DPRINTF(2, (stderr, "FALSE (offending file)\n"));
+ return (FALSE);
+ }
+ }
+
+ if ((sp = strrchr(file, '/')) == NULL)
+ sp = file;
+ else
+ sp++;
+ if (*sp == '.') {
+ DPRINTF(2, (stderr, "FALSE (file starts with '.')\n"));
+ return (FALSE);
+ }
+ if (Fortunes_only && strncmp(sp, "fortunes", 8) != 0) {
+ DPRINTF(2, (stderr, "FALSE (check fortunes only)\n"));
+ return (FALSE);
+ }
+ if ((sp = strrchr(sp, '.')) != NULL) {
+ sp++;
+ for (i = 0; suflist[i] != NULL; i++)
+ if (strcmp(sp, suflist[i]) == 0) {
+ DPRINTF(2, (stderr, "FALSE (file has suffix \".%s\")\n", sp));
+ return (FALSE);
+ }
+ }
+
+ datfile = copy(file, (unsigned int) (strlen(file) + 4)); /* +4 for ".dat" */
+ strcat(datfile, ".dat");
+ if (access(datfile, R_OK) < 0) {
+ DPRINTF(2, (stderr, "FALSE (no readable \".dat\" file)\n"));
+ free(datfile);
+ return (FALSE);
+ }
+ if (datp != NULL)
+ *datp = datfile;
+ else
+ free(datfile);
+ if (posp != NULL) {
+ if (WriteToDisk) {
+ *posp = copy(file, (unsigned int) (strlen(file) + 4)); /* +4 for ".dat" */
+ strcat(*posp, ".pos");
+ }
+ else {
+ *posp = NULL;
+ }
+ }
+ DPRINTF(2, (stderr, "TRUE\n"));
+
+ return (TRUE);
+}
+
+/*
+ * copy:
+ * Return a malloc()'ed copy of the string
+ */
+static char *
+copy(const char *str, unsigned int len)
+{
+ char *new, *sp;
+
+ new = do_malloc(len + 1);
+ sp = new;
+ do {
+ *sp++ = *str;
+ } while (*str++);
+
+ return (new);
+}
+
+/*
+ * do_malloc:
+ * Do a malloc, checking for NULL return.
+ */
+static void *
+do_malloc(unsigned int size)
+{
+ void *new;
+
+ if ((new = malloc(size)) == NULL) {
+ (void) fprintf(stderr, "fortune: out of memory.\n");
+ exit(1);
+ }
+
+ return (new);
+}
+
+/*
+ * do_free:
+ * Free malloc'ed space, if any.
+ */
+static void
+do_free(void *ptr)
+{
+ if (ptr != NULL)
+ free(ptr);
+}
+
+/*
+ * init_prob:
+ * Initialize the fortune probabilities.
+ */
+static void
+init_prob(void)
+{
+ FILEDESC *fp, *last = NULL;
+ int percent, num_noprob, frac;
+
+ /*
+ * Distribute the residual probability (if any) across all
+ * files with unspecified probability (i.e., probability of 0)
+ * (if any).
+ */
+
+ percent = 0;
+ num_noprob = 0;
+ for (fp = File_tail; fp != NULL; fp = fp->prev)
+ if (fp->percent == NO_PROB) {
+ num_noprob++;
+ if (Equal_probs)
+ last = fp;
+ } else
+ percent += fp->percent;
+ DPRINTF(1, (stderr, "summing probabilities:%d%% with %d NO_PROB's",
+ percent, num_noprob));
+ if (percent > 100) {
+ (void) fprintf(stderr,
+ "fortune: probabilities sum to %d%% > 100%%!\n", percent);
+ exit(1);
+ } else if (percent < 100 && num_noprob == 0) {
+ (void) fprintf(stderr,
+ "fortune: no place to put residual probability (%d%% < 100%%)\n",
+ percent);
+ exit(1);
+ } else if (percent == 100 && num_noprob != 0) {
+ (void) fprintf(stderr,
+ "fortune: no probability left to put in residual files (100%%)\n");
+ exit(1);
+ }
+ percent = 100 - percent;
+ if (Equal_probs) {
+ if (num_noprob != 0) {
+ if (num_noprob > 1) {
+ frac = percent / num_noprob;
+ DPRINTF(1, (stderr, ", frac = %d%%", frac));
+ for (fp = File_tail; fp != last; fp = fp->prev)
+ if (fp->percent == NO_PROB) {
+ fp->percent = frac;
+ percent -= frac;
+ }
+ }
+ last->percent = percent;
+ DPRINTF(1, (stderr, ", residual = %d%%", percent));
+ }
+ else
+ DPRINTF(1, (stderr,
+ ", %d%% distributed over remaining fortunes\n",
+ percent));
+ }
+ DPRINTF(1, (stderr, "\n"));
+
+#ifdef DEBUG
+ if (Debug >= 1)
+ print_file_list();
+#endif
+}
+
+/*
+ * get_fort:
+ * Get the fortune data file's seek pointer for the next fortune.
+ */
+static void
+get_fort(void)
+{
+ FILEDESC *fp;
+ int choice;
+
+ if (File_list->next == NULL || File_list->percent == NO_PROB)
+ fp = File_list;
+ else {
+ choice = arc4random_uniform(100);
+ DPRINTF(1, (stderr, "choice = %d\n", choice));
+ for (fp = File_list; fp->percent != NO_PROB; fp = fp->next) {
+ if (choice < fp->percent)
+ break;
+ else {
+ choice -= fp->percent;
+ DPRINTF(1, (stderr,
+ " skip \"%s\", %d%% (choice = %d)\n",
+ fp->name, fp->percent, choice));
+ }
+ }
+ DPRINTF(1, (stderr,
+ "using \"%s\", %d%% (choice = %d)\n",
+ fp->name, fp->percent, choice));
+ }
+ if (fp->percent != NO_PROB)
+ get_tbl(fp);
+ else {
+ if (fp->next != NULL) {
+ sum_noprobs(fp);
+ choice = arc4random_uniform(Noprob_tbl.str_numstr);
+ DPRINTF(1, (stderr, "choice = %d (of %u) \n", choice,
+ Noprob_tbl.str_numstr));
+ while ((unsigned int)choice >= fp->tbl.str_numstr) {
+ choice -= fp->tbl.str_numstr;
+ fp = fp->next;
+ DPRINTF(1, (stderr,
+ " skip \"%s\", %u (choice = %d)\n",
+ fp->name, fp->tbl.str_numstr,
+ choice));
+ }
+ DPRINTF(1, (stderr, "using \"%s\", %u\n", fp->name,
+ fp->tbl.str_numstr));
+ }
+ get_tbl(fp);
+ }
+ if (fp->child != NULL) {
+ DPRINTF(1, (stderr, "picking child\n"));
+ fp = pick_child(fp);
+ }
+ Fortfile = fp;
+ get_pos(fp);
+ open_dat(fp);
+ lseek(fp->datfd,
+ (off_t) (sizeof fp->tbl + fp->pos * sizeof Seekpts[0]), SEEK_SET);
+ read(fp->datfd, Seekpts, sizeof Seekpts);
+ Seekpts[0] = be64toh(Seekpts[0]);
+ Seekpts[1] = be64toh(Seekpts[1]);
+}
+
+/*
+ * pick_child
+ * Pick a child from a chosen parent.
+ */
+static FILEDESC *
+pick_child(FILEDESC *parent)
+{
+ FILEDESC *fp;
+ int choice;
+
+ if (Equal_probs) {
+ choice = arc4random_uniform(parent->num_children);
+ DPRINTF(1, (stderr, " choice = %d (of %d)\n",
+ choice, parent->num_children));
+ for (fp = parent->child; choice--; fp = fp->next)
+ continue;
+ DPRINTF(1, (stderr, " using %s\n", fp->name));
+ return (fp);
+ }
+ else {
+ get_tbl(parent);
+ choice = arc4random_uniform(parent->tbl.str_numstr);
+ DPRINTF(1, (stderr, " choice = %d (of %u)\n",
+ choice, parent->tbl.str_numstr));
+ for (fp = parent->child; (unsigned)choice >= fp->tbl.str_numstr;
+ fp = fp->next) {
+ choice -= fp->tbl.str_numstr;
+ DPRINTF(1, (stderr, "\tskip %s, %u (choice = %d)\n",
+ fp->name, fp->tbl.str_numstr, choice));
+ }
+ DPRINTF(1, (stderr, " using %s, %u\n", fp->name,
+ fp->tbl.str_numstr));
+ return (fp);
+ }
+}
+
+/*
+ * sum_noprobs:
+ * Sum up all the noprob probabilities, starting with fp.
+ */
+static void
+sum_noprobs(FILEDESC *fp)
+{
+ static bool did_noprobs = FALSE;
+
+ if (did_noprobs)
+ return;
+ zero_tbl(&Noprob_tbl);
+ while (fp != NULL) {
+ get_tbl(fp);
+ sum_tbl(&Noprob_tbl, &fp->tbl);
+ fp = fp->next;
+ }
+ did_noprobs = TRUE;
+}
+
+static int
+max(int i, int j)
+{
+ return (i >= j ? i : j);
+}
+
+/*
+ * open_fp:
+ * Assocatiate a FILE * with the given FILEDESC.
+ */
+static void
+open_fp(FILEDESC *fp)
+{
+ if (fp->inf == NULL && (fp->inf = fdopen(fp->fd, "r")) == NULL) {
+ perror(fp->path);
+ exit(1);
+ }
+}
+
+/*
+ * open_dat:
+ * Open up the dat file if we need to.
+ */
+static void
+open_dat(FILEDESC *fp)
+{
+ if (fp->datfd < 0 && (fp->datfd = open(fp->datfile, O_RDONLY)) < 0) {
+ perror(fp->datfile);
+ exit(1);
+ }
+}
+
+/*
+ * get_pos:
+ * Get the position from the pos file, if there is one. If not,
+ * return a random number.
+ */
+static void
+get_pos(FILEDESC *fp)
+{
+ int fd;
+
+ assert(fp->read_tbl);
+ if (fp->pos == POS_UNKNOWN) {
+ if (WriteToDisk) {
+ if ((fd = open(fp->posfile, O_RDONLY)) < 0 ||
+ read(fd, &fp->pos, sizeof fp->pos) != sizeof fp->pos)
+ fp->pos = arc4random_uniform(fp->tbl.str_numstr);
+ else if (fp->pos >= fp->tbl.str_numstr)
+ fp->pos %= fp->tbl.str_numstr;
+ if (fd >= 0)
+ close(fd);
+ }
+ else
+ fp->pos = arc4random_uniform(fp->tbl.str_numstr);
+ }
+ if (++(fp->pos) >= fp->tbl.str_numstr)
+ fp->pos -= fp->tbl.str_numstr;
+ DPRINTF(1, (stderr, "pos for %s is %ld\n", fp->name, (long)fp->pos));
+}
+
+/*
+ * get_tbl:
+ * Get the tbl data file the datfile.
+ */
+static void
+get_tbl(FILEDESC *fp)
+{
+ int fd;
+ FILEDESC *child;
+
+ if (fp->read_tbl)
+ return;
+ if (fp->child == NULL) {
+ if ((fd = open(fp->datfile, O_RDONLY)) < 0) {
+ perror(fp->datfile);
+ exit(1);
+ }
+ if (read(fd, (char *) &fp->tbl, sizeof fp->tbl) != sizeof fp->tbl) {
+ (void)fprintf(stderr,
+ "fortune: %s corrupted\n", fp->path);
+ exit(1);
+ }
+ /* fp->tbl.str_version = be32toh(fp->tbl.str_version); */
+ fp->tbl.str_numstr = be32toh(fp->tbl.str_numstr);
+ fp->tbl.str_longlen = be32toh(fp->tbl.str_longlen);
+ fp->tbl.str_shortlen = be32toh(fp->tbl.str_shortlen);
+ fp->tbl.str_flags = be32toh(fp->tbl.str_flags);
+ (void) close(fd);
+ }
+ else {
+ zero_tbl(&fp->tbl);
+ for (child = fp->child; child != NULL; child = child->next) {
+ get_tbl(child);
+ sum_tbl(&fp->tbl, &child->tbl);
+ }
+ }
+ fp->read_tbl = TRUE;
+}
+
+/*
+ * zero_tbl:
+ * Zero out the fields we care about in a tbl structure.
+ */
+static void
+zero_tbl(STRFILE *tp)
+{
+ tp->str_numstr = 0;
+ tp->str_longlen = 0;
+ tp->str_shortlen = ~0;
+}
+
+/*
+ * sum_tbl:
+ * Merge the tbl data of t2 into t1.
+ */
+static void
+sum_tbl(STRFILE *t1, STRFILE *t2)
+{
+ t1->str_numstr += t2->str_numstr;
+ if (t1->str_longlen < t2->str_longlen)
+ t1->str_longlen = t2->str_longlen;
+ if (t1->str_shortlen > t2->str_shortlen)
+ t1->str_shortlen = t2->str_shortlen;
+}
+
+#define STR(str) ((str) == NULL ? "NULL" : (str))
+
+/*
+ * print_file_list:
+ * Print out the file list
+ */
+static void
+print_file_list(void)
+{
+ print_list(File_list, 0);
+}
+
+/*
+ * print_list:
+ * Print out the actual list, recursively.
+ */
+static void
+print_list(FILEDESC *list, int lev)
+{
+ while (list != NULL) {
+ fprintf(stderr, "%*s", lev * 4, "");
+ if (list->percent == NO_PROB)
+ fprintf(stderr, "___%%");
+ else
+ fprintf(stderr, "%3d%%", list->percent);
+ fprintf(stderr, " %s", STR(list->name));
+ DPRINTF(1, (stderr, " (%s, %s, %s)", STR(list->path),
+ STR(list->datfile), STR(list->posfile)));
+ fprintf(stderr, "\n");
+ if (list->child != NULL)
+ print_list(list->child, lev + 1);
+ list = list->next;
+ }
+}
+
+/*
+ * conv_pat:
+ * Convert the pattern to an ignore-case equivalent.
+ */
+static char *
+conv_pat(char *orig)
+{
+ char *sp;
+ unsigned int cnt;
+ char *new;
+
+ cnt = 1; /* allow for '\0' */
+ for (sp = orig; *sp != '\0'; sp++)
+ if (isalpha((unsigned char)*sp))
+ cnt += 4;
+ else
+ cnt++;
+ if ((new = malloc(cnt)) == NULL) {
+ fprintf(stderr, "pattern too long for ignoring case\n");
+ exit(1);
+ }
+
+ for (sp = new; *orig != '\0'; orig++) {
+ if (islower((unsigned char)*orig)) {
+ *sp++ = '[';
+ *sp++ = *orig;
+ *sp++ = toupper((unsigned char)*orig);
+ *sp++ = ']';
+ }
+ else if (isupper((unsigned char)*orig)) {
+ *sp++ = '[';
+ *sp++ = *orig;
+ *sp++ = tolower((unsigned char)*orig);
+ *sp++ = ']';
+ }
+ else
+ *sp++ = *orig;
+ }
+ *sp = '\0';
+
+ return (new);
+}
+
+/*
+ * find_matches:
+ * Find all the fortunes which match the pattern we've been given.
+ */
+static int
+find_matches(void)
+{
+ Fort_len = maxlen_in_list(File_list);
+ DPRINTF(2, (stderr, "Maximum length is %d\n", Fort_len));
+ /* extra length, "%\n" is appended */
+ Fortbuf = do_malloc((unsigned int) Fort_len + 10);
+
+ Found_one = FALSE;
+ matches_in_list(File_list);
+
+ return (Found_one);
+}
+
+/*
+ * maxlen_in_list
+ * Return the maximum fortune len in the file list.
+ */
+static int
+maxlen_in_list(FILEDESC *list)
+{
+ FILEDESC *fp;
+ int len, maxlen;
+
+ maxlen = 0;
+ for (fp = list; fp != NULL; fp = fp->next) {
+ if (fp->child != NULL) {
+ if ((len = maxlen_in_list(fp->child)) > maxlen)
+ maxlen = len;
+ }
+ else {
+ get_tbl(fp);
+ if (fp->tbl.str_longlen > (unsigned int)maxlen)
+ maxlen = fp->tbl.str_longlen;
+ }
+ }
+
+ return (maxlen);
+}
+
+/*
+ * matches_in_list
+ * Print out the matches from the files in the list.
+ */
+static void
+matches_in_list(FILEDESC *list)
+{
+ char *sp, *p;
+ FILEDESC *fp;
+ int in_file;
+ unsigned char ch;
+
+ for (fp = list; fp != NULL; fp = fp->next) {
+ if (fp->child != NULL) {
+ matches_in_list(fp->child);
+ continue;
+ }
+ DPRINTF(1, (stderr, "searching in %s\n", fp->path));
+ open_fp(fp);
+ sp = Fortbuf;
+ in_file = FALSE;
+ while (fgets(sp, Fort_len, fp->inf) != NULL)
+ if (fp->tbl.str_flags & STR_COMMENTS
+ && sp[0] == fp->tbl.str_delim
+ && sp[1] == fp->tbl.str_delim)
+ continue;
+ else if (!STR_ENDSTRING(sp, fp->tbl))
+ sp += strlen(sp);
+ else {
+ *sp = '\0';
+ if (fp->tbl.str_flags & STR_ROTATED)
+ for (p = Fortbuf; (ch = *p) != '\0'; ++p) {
+ if (isascii(ch)) {
+ if (isupper(ch))
+ *p = 'A' + (ch - 'A' + 13) % 26;
+ else if (islower(ch))
+ *p = 'a' + (ch - 'a' + 13) % 26;
+ }
+ }
+ if (regexec(&Re_pat, Fortbuf, 0, NULL, 0) != REG_NOMATCH) {
+ printf("%c%c", fp->tbl.str_delim,
+ fp->tbl.str_delim);
+ if (!in_file) {
+ printf(" (%s)", fp->name);
+ Found_one = TRUE;
+ in_file = TRUE;
+ }
+ putchar('\n');
+ (void) fwrite(Fortbuf, 1, (sp - Fortbuf), stdout);
+ }
+ sp = Fortbuf;
+ }
+ }
+}
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr, "fortune [-a");
+#ifdef DEBUG
+ (void) fprintf(stderr, "D");
+#endif /* DEBUG */
+ (void) fprintf(stderr, "efilosw]");
+ (void) fprintf(stderr, " [-m pattern]");
+ (void) fprintf(stderr, " [[N%%] file/directory/all]\n");
+ exit(1);
+}
+
+/*
+ * getpath
+ * Set up file search path from environment var FORTUNE_PATH;
+ * if not set, use the compiled in FORTDIR.
+ */
+
+static void
+getpath(void)
+{
+ int nstr, foundenv;
+ char *pch, **ppch, *str, *path;
+
+ foundenv = 1;
+ Fortune_path = getenv("FORTUNE_PATH");
+ if (Fortune_path == NULL) {
+ Fortune_path = FORTDIR;
+ foundenv = 0;
+ }
+ path = strdup(Fortune_path);
+
+ for (nstr = 2, pch = path; *pch != '\0'; pch++) {
+ if (*pch == ':')
+ nstr++;
+ }
+
+ ppch = Fortune_path_arr = (char **)calloc(nstr, sizeof(char *));
+
+ nstr = 0;
+ str = strtok(path, ":");
+ while (str) {
+ if (is_dir(str)) {
+ nstr++;
+ *ppch++ = str;
+ }
+ str = strtok(NULL, ":");
+ }
+
+ if (nstr == 0) {
+ if (foundenv == 1) {
+ fprintf(stderr,
+ "fortune: FORTUNE_PATH: None of the specified "
+ "directories found.\n");
+ exit(1);
+ }
+ free(path);
+ Fortune_path_arr[0] = strdup(FORTDIR);
+ }
+}
diff --git a/usr.bin/fortune/fortune/pathnames.h b/usr.bin/fortune/fortune/pathnames.h
new file mode 100644
index 000000000000..4f6772b0667d
--- /dev/null
+++ b/usr.bin/fortune/fortune/pathnames.h
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 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.
+ */
+
+#include <paths.h>
+
+#define FORTDIR "/usr/share/games/fortune:" \
+ _PATH_LOCALBASE "/share/games/fortune"
diff --git a/usr.bin/fortune/strfile/Makefile b/usr.bin/fortune/strfile/Makefile
new file mode 100644
index 000000000000..8434ead23bd2
--- /dev/null
+++ b/usr.bin/fortune/strfile/Makefile
@@ -0,0 +1,5 @@
+PROG= strfile
+MAN= strfile.8
+MLINKS= strfile.8 unstr.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fortune/strfile/Makefile.depend b/usr.bin/fortune/strfile/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/fortune/strfile/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fortune/strfile/strfile.8 b/usr.bin/fortune/strfile/strfile.8
new file mode 100644
index 000000000000..9facbcd02331
--- /dev/null
+++ b/usr.bin/fortune/strfile/strfile.8
@@ -0,0 +1,156 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Ken Arnold.
+.\"
+.\" 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.
+.\"
+.Dd February 17, 2005
+.Dt STRFILE 8
+.Os
+.Sh NAME
+.Nm strfile ,
+.Nm unstr
+.Nd "create a random access file for storing strings"
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ciorsx
+.Op Fl c Ar char
+.Ar source_file
+.Op Ar output_file
+.Nm unstr
+.Ar source_file
+.Sh DESCRIPTION
+The
+.Nm
+utility
+reads a file containing groups of lines separated by a line containing
+a single percent
+.Ql %
+sign and creates a data file which contains
+a header structure and a table of file offsets for each group of lines.
+This allows random access of the strings.
+.Pp
+The output file, if not specified on the command line, is named
+.Ar source_file Ns Pa .dat .
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl c Ar char"
+.It Fl C
+Flag the file as containing comments.
+This option cases the
+.Dv STR_COMMENTS
+bit in the header
+.Va str_flags
+field to be set.
+Comments are designated by two delimiter characters at the
+beginning of the line, though
+.Nm
+does not give any special
+treatment to comment lines.
+.It Fl c Ar char
+Change the delimiting character from the percent sign to
+.Ar char .
+.It Fl i
+Ignore case when ordering the strings.
+.It Fl o
+Order the strings in alphabetical order.
+The offset table will be sorted in the alphabetical order of the
+groups of lines referenced.
+Any initial non-alphanumeric characters are ignored.
+This option causes the
+.Dv STR_ORDERED
+bit in the header
+.Va str_flags
+field to be set.
+.It Fl r
+Randomize access to the strings.
+Entries in the offset table will be randomly ordered.
+This option causes the
+.Dv STR_RANDOM
+bit in the header
+.Va str_flags
+field to be set.
+.It Fl s
+Run silently; do not give a summary message when finished.
+.It Fl x
+Note that each alphabetic character in the groups of lines is rotated
+13 positions in a simple caesar cypher.
+This option causes the
+.Dv STR_ROTATED
+bit in the header
+.Va str_flags
+field to be set.
+.El
+.Pp
+The format of the header is:
+.Bd -literal
+#define VERSION 1
+uint32_t str_version; /* version number */
+uint32_t str_numstr; /* # of strings in the file */
+uint32_t str_longlen; /* length of longest string */
+uint32_t str_shortlen; /* length of shortest string */
+#define STR_RANDOM 0x1 /* randomized pointers */
+#define STR_ORDERED 0x2 /* ordered pointers */
+#define STR_ROTATED 0x4 /* rot-13'd text */
+#define STR_COMMENTS 0x8 /* embedded comments */
+uint32_t str_flags; /* bit field for flags */
+char str_delim; /* delimiting character */
+.Ed
+.Pp
+All fields are written in network byte order.
+.Pp
+The purpose of
+.Nm unstr
+is to undo the work of
+.Nm .
+It prints out the strings contained in the file
+.Ar source_file
+in the order that they are listed in
+the header file
+.Ar source_file Ns Pa .dat
+to standard output.
+It is possible to create sorted versions of input files by using
+.Fl o
+when
+.Nm
+is run and then using
+.Nm unstr
+to dump them out in the table order.
+.Sh FILES
+.Bl -tag -width ".Pa strfile.dat" -compact
+.It Pa strfile.dat
+default output file.
+.El
+.Sh SEE ALSO
+.Xr byteorder 3 ,
+.Xr fortune 6
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.4 .
diff --git a/usr.bin/fortune/strfile/strfile.c b/usr.bin/fortune/strfile/strfile.c
new file mode 100644
index 000000000000..e389b621c638
--- /dev/null
+++ b/usr.bin/fortune/strfile/strfile.c
@@ -0,0 +1,450 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Arnold.
+ *
+ * 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>
+#include <sys/endian.h>
+#include <ctype.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "strfile.h"
+
+/*
+ * This program takes a file composed of strings separated by
+ * lines starting with two consecutive delimiting character (default
+ * character is '%') and creates another file which consists of a table
+ * describing the file (structure from "strfile.h"), a table of seek
+ * pointers to the start of the strings, and the strings, each terminated
+ * by a null byte. Usage:
+ *
+ * % strfile [-iorsx] [ -cC ] sourcefile [ datafile ]
+ *
+ * C - Allow comments marked by a double delimiter at line's beginning
+ * c - Change delimiting character from '%' to 'C'
+ * s - Silent. Give no summary of data processed at the end of
+ * the run.
+ * o - order the strings in alphabetic order
+ * i - if ordering, ignore case
+ * r - randomize the order of the strings
+ * x - set rotated bit
+ *
+ * Ken Arnold Sept. 7, 1978 --
+ *
+ * Added ordering options.
+ */
+
+#define STORING_PTRS (Oflag || Rflag)
+#define CHUNKSIZE 512
+
+#define ALLOC(ptr, sz) do { \
+ if (ptr == NULL) \
+ ptr = malloc(CHUNKSIZE * sizeof(*ptr)); \
+ else if (((sz) + 1) % CHUNKSIZE == 0) \
+ ptr = realloc(ptr, ((sz) + CHUNKSIZE) * sizeof(*ptr)); \
+ if (ptr == NULL) { \
+ fprintf(stderr, "out of space\n"); \
+ exit(1); \
+ } \
+ } while (0)
+
+typedef struct {
+ int first;
+ off_t pos;
+} STR;
+
+static char *Infile = NULL, /* input file name */
+ Outfile[MAXPATHLEN] = "", /* output file name */
+ Delimch = '%'; /* delimiting character */
+
+static int Cflag = false; /* embedded comments */
+static int Sflag = false; /* silent run flag */
+static int Oflag = false; /* ordering flag */
+static int Iflag = false; /* ignore case flag */
+static int Rflag = false; /* randomize order flag */
+static int Xflag = false; /* set rotated bit */
+static uint32_t Num_pts = 0; /* number of pointers/strings */
+
+static off_t *Seekpts;
+
+static FILE *Sort_1, *Sort_2; /* pointers for sorting */
+
+static STRFILE Tbl; /* statistics table */
+
+static STR *Firstch; /* first chars of each string */
+
+static void add_offset(FILE *, off_t);
+static int cmp_str(const void *, const void *);
+static int stable_collate_range_cmp(int, int);
+static void do_order(void);
+static void getargs(int, char **);
+static void randomize(void);
+static void usage(void) __dead2;
+
+/*
+ * main:
+ * Drive the sucker. There are two main modes -- either we store
+ * the seek pointers, if the table is to be sorted or randomized,
+ * or we write the pointer directly to the file, if we are to stay
+ * in file order. If the former, we allocate and re-allocate in
+ * CHUNKSIZE blocks; if the latter, we just write each pointer,
+ * and then seek back to the beginning to write in the table.
+ */
+int
+main(int ac, char *av[])
+{
+ char *sp, *nsp, dc;
+ FILE *inf, *outf;
+ off_t last_off, pos, *p;
+ size_t length;
+ int first;
+ uint32_t cnt;
+ STR *fp;
+ static char string[257];
+
+ setlocale(LC_ALL, "");
+
+ getargs(ac, av); /* evalute arguments */
+ dc = Delimch;
+ if ((inf = fopen(Infile, "r")) == NULL) {
+ perror(Infile);
+ exit(1);
+ }
+
+ if ((outf = fopen(Outfile, "w")) == NULL) {
+ perror(Outfile);
+ exit(1);
+ }
+ if (!STORING_PTRS)
+ fseek(outf, (long)sizeof(Tbl), SEEK_SET);
+
+ /*
+ * Write the strings onto the file
+ */
+
+ Tbl.str_longlen = 0;
+ Tbl.str_shortlen = 0xffffffff;
+ Tbl.str_delim = dc;
+ Tbl.str_version = VERSION;
+ first = Oflag;
+ add_offset(outf, ftello(inf));
+ last_off = 0;
+ do {
+ sp = fgets(string, 256, inf);
+ if (sp == NULL || (sp[0] == dc && sp[1] == '\n')) {
+ pos = ftello(inf);
+ length = (size_t)(pos - last_off) -
+ (sp != NULL ? strlen(sp) : 0);
+ last_off = pos;
+ if (length == 0)
+ continue;
+ add_offset(outf, pos);
+ if ((size_t)Tbl.str_longlen < length)
+ Tbl.str_longlen = length;
+ if ((size_t)Tbl.str_shortlen > length)
+ Tbl.str_shortlen = length;
+ first = Oflag;
+ }
+ else if (first) {
+ for (nsp = sp; !isalnum((unsigned char)*nsp); nsp++)
+ continue;
+ ALLOC(Firstch, Num_pts);
+ fp = &Firstch[Num_pts - 1];
+ if (Iflag && isupper((unsigned char)*nsp))
+ fp->first = tolower((unsigned char)*nsp);
+ else
+ fp->first = *nsp;
+ fp->pos = Seekpts[Num_pts - 1];
+ first = false;
+ }
+ } while (sp != NULL);
+
+ /*
+ * write the tables in
+ */
+
+ fclose(inf);
+ Tbl.str_numstr = Num_pts - 1;
+
+ if (Cflag)
+ Tbl.str_flags |= STR_COMMENTS;
+
+ if (Oflag)
+ do_order();
+ else if (Rflag)
+ randomize();
+
+ if (Xflag)
+ Tbl.str_flags |= STR_ROTATED;
+
+ if (!Sflag) {
+ printf("\"%s\" created\n", Outfile);
+ if (Num_pts == 2)
+ puts("There was 1 string");
+ else
+ printf("There were %u strings\n", Num_pts - 1);
+ printf("Longest string: %u byte%s\n", Tbl.str_longlen,
+ Tbl.str_longlen == 1 ? "" : "s");
+ printf("Shortest string: %u byte%s\n", Tbl.str_shortlen,
+ Tbl.str_shortlen == 1 ? "" : "s");
+ }
+
+ rewind(outf);
+ Tbl.str_version = htobe32(Tbl.str_version);
+ Tbl.str_numstr = htobe32(Tbl.str_numstr);
+ Tbl.str_longlen = htobe32(Tbl.str_longlen);
+ Tbl.str_shortlen = htobe32(Tbl.str_shortlen);
+ Tbl.str_flags = htobe32(Tbl.str_flags);
+ fwrite((char *)&Tbl, sizeof(Tbl), 1, outf);
+ if (STORING_PTRS) {
+ for (p = Seekpts, cnt = Num_pts; cnt--; ++p)
+ *p = htobe64(*p);
+ fwrite(Seekpts, sizeof(*Seekpts), (size_t)Num_pts, outf);
+ }
+ fclose(outf);
+ exit(0);
+}
+
+/*
+ * This routine evaluates arguments from the command line
+ */
+void
+getargs(int argc, char **argv)
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Cc:iorsx")) != -1)
+ switch(ch) {
+ case 'C': /* embedded comments */
+ Cflag++;
+ break;
+ case 'c': /* new delimiting char */
+ Delimch = *optarg;
+ if (!isascii(Delimch)) {
+ printf("bad delimiting character: '\\%o\n'",
+ (unsigned char)Delimch);
+ }
+ break;
+ case 'i': /* ignore case in ordering */
+ Iflag++;
+ break;
+ case 'o': /* order strings */
+ Oflag++;
+ break;
+ case 'r': /* randomize pointers */
+ Rflag++;
+ break;
+ case 's': /* silent */
+ Sflag++;
+ break;
+ case 'x': /* set the rotated bit */
+ Xflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+
+ if (*argv) {
+ Infile = *argv;
+ if (*++argv) {
+ if (strlcpy(Outfile, *argv, sizeof(Outfile)) >=
+ sizeof(Outfile)) {
+ fprintf(stderr,
+ "output_file path is too long\n");
+ exit(1);
+ }
+ }
+ }
+ if (!Infile) {
+ puts("No input file name");
+ usage();
+ }
+ if (*Outfile == '\0') {
+ if ((size_t)snprintf(Outfile, sizeof(Outfile), "%s.dat",
+ Infile) >= sizeof(Outfile)) {
+ fprintf(stderr,
+ "generated output_file path is too long\n");
+ exit(1);
+ }
+ }
+}
+
+void
+usage(void)
+{
+ fprintf(stderr,
+ "strfile [-Ciorsx] [-c char] source_file [output_file]\n");
+ exit(1);
+}
+
+/*
+ * add_offset:
+ * Add an offset to the list, or write it out, as appropriate.
+ */
+void
+add_offset(FILE *fp, off_t off)
+{
+ off_t beoff;
+
+ if (!STORING_PTRS) {
+ beoff = htobe64(off);
+ fwrite(&beoff, 1, sizeof(beoff), fp);
+ } else {
+ ALLOC(Seekpts, Num_pts + 1);
+ Seekpts[Num_pts] = off;
+ }
+ Num_pts++;
+}
+
+/*
+ * do_order:
+ * Order the strings alphabetically (possibly ignoring case).
+ */
+void
+do_order(void)
+{
+ uint32_t i;
+ off_t *lp;
+ STR *fp;
+
+ Sort_1 = fopen(Infile, "r");
+ Sort_2 = fopen(Infile, "r");
+ qsort(Firstch, (size_t)Tbl.str_numstr, sizeof(*Firstch), cmp_str);
+ i = Tbl.str_numstr;
+ lp = Seekpts;
+ fp = Firstch;
+ while (i--)
+ *lp++ = fp++->pos;
+ fclose(Sort_1);
+ fclose(Sort_2);
+ Tbl.str_flags |= STR_ORDERED;
+}
+
+static int
+stable_collate_range_cmp(int c1, int c2)
+{
+ static char s1[2], s2[2];
+ int ret;
+
+ s1[0] = c1;
+ s2[0] = c2;
+ if ((ret = strcoll(s1, s2)) != 0)
+ return (ret);
+ return (c1 - c2);
+}
+
+/*
+ * cmp_str:
+ * Compare two strings in the file
+ */
+int
+cmp_str(const void *s1, const void *s2)
+{
+ const STR *p1, *p2;
+ int c1, c2, n1, n2, r;
+
+#define SET_N(nf,ch) (nf = (ch == '\n'))
+#define IS_END(ch,nf) (ch == EOF || (ch == (unsigned char)Delimch && nf))
+
+ p1 = (const STR *)s1;
+ p2 = (const STR *)s2;
+
+ c1 = (unsigned char)p1->first;
+ c2 = (unsigned char)p2->first;
+ if ((r = stable_collate_range_cmp(c1, c2)) != 0)
+ return (r);
+
+ fseeko(Sort_1, p1->pos, SEEK_SET);
+ fseeko(Sort_2, p2->pos, SEEK_SET);
+
+ n1 = false;
+ n2 = false;
+ while (!isalnum(c1 = getc(Sort_1)) && c1 != '\0' && c1 != EOF)
+ SET_N(n1, c1);
+ while (!isalnum(c2 = getc(Sort_2)) && c2 != '\0' && c2 != EOF)
+ SET_N(n2, c2);
+
+ while (!IS_END(c1, n1) && !IS_END(c2, n2)) {
+ if (Iflag) {
+ if (isupper(c1))
+ c1 = tolower(c1);
+ if (isupper(c2))
+ c2 = tolower(c2);
+ }
+ if ((r = stable_collate_range_cmp(c1, c2)) != 0)
+ return (r);
+ SET_N(n1, c1);
+ SET_N(n2, c2);
+ c1 = getc(Sort_1);
+ c2 = getc(Sort_2);
+ }
+ if (IS_END(c1, n1))
+ c1 = 0;
+ if (IS_END(c2, n2))
+ c2 = 0;
+
+ return (stable_collate_range_cmp(c1, c2));
+}
+
+/*
+ * randomize:
+ * Randomize the order of the string table. We must be careful
+ * not to randomize across delimiter boundaries. All
+ * randomization is done within each block.
+ */
+void
+randomize(void)
+{
+ uint32_t cnt, i;
+ off_t tmp;
+ off_t *sp;
+
+ Tbl.str_flags |= STR_RANDOM;
+ cnt = Tbl.str_numstr;
+
+ /*
+ * move things around randomly
+ */
+
+ for (sp = Seekpts; cnt > 0; cnt--, sp++) {
+ i = arc4random_uniform(cnt);
+ tmp = sp[0];
+ sp[0] = sp[i];
+ sp[i] = tmp;
+ }
+}
diff --git a/usr.bin/fortune/strfile/strfile.h b/usr.bin/fortune/strfile/strfile.h
new file mode 100644
index 000000000000..f81c366b602b
--- /dev/null
+++ b/usr.bin/fortune/strfile/strfile.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Arnold.
+ *
+ * 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>
+
+#define STR_ENDSTRING(line,tbl) \
+ (((unsigned char)(line)[0]) == (tbl).str_delim && (line)[1] == '\n')
+
+typedef struct { /* information table */
+#define VERSION 1
+ uint32_t str_version; /* version number */
+ uint32_t str_numstr; /* # of strings in the file */
+ uint32_t str_longlen; /* length of longest string */
+ uint32_t str_shortlen; /* length of shortest string */
+#define STR_RANDOM 0x1 /* randomized pointers */
+#define STR_ORDERED 0x2 /* ordered pointers */
+#define STR_ROTATED 0x4 /* rot-13'd text */
+#define STR_COMMENTS 0x8 /* embedded comments */
+ uint32_t str_flags; /* bit field for flags */
+ unsigned char stuff[4]; /* 64-bit aligned space */
+#define str_delim stuff[0] /* delimiting character */
+} STRFILE;
diff --git a/usr.bin/fortune/tools/Do_spell b/usr.bin/fortune/tools/Do_spell
new file mode 100644
index 000000000000..2c232ac0f263
--- /dev/null
+++ b/usr.bin/fortune/tools/Do_spell
@@ -0,0 +1,7 @@
+#!/bin/sh -
+
+F=_spell.$$
+echo $1
+spell < $1 > $F
+sort $F $1.sp.ok | uniq -u | column
+rm -f $F
diff --git a/usr.bin/fortune/tools/Do_troff b/usr.bin/fortune/tools/Do_troff
new file mode 100644
index 000000000000..7dd2ec3a6f83
--- /dev/null
+++ b/usr.bin/fortune/tools/Do_troff
@@ -0,0 +1,7 @@
+#!/bin/csh -f
+
+set file=$1
+shift
+( echo ".ds Se $file" ; cat Troff.mac ; sed -f Troff.sed $file ) | \
+ $* -me >& $file.tr
+echo troff output in $file.tr
diff --git a/usr.bin/fortune/tools/Troff.mac b/usr.bin/fortune/tools/Troff.mac
new file mode 100644
index 000000000000..c2b433e1b213
--- /dev/null
+++ b/usr.bin/fortune/tools/Troff.mac
@@ -0,0 +1,26 @@
+.nr tp 8
+.nr hm 3v
+.nr fm 2v
+.nr tm 5v
+.nr bm 4v
+.cs R
+.sc
+.sz 6
+.ll +10n
+.lt \n(.l
+.de $h
+.tl 'Fortune Database'\\*(Se'\*(td'
+..
+.de $f
+.tl ''- % -''
+..
+.2c
+.nf
+.ta
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n 80n
+.de %%
+.sp .3
+.ce
+\(sq\|\(sq\|\(sq\|\(sq\|\(sq\|\(sq\|\(sq\|\(sq\|\(sq
+.sp .2
+..
diff --git a/usr.bin/fortune/tools/Troff.sed b/usr.bin/fortune/tools/Troff.sed
new file mode 100644
index 000000000000..321668123ad9
--- /dev/null
+++ b/usr.bin/fortune/tools/Troff.sed
@@ -0,0 +1,13 @@
+/^['.]/s//\\\&&/
+/^%%/s//.&/
+/--/s//\\*-/g
+/_a-squared cos 2(phi)/s//\\fIa\\fP\\u2\\d cos 2\\(*f/
+/__**\([a-zA-Z]*\)/s//\\fI\1\\fP/g
+/"\(.\)/s//\1\\*:/g
+/`\(.\)/s//\1\\*`/g
+/'\(.\)/s//\1\\*'/g
+/~\(.\)/s//\1\\*~/g
+/\^\(.\)/s//\1\\*^/g
+/,\(.\)/s//\1\\*,/g
+/\(.\)\(.\)/s//\\o_\1\2_/g
+/*/s//\\(bs/g
diff --git a/usr.bin/fortune/tools/do_sort b/usr.bin/fortune/tools/do_sort
new file mode 100644
index 000000000000..a92d02755ecb
--- /dev/null
+++ b/usr.bin/fortune/tools/do_sort
@@ -0,0 +1,9 @@
+#! /bin/sh
+# an aggressive little script for sorting the fortune files
+# depends on octal 02 and 03 not being anywhere in the files.
+
+sp="/usr/bin/sort -dfu -T /var/tmp"
+
+sed 's/^%$//' | tr '\12' '\3' | tr '\2' '\12' |
+ sed -e 's/^//' -e '/^$/d' -e 's/$/%/' |
+ $sp | tr '\3' '\12'
diff --git a/usr.bin/fortune/tools/do_uniq.py b/usr.bin/fortune/tools/do_uniq.py
new file mode 100644
index 000000000000..092d91bd0480
--- /dev/null
+++ b/usr.bin/fortune/tools/do_uniq.py
@@ -0,0 +1,67 @@
+#!/usr/local/bin/python
+#
+#
+# an aggressive little script for trimming duplicate cookies
+from __future__ import print_function
+import argparse
+import re
+
+wordlist = [
+ 'hadnot',
+ 'donot', 'hadnt',
+ 'dont', 'have', 'more', 'will', 'your',
+ 'and', 'are', 'had', 'the', 'you',
+ 'am', 'an', 'is', 'll', 've', 'we',
+ 'a', 'd', 'i', 'm', 's',
+]
+
+
+def hash(fortune):
+ f = fortune
+ f = f.lower()
+ f = re.sub('[\W_]', '', f)
+ for word in wordlist:
+ f = re.sub(word, '', f)
+# f = re.sub('[aeiouy]', '', f)
+# f = re.sub('[^aeiouy]', '', f)
+ f = f[:30]
+# f = f[-30:]
+ return f
+
+
+def edit(datfile):
+ dups = {}
+ fortunes = []
+ fortune = ""
+ with open(datfile, "r") as datfiledf:
+ for line in datfiledf:
+ if line == "%\n":
+ key = hash(fortune)
+ if key not in dups:
+ dups[key] = []
+ dups[key].append(fortune)
+ fortunes.append(fortune)
+ fortune = ""
+ else:
+ fortune += line
+ for key in list(dups.keys()):
+ if len(dups[key]) == 1:
+ del dups[key]
+ with open(datfile + "~", "w") as o:
+ for fortune in fortunes:
+ key = hash(fortune)
+ if key in dups:
+ print('\n' * 50)
+ for f in dups[key]:
+ if f != fortune:
+ print(f, '%')
+ print(fortune, '%')
+ if input("Remove last fortune? ") == 'y':
+ del dups[key]
+ continue
+ o.write(fortune + "%\n")
+
+parser = argparse.ArgumentParser(description="trimming duplicate cookies")
+parser.add_argument("filename", type=str, nargs=1)
+args = parser.parse_args()
+edit(args.filename[0])
diff --git a/usr.bin/fortune/unstr/Makefile b/usr.bin/fortune/unstr/Makefile
new file mode 100644
index 000000000000..ed1f1b7790a7
--- /dev/null
+++ b/usr.bin/fortune/unstr/Makefile
@@ -0,0 +1,5 @@
+PROG= unstr
+MAN=
+CFLAGS+= -I${FORTUNE_SRC}/strfile
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fortune/unstr/Makefile.depend b/usr.bin/fortune/unstr/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/fortune/unstr/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fortune/unstr/unstr.c b/usr.bin/fortune/unstr/unstr.c
new file mode 100644
index 000000000000..7cf7e1321cd7
--- /dev/null
+++ b/usr.bin/fortune/unstr/unstr.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ken Arnold.
+ *
+ * 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 un-does what "strfile" makes, thereby obtaining the
+ * original file again. This can be invoked with the name of the output
+ * file, the input file, or both. If invoked with only a single argument
+ * ending in ".dat", it is pressumed to be the input file and the output
+ * file will be the same stripped of the ".dat". If the single argument
+ * doesn't end in ".dat", then it is presumed to be the output file, and
+ * the input file is that name prepended by a ".dat". If both are given
+ * they are treated literally as the input and output files.
+ *
+ * Ken Arnold Aug 13, 1978
+ */
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "strfile.h"
+
+static char *Infile, /* name of input file */
+ Datafile[MAXPATHLEN], /* name of data file */
+ Delimch; /* delimiter character */
+
+static FILE *Inf, *Dataf;
+
+static void order_unstr(STRFILE *);
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ static STRFILE tbl; /* description table */
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: unstr datafile\n");
+ exit(1);
+ }
+ Infile = argv[1];
+ if ((size_t)snprintf(Datafile, sizeof(Datafile), "%s.dat", Infile) >=
+ sizeof(Datafile))
+ errx(1, "%s name too long", Infile);
+ if ((Inf = fopen(Infile, "r")) == NULL)
+ err(1, "%s", Infile);
+ if ((Dataf = fopen(Datafile, "r")) == NULL)
+ err(1, "%s", Datafile);
+ if (fread((char *)&tbl, sizeof(tbl), 1, Dataf) != 1) {
+ if (feof(Dataf))
+ errx(1, "%s read EOF", Datafile);
+ else
+ err(1, "%s read", Datafile);
+ }
+ tbl.str_version = be32toh(tbl.str_version);
+ tbl.str_numstr = be32toh(tbl.str_numstr);
+ tbl.str_longlen = be32toh(tbl.str_longlen);
+ tbl.str_shortlen = be32toh(tbl.str_shortlen);
+ tbl.str_flags = be32toh(tbl.str_flags);
+ if (!(tbl.str_flags & (STR_ORDERED | STR_RANDOM)))
+ errx(1, "nothing to do -- table in file order");
+ Delimch = tbl.str_delim;
+ order_unstr(&tbl);
+ fclose(Inf);
+ fclose(Dataf);
+ exit(0);
+}
+
+static void
+order_unstr(STRFILE *tbl)
+{
+ uint32_t i;
+ char *sp;
+ off_t pos;
+ char buf[BUFSIZ];
+
+ for (i = 0; i < tbl->str_numstr; i++) {
+ fread(&pos, 1, sizeof(pos), Dataf);
+ fseeko(Inf, be64toh(pos), SEEK_SET);
+ if (i != 0)
+ printf("%c\n", Delimch);
+ for (;;) {
+ sp = fgets(buf, sizeof(buf), Inf);
+ if (sp == NULL || STR_ENDSTRING(sp, *tbl))
+ break;
+ else
+ fputs(sp, stdout);
+ }
+ }
+}
diff --git a/usr.bin/from/Makefile b/usr.bin/from/Makefile
new file mode 100644
index 000000000000..c27be3f50a25
--- /dev/null
+++ b/usr.bin/from/Makefile
@@ -0,0 +1,3 @@
+PROG= from
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/from/Makefile.depend b/usr.bin/from/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/from/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/from/from.1 b/usr.bin/from/from.1
new file mode 100644
index 000000000000..c78c4253f99c
--- /dev/null
+++ b/usr.bin/from/from.1
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd December 30, 1993
+.Dt FROM 1
+.Os
+.Sh NAME
+.Nm from
+.Nd print names of those who have sent mail
+.Sh SYNOPSIS
+.Nm
+.Op Fl c
+.Op Fl f Ar file
+.Op Fl s Ar sender
+.Op Ar user
+.Sh DESCRIPTION
+The
+.Nm
+utility prints
+out the mail header lines from the invoker's mailbox.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Just print a count of messages and exit.
+.It Fl f Ar file
+The supplied
+.Ar file
+is examined instead of the invoker's mailbox.
+If the
+.Fl f
+option is used, the
+.Ar user
+argument should not be used.
+Read from standard input if file name
+.Dq Fl
+is given.
+.It Fl s Ar sender
+Only mail from addresses containing
+the
+supplied string are printed.
+.El
+.Pp
+If
+.Ar user
+is given, the
+.Ar user Ns 's
+mailbox is examined instead of the invoker's own mailbox.
+(Privileges are required.)
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It Ev MAIL
+If set, the location of the invoker's mailbox.
+Otherwise, the default in
+.Pa /var/mail
+is used.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /var/mail/*" -compact
+.It Pa /var/mail/*
+.El
+.Sh SEE ALSO
+.Xr biff 1 ,
+.Xr mail 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/from/from.c b/usr.bin/from/from.c
new file mode 100644
index 000000000000..031803ebae16
--- /dev/null
+++ b/usr.bin/from/from.c
@@ -0,0 +1,155 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1988, 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.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+
+static int match(const char *, const char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ FILE *mbox;
+ struct passwd *pwd;
+ int ch, count, newline;
+ const char *file;
+ char *sender, *p;
+#if MAXPATHLEN > BUFSIZ
+ char buf[MAXPATHLEN];
+#else
+ char buf[BUFSIZ];
+#endif
+
+ file = sender = NULL;
+ count = -1;
+ while ((ch = getopt(argc, argv, "cf:s:")) != -1)
+ switch (ch) {
+ case 'c':
+ count = 0;
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ case 's':
+ sender = optarg;
+ for (p = sender; *p; ++p)
+ *p = tolower(*p);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (file == NULL) {
+ if (argc) {
+ (void)snprintf(buf, sizeof(buf), "%s/%s", _PATH_MAILDIR, *argv);
+ file = buf;
+ } else {
+ if (!(file = getenv("MAIL"))) {
+ if (!(pwd = getpwuid(getuid())))
+ errx(1, "no password file entry for you");
+ file = pwd->pw_name;
+ (void)snprintf(buf, sizeof(buf),
+ "%s/%s", _PATH_MAILDIR, file);
+ file = buf;
+ }
+ }
+ }
+
+ /* read from stdin */
+ if (strcmp(file, "-") == 0) {
+ mbox = stdin;
+ }
+ else if ((mbox = fopen(file, "r")) == NULL) {
+ errx(1, "can't read %s", file);
+ }
+ for (newline = 1; fgets(buf, sizeof(buf), mbox);) {
+ if (*buf == '\n') {
+ newline = 1;
+ continue;
+ }
+ if (newline && !strncmp(buf, "From ", 5) &&
+ (!sender || match(buf + 5, sender))) {
+ if (count != -1)
+ count++;
+ else
+ printf("%s", buf);
+ }
+ newline = 0;
+ }
+ if (count != -1)
+ printf("There %s %d message%s in your incoming mailbox.\n",
+ count == 1 ? "is" : "are", count, count == 1 ? "" : "s");
+ fclose(mbox);
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: from [-c] [-f file] [-s sender] [user]\n");
+ exit(1);
+}
+
+static int
+match(const char *line, const char *sender)
+{
+ char ch, pch, first;
+ const char *p, *t;
+
+ for (first = *sender++;;) {
+ if (isspace(ch = *line))
+ return(0);
+ ++line;
+ ch = tolower(ch);
+ if (ch != first)
+ continue;
+ for (p = sender, t = line;;) {
+ if (!(pch = *p++))
+ return(1);
+ ch = tolower(*t);
+ t++;
+ if (ch != pch)
+ break;
+ }
+ }
+ /* NOTREACHED */
+}
diff --git a/usr.bin/fstat/Makefile b/usr.bin/fstat/Makefile
new file mode 100644
index 000000000000..fa51a92eb52f
--- /dev/null
+++ b/usr.bin/fstat/Makefile
@@ -0,0 +1,8 @@
+PROG= fstat
+SRCS= fstat.c fuser.c main.c
+LINKS= ${BINDIR}/fstat ${BINDIR}/fuser
+LIBADD= procstat
+
+MAN1= fuser.1 fstat.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fstat/Makefile.depend b/usr.bin/fstat/Makefile.depend
new file mode 100644
index 000000000000..0d33593a8e05
--- /dev/null
+++ b/usr.bin/fstat/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libprocstat \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fstat/fstat.1 b/usr.bin/fstat/fstat.1
new file mode 100644
index 000000000000..4d6e32438a04
--- /dev/null
+++ b/usr.bin/fstat/fstat.1
@@ -0,0 +1,344 @@
+.\" Copyright (c) 1987, 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.
+.\"
+.Dd November 19, 2020
+.Dt FSTAT 1
+.Os
+.Sh NAME
+.Nm fstat
+.Nd identify active files
+.Sh SYNOPSIS
+.Nm
+.Op Fl fmnsv
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl p Ar pid
+.Op Fl u Ar user
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility identifies open files.
+A file is considered open by a process if it was explicitly opened,
+is the working directory, root directory, jail root directory,
+active executable text, or kernel trace file for that process.
+If no options are specified,
+.Nm
+reports on all open files in the system for processes the user has access to.
+.Pp
+The following options are available:
+.Bl -tag -width "-N system"
+.It Fl f
+Restrict examination to files open in the same file systems as
+the named file arguments, or to the file system containing the
+current directory if there are no additional filename arguments.
+For example, to find all files open in the file system where the
+directory
+.Pa /usr/src
+resides, type
+.Ql fstat -f /usr/src .
+.It Fl M Ar core
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl m
+Include memory-mapped files in the listing; normally these are excluded
+due to the extra processing required.
+.It Fl N Ar system
+Extract the name list from the specified system instead of the default,
+which is the kernel image the system has booted from.
+.It Fl n
+Numerical format.
+Print the device number (maj,min) of the file system
+the file resides in rather than the mount point name; for special
+files, print the
+device number that the special device refers to rather than the filename
+in
+.Pa /dev ;
+and print the mode of the file in octal instead of symbolic form.
+.It Fl p Ar pid
+Report all files open by the specified process.
+.It Fl s
+Print socket endpoint information.
+.It Fl u Ar user
+Report all files open by the specified user.
+.It Fl v
+Verbose mode.
+Print error messages upon failures to locate particular
+system data structures rather than silently ignoring them.
+Most of
+these data structures are dynamically created or deleted and it is
+possible for them to disappear while
+.Nm
+is running.
+This
+is normal and unavoidable since the rest of the system is running while
+.Nm
+itself is running.
+.It Ar
+Restrict reports to the specified files.
+.El
+.Pp
+The following fields are printed:
+.Bl -tag -width MOUNT
+.It Sy USER
+The username of the owner of the process (effective uid).
+.It Sy CMD
+The command name of the process.
+.It Sy PID
+The process id.
+.It Sy FD
+The file number in the per-process open file table or one of the following
+special names:
+.Pp
+.Bl -tag -width jail -offset indent -compact
+.It Sy jail
+jail root directory
+.It Sy mmap
+memory-mapped file
+.It Sy root
+root inode
+.It Sy text
+executable text inode
+.It Sy tr
+kernel trace file
+.It Sy wd
+current working directory
+.El
+.Pp
+If the file number is followed by an asterisk
+.Pq Ql * ,
+the file is
+not an inode, but rather a socket, FIFO, or there is an error.
+In this case the remainder of the line does not
+correspond to the remaining headers\(em the format of the line
+is described later under
+.Sx SOCKETS .
+.It Sy MOUNT
+If the
+.Fl n
+flag was not specified, this header is present and is the
+pathname that the file system the file resides in is mounted on.
+.It Sy DEV
+If the
+.Fl n
+flag is specified, this header is present and is the
+number of the device that this file resides in.
+.It Sy INUM
+The inode number of the file.
+.It Sy MODE
+The mode of the file.
+If the
+.Fl n
+flag is not specified, the mode is printed
+using a symbolic format (see
+.Xr strmode 3 ) ;
+otherwise, the mode is printed
+as an octal number.
+.It Sy SZ\&|DV
+If the file is a semaphore,
+prints the current value of the semaphore.
+If the file is not a character or block special, prints the size of
+the file in bytes.
+Otherwise, if the
+.Fl n
+flag is not specified, prints
+the name of the special file as located in
+.Pa /dev .
+If that cannot be
+located, or the
+.Fl n
+flag is specified, prints the major/minor device
+number that the special device refers to.
+.It Sy R/W
+This column describes the access mode that the file allows.
+The letter
+.Ql r
+indicates open for reading;
+the letter
+.Ql w
+indicates open for writing.
+This field is useful when trying to find the processes that are
+preventing a file system from being down graded to read-only.
+.It Sy NAME
+If filename arguments are specified and the
+.Fl f
+flag is not, then
+this field is present and is the name associated with the given file.
+Normally the name cannot be determined since there is no mapping
+from an open file back to the directory entry that was used to open
+that file.
+Also, since different directory entries may reference
+the same file (via
+.Xr ln 1 ) ,
+the name printed may not be the actual
+name that the process originally used to open that file.
+.El
+.Sh SOCKETS
+The formatting of open sockets depends on the protocol domain.
+In all cases the first field is the domain name, the second field
+is the socket type (stream, dgram, etc.), and the third is the socket
+flags field (in hex).
+The remaining fields are protocol dependent.
+For TCP, it is the address of the tcpcb, and for UDP, the inpcb (socket pcb).
+For UNIX-domain sockets, its the address of the socket pcb and the address
+of the connected pcb (if connected).
+Otherwise the protocol number and address of the socket itself are printed.
+.Pp
+For example, the addresses mentioned above are the addresses which the
+.Ql netstat -A
+command would print for TCP, UDP, and UNIX-domain.
+Note that since pipes are implemented using sockets, a pipe appears as a
+connected UNIX-domain stream socket.
+A unidirectional UNIX-domain socket indicates the direction of flow with
+an arrow
+.Po Ql <-
+or
+.Ql ->
+.Pc ,
+and a full duplex socket shows a double arrow
+.Pq Ql <-> .
+.Pp
+When the
+.Fl s
+flag is used, socket endpoint information is shown after the address of the
+socket.
+For internet sockets the local and remote addresses are shown, separated with
+a double arrow
+.Pq Ql <-> .
+For UNIX/local sockets either the local or remote address is shown, depending
+on which one is available.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show all open files except those opened by
+.Nm
+itself:
+.Bd -literal -offset indent
+$ fstat | awk '$2 != "fstat"'
+USER CMD PID FD MOUNT INUM MODE SZ|DV R/W
+alice bash 469 text /usr/local 143355 -rwxr-xr-x 1166448 r
+alice bash 469 ctty /dev 346 crw--w---- pts/81 rw
+\&...
+.Ed
+.Pp
+Report all files opened by the current shell in the same file system as
+.Pa /usr/local
+including memory-mapped files:
+.Bd -literal -offset indent
+$ fstat -m -p $$ -f /usr/local
+USER CMD PID FD MOUNT INUM MODE SZ|DV R/W
+bob bash 469 text /usr/local 143355 -rwxr-xr-x 1166448 r
+bob bash 469 mmap /usr/local 143355 -rwxr-xr-x 1166448 r
+\&...
+.Ed
+.Pp
+Requesting information about a file that is not opened results in just a
+header line instead of an error:
+.Bd -literal -offset indent
+$ fstat /etc/rc.conf
+USER CMD PID FD MOUNT INUM MODE SZ|DV R/W NAME
+.Ed
+.Pp
+All parameters after
+.Fl f
+will be interpreted as files, so the following will not work as expected:
+.Bd -literal -offset indent
+$ fstat -f /usr/local -m -p $$
+fstat: -m: No such file or directory
+fstat: -p: No such file or directory
+fstat: 469: No such file or directory
+\&...
+.Ed
+.Pp
+Show number of pipes opened by firefox processes:
+.Bd -literal -offset indent
+$ fstat | awk '$2=="firefox" && $5=="pipe"' | wc -l
+.Ed
+.Pp
+Show processes belonging to user
+.Dq bob
+whose standard error descriptor is opened in ttyv0:
+.Bd -literal -offset indent
+$ fstat -u bob | awk '$4 == 2 && $8 == "ttyv0"'
+bob firefox 77842 2 /dev 103 crw------- ttyv0 rw
+bob xinit 1194 2 /dev 103 crw------- ttyv0 rw
+\&...
+.Ed
+.Pp
+Show opened TCP sockets.
+This output resembles the one produced by
+.Ql netstat -A -p tcp
+:
+.Bd -literal -offset indent
+$ fstat | awk '$7 == "tcp"'
+alice firefox 77991 32* internet stream tcp fffff800b7f147a0
+alice firefox 77991 137* internet stream tcp fffff800b7f12b70
+\&...
+.Ed
+.Pp
+Show a list of processes with files opened in the current directory
+mimicking the output of
+.Xr fuser 1
+:
+.Bd -literal -offset indent
+$ fstat . | awk 'NR > 1 {printf "%d%s(%s) ", $3, $4, $1;}'
+2133wd(alice) 2132wd(alice) 1991wd(alice)
+.Ed
+.Pp
+Create a list of processes sorted by number of opened files in descending order:
+.Bd -literal -offset indent
+$ fstat | awk 'NR > 1 {print $2;}' | sort | uniq -c | sort -r
+ 728 firefox
+ 23 bash
+ 14 sort
+ 8 fstat
+ 7 awk
+.Ed
+.Sh SEE ALSO
+.Xr fuser 1 ,
+.Xr netstat 1 ,
+.Xr nfsstat 1 ,
+.Xr procstat 1 ,
+.Xr ps 1 ,
+.Xr sockstat 1 ,
+.Xr systat 1 ,
+.Xr tcp 4 ,
+.Xr unix 4 ,
+.Xr iostat 8 ,
+.Xr pstat 8 ,
+.Xr vmstat 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 tahoe .
+.Sh BUGS
+Since
+.Nm
+takes a snapshot of the system, it is only correct for a very short period
+of time.
diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c
new file mode 100644
index 000000000000..e5d0755062d0
--- /dev/null
+++ b/usr.bin/fstat/fstat.c
@@ -0,0 +1,643 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#include "functions.h"
+
+static int fsflg, /* show files on same filesystem as file(s) argument */
+ pflg, /* show files open by a particular pid */
+ sflg, /* show socket details */
+ uflg; /* show files open by a particular (effective) user */
+static int checkfile; /* restrict to particular files or filesystems */
+static int nflg; /* (numerical) display f.s. and rdev as dev_t */
+static int mflg; /* include memory-mapped files */
+static int vflg; /* be verbose */
+
+typedef struct devs {
+ struct devs *next;
+ uint64_t fsid;
+ uint64_t ino;
+ const char *name;
+} DEVS;
+
+static DEVS *devs;
+static char *memf, *nlistf;
+
+static int getfname(const char *filename);
+static void dofiles(struct procstat *procstat, struct kinfo_proc *p);
+static void print_access_flags(int flags);
+static void print_file_info(struct procstat *procstat,
+ struct filestat *fst, const char *uname, const char *cmd, int pid);
+static void print_pipe_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_pts_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_sem_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_shm_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_socket_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_vnode_info(struct procstat *procstat,
+ struct filestat *fst);
+static void usage(void) __dead2;
+
+int
+do_fstat(int argc, char **argv)
+{
+ struct kinfo_proc *p;
+ struct passwd *passwd;
+ struct procstat *procstat;
+ int arg, ch, what;
+ int cnt, i;
+
+ arg = 0;
+ what = KERN_PROC_PROC;
+ nlistf = memf = NULL;
+ while ((ch = getopt(argc, argv, "fmnp:su:vN:M:")) != -1)
+ switch((char)ch) {
+ case 'f':
+ fsflg = 1;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'm':
+ mflg = 1;
+ break;
+ case 'n':
+ nflg = 1;
+ break;
+ case 'p':
+ if (pflg++)
+ usage();
+ if (!isdigit(*optarg)) {
+ warnx("-p requires a process id");
+ usage();
+ }
+ what = KERN_PROC_PID;
+ arg = atoi(optarg);
+ break;
+ case 's':
+ sflg = 1;
+ break;
+ case 'u':
+ if (uflg++)
+ usage();
+ if (!(passwd = getpwnam(optarg)))
+ errx(1, "%s: unknown uid", optarg);
+ what = KERN_PROC_UID;
+ arg = passwd->pw_uid;
+ break;
+ case 'v':
+ vflg = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (*(argv += optind)) {
+ for (; *argv; ++argv) {
+ if (getfname(*argv))
+ checkfile = 1;
+ }
+ if (!checkfile) /* file(s) specified, but none accessible */
+ exit(1);
+ }
+
+ if (fsflg && !checkfile) {
+ /* -f with no files means use wd */
+ if (getfname(".") == 0)
+ exit(1);
+ checkfile = 1;
+ }
+
+ if (memf != NULL)
+ procstat = procstat_open_kvm(nlistf, memf);
+ else
+ procstat = procstat_open_sysctl();
+ if (procstat == NULL)
+ errx(1, "procstat_open()");
+ p = procstat_getprocs(procstat, what, arg, &cnt);
+ if (p == NULL)
+ errx(1, "procstat_getprocs()");
+
+ /*
+ * Print header.
+ */
+ if (nflg)
+ printf("%s",
+"USER CMD PID FD DEV INUM MODE SZ|DV R/W");
+ else
+ printf("%s",
+"USER CMD PID FD MOUNT INUM MODE SZ|DV R/W");
+ if (checkfile && fsflg == 0)
+ printf(" NAME\n");
+ else
+ putchar('\n');
+
+ /*
+ * Go through the process list.
+ */
+ for (i = 0; i < cnt; i++) {
+ if (p[i].ki_stat == SZOMB)
+ continue;
+ dofiles(procstat, &p[i]);
+ }
+ procstat_freeprocs(procstat, p);
+ procstat_close(procstat);
+ return (0);
+}
+
+static void
+dofiles(struct procstat *procstat, struct kinfo_proc *kp)
+{
+ const char *cmd;
+ const char *uname;
+ struct filestat *fst;
+ struct filestat_list *head;
+ int pid;
+
+ uname = user_from_uid(kp->ki_uid, 0);
+ pid = kp->ki_pid;
+ cmd = kp->ki_comm;
+
+ head = procstat_getfiles(procstat, kp, mflg);
+ if (head == NULL)
+ return;
+ STAILQ_FOREACH(fst, head, next)
+ print_file_info(procstat, fst, uname, cmd, pid);
+ procstat_freefiles(procstat, head);
+}
+
+
+static void
+print_file_info(struct procstat *procstat, struct filestat *fst,
+ const char *uname, const char *cmd, int pid)
+{
+ struct vnstat vn;
+ DEVS *d;
+ const char *filename;
+ int error, fsmatch = 0;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ filename = NULL;
+ if (checkfile != 0) {
+ if (fst->fs_type != PS_FST_TYPE_VNODE &&
+ fst->fs_type != PS_FST_TYPE_FIFO)
+ return;
+ error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+ if (error != 0)
+ return;
+
+ for (d = devs; d != NULL; d = d->next)
+ if (d->fsid == vn.vn_fsid) {
+ fsmatch = 1;
+ if (d->ino == vn.vn_fileid) {
+ filename = d->name;
+ break;
+ }
+ }
+ if (fsmatch == 0 || (filename == NULL && fsflg == 0))
+ return;
+ }
+
+ /*
+ * Print entry prefix.
+ */
+ printf("%-8.8s %-10s %5d", uname, cmd, pid);
+ if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
+ printf(" text");
+ else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
+ printf(" wd");
+ else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
+ printf(" root");
+ else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
+ printf(" tr");
+ else if (fst->fs_uflags & PS_FST_UFLAG_MMAP)
+ printf(" mmap");
+ else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
+ printf(" jail");
+ else if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
+ printf(" ctty");
+ else
+ printf(" %4d", fst->fs_fd);
+
+ /*
+ * Print type-specific data.
+ */
+ switch (fst->fs_type) {
+ case PS_FST_TYPE_FIFO:
+ case PS_FST_TYPE_VNODE:
+ print_vnode_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_SOCKET:
+ print_socket_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_PIPE:
+ print_pipe_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_PTS:
+ print_pts_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_SHM:
+ print_shm_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_SEM:
+ print_sem_info(procstat, fst);
+ break;
+ case PS_FST_TYPE_DEV:
+ break;
+ default:
+ if (vflg)
+ fprintf(stderr,
+ "unknown file type %d for file %d of pid %d\n",
+ fst->fs_type, fst->fs_fd, pid);
+ }
+ if (filename && !fsflg)
+ printf(" %s", filename);
+ putchar('\n');
+}
+
+static char *
+addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
+{
+ char buffer2[INET6_ADDRSTRLEN];
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+ struct sockaddr_un *sun;
+
+ switch (ss->ss_family) {
+ case AF_LOCAL:
+ sun = (struct sockaddr_un *)ss;
+ if (strlen(sun->sun_path) == 0)
+ strlcpy(buffer, "-", buflen);
+ else
+ strlcpy(buffer, sun->sun_path, buflen);
+ break;
+
+ case AF_INET:
+ sin = (struct sockaddr_in *)ss;
+ if (sin->sin_addr.s_addr == INADDR_ANY)
+ snprintf(buffer, buflen, "%s:%d", "*",
+ ntohs(sin->sin_port));
+ else if (inet_ntop(AF_INET, &sin->sin_addr, buffer2,
+ sizeof(buffer2)) != NULL)
+ snprintf(buffer, buflen, "%s:%d", buffer2,
+ ntohs(sin->sin_port));
+ break;
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)ss;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
+ snprintf(buffer, buflen, "%s.%d", "*",
+ ntohs(sin6->sin6_port));
+ else if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
+ sizeof(buffer2)) != NULL)
+ snprintf(buffer, buflen, "%s.%d", buffer2,
+ ntohs(sin6->sin6_port));
+ else
+ strlcpy(buffer, "-", buflen);
+ break;
+
+ default:
+ strlcpy(buffer, "", buflen);
+ break;
+ }
+ return buffer;
+}
+
+
+static void
+print_socket_info(struct procstat *procstat, struct filestat *fst)
+{
+ static const char *stypename[] = {
+ "unused", /* 0 */
+ "stream", /* 1 */
+ "dgram", /* 2 */
+ "raw", /* 3 */
+ "rdm", /* 4 */
+ "seqpak" /* 5 */
+ };
+#define STYPEMAX 5
+ struct sockstat sock;
+ struct protoent *pe;
+ char errbuf[_POSIX2_LINE_MAX];
+ char src_addr[PATH_MAX], dst_addr[PATH_MAX];
+ struct sockaddr_un *sun;
+ int error;
+ static int isopen;
+
+ error = procstat_get_socket_info(procstat, fst, &sock, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
+ }
+ if (sock.type > STYPEMAX)
+ printf("* %s ?%d", sock.dname, sock.type);
+ else
+ printf("* %s %s", sock.dname, stypename[sock.type]);
+
+ /*
+ * protocol specific formatting
+ *
+ * Try to find interesting things to print. For internet and unix
+ * sockets, its the address of the socket pcb. For unix it is also the
+ * address of the connected pcb (if connected). Otherwise just print
+ * the protocol number and address of the socket itself.
+ * The idea is not to duplicate netstat, but to make available enough
+ * information for further analysis.
+ */
+ switch (sock.dom_family) {
+ case AF_INET:
+ case AF_INET6:
+ if (!isopen)
+ setprotoent(++isopen);
+ if ((pe = getprotobynumber(sock.proto)) != NULL)
+ printf(" %s", pe->p_name);
+ else
+ printf(" %d", sock.proto);
+ if (sock.so_pcb != 0)
+ printf(" %lx", (u_long)sock.so_pcb);
+ if (!sflg)
+ break;
+ printf(" %s <-> %s",
+ addr_to_string(&sock.sa_local, src_addr, sizeof(src_addr)),
+ addr_to_string(&sock.sa_peer, dst_addr, sizeof(dst_addr)));
+ break;
+ case AF_UNIX:
+ /* print address of pcb and connected pcb */
+ if (sock.so_pcb != 0) {
+ printf(" %lx", (u_long)sock.so_pcb);
+ if (sock.unp_conn) {
+ char shoconn[4], *cp;
+
+ cp = shoconn;
+ if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE))
+ *cp++ = '<';
+ *cp++ = '-';
+ if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE))
+ *cp++ = '>';
+ *cp = '\0';
+ printf(" %s %lx", shoconn,
+ (u_long)sock.unp_conn);
+ }
+ }
+ if (!sflg)
+ break;
+ sun = (struct sockaddr_un *)&sock.sa_local;
+ /*
+ * While generally we like to print two addresses,
+ * local and peer, for sockets, it turns out to be
+ * more useful to print the first non-null address for
+ * local sockets, as typically they aren't bound and
+ * connected, and the path strings can get long.
+ */
+ if (sun->sun_path[0] != 0)
+ addr_to_string(&sock.sa_local,
+ src_addr, sizeof(src_addr));
+ else
+ addr_to_string(&sock.sa_peer,
+ src_addr, sizeof(src_addr));
+ printf(" %s", src_addr);
+ break;
+ default:
+ /* print protocol number and socket address */
+ printf(" %d %lx", sock.proto, (u_long)sock.so_addr);
+ }
+}
+
+static void
+print_pipe_info(struct procstat *procstat, struct filestat *fst)
+{
+ struct pipestat ps;
+ char errbuf[_POSIX2_LINE_MAX];
+ int error;
+
+ error = procstat_get_pipe_info(procstat, fst, &ps, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
+ }
+ printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer);
+ printf(" %6zd", ps.buffer_cnt);
+ print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_pts_info(struct procstat *procstat, struct filestat *fst)
+{
+ struct ptsstat pts;
+ char errbuf[_POSIX2_LINE_MAX];
+ int error;
+
+ error = procstat_get_pts_info(procstat, fst, &pts, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
+ }
+ printf("* pseudo-terminal master ");
+ if (nflg || !*pts.devname) {
+ printf("%#10jx", (uintmax_t)pts.dev);
+ } else {
+ printf("%10s", pts.devname);
+ }
+ print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_sem_info(struct procstat *procstat, struct filestat *fst)
+{
+ struct semstat sem;
+ char errbuf[_POSIX2_LINE_MAX];
+ char mode[15];
+ int error;
+
+ error = procstat_get_sem_info(procstat, fst, &sem, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
+ }
+ if (nflg) {
+ printf(" ");
+ (void)snprintf(mode, sizeof(mode), "%o", sem.mode);
+ } else {
+ printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
+ strmode(sem.mode, mode);
+ }
+ printf(" %10s %6u", mode, sem.value);
+ print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_shm_info(struct procstat *procstat, struct filestat *fst)
+{
+ struct shmstat shm;
+ char errbuf[_POSIX2_LINE_MAX];
+ char mode[15];
+ int error;
+
+ error = procstat_get_shm_info(procstat, fst, &shm, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
+ }
+ if (nflg) {
+ printf(" ");
+ (void)snprintf(mode, sizeof(mode), "%o", shm.mode);
+ } else {
+ printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
+ strmode(shm.mode, mode);
+ }
+ printf(" %10s %6ju", mode, shm.size);
+ print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_vnode_info(struct procstat *procstat, struct filestat *fst)
+{
+ struct vnstat vn;
+ char errbuf[_POSIX2_LINE_MAX];
+ char mode[15];
+ const char *badtype;
+ int error;
+
+ badtype = NULL;
+ error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+ if (error != 0)
+ badtype = errbuf;
+ else if (vn.vn_type == PS_FST_VTYPE_VBAD)
+ badtype = "bad";
+ else if (vn.vn_type == PS_FST_VTYPE_VNON)
+ badtype = "none";
+ if (badtype != NULL) {
+ printf(" - - %10s -", badtype);
+ return;
+ }
+
+ if (nflg)
+ printf(" %#5jx", (uintmax_t)vn.vn_fsid);
+ else if (vn.vn_mntdir != NULL)
+ (void)printf(" %-8s", vn.vn_mntdir);
+
+ /*
+ * Print access mode.
+ */
+ if (nflg)
+ (void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode);
+ else {
+ strmode(vn.vn_mode, mode);
+ }
+ (void)printf(" %6jd %10s", (intmax_t)vn.vn_fileid, mode);
+
+ if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
+ if (nflg || !*vn.vn_devname)
+ printf(" %#6jx", (uintmax_t)vn.vn_dev);
+ else {
+ printf(" %6s", vn.vn_devname);
+ }
+ } else
+ printf(" %6ju", (uintmax_t)vn.vn_size);
+ print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_access_flags(int flags)
+{
+ char rw[3];
+
+ rw[0] = '\0';
+ if (flags & PS_FST_FFLAG_READ)
+ strcat(rw, "r");
+ if (flags & PS_FST_FFLAG_WRITE)
+ strcat(rw, "w");
+ printf(" %2s", rw);
+}
+
+int
+getfname(const char *filename)
+{
+ struct stat statbuf;
+ DEVS *cur;
+
+ if (stat(filename, &statbuf)) {
+ warn("%s", filename);
+ return (0);
+ }
+ if ((cur = malloc(sizeof(DEVS))) == NULL)
+ err(1, NULL);
+ cur->next = devs;
+ devs = cur;
+
+ cur->ino = statbuf.st_ino;
+ cur->fsid = statbuf.st_dev;
+ cur->name = filename;
+ return (1);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/fstat/functions.h b/usr.bin/fstat/functions.h
new file mode 100644
index 000000000000..4737a43023c3
--- /dev/null
+++ b/usr.bin/fstat/functions.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
+ * 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.
+ *
+ * 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 __FUNCTIONS_H__
+#define __FUNCTIONS_H__
+
+int do_fstat(int argc, char *argv[]);
+int do_fuser(int argc, char *argv[]);
+
+#endif /* !__FUNCTIONS_H__ */
diff --git a/usr.bin/fstat/fuser.1 b/usr.bin/fstat/fuser.1
new file mode 100644
index 000000000000..5def7b36d606
--- /dev/null
+++ b/usr.bin/fstat/fuser.1
@@ -0,0 +1,151 @@
+.\" Copyright (c) 2005-2011 Stanislav Sedov <stas@FreeBSD.org>
+.\" 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.
+.\"
+.\" 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.
+.\"
+.Dd June 18, 2020
+.Dt FUSER 1
+.Os
+.Sh NAME
+.Nm fuser
+.Nd list IDs of all processes that have one or more files open
+.Sh SYNOPSIS
+.Nm
+.Op Fl cfkmu
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl s Ar signal
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes to stdout the PIDs of processes that have one or
+more named files open.
+For block and character special devices, all processes using files
+on that device are listed.
+A file is considered open by a process if it was explicitly opened,
+is the working directory, root directory, jail root directory,
+active executable text, kernel trace file or the controlling terminal
+of the process.
+If
+.Fl m
+option is specified, the
+.Nm
+utility will also look through mmapped files.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Treat files as mount points and report on any files open in the file system.
+.It Fl f
+The report must be only for named files.
+.It Fl k
+Send signal to reported processes
+.Pq Dv SIGKILL No by default .
+.It Fl M Ar core
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl m
+Search through mmapped files too.
+.It Fl N Ar system
+Extract the name list from the specified system instead of the default,
+which is the kernel image the system has booted from.
+.It Fl s Ar signal
+Use given signal name instead of default
+.Dv SIGKILL .
+.It Fl u
+Write the user name associated with each process to stderr.
+.El
+.Pp
+The following symbols, written to stderr will indicate how files are used:
+.Pp
+.Bl -tag -width indent -compact
+.It Sy a
+The file is open as append only
+.Pq Dv O_APPEND No was specified .
+.It Sy c
+The file is the current workdir directory of the process.
+.It Sy d
+The process bypasses fs cache while writing to this file
+.Pq Dv O_DIRECT No was specified .
+.It Sy e
+Exclusive lock is hold.
+.It Sy j
+The file is the jail root of the process.
+.It Sy m
+The file is mmapped.
+.It Sy r
+The file is the root directory of the process.
+.It Sy s
+Shared lock is hold.
+.It Sy t
+The file is the kernel tracing file for the process.
+.It Sy w
+The file is open for writing.
+.It Sy x
+The file is executable text of the process.
+.It Sy y
+The process uses this file as its controlling tty.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The command
+.Ql "fuser -fu \&."
+writes to standard output the process IDs of processes that are using the
+current directory and writes to stderr an indication of how those processes are
+using the directory and user names associated with the processes that are using
+this directory.
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr iostat 8 ,
+.Xr pstat 8 ,
+.Xr vmstat 8
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.1-2004 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+utility and this manual page was written by
+.An Stanislav Sedov Aq Mt stas@FreeBSD.org .
+.Sh BUGS
+Since
+.Nm
+takes a snapshot of the system, it is only correct for a very short period
+of time.
+When working via
+.Xr kvm 3
+interface the report will be limited to filesystems the
+.Nm
+utility knows about (currently only cd9660, devfs, nfs, ntfs, nwfs, udf,
+ufs and zfs).
diff --git a/usr.bin/fstat/fuser.c b/usr.bin/fstat/fuser.c
new file mode 100644
index 000000000000..2e2befde6392
--- /dev/null
+++ b/usr.bin/fstat/fuser.c
@@ -0,0 +1,367 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005-2009 Stanislav Sedov <stas@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "functions.h"
+
+/*
+ * File access mode flags table.
+ */
+static const struct {
+ int flag;
+ char ch;
+} fflags[] = {
+ {PS_FST_FFLAG_WRITE, 'w'},
+ {PS_FST_FFLAG_APPEND, 'a'},
+ {PS_FST_FFLAG_DIRECT, 'd'},
+ {PS_FST_FFLAG_SHLOCK, 's'},
+ {PS_FST_FFLAG_EXLOCK, 'e'}
+};
+#define NFFLAGS (sizeof(fflags) / sizeof(*fflags))
+
+/*
+ * Usage flags translation table.
+ */
+static const struct {
+ int flag;
+ char ch;
+} uflags[] = {
+ {PS_FST_UFLAG_RDIR, 'r'},
+ {PS_FST_UFLAG_CDIR, 'c'},
+ {PS_FST_UFLAG_JAIL, 'j'},
+ {PS_FST_UFLAG_TRACE, 't'},
+ {PS_FST_UFLAG_TEXT, 'x'},
+ {PS_FST_UFLAG_MMAP, 'm'},
+ {PS_FST_UFLAG_CTTY, 'y'}
+};
+#define NUFLAGS (sizeof(uflags) / sizeof(*uflags))
+
+struct consumer {
+ pid_t pid;
+ uid_t uid;
+ int fd;
+ int flags;
+ int uflags;
+ STAILQ_ENTRY(consumer) next;
+};
+struct reqfile {
+ dev_t fsid;
+ ino_t fileid;
+ const char *name;
+ STAILQ_HEAD(, consumer) consumers;
+};
+
+/*
+ * Option flags.
+ */
+#define UFLAG 0x01 /* -u flag: show users */
+#define FFLAG 0x02 /* -f flag: specified files only */
+#define CFLAG 0x04 /* -c flag: treat as mpoints */
+#define MFLAG 0x10 /* -m flag: mmapped files too */
+#define KFLAG 0x20 /* -k flag: send signal (SIGKILL by default) */
+
+static int flags = 0; /* Option flags. */
+
+static void printflags(struct consumer *consumer);
+static int str2sig(const char *str);
+static void usage(void) __dead2;
+static int addfile(const char *path, struct reqfile *reqfile);
+static void dofiles(struct procstat *procstat, struct kinfo_proc *kp,
+ struct reqfile *reqfiles, size_t nfiles);
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+"usage: fuser [-cfhkmu] [-M core] [-N system] [-s signal] file ...\n");
+ exit(EX_USAGE);
+}
+
+static void
+printflags(struct consumer *cons)
+{
+ unsigned int i;
+
+ assert(cons);
+ for (i = 0; i < NUFLAGS; i++)
+ if ((cons->uflags & uflags[i].flag) != 0)
+ fputc(uflags[i].ch, stderr);
+ for (i = 0; i < NFFLAGS; i++)
+ if ((cons->flags & fflags[i].flag) != 0)
+ fputc(fflags[i].ch, stderr);
+}
+
+/*
+ * Add file to the list.
+ */
+static int
+addfile(const char *path, struct reqfile *reqfile)
+{
+ struct stat sb;
+
+ assert(path);
+ if (stat(path, &sb) != 0) {
+ warn("%s", path);
+ return (1);
+ }
+ reqfile->fileid = sb.st_ino;
+ reqfile->fsid = sb.st_dev;
+ reqfile->name = path;
+ STAILQ_INIT(&reqfile->consumers);
+ return (0);
+}
+
+int
+do_fuser(int argc, char *argv[])
+{
+ struct consumer *consumer;
+ struct kinfo_proc *procs;
+ struct procstat *procstat;
+ struct reqfile *reqfiles;
+ char *ep, *nlistf, *memf;
+ int ch, sig;
+ unsigned int i, cnt, nfiles;
+
+ sig = SIGKILL; /* Default to kill. */
+ nlistf = NULL;
+ memf = NULL;
+ while ((ch = getopt(argc, argv, "M:N:cfhkms:u")) != -1)
+ switch(ch) {
+ case 'f':
+ if ((flags & CFLAG) != 0)
+ usage();
+ flags |= FFLAG;
+ break;
+ case 'c':
+ if ((flags & FFLAG) != 0)
+ usage();
+ flags |= CFLAG;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'u':
+ flags |= UFLAG;
+ break;
+ case 'm':
+ flags |= MFLAG;
+ break;
+ case 'k':
+ flags |= KFLAG;
+ break;
+ case 's':
+ if (isdigit(*optarg)) {
+ sig = strtol(optarg, &ep, 10);
+ if (*ep != '\0' || sig < 0 || sig >= sys_nsig)
+ errx(EX_USAGE, "illegal signal number" ": %s",
+ optarg);
+ } else {
+ sig = str2sig(optarg);
+ if (sig < 0)
+ errx(EX_USAGE, "illegal signal name: "
+ "%s", optarg);
+ }
+ break;
+ case 'h':
+ /* PASSTHROUGH */
+ default:
+ usage();
+ /* NORETURN */
+ }
+ argv += optind;
+ argc -= optind;
+
+ assert(argc >= 0);
+ if (argc == 0)
+ usage();
+ /* NORETURN */
+
+ /*
+ * Process named files.
+ */
+ reqfiles = malloc(argc * sizeof(struct reqfile));
+ if (reqfiles == NULL)
+ err(EX_OSERR, "malloc()");
+ nfiles = 0;
+ while (argc--)
+ if (!addfile(*(argv++), &reqfiles[nfiles]))
+ nfiles++;
+ if (nfiles == 0)
+ errx(EX_IOERR, "files not accessible");
+
+ if (memf != NULL)
+ procstat = procstat_open_kvm(nlistf, memf);
+ else
+ procstat = procstat_open_sysctl();
+ if (procstat == NULL)
+ errx(1, "procstat_open()");
+ procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &cnt);
+ if (procs == NULL)
+ errx(1, "procstat_getprocs()");
+
+ /*
+ * Walk through process table and look for matching files.
+ */
+ for (i = 0; i < cnt; i++)
+ if (procs[i].ki_stat != SZOMB)
+ dofiles(procstat, &procs[i], reqfiles, nfiles);
+
+ for (i = 0; i < nfiles; i++) {
+ fprintf(stderr, "%s:", reqfiles[i].name);
+ fflush(stderr);
+ STAILQ_FOREACH(consumer, &reqfiles[i].consumers, next) {
+ if (consumer->flags != 0) {
+ fprintf(stdout, "%6d", consumer->pid);
+ fflush(stdout);
+ printflags(consumer);
+ if ((flags & UFLAG) != 0)
+ fprintf(stderr, "(%s)",
+ user_from_uid(consumer->uid, 0));
+ if ((flags & KFLAG) != 0)
+ kill(consumer->pid, sig);
+ fflush(stderr);
+ }
+ }
+ (void)fprintf(stderr, "\n");
+ }
+ procstat_freeprocs(procstat, procs);
+ procstat_close(procstat);
+ free(reqfiles);
+ return (0);
+}
+
+static void
+dofiles(struct procstat *procstat, struct kinfo_proc *kp,
+ struct reqfile *reqfiles, size_t nfiles)
+{
+ struct vnstat vn;
+ struct consumer *cons;
+ struct filestat *fst;
+ struct filestat_list *head;
+ int error, match;
+ unsigned int i;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ head = procstat_getfiles(procstat, kp, flags & MFLAG);
+ if (head == NULL)
+ return;
+ STAILQ_FOREACH(fst, head, next) {
+ if (fst->fs_type != PS_FST_TYPE_VNODE)
+ continue;
+ error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+ if (error != 0)
+ continue;
+ for (i = 0; i < nfiles; i++) {
+ if (flags & CFLAG && reqfiles[i].fsid == vn.vn_fsid) {
+ break;
+ }
+ else if (reqfiles[i].fsid == vn.vn_fsid &&
+ reqfiles[i].fileid == vn.vn_fileid) {
+ break;
+ }
+ else if (!(flags & FFLAG) &&
+ (vn.vn_type == PS_FST_VTYPE_VCHR ||
+ vn.vn_type == PS_FST_VTYPE_VBLK) &&
+ vn.vn_fsid == reqfiles[i].fileid) {
+ break;
+ }
+ }
+ if (i == nfiles)
+ continue; /* No match. */
+
+ /*
+ * Look for existing entries.
+ */
+ match = 0;
+ STAILQ_FOREACH(cons, &reqfiles[i].consumers, next)
+ if (cons->pid == kp->ki_pid) {
+ match = 1;
+ break;
+ }
+ if (match == 1) { /* Use old entry. */
+ cons->flags |= fst->fs_fflags;
+ cons->uflags |= fst->fs_uflags;
+ } else {
+ /*
+ * Create new entry in the consumer chain.
+ */
+ cons = calloc(1, sizeof(struct consumer));
+ if (cons == NULL) {
+ warn("malloc()");
+ continue;
+ }
+ cons->uid = kp->ki_uid;
+ cons->pid = kp->ki_pid;
+ cons->uflags = fst->fs_uflags;
+ cons->flags = fst->fs_fflags;
+ STAILQ_INSERT_TAIL(&reqfiles[i].consumers, cons, next);
+ }
+ }
+ procstat_freefiles(procstat, head);
+}
+
+/*
+ * Returns signal number for it's string representation.
+ */
+static int
+str2sig(const char *str)
+{
+ int i;
+
+ if (!strncasecmp(str, "SIG", 3))
+ str += 3;
+ for (i = 1; i < sys_nsig; i++) {
+ if (!strcasecmp(sys_signame[i], str))
+ return (i);
+ }
+ return (-1);
+}
diff --git a/usr.bin/fstat/main.c b/usr.bin/fstat/main.c
new file mode 100644
index 000000000000..c1ad8cacc147
--- /dev/null
+++ b/usr.bin/fstat/main.c
@@ -0,0 +1,49 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>.
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "functions.h"
+
+int
+main(int argc, char *argv[])
+{
+ char *p;
+
+ p = basename(argv[0]);
+ if (p == NULL)
+ err(1, "basename(%s)", argv[0]);
+ if (!strcmp(p, "fuser"))
+ return (do_fuser(argc, argv));
+ else
+ return (do_fstat(argc, argv));
+}
diff --git a/usr.bin/fsync/Makefile b/usr.bin/fsync/Makefile
new file mode 100644
index 000000000000..79c1b4579005
--- /dev/null
+++ b/usr.bin/fsync/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= runtime
+PROG= fsync
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/fsync/Makefile.depend b/usr.bin/fsync/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/fsync/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/fsync/fsync.1 b/usr.bin/fsync/fsync.1
new file mode 100644
index 000000000000..dfcb184c3bfe
--- /dev/null
+++ b/usr.bin/fsync/fsync.1
@@ -0,0 +1,61 @@
+.\" Copyright (c) 2000 Paul Saab <ps@FreeBSD.org>
+.\" 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.
+.\"
+.\" 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.
+.\"
+.Dd January 25, 2005
+.Dt FSYNC 1
+.Os
+.Sh NAME
+.Nm fsync
+.Nd synchronize a file's in-core state with that on disk
+.Sh SYNOPSIS
+.Nm
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility causes all the modified data and meta-data of
+all the files named on the command line
+to be written to a permanent storage device.
+.Pp
+The
+.Nm
+utility uses the
+.Xr fsync 2
+function call.
+.Sh EXIT STATUS
+If an error occurs, the
+.Nm
+utility proceeds to the next file, and exits >0.
+Otherwise, it exits 0.
+.Sh SEE ALSO
+.Xr fsync 2 ,
+.Xr sync 2 ,
+.Xr syncer 4 ,
+.Xr halt 8 ,
+.Xr reboot 8
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 4.3 .
diff --git a/usr.bin/fsync/fsync.c b/usr.bin/fsync/fsync.c
new file mode 100644
index 000000000000..9968bc8614a5
--- /dev/null
+++ b/usr.bin/fsync/fsync.c
@@ -0,0 +1,77 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 Paul Saab <ps@FreeBSD.org>
+ * 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.
+ *
+ * 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 <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ int i;
+ int rval;
+
+ if (argc < 2) {
+ usage();
+ /* NOTREACHED */
+ }
+
+ rval = EX_OK;
+ for (i = 1; i < argc; ++i) {
+ if ((fd = open(argv[i], O_RDONLY)) == -1) {
+ warn("open %s", argv[i]);
+ if (rval == EX_OK)
+ rval = EX_NOINPUT;
+ continue;
+ }
+
+ if (fsync(fd) == -1) {
+ warn("fsync %s", argv[i]);
+ if (rval == EX_OK)
+ rval = EX_OSERR;
+ }
+ close(fd);
+ }
+ exit(rval);
+ /* NOTREACHED */
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: fsync file ...\n");
+ exit(EX_USAGE);
+ /* NOTREACHED */
+}
diff --git a/usr.bin/ftp/Makefile b/usr.bin/ftp/Makefile
new file mode 100644
index 000000000000..48aae3466dbe
--- /dev/null
+++ b/usr.bin/ftp/Makefile
@@ -0,0 +1,32 @@
+# $NetBSD: Makefile,v 1.15 1997/10/18 15:31:20 lukem Exp $
+
+.include <src.opts.mk>
+
+# Uncomment the following to provide defaults for gate-ftp operation
+#
+#CFLAGS+=-DGATE_SERVER=\"ftp-gw.host\" # -DGATE_PORT=21
+
+PACKAGE= ftp
+
+TNFTP= ${SRCTOP}/contrib/tnftp
+.PATH: ${TNFTP}/src
+
+PROG= ftp
+SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \
+ progressbar.c ruserpass.c util.c
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+
+CFLAGS+= -I${.CURDIR} -I${TNFTP}
+LIBADD= edit
+
+WARNS?= 2
+
+LINKS= ${BINDIR}/ftp ${BINDIR}/pftp \
+ ${BINDIR}/ftp ${BINDIR}/gate-ftp
+MLINKS= ftp.1 pftp.1 \
+ ftp.1 gate-ftp.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ftp/Makefile.depend b/usr.bin/ftp/Makefile.depend
new file mode 100644
index 000000000000..f010c62edfb4
--- /dev/null
+++ b/usr.bin/ftp/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libedit \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ftp/tnftp_config.h b/usr.bin/ftp/tnftp_config.h
new file mode 100644
index 000000000000..f551312f64a0
--- /dev/null
+++ b/usr.bin/ftp/tnftp_config.h
@@ -0,0 +1,513 @@
+/* tnftp_config.h. Generated from tnftp_config.h.in by configure. */
+/* tnftp_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+#define GETPGRP_VOID 1
+
+/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */
+/* #undef GWINSZ_IN_SYS_IOCTL */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the <arpa/ftp.h> header file. */
+#define HAVE_ARPA_FTP_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you
+ don't. */
+#define HAVE_DECL_AF_INET6 1
+
+/* Define to 1 if you have the declaration of `AI_NUMERICHOST', and to 0 if
+ you don't. */
+#define HAVE_DECL_AI_NUMERICHOST 1
+
+/* Define to 1 if you have the declaration of `dirname', and to 0 if you
+ don't. */
+#define HAVE_DECL_DIRNAME 1
+
+/* Define to 1 if you have the declaration of `fclose', and to 0 if you don't.
+ */
+#define HAVE_DECL_FCLOSE 1
+
+/* Define to 1 if you have the declaration of `getpass', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETPASS 1
+
+/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
+ don't. */
+#define HAVE_DECL_H_ERRNO 1
+
+/* Define to 1 if you have the declaration of `NS_IN6ADDRSZ', and to 0 if you
+ don't. */
+#define HAVE_DECL_NS_IN6ADDRSZ 1
+
+/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
+ */
+#define HAVE_DECL_OPTARG 1
+
+/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
+ */
+#define HAVE_DECL_OPTIND 1
+
+/* Define to 1 if you have the declaration of `pclose', and to 0 if you don't.
+ */
+#define HAVE_DECL_PCLOSE 1
+
+/* Define to 1 if you have the declaration of `strptime', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRPTIME 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the `dirname' function. */
+#define HAVE_DIRNAME 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `err' function. */
+#define HAVE_ERR 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fgetln' function. */
+#define HAVE_FGETLN 1
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#define HAVE_GETHOSTBYNAME2 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define to 1 if you have the `getpass' function. */
+#define HAVE_GETPASS 1
+
+/* Define to 1 if you have the `getpassphrase' function. */
+/* #undef HAVE_GETPASSPHRASE */
+
+/* Define to 1 if you have the `getpgrp' function. */
+#define HAVE_GETPGRP 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `inet_ntop' function. */
+#define HAVE_INET_NTOP 1
+
+/* Define to 1 if you have the `inet_pton' function. */
+#define HAVE_INET_PTON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if the system has the type `in_port_t'. */
+#define HAVE_IN_PORT_T 1
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#define HAVE_LIBGEN_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if the system has the type `long double'. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define to 1 if the system has the type `long long int'. */
+#define HAVE_LONG_LONG_INT 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if we have poll() and it is not emulated. */
+#define HAVE_POLL 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define if `long long' is supported and *printf() supports %lld or %qd to
+ print them. */
+#define HAVE_PRINTF_LONG_LONG 1
+
+/* Define if *printf() uses %qd to print `long long' (otherwise uses %lld). */
+/* #undef HAVE_PRINTF_QD */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define to 1 if the system has the type `sa_family_t'. */
+#define HAVE_SA_FAMILY_T 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#define HAVE_SETJMP_H 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `setprogname' function. */
+#define HAVE_SETPROGNAME 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the `sl_init' function. */
+#define HAVE_SL_INIT 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcoll' function and it is properly defined.
+ */
+#define HAVE_STRCOLL 1
+
+/* Define to 1 if you have the `strcspn' function. */
+#define HAVE_STRCSPN 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strpbrk' function. */
+#define HAVE_STRPBRK 1
+
+/* Define to 1 if you have the `strptime' function. */
+#define HAVE_STRPTIME 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strsep' function. */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#define HAVE_STRUCT_ADDRINFO 1
+
+/* Define to 1 if `struct dirent' is a member of `d_namlen'. */
+#define HAVE_STRUCT_DIRENT_D_NAMLEN 1
+
+/* Define to 1 if the system has the type `struct pollfd'. */
+#define HAVE_STRUCT_POLLFD 1
+
+/* Define to 1 if the system has the type `struct sockaddr_in6'. */
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+
+/* Define to 1 if `struct sockaddr_in' is a member of `sin_len'. */
+#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
+
+/* Define to 1 if `struct sockaddr' is a member of `sa_len'. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if you have the `strunvis' function. */
+#define HAVE_STRUNVIS 1
+
+/* Define to 1 if you have the `strvis' function. */
+#define HAVE_STRVIS 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syslimits.h> header file. */
+#define HAVE_SYS_SYSLIMITS_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the `timegm' function. */
+#define HAVE_TIMEGM 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Define to 1 if you have the `utime' function. */
+#define HAVE_UTIME 1
+
+/* Define to 1 if you have the `utimes' function. */
+#define HAVE_UTIMES 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the <vis.h> header file. */
+#define HAVE_VIS_H 1
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Name of package */
+#define PACKAGE "tnftp"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "lukem@NetBSD.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "tnftp"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "tnftp 20100108"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "tnftp"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "20100108"
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define if using (Dante) SOCKS5 proxy. */
+/* #undef USE_SOCKS */
+
+/* Version number of package */
+#define VERSION "20100108"
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
+
+
+/* Define if using IPv6 support. */
+/* Commented out so this can be selected fromt he Makefile -gavin */
+/* #define USE_INET6 1 */
+
+#define USE_GLOB_H 1
diff --git a/usr.bin/gcore/Makefile b/usr.bin/gcore/Makefile
new file mode 100644
index 000000000000..398f7d2a36d6
--- /dev/null
+++ b/usr.bin/gcore/Makefile
@@ -0,0 +1,12 @@
+PROG= gcore
+SRCS= elfcore.c gcore.c
+LIBADD= sbuf util
+
+.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_ARCH} == "amd64" || \
+ ${MACHINE_ARCH} == "powerpc64"
+SRCS+= elf32core.c
+.endif
+
+WARNS?= 1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gcore/Makefile.depend b/usr.bin/gcore/Makefile.depend
new file mode 100644
index 000000000000..3c711d830978
--- /dev/null
+++ b/usr.bin/gcore/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsbuf \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gcore/elf32core.c b/usr.bin/gcore/elf32core.c
new file mode 100644
index 000000000000..292ff59b98b1
--- /dev/null
+++ b/usr.bin/gcore/elf32core.c
@@ -0,0 +1,10 @@
+#ifndef __LP64__
+#error "this file must be compiled for LP64."
+#endif
+
+#define __ELF_WORD_SIZE 32
+#define _MACHINE_ELF_WANT_32BIT
+
+#define ELFCORE_COMPAT_32 1
+#include "elfcore.c"
+
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
new file mode 100644
index 000000000000..2bffd409bb11
--- /dev/null
+++ b/usr.bin/gcore/elfcore.c
@@ -0,0 +1,878 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2017 Dell EMC
+ * Copyright (c) 2007 Sandvine Incorporated
+ * Copyright (c) 1998 John D. Polstra
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/procfs.h>
+#include <sys/ptrace.h>
+#include <sys/queue.h>
+#include <sys/linker_set.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <machine/elf.h>
+#include <vm/vm_param.h>
+#include <vm/vm.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libutil.h>
+
+#include "extern.h"
+
+/*
+ * Code for generating ELF core dumps.
+ */
+
+struct map_entry {
+ struct map_entry *next;
+ vm_offset_t start;
+ vm_offset_t end;
+ vm_prot_t protection;
+};
+
+typedef void (*segment_callback)(struct map_entry *, void *);
+
+/* Closure for cb_put_phdr(). */
+struct phdr_closure {
+ Elf_Phdr *phdr; /* Program header to fill in */
+ Elf_Off offset; /* Offset of segment in core file */
+};
+
+/* Closure for cb_size_segment(). */
+struct sseg_closure {
+ int count; /* Count of writable segments. */
+ size_t size; /* Total size of all writable segments. */
+};
+
+#ifdef ELFCORE_COMPAT_32
+typedef struct prpsinfo32 elfcore_prpsinfo_t;
+#else
+typedef prpsinfo_t elfcore_prpsinfo_t;
+#endif
+
+typedef void* (*notefunc_t)(void *, size_t *);
+
+static void cb_put_phdr(struct map_entry *, void *);
+static void cb_size_segment(struct map_entry *, void *);
+static void each_dumpable_segment(struct map_entry *, segment_callback,
+ void *closure);
+static void elf_detach(void); /* atexit() handler. */
+static void *elf_note_prpsinfo(void *, size_t *);
+#if defined(__i386__) || defined(__amd64__)
+static void *elf_note_x86_xstate(void *, size_t *);
+#endif
+#if defined(__powerpc__)
+static void *elf_note_powerpc_vmx(void *, size_t *);
+static void *elf_note_powerpc_vsx(void *, size_t *);
+#endif
+static void *elf_note_procstat_auxv(void *, size_t *);
+static void *elf_note_procstat_files(void *, size_t *);
+static void *elf_note_procstat_groups(void *, size_t *);
+static void *elf_note_procstat_osrel(void *, size_t *);
+static void *elf_note_procstat_proc(void *, size_t *);
+static void *elf_note_procstat_psstrings(void *, size_t *);
+static void *elf_note_procstat_rlimit(void *, size_t *);
+static void *elf_note_procstat_umask(void *, size_t *);
+static void *elf_note_procstat_vmmap(void *, size_t *);
+static void elf_puthdr(int, pid_t, struct map_entry *, void *, size_t, size_t,
+ size_t, int);
+static void elf_putnote(int, notefunc_t, void *, struct sbuf *);
+static void elf_putnotes(pid_t, struct sbuf *, size_t *);
+static void elf_putregnote(int, lwpid_t, struct sbuf *);
+static void freemap(struct map_entry *);
+static struct map_entry *readmap(pid_t);
+static void *procstat_sysctl(void *, int, size_t, size_t *sizep);
+
+static pid_t g_pid; /* Pid being dumped, global for elf_detach */
+static int g_status; /* proc status after ptrace attach */
+
+static int
+elf_ident(int efd, pid_t pid __unused, char *binfile __unused)
+{
+ Elf_Ehdr hdr;
+ int cnt;
+ uint16_t machine;
+
+ cnt = read(efd, &hdr, sizeof(hdr));
+ if (cnt != sizeof(hdr))
+ return (0);
+ if (!IS_ELF(hdr))
+ return (0);
+ switch (hdr.e_ident[EI_DATA]) {
+ case ELFDATA2LSB:
+ machine = le16toh(hdr.e_machine);
+ break;
+ case ELFDATA2MSB:
+ machine = be16toh(hdr.e_machine);
+ break;
+ default:
+ return (0);
+ }
+ if (!ELF_MACHINE_OK(machine))
+ return (0);
+
+ /* Looks good. */
+ return (1);
+}
+
+static void
+elf_detach(void)
+{
+ int sig;
+
+ if (g_pid != 0) {
+ /*
+ * Forward any pending signals. SIGSTOP is generated by ptrace
+ * itself, so ignore it.
+ */
+ sig = WIFSTOPPED(g_status) ? WSTOPSIG(g_status) : 0;
+ if (sig == SIGSTOP)
+ sig = 0;
+ ptrace(PT_DETACH, g_pid, (caddr_t)1, sig);
+ }
+}
+
+/*
+ * Write an ELF coredump for the given pid to the given fd.
+ */
+static void
+elf_coredump(int efd, int fd, pid_t pid)
+{
+ struct map_entry *map;
+ struct sseg_closure seginfo;
+ struct sbuf *sb;
+ void *hdr;
+ size_t hdrsize, notesz, segoff;
+ ssize_t n, old_len;
+ Elf_Phdr *php;
+ int i;
+
+ /* Attach to process to dump. */
+ g_pid = pid;
+ if (atexit(elf_detach) != 0)
+ err(1, "atexit");
+ errno = 0;
+ ptrace(PT_ATTACH, pid, NULL, 0);
+ if (errno)
+ err(1, "PT_ATTACH");
+ if (waitpid(pid, &g_status, 0) == -1)
+ err(1, "waitpid");
+
+ /* Get the program's memory map. */
+ map = readmap(pid);
+
+ /* Size the program segments. */
+ seginfo.count = 0;
+ seginfo.size = 0;
+ each_dumpable_segment(map, cb_size_segment, &seginfo);
+
+ /*
+ * Build the header and the notes using sbuf and write to the file.
+ */
+ sb = sbuf_new_auto();
+ hdrsize = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * (1 + seginfo.count);
+ if (seginfo.count + 1 >= PN_XNUM)
+ hdrsize += sizeof(Elf_Shdr);
+ /* Start header + notes section. */
+ sbuf_start_section(sb, NULL);
+ /* Make empty header subsection. */
+ sbuf_start_section(sb, &old_len);
+ sbuf_putc(sb, 0);
+ sbuf_end_section(sb, old_len, hdrsize, 0);
+ /* Put notes. */
+ elf_putnotes(pid, sb, &notesz);
+ /* Align up to a page boundary for the program segments. */
+ sbuf_end_section(sb, -1, getpagesize(), 0);
+ if (sbuf_finish(sb) != 0)
+ err(1, "sbuf_finish");
+ hdr = sbuf_data(sb);
+ segoff = sbuf_len(sb);
+ /* Fill in the header. */
+ elf_puthdr(efd, pid, map, hdr, hdrsize, notesz, segoff, seginfo.count);
+
+ n = write(fd, hdr, segoff);
+ if (n == -1)
+ err(1, "write");
+ if (n < segoff)
+ errx(1, "short write");
+
+ /* Write the contents of all of the writable segments. */
+ php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1;
+ for (i = 0; i < seginfo.count; i++) {
+ struct ptrace_io_desc iorequest;
+ uintmax_t nleft = php->p_filesz;
+
+ iorequest.piod_op = PIOD_READ_D;
+ iorequest.piod_offs = (caddr_t)(uintptr_t)php->p_vaddr;
+ while (nleft > 0) {
+ char buf[8*1024];
+ size_t nwant;
+ ssize_t ngot;
+
+ if (nleft > sizeof(buf))
+ nwant = sizeof buf;
+ else
+ nwant = nleft;
+ iorequest.piod_addr = buf;
+ iorequest.piod_len = nwant;
+ ptrace(PT_IO, pid, (caddr_t)&iorequest, 0);
+ ngot = iorequest.piod_len;
+ if ((size_t)ngot < nwant)
+ errx(1, "short read wanted %zu, got %zd",
+ nwant, ngot);
+ ngot = write(fd, buf, nwant);
+ if (ngot == -1)
+ err(1, "write of segment %d failed", i);
+ if ((size_t)ngot != nwant)
+ errx(1, "short write");
+ nleft -= nwant;
+ iorequest.piod_offs += ngot;
+ }
+ php++;
+ }
+ sbuf_delete(sb);
+ freemap(map);
+}
+
+/*
+ * A callback for each_dumpable_segment() to write out the segment's
+ * program header entry.
+ */
+static void
+cb_put_phdr(struct map_entry *entry, void *closure)
+{
+ struct phdr_closure *phc = (struct phdr_closure *)closure;
+ Elf_Phdr *phdr = phc->phdr;
+ size_t page_size;
+
+ page_size = getpagesize();
+ phc->offset = roundup2(phc->offset, page_size);
+
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = phc->offset;
+ phdr->p_vaddr = entry->start;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
+ phdr->p_align = page_size;
+ phdr->p_flags = 0;
+ if (entry->protection & VM_PROT_READ)
+ phdr->p_flags |= PF_R;
+ if (entry->protection & VM_PROT_WRITE)
+ phdr->p_flags |= PF_W;
+ if (entry->protection & VM_PROT_EXECUTE)
+ phdr->p_flags |= PF_X;
+
+ phc->offset += phdr->p_filesz;
+ phc->phdr++;
+}
+
+/*
+ * A callback for each_dumpable_segment() to gather information about
+ * the number of segments and their total size.
+ */
+static void
+cb_size_segment(struct map_entry *entry, void *closure)
+{
+ struct sseg_closure *ssc = (struct sseg_closure *)closure;
+
+ ssc->count++;
+ ssc->size += entry->end - entry->start;
+}
+
+/*
+ * For each segment in the given memory map, call the given function
+ * with a pointer to the map entry and some arbitrary caller-supplied
+ * data.
+ */
+static void
+each_dumpable_segment(struct map_entry *map, segment_callback func,
+ void *closure)
+{
+ struct map_entry *entry;
+
+ for (entry = map; entry != NULL; entry = entry->next)
+ (*func)(entry, closure);
+}
+
+static void
+elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep)
+{
+ lwpid_t *tids;
+ size_t threads, old_len;
+ ssize_t size;
+ int i;
+
+ errno = 0;
+ threads = ptrace(PT_GETNUMLWPS, pid, NULL, 0);
+ if (errno)
+ err(1, "PT_GETNUMLWPS");
+ tids = malloc(threads * sizeof(*tids));
+ if (tids == NULL)
+ errx(1, "out of memory");
+ errno = 0;
+ ptrace(PT_GETLWPLIST, pid, (void *)tids, threads);
+ if (errno)
+ err(1, "PT_GETLWPLIST");
+
+ sbuf_start_section(sb, &old_len);
+ elf_putnote(NT_PRPSINFO, elf_note_prpsinfo, &pid, sb);
+
+ for (i = 0; i < threads; ++i) {
+ elf_putregnote(NT_PRSTATUS, tids[i], sb);
+ elf_putregnote(NT_FPREGSET, tids[i], sb);
+ elf_putregnote(NT_THRMISC, tids[i], sb);
+ elf_putregnote(NT_PTLWPINFO, tids[i], sb);
+#if defined(__aarch64__) || defined(__arm__)
+ elf_putregnote(NT_ARM_TLS, tids[i], sb);
+#endif
+#if (defined(ELFCORE_COMPAT_32) && defined(__aarch64__)) || defined(__arm__)
+ elf_putregnote(NT_ARM_VFP, tids[i], sb);
+#endif
+#if defined(__i386__) || defined(__amd64__)
+ elf_putregnote(NT_X86_SEGBASES, tids[i], sb);
+ elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);
+#endif
+#if defined(__powerpc__)
+ elf_putnote(NT_PPC_VMX, elf_note_powerpc_vmx, tids + i, sb);
+#ifndef __SPE__
+ elf_putnote(NT_PPC_VSX, elf_note_powerpc_vsx, tids + i, sb);
+#endif
+#endif
+ }
+
+#ifndef ELFCORE_COMPAT_32
+ elf_putnote(NT_PROCSTAT_PROC, elf_note_procstat_proc, &pid, sb);
+ elf_putnote(NT_PROCSTAT_FILES, elf_note_procstat_files, &pid, sb);
+ elf_putnote(NT_PROCSTAT_VMMAP, elf_note_procstat_vmmap, &pid, sb);
+ elf_putnote(NT_PROCSTAT_GROUPS, elf_note_procstat_groups, &pid, sb);
+ elf_putnote(NT_PROCSTAT_UMASK, elf_note_procstat_umask, &pid, sb);
+ elf_putnote(NT_PROCSTAT_RLIMIT, elf_note_procstat_rlimit, &pid, sb);
+ elf_putnote(NT_PROCSTAT_OSREL, elf_note_procstat_osrel, &pid, sb);
+ elf_putnote(NT_PROCSTAT_PSSTRINGS, elf_note_procstat_psstrings, &pid,
+ sb);
+ elf_putnote(NT_PROCSTAT_AUXV, elf_note_procstat_auxv, &pid, sb);
+#endif
+
+ size = sbuf_end_section(sb, old_len, 1, 0);
+ if (size == -1)
+ err(1, "sbuf_end_section");
+ free(tids);
+ *sizep = size;
+}
+
+/*
+ * Emit one register set note section to sbuf.
+ */
+static void
+elf_putregnote(int type, lwpid_t tid, struct sbuf *sb)
+{
+ Elf_Note note;
+ struct iovec iov;
+ ssize_t old_len;
+
+ iov.iov_base = NULL;
+ iov.iov_len = 0;
+ if (ptrace(PT_GETREGSET, tid, (void *)&iov, type) != 0)
+ return;
+ iov.iov_base = calloc(1, iov.iov_len);
+ if (iov.iov_base == NULL)
+ errx(1, "out of memory");
+ if (ptrace(PT_GETREGSET, tid, (void *)&iov, type) != 0)
+ errx(1, "failed to fetch register set %d", type);
+
+ note.n_namesz = 8; /* strlen("FreeBSD") + 1 */
+ note.n_descsz = iov.iov_len;
+ note.n_type = type;
+
+ sbuf_bcat(sb, &note, sizeof(note));
+ sbuf_start_section(sb, &old_len);
+ sbuf_bcat(sb, "FreeBSD", note.n_namesz);
+ sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
+ sbuf_start_section(sb, &old_len);
+ sbuf_bcat(sb, iov.iov_base, iov.iov_len);
+ sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
+ free(iov.iov_base);
+}
+
+/*
+ * Emit one note section to sbuf.
+ */
+static void
+elf_putnote(int type, notefunc_t notefunc, void *arg, struct sbuf *sb)
+{
+ Elf_Note note;
+ size_t descsz;
+ ssize_t old_len;
+ void *desc;
+
+ desc = notefunc(arg, &descsz);
+ note.n_namesz = 8; /* strlen("FreeBSD") + 1 */
+ note.n_descsz = descsz;
+ note.n_type = type;
+
+ sbuf_bcat(sb, &note, sizeof(note));
+ sbuf_start_section(sb, &old_len);
+ sbuf_bcat(sb, "FreeBSD", note.n_namesz);
+ sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
+ if (descsz == 0)
+ return;
+ sbuf_start_section(sb, &old_len);
+ sbuf_bcat(sb, desc, descsz);
+ sbuf_end_section(sb, old_len, sizeof(Elf32_Size), 0);
+ free(desc);
+}
+
+/*
+ * Generate the ELF coredump header.
+ */
+static void
+elf_puthdr(int efd, pid_t pid, struct map_entry *map, void *hdr, size_t hdrsize,
+ size_t notesz, size_t segoff, int numsegs)
+{
+ Elf_Ehdr *ehdr, binhdr;
+ Elf_Phdr *phdr;
+ Elf_Shdr *shdr;
+ struct phdr_closure phc;
+ ssize_t cnt;
+
+ cnt = read(efd, &binhdr, sizeof(binhdr));
+ if (cnt < 0)
+ err(1, "Failed to re-read ELF header");
+ else if (cnt != sizeof(binhdr))
+ errx(1, "Failed to re-read ELF header");
+
+ ehdr = (Elf_Ehdr *)hdr;
+
+ ehdr->e_ident[EI_MAG0] = ELFMAG0;
+ ehdr->e_ident[EI_MAG1] = ELFMAG1;
+ ehdr->e_ident[EI_MAG2] = ELFMAG2;
+ ehdr->e_ident[EI_MAG3] = ELFMAG3;
+ ehdr->e_ident[EI_CLASS] = ELF_CLASS;
+ ehdr->e_ident[EI_DATA] = ELF_DATA;
+ ehdr->e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
+ ehdr->e_ident[EI_ABIVERSION] = 0;
+ ehdr->e_ident[EI_PAD] = 0;
+ ehdr->e_type = ET_CORE;
+ ehdr->e_machine = binhdr.e_machine;
+ ehdr->e_version = EV_CURRENT;
+ ehdr->e_entry = 0;
+ ehdr->e_phoff = sizeof(Elf_Ehdr);
+ ehdr->e_flags = binhdr.e_flags;
+ ehdr->e_ehsize = sizeof(Elf_Ehdr);
+ ehdr->e_phentsize = sizeof(Elf_Phdr);
+ ehdr->e_shentsize = sizeof(Elf_Shdr);
+ ehdr->e_shstrndx = SHN_UNDEF;
+ if (numsegs + 1 < PN_XNUM) {
+ ehdr->e_phnum = numsegs + 1;
+ ehdr->e_shnum = 0;
+ } else {
+ ehdr->e_phnum = PN_XNUM;
+ ehdr->e_shnum = 1;
+
+ ehdr->e_shoff = ehdr->e_phoff +
+ (numsegs + 1) * ehdr->e_phentsize;
+
+ shdr = (Elf_Shdr *)((char *)hdr + ehdr->e_shoff);
+ memset(shdr, 0, sizeof(*shdr));
+ /*
+ * A special first section is used to hold large segment and
+ * section counts. This was proposed by Sun Microsystems in
+ * Solaris and has been adopted by Linux; the standard ELF
+ * tools are already familiar with the technique.
+ *
+ * See table 7-7 of the Solaris "Linker and Libraries Guide"
+ * (or 12-7 depending on the version of the document) for more
+ * details.
+ */
+ shdr->sh_type = SHT_NULL;
+ shdr->sh_size = ehdr->e_shnum;
+ shdr->sh_link = ehdr->e_shstrndx;
+ shdr->sh_info = numsegs + 1;
+ }
+
+ /*
+ * Fill in the program header entries.
+ */
+ phdr = (Elf_Phdr *)((char *)hdr + ehdr->e_phoff);
+
+ /* The note segment. */
+ phdr->p_type = PT_NOTE;
+ phdr->p_offset = hdrsize;
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = notesz;
+ phdr->p_memsz = 0;
+ phdr->p_flags = PF_R;
+ phdr->p_align = sizeof(Elf32_Size);
+ phdr++;
+
+ /* All the writable segments from the program. */
+ phc.phdr = phdr;
+ phc.offset = segoff;
+ each_dumpable_segment(map, cb_put_phdr, &phc);
+}
+
+/*
+ * Free the memory map.
+ */
+static void
+freemap(struct map_entry *map)
+{
+ struct map_entry *next;
+
+ while (map != NULL) {
+ next = map->next;
+ free(map);
+ map = next;
+ }
+}
+
+/*
+ * Read the process's memory map using kinfo_getvmmap(), and return a list of
+ * VM map entries. Only the non-device read/writable segments are
+ * returned. The map entries in the list aren't fully filled in; only
+ * the items we need are present.
+ */
+static struct map_entry *
+readmap(pid_t pid)
+{
+ struct map_entry *ent, **linkp, *map;
+ struct kinfo_vmentry *vmentl, *kve;
+ int i, nitems;
+
+ vmentl = kinfo_getvmmap(pid, &nitems);
+ if (vmentl == NULL)
+ err(1, "cannot retrieve mappings for %u process", pid);
+
+ map = NULL;
+ linkp = &map;
+ for (i = 0; i < nitems; i++) {
+ kve = &vmentl[i];
+
+ /*
+ * Ignore 'malformed' segments or ones representing memory
+ * mapping with MAP_NOCORE on.
+ * If the 'full' support is disabled, just dump the most
+ * meaningful data segments.
+ */
+ if ((kve->kve_protection & KVME_PROT_READ) == 0 ||
+ (kve->kve_flags & KVME_FLAG_NOCOREDUMP) != 0 ||
+ kve->kve_type == KVME_TYPE_DEAD ||
+ kve->kve_type == KVME_TYPE_UNKNOWN ||
+ ((pflags & PFLAGS_FULL) == 0 &&
+ kve->kve_type != KVME_TYPE_DEFAULT &&
+ kve->kve_type != KVME_TYPE_VNODE &&
+ kve->kve_type != KVME_TYPE_SWAP &&
+ kve->kve_type != KVME_TYPE_PHYS))
+ continue;
+
+ ent = calloc(1, sizeof(*ent));
+ if (ent == NULL)
+ errx(1, "out of memory");
+ ent->start = (vm_offset_t)kve->kve_start;
+ ent->end = (vm_offset_t)kve->kve_end;
+ ent->protection = VM_PROT_READ;
+ if ((kve->kve_protection & KVME_PROT_WRITE) != 0)
+ ent->protection |= VM_PROT_WRITE;
+ if ((kve->kve_protection & KVME_PROT_EXEC) != 0)
+ ent->protection |= VM_PROT_EXECUTE;
+
+ *linkp = ent;
+ linkp = &ent->next;
+ }
+ free(vmentl);
+ return (map);
+}
+
+/*
+ * Miscellaneous note out functions.
+ */
+
+static void *
+elf_note_prpsinfo(void *arg, size_t *sizep)
+{
+ char *cp, *end;
+ pid_t pid;
+ elfcore_prpsinfo_t *psinfo;
+ struct kinfo_proc kip;
+ size_t len;
+ int name[4];
+
+ pid = *(pid_t *)arg;
+ psinfo = calloc(1, sizeof(*psinfo));
+ if (psinfo == NULL)
+ errx(1, "out of memory");
+ psinfo->pr_version = PRPSINFO_VERSION;
+ psinfo->pr_psinfosz = sizeof(*psinfo);
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_PID;
+ name[3] = pid;
+ len = sizeof(kip);
+ if (sysctl(name, 4, &kip, &len, NULL, 0) == -1)
+ err(1, "kern.proc.pid.%u", pid);
+ if (kip.ki_pid != pid)
+ err(1, "kern.proc.pid.%u", pid);
+ strlcpy(psinfo->pr_fname, kip.ki_comm, sizeof(psinfo->pr_fname));
+ name[2] = KERN_PROC_ARGS;
+ len = sizeof(psinfo->pr_psargs) - 1;
+ if (sysctl(name, 4, psinfo->pr_psargs, &len, NULL, 0) == 0 && len > 0) {
+ cp = psinfo->pr_psargs;
+ end = cp + len - 1;
+ for (;;) {
+ cp = memchr(cp, '\0', end - cp);
+ if (cp == NULL)
+ break;
+ *cp = ' ';
+ }
+ } else
+ strlcpy(psinfo->pr_psargs, kip.ki_comm,
+ sizeof(psinfo->pr_psargs));
+ psinfo->pr_pid = pid;
+
+ *sizep = sizeof(*psinfo);
+ return (psinfo);
+}
+
+#if defined(__i386__) || defined(__amd64__)
+static void *
+elf_note_x86_xstate(void *arg, size_t *sizep)
+{
+ lwpid_t tid;
+ char *xstate;
+ static bool xsave_checked = false;
+ static struct ptrace_xstate_info info;
+
+ tid = *(lwpid_t *)arg;
+ if (!xsave_checked) {
+ if (ptrace(PT_GETXSTATE_INFO, tid, (void *)&info,
+ sizeof(info)) != 0)
+ info.xsave_len = 0;
+ xsave_checked = true;
+ }
+ if (info.xsave_len == 0) {
+ *sizep = 0;
+ return (NULL);
+ }
+ xstate = calloc(1, info.xsave_len);
+ ptrace(PT_GETXSTATE, tid, xstate, 0);
+ *(uint64_t *)(xstate + X86_XSTATE_XCR0_OFFSET) = info.xsave_mask;
+ *sizep = info.xsave_len;
+ return (xstate);
+}
+#endif
+
+#if defined(__powerpc__)
+static void *
+elf_note_powerpc_vmx(void *arg, size_t *sizep)
+{
+ lwpid_t tid;
+ struct vmxreg *vmx;
+ static bool has_vmx = true;
+ struct vmxreg info;
+
+ tid = *(lwpid_t *)arg;
+ if (has_vmx) {
+ if (ptrace(PT_GETVRREGS, tid, (void *)&info,
+ sizeof(info)) != 0)
+ has_vmx = false;
+ }
+ if (!has_vmx) {
+ *sizep = 0;
+ return (NULL);
+ }
+ vmx = calloc(1, sizeof(*vmx));
+ memcpy(vmx, &info, sizeof(*vmx));
+ *sizep = sizeof(*vmx);
+ return (vmx);
+}
+
+static void *
+elf_note_powerpc_vsx(void *arg, size_t *sizep)
+{
+ lwpid_t tid;
+ char *vshr_data;
+ static bool has_vsx = true;
+ uint64_t vshr[32];
+
+ tid = *(lwpid_t *)arg;
+ if (has_vsx) {
+ if (ptrace(PT_GETVSRREGS, tid, (void *)vshr,
+ sizeof(vshr)) != 0)
+ has_vsx = false;
+ }
+ if (!has_vsx) {
+ *sizep = 0;
+ return (NULL);
+ }
+ vshr_data = calloc(1, sizeof(vshr));
+ memcpy(vshr_data, vshr, sizeof(vshr));
+ *sizep = sizeof(vshr);
+ return (vshr_data);
+}
+#endif
+
+static void *
+procstat_sysctl(void *arg, int what, size_t structsz, size_t *sizep)
+{
+ size_t len;
+ pid_t pid;
+ int name[4], structsize;
+ void *buf, *p;
+
+ pid = *(pid_t *)arg;
+ structsize = structsz;
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = what;
+ name[3] = pid;
+ len = 0;
+ if (sysctl(name, 4, NULL, &len, NULL, 0) == -1)
+ err(1, "kern.proc.%d.%u", what, pid);
+ buf = calloc(1, sizeof(structsize) + len * 4 / 3);
+ if (buf == NULL)
+ errx(1, "out of memory");
+ bcopy(&structsize, buf, sizeof(structsize));
+ p = (char *)buf + sizeof(structsize);
+ if (sysctl(name, 4, p, &len, NULL, 0) == -1)
+ err(1, "kern.proc.%d.%u", what, pid);
+
+ *sizep = sizeof(structsize) + len;
+ return (buf);
+}
+
+static void *
+elf_note_procstat_proc(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ sizeof(struct kinfo_proc), sizep));
+}
+
+static void *
+elf_note_procstat_files(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_FILEDESC,
+ sizeof(struct kinfo_file), sizep));
+}
+
+static void *
+elf_note_procstat_vmmap(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_VMMAP,
+ sizeof(struct kinfo_vmentry), sizep));
+}
+
+static void *
+elf_note_procstat_groups(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_GROUPS, sizeof(gid_t), sizep));
+}
+
+static void *
+elf_note_procstat_umask(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_UMASK, sizeof(u_short), sizep));
+}
+
+static void *
+elf_note_procstat_osrel(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_OSREL, sizeof(int), sizep));
+}
+
+static void *
+elf_note_procstat_psstrings(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_PS_STRINGS,
+ sizeof(vm_offset_t), sizep));
+}
+
+static void *
+elf_note_procstat_auxv(void *arg, size_t *sizep)
+{
+
+ return (procstat_sysctl(arg, KERN_PROC_AUXV,
+ sizeof(Elf_Auxinfo), sizep));
+}
+
+static void *
+elf_note_procstat_rlimit(void *arg, size_t *sizep)
+{
+ pid_t pid;
+ size_t len;
+ int i, name[5], structsize;
+ void *buf, *p;
+
+ pid = *(pid_t *)arg;
+ structsize = sizeof(struct rlimit) * RLIM_NLIMITS;
+ buf = calloc(1, sizeof(structsize) + structsize);
+ if (buf == NULL)
+ errx(1, "out of memory");
+ bcopy(&structsize, buf, sizeof(structsize));
+ p = (char *)buf + sizeof(structsize);
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_RLIMIT;
+ name[3] = pid;
+ len = sizeof(struct rlimit);
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ name[4] = i;
+ if (sysctl(name, 5, p, &len, NULL, 0) == -1)
+ err(1, "kern.proc.rlimit.%u", pid);
+ if (len != sizeof(struct rlimit))
+ errx(1, "kern.proc.rlimit.%u: short read", pid);
+ p += len;
+ }
+
+ *sizep = sizeof(structsize) + structsize;
+ return (buf);
+}
+
+struct dumpers __elfN(dump) = { elf_ident, elf_coredump };
+TEXT_SET(dumpset, __elfN(dump));
diff --git a/usr.bin/gcore/extern.h b/usr.bin/gcore/extern.h
new file mode 100644
index 000000000000..9044c7d9dd8c
--- /dev/null
+++ b/usr.bin/gcore/extern.h
@@ -0,0 +1,38 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+#define PFLAGS_FULL 0x01
+
+struct dumpers {
+ int (*ident)(int efd, pid_t pid, char *binfile);
+ void (*dump)(int efd, int fd, pid_t pid);
+};
+extern int pflags;
diff --git a/usr.bin/gcore/gcore.1 b/usr.bin/gcore/gcore.1
new file mode 100644
index 000000000000..931adb27a77b
--- /dev/null
+++ b/usr.bin/gcore/gcore.1
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd April 24, 2021
+.Dt GCORE 1
+.Os
+.Sh NAME
+.Nm gcore
+.Nd get core images of running process
+.Sh SYNOPSIS
+.Nm
+.Op Fl f
+.Op Fl k
+.Op Fl c Ar core
+.Op Ar executable
+.Ar pid
+.Sh DESCRIPTION
+The
+.Nm
+utility creates a core image of the specified process,
+suitable for use with
+.Xr gdb 1 Pq Pa ports/devel/gdb .
+By default, the core is written to the file
+.Dq Pa core.<pid> .
+The process identifier,
+.Ar pid ,
+must be given on the command line.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Write the core file to the specified file instead of
+.Dq Pa core.<pid> .
+.It Fl f
+Dumps all available segments, excluding only malformed and undumpable
+segments.
+Unlike the default invocation, this flag dumps mappings of devices which
+may invalidate the state of device transactions or trigger other unexpected
+behavior.
+As a result, this flag should only be used when the behavior of the
+application and any devices it has mapped is fully understood and any side
+effects can be controlled or tolerated.
+.It Fl k
+Use the
+.Xr ptrace 2
+.Dv PT_COREDUMP
+kernel facility to write the core dump, instead of reading the process'
+memory and constructing the dump file in
+.Nm
+itself.
+This is faster, and the dump is written by the
+same kernel code that writes core dumps upon fatal signals.
+.El
+.Sh FILES
+.Bl -tag -width /var/log/messages -compact
+.It Pa core.<pid>
+the core image
+.El
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.Bx 4.2 .
+.Sh BUGS
+Because of the
+.Xr ptrace 2
+usage
+.Nm
+may not work with processes which are actively being investigated with
+.Xr truss 1
+or
+.Xr gdb 1 Pq Pa ports/devel/gdb .
+Additionally, interruptable sleeps may exit with EINTR.
+.Pp
+The
+.Nm
+utility is not compatible with the original
+.Bx 4.2
+version.
diff --git a/usr.bin/gcore/gcore.c b/usr.bin/gcore/gcore.c
new file mode 100644
index 000000000000..956d012d04d0
--- /dev/null
+++ b/usr.bin/gcore/gcore.c
@@ -0,0 +1,213 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+/*
+ * Originally written by Eric Cooper in Fall 1981.
+ * Inspired by a version 6 program by Len Levin, 1978.
+ * Several pieces of code lifted from Bill Joy's 4BSD ps.
+ * Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
+ * Lawrence Berkeley Laboratory.
+ *
+ * Portions of this software were developed by the Computer Systems
+ * Engineering group at Lawrence Berkeley Laboratory under DARPA
+ * contract BG 91-66 and contributed to Berkeley.
+ */
+
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/linker_set.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+int pflags;
+
+static void killed(int);
+static void usage(void) __dead2;
+
+static pid_t pid;
+static bool kflag = false;
+
+SET_DECLARE(dumpset, struct dumpers);
+
+static int
+open_corefile(char *corefile)
+{
+ char fname[MAXPATHLEN];
+ int fd;
+
+ if (corefile == NULL) {
+ (void)snprintf(fname, sizeof(fname), "core.%d", pid);
+ corefile = fname;
+ }
+ fd = open(corefile, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+ if (fd < 0)
+ err(1, "%s", corefile);
+ return (fd);
+}
+
+static void
+kcoredump(int fd, pid_t pid)
+{
+ struct ptrace_coredump pc;
+ int error, res, ret, waited;
+
+ error = ptrace(PT_ATTACH, pid, NULL, 0);
+ if (error != 0)
+ err(1, "attach");
+
+ waited = waitpid(pid, &res, 0);
+ if (waited == -1)
+ err(1, "wait for STOP");
+
+ ret = 0;
+ memset(&pc, 0, sizeof(pc));
+ pc.pc_fd = fd;
+ pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0;
+ error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc));
+ if (error == -1) {
+ warn("coredump");
+ ret = 1;
+ }
+
+ waited = waitpid(pid, &res, WNOHANG);
+ if (waited == -1) {
+ warn("wait after coredump");
+ ret = 1;
+ }
+
+ error = ptrace(PT_DETACH, pid, NULL, 0);
+ if (error == -1) {
+ warn("detach failed, check process status");
+ ret = 1;
+ }
+
+ exit(ret);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, efd, fd, name[4];
+ char *binfile, *corefile;
+ char passpath[MAXPATHLEN];
+ struct dumpers **d, *dumper;
+ size_t len;
+
+ pflags = 0;
+ corefile = NULL;
+ while ((ch = getopt(argc, argv, "c:fk")) != -1) {
+ switch (ch) {
+ case 'c':
+ corefile = optarg;
+ break;
+ case 'f':
+ pflags |= PFLAGS_FULL;
+ break;
+ case 'k':
+ kflag = true;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ /* XXX we should check that the pid argument is really a number */
+ switch (argc) {
+ case 1:
+ pid = atoi(argv[0]);
+ break;
+ case 2:
+ binfile = argv[0];
+ pid = atoi(argv[1]);
+ break;
+ default:
+ usage();
+ }
+
+ if (kflag) {
+ fd = open_corefile(corefile);
+ kcoredump(fd, pid);
+ }
+
+ if (argc == 1) {
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_PATHNAME;
+ name[3] = pid;
+ len = sizeof(passpath);
+ if (sysctl(name, 4, passpath, &len, NULL, 0) == -1)
+ errx(1, "kern.proc.pathname failure");
+ binfile = passpath;
+ }
+ efd = open(binfile, O_RDONLY, 0);
+ if (efd < 0)
+ err(1, "%s", binfile);
+ dumper = NULL;
+ SET_FOREACH(d, dumpset) {
+ lseek(efd, 0, SEEK_SET);
+ if (((*d)->ident)(efd, pid, binfile)) {
+ dumper = (*d);
+ lseek(efd, 0, SEEK_SET);
+ break;
+ }
+ }
+ if (dumper == NULL)
+ errx(1, "Invalid executable file");
+ fd = open_corefile(corefile);
+
+ dumper->dump(efd, fd, pid);
+ (void)close(fd);
+ (void)close(efd);
+ exit(0);
+}
+
+void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: gcore [-kf] [-c core] [executable] pid\n");
+ exit(1);
+}
diff --git a/usr.bin/gencat/Makefile b/usr.bin/gencat/Makefile
new file mode 100644
index 000000000000..3fabbff02c40
--- /dev/null
+++ b/usr.bin/gencat/Makefile
@@ -0,0 +1,3 @@
+PROG= gencat
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gencat/Makefile.depend b/usr.bin/gencat/Makefile.depend
new file mode 100644
index 000000000000..344a5d0e9310
--- /dev/null
+++ b/usr.bin/gencat/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gencat/gencat.1 b/usr.bin/gencat/gencat.1
new file mode 100644
index 000000000000..7096911ca607
--- /dev/null
+++ b/usr.bin/gencat/gencat.1
@@ -0,0 +1,189 @@
+.\" $OpenBSD: gencat.1,v 1.3 1997/06/11 15:39:54 kstailey Exp $
+.\"
+.\" Copyright (c) 1997 Ken Stailey
+.\"
+.\" 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.
+.\"
+.Dd June 11, 1997
+.Dt GENCAT 1
+.Os
+.Sh NAME
+.Nm gencat
+.Nd NLS catalog compiler
+.Sh SYNOPSIS
+.Nm
+.Ar "output-file"
+.Ar "input-files..."
+.Sh DESCRIPTION
+The
+.Nm
+utility merges the text NLS input files
+.Ar "input-files..."
+into a formatted message catalog file
+.Ar "output-file" .
+The file
+.Ar "output-file"
+will be created if it does not already exist.
+If
+.Ar "output-file"
+does exist, its messages will be included in the new
+.Ar "output-file" .
+If set and message numbers collide, the new message text defined in
+.Ar "input-files..."
+will replace the old message text currently contained in
+.Ar "output-file" .
+.Sh INPUT FILES
+The format of a message text source file is defined below.
+Note that
+the fields of a message text source line are separated by a single space
+character: any other space characters are considered to be part of the
+field contents.
+.Bl -tag -width 3n
+.It Li $set Ar n comment
+This line specifies the set identifier of the following messages until
+the next
+.Li $set
+or end-of-file appears.
+The argument
+.Ar n
+is the set identifier which is defined as a number in the range
+[1, (NL_SETMAX)].
+Set identifiers must occur in ascending order within
+a single source file, but need not be contiguous.
+Any string following
+a space following the set identifier is treated as a comment.
+If no
+.Li $set
+directive is specified in a given source file, all messages will
+be located in the default message set NL_SETD.
+.It Li $del Ar n comment
+This line deletes messages from set
+.Ar n
+from a message catalog.
+The
+.Ar n
+specifies a set number.
+Any string following a space following the set
+number is treated as a comment.
+.It Li $ Ar comment
+A line beginning with
+.Li $
+followed by a space is treated as a comment.
+.It Ar m message-text
+A message line consists of a message identifier
+.Ar m
+in the range [1, (NL_MSGMAX)].
+The
+.Ar message-text
+is stored in the message catalog with the set identifier specified by
+the last
+.Li $set
+directive, and the message identifier
+.Ar m .
+If the
+.Ar message-text
+is empty, and there is a space character following the message identifier,
+an empty string is stored in the message catalog.
+If the
+.Ar message-text
+is empty, and if there is no space character following the message
+identifier, then the existing message in the current set with the
+specified message identifier is deleted from the catalog.
+Message
+identifiers must be in ascending order within a single set, but
+need not be contiguous.
+The
+.Ar message-text
+length must be in the range [0, (NL_TEXTMAX)].
+.It Li $quote Ar c
+This line specifies an optional quote character
+.Ar c
+which can be used to surround
+.Ar message-text
+so that trailing space or empty messages are visible in message
+source files.
+By default, or if an empty
+.Li $quote
+directive is specified, no quoting of
+.Ar message-text
+will be recognized.
+.El
+.Pp
+Empty lines in message source files are ignored.
+The effect of lines
+beginning with any character other than those described above is
+undefined.
+.Pp
+Text strings can contain the following special characters and escape
+sequences.
+In addition, if a quote character is defined, it may be
+escaped as well to embed a literal quote character.
+.Pp
+.Bl -tag -width "\eooo" -offset indent -compact
+.It Li \en
+line feed
+.It Li \et
+horizontal tab
+.It Li \ev
+vertical tab
+.It Li \eb
+backspace
+.It Li \er
+carriage return
+.It Li \ef
+form feed
+.It Li \e\e
+backslash
+.It Li \eooo
+octal number in the range [000, 377]
+.El
+.Pp
+A backslash character immediately before the end of the line in a file
+is used to continue the line onto the next line, e.g.:
+.Pp
+.Dl 1 This line is continued \e
+.Dl on this line.
+.Pp
+If the character following the backslash is not one of those specified,
+the backslash is ignored.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr catclose 3 ,
+.Xr catgets 3 ,
+.Xr catopen 3
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -xpg4
+standard.
+.Sh AUTHORS
+.An -nosplit
+This manual page was originally written by
+.An Ken Stailey
+and later revised by
+.An Terry Lambert .
+.Sh BUGS
+A message catalog file created from a blank input file cannot be revised;
+it must be deleted and recreated.
diff --git a/usr.bin/gencat/gencat.c b/usr.bin/gencat/gencat.c
new file mode 100644
index 000000000000..d618c49fcc32
--- /dev/null
+++ b/usr.bin/gencat/gencat.c
@@ -0,0 +1,694 @@
+/* ex:ts=4
+ */
+
+/* $NetBSD: gencat.c,v 1.18 2003/10/27 00:12:43 lukem Exp $ */
+
+/*-
+ * SPDX-License-Identifier: (BSD-2-Clause AND ISC)
+ *
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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.
+ */
+
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that Alfalfa's name not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.
+
+ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+If you make any modifications, bugfixes or other changes to this software
+we'd appreciate it if you could send a copy to us so we can keep things
+up-to-date. Many thanks.
+ Kee Hinckley
+ Alfalfa Software, Inc.
+ 267 Allston St., #3
+ Cambridge, MA 02139 USA
+ nazgul@alfalfa.com
+
+******************************************************************/
+
+#include <sys/cdefs.h>
+#define _NLS_PRIVATE
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <arpa/inet.h> /* for htonl() */
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <nl_types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct _msgT {
+ long msgId;
+ char *str;
+ LIST_ENTRY(_msgT) entries;
+};
+
+struct _setT {
+ long setId;
+ LIST_HEAD(msghead, _msgT) msghead;
+ LIST_ENTRY(_setT) entries;
+};
+
+static LIST_HEAD(sethead, _setT) sethead;
+static struct _setT *curSet;
+
+static char *curline = NULL;
+static long lineno = 0;
+
+static char *cskip(char *);
+static void error(const char *);
+static char *get_line(int);
+static char *getmsg(int, char *, char);
+static void warning(const char *, const char *);
+static char *wskip(char *);
+static char *xstrdup(const char *);
+static void *xmalloc(size_t);
+static void *xrealloc(void *, size_t);
+
+void MCParse(int);
+void MCReadCat(int);
+void MCWriteCat(int);
+void MCDelMsg(int);
+void MCAddMsg(int, const char *);
+void MCAddSet(int);
+void MCDelSet(int);
+void usage(void);
+int main(int, char **);
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: %s catfile msgfile ...\n", getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ofd, ifd;
+ char *catfile = NULL;
+ int c;
+
+#define DEPRECATEDMSG 1
+
+#ifdef DEPRECATEDMSG
+ while ((c = getopt(argc, argv, "new")) != -1) {
+#else
+ while ((c = getopt(argc, argv, "")) != -1) {
+#endif
+ switch (c) {
+#ifdef DEPRECATEDMSG
+ case 'n':
+ fprintf(stderr, "WARNING: Usage of \"-new\" argument is deprecated.\n");
+ case 'e':
+ case 'w':
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2) {
+ usage();
+ /* NOTREACHED */
+ }
+ catfile = *argv++;
+
+ for (; *argv; argv++) {
+ if ((ifd = open(*argv, O_RDONLY)) < 0)
+ err(1, "Unable to read %s", *argv);
+ MCParse(ifd);
+ close(ifd);
+ }
+
+ if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0)
+ err(1, "Unable to create a new %s", catfile);
+ MCWriteCat(ofd);
+ exit(0);
+}
+
+static void
+warning(const char *cptr, const char *msg)
+{
+ fprintf(stderr, "%s: %s on line %ld\n", getprogname(), msg, lineno);
+ fprintf(stderr, "%s\n", curline);
+ if (cptr) {
+ char *tptr;
+ for (tptr = curline; tptr < cptr; ++tptr)
+ putc(' ', stderr);
+ fprintf(stderr, "^\n");
+ }
+}
+
+#define CORRUPT() { error("corrupt message catalog"); }
+#define NOMEM() { error("out of memory"); }
+
+static void
+error(const char *msg)
+{
+ warning(NULL, msg);
+ exit(1);
+}
+
+static void *
+xmalloc(size_t len)
+{
+ void *p;
+
+ if ((p = malloc(len)) == NULL)
+ NOMEM();
+ return (p);
+}
+
+static void *
+xrealloc(void *ptr, size_t size)
+{
+ if ((ptr = realloc(ptr, size)) == NULL)
+ NOMEM();
+ return (ptr);
+}
+
+static char *
+xstrdup(const char *str)
+{
+ char *nstr;
+
+ if ((nstr = strdup(str)) == NULL)
+ NOMEM();
+ return (nstr);
+}
+
+static char *
+get_line(int fd)
+{
+ static long curlen = BUFSIZ;
+ static char buf[BUFSIZ], *bptr = buf, *bend = buf;
+ char *cptr, *cend;
+ long buflen;
+
+ if (!curline) {
+ curline = xmalloc(curlen);
+ }
+ ++lineno;
+
+ cptr = curline;
+ cend = curline + curlen;
+ for (;;) {
+ for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
+ if (*bptr == '\n') {
+ *cptr = '\0';
+ ++bptr;
+ return (curline);
+ } else
+ *cptr = *bptr;
+ }
+ if (cptr == cend) {
+ cptr = curline = xrealloc(curline, curlen *= 2);
+ cend = curline + curlen;
+ }
+ if (bptr == bend) {
+ buflen = read(fd, buf, BUFSIZ);
+ if (buflen <= 0) {
+ if (cptr > curline) {
+ *cptr = '\0';
+ return (curline);
+ }
+ return (NULL);
+ }
+ bend = buf + buflen;
+ bptr = buf;
+ }
+ }
+}
+
+static char *
+wskip(char *cptr)
+{
+ if (!*cptr || !isspace((unsigned char) *cptr)) {
+ warning(cptr, "expected a space");
+ return (cptr);
+ }
+ while (*cptr && isspace((unsigned char) *cptr))
+ ++cptr;
+ return (cptr);
+}
+
+static char *
+cskip(char *cptr)
+{
+ if (!*cptr || isspace((unsigned char) *cptr)) {
+ warning(cptr, "wasn't expecting a space");
+ return (cptr);
+ }
+ while (*cptr && !isspace((unsigned char) *cptr))
+ ++cptr;
+ return (cptr);
+}
+
+static char *
+getmsg(int fd, char *cptr, char quote)
+{
+ static char *msg = NULL;
+ static long msglen = 0;
+ long clen, i;
+ char *tptr;
+
+ if (quote && *cptr == quote) {
+ ++cptr;
+ }
+
+ clen = strlen(cptr) + 1;
+ if (clen > msglen) {
+ if (msglen)
+ msg = xrealloc(msg, clen);
+ else
+ msg = xmalloc(clen);
+ msglen = clen;
+ }
+ tptr = msg;
+
+ while (*cptr) {
+ if (quote && *cptr == quote) {
+ char *tmp;
+ tmp = cptr + 1;
+ if (*tmp && (!isspace((unsigned char) *tmp) || *wskip(tmp))) {
+ warning(cptr, "unexpected quote character, ignoring");
+ *tptr++ = *cptr++;
+ } else {
+ *cptr = '\0';
+ }
+ } else
+ if (*cptr == '\\') {
+ ++cptr;
+ switch (*cptr) {
+ case '\0':
+ cptr = get_line(fd);
+ if (!cptr)
+ error("premature end of file");
+ msglen += strlen(cptr);
+ i = tptr - msg;
+ msg = xrealloc(msg, msglen);
+ tptr = msg + i;
+ break;
+
+ #define CASEOF(CS, CH) \
+ case CS: \
+ *tptr++ = CH; \
+ ++cptr; \
+ break; \
+
+ CASEOF('n', '\n');
+ CASEOF('t', '\t');
+ CASEOF('v', '\v');
+ CASEOF('b', '\b');
+ CASEOF('r', '\r');
+ CASEOF('f', '\f');
+ CASEOF('"', '"');
+ CASEOF('\\', '\\');
+
+ default:
+ if (quote && *cptr == quote) {
+ *tptr++ = *cptr++;
+ } else if (isdigit((unsigned char) *cptr)) {
+ *tptr = 0;
+ for (i = 0; i < 3; ++i) {
+ if (!isdigit((unsigned char) *cptr))
+ break;
+ if (*cptr > '7')
+ warning(cptr, "octal number greater than 7?!");
+ *tptr *= 8;
+ *tptr += (*cptr - '0');
+ ++cptr;
+ }
+ } else {
+ warning(cptr, "unrecognized escape sequence");
+ }
+ break;
+ }
+ } else {
+ *tptr++ = *cptr++;
+ }
+ }
+ *tptr = '\0';
+ return (msg);
+}
+
+void
+MCParse(int fd)
+{
+ char *cptr, *str;
+ int setid, msgid = 0;
+ char quote = 0;
+
+ /* XXX: init sethead? */
+
+ while ((cptr = get_line(fd))) {
+ if (*cptr == '$') {
+ ++cptr;
+ if (strncmp(cptr, "set", 3) == 0) {
+ cptr += 3;
+ cptr = wskip(cptr);
+ setid = atoi(cptr);
+ MCAddSet(setid);
+ msgid = 0;
+ } else if (strncmp(cptr, "delset", 6) == 0) {
+ cptr += 6;
+ cptr = wskip(cptr);
+ setid = atoi(cptr);
+ MCDelSet(setid);
+ } else if (strncmp(cptr, "quote", 5) == 0) {
+ cptr += 5;
+ if (!*cptr)
+ quote = 0;
+ else {
+ cptr = wskip(cptr);
+ if (!*cptr)
+ quote = 0;
+ else
+ quote = *cptr;
+ }
+ } else if (isspace((unsigned char) *cptr)) {
+ ;
+ } else {
+ if (*cptr) {
+ cptr = wskip(cptr);
+ if (*cptr)
+ warning(cptr, "unrecognized line");
+ }
+ }
+ } else {
+ /*
+ * First check for (and eat) empty lines....
+ */
+ if (!*cptr)
+ continue;
+ /*
+ * We have a digit? Start of a message. Else,
+ * syntax error.
+ */
+ if (isdigit((unsigned char) *cptr)) {
+ msgid = atoi(cptr);
+ cptr = cskip(cptr);
+ cptr = wskip(cptr);
+ /* if (*cptr) ++cptr; */
+ } else {
+ warning(cptr, "neither blank line nor start of a message id");
+ continue;
+ }
+ /*
+ * If we have a message ID, but no message,
+ * then this means "delete this message id
+ * from the catalog".
+ */
+ if (!*cptr) {
+ MCDelMsg(msgid);
+ } else {
+ str = getmsg(fd, cptr, quote);
+ MCAddMsg(msgid, str);
+ }
+ }
+ }
+}
+
+/*
+ * Write message catalog.
+ *
+ * The message catalog is first converted from its internal to its
+ * external representation in a chunk of memory allocated for this
+ * purpose. Then the completed catalog is written. This approach
+ * avoids additional housekeeping variables and/or a lot of seeks
+ * that would otherwise be required.
+ */
+void
+MCWriteCat(int fd)
+{
+ int nsets; /* number of sets */
+ int nmsgs; /* number of msgs */
+ int string_size; /* total size of string pool */
+ int msgcat_size; /* total size of message catalog */
+ void *msgcat; /* message catalog data */
+ struct _nls_cat_hdr *cat_hdr;
+ struct _nls_set_hdr *set_hdr;
+ struct _nls_msg_hdr *msg_hdr;
+ char *strings;
+ struct _setT *set;
+ struct _msgT *msg;
+ int msg_index;
+ int msg_offset;
+
+ /* determine number of sets, number of messages, and size of the
+ * string pool */
+ nsets = 0;
+ nmsgs = 0;
+ string_size = 0;
+
+ for (set = sethead.lh_first; set != NULL;
+ set = set->entries.le_next) {
+ nsets++;
+
+ for (msg = set->msghead.lh_first; msg != NULL;
+ msg = msg->entries.le_next) {
+ nmsgs++;
+ string_size += strlen(msg->str) + 1;
+ }
+ }
+
+#ifdef DEBUG
+ printf("number of sets: %d\n", nsets);
+ printf("number of msgs: %d\n", nmsgs);
+ printf("string pool size: %d\n", string_size);
+#endif
+
+ /* determine size and then allocate buffer for constructing external
+ * message catalog representation */
+ msgcat_size = sizeof(struct _nls_cat_hdr)
+ + (nsets * sizeof(struct _nls_set_hdr))
+ + (nmsgs * sizeof(struct _nls_msg_hdr))
+ + string_size;
+
+ msgcat = xmalloc(msgcat_size);
+ memset(msgcat, '\0', msgcat_size);
+
+ /* fill in msg catalog header */
+ cat_hdr = (struct _nls_cat_hdr *) msgcat;
+ cat_hdr->__magic = htonl(_NLS_MAGIC);
+ cat_hdr->__nsets = htonl(nsets);
+ cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr));
+ cat_hdr->__msg_hdr_offset =
+ htonl(nsets * sizeof(struct _nls_set_hdr));
+ cat_hdr->__msg_txt_offset =
+ htonl(nsets * sizeof(struct _nls_set_hdr) +
+ nmsgs * sizeof(struct _nls_msg_hdr));
+
+ /* compute offsets for set & msg header tables and string pool */
+ set_hdr = (struct _nls_set_hdr *)(void *)((char *)msgcat +
+ sizeof(struct _nls_cat_hdr));
+ msg_hdr = (struct _nls_msg_hdr *)(void *)((char *)msgcat +
+ sizeof(struct _nls_cat_hdr) +
+ nsets * sizeof(struct _nls_set_hdr));
+ strings = (char *) msgcat +
+ sizeof(struct _nls_cat_hdr) +
+ nsets * sizeof(struct _nls_set_hdr) +
+ nmsgs * sizeof(struct _nls_msg_hdr);
+
+ msg_index = 0;
+ msg_offset = 0;
+ for (set = sethead.lh_first; set != NULL;
+ set = set->entries.le_next) {
+
+ nmsgs = 0;
+ for (msg = set->msghead.lh_first; msg != NULL;
+ msg = msg->entries.le_next) {
+ int msg_len = strlen(msg->str) + 1;
+
+ msg_hdr->__msgno = htonl(msg->msgId);
+ msg_hdr->__msglen = htonl(msg_len);
+ msg_hdr->__offset = htonl(msg_offset);
+
+ memcpy(strings, msg->str, msg_len);
+ strings += msg_len;
+ msg_offset += msg_len;
+
+ nmsgs++;
+ msg_hdr++;
+ }
+
+ set_hdr->__setno = htonl(set->setId);
+ set_hdr->__nmsgs = htonl(nmsgs);
+ set_hdr->__index = htonl(msg_index);
+ msg_index += nmsgs;
+ set_hdr++;
+ }
+
+ /* write out catalog. XXX: should this be done in small chunks? */
+ write(fd, msgcat, msgcat_size);
+}
+
+void
+MCAddSet(int setId)
+{
+ struct _setT *p, *q;
+
+ if (setId <= 0) {
+ error("setId's must be greater than zero");
+ /* NOTREACHED */
+ }
+ if (setId > NL_SETMAX) {
+ error("setId exceeds limit");
+ /* NOTREACHED */
+ }
+
+ p = sethead.lh_first;
+ q = NULL;
+ for (; p != NULL && p->setId < setId; q = p, p = p->entries.le_next);
+
+ if (p && p->setId == setId) {
+ ;
+ } else {
+ p = xmalloc(sizeof(struct _setT));
+ memset(p, '\0', sizeof(struct _setT));
+ LIST_INIT(&p->msghead);
+
+ p->setId = setId;
+
+ if (q == NULL) {
+ LIST_INSERT_HEAD(&sethead, p, entries);
+ } else {
+ LIST_INSERT_AFTER(q, p, entries);
+ }
+ }
+
+ curSet = p;
+}
+
+void
+MCAddMsg(int msgId, const char *str)
+{
+ struct _msgT *p, *q;
+
+ if (!curSet)
+ error("can't specify a message when no set exists");
+
+ if (msgId <= 0) {
+ error("msgId's must be greater than zero");
+ /* NOTREACHED */
+ }
+ if (msgId > NL_MSGMAX) {
+ error("msgID exceeds limit");
+ /* NOTREACHED */
+ }
+
+ p = curSet->msghead.lh_first;
+ q = NULL;
+ for (; p != NULL && p->msgId < msgId; q = p, p = p->entries.le_next);
+
+ if (p && p->msgId == msgId) {
+ free(p->str);
+ } else {
+ p = xmalloc(sizeof(struct _msgT));
+ memset(p, '\0', sizeof(struct _msgT));
+
+ if (q == NULL) {
+ LIST_INSERT_HEAD(&curSet->msghead, p, entries);
+ } else {
+ LIST_INSERT_AFTER(q, p, entries);
+ }
+ }
+
+ p->msgId = msgId;
+ p->str = xstrdup(str);
+}
+
+void
+MCDelSet(int setId)
+{
+ struct _setT *set;
+ struct _msgT *msg;
+
+ set = sethead.lh_first;
+ for (; set != NULL && set->setId < setId; set = set->entries.le_next);
+
+ if (set && set->setId == setId) {
+
+ msg = set->msghead.lh_first;
+ while (msg) {
+ free(msg->str);
+ LIST_REMOVE(msg, entries);
+ }
+
+ LIST_REMOVE(set, entries);
+ return;
+ }
+ warning(NULL, "specified set doesn't exist");
+}
+
+void
+MCDelMsg(int msgId)
+{
+ struct _msgT *msg;
+
+ if (!curSet)
+ error("you can't delete a message before defining the set");
+
+ msg = curSet->msghead.lh_first;
+ for (; msg != NULL && msg->msgId < msgId; msg = msg->entries.le_next);
+
+ if (msg && msg->msgId == msgId) {
+ free(msg->str);
+ LIST_REMOVE(msg, entries);
+ return;
+ }
+ warning(NULL, "specified msg doesn't exist");
+}
diff --git a/usr.bin/genl/Makefile b/usr.bin/genl/Makefile
new file mode 100644
index 000000000000..8ab5919b1486
--- /dev/null
+++ b/usr.bin/genl/Makefile
@@ -0,0 +1,4 @@
+PROG= genl
+SRCS= genl.c parser_rpc.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/genl/genl.1 b/usr.bin/genl/genl.1
new file mode 100644
index 000000000000..df9e5984f938
--- /dev/null
+++ b/usr.bin/genl/genl.1
@@ -0,0 +1,72 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+.\"
+.\" Copyright (c) 2023 Baptiste Daroussin <bapt@nours.eu>
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 Oct 5, 2024
+.Dt GENL 1
+.Os
+.Sh NAME
+.Nm genl
+.Nd "generic netlink"
+.Sh SYNOPSIS
+.Nm
+.Pp
+.Nm Cm list
+.Pp
+.Nm Cm monitor Ao family Ac
+.Op multicast group
+.Sh DESCRIPTION
+The
+.Nm
+utility provides user access to generic netlink protocols.
+.Pp
+The following commands are available:
+.Bl -tag -width indent
+.It Cm list Po default Pc
+Lists all available generic netlink protocols, and presents its details:
+.Bl -tag -width "multicast groups"
+.It operations
+Id of the operation if any and associated capabilities
+.It multicast groups
+Id of the available multicast group if any and it associated name
+.El
+.It Cm monitor Ao family Ac Oo multicast group Oc
+Connect to the
+.Ar family
+protocol and subscribe to the
+.Ar multicast group
+then print the received messages in a readable format if the protocol is known.
+So far only
+.Qq nlctrl
+and
+.Qq nlsysevent
+are known.
+If no
+.Ar multicast group
+are provided then all the groups are subscribed to.
+.El
+.Sh SEE ALSO
+.Xr genetlink 4 ,
+.Xr netlink 4
diff --git a/usr.bin/genl/genl.c b/usr.bin/genl/genl.c
new file mode 100644
index 000000000000..4d2c252dab98
--- /dev/null
+++ b/usr.bin/genl/genl.c
@@ -0,0 +1,440 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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 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.
+ */
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <stdio.h>
+#include <poll.h>
+
+#include <netlink/netlink.h>
+#include <netlink/netlink_generic.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_generic.h>
+#include <netlink/netlink_sysevent.h>
+
+#include "genl.h"
+
+static int monitor_mcast(int argc, char **argv);
+static int list_families(int argc, char **argv);
+
+static struct commands {
+ const char *name;
+ const char *usage;
+ int (*cmd)(int argc, char **argv);
+} cmds[] = {
+ { "monitor", "monitor <family> [multicast group]", monitor_mcast },
+ { "list", "list", list_families },
+};
+
+static monitor_parser_t parser_nlctrl_notify;
+static monitor_parser_t parser_nlsysevent;
+
+static struct mcast_parsers {
+ const char *family;
+ monitor_parser_t *parser;
+} mcast_parsers [] = {
+ { "nlctrl", parser_nlctrl_notify },
+ { "nlsysevent", parser_nlsysevent },
+ { "rpc", parser_rpc },
+};
+
+struct nlevent {
+ const char *name;
+ const char *subsystem;
+ const char *type;
+ const char *data;
+};
+#define _OUT(_field) offsetof(struct nlevent, _field)
+static struct snl_attr_parser ap_nlevent_get[] = {
+ { .type = NLSE_ATTR_SYSTEM, .off = _OUT(name), .cb = snl_attr_get_string },
+ { .type = NLSE_ATTR_SUBSYSTEM, .off = _OUT(subsystem), .cb = snl_attr_get_string },
+ { .type = NLSE_ATTR_TYPE, .off = _OUT(type), .cb = snl_attr_get_string },
+ { .type = NLSE_ATTR_DATA, .off = _OUT(data), .cb = snl_attr_get_string },
+};
+#undef _OUT
+SNL_DECLARE_GENL_PARSER(nlevent_get_parser, ap_nlevent_get);
+
+/*
+ * We run our own parser(s) for CTRL_CMD_GETFAMILY instead of interfaces
+ * provided by <netlink_snl_generic.h>. One reason is that we want the parsed
+ * string attributes to point into long living memory, instead of inside of
+ * just received message, hence we use snl_attr_get_stringn() instead of the
+ * snl_attr_get_string(). The shared library uses the latter to avoid creating
+ * ambiguous memory leaks. Second reason is that genl(1) usage of the data is
+ * more extended than typical application that cares only of its own family and
+ * usually one group. We are going to cycle around all available.
+ */
+struct genl_ctrl_op {
+ uint32_t id;
+ uint32_t flags;
+};
+struct genl_ctrl_ops {
+ uint32_t num_ops;
+ struct genl_ctrl_op **ops;
+};
+static struct snl_attr_parser nla_p_getops[] = {
+#define _OUT(_field) offsetof(struct genl_ctrl_op, _field)
+ {
+ .type = CTRL_ATTR_OP_ID,
+ .off = _OUT(id),
+ .cb = snl_attr_get_uint32
+ },
+ {
+ .type = CTRL_ATTR_OP_FLAGS,
+ .off = _OUT(flags),
+ .cb = snl_attr_get_uint32
+ },
+#undef _OUT
+};
+SNL_DECLARE_ATTR_PARSER_EXT(genl_ctrl_op_parser, sizeof(struct genl_ctrl_op),
+ nla_p_getops, NULL);
+
+struct genl_mcast_group {
+ uint32_t id;
+ const char *name;
+};
+struct genl_mcast_groups {
+ uint32_t num_groups;
+ struct genl_mcast_group **groups;
+};
+static struct snl_attr_parser nla_p_getmc[] = {
+#define _OUT(_field) offsetof(struct genl_mcast_group, _field)
+ {
+ .type = CTRL_ATTR_MCAST_GRP_NAME,
+ .off = _OUT(name),
+ .cb = snl_attr_get_stringn,
+ },
+ {
+ .type = CTRL_ATTR_MCAST_GRP_ID,
+ .off = _OUT(id),
+ .cb = snl_attr_get_uint32,
+ },
+#undef _OUT
+};
+SNL_DECLARE_ATTR_PARSER_EXT(genl_mc_parser, sizeof(struct genl_mcast_group),
+ nla_p_getmc, NULL);
+
+struct genl_family {
+ uint16_t id;
+ const char *name;
+ uint32_t version;
+ uint32_t hdrsize;
+ uint32_t max_attr;
+ struct genl_mcast_groups mcast_groups;
+ struct genl_ctrl_ops ops;
+};
+
+static struct snl_attr_parser nla_p_getfamily[] = {
+#define _OUT(_field) offsetof(struct genl_family, _field)
+ {
+ .type = CTRL_ATTR_FAMILY_ID,
+ .off = _OUT(id),
+ .cb = snl_attr_get_uint16,
+ },
+ {
+ .type = CTRL_ATTR_FAMILY_NAME,
+ .off = _OUT(name),
+ .cb = snl_attr_get_stringn,
+ },
+ {
+ .type = CTRL_ATTR_VERSION,
+ .off = _OUT(version),
+ .cb = snl_attr_get_uint32,
+ },
+ {
+ .type = CTRL_ATTR_VERSION,
+ .off = _OUT(hdrsize),
+ .cb = snl_attr_get_uint32,
+ },
+ {
+ .type = CTRL_ATTR_MAXATTR,
+ .off = _OUT(max_attr),
+ .cb = snl_attr_get_uint32,
+ },
+ {
+ .type = CTRL_ATTR_OPS,
+ .off = _OUT(ops),
+ .cb = snl_attr_get_parray,
+ .arg = &genl_ctrl_op_parser,
+ },
+ {
+ .type = CTRL_ATTR_MCAST_GROUPS,
+ .off = _OUT(mcast_groups),
+ .cb = snl_attr_get_parray,
+ .arg = &genl_mc_parser,
+ },
+#undef _OUT
+};
+SNL_DECLARE_GENL_PARSER(genl_family_parser, nla_p_getfamily);
+
+static struct op_capability {
+ uint32_t flag;
+ const char *str;
+} op_caps[] = {
+ { GENL_ADMIN_PERM, "requires admin permission" },
+ { GENL_CMD_CAP_DO, "can modify" },
+ { GENL_CMD_CAP_DUMP, "can get/dump" },
+ { GENL_CMD_CAP_HASPOL, "has policy" },
+};
+
+static void
+dump_operations(struct genl_ctrl_ops *ops)
+{
+ if (ops->num_ops == 0)
+ return;
+ printf("\tsupported operations: \n");
+ for (uint32_t i = 0; i < ops->num_ops; i++) {
+ bool p = true;
+
+ printf("\t - ID: %#02x, Capabilities: %#02x",
+ ops->ops[i]->id,
+ ops->ops[i]->flags);
+ for (size_t j = 0; j < nitems(op_caps); j++)
+ if ((ops->ops[i]->flags & op_caps[j].flag) ==
+ op_caps[j].flag) {
+ printf("%s%s", p ? " (" : "; ",
+ op_caps[j].str);
+ p = false;
+ }
+ printf("%s\n", p ? "" : ")");
+ }
+}
+
+static void
+dump_mcast_groups(struct genl_mcast_groups *mcast_groups)
+{
+ if (mcast_groups->num_groups == 0)
+ return;
+ printf("\tmulticast groups: \n");
+ for (uint32_t i = 0; i < mcast_groups->num_groups; i++)
+ printf("\t - ID: %#02x, Name: %s\n",
+ mcast_groups->groups[i]->id,
+ mcast_groups->groups[i]->name);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s\n", getprogname());
+ for (size_t i = 0; i < nitems(cmds); i++)
+ fprintf(stderr, " %s %s\n", getprogname(), cmds[i].usage);
+}
+
+static void
+dump_family(struct genl_family *family)
+{
+ printf("Name: %s\n\tID: %#02hx, Version: %#02x, "
+ "header size: %d, max attributes: %d\n",
+ family->name, family->id, family->version,
+ family->hdrsize, family->max_attr);
+ dump_operations(&family->ops);
+ dump_mcast_groups(&family->mcast_groups);
+}
+
+static void
+parser_nlctrl_notify(struct snl_state *ss, struct nlmsghdr *hdr)
+{
+ struct genl_family family = {};
+
+ if (snl_parse_nlmsg(ss, hdr, &genl_family_parser,
+ &family))
+ dump_family(&family);
+}
+
+static void
+parser_nlsysevent(struct snl_state *ss, struct nlmsghdr *hdr)
+{
+ struct nlevent ne = {};
+ if (snl_parse_nlmsg(ss, hdr, &nlevent_get_parser, &ne)) {
+ printf("system=%s subsystem=%s type=%s", ne.name, ne.subsystem, ne.type);
+ if (ne.data) {
+ printf(" %s", ne.data);
+ if (ne.data[strlen(ne.data) -1] != '\n')
+ printf("\n");
+ }
+ }
+}
+
+static void
+parser_fallback(struct snl_state *ss __unused, struct nlmsghdr *hdr)
+{
+ printf("Unknown message: type 0x%x, length %u\n",
+ hdr->nlmsg_type, hdr->nlmsg_len);
+}
+
+/* Populated by monitor_mcast() and may be used by protocol parser callbacks. */
+static struct genl_family attrs;
+
+const char *
+group_name(uint32_t id)
+{
+ for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++)
+ if (attrs.mcast_groups.groups[i]->id == id)
+ return (attrs.mcast_groups.groups[i]->name);
+ return ("???");
+}
+
+static int
+monitor_mcast(int argc, char **argv)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ struct pollfd pfd;
+ bool found = false;
+ bool all = false;
+ monitor_parser_t *parser;
+
+ if (argc < 1 || argc > 2) {
+ usage();
+ return (EXIT_FAILURE);
+ }
+
+ if (!snl_init(&ss, NETLINK_GENERIC))
+ err(EXIT_FAILURE, "snl_init()");
+ snl_init_writer(&ss, &nw);
+ snl_create_genl_msg_request(&nw, GENL_ID_CTRL, CTRL_CMD_GETFAMILY);
+ snl_add_msg_attr_string(&nw, CTRL_ATTR_FAMILY_NAME, argv[0]);
+ if ((hdr = snl_finalize_msg(&nw)) == NULL)
+ err(EXIT_FAILURE, "snl_finalize_msg");
+ if (!snl_send_message(&ss, hdr))
+ err(EXIT_FAILURE, "snl_send_message");
+ hdr = snl_read_reply(&ss, hdr->nlmsg_seq);
+ if (hdr == NULL)
+ err(EXIT_FAILURE, "snl_read_reply");
+ if (hdr->nlmsg_type == NLMSG_ERROR)
+ err(EXIT_FAILURE, "netlink(4) returned error");
+ memset(&attrs, 0, sizeof(attrs));
+ if (!snl_parse_nlmsg(&ss, hdr, &genl_family_parser, &attrs))
+ err(EXIT_FAILURE, "snl_parse_nlmsg CTRL_CMD_GETFAMILY");
+
+ if (argc == 1)
+ all = true;
+ for (u_int i = 0; i < attrs.mcast_groups.num_groups; i++) {
+ if (all ||
+ strcmp(attrs.mcast_groups.groups[i]->name, argv[1]) == 0) {
+ found = true;
+ if (setsockopt(ss.fd, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP,
+ &attrs.mcast_groups.groups[i]->id,
+ sizeof(attrs.mcast_groups.groups[i]->id))
+ == -1)
+ err(EXIT_FAILURE, "Cannot subscribe to command "
+ "notify");
+ if (!all)
+ break;
+ }
+ }
+ if (!found)
+ errx(EXIT_FAILURE, "No such multicast group '%s'"
+ " in family '%s'", argv[1], argv[0]);
+ parser = parser_fallback;
+ for (size_t i= 0; i < nitems(mcast_parsers); i++) {
+ if (strcmp(mcast_parsers[i].family, argv[0]) == 0) {
+ parser = mcast_parsers[i].parser;
+ break;
+ }
+ }
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.fd = ss.fd;
+ pfd.events = POLLIN | POLLERR;
+ while (true) {
+ pfd.revents = 0;
+ if (poll(&pfd, 1, -1) == -1) {
+ if (errno == EINTR)
+ continue;
+ err(EXIT_FAILURE, "poll()");
+ }
+ hdr = snl_read_message(&ss);
+ if (hdr != NULL && hdr->nlmsg_type != NLMSG_ERROR)
+ parser(&ss, hdr);
+
+ }
+
+ return (EXIT_SUCCESS);
+}
+
+int
+list_families(int argc, char **argv __unused)
+{
+ struct snl_state ss;
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ struct snl_errmsg_data e = {};
+ uint32_t seq_id;
+
+ if (argc != 0) {
+ usage();
+ return (EXIT_FAILURE);
+ }
+ if (!snl_init(&ss, NETLINK_GENERIC))
+ err(EXIT_FAILURE, "snl_init()");
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, GENL_ID_CTRL,
+ CTRL_CMD_GETFAMILY);
+ if ((hdr = snl_finalize_msg(&nw)) == NULL)
+ err(EXIT_FAILURE, "snl_finalize_msg");
+ seq_id = hdr->nlmsg_seq;
+ if (!snl_send_message(&ss, hdr))
+ err(EXIT_FAILURE, "snl_send_message");
+
+ while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
+ if (e.error != 0) {
+ err(EXIT_FAILURE, "Error reading generic netlink");
+ }
+ struct genl_family family = {};
+ if (snl_parse_nlmsg(&ss, hdr, &genl_family_parser, &family))
+ dump_family(&family);
+ }
+
+ return (EXIT_SUCCESS);
+}
+
+int
+main(int argc, char **argv)
+{
+ if (modfind("netlink") == -1)
+ err(EXIT_FAILURE, "require netlink module to be loaded");
+
+ if (argc == 1)
+ return (list_families(0, NULL));
+
+ for (size_t i = 0; i < nitems(cmds); i++) {
+ if (strcmp(argv[1], cmds[i].name) == 0)
+ return (cmds[i].cmd(argc - 2, argv + 2));
+ }
+ usage();
+
+ return (EXIT_FAILURE);
+}
diff --git a/usr.bin/genl/genl.h b/usr.bin/genl/genl.h
new file mode 100644
index 000000000000..7c518245440c
--- /dev/null
+++ b/usr.bin/genl/genl.h
@@ -0,0 +1,31 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2025 Gleb Smirnoff <glebius@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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 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.
+ */
+
+extern const char * group_name(uint32_t id);
+
+typedef void monitor_parser_t(struct snl_state *, struct nlmsghdr *);
+extern monitor_parser_t parser_rpc;
diff --git a/usr.bin/genl/parser_rpc.c b/usr.bin/genl/parser_rpc.c
new file mode 100644
index 000000000000..d63d1425c811
--- /dev/null
+++ b/usr.bin/genl/parser_rpc.c
@@ -0,0 +1,161 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2025 Gleb Smirnoff <glebius@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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 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.
+ */
+
+#include <stdio.h>
+#include <err.h>
+
+#include <netinet/in.h>
+
+#include <netlink/netlink.h>
+#include <netlink/netlink_generic.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_generic.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/clnt_nl.h>
+
+#include "genl.h"
+
+struct nl_request_parsed {
+ uint32_t group;
+ struct nlattr *data;
+};
+static const struct snl_attr_parser rpcnl_attr_parser[] = {
+#define OUT(field) offsetof(struct nl_request_parsed, field)
+ { .type = RPCNL_REQUEST_GROUP, .off = OUT(group),
+ .cb = snl_attr_get_uint32 },
+ { .type = RPCNL_REQUEST_BODY, .off = OUT(data), .cb = snl_attr_get_nla },
+#undef OUT
+};
+SNL_DECLARE_PARSER(request_parser, struct genlmsghdr, snl_f_p_empty,
+ rpcnl_attr_parser);
+
+void
+parser_rpc(struct snl_state *ss __unused, struct nlmsghdr *hdr)
+{
+ struct nl_request_parsed req;
+ struct genlmsghdr *ghdr = (struct genlmsghdr *)(hdr + 1);
+ XDR xdrs;
+ struct rpc_msg msg;
+ struct opaque_auth *oa;
+ int32_t *buf;
+
+ if (!snl_parse_nlmsg(NULL, hdr, &request_parser, &req))
+ errx(EXIT_FAILURE, "failed to parse RPC message");
+
+ printf("RPC %s: group %8s[0x%2x] length %4u XDR length %4u\n",
+ ghdr->cmd == RPCNL_REQUEST ? "request" : "unknown",
+ group_name(req.group), req.group,
+ hdr->nlmsg_len, NLA_DATA_LEN(req.data));
+
+ xdrmem_create(&xdrs, NLA_DATA(req.data), NLA_DATA_LEN(req.data),
+ XDR_DECODE);
+ if ((buf = XDR_INLINE(&xdrs, 8 * BYTES_PER_XDR_UNIT)) == NULL) {
+ printf("\trunt datagram\n");
+ return;
+ }
+
+ msg.rm_xid = IXDR_GET_U_INT32(buf);
+ msg.rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+ msg.rm_call.cb_rpcvers = IXDR_GET_U_INT32(buf);
+ msg.rm_call.cb_prog = IXDR_GET_U_INT32(buf);
+ msg.rm_call.cb_vers = IXDR_GET_U_INT32(buf);
+ msg.rm_call.cb_proc = IXDR_GET_U_INT32(buf);
+ printf(" %5s: xid 0x%-8x program 0x%08xv%u procedure %u\n",
+ msg.rm_direction == CALL ? "CALL" : "REPLY", msg.rm_xid,
+ msg.rm_call.cb_prog, msg.rm_call.cb_vers, msg.rm_call.cb_proc);
+
+ oa = &msg.rm_call.cb_cred;
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+ if (oa->oa_length) {
+ printf("\tcb_cred auth flavor %u length %u\n",
+ oa->oa_flavor, oa->oa_length);
+/*
+ * Excerpt from rpc_callmsg.c, if we want to parse cb_cred better.
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
+ }
+ buf = XDR_INLINE(&xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(&xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, buf,
+ oa->oa_length);
+ }
+*/
+ }
+ oa = &msg.rm_call.cb_verf;
+ buf = XDR_INLINE(&xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (xdr_enum(&xdrs, &oa->oa_flavor) == FALSE ||
+ xdr_u_int(&xdrs, &oa->oa_length) == FALSE)
+ return;
+ } else {
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+ }
+ if (oa->oa_length) {
+ printf("\tcb_verf auth flavor %u length %u\n",
+ oa->oa_flavor, oa->oa_length);
+/*
+ * Excerpt from rpc_callmsg.c, if we want to parse cb_verf better.
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
+ }
+ buf = XDR_INLINE(&xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(&xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, buf,
+ oa->oa_length);
+ }
+*/
+ }
+}
diff --git a/usr.bin/getaddrinfo/Makefile b/usr.bin/getaddrinfo/Makefile
new file mode 100644
index 000000000000..97c60d831ef9
--- /dev/null
+++ b/usr.bin/getaddrinfo/Makefile
@@ -0,0 +1,17 @@
+# $NetBSD: Makefile,v 1.2 2014/04/29 01:21:02 christos Exp $
+.include <bsd.own.mk>
+
+PROG= getaddrinfo
+SRCS= getaddrinfo.c tables.h
+
+CFLAGS+= -I${SRCTOP}/lib/libnetbsd
+
+LIBADD+= netbsd util
+
+SYS_SOCKET_H?= ${SRCTOP}/sys/sys/socket.h
+
+CFLAGS+= -I${.OBJDIR}
+CLEANFILES+= tables.h
+tables.h: tables.awk ${SYS_SOCKET_H}
+ LC_ALL=C awk -f ${.ALLSRC} > ${.TARGET}
+.include <bsd.prog.mk>
diff --git a/usr.bin/getaddrinfo/Makefile.depend b/usr.bin/getaddrinfo/Makefile.depend
new file mode 100644
index 000000000000..9e59887107e8
--- /dev/null
+++ b/usr.bin/getaddrinfo/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libnetbsd \
+ lib/libutil \
+ usr.bin/awk.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/getaddrinfo/getaddrinfo.1 b/usr.bin/getaddrinfo/getaddrinfo.1
new file mode 100644
index 000000000000..fa9e8adce6a2
--- /dev/null
+++ b/usr.bin/getaddrinfo/getaddrinfo.1
@@ -0,0 +1,180 @@
+.\" $NetBSD: getaddrinfo.1,v 1.5 2014/04/22 06:02:06 wiz Exp $
+.\"
+.\" Copyright (c) 2013 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This documentation is derived from text contributed to The NetBSD
+.\" Foundation by Taylor R. Campbell.
+.\"
+.\" 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 March 20, 2017
+.Dt GETADDRINFO 1
+.Os
+.Sh NAME
+.Nm getaddrinfo
+.Nd resolve names to socket addresses
+.Sh SYNOPSIS
+.Nm
+.Op Fl cNnP
+.Op Fl f Ar family
+.Op Fl p Ar protocol
+.Op Fl s Ar service Ns Op Ns / Ns Ar protocol
+.Op Fl t Ar socktype
+.Op Ar hostname
+.Sh DESCRIPTION
+The
+.Nm
+utility resolves host and service names to socket addresses with
+.Xr getaddrinfo 3
+and prints them to standard output in a user-friendly format.
+.Pp
+The output is a sequence of lines with space-separated fields:
+.Pp
+.Dl socket-type address-family protocol [af-specific data ...]
+.Pp
+For the
+.Dq inet
+and
+.Dq inet6
+address families, the af-specific data are the IP/IPv6 address and port
+number.
+.Pp
+Depending on the settings in
+.Xr nsswitch.conf 5 ,
+.Nm
+might query DNS for answers.
+However, it is not intended to be a general-purpose DNS query utility.
+Use
+.Xr drill 1
+for that.
+.Pp
+These options are available:
+.Bl -tag -width Ds
+.It Fl c
+Look up a canonical name as if with the
+.Dv AI_CANONNAME
+flag to
+.Xr getaddrinfo 3
+and print it on the first line before the socket addresses.
+.It Fl f Ar family
+Specify an address family.
+Address families are named like the
+.Dv AF_...
+constants for address family numbers in the
+.Aq Pa sys/socket.h
+header file but without the
+.Dv AF_
+prefix and lowercase.
+For example,
+.Dq inet
+corresponds with
+.Dv AF_INET .
+.It Fl N
+Treat the service as numeric and do not attempt service name
+resolution, as if with the
+.Dv AI_NUMERICSERV
+flag to
+.Xr getaddrinfo 3 .
+.It Fl n
+Treat the hostname as a numeric address and do not attempt name
+resolution, as if with the
+.Dv AI_NUMERICHOST
+flag to
+.Xr getaddrinfo 3 .
+.It Fl P
+Return socket addresses intended for use with
+.Xr bind 2 ,
+as if with the
+.Dv AI_PASSIVE
+flag to
+.Xr getaddrinfo 3 .
+By default, the socket addresses are intended for use with
+.Xr connect 2 ,
+.Xr sendto 2 ,
+or
+.Xr sendmsg 2 .
+.It Fl p Ar protocol
+Specify a protocol.
+Protocols are numeric or symbolic as listed in
+.Xr protocols 5 .
+.It Fl s Ar service Ns Op Ns / Ns Ar protocol
+Specify a service to look up.
+Services are symbolic or numeric with an optional
+protocol suffix as listed in
+.Xr services 5 .
+If a service is not specified, a hostname is required.
+.It Fl t Ar socktype
+Specify a socket type.
+Socket types are named like the
+.Dv SOCK_...
+constants for socket type numbers in the
+.Aq Pa sys/socket.h
+header file but without the
+.Dv SOCK_
+prefix and lowercase.
+For example,
+.Dq dgram
+corresponds with
+.Dv SOCK_DGRAM .
+.El
+.Sh EXIT STATUS
+.Ex -std getaddrinfo
+.Sh EXAMPLES
+Look up
+.Dq www.NetBSD.org :
+.Bd -literal -offset indent
+$ getaddrinfo www.NetBSD.org
+dgram inet6 udp 2001:4f8:3:7:2e0:81ff:fe52:9ab6 0
+dgram inet udp 149.20.53.67 0
+stream inet6 tcp 2001:4f8:3:7:2e0:81ff:fe52:9ab6 0
+stream inet tcp 149.20.53.67 0
+.Ed
+.Pp
+The port number here is zero because no service was specified.
+.Pp
+Look up
+.Dq morden.NetBSD.org
+for stream sockets on port 80, and show the canonical name:
+.Bd -literal -offset indent
+$ getaddrinfo -c -t stream -s 80 morden.NetBSD.org
+canonname ftp.NetBSD.org
+stream inet6 tcp 2001:470:1f05:3d::21 80
+stream inet tcp 199.233.217.249 80
+.Ed
+.Sh SEE ALSO
+.Xr drill 1 ,
+.Xr getent 1 ,
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3 ,
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr nsswitch.conf 5 ,
+.Xr protocols 5 ,
+.Xr resolv.conf 5 ,
+.Xr services 5 ,
+.Xr ip6addrctl 8
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Nx 7.0 .
diff --git a/usr.bin/getaddrinfo/getaddrinfo.c b/usr.bin/getaddrinfo/getaddrinfo.c
new file mode 100644
index 000000000000..da84259a3c2e
--- /dev/null
+++ b/usr.bin/getaddrinfo/getaddrinfo.c
@@ -0,0 +1,328 @@
+/* $NetBSD: getaddrinfo.c,v 1.4 2014/04/22 02:23:03 ginsbach Exp $ */
+
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+
+#include "tables.h"
+
+static void usage(void) __dead;
+static void printaddrinfo(struct addrinfo *);
+static bool parse_af(const char *, int *);
+static bool parse_protocol(const char *, int *);
+static bool parse_socktype(const char *, int *);
+static bool parse_numeric_tabular(const char *, int *, const char *const *,
+ size_t);
+
+int
+main(int argc, char **argv)
+{
+ static const struct addrinfo zero_addrinfo;
+ struct addrinfo hints = zero_addrinfo;
+ struct addrinfo *addrinfo;
+ const char *hostname = NULL, *service = NULL;
+ int ch;
+ int error;
+
+ setprogname(argv[0]);
+
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ hints.ai_flags = 0;
+
+ while ((ch = getopt(argc, argv, "cf:nNp:Ps:t:")) != -1) {
+ switch (ch) {
+ case 'c':
+ hints.ai_flags |= AI_CANONNAME;
+ break;
+
+ case 'f':
+ if (!parse_af(optarg, &hints.ai_family)) {
+ warnx("invalid address family: %s", optarg);
+ usage();
+ }
+ break;
+
+ case 'n':
+ hints.ai_flags |= AI_NUMERICHOST;
+ break;
+
+ case 'N':
+ hints.ai_flags |= AI_NUMERICSERV;
+ break;
+
+ case 's':
+ service = optarg;
+ break;
+
+ case 'p':
+ if (!parse_protocol(optarg, &hints.ai_protocol)) {
+ warnx("invalid protocol: %s", optarg);
+ usage();
+ }
+ break;
+
+ case 'P':
+ hints.ai_flags |= AI_PASSIVE;
+ break;
+
+ case 't':
+ if (!parse_socktype(optarg, &hints.ai_socktype)) {
+ warnx("invalid socket type: %s", optarg);
+ usage();
+ }
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!((argc == 1) || ((argc == 0) && (hints.ai_flags & AI_PASSIVE))))
+ usage();
+ if (argc == 1)
+ hostname = argv[0];
+
+ if (service != NULL) {
+ char *p;
+
+ if ((p = strchr(service, '/')) != NULL) {
+ if (hints.ai_protocol != 0) {
+ warnx("protocol already specified");
+ usage();
+ }
+ *p = '\0';
+ p++;
+
+ if (!parse_protocol(p, &hints.ai_protocol)) {
+ warnx("invalid protocol: %s", p);
+ usage();
+ }
+ }
+ }
+
+ error = getaddrinfo(hostname, service, &hints, &addrinfo);
+ if (error)
+ errx(1, "%s", gai_strerror(error));
+
+ if ((hints.ai_flags & AI_CANONNAME) && (addrinfo != NULL)) {
+ if (printf("canonname %s\n", addrinfo->ai_canonname) < 0)
+ err(1, "printf");
+ }
+
+ printaddrinfo(addrinfo);
+
+ freeaddrinfo(addrinfo);
+
+ return 0;
+}
+
+static void __dead
+usage(void)
+{
+
+ (void)fprintf(stderr, "Usage: %s", getprogname());
+ (void)fprintf(stderr,
+ " [-f <family>] [-p <protocol>] [-t <socktype>] [-s <service>]\n");
+ (void)fprintf(stderr, " [-cnNP] [<hostname>]\n");
+ exit(1);
+}
+
+static bool
+parse_af(const char *string, int *afp)
+{
+
+ return parse_numeric_tabular(string, afp, address_families,
+ __arraycount(address_families));
+}
+
+static bool
+parse_protocol(const char *string, int *protop)
+{
+ struct protoent *protoent;
+ char *end;
+ long value;
+
+ errno = 0;
+ value = strtol(string, &end, 0);
+ if ((string[0] == '\0') || (*end != '\0'))
+ goto numeric_failed;
+ if ((errno == ERANGE) && ((value == LONG_MAX) || (value == LONG_MIN)))
+ goto numeric_failed;
+ if ((value > INT_MAX) || (value < INT_MIN))
+ goto numeric_failed;
+
+ *protop = value;
+ return true;
+
+numeric_failed:
+ protoent = getprotobyname(string);
+ if (protoent == NULL)
+ goto protoent_failed;
+
+ *protop = protoent->p_proto;
+ return true;
+
+protoent_failed:
+ return false;
+}
+
+static bool
+parse_socktype(const char *string, int *typep)
+{
+
+ return parse_numeric_tabular(string, typep, socket_types,
+ __arraycount(socket_types));
+}
+
+static bool
+parse_numeric_tabular(const char *string, int *valuep,
+ const char *const *table, size_t n)
+{
+ char *end;
+ long value;
+ size_t i;
+
+ assert((uintmax_t)n <= (uintmax_t)INT_MAX);
+
+ errno = 0;
+ value = strtol(string, &end, 0);
+ if ((string[0] == '\0') || (*end != '\0'))
+ goto numeric_failed;
+ if ((errno == ERANGE) && ((value == LONG_MAX) || (value == LONG_MIN)))
+ goto numeric_failed;
+ if ((value > INT_MAX) || (value < INT_MIN))
+ goto numeric_failed;
+
+ *valuep = value;
+ return true;
+
+numeric_failed:
+ for (i = 0; i < n; i++)
+ if ((table[i] != NULL) && (strcmp(string, table[i]) == 0))
+ break;
+ if (i == n)
+ goto table_failed;
+ *valuep = i;
+ return true;
+
+table_failed:
+ return false;
+}
+
+static void
+printaddrinfo(struct addrinfo *addrinfo)
+{
+ struct addrinfo *ai;
+ char buf[1024];
+ int n;
+ struct protoent *protoent;
+
+ for (ai = addrinfo; ai != NULL; ai = ai->ai_next) {
+ /* Print the socket type. */
+ if ((ai->ai_socktype >= 0) &&
+ ((size_t)ai->ai_socktype < __arraycount(socket_types)) &&
+ (socket_types[ai->ai_socktype] != NULL))
+ n = printf("%s", socket_types[ai->ai_socktype]);
+ else
+ n = printf("%d", ai->ai_socktype);
+ if (n < 0)
+ err(1, "printf");
+
+ /* Print the address family. */
+ if ((ai->ai_family >= 0) &&
+ ((size_t)ai->ai_family < __arraycount(address_families)) &&
+ (address_families[ai->ai_family] != NULL))
+ n = printf(" %s", address_families[ai->ai_family]);
+ else
+ n = printf(" %d", ai->ai_family);
+ if (n < 0)
+ err(1, "printf");
+
+ /* Print the protocol number. */
+ protoent = getprotobynumber(ai->ai_protocol);
+ if (protoent == NULL)
+ n = printf(" %d", ai->ai_protocol);
+ else
+ n = printf(" %s", protoent->p_name);
+ if (n < 0)
+ err(1, "printf");
+
+ /* Format the sockaddr. */
+ switch (ai->ai_family) {
+ case AF_INET:
+ case AF_INET6:
+ n = sockaddr_snprintf(buf, sizeof(buf), " %a %p",
+ ai->ai_addr);
+ break;
+
+ default:
+ n = sockaddr_snprintf(buf, sizeof(buf),
+ "%a %p %I %F %R %S", ai->ai_addr);
+ }
+
+ /*
+ * Check for sockaddr_snprintf failure.
+ *
+ * XXX sockaddr_snprintf's error reporting is botched
+ * -- man page says it sets errno, but if getnameinfo
+ * fails, errno is not where it reports the error...
+ */
+ if (n < 0) {
+ warnx("sockaddr_snprintf failed");
+ continue;
+ }
+ if (sizeof(buf) <= (size_t)n)
+ warnx("truncated sockaddr_snprintf output");
+
+ /* Print the formatted sockaddr. */
+ if (printf("%s\n", buf) < 0)
+ err(1, "printf");
+ }
+}
diff --git a/usr.bin/getaddrinfo/tables.awk b/usr.bin/getaddrinfo/tables.awk
new file mode 100644
index 000000000000..00f6aee4ae0a
--- /dev/null
+++ b/usr.bin/getaddrinfo/tables.awk
@@ -0,0 +1,61 @@
+#!/usr/bin/awk -f
+# $NetBSD: tables.awk,v 1.2 2014/02/27 01:17:13 ginsbach Exp $
+
+# Copyright (c) 2013 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Taylor R. Campbell.
+#
+# 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.
+
+BEGIN {
+ n_afs = 0
+ n_socktypes = 0
+}
+
+!(($1 == "#define") && ($3 ~ /^[0-9]*$/)) {
+ next
+}
+
+($2 ~ /^AF_[A-Z0-9_]*$/) && ($2 != "AF_MAX") {
+ afs[n_afs++] = substr($2, 4)
+}
+
+($2 ~ /^SOCK_[A-Z0-9_]*$/) && ($2 != "SOCK_MAXADDRLEN") {
+ socktypes[n_socktypes++] = substr($2, 6)
+}
+
+END {
+ printf("/* Do not edit! This file was generated automagically! */\n");
+
+ printf("\nstatic const char *const address_families[] = {\n");
+ for (i = 0; i < n_afs; i++)
+ printf("\t[AF_%s] = \"%s\",\n", afs[i], tolower(afs[i]));
+ printf("};\n");
+
+ printf("\nstatic const char *const socket_types[] = {\n");
+ for (i = 0; i < n_socktypes; i++)
+ printf("\t[SOCK_%s] = \"%s\",\n", socktypes[i],
+ tolower(socktypes[i]));
+ printf("};\n");
+}
diff --git a/usr.bin/getconf/Makefile b/usr.bin/getconf/Makefile
new file mode 100644
index 000000000000..e2ec0543634b
--- /dev/null
+++ b/usr.bin/getconf/Makefile
@@ -0,0 +1,42 @@
+.include <src.opts.mk>
+
+PROG= getconf
+
+SRCS= confstr.c getconf.c limits.c pathconf.c progenv.c sysconf.c \
+ unsigned_limits.c
+CFLAGS+= -I${.CURDIR}
+CLEANFILES+= confstr.c limits.c pathconf.c progenv.c sysconf.c \
+ confstr.names limits.names pathconf.names sysconf.names \
+ conflicting.names unique.names unsigned_limits.names
+
+.SUFFIXES: .gperf .names
+.PHONY: conflicts
+
+all: conflicts
+
+FAKE_GPERF= ${.CURDIR}/fake-gperf.awk
+.gperf.c: ${FAKE_GPERF}
+ LC_ALL=C awk -f ${FAKE_GPERF} ${.IMPSRC} >${.TARGET}
+
+.gperf.names:
+ LC_ALL=C awk '/^[_A-Z]/ { print; }' ${.IMPSRC} | \
+ sed -e 's/,$$//' >${.TARGET}
+
+conflicts: conflicting.names unique.names
+ @if test `wc -l <conflicting.names` != `wc -l <unique.names`; then \
+ echo "Name conflicts found!" >&2; \
+ exit 1; \
+ fi
+
+# pathconf.names is not included here because pathconf names are
+# syntactically distinct from the other kinds.
+conflicting.names: confstr.names limits.names sysconf.names
+ cat ${.ALLSRC} >${.TARGET}
+
+unique.names: conflicting.names
+ LC_ALL=C sort -u ${.ALLSRC} >${.TARGET}
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/getconf/Makefile.depend b/usr.bin/getconf/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/getconf/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/getconf/confstr.gperf b/usr.bin/getconf/confstr.gperf
new file mode 100644
index 000000000000..ebb220ad3e3f
--- /dev/null
+++ b/usr.bin/getconf/confstr.gperf
@@ -0,0 +1,79 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+/*
+ * The Standard seems a bit ambiguous over whether the POSIX_V6_*
+ * are specified with or without a leading underscore, so we just
+ * use both.
+ */
+%}
+struct map { const char *name; int key; int valid; };
+%%
+PATH, _CS_PATH
+POSIX_V6_ILP32_OFF32_CFLAGS, _CS_POSIX_V6_ILP32_OFF32_CFLAGS
+POSIX_V6_ILP32_OFF32_LDFLAGS, _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
+POSIX_V6_ILP32_OFF32_LIBS, _CS_POSIX_V6_ILP32_OFF32_LIBS
+POSIX_V6_ILP32_OFFBIG_CFLAGS, _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
+POSIX_V6_ILP32_OFFBIG_LDFLAGS, _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
+POSIX_V6_ILP32_OFFBIG_LIBS, _CS_POSIX_V6_ILP32_OFFBIG_LIBS
+POSIX_V6_LP64_OFF64_CFLAGS, _CS_POSIX_V6_LP64_OFF64_CFLAGS
+POSIX_V6_LP64_OFF64_LDFLAGS, _CS_POSIX_V6_LP64_OFF64_LDFLAGS
+POSIX_V6_LP64_OFF64_LIBS, _CS_POSIX_V6_LP64_OFF64_LIBS
+POSIX_V6_LPBIG_OFFBIG_CFLAGS, _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
+POSIX_V6_LPBIG_OFFBIG_LDFLAGS, _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
+POSIX_V6_LPBIG_OFFBIG_LIBS, _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
+POSIX_V6_WIDTH_RESTRICTED_ENVS, _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
+_POSIX_V6_ILP32_OFF32_CFLAGS, _CS_POSIX_V6_ILP32_OFF32_CFLAGS
+_POSIX_V6_ILP32_OFF32_LDFLAGS, _CS_POSIX_V6_ILP32_OFF32_LDFLAGS
+_POSIX_V6_ILP32_OFF32_LIBS, _CS_POSIX_V6_ILP32_OFF32_LIBS
+_POSIX_V6_ILP32_OFFBIG_CFLAGS, _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS
+_POSIX_V6_ILP32_OFFBIG_LDFLAGS, _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS
+_POSIX_V6_ILP32_OFFBIG_LIBS, _CS_POSIX_V6_ILP32_OFFBIG_LIBS
+_POSIX_V6_LP64_OFF64_CFLAGS, _CS_POSIX_V6_LP64_OFF64_CFLAGS
+_POSIX_V6_LP64_OFF64_LDFLAGS, _CS_POSIX_V6_LP64_OFF64_LDFLAGS
+_POSIX_V6_LP64_OFF64_LIBS, _CS_POSIX_V6_LP64_OFF64_LIBS
+_POSIX_V6_LPBIG_OFFBIG_CFLAGS, _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS
+_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS
+_POSIX_V6_LPBIG_OFFBIG_LIBS, _CS_POSIX_V6_LPBIG_OFFBIG_LIBS
+_POSIX_V6_WIDTH_RESTRICTED_ENVS, _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
+%%
+int
+find_confstr(const char *name, int *key)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *key = rv->key;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+void
+foreach_confstr(void (*func)(const char *, int))
+{
+ const struct map *mp;
+
+ for (mp = wordlist; mp->name != NULL; mp++) {
+ if (mp->valid)
+ func(mp->name, mp->key);
+ }
+}
diff --git a/usr.bin/getconf/fake-gperf.awk b/usr.bin/getconf/fake-gperf.awk
new file mode 100644
index 000000000000..810f705965a3
--- /dev/null
+++ b/usr.bin/getconf/fake-gperf.awk
@@ -0,0 +1,66 @@
+#!/usr/bin/awk -f
+BEGIN {
+ state = 0;
+ struct_seen = "";
+}
+/^%{$/ && state == 0 {
+ state = 1;
+ next;
+}
+/^%}$/ && state == 1 {
+ state = 0;
+ next;
+}
+state == 1 { print; next; }
+/^struct/ && state == 0 {
+ print;
+ struct_seen = $2;
+ next;
+}
+/^%%$/ && state == 0 {
+ state = 2;
+ if (struct_seen !~ /^$/) {
+ print "static const struct", struct_seen, "wordlist[] = {";
+ } else {
+ print "static const struct map {";
+ print "\tconst char *name;";
+ print "\tint key;";
+ print "\tint valid;";
+ print "} wordlist[] = {";
+ struct_seen = "map";
+ }
+ next;
+}
+/^%%$/ && state == 2 {
+ state = 3;
+ print "\t{ NULL, 0, 0 }";
+ print "};";
+ print "#include <sys/param.h>";
+ print "#define\tNWORDS\t(nitems(wordlist) - 1)";
+ print "static const struct map *";
+ print "in_word_set(const char *word)";
+ print "{";
+ print "\tconst struct", struct_seen, "*mp;";
+ print "";
+ print "\tfor (mp = wordlist; mp < &wordlist[NWORDS]; mp++) {";
+ print "\t\tif (strcmp(word, mp->name) == 0)";
+ print "\t\t\treturn (mp);";
+ print "\t}";
+ print "\treturn (NULL);";
+ print "}";
+ print "";
+ next;
+}
+state == 2 && NF == 2 {
+ name = substr($1, 1, length($1) - 1);
+ printf "#ifdef %s\n", $2;
+ printf "\t{ \"%s\", %s, 1 },\n", name, $2;
+ print "#else";
+ printf "\t{ \"%s\", 0, 0 },\n", name, $2;
+ print "#endif"
+ next;
+}
+state == 3 { print; next; }
+{
+ # eat anything not matched.
+}
diff --git a/usr.bin/getconf/getconf.1 b/usr.bin/getconf/getconf.1
new file mode 100644
index 000000000000..1ebf4a4f1288
--- /dev/null
+++ b/usr.bin/getconf/getconf.1
@@ -0,0 +1,223 @@
+.\"
+.\" Copyright 2000 Massachusetts Institute of Technology
+.\"
+.\" Permission to use, copy, modify, and distribute this software and
+.\" its documentation for any purpose and without fee is hereby
+.\" granted, provided that both the above copyright notice and this
+.\" permission notice appear in all copies, that both the above
+.\" copyright notice and this permission notice appear in all
+.\" supporting documentation, and that the name of M.I.T. not be used
+.\" in advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission. M.I.T. makes
+.\" no representations about the suitability of this software for any
+.\" purpose. It is provided "as is" without express or implied
+.\" warranty.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+.\" SHALL M.I.T. 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 September 15, 2017
+.Dt GETCONF 1
+.Os
+.Sh NAME
+.Nm getconf
+.Nd retrieve standard configuration variables
+.Sh SYNOPSIS
+.Nm
+.Fl a
+.Op Ar file
+.Nm
+.Op Fl v Ar environment
+.Ar path_var
+.Ar file
+.Nm
+.Op Fl v Ar environment
+.Ar system_var
+.Sh DESCRIPTION
+The
+.Nm
+utility prints the values of
+.Tn POSIX
+or
+.Tn X/Open
+path or system configuration variables to the standard output.
+If a variable is undefined, the string
+.Dq Li undefined
+is output.
+.Pp
+The first form of the command displays all of the path or system configuration
+variables to standard output.
+If
+.Ar file
+is provided,
+all path configuration variables are reported for
+.Ar file
+using
+.Xr pathconf 2 .
+Otherwise,
+all system configuration variables are reported using
+.Xr confstr 3
+and
+.Xr sysconf 3 .
+.Pp
+The second form of the command, with two mandatory
+arguments, retrieves file- and file system-specific
+configuration variables using
+.Xr pathconf 2 .
+The third form, with a single argument, retrieves system
+configuration variables using
+.Xr confstr 3
+and
+.Xr sysconf 3 ,
+depending on the type of variable.
+As an extension, the second form can also be used to query static limits from
+.In limits.h .
+.Pp
+All
+.Xr sysconf 3
+and
+.Xr pathconf 2
+variables use the same name as the manifest constants defined in
+the relevant standard C-language bindings, including any leading
+underscore or prefix.
+That is to say,
+.Ar system_var
+might be
+.Dv ARG_MAX
+or
+.Dv _POSIX_VERSION ,
+as opposed to the
+.Xr sysconf 3
+names
+.Dv _SC_ARG_MAX
+or
+.Dv _SC_POSIX_VERSION .
+Variables retrieved from
+.Xr confstr 3
+have the leading
+.Ql _CS_
+stripped off; thus,
+.Dv _CS_PATH
+is queried by a
+.Ar system_var
+of
+.Dq Li PATH .
+.Ss Programming Environments
+The
+.Fl v Ar environment
+option specifies a
+.St -p1003.1-2001
+programming environment under which the values are to be queried.
+This option currently does nothing, but may in the future be used
+to select between 32-bit and 64-bit execution environments on platforms
+which support both.
+Specifying an environment which is not supported on the current execution
+platform gives undefined results.
+.Pp
+The standard programming environments are as follows:
+.Bl -tag -width ".Li POSIX_V6_LPBIG_OFFBIG" -offset indent
+.It Li POSIX_V6_ILP32_OFF32
+Exactly 32-bit integer, long, pointer, and file offset.
+.Sy Supported platforms :
+None.
+.It Li POSIX_V6_ILP32_OFFBIG
+Exactly 32-bit integer, long, and pointer; at least 64-bit file offset.
+.Sy Supported platforms :
+.Tn IA32 ,
+.Tn PowerPC .
+.It Li POSIX_V6_LP64_OFF64
+Exactly 32-bit integer; exactly 64-bit long, pointer, and file offset.
+.Sy Supported platforms :
+.Tn AMD64 ,
+.Tn SPARC64 .
+.It Li POSIX_V6_LPBIG_OFFBIG
+At least 32-bit integer; at least 64-bit long, pointer, and file offset.
+.Sy Supported platforms :
+None.
+.El
+.Pp
+The command:
+.Pp
+.Dl "getconf POSIX_V6_WIDTH_RESTRICTED_ENVS"
+.Pp
+returns a newline-separated list of environments in which the width
+of certain fundamental types is no greater than the width of the native
+C type
+.Vt long .
+At present, all programming environments supported by
+.Fx
+have this property.
+Several of the
+.Xr confstr 3
+variables provide information on the necessary compiler and linker flags
+to use the standard programming environments described above.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The command:
+.Pp
+.Dl "getconf PATH"
+.Pp
+will display the system default setting for the
+.Ev PATH
+environment variable.
+.Pp
+The command:
+.Pp
+.Dl "getconf NAME_MAX /tmp"
+.Pp
+will display the maximum length of a filename in the
+.Pa /tmp
+directory.
+.Pp
+The command:
+.Pp
+.Dl "getconf -v POSIX_V6_LPBIG_OFFBIG LONG_MAX"
+.Pp
+will display the maximum value of the C type
+.Vt long
+in the
+.Li POSIX_V6_LPBIG_OFFBIG
+programming environment,
+if the system supports that environment.
+.Sh DIAGNOSTICS
+Use of a
+.Ar system_var
+or
+.Ar path_var
+which is completely unrecognized is considered an error,
+causing a diagnostic message to be written to standard error.
+One
+which is known but merely undefined does not result in an error
+indication.
+The
+.Nm
+utility recognizes all of the variables defined for
+.St -p1003.1-2001 ,
+including those which are not currently implemented.
+.Sh SEE ALSO
+.Xr pathconf 2 ,
+.Xr confstr 3 ,
+.Xr sysconf 3
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be compliant with
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An Garrett A. Wollman Aq Mt wollman@lcs.mit.edu
diff --git a/usr.bin/getconf/getconf.c b/usr.bin/getconf/getconf.c
new file mode 100644
index 000000000000..ed69d5f0454b
--- /dev/null
+++ b/usr.bin/getconf/getconf.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2000 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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 <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "getconf.h"
+
+static void do_allsys(void);
+static void do_allpath(const char *path);
+static void do_confstr(const char *name, int key);
+static void do_sysconf(const char *name, int key);
+static void do_pathconf(const char *name, int key, const char *path);
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"usage: getconf -a [pathname]\n"
+" getconf [-v prog_env] system_var\n"
+" getconf [-v prog_env] path_var pathname\n");
+ exit(EX_USAGE);
+}
+
+int
+main(int argc, char **argv)
+{
+ bool aflag;
+ int c, key, valid;
+ const char *name, *vflag, *alt_path;
+ intmax_t limitval;
+ uintmax_t ulimitval;
+
+ aflag = false;
+ vflag = NULL;
+ while ((c = getopt(argc, argv, "av:")) != -1) {
+ switch (c) {
+ case 'a':
+ aflag = true;
+ break;
+ case 'v':
+ vflag = optarg;
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ if (aflag) {
+ if (vflag != NULL)
+ usage();
+ if (argv[optind] == NULL)
+ do_allsys();
+ else
+ do_allpath(argv[optind]);
+ return (0);
+ }
+
+ if ((name = argv[optind]) == NULL)
+ usage();
+
+ if (vflag != NULL) {
+ if ((valid = find_progenv(vflag, &alt_path)) == 0)
+ errx(EX_USAGE, "invalid programming environment %s",
+ vflag);
+ if (valid > 0 && alt_path != NULL) {
+ if (argv[optind + 1] == NULL)
+ execl(alt_path, "getconf", argv[optind],
+ (char *)NULL);
+ else
+ execl(alt_path, "getconf", argv[optind],
+ argv[optind + 1], (char *)NULL);
+
+ err(EX_OSERR, "execl: %s", alt_path);
+ }
+ if (valid < 0)
+ errx(EX_UNAVAILABLE, "environment %s is not available",
+ vflag);
+ }
+
+ if (argv[optind + 1] == NULL) { /* confstr or sysconf */
+ if ((valid = find_unsigned_limit(name, &ulimitval)) != 0) {
+ if (valid > 0)
+ printf("%" PRIuMAX "\n", ulimitval);
+ else
+ printf("undefined\n");
+ return 0;
+ }
+ if ((valid = find_limit(name, &limitval)) != 0) {
+ if (valid > 0)
+ printf("%" PRIdMAX "\n", limitval);
+ else
+ printf("undefined\n");
+
+ return 0;
+ }
+ if ((valid = find_confstr(name, &key)) != 0) {
+ if (valid > 0)
+ do_confstr(name, key);
+ else
+ printf("undefined\n");
+ } else {
+ valid = find_sysconf(name, &key);
+ if (valid > 0) {
+ do_sysconf(name, key);
+ } else if (valid < 0) {
+ printf("undefined\n");
+ } else
+ errx(EX_USAGE,
+ "no such configuration parameter `%s'",
+ name);
+ }
+ } else {
+ valid = find_pathconf(name, &key);
+ if (valid != 0) {
+ if (valid > 0)
+ do_pathconf(name, key, argv[optind + 1]);
+ else
+ printf("undefined\n");
+ } else
+ errx(EX_USAGE,
+ "no such path configuration parameter `%s'",
+ name);
+ }
+ return 0;
+}
+
+static void
+do_onestr(const char *name, int key)
+{
+ size_t len;
+
+ errno = 0;
+ len = confstr(key, 0, 0);
+ if (len == 0 && errno != 0) {
+ warn("confstr: %s", name);
+ return;
+ }
+ printf("%s: ", name);
+ if (len == 0)
+ printf("undefined\n");
+ else {
+ char buf[len + 1];
+
+ confstr(key, buf, len);
+ printf("%s\n", buf);
+ }
+}
+
+static void
+do_onesys(const char *name, int key)
+{
+ long value;
+
+ errno = 0;
+ value = sysconf(key);
+ if (value == -1 && errno != 0) {
+ warn("sysconf: %s", name);
+ return;
+ }
+ printf("%s: ", name);
+ if (value == -1)
+ printf("undefined\n");
+ else
+ printf("%ld\n", value);
+}
+
+static void
+do_allsys(void)
+{
+
+ foreach_confstr(do_onestr);
+ foreach_sysconf(do_onesys);
+}
+
+static void
+do_onepath(const char *name, int key, const char *path)
+{
+ long value;
+
+ errno = 0;
+ value = pathconf(path, key);
+ if (value == -1 && errno != EINVAL && errno != 0)
+ warn("pathconf: %s", name);
+ printf("%s: ", name);
+ if (value == -1)
+ printf("undefined\n");
+ else
+ printf("%ld\n", value);
+}
+
+static void
+do_allpath(const char *path)
+{
+
+ foreach_pathconf(do_onepath, path);
+}
+
+static void
+do_confstr(const char *name, int key)
+{
+ size_t len;
+ int savederr;
+
+ savederr = errno;
+ errno = 0;
+ len = confstr(key, 0, 0);
+ if (len == 0) {
+ if (errno)
+ err(EX_OSERR, "confstr: %s", name);
+ else
+ printf("undefined\n");
+ } else {
+ char buf[len + 1];
+
+ confstr(key, buf, len);
+ printf("%s\n", buf);
+ }
+ errno = savederr;
+}
+
+static void
+do_sysconf(const char *name, int key)
+{
+ long value;
+
+ errno = 0;
+ value = sysconf(key);
+ if (value == -1 && errno != 0)
+ err(EX_OSERR, "sysconf: %s", name);
+ else if (value == -1)
+ printf("undefined\n");
+ else
+ printf("%ld\n", value);
+}
+
+static void
+do_pathconf(const char *name, int key, const char *path)
+{
+ long value;
+
+ errno = 0;
+ value = pathconf(path, key);
+ if (value == -1 && errno != 0)
+ err(EX_OSERR, "pathconf: %s", name);
+ else if (value == -1)
+ printf("undefined\n");
+ else
+ printf("%ld\n", value);
+}
+
diff --git a/usr.bin/getconf/getconf.h b/usr.bin/getconf/getconf.h
new file mode 100644
index 000000000000..124931788c15
--- /dev/null
+++ b/usr.bin/getconf/getconf.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ */
+
+#ifdef STABLE
+typedef long long intmax_t;
+#define PRIdMAX "lld"
+#else
+#include <inttypes.h>
+#endif
+
+int find_confstr(const char *name, int *key);
+int find_unsigned_limit(const char *name, uintmax_t *value);
+int find_limit(const char *name, intmax_t *value);
+int find_pathconf(const char *name, int *key);
+int find_progenv(const char *name, const char **alt_path);
+int find_sysconf(const char *name, int *key);
+void foreach_confstr(void (*func)(const char *, int));
+void foreach_pathconf(void (*func)(const char *, int, const char *),
+ const char *path);
+void foreach_sysconf(void (*func)(const char *, int));
diff --git a/usr.bin/getconf/limits.gperf b/usr.bin/getconf/limits.gperf
new file mode 100644
index 000000000000..e2bc7b4b87d3
--- /dev/null
+++ b/usr.bin/getconf/limits.gperf
@@ -0,0 +1,111 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <limits.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+%}
+struct map { const char *name; intmax_t value; int valid; };
+%%
+_POSIX_CLOCKRES_MIN, _POSIX_CLOCKRES_MIN
+_POSIX_AIO_LISTIO_MAX, _POSIX_AIO_LISTIO_MAX
+_POSIX_AIO_MAX, _POSIX_AIO_MAX
+_POSIX_ARG_MAX, _POSIX_ARG_MAX
+_POSIX_CHILD_MAX, _POSIX_CHILD_MAX
+_POSIX_DELAYTIMER_MAX, _POSIX_DELAYTIMER_MAX
+_POSIX_HOST_NAME_MAX, _POSIX_HOST_NAME_MAX
+_POSIX_LINK_MAX, _POSIX_LINK_MAX
+_POSIX_LOGIN_NAME_MAX, _POSIX_LOGIN_NAME_MAX
+_POSIX_MAX_CANON, _POSIX_MAX_CANON
+_POSIX_MAX_INPUT, _POSIX_MAX_INPUT
+_POSIX_MQ_OPEN_MAX, _POSIX_MQ_OPEN_MAX
+_POSIX_MQ_PRIO_MAX, _POSIX_MQ_PRIO_MAX
+_POSIX_NAME_MAX, _POSIX_NAME_MAX
+_POSIX_NGROUPS_MAX, _POSIX_NGROUPS_MAX
+_POSIX_OPEN_MAX, _POSIX_OPEN_MAX
+_POSIX_PATH_MAX, _POSIX_PATH_MAX
+_POSIX_PIPE_BUF, __POSIX_PIPE_BUF
+_POSIX_RE_DUP_MAX, _POSIX_RE_DUP_MAX
+_POSIX_RTSIG_MAX, _POSIX_RTSIG_MAX
+_POSIX_SEM_NSEMS_MAX, _POSIX_SEM_NSEMS_MAX
+_POSIX_SEM_VALUE_MAX, _POSIX_SEM_VALUE_MAX
+_POSIX_SIGQUEUE_MAX, _POSIX_SIGQUEUE_MAX
+_POSIX_SSIZE_MAX, _POSIX_SSIZE_MAX
+_POSIX_STREAM_MAX, _POSIX_STREAM_MAX
+_POSIX_SS_REPL_MAX, _POSIX_SS_REPL_MAX
+_POSIX_SYMLINK_MAX, _POSIX_SYMLINK_MAX
+_POSIX_SYMLOOP_MAX, _POSIX_SYMLOOP_MAX
+_POSIX_THREAD_DESTRUCTOR_ITERATIONS, _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+_POSIX_THREAD_KEYS_MAX, _POSIX_THREAD_KEYS_MAX
+_POSIX_THREAD_THREADS_MAX, _POSIX_THREAD_THREADS_MAX
+_POSIX_TIMER_MAX, _POSIX_TIMER_MAX
+_POSIX_TRACE_EVENT_NAME_MAX, _POSIX_TRACE_EVENT_NAME_MAX
+_POSIX_TRACE_NAME_MAX, _POSIX_TRACE_NAME_MAX
+_POSIX_TRACE_SYS_MAX, _POSIX_TRACE_SYS_MAX
+_POSIX_TRACE_USER_EVENT_MAX, _POSIX_TRACE_USER_EVENT_MAX
+_POSIX_TTY_NAME_MAX, _POSIX_TTY_NAME_MAX
+_POSIX_TZNAME_MAX, _POSIX_TZNAME_MAX
+_POSIX2_BC_BASE_MAX, _POSIX2_BC_BASE_MAX
+_POSIX2_BC_DIM_MAX, _POSIX2_BC_DIM_MAX
+_POSIX2_BC_SCALE_MAX, _POSIX2_BC_SCALE_MAX
+_POSIX2_BC_STRING_MAX, _POSIX2_BC_STRING_MAX
+_POSIX2_CHARCLASS_NAME_MAX, _POSIX2_CHARCLASS_NAME_MAX
+_POSIX2_COLL_WEIGHTS_MAX, _POSIX2_COLL_WEIGHTS_MAX
+_POSIX2_EXPR_NEXT_MAX, _POSIX2_EXPR_NEST_MAX
+_POSIX2_LINE_MAX, _POSIX2_LINE_MAX
+_POSIX2_RE_DUP_MAX, _POSIX2_RE_DUP_MAX
+_XOPEN_IOV_MAX, _XOPEN_IOV_MAX
+_XOPEN_NAME_MAX, _XOPEN_NAME_MAX
+_XOPEN_PATH_MAX, _XOPEN_PATH_MAX
+CHAR_BIT, CHAR_BIT
+CHAR_MAX, CHAR_MAX
+CHAR_MIN, CHAR_MIN
+INT_MAX, INT_MAX
+INT_MIN, INT_MIN
+LLONG_MIN, LLONG_MIN
+LLONG_MAX, LLONG_MAX
+LONG_BIT, LONG_BIT
+LONG_MAX, LONG_MAX
+LONG_MIN, LONG_MIN
+MB_LEN_MAX, MB_LEN_MAX
+SCHAR_MAX, SCHAR_MAX
+SCHAR_MIN, SCHAR_MIN
+SHRT_MAX, SHRT_MAX
+SHRT_MIN, SHRT_MIN
+SSIZE_MAX, SSIZE_MAX
+WORD_BIT, WORD_BIT
+CHARCLASS_NAME_MAX, CHARCLASS_NAME_MAX
+NL_ARGMAX, NL_ARGMAX
+ML_LANGMAX, NL_LANGMAX
+NL_MSGMAX, NL_MSGMAX
+NL_NMAX, NL_NMAX
+NL_SETMAX, NL_SETMAX
+NL_TEXTMAX, NL_TEXTMAX
+NZERO, NZERO
+%%
+int
+find_limit(const char *name, intmax_t *value)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *value = rv->value;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
diff --git a/usr.bin/getconf/pathconf.gperf b/usr.bin/getconf/pathconf.gperf
new file mode 100644
index 000000000000..caf97e841d3b
--- /dev/null
+++ b/usr.bin/getconf/pathconf.gperf
@@ -0,0 +1,81 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+%}
+struct map { const char *name; int key; int valid; };
+%%
+ACL_EXTENDED, _PC_ACL_EXTENDED
+ACL_NFS4, _PC_ACL_NFS4
+ACL_PATH_MAX, _PC_ACL_PATH_MAX
+CAP_PRESENT, _PC_CAP_PRESENT
+DEALLOC_PRESENT, _PC_DEALLOC_PRESENT
+FILESIZEBITS, _PC_FILESIZEBITS
+INF_PRESENT, _PC_INF_PRESENT
+LINK_MAX, _PC_LINK_MAX
+MAC_PRESENT, _PC_MAC_PRESENT
+MAX_CANON, _PC_MAX_CANON
+MAX_INPUT, _PC_MAX_INPUT
+MIN_HOLE_SIZE, _PC_MIN_HOLE_SIZE
+NAME_MAX, _PC_NAME_MAX
+PATH_MAX, _PC_PATH_MAX
+PIPE_BUF, _PC_PIPE_BUF
+POSIX_ALLOC_SIZE_MIN, _PC_ALLOC_SIZE_MIN
+POSIX_REC_INCR_XFER_SIZE, _PC_REC_INCR_XFER_SIZE
+POSIX_REC_MAX_XFER_SIZE, _PC_REC_MAX_XFER_SIZE
+POSIX_REC_MIN_XFER_SIZE, _PC_REC_MIN_XFER_SIZE
+POSIX_REC_XFER_ALIGN, _PC_REC_XFER_ALIGN
+SYMLINK_MAX, _PC_SYMLINK_MAX
+TRUSTEDBSD_ACL_EXTENDED, _PC_ACL_EXTENDED
+TRUSTEDBSD_ACL_NFS4, _PC_ACL_NFS4
+TRUSTEDBSD_ACL_PATH_MAX, _PC_ACL_PATH_MAX
+TRUSTEDBSD_CAP_PRESENT, _PC_CAP_PRESENT
+TRUSTEDBSD_INF_PRESENT, _PC_INF_PRESENT
+TRUSTEDBSD_MAC_PRESENT, _PC_MAC_PRESENT
+_POSIX_CHOWN_RESTRICTED, _PC_CHOWN_RESTRICTED
+_POSIX_NO_TRUNC, _PC_NO_TRUNC
+_POSIX_VDISABLE, _PC_VDISABLE
+_POSIX_ASYNC_IO, _PC_ASYNC_IO
+_POSIX_PRIO_IO, _PC_PRIO_IO
+_POSIX_SYNC_IO, _PC_SYNC_IO
+%%
+int
+find_pathconf(const char *name, int *key)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *key = rv->key;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+void
+foreach_pathconf(void (*func)(const char *, int, const char *),
+ const char *path)
+{
+ const struct map *mp;
+
+ for (mp = wordlist; mp->name != NULL; mp++) {
+ if (mp->valid)
+ func(mp->name, mp->key, path);
+ }
+}
diff --git a/usr.bin/getconf/progenv.gperf b/usr.bin/getconf/progenv.gperf
new file mode 100644
index 000000000000..564958725923
--- /dev/null
+++ b/usr.bin/getconf/progenv.gperf
@@ -0,0 +1,65 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+/*
+ * The Standard seems a bit ambiguous over whether the POSIX_V6_*
+ * are specified with or without a leading underscore, so we just
+ * use both.
+ */
+/*
+ * The alt_path member gives the path containing another `getconf'
+ * executable which was compiled using the specified programming
+ * environment. If it is NULL, the current executable is good enough.
+ * If we ever support multiple environments, this table will need to
+ * be updated. (We cheat here and define the supported environments
+ * statically.)
+ */
+#ifdef __LP64__
+#define have_LP64_OFF64 NULL
+#endif
+
+#ifdef __ILP32__
+#define have_ILP32_OFFBIG NULL
+#endif
+
+%}
+struct map { const char *name; const char *alt_path; int valid; };
+%%
+POSIX_V6_ILP32_OFF32, notdef
+POSIX_V6_ILP32_OFFBIG, have_ILP32_OFFBIG
+POSIX_V6_LP64_OFF64, have_LP64_OFF64
+POSIX_V6_LPBIG_OFFBIG, notdef
+_POSIX_V6_ILP32_OFF32, notdef
+_POSIX_V6_ILP32_OFFBIG, have_ILP32_OFFBIG
+_POSIX_V6_LP64_OFF64, have_LP64_OFF64
+_POSIX_V6_LPBIG_OFFBIG, notdef
+%%
+int
+find_progenv(const char *name, const char **alt_path)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *alt_path = rv->alt_path;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
diff --git a/usr.bin/getconf/sysconf.gperf b/usr.bin/getconf/sysconf.gperf
new file mode 100644
index 000000000000..baf341c8962b
--- /dev/null
+++ b/usr.bin/getconf/sysconf.gperf
@@ -0,0 +1,160 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+%}
+struct map { const char *name; int key; int valid; };
+%%
+AIO_LISTIO_MAX, _SC_AIO_LISTIO_MAX
+AIO_MAX, _SC_AIO_MAX
+AIO_PRIO_DELTA_MAX, _SC_AIO_PRIO_DELTA_MAX
+ARG_MAX, _SC_ARG_MAX
+ATEXIT_MAX, _SC_ATEXIT_MAX
+BC_BASE_MAX, _SC_BC_BASE_MAX
+BC_DIM_MAX, _SC_BC_DIM_MAX
+BC_SCALE_MAX, _SC_BC_SCALE_MAX
+BC_STRING_MAX, _SC_BC_STRING_MAX
+CHILD_MAX, _SC_CHILD_MAX
+CLK_TCK, _SC_CLK_TCK
+COLL_WEIGHTS_MAX, _SC_COLL_WEIGHTS_MAX
+DELAYTIMER_MAX, _SC_DELAYTIMER_MAX
+EXPR_NEST_MAX, _SC_EXPR_NEST_MAX
+GETGR_R_SIZE_MAX, _SC_GETGR_R_SIZE_MAX
+GETPW_R_SIZE_MAX, _SC_GETPW_R_SIZE_MAX
+HOST_NAME_MAX, _SC_HOST_NAME_MAX
+IOV_MAX, _SC_IOV_MAX
+LINE_MAX, _SC_LINE_MAX
+LOGIN_NAME_MAX, _SC_LOGIN_NAME_MAX
+MQ_OPEN_MAX, _SC_MQ_OPEN_MAX
+MQ_PRIO_MAX, _SC_MQ_PRIO_MAX
+NGROUPS_MAX, _SC_NGROUPS_MAX
+NPROCESSORS_CONF, _SC_NPROCESSORS_CONF
+NPROCESSORS_ONLN, _SC_NPROCESSORS_ONLN
+OPEN_MAX, _SC_OPEN_MAX
+PAGESIZE, _SC_PAGESIZE
+PAGE_SIZE, _SC_PAGESIZE
+PASS_MAX, _SC_PASS_MAX
+PTHREAD_DESTRUCTOR_ITERATIONS, _SC_THREAD_DESTRUCTOR_ITERATIONS
+PTHREAD_KEYS_MAX, _SC_THREAD_KEYS_MAX
+PTHREAD_STACK_MIN, _SC_THREAD_STACK_MIN
+PTHREAD_THREADS_MAX, _SC_THREAD_THREADS_MAX
+RE_DUP_MAX, _SC_RE_DUP_MAX
+RTSIG_MAX, _SC_RTSIG_MAX
+SEM_NSEMS_MAX, _SC_SEM_NSEMS_MAX
+SEM_VALUE_MAX, _SC_SEM_VALUE_MAX
+SIGQUEUE_MAX, _SC_SIGQUEUE_MAX
+STREAM_MAX, _SC_STREAM_MAX
+SYMLOOP_MAX, _SC_SYMLOOP_MAX
+TIMER_MAX, _SC_TIMER_MAX
+TTY_NAME_MAX, _SC_TTY_NAME_MAX
+TZNAME_MAX, _SC_TZNAME_MAX
+_NPROCESSORS_CONF, _SC_NPROCESSORS_CONF
+_NPROCESSORS_ONLN, _SC_NPROCESSORS_ONLN
+_POSIX2_CHAR_TERM, _SC_2_CHAR_TERM
+_POSIX2_C_BIND, _SC_2_C_BIND
+_POSIX2_C_DEV, _SC_2_C_DEV
+_POSIX2_C_VERSION, _SC_2_C_VERSION
+_POSIX2_FORT_DEV, _SC_2_FORT_DEV
+_POSIX2_FORT_RUN, _SC_2_FORT_RUN
+_POSIX2_LOCALEDEF, _SC_2_LOCALEDEF
+_POSIX2_SW_DEV, _SC_2_SW_DEV
+_POSIX2_UPE, _SC_2_UPE
+_POSIX2_VERSION, _SC_2_VERSION
+_POSIX_ASYNCHRONOUS_IO, _SC_ASYNCHRONOUS_IO
+_POSIX_BARRIERS, _SC_BARRIERS
+_POSIX_CLOCK_SELECTION, _SC_CLOCK_SELECTION
+_POSIX_CPUTIME, _SC_CPUTIME
+_POSIX_FILE_LOCKING, _SC_FILE_LOCKING
+_POSIX_FSYNC, _SC_FSYNC
+_POSIX_IPV6, _SC_IPV6
+_POSIX_JOB_CONTROL, _SC_JOB_CONTROL
+_POSIX_MAPPED_FILES, _SC_MAPPED_FILES
+_POSIX_MEMLOCK, _SC_MEMLOCK
+_POSIX_MEMLOCK_RANGE, _SC_MEMLOCK_RANGE
+_POSIX_MEMORY_PROTECTION, _SC_MEMORY_PROTECTION
+_POSIX_MESSAGE_PASSING, _SC_MESSAGE_PASSING
+_POSIX_MONOTONIC_CLOCK, _SC_MONOTONIC_CLOCK
+_POSIX_PRIORITIZED_IO, _SC_PRIORITIZED_IO
+_POSIX_PRIORITY_SCHEDULING, _SC_PRIORITY_SCHEDULING
+_POSIX_READER_WRITER_LOCKS, _SC_READER_WRITER_LOCKS
+_POSIX_REALTIME_SIGNALS, _SC_REALTIME_SIGNALS
+_POSIX_REGEXP, _SC_REGEXP
+_POSIX_SAVED_IDS, _SC_SAVED_IDS
+_POSIX_SEMAPHORES, _SC_SEMAPHORES
+_POSIX_SHARED_MEMORY_OBJECTS, _SC_SHARED_MEMORY_OBJECTS
+_POSIX_SHELL, _SC_SHELL
+_POSIX_SPAWN, _SC_SPAWN
+_POSIX_SPIN_LOCKS, _SC_SPIN_LOCKS
+_POSIX_SPORADIC_SERVER, _SC_SPORADIC_SERVER
+_POSIX_SYNCHRONIZED_IO, _SC_SYNCHRONIZED_IO
+_POSIX_THREADS, _SC_THREADS
+_POSIX_THREAD_ATTR_STACKADDR, _SC_THREAD_ATTR_STACKADDR
+_POSIX_THREAD_ATTR_STACKSIZE, _SC_THREAD_ATTR_STACKSIZE
+_POSIX_THREAD_CPUTIME, _SC_THREAD_CPUTIME
+_POSIX_THREAD_PRIORITY_SCHEDULING, _SC_THREAD_PRIORITY_SCHEDULING
+_POSIX_THREAD_PRIO_INHERIT, _SC_THREAD_PRIO_INHERIT
+_POSIX_THREAD_PRIO_PROTECT, _SC_THREAD_PRIO_PROTECT
+_POSIX_THREAD_PROCESS_SHARED, _SC_THREAD_PROCESS_SHARED
+_POSIX_THREAD_SAFE_FUNCTIONS, _SC_THREAD_SAFE_FUNCTIONS
+_POSIX_THREAD_SPORADIC_SERVER, _SC_THREAD_SPORADIC_SERVER
+_POSIX_TIMEOUTS, _SC_TIMEOUTS
+_POSIX_TRACE, _SC_TRACE
+_POSIX_TRACE_EVENT_FILTER, _SC_TRACE_EVENT_FILTER
+_POSIX_TRACE_INHERIT, _SC_TRACE_INHERIT
+_POSIX_TRACE_LOG, _SC_TRACE_LOG
+_POSIX_TIMERS, _SC_TIMERS
+_POSIX_TYPED_MEMORY_OBJECTS, _SC_TYPED_MEMORY_OBJECTS
+_POSIX_VERSION, _SC_VERSION
+_POSIX_V6_ILP32_OFF32, _SC_V6_ILP32_OFF32
+_POSIX_V6_ILP32_OFFBIG, _SC_V6_ILP32_OFFBIG
+_POSIX_V6_LP64_OFF64, _SC_V6_LP64_OFF64
+_POSIX_V6_LPBIG_OFFBIG, _SC_V6_LPBIG_OFFBIG
+_XOPEN_CRYPT, _SC_XOPEN_CRYPT
+_XOPEN_ENH_I18N, _SC_XOPEN_ENH_I18N
+_XOPEN_LEGACY, _SC_XOPEN_LEGACY
+_XOPEN_REALTIME, _SC_XOPEN_REALTIME
+_XOPEN_REALTIME_THREADS, _SC_XOPEN_REALTIME_THREADS
+_XOPEN_SHM, _SC_XOPEN_SHM
+_XOPEN_UNIX, _SC_XOPEN_UNIX
+_XOPEN_VERSION, _SC_XOPEN_VERSION
+_XOPEN_XCU_VERSION, _SC_XCU_VERSION
+%%
+int
+find_sysconf(const char *name, int *key)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *key = rv->key;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+void
+foreach_sysconf(void (*func)(const char *, int))
+{
+ const struct map *mp;
+
+ for (mp = wordlist; mp->name != NULL; mp++) {
+ if (mp->valid)
+ func(mp->name, mp->key);
+ }
+}
diff --git a/usr.bin/getconf/tests/Makefile b/usr.bin/getconf/tests/Makefile
new file mode 100644
index 000000000000..e29a1876a826
--- /dev/null
+++ b/usr.bin/getconf/tests/Makefile
@@ -0,0 +1,7 @@
+ATF_TESTS_SH+= getconf_test
+
+PROGS+= arch_type
+
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/getconf/tests/Makefile.depend b/usr.bin/getconf/tests/Makefile.depend
new file mode 100644
index 000000000000..d80b3a4991d1
--- /dev/null
+++ b/usr.bin/getconf/tests/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/getconf/tests/arch_type.c b/usr.bin/getconf/tests/arch_type.c
new file mode 100644
index 000000000000..731ddae656bb
--- /dev/null
+++ b/usr.bin/getconf/tests/arch_type.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 Enji Cooper <ngie@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(void)
+{
+ bool known_arch_type;
+
+ known_arch_type = false;
+#ifdef __LP64__
+ printf("LP64\n");
+ known_arch_type = true;
+#endif
+#ifdef __LP32__
+ printf("LP32\n");
+ known_arch_type = true;
+#endif
+#ifdef __ILP32__
+ printf("ILP32\n");
+ known_arch_type = true;
+#endif
+
+ if (known_arch_type)
+ exit(0);
+
+ fprintf(stderr, "unknown architecture type detected\n");
+ assert(0);
+}
diff --git a/usr.bin/getconf/tests/getconf_test.sh b/usr.bin/getconf/tests/getconf_test.sh
new file mode 100755
index 000000000000..95403db7115d
--- /dev/null
+++ b/usr.bin/getconf/tests/getconf_test.sh
@@ -0,0 +1,119 @@
+#
+# Copyright (c) 2017 Dell EMC
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+POSITIVE_EXP_EXPR_RE='match:[1-9][0-9]*'
+
+POSIX_CONSTANTS="ARG_MAX PAGESIZE"
+POSIX_PATH_CONSTANTS="NAME_MAX PATH_MAX"
+SUPPORTED_32BIT_PROGRAM_ENVS="POSIX_V6_ILP32_OFFBIG"
+SUPPORTED_64BIT_PROGRAM_ENVS="POSIX_V6_LP64_OFF64"
+UNAVAILABLE_PROGRAM_ENVS="I_AM_BOGUS"
+UNSUPPORTED_32BIT_PROGRAM_ENVS="POSIX_V6_LP64_OFF64"
+UNSUPPORTED_64BIT_PROGRAM_ENVS="POSIX_V6_ILP32_OFFBIG"
+
+XOPEN_CONSTANTS=
+
+# XXX: hardcoded sysexits
+EX_USAGE=64
+EX_UNAVAILABLE=69
+
+set_program_environments()
+{
+ atf_check -o save:arch_type.out $(atf_get_srcdir)/arch_type
+ arch_type=$(cat arch_type.out)
+ case "$arch_type" in
+ ILP32|LP32)
+ SUPPORTED_PROGRAM_ENVS="$SUPPORTED_PROGRAM_ENVS $SUPPORTED_32BIT_PROGRAM_ENVS"
+ UNSUPPORTED_PROGRAM_ENVS="$UNSUPPORTED_PROGRAM_ENVS $UNSUPPORTED_32BIT_PROGRAM_ENVS"
+ ;;
+ LP64)
+ SUPPORTED_PROGRAM_ENVS="$SUPPORTED_PROGRAM_ENVS $SUPPORTED_64BIT_PROGRAM_ENVS"
+ UNSUPPORTED_PROGRAM_ENVS="$UNSUPPORTED_PROGRAM_ENVS $UNSUPPORTED_64BIT_PROGRAM_ENVS"
+ ;;
+ *)
+ atf_fail "arch_type output unexpected: $arch_type"
+ ;;
+ esac
+}
+
+atf_test_case no_programming_environment
+no_programming_environment_head()
+{
+ atf_set "descr" "Test some POSIX constants as a positive functional test"
+}
+
+no_programming_environment_body()
+{
+ for var in $POSIX_CONSTANTS; do
+ atf_check -o "$POSITIVE_EXP_EXPR_RE" getconf $var
+ done
+ for var in $POSIX_PATH_CONSTANTS; do
+ atf_check -o "$POSITIVE_EXP_EXPR_RE" getconf $var .
+ done
+}
+
+atf_test_case programming_environment
+programming_environment_head()
+{
+ atf_set "descr" "Test some constants with specific programming environments"
+}
+
+programming_environment_body()
+{
+ set_program_environments
+
+ for prog_env in ${SUPPORTED_PROGRAM_ENVS}; do
+ for var in $POSIX_CONSTANTS; do
+ atf_check -o "$POSITIVE_EXP_EXPR_RE" \
+ getconf -v $prog_env $var
+ done
+ done
+}
+
+atf_test_case programming_environment_unsupported
+programming_environment_unsupported_head()
+{
+ atf_set "descr" "Test for unsupported environments"
+}
+
+programming_environment_unsupported_body()
+{
+ set_program_environments
+
+ for prog_env in ${UNSUPPORTED_PROGRAM_ENVS}; do
+ for var in $POSIX_CONSTANTS; do
+ atf_check -e not-empty -s exit:$EX_UNAVAILABLE \
+ getconf -v $prog_env $var
+ done
+ done
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case no_programming_environment
+ atf_add_test_case programming_environment
+ atf_add_test_case programming_environment_unsupported
+}
diff --git a/usr.bin/getconf/unsigned_limits.gperf b/usr.bin/getconf/unsigned_limits.gperf
new file mode 100644
index 000000000000..8950828ee176
--- /dev/null
+++ b/usr.bin/getconf/unsigned_limits.gperf
@@ -0,0 +1,41 @@
+%{
+/*
+ * Copyright is disclaimed as to the contents of this file.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <limits.h>
+
+#include "getconf.h"
+
+/*
+ * Override gperf's built-in external scope.
+ */
+static const struct map *in_word_set(const char *str);
+
+%}
+struct map { const char *name; uintmax_t value; int valid; };
+%%
+UCHAR_MAX, UCHAR_MAX
+UINT_MAX, UINT_MAX
+ULLONG_MAX, ULLONG_MAX
+ULONG_MAX, ULONG_MAX
+USHRT_MAX, USHRT_MAX
+%%
+int
+find_unsigned_limit(const char *name, uintmax_t *value)
+{
+ const struct map *rv;
+
+ rv = in_word_set(name);
+ if (rv != NULL) {
+ if (rv->valid) {
+ *value = rv->value;
+ return 1;
+ }
+ return -1;
+ }
+ return 0;
+}
diff --git a/usr.bin/getent/Makefile b/usr.bin/getent/Makefile
new file mode 100644
index 000000000000..f6df38652766
--- /dev/null
+++ b/usr.bin/getent/Makefile
@@ -0,0 +1,3 @@
+PROG= getent
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/getent/Makefile.depend b/usr.bin/getent/Makefile.depend
new file mode 100644
index 000000000000..90cdaad976de
--- /dev/null
+++ b/usr.bin/getent/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/rpc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/getent/getent.1 b/usr.bin/getent/getent.1
new file mode 100644
index 000000000000..a0a6befd7aef
--- /dev/null
+++ b/usr.bin/getent/getent.1
@@ -0,0 +1,142 @@
+.\" $NetBSD: getent.1,v 1.13 2005/09/11 23:16:15 wiz Exp $
+.\"
+.\" Copyright (c) 2004 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Luke Mewburn.
+.\"
+.\" 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 October 24, 2020
+.Dt GETENT 1
+.Os
+.Sh NAME
+.Nm getent
+.Nd get entries from administrative database
+.Sh SYNOPSIS
+.Nm
+.Ar database
+.Op Ar key ...
+.Sh DESCRIPTION
+The
+.Nm
+utility retrieves and displays entries from the administrative
+database specified by
+.Ar database ,
+using the lookup order specified in
+.Xr nsswitch.conf 5 .
+The display format for a given
+.Ar database
+is as per the
+.Dq traditional
+file format for that database.
+.Pp
+The
+.Ar database
+argument may be one of:
+.Pp
+.Bl -column ".Li netgroup" -offset indent -compact
+.Sy Database Ta Sy Display format
+.It Li ethers Ta address name
+.It Li group Ta group:passwd:gid:[member[,member]...]
+.It Li hosts Ta address name [alias ...]
+.It Li netgroup Ta (host,user,domain) [...]
+.It Li networks Ta name network [alias ...]
+.It Li passwd Ta user:passwd:uid:gid:gecos:home_dir:shell
+.It Li protocols Ta name protocol [alias ...]
+.It Li rpc Ta name number [alias ...]
+.It Li services Ta name port/protocol [alias ...]
+.It Li shells Ta /path/to/shell
+.It Li utmpx Ta [time] type: properties
+.El
+.Pp
+If one or more
+.Ar key
+arguments are provided, they will be looked up in
+.Ar database
+using the appropriate function.
+For example,
+.Dq Li passwd
+supports a numeric UID or user name;
+.Dq Li hosts
+supports an IPv4 address, IPv6 address, or host name;
+and
+.Dq Li services
+supports a service name, service name/protocol name, numeric port, or
+numeric port/protocol name.
+.Pp
+If no
+.Ar key
+is provided and
+.Ar database
+supports enumeration, all entries for
+.Ar database
+will be retrieved using the appropriate enumeration function and printed.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success,
+1 if there was an error in the command syntax,
+2 if one of the specified key names was not found in
+.Ar database ,
+or 3 if there is no support for enumeration on
+.Ar database .
+.Sh EXAMPLES
+Show entry for user sshd from the passwd database:
+.Bd -literal -offset indent
+$ getent passwd sshd
+sshd:*:22:22:Secure Shell Daemon:/var/empty:/usr/sbin/nologin
+.Ed
+.Pp
+Show entry for TCP from the protocols database:
+.Bd -literal -offset indent
+$ getent protocols tcp
+tcp 6 TCP
+.Ed
+.Pp
+Show entry for the localhost IPv6 address ::1 from the hosts database:
+.Bd -literal -offset indent
+$ getent hosts ::1
+::1 localhost localhost.my.domain
+.Ed
+.Sh SEE ALSO
+.Xr getutxent 3 ,
+.Xr ethers 5 ,
+.Xr group 5 ,
+.Xr hosts 5 ,
+.Xr netgroup 5 ,
+.Xr networks 5 ,
+.Xr nsswitch.conf 5 ,
+.Xr passwd 5 ,
+.Xr protocols 5 ,
+.Xr rpc 5 ,
+.Xr services 5 ,
+.Xr shells 5
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.Nx 3.0 ,
+and was imported into
+.Fx 7.0 .
+It was based on the command of the same name in Solaris and Linux.
diff --git a/usr.bin/getent/getent.c b/usr.bin/getent/getent.c
new file mode 100644
index 000000000000..34fcf0571a43
--- /dev/null
+++ b/usr.bin/getent/getent.c
@@ -0,0 +1,715 @@
+/* $NetBSD: getent.c,v 1.7 2005/08/24 14:31:02 ginsbach Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 <sys/cdefs.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+#include <netinet/in.h> /* for INET6_ADDRSTRLEN */
+#include <rpc/rpcent.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+
+static int usage(void);
+static int parsenum(const char *, unsigned long *);
+static int ethers(int, char *[]);
+static int group(int, char *[]);
+static int hosts(int, char *[]);
+static int netgroup(int, char *[]);
+static int networks(int, char *[]);
+static int passwd(int, char *[]);
+static int protocols(int, char *[]);
+static int rpc(int, char *[]);
+static int services(int, char *[]);
+static int shells(int, char *[]);
+static int utmpx(int, char *[]);
+
+enum {
+ RV_OK = 0,
+ RV_USAGE = 1,
+ RV_NOTFOUND = 2,
+ RV_NOENUM = 3
+};
+
+static struct getentdb {
+ const char *name;
+ int (*callback)(int, char *[]);
+} databases[] = {
+ { "ethers", ethers, },
+ { "group", group, },
+ { "hosts", hosts, },
+ { "netgroup", netgroup, },
+ { "networks", networks, },
+ { "passwd", passwd, },
+ { "protocols", protocols, },
+ { "rpc", rpc, },
+ { "services", services, },
+ { "shells", shells, },
+ { "utmpx", utmpx, },
+
+ { NULL, NULL, },
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct getentdb *curdb;
+
+ setprogname(argv[0]);
+
+ if (argc < 2)
+ usage();
+ for (curdb = databases; curdb->name != NULL; curdb++) {
+ if (strcmp(curdb->name, argv[1]) == 0) {
+ exit(curdb->callback(argc, argv));
+ }
+ }
+ fprintf(stderr, "Unknown database: %s\n", argv[1]);
+ usage();
+ /* NOTREACHED */
+ return RV_USAGE;
+}
+
+static int
+usage(void)
+{
+ struct getentdb *curdb;
+
+ fprintf(stderr, "Usage: %s database [key ...]\n",
+ getprogname());
+ fprintf(stderr, " database may be one of:\n\t");
+ for (curdb = databases; curdb->name != NULL; curdb++) {
+ fprintf(stderr, " %s", curdb->name);
+ }
+ fprintf(stderr, "\n");
+ exit(RV_USAGE);
+ /* NOTREACHED */
+}
+
+static int
+parsenum(const char *word, unsigned long *result)
+{
+ unsigned long num;
+ char *ep;
+
+ assert(word != NULL);
+ assert(result != NULL);
+
+ if (!isdigit((unsigned char)word[0]))
+ return 0;
+ errno = 0;
+ num = strtoul(word, &ep, 10);
+ if (num == ULONG_MAX && errno == ERANGE)
+ return 0;
+ if (*ep != '\0')
+ return 0;
+ *result = num;
+ return 1;
+}
+
+/*
+ * printfmtstrings --
+ * vprintf(format, ...),
+ * then the aliases (beginning with prefix, separated by sep),
+ * then a newline
+ */
+static void
+printfmtstrings(char *strings[], const char *prefix, const char *sep,
+ const char *fmt, ...)
+{
+ va_list ap;
+ const char *curpref;
+ int i;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+
+ curpref = prefix;
+ for (i = 0; strings[i] != NULL; i++) {
+ printf("%s%s", curpref, strings[i]);
+ curpref = sep;
+ }
+ printf("\n");
+ va_end(ap);
+}
+
+/*
+ * ethers
+ */
+static int
+ethers(int argc, char *argv[])
+{
+ char hostname[MAXHOSTNAMELEN + 1], *hp;
+ struct ether_addr ea, *eap;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define ETHERSPRINT printf("%-17s %s\n", ether_ntoa(eap), hp)
+
+ rv = RV_OK;
+ if (argc == 2) {
+ fprintf(stderr, "Enumeration not supported on ethers\n");
+ rv = RV_NOENUM;
+ } else {
+ for (i = 2; i < argc; i++) {
+ if ((eap = ether_aton(argv[i])) == NULL) {
+ eap = &ea;
+ hp = argv[i];
+ if (ether_hostton(hp, eap) != 0) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ } else {
+ hp = hostname;
+ if (ether_ntohost(hp, eap) != 0) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ ETHERSPRINT;
+ }
+ }
+ return rv;
+}
+
+/*
+ * group
+ */
+
+static int
+group(int argc, char *argv[])
+{
+ struct group *gr;
+ unsigned long id;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define GROUPPRINT printfmtstrings(gr->gr_mem, ":", ",", "%s:%s:%u", \
+ gr->gr_name, gr->gr_passwd, gr->gr_gid)
+
+ setgroupent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((gr = getgrent()) != NULL)
+ GROUPPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ gr = getgrgid((gid_t)id);
+ else
+ gr = getgrnam(argv[i]);
+ if (gr != NULL)
+ GROUPPRINT;
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endgrent();
+ return rv;
+}
+
+
+/*
+ * hosts
+ */
+
+static void
+hostsprint(const struct hostent *he)
+{
+ char buf[INET6_ADDRSTRLEN];
+
+ assert(he != NULL);
+ if (inet_ntop(he->h_addrtype, he->h_addr, buf, sizeof(buf)) == NULL)
+ strlcpy(buf, "# unknown", sizeof(buf));
+ printfmtstrings(he->h_aliases, " ", " ", "%-16s %s", buf, he->h_name);
+}
+
+static int
+hosts(int argc, char *argv[])
+{
+ struct hostent *he4, *he6;
+ char addr[IN6ADDRSZ];
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+ sethostent(1);
+ he4 = he6 = NULL;
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((he4 = gethostent()) != NULL)
+ hostsprint(he4);
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (inet_pton(AF_INET6, argv[i], (void *)addr) > 0) {
+ he6 = gethostbyaddr(addr, IN6ADDRSZ, AF_INET6);
+ if (he6 != NULL)
+ hostsprint(he6);
+ } else if (inet_pton(AF_INET, argv[i],
+ (void *)addr) > 0) {
+ he4 = gethostbyaddr(addr, INADDRSZ, AF_INET);
+ if (he4 != NULL)
+ hostsprint(he4);
+ } else {
+ he6 = gethostbyname2(argv[i], AF_INET6);
+ if (he6 != NULL)
+ hostsprint(he6);
+ he4 = gethostbyname(argv[i]);
+ if (he4 != NULL)
+ hostsprint(he4);
+ }
+ if ( he4 == NULL && he6 == NULL ) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endhostent();
+ return rv;
+}
+
+/*
+ * networks
+ */
+static void
+networksprint(const struct netent *ne)
+{
+ char buf[INET6_ADDRSTRLEN];
+ struct in_addr ianet;
+
+ assert(ne != NULL);
+ ianet = inet_makeaddr(ne->n_net, 0);
+ if (inet_ntop(ne->n_addrtype, &ianet, buf, sizeof(buf)) == NULL)
+ strlcpy(buf, "# unknown", sizeof(buf));
+ printfmtstrings(ne->n_aliases, " ", " ", "%-16s %s", ne->n_name, buf);
+}
+
+static int
+networks(int argc, char *argv[])
+{
+ struct netent *ne;
+ in_addr_t net;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+ setnetent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((ne = getnetent()) != NULL)
+ networksprint(ne);
+ } else {
+ for (i = 2; i < argc; i++) {
+ net = inet_network(argv[i]);
+ if (net != INADDR_NONE)
+ ne = getnetbyaddr(net, AF_INET);
+ else
+ ne = getnetbyname(argv[i]);
+ if (ne != NULL)
+ networksprint(ne);
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endnetent();
+ return rv;
+}
+
+/*
+ * passwd
+ */
+static int
+passwd(int argc, char *argv[])
+{
+ struct passwd *pw;
+ unsigned long id;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define PASSWDPRINT printf("%s:%s:%u:%u:%s:%s:%s\n", \
+ pw->pw_name, pw->pw_passwd, pw->pw_uid, \
+ pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell)
+
+ setpassent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((pw = getpwent()) != NULL)
+ PASSWDPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ pw = getpwuid((uid_t)id);
+ else
+ pw = getpwnam(argv[i]);
+ if (pw != NULL)
+ PASSWDPRINT;
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endpwent();
+ return rv;
+}
+
+/*
+ * protocols
+ */
+static int
+protocols(int argc, char *argv[])
+{
+ struct protoent *pe;
+ unsigned long id;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define PROTOCOLSPRINT printfmtstrings(pe->p_aliases, " ", " ", \
+ "%-16s %5d", pe->p_name, pe->p_proto)
+
+ setprotoent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((pe = getprotoent()) != NULL)
+ PROTOCOLSPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ pe = getprotobynumber((int)id);
+ else
+ pe = getprotobyname(argv[i]);
+ if (pe != NULL)
+ PROTOCOLSPRINT;
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endprotoent();
+ return rv;
+}
+
+/*
+ * rpc
+ */
+static int
+rpc(int argc, char *argv[])
+{
+ struct rpcent *re;
+ unsigned long id;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define RPCPRINT printfmtstrings(re->r_aliases, " ", " ", \
+ "%-16s %6d", \
+ re->r_name, re->r_number)
+
+ setrpcent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((re = getrpcent()) != NULL)
+ RPCPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ if (parsenum(argv[i], &id))
+ re = getrpcbynumber((int)id);
+ else
+ re = getrpcbyname(argv[i]);
+ if (re != NULL)
+ RPCPRINT;
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endrpcent();
+ return rv;
+}
+
+/*
+ * services
+ */
+static int
+services(int argc, char *argv[])
+{
+ struct servent *se;
+ unsigned long id;
+ char *proto;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define SERVICESPRINT printfmtstrings(se->s_aliases, " ", " ", \
+ "%-16s %5d/%s", \
+ se->s_name, ntohs(se->s_port), se->s_proto)
+
+ setservent(1);
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((se = getservent()) != NULL)
+ SERVICESPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ proto = strchr(argv[i], '/');
+ if (proto != NULL)
+ *proto++ = '\0';
+ if (parsenum(argv[i], &id))
+ se = getservbyport(htons((u_short)id), proto);
+ else
+ se = getservbyname(argv[i], proto);
+ if (se != NULL)
+ SERVICESPRINT;
+ else {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endservent();
+ return rv;
+}
+
+/*
+ * shells
+ */
+static int
+shells(int argc, char *argv[])
+{
+ const char *sh;
+ int i, rv;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define SHELLSPRINT printf("%s\n", sh)
+
+ setusershell();
+ rv = RV_OK;
+ if (argc == 2) {
+ while ((sh = getusershell()) != NULL)
+ SHELLSPRINT;
+ } else {
+ for (i = 2; i < argc; i++) {
+ setusershell();
+ while ((sh = getusershell()) != NULL) {
+ if (strcmp(sh, argv[i]) == 0) {
+ SHELLSPRINT;
+ break;
+ }
+ }
+ if (sh == NULL) {
+ rv = RV_NOTFOUND;
+ break;
+ }
+ }
+ }
+ endusershell();
+ return rv;
+}
+
+/*
+ * netgroup
+ */
+static int
+netgroup(int argc, char *argv[])
+{
+ char *host, *user, *domain;
+ int first;
+ int rv, i;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+#define NETGROUPPRINT(s) (((s) != NULL) ? (s) : "")
+
+ rv = RV_OK;
+ if (argc == 2) {
+ fprintf(stderr, "Enumeration not supported on netgroup\n");
+ rv = RV_NOENUM;
+ } else {
+ for (i = 2; i < argc; i++) {
+ setnetgrent(argv[i]);
+ first = 1;
+ while (getnetgrent(&host, &user, &domain) != 0) {
+ if (first) {
+ first = 0;
+ (void)fputs(argv[i], stdout);
+ }
+ (void)printf(" (%s,%s,%s)",
+ NETGROUPPRINT(host),
+ NETGROUPPRINT(user),
+ NETGROUPPRINT(domain));
+ }
+ if (!first)
+ (void)putchar('\n');
+ endnetgrent();
+ }
+ }
+ return rv;
+}
+
+/*
+ * utmpx
+ */
+
+#define UTMPXPRINTID do { \
+ size_t i; \
+ for (i = 0; i < sizeof ut->ut_id; i++) \
+ printf("%02hhx", ut->ut_id[i]); \
+} while (0)
+
+static void
+utmpxprint(const struct utmpx *ut)
+{
+
+ if (ut->ut_type == EMPTY)
+ return;
+
+ printf("[%jd.%06u -- %.24s] ",
+ (intmax_t)ut->ut_tv.tv_sec, (unsigned int)ut->ut_tv.tv_usec,
+ ctime(&ut->ut_tv.tv_sec));
+
+ switch (ut->ut_type) {
+ case BOOT_TIME:
+ printf("system boot\n");
+ return;
+ case SHUTDOWN_TIME:
+ printf("system shutdown\n");
+ return;
+ case OLD_TIME:
+ printf("old system time\n");
+ return;
+ case NEW_TIME:
+ printf("new system time\n");
+ return;
+ case USER_PROCESS:
+ printf("user process: id=\"");
+ UTMPXPRINTID;
+ printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n",
+ ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host);
+ break;
+ case INIT_PROCESS:
+ printf("init process: id=\"");
+ UTMPXPRINTID;
+ printf("\" pid=\"%d\"\n", ut->ut_pid);
+ break;
+ case LOGIN_PROCESS:
+ printf("login process: id=\"");
+ UTMPXPRINTID;
+ printf("\" pid=\"%d\" user=\"%s\" line=\"%s\" host=\"%s\"\n",
+ ut->ut_pid, ut->ut_user, ut->ut_line, ut->ut_host);
+ break;
+ case DEAD_PROCESS:
+ printf("dead process: id=\"");
+ UTMPXPRINTID;
+ printf("\" pid=\"%d\"\n", ut->ut_pid);
+ break;
+ default:
+ printf("unknown record type %hu\n", ut->ut_type);
+ break;
+ }
+}
+
+static int
+utmpx(int argc, char *argv[])
+{
+ const struct utmpx *ut;
+ const char *file = NULL;
+ int rv = RV_OK, db = 0;
+
+ assert(argc > 1);
+ assert(argv != NULL);
+
+ if (argc == 3 || argc == 4) {
+ if (strcmp(argv[2], "active") == 0)
+ db = UTXDB_ACTIVE;
+ else if (strcmp(argv[2], "lastlogin") == 0)
+ db = UTXDB_LASTLOGIN;
+ else if (strcmp(argv[2], "log") == 0)
+ db = UTXDB_LOG;
+ else
+ rv = RV_USAGE;
+ if (argc == 4)
+ file = argv[3];
+ } else {
+ rv = RV_USAGE;
+ }
+
+ if (rv == RV_USAGE) {
+ fprintf(stderr,
+ "Usage: %s utmpx active | lastlogin | log [filename]\n",
+ getprogname());
+ } else if (rv == RV_OK) {
+ if (setutxdb(db, file) != 0)
+ return (RV_NOTFOUND);
+ while ((ut = getutxent()) != NULL)
+ utmpxprint(ut);
+ endutxent();
+ }
+ return (rv);
+}
diff --git a/usr.bin/getopt/Makefile b/usr.bin/getopt/Makefile
new file mode 100644
index 000000000000..1abe599df10f
--- /dev/null
+++ b/usr.bin/getopt/Makefile
@@ -0,0 +1,5 @@
+#
+
+PROG = getopt
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/getopt/Makefile.depend b/usr.bin/getopt/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/getopt/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/getopt/getopt.1 b/usr.bin/getopt/getopt.1
new file mode 100644
index 000000000000..cfd3219f11d2
--- /dev/null
+++ b/usr.bin/getopt/getopt.1
@@ -0,0 +1,133 @@
+.\"
+.Dd August 1, 2015
+.Dt GETOPT 1
+.Os
+.Sh NAME
+.Nm getopt
+.Nd parse command options
+.Sh SYNOPSIS
+.Nm args=\`getopt Ar optstring $*\`
+; errcode=$?; set \-\- $args
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to break up options in command lines for easy parsing by
+shell procedures, and to check for legal options.
+.Ar 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.
+The special option
+.Ql \-\-
+is used to delimit the end of the options.
+The
+.Nm
+utility will place
+.Ql \-\-
+in the arguments at the end of the options,
+or recognize it if used explicitly.
+The shell arguments
+(\fB$1 $2\fR ...) are reset so that each option is
+preceded by a
+.Ql \-
+and in its own shell argument;
+each option argument is also in its own shell argument.
+.Sh EXIT STATUS
+The
+.Nm
+utility prints an error message on the standard error output and exits with
+status > 0 when it encounters an option letter not included in
+.Ar optstring .
+.Sh EXAMPLES
+The following code fragment shows how one might process the arguments
+for a command that can take the options
+.Fl a
+and
+.Fl b ,
+and the option
+.Fl o ,
+which requires an argument.
+.Bd -literal -offset indent
+args=\`getopt abo: $*\`
+# you should not use \`getopt abo: "$@"\` since that would parse
+# the arguments differently from what the set command below does.
+if [ $? -ne 0 ]; then
+ echo 'Usage: ...'
+ exit 2
+fi
+set \-\- $args
+# You cannot use the set command with a backquoted getopt directly,
+# since the exit code from getopt would be shadowed by those of set,
+# which is zero by definition.
+while :; do
+ case "$1" in
+ \-a|\-b)
+ echo "flag $1 set"; sflags="${1#-}$sflags"
+ shift
+ ;;
+ \-o)
+ echo "oarg is '$2'"; oarg="$2"
+ shift; shift
+ ;;
+ \-\-)
+ shift; break
+ ;;
+ esac
+done
+echo "single-char flags: '$sflags'"
+echo "oarg is '$oarg'"
+.Ed
+.Pp
+This code will accept any of the following as equivalent:
+.Bd -literal -offset indent
+cmd \-aoarg file1 file2
+cmd \-a \-o arg file1 file2
+cmd \-oarg -a file1 file2
+cmd \-a \-oarg \-\- file1 file2
+.Ed
+.Sh SEE ALSO
+.Xr getopts 1 ,
+.Xr sh 1 ,
+.Xr getopt 3
+.Sh HISTORY
+Written by
+.An Henry Spencer ,
+working from a Bell Labs manual page.
+Behavior believed identical to the Bell version.
+Example changed in
+.Fx
+version 3.2 and 4.0.
+.Sh BUGS
+Whatever
+.Xr getopt 3
+has.
+.Pp
+Arguments containing white space or embedded shell metacharacters
+generally will not survive intact; this looks easy to fix but
+is not.
+People trying to fix
+.Nm
+or the example in this manpage should check the history of this file
+in
+.Fx .
+.Pp
+The error message for an invalid option is identified as coming
+from
+.Nm
+rather than from the shell procedure containing the invocation
+of
+.Nm ;
+this again is hard to fix.
+.Pp
+The precise best way to use the
+.Nm set
+command to set the arguments without disrupting the value(s) of
+shell options varies from one shell version to another.
+.Pp
+Each shellscript has to carry complex code to parse arguments halfway
+correctly (like the example presented here).
+A better getopt-like tool
+would move much of the complexity into the tool and keep the client
+shell scripts simpler.
diff --git a/usr.bin/getopt/getopt.c b/usr.bin/getopt/getopt.c
new file mode 100644
index 000000000000..09036a34b657
--- /dev/null
+++ b/usr.bin/getopt/getopt.c
@@ -0,0 +1,41 @@
+#include <sys/cdefs.h>
+/*
+ * This material, written by Henry Spencer, was released by him
+ * into the public domain and is thus not subject to any copyright.
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int status = 0;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ optind = 2; /* Past the program name and the option letters. */
+ while ((c = getopt(argc, argv, argv[1])) != -1)
+ switch (c) {
+ case '?':
+ status = 1; /* getopt routine gave message */
+ break;
+ default:
+ if (optarg != NULL)
+ printf(" -%c %s", c, optarg);
+ else
+ printf(" -%c", c);
+ break;
+ }
+ printf(" --");
+ for (; optind < argc; optind++)
+ printf(" %s", argv[optind]);
+ printf("\n");
+ return status;
+}
diff --git a/usr.bin/gh-bc/Makefile b/usr.bin/gh-bc/Makefile
new file mode 100644
index 000000000000..0fdc687c0e50
--- /dev/null
+++ b/usr.bin/gh-bc/Makefile
@@ -0,0 +1,130 @@
+.include <src.opts.mk>
+
+PROG= gh-bc
+PROGNAME= bc
+
+BCDIR= ${SRCTOP}/contrib/${PROGNAME}
+
+SRCS= args.c bc.c bc_lex.c bc_parse.c data.c dc.c dc_lex.c dc_parse.c file.c history.c
+SRCS+= lang.c lex.c main.c num.c opt.c parse.c program.c rand.c read.c vector.c vm.c
+SRCS+= bc_help.c dc_help.c lib.c lib2.c
+
+LIBADD= edit
+
+MAN= bc.1 dc.1
+
+LINKS= ${BINDIR}/bc ${BINDIR}/dc
+
+.PATH: ${BCDIR}/src ${BCDIR}/gen ${BCDIR}/manuals ${.OBJDIR}
+
+CATALOGS= en_US.UTF-8
+CATALOGS+= de_DE.UTF-8 de_DE.ISO8859-1
+CATALOGS+= es_ES.UTF-8 es_ES.ISO8859-1
+CATALOGS+= fr_FR.UTF-8 fr_FR.ISO8859-1
+CATALOGS+= ja_JP.UTF-8 ja_JP.eucJP
+CATALOGS+= nl_NL.UTF-8 nl_NL.ISO8859-1
+CATALOGS+= pl_PL.UTF-8 pl_PL.ISO8859-2
+CATALOGS+= pt_PT.UTF-8 pt_PT.ISO8859-1
+CATALOGS+= ru_RU.UTF-8 ru_RU.ISO8859-5 ru_RU.CP1251 ru_RU.CP866 ru_RU.KOI8-R
+CATALOGS+= zh_CN.UTF-8 zh_CN.eucCN zh_CN.GB18030 zh_CN.GB2312 zh_CN.GBK
+
+NLSNAME= bc
+NLSSRCDIR= ${BCDIR}/locales
+
+CFLAGS+= -DBC_DEFAULT_BANNER=0
+CFLAGS+= -DBC_DEFAULT_DIGIT_CLAMP=0
+CFLAGS+= -DBC_DEFAULT_EXPR_EXIT=1
+CFLAGS+= -DBC_DEFAULT_PROMPT=0
+CFLAGS+= -DBC_DEFAULT_SIGINT_RESET=1
+CFLAGS+= -DBC_DEFAULT_TTY_MODE=1
+CFLAGS+= -DBC_ENABLED=1
+CFLAGS+= -DBC_ENABLE_AFL=0
+CFLAGS+= -DBC_ENABLE_EDITLINE=1
+CFLAGS+= -DBC_ENABLE_EXTRA_MATH=1
+CFLAGS+= -DBC_ENABLE_HISTORY=1
+CFLAGS+= -DBC_ENABLE_LIBRARY=0
+CFLAGS+= -DBC_ENABLE_MEMCHECK=0
+CFLAGS+= -DBC_EXCLUDE_EXTRA_MATH=0
+
+CFLAGS+= -DDC_DEFAULT_DIGIT_CLAMP=0
+CFLAGS+= -DDC_DEFAULT_EXPR_EXIT=1
+CFLAGS+= -DDC_DEFAULT_PROMPT=0
+CFLAGS+= -DDC_DEFAULT_SIGINT_RESET=1
+CFLAGS+= -DDC_DEFAULT_TTY_MODE=0
+CFLAGS+= -DDC_ENABLED=1
+
+CFLAGS+= -DBUILD_TYPE=A
+CFLAGS+= -DMAINEXEC=${PROGNAME}
+CFLAGS+= -DNDEBUG
+CFLAGS+= -DNLSPATH=/usr/share/nls/%L/%N.cat
+CFLAGS+= -I${BCDIR}/include
+
+# prevent floating point incompatibilities caused by -flto on some architectures
+.if ${MACHINE_ARCH} != riscv64
+CFLAGS+= -flto
+.endif
+
+HAS_TESTS= yes
+SUBDIR.${MK_TESTS}+= tests
+
+.if ${MK_NLS_CATALOGS} == "no"
+CFLAGS+= -DBC_ENABLE_NLS=0
+MAN_SRC_BC= bc/N.1
+MAN_SRC_DC= dc/N.1
+.else
+CFLAGS+= -DBC_ENABLE_NLS=1
+MAN_SRC_BC= bc/A.1
+MAN_SRC_DC= dc/A.1
+
+.for catalog in ${CATALOGS}
+NLS+= ${catalog:C/.*://}
+NLSSRCFILES_${catalog:C/.*://}= ${catalog:C/.*://}.msg
+.endfor
+
+NLSLINKS_en_US.UTF-8+= en_AU.UTF-8 en_CA.UTF-8 en_GB.UTF-8 en_IE.UTF-8 \
+ en_NZ.UTF-8 C
+NLSLINKS_en_US.UTF-8+= en_AU.US-ASCII en_CA.US-ASCII en_GB.US-ASCII \
+ en_NZ.US-ASCII
+NLSLINKS_en_US.UTF-8+= en_AU.ISO8859-1 en_CA.ISO8859-1 en_GB.ISO8859-1 \
+ en_NZ.ISO8859-1 en_US.ISO8859-1
+NLSLINKS_en_US.UTF-8+= en_AU.ISO8859-15 en_CA.ISO8859-15 en_GB.ISO8859-15 \
+ en_NZ.ISO8859-15 en_US.ISO8859-15
+
+NLSLINKS_de_DE.UTF-8+= de_AT.UTF-8 de_CH.UTF-8
+NLSLINKS_de_DE.ISO8859-1+= de_AT.ISO8859-1 de_CH.ISO8859-1
+NLSLINKS_de_DE.ISO8859-1+= de_AT.ISO8859-15 de_CH.ISO8859-15 de_DE.ISO8859-15
+
+NLSLINKS_es_ES.ISO8859-1+= es_ES.ISO8859-15
+
+NLSLINKS_fr_FR.UTF-8+= fr_BE.UTF-8 fr_CA.UTF-8 fr_CH.UTF-8
+NLSLINKS_fr_FR.ISO8859-1+= fr_BE.ISO8859-1 fr_CA.ISO8859-1 fr_CH.ISO8859-1
+NLSLINKS_fr_FR.ISO8859-1+= fr_BE.ISO8859-15 fr_CA.ISO8859-15 fr_CH.ISO8859-15 \
+ fr_FR.ISO8859-15
+
+NLSLINKS_nl_NL.ISO8859-1+= nl_BE.ISO8859-1
+NLSLINKS_nl_NL.ISO8859-1+= nl_BE.ISO8859-15 nl_NL.ISO8859-15
+
+NLSLINKS_pt_PT.UTF-8+= pt_BR.UTF-8
+NLSLINKS_pt_PT.ISO8859-1+= pt_BR.ISO8859-1
+NLSLINKS_pt_PT.ISO8859-1+= pt_PT.ISO8859-15
+.endif
+
+lib.c: lib.bc Makefile
+ cd ${BCDIR} && sh gen/strgen.sh gen/lib.bc ${.OBJDIR}/lib.c 0 bc_lib bc_lib_name "" 1
+
+lib2.c: lib2.bc Makefile
+ cd ${BCDIR} && sh gen/strgen.sh gen/lib2.bc ${.OBJDIR}/lib2.c 0 bc_lib2 bc_lib2_name "" 1
+
+bc_help.c: bc_help.txt Makefile
+ cd ${BCDIR} && sh gen/strgen.sh gen/bc_help.txt ${.OBJDIR}/bc_help.c 0 bc_help "" 1 0
+
+dc_help.c: dc_help.txt Makefile
+ cd ${BCDIR} && sh gen/strgen.sh gen/dc_help.txt ${.OBJDIR}/dc_help.c 0 dc_help "" 1 0
+
+bc.1:
+ ${CP} ${BCDIR}/manuals/${MAN_SRC_BC} ${.OBJDIR}/bc.1
+
+dc.1:
+ ${CP} ${BCDIR}/manuals/${MAN_SRC_DC} ${.OBJDIR}/dc.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gh-bc/tests/Makefile b/usr.bin/gh-bc/tests/Makefile
new file mode 100644
index 000000000000..464ae4b5d3c3
--- /dev/null
+++ b/usr.bin/gh-bc/tests/Makefile
@@ -0,0 +1,65 @@
+.include <bsd.own.mk>
+
+PACKAGE= tests
+
+TEST_DIR= ${SRCTOP}/contrib/bc
+
+TESTSDIR= ${TESTSBASE}/usr.bin/gh-bc
+
+.PATH: ${SRCTOP}/tests
+
+FILESGROUPS+= FILESf
+FILESfPACKAGE= ${PACKAGE}
+FILESfDIR= ${TESTSDIR}/scripts
+FILESf= ${TEST_DIR}/scripts/functions.sh
+FILESfMODE= 0755
+
+FILESGROUPS+= FILEStests
+FILEStestsPACKAGE= ${PACKAGE}
+FILEStestsDIR= ${TESTSDIR}/tests
+FILEStests!= echo ${TEST_DIR}/tests/*.py ${TEST_DIR}/tests/*.sh ${TEST_DIR}/tests/*.txt
+FILEStestsMODE= 0755
+
+FILESGROUPS+= FILESbc
+FILESbcPACKAGE= ${PACKAGE}
+FILESbcDIR= ${TESTSDIR}/tests/bc
+FILESbc!= echo ${TEST_DIR}/tests/bc/*.*
+
+FILESGROUPS+= FILESbc_errors
+FILESbc_errorsPACKAGE= ${PACKAGE}
+FILESbc_errorsDIR= ${TESTSDIR}/tests/bc/errors
+FILESbc_errors!= echo ${TEST_DIR}/tests/bc/errors/*.*
+
+FILESGROUPS+= FILESbc_scripts
+FILESbc_scriptsPACKAGE= ${PACKAGE}
+FILESbc_scriptsDIR= ${TESTSDIR}/tests/bc/scripts
+FILESbc_scripts!= echo ${TEST_DIR}/tests/bc/scripts/*.*
+FILESbc_scriptsMODE= 0755
+
+FILESGROUPS+= FILESdc
+FILESdcPACKAGE= ${PACKAGE}
+FILESdcDIR= ${TESTSDIR}/tests/dc
+FILESdc!= echo ${TEST_DIR}/tests/dc/*.*
+
+FILESGROUPS+= FILESdc_errors
+FILESdc_errorsPACKAGE= ${PACKAGE}
+FILESdc_errorsDIR= ${TESTSDIR}/tests/dc/errors
+FILESdc_errors!= echo ${TEST_DIR}/tests/dc/errors/*.*
+
+FILESGROUPS+= FILESdc_scripts
+FILESdc_scriptsPACKAGE= ${PACKAGE}
+FILESdc_scriptsDIR= ${TESTSDIR}/tests/dc/scripts
+FILESdc_scripts!= echo ${TEST_DIR}/tests/dc/scripts/*.*
+FILESdc_scriptsMODE= 0755
+
+PLAIN_TESTS_SH= bc_tests dc_tests
+
+bc_tests.sh:
+ echo "#!/bin/sh" > ${.TARGET}
+ echo "env LANG=C ${TESTSDIR}/tests/all.sh bc 1 1 0 0 0 bc" >> ${.TARGET}
+
+dc_tests.sh:
+ echo "#!/bin/sh" > ${.TARGET}
+ echo "env LANG=C ${TESTSDIR}/tests/all.sh dc 1 1 0 0 0 dc" >> ${.TARGET}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/gh-bc/tests/Makefile.depend b/usr.bin/gh-bc/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/gh-bc/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gprof/Makefile b/usr.bin/gprof/Makefile
new file mode 100644
index 000000000000..e486dd8ce6d9
--- /dev/null
+++ b/usr.bin/gprof/Makefile
@@ -0,0 +1,10 @@
+PROG= gprof
+SRCS= gprof.c arcs.c dfn.c elf.c lookup.c hertz.c \
+ printgprof.c printlist.c kernel.c
+
+FILES= gprof.flat gprof.callg
+FILESDIR= ${SHAREDIR}/misc
+
+WARNS?= 1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gprof/Makefile.depend b/usr.bin/gprof/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/gprof/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gprof/arcs.c b/usr.bin/gprof/arcs.c
new file mode 100644
index 000000000000..5e8ba06402a3
--- /dev/null
+++ b/usr.bin/gprof/arcs.c
@@ -0,0 +1,947 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include "gprof.h"
+
+#ifdef DEBUG
+int visited;
+int viable;
+int newcycle;
+int oldcycle;
+#endif /* DEBUG */
+
+int topcmp(const void *, const void *);
+
+ /*
+ * add (or just increment) an arc
+ */
+void
+addarc(nltype *parentp, nltype *childp, long count)
+{
+ arctype *arcp;
+
+# ifdef DEBUG
+ if ( debug & TALLYDEBUG ) {
+ printf( "[addarc] %ld arcs from %s to %s\n" ,
+ count , parentp -> name , childp -> name );
+ }
+# endif /* DEBUG */
+ arcp = arclookup( parentp , childp );
+ if ( arcp != 0 ) {
+ /*
+ * a hit: just increment the count.
+ */
+# ifdef DEBUG
+ if ( debug & TALLYDEBUG ) {
+ printf( "[tally] hit %ld += %ld\n" ,
+ arcp -> arc_count , count );
+ }
+# endif /* DEBUG */
+ arcp -> arc_count += count;
+ return;
+ }
+ arcp = (arctype *)calloc( 1 , sizeof *arcp );
+ if (arcp == NULL)
+ errx( 1 , "malloc failed" );
+ arcp -> arc_parentp = parentp;
+ arcp -> arc_childp = childp;
+ arcp -> arc_count = count;
+ /*
+ * prepend this child to the children of this parent
+ */
+ arcp -> arc_childlist = parentp -> children;
+ parentp -> children = arcp;
+ /*
+ * prepend this parent to the parents of this child
+ */
+ arcp -> arc_parentlist = childp -> parents;
+ childp -> parents = arcp;
+}
+
+ /*
+ * the code below topologically sorts the graph (collapsing cycles),
+ * and propagates time bottom up and flags top down.
+ */
+
+ /*
+ * the topologically sorted name list pointers
+ */
+nltype **topsortnlp;
+
+int
+topcmp(const void *v1, const void *v2)
+{
+ const nltype **npp1 = (const nltype **)v1;
+ const nltype **npp2 = (const nltype **)v2;
+
+ return (*npp1) -> toporder - (*npp2) -> toporder;
+}
+
+nltype **
+doarcs(void)
+{
+ nltype *parentp, **timesortnlp;
+ arctype *arcp;
+ long index;
+ long pass;
+
+ /*
+ * initialize various things:
+ * zero out child times.
+ * count self-recursive calls.
+ * indicate that nothing is on cycles.
+ */
+ for ( parentp = nl ; parentp < npe ; parentp++ ) {
+ parentp -> childtime = 0.0;
+ arcp = arclookup( parentp , parentp );
+ if ( arcp != 0 ) {
+ parentp -> ncall -= arcp -> arc_count;
+ parentp -> selfcalls = arcp -> arc_count;
+ } else {
+ parentp -> selfcalls = 0;
+ }
+ parentp -> npropcall = parentp -> ncall;
+ parentp -> propfraction = 0.0;
+ parentp -> propself = 0.0;
+ parentp -> propchild = 0.0;
+ parentp -> printflag = FALSE;
+ parentp -> toporder = DFN_NAN;
+ parentp -> cycleno = 0;
+ parentp -> cyclehead = parentp;
+ parentp -> cnext = 0;
+ }
+ for ( pass = 1 ; ; pass++ ) {
+ /*
+ * topologically order things
+ * if any node is unnumbered,
+ * number it and any of its descendents.
+ */
+ for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) {
+ if ( parentp -> toporder == DFN_NAN ) {
+ dfn( parentp );
+ }
+ }
+ /*
+ * link together nodes on the same cycle
+ */
+ cyclelink();
+ /*
+ * if no cycles to break up, proceed
+ */
+ if ( ! Cflag )
+ break;
+ /*
+ * analyze cycles to determine breakup
+ */
+# ifdef DEBUG
+ if ( debug & BREAKCYCLE ) {
+ printf("[doarcs] pass %ld, cycle(s) %d\n" , pass , ncycle );
+ }
+# endif /* DEBUG */
+ if ( pass == 1 ) {
+ printf( "\n\n%s %s\n%s %d:\n" ,
+ "The following arcs were deleted" ,
+ "from the propagation calculation" ,
+ "to reduce the maximum cycle size to", cyclethreshold );
+ }
+ if ( cycleanalyze() )
+ break;
+ free ( cyclenl );
+ ncycle = 0;
+ for ( parentp = nl ; parentp < npe ; parentp++ ) {
+ parentp -> toporder = DFN_NAN;
+ parentp -> cycleno = 0;
+ parentp -> cyclehead = parentp;
+ parentp -> cnext = 0;
+ }
+ }
+ if ( pass > 1 ) {
+ printf( "\f\n" );
+ } else {
+ printf( "\tNone\n\n" );
+ }
+ /*
+ * Sort the symbol table in reverse topological order
+ */
+ topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
+ if ( topsortnlp == (nltype **) 0 )
+ errx( 1 , "[doarcs] ran out of memory for topo sorting" );
+ for ( index = 0 ; index < nname ; index += 1 ) {
+ topsortnlp[ index ] = &nl[ index ];
+ }
+ qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[doarcs] topological sort listing\n" );
+ for ( index = 0 ; index < nname ; index += 1 ) {
+ printf( "[doarcs] " );
+ printf( "%d:" , topsortnlp[ index ] -> toporder );
+ printname( topsortnlp[ index ] );
+ printf( "\n" );
+ }
+ }
+# endif /* DEBUG */
+ /*
+ * starting from the topological top,
+ * propagate print flags to children.
+ * also, calculate propagation fractions.
+ * this happens before time propagation
+ * since time propagation uses the fractions.
+ */
+ doflags();
+ /*
+ * starting from the topological bottom,
+ * propagate children times up to parents.
+ */
+ dotime();
+ /*
+ * Now, sort by propself + propchild.
+ * sorting both the regular function names
+ * and cycle headers.
+ */
+ timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
+ if ( timesortnlp == (nltype **) 0 )
+ errx( 1 , "ran out of memory for sorting" );
+ for ( index = 0 ; index < nname ; index++ ) {
+ timesortnlp[index] = &nl[index];
+ }
+ for ( index = 1 ; index <= ncycle ; index++ ) {
+ timesortnlp[nname+index-1] = &cyclenl[index];
+ }
+ qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
+ for ( index = 0 ; index < nname + ncycle ; index++ ) {
+ timesortnlp[ index ] -> index = index + 1;
+ }
+ return( timesortnlp );
+}
+
+void
+dotime(void)
+{
+ int index;
+
+ cycletime();
+ for ( index = 0 ; index < nname ; index += 1 ) {
+ timepropagate( topsortnlp[ index ] );
+ }
+}
+
+void
+timepropagate(nltype *parentp)
+{
+ arctype *arcp;
+ nltype *childp;
+ double share;
+ double propshare;
+
+ if ( parentp -> propfraction == 0.0 ) {
+ return;
+ }
+ /*
+ * gather time from children of this parent.
+ */
+ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+ childp = arcp -> arc_childp;
+ if ( arcp -> arc_flags & DEADARC ) {
+ continue;
+ }
+ if ( arcp -> arc_count == 0 ) {
+ continue;
+ }
+ if ( childp == parentp ) {
+ continue;
+ }
+ if ( childp -> propfraction == 0.0 ) {
+ continue;
+ }
+ if ( childp -> cyclehead != childp ) {
+ if ( parentp -> cycleno == childp -> cycleno ) {
+ continue;
+ }
+ if ( parentp -> toporder <= childp -> toporder ) {
+ fprintf( stderr , "[propagate] toporder botches\n" );
+ }
+ childp = childp -> cyclehead;
+ } else {
+ if ( parentp -> toporder <= childp -> toporder ) {
+ fprintf( stderr , "[propagate] toporder botches\n" );
+ continue;
+ }
+ }
+ if ( childp -> npropcall == 0 ) {
+ continue;
+ }
+ /*
+ * distribute time for this arc
+ */
+ arcp -> arc_time = childp -> time
+ * ( ( (double) arcp -> arc_count ) /
+ ( (double) childp -> npropcall ) );
+ arcp -> arc_childtime = childp -> childtime
+ * ( ( (double) arcp -> arc_count ) /
+ ( (double) childp -> npropcall ) );
+ share = arcp -> arc_time + arcp -> arc_childtime;
+ parentp -> childtime += share;
+ /*
+ * ( 1 - propfraction ) gets lost along the way
+ */
+ propshare = parentp -> propfraction * share;
+ /*
+ * fix things for printing
+ */
+ parentp -> propchild += propshare;
+ arcp -> arc_time *= parentp -> propfraction;
+ arcp -> arc_childtime *= parentp -> propfraction;
+ /*
+ * add this share to the parent's cycle header, if any.
+ */
+ if ( parentp -> cyclehead != parentp ) {
+ parentp -> cyclehead -> childtime += share;
+ parentp -> cyclehead -> propchild += propshare;
+ }
+# ifdef DEBUG
+ if ( debug & PROPDEBUG ) {
+ printf( "[dotime] child \t" );
+ printname( childp );
+ printf( " with %f %f %ld/%ld\n" ,
+ childp -> time , childp -> childtime ,
+ arcp -> arc_count , childp -> npropcall );
+ printf( "[dotime] parent\t" );
+ printname( parentp );
+ printf( "\n[dotime] share %f\n" , share );
+ }
+# endif /* DEBUG */
+ }
+}
+
+void
+cyclelink(void)
+{
+ register nltype *nlp;
+ register nltype *cyclenlp;
+ int cycle;
+ nltype *memberp;
+ arctype *arcp;
+
+ /*
+ * Count the number of cycles, and initialize the cycle lists
+ */
+ ncycle = 0;
+ for ( nlp = nl ; nlp < npe ; nlp++ ) {
+ /*
+ * this is how you find unattached cycles
+ */
+ if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
+ ncycle += 1;
+ }
+ }
+ /*
+ * cyclenl is indexed by cycle number:
+ * i.e. it is origin 1, not origin 0.
+ */
+ cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
+ if ( cyclenl == NULL )
+ errx( 1 , "no room for %zu bytes of cycle headers" ,
+ ( ncycle + 1 ) * sizeof( nltype ) );
+ /*
+ * now link cycles to true cycleheads,
+ * number them, accumulate the data for the cycle
+ */
+ cycle = 0;
+ for ( nlp = nl ; nlp < npe ; nlp++ ) {
+ if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
+ continue;
+ }
+ cycle += 1;
+ cyclenlp = &cyclenl[cycle];
+ cyclenlp -> name = 0; /* the name */
+ cyclenlp -> value = 0; /* the pc entry point */
+ cyclenlp -> time = 0.0; /* ticks in this routine */
+ cyclenlp -> childtime = 0.0; /* cumulative ticks in children */
+ cyclenlp -> ncall = 0; /* how many times called */
+ cyclenlp -> selfcalls = 0; /* how many calls to self */
+ cyclenlp -> propfraction = 0.0; /* what % of time propagates */
+ cyclenlp -> propself = 0.0; /* how much self time propagates */
+ cyclenlp -> propchild = 0.0; /* how much child time propagates */
+ cyclenlp -> printflag = TRUE; /* should this be printed? */
+ cyclenlp -> index = 0; /* index in the graph list */
+ cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */
+ cyclenlp -> cycleno = cycle; /* internal number of cycle on */
+ cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */
+ cyclenlp -> cnext = nlp; /* pointer to next member of cycle */
+ cyclenlp -> parents = 0; /* list of caller arcs */
+ cyclenlp -> children = 0; /* list of callee arcs */
+# ifdef DEBUG
+ if ( debug & CYCLEDEBUG ) {
+ printf( "[cyclelink] " );
+ printname( nlp );
+ printf( " is the head of cycle %d\n" , cycle );
+ }
+# endif /* DEBUG */
+ /*
+ * link members to cycle header
+ */
+ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
+ memberp -> cycleno = cycle;
+ memberp -> cyclehead = cyclenlp;
+ }
+ /*
+ * count calls from outside the cycle
+ * and those among cycle members
+ */
+ for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
+ for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
+ if ( arcp -> arc_parentp == memberp ) {
+ continue;
+ }
+ if ( arcp -> arc_parentp -> cycleno == cycle ) {
+ cyclenlp -> selfcalls += arcp -> arc_count;
+ } else {
+ cyclenlp -> npropcall += arcp -> arc_count;
+ }
+ }
+ }
+ }
+}
+
+ /*
+ * analyze cycles to determine breakup
+ */
+bool
+cycleanalyze(void)
+{
+ arctype **cyclestack;
+ arctype **stkp;
+ arctype **arcpp;
+ arctype **endlist;
+ arctype *arcp;
+ nltype *nlp;
+ cltype *clp;
+ bool ret;
+ bool done;
+ int size;
+ int cycleno;
+
+ /*
+ * calculate the size of the cycle, and find nodes that
+ * exit the cycle as they are desirable targets to cut
+ * some of their parents
+ */
+ for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) {
+ size = 0;
+ for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) {
+ size += 1;
+ nlp -> parentcnt = 0;
+ nlp -> flags &= ~HASCYCLEXIT;
+ for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) {
+ nlp -> parentcnt += 1;
+ if ( arcp -> arc_parentp -> cycleno != cycleno )
+ nlp -> flags |= HASCYCLEXIT;
+ }
+ }
+ if ( size <= cyclethreshold )
+ continue;
+ done = FALSE;
+ cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) );
+ if ( cyclestack == NULL )
+ errx( 1, "no room for %zu bytes of cycle stack" ,
+ ( size + 1 ) * sizeof( arctype * ) );
+# ifdef DEBUG
+ if ( debug & BREAKCYCLE ) {
+ printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" ,
+ cycleno , ncycle , size );
+ }
+# endif /* DEBUG */
+ for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) {
+ stkp = &cyclestack[0];
+ nlp -> flags |= CYCLEHEAD;
+ ret = descend ( nlp , cyclestack , stkp );
+ nlp -> flags &= ~CYCLEHEAD;
+ if ( ret == FALSE )
+ break;
+ }
+ free( cyclestack );
+ if ( cyclecnt > 0 ) {
+ compresslist();
+ for ( clp = cyclehead ; clp ; ) {
+ endlist = &clp -> list[ clp -> size ];
+ for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
+ (*arcpp) -> arc_cyclecnt--;
+ cyclecnt--;
+ clp = clp -> next;
+ free( clp );
+ }
+ cyclehead = 0;
+ }
+ }
+# ifdef DEBUG
+ if ( debug & BREAKCYCLE ) {
+ printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n",
+ "[doarcs]" , visited , viable , newcycle , oldcycle);
+ }
+# endif /* DEBUG */
+ return( done );
+}
+
+bool
+descend(nltype *node, arctype **stkstart, arctype **stkp)
+{
+ arctype *arcp;
+ bool ret;
+
+ for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+# ifdef DEBUG
+ visited++;
+# endif /* DEBUG */
+ if ( arcp -> arc_childp -> cycleno != node -> cycleno
+ || ( arcp -> arc_childp -> flags & VISITED )
+ || ( arcp -> arc_flags & DEADARC ) )
+ continue;
+# ifdef DEBUG
+ viable++;
+# endif /* DEBUG */
+ *stkp = arcp;
+ if ( arcp -> arc_childp -> flags & CYCLEHEAD ) {
+ if ( addcycle( stkstart , stkp ) == FALSE )
+ return( FALSE );
+ continue;
+ }
+ arcp -> arc_childp -> flags |= VISITED;
+ ret = descend( arcp -> arc_childp , stkstart , stkp + 1 );
+ arcp -> arc_childp -> flags &= ~VISITED;
+ if ( ret == FALSE )
+ return( FALSE );
+ }
+ return( TRUE );
+}
+
+bool
+addcycle(arctype **stkstart, arctype **stkend)
+{
+ arctype **arcpp;
+ arctype **stkloc;
+ arctype **stkp;
+ arctype **endlist;
+ arctype *minarc;
+ arctype *arcp;
+ cltype *clp;
+ int size;
+
+ size = stkend - stkstart + 1;
+ if ( size <= 1 )
+ return( TRUE );
+ for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) {
+ if ( *arcpp > minarc )
+ continue;
+ minarc = *arcpp;
+ stkloc = arcpp;
+ }
+ for ( clp = cyclehead ; clp ; clp = clp -> next ) {
+ if ( clp -> size != size )
+ continue;
+ stkp = stkloc;
+ endlist = &clp -> list[ size ];
+ for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
+ if ( *stkp++ != *arcpp )
+ break;
+ if ( stkp > stkend )
+ stkp = stkstart;
+ }
+ if ( arcpp == endlist ) {
+# ifdef DEBUG
+ oldcycle++;
+# endif /* DEBUG */
+ return( TRUE );
+ }
+ }
+ clp = (cltype *)
+ calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
+ if ( clp == NULL ) {
+ warnx( "no room for %zu bytes of subcycle storage" ,
+ sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
+ return( FALSE );
+ }
+ stkp = stkloc;
+ endlist = &clp -> list[ size ];
+ for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
+ arcp = *arcpp = *stkp++;
+ if ( stkp > stkend )
+ stkp = stkstart;
+ arcp -> arc_cyclecnt++;
+ if ( ( arcp -> arc_flags & ONLIST ) == 0 ) {
+ arcp -> arc_flags |= ONLIST;
+ arcp -> arc_next = archead;
+ archead = arcp;
+ }
+ }
+ clp -> size = size;
+ clp -> next = cyclehead;
+ cyclehead = clp;
+# ifdef DEBUG
+ newcycle++;
+ if ( debug & SUBCYCLELIST ) {
+ printsubcycle( clp );
+ }
+# endif /* DEBUG */
+ cyclecnt++;
+ if ( cyclecnt >= CYCLEMAX )
+ return( FALSE );
+ return( TRUE );
+}
+
+void
+compresslist(void)
+{
+ cltype *clp;
+ cltype **prev;
+ arctype **arcpp;
+ arctype **endlist;
+ arctype *arcp;
+ arctype *maxarcp;
+ arctype *maxexitarcp;
+ arctype *maxwithparentarcp;
+ arctype *maxnoparentarcp;
+ int maxexitcnt;
+ int maxwithparentcnt;
+ int maxnoparentcnt;
+# ifdef DEBUG
+ const char *type;
+# endif /* DEBUG */
+
+ maxexitcnt = 0;
+ maxwithparentcnt = 0;
+ maxnoparentcnt = 0;
+ for ( endlist = &archead , arcp = archead ; arcp ; ) {
+ if ( arcp -> arc_cyclecnt == 0 ) {
+ arcp -> arc_flags &= ~ONLIST;
+ *endlist = arcp -> arc_next;
+ arcp -> arc_next = 0;
+ arcp = *endlist;
+ continue;
+ }
+ if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) {
+ if ( arcp -> arc_cyclecnt > maxexitcnt ||
+ ( arcp -> arc_cyclecnt == maxexitcnt &&
+ arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) {
+ maxexitcnt = arcp -> arc_cyclecnt;
+ maxexitarcp = arcp;
+ }
+ } else if ( arcp -> arc_childp -> parentcnt > 1 ) {
+ if ( arcp -> arc_cyclecnt > maxwithparentcnt ||
+ ( arcp -> arc_cyclecnt == maxwithparentcnt &&
+ arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) {
+ maxwithparentcnt = arcp -> arc_cyclecnt;
+ maxwithparentarcp = arcp;
+ }
+ } else {
+ if ( arcp -> arc_cyclecnt > maxnoparentcnt ||
+ ( arcp -> arc_cyclecnt == maxnoparentcnt &&
+ arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) {
+ maxnoparentcnt = arcp -> arc_cyclecnt;
+ maxnoparentarcp = arcp;
+ }
+ }
+ endlist = &arcp -> arc_next;
+ arcp = arcp -> arc_next;
+ }
+ if ( maxexitcnt > 0 ) {
+ /*
+ * first choice is edge leading to node with out-of-cycle parent
+ */
+ maxarcp = maxexitarcp;
+# ifdef DEBUG
+ type = "exit";
+# endif /* DEBUG */
+ } else if ( maxwithparentcnt > 0 ) {
+ /*
+ * second choice is edge leading to node with at least one
+ * other in-cycle parent
+ */
+ maxarcp = maxwithparentarcp;
+# ifdef DEBUG
+ type = "internal";
+# endif /* DEBUG */
+ } else {
+ /*
+ * last choice is edge leading to node with only this arc as
+ * a parent (as it will now be orphaned)
+ */
+ maxarcp = maxnoparentarcp;
+# ifdef DEBUG
+ type = "orphan";
+# endif /* DEBUG */
+ }
+ maxarcp -> arc_flags |= DEADARC;
+ maxarcp -> arc_childp -> parentcnt -= 1;
+ maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count;
+# ifdef DEBUG
+ if ( debug & BREAKCYCLE ) {
+ printf( "%s delete %s arc: %s (%ld) -> %s from %u cycle(s)\n" ,
+ "[compresslist]" , type , maxarcp -> arc_parentp -> name ,
+ maxarcp -> arc_count , maxarcp -> arc_childp -> name ,
+ maxarcp -> arc_cyclecnt );
+ }
+# endif /* DEBUG */
+ printf( "\t%s to %s with %ld calls\n" , maxarcp -> arc_parentp -> name ,
+ maxarcp -> arc_childp -> name , maxarcp -> arc_count );
+ prev = &cyclehead;
+ for ( clp = cyclehead ; clp ; ) {
+ endlist = &clp -> list[ clp -> size ];
+ for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
+ if ( (*arcpp) -> arc_flags & DEADARC )
+ break;
+ if ( arcpp == endlist ) {
+ prev = &clp -> next;
+ clp = clp -> next;
+ continue;
+ }
+ for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
+ (*arcpp) -> arc_cyclecnt--;
+ cyclecnt--;
+ *prev = clp -> next;
+ clp = clp -> next;
+ free( clp );
+ }
+}
+
+#ifdef DEBUG
+void
+printsubcycle(cltype *clp)
+{
+ arctype **arcpp;
+ arctype **endlist;
+
+ arcpp = clp -> list;
+ printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name ,
+ (*arcpp) -> arc_parentp -> cycleno ) ;
+ for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ )
+ printf( "\t(%ld) -> %s\n" , (*arcpp) -> arc_count ,
+ (*arcpp) -> arc_childp -> name ) ;
+}
+#endif /* DEBUG */
+
+void
+cycletime(void)
+{
+ int cycle;
+ nltype *cyclenlp;
+ nltype *childp;
+
+ for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
+ cyclenlp = &cyclenl[ cycle ];
+ for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
+ if ( childp -> propfraction == 0.0 ) {
+ /*
+ * all members have the same propfraction except those
+ * that were excluded with -E
+ */
+ continue;
+ }
+ cyclenlp -> time += childp -> time;
+ }
+ cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
+ }
+}
+
+ /*
+ * in one top to bottom pass over the topologically sorted namelist
+ * propagate:
+ * printflag as the union of parents' printflags
+ * propfraction as the sum of fractional parents' propfractions
+ * and while we're here, sum time for functions.
+ */
+void
+doflags(void)
+{
+ int index;
+ nltype *childp;
+ nltype *oldhead;
+
+ oldhead = 0;
+ for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
+ childp = topsortnlp[ index ];
+ /*
+ * if we haven't done this function or cycle,
+ * inherit things from parent.
+ * this way, we are linear in the number of arcs
+ * since we do all members of a cycle (and the cycle itself)
+ * as we hit the first member of the cycle.
+ */
+ if ( childp -> cyclehead != oldhead ) {
+ oldhead = childp -> cyclehead;
+ inheritflags( childp );
+ }
+# ifdef DEBUG
+ if ( debug & PROPDEBUG ) {
+ printf( "[doflags] " );
+ printname( childp );
+ printf( " inherits printflag %d and propfraction %f\n" ,
+ childp -> printflag , childp -> propfraction );
+ }
+# endif /* DEBUG */
+ if ( ! childp -> printflag ) {
+ /*
+ * printflag is off
+ * it gets turned on by
+ * being on -f list,
+ * or there not being any -f list and not being on -e list.
+ */
+ if ( onlist( flist , childp -> name )
+ || ( !fflag && !onlist( elist , childp -> name ) ) ) {
+ childp -> printflag = TRUE;
+ }
+ } else {
+ /*
+ * this function has printing parents:
+ * maybe someone wants to shut it up
+ * by putting it on -e list. (but favor -f over -e)
+ */
+ if ( ( !onlist( flist , childp -> name ) )
+ && onlist( elist , childp -> name ) ) {
+ childp -> printflag = FALSE;
+ }
+ }
+ if ( childp -> propfraction == 0.0 ) {
+ /*
+ * no parents to pass time to.
+ * collect time from children if
+ * its on -F list,
+ * or there isn't any -F list and its not on -E list.
+ */
+ if ( onlist( Flist , childp -> name )
+ || ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
+ childp -> propfraction = 1.0;
+ }
+ } else {
+ /*
+ * it has parents to pass time to,
+ * but maybe someone wants to shut it up
+ * by putting it on -E list. (but favor -F over -E)
+ */
+ if ( !onlist( Flist , childp -> name )
+ && onlist( Elist , childp -> name ) ) {
+ childp -> propfraction = 0.0;
+ }
+ }
+ childp -> propself = childp -> time * childp -> propfraction;
+ printtime += childp -> propself;
+# ifdef DEBUG
+ if ( debug & PROPDEBUG ) {
+ printf( "[doflags] " );
+ printname( childp );
+ printf( " ends up with printflag %d and propfraction %f\n" ,
+ childp -> printflag , childp -> propfraction );
+ printf( "time %f propself %f printtime %f\n" ,
+ childp -> time , childp -> propself , printtime );
+ }
+# endif /* DEBUG */
+ }
+}
+
+ /*
+ * check if any parent of this child
+ * (or outside parents of this cycle)
+ * have their print flags on and set the
+ * print flag of the child (cycle) appropriately.
+ * similarly, deal with propagation fractions from parents.
+ */
+void
+inheritflags(nltype *childp)
+{
+ nltype *headp;
+ arctype *arcp;
+ nltype *parentp;
+ nltype *memp;
+
+ headp = childp -> cyclehead;
+ if ( childp == headp ) {
+ /*
+ * just a regular child, check its parents
+ */
+ childp -> printflag = FALSE;
+ childp -> propfraction = 0.0;
+ for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
+ parentp = arcp -> arc_parentp;
+ if ( childp == parentp ) {
+ continue;
+ }
+ childp -> printflag |= parentp -> printflag;
+ /*
+ * if the child was never actually called
+ * (e.g. this arc is static (and all others are, too))
+ * no time propagates along this arc.
+ */
+ if ( arcp -> arc_flags & DEADARC ) {
+ continue;
+ }
+ if ( childp -> npropcall ) {
+ childp -> propfraction += parentp -> propfraction
+ * ( ( (double) arcp -> arc_count )
+ / ( (double) childp -> npropcall ) );
+ }
+ }
+ } else {
+ /*
+ * its a member of a cycle, look at all parents from
+ * outside the cycle
+ */
+ headp -> printflag = FALSE;
+ headp -> propfraction = 0.0;
+ for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
+ for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
+ if ( arcp -> arc_parentp -> cyclehead == headp ) {
+ continue;
+ }
+ parentp = arcp -> arc_parentp;
+ headp -> printflag |= parentp -> printflag;
+ /*
+ * if the cycle was never actually called
+ * (e.g. this arc is static (and all others are, too))
+ * no time propagates along this arc.
+ */
+ if ( arcp -> arc_flags & DEADARC ) {
+ continue;
+ }
+ if ( headp -> npropcall ) {
+ headp -> propfraction += parentp -> propfraction
+ * ( ( (double) arcp -> arc_count )
+ / ( (double) headp -> npropcall ) );
+ }
+ }
+ }
+ for ( memp = headp ; memp ; memp = memp -> cnext ) {
+ memp -> printflag = headp -> printflag;
+ memp -> propfraction = headp -> propfraction;
+ }
+ }
+}
diff --git a/usr.bin/gprof/dfn.c b/usr.bin/gprof/dfn.c
new file mode 100644
index 000000000000..b0bafc18fb52
--- /dev/null
+++ b/usr.bin/gprof/dfn.c
@@ -0,0 +1,315 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include "gprof.h"
+
+#define DFN_DEPTH 100
+struct dfnstruct {
+ nltype *nlentryp;
+ int cycletop;
+};
+typedef struct dfnstruct dfntype;
+
+dfntype dfn_stack[ DFN_DEPTH ];
+int dfn_depth;
+
+int dfn_counter;
+
+void
+dfn_init(void)
+{
+
+ dfn_depth = 0;
+ dfn_counter = DFN_NAN;
+}
+
+ /*
+ * given this parent, depth first number its children.
+ */
+void
+dfn(nltype *parentp)
+{
+ arctype *arcp;
+
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn] dfn(" );
+ printname( parentp );
+ printf( ")\n" );
+ }
+# endif /* DEBUG */
+ /*
+ * if we're already numbered, no need to look any further.
+ */
+ if ( dfn_numbered( parentp ) ) {
+ return;
+ }
+ /*
+ * if we're already busy, must be a cycle
+ */
+ if ( dfn_busy( parentp ) ) {
+ dfn_findcycle( parentp );
+ return;
+ }
+ /*
+ * visit yourself before your children
+ */
+ dfn_pre_visit( parentp );
+ /*
+ * visit children
+ */
+ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+ if ( arcp -> arc_flags & DEADARC )
+ continue;
+ dfn( arcp -> arc_childp );
+ }
+ /*
+ * visit yourself after your children
+ */
+ dfn_post_visit( parentp );
+}
+
+ /*
+ * push a parent onto the stack and mark it busy
+ */
+void
+dfn_pre_visit(nltype *parentp)
+{
+
+ dfn_depth += 1;
+ if ( dfn_depth >= DFN_DEPTH )
+ errx( 1 , "[dfn] out of my depth (dfn_stack overflow)" );
+ dfn_stack[ dfn_depth ].nlentryp = parentp;
+ dfn_stack[ dfn_depth ].cycletop = dfn_depth;
+ parentp -> toporder = DFN_BUSY;
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
+ printname( parentp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+}
+
+ /*
+ * are we already numbered?
+ */
+bool
+dfn_numbered(nltype *childp)
+{
+
+ return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
+}
+
+ /*
+ * are we already busy?
+ */
+bool
+dfn_busy(nltype *childp)
+{
+
+ if ( childp -> toporder == DFN_NAN ) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+ /*
+ * MISSING: an explanation
+ */
+void
+dfn_findcycle(nltype *childp)
+{
+ int cycletop;
+ nltype *cycleheadp;
+ nltype *tailp;
+ int index;
+
+ for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
+ cycleheadp = dfn_stack[ cycletop ].nlentryp;
+ if ( childp == cycleheadp ) {
+ break;
+ }
+ if ( childp -> cyclehead != childp &&
+ childp -> cyclehead == cycleheadp ) {
+ break;
+ }
+ }
+ if ( cycletop <= 0 )
+ errx( 1 , "[dfn_findcycle] couldn't find head of cycle" );
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
+ dfn_depth , cycletop );
+ printname( cycleheadp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ if ( cycletop == dfn_depth ) {
+ /*
+ * this is previous function, e.g. this calls itself
+ * sort of boring
+ */
+ dfn_self_cycle( childp );
+ } else {
+ /*
+ * glom intervening functions that aren't already
+ * glommed into this cycle.
+ * things have been glommed when their cyclehead field
+ * points to the head of the cycle they are glommed into.
+ */
+ for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
+ /* void: chase down to tail of things already glommed */
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_findcycle] tail " );
+ printname( tailp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ }
+ /*
+ * if what we think is the top of the cycle
+ * has a cyclehead field, then it's not really the
+ * head of the cycle, which is really what we want
+ */
+ if ( cycleheadp -> cyclehead != cycleheadp ) {
+ cycleheadp = cycleheadp -> cyclehead;
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_findcycle] new cyclehead " );
+ printname( cycleheadp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ }
+ for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
+ childp = dfn_stack[ index ].nlentryp;
+ if ( childp -> cyclehead == childp ) {
+ /*
+ * not yet glommed anywhere, glom it
+ * and fix any children it has glommed
+ */
+ tailp -> cnext = childp;
+ childp -> cyclehead = cycleheadp;
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_findcycle] glomming " );
+ printname( childp );
+ printf( " onto " );
+ printname( cycleheadp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
+ tailp -> cnext -> cyclehead = cycleheadp;
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_findcycle] and its tail " );
+ printname( tailp -> cnext );
+ printf( " onto " );
+ printname( cycleheadp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ }
+ } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) {
+ fprintf( stderr ,
+ "[dfn_busy] glommed, but not to cyclehead\n" );
+ }
+ }
+ }
+}
+
+ /*
+ * deal with self-cycles
+ * for lint: ARGSUSED
+ */
+void
+dfn_self_cycle(nltype *parentp)
+{
+ /*
+ * since we are taking out self-cycles elsewhere
+ * no need for the special case, here.
+ */
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_self_cycle] " );
+ printname( parentp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+}
+
+ /*
+ * visit a node after all its children
+ * [MISSING: an explanation]
+ * and pop it off the stack
+ */
+void
+dfn_post_visit(nltype *parentp)
+{
+ nltype *memberp;
+
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_post_visit]\t%d: " , dfn_depth );
+ printname( parentp );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ /*
+ * number functions and things in their cycles
+ * unless the function is itself part of a cycle
+ */
+ if ( parentp -> cyclehead == parentp ) {
+ dfn_counter += 1;
+ for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
+ memberp -> toporder = dfn_counter;
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_post_visit]\t\tmember " );
+ printname( memberp );
+ printf( " -> toporder = %d\n" , dfn_counter );
+ }
+# endif /* DEBUG */
+ }
+ } else {
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
+ }
+# endif /* DEBUG */
+ }
+ dfn_depth -= 1;
+}
diff --git a/usr.bin/gprof/elf.c b/usr.bin/gprof/elf.c
new file mode 100644
index 000000000000..a237e1dd4c02
--- /dev/null
+++ b/usr.bin/gprof/elf.c
@@ -0,0 +1,140 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#if 0
+/* From: */
+#endif
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <machine/elf.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "gprof.h"
+
+static bool wantsym(const Elf_Sym *, const char *);
+
+/* Things which get -E excluded by default. */
+static char *excludes[] = { ".mcount", "_mcleanup", NULL };
+
+int
+elf_getnfile(const char *filename, char ***defaultEs)
+{
+ int fd;
+ Elf_Ehdr h;
+ struct stat s;
+ void *mapbase;
+ const char *base;
+ const Elf_Shdr *shdrs;
+ const Elf_Shdr *sh_symtab;
+ const Elf_Shdr *sh_strtab;
+ const char *strtab;
+ const Elf_Sym *symtab;
+ int symtabct;
+ int i;
+
+ if ((fd = open(filename, O_RDONLY)) == -1)
+ err(1, "%s", filename);
+ if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) {
+ close(fd);
+ return -1;
+ }
+ if (fstat(fd, &s) == -1)
+ err(1, "cannot fstat %s", filename);
+ if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) ==
+ MAP_FAILED)
+ err(1, "cannot mmap %s", filename);
+ close(fd);
+
+ base = (const char *)mapbase;
+ shdrs = (const Elf_Shdr *)(base + h.e_shoff);
+
+ /* Find the symbol table and associated string table section. */
+ for (i = 1; i < h.e_shnum; i++)
+ if (shdrs[i].sh_type == SHT_SYMTAB)
+ break;
+ if (i == h.e_shnum)
+ errx(1, "%s has no symbol table", filename);
+ sh_symtab = &shdrs[i];
+ sh_strtab = &shdrs[sh_symtab->sh_link];
+
+ symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset);
+ symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize;
+ strtab = (const char *)(base + sh_strtab->sh_offset);
+
+ /* Count the symbols that we're interested in. */
+ nname = 0;
+ for (i = 1; i < symtabct; i++)
+ if (wantsym(&symtab[i], strtab))
+ nname++;
+
+ /* Allocate memory for them, plus a terminating entry. */
+ if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
+ errx(1, "insufficient memory for symbol table");
+
+ /* Read them in. */
+ npe = nl;
+ for (i = 1; i < symtabct; i++) {
+ const Elf_Sym *sym = &symtab[i];
+
+ if (wantsym(sym, strtab)) {
+ npe->value = sym->st_value;
+ npe->name = strtab + sym->st_name;
+ npe++;
+ }
+ }
+ npe->value = -1;
+
+ *defaultEs = excludes;
+ return 0;
+}
+
+static bool
+wantsym(const Elf_Sym *sym, const char *strtab)
+{
+ int type;
+ int bind;
+
+ type = ELF_ST_TYPE(sym->st_info);
+ bind = ELF_ST_BIND(sym->st_info);
+
+ if (type != STT_FUNC ||
+ (aflag && bind == STB_LOCAL) ||
+ (uflag && strchr(strtab + sym->st_name, '.') != NULL))
+ return 0;
+
+ return 1;
+}
diff --git a/usr.bin/gprof/gprof.1 b/usr.bin/gprof/gprof.1
new file mode 100644
index 000000000000..c3945f7da5a2
--- /dev/null
+++ b/usr.bin/gprof/gprof.1
@@ -0,0 +1,326 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd November 27, 2017
+.Dt GPROF 1
+.Os
+.Sh NAME
+.Nm gprof
+.Nd display call graph profile data
+.Sh SYNOPSIS
+.Nm
+.Op Fl abKlLsuz
+.Op Fl C Ar count
+.Op Fl e Ar name
+.Op Fl E Ar name
+.Op Fl f Ar name
+.Op Fl F Ar name
+.Op Fl k Ar fromname toname
+.Op Ar a.out Op Ar a.out.gmon ...
+.Sh DESCRIPTION
+The
+.Nm
+utility produces an execution profile of C, Pascal, or Fortran77 programs.
+The effect of called routines is incorporated in the profile of each caller.
+The profile data is taken from the call graph profile file
+which is created by programs that are compiled with the
+.Fl pg
+option of
+.Xr cc 1 ,
+.Xr pc 1 ,
+and
+.Xr f77 1 .
+The
+.Fl pg
+option also links in versions of the library routines
+that are compiled for profiling.
+By convention these libraries have their name suffixed with
+.Pa _p ,
+i.e., the profiled version of
+.Pa libc.a
+is
+.Pa libc_p.a
+and if you specify libraries directly to the
+compiler or linker you can use
+.Fl l Ns Ar c_p
+instead of
+.Fl l Ns Ar c .
+Read the given object file (the default is
+.Pa a.out )
+and establishes the relation between its symbol table
+and the call graph profile.
+The default graph profile file name is the name
+of the executable with the suffix
+.Pa .gmon
+appended.
+If more than one profile file is specified,
+the
+.Nm
+output shows the sum of the profile information in the given profile files.
+.Pp
+The
+.Nm
+utility calculates the amount of time spent in each routine.
+Next, these times are propagated along the edges of the call graph.
+Cycles are discovered, and calls into a cycle are made to share the time
+of the cycle.
+The first listing shows the functions
+sorted according to the time they represent
+including the time of their call graph descendants.
+Below each function entry is shown its (direct) call graph children,
+and how their times are propagated to this function.
+A similar display above the function shows how this function's time and the
+time of its descendants is propagated to its (direct) call graph parents.
+.Pp
+Cycles are also shown, with an entry for the cycle as a whole and
+a listing of the members of the cycle and their contributions to the
+time and call counts of the cycle.
+.Pp
+Second, a flat profile is given,
+similar to that provided by
+.Xr prof 1 .
+This listing gives the total execution times, the call counts,
+the time that the call spent in the routine itself, and
+the time that the call spent in the routine itself including
+its descendants.
+The units for the per-call times are normally milliseconds,
+but they are nanoseconds if the profiling clock frequency
+is 10 million or larger,
+and if a function appears to be never called then its total self time
+is printed as a percentage in the self time per call column.
+The very high profiling clock frequencies needed to get sufficient
+accuracy in the per-call times for short-lived programs are only
+implemented for
+.Dq high resolution
+(non-statistical) kernel profiling.
+.Pp
+Finally, an index of the function names is provided.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Suppress the printing of statically declared functions.
+If this option is given, all relevant information about the static function
+(e.g., time samples, calls to other functions, calls from other functions)
+belongs to the function loaded just before the static function in the
+.Pa a.out
+file.
+.It Fl b
+Suppress the printing of a description of each field in the profile.
+.It Fl C Ar count
+Find a minimal set of arcs that can be broken to eliminate all cycles with
+.Ar count
+or more members.
+Caution: the algorithm used to break cycles is exponential,
+so using this option may cause
+.Nm
+to run for a very long time.
+.It Fl e Ar name
+Suppress the printing of the graph profile entry for routine
+.Ar name
+and all its descendants
+(unless they have other ancestors that are not suppressed).
+More than one
+.Fl e
+option may be given.
+Only one
+.Ar name
+may be given with each
+.Fl e
+option.
+.It Fl E Ar name
+Suppress the printing of the graph profile entry for routine
+.Ar name
+(and its descendants) as
+.Fl e ,
+above, and also excludes the time spent in
+.Ar name
+(and its descendants) from the total and percentage time computations.
+(For example,
+.Fl E
+.Ar mcount
+.Fl E
+.Ar mcleanup
+is the default.)
+.It Fl f Ar name
+Print the graph profile entry of only the specified routine
+.Ar name
+and its descendants.
+More than one
+.Fl f
+option may be given.
+Only one
+.Ar name
+may be given with each
+.Fl f
+option.
+.It Fl F Ar name
+Print the graph profile entry of only the routine
+.Ar name
+and its descendants (as
+.Fl f ,
+above) and also uses only the times of the printed routines
+in total time and percentage computations.
+More than one
+.Fl F
+option may be given.
+Only one
+.Ar name
+may be given with each
+.Fl F
+option.
+The
+.Fl F
+option
+overrides
+the
+.Fl E
+option.
+.It Fl k Ar fromname Ar toname
+Will delete any arcs from routine
+.Ar fromname
+to routine
+.Ar toname .
+This can be used to break undesired cycles.
+More than one
+.Fl k
+option may be given.
+Only one pair of routine names may be given with each
+.Fl k
+option.
+.It Fl K
+Gather information about symbols from the currently-running kernel using the
+.Xr sysctl 3
+and
+.Xr kldsym 2
+interfaces.
+This forces the
+.Pa a.out
+argument to be ignored, and allows for symbols in
+.Xr kld 4
+modules to be used.
+.It Fl l
+Suppress the printing of the call-graph profile.
+.It Fl L
+Suppress the printing of the flat profile.
+.It Fl s
+A profile file
+.Pa gmon.sum
+is produced that represents
+the sum of the profile information in all the specified profile files.
+This summary profile file may be given to later
+executions of gprof (probably also with a
+.Fl s )
+to accumulate profile data across several runs of an
+.Pa a.out
+file.
+.It Fl u
+Suppress the printing of functions whose names are not visible to
+C programs.
+For the ELF object format, this means names that
+contain the
+.Ql .\&
+character.
+For the a.out object format, it means names that do not
+begin with a
+.Ql _
+character.
+All relevant information about such functions belongs to the
+(non-suppressed) function with the next lowest address.
+This is useful for eliminating "functions" that are just labels
+inside other functions.
+.It Fl z
+Display routines that have zero usage (as shown by call counts
+and accumulated time).
+.El
+.Sh FILES
+.Bl -tag -width a.out.gmon -compact
+.It Pa a.out
+The namelist and text space.
+.It Pa a.out.gmon
+Dynamic call graph and profile.
+.It Pa gmon.sum
+Summarized dynamic call graph and profile.
+.El
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr profil 2 ,
+.Xr clocks 7 ,
+.Xr pmcstat 8
+.\" .Xr monitor 3 ,
+.\" .Xr prof 1
+.Rs
+.%T "An Execution Profiler for Modular Programs"
+.%A S. Graham
+.%A P. Kessler
+.%A M. McKusick
+.%J "Software - Practice and Experience"
+.%V 13
+.%P pp. 671-685
+.%D 1983
+.Re
+.Rs
+.%T "gprof: A Call Graph Execution Profiler"
+.%A S. Graham
+.%A P. Kessler
+.%A M. McKusick
+.%J "Proceedings of the SIGPLAN '82 Symposium on Compiler Construction, SIGPLAN Notices"
+.%V 17
+.%N 6
+.%P pp. 120-126
+.%D June 1982
+.Re
+.Sh HISTORY
+The
+.Nm
+profiler
+appeared in
+.Bx 4.2 .
+.Sh BUGS
+The granularity of the sampling is shown, but remains
+statistical at best.
+We assume that the time for each execution of a function
+can be expressed by the total time for the function divided
+by the number of times the function is called.
+Thus the time propagated along the call graph arcs to the function's
+parents is directly proportional to the number of times that
+arc is traversed.
+.Pp
+Parents that are not themselves profiled will have the time of
+their profiled children propagated to them, but they will appear
+to be spontaneously invoked in the call graph listing, and will
+not have their time propagated further.
+Similarly, signal catchers, even though profiled, will appear
+to be spontaneous (although for more obscure reasons).
+Any profiled children of signal catchers should have their times
+propagated properly, unless the signal catcher was invoked during
+the execution of the profiling routine, in which case all is lost.
+.Pp
+The profiled program must call
+.Xr exit 3
+or return normally for the profiling information to be saved
+in the graph profile file.
diff --git a/usr.bin/gprof/gprof.c b/usr.bin/gprof/gprof.c
new file mode 100644
index 000000000000..044567d09269
--- /dev/null
+++ b/usr.bin/gprof/gprof.c
@@ -0,0 +1,580 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <err.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+
+#define EXTERN
+#include "gprof.h"
+
+static int valcmp(const void *, const void *);
+
+static struct gmonhdr gmonhdr;
+static int lflag;
+static int Lflag;
+
+int
+main(int argc, char **argv)
+{
+ char **sp;
+ nltype **timesortnlp;
+ char **defaultEs;
+
+ --argc;
+ argv++;
+ debug = 0;
+ bflag = TRUE;
+ while ( *argv != 0 && **argv == '-' ) {
+ (*argv)++;
+ switch ( **argv ) {
+ case 'a':
+ aflag = TRUE;
+ break;
+ case 'b':
+ bflag = FALSE;
+ break;
+ case 'C':
+ Cflag = TRUE;
+ cyclethreshold = atoi( *++argv );
+ break;
+ case 'd':
+ dflag = TRUE;
+ setlinebuf(stdout);
+ debug |= atoi( *++argv );
+ debug |= ANYDEBUG;
+# ifdef DEBUG
+ printf("[main] debug = %d\n", debug);
+# else /* not DEBUG */
+ printf("gprof: -d ignored\n");
+# endif /* DEBUG */
+ break;
+ case 'E':
+ ++argv;
+ addlist( Elist , *argv );
+ Eflag = TRUE;
+ addlist( elist , *argv );
+ eflag = TRUE;
+ break;
+ case 'e':
+ addlist( elist , *++argv );
+ eflag = TRUE;
+ break;
+ case 'F':
+ ++argv;
+ addlist( Flist , *argv );
+ Fflag = TRUE;
+ addlist( flist , *argv );
+ fflag = TRUE;
+ break;
+ case 'f':
+ addlist( flist , *++argv );
+ fflag = TRUE;
+ break;
+ case 'k':
+ addlist( kfromlist , *++argv );
+ addlist( ktolist , *++argv );
+ kflag = TRUE;
+ break;
+ case 'K':
+ Kflag = TRUE;
+ break;
+ case 'l':
+ lflag = 1;
+ Lflag = 0;
+ break;
+ case 'L':
+ Lflag = 1;
+ lflag = 0;
+ break;
+ case 's':
+ sflag = TRUE;
+ break;
+ case 'u':
+ uflag = TRUE;
+ break;
+ case 'z':
+ zflag = TRUE;
+ break;
+ }
+ argv++;
+ }
+ if ( *argv != 0 ) {
+ a_outname = *argv;
+ argv++;
+ } else {
+ a_outname = A_OUTNAME;
+ }
+ if ( *argv != 0 ) {
+ gmonname = *argv;
+ argv++;
+ } else {
+ gmonname = (char *) malloc(strlen(a_outname)+6);
+ strcpy(gmonname, a_outname);
+ strcat(gmonname, ".gmon");
+ }
+ /*
+ * get information from the executable file.
+ */
+ if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) ||
+ (!Kflag && elf_getnfile(a_outname, &defaultEs) == -1))
+ errx(1, "%s: bad format", a_outname);
+ /*
+ * sort symbol table.
+ */
+ qsort(nl, nname, sizeof(nltype), valcmp);
+ /*
+ * turn off default functions
+ */
+ for ( sp = defaultEs ; *sp ; sp++ ) {
+ Eflag = TRUE;
+ addlist( Elist , *sp );
+ eflag = TRUE;
+ addlist( elist , *sp );
+ }
+ /*
+ * get information about mon.out file(s).
+ */
+ do {
+ getpfile( gmonname );
+ if ( *argv != 0 ) {
+ gmonname = *argv;
+ }
+ } while ( *argv++ != 0 );
+ /*
+ * how many ticks per second?
+ * if we can't tell, report time in ticks.
+ */
+ if (hz == 0) {
+ hz = 1;
+ fprintf(stderr, "time is in ticks, not seconds\n");
+ }
+ /*
+ * dump out a gmon.sum file if requested
+ */
+ if ( sflag ) {
+ dumpsum( GMONSUM );
+ }
+ /*
+ * assign samples to procedures
+ */
+ asgnsamples();
+ /*
+ * assemble the dynamic profile
+ */
+ timesortnlp = doarcs();
+ /*
+ * print the dynamic profile
+ */
+ if(!lflag) {
+ printgprof( timesortnlp );
+ }
+ /*
+ * print the flat profile
+ */
+ if(!Lflag) {
+ printprof();
+ }
+ /*
+ * print the index
+ */
+ printindex();
+ exit(0);
+}
+
+ /*
+ * information from a gmon.out file is in two parts:
+ * an array of sampling hits within pc ranges,
+ * and the arcs.
+ */
+void
+getpfile(char *filename)
+{
+ FILE *pfile;
+ struct rawarc arc;
+
+ pfile = openpfile(filename);
+ readsamples(pfile);
+ /*
+ * the rest of the file consists of
+ * a bunch of <from,self,count> tuples.
+ */
+ while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) {
+# ifdef DEBUG
+ if ( debug & SAMPLEDEBUG ) {
+ printf( "[getpfile] frompc 0x%lx selfpc 0x%lx count %ld\n" ,
+ arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
+ }
+# endif /* DEBUG */
+ /*
+ * add this arc
+ */
+ tally( &arc );
+ }
+ fclose(pfile);
+}
+
+FILE *
+openpfile(char *filename)
+{
+ struct gmonhdr tmp;
+ FILE *pfile;
+ int size;
+ int rate;
+
+ if((pfile = fopen(filename, "r")) == NULL)
+ err(1, "%s", filename);
+ fread(&tmp, sizeof(struct gmonhdr), 1, pfile);
+ if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc ||
+ tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) )
+ errx(1, "%s: incompatible with first gmon file", filename);
+ gmonhdr = tmp;
+ if ( gmonhdr.version == GMONVERSION ) {
+ rate = gmonhdr.profrate;
+ size = sizeof(struct gmonhdr);
+ } else {
+ fseek(pfile, sizeof(struct ophdr), SEEK_SET);
+ size = sizeof(struct ophdr);
+ gmonhdr.profrate = rate = hertz();
+ gmonhdr.version = GMONVERSION;
+ }
+ if (hz == 0) {
+ hz = rate;
+ } else if (hz != rate)
+ errx(0, "%s: profile clock rate (%d) %s (%ld) in first gmon file",
+ filename, rate, "incompatible with clock rate", hz);
+ if ( gmonhdr.histcounter_type == 0 ) {
+ /* Historical case. The type was u_short (2 bytes in practice). */
+ histcounter_type = 16;
+ histcounter_size = 2;
+ } else {
+ histcounter_type = gmonhdr.histcounter_type;
+ histcounter_size = abs(histcounter_type) / CHAR_BIT;
+ }
+ s_lowpc = (unsigned long) gmonhdr.lpc;
+ s_highpc = (unsigned long) gmonhdr.hpc;
+ lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2;
+ highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2;
+ sampbytes = gmonhdr.ncnt - size;
+ nsamples = sampbytes / histcounter_size;
+# ifdef DEBUG
+ if ( debug & SAMPLEDEBUG ) {
+ printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n",
+ gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt );
+ printf( "[openpfile] s_lowpc 0x%lx s_highpc 0x%lx\n" ,
+ s_lowpc , s_highpc );
+ printf( "[openpfile] lowpc 0x%lx highpc 0x%lx\n" ,
+ lowpc , highpc );
+ printf( "[openpfile] sampbytes %d nsamples %d\n" ,
+ sampbytes , nsamples );
+ printf( "[openpfile] sample rate %ld\n" , hz );
+ }
+# endif /* DEBUG */
+ return(pfile);
+}
+
+void
+tally(struct rawarc *rawp)
+{
+ nltype *parentp;
+ nltype *childp;
+
+ parentp = nllookup( rawp -> raw_frompc );
+ childp = nllookup( rawp -> raw_selfpc );
+ if ( parentp == 0 || childp == 0 )
+ return;
+ if ( kflag
+ && onlist( kfromlist , parentp -> name )
+ && onlist( ktolist , childp -> name ) ) {
+ return;
+ }
+ childp -> ncall += rawp -> raw_count;
+# ifdef DEBUG
+ if ( debug & TALLYDEBUG ) {
+ printf( "[tally] arc from %s to %s traversed %ld times\n" ,
+ parentp -> name , childp -> name , rawp -> raw_count );
+ }
+# endif /* DEBUG */
+ addarc( parentp , childp , rawp -> raw_count );
+}
+
+/*
+ * dump out the gmon.sum file
+ */
+void
+dumpsum(const char *sumfile)
+{
+ register nltype *nlp;
+ register arctype *arcp;
+ struct rawarc arc;
+ FILE *sfile;
+
+ if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL )
+ err( 1 , "%s" , sumfile );
+ /*
+ * dump the header; use the last header read in
+ */
+ if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 )
+ err( 1 , "%s" , sumfile );
+ /*
+ * dump the samples
+ */
+ if (fwrite(samples, histcounter_size, nsamples, sfile) != nsamples)
+ err( 1 , "%s" , sumfile );
+ /*
+ * dump the normalized raw arc information
+ */
+ for ( nlp = nl ; nlp < npe ; nlp++ ) {
+ for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+ arc.raw_frompc = arcp -> arc_parentp -> value;
+ arc.raw_selfpc = arcp -> arc_childp -> value;
+ arc.raw_count = arcp -> arc_count;
+ if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 )
+ err( 1 , "%s" , sumfile );
+# ifdef DEBUG
+ if ( debug & SAMPLEDEBUG ) {
+ printf( "[dumpsum] frompc 0x%lx selfpc 0x%lx count %ld\n" ,
+ arc.raw_frompc , arc.raw_selfpc , arc.raw_count );
+ }
+# endif /* DEBUG */
+ }
+ }
+ fclose( sfile );
+}
+
+static int
+valcmp(const void *v1, const void *v2)
+{
+ const nltype *p1 = (const nltype *)v1;
+ const nltype *p2 = (const nltype *)v2;
+
+ if ( p1 -> value < p2 -> value ) {
+ return LESSTHAN;
+ }
+ if ( p1 -> value > p2 -> value ) {
+ return GREATERTHAN;
+ }
+ return EQUALTO;
+}
+
+void
+readsamples(FILE *pfile)
+{
+ int i;
+ intmax_t sample;
+
+ if (samples == 0) {
+ samples = (double *) calloc(nsamples, sizeof(double));
+ if (samples == NULL)
+ errx(0, "no room for %d sample pc's", nsamples);
+ }
+ for (i = 0; i < nsamples; i++) {
+ fread(&sample, histcounter_size, 1, pfile);
+ if (feof(pfile))
+ break;
+ switch ( histcounter_type ) {
+ case -8:
+ samples[i] += *(int8_t *)&sample;
+ break;
+ case 8:
+ samples[i] += *(u_int8_t *)&sample;
+ break;
+ case -16:
+ samples[i] += *(int16_t *)&sample;
+ break;
+ case 16:
+ samples[i] += *(u_int16_t *)&sample;
+ break;
+ case -32:
+ samples[i] += *(int32_t *)&sample;
+ break;
+ case 32:
+ samples[i] += *(u_int32_t *)&sample;
+ break;
+ case -64:
+ samples[i] += *(int64_t *)&sample;
+ break;
+ case 64:
+ samples[i] += *(u_int64_t *)&sample;
+ break;
+ default:
+ err(1, "unsupported histogram counter type %d", histcounter_type);
+ }
+ }
+ if (i != nsamples)
+ errx(1, "unexpected EOF after reading %d/%d samples", --i , nsamples );
+}
+
+/*
+ * Assign samples to the procedures to which they belong.
+ *
+ * There are three cases as to where pcl and pch can be
+ * with respect to the routine entry addresses svalue0 and svalue1
+ * as shown in the following diagram. overlap computes the
+ * distance between the arrows, the fraction of the sample
+ * that is to be credited to the routine which starts at svalue0.
+ *
+ * svalue0 svalue1
+ * | |
+ * v v
+ *
+ * +-----------------------------------------------+
+ * | |
+ * | ->| |<- ->| |<- ->| |<- |
+ * | | | | | |
+ * +---------+ +---------+ +---------+
+ *
+ * ^ ^ ^ ^ ^ ^
+ * | | | | | |
+ * pcl pch pcl pch pcl pch
+ *
+ * For the vax we assert that samples will never fall in the first
+ * two bytes of any routine, since that is the entry mask,
+ * thus we give call alignentries() to adjust the entry points if
+ * the entry mask falls in one bucket but the code for the routine
+ * doesn't start until the next bucket. In conjunction with the
+ * alignment of routine addresses, this should allow us to have
+ * only one sample for every four bytes of text space and never
+ * have any overlap (the two end cases, above).
+ */
+void
+asgnsamples(void)
+{
+ register int j;
+ double ccnt;
+ double thetime;
+ unsigned long pcl, pch;
+ register int i;
+ unsigned long overlap;
+ unsigned long svalue0, svalue1;
+
+ /* read samples and assign to namelist symbols */
+ scale = highpc - lowpc;
+ scale /= nsamples;
+ alignentries();
+ for (i = 0, j = 1; i < nsamples; i++) {
+ ccnt = samples[i];
+ if (ccnt == 0)
+ continue;
+ pcl = lowpc + (unsigned long)(scale * i);
+ pch = lowpc + (unsigned long)(scale * (i + 1));
+ thetime = ccnt;
+# ifdef DEBUG
+ if ( debug & SAMPLEDEBUG ) {
+ printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %.0f\n" ,
+ pcl , pch , ccnt );
+ }
+# endif /* DEBUG */
+ totime += thetime;
+ for (j = j - 1; j < nname; j++) {
+ svalue0 = nl[j].svalue;
+ svalue1 = nl[j+1].svalue;
+ /*
+ * if high end of tick is below entry address,
+ * go for next tick.
+ */
+ if (pch < svalue0)
+ break;
+ /*
+ * if low end of tick into next routine,
+ * go for next routine.
+ */
+ if (pcl >= svalue1)
+ continue;
+ overlap = min(pch, svalue1) - max(pcl, svalue0);
+ if (overlap > 0) {
+# ifdef DEBUG
+ if (debug & SAMPLEDEBUG) {
+ printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n",
+ nl[j].value / HISTORICAL_SCALE_2,
+ svalue0, svalue1, nl[j].name,
+ overlap * thetime / scale, overlap);
+ }
+# endif /* DEBUG */
+ nl[j].time += overlap * thetime / scale;
+ }
+ }
+ }
+# ifdef DEBUG
+ if (debug & SAMPLEDEBUG) {
+ printf("[asgnsamples] totime %f\n", totime);
+ }
+# endif /* DEBUG */
+}
+
+
+unsigned long
+min(unsigned long a, unsigned long b)
+{
+ if (a<b)
+ return(a);
+ return(b);
+}
+
+unsigned long
+max(unsigned long a, unsigned long b)
+{
+ if (a>b)
+ return(a);
+ return(b);
+}
+
+ /*
+ * calculate scaled entry point addresses (to save time in asgnsamples),
+ * and possibly push the scaled entry points over the entry mask,
+ * if it turns out that the entry point is in one bucket and the code
+ * for a routine is in the next bucket.
+ */
+void
+alignentries(void)
+{
+ register struct nl *nlp;
+ unsigned long bucket_of_entry;
+ unsigned long bucket_of_code;
+
+ for (nlp = nl; nlp < npe; nlp++) {
+ nlp -> svalue = nlp -> value / HISTORICAL_SCALE_2;
+ bucket_of_entry = (nlp->svalue - lowpc) / scale;
+ bucket_of_code = (nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2 -
+ lowpc) / scale;
+ if (bucket_of_entry < bucket_of_code) {
+# ifdef DEBUG
+ if (debug & SAMPLEDEBUG) {
+ printf("[alignentries] pushing svalue 0x%lx to 0x%lx\n",
+ nlp->svalue,
+ nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2);
+ }
+# endif /* DEBUG */
+ nlp->svalue += OFFSET_OF_CODE / HISTORICAL_SCALE_2;
+ }
+ }
+}
diff --git a/usr.bin/gprof/gprof.callg b/usr.bin/gprof/gprof.callg
new file mode 100644
index 000000000000..533c96ca4396
--- /dev/null
+++ b/usr.bin/gprof/gprof.callg
@@ -0,0 +1,108 @@
+
+
+
+call graph profile:
+ The sum of self and descendents is the major sort
+ for this listing.
+
+ function entries:
+
+index the index of the function in the call graph
+ listing, as an aid to locating it (see below).
+
+%time the percentage of the total time of the program
+ accounted for by this function and its
+ descendents.
+
+self the number of seconds spent in this function
+ itself.
+
+descendents
+ the number of seconds spent in the descendents of
+ this function on behalf of this function.
+
+called the number of times this function is called (other
+ than recursive calls).
+
+self the number of times this function calls itself
+ recursively.
+
+name the name of the function, with an indication of
+ its membership in a cycle, if any.
+
+index the index of the function in the call graph
+ listing, as an aid to locating it.
+
+
+
+ parent listings:
+
+self* the number of seconds of this function's self time
+ which is due to calls from this parent.
+
+descendents*
+ the number of seconds of this function's
+ descendent time which is due to calls from this
+ parent.
+
+called** the number of times this function is called by
+ this parent. This is the numerator of the
+ fraction which divides up the function's time to
+ its parents.
+
+total* the number of times this function was called by
+ all of its parents. This is the denominator of
+ the propagation fraction.
+
+parents the name of this parent, with an indication of the
+ parent's membership in a cycle, if any.
+
+index the index of this parent in the call graph
+ listing, as an aid in locating it.
+
+
+
+ children listings:
+
+self* the number of seconds of this child's self time
+ which is due to being called by this function.
+
+descendent*
+ the number of seconds of this child's descendent's
+ time which is due to being called by this
+ function.
+
+called** the number of times this child is called by this
+ function. This is the numerator of the
+ propagation fraction for this child.
+
+total* the number of times this child is called by all
+ functions. This is the denominator of the
+ propagation fraction.
+
+children the name of this child, and an indication of its
+ membership in a cycle, if any.
+
+index the index of this child in the call graph listing,
+ as an aid to locating it.
+
+
+
+ * these fields are omitted for parents (or
+ children) in the same cycle as the function. If
+ the function (or child) is a member of a cycle,
+ the propagated times and propagation denominator
+ represent the self time and descendent time of the
+ cycle as a whole.
+
+ ** static-only parents and children are indicated
+ by a call count of 0.
+
+
+
+ cycle listings:
+ the cycle as a whole is listed with the same
+ fields as a function entry. Below it are listed
+ the members of the cycle, and their contributions
+ to the time and call counts of the cycle.
+
diff --git a/usr.bin/gprof/gprof.flat b/usr.bin/gprof/gprof.flat
new file mode 100644
index 000000000000..60999a35f2fc
--- /dev/null
+++ b/usr.bin/gprof/gprof.flat
@@ -0,0 +1,32 @@
+
+
+
+flat profile:
+
+ % the percentage of the total running time of the
+time program used by this function.
+
+cumulative a running sum of the number of seconds accounted
+ seconds for by this function and those listed above it.
+
+ self the number of seconds accounted for by this
+seconds function alone. This is the major sort for this
+ listing.
+
+calls the number of times this function was invoked, if
+ this function is profiled, else blank.
+
+ self the average number of milliseconds spent in this
+ms/call function per call, if this function is profiled,
+ else blank.
+
+ total the average number of milliseconds spent in this
+ms/call function and its descendents per call, if this
+ function is profiled, else blank.
+
+name the name of the function. This is the minor sort
+ for this listing. The index shows the location of
+ the function in the gprof listing. If the index is
+ in parenthesis it shows where it would appear in
+ the gprof listing if it were to be printed.
+
diff --git a/usr.bin/gprof/gprof.h b/usr.bin/gprof/gprof.h
new file mode 100644
index 000000000000..9cb6493e7c24
--- /dev/null
+++ b/usr.bin/gprof/gprof.h
@@ -0,0 +1,324 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/gmon.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+ /*
+ * offset (in bytes) of the code from the entry address of a routine.
+ * (see asgnsamples for use and explanation.)
+ */
+#define OFFSET_OF_CODE 0
+
+enum opermodes { dummy };
+typedef enum opermodes operandenum;
+
+ /*
+ * booleans
+ */
+typedef int bool;
+#define FALSE 0
+#define TRUE 1
+
+ /*
+ * Historical scale factor in profil(2)'s algorithm for converting
+ * pc addresses to bucket numbers. This now just complicates the
+ * scaling and makes bucket:pc densities of more than 1/2 useless.
+ */
+#define HISTORICAL_SCALE_2 2
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+ /*
+ * ticks per second
+ */
+EXTERN long hz;
+
+EXTERN size_t histcounter_size;
+EXTERN int histcounter_type;
+
+EXTERN char *a_outname;
+#define A_OUTNAME "a.out"
+
+EXTERN char *gmonname;
+#define GMONSUM "gmon.sum"
+
+ /*
+ * a constructed arc,
+ * with pointers to the namelist entry of the parent and the child,
+ * a count of how many times this arc was traversed,
+ * and pointers to the next parent of this child and
+ * the next child of this parent.
+ */
+struct arcstruct {
+ struct nl *arc_parentp; /* pointer to parent's nl entry */
+ struct nl *arc_childp; /* pointer to child's nl entry */
+ long arc_count; /* num calls from parent to child */
+ double arc_time; /* time inherited along arc */
+ double arc_childtime; /* childtime inherited along arc */
+ struct arcstruct *arc_parentlist; /* parents-of-this-child list */
+ struct arcstruct *arc_childlist; /* children-of-this-parent list */
+ struct arcstruct *arc_next; /* list of arcs on cycle */
+ unsigned short arc_cyclecnt; /* num cycles involved in */
+ unsigned short arc_flags; /* see below */
+};
+typedef struct arcstruct arctype;
+
+ /*
+ * arc flags
+ */
+#define DEADARC 0x01 /* time should not propagate across the arc */
+#define ONLIST 0x02 /* arc is on list of arcs in cycles */
+
+ /*
+ * The symbol table;
+ * for each external in the specified file we gather
+ * its address, the number of calls and compute its share of CPU time.
+ */
+struct nl {
+ const char *name; /* the name */
+ unsigned long value; /* the pc entry point */
+ unsigned long svalue; /* entry point aligned to histograms */
+ double time; /* ticks in this routine */
+ double childtime; /* cumulative ticks in children */
+ long ncall; /* how many times called */
+ long npropcall; /* times called by live arcs */
+ long selfcalls; /* how many calls to self */
+ double propfraction; /* what % of time propagates */
+ double propself; /* how much self time propagates */
+ double propchild; /* how much child time propagates */
+ short printflag; /* should this be printed? */
+ short flags; /* see below */
+ int index; /* index in the graph list */
+ int toporder; /* graph call chain top-sort order */
+ int cycleno; /* internal number of cycle on */
+ int parentcnt; /* number of live parent arcs */
+ struct nl *cyclehead; /* pointer to head of cycle */
+ struct nl *cnext; /* pointer to next member of cycle */
+ arctype *parents; /* list of caller arcs */
+ arctype *children; /* list of callee arcs */
+};
+typedef struct nl nltype;
+
+EXTERN nltype *nl; /* the whole namelist */
+EXTERN nltype *npe; /* the virtual end of the namelist */
+EXTERN int nname; /* the number of function names */
+
+#define HASCYCLEXIT 0x08 /* node has arc exiting from cycle */
+#define CYCLEHEAD 0x10 /* node marked as head of a cycle */
+#define VISITED 0x20 /* node visited during a cycle */
+
+ /*
+ * The cycle list.
+ * for each subcycle within an identified cycle, we gather
+ * its size and the list of included arcs.
+ */
+struct cl {
+ int size; /* length of cycle */
+ struct cl *next; /* next member of list */
+ arctype *list[1]; /* list of arcs in cycle */
+ /* actually longer */
+};
+typedef struct cl cltype;
+
+EXTERN arctype *archead; /* the head of arcs in current cycle list */
+EXTERN cltype *cyclehead; /* the head of the list */
+EXTERN int cyclecnt; /* the number of cycles found */
+#define CYCLEMAX 100 /* maximum cycles before cutting one of them */
+
+ /*
+ * flag which marks a nl entry as topologically ``busy''
+ * flag which marks a nl entry as topologically ``not_numbered''
+ */
+#define DFN_BUSY -1
+#define DFN_NAN 0
+
+ /*
+ * namelist entries for cycle headers.
+ * the number of discovered cycles.
+ */
+EXTERN nltype *cyclenl; /* cycle header namelist */
+EXTERN int ncycle; /* number of cycles discovered */
+
+ /*
+ * The header on the gmon.out file.
+ * gmon.out consists of a struct phdr (defined in gmon.h)
+ * and then an array of ncnt samples representing the
+ * discretized program counter values.
+ *
+ * Backward compatible old style header
+ */
+struct ophdr {
+ u_short *lpc;
+ u_short *hpc;
+ int ncnt;
+};
+
+EXTERN int debug;
+
+ /*
+ * Each discretized pc sample has
+ * a count of the number of samples in its range
+ */
+EXTERN double *samples;
+
+EXTERN unsigned long s_lowpc; /* lowpc from the profile file */
+EXTERN unsigned long s_highpc; /* highpc from the profile file */
+/* range profiled, in historical units */
+EXTERN unsigned long lowpc, highpc;
+EXTERN unsigned sampbytes; /* number of bytes of samples */
+EXTERN int nsamples; /* number of samples */
+/* accumulated time thus far for putprofline */
+EXTERN double actime;
+EXTERN double totime; /* total time for all routines */
+EXTERN double printtime; /* total of time being printed */
+EXTERN double scale; /* scale factor converting samples to pc
+ values: each sample covers scale bytes */
+EXTERN unsigned char *textspace; /* text space of a.out in core */
+/* with -C, minimum cycle size to ignore */
+EXTERN int cyclethreshold;
+
+ /*
+ * option flags, from a to z.
+ */
+EXTERN bool aflag; /* suppress static functions */
+EXTERN bool bflag; /* blurbs, too */
+EXTERN bool Cflag; /* find cut-set to eliminate cycles */
+EXTERN bool dflag; /* debugging options */
+EXTERN bool eflag; /* specific functions excluded */
+EXTERN bool Eflag; /* functions excluded with time */
+EXTERN bool fflag; /* specific functions requested */
+EXTERN bool Fflag; /* functions requested with time */
+EXTERN bool kflag; /* arcs to be deleted */
+EXTERN bool Kflag; /* use the running kernel for symbols */
+EXTERN bool sflag; /* sum multiple gmon.out files */
+EXTERN bool uflag; /* suppress symbols hidden from C */
+EXTERN bool zflag; /* zero time/called functions, too */
+
+ /*
+ * structure for various string lists
+ */
+struct stringlist {
+ struct stringlist *next;
+ char *string;
+};
+extern struct stringlist *elist;
+extern struct stringlist *Elist;
+extern struct stringlist *flist;
+extern struct stringlist *Flist;
+extern struct stringlist *kfromlist;
+extern struct stringlist *ktolist;
+
+ /*
+ * function declarations
+ */
+void addarc(nltype *, nltype *, long);
+bool addcycle(arctype **, arctype **);
+void addlist(struct stringlist *, char *);
+void alignentries(void);
+int arccmp(arctype *, arctype *);
+arctype *arclookup(nltype *, nltype *);
+void asgnsamples(void);
+void compresslist(void);
+bool cycleanalyze(void);
+void cyclelink(void);
+void cycletime(void);
+bool descend(nltype *, arctype **, arctype **);
+void dfn(nltype *);
+bool dfn_busy(nltype *);
+void dfn_findcycle(nltype *);
+void dfn_init(void);
+bool dfn_numbered(nltype *);
+void dfn_post_visit(nltype *);
+void dfn_pre_visit(nltype *);
+void dfn_self_cycle(nltype *);
+nltype **doarcs(void);
+void doflags(void);
+void dotime(void);
+void dumpsum(const char *);
+int elf_getnfile(const char *, char ***);
+void flatprofheader(void);
+void flatprofline(nltype *);
+void getpfile(char *);
+void gprofheader(void);
+void gprofline(register nltype *);
+int hertz(void);
+void inheritflags(nltype *);
+int kernel_getnfile(const char *, char ***);
+/*
+ main();
+*/
+unsigned long max(unsigned long, unsigned long);
+int membercmp(nltype *, nltype *);
+unsigned long min(unsigned long, unsigned long);
+nltype *nllookup(unsigned long);
+bool onlist(struct stringlist *, const char *);
+FILE *openpfile(char *);
+void printblurb(const char *);
+void printchildren(nltype *);
+void printcycle(nltype *);
+void printgprof(nltype **);
+void printindex(void);
+void printmembers(nltype *);
+void printname(nltype *);
+void printparents(nltype *);
+void printprof(void);
+void printsubcycle(cltype *);
+void readsamples(FILE *);
+void sortchildren(nltype *);
+void sortmembers(nltype *);
+void sortparents(nltype *);
+void tally(struct rawarc *);
+void timepropagate(nltype *);
+int totalcmp(const void *, const void *);
+
+#define LESSTHAN -1
+#define EQUALTO 0
+#define GREATERTHAN 1
+
+#define DFNDEBUG 1
+#define CYCLEDEBUG 2
+#define ARCDEBUG 4
+#define TALLYDEBUG 8
+#define TIMEDEBUG 16
+#define SAMPLEDEBUG 32
+#define CALLDEBUG 128
+#define LOOKUPDEBUG 256
+#define PROPDEBUG 512
+#define BREAKCYCLE 1024
+#define SUBCYCLELIST 2048
+#define ANYDEBUG 4096
diff --git a/usr.bin/gprof/hertz.c b/usr.bin/gprof/hertz.c
new file mode 100644
index 000000000000..2d1b6edca52a
--- /dev/null
+++ b/usr.bin/gprof/hertz.c
@@ -0,0 +1,57 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/time.h>
+
+ /*
+ * discover the tick frequency of the machine
+ * if something goes wrong, we return 0, an impossible hertz.
+ */
+#define HZ_WRONG 0
+
+int hertz(void);
+
+int
+hertz(void)
+{
+ struct itimerval tim;
+
+ tim.it_interval.tv_sec = 0;
+ tim.it_interval.tv_usec = 1;
+ tim.it_value.tv_sec = 0;
+ tim.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &tim, 0);
+ setitimer(ITIMER_REAL, 0, &tim);
+ if (tim.it_interval.tv_usec < 2)
+ return(HZ_WRONG);
+ return (1000000 / tim.it_interval.tv_usec);
+}
diff --git a/usr.bin/gprof/kernel.c b/usr.bin/gprof/kernel.c
new file mode 100644
index 000000000000..ca2d53ed3f56
--- /dev/null
+++ b/usr.bin/gprof/kernel.c
@@ -0,0 +1,62 @@
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gprof.h"
+
+/* Things which get -E excluded by default. */
+static char *excludes[] = { ".mcount", "_mcleanup", NULL };
+
+int
+kernel_getnfile(const char *unused __unused, char ***defaultEs)
+{
+ char *namelist;
+ size_t len;
+ char *name;
+
+ if (sysctlbyname("kern.function_list", NULL, &len, NULL, 0) == -1)
+ err(1, "sysctlbyname: function_list size");
+ for (;;) {
+ namelist = malloc(len);
+ if (namelist == NULL)
+ err(1, "malloc");
+ if (sysctlbyname("kern.function_list", namelist, &len, NULL,
+ 0) == 0)
+ break;
+ if (errno == ENOMEM)
+ free(namelist);
+ else
+ err(1, "sysctlbyname: function_list");
+ }
+ nname = 0;
+ for (name = namelist; *name != '\0'; name += strlen(name) + 1)
+ nname++;
+ /* Allocate memory for them, plus a terminating entry. */
+ if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
+ errx(1, "Insufficient memory for symbol table");
+ npe = nl;
+ for (name = namelist; *name != '\0'; name += strlen(name) + 1) {
+ struct kld_sym_lookup ksl;
+
+ ksl.version = sizeof(ksl);
+ ksl.symname = name;
+ if (kldsym(0, KLDSYM_LOOKUP, &ksl))
+ err(1, "kldsym(%s)", name);
+ /* aflag not supported */
+ if (uflag && strchr(name, '.') != NULL)
+ continue;
+ npe->value = ksl.symvalue;
+ npe->name = name;
+ npe++;
+ }
+ npe->value = -1;
+
+ *defaultEs = excludes;
+ return (0);
+}
diff --git a/usr.bin/gprof/lookup.c b/usr.bin/gprof/lookup.c
new file mode 100644
index 000000000000..1d53744f59cc
--- /dev/null
+++ b/usr.bin/gprof/lookup.c
@@ -0,0 +1,113 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include "gprof.h"
+
+ /*
+ * look up an address in a sorted-by-address namelist
+ * this deals with misses by mapping them to the next lower
+ * entry point.
+ */
+nltype *
+nllookup(unsigned long address)
+{
+ register long low;
+ register long middle;
+ register long high;
+# ifdef DEBUG
+ register int probes;
+
+ probes = 0;
+# endif /* DEBUG */
+ for ( low = 0 , high = nname - 1 ; low != high ; ) {
+# ifdef DEBUG
+ probes += 1;
+# endif /* DEBUG */
+ middle = ( high + low ) >> 1;
+ if ( nl[ middle ].value <= address && nl[ middle+1 ].value > address ) {
+# ifdef DEBUG
+ if ( debug & LOOKUPDEBUG ) {
+ printf( "[nllookup] %d (%d) probes\n" , probes , nname-1 );
+ }
+# endif /* DEBUG */
+#if defined(__arm__)
+ if (nl[middle].name[0] == '$' &&
+ nl[middle-1].value == nl[middle].value)
+ middle--;
+#endif
+
+ return &nl[ middle ];
+ }
+ if ( nl[ middle ].value > address ) {
+ high = middle;
+ } else {
+ low = middle + 1;
+ }
+ }
+# ifdef DEBUG
+ if ( debug & LOOKUPDEBUG ) {
+ fprintf( stderr , "[nllookup] (%d) binary search fails\n" ,
+ nname-1 );
+ }
+# endif /* DEBUG */
+ return 0;
+}
+
+arctype *
+arclookup(nltype *parentp, nltype *childp)
+{
+ arctype *arcp;
+
+ if ( parentp == 0 || childp == 0 ) {
+ fprintf( stderr, "[arclookup] parentp == 0 || childp == 0\n" );
+ return 0;
+ }
+# ifdef DEBUG
+ if ( debug & LOOKUPDEBUG ) {
+ printf( "[arclookup] parent %s child %s\n" ,
+ parentp -> name , childp -> name );
+ }
+# endif /* DEBUG */
+ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+# ifdef DEBUG
+ if ( debug & LOOKUPDEBUG ) {
+ printf( "[arclookup]\t arc_parent %s arc_child %s\n" ,
+ arcp -> arc_parentp -> name ,
+ arcp -> arc_childp -> name );
+ }
+# endif /* DEBUG */
+ if ( arcp -> arc_childp == childp ) {
+ return arcp;
+ }
+ }
+ return 0;
+}
diff --git a/usr.bin/gprof/pathnames.h b/usr.bin/gprof/pathnames.h
new file mode 100644
index 000000000000..958cdcac9f32
--- /dev/null
+++ b/usr.bin/gprof/pathnames.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_FLAT_BLURB "/usr/share/misc/gprof.flat"
+#define _PATH_CALLG_BLURB "/usr/share/misc/gprof.callg"
+
diff --git a/usr.bin/gprof/printgprof.c b/usr.bin/gprof/printgprof.c
new file mode 100644
index 000000000000..07791bf2d154
--- /dev/null
+++ b/usr.bin/gprof/printgprof.c
@@ -0,0 +1,740 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <string.h>
+
+#include "gprof.h"
+#include "pathnames.h"
+
+int namecmp(const void *, const void *);
+int timecmp(const void *, const void *);
+
+void
+printprof(void)
+{
+ register nltype *np;
+ nltype **sortednlp;
+ int idx;
+
+ actime = 0.0;
+ printf( "\f\n" );
+ flatprofheader();
+ /*
+ * Sort the symbol table in by time
+ */
+ sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
+ if ( sortednlp == (nltype **) 0 )
+ errx( 1 , "[printprof] ran out of memory for time sorting" );
+ for ( idx = 0 ; idx < nname ; idx += 1 ) {
+ sortednlp[ idx ] = &nl[ idx ];
+ }
+ qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
+ for ( idx = 0 ; idx < nname ; idx += 1 ) {
+ np = sortednlp[ idx ];
+ flatprofline( np );
+ }
+ actime = 0.0;
+ free( sortednlp );
+}
+
+int
+timecmp(const void *v1, const void *v2)
+{
+ const nltype **npp1 = (const nltype **)v1;
+ const nltype **npp2 = (const nltype **)v2;
+ double timediff;
+ long calldiff;
+
+ timediff = (*npp2) -> time - (*npp1) -> time;
+ if ( timediff > 0.0 )
+ return 1 ;
+ if ( timediff < 0.0 )
+ return -1;
+ calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
+ if ( calldiff > 0 )
+ return 1;
+ if ( calldiff < 0 )
+ return -1;
+ return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
+}
+
+ /*
+ * header for flatprofline
+ */
+void
+flatprofheader(void)
+{
+
+ if ( bflag ) {
+ printblurb( _PATH_FLAT_BLURB );
+ }
+ printf( "\ngranularity: each sample hit covers %g byte(s)" ,
+ scale * HISTORICAL_SCALE_2 );
+ if ( totime > 0.0 ) {
+ printf( " for %.2f%% of %.2f seconds\n\n" ,
+ 100.0/totime , totime / hz );
+ } else {
+ printf( " no time accumulated\n\n" );
+ /*
+ * this doesn't hurt since all the numerators will be zero.
+ */
+ totime = 1.0;
+ }
+ printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
+ "% " , "cumulative" , "self " , "" , "self " , "total " , "" );
+ printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" ,
+ "time" , "seconds " , "seconds" , "calls" ,
+ hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" ,
+ hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" ,
+ "name" );
+}
+
+void
+flatprofline(register nltype *np)
+{
+
+ if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 &&
+ np -> childtime == 0 ) {
+ return;
+ }
+ actime += np -> time;
+ if (hz >= 10000)
+ printf( "%5.1f %10.3f %8.3f" ,
+ 100 * np -> time / totime , actime / hz , np -> time / hz );
+ else
+ printf( "%5.1f %10.2f %8.2f" ,
+ 100 * np -> time / totime , actime / hz , np -> time / hz );
+ if ( np -> ncall != 0 ) {
+ if (hz >= 10000000)
+ printf( " %8ld %8.0f %8.0f " , np -> ncall ,
+ 1e9 * np -> time / hz / np -> ncall ,
+ 1e9 * ( np -> time + np -> childtime ) / hz / np -> ncall );
+ else if (hz >= 10000)
+ printf( " %8ld %8.0f %8.0f " , np -> ncall ,
+ 1e6 * np -> time / hz / np -> ncall ,
+ 1e6 * ( np -> time + np -> childtime ) / hz / np -> ncall );
+ else
+ printf( " %8ld %8.2f %8.2f " , np -> ncall ,
+ 1000 * np -> time / hz / np -> ncall ,
+ 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
+ } else if ( np -> time != 0 || np -> childtime != 0 ) {
+ printf( " %8ld %7.2f%% %8.8s " , np -> ncall ,
+ 100 * np -> time / ( np -> time + np -> childtime ) , "" );
+ } else {
+ printf( " %8.8s %8.8s %8.8s " , "" , "" , "" );
+ }
+ printname( np );
+ printf( "\n" );
+}
+
+void
+gprofheader(void)
+{
+
+ if ( bflag ) {
+ printblurb( _PATH_CALLG_BLURB );
+ }
+ printf( "\ngranularity: each sample hit covers %g byte(s)" ,
+ scale * HISTORICAL_SCALE_2 );
+ if ( printtime > 0.0 ) {
+ printf( " for %.2f%% of %.2f seconds\n\n" ,
+ 100.0/printtime , printtime / hz );
+ } else {
+ printf( " no time propagated\n\n" );
+ /*
+ * this doesn't hurt, since all the numerators will be 0.0
+ */
+ printtime = 1.0;
+ }
+ printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
+ "" , "" , "" , "" , "called" , "total" , "parents");
+ printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
+ "index" , "%time" , "self" , "descendents" ,
+ "called" , "self" , "name" , "index" );
+ printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" ,
+ "" , "" , "" , "" , "called" , "total" , "children");
+ printf( "\n" );
+}
+
+void
+gprofline(register nltype *np)
+{
+ char kirkbuffer[ BUFSIZ ];
+
+ sprintf( kirkbuffer , "[%d]" , np -> index );
+ printf( "%-6.6s %5.1f %7.2f %11.2f" ,
+ kirkbuffer ,
+ 100 * ( np -> propself + np -> propchild ) / printtime ,
+ np -> propself / hz ,
+ np -> propchild / hz );
+ if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
+ printf( " %7ld" , np -> npropcall );
+ if ( np -> selfcalls != 0 ) {
+ printf( "+%-7ld " , np -> selfcalls );
+ } else {
+ printf( " %7.7s " , "" );
+ }
+ } else {
+ printf( " %7.7s %7.7s " , "" , "" );
+ }
+ printname( np );
+ printf( "\n" );
+}
+
+void
+printgprof(nltype **timesortnlp)
+{
+ int idx;
+ nltype *parentp;
+
+ /*
+ * Print out the structured profiling list
+ */
+ gprofheader();
+ for ( idx = 0 ; idx < nname + ncycle ; idx ++ ) {
+ parentp = timesortnlp[ idx ];
+ if ( zflag == 0 &&
+ parentp -> ncall == 0 &&
+ parentp -> selfcalls == 0 &&
+ parentp -> propself == 0 &&
+ parentp -> propchild == 0 ) {
+ continue;
+ }
+ if ( ! parentp -> printflag ) {
+ continue;
+ }
+ if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
+ /*
+ * cycle header
+ */
+ printcycle( parentp );
+ printmembers( parentp );
+ } else {
+ printparents( parentp );
+ gprofline( parentp );
+ printchildren( parentp );
+ }
+ printf( "\n" );
+ printf( "-----------------------------------------------\n" );
+ printf( "\n" );
+ }
+ free( timesortnlp );
+}
+
+ /*
+ * sort by decreasing propagated time
+ * if times are equal, but one is a cycle header,
+ * say that's first (e.g. less, i.e. -1).
+ * if one's name doesn't have an underscore and the other does,
+ * say the one is first.
+ * all else being equal, sort by names.
+ */
+int
+totalcmp(const void *v1, const void *v2)
+{
+ const nltype **npp1 = (const nltype **)v1;
+ const nltype **npp2 = (const nltype **)v2;
+ register const nltype *np1 = *npp1;
+ register const nltype *np2 = *npp2;
+ double diff;
+
+ diff = ( np1 -> propself + np1 -> propchild )
+ - ( np2 -> propself + np2 -> propchild );
+ if ( diff < 0.0 )
+ return 1;
+ if ( diff > 0.0 )
+ return -1;
+ if ( np1 -> name == 0 && np1 -> cycleno != 0 )
+ return -1;
+ if ( np2 -> name == 0 && np2 -> cycleno != 0 )
+ return 1;
+ if ( np1 -> name == 0 )
+ return -1;
+ if ( np2 -> name == 0 )
+ return 1;
+ if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
+ return -1;
+ if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
+ return 1;
+ if ( np1 -> ncall > np2 -> ncall )
+ return -1;
+ if ( np1 -> ncall < np2 -> ncall )
+ return 1;
+ return strcmp( np1 -> name , np2 -> name );
+}
+
+void
+printparents(nltype *childp)
+{
+ nltype *parentp;
+ arctype *arcp;
+ nltype *cycleheadp;
+
+ if ( childp -> cyclehead != 0 ) {
+ cycleheadp = childp -> cyclehead;
+ } else {
+ cycleheadp = childp;
+ }
+ if ( childp -> parents == 0 ) {
+ printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" ,
+ "" , "" , "" , "" , "" , "" );
+ return;
+ }
+ sortparents( childp );
+ for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
+ parentp = arcp -> arc_parentp;
+ if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) ||
+ ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
+ /*
+ * selfcall or call among siblings
+ */
+ printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " ,
+ "" , "" , "" , "" ,
+ arcp -> arc_count , "" );
+ printname( parentp );
+ printf( "\n" );
+ } else {
+ /*
+ * regular parent of child
+ */
+ printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " ,
+ "" , "" ,
+ arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
+ arcp -> arc_count , cycleheadp -> npropcall );
+ printname( parentp );
+ printf( "\n" );
+ }
+ }
+}
+
+void
+printchildren(nltype *parentp)
+{
+ nltype *childp;
+ arctype *arcp;
+
+ sortchildren( parentp );
+ arcp = parentp -> children;
+ for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
+ childp = arcp -> arc_childp;
+ if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) ||
+ ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
+ /*
+ * self call or call to sibling
+ */
+ printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " ,
+ "" , "" , "" , "" , arcp -> arc_count , "" );
+ printname( childp );
+ printf( "\n" );
+ } else {
+ /*
+ * regular child of parent
+ */
+ printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " ,
+ "" , "" ,
+ arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
+ arcp -> arc_count , childp -> cyclehead -> npropcall );
+ printname( childp );
+ printf( "\n" );
+ }
+ }
+}
+
+void
+printname(nltype *selfp)
+{
+
+ if ( selfp -> name != 0 ) {
+ printf( "%s" , selfp -> name );
+# ifdef DEBUG
+ if ( debug & DFNDEBUG ) {
+ printf( "{%d} " , selfp -> toporder );
+ }
+ if ( debug & PROPDEBUG ) {
+ printf( "%5.2f%% " , selfp -> propfraction );
+ }
+# endif /* DEBUG */
+ }
+ if ( selfp -> cycleno != 0 ) {
+ printf( " <cycle %d>" , selfp -> cycleno );
+ }
+ if ( selfp -> index != 0 ) {
+ if ( selfp -> printflag ) {
+ printf( " [%d]" , selfp -> index );
+ } else {
+ printf( " (%d)" , selfp -> index );
+ }
+ }
+}
+
+void
+sortchildren(nltype *parentp)
+{
+ arctype *arcp;
+ arctype *detachedp;
+ arctype sorted;
+ arctype *prevp;
+
+ /*
+ * unlink children from parent,
+ * then insertion sort back on to sorted's children.
+ * *arcp the arc you have detached and are inserting.
+ * *detachedp the rest of the arcs to be sorted.
+ * sorted arc list onto which you insertion sort.
+ * *prevp arc before the arc you are comparing.
+ */
+ sorted.arc_childlist = 0;
+ for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
+ arcp ;
+ (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
+ /*
+ * consider *arcp as disconnected
+ * insert it into sorted
+ */
+ for ( prevp = &sorted ;
+ prevp -> arc_childlist ;
+ prevp = prevp -> arc_childlist ) {
+ if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
+ break;
+ }
+ }
+ arcp -> arc_childlist = prevp -> arc_childlist;
+ prevp -> arc_childlist = arcp;
+ }
+ /*
+ * reattach sorted children to parent
+ */
+ parentp -> children = sorted.arc_childlist;
+}
+
+void
+sortparents(nltype *childp)
+{
+ arctype *arcp;
+ arctype *detachedp;
+ arctype sorted;
+ arctype *prevp;
+
+ /*
+ * unlink parents from child,
+ * then insertion sort back on to sorted's parents.
+ * *arcp the arc you have detached and are inserting.
+ * *detachedp the rest of the arcs to be sorted.
+ * sorted arc list onto which you insertion sort.
+ * *prevp arc before the arc you are comparing.
+ */
+ sorted.arc_parentlist = 0;
+ for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
+ arcp ;
+ (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
+ /*
+ * consider *arcp as disconnected
+ * insert it into sorted
+ */
+ for ( prevp = &sorted ;
+ prevp -> arc_parentlist ;
+ prevp = prevp -> arc_parentlist ) {
+ if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
+ break;
+ }
+ }
+ arcp -> arc_parentlist = prevp -> arc_parentlist;
+ prevp -> arc_parentlist = arcp;
+ }
+ /*
+ * reattach sorted arcs to child
+ */
+ childp -> parents = sorted.arc_parentlist;
+}
+
+ /*
+ * print a cycle header
+ */
+void
+printcycle(nltype *cyclep)
+{
+ char kirkbuffer[ BUFSIZ ];
+
+ sprintf( kirkbuffer , "[%d]" , cyclep -> index );
+ printf( "%-6.6s %5.1f %7.2f %11.2f %7ld" ,
+ kirkbuffer ,
+ 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
+ cyclep -> propself / hz ,
+ cyclep -> propchild / hz ,
+ cyclep -> npropcall );
+ if ( cyclep -> selfcalls != 0 ) {
+ printf( "+%-7ld" , cyclep -> selfcalls );
+ } else {
+ printf( " %7.7s" , "" );
+ }
+ printf( " <cycle %d as a whole>\t[%d]\n" ,
+ cyclep -> cycleno , cyclep -> index );
+}
+
+ /*
+ * print the members of a cycle
+ */
+void
+printmembers(nltype *cyclep)
+{
+ nltype *memberp;
+
+ sortmembers( cyclep );
+ for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
+ printf( "%6.6s %5.5s %7.2f %11.2f %7ld" ,
+ "" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
+ memberp -> npropcall );
+ if ( memberp -> selfcalls != 0 ) {
+ printf( "+%-7ld" , memberp -> selfcalls );
+ } else {
+ printf( " %7.7s" , "" );
+ }
+ printf( " " );
+ printname( memberp );
+ printf( "\n" );
+ }
+}
+
+ /*
+ * sort members of a cycle
+ */
+void
+sortmembers(nltype *cyclep)
+{
+ nltype *todo;
+ nltype *doing;
+ nltype *prev;
+
+ /*
+ * detach cycle members from cyclehead,
+ * and insertion sort them back on.
+ */
+ todo = cyclep -> cnext;
+ cyclep -> cnext = 0;
+ for ( (doing = todo)&&(todo = doing -> cnext);
+ doing ;
+ (doing = todo )&&(todo = doing -> cnext )){
+ for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
+ if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
+ break;
+ }
+ }
+ doing -> cnext = prev -> cnext;
+ prev -> cnext = doing;
+ }
+}
+
+ /*
+ * major sort is on propself + propchild,
+ * next is sort on ncalls + selfcalls.
+ */
+int
+membercmp(nltype *this, nltype *that)
+{
+ double thistime = this -> propself + this -> propchild;
+ double thattime = that -> propself + that -> propchild;
+ long thiscalls = this -> ncall + this -> selfcalls;
+ long thatcalls = that -> ncall + that -> selfcalls;
+
+ if ( thistime > thattime ) {
+ return GREATERTHAN;
+ }
+ if ( thistime < thattime ) {
+ return LESSTHAN;
+ }
+ if ( thiscalls > thatcalls ) {
+ return GREATERTHAN;
+ }
+ if ( thiscalls < thatcalls ) {
+ return LESSTHAN;
+ }
+ return EQUALTO;
+}
+ /*
+ * compare two arcs to/from the same child/parent.
+ * - if one arc is a self arc, it's least.
+ * - if one arc is within a cycle, it's less than.
+ * - if both arcs are within a cycle, compare arc counts.
+ * - if neither arc is within a cycle, compare with
+ * arc_time + arc_childtime as major key
+ * arc count as minor key
+ */
+int
+arccmp(arctype *thisp, arctype *thatp)
+{
+ nltype *thisparentp = thisp -> arc_parentp;
+ nltype *thischildp = thisp -> arc_childp;
+ nltype *thatparentp = thatp -> arc_parentp;
+ nltype *thatchildp = thatp -> arc_childp;
+ double thistime;
+ double thattime;
+
+# ifdef DEBUG
+ if ( debug & TIMEDEBUG ) {
+ printf( "[arccmp] " );
+ printname( thisparentp );
+ printf( " calls " );
+ printname ( thischildp );
+ printf( " %f + %f %ld/%ld\n" ,
+ thisp -> arc_time , thisp -> arc_childtime ,
+ thisp -> arc_count , thischildp -> ncall );
+ printf( "[arccmp] " );
+ printname( thatparentp );
+ printf( " calls " );
+ printname( thatchildp );
+ printf( " %f + %f %ld/%ld\n" ,
+ thatp -> arc_time , thatp -> arc_childtime ,
+ thatp -> arc_count , thatchildp -> ncall );
+ printf( "\n" );
+ }
+# endif /* DEBUG */
+ if ( thisparentp == thischildp ) {
+ /* this is a self call */
+ return LESSTHAN;
+ }
+ if ( thatparentp == thatchildp ) {
+ /* that is a self call */
+ return GREATERTHAN;
+ }
+ if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
+ thisparentp -> cycleno == thischildp -> cycleno ) {
+ /* this is a call within a cycle */
+ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
+ thatparentp -> cycleno == thatchildp -> cycleno ) {
+ /* that is a call within the cycle, too */
+ if ( thisp -> arc_count < thatp -> arc_count ) {
+ return LESSTHAN;
+ }
+ if ( thisp -> arc_count > thatp -> arc_count ) {
+ return GREATERTHAN;
+ }
+ return EQUALTO;
+ } else {
+ /* that isn't a call within the cycle */
+ return LESSTHAN;
+ }
+ } else {
+ /* this isn't a call within a cycle */
+ if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
+ thatparentp -> cycleno == thatchildp -> cycleno ) {
+ /* that is a call within a cycle */
+ return GREATERTHAN;
+ } else {
+ /* neither is a call within a cycle */
+ thistime = thisp -> arc_time + thisp -> arc_childtime;
+ thattime = thatp -> arc_time + thatp -> arc_childtime;
+ if ( thistime < thattime )
+ return LESSTHAN;
+ if ( thistime > thattime )
+ return GREATERTHAN;
+ if ( thisp -> arc_count < thatp -> arc_count )
+ return LESSTHAN;
+ if ( thisp -> arc_count > thatp -> arc_count )
+ return GREATERTHAN;
+ return EQUALTO;
+ }
+ }
+}
+
+void
+printblurb(const char *blurbname)
+{
+ FILE *blurbfile;
+ int input;
+
+ blurbfile = fopen( blurbname , "r" );
+ if ( blurbfile == NULL ) {
+ warn( "%s" , blurbname );
+ return;
+ }
+ while ( ( input = getc( blurbfile ) ) != EOF ) {
+ putchar( input );
+ }
+ fclose( blurbfile );
+}
+
+int
+namecmp(const void *v1, const void *v2)
+{
+ const nltype **npp1 = (const nltype **)v1;
+ const nltype **npp2 = (const nltype **)v2;
+
+ return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
+}
+
+void
+printindex(void)
+{
+ nltype **namesortnlp;
+ register nltype *nlp;
+ int idx, nnames, todo, i, j;
+ char peterbuffer[ BUFSIZ ];
+
+ /*
+ * Now, sort regular function name alphabetically
+ * to create an index.
+ */
+ namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
+ if ( namesortnlp == (nltype **) 0 )
+ errx( 1 , "ran out of memory for sorting");
+ for ( idx = 0 , nnames = 0 ; idx < nname ; idx++ ) {
+ if ( zflag == 0 && nl[idx].ncall == 0 && nl[idx].time == 0 )
+ continue;
+ namesortnlp[nnames++] = &nl[idx];
+ }
+ qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
+ for ( idx = 1 , todo = nnames ; idx <= ncycle ; idx++ ) {
+ namesortnlp[todo++] = &cyclenl[idx];
+ }
+ printf( "\f\nIndex by function name\n\n" );
+ idx = ( todo + 2 ) / 3;
+ for ( i = 0; i < idx ; i++ ) {
+ for ( j = i; j < todo ; j += idx ) {
+ nlp = namesortnlp[ j ];
+ if ( nlp -> printflag ) {
+ sprintf( peterbuffer , "[%d]" , nlp -> index );
+ } else {
+ sprintf( peterbuffer , "(%d)" , nlp -> index );
+ }
+ if ( j < nnames ) {
+ printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name );
+ } else {
+ printf( "%6.6s " , peterbuffer );
+ sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
+ printf( "%-19.19s" , peterbuffer );
+ }
+ }
+ printf( "\n" );
+ }
+ free( namesortnlp );
+}
diff --git a/usr.bin/gprof/printlist.c b/usr.bin/gprof/printlist.c
new file mode 100644
index 000000000000..a248aa9f3226
--- /dev/null
+++ b/usr.bin/gprof/printlist.c
@@ -0,0 +1,84 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <string.h>
+
+#include "gprof.h"
+
+ /*
+ * these are the lists of names:
+ * there is the list head and then the listname
+ * is a pointer to the list head
+ * (for ease of passing to stringlist functions).
+ */
+struct stringlist kfromhead = { 0 , 0 };
+struct stringlist *kfromlist = &kfromhead;
+struct stringlist ktohead = { 0 , 0 };
+struct stringlist *ktolist = &ktohead;
+struct stringlist fhead = { 0 , 0 };
+struct stringlist *flist = &fhead;
+struct stringlist Fhead = { 0 , 0 };
+struct stringlist *Flist = &Fhead;
+struct stringlist ehead = { 0 , 0 };
+struct stringlist *elist = &ehead;
+struct stringlist Ehead = { 0 , 0 };
+struct stringlist *Elist = &Ehead;
+
+void
+addlist(struct stringlist *listp, char *funcname)
+{
+ struct stringlist *slp;
+
+ slp = (struct stringlist *) malloc( sizeof(struct stringlist));
+ if ( slp == (struct stringlist *) 0 )
+ errx( 1 , "no room for printlist");
+ slp -> next = listp -> next;
+ slp -> string = funcname;
+ listp -> next = slp;
+}
+
+bool
+onlist(struct stringlist *listp, const char *funcname)
+{
+ struct stringlist *slp;
+
+ for ( slp = listp -> next ; slp ; slp = slp -> next ) {
+ if ( ! strcmp( slp -> string , funcname ) ) {
+ return TRUE;
+ }
+ if ( funcname[0] == '_' && ! strcmp( slp -> string , &funcname[1] ) ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/usr.bin/grdc/Makefile b/usr.bin/grdc/Makefile
new file mode 100644
index 000000000000..de541283e3a4
--- /dev/null
+++ b/usr.bin/grdc/Makefile
@@ -0,0 +1,7 @@
+PACKAGE= games
+
+PROG= grdc
+MAN= grdc.6
+LIBADD= tinfow ncursesw
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/grdc/Makefile.depend b/usr.bin/grdc/Makefile.depend
new file mode 100644
index 000000000000..04dbb4f44313
--- /dev/null
+++ b/usr.bin/grdc/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/grdc/grdc.6 b/usr.bin/grdc/grdc.6
new file mode 100644
index 000000000000..7420c8ecbe8b
--- /dev/null
+++ b/usr.bin/grdc/grdc.6
@@ -0,0 +1,61 @@
+.Dd January 15, 2023
+.Dt GRDC 6
+.Os
+.Sh NAME
+.Nm grdc
+.Nd grand digital clock (curses)
+.Sh SYNOPSIS
+.Nm
+.Op Fl st
+.Op Ar n
+.Nm
+.Fl c
+.Ar n
+.Sh DESCRIPTION
+.Nm
+runs a digital clock made of reverse-video blanks on a curses
+compatible VDU screen.
+With an optional numeric argument
+.Ar n
+it stops after
+.Ar n
+seconds (default never).
+The clock can act as a countdown timer with the
+.Fl c
+flag,
+.Ar n
+specifies the number of seconds to time for.
+The optional
+.Fl s
+flag makes digits scroll as they change.
+The optional
+.Fl t
+flag tells grdc to output the time in a 12-hour format.
+In this curses mode implementation,
+the scrolling option has trouble keeping up.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev TZ
+The time zone to use for displaying the time.
+It is normally specified as a pathname relative to
+.Pa /usr/share/zoneinfo ,
+though see
+.Xr tzset 3
+for more information.
+If this variable is not set, the time zone is determined based on
+.Pa /etc/localtime .
+.El
+.Sh NOTES
+In countdown timer mode, the specifying of
+.Fl n
+> 360000 seconds (100 hours) will lead to the counter displaying
+incorrect remaining time, however it will time correctly, and
+display correctly when the remaining time becomes less than
+100 hours.
+.Sh AUTHORS
+.An -nosplit
+.An Amos Shapir ,
+modified for curses by
+.An John Lupien .
+Countdown timer mode by
+.An Gavin Atkinson .
diff --git a/usr.bin/grdc/grdc.c b/usr.bin/grdc/grdc.c
new file mode 100644
index 000000000000..07d12f5a7fb0
--- /dev/null
+++ b/usr.bin/grdc/grdc.c
@@ -0,0 +1,294 @@
+/*
+ * Grand digital clock for curses compatible terminals
+ * Usage: grdc [-st] [n] -- run for n seconds (default infinity)
+ * grdc -c n -- countdown n seconds
+ * Flags: -c: Countdown timer mode
+ * -s: scroll
+ * -t: output time in 12-hour format
+ *
+ *
+ * modified 10-18-89 for curses (jrl)
+ * 10-18-89 added signal handling
+ * 02-18-02 added countdown timer mode
+ *
+ * modified 03-25-03 for 12 hour option
+ * - Samy Al Bahra <samy@kerneled.com>
+ */
+
+#include <err.h>
+#include <ncurses.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define YBASE 10
+#define XBASE 10
+#define XLENGTH 58
+#define YDEPTH 7
+
+static struct timespec now;
+static struct tm *tm;
+static struct timespec end;
+
+static short disp[11] = {
+ 075557, 011111, 071747, 071717, 055711,
+ 074717, 074757, 071111, 075757, 075717, 002020
+};
+static long old[6], next[6], new[6], mask;
+
+static volatile sig_atomic_t sigtermed;
+
+static int hascolor = 0;
+
+static void set(int, int);
+static void standt(int);
+static void movto(int, int);
+static void sighndl(int);
+static void usage(void) __dead2;
+
+static void
+sighndl(int signo)
+{
+
+ sigtermed = signo;
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct timespec delay;
+ time_t prev_sec;
+ long t, a;
+ int i, j, s, k;
+ int n;
+ int ch;
+ bool scrol = false, t12 = false, timer = false;
+ int hour, minute, second;
+
+ while ((ch = getopt(argc, argv, "cst")) != -1)
+ switch (ch) {
+ case 'c':
+ timer = true;
+ break;
+ case 's':
+ scrol = true;
+ break;
+ case 't':
+ t12 = true;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((argc > 1) || (argc == 0 && timer)) {
+ usage();
+ /* NOTREACHED */
+ }
+
+ if (argc > 0) {
+ n = atoi(*argv) + 1;
+ if (n < 1) {
+ warnx("number of seconds is out of range");
+ usage();
+ /* NOTREACHED */
+ }
+ } else
+ n = 0;
+
+ if (timer && n == 0)
+ return(0);
+
+ initscr();
+
+ signal(SIGINT,sighndl);
+ signal(SIGTERM,sighndl);
+ signal(SIGHUP,sighndl);
+
+ cbreak();
+ noecho();
+ curs_set(0);
+
+ hascolor = has_colors();
+
+ if (hascolor) {
+ start_color();
+ init_pair(1, COLOR_BLACK, COLOR_RED);
+ init_pair(2, COLOR_RED, COLOR_BLACK);
+ init_pair(3, COLOR_WHITE, COLOR_BLACK);
+ attrset(COLOR_PAIR(2));
+ }
+
+ clear();
+ refresh();
+
+ if (hascolor) {
+ attrset(COLOR_PAIR(3));
+
+ mvaddch(YBASE - 2, XBASE - 3, ACS_ULCORNER);
+ hline(ACS_HLINE, XLENGTH);
+ mvaddch(YBASE - 2, XBASE - 2 + XLENGTH, ACS_URCORNER);
+
+ mvaddch(YBASE + YDEPTH - 1, XBASE - 3, ACS_LLCORNER);
+ hline(ACS_HLINE, XLENGTH);
+ mvaddch(YBASE + YDEPTH - 1, XBASE - 2 + XLENGTH, ACS_LRCORNER);
+
+ move(YBASE - 1, XBASE - 3);
+ vline(ACS_VLINE, YDEPTH);
+
+ move(YBASE - 1, XBASE - 2 + XLENGTH);
+ vline(ACS_VLINE, YDEPTH);
+
+ attrset(COLOR_PAIR(2));
+ }
+ clock_gettime(CLOCK_REALTIME_FAST, &now);
+ prev_sec = now.tv_sec;
+ if (timer) {
+ end = now;
+ end.tv_sec += n;
+ }
+ do {
+ mask = 0;
+ if (!timer) {
+ tm = localtime(&now.tv_sec);
+ if (t12) {
+ if (tm->tm_hour < 12) {
+ if (tm->tm_hour == 0)
+ tm->tm_hour = 12;
+ mvaddstr(YBASE + 5, XBASE + 52, "AM");
+ } else {
+ if (tm->tm_hour > 12)
+ tm->tm_hour -= 12;
+ mvaddstr(YBASE + 5, XBASE + 52, "PM");
+ }
+ }
+ hour = tm->tm_hour;
+ minute = tm->tm_min;
+ second = tm->tm_sec;
+ } else {
+ n = end.tv_sec - now.tv_sec;
+ if (n <= 0)
+ break;
+ hour = (n / 3600) % 100;
+ minute = (n / 60) % 60;
+ second = n % 60;
+ }
+ set(second % 10, 0);
+ set(second / 10, 4);
+ set(minute % 10, 10);
+ set(minute / 10, 14);
+ set(hour % 10, 20);
+ set(hour / 10, 24);
+ set(10, 7);
+ set(10, 17);
+ for(k=0; k<6; k++) {
+ if(scrol) {
+ for(i=0; i<5; i++)
+ new[i] = (new[i]&~mask) | (new[i+1]&mask);
+ new[5] = (new[5]&~mask) | (next[k]&mask);
+ } else
+ new[k] = (new[k]&~mask) | (next[k]&mask);
+ next[k] = 0;
+ for(s=1; s>=0; s--) {
+ standt(s);
+ for(i=0; i<6; i++) {
+ if((a = (new[i]^old[i])&(s ? new : old)[i]) != 0) {
+ for(j=0,t=1<<26; t; t>>=1,j++) {
+ if(a&t) {
+ if(!(a&(t<<1))) {
+ movto(YBASE + i, XBASE + 2*j);
+ }
+ addstr(" ");
+ }
+ }
+ }
+ if(!s) {
+ old[i] = new[i];
+ }
+ }
+ if(!s) {
+ refresh();
+ }
+ }
+ }
+ movto(6, 0);
+ refresh();
+ clock_gettime(CLOCK_REALTIME_FAST, &now);
+ if (now.tv_sec == prev_sec) {
+ if (delay.tv_nsec > 0) {
+ delay.tv_sec = 0;
+ delay.tv_nsec = 1000000000 - now.tv_nsec;
+ } else {
+ delay.tv_sec = 1;
+ delay.tv_nsec = 0;
+ }
+ nanosleep(&delay, NULL);
+ clock_gettime(CLOCK_REALTIME_FAST, &now);
+ }
+ n -= now.tv_sec - prev_sec;
+ prev_sec = now.tv_sec;
+ if (sigtermed) {
+ standend();
+ clear();
+ refresh();
+ endwin();
+ errx(1, "terminated by signal %d", (int)sigtermed);
+ }
+ } while (n);
+ standend();
+ clear();
+ refresh();
+ endwin();
+ return(0);
+}
+
+static void
+set(int t, int n)
+{
+ int i, m;
+
+ m = 7<<n;
+ for(i=0; i<5; i++) {
+ next[i] |= ((disp[t]>>(4-i)*3)&07)<<n;
+ mask |= (next[i]^old[i])&m;
+ }
+ if(mask&m)
+ mask |= m;
+}
+
+static void
+standt(int on)
+{
+ if (on) {
+ if(hascolor) {
+ attron(COLOR_PAIR(1));
+ } else {
+ attron(A_STANDOUT);
+ }
+ } else {
+ if(hascolor) {
+ attron(COLOR_PAIR(2));
+ } else {
+ attroff(A_STANDOUT);
+ }
+ }
+}
+
+static void
+movto(int line, int col)
+{
+ move(line, col);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: grdc [-st] [n]\n"
+ " grdc -c n\n");
+ exit(1);
+}
diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile
new file mode 100644
index 000000000000..2204758ece5a
--- /dev/null
+++ b/usr.bin/grep/Makefile
@@ -0,0 +1,61 @@
+# $NetBSD: Makefile,v 1.4 2011/02/16 01:31:33 joerg Exp $
+# $OpenBSD: Makefile,v 1.6 2003/06/25 15:00:04 millert Exp $
+
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= grep
+MAN1= grep.1 zgrep.1
+
+SRCS= file.c grep.c queue.c util.c
+
+SCRIPTS= zgrep.sh
+LINKS= ${BINDIR}/zgrep ${BINDIR}/zfgrep \
+ ${BINDIR}/zgrep ${BINDIR}/zegrep \
+ ${BINDIR}/zgrep ${BINDIR}/bzgrep \
+ ${BINDIR}/zgrep ${BINDIR}/bzegrep \
+ ${BINDIR}/zgrep ${BINDIR}/bzfgrep \
+ ${BINDIR}/zgrep ${BINDIR}/lzgrep \
+ ${BINDIR}/zgrep ${BINDIR}/lzegrep \
+ ${BINDIR}/zgrep ${BINDIR}/lzfgrep \
+ ${BINDIR}/zgrep ${BINDIR}/xzgrep \
+ ${BINDIR}/zgrep ${BINDIR}/xzegrep \
+ ${BINDIR}/zgrep ${BINDIR}/xzfgrep \
+ ${BINDIR}/zgrep ${BINDIR}/zstdgrep \
+ ${BINDIR}/zgrep ${BINDIR}/zstdegrep \
+ ${BINDIR}/zgrep ${BINDIR}/zstdfgrep
+
+LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \
+ ${BINDIR}/grep ${BINDIR}/fgrep \
+ ${BINDIR}/grep ${BINDIR}/rgrep \
+
+MLINKS= zgrep.1 zfgrep.1 \
+ zgrep.1 zegrep.1 \
+ zgrep.1 bzgrep.1 \
+ zgrep.1 bzegrep.1 \
+ zgrep.1 bzfgrep.1 \
+ zgrep.1 lzgrep.1 \
+ zgrep.1 lzegrep.1 \
+ zgrep.1 lzfgrep.1 \
+ zgrep.1 xzgrep.1 \
+ zgrep.1 xzegrep.1 \
+ zgrep.1 xzfgrep.1 \
+ zgrep.1 zstdgrep.1 \
+ zgrep.1 zstdegrep.1 \
+ zgrep.1 zstdfgrep.1
+
+MLINKS+= grep.1 egrep.1 \
+ grep.1 fgrep.1 \
+ grep.1 rgrep.1
+
+CFLAGS.gcc+= --param max-inline-insns-single=500
+
+.if !defined(BOOTSTRAPPING)
+LIBADD+= regex
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/grep/Makefile.depend b/usr.bin/grep/Makefile.depend
new file mode 100644
index 000000000000..92fa8c2d80f7
--- /dev/null
+++ b/usr.bin/grep/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbz2 \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libregex \
+ lib/libz \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/grep/Makefile.depend.options b/usr.bin/grep/Makefile.depend.options
new file mode 100644
index 000000000000..b62a74f3895c
--- /dev/null
+++ b/usr.bin/grep/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= GNU_GREP_COMPAT
+
+DIRDEPS.GNU_GREP_COMPAT.yes= gnu/lib/libregex
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/grep/file.c b/usr.bin/grep/file.c
new file mode 100644
index 000000000000..0b8240504ce6
--- /dev/null
+++ b/usr.bin/grep/file.c
@@ -0,0 +1,248 @@
+/* $NetBSD: file.c,v 1.5 2011/02/16 18:35:39 joerg Exp $ */
+/* $OpenBSD: file.c,v 1.11 2010/07/02 20:48:48 nicm Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
+ * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2010 Dimitry Andric <dimitry@andric.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "grep.h"
+
+#define MAXBUFSIZ (32 * 1024)
+#define LNBUFBUMP 80
+
+static char *buffer;
+static char *bufpos;
+static size_t bufrem;
+static size_t fsiz;
+
+static char *lnbuf;
+static size_t lnbuflen;
+
+static inline int
+grep_refill(struct file *f)
+{
+ ssize_t nr;
+
+ if (filebehave == FILE_MMAP)
+ return (0);
+
+ bufpos = buffer;
+ bufrem = 0;
+
+ nr = read(f->fd, buffer, MAXBUFSIZ);
+ if (nr < 0 && errno == EISDIR)
+ nr = 0;
+ if (nr < 0)
+ return (-1);
+
+ bufrem = nr;
+ return (0);
+}
+
+static inline int
+grep_lnbufgrow(size_t newlen)
+{
+
+ if (lnbuflen < newlen) {
+ lnbuf = grep_realloc(lnbuf, newlen);
+ lnbuflen = newlen;
+ }
+
+ return (0);
+}
+
+char *
+grep_fgetln(struct file *f, struct parsec *pc)
+{
+ char *p;
+ size_t len;
+ size_t off;
+ ptrdiff_t diff;
+
+ /* Fill the buffer, if necessary */
+ if (bufrem == 0 && grep_refill(f) != 0)
+ goto error;
+
+ if (bufrem == 0) {
+ /* Return zero length to indicate EOF */
+ pc->ln.len= 0;
+ return (bufpos);
+ }
+
+ /* Look for a newline in the remaining part of the buffer */
+ if ((p = memchr(bufpos, fileeol, bufrem)) != NULL) {
+ ++p; /* advance over newline */
+ len = p - bufpos;
+ if (grep_lnbufgrow(len + 1))
+ goto error;
+ memcpy(lnbuf, bufpos, len);
+ bufrem -= len;
+ bufpos = p;
+ pc->ln.len = len;
+ lnbuf[len] = '\0';
+ return (lnbuf);
+ }
+
+ /* We have to copy the current buffered data to the line buffer */
+ for (len = bufrem, off = 0; ; len += bufrem) {
+ /* Make sure there is room for more data */
+ if (grep_lnbufgrow(len + LNBUFBUMP))
+ goto error;
+ memcpy(lnbuf + off, bufpos, len - off);
+ /* With FILE_MMAP, this is EOF; there's no more to refill */
+ if (filebehave == FILE_MMAP) {
+ bufrem -= len;
+ break;
+ }
+ off = len;
+ /* Fetch more to try and find EOL/EOF */
+ if (grep_refill(f) != 0)
+ goto error;
+ if (bufrem == 0)
+ /* EOF: return partial line */
+ break;
+ if ((p = memchr(bufpos, fileeol, bufrem)) == NULL)
+ continue;
+ /* got it: finish up the line (like code above) */
+ ++p;
+ diff = p - bufpos;
+ len += diff;
+ if (grep_lnbufgrow(len + 1))
+ goto error;
+ memcpy(lnbuf + off, bufpos, diff);
+ bufrem -= diff;
+ bufpos = p;
+ break;
+ }
+ pc->ln.len = len;
+ lnbuf[len] = '\0';
+ return (lnbuf);
+
+error:
+ pc->ln.len = 0;
+ return (NULL);
+}
+
+/*
+ * Opens a file for processing.
+ */
+struct file *
+grep_open(const char *path)
+{
+ struct file *f;
+
+ f = grep_malloc(sizeof *f);
+ memset(f, 0, sizeof *f);
+ if (path == NULL) {
+ /* Processing stdin implies --line-buffered. */
+ lbflag = true;
+ f->fd = STDIN_FILENO;
+ } else if ((f->fd = open(path, O_RDONLY)) == -1)
+ goto error1;
+
+ if (filebehave == FILE_MMAP) {
+ struct stat st;
+
+ if (fstat(f->fd, &st) == -1 || !S_ISREG(st.st_mode))
+ filebehave = FILE_STDIO;
+ else {
+ int flags = MAP_PRIVATE | MAP_NOCORE | MAP_NOSYNC;
+#ifdef MAP_PREFAULT_READ
+ flags |= MAP_PREFAULT_READ;
+#endif
+ fsiz = st.st_size;
+ buffer = mmap(NULL, fsiz, PROT_READ, flags,
+ f->fd, (off_t)0);
+ if (buffer == MAP_FAILED)
+ filebehave = FILE_STDIO;
+ else {
+ bufrem = st.st_size;
+ bufpos = buffer;
+ madvise(buffer, st.st_size, MADV_SEQUENTIAL);
+ }
+ }
+ }
+
+ if ((buffer == NULL) || (buffer == MAP_FAILED))
+ buffer = grep_malloc(MAXBUFSIZ);
+
+ /* Fill read buffer, also catches errors early */
+ if (bufrem == 0 && grep_refill(f) != 0)
+ goto error2;
+
+ /* Check for binary stuff, if necessary */
+ if (binbehave != BINFILE_TEXT && fileeol != '\0' &&
+ memchr(bufpos, '\0', bufrem) != NULL)
+ f->binary = true;
+
+ return (f);
+
+error2:
+ close(f->fd);
+error1:
+ free(f);
+ return (NULL);
+}
+
+/*
+ * Closes a file.
+ */
+void
+grep_close(struct file *f)
+{
+
+ close(f->fd);
+
+ /* Reset read buffer and line buffer */
+ if (filebehave == FILE_MMAP) {
+ munmap(buffer, fsiz);
+ buffer = NULL;
+ }
+ bufpos = buffer;
+ bufrem = 0;
+
+ free(lnbuf);
+ lnbuf = NULL;
+ lnbuflen = 0;
+}
diff --git a/usr.bin/grep/grep.1 b/usr.bin/grep/grep.1
new file mode 100644
index 000000000000..9b50565ec605
--- /dev/null
+++ b/usr.bin/grep/grep.1
@@ -0,0 +1,592 @@
+.\" $NetBSD: grep.1,v 1.2 2011/02/16 01:31:33 joerg Exp $
+.\" $OpenBSD: grep.1,v 1.38 2010/04/05 06:30:59 jmc Exp $
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd December 18, 2022
+.Dt GREP 1
+.Os
+.Sh NAME
+.Nm grep ,
+.Nm egrep ,
+.Nm fgrep ,
+.Nm rgrep
+.Nd file pattern searcher
+.Sh SYNOPSIS
+.Nm grep
+.Bk -words
+.Op Fl abcdDEFGHhIiLlmnOopqRSsUVvwxz
+.Op Fl A Ar num
+.Op Fl B Ar num
+.Op Fl C Ar num
+.Op Fl e Ar pattern
+.Op Fl f Ar file
+.Op Fl Fl binary-files= Ns Ar value
+.Op Fl Fl color Ns Op Cm = Ns Ar when
+.Op Fl Fl colour Ns Op Cm = Ns Ar when
+.Op Fl Fl context= Ns Ar num
+.Op Fl Fl label
+.Op Fl Fl line-buffered
+.Op Fl Fl null
+.Op Ar pattern
+.Op Ar
+.Ek
+.Sh DESCRIPTION
+The
+.Nm grep
+utility searches any given input files,
+selecting lines that match one or more patterns.
+By default, a pattern matches an input line if the regular expression
+(RE) in the pattern matches the input line
+without its trailing newline.
+An empty expression matches every line.
+Each input line that matches at least one of the patterns is written
+to the standard output.
+.Pp
+.Nm grep
+is used for simple patterns and
+basic regular expressions
+.Pq BREs ;
+.Nm egrep
+can handle extended regular expressions
+.Pq EREs .
+See
+.Xr re_format 7
+for more information on regular expressions.
+.Nm fgrep
+is quicker than both
+.Nm grep
+and
+.Nm egrep ,
+but can only handle fixed patterns
+(i.e., it does not interpret regular expressions).
+Patterns may consist of one or more lines,
+allowing any of the pattern lines to match a portion of the input.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl A Ar num , Fl Fl after-context= Ns Ar num
+Print
+.Ar num
+lines of trailing context after each match.
+See also the
+.Fl B
+and
+.Fl C
+options.
+.It Fl a , Fl Fl text
+Treat all files as ASCII text.
+Normally
+.Nm
+will simply print
+.Dq Binary file ... matches
+if files contain binary characters.
+Use of this option forces
+.Nm
+to output lines matching the specified pattern.
+.It Fl B Ar num , Fl Fl before-context= Ns Ar num
+Print
+.Ar num
+lines of leading context before each match.
+See also the
+.Fl A
+and
+.Fl C
+options.
+.It Fl b , Fl Fl byte-offset
+The offset in bytes of a matched pattern is
+displayed in front of the respective matched line.
+.It Fl C Ar num , Fl Fl context= Ns Ar num
+Print
+.Ar num
+lines of leading and trailing context surrounding each match.
+See also the
+.Fl A
+and
+.Fl B
+options.
+.It Fl c , Fl Fl count
+Only a count of selected lines is written to standard output.
+.It Fl Fl colour= Ns Oo Ar when Oc , Fl Fl color= Ns Oo Ar when Oc
+Mark up the matching text with the expression stored in the
+.Ev GREP_COLOR
+environment variable.
+The possible values of
+.Ar when
+are
+.Dq Cm never ,
+.Dq Cm always
+and
+.Dq Cm auto .
+.It Fl D Ar action , Fl Fl devices= Ns Ar action
+Specify the demanded
+.Ar action
+for devices, FIFOs and sockets.
+The default
+.Ar action
+is
+.Dq Cm read ,
+which means, that they are read as if they were normal files.
+If the
+.Ar action
+is set to
+.Dq Cm skip ,
+devices are silently skipped.
+.It Fl d Ar action , Fl Fl directories= Ns Ar action
+Specify the demanded
+.Ar action
+for directories.
+It is
+.Dq Cm read
+by default, which means that the directories
+are read in the same manner as normal files.
+Other possible values are
+.Dq Cm skip
+to silently ignore the directories, and
+.Dq Cm recurse
+to read them recursively, which has the same effect as the
+.Fl R
+and
+.Fl r
+option.
+.It Fl E , Fl Fl extended-regexp
+Interpret
+.Ar pattern
+as an extended regular expression
+(i.e., force
+.Nm grep
+to behave as
+.Nm egrep ) .
+.It Fl e Ar pattern , Fl Fl regexp= Ns Ar pattern
+Specify a
+.Ar pattern
+used during the search of the input:
+an input line is selected if it matches any of the specified patterns.
+This option is most useful when multiple
+.Fl e
+options are used to specify multiple patterns,
+or when a
+.Ar pattern
+begins with a dash
+.Pq Sq - .
+.It Fl Fl exclude Ar pattern
+If specified, it excludes files matching the given
+filename
+.Ar pattern
+from the search.
+Note that
+.Fl Fl exclude
+and
+.Fl Fl include
+patterns are processed in the order given.
+If a name matches multiple patterns, the latest matching rule wins.
+If no
+.Fl Fl include
+pattern is specified, all files are searched that are
+not excluded.
+Patterns are matched to the full path specified,
+not only to the filename component.
+.It Fl Fl exclude-dir Ar pattern
+If
+.Fl R
+is specified, it excludes directories matching the
+given filename
+.Ar pattern
+from the search.
+Note that
+.Fl Fl exclude-dir
+and
+.Fl Fl include-dir
+patterns are processed in the order given.
+If a name matches multiple patterns, the latest matching rule wins.
+If no
+.Fl Fl include-dir
+pattern is specified, all directories are searched that are
+not excluded.
+.It Fl F , Fl Fl fixed-strings
+Interpret
+.Ar pattern
+as a set of fixed strings
+(i.e., force
+.Nm grep
+to behave as
+.Nm fgrep ) .
+.It Fl f Ar file , Fl Fl file= Ns Ar file
+Read one or more newline separated patterns from
+.Ar file .
+Empty pattern lines match every input line.
+Newlines are not considered part of a pattern.
+If
+.Ar file
+is empty, nothing is matched.
+.It Fl G , Fl Fl basic-regexp
+Interpret
+.Ar pattern
+as a basic regular expression
+(i.e., force
+.Nm grep
+to behave as traditional
+.Nm grep ) .
+.It Fl H
+Always print filename headers with output lines.
+.It Fl h , Fl Fl no-filename
+Never print filename headers
+.Pq i.e., filenames
+with output lines.
+.It Fl Fl help
+Print a brief help message.
+.It Fl I
+Ignore binary files.
+This option is equivalent to the
+.Dq Fl Fl binary-files= Ns Cm without-match
+option.
+.It Fl i , Fl Fl ignore-case
+Perform case insensitive matching.
+By default,
+.Nm grep
+is case sensitive.
+.It Fl Fl include Ar pattern
+If specified, only files matching the given filename
+.Ar pattern
+are searched.
+Note that
+.Fl Fl include
+and
+.Fl Fl exclude
+patterns are processed in the order given.
+If a name matches multiple patterns, the latest matching rule wins.
+Patterns are matched to the full path specified,
+not only to the filename component.
+.It Fl Fl include-dir Ar pattern
+If
+.Fl R
+is specified, only directories matching the given filename
+.Ar pattern
+are searched.
+Note that
+.Fl Fl include-dir
+and
+.Fl Fl exclude-dir
+patterns are processed in the order given.
+If a name matches multiple patterns, the latest matching rule wins.
+.It Fl L , Fl Fl files-without-match
+Only the names of files not containing selected lines are written to
+standard output.
+Pathnames are listed once per file searched.
+If the standard input is searched, the string
+.Dq (standard input)
+is written unless a
+.Fl Fl label
+is specified.
+.It Fl l , Fl Fl files-with-matches
+Only the names of files containing selected lines are written to
+standard output.
+.Nm grep
+will only search a file until a match has been found,
+making searches potentially less expensive.
+Pathnames are listed once per file searched.
+If the standard input is searched, the string
+.Dq (standard input)
+is written unless a
+.Fl Fl label
+is specified.
+.It Fl Fl label
+Label to use in place of
+.Dq (standard input)
+for a file name where a file name would normally be printed.
+This option applies to
+.Fl H ,
+.Fl L ,
+and
+.Fl l .
+.It Fl Fl mmap
+Use
+.Xr mmap 2
+instead of
+.Xr read 2
+to read input, which can result in better performance under some
+circumstances but can cause undefined behaviour.
+.It Fl m Ar num , Fl Fl max-count= Ns Ar num
+Stop reading the file after
+.Ar num
+matches.
+.It Fl n , Fl Fl line-number
+Each output line is preceded by its relative line number in the file,
+starting at line 1.
+The line number counter is reset for each file processed.
+This option is ignored if
+.Fl c ,
+.Fl L ,
+.Fl l ,
+or
+.Fl q
+is
+specified.
+.It Fl Fl null
+Prints a zero-byte after the file name.
+.It Fl O
+If
+.Fl R
+is specified, follow symbolic links only if they were explicitly listed
+on the command line.
+The default is not to follow symbolic links.
+.It Fl o , Fl Fl only-matching
+Prints only the matching part of the lines.
+.It Fl p
+If
+.Fl R
+is specified, no symbolic links are followed.
+This is the default.
+.It Fl q , Fl Fl quiet , Fl Fl silent
+Quiet mode:
+suppress normal output.
+.Nm grep
+will only search a file until a match has been found,
+making searches potentially less expensive.
+.It Fl R , Fl r , Fl Fl recursive
+Recursively search subdirectories listed.
+(i.e., force
+.Nm grep
+to behave as
+.Nm rgrep ) .
+.It Fl S
+If
+.Fl R
+is specified, all symbolic links are followed.
+The default is not to follow symbolic links.
+.It Fl s , Fl Fl no-messages
+Silent mode.
+Nonexistent and unreadable files are ignored
+(i.e., their error messages are suppressed).
+.It Fl U , Fl Fl binary
+Search binary files, but do not attempt to print them.
+.It Fl u
+This option has no effect and is provided only for compatibility with GNU grep.
+.It Fl V , Fl Fl version
+Display version information and exit.
+.It Fl v , Fl Fl invert-match
+Selected lines are those
+.Em not
+matching any of the specified patterns.
+.It Fl w , Fl Fl word-regexp
+The expression is searched for as a word (as if surrounded by
+.Sq [[:<:]]
+and
+.Sq [[:>:]] ;
+see
+.Xr re_format 7 ) .
+This option has no effect if
+.Fl x
+is also specified.
+.It Fl x , Fl Fl line-regexp
+Only input lines selected against an entire fixed string or regular
+expression are considered to be matching lines.
+.It Fl y
+Equivalent to
+.Fl i .
+Obsoleted.
+.It Fl z , Fl Fl null-data
+Treat input and output data as sequences of lines terminated by a
+zero-byte instead of a newline.
+.It Fl Fl binary-files= Ns Ar value
+Controls searching and printing of binary files.
+Options are:
+.Bl -tag -compact -width "binary (default)"
+.It Cm binary No (default)
+Search binary files but do not print them.
+.It Cm without-match
+Do not search binary files.
+.It Cm text
+Treat all files as text.
+.El
+.It Fl Fl line-buffered
+Force output to be line buffered.
+By default, output is line buffered when standard output is a terminal
+and block buffered otherwise.
+.El
+.Pp
+If no file arguments are specified, the standard input is used.
+Additionally,
+.Dq Cm -
+may be used in place of a file name, anywhere that a file name is accepted, to
+read from standard input.
+This includes both
+.Fl f
+and file arguments.
+.Sh ENVIRONMENT
+The following environment variables affect the execution of
+.Nm :
+.Bl -tag -width "GREP_OPTIONS"
+.It Ev GREP_COLOR
+This variable specifies the color used to highlight matched (non-empty) text.
+.It Ev GREP_OPTIONS
+This variable specifies default options
+to be placed in front of any explicit options.
+It may cause problems with portable scripts.
+.It Ev TERM
+This variable specifies the type name of the terminal, console or display-device
+type to be used.
+See
+.Xr term 7 .
+.El
+.Sh EXIT STATUS
+The
+.Nm grep
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width flag -compact
+.It Li 0
+One or more lines were selected.
+.It Li 1
+No lines were selected.
+.It Li \*(Gt1
+An error occurred.
+.El
+.Sh EXAMPLES
+.Bl -dash
+.It
+Find all occurrences of the pattern
+.Sq patricia
+in a file:
+.Pp
+.Dl $ grep 'patricia' myfile
+.It
+Same as above but looking only for complete words:
+.Pp
+.Dl $ grep -w 'patricia' myfile
+.It
+Count occurrences of the exact pattern
+.Sq FOO
+:
+.Pp
+.Dl $ grep -c FOO myfile
+.It
+Same as above but ignoring case:
+.Pp
+.Dl $ grep -c -i FOO myfile
+.It
+Find all occurrences of the pattern
+.Ql .Pp
+at the beginning of a line:
+.Pp
+.Dl $ grep '^\e.Pp' myfile
+.Pp
+The apostrophes ensure the entire expression is evaluated by
+.Nm grep
+instead of by the user's shell.
+The caret
+.Ql ^
+matches the null string at the beginning of a line,
+and the
+.Ql \e
+escapes the
+.Ql \&. ,
+which would otherwise match any character.
+.It
+Find all lines in a file which do not contain the words
+.Sq foo
+or
+.Sq bar :
+.Pp
+.Dl $ grep -v -e 'foo' -e 'bar' myfile
+.It
+Peruse the file
+.Sq calendar
+looking for either 19, 20, or 25 using extended regular expressions:
+.Pp
+.Dl $ egrep '19|20|25' calendar
+.It
+Show matching lines and the name of the
+.Sq *.h
+files which contain the pattern
+.Sq FIXME .
+Do the search recursively from the
+.Pa /usr/src/sys/arm
+directory
+.Pp
+.Dl $ grep -H -R FIXME --include="*.h" /usr/src/sys/arm/
+.It
+Same as above but show only the name of the matching file:
+.Pp
+.Dl $ grep -l -R FIXME --include="*.h" /usr/src/sys/arm/
+.It
+Show lines containing the text
+.Sq foo .
+The matching part of the output is colored and every line is prefixed with
+the line number and the offset in the file for those lines that matched.
+.Pp
+.Dl $ grep -b --colour -n foo myfile
+.It
+Show lines that match the extended regular expression patterns read from the
+standard input:
+.Pp
+.Dl $ echo -e 'Free\enBSD\enAll.*reserved' | grep -E -f - myfile
+.It
+Show lines from the output of the
+.Xr pciconf 8
+command matching the specified extended regular expression along with
+three lines of leading context and one line of trailing context:
+.Pp
+.Dl $ pciconf -lv | grep -B3 -A1 -E 'class.*=.*storage'
+.It
+Suppress any output and use the exit status to show an appropriate message:
+.Pp
+.Dl $ grep -q foo myfile && echo File matches
+.El
+.Sh SEE ALSO
+.Xr ed 1 ,
+.Xr ex 1 ,
+.Xr sed 1 ,
+.Xr zgrep 1 ,
+.Xr re_format 7
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl AaBbCDdGHhILmopRSUVw
+are extensions to that specification, and the behaviour of the
+.Fl f
+flag when used with an empty pattern file is left undefined.
+.Pp
+All long options are provided for compatibility with
+GNU versions of this utility.
+.Pp
+Historic versions of the
+.Nm grep
+utility also supported the flags
+.Op Fl ruy .
+This implementation supports those options;
+however, their use is strongly discouraged.
+.Sh HISTORY
+The
+.Nm grep
+command first appeared in
+.At v6 .
diff --git a/usr.bin/grep/grep.c b/usr.bin/grep/grep.c
new file mode 100644
index 000000000000..feaf17d7c1e1
--- /dev/null
+++ b/usr.bin/grep/grep.c
@@ -0,0 +1,724 @@
+/* $NetBSD: grep.c,v 1.6 2011/04/18 03:48:23 joerg Exp $ */
+/* $OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
+ * Copyright (C) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <libgen.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "grep.h"
+
+const char *errstr[] = {
+ "",
+/* 1*/ "(standard input)",
+/* 2*/ "unknown %s option",
+/* 3*/ "usage: %s [-abcDEFGHhIiLlmnOopqRSsUVvwxz] [-A num] [-B num] [-C num]\n",
+/* 4*/ "\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
+/* 5*/ "\t[--context=num] [--directories=action] [--label] [--line-buffered]\n",
+/* 6*/ "\t[--null] [pattern] [file ...]\n",
+/* 7*/ "Binary file %s matches\n",
+/* 8*/ "%s (BSD grep, GNU compatible) %s\n",
+};
+
+/* Flags passed to regcomp() and regexec() */
+int cflags = REG_NOSUB | REG_NEWLINE;
+int eflags = REG_STARTEND;
+
+bool matchall;
+
+/* Searching patterns */
+unsigned int patterns;
+static unsigned int pattern_sz;
+struct pat *pattern;
+regex_t *r_pattern;
+
+/* Filename exclusion/inclusion patterns */
+unsigned int fpatterns, dpatterns;
+static unsigned int fpattern_sz, dpattern_sz;
+struct epat *dpattern, *fpattern;
+
+/* For regex errors */
+char re_error[RE_ERROR_BUF + 1];
+
+/* Command-line flags */
+long long Aflag; /* -A x: print x lines trailing each match */
+long long Bflag; /* -B x: print x lines leading each match */
+bool Hflag; /* -H: always print file name */
+bool Lflag; /* -L: only show names of files with no matches */
+bool bflag; /* -b: show block numbers for each match */
+bool cflag; /* -c: only show a count of matching lines */
+bool hflag; /* -h: don't print filename headers */
+bool iflag; /* -i: ignore case */
+bool lflag; /* -l: only show names of files with matches */
+bool mflag; /* -m x: stop reading the files after x matches */
+long long mcount; /* count for -m */
+long long mlimit; /* requested value for -m */
+char fileeol; /* indicator for eol */
+bool nflag; /* -n: show line numbers in front of matching lines */
+bool oflag; /* -o: print only matching part */
+bool qflag; /* -q: quiet mode (don't output anything) */
+bool sflag; /* -s: silent mode (ignore errors) */
+bool vflag; /* -v: only show non-matching lines */
+bool wflag; /* -w: pattern must start and end on word boundaries */
+bool xflag; /* -x: pattern must match entire line */
+bool lbflag; /* --line-buffered */
+bool nullflag; /* --null */
+char *label; /* --label */
+const char *color; /* --color */
+int grepbehave = GREP_BASIC; /* -EFG: type of the regex */
+int binbehave = BINFILE_BIN; /* -aIU: handling of binary files */
+int filebehave = FILE_STDIO;
+int devbehave = DEV_READ; /* -D: handling of devices */
+int dirbehave = DIR_READ; /* -dRr: handling of directories */
+int linkbehave = LINK_SKIP; /* -OpS: handling of symlinks */
+
+bool dexclude, dinclude; /* --exclude-dir and --include-dir */
+bool fexclude, finclude; /* --exclude and --include */
+
+enum {
+ BIN_OPT = CHAR_MAX + 1,
+ COLOR_OPT,
+ HELP_OPT,
+ MMAP_OPT,
+ LINEBUF_OPT,
+ LABEL_OPT,
+ NULL_OPT,
+ R_EXCLUDE_OPT,
+ R_INCLUDE_OPT,
+ R_DEXCLUDE_OPT,
+ R_DINCLUDE_OPT
+};
+
+static inline const char *init_color(const char *);
+
+/* Housekeeping */
+bool file_err; /* file reading error */
+
+/*
+ * Prints usage information and returns 2.
+ */
+static void
+usage(void)
+{
+ fprintf(stderr, errstr[3], getprogname());
+ fprintf(stderr, "%s", errstr[4]);
+ fprintf(stderr, "%s", errstr[5]);
+ fprintf(stderr, "%s", errstr[6]);
+ exit(2);
+}
+
+static const char *optstr = "0123456789A:B:C:D:EFGHILOSRUVabcd:e:f:hilm:nopqrsuvwxyz";
+
+static const struct option long_options[] =
+{
+ {"binary-files", required_argument, NULL, BIN_OPT},
+ {"help", no_argument, NULL, HELP_OPT},
+ {"mmap", no_argument, NULL, MMAP_OPT},
+ {"line-buffered", no_argument, NULL, LINEBUF_OPT},
+ {"label", required_argument, NULL, LABEL_OPT},
+ {"null", no_argument, NULL, NULL_OPT},
+ {"color", optional_argument, NULL, COLOR_OPT},
+ {"colour", optional_argument, NULL, COLOR_OPT},
+ {"exclude", required_argument, NULL, R_EXCLUDE_OPT},
+ {"include", required_argument, NULL, R_INCLUDE_OPT},
+ {"exclude-dir", required_argument, NULL, R_DEXCLUDE_OPT},
+ {"include-dir", required_argument, NULL, R_DINCLUDE_OPT},
+ {"after-context", required_argument, NULL, 'A'},
+ {"text", no_argument, NULL, 'a'},
+ {"before-context", required_argument, NULL, 'B'},
+ {"byte-offset", no_argument, NULL, 'b'},
+ {"context", optional_argument, NULL, 'C'},
+ {"count", no_argument, NULL, 'c'},
+ {"devices", required_argument, NULL, 'D'},
+ {"directories", required_argument, NULL, 'd'},
+ {"extended-regexp", no_argument, NULL, 'E'},
+ {"regexp", required_argument, NULL, 'e'},
+ {"fixed-strings", no_argument, NULL, 'F'},
+ {"file", required_argument, NULL, 'f'},
+ {"basic-regexp", no_argument, NULL, 'G'},
+ {"no-filename", no_argument, NULL, 'h'},
+ {"with-filename", no_argument, NULL, 'H'},
+ {"ignore-case", no_argument, NULL, 'i'},
+ {"files-with-matches", no_argument, NULL, 'l'},
+ {"files-without-match", no_argument, NULL, 'L'},
+ {"max-count", required_argument, NULL, 'm'},
+ {"line-number", no_argument, NULL, 'n'},
+ {"only-matching", no_argument, NULL, 'o'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"silent", no_argument, NULL, 'q'},
+ {"recursive", no_argument, NULL, 'r'},
+ {"no-messages", no_argument, NULL, 's'},
+ {"binary", no_argument, NULL, 'U'},
+ {"unix-byte-offsets", no_argument, NULL, 'u'},
+ {"invert-match", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'},
+ {"word-regexp", no_argument, NULL, 'w'},
+ {"line-regexp", no_argument, NULL, 'x'},
+ {"null-data", no_argument, NULL, 'z'},
+ {NULL, no_argument, NULL, 0}
+};
+
+/*
+ * Adds a searching pattern to the internal array.
+ */
+static void
+add_pattern(char *pat, size_t len)
+{
+
+ /* Check if we can do a shortcut */
+ if (len == 0) {
+ matchall = true;
+ return;
+ }
+ /* Increase size if necessary */
+ if (patterns == pattern_sz) {
+ pattern_sz *= 2;
+ pattern = grep_realloc(pattern, ++pattern_sz *
+ sizeof(struct pat));
+ }
+ if (len > 0 && pat[len - 1] == '\n')
+ --len;
+ /* pat may not be NUL-terminated */
+ pattern[patterns].pat = grep_malloc(len + 1);
+ memcpy(pattern[patterns].pat, pat, len);
+ pattern[patterns].len = len;
+ pattern[patterns].pat[len] = '\0';
+ ++patterns;
+}
+
+/*
+ * Adds a file include/exclude pattern to the internal array.
+ */
+static void
+add_fpattern(const char *pat, int mode)
+{
+
+ /* Increase size if necessary */
+ if (fpatterns == fpattern_sz) {
+ fpattern_sz *= 2;
+ fpattern = grep_realloc(fpattern, ++fpattern_sz *
+ sizeof(struct epat));
+ }
+ fpattern[fpatterns].pat = grep_strdup(pat);
+ fpattern[fpatterns].mode = mode;
+ ++fpatterns;
+}
+
+/*
+ * Adds a directory include/exclude pattern to the internal array.
+ */
+static void
+add_dpattern(const char *pat, int mode)
+{
+
+ /* Increase size if necessary */
+ if (dpatterns == dpattern_sz) {
+ dpattern_sz *= 2;
+ dpattern = grep_realloc(dpattern, ++dpattern_sz *
+ sizeof(struct epat));
+ }
+ dpattern[dpatterns].pat = grep_strdup(pat);
+ dpattern[dpatterns].mode = mode;
+ ++dpatterns;
+}
+
+/*
+ * Reads searching patterns from a file and adds them with add_pattern().
+ */
+static void
+read_patterns(const char *fn)
+{
+ struct stat st;
+ FILE *f;
+ char *line;
+ size_t len;
+ ssize_t rlen;
+
+ if (strcmp(fn, "-") == 0)
+ f = stdin;
+ else if ((f = fopen(fn, "r")) == NULL)
+ err(2, "%s", fn);
+ if ((fstat(fileno(f), &st) == -1) || (S_ISDIR(st.st_mode))) {
+ fclose(f);
+ return;
+ }
+ len = 0;
+ line = NULL;
+ while ((rlen = getline(&line, &len, f)) != -1) {
+ if (line[0] == '\0')
+ continue;
+ add_pattern(line, line[0] == '\n' ? 0 : (size_t)rlen);
+ }
+
+ free(line);
+ if (ferror(f))
+ err(2, "%s", fn);
+ if (strcmp(fn, "-") != 0)
+ fclose(f);
+}
+
+static inline const char *
+init_color(const char *d)
+{
+ char *c;
+
+ c = getenv("GREP_COLOR");
+ return (c != NULL && c[0] != '\0' ? c : d);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char **aargv, **eargv, *eopts;
+ char *ep;
+ const char *pn;
+ long long l;
+ unsigned int aargc, eargc, i;
+ int c, lastc, needpattern, newarg, prevoptind;
+ bool matched;
+
+ setlocale(LC_ALL, "");
+
+ /*
+ * Check how we've bene invoked to determine the behavior we should
+ * exhibit. In this way we can have all the functionalities in one
+ * binary without the need of scripting and using ugly hacks.
+ */
+ pn = getprogname();
+ switch (pn[0]) {
+ case 'e':
+ grepbehave = GREP_EXTENDED;
+ break;
+ case 'f':
+ grepbehave = GREP_FIXED;
+ break;
+ case 'r':
+ dirbehave = DIR_RECURSE;
+ Hflag = true;
+ break;
+ }
+
+ lastc = '\0';
+ newarg = 1;
+ prevoptind = 1;
+ needpattern = 1;
+ fileeol = '\n';
+
+ eopts = getenv("GREP_OPTIONS");
+
+ /* support for extra arguments in GREP_OPTIONS */
+ eargc = 0;
+ if (eopts != NULL && eopts[0] != '\0') {
+ char *str;
+
+ /* make an estimation of how many extra arguments we have */
+ for (unsigned int j = 0; j < strlen(eopts); j++)
+ if (eopts[j] == ' ')
+ eargc++;
+
+ eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
+
+ eargc = 0;
+ /* parse extra arguments */
+ while ((str = strsep(&eopts, " ")) != NULL)
+ if (str[0] != '\0')
+ eargv[eargc++] = grep_strdup(str);
+
+ aargv = (char **)grep_calloc(eargc + argc + 1,
+ sizeof(char *));
+
+ aargv[0] = argv[0];
+ for (i = 0; i < eargc; i++)
+ aargv[i + 1] = eargv[i];
+ for (int j = 1; j < argc; j++, i++)
+ aargv[i + 1] = argv[j];
+
+ aargc = eargc + argc;
+ } else {
+ aargv = argv;
+ aargc = argc;
+ }
+
+ while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
+ -1)) {
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (newarg || !isdigit(lastc))
+ Aflag = 0;
+ else if (Aflag > LLONG_MAX / 10 - 1) {
+ errno = ERANGE;
+ err(2, NULL);
+ }
+
+ Aflag = Bflag = (Aflag * 10) + (c - '0');
+ break;
+ case 'C':
+ if (optarg == NULL) {
+ Aflag = Bflag = 2;
+ break;
+ }
+ /* FALLTHROUGH */
+ case 'A':
+ /* FALLTHROUGH */
+ case 'B':
+ errno = 0;
+ l = strtoll(optarg, &ep, 10);
+ if (errno == ERANGE || errno == EINVAL)
+ err(2, NULL);
+ else if (ep[0] != '\0') {
+ errno = EINVAL;
+ err(2, NULL);
+ } else if (l < 0) {
+ errno = EINVAL;
+ err(2, "context argument must be non-negative");
+ }
+
+ if (c == 'A')
+ Aflag = l;
+ else if (c == 'B')
+ Bflag = l;
+ else
+ Aflag = Bflag = l;
+ break;
+ case 'a':
+ binbehave = BINFILE_TEXT;
+ break;
+ case 'b':
+ bflag = true;
+ break;
+ case 'c':
+ cflag = true;
+ break;
+ case 'D':
+ if (strcasecmp(optarg, "skip") == 0)
+ devbehave = DEV_SKIP;
+ else if (strcasecmp(optarg, "read") == 0)
+ devbehave = DEV_READ;
+ else
+ errx(2, errstr[2], "--devices");
+ break;
+ case 'd':
+ if (strcasecmp("recurse", optarg) == 0) {
+ Hflag = true;
+ dirbehave = DIR_RECURSE;
+ } else if (strcasecmp("skip", optarg) == 0)
+ dirbehave = DIR_SKIP;
+ else if (strcasecmp("read", optarg) == 0)
+ dirbehave = DIR_READ;
+ else
+ errx(2, errstr[2], "--directories");
+ break;
+ case 'E':
+ grepbehave = GREP_EXTENDED;
+ break;
+ case 'e':
+ {
+ char *token;
+ char *string = optarg;
+
+ while ((token = strsep(&string, "\n")) != NULL)
+ add_pattern(token, strlen(token));
+ }
+ needpattern = 0;
+ break;
+ case 'F':
+ grepbehave = GREP_FIXED;
+ break;
+ case 'f':
+ read_patterns(optarg);
+ needpattern = 0;
+ break;
+ case 'G':
+ grepbehave = GREP_BASIC;
+ break;
+ case 'H':
+ Hflag = true;
+ break;
+ case 'h':
+ Hflag = false;
+ hflag = true;
+ break;
+ case 'I':
+ binbehave = BINFILE_SKIP;
+ break;
+ case 'i':
+ case 'y':
+ iflag = true;
+ cflags |= REG_ICASE;
+ break;
+ case 'L':
+ lflag = false;
+ Lflag = true;
+ break;
+ case 'l':
+ Lflag = false;
+ lflag = true;
+ break;
+ case 'm':
+ mflag = true;
+ errno = 0;
+ mlimit = mcount = strtoll(optarg, &ep, 10);
+ if (((errno == ERANGE) && (mcount == LLONG_MAX)) ||
+ ((errno == EINVAL) && (mcount == 0)))
+ err(2, NULL);
+ else if (ep[0] != '\0') {
+ errno = EINVAL;
+ err(2, NULL);
+ }
+ break;
+ case 'n':
+ nflag = true;
+ break;
+ case 'O':
+ linkbehave = LINK_EXPLICIT;
+ break;
+ case 'o':
+ oflag = true;
+ cflags &= ~REG_NOSUB;
+ break;
+ case 'p':
+ linkbehave = LINK_SKIP;
+ break;
+ case 'q':
+ qflag = true;
+ break;
+ case 'S':
+ linkbehave = LINK_READ;
+ break;
+ case 'R':
+ case 'r':
+ dirbehave = DIR_RECURSE;
+ Hflag = true;
+ break;
+ case 's':
+ sflag = true;
+ break;
+ case 'U':
+ binbehave = BINFILE_BIN;
+ break;
+ case 'u':
+ case MMAP_OPT:
+ filebehave = FILE_MMAP;
+ break;
+ case 'V':
+ printf(errstr[8], getprogname(), VERSION);
+ exit(0);
+ case 'v':
+ vflag = true;
+ break;
+ case 'w':
+ wflag = true;
+ cflags &= ~REG_NOSUB;
+ break;
+ case 'x':
+ xflag = true;
+ cflags &= ~REG_NOSUB;
+ break;
+ case 'z':
+ fileeol = '\0';
+ cflags &= ~REG_NEWLINE;
+ break;
+ case BIN_OPT:
+ if (strcasecmp("binary", optarg) == 0)
+ binbehave = BINFILE_BIN;
+ else if (strcasecmp("without-match", optarg) == 0)
+ binbehave = BINFILE_SKIP;
+ else if (strcasecmp("text", optarg) == 0)
+ binbehave = BINFILE_TEXT;
+ else
+ errx(2, errstr[2], "--binary-files");
+ break;
+ case COLOR_OPT:
+ color = NULL;
+ if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
+ strcasecmp("tty", optarg) == 0 ||
+ strcasecmp("if-tty", optarg) == 0) {
+ char *term;
+
+ term = getenv("TERM");
+ if (isatty(STDOUT_FILENO) && term != NULL &&
+ strcasecmp(term, "dumb") != 0)
+ color = init_color("01;31");
+ } else if (strcasecmp("always", optarg) == 0 ||
+ strcasecmp("yes", optarg) == 0 ||
+ strcasecmp("force", optarg) == 0) {
+ color = init_color("01;31");
+ } else if (strcasecmp("never", optarg) != 0 &&
+ strcasecmp("none", optarg) != 0 &&
+ strcasecmp("no", optarg) != 0)
+ errx(2, errstr[2], "--color");
+ cflags &= ~REG_NOSUB;
+ break;
+ case LABEL_OPT:
+ label = optarg;
+ break;
+ case LINEBUF_OPT:
+ lbflag = true;
+ break;
+ case NULL_OPT:
+ nullflag = true;
+ break;
+ case R_INCLUDE_OPT:
+ finclude = true;
+ add_fpattern(optarg, INCL_PAT);
+ break;
+ case R_EXCLUDE_OPT:
+ fexclude = true;
+ add_fpattern(optarg, EXCL_PAT);
+ break;
+ case R_DINCLUDE_OPT:
+ dinclude = true;
+ add_dpattern(optarg, INCL_PAT);
+ break;
+ case R_DEXCLUDE_OPT:
+ dexclude = true;
+ add_dpattern(optarg, EXCL_PAT);
+ break;
+ case HELP_OPT:
+ default:
+ usage();
+ }
+ lastc = c;
+ newarg = optind != prevoptind;
+ prevoptind = optind;
+ }
+ aargc -= optind;
+ aargv += optind;
+
+ /* xflag takes precedence, don't confuse the matching bits. */
+ if (wflag && xflag)
+ wflag = false;
+
+ /* Fail if we don't have any pattern */
+ if (aargc == 0 && needpattern)
+ usage();
+
+ /* Process patterns from command line */
+ if (aargc != 0 && needpattern) {
+ char *token;
+ char *string = *aargv;
+
+ while ((token = strsep(&string, "\n")) != NULL)
+ add_pattern(token, strlen(token));
+ --aargc;
+ ++aargv;
+ }
+
+ switch (grepbehave) {
+ case GREP_BASIC:
+ break;
+ case GREP_FIXED:
+ /*
+ * regex(3) implementations that support fixed-string searches generally
+ * define either REG_NOSPEC or REG_LITERAL. Set the appropriate flag
+ * here. If neither are defined, GREP_FIXED later implies that the
+ * internal literal matcher should be used. Other cflags that have
+ * the same interpretation as REG_NOSPEC and REG_LITERAL should be
+ * similarly added here, and grep.h should be amended to take this into
+ * consideration when defining WITH_INTERNAL_NOSPEC.
+ */
+#if defined(REG_NOSPEC)
+ cflags |= REG_NOSPEC;
+#elif defined(REG_LITERAL)
+ cflags |= REG_LITERAL;
+#endif
+ break;
+ case GREP_EXTENDED:
+ cflags |= REG_EXTENDED;
+ break;
+ default:
+ /* NOTREACHED */
+ usage();
+ }
+
+ r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
+
+#ifdef WITH_INTERNAL_NOSPEC
+ if (grepbehave != GREP_FIXED) {
+#else
+ {
+#endif
+ /* Check if cheating is allowed (always is for fgrep). */
+ for (i = 0; i < patterns; ++i) {
+ c = regcomp(&r_pattern[i], pattern[i].pat, cflags);
+ if (c != 0) {
+ regerror(c, &r_pattern[i], re_error,
+ RE_ERROR_BUF);
+ errx(2, "%s", re_error);
+ }
+ }
+ }
+
+ if (lbflag)
+ setlinebuf(stdout);
+
+ if ((aargc == 0 || aargc == 1) && !Hflag)
+ hflag = true;
+
+ initqueue();
+
+ if (aargc == 0 && dirbehave != DIR_RECURSE)
+ exit(!procfile("-"));
+
+ if (dirbehave == DIR_RECURSE)
+ matched = grep_tree(aargv);
+ else
+ for (matched = false; aargc--; ++aargv) {
+ if ((finclude || fexclude) && !file_matching(*aargv))
+ continue;
+ if (procfile(*aargv))
+ matched = true;
+ }
+
+ if (Lflag)
+ matched = !matched;
+
+ /*
+ * Calculate the correct return value according to the
+ * results and the command line option.
+ */
+ exit(matched ? (file_err ? (qflag ? 0 : 2) : 0) : (file_err ? 2 : 1));
+}
diff --git a/usr.bin/grep/grep.h b/usr.bin/grep/grep.h
new file mode 100644
index 000000000000..211fe1ae75c8
--- /dev/null
+++ b/usr.bin/grep/grep.h
@@ -0,0 +1,159 @@
+/* $NetBSD: grep.h,v 1.5 2011/02/27 17:33:37 joerg Exp $ */
+/* $OpenBSD: grep.h,v 1.15 2010/04/05 03:03:55 tedu Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
+ * Copyright (c) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <bzlib.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <zlib.h>
+
+extern const char *errstr[];
+
+#define VERSION "2.6.0-FreeBSD"
+
+#define GREP_FIXED 0
+#define GREP_BASIC 1
+#define GREP_EXTENDED 2
+
+#if !defined(REG_NOSPEC) && !defined(REG_LITERAL)
+#define WITH_INTERNAL_NOSPEC
+#endif
+
+#define BINFILE_BIN 0
+#define BINFILE_SKIP 1
+#define BINFILE_TEXT 2
+
+#define FILE_STDIO 0
+#define FILE_MMAP 1
+
+#define DIR_READ 0
+#define DIR_SKIP 1
+#define DIR_RECURSE 2
+
+#define DEV_READ 0
+#define DEV_SKIP 1
+
+#define LINK_READ 0
+#define LINK_EXPLICIT 1
+#define LINK_SKIP 2
+
+#define EXCL_PAT 0
+#define INCL_PAT 1
+
+#define MAX_MATCHES 32
+
+struct file {
+ int fd;
+ bool binary;
+};
+
+struct str {
+ off_t boff;
+ off_t off;
+ size_t len;
+ char *dat;
+ char *file;
+ int line_no;
+};
+
+struct pat {
+ char *pat;
+ int len;
+};
+
+struct epat {
+ char *pat;
+ int mode;
+};
+
+/*
+ * Parsing context; used to hold things like matches made and
+ * other useful bits
+ */
+struct parsec {
+ regmatch_t matches[MAX_MATCHES]; /* Matches made */
+ /* XXX TODO: This should be a chunk, not a line */
+ struct str ln; /* Current line */
+ size_t lnstart; /* Position in line */
+ size_t matchidx; /* Latest match index */
+ int printed; /* Metadata printed? */
+ bool binary; /* Binary file? */
+ bool cntlines; /* Count lines? */
+};
+
+/* Flags passed to regcomp() and regexec() */
+extern int cflags, eflags;
+
+/* Command line flags */
+extern bool Eflag, Fflag, Gflag, Hflag, Lflag,
+ bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag,
+ qflag, sflag, vflag, wflag, xflag;
+extern bool dexclude, dinclude, fexclude, finclude, lbflag, nullflag;
+extern long long Aflag, Bflag;
+extern long long mcount;
+extern long long mlimit;
+extern char fileeol;
+extern char *label;
+extern const char *color;
+extern int binbehave, devbehave, dirbehave, filebehave, grepbehave, linkbehave;
+
+extern bool file_err, matchall;
+extern unsigned int dpatterns, fpatterns, patterns;
+extern struct pat *pattern;
+extern struct epat *dpattern, *fpattern;
+extern regex_t *er_pattern, *r_pattern;
+
+/* For regex errors */
+#define RE_ERROR_BUF 512
+extern char re_error[RE_ERROR_BUF + 1]; /* Seems big enough */
+
+/* util.c */
+bool file_matching(const char *fname);
+bool procfile(const char *fn);
+bool grep_tree(char **argv);
+void *grep_malloc(size_t size);
+void *grep_calloc(size_t nmemb, size_t size);
+void *grep_realloc(void *ptr, size_t size);
+char *grep_strdup(const char *str);
+void grep_printline(struct str *line, int sep);
+
+/* queue.c */
+void initqueue(void);
+bool enqueue(struct str *x);
+void printqueue(void);
+void clearqueue(void);
+
+/* file.c */
+void grep_close(struct file *f);
+struct file *grep_open(const char *path);
+char *grep_fgetln(struct file *f, struct parsec *pc);
diff --git a/usr.bin/grep/queue.c b/usr.bin/grep/queue.c
new file mode 100644
index 000000000000..296e19fb0f6d
--- /dev/null
+++ b/usr.bin/grep/queue.c
@@ -0,0 +1,142 @@
+/* $NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
+ * All rights reserved.
+ * Copyright (c) 2020 Kyle Evans <kevans@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * A really poor man's queue. It does only what it has to and gets out of
+ * Dodge. It is used in place of <sys/queue.h> to get a better performance.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "grep.h"
+
+typedef struct str qentry_t;
+
+static long long filled;
+static qentry_t *qend, *qpool;
+
+/*
+ * qnext is the next entry to populate. qlist is where the list actually
+ * starts, for the purposes of printing.
+ */
+static qentry_t *qlist, *qnext;
+
+void
+initqueue(void)
+{
+
+ qlist = qnext = qpool = grep_calloc(Bflag, sizeof(*qpool));
+ qend = qpool + (Bflag - 1);
+}
+
+static qentry_t *
+advqueue(qentry_t *itemp)
+{
+
+ if (itemp == qend)
+ return (qpool);
+ return (itemp + 1);
+}
+
+/*
+ * Enqueue another line; return true if we've dequeued a line as a result
+ */
+bool
+enqueue(struct str *x)
+{
+ qentry_t *item;
+ bool rotated;
+
+ item = qnext;
+ qnext = advqueue(qnext);
+ rotated = false;
+
+ if (filled < Bflag) {
+ filled++;
+ } else if (filled == Bflag) {
+ /* We had already filled up coming in; just rotate. */
+ qlist = advqueue(qlist);
+ rotated = true;
+ free(item->dat);
+ }
+ /* len + 1 for NUL-terminator */
+ item->dat = grep_malloc(sizeof(char) * x->len + 1);
+ item->len = x->len;
+ item->line_no = x->line_no;
+ item->boff = x->boff;
+ item->off = x->off;
+ memcpy(item->dat, x->dat, x->len);
+ item->dat[x->len] = '\0';
+ item->file = x->file;
+
+ return (rotated);
+}
+
+void
+printqueue(void)
+{
+ qentry_t *item;
+
+ item = qlist;
+ do {
+ /* Buffer must have ended early. */
+ if (item->dat == NULL)
+ break;
+
+ grep_printline(item, '-');
+ free(item->dat);
+ item->dat = NULL;
+ item = advqueue(item);
+ } while (item != qlist);
+
+ qlist = qnext = qpool;
+ filled = 0;
+}
+
+void
+clearqueue(void)
+{
+ qentry_t *item;
+
+ item = qlist;
+ do {
+ free(item->dat);
+ item->dat = NULL;
+ item = advqueue(item);
+ } while (item != qlist);
+
+ qlist = qnext = qpool;
+ filled = 0;
+}
diff --git a/usr.bin/grep/tests/Makefile b/usr.bin/grep/tests/Makefile
new file mode 100644
index 000000000000..b3c79657e53c
--- /dev/null
+++ b/usr.bin/grep/tests/Makefile
@@ -0,0 +1,55 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= grep_freebsd_test
+NETBSD_ATF_TESTS_SH= grep_test
+
+${PACKAGE}FILES+= d_basic.out
+${PACKAGE}FILES+= d_begin_end_a.out
+${PACKAGE}FILES+= d_begin_end_b.out
+${PACKAGE}FILES+= d_binary.out
+${PACKAGE}FILES+= d_color_a.in
+${PACKAGE}FILES+= d_color_a.out
+${PACKAGE}FILES+= d_color_b.in
+${PACKAGE}FILES+= d_color_b.out
+${PACKAGE}FILES+= d_color_c.out
+${PACKAGE}FILES+= d_context2_a.out
+${PACKAGE}FILES+= d_context2_b.out
+${PACKAGE}FILES+= d_context2_c.out
+${PACKAGE}FILES+= d_context_a.in
+${PACKAGE}FILES+= d_context_a.out
+${PACKAGE}FILES+= d_context_b.in
+${PACKAGE}FILES+= d_context_e.in
+${PACKAGE}FILES+= d_context_b.out
+${PACKAGE}FILES+= d_context_c.out
+${PACKAGE}FILES+= d_context_d.out
+${PACKAGE}FILES+= d_context_e.out
+${PACKAGE}FILES+= d_context_f.out
+${PACKAGE}FILES+= d_context_g.out
+${PACKAGE}FILES+= d_egrep.out
+${PACKAGE}FILES+= d_escmap.in
+${PACKAGE}FILES+= d_f_file_empty.in
+${PACKAGE}FILES+= d_file_exp.in
+${PACKAGE}FILES+= d_file_exp.out
+${PACKAGE}FILES+= d_ignore_case.out
+${PACKAGE}FILES+= d_input
+${PACKAGE}FILES+= d_invert.in
+${PACKAGE}FILES+= d_invert.out
+${PACKAGE}FILES+= d_oflag_zerolen_a.in
+${PACKAGE}FILES+= d_oflag_zerolen_a.out
+${PACKAGE}FILES+= d_oflag_zerolen_b.in
+${PACKAGE}FILES+= d_oflag_zerolen_b.out
+${PACKAGE}FILES+= d_oflag_zerolen_c.in
+${PACKAGE}FILES+= d_oflag_zerolen_c.out
+${PACKAGE}FILES+= d_oflag_zerolen_d.in
+${PACKAGE}FILES+= d_oflag_zerolen_e.in
+${PACKAGE}FILES+= d_oflag_zerolen_e.out
+${PACKAGE}FILES+= d_recurse.out
+${PACKAGE}FILES+= d_recurse_symlink.err
+${PACKAGE}FILES+= d_recurse_symlink.out
+${PACKAGE}FILES+= d_whole_line.out
+${PACKAGE}FILES+= d_word_regexps.out
+${PACKAGE}FILES+= d_zgrep.out
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/grep/tests/Makefile.depend b/usr.bin/grep/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/grep/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/grep/tests/grep_freebsd_test.sh b/usr.bin/grep/tests/grep_freebsd_test.sh
new file mode 100755
index 000000000000..77017529843e
--- /dev/null
+++ b/usr.bin/grep/tests/grep_freebsd_test.sh
@@ -0,0 +1,112 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2017 Kyle Evans <kevans@FreeBSD.org>
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+# What grep(1) are we working with?
+# - 0 : bsdgrep
+# - 1 : gnu grep (ports)
+GREP_TYPE_BSD=0
+GREP_TYPE_GNU=1
+
+grep_type()
+{
+ local grep_version=$(grep --version)
+
+ case "$grep_version" in
+ *"BSD grep"*)
+ return $GREP_TYPE_BSD
+ ;;
+ *"GNU grep"*)
+ return $GREP_TYPE_GNU
+ ;;
+ esac
+ atf_fail "unknown grep type: $grep_version"
+}
+
+atf_test_case grep_r_implied
+grep_r_implied_body()
+{
+ grep_type
+ if [ $? -ne $GREP_TYPE_BSD ]; then
+ atf_skip "this test only works with bsdgrep(1)"
+ fi
+
+ (cd "$(atf_get_srcdir)" && grep -r --exclude="*.out" -e "test" .) > d_grep_r_implied.out
+
+ atf_check -s exit:0 -x \
+ "(cd $(atf_get_srcdir) && grep -r --exclude=\"*.out\" -e \"test\") | diff d_grep_r_implied.out -"
+}
+
+atf_test_case rgrep
+rgrep_head()
+{
+ atf_set "require.progs" "rgrep"
+}
+rgrep_body()
+{
+ atf_check -o save:d_grep_r_implied.out grep -r --exclude="*.out" -e "test" "$(atf_get_srcdir)"
+ atf_check -o file:d_grep_r_implied.out rgrep --exclude="*.out" -e "test" "$(atf_get_srcdir)"
+}
+
+atf_test_case gnuext
+gnuext_body()
+{
+ grep_type
+ _type=$?
+
+ atf_check -o save:grep_alnum.out grep -o '[[:alnum:]]' /COPYRIGHT
+ atf_check -o file:grep_alnum.out grep -o '\w' /COPYRIGHT
+
+ atf_check -o save:grep_nalnum.out grep -o '[^[:alnum:]]' /COPYRIGHT
+ atf_check -o file:grep_nalnum.out grep -o '\W' /COPYRIGHT
+
+ atf_check -o save:grep_space.out grep -o '[[:space:]]' /COPYRIGHT
+ atf_check -o file:grep_space.out grep -o '\s' /COPYRIGHT
+
+ atf_check -o save:grep_nspace.out grep -o '[^[:space:]]' /COPYRIGHT
+ atf_check -o file:grep_nspace.out grep -o '\S' /COPYRIGHT
+
+}
+
+atf_test_case zflag
+zflag_body()
+{
+
+ # The -z flag should pick up 'foo' and 'bar' as on the same line with
+ # 'some kind of junk' in between; a bug was present that instead made
+ # it process this incorrectly.
+ printf "foo\nbar\0" > in
+
+ atf_check grep -qz "foo.*bar" in
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case grep_r_implied
+ atf_add_test_case rgrep
+ atf_add_test_case gnuext
+ atf_add_test_case zflag
+}
diff --git a/usr.bin/grep/util.c b/usr.bin/grep/util.c
new file mode 100644
index 000000000000..4e1c44b442f2
--- /dev/null
+++ b/usr.bin/grep/util.c
@@ -0,0 +1,805 @@
+/* $NetBSD: util.c,v 1.9 2011/02/27 17:33:37 joerg Exp $ */
+/* $OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 James Howard and Dag-Erling Smørgrav
+ * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2017 Kyle Evans <kevans@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <fts.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "grep.h"
+
+static bool first_match = true;
+
+/*
+ * Match printing context
+ */
+struct mprintc {
+ long long tail; /* Number of trailing lines to record */
+ int last_outed; /* Number of lines since last output */
+ bool doctx; /* Printing context? */
+ bool printmatch; /* Printing matches? */
+ bool same_file; /* Same file as previously printed? */
+};
+
+static void procmatch_match(struct mprintc *mc, struct parsec *pc);
+static void procmatch_nomatch(struct mprintc *mc, struct parsec *pc);
+static bool procmatches(struct mprintc *mc, struct parsec *pc, bool matched);
+#ifdef WITH_INTERNAL_NOSPEC
+static int litexec(const struct pat *pat, const char *string,
+ size_t nmatch, regmatch_t pmatch[]);
+#endif
+static bool procline(struct parsec *pc);
+static void printline(struct parsec *pc, int sep);
+static void printline_metadata(struct str *line, int sep);
+
+bool
+file_matching(const char *fname)
+{
+ char *fname_base, *fname_buf;
+ bool ret;
+
+ ret = finclude ? false : true;
+ fname_buf = strdup(fname);
+ if (fname_buf == NULL)
+ err(2, "strdup");
+ fname_base = basename(fname_buf);
+
+ for (unsigned int i = 0; i < fpatterns; ++i) {
+ if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
+ fnmatch(fpattern[i].pat, fname_base, 0) == 0)
+ /*
+ * The last pattern matched wins exclusion/inclusion
+ * rights, so we can't reasonably bail out early here.
+ */
+ ret = (fpattern[i].mode != EXCL_PAT);
+ }
+ free(fname_buf);
+ return (ret);
+}
+
+static inline bool
+dir_matching(const char *dname)
+{
+ bool ret;
+
+ ret = dinclude ? false : true;
+
+ for (unsigned int i = 0; i < dpatterns; ++i) {
+ if (dname != NULL && fnmatch(dpattern[i].pat, dname, 0) == 0)
+ /*
+ * The last pattern matched wins exclusion/inclusion
+ * rights, so we can't reasonably bail out early here.
+ */
+ ret = (dpattern[i].mode != EXCL_PAT);
+ }
+ return (ret);
+}
+
+/*
+ * Processes a directory when a recursive search is performed with
+ * the -R option. Each appropriate file is passed to procfile().
+ */
+bool
+grep_tree(char **argv)
+{
+ FTS *fts;
+ FTSENT *p;
+ int fts_flags;
+ bool matched, ok;
+ const char *wd[] = { ".", NULL };
+
+ matched = false;
+
+ /* This switch effectively initializes 'fts_flags' */
+ switch(linkbehave) {
+ case LINK_EXPLICIT:
+ fts_flags = FTS_COMFOLLOW | FTS_PHYSICAL;
+ break;
+ case LINK_SKIP:
+ fts_flags = FTS_PHYSICAL;
+ break;
+ default:
+ fts_flags = FTS_LOGICAL | FTS_NOSTAT;
+ }
+
+ fts_flags |= FTS_NOCHDIR;
+
+ fts = fts_open((argv[0] == NULL) ?
+ __DECONST(char * const *, wd) : argv, fts_flags, NULL);
+ if (fts == NULL)
+ err(2, "fts_open");
+ while (errno = 0, (p = fts_read(fts)) != NULL) {
+ switch (p->fts_info) {
+ case FTS_DNR:
+ case FTS_ERR:
+ case FTS_NS:
+ file_err = true;
+ if(!sflag)
+ warnc(p->fts_errno, "%s", p->fts_path);
+ break;
+ case FTS_D:
+ if (dexclude || dinclude)
+ if (!dir_matching(p->fts_name) ||
+ !dir_matching(p->fts_path))
+ fts_set(fts, p, FTS_SKIP);
+ break;
+ case FTS_DC:
+ /* Print a warning for recursive directory loop */
+ warnx("warning: %s: recursive directory loop",
+ p->fts_path);
+ break;
+ case FTS_DP:
+ break;
+ case FTS_SL:
+ /*
+ * Skip symlinks for LINK_EXPLICIT and
+ * LINK_SKIP. Note that due to FTS_COMFOLLOW,
+ * symlinks on the command line are followed
+ * for LINK_EXPLICIT and not reported as
+ * symlinks.
+ */
+ break;
+ default:
+ /* Check for file exclusion/inclusion */
+ ok = true;
+ if (fexclude || finclude)
+ ok &= file_matching(p->fts_path);
+
+ if (ok && procfile(p->fts_path))
+ matched = true;
+ break;
+ }
+ }
+ if (errno != 0)
+ err(2, "fts_read");
+
+ fts_close(fts);
+ return (matched);
+}
+
+static void
+procmatch_match(struct mprintc *mc, struct parsec *pc)
+{
+
+ if (mc->doctx) {
+ if (!first_match && (!mc->same_file || mc->last_outed > 0))
+ printf("--\n");
+ if (Bflag > 0)
+ printqueue();
+ mc->tail = Aflag;
+ }
+
+ /* Print the matching line, but only if not quiet/binary */
+ if (mc->printmatch) {
+ printline(pc, ':');
+ while (pc->matchidx >= MAX_MATCHES) {
+ /* Reset matchidx and try again */
+ pc->matchidx = 0;
+ if (procline(pc) == !vflag)
+ printline(pc, ':');
+ else
+ break;
+ }
+ first_match = false;
+ mc->same_file = true;
+ mc->last_outed = 0;
+ }
+}
+
+static void
+procmatch_nomatch(struct mprintc *mc, struct parsec *pc)
+{
+
+ /* Deal with any -A context as needed */
+ if (mc->tail > 0) {
+ grep_printline(&pc->ln, '-');
+ mc->tail--;
+ if (Bflag > 0)
+ clearqueue();
+ } else if (Bflag == 0 || (Bflag > 0 && enqueue(&pc->ln)))
+ /*
+ * Enqueue non-matching lines for -B context. If we're not
+ * actually doing -B context or if the enqueue resulted in a
+ * line being rotated out, then go ahead and increment
+ * last_outed to signify a gap between context/match.
+ */
+ ++mc->last_outed;
+}
+
+/*
+ * Process any matches in the current parsing context, return a boolean
+ * indicating whether we should halt any further processing or not. 'true' to
+ * continue processing, 'false' to halt.
+ */
+static bool
+procmatches(struct mprintc *mc, struct parsec *pc, bool matched)
+{
+
+ if (mflag && mcount <= 0) {
+ /*
+ * We already hit our match count, but we need to keep dumping
+ * lines until we've lost our tail.
+ */
+ grep_printline(&pc->ln, '-');
+ mc->tail--;
+ return (mc->tail != 0);
+ }
+
+ /*
+ * XXX TODO: This should loop over pc->matches and handle things on a
+ * line-by-line basis, setting up a `struct str` as needed.
+ */
+ /* Deal with any -B context or context separators */
+ if (matched) {
+ procmatch_match(mc, pc);
+
+ /* Count the matches if we have a match limit */
+ if (mflag) {
+ /* XXX TODO: Decrement by number of matched lines */
+ mcount -= 1;
+ if (mcount <= 0)
+ return (mc->tail != 0);
+ }
+ } else if (mc->doctx)
+ procmatch_nomatch(mc, pc);
+
+ return (true);
+}
+
+/*
+ * Opens a file and processes it. Each file is processed line-by-line
+ * passing the lines to procline().
+ */
+bool
+procfile(const char *fn)
+{
+ struct parsec pc;
+ struct mprintc mc;
+ struct file *f;
+ struct stat sb;
+ mode_t s;
+ int lines;
+ bool line_matched;
+
+ if (strcmp(fn, "-") == 0) {
+ fn = label != NULL ? label : errstr[1];
+ f = grep_open(NULL);
+ } else {
+ if (stat(fn, &sb) == 0) {
+ /* Check if we need to process the file */
+ s = sb.st_mode & S_IFMT;
+ if (dirbehave == DIR_SKIP && s == S_IFDIR)
+ return (false);
+ if (devbehave == DEV_SKIP && (s == S_IFIFO ||
+ s == S_IFCHR || s == S_IFBLK || s == S_IFSOCK))
+ return (false);
+ }
+ f = grep_open(fn);
+ }
+ if (f == NULL) {
+ file_err = true;
+ if (!sflag)
+ warn("%s", fn);
+ return (false);
+ }
+
+ pc.ln.file = grep_strdup(fn);
+ pc.ln.line_no = 0;
+ pc.ln.len = 0;
+ pc.ln.boff = 0;
+ pc.ln.off = -1;
+ pc.binary = f->binary;
+ pc.cntlines = false;
+ memset(&mc, 0, sizeof(mc));
+ mc.printmatch = true;
+ if ((pc.binary && binbehave == BINFILE_BIN) || cflag || qflag ||
+ lflag || Lflag)
+ mc.printmatch = false;
+ if (mc.printmatch && (Aflag != 0 || Bflag != 0))
+ mc.doctx = true;
+ if (mc.printmatch && (Aflag != 0 || Bflag != 0 || mflag || nflag))
+ pc.cntlines = true;
+ mcount = mlimit;
+
+ for (lines = 0; lines == 0 || !(lflag || qflag); ) {
+ /*
+ * XXX TODO: We need to revisit this in a chunking world. We're
+ * not going to be doing per-line statistics because of the
+ * overhead involved. procmatches can figure that stuff out as
+ * needed. */
+ /* Reset per-line statistics */
+ pc.printed = 0;
+ pc.matchidx = 0;
+ pc.lnstart = 0;
+ pc.ln.boff = 0;
+ pc.ln.off += pc.ln.len + 1;
+ /* XXX TODO: Grab a chunk */
+ if ((pc.ln.dat = grep_fgetln(f, &pc)) == NULL ||
+ pc.ln.len == 0)
+ break;
+
+ if (pc.ln.len > 0 && pc.ln.dat[pc.ln.len - 1] == fileeol)
+ --pc.ln.len;
+ pc.ln.line_no++;
+
+ /* Return if we need to skip a binary file */
+ if (pc.binary && binbehave == BINFILE_SKIP) {
+ grep_close(f);
+ free(pc.ln.file);
+ free(f);
+ return (0);
+ }
+
+ if (mflag && mcount <= 0) {
+ /*
+ * Short-circuit, already hit match count and now we're
+ * just picking up any remaining pieces.
+ */
+ if (!procmatches(&mc, &pc, false))
+ break;
+ continue;
+ }
+ line_matched = procline(&pc) == !vflag;
+ if (line_matched)
+ ++lines;
+
+ /* Halt processing if we hit our match limit */
+ if (!procmatches(&mc, &pc, line_matched))
+ break;
+ }
+ if (Bflag > 0)
+ clearqueue();
+ grep_close(f);
+
+ if (cflag && !qflag) {
+ if (!hflag)
+ printf("%s:", pc.ln.file);
+ printf("%u\n", lines);
+ }
+ if (lflag && !qflag && lines != 0)
+ printf("%s%c", fn, nullflag ? 0 : '\n');
+ if (Lflag && !qflag && lines == 0)
+ printf("%s%c", fn, nullflag ? 0 : '\n');
+ if (lines != 0 && !cflag && !lflag && !Lflag &&
+ binbehave == BINFILE_BIN && f->binary && !qflag)
+ printf(errstr[7], fn);
+
+ free(pc.ln.file);
+ free(f);
+ return (lines != 0);
+}
+
+#ifdef WITH_INTERNAL_NOSPEC
+/*
+ * Internal implementation of literal string search within a string, modeled
+ * after regexec(3), for use when the regex(3) implementation doesn't offer
+ * either REG_NOSPEC or REG_LITERAL. This does not apply in the default FreeBSD
+ * config, but in other scenarios such as building against libgnuregex or on
+ * some non-FreeBSD OSes.
+ */
+static int
+litexec(const struct pat *pat, const char *string, size_t nmatch,
+ regmatch_t pmatch[])
+{
+ char *(*strstr_fn)(const char *, const char *);
+ char *sub, *subject;
+ const char *search;
+ size_t idx, n, ofs, stringlen;
+
+ if (cflags & REG_ICASE)
+ strstr_fn = strcasestr;
+ else
+ strstr_fn = strstr;
+ idx = 0;
+ ofs = pmatch[0].rm_so;
+ stringlen = pmatch[0].rm_eo;
+ if (ofs >= stringlen)
+ return (REG_NOMATCH);
+ subject = strndup(string, stringlen);
+ if (subject == NULL)
+ return (REG_ESPACE);
+ for (n = 0; ofs < stringlen;) {
+ search = (subject + ofs);
+ if ((unsigned long)pat->len > strlen(search))
+ break;
+ sub = strstr_fn(search, pat->pat);
+ /*
+ * Ignoring the empty string possibility due to context: grep optimizes
+ * for empty patterns and will never reach this point.
+ */
+ if (sub == NULL)
+ break;
+ ++n;
+ /* Fill in pmatch if necessary */
+ if (nmatch > 0) {
+ pmatch[idx].rm_so = ofs + (sub - search);
+ pmatch[idx].rm_eo = pmatch[idx].rm_so + pat->len;
+ if (++idx == nmatch)
+ break;
+ ofs = pmatch[idx].rm_so + 1;
+ } else
+ /* We only needed to know if we match or not */
+ break;
+ }
+ free(subject);
+ if (n > 0 && nmatch > 0)
+ for (n = idx; n < nmatch; ++n)
+ pmatch[n].rm_so = pmatch[n].rm_eo = -1;
+
+ return (n > 0 ? 0 : REG_NOMATCH);
+}
+#endif /* WITH_INTERNAL_NOSPEC */
+
+#define iswword(x) (iswalnum((x)) || (x) == L'_')
+
+/*
+ * Processes a line comparing it with the specified patterns. Each pattern
+ * is looped to be compared along with the full string, saving each and every
+ * match, which is necessary to colorize the output and to count the
+ * matches. The matching lines are passed to printline() to display the
+ * appropriate output.
+ */
+static bool
+procline(struct parsec *pc)
+{
+ regmatch_t pmatch, lastmatch, chkmatch;
+ wchar_t wbegin, wend;
+ size_t st, nst;
+ unsigned int i;
+ int r = 0, leflags = eflags;
+ size_t startm = 0, matchidx;
+ unsigned int retry;
+ bool lastmatched, matched;
+
+ matchidx = pc->matchidx;
+
+ /* Null pattern shortcuts. */
+ if (matchall) {
+ if (xflag && pc->ln.len == 0) {
+ /* Matches empty lines (-x). */
+ return (true);
+ } else if (!wflag && !xflag) {
+ /* Matches every line (no -w or -x). */
+ return (true);
+ }
+
+ /*
+ * If we only have the NULL pattern, whether we match or not
+ * depends on if we got here with -w or -x. If either is set,
+ * the answer is no. If we have other patterns, we'll defer
+ * to them.
+ */
+ if (patterns == 0) {
+ return (!(wflag || xflag));
+ }
+ } else if (patterns == 0) {
+ /* Pattern file with no patterns. */
+ return (false);
+ }
+
+ matched = false;
+ st = pc->lnstart;
+ nst = 0;
+ /* Initialize to avoid a false positive warning from GCC. */
+ lastmatch.rm_so = lastmatch.rm_eo = 0;
+
+ /* Loop to process the whole line */
+ while (st <= pc->ln.len) {
+ lastmatched = false;
+ startm = matchidx;
+ retry = 0;
+ if (st > 0 && pc->ln.dat[st - 1] != fileeol)
+ leflags |= REG_NOTBOL;
+ /* Loop to compare with all the patterns */
+ for (i = 0; i < patterns; i++) {
+ pmatch.rm_so = st;
+ pmatch.rm_eo = pc->ln.len;
+#ifdef WITH_INTERNAL_NOSPEC
+ if (grepbehave == GREP_FIXED)
+ r = litexec(&pattern[i], pc->ln.dat, 1, &pmatch);
+ else
+#endif
+ r = regexec(&r_pattern[i], pc->ln.dat, 1, &pmatch,
+ leflags);
+ if (r != 0)
+ continue;
+ /* Check for full match */
+ if (xflag && (pmatch.rm_so != 0 ||
+ (size_t)pmatch.rm_eo != pc->ln.len))
+ continue;
+ /* Check for whole word match */
+ if (wflag) {
+ wbegin = wend = L' ';
+ if (pmatch.rm_so != 0 &&
+ sscanf(&pc->ln.dat[pmatch.rm_so - 1],
+ "%lc", &wbegin) != 1)
+ r = REG_NOMATCH;
+ else if ((size_t)pmatch.rm_eo !=
+ pc->ln.len &&
+ sscanf(&pc->ln.dat[pmatch.rm_eo],
+ "%lc", &wend) != 1)
+ r = REG_NOMATCH;
+ else if (iswword(wbegin) ||
+ iswword(wend))
+ r = REG_NOMATCH;
+ /*
+ * If we're doing whole word matching and we
+ * matched once, then we should try the pattern
+ * again after advancing just past the start of
+ * the earliest match. This allows the pattern
+ * to match later on in the line and possibly
+ * still match a whole word.
+ */
+ if (r == REG_NOMATCH &&
+ (retry == pc->lnstart ||
+ (unsigned int)pmatch.rm_so + 1 < retry))
+ retry = pmatch.rm_so + 1;
+ if (r == REG_NOMATCH)
+ continue;
+ }
+ lastmatched = true;
+ lastmatch = pmatch;
+
+ if (matchidx == 0)
+ matched = true;
+
+ /*
+ * Replace previous match if the new one is earlier
+ * and/or longer. This will lead to some amount of
+ * extra work if -o/--color are specified, but it's
+ * worth it from a correctness point of view.
+ */
+ if (matchidx > startm) {
+ chkmatch = pc->matches[matchidx - 1];
+ if (pmatch.rm_so < chkmatch.rm_so ||
+ (pmatch.rm_so == chkmatch.rm_so &&
+ (pmatch.rm_eo - pmatch.rm_so) >
+ (chkmatch.rm_eo - chkmatch.rm_so))) {
+ pc->matches[matchidx - 1] = pmatch;
+ nst = pmatch.rm_eo;
+ }
+ } else {
+ /* Advance as normal if not */
+ pc->matches[matchidx++] = pmatch;
+ nst = pmatch.rm_eo;
+ }
+ /* avoid excessive matching - skip further patterns */
+ if ((color == NULL && !oflag) || qflag || lflag ||
+ matchidx >= MAX_MATCHES) {
+ pc->lnstart = nst;
+ lastmatched = false;
+ break;
+ }
+ }
+
+ /*
+ * Advance to just past the start of the earliest match, try
+ * again just in case we still have a chance to match later in
+ * the string.
+ */
+ if (!lastmatched && retry > pc->lnstart) {
+ st = retry;
+ continue;
+ }
+
+ /* XXX TODO: We will need to keep going, since we're chunky */
+ /* One pass if we are not recording matches */
+ if (!wflag && ((color == NULL && !oflag) || qflag || lflag || Lflag))
+ break;
+
+ /* If we didn't have any matches or REG_NOSUB set */
+ if (!lastmatched || (cflags & REG_NOSUB))
+ nst = pc->ln.len;
+
+ if (!lastmatched)
+ /* No matches */
+ break;
+ else if (st == nst && lastmatch.rm_so == lastmatch.rm_eo)
+ /* Zero-length match -- advance one more so we don't get stuck */
+ nst++;
+
+ /* Advance st based on previous matches */
+ st = nst;
+ pc->lnstart = st;
+ }
+
+ /* Reflect the new matchidx in the context */
+ pc->matchidx = matchidx;
+ return matched;
+}
+
+/*
+ * Safe malloc() for internal use.
+ */
+void *
+grep_malloc(size_t size)
+{
+ void *ptr;
+
+ if (size == 0)
+ return (NULL);
+ if ((ptr = malloc(size)) == NULL)
+ err(2, "malloc");
+ return (ptr);
+}
+
+/*
+ * Safe calloc() for internal use.
+ */
+void *
+grep_calloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+
+ if (nmemb == 0 || size == 0)
+ return (NULL);
+ if ((ptr = calloc(nmemb, size)) == NULL)
+ err(2, "calloc");
+ return (ptr);
+}
+
+/*
+ * Safe realloc() for internal use.
+ */
+void *
+grep_realloc(void *ptr, size_t size)
+{
+
+ if ((ptr = realloc(ptr, size)) == NULL)
+ err(2, "realloc");
+ return (ptr);
+}
+
+/*
+ * Safe strdup() for internal use.
+ */
+char *
+grep_strdup(const char *str)
+{
+ char *ret;
+
+ if ((ret = strdup(str)) == NULL)
+ err(2, "strdup");
+ return (ret);
+}
+
+/*
+ * Print an entire line as-is, there are no inline matches to consider. This is
+ * used for printing context.
+ */
+void grep_printline(struct str *line, int sep) {
+ printline_metadata(line, sep);
+ fwrite(line->dat, line->len, 1, stdout);
+ putchar(fileeol);
+}
+
+static void
+printline_metadata(struct str *line, int sep)
+{
+ bool printsep;
+
+ printsep = false;
+ if (!hflag) {
+ if (!nullflag) {
+ fputs(line->file, stdout);
+ printsep = true;
+ } else {
+ printf("%s", line->file);
+ putchar(0);
+ }
+ }
+ if (nflag) {
+ if (printsep)
+ putchar(sep);
+ printf("%d", line->line_no);
+ printsep = true;
+ }
+ if (bflag) {
+ if (printsep)
+ putchar(sep);
+ printf("%lld", (long long)(line->off + line->boff));
+ printsep = true;
+ }
+ if (printsep)
+ putchar(sep);
+}
+
+/*
+ * Prints a matching line according to the command line options.
+ */
+static void
+printline(struct parsec *pc, int sep)
+{
+ size_t a = 0;
+ size_t i, matchidx;
+ regmatch_t match;
+
+ /* If matchall, everything matches but don't actually print for -o */
+ if (oflag && matchall)
+ return;
+
+ matchidx = pc->matchidx;
+
+ /* --color and -o */
+ if ((oflag || color) && matchidx > 0) {
+ /* Only print metadata once per line if --color */
+ if (!oflag && pc->printed == 0)
+ printline_metadata(&pc->ln, sep);
+ for (i = 0; i < matchidx; i++) {
+ match = pc->matches[i];
+ /* Don't output zero length matches */
+ if (match.rm_so == match.rm_eo)
+ continue;
+ /*
+ * Metadata is printed on a per-line basis, so every
+ * match gets file metadata with the -o flag.
+ */
+ if (oflag) {
+ pc->ln.boff = match.rm_so;
+ printline_metadata(&pc->ln, sep);
+ } else
+ fwrite(pc->ln.dat + a, match.rm_so - a, 1,
+ stdout);
+ if (color)
+ fprintf(stdout, "\33[%sm\33[K", color);
+ fwrite(pc->ln.dat + match.rm_so,
+ match.rm_eo - match.rm_so, 1, stdout);
+ if (color)
+ fprintf(stdout, "\33[m\33[K");
+ a = match.rm_eo;
+ if (oflag)
+ putchar('\n');
+ }
+ if (!oflag) {
+ if (pc->ln.len - a > 0)
+ fwrite(pc->ln.dat + a, pc->ln.len - a, 1,
+ stdout);
+ putchar('\n');
+ }
+ } else
+ grep_printline(&pc->ln, sep);
+ pc->printed++;
+}
diff --git a/usr.bin/grep/zgrep.1 b/usr.bin/grep/zgrep.1
new file mode 100644
index 000000000000..76eb145db82d
--- /dev/null
+++ b/usr.bin/grep/zgrep.1
@@ -0,0 +1,112 @@
+.\" Copyright (c) 2018 Baptiste Daroussin <bapt@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 July 20, 2020
+.Dt ZGREP 1
+.Os
+.Sh NAME
+.Nm zgrep ,
+.Nm zegrep ,
+.Nm zfgrep ,
+.Nm bzgrep ,
+.Nm bzegrep ,
+.Nm bzfgrep ,
+.Nm lzgrep ,
+.Nm lzegrep ,
+.Nm lzfgrep ,
+.Nm xzgrep ,
+.Nm xzegrep ,
+.Nm xzfgrep ,
+.Nm zstdgrep ,
+.Nm zstdegrep ,
+.Nm zstdfgrep
+.Nd grep compressed files
+.Sh SYNOPSIS
+.Nm
+.Oo Ar flags Oc Ar files
+.Nm zegrep
+.Oo Ar flags Oc Ar files
+.Nm zfgrep
+.Oo Ar flags Oc Ar files
+.Pp
+.Nm bzgrep
+.Oo Ar flags Oc Ar files
+.Nm bzegrep
+.Oo Ar flags Oc Ar files
+.Nm bzfgrep
+.Oo Ar flags Oc Ar files
+.Pp
+.Nm lzgrep
+.Oo Ar flags Oc Ar files
+.Nm lzegrep
+.Oo Ar flags Oc Ar files
+.Nm lzfgrep
+.Oo Ar flags Oc Ar files
+.Pp
+.Nm xzgrep
+.Oo Ar flags Oc Ar files
+.Nm xzegrep
+.Oo Ar flags Oc Ar files
+.Nm xzfgrep
+.Oo Ar flags Oc Ar files
+.Pp
+.Nm zstdgrep
+.Oo Ar flags Oc Ar files
+.Nm zstdegrep
+.Oo Ar flags Oc Ar files
+.Nm zstdfgrep
+.Oo Ar flags Oc Ar files
+.Sh DESCRIPTION
+Allow
+.Xr grep 1
+to read compressed files.
+.Sh SEE ALSO
+.Xr bzip2 1 ,
+.Xr grep 1 ,
+.Xr gzip 1 ,
+.Xr xz 1 ,
+.Xr zstd 1
+.Sh AUTHORS
+This version of the
+.Nm
+utility was written by
+.An Thomas Klausner Aq Mt wiz@NetBSD.org .
+.Sh BUGS
+.Xr zgrep 1
+does not handle flags that take arguments if there is no whitespace
+between the flag and the argument, for example:
+.Pp
+.Dl "zgrep -enfs /etc/rpc"
+.Pp
+When more than one
+.Fl e
+flag is used matching
+should occur for any of the patterns (similar to multiple patterns
+supplied in a file with the
+.Fl f
+flag).
+.Xr zgrep 1
+only matches the last
+.Fl e
+pattern.
diff --git a/usr.bin/grep/zgrep.sh b/usr.bin/grep/zgrep.sh
new file mode 100755
index 000000000000..8bd630726647
--- /dev/null
+++ b/usr.bin/grep/zgrep.sh
@@ -0,0 +1,230 @@
+#!/bin/sh
+#
+# Copyright (c) 2003 Thomas Klausner.
+#
+# 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 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.
+#
+
+set -u
+grep=grep
+zcat=zstdcat
+
+endofopts=0
+pattern_file=0
+pattern_found=0
+grep_args=""
+hyphen=0
+silent=0
+
+prg=${0##*/}
+
+# handle being called 'zegrep' or 'zfgrep'
+case ${prg} in
+*egrep)
+ grep_args="-E";;
+*fgrep)
+ grep_args="-F";;
+esac
+
+catargs="-f"
+case ${prg} in
+zstd*)
+ cattool="/usr/bin/zstdcat"
+ catargs="-fq"
+ ;;
+bz*)
+ cattool="/usr/bin/bzcat"
+ ;;
+z*)
+ cattool="/usr/bin/zcat"
+ ;;
+xz*)
+ cattool="/usr/bin/xzcat"
+ ;;
+lz*)
+ cattool="/usr/bin/lzcat"
+ ;;
+*)
+ echo "Invalid command: ${prg}" >&2
+ exit 1
+ ;;
+esac
+
+# skip all options and pass them on to grep taking care of options
+# with arguments, and if -e was supplied
+
+while [ $# -gt 0 -a ${endofopts} -eq 0 ]
+do
+ case $1 in
+ # from GNU grep-2.6.0 -- keep in sync!
+ --)
+ shift
+ endofopts=1
+ ;;
+ --file=*)
+ pattern_file=1
+ grep_args="${grep_args} ${1}"
+ shift
+ ;;
+ --regexp=*)
+ if [ ${pattern_found} -ne 0 ]; then
+ grep_args="${grep_args} -e ${pattern}"
+ fi
+ pattern="${1#--regexp=}"
+ pattern_found=1
+ shift
+ ;;
+ -h|--no-filename)
+ silent=1
+ shift
+ ;;
+ -V|--version)
+ exec ${grep} -V
+ ;;
+ --*)
+ grep_args="${grep_args} $1"
+ shift
+ ;;
+ -[EFGHILOSUVabchilnopqsuvwxyz]*)
+ post="${1#-?}"
+ pre=${1%${post}}
+ grep_args="${grep_args} ${pre}"
+ shift
+ # Put back partial arg
+ set -- "-${post}" $*
+ ;;
+ -[ABCDdefm])
+ if [ $# -lt 2 ]
+ then
+ echo "${prg}: missing argument for $1 flag" >&2
+ exit 1
+ fi
+ case $1 in
+ -e)
+ if [ ${pattern_found} -ne 0 ]; then
+ grep_args="${grep_args} -e ${pattern}"
+ fi
+ pattern="$2"
+ pattern_found=1
+ shift 2
+ continue
+ ;;
+ -f)
+ pattern_file=1
+ ;;
+ *)
+ ;;
+ esac
+ grep_args="${grep_args} $1 $2"
+ shift 2
+ ;;
+ -[ABCDdefm]*)
+ post="${1#-e}"
+ case ${1} in
+ -e*)
+ if [ ${pattern_found} -ne 0 ]; then
+ grep_args="${grep_args} -e ${pattern}"
+ fi
+ pattern="${post}"
+ pattern_found=1
+ shift
+ continue
+ ;;
+ -f*)
+ pattern_file=1
+ ;;
+ *)
+ ;;
+ esac
+ grep_args="${grep_args} ${post}"
+ shift
+ ;;
+ -)
+ hyphen=1
+ shift
+ ;;
+ -r|-R)
+ echo "${prg}: the ${1} flag is not currently supported" >&2
+ exit 1
+ ;;
+ -?)
+ grep_args="${grep_args} $1"
+ shift
+ ;;
+ *)
+ # pattern to grep for
+ endofopts=1
+ ;;
+ esac
+done
+
+# if no -e option was found, take next argument as grep-pattern
+if [ ${pattern_file} -eq 0 -a ${pattern_found} -eq 0 ]
+then
+ if [ $# -ge 1 ]; then
+ pattern="$1"
+ shift
+ elif [ ${hyphen} -gt 0 ]; then
+ pattern="-"
+ else
+ echo "${prg}: missing pattern" >&2
+ exit 1
+ fi
+ pattern_found=1
+fi
+
+# Clean up possible leading blank
+grep_args="${grep_args# }"
+
+# call grep ...
+if [ $# -lt 1 ]
+then
+ # ... on stdin
+ if [ ${pattern_file} -eq 0 ]; then
+ ${cattool} ${catargs} - | ${grep} ${grep_args} -e "${pattern}" -- -
+ else
+ ${cattool} ${catargs} - | ${grep} ${grep_args} -- -
+ fi
+ ret=$?
+else
+ # ... on all files given on the command line
+ if [ ${silent} -lt 1 -a $# -gt 1 ]; then
+ grep_args="-H ${grep_args}"
+ fi
+ # Succeed if any file matches. First assume no match.
+ ret=1
+ for file; do
+ if [ ${pattern_file} -eq 0 ]; then
+ ${cattool} ${catargs} -- "${file}" |
+ ${grep} --label="${file}" ${grep_args} -e "${pattern}" -- -
+ else
+ ${cattool} ${catargs} -- "${file}" |
+ ${grep} --label="${file}" ${grep_args} -- -
+ fi
+ this_ret=$?
+ # A match (0) overrides a no-match (1). An error (>=2) overrides all.
+ if [ ${this_ret} -eq 0 -a ${ret} -eq 1 ] || [ ${this_ret} -ge 2 ]; then
+ ret=${this_ret}
+ fi
+ done
+fi
+
+exit ${ret}
diff --git a/usr.bin/gzip/Makefile b/usr.bin/gzip/Makefile
new file mode 100644
index 000000000000..33fbdb85d78c
--- /dev/null
+++ b/usr.bin/gzip/Makefile
@@ -0,0 +1,36 @@
+# $NetBSD: Makefile,v 1.18 2013/11/13 11:12:24 pettai Exp $
+
+.include <src.opts.mk>
+
+PROG= gzip
+MAN= gzip.1 gzexe.1 zdiff.1 zforce.1 zmore.1 znew.1
+
+LIBADD= z lzma zstd
+
+.if ${MK_BZIP2_SUPPORT} != "no"
+LIBADD+= bz2
+.else
+CFLAGS+= -DNO_BZIP2_SUPPORT
+.endif
+
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib
+
+SCRIPTS= gzexe zdiff zforce zmore znew
+
+MLINKS+= gzip.1 gunzip.1 \
+ gzip.1 gzcat.1 \
+ gzip.1 zcat.1 \
+ zdiff.1 zcmp.1 \
+ zdiff.1 xzdiff.1 \
+ zmore.1 zless.1
+
+LINKS+= ${BINDIR}/gzip ${BINDIR}/gunzip \
+ ${BINDIR}/gzip ${BINDIR}/gzcat \
+ ${BINDIR}/gzip ${BINDIR}/zcat \
+ ${BINDIR}/zdiff ${BINDIR}/xzdiff \
+ ${BINDIR}/zdiff ${BINDIR}/zcmp
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/gzip/Makefile.depend b/usr.bin/gzip/Makefile.depend
new file mode 100644
index 000000000000..bc41ed39450b
--- /dev/null
+++ b/usr.bin/gzip/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/liblzma \
+ lib/libz \
+ lib/libzstd \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gzip/Makefile.depend.options b/usr.bin/gzip/Makefile.depend.options
new file mode 100644
index 000000000000..2370c8a69e35
--- /dev/null
+++ b/usr.bin/gzip/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= BZIP2_SUPPORT
+
+DIRDEPS.BZIP2_SUPPORT.yes= lib/libbz2
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/gzip/gzexe b/usr.bin/gzip/gzexe
new file mode 100644
index 000000000000..ca96dfc83bce
--- /dev/null
+++ b/usr.bin/gzip/gzexe
@@ -0,0 +1,178 @@
+#!/bin/sh -
+#
+# $NetBSD: gzexe,v 1.3 2004/05/01 08:22:41 wiz Exp $
+# $OpenBSD: gzexe,v 1.3 2003/08/05 18:22:17 deraadt Exp $
+#
+#-
+# Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+# The number of lines plus one in the on-the-fly decompression script
+lines=19
+
+# A simple string to recognize already compressed files
+magic="# compressed by gzexe"
+
+# Write the decompression script to stdout
+header () {
+ # first section needs variable expansion, second not
+ cat <<- EOF
+ #!/bin/sh -
+ $magic
+ lines=$lines
+ EOF
+ cat <<- 'EOF'
+ prog=`/usr/bin/basename "$0"`
+ tmp=`/usr/bin/mktemp -d /tmp/gzexeXXXXXXXXXX` || {
+ /bin/echo "$prog: cannot create tmp dir"; exit 1
+ }
+ trap '/bin/rm -rf "$tmp"' 0
+ if /usr/bin/tail +$lines "$0" |
+ /usr/bin/gzip -dc > "$tmp/$prog" 2> /dev/null; then
+ /bin/chmod u+x "$tmp/$prog"
+ "$tmp/$prog" ${1+"$@"}
+ ret=$?
+ else
+ /bin/echo "$prog: cannot decompress $0"
+ ret=1
+ fi
+ exit $ret
+ EOF
+}
+
+# Test if a file is compressed by checking the magic line
+compressed () {
+ test "X`sed -n 2p "$1" 2> /dev/null`" = "X$magic"
+}
+
+# Decompress a file
+decompress () {
+ tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || {
+ echo "$prog: cannot create tmp file"
+ return 1
+ }
+ if ! cp "$1" "$tmp"; then
+ echo "$prog: cannot copy $1 to $tmp"
+ rm -f "$tmp"
+ return 1
+ fi
+ if ! tail +$lines "$tmp" | gzip -vdc > "$1"; then
+ echo "$prog: cannot decompress $1"
+ cp "$tmp" "$1"
+ rm -f "$tmp"
+ return 1
+ fi
+}
+
+# Perform some sanity checks on the file
+check () {
+ if test ! -e "$1"; then
+ echo "$prog: cannot compress non-existing file $1"
+ return 1
+ fi
+
+ if test ! -f "$1"; then
+ echo "$prog: cannot compress non-regular file $1"
+ return 1
+ fi
+
+ case `basename "$1"` in
+ sh | mktemp | rm | echo | tail | gzip | chmod)
+ echo "$prog: cannot compress $1, I depend on it"
+ return 1
+ esac
+
+ if test ! -x "$1"; then
+ echo "$prog: cannot compress $1, it is not executable"
+ return 1
+ fi
+
+ if test -u "$1" -o -g "$1"; then
+ echo "$prog: cannot compress $1, it has an s bit set"
+ return 1
+ fi
+}
+
+# Compress a file
+compress () {
+ tmp=`mktemp /tmp/gzexeXXXXXXXXXX` || {
+ echo "$prog: cannot create tmp file"
+ return 1
+ }
+ if ! cp "$1" "$tmp"; then
+ echo "$prog: cannot copy $1 to $tmp"
+ rm -f "$tmp"
+ return 1
+ fi
+ if ! cp "$1" "$1"~; then
+ echo "$prog: cannot create backup copy $1~"
+ rm -f "$1"~ "$tmp"
+ return 1
+ fi
+
+ # Use cp to overwrite the existing file preserving mode and owner
+ # if possible. If the file is not writable, this will produce an
+ # error.
+
+ if header "$1" > "$tmp" && gzip -vc "$1" >> "$tmp"; then
+ if ! cp "$tmp" "$1"; then
+ echo "$prog: cannot copy $tmp to $1"
+ rm -f "$tmp"
+ return 1
+ fi
+ else
+ echo "$prog: cannot compress $1"
+ rm -f "$1"~ "$tmp"
+ return 1
+ fi
+}
+
+# Is the -d flag specified?
+dflag=
+
+# Return value
+rc=0
+
+if test "X$1" = X-d; then
+ dflag=1
+ shift
+fi
+
+prog=`basename "$0"`
+USAGE="usage: $prog [-d] file ..."
+if test $# -eq 0; then
+ echo $USAGE
+ exit 1
+fi
+
+while test $# -ne 0; do
+ if test $dflag; then
+ if ! compressed "$1"; then
+ echo "$prog: $1 is not compressed"
+ rc=1;
+ elif ! decompress "$1"; then
+ rc=$?
+ fi
+ else
+ if compressed "$1"; then
+ echo "$prog: $1 is already compressed"
+ rc=1;
+ elif ! check "$1" || ! compress "$1"; then
+ rc=$?
+ fi
+ fi
+ shift
+done
+exit $rc
diff --git a/usr.bin/gzip/gzexe.1 b/usr.bin/gzip/gzexe.1
new file mode 100644
index 000000000000..7247714b1f05
--- /dev/null
+++ b/usr.bin/gzip/gzexe.1
@@ -0,0 +1,71 @@
+.\" $NetBSD: gzexe.1,v 1.3 2003/12/28 12:49:41 wiz Exp $
+.\" $OpenBSD: gzexe.1,v 1.1 2003/07/31 07:32:47 otto Exp $
+.\"
+.\" Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.Dd January 26, 2007
+.Dt GZEXE 1
+.Os
+.Sh NAME
+.Nm gzexe
+.Nd create auto-decompressing executables
+.Sh SYNOPSIS
+.Nm gzexe
+.Op Fl d
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility uses
+.Xr gzip 1
+to compress executables, producing executables that decompress on-the-fly
+when executed.
+This saves disk space, at the cost of slower execution times.
+The original executables are saved by copying each of them to a file with
+the same name with a
+.Sq ~
+suffix appended.
+After verifying that the compressed executables work as expected, the backup
+files can be removed.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d
+Decompress executables previously compressed by
+.Nm .
+.El
+.Pp
+The
+.Nm
+program refuses to compress non-regular or non-executable files,
+files with a setuid or setgid bit set, files that are already
+compressed using
+.Nm
+or programs it needs to perform on-the-fly decompression:
+.Xr sh 1 ,
+.Xr mktemp 1 ,
+.Xr rm 1 ,
+.Xr echo 1 ,
+.Xr tail 1 ,
+.Xr gzip 1 ,
+and
+.Xr chmod 1 .
+.Sh SEE ALSO
+.Xr gzip 1
+.Sh CAVEATS
+The
+.Nm
+utility replaces files by overwriting them with the generated
+compressed executable.
+To be able to do this, it is required that the original files are writable.
diff --git a/usr.bin/gzip/gzip.1 b/usr.bin/gzip/gzip.1
new file mode 100644
index 000000000000..86df53f59669
--- /dev/null
+++ b/usr.bin/gzip/gzip.1
@@ -0,0 +1,246 @@
+.\" $NetBSD: gzip.1,v 1.31 2018/10/26 22:10:15 christos Exp $
+.\"
+.\" Copyright (c) 1997, 2003, 2004, 2008, 2009, 2015, 2017 Matthew R. Green
+.\" 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.
+.\"
+.\" 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.
+.Dd November 2, 2022
+.Dt GZIP 1
+.Os
+.Sh NAME
+.Nm gzip ,
+.Nm gunzip ,
+.Nm zcat
+.Nd compression/decompression tool using Lempel-Ziv coding (LZ77)
+.Sh SYNOPSIS
+.Nm
+.Op Fl cdfhkLlNnqrtVv
+.Op Fl S Ar suffix
+.Ar file
+.Oo
+.Ar file Oo ...
+.Oc
+.Oc
+.Nm gunzip
+.Op Fl cfhkLNqrtVv
+.Op Fl S Ar suffix
+.Ar file
+.Oo
+.Ar file Oo ...
+.Oc
+.Oc
+.Nm zcat
+.Op Fl fhV
+.Ar file
+.Oo
+.Ar file Oo ...
+.Oc
+.Oc
+.Sh DESCRIPTION
+The
+.Nm
+program compresses and decompresses files using Lempel-Ziv coding
+(LZ77).
+If no
+.Ar files
+are specified,
+.Nm
+will compress from standard input, or decompress to standard output.
+When in compression mode, each
+.Ar file
+will be replaced with another file with the suffix, set by the
+.Fl S Ar suffix
+option, added, if possible.
+.Pp
+In decompression mode, each
+.Ar file
+will be checked for existence, as will the file with the suffix
+added.
+Each
+.Ar file
+argument must contain a separate complete archive;
+when multiple
+.Ar files
+are indicated, each is decompressed in turn.
+.Pp
+In the case of
+.Nm gzcat
+the resulting data is then concatenated in the manner of
+.Xr cat 1 .
+.Pp
+If invoked as
+.Nm gunzip
+then the
+.Fl d
+option is enabled.
+If invoked as
+.Nm zcat
+or
+.Nm gzcat
+then both the
+.Fl c
+and
+.Fl d
+options are enabled.
+.Pp
+This version of
+.Nm
+is also capable of decompressing files compressed using
+.Xr compress 1 ,
+.Xr bzip2 1 ,
+.Ar lzip ,
+.Xr zstd 1 ,
+or
+.Xr xz 1 .
+.Sh OPTIONS
+The following options are available:
+.Bl -tag -width XXrXXXrecursiveX
+.It Fl 1 , Fl Fl fast
+.It Fl 2 , 3 , 4 , 5 , 6 , 7 , 8
+.It Fl 9 , Fl Fl best
+These options change the compression level used, with the
+.Fl 1
+option being the fastest, with less compression, and the
+.Fl 9
+option being the slowest, with optimal compression.
+The default compression level is 6.
+.It Fl c , Fl Fl stdout , Fl Fl to-stdout
+This option specifies that output will go to the standard output
+stream, leaving files intact.
+.It Fl d , Fl Fl decompress , Fl Fl uncompress
+This option selects decompression rather than compression.
+.It Fl f , Fl Fl force
+This option turns on force mode.
+This allows files with multiple links, symbolic links to regular files,
+overwriting of pre-existing files, reading from or writing to a terminal,
+and when combined with the
+.Fl c
+option, allowing non-compressed data to pass through unchanged.
+.It Fl h , Fl Fl help
+This option prints a usage summary and exits.
+.It Fl k , Fl Fl keep
+This option prevents
+.Nm
+from deleting input files after (de)compression.
+.It Fl L , -license
+This option prints
+.Nm
+license.
+.It Fl l , Fl Fl list
+This option displays information about the file's compressed and
+uncompressed size, ratio, uncompressed name.
+With the
+.Fl v
+option, it also displays the compression method, CRC, date and time
+embedded in the file.
+.It Fl N , Fl Fl name
+This option causes the stored filename in the input file to be used
+as the output file.
+.It Fl n , Fl Fl no-name
+This option stops the filename and timestamp from being stored in
+the output file.
+.It Fl q , Fl Fl quiet
+With this option, no warnings or errors are printed.
+.It Fl r , Fl Fl recursive
+This option is used to
+.Nm
+the files in a directory tree individually, using the
+.Xr fts 3
+library.
+.It Fl S Ar suffix , Fl Fl suffix Ar suffix
+This option changes the default suffix from .gz to
+.Ar suffix .
+.It Fl t , Fl Fl test
+This option will test compressed files for integrity.
+.It Fl V , Fl Fl version
+This option prints the version of the
+.Nm
+program.
+.It Fl v , Fl Fl verbose
+This option turns on verbose mode, which prints the compression
+ratio for each file compressed.
+.El
+.Sh ENVIRONMENT
+If the environment variable
+.Ev GZIP
+is set, it is parsed as a white-space separated list of options
+handled before any options on the command line.
+Options on the command line will override anything in
+.Ev GZIP .
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success,
+1 on errors,
+and 2 if a warning occurs.
+.Sh SIGNALS
+.Nm
+responds to the following signals:
+.Bl -tag -width indent
+.It Dv SIGINFO
+Report progress to standard error.
+.El
+.Sh SEE ALSO
+.Xr bzip2 1 ,
+.Xr compress 1 ,
+.Xr xz 1 ,
+.Xr zstd 1 ,
+.Xr fts 3 ,
+.Xr zlib 3
+.Sh HISTORY
+The
+.Nm
+program was originally written by Jean-loup Gailly, licensed under
+the GNU Public Licence.
+Matthew R. Green wrote a simple front end for
+.Nx 1.3
+distribution media, based on the freely re-distributable zlib library.
+It was enhanced to be mostly feature-compatible with the original
+GNU
+.Nm
+program for
+.Nx 2.0 .
+.Pp
+This implementation of
+.Nm
+was ported based on the
+.Nx
+.Nm
+version 20181111,
+and first appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+.An -nosplit
+This implementation of
+.Nm
+was written by
+.An Matthew R. Green Aq Mt mrg@eterna.com.au
+with unpack support written by
+.An Xin LI Aq Mt delphij@FreeBSD.org .
+.Sh BUGS
+According to RFC 1952, the recorded file size is stored in a 32-bit
+integer, therefore, it cannot represent files larger than 4GB.
+This limitation also applies to
+.Fl l
+option of
+.Nm
+utility.
diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c
new file mode 100644
index 000000000000..fd8026af6a81
--- /dev/null
+++ b/usr.bin/gzip/gzip.c
@@ -0,0 +1,2261 @@
+/* $NetBSD: gzip.c,v 1.116 2018/10/27 11:39:12 skrll Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1997, 1998, 2003, 2004, 2006, 2008, 2009, 2010, 2011, 2015, 2017
+ * Matthew R. Green
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * gzip.c -- GPL free gzip using zlib.
+ *
+ * RFC 1950 covers the zlib format
+ * RFC 1951 covers the deflate format
+ * RFC 1952 covers the gzip format
+ *
+ * TODO:
+ * - use mmap where possible
+ * - make bzip2/compress -v/-t/-l support work as well as possible
+ */
+
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <zlib.h>
+#include <fts.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <time.h>
+
+/* what type of file are we dealing with */
+enum filetype {
+ FT_GZIP,
+#ifndef NO_BZIP2_SUPPORT
+ FT_BZIP2,
+#endif
+#ifndef NO_COMPRESS_SUPPORT
+ FT_Z,
+#endif
+#ifndef NO_PACK_SUPPORT
+ FT_PACK,
+#endif
+#ifndef NO_XZ_SUPPORT
+ FT_XZ,
+#endif
+#ifndef NO_LZ_SUPPORT
+ FT_LZ,
+#endif
+#ifndef NO_ZSTD_SUPPORT
+ FT_ZSTD,
+#endif
+ FT_LAST,
+ FT_UNKNOWN
+};
+
+#ifndef NO_BZIP2_SUPPORT
+#include <bzlib.h>
+
+#define BZ2_SUFFIX ".bz2"
+#define BZIP2_MAGIC "BZh"
+#endif
+
+#ifndef NO_COMPRESS_SUPPORT
+#define Z_SUFFIX ".Z"
+#define Z_MAGIC "\037\235"
+#endif
+
+#ifndef NO_PACK_SUPPORT
+#define PACK_MAGIC "\037\036"
+#endif
+
+#ifndef NO_XZ_SUPPORT
+#include <lzma.h>
+#define XZ_SUFFIX ".xz"
+#define XZ_MAGIC "\3757zXZ"
+#endif
+
+#ifndef NO_LZ_SUPPORT
+#define LZ_SUFFIX ".lz"
+#define LZ_MAGIC "LZIP"
+#endif
+
+#ifndef NO_ZSTD_SUPPORT
+#include <zstd.h>
+#define ZSTD_SUFFIX ".zst"
+#define ZSTD_MAGIC "\050\265\057\375"
+#endif
+
+#define GZ_SUFFIX ".gz"
+
+#define BUFLEN (64 * 1024)
+
+#define GZIP_MAGIC0 0x1F
+#define GZIP_MAGIC1 0x8B
+#define GZIP_OMAGIC1 0x9E
+
+#define GZIP_TIMESTAMP (off_t)4
+#define GZIP_ORIGNAME (off_t)10
+
+#define HEAD_CRC 0x02
+#define EXTRA_FIELD 0x04
+#define ORIG_NAME 0x08
+#define COMMENT 0x10
+
+#define OS_CODE 3 /* Unix */
+
+typedef struct {
+ const char *zipped;
+ int ziplen;
+ const char *normal; /* for unzip - must not be longer than zipped */
+} suffixes_t;
+static suffixes_t suffixes[] = {
+#define SUFFIX(Z, N) {Z, sizeof Z - 1, N}
+ SUFFIX(GZ_SUFFIX, ""), /* Overwritten by -S .xxx */
+ SUFFIX(GZ_SUFFIX, ""),
+ SUFFIX(".z", ""),
+ SUFFIX("-gz", ""),
+ SUFFIX("-z", ""),
+ SUFFIX("_z", ""),
+ SUFFIX(".taz", ".tar"),
+ SUFFIX(".tgz", ".tar"),
+#ifndef NO_BZIP2_SUPPORT
+ SUFFIX(BZ2_SUFFIX, ""),
+ SUFFIX(".tbz", ".tar"),
+ SUFFIX(".tbz2", ".tar"),
+#endif
+#ifndef NO_COMPRESS_SUPPORT
+ SUFFIX(Z_SUFFIX, ""),
+#endif
+#ifndef NO_XZ_SUPPORT
+ SUFFIX(XZ_SUFFIX, ""),
+#endif
+#ifndef NO_LZ_SUPPORT
+ SUFFIX(LZ_SUFFIX, ""),
+#endif
+#ifndef NO_ZSTD_SUPPORT
+ SUFFIX(ZSTD_SUFFIX, ""),
+#endif
+ SUFFIX(GZ_SUFFIX, ""), /* Overwritten by -S "" */
+#undef SUFFIX
+};
+#define NUM_SUFFIXES (nitems(suffixes))
+#define SUFFIX_MAXLEN 30
+
+static const char gzip_version[] = "FreeBSD gzip 20190107";
+
+static const char gzip_copyright[] = \
+" Copyright (c) 1997, 1998, 2003, 2004, 2006 Matthew R. Green\n"
+" All rights reserved.\n"
+"\n"
+" Redistribution and use in source and binary forms, with or without\n"
+" modification, are permitted provided that the following conditions\n"
+" are met:\n"
+" 1. Redistributions of source code must retain the above copyright\n"
+" notice, this list of conditions and the following disclaimer.\n"
+" 2. Redistributions in binary form must reproduce the above copyright\n"
+" notice, this list of conditions and the following disclaimer in the\n"
+" documentation and/or other materials provided with the distribution.\n"
+"\n"
+" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
+" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
+" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
+" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
+" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n"
+" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n"
+" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n"
+" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n"
+" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n"
+" SUCH DAMAGE.";
+
+static int cflag; /* stdout mode */
+static int dflag; /* decompress mode */
+static int lflag; /* list mode */
+static int numflag = 6; /* gzip -1..-9 value */
+
+static const char *remove_file = NULL; /* file to be removed upon SIGINT */
+
+static int fflag; /* force mode */
+static int kflag; /* don't delete input files */
+static int nflag; /* don't save name/timestamp */
+static int Nflag; /* don't restore name/timestamp */
+static int qflag; /* quiet mode */
+static int rflag; /* recursive mode */
+static int tflag; /* test */
+static int vflag; /* verbose mode */
+static sig_atomic_t print_info = 0;
+
+static int exit_value = 0; /* exit value */
+
+static const char *infile; /* name of file coming in */
+
+static void maybe_err(const char *fmt, ...) __printflike(1, 2) __dead2;
+#if !defined(NO_BZIP2_SUPPORT) || !defined(NO_PACK_SUPPORT) || \
+ !defined(NO_XZ_SUPPORT) || !defined(NO_ZSTD_SUPPORT)
+static void maybe_errx(const char *fmt, ...) __printflike(1, 2) __dead2;
+#endif
+static void maybe_warn(const char *fmt, ...) __printflike(1, 2);
+static void maybe_warnx(const char *fmt, ...) __printflike(1, 2);
+static enum filetype file_gettype(u_char *);
+static off_t gz_compress(int, int, off_t *, const char *, uint32_t);
+static off_t gz_uncompress(int, int, char *, size_t, off_t *, const char *);
+static off_t file_compress(char *, char *, size_t);
+static off_t file_uncompress(char *, char *, size_t);
+static void handle_pathname(char *);
+static void handle_file(char *, struct stat *);
+static void handle_stdin(void);
+static void handle_stdout(void);
+static void print_ratio(off_t, off_t, FILE *);
+static void print_list(int fd, off_t, const char *, time_t);
+static void usage(void) __dead2;
+static void display_version(void) __dead2;
+static void display_license(void);
+static const suffixes_t *check_suffix(char *, int);
+static ssize_t read_retry(int, void *, size_t);
+static ssize_t write_retry(int, const void *, size_t);
+static void print_list_out(off_t, off_t, const char*);
+
+static void infile_set(const char *newinfile, off_t total);
+
+static off_t infile_total; /* total expected to read/write */
+static off_t infile_current; /* current read/write */
+
+static void check_siginfo(void);
+static off_t cat_fd(unsigned char *, size_t, off_t *, int fd);
+static void prepend_gzip(char *, int *, char ***);
+static void handle_dir(char *);
+static void print_verbage(const char *, const char *, off_t, off_t);
+static void print_test(const char *, int);
+static void copymodes(int fd, const struct stat *, const char *file);
+static int check_outfile(const char *outfile);
+static void setup_signals(void);
+static void infile_newdata(size_t newdata);
+static void infile_clear(void);
+
+#ifndef NO_BZIP2_SUPPORT
+static off_t unbzip2(int, int, char *, size_t, off_t *);
+#endif
+
+#ifndef NO_COMPRESS_SUPPORT
+static FILE *zdopen(int);
+static off_t zuncompress(FILE *, FILE *, char *, size_t, off_t *);
+#endif
+
+#ifndef NO_PACK_SUPPORT
+static off_t unpack(int, int, char *, size_t, off_t *);
+#endif
+
+#ifndef NO_XZ_SUPPORT
+static off_t unxz(int, int, char *, size_t, off_t *);
+static off_t unxz_len(int);
+#endif
+
+#ifndef NO_LZ_SUPPORT
+static off_t unlz(int, int, char *, size_t, off_t *);
+#endif
+
+#ifndef NO_ZSTD_SUPPORT
+static off_t unzstd(int, int, char *, size_t, off_t *);
+#endif
+
+static const struct option longopts[] = {
+ { "stdout", no_argument, 0, 'c' },
+ { "to-stdout", no_argument, 0, 'c' },
+ { "decompress", no_argument, 0, 'd' },
+ { "uncompress", no_argument, 0, 'd' },
+ { "force", no_argument, 0, 'f' },
+ { "help", no_argument, 0, 'h' },
+ { "keep", no_argument, 0, 'k' },
+ { "list", no_argument, 0, 'l' },
+ { "no-name", no_argument, 0, 'n' },
+ { "name", no_argument, 0, 'N' },
+ { "quiet", no_argument, 0, 'q' },
+ { "recursive", no_argument, 0, 'r' },
+ { "suffix", required_argument, 0, 'S' },
+ { "test", no_argument, 0, 't' },
+ { "verbose", no_argument, 0, 'v' },
+ { "version", no_argument, 0, 'V' },
+ { "fast", no_argument, 0, '1' },
+ { "best", no_argument, 0, '9' },
+ { "ascii", no_argument, 0, 'a' },
+ { "license", no_argument, 0, 'L' },
+ { NULL, no_argument, 0, 0 },
+};
+
+int
+main(int argc, char **argv)
+{
+ const char *progname = getprogname();
+ char *gzip;
+ int len;
+ int ch;
+
+ setup_signals();
+
+ if ((gzip = getenv("GZIP")) != NULL)
+ prepend_gzip(gzip, &argc, &argv);
+
+ /*
+ * XXX
+ * handle being called `gunzip', `zcat' and `gzcat'
+ */
+ if (strcmp(progname, "gunzip") == 0)
+ dflag = 1;
+ else if (strcmp(progname, "zcat") == 0 ||
+ strcmp(progname, "gzcat") == 0)
+ dflag = cflag = 1;
+
+#define OPT_LIST "123456789acdfhklLNnqrS:tVv"
+
+ while ((ch = getopt_long(argc, argv, OPT_LIST, longopts, NULL)) != -1) {
+ switch (ch) {
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ numflag = ch - '0';
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ dflag = 1;
+ break;
+ case 'V':
+ display_version();
+ /* NOTREACHED */
+ case 'a':
+ fprintf(stderr, "%s: option --ascii ignored on this system\n", progname);
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'L':
+ display_license();
+ /* NOT REACHED */
+ case 'N':
+ nflag = 0;
+ Nflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ Nflag = 0;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'S':
+ len = strlen(optarg);
+ if (len != 0) {
+ if (len > SUFFIX_MAXLEN)
+ errx(1, "incorrect suffix: '%s': too long", optarg);
+ suffixes[0].zipped = optarg;
+ suffixes[0].ziplen = len;
+ } else {
+ suffixes[NUM_SUFFIXES - 1].zipped = "";
+ suffixes[NUM_SUFFIXES - 1].ziplen = 0;
+ }
+ break;
+ case 't':
+ cflag = 1;
+ tflag = 1;
+ dflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc == 0) {
+ if (dflag) /* stdin mode */
+ handle_stdin();
+ else /* stdout mode */
+ handle_stdout();
+ } else {
+ do {
+ handle_pathname(argv[0]);
+ } while (*++argv);
+ }
+ if (qflag == 0 && lflag && argc > 1)
+ print_list(-1, 0, "(totals)", 0);
+ exit(exit_value);
+}
+
+/* maybe print a warning */
+void
+maybe_warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (qflag == 0) {
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+ }
+ if (exit_value == 0)
+ exit_value = 1;
+}
+
+/* ... without an errno. */
+void
+maybe_warnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (qflag == 0) {
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ }
+ if (exit_value == 0)
+ exit_value = 1;
+}
+
+/* maybe print an error */
+void
+maybe_err(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (qflag == 0) {
+ va_start(ap, fmt);
+ vwarn(fmt, ap);
+ va_end(ap);
+ }
+ exit(2);
+}
+
+#if !defined(NO_BZIP2_SUPPORT) || !defined(NO_PACK_SUPPORT) || \
+ !defined(NO_XZ_SUPPORT) || !defined(NO_ZSTD_SUPPORT)
+/* ... without an errno. */
+void
+maybe_errx(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (qflag == 0) {
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ }
+ exit(2);
+}
+#endif
+
+/* split up $GZIP and prepend it to the argument list */
+static void
+prepend_gzip(char *gzip, int *argc, char ***argv)
+{
+ char *s, **nargv, **ac;
+ int nenvarg = 0, i;
+
+ /* scan how many arguments there are */
+ for (s = gzip;;) {
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == 0)
+ goto count_done;
+ nenvarg++;
+ while (*s != ' ' && *s != '\t')
+ if (*s++ == 0)
+ goto count_done;
+ }
+count_done:
+ /* punt early */
+ if (nenvarg == 0)
+ return;
+
+ *argc += nenvarg;
+ ac = *argv;
+
+ nargv = (char **)malloc((*argc + 1) * sizeof(char *));
+ if (nargv == NULL)
+ maybe_err("malloc");
+
+ /* stash this away */
+ *argv = nargv;
+
+ /* copy the program name first */
+ i = 0;
+ nargv[i++] = *(ac++);
+
+ /* take a copy of $GZIP and add it to the array */
+ s = strdup(gzip);
+ if (s == NULL)
+ maybe_err("strdup");
+ for (;;) {
+ /* Skip whitespaces. */
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == 0)
+ goto copy_done;
+ nargv[i++] = s;
+ /* Find the end of this argument. */
+ while (*s != ' ' && *s != '\t')
+ if (*s++ == 0)
+ /* Argument followed by NUL. */
+ goto copy_done;
+ /* Terminate by overwriting ' ' or '\t' with NUL. */
+ *s++ = 0;
+ }
+copy_done:
+
+ /* copy the original arguments and a NULL */
+ while (*ac)
+ nargv[i++] = *(ac++);
+ nargv[i] = NULL;
+}
+
+/* compress input to output. Return bytes read, -1 on error */
+static off_t
+gz_compress(int in, int out, off_t *gsizep, const char *origname, uint32_t mtime)
+{
+ z_stream z;
+ char *outbufp, *inbufp;
+ off_t in_tot = 0, out_tot = 0;
+ ssize_t in_size;
+ int i, error;
+ uLong crc;
+
+ outbufp = malloc(BUFLEN);
+ inbufp = malloc(BUFLEN);
+ if (outbufp == NULL || inbufp == NULL) {
+ maybe_err("malloc failed");
+ goto out;
+ }
+
+ memset(&z, 0, sizeof z);
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = 0;
+
+ if (nflag != 0) {
+ mtime = 0;
+ origname = "";
+ }
+
+ i = snprintf(outbufp, BUFLEN, "%c%c%c%c%c%c%c%c%c%c%s",
+ GZIP_MAGIC0, GZIP_MAGIC1, Z_DEFLATED,
+ *origname ? ORIG_NAME : 0,
+ mtime & 0xff,
+ (mtime >> 8) & 0xff,
+ (mtime >> 16) & 0xff,
+ (mtime >> 24) & 0xff,
+ numflag == 1 ? 4 : numflag == 9 ? 2 : 0,
+ OS_CODE, origname);
+ if (i >= BUFLEN)
+ /* this need PATH_MAX > BUFLEN ... */
+ maybe_err("snprintf");
+ if (*origname)
+ i++;
+
+ z.next_out = (unsigned char *)outbufp + i;
+ z.avail_out = BUFLEN - i;
+
+ error = deflateInit2(&z, numflag, Z_DEFLATED,
+ (-MAX_WBITS), 8, Z_DEFAULT_STRATEGY);
+ if (error != Z_OK) {
+ maybe_warnx("deflateInit2 failed");
+ in_tot = -1;
+ goto out;
+ }
+
+ crc = crc32(0L, Z_NULL, 0);
+ for (;;) {
+ if (z.avail_out == 0) {
+ if (write_retry(out, outbufp, BUFLEN) != BUFLEN) {
+ maybe_warn("write");
+ out_tot = -1;
+ goto out;
+ }
+
+ out_tot += BUFLEN;
+ z.next_out = (unsigned char *)outbufp;
+ z.avail_out = BUFLEN;
+ }
+
+ if (z.avail_in == 0) {
+ in_size = read(in, inbufp, BUFLEN);
+ if (in_size < 0) {
+ maybe_warn("read");
+ in_tot = -1;
+ goto out;
+ }
+ if (in_size == 0)
+ break;
+ infile_newdata(in_size);
+
+ crc = crc32(crc, (const Bytef *)inbufp, (unsigned)in_size);
+ in_tot += in_size;
+ z.next_in = (unsigned char *)inbufp;
+ z.avail_in = in_size;
+ }
+
+ error = deflate(&z, Z_NO_FLUSH);
+ if (error != Z_OK && error != Z_STREAM_END) {
+ maybe_warnx("deflate failed");
+ in_tot = -1;
+ goto out;
+ }
+ }
+
+ /* clean up */
+ for (;;) {
+ size_t len;
+ ssize_t w;
+
+ error = deflate(&z, Z_FINISH);
+ if (error != Z_OK && error != Z_STREAM_END) {
+ maybe_warnx("deflate failed");
+ in_tot = -1;
+ goto out;
+ }
+
+ len = (char *)z.next_out - outbufp;
+
+ w = write_retry(out, outbufp, len);
+ if (w == -1 || (size_t)w != len) {
+ maybe_warn("write");
+ out_tot = -1;
+ goto out;
+ }
+ out_tot += len;
+ z.next_out = (unsigned char *)outbufp;
+ z.avail_out = BUFLEN;
+
+ if (error == Z_STREAM_END)
+ break;
+ }
+
+ if (deflateEnd(&z) != Z_OK) {
+ maybe_warnx("deflateEnd failed");
+ in_tot = -1;
+ goto out;
+ }
+
+ i = snprintf(outbufp, BUFLEN, "%c%c%c%c%c%c%c%c",
+ (int)crc & 0xff,
+ (int)(crc >> 8) & 0xff,
+ (int)(crc >> 16) & 0xff,
+ (int)(crc >> 24) & 0xff,
+ (int)in_tot & 0xff,
+ (int)(in_tot >> 8) & 0xff,
+ (int)(in_tot >> 16) & 0xff,
+ (int)(in_tot >> 24) & 0xff);
+ if (i != 8)
+ maybe_err("snprintf");
+ if (write_retry(out, outbufp, i) != i) {
+ maybe_warn("write");
+ in_tot = -1;
+ } else
+ out_tot += i;
+
+out:
+ if (inbufp != NULL)
+ free(inbufp);
+ if (outbufp != NULL)
+ free(outbufp);
+ if (gsizep)
+ *gsizep = out_tot;
+ return in_tot;
+}
+
+/*
+ * uncompress input to output then close the input. return the
+ * uncompressed size written, and put the compressed sized read
+ * into `*gsizep'.
+ */
+static off_t
+gz_uncompress(int in, int out, char *pre, size_t prelen, off_t *gsizep,
+ const char *filename)
+{
+ z_stream z;
+ char *outbufp, *inbufp;
+ off_t out_tot = -1, in_tot = 0;
+ uint32_t out_sub_tot = 0;
+ enum {
+ GZSTATE_MAGIC0,
+ GZSTATE_MAGIC1,
+ GZSTATE_METHOD,
+ GZSTATE_FLAGS,
+ GZSTATE_SKIPPING,
+ GZSTATE_EXTRA,
+ GZSTATE_EXTRA2,
+ GZSTATE_EXTRA3,
+ GZSTATE_ORIGNAME,
+ GZSTATE_COMMENT,
+ GZSTATE_HEAD_CRC1,
+ GZSTATE_HEAD_CRC2,
+ GZSTATE_INIT,
+ GZSTATE_READ,
+ GZSTATE_CRC,
+ GZSTATE_LEN,
+ } state = GZSTATE_MAGIC0;
+ int flags = 0, skip_count = 0;
+ int error = Z_STREAM_ERROR, done_reading = 0;
+ uLong crc = 0;
+ ssize_t wr;
+ int needmore = 0;
+
+#define ADVANCE() { z.next_in++; z.avail_in--; }
+
+ if ((outbufp = malloc(BUFLEN)) == NULL) {
+ maybe_err("malloc failed");
+ goto out2;
+ }
+ if ((inbufp = malloc(BUFLEN)) == NULL) {
+ maybe_err("malloc failed");
+ goto out1;
+ }
+
+ memset(&z, 0, sizeof z);
+ z.avail_in = prelen;
+ z.next_in = (unsigned char *)pre;
+ z.avail_out = BUFLEN;
+ z.next_out = (unsigned char *)outbufp;
+ z.zalloc = NULL;
+ z.zfree = NULL;
+ z.opaque = 0;
+
+ in_tot = prelen;
+ out_tot = 0;
+
+ for (;;) {
+ check_siginfo();
+ if ((z.avail_in == 0 || needmore) && done_reading == 0) {
+ ssize_t in_size;
+
+ if (z.avail_in > 0) {
+ memmove(inbufp, z.next_in, z.avail_in);
+ }
+ z.next_in = (unsigned char *)inbufp;
+ in_size = read(in, z.next_in + z.avail_in,
+ BUFLEN - z.avail_in);
+
+ if (in_size == -1) {
+ maybe_warn("failed to read stdin");
+ goto stop_and_fail;
+ } else if (in_size == 0) {
+ done_reading = 1;
+ }
+ infile_newdata(in_size);
+
+ z.avail_in += in_size;
+ needmore = 0;
+
+ in_tot += in_size;
+ }
+ if (z.avail_in == 0) {
+ if (done_reading && state != GZSTATE_MAGIC0) {
+ maybe_warnx("%s: unexpected end of file",
+ filename);
+ goto stop_and_fail;
+ }
+ goto stop;
+ }
+ switch (state) {
+ case GZSTATE_MAGIC0:
+ if (*z.next_in != GZIP_MAGIC0) {
+ if (in_tot > 0) {
+ maybe_warnx("%s: trailing garbage "
+ "ignored", filename);
+ exit_value = 2;
+ goto stop;
+ }
+ maybe_warnx("input not gziped (MAGIC0)");
+ goto stop_and_fail;
+ }
+ ADVANCE();
+ state++;
+ out_sub_tot = 0;
+ crc = crc32(0L, Z_NULL, 0);
+ break;
+
+ case GZSTATE_MAGIC1:
+ if (*z.next_in != GZIP_MAGIC1 &&
+ *z.next_in != GZIP_OMAGIC1) {
+ maybe_warnx("input not gziped (MAGIC1)");
+ goto stop_and_fail;
+ }
+ ADVANCE();
+ state++;
+ break;
+
+ case GZSTATE_METHOD:
+ if (*z.next_in != Z_DEFLATED) {
+ maybe_warnx("unknown compression method");
+ goto stop_and_fail;
+ }
+ ADVANCE();
+ state++;
+ break;
+
+ case GZSTATE_FLAGS:
+ flags = *z.next_in;
+ ADVANCE();
+ skip_count = 6;
+ state++;
+ break;
+
+ case GZSTATE_SKIPPING:
+ if (skip_count > 0) {
+ skip_count--;
+ ADVANCE();
+ } else
+ state++;
+ break;
+
+ case GZSTATE_EXTRA:
+ if ((flags & EXTRA_FIELD) == 0) {
+ state = GZSTATE_ORIGNAME;
+ break;
+ }
+ skip_count = *z.next_in;
+ ADVANCE();
+ state++;
+ break;
+
+ case GZSTATE_EXTRA2:
+ skip_count |= ((*z.next_in) << 8);
+ ADVANCE();
+ state++;
+ break;
+
+ case GZSTATE_EXTRA3:
+ if (skip_count > 0) {
+ skip_count--;
+ ADVANCE();
+ } else
+ state++;
+ break;
+
+ case GZSTATE_ORIGNAME:
+ if ((flags & ORIG_NAME) == 0) {
+ state++;
+ break;
+ }
+ if (*z.next_in == 0)
+ state++;
+ ADVANCE();
+ break;
+
+ case GZSTATE_COMMENT:
+ if ((flags & COMMENT) == 0) {
+ state++;
+ break;
+ }
+ if (*z.next_in == 0)
+ state++;
+ ADVANCE();
+ break;
+
+ case GZSTATE_HEAD_CRC1:
+ if (flags & HEAD_CRC)
+ skip_count = 2;
+ else
+ skip_count = 0;
+ state++;
+ break;
+
+ case GZSTATE_HEAD_CRC2:
+ if (skip_count > 0) {
+ skip_count--;
+ ADVANCE();
+ } else
+ state++;
+ break;
+
+ case GZSTATE_INIT:
+ if (inflateInit2(&z, -MAX_WBITS) != Z_OK) {
+ maybe_warnx("failed to inflateInit");
+ goto stop_and_fail;
+ }
+ state++;
+ break;
+
+ case GZSTATE_READ:
+ error = inflate(&z, Z_FINISH);
+ switch (error) {
+ /* Z_BUF_ERROR goes with Z_FINISH... */
+ case Z_BUF_ERROR:
+ if (z.avail_out > 0 && !done_reading)
+ continue;
+
+ case Z_STREAM_END:
+ case Z_OK:
+ break;
+
+ case Z_NEED_DICT:
+ maybe_warnx("Z_NEED_DICT error");
+ goto stop_and_fail;
+ case Z_DATA_ERROR:
+ maybe_warnx("data stream error");
+ goto stop_and_fail;
+ case Z_STREAM_ERROR:
+ maybe_warnx("internal stream error");
+ goto stop_and_fail;
+ case Z_MEM_ERROR:
+ maybe_warnx("memory allocation error");
+ goto stop_and_fail;
+
+ default:
+ maybe_warn("unknown error from inflate(): %d",
+ error);
+ }
+ wr = BUFLEN - z.avail_out;
+
+ if (wr != 0) {
+ crc = crc32(crc, (const Bytef *)outbufp, (unsigned)wr);
+ if (
+ /* don't write anything with -t */
+ tflag == 0 &&
+ write_retry(out, outbufp, wr) != wr) {
+ maybe_warn("error writing to output");
+ goto stop_and_fail;
+ }
+
+ out_tot += wr;
+ out_sub_tot += wr;
+ }
+
+ if (error == Z_STREAM_END) {
+ inflateEnd(&z);
+ state++;
+ }
+
+ z.next_out = (unsigned char *)outbufp;
+ z.avail_out = BUFLEN;
+
+ break;
+ case GZSTATE_CRC:
+ {
+ uLong origcrc;
+
+ if (z.avail_in < 4) {
+ if (!done_reading) {
+ needmore = 1;
+ continue;
+ }
+ maybe_warnx("truncated input");
+ goto stop_and_fail;
+ }
+ origcrc = le32dec(&z.next_in[0]);
+ if (origcrc != crc) {
+ maybe_warnx("invalid compressed"
+ " data--crc error");
+ goto stop_and_fail;
+ }
+ }
+
+ z.avail_in -= 4;
+ z.next_in += 4;
+
+ if (!z.avail_in && done_reading) {
+ goto stop;
+ }
+ state++;
+ break;
+ case GZSTATE_LEN:
+ {
+ uLong origlen;
+
+ if (z.avail_in < 4) {
+ if (!done_reading) {
+ needmore = 1;
+ continue;
+ }
+ maybe_warnx("truncated input");
+ goto stop_and_fail;
+ }
+ origlen = le32dec(&z.next_in[0]);
+
+ if (origlen != out_sub_tot) {
+ maybe_warnx("invalid compressed"
+ " data--length error");
+ goto stop_and_fail;
+ }
+ }
+
+ z.avail_in -= 4;
+ z.next_in += 4;
+
+ if (error < 0) {
+ maybe_warnx("decompression error");
+ goto stop_and_fail;
+ }
+ state = GZSTATE_MAGIC0;
+ break;
+ }
+ continue;
+stop_and_fail:
+ out_tot = -1;
+stop:
+ break;
+ }
+ if (state > GZSTATE_INIT)
+ inflateEnd(&z);
+
+ free(inbufp);
+out1:
+ free(outbufp);
+out2:
+ if (gsizep)
+ *gsizep = in_tot;
+ return (out_tot);
+}
+
+/*
+ * set the owner, mode, flags & utimes using the given file descriptor.
+ * file is only used in possible warning messages.
+ */
+static void
+copymodes(int fd, const struct stat *sbp, const char *file)
+{
+ struct timespec times[2];
+ struct stat sb;
+
+ /*
+ * If we have no info on the input, give this file some
+ * default values and return..
+ */
+ if (sbp == NULL) {
+ mode_t mask = umask(022);
+
+ (void)fchmod(fd, DEFFILEMODE & ~mask);
+ (void)umask(mask);
+ return;
+ }
+ sb = *sbp;
+
+ /* if the chown fails, remove set-id bits as-per compress(1) */
+ if (fchown(fd, sb.st_uid, sb.st_gid) < 0) {
+ if (errno != EPERM)
+ maybe_warn("couldn't fchown: %s", file);
+ sb.st_mode &= ~(S_ISUID|S_ISGID);
+ }
+
+ /* we only allow set-id and the 9 normal permission bits */
+ sb.st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
+ if (fchmod(fd, sb.st_mode) < 0)
+ maybe_warn("couldn't fchmod: %s", file);
+
+ times[0] = sb.st_atim;
+ times[1] = sb.st_mtim;
+ if (futimens(fd, times) < 0)
+ maybe_warn("couldn't futimens: %s", file);
+
+ /* only try flags if they exist already */
+ if (sb.st_flags != 0 && fchflags(fd, sb.st_flags) < 0)
+ maybe_warn("couldn't fchflags: %s", file);
+}
+
+/* what sort of file is this? */
+static enum filetype
+file_gettype(u_char *buf)
+{
+
+ if (buf[0] == GZIP_MAGIC0 &&
+ (buf[1] == GZIP_MAGIC1 || buf[1] == GZIP_OMAGIC1))
+ return FT_GZIP;
+#ifndef NO_BZIP2_SUPPORT
+ else if (memcmp(buf, BZIP2_MAGIC, 3) == 0 &&
+ buf[3] >= '0' && buf[3] <= '9')
+ return FT_BZIP2;
+#endif
+#ifndef NO_COMPRESS_SUPPORT
+ else if (memcmp(buf, Z_MAGIC, 2) == 0)
+ return FT_Z;
+#endif
+#ifndef NO_PACK_SUPPORT
+ else if (memcmp(buf, PACK_MAGIC, 2) == 0)
+ return FT_PACK;
+#endif
+#ifndef NO_XZ_SUPPORT
+ else if (memcmp(buf, XZ_MAGIC, 4) == 0) /* XXX: We only have 4 bytes */
+ return FT_XZ;
+#endif
+#ifndef NO_LZ_SUPPORT
+ else if (memcmp(buf, LZ_MAGIC, 4) == 0)
+ return FT_LZ;
+#endif
+#ifndef NO_ZSTD_SUPPORT
+ else if (memcmp(buf, ZSTD_MAGIC, 4) == 0)
+ return FT_ZSTD;
+#endif
+ else
+ return FT_UNKNOWN;
+}
+
+/* check the outfile is OK. */
+static int
+check_outfile(const char *outfile)
+{
+ struct stat sb;
+ int ok = 1;
+
+ if (lflag == 0 && stat(outfile, &sb) == 0) {
+ if (fflag)
+ unlink(outfile);
+ else if (isatty(STDIN_FILENO)) {
+ char ans[10] = { 'n', '\0' }; /* default */
+
+ fprintf(stderr, "%s already exists -- do you wish to "
+ "overwrite (y or n)? " , outfile);
+ (void)fgets(ans, sizeof(ans) - 1, stdin);
+ if (ans[0] != 'y' && ans[0] != 'Y') {
+ fprintf(stderr, "\tnot overwriting\n");
+ ok = 0;
+ } else
+ unlink(outfile);
+ } else {
+ maybe_warnx("%s already exists -- skipping", outfile);
+ ok = 0;
+ }
+ }
+ return ok;
+}
+
+static void
+unlink_input(const char *file, const struct stat *sb)
+{
+ struct stat nsb;
+
+ if (kflag)
+ return;
+ if (stat(file, &nsb) != 0)
+ /* Must be gone already */
+ return;
+ if (nsb.st_dev != sb->st_dev || nsb.st_ino != sb->st_ino)
+ /* Definitely a different file */
+ return;
+ unlink(file);
+}
+
+static void
+got_sigint(int signo __unused)
+{
+
+ if (remove_file != NULL)
+ unlink(remove_file);
+ _exit(2);
+}
+
+static void
+got_siginfo(int signo __unused)
+{
+
+ print_info = 1;
+}
+
+static void
+setup_signals(void)
+{
+
+ signal(SIGINFO, got_siginfo);
+ signal(SIGINT, got_sigint);
+}
+
+static void
+infile_newdata(size_t newdata)
+{
+
+ infile_current += newdata;
+}
+
+static void
+infile_set(const char *newinfile, off_t total)
+{
+
+ if (newinfile)
+ infile = newinfile;
+ infile_total = total;
+}
+
+static void
+infile_clear(void)
+{
+
+ infile = NULL;
+ infile_total = infile_current = 0;
+}
+
+static const suffixes_t *
+check_suffix(char *file, int xlate)
+{
+ const suffixes_t *s;
+ int len = strlen(file);
+ char *sp;
+
+ for (s = suffixes; s != suffixes + NUM_SUFFIXES; s++) {
+ /* if it doesn't fit in "a.suf", don't bother */
+ if (s->ziplen >= len)
+ continue;
+ sp = file + len - s->ziplen;
+ if (strcmp(s->zipped, sp) != 0)
+ continue;
+ if (xlate)
+ strcpy(sp, s->normal);
+ return s;
+ }
+ return NULL;
+}
+
+/*
+ * compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+static off_t
+file_compress(char *file, char *outfile, size_t outsize)
+{
+ int in;
+ int out;
+ off_t size, in_size;
+ struct stat isb, osb;
+ const suffixes_t *suff;
+
+ in = open(file, O_RDONLY);
+ if (in == -1) {
+ maybe_warn("can't open %s", file);
+ return (-1);
+ }
+
+ if (fstat(in, &isb) != 0) {
+ maybe_warn("couldn't stat: %s", file);
+ close(in);
+ return (-1);
+ }
+
+ if (fstat(in, &isb) != 0) {
+ close(in);
+ maybe_warn("can't stat %s", file);
+ return -1;
+ }
+ infile_set(file, isb.st_size);
+
+ if (cflag == 0) {
+ if (isb.st_nlink > 1 && fflag == 0) {
+ maybe_warnx("%s has %ju other link%s -- "
+ "skipping", file,
+ (uintmax_t)isb.st_nlink - 1,
+ isb.st_nlink == 1 ? "" : "s");
+ close(in);
+ return -1;
+ }
+
+ if (fflag == 0 && (suff = check_suffix(file, 0)) &&
+ suff->zipped[0] != 0) {
+ maybe_warnx("%s already has %s suffix -- unchanged",
+ file, suff->zipped);
+ close(in);
+ return (-1);
+ }
+
+ /* Add (usually) .gz to filename */
+ if ((size_t)snprintf(outfile, outsize, "%s%s",
+ file, suffixes[0].zipped) >= outsize)
+ memcpy(outfile + outsize - suffixes[0].ziplen - 1,
+ suffixes[0].zipped, suffixes[0].ziplen + 1);
+
+ if (check_outfile(outfile) == 0) {
+ close(in);
+ return (-1);
+ }
+ }
+
+ if (cflag == 0) {
+ out = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (out == -1) {
+ maybe_warn("could not create output: %s", outfile);
+ fclose(stdin);
+ return (-1);
+ }
+ remove_file = outfile;
+ } else
+ out = STDOUT_FILENO;
+
+ in_size = gz_compress(in, out, &size, basename(file), (uint32_t)isb.st_mtime);
+
+ (void)close(in);
+
+ /*
+ * If there was an error, in_size will be -1.
+ * If we compressed to stdout, just return the size.
+ * Otherwise stat the file and check it is the correct size.
+ * We only blow away the file if we can stat the output and it
+ * has the expected size.
+ */
+ if (cflag != 0)
+ return in_size == -1 ? -1 : size;
+
+ if (fstat(out, &osb) != 0) {
+ maybe_warn("couldn't stat: %s", outfile);
+ goto bad_outfile;
+ }
+
+ if (osb.st_size != size) {
+ maybe_warnx("output file: %s wrong size (%ju != %ju), deleting",
+ outfile, (uintmax_t)osb.st_size, (uintmax_t)size);
+ goto bad_outfile;
+ }
+
+ copymodes(out, &isb, outfile);
+ remove_file = NULL;
+ if (close(out) == -1)
+ maybe_warn("couldn't close output");
+
+ /* output is good, ok to delete input */
+ unlink_input(file, &isb);
+ return (size);
+
+ bad_outfile:
+ if (close(out) == -1)
+ maybe_warn("couldn't close output");
+
+ maybe_warnx("leaving original %s", file);
+ unlink(outfile);
+ return (size);
+}
+
+/* uncompress the given file and remove the original */
+static off_t
+file_uncompress(char *file, char *outfile, size_t outsize)
+{
+ struct stat isb, osb;
+ off_t size;
+ ssize_t rbytes;
+ unsigned char fourbytes[4];
+ enum filetype method;
+ int fd, ofd, zfd = -1;
+ int error;
+ size_t in_size;
+ ssize_t rv;
+ time_t timestamp = 0;
+ char name[PATH_MAX + 1];
+
+ /* gather the old name info */
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ maybe_warn("can't open %s", file);
+ goto lose;
+ }
+ if (fstat(fd, &isb) != 0) {
+ maybe_warn("can't stat %s", file);
+ goto lose;
+ }
+ if (S_ISREG(isb.st_mode))
+ in_size = isb.st_size;
+ else
+ in_size = 0;
+ infile_set(file, in_size);
+
+ strlcpy(outfile, file, outsize);
+ if (check_suffix(outfile, 1) == NULL && !(cflag || lflag)) {
+ maybe_warnx("%s: unknown suffix -- ignored", file);
+ goto lose;
+ }
+
+ rbytes = read(fd, fourbytes, sizeof fourbytes);
+ if (rbytes != sizeof fourbytes) {
+ /* we don't want to fail here. */
+ if (fflag)
+ goto lose;
+ if (rbytes == -1)
+ maybe_warn("can't read %s", file);
+ else
+ goto unexpected_EOF;
+ goto lose;
+ }
+ infile_newdata(rbytes);
+
+ method = file_gettype(fourbytes);
+ if (fflag == 0 && method == FT_UNKNOWN) {
+ maybe_warnx("%s: not in gzip format", file);
+ goto lose;
+ }
+
+
+ if (method == FT_GZIP && Nflag) {
+ unsigned char ts[4]; /* timestamp */
+
+ rv = pread(fd, ts, sizeof ts, GZIP_TIMESTAMP);
+ if (rv >= 0 && rv < (ssize_t)(sizeof ts))
+ goto unexpected_EOF;
+ if (rv == -1) {
+ if (!fflag)
+ maybe_warn("can't read %s", file);
+ goto lose;
+ }
+ infile_newdata(rv);
+ timestamp = le32dec(&ts[0]);
+
+ if (fourbytes[3] & ORIG_NAME) {
+ rbytes = pread(fd, name, sizeof(name) - 1, GZIP_ORIGNAME);
+ if (rbytes < 0) {
+ maybe_warn("can't read %s", file);
+ goto lose;
+ }
+ if (name[0] != '\0') {
+ char *dp, *nf;
+
+ /* Make sure that name is NUL-terminated */
+ name[rbytes] = '\0';
+
+ /* strip saved directory name */
+ nf = strrchr(name, '/');
+ if (nf == NULL)
+ nf = name;
+ else
+ nf++;
+
+ /* preserve original directory name */
+ dp = strrchr(file, '/');
+ if (dp == NULL)
+ dp = file;
+ else
+ dp++;
+ snprintf(outfile, outsize, "%.*s%.*s",
+ (int) (dp - file),
+ file, (int) rbytes, nf);
+ }
+ }
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ if (cflag == 0 || lflag) {
+ if (isb.st_nlink > 1 && lflag == 0 && fflag == 0) {
+ maybe_warnx("%s has %ju other links -- skipping",
+ file, (uintmax_t)isb.st_nlink - 1);
+ goto lose;
+ }
+ if (nflag == 0 && timestamp)
+ isb.st_mtime = timestamp;
+ if (check_outfile(outfile) == 0)
+ goto lose;
+ }
+
+ if (cflag)
+ zfd = STDOUT_FILENO;
+ else if (lflag)
+ zfd = -1;
+ else {
+ zfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0600);
+ if (zfd == STDOUT_FILENO) {
+ /* We won't close STDOUT_FILENO later... */
+ zfd = dup(zfd);
+ close(STDOUT_FILENO);
+ }
+ if (zfd == -1) {
+ maybe_warn("can't open %s", outfile);
+ goto lose;
+ }
+ remove_file = outfile;
+ }
+
+ switch (method) {
+#ifndef NO_BZIP2_SUPPORT
+ case FT_BZIP2:
+ /* XXX */
+ if (lflag) {
+ maybe_warnx("no -l with bzip2 files");
+ goto lose;
+ }
+
+ size = unbzip2(fd, zfd, NULL, 0, NULL);
+ break;
+#endif
+
+#ifndef NO_COMPRESS_SUPPORT
+ case FT_Z: {
+ FILE *in, *out;
+
+ /* XXX */
+ if (lflag) {
+ maybe_warnx("no -l with Lempel-Ziv files");
+ goto lose;
+ }
+
+ if ((in = zdopen(fd)) == NULL) {
+ maybe_warn("zdopen for read: %s", file);
+ goto lose;
+ }
+
+ out = fdopen(dup(zfd), "w");
+ if (out == NULL) {
+ maybe_warn("fdopen for write: %s", outfile);
+ fclose(in);
+ goto lose;
+ }
+
+ size = zuncompress(in, out, NULL, 0, NULL);
+ /* need to fclose() if ferror() is true... */
+ error = ferror(in);
+ if (error | fclose(in)) {
+ if (error)
+ maybe_warn("failed infile");
+ else
+ maybe_warn("failed infile fclose");
+ if (cflag == 0)
+ unlink(outfile);
+ (void)fclose(out);
+ goto lose;
+ }
+ if (fclose(out) != 0) {
+ maybe_warn("failed outfile fclose");
+ if (cflag == 0)
+ unlink(outfile);
+ goto lose;
+ }
+ break;
+ }
+#endif
+
+#ifndef NO_PACK_SUPPORT
+ case FT_PACK:
+ if (lflag) {
+ maybe_warnx("no -l with packed files");
+ goto lose;
+ }
+
+ size = unpack(fd, zfd, NULL, 0, NULL);
+ break;
+#endif
+
+#ifndef NO_XZ_SUPPORT
+ case FT_XZ:
+ if (lflag) {
+ size = unxz_len(fd);
+ if (!tflag) {
+ print_list_out(in_size, size, file);
+ close(fd);
+ return -1;
+ }
+ } else
+ size = unxz(fd, zfd, NULL, 0, NULL);
+ break;
+#endif
+
+#ifndef NO_LZ_SUPPORT
+ case FT_LZ:
+ if (lflag) {
+ maybe_warnx("no -l with lzip files");
+ goto lose;
+ }
+ size = unlz(fd, zfd, NULL, 0, NULL);
+ break;
+#endif
+
+#ifndef NO_ZSTD_SUPPORT
+ case FT_ZSTD:
+ if (lflag) {
+ maybe_warnx("no -l with zstd files");
+ goto lose;
+ }
+ size = unzstd(fd, zfd, NULL, 0, NULL);
+ break;
+#endif
+ case FT_UNKNOWN:
+ if (lflag) {
+ maybe_warnx("no -l for unknown filetypes");
+ goto lose;
+ }
+ size = cat_fd(NULL, 0, NULL, fd);
+ break;
+ default:
+ if (lflag) {
+ print_list(fd, in_size, outfile, isb.st_mtime);
+ if (!tflag) {
+ close(fd);
+ return -1; /* XXX */
+ }
+ }
+
+ size = gz_uncompress(fd, zfd, NULL, 0, NULL, file);
+ break;
+ }
+
+ if (close(fd) != 0)
+ maybe_warn("couldn't close input");
+ if (zfd != STDOUT_FILENO && close(zfd) != 0)
+ maybe_warn("couldn't close output");
+
+ if (size == -1) {
+ if (cflag == 0)
+ unlink(outfile);
+ maybe_warnx("%s: uncompress failed", file);
+ return -1;
+ }
+
+ /* if testing, or we uncompressed to stdout, this is all we need */
+ if (tflag)
+ return size;
+ /* if we are uncompressing to stdin, don't remove the file. */
+ if (cflag)
+ return size;
+
+ /*
+ * if we create a file...
+ */
+ /*
+ * if we can't stat the file don't remove the file.
+ */
+
+ ofd = open(outfile, O_RDWR, 0);
+ if (ofd == -1) {
+ maybe_warn("couldn't open (leaving original): %s",
+ outfile);
+ return -1;
+ }
+ if (fstat(ofd, &osb) != 0) {
+ maybe_warn("couldn't stat (leaving original): %s",
+ outfile);
+ close(ofd);
+ return -1;
+ }
+ if (osb.st_size != size) {
+ maybe_warnx("stat gave different size: %ju != %ju (leaving original)",
+ (uintmax_t)size, (uintmax_t)osb.st_size);
+ close(ofd);
+ unlink(outfile);
+ return -1;
+ }
+ copymodes(ofd, &isb, outfile);
+ remove_file = NULL;
+ close(ofd);
+ unlink_input(file, &isb);
+ return size;
+
+ unexpected_EOF:
+ maybe_warnx("%s: unexpected end of file", file);
+ lose:
+ if (fd != -1)
+ close(fd);
+ if (zfd != -1 && zfd != STDOUT_FILENO)
+ close(zfd);
+ return -1;
+}
+
+static void
+check_siginfo(void)
+{
+ if (print_info == 0)
+ return;
+ if (infile) {
+ if (infile_total) {
+ int pcent = (int)((100.0 * infile_current) / infile_total);
+
+ fprintf(stderr, "%s: done %llu/%llu bytes %d%%\n",
+ infile, (unsigned long long)infile_current,
+ (unsigned long long)infile_total, pcent);
+ } else
+ fprintf(stderr, "%s: done %llu bytes\n",
+ infile, (unsigned long long)infile_current);
+ }
+ print_info = 0;
+}
+
+static off_t
+cat_fd(unsigned char * prepend, size_t count, off_t *gsizep, int fd)
+{
+ char buf[BUFLEN];
+ off_t in_tot;
+ ssize_t w;
+
+ in_tot = count;
+ w = write_retry(STDOUT_FILENO, prepend, count);
+ if (w == -1 || (size_t)w != count) {
+ maybe_warn("write to stdout");
+ return -1;
+ }
+ for (;;) {
+ ssize_t rv;
+
+ rv = read(fd, buf, sizeof buf);
+ if (rv == 0)
+ break;
+ if (rv < 0) {
+ maybe_warn("read from fd %d", fd);
+ break;
+ }
+ infile_newdata(rv);
+
+ if (write_retry(STDOUT_FILENO, buf, rv) != rv) {
+ maybe_warn("write to stdout");
+ break;
+ }
+ in_tot += rv;
+ }
+
+ if (gsizep)
+ *gsizep = in_tot;
+ return (in_tot);
+}
+
+static void
+handle_stdin(void)
+{
+ struct stat isb;
+ unsigned char fourbytes[4];
+ size_t in_size;
+ off_t usize, gsize;
+ enum filetype method;
+ ssize_t bytes_read;
+#ifndef NO_COMPRESS_SUPPORT
+ FILE *in;
+#endif
+
+ if (fflag == 0 && lflag == 0 && isatty(STDIN_FILENO)) {
+ maybe_warnx("standard input is a terminal -- ignoring");
+ goto out;
+ }
+
+ if (fstat(STDIN_FILENO, &isb) < 0) {
+ maybe_warn("fstat");
+ goto out;
+ }
+ if (S_ISREG(isb.st_mode))
+ in_size = isb.st_size;
+ else
+ in_size = 0;
+ infile_set("(stdin)", in_size);
+
+ if (lflag) {
+ print_list(STDIN_FILENO, in_size, infile, isb.st_mtime);
+ goto out;
+ }
+
+ bytes_read = read_retry(STDIN_FILENO, fourbytes, sizeof fourbytes);
+ if (bytes_read == -1) {
+ maybe_warn("can't read stdin");
+ goto out;
+ } else if (bytes_read != sizeof(fourbytes)) {
+ maybe_warnx("(stdin): unexpected end of file");
+ goto out;
+ }
+
+ method = file_gettype(fourbytes);
+ switch (method) {
+ default:
+ if (fflag == 0) {
+ maybe_warnx("unknown compression format");
+ goto out;
+ }
+ usize = cat_fd(fourbytes, sizeof fourbytes, &gsize, STDIN_FILENO);
+ break;
+ case FT_GZIP:
+ usize = gz_uncompress(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize, "(stdin)");
+ break;
+#ifndef NO_BZIP2_SUPPORT
+ case FT_BZIP2:
+ usize = unbzip2(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize);
+ break;
+#endif
+#ifndef NO_COMPRESS_SUPPORT
+ case FT_Z:
+ if ((in = zdopen(STDIN_FILENO)) == NULL) {
+ maybe_warnx("zopen of stdin");
+ goto out;
+ }
+
+ usize = zuncompress(in, stdout, (char *)fourbytes,
+ sizeof fourbytes, &gsize);
+ fclose(in);
+ break;
+#endif
+#ifndef NO_PACK_SUPPORT
+ case FT_PACK:
+ usize = unpack(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize);
+ break;
+#endif
+#ifndef NO_XZ_SUPPORT
+ case FT_XZ:
+ usize = unxz(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize);
+ break;
+#endif
+#ifndef NO_LZ_SUPPORT
+ case FT_LZ:
+ usize = unlz(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize);
+ break;
+#endif
+#ifndef NO_ZSTD_SUPPORT
+ case FT_ZSTD:
+ usize = unzstd(STDIN_FILENO, STDOUT_FILENO,
+ (char *)fourbytes, sizeof fourbytes, &gsize);
+ break;
+#endif
+ }
+
+ if (vflag && !tflag && usize != -1 && gsize != -1)
+ print_verbage(NULL, NULL, usize, gsize);
+ if (vflag && tflag)
+ print_test("(stdin)", usize != -1);
+
+out:
+ infile_clear();
+}
+
+static void
+handle_stdout(void)
+{
+ off_t gsize;
+ off_t usize;
+ struct stat sb;
+ time_t systime;
+ uint32_t mtime;
+ int ret;
+
+ infile_set("(stdout)", 0);
+
+ if (fflag == 0 && isatty(STDOUT_FILENO)) {
+ maybe_warnx("standard output is a terminal -- ignoring");
+ return;
+ }
+
+ /* If stdin is a file use its mtime, otherwise use current time */
+ ret = fstat(STDIN_FILENO, &sb);
+ if (ret < 0) {
+ maybe_warn("Can't stat stdin");
+ return;
+ }
+
+ if (S_ISREG(sb.st_mode)) {
+ infile_set("(stdout)", sb.st_size);
+ mtime = (uint32_t)sb.st_mtime;
+ } else {
+ systime = time(NULL);
+ if (systime == -1) {
+ maybe_warn("time");
+ return;
+ }
+ mtime = (uint32_t)systime;
+ }
+
+ usize =
+ gz_compress(STDIN_FILENO, STDOUT_FILENO, &gsize, "", mtime);
+ if (vflag && !tflag && usize != -1 && gsize != -1)
+ print_verbage(NULL, NULL, usize, gsize);
+}
+
+/* do what is asked for, for the path name */
+static void
+handle_pathname(char *path)
+{
+ char *opath = path, *s = NULL;
+ ssize_t len;
+ int slen;
+ struct stat sb;
+
+ /* check for stdout/stdin */
+ if (path[0] == '-' && path[1] == '\0') {
+ if (dflag)
+ handle_stdin();
+ else
+ handle_stdout();
+ return;
+ }
+
+retry:
+ if (stat(path, &sb) != 0 || (fflag == 0 && cflag == 0 &&
+ lstat(path, &sb) != 0)) {
+ /* lets try <path>.gz if we're decompressing */
+ if (dflag && s == NULL && errno == ENOENT) {
+ len = strlen(path);
+ slen = suffixes[0].ziplen;
+ s = malloc(len + slen + 1);
+ if (s == NULL)
+ maybe_err("malloc");
+ memcpy(s, path, len);
+ memcpy(s + len, suffixes[0].zipped, slen + 1);
+ path = s;
+ goto retry;
+ }
+ maybe_warn("can't stat: %s", opath);
+ goto out;
+ }
+
+ if (S_ISDIR(sb.st_mode)) {
+ if (rflag)
+ handle_dir(path);
+ else
+ maybe_warnx("%s is a directory", path);
+ goto out;
+ }
+
+ if (S_ISREG(sb.st_mode))
+ handle_file(path, &sb);
+ else
+ maybe_warnx("%s is not a regular file", path);
+
+out:
+ if (s)
+ free(s);
+}
+
+/* compress/decompress a file */
+static void
+handle_file(char *file, struct stat *sbp)
+{
+ off_t usize, gsize;
+ char outfile[PATH_MAX];
+
+ infile_set(file, sbp->st_size);
+ if (dflag) {
+ usize = file_uncompress(file, outfile, sizeof(outfile));
+ if (vflag && tflag)
+ print_test(file, usize != -1);
+ if (usize == -1)
+ return;
+ gsize = sbp->st_size;
+ } else {
+ gsize = file_compress(file, outfile, sizeof(outfile));
+ if (gsize == -1)
+ return;
+ usize = sbp->st_size;
+ }
+ infile_clear();
+
+ if (vflag && !tflag)
+ print_verbage(file, (cflag) ? NULL : outfile, usize, gsize);
+}
+
+/* this is used with -r to recursively descend directories */
+static void
+handle_dir(char *dir)
+{
+ char *path_argv[2];
+ FTS *fts;
+ FTSENT *entry;
+
+ path_argv[0] = dir;
+ path_argv[1] = 0;
+ fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
+ if (fts == NULL) {
+ warn("couldn't fts_open %s", dir);
+ return;
+ }
+
+ while (errno = 0, (entry = fts_read(fts))) {
+ switch(entry->fts_info) {
+ case FTS_D:
+ case FTS_DP:
+ continue;
+
+ case FTS_DNR:
+ case FTS_ERR:
+ case FTS_NS:
+ maybe_warn("%s", entry->fts_path);
+ continue;
+ case FTS_F:
+ handle_file(entry->fts_path, entry->fts_statp);
+ }
+ }
+ if (errno != 0)
+ warn("error with fts_read %s", dir);
+ (void)fts_close(fts);
+}
+
+/* print a ratio - size reduction as a fraction of uncompressed size */
+static void
+print_ratio(off_t in, off_t out, FILE *where)
+{
+ int percent10; /* 10 * percent */
+ off_t diff;
+ char buff[8];
+ int len;
+
+ diff = in - out/2;
+ if (in == 0 && out == 0)
+ percent10 = 0;
+ else if (diff < 0)
+ /*
+ * Output is more than double size of input! print -99.9%
+ * Quite possibly we've failed to get the original size.
+ */
+ percent10 = -999;
+ else {
+ /*
+ * We only need 12 bits of result from the final division,
+ * so reduce the values until a 32bit division will suffice.
+ */
+ while (in > 0x100000) {
+ diff >>= 1;
+ in >>= 1;
+ }
+ if (in != 0)
+ percent10 = ((u_int)diff * 2000) / (u_int)in - 1000;
+ else
+ percent10 = 0;
+ }
+
+ len = snprintf(buff, sizeof buff, "%2.2d.", percent10);
+ /* Move the '.' to before the last digit */
+ buff[len - 1] = buff[len - 2];
+ buff[len - 2] = '.';
+ fprintf(where, "%5s%%", buff);
+}
+
+/* print compression statistics, and the new name (if there is one!) */
+static void
+print_verbage(const char *file, const char *nfile, off_t usize, off_t gsize)
+{
+ if (file)
+ fprintf(stderr, "%s:%s ", file,
+ strlen(file) < 7 ? "\t\t" : "\t");
+ print_ratio(usize, gsize, stderr);
+ if (nfile)
+ fprintf(stderr, " -- replaced with %s", nfile);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
+
+/* print test results */
+static void
+print_test(const char *file, int ok)
+{
+
+ if (exit_value == 0 && ok == 0)
+ exit_value = 1;
+ fprintf(stderr, "%s:%s %s\n", file,
+ strlen(file) < 7 ? "\t\t" : "\t", ok ? "OK" : "NOT OK");
+ fflush(stderr);
+}
+
+/* print a file's info ala --list */
+/* eg:
+ compressed uncompressed ratio uncompressed_name
+ 354841 1679360 78.8% /usr/pkgsrc/distfiles/libglade-2.0.1.tar
+*/
+static void
+print_list(int fd, off_t out, const char *outfile, time_t ts)
+{
+ static int first = 1;
+ static off_t in_tot, out_tot;
+ uint32_t crc = 0;
+ off_t in = 0, rv;
+
+ if (first) {
+ if (vflag)
+ printf("method crc date time ");
+ if (qflag == 0)
+ printf(" compressed uncompressed "
+ "ratio uncompressed_name\n");
+ }
+ first = 0;
+
+ /* print totals? */
+ if (fd == -1) {
+ in = in_tot;
+ out = out_tot;
+ } else
+ {
+ /* read the last 4 bytes - this is the uncompressed size */
+ rv = lseek(fd, (off_t)(-8), SEEK_END);
+ if (rv != -1) {
+ unsigned char buf[8];
+ uint32_t usize;
+
+ rv = read(fd, (char *)buf, sizeof(buf));
+ if (rv == -1)
+ maybe_warn("read of uncompressed size");
+ else if (rv != sizeof(buf))
+ maybe_warnx("read of uncompressed size");
+
+ else {
+ usize = le32dec(&buf[4]);
+ in = (off_t)usize;
+ crc = le32dec(&buf[0]);
+ }
+ }
+ }
+
+ if (vflag && fd == -1)
+ printf(" ");
+ else if (vflag) {
+ char *date = ctime(&ts);
+
+ /* skip the day, 1/100th second, and year */
+ date += 4;
+ date[12] = 0;
+ printf("%5s %08x %11s ", "defla"/*XXX*/, crc, date);
+ }
+ in_tot += in;
+ out_tot += out;
+ print_list_out(out, in, outfile);
+}
+
+static void
+print_list_out(off_t out, off_t in, const char *outfile)
+{
+ printf("%12llu %12llu ", (unsigned long long)out, (unsigned long long)in);
+ print_ratio(in, out, stdout);
+ printf(" %s\n", outfile);
+}
+
+/* display the usage of NetBSD gzip */
+static void
+usage(void)
+{
+
+ fprintf(stderr, "%s\n", gzip_version);
+ fprintf(stderr,
+ "usage: %s [-123456789acdfhklLNnqrtVv] [-S .suffix] [<file> [<file> ...]]\n"
+ " -1 --fast fastest (worst) compression\n"
+ " -2 .. -8 set compression level\n"
+ " -9 --best best (slowest) compression\n"
+ " -c --stdout write to stdout, keep original files\n"
+ " --to-stdout\n"
+ " -d --decompress uncompress files\n"
+ " --uncompress\n"
+ " -f --force force overwriting & compress links\n"
+ " -h --help display this help\n"
+ " -k --keep don't delete input files during operation\n"
+ " -l --list list compressed file contents\n"
+ " -N --name save or restore original file name and time stamp\n"
+ " -n --no-name don't save original file name or time stamp\n"
+ " -q --quiet output no warnings\n"
+ " -r --recursive recursively compress files in directories\n"
+ " -S .suf use suffix .suf instead of .gz\n"
+ " --suffix .suf\n"
+ " -t --test test compressed file\n"
+ " -V --version display program version\n"
+ " -v --verbose print extra statistics\n",
+ getprogname());
+ exit(0);
+}
+
+/* display the license information of FreeBSD gzip */
+static void
+display_license(void)
+{
+
+ fprintf(stderr, "%s (based on NetBSD gzip 20150113)\n", gzip_version);
+ fprintf(stderr, "%s\n", gzip_copyright);
+ exit(0);
+}
+
+/* display the version of NetBSD gzip */
+static void
+display_version(void)
+{
+
+ fprintf(stderr, "%s\n", gzip_version);
+ exit(0);
+}
+
+#ifndef NO_BZIP2_SUPPORT
+#include "unbzip2.c"
+#endif
+#ifndef NO_COMPRESS_SUPPORT
+#include "zuncompress.c"
+#endif
+#ifndef NO_PACK_SUPPORT
+#include "unpack.c"
+#endif
+#ifndef NO_XZ_SUPPORT
+#include "unxz.c"
+#endif
+#ifndef NO_LZ_SUPPORT
+#include "unlz.c"
+#endif
+#ifndef NO_ZSTD_SUPPORT
+#include "unzstd.c"
+#endif
+
+static ssize_t
+read_retry(int fd, void *buf, size_t sz)
+{
+ char *cp = buf;
+ size_t left = MIN(sz, (size_t) SSIZE_MAX);
+
+ while (left > 0) {
+ ssize_t ret;
+
+ ret = read(fd, cp, left);
+ if (ret == -1) {
+ return ret;
+ } else if (ret == 0) {
+ break; /* EOF */
+ }
+ cp += ret;
+ left -= ret;
+ }
+
+ return sz - left;
+}
+
+static ssize_t
+write_retry(int fd, const void *buf, size_t sz)
+{
+ const char *cp = buf;
+ size_t left = MIN(sz, (size_t) SSIZE_MAX);
+
+ while (left > 0) {
+ ssize_t ret;
+
+ ret = write(fd, cp, left);
+ if (ret == -1) {
+ return ret;
+ } else if (ret == 0) {
+ abort(); /* Can't happen */
+ }
+ cp += ret;
+ left -= ret;
+ }
+
+ return sz - left;
+}
diff --git a/usr.bin/gzip/tests/Makefile b/usr.bin/gzip/tests/Makefile
new file mode 100644
index 000000000000..96783eec23ea
--- /dev/null
+++ b/usr.bin/gzip/tests/Makefile
@@ -0,0 +1,12 @@
+.include <bsd.own.mk>
+
+PACKAGE= tests
+
+ATF_TESTS_SH= zdiff_test
+NETBSD_ATF_TESTS_SH= gzip_test
+
+${PACKAGE}FILES+= foo.diff
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/gzip/tests/Makefile.depend b/usr.bin/gzip/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/gzip/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/gzip/tests/foo.diff b/usr.bin/gzip/tests/foo.diff
new file mode 100644
index 000000000000..278d14088435
--- /dev/null
+++ b/usr.bin/gzip/tests/foo.diff
@@ -0,0 +1,2 @@
+1a2
+> bar
diff --git a/usr.bin/gzip/tests/zdiff_test.sh b/usr.bin/gzip/tests/zdiff_test.sh
new file mode 100644
index 000000000000..e260261fa291
--- /dev/null
+++ b/usr.bin/gzip/tests/zdiff_test.sh
@@ -0,0 +1,125 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022 Kyle Evans <kevans@FreeBSD.org>
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+specials="foo'bar foo\"bar foo\$bar"
+
+prepare_files()
+{
+ compressfunc="$1"
+ compresssuffix="$2"
+
+ echo "foo" > foo
+
+ for f in $specials foo; do
+ [ "$f" == "foo" ] || cp foo "$f"
+ atf_check "$compressfunc" -k "$f"
+ atf_check tar -ckf "$f.tar" "$f"
+ atf_check -o save:"$f.$compresssuffix" \
+ "$compressfunc" -c "$f.tar"
+
+ # Regenerate $f.tar to create a diff from the .$compresssuffix
+ # file, too.
+ echo "bar" >> "$f"
+ atf_check tar -ckf "$f.tar" "$f"
+ done
+}
+
+atf_test_case gzip
+gzip_body()
+{
+ prepare_files gzip tgz
+ cp foo.gz foo.Z
+
+ for f in foo $specials; do
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff \
+ zdiff "$f.gz"
+ done
+
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff zdiff foo.Z
+
+ for f in foo $specials; do
+ rm "$f"
+ atf_check -s exit:1 -o match:"Binary files" zdiff "$f.tgz"
+ done
+}
+
+atf_test_case bzip
+bzip_body()
+{
+ prepare_files bzip2 tbz2
+ cp foo.bz2 foo.bz
+
+ for f in foo $specials; do
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff \
+ zdiff "$f.bz2"
+ done
+
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff zdiff foo.bz
+
+ for f in foo $specials; do
+ rm "$f"
+ atf_check -s exit:1 -o match:"Binary files" zdiff "$f.tbz2"
+ done
+}
+
+atf_test_case xzip
+xzip_body()
+{
+ prepare_files xz txz
+ cp foo.xz foo.lzma
+
+ for f in foo $specials; do
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff \
+ zdiff "$f.xz"
+ done
+
+ atf_check -s exit:1 -o file:"$(atf_get_srcdir)"/foo.diff zdiff foo.lzma
+
+ for f in foo $specials; do
+ rm "$f"
+ atf_check -s exit:1 -o match:"Binary files" zdiff "$f.txz"
+ done
+}
+
+atf_test_case unknown
+unknown_body()
+{
+ prepare_files xz fxz
+
+ for f in foo $specials; do
+ atf_check -s exit:1 -e match:"unknown suffix$" zdiff "$f.fxz"
+ done
+}
+
+atf_init_test_cases()
+{
+
+ atf_add_test_case gzip
+ atf_add_test_case bzip
+ atf_add_test_case xzip
+ atf_add_test_case unknown
+}
diff --git a/usr.bin/gzip/unbzip2.c b/usr.bin/gzip/unbzip2.c
new file mode 100644
index 000000000000..3fd74f1bac57
--- /dev/null
+++ b/usr.bin/gzip/unbzip2.c
@@ -0,0 +1,143 @@
+/* $NetBSD: unbzip2.c,v 1.14 2017/08/04 07:27:08 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2006 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Simon Burge.
+ *
+ * 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.
+ */
+
+/* This file is #included by gzip.c */
+
+static off_t
+unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
+{
+ int ret, end_of_file, cold = 0;
+ off_t bytes_out = 0;
+ bz_stream bzs;
+ static char *inbuf, *outbuf;
+
+ if (inbuf == NULL)
+ inbuf = malloc(BUFLEN);
+ if (outbuf == NULL)
+ outbuf = malloc(BUFLEN);
+ if (inbuf == NULL || outbuf == NULL)
+ maybe_err("malloc");
+
+ bzs.bzalloc = NULL;
+ bzs.bzfree = NULL;
+ bzs.opaque = NULL;
+
+ end_of_file = 0;
+ ret = BZ2_bzDecompressInit(&bzs, 0, 0);
+ if (ret != BZ_OK)
+ maybe_errx("bzip2 init");
+
+ /* Prepend. */
+ bzs.avail_in = prelen;
+ bzs.next_in = pre;
+
+ if (bytes_in)
+ *bytes_in = prelen;
+
+ while (ret == BZ_OK) {
+ check_siginfo();
+ if (bzs.avail_in == 0 && !end_of_file) {
+ ssize_t n;
+
+ n = read(in, inbuf, BUFLEN);
+ if (n < 0)
+ maybe_err("read");
+ if (n == 0)
+ end_of_file = 1;
+ infile_newdata(n);
+ bzs.next_in = inbuf;
+ bzs.avail_in = n;
+ if (bytes_in)
+ *bytes_in += n;
+ }
+
+ bzs.next_out = outbuf;
+ bzs.avail_out = BUFLEN;
+ ret = BZ2_bzDecompress(&bzs);
+
+ switch (ret) {
+ case BZ_STREAM_END:
+ case BZ_OK:
+ if (ret == BZ_OK && end_of_file) {
+ /*
+ * If we hit this after a stream end, consider
+ * it as the end of the whole file and don't
+ * bail out.
+ */
+ if (cold == 1)
+ ret = BZ_STREAM_END;
+ else
+ maybe_errx("truncated file");
+ }
+ cold = 0;
+ if (!tflag && bzs.avail_out != BUFLEN) {
+ ssize_t n;
+
+ n = write(out, outbuf, BUFLEN - bzs.avail_out);
+ if (n < 0)
+ maybe_err("write");
+ bytes_out += n;
+ }
+ if (ret == BZ_STREAM_END && !end_of_file) {
+ if (BZ2_bzDecompressEnd(&bzs) != BZ_OK ||
+ BZ2_bzDecompressInit(&bzs, 0, 0) != BZ_OK)
+ maybe_errx("bzip2 re-init");
+ cold = 1;
+ ret = BZ_OK;
+ }
+ break;
+
+ case BZ_DATA_ERROR:
+ maybe_warnx("bzip2 data integrity error");
+ break;
+
+ case BZ_DATA_ERROR_MAGIC:
+ maybe_warnx("bzip2 magic number error");
+ break;
+
+ case BZ_MEM_ERROR:
+ maybe_warnx("bzip2 out of memory");
+ break;
+
+ default:
+ maybe_warnx("unknown bzip2 error: %d", ret);
+ break;
+ }
+ }
+
+ if (ret != BZ_STREAM_END || BZ2_bzDecompressEnd(&bzs) != BZ_OK)
+ return (-1);
+
+ return (bytes_out);
+}
+
diff --git a/usr.bin/gzip/unlz.c b/usr.bin/gzip/unlz.c
new file mode 100644
index 000000000000..71e752ab1112
--- /dev/null
+++ b/usr.bin/gzip/unlz.c
@@ -0,0 +1,642 @@
+/* $NetBSD: unlz.c,v 1.6 2018/11/11 01:42:36 christos Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ */
+
+/* Lzd - Educational decompressor for the lzip format
+ Copyright (C) 2013-2018 Antonio Diaz Diaz.
+
+ This program is free software. 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 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.
+*/
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define LZ_STATES 12
+
+#define LITERAL_CONTEXT_BITS 3
+#define POS_STATE_BITS 2
+#define POS_STATES (1 << POS_STATE_BITS)
+#define POS_STATE_MASK (POS_STATES - 1)
+
+#define STATES 4
+#define DIS_SLOT_BITS 6
+
+#define DIS_MODEL_START 4
+#define DIS_MODEL_END 14
+
+#define MODELED_DISTANCES (1 << (DIS_MODEL_END / 2))
+#define DIS_ALIGN_BITS 4
+#define DIS_ALIGN_SIZE (1 << DIS_ALIGN_BITS)
+
+#define LOW_BITS 3
+#define MID_BITS 3
+#define HIGH_BITS 8
+
+#define LOW_SYMBOLS (1 << LOW_BITS)
+#define MID_SYMBOLS (1 << MID_BITS)
+#define HIGH_SYMBOLS (1 << HIGH_BITS)
+
+#define MAX_SYMBOLS (LOW_SYMBOLS + MID_SYMBOLS + HIGH_SYMBOLS)
+
+#define MIN_MATCH_LEN 2
+
+#define BIT_MODEL_MOVE_BITS 5
+#define BIT_MODEL_TOTAL_BITS 11
+#define BIT_MODEL_TOTAL (1 << BIT_MODEL_TOTAL_BITS)
+#define BIT_MODEL_INIT (BIT_MODEL_TOTAL / 2)
+
+static const int lz_st_next[] = {
+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
+};
+
+static bool
+lz_st_is_char(int st) {
+ return st < 7;
+}
+
+static int
+lz_st_get_char(int st) {
+ return lz_st_next[st];
+}
+
+static int
+lz_st_get_match(int st) {
+ return st < 7 ? 7 : 10;
+}
+
+static int
+lz_st_get_rep(int st) {
+ return st < 7 ? 8 : 11;
+}
+
+static int
+lz_st_get_short_rep(int st) {
+ return st < 7 ? 9 : 11;
+}
+
+struct lz_len_model {
+ int choice1;
+ int choice2;
+ int bm_low[POS_STATES][LOW_SYMBOLS];
+ int bm_mid[POS_STATES][MID_SYMBOLS];
+ int bm_high[HIGH_SYMBOLS];
+};
+
+static uint32_t lz_crc[256];
+
+static void
+lz_crc_init(void)
+{
+ for (unsigned i = 0; i < nitems(lz_crc); i++) {
+ unsigned c = i;
+ for (unsigned j = 0; j < 8; j++) {
+ if (c & 1)
+ c = 0xEDB88320U ^ (c >> 1);
+ else
+ c >>= 1;
+ }
+ lz_crc[i] = c;
+ }
+}
+
+static void
+lz_crc_update(uint32_t *crc, const uint8_t *buf, size_t len)
+{
+ for (size_t i = 0; i < len; i++)
+ *crc = lz_crc[(*crc ^ buf[i]) & 0xFF] ^ (*crc >> 8);
+}
+
+struct lz_range_decoder {
+ FILE *fp;
+ uint32_t code;
+ uint32_t range;
+};
+
+static int
+lz_rd_create(struct lz_range_decoder *rd, FILE *fp)
+{
+ rd->fp = fp;
+ rd->code = 0;
+ rd->range = ~0;
+ for (int i = 0; i < 5; i++)
+ rd->code = (rd->code << 8) | (uint8_t)getc(rd->fp);
+ return ferror(rd->fp) ? -1 : 0;
+}
+
+static unsigned
+lz_rd_decode(struct lz_range_decoder *rd, int num_bits)
+{
+ unsigned symbol = 0;
+
+ for (int i = num_bits; i > 0; i--) {
+ rd->range >>= 1;
+ symbol <<= 1;
+ if (rd->code >= rd->range) {
+ rd->code -= rd->range;
+ symbol |= 1;
+ }
+ if (rd->range <= 0x00FFFFFFU) {
+ rd->range <<= 8;
+ rd->code = (rd->code << 8) | (uint8_t)getc(rd->fp);
+ }
+ }
+
+ return symbol;
+}
+
+static unsigned
+lz_rd_decode_bit(struct lz_range_decoder *rd, int *bm)
+{
+ unsigned symbol;
+ const uint32_t bound = (rd->range >> BIT_MODEL_TOTAL_BITS) * *bm;
+
+ if(rd->code < bound) {
+ rd->range = bound;
+ *bm += (BIT_MODEL_TOTAL - *bm) >> BIT_MODEL_MOVE_BITS;
+ symbol = 0;
+ }
+ else {
+ rd->range -= bound;
+ rd->code -= bound;
+ *bm -= *bm >> BIT_MODEL_MOVE_BITS;
+ symbol = 1;
+ }
+
+ if (rd->range <= 0x00FFFFFFU) {
+ rd->range <<= 8;
+ rd->code = (rd->code << 8) | (uint8_t)getc(rd->fp);
+ }
+ return symbol;
+}
+
+static unsigned
+lz_rd_decode_tree(struct lz_range_decoder *rd, int *bm, int num_bits)
+{
+ unsigned symbol = 1;
+
+ for (int i = 0; i < num_bits; i++)
+ symbol = (symbol << 1) | lz_rd_decode_bit(rd, &bm[symbol]);
+
+ return symbol - (1 << num_bits);
+}
+
+static unsigned
+lz_rd_decode_tree_reversed(struct lz_range_decoder *rd, int *bm, int num_bits)
+{
+ unsigned symbol = lz_rd_decode_tree(rd, bm, num_bits);
+ unsigned reversed_symbol = 0;
+
+ for (int i = 0; i < num_bits; i++) {
+ reversed_symbol = (reversed_symbol << 1) | (symbol & 1);
+ symbol >>= 1;
+ }
+
+ return reversed_symbol;
+}
+
+static unsigned
+lz_rd_decode_matched(struct lz_range_decoder *rd, int *bm, int match_byte)
+{
+ unsigned symbol = 1;
+
+ for (int i = 7; i >= 0; i--) {
+ const unsigned match_bit = (match_byte >> i) & 1;
+ const unsigned bit = lz_rd_decode_bit(rd,
+ &bm[symbol + (match_bit << 8) + 0x100]);
+ symbol = (symbol << 1) | bit;
+ if (match_bit != bit) {
+ while (symbol < 0x100) {
+ symbol = (symbol << 1) |
+ lz_rd_decode_bit(rd, &bm[symbol]);
+ }
+ break;
+ }
+ }
+ return symbol & 0xFF;
+}
+
+static unsigned
+lz_rd_decode_len(struct lz_range_decoder *rd, struct lz_len_model *lm,
+ int pos_state)
+{
+ if (lz_rd_decode_bit(rd, &lm->choice1) == 0)
+ return lz_rd_decode_tree(rd, lm->bm_low[pos_state], LOW_BITS);
+
+ if (lz_rd_decode_bit(rd, &lm->choice2) == 0) {
+ return LOW_SYMBOLS +
+ lz_rd_decode_tree(rd, lm->bm_mid[pos_state], MID_BITS);
+ }
+
+ return LOW_SYMBOLS + MID_SYMBOLS +
+ lz_rd_decode_tree(rd, lm->bm_high, HIGH_BITS);
+}
+
+struct lz_decoder {
+ FILE *fin, *fout;
+ off_t pos, ppos, spos, dict_size;
+ bool wrapped;
+ uint32_t crc;
+ uint8_t *obuf;
+ struct lz_range_decoder rdec;
+};
+
+static int
+lz_flush(struct lz_decoder *lz)
+{
+ off_t offs = lz->pos - lz->spos;
+ if (offs <= 0)
+ return -1;
+
+ size_t size = (size_t)offs;
+ lz_crc_update(&lz->crc, lz->obuf + lz->spos, size);
+ if (fwrite(lz->obuf + lz->spos, 1, size, lz->fout) != size)
+ return -1;
+
+ lz->wrapped = lz->pos >= lz->dict_size;
+ if (lz->wrapped) {
+ lz->ppos += lz->pos;
+ lz->pos = 0;
+ }
+ lz->spos = lz->pos;
+ return 0;
+}
+
+static void
+lz_destroy(struct lz_decoder *lz)
+{
+ if (lz->fin)
+ fclose(lz->fin);
+ if (lz->fout)
+ fclose(lz->fout);
+ free(lz->obuf);
+}
+
+static int
+lz_create(struct lz_decoder *lz, int fin, int fdout, int dict_size)
+{
+ memset(lz, 0, sizeof(*lz));
+
+ lz->fin = fdopen(dup(fin), "r");
+ if (lz->fin == NULL)
+ goto out;
+
+ lz->fout = fdopen(dup(fdout), "w");
+ if (lz->fout == NULL)
+ goto out;
+
+ lz->pos = lz->ppos = lz->spos = 0;
+ lz->crc = ~0;
+ lz->dict_size = dict_size;
+ lz->wrapped = false;
+
+ lz->obuf = malloc(dict_size);
+ if (lz->obuf == NULL)
+ goto out;
+
+ if (lz_rd_create(&lz->rdec, lz->fin) == -1)
+ goto out;
+ return 0;
+out:
+ lz_destroy(lz);
+ return -1;
+}
+
+static uint8_t
+lz_peek(const struct lz_decoder *lz, unsigned ahead)
+{
+ off_t diff = lz->pos - ahead - 1;
+
+ if (diff >= 0)
+ return lz->obuf[diff];
+
+ if (lz->wrapped)
+ return lz->obuf[lz->dict_size + diff];
+
+ return 0;
+}
+
+static void
+lz_put(struct lz_decoder *lz, uint8_t b)
+{
+ lz->obuf[lz->pos++] = b;
+ if (lz->dict_size == lz->pos)
+ lz_flush(lz);
+}
+
+static off_t
+lz_get_data_position(const struct lz_decoder *lz)
+{
+ return lz->ppos + lz->pos;
+}
+
+static unsigned
+lz_get_crc(const struct lz_decoder *lz)
+{
+ return lz->crc ^ 0xffffffffU;
+}
+
+static void
+lz_bm_init(int *a, size_t l)
+{
+ for (size_t i = 0; i < l; i++)
+ a[i] = BIT_MODEL_INIT;
+}
+
+#define LZ_BM_INIT(a) lz_bm_init(a, nitems(a))
+#define LZ_BM_INIT2(a) do { \
+ size_t l = nitems(a[0]); \
+ for (size_t i = 0; i < nitems(a); i++) \
+ lz_bm_init(a[i], l); \
+} while (/*CONSTCOND*/0)
+
+#define LZ_MODEL_INIT(a) do { \
+ a.choice1 = BIT_MODEL_INIT; \
+ a.choice2 = BIT_MODEL_INIT; \
+ LZ_BM_INIT2(a.bm_low); \
+ LZ_BM_INIT2(a.bm_mid); \
+ LZ_BM_INIT(a.bm_high); \
+} while (/*CONSTCOND*/0)
+
+static bool
+lz_decode_member(struct lz_decoder *lz)
+{
+ int bm_literal[1 << LITERAL_CONTEXT_BITS][0x300];
+ int bm_match[LZ_STATES][POS_STATES];
+ int bm_rep[4][LZ_STATES];
+ int bm_len[LZ_STATES][POS_STATES];
+ int bm_dis_slot[LZ_STATES][1 << DIS_SLOT_BITS];
+ int bm_dis[MODELED_DISTANCES - DIS_MODEL_END + 1];
+ int bm_align[DIS_ALIGN_SIZE];
+
+ LZ_BM_INIT2(bm_literal);
+ LZ_BM_INIT2(bm_match);
+ LZ_BM_INIT2(bm_rep);
+ LZ_BM_INIT2(bm_len);
+ LZ_BM_INIT2(bm_dis_slot);
+ LZ_BM_INIT(bm_dis);
+ LZ_BM_INIT(bm_align);
+
+ struct lz_len_model match_len_model;
+ struct lz_len_model rep_len_model;
+
+ LZ_MODEL_INIT(match_len_model);
+ LZ_MODEL_INIT(rep_len_model);
+
+ struct lz_range_decoder *rd = &lz->rdec;
+ unsigned rep[4] = { 0 };
+
+
+ int state = 0;
+
+ while (!feof(lz->fin) && !ferror(lz->fin)) {
+ const int pos_state = lz_get_data_position(lz) & POS_STATE_MASK;
+ // bit 1
+ if (lz_rd_decode_bit(rd, &bm_match[state][pos_state]) == 0) {
+ const uint8_t prev_byte = lz_peek(lz, 0);
+ const int literal_state =
+ prev_byte >> (8 - LITERAL_CONTEXT_BITS);
+ int *bm = bm_literal[literal_state];
+ if (lz_st_is_char(state))
+ lz_put(lz, lz_rd_decode_tree(rd, bm, 8));
+ else {
+ int peek = lz_peek(lz, rep[0]);
+ lz_put(lz, lz_rd_decode_matched(rd, bm, peek));
+ }
+ state = lz_st_get_char(state);
+ continue;
+ }
+ int len;
+ // bit 2
+ if (lz_rd_decode_bit(rd, &bm_rep[0][state]) != 0) {
+ // bit 3
+ if (lz_rd_decode_bit(rd, &bm_rep[1][state]) == 0) {
+ // bit 4
+ if (lz_rd_decode_bit(rd,
+ &bm_len[state][pos_state]) == 0)
+ {
+ state = lz_st_get_short_rep(state);
+ lz_put(lz, lz_peek(lz, rep[0]));
+ continue;
+ }
+ } else {
+ unsigned distance;
+ // bit 4
+ if (lz_rd_decode_bit(rd, &bm_rep[2][state])
+ == 0)
+ distance = rep[1];
+ else {
+ // bit 5
+ if (lz_rd_decode_bit(rd,
+ &bm_rep[3][state]) == 0)
+ distance = rep[2];
+ else {
+ distance = rep[3];
+ rep[3] = rep[2];
+ }
+ rep[2] = rep[1];
+ }
+ rep[1] = rep[0];
+ rep[0] = distance;
+ }
+ state = lz_st_get_rep(state);
+ len = MIN_MATCH_LEN +
+ lz_rd_decode_len(rd, &rep_len_model, pos_state);
+ } else {
+ rep[3] = rep[2]; rep[2] = rep[1]; rep[1] = rep[0];
+ len = MIN_MATCH_LEN +
+ lz_rd_decode_len(rd, &match_len_model, pos_state);
+ const int len_state =
+ MIN(len - MIN_MATCH_LEN, STATES - 1);
+ rep[0] = lz_rd_decode_tree(rd, bm_dis_slot[len_state],
+ DIS_SLOT_BITS);
+ if (rep[0] >= DIS_MODEL_START) {
+ const unsigned dis_slot = rep[0];
+ const int direct_bits = (dis_slot >> 1) - 1;
+ rep[0] = (2 | (dis_slot & 1)) << direct_bits;
+ if (dis_slot < DIS_MODEL_END)
+ rep[0] += lz_rd_decode_tree_reversed(rd,
+ &bm_dis[rep[0] - dis_slot],
+ direct_bits);
+ else {
+ rep[0] += lz_rd_decode(rd, direct_bits
+ - DIS_ALIGN_BITS) << DIS_ALIGN_BITS;
+ rep[0] += lz_rd_decode_tree_reversed(rd,
+ bm_align, DIS_ALIGN_BITS);
+ if (rep[0] == 0xFFFFFFFFU) {
+ lz_flush(lz);
+ return len == MIN_MATCH_LEN;
+ }
+ }
+ }
+ state = lz_st_get_match(state);
+ if (rep[0] >= lz->dict_size ||
+ (rep[0] >= lz->pos && !lz->wrapped)) {
+ lz_flush(lz);
+ return false;
+ }
+ }
+ for (int i = 0; i < len; i++)
+ lz_put(lz, lz_peek(lz, rep[0]));
+ }
+ lz_flush(lz);
+ return false;
+}
+
+/*
+ * 0-3 CRC32 of the uncompressed data
+ * 4-11 size of the uncompressed data
+ * 12-19 member size including header and trailer
+ */
+#define TRAILER_SIZE 20
+
+
+static off_t
+lz_decode(int fin, int fdout, unsigned dict_size, off_t *insize)
+{
+ struct lz_decoder lz;
+ off_t rv = -1;
+
+ if (lz_create(&lz, fin, fdout, dict_size) == -1)
+ return -1;
+
+ if (!lz_decode_member(&lz))
+ goto out;
+
+ uint8_t trailer[TRAILER_SIZE];
+
+ for(size_t i = 0; i < nitems(trailer); i++)
+ trailer[i] = (uint8_t)getc(lz.fin);
+
+ unsigned crc = 0;
+ for (int i = 3; i >= 0; --i) {
+ crc <<= 8;
+ crc += trailer[i];
+ }
+
+ int64_t data_size = 0;
+ for (int i = 11; i >= 4; --i) {
+ data_size <<= 8;
+ data_size += trailer[i];
+ }
+
+ if (crc != lz_get_crc(&lz) || data_size != lz_get_data_position(&lz))
+ goto out;
+
+ rv = 0;
+ for (int i = 19; i >= 12; --i) {
+ rv <<= 8;
+ rv += trailer[i];
+ }
+ if (insize)
+ *insize = rv;
+#if 0
+ /* Does not work with pipes */
+ rv = ftello(lz.fout);
+#else
+ rv = data_size;
+#endif
+out:
+ lz_destroy(&lz);
+ return rv;
+}
+
+
+/*
+ * 0-3 magic
+ * 4 version
+ * 5 coded dict_size
+ */
+#define HDR_SIZE 6
+#define MIN_DICTIONARY_SIZE (1 << 12)
+#define MAX_DICTIONARY_SIZE (1 << 29)
+
+static const char hdrmagic[] = { 'L', 'Z', 'I', 'P', 1 };
+
+static unsigned
+lz_get_dict_size(unsigned char c)
+{
+ unsigned dict_size = 1 << (c & 0x1f);
+ dict_size -= (dict_size >> 2) * ( (c >> 5) & 0x7);
+ if (dict_size < MIN_DICTIONARY_SIZE || dict_size > MAX_DICTIONARY_SIZE)
+ return 0;
+ return dict_size;
+}
+
+static off_t
+unlz(int fin, int fout, char *pre, size_t prelen, off_t *bytes_in)
+{
+ if (lz_crc[0] == 0)
+ lz_crc_init();
+
+ char header[HDR_SIZE];
+
+ if (pre && prelen)
+ memcpy(header, pre, prelen);
+
+ ssize_t nr = read(fin, header + prelen, sizeof(header) - prelen);
+ switch (nr) {
+ case -1:
+ return -1;
+ case 0:
+ return prelen ? -1 : 0;
+ default:
+ if ((size_t)nr != sizeof(header) - prelen)
+ return -1;
+ break;
+ }
+
+ if (memcmp(header, hdrmagic, sizeof(hdrmagic)) != 0)
+ return -1;
+
+ unsigned dict_size = lz_get_dict_size(header[5]);
+ if (dict_size == 0)
+ return -1;
+
+ return lz_decode(fin, fout, dict_size, bytes_in);
+}
diff --git a/usr.bin/gzip/unpack.c b/usr.bin/gzip/unpack.c
new file mode 100644
index 000000000000..110500ac21d6
--- /dev/null
+++ b/usr.bin/gzip/unpack.c
@@ -0,0 +1,334 @@
+/* $NetBSD: unpack.c,v 1.3 2017/08/04 07:27:08 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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 file is #included by gzip.c */
+
+/*
+ * pack(1) file format:
+ *
+ * The first 7 bytes is the header:
+ * 00, 01 - Signature (US, RS), we already validated it earlier.
+ * 02..05 - Uncompressed size
+ * 06 - Level for the huffman tree (<=24)
+ *
+ * pack(1) will then store symbols (leaf) nodes count in each huffman
+ * tree levels, each level would consume 1 byte (See [1]).
+ *
+ * After the symbol count table, there is the symbol table, storing
+ * symbols represented by corresponding leaf node. EOB is not being
+ * explicitly transmitted (not necessary anyway) in the symbol table.
+ *
+ * Compressed data goes after the symbol table.
+ *
+ * NOTES
+ *
+ * [1] If we count EOB into the symbols, that would mean that we will
+ * have at most 256 symbols in the huffman tree. pack(1) rejects empty
+ * file and files that just repeats one character, which means that we
+ * will have at least 2 symbols. Therefore, pack(1) would reduce the
+ * last level symbol count by 2 which makes it a number in
+ * range [0..254], so all levels' symbol count would fit into 1 byte.
+ */
+
+#define PACK_HEADER_LENGTH 7
+#define HTREE_MAXLEVEL 24
+
+/*
+ * unpack descriptor
+ *
+ * Represent the huffman tree in a similar way that pack(1) would
+ * store in a packed file. We store all symbols in a linear table,
+ * and store pointers to each level's first symbol. In addition to
+ * that, maintain two counts for each level: inner nodes count and
+ * leaf nodes count.
+ */
+typedef struct {
+ int symbol_size; /* Size of the symbol table */
+ int treelevels; /* Levels for the huffman tree */
+
+ int *symbolsin; /* Table of leaf symbols count in each
+ * level */
+ int *inodesin; /* Table of internal nodes count in
+ * each level */
+
+ char *symbol; /* The symbol table */
+ char *symbol_eob; /* Pointer to the EOB symbol */
+ char **tree; /* Decoding huffman tree (pointers to
+ * first symbol of each tree level */
+
+ off_t uncompressed_size; /* Uncompressed size */
+ FILE *fpIn; /* Input stream */
+ FILE *fpOut; /* Output stream */
+} unpack_descriptor_t;
+
+/*
+ * Release resource allocated to an unpack descriptor.
+ *
+ * Caller is responsible to make sure that all of these pointers are
+ * initialized (in our case, they all point to valid memory block).
+ * We don't zero out pointers here because nobody else would ever
+ * reference the memory block without scrubbing them.
+ */
+static void
+unpack_descriptor_fini(unpack_descriptor_t *unpackd)
+{
+
+ free(unpackd->symbolsin);
+ free(unpackd->inodesin);
+ free(unpackd->symbol);
+ free(unpackd->tree);
+
+ fclose(unpackd->fpIn);
+ fclose(unpackd->fpOut);
+}
+
+/*
+ * Recursively fill the internal node count table
+ */
+static void
+unpackd_fill_inodesin(const unpack_descriptor_t *unpackd, int level)
+{
+
+ /*
+ * The internal nodes would be 1/2 of total internal nodes and
+ * leaf nodes in the next level. For the last level there
+ * would be no internal node by definition.
+ */
+ if (level < unpackd->treelevels) {
+ unpackd_fill_inodesin(unpackd, level + 1);
+ unpackd->inodesin[level] = (unpackd->inodesin[level + 1] +
+ unpackd->symbolsin[level + 1]) / 2;
+ } else
+ unpackd->inodesin[level] = 0;
+}
+
+/*
+ * Update counter for accepted bytes
+ */
+static void
+accepted_bytes(off_t *bytes_in, off_t newbytes)
+{
+
+ if (bytes_in != NULL)
+ (*bytes_in) += newbytes;
+}
+
+/*
+ * Read file header and construct the tree. Also, prepare the buffered I/O
+ * for decode routine.
+ *
+ * Return value is uncompressed size.
+ */
+static void
+unpack_parse_header(int in, int out, char *pre, size_t prelen, off_t *bytes_in,
+ unpack_descriptor_t *unpackd)
+{
+ unsigned char hdr[PACK_HEADER_LENGTH]; /* buffer for header */
+ ssize_t bytesread; /* Bytes read from the file */
+ int i, j, thisbyte;
+
+ /* Prepend the header buffer if we already read some data */
+ if (prelen != 0)
+ memcpy(hdr, pre, prelen);
+
+ /* Read in and fill the rest bytes of header */
+ bytesread = read(in, hdr + prelen, PACK_HEADER_LENGTH - prelen);
+ if (bytesread < 0)
+ maybe_err("Error reading pack header");
+ infile_newdata(bytesread);
+
+ accepted_bytes(bytes_in, PACK_HEADER_LENGTH);
+
+ /* Obtain uncompressed length (bytes 2,3,4,5) */
+ unpackd->uncompressed_size = 0;
+ for (i = 2; i <= 5; i++) {
+ unpackd->uncompressed_size <<= 8;
+ unpackd->uncompressed_size |= hdr[i];
+ }
+
+ /* Get the levels of the tree */
+ unpackd->treelevels = hdr[6];
+ if (unpackd->treelevels > HTREE_MAXLEVEL || unpackd->treelevels < 1)
+ maybe_errx("Huffman tree has insane levels");
+
+ /* Let libc take care for buffering from now on */
+ if ((unpackd->fpIn = fdopen(in, "r")) == NULL)
+ maybe_err("Can not fdopen() input stream");
+ if ((unpackd->fpOut = fdopen(out, "w")) == NULL)
+ maybe_err("Can not fdopen() output stream");
+
+ /* Allocate for the tables of bounds and the tree itself */
+ unpackd->inodesin =
+ calloc(unpackd->treelevels, sizeof(*(unpackd->inodesin)));
+ unpackd->symbolsin =
+ calloc(unpackd->treelevels, sizeof(*(unpackd->symbolsin)));
+ unpackd->tree =
+ calloc(unpackd->treelevels, (sizeof(*(unpackd->tree))));
+ if (unpackd->inodesin == NULL || unpackd->symbolsin == NULL ||
+ unpackd->tree == NULL)
+ maybe_err("calloc");
+
+ /* We count from 0 so adjust to match array upper bound */
+ unpackd->treelevels--;
+
+ /* Read the levels symbol count table and calculate total */
+ unpackd->symbol_size = 1; /* EOB */
+ for (i = 0; i <= unpackd->treelevels; i++) {
+ if ((thisbyte = fgetc(unpackd->fpIn)) == EOF)
+ maybe_err("File appears to be truncated");
+ unpackd->symbolsin[i] = (unsigned char)thisbyte;
+ unpackd->symbol_size += unpackd->symbolsin[i];
+ }
+ accepted_bytes(bytes_in, unpackd->treelevels);
+ if (unpackd->symbol_size > 256)
+ maybe_errx("Bad symbol table");
+ infile_newdata(unpackd->treelevels);
+
+ /* Allocate for the symbol table, point symbol_eob at the beginning */
+ unpackd->symbol_eob = unpackd->symbol = calloc(1, unpackd->symbol_size);
+ if (unpackd->symbol == NULL)
+ maybe_err("calloc");
+
+ /*
+ * Read in the symbol table, which contain [2, 256] symbols.
+ * In order to fit the count in one byte, pack(1) would offset
+ * it by reducing 2 from the actual number from the last level.
+ *
+ * We adjust the last level's symbol count by 1 here, because
+ * the EOB symbol is not being transmitted explicitly. Another
+ * adjustment would be done later afterward.
+ */
+ unpackd->symbolsin[unpackd->treelevels]++;
+ for (i = 0; i <= unpackd->treelevels; i++) {
+ unpackd->tree[i] = unpackd->symbol_eob;
+ for (j = 0; j < unpackd->symbolsin[i]; j++) {
+ if ((thisbyte = fgetc(unpackd->fpIn)) == EOF)
+ maybe_errx("Symbol table truncated");
+ *unpackd->symbol_eob++ = (char)thisbyte;
+ }
+ infile_newdata(unpackd->symbolsin[i]);
+ accepted_bytes(bytes_in, unpackd->symbolsin[i]);
+ }
+
+ /* Now, take account for the EOB symbol as well */
+ unpackd->symbolsin[unpackd->treelevels]++;
+
+ /*
+ * The symbolsin table has been constructed now.
+ * Calculate the internal nodes count table based on it.
+ */
+ unpackd_fill_inodesin(unpackd, 0);
+}
+
+/*
+ * Decode huffman stream, based on the huffman tree.
+ */
+static void
+unpack_decode(const unpack_descriptor_t *unpackd, off_t *bytes_in)
+{
+ int thislevel, thiscode, thisbyte, inlevelindex;
+ int i;
+ off_t bytes_out = 0;
+ const char *thissymbol; /* The symbol pointer decoded from stream */
+
+ /*
+ * Decode huffman. Fetch every bytes from the file, get it
+ * into 'thiscode' bit-by-bit, then output the symbol we got
+ * when one has been found.
+ *
+ * Assumption: sizeof(int) > ((max tree levels + 1) / 8).
+ * bad things could happen if not.
+ */
+ thislevel = 0;
+ thiscode = thisbyte = 0;
+
+ while ((thisbyte = fgetc(unpackd->fpIn)) != EOF) {
+ accepted_bytes(bytes_in, 1);
+ infile_newdata(1);
+ check_siginfo();
+
+ /*
+ * Split one bit from thisbyte, from highest to lowest,
+ * feed the bit into thiscode, until we got a symbol from
+ * the tree.
+ */
+ for (i = 7; i >= 0; i--) {
+ thiscode = (thiscode << 1) | ((thisbyte >> i) & 1);
+
+ /* Did we got a symbol? (referencing leaf node) */
+ if (thiscode >= unpackd->inodesin[thislevel]) {
+ inlevelindex =
+ thiscode - unpackd->inodesin[thislevel];
+ if (inlevelindex > unpackd->symbolsin[thislevel])
+ maybe_errx("File corrupt");
+
+ thissymbol =
+ &(unpackd->tree[thislevel][inlevelindex]);
+ if ((thissymbol == unpackd->symbol_eob) &&
+ (bytes_out == unpackd->uncompressed_size))
+ goto finished;
+
+ fputc((*thissymbol), unpackd->fpOut);
+ bytes_out++;
+
+ /* Prepare for next input */
+ thislevel = 0; thiscode = 0;
+ } else {
+ thislevel++;
+ if (thislevel > unpackd->treelevels)
+ maybe_errx("File corrupt");
+ }
+ }
+ }
+
+finished:
+ if (bytes_out != unpackd->uncompressed_size)
+ maybe_errx("Premature EOF");
+}
+
+/* Handler for pack(1)'ed file */
+static off_t
+unpack(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
+{
+ unpack_descriptor_t unpackd;
+
+ in = dup(in);
+ if (in == -1)
+ maybe_err("dup");
+ out = dup(out);
+ if (out == -1)
+ maybe_err("dup");
+
+ unpack_parse_header(in, out, pre, prelen, bytes_in, &unpackd);
+ unpack_decode(&unpackd, bytes_in);
+ unpack_descriptor_fini(&unpackd);
+
+ /* If we reached here, the unpack was successful */
+ return (unpackd.uncompressed_size);
+}
diff --git a/usr.bin/gzip/unxz.c b/usr.bin/gzip/unxz.c
new file mode 100644
index 000000000000..de6683b246b8
--- /dev/null
+++ b/usr.bin/gzip/unxz.c
@@ -0,0 +1,474 @@
+/* $NetBSD: unxz.c,v 1.8 2018/10/06 16:36:45 martin Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 <sys/cdefs.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <lzma.h>
+
+static off_t
+unxz(int i, int o, char *pre, size_t prelen, off_t *bytes_in)
+{
+ lzma_stream strm = LZMA_STREAM_INIT;
+ static const int flags = LZMA_TELL_UNSUPPORTED_CHECK|LZMA_CONCATENATED;
+ lzma_ret ret;
+ lzma_action action = LZMA_RUN;
+ off_t bytes_out, bp;
+ uint8_t ibuf[BUFSIZ];
+ uint8_t obuf[BUFSIZ];
+
+ if (bytes_in == NULL)
+ bytes_in = &bp;
+
+ strm.next_in = ibuf;
+ memcpy(ibuf, pre, prelen);
+ strm.avail_in = read(i, ibuf + prelen, sizeof(ibuf) - prelen);
+ if (strm.avail_in == (size_t)-1)
+ maybe_err("read failed");
+ infile_newdata(strm.avail_in);
+ strm.avail_in += prelen;
+ *bytes_in = strm.avail_in;
+
+ if ((ret = lzma_stream_decoder(&strm, UINT64_MAX, flags)) != LZMA_OK)
+ maybe_errx("Can't initialize decoder (%d)", ret);
+
+ strm.next_out = NULL;
+ strm.avail_out = 0;
+ if ((ret = lzma_code(&strm, LZMA_RUN)) != LZMA_OK)
+ maybe_errx("Can't read headers (%d)", ret);
+
+ bytes_out = 0;
+ strm.next_out = obuf;
+ strm.avail_out = sizeof(obuf);
+
+ for (;;) {
+ check_siginfo();
+ if (strm.avail_in == 0) {
+ strm.next_in = ibuf;
+ strm.avail_in = read(i, ibuf, sizeof(ibuf));
+ switch (strm.avail_in) {
+ case (size_t)-1:
+ maybe_err("read failed");
+ /*NOTREACHED*/
+ case 0:
+ action = LZMA_FINISH;
+ break;
+ default:
+ infile_newdata(strm.avail_in);
+ *bytes_in += strm.avail_in;
+ break;
+ }
+ }
+
+ ret = lzma_code(&strm, action);
+
+ // Write and check write error before checking decoder error.
+ // This way as much data as possible gets written to output
+ // even if decoder detected an error.
+ if (strm.avail_out == 0 || ret != LZMA_OK) {
+ const size_t write_size = sizeof(obuf) - strm.avail_out;
+
+ if (write(o, obuf, write_size) != (ssize_t)write_size)
+ maybe_err("write failed");
+
+ strm.next_out = obuf;
+ strm.avail_out = sizeof(obuf);
+ bytes_out += write_size;
+ }
+
+ if (ret != LZMA_OK) {
+ if (ret == LZMA_STREAM_END) {
+ // Check that there's no trailing garbage.
+ if (strm.avail_in != 0 || read(i, ibuf, 1))
+ ret = LZMA_DATA_ERROR;
+ else {
+ lzma_end(&strm);
+ return bytes_out;
+ }
+ }
+
+ const char *msg;
+ switch (ret) {
+ case LZMA_MEM_ERROR:
+ msg = strerror(ENOMEM);
+ break;
+
+ case LZMA_FORMAT_ERROR:
+ msg = "File format not recognized";
+ break;
+
+ case LZMA_OPTIONS_ERROR:
+ // FIXME: Better message?
+ msg = "Unsupported compression options";
+ break;
+
+ case LZMA_DATA_ERROR:
+ msg = "File is corrupt";
+ break;
+
+ case LZMA_BUF_ERROR:
+ msg = "Unexpected end of input";
+ break;
+
+ case LZMA_MEMLIMIT_ERROR:
+ msg = "Reached memory limit";
+ break;
+
+ default:
+ maybe_errx("Unknown error (%d)", ret);
+ break;
+ }
+ maybe_errx("%s", msg);
+
+ }
+ }
+}
+
+#include <stdbool.h>
+
+/*
+ * Copied various bits and pieces from xz support code or brute force
+ * replacements.
+ */
+
+#define my_min(A,B) ((A)<(B)?(A):(B))
+
+// Some systems have suboptimal BUFSIZ. Use a bit bigger value on them.
+// We also need that IO_BUFFER_SIZE is a multiple of 8 (sizeof(uint64_t))
+#if BUFSIZ <= 1024
+# define IO_BUFFER_SIZE 8192
+#else
+# define IO_BUFFER_SIZE (BUFSIZ & ~7U)
+#endif
+
+/// is_sparse() accesses the buffer as uint64_t for maximum speed.
+/// Use an union to make sure that the buffer is properly aligned.
+typedef union {
+ uint8_t u8[IO_BUFFER_SIZE];
+ uint32_t u32[IO_BUFFER_SIZE / sizeof(uint32_t)];
+ uint64_t u64[IO_BUFFER_SIZE / sizeof(uint64_t)];
+} io_buf;
+
+
+static bool
+io_pread(int fd, io_buf *buf, size_t size, off_t pos)
+{
+ // Using lseek() and read() is more portable than pread() and
+ // for us it is as good as real pread().
+ if (lseek(fd, pos, SEEK_SET) != pos) {
+ return true;
+ }
+
+ const size_t amount = read(fd, buf, size);
+ if (amount == SIZE_MAX)
+ return true;
+
+ if (amount != size) {
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Most of the following is copied (mostly verbatim) from the xz
+ * distribution, from file src/xz/list.c
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file list.c
+/// \brief Listing information about .xz files
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+/// Information about a .xz file
+typedef struct {
+ /// Combined Index of all Streams in the file
+ lzma_index *idx;
+
+ /// Total amount of Stream Padding
+ uint64_t stream_padding;
+
+ /// Highest memory usage so far
+ uint64_t memusage_max;
+
+ /// True if all Blocks so far have Compressed Size and
+ /// Uncompressed Size fields
+ bool all_have_sizes;
+
+ /// Oldest XZ Utils version that will decompress the file
+ uint32_t min_version;
+
+} xz_file_info;
+
+#define XZ_FILE_INFO_INIT { NULL, 0, 0, true, 50000002 }
+
+
+/// \brief Parse the Index(es) from the given .xz file
+///
+/// \param xfi Pointer to structure where the decoded information
+/// is stored.
+/// \param pair Input file
+///
+/// \return On success, false is returned. On error, true is returned.
+///
+// TODO: This function is pretty big. liblzma should have a function that
+// takes a callback function to parse the Index(es) from a .xz file to make
+// it easy for applications.
+static bool
+parse_indexes(xz_file_info *xfi, int src_fd)
+{
+ struct stat st;
+
+ if (fstat(src_fd, &st) != 0) {
+ return true;
+ }
+
+ if (st.st_size < 2 * LZMA_STREAM_HEADER_SIZE) {
+ return true;
+ }
+
+ io_buf buf;
+ lzma_stream_flags header_flags;
+ lzma_stream_flags footer_flags;
+ lzma_ret ret;
+
+ // lzma_stream for the Index decoder
+ lzma_stream strm = LZMA_STREAM_INIT;
+
+ // All Indexes decoded so far
+ lzma_index *combined_index = NULL;
+
+ // The Index currently being decoded
+ lzma_index *this_index = NULL;
+
+ // Current position in the file. We parse the file backwards so
+ // initialize it to point to the end of the file.
+ off_t pos = st.st_size;
+
+ // Each loop iteration decodes one Index.
+ do {
+ // Check that there is enough data left to contain at least
+ // the Stream Header and Stream Footer. This check cannot
+ // fail in the first pass of this loop.
+ if (pos < 2 * LZMA_STREAM_HEADER_SIZE) {
+ goto error;
+ }
+
+ pos -= LZMA_STREAM_HEADER_SIZE;
+ lzma_vli stream_padding = 0;
+
+ // Locate the Stream Footer. There may be Stream Padding which
+ // we must skip when reading backwards.
+ while (true) {
+ if (pos < LZMA_STREAM_HEADER_SIZE) {
+ goto error;
+ }
+
+ if (io_pread(src_fd, &buf,
+ LZMA_STREAM_HEADER_SIZE, pos))
+ goto error;
+
+ // Stream Padding is always a multiple of four bytes.
+ int i = 2;
+ if (buf.u32[i] != 0)
+ break;
+
+ // To avoid calling io_pread() for every four bytes
+ // of Stream Padding, take advantage that we read
+ // 12 bytes (LZMA_STREAM_HEADER_SIZE) already and
+ // check them too before calling io_pread() again.
+ do {
+ stream_padding += 4;
+ pos -= 4;
+ --i;
+ } while (i >= 0 && buf.u32[i] == 0);
+ }
+
+ // Decode the Stream Footer.
+ ret = lzma_stream_footer_decode(&footer_flags, buf.u8);
+ if (ret != LZMA_OK) {
+ goto error;
+ }
+
+ // Check that the Stream Footer doesn't specify something
+ // that we don't support. This can only happen if the xz
+ // version is older than liblzma and liblzma supports
+ // something new.
+ //
+ // It is enough to check Stream Footer. Stream Header must
+ // match when it is compared against Stream Footer with
+ // lzma_stream_flags_compare().
+ if (footer_flags.version != 0) {
+ goto error;
+ }
+
+ // Check that the size of the Index field looks sane.
+ lzma_vli index_size = footer_flags.backward_size;
+ if ((lzma_vli)(pos) < index_size + LZMA_STREAM_HEADER_SIZE) {
+ goto error;
+ }
+
+ // Set pos to the beginning of the Index.
+ pos -= index_size;
+
+ // Decode the Index.
+ ret = lzma_index_decoder(&strm, &this_index, UINT64_MAX);
+ if (ret != LZMA_OK) {
+ goto error;
+ }
+
+ do {
+ // Don't give the decoder more input than the
+ // Index size.
+ strm.avail_in = my_min(IO_BUFFER_SIZE, index_size);
+ if (io_pread(src_fd, &buf, strm.avail_in, pos))
+ goto error;
+
+ pos += strm.avail_in;
+ index_size -= strm.avail_in;
+
+ strm.next_in = buf.u8;
+ ret = lzma_code(&strm, LZMA_RUN);
+
+ } while (ret == LZMA_OK);
+
+ // If the decoding seems to be successful, check also that
+ // the Index decoder consumed as much input as indicated
+ // by the Backward Size field.
+ if (ret == LZMA_STREAM_END)
+ if (index_size != 0 || strm.avail_in != 0)
+ ret = LZMA_DATA_ERROR;
+
+ if (ret != LZMA_STREAM_END) {
+ // LZMA_BUFFER_ERROR means that the Index decoder
+ // would have liked more input than what the Index
+ // size should be according to Stream Footer.
+ // The message for LZMA_DATA_ERROR makes more
+ // sense in that case.
+ if (ret == LZMA_BUF_ERROR)
+ ret = LZMA_DATA_ERROR;
+
+ goto error;
+ }
+
+ // Decode the Stream Header and check that its Stream Flags
+ // match the Stream Footer.
+ pos -= footer_flags.backward_size + LZMA_STREAM_HEADER_SIZE;
+ if ((lzma_vli)(pos) < lzma_index_total_size(this_index)) {
+ goto error;
+ }
+
+ pos -= lzma_index_total_size(this_index);
+ if (io_pread(src_fd, &buf, LZMA_STREAM_HEADER_SIZE, pos))
+ goto error;
+
+ ret = lzma_stream_header_decode(&header_flags, buf.u8);
+ if (ret != LZMA_OK) {
+ goto error;
+ }
+
+ ret = lzma_stream_flags_compare(&header_flags, &footer_flags);
+ if (ret != LZMA_OK) {
+ goto error;
+ }
+
+ // Store the decoded Stream Flags into this_index. This is
+ // needed so that we can print which Check is used in each
+ // Stream.
+ ret = lzma_index_stream_flags(this_index, &footer_flags);
+ if (ret != LZMA_OK)
+ goto error;
+
+ // Store also the size of the Stream Padding field. It is
+ // needed to show the offsets of the Streams correctly.
+ ret = lzma_index_stream_padding(this_index, stream_padding);
+ if (ret != LZMA_OK)
+ goto error;
+
+ if (combined_index != NULL) {
+ // Append the earlier decoded Indexes
+ // after this_index.
+ ret = lzma_index_cat(
+ this_index, combined_index, NULL);
+ if (ret != LZMA_OK) {
+ goto error;
+ }
+ }
+
+ combined_index = this_index;
+ this_index = NULL;
+
+ xfi->stream_padding += stream_padding;
+
+ } while (pos > 0);
+
+ lzma_end(&strm);
+
+ // All OK. Make combined_index available to the caller.
+ xfi->idx = combined_index;
+ return false;
+
+error:
+ // Something went wrong, free the allocated memory.
+ lzma_end(&strm);
+ lzma_index_end(combined_index, NULL);
+ lzma_index_end(this_index, NULL);
+ return true;
+}
+
+/***************** end of copy form list.c *************************/
+
+/*
+ * Small wrapper to extract total length of a file
+ */
+off_t
+unxz_len(int fd)
+{
+ xz_file_info xfi = XZ_FILE_INFO_INIT;
+ if (!parse_indexes(&xfi, fd)) {
+ off_t res = lzma_index_uncompressed_size(xfi.idx);
+ lzma_index_end(xfi.idx, NULL);
+ return res;
+ }
+ return 0;
+}
+
diff --git a/usr.bin/gzip/unzstd.c b/usr.bin/gzip/unzstd.c
new file mode 100644
index 000000000000..4536f3119ace
--- /dev/null
+++ b/usr.bin/gzip/unzstd.c
@@ -0,0 +1,89 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Klara, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 file is #included by gzip.c */
+
+static off_t
+unzstd(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
+{
+ static char *ibuf, *obuf;
+ ZSTD_inBuffer zib;
+ ZSTD_outBuffer zob;
+ ZSTD_DCtx *zds;
+ ssize_t res;
+ size_t zres;
+ size_t bytes_out = 0;
+ int eof = 0;
+
+ if (ibuf == NULL)
+ ibuf = malloc(BUFLEN);
+ if (obuf == NULL)
+ obuf = malloc(BUFLEN);
+ if (ibuf == NULL || obuf == NULL)
+ maybe_err("malloc");
+
+ zds = ZSTD_createDStream();
+ ZSTD_initDStream(zds);
+
+ zib.src = pre;
+ zib.size = prelen;
+ zib.pos = 0;
+ if (bytes_in != NULL)
+ *bytes_in = prelen;
+ zob.dst = obuf;
+ zob.size = BUFLEN;
+ zob.pos = 0;
+
+ while (!eof) {
+ if (zib.pos >= zib.size) {
+ res = read(in, ibuf, BUFLEN);
+ if (res < 0)
+ maybe_err("read");
+ if (res == 0)
+ eof = 1;
+ infile_newdata(res);
+ zib.src = ibuf;
+ zib.size = res;
+ zib.pos = 0;
+ if (bytes_in != NULL)
+ *bytes_in += res;
+ }
+ zres = ZSTD_decompressStream(zds, &zob, &zib);
+ if (ZSTD_isError(zres)) {
+ maybe_errx("%s", ZSTD_getErrorName(zres));
+ }
+ if (zob.pos > 0) {
+ res = write(out, obuf, zob.pos);
+ if (res < 0)
+ maybe_err("write");
+ zob.pos = 0;
+ bytes_out += res;
+ }
+ }
+ ZSTD_freeDStream(zds);
+ return (bytes_out);
+}
diff --git a/usr.bin/gzip/zdiff b/usr.bin/gzip/zdiff
new file mode 100644
index 000000000000..f0f8c2d64681
--- /dev/null
+++ b/usr.bin/gzip/zdiff
@@ -0,0 +1,141 @@
+#!/bin/sh -
+#
+# $NetBSD: zdiff,v 1.5 2010/04/14 20:30:28 joerg Exp $
+#
+# $OpenBSD: zdiff,v 1.2 2003/07/29 07:42:44 otto Exp $
+#
+#-
+# Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+# Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Sponsored in part by the Defense Advanced Research Projects
+# Agency (DARPA) and Air Force Research Laboratory, Air Force
+# Materiel Command, USAF, under agreement number F39502-99-1-0512.
+#
+
+# Set $prog based on $0
+case $0 in
+ *cmp) prog=cmp
+ ;;
+ *) prog=diff
+ ;;
+esac
+USAGE="usage: $0 [options] file1 [file2]"
+
+check_suffix() {
+ case "$1" in
+ *[._-][Zz])
+ eval "$2=\${1%??}"
+ eval "$3=\"gzip -cdqf\""
+ ;;
+ *[._-]bz)
+ eval "$2=\${1%???}"
+ eval "$3=\"bzip2 -cdqf\""
+ ;;
+ *[._-]gz)
+ eval "$2=\${1%???}"
+ eval "$3=\"gzip -cdqf\""
+ ;;
+ *[._-]xz)
+ eval "$2=\${1%???}"
+ eval "$3=\"xz -cdqf\""
+ ;;
+ *[._-]bz2)
+ eval "$2=\${1%????}"
+ eval "$3=\"bzip2 -cdqf\""
+ ;;
+ *[._-]lzma)
+ eval "$2=\${1%?????}"
+ eval "$3=\"xz -cdqf\""
+ ;;
+ *.t[ag]z)
+ eval "$2=\${1%??}ar"
+ eval "$3=\"gzip -cdqf\""
+ ;;
+ *.tbz)
+ eval "$2=\${1%??}ar"
+ eval "$3=\"bzip2 -cdqf\""
+ ;;
+ *.tbz2)
+ eval "$2=\${1%???}ar"
+ eval "$3=\"bzip2 -cdqf\""
+ ;;
+ *.t[lx]z)
+ eval "$2=\${1%??}ar"
+ eval "$3=\"xz -cdqf\""
+ ;;
+ *)
+ eval "$2=\$1"
+ eval "$3=\"\""
+ ;;
+ esac
+}
+
+
+# Pull out any command line flags so we can pass them to diff/cmp
+# XXX - assumes there is no optarg
+flags=
+while test $# -ne 0; do
+ case "$1" in
+ --)
+ shift
+ break
+ ;;
+ -)
+ break
+ ;;
+ -*)
+ flags="$flags $1"
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+if [ $# -eq 1 ]; then
+ # One file given, compare compressed to uncompressed
+ files="$1"
+ check_suffix "$1" files filt
+ if [ -z "$filt" ]; then
+ echo "z$prog: unknown suffix" 1>&2
+ exit 1
+ fi
+ $filt -- "$1" | $prog $flags -- - "$files"
+ status=$?
+elif [ $# -eq 2 ]; then
+ # Two files given, compare the two uncompressing as needed
+ check_suffix "$1" files filt
+ check_suffix "$2" files2 filt2
+ if [ -z "$filt" -a -z "$filt2" ]; then
+ $prog $flags -- "$1" "$2"
+ elif [ -z "$filt" -a -n "$filt2" -a "$1" != "-" ]; then
+ $filt2 -- "$2" | $prog $flags -- "$1" -
+ elif [ -n "$filt" -a -z "$filt2" -a "$2" != "-" ]; then
+ $filt -- "$1" | $prog $flags -- - "$2"
+ else
+ tmp=`mktemp -t z$prog.XXXXXXXXXX` || exit 1
+ trap "rm -f $tmp" 0 1 2 3 13 15
+ ${filt2:-cat} -- "$2" > $tmp || exit $?
+ ${filt:-cat} -- "$1" | $prog $flags -- - "$tmp"
+ fi
+ status=$?
+else
+ echo "$USAGE" 1>&2
+ exit 1
+fi
+
+exit $status
diff --git a/usr.bin/gzip/zdiff.1 b/usr.bin/gzip/zdiff.1
new file mode 100644
index 000000000000..3ce1663ae1ce
--- /dev/null
+++ b/usr.bin/gzip/zdiff.1
@@ -0,0 +1,140 @@
+.\" $NetBSD: zdiff.1,v 1.5 2010/04/14 19:52:05 wiz Exp $
+.\" $OpenBSD: zdiff.1,v 1.2 2003/07/13 17:39:14 millert Exp $
+.\"
+.\" Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+.\" Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.Dd May 23, 2011
+.Dt ZDIFF 1
+.Os
+.Sh NAME
+.Nm zcmp ,
+.Nm zdiff
+.Nd compare compressed files
+.Sh SYNOPSIS
+.Nm zcmp
+.Op Ar options
+.Ar file
+.Op Ar file2
+.Nm zdiff
+.Op Ar options
+.Ar file
+.Op Ar file2
+.Sh DESCRIPTION
+.Nm zcmp
+and
+.Nm zdiff
+are filters that invoke
+.Xr cmp 1
+or
+.Xr diff 1
+respectively to compare compressed files.
+Any
+.Ar options
+that are specified are passed to
+.Xr cmp 1
+or
+.Xr diff 1 .
+.Pp
+If only
+.Ar file1
+is specified, it is compared against a file with the same name, but
+with the extension removed.
+When both
+.Ar file1
+or
+.Ar file2
+are specified, either file may be compressed.
+.Pp
+Extensions handled by
+.Xr gzip 1 :
+.Bl -bullet -compact
+.It
+z, Z,
+.It
+gz,
+.It
+taz,
+.It
+tgz.
+.El
+.Pp
+Extensions handled by
+.Xr bzip2 1 :
+.Bl -bullet -compact
+.It
+bz,
+.It
+bz2,
+.It
+tbz,
+.It
+tbz2.
+.El
+.Pp
+Extensions handled by
+.Xr xz 1 :
+.Bl -bullet -compact
+.It
+lzma,
+.It
+xz,
+.It
+tlz,
+.It
+txz.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width "TMPDIR"
+.It Ev TMPDIR
+Directory in which to place temporary files.
+If unset,
+.Pa /tmp
+is used.
+.El
+.Sh FILES
+.Bl -tag -width "/tmp/zdiff.XXXXXXXXXX" -compact
+.It Pa /tmp/zcmp.XXXXXXXXXX
+Temporary file for
+.Nm zcmp .
+.It Pa /tmp/zdiff.XXXXXXXXXX
+Temporary file for
+.Nm zdiff .
+.El
+.Sh SEE ALSO
+.Xr bzip2 1 ,
+.Xr cmp 1 ,
+.Xr diff 1 ,
+.Xr gzip 1 ,
+.Xr xz 1
+.Sh CAVEATS
+.Nm zcmp
+and
+.Nm zdiff
+rely solely on the file extension to determine what is, or is not,
+a compressed file.
+Consequently, the following are not supported as arguments:
+.Bl -dash
+.It
+directories
+.It
+device special files
+.It
+filenames indicating the standard input
+.Pq Dq \-
+.El
diff --git a/usr.bin/gzip/zforce b/usr.bin/gzip/zforce
new file mode 100644
index 000000000000..06c897ddf709
--- /dev/null
+++ b/usr.bin/gzip/zforce
@@ -0,0 +1,54 @@
+#!/bin/sh -
+#
+# $NetBSD: zforce,v 1.2 2003/12/28 12:43:43 wiz Exp $
+# $OpenBSD: zforce,v 1.2 2003/08/05 18:22:17 deraadt Exp $
+#
+#-
+# Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+prog=`basename $0`
+USAGE="usage: $prog file ..."
+if test $# -eq 0; then
+ echo $USAGE
+ exit 1
+fi
+
+ret=0
+
+while test $# -ne 0; do
+ case "$1" in
+ *[._-]gz)
+ shift
+ ;;
+ *.t[ag]z)
+ shift
+ ;;
+ *)
+ if file "$1" |
+ grep -q "gzip compressed data" 2> /dev/null
+ then
+ n="$1".gz
+ if mv "$1" "$n" 2> /dev/null; then
+ echo "$1" -- renamed to "$n"
+ else
+ ret=1
+ echo $prog: cannot rename "$1" to "$n"
+ fi
+ fi
+ shift
+ ;;
+ esac
+done
+exit $ret
diff --git a/usr.bin/gzip/zforce.1 b/usr.bin/gzip/zforce.1
new file mode 100644
index 000000000000..10010d61cc14
--- /dev/null
+++ b/usr.bin/gzip/zforce.1
@@ -0,0 +1,51 @@
+.\" $NetBSD: zforce.1,v 1.2 2003/12/28 12:43:43 wiz Exp $
+.\" $OpenBSD: zforce.1,v 1.1 2003/07/29 11:50:09 otto Exp $
+.\"
+.\" Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.Dd January 26, 2007
+.Dt ZFORCE 1
+.Os
+.Sh NAME
+.Nm zforce
+.Nd force gzip files to have a .gz suffix
+.Sh SYNOPSIS
+.Nm zforce
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility renames
+.Xr gzip 1
+files to have a
+.Sq .gz
+suffix, so that
+.Xr gzip 1
+will not compress them twice.
+This can be useful if file names were truncated during a file transfer.
+Files that have an existing
+.Sq .gz ,
+.Sq -gz ,
+.Sq _gz ,
+.Sq .tgz
+or
+.Sq .taz
+suffix, or that have not been compressed by
+.Xr gzip 1 ,
+are ignored.
+.Sh SEE ALSO
+.Xr gzip 1
+.Sh CAVEATS
+.Nm
+overwrites existing files without warning.
diff --git a/usr.bin/gzip/zmore b/usr.bin/gzip/zmore
new file mode 100644
index 000000000000..fb195c482a99
--- /dev/null
+++ b/usr.bin/gzip/zmore
@@ -0,0 +1,81 @@
+#!/bin/sh -
+#
+# $NetBSD: zmore,v 1.5 2013/12/06 13:33:15 pettai Exp $
+#
+# $OpenBSD: zmore,v 1.6 2008/08/20 09:22:02 mpf Exp $
+#
+#-
+# Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Sponsored in part by the Defense Advanced Research Projects
+# Agency (DARPA) and Air Force Research Laboratory, Air Force
+# Materiel Command, USAF, under agreement number F39502-99-1-0512.
+#
+
+# Pull out any command line flags so we can pass them to more/less
+flags=
+while test $# -ne 0; do
+ case "$1" in
+ --)
+ shift
+ break
+ ;;
+ -*)
+ flags="$flags $1"
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+if [ `basename $0` = "zless" ] ; then
+ pager=${PAGER-less}
+else
+ pager=${PAGER-more}
+fi
+
+# No files means read from stdin
+if [ $# -eq 0 ]; then
+ gzip -cdfq 2>&1 | $pager $flags
+ exit 0
+fi
+
+oterm=`stty -g 2>/dev/null`
+while test $# -ne 0; do
+ gzip -cdfq "$1" 2>&1 | $pager $flags
+ prev="$1"
+ shift
+ if tty -s && test -n "$oterm" -a $# -gt 0; then
+ #echo -n "--More--(Next file: $1)"
+ echo -n "$prev (END) - Next: $1 "
+ trap "stty $oterm 2>/dev/null" 0 1 2 3 13 15
+ stty cbreak -echo 2>/dev/null
+ REPLY=`dd bs=1 count=1 2>/dev/null`
+ stty $oterm 2>/dev/null
+ trap - 0 1 2 3 13 15
+ echo
+ case "$REPLY" in
+ s)
+ shift
+ ;;
+ e|q)
+ break
+ ;;
+ esac
+ fi
+done
+exit 0
diff --git a/usr.bin/gzip/zmore.1 b/usr.bin/gzip/zmore.1
new file mode 100644
index 000000000000..5e0acc9b5901
--- /dev/null
+++ b/usr.bin/gzip/zmore.1
@@ -0,0 +1,108 @@
+.\" $NetBSD: zmore.1,v 1.4 2013/11/12 21:58:37 pettai Exp $
+.\" $OpenBSD: zmore.1,v 1.10 2009/08/16 09:41:08 sobrado Exp $
+.\"
+.\" Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.Dd October 22, 2014
+.Dt ZMORE 1
+.Os
+.Sh NAME
+.Nm zmore ,
+.Nm zless
+.Nd view compressed files
+.Sh SYNOPSIS
+.Nm zmore
+.Op Ar flags
+.Op Ar
+.Nm zless
+.Op Ar flags
+.Op Ar
+.Sh DESCRIPTION
+.Nm
+is a filter that allows the viewing of files compressed with Lempel-Ziv
+encoding.
+Such files generally have a
+.Dq Z
+or
+.Dq gz
+extension (both the
+.Xr compress 1
+and
+.Xr gzip 1
+formats are supported).
+Any
+.Ar flags
+that are specified are passed to the user's preferred
+.Ev PAGER
+(which is
+.Pa /usr/bin/more
+by default).
+.Pp
+.Nm zless
+is equivalent to
+.Nm zmore
+but uses
+.Xr less 1
+as a pager instead of
+.Xr more 1 .
+.Pp
+When multiple files are specified,
+.Nm
+will pause at the end of each file and present the following prompt to the user:
+.Bd -literal -offset indent
+prev_file (END) - Next: next_file
+.Ed
+.Pp
+Where
+.Sy prev_file
+is the file that was just displayed and
+.Sy next_file
+is the next file to be displayed.
+The following keys are recognized at the prompt:
+.Bl -tag -width "e or q" -offset indent
+.It Ic e No or Ic q
+quit
+.Nm zmore .
+.It Ic s
+skip the next file (or exit if the next file is the last).
+.El
+.Pp
+If no files are specified,
+.Nm
+will read from the standard input.
+In this mode
+.Nm
+will assume
+.Xr gzip 1
+style compression since there is no suffix on which to make a decision.
+.Sh ENVIRONMENT
+.Bl -tag -width "PAGER"
+.It Ev PAGER
+Program used to display files.
+If unset,
+.Pa /usr/bin/more
+is used
+.Pq Nm zmore
+or
+.Pa /usr/bin/less
+.Pq Nm zless .
+.El
+.Sh SEE ALSO
+.Xr compress 1 ,
+.Xr less 1 ,
+.Xr more 1
diff --git a/usr.bin/gzip/znew b/usr.bin/gzip/znew
new file mode 100644
index 000000000000..498c1b70622d
--- /dev/null
+++ b/usr.bin/gzip/znew
@@ -0,0 +1,136 @@
+#!/bin/sh -
+#
+# $NetBSD: znew,v 1.3 2008/04/27 09:07:13 nakayama Exp $
+# $OpenBSD: znew,v 1.2 2003/08/05 18:22:17 deraadt Exp $
+#
+#-
+# Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+# Return 0 if the first arg file size is smaller than the second, 1 otherwise.
+smaller () {
+ a=`du -k "$1" | awk '{ print $1 }'`
+ b=`du -k "$2" | awk '{ print $1 }'`
+ test $a -lt $b
+}
+
+# Check gzip integrity if the -t flag is specified
+checkfile () {
+ if test $tflag -eq 1; then
+ gzip -qt < "$1"
+ fi
+}
+
+# Decompress a file and then gzip it
+process () {
+ prefix="${1%.Z}"
+ filez="$prefix".Z
+ filegz="$prefix".gz
+
+ if test ! -e "$filez"; then
+ echo "$prog: $filez does not exist"
+ return 1
+ fi
+ if test ! -f "$filez"; then
+ echo "$prog: $filez is not a regular file"
+ return 1
+ fi
+ if test -e "$filegz" -a $fflag -eq 0; then
+ echo "$prog: $filegz already exists"
+ return 1
+ fi
+
+ tmp=`mktemp /tmp/znewXXXXXXXXXX` || {
+ echo "$prog: cannot create tmp file"
+ return 1
+ }
+ trap 'rm -f "$tmp"; exit 1' HUP INT QUIT PIPE TERM
+
+ # Do the actual work, producing a file "$tmp"
+ if uncompress -f -c < "$filez" | gzip -f -c $gzipflags > "$tmp"; then
+ if test $kflag -eq 1 && smaller "$filez" "$tmp"; then
+ echo -n "$prog: $filez is smaller than $filegz"
+ echo "; keeping it"
+ rm -f "$tmp"
+ return 0
+ fi
+ if ! checkfile "$tmp"; then
+ echo "$prog: integrity check of $tmp failed"
+ rm -f "$tmp"
+ return 1;
+ fi
+
+ # Try to keep the mode of the original file
+ if ! cp -fp "$filez" "$filegz"; then
+ echo "$prog: warning: could not keep mode of $filez"
+ fi
+ if ! cp "$tmp" "$filegz" 2> /dev/null; then
+ echo "$prog: warning: could not keep mode of $filez"
+ if ! cp -f "$tmp" "$filegz" 2> /dev/null; then
+ echo "$prog: could not copy $tmp to $filegz"
+ rm -f "$filegz" "$tmp"
+ return 1
+ fi
+ fi
+ if ! touch -fr "$filez" "$filegz"; then
+ echo -n "$prog: warning: could not keep timestamp of "
+ echo "$filez"
+ fi
+ rm -f "$filez" "$tmp"
+ else
+ echo "$prog: failed to process $filez"
+ rm -f "$tmp"
+ return 1
+ fi
+}
+
+prog=`basename "$0"`
+usage="usage: $prog [-ftv9K] file ..."
+
+fflag=0
+tflag=0
+kflag=0
+gzipflags=
+
+# -P flag is recognized to maintain compatibility, but ignored. Pipe mode is
+# always used
+while getopts :ftv9PK i; do
+ case $i in
+ f) fflag=1;;
+ t) tflag=1;;
+ v) gzipflags="-v $gzipflags";;
+ 9) gzipflags="-9 $gzipflags";;
+ P) ;;
+ K) kflag=1;;
+ \?) echo "$usage"; exit 1;;
+ esac
+done
+
+shift $((OPTIND - 1))
+
+if test $# -eq 0; then
+ echo "$usage"
+ exit 1
+fi
+
+rc=0
+
+while test $# -ne 0; do
+ if ! process "$1"; then
+ rc=$?
+ fi
+ shift
+done
+exit $rc
diff --git a/usr.bin/gzip/znew.1 b/usr.bin/gzip/znew.1
new file mode 100644
index 000000000000..0b97fe6f4a9f
--- /dev/null
+++ b/usr.bin/gzip/znew.1
@@ -0,0 +1,69 @@
+.\" $NetBSD: znew.1,v 1.2 2003/12/28 12:43:43 wiz Exp $
+.\" $OpenBSD: znew.1,v 1.1 2003/08/02 20:52:50 otto Exp $
+.\"
+.\" Copyright (c) 2003 Otto Moerbeek <otto@drijf.net>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.Dd January 26, 2007
+.Dt ZNEW 1
+.Os
+.Sh NAME
+.Nm znew
+.Nd convert compressed files to gzipped files
+.Sh SYNOPSIS
+.Nm
+.Op Fl ftv9K
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility uncompresses files compressed by
+.Xr compress 1
+and recompresses them with
+.Xr gzip 1 .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+Overwrite existing
+.Sq .gz
+files.
+Unless this option is specified,
+.Nm
+refuses to overwrite existing files.
+.It Fl t
+Test integrity of the gzipped file before deleting the original file.
+If the integrity check fails, the original
+.Sq .Z
+file is not removed.
+.It Fl v
+Print a report specifying the achieved compression ratios.
+.It Fl 9
+Use the -9 mode of
+.Xr gzip 1 ,
+achieving better compression at the cost of slower execution.
+.It Fl K
+Keep the original
+.Sq .Z
+file if it uses less disk blocks than the gzipped one.
+A disk block is 1024 bytes.
+.El
+.Sh SEE ALSO
+.Xr gzip 1
+.Sh CAVEATS
+The
+.Nm
+utility tries to maintain the file mode of the original file.
+If the original file is not writable, it is not able to do that and
+.Nm
+will print a warning.
diff --git a/usr.bin/gzip/zuncompress.c b/usr.bin/gzip/zuncompress.c
new file mode 100644
index 000000000000..79f3983037f7
--- /dev/null
+++ b/usr.bin/gzip/zuncompress.c
@@ -0,0 +1,397 @@
+/* $NetBSD: zuncompress.c,v 1.11 2011/08/16 13:55:02 joerg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1985, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis and James A. Woods, derived from original
+ * work by Spencer Thomas and Joseph Orost.
+ *
+ * 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: NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp
+ */
+
+/* This file is #included by gzip.c */
+
+static int zread(void *, char *, int);
+
+#define tab_prefixof(i) (zs->zs_codetab[i])
+#define tab_suffixof(i) ((char_type *)(zs->zs_htab))[i]
+#define de_stack ((char_type *)&tab_suffixof(1 << BITS))
+
+#define BITS 16 /* Default bits. */
+#define HSIZE 69001 /* 95% occupancy */ /* XXX may not need HSIZE */
+#define BIT_MASK 0x1f /* Defines for third byte of header. */
+#define BLOCK_MASK 0x80
+#define CHECK_GAP 10000 /* Ratio check interval. */
+#define BUFSIZE (64 * 1024)
+
+/*
+ * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
+ * a fourth header byte (for expansion).
+ */
+#define INIT_BITS 9 /* Initial number of bits/code. */
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* First free entry. */
+#define CLEAR 256 /* Table clear output code. */
+
+
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+typedef long code_int;
+typedef long count_int;
+typedef u_char char_type;
+
+static char_type magic_header[] =
+ {'\037', '\235'}; /* 1F 9D */
+
+static char_type rmask[9] =
+ {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+static off_t total_compressed_bytes;
+static size_t compressed_prelen;
+static char *compressed_pre;
+
+struct s_zstate {
+ FILE *zs_fp; /* File stream for I/O */
+ char zs_mode; /* r or w */
+ enum {
+ S_START, S_MIDDLE, S_EOF
+ } zs_state; /* State of computation */
+ int zs_n_bits; /* Number of bits/code. */
+ int zs_maxbits; /* User settable max # bits/code. */
+ code_int zs_maxcode; /* Maximum code, given n_bits. */
+ code_int zs_maxmaxcode; /* Should NEVER generate this code. */
+ count_int zs_htab [HSIZE];
+ u_short zs_codetab [HSIZE];
+ code_int zs_hsize; /* For dynamic table sizing. */
+ code_int zs_free_ent; /* First unused entry. */
+ /*
+ * Block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+ int zs_block_compress;
+ int zs_clear_flg;
+ long zs_ratio;
+ count_int zs_checkpoint;
+ int zs_offset;
+ long zs_in_count; /* Length of input. */
+ long zs_bytes_out; /* Length of compressed output. */
+ long zs_out_count; /* # of codes output (for debugging). */
+ char_type zs_buf[BITS];
+ union {
+ struct {
+ long zs_fcode;
+ code_int zs_ent;
+ code_int zs_hsize_reg;
+ int zs_hshift;
+ } w; /* Write parameters */
+ struct {
+ char_type *zs_stackp;
+ int zs_finchar;
+ code_int zs_code, zs_oldcode, zs_incode;
+ int zs_roffset, zs_size;
+ char_type zs_gbuf[BITS];
+ } r; /* Read parameters */
+ } u;
+};
+
+static code_int getcode(struct s_zstate *zs);
+
+static off_t
+zuncompress(FILE *in, FILE *out, char *pre, size_t prelen,
+ off_t *compressed_bytes)
+{
+ off_t bin, bout = 0;
+ char *buf;
+
+ buf = malloc(BUFSIZE);
+ if (buf == NULL)
+ return -1;
+
+ /* XXX */
+ compressed_prelen = prelen;
+ if (prelen != 0)
+ compressed_pre = pre;
+ else
+ compressed_pre = NULL;
+
+ while ((bin = fread(buf, 1, BUFSIZE, in)) != 0) {
+ if (tflag == 0 && (off_t)fwrite(buf, 1, bin, out) != bin) {
+ free(buf);
+ return -1;
+ }
+ bout += bin;
+ }
+
+ if (compressed_bytes)
+ *compressed_bytes = total_compressed_bytes;
+
+ free(buf);
+ return bout;
+}
+
+static int
+zclose(void *zs)
+{
+ free(zs);
+ /* We leave the caller to close the fd passed to zdopen() */
+ return 0;
+}
+
+FILE *
+zdopen(int fd)
+{
+ struct s_zstate *zs;
+
+ if ((zs = calloc(1, sizeof(struct s_zstate))) == NULL)
+ return (NULL);
+
+ zs->zs_state = S_START;
+
+ /* XXX we can get rid of some of these */
+ zs->zs_hsize = HSIZE; /* For dynamic table sizing. */
+ zs->zs_free_ent = 0; /* First unused entry. */
+ zs->zs_block_compress = BLOCK_MASK;
+ zs->zs_clear_flg = 0; /* XXX we calloc()'d this structure why = 0? */
+ zs->zs_ratio = 0;
+ zs->zs_checkpoint = CHECK_GAP;
+ zs->zs_in_count = 1; /* Length of input. */
+ zs->zs_out_count = 0; /* # of codes output (for debugging). */
+ zs->u.r.zs_roffset = 0;
+ zs->u.r.zs_size = 0;
+
+ /*
+ * Layering compress on top of stdio in order to provide buffering,
+ * and ensure that reads and write work with the data specified.
+ */
+ if ((zs->zs_fp = fdopen(fd, "r")) == NULL) {
+ free(zs);
+ return NULL;
+ }
+
+ return funopen(zs, zread, NULL, NULL, zclose);
+}
+
+/*
+ * Decompress read. This routine adapts to the codes in the file building
+ * the "string" table on-the-fly; requiring no table to be stored in the
+ * compressed file. The tables used herein are shared with those of the
+ * compress() routine. See the definitions above.
+ */
+static int
+zread(void *cookie, char *rbp, int num)
+{
+ u_int count, i;
+ struct s_zstate *zs;
+ u_char *bp, header[3];
+
+ if (num == 0)
+ return (0);
+
+ zs = cookie;
+ count = num;
+ bp = (u_char *)rbp;
+ switch (zs->zs_state) {
+ case S_START:
+ zs->zs_state = S_MIDDLE;
+ break;
+ case S_MIDDLE:
+ goto middle;
+ case S_EOF:
+ goto eof;
+ }
+
+ /* Check the magic number */
+ for (i = 0; i < 3 && compressed_prelen; i++, compressed_prelen--)
+ header[i] = *compressed_pre++;
+
+ if (fread(header + i, 1, sizeof(header) - i, zs->zs_fp) !=
+ sizeof(header) - i ||
+ memcmp(header, magic_header, sizeof(magic_header)) != 0) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ total_compressed_bytes = 0;
+ zs->zs_maxbits = header[2]; /* Set -b from file. */
+ zs->zs_block_compress = zs->zs_maxbits & BLOCK_MASK;
+ zs->zs_maxbits &= BIT_MASK;
+ zs->zs_maxmaxcode = 1L << zs->zs_maxbits;
+ if (zs->zs_maxbits > BITS || zs->zs_maxbits < 12) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ /* As above, initialize the first 256 entries in the table. */
+ zs->zs_maxcode = MAXCODE(zs->zs_n_bits = INIT_BITS);
+ for (zs->u.r.zs_code = 255; zs->u.r.zs_code >= 0; zs->u.r.zs_code--) {
+ tab_prefixof(zs->u.r.zs_code) = 0;
+ tab_suffixof(zs->u.r.zs_code) = (char_type) zs->u.r.zs_code;
+ }
+ zs->zs_free_ent = zs->zs_block_compress ? FIRST : 256;
+
+ zs->u.r.zs_oldcode = -1;
+ zs->u.r.zs_stackp = de_stack;
+
+ while ((zs->u.r.zs_code = getcode(zs)) > -1) {
+
+ if ((zs->u.r.zs_code == CLEAR) && zs->zs_block_compress) {
+ for (zs->u.r.zs_code = 255; zs->u.r.zs_code >= 0;
+ zs->u.r.zs_code--)
+ tab_prefixof(zs->u.r.zs_code) = 0;
+ zs->zs_clear_flg = 1;
+ zs->zs_free_ent = FIRST;
+ zs->u.r.zs_oldcode = -1;
+ continue;
+ }
+ zs->u.r.zs_incode = zs->u.r.zs_code;
+
+ /* Special case for KwKwK string. */
+ if (zs->u.r.zs_code >= zs->zs_free_ent) {
+ if (zs->u.r.zs_code > zs->zs_free_ent ||
+ zs->u.r.zs_oldcode == -1) {
+ /* Bad stream. */
+ errno = EFTYPE;
+ return (-1);
+ }
+ *zs->u.r.zs_stackp++ = zs->u.r.zs_finchar;
+ zs->u.r.zs_code = zs->u.r.zs_oldcode;
+ }
+ /*
+ * The above condition ensures that code < free_ent.
+ * The construction of tab_prefixof in turn guarantees that
+ * each iteration decreases code and therefore stack usage is
+ * bound by 1 << BITS - 256.
+ */
+
+ /* Generate output characters in reverse order. */
+ while (zs->u.r.zs_code >= 256) {
+ *zs->u.r.zs_stackp++ = tab_suffixof(zs->u.r.zs_code);
+ zs->u.r.zs_code = tab_prefixof(zs->u.r.zs_code);
+ }
+ *zs->u.r.zs_stackp++ = zs->u.r.zs_finchar = tab_suffixof(zs->u.r.zs_code);
+
+ /* And put them out in forward order. */
+middle: do {
+ if (count-- == 0)
+ return (num);
+ *bp++ = *--zs->u.r.zs_stackp;
+ } while (zs->u.r.zs_stackp > de_stack);
+
+ /* Generate the new entry. */
+ if ((zs->u.r.zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode &&
+ zs->u.r.zs_oldcode != -1) {
+ tab_prefixof(zs->u.r.zs_code) = (u_short) zs->u.r.zs_oldcode;
+ tab_suffixof(zs->u.r.zs_code) = zs->u.r.zs_finchar;
+ zs->zs_free_ent = zs->u.r.zs_code + 1;
+ }
+
+ /* Remember previous code. */
+ zs->u.r.zs_oldcode = zs->u.r.zs_incode;
+ }
+ zs->zs_state = S_EOF;
+eof: return (num - count);
+}
+
+/*-
+ * Read one code from the standard input. If EOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+static code_int
+getcode(struct s_zstate *zs)
+{
+ code_int gcode;
+ int r_off, bits, i;
+ char_type *bp;
+
+ bp = zs->u.r.zs_gbuf;
+ if (zs->zs_clear_flg > 0 || zs->u.r.zs_roffset >= zs->u.r.zs_size ||
+ zs->zs_free_ent > zs->zs_maxcode) {
+ /*
+ * If the next entry will be too big for the current gcode
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if (zs->zs_free_ent > zs->zs_maxcode) {
+ zs->zs_n_bits++;
+ if (zs->zs_n_bits == zs->zs_maxbits) /* Won't get any bigger now. */
+ zs->zs_maxcode = zs->zs_maxmaxcode;
+ else
+ zs->zs_maxcode = MAXCODE(zs->zs_n_bits);
+ }
+ if (zs->zs_clear_flg > 0) {
+ zs->zs_maxcode = MAXCODE(zs->zs_n_bits = INIT_BITS);
+ zs->zs_clear_flg = 0;
+ }
+ /* XXX */
+ for (i = 0; i < zs->zs_n_bits && compressed_prelen; i++, compressed_prelen--)
+ zs->u.r.zs_gbuf[i] = *compressed_pre++;
+ zs->u.r.zs_size = fread(zs->u.r.zs_gbuf + i, 1, zs->zs_n_bits - i, zs->zs_fp);
+ zs->u.r.zs_size += i;
+ if (zs->u.r.zs_size <= 0) /* End of file. */
+ return (-1);
+ zs->u.r.zs_roffset = 0;
+
+ total_compressed_bytes += zs->u.r.zs_size;
+
+ /* Round size down to integral number of codes. */
+ zs->u.r.zs_size = (zs->u.r.zs_size << 3) - (zs->zs_n_bits - 1);
+ }
+ r_off = zs->u.r.zs_roffset;
+ bits = zs->zs_n_bits;
+
+ /* Get to the first byte. */
+ bp += (r_off >> 3);
+ r_off &= 7;
+
+ /* Get first part (low order bits). */
+ gcode = (*bp++ >> r_off);
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* Now, roffset into gcode word. */
+
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if (bits >= 8) {
+ gcode |= *bp++ << r_off;
+ r_off += 8;
+ bits -= 8;
+ }
+
+ /* High order bits. */
+ gcode |= (*bp & rmask[bits]) << r_off;
+ zs->u.r.zs_roffset += zs->zs_n_bits;
+
+ return (gcode);
+}
+
diff --git a/usr.bin/head/Makefile b/usr.bin/head/Makefile
new file mode 100644
index 000000000000..aaf41e24baa1
--- /dev/null
+++ b/usr.bin/head/Makefile
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+PROG= head
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.if ${MK_CASPER} != "no" && !defined(RESCUE)
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+=-DWITH_CASPER
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/head/Makefile.depend b/usr.bin/head/Makefile.depend
new file mode 100644
index 000000000000..7354b9b88616
--- /dev/null
+++ b/usr.bin/head/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/head/Makefile.depend.options b/usr.bin/head/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/head/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/head/head.1 b/usr.bin/head/head.1
new file mode 100644
index 000000000000..023ee5a7ce7d
--- /dev/null
+++ b/usr.bin/head/head.1
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd June 12, 2022
+.Dt HEAD 1
+.Os
+.Sh NAME
+.Nm head
+.Nd display first lines of a file
+.Sh SYNOPSIS
+.Nm
+.Op Fl qv
+.Op Fl n Ar count | Fl c Ar bytes
+.Op Ar
+.Sh DESCRIPTION
+This filter displays the first
+.Ar count
+lines or
+.Ar bytes
+of each of the specified files, or of the standard input if no
+files are specified.
+If
+.Ar count
+is omitted it defaults to 10.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c Ar bytes , Fl -bytes Ns = Ns Ar bytes
+Print
+.Ar bytes
+of each of the specified files.
+.It Fl n Ar count , Fl -lines Ns = Ns Ar count
+Print
+.Ar count
+lines of each of the specified files.
+.Pp
+Both
+.Ar count
+and
+.Ar bytes
+may also be specified with size suffixes supported by
+.Xr expand_number 3 .
+.It Fl q , Fl -quiet , Fl -silent
+Suppresses printing of headers when multiple files are being examined.
+.It Fl v , Fl -verbose
+Prepend each file with a header.
+.El
+.Pp
+If more than a single file is specified, or if the
+.Fl v
+option is used, each file is preceded by a
+header consisting of the string
+.Dq ==> XXX <==
+where
+.Dq XXX
+is the name of the file.
+The
+.Fl q
+flag disables the printing of the header in all cases.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To display the first 500 lines of the file
+.Ar foo :
+.Pp
+.Dl $ head -n 500 foo
+.Pp
+.Nm
+can be used in conjunction with
+.Xr tail 1
+in the following way to, for example, display only line 500 from the file
+.Ar foo :
+.Pp
+.Dl $ head -n 500 foo | tail -n 1
+.Sh SEE ALSO
+.Xr tail 1 ,
+.Xr expand_number 3
+.Sh HISTORY
+The
+.Nm
+command appeared in PWB UNIX.
diff --git a/usr.bin/head/head.c b/usr.bin/head/head.c
new file mode 100644
index 000000000000..62796ae144a1
--- /dev/null
+++ b/usr.bin/head/head.c
@@ -0,0 +1,215 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1987, 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/types.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+/*
+ * head - give the first few lines of a stream or of each of a set of files
+ *
+ * Bill Joy UCB August 24, 1977
+ */
+
+static void head(FILE *, intmax_t);
+static void head_bytes(FILE *, off_t);
+static void obsolete(char *[]);
+static void usage(void) __dead2;
+
+static const struct option long_opts[] =
+{
+ {"bytes", required_argument, NULL, 'c'},
+ {"lines", required_argument, NULL, 'n'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"silent", no_argument, NULL, 'q'},
+ {"verbose", no_argument, NULL, 'v'},
+ {NULL, no_argument, NULL, 0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp;
+ off_t bytecnt;
+ intmax_t linecnt;
+ int ch, first, eval;
+ fileargs_t *fa;
+ cap_rights_t rights;
+ int qflag = 0;
+ int vflag = 0;
+
+ linecnt = -1;
+ eval = 0;
+ bytecnt = -1;
+
+ obsolete(argv);
+ while ((ch = getopt_long(argc, argv, "+n:c:qv", long_opts, NULL)) != -1) {
+ switch(ch) {
+ case 'c':
+ if (expand_number(optarg, &bytecnt) || bytecnt <= 0)
+ errx(1, "illegal byte count -- %s", optarg);
+ break;
+ case 'n':
+ if (expand_number(optarg, &linecnt) || linecnt <= 0)
+ errx(1, "illegal line count -- %s", optarg);
+ break;
+ case 'q':
+ qflag = 1;
+ vflag = 0;
+ break;
+ case 'v':
+ qflag = 0;
+ vflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ fa = fileargs_init(argc, argv, O_RDONLY, 0,
+ cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN);
+ if (fa == NULL)
+ err(1, "unable to init casper");
+
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter_casper() < 0)
+ err(1, "unable to enter capability mode");
+
+ if (linecnt != -1 && bytecnt != -1)
+ errx(1, "can't combine line and byte counts");
+ if (linecnt == -1)
+ linecnt = 10;
+ if (*argv != NULL) {
+ for (first = 1; *argv != NULL; ++argv) {
+ if ((fp = fileargs_fopen(fa, *argv, "r")) == NULL) {
+ warn("%s", *argv);
+ eval = 1;
+ continue;
+ }
+ if (vflag || (qflag == 0 && argc > 1)) {
+ (void)printf("%s==> %s <==\n",
+ first ? "" : "\n", *argv);
+ first = 0;
+ }
+ if (bytecnt == -1)
+ head(fp, linecnt);
+ else
+ head_bytes(fp, bytecnt);
+ (void)fclose(fp);
+ }
+ } else if (bytecnt == -1)
+ head(stdin, linecnt);
+ else
+ head_bytes(stdin, bytecnt);
+
+ fileargs_free(fa);
+ exit(eval);
+}
+
+static void
+head(FILE *fp, intmax_t cnt)
+{
+ char *cp = NULL;
+ size_t error, bufsize = 0;
+ ssize_t readlen;
+
+ while (cnt != 0 && (readlen = getline(&cp, &bufsize, fp)) >= 0) {
+ error = fwrite(cp, sizeof(char), readlen, stdout);
+ if ((ssize_t)error != readlen)
+ err(1, "stdout");
+ cnt--;
+ }
+}
+
+static void
+head_bytes(FILE *fp, off_t cnt)
+{
+ char buf[4096];
+ size_t readlen;
+
+ while (cnt) {
+ if ((uintmax_t)cnt < sizeof(buf))
+ readlen = cnt;
+ else
+ readlen = sizeof(buf);
+ readlen = fread(buf, sizeof(char), readlen, fp);
+ if (readlen == 0)
+ break;
+ if (fwrite(buf, sizeof(char), readlen, stdout) != readlen)
+ err(1, "stdout");
+ cnt -= readlen;
+ }
+}
+
+static void
+obsolete(char *argv[])
+{
+ char *ap;
+
+ while ((ap = *++argv)) {
+ /* Return if "--" or not "-[0-9]*". */
+ if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1]))
+ return;
+ if ((ap = malloc(strlen(*argv) + 2)) == NULL)
+ err(1, NULL);
+ ap[0] = '-';
+ ap[1] = 'n';
+ (void)strcpy(ap + 2, *argv + 1);
+ *argv = ap;
+ }
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: head [-n lines | -c bytes] [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/head/tests/Makefile b/usr.bin/head/tests/Makefile
new file mode 100644
index 000000000000..0ca086db4151
--- /dev/null
+++ b/usr.bin/head/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= head_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/head/tests/Makefile.depend b/usr.bin/head/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/head/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/head/tests/head_test.sh b/usr.bin/head/tests/head_test.sh
new file mode 100755
index 000000000000..2dfc1896f6ef
--- /dev/null
+++ b/usr.bin/head/tests/head_test.sh
@@ -0,0 +1,176 @@
+# Copyright (c) 2017 Fred Schlechter
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case empty_file
+empty_file_head() {
+ atf_set "descr" "Test head(1)'s handling of an empty file"
+}
+empty_file_body() {
+ touch infile expectfile
+ head infile > outfile
+ head < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case default_no_options
+default_no_options_head() {
+ atf_set "descr" "Test head(1)'s default mode"
+}
+default_no_options_body() {
+ #head(1) is supposed to default to 10 lines of output. Verify that it does that.
+ jot -b test 10 > expectfile
+ jot -b test 100 > infile
+ head infile > outfile
+ atf_check -e empty cmp expectfile outfile
+}
+
+atf_test_case line_count
+line_count_head() {
+ atf_set "descr" "Test head(1)'s -n option"
+}
+line_count_body() {
+ jot -b test 100 > outfile
+ head -n 50 outfile > expectfile
+ atf_check -o inline:" 50 expectfile\n" wc -l expectfile
+}
+
+atf_test_case byte_count
+byte_count_head() {
+ atf_set "descr" "Test head(1)'s -c option"
+}
+byte_count_body() {
+ jot -b test 100 > outfile
+ head -c 50 outfile > expectfile
+ atf_check -o inline:" 50 expectfile\n" wc -c expectfile
+}
+
+atf_test_case sparse_file_text_at_beginning
+sparse_file_text_at_beginning_head() {
+ atf_set "descr" "Test head(1)'s handling of a sparse file with text at the beginning of the file"
+}
+sparse_file_text_at_beginning_body () {
+ jot -b test 10 > outfile
+ truncate -s +1K outfile
+ head -c 512 outfile > expectfile
+ atf_check -o inline:" 512 expectfile\n" wc -c expectfile
+}
+
+atf_test_case sparse_file_text_at_end
+sparse_file_text_at_end_head() {
+ atf_set "descr" "Test head(1)'s handling of a sparse file with text at the end of the file"
+}
+sparse_file_text_at_end_body () {
+ truncate -s +1K infile
+ echo test >> infile
+ head -c 4096 < infile > outpipe
+ atf_check cmp infile outpipe
+}
+
+atf_test_case missing_line_count
+missing_line_count_head() {
+ atf_set "descr" "Test head(1)'s handling of a missing line count arg"
+}
+missing_line_count_body () {
+ jot -b test 100 > outfile
+ atf_check -s not-exit:0 -e not-empty head -n outfile
+}
+
+atf_test_case invalid_line_count
+invalid_line_count_head() {
+ atf_set "descr" "Test head(1)'s handling of an invalid line count arg"
+}
+invalid_line_count_body () {
+ jot -b test 100 > outfile
+ atf_check -s not-exit:0 -e not-empty head -n -10 outfile
+}
+
+atf_test_case read_from_stdin
+read_from_stdin_head() {
+ atf_set "descr" "Test head(1)'s reading of stdin"
+}
+read_from_stdin_body() {
+ #head(1) defaults to head -n 10 if no args are given.
+ jot -b test 10 > outfile
+ jot -b test 20 | head > expectfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case silent_header
+silent_header_head() {
+ atf_set "descr" "Test head(1)'s silent header feature"
+}
+silent_header_body() {
+ #head(1) defaults to head -n 10 if no args are given.
+ jot 11 1 11 > file1
+ jot 11 2 12 > file2
+ jot 10 1 10 > expectfile
+ jot 10 2 11 >> expectfile
+ head -q file1 file2 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case verbose_header
+verbose_header_head() {
+ atf_set "descr" "Test head(1)'s verbose header feature"
+}
+verbose_header_body() {
+ #head(1) defaults to head -n 10 if no args are given.
+ jot -b test 10 > file1
+ echo '==> file1 <==' > expectfile
+ cat file1 >> expectfile
+ head -v file1 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case si_number
+si_number_head() {
+ atf_set "descr" "Test head(1)'s SI number feature"
+}
+si_number_body() {
+ jot -b aaaaaaa 129 > file1
+ jot -b aaaaaaa 128 > expectfile
+ head -c 1k file1 > outfile
+ atf_check cmp outfile expectfile
+ jot 1025 1 1025 > file1
+ jot 1024 1 1024 > expectfile
+ head -n 1k file1 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_init_test_cases() {
+ atf_add_test_case empty_file
+ atf_add_test_case default_no_options
+ atf_add_test_case line_count
+ atf_add_test_case byte_count
+ atf_add_test_case sparse_file_text_at_beginning
+ atf_add_test_case sparse_file_text_at_end
+ atf_add_test_case missing_line_count
+ atf_add_test_case invalid_line_count
+ atf_add_test_case read_from_stdin
+ atf_add_test_case silent_header
+ atf_add_test_case verbose_header
+ atf_add_test_case si_number
+}
diff --git a/usr.bin/hesinfo/Makefile b/usr.bin/hesinfo/Makefile
new file mode 100644
index 000000000000..bb95e6200d1c
--- /dev/null
+++ b/usr.bin/hesinfo/Makefile
@@ -0,0 +1,3 @@
+PROG= hesinfo
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/hesinfo/hesinfo.1 b/usr.bin/hesinfo/hesinfo.1
new file mode 100644
index 000000000000..b1767eccb942
--- /dev/null
+++ b/usr.bin/hesinfo/hesinfo.1
@@ -0,0 +1,195 @@
+.\" $NetBSD: hesinfo.1,v 1.1 1999/01/25 22:45:55 lukem Exp $
+.\"
+.\" from: #Id: hesinfo.1,v 1.9 1996/11/07 01:57:12 ghudson Exp #
+.\"
+.\" Copyright 1987, 1996 by the Massachusetts Institute of Technology.
+.\"
+.\" Permission to use, copy, modify, and distribute this
+.\" software and its documentation for any purpose and without
+.\" fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright
+.\" notice and this permission notice appear in supporting
+.\" documentation, and that the name of M.I.T. not be used in
+.\" advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose. It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.Dd June 27, 2022
+.Dt HESINFO 1
+.Os
+.Sh NAME
+.Nm hesinfo
+.Nd "find out what is stored in the Hesiod database"
+.Sh SYNOPSIS
+.Nm
+.Op Fl bl
+.Ar HesiodName HesiodNameType
+.Sh DESCRIPTION
+The
+.Nm
+utility takes two arguments, a name to be resolved and a string, known
+as a
+.Ar HesiodNameType .
+It then prints the information returned by
+the Hesiod nameserver.
+.Pp
+The value returned by
+.Nm
+is of the type
+.Ar HesiodNameType .
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl l
+Selects long format.
+.It Fl b
+Prints the fully\-qualified string passed to the nameserver.
+.El
+.Ss VALID Hesiod_Names
+The following types of identifiers may be used in the
+.Ar HesiodName
+argument to
+.Nm .
+These values will be resolved by accessing the
+.Xr hesiod 3
+database.
+.Bl -tag -width indent
+.It Aq Ar username
+the 8\-character\-or\-less string used to identify users or classes
+(e.g.\& joeuser, root, 1.00, etc).
+Used with the
+.Ar Hesiod_Name_Types
+.Cm passwd ,
+.Cm pobox ,
+and
+.Cm filsys .
+.It Aq Ar uid
+the id number assigned to a user.
+.It Aq Ar groupid
+the id number assigned to a group.
+.It Aq Ar groupname
+a name identifying a unique group.
+.It Aq Ar file\-system\-name
+the name of an Athena file system.
+.It Xo
+.Ao Ar "rvd\-server" Ac : Ns Aq Ar pack
+.Xc
+the name of an rvd's server and pack separated by a colon.
+.It Xo
+.Ao Ar "nfs\-server" Ac : Ns Aq Ar partition
+.Xc
+the name of an
+.Tn NFS
+server and its partition separated by a colon.
+.It Aq Ar workstation\-name
+the machine name of an Athena workstation (e.g.\& E40\-343\-3).
+.It Aq Ar service\-name
+name of an Athena service (e.g.\& Zephyr).
+.It Aq Ar service\-type
+name of
+.Ux
+service (valid entries are defined in
+.Pa /etc/services ) .
+.It Aq Ar printer\-name
+name of a printer.
+.It Aq Ar printer\-cluster\-name
+name of an Athena print cluster.
+.It Aq Ar foo
+some
+.Nm
+calls (e.g.\&
+.Cm prclusterlist )
+do not require a specific
+.Ar HesiodName
+argument.
+However, you must include a dummy string (e.g.\&
+.Ql foo )
+for
+.Nm
+to work properly.
+.El
+.Ss VALID Hesiod_Name_Types
+The following symbols are valid substitutions for the
+.Ar HesiodNameType
+argument to
+.Nm .
+.Bl -tag -width indent
+.It Cm passwd
+returns string suitable for inclusion in
+.Pa /etc/passwd ,
+searching with
+.Aq Ar username .
+.It Cm pobox
+returns information on the pobox assigned to the user specified by
+.Ar HesiodName ,
+searching with
+.Aq Ar username .
+.It Cm uid
+returns string suitable for inclusion in
+.Pa /etc/passwd ,
+searching with
+.Aq Ar uid .
+.It Cm gid
+returns string suitable for inclusion in
+.Pa /etc/group ,
+searching with
+.Aq Ar groupid .
+.It Cm group
+returns string suitable for inclusion in
+.Pa /etc/group ,
+searching with
+.Aq Ar groupname .
+.It Cm grplist
+returns subgroups included in superset
+defined by
+.Aq Ar groupname .
+.It Cm filsys
+returns file system type, export point, server, mount mode, and import point
+for the following valid
+.Ar HesiodNames
+(see above) -
+.Aq Ar "file\-system\-name" ,
+.Aq Ar username ,
+.Ao Ar "rvd\-server" Ac : Ns Aq Ar pack ,
+and
+.Ao Ar "nfs\-server" Ac : Ns Aq Ar partition .
+.It Cm cluster
+returns information about the local cluster the workstation, specified by
+.Aq Ar "workstation\-name" .
+Included is information about the local file and print servers.
+This information is accesses by
+.Sy clusterinfo
+at boot time.
+.It Cm sloc
+returns network name of service host for
+.Aq Ar service\-name .
+.It Cm service
+returns Internet protocol type and protocol service port for
+.Aq Ar service\-type .
+.It Cm pcap
+returns a valid entry for
+.Pa /etc/printcap
+for
+.Aq Ar printer\-name .
+.It Cm prcluserlist
+returns a list of print clusters.
+.It Cm prcluster
+returns a list of printers in a cluster specified by
+.Aq Ar printer\-cluster\-name .
+.El
+.Sh FILES
+.Bl -tag -width /etc/hesiod.conf
+.It Pa /etc/hesiod.conf
+.El
+.Sh SEE ALSO
+.Xr hesiod 3
+.Rs
+.%T "Hesiod - Project Athena Technical Plan -- Name Service"
+.Re
+.Sh AUTHORS
+.An Steve Dyer ,
+IBM/Project Athena
+.Pp
+Copyright 1987, 1988, 1996 by the Massachusetts Institute of Technology.
diff --git a/usr.bin/hesinfo/hesinfo.c b/usr.bin/hesinfo/hesinfo.c
new file mode 100644
index 000000000000..ed91f14f5644
--- /dev/null
+++ b/usr.bin/hesinfo/hesinfo.c
@@ -0,0 +1,106 @@
+/* $NetBSD: hesinfo.c,v 1.1 1999/01/25 22:45:55 lukem Exp $ */
+
+/* Copyright 1988, 1996 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+/* This file is a simple driver for the Hesiod library. */
+
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <errno.h>
+#include <hesiod.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ char **list, **p, *bindname, *name, *type;
+ int lflag = 0, errflg = 0, bflag = 0, c;
+ void *context;
+
+ while ((c = getopt(argc, argv, "lb")) != -1) {
+ switch (c) {
+ case 'l':
+ lflag = 1;
+ break;
+ case 'b':
+ bflag = 1;
+ break;
+ default:
+ errflg++;
+ break;
+ }
+ }
+ if (argc - optind != 2 || errflg) {
+ fprintf(stderr, "usage: hesinfo [-bl] name type\n");
+ fprintf(stderr, "\t-l selects long format\n");
+ fprintf(stderr, "\t-b also does hes_to_bind conversion\n");
+ exit(2);
+ }
+ name = argv[optind];
+ type = argv[optind + 1];
+
+ if (hesiod_init(&context) < 0) {
+ if (errno == ENOEXEC)
+ warnx(
+ "hesiod_init: Invalid Hesiod configuration file.");
+ else
+ warn("hesiod_init");
+ }
+ /* Display bind name if requested. */
+ if (bflag) {
+ if (lflag)
+ printf("hes_to_bind(%s, %s) expands to\n", name, type);
+ bindname = hesiod_to_bind(context, name, type);
+ if (!bindname) {
+ if (lflag)
+ printf("nothing\n");
+ if (errno == ENOENT)
+ warnx("hesiod_to_bind: Unknown rhs-extension.");
+ else
+ warn("hesiod_to_bind");
+ exit(1);
+ }
+ printf("%s\n", bindname);
+ free(bindname);
+ if (lflag)
+ printf("which ");
+ }
+ if (lflag)
+ printf("resolves to\n");
+
+ /* Do the hesiod resolve and check for errors. */
+ list = hesiod_resolve(context, name, type);
+ if (!list) {
+ if (lflag)
+ printf("nothing\n");
+ if (errno == ENOENT)
+ warnx("hesiod_resolve: Hesiod name not found.");
+ else
+ warn("hesiod_resolve");
+ exit(1);
+ }
+ /* Display the results. */
+ for (p = list; *p; p++)
+ printf("%s\n", *p);
+
+ hesiod_free_list(context, list);
+ hesiod_end(context);
+ exit(0);
+}
diff --git a/usr.bin/hexdump/Makefile b/usr.bin/hexdump/Makefile
new file mode 100644
index 000000000000..d7a10ceb7aa7
--- /dev/null
+++ b/usr.bin/hexdump/Makefile
@@ -0,0 +1,13 @@
+.include <src.opts.mk>
+
+PROG= hexdump
+SRCS= conv.c display.c hexdump.c hexsyntax.c odsyntax.c parse.c
+MAN= hexdump.1 od.1
+MLINKS= hexdump.1 hd.1
+LINKS= ${BINDIR}/hexdump ${BINDIR}/od
+LINKS+= ${BINDIR}/hexdump ${BINDIR}/hd
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/hexdump/Makefile.depend b/usr.bin/hexdump/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/hexdump/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/hexdump/conv.c b/usr.bin/hexdump/conv.c
new file mode 100644
index 000000000000..ddfb0f8c64c4
--- /dev/null
+++ b/usr.bin/hexdump/conv.c
@@ -0,0 +1,187 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "hexdump.h"
+
+void
+conv_c(PR *pr, u_char *p, size_t bufsize)
+{
+ char buf[10];
+ char const *str;
+ wchar_t wc;
+ size_t clen, oclen;
+ int converr, pad, width;
+ u_char peekbuf[MB_LEN_MAX];
+ u_char *op;
+
+ op = NULL;
+
+ if (pr->mbleft > 0) {
+ str = "**";
+ pr->mbleft--;
+ goto strpr;
+ }
+
+ switch(*p) {
+ case '\0':
+ str = "\\0";
+ goto strpr;
+ /* case '\a': */
+ case '\007':
+ str = "\\a";
+ goto strpr;
+ case '\b':
+ str = "\\b";
+ goto strpr;
+ case '\f':
+ str = "\\f";
+ goto strpr;
+ case '\n':
+ str = "\\n";
+ goto strpr;
+ case '\r':
+ str = "\\r";
+ goto strpr;
+ case '\t':
+ str = "\\t";
+ goto strpr;
+ case '\v':
+ str = "\\v";
+ goto strpr;
+ default:
+ break;
+ }
+ /*
+ * Multibyte characters are disabled for hexdump(1) for backwards
+ * compatibility and consistency (none of its other output formats
+ * recognize them correctly).
+ */
+ converr = 0;
+ if (odmode && MB_CUR_MAX > 1) {
+ oclen = 0;
+retry:
+ clen = mbrtowc(&wc, p, bufsize, &pr->mbstate);
+ if (clen == 0)
+ clen = 1;
+ else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
+ p == peekbuf)) {
+ memset(&pr->mbstate, 0, sizeof(pr->mbstate));
+ if (p == peekbuf) {
+ /*
+ * We peeked ahead, but that didn't help --
+ * we either got an illegal sequence or still
+ * can't complete; restore original character.
+ */
+ oclen = 0;
+ p = op;
+ }
+ wc = *p;
+ clen = 1;
+ converr = 1;
+ } else if (clen == (size_t)-2) {
+ /*
+ * Incomplete character; peek ahead and see if we
+ * can complete it.
+ */
+ oclen = bufsize;
+ op = p;
+ bufsize = peek(p = peekbuf, MB_CUR_MAX);
+ goto retry;
+ }
+ clen += oclen;
+ } else {
+ wc = *p;
+ clen = 1;
+ }
+ if (!converr && iswprint(wc)) {
+ if (!odmode) {
+ *pr->cchar = 'c';
+ (void)printf(pr->fmt, (int)wc);
+ } else {
+ *pr->cchar = 'C';
+ assert(strcmp(pr->fmt, "%3C") == 0);
+ width = wcwidth(wc);
+ assert(width >= 0);
+ pad = 3 - width;
+ if (pad < 0)
+ pad = 0;
+ (void)printf("%*s%C", pad, "", wc);
+ pr->mbleft = clen - 1;
+ }
+ } else {
+ (void)sprintf(buf, "%03o", (int)*p);
+ str = buf;
+strpr: *pr->cchar = 's';
+ (void)printf(pr->fmt, str);
+ }
+}
+
+void
+conv_u(PR *pr, u_char *p)
+{
+ static char const * list[] = {
+ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
+ "bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
+ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
+ "can", "em", "sub", "esc", "fs", "gs", "rs", "us",
+ };
+
+ /* od used nl, not lf */
+ if (*p <= 0x1f) {
+ *pr->cchar = 's';
+ if (odmode && *p == 0x0a)
+ (void)printf(pr->fmt, "nl");
+ else
+ (void)printf(pr->fmt, list[*p]);
+ } else if (*p == 0x7f) {
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, "del");
+ } else if (odmode && *p == 0x20) { /* od replaced space with sp */
+ *pr->cchar = 's';
+ (void)printf(pr->fmt, " sp");
+ } else if (isprint(*p)) {
+ *pr->cchar = 'c';
+ (void)printf(pr->fmt, *p);
+ } else {
+ *pr->cchar = 'x';
+ (void)printf(pr->fmt, (int)*p);
+ }
+}
diff --git a/usr.bin/hexdump/display.c b/usr.bin/hexdump/display.c
new file mode 100644
index 000000000000..77de580983ca
--- /dev/null
+++ b/usr.bin/hexdump/display.c
@@ -0,0 +1,434 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "hexdump.h"
+
+enum _vflag vflag = FIRST;
+
+static off_t address; /* address/offset in stream */
+static off_t eaddress; /* end address */
+
+static void print(PR *, u_char *);
+static void noseek(void);
+
+void
+display(void)
+{
+ FS *fs;
+ FU *fu;
+ PR *pr;
+ int cnt;
+ u_char *bp;
+ off_t saveaddress;
+ u_char savech, *savebp;
+
+ savech = 0;
+ while ((bp = get()))
+ for (fs = fshead, savebp = bp, saveaddress = address; fs;
+ fs = fs->nextfs, bp = savebp, address = saveaddress)
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (fu->flags&F_IGNORE)
+ break;
+ for (cnt = fu->reps; cnt; --cnt)
+ for (pr = fu->nextpr; pr; address += pr->bcnt,
+ bp += pr->bcnt, pr = pr->nextpr) {
+ if (eaddress && address >= eaddress &&
+ !(pr->flags & (F_TEXT|F_BPAD)))
+ bpad(pr);
+ if (cnt == 1 && pr->nospace) {
+ savech = *pr->nospace;
+ *pr->nospace = '\0';
+ }
+ print(pr, bp);
+ if (cnt == 1 && pr->nospace)
+ *pr->nospace = savech;
+ }
+ }
+ if (endfu) {
+ /*
+ * If eaddress not set, error or file size was multiple of
+ * blocksize, and no partial block ever found.
+ */
+ if (!eaddress) {
+ if (!address)
+ return;
+ eaddress = address;
+ }
+ for (pr = endfu->nextpr; pr; pr = pr->nextpr)
+ switch(pr->flags) {
+ case F_ADDRESS:
+ (void)printf(pr->fmt, (quad_t)eaddress);
+ break;
+ case F_TEXT:
+ (void)printf("%s", pr->fmt);
+ break;
+ }
+ }
+}
+
+static void
+print(PR *pr, u_char *bp)
+{
+ long double ldbl;
+ double f8;
+ float f4;
+ int16_t s2;
+ int32_t s4;
+ int64_t s8;
+ u_int16_t u2;
+ u_int32_t u4;
+ u_int64_t u8;
+
+ switch(pr->flags) {
+ case F_ADDRESS:
+ (void)printf(pr->fmt, (quad_t)address);
+ break;
+ case F_BPAD:
+ (void)printf(pr->fmt, "");
+ break;
+ case F_C:
+ conv_c(pr, bp, eaddress ? eaddress - address :
+ blocksize - address % blocksize);
+ break;
+ case F_CHAR:
+ (void)printf(pr->fmt, *bp);
+ break;
+ case F_DBL:
+ switch(pr->bcnt) {
+ case 4:
+ bcopy(bp, &f4, sizeof(f4));
+ (void)printf(pr->fmt, f4);
+ break;
+ case 8:
+ bcopy(bp, &f8, sizeof(f8));
+ (void)printf(pr->fmt, f8);
+ break;
+ default:
+ if (pr->bcnt == sizeof(long double)) {
+ bcopy(bp, &ldbl, sizeof(ldbl));
+ (void)printf(pr->fmt, ldbl);
+ }
+ break;
+ }
+ break;
+ case F_INT:
+ switch(pr->bcnt) {
+ case 1:
+ (void)printf(pr->fmt, (quad_t)(signed char)*bp);
+ break;
+ case 2:
+ bcopy(bp, &s2, sizeof(s2));
+ (void)printf(pr->fmt, (quad_t)s2);
+ break;
+ case 4:
+ bcopy(bp, &s4, sizeof(s4));
+ (void)printf(pr->fmt, (quad_t)s4);
+ break;
+ case 8:
+ bcopy(bp, &s8, sizeof(s8));
+ (void)printf(pr->fmt, s8);
+ break;
+ }
+ break;
+ case F_P:
+ (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
+ break;
+ case F_STR:
+ (void)printf(pr->fmt, (char *)bp);
+ break;
+ case F_TEXT:
+ (void)printf("%s", pr->fmt);
+ break;
+ case F_U:
+ conv_u(pr, bp);
+ break;
+ case F_UINT:
+ switch(pr->bcnt) {
+ case 1:
+ (void)printf(pr->fmt, (u_quad_t)*bp);
+ break;
+ case 2:
+ bcopy(bp, &u2, sizeof(u2));
+ (void)printf(pr->fmt, (u_quad_t)u2);
+ break;
+ case 4:
+ bcopy(bp, &u4, sizeof(u4));
+ (void)printf(pr->fmt, (u_quad_t)u4);
+ break;
+ case 8:
+ bcopy(bp, &u8, sizeof(u8));
+ (void)printf(pr->fmt, u8);
+ break;
+ }
+ break;
+ }
+}
+
+void
+bpad(PR *pr)
+{
+ static char const *spec = " -0+#";
+ char *p1, *p2;
+
+ /*
+ * Remove all conversion flags; '-' is the only one valid
+ * with %s, and it's not useful here.
+ */
+ pr->flags = F_BPAD;
+ pr->cchar[0] = 's';
+ pr->cchar[1] = '\0';
+ for (p1 = pr->fmt; *p1 != '%'; ++p1);
+ for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
+ while ((*p2++ = *p1++));
+}
+
+static char **_argv;
+
+u_char *
+get(void)
+{
+ static int ateof = 1;
+ static u_char *curp, *savp;
+ int n;
+ int need, nread;
+ int valid_save = 0;
+ u_char *tmpp;
+
+ if (!curp) {
+ if ((curp = calloc(1, blocksize)) == NULL)
+ err(1, NULL);
+ if ((savp = calloc(1, blocksize)) == NULL)
+ err(1, NULL);
+ } else {
+ tmpp = curp;
+ curp = savp;
+ savp = tmpp;
+ address += blocksize;
+ valid_save = 1;
+ }
+ for (need = blocksize, nread = 0;;) {
+ /*
+ * if read the right number of bytes, or at EOF for one file,
+ * and no other files are available, zero-pad the rest of the
+ * block and set the end flag.
+ */
+ if (!length || (ateof && !next((char **)NULL))) {
+ if (odmode && skip > 0)
+ errx(1, "cannot skip past end of input");
+ if (need == blocksize)
+ return((u_char *)NULL);
+ /*
+ * XXX bcmp() is not quite right in the presence
+ * of multibyte characters.
+ */
+ if (need == 0 && vflag != ALL &&
+ valid_save &&
+ bcmp(curp, savp, nread) == 0) {
+ if (vflag != DUP) {
+ (void)printf("*\n");
+ (void)fflush(stdout);
+ }
+ return((u_char *)NULL);
+ }
+ bzero((char *)curp + nread, need);
+ eaddress = address + nread;
+ return(curp);
+ }
+ n = fread((char *)curp + nread, sizeof(u_char),
+ length == -1 ? need : MIN(length, need), stdin);
+ if (!n) {
+ if (ferror(stdin))
+ warn("%s", _argv[-1]);
+ ateof = 1;
+ continue;
+ }
+ ateof = 0;
+ if (length != -1)
+ length -= n;
+ if (!(need -= n)) {
+ /*
+ * XXX bcmp() is not quite right in the presence
+ * of multibyte characters.
+ */
+ if (vflag == ALL || vflag == FIRST ||
+ valid_save == 0 ||
+ bcmp(curp, savp, blocksize) != 0) {
+ if (vflag == DUP || vflag == FIRST)
+ vflag = WAIT;
+ return(curp);
+ }
+ if (vflag == WAIT) {
+ (void)printf("*\n");
+ (void)fflush(stdout);
+ }
+ vflag = DUP;
+ address += blocksize;
+ need = blocksize;
+ nread = 0;
+ }
+ else
+ nread += n;
+ }
+}
+
+size_t
+peek(u_char *buf, size_t nbytes)
+{
+ size_t n, nread;
+ int c;
+
+ if (length != -1 && nbytes > (unsigned int)length)
+ nbytes = length;
+ nread = 0;
+ while (nread < nbytes && (c = getchar()) != EOF) {
+ *buf++ = c;
+ nread++;
+ }
+ n = nread;
+ while (n-- > 0) {
+ c = *--buf;
+ ungetc(c, stdin);
+ }
+ return (nread);
+}
+
+int
+next(char **argv)
+{
+ static int done;
+ int statok;
+
+ if (argv) {
+ _argv = argv;
+ return(1);
+ }
+ for (;;) {
+ if (*_argv) {
+ done = 1;
+ if (!(freopen(*_argv, "r", stdin))) {
+ warn("%s", *_argv);
+ exitval = 1;
+ ++_argv;
+ continue;
+ }
+ statok = 1;
+ } else {
+ if (done++)
+ return(0);
+ statok = 0;
+ }
+
+ if (caph_limit_stream(fileno(stdin), CAPH_READ) < 0)
+ err(1, "unable to restrict %s",
+ statok ? *_argv : "stdin");
+
+ /*
+ * We've opened our last input file; enter capsicum sandbox.
+ */
+ if (statok == 0 || *(_argv + 1) == NULL) {
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+ }
+
+ if (skip)
+ doskip(statok ? *_argv : "stdin", statok);
+ if (*_argv)
+ ++_argv;
+ if (!skip)
+ return(1);
+ }
+ /* NOTREACHED */
+}
+
+void
+doskip(const char *fname, int statok)
+{
+ int type;
+ struct stat sb;
+
+ if (statok) {
+ if (fstat(fileno(stdin), &sb))
+ err(1, "%s", fname);
+ if (S_ISREG(sb.st_mode) && skip > sb.st_size && sb.st_size > 0) {
+ address += sb.st_size;
+ skip -= sb.st_size;
+ return;
+ }
+ }
+ if (!statok || S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode) || \
+ (S_ISREG(sb.st_mode) && sb.st_size == 0)) {
+ noseek();
+ return;
+ }
+ if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ if (ioctl(fileno(stdin), FIODTYPE, &type))
+ err(1, "%s", fname);
+ /*
+ * Most tape drives don't support seeking,
+ * yet fseek() would succeed.
+ */
+ if (type & D_TAPE) {
+ noseek();
+ return;
+ }
+ }
+ if (fseeko(stdin, skip, SEEK_SET)) {
+ noseek();
+ return;
+ }
+ address += skip;
+ skip = 0;
+}
+
+static void
+noseek(void)
+{
+ int count;
+ for (count = 0; count < skip; ++count)
+ if (getchar() == EOF)
+ break;
+ address += count;
+ skip -= count;
+}
diff --git a/usr.bin/hexdump/hexdump.1 b/usr.bin/hexdump/hexdump.1
new file mode 100644
index 000000000000..9300e2e0c5c9
--- /dev/null
+++ b/usr.bin/hexdump/hexdump.1
@@ -0,0 +1,384 @@
+.\" Copyright (c) 1989, 1990, 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.
+.\"
+.Dd June 29, 2020
+.Dt HEXDUMP 1
+.Os
+.Sh NAME
+.Nm hexdump , hd
+.Nd ASCII, decimal, hexadecimal, octal dump
+.Sh SYNOPSIS
+.Nm
+.Op Fl bcCdovx
+.Op Fl e Ar format_string
+.Op Fl f Ar format_file
+.Op Fl n Ar length
+.Bk -words
+.Op Fl s Ar offset
+.Ek
+.Ar
+.Nm hd
+.Op Fl bcdovx
+.Op Fl e Ar format_string
+.Op Fl f Ar format_file
+.Op Fl n Ar length
+.Bk -words
+.Op Fl s Ar offset
+.Ek
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a filter which displays the specified files, or
+the standard input, if no files are specified, in a user specified
+format.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b
+.Em One-byte octal display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, three column, zero-filled, bytes of input data,
+in octal, per line.
+.It Fl c
+.Em One-byte character display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, three column, space-filled, characters of input
+data per line.
+.It Fl C
+.Em Canonical hex+ASCII display .
+Display the input offset in hexadecimal, followed by sixteen
+space-separated, two column, hexadecimal bytes, followed by the
+same sixteen bytes in %_p format enclosed in ``|'' characters.
+.Pp
+Calling the command
+.Nm hd
+implies this option.
+.It Fl d
+.Em Two-byte decimal display .
+Display the input offset in hexadecimal, followed by eight
+space-separated, five column, zero-filled, two-byte units
+of input data, in unsigned decimal, per line.
+.It Fl e Ar format_string
+Specify a format string to be used for displaying data.
+.It Fl f Ar format_file
+Specify a file that contains one or more newline separated format strings.
+Empty lines and lines whose first non-blank character is a hash mark
+.Pf ( Cm \&# )
+are ignored.
+.It Fl n Ar length
+Interpret only
+.Ar length
+bytes of input.
+.It Fl o
+.Em Two-byte octal display .
+Display the input offset in hexadecimal, followed by eight
+space-separated, six column, zero-filled, two byte quantities of
+input data, in octal, per line.
+.It Fl s Ar offset
+Skip
+.Ar offset
+bytes from the beginning of the input.
+By default,
+.Ar offset
+is interpreted as a decimal number.
+With a leading
+.Cm 0x
+or
+.Cm 0X ,
+.Ar offset
+is interpreted as a hexadecimal number,
+otherwise, with a leading
+.Cm 0 ,
+.Ar offset
+is interpreted as an octal number.
+Appending the character
+.Cm b ,
+.Cm k ,
+or
+.Cm m
+to
+.Ar offset
+causes it to be interpreted as a multiple of
+.Li 512 ,
+.Li 1024 ,
+or
+.Li 1048576 ,
+respectively.
+.It Fl v
+Cause
+.Nm
+to display all input data.
+Without the
+.Fl v
+option, any number of groups of output lines, which would be
+identical to the immediately preceding group of output lines (except
+for the input offsets), are replaced with a line comprised of a
+single asterisk.
+.It Fl x
+.Em Two-byte hexadecimal display .
+Display the input offset in hexadecimal, followed by eight, space
+separated, four column, zero-filled, two-byte quantities of input
+data, in hexadecimal, per line.
+.El
+.Pp
+For each input file,
+.Nm
+sequentially copies the input to standard output, transforming the
+data according to the format strings specified by the
+.Fl e
+and
+.Fl f
+options, in the order that they were specified.
+.Ss Formats
+A format string contains any number of format units, separated by
+whitespace.
+A format unit contains up to three items: an iteration count, a byte
+count, and a format.
+.Pp
+The iteration count is an optional positive integer, which defaults to
+one.
+Each format is applied iteration count times.
+.Pp
+The byte count is an optional positive integer.
+If specified it defines the number of bytes to be interpreted by
+each iteration of the format.
+.Pp
+If an iteration count and/or a byte count is specified, a single slash
+must be placed after the iteration count and/or before the byte count
+to disambiguate them.
+Any whitespace before or after the slash is ignored.
+.Pp
+The format is required and must be surrounded by double quote
+(" ") marks.
+It is interpreted as a fprintf-style format string (see
+.Xr fprintf 3 ) ,
+with the
+following exceptions:
+.Bl -bullet -offset indent
+.It
+An asterisk (*) may not be used as a field width or precision.
+.It
+A byte count or field precision
+.Em is
+required for each ``s'' conversion
+character (unlike the
+.Xr fprintf 3
+default which prints the entire string if the precision is unspecified).
+.It
+The conversion characters ``h'', ``l'', ``n'', ``p'' and ``q'' are
+not supported.
+.It
+The single character escape sequences
+described in the C standard are supported:
+.Bd -ragged -offset indent -compact
+.Bl -column <alert_character>
+.It "NUL \e0"
+.It "<alert character> \ea"
+.It "<backspace> \eb"
+.It "<form-feed> \ef"
+.It "<newline> \en"
+.It "<carriage return> \er"
+.It "<tab> \et"
+.It "<vertical tab> \ev"
+.El
+.Ed
+.El
+.Pp
+The
+.Nm
+utility also supports the following additional conversion strings:
+.Bl -tag -width Fl
+.It Cm \&_a Ns Op Cm dox
+Display the input offset, cumulative across input files, of the
+next byte to be displayed.
+The appended characters
+.Cm d ,
+.Cm o ,
+and
+.Cm x
+specify the display base
+as decimal, octal or hexadecimal respectively.
+.It Cm \&_A Ns Op Cm dox
+Identical to the
+.Cm \&_a
+conversion string except that it is only performed
+once, when all of the input data has been processed.
+.It Cm \&_c
+Output characters in the default character set.
+Nonprinting characters are displayed in three character, zero-padded
+octal, except for those representable by standard escape notation
+(see above),
+which are displayed as two character strings.
+.It Cm _p
+Output characters in the default character set.
+Nonprinting characters are displayed as a single
+.Dq Cm \&. .
+.It Cm _u
+Output US ASCII
+characters, with the exception that control characters are
+displayed using the following, lower-case, names.
+Characters greater than 0xff, hexadecimal, are displayed as hexadecimal
+strings.
+.Bl -column 000_nu 001_so 002_st 003_et 004_eo
+.It "000 NUL" Ta "001 SOH" Ta "002 STX" Ta "003 ETX" Ta "004 EOT" Ta "005 ENQ"
+.It "006 ACK" Ta "007 BEL" Ta "008 BS" Ta "009 HT" Ta "00A LF" Ta "00B VT"
+.It "00C FF" Ta "00D CR" Ta "00E\ SO" Ta "00F SI" Ta "010 DLE" Ta "011 DC1"
+.It "012 DC2" Ta "013 DC3" Ta "014 DC4" Ta "015\ NAK" Ta "016 SYN" Ta "017 ETB"
+.It "018 CAN" Ta "019 EM" Ta "01A SUB" Ta "01B ESC" Ta "01C FS" Ta "01D GS"
+.It "01E RS" Ta "01F US" Ta "07F DEL" Ta \& Ta \& Ta \&
+.El
+.El
+.Pp
+The default and supported byte counts for the conversion characters
+are as follows:
+.Bl -tag -width "Xc,_Xc,_Xc,_Xc,_Xc,_Xc" -offset indent
+.It Li \&%_c , \&%_p , \&%_u , \&%c
+One byte counts only.
+.It Xo
+.Li \&%d , \&%i , \&%o ,
+.Li \&%u , \&%X , \&%x
+.Xc
+Four byte default, one, two and four byte counts supported.
+.It Xo
+.Li \&%E , \&%e , \&%f ,
+.Li \&%G , \&%g
+.Xc
+Eight byte default, four and twelve byte counts supported.
+.El
+.Pp
+The amount of data interpreted by each format string is the sum of the
+data required by each format unit, which is the iteration count times the
+byte count, or the iteration count times the number of bytes required by
+the format if the byte count is not specified.
+.Pp
+The input is manipulated in ``blocks'', where a block is defined as the
+largest amount of data specified by any format string.
+Format strings interpreting less than an input block's worth of data,
+whose last format unit both interprets some number of bytes and does
+not have a specified iteration count, have the iteration count
+incremented until the entire input block has been processed or there
+is not enough data remaining in the block to satisfy the format string.
+.Pp
+If, either as a result of user specification or
+.Nm
+modifying
+the iteration count as described above, an iteration count is
+greater than one, no trailing whitespace characters are output
+during the last iteration.
+.Pp
+It is an error to specify a byte count as well as multiple conversion
+characters or strings unless all but one of the conversion characters
+or strings is
+.Cm \&_a
+or
+.Cm \&_A .
+.Pp
+If, as a result of the specification of the
+.Fl n
+option or end-of-file being reached, input data only partially
+satisfies a format string, the input block is zero-padded sufficiently
+to display all available data (i.e., any format units overlapping the
+end of data will display some number of the zero bytes).
+.Pp
+Further output by such format strings is replaced by an equivalent
+number of spaces.
+An equivalent number of spaces is defined as the number of spaces
+output by an
+.Cm s
+conversion character with the same field width
+and precision as the original conversion character or conversion
+string but with any
+.Dq Li \&+ ,
+.Dq \&\ \& ,
+.Dq Li \&#
+conversion flag characters
+removed, and referencing a NULL string.
+.Pp
+If no format strings are specified, the default display is equivalent
+to specifying the
+.Fl x
+option.
+.Sh EXIT STATUS
+.Ex -std hexdump hd
+.Sh EXAMPLES
+Dump input in canonical (hex+ASCII) form:
+.Bd -literal -offset indent
+$ echo "FreeBSD: The power to serve" | hexdump -C
+00000000 46 72 65 65 42 53 44 3a 20 54 68 65 20 70 6f 77 |FreeBSD: The pow|
+00000010 65 72 20 74 6f 20 73 65 72 76 65 0a |er to serve.|
+0000001c
+.Ed
+.Pp
+Same as above but skipping the first 4 bytes of stdin and interpreting only 3
+bytes of input:
+.Bd -literal -offset indent
+$ echo "FreeBSD: The power to serve" | hexdump -C -s 4 -n 3
+00000004 42 53 44 |BSD|
+00000007
+.Ed
+.Pp
+Assuming a format file named
+.Pa format.txt
+with the following contents that specify a perusal format:
+.Bd -literal -offset indent
+"%06.6_ao " 12/1 "%3_u "
+"\et\et" "%_p "
+"\en"
+.Ed
+.Pp
+Dump input in canonical form using the format in
+.Pa format.txt :
+.Bd -literal -offset indent
+$ echo "FreeBSD" | hexdump -f format.txt -C
+000000 F r e e B S D lf F r e e B S D .
+00000000 46 72 65 65 42 53 44 0a |FreeBSD.|
+00000008
+.Ed
+.Pp
+Assuming a format file named
+.Pa format.txt
+with the following contents that simulate the
+.Fl x
+option:
+.Bd -literal -offset indent
+"%07.7_Ax\en"
+"%07.7_ax " 8/2 "%04x " "\en"
+.Ed
+.Pp
+Dump input in canonical form using the format in
+.Pa format.txt :
+.Bd -literal -offset indent
+$ echo "FreeBSD: The power to serve" | hexdump -f format.txt -C
+0000000 7246 6565 5342 3a44 5420 6568 7020 776f
+00000000 46 72 65 65 42 53 44 3a 20 54 68 65 20 70 6f 77 |FreeBSD: The pow|
+0000010 7265 7420 206f 6573 7672 0a65
+00000010 65 72 20 74 6f 20 73 65 72 76 65 0a |er to serve.|
+0000001c
+.Ed
+.Sh SEE ALSO
+.Xr od 1
diff --git a/usr.bin/hexdump/hexdump.c b/usr.bin/hexdump/hexdump.c
new file mode 100644
index 000000000000..7fd6ff107afd
--- /dev/null
+++ b/usr.bin/hexdump/hexdump.c
@@ -0,0 +1,81 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "hexdump.h"
+
+FS *fshead; /* head of format strings */
+int blocksize; /* data block size */
+int exitval; /* final exit value */
+int length = -1; /* max bytes to read */
+
+int
+main(int argc, char *argv[])
+{
+ FS *tfs;
+ char *p;
+
+ (void)setlocale(LC_ALL, "");
+
+ if (!(p = strrchr(argv[0], 'o')) || strcmp(p, "od"))
+ newsyntax(argc, &argv);
+ else
+ oldsyntax(argc, &argv);
+
+ /* figure out the data block size */
+ for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
+ tfs->bcnt = size(tfs);
+ if (blocksize < tfs->bcnt)
+ blocksize = tfs->bcnt;
+ }
+ /* rewrite the rules, do syntax checking */
+ for (tfs = fshead; tfs; tfs = tfs->nextfs)
+ rewrite(tfs);
+
+ /*
+ * Cache NLS data, for strerror, for err(3), before entering capability
+ * mode.
+ */
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0)
+ err(1, "capsicum");
+
+ (void)next(argv);
+ display();
+ exit(exitval);
+}
diff --git a/usr.bin/hexdump/hexdump.h b/usr.bin/hexdump/hexdump.h
new file mode 100644
index 000000000000..f4110a38fd2a
--- /dev/null
+++ b/usr.bin/hexdump/hexdump.h
@@ -0,0 +1,104 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <wchar.h>
+
+typedef struct _pr {
+ struct _pr *nextpr; /* next print unit */
+#define F_ADDRESS 0x001 /* print offset */
+#define F_BPAD 0x002 /* blank pad */
+#define F_C 0x004 /* %_c */
+#define F_CHAR 0x008 /* %c */
+#define F_DBL 0x010 /* %[EefGf] */
+#define F_INT 0x020 /* %[di] */
+#define F_P 0x040 /* %_p */
+#define F_STR 0x080 /* %s */
+#define F_U 0x100 /* %_u */
+#define F_UINT 0x200 /* %[ouXx] */
+#define F_TEXT 0x400 /* no conversions */
+ u_int flags; /* flag values */
+ int bcnt; /* byte count */
+ char *cchar; /* conversion character */
+ char *fmt; /* printf format */
+ char *nospace; /* no whitespace version */
+ int mbleft; /* bytes left of multibyte char. */
+ mbstate_t mbstate; /* conversion state */
+} PR;
+
+typedef struct _fu {
+ struct _fu *nextfu; /* next format unit */
+ struct _pr *nextpr; /* next print unit */
+#define F_IGNORE 0x01 /* %_A */
+#define F_SETREP 0x02 /* rep count set, not default */
+ u_int flags; /* flag values */
+ int reps; /* repetition count */
+ int bcnt; /* byte count */
+ char *fmt; /* format string */
+} FU;
+
+typedef struct _fs { /* format strings */
+ struct _fs *nextfs; /* linked list of format strings */
+ struct _fu *nextfu; /* linked list of format units */
+ int bcnt;
+} FS;
+
+extern FS *fshead; /* head of format strings list */
+extern FU *endfu; /* format at end-of-data */
+extern int blocksize; /* data block size */
+extern int exitval; /* final exit value */
+extern int odmode; /* are we acting as od(1)? */
+extern int length; /* amount of data to read */
+extern off_t skip; /* amount of data to skip at start */
+enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
+extern enum _vflag vflag;
+
+void add(const char *);
+void addfile(const char *);
+void badcnt(const char *);
+void badconv(const char *);
+void badfmt(const char *);
+void badnoconv(void);
+void badsfmt(void);
+void bpad(PR *);
+void conv_c(PR *, u_char *, size_t);
+void conv_u(PR *, u_char *);
+void display(void);
+void doskip(const char *, int);
+void escape(char *);
+u_char *get(void);
+void newsyntax(int, char ***);
+int next(char **);
+void nomem(void);
+void oldsyntax(int, char ***);
+size_t peek(u_char *, size_t);
+void rewrite(FS *);
+int size(FS *);
+void usage(void);
diff --git a/usr.bin/hexdump/hexsyntax.c b/usr.bin/hexdump/hexsyntax.c
new file mode 100644
index 000000000000..de6b384cdb73
--- /dev/null
+++ b/usr.bin/hexdump/hexsyntax.c
@@ -0,0 +1,134 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 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.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "hexdump.h"
+
+off_t skip; /* bytes to skip */
+
+void
+newsyntax(int argc, char ***argvp)
+{
+ int ch;
+ char *p, **argv;
+
+ argv = *argvp;
+ if ((p = strrchr(argv[0], 'h')) != NULL &&
+ strcmp(p, "hd") == 0) {
+ /* "Canonical" format, implies -C. */
+ add("\"%08.8_Ax\n\"");
+ add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
+ add("\" |\" 16/1 \"%_p\" \"|\\n\"");
+ }
+ while ((ch = getopt(argc, argv, "bcCde:f:n:os:vx")) != -1)
+ switch (ch) {
+ case 'b':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
+ break;
+ case 'c':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
+ break;
+ case 'C':
+ add("\"%08.8_Ax\n\"");
+ add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
+ add("\" |\" 16/1 \"%_p\" \"|\\n\"");
+ break;
+ case 'd':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
+ break;
+ case 'e':
+ add(optarg);
+ break;
+ case 'f':
+ addfile(optarg);
+ break;
+ case 'n':
+ if ((length = atoi(optarg)) < 0)
+ errx(1, "%s: bad length value", optarg);
+ break;
+ case 'o':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
+ break;
+ case 's':
+ if ((skip = strtoll(optarg, &p, 0)) < 0)
+ errx(1, "%s: bad skip value", optarg);
+ switch(*p) {
+ case 'b':
+ skip *= 512;
+ break;
+ case 'k':
+ skip *= 1024;
+ break;
+ case 'm':
+ skip *= 1048576;
+ break;
+ }
+ break;
+ case 'v':
+ vflag = ALL;
+ break;
+ case 'x':
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
+ break;
+ case '?':
+ usage();
+ }
+
+ if (!fshead) {
+ add("\"%07.7_Ax\n\"");
+ add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
+ }
+
+ *argvp += optind;
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
+"usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]",
+" [-s skip] [file ...]",
+" hd [-bcdovx] [-e fmt] [-f fmt_file] [-n length]",
+" [-s skip] [file ...]");
+ exit(1);
+}
diff --git a/usr.bin/hexdump/od.1 b/usr.bin/hexdump/od.1
new file mode 100644
index 000000000000..4738fa040db0
--- /dev/null
+++ b/usr.bin/hexdump/od.1
@@ -0,0 +1,279 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd December 22, 2011
+.Dt OD 1
+.Os
+.Sh NAME
+.Nm od
+.Nd octal, decimal, hex, ASCII dump
+.Sh SYNOPSIS
+.Nm
+.Op Fl aBbcDdeFfHhIiLlOosvXx
+.Op Fl A Ar base
+.Op Fl j Ar skip
+.Op Fl N Ar length
+.Op Fl t Ar type
+.Op Oo Cm + Oc Ns Ar offset Ns Oo Cm \&. Oc Ns Op Cm Bb
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a filter which displays the specified files, or standard
+input if no files are specified, in a user specified format.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl I , L , l"
+.It Fl A Ar base
+Specify the input address base.
+The argument
+.Ar base
+may be one of
+.Cm d ,
+.Cm o ,
+.Cm x
+or
+.Cm n ,
+which specify decimal, octal, hexadecimal
+addresses or no address, respectively.
+.It Fl a
+Output named characters.
+Equivalent to
+.Fl t Cm a .
+.It Fl B , o
+Output octal shorts.
+Equivalent to
+.Fl t Cm o2 .
+.It Fl b
+Output octal bytes.
+Equivalent to
+.Fl t Cm o1 .
+.It Fl c
+Output C-style escaped characters.
+Equivalent to
+.Fl t Cm c .
+.It Fl D
+Output unsigned decimal ints.
+Equivalent to
+.Fl t Cm u4 .
+.It Fl d
+Output unsigned decimal shorts.
+Equivalent to
+.Fl t Cm u2 .
+.It Fl e , F
+Output double-precision floating point numbers.
+Equivalent to
+.Fl t Cm fD .
+.It Fl f
+Output single-precision floating point numbers.
+Equivalent to
+.Fl t Cm fF .
+.It Fl H , X
+Output hexadecimal ints.
+Equivalent to
+.Fl t Cm x4 .
+.It Fl h , x
+Output hexadecimal shorts.
+Equivalent to
+.Fl t Cm x2 .
+.It Fl I , L , l
+Output signed decimal longs.
+Equivalent to
+.Fl t Cm dL .
+.It Fl i
+Output signed decimal ints.
+Equivalent to
+.Fl t Cm dI .
+.It Fl j Ar skip
+Skip
+.Ar skip
+bytes of the combined input before dumping.
+The number may be followed by one
+of
+.Cm b , k
+or
+.Cm m
+which specify the units of the number as blocks (512 bytes), kilobytes and
+megabytes, respectively.
+.It Fl N Ar length
+Dump at most
+.Ar length
+bytes of input.
+.It Fl O
+Output octal ints.
+Equivalent to
+.Fl t Cm o4 .
+.It Fl s
+Output signed decimal shorts.
+Equivalent to
+.Fl t Cm d2 .
+.It Fl t Ar type
+Specify the output format.
+The
+.Ar type
+argument
+is a string containing one or more of the following kinds of type specifiers:
+.Bl -tag -width indent
+.It Cm a
+Named characters
+.Pq ASCII .
+Control characters are displayed using the following names:
+.Bl -column "000 NUL" "001 SOH" "002 STX" "003 ETX" "004 EOT" "005 ENQ"
+.It "000 NUL 001 SOH 002 STX 003 ETX 004 EOT 005 ENQ"
+.It "006 ACK 007 BEL 008 BS 009 HT 00A NL 00B VT"
+.It "00C FF 00D CR 00E SO 00F SI 010 DLE 011 DC1"
+.It "012 DC2 013 DC3 014 DC4 015 NAK 016 SYN 017 ETB"
+.It "018 CAN 019 EM 01A SUB 01B ESC 01C FS 01D GS"
+.It "01E RS 01F US 020 SP 07F DEL \& \&"
+.El
+.It Cm c
+Characters in the default character set.
+Non-printing characters are
+represented as 3-digit octal character codes, except the following
+characters, which are represented as C escapes:
+.Pp
+.Bl -tag -width carriage-return -compact
+.It NUL
+\e0
+.It alert
+\ea
+.It backspace
+\eb
+.It newline
+\en
+.It carriage-return
+\er
+.It tab
+\et
+.It vertical tab
+\ev
+.El
+.Pp
+Multi-byte characters are displayed in the area corresponding to the first
+byte of the character.
+The remaining bytes are shown as
+.Ql ** .
+.It Xo
+.Sm off
+.Op Cm d | o | u | x
+.Op Cm C | S | I | L | Ar n
+.Sm on
+.Xc
+Signed decimal
+.Pq Cm d ,
+octal
+.Pq Cm o ,
+unsigned decimal
+.Pq Cm u
+or
+hexadecimal
+.Pq Cm x .
+Followed by an optional size specifier, which may be either
+.Cm C
+.Pq Vt char ,
+.Cm S
+.Pq Vt short ,
+.Cm I
+.Pq Vt int ,
+.Cm L
+.Pq Vt long ,
+or a byte count as a decimal integer.
+.It Xo
+.Sm off
+.Cm f
+.Op Cm F | D | L | Ar n
+.Sm on
+.Xc
+Floating-point number.
+Followed by an optional size specifier, which may be either
+.Cm F
+.Pq Vt float ,
+.Cm D
+.Pq Vt double
+or
+.Cm L
+.Pq Vt "long double" .
+.El
+.It Fl v
+Write all input data, instead of replacing lines of duplicate values with a
+.Ql * .
+.El
+.Pp
+Multiple options that specify output format may be used; the output will
+contain one line for each format.
+.Pp
+If no output format is specified,
+.Fl t Cm oS
+is assumed.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Dump stdin and show the output using named characters and C-style escaped
+characters:
+.Bd -literal -offset indent
+$ echo "FreeBSD: The power to serve" | od -a -c
+0000000 F r e e B S D : sp T h e sp p o w
+ F r e e B S D : T h e p o w
+0000020 e r sp t o sp s e r v e nl
+ e r t o s e r v e \en
+0000034
+.Ed
+.Pp
+Dump stdin skipping the first 13 bytes using named characters and dumping no
+more than 5 bytes:
+.Bd -literal -offset indent
+$ echo "FreeBSD: The power to serve" | od -An -a -j 13 -N 5
+ p o w e r
+.Ed
+.Sh COMPATIBILITY
+The traditional
+.Fl s
+option to extract string constants is not supported; consider using
+.Xr strings 1
+instead.
+.Sh SEE ALSO
+.Xr hexdump 1 ,
+.Xr strings 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+An
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/hexdump/odsyntax.c b/usr.bin/hexdump/odsyntax.c
new file mode 100644
index 000000000000..6c7ca55c3232
--- /dev/null
+++ b/usr.bin/hexdump/odsyntax.c
@@ -0,0 +1,432 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 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.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <float.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "hexdump.h"
+
+#define PADDING " "
+
+int odmode;
+
+static void odadd(const char *);
+static void odformat(const char *);
+static const char *odformatfp(char, const char *);
+static const char *odformatint(char, const char *);
+static void odoffset(int, char ***);
+static void odusage(void);
+
+void
+oldsyntax(int argc, char ***argvp)
+{
+ static char empty[] = "", padding[] = PADDING;
+ int ch;
+ char **argv, *end;
+
+ /* Add initial (default) address format. -A may change it later. */
+#define TYPE_OFFSET 7
+ add("\"%07.7_Ao\n\"");
+ add("\"%07.7_ao \"");
+
+ odmode = 1;
+ argv = *argvp;
+ while ((ch = getopt(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx")) != -1)
+ switch (ch) {
+ case 'A':
+ switch (*optarg) {
+ case 'd': case 'o': case 'x':
+ fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
+ fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
+ *optarg;
+ break;
+ case 'n':
+ fshead->nextfu->fmt = empty;
+ fshead->nextfs->nextfu->fmt = padding;
+ break;
+ default:
+ errx(1, "%s: invalid address base", optarg);
+ }
+ break;
+ case 'a':
+ odformat("a");
+ break;
+ case 'B':
+ case 'o':
+ odformat("o2");
+ break;
+ case 'b':
+ odformat("o1");
+ break;
+ case 'c':
+ odformat("c");
+ break;
+ case 'd':
+ odformat("u2");
+ break;
+ case 'D':
+ odformat("u4");
+ break;
+ case 'e': /* undocumented in od */
+ case 'F':
+ odformat("fD");
+ break;
+ case 'f':
+ odformat("fF");
+ break;
+ case 'H':
+ case 'X':
+ odformat("x4");
+ break;
+ case 'h':
+ case 'x':
+ odformat("x2");
+ break;
+ case 'I':
+ case 'L':
+ case 'l':
+ odformat("dL");
+ break;
+ case 'i':
+ odformat("dI");
+ break;
+ case 'j':
+ errno = 0;
+ skip = strtoll(optarg, &end, 0);
+ if (*end == 'b')
+ skip *= 512;
+ else if (*end == 'k')
+ skip *= 1024;
+ else if (*end == 'm')
+ skip *= 1048576L;
+ if (errno != 0 || skip < 0 || strlen(end) > 1)
+ errx(1, "%s: invalid skip amount", optarg);
+ break;
+ case 'N':
+ if ((length = atoi(optarg)) <= 0)
+ errx(1, "%s: invalid length", optarg);
+ break;
+ case 'O':
+ odformat("o4");
+ break;
+ case 's':
+ odformat("d2");
+ break;
+ case 't':
+ odformat(optarg);
+ break;
+ case 'v':
+ vflag = ALL;
+ break;
+ case '?':
+ default:
+ odusage();
+ }
+
+ if (fshead->nextfs->nextfs == NULL)
+ odformat("oS");
+
+ argc -= optind;
+ *argvp += optind;
+
+ if (argc)
+ odoffset(argc, argvp);
+}
+
+static void
+odusage(void)
+{
+
+ fprintf(stderr,
+"usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n");
+ fprintf(stderr,
+" [[+]offset[.][Bb]] [file ...]\n");
+ exit(1);
+}
+
+static void
+odoffset(int argc, char ***argvp)
+{
+ char *p, *num, *end;
+ int base;
+
+ /*
+ * The offset syntax of od(1) was genuinely bizarre. First, if
+ * it started with a plus it had to be an offset. Otherwise, if
+ * there were at least two arguments, a number or lower-case 'x'
+ * followed by a number makes it an offset. By default it was
+ * octal; if it started with 'x' or '0x' it was hex. If it ended
+ * in a '.', it was decimal. If a 'b' or 'B' was appended, it
+ * multiplied the number by 512 or 1024 byte units. There was
+ * no way to assign a block count to a hex offset.
+ *
+ * We assume it's a file if the offset is bad.
+ */
+ p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
+
+ if (*p != '+' && (argc < 2 ||
+ (!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
+ return;
+
+ base = 0;
+ /*
+ * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
+ * set base.
+ */
+ if (p[0] == '+')
+ ++p;
+ if (p[0] == 'x' && isxdigit(p[1])) {
+ ++p;
+ base = 16;
+ } else if (p[0] == '0' && p[1] == 'x') {
+ p += 2;
+ base = 16;
+ }
+
+ /* skip over the number */
+ if (base == 16)
+ for (num = p; isxdigit(*p); ++p);
+ else
+ for (num = p; isdigit(*p); ++p);
+
+ /* check for no number */
+ if (num == p)
+ return;
+
+ /* if terminates with a '.', base is decimal */
+ if (*p == '.') {
+ if (base)
+ return;
+ base = 10;
+ }
+
+ skip = strtoll(num, &end, base ? base : 8);
+
+ /* if end isn't the same as p, we got a non-octal digit */
+ if (end != p) {
+ skip = 0;
+ return;
+ }
+
+ if (*p) {
+ if (*p == 'B') {
+ skip *= 1024;
+ ++p;
+ } else if (*p == 'b') {
+ skip *= 512;
+ ++p;
+ }
+ }
+
+ if (*p) {
+ skip = 0;
+ return;
+ }
+
+ /*
+ * If the offset uses a non-octal base, the base of the offset
+ * is changed as well. This isn't pretty, but it's easy.
+ */
+ if (base == 16) {
+ fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
+ fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
+ } else if (base == 10) {
+ fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
+ fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
+ }
+
+ /* Terminate file list. */
+ (*argvp)[1] = NULL;
+}
+
+static void
+odformat(const char *fmt)
+{
+ char fchar;
+
+ while (*fmt != '\0') {
+ switch ((fchar = *fmt++)) {
+ case 'a':
+ odadd("16/1 \"%3_u \" \"\\n\"");
+ break;
+ case 'c':
+ odadd("16/1 \"%3_c \" \"\\n\"");
+ break;
+ case 'o': case 'u': case 'd': case 'x':
+ fmt = odformatint(fchar, fmt);
+ break;
+ case 'f':
+ fmt = odformatfp(fchar, fmt);
+ break;
+ default:
+ errx(1, "%c: unrecognised format character", fchar);
+ }
+ }
+}
+
+static const char *
+odformatfp(char fchar __unused, const char *fmt)
+{
+ size_t isize;
+ int digits;
+ char *end, *hdfmt;
+
+ isize = sizeof(double);
+ switch (*fmt) {
+ case 'F':
+ isize = sizeof(float);
+ fmt++;
+ break;
+ case 'D':
+ isize = sizeof(double);
+ fmt++;
+ break;
+ case 'L':
+ isize = sizeof(long double);
+ fmt++;
+ break;
+ default:
+ if (isdigit((unsigned char)*fmt)) {
+ errno = 0;
+ isize = (size_t)strtoul(fmt, &end, 10);
+ if (errno != 0 || isize == 0)
+ errx(1, "%s: invalid size", fmt);
+ fmt = (const char *)end;
+ }
+ }
+ switch (isize) {
+ case sizeof(float):
+ digits = FLT_DIG;
+ break;
+ case sizeof(double):
+ digits = DBL_DIG;
+ break;
+ default:
+ if (isize == sizeof(long double))
+ digits = LDBL_DIG;
+ else
+ errx(1, "unsupported floating point size %lu",
+ (u_long)isize);
+ }
+
+ asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"",
+ 16UL / (u_long)isize, (u_long)isize, digits + 8, digits);
+ if (hdfmt == NULL)
+ err(1, NULL);
+ odadd(hdfmt);
+ free(hdfmt);
+
+ return (fmt);
+}
+
+static const char *
+odformatint(char fchar, const char *fmt)
+{
+ unsigned long long n;
+ size_t isize;
+ int digits;
+ char *end, *hdfmt;
+
+ isize = sizeof(int);
+ switch (*fmt) {
+ case 'C':
+ isize = sizeof(char);
+ fmt++;
+ break;
+ case 'I':
+ isize = sizeof(int);
+ fmt++;
+ break;
+ case 'L':
+ isize = sizeof(long);
+ fmt++;
+ break;
+ case 'S':
+ isize = sizeof(short);
+ fmt++;
+ break;
+ default:
+ if (isdigit((unsigned char)*fmt)) {
+ errno = 0;
+ isize = (size_t)strtoul(fmt, &end, 10);
+ if (errno != 0 || isize == 0)
+ errx(1, "%s: invalid size", fmt);
+ if (isize != sizeof(char) && isize != sizeof(short) &&
+ isize != sizeof(int) && isize != sizeof(long))
+ errx(1, "unsupported int size %lu",
+ (u_long)isize);
+ fmt = (const char *)end;
+ }
+ }
+
+ /*
+ * Calculate the maximum number of digits we need to
+ * fit the number. Overestimate for decimal with log
+ * base 8. We need one extra space for signed numbers
+ * to store the sign.
+ */
+ n = (1ULL << (8 * isize)) - 1;
+ digits = 0;
+ while (n != 0) {
+ digits++;
+ n >>= (fchar == 'x') ? 4 : 3;
+ }
+ if (fchar == 'd')
+ digits++;
+ asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",
+ 16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits),
+ "", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar);
+ if (hdfmt == NULL)
+ err(1, NULL);
+ odadd(hdfmt);
+ free(hdfmt);
+
+ return (fmt);
+}
+
+static void
+odadd(const char *fmt)
+{
+ static int needpad;
+
+ if (needpad)
+ add("\""PADDING"\"");
+ add(fmt);
+ needpad = 1;
+}
diff --git a/usr.bin/hexdump/parse.c b/usr.bin/hexdump/parse.c
new file mode 100644
index 000000000000..0f61763bd7bf
--- /dev/null
+++ b/usr.bin/hexdump/parse.c
@@ -0,0 +1,524 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "hexdump.h"
+
+FU *endfu; /* format at end-of-data */
+
+void
+addfile(const char *name)
+{
+ unsigned char *p;
+ FILE *fp;
+ int ch;
+ char buf[2048 + 1];
+
+ if ((fp = fopen(name, "r")) == NULL)
+ err(1, "%s", name);
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (!(p = strchr(buf, '\n'))) {
+ warnx("line too long");
+ while ((ch = getchar()) != '\n' && ch != EOF);
+ continue;
+ }
+ *p = '\0';
+ for (p = buf; *p && isspace(*p); ++p);
+ if (!*p || *p == '#')
+ continue;
+ add(p);
+ }
+ (void)fclose(fp);
+}
+
+void
+add(const char *fmt)
+{
+ unsigned const char *p, *savep;
+ static FS **nextfs;
+ FS *tfs;
+ FU *tfu, **nextfu;
+
+ /* start new linked list of format units */
+ if ((tfs = calloc(1, sizeof(FS))) == NULL)
+ err(1, NULL);
+ if (!fshead)
+ fshead = tfs;
+ else
+ *nextfs = tfs;
+ nextfs = &tfs->nextfs;
+ nextfu = &tfs->nextfu;
+
+ /* take the format string and break it up into format units */
+ for (p = fmt;;) {
+ /* skip leading white space */
+ for (; isspace(*p); ++p);
+ if (!*p)
+ break;
+
+ /* allocate a new format unit and link it in */
+ if ((tfu = calloc(1, sizeof(FU))) == NULL)
+ err(1, NULL);
+ *nextfu = tfu;
+ nextfu = &tfu->nextfu;
+ tfu->reps = 1;
+
+ /* if leading digit, repetition count */
+ if (isdigit(*p)) {
+ for (savep = p; isdigit(*p); ++p);
+ if (!isspace(*p) && *p != '/')
+ badfmt(fmt);
+ /* may overwrite either white space or slash */
+ tfu->reps = atoi(savep);
+ tfu->flags = F_SETREP;
+ /* skip trailing white space */
+ for (++p; isspace(*p); ++p);
+ }
+
+ /* skip slash and trailing white space */
+ if (*p == '/')
+ while (isspace(*++p));
+
+ /* byte count */
+ if (isdigit(*p)) {
+ for (savep = p; isdigit(*p); ++p);
+ if (!isspace(*p))
+ badfmt(fmt);
+ tfu->bcnt = atoi(savep);
+ /* skip trailing white space */
+ for (++p; isspace(*p); ++p);
+ }
+
+ /* format */
+ if (*p != '"')
+ badfmt(fmt);
+ for (savep = ++p; *p != '"';)
+ if (*p++ == 0)
+ badfmt(fmt);
+ if (!(tfu->fmt = malloc(p - savep + 1)))
+ err(1, NULL);
+ (void) strlcpy(tfu->fmt, savep, p - savep + 1);
+ escape(tfu->fmt);
+ p++;
+ }
+}
+
+static const char *spec = ".#-+ 0123456789";
+
+int
+size(FS *fs)
+{
+ FU *fu;
+ int bcnt, cursize;
+ unsigned char *fmt;
+ int prec;
+
+ /* figure out the data block size needed for each format unit */
+ for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (fu->bcnt) {
+ cursize += fu->bcnt * fu->reps;
+ continue;
+ }
+ for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
+ if (*fmt != '%')
+ continue;
+ /*
+ * skip any special chars -- save precision in
+ * case it's a %s format.
+ */
+ while (*++fmt != 0 && strchr(spec + 1, *fmt) != NULL)
+ ;
+ if (*fmt == 0)
+ badnoconv();
+ if (*fmt == '.' && isdigit(*++fmt)) {
+ prec = atoi(fmt);
+ while (isdigit(*++fmt));
+ }
+ switch(*fmt) {
+ case 'c':
+ bcnt += 1;
+ break;
+ case 'd': case 'i': case 'o': case 'u':
+ case 'x': case 'X':
+ bcnt += 4;
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ bcnt += 8;
+ break;
+ case 's':
+ bcnt += prec;
+ break;
+ case '_':
+ switch(*++fmt) {
+ case 'c': case 'p': case 'u':
+ bcnt += 1;
+ break;
+ }
+ }
+ }
+ cursize += bcnt * fu->reps;
+ }
+ return (cursize);
+}
+
+void
+rewrite(FS *fs)
+{
+ enum { NOTOKAY, USEBCNT, USEPREC } sokay;
+ PR *pr, **nextpr;
+ FU *fu;
+ unsigned char *p1, *p2, *fmtp;
+ char savech, cs[3];
+ int nconv, prec;
+
+ prec = 0;
+
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ /*
+ * Break each format unit into print units; each conversion
+ * character gets its own.
+ */
+ nextpr = &fu->nextpr;
+ for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
+ if ((pr = calloc(1, sizeof(PR))) == NULL)
+ err(1, NULL);
+ *nextpr = pr;
+
+ /* Skip preceding text and up to the next % sign. */
+ for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
+
+ /* Only text in the string. */
+ if (!*p1) {
+ pr->fmt = fmtp;
+ pr->flags = F_TEXT;
+ break;
+ }
+
+ /*
+ * Get precision for %s -- if have a byte count, don't
+ * need it.
+ */
+ if (fu->bcnt) {
+ sokay = USEBCNT;
+ /* Skip to conversion character. */
+ while (*++p1 != 0 && strchr(spec, *p1) != NULL)
+ ;
+ if (*p1 == 0)
+ badnoconv();
+ } else {
+ /* Skip any special chars, field width. */
+ while (*++p1 != 0 && strchr(spec + 1, *p1) != NULL)
+ ;
+ if (*p1 == 0)
+ badnoconv();
+ if (*p1 == '.' && isdigit(*++p1)) {
+ sokay = USEPREC;
+ prec = atoi(p1);
+ while (isdigit(*++p1));
+ } else
+ sokay = NOTOKAY;
+ }
+
+ p2 = *p1 ? p1 + 1 : p1; /* Set end pointer -- make sure
+ * that it's non-NUL/-NULL first
+ * though. */
+ cs[0] = *p1; /* Set conversion string. */
+ cs[1] = '\0';
+
+ /*
+ * Figure out the byte count for each conversion;
+ * rewrite the format as necessary, set up blank-
+ * padding for end of data.
+ */
+ switch(cs[0]) {
+ case 'c':
+ pr->flags = F_CHAR;
+ switch(fu->bcnt) {
+ case 0: case 1:
+ pr->bcnt = 1;
+ break;
+ default:
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ break;
+ case 'd': case 'i':
+ pr->flags = F_INT;
+ goto isint;
+ case 'o': case 'u': case 'x': case 'X':
+ pr->flags = F_UINT;
+isint: cs[2] = '\0';
+ cs[1] = cs[0];
+ cs[0] = 'q';
+ switch(fu->bcnt) {
+ case 0: case 4:
+ pr->bcnt = 4;
+ break;
+ case 1:
+ pr->bcnt = 1;
+ break;
+ case 2:
+ pr->bcnt = 2;
+ break;
+ case 8:
+ pr->bcnt = 8;
+ break;
+ default:
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ break;
+ case 'e': case 'E': case 'f': case 'g': case 'G':
+ pr->flags = F_DBL;
+ switch(fu->bcnt) {
+ case 0: case 8:
+ pr->bcnt = 8;
+ break;
+ case 4:
+ pr->bcnt = 4;
+ break;
+ default:
+ if (fu->bcnt == sizeof(long double)) {
+ cs[2] = '\0';
+ cs[1] = cs[0];
+ cs[0] = 'L';
+ pr->bcnt = sizeof(long double);
+ } else {
+ p1[1] = '\0';
+ badcnt(p1);
+ }
+ }
+ break;
+ case 's':
+ pr->flags = F_STR;
+ switch(sokay) {
+ case NOTOKAY:
+ badsfmt();
+ case USEBCNT:
+ pr->bcnt = fu->bcnt;
+ break;
+ case USEPREC:
+ pr->bcnt = prec;
+ break;
+ }
+ break;
+ case '_':
+ ++p2;
+ switch(p1[1]) {
+ case 'A':
+ endfu = fu;
+ fu->flags |= F_IGNORE;
+ /* FALLTHROUGH */
+ case 'a':
+ pr->flags = F_ADDRESS;
+ ++p2;
+ switch(p1[2]) {
+ case 'd': case 'o': case'x':
+ cs[0] = 'q';
+ cs[1] = p1[2];
+ cs[2] = '\0';
+ break;
+ default:
+ p1[3] = '\0';
+ badconv(p1);
+ }
+ break;
+ case 'c':
+ pr->flags = F_C;
+ /* cs[0] = 'c'; set in conv_c */
+ goto isint2;
+ case 'p':
+ pr->flags = F_P;
+ cs[0] = 'c';
+ goto isint2;
+ case 'u':
+ pr->flags = F_U;
+ /* cs[0] = 'c'; set in conv_u */
+isint2: switch(fu->bcnt) {
+ case 0: case 1:
+ pr->bcnt = 1;
+ break;
+ default:
+ p1[2] = '\0';
+ badcnt(p1);
+ }
+ break;
+ default:
+ p1[2] = '\0';
+ badconv(p1);
+ }
+ break;
+ default:
+ p1[1] = '\0';
+ badconv(p1);
+ }
+
+ /*
+ * Copy to PR format string, set conversion character
+ * pointer, update original.
+ */
+ savech = *p2;
+ p1[0] = '\0';
+ if (asprintf(&pr->fmt, "%s%s", fmtp, cs) == -1)
+ err(1, NULL);
+ *p2 = savech;
+ pr->cchar = pr->fmt + (p1 - fmtp);
+ fmtp = p2;
+
+ /* Only one conversion character if byte count. */
+ if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)
+ errx(1, "byte count with multiple conversion characters");
+ }
+ /*
+ * If format unit byte count not specified, figure it out
+ * so can adjust rep count later.
+ */
+ if (!fu->bcnt)
+ for (pr = fu->nextpr; pr; pr = pr->nextpr)
+ fu->bcnt += pr->bcnt;
+ }
+ /*
+ * If the format string interprets any data at all, and it's
+ * not the same as the blocksize, and its last format unit
+ * interprets any data at all, and has no iteration count,
+ * repeat it as necessary.
+ *
+ * If, rep count is greater than 1, no trailing whitespace
+ * gets output from the last iteration of the format unit.
+ */
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ if (!fu->nextfu && fs->bcnt < blocksize &&
+ !(fu->flags&F_SETREP) && fu->bcnt)
+ fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
+ if (fu->reps > 1) {
+ for (pr = fu->nextpr;; pr = pr->nextpr)
+ if (!pr->nextpr)
+ break;
+ for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
+ p2 = isspace(*p1) ? p1 : NULL;
+ if (p2)
+ pr->nospace = p2;
+ }
+ }
+#ifdef DEBUG
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
+ (void)printf("fmt:");
+ for (pr = fu->nextpr; pr; pr = pr->nextpr)
+ (void)printf(" {%s}", pr->fmt);
+ (void)printf("\n");
+ }
+#endif
+}
+
+void
+escape(char *p1)
+{
+ char *p2;
+
+ /* alphabetic escape sequences have to be done in place */
+ for (p2 = p1;; p1++, p2++) {
+ if (*p1 == '\\') {
+ p1++;
+ switch(*p1) {
+ case '\0':
+ *p2 = '\\';
+ *++p2 = '\0';
+ return;
+ case 'a':
+ /* *p2 = '\a'; */
+ *p2 = '\007';
+ break;
+ case 'b':
+ *p2 = '\b';
+ break;
+ case 'f':
+ *p2 = '\f';
+ break;
+ case 'n':
+ *p2 = '\n';
+ break;
+ case 'r':
+ *p2 = '\r';
+ break;
+ case 't':
+ *p2 = '\t';
+ break;
+ case 'v':
+ *p2 = '\v';
+ break;
+ default:
+ *p2 = *p1;
+ break;
+ }
+ } else {
+ *p2 = *p1;
+ if (*p1 == '\0')
+ return;
+ }
+ }
+}
+
+void
+badcnt(const char *s)
+{
+ errx(1, "%s: bad byte count", s);
+}
+
+void
+badsfmt(void)
+{
+ errx(1, "%%s: requires a precision or a byte count");
+}
+
+void
+badfmt(const char *fmt)
+{
+ errx(1, "\"%s\": bad format", fmt);
+}
+
+void
+badconv(const char *ch)
+{
+ errx(1, "%%%s: bad conversion character", ch);
+}
+
+void
+badnoconv(void)
+{
+ errx(1, "missing conversion character");
+}
diff --git a/usr.bin/hexdump/tests/Makefile b/usr.bin/hexdump/tests/Makefile
new file mode 100644
index 000000000000..151407d3459c
--- /dev/null
+++ b/usr.bin/hexdump/tests/Makefile
@@ -0,0 +1,43 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= hexdump_test od_test
+
+${PACKAGE}FILES+= d_hexdump_a.in
+${PACKAGE}FILES+= d_hexdump_b.in
+${PACKAGE}FILES+= d_hexdump_c.in
+${PACKAGE}FILES+= d_hexdump_bug118723.in
+${PACKAGE}FILES+= d_hexdump_bflag_a.out
+${PACKAGE}FILES+= d_hexdump_bflag_b.out
+${PACKAGE}FILES+= d_hexdump_bflag_c.out
+${PACKAGE}FILES+= d_hexdump_cflag_a.out
+${PACKAGE}FILES+= d_hexdump_cflag_b.out
+${PACKAGE}FILES+= d_hexdump_cflag_c.out
+${PACKAGE}FILES+= d_hexdump_dflag_a_el.out
+${PACKAGE}FILES+= d_hexdump_dflag_b_el.out
+${PACKAGE}FILES+= d_hexdump_dflag_c_el.out
+${PACKAGE}FILES+= d_hexdump_dflag_a_eb.out
+${PACKAGE}FILES+= d_hexdump_dflag_b_eb.out
+${PACKAGE}FILES+= d_hexdump_dflag_c_eb.out
+${PACKAGE}FILES+= d_hexdump_nflag_a.out
+${PACKAGE}FILES+= d_hexdump_oflag_a_el.out
+${PACKAGE}FILES+= d_hexdump_oflag_b_el.out
+${PACKAGE}FILES+= d_hexdump_oflag_c_el.out
+${PACKAGE}FILES+= d_hexdump_oflag_a_eb.out
+${PACKAGE}FILES+= d_hexdump_oflag_b_eb.out
+${PACKAGE}FILES+= d_hexdump_oflag_c_eb.out
+${PACKAGE}FILES+= d_hexdump_sflag_a.out
+${PACKAGE}FILES+= d_hexdump_UCflag_a.out
+${PACKAGE}FILES+= d_hexdump_UCflag_b.out
+${PACKAGE}FILES+= d_hexdump_UCflag_c.out
+${PACKAGE}FILES+= d_hexdump_UCflag_bug118723.out
+${PACKAGE}FILES+= d_hexdump_UCvflag_bug118723.out
+${PACKAGE}FILES+= d_hexdump_xflag_a_el.out
+${PACKAGE}FILES+= d_hexdump_xflag_b_el.out
+${PACKAGE}FILES+= d_hexdump_xflag_c_el.out
+${PACKAGE}FILES+= d_hexdump_xflag_a_eb.out
+${PACKAGE}FILES+= d_hexdump_xflag_b_eb.out
+${PACKAGE}FILES+= d_hexdump_xflag_c_eb.out
+${PACKAGE}FILES+= d_od_cflag_a.out
+${PACKAGE}FILES+= d_od_cflag_b.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/hexdump/tests/Makefile.depend b/usr.bin/hexdump/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/hexdump/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/hexdump/tests/d_hexdump_UCflag_a.out b/usr.bin/hexdump/tests/d_hexdump_UCflag_a.out
new file mode 100644
index 000000000000..b929e8f6e299
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_UCflag_a.out
@@ -0,0 +1,2 @@
+00000000 54 65 73 74 0a |Test.|
+00000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_UCflag_b.out b/usr.bin/hexdump/tests/d_hexdump_UCflag_b.out
new file mode 100644
index 000000000000..44c0fb3ac1af
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_UCflag_b.out
@@ -0,0 +1,4 @@
+00000000 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 |The quick brown |
+00000010 66 6f 78 20 6a 75 6d 70 65 64 20 6f 76 65 72 20 |fox jumped over |
+00000020 74 68 65 20 62 6c 75 65 20 68 6f 75 73 65 0a 0a |the blue house..|
+00000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_UCflag_bug118723.out b/usr.bin/hexdump/tests/d_hexdump_UCflag_bug118723.out
new file mode 100644
index 000000000000..bd1f5333b6a1
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_UCflag_bug118723.out
@@ -0,0 +1,4 @@
+00000000 61 62 63 64 65 66 67 0a 30 31 32 33 34 35 36 0a |abcdefg.0123456.|
+*
+00000020 61 62 63 64 65 66 67 0a |abcdefg.|
+00000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_UCflag_c.out b/usr.bin/hexdump/tests/d_hexdump_UCflag_c.out
new file mode 100644
index 000000000000..ee16184cd74a
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_UCflag_c.out
@@ -0,0 +1,4 @@
+00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAAAAAA|
+*
+00000020 41 41 41 41 41 41 41 0a |AAAAAAA.|
+00000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_UCvflag_bug118723.out b/usr.bin/hexdump/tests/d_hexdump_UCvflag_bug118723.out
new file mode 100644
index 000000000000..927897a3cef8
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_UCvflag_bug118723.out
@@ -0,0 +1,4 @@
+00000000 61 62 63 64 65 66 67 0a 30 31 32 33 34 35 36 0a |abcdefg.0123456.|
+00000010 61 62 63 64 65 66 67 0a 30 31 32 33 34 35 36 0a |abcdefg.0123456.|
+00000020 61 62 63 64 65 66 67 0a |abcdefg.|
+00000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_a.in b/usr.bin/hexdump/tests/d_hexdump_a.in
new file mode 100644
index 000000000000..345e6aef7132
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_a.in
@@ -0,0 +1 @@
+Test
diff --git a/usr.bin/hexdump/tests/d_hexdump_b.in b/usr.bin/hexdump/tests/d_hexdump_b.in
new file mode 100644
index 000000000000..0fa918480ebe
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_b.in
@@ -0,0 +1,2 @@
+The quick brown fox jumped over the blue house
+
diff --git a/usr.bin/hexdump/tests/d_hexdump_bflag_a.out b/usr.bin/hexdump/tests/d_hexdump_bflag_a.out
new file mode 100644
index 000000000000..232ab776f0f3
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_bflag_a.out
@@ -0,0 +1,2 @@
+0000000 124 145 163 164 012
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_bflag_b.out b/usr.bin/hexdump/tests/d_hexdump_bflag_b.out
new file mode 100644
index 000000000000..1bd7c9ddbabb
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_bflag_b.out
@@ -0,0 +1,4 @@
+0000000 124 150 145 040 161 165 151 143 153 040 142 162 157 167 156 040
+0000010 146 157 170 040 152 165 155 160 145 144 040 157 166 145 162 040
+0000020 164 150 145 040 142 154 165 145 040 150 157 165 163 145 012 012
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_bflag_c.out b/usr.bin/hexdump/tests/d_hexdump_bflag_c.out
new file mode 100644
index 000000000000..c19f2671a8ae
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_bflag_c.out
@@ -0,0 +1,4 @@
+0000000 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101
+*
+0000020 101 101 101 101 101 101 101 012
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_bug118723.in b/usr.bin/hexdump/tests/d_hexdump_bug118723.in
new file mode 100644
index 000000000000..8ecef445e1e6
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_bug118723.in
@@ -0,0 +1,5 @@
+abcdefg
+0123456
+abcdefg
+0123456
+abcdefg
diff --git a/usr.bin/hexdump/tests/d_hexdump_c.in b/usr.bin/hexdump/tests/d_hexdump_c.in
new file mode 100644
index 000000000000..2304918bcccb
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_c.in
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
diff --git a/usr.bin/hexdump/tests/d_hexdump_cflag_a.out b/usr.bin/hexdump/tests/d_hexdump_cflag_a.out
new file mode 100644
index 000000000000..c0f49ff32051
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_cflag_a.out
@@ -0,0 +1,2 @@
+0000000 T e s t \n
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_cflag_b.out b/usr.bin/hexdump/tests/d_hexdump_cflag_b.out
new file mode 100644
index 000000000000..0d087ed042f9
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_cflag_b.out
@@ -0,0 +1,4 @@
+0000000 T h e q u i c k b r o w n
+0000010 f o x j u m p e d o v e r
+0000020 t h e b l u e h o u s e \n \n
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_cflag_c.out b/usr.bin/hexdump/tests/d_hexdump_cflag_c.out
new file mode 100644
index 000000000000..edebd59246dc
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_cflag_c.out
@@ -0,0 +1,4 @@
+0000000 A A A A A A A A A A A A A A A A
+*
+0000020 A A A A A A A \n
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_a_eb.out b/usr.bin/hexdump/tests/d_hexdump_dflag_a_eb.out
new file mode 100644
index 000000000000..1d01c608f542
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_a_eb.out
@@ -0,0 +1,2 @@
+0000000 21605 29556 02560
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_a_el.out b/usr.bin/hexdump/tests/d_hexdump_dflag_a_el.out
new file mode 100644
index 000000000000..148b1bcecbb5
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_a_el.out
@@ -0,0 +1,2 @@
+0000000 25940 29811 00010
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_b_eb.out b/usr.bin/hexdump/tests/d_hexdump_dflag_b_eb.out
new file mode 100644
index 000000000000..eb09cbcb69ba
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_b_eb.out
@@ -0,0 +1,4 @@
+0000000 21608 25888 29045 26979 27424 25202 28535 28192
+0000010 26223 30752 27253 28016 25956 08303 30309 29216
+0000020 29800 25888 25196 30053 08296 28533 29541 02570
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_b_el.out b/usr.bin/hexdump/tests/d_hexdump_dflag_b_el.out
new file mode 100644
index 000000000000..e8b486c9bba6
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_b_el.out
@@ -0,0 +1,4 @@
+0000000 26708 08293 30065 25449 08299 29282 30575 08302
+0000010 28518 08312 30058 28781 25701 28448 25974 08306
+0000020 26740 08293 27746 25973 26656 30063 25971 02570
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_c_eb.out b/usr.bin/hexdump/tests/d_hexdump_dflag_c_eb.out
new file mode 100644
index 000000000000..75eb88e5da10
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_c_eb.out
@@ -0,0 +1,4 @@
+0000000 16705 16705 16705 16705 16705 16705 16705 16705
+*
+0000020 16705 16705 16705 16650
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_dflag_c_el.out b/usr.bin/hexdump/tests/d_hexdump_dflag_c_el.out
new file mode 100644
index 000000000000..7a2d17714263
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_dflag_c_el.out
@@ -0,0 +1,4 @@
+0000000 16705 16705 16705 16705 16705 16705 16705 16705
+*
+0000020 16705 16705 16705 02625
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_nflag_a.out b/usr.bin/hexdump/tests/d_hexdump_nflag_a.out
new file mode 100644
index 000000000000..2b7b61b4fc8b
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_nflag_a.out
@@ -0,0 +1,2 @@
+0000000 124
+0000001
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_a_eb.out b/usr.bin/hexdump/tests/d_hexdump_oflag_a_eb.out
new file mode 100644
index 000000000000..ca410afdb2b9
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_a_eb.out
@@ -0,0 +1,2 @@
+0000000 052145 071564 005000
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_a_el.out b/usr.bin/hexdump/tests/d_hexdump_oflag_a_el.out
new file mode 100644
index 000000000000..92b8c177f5d8
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_a_el.out
@@ -0,0 +1,2 @@
+0000000 062524 072163 000012
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_b_eb.out b/usr.bin/hexdump/tests/d_hexdump_oflag_b_eb.out
new file mode 100644
index 000000000000..045db8f65e8b
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_b_eb.out
@@ -0,0 +1,4 @@
+0000000 052150 062440 070565 064543 065440 061162 067567 067040
+0000010 063157 074040 065165 066560 062544 020157 073145 071040
+0000020 072150 062440 061154 072545 020150 067565 071545 005012
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_b_el.out b/usr.bin/hexdump/tests/d_hexdump_oflag_b_el.out
new file mode 100644
index 000000000000..6e8c2615cc3d
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_b_el.out
@@ -0,0 +1,4 @@
+0000000 064124 020145 072561 061551 020153 071142 073557 020156
+0000010 067546 020170 072552 070155 062145 067440 062566 020162
+0000020 064164 020145 066142 062565 064040 072557 062563 005012
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_c_eb.out b/usr.bin/hexdump/tests/d_hexdump_oflag_c_eb.out
new file mode 100644
index 000000000000..90347e00a452
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_c_eb.out
@@ -0,0 +1,4 @@
+0000000 040501 040501 040501 040501 040501 040501 040501 040501
+*
+0000020 040501 040501 040501 040412
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_oflag_c_el.out b/usr.bin/hexdump/tests/d_hexdump_oflag_c_el.out
new file mode 100644
index 000000000000..26a076074b69
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_oflag_c_el.out
@@ -0,0 +1,4 @@
+0000000 040501 040501 040501 040501 040501 040501 040501 040501
+*
+0000020 040501 040501 040501 005101
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_sflag_a.out b/usr.bin/hexdump/tests/d_hexdump_sflag_a.out
new file mode 100644
index 000000000000..c7179d5c62ed
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_sflag_a.out
@@ -0,0 +1,2 @@
+0000004 012
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_a_eb.out b/usr.bin/hexdump/tests/d_hexdump_xflag_a_eb.out
new file mode 100644
index 000000000000..777a09c40a69
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_a_eb.out
@@ -0,0 +1,2 @@
+0000000 5465 7374 0a00
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_a_el.out b/usr.bin/hexdump/tests/d_hexdump_xflag_a_el.out
new file mode 100644
index 000000000000..adba00a2ae03
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_a_el.out
@@ -0,0 +1,2 @@
+0000000 6554 7473 000a
+0000005
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_b_eb.out b/usr.bin/hexdump/tests/d_hexdump_xflag_b_eb.out
new file mode 100644
index 000000000000..1e7672b7fbb2
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_b_eb.out
@@ -0,0 +1,4 @@
+0000000 5468 6520 7175 6963 6b20 6272 6f77 6e20
+0000010 666f 7820 6a75 6d70 6564 206f 7665 7220
+0000020 7468 6520 626c 7565 2068 6f75 7365 0a0a
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_b_el.out b/usr.bin/hexdump/tests/d_hexdump_xflag_b_el.out
new file mode 100644
index 000000000000..75911e776375
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_b_el.out
@@ -0,0 +1,4 @@
+0000000 6854 2065 7571 6369 206b 7262 776f 206e
+0000010 6f66 2078 756a 706d 6465 6f20 6576 2072
+0000020 6874 2065 6c62 6575 6820 756f 6573 0a0a
+0000030
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_c_eb.out b/usr.bin/hexdump/tests/d_hexdump_xflag_c_eb.out
new file mode 100644
index 000000000000..3515e498b977
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_c_eb.out
@@ -0,0 +1,4 @@
+0000000 4141 4141 4141 4141 4141 4141 4141 4141
+*
+0000020 4141 4141 4141 410a
+0000028
diff --git a/usr.bin/hexdump/tests/d_hexdump_xflag_c_el.out b/usr.bin/hexdump/tests/d_hexdump_xflag_c_el.out
new file mode 100644
index 000000000000..39bb73adc326
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_hexdump_xflag_c_el.out
@@ -0,0 +1,4 @@
+0000000 4141 4141 4141 4141 4141 4141 4141 4141
+*
+0000020 4141 4141 4141 0a41
+0000028
diff --git a/usr.bin/hexdump/tests/d_od_cflag_a.out b/usr.bin/hexdump/tests/d_od_cflag_a.out
new file mode 100644
index 000000000000..db8037f0824d
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_od_cflag_a.out
@@ -0,0 +1,3 @@
+0000000 T e s t T e s t T e s t T e s 345
+0000020 T e s t 345
+0000025
diff --git a/usr.bin/hexdump/tests/d_od_cflag_b.out b/usr.bin/hexdump/tests/d_od_cflag_b.out
new file mode 100644
index 000000000000..bd9e9d1dddfb
--- /dev/null
+++ b/usr.bin/hexdump/tests/d_od_cflag_b.out
@@ -0,0 +1,3 @@
+0000000 T e s t T e s t T e s t T e s Ñ‚
+0000020 ** Т ** е ** Ñ ** Ñ‚ **
+0000031
diff --git a/usr.bin/hexdump/tests/hexdump_test.sh b/usr.bin/hexdump/tests/hexdump_test.sh
new file mode 100755
index 000000000000..e7dc447d0ea5
--- /dev/null
+++ b/usr.bin/hexdump/tests/hexdump_test.sh
@@ -0,0 +1,218 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2017 Kyle Evans <kevans@FreeBSD.org>
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+ENDIAN=el
+ret=$(echo I | tr -d "[:space:]" | od -to2 | head -n1 | awk '{print $2}' | cut -c6)
+if [ "$ret" = "0" ]; then
+ ENDIAN=eb
+fi
+
+atf_test_case b_flag
+b_flag_head()
+{
+ atf_set "descr" "Verify -b output"
+}
+b_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_bflag_a.out" \
+ hexdump -b "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_bflag_b.out" \
+ hexdump -b "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_bflag_c.out" \
+ hexdump -b "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case c_flag
+c_flag_head()
+{
+ atf_set "descr" "Verify -c output"
+}
+c_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_cflag_a.out" \
+ hexdump -c "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_cflag_b.out" \
+ hexdump -c "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_cflag_c.out" \
+ hexdump -c "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case C_flag
+C_flag_head()
+{
+ atf_set "descr" "Verify -C output"
+}
+C_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_a.out" \
+ hexdump -C "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_b.out" \
+ hexdump -C "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_c.out" \
+ hexdump -C "$(atf_get_srcdir)/d_hexdump_c.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_bug118723.out" \
+ hexdump -C "$(atf_get_srcdir)/d_hexdump_bug118723.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCvflag_bug118723.out" \
+ hexdump -Cv "$(atf_get_srcdir)/d_hexdump_bug118723.in"
+}
+
+atf_test_case hd_name
+hd_name_head()
+{
+ atf_set "descr" "Verify hd output matching -C output"
+}
+hd_name_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_a.out" \
+ hd "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_b.out" \
+ hd "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_c.out" \
+ hd "$(atf_get_srcdir)/d_hexdump_c.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCflag_bug118723.out" \
+ hd "$(atf_get_srcdir)/d_hexdump_bug118723.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_UCvflag_bug118723.out" \
+ hd -v "$(atf_get_srcdir)/d_hexdump_bug118723.in"
+}
+
+atf_test_case d_flag
+d_flag_head()
+{
+ atf_set "descr" "Verify -d output"
+}
+d_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_dflag_a_$ENDIAN.out" \
+ hexdump -d "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_dflag_b_$ENDIAN.out" \
+ hexdump -d "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_dflag_c_$ENDIAN.out" \
+ hexdump -d "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case n_flag
+n_flag_head()
+{
+ atf_set "descr" "Check -n functionality"
+}
+n_flag_body()
+{
+ atf_check -o empty hexdump -bn 0 "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_nflag_a.out" \
+ hexdump -bn 1 "$(atf_get_srcdir)/d_hexdump_a.in"
+}
+
+atf_test_case o_flag
+o_flag_head()
+{
+ atf_set "descr" "Verify -o output"
+}
+o_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_oflag_a_$ENDIAN.out" \
+ hexdump -o "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_oflag_b_$ENDIAN.out" \
+ hexdump -o "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_oflag_c_$ENDIAN.out" \
+ hexdump -o "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case s_flag
+s_flag_head()
+{
+ atf_set "descr" "Verify -s output"
+}
+s_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_sflag_a.out" \
+ hexdump -bs 4 "$(atf_get_srcdir)/d_hexdump_a.in"
+
+ atf_check -o not-empty hexdump -n 100 -s 1024 /dev/random
+}
+
+atf_test_case v_flag
+v_flag_head()
+{
+ atf_set "descr" "Verify -v functionality"
+}
+v_flag_body()
+{
+ for i in $(seq 0 7); do
+ atf_check -o match:"^\*$" \
+ hexdump -s ${i} "$(atf_get_srcdir)/d_hexdump_c.in"
+ atf_check -o not-match:"^\*$" \
+ hexdump -vs ${i} "$(atf_get_srcdir)/d_hexdump_c.in"
+ done
+
+ atf_check -o not-match:"^\*$" \
+ hexdump -s 8 "$(atf_get_srcdir)/d_hexdump_c.in"
+ atf_check -o not-match:"^\*$" \
+ hexdump -vs 8 "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case x_flag
+x_flag_head()
+{
+ atf_set "descr" "Verify -x output"
+}
+x_flag_body()
+{
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_xflag_a_$ENDIAN.out" \
+ hexdump -x "$(atf_get_srcdir)/d_hexdump_a.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_xflag_b_$ENDIAN.out" \
+ hexdump -x "$(atf_get_srcdir)/d_hexdump_b.in"
+ atf_check -o file:"$(atf_get_srcdir)/d_hexdump_xflag_c_$ENDIAN.out" \
+ hexdump -x "$(atf_get_srcdir)/d_hexdump_c.in"
+}
+
+atf_test_case no_conv_err
+no_conv_err()
+{
+ atf_set "descr" "Verify missing conversion char error handling"
+}
+no_conv_err_body()
+{
+ atf_check -s exit:1 -e ignore \
+ hexdump -e '"%"'
+ atf_check -s exit:1 -e ignore \
+ hexdump -e '4/2 "%"'
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case b_flag
+ atf_add_test_case c_flag
+ atf_add_test_case C_flag
+ atf_add_test_case hd_name
+ atf_add_test_case d_flag
+ atf_add_test_case n_flag
+ atf_add_test_case o_flag
+ atf_add_test_case s_flag
+ atf_add_test_case v_flag
+ atf_add_test_case x_flag
+ atf_add_test_case no_conv_err
+}
diff --git a/usr.bin/hexdump/tests/od_test.sh b/usr.bin/hexdump/tests/od_test.sh
new file mode 100755
index 000000000000..6b46bc034414
--- /dev/null
+++ b/usr.bin/hexdump/tests/od_test.sh
@@ -0,0 +1,49 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2018 (C) Yuri Pankov
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case c_flag
+c_flag_head()
+{
+ atf_set "descr" "Verify -c output (PR 224552)"
+}
+c_flag_body()
+{
+ export LC_ALL="en_US.UTF-8"
+
+ printf 'TestTestTestTes\345Test\345' > d_od_cflag.in
+ atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_a.out" \
+ od -c d_od_cflag.in
+ printf 'TestTestTestTesтТеÑÑ‚' > d_od_cflag.in
+ atf_check -o file:"$(atf_get_srcdir)/d_od_cflag_b.out" \
+ od -c d_od_cflag.in
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case c_flag
+}
diff --git a/usr.bin/host/Makefile b/usr.bin/host/Makefile
new file mode 100644
index 000000000000..45ca3698abd5
--- /dev/null
+++ b/usr.bin/host/Makefile
@@ -0,0 +1,18 @@
+LDNSDIR= ${SRCTOP}/contrib/ldns
+LDNSHOSTDIR= ${SRCTOP}/contrib/ldns-host
+
+.PATH: ${LDNSHOSTDIR}
+
+PROG= host
+SRCS= ldns-host.c
+MAN= host.1
+CLEANFILES+= host.1
+
+host.1: ldns-host.1
+ sed -e 's/ldns-//gI' <${.ALLSRC} >${.TARGET} || \
+ (rm -rf ${.TARGET} ; false)
+
+CFLAGS+= -I${LDNSDIR}
+LIBADD= ldns
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/host/Makefile.depend b/usr.bin/host/Makefile.depend
new file mode 100644
index 000000000000..87435ce2fe39
--- /dev/null
+++ b/usr.bin/host/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libldns \
+ secure/lib/libcrypto \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/iconv/Makefile b/usr.bin/iconv/Makefile
new file mode 100644
index 000000000000..2bdf8479f0ea
--- /dev/null
+++ b/usr.bin/iconv/Makefile
@@ -0,0 +1,9 @@
+# $NetBSD: Makefile,v 1.6 2009/04/14 22:15:21 lukem Exp $
+
+.include <bsd.own.mk>
+
+PROG= iconv
+#SRCS= iconv.c
+MAN= iconv.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/iconv/Makefile.depend b/usr.bin/iconv/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/iconv/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/iconv/iconv.1 b/usr.bin/iconv/iconv.1
new file mode 100644
index 000000000000..e1a7afca6987
--- /dev/null
+++ b/usr.bin/iconv/iconv.1
@@ -0,0 +1,125 @@
+.\" $NetBSD: iconv.1,v 1.3 2008/03/20 11:35:44 tnozaki Exp $
+.\"
+.\" Copyright (c)2003 Citrus Project,
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 October 22, 2009
+.Dt ICONV 1
+.Os
+.Sh NAME
+.Nm iconv
+.Nd codeset conversion utility
+.Sh SYNOPSIS
+.Nm
+.Op Fl cs
+.Fl f
+.Ar from_name
+.Fl t
+.Ar to_name
+.Op Ar file ...
+.Nm
+.Fl f
+.Ar from_name
+.Op Fl cs
+.Op Fl t Ar to_name
+.Op Ar file ...
+.Nm
+.Fl t
+.Ar to_name
+.Op Fl cs
+.Op Fl f Ar from_name
+.Op Ar file ...
+.Nm
+.Fl l
+.Sh DESCRIPTION
+The
+.Nm
+utility converts the codeset of
+.Ar file
+(or from standard input if no file is specified) from codeset
+.Ar from_name
+to codeset
+.Ar to_name
+and outputs the
+converted text on standard output.
+.Pp
+The following options are available:
+.Bl -tag -width 0123
+.It Fl c
+Prevent output of any invalid characters.
+By default,
+.Nm
+outputs an
+.Dq invalid character
+specified by the
+.Ar to_name
+codeset when it encounts a character which is valid in the
+.Ar from_name
+codeset but does not have a corresponding character in the
+.Ar to_name
+codeset.
+.It Fl f
+Specifies the source codeset name as
+.Ar from_name .
+.It Fl l
+Lists available codeset names.
+Note that not all combinations of
+.Ar from_name
+and
+.Ar to_name
+are valid.
+.It Fl s
+Silent.
+By default,
+.Nm
+outputs the number of
+.Dq invalid characters
+to standard error if they exist.
+This option prevents this behaviour.
+.It Fl t
+Specifies the destination codeset name as
+.Ar to_name .
+.El
+.Sh EXIT STATUS
+.Ex -std iconv
+.Sh EXAMPLES
+Convert
+.Pa file.txt
+from IBM273 to UTF-8 and save the result to
+.Pa converted.txt :
+.Pp
+.Dl iconv -f IBM273 -t UTF-8 file.txt > converted.txt
+.Sh SEE ALSO
+.Xr mkcsmapper 1 ,
+.Xr mkesdb 1 ,
+.Xr iconv 3
+.Sh STANDARDS
+.Nm
+conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 2.0 , and made its appearance in
+.Fx 9.0 .
diff --git a/usr.bin/iconv/iconv.c b/usr.bin/iconv/iconv.c
new file mode 100644
index 000000000000..7d1b3c49eee6
--- /dev/null
+++ b/usr.bin/iconv/iconv.c
@@ -0,0 +1,248 @@
+/* $NetBSD: iconv.c,v 1.16 2009/02/20 15:28:21 yamt Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <iconv.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_conv(FILE *, iconv_t, bool, bool);
+static int do_list(unsigned int, const char * const *, void *);
+static void usage(void) __dead2;
+
+static const struct option long_options[] = {
+ {"from-code", required_argument, NULL, 'f'},
+ {"list", no_argument, NULL, 'l'},
+ {"silent", no_argument, NULL, 's'},
+ {"to-code", required_argument, NULL, 't'},
+ {NULL, no_argument, NULL, 0}
+};
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage:\t%1$s [-cs] -f <from_code> -t <to_code> [file ...]\n"
+ "\t%1$s -f <from_code> [-cs] [-t <to_code>] [file ...]\n"
+ "\t%1$s -t <to_code> [-cs] [-f <from_code>] [file ...]\n"
+ "\t%1$s -l\n", getprogname());
+ exit(1);
+}
+
+#define INBUFSIZE 1024
+#define OUTBUFSIZE (INBUFSIZE * 2)
+static int
+do_conv(FILE *fp, iconv_t cd, bool silent, bool hide_invalid)
+{
+ char inbuf[INBUFSIZE], outbuf[OUTBUFSIZE], *in, *out;
+ unsigned long long invalids;
+ size_t inbytes, outbytes, ret;
+
+ /*
+ * Don't touch ICONV_SET_DISCARD_ILSEQ if -c wasn't specified. It may
+ * be that the user has specified //IGNORE in the -t specification, and
+ * we don't want to clobber that.
+ */
+ if (hide_invalid) {
+ int arg = (int)hide_invalid;
+ if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&arg) == -1)
+ err(EXIT_FAILURE, "iconvctl(DISCARD_ILSEQ, %d)", arg);
+ }
+
+ invalids = 0;
+ while ((inbytes = fread(inbuf, 1, INBUFSIZE, fp)) > 0) {
+ in = inbuf;
+ while (inbytes > 0) {
+ size_t inval;
+
+ out = outbuf;
+ outbytes = OUTBUFSIZE;
+ ret = __iconv(cd, &in, &inbytes, &out, &outbytes,
+ 0, &inval);
+ invalids += inval;
+ if (outbytes < OUTBUFSIZE)
+ (void)fwrite(outbuf, 1, OUTBUFSIZE - outbytes,
+ stdout);
+ if (ret == (size_t)-1 && errno != E2BIG) {
+ if (errno != EINVAL || in == inbuf)
+ err(EXIT_FAILURE, "iconv()");
+
+ /* incomplete input character */
+ (void)memmove(inbuf, in, inbytes);
+ ret = fread(inbuf + inbytes, 1,
+ INBUFSIZE - inbytes, fp);
+ if (ret == 0) {
+ fflush(stdout);
+ if (feof(fp))
+ errx(EXIT_FAILURE,
+ "unexpected end of file; "
+ "the last character is "
+ "incomplete.");
+ else
+ err(EXIT_FAILURE, "fread()");
+ }
+ in = inbuf;
+ inbytes += ret;
+ }
+ }
+ }
+ /* reset the shift state of the output buffer */
+ outbytes = OUTBUFSIZE;
+ out = outbuf;
+ ret = iconv(cd, NULL, NULL, &out, &outbytes);
+ if (ret == (size_t)-1)
+ err(EXIT_FAILURE, "iconv()");
+ if (outbytes < OUTBUFSIZE)
+ (void)fwrite(outbuf, 1, OUTBUFSIZE - outbytes, stdout);
+
+ if (invalids > 0 && !silent)
+ warnx("warning: invalid characters: %llu", invalids);
+
+ return (invalids > 0);
+}
+
+static int
+do_list(unsigned int n, const char * const *list, void *data __unused)
+{
+ unsigned int i;
+
+ for(i = 0; i < n; i++) {
+ printf("%s", list[i]);
+ if (i < n - 1)
+ printf(" ");
+ }
+ printf("\n");
+
+ return (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ iconv_t cd;
+ FILE *fp;
+ const char *opt_f, *opt_t;
+ int ch, i, res;
+ bool opt_c = false, opt_s = false;
+
+ opt_f = opt_t = "";
+
+ setlocale(LC_ALL, "");
+ setprogname(argv[0]);
+
+ while ((ch = getopt_long(argc, argv, "csLlf:t:",
+ long_options, NULL)) != -1) {
+ switch (ch) {
+ case 'c':
+ opt_c = true;
+ break;
+ case 's':
+ opt_s = true;
+ break;
+ case 'l':
+ /* list */
+ if (opt_s || opt_c || strcmp(opt_f, "") != 0 ||
+ strcmp(opt_t, "") != 0) {
+ warnx("-l is not allowed with other flags.");
+ usage();
+ }
+ iconvlist(do_list, NULL);
+ return (EXIT_SUCCESS);
+ case 'f':
+ /* from */
+ if (optarg != NULL)
+ opt_f = optarg;
+ break;
+ case 't':
+ /* to */
+ if (optarg != NULL)
+ opt_t = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if ((strcmp(opt_f, "") == 0) && (strcmp(opt_t, "") == 0))
+ usage();
+
+ if (caph_limit_stdio() < 0)
+ err(EXIT_FAILURE, "capsicum");
+
+ /*
+ * Cache NLS data, for strerror, for err(3), before entering capability
+ * mode.
+ */
+ caph_cache_catpages();
+
+ /*
+ * Cache iconv conversion handle before entering sandbox.
+ */
+ cd = iconv_open(opt_t, opt_f);
+ if (cd == (iconv_t)-1)
+ err(EXIT_FAILURE, "iconv_open(%s, %s)", opt_t, opt_f);
+
+ if (argc == 0) {
+ if (caph_enter() < 0)
+ err(EXIT_FAILURE, "unable to enter capability mode");
+ res = do_conv(stdin, cd, opt_s, opt_c);
+ } else {
+ res = 0;
+ for (i = 0; i < argc; i++) {
+ fp = (strcmp(argv[i], "-") != 0) ?
+ fopen(argv[i], "r") : stdin;
+ if (fp == NULL)
+ err(EXIT_FAILURE, "Cannot open `%s'",
+ argv[i]);
+ /* Enter Capsicum sandbox for final input file. */
+ if (i + 1 == argc && caph_enter() < 0)
+ err(EXIT_FAILURE,
+ "unable to enter capability mode");
+ res |= do_conv(fp, cd, opt_s, opt_c);
+ (void)fclose(fp);
+
+ /* Reset iconv descriptor state. */
+ (void)iconv(cd, NULL, NULL, NULL, NULL);
+ }
+ }
+ iconv_close(cd);
+ return (res == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
diff --git a/usr.bin/id/Makefile b/usr.bin/id/Makefile
new file mode 100644
index 000000000000..bc19e94b1f76
--- /dev/null
+++ b/usr.bin/id/Makefile
@@ -0,0 +1,14 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= id
+LINKS= ${BINDIR}/id ${BINDIR}/groups
+LINKS+= ${BINDIR}/id ${BINDIR}/whoami
+MAN= id.1 groups.1 whoami.1
+
+.if ${MK_AUDIT} != "no"
+CFLAGS+= -DUSE_BSM_AUDIT
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/id/Makefile.depend b/usr.bin/id/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/id/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/id/groups.1 b/usr.bin/id/groups.1
new file mode 100644
index 000000000000..1a6b4f769b05
--- /dev/null
+++ b/usr.bin/id/groups.1
@@ -0,0 +1,62 @@
+.\" Copyright (c) 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.
+.\"
+.Dd June 6, 1993
+.Dt GROUPS 1
+.Os
+.Sh NAME
+.Nm groups
+.Nd show group memberships
+.Sh SYNOPSIS
+.Nm
+.Op Ar user
+.Sh DESCRIPTION
+The
+.Nm
+utility has been obsoleted by the
+.Xr id 1
+utility, and is equivalent to
+.Dq Nm id Fl Gn Op Ar user .
+The command
+.Dq Nm id Fl p
+is suggested for normal interactive use.
+.Pp
+The
+.Nm
+utility displays the groups to which you (or the optionally specified
+.Ar user )
+belong.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show groups the root user belongs to:
+.Bd -literal -offset indent
+$ groups root
+wheel operator
+.Ed
+.Sh SEE ALSO
+.Xr id 1
diff --git a/usr.bin/id/id.1 b/usr.bin/id/id.1
new file mode 100644
index 000000000000..b8dafb6650b0
--- /dev/null
+++ b/usr.bin/id/id.1
@@ -0,0 +1,195 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd March 5, 2011
+.Dt ID 1
+.Os
+.Sh NAME
+.Nm id
+.Nd return user identity
+.Sh SYNOPSIS
+.Nm
+.Op Ar user
+.Nm
+.Fl A
+.Nm
+.Fl G Op Fl n
+.Op Ar user
+.Nm
+.Fl M
+.Nm
+.Fl P
+.Op Ar user
+.Nm
+.Fl c
+.Nm
+.Fl g Op Fl nr
+.Op Ar user
+.Nm
+.Fl p
+.Op Ar user
+.Nm
+.Fl u Op Fl nr
+.Op Ar user
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the user and group names and numeric IDs, of the
+calling process, to the standard output.
+If the real and effective IDs are different, both are displayed,
+otherwise only the real ID is displayed.
+.Pp
+If a
+.Ar user
+(login name or user ID)
+is specified, the user and group IDs of that user are displayed.
+In this case, the real and effective IDs are assumed to be the same.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl A
+Display the process audit user ID and other process audit properties, which
+requires privilege.
+.It Fl G
+Display the different group IDs (effective, real and supplementary)
+as white-space separated numbers, in no particular order.
+.It Fl M
+Display the MAC label of the current process.
+.It Fl P
+Display the id as a password file entry.
+.It Fl a
+Ignored for compatibility with other
+.Nm
+implementations.
+.It Fl c
+Display current login class.
+.It Fl g
+Display the effective group ID as a number.
+.It Fl n
+Display the name of the user or group ID for the
+.Fl G ,
+.Fl g
+and
+.Fl u
+options instead of the number.
+If any of the ID numbers cannot be mapped into names, the number will be
+displayed as usual.
+.It Fl p
+Make the output human-readable.
+If the user name returned by
+.Xr getlogin 2
+is different from the login name referenced by the user ID, the name
+returned by
+.Xr getlogin 2
+is displayed, preceded by the keyword
+.Dq login .
+The user ID as a name is displayed, preceded by the keyword
+.Dq uid .
+If the effective user ID is different from the real user ID, the real user
+ID is displayed as a name, preceded by the keyword
+.Dq euid .
+If the effective group ID is different from the real group ID, the real group
+ID is displayed as a name, preceded by the keyword
+.Dq rgid .
+The list of groups to which the user belongs is then displayed as names,
+preceded by the keyword
+.Dq groups .
+Each display is on a separate line.
+.It Fl r
+Display the real ID for the
+.Fl g
+and
+.Fl u
+options instead of the effective ID.
+.It Fl u
+Display the effective user ID as a number.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show information for the user
+.Ql bob
+as a password file entry:
+.Bd -literal -offset indent
+$ id -P bob
+bob:*:0:0::0:0:Robert:/bob:/usr/local/bin/bash
+.Ed
+.Pp
+Same output as
+.Xr groups 1 for the root user:
+.Bd -literal -offset indent
+$ id -Gn root
+wheel operator
+.Ed
+.Pp
+Show human readable information about
+.Ql alice :
+.Bd -literal -offset indent
+$ id -p alice
+uid alice
+groups alice webcamd vboxusers
+.Ed
+.Pp
+Assuming the user
+.Ql bob
+executed
+.Dq Nm su Fl l
+to simulate a root login, compare the result of the following commands:
+.Bd -literal -offset indent
+# id -un
+root
+# who am i
+bob pts/5 Dec 4 19:51
+.Ed
+.Sh SEE ALSO
+.Xr groups 1 ,
+.Xr who 1
+.Sh STANDARDS
+The
+.Nm
+function is expected to conform to
+.St -p1003.2 .
+.Sh HISTORY
+The
+historic
+.Xr groups 1
+command is equivalent to
+.Dq Nm id Fl Gn Op Ar user .
+.Pp
+The
+historic
+.Xr whoami 1
+command is equivalent to
+.Dq Nm id Fl un .
+.Pp
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.bin/id/id.c b/usr.bin/id/id.c
new file mode 100644
index 000000000000..dfd2e89a7e78
--- /dev/null
+++ b/usr.bin/id/id.c
@@ -0,0 +1,491 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/param.h>
+#include <sys/mac.h>
+
+#ifdef USE_BSM_AUDIT
+#include <bsm/audit.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void id_print(struct passwd *, int, int, int);
+static void pline(struct passwd *);
+static void pretty(struct passwd *);
+#ifdef USE_BSM_AUDIT
+static void auditid(void);
+#endif
+static void group(struct passwd *, int);
+static void maclabel(void);
+static void usage(void);
+static struct passwd *who(char *);
+
+static int isgroups, iswhoami;
+
+int
+main(int argc, char *argv[])
+{
+ struct group *gr;
+ struct passwd *pw;
+ int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
+ int Aflag, cflag;
+ int error;
+ const char *myname;
+ char loginclass[MAXLOGNAME];
+
+ Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
+ Aflag = cflag = 0;
+
+ myname = strrchr(argv[0], '/');
+ myname = (myname != NULL) ? myname + 1 : argv[0];
+ if (strcmp(myname, "groups") == 0) {
+ isgroups = 1;
+ Gflag = nflag = 1;
+ }
+ else if (strcmp(myname, "whoami") == 0) {
+ iswhoami = 1;
+ uflag = nflag = 1;
+ }
+
+ while ((ch = getopt(argc, argv,
+ (isgroups || iswhoami) ? "" : "APGMacgnpru")) != -1)
+ switch(ch) {
+#ifdef USE_BSM_AUDIT
+ case 'A':
+ Aflag = 1;
+ break;
+#endif
+ case 'G':
+ Gflag = 1;
+ break;
+ case 'M':
+ Mflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ break;
+ case 'a':
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'g':
+ gflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (iswhoami && argc > 0)
+ usage();
+ if ((cflag || Aflag || Mflag) && argc > 0)
+ usage();
+
+ switch(Aflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
+ case 1:
+ break;
+ case 0:
+ if (!nflag && !rflag)
+ break;
+ /* FALLTHROUGH */
+ default:
+ usage();
+ }
+
+ pw = *argv ? who(*argv) : NULL;
+
+ if (Mflag && pw != NULL)
+ usage();
+
+#ifdef USE_BSM_AUDIT
+ if (Aflag) {
+ auditid();
+ exit(0);
+ }
+#endif
+
+ if (cflag) {
+ error = getloginclass(loginclass, sizeof(loginclass));
+ if (error != 0)
+ err(1, "loginclass");
+ (void)printf("%s\n", loginclass);
+ exit(0);
+ }
+
+ if (gflag) {
+ id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
+ if (nflag && (gr = getgrgid(id)))
+ (void)printf("%s\n", gr->gr_name);
+ else
+ (void)printf("%u\n", id);
+ exit(0);
+ }
+
+ if (uflag) {
+ id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
+ if (nflag && (pw = getpwuid(id)))
+ (void)printf("%s\n", pw->pw_name);
+ else
+ (void)printf("%u\n", id);
+ exit(0);
+ }
+
+ if (Gflag) {
+ group(pw, nflag);
+ exit(0);
+ }
+
+ if (Mflag) {
+ maclabel();
+ exit(0);
+ }
+
+ if (Pflag) {
+ pline(pw);
+ exit(0);
+ }
+
+ if (pflag) {
+ pretty(pw);
+ exit(0);
+ }
+
+ if (pw) {
+ id_print(pw, 1, 0, 0);
+ }
+ else {
+ id = getuid();
+ pw = getpwuid(id);
+ id_print(pw, 0, 1, 1);
+ }
+ exit(0);
+}
+
+static void
+pretty(struct passwd *pw)
+{
+ struct group *gr;
+ u_int eid, rid;
+ char *login;
+
+ if (pw) {
+ (void)printf("uid\t%s\n", pw->pw_name);
+ (void)printf("groups\t");
+ group(pw, 1);
+ } else {
+ if ((login = getlogin()) == NULL)
+ err(1, "getlogin");
+
+ pw = getpwuid(rid = getuid());
+ if (pw == NULL || strcmp(login, pw->pw_name))
+ (void)printf("login\t%s\n", login);
+ if (pw)
+ (void)printf("uid\t%s\n", pw->pw_name);
+ else
+ (void)printf("uid\t%u\n", rid);
+
+ if ((eid = geteuid()) != rid) {
+ if ((pw = getpwuid(eid)))
+ (void)printf("euid\t%s\n", pw->pw_name);
+ else
+ (void)printf("euid\t%u\n", eid);
+ }
+ if ((rid = getgid()) != (eid = getegid())) {
+ if ((gr = getgrgid(rid)))
+ (void)printf("rgid\t%s\n", gr->gr_name);
+ else
+ (void)printf("rgid\t%u\n", rid);
+ }
+ (void)printf("groups\t");
+ group(NULL, 1);
+ }
+}
+
+static void
+id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
+{
+ struct group *gr;
+ gid_t gid, egid, lastgid;
+ uid_t uid, euid;
+ int cnt, ngroups;
+ long ngroups_max;
+ gid_t *groups;
+ const char *fmt;
+
+ if (pw != NULL) {
+ uid = pw->pw_uid;
+ gid = pw->pw_gid;
+ }
+ else {
+ uid = getuid();
+ gid = getgid();
+ }
+
+ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
+ err(1, "malloc");
+
+ if (use_ggl && pw != NULL) {
+ ngroups = ngroups_max;
+ getgrouplist(pw->pw_name, gid, groups, &ngroups);
+ }
+ else {
+ ngroups = getgroups(ngroups_max, groups);
+ }
+
+ if (pw != NULL)
+ printf("uid=%u(%s)", uid, pw->pw_name);
+ else
+ printf("uid=%u", getuid());
+ printf(" gid=%u", gid);
+ if ((gr = getgrgid(gid)))
+ (void)printf("(%s)", gr->gr_name);
+ if (p_euid && (euid = geteuid()) != uid) {
+ (void)printf(" euid=%u", euid);
+ if ((pw = getpwuid(euid)))
+ (void)printf("(%s)", pw->pw_name);
+ }
+ if (p_egid && (egid = getegid()) != gid) {
+ (void)printf(" egid=%u", egid);
+ if ((gr = getgrgid(egid)))
+ (void)printf("(%s)", gr->gr_name);
+ }
+ fmt = " groups=%u";
+ for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
+ if (lastgid == (gid = groups[cnt]))
+ continue;
+ printf(fmt, gid);
+ fmt = ",%u";
+ if ((gr = getgrgid(gid)))
+ printf("(%s)", gr->gr_name);
+ lastgid = gid;
+ }
+ printf("\n");
+ free(groups);
+}
+
+#ifdef USE_BSM_AUDIT
+static void
+auditid(void)
+{
+ auditinfo_t auditinfo;
+ auditinfo_addr_t ainfo_addr;
+ int ret, extended;
+
+ extended = 0;
+ ret = getaudit(&auditinfo);
+ if (ret < 0 && errno == E2BIG) {
+ if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0)
+ err(1, "getaudit_addr");
+ extended = 1;
+ } else if (ret < 0)
+ err(1, "getaudit");
+ if (extended != 0) {
+ (void) printf("auid=%d\n"
+ "mask.success=0x%08x\n"
+ "mask.failure=0x%08x\n"
+ "asid=%d\n"
+ "termid_addr.port=0x%08jx\n"
+ "termid_addr.addr[0]=0x%08x\n"
+ "termid_addr.addr[1]=0x%08x\n"
+ "termid_addr.addr[2]=0x%08x\n"
+ "termid_addr.addr[3]=0x%08x\n",
+ ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success,
+ ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid,
+ (uintmax_t)ainfo_addr.ai_termid.at_port,
+ ainfo_addr.ai_termid.at_addr[0],
+ ainfo_addr.ai_termid.at_addr[1],
+ ainfo_addr.ai_termid.at_addr[2],
+ ainfo_addr.ai_termid.at_addr[3]);
+ } else {
+ (void) printf("auid=%d\n"
+ "mask.success=0x%08x\n"
+ "mask.failure=0x%08x\n"
+ "asid=%d\n"
+ "termid.port=0x%08jx\n"
+ "termid.machine=0x%08x\n",
+ auditinfo.ai_auid, auditinfo.ai_mask.am_success,
+ auditinfo.ai_mask.am_failure,
+ auditinfo.ai_asid, (uintmax_t)auditinfo.ai_termid.port,
+ auditinfo.ai_termid.machine);
+ }
+}
+#endif
+
+static void
+group(struct passwd *pw, int nflag)
+{
+ struct group *gr;
+ int cnt, id, lastid, ngroups;
+ long ngroups_max;
+ gid_t *groups;
+ const char *fmt;
+
+ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ if ((groups = malloc(sizeof(gid_t) * (ngroups_max))) == NULL)
+ err(1, "malloc");
+
+ if (pw) {
+ ngroups = ngroups_max;
+ (void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+ } else {
+ ngroups = getgroups(ngroups_max, groups);
+ }
+ fmt = nflag ? "%s" : "%u";
+ for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
+ if (lastid == (id = groups[cnt]))
+ continue;
+ if (nflag) {
+ if ((gr = getgrgid(id)))
+ (void)printf(fmt, gr->gr_name);
+ else
+ (void)printf(*fmt == ' ' ? " %u" : "%u",
+ id);
+ fmt = " %s";
+ } else {
+ (void)printf(fmt, id);
+ fmt = " %u";
+ }
+ lastid = id;
+ }
+ (void)printf("\n");
+ free(groups);
+}
+
+static void
+maclabel(void)
+{
+ char *string;
+ mac_t label;
+ int error;
+
+ error = mac_prepare_process_label(&label);
+ if (error == -1)
+ errx(1, "mac_prepare_type: %s", strerror(errno));
+
+ error = mac_get_proc(label);
+ if (error == -1)
+ errx(1, "mac_get_proc: %s", strerror(errno));
+
+ error = mac_to_text(label, &string);
+ if (error == -1)
+ errx(1, "mac_to_text: %s", strerror(errno));
+
+ (void)printf("%s\n", string);
+ mac_free(label);
+ free(string);
+}
+
+static struct passwd *
+who(char *u)
+{
+ struct passwd *pw;
+ long id;
+ char *ep;
+
+ /*
+ * Translate user argument into a pw pointer. First, try to
+ * get it as specified. If that fails, try it as a number.
+ */
+ if ((pw = getpwnam(u)))
+ return(pw);
+ id = strtol(u, &ep, 10);
+ if (*u && !*ep && (pw = getpwuid(id)))
+ return(pw);
+ errx(1, "%s: no such user", u);
+ /* NOTREACHED */
+}
+
+static void
+pline(struct passwd *pw)
+{
+
+ if (!pw) {
+ if ((pw = getpwuid(getuid())) == NULL)
+ err(1, "getpwuid");
+ }
+
+ (void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
+ pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
+ (long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
+ pw->pw_dir, pw->pw_shell);
+}
+
+
+static void
+usage(void)
+{
+
+ if (isgroups)
+ (void)fprintf(stderr, "usage: groups [user]\n");
+ else if (iswhoami)
+ (void)fprintf(stderr, "usage: whoami\n");
+ else
+ (void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+ "usage: id [user]",
+#ifdef USE_BSM_AUDIT
+ " id -A\n",
+#else
+ "",
+#endif
+ " id -G [-n] [user]",
+ " id -M",
+ " id -P [user]",
+ " id -c",
+ " id -g [-nr] [user]",
+ " id -p [user]",
+ " id -u [-nr] [user]");
+ exit(1);
+}
diff --git a/usr.bin/id/whoami.1 b/usr.bin/id/whoami.1
new file mode 100644
index 000000000000..c3aba4b3bdcb
--- /dev/null
+++ b/usr.bin/id/whoami.1
@@ -0,0 +1,53 @@
+.\" Copyright (c) 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.
+.\"
+.Dd June 6, 1993
+.Dt WHOAMI 1
+.Os
+.Sh NAME
+.Nm whoami
+.Nd display effective user id
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility has been obsoleted by the
+.Xr id 1
+utility, and is equivalent to
+.Dq Nm id Fl un .
+The command
+.Dq Nm id Fl p
+is suggested for normal interactive use.
+.Pp
+The
+.Nm
+utility displays your effective user ID as a name.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr id 1
diff --git a/usr.bin/ident/Makefile b/usr.bin/ident/Makefile
new file mode 100644
index 000000000000..8695ae3e6003
--- /dev/null
+++ b/usr.bin/ident/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= ident
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ident/Makefile.depend b/usr.bin/ident/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/ident/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ident/ident.1 b/usr.bin/ident/ident.1
new file mode 100644
index 000000000000..c17279720517
--- /dev/null
+++ b/usr.bin/ident/ident.1
@@ -0,0 +1,66 @@
+.\" Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 July 25, 2015
+.Dt IDENT 1
+.Os
+.Sh NAME
+.Nm ident
+.Nd identify RCS keyword string in files
+.Sh SYNOPSIS
+.Nm
+.Op Fl q
+.Op Fl V
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility searches for all instances of the pattern
+.Sq $keyword: text$
+in
+.Ar files .
+.Pp
+If no arguments are passed, then
+.Nm
+parses the standard input.
+.Pp
+.Em keyword
+must only be composed of alphanumeric values in the C locale, followed by
+.Sq \&:
+and a space.
+.Pp
+These options are supported:
+.Bl -tag -width "XXX"
+.It Fl q
+Quiet mode: suppress warnings if no pattern found.
+.It Fl V
+Do nothing, added for compatibility with GNU ident.
+.El
+.Sh EXIT STATUS
+.Ex -std ident
+.Sh AUTHORS
+This version of the
+.Nm
+utility was written by
+.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org .
diff --git a/usr.bin/ident/ident.c b/usr.bin/ident/ident.c
new file mode 100644
index 000000000000..96190723dbf7
--- /dev/null
+++ b/usr.bin/ident/ident.c
@@ -0,0 +1,286 @@
+/*-
+ * Copyright (c) 2015-2021 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2015 Xin LI <delphij@FreeBSD.org>
+ *
+ * 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
+ * in this position and unchanged.
+ * 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 AUTHOR(S) ``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(S) 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/capsicum.h>
+#include <sys/types.h>
+#include <sys/sbuf.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <xlocale.h>
+
+typedef enum {
+ /* state condition to transit to next state */
+ INIT, /* '$' */
+ DELIM_SEEN, /* letter */
+ KEYWORD, /* punctuation mark */
+ PUNC_SEEN, /* ':' -> _SVN; space -> TEXT */
+ PUNC_SEEN_SVN, /* space */
+ TEXT
+} analyzer_states;
+
+static int
+scan(FILE *fp, const char *name, bool quiet)
+{
+ int c;
+ bool hasid = false;
+ bool subversion = false;
+ analyzer_states state = INIT;
+ FILE* buffp;
+ char *buf;
+ size_t sz;
+ locale_t l;
+
+ l = newlocale(LC_ALL_MASK, "C", NULL);
+ sz = 0;
+ buf = NULL;
+ buffp = open_memstream(&buf, &sz);
+ if (buffp == NULL)
+ err(EXIT_FAILURE, "open_memstream()");
+
+ if (name != NULL)
+ printf("%s:\n", name);
+
+ while ((c = fgetc(fp)) != EOF) {
+ switch (state) {
+ case INIT:
+ if (c == '$') {
+ /* Transit to DELIM_SEEN if we see $ */
+ state = DELIM_SEEN;
+ } else {
+ /* Otherwise, stay in INIT state */
+ continue;
+ }
+ break;
+ case DELIM_SEEN:
+ if (isalpha_l(c, l)) {
+ /* Transit to KEYWORD if we see letter */
+ if (buf != NULL)
+ memset(buf, 0, sz);
+ rewind(buffp);
+ fputc('$', buffp);
+ fputc(c, buffp);
+ state = KEYWORD;
+
+ continue;
+ } else if (c == '$') {
+ /* Or, stay in DELIM_SEEN if more $ */
+ continue;
+ } else {
+ /* Otherwise, transit back to INIT */
+ state = INIT;
+ }
+ break;
+ case KEYWORD:
+ fputc(c, buffp);
+
+ if (isalpha_l(c, l)) {
+ /*
+ * Stay in KEYWORD if additional letter is seen
+ */
+ continue;
+ } else if (c == ':') {
+ /*
+ * See ':' for the first time, transit to
+ * PUNC_SEEN.
+ */
+ state = PUNC_SEEN;
+ subversion = false;
+ } else if (c == '$') {
+ /*
+ * Incomplete ident. Go back to DELIM_SEEN
+ * state because we see a '$' which could be
+ * the beginning of a keyword.
+ */
+ state = DELIM_SEEN;
+ } else {
+ /*
+ * Go back to INIT state otherwise.
+ */
+ state = INIT;
+ }
+ break;
+ case PUNC_SEEN:
+ case PUNC_SEEN_SVN:
+ fputc(c, buffp);
+
+ switch (c) {
+ case ':':
+ /*
+ * If we see '::' (seen : in PUNC_SEEN),
+ * activate subversion treatment and transit
+ * to PUNC_SEEN_SVN state.
+ *
+ * If more than two :'s were seen, the ident
+ * is invalid and we would therefore go back
+ * to INIT state.
+ */
+ if (state == PUNC_SEEN) {
+ state = PUNC_SEEN_SVN;
+ subversion = true;
+ } else {
+ state = INIT;
+ }
+ break;
+ case ' ':
+ /*
+ * A space after ':' or '::' indicates we are at the
+ * last component of potential ident.
+ */
+ state = TEXT;
+ break;
+ default:
+ /* All other characters are invalid */
+ state = INIT;
+ break;
+ }
+ break;
+ case TEXT:
+ fputc(c, buffp);
+
+ if (iscntrl_l(c, l)) {
+ /* Control characters are not allowed in this state */
+ state = INIT;
+ } else if (c == '$') {
+ fflush(buffp);
+ /*
+ * valid ident should end with a space.
+ *
+ * subversion extension uses '#' to indicate that
+ * the keyword expansion have exceeded the fixed
+ * width, so it is also permitted if we are in
+ * subversion mode. No length check is enforced
+ * because GNU RCS ident(1) does not do it either.
+ */
+ c = buf[strlen(buf) -2 ];
+ if (c == ' ' || (subversion && c == '#')) {
+ printf(" %s\n", buf);
+ hasid = true;
+ }
+ state = INIT;
+ }
+ /* Other characters: stay in the state */
+ break;
+ }
+ }
+ fclose(buffp);
+ free(buf);
+ freelocale(l);
+
+ if (!hasid) {
+ if (!quiet)
+ fprintf(stderr, "%s warning: no id keywords in %s\n",
+ getprogname(), name ? name : "standard input");
+
+ return (EXIT_FAILURE);
+ }
+
+ return (EXIT_SUCCESS);
+}
+
+int
+main(int argc, char **argv)
+{
+ bool quiet = false;
+ int ch, i, *fds, fd;
+ int ret = EXIT_SUCCESS;
+ size_t nfds;
+ FILE *fp;
+
+ while ((ch = getopt(argc, argv, "qV")) != -1) {
+ switch (ch) {
+ case 'q':
+ quiet = true;
+ break;
+ case 'V':
+ /* Do nothing, compat with GNU rcs's ident */
+ return (EXIT_SUCCESS);
+ default:
+ errx(EXIT_FAILURE, "usage: %s [-q] [-V] [file...]",
+ getprogname());
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (caph_limit_stdio() < 0)
+ err(EXIT_FAILURE, "unable to limit stdio");
+
+ if (argc == 0) {
+ nfds = 1;
+ fds = malloc(sizeof(*fds));
+ if (fds == NULL)
+ err(EXIT_FAILURE, "unable to allocate fds array");
+ fds[0] = STDIN_FILENO;
+ } else {
+ nfds = argc;
+ fds = malloc(sizeof(*fds) * nfds);
+ if (fds == NULL)
+ err(EXIT_FAILURE, "unable to allocate fds array");
+
+ for (i = 0; i < argc; i++) {
+ fds[i] = fd = open(argv[i], O_RDONLY);
+ if (fd < 0) {
+ warn("%s", argv[i]);
+ ret = EXIT_FAILURE;
+ continue;
+ }
+ if (caph_limit_stream(fd, CAPH_READ) < 0)
+ err(EXIT_FAILURE,
+ "unable to limit fcntls/rights for %s",
+ argv[i]);
+ }
+ }
+
+ /* Enter Capsicum sandbox. */
+ if (caph_enter() < 0)
+ err(EXIT_FAILURE, "unable to enter capability mode");
+
+ for (i = 0; i < (int)nfds; i++) {
+ if (fds[i] < 0)
+ continue;
+
+ fp = fdopen(fds[i], "r");
+ if (fp == NULL) {
+ warn("%s", argv[i]);
+ ret = EXIT_FAILURE;
+ continue;
+ }
+ if (scan(fp, argc == 0 ? NULL : argv[i], quiet) != EXIT_SUCCESS)
+ ret = EXIT_FAILURE;
+ fclose(fp);
+ }
+
+ return (ret);
+}
diff --git a/usr.bin/ident/tests/Makefile b/usr.bin/ident/tests/Makefile
new file mode 100644
index 000000000000..d7b7256f07c0
--- /dev/null
+++ b/usr.bin/ident/tests/Makefile
@@ -0,0 +1,9 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= ident_test
+${PACKAGE}FILES+= \
+ test.in \
+ test.out \
+ testnoid
+
+.include <bsd.test.mk>
diff --git a/usr.bin/ident/tests/Makefile.depend b/usr.bin/ident/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/ident/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ident/tests/ident_test.sh b/usr.bin/ident/tests/ident_test.sh
new file mode 100755
index 000000000000..5422a9708d65
--- /dev/null
+++ b/usr.bin/ident/tests/ident_test.sh
@@ -0,0 +1,15 @@
+
+atf_test_case ident
+ident_body() {
+ atf_check -o file:$(atf_get_srcdir)/test.out \
+ ident < $(atf_get_srcdir)/test.in
+ atf_check -o match:'Foo.*' -s exit:1 \
+ -e inline:"ident warning: no id keywords in $(atf_get_srcdir)/testnoid\n" \
+ ident $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid
+ atf_check -o match:'Foo.*' -s exit:1 \
+ ident -q $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid
+}
+atf_init_test_cases()
+{
+ atf_add_test_case ident
+}
diff --git a/usr.bin/ident/tests/test.in b/usr.bin/ident/tests/test.in
new file mode 100644
index 000000000000..634943833ce5
--- /dev/null
+++ b/usr.bin/ident/tests/test.in
@@ -0,0 +1,15 @@
+# tranditional
+ $Foo: bar $ (OK traditional)
+ $$Foo: bar $
+ $$Fo$o: bar $
+ $Fo$o: bar $
+ $ Foo : bar $ (WRONG -- NON ALPHANUM BEFORE :)
+ $ Foo : bar $ (WRONG -- NON ALPHANUM BEFORE :)
+ $Foo: bar $ (WRONG -- NO SPACE AFTER :)
+ $Foo:bar $ (WRONG -- NO SPACE AFTER :)
+ $Foo: bar$ (WRONG -- NO SPACE BEFORE $))
+# Subversion like
+ $Bar:: baz$ (WRONG -- NO SPACE BEFORE $)
+ $Bar:: baz $ (OK -- SPACE BEFORE $)
+ $Qux:: frobby zow#$ (OK -- HASH BEFORE $)' '
+
diff --git a/usr.bin/ident/tests/test.out b/usr.bin/ident/tests/test.out
new file mode 100644
index 000000000000..36cccc9b2098
--- /dev/null
+++ b/usr.bin/ident/tests/test.out
@@ -0,0 +1,6 @@
+ $Foo: bar $
+ $Foo: bar $
+ $o: bar $
+ $o: bar $
+ $Bar:: baz $
+ $Qux:: frobby zow#$
diff --git a/usr.bin/ident/tests/testnoid b/usr.bin/ident/tests/testnoid
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/ident/tests/testnoid
diff --git a/usr.bin/indent/Makefile b/usr.bin/indent/Makefile
new file mode 100644
index 000000000000..3f7ee955a228
--- /dev/null
+++ b/usr.bin/indent/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PROG= indent
+SRCS= indent.c io.c lexi.c parse.c pr_comment.c args.c
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/indent/Makefile.depend b/usr.bin/indent/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/indent/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/indent/README b/usr.bin/indent/README
new file mode 100644
index 000000000000..246f92c93282
--- /dev/null
+++ b/usr.bin/indent/README
@@ -0,0 +1,98 @@
+
+This is the C indenter, it originally came from the University of Illinois
+via some distribution tape for PDP-11 Unix. It has subsequently been
+hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs
+to be completely redone, but it is probably the nicest C pretty printer
+around.
+
+Further additions to provide "Kernel Normal Form" were contributed
+by the folks at Sun Microsystems.
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988
+> Date: Tue, 8 Mar 88 18:36:25 EST
+> From: yunexus!oz@uunet.UU.NET (Ozan Yigit)
+> To: bostic@okeeffe.berkeley.edu
+> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET
+> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST
+> Subject: Re: Indent...
+
+Thank you for your response about indent. I was wrong in my original
+observation (or mis-observation :-). UCB did keep the Illinois
+copyright intact.
+
+The issue still is whether we can distribute indent, and if we can, which
+version. David Willcox (the author) states that:
+
+| Several people have asked me on what basis I claim that indent is in
+| the public domain. I knew I would be sorry I made that posting.
+|
+| Some history. Way back in 1976, the project I worked on at the
+| University of Illinois Center for Advanced Computation had a huge
+| battle about how to format C code. After about a week of fighting, I
+| got disgusted and wrote a program, which I called indent, to reformat C
+| code. It had a bunch of different options that would let you format
+| the output the way you liked. In particular, all of the different
+| formats being championed were supported.
+|
+| It was my first big C program. It was ugly. It wasn't designed, it
+| just sort of grew. But it pretty much worked, and it stopped most of
+| the fighting.
+|
+| As a matter of form, I included a University of Illinois Copyright
+| notice. However, my understanding was that, since the work was done
+| on an ARPA contract, it was in the public domain.
+|
+| Time passed. Some years later, indent showed up on one of the early
+| emacs distributions.
+|
+| Later still, someone from UC Berkeley called the UofI and asked if
+| indent was in the public domain. They wanted to include it in their
+| UNIX distributions, along with the emacs stuff. I was no longer at the
+| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't
+| care if they used it, and since then it has been on the BSD distributions.
+|
+| Somewhere along the way, several other unnamed people have had their
+| hands in it. It was converted to understand version 7 C. (The
+| original was version 6.) It was converted from its original filter
+| interface to its current "blow away the user's file" interface.
+| The $HOME/.indent.pro file parsing was added. Some more formatting
+| options were added.
+|
+| The source I have right now has two copyright notices. One is the
+| original from the UofI. One is from Berkeley.
+|
+| I am not a lawyer, and I certainly do not understand copyright law. As
+| far as I am concerned, the bulk of this program, everything covered by
+| the UofI copyright, is in the public domain, and worth every penny.
+| Berkeley's copyright probably should only cover their changes, and I
+| don't know their feelings about sending it out.
+
+In any case, there appears to be none at UofI to clarify/and change
+that copyright, but I am confident (based on the statements of its
+author) that the code, as it stands with its copyright, is
+distributable, and will not cause any legal problems.
+
+Hence, the issue reduces to *which* one to distribute through
+comp.sources.unix. I would suggest that with the permission of you
+folks (given that you have parts copyrighted), we distribute the 4.3
+version of indent, which appears to be the most up-to-date version. I
+happen to have just about every known version of indent, including the
+very original submission from the author to a unix tape, later the
+G-Emacs version, any 4.n version, sun version and the Unipress
+version. I still think we should not have to "go-back-in-time" and
+re-do all the work you people have done.
+
+I hope to hear from you as to what you think about this. You may of
+course send 4.3 version to the moderator directly, or you can let me
+know of your permission, and I will send the sources, or you can let
+me know that 4.3 version is off-limits, in which case we would probably
+have to revert to an older version. One way or another, I hope to get
+a version of indent to comp.sources.unix.
+
+regards.. oz
+
+cc: ccvaxa!willcox
+ sun.com!jar
+ uunet!rsalz
+
diff --git a/usr.bin/indent/args.c b/usr.bin/indent/args.c
new file mode 100644
index 000000000000..fe03557169c2
--- /dev/null
+++ b/usr.bin/indent/args.c
@@ -0,0 +1,348 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+/*
+ * Argument scanning and profile reading code. Default parameters are set
+ * here as well.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "indent_globs.h"
+#include "indent.h"
+
+#define INDENT_VERSION "2.0"
+
+/* profile types */
+#define PRO_SPECIAL 1 /* special case */
+#define PRO_BOOL 2 /* boolean */
+#define PRO_INT 3 /* integer */
+
+/* profile specials for booleans */
+#define ON 1 /* turn it on */
+#define OFF 0 /* turn it off */
+
+/* profile specials for specials */
+#define IGN 1 /* ignore it */
+#define CLI 2 /* case label indent (float) */
+#define STDIN 3 /* use stdin */
+#define KEY 4 /* type (keyword) */
+
+static void scan_profile(FILE *);
+
+#define KEY_FILE 5 /* only used for args */
+#define VERSION 6 /* only used for args */
+
+const char *option_source = "?";
+
+void add_typedefs_from_file(const char *str);
+
+/*
+ * N.B.: because of the way the table here is scanned, options whose names are
+ * substrings of other options must occur later; that is, with -lp vs -l, -lp
+ * must be first. Also, while (most) booleans occur more than once, the last
+ * default value is the one actually assigned.
+ */
+struct pro {
+ const char *p_name; /* name, e.g. -bl, -cli */
+ int p_type; /* type (int, bool, special) */
+ int p_default; /* the default value (if int) */
+ int p_special; /* depends on type */
+ int *p_obj; /* the associated variable */
+} pro[] = {
+
+ {"T", PRO_SPECIAL, 0, KEY, 0},
+ {"U", PRO_SPECIAL, 0, KEY_FILE, 0},
+ {"-version", PRO_SPECIAL, 0, VERSION, 0},
+ {"P", PRO_SPECIAL, 0, IGN, 0},
+ {"bacc", PRO_BOOL, false, ON, &opt.blanklines_around_conditional_compilation},
+ {"badp", PRO_BOOL, false, ON, &opt.blanklines_after_declarations_at_proctop},
+ {"bad", PRO_BOOL, false, ON, &opt.blanklines_after_declarations},
+ {"bap", PRO_BOOL, false, ON, &opt.blanklines_after_procs},
+ {"bbb", PRO_BOOL, false, ON, &opt.blanklines_before_blockcomments},
+ {"bc", PRO_BOOL, true, OFF, &opt.leave_comma},
+ {"bl", PRO_BOOL, true, OFF, &opt.btype_2},
+ {"br", PRO_BOOL, true, ON, &opt.btype_2},
+ {"bs", PRO_BOOL, false, ON, &opt.Bill_Shannon},
+ {"cdb", PRO_BOOL, true, ON, &opt.comment_delimiter_on_blankline},
+ {"cd", PRO_INT, 0, 0, &opt.decl_com_ind},
+ {"ce", PRO_BOOL, true, ON, &opt.cuddle_else},
+ {"ci", PRO_INT, 0, 0, &opt.continuation_indent},
+ {"cli", PRO_SPECIAL, 0, CLI, 0},
+ {"cs", PRO_BOOL, false, ON, &opt.space_after_cast},
+ {"c", PRO_INT, 33, 0, &opt.com_ind},
+ {"di", PRO_INT, 16, 0, &opt.decl_indent},
+ {"dj", PRO_BOOL, false, ON, &opt.ljust_decl},
+ {"d", PRO_INT, 0, 0, &opt.unindent_displace},
+ {"eei", PRO_BOOL, false, ON, &opt.extra_expression_indent},
+ {"ei", PRO_BOOL, true, ON, &opt.else_if},
+ {"fbs", PRO_BOOL, true, ON, &opt.function_brace_split},
+ {"fc1", PRO_BOOL, true, ON, &opt.format_col1_comments},
+ {"fcb", PRO_BOOL, true, ON, &opt.format_block_comments},
+ {"ip", PRO_BOOL, true, ON, &opt.indent_parameters},
+ {"i", PRO_INT, 8, 0, &opt.ind_size},
+ {"lc", PRO_INT, 0, 0, &opt.block_comment_max_col},
+ {"ldi", PRO_INT, -1, 0, &opt.local_decl_indent},
+ {"lpl", PRO_BOOL, false, ON, &opt.lineup_to_parens_always},
+ {"lp", PRO_BOOL, true, ON, &opt.lineup_to_parens},
+ {"l", PRO_INT, 78, 0, &opt.max_col},
+ {"nbacc", PRO_BOOL, false, OFF, &opt.blanklines_around_conditional_compilation},
+ {"nbadp", PRO_BOOL, false, OFF, &opt.blanklines_after_declarations_at_proctop},
+ {"nbad", PRO_BOOL, false, OFF, &opt.blanklines_after_declarations},
+ {"nbap", PRO_BOOL, false, OFF, &opt.blanklines_after_procs},
+ {"nbbb", PRO_BOOL, false, OFF, &opt.blanklines_before_blockcomments},
+ {"nbc", PRO_BOOL, true, ON, &opt.leave_comma},
+ {"nbs", PRO_BOOL, false, OFF, &opt.Bill_Shannon},
+ {"ncdb", PRO_BOOL, true, OFF, &opt.comment_delimiter_on_blankline},
+ {"nce", PRO_BOOL, true, OFF, &opt.cuddle_else},
+ {"ncs", PRO_BOOL, false, OFF, &opt.space_after_cast},
+ {"ndj", PRO_BOOL, false, OFF, &opt.ljust_decl},
+ {"neei", PRO_BOOL, false, OFF, &opt.extra_expression_indent},
+ {"nei", PRO_BOOL, true, OFF, &opt.else_if},
+ {"nfbs", PRO_BOOL, true, OFF, &opt.function_brace_split},
+ {"nfc1", PRO_BOOL, true, OFF, &opt.format_col1_comments},
+ {"nfcb", PRO_BOOL, true, OFF, &opt.format_block_comments},
+ {"nip", PRO_BOOL, true, OFF, &opt.indent_parameters},
+ {"nlpl", PRO_BOOL, false, OFF, &opt.lineup_to_parens_always},
+ {"nlp", PRO_BOOL, true, OFF, &opt.lineup_to_parens},
+ {"npcs", PRO_BOOL, false, OFF, &opt.proc_calls_space},
+ {"npro", PRO_SPECIAL, 0, IGN, 0},
+ {"npsl", PRO_BOOL, true, OFF, &opt.procnames_start_line},
+ {"nps", PRO_BOOL, false, OFF, &opt.pointer_as_binop},
+ {"nsc", PRO_BOOL, true, OFF, &opt.star_comment_cont},
+ {"nsob", PRO_BOOL, false, OFF, &opt.swallow_optional_blanklines},
+ {"nut", PRO_BOOL, true, OFF, &opt.use_tabs},
+ {"nv", PRO_BOOL, false, OFF, &opt.verbose},
+ {"pcs", PRO_BOOL, false, ON, &opt.proc_calls_space},
+ {"psl", PRO_BOOL, true, ON, &opt.procnames_start_line},
+ {"ps", PRO_BOOL, false, ON, &opt.pointer_as_binop},
+ {"sc", PRO_BOOL, true, ON, &opt.star_comment_cont},
+ {"sob", PRO_BOOL, false, ON, &opt.swallow_optional_blanklines},
+ {"st", PRO_SPECIAL, 0, STDIN, 0},
+ {"ta", PRO_BOOL, false, ON, &opt.auto_typedefs},
+ {"ts", PRO_INT, 8, 0, &opt.tabsize},
+ {"ut", PRO_BOOL, true, ON, &opt.use_tabs},
+ {"v", PRO_BOOL, false, ON, &opt.verbose},
+ /* whew! */
+ {0, 0, 0, 0, 0}
+};
+
+/*
+ * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
+ * given in these files.
+ */
+void
+set_profile(const char *profile_name)
+{
+ FILE *f;
+ char fname[PATH_MAX];
+ static char prof[] = ".indent.pro";
+
+ if (profile_name == NULL)
+ snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
+ else
+ snprintf(fname, sizeof(fname), "%s", profile_name + 2);
+ if ((f = fopen(option_source = fname, "r")) != NULL) {
+ scan_profile(f);
+ (void) fclose(f);
+ }
+ if ((f = fopen(option_source = prof, "r")) != NULL) {
+ scan_profile(f);
+ (void) fclose(f);
+ }
+ option_source = "Command line";
+}
+
+static void
+scan_profile(FILE *f)
+{
+ int comment, i;
+ char *p;
+ char buf[BUFSIZ];
+
+ while (1) {
+ p = buf;
+ comment = 0;
+ while ((i = getc(f)) != EOF) {
+ if (i == '*' && !comment && p > buf && p[-1] == '/') {
+ comment = p - buf;
+ *p++ = i;
+ } else if (i == '/' && comment && p > buf && p[-1] == '*') {
+ p = buf + comment - 1;
+ comment = 0;
+ } else if (isspace((unsigned char)i)) {
+ if (p > buf && !comment)
+ break;
+ } else {
+ *p++ = i;
+ }
+ }
+ if (p != buf) {
+ *p++ = 0;
+ if (opt.verbose)
+ printf("profile: %s\n", buf);
+ set_option(buf);
+ }
+ else if (i == EOF)
+ return;
+ }
+}
+
+static const char *
+eqin(const char *s1, const char *s2)
+{
+ while (*s1) {
+ if (*s1++ != *s2++)
+ return (NULL);
+ }
+ return (s2);
+}
+
+/*
+ * Set the defaults.
+ */
+void
+set_defaults(void)
+{
+ struct pro *p;
+
+ /*
+ * Because ps.case_indent is a float, we can't initialize it from the
+ * table:
+ */
+ opt.case_indent = 0.0; /* -cli0.0 */
+ for (p = pro; p->p_name; p++)
+ if (p->p_type != PRO_SPECIAL)
+ *p->p_obj = p->p_default;
+}
+
+void
+set_option(char *arg)
+{
+ struct pro *p;
+ const char *param_start;
+
+ arg++; /* ignore leading "-" */
+ for (p = pro; p->p_name; p++)
+ if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL)
+ goto found;
+ errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
+found:
+ switch (p->p_type) {
+
+ case PRO_SPECIAL:
+ switch (p->p_special) {
+
+ case IGN:
+ break;
+
+ case CLI:
+ if (*param_start == 0)
+ goto need_param;
+ opt.case_indent = atof(param_start);
+ break;
+
+ case STDIN:
+ if (input == NULL)
+ input = stdin;
+ if (output == NULL)
+ output = stdout;
+ break;
+
+ case KEY:
+ if (*param_start == 0)
+ goto need_param;
+ add_typename(param_start);
+ break;
+
+ case KEY_FILE:
+ if (*param_start == 0)
+ goto need_param;
+ add_typedefs_from_file(param_start);
+ break;
+
+ case VERSION:
+ printf("FreeBSD indent %s\n", INDENT_VERSION);
+ exit(0);
+
+ default:
+ errx(1, "set_option: internal error: p_special %d", p->p_special);
+ }
+ break;
+
+ case PRO_BOOL:
+ if (p->p_special == OFF)
+ *p->p_obj = false;
+ else
+ *p->p_obj = true;
+ break;
+
+ case PRO_INT:
+ if (!isdigit((unsigned char)*param_start)) {
+ need_param:
+ errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name);
+ }
+ *p->p_obj = atoi(param_start);
+ break;
+
+ default:
+ errx(1, "set_option: internal error: p_type %d", p->p_type);
+ }
+}
+
+void
+add_typedefs_from_file(const char *str)
+{
+ FILE *file;
+ char line[BUFSIZ];
+
+ if ((file = fopen(str, "r")) == NULL) {
+ fprintf(stderr, "indent: cannot open file %s\n", str);
+ exit(1);
+ }
+ while ((fgets(line, BUFSIZ, file)) != NULL) {
+ /* Remove trailing whitespace */
+ line[strcspn(line, " \t\n\r")] = '\0';
+ add_typename(line);
+ }
+ fclose(file);
+}
diff --git a/usr.bin/indent/indent.1 b/usr.bin/indent/indent.1
new file mode 100644
index 000000000000..e34a244a6821
--- /dev/null
+++ b/usr.bin/indent/indent.1
@@ -0,0 +1,613 @@
+.\" Copyright (c) 1980, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 1976 Board of Trustees of the University of Illinois.
+.\" 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.
+.\"
+.Dd June 28, 2023
+.Dt INDENT 1
+.Os
+.Sh NAME
+.Nm indent
+.Nd indent and format C program source
+.Sh SYNOPSIS
+.Nm
+.Op Ar input-file Op Ar output-file
+.Op Fl bacc | Fl nbacc
+.Op Fl bad | Fl nbad
+.Op Fl badp | Fl nbadp
+.Op Fl bap | Fl nbap
+.Op Fl bbb | Fl nbbb
+.Op Fl \&bc | Fl nbc
+.Op Fl \&bl | Fl \&br
+.Op Fl bs | Fl nbs
+.Op Fl c Ns Ar n
+.Op Fl \&cd Ns Ar n
+.Bk -words
+.Op Fl cdb | Fl ncdb
+.Ek
+.Op Fl \&ce | Fl nce
+.Op Fl \&ci Ns Ar n
+.Op Fl cli Ns Ar n
+.Op Fl cs | Fl ncs
+.Op Fl d Ns Ar n
+.Op Fl \&di Ns Ar n
+.Op Fl dj | Fl ndj
+.Bk -words
+.Op Fl ei | Fl nei
+.Op Fl eei | Fl neei
+.Ek
+.Bk -words
+.Op Fl fbs | Fl nfbs
+.Op Fl fc1 | Fl nfc1
+.Op Fl fcb | Fl nfcb
+.Ek
+.Op Fl i Ns Ar n
+.Op Fl \&ip | Fl nip
+.Op Fl l Ns Ar n
+.Op Fl \&lc Ns Ar n
+.Op Fl \&ldi Ns Ar n
+.Op Fl \&lp | Fl nlp
+.Op Fl \&lpl | Fl nlpl
+.Op Fl npro
+.Op Fl P Ns Ar file
+.Op Fl pcs | Fl npcs
+.Op Fl ps | Fl nps
+.Op Fl psl | Fl npsl
+.Op Fl \&sc | Fl nsc
+.Bk -words
+.Op Fl sob | Fl nsob
+.Ek
+.Op Fl \&st
+.Op Fl \&ta
+.Op Fl T Ns Ar typename
+.Op Fl ts Ns Ar n
+.Op Fl U Ns Ar file
+.Op Fl ut | Fl nut
+.Op Fl v | Fl \&nv
+.Op Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+utility is a
+.Em C
+program formatter.
+It reformats the
+.Em C
+program in the
+.Ar input-file
+according to the switches.
+The switches which can be
+specified are described below.
+They may appear before or after the file
+names.
+.Pp
+.Sy NOTE :
+If you only specify an
+.Ar input-file ,
+the formatting is
+done `in-place', that is, the formatted file is written back into
+.Ar input-file
+and a backup copy of
+.Ar input-file
+is written in the current directory.
+If
+.Ar input-file
+is named
+.Sq Pa /blah/blah/file ,
+the backup file is named
+.Sq Pa file.BAK
+by default.
+The extension used for the backup file may be overridden using the
+.Ev SIMPLE_BACKUP_SUFFIX
+environment variable.
+.Pp
+If
+.Ar output-file
+is specified,
+.Nm
+checks to make sure that it is different from
+.Ar input-file .
+.Pp
+The options listed below control the formatting style imposed by
+.Nm .
+.Bl -tag -width Op
+.It Fl bacc , nbacc
+If
+.Fl bacc
+is specified, a blank line is forced around every conditional
+compilation block.
+For example, in front of every #ifdef and after every #endif.
+Other blank lines surrounding such blocks will be swallowed.
+Default:
+.Fl nbacc .
+.It Fl bad , nbad
+If
+.Fl bad
+is specified, a blank line is forced after every block of
+declarations.
+Default:
+.Fl nbad .
+.It Fl badp , nbadp
+This is vaguely similar to
+.Fl bad
+except that it only applies to the first set of declarations
+in a procedure (just after the first `{') and it causes a blank
+line to be generated even if there are no declarations.
+The default is
+.Fl nbadp .
+.It Fl bap , nbap
+If
+.Fl bap
+is specified, a blank line is forced after every procedure body.
+Default:
+.Fl nbap .
+.It Fl bbb , nbbb
+If
+.Fl bbb
+is specified, a blank line is forced before every block comment.
+Default:
+.Fl nbbb .
+.It Fl \&bc , nbc
+If
+.Fl \&bc
+is specified, then a newline is forced after each comma in a declaration.
+.Fl nbc
+turns off this option.
+Default:
+.Fl \&nbc .
+.It Fl \&bl , \&br
+Specifying
+.Fl \&bl
+lines up compound statements like this:
+.Bd -literal -offset indent
+if (...)
+{
+ code
+}
+.Ed
+.Pp
+Specifying
+.Fl \&br
+(the default) makes them look like this:
+.Bd -literal -offset indent
+if (...) {
+ code
+}
+.Ed
+.It Fl bs , nbs
+Whether a blank should always be inserted after sizeof.
+The default is
+.Fl nbs .
+.It Fl c Ns Ar n
+The column in which comments on code start.
+The default is 33.
+.It Fl cd Ns Ar n
+The column in which comments on declarations start.
+The default
+is for these comments to start in the same column as those on code.
+.It Fl cdb , ncdb
+Enables (disables) the placement of comment delimiters on blank lines.
+With
+this option enabled, comments look like this:
+.Bd -literal -offset indent
+ /*
+ * this is a comment
+ */
+.Ed
+.Pp
+Rather than like this:
+.Bd -literal -offset indent
+ /* this is a comment */
+.Ed
+.Pp
+This only affects block comments, not comments to the right of
+code.
+The default is
+.Fl cdb .
+.It Fl ce , nce
+Enables (disables) forcing of `else's to cuddle up to the immediately preceding
+`}'.
+The default is
+.Fl \&ce .
+.It Fl \&ci Ns Ar n
+Sets the continuation indent to be
+.Ar n .
+Continuation
+lines will be indented that far from the beginning of the first line of the
+statement.
+Parenthesized expressions have extra indentation added to
+indicate the nesting, unless
+.Fl \&lp
+is in effect
+or the continuation indent is exactly half of the main indent.
+.Fl \&ci
+defaults to the same value as
+.Fl i .
+.It Fl cli Ns Ar n
+Causes case labels to be indented
+.Ar n
+tab stops to the right of the containing
+.Ic switch
+statement.
+.Fl cli0.5
+causes case labels to be indented half a tab stop.
+The
+default is
+.Fl cli0 .
+.It Fl cs , ncs
+Control whether parenthesized type names in casts are followed by a space or
+not.
+The default is
+.Fl ncs .
+.It Fl d Ns Ar n
+Controls the placement of comments which are not to the
+right of code.
+For example,
+.Fl \&d\&1
+means that such comments are placed one indentation level to the
+left of code.
+Specifying the default
+.Fl \&d\&0
+lines up these comments with the code.
+See the section on comment
+indentation below.
+.It Fl \&di Ns Ar n
+Specifies the indentation, in character positions,
+of global variable names and all struct/union member names
+relative to the beginning of their type declaration.
+The default is
+.Fl di16 .
+.It Fl dj , ndj
+.Fl \&dj
+left justifies declarations.
+.Fl ndj
+indents declarations the same as code.
+The default is
+.Fl ndj .
+.It Fl \&ei , nei
+Enables (disables) special
+.Ic else-if
+processing.
+If it is enabled, an
+.Ic if
+following an
+.Ic else
+will have the same indentation as the preceding
+.Ic \&if
+statement.
+The default is
+.Fl ei .
+.It Fl eei , neei
+Enables (disables) extra indentation on continuation lines of
+the expression part of
+.Ic if
+and
+.Ic while
+statements.
+These continuation lines will be indented one extra level.
+The default is
+.Fl neei .
+.It Fl fbs , nfbs
+Enables (disables) splitting the function declaration and opening brace
+across two lines.
+The default is
+.Fl fbs .
+.It Fl fc1 , nfc1
+Enables (disables) the formatting of comments that start in column 1.
+Often, comments whose leading `/' is in column 1 have been carefully
+hand formatted by the programmer.
+In such cases,
+.Fl nfc1
+should be
+used.
+The default is
+.Fl fc1 .
+.It Fl fcb , nfcb
+Enables (disables) the formatting of block comments (ones that begin
+with `/*\\n').
+Often, block comments have been not so carefully hand formatted by the
+programmer, but reformatting that would just change the line breaks is not
+wanted.
+In such cases,
+.Fl nfcb
+should be used.
+Block comments are then handled like box comments.
+The default is
+.Fl fcb .
+.It Fl i Ns Ar n
+The number of columns for one indentation level.
+The default is 8.
+.It Fl \&ip , nip
+Enables (disables) the indentation of parameter declarations from the left
+margin.
+The default is
+.Fl \&ip .
+.It Fl l Ns Ar n
+Maximum length of an output line.
+The default is 78.
+.It Fl lc Ns Ar n
+Maximum length of an output line in a block comment.
+The default is 0, which means to limit block comment lines in accordance with
+.Fl l .
+.It Fl \&ldi Ns Ar n
+Specifies the indentation, in character positions,
+of local variable names
+relative to the beginning of their type declaration.
+The default is for local variable names to be indented
+by the same amount as global ones.
+.It Fl \&lp , nlp
+Lines up code surrounded by parentheses in continuation lines.
+With
+.Fl \&lp ,
+if a line
+has a left paren which is not closed on that line, then continuation lines
+will be lined up to start at the character position just after the left
+paren.
+For example, here is how a piece of continued code looks with
+.Fl nlp
+in effect:
+.Bd -literal -offset indent
+p1 = first_procedure(second_procedure(p2, p3),
+\ \ third_procedure(p4, p5));
+.Ed
+.Pp
+With
+.Fl lp
+in effect (the default) the code looks somewhat clearer:
+.Bd -literal -offset indent
+p1\ =\ first_procedure(second_procedure(p2,\ p3),
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5));
+.Ed
+.Pp
+Inserting two more newlines we get:
+.Bd -literal -offset indent
+p1\ =\ first_procedure(second_procedure(p2,
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3),
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,
+\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5));
+.Ed
+.It Fl \&lpl , nlpl
+With
+.Fl \&lpl ,
+code surrounded by parentheses in continuation lines is lined up even if it
+would extend past the right margin.
+With
+.Fl \&nlpl
+(the default), such a line that would extend past the right margin is moved
+left to keep it within the margin, if that does not require placing it to
+the left of the prevailing indentation level.
+These switches have no effect if
+.Fl nlp
+is selected.
+.It Fl npro
+Causes the profile files,
+.Sq Pa ./.indent.pro
+and
+.Sq Pa ~/.indent.pro ,
+to be ignored.
+.It Fl P Ns Ar file
+Read profile from
+.Ar file .
+.It Fl pcs , npcs
+If true
+.Pq Fl pcs
+all procedure calls will have a space inserted between
+the name and the `('.
+The default is
+.Fl npcs .
+.It Fl ps , nps
+If true
+.Pq Fl ps
+the pointer dereference operator (`->') is treated like any other
+binary operator.
+The default is
+.Fl nps .
+.It Fl psl , npsl
+If true
+.Pq Fl psl
+the names of procedures being defined are placed in
+column 1 \- their types, if any, will be left on the previous lines.
+The
+default is
+.Fl psl .
+.It Fl \&sc , nsc
+Enables (disables) the placement of asterisks (`*'s) at the left edge of all
+comments.
+The default is
+.Fl sc .
+.It Fl sob , nsob
+If
+.Fl sob
+is specified, indent will swallow optional blank lines.
+You can use this to
+get rid of blank lines after declarations.
+Default:
+.Fl nsob .
+.It Fl \&st
+Causes
+.Nm
+to take its input from stdin and put its output to stdout.
+.It Fl ta
+Automatically add all identifiers ending in "_t" to the list
+of type keywords.
+.It Fl T Ns Ar typename
+Adds
+.Ar typename
+to the list of type keywords.
+Names accumulate:
+.Fl T
+can be specified more than once.
+You need to specify all the typenames that
+appear in your program that are defined by
+.Ic typedef
+\- nothing will be
+harmed if you miss a few, but the program will not be formatted as nicely as
+it should.
+This sounds like a painful thing to have to do, but it is really
+a symptom of a problem in C:
+.Ic typedef
+causes a syntactic change in the
+language and
+.Nm
+cannot find all
+instances of
+.Ic typedef .
+.It Fl ts Ns Ar n
+Assumed distance between tab stops.
+The default is 8.
+.It Fl U Ns Ar file
+Adds type names from
+.Ar file
+to the list of type keywords.
+.It Fl ut , nut
+Enables (disables) the use of tab characters in the output.
+The default is
+.Fl ut .
+.It Fl v , \&nv
+.Fl v
+turns on `verbose' mode;
+.Fl \&nv
+turns it off.
+When in verbose mode,
+.Nm
+reports when it splits one line of input into two or more lines of output,
+and gives some size statistics at completion.
+The default is
+.Fl \&nv .
+.It Fl -version
+Causes
+.Nm
+to print its version number and exit.
+.El
+.Pp
+You may set up your own `profile' of defaults to
+.Nm
+by creating a file called
+.Pa .indent.pro
+in your login directory and/or the current directory and including
+whatever switches you like.
+A `.indent.pro' in the current directory takes
+precedence over the one in your login directory.
+If
+.Nm
+is run and a profile file exists, then it is read to set up the program's
+defaults.
+Switches on the command line, though, always override profile
+switches.
+The switches should be separated by spaces, tabs or newlines.
+.Pp
+.Ss Comments
+.Sq Em Box
+.Em comments .
+The
+.Nm
+utility
+assumes that any comment with a dash or star immediately after the start of
+comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars.
+Each line of such a comment is left unchanged, except that its indentation
+may be adjusted to account for the change in indentation of the first line
+of the comment.
+.Pp
+.Em Straight text .
+All other comments are treated as straight text.
+The
+.Nm
+utility fits as many words (separated by blanks, tabs, or newlines) on a
+line as possible.
+Blank lines break paragraphs.
+.Ss Comment indentation
+If a comment is on a line with code it is started in the `comment column',
+which is set by the
+.Fl c Ns Ns Ar n
+command line parameter.
+Otherwise, the comment is started at
+.Ar n
+indentation levels less than where code is currently being placed, where
+.Ar n
+is specified by the
+.Fl d Ns Ns Ar n
+command line parameter.
+If the code on a line extends past the comment
+column, the comment starts further to the right, and the right margin may be
+automatically extended in extreme cases.
+.Ss Preprocessor lines
+In general,
+.Nm
+leaves preprocessor lines alone.
+The only
+reformatting that it will do is to straighten up trailing comments.
+It
+leaves embedded comments alone.
+Conditional compilation
+.Pq Ic #ifdef...#endif
+is recognized and
+.Nm
+attempts to correctly
+compensate for the syntactic peculiarities introduced.
+.Ss C syntax
+The
+.Nm
+utility understands a substantial amount about the syntax of C, but it
+has a `forgiving' parser.
+It attempts to cope with the usual sorts of
+incomplete and malformed syntax.
+In particular, the use of macros like:
+.Pp
+.Dl #define forever for(;;)
+.Pp
+is handled properly.
+.Sh ENVIRONMENT
+The
+.Nm
+utility uses the
+.Ev HOME
+environment variable.
+.Sh FILES
+.Bl -tag -width "./.indent.pro" -compact
+.It Pa ./.indent.pro
+profile file
+.It Pa ~/.indent.pro
+profile file
+.El
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+The
+.Nm
+utility has even more switches than
+.Xr ls 1 .
+.Pp
+A common mistake is to try to indent all the
+.Em C
+programs in a directory by typing:
+.Pp
+.Dl indent *.c
+.Pp
+This is probably a bug, not a feature.
diff --git a/usr.bin/indent/indent.c b/usr.bin/indent/indent.c
new file mode 100644
index 000000000000..4739e861fef9
--- /dev/null
+++ b/usr.bin/indent/indent.c
@@ -0,0 +1,1309 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1976 Board of Trustees of the University of Illinois.
+ * Copyright (c) 1980, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "indent_globs.h"
+#include "indent_codes.h"
+#include "indent.h"
+
+/* Globals */
+FILE *input, *output;
+char *labbuf, *s_lab, *e_lab, *l_lab;
+char *codebuf, *s_code, *e_code, *l_code;
+char *combuf, *s_com, *e_com, *l_com;
+char *tokenbuf, *s_token, *e_token, *l_token;
+char *in_buffer, *in_buffer_limit;
+char *buf_ptr, *buf_end;
+
+char sc_buf[sc_size];
+
+char *save_com, *sc_end;
+char *bp_save;
+char *be_save;
+
+struct options opt;
+int line_no;
+
+struct parser_state ps;
+int ifdef_level;
+struct parser_state state_stack[5];
+struct parser_state match_state[5];
+
+
+static void bakcopy(void);
+static void indent_declaration(int, int);
+
+const char *in_name = "Standard Input"; /* will always point to name of input
+ * file */
+const char *out_name = "Standard Output"; /* will always point to name
+ * of output file */
+const char *simple_backup_suffix = ".BAK"; /* Suffix to use for backup
+ * files */
+char bakfile[MAXPATHLEN] = "";
+
+int
+main(int argc, char **argv)
+{
+ cap_rights_t rights;
+
+ int dec_ind; /* current indentation for declarations */
+ int di_stack[20]; /* a stack of structure indentation levels */
+ int force_nl; /* when true, code must be broken */
+ int hd_type = 0; /* used to store type of stmt for if (...),
+ * for (...), etc */
+ int i; /* local loop counter */
+ int scase; /* set to true when we see a case, so we will
+ * know what to do with the following colon */
+ int sp_sw; /* when true, we are in the expression of
+ * if(...), while(...), etc. */
+ int squest; /* when this is positive, we have seen a ?
+ * without the matching : in a <c>?<s>:<s>
+ * construct */
+ const char *t_ptr; /* used for copying tokens */
+ int tabs_to_var; /* true if using tabs to indent to var name */
+ int type_code; /* the type of token, returned by lexi */
+
+ int last_else = 0; /* true iff last keyword was an else */
+ const char *profile_name = NULL;
+ const char *envval = NULL;
+ struct parser_state transient_state; /* a copy for lookup */
+
+ /*-----------------------------------------------*\
+ | INITIALIZATION |
+ \*-----------------------------------------------*/
+
+ found_err = 0;
+
+ ps.p_stack[0] = stmt; /* this is the parser's stack */
+ ps.last_nl = true; /* this is true if the last thing scanned was
+ * a newline */
+ ps.last_token = semicolon;
+ combuf = (char *) malloc(bufsize);
+ if (combuf == NULL)
+ err(1, NULL);
+ labbuf = (char *) malloc(bufsize);
+ if (labbuf == NULL)
+ err(1, NULL);
+ codebuf = (char *) malloc(bufsize);
+ if (codebuf == NULL)
+ err(1, NULL);
+ tokenbuf = (char *) malloc(bufsize);
+ if (tokenbuf == NULL)
+ err(1, NULL);
+ alloc_typenames();
+ init_constant_tt();
+ l_com = combuf + bufsize - 5;
+ l_lab = labbuf + bufsize - 5;
+ l_code = codebuf + bufsize - 5;
+ l_token = tokenbuf + bufsize - 5;
+ combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and
+ * comment buffers */
+ combuf[1] = codebuf[1] = labbuf[1] = '\0';
+ opt.else_if = 1; /* Default else-if special processing to on */
+ s_lab = e_lab = labbuf + 1;
+ s_code = e_code = codebuf + 1;
+ s_com = e_com = combuf + 1;
+ s_token = e_token = tokenbuf + 1;
+
+ in_buffer = (char *) malloc(10);
+ if (in_buffer == NULL)
+ err(1, NULL);
+ in_buffer_limit = in_buffer + 8;
+ buf_ptr = buf_end = in_buffer;
+ line_no = 1;
+ had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
+ sp_sw = force_nl = false;
+ ps.in_or_st = false;
+ ps.bl_line = true;
+ dec_ind = 0;
+ di_stack[ps.dec_nest = 0] = 0;
+ ps.want_blank = ps.in_stmt = ps.ind_stmt = false;
+
+ scase = ps.pcase = false;
+ squest = 0;
+ sc_end = NULL;
+ bp_save = NULL;
+ be_save = NULL;
+
+ output = NULL;
+ tabs_to_var = 0;
+
+ envval = getenv("SIMPLE_BACKUP_SUFFIX");
+ if (envval)
+ simple_backup_suffix = envval;
+
+ /*--------------------------------------------------*\
+ | COMMAND LINE SCAN |
+ \*--------------------------------------------------*/
+
+#ifdef undef
+ max_col = 78; /* -l78 */
+ lineup_to_parens = 1; /* -lp */
+ lineup_to_parens_always = 0; /* -nlpl */
+ ps.ljust_decl = 0; /* -ndj */
+ ps.com_ind = 33; /* -c33 */
+ star_comment_cont = 1; /* -sc */
+ ps.ind_size = 8; /* -i8 */
+ verbose = 0;
+ ps.decl_indent = 16; /* -di16 */
+ ps.local_decl_indent = -1; /* if this is not set to some nonnegative value
+ * by an arg, we will set this equal to
+ * ps.decl_ind */
+ ps.indent_parameters = 1; /* -ip */
+ ps.decl_com_ind = 0; /* if this is not set to some positive value
+ * by an arg, we will set this equal to
+ * ps.com_ind */
+ btype_2 = 1; /* -br */
+ cuddle_else = 1; /* -ce */
+ ps.unindent_displace = 0; /* -d0 */
+ ps.case_indent = 0; /* -cli0 */
+ format_block_comments = 1; /* -fcb */
+ format_col1_comments = 1; /* -fc1 */
+ procnames_start_line = 1; /* -psl */
+ proc_calls_space = 0; /* -npcs */
+ comment_delimiter_on_blankline = 1; /* -cdb */
+ ps.leave_comma = 1; /* -nbc */
+#endif
+
+ for (i = 1; i < argc; ++i)
+ if (strcmp(argv[i], "-npro") == 0)
+ break;
+ else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0')
+ profile_name = argv[i]; /* non-empty -P (set profile) */
+ set_defaults();
+ if (i >= argc)
+ set_profile(profile_name);
+
+ for (i = 1; i < argc; ++i) {
+
+ /*
+ * look thru args (if any) for changes to defaults
+ */
+ if (argv[i][0] != '-') {/* no flag on parameter */
+ if (input == NULL) { /* we must have the input file */
+ in_name = argv[i]; /* remember name of input file */
+ input = fopen(in_name, "r");
+ if (input == NULL) /* check for open error */
+ err(1, "%s", in_name);
+ continue;
+ }
+ else if (output == NULL) { /* we have the output file */
+ out_name = argv[i]; /* remember name of output file */
+ if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite
+ * the file */
+ errx(1, "input and output files must be different");
+ }
+ output = fopen(out_name, "w");
+ if (output == NULL) /* check for create error */
+ err(1, "%s", out_name);
+ continue;
+ }
+ errx(1, "unknown parameter: %s", argv[i]);
+ }
+ else
+ set_option(argv[i]);
+ } /* end of for */
+ if (input == NULL)
+ input = stdin;
+ if (output == NULL) {
+ if (input == stdin)
+ output = stdout;
+ else {
+ out_name = in_name;
+ bakcopy();
+ }
+ }
+
+ /* Restrict input/output descriptors and enter Capsicum sandbox. */
+ cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
+ if (caph_rights_limit(fileno(output), &rights) < 0)
+ err(EXIT_FAILURE, "unable to limit rights for %s", out_name);
+ cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
+ if (caph_rights_limit(fileno(input), &rights) < 0)
+ err(EXIT_FAILURE, "unable to limit rights for %s", in_name);
+ if (caph_enter() < 0)
+ err(EXIT_FAILURE, "unable to enter capability mode");
+
+ if (opt.com_ind <= 1)
+ opt.com_ind = 2; /* don't put normal comments before column 2 */
+ if (opt.block_comment_max_col <= 0)
+ opt.block_comment_max_col = opt.max_col;
+ if (opt.local_decl_indent < 0) /* if not specified by user, set this */
+ opt.local_decl_indent = opt.decl_indent;
+ if (opt.decl_com_ind <= 0) /* if not specified by user, set this */
+ opt.decl_com_ind = opt.ljust_decl ? (opt.com_ind <= 10 ? 2 : opt.com_ind - 8) : opt.com_ind;
+ if (opt.continuation_indent == 0)
+ opt.continuation_indent = opt.ind_size;
+ fill_buffer(); /* get first batch of stuff into input buffer */
+
+ parse(semicolon);
+ {
+ char *p = buf_ptr;
+ int col = 1;
+
+ while (1) {
+ if (*p == ' ')
+ col++;
+ else if (*p == '\t')
+ col = opt.tabsize * (1 + (col - 1) / opt.tabsize) + 1;
+ else
+ break;
+ p++;
+ }
+ if (col > opt.ind_size)
+ ps.ind_level = ps.i_l_follow = col / opt.ind_size;
+ }
+
+ /*
+ * START OF MAIN LOOP
+ */
+
+ while (1) { /* this is the main loop. it will go until we
+ * reach eof */
+ int comment_buffered = false;
+
+ type_code = lexi(&ps); /* lexi reads one token. The actual
+ * characters read are stored in "token". lexi
+ * returns a code indicating the type of token */
+
+ /*
+ * The following code moves newlines and comments following an if (),
+ * while (), else, etc. up to the start of the following stmt to
+ * a buffer. This allows proper handling of both kinds of brace
+ * placement (-br, -bl) and cuddling "else" (-ce).
+ */
+
+ while (ps.search_brace) {
+ switch (type_code) {
+ case newline:
+ if (sc_end == NULL) {
+ save_com = sc_buf;
+ save_com[0] = save_com[1] = ' ';
+ sc_end = &save_com[2];
+ }
+ *sc_end++ = '\n';
+ /*
+ * We may have inherited a force_nl == true from the previous
+ * token (like a semicolon). But once we know that a newline
+ * has been scanned in this loop, force_nl should be false.
+ *
+ * However, the force_nl == true must be preserved if newline
+ * is never scanned in this loop, so this assignment cannot be
+ * done earlier.
+ */
+ force_nl = false;
+ case form_feed:
+ break;
+ case comment:
+ if (sc_end == NULL) {
+ /*
+ * Copy everything from the start of the line, because
+ * pr_comment() will use that to calculate original
+ * indentation of a boxed comment.
+ */
+ memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4);
+ save_com = sc_buf + (buf_ptr - in_buffer - 4);
+ save_com[0] = save_com[1] = ' ';
+ sc_end = &save_com[2];
+ }
+ comment_buffered = true;
+ *sc_end++ = '/'; /* copy in start of comment */
+ *sc_end++ = '*';
+ for (;;) { /* loop until we get to the end of the comment */
+ *sc_end = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ if (*sc_end++ == '*' && *buf_ptr == '/')
+ break; /* we are at end of comment */
+ if (sc_end >= &save_com[sc_size]) { /* check for temp buffer
+ * overflow */
+ diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
+ fflush(output);
+ exit(1);
+ }
+ }
+ *sc_end++ = '/'; /* add ending slash */
+ if (++buf_ptr >= buf_end) /* get past / in buffer */
+ fill_buffer();
+ break;
+ case lbrace:
+ /*
+ * Put KNF-style lbraces before the buffered up tokens and
+ * jump out of this loop in order to avoid copying the token
+ * again under the default case of the switch below.
+ */
+ if (sc_end != NULL && opt.btype_2) {
+ save_com[0] = '{';
+ /*
+ * Originally the lbrace may have been alone on its own
+ * line, but it will be moved into "the else's line", so
+ * if there was a newline resulting from the "{" before,
+ * it must be scanned now and ignored.
+ */
+ while (isspace((unsigned char)*buf_ptr)) {
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ if (*buf_ptr == '\n')
+ break;
+ }
+ goto sw_buffer;
+ }
+ /* FALLTHROUGH */
+ default: /* it is the start of a normal statement */
+ {
+ int remove_newlines;
+
+ remove_newlines =
+ /* "} else" */
+ (type_code == sp_nparen && *token == 'e' &&
+ e_code != s_code && e_code[-1] == '}')
+ /* "else if" */
+ || (type_code == sp_paren && *token == 'i' &&
+ last_else && opt.else_if);
+ if (remove_newlines)
+ force_nl = false;
+ if (sc_end == NULL) { /* ignore buffering if
+ * comment wasn't saved up */
+ ps.search_brace = false;
+ goto check_type;
+ }
+ while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) {
+ sc_end--;
+ }
+ if (opt.swallow_optional_blanklines ||
+ (!comment_buffered && remove_newlines)) {
+ force_nl = !remove_newlines;
+ while (sc_end > save_com && sc_end[-1] == '\n') {
+ sc_end--;
+ }
+ }
+ if (force_nl) { /* if we should insert a nl here, put
+ * it into the buffer */
+ force_nl = false;
+ --line_no; /* this will be re-increased when the
+ * newline is read from the buffer */
+ *sc_end++ = '\n';
+ *sc_end++ = ' ';
+ if (opt.verbose) /* print error msg if the line was
+ * not already broken */
+ diag2(0, "Line broken");
+ }
+ for (t_ptr = token; *t_ptr; ++t_ptr)
+ *sc_end++ = *t_ptr;
+
+ sw_buffer:
+ ps.search_brace = false; /* stop looking for start of
+ * stmt */
+ bp_save = buf_ptr; /* save current input buffer */
+ be_save = buf_end;
+ buf_ptr = save_com; /* fix so that subsequent calls to
+ * lexi will take tokens out of
+ * save_com */
+ *sc_end++ = ' ';/* add trailing blank, just in case */
+ buf_end = sc_end;
+ sc_end = NULL;
+ break;
+ }
+ } /* end of switch */
+ /*
+ * We must make this check, just in case there was an unexpected
+ * EOF.
+ */
+ if (type_code != 0) {
+ /*
+ * The only intended purpose of calling lexi() below is to
+ * categorize the next token in order to decide whether to
+ * continue buffering forthcoming tokens. Once the buffering
+ * is over, lexi() will be called again elsewhere on all of
+ * the tokens - this time for normal processing.
+ *
+ * Calling it for this purpose is a bug, because lexi() also
+ * changes the parser state and discards leading whitespace,
+ * which is needed mostly for comment-related considerations.
+ *
+ * Work around the former problem by giving lexi() a copy of
+ * the current parser state and discard it if the call turned
+ * out to be just a look ahead.
+ *
+ * Work around the latter problem by copying all whitespace
+ * characters into the buffer so that the later lexi() call
+ * will read them.
+ */
+ if (sc_end != NULL) {
+ while (*buf_ptr == ' ' || *buf_ptr == '\t') {
+ *sc_end++ = *buf_ptr++;
+ if (sc_end >= &save_com[sc_size]) {
+ errx(1, "input too long");
+ }
+ }
+ if (buf_ptr >= buf_end) {
+ fill_buffer();
+ }
+ }
+ transient_state = ps;
+ type_code = lexi(&transient_state); /* read another token */
+ if (type_code != newline && type_code != form_feed &&
+ type_code != comment && !transient_state.search_brace) {
+ ps = transient_state;
+ }
+ }
+ } /* end of while (search_brace) */
+ last_else = 0;
+check_type:
+ if (type_code == 0) { /* we got eof */
+ if (s_lab != e_lab || s_code != e_code
+ || s_com != e_com) /* must dump end of line */
+ dump_line();
+ if (ps.tos > 1) /* check for balanced braces */
+ diag2(1, "Stuff missing from end of file");
+
+ if (opt.verbose) {
+ printf("There were %d output lines and %d comments\n",
+ ps.out_lines, ps.out_coms);
+ printf("(Lines with comments)/(Lines with code): %6.3f\n",
+ (1.0 * ps.com_lines) / code_lines);
+ }
+ fflush(output);
+ exit(found_err);
+ }
+ if (
+ (type_code != comment) &&
+ (type_code != newline) &&
+ (type_code != preesc) &&
+ (type_code != form_feed)) {
+ if (force_nl &&
+ (type_code != semicolon) &&
+ (type_code != lbrace || !opt.btype_2)) {
+ /* we should force a broken line here */
+ if (opt.verbose)
+ diag2(0, "Line broken");
+ dump_line();
+ ps.want_blank = false; /* dont insert blank at line start */
+ force_nl = false;
+ }
+ ps.in_stmt = true; /* turn on flag which causes an extra level of
+ * indentation. this is turned off by a ; or
+ * '}' */
+ if (s_com != e_com) { /* the turkey has embedded a comment
+ * in a line. fix it */
+ int len = e_com - s_com;
+
+ CHECK_SIZE_CODE(len + 3);
+ *e_code++ = ' ';
+ memcpy(e_code, s_com, len);
+ e_code += len;
+ *e_code++ = ' ';
+ *e_code = '\0'; /* null terminate code sect */
+ ps.want_blank = false;
+ e_com = s_com;
+ }
+ }
+ else if (type_code != comment) /* preserve force_nl thru a comment */
+ force_nl = false; /* cancel forced newline after newline, form
+ * feed, etc */
+
+
+
+ /*-----------------------------------------------------*\
+ | do switch on type of token scanned |
+ \*-----------------------------------------------------*/
+ CHECK_SIZE_CODE(3); /* maximum number of increments of e_code
+ * before the next CHECK_SIZE_CODE or
+ * dump_line() is 2. After that there's the
+ * final increment for the null character. */
+ switch (type_code) { /* now, decide what to do with the token */
+
+ case form_feed: /* found a form feed in line */
+ ps.use_ff = true; /* a form feed is treated much like a newline */
+ dump_line();
+ ps.want_blank = false;
+ break;
+
+ case newline:
+ if (ps.last_token != comma || ps.p_l_follow > 0
+ || !opt.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
+ dump_line();
+ ps.want_blank = false;
+ }
+ ++line_no; /* keep track of input line number */
+ break;
+
+ case lparen: /* got a '(' or '[' */
+ /* count parens to make Healy happy */
+ if (++ps.p_l_follow == nitems(ps.paren_indents)) {
+ diag3(0, "Reached internal limit of %d unclosed parens",
+ nitems(ps.paren_indents));
+ ps.p_l_follow--;
+ }
+ if (*token == '[')
+ /* not a function pointer declaration or a function call */;
+ else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent &&
+ ps.procname[0] == '\0' && ps.paren_level == 0) {
+ /* function pointer declarations */
+ indent_declaration(dec_ind, tabs_to_var);
+ ps.dumped_decl_indent = true;
+ }
+ else if (ps.want_blank &&
+ ((ps.last_token != ident && ps.last_token != funcname) ||
+ opt.proc_calls_space ||
+ /* offsetof (1) is never allowed a space; sizeof (2) gets
+ * one iff -bs; all other keywords (>2) always get a space
+ * before lparen */
+ ps.keyword + opt.Bill_Shannon > 2))
+ *e_code++ = ' ';
+ ps.want_blank = false;
+ *e_code++ = token[0];
+ ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1;
+ if (sp_sw && ps.p_l_follow == 1 && opt.extra_expression_indent
+ && ps.paren_indents[0] < 2 * opt.ind_size)
+ ps.paren_indents[0] = 2 * opt.ind_size;
+ if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
+ /*
+ * this is a kluge to make sure that declarations will be
+ * aligned right if proc decl has an explicit type on it, i.e.
+ * "int a(x) {..."
+ */
+ parse(semicolon); /* I said this was a kluge... */
+ ps.in_or_st = false; /* turn off flag for structure decl or
+ * initialization */
+ }
+ /* parenthesized type following sizeof or offsetof is not a cast */
+ if (ps.keyword == 1 || ps.keyword == 2)
+ ps.not_cast_mask |= 1 << ps.p_l_follow;
+ break;
+
+ case rparen: /* got a ')' or ']' */
+ if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) {
+ ps.last_u_d = true;
+ ps.cast_mask &= (1 << ps.p_l_follow) - 1;
+ ps.want_blank = opt.space_after_cast;
+ } else
+ ps.want_blank = true;
+ ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
+ if (--ps.p_l_follow < 0) {
+ ps.p_l_follow = 0;
+ diag3(0, "Extra %c", *token);
+ }
+ if (e_code == s_code) /* if the paren starts the line */
+ ps.paren_level = ps.p_l_follow; /* then indent it */
+
+ *e_code++ = token[0];
+
+ if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if
+ * (...), or some such */
+ sp_sw = false;
+ force_nl = true;/* must force newline after if */
+ ps.last_u_d = true; /* inform lexi that a following
+ * operator is unary */
+ ps.in_stmt = false; /* dont use stmt continuation
+ * indentation */
+
+ parse(hd_type); /* let parser worry about if, or whatever */
+ }
+ ps.search_brace = opt.btype_2; /* this should ensure that
+ * constructs such as main(){...}
+ * and int[]{...} have their braces
+ * put in the right place */
+ break;
+
+ case unary_op: /* this could be any unary operation */
+ if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init &&
+ ps.procname[0] == '\0' && ps.paren_level == 0) {
+ /* pointer declarations */
+
+ /*
+ * if this is a unary op in a declaration, we should indent
+ * this token
+ */
+ for (i = 0; token[i]; ++i)
+ /* find length of token */;
+ indent_declaration(dec_ind - i, tabs_to_var);
+ ps.dumped_decl_indent = true;
+ }
+ else if (ps.want_blank)
+ *e_code++ = ' ';
+
+ {
+ int len = e_token - s_token;
+
+ CHECK_SIZE_CODE(len);
+ memcpy(e_code, token, len);
+ e_code += len;
+ }
+ ps.want_blank = false;
+ break;
+
+ case binary_op: /* any binary operation */
+ {
+ int len = e_token - s_token;
+
+ CHECK_SIZE_CODE(len + 1);
+ if (ps.want_blank)
+ *e_code++ = ' ';
+ memcpy(e_code, token, len);
+ e_code += len;
+ }
+ ps.want_blank = true;
+ break;
+
+ case postop: /* got a trailing ++ or -- */
+ *e_code++ = token[0];
+ *e_code++ = token[1];
+ ps.want_blank = true;
+ break;
+
+ case question: /* got a ? */
+ squest++; /* this will be used when a later colon
+ * appears so we can distinguish the
+ * <c>?<n>:<n> construct */
+ if (ps.want_blank)
+ *e_code++ = ' ';
+ *e_code++ = '?';
+ ps.want_blank = true;
+ break;
+
+ case casestmt: /* got word 'case' or 'default' */
+ scase = true; /* so we can process the later colon properly */
+ goto copy_id;
+
+ case colon: /* got a ':' */
+ if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */
+ --squest;
+ if (ps.want_blank)
+ *e_code++ = ' ';
+ *e_code++ = ':';
+ ps.want_blank = true;
+ break;
+ }
+ if (ps.in_or_st) {
+ *e_code++ = ':';
+ ps.want_blank = false;
+ break;
+ }
+ ps.in_stmt = false; /* seeing a label does not imply we are in a
+ * stmt */
+ /*
+ * turn everything so far into a label
+ */
+ {
+ int len = e_code - s_code;
+
+ CHECK_SIZE_LAB(len + 3);
+ memcpy(e_lab, s_code, len);
+ e_lab += len;
+ *e_lab++ = ':';
+ *e_lab = '\0';
+ e_code = s_code;
+ }
+ force_nl = ps.pcase = scase; /* ps.pcase will be used by
+ * dump_line to decide how to
+ * indent the label. force_nl
+ * will force a case n: to be
+ * on a line by itself */
+ scase = false;
+ ps.want_blank = false;
+ break;
+
+ case semicolon: /* got a ';' */
+ if (ps.dec_nest == 0)
+ ps.in_or_st = false;/* we are not in an initialization or
+ * structure declaration */
+ scase = false; /* these will only need resetting in an error */
+ squest = 0;
+ if (ps.last_token == rparen)
+ ps.in_parameter_declaration = 0;
+ ps.cast_mask = 0;
+ ps.not_cast_mask = 0;
+ ps.block_init = 0;
+ ps.block_init_level = 0;
+ ps.just_saw_decl--;
+
+ if (ps.in_decl && s_code == e_code && !ps.block_init &&
+ !ps.dumped_decl_indent && ps.paren_level == 0) {
+ /* indent stray semicolons in declarations */
+ indent_declaration(dec_ind - 1, tabs_to_var);
+ ps.dumped_decl_indent = true;
+ }
+
+ ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level
+ * structure declaration, we
+ * arent any more */
+
+ if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
+
+ /*
+ * This should be true iff there were unbalanced parens in the
+ * stmt. It is a bit complicated, because the semicolon might
+ * be in a for stmt
+ */
+ diag2(1, "Unbalanced parens");
+ ps.p_l_follow = 0;
+ if (sp_sw) { /* this is a check for an if, while, etc. with
+ * unbalanced parens */
+ sp_sw = false;
+ parse(hd_type); /* dont lose the if, or whatever */
+ }
+ }
+ *e_code++ = ';';
+ ps.want_blank = true;
+ ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the
+ * middle of a stmt */
+
+ if (!sp_sw) { /* if not if for (;;) */
+ parse(semicolon); /* let parser know about end of stmt */
+ force_nl = true;/* force newline after an end of stmt */
+ }
+ break;
+
+ case lbrace: /* got a '{' */
+ ps.in_stmt = false; /* dont indent the {} */
+ if (!ps.block_init)
+ force_nl = true;/* force other stuff on same line as '{' onto
+ * new line */
+ else if (ps.block_init_level <= 0)
+ ps.block_init_level = 1;
+ else
+ ps.block_init_level++;
+
+ if (s_code != e_code && !ps.block_init) {
+ if (!opt.btype_2) {
+ dump_line();
+ ps.want_blank = false;
+ }
+ else if (ps.in_parameter_declaration && !ps.in_or_st) {
+ ps.i_l_follow = 0;
+ if (opt.function_brace_split) { /* dump the line prior
+ * to the brace ... */
+ dump_line();
+ ps.want_blank = false;
+ } else /* add a space between the decl and brace */
+ ps.want_blank = true;
+ }
+ }
+ if (ps.in_parameter_declaration)
+ prefix_blankline_requested = 0;
+
+ if (ps.p_l_follow > 0) { /* check for preceding unbalanced
+ * parens */
+ diag2(1, "Unbalanced parens");
+ ps.p_l_follow = 0;
+ if (sp_sw) { /* check for unclosed if, for, etc. */
+ sp_sw = false;
+ parse(hd_type);
+ ps.ind_level = ps.i_l_follow;
+ }
+ }
+ if (s_code == e_code)
+ ps.ind_stmt = false; /* dont put extra indentation on line
+ * with '{' */
+ if (ps.in_decl && ps.in_or_st) { /* this is either a structure
+ * declaration or an init */
+ di_stack[ps.dec_nest] = dec_ind;
+ if (++ps.dec_nest == nitems(di_stack)) {
+ diag3(0, "Reached internal limit of %d struct levels",
+ nitems(di_stack));
+ ps.dec_nest--;
+ }
+ /* ? dec_ind = 0; */
+ }
+ else {
+ ps.decl_on_line = false; /* we can't be in the middle of
+ * a declaration, so don't do
+ * special indentation of
+ * comments */
+ if (opt.blanklines_after_declarations_at_proctop
+ && ps.in_parameter_declaration)
+ postfix_blankline_requested = 1;
+ ps.in_parameter_declaration = 0;
+ ps.in_decl = false;
+ }
+ dec_ind = 0;
+ parse(lbrace); /* let parser know about this */
+ if (ps.want_blank) /* put a blank before '{' if '{' is not at
+ * start of line */
+ *e_code++ = ' ';
+ ps.want_blank = false;
+ *e_code++ = '{';
+ ps.just_saw_decl = 0;
+ break;
+
+ case rbrace: /* got a '}' */
+ if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be
+ * omitted in
+ * declarations */
+ parse(semicolon);
+ if (ps.p_l_follow) {/* check for unclosed if, for, else. */
+ diag2(1, "Unbalanced parens");
+ ps.p_l_follow = 0;
+ sp_sw = false;
+ }
+ ps.just_saw_decl = 0;
+ ps.block_init_level--;
+ if (s_code != e_code && !ps.block_init) { /* '}' must be first on
+ * line */
+ if (opt.verbose)
+ diag2(0, "Line broken");
+ dump_line();
+ }
+ *e_code++ = '}';
+ ps.want_blank = true;
+ ps.in_stmt = ps.ind_stmt = false;
+ if (ps.dec_nest > 0) { /* we are in multi-level structure
+ * declaration */
+ dec_ind = di_stack[--ps.dec_nest];
+ if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
+ ps.just_saw_decl = 2;
+ ps.in_decl = true;
+ }
+ prefix_blankline_requested = 0;
+ parse(rbrace); /* let parser know about this */
+ ps.search_brace = opt.cuddle_else && ps.p_stack[ps.tos] == ifhead
+ && ps.il[ps.tos] >= ps.ind_level;
+ if (ps.tos <= 1 && opt.blanklines_after_procs && ps.dec_nest <= 0)
+ postfix_blankline_requested = 1;
+ break;
+
+ case swstmt: /* got keyword "switch" */
+ sp_sw = true;
+ hd_type = swstmt; /* keep this for when we have seen the
+ * expression */
+ goto copy_id; /* go move the token into buffer */
+
+ case sp_paren: /* token is if, while, for */
+ sp_sw = true; /* the interesting stuff is done after the
+ * expression is scanned */
+ hd_type = (*token == 'i' ? ifstmt :
+ (*token == 'w' ? whilestmt : forstmt));
+
+ /*
+ * remember the type of header for later use by parser
+ */
+ goto copy_id; /* copy the token into line */
+
+ case sp_nparen: /* got else, do */
+ ps.in_stmt = false;
+ if (*token == 'e') {
+ if (e_code != s_code && (!opt.cuddle_else || e_code[-1] != '}')) {
+ if (opt.verbose)
+ diag2(0, "Line broken");
+ dump_line();/* make sure this starts a line */
+ ps.want_blank = false;
+ }
+ force_nl = true;/* also, following stuff must go onto new line */
+ last_else = 1;
+ parse(elselit);
+ }
+ else {
+ if (e_code != s_code) { /* make sure this starts a line */
+ if (opt.verbose)
+ diag2(0, "Line broken");
+ dump_line();
+ ps.want_blank = false;
+ }
+ force_nl = true;/* also, following stuff must go onto new line */
+ last_else = 0;
+ parse(dolit);
+ }
+ goto copy_id; /* move the token into line */
+
+ case type_def:
+ case storage:
+ prefix_blankline_requested = 0;
+ goto copy_id;
+
+ case structure:
+ if (ps.p_l_follow > 0)
+ goto copy_id;
+ /* FALLTHROUGH */
+ case decl: /* we have a declaration type (int, etc.) */
+ parse(decl); /* let parser worry about indentation */
+ if (ps.last_token == rparen && ps.tos <= 1) {
+ if (s_code != e_code) {
+ dump_line();
+ ps.want_blank = 0;
+ }
+ }
+ if (ps.in_parameter_declaration && opt.indent_parameters && ps.dec_nest == 0) {
+ ps.ind_level = ps.i_l_follow = 1;
+ ps.ind_stmt = 0;
+ }
+ ps.in_or_st = true; /* this might be a structure or initialization
+ * declaration */
+ ps.in_decl = ps.decl_on_line = ps.last_token != type_def;
+ if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
+ ps.just_saw_decl = 2;
+ prefix_blankline_requested = 0;
+ for (i = 0; token[i++];); /* get length of token */
+
+ if (ps.ind_level == 0 || ps.dec_nest > 0) {
+ /* global variable or struct member in local variable */
+ dec_ind = opt.decl_indent > 0 ? opt.decl_indent : i;
+ tabs_to_var = (opt.use_tabs ? opt.decl_indent > 0 : 0);
+ } else {
+ /* local variable */
+ dec_ind = opt.local_decl_indent > 0 ? opt.local_decl_indent : i;
+ tabs_to_var = (opt.use_tabs ? opt.local_decl_indent > 0 : 0);
+ }
+ goto copy_id;
+
+ case funcname:
+ case ident: /* got an identifier or constant */
+ if (ps.in_decl) {
+ if (type_code == funcname) {
+ ps.in_decl = false;
+ if (opt.procnames_start_line && s_code != e_code) {
+ *e_code = '\0';
+ dump_line();
+ }
+ else if (ps.want_blank) {
+ *e_code++ = ' ';
+ }
+ ps.want_blank = false;
+ }
+ else if (!ps.block_init && !ps.dumped_decl_indent &&
+ ps.paren_level == 0) { /* if we are in a declaration, we
+ * must indent identifier */
+ indent_declaration(dec_ind, tabs_to_var);
+ ps.dumped_decl_indent = true;
+ ps.want_blank = false;
+ }
+ }
+ else if (sp_sw && ps.p_l_follow == 0) {
+ sp_sw = false;
+ force_nl = true;
+ ps.last_u_d = true;
+ ps.in_stmt = false;
+ parse(hd_type);
+ }
+ copy_id:
+ {
+ int len = e_token - s_token;
+
+ CHECK_SIZE_CODE(len + 1);
+ if (ps.want_blank)
+ *e_code++ = ' ';
+ memcpy(e_code, s_token, len);
+ e_code += len;
+ }
+ if (type_code != funcname)
+ ps.want_blank = true;
+ break;
+
+ case strpfx:
+ {
+ int len = e_token - s_token;
+
+ CHECK_SIZE_CODE(len + 1);
+ if (ps.want_blank)
+ *e_code++ = ' ';
+ memcpy(e_code, token, len);
+ e_code += len;
+ }
+ ps.want_blank = false;
+ break;
+
+ case period: /* treat a period kind of like a binary
+ * operation */
+ *e_code++ = '.'; /* move the period into line */
+ ps.want_blank = false; /* dont put a blank after a period */
+ break;
+
+ case comma:
+ ps.want_blank = (s_code != e_code); /* only put blank after comma
+ * if comma does not start the
+ * line */
+ if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init &&
+ !ps.dumped_decl_indent && ps.paren_level == 0) {
+ /* indent leading commas and not the actual identifiers */
+ indent_declaration(dec_ind - 1, tabs_to_var);
+ ps.dumped_decl_indent = true;
+ }
+ *e_code++ = ',';
+ if (ps.p_l_follow == 0) {
+ if (ps.block_init_level <= 0)
+ ps.block_init = 0;
+ if (break_comma && (!opt.leave_comma ||
+ count_spaces_until(compute_code_target(), s_code, e_code) >
+ opt.max_col - opt.tabsize))
+ force_nl = true;
+ }
+ break;
+
+ case preesc: /* got the character '#' */
+ if ((s_com != e_com) ||
+ (s_lab != e_lab) ||
+ (s_code != e_code))
+ dump_line();
+ CHECK_SIZE_LAB(1);
+ *e_lab++ = '#'; /* move whole line to 'label' buffer */
+ {
+ int in_comment = 0;
+ int com_start = 0;
+ char quote = 0;
+ int com_end = 0;
+
+ while (*buf_ptr == ' ' || *buf_ptr == '\t') {
+ buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
+ CHECK_SIZE_LAB(2);
+ *e_lab = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ switch (*e_lab++) {
+ case BACKSLASH:
+ if (!in_comment) {
+ *e_lab++ = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ break;
+ case '/':
+ if (*buf_ptr == '*' && !in_comment && !quote) {
+ in_comment = 1;
+ *e_lab++ = *buf_ptr++;
+ com_start = e_lab - s_lab - 2;
+ }
+ break;
+ case '"':
+ if (quote == '"')
+ quote = 0;
+ break;
+ case '\'':
+ if (quote == '\'')
+ quote = 0;
+ break;
+ case '*':
+ if (*buf_ptr == '/' && in_comment) {
+ in_comment = 0;
+ *e_lab++ = *buf_ptr++;
+ com_end = e_lab - s_lab;
+ }
+ break;
+ }
+ }
+
+ while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+ e_lab--;
+ if (e_lab - s_lab == com_end && bp_save == NULL) {
+ /* comment on preprocessor line */
+ if (sc_end == NULL) { /* if this is the first comment,
+ * we must set up the buffer */
+ save_com = sc_buf;
+ sc_end = &save_com[0];
+ }
+ else {
+ *sc_end++ = '\n'; /* add newline between
+ * comments */
+ *sc_end++ = ' ';
+ --line_no;
+ }
+ if (sc_end - save_com + com_end - com_start > sc_size)
+ errx(1, "input too long");
+ memmove(sc_end, s_lab + com_start, com_end - com_start);
+ sc_end += com_end - com_start;
+ e_lab = s_lab + com_start;
+ while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+ e_lab--;
+ bp_save = buf_ptr; /* save current input buffer */
+ be_save = buf_end;
+ buf_ptr = save_com; /* fix so that subsequent calls to
+ * lexi will take tokens out of
+ * save_com */
+ *sc_end++ = ' '; /* add trailing blank, just in case */
+ buf_end = sc_end;
+ sc_end = NULL;
+ }
+ CHECK_SIZE_LAB(1);
+ *e_lab = '\0'; /* null terminate line */
+ ps.pcase = false;
+ }
+
+ if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */
+ if ((size_t)ifdef_level < nitems(state_stack)) {
+ match_state[ifdef_level].tos = -1;
+ state_stack[ifdef_level++] = ps;
+ }
+ else
+ diag2(1, "#if stack overflow");
+ }
+ else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */
+ if (ifdef_level <= 0)
+ diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
+ else {
+ match_state[ifdef_level - 1] = ps;
+ ps = state_stack[ifdef_level - 1];
+ }
+ }
+ else if (strncmp(s_lab, "#endif", 6) == 0) {
+ if (ifdef_level <= 0)
+ diag2(1, "Unmatched #endif");
+ else
+ ifdef_level--;
+ } else {
+ struct directives {
+ int size;
+ const char *string;
+ }
+ recognized[] = {
+ {7, "include"},
+ {6, "define"},
+ {5, "undef"},
+ {4, "line"},
+ {5, "error"},
+ {6, "pragma"}
+ };
+ int d = nitems(recognized);
+ while (--d >= 0)
+ if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0)
+ break;
+ if (d < 0) {
+ diag2(1, "Unrecognized cpp directive");
+ break;
+ }
+ }
+ if (opt.blanklines_around_conditional_compilation) {
+ postfix_blankline_requested++;
+ n_real_blanklines = 0;
+ }
+ else {
+ postfix_blankline_requested = 0;
+ prefix_blankline_requested = 0;
+ }
+ break; /* subsequent processing of the newline
+ * character will cause the line to be printed */
+
+ case comment: /* we have gotten a / followed by * this is a biggie */
+ pr_comment();
+ break;
+ } /* end of big switch stmt */
+
+ *e_code = '\0'; /* make sure code section is null terminated */
+ if (type_code != comment && type_code != newline && type_code != preesc)
+ ps.last_token = type_code;
+ } /* end of main while (1) loop */
+}
+
+/*
+ * copy input file to backup file if in_name is /blah/blah/blah/file, then
+ * backup file will be ".Bfile" then make the backup file the input and
+ * original input file the output
+ */
+static void
+bakcopy(void)
+{
+ int n,
+ bakchn;
+ char buff[8 * 1024];
+ const char *p;
+
+ /* construct file name .Bfile */
+ for (p = in_name; *p; p++); /* skip to end of string */
+ while (p > in_name && *p != '/') /* find last '/' */
+ p--;
+ if (*p == '/')
+ p++;
+ sprintf(bakfile, "%s%s", p, simple_backup_suffix);
+
+ /* copy in_name to backup file */
+ bakchn = creat(bakfile, 0600);
+ if (bakchn < 0)
+ err(1, "%s", bakfile);
+ while ((n = read(fileno(input), buff, sizeof(buff))) > 0)
+ if (write(bakchn, buff, n) != n)
+ err(1, "%s", bakfile);
+ if (n < 0)
+ err(1, "%s", in_name);
+ close(bakchn);
+ fclose(input);
+
+ /* re-open backup file as the input file */
+ input = fopen(bakfile, "r");
+ if (input == NULL)
+ err(1, "%s", bakfile);
+ /* now the original input file will be the output */
+ output = fopen(in_name, "w");
+ if (output == NULL) {
+ unlink(bakfile);
+ err(1, "%s", in_name);
+ }
+}
+
+static void
+indent_declaration(int cur_dec_ind, int tabs_to_var)
+{
+ int pos = e_code - s_code;
+ char *startpos = e_code;
+
+ /*
+ * get the tab math right for indentations that are not multiples of tabsize
+ */
+ if ((ps.ind_level * opt.ind_size) % opt.tabsize != 0) {
+ pos += (ps.ind_level * opt.ind_size) % opt.tabsize;
+ cur_dec_ind += (ps.ind_level * opt.ind_size) % opt.tabsize;
+ }
+ if (tabs_to_var) {
+ int tpos;
+
+ CHECK_SIZE_CODE(cur_dec_ind / opt.tabsize);
+ while ((tpos = opt.tabsize * (1 + pos / opt.tabsize)) <= cur_dec_ind) {
+ *e_code++ = '\t';
+ pos = tpos;
+ }
+ }
+ CHECK_SIZE_CODE(cur_dec_ind - pos + 1);
+ while (pos < cur_dec_ind) {
+ *e_code++ = ' ';
+ pos++;
+ }
+ if (e_code == startpos && ps.want_blank) {
+ *e_code++ = ' ';
+ ps.want_blank = false;
+ }
+}
diff --git a/usr.bin/indent/indent.h b/usr.bin/indent/indent.h
new file mode 100644
index 000000000000..1f9ceac11253
--- /dev/null
+++ b/usr.bin/indent/indent.h
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2001 Jens Schweikhardt
+ * 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.
+ *
+ * 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.
+ */
+
+void add_typename(const char *);
+void alloc_typenames(void);
+int compute_code_target(void);
+int compute_label_target(void);
+int count_spaces(int, char *);
+int count_spaces_until(int, char *, char *);
+void init_constant_tt(void);
+int lexi(struct parser_state *);
+void diag2(int, const char *);
+void diag3(int, const char *, int);
+void diag4(int, const char *, int, int);
+void dump_line(void);
+void fill_buffer(void);
+void parse(int);
+void pr_comment(void);
+void set_defaults(void);
+void set_option(char *);
+void set_profile(const char *);
diff --git a/usr.bin/indent/indent_codes.h b/usr.bin/indent/indent_codes.h
new file mode 100644
index 000000000000..7be9b0022419
--- /dev/null
+++ b/usr.bin/indent/indent_codes.h
@@ -0,0 +1,74 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 newline 1
+#define lparen 2
+#define rparen 3
+#define unary_op 4
+#define binary_op 5
+#define postop 6
+#define question 7
+#define casestmt 8
+#define colon 9
+#define semicolon 10
+#define lbrace 11
+#define rbrace 12
+#define ident 13
+#define comma 14
+#define comment 15
+#define swstmt 16
+#define preesc 17
+#define form_feed 18
+#define decl 19
+#define sp_paren 20
+#define sp_nparen 21
+#define ifstmt 22
+#define whilestmt 23
+#define forstmt 24
+#define stmt 25
+#define stmtl 26
+#define elselit 27
+#define dolit 28
+#define dohead 29
+#define ifhead 30
+#define elsehead 31
+#define period 32
+#define strpfx 33
+#define storage 34
+#define funcname 35
+#define type_def 36
+#define structure 37
diff --git a/usr.bin/indent/indent_globs.h b/usr.bin/indent/indent_globs.h
new file mode 100644
index 000000000000..7f4ddff0d989
--- /dev/null
+++ b/usr.bin/indent/indent_globs.h
@@ -0,0 +1,323 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 BACKSLASH '\\'
+#define bufsize 200 /* size of internal buffers */
+#define sc_size 5000 /* size of save_com buffer */
+#define label_offset 2 /* number of levels a label is placed to left
+ * of code */
+
+
+#define false 0
+#define true 1
+
+
+extern FILE *input; /* the fid for the input file */
+extern FILE *output; /* the output file */
+
+#define CHECK_SIZE_CODE(desired_size) \
+ if (e_code + (desired_size) >= l_code) { \
+ int nsize = l_code-s_code + 400 + desired_size; \
+ int code_len = e_code-s_code; \
+ codebuf = (char *) realloc(codebuf, nsize); \
+ if (codebuf == NULL) \
+ err(1, NULL); \
+ e_code = codebuf + code_len + 1; \
+ l_code = codebuf + nsize - 5; \
+ s_code = codebuf + 1; \
+ }
+#define CHECK_SIZE_COM(desired_size) \
+ if (e_com + (desired_size) >= l_com) { \
+ int nsize = l_com-s_com + 400 + desired_size; \
+ int com_len = e_com - s_com; \
+ int blank_pos; \
+ if (last_bl != NULL) \
+ blank_pos = last_bl - combuf; \
+ else \
+ blank_pos = -1; \
+ combuf = (char *) realloc(combuf, nsize); \
+ if (combuf == NULL) \
+ err(1, NULL); \
+ e_com = combuf + com_len + 1; \
+ if (blank_pos > 0) \
+ last_bl = combuf + blank_pos; \
+ l_com = combuf + nsize - 5; \
+ s_com = combuf + 1; \
+ }
+#define CHECK_SIZE_LAB(desired_size) \
+ if (e_lab + (desired_size) >= l_lab) { \
+ int nsize = l_lab-s_lab + 400 + desired_size; \
+ int label_len = e_lab - s_lab; \
+ labbuf = (char *) realloc(labbuf, nsize); \
+ if (labbuf == NULL) \
+ err(1, NULL); \
+ e_lab = labbuf + label_len + 1; \
+ l_lab = labbuf + nsize - 5; \
+ s_lab = labbuf + 1; \
+ }
+#define CHECK_SIZE_TOKEN(desired_size) \
+ if (e_token + (desired_size) >= l_token) { \
+ int nsize = l_token-s_token + 400 + desired_size; \
+ int token_len = e_token - s_token; \
+ tokenbuf = (char *) realloc(tokenbuf, nsize); \
+ if (tokenbuf == NULL) \
+ err(1, NULL); \
+ e_token = tokenbuf + token_len + 1; \
+ l_token = tokenbuf + nsize - 5; \
+ s_token = tokenbuf + 1; \
+ }
+
+extern char *labbuf; /* buffer for label */
+extern char *s_lab; /* start ... */
+extern char *e_lab; /* .. and end of stored label */
+extern char *l_lab; /* limit of label buffer */
+
+extern char *codebuf; /* buffer for code section */
+extern char *s_code; /* start ... */
+extern char *e_code; /* .. and end of stored code */
+extern char *l_code; /* limit of code section */
+
+extern char *combuf; /* buffer for comments */
+extern char *s_com; /* start ... */
+extern char *e_com; /* ... and end of stored comments */
+extern char *l_com; /* limit of comment buffer */
+
+#define token s_token
+extern char *tokenbuf; /* the last token scanned */
+extern char *s_token;
+extern char *e_token;
+extern char *l_token;
+
+extern char *in_buffer; /* input buffer */
+extern char *in_buffer_limit; /* the end of the input buffer */
+extern char *buf_ptr; /* ptr to next character to be taken
+ * from in_buffer */
+extern char *buf_end; /* ptr to first after last char in
+ * in_buffer */
+
+extern char sc_buf[sc_size]; /* input text is saved here when looking
+ * for the brace after an if, while, etc */
+extern char *save_com; /* start of the comment stored in
+ * sc_buf */
+extern char *sc_end; /* pointer into save_com buffer */
+
+extern char *bp_save; /* saved value of buf_ptr when taking
+ * input from save_com */
+extern char *be_save; /* similarly saved value of buf_end */
+
+
+struct options {
+ int blanklines_around_conditional_compilation;
+ int blanklines_after_declarations_at_proctop; /* this is vaguely
+ * similar to blanklines_after_decla except
+ * that in only applies to the first set of
+ * declarations in a procedure (just after
+ * the first '{') and it causes a blank line
+ * to be generated even if there are no
+ * declarations */
+ int blanklines_after_declarations;
+ int blanklines_after_procs;
+ int blanklines_before_blockcomments;
+ int leave_comma; /* if true, never break declarations after
+ * commas */
+ int btype_2; /* when true, brace should be on same line
+ * as if, while, etc */
+ int Bill_Shannon; /* true iff a blank should always be
+ * inserted after sizeof */
+ int comment_delimiter_on_blankline;
+ int decl_com_ind; /* the column in which comments after
+ * declarations should be put */
+ int cuddle_else; /* true if else should cuddle up to '}' */
+ int continuation_indent; /* set to the indentation between the
+ * edge of code and continuation lines */
+ float case_indent; /* The distance to indent case labels from the
+ * switch statement */
+ int com_ind; /* the column in which comments to the right
+ * of code should start */
+ int decl_indent; /* column to indent declared identifiers to */
+ int ljust_decl; /* true if declarations should be left
+ * justified */
+ int unindent_displace; /* comments not to the right of code
+ * will be placed this many
+ * indentation levels to the left of
+ * code */
+ int extra_expression_indent; /* true if continuation lines from
+ * the expression part of "if(e)",
+ * "while(e)", "for(e;e;e)" should be
+ * indented an extra tab stop so that they
+ * don't conflict with the code that follows */
+ int else_if; /* True iff else if pairs should be handled
+ * specially */
+ int function_brace_split; /* split function declaration and
+ * brace onto separate lines */
+ int format_col1_comments; /* If comments which start in column 1
+ * are to be magically reformatted (just
+ * like comments that begin in later columns) */
+ int format_block_comments; /* true if comments beginning with
+ * `/ * \n' are to be reformatted */
+ int indent_parameters;
+ int ind_size; /* the size of one indentation level */
+ int block_comment_max_col;
+ int local_decl_indent; /* like decl_indent but for locals */
+ int lineup_to_parens_always; /* if true, do not attempt to keep
+ * lined-up code within the margin */
+ int lineup_to_parens; /* if true, continued code within parens
+ * will be lined up to the open paren */
+ int pointer_as_binop; /* if true, the pointer dereference operator
+ * will be treated as a binary operator */
+ int proc_calls_space; /* If true, procedure calls look like:
+ * foo (bar) rather than foo(bar) */
+ int procnames_start_line; /* if true, the names of procedures
+ * being defined get placed in column 1 (ie.
+ * a newline is placed between the type of
+ * the procedure and its name) */
+ int space_after_cast; /* "b = (int) a" vs "b = (int)a" */
+ int star_comment_cont; /* true iff comment continuation lines
+ * should have stars at the beginning of
+ * each line. */
+ int swallow_optional_blanklines;
+ int auto_typedefs; /* set true to recognize identifiers
+ * ending in "_t" like typedefs */
+ int tabsize; /* the size of a tab */
+ int max_col; /* the maximum allowable line length */
+ int use_tabs; /* set true to use tabs for spacing, false
+ * uses all spaces */
+ int verbose; /* when true, non-essential error messages
+ * are printed */
+};
+extern struct options opt;
+
+extern int found_err;
+extern int n_real_blanklines;
+extern int prefix_blankline_requested;
+extern int postfix_blankline_requested;
+extern int break_comma; /* when true and not in parens, break after a
+ * comma */
+extern float case_ind; /* indentation level to be used for a "case
+ * n:" */
+extern int code_lines; /* count of lines with code */
+extern int had_eof; /* set to true when input is exhausted */
+extern int line_no; /* the current line number. */
+extern int inhibit_formatting; /* true if INDENT OFF is in effect */
+extern int suppress_blanklines;/* set iff following blanklines should be
+ * suppressed */
+
+#define STACKSIZE 256
+
+struct parser_state {
+ int last_token;
+ int p_stack[STACKSIZE]; /* this is the parsers stack */
+ int il[STACKSIZE]; /* this stack stores indentation levels */
+ float cstk[STACKSIZE];/* used to store case stmt indentation levels */
+ int box_com; /* set to true when we are in a "boxed"
+ * comment. In that case, the first non-blank
+ * char should be lined up with the / in / followed by * */
+ int comment_delta; /* used to set up indentation for all lines
+ * of a boxed comment after the first one */
+ int n_comment_delta;/* remembers how many columns there were
+ * before the start of a box comment so that
+ * forthcoming lines of the comment are
+ * indented properly */
+ int cast_mask; /* indicates which close parens potentially
+ * close off casts */
+ int not_cast_mask; /* indicates which close parens definitely
+ * close off something else than casts */
+ int block_init; /* true iff inside a block initialization */
+ int block_init_level; /* The level of brace nesting in an
+ * initialization */
+ int last_nl; /* this is true if the last thing scanned was
+ * a newline */
+ int in_or_st; /* Will be true iff there has been a
+ * declarator (e.g. int or char) and no left
+ * paren since the last semicolon. When true,
+ * a '{' is starting a structure definition or
+ * an initialization list */
+ int bl_line; /* set to 1 by dump_line if the line is blank */
+ int col_1; /* set to true if the last token started in
+ * column 1 */
+ int com_col; /* this is the column in which the current
+ * comment should start */
+ int com_lines; /* the number of lines with comments, set by
+ * dump_line */
+ int dec_nest; /* current nesting level for structure or init */
+ int decl_on_line; /* set to true if this line of code has part
+ * of a declaration on it */
+ int i_l_follow; /* the level to which ind_level should be set
+ * after the current line is printed */
+ int in_decl; /* set to true when we are in a declaration
+ * stmt. The processing of braces is then
+ * slightly different */
+ int in_stmt; /* set to 1 while in a stmt */
+ int ind_level; /* the current indentation level */
+ int ind_stmt; /* set to 1 if next line should have an extra
+ * indentation level because we are in the
+ * middle of a stmt */
+ int last_u_d; /* set to true after scanning a token which
+ * forces a following operator to be unary */
+ int out_coms; /* the number of comments processed, set by
+ * pr_comment */
+ int out_lines; /* the number of lines written, set by
+ * dump_line */
+ int p_l_follow; /* used to remember how to indent following
+ * statement */
+ int paren_level; /* parenthesization level. used to indent
+ * within statements */
+ short paren_indents[20]; /* column positions of each paren */
+ int pcase; /* set to 1 if the current line label is a
+ * case. It is printed differently from a
+ * regular label */
+ int search_brace; /* set to true by parse when it is necessary
+ * to buffer up all info up to the start of a
+ * stmt after an if, while, etc */
+ int use_ff; /* set to one if the current line should be
+ * terminated with a form feed */
+ int want_blank; /* set to true when the following token should
+ * be prefixed by a blank. (Said prefixing is
+ * ignored in some cases.) */
+ int keyword; /* the type of a keyword or 0 */
+ int dumped_decl_indent;
+ int in_parameter_declaration;
+ int tos; /* pointer to top of stack */
+ char procname[100]; /* The name of the current procedure */
+ int just_saw_decl;
+};
+
+extern struct parser_state ps;
+
+extern int ifdef_level;
+extern struct parser_state state_stack[5];
+extern struct parser_state match_state[5];
diff --git a/usr.bin/indent/io.c b/usr.bin/indent/io.c
new file mode 100644
index 000000000000..61b87c9343ce
--- /dev/null
+++ b/usr.bin/indent/io.c
@@ -0,0 +1,529 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "indent_globs.h"
+#include "indent.h"
+
+/* Globals */
+int found_err;
+int n_real_blanklines;
+int prefix_blankline_requested, postfix_blankline_requested;
+int code_lines;
+int had_eof;
+int inhibit_formatting;
+int suppress_blanklines;
+
+int comment_open;
+static int paren_target;
+static int pad_output(int current, int target);
+
+void
+dump_line(void)
+{ /* dump_line is the routine that actually
+ * effects the printing of the new source. It
+ * prints the label section, followed by the
+ * code section with the appropriate nesting
+ * level, followed by any comments */
+ int cur_col,
+ target_col = 1;
+ static int not_first_line;
+
+ if (ps.procname[0]) {
+ ps.ind_level = 0;
+ ps.procname[0] = 0;
+ }
+ if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
+ if (suppress_blanklines > 0)
+ suppress_blanklines--;
+ else {
+ ps.bl_line = true;
+ n_real_blanklines++;
+ }
+ }
+ else if (!inhibit_formatting) {
+ suppress_blanklines = 0;
+ ps.bl_line = false;
+ if (prefix_blankline_requested && not_first_line) {
+ if (opt.swallow_optional_blanklines) {
+ if (n_real_blanklines == 1)
+ n_real_blanklines = 0;
+ }
+ else {
+ if (n_real_blanklines == 0)
+ n_real_blanklines = 1;
+ }
+ }
+ while (--n_real_blanklines >= 0)
+ putc('\n', output);
+ n_real_blanklines = 0;
+ if (ps.ind_level == 0)
+ ps.ind_stmt = 0; /* this is a class A kludge. dont do
+ * additional statement indentation if we are
+ * at bracket level 0 */
+
+ if (e_lab != s_lab || e_code != s_code)
+ ++code_lines; /* keep count of lines with code */
+
+
+ if (e_lab != s_lab) { /* print lab, if any */
+ if (comment_open) {
+ comment_open = 0;
+ fprintf(output, ".*/\n");
+ }
+ while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
+ e_lab--;
+ *e_lab = '\0';
+ cur_col = pad_output(1, compute_label_target());
+ if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0
+ || strncmp(s_lab, "#endif", 6) == 0)) {
+ char *s = s_lab;
+ if (e_lab[-1] == '\n') e_lab--;
+ do putc(*s++, output);
+ while (s < e_lab && 'a' <= *s && *s<='z');
+ while ((*s == ' ' || *s == '\t') && s < e_lab)
+ s++;
+ if (s < e_lab)
+ fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */",
+ (int)(e_lab - s), s);
+ }
+ else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab);
+ cur_col = count_spaces(cur_col, s_lab);
+ }
+ else
+ cur_col = 1; /* there is no label section */
+
+ ps.pcase = false;
+
+ if (s_code != e_code) { /* print code section, if any */
+ char *p;
+
+ if (comment_open) {
+ comment_open = 0;
+ fprintf(output, ".*/\n");
+ }
+ target_col = compute_code_target();
+ {
+ int i;
+
+ for (i = 0; i < ps.p_l_follow; i++)
+ if (ps.paren_indents[i] >= 0)
+ ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
+ }
+ cur_col = pad_output(cur_col, target_col);
+ for (p = s_code; p < e_code; p++)
+ if (*p == (char) 0200)
+ fprintf(output, "%d", target_col * 7);
+ else
+ putc(*p, output);
+ cur_col = count_spaces(cur_col, s_code);
+ }
+ if (s_com != e_com) { /* print comment, if any */
+ int target = ps.com_col;
+ char *com_st = s_com;
+
+ target += ps.comment_delta;
+ while (*com_st == '\t') /* consider original indentation in
+ * case this is a box comment */
+ com_st++, target += opt.tabsize;
+ while (target <= 0)
+ if (*com_st == ' ')
+ target++, com_st++;
+ else if (*com_st == '\t') {
+ target = opt.tabsize * (1 + (target - 1) / opt.tabsize) + 1;
+ com_st++;
+ }
+ else
+ target = 1;
+ if (cur_col > target) { /* if comment can't fit on this line,
+ * put it on next line */
+ putc('\n', output);
+ cur_col = 1;
+ ++ps.out_lines;
+ }
+ while (e_com > com_st && isspace((unsigned char)e_com[-1]))
+ e_com--;
+ (void)pad_output(cur_col, target);
+ fwrite(com_st, e_com - com_st, 1, output);
+ ps.comment_delta = ps.n_comment_delta;
+ ++ps.com_lines; /* count lines with comments */
+ }
+ if (ps.use_ff)
+ putc('\014', output);
+ else
+ putc('\n', output);
+ ++ps.out_lines;
+ if (ps.just_saw_decl == 1 && opt.blanklines_after_declarations) {
+ prefix_blankline_requested = 1;
+ ps.just_saw_decl = 0;
+ }
+ else
+ prefix_blankline_requested = postfix_blankline_requested;
+ postfix_blankline_requested = 0;
+ }
+ ps.decl_on_line = ps.in_decl; /* if we are in the middle of a
+ * declaration, remember that fact for
+ * proper comment indentation */
+ ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be
+ * indented if we have not
+ * completed this stmt and if
+ * we are not in the middle of
+ * a declaration */
+ ps.use_ff = false;
+ ps.dumped_decl_indent = 0;
+ *(e_lab = s_lab) = '\0'; /* reset buffers */
+ *(e_code = s_code) = '\0';
+ *(e_com = s_com = combuf + 1) = '\0';
+ ps.ind_level = ps.i_l_follow;
+ ps.paren_level = ps.p_l_follow;
+ if (ps.paren_level > 0)
+ paren_target = -ps.paren_indents[ps.paren_level - 1];
+ not_first_line = 1;
+}
+
+int
+compute_code_target(void)
+{
+ int target_col = opt.ind_size * ps.ind_level + 1;
+
+ if (ps.paren_level)
+ if (!opt.lineup_to_parens)
+ target_col += opt.continuation_indent *
+ (2 * opt.continuation_indent == opt.ind_size ? 1 : ps.paren_level);
+ else if (opt.lineup_to_parens_always)
+ target_col = paren_target;
+ else {
+ int w;
+ int t = paren_target;
+
+ if ((w = count_spaces(t, s_code) - opt.max_col) > 0
+ && count_spaces(target_col, s_code) <= opt.max_col) {
+ t -= w + 1;
+ if (t > target_col)
+ target_col = t;
+ }
+ else
+ target_col = t;
+ }
+ else if (ps.ind_stmt)
+ target_col += opt.continuation_indent;
+ return target_col;
+}
+
+int
+compute_label_target(void)
+{
+ return
+ ps.pcase ? (int) (case_ind * opt.ind_size) + 1
+ : *s_lab == '#' ? 1
+ : opt.ind_size * (ps.ind_level - label_offset) + 1;
+}
+
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: fill_buffer
+ *
+ * FUNCTION: Reads one block of input into input_buffer
+ *
+ * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A
+ * Willcox of CAC Added check for switch back to partly full input
+ * buffer from temporary buffer
+ *
+ */
+void
+fill_buffer(void)
+{ /* this routine reads stuff from the input */
+ char *p;
+ int i;
+ FILE *f = input;
+
+ if (bp_save != NULL) { /* there is a partly filled input buffer left */
+ buf_ptr = bp_save; /* do not read anything, just switch buffers */
+ buf_end = be_save;
+ bp_save = be_save = NULL;
+ if (buf_ptr < buf_end)
+ return; /* only return if there is really something in
+ * this buffer */
+ }
+ for (p = in_buffer;;) {
+ if (p >= in_buffer_limit) {
+ int size = (in_buffer_limit - in_buffer) * 2 + 10;
+ int offset = p - in_buffer;
+ in_buffer = realloc(in_buffer, size);
+ if (in_buffer == NULL)
+ errx(1, "input line too long");
+ p = in_buffer + offset;
+ in_buffer_limit = in_buffer + size - 2;
+ }
+ if ((i = getc(f)) == EOF) {
+ *p++ = ' ';
+ *p++ = '\n';
+ had_eof = true;
+ break;
+ }
+ if (i != '\0')
+ *p++ = i;
+ if (i == '\n')
+ break;
+ }
+ buf_ptr = in_buffer;
+ buf_end = p;
+ if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') {
+ if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
+ fill_buffer(); /* flush indent error message */
+ else {
+ int com = 0;
+
+ p = in_buffer;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (*p == '/' && p[1] == '*') {
+ p += 2;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
+ && p[4] == 'N' && p[5] == 'T') {
+ p += 6;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (*p == '*')
+ com = 1;
+ else if (*p == 'O') {
+ if (*++p == 'N')
+ p++, com = 1;
+ else if (*p == 'F' && *++p == 'F')
+ p++, com = 2;
+ }
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
+ if (s_com != e_com || s_lab != e_lab || s_code != e_code)
+ dump_line();
+ if (!(inhibit_formatting = com - 1)) {
+ n_real_blanklines = 0;
+ postfix_blankline_requested = 0;
+ prefix_blankline_requested = 0;
+ suppress_blanklines = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (inhibit_formatting) {
+ p = in_buffer;
+ do
+ putc(*p, output);
+ while (*p++ != '\n');
+ }
+}
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: pad_output
+ *
+ * FUNCTION: Writes tabs and spaces to move the current column up to the desired
+ * position.
+ *
+ * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
+ *
+ * PARAMETERS: current integer The current column target
+ * nteger The desired column
+ *
+ * RETURNS: Integer value of the new column. (If current >= target, no action is
+ * taken, and current is returned.
+ *
+ * GLOBALS: None
+ *
+ * CALLS: write (sys)
+ *
+ * CALLED BY: dump_line
+ *
+ * HISTORY: initial coding November 1976 D A Willcox of CAC
+ *
+ */
+static int
+pad_output(int current, int target)
+ /* writes tabs and blanks (if necessary) to
+ * get the current output position up to the
+ * target column */
+ /* current: the current column value */
+ /* target: position we want it at */
+{
+ int curr; /* internal column pointer */
+
+ if (current >= target)
+ return (current); /* line is already long enough */
+ curr = current;
+ if (opt.use_tabs) {
+ int tcur;
+
+ while ((tcur = opt.tabsize * (1 + (curr - 1) / opt.tabsize) + 1) <= target) {
+ putc('\t', output);
+ curr = tcur;
+ }
+ }
+ while (curr++ < target)
+ putc(' ', output); /* pad with final blanks */
+
+ return (target);
+}
+
+/*
+ * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
+ *
+ * All rights reserved
+ *
+ *
+ * NAME: count_spaces
+ *
+ * FUNCTION: Find out where printing of a given string will leave the current
+ * character position on output.
+ *
+ * ALGORITHM: Run thru input string and add appropriate values to current
+ * position.
+ *
+ * RETURNS: Integer value of position after printing "buffer" starting in column
+ * "current".
+ *
+ * HISTORY: initial coding November 1976 D A Willcox of CAC
+ *
+ */
+int
+count_spaces_until(int cur, char *buffer, char *end)
+/*
+ * this routine figures out where the character position will be after
+ * printing the text in buffer starting at column "current"
+ */
+{
+ char *buf; /* used to look thru buffer */
+
+ for (buf = buffer; *buf != '\0' && buf != end; ++buf) {
+ switch (*buf) {
+
+ case '\n':
+ case 014: /* form feed */
+ cur = 1;
+ break;
+
+ case '\t':
+ cur = opt.tabsize * (1 + (cur - 1) / opt.tabsize) + 1;
+ break;
+
+ case 010: /* backspace */
+ --cur;
+ break;
+
+ default:
+ ++cur;
+ break;
+ } /* end of switch */
+ } /* end of for loop */
+ return (cur);
+}
+
+int
+count_spaces(int cur, char *buffer)
+{
+ return (count_spaces_until(cur, buffer, NULL));
+}
+
+void
+diag4(int level, const char *msg, int a, int b)
+{
+ if (level)
+ found_err = 1;
+ if (output == stdout) {
+ fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stdout, msg, a, b);
+ fprintf(stdout, " */\n");
+ }
+ else {
+ fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stderr, msg, a, b);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+diag3(int level, const char *msg, int a)
+{
+ if (level)
+ found_err = 1;
+ if (output == stdout) {
+ fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stdout, msg, a);
+ fprintf(stdout, " */\n");
+ }
+ else {
+ fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stderr, msg, a);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+diag2(int level, const char *msg)
+{
+ if (level)
+ found_err = 1;
+ if (output == stdout) {
+ fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stdout, "%s", msg);
+ fprintf(stdout, " */\n");
+ }
+ else {
+ fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
+ fprintf(stderr, "%s", msg);
+ fprintf(stderr, "\n");
+ }
+}
+
diff --git a/usr.bin/indent/lexi.c b/usr.bin/indent/lexi.c
new file mode 100644
index 000000000000..7883b7c53f36
--- /dev/null
+++ b/usr.bin/indent/lexi.c
@@ -0,0 +1,647 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * Here we have the token scanner for indent. It scans off one token and puts
+ * it in the global variable "token". It returns a code, indicating the type
+ * of token scanned.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "indent_globs.h"
+#include "indent_codes.h"
+#include "indent.h"
+
+struct templ {
+ const char *rwd;
+ int rwcode;
+};
+
+/*
+ * This table has to be sorted alphabetically, because it'll be used in binary
+ * search. For the same reason, string must be the first thing in struct templ.
+ */
+struct templ specials[] =
+{
+ {"_Bool", 4},
+ {"_Complex", 4},
+ {"_Imaginary", 4},
+ {"auto", 10},
+ {"bool", 4},
+ {"break", 9},
+ {"case", 8},
+ {"char", 4},
+ {"complex", 4},
+ {"const", 4},
+ {"continue", 12},
+ {"default", 8},
+ {"do", 6},
+ {"double", 4},
+ {"else", 6},
+ {"enum", 3},
+ {"extern", 10},
+ {"float", 4},
+ {"for", 5},
+ {"global", 4},
+ {"goto", 9},
+ {"if", 5},
+ {"imaginary", 4},
+ {"inline", 12},
+ {"int", 4},
+ {"long", 4},
+ {"offsetof", 1},
+ {"register", 10},
+ {"restrict", 12},
+ {"return", 9},
+ {"short", 4},
+ {"signed", 4},
+ {"sizeof", 2},
+ {"static", 10},
+ {"struct", 3},
+ {"switch", 7},
+ {"typedef", 11},
+ {"union", 3},
+ {"unsigned", 4},
+ {"void", 4},
+ {"volatile", 4},
+ {"while", 5}
+};
+
+const char **typenames;
+int typename_count;
+int typename_top = -1;
+
+/*
+ * The transition table below was rewritten by hand from lx's output, given
+ * the following definitions. lx is Katherine Flavel's lexer generator.
+ *
+ * O = /[0-7]/; D = /[0-9]/; NZ = /[1-9]/;
+ * H = /[a-f0-9]/i; B = /[0-1]/; HP = /0x/i;
+ * BP = /0b/i; E = /e[+\-]?/i D+; P = /p[+\-]?/i D+;
+ * FS = /[fl]/i; IS = /u/i /(l|L|ll|LL)/? | /(l|L|ll|LL)/ /u/i?;
+ *
+ * D+ E FS? -> $float;
+ * D* "." D+ E? FS? -> $float;
+ * D+ "." E? FS? -> $float; HP H+ IS? -> $int;
+ * HP H+ P FS? -> $float; NZ D* IS? -> $int;
+ * HP H* "." H+ P FS? -> $float; "0" O* IS? -> $int;
+ * HP H+ "." P FS -> $float; BP B+ IS? -> $int;
+ */
+static char const *table[] = {
+ /* examples:
+ 00
+ s 0xx
+ t 00xaa
+ a 11 101100xxa..
+ r 11ee0001101lbuuxx.a.pp
+ t.01.e+008bLuxll0Ll.aa.p+0
+ states: ABCDEFGHIJKLMNOPQRSTUVWXYZ */
+ ['0'] = "CEIDEHHHIJQ U Q VUVVZZZ",
+ ['1'] = "DEIDEHHHIJQ U Q VUVVZZZ",
+ ['7'] = "DEIDEHHHIJ U VUVVZZZ",
+ ['9'] = "DEJDEHHHJJ U VUVVZZZ",
+ ['a'] = " U VUVV ",
+ ['b'] = " K U VUVV ",
+ ['e'] = " FFF FF U VUVV ",
+ ['f'] = " f f U VUVV f",
+ ['u'] = " MM M i iiM M ",
+ ['x'] = " N ",
+ ['p'] = " FFX ",
+ ['L'] = " LLf fL PR Li L f",
+ ['l'] = " OOf fO S P O i O f",
+ ['+'] = " G Y ",
+ ['.'] = "B EE EE T W ",
+ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */
+ [0] = "uuiifuufiuuiiuiiiiiuiuuuuu",
+};
+
+static int
+strcmp_type(const void *e1, const void *e2)
+{
+ return (strcmp(e1, *(const char * const *)e2));
+}
+
+int
+lexi(struct parser_state *state)
+{
+ int unary_delim; /* this is set to 1 if the current token
+ * forces a following operator to be unary */
+ int code; /* internal code to be returned */
+ char qchar; /* the delimiter character for a string */
+
+ e_token = s_token; /* point to start of place to save token */
+ unary_delim = false;
+ state->col_1 = state->last_nl; /* tell world that this token started
+ * in column 1 iff the last thing
+ * scanned was a newline */
+ state->last_nl = false;
+
+ while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
+ state->col_1 = false; /* leading blanks imply token is not in column
+ * 1 */
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ }
+
+ /* Scan an alphanumeric token */
+ if (isalnum((unsigned char)*buf_ptr) ||
+ *buf_ptr == '_' || *buf_ptr == '$' ||
+ (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
+ /*
+ * we have a character or number
+ */
+ struct templ *p;
+
+ if (isdigit((unsigned char)*buf_ptr) ||
+ (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
+ char s;
+ unsigned char i;
+
+ for (s = 'A'; s != 'f' && s != 'i' && s != 'u'; ) {
+ i = (unsigned char)*buf_ptr;
+ if (i >= nitems(table) || table[i] == NULL ||
+ table[i][s - 'A'] == ' ') {
+ s = table[0][s - 'A'];
+ break;
+ }
+ s = table[i][s - 'A'];
+ CHECK_SIZE_TOKEN(1);
+ *e_token++ = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ /* s now indicates the type: f(loating), i(integer), u(nknown) */
+ }
+ else
+ while (isalnum((unsigned char)*buf_ptr) ||
+ *buf_ptr == BACKSLASH ||
+ *buf_ptr == '_' || *buf_ptr == '$') {
+ /* fill_buffer() terminates buffer with newline */
+ if (*buf_ptr == BACKSLASH) {
+ if (*(buf_ptr + 1) == '\n') {
+ buf_ptr += 2;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ } else
+ break;
+ }
+ CHECK_SIZE_TOKEN(1);
+ /* copy it over */
+ *e_token++ = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ *e_token = '\0';
+
+ if (s_token[0] == 'L' && s_token[1] == '\0' &&
+ (*buf_ptr == '"' || *buf_ptr == '\''))
+ return (strpfx);
+
+ while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ state->keyword = 0;
+ if (state->last_token == structure && !state->p_l_follow) {
+ /* if last token was 'struct' and we're not
+ * in parentheses, then this token
+ * should be treated as a declaration */
+ state->last_u_d = true;
+ return (decl);
+ }
+ /*
+ * Operator after identifier is binary unless last token was 'struct'
+ */
+ state->last_u_d = (state->last_token == structure);
+
+ p = bsearch(s_token,
+ specials,
+ sizeof(specials) / sizeof(specials[0]),
+ sizeof(specials[0]),
+ strcmp_type);
+ if (p == NULL) { /* not a special keyword... */
+ char *u;
+
+ /* ... so maybe a type_t or a typedef */
+ if ((opt.auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
+ strcmp(u, "_t") == 0) || (typename_top >= 0 &&
+ bsearch(s_token, typenames, typename_top + 1,
+ sizeof(typenames[0]), strcmp_type))) {
+ state->keyword = 4; /* a type name */
+ state->last_u_d = true;
+ goto found_typename;
+ }
+ } else { /* we have a keyword */
+ state->keyword = p->rwcode;
+ state->last_u_d = true;
+ switch (p->rwcode) {
+ case 7: /* it is a switch */
+ return (swstmt);
+ case 8: /* a case or default */
+ return (casestmt);
+
+ case 3: /* a "struct" */
+ /* FALLTHROUGH */
+ case 4: /* one of the declaration keywords */
+ found_typename:
+ if (state->p_l_follow) {
+ /* inside parens: cast, param list, offsetof or sizeof */
+ state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
+ }
+ if (state->last_token == period || state->last_token == unary_op) {
+ state->keyword = 0;
+ break;
+ }
+ if (p != NULL && p->rwcode == 3)
+ return (structure);
+ if (state->p_l_follow)
+ break;
+ return (decl);
+
+ case 5: /* if, while, for */
+ return (sp_paren);
+
+ case 6: /* do, else */
+ return (sp_nparen);
+
+ case 10: /* storage class specifier */
+ return (storage);
+
+ case 11: /* typedef */
+ return (type_def);
+
+ default: /* all others are treated like any other
+ * identifier */
+ return (ident);
+ } /* end of switch */
+ } /* end of if (found_it) */
+ if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
+ state->in_parameter_declaration == 0 && state->block_init == 0) {
+ char *tp = buf_ptr;
+ while (tp < buf_end)
+ if (*tp++ == ')' && (*tp == ';' || *tp == ','))
+ goto not_proc;
+ strncpy(state->procname, token, sizeof state->procname - 1);
+ if (state->in_decl)
+ state->in_parameter_declaration = 1;
+ return (funcname);
+ not_proc:;
+ }
+ /*
+ * The following hack attempts to guess whether or not the current
+ * token is in fact a declaration keyword -- one that has been
+ * typedefd
+ */
+ else if (!state->p_l_follow && !state->block_init &&
+ !state->in_stmt &&
+ ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
+ isalpha((unsigned char)*buf_ptr)) &&
+ (state->last_token == semicolon || state->last_token == lbrace ||
+ state->last_token == rbrace)) {
+ state->keyword = 4; /* a type name */
+ state->last_u_d = true;
+ return decl;
+ }
+ if (state->last_token == decl) /* if this is a declared variable,
+ * then following sign is unary */
+ state->last_u_d = true; /* will make "int a -1" work */
+ return (ident); /* the ident is not in the list */
+ } /* end of processing for alpanum character */
+
+ /* Scan a non-alphanumeric token */
+
+ CHECK_SIZE_TOKEN(3); /* things like "<<=" */
+ *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
+ * moved here */
+ *e_token = '\0';
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+
+ switch (*token) {
+ case '\n':
+ unary_delim = state->last_u_d;
+ state->last_nl = true; /* remember that we just had a newline */
+ code = (had_eof ? 0 : newline);
+
+ /*
+ * if data has been exhausted, the newline is a dummy, and we should
+ * return code to stop
+ */
+ break;
+
+ case '\'': /* start of quoted character */
+ case '"': /* start of string */
+ qchar = *token;
+ do { /* copy the string */
+ while (1) { /* move one character or [/<char>]<char> */
+ if (*buf_ptr == '\n') {
+ diag2(1, "Unterminated literal");
+ goto stop_lit;
+ }
+ CHECK_SIZE_TOKEN(2);
+ *e_token = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ if (*e_token == BACKSLASH) { /* if escape, copy extra char */
+ if (*buf_ptr == '\n') /* check for escaped newline */
+ ++line_no;
+ *++e_token = *buf_ptr++;
+ ++e_token; /* we must increment this again because we
+ * copied two chars */
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ else
+ break; /* we copied one character */
+ } /* end of while (1) */
+ } while (*e_token++ != qchar);
+stop_lit:
+ code = ident;
+ break;
+
+ case ('('):
+ case ('['):
+ unary_delim = true;
+ code = lparen;
+ break;
+
+ case (')'):
+ case (']'):
+ code = rparen;
+ break;
+
+ case '#':
+ unary_delim = state->last_u_d;
+ code = preesc;
+ break;
+
+ case '?':
+ unary_delim = true;
+ code = question;
+ break;
+
+ case (':'):
+ code = colon;
+ unary_delim = true;
+ break;
+
+ case (';'):
+ unary_delim = true;
+ code = semicolon;
+ break;
+
+ case ('{'):
+ unary_delim = true;
+
+ /*
+ * if (state->in_or_st) state->block_init = 1;
+ */
+ /* ? code = state->block_init ? lparen : lbrace; */
+ code = lbrace;
+ break;
+
+ case ('}'):
+ unary_delim = true;
+ /* ? code = state->block_init ? rparen : rbrace; */
+ code = rbrace;
+ break;
+
+ case 014: /* a form feed */
+ unary_delim = state->last_u_d;
+ state->last_nl = true; /* remember this so we can set 'state->col_1'
+ * right */
+ code = form_feed;
+ break;
+
+ case (','):
+ unary_delim = true;
+ code = comma;
+ break;
+
+ case '.':
+ unary_delim = false;
+ code = period;
+ break;
+
+ case '-':
+ case '+': /* check for -, +, --, ++ */
+ code = (state->last_u_d ? unary_op : binary_op);
+ unary_delim = true;
+
+ if (*buf_ptr == token[0]) {
+ /* check for doubled character */
+ *e_token++ = *buf_ptr++;
+ /* buffer overflow will be checked at end of loop */
+ if (state->last_token == ident || state->last_token == rparen) {
+ code = (state->last_u_d ? unary_op : postop);
+ /* check for following ++ or -- */
+ unary_delim = false;
+ }
+ }
+ else if (*buf_ptr == '=')
+ /* check for operator += */
+ *e_token++ = *buf_ptr++;
+ else if (*buf_ptr == '>') {
+ /* check for operator -> */
+ *e_token++ = *buf_ptr++;
+ if (!opt.pointer_as_binop) {
+ unary_delim = false;
+ code = unary_op;
+ state->want_blank = false;
+ }
+ }
+ break; /* buffer overflow will be checked at end of
+ * switch */
+
+ case '=':
+ if (state->in_or_st)
+ state->block_init = 1;
+ if (*buf_ptr == '=') {/* == */
+ *e_token++ = '='; /* Flip =+ to += */
+ buf_ptr++;
+ *e_token = 0;
+ }
+ code = binary_op;
+ unary_delim = true;
+ break;
+ /* can drop thru!!! */
+
+ case '>':
+ case '<':
+ case '!': /* ops like <, <<, <=, !=, etc */
+ if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
+ *e_token++ = *buf_ptr;
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ if (*buf_ptr == '=')
+ *e_token++ = *buf_ptr++;
+ code = (state->last_u_d ? unary_op : binary_op);
+ unary_delim = true;
+ break;
+
+ case '*':
+ unary_delim = true;
+ if (!state->last_u_d) {
+ if (*buf_ptr == '=')
+ *e_token++ = *buf_ptr++;
+ code = binary_op;
+ break;
+ }
+ while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
+ if (*buf_ptr == '*') {
+ CHECK_SIZE_TOKEN(1);
+ *e_token++ = *buf_ptr;
+ }
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ if (ps.in_decl) {
+ char *tp = buf_ptr;
+
+ while (isalpha((unsigned char)*tp) ||
+ isspace((unsigned char)*tp)) {
+ if (++tp >= buf_end)
+ fill_buffer();
+ }
+ if (*tp == '(')
+ ps.procname[0] = ' ';
+ }
+ code = unary_op;
+ break;
+
+ default:
+ if (token[0] == '/' && *buf_ptr == '*') {
+ /* it is start of comment */
+ *e_token++ = '*';
+
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+
+ code = comment;
+ unary_delim = state->last_u_d;
+ break;
+ }
+ while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
+ /*
+ * handle ||, &&, etc, and also things as in int *****i
+ */
+ CHECK_SIZE_TOKEN(1);
+ *e_token++ = *buf_ptr;
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ }
+ code = (state->last_u_d ? unary_op : binary_op);
+ unary_delim = true;
+
+
+ } /* end of switch */
+ if (buf_ptr >= buf_end) /* check for input buffer empty */
+ fill_buffer();
+ state->last_u_d = unary_delim;
+ CHECK_SIZE_TOKEN(1);
+ *e_token = '\0'; /* null terminate the token */
+ return (code);
+}
+
+/* Initialize constant transition table */
+void
+init_constant_tt(void)
+{
+ table['-'] = table['+'];
+ table['8'] = table['9'];
+ table['2'] = table['3'] = table['4'] = table['5'] = table['6'] = table['7'];
+ table['A'] = table['C'] = table['D'] = table['c'] = table['d'] = table['a'];
+ table['B'] = table['b'];
+ table['E'] = table['e'];
+ table['U'] = table['u'];
+ table['X'] = table['x'];
+ table['P'] = table['p'];
+ table['F'] = table['f'];
+}
+
+void
+alloc_typenames(void)
+{
+
+ typenames = (const char **)malloc(sizeof(typenames[0]) *
+ (typename_count = 16));
+ if (typenames == NULL)
+ err(1, NULL);
+}
+
+void
+add_typename(const char *key)
+{
+ int comparison;
+ const char *copy;
+
+ if (typename_top + 1 >= typename_count) {
+ typenames = realloc((void *)typenames,
+ sizeof(typenames[0]) * (typename_count *= 2));
+ if (typenames == NULL)
+ err(1, NULL);
+ }
+ if (typename_top == -1)
+ typenames[++typename_top] = copy = strdup(key);
+ else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
+ /* take advantage of sorted input */
+ if (comparison == 0) /* remove duplicates */
+ return;
+ typenames[++typename_top] = copy = strdup(key);
+ }
+ else {
+ int p;
+
+ for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
+ /* find place for the new key */;
+ if (comparison == 0) /* remove duplicates */
+ return;
+ memmove(&typenames[p + 1], &typenames[p],
+ sizeof(typenames[0]) * (++typename_top - p));
+ typenames[p] = copy = strdup(key);
+ }
+
+ if (copy == NULL)
+ err(1, NULL);
+}
diff --git a/usr.bin/indent/parse.c b/usr.bin/indent/parse.c
new file mode 100644
index 000000000000..4434e9b01c16
--- /dev/null
+++ b/usr.bin/indent/parse.c
@@ -0,0 +1,341 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+#include <err.h>
+#include <stdio.h>
+#include "indent_globs.h"
+#include "indent_codes.h"
+#include "indent.h"
+
+/* Globals */
+int break_comma;
+float case_ind;
+
+static void reduce(void);
+
+void
+parse(int tk) /* tk: the code for the construct scanned */
+{
+ int i;
+
+#ifdef debug
+ printf("%2d - %s\n", tk, token);
+#endif
+
+ while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
+ /* true if we have an if without an else */
+ ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt
+ * reduction */
+ reduce(); /* see if this allows any reduction */
+ }
+
+
+ switch (tk) { /* go on and figure out what to do with the
+ * input */
+
+ case decl: /* scanned a declaration word */
+ ps.search_brace = opt.btype_2;
+ /* indicate that following brace should be on same line */
+ if (ps.p_stack[ps.tos] != decl) { /* only put one declaration
+ * onto stack */
+ break_comma = true; /* while in declaration, newline should be
+ * forced after comma */
+ ps.p_stack[++ps.tos] = decl;
+ ps.il[ps.tos] = ps.i_l_follow;
+
+ if (opt.ljust_decl) {/* only do if we want left justified
+ * declarations */
+ ps.ind_level = 0;
+ for (i = ps.tos - 1; i > 0; --i)
+ if (ps.p_stack[i] == decl)
+ ++ps.ind_level; /* indentation is number of
+ * declaration levels deep we are */
+ ps.i_l_follow = ps.ind_level;
+ }
+ }
+ break;
+
+ case ifstmt: /* scanned if (...) */
+ if (ps.p_stack[ps.tos] == elsehead && opt.else_if) /* "else if ..." */
+ /*
+ * Note that the stack pointer here is decremented, effectively
+ * reducing "else if" to "if". This saves a lot of stack space
+ * in case of a long "if-else-if ... else-if" sequence.
+ */
+ ps.i_l_follow = ps.il[ps.tos--];
+ /* the rest is the same as for dolit and forstmt */
+ /* FALLTHROUGH */
+ case dolit: /* 'do' */
+ case forstmt: /* for (...) */
+ ps.p_stack[++ps.tos] = tk;
+ ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
+ ++ps.i_l_follow; /* subsequent statements should be indented 1 */
+ ps.search_brace = opt.btype_2;
+ break;
+
+ case lbrace: /* scanned { */
+ break_comma = false; /* don't break comma in an initial list */
+ if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
+ || ps.p_stack[ps.tos] == stmtl)
+ ++ps.i_l_follow; /* it is a random, isolated stmt group or a
+ * declaration */
+ else {
+ if (s_code == e_code) {
+ /*
+ * only do this if there is nothing on the line
+ */
+ --ps.ind_level;
+ /*
+ * it is a group as part of a while, for, etc.
+ */
+ if (ps.p_stack[ps.tos] == swstmt && opt.case_indent >= 1)
+ --ps.ind_level;
+ /*
+ * for a switch, brace should be two levels out from the code
+ */
+ }
+ }
+
+ ps.p_stack[++ps.tos] = lbrace;
+ ps.il[ps.tos] = ps.ind_level;
+ ps.p_stack[++ps.tos] = stmt;
+ /* allow null stmt between braces */
+ ps.il[ps.tos] = ps.i_l_follow;
+ break;
+
+ case whilestmt: /* scanned while (...) */
+ if (ps.p_stack[ps.tos] == dohead) {
+ /* it is matched with do stmt */
+ ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
+ ps.p_stack[++ps.tos] = whilestmt;
+ ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
+ }
+ else { /* it is a while loop */
+ ps.p_stack[++ps.tos] = whilestmt;
+ ps.il[ps.tos] = ps.i_l_follow;
+ ++ps.i_l_follow;
+ ps.search_brace = opt.btype_2;
+ }
+
+ break;
+
+ case elselit: /* scanned an else */
+
+ if (ps.p_stack[ps.tos] != ifhead)
+ diag2(1, "Unmatched 'else'");
+ else {
+ ps.ind_level = ps.il[ps.tos]; /* indentation for else should
+ * be same as for if */
+ ps.i_l_follow = ps.ind_level + 1; /* everything following should
+ * be in 1 level */
+ ps.p_stack[ps.tos] = elsehead;
+ /* remember if with else */
+ ps.search_brace = opt.btype_2 | opt.else_if;
+ }
+ break;
+
+ case rbrace: /* scanned a } */
+ /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
+ if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) {
+ ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
+ ps.p_stack[ps.tos] = stmt;
+ }
+ else
+ diag2(1, "Statement nesting error");
+ break;
+
+ case swstmt: /* had switch (...) */
+ ps.p_stack[++ps.tos] = swstmt;
+ ps.cstk[ps.tos] = case_ind;
+ /* save current case indent level */
+ ps.il[ps.tos] = ps.i_l_follow;
+ case_ind = ps.i_l_follow + opt.case_indent; /* cases should be one
+ * level down from
+ * switch */
+ ps.i_l_follow += opt.case_indent + 1; /* statements should be two
+ * levels in */
+ ps.search_brace = opt.btype_2;
+ break;
+
+ case semicolon: /* this indicates a simple stmt */
+ break_comma = false; /* turn off flag to break after commas in a
+ * declaration */
+ ps.p_stack[++ps.tos] = stmt;
+ ps.il[ps.tos] = ps.ind_level;
+ break;
+
+ default: /* this is an error */
+ diag2(1, "Unknown code to parser");
+ return;
+
+
+ } /* end of switch */
+
+ if (ps.tos >= STACKSIZE - 1)
+ errx(1, "Parser stack overflow");
+
+ reduce(); /* see if any reduction can be done */
+
+#ifdef debug
+ for (i = 1; i <= ps.tos; ++i)
+ printf("(%d %d)", ps.p_stack[i], ps.il[i]);
+ printf("\n");
+#endif
+
+ return;
+}
+
+/*
+ * NAME: reduce
+ *
+ * FUNCTION: Implements the reduce part of the parsing algorithm
+ *
+ * ALGORITHM: The following reductions are done. Reductions are repeated
+ * until no more are possible.
+ *
+ * Old TOS New TOS
+ * <stmt> <stmt> <stmtl>
+ * <stmtl> <stmt> <stmtl>
+ * do <stmt> "dostmt"
+ * if <stmt> "ifstmt"
+ * switch <stmt> <stmt>
+ * decl <stmt> <stmt>
+ * "ifelse" <stmt> <stmt>
+ * for <stmt> <stmt>
+ * while <stmt> <stmt>
+ * "dostmt" while <stmt>
+ *
+ * On each reduction, ps.i_l_follow (the indentation for the following line)
+ * is set to the indentation level associated with the old TOS.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNS: Nothing
+ *
+ * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
+ *
+ * CALLS: None
+ *
+ * CALLED BY: parse
+ *
+ * HISTORY: initial coding November 1976 D A Willcox of CAC
+ *
+ */
+/*----------------------------------------------*\
+| REDUCTION PHASE |
+\*----------------------------------------------*/
+static void
+reduce(void)
+{
+ int i;
+
+ for (;;) { /* keep looping until there is nothing left to
+ * reduce */
+
+ switch (ps.p_stack[ps.tos]) {
+
+ case stmt:
+ switch (ps.p_stack[ps.tos - 1]) {
+
+ case stmt:
+ case stmtl:
+ /* stmtl stmt or stmt stmt */
+ ps.p_stack[--ps.tos] = stmtl;
+ break;
+
+ case dolit: /* <do> <stmt> */
+ ps.p_stack[--ps.tos] = dohead;
+ ps.i_l_follow = ps.il[ps.tos];
+ break;
+
+ case ifstmt:
+ /* <if> <stmt> */
+ ps.p_stack[--ps.tos] = ifhead;
+ for (i = ps.tos - 1;
+ (
+ ps.p_stack[i] != stmt
+ &&
+ ps.p_stack[i] != stmtl
+ &&
+ ps.p_stack[i] != lbrace
+ );
+ --i);
+ ps.i_l_follow = ps.il[i];
+ /*
+ * for the time being, we will assume that there is no else on
+ * this if, and set the indentation level accordingly. If an
+ * else is scanned, it will be fixed up later
+ */
+ break;
+
+ case swstmt:
+ /* <switch> <stmt> */
+ case_ind = ps.cstk[ps.tos - 1];
+ /* FALLTHROUGH */
+ case decl: /* finish of a declaration */
+ case elsehead:
+ /* <<if> <stmt> else> <stmt> */
+ case forstmt:
+ /* <for> <stmt> */
+ case whilestmt:
+ /* <while> <stmt> */
+ ps.p_stack[--ps.tos] = stmt;
+ ps.i_l_follow = ps.il[ps.tos];
+ break;
+
+ default: /* <anything else> <stmt> */
+ return;
+
+ } /* end of section for <stmt> on top of stack */
+ break;
+
+ case whilestmt: /* while (...) on top */
+ if (ps.p_stack[ps.tos - 1] == dohead) {
+ /* it is termination of a do while */
+ ps.tos -= 2;
+ break;
+ }
+ else
+ return;
+
+ default: /* anything else on top */
+ return;
+
+ }
+ }
+}
diff --git a/usr.bin/indent/pr_comment.c b/usr.bin/indent/pr_comment.c
new file mode 100644
index 000000000000..c9de7c2ccfe4
--- /dev/null
+++ b/usr.bin/indent/pr_comment.c
@@ -0,0 +1,347 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1985 Sun Microsystems, Inc.
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "indent_globs.h"
+#include "indent_codes.h"
+#include "indent.h"
+/*
+ * NAME:
+ * pr_comment
+ *
+ * FUNCTION:
+ * This routine takes care of scanning and printing comments.
+ *
+ * ALGORITHM:
+ * 1) Decide where the comment should be aligned, and if lines should
+ * be broken.
+ * 2) If lines should not be broken and filled, just copy up to end of
+ * comment.
+ * 3) If lines should be filled, then scan thru input_buffer copying
+ * characters to com_buf. Remember where the last blank, tab, or
+ * newline was. When line is filled, print up to last blank and
+ * continue copying.
+ *
+ * HISTORY:
+ * November 1976 D A Willcox of CAC Initial coding
+ * 12/6/76 D A Willcox of CAC Modification to handle
+ * UNIX-style comments
+ *
+ */
+
+/*
+ * this routine processes comments. It makes an attempt to keep comments from
+ * going over the max line length. If a line is too long, it moves everything
+ * from the last blank to the next comment line. Blanks and tabs from the
+ * beginning of the input line are removed
+ */
+
+void
+pr_comment(void)
+{
+ int now_col; /* column we are in now */
+ int adj_max_col; /* Adjusted max_col for when we decide to
+ * spill comments over the right margin */
+ char *last_bl; /* points to the last blank in the output
+ * buffer */
+ char *t_ptr; /* used for moving string */
+ int break_delim = opt.comment_delimiter_on_blankline;
+ int l_just_saw_decl = ps.just_saw_decl;
+
+ adj_max_col = opt.max_col;
+ ps.just_saw_decl = 0;
+ last_bl = NULL; /* no blanks found so far */
+ ps.box_com = false; /* at first, assume that we are not in
+ * a boxed comment or some other
+ * comment that should not be touched */
+ ++ps.out_coms; /* keep track of number of comments */
+
+ /* Figure where to align and how to treat the comment */
+
+ if (ps.col_1 && !opt.format_col1_comments) { /* if comment starts in column
+ * 1 it should not be touched */
+ ps.box_com = true;
+ break_delim = false;
+ ps.com_col = 1;
+ }
+ else {
+ if (*buf_ptr == '-' || *buf_ptr == '*' ||
+ (*buf_ptr == '\n' && !opt.format_block_comments)) {
+ ps.box_com = true; /* A comment with a '-' or '*' immediately
+ * after the /+* is assumed to be a boxed
+ * comment. A comment with a newline
+ * immediately after the /+* is assumed to
+ * be a block comment and is treated as a
+ * box comment unless format_block_comments
+ * is nonzero (the default). */
+ break_delim = false;
+ }
+ if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) {
+ /* klg: check only if this line is blank */
+ /*
+ * If this (*and previous lines are*) blank, dont put comment way
+ * out at left
+ */
+ ps.com_col = (ps.ind_level - opt.unindent_displace) * opt.ind_size + 1;
+ adj_max_col = opt.block_comment_max_col;
+ if (ps.com_col <= 1)
+ ps.com_col = 1 + !opt.format_col1_comments;
+ }
+ else {
+ int target_col;
+ break_delim = false;
+ if (s_code != e_code)
+ target_col = count_spaces(compute_code_target(), s_code);
+ else {
+ target_col = 1;
+ if (s_lab != e_lab)
+ target_col = count_spaces(compute_label_target(), s_lab);
+ }
+ ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? opt.decl_com_ind : opt.com_ind;
+ if (ps.com_col <= target_col)
+ ps.com_col = opt.tabsize * (1 + (target_col - 1) / opt.tabsize) + 1;
+ if (ps.com_col + 24 > adj_max_col)
+ adj_max_col = ps.com_col + 24;
+ }
+ }
+ if (ps.box_com) {
+ /*
+ * Find out how much indentation there was originally, because that
+ * much will have to be ignored by pad_output() in dump_line(). This
+ * is a box comment, so nothing changes -- not even indentation.
+ *
+ * The comment we're about to read usually comes from in_buffer,
+ * unless it has been copied into save_com.
+ */
+ char *start;
+
+ start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ?
+ sc_buf : in_buffer;
+ ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2);
+ }
+ else {
+ ps.n_comment_delta = 0;
+ while (*buf_ptr == ' ' || *buf_ptr == '\t')
+ buf_ptr++;
+ }
+ ps.comment_delta = 0;
+ *e_com++ = '/'; /* put '/' followed by '*' into buffer */
+ *e_com++ = '*';
+ if (*buf_ptr != ' ' && !ps.box_com)
+ *e_com++ = ' ';
+
+ /*
+ * Don't put a break delimiter if this is a one-liner that won't wrap.
+ */
+ if (break_delim)
+ for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) {
+ if (t_ptr >= buf_end)
+ fill_buffer();
+ if (t_ptr[0] == '*' && t_ptr[1] == '/') {
+ if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2))
+ break_delim = false;
+ break;
+ }
+ }
+
+ if (break_delim) {
+ char *t = e_com;
+ e_com = s_com + 2;
+ *e_com = 0;
+ if (opt.blanklines_before_blockcomments && ps.last_token != lbrace)
+ prefix_blankline_requested = 1;
+ dump_line();
+ e_com = s_com = t;
+ if (!ps.box_com && opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ }
+
+ /* Start to copy the comment */
+
+ while (1) { /* this loop will go until the comment is
+ * copied */
+ switch (*buf_ptr) { /* this checks for various spcl cases */
+ case 014: /* check for a form feed */
+ CHECK_SIZE_COM(3);
+ if (!ps.box_com) { /* in a text comment, break the line here */
+ ps.use_ff = true;
+ /* fix so dump_line uses a form feed */
+ dump_line();
+ last_bl = NULL;
+ if (!ps.box_com && opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ while (*++buf_ptr == ' ' || *buf_ptr == '\t')
+ ;
+ }
+ else {
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ *e_com++ = 014;
+ }
+ break;
+
+ case '\n':
+ if (had_eof) { /* check for unexpected eof */
+ printf("Unterminated comment\n");
+ dump_line();
+ return;
+ }
+ last_bl = NULL;
+ CHECK_SIZE_COM(4);
+ if (ps.box_com || ps.last_nl) { /* if this is a boxed comment,
+ * we dont ignore the newline */
+ if (s_com == e_com)
+ *e_com++ = ' ';
+ if (!ps.box_com && e_com - s_com > 3) {
+ dump_line();
+ if (opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ }
+ dump_line();
+ if (!ps.box_com && opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ }
+ else {
+ ps.last_nl = 1;
+ if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t')
+ last_bl = e_com - 1;
+ /*
+ * if there was a space at the end of the last line, remember
+ * where it was
+ */
+ else { /* otherwise, insert one */
+ last_bl = e_com;
+ *e_com++ = ' ';
+ }
+ }
+ ++line_no; /* keep track of input line number */
+ if (!ps.box_com) {
+ int nstar = 1;
+ do { /* flush any blanks and/or tabs at start of
+ * next line */
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ if (*buf_ptr == '*' && --nstar >= 0) {
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ if (*buf_ptr == '/')
+ goto end_of_comment;
+ }
+ } while (*buf_ptr == ' ' || *buf_ptr == '\t');
+ }
+ else if (++buf_ptr >= buf_end)
+ fill_buffer();
+ break; /* end of case for newline */
+
+ case '*': /* must check for possibility of being at end
+ * of comment */
+ if (++buf_ptr >= buf_end) /* get to next char after * */
+ fill_buffer();
+ CHECK_SIZE_COM(4);
+ if (*buf_ptr == '/') { /* it is the end!!! */
+ end_of_comment:
+ if (++buf_ptr >= buf_end)
+ fill_buffer();
+ if (break_delim) {
+ if (e_com > s_com + 3) {
+ dump_line();
+ }
+ else
+ s_com = e_com;
+ *e_com++ = ' ';
+ }
+ if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com)
+ *e_com++ = ' '; /* ensure blank before end */
+ *e_com++ = '*', *e_com++ = '/', *e_com = '\0';
+ ps.just_saw_decl = l_just_saw_decl;
+ return;
+ }
+ else /* handle isolated '*' */
+ *e_com++ = '*';
+ break;
+ default: /* we have a random char */
+ now_col = count_spaces_until(ps.com_col, s_com, e_com);
+ do {
+ CHECK_SIZE_COM(1);
+ *e_com = *buf_ptr++;
+ if (buf_ptr >= buf_end)
+ fill_buffer();
+ if (*e_com == ' ' || *e_com == '\t')
+ last_bl = e_com; /* remember we saw a blank */
+ ++e_com;
+ now_col++;
+ } while (!memchr("*\n\r\b\t", *buf_ptr, 6) &&
+ (now_col <= adj_max_col || !last_bl));
+ ps.last_nl = false;
+ if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') {
+ /*
+ * the comment is too long, it must be broken up
+ */
+ if (last_bl == NULL) {
+ dump_line();
+ if (!ps.box_com && opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ break;
+ }
+ *e_com = '\0';
+ e_com = last_bl;
+ dump_line();
+ if (!ps.box_com && opt.star_comment_cont)
+ *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' ';
+ for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t';
+ t_ptr++)
+ ;
+ last_bl = NULL;
+ /*
+ * t_ptr will be somewhere between e_com (dump_line() reset)
+ * and l_com. So it's safe to copy byte by byte from t_ptr
+ * to e_com without any CHECK_SIZE_COM().
+ */
+ while (*t_ptr != '\0') {
+ if (*t_ptr == ' ' || *t_ptr == '\t')
+ last_bl = e_com;
+ *e_com++ = *t_ptr++;
+ }
+ }
+ break;
+ }
+ }
+}
diff --git a/usr.bin/indent/tests/Makefile b/usr.bin/indent/tests/Makefile
new file mode 100644
index 000000000000..4e84917f8a40
--- /dev/null
+++ b/usr.bin/indent/tests/Makefile
@@ -0,0 +1,54 @@
+PACKAGE= tests
+
+${PACKAGE}FILES+= binary.0
+${PACKAGE}FILES+= binary.0.stdout
+${PACKAGE}FILES+= comments.0
+${PACKAGE}FILES+= comments.0.stdout
+${PACKAGE}FILES+= declarations.0
+${PACKAGE}FILES+= declarations.0.stdout
+${PACKAGE}FILES+= elsecomment.0
+${PACKAGE}FILES+= elsecomment.0.stdout
+${PACKAGE}FILES+= elsecomment.0.pro
+${PACKAGE}FILES+= f_decls.0
+${PACKAGE}FILES+= f_decls.0.stdout
+${PACKAGE}FILES+= float.0
+${PACKAGE}FILES+= float.0.stdout
+${PACKAGE}FILES+= label.0
+${PACKAGE}FILES+= label.0.stdout
+${PACKAGE}FILES+= label.0.pro
+${PACKAGE}FILES+= list_head.0
+${PACKAGE}FILES+= list_head.0.stdout
+${PACKAGE}FILES+= ncs.0
+${PACKAGE}FILES+= ncs.0.stdout
+${PACKAGE}FILES+= ncs.0.pro
+${PACKAGE}FILES+= offsetof.0
+${PACKAGE}FILES+= offsetof.0.stdout
+${PACKAGE}FILES+= parens.0
+${PACKAGE}FILES+= parens.0.stdout
+${PACKAGE}FILES+= parens.0.pro
+${PACKAGE}FILES+= pcs.0
+${PACKAGE}FILES+= pcs.0.stdout
+${PACKAGE}FILES+= pcs.0.pro
+${PACKAGE}FILES+= cs.0
+${PACKAGE}FILES+= cs.0.stdout
+${PACKAGE}FILES+= cs.0.pro
+${PACKAGE}FILES+= struct.0
+${PACKAGE}FILES+= struct.0.stdout
+${PACKAGE}FILES+= surplusbad.0
+${PACKAGE}FILES+= surplusbad.0.stdout
+${PACKAGE}FILES+= surplusbad.0.pro
+${PACKAGE}FILES+= types_from_file.0
+${PACKAGE}FILES+= types_from_file.0.stdout
+${PACKAGE}FILES+= types_from_file.0.list
+${PACKAGE}FILES+= types_from_file.0.pro
+${PACKAGE}FILES+= wchar.0
+${PACKAGE}FILES+= wchar.0.stdout
+${PACKAGE}FILES+= ps.0
+${PACKAGE}FILES+= ps.0.stdout
+${PACKAGE}FILES+= ps.0.pro
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/indent/tests/Makefile.depend b/usr.bin/indent/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/indent/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/indent/tests/binary.0 b/usr.bin/indent/tests/binary.0
new file mode 100644
index 000000000000..0c5ebf7e8f89
--- /dev/null
+++ b/usr.bin/indent/tests/binary.0
@@ -0,0 +1,9 @@
+#define b00101010 -1
+void t(void) {
+ unsigned a[] = {0b00101010, 0x00005678, 02, 17U};
+ float x[] = {.7f, 0.7f};
+ unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL};
+
+ if (0 b00101010)
+ return;
+}
diff --git a/usr.bin/indent/tests/binary.0.stdout b/usr.bin/indent/tests/binary.0.stdout
new file mode 100644
index 000000000000..6118ac505550
--- /dev/null
+++ b/usr.bin/indent/tests/binary.0.stdout
@@ -0,0 +1,11 @@
+#define b00101010 -1
+void
+t(void)
+{
+ unsigned a[] = {0b00101010, 0x00005678, 02, 17U};
+ float x[] = {.7f, 0.7f};
+ unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL};
+
+ if (0 b00101010)
+ return;
+}
diff --git a/usr.bin/indent/tests/comments.0 b/usr.bin/indent/tests/comments.0
new file mode 100644
index 000000000000..6c40b9acfacb
--- /dev/null
+++ b/usr.bin/indent/tests/comments.0
@@ -0,0 +1,51 @@
+typedef enum x {
+ aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */
+ bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */
+ cccccccccccccc = 1 << 1, /* test c */
+ dddddddddddddddddddddddddddddd = 1 << 2 /* test d */
+} x;
+
+/* See r303597, r303598, r309219, and r309343 */
+void t(void) {
+ /*
+ * Old indent wrapped the URL near where this sentence ends.
+ *
+ * https://man.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=freebsd-current&arch=default&format=html&x
+ */
+
+ /*
+ * Old indent did not wrap to column 78
+ *
+ * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk
+ */
+
+ /*
+ * Old indent unnecessarily removed the star comment continuation on the next line.
+ *
+ * *test*
+ */
+
+ /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */
+
+ /* r309343 */
+}
+
+int c(void)
+{
+ if (1) { /*- a christmas tree *
+ ***
+ ***** */
+ /*- another one *
+ ***
+ ***** */
+ 7;
+ }
+
+ if (1) /*- a christmas tree *
+ ***
+ ***** */
+ /*- another one *
+ ***
+ ***** */
+ 1;
+}
diff --git a/usr.bin/indent/tests/comments.0.pro b/usr.bin/indent/tests/comments.0.pro
new file mode 100644
index 000000000000..ce818772931d
--- /dev/null
+++ b/usr.bin/indent/tests/comments.0.pro
@@ -0,0 +1 @@
+-bbb
diff --git a/usr.bin/indent/tests/comments.0.stdout b/usr.bin/indent/tests/comments.0.stdout
new file mode 100644
index 000000000000..bc3f7ace6b9b
--- /dev/null
+++ b/usr.bin/indent/tests/comments.0.stdout
@@ -0,0 +1,59 @@
+typedef enum x {
+ aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */
+ bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */
+ cccccccccccccc = 1 << 1, /* test c */
+ dddddddddddddddddddddddddddddd = 1 << 2 /* test d */
+} x;
+
+/* See r303597, r303598, r309219, and r309343 */
+void
+t(void)
+{
+ /*
+ * Old indent wrapped the URL near where this sentence ends.
+ *
+ * https://man.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=freebsd-current&arch=default&format=html&x
+ */
+
+ /*
+ * Old indent did not wrap to column 78
+ *
+ * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj
+ * kk
+ */
+
+ /*
+ * Old indent unnecessarily removed the star comment continuation on
+ * the next line.
+ *
+ * *test*
+ */
+
+ /*
+ * r309219 Go through linked list, freeing from the malloced (t[-1])
+ * address.
+ */
+
+ /* r309343 */
+}
+
+int
+c(void)
+{
+ if (1) { /*- a christmas tree *
+ ***
+ ***** */
+ /*- another one *
+ ***
+ ***** */
+ 7;
+ }
+
+ if (1) /*- a christmas tree *
+ ***
+ ***** */
+ /*- another one *
+ ***
+ ***** */
+ 1;
+}
diff --git a/usr.bin/indent/tests/cs.0 b/usr.bin/indent/tests/cs.0
new file mode 100644
index 000000000000..129feeeeae4b
--- /dev/null
+++ b/usr.bin/indent/tests/cs.0
@@ -0,0 +1,3 @@
+void t(void) {
+ int a = (double) 8;
+}
diff --git a/usr.bin/indent/tests/cs.0.pro b/usr.bin/indent/tests/cs.0.pro
new file mode 100644
index 000000000000..b0d3b81a79c5
--- /dev/null
+++ b/usr.bin/indent/tests/cs.0.pro
@@ -0,0 +1 @@
+-cs
diff --git a/usr.bin/indent/tests/cs.0.stdout b/usr.bin/indent/tests/cs.0.stdout
new file mode 100644
index 000000000000..177882470c02
--- /dev/null
+++ b/usr.bin/indent/tests/cs.0.stdout
@@ -0,0 +1,5 @@
+void
+t(void)
+{
+ int a = (double) 8;
+}
diff --git a/usr.bin/indent/tests/declarations.0 b/usr.bin/indent/tests/declarations.0
new file mode 100644
index 000000000000..706352ee2e37
--- /dev/null
+++ b/usr.bin/indent/tests/declarations.0
@@ -0,0 +1,78 @@
+/* See r303570 */
+
+typedef void (*voidptr) (int *);
+
+static const struct
+{
+ double x;
+ double y, z;
+} n[m + 1] =
+{
+ {
+ .0,
+ .9,
+ 5
+ }
+};
+
+typedef struct Complex
+{
+ double x;
+ double y;
+} Complex;
+
+void
+t1 (char *a, int b,
+ void (*fn)(void))
+{}
+
+void t2 (char *x, int y)
+{
+ int a,
+ b,
+ c;
+ int
+ *d,
+ *e,
+ *f;
+ int (*g)(),
+ (*h)(),
+ (*i)();
+ int j,
+ k,
+ l;
+ int m
+ ,n
+ ,o
+ ;
+ int chars[ /* push the comma beyond column 74 .... */ ], x;
+}
+
+const int int_minimum_size =
+MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF;
+
+int *int_create(void)
+{
+
+}
+
+static
+_attribute_printf(1, 2)
+void
+print_error(const char *fmt,...)
+{
+
+}
+
+static LIST_HEAD(, alq) ald_active;
+static int ald_shutingdown = 0;
+struct thread *ald_thread;
+
+static int
+do_execve(td, args, mac_p)
+ struct thread *td;
+ struct image_args *args;
+ struct mac *mac_p;
+{
+
+}
diff --git a/usr.bin/indent/tests/declarations.0.stdout b/usr.bin/indent/tests/declarations.0.stdout
new file mode 100644
index 000000000000..f807c559c6ea
--- /dev/null
+++ b/usr.bin/indent/tests/declarations.0.stdout
@@ -0,0 +1,72 @@
+/* See r303570 */
+
+typedef void (*voidptr) (int *);
+
+static const struct {
+ double x;
+ double y, z;
+} n[m + 1] =
+{
+ {
+ .0,
+ .9,
+ 5
+ }
+};
+
+typedef struct Complex {
+ double x;
+ double y;
+} Complex;
+
+void
+t1(char *a, int b,
+ void (*fn) (void))
+{
+}
+
+void
+t2(char *x, int y)
+{
+ int a, b, c;
+ int
+ *d, *e, *f;
+ int (*g) (), (*h) (), (*i) ();
+ int j, k, l;
+ int m
+ ,n
+ ,o
+ ;
+ int chars[ /* push the comma beyond column 74 .... */ ],
+ x;
+}
+
+const int int_minimum_size =
+MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF;
+
+int *
+int_create(void)
+{
+
+}
+
+static
+_attribute_printf(1, 2)
+void
+print_error(const char *fmt,...)
+{
+
+}
+
+static LIST_HEAD(, alq) ald_active;
+static int ald_shutingdown = 0;
+struct thread *ald_thread;
+
+static int
+do_execve(td, args, mac_p)
+ struct thread *td;
+ struct image_args *args;
+ struct mac *mac_p;
+{
+
+}
diff --git a/usr.bin/indent/tests/elsecomment.0 b/usr.bin/indent/tests/elsecomment.0
new file mode 100644
index 000000000000..f8aa05c77d82
--- /dev/null
+++ b/usr.bin/indent/tests/elsecomment.0
@@ -0,0 +1,41 @@
+/* See r303484 and r309342 */
+void t(void) {
+ /* The two if statements below excercise two different code paths. */
+
+ if (1) /* a */ int a; else /* b */ int b;
+
+ if (1) /* a */
+ int a;
+ else /* b */
+ int b;
+
+ if (1) {
+
+ }
+
+
+
+ /* Old indent would remove the 3 blank lines above, awaiting "else". */
+
+ if (1) {
+ int a;
+ }
+
+
+ else if (0) {
+ int b;
+ }
+ /* test */
+ else
+ ;
+
+ if (1)
+ ;
+ else /* Old indent would get very confused here */
+ /* We also mustn't assume that there's only one comment */
+ /* before the left brace. */
+ {
+
+
+ }
+}
diff --git a/usr.bin/indent/tests/elsecomment.0.pro b/usr.bin/indent/tests/elsecomment.0.pro
new file mode 100644
index 000000000000..84cf83a1ea27
--- /dev/null
+++ b/usr.bin/indent/tests/elsecomment.0.pro
@@ -0,0 +1 @@
+-bl
diff --git a/usr.bin/indent/tests/elsecomment.0.stdout b/usr.bin/indent/tests/elsecomment.0.stdout
new file mode 100644
index 000000000000..349f168d7e0a
--- /dev/null
+++ b/usr.bin/indent/tests/elsecomment.0.stdout
@@ -0,0 +1,46 @@
+/* See r303484 and r309342 */
+void
+t(void)
+{
+ /* The two if statements below excercise two different code paths. */
+
+ if (1) /* a */
+ int a;
+ else /* b */
+ int b;
+
+ if (1) /* a */
+ int a;
+ else /* b */
+ int b;
+
+ if (1)
+ {
+
+ }
+
+
+
+ /* Old indent would remove the 3 blank lines above, awaiting "else". */
+
+ if (1)
+ {
+ int a;
+ } else if (0)
+ {
+ int b;
+ }
+ /* test */
+ else
+ ;
+
+ if (1)
+ ;
+ else /* Old indent would get very confused here */
+ /* We also mustn't assume that there's only one comment */
+ /* before the left brace. */
+ {
+
+
+ }
+}
diff --git a/usr.bin/indent/tests/f_decls.0 b/usr.bin/indent/tests/f_decls.0
new file mode 100644
index 000000000000..dc175af40904
--- /dev/null
+++ b/usr.bin/indent/tests/f_decls.0
@@ -0,0 +1,28 @@
+
+char * x(void)
+{
+ type identifier;
+ type *pointer;
+ unused * value;
+ (void)unused * value;
+
+ dmax = (double)3 * 10.0;
+ dmin = (double)dmax * 10.0;
+ davg = (double)dmax * dmin;
+
+ return NULL;
+}
+
+int *
+y(void) {
+
+}
+
+int
+z(void) {
+
+}
+
+int x;
+int *y;
+int * * * * z;
diff --git a/usr.bin/indent/tests/f_decls.0.stdout b/usr.bin/indent/tests/f_decls.0.stdout
new file mode 100644
index 000000000000..1e95f9ae7e03
--- /dev/null
+++ b/usr.bin/indent/tests/f_decls.0.stdout
@@ -0,0 +1,31 @@
+
+char *
+x(void)
+{
+ type identifier;
+ type *pointer;
+ unused *value;
+ (void)unused * value;
+
+ dmax = (double)3 * 10.0;
+ dmin = (double)dmax * 10.0;
+ davg = (double)dmax * dmin;
+
+ return NULL;
+}
+
+int *
+y(void)
+{
+
+}
+
+int
+z(void)
+{
+
+}
+
+int x;
+int *y;
+int ****z;
diff --git a/usr.bin/indent/tests/float.0 b/usr.bin/indent/tests/float.0
new file mode 100644
index 000000000000..8ea2b41b7cc2
--- /dev/null
+++ b/usr.bin/indent/tests/float.0
@@ -0,0 +1,7 @@
+void t(void) {
+ unsigned long x = 314UL;
+ double y[] = {0x1P+9F, 0.3, .1, 1.2f, 0xa.p01f, 3.14f, 2.L};
+ int z = 0b0101;
+ DO_NOTHING;
+ x._y = 5;
+}
diff --git a/usr.bin/indent/tests/float.0.stdout b/usr.bin/indent/tests/float.0.stdout
new file mode 100644
index 000000000000..52bba26c2a3f
--- /dev/null
+++ b/usr.bin/indent/tests/float.0.stdout
@@ -0,0 +1,9 @@
+void
+t(void)
+{
+ unsigned long x = 314UL;
+ double y[] = {0x1P+9F, 0.3, .1, 1.2f, 0xa.p01f, 3.14f, 2.L};
+ int z = 0b0101;
+ DO_NOTHING;
+ x._y = 5;
+}
diff --git a/usr.bin/indent/tests/functional_test.sh b/usr.bin/indent/tests/functional_test.sh
new file mode 100755
index 000000000000..44538e5b6e12
--- /dev/null
+++ b/usr.bin/indent/tests/functional_test.sh
@@ -0,0 +1,89 @@
+#
+# Copyright 2016 Dell EMC
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+SRCDIR=$(atf_get_srcdir)
+
+check()
+{
+ local tc=${1}; shift
+
+ local indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent)
+
+ # All of the files need to be in the ATF sandbox in order for the tests
+ # to pass.
+ atf_check cp ${SRCDIR}/${tc}* .
+
+ # Remove $FreeBSD$ RCS expansions because they get re-indented, which
+ # changes the output
+ local out_file="${tc}.stdout"
+ if [ -f "${out_file}" ]; then
+ parsed_file=output_file.parsed
+
+ atf_check -o save:$parsed_file sed -e '/\$FreeBSD.*\$/d' \
+ ${tc}.stdout
+ out_flag="-o file:$parsed_file"
+ fi
+ local profile_file="${tc}.pro"
+ if [ -f "${profile_file}" ]; then
+ profile_flag="-P${profile_file}"
+ else
+ # Make sure we don't implicitly use ~/.indent.pro from the test
+ # host, for determinism purposes.
+ profile_flag="-npro"
+ fi
+ sed -e '/\$FreeBSD.*\$/d' ${tc} > input_file.parsed
+ atf_check -s exit:${tc##*.} ${out_flag} ${indent} ${profile_flag} < input_file.parsed
+}
+
+add_testcase()
+{
+ local tc=${1}
+ local tc_escaped word
+
+ case "${tc%.*}" in
+ *-*)
+ local IFS="-"
+ for word in ${tc%.*}; do
+ tc_escaped="${tc_escaped:+${tc_escaped}_}${word}"
+ done
+ ;;
+ *)
+ tc_escaped=${tc%.*}
+ ;;
+ esac
+
+ atf_test_case ${tc_escaped}
+ eval "${tc_escaped}_body() { check ${tc}; }"
+ atf_add_test_case ${tc_escaped}
+}
+
+atf_init_test_cases()
+{
+ for path in $(find -Es "${SRCDIR}" -regex '.*\.[0-9]+$'); do
+ add_testcase ${path##*/}
+ done
+}
diff --git a/usr.bin/indent/tests/label.0 b/usr.bin/indent/tests/label.0
new file mode 100644
index 000000000000..d4c54446e0bf
--- /dev/null
+++ b/usr.bin/indent/tests/label.0
@@ -0,0 +1,12 @@
+/* See r303489 */
+void t(void) {
+ switch (1)
+ {
+ case 1: /* test */
+ case 2: /* test */
+ }
+CLEANUP:
+ ;
+V: ;
+U: ;
+}
diff --git a/usr.bin/indent/tests/label.0.pro b/usr.bin/indent/tests/label.0.pro
new file mode 100644
index 000000000000..09d814950dfa
--- /dev/null
+++ b/usr.bin/indent/tests/label.0.pro
@@ -0,0 +1 @@
+-nut
diff --git a/usr.bin/indent/tests/label.0.stdout b/usr.bin/indent/tests/label.0.stdout
new file mode 100644
index 000000000000..ab1b985e9687
--- /dev/null
+++ b/usr.bin/indent/tests/label.0.stdout
@@ -0,0 +1,13 @@
+/* See r303489 */
+void
+t(void)
+{
+ switch (1) {
+ case 1: /* test */
+ case 2: /* test */
+ }
+CLEANUP:
+ ;
+V: ;
+U: ;
+}
diff --git a/usr.bin/indent/tests/list_head.0 b/usr.bin/indent/tests/list_head.0
new file mode 100644
index 000000000000..ec17a7bc1c9a
--- /dev/null
+++ b/usr.bin/indent/tests/list_head.0
@@ -0,0 +1,15 @@
+/* See r309380 */
+static int
+do_execve(td, args, mac_p)
+ struct thread *td;
+ struct image_args *args;
+ struct mac *mac_p;
+{
+
+}
+
+static LIST_HEAD(, alq) ald_active;
+static int ald_shuttingdown = 0;
+struct thread *ald_thread;
+
+
diff --git a/usr.bin/indent/tests/list_head.0.stdout b/usr.bin/indent/tests/list_head.0.stdout
new file mode 100644
index 000000000000..b74117a097e6
--- /dev/null
+++ b/usr.bin/indent/tests/list_head.0.stdout
@@ -0,0 +1,13 @@
+/* See r309380 */
+static int
+do_execve(td, args, mac_p)
+ struct thread *td;
+ struct image_args *args;
+ struct mac *mac_p;
+{
+
+}
+
+static LIST_HEAD(, alq) ald_active;
+static int ald_shuttingdown = 0;
+struct thread *ald_thread;
diff --git a/usr.bin/indent/tests/ncs.0 b/usr.bin/indent/tests/ncs.0
new file mode 100644
index 000000000000..129feeeeae4b
--- /dev/null
+++ b/usr.bin/indent/tests/ncs.0
@@ -0,0 +1,3 @@
+void t(void) {
+ int a = (double) 8;
+}
diff --git a/usr.bin/indent/tests/ncs.0.pro b/usr.bin/indent/tests/ncs.0.pro
new file mode 100644
index 000000000000..3f2185b2863a
--- /dev/null
+++ b/usr.bin/indent/tests/ncs.0.pro
@@ -0,0 +1 @@
+-ncs
diff --git a/usr.bin/indent/tests/ncs.0.stdout b/usr.bin/indent/tests/ncs.0.stdout
new file mode 100644
index 000000000000..e7ad0b5dbf12
--- /dev/null
+++ b/usr.bin/indent/tests/ncs.0.stdout
@@ -0,0 +1,5 @@
+void
+t(void)
+{
+ int a = (double)8;
+}
diff --git a/usr.bin/indent/tests/offsetof.0 b/usr.bin/indent/tests/offsetof.0
new file mode 100644
index 000000000000..c1870fa0daa3
--- /dev/null
+++ b/usr.bin/indent/tests/offsetof.0
@@ -0,0 +1,4 @@
+/* See r303718 */
+void t(void) {
+ int n = malloc(offsetof(struct s, f) + 1);
+}
diff --git a/usr.bin/indent/tests/offsetof.0.stdout b/usr.bin/indent/tests/offsetof.0.stdout
new file mode 100644
index 000000000000..dedf90e8ab3a
--- /dev/null
+++ b/usr.bin/indent/tests/offsetof.0.stdout
@@ -0,0 +1,6 @@
+/* See r303718 */
+void
+t(void)
+{
+ int n = malloc(offsetof(struct s, f) + 1);
+}
diff --git a/usr.bin/indent/tests/parens.0 b/usr.bin/indent/tests/parens.0
new file mode 100644
index 000000000000..5293ad7666a9
--- /dev/null
+++ b/usr.bin/indent/tests/parens.0
@@ -0,0 +1,26 @@
+typedef void (*xxxxxxxxxxx) (int,
+ char);
+
+typedef char (*xxxxxxxxxxxxxxxxxxxxxxxxxxxx) (int *,
+ unsigned *,
+ char,
+ float *);
+
+void
+test(void)
+{
+ char chars[secondf(firstf(B),
+ *here)];
+
+ float xxx = yyyyyyyyyyyyyy(zzzzzzzzzzzzz(p1,
+ (p2),
+ p3));
+
+ if (1) {
+ char *xxx = firstf(secondf2(p1,
+ p2));
+ }
+
+ rb->allocfunc(1);
+ rb2.allocfunc(7);
+}
diff --git a/usr.bin/indent/tests/parens.0.pro b/usr.bin/indent/tests/parens.0.pro
new file mode 100644
index 000000000000..e860911a1173
--- /dev/null
+++ b/usr.bin/indent/tests/parens.0.pro
@@ -0,0 +1 @@
+-ts4 -i4 -di12 -Tallocfunc
diff --git a/usr.bin/indent/tests/parens.0.stdout b/usr.bin/indent/tests/parens.0.stdout
new file mode 100644
index 000000000000..99433239bc30
--- /dev/null
+++ b/usr.bin/indent/tests/parens.0.stdout
@@ -0,0 +1,26 @@
+typedef void (*xxxxxxxxxxx) (int,
+ char);
+
+typedef char (*xxxxxxxxxxxxxxxxxxxxxxxxxxxx) (int *,
+ unsigned *,
+ char,
+ float *);
+
+void
+test(void)
+{
+ char chars[secondf(firstf(B),
+ *here)];
+
+ float xxx = yyyyyyyyyyyyyy(zzzzzzzzzzzzz(p1,
+ (p2),
+ p3));
+
+ if (1) {
+ char *xxx = firstf(secondf2(p1,
+ p2));
+ }
+
+ rb->allocfunc(1);
+ rb2.allocfunc(7);
+}
diff --git a/usr.bin/indent/tests/pcs.0 b/usr.bin/indent/tests/pcs.0
new file mode 100644
index 000000000000..9fd8aad863a1
--- /dev/null
+++ b/usr.bin/indent/tests/pcs.0
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void) {
+ puts("Hello");
+ return 0;
+}
diff --git a/usr.bin/indent/tests/pcs.0.pro b/usr.bin/indent/tests/pcs.0.pro
new file mode 100644
index 000000000000..60d7c2ccd850
--- /dev/null
+++ b/usr.bin/indent/tests/pcs.0.pro
@@ -0,0 +1 @@
+-pcs
diff --git a/usr.bin/indent/tests/pcs.0.stdout b/usr.bin/indent/tests/pcs.0.stdout
new file mode 100644
index 000000000000..013082de8b38
--- /dev/null
+++ b/usr.bin/indent/tests/pcs.0.stdout
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int
+main(void)
+{
+ puts ("Hello");
+ return 0;
+}
diff --git a/usr.bin/indent/tests/ps.0 b/usr.bin/indent/tests/ps.0
new file mode 100644
index 000000000000..0dc72ccfddf2
--- /dev/null
+++ b/usr.bin/indent/tests/ps.0
@@ -0,0 +1,4 @@
+struct s { int i; };
+void f(struct s *p) {
+ p->i--;
+}
diff --git a/usr.bin/indent/tests/ps.0.pro b/usr.bin/indent/tests/ps.0.pro
new file mode 100644
index 000000000000..5fdebee73785
--- /dev/null
+++ b/usr.bin/indent/tests/ps.0.pro
@@ -0,0 +1 @@
+-ps
diff --git a/usr.bin/indent/tests/ps.0.stdout b/usr.bin/indent/tests/ps.0.stdout
new file mode 100644
index 000000000000..08f421e984ff
--- /dev/null
+++ b/usr.bin/indent/tests/ps.0.stdout
@@ -0,0 +1,8 @@
+struct s {
+ int i;
+};
+void
+f(struct s *p)
+{
+ p -> i--;
+}
diff --git a/usr.bin/indent/tests/struct.0 b/usr.bin/indent/tests/struct.0
new file mode 100644
index 000000000000..784d387cc717
--- /dev/null
+++ b/usr.bin/indent/tests/struct.0
@@ -0,0 +1,20 @@
+
+int f(struct x *a);
+
+/* See r303485 */
+void
+t(void)
+{
+ static const struct {
+ int a;
+ int b;
+ } c[] = {
+ { D, E },
+ { F, G }
+ };
+}
+
+void u(struct x a) {
+ int b;
+ struct y c = (struct y *)&a;
+}
diff --git a/usr.bin/indent/tests/struct.0.stdout b/usr.bin/indent/tests/struct.0.stdout
new file mode 100644
index 000000000000..55b559ab9d6b
--- /dev/null
+++ b/usr.bin/indent/tests/struct.0.stdout
@@ -0,0 +1,22 @@
+
+int f(struct x *a);
+
+/* See r303485 */
+void
+t(void)
+{
+ static const struct {
+ int a;
+ int b;
+ } c[] = {
+ {D, E},
+ {F, G}
+ };
+}
+
+void
+u(struct x a)
+{
+ int b;
+ struct y c = (struct y *)&a;
+}
diff --git a/usr.bin/indent/tests/surplusbad.0 b/usr.bin/indent/tests/surplusbad.0
new file mode 100644
index 000000000000..f9f2bf80c24a
--- /dev/null
+++ b/usr.bin/indent/tests/surplusbad.0
@@ -0,0 +1,8 @@
+/* See r303599 */
+#if defined(__i386__)
+int a;
+#elif defined(__amd64__)
+int b;
+#else
+#error "Port me"
+#endif
diff --git a/usr.bin/indent/tests/surplusbad.0.pro b/usr.bin/indent/tests/surplusbad.0.pro
new file mode 100644
index 000000000000..b3fe0943ec66
--- /dev/null
+++ b/usr.bin/indent/tests/surplusbad.0.pro
@@ -0,0 +1 @@
+-bad
diff --git a/usr.bin/indent/tests/surplusbad.0.stdout b/usr.bin/indent/tests/surplusbad.0.stdout
new file mode 100644
index 000000000000..2f5856bc4092
--- /dev/null
+++ b/usr.bin/indent/tests/surplusbad.0.stdout
@@ -0,0 +1,8 @@
+/* See r303599 */
+#if defined(__i386__)
+int a;
+#elif defined(__amd64__)
+int b;
+#else
+#error "Port me"
+#endif
diff --git a/usr.bin/indent/tests/types_from_file.0 b/usr.bin/indent/tests/types_from_file.0
new file mode 100644
index 000000000000..c7673f55a0fc
--- /dev/null
+++ b/usr.bin/indent/tests/types_from_file.0
@@ -0,0 +1,2 @@
+/* See r303735 */
+void t(a *x, b *y, c *z);
diff --git a/usr.bin/indent/tests/types_from_file.0.list b/usr.bin/indent/tests/types_from_file.0.list
new file mode 100644
index 000000000000..5f733616b1b4
--- /dev/null
+++ b/usr.bin/indent/tests/types_from_file.0.list
@@ -0,0 +1,2 @@
+b
+a \ No newline at end of file
diff --git a/usr.bin/indent/tests/types_from_file.0.pro b/usr.bin/indent/tests/types_from_file.0.pro
new file mode 100644
index 000000000000..255b8817589b
--- /dev/null
+++ b/usr.bin/indent/tests/types_from_file.0.pro
@@ -0,0 +1 @@
+-Utypes_from_file.0.list
diff --git a/usr.bin/indent/tests/types_from_file.0.stdout b/usr.bin/indent/tests/types_from_file.0.stdout
new file mode 100644
index 000000000000..dca345ffafbf
--- /dev/null
+++ b/usr.bin/indent/tests/types_from_file.0.stdout
@@ -0,0 +1,2 @@
+/* See r303735 */
+void t(a *x, b *y, c * z);
diff --git a/usr.bin/indent/tests/wchar.0 b/usr.bin/indent/tests/wchar.0
new file mode 100644
index 000000000000..699703903373
--- /dev/null
+++ b/usr.bin/indent/tests/wchar.0
@@ -0,0 +1,5 @@
+/* See r309220 */
+#include <wchar.h>
+
+wchar_t *x = L"test";
+wchar_t y = L't';
diff --git a/usr.bin/indent/tests/wchar.0.stdout b/usr.bin/indent/tests/wchar.0.stdout
new file mode 100644
index 000000000000..a901b043328e
--- /dev/null
+++ b/usr.bin/indent/tests/wchar.0.stdout
@@ -0,0 +1,5 @@
+/* See r309220 */
+#include <wchar.h>
+
+wchar_t *x = L"test";
+wchar_t y = L't';
diff --git a/usr.bin/ipcrm/Makefile b/usr.bin/ipcrm/Makefile
new file mode 100644
index 000000000000..797b9f3dc5a9
--- /dev/null
+++ b/usr.bin/ipcrm/Makefile
@@ -0,0 +1,9 @@
+PROG= ipcrm
+SRCS= ipcrm.c ipc.c
+LIBADD= kvm
+CFLAGS+=-I${SRCTOP}/usr.bin/ipcs
+.PATH: ${SRCTOP}/usr.bin/ipcs
+
+WARNS?= 0
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ipcrm/Makefile.depend b/usr.bin/ipcrm/Makefile.depend
new file mode 100644
index 000000000000..124f2f93f8a6
--- /dev/null
+++ b/usr.bin/ipcrm/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libkvm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ipcrm/ipcrm.1 b/usr.bin/ipcrm/ipcrm.1
new file mode 100644
index 000000000000..556c7bdfd99a
--- /dev/null
+++ b/usr.bin/ipcrm/ipcrm.1
@@ -0,0 +1,120 @@
+.\" Copyright (c) 1994 Adam Glass
+.\" 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. 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 Adam Glass ``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 Adam Glass 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 December 12, 2007
+.Dt IPCRM 1
+.Os
+.Sh NAME
+.Nm ipcrm
+.Nd "remove the specified message queues, semaphore sets, and shared segments"
+.Sh SYNOPSIS
+.Nm
+.Op Fl W
+.Op Fl v
+.Op Fl q Ar msqid
+.Op Fl m Ar shmid
+.Op Fl s Ar semid
+.Op Fl Q Ar msgkey
+.Op Fl M Ar shmkey
+.Op Fl S Ar semkey
+.Ar ...
+.Sh DESCRIPTION
+The
+.Nm
+utility removes the specified message queues, semaphores and shared memory
+segments.
+These System V IPC objects can be specified by their
+creation ID or any associated key.
+.Pp
+The following options are generic:
+.Bl -tag -width indent
+.It Fl v
+If specified once with -W or with -1 for an object, it will show
+all removed objects.
+If specified twice with -W or with -1 for an objects, it will show
+all removed objects and all failed removals.
+.It Fl W
+Try to wipe all specified message queues, semaphores and shared
+memory segments.
+.It Fl y
+Use the
+.Xr kvm 3
+interface instead of the
+.Xr sysctl 3
+interface to extract the required information.
+If
+.Nm
+is to operate on the running system,
+using
+.Xr kvm 3
+will require read privileges to
+.Pa /dev/kmem .
+.El
+.Pp
+The following options are used to specify which IPC objects will be removed.
+Any number and combination of these options can be used:
+.Bl -tag -width indent
+.It Fl q Ar msqid
+Remove the message queue associated with the ID
+.Ar msqid
+from the system.
+.It Fl m Ar shmid
+Mark the shared memory segment associated with ID
+.Ar shmid
+for removal.
+This marked segment will be destroyed after the last detach.
+.It Fl s Ar semid
+Remove the semaphore set associated with ID
+.Ar semid
+from the system.
+.It Fl Q Ar msgkey
+Remove the message queue associated with key
+.Ar msgkey
+from the system.
+.It Fl M Ar shmkey
+Mark the shared memory segment associated with key
+.Ar shmkey
+for removal.
+This marked segment will be destroyed after the last detach.
+.It Fl S Ar semkey
+Remove the semaphore set associated with key
+.Ar semkey
+from the system.
+.El
+.Pp
+The identifiers and keys associated with these System V IPC objects can be
+determined by using
+.Xr ipcs 1 .
+If the identifier or the key is -1, it will remove all these objects.
+.Sh SEE ALSO
+.Xr ipcs 1
+.Sh HISTORY
+The wiping of all System V IPC objects was first implemented in
+.Fx 6.4 No and 7.1.
+.Sh AUTHORS
+The original author was
+.An Adam Glass .
+The wiping of all System V IPC objects was thought up by
+.An Callum Gibson
+and extended and implemented by
+.An Edwin Groothuis .
diff --git a/usr.bin/ipcrm/ipcrm.c b/usr.bin/ipcrm/ipcrm.c
new file mode 100644
index 000000000000..0e0d40837127
--- /dev/null
+++ b/usr.bin/ipcrm/ipcrm.c
@@ -0,0 +1,298 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1994 Adam Glass
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Glass.
+ * 4. 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 Adam Glass ``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 Adam Glass 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>
+#define _WANT_SYSVMSG_INTERNALS
+#include <sys/msg.h>
+#define _WANT_SYSVSEM_INTERNALS
+#define _WANT_SEMUN
+#include <sys/sem.h>
+#define _WANT_SYSVSHM_INTERNALS
+#include <sys/shm.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <grp.h>
+#include <kvm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ipc.h"
+
+static int signaled;
+static int errflg;
+static int rmverbose = 0;
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: ipcrm [-W] [-v[v]]\n"
+ " [-q msqid] [-m shmid] [-s semid]\n"
+ " [-Q msgkey] [-M shmkey] [-S semkey] ...\n");
+ exit(1);
+}
+
+static int
+msgrm(key_t key, int id)
+{
+
+ if (key == -1 || id == -1) {
+ struct msqid_kernel *kxmsqids;
+ size_t kxmsqids_len;
+ int num;
+
+ kget(X_MSGINFO, &msginfo, sizeof(msginfo));
+ kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni;
+ kxmsqids = malloc(kxmsqids_len);
+ kget(X_MSQIDS, kxmsqids, kxmsqids_len);
+ num = msginfo.msgmni;
+ while (num-- && !signaled)
+ if (kxmsqids[num].u.msg_qbytes != 0) {
+ id = IXSEQ_TO_IPCID(num,
+ kxmsqids[num].u.msg_perm);
+ if (msgctl(id, IPC_RMID, NULL) < 0) {
+ if (rmverbose > 1)
+ warn("msqid(%d): ", id);
+ errflg++;
+ } else
+ if (rmverbose)
+ printf(
+ "Removed %s %d\n",
+ IPC_TO_STRING('Q'),
+ id);
+ }
+ return signaled ? -1 : 0; /* errors maybe handled above */
+ }
+
+ if (key) {
+ id = msgget(key, 0);
+ if (id == -1)
+ return -1;
+ }
+
+ return msgctl(id, IPC_RMID, NULL);
+}
+
+static int
+shmrm(key_t key, int id)
+{
+
+ if (key == -1 || id == -1) {
+ struct shmid_kernel *kxshmids;
+ size_t kxshmids_len;
+ int num;
+
+ kget(X_SHMINFO, &shminfo, sizeof(shminfo));
+ kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni;
+ kxshmids = malloc(kxshmids_len);
+ kget(X_SHMSEGS, kxshmids, kxshmids_len);
+ num = shminfo.shmmni;
+ while (num-- && !signaled)
+ if (kxshmids[num].u.shm_perm.mode & 0x0800) {
+ id = IXSEQ_TO_IPCID(num,
+ kxshmids[num].u.shm_perm);
+ if (shmctl(id, IPC_RMID, NULL) < 0) {
+ if (rmverbose > 1)
+ warn("shmid(%d): ", id);
+ errflg++;
+ } else
+ if (rmverbose)
+ printf(
+ "Removed %s %d\n",
+ IPC_TO_STRING('M'),
+ id);
+ }
+ return signaled ? -1 : 0; /* errors maybe handled above */
+ }
+
+ if (key) {
+ id = shmget(key, 0, 0);
+ if (id == -1)
+ return -1;
+ }
+
+ return shmctl(id, IPC_RMID, NULL);
+}
+
+static int
+semrm(key_t key, int id)
+{
+ union semun arg;
+
+ if (key == -1 || id == -1) {
+ struct semid_kernel *kxsema;
+ size_t kxsema_len;
+ int num;
+
+ kget(X_SEMINFO, &seminfo, sizeof(seminfo));
+ kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni;
+ kxsema = malloc(kxsema_len);
+ kget(X_SEMA, kxsema, kxsema_len);
+ num = seminfo.semmni;
+ while (num-- && !signaled)
+ if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) {
+ id = IXSEQ_TO_IPCID(num,
+ kxsema[num].u.sem_perm);
+ if (semctl(id, 0, IPC_RMID, NULL) < 0) {
+ if (rmverbose > 1)
+ warn("semid(%d): ", id);
+ errflg++;
+ } else
+ if (rmverbose)
+ printf(
+ "Removed %s %d\n",
+ IPC_TO_STRING('S'),
+ id);
+ }
+ return signaled ? -1 : 0; /* errors maybe handled above */
+ }
+
+ if (key) {
+ id = semget(key, 0, 0);
+ if (id == -1)
+ return -1;
+ }
+
+ return semctl(id, 0, IPC_RMID, arg);
+}
+
+static void
+not_configured(int signo __unused)
+{
+
+ signaled++;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, result, target_id;
+ key_t target_key;
+
+ while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
+
+ signaled = 0;
+ switch (c) {
+ case 'v':
+ rmverbose++;
+ break;
+ case 'y':
+ use_sysctl = 0;
+ break;
+ }
+ }
+
+ optind = 1;
+ errflg = 0;
+ signal(SIGSYS, not_configured);
+ while ((c = getopt(argc, argv, "q:m:s:Q:M:S:vWy")) != -1) {
+
+ signaled = 0;
+ switch (c) {
+ case 'q':
+ case 'm':
+ case 's':
+ target_id = atoi(optarg);
+ if (c == 'q')
+ result = msgrm(0, target_id);
+ else if (c == 'm')
+ result = shmrm(0, target_id);
+ else
+ result = semrm(0, target_id);
+ if (result < 0) {
+ errflg++;
+ if (!signaled)
+ warn("%sid(%d): ",
+ IPC_TO_STR(toupper(c)), target_id);
+ else
+ warnx(
+ "%ss are not configured "
+ "in the running kernel",
+ IPC_TO_STRING(toupper(c)));
+ }
+ break;
+ case 'Q':
+ case 'M':
+ case 'S':
+ target_key = atol(optarg);
+ if (target_key == IPC_PRIVATE) {
+ warnx("can't remove private %ss",
+ IPC_TO_STRING(c));
+ continue;
+ }
+ if (c == 'Q')
+ result = msgrm(target_key, 0);
+ else if (c == 'M')
+ result = shmrm(target_key, 0);
+ else
+ result = semrm(target_key, 0);
+ if (result < 0) {
+ errflg++;
+ if (!signaled)
+ warn("%ss(%ld): ",
+ IPC_TO_STR(c), target_key);
+ else
+ warnx("%ss are not configured "
+ "in the running kernel",
+ IPC_TO_STRING(c));
+ }
+ break;
+ case 'v':
+ case 'y':
+ /* Handled in other getopt() loop */
+ break;
+ case 'W':
+ msgrm(-1, 0);
+ shmrm(-1, 0);
+ semrm(-1, 0);
+ break;
+ case ':':
+ fprintf(stderr,
+ "option -%c requires an argument\n", optopt);
+ usage();
+ case '?':
+ fprintf(stderr, "unrecognized option: -%c\n", optopt);
+ usage();
+ }
+ }
+
+ if (optind != argc) {
+ fprintf(stderr, "unknown argument: %s\n", argv[optind]);
+ usage();
+ }
+ exit(errflg);
+}
diff --git a/usr.bin/ipcs/Makefile b/usr.bin/ipcs/Makefile
new file mode 100644
index 000000000000..22a2543e9eda
--- /dev/null
+++ b/usr.bin/ipcs/Makefile
@@ -0,0 +1,5 @@
+PROG= ipcs
+SRCS= ipcs.c ipc.c
+LIBADD= kvm
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ipcs/Makefile.depend b/usr.bin/ipcs/Makefile.depend
new file mode 100644
index 000000000000..124f2f93f8a6
--- /dev/null
+++ b/usr.bin/ipcs/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libkvm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ipcs/ipc.c b/usr.bin/ipcs/ipc.c
new file mode 100644
index 000000000000..0d9cccf20421
--- /dev/null
+++ b/usr.bin/ipcs/ipc.c
@@ -0,0 +1,204 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+ * 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 ``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.
+ *
+ * The split of ipcs.c into ipcs.c and ipc.c to accommodate the
+ * changes in ipcrm.c was done by Edwin Groothuis <edwin@FreeBSD.org>
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#define _WANT_SYSVMSG_INTERNALS
+#include <sys/msg.h>
+#define _WANT_SYSVSEM_INTERNALS
+#include <sys/sem.h>
+#define _WANT_SYSVSHM_INTERNALS
+#include <sys/shm.h>
+
+#include <assert.h>
+#include <err.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <stddef.h>
+
+#include "ipc.h"
+
+int use_sysctl = 1;
+struct semid_kernel *sema;
+struct seminfo seminfo;
+struct msginfo msginfo;
+struct msqid_kernel *msqids;
+struct shminfo shminfo;
+struct shmid_kernel *shmsegs;
+
+struct nlist symbols[] = {
+ { .n_name = "sema" },
+ { .n_name = "seminfo" },
+ { .n_name = "msginfo" },
+ { .n_name = "msqids" },
+ { .n_name = "shminfo" },
+ { .n_name = "shmsegs" },
+ { .n_name = NULL }
+};
+
+#define SHMINFO_XVEC X(shmmax, sizeof(u_long)) \
+ X(shmmin, sizeof(u_long)) \
+ X(shmmni, sizeof(u_long)) \
+ X(shmseg, sizeof(u_long)) \
+ X(shmall, sizeof(u_long))
+
+#define SEMINFO_XVEC X(semmni, sizeof(int)) \
+ X(semmns, sizeof(int)) \
+ X(semmnu, sizeof(int)) \
+ X(semmsl, sizeof(int)) \
+ X(semopm, sizeof(int)) \
+ X(semume, sizeof(int)) \
+ X(semusz, sizeof(int)) \
+ X(semvmx, sizeof(int)) \
+ X(semaem, sizeof(int))
+
+#define MSGINFO_XVEC X(msgmax, sizeof(int)) \
+ X(msgmni, sizeof(int)) \
+ X(msgmnb, sizeof(int)) \
+ X(msgtql, sizeof(int)) \
+ X(msgssz, sizeof(int)) \
+ X(msgseg, sizeof(int))
+
+#define X(a, b) { "kern.ipc." #a, offsetof(TYPEC, a), (b) },
+#define TYPEC struct shminfo
+static struct scgs_vector shminfo_scgsv[] = { SHMINFO_XVEC { .sysctl=NULL } };
+#undef TYPEC
+#define TYPEC struct seminfo
+static struct scgs_vector seminfo_scgsv[] = { SEMINFO_XVEC { .sysctl=NULL } };
+#undef TYPEC
+#define TYPEC struct msginfo
+static struct scgs_vector msginfo_scgsv[] = { MSGINFO_XVEC { .sysctl=NULL } };
+#undef TYPEC
+#undef X
+
+kvm_t *kd;
+
+void
+sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vecarr)
+{
+ struct scgs_vector *xp;
+ size_t tsiz;
+ int rv;
+
+ for (xp = vecarr; xp->sysctl != NULL; xp++) {
+ assert(xp->offset <= size);
+ tsiz = xp->size;
+ rv = sysctlbyname(xp->sysctl, (char *)addr + xp->offset,
+ &tsiz, NULL, 0);
+ if (rv == -1)
+ err(1, "sysctlbyname: %s", xp->sysctl);
+ if (tsiz != xp->size)
+ errx(1, "%s size mismatch (expected %zu, got %zu)",
+ xp->sysctl, xp->size, tsiz);
+ }
+}
+
+void
+kget(int idx, void *addr, size_t size)
+{
+ const char *symn; /* symbol name */
+ size_t tsiz;
+ int rv;
+ unsigned long kaddr;
+ const char *sym2sysctl[] = { /* symbol to sysctl name table */
+ "kern.ipc.sema",
+ "kern.ipc.seminfo",
+ "kern.ipc.msginfo",
+ "kern.ipc.msqids",
+ "kern.ipc.shminfo",
+ "kern.ipc.shmsegs" };
+
+ assert((unsigned)idx <= sizeof(sym2sysctl) / sizeof(*sym2sysctl));
+ if (!use_sysctl) {
+ symn = symbols[idx].n_name;
+ if (*symn == '_')
+ symn++;
+ if (symbols[idx].n_type == 0 || symbols[idx].n_value == 0)
+ errx(1, "symbol %s undefined", symn);
+ /*
+ * For some symbols, the value we retrieve is
+ * actually a pointer; since we want the actual value,
+ * we have to manually dereference it.
+ */
+ switch (idx) {
+ case X_MSQIDS:
+ tsiz = sizeof(msqids);
+ rv = kvm_read(kd, symbols[idx].n_value,
+ &msqids, tsiz);
+ kaddr = (u_long)msqids;
+ break;
+ case X_SHMSEGS:
+ tsiz = sizeof(shmsegs);
+ rv = kvm_read(kd, symbols[idx].n_value,
+ &shmsegs, tsiz);
+ kaddr = (u_long)shmsegs;
+ break;
+ case X_SEMA:
+ tsiz = sizeof(sema);
+ rv = kvm_read(kd, symbols[idx].n_value,
+ &sema, tsiz);
+ kaddr = (u_long)sema;
+ break;
+ default:
+ rv = tsiz = 0;
+ kaddr = symbols[idx].n_value;
+ break;
+ }
+ if ((unsigned)rv != tsiz)
+ errx(1, "%s: %s", symn, kvm_geterr(kd));
+ if ((unsigned)kvm_read(kd, kaddr, addr, size) != size)
+ errx(1, "%s: %s", symn, kvm_geterr(kd));
+ } else {
+ switch (idx) {
+ case X_SHMINFO:
+ sysctlgatherstruct(addr, size, shminfo_scgsv);
+ break;
+ case X_SEMINFO:
+ sysctlgatherstruct(addr, size, seminfo_scgsv);
+ break;
+ case X_MSGINFO:
+ sysctlgatherstruct(addr, size, msginfo_scgsv);
+ break;
+ default:
+ tsiz = size;
+ rv = sysctlbyname(sym2sysctl[idx], addr, &tsiz,
+ NULL, 0);
+ if (rv == -1)
+ err(1, "sysctlbyname: %s", sym2sysctl[idx]);
+ if (tsiz != size)
+ errx(1, "%s size mismatch "
+ "(expected %zu, got %zu)",
+ sym2sysctl[idx], size, tsiz);
+ break;
+ }
+ }
+}
diff --git a/usr.bin/ipcs/ipc.h b/usr.bin/ipcs/ipc.h
new file mode 100644
index 000000000000..6a9c1ae71571
--- /dev/null
+++ b/usr.bin/ipcs/ipc.h
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+ * 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 ``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.
+ *
+ * The split of ipcs.c into ipcs.c and ipc.c to accommodate the
+ * changes in ipcrm.c was done by Edwin Groothuis <edwin@FreeBSD.org>
+ */
+
+/* Part of struct nlist symbols[] */
+#define X_SEMA 0
+#define X_SEMINFO 1
+#define X_MSGINFO 2
+#define X_MSQIDS 3
+#define X_SHMINFO 4
+#define X_SHMSEGS 5
+
+#define SHMINFO 1
+#define SHMTOTAL 2
+#define MSGINFO 4
+#define MSGTOTAL 8
+#define SEMINFO 16
+#define SEMTOTAL 32
+
+#define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem"))
+#define IPC_TO_STRING(x) (x == 'Q' ? "message queue" : \
+ (x == 'M' ? "shared memory segment" : "semaphore"))
+
+/* SysCtlGatherStruct structure. */
+struct scgs_vector {
+ const char *sysctl;
+ size_t offset;
+ size_t size;
+};
+
+void kget(int idx, void *addr, size_t size);
+void sysctlgatherstruct(void *addr, size_t size, struct scgs_vector *vec);
+
+extern int use_sysctl;
+extern struct nlist symbols[];
+extern kvm_t *kd;
+
+extern struct semid_kernel *sema;
+extern struct msqid_kernel *msqids;
+extern struct shmid_kernel *shmsegs;
+extern struct seminfo seminfo;
+extern struct msginfo msginfo;
+extern struct shminfo shminfo;
diff --git a/usr.bin/ipcs/ipcs.1 b/usr.bin/ipcs/ipcs.1
new file mode 100644
index 000000000000..cb477220c971
--- /dev/null
+++ b/usr.bin/ipcs/ipcs.1
@@ -0,0 +1,174 @@
+.\"
+.\" Copyright (c) 1994 SigmaSoft, Th. Lockert
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by SigmaSoft, Th. Lockert.
+.\" 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.
+.\"
+.Dd March 24, 2004
+.Dt "IPCS" 1
+.Os
+.Sh NAME
+.Nm ipcs
+.Nd report System V interprocess communication facilities status
+.Sh SYNOPSIS
+.Nm
+.Op Fl abcmopqstMQSTy
+.Op Fl C Ar core
+.Op Fl N Ar system
+.Op Fl u Ar user
+.Sh DESCRIPTION
+The
+.Nm
+utility provides information on System V interprocess communication
+(IPC) facilities on the system.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Show the maximum amount of information possible when
+displaying active semaphores, message queues,
+and shared memory segments.
+(This is shorthand for specifying the
+.Fl b ,
+.Fl c ,
+.Fl o ,
+.Fl p ,
+and
+.Fl t
+options.)
+.It Fl b
+Show the maximum allowed sizes for active semaphores, message queues,
+and shared memory segments.
+The
+.Dq maximum allowed size
+is the maximum number of bytes in a message on a message queue,
+the size of a shared memory segment,
+or the number of semaphores in a set of semaphores.
+.It Fl c
+Show the creator's name and group for active semaphores, message queues,
+and shared memory segments.
+.It Fl m
+Display information about active shared memory segments.
+.It Fl o
+Show outstanding usage for active message queues,
+and shared memory segments.
+The
+.Dq outstanding usage
+is the number of messages in a message queue, or the number
+of processes attached to a shared memory segment.
+.It Fl p
+Show the process ID information for active semaphores, message queues,
+and shared memory segments.
+The
+.Dq process ID information
+is the last process to send a message to or receive a message from
+a message queue,
+the process that created a semaphore, or the last process to attach
+or detach a shared memory segment.
+.It Fl q
+Display information about active message queues.
+.It Fl s
+Display information about active semaphores.
+.It Fl t
+Show access times for active semaphores, message queues,
+and shared memory segments.
+The access times is the time
+of the last control operation on an IPC object,
+the last send or receive of a message,
+the last attach or detach of a shared memory segment,
+or the last operation on a semaphore.
+.It Fl C Ar core
+Extract values associated with the name list from the specified
+core instead of the default
+.Pa /dev/kmem .
+Implies
+.Fl y .
+.It Fl M
+Display system information about shared memory.
+.It Fl N Ar system
+Extract the name list from the specified system instead of the
+default
+.Pa /boot/kernel/kernel .
+Implies
+.Fl y .
+.It Fl Q
+Display system information about messages queues.
+.It Fl S
+Display system information about semaphores.
+.It Fl T
+Display system information about shared memory, message queues
+and semaphores.
+.It Fl y
+Use the
+.Xr kvm 3
+interface instead of the
+.Xr sysctl 3
+interface to extract the required information.
+If
+.Nm
+is to operate on the running system,
+using
+.Xr kvm 3
+will require read privileges to
+.Pa /dev/kmem .
+.It Fl u Ar user
+Display information about IPC mechanisms owned by
+.Pa user .
+User specification can be in the form of a numeric UID or
+a login name.
+.El
+.Pp
+If none of the
+.Fl M ,
+.Fl m ,
+.Fl Q ,
+.Fl q ,
+.Fl S ,
+or
+.Fl s
+options are specified, information about all active IPC facilities is
+listed.
+.Sh RESTRICTIONS
+System data structures may change while
+.Nm
+is running; the output of
+.Nm
+is not guaranteed to be consistent.
+.Sh FILES
+.Bl -tag -width /boot/kernel/kernel -compact
+.It Pa /dev/kmem
+default kernel memory
+.It Pa /boot/kernel/kernel
+default system name list
+.El
+.Sh SEE ALSO
+.Xr ipcrm 1
+.Sh AUTHORS
+.An Thorsten Lockert Aq Mt tholo@sigmasoft.com
+.Sh BUGS
+This manual page is woefully incomplete, because it does not
+at all attempt to explain the information printed by
+.Nm .
diff --git a/usr.bin/ipcs/ipcs.c b/usr.bin/ipcs/ipcs.c
new file mode 100644
index 000000000000..99e2c8f09218
--- /dev/null
+++ b/usr.bin/ipcs/ipcs.c
@@ -0,0 +1,555 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+ * 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 ``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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#define _WANT_SYSVMSG_INTERNALS
+#include <sys/msg.h>
+#define _WANT_SYSVSEM_INTERNALS
+#include <sys/sem.h>
+#define _WANT_SYSVSHM_INTERNALS
+#include <sys/shm.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <kvm.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ipc.h"
+
+char *fmt_perm(u_short);
+void cvt_time(time_t, char *);
+void usage(void);
+uid_t user2uid(char *username);
+
+void print_kmsqtotal(struct msginfo msginfo);
+void print_kmsqheader(int option);
+void print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr);
+void print_kshmtotal(struct shminfo shminfo);
+void print_kshmheader(int option);
+void print_kshmptr(int i, int option, struct shmid_kernel *kshmptr);
+void print_ksemtotal(struct seminfo seminfo);
+void print_ksemheader(int option);
+void print_ksemptr(int i, int option, struct semid_kernel *ksemaptr);
+
+char *
+fmt_perm(u_short mode)
+{
+ static char buffer[100];
+
+ buffer[0] = '-';
+ buffer[1] = '-';
+ buffer[2] = ((mode & 0400) ? 'r' : '-');
+ buffer[3] = ((mode & 0200) ? 'w' : '-');
+ buffer[4] = ((mode & 0100) ? 'a' : '-');
+ buffer[5] = ((mode & 0040) ? 'r' : '-');
+ buffer[6] = ((mode & 0020) ? 'w' : '-');
+ buffer[7] = ((mode & 0010) ? 'a' : '-');
+ buffer[8] = ((mode & 0004) ? 'r' : '-');
+ buffer[9] = ((mode & 0002) ? 'w' : '-');
+ buffer[10] = ((mode & 0001) ? 'a' : '-');
+ buffer[11] = '\0';
+ return (&buffer[0]);
+}
+
+void
+cvt_time(time_t t, char *buf)
+{
+ struct tm *tm;
+
+ if (t == 0) {
+ strcpy(buf, "no-entry");
+ } else {
+ tm = localtime(&t);
+ sprintf(buf, "%2d:%02d:%02d",
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ }
+}
+
+#define BIGGEST 1
+#define CREATOR 2
+#define OUTSTANDING 4
+#define PID 8
+#define TIME 16
+
+int
+main(int argc, char *argv[])
+{
+ int display = SHMINFO | MSGINFO | SEMINFO;
+ int option = 0;
+ char *core = NULL, *user = NULL, *namelist = NULL;
+ char kvmoferr[_POSIX2_LINE_MAX]; /* Error buf for kvm_openfiles. */
+ int i;
+ u_long shmidx;
+ uid_t uid = 0;
+
+ while ((i = getopt(argc, argv, "MmQqSsabC:cN:optTu:y")) != -1)
+ switch (i) {
+ case 'a':
+ option |= BIGGEST | CREATOR | OUTSTANDING | PID | TIME;
+ break;
+ case 'b':
+ option |= BIGGEST;
+ break;
+ case 'C':
+ core = optarg;
+ break;
+ case 'c':
+ option |= CREATOR;
+ break;
+ case 'M':
+ display = SHMTOTAL;
+ break;
+ case 'm':
+ display = SHMINFO;
+ break;
+ case 'N':
+ namelist = optarg;
+ break;
+ case 'o':
+ option |= OUTSTANDING;
+ break;
+ case 'p':
+ option |= PID;
+ break;
+ case 'Q':
+ display = MSGTOTAL;
+ break;
+ case 'q':
+ display = MSGINFO;
+ break;
+ case 'S':
+ display = SEMTOTAL;
+ break;
+ case 's':
+ display = SEMINFO;
+ break;
+ case 'T':
+ display = SHMTOTAL | MSGTOTAL | SEMTOTAL;
+ break;
+ case 't':
+ option |= TIME;
+ break;
+ case 'u':
+ user = optarg;
+ uid = user2uid(user);
+ break;
+ case 'y':
+ use_sysctl = 0;
+ break;
+ default:
+ usage();
+ }
+
+ /*
+ * If paths to the exec file or core file were specified, we
+ * aren't operating on the running kernel, so we can't use
+ * sysctl.
+ */
+ if (namelist != NULL || core != NULL)
+ use_sysctl = 0;
+
+ if (!use_sysctl) {
+ kd = kvm_openfiles(namelist, core, NULL, O_RDONLY, kvmoferr);
+ if (kd == NULL)
+ errx(1, "kvm_openfiles: %s", kvmoferr);
+ switch (kvm_nlist(kd, symbols)) {
+ case 0:
+ break;
+ case -1:
+ errx(1, "unable to read kernel symbol table");
+ default:
+ break;
+ }
+ }
+
+ kget(X_MSGINFO, &msginfo, sizeof(msginfo));
+ if (display & (MSGINFO | MSGTOTAL)) {
+ if (display & MSGTOTAL)
+ print_kmsqtotal(msginfo);
+
+ if (display & MSGINFO) {
+ struct msqid_kernel *kxmsqids;
+ size_t kxmsqids_len;
+
+ kxmsqids_len =
+ sizeof(struct msqid_kernel) * msginfo.msgmni;
+ kxmsqids = malloc(kxmsqids_len);
+ kget(X_MSQIDS, kxmsqids, kxmsqids_len);
+
+ print_kmsqheader(option);
+
+ for (i = 0; i < msginfo.msgmni; i += 1) {
+ if (kxmsqids[i].u.msg_qbytes != 0) {
+ if (user &&
+ uid != kxmsqids[i].u.msg_perm.uid)
+ continue;
+
+ print_kmsqptr(i, option, &kxmsqids[i]);
+ }
+
+ }
+
+ printf("\n");
+ }
+ }
+
+ kget(X_SHMINFO, &shminfo, sizeof(shminfo));
+ if (display & (SHMINFO | SHMTOTAL)) {
+
+ if (display & SHMTOTAL)
+ print_kshmtotal(shminfo);
+
+ if (display & SHMINFO) {
+ struct shmid_kernel *kxshmids;
+ size_t kxshmids_len;
+
+ kxshmids_len =
+ sizeof(struct shmid_kernel) * shminfo.shmmni;
+ kxshmids = malloc(kxshmids_len);
+ kget(X_SHMSEGS, kxshmids, kxshmids_len);
+
+ print_kshmheader(option);
+
+ for (shmidx = 0; shmidx < shminfo.shmmni; shmidx += 1) {
+ if (kxshmids[shmidx].u.shm_perm.mode & 0x0800) {
+ if (user &&
+ uid != kxshmids[shmidx].u.shm_perm.uid)
+ continue;
+
+ print_kshmptr(shmidx, option, &kxshmids[shmidx]);
+ }
+ }
+ printf("\n");
+ }
+ }
+
+ kget(X_SEMINFO, &seminfo, sizeof(seminfo));
+ if (display & (SEMINFO | SEMTOTAL)) {
+ struct semid_kernel *kxsema;
+ size_t kxsema_len;
+
+ if (display & SEMTOTAL)
+ print_ksemtotal(seminfo);
+
+ if (display & SEMINFO) {
+ kxsema_len =
+ sizeof(struct semid_kernel) * seminfo.semmni;
+ kxsema = malloc(kxsema_len);
+ kget(X_SEMA, kxsema, kxsema_len);
+
+ print_ksemheader(option);
+
+ for (i = 0; i < seminfo.semmni; i += 1) {
+ if ((kxsema[i].u.sem_perm.mode & SEM_ALLOC)
+ != 0) {
+ if (user &&
+ uid != kxsema[i].u.sem_perm.uid)
+ continue;
+
+ print_ksemptr(i, option, &kxsema[i]);
+
+ }
+ }
+
+ printf("\n");
+ }
+ }
+
+ if (!use_sysctl)
+ kvm_close(kd);
+
+ exit(0);
+}
+
+void
+print_kmsqtotal(struct msginfo local_msginfo)
+{
+
+ printf("msginfo:\n");
+ printf("\tmsgmax: %12d\t(max characters in a message)\n",
+ local_msginfo.msgmax);
+ printf("\tmsgmni: %12d\t(# of message queues)\n",
+ local_msginfo.msgmni);
+ printf("\tmsgmnb: %12d\t(max characters in a message queue)\n",
+ local_msginfo.msgmnb);
+ printf("\tmsgtql: %12d\t(max # of messages in system)\n",
+ local_msginfo.msgtql);
+ printf("\tmsgssz: %12d\t(size of a message segment)\n",
+ local_msginfo.msgssz);
+ printf("\tmsgseg: %12d\t(# of message segments in system)\n\n",
+ local_msginfo.msgseg);
+}
+
+void print_kmsqheader(int option)
+{
+
+ printf("Message Queues:\n");
+ printf("T %12s %12s %-11s %-8s %-8s",
+ "ID", "KEY", "MODE", "OWNER", "GROUP");
+ if (option & CREATOR)
+ printf(" %-8s %-8s", "CREATOR", "CGROUP");
+ if (option & OUTSTANDING)
+ printf(" %20s %20s", "CBYTES", "QNUM");
+ if (option & BIGGEST)
+ printf(" %20s", "QBYTES");
+ if (option & PID)
+ printf(" %12s %12s", "LSPID", "LRPID");
+ if (option & TIME)
+ printf(" %-8s %-8s %-8s", "STIME", "RTIME", "CTIME");
+ printf("\n");
+}
+
+void
+print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr)
+{
+ char stime_buf[100], rtime_buf[100], ctime_buf[100];
+
+ cvt_time(kmsqptr->u.msg_stime, stime_buf);
+ cvt_time(kmsqptr->u.msg_rtime, rtime_buf);
+ cvt_time(kmsqptr->u.msg_ctime, ctime_buf);
+
+ printf("q %12d %12d %s %-8s %-8s",
+ IXSEQ_TO_IPCID(i, kmsqptr->u.msg_perm),
+ (int)kmsqptr->u.msg_perm.key,
+ fmt_perm(kmsqptr->u.msg_perm.mode),
+ user_from_uid(kmsqptr->u.msg_perm.uid, 0),
+ group_from_gid(kmsqptr->u.msg_perm.gid, 0));
+
+ if (option & CREATOR)
+ printf(" %-8s %-8s",
+ user_from_uid(kmsqptr->u.msg_perm.cuid, 0),
+ group_from_gid(kmsqptr->u.msg_perm.cgid, 0));
+
+ if (option & OUTSTANDING)
+ printf(" %12lu %12lu",
+ kmsqptr->u.msg_cbytes,
+ kmsqptr->u.msg_qnum);
+
+ if (option & BIGGEST)
+ printf(" %20lu", kmsqptr->u.msg_qbytes);
+
+ if (option & PID)
+ printf(" %12d %12d",
+ kmsqptr->u.msg_lspid,
+ kmsqptr->u.msg_lrpid);
+
+ if (option & TIME)
+ printf(" %s %s %s",
+ stime_buf,
+ rtime_buf,
+ ctime_buf);
+
+ printf("\n");
+}
+
+void
+print_kshmtotal(struct shminfo local_shminfo)
+{
+
+ printf("shminfo:\n");
+ printf("\tshmmax: %12lu\t(max shared memory segment size)\n",
+ local_shminfo.shmmax);
+ printf("\tshmmin: %12lu\t(min shared memory segment size)\n",
+ local_shminfo.shmmin);
+ printf("\tshmmni: %12lu\t(max number of shared memory identifiers)\n",
+ local_shminfo.shmmni);
+ printf("\tshmseg: %12lu\t(max shared memory segments per process)\n",
+ local_shminfo.shmseg);
+ printf("\tshmall: %12lu\t(max amount of shared memory in pages)\n\n",
+ local_shminfo.shmall);
+}
+
+void
+print_kshmheader(int option)
+{
+
+ printf("Shared Memory:\n");
+ printf("T %12s %12s %-11s %-8s %-8s",
+ "ID", "KEY", "MODE", "OWNER", "GROUP");
+ if (option & CREATOR)
+ printf(" %-8s %-8s", "CREATOR", "CGROUP");
+ if (option & OUTSTANDING)
+ printf(" %12s", "NATTCH");
+ if (option & BIGGEST)
+ printf(" %12s", "SEGSZ");
+ if (option & PID)
+ printf(" %12s %12s", "CPID", "LPID");
+ if (option & TIME)
+ printf(" %-8s %-8s %-8s", "ATIME", "DTIME", "CTIME");
+ printf("\n");
+}
+
+void
+print_kshmptr(int i, int option, struct shmid_kernel *kshmptr)
+{
+ char atime_buf[100], dtime_buf[100], ctime_buf[100];
+
+ cvt_time(kshmptr->u.shm_atime, atime_buf);
+ cvt_time(kshmptr->u.shm_dtime, dtime_buf);
+ cvt_time(kshmptr->u.shm_ctime, ctime_buf);
+
+ printf("m %12d %12d %s %-8s %-8s",
+ IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm),
+ (int)kshmptr->u.shm_perm.key,
+ fmt_perm(kshmptr->u.shm_perm.mode),
+ user_from_uid(kshmptr->u.shm_perm.uid, 0),
+ group_from_gid(kshmptr->u.shm_perm.gid, 0));
+
+ if (option & CREATOR)
+ printf(" %-8s %-8s",
+ user_from_uid(kshmptr->u.shm_perm.cuid, 0),
+ group_from_gid(kshmptr->u.shm_perm.cgid, 0));
+
+ if (option & OUTSTANDING)
+ printf(" %12d",
+ kshmptr->u.shm_nattch);
+
+ if (option & BIGGEST)
+ printf(" %12zu",
+ kshmptr->u.shm_segsz);
+
+ if (option & PID)
+ printf(" %12d %12d",
+ kshmptr->u.shm_cpid,
+ kshmptr->u.shm_lpid);
+
+ if (option & TIME)
+ printf(" %s %s %s",
+ atime_buf,
+ dtime_buf,
+ ctime_buf);
+
+ printf("\n");
+}
+
+void
+print_ksemtotal(struct seminfo local_seminfo)
+{
+
+ printf("seminfo:\n");
+ printf("\tsemmni: %12d\t(# of semaphore identifiers)\n",
+ local_seminfo.semmni);
+ printf("\tsemmns: %12d\t(# of semaphores in system)\n",
+ local_seminfo.semmns);
+ printf("\tsemmnu: %12d\t(# of undo structures in system)\n",
+ local_seminfo.semmnu);
+ printf("\tsemmsl: %12d\t(max # of semaphores per id)\n",
+ local_seminfo.semmsl);
+ printf("\tsemopm: %12d\t(max # of operations per semop call)\n",
+ local_seminfo.semopm);
+ printf("\tsemume: %12d\t(max # of undo entries per process)\n",
+ local_seminfo.semume);
+ printf("\tsemusz: %12d\t(size in bytes of undo structure)\n",
+ local_seminfo.semusz);
+ printf("\tsemvmx: %12d\t(semaphore maximum value)\n",
+ local_seminfo.semvmx);
+ printf("\tsemaem: %12d\t(adjust on exit max value)\n\n",
+ local_seminfo.semaem);
+}
+
+void
+print_ksemheader(int option)
+{
+
+ printf("Semaphores:\n");
+ printf("T %12s %12s %-11s %-8s %-8s",
+ "ID", "KEY", "MODE", "OWNER", "GROUP");
+ if (option & CREATOR)
+ printf(" %-8s %-8s", "CREATOR", "CGROUP");
+ if (option & BIGGEST)
+ printf(" %12s", "NSEMS");
+ if (option & TIME)
+ printf(" %-8s %-8s", "OTIME", "CTIME");
+ printf("\n");
+}
+
+void
+print_ksemptr(int i, int option, struct semid_kernel *ksemaptr)
+{
+ char ctime_buf[100], otime_buf[100];
+
+ cvt_time(ksemaptr->u.sem_otime, otime_buf);
+ cvt_time(ksemaptr->u.sem_ctime, ctime_buf);
+
+ printf("s %12d %12d %s %-8s %-8s",
+ IXSEQ_TO_IPCID(i, ksemaptr->u.sem_perm),
+ (int)ksemaptr->u.sem_perm.key,
+ fmt_perm(ksemaptr->u.sem_perm.mode),
+ user_from_uid(ksemaptr->u.sem_perm.uid, 0),
+ group_from_gid(ksemaptr->u.sem_perm.gid, 0));
+
+ if (option & CREATOR)
+ printf(" %-8s %-8s",
+ user_from_uid(ksemaptr->u.sem_perm.cuid, 0),
+ group_from_gid(ksemaptr->u.sem_perm.cgid, 0));
+
+ if (option & BIGGEST)
+ printf(" %12d",
+ ksemaptr->u.sem_nsems);
+
+ if (option & TIME)
+ printf(" %s %s",
+ otime_buf,
+ ctime_buf);
+
+ printf("\n");
+}
+
+uid_t
+user2uid(char *username)
+{
+ struct passwd *pwd;
+ uid_t uid;
+ char *r;
+
+ uid = strtoul(username, &r, 0);
+ if (!*r && r != username)
+ return (uid);
+ if ((pwd = getpwnam(username)) == NULL)
+ errx(1, "getpwnam failed: No such user");
+ endpwent();
+ return (pwd->pw_uid);
+}
+
+void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: "
+ "ipcs [-abcmopqstyMQST] [-C corefile] [-N namelist] [-u user]\n");
+ exit(1);
+}
diff --git a/usr.bin/iscsictl/Makefile b/usr.bin/iscsictl/Makefile
new file mode 100644
index 000000000000..c47b28e7be5e
--- /dev/null
+++ b/usr.bin/iscsictl/Makefile
@@ -0,0 +1,17 @@
+PACKAGE= iscsi
+PROG= iscsictl
+SRCS= iscsictl.c periphs.c parse.y token.l y.tab.h
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -I${SRCTOP}/sys/dev/iscsi
+CFLAGS+= -I${SRCTOP}/lib/libiscsiutil
+MAN= iscsi.conf.5 iscsictl.8
+
+LIBADD= iscsiutil util xo
+
+YFLAGS+= -v
+LFLAGS+= -i
+CLEANFILES= y.tab.c y.tab.h y.output
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/iscsictl/Makefile.depend b/usr.bin/iscsictl/Makefile.depend
new file mode 100644
index 000000000000..b88946febb66
--- /dev/null
+++ b/usr.bin/iscsictl/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcam \
+ lib/libcompiler_rt \
+ lib/libutil \
+ lib/libxo/libxo \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/iscsictl/iscsi.conf.5 b/usr.bin/iscsictl/iscsi.conf.5
new file mode 100644
index 000000000000..325d00bfabe6
--- /dev/null
+++ b/usr.bin/iscsictl/iscsi.conf.5
@@ -0,0 +1,214 @@
+.\" Copyright (c) 2007-2010 Daniel Braniss <danny@cs.huji.ac.il>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 February 25, 2022
+.Dt ISCSI.CONF 5
+.Os
+.Sh NAME
+.Nm iscsi.conf
+.Nd iSCSI initiator configuration file
+.Sh DESCRIPTION
+The
+.Nm
+configuration file is used by the
+.Xr iscsictl 8
+utility.
+The general syntax is:
+.Bf Li
+.Bd -literal
+ # this is a comment
+ nickname_1 {
+ variable = value;
+ ...
+ }
+ nickname_2 {
+ variable = value;
+ ...
+ }
+ ...
+.Ed
+.Ef
+.Bl -tag -width MaxConnections
+.It Cm AuthMethod
+Sets the authentication type.
+Type can be either
+.Qq Ar None ,
+or
+.Qq Ar CHAP .
+Default is
+.Qq Ar None .
+When set to
+.Cm CHAP ,
+both
+.Cm chapIName
+and
+.Cm chapSecret
+must be defined.
+.It Cm chapIName
+Login for CHAP authentication.
+.It Cm chapSecret
+Secret for CHAP authentication.
+.It Cm tgtChapName
+Target login for Mutual CHAP authentication.
+.It Cm tgtChapSecret
+Target secret for Mutual CHAP authentication.
+.It Cm HeaderDigest
+Sets the header digest; a checksum calculated over the header of iSCSI
+PDUs, and verified on receive.
+Digest can be either
+.Qq Ar None ,
+or
+.Qq Ar CRC32C .
+Default is
+.Qq Ar None .
+.It Cm DataDigest
+Sets the data digest; a checksum calculated over the Data Section of iSCSI
+PDUs, and verified on receive.
+Digest can be either
+.Qq Ar None ,
+or
+.Qq Ar CRC32C .
+Default is
+.Qq Ar None .
+.It Cm InitiatorName
+Sets the initiator name.
+By default, the name is concatenation of
+.Qq Ar iqn.1994-09.org.freebsd:
+with the hostname.
+.It Cm TargetName
+Sets the target name.
+Not required for discovery sessions.
+.It Cm TargetAddress
+Sets the target address and port, in
+.Sy address[:port]
+format.
+The
+.Sy address
+can be either an IP address, or hostname.
+The optional port defaults to 3260.
+.It Cm SessionType
+Sets the session type.
+Type can be either
+.Qq Ar Discovery ,
+or
+.Qq Ar Normal .
+Default is
+.Qq Ar Normal .
+For normal sessions, the
+.Sy TargetName
+must be defined.
+Discovery sessions result in the initiator connecting to all the targets
+returned by SendTargets iSCSI discovery with the defined
+.Sy TargetAddress .
+.It Cm Enable
+Enable or disable the session.
+State can be either
+.Qq Ar On ,
+or
+.Qq Ar Off .
+Default is
+.Qq Ar On .
+.It Cm Offload
+Name of selected iSCSI hardware offload driver.
+Default is
+.Qq Ar None .
+.It Cm Protocol
+Name of selected protocol.
+It can be either
+.Qq Ar iSER ,
+for iSCSI over RDMA, or
+.Qq Ar iSCSI .
+Default is
+.Qq Ar iSCSI .
+.It Cm dscp
+The DiffServ Codepoint used for sending data.
+The DSCP can be set to numeric, or hexadecimal values directly,
+as well as the well-defined
+.Qq Ar cs<n>
+and
+.Qq Ar af<xx>
+codepoints.
+Default is no specified dscp codepoint, which means the default
+of the outgoing interface is used.
+.It Cm pcp
+The 802.1Q Priority CodePoint used for sending packets.
+The PCP can be set to a value in the range between
+.Qq Ar 0
+to
+.Qq Ar 7 .
+When omitted, the default for the outgoing interface is used.
+.It Cm PingTimeout
+Specify the time in seconds to wait between pings (SCSI NOP), and
+for a ping response before declaring the session as dead and
+attempting a re-establishment.
+If this entry is not present in the conf file, the default value
+configured using
+.Qq Ar kern.iscsi.ping_timeout
+(default at
+.Qq Ar 5
+seconds) is taken by the driver.
+If present, the PingTimeout can be set to any positive value
+starting with
+.Qq Ar 1 .
+.It Cm LoginTimeout
+Specify the time in seconds to wait for a login PDU to be sent or
+received after trying to establish a new session.
+When no login PDU is received within this time, the login on a
+particular connection fails and a new reconnection attempt is made.
+If this entry is not present in the conf file, the default value of
+.Qq Ar 60
+seconds is used, as configured by
+.Qq Ar kern.iscsi.login_timeout .
+The LoginTimeout can be set to any positive value starting with
+.Qq Ar 1 .
+.El
+.Sh FILES
+.Bl -tag -width indent
+.It Pa /etc/iscsi.conf
+.El
+.Sh EXAMPLES
+.Bd -literal
+myiscsi { # nickname
+ targetaddress = iscsi1
+ targetname = iqn.1900.com.com:sn.123456
+}
+
+myiscsi6 { # nickname
+ targetaddress = [2001:db8::de:ef]:3260
+ targetname = iqn.1900.com.com:sn.123456
+}
+
+chaptest {
+ targetaddress = 10.0.0.1;
+ targetname = iqn.1900.com.com:sn.123456;
+ initiatorname = iqn.2005-01.il.ac.huji.cs:nobody;
+ authmethod = CHAP;
+ chapiname = iqn.2005-01.il.ac.huji.cs:nobody;
+ chapsecret = "secretsecret";
+}
+.Ed
+.Sh SEE ALSO
+.Xr iscsictl 8
+.\"Sh HISTORY
+.\"Sh AUTHORS
diff --git a/usr.bin/iscsictl/iscsictl.8 b/usr.bin/iscsictl/iscsictl.8
new file mode 100644
index 000000000000..74394063a007
--- /dev/null
+++ b/usr.bin/iscsictl/iscsictl.8
@@ -0,0 +1,207 @@
+.\" Copyright (c) 2012 The FreeBSD Foundation
+.\"
+.\" This software was developed by Edward Tomasz Napierala under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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 AUTHORS 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 AUTHORS 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 December 27, 2018
+.Dt ISCSICTL 8
+.Os
+.Sh NAME
+.Nm iscsictl
+.Nd iSCSI initiator management utility
+.Sh SYNOPSIS
+.Nm
+.Fl A
+.Fl p Ar portal Fl t Ar target
+.Op Fl u Ar user Fl s Ar secret
+.Op Fl w Ar timeout
+.Op Fl r
+.Op Fl e Cm on Ns | Ns Cm off
+.Nm
+.Fl A
+.Fl d Ar discovery-host
+.Op Fl u Ar user Fl s Ar secret
+.Op Fl r
+.Op Fl e Cm on Ns | Ns Cm off
+.Nm
+.Fl A
+.Fl a Op Fl c Ar path
+.Nm
+.Fl A
+.Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl M
+.Fl i Ar session-id
+.Op Fl p Ar portal
+.Op Fl t Ar target
+.Op Fl u Ar user
+.Op Fl s Ar secret
+.Op Fl e Cm on Ns | Ns Cm off
+.Nm
+.Fl M
+.Fl i Ar session-id
+.Op Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl R
+.Op Fl p Ar portal
+.Op Fl t Ar target
+.Nm
+.Fl R
+.Fl a
+.Nm
+.Fl R
+.Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl L
+.Op Fl v
+.Op Fl w Ar timeout
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to configure the iSCSI initiator.
+.Pp
+The following options are available:
+.Bl -tag -width "-d discovery-host"
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl A
+Add session.
+.It Fl M
+Modify session.
+.It Fl R
+Remove session.
+.It Fl L
+List sessions.
+.It Fl a
+When adding, add all sessions defined in the configuration file.
+When removing, remove all currently established sessions.
+.It Fl c Ar path
+Path to the configuration file.
+The default is
+.Pa /etc/iscsi.conf .
+.It Fl d Ar discovery-host
+Target host name or address used for SendTargets discovery.
+When used, it will add a temporary discovery session.
+After discovery is done, sessions will be added for each discovered target,
+and the temporary discovery session will be removed.
+.It Fl e Cm on Ns | Ns Cm off
+Enable or disable the session.
+This is ignored for discovery sessions, but gets passed down to normal
+sessions they add.
+.It Fl i Ar session-id
+Session ID, as displayed by
+.Nm
+.Fl v .
+.It Fl n Ar nickname
+The
+.Ar nickname
+of a session defined in the configuration file.
+.It Fl p Ar portal
+Target portal \(em host name or address \(em for statically defined targets.
+.It Fl r
+Use iSER (iSCSI over RDMA) instead of plain iSCSI over TCP/IP.
+.It Fl s Ar secret
+CHAP secret.
+.It Fl t Ar target
+Target name.
+.It Fl u Ar user
+CHAP login.
+.It Fl v
+Verbose mode.
+.It Fl w Ar timeout
+Instead of returning immediately, wait up to
+.Ar timeout
+seconds until all configured sessions are successfully established.
+.El
+.Pp
+Certain parameters are necessary when adding a session.
+One can specify these either via command line (using the
+.Fl t ,
+.Fl p ,
+.Fl u ,
+and
+.Fl s
+options), or configuration file (using the
+.Fl a
+or
+.Fl n
+options).
+Some functionality - for example mutual CHAP - is available only
+via configuration file.
+.Pp
+Since connecting to the target is performed in background, non-zero
+exit status does not mean that the session was successfully established.
+Use either
+.Nm Fl L
+to check the connection status, or the
+.Fl w
+flag to wait for session establishment.
+.Pp
+Note that in order for the iSCSI initiator to be able to connect to a target,
+the
+.Xr iscsid 8
+daemon must be running.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/iscsi.conf" -compact
+.It Pa /etc/iscsi.conf
+iSCSI initiator configuration file.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success, and >0 if an error occurs.
+.Sh EXAMPLES
+Attach to target iqn.2012-06.com.example:target0, served by 192.168.1.1:
+.Dl Nm Fl A Fl t Ar iqn.2012-06.com.example:target0 Fl p Ar 192.168.1.1
+.Pp
+Perform discovery on 192.168.1.1, and add disabled sessions for each
+discovered target; use
+.Nm -M -e on
+to connect them:
+.Dl Nm Fl A Fl d Ar 192.168.1.1 Fl e Ar off
+.Pp
+Disconnect all iSCSI sessions:
+.Dl Nm Fl Ra
+.Sh SEE ALSO
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
+.Xr iscsi 4 ,
+.Xr iscsi.conf 5 ,
+.Xr iscsid 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was developed by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org
+under sponsorship from the FreeBSD Foundation.
diff --git a/usr.bin/iscsictl/iscsictl.c b/usr.bin/iscsictl/iscsictl.c
new file mode 100644
index 000000000000..f78e47d226bf
--- /dev/null
+++ b/usr.bin/iscsictl/iscsictl.c
@@ -0,0 +1,963 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012 The FreeBSD Foundation
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libiscsiutil.h>
+#include <libxo/xo.h>
+
+#include <iscsi_ioctl.h>
+#include "iscsictl.h"
+
+struct conf *
+conf_new(void)
+{
+ struct conf *conf;
+
+ conf = calloc(1, sizeof(*conf));
+ if (conf == NULL)
+ xo_err(1, "calloc");
+
+ TAILQ_INIT(&conf->conf_targets);
+
+ return (conf);
+}
+
+struct target *
+target_find(struct conf *conf, const char *nickname)
+{
+ struct target *targ;
+
+ TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
+ if (targ->t_nickname != NULL &&
+ strcasecmp(targ->t_nickname, nickname) == 0)
+ return (targ);
+ }
+
+ return (NULL);
+}
+
+struct target *
+target_new(struct conf *conf)
+{
+ struct target *targ;
+
+ targ = calloc(1, sizeof(*targ));
+ if (targ == NULL)
+ xo_err(1, "calloc");
+ targ->t_conf = conf;
+ targ->t_dscp = -1;
+ targ->t_pcp = -1;
+ targ->t_pingtimeout = -1;
+ targ->t_logintimeout = -1;
+ TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
+
+ return (targ);
+}
+
+void
+target_delete(struct target *targ)
+{
+
+ TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
+ free(targ);
+}
+
+static char *
+default_initiator_name(void)
+{
+ char *name;
+ size_t namelen;
+ int error;
+
+ namelen = _POSIX_HOST_NAME_MAX + strlen(DEFAULT_IQN);
+
+ name = calloc(1, namelen + 1);
+ if (name == NULL)
+ xo_err(1, "calloc");
+ strcpy(name, DEFAULT_IQN);
+ error = gethostname(name + strlen(DEFAULT_IQN),
+ namelen - strlen(DEFAULT_IQN));
+ if (error != 0)
+ xo_err(1, "gethostname");
+
+ return (name);
+}
+
+int
+parse_enable(const char *enable)
+{
+ if (enable == NULL)
+ return (ENABLE_UNSPECIFIED);
+
+ if (strcasecmp(enable, "on") == 0 ||
+ strcasecmp(enable, "yes") == 0)
+ return (ENABLE_ON);
+
+ if (strcasecmp(enable, "off") == 0 ||
+ strcasecmp(enable, "no") == 0)
+ return (ENABLE_OFF);
+
+ return (ENABLE_UNSPECIFIED);
+}
+
+void
+conf_verify(struct conf *conf)
+{
+ struct target *targ;
+
+ TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
+ assert(targ->t_nickname != NULL);
+ if (targ->t_session_type == SESSION_TYPE_UNSPECIFIED)
+ targ->t_session_type = SESSION_TYPE_NORMAL;
+ if (targ->t_session_type == SESSION_TYPE_NORMAL &&
+ targ->t_name == NULL)
+ xo_errx(1, "missing TargetName for target \"%s\"",
+ targ->t_nickname);
+ if (targ->t_session_type == SESSION_TYPE_DISCOVERY &&
+ targ->t_name != NULL)
+ xo_errx(1, "cannot specify TargetName for discovery "
+ "sessions for target \"%s\"", targ->t_nickname);
+ if (targ->t_name != NULL) {
+ if (valid_iscsi_name(targ->t_name, xo_warnx) == false)
+ xo_errx(1, "invalid target name \"%s\"",
+ targ->t_name);
+ }
+ if (targ->t_protocol == PROTOCOL_UNSPECIFIED)
+ targ->t_protocol = PROTOCOL_ISCSI;
+ if (targ->t_address == NULL)
+ xo_errx(1, "missing TargetAddress for target \"%s\"",
+ targ->t_nickname);
+ if (targ->t_initiator_name == NULL)
+ targ->t_initiator_name = default_initiator_name();
+ if (valid_iscsi_name(targ->t_initiator_name, xo_warnx) == false)
+ xo_errx(1, "invalid initiator name \"%s\"",
+ targ->t_initiator_name);
+ if (targ->t_header_digest == DIGEST_UNSPECIFIED)
+ targ->t_header_digest = DIGEST_NONE;
+ if (targ->t_data_digest == DIGEST_UNSPECIFIED)
+ targ->t_data_digest = DIGEST_NONE;
+ if (targ->t_auth_method == AUTH_METHOD_UNSPECIFIED) {
+ if (targ->t_user != NULL || targ->t_secret != NULL ||
+ targ->t_mutual_user != NULL ||
+ targ->t_mutual_secret != NULL)
+ targ->t_auth_method =
+ AUTH_METHOD_CHAP;
+ else
+ targ->t_auth_method =
+ AUTH_METHOD_NONE;
+ }
+ if (targ->t_auth_method == AUTH_METHOD_CHAP) {
+ if (targ->t_user == NULL) {
+ xo_errx(1, "missing chapIName for target \"%s\"",
+ targ->t_nickname);
+ }
+ if (targ->t_secret == NULL)
+ xo_errx(1, "missing chapSecret for target \"%s\"",
+ targ->t_nickname);
+ if (targ->t_mutual_user != NULL ||
+ targ->t_mutual_secret != NULL) {
+ if (targ->t_mutual_user == NULL)
+ xo_errx(1, "missing tgtChapName for "
+ "target \"%s\"", targ->t_nickname);
+ if (targ->t_mutual_secret == NULL)
+ xo_errx(1, "missing tgtChapSecret for "
+ "target \"%s\"", targ->t_nickname);
+ }
+ }
+ }
+}
+
+static void
+conf_from_target(struct iscsi_session_conf *conf,
+ const struct target *targ)
+{
+ memset(conf, 0, sizeof(*conf));
+
+ /*
+ * XXX: Check bounds and return error instead of silently truncating.
+ */
+ if (targ->t_initiator_name != NULL)
+ strlcpy(conf->isc_initiator, targ->t_initiator_name,
+ sizeof(conf->isc_initiator));
+ if (targ->t_initiator_address != NULL)
+ strlcpy(conf->isc_initiator_addr, targ->t_initiator_address,
+ sizeof(conf->isc_initiator_addr));
+ if (targ->t_initiator_alias != NULL)
+ strlcpy(conf->isc_initiator_alias, targ->t_initiator_alias,
+ sizeof(conf->isc_initiator_alias));
+ if (targ->t_name != NULL)
+ strlcpy(conf->isc_target, targ->t_name,
+ sizeof(conf->isc_target));
+ if (targ->t_address != NULL)
+ strlcpy(conf->isc_target_addr, targ->t_address,
+ sizeof(conf->isc_target_addr));
+ if (targ->t_user != NULL)
+ strlcpy(conf->isc_user, targ->t_user,
+ sizeof(conf->isc_user));
+ if (targ->t_secret != NULL)
+ strlcpy(conf->isc_secret, targ->t_secret,
+ sizeof(conf->isc_secret));
+ if (targ->t_mutual_user != NULL)
+ strlcpy(conf->isc_mutual_user, targ->t_mutual_user,
+ sizeof(conf->isc_mutual_user));
+ if (targ->t_mutual_secret != NULL)
+ strlcpy(conf->isc_mutual_secret, targ->t_mutual_secret,
+ sizeof(conf->isc_mutual_secret));
+ if (targ->t_session_type == SESSION_TYPE_DISCOVERY)
+ conf->isc_discovery = 1;
+ if (targ->t_enable != ENABLE_OFF)
+ conf->isc_enable = 1;
+ if (targ->t_protocol == PROTOCOL_ISER)
+ conf->isc_iser = 1;
+ if (targ->t_offload != NULL)
+ strlcpy(conf->isc_offload, targ->t_offload,
+ sizeof(conf->isc_offload));
+ if (targ->t_header_digest == DIGEST_CRC32C)
+ conf->isc_header_digest = ISCSI_DIGEST_CRC32C;
+ else
+ conf->isc_header_digest = ISCSI_DIGEST_NONE;
+ if (targ->t_data_digest == DIGEST_CRC32C)
+ conf->isc_data_digest = ISCSI_DIGEST_CRC32C;
+ else
+ conf->isc_data_digest = ISCSI_DIGEST_NONE;
+ conf->isc_dscp = targ->t_dscp;
+ conf->isc_pcp = targ->t_pcp;
+ conf->isc_ping_timeout = targ->t_pingtimeout;
+ conf->isc_login_timeout = targ->t_logintimeout;
+}
+
+static int
+kernel_add(int iscsi_fd, const struct target *targ)
+{
+ struct iscsi_session_add isa;
+ int error;
+
+ memset(&isa, 0, sizeof(isa));
+ conf_from_target(&isa.isa_conf, targ);
+ error = ioctl(iscsi_fd, ISCSISADD, &isa);
+ if (error != 0)
+ xo_warn("ISCSISADD");
+ return (error);
+}
+
+static int
+kernel_modify(int iscsi_fd, unsigned int session_id, const struct target *targ)
+{
+ struct iscsi_session_modify ism;
+ int error;
+
+ memset(&ism, 0, sizeof(ism));
+ ism.ism_session_id = session_id;
+ conf_from_target(&ism.ism_conf, targ);
+ error = ioctl(iscsi_fd, ISCSISMODIFY, &ism);
+ if (error != 0)
+ xo_warn("ISCSISMODIFY");
+ return (error);
+}
+
+static void
+kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target,
+ const char *target_addr, const char *user, const char *secret, int enable)
+{
+ struct iscsi_session_state *states = NULL;
+ struct iscsi_session_state *state;
+ struct iscsi_session_conf *conf;
+ struct iscsi_session_list isl;
+ struct iscsi_session_modify ism;
+ unsigned int i, nentries = 1;
+ int error;
+
+ for (;;) {
+ states = realloc(states,
+ nentries * sizeof(struct iscsi_session_state));
+ if (states == NULL)
+ xo_err(1, "realloc");
+
+ memset(&isl, 0, sizeof(isl));
+ isl.isl_nentries = nentries;
+ isl.isl_pstates = states;
+
+ error = ioctl(iscsi_fd, ISCSISLIST, &isl);
+ if (error != 0 && errno == EMSGSIZE) {
+ nentries *= 4;
+ continue;
+ }
+ break;
+ }
+ if (error != 0)
+ xo_errx(1, "ISCSISLIST");
+
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+
+ if (state->iss_id == session_id)
+ break;
+ }
+ if (i == isl.isl_nentries)
+ xo_errx(1, "session-id %u not found", session_id);
+
+ conf = &state->iss_conf;
+
+ if (target != NULL)
+ strlcpy(conf->isc_target, target, sizeof(conf->isc_target));
+ if (target_addr != NULL)
+ strlcpy(conf->isc_target_addr, target_addr,
+ sizeof(conf->isc_target_addr));
+ if (user != NULL)
+ strlcpy(conf->isc_user, user, sizeof(conf->isc_user));
+ if (secret != NULL)
+ strlcpy(conf->isc_secret, secret, sizeof(conf->isc_secret));
+ if (enable == ENABLE_ON)
+ conf->isc_enable = 1;
+ else if (enable == ENABLE_OFF)
+ conf->isc_enable = 0;
+
+ memset(&ism, 0, sizeof(ism));
+ ism.ism_session_id = session_id;
+ memcpy(&ism.ism_conf, conf, sizeof(ism.ism_conf));
+ error = ioctl(iscsi_fd, ISCSISMODIFY, &ism);
+ if (error != 0)
+ xo_warn("ISCSISMODIFY");
+}
+
+static int
+kernel_remove(int iscsi_fd, const struct target *targ)
+{
+ struct iscsi_session_remove isr;
+ int error;
+
+ memset(&isr, 0, sizeof(isr));
+ conf_from_target(&isr.isr_conf, targ);
+ error = ioctl(iscsi_fd, ISCSISREMOVE, &isr);
+ if (error != 0)
+ xo_warn("ISCSISREMOVE");
+ return (error);
+}
+
+/*
+ * XXX: Add filtering.
+ */
+static int
+kernel_list(int iscsi_fd, const struct target *targ __unused,
+ int verbose)
+{
+ struct iscsi_session_state *states = NULL;
+ const struct iscsi_session_state *state;
+ const struct iscsi_session_conf *conf;
+ struct iscsi_session_list isl;
+ unsigned int i, nentries = 1;
+ int error;
+
+ for (;;) {
+ states = realloc(states,
+ nentries * sizeof(struct iscsi_session_state));
+ if (states == NULL)
+ xo_err(1, "realloc");
+
+ memset(&isl, 0, sizeof(isl));
+ isl.isl_nentries = nentries;
+ isl.isl_pstates = states;
+
+ error = ioctl(iscsi_fd, ISCSISLIST, &isl);
+ if (error != 0 && errno == EMSGSIZE) {
+ nentries *= 4;
+ continue;
+ }
+ break;
+ }
+ if (error != 0) {
+ xo_warn("ISCSISLIST");
+ return (error);
+ }
+
+ if (verbose != 0) {
+ xo_open_list("session");
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+ conf = &state->iss_conf;
+
+ xo_open_instance("session");
+
+ /*
+ * Display-only modifier as this information
+ * is also present within the 'session' container
+ */
+ xo_emit("{L:/%-26s}{V:sessionId/%u}\n",
+ "Session ID:", state->iss_id);
+
+ xo_open_container("initiator");
+ xo_emit("{L:/%-26s}{V:name/%s}\n",
+ "Initiator name:", conf->isc_initiator);
+ xo_emit("{L:/%-26s}{V:portal/%s}\n",
+ "Initiator portal:", conf->isc_initiator_addr);
+ xo_emit("{L:/%-26s}{V:alias/%s}\n",
+ "Initiator alias:", conf->isc_initiator_alias);
+ xo_close_container("initiator");
+
+ xo_open_container("target");
+ xo_emit("{L:/%-26s}{V:name/%s}\n",
+ "Target name:", conf->isc_target);
+ xo_emit("{L:/%-26s}{V:portal/%s}\n",
+ "Target portal:", conf->isc_target_addr);
+ xo_emit("{L:/%-26s}{V:alias/%s}\n",
+ "Target alias:", state->iss_target_alias);
+ if (conf->isc_dscp != -1)
+ xo_emit("{L:/%-26s}{V:dscp/0x%02x}\n",
+ "Target DSCP:", conf->isc_dscp);
+ if (conf->isc_pcp != -1)
+ xo_emit("{L:/%-26s}{V:pcp/0x%02x}\n",
+ "Target PCP:", conf->isc_pcp);
+ if (conf->isc_ping_timeout != -1)
+ xo_emit("{L:/%-26s}{V:PingTimeout/%d}\n",
+ "Target PingTimeout:",
+ conf->isc_ping_timeout);
+ if (conf->isc_login_timeout != -1)
+ xo_emit("{L:/%-26s}{V:LoginTimeout/%d}\n",
+ "Target LoginTimeout:",
+ conf->isc_login_timeout);
+ xo_close_container("target");
+
+ xo_open_container("auth");
+ xo_emit("{L:/%-26s}{V:user/%s}\n",
+ "User:", conf->isc_user);
+ xo_emit("{L:/%-26s}{V:secret/%s}\n",
+ "Secret:", conf->isc_secret);
+ xo_emit("{L:/%-26s}{V:mutualUser/%s}\n",
+ "Mutual user:", conf->isc_mutual_user);
+ xo_emit("{L:/%-26s}{V:mutualSecret/%s}\n",
+ "Mutual secret:", conf->isc_mutual_secret);
+ xo_close_container("auth");
+
+ xo_emit("{L:/%-26s}{V:type/%s}\n",
+ "Session type:",
+ conf->isc_discovery ? "Discovery" : "Normal");
+ xo_emit("{L:/%-26s}{V:enable/%s}\n",
+ "Enable:",
+ conf->isc_enable ? "Yes" : "No");
+ xo_emit("{L:/%-26s}{V:state/%s}\n",
+ "Session state:",
+ state->iss_connected ? "Connected" : "Disconnected");
+ xo_emit("{L:/%-26s}{V:failureReason/%s}\n",
+ "Failure reason:", state->iss_reason);
+ xo_emit("{L:/%-26s}{V:headerDigest/%s}\n",
+ "Header digest:",
+ state->iss_header_digest == ISCSI_DIGEST_CRC32C ?
+ "CRC32C" : "None");
+ xo_emit("{L:/%-26s}{V:dataDigest/%s}\n",
+ "Data digest:",
+ state->iss_data_digest == ISCSI_DIGEST_CRC32C ?
+ "CRC32C" : "None");
+ xo_emit("{L:/%-26s}{V:recvDataSegmentLen/%d}\n",
+ "MaxRecvDataSegmentLength:",
+ state->iss_max_recv_data_segment_length);
+ xo_emit("{L:/%-26s}{V:sendDataSegmentLen/%d}\n",
+ "MaxSendDataSegmentLength:",
+ state->iss_max_send_data_segment_length);
+ xo_emit("{L:/%-26s}{V:maxBurstLen/%d}\n",
+ "MaxBurstLen:", state->iss_max_burst_length);
+ xo_emit("{L:/%-26s}{V:firstBurstLen/%d}\n",
+ "FirstBurstLen:", state->iss_first_burst_length);
+ xo_emit("{L:/%-26s}{V:immediateData/%s}\n",
+ "ImmediateData:", state->iss_immediate_data ? "Yes" : "No");
+ xo_emit("{L:/%-26s}{V:iSER/%s}\n",
+ "iSER (RDMA):", conf->isc_iser ? "Yes" : "No");
+ xo_emit("{L:/%-26s}{V:offloadDriver/%s}\n",
+ "Offload driver:", state->iss_offload);
+ xo_emit("{L:/%-26s}",
+ "Device nodes:");
+ print_periphs(state->iss_id);
+ xo_emit("\n\n");
+ xo_close_instance("session");
+ }
+ xo_close_list("session");
+ } else {
+ xo_emit("{T:/%-36s} {T:/%-16s} {T:/%s}\n",
+ "Target name", "Target portal", "State");
+
+ if (isl.isl_nentries != 0)
+ xo_open_list("session");
+ for (i = 0; i < isl.isl_nentries; i++) {
+
+ state = &states[i];
+ conf = &state->iss_conf;
+
+ xo_open_instance("session");
+ xo_emit("{V:name/%-36s/%s} {V:portal/%-16s/%s} ",
+ conf->isc_target, conf->isc_target_addr);
+
+ if (state->iss_reason[0] != '\0' &&
+ conf->isc_enable != 0) {
+ xo_emit("{V:state/%s}\n", state->iss_reason);
+ } else {
+ if (conf->isc_discovery) {
+ xo_emit("{V:state}\n", "Discovery");
+ } else if (conf->isc_enable == 0) {
+ xo_emit("{V:state}\n", "Disabled");
+ } else if (state->iss_connected) {
+ xo_emit("{V:state}: ", "Connected");
+ print_periphs(state->iss_id);
+ xo_emit("\n");
+ } else {
+ xo_emit("{V:state}\n", "Disconnected");
+ }
+ }
+ xo_close_instance("session");
+ }
+ if (isl.isl_nentries != 0)
+ xo_close_list("session");
+ }
+
+ return (0);
+}
+
+static int
+kernel_wait(int iscsi_fd, int timeout)
+{
+ struct iscsi_session_state *states = NULL;
+ const struct iscsi_session_state *state;
+ struct iscsi_session_list isl;
+ unsigned int i, nentries = 1;
+ bool all_connected;
+ int error;
+
+ for (;;) {
+ for (;;) {
+ states = realloc(states,
+ nentries * sizeof(struct iscsi_session_state));
+ if (states == NULL)
+ xo_err(1, "realloc");
+
+ memset(&isl, 0, sizeof(isl));
+ isl.isl_nentries = nentries;
+ isl.isl_pstates = states;
+
+ error = ioctl(iscsi_fd, ISCSISLIST, &isl);
+ if (error != 0 && errno == EMSGSIZE) {
+ nentries *= 4;
+ continue;
+ }
+ break;
+ }
+ if (error != 0) {
+ xo_warn("ISCSISLIST");
+ return (error);
+ }
+
+ all_connected = true;
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+
+ if (!state->iss_connected) {
+ all_connected = false;
+ break;
+ }
+ }
+
+ if (all_connected)
+ return (0);
+
+ sleep(1);
+
+ if (timeout > 0) {
+ timeout--;
+ if (timeout == 0)
+ return (1);
+ }
+ }
+}
+
+static void
+usage(void)
+{
+
+ xo_error("usage: iscsictl -A -p portal -t target "
+ "[-u user -s secret] [-w timeout] [-e on | off]\n");
+ xo_error(" iscsictl -A -d discovery-host "
+ "[-u user -s secret] [-e on | off]\n");
+ xo_error(" iscsictl -A -a [-c path]\n");
+ xo_error(" iscsictl -A -n nickname [-c path]\n");
+ xo_error(" iscsictl -M -i session-id [-p portal] "
+ "[-t target] [-u user] [-s secret] [-e on | off]\n");
+ xo_error(" iscsictl -M -i session-id -n nickname "
+ "[-c path]\n");
+ xo_error(" iscsictl -R [-p portal] [-t target]\n");
+ xo_error(" iscsictl -R -a\n");
+ xo_error(" iscsictl -R -n nickname [-c path]\n");
+ xo_error(" iscsictl -L [-v] [-w timeout]\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int Aflag = 0, Mflag = 0, Rflag = 0, Lflag = 0, aflag = 0,
+ rflag = 0, vflag = 0;
+ const char *conf_path = DEFAULT_CONFIG_PATH;
+ char *nickname = NULL, *discovery_host = NULL, *portal = NULL,
+ *target = NULL, *user = NULL, *secret = NULL;
+ int timeout = -1, enable = ENABLE_UNSPECIFIED;
+ long long session_id = -1;
+ char *end;
+ int ch, error, iscsi_fd, retval, saved_errno;
+ int failed = 0;
+ struct conf *conf;
+ struct target *targ;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+ xo_set_version(ISCSICTL_XO_VERSION);
+ xo_open_container("iscsictl");
+
+ while ((ch = getopt(argc, argv, "AMRLac:d:e:i:n:p:rt:u:s:vw:")) != -1) {
+ switch (ch) {
+ case 'A':
+ Aflag = 1;
+ break;
+ case 'M':
+ Mflag = 1;
+ break;
+ case 'R':
+ Rflag = 1;
+ break;
+ case 'L':
+ Lflag = 1;
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'c':
+ conf_path = optarg;
+ break;
+ case 'd':
+ discovery_host = optarg;
+ break;
+ case 'e':
+ enable = parse_enable(optarg);
+ if (enable == ENABLE_UNSPECIFIED) {
+ xo_errx(1, "invalid argument to -e, "
+ "must be either \"on\" or \"off\"");
+ }
+ break;
+ case 'i':
+ session_id = strtol(optarg, &end, 10);
+ if ((size_t)(end - optarg) != strlen(optarg))
+ xo_errx(1, "trailing characters after session-id");
+ if (session_id < 0)
+ xo_errx(1, "session-id cannot be negative");
+ if (session_id > UINT_MAX)
+ xo_errx(1, "session-id cannot be greater than %u",
+ UINT_MAX);
+ break;
+ case 'n':
+ nickname = optarg;
+ break;
+ case 'p':
+ portal = optarg;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 't':
+ target = optarg;
+ break;
+ case 'u':
+ user = optarg;
+ break;
+ case 's':
+ secret = optarg;
+ break;
+ case 'v':
+ vflag = 1;
+ break;
+ case 'w':
+ timeout = strtol(optarg, &end, 10);
+ if ((size_t)(end - optarg) != strlen(optarg))
+ xo_errx(1, "trailing characters after timeout");
+ if (timeout < 0)
+ xo_errx(1, "timeout cannot be negative");
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ if (argc != 0)
+ usage();
+
+ if (Aflag + Mflag + Rflag + Lflag == 0)
+ Lflag = 1;
+ if (Aflag + Mflag + Rflag + Lflag > 1)
+ xo_errx(1, "at most one of -A, -M, -R, or -L may be specified");
+
+ /*
+ * Note that we ignore unnecessary/inapplicable "-c" flag; so that
+ * people can do something like "alias ISCSICTL="iscsictl -c path"
+ * in shell scripts.
+ */
+ if (Aflag != 0) {
+ if (aflag != 0) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-a and -e are mutually exclusive");
+ if (portal != NULL)
+ xo_errx(1, "-a and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-a and -t are mutually exclusive");
+ if (user != NULL)
+ xo_errx(1, "-a and -u are mutually exclusive");
+ if (secret != NULL)
+ xo_errx(1, "-a and -s are mutually exclusive");
+ if (nickname != NULL)
+ xo_errx(1, "-a and -n are mutually exclusive");
+ if (discovery_host != NULL)
+ xo_errx(1, "-a and -d are mutually exclusive");
+ if (rflag != 0)
+ xo_errx(1, "-a and -r are mutually exclusive");
+ } else if (nickname != NULL) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-n and -e are mutually exclusive");
+ if (portal != NULL)
+ xo_errx(1, "-n and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-n and -t are mutually exclusive");
+ if (user != NULL)
+ xo_errx(1, "-n and -u are mutually exclusive");
+ if (secret != NULL)
+ xo_errx(1, "-n and -s are mutually exclusive");
+ if (discovery_host != NULL)
+ xo_errx(1, "-n and -d are mutually exclusive");
+ if (rflag != 0)
+ xo_errx(1, "-n and -r are mutually exclusive");
+ } else if (discovery_host != NULL) {
+ if (portal != NULL)
+ xo_errx(1, "-d and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-d and -t are mutually exclusive");
+ } else {
+ if (target == NULL && portal == NULL)
+ xo_errx(1, "must specify -a, -n or -t/-p");
+
+ if (target != NULL && portal == NULL)
+ xo_errx(1, "-t must always be used with -p");
+ if (portal != NULL && target == NULL)
+ xo_errx(1, "-p must always be used with -t");
+ }
+
+ if (user != NULL && secret == NULL)
+ xo_errx(1, "-u must always be used with -s");
+ if (secret != NULL && user == NULL)
+ xo_errx(1, "-s must always be used with -u");
+
+ if (session_id != -1)
+ xo_errx(1, "-i cannot be used with -A");
+ if (vflag != 0)
+ xo_errx(1, "-v cannot be used with -A");
+
+ } else if (Mflag != 0) {
+ if (session_id == -1)
+ xo_errx(1, "-M requires -i");
+
+ if (nickname != NULL) {
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-n and -e are mutually exclusive");
+ if (portal != NULL)
+ xo_errx(1, "-n and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-n and -t are mutually exclusive");
+ if (user != NULL)
+ xo_errx(1, "-n and -u are mutually exclusive");
+ if (secret != NULL)
+ xo_errx(1, "-n and -s are mutually exclusive");
+ }
+
+ if (aflag != 0)
+ xo_errx(1, "-a cannot be used with -M");
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -M");
+ if (rflag != 0)
+ xo_errx(1, "-r cannot be used with -M");
+ if (vflag != 0)
+ xo_errx(1, "-v cannot be used with -M");
+ if (timeout != -1)
+ xo_errx(1, "-w cannot be used with -M");
+
+ } else if (Rflag != 0) {
+ if (aflag != 0) {
+ if (portal != NULL)
+ xo_errx(1, "-a and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-a and -t are mutually exclusive");
+ if (nickname != NULL)
+ xo_errx(1, "-a and -n are mutually exclusive");
+ } else if (nickname != NULL) {
+ if (portal != NULL)
+ xo_errx(1, "-n and -p are mutually exclusive");
+ if (target != NULL)
+ xo_errx(1, "-n and -t are mutually exclusive");
+ } else if (target == NULL && portal == NULL) {
+ xo_errx(1, "must specify either -a, -n, -t, or -p");
+ }
+
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -R");
+ if (enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "-e cannot be used with -R");
+ if (session_id != -1)
+ xo_errx(1, "-i cannot be used with -R");
+ if (rflag != 0)
+ xo_errx(1, "-r cannot be used with -R");
+ if (user != NULL)
+ xo_errx(1, "-u cannot be used with -R");
+ if (secret != NULL)
+ xo_errx(1, "-s cannot be used with -R");
+ if (vflag != 0)
+ xo_errx(1, "-v cannot be used with -R");
+ if (timeout != -1)
+ xo_errx(1, "-w cannot be used with -R");
+
+ } else {
+ assert(Lflag != 0);
+
+ if (discovery_host != NULL)
+ xo_errx(1, "-d cannot be used with -L");
+ if (session_id != -1)
+ xo_errx(1, "-i cannot be used with -L");
+ if (nickname != NULL)
+ xo_errx(1, "-n cannot be used with -L");
+ if (portal != NULL)
+ xo_errx(1, "-p cannot be used with -L");
+ if (rflag != 0)
+ xo_errx(1, "-r cannot be used with -L");
+ if (target != NULL)
+ xo_errx(1, "-t cannot be used with -L");
+ if (user != NULL)
+ xo_errx(1, "-u cannot be used with -L");
+ if (secret != NULL)
+ xo_errx(1, "-s cannot be used with -L");
+ }
+
+ iscsi_fd = open(ISCSI_PATH, O_RDWR);
+ if (iscsi_fd < 0 && errno == ENOENT) {
+ saved_errno = errno;
+ retval = kldload("iscsi");
+ if (retval != -1)
+ iscsi_fd = open(ISCSI_PATH, O_RDWR);
+ else
+ errno = saved_errno;
+ }
+ if (iscsi_fd < 0)
+ xo_err(1, "failed to open %s", ISCSI_PATH);
+
+ if (Aflag != 0 && aflag != 0) {
+ conf = conf_new_from_file(conf_path);
+
+ TAILQ_FOREACH(targ, &conf->conf_targets, t_next)
+ failed += kernel_add(iscsi_fd, targ);
+ } else if (nickname != NULL) {
+ conf = conf_new_from_file(conf_path);
+ targ = target_find(conf, nickname);
+ if (targ == NULL)
+ xo_errx(1, "target %s not found in %s",
+ nickname, conf_path);
+
+ if (Aflag != 0)
+ failed += kernel_add(iscsi_fd, targ);
+ else if (Mflag != 0)
+ failed += kernel_modify(iscsi_fd, session_id, targ);
+ else if (Rflag != 0)
+ failed += kernel_remove(iscsi_fd, targ);
+ else
+ failed += kernel_list(iscsi_fd, targ, vflag);
+ } else if (Mflag != 0) {
+ kernel_modify_some(iscsi_fd, session_id, target, portal,
+ user, secret, enable);
+ } else {
+ if (Aflag != 0 && target != NULL) {
+ if (valid_iscsi_name(target, xo_warnx) == false)
+ xo_errx(1, "invalid target name \"%s\"", target);
+ }
+ conf = conf_new();
+ targ = target_new(conf);
+ targ->t_initiator_name = default_initiator_name();
+ targ->t_header_digest = DIGEST_NONE;
+ targ->t_data_digest = DIGEST_NONE;
+ targ->t_name = target;
+ if (discovery_host != NULL) {
+ targ->t_session_type = SESSION_TYPE_DISCOVERY;
+ targ->t_address = discovery_host;
+ } else {
+ targ->t_session_type = SESSION_TYPE_NORMAL;
+ targ->t_address = portal;
+ }
+ targ->t_enable = enable;
+ if (rflag != 0)
+ targ->t_protocol = PROTOCOL_ISER;
+ targ->t_user = user;
+ targ->t_secret = secret;
+
+ if (Aflag != 0)
+ failed += kernel_add(iscsi_fd, targ);
+ else if (Rflag != 0)
+ failed += kernel_remove(iscsi_fd, targ);
+ else
+ failed += kernel_list(iscsi_fd, targ, vflag);
+ }
+
+ if (timeout != -1)
+ failed += kernel_wait(iscsi_fd, timeout);
+
+ error = close(iscsi_fd);
+ if (error != 0)
+ xo_err(1, "close");
+
+ xo_close_container("iscsictl");
+ if (xo_finish() < 0)
+ xo_err(1, "stdout");
+
+ if (failed != 0)
+ exit(1);
+
+ exit(0);
+}
diff --git a/usr.bin/iscsictl/iscsictl.h b/usr.bin/iscsictl/iscsictl.h
new file mode 100644
index 000000000000..dea1a6712dd8
--- /dev/null
+++ b/usr.bin/iscsictl/iscsictl.h
@@ -0,0 +1,106 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012 The FreeBSD Foundation
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 ISCSICTL_H
+#define ISCSICTL_H
+
+#include <sys/queue.h>
+#include <stdbool.h>
+#include <libutil.h>
+
+#define DEFAULT_CONFIG_PATH "/etc/iscsi.conf"
+#define DEFAULT_IQN "iqn.1994-09.org.freebsd:"
+
+#define ISCSICTL_XO_VERSION "1"
+
+#define AUTH_METHOD_UNSPECIFIED 0
+#define AUTH_METHOD_NONE 1
+#define AUTH_METHOD_CHAP 2
+
+#define DIGEST_UNSPECIFIED 0
+#define DIGEST_NONE 1
+#define DIGEST_CRC32C 2
+
+#define SESSION_TYPE_UNSPECIFIED 0
+#define SESSION_TYPE_NORMAL 1
+#define SESSION_TYPE_DISCOVERY 2
+
+#define PROTOCOL_UNSPECIFIED 0
+#define PROTOCOL_ISCSI 1
+#define PROTOCOL_ISER 2
+
+#define ENABLE_UNSPECIFIED 0
+#define ENABLE_ON 1
+#define ENABLE_OFF 2
+
+struct target {
+ TAILQ_ENTRY(target) t_next;
+ struct conf *t_conf;
+ char *t_nickname;
+ char *t_name;
+ char *t_address;
+ char *t_initiator_name;
+ char *t_initiator_address;
+ char *t_initiator_alias;
+ int t_header_digest;
+ int t_data_digest;
+ int t_auth_method;
+ int t_session_type;
+ int t_enable;
+ int t_protocol;
+ int t_dscp;
+ int t_pcp;
+ int t_pingtimeout;
+ int t_logintimeout;
+ char *t_offload;
+ char *t_user;
+ char *t_secret;
+ char *t_mutual_user;
+ char *t_mutual_secret;
+};
+
+struct conf {
+ TAILQ_HEAD(, target) conf_targets;
+};
+
+struct conf *conf_new(void);
+struct conf *conf_new_from_file(const char *path);
+void conf_delete(struct conf *conf);
+void conf_verify(struct conf *conf);
+
+struct target *target_new(struct conf *conf);
+struct target *target_find(struct conf *conf, const char *nickname);
+void target_delete(struct target *ic);
+
+void print_periphs(int session_id);
+
+int parse_enable(const char *enable);
+
+#endif /* !ISCSICTL_H */
diff --git a/usr.bin/iscsictl/parse.y b/usr.bin/iscsictl/parse.y
new file mode 100644
index 000000000000..90e0e6320317
--- /dev/null
+++ b/usr.bin/iscsictl/parse.y
@@ -0,0 +1,466 @@
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012 The FreeBSD Foundation
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxo/xo.h>
+
+#include "iscsictl.h"
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+extern FILE *yyin;
+extern char *yytext;
+extern int lineno;
+
+static struct conf *conf;
+static struct target *target;
+
+extern void yyerror(const char *);
+extern void yyrestart(FILE *);
+
+%}
+
+%token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
+%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
+%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
+%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET DSCP PINGTIMEOUT LOGINTIMEOUT
+%token AF11 AF12 AF13 AF21 AF22 AF23 AF31 AF32 AF33 AF41 AF42 AF43
+%token BE EF CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7
+
+%union
+{
+ char *str;
+}
+
+%token <str> STR
+
+%%
+
+targets:
+ |
+ targets target
+ ;
+
+target: STR OPENING_BRACKET target_entries CLOSING_BRACKET
+ {
+ if (target_find(conf, $1) != NULL)
+ xo_errx(1, "duplicated target %s", $1);
+ target->t_nickname = $1;
+ target = target_new(conf);
+ }
+ ;
+
+target_entries:
+ |
+ target_entries target_entry
+ |
+ target_entries target_entry SEMICOLON
+ ;
+
+target_entry:
+ target_name
+ |
+ target_address
+ |
+ initiator_name
+ |
+ initiator_address
+ |
+ initiator_alias
+ |
+ user
+ |
+ secret
+ |
+ mutual_user
+ |
+ mutual_secret
+ |
+ auth_method
+ |
+ header_digest
+ |
+ data_digest
+ |
+ session_type
+ |
+ enable
+ |
+ offload
+ |
+ protocol
+ |
+ ignored
+ |
+ dscp
+ |
+ pcp
+ |
+ ping_timeout
+ |
+ login_timeout
+ ;
+
+target_name: TARGET_NAME EQUALS STR
+ {
+ if (target->t_name != NULL)
+ xo_errx(1, "duplicated TargetName at line %d", lineno);
+ target->t_name = $3;
+ }
+ ;
+
+target_address: TARGET_ADDRESS EQUALS STR
+ {
+ if (target->t_address != NULL)
+ xo_errx(1, "duplicated TargetAddress at line %d", lineno);
+ target->t_address = $3;
+ }
+ ;
+
+initiator_name: INITIATOR_NAME EQUALS STR
+ {
+ if (target->t_initiator_name != NULL)
+ xo_errx(1, "duplicated InitiatorName at line %d", lineno);
+ target->t_initiator_name = $3;
+ }
+ ;
+
+initiator_address: INITIATOR_ADDRESS EQUALS STR
+ {
+ if (target->t_initiator_address != NULL)
+ xo_errx(1, "duplicated InitiatorAddress at line %d", lineno);
+ target->t_initiator_address = $3;
+ }
+ ;
+
+initiator_alias: INITIATOR_ALIAS EQUALS STR
+ {
+ if (target->t_initiator_alias != NULL)
+ xo_errx(1, "duplicated InitiatorAlias at line %d", lineno);
+ target->t_initiator_alias = $3;
+ }
+ ;
+
+user: USER EQUALS STR
+ {
+ if (target->t_user != NULL)
+ xo_errx(1, "duplicated chapIName at line %d", lineno);
+ target->t_user = $3;
+ }
+ ;
+
+secret: SECRET EQUALS STR
+ {
+ if (target->t_secret != NULL)
+ xo_errx(1, "duplicated chapSecret at line %d", lineno);
+ target->t_secret = $3;
+ }
+ ;
+
+mutual_user: MUTUAL_USER EQUALS STR
+ {
+ if (target->t_mutual_user != NULL)
+ xo_errx(1, "duplicated tgtChapName at line %d", lineno);
+ target->t_mutual_user = $3;
+ }
+ ;
+
+mutual_secret: MUTUAL_SECRET EQUALS STR
+ {
+ if (target->t_mutual_secret != NULL)
+ xo_errx(1, "duplicated tgtChapSecret at line %d", lineno);
+ target->t_mutual_secret = $3;
+ }
+ ;
+
+auth_method: AUTH_METHOD EQUALS STR
+ {
+ if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED)
+ xo_errx(1, "duplicated AuthMethod at line %d", lineno);
+ if (strcasecmp($3, "none") == 0)
+ target->t_auth_method = AUTH_METHOD_NONE;
+ else if (strcasecmp($3, "chap") == 0)
+ target->t_auth_method = AUTH_METHOD_CHAP;
+ else
+ xo_errx(1, "invalid AuthMethod at line %d; "
+ "must be either \"none\" or \"CHAP\"", lineno);
+ }
+ ;
+
+header_digest: HEADER_DIGEST EQUALS STR
+ {
+ if (target->t_header_digest != DIGEST_UNSPECIFIED)
+ xo_errx(1, "duplicated HeaderDigest at line %d", lineno);
+ if (strcasecmp($3, "none") == 0)
+ target->t_header_digest = DIGEST_NONE;
+ else if (strcasecmp($3, "CRC32C") == 0)
+ target->t_header_digest = DIGEST_CRC32C;
+ else
+ xo_errx(1, "invalid HeaderDigest at line %d; "
+ "must be either \"none\" or \"CRC32C\"", lineno);
+ }
+ ;
+
+data_digest: DATA_DIGEST EQUALS STR
+ {
+ if (target->t_data_digest != DIGEST_UNSPECIFIED)
+ xo_errx(1, "duplicated DataDigest at line %d", lineno);
+ if (strcasecmp($3, "none") == 0)
+ target->t_data_digest = DIGEST_NONE;
+ else if (strcasecmp($3, "CRC32C") == 0)
+ target->t_data_digest = DIGEST_CRC32C;
+ else
+ xo_errx(1, "invalid DataDigest at line %d; "
+ "must be either \"none\" or \"CRC32C\"", lineno);
+ }
+ ;
+
+session_type: SESSION_TYPE EQUALS STR
+ {
+ if (target->t_session_type != SESSION_TYPE_UNSPECIFIED)
+ xo_errx(1, "duplicated SessionType at line %d", lineno);
+ if (strcasecmp($3, "normal") == 0)
+ target->t_session_type = SESSION_TYPE_NORMAL;
+ else if (strcasecmp($3, "discovery") == 0)
+ target->t_session_type = SESSION_TYPE_DISCOVERY;
+ else
+ xo_errx(1, "invalid SessionType at line %d; "
+ "must be either \"normal\" or \"discovery\"", lineno);
+ }
+ ;
+
+enable: ENABLE EQUALS STR
+ {
+ if (target->t_enable != ENABLE_UNSPECIFIED)
+ xo_errx(1, "duplicated enable at line %d", lineno);
+ target->t_enable = parse_enable($3);
+ if (target->t_enable == ENABLE_UNSPECIFIED)
+ xo_errx(1, "invalid enable at line %d; "
+ "must be either \"on\" or \"off\"", lineno);
+ }
+ ;
+
+offload: OFFLOAD EQUALS STR
+ {
+ if (target->t_offload != NULL)
+ xo_errx(1, "duplicated offload at line %d", lineno);
+ target->t_offload = $3;
+ }
+ ;
+
+protocol: PROTOCOL EQUALS STR
+ {
+ if (target->t_protocol != PROTOCOL_UNSPECIFIED)
+ xo_errx(1, "duplicated protocol at line %d", lineno);
+ if (strcasecmp($3, "iscsi") == 0)
+ target->t_protocol = PROTOCOL_ISCSI;
+ else if (strcasecmp($3, "iser") == 0)
+ target->t_protocol = PROTOCOL_ISER;
+ else
+ xo_errx(1, "invalid protocol at line %d; "
+ "must be either \"iscsi\" or \"iser\"", lineno);
+ }
+ ;
+
+ignored: IGNORED EQUALS STR
+ {
+ xo_warnx("obsolete statement ignored at line %d", lineno);
+ }
+ ;
+
+dscp: DSCP EQUALS STR
+ {
+ uint64_t tmp;
+
+ if (target->t_dscp != -1)
+ xo_errx(1, "duplicated dscp at line %d", lineno);
+ if (strcmp($3, "0x") == 0) {
+ tmp = strtol($3 + 2, NULL, 16);
+ } else if (expand_number($3, &tmp) != 0) {
+ yyerror("invalid numeric value");
+ free($3);
+ return(1);
+ }
+ if (tmp >= 0x40) {
+ yyerror("invalid dscp value");
+ return(1);
+ }
+
+ target->t_dscp = tmp;
+ }
+ | DSCP EQUALS BE { target->t_dscp = IPTOS_DSCP_CS0 >> 2 ; }
+ | DSCP EQUALS EF { target->t_dscp = IPTOS_DSCP_EF >> 2 ; }
+ | DSCP EQUALS CS0 { target->t_dscp = IPTOS_DSCP_CS0 >> 2 ; }
+ | DSCP EQUALS CS1 { target->t_dscp = IPTOS_DSCP_CS1 >> 2 ; }
+ | DSCP EQUALS CS2 { target->t_dscp = IPTOS_DSCP_CS2 >> 2 ; }
+ | DSCP EQUALS CS3 { target->t_dscp = IPTOS_DSCP_CS3 >> 2 ; }
+ | DSCP EQUALS CS4 { target->t_dscp = IPTOS_DSCP_CS4 >> 2 ; }
+ | DSCP EQUALS CS5 { target->t_dscp = IPTOS_DSCP_CS5 >> 2 ; }
+ | DSCP EQUALS CS6 { target->t_dscp = IPTOS_DSCP_CS6 >> 2 ; }
+ | DSCP EQUALS CS7 { target->t_dscp = IPTOS_DSCP_CS7 >> 2 ; }
+ | DSCP EQUALS AF11 { target->t_dscp = IPTOS_DSCP_AF11 >> 2 ; }
+ | DSCP EQUALS AF12 { target->t_dscp = IPTOS_DSCP_AF12 >> 2 ; }
+ | DSCP EQUALS AF13 { target->t_dscp = IPTOS_DSCP_AF13 >> 2 ; }
+ | DSCP EQUALS AF21 { target->t_dscp = IPTOS_DSCP_AF21 >> 2 ; }
+ | DSCP EQUALS AF22 { target->t_dscp = IPTOS_DSCP_AF22 >> 2 ; }
+ | DSCP EQUALS AF23 { target->t_dscp = IPTOS_DSCP_AF23 >> 2 ; }
+ | DSCP EQUALS AF31 { target->t_dscp = IPTOS_DSCP_AF31 >> 2 ; }
+ | DSCP EQUALS AF32 { target->t_dscp = IPTOS_DSCP_AF32 >> 2 ; }
+ | DSCP EQUALS AF33 { target->t_dscp = IPTOS_DSCP_AF33 >> 2 ; }
+ | DSCP EQUALS AF41 { target->t_dscp = IPTOS_DSCP_AF41 >> 2 ; }
+ | DSCP EQUALS AF42 { target->t_dscp = IPTOS_DSCP_AF42 >> 2 ; }
+ | DSCP EQUALS AF43 { target->t_dscp = IPTOS_DSCP_AF43 >> 2 ; }
+ ;
+
+pcp: PCP EQUALS STR
+ {
+ uint64_t tmp;
+
+ if (target->t_pcp != -1)
+ xo_errx(1, "duplicated pcp at line %d", lineno);
+
+ if (expand_number($3, &tmp) != 0) {
+ yyerror("invalid numeric value");
+ free($3);
+ return(1);
+ }
+ if (tmp > 7) {
+ yyerror("invalid pcp value");
+ return(1);
+ }
+
+ target->t_pcp = tmp;
+ }
+ ;
+
+ping_timeout: PINGTIMEOUT EQUALS STR
+ {
+ uint64_t tmp;
+
+ if (target->t_pingtimeout != -1)
+ xo_errx(1, "duplicated PingTimeout at line %d", lineno);
+
+ if (expand_number($3, &tmp) != 0) {
+ yyerror("invalid numeric value");
+ free($3);
+ return(1);
+ }
+ target->t_pingtimeout = tmp;
+ }
+ ;
+
+login_timeout: LOGINTIMEOUT EQUALS STR
+ {
+ uint64_t tmp;
+
+ if (target->t_logintimeout != -1)
+ xo_errx(1, "duplicated LoginTimeout at line %d", lineno);
+
+ if (expand_number($3, &tmp) != 0) {
+ yyerror("invalid numeric value");
+ free($3);
+ return(1);
+ }
+ target->t_logintimeout = tmp;
+ }
+ ;
+
+%%
+
+void
+yyerror(const char *str)
+{
+
+ xo_errx(1, "error in configuration file at line %d near '%s': %s",
+ lineno, yytext, str);
+}
+
+static void
+check_perms(const char *path)
+{
+ struct stat sb;
+ int error;
+
+ error = stat(path, &sb);
+ if (error != 0) {
+ xo_warn("stat");
+ return;
+ }
+ if (sb.st_mode & S_IWOTH) {
+ xo_warnx("%s is world-writable", path);
+ } else if (sb.st_mode & S_IROTH) {
+ xo_warnx("%s is world-readable", path);
+ } else if (sb.st_mode & S_IXOTH) {
+ /*
+ * Ok, this one doesn't matter, but still do it,
+ * just for consistency.
+ */
+ xo_warnx("%s is world-executable", path);
+ }
+
+ /*
+ * XXX: Should we also check for owner != 0?
+ */
+}
+
+struct conf *
+conf_new_from_file(const char *path)
+{
+ int error;
+
+ conf = conf_new();
+ target = target_new(conf);
+
+ yyin = fopen(path, "r");
+ if (yyin == NULL)
+ xo_err(1, "unable to open configuration file %s", path);
+ check_perms(path);
+ lineno = 1;
+ yyrestart(yyin);
+ error = yyparse();
+ assert(error == 0);
+ fclose(yyin);
+
+ assert(target->t_nickname == NULL);
+ target_delete(target);
+
+ conf_verify(conf);
+
+ return (conf);
+}
diff --git a/usr.bin/iscsictl/periphs.c b/usr.bin/iscsictl/periphs.c
new file mode 100644
index 000000000000..1f623277af10
--- /dev/null
+++ b/usr.bin/iscsictl/periphs.c
@@ -0,0 +1,202 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1997-2007 Kenneth D. Merry
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Edward Tomasz Napierala
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 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 AUTHOR 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/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_da.h>
+#include <cam/scsi/scsi_pass.h>
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/smp_all.h>
+#include <cam/ata/ata_all.h>
+#include <camlib.h>
+#include <libxo/xo.h>
+
+#include "iscsictl.h"
+
+void
+print_periphs(int session_id)
+{
+ union ccb ccb;
+ int bufsize, fd;
+ unsigned int i;
+ int have_path_id, skip_bus, skip_device;
+ path_id_t path_id;
+
+ if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
+ xo_warn("couldn't open %s", XPT_DEVICE);
+ return;
+ }
+
+ /*
+ * First, iterate over the whole list to find the bus.
+ */
+
+ bzero(&ccb, sizeof(union ccb));
+
+ ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
+ ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
+ ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
+
+ ccb.ccb_h.func_code = XPT_DEV_MATCH;
+ bufsize = sizeof(struct dev_match_result) * 100;
+ ccb.cdm.match_buf_len = bufsize;
+ ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
+ if (ccb.cdm.matches == NULL) {
+ xo_warnx("can't malloc memory for matches");
+ close(fd);
+ return;
+ }
+ ccb.cdm.num_matches = 0;
+
+ /*
+ * We fetch all nodes, since we display most of them in the default
+ * case, and all in the verbose case.
+ */
+ ccb.cdm.num_patterns = 0;
+ ccb.cdm.pattern_buf_len = 0;
+
+ path_id = -1; /* Make GCC happy. */
+ have_path_id = 0;
+ skip_bus = 1;
+ skip_device = 1;
+
+ xo_open_container("devices");
+ xo_open_list("lun");
+ /*
+ * We do the ioctl multiple times if necessary, in case there are
+ * more than 100 nodes in the EDT.
+ */
+ do {
+ if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
+ xo_warn("error sending CAMIOCOMMAND ioctl");
+ break;
+ }
+
+ if ((ccb.ccb_h.status != CAM_REQ_CMP)
+ || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
+ && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
+ xo_warnx("got CAM error %#x, CDM error %d\n",
+ ccb.ccb_h.status, ccb.cdm.status);
+ break;
+ }
+
+ for (i = 0; i < ccb.cdm.num_matches; i++) {
+ switch (ccb.cdm.matches[i].type) {
+ case DEV_MATCH_BUS: {
+ struct bus_match_result *bus_result;
+
+ bus_result = &ccb.cdm.matches[i].result.bus_result;
+
+ skip_bus = 1;
+
+ if (strcmp(bus_result->dev_name, "iscsi") != 0) {
+ //printf("not iscsi\n");
+ continue;
+ }
+
+ if ((int)bus_result->unit_number != session_id) {
+ //printf("wrong unit, %d != %d\n", bus_result->unit_number, session_id);
+ continue;
+ }
+ skip_bus = 0;
+ }
+ case DEV_MATCH_DEVICE: {
+ skip_device = 1;
+
+ if (skip_bus != 0)
+ continue;
+
+ skip_device = 0;
+ break;
+ }
+ case DEV_MATCH_PERIPH: {
+ struct periph_match_result *periph_result;
+
+ periph_result =
+ &ccb.cdm.matches[i].result.periph_result;
+
+ if (skip_device != 0)
+ continue;
+
+ if (strcmp(periph_result->periph_name, "pass") == 0)
+ continue;
+
+ xo_open_instance("lun");
+ xo_emit("{e:lun/%d}", periph_result->target_lun);
+ xo_emit("{Vq:device/%s%d} ",
+ periph_result->periph_name,
+ periph_result->unit_number);
+ xo_close_instance("lun");
+
+ if (have_path_id == 0) {
+ path_id = periph_result->path_id;
+ have_path_id = 1;
+ }
+
+ break;
+ }
+ default:
+ fprintf(stdout, "unknown match type\n");
+ break;
+ }
+ }
+
+ } while ((ccb.ccb_h.status == CAM_REQ_CMP)
+ && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
+ xo_close_list("lun");
+
+ xo_emit("{e:scbus/%d}{e:bus/%d}{e:target/%d}",
+ have_path_id ? (int)path_id : -1, 0, have_path_id ? 0 : -1);
+ xo_close_container("devices");
+
+ close(fd);
+}
+
diff --git a/usr.bin/iscsictl/token.l b/usr.bin/iscsictl/token.l
new file mode 100644
index 000000000000..efe075958ca1
--- /dev/null
+++ b/usr.bin/iscsictl/token.l
@@ -0,0 +1,124 @@
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012 The FreeBSD Foundation
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 <stdint.h>
+#include <string.h>
+
+#include "iscsictl.h"
+#include "y.tab.h"
+
+int lineno;
+
+#define YY_DECL int yylex(void)
+extern int yylex(void);
+
+%}
+
+%option noinput
+%option nounput
+%option noyywrap
+
+%%
+HeaderDigest { return HEADER_DIGEST; }
+DataDigest { return DATA_DIGEST; }
+TargetName { return TARGET_NAME; }
+TargetAddress { return TARGET_ADDRESS; }
+InitiatorName { return INITIATOR_NAME; }
+InitiatorAddress { return INITIATOR_ADDRESS; }
+InitiatorAlias { return INITIATOR_ALIAS; }
+chapIName { return USER; }
+chapSecret { return SECRET; }
+tgtChapName { return MUTUAL_USER; }
+tgtChapSecret { return MUTUAL_SECRET; }
+AuthMethod { return AUTH_METHOD; }
+SessionType { return SESSION_TYPE; }
+enable { return ENABLE; }
+protocol { return PROTOCOL; }
+offload { return OFFLOAD; }
+port { return IGNORED; }
+dscp { return DSCP; }
+pcp { return PCP; }
+PingTimeout { return PINGTIMEOUT; }
+LoginTimeout { return LOGINTIMEOUT; }
+MaxConnections { return IGNORED; }
+TargetAlias { return IGNORED; }
+TargetPortalGroupTag { return IGNORED; }
+InitialR2T { return IGNORED; }
+ImmediateData { return IGNORED; }
+MaxRecvDataSegmentLength { return IGNORED; }
+MaxBurstLength { return IGNORED; }
+FirstBurstLength { return IGNORED; }
+DefaultTime2Wait { return IGNORED; }
+DefaultTime2Retain { return IGNORED; }
+MaxOutstandingR2T { return IGNORED; }
+DataPDUInOrder { return IGNORED; }
+DataSequenceInOrder { return IGNORED; }
+ErrorRecoveryLevel { return IGNORED; }
+tags { return IGNORED; }
+maxluns { return IGNORED; }
+sockbufsize { return IGNORED; }
+chapDigest { return IGNORED; }
+af11 { return AF11; }
+af12 { return AF12; }
+af13 { return AF13; }
+af21 { return AF21; }
+af22 { return AF22; }
+af23 { return AF23; }
+af31 { return AF31; }
+af32 { return AF32; }
+af33 { return AF33; }
+af41 { return AF41; }
+af42 { return AF42; }
+af43 { return AF43; }
+be { return CS0; }
+ef { return EF; }
+cs0 { return CS0; }
+cs1 { return CS1; }
+cs2 { return CS2; }
+cs3 { return CS3; }
+cs4 { return CS4; }
+cs5 { return CS5; }
+cs6 { return CS6; }
+cs7 { return CS7; }
+\"[^"]+\" { yylval.str = strndup(yytext + 1,
+ strlen(yytext) - 2); return STR; }
+[a-zA-Z0-9\.\-_/\:\[\]]+ { yylval.str = strdup(yytext); return STR; }
+\{ { return OPENING_BRACKET; }
+\} { return CLOSING_BRACKET; }
+= { return EQUALS; }
+; { return SEMICOLON; }
+#.*$ /* ignore comments */;
+\r\n { lineno++; }
+\n { lineno++; }
+[ \t]+ /* ignore whitespace */;
+. { yylval.str = strdup(yytext); return STR; }
+%%
diff --git a/usr.bin/join/Makefile b/usr.bin/join/Makefile
new file mode 100644
index 000000000000..4ec29f14e3c9
--- /dev/null
+++ b/usr.bin/join/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= join
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/join/Makefile.depend b/usr.bin/join/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/join/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/join/join.1 b/usr.bin/join/join.1
new file mode 100644
index 000000000000..27477d87a900
--- /dev/null
+++ b/usr.bin/join/join.1
@@ -0,0 +1,292 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 20, 2020
+.Dt JOIN 1
+.Os
+.Sh NAME
+.Nm join
+.Nd relational database operator
+.Sh SYNOPSIS
+.Nm
+.Oo
+.Fl a Ar file_number | Fl v Ar file_number
+.Oc
+.Op Fl e Ar string
+.Op Fl o Ar list
+.Op Fl t Ar char
+.Op Fl 1 Ar field
+.Op Fl 2 Ar field
+.Ar file1
+.Ar file2
+.Sh DESCRIPTION
+The
+.Nm
+utility performs an
+.Dq equality join
+on the specified files
+and writes the result to the standard output.
+The
+.Dq join field
+is the field in each file by which the files are compared.
+The first field in each line is used by default.
+There is one line in the output for each pair of lines in
+.Ar file1
+and
+.Ar file2
+which have identical join fields.
+Each output line consists of the join field, the remaining fields from
+.Ar file1
+and then the remaining fields from
+.Ar file2 .
+.Pp
+The default field separators are tab and space characters.
+In this case, multiple tabs and spaces count as a single field separator,
+and leading tabs and spaces are ignored.
+The default output field separator is a single space character.
+.Pp
+Many of the options use file and field numbers.
+Both file numbers and field numbers are 1 based, i.e., the first file on
+the command line is file number 1 and the first field is field number 1.
+The following options are available:
+.Bl -tag -width indent
+.It Fl a Ar file_number
+In addition to the default output, produce a line for each unpairable
+line in file
+.Ar file_number .
+.It Fl e Ar string
+Replace empty output fields with
+.Ar string .
+.It Fl o Ar list
+The
+.Fl o
+option specifies the fields that will be output from each file for
+each line with matching join fields.
+Each element of
+.Ar list
+has either the form
+.Ar file_number . Ns Ar field ,
+where
+.Ar file_number
+is a file number and
+.Ar field
+is a field number, or the form
+.Ql 0
+.Pq zero ,
+representing the join field.
+The elements of list must be either comma
+.Pq Ql \&,
+or whitespace separated.
+(The latter requires quoting to protect it from the shell, or, a simpler
+approach is to use multiple
+.Fl o
+options.)
+.It Fl t Ar char
+Use character
+.Ar char
+as a field delimiter for both input and output.
+Every occurrence of
+.Ar char
+in a line is significant.
+.It Fl v Ar file_number
+Do not display the default output, but display a line for each unpairable
+line in file
+.Ar file_number .
+The options
+.Fl v Cm 1
+and
+.Fl v Cm 2
+may be specified at the same time.
+.It Fl 1 Ar field
+Join on the
+.Ar field Ns 'th
+field of
+.Ar file1 .
+.It Fl 2 Ar field
+Join on the
+.Ar field Ns 'th
+field of
+.Ar file2 .
+.El
+.Pp
+When the default field delimiter characters are used, the files to be joined
+should be ordered in the collating sequence of
+.Xr sort 1 ,
+using the
+.Fl b
+option, on the fields on which they are to be joined, otherwise
+.Nm
+may not report all field matches.
+When the field delimiter characters are specified by the
+.Fl t
+option, the collating sequence should be the same as
+.Xr sort 1
+without the
+.Fl b
+option.
+.Pp
+If one of the arguments
+.Ar file1
+or
+.Ar file2
+is
+.Sq Fl ,
+the standard input is used.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Assuming a file named
+.Pa nobel_laureates.txt
+with information about some of the first Nobel Peace Prize laureates:
+.Bd -literal -offset indent
+1901,Jean Henri Dunant,M
+1901,Frederic Passy,M
+1902,Elie Ducommun,M
+1905,Baroness Bertha Sophie Felicita Von Suttner,F
+1910,Permanent International Peace Bureau,
+.Ed
+.Pp
+and a second file
+.Pa nobel_nationalities.txt
+with their nationalities:
+.Bd -literal -offset indent
+Jean Henri Dunant,Switzerland
+Frederic Passy,France
+Elie Ducommun,Switzerland
+Baroness Bertha Sophie Felicita Von Suttner
+.Ed
+.Pp
+Join the two files using the second column from first file and the default first
+column from second file specifying a custom field delimiter:
+.Bd -literal -offset indent
+$ join -t, -1 2 nobel_laureates.txt nobel_nationalities.txt
+Jean Henri Dunant,1901,M,Switzerland
+Frederic Passy,1901,M,France
+Elie Ducommun,1902,M,Switzerland
+Baroness Bertha Sophie Felicita Von Suttner,1905,F
+.Ed
+.Pp
+Show only the year and the nationality of the laureate using
+.Ql <<NULL>>
+to replace empty fields:
+.Bd -literal -offset indent
+$ join -e "<<NULL>>" -t, -1 2 -o "1.1 2.2" nobel_laureates.txt nobel_nationalities.txt
+1901,Switzerland
+1901,France
+1902,Switzerland
+1905,<<NULL>>
+.Ed
+.Pp
+Show only lines from first file which do not have a match in second file:
+.Bd -literal -offset indent
+$ join -v1 -t, -1 2 nobel_laureates.txt nobel_nationalities.txt
+Permanent International Peace Bureau,1910,
+.Ed
+.Pp
+Assuming a file named
+.Pa capitals.txt
+with the following content:
+.Bd -literal -offset indent
+Belgium,Brussels
+France,Paris
+Italy,Rome
+Switzerland
+.Ed
+.Pp
+Show the name and capital of the country where the laureate was born.
+This example uses
+.Pa nobel_nationalities.txt
+as a bridge but does not show any information from that file.
+Also see the note about
+.Xr sort 1
+above to understand why we need to sort the intermediate result.
+.Bd -literal -offset indent
+$ join -t, -1 2 -o 1.2 2.2 nobel_laureates.txt nobel_nationalities.txt | \e
+ sort -k2 -t, | join -t, -e "<<NULL>>" -1 2 -o 1.1 2.2 - capitals.txt
+Elie Ducommun,<<NULL>>
+Jean Henri Dunant,<<NULL>>
+.Ed
+.Sh COMPATIBILITY
+For compatibility with historic versions of
+.Nm ,
+the following options are available:
+.Bl -tag -width indent
+.It Fl a
+In addition to the default output, produce a line for each unpairable line
+in both
+.Ar file1
+and
+.Ar file2 .
+.It Fl j1 Ar field
+Join on the
+.Ar field Ns 'th
+field of
+.Ar file1 .
+.It Fl j2 Ar field
+Join on the
+.Ar field Ns 'th
+field of
+.Ar file2 .
+.It Fl j Ar field
+Join on the
+.Ar field Ns 'th
+field of both
+.Ar file1
+and
+.Ar file2 .
+.It Fl o Ar list ...
+Historical implementations of
+.Nm
+permitted multiple arguments to the
+.Fl o
+option.
+These arguments were of the form
+.Ar file_number . Ns Ar field_number
+as described
+for the current
+.Fl o
+option.
+This has obvious difficulties in the presence of files named
+.Pa 1.2 .
+.El
+.Pp
+These options are available only so historic shell scripts do not require
+modification and should not be used.
+.Sh SEE ALSO
+.Xr awk 1 ,
+.Xr comm 1 ,
+.Xr paste 1 ,
+.Xr sort 1 ,
+.Xr uniq 1
+.Sh STANDARDS
+The
+.Nm
+command conforms to
+.St -p1003.1-2001 .
diff --git a/usr.bin/join/join.c b/usr.bin/join/join.c
new file mode 100644
index 000000000000..79469cdc52db
--- /dev/null
+++ b/usr.bin/join/join.c
@@ -0,0 +1,661 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Steve Hayman of the Computer Science Department, Indiana University,
+ * Michiro Hikida and David Goodenough.
+ *
+ * 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>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+/*
+ * There's a structure per input file which encapsulates the state of the
+ * file. We repeatedly read lines from each file until we've read in all
+ * the consecutive lines from the file with a common join field. Then we
+ * compare the set of lines with an equivalent set from the other file.
+ */
+typedef struct {
+ char *line; /* line */
+ u_long linealloc; /* line allocated count */
+ char **fields; /* line field(s) */
+ u_long fieldcnt; /* line field(s) count */
+ u_long fieldalloc; /* line field(s) allocated count */
+} LINE;
+
+typedef struct {
+ FILE *fp; /* file descriptor */
+ u_long joinf; /* join field (-1, -2, -j) */
+ int unpair; /* output unpairable lines (-a) */
+ u_long number; /* 1 for file 1, 2 for file 2 */
+
+ LINE *set; /* set of lines with same field */
+ int pushbool; /* if pushback is set */
+ u_long pushback; /* line on the stack */
+ u_long setcnt; /* set count */
+ u_long setalloc; /* set allocated count */
+} INPUT;
+static INPUT input1 = { NULL, 0, 0, 1, NULL, 0, 0, 0, 0 },
+ input2 = { NULL, 0, 0, 2, NULL, 0, 0, 0, 0 };
+
+typedef struct {
+ u_long filenum; /* file number */
+ u_long fieldno; /* field number */
+} OLIST;
+static OLIST *olist; /* output field list */
+static u_long olistcnt; /* output field list count */
+static u_long olistalloc; /* output field allocated count */
+
+static int joinout = 1; /* show lines with matched join fields (-v) */
+static int needsep; /* need separator character */
+static int spans = 1; /* span multiple delimiters (-t) */
+static char *empty; /* empty field replacement string (-e) */
+static wchar_t default_tabchar[] = L" \t";
+static wchar_t *tabchar = default_tabchar; /* delimiter characters (-t) */
+
+static int cmp(LINE *, u_long, LINE *, u_long);
+static void fieldarg(char *);
+static void joinlines(INPUT *, INPUT *);
+static int mbscoll(const char *, const char *);
+static char *mbssep(char **, const wchar_t *);
+static void obsolete(char **);
+static void outfield(LINE *, u_long, int);
+static void outoneline(INPUT *, LINE *);
+static void outtwoline(INPUT *, LINE *, INPUT *, LINE *);
+static void slurp(INPUT *);
+static wchar_t *towcs(const char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ INPUT *F1, *F2;
+ int aflag, ch, cval, vflag;
+ char *end;
+
+ setlocale(LC_ALL, "");
+
+ F1 = &input1;
+ F2 = &input2;
+
+ aflag = vflag = 0;
+ obsolete(argv);
+ while ((ch = getopt(argc, argv, "\01a:e:j:1:2:o:t:v:")) != -1) {
+ switch (ch) {
+ case '\01': /* See comment in obsolete(). */
+ aflag = 1;
+ F1->unpair = F2->unpair = 1;
+ break;
+ case '1':
+ if ((F1->joinf = strtol(optarg, &end, 10)) < 1)
+ errx(1, "-1 option field number less than 1");
+ if (*end)
+ errx(1, "illegal field number -- %s", optarg);
+ --F1->joinf;
+ break;
+ case '2':
+ if ((F2->joinf = strtol(optarg, &end, 10)) < 1)
+ errx(1, "-2 option field number less than 1");
+ if (*end)
+ errx(1, "illegal field number -- %s", optarg);
+ --F2->joinf;
+ break;
+ case 'a':
+ aflag = 1;
+ switch(strtol(optarg, &end, 10)) {
+ case 1:
+ F1->unpair = 1;
+ break;
+ case 2:
+ F2->unpair = 1;
+ break;
+ default:
+ errx(1, "-a option file number not 1 or 2");
+ break;
+ }
+ if (*end)
+ errx(1, "illegal file number -- %s", optarg);
+ break;
+ case 'e':
+ empty = optarg;
+ break;
+ case 'j':
+ if ((F1->joinf = F2->joinf =
+ strtol(optarg, &end, 10)) < 1)
+ errx(1, "-j option field number less than 1");
+ if (*end)
+ errx(1, "illegal field number -- %s", optarg);
+ --F1->joinf;
+ --F2->joinf;
+ break;
+ case 'o':
+ fieldarg(optarg);
+ break;
+ case 't':
+ spans = 0;
+ if (mbrtowc(&tabchar[0], optarg, MB_LEN_MAX, NULL) !=
+ strlen(optarg))
+ errx(1, "illegal tab character specification");
+ tabchar[1] = L'\0';
+ break;
+ case 'v':
+ vflag = 1;
+ joinout = 0;
+ switch (strtol(optarg, &end, 10)) {
+ case 1:
+ F1->unpair = 1;
+ break;
+ case 2:
+ F2->unpair = 1;
+ break;
+ default:
+ errx(1, "-v option file number not 1 or 2");
+ break;
+ }
+ if (*end)
+ errx(1, "illegal file number -- %s", optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (aflag && vflag)
+ errx(1, "the -a and -v options are mutually exclusive");
+
+ if (argc != 2)
+ usage();
+
+ /* Open the files; "-" means stdin. */
+ if (!strcmp(*argv, "-"))
+ F1->fp = stdin;
+ else if ((F1->fp = fopen(*argv, "r")) == NULL)
+ err(1, "%s", *argv);
+ ++argv;
+ if (!strcmp(*argv, "-"))
+ F2->fp = stdin;
+ else if ((F2->fp = fopen(*argv, "r")) == NULL)
+ err(1, "%s", *argv);
+ if (F1->fp == stdin && F2->fp == stdin)
+ errx(1, "only one input file may be stdin");
+
+ slurp(F1);
+ slurp(F2);
+ while (F1->setcnt && F2->setcnt) {
+ cval = cmp(F1->set, F1->joinf, F2->set, F2->joinf);
+ if (cval == 0) {
+ /* Oh joy, oh rapture, oh beauty divine! */
+ if (joinout)
+ joinlines(F1, F2);
+ slurp(F1);
+ slurp(F2);
+ } else if (cval < 0) {
+ /* File 1 takes the lead... */
+ if (F1->unpair)
+ joinlines(F1, NULL);
+ slurp(F1);
+ } else {
+ /* File 2 takes the lead... */
+ if (F2->unpair)
+ joinlines(F2, NULL);
+ slurp(F2);
+ }
+ }
+
+ /*
+ * Now that one of the files is used up, optionally output any
+ * remaining lines from the other file.
+ */
+ if (F1->unpair)
+ while (F1->setcnt) {
+ joinlines(F1, NULL);
+ slurp(F1);
+ }
+ if (F2->unpair)
+ while (F2->setcnt) {
+ joinlines(F2, NULL);
+ slurp(F2);
+ }
+ exit(0);
+}
+
+static void
+slurp(INPUT *F)
+{
+ LINE *lp, *lastlp, tmp;
+ size_t blen = 0;
+ ssize_t len;
+ int cnt;
+ char *bp, *buf = NULL, *fieldp;
+
+ /*
+ * Read all of the lines from an input file that have the same
+ * join field.
+ */
+ F->setcnt = 0;
+ for (lastlp = NULL;; ++F->setcnt) {
+ /*
+ * If we're out of space to hold line structures, allocate
+ * more. Initialize the structure so that we know that this
+ * is new space.
+ */
+ if (F->setcnt == F->setalloc) {
+ cnt = F->setalloc;
+ F->setalloc += 50;
+ if ((F->set = realloc(F->set,
+ F->setalloc * sizeof(LINE))) == NULL)
+ err(1, NULL);
+ memset(F->set + cnt, 0, 50 * sizeof(LINE));
+
+ /* re-set lastlp in case it moved */
+ if (lastlp != NULL)
+ lastlp = &F->set[F->setcnt - 1];
+ }
+
+ /*
+ * Get any pushed back line, else get the next line. Allocate
+ * space as necessary. If taking the line from the stack swap
+ * the two structures so that we don't lose space allocated to
+ * either structure. This could be avoided by doing another
+ * level of indirection, but it's probably okay as is.
+ */
+ lp = &F->set[F->setcnt];
+ if (F->setcnt)
+ lastlp = &F->set[F->setcnt - 1];
+ if (F->pushbool) {
+ tmp = F->set[F->setcnt];
+ F->set[F->setcnt] = F->set[F->pushback];
+ F->set[F->pushback] = tmp;
+ F->pushbool = 0;
+ continue;
+ }
+ if ((len = getline(&buf, &blen, F->fp)) < 0) {
+ free(buf);
+ return;
+ }
+ if (lp->linealloc <= (size_t)(len + 1)) {
+ lp->linealloc += MAX(100, len + 1 - lp->linealloc);
+ if ((lp->line =
+ realloc(lp->line, lp->linealloc)) == NULL)
+ err(1, NULL);
+ }
+ memmove(lp->line, buf, len);
+
+ /* Replace trailing newline, if it exists. */
+ if (buf[len - 1] == '\n')
+ lp->line[len - 1] = '\0';
+ bp = lp->line;
+
+ /* Split the line into fields, allocate space as necessary. */
+ lp->fieldcnt = 0;
+ while ((fieldp = mbssep(&bp, tabchar)) != NULL) {
+ if (spans && *fieldp == '\0')
+ continue;
+ if (lp->fieldcnt == lp->fieldalloc) {
+ lp->fieldalloc += 50;
+ if ((lp->fields = realloc(lp->fields,
+ lp->fieldalloc * sizeof(char *))) == NULL)
+ err(1, NULL);
+ }
+ lp->fields[lp->fieldcnt++] = fieldp;
+ }
+
+ /* See if the join field value has changed. */
+ if (lastlp != NULL && cmp(lp, F->joinf, lastlp, F->joinf)) {
+ F->pushbool = 1;
+ F->pushback = F->setcnt;
+ break;
+ }
+ }
+ free(buf);
+}
+
+static char *
+mbssep(char **stringp, const wchar_t *delim)
+{
+ char *s, *tok;
+ const wchar_t *spanp;
+ wchar_t c, sc;
+ size_t n;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ n = mbrtowc(&c, s, MB_LEN_MAX, NULL);
+ if (n == (size_t)-1 || n == (size_t)-2)
+ errc(1, EILSEQ, NULL); /* XXX */
+ s += n;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-n] = '\0';
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+}
+
+static int
+cmp(LINE *lp1, u_long fieldno1, LINE *lp2, u_long fieldno2)
+{
+ if (lp1->fieldcnt <= fieldno1)
+ return (lp2->fieldcnt <= fieldno2 ? 0 : -1);
+ if (lp2->fieldcnt <= fieldno2)
+ return (1);
+ return (mbscoll(lp1->fields[fieldno1], lp2->fields[fieldno2]));
+}
+
+static int
+mbscoll(const char *s1, const char *s2)
+{
+ wchar_t *w1, *w2;
+ int ret;
+
+ if (MB_CUR_MAX == 1)
+ return (strcoll(s1, s2));
+ if ((w1 = towcs(s1)) == NULL || (w2 = towcs(s2)) == NULL)
+ err(1, NULL); /* XXX */
+ ret = wcscoll(w1, w2);
+ free(w1);
+ free(w2);
+ return (ret);
+}
+
+static wchar_t *
+towcs(const char *s)
+{
+ wchar_t *wcs;
+ size_t n;
+
+ if ((n = mbsrtowcs(NULL, &s, 0, NULL)) == (size_t)-1)
+ return (NULL);
+ if ((wcs = malloc((n + 1) * sizeof(*wcs))) == NULL)
+ return (NULL);
+ mbsrtowcs(wcs, &s, n + 1, NULL);
+ return (wcs);
+}
+
+static void
+joinlines(INPUT *F1, INPUT *F2)
+{
+ u_long cnt1, cnt2;
+
+ /*
+ * Output the results of a join comparison. The output may be from
+ * either file 1 or file 2 (in which case the first argument is the
+ * file from which to output) or from both.
+ */
+ if (F2 == NULL) {
+ for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1)
+ outoneline(F1, &F1->set[cnt1]);
+ return;
+ }
+ for (cnt1 = 0; cnt1 < F1->setcnt; ++cnt1)
+ for (cnt2 = 0; cnt2 < F2->setcnt; ++cnt2)
+ outtwoline(F1, &F1->set[cnt1], F2, &F2->set[cnt2]);
+}
+
+static void
+outoneline(INPUT *F, LINE *lp)
+{
+ u_long cnt;
+
+ /*
+ * Output a single line from one of the files, according to the
+ * join rules. This happens when we are writing unmatched single
+ * lines. Output empty fields in the right places.
+ */
+ if (olist)
+ for (cnt = 0; cnt < olistcnt; ++cnt) {
+ if (olist[cnt].filenum == (unsigned)F->number)
+ outfield(lp, olist[cnt].fieldno, 0);
+ else if (olist[cnt].filenum == 0)
+ outfield(lp, F->joinf, 0);
+ else
+ outfield(lp, 0, 1);
+ }
+ else {
+ /*
+ * Output the join field, then the remaining fields.
+ */
+ outfield(lp, F->joinf, 0);
+ for (cnt = 0; cnt < lp->fieldcnt; ++cnt)
+ if (F->joinf != cnt)
+ outfield(lp, cnt, 0);
+ }
+ (void)printf("\n");
+ if (ferror(stdout))
+ err(1, "stdout");
+ needsep = 0;
+}
+
+static void
+outtwoline(INPUT *F1, LINE *lp1, INPUT *F2, LINE *lp2)
+{
+ u_long cnt;
+
+ /* Output a pair of lines according to the join list (if any). */
+ if (olist)
+ for (cnt = 0; cnt < olistcnt; ++cnt)
+ if (olist[cnt].filenum == 0) {
+ if (lp1->fieldcnt >= F1->joinf)
+ outfield(lp1, F1->joinf, 0);
+ else
+ outfield(lp2, F2->joinf, 0);
+ } else if (olist[cnt].filenum == 1)
+ outfield(lp1, olist[cnt].fieldno, 0);
+ else /* if (olist[cnt].filenum == 2) */
+ outfield(lp2, olist[cnt].fieldno, 0);
+ else {
+ /*
+ * Output the join field, then the remaining fields from F1
+ * and F2.
+ */
+ outfield(lp1, F1->joinf, 0);
+ for (cnt = 0; cnt < lp1->fieldcnt; ++cnt)
+ if (F1->joinf != cnt)
+ outfield(lp1, cnt, 0);
+ for (cnt = 0; cnt < lp2->fieldcnt; ++cnt)
+ if (F2->joinf != cnt)
+ outfield(lp2, cnt, 0);
+ }
+ (void)printf("\n");
+ if (ferror(stdout))
+ err(1, "stdout");
+ needsep = 0;
+}
+
+static void
+outfield(LINE *lp, u_long fieldno, int out_empty)
+{
+ if (needsep++)
+ (void)printf("%lc", (wint_t)*tabchar);
+ if (!ferror(stdout)) {
+ if (lp->fieldcnt <= fieldno || out_empty) {
+ if (empty != NULL)
+ (void)printf("%s", empty);
+ } else {
+ if (*lp->fields[fieldno] == '\0')
+ return;
+ (void)printf("%s", lp->fields[fieldno]);
+ }
+ }
+ if (ferror(stdout))
+ err(1, "stdout");
+}
+
+/*
+ * Convert an output list argument "2.1, 1.3, 2.4" into an array of output
+ * fields.
+ */
+static void
+fieldarg(char *option)
+{
+ u_long fieldno, filenum;
+ char *end, *token;
+
+ while ((token = strsep(&option, ", \t")) != NULL) {
+ if (*token == '\0')
+ continue;
+ if (token[0] == '0')
+ filenum = fieldno = 0;
+ else if ((token[0] == '1' || token[0] == '2') &&
+ token[1] == '.') {
+ filenum = token[0] - '0';
+ fieldno = strtol(token + 2, &end, 10);
+ if (*end)
+ errx(1, "malformed -o option field");
+ if (fieldno == 0)
+ errx(1, "field numbers are 1 based");
+ --fieldno;
+ } else
+ errx(1, "malformed -o option field");
+ if (olistcnt == olistalloc) {
+ olistalloc += 50;
+ if ((olist = realloc(olist,
+ olistalloc * sizeof(OLIST))) == NULL)
+ err(1, NULL);
+ }
+ olist[olistcnt].filenum = filenum;
+ olist[olistcnt].fieldno = fieldno;
+ ++olistcnt;
+ }
+}
+
+static void
+obsolete(char **argv)
+{
+ size_t len;
+ char **p, *ap, *t;
+
+ while ((ap = *++argv) != NULL) {
+ /* Return if "--". */
+ if (ap[0] == '-' && ap[1] == '-')
+ return;
+ /* skip if not an option */
+ if (ap[0] != '-')
+ continue;
+ switch (ap[1]) {
+ case 'a':
+ /*
+ * The original join allowed "-a", which meant the
+ * same as -a1 plus -a2. POSIX 1003.2, Draft 11.2
+ * only specifies this as "-a 1" and "a -2", so we
+ * have to use another option flag, one that is
+ * unlikely to ever be used or accidentally entered
+ * on the command line. (Well, we could reallocate
+ * the argv array, but that hardly seems worthwhile.)
+ */
+ if (ap[2] == '\0' && (argv[1] == NULL ||
+ (strcmp(argv[1], "1") != 0 &&
+ strcmp(argv[1], "2") != 0))) {
+ ap[1] = '\01';
+ warnx("-a option used without an argument; "
+ "reverting to historical behavior");
+ }
+ break;
+ case 'j':
+ /*
+ * The original join allowed "-j[12] arg" and "-j arg".
+ * Convert the former to "-[12] arg". Don't convert
+ * the latter since getopt(3) can handle it.
+ */
+ switch(ap[2]) {
+ case '1':
+ if (ap[3] != '\0')
+ goto jbad;
+ ap[1] = '1';
+ ap[2] = '\0';
+ break;
+ case '2':
+ if (ap[3] != '\0')
+ goto jbad;
+ ap[1] = '2';
+ ap[2] = '\0';
+ break;
+ case '\0':
+ break;
+ default:
+jbad: errx(1, "illegal option -- %s", ap);
+ usage();
+ }
+ break;
+ case 'o':
+ /*
+ * The original join allowed "-o arg arg".
+ * Convert to "-o arg -o arg".
+ */
+ if (ap[2] != '\0')
+ break;
+ for (p = argv + 2; *p; ++p) {
+ if (p[0][0] == '0' || ((p[0][0] != '1' &&
+ p[0][0] != '2') || p[0][1] != '.'))
+ break;
+ len = strlen(*p);
+ if (len - 2 != strspn(*p + 2, "0123456789"))
+ break;
+ if ((t = malloc(len + 3)) == NULL)
+ err(1, NULL);
+ t[0] = '-';
+ t[1] = 'o';
+ memmove(t + 2, *p, len + 1);
+ *p = t;
+ }
+ argv = p - 1;
+ break;
+ }
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s %s\n%s\n",
+ "usage: join [-a fileno | -v fileno ] [-e string] [-1 field]",
+ "[-2 field]",
+ " [-o list] [-t char] file1 file2");
+ exit(1);
+}
diff --git a/usr.bin/join/tests/Makefile b/usr.bin/join/tests/Makefile
new file mode 100644
index 000000000000..51e46dc2f189
--- /dev/null
+++ b/usr.bin/join/tests/Makefile
@@ -0,0 +1,10 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.1.in
+${PACKAGE}FILES+= regress.2.in
+${PACKAGE}FILES+= regress.out
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/join/tests/Makefile.depend b/usr.bin/join/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/join/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/join/tests/legacy_test.sh b/usr.bin/join/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/join/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/join/tests/regress.1.in b/usr.bin/join/tests/regress.1.in
new file mode 100644
index 000000000000..975bbaf13b3b
--- /dev/null
+++ b/usr.bin/join/tests/regress.1.in
@@ -0,0 +1,4 @@
+!Name,Data1
+Foo,1
+Bar,2
+Baz,3
diff --git a/usr.bin/join/tests/regress.2.in b/usr.bin/join/tests/regress.2.in
new file mode 100644
index 000000000000..0206b49fda55
--- /dev/null
+++ b/usr.bin/join/tests/regress.2.in
@@ -0,0 +1,4 @@
+!Name,Data2
+Foo,Bar
+Baz,2
+Foobar,1
diff --git a/usr.bin/join/tests/regress.out b/usr.bin/join/tests/regress.out
new file mode 100644
index 000000000000..fa75c88052a4
--- /dev/null
+++ b/usr.bin/join/tests/regress.out
@@ -0,0 +1,5 @@
+!Name,Data1,Data2
+Foo,1,Bar
+Bar,2,(unknown)
+Baz,3,2
+Foobar,(unknown),1
diff --git a/usr.bin/join/tests/regress.sh b/usr.bin/join/tests/regress.sh
new file mode 100644
index 000000000000..601de50c093d
--- /dev/null
+++ b/usr.bin/join/tests/regress.sh
@@ -0,0 +1,8 @@
+
+echo 1..1
+
+REGRESSION_START($1)
+
+REGRESSION_TEST_ONE(`join -t , -a1 -a2 -e "(unknown)" -o 0,1.2,2.2 ${SRCDIR}/regress.1.in ${SRCDIR}/regress.2.in')
+
+REGRESSION_END()
diff --git a/usr.bin/jot/Makefile b/usr.bin/jot/Makefile
new file mode 100644
index 000000000000..7c9c1a745a12
--- /dev/null
+++ b/usr.bin/jot/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= jot
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/jot/Makefile.depend b/usr.bin/jot/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/jot/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/jot/jot.1 b/usr.bin/jot/jot.1
new file mode 100644
index 000000000000..eb50498af2d0
--- /dev/null
+++ b/usr.bin/jot/jot.1
@@ -0,0 +1,327 @@
+.\" Copyright (c) 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.
+.\"
+.Dd September 21, 2019
+.Dt JOT 1
+.Os
+.Sh NAME
+.Nm jot
+.Nd print sequential or random data
+.Sh SYNOPSIS
+.Nm
+.Op Fl cnr
+.Op Fl b Ar word
+.Op Fl w Ar word
+.Op Fl s Ar string
+.Op Fl p Ar precision
+.Op Ar reps Op Ar begin Op Ar end Op Ar s
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to print out increasing, decreasing, random,
+or redundant data, usually numbers, one per line.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl r
+Generate random data instead of the default sequential data.
+.It Fl b Ar word
+Just print
+.Ar word
+repetitively.
+.It Fl w Ar word
+Print
+.Ar word
+with the generated data appended to it.
+Octal, hexadecimal, exponential,
+.Tn ASCII ,
+zero padded,
+and right-adjusted representations
+are possible by using the appropriate
+.Xr printf 3
+conversion specification inside
+.Ar word ,
+in which case the data are inserted rather than appended.
+.It Fl c
+This is an abbreviation for
+.Fl w Ar %c .
+.It Fl s Ar string
+Print data separated by
+.Ar string .
+Normally, newlines separate data.
+.It Fl n
+Do not print the final newline normally appended to the output.
+.It Fl p Ar precision
+Print only as many digits or characters of the data
+as indicated by the integer
+.Ar precision .
+In the absence of
+.Fl p ,
+the precision is the greater of the precisions of
+.Ar begin
+and
+.Ar end .
+The
+.Fl p
+option is overridden by whatever appears in a
+.Xr printf 3
+conversion following
+.Fl w .
+.El
+.Pp
+The last four arguments indicate, respectively,
+the number of data, the lower bound, the upper bound,
+and the step size or, for random data, the seed.
+While at least one of them must appear,
+any of the other three may be omitted, and
+will be considered as such if given as
+.Fl ""
+or as an empty string.
+Any three of these arguments determines the fourth.
+If four are specified and the given and computed values of
+.Ar reps
+conflict, the lower value is used.
+If one or two are specified, defaults are assigned
+starting with
+.Ar s ,
+which assumes a default of 1 (or -1 if
+.Ar begin
+and
+.Ar end
+specify a descending range).
+Then the default values are assigned to the leftmost omitted arguments until
+three arguments are set.
+.Pp
+Defaults for the four arguments are, respectively,
+100, 1, 100, and 1, except that when random data are requested,
+the seed,
+.Ar s ,
+is picked randomly.
+The
+.Ar reps
+argument is expected to be an unsigned integer,
+and if given as zero is taken to be infinite.
+The
+.Ar begin
+and
+.Ar end
+arguments may be given as real numbers or as characters
+representing the corresponding value in
+.Tn ASCII .
+The last argument must be a real number.
+.Pp
+Random numbers are obtained through
+.Xr arc4random 3
+when no seed is specified,
+and through
+.Xr random 3
+when a seed is given.
+When
+.Nm
+is asked to generate random integers or characters with begin
+and end values in the range of the random number generator function
+and no format is specified with one of the
+.Fl w ,
+.Fl b ,
+or
+.Fl p
+options,
+.Nm
+will arrange for all the values in the range to appear in the output
+with an equal probability.
+In all other cases be careful to ensure that the output format's
+rounding or truncation will not skew the distribution of output
+values in an unintended way.
+.Pp
+The name
+.Nm
+derives in part from
+.Nm iota ,
+a function in APL.
+.Ss Rounding and truncation
+The
+.Nm
+utility uses double precision floating point arithmetic internally.
+Before printing a number, it is converted depending on the output
+format used.
+.Pp
+If no output format is specified or the output format is a
+floating point format
+.Po
+.Sq E ,
+.Sq G ,
+.Sq e ,
+.Sq f ,
+or
+.Sq g
+.Pc ,
+the value is rounded using the
+.Xr printf 3
+function, taking into account the requested precision.
+.Pp
+If the output format is an integer format
+.Po
+.Sq D ,
+.Sq O ,
+.Sq U ,
+.Sq X ,
+.Sq c ,
+.Sq d ,
+.Sq i ,
+.Sq o ,
+.Sq u ,
+or
+.Sq x
+.Pc ,
+the value is converted to an integer value by truncation.
+.Pp
+As an illustration, consider the following command:
+.Bd -literal -offset indent
+$ jot 6 1 10 0.5
+1
+2
+2
+2
+3
+4
+.Ed
+.Pp
+By requesting an explicit precision of 1, the values generated before rounding
+can be seen.
+The .5 values are rounded down if the integer part is even,
+up otherwise.
+.Bd -literal -offset indent
+$ jot -p 1 6 1 10 0.5
+1.0
+1.5
+2.0
+2.5
+3.0
+3.5
+.Ed
+.Pp
+By offsetting the values slightly, the values generated by the following
+command are always rounded down:
+.Bd -literal -offset indent
+$ jot -p 0 6 .9999999999 10 0.5
+1
+1
+2
+2
+3
+3
+.Ed
+.Pp
+Another way of achieving the same result is to force truncation by
+specifying an integer format:
+.Bd -literal -offset indent
+$ jot -w %d 6 1 10 0.5
+.Ed
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The command
+.Dl jot - 1 10
+.Pp
+prints the integers from 1 to 10,
+while the command
+.Dl jot 21 -1 1.00
+.Pp
+prints 21 evenly spaced numbers increasing from -1 to 1.
+The
+.Tn ASCII
+character set is generated with
+.Dl jot -c 128 0
+.Pp
+and the strings xaa through xaz with
+.Dl jot -w xa%c 26 a
+.Pp
+while 20 random 8-letter strings are produced with
+.Dl "jot -r -c 160 a z | rs -g 0 8"
+.Pp
+Infinitely many
+.Em yes Ns 's
+may be obtained through
+.Dl jot -b yes 0
+.Pp
+and thirty
+.Xr ed 1
+substitution commands applying to lines 2, 7, 12, etc.\& is
+the result of
+.Dl jot -w %ds/old/new/ 30 2 - 5
+.Pp
+The stuttering sequence 9, 9, 8, 8, 7, etc.\& can be
+produced by truncating the output precision and a suitable choice of step size,
+as in
+.Dl jot -w %d - 9.5 0 -.5
+.Pp
+and a file containing exactly 1024 bytes is created with
+.Dl jot -b x 512 > block
+.Pp
+Finally, to set tabs four spaces apart starting
+from column 10 and ending in column 132, use
+.Dl expand -`jot -s, - 10 132 4`
+.Pp
+and to print all lines 80 characters or longer,
+.Dl grep `jot -s \&"\&" -b \&. 80`
+.Sh DIAGNOSTICS
+The following diagnostic messages deserve special explanation:
+.Bl -diag
+.It "illegal or unsupported format '%s'"
+The requested conversion format specifier for
+.Xr printf 3
+was not of the form
+.Dl %[#][ ][{+,-}][0-9]*[.[0-9]*]?
+where
+.Dq ?\&
+must be one of
+.Dl [l]{d,i,o,u,x}
+or
+.Dl {c,e,f,g,D,E,G,O,U,X}
+.It "range error in conversion"
+A value to be printed fell outside the range of the data type
+associated with the requested output format.
+.It "too many conversions"
+More than one conversion format specifier has been supplied,
+but only one is allowed.
+.El
+.Sh SEE ALSO
+.Xr ed 1 ,
+.Xr expand 1 ,
+.Xr rs 1 ,
+.Xr seq 1 ,
+.Xr yes 1 ,
+.Xr arc4random 3 ,
+.Xr printf 3 ,
+.Xr random 3
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+.An John A. Kunze
diff --git a/usr.bin/jot/jot.c b/usr.bin/jot/jot.c
new file mode 100644
index 000000000000..b77e3943a45c
--- /dev/null
+++ b/usr.bin/jot/jot.c
@@ -0,0 +1,503 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+/*
+ * jot - print sequential or random data
+ *
+ * Author: John Kunze, Office of Comp. Affairs, UCB
+ */
+
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Defaults */
+#define REPS_DEF 100
+#define BEGIN_DEF 1
+#define ENDER_DEF 100
+#define STEP_DEF 1
+
+/* Flags of options that have been set */
+#define HAVE_STEP 1
+#define HAVE_ENDER 2
+#define HAVE_BEGIN 4
+#define HAVE_REPS 8
+
+#define is_default(s) (*(s) == 0 || strcmp((s), "-") == 0)
+
+static bool boring;
+static int prec = -1;
+static bool longdata;
+static bool intdata;
+static bool chardata;
+static bool nosign;
+static const char *sepstring = "\n";
+static char format[BUFSIZ];
+
+static void getformat(void);
+static int getprec(const char *);
+static int putdata(double, bool);
+static void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ cap_rights_t rights;
+ bool have_format = false;
+ bool infinity = false;
+ bool nofinalnl = false;
+ bool randomize = false;
+ bool use_random = false;
+ int ch;
+ int mask = 0;
+ int n = 0;
+ double begin = BEGIN_DEF;
+ double divisor;
+ double ender = ENDER_DEF;
+ double s = STEP_DEF;
+ double x, y;
+ long i;
+ long reps = REPS_DEF;
+
+ if (caph_limit_stdio() < 0)
+ err(1, "unable to limit rights for stdio");
+ cap_rights_init(&rights);
+ if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
+ err(1, "unable to limit rights for stdin");
+
+ /*
+ * Cache NLS data, for strerror, for err(3), before entering capability
+ * mode.
+ */
+ caph_cache_catpages();
+
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ while ((ch = getopt(argc, argv, "b:cnp:rs:w:")) != -1)
+ switch (ch) {
+ case 'b':
+ boring = true;
+ /* FALLTHROUGH */
+ case 'w':
+ if (strlcpy(format, optarg, sizeof(format)) >=
+ sizeof(format))
+ errx(1, "-%c word too long", ch);
+ have_format = true;
+ break;
+ case 'c':
+ chardata = true;
+ break;
+ case 'n':
+ nofinalnl = true;
+ break;
+ case 'p':
+ prec = atoi(optarg);
+ if (prec < 0)
+ errx(1, "bad precision value");
+ have_format = true;
+ break;
+ case 'r':
+ randomize = true;
+ break;
+ case 's':
+ sepstring = optarg;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) { /* examine args right to left, falling thru cases */
+ case 4:
+ if (!is_default(argv[3])) {
+ if (!sscanf(argv[3], "%lf", &s))
+ errx(1, "bad s value: %s", argv[3]);
+ mask |= HAVE_STEP;
+ if (randomize)
+ use_random = true;
+ }
+ /* FALLTHROUGH */
+ case 3:
+ if (!is_default(argv[2])) {
+ if (!sscanf(argv[2], "%lf", &ender))
+ ender = argv[2][strlen(argv[2])-1];
+ mask |= HAVE_ENDER;
+ if (prec < 0)
+ n = getprec(argv[2]);
+ }
+ /* FALLTHROUGH */
+ case 2:
+ if (!is_default(argv[1])) {
+ if (!sscanf(argv[1], "%lf", &begin))
+ begin = argv[1][strlen(argv[1])-1];
+ mask |= HAVE_BEGIN;
+ if (prec < 0)
+ prec = getprec(argv[1]);
+ if (n > prec) /* maximum precision */
+ prec = n;
+ }
+ /* FALLTHROUGH */
+ case 1:
+ if (!is_default(argv[0])) {
+ if (!sscanf(argv[0], "%ld", &reps))
+ errx(1, "bad reps value: %s", argv[0]);
+ mask |= HAVE_REPS;
+ }
+ break;
+ case 0:
+ usage();
+ default:
+ errx(1, "too many arguments. What do you mean by %s?",
+ argv[4]);
+ }
+ getformat();
+
+ if (prec == -1)
+ prec = 0;
+
+ while (mask) /* 4 bit mask has 1's where last 4 args were given */
+ switch (mask) { /* fill in the 0's by default or computation */
+ case HAVE_STEP:
+ case HAVE_ENDER:
+ case HAVE_ENDER | HAVE_STEP:
+ case HAVE_BEGIN:
+ case HAVE_BEGIN | HAVE_STEP:
+ reps = REPS_DEF;
+ mask |= HAVE_REPS;
+ break;
+ case HAVE_BEGIN | HAVE_ENDER:
+ s = ender > begin ? 1 : -1;
+ mask |= HAVE_STEP;
+ break;
+ case HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
+ if (randomize)
+ reps = REPS_DEF;
+ else if (s == 0.0)
+ reps = 0;
+ else
+ reps = (ender - begin + s) / s;
+ if (reps <= 0)
+ errx(1, "impossible stepsize");
+ mask = 0;
+ break;
+ case HAVE_REPS:
+ case HAVE_REPS | HAVE_STEP:
+ begin = BEGIN_DEF;
+ mask |= HAVE_BEGIN;
+ break;
+ case HAVE_REPS | HAVE_ENDER:
+ s = STEP_DEF;
+ mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP;
+ break;
+ case HAVE_REPS | HAVE_ENDER | HAVE_STEP:
+ if (randomize)
+ begin = BEGIN_DEF;
+ else if (reps == 0)
+ errx(1, "must specify begin if reps == 0");
+ begin = ender - reps * s + s;
+ mask = 0;
+ break;
+ case HAVE_REPS | HAVE_BEGIN:
+ s = STEP_DEF;
+ mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP;
+ break;
+ case HAVE_REPS | HAVE_BEGIN | HAVE_STEP:
+ if (randomize)
+ ender = ENDER_DEF;
+ else
+ ender = begin + reps * s - s;
+ mask = 0;
+ break;
+ case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER:
+ if (!randomize) {
+ if (reps == 0)
+ errx(1, "infinite sequences cannot "
+ "be bounded");
+ else if (reps == 1)
+ s = 0.0;
+ else
+ s = (ender - begin) / (reps - 1);
+ }
+ mask = 0;
+ break;
+ case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
+ /* if reps given and implied, */
+ if (!randomize && s != 0.0) {
+ long t = (ender - begin + s) / s;
+ if (t <= 0)
+ errx(1, "impossible stepsize");
+ if (t < reps) /* take lesser */
+ reps = t;
+ }
+ mask = 0;
+ break;
+ default:
+ errx(1, "bad mask");
+ }
+ if (reps == 0)
+ infinity = true;
+ if (randomize) {
+ if (use_random) {
+ srandom((unsigned long)s);
+ divisor = (double)INT32_MAX + 1;
+ } else
+ divisor = (double)UINT32_MAX + 1;
+
+ /*
+ * Attempt to DWIM when the user has specified an
+ * integer range within that of the random number
+ * generator: distribute the numbers equally in
+ * the range [begin .. ender]. Jot's default %.0f
+ * format would make the appearance of the first and
+ * last specified value half as likely as the rest.
+ */
+ if (!have_format && prec == 0 &&
+ begin >= 0 && begin < divisor &&
+ ender >= 0 && ender < divisor) {
+ if (begin <= ender)
+ ender += 1;
+ else
+ begin += 1;
+ nosign = true;
+ intdata = true;
+ (void)strlcpy(format,
+ chardata ? "%c" : "%u", sizeof(format));
+ }
+ x = ender - begin;
+ for (i = 1; i <= reps || infinity; i++) {
+ if (use_random)
+ y = random() / divisor;
+ else
+ y = arc4random() / divisor;
+ if (putdata(y * x + begin, !(reps - i)))
+ errx(1, "range error in conversion");
+ }
+ } else
+ for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
+ if (putdata(x, !(reps - i)))
+ errx(1, "range error in conversion");
+ if (!nofinalnl)
+ putchar('\n');
+ exit(0);
+}
+
+/*
+ * Send x to stdout using the specified format.
+ * Last is true if this is the set's last value.
+ * Return 0 if OK, or a positive number if the number passed was
+ * outside the range specified by the various flags.
+ */
+static int
+putdata(double x, bool last)
+{
+
+ if (boring)
+ printf("%s", format);
+ else if (longdata && nosign) {
+ if (x <= (double)ULONG_MAX && x >= (double)0)
+ printf(format, (unsigned long)x);
+ else
+ return (1);
+ } else if (longdata) {
+ if (x <= (double)LONG_MAX && x >= (double)LONG_MIN)
+ printf(format, (long)x);
+ else
+ return (1);
+ } else if (chardata || (intdata && !nosign)) {
+ if (x <= (double)INT_MAX && x >= (double)INT_MIN)
+ printf(format, (int)x);
+ else
+ return (1);
+ } else if (intdata) {
+ if (x <= (double)UINT_MAX && x >= (double)0)
+ printf(format, (unsigned int)x);
+ else
+ return (1);
+
+ } else
+ printf(format, x);
+ if (!last)
+ fputs(sepstring, stdout);
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
+ " [reps [begin [end [s]]]]");
+ exit(1);
+}
+
+/*
+ * Return the number of digits following the number's decimal point.
+ * Return 0 if no decimal point is found.
+ */
+static int
+getprec(const char *str)
+{
+ const char *p;
+ const char *q;
+
+ for (p = str; *p; p++)
+ if (*p == '.')
+ break;
+ if (!*p)
+ return (0);
+ for (q = ++p; *p; p++)
+ if (!isdigit((unsigned char)*p))
+ break;
+ return (p - q);
+}
+
+/*
+ * Set format, intdata, chardata, longdata, and nosign
+ * based on the command line arguments.
+ */
+static void
+getformat(void)
+{
+ char *p, *p2;
+ int dot, hash, space, sign, numbers = 0;
+ size_t sz;
+
+ if (boring) /* no need to bother */
+ return;
+ for (p = format; *p; p++) /* look for '%' */
+ if (*p == '%') {
+ if (p[1] == '%')
+ p++; /* leave %% alone */
+ else
+ break;
+ }
+ sz = sizeof(format) - strlen(format) - 1;
+ if (!*p && !chardata) {
+ if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
+ errx(1, "-w word too long");
+ } else if (!*p && chardata) {
+ if (strlcpy(p, "%c", sz) >= sz)
+ errx(1, "-w word too long");
+ intdata = true;
+ } else if (!*(p+1)) {
+ if (sz <= 0)
+ errx(1, "-w word too long");
+ strcat(format, "%"); /* cannot end in single '%' */
+ } else {
+ /*
+ * Allow conversion format specifiers of the form
+ * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of
+ * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u}
+ */
+ p2 = p++;
+ dot = hash = space = sign = numbers = 0;
+ while (!isalpha((unsigned char)*p)) {
+ if (isdigit((unsigned char)*p)) {
+ numbers++;
+ p++;
+ } else if ((*p == '#' && !(numbers|dot|sign|space|
+ hash++)) ||
+ (*p == ' ' && !(numbers|dot|space++)) ||
+ ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
+ || (*p == '.' && !(dot++)))
+ p++;
+ else
+ goto fmt_broken;
+ }
+ if (*p == 'l') {
+ longdata = true;
+ if (*++p == 'l') {
+ if (p[1] != '\0')
+ p++;
+ goto fmt_broken;
+ }
+ }
+ switch (*p) {
+ case 'o': case 'u': case 'x': case 'X':
+ intdata = nosign = true;
+ break;
+ case 'd': case 'i':
+ intdata = true;
+ break;
+ case 'D':
+ if (!longdata) {
+ intdata = true;
+ break;
+ }
+ case 'O': case 'U':
+ if (!longdata) {
+ intdata = nosign = true;
+ break;
+ }
+ case 'c':
+ if (!(intdata | longdata)) {
+ chardata = true;
+ break;
+ }
+ case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
+ case '$': case '*':
+ goto fmt_broken;
+ case 'f': case 'e': case 'g': case 'E': case 'G':
+ if (!longdata)
+ break;
+ /* FALLTHROUGH */
+ default:
+fmt_broken:
+ *++p = '\0';
+ errx(1, "illegal or unsupported format '%s'", p2);
+ /* NOTREACHED */
+ }
+ while (*++p)
+ if (*p == '%' && *(p+1) && *(p+1) != '%')
+ errx(1, "too many conversions");
+ else if (*p == '%' && *(p+1) == '%')
+ p++;
+ else if (*p == '%' && !*(p+1)) {
+ if (strlcat(format, "%", sizeof(format)) >=
+ sizeof(format))
+ errx(1, "-w word too long");
+ break;
+ }
+ }
+}
diff --git a/usr.bin/jot/tests/Makefile b/usr.bin/jot/tests/Makefile
new file mode 100644
index 000000000000..6b47c7251904
--- /dev/null
+++ b/usr.bin/jot/tests/Makefile
@@ -0,0 +1,68 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.ascii.out
+${PACKAGE}FILES+= regress.block.out
+${PACKAGE}FILES+= regress.dddd.out
+${PACKAGE}FILES+= regress.dddh.out
+${PACKAGE}FILES+= regress.ddhd.out
+${PACKAGE}FILES+= regress.ddhd2.out
+${PACKAGE}FILES+= regress.ddhh.out
+${PACKAGE}FILES+= regress.ddhh2.out
+${PACKAGE}FILES+= regress.dhdd.out
+${PACKAGE}FILES+= regress.dhdh.out
+${PACKAGE}FILES+= regress.dhhd.out
+${PACKAGE}FILES+= regress.dhhd2.out
+${PACKAGE}FILES+= regress.dhhh.out
+${PACKAGE}FILES+= regress.dhhh2.out
+${PACKAGE}FILES+= regress.ed.out
+${PACKAGE}FILES+= regress.grep.out
+${PACKAGE}FILES+= regress.hddd.out
+${PACKAGE}FILES+= regress.hddd2.out
+${PACKAGE}FILES+= regress.hddh.out
+${PACKAGE}FILES+= regress.hddh2.out
+${PACKAGE}FILES+= regress.hdhd.out
+${PACKAGE}FILES+= regress.hdhd2.out
+${PACKAGE}FILES+= regress.hdhh.out
+${PACKAGE}FILES+= regress.hdhh2.out
+${PACKAGE}FILES+= regress.hhdd.out
+${PACKAGE}FILES+= regress.hhdd2.out
+${PACKAGE}FILES+= regress.hhdh.out
+${PACKAGE}FILES+= regress.hhdh2.out
+${PACKAGE}FILES+= regress.hhhd.out
+${PACKAGE}FILES+= regress.hhhd2.out
+${PACKAGE}FILES+= regress.hhhh.out
+${PACKAGE}FILES+= regress.hhhh2.out
+${PACKAGE}FILES+= regress.n21.out
+${PACKAGE}FILES+= regress.rand1.out
+${PACKAGE}FILES+= regress.rand2.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.stutter.out
+${PACKAGE}FILES+= regress.stutter2.out
+${PACKAGE}FILES+= regress.tabs.out
+${PACKAGE}FILES+= regress.wX1.out
+${PACKAGE}FILES+= regress.wXl.out
+${PACKAGE}FILES+= regress.wc.out
+${PACKAGE}FILES+= regress.wdl.out
+${PACKAGE}FILES+= regress.wdn.out
+${PACKAGE}FILES+= regress.we.out
+${PACKAGE}FILES+= regress.wf.out
+${PACKAGE}FILES+= regress.wg.out
+${PACKAGE}FILES+= regress.wgd.out
+${PACKAGE}FILES+= regress.wo.out
+${PACKAGE}FILES+= regress.wp1.out
+${PACKAGE}FILES+= regress.wp2.out
+${PACKAGE}FILES+= regress.wp3.out
+${PACKAGE}FILES+= regress.wp4.out
+${PACKAGE}FILES+= regress.wp5.out
+${PACKAGE}FILES+= regress.wp6.out
+${PACKAGE}FILES+= regress.wu.out
+${PACKAGE}FILES+= regress.wwe.out
+${PACKAGE}FILES+= regress.wx.out
+${PACKAGE}FILES+= regress.wxn.out
+${PACKAGE}FILES+= regress.x.out
+${PACKAGE}FILES+= regress.xaa.out
+${PACKAGE}FILES+= regress.yes.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/jot/tests/Makefile.depend b/usr.bin/jot/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/jot/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/jot/tests/legacy_test.sh b/usr.bin/jot/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/jot/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/jot/tests/regress.ascii.out b/usr.bin/jot/tests/regress.ascii.out
new file mode 100644
index 000000000000..abcfb84107fd
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ascii.out
Binary files differ
diff --git a/usr.bin/jot/tests/regress.block.out b/usr.bin/jot/tests/regress.block.out
new file mode 100644
index 000000000000..a6f4536b29f3
--- /dev/null
+++ b/usr.bin/jot/tests/regress.block.out
@@ -0,0 +1,512 @@
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
+x
diff --git a/usr.bin/jot/tests/regress.dddd.out b/usr.bin/jot/tests/regress.dddd.out
new file mode 100644
index 000000000000..190423f88f82
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dddd.out
@@ -0,0 +1,100 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
diff --git a/usr.bin/jot/tests/regress.dddh.out b/usr.bin/jot/tests/regress.dddh.out
new file mode 100644
index 000000000000..d0da9013ad24
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dddh.out
@@ -0,0 +1,100 @@
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+31
+33
+35
+37
+39
+41
+43
+45
+47
+49
+51
+53
+55
+57
+59
+61
+63
+65
+67
+69
+71
+73
+75
+77
+79
+81
+83
+85
+87
+89
+91
+93
+95
+97
+99
+101
+103
+105
+107
+109
+111
+113
+115
+117
+119
+121
+123
+125
+127
+129
+131
+133
+135
+137
+139
+141
+143
+145
+147
+149
+151
+153
+155
+157
+159
+161
+163
+165
+167
+169
+171
+173
+175
+177
+179
+181
+183
+185
+187
+189
+191
+193
+195
+197
+199
diff --git a/usr.bin/jot/tests/regress.ddhd.out b/usr.bin/jot/tests/regress.ddhd.out
new file mode 100644
index 000000000000..544a1eafe367
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ddhd.out
@@ -0,0 +1,100 @@
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
diff --git a/usr.bin/jot/tests/regress.ddhd2.out b/usr.bin/jot/tests/regress.ddhd2.out
new file mode 100644
index 000000000000..6e21bc776693
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ddhd2.out
@@ -0,0 +1,100 @@
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
diff --git a/usr.bin/jot/tests/regress.ddhh.out b/usr.bin/jot/tests/regress.ddhh.out
new file mode 100644
index 000000000000..46066d06aeaf
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ddhh.out
@@ -0,0 +1,100 @@
+-78
+-76
+-74
+-72
+-70
+-68
+-66
+-64
+-62
+-60
+-58
+-56
+-54
+-52
+-50
+-48
+-46
+-44
+-42
+-40
+-38
+-36
+-34
+-32
+-30
+-28
+-26
+-24
+-22
+-20
+-18
+-16
+-14
+-12
+-10
+-8
+-6
+-4
+-2
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
diff --git a/usr.bin/jot/tests/regress.ddhh2.out b/usr.bin/jot/tests/regress.ddhh2.out
new file mode 100644
index 000000000000..9299c4ca25af
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ddhh2.out
@@ -0,0 +1,100 @@
+-38
+-36
+-34
+-32
+-30
+-28
+-26
+-24
+-22
+-20
+-18
+-16
+-14
+-12
+-10
+-8
+-6
+-4
+-2
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
+122
+124
+126
+128
+130
+132
+134
+136
+138
+140
+142
+144
+146
+148
+150
+152
+154
+156
+158
+160
diff --git a/usr.bin/jot/tests/regress.dhdd.out b/usr.bin/jot/tests/regress.dhdd.out
new file mode 100644
index 000000000000..d61477be889d
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhdd.out
@@ -0,0 +1,100 @@
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
diff --git a/usr.bin/jot/tests/regress.dhdh.out b/usr.bin/jot/tests/regress.dhdh.out
new file mode 100644
index 000000000000..1fc43dc85699
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhdh.out
@@ -0,0 +1,100 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
+122
+124
+126
+128
+130
+132
+134
+136
+138
+140
+142
+144
+146
+148
+150
+152
+154
+156
+158
+160
+162
+164
+166
+168
+170
+172
+174
+176
+178
+180
+182
+184
+186
+188
+190
+192
+194
+196
+198
+200
+202
+204
+206
+208
+210
+212
+214
+216
+218
diff --git a/usr.bin/jot/tests/regress.dhhd.out b/usr.bin/jot/tests/regress.dhhd.out
new file mode 100644
index 000000000000..d21b1342c6db
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhhd.out
@@ -0,0 +1,101 @@
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
diff --git a/usr.bin/jot/tests/regress.dhhd2.out b/usr.bin/jot/tests/regress.dhhd2.out
new file mode 100644
index 000000000000..315826d6b7fd
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhhd2.out
@@ -0,0 +1,141 @@
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
diff --git a/usr.bin/jot/tests/regress.dhhh.out b/usr.bin/jot/tests/regress.dhhh.out
new file mode 100644
index 000000000000..302eb42c8389
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhhh.out
@@ -0,0 +1,51 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
diff --git a/usr.bin/jot/tests/regress.dhhh2.out b/usr.bin/jot/tests/regress.dhhh2.out
new file mode 100644
index 000000000000..f56b35b7114b
--- /dev/null
+++ b/usr.bin/jot/tests/regress.dhhh2.out
@@ -0,0 +1,71 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
+122
+124
+126
+128
+130
+132
+134
+136
+138
+140
+142
+144
+146
+148
+150
+152
+154
+156
+158
+160
diff --git a/usr.bin/jot/tests/regress.ed.out b/usr.bin/jot/tests/regress.ed.out
new file mode 100644
index 000000000000..d82a36d630c5
--- /dev/null
+++ b/usr.bin/jot/tests/regress.ed.out
@@ -0,0 +1,30 @@
+2s/old/new/
+7s/old/new/
+12s/old/new/
+17s/old/new/
+22s/old/new/
+27s/old/new/
+32s/old/new/
+37s/old/new/
+42s/old/new/
+47s/old/new/
+52s/old/new/
+57s/old/new/
+62s/old/new/
+67s/old/new/
+72s/old/new/
+77s/old/new/
+82s/old/new/
+87s/old/new/
+92s/old/new/
+97s/old/new/
+102s/old/new/
+107s/old/new/
+112s/old/new/
+117s/old/new/
+122s/old/new/
+127s/old/new/
+132s/old/new/
+137s/old/new/
+142s/old/new/
+147s/old/new/
diff --git a/usr.bin/jot/tests/regress.grep.out b/usr.bin/jot/tests/regress.grep.out
new file mode 100644
index 000000000000..b6578efc7c05
--- /dev/null
+++ b/usr.bin/jot/tests/regress.grep.out
@@ -0,0 +1 @@
+................................................................................
diff --git a/usr.bin/jot/tests/regress.hddd.out b/usr.bin/jot/tests/regress.hddd.out
new file mode 100644
index 000000000000..96cc558853a0
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hddd.out
@@ -0,0 +1,50 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
diff --git a/usr.bin/jot/tests/regress.hddd2.out b/usr.bin/jot/tests/regress.hddd2.out
new file mode 100644
index 000000000000..e8823e176663
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hddd2.out
@@ -0,0 +1,30 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
diff --git a/usr.bin/jot/tests/regress.hddh.out b/usr.bin/jot/tests/regress.hddh.out
new file mode 100644
index 000000000000..7927325e974f
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hddh.out
@@ -0,0 +1,50 @@
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+31
+33
+35
+37
+39
+41
+43
+45
+47
+49
+51
+53
+55
+57
+59
+61
+63
+65
+67
+69
+71
+73
+75
+77
+79
+81
+83
+85
+87
+89
+91
+93
+95
+97
+99
diff --git a/usr.bin/jot/tests/regress.hddh2.out b/usr.bin/jot/tests/regress.hddh2.out
new file mode 100644
index 000000000000..da7d98bed4d7
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hddh2.out
@@ -0,0 +1,30 @@
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+31
+33
+35
+37
+39
+41
+43
+45
+47
+49
+51
+53
+55
+57
+59
diff --git a/usr.bin/jot/tests/regress.hdhd.out b/usr.bin/jot/tests/regress.hdhd.out
new file mode 100644
index 000000000000..32ee48f514a8
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hdhd.out
@@ -0,0 +1,50 @@
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
diff --git a/usr.bin/jot/tests/regress.hdhd2.out b/usr.bin/jot/tests/regress.hdhd2.out
new file mode 100644
index 000000000000..eaa2cdc47d0c
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hdhd2.out
@@ -0,0 +1,30 @@
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
diff --git a/usr.bin/jot/tests/regress.hdhh.out b/usr.bin/jot/tests/regress.hdhh.out
new file mode 100644
index 000000000000..d06ebfa3015e
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hdhh.out
@@ -0,0 +1,50 @@
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
diff --git a/usr.bin/jot/tests/regress.hdhh2.out b/usr.bin/jot/tests/regress.hdhh2.out
new file mode 100644
index 000000000000..3a412e68e5c0
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hdhh2.out
@@ -0,0 +1,30 @@
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
+122
+124
+126
+128
+130
+132
+134
+136
+138
+140
+142
+144
+146
+148
+150
+152
+154
+156
+158
+160
diff --git a/usr.bin/jot/tests/regress.hhdd.out b/usr.bin/jot/tests/regress.hhdd.out
new file mode 100644
index 000000000000..8d9aa3539f69
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhdd.out
@@ -0,0 +1,50 @@
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
diff --git a/usr.bin/jot/tests/regress.hhdd2.out b/usr.bin/jot/tests/regress.hhdd2.out
new file mode 100644
index 000000000000..ae3c906e09f7
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhdd2.out
@@ -0,0 +1,30 @@
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
diff --git a/usr.bin/jot/tests/regress.hhdh.out b/usr.bin/jot/tests/regress.hhdh.out
new file mode 100644
index 000000000000..520f4ef0441b
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhdh.out
@@ -0,0 +1,50 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
diff --git a/usr.bin/jot/tests/regress.hhdh2.out b/usr.bin/jot/tests/regress.hhdh2.out
new file mode 100644
index 000000000000..5b289bf10c1e
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhdh2.out
@@ -0,0 +1,30 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
diff --git a/usr.bin/jot/tests/regress.hhhd.out b/usr.bin/jot/tests/regress.hhhd.out
new file mode 100644
index 000000000000..f5ddbc568573
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhhd.out
@@ -0,0 +1,50 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+47
+49
+51
+53
+55
+57
+59
+61
+63
+65
+67
+69
+71
+73
+75
+77
+79
+81
+83
+85
+87
+89
+91
+93
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
+120
diff --git a/usr.bin/jot/tests/regress.hhhd2.out b/usr.bin/jot/tests/regress.hhhd2.out
new file mode 100644
index 000000000000..e6a8c4f5e738
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhhd2.out
@@ -0,0 +1,30 @@
+20
+25
+30
+34
+39
+44
+49
+54
+59
+63
+68
+73
+78
+83
+88
+92
+97
+102
+107
+112
+117
+121
+126
+131
+136
+141
+146
+150
+155
+160
diff --git a/usr.bin/jot/tests/regress.hhhh.out b/usr.bin/jot/tests/regress.hhhh.out
new file mode 100644
index 000000000000..520f4ef0441b
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhhh.out
@@ -0,0 +1,50 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
+80
+82
+84
+86
+88
+90
+92
+94
+96
+98
+100
+102
+104
+106
+108
+110
+112
+114
+116
+118
diff --git a/usr.bin/jot/tests/regress.hhhh2.out b/usr.bin/jot/tests/regress.hhhh2.out
new file mode 100644
index 000000000000..5b289bf10c1e
--- /dev/null
+++ b/usr.bin/jot/tests/regress.hhhh2.out
@@ -0,0 +1,30 @@
+20
+22
+24
+26
+28
+30
+32
+34
+36
+38
+40
+42
+44
+46
+48
+50
+52
+54
+56
+58
+60
+62
+64
+66
+68
+70
+72
+74
+76
+78
diff --git a/usr.bin/jot/tests/regress.n21.out b/usr.bin/jot/tests/regress.n21.out
new file mode 100644
index 000000000000..89b0879a5642
--- /dev/null
+++ b/usr.bin/jot/tests/regress.n21.out
@@ -0,0 +1,21 @@
+-1.00
+-0.90
+-0.80
+-0.70
+-0.60
+-0.50
+-0.40
+-0.30
+-0.20
+-0.10
+-0.00
+0.10
+0.20
+0.30
+0.40
+0.50
+0.60
+0.70
+0.80
+0.90
+1.00
diff --git a/usr.bin/jot/tests/regress.rand1.out b/usr.bin/jot/tests/regress.rand1.out
new file mode 100644
index 000000000000..8b1acc12b635
--- /dev/null
+++ b/usr.bin/jot/tests/regress.rand1.out
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/usr.bin/jot/tests/regress.rand2.out b/usr.bin/jot/tests/regress.rand2.out
new file mode 100644
index 000000000000..8b1acc12b635
--- /dev/null
+++ b/usr.bin/jot/tests/regress.rand2.out
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/usr.bin/jot/tests/regress.sh b/usr.bin/jot/tests/regress.sh
new file mode 100644
index 000000000000..85f431fac103
--- /dev/null
+++ b/usr.bin/jot/tests/regress.sh
@@ -0,0 +1,67 @@
+
+echo 1..60
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`x', `jot -w "%X" -s , 100 1 200')
+REGRESSION_TEST(`hhhh', `jot 50 20 120 2')
+REGRESSION_TEST(`hhhd', `jot 50 20 120 -')
+REGRESSION_TEST(`hhdh', `jot 50 20 - 2')
+REGRESSION_TEST(`hhdd', `jot 50 20 - -')
+REGRESSION_TEST(`hdhh', `jot 50 - 120 2')
+REGRESSION_TEST(`hdhd', `jot 50 - 120 -')
+REGRESSION_TEST(`hddh', `jot 50 - - 2')
+REGRESSION_TEST(`hddd', `jot 50 - - -')
+REGRESSION_TEST(`dhhh', `jot - 20 120 2')
+REGRESSION_TEST(`dhhd', `jot - 20 120 -')
+REGRESSION_TEST(`dhdh', `jot - 20 - 2')
+REGRESSION_TEST(`dhdd', `jot - 20 - -')
+REGRESSION_TEST(`ddhh', `jot - - 120 2')
+REGRESSION_TEST(`ddhd', `jot - - 120 -')
+REGRESSION_TEST(`dddh', `jot - - - 2')
+REGRESSION_TEST(`dddd', `jot - - - -')
+REGRESSION_TEST(`hhhh2', `jot 30 20 160 2')
+REGRESSION_TEST(`hhhd2', `jot 30 20 160 -')
+REGRESSION_TEST(`hhdh2', `jot 30 20 - 2')
+REGRESSION_TEST(`hhdd2', `jot 30 20 - -')
+REGRESSION_TEST(`hdhh2', `jot 30 - 160 2')
+REGRESSION_TEST(`hdhd2', `jot 30 - 160 -')
+REGRESSION_TEST(`hddh2', `jot 30 - - 2')
+REGRESSION_TEST(`hddd2', `jot 30 - - -')
+REGRESSION_TEST(`dhhh2', `jot - 20 160 2')
+REGRESSION_TEST(`dhhd2', `jot - 20 160 -')
+REGRESSION_TEST(`ddhh2', `jot - - 160 2')
+REGRESSION_TEST(`rand1', `jot -r 10000 0 9 | sort -u')
+REGRESSION_TEST(`rand2', `jot -r 10000 9 0 | sort -u')
+REGRESSION_TEST(`n21', `jot 21 -1 1.00')
+REGRESSION_TEST(`ascii', `jot -c 128 0')
+REGRESSION_TEST(`xaa', `jot -w xa%c 26 a')
+REGRESSION_TEST(`yes', `jot -b yes 10')
+REGRESSION_TEST(`ed', `jot -w %ds/old/new/ 30 2 - 5')
+REGRESSION_TEST(`stutter', `jot - 9 0 -.5')
+REGRESSION_TEST(`stutter2', `jot -w %d - 9.5 0 -.5')
+REGRESSION_TEST(`block', `jot -b x 512')
+REGRESSION_TEST(`tabs', `jot -s, - 10 132 4')
+REGRESSION_TEST(`grep', `jot -s "" -b . 80')
+REGRESSION_TEST(`wf', `jot -w "a%.1fb" 10')
+REGRESSION_TEST(`we', `jot -w "a%eb" 10')
+REGRESSION_TEST(`wwe', `jot -w "a%-15eb" 10')
+REGRESSION_TEST(`wg', `jot -w "a%20gb" 10')
+REGRESSION_TEST(`wc', `jot -w "a%cb" 10 33 43')
+REGRESSION_TEST(`wgd', `jot -w "a%gb" 10 .2')
+REGRESSION_TEST(`wu', `jot -w "a%ub" 10')
+REGRESSION_TEST(`wo', `jot -w "a%ob" 10')
+REGRESSION_TEST(`wx', `jot -w "a%xb" 10')
+REGRESSION_TEST(`wX1', `jot -w "a%Xb" 10')
+REGRESSION_TEST(`wXl', `jot -w "a%Xb" 10 2147483648')
+REGRESSION_TEST(`wdl', `jot -w "a%db" 10 2147483648 2>/dev/null')
+REGRESSION_TEST(`wxn', `jot -w "a%xb" 10 -5 2>/dev/null')
+REGRESSION_TEST(`wdn', `jot -w "a%db" 10 -5')
+REGRESSION_TEST(`wp1', `jot -w "%%%d%%%%" 10')
+REGRESSION_TEST(`wp2', `jot -w "%d%%d%%" 10')
+REGRESSION_TEST(`wp3', `jot -w "a%%A%%%d%%B%%b" 10')
+REGRESSION_TEST(`wp4', `jot -w "%%d%d%%d%%" 10')
+REGRESSION_TEST(`wp5', `jot -w ftp://www.example.com/pub/uploaded%%20files/disk%03d.iso 10')
+REGRESSION_TEST(`wp6', `jot -w "%d%" 10')
+
+REGRESSION_END()
diff --git a/usr.bin/jot/tests/regress.stutter.out b/usr.bin/jot/tests/regress.stutter.out
new file mode 100644
index 000000000000..10eb87d2a40a
--- /dev/null
+++ b/usr.bin/jot/tests/regress.stutter.out
@@ -0,0 +1,19 @@
+9
+8
+8
+8
+7
+6
+6
+6
+5
+4
+4
+4
+3
+2
+2
+2
+1
+0
+0
diff --git a/usr.bin/jot/tests/regress.stutter2.out b/usr.bin/jot/tests/regress.stutter2.out
new file mode 100644
index 000000000000..44e0ba1c89cc
--- /dev/null
+++ b/usr.bin/jot/tests/regress.stutter2.out
@@ -0,0 +1,20 @@
+9
+9
+8
+8
+7
+7
+6
+6
+5
+5
+4
+4
+3
+3
+2
+2
+1
+1
+0
+0
diff --git a/usr.bin/jot/tests/regress.tabs.out b/usr.bin/jot/tests/regress.tabs.out
new file mode 100644
index 000000000000..7859413434a7
--- /dev/null
+++ b/usr.bin/jot/tests/regress.tabs.out
@@ -0,0 +1 @@
+10,14,18,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130
diff --git a/usr.bin/jot/tests/regress.wX1.out b/usr.bin/jot/tests/regress.wX1.out
new file mode 100644
index 000000000000..dc7f5e92ed38
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wX1.out
@@ -0,0 +1,10 @@
+a1b
+a2b
+a3b
+a4b
+a5b
+a6b
+a7b
+a8b
+a9b
+aAb
diff --git a/usr.bin/jot/tests/regress.wXl.out b/usr.bin/jot/tests/regress.wXl.out
new file mode 100644
index 000000000000..cf6b9b74ca3b
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wXl.out
@@ -0,0 +1,10 @@
+a80000000b
+a80000001b
+a80000002b
+a80000003b
+a80000004b
+a80000005b
+a80000006b
+a80000007b
+a80000008b
+a80000009b
diff --git a/usr.bin/jot/tests/regress.wc.out b/usr.bin/jot/tests/regress.wc.out
new file mode 100644
index 000000000000..f6e77d93fc54
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wc.out
@@ -0,0 +1,10 @@
+a!b
+a"b
+a#b
+a$b
+a%b
+a&b
+a'b
+a(b
+a)b
+a+b
diff --git a/usr.bin/jot/tests/regress.wdl.out b/usr.bin/jot/tests/regress.wdl.out
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wdl.out
diff --git a/usr.bin/jot/tests/regress.wdn.out b/usr.bin/jot/tests/regress.wdn.out
new file mode 100644
index 000000000000..c4027de9f0d2
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wdn.out
@@ -0,0 +1,10 @@
+a-5b
+a-4b
+a-3b
+a-2b
+a-1b
+a0b
+a1b
+a2b
+a3b
+a4b
diff --git a/usr.bin/jot/tests/regress.we.out b/usr.bin/jot/tests/regress.we.out
new file mode 100644
index 000000000000..5a3727da9fdd
--- /dev/null
+++ b/usr.bin/jot/tests/regress.we.out
@@ -0,0 +1,10 @@
+a1.000000e+00b
+a2.000000e+00b
+a3.000000e+00b
+a4.000000e+00b
+a5.000000e+00b
+a6.000000e+00b
+a7.000000e+00b
+a8.000000e+00b
+a9.000000e+00b
+a1.000000e+01b
diff --git a/usr.bin/jot/tests/regress.wf.out b/usr.bin/jot/tests/regress.wf.out
new file mode 100644
index 000000000000..7fd30214f7e1
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wf.out
@@ -0,0 +1,10 @@
+a1.0b
+a2.0b
+a3.0b
+a4.0b
+a5.0b
+a6.0b
+a7.0b
+a8.0b
+a9.0b
+a10.0b
diff --git a/usr.bin/jot/tests/regress.wg.out b/usr.bin/jot/tests/regress.wg.out
new file mode 100644
index 000000000000..5c33e352c97d
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wg.out
@@ -0,0 +1,10 @@
+a 1b
+a 2b
+a 3b
+a 4b
+a 5b
+a 6b
+a 7b
+a 8b
+a 9b
+a 10b
diff --git a/usr.bin/jot/tests/regress.wgd.out b/usr.bin/jot/tests/regress.wgd.out
new file mode 100644
index 000000000000..0f3f96d09b1b
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wgd.out
@@ -0,0 +1,10 @@
+a0.2b
+a1.2b
+a2.2b
+a3.2b
+a4.2b
+a5.2b
+a6.2b
+a7.2b
+a8.2b
+a9.2b
diff --git a/usr.bin/jot/tests/regress.wo.out b/usr.bin/jot/tests/regress.wo.out
new file mode 100644
index 000000000000..4c89c92b0b20
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wo.out
@@ -0,0 +1,10 @@
+a1b
+a2b
+a3b
+a4b
+a5b
+a6b
+a7b
+a10b
+a11b
+a12b
diff --git a/usr.bin/jot/tests/regress.wp1.out b/usr.bin/jot/tests/regress.wp1.out
new file mode 100644
index 000000000000..6a5e94cba361
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp1.out
@@ -0,0 +1,10 @@
+%1%%
+%2%%
+%3%%
+%4%%
+%5%%
+%6%%
+%7%%
+%8%%
+%9%%
+%10%%
diff --git a/usr.bin/jot/tests/regress.wp2.out b/usr.bin/jot/tests/regress.wp2.out
new file mode 100644
index 000000000000..a489d6932cbc
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp2.out
@@ -0,0 +1,10 @@
+1%d%
+2%d%
+3%d%
+4%d%
+5%d%
+6%d%
+7%d%
+8%d%
+9%d%
+10%d%
diff --git a/usr.bin/jot/tests/regress.wp3.out b/usr.bin/jot/tests/regress.wp3.out
new file mode 100644
index 000000000000..95e31bb3dcbd
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp3.out
@@ -0,0 +1,10 @@
+a%A%1%B%b
+a%A%2%B%b
+a%A%3%B%b
+a%A%4%B%b
+a%A%5%B%b
+a%A%6%B%b
+a%A%7%B%b
+a%A%8%B%b
+a%A%9%B%b
+a%A%10%B%b
diff --git a/usr.bin/jot/tests/regress.wp4.out b/usr.bin/jot/tests/regress.wp4.out
new file mode 100644
index 000000000000..cd177b28f09c
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp4.out
@@ -0,0 +1,10 @@
+%d1%d%
+%d2%d%
+%d3%d%
+%d4%d%
+%d5%d%
+%d6%d%
+%d7%d%
+%d8%d%
+%d9%d%
+%d10%d%
diff --git a/usr.bin/jot/tests/regress.wp5.out b/usr.bin/jot/tests/regress.wp5.out
new file mode 100644
index 000000000000..2889d8fac8e8
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp5.out
@@ -0,0 +1,10 @@
+ftp://www.example.com/pub/uploaded%20files/disk001.iso
+ftp://www.example.com/pub/uploaded%20files/disk002.iso
+ftp://www.example.com/pub/uploaded%20files/disk003.iso
+ftp://www.example.com/pub/uploaded%20files/disk004.iso
+ftp://www.example.com/pub/uploaded%20files/disk005.iso
+ftp://www.example.com/pub/uploaded%20files/disk006.iso
+ftp://www.example.com/pub/uploaded%20files/disk007.iso
+ftp://www.example.com/pub/uploaded%20files/disk008.iso
+ftp://www.example.com/pub/uploaded%20files/disk009.iso
+ftp://www.example.com/pub/uploaded%20files/disk010.iso
diff --git a/usr.bin/jot/tests/regress.wp6.out b/usr.bin/jot/tests/regress.wp6.out
new file mode 100644
index 000000000000..1f097f0216d7
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wp6.out
@@ -0,0 +1,10 @@
+1%
+2%
+3%
+4%
+5%
+6%
+7%
+8%
+9%
+10%
diff --git a/usr.bin/jot/tests/regress.wu.out b/usr.bin/jot/tests/regress.wu.out
new file mode 100644
index 000000000000..c39e5f6712be
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wu.out
@@ -0,0 +1,10 @@
+a1b
+a2b
+a3b
+a4b
+a5b
+a6b
+a7b
+a8b
+a9b
+a10b
diff --git a/usr.bin/jot/tests/regress.wwe.out b/usr.bin/jot/tests/regress.wwe.out
new file mode 100644
index 000000000000..7c873a510bc3
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wwe.out
@@ -0,0 +1,10 @@
+a1.000000e+00 b
+a2.000000e+00 b
+a3.000000e+00 b
+a4.000000e+00 b
+a5.000000e+00 b
+a6.000000e+00 b
+a7.000000e+00 b
+a8.000000e+00 b
+a9.000000e+00 b
+a1.000000e+01 b
diff --git a/usr.bin/jot/tests/regress.wx.out b/usr.bin/jot/tests/regress.wx.out
new file mode 100644
index 000000000000..5520d0101db5
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wx.out
@@ -0,0 +1,10 @@
+a1b
+a2b
+a3b
+a4b
+a5b
+a6b
+a7b
+a8b
+a9b
+aab
diff --git a/usr.bin/jot/tests/regress.wxn.out b/usr.bin/jot/tests/regress.wxn.out
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/jot/tests/regress.wxn.out
diff --git a/usr.bin/jot/tests/regress.x.out b/usr.bin/jot/tests/regress.x.out
new file mode 100644
index 000000000000..b10979320b73
--- /dev/null
+++ b/usr.bin/jot/tests/regress.x.out
@@ -0,0 +1 @@
+1,3,5,7,9,B,D,F,11,13,15,17,19,1B,1D,1F,21,23,25,27,29,2B,2D,2F,31,33,35,37,39,3B,3D,3F,41,43,45,47,49,4B,4D,4F,51,53,55,57,59,5B,5D,5F,61,63,65,67,69,6B,6D,6F,71,73,75,77,79,7B,7D,7F,81,83,85,87,89,8B,8D,8F,91,93,95,97,99,9B,9D,9F,A1,A3,A5,A7,A9,AB,AD,AF,B1,B3,B5,B7,B9,BB,BD,BF,C1,C3,C5,C8
diff --git a/usr.bin/jot/tests/regress.xaa.out b/usr.bin/jot/tests/regress.xaa.out
new file mode 100644
index 000000000000..b14f9a011092
--- /dev/null
+++ b/usr.bin/jot/tests/regress.xaa.out
@@ -0,0 +1,26 @@
+xaa
+xab
+xac
+xad
+xae
+xaf
+xag
+xah
+xai
+xaj
+xak
+xal
+xam
+xan
+xao
+xap
+xaq
+xar
+xas
+xat
+xau
+xav
+xaw
+xax
+xay
+xaz
diff --git a/usr.bin/jot/tests/regress.yes.out b/usr.bin/jot/tests/regress.yes.out
new file mode 100644
index 000000000000..74e8d372a576
--- /dev/null
+++ b/usr.bin/jot/tests/regress.yes.out
@@ -0,0 +1,10 @@
+yes
+yes
+yes
+yes
+yes
+yes
+yes
+yes
+yes
+yes
diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile
new file mode 100644
index 000000000000..2c5c456a6de5
--- /dev/null
+++ b/usr.bin/kdump/Makefile
@@ -0,0 +1,24 @@
+.include <src.opts.mk>
+
+.PATH: ${SRCTOP}/usr.bin/ktrace
+
+PROG= kdump
+SRCS= kdump.c subr.c
+CFLAGS+= -I${SRCTOP}/usr.bin/ktrace
+
+LIBADD= sysdecode
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_grp
+LIBADD+= cap_pwd
+CFLAGS+=-DWITH_CASPER
+.endif
+
+.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
+ ${MACHINE_CPUARCH} == "i386"
+SRCS+= linux.c
+.endif
+
+CFLAGS.linux.c+= -I${SRCTOP}/sys
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/kdump/Makefile.depend b/usr.bin/kdump/Makefile.depend
new file mode 100644
index 000000000000..2e066e8921c5
--- /dev/null
+++ b/usr.bin/kdump/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libsysdecode \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/kdump/Makefile.depend.options b/usr.bin/kdump/Makefile.depend.options
new file mode 100644
index 000000000000..57e160185715
--- /dev/null
+++ b/usr.bin/kdump/Makefile.depend.options
@@ -0,0 +1,9 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= \
+ lib/libcasper/services/cap_grp \
+ lib/libcasper/services/cap_pwd
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/kdump/kdump.1 b/usr.bin/kdump/kdump.1
new file mode 100644
index 000000000000..4e0b0f8de30e
--- /dev/null
+++ b/usr.bin/kdump/kdump.1
@@ -0,0 +1,184 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd July 16, 2022
+.Dt KDUMP 1
+.Os
+.Sh NAME
+.Nm kdump
+.Nd display kernel trace data
+.Sh SYNOPSIS
+.Nm
+.Op Fl dEnlHRSsTA
+.Op Fl f Ar trfile
+.Op Fl m Ar maxdata
+.Op Fl p Ar pid
+.Op Fl t Ar trstr
+.Sh DESCRIPTION
+The
+.Nm
+command displays the kernel trace files produced with
+.Xr ktrace 1
+in human readable format.
+By default, the file
+.Pa ktrace.out
+in the current directory is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl A
+Display the ABI of the traced process.
+.It Fl c
+Display the CPU number with each trace entry.
+.It Fl d
+Display all numbers in decimal.
+.It Fl E
+Display elapsed timestamps (time since beginning of trace).
+.It Fl f Ar trfile
+Display the specified file instead of
+.Pa ktrace.out .
+.It Fl H
+List the thread ID (tid) of the thread with each trace record, if available.
+If no thread ID is available, 0 will be printed.
+.It Fl l
+Loop reading the trace file, once the end-of-file is reached, waiting for
+more data.
+.It Fl m Ar maxdata
+Display at most
+.Ar maxdata
+bytes when decoding
+.Tn I/O .
+.It Fl n
+Suppress ad hoc translations.
+Normally
+.Nm
+tries to decode many system calls into a more human readable format.
+For example,
+.Xr ioctl 2
+values are replaced with the macro name and
+.Va errno
+values are replaced with the
+.Xr strerror 3
+string.
+Suppressing this feature yields a more consistent output format and is
+easily amenable to further processing.
+.It Fl p Ar pid
+Display only trace events that correspond to the process or thread
+.Ar pid .
+This may be useful when there are multiple processes or threads recorded in the
+same trace file.
+.It Fl R
+Display relative timestamps (time since previous entry).
+.It Fl r
+When decoding STRU records, display structure members such as UIDs,
+GIDs, dates etc. symbolically instead of numerically.
+.It Fl S
+Display system call numbers.
+.It Fl s
+Suppress display of I/O data.
+.It Fl T
+Display absolute timestamps for each entry (seconds since epoch).
+.It Fl t Ar trstr
+See the
+.Fl t
+option of
+.Xr ktrace 1 .
+.El
+.Pp
+The output format of
+.Nm
+is line oriented with several fields.
+The example below shows a section of a kdump generated by the following
+commands:
+.Bd -literal -offset indent
+?> ktrace echo "ktrace"
+
+?> kdump
+
+ 85045 echo CALL writev(0x1,0x804b030,0x2)
+ 85045 echo GIO fd 1 wrote 7 bytes
+ "ktrace
+ "
+ 85045 echo RET writev 7
+.Ed
+.Pp
+The first field is the PID of the process being traced.
+The second field is the name of the program being traced.
+The third field is the operation that the kernel performed
+on behalf of the process.
+If thread IDs are being printed, then an additional thread ID column will be
+added to the output between the PID field and program name field.
+.Pp
+In the first line above, the kernel executes the
+.Xr writev 2
+system call on behalf of the process so this is a
+.Li CALL
+operation.
+The fourth field shows the system call that was executed,
+including its arguments.
+The
+.Xr writev 2
+system call takes a file descriptor, in this case 1, or standard
+output, then a pointer to the iovector to write, and the number of
+iovectors that are to be written.
+In the second line we see the operation was
+.Li GIO ,
+for general I/O, and that file descriptor 1 had
+seven bytes written to it.
+This is followed by the seven bytes that were written, the string
+.Qq Li ktrace
+with a carriage return and line feed.
+The last line is the
+.Li RET
+operation, showing a return from the kernel, what system call we are
+returning from, and the return value that the process received.
+Seven bytes were written by the
+.Xr writev 2
+system call, so 7 is the return value.
+.Pp
+The possible operations are:
+.Bl -column -offset indent ".Li CALL" ".No data from user process"
+.It Sy Name Ta Sy Operation Ta Sy Fourth field
+.It Li CALL Ta enter syscall Ta syscall name and arguments
+.It Li RET Ta return from syscall Ta syscall name and return value
+.It Li NAMI Ta file name lookup Ta path to file
+.It Li GIO Ta general I/O Ta fd, read/write, number of bytes
+.It Li PSIG Ta signal Ta signal name, handler, mask, code
+.It Li CSW Ta context switch Ta stop/resume user/kernel wmesg
+.It Li USER Ta data from user process Ta the data
+.It Li STRU Ta various syscalls Ta structure
+.It Li SCTL Ta Xr sysctl 3 requests Ta MIB name
+.It Li PFLT Ta enter page fault Ta fault address and type
+.It Li PRET Ta return from page fault Ta fault result
+.El
+.Sh SEE ALSO
+.Xr ktrace 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
new file mode 100644
index 000000000000..48f645c339b9
--- /dev/null
+++ b/usr.bin/kdump/kdump.c
@@ -0,0 +1,2429 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#define _WANT_KERNEL_ERRNO
+#ifdef __LP64__
+#define _WANT_KEVENT32
+#endif
+#define _WANT_FREEBSD11_KEVENT
+#define _WANT_FREEBSD_BITSET
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/_bitset.h>
+#include <sys/bitset.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/event.h>
+#include <sys/ktrace.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysent.h>
+#include <sys/umtx.h>
+#include <sys/un.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+#ifdef WITH_CASPER
+#include <sys/nv.h>
+#endif
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netlink/netlink.h>
+#include <ctype.h>
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <netdb.h>
+#include <nl_types.h>
+#include <pwd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdecode.h>
+#include <time.h>
+#include <unistd.h>
+#include <vis.h>
+#include "ktrace.h"
+#include "kdump.h"
+
+#ifdef WITH_CASPER
+#include <libcasper.h>
+
+#include <casper/cap_grp.h>
+#include <casper/cap_pwd.h>
+#endif
+
+int fetchprocinfo(struct ktr_header *, u_int *);
+u_int findabi(struct ktr_header *);
+int fread_tail(void *, int, int);
+void dumpheader(struct ktr_header *, u_int);
+void dumptimeval(struct ktr_header_v0 *kth);
+void dumptimespec(struct ktr_header *kth);
+void ktrsyscall(struct ktr_syscall *, u_int);
+void ktrsysret(struct ktr_sysret *, u_int);
+void ktrnamei(char *, int);
+void hexdump(char *, int, int);
+void visdump(char *, int, int);
+void ktrgenio(struct ktr_genio *, int);
+void ktrpsig(struct ktr_psig *);
+void ktrcsw(struct ktr_csw *);
+void ktrcsw_old(struct ktr_csw_old *);
+void ktruser(int, void *);
+void ktrcaprights(cap_rights_t *);
+void ktritimerval(struct itimerval *it);
+void ktrsockaddr(struct sockaddr *);
+void ktrsplice(struct splice *);
+void ktrstat(struct stat *);
+void ktrstruct(char *, size_t);
+void ktrcapfail(struct ktr_cap_fail *);
+void ktrfault(struct ktr_fault *);
+void ktrfaultend(struct ktr_faultend *);
+void ktrkevent(struct kevent *);
+void ktrpollfd(struct pollfd *);
+void ktrstructarray(struct ktr_struct_array *, size_t);
+void ktrbitset(char *, struct bitset *, size_t);
+void ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc, u_int sv_flags);
+void ktrexecve(char *, int);
+void usage(void);
+
+#define TIMESTAMP_NONE 0x0
+#define TIMESTAMP_ABSOLUTE 0x1
+#define TIMESTAMP_ELAPSED 0x2
+#define TIMESTAMP_RELATIVE 0x4
+
+bool decimal, fancy = true, resolv;
+static bool abiflag, suppressdata, syscallno, tail, threads, cpuflag;
+static int timestamp, maxdata;
+static const char *tracefile = DEF_TRACEFILE;
+static struct ktr_header ktr_header;
+static short version;
+
+#define TIME_FORMAT "%b %e %T %Y"
+#define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
+
+struct proc_info
+{
+ TAILQ_ENTRY(proc_info) info;
+ u_int sv_flags;
+ pid_t pid;
+};
+
+static TAILQ_HEAD(trace_procs, proc_info) trace_procs;
+
+#ifdef WITH_CASPER
+static cap_channel_t *cappwd, *capgrp;
+
+static int
+cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp)
+{
+ cap_channel_t *capcas, *cappwdloc, *capgrploc;
+ const char *cmds[1], *fields[1];
+
+ capcas = cap_init();
+ if (capcas == NULL) {
+ err(1, "unable to create casper process");
+ exit(1);
+ }
+ cappwdloc = cap_service_open(capcas, "system.pwd");
+ capgrploc = cap_service_open(capcas, "system.grp");
+ /* Casper capability no longer needed. */
+ cap_close(capcas);
+ if (cappwdloc == NULL || capgrploc == NULL) {
+ if (cappwdloc == NULL)
+ warn("unable to open system.pwd service");
+ if (capgrploc == NULL)
+ warn("unable to open system.grp service");
+ exit(1);
+ }
+ /* Limit system.pwd to only getpwuid() function and pw_name field. */
+ cmds[0] = "getpwuid";
+ if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0)
+ err(1, "unable to limit system.pwd service");
+ fields[0] = "pw_name";
+ if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0)
+ err(1, "unable to limit system.pwd service");
+ /* Limit system.grp to only getgrgid() function and gr_name field. */
+ cmds[0] = "getgrgid";
+ if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0)
+ err(1, "unable to limit system.grp service");
+ fields[0] = "gr_name";
+ if (cap_grp_limit_fields(capgrploc, fields, 1) < 0)
+ err(1, "unable to limit system.grp service");
+
+ *cappwdp = cappwdloc;
+ *capgrpp = capgrploc;
+ return (0);
+}
+#endif /* WITH_CASPER */
+
+void
+print_integer_arg(const char *(*decoder)(int), int value)
+{
+ const char *str;
+
+ str = decoder(value);
+ if (str != NULL)
+ printf("%s", str);
+ else {
+ if (decimal)
+ printf("<invalid=%d>", value);
+ else
+ printf("<invalid=%#x>", value);
+ }
+}
+
+/* Like print_integer_arg but unknown values are treated as valid. */
+void
+print_integer_arg_valid(const char *(*decoder)(int), int value)
+{
+ const char *str;
+
+ str = decoder(value);
+ if (str != NULL)
+ printf("%s", str);
+ else {
+ if (decimal)
+ printf("%d", value);
+ else
+ printf("%#x", value);
+ }
+}
+
+bool
+print_mask_arg_part(bool (*decoder)(FILE *, int, int *), int value, int *rem)
+{
+
+ printf("%#x<", value);
+ return (decoder(stdout, value, rem));
+}
+
+void
+print_mask_arg(bool (*decoder)(FILE *, int, int *), int value)
+{
+ bool invalid;
+ int rem;
+
+ invalid = !print_mask_arg_part(decoder, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%u", rem);
+}
+
+void
+print_mask_arg0(bool (*decoder)(FILE *, int, int *), int value)
+{
+ bool invalid;
+ int rem;
+
+ if (value == 0) {
+ printf("0");
+ return;
+ }
+ printf("%#x<", value);
+ invalid = !decoder(stdout, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%u", rem);
+}
+
+static void
+decode_fileflags(fflags_t value)
+{
+ bool invalid;
+ fflags_t rem;
+
+ if (value == 0) {
+ printf("0");
+ return;
+ }
+ printf("%#x<", value);
+ invalid = !sysdecode_fileflags(stdout, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%u", rem);
+}
+
+void
+decode_filemode(int value)
+{
+ bool invalid;
+ int rem;
+
+ if (value == 0) {
+ printf("0");
+ return;
+ }
+ printf("%#o<", value);
+ invalid = !sysdecode_filemode(stdout, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%u", rem);
+}
+
+void
+print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), uint32_t value)
+{
+ bool invalid;
+ uint32_t rem;
+
+ printf("%#x<", value);
+ invalid = !decoder(stdout, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%u", rem);
+}
+
+void
+print_mask_argul(bool (*decoder)(FILE *, u_long, u_long *), u_long value)
+{
+ bool invalid;
+ u_long rem;
+
+ if (value == 0) {
+ printf("0");
+ return;
+ }
+ printf("%#lx<", value);
+ invalid = !decoder(stdout, value, &rem);
+ printf(">");
+ if (invalid)
+ printf("<invalid>%lu", rem);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ktrlen, size;
+ void *m;
+ int trpoints = ALL_POINTS;
+ int drop_logged;
+ pid_t pid = 0;
+ u_int sv_flags;
+
+ setlocale(LC_CTYPE, "");
+
+ timestamp = TIMESTAMP_NONE;
+
+ while ((ch = getopt(argc,argv,"f:cdElm:np:AHRrSsTt:")) != -1)
+ switch (ch) {
+ case 'A':
+ abiflag = true;
+ break;
+ case 'f':
+ tracefile = optarg;
+ break;
+ case 'c':
+ cpuflag = true;
+ break;
+ case 'd':
+ decimal = true;
+ break;
+ case 'l':
+ tail = true;
+ break;
+ case 'm':
+ maxdata = atoi(optarg);
+ break;
+ case 'n':
+ fancy = false;
+ break;
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'r':
+ resolv = true;
+ break;
+ case 'S':
+ syscallno = true;
+ break;
+ case 's':
+ suppressdata = true;
+ break;
+ case 'E':
+ timestamp |= TIMESTAMP_ELAPSED;
+ break;
+ case 'H':
+ threads = true;
+ break;
+ case 'R':
+ timestamp |= TIMESTAMP_RELATIVE;
+ break;
+ case 'T':
+ timestamp |= TIMESTAMP_ABSOLUTE;
+ break;
+ case 't':
+ trpoints = getpoints(optarg);
+ if (trpoints < 0)
+ errx(1, "unknown trace point in %s", optarg);
+ break;
+ default:
+ usage();
+ }
+
+ if (argc > optind)
+ usage();
+
+ m = malloc(size = 1025);
+ if (m == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ if (strcmp(tracefile, "-") != 0)
+ if (!freopen(tracefile, "r", stdin))
+ err(1, "%s", tracefile);
+
+ caph_cache_catpages();
+ caph_cache_tzdata();
+
+#ifdef WITH_CASPER
+ if (resolv) {
+ if (cappwdgrp_setup(&cappwd, &capgrp) < 0) {
+ cappwd = NULL;
+ capgrp = NULL;
+ }
+ }
+ if (!resolv || (cappwd != NULL && capgrp != NULL)) {
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+ }
+#else
+ if (!resolv) {
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+ }
+#endif
+ if (caph_limit_stdio() == -1)
+ err(1, "unable to limit stdio");
+
+ TAILQ_INIT(&trace_procs);
+ drop_logged = 0;
+ while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
+ if (ktr_header.ktr_type & KTR_VERSIONED) {
+ ktr_header.ktr_type &= ~KTR_VERSIONED;
+ version = ktr_header.ktr_version;
+ } else
+ version = KTR_VERSION0;
+ if (ktr_header.ktr_type & KTR_DROP) {
+ ktr_header.ktr_type &= ~KTR_DROP;
+ if (!drop_logged && threads) {
+ printf(
+ "%6d %6d %-8.*s Events dropped.\n",
+ ktr_header.ktr_pid,
+ ktr_header.ktr_tid > 0 ?
+ (lwpid_t)ktr_header.ktr_tid : 0,
+ MAXCOMLEN, ktr_header.ktr_comm);
+ drop_logged = 1;
+ } else if (!drop_logged) {
+ printf("%6d %-8.*s Events dropped.\n",
+ ktr_header.ktr_pid, MAXCOMLEN,
+ ktr_header.ktr_comm);
+ drop_logged = 1;
+ }
+ }
+ if ((ktrlen = ktr_header.ktr_len) < 0)
+ errx(1, "bogus length 0x%x", ktrlen);
+ if (ktrlen > size) {
+ m = realloc(m, ktrlen+1);
+ if (m == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ size = ktrlen;
+ }
+ if (version == KTR_VERSION0 &&
+ fseek(stdin, KTR_OFFSET_V0, SEEK_CUR) < 0)
+ errx(1, "%s", strerror(errno));
+ if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
+ errx(1, "data too short");
+ if (fetchprocinfo(&ktr_header, (u_int *)m) != 0)
+ continue;
+ if (pid && ktr_header.ktr_pid != pid &&
+ ktr_header.ktr_tid != pid)
+ continue;
+ if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
+ continue;
+ sv_flags = findabi(&ktr_header);
+ dumpheader(&ktr_header, sv_flags);
+ drop_logged = 0;
+ switch (ktr_header.ktr_type) {
+ case KTR_SYSCALL:
+ ktrsyscall((struct ktr_syscall *)m, sv_flags);
+ break;
+ case KTR_SYSRET:
+ ktrsysret((struct ktr_sysret *)m, sv_flags);
+ break;
+ case KTR_NAMEI:
+ case KTR_SYSCTL:
+ ktrnamei(m, ktrlen);
+ break;
+ case KTR_GENIO:
+ ktrgenio((struct ktr_genio *)m, ktrlen);
+ break;
+ case KTR_PSIG:
+ ktrpsig((struct ktr_psig *)m);
+ break;
+ case KTR_CSW:
+ if (ktrlen == sizeof(struct ktr_csw_old))
+ ktrcsw_old((struct ktr_csw_old *)m);
+ else
+ ktrcsw((struct ktr_csw *)m);
+ break;
+ case KTR_USER:
+ ktruser(ktrlen, m);
+ break;
+ case KTR_STRUCT:
+ ktrstruct(m, ktrlen);
+ break;
+ case KTR_CAPFAIL:
+ ktrcapfail((struct ktr_cap_fail *)m);
+ break;
+ case KTR_FAULT:
+ ktrfault((struct ktr_fault *)m);
+ break;
+ case KTR_FAULTEND:
+ ktrfaultend((struct ktr_faultend *)m);
+ break;
+ case KTR_STRUCT_ARRAY:
+ ktrstructarray((struct ktr_struct_array *)m, ktrlen);
+ break;
+ case KTR_ARGS:
+ case KTR_ENVS:
+ ktrexecve(m, ktrlen);
+ break;
+ default:
+ printf("\n");
+ break;
+ }
+ if (tail)
+ fflush(stdout);
+ }
+ return 0;
+}
+
+int
+fread_tail(void *buf, int size, int num)
+{
+ int i;
+
+ while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
+ sleep(1);
+ clearerr(stdin);
+ }
+ return (i);
+}
+
+int
+fetchprocinfo(struct ktr_header *kth, u_int *flags)
+{
+ struct proc_info *pi;
+
+ switch (kth->ktr_type) {
+ case KTR_PROCCTOR:
+ TAILQ_FOREACH(pi, &trace_procs, info) {
+ if (pi->pid == kth->ktr_pid) {
+ TAILQ_REMOVE(&trace_procs, pi, info);
+ break;
+ }
+ }
+ pi = malloc(sizeof(struct proc_info));
+ if (pi == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ pi->sv_flags = *flags;
+ pi->pid = kth->ktr_pid;
+ TAILQ_INSERT_TAIL(&trace_procs, pi, info);
+ return (1);
+
+ case KTR_PROCDTOR:
+ TAILQ_FOREACH(pi, &trace_procs, info) {
+ if (pi->pid == kth->ktr_pid) {
+ TAILQ_REMOVE(&trace_procs, pi, info);
+ free(pi);
+ break;
+ }
+ }
+ return (1);
+ }
+
+ return (0);
+}
+
+u_int
+findabi(struct ktr_header *kth)
+{
+ struct proc_info *pi;
+
+ TAILQ_FOREACH(pi, &trace_procs, info) {
+ if (pi->pid == kth->ktr_pid) {
+ return (pi->sv_flags);
+ }
+ }
+ return (0);
+}
+
+void
+dumptimeval(struct ktr_header_v0 *kth)
+{
+ static struct timeval prevtime, prevtime_e;
+ struct timeval temp;
+ const char *sign;
+
+ if (timestamp & TIMESTAMP_ABSOLUTE) {
+ printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec,
+ kth->ktr_time.tv_usec);
+ }
+ if (timestamp & TIMESTAMP_ELAPSED) {
+ if (prevtime_e.tv_sec == 0)
+ prevtime_e = kth->ktr_time;
+ timersub(&kth->ktr_time, &prevtime_e, &temp);
+ printf("%jd.%06ld ", (intmax_t)temp.tv_sec,
+ temp.tv_usec);
+ }
+ if (timestamp & TIMESTAMP_RELATIVE) {
+ if (prevtime.tv_sec == 0)
+ prevtime = kth->ktr_time;
+ if (timercmp(&kth->ktr_time, &prevtime, <)) {
+ timersub(&prevtime, &kth->ktr_time, &temp);
+ sign = "-";
+ } else {
+ timersub(&kth->ktr_time, &prevtime, &temp);
+ sign = "";
+ }
+ prevtime = kth->ktr_time;
+ printf("%s%jd.%06ld ", sign, (intmax_t)temp.tv_sec,
+ temp.tv_usec);
+ }
+}
+
+void
+dumptimespec(struct ktr_header *kth)
+{
+ static struct timespec prevtime, prevtime_e;
+ struct timespec temp;
+ const char *sign;
+
+ if (timestamp & TIMESTAMP_ABSOLUTE) {
+ printf("%jd.%09ld ", (intmax_t)kth->ktr_time.tv_sec,
+ kth->ktr_time.tv_nsec);
+ }
+ if (timestamp & TIMESTAMP_ELAPSED) {
+ if (prevtime_e.tv_sec == 0)
+ prevtime_e = kth->ktr_time;
+ timespecsub(&kth->ktr_time, &prevtime_e, &temp);
+ printf("%jd.%09ld ", (intmax_t)temp.tv_sec,
+ temp.tv_nsec);
+ }
+ if (timestamp & TIMESTAMP_RELATIVE) {
+ if (prevtime.tv_sec == 0)
+ prevtime = kth->ktr_time;
+ if (timespeccmp(&kth->ktr_time, &prevtime, <)) {
+ timespecsub(&prevtime, &kth->ktr_time, &temp);
+ sign = "-";
+ } else {
+ timespecsub(&kth->ktr_time, &prevtime, &temp);
+ sign = "";
+ }
+ prevtime = kth->ktr_time;
+ printf("%s%jd.%09ld ", sign, (intmax_t)temp.tv_sec,
+ temp.tv_nsec);
+ }
+}
+
+void
+dumpheader(struct ktr_header *kth, u_int sv_flags)
+{
+ static char unknown[64];
+ const char *abi;
+ const char *arch;
+ const char *type;
+
+ switch (kth->ktr_type) {
+ case KTR_SYSCALL:
+ type = "CALL";
+ break;
+ case KTR_SYSRET:
+ type = "RET ";
+ break;
+ case KTR_NAMEI:
+ type = "NAMI";
+ break;
+ case KTR_GENIO:
+ type = "GIO ";
+ break;
+ case KTR_PSIG:
+ type = "PSIG";
+ break;
+ case KTR_CSW:
+ type = "CSW ";
+ break;
+ case KTR_USER:
+ type = "USER";
+ break;
+ case KTR_STRUCT:
+ case KTR_STRUCT_ARRAY:
+ type = "STRU";
+ break;
+ case KTR_SYSCTL:
+ type = "SCTL";
+ break;
+ case KTR_CAPFAIL:
+ type = "CAP ";
+ break;
+ case KTR_FAULT:
+ type = "PFLT";
+ break;
+ case KTR_FAULTEND:
+ type = "PRET";
+ break;
+ case KTR_ARGS:
+ type = "ARGS";
+ break;
+ case KTR_ENVS:
+ type = "ENVS";
+ break;
+ default:
+ sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
+ type = unknown;
+ }
+
+ /*
+ * The ktr_tid field was previously the ktr_buffer field, which held
+ * the kernel pointer value for the buffer associated with data
+ * following the record header. It now holds a threadid, but only
+ * for trace files after the change. Older trace files still contain
+ * kernel pointers. Detect this and suppress the results by printing
+ * negative tid's as 0.
+ */
+ if (threads)
+ printf("%6d %6d %-8.*s ", kth->ktr_pid,
+ kth->ktr_tid > 0 ? (lwpid_t)kth->ktr_tid : 0,
+ MAXCOMLEN, kth->ktr_comm);
+ else
+ printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
+ if (timestamp) {
+ if (version == KTR_VERSION0)
+ dumptimeval((struct ktr_header_v0 *)kth);
+ else
+ dumptimespec(kth);
+ }
+ if (cpuflag && version > KTR_VERSION0)
+ printf("%3d ", kth->ktr_cpu);
+ printf("%s ", type);
+ if (abiflag != 0) {
+ switch (sv_flags & SV_ABI_MASK) {
+ case SV_ABI_LINUX:
+ abi = "L";
+ break;
+ case SV_ABI_FREEBSD:
+ abi = "F";
+ break;
+ default:
+ abi = "U";
+ break;
+ }
+
+ if ((sv_flags & SV_LP64) != 0)
+ arch = "64";
+ else if ((sv_flags & SV_ILP32) != 0)
+ arch = "32";
+ else
+ arch = "00";
+
+ printf("%s%s ", abi, arch);
+ }
+}
+
+#include <sys/syscall.h>
+
+static void
+ioctlname(unsigned long val)
+{
+ const char *str;
+
+ str = sysdecode_ioctlname(val);
+ if (str != NULL)
+ printf("%s", str);
+ else if (decimal)
+ printf("%lu", val);
+ else
+ printf("%#lx", val);
+}
+
+static enum sysdecode_abi
+syscallabi(u_int sv_flags)
+{
+
+ if (sv_flags == 0)
+ return (SYSDECODE_ABI_FREEBSD);
+ switch (sv_flags & SV_ABI_MASK) {
+ case SV_ABI_FREEBSD:
+ return (SYSDECODE_ABI_FREEBSD);
+ case SV_ABI_LINUX:
+#ifdef __LP64__
+ if (sv_flags & SV_ILP32)
+ return (SYSDECODE_ABI_LINUX32);
+#endif
+ return (SYSDECODE_ABI_LINUX);
+ default:
+ return (SYSDECODE_ABI_UNKNOWN);
+ }
+}
+
+static void
+syscallname(u_int code, u_int sv_flags)
+{
+ const char *name;
+
+ name = sysdecode_syscallname(syscallabi(sv_flags), code);
+ if (name == NULL)
+ printf("[%d]", code);
+ else {
+ printf("%s", name);
+ if (syscallno)
+ printf("[%d]", code);
+ }
+}
+
+static void
+print_signal(int signo)
+{
+ const char *signame;
+
+ signame = sysdecode_signal(signo);
+ if (signame != NULL)
+ printf("%s", signame);
+ else
+ printf("SIG %d", signo);
+}
+
+void
+ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip;
+
+ syscallname(ktr->ktr_code, sv_flags);
+ ip = &ktr->ktr_args[0];
+ if (narg) {
+ char c = '(';
+ if (fancy) {
+ switch (sv_flags & SV_ABI_MASK) {
+ case SV_ABI_FREEBSD:
+ ktrsyscall_freebsd(ktr, &ip, &narg, &c,
+ sv_flags);
+ break;
+#ifdef SYSDECODE_HAVE_LINUX
+ case SV_ABI_LINUX:
+#ifdef __amd64__
+ if (sv_flags & SV_ILP32)
+ ktrsyscall_linux32(ktr, &ip,
+ &narg, &c);
+ else
+#endif
+ ktrsyscall_linux(ktr, &ip, &narg, &c);
+ break;
+#endif /* SYSDECODE_HAVE_LINUX */
+ }
+ }
+ while (narg > 0)
+ print_number(ip, narg, c);
+ putchar(')');
+ }
+ putchar('\n');
+}
+
+void
+ktrsyscall_freebsd(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc, u_int sv_flags)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip, *first;
+ intmax_t arg;
+ int quad_align, quad_slots;
+
+ ip = first = &ktr->ktr_args[0];
+ char c = *resc;
+
+ quad_align = 0;
+ if (sv_flags & SV_ILP32) {
+#ifdef __powerpc__
+ quad_align = 1;
+#endif
+ quad_slots = 2;
+ } else
+ quad_slots = 1;
+ switch (ktr->ktr_code) {
+ case SYS_bindat:
+ case SYS_chflagsat:
+ case SYS_connectat:
+ case SYS_faccessat:
+ case SYS_fchmodat:
+ case SYS_fchownat:
+ case SYS_fstatat:
+ case SYS_futimesat:
+ case SYS_linkat:
+ case SYS_mkdirat:
+ case SYS_mkfifoat:
+ case SYS_mknodat:
+ case SYS_openat:
+ case SYS_readlinkat:
+ case SYS_renameat:
+ case SYS_unlinkat:
+ case SYS_utimensat:
+ putchar('(');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ }
+ switch (ktr->ktr_code) {
+ case SYS_ioctl: {
+ print_number(ip, narg, c);
+ putchar(c);
+ ioctlname(*ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ }
+ case SYS_ptrace:
+ putchar('(');
+ print_integer_arg(sysdecode_ptrace_request, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case SYS_access:
+ case SYS_eaccess:
+ case SYS_faccessat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_access_mode, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_close_range:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_close_range_flags,
+ *ip);
+ ip += 3;
+ narg -= 3;
+ break;
+ case SYS_open:
+ case SYS_openat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_open_flags, ip[0]);
+ if ((ip[0] & O_CREAT) == O_CREAT) {
+ putchar(',');
+ decode_filemode(ip[1]);
+ }
+ ip += 2;
+ narg -= 2;
+ break;
+ case SYS_wait4:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_wait4_options, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_wait6:
+ putchar('(');
+ print_integer_arg(sysdecode_idtype, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ print_number64(first, ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_wait6_options, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_chmod:
+ case SYS_fchmod:
+ case SYS_lchmod:
+ case SYS_fchmodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mknodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_getfsstat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_getfsstat_mode, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mount:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_mount_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_unmount:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_mount_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_recvmsg:
+ case SYS_sendmsg:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_msg_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_recvfrom:
+ case SYS_sendto:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_msg_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_chflags:
+ case SYS_chflagsat:
+ case SYS_fchflags:
+ case SYS_lchflags:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_fileflags(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kill:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_signal(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_reboot:
+ putchar('(');
+ print_mask_arg(sysdecode_reboot_howto, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_umask:
+ putchar('(');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_msync:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_msync_flags, *ip);
+ ip++;
+ narg--;
+ break;
+#ifdef SYS_freebsd6_mmap
+ case SYS_freebsd6_mmap:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_mmap_prot, *ip);
+ putchar(',');
+ ip++;
+ narg--;
+ print_mask_arg(sysdecode_mmap_flags, *ip);
+ ip++;
+ narg--;
+ break;
+#endif
+ case SYS_mmap:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_mmap_prot, *ip);
+ putchar(',');
+ ip++;
+ narg--;
+ print_mask_arg(sysdecode_mmap_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mprotect:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_mmap_prot, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_madvise:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_madvice, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_pathconf:
+ case SYS_lpathconf:
+ case SYS_fpathconf:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_pathconf_name, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_getpriority:
+ case SYS_setpriority:
+ putchar('(');
+ print_integer_arg(sysdecode_prio_which, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case SYS_fcntl:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_fcntl_cmd, ip[0]);
+ if (sysdecode_fcntl_arg_p(ip[0])) {
+ putchar(',');
+ if (ip[0] == F_SETFL)
+ print_mask_arg(
+ sysdecode_fcntl_fileflags,
+ ip[1]);
+ else
+ sysdecode_fcntl_arg(stdout,
+ ip[0], ip[1],
+ decimal ? 10 : 16);
+ }
+ ip += 2;
+ narg -= 2;
+ break;
+ case SYS_socket: {
+ int sockdomain;
+ putchar('(');
+ sockdomain = *ip;
+ print_integer_arg(sysdecode_socketdomain,
+ sockdomain);
+ ip++;
+ narg--;
+ putchar(',');
+ print_mask_arg(sysdecode_socket_type, *ip);
+ ip++;
+ narg--;
+ if (sockdomain == PF_INET ||
+ sockdomain == PF_INET6) {
+ putchar(',');
+ print_integer_arg(sysdecode_ipproto,
+ *ip);
+ ip++;
+ narg--;
+ }
+ c = ',';
+ break;
+ }
+ case SYS_setsockopt:
+ case SYS_getsockopt: {
+ const char *str;
+
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg_valid(sysdecode_sockopt_level,
+ *ip);
+ str = sysdecode_sockopt_name(ip[0], ip[1]);
+ if (str != NULL) {
+ printf(",%s", str);
+ ip++;
+ narg--;
+ }
+ ip++;
+ narg--;
+ break;
+ }
+#ifdef SYS_freebsd6_lseek
+ case SYS_freebsd6_lseek:
+ print_number(ip, narg, c);
+ /* Hidden 'pad' argument, not in lseek(2) */
+ print_number(ip, narg, c);
+ print_number64(first, ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_whence, *ip);
+ ip++;
+ narg--;
+ break;
+#endif
+ case SYS_lseek:
+ print_number(ip, narg, c);
+ print_number64(first, ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_whence, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_flock:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_flock_operation, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mkfifo:
+ case SYS_mkfifoat:
+ case SYS_mkdir:
+ case SYS_mkdirat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shutdown:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_shutdown_how, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_socketpair:
+ putchar('(');
+ print_integer_arg(sysdecode_socketdomain, *ip);
+ ip++;
+ narg--;
+ putchar(',');
+ print_mask_arg(sysdecode_socket_type, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_getrlimit:
+ case SYS_setrlimit:
+ putchar('(');
+ print_integer_arg(sysdecode_rlimit, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_getrusage:
+ putchar('(');
+ print_integer_arg(sysdecode_getrusage_who, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_quotactl:
+ print_number(ip, narg, c);
+ putchar(',');
+ if (!sysdecode_quotactl_cmd(stdout, *ip)) {
+ if (decimal)
+ printf("<invalid=%d>", (int)*ip);
+ else
+ printf("<invalid=%#x>",
+ (int)*ip);
+ }
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_nfssvc:
+ putchar('(');
+ print_integer_arg(sysdecode_nfssvc_flags, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_rtprio:
+ case SYS_rtprio_thread:
+ putchar('(');
+ print_integer_arg(sysdecode_rtprio_function,
+ *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS___semctl:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_semctl_cmd, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_semget:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_semget_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_msgctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_msgctl_cmd, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shmat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_shmat_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shmctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_shmctl_cmd, *ip);
+ ip++;
+ narg--;
+ break;
+#ifdef SYS_freebsd12_shm_open
+ case SYS_freebsd12_shm_open:
+ if (ip[0] == (uintptr_t)SHM_ANON) {
+ printf("(SHM_ANON");
+ ip++;
+ } else {
+ print_number(ip, narg, c);
+ }
+ putchar(',');
+ print_mask_arg(sysdecode_open_flags, ip[0]);
+ putchar(',');
+ decode_filemode(ip[1]);
+ ip += 2;
+ narg -= 2;
+ break;
+#endif
+ case SYS_shm_open2:
+ if (ip[0] == (uintptr_t)SHM_ANON) {
+ printf("(SHM_ANON");
+ ip++;
+ } else {
+ print_number(ip, narg, c);
+ }
+ putchar(',');
+ print_mask_arg(sysdecode_open_flags, ip[0]);
+ putchar(',');
+ decode_filemode(ip[1]);
+ putchar(',');
+ print_mask_arg(sysdecode_shmflags, ip[2]);
+ ip += 3;
+ narg -= 3;
+ break;
+ case SYS_minherit:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_minherit_inherit,
+ *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_rfork:
+ putchar('(');
+ print_mask_arg(sysdecode_rfork_flags, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_lio_listio:
+ putchar('(');
+ print_integer_arg(sysdecode_lio_listio_mode,
+ *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_mlockall:
+ putchar('(');
+ print_mask_arg(sysdecode_mlockall_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sched_setscheduler:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_scheduler_policy,
+ *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sched_get_priority_max:
+ case SYS_sched_get_priority_min:
+ putchar('(');
+ print_integer_arg(sysdecode_scheduler_policy,
+ *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sendfile:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_sendfile_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kldsym:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_kldsym_cmd, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sigprocmask:
+ putchar('(');
+ print_integer_arg(sysdecode_sigprocmask_how,
+ *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS___acl_get_file:
+ case SYS___acl_set_file:
+ case SYS___acl_get_fd:
+ case SYS___acl_set_fd:
+ case SYS___acl_delete_file:
+ case SYS___acl_delete_fd:
+ case SYS___acl_aclcheck_file:
+ case SYS___acl_aclcheck_fd:
+ case SYS___acl_get_link:
+ case SYS___acl_set_link:
+ case SYS___acl_delete_link:
+ case SYS___acl_aclcheck_link:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_acltype, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sigaction:
+ putchar('(');
+ print_signal(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_extattrctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_extattrnamespace,
+ *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_nmount:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg0(sysdecode_mount_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_thr_create:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_thr_create_flags, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_thr_kill:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_signal(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kldunloadf:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_kldunload_flags,
+ *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_linkat:
+ case SYS_renameat:
+ case SYS_symlinkat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ ip++;
+ narg--;
+ print_number(ip, narg, c);
+ break;
+ case SYS_cap_fcntls_limit:
+ print_number(ip, narg, c);
+ putchar(',');
+ arg = *ip;
+ ip++;
+ narg--;
+ print_mask_arg32(sysdecode_cap_fcntlrights, arg);
+ break;
+ case SYS_posix_fadvise:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ (void)putchar(',');
+ print_integer_arg(sysdecode_fadvice, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_procctl:
+ putchar('(');
+ print_integer_arg(sysdecode_idtype, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ print_number64(first, ip, narg, c);
+ putchar(',');
+ print_integer_arg(sysdecode_procctl_cmd, *ip);
+ ip++;
+ narg--;
+ break;
+ case SYS__umtx_op: {
+ int op;
+
+ print_number(ip, narg, c);
+ putchar(',');
+ if (print_mask_arg_part(sysdecode_umtx_op_flags,
+ *ip, &op))
+ putchar('|');
+ print_integer_arg(sysdecode_umtx_op, op);
+ putchar('>');
+ switch (*ip) {
+ case UMTX_OP_CV_WAIT:
+ ip++;
+ narg--;
+ putchar(',');
+ print_mask_argul(
+ sysdecode_umtx_cvwait_flags, *ip);
+ break;
+ case UMTX_OP_RW_RDLOCK:
+ ip++;
+ narg--;
+ putchar(',');
+ print_mask_argul(
+ sysdecode_umtx_rwlock_flags, *ip);
+ break;
+ }
+ ip++;
+ narg--;
+ break;
+ }
+ case SYS_ftruncate:
+ case SYS_truncate:
+ print_number(ip, narg, c);
+ print_number64(first, ip, narg, c);
+ break;
+ case SYS_fchownat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+ case SYS_fstatat:
+ case SYS_utimensat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+ case SYS_unlinkat:
+ print_number(ip, narg, c);
+ break;
+ case SYS_sysarch:
+ putchar('(');
+ print_integer_arg(sysdecode_sysarch_number, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_getitimer:
+ case SYS_setitimer:
+ putchar('(');
+ print_integer_arg(sysdecode_itimer, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ }
+ switch (ktr->ktr_code) {
+ case SYS_chflagsat:
+ case SYS_fchownat:
+ case SYS_faccessat:
+ case SYS_fchmodat:
+ case SYS_fstatat:
+ case SYS_linkat:
+ case SYS_unlinkat:
+ case SYS_utimensat:
+ putchar(',');
+ print_mask_arg0(sysdecode_atflags, *ip);
+ ip++;
+ narg--;
+ break;
+ }
+ *resc = c;
+ *resip = ip;
+ *resnarg = narg;
+}
+
+void
+ktrsysret(struct ktr_sysret *ktr, u_int sv_flags)
+{
+ register_t ret = ktr->ktr_retval;
+ int error = ktr->ktr_error;
+
+ syscallname(ktr->ktr_code, sv_flags);
+ printf(" ");
+
+ if (error == 0) {
+ if (fancy) {
+ printf("%ld", (long)ret);
+ if (ret < 0 || ret > 9)
+ printf("/%#lx", (unsigned long)ret);
+ } else {
+ if (decimal)
+ printf("%ld", (long)ret);
+ else
+ printf("%#lx", (unsigned long)ret);
+ }
+ } else if (error == ERESTART)
+ printf("RESTART");
+ else if (error == EJUSTRETURN)
+ printf("JUSTRETURN");
+ else {
+ printf("-1 errno %d", sysdecode_freebsd_to_abi_errno(
+ syscallabi(sv_flags), error));
+ if (fancy)
+ printf(" %s", strerror(ktr->ktr_error));
+ }
+ putchar('\n');
+}
+
+void
+ktrnamei(char *cp, int len)
+{
+ printf("\"%.*s\"\n", len, cp);
+}
+
+void
+ktrexecve(char *m, int len)
+{
+ int i = 0;
+
+ while (i < len) {
+ printf("\"%s\"", m + i);
+ i += strlen(m + i) + 1;
+ if (i != len) {
+ printf(", ");
+ }
+ }
+ printf("\n");
+}
+
+void
+hexdump(char *p, int len, int screenwidth)
+{
+ int n, i;
+ int width;
+
+ width = 0;
+ do {
+ width += 2;
+ i = 13; /* base offset */
+ i += (width / 2) + 1; /* spaces every second byte */
+ i += (width * 2); /* width of bytes */
+ i += 3; /* " |" */
+ i += width; /* each byte */
+ i += 1; /* "|" */
+ } while (i < screenwidth);
+ width -= 2;
+
+ for (n = 0; n < len; n += width) {
+ for (i = n; i < n + width; i++) {
+ if ((i % width) == 0) { /* beginning of line */
+ printf(" 0x%04x", i);
+ }
+ if ((i % 2) == 0) {
+ printf(" ");
+ }
+ if (i < len)
+ printf("%02x", p[i] & 0xff);
+ else
+ printf(" ");
+ }
+ printf(" |");
+ for (i = n; i < n + width; i++) {
+ if (i >= len)
+ break;
+ if (p[i] >= ' ' && p[i] <= '~')
+ printf("%c", p[i]);
+ else
+ printf(".");
+ }
+ printf("|\n");
+ }
+ if ((i % width) != 0)
+ printf("\n");
+}
+
+void
+visdump(char *dp, int datalen, int screenwidth)
+{
+ int col = 0;
+ char *cp;
+ int width;
+ char visbuf[5];
+
+ printf(" \"");
+ col = 8;
+ for (;datalen > 0; datalen--, dp++) {
+ vis(visbuf, *dp, VIS_CSTYLE | VIS_NOLOCALE, *(dp+1));
+ cp = visbuf;
+ /*
+ * Keep track of printables and
+ * space chars (like fold(1)).
+ */
+ if (col == 0) {
+ putchar('\t');
+ col = 8;
+ }
+ switch(*cp) {
+ case '\n':
+ col = 0;
+ putchar('\n');
+ continue;
+ case '\t':
+ width = 8 - (col&07);
+ break;
+ default:
+ width = strlen(cp);
+ }
+ if (col + width > (screenwidth-2)) {
+ printf("\\\n\t");
+ col = 8;
+ }
+ col += width;
+ do {
+ putchar(*cp++);
+ } while (*cp);
+ }
+ if (col == 0)
+ printf(" ");
+ printf("\"\n");
+}
+
+void
+ktrgenio(struct ktr_genio *ktr, int len)
+{
+ int datalen = len - sizeof (struct ktr_genio);
+ char *dp = (char *)ktr + sizeof (struct ktr_genio);
+ static int screenwidth = 0;
+ int i, binary;
+
+ printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
+ ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
+ datalen == 1 ? "" : "s");
+ if (suppressdata)
+ return;
+ if (screenwidth == 0) {
+ struct winsize ws;
+
+ if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
+ ws.ws_col > 8)
+ screenwidth = ws.ws_col;
+ else
+ screenwidth = 80;
+ }
+ if (maxdata && datalen > maxdata)
+ datalen = maxdata;
+
+ for (i = 0, binary = 0; i < datalen && binary == 0; i++) {
+ if (dp[i] >= 32 && dp[i] < 127)
+ continue;
+ if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
+ continue;
+ binary = 1;
+ }
+ if (binary)
+ hexdump(dp, datalen, screenwidth);
+ else
+ visdump(dp, datalen, screenwidth);
+}
+
+void
+ktrpsig(struct ktr_psig *psig)
+{
+ const char *str;
+
+ print_signal(psig->signo);
+ if (psig->action == SIG_DFL) {
+ printf(" SIG_DFL");
+ } else {
+ printf(" caught handler=0x%lx mask=0x%x",
+ (u_long)psig->action, psig->mask.__bits[0]);
+ }
+ printf(" code=");
+ str = sysdecode_sigcode(psig->signo, psig->code);
+ if (str != NULL)
+ printf("%s", str);
+ else
+ printf("<invalid=%#x>", psig->code);
+ putchar('\n');
+}
+
+void
+ktrcsw_old(struct ktr_csw_old *cs)
+{
+ printf("%s %s\n", cs->out ? "stop" : "resume",
+ cs->user ? "user" : "kernel");
+}
+
+void
+ktrcsw(struct ktr_csw *cs)
+{
+ printf("%s %s \"%s\"\n", cs->out ? "stop" : "resume",
+ cs->user ? "user" : "kernel", cs->wmesg);
+}
+
+void
+ktruser(int len, void *p)
+{
+ unsigned char *cp;
+
+ if (sysdecode_utrace(stdout, p, len)) {
+ printf("\n");
+ return;
+ }
+
+ printf("%d ", len);
+ cp = p;
+ while (len--)
+ if (decimal)
+ printf(" %d", *cp++);
+ else
+ printf(" %02x", *cp++);
+ printf("\n");
+}
+
+void
+ktrcaprights(cap_rights_t *rightsp)
+{
+
+ printf("cap_rights_t ");
+ sysdecode_cap_rights(stdout, rightsp);
+ printf("\n");
+}
+
+static void
+ktrtimeval(struct timeval *tv)
+{
+
+ printf("{%ld, %ld}", (long)tv->tv_sec, tv->tv_usec);
+}
+
+void
+ktritimerval(struct itimerval *it)
+{
+
+ printf("itimerval { .interval = ");
+ ktrtimeval(&it->it_interval);
+ printf(", .value = ");
+ ktrtimeval(&it->it_value);
+ printf(" }\n");
+}
+
+void
+ktrsockaddr(struct sockaddr *sa)
+{
+/*
+ TODO: Support additional address families
+ #include <netsmb/netbios.h>
+ struct sockaddr_nb *nb;
+*/
+ const char *str;
+ char addr[64];
+
+ /*
+ * note: ktrstruct() has already verified that sa points to a
+ * buffer at least sizeof(struct sockaddr) bytes long and exactly
+ * sa->sa_len bytes long.
+ */
+ printf("struct sockaddr { ");
+ str = sysdecode_sockaddr_family(sa->sa_family);
+ if (str != NULL)
+ printf("%s", str);
+ else
+ printf("<invalid=%d>", sa->sa_family);
+ printf(", ");
+
+#define check_sockaddr_len(n) \
+ if (sa_##n.s##n##_len < sizeof(struct sockaddr_##n)) { \
+ printf("invalid"); \
+ break; \
+ }
+
+ switch(sa->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in sa_in;
+
+ memset(&sa_in, 0, sizeof(sa_in));
+ memcpy(&sa_in, sa, sa->sa_len);
+ check_sockaddr_len(in);
+ inet_ntop(AF_INET, &sa_in.sin_addr, addr, sizeof addr);
+ printf("%s:%u", addr, ntohs(sa_in.sin_port));
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 sa_in6;
+
+ memset(&sa_in6, 0, sizeof(sa_in6));
+ memcpy(&sa_in6, sa, sa->sa_len);
+ check_sockaddr_len(in6);
+ getnameinfo((struct sockaddr *)&sa_in6, sizeof(sa_in6),
+ addr, sizeof(addr), NULL, 0, NI_NUMERICHOST);
+ printf("[%s]:%u", addr, htons(sa_in6.sin6_port));
+ break;
+ }
+ case AF_UNIX: {
+ struct sockaddr_un sa_un;
+
+ memset(&sa_un, 0, sizeof(sa_un));
+ memcpy(&sa_un, sa, sa->sa_len);
+ printf("%.*s", (int)sizeof(sa_un.sun_path), sa_un.sun_path);
+ break;
+ }
+ case AF_NETLINK: {
+ struct sockaddr_nl sa_nl;
+
+ memset(&sa_nl, 0, sizeof(sa_nl));
+ memcpy(&sa_nl, sa, sa->sa_len);
+ printf("netlink[pid=%u, groups=0x%x]",
+ sa_nl.nl_pid, sa_nl.nl_groups);
+ break;
+ }
+ default:
+ printf("unknown address family");
+ }
+ printf(" }\n");
+}
+
+void
+ktrsplice(struct splice *sp)
+{
+ printf("struct splice { fd=%d, max=%#jx, idle=%jd.%06jd }\n",
+ sp->sp_fd, (uintmax_t)sp->sp_max, (intmax_t)sp->sp_idle.tv_sec,
+ (intmax_t)sp->sp_idle.tv_usec);
+}
+
+void
+ktrstat(struct stat *statp)
+{
+ char mode[12], timestr[PATH_MAX + 4];
+ struct passwd *pwd;
+ struct group *grp;
+ struct tm *tm;
+
+ /*
+ * note: ktrstruct() has already verified that statp points to a
+ * buffer exactly sizeof(struct stat) bytes long.
+ */
+ printf("struct stat {");
+ printf("dev=%ju, ino=%ju, ",
+ (uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino);
+ if (!resolv)
+ printf("mode=0%jo, ", (uintmax_t)statp->st_mode);
+ else {
+ strmode(statp->st_mode, mode);
+ printf("mode=%s, ", mode);
+ }
+ printf("nlink=%ju, ", (uintmax_t)statp->st_nlink);
+ if (!resolv) {
+ pwd = NULL;
+ } else {
+#ifdef WITH_CASPER
+ if (cappwd != NULL)
+ pwd = cap_getpwuid(cappwd, statp->st_uid);
+ else
+#endif
+ pwd = getpwuid(statp->st_uid);
+ }
+ if (pwd == NULL)
+ printf("uid=%ju, ", (uintmax_t)statp->st_uid);
+ else
+ printf("uid=\"%s\", ", pwd->pw_name);
+ if (!resolv) {
+ grp = NULL;
+ } else {
+#ifdef WITH_CASPER
+ if (capgrp != NULL)
+ grp = cap_getgrgid(capgrp, statp->st_gid);
+ else
+#endif
+ grp = getgrgid(statp->st_gid);
+ }
+ if (grp == NULL)
+ printf("gid=%ju, ", (uintmax_t)statp->st_gid);
+ else
+ printf("gid=\"%s\", ", grp->gr_name);
+ printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
+ printf("atime=");
+ if (!resolv)
+ printf("%jd", (intmax_t)statp->st_atim.tv_sec);
+ else {
+ tm = localtime(&statp->st_atim.tv_sec);
+ strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
+ printf("\"%s\"", timestr);
+ }
+ if (statp->st_atim.tv_nsec != 0)
+ printf(".%09ld, ", statp->st_atim.tv_nsec);
+ else
+ printf(", ");
+ printf("mtime=");
+ if (!resolv)
+ printf("%jd", (intmax_t)statp->st_mtim.tv_sec);
+ else {
+ tm = localtime(&statp->st_mtim.tv_sec);
+ strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
+ printf("\"%s\"", timestr);
+ }
+ if (statp->st_mtim.tv_nsec != 0)
+ printf(".%09ld, ", statp->st_mtim.tv_nsec);
+ else
+ printf(", ");
+ printf("ctime=");
+ if (!resolv)
+ printf("%jd", (intmax_t)statp->st_ctim.tv_sec);
+ else {
+ tm = localtime(&statp->st_ctim.tv_sec);
+ strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
+ printf("\"%s\"", timestr);
+ }
+ if (statp->st_ctim.tv_nsec != 0)
+ printf(".%09ld, ", statp->st_ctim.tv_nsec);
+ else
+ printf(", ");
+ printf("birthtime=");
+ if (!resolv)
+ printf("%jd", (intmax_t)statp->st_birthtim.tv_sec);
+ else {
+ tm = localtime(&statp->st_birthtim.tv_sec);
+ strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
+ printf("\"%s\"", timestr);
+ }
+ if (statp->st_birthtim.tv_nsec != 0)
+ printf(".%09ld, ", statp->st_birthtim.tv_nsec);
+ else
+ printf(", ");
+ printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
+ (uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
+ (intmax_t)statp->st_blocks, statp->st_flags);
+ printf(" }\n");
+}
+
+void
+ktrbitset(char *name, struct bitset *set, size_t setlen)
+{
+ int i, maxi, c = 0;
+
+ if (setlen > INT32_MAX)
+ setlen = INT32_MAX;
+ maxi = setlen * CHAR_BIT;
+ printf("%s [ ", name);
+ for (i = 0; i < maxi; i++) {
+ if (!BIT_ISSET(setlen, i, set))
+ continue;
+ if (c == 0)
+ printf("%d", i);
+ else
+ printf(", %d", i);
+ c++;
+ }
+ if (c == 0)
+ printf(" empty ]\n");
+ else
+ printf(" ]\n");
+}
+
+void
+ktrstruct(char *buf, size_t buflen)
+{
+ char *name, *data;
+ size_t namelen, datalen;
+ int i;
+ cap_rights_t rights;
+ struct itimerval it;
+ struct stat sb;
+ struct sockaddr_storage ss;
+ struct bitset *set;
+
+ for (name = buf, namelen = 0;
+ namelen < buflen && name[namelen] != '\0';
+ ++namelen)
+ /* nothing */;
+ if (namelen == buflen)
+ goto invalid;
+ if (name[namelen] != '\0')
+ goto invalid;
+ data = buf + namelen + 1;
+ datalen = buflen - namelen - 1;
+ if (datalen == 0)
+ goto invalid;
+ /* sanity check */
+ for (i = 0; i < (int)namelen; ++i)
+ if (!isalpha(name[i]) && name[i] != '_')
+ goto invalid;
+ if (strcmp(name, "caprights") == 0) {
+ if (datalen != sizeof(cap_rights_t))
+ goto invalid;
+ memcpy(&rights, data, datalen);
+ ktrcaprights(&rights);
+ } else if (strcmp(name, "itimerval") == 0) {
+ if (datalen != sizeof(struct itimerval))
+ goto invalid;
+ memcpy(&it, data, datalen);
+ ktritimerval(&it);
+ } else if (strcmp(name, "stat") == 0) {
+ if (datalen != sizeof(struct stat))
+ goto invalid;
+ memcpy(&sb, data, datalen);
+ ktrstat(&sb);
+ } else if (strcmp(name, "sockaddr") == 0) {
+ if (datalen > sizeof(ss))
+ goto invalid;
+ memcpy(&ss, data, datalen);
+ if (datalen != ss.ss_len)
+ goto invalid;
+ ktrsockaddr((struct sockaddr *)&ss);
+ } else if (strcmp(name, "cpuset_t") == 0) {
+ if (datalen < 1)
+ goto invalid;
+ set = malloc(datalen);
+ if (set == NULL)
+ errx(1, "%s", strerror(ENOMEM));
+ memcpy(set, data, datalen);
+ ktrbitset(name, set, datalen);
+ free(set);
+ } else if (strcmp(name, "splice") == 0) {
+ struct splice sp;
+
+ if (datalen != sizeof(sp))
+ goto invalid;
+ memcpy(&sp, data, datalen);
+ ktrsplice(&sp);
+ } else {
+#ifdef SYSDECODE_HAVE_LINUX
+ if (ktrstruct_linux(name, data, datalen) == false)
+#endif
+ printf("unknown structure\n");
+ }
+ return;
+invalid:
+ printf("invalid record\n");
+}
+
+void
+ktrcapfail(struct ktr_cap_fail *ktr)
+{
+ union ktr_cap_data *kcd = &ktr->cap_data;
+
+ switch (ktr->cap_type) {
+ case CAPFAIL_NOTCAPABLE:
+ /* operation on fd with insufficient capabilities */
+ printf("operation requires ");
+ sysdecode_cap_rights(stdout, &kcd->cap_needed);
+ printf(", descriptor holds ");
+ sysdecode_cap_rights(stdout, &kcd->cap_held);
+ break;
+ case CAPFAIL_INCREASE:
+ /* requested more capabilities than fd already has */
+ printf("attempt to increase capabilities from ");
+ sysdecode_cap_rights(stdout, &kcd->cap_held);
+ printf(" to ");
+ sysdecode_cap_rights(stdout, &kcd->cap_needed);
+ break;
+ case CAPFAIL_SYSCALL:
+ /* called restricted syscall */
+ printf("system call not allowed: ");
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ if (syscallabi(ktr->cap_svflags) == SYSDECODE_ABI_FREEBSD) {
+ switch (ktr->cap_code) {
+ case SYS_sysarch:
+ printf(", op: ");
+ print_integer_arg(sysdecode_sysarch_number,
+ kcd->cap_int);
+ break;
+ case SYS_fcntl:
+ printf(", cmd: ");
+ print_integer_arg(sysdecode_fcntl_cmd,
+ kcd->cap_int);
+ break;
+ }
+ }
+ break;
+ case CAPFAIL_SIGNAL:
+ /* sent signal to proc other than self */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": signal delivery not allowed: ");
+ print_integer_arg(sysdecode_signal, kcd->cap_int);
+ break;
+ case CAPFAIL_PROTO:
+ /* created socket with restricted protocol */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": protocol not allowed: ");
+ print_integer_arg(sysdecode_ipproto, kcd->cap_int);
+ break;
+ case CAPFAIL_SOCKADDR:
+ /* unable to look up address */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted address lookup: ");
+ ktrsockaddr(&kcd->cap_sockaddr);
+ return;
+ case CAPFAIL_NAMEI:
+ /* absolute or AT_FDCWD path, ".." path, etc. */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted VFS lookup: %s\n", kcd->cap_path);
+ return;
+ case CAPFAIL_CPUSET:
+ /* modification of an external cpuset */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted cpuset operation\n");
+ return;
+ default:
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": unknown capability failure\n");
+ return;
+ }
+ printf("\n");
+}
+
+void
+ktrfault(struct ktr_fault *ktr)
+{
+
+ printf("0x%jx ", (uintmax_t)ktr->vaddr);
+ print_mask_arg(sysdecode_vmprot, ktr->type);
+ printf("\n");
+}
+
+void
+ktrfaultend(struct ktr_faultend *ktr)
+{
+ const char *str;
+
+ str = sysdecode_vmresult(ktr->result);
+ if (str != NULL)
+ printf("%s", str);
+ else
+ printf("<invalid=%d>", ktr->result);
+ printf("\n");
+}
+
+void
+ktrkevent(struct kevent *kev)
+{
+
+ printf("{ ident=");
+ switch (kev->filter) {
+ case EVFILT_READ:
+ case EVFILT_WRITE:
+ case EVFILT_VNODE:
+ case EVFILT_PROC:
+ case EVFILT_TIMER:
+ case EVFILT_PROCDESC:
+ case EVFILT_EMPTY:
+ printf("%ju", (uintmax_t)kev->ident);
+ break;
+ case EVFILT_SIGNAL:
+ print_signal(kev->ident);
+ break;
+ default:
+ printf("%p", (void *)kev->ident);
+ }
+ printf(", filter=");
+ print_integer_arg(sysdecode_kevent_filter, kev->filter);
+ printf(", flags=");
+ print_mask_arg0(sysdecode_kevent_flags, kev->flags);
+ printf(", fflags=");
+ sysdecode_kevent_fflags(stdout, kev->filter, kev->fflags,
+ decimal ? 10 : 16);
+ printf(", data=%#jx, udata=%p }", (uintmax_t)kev->data, kev->udata);
+}
+
+void
+ktrpollfd(struct pollfd *pfd)
+{
+
+ printf("{ fd=%d", pfd->fd);
+ printf(", events=");
+ print_mask_arg0(sysdecode_pollfd_events, pfd->events);
+ printf(", revents=");
+ print_mask_arg0(sysdecode_pollfd_events, pfd->revents);
+ printf("}");
+}
+
+void
+ktrstructarray(struct ktr_struct_array *ksa, size_t buflen)
+{
+ struct kevent kev;
+ struct pollfd pfd;
+ char *name, *data;
+ size_t namelen, datalen;
+ int i;
+ bool first;
+
+ buflen -= sizeof(*ksa);
+ for (name = (char *)(ksa + 1), namelen = 0;
+ namelen < buflen && name[namelen] != '\0';
+ ++namelen)
+ /* nothing */;
+ if (namelen == buflen)
+ goto invalid;
+ if (name[namelen] != '\0')
+ goto invalid;
+ /* sanity check */
+ for (i = 0; i < (int)namelen; ++i)
+ if (!isalnum(name[i]) && name[i] != '_')
+ goto invalid;
+ data = name + namelen + 1;
+ datalen = buflen - namelen - 1;
+ printf("struct %s[] = { ", name);
+ first = true;
+ for (; datalen >= ksa->struct_size;
+ data += ksa->struct_size, datalen -= ksa->struct_size) {
+ if (!first)
+ printf("\n ");
+ else
+ first = false;
+ if (strcmp(name, "kevent") == 0) {
+ if (ksa->struct_size != sizeof(kev))
+ goto bad_size;
+ memcpy(&kev, data, sizeof(kev));
+ ktrkevent(&kev);
+ } else if (strcmp(name, "freebsd11_kevent") == 0) {
+ struct freebsd11_kevent kev11;
+
+ if (ksa->struct_size != sizeof(kev11))
+ goto bad_size;
+ memcpy(&kev11, data, sizeof(kev11));
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = kev11.ident;
+ kev.filter = kev11.filter;
+ kev.flags = kev11.flags;
+ kev.fflags = kev11.fflags;
+ kev.data = kev11.data;
+ kev.udata = kev11.udata;
+ ktrkevent(&kev);
+#ifdef _WANT_KEVENT32
+ } else if (strcmp(name, "kevent32") == 0) {
+ struct kevent32 kev32;
+
+ if (ksa->struct_size != sizeof(kev32))
+ goto bad_size;
+ memcpy(&kev32, data, sizeof(kev32));
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = kev32.ident;
+ kev.filter = kev32.filter;
+ kev.flags = kev32.flags;
+ kev.fflags = kev32.fflags;
+#if BYTE_ORDER == BIG_ENDIAN
+ kev.data = kev32.data2 | ((int64_t)kev32.data1 << 32);
+#else
+ kev.data = kev32.data1 | ((int64_t)kev32.data2 << 32);
+#endif
+ kev.udata = (void *)(uintptr_t)kev32.udata;
+ ktrkevent(&kev);
+ } else if (strcmp(name, "freebsd11_kevent32") == 0) {
+ struct freebsd11_kevent32 kev32;
+
+ if (ksa->struct_size != sizeof(kev32))
+ goto bad_size;
+ memcpy(&kev32, data, sizeof(kev32));
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = kev32.ident;
+ kev.filter = kev32.filter;
+ kev.flags = kev32.flags;
+ kev.fflags = kev32.fflags;
+ kev.data = kev32.data;
+ kev.udata = (void *)(uintptr_t)kev32.udata;
+ ktrkevent(&kev);
+#endif
+ } else if (strcmp(name, "pollfd") == 0) {
+ if (ksa->struct_size != sizeof(pfd))
+ goto bad_size;
+ memcpy(&pfd, data, sizeof(pfd));
+ ktrpollfd(&pfd);
+ } else {
+ printf("<unknown structure> }\n");
+ return;
+ }
+ }
+ printf(" }\n");
+ return;
+invalid:
+ printf("invalid record\n");
+ return;
+bad_size:
+ printf("<bad size> }\n");
+ return;
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: kdump [-dEnlHRrSsTA] [-f trfile] "
+ "[-m maxdata] [-p pid] [-t trstr]\n");
+ exit(1);
+}
diff --git a/usr.bin/kdump/kdump.h b/usr.bin/kdump/kdump.h
new file mode 100644
index 000000000000..1d3e9be2b6e0
--- /dev/null
+++ b/usr.bin/kdump/kdump.h
@@ -0,0 +1,95 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#ifndef __KDUMP_H__
+#define __KDUMP_H__
+
+extern bool decimal, fancy, resolv;
+
+#define _print_number64(first,i,n,c,d) do { \
+ uint64_t __v; \
+ \
+ if (quad_align && (((ptrdiff_t)((i) - (first))) & 1) == 1) { \
+ (i)++; \
+ (n)--; \
+ } \
+ if (quad_slots == 2) \
+ __v = (uint64_t)(uint32_t)(i)[0] | \
+ ((uint64_t)(uint32_t)(i)[1]) << 32; \
+ else \
+ __v = (uint64_t)*(i); \
+ if (d) \
+ printf("%c%jd", (c), (intmax_t)__v); \
+ else \
+ printf("%c%#jx", (c), (uintmax_t)__v); \
+ (i) += quad_slots; \
+ (n) -= quad_slots; \
+ (c) = ','; \
+} while (0)
+
+#define _print_number(i,n,c,d) do { \
+ if (d) \
+ printf("%c%jd", c, (intmax_t)*i); \
+ else \
+ printf("%c%#jx", c, (uintmax_t)(u_register_t)*i); \
+ i++; \
+ n--; \
+ c = ','; \
+} while (0)
+
+#define print_number(i,n,c) _print_number(i,n,c,decimal)
+#define print_decimal_number(i,n,c) _print_number(i,n,c,true)
+#define print_number64(first,i,n,c) _print_number64(first,i,n,c,decimal)
+#define print_decimal_number64(first,i,n,c) _print_number64(first,i,n,c,true)
+
+void decode_filemode(int value);
+void print_integer_arg(const char *(*decoder)(int), int value);
+void print_integer_arg_valid(const char *(*decoder)(int), int value);
+void print_mask_arg(bool (*decoder)(FILE *, int, int *), int value);
+void print_mask_arg0(bool (*decoder)(FILE *, int, int *), int value);
+void print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *),
+ uint32_t value);
+void print_mask_argul(bool (*decoder)(FILE *, u_long, u_long *),
+ u_long value);
+bool print_mask_arg_part(bool (*decoder)(FILE *, int, int *),
+ int value, int *rem);
+
+#ifdef SYSDECODE_HAVE_LINUX
+bool ktrstruct_linux(const char *name, const char *data, size_t datalen);
+void ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc);
+#ifdef __amd64__
+void ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc);
+#endif
+#endif /* SYSDECODE_HAVE_LINUX */
+
+#endif /* !__KDUMP_H__ */
diff --git a/usr.bin/kdump/linux.c b/usr.bin/kdump/linux.c
new file mode 100644
index 000000000000..a52fbb2ba498
--- /dev/null
+++ b/usr.bin/kdump/linux.c
@@ -0,0 +1,525 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#include <err.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdecode.h>
+
+#include "kdump.h"
+
+#ifdef __amd64__
+#include <amd64/linux/linux.h>
+#include <amd64/linux32/linux32_syscall.h>
+#elif __aarch64__
+#include <arm64/linux/linux.h>
+#elif __i386__
+#include <i386/linux/linux.h>
+#endif
+
+#include <compat/linux/linux.h>
+#include <compat/linux/linux_file.h>
+
+static void
+print_linux_signal(int signo)
+{
+ const char *signame;
+
+ signame = sysdecode_linux_signal(signo);
+ if (signame != NULL)
+ printf("%s", signame);
+ else
+ printf("SIG %d", signo);
+}
+
+void
+ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip, *first;
+ int quad_align, quad_slots;
+ char c;
+
+ ip = first = &ktr->ktr_args[0];
+ c = *resc;
+ quad_align = 0;
+ quad_slots = 1;
+ switch (ktr->ktr_code) {
+ case LINUX_SYS_linux_faccessat:
+ case LINUX_SYS_linux_fchmodat:
+ case LINUX_SYS_linux_fchownat:
+#ifdef LINUX_SYS_linux_newfstatat
+ case LINUX_SYS_linux_newfstatat:
+#endif
+#ifdef LINUX_SYS_linux_fstatat64
+ case LINUX_SYS_linux_fstatat64:
+#endif
+#ifdef LINUX_SYS_linux_futimesat
+ case LINUX_SYS_linux_futimesat:
+#endif
+ case LINUX_SYS_linux_linkat:
+ case LINUX_SYS_linux_mkdirat:
+ case LINUX_SYS_linux_mknodat:
+ case LINUX_SYS_linux_openat:
+ case LINUX_SYS_linux_readlinkat:
+ case LINUX_SYS_linux_renameat:
+ case LINUX_SYS_linux_unlinkat:
+ case LINUX_SYS_linux_utimensat:
+ putchar('(');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ }
+ switch (ktr->ktr_code) {
+#ifdef LINUX_SYS_linux_access
+ case LINUX_SYS_linux_access:
+#endif
+ case LINUX_SYS_linux_faccessat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_access_mode, *ip);
+ ip++;
+ narg--;
+ break;
+#ifdef LINUX_SYS_linux_chmod
+ case LINUX_SYS_linux_chmod:
+#endif
+ case LINUX_SYS_linux_fchmodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX_SYS_linux_mknodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+#ifdef LINUX_SYS_linux_mkdir
+ case LINUX_SYS_linux_mkdir:
+#endif
+ case LINUX_SYS_linux_mkdirat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX_SYS_linux_linkat:
+ case LINUX_SYS_linux_renameat:
+ case LINUX_SYS_linux_symlinkat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ ip++;
+ narg--;
+ print_number(ip, narg, c);
+ break;
+ case LINUX_SYS_linux_fchownat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+#ifdef LINUX_SYS_linux_newfstatat
+ case LINUX_SYS_linux_newfstatat:
+#endif
+#ifdef LINUX_SYS_linux_fstatat64
+ case LINUX_SYS_linux_fstatat64:
+#endif
+ case LINUX_SYS_linux_utimensat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+ case LINUX_SYS_linux_unlinkat:
+ print_number(ip, narg, c);
+ break;
+ case LINUX_SYS_linux_clock_gettime:
+ case LINUX_SYS_linux_clock_settime:
+ case LINUX_SYS_linux_clock_getres:
+ case LINUX_SYS_linux_timer_create:
+ putchar('(');
+ sysdecode_linux_clockid(stdout, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case LINUX_SYS_linux_clock_nanosleep:
+ putchar('(');
+ sysdecode_linux_clockid(stdout, *ip);
+ putchar(',');
+ ip++;
+ narg--;
+ print_mask_arg0(sysdecode_linux_clock_flags, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case LINUX_SYS_linux_clone:
+ putchar('(');
+ print_mask_arg(sysdecode_linux_clone_flags, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX_SYS_linux_kill:
+ case LINUX_SYS_linux_tkill:
+ case LINUX_SYS_linux_rt_sigqueueinfo:
+ print_decimal_number(ip, narg, c);
+ putchar(',');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX_SYS_linux_tgkill:
+ case LINUX_SYS_linux_rt_tgsigqueueinfo:
+ print_decimal_number(ip, narg, c);
+ print_decimal_number(ip, narg, c);
+ putchar(',');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ break;
+#ifdef LINUX_SYS_linux_open
+ case LINUX_SYS_linux_open:
+#endif
+ case LINUX_SYS_linux_openat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_linux_open_flags, ip[0]);
+ if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
+ putchar(',');
+ decode_filemode(ip[1]);
+ }
+ ip += 2;
+ narg -= 2;
+ break;
+ case LINUX_SYS_linux_rt_sigaction:
+ putchar('(');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX_SYS_linux_ftruncate:
+ case LINUX_SYS_linux_truncate:
+ print_number(ip, narg, c);
+ print_number64(first, ip, narg, c);
+ break;
+ case LINUX_SYS_linux_getitimer:
+ case LINUX_SYS_linux_setitimer:
+ putchar('(');
+ print_integer_arg(sysdecode_itimer, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX_SYS_linux_rt_sigprocmask:
+#ifdef LINUX_SYS_linux_sigprocmask
+ case LINUX_SYS_linux_sigprocmask:
+#endif
+ putchar('(');
+ print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ }
+ switch (ktr->ktr_code) {
+ case LINUX_SYS_linux_fchownat:
+ case LINUX_SYS_linux_faccessat:
+ case LINUX_SYS_linux_fchmodat:
+#ifdef LINUX_SYS_linux_newfstatat
+ case LINUX_SYS_linux_newfstatat:
+#endif
+#ifdef LINUX_SYS_linux_fstatat64
+ case LINUX_SYS_linux_fstatat64:
+#endif
+ case LINUX_SYS_linux_linkat:
+ case LINUX_SYS_linux_unlinkat:
+ case LINUX_SYS_linux_utimensat:
+ putchar(',');
+ print_mask_arg0(sysdecode_linux_atflags, *ip);
+ ip++;
+ narg--;
+ break;
+ }
+ *resc = c;
+ *resip = ip;
+ *resnarg = narg;
+}
+
+#if defined(__amd64__)
+void
+ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
+ int *resnarg, char *resc)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip, *first;
+ int quad_align, quad_slots;
+ char c;
+
+ ip = first = &ktr->ktr_args[0];
+ c = *resc;
+ quad_align = 0;
+ quad_slots = 2;
+ switch (ktr->ktr_code) {
+ case LINUX32_SYS_linux_faccessat:
+ case LINUX32_SYS_linux_fchmodat:
+ case LINUX32_SYS_linux_fchownat:
+ case LINUX32_SYS_linux_fstatat64:
+ case LINUX32_SYS_linux_futimesat:
+ case LINUX32_SYS_linux_linkat:
+ case LINUX32_SYS_linux_mkdirat:
+ case LINUX32_SYS_linux_mknodat:
+ case LINUX32_SYS_linux_openat:
+ case LINUX32_SYS_linux_readlinkat:
+ case LINUX32_SYS_linux_renameat:
+ case LINUX32_SYS_linux_unlinkat:
+ case LINUX32_SYS_linux_utimensat:
+ putchar('(');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ }
+ switch (ktr->ktr_code) {
+ case LINUX32_SYS_linux_access:
+ case LINUX32_SYS_linux_faccessat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_access_mode, *ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_chmod:
+ case LINUX32_SYS_fchmod:
+ case LINUX32_SYS_linux_fchmodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_mknodat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_mkdir:
+ case LINUX32_SYS_linux_mkdirat:
+ print_number(ip, narg, c);
+ putchar(',');
+ decode_filemode(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_linkat:
+ case LINUX32_SYS_linux_renameat:
+ case LINUX32_SYS_linux_symlinkat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_integer_arg_valid(sysdecode_atfd, *ip);
+ ip++;
+ narg--;
+ print_number(ip, narg, c);
+ break;
+ case LINUX32_SYS_linux_fchownat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+ case LINUX32_SYS_linux_fstatat64:
+ case LINUX32_SYS_linux_utimensat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ break;
+ case LINUX32_SYS_linux_unlinkat:
+ print_number(ip, narg, c);
+ break;
+ case LINUX32_SYS_linux_clock_gettime:
+ case LINUX32_SYS_linux_clock_settime:
+ case LINUX32_SYS_linux_clock_getres:
+ case LINUX32_SYS_linux_timer_create:
+ case LINUX32_SYS_linux_clock_gettime64:
+ case LINUX32_SYS_linux_clock_settime64:
+ case LINUX32_SYS_linux_clock_getres_time64:
+ putchar('(');
+ sysdecode_linux_clockid(stdout, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_clock_nanosleep:
+ putchar('(');
+ sysdecode_linux_clockid(stdout, *ip);
+ putchar(',');
+ ip++;
+ narg--;
+ print_mask_arg0(sysdecode_linux_clock_flags, *ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_clone:
+ putchar('(');
+ print_mask_arg(sysdecode_linux_clone_flags, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX32_SYS_linux_kill:
+ case LINUX32_SYS_linux_tkill:
+ case LINUX32_SYS_linux_rt_sigqueueinfo:
+ print_decimal_number(ip, narg, c);
+ putchar(',');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_tgkill:
+ case LINUX32_SYS_linux_rt_tgsigqueueinfo:
+ print_decimal_number(ip, narg, c);
+ print_decimal_number(ip, narg, c);
+ putchar(',');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ break;
+ case LINUX32_SYS_linux_open:
+ case LINUX32_SYS_linux_openat:
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_linux_open_flags, ip[0]);
+ if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
+ putchar(',');
+ decode_filemode(ip[1]);
+ }
+ ip += 2;
+ narg -= 2;
+ break;
+ case LINUX32_SYS_linux_signal:
+ case LINUX32_SYS_linux_sigaction:
+ case LINUX32_SYS_linux_rt_sigaction:
+ putchar('(');
+ print_linux_signal(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX32_SYS_linux_ftruncate:
+ case LINUX32_SYS_linux_truncate:
+ print_number(ip, narg, c);
+ print_number64(first, ip, narg, c);
+ break;
+ case LINUX32_SYS_linux_getitimer:
+ case LINUX32_SYS_linux_setitimer:
+ putchar('(');
+ print_integer_arg(sysdecode_itimer, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case LINUX32_SYS_linux_rt_sigprocmask:
+ case LINUX32_SYS_linux_sigprocmask:
+ putchar('(');
+ print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ }
+ switch (ktr->ktr_code) {
+ case LINUX32_SYS_linux_fchownat:
+ case LINUX32_SYS_linux_faccessat:
+ case LINUX32_SYS_linux_fchmodat:
+ case LINUX32_SYS_linux_fstatat64:
+ case LINUX32_SYS_linux_linkat:
+ case LINUX32_SYS_linux_unlinkat:
+ case LINUX32_SYS_linux_utimensat:
+ putchar(',');
+ print_mask_arg0(sysdecode_linux_atflags, *ip);
+ ip++;
+ narg--;
+ break;
+ }
+ *resc = c;
+ *resip = ip;
+ *resnarg = narg;
+}
+#endif /* __amd64__ */
+
+static void
+ktrsigset(const char *name, const l_sigset_t *mask, size_t sz)
+{
+ unsigned long i, c;
+
+ printf("%s [ ", name);
+ c = 0;
+ for (i = 1; i <= sz * CHAR_BIT; i++) {
+ if (!LINUX_SIGISMEMBER(*mask, i))
+ continue;
+ if (c != 0)
+ printf(", ");
+ printf("%s", sysdecode_linux_signal(i));
+ c++;
+ }
+ if (c == 0)
+ printf("empty ]\n");
+ else
+ printf(" ]\n");
+}
+
+bool
+ktrstruct_linux(const char *name, const char *data, size_t datalen)
+{
+ l_sigset_t mask;
+
+ if (strcmp(name, "l_sigset_t") == 0) {
+ /* Old Linux sigset_t is one word size. */
+ if (datalen < sizeof(int) || datalen > sizeof(l_sigset_t))
+ return (false);
+ memcpy(&mask, data, datalen);
+ ktrsigset(name, &mask, datalen);
+ } else
+ return (false);
+
+ return (true);
+}
diff --git a/usr.bin/killall/Makefile b/usr.bin/killall/Makefile
new file mode 100644
index 000000000000..4088d0a58005
--- /dev/null
+++ b/usr.bin/killall/Makefile
@@ -0,0 +1,4 @@
+PROG= killall
+LIBADD= jail
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/killall/Makefile.depend b/usr.bin/killall/Makefile.depend
new file mode 100644
index 000000000000..2f6b4a414fb5
--- /dev/null
+++ b/usr.bin/killall/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libjail \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/killall/killall.1 b/usr.bin/killall/killall.1
new file mode 100644
index 000000000000..af3a60329245
--- /dev/null
+++ b/usr.bin/killall/killall.1
@@ -0,0 +1,222 @@
+.\" Copyright (C) 1995 by Joerg Wunsch, Dresden
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 June 27, 2020
+.Dt KILLALL 1
+.Os
+.Sh NAME
+.Nm killall
+.Nd kill processes by name
+.Sh SYNOPSIS
+.Nm
+.Op Fl delmsvz
+.Op Fl help
+.Op Fl I
+.Op Fl j Ar jail
+.Op Fl u Ar user
+.Op Fl t Ar tty
+.Op Fl c Ar procname
+.Op Fl Ar SIGNAL
+.Op Ar procname ...
+.Sh DESCRIPTION
+The
+.Nm
+utility kills processes selected by name, as opposed to the selection by PID
+as done by
+.Xr kill 1 .
+By default, it will send a
+.Dv TERM
+signal to all processes with a real UID identical to the
+caller of
+.Nm
+that match the name
+.Ar procname .
+The super-user is allowed to kill any process.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl c Ar procname"
+.It Fl d
+Be more verbose about what will be done, but do not send any signal.
+The total number of user processes and the real user ID is shown.
+A list of the processes that will be sent the signal will be printed, or a
+message indicating that no matching processes have been found.
+.It Fl e
+Use the effective user ID instead of the (default) real user ID for matching
+processes specified with the
+.Fl u
+option.
+.It Fl help
+Give a help on the command usage and exit.
+.It Fl I
+Request confirmation before attempting to signal each
+process.
+.It Fl l
+List the names of the available signals and exit, like in
+.Xr kill 1 .
+.It Fl m
+Match the argument
+.Ar procname
+as a (case sensitive) regular expression against the names
+of processes found.
+CAUTION!
+This is dangerous, a single dot will match any process
+running under the real UID of the caller.
+.It Fl v
+Be verbose about what will be done.
+.It Fl s
+Same as
+.Fl v ,
+but do not send any signal.
+.It Fl Ar SIGNAL
+Send a different signal instead of the default
+.Dv TERM .
+The signal may be specified either as a name
+(with or without a leading
+.Dq Li SIG ) ,
+or numerically.
+.It Fl j Ar jail
+Kill processes in the specified
+.Ar jail .
+.It Fl u Ar user
+Limit potentially matching processes to those belonging to
+the specified
+.Ar user .
+.It Fl t Ar tty
+Limit potentially matching processes to those running on
+the specified
+.Ar tty .
+.It Fl c Ar procname
+Limit potentially matching processes to those matching
+the specified
+.Ar procname .
+.It Fl q
+Suppress error message if no processes are matched.
+.It Fl z
+Do not skip zombies.
+This should not have any effect except to print a few error messages
+if there are zombie processes that match the specified pattern.
+.El
+.Sh ALL PROCESSES
+Sending a signal to all processes with the given UID
+is already supported by
+.Xr kill 1 .
+So use
+.Xr kill 1
+for this job (e.g.\&
+.Dq Li "kill -TERM -1"
+or as root
+.Dq Li "echo kill -TERM -1 | su -m <user>" ) .
+.Sh IMPLEMENTATION NOTES
+This
+.Fx
+implementation of
+.Nm
+has completely different semantics as compared to the traditional
+.Ux
+System V behavior of
+.Nm .
+The latter will kill all processes that the current user is able to
+kill, and is intended to be used by the system shutdown process only.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 if some processes have been found and
+signalled successfully.
+Otherwise, a status of 1 will be
+returned.
+.Sh EXAMPLES
+Send
+.Dv SIGTERM
+to all firefox processes:
+.Bd -literal -offset indent
+killall firefox
+.Ed
+.Pp
+Send
+.Dv SIGTERM
+to firefox processes belonging to
+.Va USER :
+.Bd -literal -offset indent
+killall -u ${USER} firefox
+.Ed
+.Pp
+Stop all firefox processes:
+.Bd -literal -offset indent
+killall -SIGSTOP firefox
+.Ed
+.Pp
+Resume firefox processes:
+.Bd -literal -offset indent
+killall -SIGCONT firefox
+.Ed
+.Pp
+Show what would be done to firefox processes, but do not actually signal them:
+.Bd -literal -offset indent
+killall -s firefox
+.Ed
+.Pp
+Send
+.Dv SIGKILL
+to csh process running inside jail ID 282:
+.Bd -literal -offset indent
+killall -9 -j282 csh
+.Ed
+.Pp
+Send
+.Dv SIGTERM
+to all processes matching provided pattern (like vim and vimdiff):
+.Bd -literal -offset indent
+killall -m 'vim*'
+.Ed
+.Sh DIAGNOSTICS
+Diagnostic messages will only be printed if the
+.Fl d
+flag is used.
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr pkill 1 ,
+.Xr sysctl 3 ,
+.Xr jail 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 2.1 .
+It has been modeled after the
+.Nm
+command as available on other platforms.
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+program was originally written in Perl and was contributed by
+.An Wolfram Schneider ,
+this manual page has been written by
+.An J\(:org Wunsch .
+The current version of
+.Nm
+was rewritten in C by
+.An Peter Wemm
+using
+.Xr sysctl 3 .
diff --git a/usr.bin/killall/killall.c b/usr.bin/killall/killall.c
new file mode 100644
index 000000000000..8f1b4bad80f2
--- /dev/null
+++ b/usr.bin/killall/killall.c
@@ -0,0 +1,437 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
+ * Copyright (c) 2000 Paul Saab <ps@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/jail.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <jail.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <signal.h>
+#include <regex.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <locale.h>
+
+static void __dead2
+usage(void)
+{
+
+ fprintf(stderr, "usage: killall [-delmsqvz] [-help] [-I] [-j jail]\n");
+ fprintf(stderr,
+ " [-u user] [-t tty] [-c cmd] [-SIGNAL] [cmd]...\n");
+ fprintf(stderr, "At least one option or argument to specify processes must be given.\n");
+ exit(1);
+}
+
+
+static void
+printsig(FILE *fp)
+{
+ const char *const * p;
+ int cnt;
+ int offset = 0;
+
+ for (cnt = NSIG, p = sys_signame + 1; --cnt; ++p) {
+ offset += fprintf(fp, "%s ", *p);
+ if (offset >= 75 && cnt > 1) {
+ offset = 0;
+ fprintf(fp, "\n");
+ }
+ }
+ fprintf(fp, "\n");
+}
+
+static void
+nosig(char *name)
+{
+
+ warnx("unknown signal %s; valid signals:", name);
+ printsig(stderr);
+ exit(1);
+}
+
+int
+main(int ac, char **av)
+{
+ char **saved_av;
+ struct kinfo_proc *procs, *newprocs;
+ struct stat sb;
+ struct passwd *pw;
+ regex_t rgx;
+ regmatch_t pmatch;
+ int i, j, ch;
+ char buf[256];
+ char first;
+ char *user = NULL;
+ char *tty = NULL;
+ char *cmd = NULL;
+ int qflag = 0;
+ int vflag = 0;
+ int sflag = 0;
+ int dflag = 0;
+ int eflag = 0;
+ int Iflag = 0;
+ int jflag = 0;
+ int mflag = 0;
+ int zflag = 0;
+ uid_t uid = 0;
+ dev_t tdev = 0;
+ pid_t mypid;
+ char thiscmd[MAXCOMLEN + 1];
+ pid_t thispid;
+ uid_t thisuid;
+ dev_t thistdev;
+ int sig = SIGTERM;
+ const char *const *p;
+ char *ep;
+ int errors = 0;
+ int jid;
+ int mib[4];
+ size_t miblen;
+ int st, nprocs;
+ size_t size;
+ int matched;
+ int killed = 0;
+
+ setlocale(LC_ALL, "");
+
+ av++;
+ ac--;
+
+ while (ac > 0) {
+ if (strcmp(*av, "-l") == 0) {
+ printsig(stdout);
+ exit(0);
+ }
+ if (strcmp(*av, "-help") == 0)
+ usage();
+ if (**av == '-') {
+ ++*av;
+ switch (**av) {
+ case 'j':
+ ++*av;
+ if (**av == '\0') {
+ ++av;
+ --ac;
+ }
+ jflag++;
+ if (*av == NULL)
+ errx(1, "must specify jail");
+ jid = jail_getid(*av);
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
+ if (jail_attach(jid) == -1)
+ err(1, "jail_attach(%d)", jid);
+ break;
+ case 'u':
+ ++*av;
+ if (**av == '\0') {
+ ++av;
+ --ac;
+ }
+ if (*av == NULL)
+ errx(1, "must specify user");
+ user = *av;
+ break;
+ case 't':
+ ++*av;
+ if (**av == '\0') {
+ ++av;
+ --ac;
+ }
+ if (*av == NULL)
+ errx(1, "must specify tty");
+ tty = *av;
+ break;
+ case 'c':
+ ++*av;
+ if (**av == '\0') {
+ ++av;
+ --ac;
+ }
+ if (*av == NULL)
+ errx(1, "must specify procname");
+ cmd = *av;
+ break;
+ case 'q':
+ qflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 's':
+ sflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+ case 'e':
+ eflag++;
+ break;
+ case 'm':
+ mflag++;
+ break;
+ case 'z':
+ zflag++;
+ break;
+ default:
+ saved_av = av;
+ if (isalpha((unsigned char)**av)) {
+ if (strncasecmp(*av, "SIG", 3) == 0)
+ *av += 3;
+ for (sig = NSIG, p = sys_signame + 1;
+ --sig; ++p)
+ if (strcasecmp(*p, *av) == 0) {
+ sig = p - sys_signame;
+ break;
+ }
+ if (!sig) {
+ if (**saved_av == 'I') {
+ av = saved_av;
+ Iflag = 1;
+ break;
+ } else
+ nosig(*av);
+ }
+ } else if (isdigit((unsigned char)**av)) {
+ sig = strtol(*av, &ep, 10);
+ if (!*av || *ep)
+ errx(1, "illegal signal number: %s", *av);
+ if (sig < 0 || sig >= NSIG)
+ nosig(*av);
+ } else
+ nosig(*av);
+ }
+ ++av;
+ --ac;
+ } else {
+ break;
+ }
+ }
+
+ if (user == NULL && tty == NULL && cmd == NULL && !jflag && ac == 0)
+ usage();
+
+ if (tty) {
+ if (strncmp(tty, "/dev/", 5) == 0)
+ snprintf(buf, sizeof(buf), "%s", tty);
+ else if (strncmp(tty, "tty", 3) == 0 ||
+ strncmp(tty, "pts/", 4) == 0)
+ snprintf(buf, sizeof(buf), "/dev/%s", tty);
+ else
+ snprintf(buf, sizeof(buf), "/dev/tty%s", tty);
+ if (stat(buf, &sb) < 0)
+ err(1, "stat(%s)", buf);
+ if (!S_ISCHR(sb.st_mode))
+ errx(1, "%s: not a character device", buf);
+ tdev = sb.st_rdev;
+ if (dflag)
+ printf("ttydev:0x%jx\n", (uintmax_t)tdev);
+ }
+ if (user) {
+ uid = strtol(user, &ep, 10);
+ if (*user == '\0' || *ep != '\0') { /* was it a number? */
+ pw = getpwnam(user);
+ if (pw == NULL)
+ errx(1, "user %s does not exist", user);
+ uid = pw->pw_uid;
+ if (dflag)
+ printf("uid:%d\n", uid);
+ }
+ } else {
+ uid = getuid();
+ if (uid != 0) {
+ pw = getpwuid(uid);
+ if (pw)
+ user = pw->pw_name;
+ if (dflag)
+ printf("uid:%d\n", uid);
+ }
+ }
+ size = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+
+ if (user) {
+ mib[2] = eflag ? KERN_PROC_UID : KERN_PROC_RUID;
+ mib[3] = uid;
+ miblen = 4;
+ } else if (tty) {
+ mib[2] = KERN_PROC_TTY;
+ mib[3] = tdev;
+ miblen = 4;
+ } else {
+ mib[2] = KERN_PROC_PROC;
+ mib[3] = 0;
+ miblen = 3;
+ }
+
+ procs = NULL;
+ st = sysctl(mib, miblen, NULL, &size, NULL, 0);
+ do {
+ size += size / 10;
+ newprocs = realloc(procs, size);
+ if (newprocs == NULL) {
+ free(procs);
+ err(1, "could not reallocate memory");
+ }
+ procs = newprocs;
+ st = sysctl(mib, miblen, procs, &size, NULL, 0);
+ } while (st == -1 && errno == ENOMEM);
+ if (st == -1)
+ err(1, "could not sysctl(KERN_PROC)");
+ if (size % sizeof(struct kinfo_proc) != 0) {
+ fprintf(stderr, "proc size mismatch (%zu total, %zu chunks)\n",
+ size, sizeof(struct kinfo_proc));
+ fprintf(stderr, "userland out of sync with kernel\n");
+ exit(1);
+ }
+ nprocs = size / sizeof(struct kinfo_proc);
+ if (dflag)
+ printf("nprocs %d\n", nprocs);
+ mypid = getpid();
+
+ for (i = 0; i < nprocs; i++) {
+ if (procs[i].ki_stat == SZOMB && !zflag)
+ continue;
+ thispid = procs[i].ki_pid;
+ strlcpy(thiscmd, procs[i].ki_comm, sizeof(thiscmd));
+ thistdev = procs[i].ki_tdev;
+ if (eflag)
+ thisuid = procs[i].ki_uid; /* effective uid */
+ else
+ thisuid = procs[i].ki_ruid; /* real uid */
+
+ if (thispid == mypid)
+ continue;
+ matched = 1;
+ if (user) {
+ if (thisuid != uid)
+ matched = 0;
+ }
+ if (tty) {
+ if (thistdev != tdev)
+ matched = 0;
+ }
+ if (cmd) {
+ if (mflag) {
+ if (regcomp(&rgx, cmd,
+ REG_EXTENDED|REG_NOSUB) != 0) {
+ mflag = 0;
+ warnx("%s: illegal regexp", cmd);
+ }
+ }
+ if (mflag) {
+ pmatch.rm_so = 0;
+ pmatch.rm_eo = strlen(thiscmd);
+ if (regexec(&rgx, thiscmd, 0, &pmatch,
+ REG_STARTEND) != 0)
+ matched = 0;
+ regfree(&rgx);
+ } else {
+ if (strncmp(thiscmd, cmd, MAXCOMLEN) != 0)
+ matched = 0;
+ }
+ }
+ if (jflag && thispid == getpid())
+ matched = 0;
+ if (matched == 0)
+ continue;
+ if (ac > 0)
+ matched = 0;
+ for (j = 0; j < ac; j++) {
+ if (mflag) {
+ if (regcomp(&rgx, av[j],
+ REG_EXTENDED|REG_NOSUB) != 0) {
+ mflag = 0;
+ warnx("%s: illegal regexp", av[j]);
+ }
+ }
+ if (mflag) {
+ pmatch.rm_so = 0;
+ pmatch.rm_eo = strlen(thiscmd);
+ if (regexec(&rgx, thiscmd, 0, &pmatch,
+ REG_STARTEND) == 0)
+ matched = 1;
+ regfree(&rgx);
+ } else {
+ if (strcmp(thiscmd, av[j]) == 0)
+ matched = 1;
+ }
+ if (matched)
+ break;
+ }
+ if (matched != 0 && Iflag) {
+ printf("Send signal %d to %s (pid %d uid %d)? ",
+ sig, thiscmd, thispid, thisuid);
+ fflush(stdout);
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first != 'y' && first != 'Y')
+ matched = 0;
+ }
+ if (matched == 0)
+ continue;
+ if (dflag)
+ printf("sig:%d, cmd:%s, pid:%d, dev:0x%jx uid:%d\n",
+ sig, thiscmd, thispid, (uintmax_t)thistdev,
+ thisuid);
+
+ if (vflag || sflag)
+ printf("kill -%s %d\n", sys_signame[sig], thispid);
+
+ killed++;
+ if (!dflag && !sflag) {
+ if (kill(thispid, sig) < 0 /* && errno != ESRCH */ ) {
+ warn("warning: kill -%s %d",
+ sys_signame[sig], thispid);
+ errors = 1;
+ }
+ }
+ }
+ if (killed == 0) {
+ if (!qflag)
+ fprintf(stderr, "No matching processes %swere found\n",
+ getuid() != 0 ? "belonging to you " : "");
+ errors = 1;
+ }
+ exit(errors);
+}
diff --git a/usr.bin/ktrace/Makefile b/usr.bin/ktrace/Makefile
new file mode 100644
index 000000000000..6c1f454725c2
--- /dev/null
+++ b/usr.bin/ktrace/Makefile
@@ -0,0 +1,5 @@
+PROG= ktrace
+SRCS= ktrace.c subr.c
+MLINKS= ktrace.1 trace.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ktrace/Makefile.depend b/usr.bin/ktrace/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/ktrace/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1
new file mode 100644
index 000000000000..c2f046dc5287
--- /dev/null
+++ b/usr.bin/ktrace/ktrace.1
@@ -0,0 +1,229 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd November 17, 2024
+.Dt KTRACE 1
+.Os
+.Sh NAME
+.Nm ktrace
+.Nd enable kernel process tracing
+.Sh SYNOPSIS
+.Nm
+.Op Fl aCcdi
+.Op Fl f Ar trfile
+.Op Fl g Ar pgrp | Fl p Ar pid
+.Op Fl t Ar trstr
+.Nm
+.Op Fl adi
+.Op Fl f Ar trfile
+.Op Fl t Ar trstr
+.Ar command
+.Sh DESCRIPTION
+The
+.Nm
+utility enables kernel trace logging for the specified processes.
+Kernel trace data is logged to the file
+.Pa ktrace.out .
+The kernel operations that are traced include system calls
+.Pq see Xr intro 2 ,
+file system path lookups
+.Pq Xr namei 9 ,
+signal processing
+.Pq Xr sigaction 2 ,
+and
+.Tn I/O .
+.Pp
+Once tracing is enabled on a process, trace data will be logged until
+either the process exits or the trace point is cleared.
+A traced process can generate enormous amounts of log data quickly;
+It is strongly suggested that users memorize how to disable tracing before
+attempting to trace a process.
+The following command is sufficient to disable tracing on all user-owned
+processes, and, if executed by root, all processes:
+.Pp
+.Dl \&$ ktrace -C
+.Pp
+The trace file is not human readable; use
+.Xr kdump 1
+to decode it.
+.Pp
+The utility may be used only with a kernel that has been built with the
+.Dq KTRACE
+option in the kernel configuration file.
+.Pp
+The options are:
+.Bl -tag -width indent
+.It Fl a
+Append to the trace file instead of recreating it.
+.It Fl C
+Disable tracing on all user-owned processes, and, if executed by root, all
+processes in the system.
+.It Fl c
+Clear the specified trace points associated with the given file or processes.
+.It Fl d
+Descendants; perform the operation for all current children of the
+designated processes.
+See also the
+.Fl i
+option.
+.It Fl f Ar trfile
+Log trace records to
+.Ar trfile
+instead of
+.Pa ktrace.out .
+.It Fl g Ar pgid
+Enable (disable) tracing on all processes in the process group (only one
+.Fl g
+flag is permitted).
+.It Fl i
+Inherit; pass the trace flags to all future children of the designated
+processes.
+See also the
+.Fl d
+option.
+.It Fl p Ar pid
+Enable (disable) tracing on the indicated process id (only one
+.Fl p
+flag is permitted).
+.It Fl t Ar trstr
+Specify the list of trace points to enable or disable, one per letter.
+If an explicit list is not specified, the default set of trace points is used.
+.Pp
+The following trace points are supported:
+.Pp
+.Bl -tag -width flag -compact
+.It Cm c
+trace system calls
+.It Cm f
+trace page faults
+.It Cm i
+trace
+.Tn I/O
+.It Cm n
+trace
+.Xr namei 9
+translations
+.It Cm p
+trace capability check failures
+.It Cm s
+trace signal processing
+.It Cm t
+trace various structures and arrays of structures
+.It Cm u
+userland traces generated by
+.Xr utrace 2
+.It Cm w
+context switches
+.It Cm y
+trace
+.Xr sysctl 3
+requests
+.It Cm a
+trace
+.Xr execve 2
+arguments
+.It Cm e
+trace
+.Xr execve 2
+environment variables
+.It Cm +
+trace the default set of trace points -
+.Cm a, c , e, i , n , s , t , u , y
+.El
+.It Ar command
+Execute
+.Ar command
+with the specified trace flags.
+.El
+.Pp
+The
+.Fl p ,
+.Fl g ,
+and
+.Ar command
+options are mutually exclusive.
+.Sh CAPABILITY VIOLATION TRACING
+When the
+.Cm p
+trace point is specified,
+.Nm
+will record
+.Xr capsicum 4
+capability mode violations made by the traced process.
+Violations will be logged regardless of whether the process has actually
+entered capability mode.
+.Pp
+For developers that are interested in Capsicumizing their programs, the
+.Cm c , n , p
+trace points can help quickly identify any system calls and path lookups that
+are triggering violations.
+.Sh EXAMPLES
+Run "make", then trace it and any child processes:
+.Dl $ ktrace -i make
+.Pp
+Trace all kernel operations of process id 34:
+.Dl $ ktrace -p 34
+.Pp
+Trace all kernel operations of processes in process group 15 and
+pass the trace flags to all current and future children:
+.Dl $ ktrace -idg 15
+.Pp
+Disable all tracing of process 65:
+.Dl $ ktrace -cp 65
+.Pp
+Disable tracing signals on process 70 and all current children:
+.Dl $ ktrace -t s -cdp 70
+.Pp
+Enable tracing of
+.Tn I/O
+on process 67:
+.Dl $ ktrace -ti -p 67
+.Pp
+Disable all tracing to the file "tracedata":
+.Dl $ ktrace -c -f tracedata
+.Pp
+Disable tracing of all user-owned processes:
+.Dl $ ktrace -C
+.Sh SEE ALSO
+.Xr dtrace 1 ,
+.Xr kdump 1 ,
+.Xr truss 1 ,
+.Xr intro 2 ,
+.Xr ktrace 2 ,
+.Xr sigaction 2 ,
+.Xr utrace 2 ,
+.Xr capsicum 4 ,
+.Xr namei 9
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
+.Sh BUGS
+Only works if
+.Ar trfile
+is a regular file.
diff --git a/usr.bin/ktrace/ktrace.c b/usr.bin/ktrace/ktrace.c
new file mode 100644
index 000000000000..fcc50fd7f9ca
--- /dev/null
+++ b/usr.bin/ktrace/ktrace.c
@@ -0,0 +1,227 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ktrace.h"
+
+static char def_tracefile[] = DEF_TRACEFILE;
+
+static enum clear { NOTSET, CLEAR, CLEARALL } clear = NOTSET;
+static int pid;
+
+static void no_ktrace(int);
+static void set_pid_clear(const char *, enum clear);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int append, ch, fd, inherit, ops, trpoints;
+ const char *tracefile;
+ mode_t omask;
+ struct stat sb;
+
+ append = ops = inherit = 0;
+ trpoints = DEF_POINTS;
+ tracefile = def_tracefile;
+ while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != -1)
+ switch((char)ch) {
+ case 'a':
+ append = 1;
+ break;
+ case 'C':
+ set_pid_clear("1", CLEARALL);
+ break;
+ case 'c':
+ set_pid_clear(NULL, CLEAR);
+ break;
+ case 'd':
+ ops |= KTRFLAG_DESCEND;
+ break;
+ case 'f':
+ tracefile = optarg;
+ break;
+ case 'g':
+ set_pid_clear(optarg, NOTSET);
+ pid = -pid;
+ break;
+ case 'i':
+ inherit = 1;
+ break;
+ case 'p':
+ set_pid_clear(optarg, NOTSET);
+ break;
+ case 't':
+ trpoints = getpoints(optarg);
+ if (trpoints < 0) {
+ warnx("unknown facility in %s", optarg);
+ usage();
+ }
+ break;
+ default:
+ usage();
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ /* must have either -[Cc], a pid or a command */
+ if (clear == NOTSET && pid == 0 && argc == 0)
+ usage();
+ /* can't have both a pid and a command */
+ /* (note that -C sets pid to 1) */
+ if (pid != 0 && argc > 0) {
+ usage();
+ }
+
+ if (inherit)
+ trpoints |= KTRFAC_INHERIT;
+
+ (void)signal(SIGSYS, no_ktrace);
+ if (clear != NOTSET) {
+ if (clear == CLEARALL) {
+ ops = KTROP_CLEAR | KTRFLAG_DESCEND;
+ trpoints = ALL_POINTS;
+ } else {
+ ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE;
+ }
+ if (ktrace(tracefile, ops, trpoints, pid) < 0)
+ err(1, "%s", tracefile);
+ exit(0);
+ }
+
+ omask = umask(S_IRWXG|S_IRWXO);
+ if (append) {
+ if ((fd = open(tracefile, O_CREAT | O_WRONLY | O_NONBLOCK,
+ DEFFILEMODE)) < 0)
+ err(1, "%s", tracefile);
+ if (fstat(fd, &sb) != 0 || sb.st_uid != getuid())
+ errx(1, "refuse to append to %s not owned by you",
+ tracefile);
+ if (!(S_ISREG(sb.st_mode)))
+ errx(1, "%s not regular file", tracefile);
+ } else {
+ if (unlink(tracefile) == -1 && errno != ENOENT)
+ err(1, "unlink %s", tracefile);
+ if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY,
+ DEFFILEMODE)) < 0)
+ err(1, "%s", tracefile);
+ }
+ (void)umask(omask);
+ (void)close(fd);
+
+ trpoints |= PROC_ABI_POINTS;
+
+ if (argc > 0) {
+ if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
+ err(1, "%s", tracefile);
+ execvp(*argv, argv);
+ err(1, "exec of '%s' failed", *argv);
+ }
+ if (ktrace(tracefile, ops, trpoints, pid) < 0)
+ err(1, "%s", tracefile);
+ exit(0);
+}
+
+static void
+set_pid_clear(const char *p, enum clear cl)
+{
+ intmax_t n;
+ char *e;
+
+ if (clear != NOTSET && cl != NOTSET) {
+ /* either -c and -C or either of them twice */
+ warnx("only one -c or -C flag is permitted");
+ usage();
+ }
+ if ((clear == CLEARALL && p != NULL) || (cl == CLEARALL && pid != 0)) {
+ /* both -C and a pid or pgid */
+ warnx("the -C flag may not be combined with -g or -p");
+ usage();
+ }
+ if (p != NULL && pid != 0) {
+ /* either -p and -g or either of them twice */
+ warnx("only one -g or -p flag is permitted");
+ usage();
+ }
+ if (p != NULL) {
+ errno = 0;
+ n = strtoimax(p, &e, 10);
+ /*
+ * 1) not a number, or outside the range of an intmax_t
+ * 2) inside the range of intmax_t but outside the range
+ * of an int, keeping in mind that the pid may be
+ * negated if it's actually a pgid.
+ */
+ if (*e != '\0' || n < 1 || errno == ERANGE ||
+ n > (intmax_t)INT_MAX || n > -(intmax_t)INT_MIN) {
+ warnx("invalid process or group id");
+ usage();
+ }
+ pid = n;
+ }
+ if (cl != NOTSET)
+ if ((clear = cl) == CLEARALL)
+ pid = 1;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "%s\n%s\n",
+ "usage: ktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t trstr]",
+ " ktrace [-adi] [-f trfile] [-t trstr] command");
+ exit(1);
+}
+
+static void
+no_ktrace(int sig __unused)
+{
+
+ fprintf(stderr, "error:\t%s\n\t%s\n",
+ "ktrace() system call not supported in the running kernel",
+ "re-compile kernel with 'options KTRACE'");
+ exit(1);
+}
diff --git a/usr.bin/ktrace/ktrace.h b/usr.bin/ktrace/ktrace.h
new file mode 100644
index 000000000000..d6da094f33a2
--- /dev/null
+++ b/usr.bin/ktrace/ktrace.h
@@ -0,0 +1,44 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
+ KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \
+ KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_STRUCT_ARRAY | \
+ KTRFAC_ARGS | KTRFAC_ENVS)
+
+#define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR)
+
+#define ALL_POINTS (DEF_POINTS | KTRFAC_CAPFAIL | KTRFAC_CSW | \
+ PROC_ABI_POINTS | KTRFAC_FAULT | KTRFAC_FAULTEND)
+
+#define DEF_TRACEFILE "ktrace.out"
+
+int getpoints(char *);
diff --git a/usr.bin/ktrace/subr.c b/usr.bin/ktrace/subr.c
new file mode 100644
index 000000000000..1db4c214414b
--- /dev/null
+++ b/usr.bin/ktrace/subr.c
@@ -0,0 +1,128 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+
+#include <stdio.h>
+
+#include "ktrace.h"
+
+void timevaladd(struct timeval *, struct timeval *);
+void timevalsub(struct timeval *, struct timeval *);
+void timevalfix(struct timeval *);
+
+int
+getpoints(char *s)
+{
+ int facs = 0;
+
+ while (*s) {
+ switch(*s) {
+ case 'c':
+ facs |= KTRFAC_SYSCALL | KTRFAC_SYSRET;
+ break;
+ case 'i':
+ facs |= KTRFAC_GENIO;
+ break;
+ case 'f':
+ facs |= KTRFAC_FAULT | KTRFAC_FAULTEND;
+ break;
+ case 'n':
+ facs |= KTRFAC_NAMEI;
+ break;
+ case 'p':
+ facs |= KTRFAC_CAPFAIL;
+ break;
+ case 's':
+ facs |= KTRFAC_PSIG;
+ break;
+ case 't':
+ facs |= KTRFAC_STRUCT | KTRFAC_STRUCT_ARRAY;
+ break;
+ case 'u':
+ facs |= KTRFAC_USER;
+ break;
+ case 'w':
+ facs |= KTRFAC_CSW;
+ break;
+ case 'y':
+ facs |= KTRFAC_SYSCTL;
+ break;
+ case 'a':
+ facs |= KTRFAC_ARGS;
+ break;
+ case 'e':
+ facs |= KTRFAC_ENVS;
+ break;
+ case '+':
+ facs |= DEF_POINTS;
+ break;
+ default:
+ return (-1);
+ }
+ s++;
+ }
+ return (facs);
+}
+
+void
+timevaladd(struct timeval *t1, struct timeval *t2)
+{
+ t1->tv_sec += t2->tv_sec;
+ t1->tv_usec += t2->tv_usec;
+ timevalfix(t1);
+}
+
+void
+timevalsub(struct timeval *t1, struct timeval *t2)
+{
+ t1->tv_sec -= t2->tv_sec;
+ t1->tv_usec -= t2->tv_usec;
+ timevalfix(t1);
+}
+
+void
+timevalfix(struct timeval *t1)
+{
+ if (t1->tv_usec < 0) {
+ t1->tv_sec--;
+ t1->tv_usec += 1000000;
+ }
+ if (t1->tv_usec >= 1000000) {
+ t1->tv_sec++;
+ t1->tv_usec -= 1000000;
+ }
+}
diff --git a/usr.bin/ktrdump/Makefile b/usr.bin/ktrdump/Makefile
new file mode 100644
index 000000000000..2bea92917d2b
--- /dev/null
+++ b/usr.bin/ktrdump/Makefile
@@ -0,0 +1,5 @@
+PROG= ktrdump
+LIBADD= kvm
+MAN= ktrdump.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ktrdump/Makefile.depend b/usr.bin/ktrdump/Makefile.depend
new file mode 100644
index 000000000000..03e36f90628e
--- /dev/null
+++ b/usr.bin/ktrdump/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libkvm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ktrdump/ktrdump.8 b/usr.bin/ktrdump/ktrdump.8
new file mode 100644
index 000000000000..5ad2ee8f3c1d
--- /dev/null
+++ b/usr.bin/ktrdump/ktrdump.8
@@ -0,0 +1,93 @@
+.\"-
+.\" Copyright (c) 2002 Chad David
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 October 22, 2018
+.Dt KTRDUMP 8
+.Os
+.Sh NAME
+.Nm ktrdump
+.Nd print kernel ktr trace buffer
+.Sh SYNOPSIS
+.Nm
+.Op Fl cflqrtH
+.Op Fl i Ar ktrfile
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl o Ar outfile
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to dump the contents of the kernel ktr trace buffer.
+.Pp
+The following options are available:
+.Bl -tag -width ".Fl i Ar ktrfile"
+.It Fl c
+Print the CPU number that each entry was logged from.
+.It Fl l
+Poll the kernel ktr trace buffer periodically dumping any new events after
+each poll.
+.It Fl f
+Print the file and line number that each entry was logged from.
+.It Fl q
+Quiet mode; do not print the column header.
+.It Fl r
+Print relative timestamps rather than absolute timestamps.
+.It Fl t
+Print the timestamp for each entry.
+.It Fl H
+Print the thread ID for each entry.
+.It Fl i Ar ktrfile
+File containing saved ktr trace events; for more information see the
+.Xr ktr 4
+manual page.
+.It Fl N Ar system
+The kernel image to resolve symbols from.
+The default is the value returned via
+.Xr getbootfile 3 .
+.It Fl M Ar core
+The core file or memory image to read from.
+The default is
+.Pa /dev/mem .
+.It Fl o Ar outfile
+The file to write the output to.
+The default is standard output.
+.El
+.Sh SEE ALSO
+.Xr ktr 4 ,
+.Xr ktr 9
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was implemented by
+.An Jake Burkholder Aq Mt jake@FreeBSD.org .
+.Pp
+This manual page was written by
+.An Chad David Aq Mt davidc@FreeBSD.org .
diff --git a/usr.bin/ktrdump/ktrdump.c b/usr.bin/ktrdump/ktrdump.c
new file mode 100644
index 000000000000..417c565022da
--- /dev/null
+++ b/usr.bin/ktrdump/ktrdump.c
@@ -0,0 +1,403 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Jake Burkholder
+ * Copyright (c) 2004 Robert Watson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/capsicum.h>
+#include <sys/ktr.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SBUFLEN 128
+#define USAGE \
+ "usage: ktrdump [-cflqrtH] [-i ktrfile] [-M core] [-N system] [-o outfile]\n"
+
+static void usage(void) __dead2;
+
+static struct nlist nl[] = {
+ { .n_name = "_ktr_version" },
+ { .n_name = "_ktr_entries" },
+ { .n_name = "_ktr_idx" },
+ { .n_name = "_ktr_buf" },
+ { .n_name = NULL }
+};
+
+static int cflag;
+static int fflag;
+static int lflag;
+static int Mflag;
+static int Nflag;
+static int qflag;
+static int rflag;
+static int tflag;
+static int iflag;
+static int hflag;
+
+static char corefile[PATH_MAX];
+static char execfile[PATH_MAX];
+static char outfile[PATH_MAX] = "stdout";
+
+static char desc[SBUFLEN];
+static char errbuf[_POSIX2_LINE_MAX];
+static char fbuf[PATH_MAX];
+static char obuf[PATH_MAX];
+static char sbuf[KTR_PARMS][SBUFLEN];
+
+/*
+ * Reads the ktr trace buffer from kernel memory and prints the trace entries.
+ */
+int
+main(int ac, char **av)
+{
+ u_long parms[KTR_PARMS];
+ struct ktr_entry *buf;
+ uintmax_t tlast, tnow;
+ unsigned long bufptr;
+ cap_rights_t rights;
+ struct stat sb;
+ kvm_t *kd;
+ FILE *out;
+ char *p;
+ int version;
+ int entries;
+ int count;
+ int index, index2;
+ int parm;
+ int in;
+ int c;
+ int i = 0;
+
+ /*
+ * Parse commandline arguments.
+ */
+ out = stdout;
+ while ((c = getopt(ac, av, "cflqrtHe:i:m:M:N:o:")) != -1)
+ switch (c) {
+ case 'c':
+ cflag = 1;
+ break;
+ case 'N':
+ case 'e':
+ if (strlcpy(execfile, optarg, sizeof(execfile))
+ >= sizeof(execfile))
+ errx(1, "%s: File name too long", optarg);
+ Nflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ if ((in = open(optarg, O_RDONLY)) == -1)
+ err(1, "%s", optarg);
+ cap_rights_init(&rights, CAP_FSTAT, CAP_MMAP_R);
+ if (caph_rights_limit(in, &rights) < 0)
+ err(1, "unable to limit rights for %s",
+ optarg);
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'M':
+ case 'm':
+ if (strlcpy(corefile, optarg, sizeof(corefile))
+ >= sizeof(corefile))
+ errx(1, "%s: File name too long", optarg);
+ Mflag = 1;
+ break;
+ case 'o':
+ if ((out = fopen(optarg, "w")) == NULL)
+ err(1, "%s", optarg);
+ strlcpy(outfile, optarg, sizeof(outfile));
+ break;
+ case 'q':
+ qflag++;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'H':
+ hflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ ac -= optind;
+ av += optind;
+ if (ac != 0)
+ usage();
+
+ if (caph_limit_stream(fileno(out), CAPH_WRITE) < 0)
+ err(1, "unable to limit rights for %s", outfile);
+ if (caph_limit_stderr() < 0)
+ err(1, "unable to limit rights for stderr");
+
+ /*
+ * Open our execfile and corefile, resolve needed symbols and read in
+ * the trace buffer.
+ */
+ if ((kd = kvm_openfiles(Nflag ? execfile : NULL,
+ Mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
+ errx(1, "%s", errbuf);
+
+ /*
+ * Cache NLS data, for strerror, for err(3), before entering capability
+ * mode.
+ */
+ caph_cache_catpages();
+
+ count = kvm_nlist(kd, nl);
+ if (count == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ if (count > 0)
+ errx(1, "failed to resolve ktr symbols");
+ if (kvm_read(kd, nl[0].n_value, &version, sizeof(version)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ if (version != KTR_VERSION)
+ errx(1, "ktr version mismatch");
+
+ /*
+ * Enter Capsicum sandbox.
+ *
+ * kvm_nlist() above uses kldsym(2) for native kernels, and that isn't
+ * allowed in the sandbox.
+ */
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ if (iflag) {
+ if (fstat(in, &sb) == -1)
+ errx(1, "stat");
+ entries = sb.st_size / sizeof(*buf);
+ index = 0;
+ buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, in, 0);
+ if (buf == MAP_FAILED)
+ errx(1, "mmap");
+ } else {
+ if (kvm_read(kd, nl[1].n_value, &entries, sizeof(entries))
+ == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ if ((buf = malloc(sizeof(*buf) * entries)) == NULL)
+ err(1, NULL);
+ if (kvm_read(kd, nl[2].n_value, &index, sizeof(index)) == -1 ||
+ kvm_read(kd, nl[3].n_value, &bufptr,
+ sizeof(bufptr)) == -1 ||
+ kvm_read(kd, bufptr, buf, sizeof(*buf) * entries) == -1 ||
+ kvm_read(kd, nl[2].n_value, &index2, sizeof(index2)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ }
+
+ /*
+ * Print a nice header.
+ */
+ if (!qflag) {
+ fprintf(out, "%-6s ", "index");
+ if (cflag)
+ fprintf(out, "%-3s ", "cpu");
+ if (tflag)
+ fprintf(out, "%-16s ", "timestamp");
+ if (fflag)
+ fprintf(out, "%-40s ", "file and line");
+ if (hflag)
+ fprintf(out, "%-18s ", "tid");
+ fprintf(out, "%s", "trace");
+ fprintf(out, "\n");
+
+ fprintf(out, "------ ");
+ if (cflag)
+ fprintf(out, "--- ");
+ if (tflag)
+ fprintf(out, "---------------- ");
+ if (fflag)
+ fprintf(out,
+ "---------------------------------------- ");
+ if (hflag)
+ fprintf(out, "------------------ ");
+ fprintf(out, "----- ");
+ fprintf(out, "\n");
+ }
+
+ tlast = UINTPTR_MAX;
+ /*
+ * Now tear through the trace buffer.
+ *
+ * In "live" mode, find the oldest entry (first non-NULL entry
+ * after index2) and walk forward. Otherwise, start with the
+ * most recent entry and walk backwards.
+ */
+ if (!iflag) {
+ if (lflag) {
+ i = index2 + 1 % entries;
+ while (buf[i].ktr_desc == NULL && i != index) {
+ i++;
+ if (i == entries)
+ i = 0;
+ }
+ } else {
+ i = index - 1;
+ if (i < 0)
+ i = entries - 1;
+ }
+ }
+dump_entries:
+ for (;;) {
+ if (buf[i].ktr_desc == NULL)
+ break;
+ if (kvm_read(kd, (u_long)buf[i].ktr_desc, desc,
+ sizeof(desc)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ desc[sizeof(desc) - 1] = '\0';
+ parm = 0;
+ for (p = desc; (c = *p++) != '\0';) {
+ if (c != '%')
+ continue;
+next: if ((c = *p++) == '\0')
+ break;
+ if (c == '%')
+ continue;
+ if (parm == KTR_PARMS)
+ errx(1, "too many parameters in \"%s\"", desc);
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '#': case '-': case ' ': case '+': case '\'':
+ case 'h': case 'l': case 'j': case 't': case 'z':
+ case 'q': case 'L': case '.':
+ goto next;
+ case 's':
+ if (kvm_read(kd, (u_long)buf[i].ktr_parms[parm],
+ sbuf[parm], sizeof(sbuf[parm])) == -1)
+ strcpy(sbuf[parm], "(null)");
+ sbuf[parm][sizeof(sbuf[0]) - 1] = '\0';
+ parms[parm] = (u_long)sbuf[parm];
+ parm++;
+ break;
+ default:
+ parms[parm] = buf[i].ktr_parms[parm];
+ parm++;
+ break;
+ }
+ }
+ fprintf(out, "%6d ", i);
+ if (cflag)
+ fprintf(out, "%3d ", buf[i].ktr_cpu);
+ if (tflag) {
+ tnow = (uintmax_t)buf[i].ktr_timestamp;
+ if (rflag) {
+ if (tlast == UINTPTR_MAX)
+ tlast = tnow;
+ fprintf(out, "%16ju ", !iflag ? tlast - tnow :
+ tnow - tlast);
+ tlast = tnow;
+ } else
+ fprintf(out, "%16ju ", tnow);
+ }
+ if (fflag) {
+ if (kvm_read(kd, (u_long)buf[i].ktr_file, fbuf,
+ sizeof(fbuf)) == -1)
+ strcpy(fbuf, "(null)");
+ snprintf(obuf, sizeof(obuf), "%s:%d", fbuf,
+ buf[i].ktr_line);
+ fprintf(out, "%-40s ", obuf);
+ }
+ if (hflag)
+ fprintf(out, "%p ", buf[i].ktr_thread);
+ fprintf(out, desc, parms[0], parms[1], parms[2], parms[3],
+ parms[4], parms[5]);
+ fprintf(out, "\n");
+ if (!iflag) {
+ /*
+ * 'index' and 'index2' are the values of 'ktr_idx'
+ * before and after the KTR buffer was copied into
+ * 'buf'. Since the KTR entries between 'index' and
+ * 'index2' were in flux while the KTR buffer was
+ * being copied to userspace we don't dump them.
+ */
+ if (lflag) {
+ if (++i == entries)
+ i = 0;
+ if (i == index)
+ break;
+ } else {
+ if (i == index2)
+ break;
+ if (--i < 0)
+ i = entries - 1;
+ }
+ } else {
+ if (++i == entries)
+ break;
+ }
+ }
+
+ /*
+ * In "live" mode, poll 'ktr_idx' periodically and dump any
+ * new entries since our last pass through the ring.
+ */
+ if (lflag && !iflag) {
+ while (index == index2) {
+ usleep(50 * 1000);
+ if (kvm_read(kd, nl[2].n_value, &index2,
+ sizeof(index2)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ }
+ i = index;
+ index = index2;
+ if (kvm_read(kd, bufptr, buf, sizeof(*buf) * entries) == -1 ||
+ kvm_read(kd, nl[2].n_value, &index2, sizeof(index2)) == -1)
+ errx(1, "%s", kvm_geterr(kd));
+ goto dump_entries;
+ }
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, USAGE);
+ exit(1);
+}
diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile
new file mode 100644
index 000000000000..f9ac12bb0f9d
--- /dev/null
+++ b/usr.bin/kyua/Makefile
@@ -0,0 +1,224 @@
+.include <src.opts.mk>
+
+KYUA_CONFDIR= /etc/kyua
+KYUA_DOCDIR= /usr/share/doc/kyua
+KYUA_EGDIR= /usr/share/examples/kyua
+KYUA_MISCDIR= /usr/share/kyua/misc
+KYUA_STOREDIR= /usr/share/kyua/store
+KYUA_VERSION= 0.13
+
+KYUA_SRCDIR= ${SRCTOP}/contrib/kyua
+.PATH: ${KYUA_SRCDIR}
+
+PACKAGE= tests
+PROG_CXX= kyua
+SRCS= main.cpp
+LIBADD= lutok sqlite3
+
+MAN= kyua-about.1 \
+ kyua-config.1 \
+ kyua-db-exec.1 \
+ kyua-db-migrate.1 \
+ kyua-debug.1 \
+ kyua-help.1 \
+ kyua-list.1 \
+ kyua-report-html.1 \
+ kyua-report-junit.1 \
+ kyua-report.1 \
+ kyua-test.1 \
+ kyua.1 \
+ kyua.conf.5 \
+ kyuafile.5
+
+CFLAGS+= -I${KYUA_SRCDIR} -I${.CURDIR}
+CFLAGS+= -I${SRCTOP}/contrib/lutok/include
+CFLAGS+= -I${SRCTOP}/contrib/sqlite3
+# kyua uses auto_ptr
+CFLAGS+= -Wno-deprecated-declarations
+CXXSTD= c++11
+CFLAGS+= -DHAVE_CONFIG_H
+
+# We compile the kyua libraries as part of the main executable as this saves
+# compile time and we don't install them anyway.
+CFLAGS+= -DGDB=\"/usr/local/bin/gdb\" \
+ -DKYUA_ARCHITECTURE=\"${MACHINE_ARCH}\" \
+ -DKYUA_CONFDIR=\"${KYUA_CONFDIR}\" \
+ -DKYUA_DOCDIR=\"${KYUA_DOCDIR}\" \
+ -DKYUA_MISCDIR=\"${KYUA_MISCDIR}\" \
+ -DKYUA_PLATFORM=\"${MACHINE}\" \
+ -DKYUA_STOREDIR=\"${KYUA_STOREDIR}\" \
+ -DPACKAGE=\"kyua\" \
+ -DPACKAGE_NAME=\"Kyua\" \
+ -DPACKAGE_VERSION=\"${KYUA_VERSION}\" \
+ -DVERSION=\"${KYUA_VERSION}\"
+
+SRCS+= utils/datetime.cpp \
+ utils/env.cpp \
+ utils/memory.cpp \
+ utils/passwd.cpp \
+ utils/sanity.cpp \
+ utils/stacktrace.cpp \
+ utils/stream.cpp \
+ utils/units.cpp \
+ utils/cmdline/base_command.cpp \
+ utils/cmdline/exceptions.cpp \
+ utils/cmdline/globals.cpp \
+ utils/cmdline/options.cpp \
+ utils/cmdline/parser.cpp \
+ utils/cmdline/ui.cpp \
+ utils/cmdline/ui_mock.cpp \
+ utils/config/exceptions.cpp \
+ utils/config/keys.cpp \
+ utils/config/lua_module.cpp \
+ utils/config/nodes.cpp \
+ utils/config/parser.cpp \
+ utils/config/tree.cpp \
+ utils/format/exceptions.cpp \
+ utils/format/formatter.cpp \
+ utils/fs/auto_cleaners.cpp \
+ utils/fs/directory.cpp \
+ utils/fs/exceptions.cpp \
+ utils/fs/lua_module.cpp \
+ utils/fs/operations.cpp \
+ utils/fs/path.cpp \
+ utils/logging/operations.cpp \
+ utils/process/child.cpp \
+ utils/process/deadline_killer.cpp \
+ utils/process/exceptions.cpp \
+ utils/process/executor.cpp \
+ utils/process/fdstream.cpp \
+ utils/process/isolation.cpp \
+ utils/process/operations.cpp \
+ utils/process/status.cpp \
+ utils/process/system.cpp \
+ utils/process/systembuf.cpp \
+ utils/signals/exceptions.cpp \
+ utils/signals/interrupts.cpp \
+ utils/signals/misc.cpp \
+ utils/signals/programmer.cpp \
+ utils/signals/timer.cpp \
+ utils/sqlite/c_gate.cpp \
+ utils/sqlite/database.cpp \
+ utils/sqlite/exceptions.cpp \
+ utils/sqlite/statement.cpp \
+ utils/sqlite/transaction.cpp \
+ utils/text/exceptions.cpp \
+ utils/text/operations.cpp \
+ utils/text/regex.cpp \
+ utils/text/table.cpp \
+ utils/text/templates.cpp
+
+SRCS+= model/context.cpp \
+ model/exceptions.cpp \
+ model/metadata.cpp \
+ model/test_case.cpp \
+ model/test_program.cpp \
+ model/test_result.cpp
+
+SRCS+= engine/atf.cpp \
+ engine/atf_list.cpp \
+ engine/atf_result.cpp \
+ engine/config.cpp \
+ engine/exceptions.cpp \
+ engine/filters.cpp \
+ engine/kyuafile.cpp \
+ engine/plain.cpp \
+ engine/requirements.cpp \
+ engine/scanner.cpp \
+ engine/tap.cpp \
+ engine/tap_parser.cpp \
+ engine/scheduler.cpp \
+ engine/execenv/execenv.cpp \
+ engine/execenv/execenv_host.cpp
+
+SRCS+= os/freebsd/execenv_jail_manager.cpp \
+ os/freebsd/main.cpp
+
+SRCS+= store/dbtypes.cpp \
+ store/exceptions.cpp \
+ store/layout.cpp \
+ store/metadata.cpp \
+ store/migrate.cpp \
+ store/read_backend.cpp \
+ store/read_transaction.cpp \
+ store/write_backend.cpp \
+ store/write_transaction.cpp
+
+SRCS+= drivers/debug_test.cpp \
+ drivers/list_tests.cpp \
+ drivers/report_junit.cpp \
+ drivers/run_tests.cpp \
+ drivers/scan_results.cpp
+
+SRCS+= cli/cmd_about.cpp \
+ cli/cmd_config.cpp \
+ cli/cmd_db_exec.cpp \
+ cli/cmd_db_migrate.cpp \
+ cli/cmd_debug.cpp \
+ cli/cmd_help.cpp \
+ cli/cmd_list.cpp \
+ cli/cmd_report.cpp \
+ cli/cmd_report_html.cpp \
+ cli/cmd_report_junit.cpp \
+ cli/cmd_test.cpp \
+ cli/common.cpp \
+ cli/config.cpp \
+ cli/main.cpp
+
+.if ${MK_JAIL} == "no"
+SRCS+= os/freebsd/execenv_jail_stub.cpp
+.else
+SRCS+= os/freebsd/execenv_jail.cpp \
+ os/freebsd/utils/jail.cpp
+LIBADD+= jail
+.endif
+
+FILESGROUPS= DOCS MISC STORE
+
+.if ${MK_EXAMPLES} != "no"
+FILESGROUPS+= EXAMPLES
+.endif
+
+# Install a minimal default config that uses the 'tests' user.
+# The examples config is not appropriate for general use.
+CONFS= kyua.conf-default
+CONFSDIR= ${KYUA_CONFDIR}
+CONFSNAME= kyua.conf
+CONFSDIRTAGS= package=tests
+
+DOCS= AUTHORS CONTRIBUTORS LICENSE
+DOCSDIR= ${KYUA_DOCDIR}
+DOCSTAGS= package=tests
+
+EXAMPLES= Kyuafile.top kyua.conf
+EXAMPLESDIR= ${KYUA_EGDIR}
+EXAMPLESTAGS= package=tests
+.PATH: ${KYUA_SRCDIR}/examples
+
+MISC= context.html index.html report.css test_result.html
+MISCDIR= ${KYUA_MISCDIR}
+MISCTAGS= package=tests
+.PATH: ${KYUA_SRCDIR}/misc
+
+STORE= migrate_v1_v2.sql migrate_v2_v3.sql schema_v3.sql
+STOREDIR= ${KYUA_STOREDIR}
+STORETAGS= package=tests
+.PATH: ${KYUA_SRCDIR}/store
+
+CLEANFILES+= ${MAN}
+.PATH: ${KYUA_SRCDIR}/doc
+.for man in ${MAN}
+${man}: ${man}.in
+ sh ${KYUA_SRCDIR}/doc/manbuild.sh \
+ -v "CONFDIR=${KYUA_CONFDIR}" \
+ -v "DOCDIR=${KYUA_DOCDIR}" \
+ -v "EGDIR=${KYUA_EGDIR}" \
+ -v "MISCDIR=${KYUA_MISCDIR}" \
+ -v "PACKAGE=kyua" \
+ -v "STOREDIR=${KYUA_STOREDIR}" \
+ -v "TESTSDIR=${TESTSBASE}" \
+ -v "VERSION=${KYUA_VERSION}" \
+ ${.ALLSRC} ${.TARGET}
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/kyua/Makefile.depend b/usr.bin/kyua/Makefile.depend
new file mode 100644
index 000000000000..d6bfbeef15c5
--- /dev/null
+++ b/usr.bin/kyua/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ bin/sh.host \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/libjail \
+ lib/liblua \
+ lib/liblutok \
+ lib/libsqlite3 \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/kyua/config.h b/usr.bin/kyua/config.h
new file mode 100644
index 000000000000..132972229364
--- /dev/null
+++ b/usr.bin/kyua/config.h
@@ -0,0 +1,122 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to the optind value to reset getopt processing */
+#define GETOPT_OPTIND_RESET_VALUE 1
+
+/* Define to 1 if getcwd(NULL, 0) works */
+#define HAVE_GETCWD_DYN 1
+
+/* Define to 1 if getopt allows a + sign for POSIX behavior */
+/* #undef HAVE_GETOPT_GNU */
+
+/* Define to 1 if getopt has optreset */
+#define HAVE_GETOPT_WITH_OPTRESET 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `statfs' function. */
+#define HAVE_STATFS 1
+
+/* Define to 1 if you have the `statvfs' function. */
+#define HAVE_STATVFS 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `sysctlbyname' function. */
+#define HAVE_SYSCTLBYNAME 1
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#define HAVE_SYS_STATVFS_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unmount' function. */
+#define HAVE_UNMOUNT 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if your lchmod works */
+#define HAVE_WORKING_LCHMOD 1
+
+/* Define to the last valid signal number */
+#define LAST_SIGNO 128
+
+/* Define to the name of the sysctl MIB */
+#define MEMORY_QUERY_SYSCTL_MIB "hw.usermem"
+
+/* Define to the memory query type */
+#define MEMORY_QUERY_TYPE "sysctlbyname"
+
+/* Name of package */
+#define PACKAGE "kyua"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "kyua-discuss@googlegroups.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Kyua"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Kyua 0.13"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "kyua"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "https://github.com/jmmv/kyua/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.13"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Set to the path of umount(8) */
+/* #undef UMOUNT */
+
+/* Version number of package */
+#define VERSION "0.13"
diff --git a/usr.bin/kyua/kyua.conf-default b/usr.bin/kyua/kyua.conf-default
new file mode 100644
index 000000000000..e2e73c66515c
--- /dev/null
+++ b/usr.bin/kyua/kyua.conf-default
@@ -0,0 +1,13 @@
+--
+-- System-wide configuration file for kyua(1). See kyua.conf(5) for details
+-- on the syntax.
+--
+
+syntax(2)
+
+-- User to drop privileges to when invoking kyua(1) as root and a test case
+-- requests to be run with non-root permissions.
+unprivileged_user = 'tests'
+
+-- An example to set a configuration property specific to FreeBSD.
+--test_suites.FreeBSD.fstype = 'ffs'
diff --git a/usr.bin/kyua/utils/defs.hpp b/usr.bin/kyua/utils/defs.hpp
new file mode 100644
index 000000000000..32d1f9bb2344
--- /dev/null
+++ b/usr.bin/kyua/utils/defs.hpp
@@ -0,0 +1,70 @@
+// Copyright 2010 The Kyua Authors.
+// All rights reserved.
+//
+// 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.
+//
+// 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.
+
+/// \file utils/defs.hpp
+///
+/// Definitions for compiler and system features autodetected at configuration
+/// time.
+
+#if !defined(UTILS_DEFS_HPP)
+#define UTILS_DEFS_HPP
+
+
+/// Attribute to mark a function as non-returning.
+#define UTILS_NORETURN __attribute__((noreturn))
+
+
+/// Attribute to mark a function as pure.
+#define UTILS_PURE __attribute__((__pure__))
+
+
+/// Attribute to mark an entity as unused.
+#define UTILS_UNUSED __attribute__((__unused__))
+
+
+/// Unconstifies a pointer.
+///
+/// \param type The target type of the conversion.
+/// \param ptr The pointer to be unconstified.
+#define UTILS_UNCONST(type, ptr) ((type*)(unsigned long)(const void*)(ptr))
+
+
+/// Macro to mark a parameter as unused.
+///
+/// This macro has to be called on the name of a parameter during the
+/// definition (not declaration) of a function. When doing so, it declares
+/// the parameter as unused to silence compiler warnings and also renames
+/// the parameter by prefixing "unused_" to it. This is to ensure that the
+/// developer remembers to remove the call to this macro from the parameter
+/// when he actually starts using it.
+///
+/// \param name The name of the function parameter to mark as unused.
+#define UTILS_UNUSED_PARAM(name) unused_ ## name UTILS_UNUSED
+
+
+#endif // !defined(UTILS_DEFS_HPP)
diff --git a/usr.bin/lam/Makefile b/usr.bin/lam/Makefile
new file mode 100644
index 000000000000..e47ea0a98eaa
--- /dev/null
+++ b/usr.bin/lam/Makefile
@@ -0,0 +1,3 @@
+PROG= lam
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lam/Makefile.depend b/usr.bin/lam/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/lam/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lam/lam.1 b/usr.bin/lam/lam.1
new file mode 100644
index 000000000000..cf1af65b2f14
--- /dev/null
+++ b/usr.bin/lam/lam.1
@@ -0,0 +1,155 @@
+.\" Copyright (c) 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.
+.\"
+.Dd April 7, 2015
+.Dt LAM 1
+.Os
+.Sh NAME
+.Nm lam
+.Nd laminate files
+.Sh SYNOPSIS
+.Nm
+.Op Fl f Ar min . Ns Ar max
+.Op Fl s Ar sepstring
+.Op Fl t Ar c
+.Ar
+.Nm
+.Op Fl p Ar min . Ns Ar max
+.Op Fl s Ar sepstring
+.Op Fl t Ar c
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility copies the named files side by side onto the standard output.
+The
+.Em n-th
+input lines from the input
+.Ar files
+are considered fragments of the single long
+.Em n-th
+output line into which they are assembled.
+The name `\fB\-\fP' means the standard input, and may be repeated.
+.Pp
+.Bl -tag -width indent
+.It Fl f Ar min . Ns Ar max , Fl F Ar min . Ns Ar max
+Print line fragments according to the format string
+.Ar min . Ns Ar max ,
+where
+.Ar min
+is the minimum field width and
+.Ar max
+the maximum field width.
+If
+.Ar min
+begins with a zero, zeros will be added to make up the field width,
+and if it begins with a `\-', the fragment will be left-adjusted
+within the field.
+Using
+.Fl f
+applies only to the next file while
+.Fl F
+applies to all subsequent files until it appears again uncapitalized.
+.It Fl p Ar min . Ns Ar max , Fl P Ar min . Ns Ar max
+Like
+.Fl f ,
+but pad this file's field when end-of-file is reached
+and other files are still active.
+Using
+.Fl p
+applies only to the next file while
+.Fl P
+applies to all subsequent files until it appears again uncapitalized.
+.It Fl s Ar sepstring , Fl S Ar sepstring
+Print
+.Ar sepstring
+before printing line fragments from the next file.
+This option may appear after the last file.
+Using
+.Fl s
+applies only to the next file while
+.Fl S
+applies to all subsequent files until it appears again uncapitalized.
+.It Fl t Ar c , Fl T Ar c
+The input line terminator is
+.Ar c
+instead of a newline.
+The newline normally appended to each output line is omitted.
+Using
+.Fl t
+applies only to the next file while
+.Fl T
+applies to all subsequent files until it appears again uncapitalized.
+.El
+.Pp
+To print files simultaneously for easy viewing use
+.Xr pr 1 .
+.Sh EXAMPLES
+The command
+.Bd -literal
+lam file1 file2 file3 file4
+.Ed
+.Pp
+joins 4 files together along each line.
+To merge the lines from four different files use
+.Bd -literal
+lam file1 \-S "\\
+" file2 file3 file4
+.Ed
+.Pp
+Every 2 lines of a file may be joined on one line with
+.Bd -literal
+lam \- \- < file
+.Ed
+.Pp
+and a form letter with substitutions keyed by `@' can be done with
+.Bd -literal
+lam \-t @ letter changes
+.Ed
+.Sh SEE ALSO
+.Xr join 1 ,
+.Xr paste 1 ,
+.Xr pr 1 ,
+.Xr printf 3
+.Sh STANDARDS
+Some of the functionality of
+.Nm
+is standardized as the
+.Xr paste 1
+utility by
+.St -p1003.2 .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+.An John A. Kunze
+.Sh BUGS
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/lam/lam.c b/usr.bin/lam/lam.c
new file mode 100644
index 000000000000..2194ae7ab596
--- /dev/null
+++ b/usr.bin/lam/lam.c
@@ -0,0 +1,238 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+/*
+ * lam - laminate files
+ * Author: John Kunze, UCB
+ */
+
+#include <sys/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#define MAXOFILES 20
+#define BIGBUFSIZ 5 * BUFSIZ
+
+static struct openfile { /* open file structure */
+ FILE *fp; /* file pointer */
+ short eof; /* eof flag */
+ short pad; /* pad flag for missing columns */
+ char eol; /* end of line character */
+ const char *sepstring; /* string to print before each line */
+ const char *format; /* printf(3) style string spec. */
+} input[MAXOFILES];
+
+static int morefiles; /* set by getargs(), changed by gatherline() */
+static int nofinalnl; /* normally append \n to each output line */
+static char line[BIGBUFSIZ];
+static char *linep;
+
+static char *gatherline(struct openfile *);
+static void getargs(char *[]);
+static char *pad(struct openfile *);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct openfile *ip;
+
+ if (argc == 1)
+ usage();
+ if (caph_limit_stdio() == -1)
+ err(1, "unable to limit stdio");
+ getargs(argv);
+ if (!morefiles)
+ usage();
+
+ /*
+ * Cache NLS data, for strerror, for err(3), before entering capability
+ * mode.
+ */
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ for (;;) {
+ linep = line;
+ for (ip = input; ip->fp != NULL; ip++)
+ linep = gatherline(ip);
+ if (!morefiles)
+ exit(0);
+ fputs(line, stdout);
+ fputs(ip->sepstring, stdout);
+ if (!nofinalnl)
+ putchar('\n');
+ }
+}
+
+static void
+getargs(char *av[])
+{
+ struct openfile *ip = input;
+ char *p, *c;
+ static char fmtbuf[BUFSIZ];
+ char *fmtp = fmtbuf;
+ int P, S, F, T;
+ cap_rights_t rights_ro;
+
+ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT);
+ P = S = F = T = 0; /* capitalized options */
+ while ((p = *++av) != NULL) {
+ if (*p != '-' || !p[1]) {
+ if (++morefiles >= MAXOFILES)
+ errx(1, "too many input files");
+ if (*p == '-')
+ ip->fp = stdin;
+ else if ((ip->fp = fopen(p, "r")) == NULL) {
+ err(1, "%s", p);
+ }
+ if (caph_rights_limit(fileno(ip->fp), &rights_ro) < 0)
+ err(1, "unable to limit rights on: %s", p);
+ ip->pad = P;
+ if (!ip->sepstring)
+ ip->sepstring = (S ? (ip-1)->sepstring : "");
+ if (!ip->format)
+ ip->format = ((P || F) ? (ip-1)->format : "%s");
+ if (!ip->eol)
+ ip->eol = (T ? (ip-1)->eol : '\n');
+ ip++;
+ continue;
+ }
+ c = ++p;
+ switch (tolower((unsigned char)*c)) {
+ case 's':
+ if (*++p || (p = *++av))
+ ip->sepstring = p;
+ else
+ usage();
+ S = (*c == 'S' ? 1 : 0);
+ break;
+ case 't':
+ if (*++p || (p = *++av))
+ ip->eol = *p;
+ else
+ usage();
+ T = (*c == 'T' ? 1 : 0);
+ nofinalnl = 1;
+ break;
+ case 'p':
+ ip->pad = 1;
+ P = (*c == 'P' ? 1 : 0);
+ /* FALLTHROUGH */
+ case 'f':
+ F = (*c == 'F' ? 1 : 0);
+ if (*++p || (p = *++av)) {
+ fmtp += strlen(fmtp) + 1;
+ if (fmtp >= fmtbuf + sizeof(fmtbuf))
+ errx(1, "no more format space");
+ /* restrict format string to only valid width formatters */
+ if (strspn(p, "-.0123456789") != strlen(p))
+ errx(1, "invalid format string `%s'", p);
+ if (snprintf(fmtp, fmtbuf + sizeof(fmtbuf) - fmtp, "%%%ss", p)
+ >= fmtbuf + sizeof(fmtbuf) - fmtp)
+ errx(1, "no more format space");
+ ip->format = fmtp;
+ }
+ else
+ usage();
+ break;
+ default:
+ usage();
+ }
+ }
+ ip->fp = NULL;
+ if (!ip->sepstring)
+ ip->sepstring = "";
+}
+
+static char *
+pad(struct openfile *ip)
+{
+ char *lp = linep;
+
+ strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
+ lp += strlen(lp);
+ if (ip->pad) {
+ snprintf(lp, line + sizeof(line) - lp, ip->format, "");
+ lp += strlen(lp);
+ }
+ return (lp);
+}
+
+static char *
+gatherline(struct openfile *ip)
+{
+ char s[BUFSIZ];
+ int c;
+ char *p;
+ char *lp = linep;
+ char *end = s + sizeof(s) - 1;
+
+ if (ip->eof)
+ return (pad(ip));
+ for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++)
+ if ((*p = c) == ip->eol)
+ break;
+ *p = '\0';
+ if (c == EOF) {
+ ip->eof = 1;
+ if (ferror(ip->fp)) {
+ err(EX_IOERR, NULL);
+ }
+ if (ip->fp == stdin)
+ fclose(stdin);
+ morefiles--;
+ return (pad(ip));
+ }
+ strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
+ lp += strlen(lp);
+ snprintf(lp, line + sizeof(line) - lp, ip->format, s);
+ lp += strlen(lp);
+ return (lp);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+"usage: lam [ -f min.max ] [ -s sepstring ] [ -t c ] file ...",
+" lam [ -p min.max ] [ -s sepstring ] [ -t c ] file ...");
+ exit(1);
+}
diff --git a/usr.bin/last/Makefile b/usr.bin/last/Makefile
new file mode 100644
index 000000000000..eb32dcfb35b7
--- /dev/null
+++ b/usr.bin/last/Makefile
@@ -0,0 +1,7 @@
+PROG= last
+PACKAGE= acct
+LIBADD= xo
+
+NO_WFORMAT=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/last/Makefile.depend b/usr.bin/last/Makefile.depend
new file mode 100644
index 000000000000..705250164fe1
--- /dev/null
+++ b/usr.bin/last/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/last/last.1 b/usr.bin/last/last.1
new file mode 100644
index 000000000000..f3ccc6e772af
--- /dev/null
+++ b/usr.bin/last/last.1
@@ -0,0 +1,250 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd January 9, 2021
+.Dt LAST 1
+.Os
+.Sh NAME
+.Nm last
+.Nd indicate last logins of users and ttys
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl swy
+.Oo
+.Fl d
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Op Ar MM DD
+.Ar hh mm
+.Op Ar .SS
+.Sm on
+.Oc
+.Op Fl f Ar file
+.Op Fl h Ar host
+.Op Fl n Ar maxrec
+.Op Fl t Ar tty
+.Op Ar user ...
+.Sh DESCRIPTION
+The
+.Nm
+utility will either list the sessions of specified
+.Ar users ,
+.Ar ttys ,
+and
+.Ar hosts ,
+in reverse time order,
+or list the users logged in at a specified date and time.
+Each line of output contains
+the user name, the tty from which the session was conducted, any
+hostname, the start and stop times for the session, and the duration
+of the session.
+If the session is still continuing or was cut short by
+a crash or shutdown,
+.Nm
+will so indicate.
+.Pp
+The following options are available:
+.Bl -tag -width indent-two
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl d Ar date
+Specify the snapshot date and time.
+All users logged in at the snapshot date and time will
+be reported.
+This may be used with the
+.Fl f
+option to derive the results from stored
+.Pa utx.log
+files.
+When this argument is provided, all other options except for
+.Fl f
+and
+.Fl n
+are ignored.
+The argument should be in the form
+.Sm off
+.Op Oo Ar CC Oc Ar YY
+.Op Ar MM DD
+.Ar hh mm
+.Op Ar .SS
+.Sm on
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Ar CC
+The first two digits of the year (the century).
+.It Ar YY
+The second two digits of the year.
+If
+.Ar YY
+is specified, but
+.Ar CC
+is not, a value for
+.Ar YY
+between 69 and 99 results in a
+.Ar CC
+value of 19.
+Otherwise, a
+.Ar CC
+value of 20 is used.
+.It Ar MM
+Month of the year, from 1 to 12.
+.It Ar DD
+Day of the month, from 1 to 31.
+.It Ar hh
+Hour of the day, from 0 to 23.
+.It Ar mm
+Minute of the hour, from 0 to 59.
+.It Ar SS
+Second of the minute, from 0 to 60.
+.El
+.Pp
+If the
+.Ar CC
+and
+.Ar YY
+letter pairs are not specified, the values default to the current
+year.
+If the
+.Ar SS
+letter pair is not specified, the value defaults to 0.
+.It Fl f Ar file
+Read the file
+.Ar file
+instead of the default,
+.Pa /var/log/utx.log .
+.It Fl h Ar host
+.Ar Host
+names may be names or internet numbers.
+.It Fl n Ar maxrec
+Limit the report to
+.Ar maxrec
+lines.
+.It Fl s
+Report the duration of the login session in seconds, instead of the
+default days, hours and minutes.
+.It Fl t Ar tty
+Specify the
+.Ar tty .
+Tty names may be given fully or abbreviated, for example,
+.Dq Li "last -t 03"
+is
+equivalent to
+.Dq Li "last -t tty03" .
+.It Fl w
+Widen the duration field to show seconds, as well as the
+default days, hours and minutes.
+.It Fl y
+Report the year in the session start time.
+.El
+.Pp
+If multiple arguments are given,
+and a snapshot time is not specified,
+the information which applies to any of the
+arguments is printed, e.g.,
+.Dq Li "last root -t console"
+would list all of
+.Dq Li root Ns 's
+sessions as well as all sessions on the console terminal.
+If no
+users, hostnames or terminals are specified,
+.Nm
+prints a record of
+all logins and logouts.
+.Pp
+The pseudo-user
+.Ar reboot
+logs in at reboots of the system, thus
+.Dq Li last reboot
+will give an indication of mean time between reboot.
+.Pp
+If
+.Nm
+is interrupted, it indicates to what date the search has
+progressed.
+If interrupted with a quit signal
+.Nm
+indicates how
+far the search has progressed and then continues.
+.Sh FILES
+.Bl -tag -width /var/log/utx.log -compact
+.It Pa /var/log/utx.log
+login data base
+.El
+.Sh EXAMPLES
+Show logins in pts/14 with the duration in seconds and limit the report to
+two lines:
+.Bd -literal -offset indent
+$ last -n2 -s -t pts/14
+bob pts/1 Wed Dec 9 11:08 still logged in
+bob pts/2 Mon Dec 7 20:10 - 20:23 ( 776)
+.Ed
+.Pp
+Show active logins at
+.Ql December 7th 20:23
+of the current year:
+.Bd -literal -offset indent
+$ last -d 12072023
+bob pts/1 Mon Dec 7 20:10 - 20:23 (00:12)
+bob pts/6 Mon Dec 7 19:24 - 22:27 (03:03)
+alice ttyv0 Mon Dec 7 19:18 - 22:27 (03:09)
+.Ed
+.Sh SEE ALSO
+.Xr lastcomm 1 ,
+.Xr getutxent 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
+.Xr ac 8 ,
+.Xr lastlogin 8
+.Sh HISTORY
+.Nm
+utility first appeared in
+.Bx 1 .
+.Sh AUTHORS
+.An -nosplit
+The original version was written by
+.An Howard P. Katseff ;
+.An Keith Bostic
+rewrote it in 1986/87 to add functionality and to improve code quality.
+.An Philip Paeps
+added
+.Xr libxo 3
+support in August 2018.
+.Sh BUGS
+If a login shell should terminate abnormally for some reason, it is likely
+that a logout record will not be written to the
+.Pa utx.log
+file.
+In this case,
+.Nm
+will indicate the logout time as "shutdown".
diff --git a/usr.bin/last/last.c b/usr.bin/last/last.c
new file mode 100644
index 000000000000..69848f359d79
--- /dev/null
+++ b/usr.bin/last/last.c
@@ -0,0 +1,593 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2018 Philip Paeps
+ *
+ * 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>
+#include <sys/capsicum.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <timeconv.h>
+#include <unistd.h>
+#include <utmpx.h>
+
+#include <libxo/xo.h>
+
+#define NO 0 /* false/no */
+#define YES 1 /* true/yes */
+#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
+
+typedef struct arg {
+ char *name; /* argument */
+#define REBOOT_TYPE -1
+#define HOST_TYPE -2
+#define TTY_TYPE -3
+#define USER_TYPE -4
+ int type; /* type of arg */
+ struct arg *next; /* linked list pointer */
+} ARG;
+static ARG *arglist; /* head of linked list */
+
+static SLIST_HEAD(, idtab) idlist;
+
+struct idtab {
+ time_t logout; /* log out time */
+ char id[sizeof ((struct utmpx *)0)->ut_id]; /* identifier */
+ SLIST_ENTRY(idtab) list;
+};
+
+static const char *crmsg; /* cause of last reboot */
+static time_t currentout; /* current logout value */
+static long maxrec; /* records to display */
+static const char *file = NULL; /* utx.log file */
+static int sflag = 0; /* show delta in seconds */
+static int width = 5; /* show seconds in delta */
+static int yflag; /* show year */
+static int d_first;
+static int snapfound = 0; /* found snapshot entry? */
+static time_t snaptime; /* if != 0, we will only
+ * report users logged in
+ * at this snapshot time
+ */
+
+static void addarg(int, char *);
+static time_t dateconv(char *);
+static void doentry(struct utmpx *);
+static void hostconv(char *);
+static void printentry(struct utmpx *, struct idtab *);
+static char *ttyconv(char *);
+static int want(struct utmpx *);
+static void usage(void);
+static void wtmp(void);
+
+static void
+usage(void)
+{
+ xo_error(
+"usage: last [-swy] [-d [[CC]YY][MMDD]hhmm[.SS]] [-f file] [-h host]\n"
+" [-n maxrec] [-t tty] [user ...]\n");
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ char *p;
+
+ (void) setlocale(LC_TIME, "");
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(EXIT_FAILURE);
+
+ maxrec = -1;
+ snaptime = 0;
+ while ((ch = getopt(argc, argv, "0123456789d:f:h:n:st:wy")) != -1)
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /*
+ * kludge: last was originally designed to take
+ * a number after a dash.
+ */
+ if (maxrec == -1) {
+ p = strchr(argv[optind - 1], ch);
+ if (p == NULL)
+ p = strchr(argv[optind], ch);
+ maxrec = atol(p);
+ if (!maxrec) {
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_SUCCESS);
+ }
+ }
+ break;
+ case 'd':
+ snaptime = dateconv(optarg);
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ case 'h':
+ hostconv(optarg);
+ addarg(HOST_TYPE, optarg);
+ break;
+ case 'n':
+ errno = 0;
+ maxrec = strtol(optarg, &p, 10);
+ if (p == optarg || *p != '\0' || errno != 0 ||
+ maxrec <= 0)
+ xo_errx(1, "%s: bad line count", optarg);
+ break;
+ case 's':
+ sflag++; /* Show delta as seconds */
+ break;
+ case 't':
+ addarg(TTY_TYPE, ttyconv(optarg));
+ break;
+ case 'w':
+ width = 8;
+ break;
+ case 'y':
+ yflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (caph_limit_stdio() < 0)
+ xo_err(1, "can't limit stdio rights");
+
+ caph_cache_catpages();
+ caph_cache_tzdata();
+
+ /* Cache UTX database. */
+ if (setutxdb(UTXDB_LOG, file) != 0)
+ xo_err(1, "%s", file != NULL ? file : "(default utx db)");
+
+ if (caph_enter() < 0)
+ xo_err(1, "cap_enter");
+
+ if (sflag && width == 8) usage();
+
+ if (argc) {
+ setlinebuf(stdout);
+ for (argv += optind; *argv; ++argv) {
+ if (strcmp(*argv, "reboot") == 0)
+ addarg(REBOOT_TYPE, *argv);
+#define COMPATIBILITY
+#ifdef COMPATIBILITY
+ /* code to allow "last p5" to work */
+ addarg(TTY_TYPE, ttyconv(*argv));
+#endif
+ addarg(USER_TYPE, *argv);
+ }
+ }
+ wtmp();
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * wtmp --
+ * read through the utx.log file
+ */
+static void
+wtmp(void)
+{
+ struct utmpx *buf = NULL;
+ struct utmpx *ut;
+ static unsigned int amount = 0;
+ time_t t;
+ char ct[80];
+ struct tm *tm;
+
+ SLIST_INIT(&idlist);
+ (void)time(&t);
+
+ xo_open_container("last-information");
+
+ /* Load the last entries from the file. */
+ while ((ut = getutxent()) != NULL) {
+ if (amount % 128 == 0) {
+ buf = realloc(buf, (amount + 128) * sizeof *ut);
+ if (buf == NULL)
+ xo_err(1, "realloc");
+ }
+ memcpy(&buf[amount++], ut, sizeof *ut);
+ if (t > ut->ut_tv.tv_sec)
+ t = ut->ut_tv.tv_sec;
+ }
+ endutxent();
+
+ /* Display them in reverse order. */
+ xo_open_list("last");
+ while (amount > 0)
+ doentry(&buf[--amount]);
+ xo_close_list("last");
+ free(buf);
+ tm = localtime(&t);
+ (void) strftime(ct, sizeof(ct), "%+", tm);
+ xo_emit("\n{:utxdb/%s}", (file == NULL) ? "utx.log" : file);
+ xo_attr("seconds", "%lu", (unsigned long) t);
+ xo_emit(" begins {:begins/%hs}\n", ct);
+ xo_close_container("last-information");
+}
+
+/*
+ * doentry --
+ * process a single utx.log entry
+ */
+static void
+doentry(struct utmpx *bp)
+{
+ struct idtab *tt;
+
+ /* the machine stopped */
+ if (bp->ut_type == BOOT_TIME || bp->ut_type == SHUTDOWN_TIME) {
+ /* everybody just logged out */
+ while ((tt = SLIST_FIRST(&idlist)) != NULL) {
+ SLIST_REMOVE_HEAD(&idlist, list);
+ free(tt);
+ }
+ currentout = -bp->ut_tv.tv_sec;
+ crmsg = bp->ut_type != SHUTDOWN_TIME ?
+ "crash" : "shutdown";
+ /*
+ * if we're in snapshot mode, we want to exit if this
+ * shutdown/reboot appears while we are tracking the
+ * active range
+ */
+ if (snaptime && snapfound) {
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_SUCCESS);
+ }
+ /*
+ * don't print shutdown/reboot entries unless flagged for
+ */
+ if (!snaptime && want(bp))
+ printentry(bp, NULL);
+ return;
+ }
+ /* date got set */
+ if (bp->ut_type == OLD_TIME || bp->ut_type == NEW_TIME) {
+ if (want(bp) && !snaptime)
+ printentry(bp, NULL);
+ return;
+ }
+
+ if (bp->ut_type != USER_PROCESS && bp->ut_type != DEAD_PROCESS)
+ return;
+
+ /* find associated identifier */
+ SLIST_FOREACH(tt, &idlist, list)
+ if (!memcmp(tt->id, bp->ut_id, sizeof bp->ut_id))
+ break;
+
+ if (tt == NULL) {
+ /* add new one */
+ tt = malloc(sizeof(struct idtab));
+ if (tt == NULL)
+ xo_errx(1, "malloc failure");
+ tt->logout = currentout;
+ memcpy(tt->id, bp->ut_id, sizeof bp->ut_id);
+ SLIST_INSERT_HEAD(&idlist, tt, list);
+ }
+
+ /*
+ * print record if not in snapshot mode and wanted
+ * or in snapshot mode and in snapshot range
+ */
+ if (bp->ut_type == USER_PROCESS && (want(bp) ||
+ (bp->ut_tv.tv_sec < snaptime &&
+ (tt->logout > snaptime || tt->logout < 1)))) {
+ snapfound = 1;
+ printentry(bp, tt);
+ }
+ tt->logout = bp->ut_tv.tv_sec;
+}
+
+/*
+ * printentry --
+ * output an entry
+ *
+ * If `tt' is non-NULL, use it and `crmsg' to print the logout time or
+ * logout type (crash/shutdown) as appropriate.
+ */
+static void
+printentry(struct utmpx *bp, struct idtab *tt)
+{
+ char ct[80];
+ struct tm *tm;
+ time_t delta; /* time difference */
+ time_t t;
+
+ if (maxrec != -1 && !maxrec--) {
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_SUCCESS);
+ }
+ xo_open_instance("last");
+ t = bp->ut_tv.tv_sec;
+ tm = localtime(&t);
+ (void) strftime(ct, sizeof(ct), d_first ?
+ (yflag ? "%a %e %b %Y %R" : "%a %e %b %R") :
+ (yflag ? "%a %b %e %Y %R" : "%a %b %e %R"), tm);
+ switch (bp->ut_type) {
+ case BOOT_TIME:
+ xo_emit("{:user/%-42s/%s}", "boot time");
+ break;
+ case SHUTDOWN_TIME:
+ xo_emit("{:user/%-42s/%s}", "shutdown time");
+ break;
+ case OLD_TIME:
+ xo_emit("{:user/%-42s/%s}", "old time");
+ break;
+ case NEW_TIME:
+ xo_emit("{:user/%-42s/%s}", "new time");
+ break;
+ case USER_PROCESS:
+ xo_emit("{:user/%-10s/%s} {:tty/%-8s/%s} {:from/%-22.22s/%s}",
+ bp->ut_user, bp->ut_line, bp->ut_host);
+ break;
+ }
+ xo_attr("seconds", "%lu", (unsigned long)t);
+ xo_emit(" {:login-time/%hs%c/%s}", ct, tt == NULL ? '\n' : ' ');
+ if (tt == NULL)
+ goto end;
+ if (!tt->logout) {
+ xo_emit(" {:logout-time/still logged in}\n");
+ goto end;
+ }
+ if (tt->logout < 0) {
+ tt->logout = -tt->logout;
+ xo_emit("- {:logout-reason/%s}", crmsg);
+ } else {
+ tm = localtime(&tt->logout);
+ (void) strftime(ct, sizeof(ct), "%R", tm);
+ xo_attr("seconds", "%lu", (unsigned long)tt->logout);
+ xo_emit("- {:logout-time/%s}", ct);
+ }
+ delta = tt->logout - bp->ut_tv.tv_sec;
+ xo_attr("seconds", "%ld", (long)delta);
+ if (sflag) {
+ xo_emit(" ({:session-length/%8ld})\n", (long)delta);
+ } else {
+ tm = gmtime(&delta);
+ (void) strftime(ct, sizeof(ct), width >= 8 ? "%T" : "%R", tm);
+ if (delta < 86400)
+ xo_emit(" ({:session-length/%s})\n", ct);
+ else
+ xo_emit(" ({:session-length/%ld+%s})\n",
+ (long)delta / 86400, ct);
+ }
+
+end:
+ xo_close_instance("last");
+}
+
+/*
+ * want --
+ * see if want this entry
+ */
+static int
+want(struct utmpx *bp)
+{
+ ARG *step;
+
+ if (snaptime)
+ return (NO);
+
+ if (!arglist)
+ return (YES);
+
+ for (step = arglist; step; step = step->next)
+ switch(step->type) {
+ case REBOOT_TYPE:
+ if (bp->ut_type == BOOT_TIME ||
+ bp->ut_type == SHUTDOWN_TIME)
+ return (YES);
+ break;
+ case HOST_TYPE:
+ if (!strcasecmp(step->name, bp->ut_host))
+ return (YES);
+ break;
+ case TTY_TYPE:
+ if (!strcmp(step->name, bp->ut_line))
+ return (YES);
+ break;
+ case USER_TYPE:
+ if (!strcmp(step->name, bp->ut_user))
+ return (YES);
+ break;
+ }
+ return (NO);
+}
+
+/*
+ * addarg --
+ * add an entry to a linked list of arguments
+ */
+static void
+addarg(int type, char *arg)
+{
+ ARG *cur;
+
+ if ((cur = malloc(sizeof(ARG))) == NULL)
+ xo_errx(1, "malloc failure");
+ cur->next = arglist;
+ cur->type = type;
+ cur->name = arg;
+ arglist = cur;
+}
+
+/*
+ * hostconv --
+ * convert the hostname to search pattern; if the supplied host name
+ * has a domain attached that is the same as the current domain, rip
+ * off the domain suffix since that's what login(1) does.
+ */
+static void
+hostconv(char *arg)
+{
+ static int first = 1;
+ static char *hostdot, name[MAXHOSTNAMELEN];
+ char *argdot;
+
+ if (!(argdot = strchr(arg, '.')))
+ return;
+ if (first) {
+ first = 0;
+ if (gethostname(name, sizeof(name)))
+ xo_err(1, "gethostname");
+ hostdot = strchr(name, '.');
+ }
+ if (hostdot && !strcasecmp(hostdot, argdot))
+ *argdot = '\0';
+}
+
+/*
+ * ttyconv --
+ * convert tty to correct name.
+ */
+static char *
+ttyconv(char *arg)
+{
+ char *mval;
+
+ /*
+ * kludge -- we assume that all tty's end with
+ * a two character suffix.
+ */
+ if (strlen(arg) == 2) {
+ /* either 6 for "ttyxx" or 8 for "console" */
+ if ((mval = malloc(8)) == NULL)
+ xo_errx(1, "malloc failure");
+ if (!strcmp(arg, "co"))
+ (void)strcpy(mval, "console");
+ else {
+ (void)strcpy(mval, "tty");
+ (void)strcpy(mval + 3, arg);
+ }
+ return (mval);
+ }
+ if (!strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1))
+ return (arg + 5);
+ return (arg);
+}
+
+/*
+ * dateconv --
+ * Convert the snapshot time in command line given in the format
+ * [[CC]YY]MMDDhhmm[.SS]] to a time_t.
+ * Derived from atime_arg1() in usr.bin/touch/touch.c
+ */
+static time_t
+dateconv(char *arg)
+{
+ time_t timet;
+ struct tm *t;
+ int yearset;
+ char *p;
+
+ /* Start with the current time. */
+ if (time(&timet) < 0)
+ xo_err(1, "time");
+ if ((t = localtime(&timet)) == NULL)
+ xo_err(1, "localtime");
+
+ /* [[CC]YY]MMDDhhmm[.SS] */
+ if ((p = strchr(arg, '.')) == NULL)
+ t->tm_sec = 0; /* Seconds defaults to 0. */
+ else {
+ if (strlen(p + 1) != 2)
+ goto terr;
+ *p++ = '\0';
+ t->tm_sec = ATOI2(p);
+ }
+
+ yearset = 0;
+ switch (strlen(arg)) {
+ case 12: /* CCYYMMDDhhmm */
+ t->tm_year = ATOI2(arg);
+ t->tm_year *= 100;
+ yearset = 1;
+ /* FALLTHROUGH */
+ case 10: /* YYMMDDhhmm */
+ if (yearset) {
+ yearset = ATOI2(arg);
+ t->tm_year += yearset;
+ } else {
+ yearset = ATOI2(arg);
+ if (yearset < 69)
+ t->tm_year = yearset + 2000;
+ else
+ t->tm_year = yearset + 1900;
+ }
+ t->tm_year -= 1900; /* Convert to UNIX time. */
+ /* FALLTHROUGH */
+ case 8: /* MMDDhhmm */
+ t->tm_mon = ATOI2(arg);
+ --t->tm_mon; /* Convert from 01-12 to 00-11 */
+ t->tm_mday = ATOI2(arg);
+ t->tm_hour = ATOI2(arg);
+ t->tm_min = ATOI2(arg);
+ break;
+ case 4: /* hhmm */
+ t->tm_hour = ATOI2(arg);
+ t->tm_min = ATOI2(arg);
+ break;
+ default:
+ goto terr;
+ }
+ t->tm_isdst = -1; /* Figure out DST. */
+ timet = mktime(t);
+ if (timet == -1)
+terr: xo_errx(1,
+ "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]");
+ return timet;
+}
diff --git a/usr.bin/lastcomm/Makefile b/usr.bin/lastcomm/Makefile
new file mode 100644
index 000000000000..48c49cc2df3d
--- /dev/null
+++ b/usr.bin/lastcomm/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PACKAGE=acct
+
+PROG= lastcomm
+SRCS= lastcomm.c readrec.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lastcomm/Makefile.depend b/usr.bin/lastcomm/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/lastcomm/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lastcomm/lastcomm.1 b/usr.bin/lastcomm/lastcomm.1
new file mode 100644
index 000000000000..4333c79dd1f5
--- /dev/null
+++ b/usr.bin/lastcomm/lastcomm.1
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd May 17, 2012
+.Dt LASTCOMM 1
+.Os
+.Sh NAME
+.Nm lastcomm
+.Nd show last commands executed
+.Sh SYNOPSIS
+.Nm
+.Op Fl EScesu
+.Op Fl f Ar file
+.Op Cm + Ns Ar format
+.Op Ar command ...\&
+.Op Ar user ...\&
+.Op Ar terminal ...\&
+.Sh DESCRIPTION
+The
+.Nm
+utility gives information on previously executed commands.
+With no arguments,
+.Nm
+prints information about all the commands recorded
+during the current accounting file's lifetime.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl E
+Print the time the process exited.
+.It Fl S
+Print the time the process started.
+.It Fl c
+Print the amount of cpu time used by the process.
+.It Fl e
+Print the amount of elapsed time used by the process.
+.It Fl s
+Print the amount of system time used by the process.
+.It Fl u
+Print the amount of user time used by the process.
+.It Fl f Ar file
+Read from
+.Ar file
+rather than the default
+.Pa /var/account/acct .
+If
+.Ar file
+is a single dash
+.Pq Sq \&-
+.Nm
+reads accounting entries from the standard input.
+.El
+.Pp
+An operand with a leading plus sign
+.Pq Sq +
+is followed a user-defined format string which specifies the format
+in which to display the process's start or exit date and time.
+The format string may contain any of the conversion specifications
+described in the
+.Xr strftime 3
+manual page, as well as arbitrary text.
+.Pp
+If no options are specified,
+.Fl cS
+is assumed.
+If
+.Nm
+is invoked with arguments, only accounting entries with a
+matching
+.Ar command
+name,
+.Ar user
+name,
+or
+.Ar terminal
+name
+are printed.
+For example:
+.Pp
+.Dl lastcomm a.out root ttyd0
+.Pp
+would produce a listing of all the
+executions of commands named
+.Pa a.out
+by user
+.Ar root
+on the terminal
+.Ar ttyd0 .
+.Pp
+For each process entry, the following are printed.
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+The name of the user who ran the process.
+.It
+Flags, as accumulated by the accounting facilities in the system.
+.It
+The command name under which the process was called.
+.It
+The amount of
+CPU
+.Pq Fl c ,
+wall
+.Pq Fl e ,
+system
+.Pq Fl s ,
+or user
+.Pq Fl u
+time used by the process (in seconds).
+.It
+The time the process started
+.Pq Fl S
+or exited
+.Pq Fl E .
+.El
+.Pp
+The flags are encoded as follows: ``S'' indicates the command was
+executed by the super-user, ``F'' indicates the command ran after
+a fork, but without a following
+.Xr exec 3 ,
+.\" ``C'' indicates the command was run in PDP-11 compatibility mode
+.\" (VAX only),
+``D'' indicates the command terminated with the generation of a
+.Pa core
+file, and ``X'' indicates the command was terminated with a signal.
+.Pp
+By default, accounting entries are printed going backwards in time,
+starting from the time
+.Nm
+was executed.
+However, if
+.Nm
+reads entries from its standard input, then entries are printed in
+the order they are read.
+.Sh FILES
+.Bl -tag -width /var/account/acct -compact
+.It Pa /var/account/acct
+default accounting file
+.El
+.Sh EXAMPLES
+The command
+.Dl lastcomm -Ee
+will print the exit time and elapsed time of each command logged in
+.Pa /var/account/acct ,
+while
+.Dl tail -f -c 0 /var/account/acct | lastcomm -f -
+will print details of each terminating command.
+.Sh SEE ALSO
+.Xr last 1 ,
+.Xr sigaction 2 ,
+.Xr strftime 3 ,
+.Xr acct 5 ,
+.Xr core 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/lastcomm/lastcomm.c b/usr.bin/lastcomm/lastcomm.c
new file mode 100644
index 000000000000..36ef0bbb992e
--- /dev/null
+++ b/usr.bin/lastcomm/lastcomm.c
@@ -0,0 +1,263 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/acct.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include "pathnames.h"
+
+/*XXX*/#include <inttypes.h>
+
+time_t expand(u_int);
+char *flagbits(int);
+const char *getdev(dev_t);
+int readrec_forward(FILE *f, struct acctv3 *av3);
+int readrec_backward(FILE *f, struct acctv3 *av3);
+int requested(char *[], struct acctv3 *);
+static void usage(void);
+
+#define AC_UTIME 1 /* user */
+#define AC_STIME 2 /* system */
+#define AC_ETIME 4 /* elapsed */
+#define AC_CTIME 8 /* user + system time, default */
+
+#define AC_BTIME 16 /* starting time */
+#define AC_FTIME 32 /* exit time (starting time + elapsed time )*/
+
+int
+main(int argc, char *argv[])
+{
+ struct acctv3 ab;
+ char *p;
+ FILE *fp;
+ int (*readrec)(FILE *f, struct acctv3 *av3);
+ time_t t;
+ int ch, rv;
+ const char *acctfile, *format;
+ char buf[1024];
+ int flags = 0;
+
+ acctfile = _PATH_ACCT;
+ format = NULL;
+ while ((ch = getopt(argc, argv, "f:usecSE")) != -1)
+ switch((char)ch) {
+ case 'f':
+ acctfile = optarg;
+ break;
+
+ case 'u':
+ flags |= AC_UTIME; /* user time */
+ break;
+ case 's':
+ flags |= AC_STIME; /* system time */
+ break;
+ case 'e':
+ flags |= AC_ETIME; /* elapsed time */
+ break;
+ case 'c':
+ flags |= AC_CTIME; /* user + system time */
+ break;
+
+ case 'S':
+ flags |= AC_BTIME; /* starting time */
+ break;
+ case 'E':
+ /* exit time (starting time + elapsed time )*/
+ flags |= AC_FTIME;
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+
+ /* default user + system time and starting time */
+ if (!flags) {
+ flags = AC_CTIME | AC_BTIME;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0 && **argv == '+') {
+ format = *argv + 1; /* skip + */
+ argc--;
+ argv++;
+ }
+
+ if (strcmp(acctfile, "-") == 0) {
+ fp = stdin;
+ readrec = readrec_forward;
+ } else {
+ /* Open the file. */
+ if ((fp = fopen(acctfile, "r")) == NULL)
+ err(1, "could not open %s", acctfile);
+ if (fseek(fp, 0l, SEEK_END) == -1)
+ err(1, "seek to end of %s failed", acctfile);
+ readrec = readrec_backward;
+ }
+
+ while ((rv = readrec(fp, &ab)) == 1) {
+ for (p = &ab.ac_comm[0];
+ p < &ab.ac_comm[AC_COMM_LEN] && *p; ++p)
+ if (!isprint(*p))
+ *p = '?';
+
+ if (*argv && !requested(argv, &ab))
+ continue;
+
+ (void)printf("%-*.*s %-7s %-*s %-8s",
+ AC_COMM_LEN, AC_COMM_LEN, ab.ac_comm,
+ flagbits(ab.ac_flagx),
+ MAXLOGNAME - 1, user_from_uid(ab.ac_uid, 0),
+ getdev(ab.ac_tty));
+
+
+ /* user + system time */
+ if (flags & AC_CTIME) {
+ (void)printf(" %6.3f secs",
+ (ab.ac_utime + ab.ac_stime) / 1000000);
+ }
+
+ /* usr time */
+ if (flags & AC_UTIME) {
+ (void)printf(" %6.3f us", ab.ac_utime / 1000000);
+ }
+
+ /* system time */
+ if (flags & AC_STIME) {
+ (void)printf(" %6.3f sy", ab.ac_stime / 1000000);
+ }
+
+ /* elapsed time */
+ if (flags & AC_ETIME) {
+ (void)printf(" %8.3f es", ab.ac_etime / 1000000);
+ }
+
+ /* starting time */
+ if (flags & AC_BTIME) {
+ if (format != NULL) {
+ (void)strftime(buf, sizeof(buf), format,
+ localtime(&ab.ac_btime));
+ (void)printf(" %s", buf);
+ } else
+ (void)printf(" %.19s", ctime(&ab.ac_btime));
+ }
+
+ /* exit time (starting time + elapsed time )*/
+ if (flags & AC_FTIME) {
+ t = ab.ac_btime;
+ t += (time_t)(ab.ac_etime / 1000000);
+ if (format != NULL) {
+ (void)strftime(buf, sizeof(buf), format,
+ localtime(&t));
+ (void)printf(" %s", buf);
+ } else
+ (void)printf(" %.19s", ctime(&t));
+ }
+ printf("\n");
+ }
+ if (rv == EOF)
+ err(1, "read record from %s failed", acctfile);
+
+ if (fflush(stdout))
+ err(1, "stdout");
+ exit(0);
+}
+
+char *
+flagbits(int f)
+{
+ static char flags[20] = "-";
+ char *p;
+
+#define BIT(flag, ch) if (f & flag) *p++ = ch
+
+ p = flags + 1;
+ BIT(ASU, 'S');
+ BIT(AFORK, 'F');
+ BIT(ACOMPAT, 'C');
+ BIT(ACORE, 'D');
+ BIT(AXSIG, 'X');
+ *p = '\0';
+ return (flags);
+}
+
+int
+requested(char *argv[], struct acctv3 *acp)
+{
+ const char *p;
+
+ do {
+ p = user_from_uid(acp->ac_uid, 0);
+ if (!strcmp(p, *argv))
+ return (1);
+ if ((p = getdev(acp->ac_tty)) && !strcmp(p, *argv))
+ return (1);
+ if (!strncmp(acp->ac_comm, *argv, AC_COMM_LEN))
+ return (1);
+ } while (*++argv);
+ return (0);
+}
+
+const char *
+getdev(dev_t dev)
+{
+ static dev_t lastdev = (dev_t)-1;
+ static const char *lastname;
+
+ if (dev == NODEV) /* Special case. */
+ return ("__");
+ if (dev == lastdev) /* One-element cache. */
+ return (lastname);
+ lastdev = dev;
+ lastname = devname(dev, S_IFCHR);
+ return (lastname);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: lastcomm [-EScesu] [-f file] [+format] [command ...] "
+ "[user ...] [terminal ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/lastcomm/pathnames.h b/usr.bin/lastcomm/pathnames.h
new file mode 100644
index 000000000000..a6231d4aa181
--- /dev/null
+++ b/usr.bin/lastcomm/pathnames.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_ACCT "/var/account/acct"
diff --git a/usr.bin/lastcomm/readrec.c b/usr.bin/lastcomm/readrec.c
new file mode 100644
index 000000000000..a8665a6f76ac
--- /dev/null
+++ b/usr.bin/lastcomm/readrec.c
@@ -0,0 +1,262 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Diomidis Spinellis
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/acct.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+int readrec_forward(FILE *f, struct acctv3 *av2);
+int readrec_backward(FILE *f, struct acctv3 *av2);
+
+/*
+ * Reverse offsetof: return the offset of field f
+ * from the end of the structure s.
+ */
+#define roffsetof(s, f) (sizeof(s) - offsetof(s, f))
+
+/*
+ * Read exactly one record of size size from stream f into ptr.
+ * Failure to read the complete record is considered a file format error,
+ * and will set errno to EFTYPE.
+ * Return 0 on success, EOF on end of file or error.
+ */
+static int
+fread_record(void *ptr, size_t size, FILE *f)
+{
+ size_t rv;
+
+ if ((rv = fread(ptr, 1, size, f)) == size)
+ return (0);
+ else if (ferror(f) || rv == 0)
+ return (EOF);
+ else {
+ /* Short read. */
+ errno = EFTYPE;
+ return (EOF);
+ }
+}
+
+/*
+ * Return the value of a comp_t field.
+ */
+static float
+decode_comp(comp_t v)
+{
+ int result, exp;
+
+ result = v & 017777;
+ for (exp = v >> 13; exp; exp--)
+ result <<= 3;
+ return ((double)result / AHZV1);
+}
+
+/*
+ * Read a v1 accounting record stored at the current
+ * position of stream f.
+ * Convert the data to the current record format.
+ * Return EOF on error or end-of-file.
+ */
+static int
+readrec_v1(FILE *f, struct acctv3 *av3)
+{
+ struct acctv1 av1;
+ int rv;
+
+ if ((rv = fread_record(&av1, sizeof(av1), f)) == EOF)
+ return (EOF);
+ av3->ac_zero = 0;
+ av3->ac_version = 3;
+ av3->ac_len = av3->ac_len2 = sizeof(*av3);
+ memcpy(av3->ac_comm, av1.ac_comm, AC_COMM_LEN);
+ av3->ac_utime = decode_comp(av1.ac_utime) * 1000000;
+ av3->ac_stime = decode_comp(av1.ac_stime) * 1000000;
+ av3->ac_etime = decode_comp(av1.ac_etime) * 1000000;
+ av3->ac_btime = av1.ac_btime;
+ av3->ac_uid = av1.ac_uid;
+ av3->ac_gid = av1.ac_gid;
+ av3->ac_mem = av1.ac_mem;
+ av3->ac_io = decode_comp(av1.ac_io);
+ av3->ac_tty = av1.ac_tty;
+ av3->ac_flagx = av1.ac_flag | ANVER;
+ return (0);
+}
+
+/*
+ * Read an v2 accounting record stored at the current
+ * position of stream f.
+ * Return EOF on error or end-of-file.
+ */
+static int
+readrec_v2(FILE *f, struct acctv3 *av3)
+{
+ struct acctv2 av2;
+ int rv;
+
+ if ((rv = fread_record(&av2, sizeof(av2), f)) == EOF)
+ return (EOF);
+ av3->ac_zero = 0;
+ av3->ac_version = 3;
+ av3->ac_len = av3->ac_len2 = sizeof(*av3);
+ memcpy(av3->ac_comm, av2.ac_comm, AC_COMM_LEN);
+ av3->ac_utime = av2.ac_utime;
+ av3->ac_stime = av2.ac_stime;
+ av3->ac_etime = av2.ac_etime;
+ av3->ac_btime = av2.ac_btime;
+ av3->ac_uid = av2.ac_uid;
+ av3->ac_gid = av2.ac_gid;
+ av3->ac_mem = av2.ac_mem;
+ av3->ac_io = av2.ac_io;
+ av3->ac_tty = av2.ac_tty;
+ av3->ac_flagx = av2.ac_flagx;
+ return (0);
+}
+
+/*
+ * Read an v2 accounting record stored at the current
+ * position of stream f.
+ * Return EOF on error or end-of-file.
+ */
+static int
+readrec_v3(FILE *f, struct acctv3 *av3)
+{
+
+ return (fread_record(av3, sizeof(*av3), f));
+}
+
+/*
+ * Read a new-style (post-v1) accounting record stored at
+ * the current position of stream f.
+ * Convert the data to the current record format.
+ * Return EOF on error or end-of-file.
+ */
+static int
+readrec_vx(FILE *f, struct acctv3 *av3)
+{
+ uint8_t magic, version;
+
+ if (fread_record(&magic, sizeof(magic), f) == EOF ||
+ fread_record(&version, sizeof(version), f) == EOF ||
+ ungetc(version, f) == EOF ||
+ ungetc(magic, f) == EOF)
+ return (EOF);
+ switch (version) {
+ case 2:
+ return (readrec_v2(f, av3));
+ case 3:
+ return (readrec_v3(f, av3));
+
+ /* Add handling for more versions here. */
+
+ default:
+ errno = EFTYPE;
+ return (EOF);
+ }
+}
+
+/*
+ * Read an accounting record stored at the current
+ * position of stream f.
+ * Old-format records are converted to the current record
+ * format.
+ * Return the number of records read (1 or 0 at the end-of-file),
+ * or EOF on error.
+ */
+int
+readrec_forward(FILE *f, struct acctv3 *av3)
+{
+ int magic, rv;
+
+ if ((magic = getc(f)) == EOF)
+ return (ferror(f) ? EOF : 0);
+ if (ungetc(magic, f) == EOF)
+ return (EOF);
+ if (magic != 0)
+ /* Old record format. */
+ rv = readrec_v1(f, av3);
+ else
+ /* New record formats. */
+ rv = readrec_vx(f, av3);
+ return (rv == EOF ? EOF : 1);
+}
+
+/*
+ * Read an accounting record ending at the current
+ * position of stream f.
+ * Old-format records are converted to the current record
+ * format.
+ * The file pointer is positioned at the beginning of the
+ * record read.
+ * Return the number of records read (1 or 0 at the end-of-file),
+ * or EOF on error.
+ */
+int
+readrec_backward(FILE *f, struct acctv3 *av3)
+{
+ off_t pos;
+ int c;
+ uint16_t len;
+
+ if ((pos = ftell(f)) == -1)
+ return (EOF);
+ if (pos == 0)
+ return (0);
+ if (fseek(f, -roffsetof(struct acctv3, ac_trailer),
+ SEEK_CUR) == EOF ||
+ (c = getc(f)) == EOF)
+ return (EOF);
+ if (c & ANVER) {
+ /*
+ * New record formats. For v2 and v3 offset from the
+ * end for ac_len2 should be same.
+ */
+ if (fseeko(f, pos - roffsetof(struct acctv2, ac_len2),
+ SEEK_SET) == EOF ||
+ fread_record(&len, sizeof(len), f) == EOF ||
+ fseeko(f, pos - len, SEEK_SET) == EOF ||
+ readrec_vx(f, av3) == EOF ||
+ fseeko(f, pos - len, SEEK_SET) == EOF)
+ return (EOF);
+ else
+ return (1);
+ } else {
+ /* Old record format. */
+ if (fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF ||
+ readrec_v1(f, av3) == EOF ||
+ fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF)
+ return (EOF);
+ else
+ return (1);
+ }
+}
diff --git a/usr.bin/lastcomm/tests/Makefile b/usr.bin/lastcomm/tests/Makefile
new file mode 100644
index 000000000000..8a00382979b1
--- /dev/null
+++ b/usr.bin/lastcomm/tests/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+TEST_METADATA.legacy_test+= allowed_architectures="amd64 i386"
+
+${PACKAGE}FILES+= v1-amd64-acct.in
+${PACKAGE}FILES+= v1-amd64.out
+${PACKAGE}FILES+= v1-i386-acct.in
+${PACKAGE}FILES+= v1-i386.out
+${PACKAGE}FILES+= v2-amd64-acct.in
+${PACKAGE}FILES+= v2-amd64.out
+${PACKAGE}FILES+= v2-i386-acct.in
+${PACKAGE}FILES+= v2-i386.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/lastcomm/tests/Makefile.depend b/usr.bin/lastcomm/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/lastcomm/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lastcomm/tests/README b/usr.bin/lastcomm/tests/README
new file mode 100644
index 000000000000..1617d04adfb3
--- /dev/null
+++ b/usr.bin/lastcomm/tests/README
@@ -0,0 +1,9 @@
+
+To create the files for regression testing do the following.
+
+1. Run values.sh for a given architecture and accounting version.
+2. Unpack the generated file and rename acct into VERSION-ARCH.acct.
+3. Run lastcomm -cuseS -f VERSION-ARCH-acct.in |
+ awk '{$4 = ""; print}' >VERSION-ARCH.out.
+4. Compare the reported values in VERSION-ARCH.out against the
+ *.time values found in the file that values.sh generated.
diff --git a/usr.bin/lastcomm/tests/legacy_test.sh b/usr.bin/lastcomm/tests/legacy_test.sh
new file mode 100644
index 000000000000..d890db590e14
--- /dev/null
+++ b/usr.bin/lastcomm/tests/legacy_test.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+#
+
+DIR=`dirname $0`
+ARCH=`uname -m`
+
+TZ=UTC; export TZ
+
+check()
+{
+ NUM=$1
+ shift
+ # Remove tty field, which varies between systems.
+ awk '{$4 = ""; print}' |
+ if diff -a - $1 >&2
+ then
+ echo "ok $NUM"
+ else
+ echo "not ok $NUM"
+ fi
+}
+
+
+cat $DIR/v1-$ARCH-acct.in $DIR/v2-$ARCH-acct.in >v1v2-$ARCH-acct.in
+cat $DIR/v2-$ARCH.out $DIR/v1-$ARCH.out >v1v2-$ARCH.out
+
+echo 1..6
+
+lastcomm -cesuS -f $DIR/v1-$ARCH-acct.in | check 1 $DIR/v1-$ARCH.out
+lastcomm -cesuS -f - <$DIR/v1-$ARCH-acct.in | tail -r | check 2 $DIR/v1-$ARCH.out
+lastcomm -cesuS -f $DIR/v2-$ARCH-acct.in | check 3 $DIR/v2-$ARCH.out
+lastcomm -cesuS -f - <$DIR/v2-$ARCH-acct.in | tail -r | check 4 $DIR/v2-$ARCH.out
+lastcomm -cesuS -f v1v2-$ARCH-acct.in | check 5 v1v2-$ARCH.out
+lastcomm -cesuS -f - <v1v2-$ARCH-acct.in | tail -r | check 6 v1v2-$ARCH.out
+
+exit 0
diff --git a/usr.bin/lastcomm/tests/v1-amd64-acct.in b/usr.bin/lastcomm/tests/v1-amd64-acct.in
new file mode 100644
index 000000000000..50546a3f1b86
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v1-amd64-acct.in
Binary files differ
diff --git a/usr.bin/lastcomm/tests/v1-amd64.out b/usr.bin/lastcomm/tests/v1-amd64.out
new file mode 100644
index 000000000000..a71556d771ca
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v1-amd64.out
@@ -0,0 +1,28 @@
+core -FDX root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+core -DX root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+cc - root 0.000 secs 0.000 us 0.000 sy 0.016 es Wed May 16 11:44:38
+ld - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+as - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+cc1 - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time -F root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time -F root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time -F root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:38
+time - root 0.000 secs 0.000 us 0.000 sy 0.234 es Wed May 16 11:44:38
+diff - root 0.203 secs 0.203 us 0.000 sy 0.234 es Wed May 16 11:44:38
+time - root 0.000 secs 0.000 us 0.000 sy 0.016 es Wed May 16 11:44:37
+dd - root 0.016 secs 0.000 us 0.016 sy 0.016 es Wed May 16 11:44:37
+time - root 0.000 secs 0.000 us 0.000 sy 3.016 es Wed May 16 11:44:34
+sleep - root 0.000 secs 0.000 us 0.000 sy 3.000 es Wed May 16 11:44:34
+time - root 0.000 secs 0.000 us 0.000 sy 1.938 es Wed May 16 11:44:33
+find - root 0.250 secs 0.031 us 0.219 sy 1.938 es Wed May 16 11:44:33
+time - root 0.000 secs 0.000 us 0.000 sy 3.062 es Wed May 16 11:44:29
+egrep - root 3.031 secs 3.031 us 0.000 sy 3.062 es Wed May 16 11:44:29
+time - root 0.000 secs 0.000 us 0.000 sy 0.188 es Wed May 16 11:44:29
+awk - root 0.172 secs 0.172 us 0.000 sy 0.188 es Wed May 16 11:44:29
+accton - root 0.000 secs 0.000 us 0.000 sy 0.000 es Wed May 16 11:44:29
diff --git a/usr.bin/lastcomm/tests/v1-i386-acct.in b/usr.bin/lastcomm/tests/v1-i386-acct.in
new file mode 100644
index 000000000000..f427c0ece3d7
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v1-i386-acct.in
Binary files differ
diff --git a/usr.bin/lastcomm/tests/v1-i386.out b/usr.bin/lastcomm/tests/v1-i386.out
new file mode 100644
index 000000000000..e30c5c7cfc2c
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v1-i386.out
@@ -0,0 +1,28 @@
+core -FDX root 0.000 secs 0.000 us 0.000 sy 0.031 es Fri May 18 08:34:08
+core -DX root 0.000 secs 0.000 us 0.000 sy 0.031 es Fri May 18 08:34:08
+cc - root 0.000 secs 0.000 us 0.000 sy 0.469 es Fri May 18 08:34:07
+ld - root 0.000 secs 0.000 us 0.000 sy 0.109 es Fri May 18 08:34:08
+as - root 0.000 secs 0.000 us 0.000 sy 0.047 es Fri May 18 08:34:08
+cc1 - root 0.016 secs 0.016 us 0.000 sy 0.203 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+1234567890123456 - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+1234567890123456 - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+123456789012345 - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+ln - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 0.359 es Fri May 18 08:34:07
+diff - root 0.312 secs 0.297 us 0.016 sy 0.359 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 0.031 es Fri May 18 08:34:07
+dd - root 0.016 secs 0.000 us 0.016 sy 0.031 es Fri May 18 08:34:07
+time - root 0.000 secs 0.000 us 0.000 sy 3.000 es Fri May 18 08:34:04
+sleep - root 0.000 secs 0.000 us 0.000 sy 3.000 es Fri May 18 08:34:04
+time - root 0.000 secs 0.000 us 0.000 sy 3.406 es Fri May 18 08:34:00
+find - root 0.266 secs 0.062 us 0.203 sy 3.406 es Fri May 18 08:34:00
+time - root 0.000 secs 0.000 us 0.000 sy 5.047 es Fri May 18 08:33:55
+egrep - root 4.984 secs 4.984 us 0.000 sy 5.047 es Fri May 18 08:33:55
+time - root 0.000 secs 0.000 us 0.000 sy 0.484 es Fri May 18 08:33:55
+awk - root 0.453 secs 0.453 us 0.000 sy 0.453 es Fri May 18 08:33:55
+accton - root 0.000 secs 0.000 us 0.000 sy 0.000 es Fri May 18 08:33:55
diff --git a/usr.bin/lastcomm/tests/v2-amd64-acct.in b/usr.bin/lastcomm/tests/v2-amd64-acct.in
new file mode 100644
index 000000000000..ca7bcaa66f78
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v2-amd64-acct.in
Binary files differ
diff --git a/usr.bin/lastcomm/tests/v2-amd64.out b/usr.bin/lastcomm/tests/v2-amd64.out
new file mode 100644
index 000000000000..4fcf219eef7d
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v2-amd64.out
@@ -0,0 +1,28 @@
+core -FDX root 0.002 secs 0.000 us 0.002 sy 0.009 es Thu May 17 05:57:17
+core -DX root 0.005 secs 0.000 us 0.005 sy 0.010 es Thu May 17 05:57:17
+cc - root 0.005 secs 0.000 us 0.005 sy 0.652 es Thu May 17 05:57:16
+ld - root 0.014 secs 0.005 us 0.009 sy 0.150 es Thu May 17 05:57:17
+as - root 0.005 secs 0.000 us 0.005 sy 0.078 es Thu May 17 05:57:17
+cc1 - root 0.024 secs 0.008 us 0.016 sy 0.347 es Thu May 17 05:57:17
+time - root 0.003 secs 0.000 us 0.003 sy 0.005 es Thu May 17 05:57:16
+1234567890123456 - root 0.002 secs 0.000 us 0.002 sy 0.002 es Thu May 17 05:57:16
+ln - root 0.002 secs 0.000 us 0.002 sy 0.002 es Thu May 17 05:57:16
+time - root 0.003 secs 0.000 us 0.003 sy 0.005 es Thu May 17 05:57:16
+1234567890123456 - root 0.002 secs 0.000 us 0.002 sy 0.002 es Thu May 17 05:57:16
+ln - root 0.002 secs 0.000 us 0.002 sy 0.002 es Thu May 17 05:57:16
+time - root 0.003 secs 0.000 us 0.003 sy 0.013 es Thu May 17 05:57:16
+123456789012345 - root 0.002 secs 0.000 us 0.002 sy 0.010 es Thu May 17 05:57:16
+ln - root 0.003 secs 0.000 us 0.003 sy 0.003 es Thu May 17 05:57:16
+time - root 0.003 secs 0.000 us 0.003 sy 0.246 es Thu May 17 05:57:16
+diff - root 0.223 secs 0.164 us 0.060 sy 0.243 es Thu May 17 05:57:16
+time - root 0.003 secs 0.000 us 0.003 sy 0.079 es Thu May 17 05:57:16
+dd - root 0.076 secs 0.000 us 0.076 sy 0.076 es Thu May 17 05:57:16
+time - root 0.004 secs 0.000 us 0.004 sy 3.006 es Thu May 17 05:57:13
+sleep - root 0.002 secs 0.000 us 0.002 sy 3.002 es Thu May 17 05:57:13
+time - root 0.003 secs 0.000 us 0.003 sy 9.945 es Thu May 17 05:57:03
+find - root 0.822 secs 0.055 us 0.767 sy 9.942 es Thu May 17 05:57:03
+time - root 0.003 secs 0.000 us 0.003 sy 3.313 es Thu May 17 05:57:00
+egrep - root 3.247 secs 3.247 us 0.000 sy 3.310 es Thu May 17 05:57:00
+time - root 0.003 secs 0.000 us 0.003 sy 0.185 es Thu May 17 05:57:00
+awk - root 0.163 secs 0.156 us 0.007 sy 0.164 es Thu May 17 05:57:00
+accton - root 0.002 secs 0.000 us 0.002 sy 0.019 es Thu May 17 05:57:00
diff --git a/usr.bin/lastcomm/tests/v2-i386-acct.in b/usr.bin/lastcomm/tests/v2-i386-acct.in
new file mode 100644
index 000000000000..4cdd97330947
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v2-i386-acct.in
Binary files differ
diff --git a/usr.bin/lastcomm/tests/v2-i386.out b/usr.bin/lastcomm/tests/v2-i386.out
new file mode 100644
index 000000000000..7200c1f9dfe8
--- /dev/null
+++ b/usr.bin/lastcomm/tests/v2-i386.out
@@ -0,0 +1,28 @@
+core -FDX root 0.000 secs 0.000 us 0.000 sy 0.005 es Fri May 18 12:13:04
+core -DX root 0.002 secs 0.000 us 0.002 sy 0.005 es Fri May 18 12:13:04
+cc - root 0.002 secs 0.000 us 0.002 sy 0.048 es Fri May 18 12:13:03
+ld - root 0.028 secs 0.019 us 0.009 sy 0.028 es Fri May 18 12:13:04
+as - root 0.002 secs 0.002 us 0.000 sy 0.002 es Fri May 18 12:13:04
+cc1 - root 0.016 secs 0.016 us 0.000 sy 0.016 es Fri May 18 12:13:03
+time - root 0.001 secs 0.000 us 0.001 sy 0.002 es Fri May 18 12:13:03
+1234567890123456 - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+ln - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+time - root 0.001 secs 0.001 us 0.000 sy 0.002 es Fri May 18 12:13:03
+1234567890123456 - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+ln - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+time - root 0.001 secs 0.000 us 0.001 sy 0.002 es Fri May 18 12:13:03
+123456789012345 - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+ln - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:13:03
+time - root 0.001 secs 0.000 us 0.001 sy 0.425 es Fri May 18 12:13:03
+diff - root 0.423 secs 0.392 us 0.031 sy 0.424 es Fri May 18 12:13:03
+time - root 0.001 secs 0.000 us 0.001 sy 0.028 es Fri May 18 12:13:03
+dd - root 0.025 secs 0.000 us 0.025 sy 0.026 es Fri May 18 12:13:03
+time - root 0.001 secs 0.000 us 0.001 sy 3.002 es Fri May 18 12:13:00
+sleep - root 0.001 secs 0.000 us 0.001 sy 3.001 es Fri May 18 12:13:00
+time - root 0.001 secs 0.000 us 0.001 sy 0.250 es Fri May 18 12:13:00
+find - root 0.248 secs 0.078 us 0.171 sy 0.249 es Fri May 18 12:13:00
+time - root 0.001 secs 0.000 us 0.001 sy 6.724 es Fri May 18 12:12:53
+egrep - root 6.680 secs 6.680 us 0.000 sy 6.722 es Fri May 18 12:12:53
+time - root 0.001 secs 0.000 us 0.001 sy 0.450 es Fri May 18 12:12:53
+awk - root 0.448 secs 0.448 us 0.000 sy 0.449 es Fri May 18 12:12:53
+accton - root 0.001 secs 0.000 us 0.001 sy 0.001 es Fri May 18 12:12:53
diff --git a/usr.bin/lastcomm/tests/values.sh b/usr.bin/lastcomm/tests/values.sh
new file mode 100755
index 000000000000..e5756f479a58
--- /dev/null
+++ b/usr.bin/lastcomm/tests/values.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+#
+
+ACCT=acct
+RESULTS=acct.`uname -m`.tar.gz
+TMPDIR=$$.tmp
+TZ=UTC; export TZ
+
+run()
+{
+ /usr/bin/time -l -o $1.time "$@"
+}
+
+if [ `whoami` != "root" ]; then
+ echo "You need to be root to run this test."
+ exit 1
+fi
+
+echo Redirecting accounting.
+
+mkdir $TMPDIR
+cd $TMPDIR
+
+:>$ACCT
+accton $ACCT
+
+echo Running commands. This should not take more than 30s.
+
+# User time
+run awk 'BEGIN {for (i = 0; i < 1000000; i++) cos(.3)}' /dev/null
+run egrep '(.)(.)(.)(.)(.)(.)(.)(.)(.)\9\8\7\6\5\4\3\2\1' /usr/share/dict/words
+
+# System time
+run find /usr/src -name xyzzy
+
+# Elapsed time
+run sleep 3
+
+# IO
+run dd if=/dev/zero bs=512 count=4096 of=zero 2>/dev/null
+
+# Memory
+run diff /usr/share/dict/words /dev/null >/dev/null
+
+# AC_COMM_LEN - 1
+ln /usr/bin/true 123456789012345
+run ./123456789012345
+
+# AC_COMM_LEN
+ln /usr/bin/true 1234567890123456
+run ./1234567890123456
+
+# AC_COMM_LEN + 1
+ln /usr/bin/true 12345678901234567
+run ./12345678901234567
+
+# Flags: core, fork, signal
+echo 'main(){volatile int s; fork(); s = *(int *)0;}' >core.c
+cc -o core core.c
+echo Generating segmentation fault.
+./core
+
+echo Turning off redirected accounting.
+
+accton
+
+echo Packing the results.
+
+sa -u $ACCT >sa.u
+lastcomm -cesuS -f $ACCT >lastcomm.cesuS
+tar -cf - acct sa.u lastcomm.cesuS *.time |
+gzip -c |
+uuencode $RESULTS >../$RESULTS.uue
+
+echo Cleaning up.
+cd ..
+rm -rf $TMPDIR
+
+echo "Done! Please send your reply, enclosing the file $RESULTS.uue"
+echo If your system runs with accounting enabled you probably need to run:
+echo accton /var/account/acct
diff --git a/usr.bin/ldd/Makefile b/usr.bin/ldd/Makefile
new file mode 100644
index 000000000000..3abaf20af1b3
--- /dev/null
+++ b/usr.bin/ldd/Makefile
@@ -0,0 +1,7 @@
+PROG?= ldd
+SRCS= ldd.c
+
+CFLAGS+= -I${SRCTOP}/libexec/rtld-elf
+LIBADD= elf
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ldd/Makefile.depend b/usr.bin/ldd/Makefile.depend
new file mode 100644
index 000000000000..0bb6c3493ad3
--- /dev/null
+++ b/usr.bin/ldd/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libelf \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ldd/ldd.1 b/usr.bin/ldd/ldd.1
new file mode 100644
index 000000000000..ffe125f6f325
--- /dev/null
+++ b/usr.bin/ldd/ldd.1
@@ -0,0 +1,72 @@
+.\"
+.Dd March 21, 2023
+.Dt LDD 1
+.Os
+.Sh NAME
+.Nm ldd
+.Nd list dynamic object dependencies
+.Sh SYNOPSIS
+.Nm
+.Op Fl a
+.Op Fl f Ar format Op Fl f Ar format
+.Ar program ...
+.Sh DESCRIPTION
+The
+.Nm
+utility displays all shared objects that are needed to run the given program or
+to load the given shared object.
+Contrary to
+.Xr nm 1 ,
+the list includes
+.Dq indirect
+dependencies that are the result of needed shared objects which themselves
+depend on yet other shared objects.
+.Pp
+Zero, one or two
+.Fl f
+options may be given.
+The argument is a format string passed to
+.Xr rtld 1
+and allows customization of
+.Nm Ns 's
+output.
+If one is given, it sets
+.Ev LD_TRACE_LOADED_OBJECTS_FMT1 .
+If two are given, they set
+.Ev LD_TRACE_LOADED_OBJECTS_FMT1
+and
+.Ev LD_TRACE_LOADED_OBJECTS_FMT2 ,
+respectively.
+See
+.Xr rtld 1
+for details, including a list of recognized conversion characters.
+.Pp
+The
+.Fl a
+option displays the list of all objects that are needed by each loaded
+object.
+.Sh IMPLEMENTATION NOTES
+.Nm
+lists the dependencies of an executable by setting
+.Xr rtld 1
+environment variables and running the executable in a child process.
+If the executable is corrupt or invalid,
+.Nm
+may therefore fail without providing any diagnostic error messages.
+.Sh EXAMPLES
+The following is an example of a shell pipeline which uses the
+.Fl f
+option.
+It will print a report of all ELF binaries in the current directory,
+which link against the old libc.so.6:
+.Dl "find . -type f | xargs file -F ' ' | grep 'ELF.*dynamically' | cut -f1 -d' ' | xargs ldd -f '%A %o\en' | grep -F libc.so.6"
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr nm 1 ,
+.Xr readelf 1 ,
+.Xr rtld 1
+.Sh HISTORY
+A
+.Nm
+utility first appeared in SunOS 4.0, it appeared in its current form in
+.Fx 1.1 .
diff --git a/usr.bin/ldd/ldd.c b/usr.bin/ldd/ldd.c
new file mode 100644
index 000000000000..1c0fc0fbc2ea
--- /dev/null
+++ b/usr.bin/ldd/ldd.c
@@ -0,0 +1,471 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1993 Paul Kranenburg
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. 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.
+ */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+
+#include <machine/elf.h>
+
+#include <arpa/inet.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <rtld_paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * 32-bit ELF data structures can only be used if the system header[s] declare
+ * them. There is no official macro for determining whether they are declared,
+ * so check for the existence of one of the 32-macros defined in elf(5).
+ */
+#ifdef ELF32_R_TYPE
+#define ELF32_SUPPORTED
+#endif
+
+#define LDD_SETENV(name, value, overwrite) do { \
+ setenv("LD_" name, value, overwrite); \
+ setenv("LD_32_" name, value, overwrite); \
+} while (0)
+
+#define LDD_UNSETENV(name) do { \
+ unsetenv("LD_" name); \
+ unsetenv("LD_32_" name); \
+} while (0)
+
+static int is_executable(const char *fname, int fd, int *is_shlib,
+ int *type);
+static void usage(void);
+
+#define TYPE_UNKNOWN 0
+#define TYPE_ELF 1 /* Architecture default */
+#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
+#define TYPE_ELF32 2 /* Explicit 32 bits on architectures >32 bits */
+
+#define _PATH_LDD32 "/usr/bin/ldd32"
+
+static int
+execldd32(char *file, char *fmt1, char *fmt2, int aflag)
+{
+ char *argv[9];
+ int i, rval, status;
+
+ LDD_UNSETENV("TRACE_LOADED_OBJECTS");
+ rval = 0;
+ i = 0;
+ argv[i++] = strdup(_PATH_LDD32);
+ if (aflag)
+ argv[i++] = strdup("-a");
+ if (fmt1 != NULL) {
+ argv[i++] = strdup("-f");
+ argv[i++] = strdup(fmt1);
+ }
+ if (fmt2 != NULL) {
+ argv[i++] = strdup("-f");
+ argv[i++] = strdup(fmt2);
+ }
+ argv[i++] = strdup(file);
+ argv[i++] = NULL;
+
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ break;
+ case 0:
+ execv(_PATH_LDD32, argv);
+ warn("%s", _PATH_LDD32);
+ _exit(127);
+ break;
+ default:
+ if (wait(&status) < 0)
+ rval = 1;
+ else if (WIFSIGNALED(status))
+ rval = 1;
+ else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
+ rval = 1;
+ break;
+ }
+ while (i--)
+ free(argv[i]);
+ LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
+ return (rval);
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ char *fmt1, *fmt2;
+ const char *rtld;
+ int aflag, c, fd, rval, status, is_shlib, rv, type;
+
+ aflag = 0;
+ fmt1 = fmt2 = NULL;
+
+ while ((c = getopt(argc, argv, "af:")) != -1) {
+ switch (c) {
+ case 'a':
+ aflag++;
+ break;
+ case 'f':
+ if (fmt1 != NULL) {
+ if (fmt2 != NULL)
+ errx(1, "too many formats");
+ fmt2 = optarg;
+ } else
+ fmt1 = optarg;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc <= 0) {
+ usage();
+ /* NOTREACHED */
+ }
+
+ rval = 0;
+ for (; argc > 0; argc--, argv++) {
+ if ((fd = open(*argv, O_RDONLY | O_VERIFY, 0)) < 0) {
+ warn("%s", *argv);
+ rval |= 1;
+ continue;
+ }
+ rv = is_executable(*argv, fd, &is_shlib, &type);
+ close(fd);
+ if (rv == 0) {
+ rval |= 1;
+ continue;
+ }
+
+ switch (type) {
+ case TYPE_ELF:
+ break;
+#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
+ case TYPE_ELF32:
+ rval |= execldd32(*argv, fmt1, fmt2, aflag);
+ continue;
+#endif
+ case TYPE_UNKNOWN:
+ default:
+ /*
+ * This shouldn't happen unless is_executable()
+ * is broken.
+ */
+ errx(EDOOFUS, "unknown executable type");
+ }
+
+ /* ld.so magic */
+ LDD_SETENV("TRACE_LOADED_OBJECTS", "yes", 1);
+ if (fmt1 != NULL)
+ LDD_SETENV("TRACE_LOADED_OBJECTS_FMT1", fmt1, 1);
+ if (fmt2 != NULL)
+ LDD_SETENV("TRACE_LOADED_OBJECTS_FMT2", fmt2, 1);
+
+ LDD_SETENV("TRACE_LOADED_OBJECTS_PROGNAME", *argv, 1);
+ if (aflag)
+ LDD_SETENV("TRACE_LOADED_OBJECTS_ALL", "1", 1);
+ else if (fmt1 == NULL && fmt2 == NULL)
+ /* Default formats */
+ printf("%s:\n", *argv);
+ fflush(stdout);
+
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ break;
+ default:
+ if (wait(&status) < 0) {
+ warn("wait");
+ rval |= 1;
+ } else if (WIFSIGNALED(status)) {
+ fprintf(stderr, "%s: signal %d\n", *argv,
+ WTERMSIG(status));
+ rval |= 1;
+ } else if (WIFEXITED(status) &&
+ WEXITSTATUS(status) != 0) {
+ fprintf(stderr, "%s: exit status %d\n", *argv,
+ WEXITSTATUS(status));
+ rval |= 1;
+ }
+ break;
+ case 0:
+ rtld = _PATH_RTLD;
+#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
+ if (type == TYPE_ELF32)
+ rtld = __PATH_RTLD("32");
+#endif
+ if (is_shlib == 0) {
+ execl(rtld, rtld, "--",
+ *argv, (char *)NULL);
+ warn("%s", *argv);
+ } else if (fmt1 == NULL && fmt2 == NULL && !aflag) {
+ dlopen(*argv, RTLD_TRACE);
+ warnx("%s: %s", *argv, dlerror());
+ } else {
+ execl(rtld, rtld, "-d", "--",
+ *argv, (char *)NULL);
+ }
+ _exit(1);
+ }
+ }
+
+ return (rval);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: ldd [-a] [-f format [-f format]] program ...\n");
+ exit(1);
+}
+
+static bool
+has_freebsd_abi_tag(const char *fname, Elf *elf, GElf_Ehdr *ehdr, off_t offset,
+ size_t len)
+{
+ Elf_Data dst, src;
+ const Elf_Note *note;
+ char *buf;
+ const char *name;
+ void *copy;
+ size_t namesz, descsz;
+ bool has_abi_tag;
+
+ buf = elf_rawfile(elf, NULL);
+ if (buf == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (false);
+ }
+
+ memset(&src, 0, sizeof(src));
+ src.d_buf = buf + offset;
+ src.d_size = len;
+ src.d_type = ELF_T_NOTE;
+ src.d_version = EV_CURRENT;
+
+ memset(&dst, 0, sizeof(dst));
+ dst.d_buf = copy = malloc(len);
+ dst.d_size = len;
+ dst.d_type = ELF_T_NOTE;
+ dst.d_version = EV_CURRENT;
+
+ if (gelf_xlatetom(elf, &dst, &src, ehdr->e_ident[EI_DATA]) == NULL) {
+ warnx("%s: failed to parse notes: %s", fname, elf_errmsg(0));
+ free(copy);
+ return (false);
+ }
+
+ buf = copy;
+ has_abi_tag = false;
+ for (;;) {
+ if (len < sizeof(*note))
+ break;
+
+ note = (const void *)buf;
+ buf += sizeof(*note);
+ len -= sizeof(*note);
+
+ namesz = roundup2(note->n_namesz, sizeof(uint32_t));
+ descsz = roundup2(note->n_descsz, sizeof(uint32_t));
+ if (len < namesz + descsz)
+ break;
+
+ name = buf;
+ if (note->n_namesz == sizeof(ELF_NOTE_FREEBSD) &&
+ strncmp(name, ELF_NOTE_FREEBSD, note->n_namesz) == 0 &&
+ note->n_type == NT_FREEBSD_ABI_TAG &&
+ note->n_descsz == sizeof(uint32_t)) {
+ has_abi_tag = true;
+ break;
+ }
+
+ buf += namesz + descsz;
+ len -= namesz + descsz;
+ }
+
+ free(copy);
+ return (has_abi_tag);
+}
+
+static bool
+is_pie(const char *fname, Elf *elf, GElf_Ehdr *ehdr, off_t offset, size_t len)
+{
+ Elf_Data dst, src;
+ char *buf;
+ void *copy;
+ const GElf_Dyn *dyn;
+ size_t dynsize;
+ u_int count, i;
+ bool pie;
+
+ buf = elf_rawfile(elf, NULL);
+ if (buf == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (false);
+ }
+
+ dynsize = gelf_fsize(elf, ELF_T_DYN, 1, EV_CURRENT);
+ if (dynsize == 0) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (false);
+ }
+ count = len / dynsize;
+
+ memset(&src, 0, sizeof(src));
+ src.d_buf = buf + offset;
+ src.d_size = len;
+ src.d_type = ELF_T_DYN;
+ src.d_version = EV_CURRENT;
+
+ memset(&dst, 0, sizeof(dst));
+ dst.d_buf = copy = malloc(count * sizeof(*dyn));
+ dst.d_size = count * sizeof(*dyn);
+ dst.d_type = ELF_T_DYN;
+ dst.d_version = EV_CURRENT;
+
+ if (gelf_xlatetom(elf, &dst, &src, ehdr->e_ident[EI_DATA]) == NULL) {
+ warnx("%s: failed to parse .dynamic: %s", fname, elf_errmsg(0));
+ free(copy);
+ return (false);
+ }
+
+ dyn = copy;
+ pie = false;
+ for (i = 0; i < count; i++) {
+ if (dyn[i].d_tag != DT_FLAGS_1)
+ continue;
+
+ pie = (dyn[i].d_un.d_val & DF_1_PIE) != 0;
+ break;
+ }
+
+ free(copy);
+ return (pie);
+}
+
+static int
+is_executable(const char *fname, int fd, int *is_shlib, int *type)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ GElf_Phdr phdr;
+ bool dynamic, freebsd, pie;
+ int i;
+
+ *is_shlib = 0;
+ *type = TYPE_UNKNOWN;
+ dynamic = false;
+ freebsd = false;
+ pie = false;
+
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ warnx("unsupported libelf");
+ return (0);
+ }
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (elf == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ return (0);
+ }
+ if (elf_kind(elf) != ELF_K_ELF) {
+ elf_end(elf);
+ warnx("%s: not a dynamic ELF executable", fname);
+ return (0);
+ }
+ if (gelf_getehdr(elf, &ehdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ elf_end(elf);
+ return (0);
+ }
+
+ *type = TYPE_ELF;
+#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
+ if (gelf_getclass(elf) == ELFCLASS32) {
+ *type = TYPE_ELF32;
+ }
+#endif
+
+ freebsd = ehdr.e_ident[EI_OSABI] == ELFOSABI_FREEBSD;
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ if (gelf_getphdr(elf, i, &phdr) == NULL) {
+ warnx("%s: %s", fname, elf_errmsg(0));
+ elf_end(elf);
+ return (0);
+ }
+ switch (phdr.p_type) {
+ case PT_NOTE:
+ if (ehdr.e_ident[EI_OSABI] == ELFOSABI_NONE && !freebsd)
+ freebsd = has_freebsd_abi_tag(fname, elf, &ehdr,
+ phdr.p_offset, phdr.p_filesz);
+ break;
+ case PT_DYNAMIC:
+ dynamic = true;
+ if (ehdr.e_type == ET_DYN)
+ pie = is_pie(fname, elf, &ehdr, phdr.p_offset,
+ phdr.p_filesz);
+ break;
+ }
+ }
+
+ if (!dynamic) {
+ elf_end(elf);
+ warnx("%s: not a dynamic ELF executable", fname);
+ return (0);
+ }
+
+ if (ehdr.e_type == ET_DYN && !pie) {
+ *is_shlib = 1;
+
+ if (!freebsd) {
+ elf_end(elf);
+ warnx("%s: not a FreeBSD ELF shared object", fname);
+ return (0);
+ }
+ }
+
+ elf_end(elf);
+ return (1);
+}
diff --git a/usr.bin/ldd32/Makefile b/usr.bin/ldd32/Makefile
new file mode 100644
index 000000000000..993fa8f3ff5c
--- /dev/null
+++ b/usr.bin/ldd32/Makefile
@@ -0,0 +1,10 @@
+NEED_COMPAT= 32
+.include <bsd.compat.mk>
+
+PROG= ldd32
+MAN=
+MLINKS= ldd.1 ldd32.1
+TAGS+= lib32
+
+.PATH: ${SRCTOP}/usr.bin/ldd
+.include "${SRCTOP}/usr.bin/ldd/Makefile"
diff --git a/usr.bin/leave/Makefile b/usr.bin/leave/Makefile
new file mode 100644
index 000000000000..31e9b12e975d
--- /dev/null
+++ b/usr.bin/leave/Makefile
@@ -0,0 +1,5 @@
+PROG= leave
+
+NO_WFORMAT=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/leave/Makefile.depend b/usr.bin/leave/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/leave/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/leave/leave.1 b/usr.bin/leave/leave.1
new file mode 100644
index 000000000000..3fcb1de7ae98
--- /dev/null
+++ b/usr.bin/leave/leave.1
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd April 28, 1995
+.Dt LEAVE 1
+.Os
+.Sh NAME
+.Nm leave
+.Nd remind you when you have to leave
+.Sh SYNOPSIS
+.Nm
+.Op Oo Cm \&+ Oc Ns Ar hhmm
+.Sh DESCRIPTION
+The
+.Nm
+utility waits until the specified time, then reminds you that you
+have to leave.
+You are reminded 5 minutes and 1 minute before the actual
+time, at the time, and every minute thereafter.
+When you log off,
+.Nm
+exits just before it would have
+printed the next message.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Ar hhmm
+The time of day is in the form
+.Ar hhmm
+where
+.Ar hh
+is a time in
+hours (on a 12 or 24 hour clock), and
+.Ar mm
+are minutes.
+All times are converted to a 12 hour clock, and assumed to
+be in the next 12 hours.
+.It Cm \&+
+If the time is preceded by
+.Sq Cm \&+ ,
+the alarm will go off in hours and minutes
+from the current time.
+.El
+.Pp
+If no argument is given,
+.Nm
+prompts with "When do you
+have to leave?".
+A reply of newline causes
+.Nm
+to exit,
+otherwise the reply is assumed to be a time.
+This form is suitable for inclusion in a
+.Pa .login
+or
+.Pa .profile .
+.Pp
+To get rid of
+.Nm
+you should either log off or use
+.Ql kill \-s KILL
+giving its process id.
+.Sh SEE ALSO
+.Xr calendar 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/leave/leave.c b/usr.bin/leave/leave.c
new file mode 100644
index 000000000000..a310f3e4a75c
--- /dev/null
+++ b/usr.bin/leave/leave.c
@@ -0,0 +1,187 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1988, 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.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <capsicum_helpers.h>
+
+static void doalarm(u_int);
+static void usage(void) __dead2;
+
+/*
+ * leave [[+]hhmm]
+ *
+ * Reminds you when you have to leave.
+ * Leave prompts for input and goes away if you hit return.
+ * It nags you like a mother hen.
+ */
+int
+main(int argc, char **argv)
+{
+ u_int secs;
+ int hours, minutes;
+ char c, *cp = NULL;
+ struct tm *t;
+ time_t now;
+ int plusnow, t_12_hour;
+ char buf[50];
+
+ if (setlocale(LC_TIME, "") == NULL)
+ warn("setlocale");
+
+ caph_cache_tzdata();
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(EXIT_FAILURE, "capsicum");
+
+ if (argc < 2) {
+#define MSG1 "When do you have to leave? "
+ (void)write(STDOUT_FILENO, MSG1, sizeof(MSG1) - 1);
+ cp = fgets(buf, sizeof(buf), stdin);
+ if (cp == NULL || *cp == '\n')
+ exit(EXIT_SUCCESS);
+ } else if (argc > 2)
+ usage();
+ else
+ cp = argv[1];
+
+ if (*cp == '+') {
+ plusnow = 1;
+ ++cp;
+ } else
+ plusnow = 0;
+
+ for (hours = 0; (c = *cp) && c != '\n'; ++cp) {
+ if (!isdigit(c))
+ usage();
+ hours = hours * 10 + (c - '0');
+ }
+ minutes = hours % 100;
+ hours /= 100;
+
+ if (minutes < 0 || minutes > 59)
+ usage();
+ if (plusnow)
+ secs = hours * 60 * 60 + minutes * 60;
+ else {
+ (void)time(&now);
+ t = localtime(&now);
+
+ if (hours > 23)
+ usage();
+
+ /* Convert tol to 12 hr time (0:00...11:59) */
+ if (hours > 11)
+ hours -= 12;
+
+ /* Convert tm to 12 hr time (0:00...11:59) */
+ if (t->tm_hour > 11)
+ t_12_hour = t->tm_hour - 12;
+ else
+ t_12_hour = t->tm_hour;
+
+ if (hours < t_12_hour ||
+ (hours == t_12_hour && minutes <= t->tm_min))
+ /* Leave time is in the past so we add 12 hrs */
+ hours += 12;
+
+ secs = (hours - t_12_hour) * 60 * 60;
+ secs += (minutes - t->tm_min) * 60;
+ secs -= now % 60; /* truncate (now + secs) to min */
+ }
+ doalarm(secs);
+ exit(EXIT_SUCCESS);
+}
+
+void
+doalarm(u_int secs)
+{
+ int bother;
+ time_t daytime;
+ char tb[80];
+ int pid;
+
+ if ((pid = fork())) {
+ (void)time(&daytime);
+ daytime += secs;
+ strftime(tb, sizeof(tb), "%+", localtime(&daytime));
+ printf("Alarm set for %s. (pid %d)\n", tb, pid);
+ exit(EXIT_SUCCESS);
+ }
+ sleep((u_int)2); /* let parent print set message */
+ if (secs >= 2)
+ secs -= 2;
+
+ /*
+ * if write fails, we've lost the terminal through someone else
+ * causing a vhangup by logging in.
+ */
+#define FIVEMIN (5 * 60)
+#define MSG2 "\07\07You have to leave in 5 minutes.\n"
+ if (secs >= FIVEMIN) {
+ sleep(secs - FIVEMIN);
+ if (write(STDOUT_FILENO, MSG2, sizeof(MSG2) - 1) != sizeof(MSG2) - 1)
+ exit(EXIT_SUCCESS);
+ secs = FIVEMIN;
+ }
+
+#define ONEMIN (60)
+#define MSG3 "\07\07Just one more minute!\n"
+ if (secs >= ONEMIN) {
+ sleep(secs - ONEMIN);
+ if (write(STDOUT_FILENO, MSG3, sizeof(MSG3) - 1) != sizeof(MSG3) - 1)
+ exit(EXIT_SUCCESS);
+ }
+
+#define MSG4 "\07\07Time to leave!\n"
+ for (bother = 10; bother--;) {
+ sleep((u_int)ONEMIN);
+ if (write(STDOUT_FILENO, MSG4, sizeof(MSG4) - 1) != sizeof(MSG4) - 1)
+ exit(EXIT_SUCCESS);
+ }
+
+#define MSG5 "\07\07That was the last time I'll tell you. Bye.\n"
+ (void)write(STDOUT_FILENO, MSG5, sizeof(MSG5) - 1);
+ exit(EXIT_SUCCESS);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: leave [[+]hhmm]\n");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/less/Makefile b/usr.bin/less/Makefile
new file mode 100644
index 000000000000..b9a46c5cbeaa
--- /dev/null
+++ b/usr.bin/less/Makefile
@@ -0,0 +1,21 @@
+PACKAGE= runtime
+PROG= less
+SRCS= main.c screen.c brac.c ch.c charset.c cmdbuf.c command.c cvt.c \
+ decode.c evar.c edit.c filename.c forwback.c help.c ifile.c input.c \
+ jump.c lesskey_parse.c \
+ line.c linenum.c lsystem.c mark.c optfunc.c option.c \
+ opttbl.c os.c output.c pattern.c position.c prompt.c search.c \
+ signal.c tags.c ttyin.c version.c xbuf.c
+SCRIPTS=lesspipe.sh zless.sh
+SCRIPTSNAME_lesspipe.sh=lesspipe.sh
+LIBADD= tinfow
+LINKS= ${BINDIR}/less ${BINDIR}/more \
+ ${BINDIR}/zless ${BINDIR}/bzless \
+ ${BINDIR}/zless ${BINDIR}/xzless \
+ ${BINDIR}/zless ${BINDIR}/lzless \
+ ${BINDIR}/zless ${BINDIR}/zstdless
+MLINKS= less.1 more.1
+CLEANFILES= less.1
+
+.include "Makefile.common"
+.include <bsd.prog.mk>
diff --git a/usr.bin/less/Makefile.common b/usr.bin/less/Makefile.common
new file mode 100644
index 000000000000..f0fcc9150087
--- /dev/null
+++ b/usr.bin/less/Makefile.common
@@ -0,0 +1,10 @@
+LSDIR= ${SRCTOP}/contrib/less
+.PATH: ${LSDIR}
+
+CFLAGS+=-I${SRCTOP}/usr.bin/less -I${LSDIR}
+WARNS?= 1
+
+.SUFFIXES: .nro .1
+
+.nro.1:
+ cat ${.IMPSRC} > ${.TARGET}
diff --git a/usr.bin/less/Makefile.depend b/usr.bin/less/Makefile.depend
new file mode 100644
index 000000000000..dd06faaab7bf
--- /dev/null
+++ b/usr.bin/less/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/less/defines.h b/usr.bin/less/defines.h
new file mode 100644
index 000000000000..cdfc2899511f
--- /dev/null
+++ b/usr.bin/less/defines.h
@@ -0,0 +1,483 @@
+/* defines.h. Generated from defines.h.in by configure. */
+/* defines.h.in. Generated from configure.ac by autoheader. */
+
+
+/* Unix definition file for less. -*- C -*-
+ *
+ * This file has 3 sections:
+ * User preferences.
+ * Settings always true on Unix.
+ * Settings automatically determined by configure.
+ *
+ * * * * * * WARNING * * * * * *
+ * If you edit defines.h by hand, do "touch stamp-h" before you run make
+ * so config.status doesn't overwrite your changes.
+ */
+
+/* User preferences. */
+
+/*
+ * SECURE is 1 if you wish to disable a bunch of features in order to
+ * be safe to run by unprivileged users.
+ * SECURE_COMPILE is set by the --with-secure configure option.
+ */
+#define SECURE SECURE_COMPILE
+
+/*
+ * SHELL_ESCAPE is 1 if you wish to allow shell escapes.
+ * (This is possible only if your system supplies the system() function.)
+ */
+#define SHELL_ESCAPE (!SECURE)
+
+/*
+ * EXAMINE is 1 if you wish to allow examining files by name from within less.
+ */
+#define EXAMINE (!SECURE)
+
+/*
+ * TAB_COMPLETE_FILENAME is 1 if you wish to allow the TAB key
+ * to complete filenames at prompts.
+ */
+#define TAB_COMPLETE_FILENAME (!SECURE)
+
+/*
+ * CMD_HISTORY is 1 if you wish to allow keys to cycle through
+ * previous commands at prompts.
+ */
+#define CMD_HISTORY 1
+
+/*
+ * HILITE_SEARCH is 1 if you wish to have search targets to be
+ * displayed in standout mode.
+ */
+#define HILITE_SEARCH 1
+
+/*
+ * EDITOR is 1 if you wish to allow editor invocation (the "v" command).
+ * (This is possible only if your system supplies the system() function.)
+ * EDIT_PGM is the name of the (default) editor to be invoked.
+ */
+#define EDITOR (!SECURE)
+
+/*
+ * TAGS is 1 if you wish to support tag files.
+ */
+#define TAGS (!SECURE)
+
+/*
+ * USERFILE is 1 if you wish to allow a .less file to specify
+ * user-defined key bindings.
+ */
+#define USERFILE (!SECURE)
+
+/*
+ * GLOB is 1 if you wish to have shell metacharacters expanded in filenames.
+ * This will generally work if your system provides the "popen" function
+ * and the "echo" shell command.
+ */
+#define GLOB (!SECURE)
+
+/*
+ * PIPEC is 1 if you wish to have the "|" command
+ * which allows the user to pipe data into a shell command.
+ */
+#define PIPEC (!SECURE && HAVE_POPEN)
+
+/*
+ * LOGFILE is 1 if you wish to allow the -o option (to create log files).
+ */
+#define LOGFILE (!SECURE)
+
+/*
+ * OSC8_SEARCH is 1 if you wish to allow the ^O^O and related commands
+ * (to open OSC8 hyperlinks).
+ */
+#define OSC8_LINK 1
+
+/*
+ * GNU_OPTIONS is 1 if you wish to support the GNU-style command
+ * line options --help and --version.
+ */
+#define GNU_OPTIONS 1
+
+/*
+ * ONLY_RETURN is 1 if you want RETURN to be the only input which
+ * will continue past an error message.
+ * Otherwise, any key will continue past an error message.
+ */
+#define ONLY_RETURN 0
+
+/*
+ * LESSKEYFILE is the filename of the default lesskey output file
+ * (in the HOME directory).
+ * LESSKEYFILE_SYS is the filename of the system-wide lesskey output file.
+ * DEF_LESSKEYINFILE is the filename of the default lesskey input
+ * (in the HOME directory).
+ * LESSHISTFILE is the filename of the history file
+ * (in the HOME directory).
+ */
+#define LESSKEYFILE ".less"
+#define LESSKEYFILE_SYS "/etc/lesskey"
+#define DEF_LESSKEYINFILE ".lesskey"
+#define LESSKEYINFILE_SYS "/etc/syslesskey"
+#define LESSHISTFILE ".lesshst"
+
+
+/* Settings always true on Unix. */
+
+/*
+ * Define MSDOS_COMPILER if compiling under Microsoft C.
+ */
+#define MSDOS_COMPILER 0
+
+/*
+ * Pathname separator character.
+ */
+#define PATHNAME_SEP "/"
+
+/*
+ * The value returned from tgetent on success.
+ * Some HP-UX systems return 0 on success.
+ */
+#define TGETENT_OK 1
+
+/*
+ * HAVE_ANSI_PROTOS is 1 if your compiler supports ANSI function prototypes.
+ */
+#define HAVE_ANSI_PROTOS 1
+
+/*
+ * HAVE_SYS_TYPES_H is 1 if your system has <sys/types.h>.
+ */
+#define HAVE_SYS_TYPES_H 1
+
+/*
+ * Define if you have the <sgstat.h> header file.
+ */
+/* #undef HAVE_SGSTAT_H */
+
+/*
+ * HAVE_PERROR is 1 if your system has the perror() call.
+ * (Actually, if it has sys_errlist, sys_nerr and errno.)
+ */
+#define HAVE_PERROR 1
+
+/*
+ * HAVE_TIME is 1 if your system has the time() call.
+ */
+#define HAVE_TIME 1
+
+/*
+ * HAVE_SHELL is 1 if your system supports a SHELL command interpreter.
+ */
+#define HAVE_SHELL 1
+
+/*
+ * Default shell metacharacters and meta-escape character.
+ */
+#define DEF_METACHARS "; *?\t\n'\"()<>[]|&^`#\\$%=~{},"
+#define DEF_METAESCAPE "\\"
+
+/*
+ * HAVE_DUP is 1 if your system has the dup() call.
+ */
+#define HAVE_DUP 1
+
+/* Define to 1 if you have the memcpy() function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the strchr() function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the strstr() function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 to support reading lesskey source files (not just binary). */
+#define HAVE_LESSKEYSRC 1
+
+/*
+ * Sizes of various buffers.
+ */
+#if 0 /* old sizes for small memory machines */
+#define CMDBUF_SIZE 512 /* Buffer for multichar commands */
+#define UNGOT_SIZE 100 /* Max chars to unget() */
+#define LINEBUF_SIZE 1024 /* Max size of line in input file */
+#define OUTBUF_SIZE 1024 /* Output buffer */
+#define PROMPT_SIZE 200 /* Max size of prompt string */
+#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */
+#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
+#define TAGLINE_SIZE 512 /* Max size of line in tags file */
+#define TABSTOP_MAX 32 /* Max number of custom tab stops */
+#else /* more reasonable sizes for modern machines */
+#define CMDBUF_SIZE 2048 /* Buffer for multichar commands */
+#define UNGOT_SIZE 200 /* Max chars to unget() */
+#define LINEBUF_SIZE 1024 /* Initial max size of line in input file */
+#define OUTBUF_SIZE 1024 /* Output buffer */
+#define PROMPT_SIZE 2048 /* Max size of prompt string */
+#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */
+#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */
+#define TAGLINE_SIZE 1024 /* Max size of line in tags file */
+#define TABSTOP_MAX 128 /* Max number of custom tab stops */
+#endif
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Settings automatically determined by configure. */
+
+
+/* Define EDIT_PGM to your editor. */
+#define EDIT_PGM "vi"
+
+/* Define HAVE_CONST if your compiler supports the "const" modifier. */
+#define HAVE_CONST 1
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#define HAVE_CTYPE_H 1
+
+/* Define HAVE_ERRNO if you have the errno variable. */
+#define HAVE_ERRNO 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the 'fchmod' function. */
+#define HAVE_FCHMOD 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define HAVE_FILENO if you have the fileno() macro. */
+#define HAVE_FILENO 1
+
+/* Define to 1 if you have the 'fsync' function. */
+#define HAVE_FSYNC 1
+
+/* GNU regex library */
+/* #undef HAVE_GNU_REGEX */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/magic.h> header file. */
+/* #undef HAVE_LINUX_MAGIC_H */
+
+/* Define HAVE_LOCALE if you have locale.h and setlocale. */
+#define HAVE_LOCALE 1
+
+/* Define to 1 if you have the 'nanosleep' function. */
+#define HAVE_NANOSLEEP 1
+
+/* Define to 1 if you have the <ncursesw/termcap.h> header file. */
+/* #undef HAVE_NCURSESW_TERMCAP_H */
+
+/* Define to 1 if you have the <ncurses/termcap.h> header file. */
+/* #undef HAVE_NCURSES_TERMCAP_H */
+
+/* Define HAVE_OSPEED if your termcap library has the ospeed variable. */
+#define HAVE_OSPEED 1
+
+/* PCRE (Perl-compatible regular expression) library */
+/* #undef HAVE_PCRE */
+
+/* PCRE2 (Perl-compatible regular expression) library */
+/* #undef HAVE_PCRE2 */
+
+/* Define to 1 if you have the 'poll' function. */
+#define HAVE_POLL 1
+
+/* Define to 1 if you have the 'popen' function. */
+#define HAVE_POPEN 1
+
+/* POSIX regcomp() and regex.h */
+#define HAVE_POSIX_REGCOMP 1
+
+/* Define to 1 if you have the 'realpath' function. */
+#define HAVE_REALPATH 1
+
+/* System V regcmp() */
+/* #undef HAVE_REGCMP */
+
+/* */
+/* #undef HAVE_REGEXEC2 */
+
+/* BSD re_comp() */
+/* #undef HAVE_RE_COMP */
+
+/* Define HAVE_SIGEMPTYSET if you have the sigemptyset macro. */
+#define HAVE_SIGEMPTYSET 1
+
+/* Define to 1 if you have the 'sigprocmask' function. */
+#define HAVE_SIGPROCMASK 1
+
+/* Define to 1 if you have the 'sigsetmask' function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define to 1 if the system has the type 'sigset_t'. */
+#define HAVE_SIGSET_T 1
+
+/* Define to 1 if you have the 'snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the 'stat' function. */
+#define HAVE_STAT 1
+
+/* Define HAVE_STAT_INO if your struct stat has st_ino and st_dev. */
+#define HAVE_STAT_INO 1
+
+/* Define to 1 if you have the <stdckdint.h> header file. */
+#define HAVE_STDCKDINT_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define HAVE_STRERROR if you have the strerror() function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the 'strsignal' function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define to 1 if you have the 'system' function. */
+#define HAVE_SYSTEM 1
+
+/* Define HAVE_SYS_ERRLIST if you have the sys_errlist[] variable. */
+#define HAVE_SYS_ERRLIST 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/stream.h> header file. */
+/* #undef HAVE_SYS_STREAM_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define HAVE_TERMIOS_FUNCS if you have tcgetattr/tcsetattr. */
+#define HAVE_TERMIOS_FUNCS 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define HAVE_TIME_T if your system supports the "time_t" type. */
+#define HAVE_TIME_T 1
+
+/* Define to 1 if you have the 'ttyname' function. */
+#define HAVE_TTYNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define HAVE_UPPER_LOWER if you have isupper, islower, toupper, tolower. */
+#define HAVE_UPPER_LOWER 1
+
+/* Define to 1 if you have the 'usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Henry Spencer V8 regcomp() and regexp.h */
+/* #undef HAVE_V8_REGCOMP */
+
+/* Define to 1 if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define HAVE_VOID if your compiler supports the "void" type. */
+#define HAVE_VOID 1
+
+/* Define HAVE_WCTYPE if you have iswupper, iswlower, towupper, towlower. */
+#define HAVE_WCTYPE 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if you have the '_setjmp' function. */
+#define HAVE__SETJMP 1
+
+/* Define MUST_DEFINE_ERRNO if you have errno but it is not define in errno.h.
+ */
+/* #undef MUST_DEFINE_ERRNO */
+
+/* Define MUST_DEFINE_OSPEED if you have ospeed but it is not defined in
+ termcap.h. */
+/* #undef MUST_DEFINE_OSPEED */
+
+/* pattern matching is supported, but without metacharacters. */
+/* #undef NO_REGEX */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "less"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "less 1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "less"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1"
+
+/* Define SECURE_COMPILE=1 to build a secure version of less. */
+#define SECURE_COMPILE 0
+
+/* Define to 1 if the 'S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 on platforms where this makes off_t a 64-bit type. */
+/* #undef _LARGE_FILES */
+
+/* Number of bits in time_t, on hosts where this is settable. */
+/* #undef _TIME_BITS */
+
+/* Define to 1 on platforms where this makes time_t a 64-bit type. */
+/* #undef __MINGW_USE_VC2005_COMPAT */
+
+/* Define to empty if 'const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to 'long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define as 'unsigned int' if <stddef.h> doesn't define. */
+/* #undef size_t */
diff --git a/usr.bin/less/lesspipe.sh b/usr.bin/less/lesspipe.sh
new file mode 100644
index 000000000000..253914b8b3ee
--- /dev/null
+++ b/usr.bin/less/lesspipe.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# ex:ts=8
+
+case "$1" in
+ *.zip)
+ exec unzip -c "$1" 2>/dev/null
+ ;;
+ *.Z)
+ exec uncompress -c "$1" 2>/dev/null
+ ;;
+ *.gz)
+ exec gzip -d -c "$1" 2>/dev/null
+ ;;
+ *.bz2)
+ exec bzip2 -d -c "$1" 2>/dev/null
+ ;;
+ *.xz)
+ exec xz -d -c "$1" 2>/dev/null
+ ;;
+ *.lzma)
+ exec lzma -d -c "$1" 2>/dev/null
+ ;;
+ *.zst)
+ exec zstd -d -q -c "$1" 2>/dev/null
+ ;;
+ *) exec cat "$1" 2>/dev/null
+ ;;
+esac
diff --git a/usr.bin/less/zless.sh b/usr.bin/less/zless.sh
new file mode 100644
index 000000000000..dbf4bd5997c6
--- /dev/null
+++ b/usr.bin/less/zless.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+#
+
+export LESSOPEN="||/usr/bin/lesspipe.sh %s"
+exec /usr/bin/less "$@"
diff --git a/usr.bin/lessecho/Makefile b/usr.bin/lessecho/Makefile
new file mode 100644
index 000000000000..d8571677f0ac
--- /dev/null
+++ b/usr.bin/lessecho/Makefile
@@ -0,0 +1,6 @@
+PROG= lessecho
+SRCS= lessecho.c version.c
+CLEANFILES= lessecho.1
+
+.include "${SRCTOP}/usr.bin/less/Makefile.common"
+.include <bsd.prog.mk>
diff --git a/usr.bin/lessecho/Makefile.depend b/usr.bin/lessecho/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/lessecho/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lesskey/Makefile b/usr.bin/lesskey/Makefile
new file mode 100644
index 000000000000..e1fd0d557136
--- /dev/null
+++ b/usr.bin/lesskey/Makefile
@@ -0,0 +1,6 @@
+PROG= lesskey
+SRCS= lesskey.c lesskey_parse.c version.c xbuf.c
+CLEANFILES= lesskey.1
+
+.include "${SRCTOP}/usr.bin/less/Makefile.common"
+.include <bsd.prog.mk>
diff --git a/usr.bin/lesskey/Makefile.depend b/usr.bin/lesskey/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/lesskey/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lex/Makefile b/usr.bin/lex/Makefile
new file mode 100644
index 000000000000..c1311105cdc5
--- /dev/null
+++ b/usr.bin/lex/Makefile
@@ -0,0 +1,61 @@
+#
+# By default, flex will be configured to generate 8-bit scanners only if the
+# -8 flag is given. If you want it to always generate 8-bit scanners, add
+# "-DDEFAULT_CSIZE=256" to CFLAGS. Note that doing so will double the size
+# of all uncompressed scanners.
+#
+# Bootstrapping of lex is handled automatically.
+# Also note that flex.skel no longer gets installed.
+#
+
+PROG= lex
+LINKS+= ${BINDIR}/lex ${BINDIR}/lex++
+LINKS+= ${BINDIR}/lex ${BINDIR}/flex
+LINKS+= ${BINDIR}/lex ${BINDIR}/flex++
+
+FLEXDIR= ${SRCTOP}/contrib/flex/src
+
+.PATH: ${FLEXDIR}
+
+SRCS= buf.c ccl.c dfa.c ecs.c filter.c gen.c main.c misc.c \
+ nfa.c options.c parse.y regex.c scan.c scanflags.c \
+ scanopt.c skel.c sym.c tables.c tables_shared.c \
+ tblcmp.c yylex.c
+LFLAGS+= -is
+CFLAGS+= -I. -I${.CURDIR} -I${FLEXDIR} -DHAVE_CONFIG_H
+INCS= FlexLexer.h
+INCSDIR= ${INCLUDEDIR}
+MLINKS+= lex.1 flex.1
+MLINKS+= lex.1 flex++.1
+MLINKS+= lex.1 lex++.1
+
+WARNS?= 3
+
+NO_WMISLEADING_INDENTATION=
+
+CLEANFILES= scan.c skel.c
+GENFILES= parse.c parse.h scan.c skel.c
+
+SUBDIR= lib
+
+FLEX_VERSION= `awk -f ${.CURDIR}/version.awk ${.CURDIR}/config.h`
+
+skel.c: config.h mkskel.sh flex.skl version.awk
+ sh ${FLEXDIR}/mkskel.sh ${FLEXDIR} m4 ${FLEX_VERSION} > ${.TARGET}
+
+bootstrap: ${GENFILES:S/^/init/g}
+.for _f in ${GENFILES}
+ @diff -I '^#line ' -I '\$$FreeBS[D]: .*\$$' -q \
+ ${.CURDIR}/init${_f} ${_f} 2> /dev/null || { \
+ echo "Bootstrapping ${_f}" ; \
+ ${CP} ${.CURDIR}/init${_f} ${_f} ; \
+ }
+.endfor
+
+test: check
+check: ${PROG}
+ ./${PROG} ${LFLAGS} -t ${COMPRESSION} ${FLEXDIR}/scan.l | \
+ diff -I '^#line ' -I '\$$FreeBS[D]: .*\$$' ${.CURDIR}/initscan.c -
+ @echo "Check successful"
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lex/Makefile.depend b/usr.bin/lex/Makefile.depend
new file mode 100644
index 000000000000..c2fea3d32305
--- /dev/null
+++ b/usr.bin/lex/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lex/Makefile.depend.host b/usr.bin/lex/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/lex/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lex/Makefile.depend.options b/usr.bin/lex/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/lex/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/lex/config.h b/usr.bin/lex/config.h
new file mode 100644
index 000000000000..941a74d9d71c
--- /dev/null
+++ b/usr.bin/lex/config.h
@@ -0,0 +1,266 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+/* #undef ENABLE_NLS */
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the `available.' function. */
+/* #undef HAVE_AVAILABLE_ */
+
+/* Define to 1 if you have the `by' function. */
+/* #undef HAVE_BY */
+
+/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
+ CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
+ the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+ */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `dnl' function. */
+/* #undef HAVE_DNL */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the `enabled' function. */
+/* #undef HAVE_ENABLED */
+
+/* Define to 1 if you have the `fork' function. */
+#define HAVE_FORK 1
+
+/* Define to 1 if you have the `function.' function. */
+/* #undef HAVE_FUNCTION_ */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `have' function. */
+/* #undef HAVE_HAVE */
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the `if' function. */
+/* #undef HAVE_IF */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `is' function. */
+/* #undef HAVE_IS */
+
+/* Define to 1 if you have the <libintl.h> header file. */
+/* #undef HAVE_LIBINTL_H */
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `Needed' function. */
+/* #undef HAVE_NEEDED */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the `NLS' function. */
+/* #undef HAVE_NLS */
+
+/* Define to 1 if you have the `not' function. */
+/* #undef HAVE_NOT */
+
+/* Define to 1 if you have the `only' function. */
+/* #undef HAVE_ONLY */
+
+/* Define to 1 if you have the `OpenBSD' function. */
+/* #undef HAVE_OPENBSD */
+
+/* Define to 1 if you have the `pow' function. */
+#define HAVE_POW 1
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#define HAVE_REALLOC 1
+
+/* Define to 1 if you have the `reallocarray' function. */
+#define HAVE_REALLOCARRAY 1
+
+/* Define to 1 if you have the `regcomp' function. */
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
+
+/* Define to 1 if you have the `replacement' function. */
+/* #undef HAVE_REPLACEMENT */
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `Used' function. */
+/* #undef HAVE_USED */
+
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
+/* Define to 1 if you have the <vfork.h> header file. */
+/* #undef HAVE_VFORK_H */
+
+/* Define to 1 if you have the `We' function. */
+/* #undef HAVE_WE */
+
+/* Define to 1 if `fork' works. */
+#define HAVE_WORKING_FORK 1
+
+/* Define to 1 if `vfork' works. */
+#define HAVE_WORKING_VFORK 1
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Define to the m4 executable name. */
+#define M4 "m4"
+
+/* Name of package */
+#define PACKAGE "flex"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "flex-help@lists.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "the fast lexical analyser generator"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "the fast lexical analyser generator 2.6.4"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "flex"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.6.4"
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+/* #undef STACK_DIRECTION */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "2.6.4"
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define as `fork' if `vfork' does not work. */
+/* #undef vfork */
diff --git a/usr.bin/lex/initparse.c b/usr.bin/lex/initparse.c
new file mode 100644
index 000000000000..47437a0e2976
--- /dev/null
+++ b/usr.bin/lex/initparse.c
@@ -0,0 +1,1843 @@
+/* original parser id follows */
+/* (use YYMAJOR/YYMINOR for ifdefs dependent on parser version) */
+
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYPATCH 20200330
+
+#define YYEMPTY (-1)
+#define yyclearin (yychar = YYEMPTY)
+#define yyerrok (yyerrflag = 0)
+#define YYRECOVERING() (yyerrflag != 0)
+#define YYENOMEM (-2)
+#define YYEOF 0
+#define YYPREFIX "yy"
+
+#define YYPURE 0
+
+#line 35 "parse.y"
+/* Copyright (c) 1990 The Regents of the University of California. */
+/* All rights reserved. */
+
+/* This code is derived from software contributed to Berkeley by */
+/* Vern Paxson. */
+
+/* The United States Government has rights in this work pursuant */
+/* to contract no. DE-AC03-76SF00098 between the United States */
+/* Department of Energy and the University of California. */
+
+/* This file is part of flex. */
+
+/* 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. */
+
+/* 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR */
+/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
+/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
+/* PURPOSE. */
+
+#include "flexdef.h"
+#include "tables.h"
+
+int pat, scnum, eps, headcnt, trailcnt, lastchar, i, rulelen;
+int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
+
+int *scon_stk;
+int scon_stk_ptr;
+
+static int madeany = false; /* whether we've made the '.' character class */
+static int ccldot, cclany;
+int previous_continued_action; /* whether the previous rule's action was '|' */
+
+#define format_warn3(fmt, a1, a2) \
+ do{ \
+ char fw3_msg[MAXLINE];\
+ snprintf( fw3_msg, MAXLINE,(fmt), (a1), (a2) );\
+ lwarn( fw3_msg );\
+ }while(0)
+
+/* Expand a POSIX character class expression. */
+#define CCL_EXPR(func) \
+ do{ \
+ int c; \
+ for ( c = 0; c < csize; ++c ) \
+ if ( isascii(c) && func(c) ) \
+ ccladd( currccl, c ); \
+ }while(0)
+
+/* negated class */
+#define CCL_NEG_EXPR(func) \
+ do{ \
+ int c; \
+ for ( c = 0; c < csize; ++c ) \
+ if ( !func(c) ) \
+ ccladd( currccl, c ); \
+ }while(0)
+
+/* While POSIX defines isblank(), it's not ANSI C. */
+#define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
+
+/* On some over-ambitious machines, such as DEC Alpha's, the default
+ * token type is "long" instead of "int"; this leads to problems with
+ * declaring yylval in flexdef.h. But so far, all the yacc's I've seen
+ * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
+ * following should ensure that the default token type is "int".
+ */
+#define YYSTYPE int
+
+#line 102 "parse.c"
+
+#if ! defined(YYSTYPE) && ! defined(YYSTYPE_IS_DECLARED)
+/* Default: YYSTYPE is the semantic value type. */
+typedef int YYSTYPE;
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+/* compatibility with bison */
+#ifdef YYPARSE_PARAM
+/* compatibility with FreeBSD */
+# ifdef YYPARSE_PARAM_TYPE
+# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
+# else
+# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
+# endif
+#else
+# define YYPARSE_DECL() yyparse(void)
+#endif
+
+/* Parameters sent to lex. */
+#ifdef YYLEX_PARAM
+# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
+# define YYLEX yylex(YYLEX_PARAM)
+#else
+# define YYLEX_DECL() yylex(void)
+# define YYLEX yylex()
+#endif
+
+#if !(defined(yylex) || defined(YYSTATE))
+int YYLEX_DECL();
+#endif
+
+/* Parameters sent to yyerror. */
+#ifndef YYERROR_DECL
+#define YYERROR_DECL() yyerror(const char *s)
+#endif
+#ifndef YYERROR_CALL
+#define YYERROR_CALL(msg) yyerror(msg)
+#endif
+
+extern int YYPARSE_DECL();
+
+#define CHAR 257
+#define NUMBER 258
+#define SECTEND 259
+#define SCDECL 260
+#define XSCDECL 261
+#define NAME 262
+#define PREVCCL 263
+#define EOF_OP 264
+#define TOK_OPTION 265
+#define TOK_OUTFILE 266
+#define TOK_PREFIX 267
+#define TOK_YYCLASS 268
+#define TOK_HEADER_FILE 269
+#define TOK_EXTRA_TYPE 270
+#define TOK_TABLES_FILE 271
+#define CCE_ALNUM 272
+#define CCE_ALPHA 273
+#define CCE_BLANK 274
+#define CCE_CNTRL 275
+#define CCE_DIGIT 276
+#define CCE_GRAPH 277
+#define CCE_LOWER 278
+#define CCE_PRINT 279
+#define CCE_PUNCT 280
+#define CCE_SPACE 281
+#define CCE_UPPER 282
+#define CCE_XDIGIT 283
+#define CCE_NEG_ALNUM 284
+#define CCE_NEG_ALPHA 285
+#define CCE_NEG_BLANK 286
+#define CCE_NEG_CNTRL 287
+#define CCE_NEG_DIGIT 288
+#define CCE_NEG_GRAPH 289
+#define CCE_NEG_LOWER 290
+#define CCE_NEG_PRINT 291
+#define CCE_NEG_PUNCT 292
+#define CCE_NEG_SPACE 293
+#define CCE_NEG_UPPER 294
+#define CCE_NEG_XDIGIT 295
+#define CCL_OP_DIFF 296
+#define CCL_OP_UNION 297
+#define BEGIN_REPEAT_POSIX 298
+#define END_REPEAT_POSIX 299
+#define BEGIN_REPEAT_FLEX 300
+#define END_REPEAT_FLEX 301
+#define YYERRCODE 256
+typedef int YYINT;
+static const YYINT yylhs[] = { -1,
+ 0, 1, 2, 2, 2, 2, 3, 6, 6, 7,
+ 7, 7, 8, 9, 9, 10, 10, 10, 10, 10,
+ 10, 4, 4, 4, 5, 12, 12, 12, 12, 14,
+ 11, 11, 11, 15, 15, 15, 16, 13, 13, 13,
+ 13, 18, 18, 17, 19, 19, 19, 19, 19, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 21, 21, 21, 23, 23, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 22, 22,
+};
+static const YYINT yylen[] = { 2,
+ 5, 0, 3, 2, 0, 1, 1, 1, 1, 2,
+ 1, 1, 2, 2, 0, 3, 3, 3, 3, 3,
+ 3, 5, 5, 0, 0, 2, 1, 1, 1, 0,
+ 4, 3, 0, 3, 1, 1, 1, 2, 3, 2,
+ 1, 3, 1, 2, 2, 1, 6, 5, 4, 2,
+ 2, 2, 6, 5, 4, 1, 1, 1, 3, 3,
+ 1, 3, 3, 1, 3, 4, 4, 2, 2, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 0,
+};
+static const YYINT yydefred[] = { 2,
+ 0, 0, 6, 0, 7, 8, 9, 15, 24, 0,
+ 4, 0, 0, 12, 11, 0, 0, 0, 0, 0,
+ 0, 0, 14, 0, 1, 0, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 24, 0, 16, 18, 19,
+ 20, 17, 21, 32, 36, 37, 0, 35, 0, 29,
+ 61, 58, 28, 0, 56, 96, 0, 0, 0, 27,
+ 0, 0, 0, 0, 0, 64, 31, 0, 23, 26,
+ 0, 0, 70, 0, 22, 0, 40, 0, 44, 0,
+ 0, 0, 50, 51, 52, 0, 0, 34, 95, 59,
+ 60, 0, 0, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 82, 81, 83, 84, 85, 86, 87,
+ 88, 93, 89, 90, 91, 94, 92, 65, 69, 39,
+ 0, 0, 0, 62, 63, 66, 0, 49, 0, 55,
+ 0, 67, 0, 48, 0, 54, 47, 53,
+};
+static const YYINT yydgoto[] = { 1,
+ 2, 4, 9, 13, 25, 10, 16, 11, 12, 23,
+ 26, 59, 60, 35, 47, 48, 61, 62, 63, 64,
+ 65, 71, 66, 74, 119,
+};
+static const YYINT yysindex[] = { 0,
+ 0, -222, 0, -155, 0, 0, 0, 0, 0, -215,
+ 0, -123, 6, 0, 0, -193, 10, 21, 26, 31,
+ 35, 37, 0, 59, 0, -44, 0, -147, -145, -140,
+ -133, -132, -129, 75, -214, 0, -19, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 23, 0, -48, 0,
+ 0, 0, 0, -17, 0, 0, -17, 27, 128, 0,
+ -17, -1, -30, -41, -189, 0, 0, -121, 0, 0,
+ -31, -34, 0, -87, 0, -25, 0, -17, 0, -109,
+ -41, -108, 0, 0, 0, 60, 60, 0, 0, 0,
+ 0, 46, 107, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -30, -36, -39, 0, 0, 0, -104, 0, -219, 0,
+ -238, 0, -144, 0, -143, 0, 0, 0,
+};
+static const YYINT yyrindex[] = { 0,
+ 0, -141, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -134, 9, 0, 0, -125, 0, 0, 0, 0,
+ 0, 0, 0, -178, 0, 22, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -21, 0,
+ 0, 0, 0, 0, 0, 0, 0, 85, 0, 0,
+ 0, 144, 47, 4, -10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 146, 0, 0, 0, 0,
+ 18, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 124, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+static const YYINT yygindex[] = { 0,
+ 0, 0, 0, 121, 133, 0, 0, 0, 0, 0,
+ 0, 0, 106, 0, 0, 93, 0, 32, 84, -45,
+ 0, 0, 25, 90, 0,
+};
+#define YYTABLESIZE 419
+static const YYINT yytable[] = { 57,
+ 83, 84, 90, 56, 131, 118, 91, 129, 25, 57,
+ 120, 24, 33, 46, 56, 55, 56, 81, 33, 135,
+ 57, 85, 57, 57, 33, 57, 55, 45, 55, 57,
+ 57, 57, 57, 3, 77, 57, 57, 46, 133, 46,
+ 14, 45, 33, 46, 46, 79, 15, 46, 33, 46,
+ 46, 45, 57, 45, 33, 25, 43, 45, 45, 42,
+ 58, 25, 136, 45, 45, 24, 68, 25, 27, 33,
+ 28, 58, 33, 58, 54, 81, 69, 30, 36, 134,
+ 57, 29, 43, 30, 67, 42, 30, 43, 72, 78,
+ 42, 31, 76, 43, 46, 32, 42, 33, 78, 33,
+ 34, 33, 33, 5, 6, 7, 86, 87, 45, 8,
+ 124, 125, 25, 57, 38, 25, 39, 5, 5, 5,
+ 73, 40, 78, 5, 13, 13, 13, 46, 41, 42,
+ 13, 33, 43, 3, 3, 3, 44, 75, 126, 3,
+ 46, 45, 17, 18, 19, 20, 21, 22, 122, 123,
+ 58, 127, 132, 41, 137, 38, 49, 138, 37, 70,
+ 88, 121, 92, 0, 0, 0, 0, 0, 0, 93,
+ 43, 0, 0, 42, 0, 0, 0, 70, 0, 0,
+ 0, 0, 0, 0, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 0, 0,
+ 0, 0, 0, 0, 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 89, 51, 0, 0, 0,
+ 0, 0, 52, 0, 33, 33, 50, 51, 0, 51,
+ 0, 33, 33, 52, 53, 52, 57, 0, 0, 0,
+ 0, 0, 57, 0, 0, 0, 0, 0, 82, 0,
+ 46, 130, 128, 0, 33, 33, 46, 80, 0, 0,
+ 0, 33, 33, 0, 45, 0, 0, 25, 25, 0,
+ 45, 0, 0, 0, 25, 25, 0, 57, 0, 57,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 46, 93, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 45, 0, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 70, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 68, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68,
+};
+static const YYINT yycheck[] = { 10,
+ 42, 43, 34, 34, 44, 93, 41, 44, 0, 40,
+ 36, 60, 34, 10, 34, 46, 34, 63, 40, 258,
+ 40, 63, 40, 34, 46, 36, 46, 10, 46, 40,
+ 41, 42, 43, 256, 36, 46, 47, 34, 258, 36,
+ 256, 256, 34, 40, 41, 47, 262, 262, 40, 46,
+ 47, 34, 63, 36, 46, 34, 10, 40, 41, 10,
+ 91, 40, 301, 46, 47, 60, 44, 46, 262, 91,
+ 61, 91, 94, 91, 94, 121, 125, 256, 123, 299,
+ 91, 61, 36, 262, 62, 36, 61, 41, 57, 124,
+ 41, 61, 61, 47, 91, 61, 47, 61, 124, 91,
+ 42, 123, 94, 259, 260, 261, 296, 297, 91, 265,
+ 86, 87, 91, 124, 262, 94, 262, 259, 260, 261,
+ 94, 262, 124, 265, 259, 260, 261, 124, 262, 262,
+ 265, 123, 262, 259, 260, 261, 62, 10, 93, 265,
+ 262, 124, 266, 267, 268, 269, 270, 271, 258, 258,
+ 91, 45, 257, 10, 299, 10, 36, 301, 26, 54,
+ 68, 78, 73, -1, -1, -1, -1, -1, -1, 257,
+ 124, -1, -1, 124, -1, -1, -1, 93, -1, -1,
+ -1, -1, -1, -1, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, -1, -1,
+ -1, -1, -1, -1, -1, -1, 93, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, 257, -1, -1, -1,
+ -1, -1, 263, -1, 256, 257, 256, 257, -1, 257,
+ -1, 263, 264, 263, 264, 263, 257, -1, -1, -1,
+ -1, -1, 263, -1, -1, -1, -1, -1, 300, -1,
+ 257, 301, 299, -1, 256, 257, 263, 298, -1, -1,
+ -1, 263, 264, -1, 257, -1, -1, 256, 257, -1,
+ 263, -1, -1, -1, 263, 264, -1, 298, -1, 300,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 298, 257, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 298, -1, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 257, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 272, 273, 274, 275,
+ 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 257, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+ 287, 288, 289, 290, 291, 292, 293, 294, 295,
+};
+#define YYFINAL 1
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 301
+#define YYUNDFTOKEN 329
+#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? YYUNDFTOKEN : (a))
+#if YYDEBUG
+static const char *const yyname[] = {
+
+"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,"'\"'",0,"'$'",0,0,0,"'('","')'","'*'","'+'","','","'-'","'.'","'/'",0,0,
+0,0,0,0,0,0,0,0,0,0,"'<'","'='","'>'","'?'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,"'['",0,"']'","'^'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,"'{'","'|'","'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"CHAR","NUMBER","SECTEND",
+"SCDECL","XSCDECL","NAME","PREVCCL","EOF_OP","TOK_OPTION","TOK_OUTFILE",
+"TOK_PREFIX","TOK_YYCLASS","TOK_HEADER_FILE","TOK_EXTRA_TYPE","TOK_TABLES_FILE",
+"CCE_ALNUM","CCE_ALPHA","CCE_BLANK","CCE_CNTRL","CCE_DIGIT","CCE_GRAPH",
+"CCE_LOWER","CCE_PRINT","CCE_PUNCT","CCE_SPACE","CCE_UPPER","CCE_XDIGIT",
+"CCE_NEG_ALNUM","CCE_NEG_ALPHA","CCE_NEG_BLANK","CCE_NEG_CNTRL","CCE_NEG_DIGIT",
+"CCE_NEG_GRAPH","CCE_NEG_LOWER","CCE_NEG_PRINT","CCE_NEG_PUNCT","CCE_NEG_SPACE",
+"CCE_NEG_UPPER","CCE_NEG_XDIGIT","CCL_OP_DIFF","CCL_OP_UNION",
+"BEGIN_REPEAT_POSIX","END_REPEAT_POSIX","BEGIN_REPEAT_FLEX","END_REPEAT_FLEX",0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"illegal-symbol",
+};
+static const char *const yyrule[] = {
+"$accept : goal",
+"goal : initlex sect1 sect1end sect2 initforrule",
+"initlex :",
+"sect1 : sect1 startconddecl namelist1",
+"sect1 : sect1 options",
+"sect1 :",
+"sect1 : error",
+"sect1end : SECTEND",
+"startconddecl : SCDECL",
+"startconddecl : XSCDECL",
+"namelist1 : namelist1 NAME",
+"namelist1 : NAME",
+"namelist1 : error",
+"options : TOK_OPTION optionlist",
+"optionlist : optionlist option",
+"optionlist :",
+"option : TOK_OUTFILE '=' NAME",
+"option : TOK_EXTRA_TYPE '=' NAME",
+"option : TOK_PREFIX '=' NAME",
+"option : TOK_YYCLASS '=' NAME",
+"option : TOK_HEADER_FILE '=' NAME",
+"option : TOK_TABLES_FILE '=' NAME",
+"sect2 : sect2 scon initforrule flexrule '\\n'",
+"sect2 : sect2 scon '{' sect2 '}'",
+"sect2 :",
+"initforrule :",
+"flexrule : '^' rule",
+"flexrule : rule",
+"flexrule : EOF_OP",
+"flexrule : error",
+"scon_stk_ptr :",
+"scon : '<' scon_stk_ptr namelist2 '>'",
+"scon : '<' '*' '>'",
+"scon :",
+"namelist2 : namelist2 ',' sconname",
+"namelist2 : sconname",
+"namelist2 : error",
+"sconname : NAME",
+"rule : re2 re",
+"rule : re2 re '$'",
+"rule : re '$'",
+"rule : re",
+"re : re '|' series",
+"re : series",
+"re2 : re '/'",
+"series : series singleton",
+"series : singleton",
+"series : series BEGIN_REPEAT_POSIX NUMBER ',' NUMBER END_REPEAT_POSIX",
+"series : series BEGIN_REPEAT_POSIX NUMBER ',' END_REPEAT_POSIX",
+"series : series BEGIN_REPEAT_POSIX NUMBER END_REPEAT_POSIX",
+"singleton : singleton '*'",
+"singleton : singleton '+'",
+"singleton : singleton '?'",
+"singleton : singleton BEGIN_REPEAT_FLEX NUMBER ',' NUMBER END_REPEAT_FLEX",
+"singleton : singleton BEGIN_REPEAT_FLEX NUMBER ',' END_REPEAT_FLEX",
+"singleton : singleton BEGIN_REPEAT_FLEX NUMBER END_REPEAT_FLEX",
+"singleton : '.'",
+"singleton : fullccl",
+"singleton : PREVCCL",
+"singleton : '\"' string '\"'",
+"singleton : '(' re ')'",
+"singleton : CHAR",
+"fullccl : fullccl CCL_OP_DIFF braceccl",
+"fullccl : fullccl CCL_OP_UNION braceccl",
+"fullccl : braceccl",
+"braceccl : '[' ccl ']'",
+"braceccl : '[' '^' ccl ']'",
+"ccl : ccl CHAR '-' CHAR",
+"ccl : ccl CHAR",
+"ccl : ccl ccl_expr",
+"ccl :",
+"ccl_expr : CCE_ALNUM",
+"ccl_expr : CCE_ALPHA",
+"ccl_expr : CCE_BLANK",
+"ccl_expr : CCE_CNTRL",
+"ccl_expr : CCE_DIGIT",
+"ccl_expr : CCE_GRAPH",
+"ccl_expr : CCE_LOWER",
+"ccl_expr : CCE_PRINT",
+"ccl_expr : CCE_PUNCT",
+"ccl_expr : CCE_SPACE",
+"ccl_expr : CCE_XDIGIT",
+"ccl_expr : CCE_UPPER",
+"ccl_expr : CCE_NEG_ALNUM",
+"ccl_expr : CCE_NEG_ALPHA",
+"ccl_expr : CCE_NEG_BLANK",
+"ccl_expr : CCE_NEG_CNTRL",
+"ccl_expr : CCE_NEG_DIGIT",
+"ccl_expr : CCE_NEG_GRAPH",
+"ccl_expr : CCE_NEG_PRINT",
+"ccl_expr : CCE_NEG_PUNCT",
+"ccl_expr : CCE_NEG_SPACE",
+"ccl_expr : CCE_NEG_XDIGIT",
+"ccl_expr : CCE_NEG_LOWER",
+"ccl_expr : CCE_NEG_UPPER",
+"string : string CHAR",
+"string :",
+
+};
+#endif
+
+#if YYDEBUG
+int yydebug;
+#endif
+
+int yyerrflag;
+int yychar;
+YYSTYPE yyval;
+YYSTYPE yylval;
+int yynerrs;
+
+/* define the initial stack-sizes */
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+
+#define YYINITSTACKSIZE 200
+
+typedef struct {
+ unsigned stacksize;
+ YYINT *s_base;
+ YYINT *s_mark;
+ YYINT *s_last;
+ YYSTYPE *l_base;
+ YYSTYPE *l_mark;
+} YYSTACKDATA;
+/* variables for the parser stack */
+static YYSTACKDATA yystack;
+#line 950 "parse.y"
+
+
+/* build_eof_action - build the "<<EOF>>" action for the active start
+ * conditions
+ */
+
+void build_eof_action(void)
+ {
+ int i;
+ char action_text[MAXLINE];
+
+ for ( i = 1; i <= scon_stk_ptr; ++i )
+ {
+ if ( sceof[scon_stk[i]] )
+ format_pinpoint_message(
+ "multiple <<EOF>> rules for start condition %s",
+ scname[scon_stk[i]] );
+
+ else
+ {
+ sceof[scon_stk[i]] = true;
+
+ if (previous_continued_action /* && previous action was regular */)
+ add_action("YY_RULE_SETUP\n");
+
+ snprintf( action_text, sizeof(action_text), "case YY_STATE_EOF(%s):\n",
+ scname[scon_stk[i]] );
+ add_action( action_text );
+ }
+ }
+
+ line_directive_out(NULL, 1);
+ add_action("[[");
+
+ /* This isn't a normal rule after all - don't count it as
+ * such, so we don't have any holes in the rule numbering
+ * (which make generating "rule can never match" warnings
+ * more difficult.
+ */
+ --num_rules;
+ ++num_eof_rules;
+ }
+
+
+/* format_synerr - write out formatted syntax error */
+
+void format_synerr( const char *msg, const char arg[] )
+ {
+ char errmsg[MAXLINE];
+
+ (void) snprintf( errmsg, sizeof(errmsg), msg, arg );
+ synerr( errmsg );
+ }
+
+
+/* synerr - report a syntax error */
+
+void synerr( const char *str )
+ {
+ syntaxerror = true;
+ pinpoint_message( str );
+ }
+
+
+/* format_warn - write out formatted warning */
+
+void format_warn( const char *msg, const char arg[] )
+ {
+ char warn_msg[MAXLINE];
+
+ snprintf( warn_msg, sizeof(warn_msg), msg, arg );
+ lwarn( warn_msg );
+ }
+
+
+/* lwarn - report a warning, unless -w was given */
+
+void lwarn( const char *str )
+ {
+ line_warning( str, linenum );
+ }
+
+/* format_pinpoint_message - write out a message formatted with one string,
+ * pinpointing its location
+ */
+
+void format_pinpoint_message( const char *msg, const char arg[] )
+ {
+ char errmsg[MAXLINE];
+
+ snprintf( errmsg, sizeof(errmsg), msg, arg );
+ pinpoint_message( errmsg );
+ }
+
+
+/* pinpoint_message - write out a message, pinpointing its location */
+
+void pinpoint_message( const char *str )
+ {
+ line_pinpoint( str, linenum );
+ }
+
+
+/* line_warning - report a warning at a given line, unless -w was given */
+
+void line_warning( const char *str, int line )
+ {
+ char warning[MAXLINE];
+
+ if ( ! nowarn )
+ {
+ snprintf( warning, sizeof(warning), "warning, %s", str );
+ line_pinpoint( warning, line );
+ }
+ }
+
+
+/* line_pinpoint - write out a message, pinpointing it at the given line */
+
+void line_pinpoint( const char *str, int line )
+ {
+ fprintf( stderr, "%s:%d: %s\n", infilename, line, str );
+ }
+
+
+/* yyerror - eat up an error message from the parser;
+ * currently, messages are ignore
+ */
+
+void yyerror( const char *msg )
+ {
+ (void)msg;
+ }
+#line 662 "parse.c"
+
+#if YYDEBUG
+#include <stdio.h> /* needed for printf */
+#endif
+
+#include <stdlib.h> /* needed for malloc, etc */
+#include <string.h> /* needed for memset */
+
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+static int yygrowstack(YYSTACKDATA *data)
+{
+ int i;
+ unsigned newsize;
+ YYINT *newss;
+ YYSTYPE *newvs;
+
+ if ((newsize = data->stacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return YYENOMEM;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+
+ i = (int) (data->s_mark - data->s_base);
+ newss = (YYINT *)realloc(data->s_base, newsize * sizeof(*newss));
+ if (newss == NULL)
+ return YYENOMEM;
+
+ data->s_base = newss;
+ data->s_mark = newss + i;
+
+ newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
+ if (newvs == NULL)
+ return YYENOMEM;
+
+ data->l_base = newvs;
+ data->l_mark = newvs + i;
+
+ data->stacksize = newsize;
+ data->s_last = data->s_base + newsize - 1;
+ return 0;
+}
+
+#if YYPURE || defined(YY_NO_LEAKS)
+static void yyfreestack(YYSTACKDATA *data)
+{
+ free(data->s_base);
+ free(data->l_base);
+ memset(data, 0, sizeof(*data));
+}
+#else
+#define yyfreestack(data) /* nothing */
+#endif
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+
+int
+YYPARSE_DECL()
+{
+ int yym, yyn, yystate;
+#if YYDEBUG
+ const char *yys;
+
+ if ((yys = getenv("YYDEBUG")) != NULL)
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yym = 0;
+ yyn = 0;
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = YYEMPTY;
+ yystate = 0;
+
+#if YYPURE
+ memset(&yystack, 0, sizeof(yystack));
+#endif
+
+ if (yystack.s_base == NULL && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystack.s_mark = yystack.s_base;
+ yystack.l_mark = yystack.l_base;
+ yystate = 0;
+ *yystack.s_mark = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+ yychar = YYLEX;
+ if (yychar < 0) yychar = YYEOF;
+#if YYDEBUG
+ if (yydebug)
+ {
+ if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if (((yyn = yysindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+ yychar = YYEMPTY;
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if (((yyn = yyrindex[yystate]) != 0) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag != 0) goto yyinrecovery;
+
+ YYERROR_CALL("syntax error");
+
+ goto yyerrlab; /* redundant goto avoids 'unused label' warning */
+yyerrlab:
+ ++yynerrs;
+
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if (((yyn = yysindex[*yystack.s_mark]) != 0) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ yystate = yytable[yyn];
+ *++yystack.s_mark = yytable[yyn];
+ *++yystack.l_mark = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yystack.s_mark);
+#endif
+ if (yystack.s_mark <= yystack.s_base) goto yyabort;
+ --yystack.s_mark;
+ --yystack.l_mark;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == YYEOF) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = YYEMPTY;
+ goto yyloop;
+ }
+
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ if (yym > 0)
+ yyval = yystack.l_mark[1-yym];
+ else
+ memset(&yyval, 0, sizeof yyval);
+
+ switch (yyn)
+ {
+case 1:
+#line 119 "parse.y"
+ { /* add default rule */
+ int def_rule;
+
+ pat = cclinit();
+ cclnegate( pat );
+
+ def_rule = mkstate( -pat );
+
+ /* Remember the number of the default rule so we
+ * don't generate "can't match" warnings for it.
+ */
+ default_rule = num_rules;
+
+ finish_rule( def_rule, false, 0, 0, 0);
+
+ for ( i = 1; i <= lastsc; ++i )
+ scset[i] = mkbranch( scset[i], def_rule );
+
+ if ( spprdflt )
+ add_action(
+ "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
+ else
+ add_action( "ECHO" );
+
+ add_action( ";\n\tYY_BREAK]]\n" );
+ }
+break;
+case 2:
+#line 148 "parse.y"
+ { /* initialize for processing rules */
+
+ /* Create default DFA start condition. */
+ scinstal( "INITIAL", false );
+ }
+break;
+case 6:
+#line 159 "parse.y"
+ { synerr( _("unknown error processing section 1") ); }
+break;
+case 7:
+#line 163 "parse.y"
+ {
+ check_options();
+ scon_stk = allocate_integer_array( lastsc + 1 );
+ scon_stk_ptr = 0;
+ }
+break;
+case 8:
+#line 171 "parse.y"
+ { xcluflg = false; }
+break;
+case 9:
+#line 174 "parse.y"
+ { xcluflg = true; }
+break;
+case 10:
+#line 178 "parse.y"
+ { scinstal( nmstr, xcluflg ); }
+break;
+case 11:
+#line 181 "parse.y"
+ { scinstal( nmstr, xcluflg ); }
+break;
+case 12:
+#line 184 "parse.y"
+ { synerr( _("bad start condition list") ); }
+break;
+case 16:
+#line 195 "parse.y"
+ {
+ outfilename = xstrdup(nmstr);
+ did_outfilename = 1;
+ }
+break;
+case 17:
+#line 200 "parse.y"
+ { extra_type = xstrdup(nmstr); }
+break;
+case 18:
+#line 202 "parse.y"
+ { prefix = xstrdup(nmstr);
+ if (strchr(prefix, '[') || strchr(prefix, ']'))
+ flexerror(_("Prefix must not contain [ or ]")); }
+break;
+case 19:
+#line 206 "parse.y"
+ { yyclass = xstrdup(nmstr); }
+break;
+case 20:
+#line 208 "parse.y"
+ { headerfilename = xstrdup(nmstr); }
+break;
+case 21:
+#line 210 "parse.y"
+ { tablesext = true; tablesfilename = xstrdup(nmstr); }
+break;
+case 22:
+#line 214 "parse.y"
+ { scon_stk_ptr = yystack.l_mark[-3]; }
+break;
+case 23:
+#line 216 "parse.y"
+ { scon_stk_ptr = yystack.l_mark[-3]; }
+break;
+case 25:
+#line 221 "parse.y"
+ {
+ /* Initialize for a parse of one rule. */
+ trlcontxt = variable_trail_rule = varlength = false;
+ trailcnt = headcnt = rulelen = 0;
+ current_state_type = STATE_NORMAL;
+ previous_continued_action = continued_action;
+ in_rule = true;
+
+ new_rule();
+ }
+break;
+case 26:
+#line 234 "parse.y"
+ {
+ pat = yystack.l_mark[0];
+ finish_rule( pat, variable_trail_rule,
+ headcnt, trailcnt , previous_continued_action);
+
+ if ( scon_stk_ptr > 0 )
+ {
+ for ( i = 1; i <= scon_stk_ptr; ++i )
+ scbol[scon_stk[i]] =
+ mkbranch( scbol[scon_stk[i]],
+ pat );
+ }
+
+ else
+ {
+ /* Add to all non-exclusive start conditions,
+ * including the default (0) start condition.
+ */
+
+ for ( i = 1; i <= lastsc; ++i )
+ if ( ! scxclu[i] )
+ scbol[i] = mkbranch( scbol[i],
+ pat );
+ }
+
+ if ( ! bol_needed )
+ {
+ bol_needed = true;
+
+ if ( performance_report > 1 )
+ pinpoint_message(
+ "'^' operator results in sub-optimal performance" );
+ }
+ }
+break;
+case 27:
+#line 270 "parse.y"
+ {
+ pat = yystack.l_mark[0];
+ finish_rule( pat, variable_trail_rule,
+ headcnt, trailcnt , previous_continued_action);
+
+ if ( scon_stk_ptr > 0 )
+ {
+ for ( i = 1; i <= scon_stk_ptr; ++i )
+ scset[scon_stk[i]] =
+ mkbranch( scset[scon_stk[i]],
+ pat );
+ }
+
+ else
+ {
+ for ( i = 1; i <= lastsc; ++i )
+ if ( ! scxclu[i] )
+ scset[i] =
+ mkbranch( scset[i],
+ pat );
+ }
+ }
+break;
+case 28:
+#line 294 "parse.y"
+ {
+ if ( scon_stk_ptr > 0 )
+ build_eof_action();
+
+ else
+ {
+ /* This EOF applies to all start conditions
+ * which don't already have EOF actions.
+ */
+ for ( i = 1; i <= lastsc; ++i )
+ if ( ! sceof[i] )
+ scon_stk[++scon_stk_ptr] = i;
+
+ if ( scon_stk_ptr == 0 )
+ lwarn(
+ "all start conditions already have <<EOF>> rules" );
+
+ else
+ build_eof_action();
+ }
+ }
+break;
+case 29:
+#line 317 "parse.y"
+ { synerr( _("unrecognized rule") ); }
+break;
+case 30:
+#line 321 "parse.y"
+ { yyval = scon_stk_ptr; }
+break;
+case 31:
+#line 325 "parse.y"
+ { yyval = yystack.l_mark[-2]; }
+break;
+case 32:
+#line 328 "parse.y"
+ {
+ yyval = scon_stk_ptr;
+
+ for ( i = 1; i <= lastsc; ++i )
+ {
+ int j;
+
+ for ( j = 1; j <= scon_stk_ptr; ++j )
+ if ( scon_stk[j] == i )
+ break;
+
+ if ( j > scon_stk_ptr )
+ scon_stk[++scon_stk_ptr] = i;
+ }
+ }
+break;
+case 33:
+#line 345 "parse.y"
+ { yyval = scon_stk_ptr; }
+break;
+case 36:
+#line 353 "parse.y"
+ { synerr( _("bad start condition list") ); }
+break;
+case 37:
+#line 357 "parse.y"
+ {
+ if ( (scnum = sclookup( nmstr )) == 0 )
+ format_pinpoint_message(
+ "undeclared start condition %s",
+ nmstr );
+ else
+ {
+ for ( i = 1; i <= scon_stk_ptr; ++i )
+ if ( scon_stk[i] == scnum )
+ {
+ format_warn(
+ "<%s> specified twice",
+ scname[scnum] );
+ break;
+ }
+
+ if ( i > scon_stk_ptr )
+ scon_stk[++scon_stk_ptr] = scnum;
+ }
+ }
+break;
+case 38:
+#line 380 "parse.y"
+ {
+ if ( transchar[lastst[yystack.l_mark[0]]] != SYM_EPSILON )
+ /* Provide final transition \now/ so it
+ * will be marked as a trailing context
+ * state.
+ */
+ yystack.l_mark[0] = link_machines( yystack.l_mark[0],
+ mkstate( SYM_EPSILON ) );
+
+ mark_beginning_as_normal( yystack.l_mark[0] );
+ current_state_type = STATE_NORMAL;
+
+ if ( previous_continued_action )
+ {
+ /* We need to treat this as variable trailing
+ * context so that the backup does not happen
+ * in the action but before the action switch
+ * statement. If the backup happens in the
+ * action, then the rules "falling into" this
+ * one's action will *also* do the backup,
+ * erroneously.
+ */
+ if ( ! varlength || headcnt != 0 )
+ lwarn(
+ "trailing context made variable due to preceding '|' action" );
+
+ /* Mark as variable. */
+ varlength = true;
+ headcnt = 0;
+
+ }
+
+ if ( lex_compat || (varlength && headcnt == 0) )
+ { /* variable trailing context rule */
+ /* Mark the first part of the rule as the
+ * accepting "head" part of a trailing
+ * context rule.
+ *
+ * By the way, we didn't do this at the
+ * beginning of this production because back
+ * then current_state_type was set up for a
+ * trail rule, and add_accept() can create
+ * a new state ...
+ */
+ add_accept( yystack.l_mark[-1],
+ num_rules | YY_TRAILING_HEAD_MASK );
+ variable_trail_rule = true;
+ }
+
+ else
+ trailcnt = rulelen;
+
+ yyval = link_machines( yystack.l_mark[-1], yystack.l_mark[0] );
+ }
+break;
+case 39:
+#line 436 "parse.y"
+ { synerr( _("trailing context used twice") ); }
+break;
+case 40:
+#line 439 "parse.y"
+ {
+ headcnt = 0;
+ trailcnt = 1;
+ rulelen = 1;
+ varlength = false;
+
+ current_state_type = STATE_TRAILING_CONTEXT;
+
+ if ( trlcontxt )
+ {
+ synerr( _("trailing context used twice") );
+ yyval = mkstate( SYM_EPSILON );
+ }
+
+ else if ( previous_continued_action )
+ {
+ /* See the comment in the rule for "re2 re"
+ * above.
+ */
+ lwarn(
+ "trailing context made variable due to preceding '|' action" );
+
+ varlength = true;
+ }
+
+ if ( lex_compat || varlength )
+ {
+ /* Again, see the comment in the rule for
+ * "re2 re" above.
+ */
+ add_accept( yystack.l_mark[-1],
+ num_rules | YY_TRAILING_HEAD_MASK );
+ variable_trail_rule = true;
+ }
+
+ trlcontxt = true;
+
+ eps = mkstate( SYM_EPSILON );
+ yyval = link_machines( yystack.l_mark[-1],
+ link_machines( eps, mkstate( '\n' ) ) );
+ }
+break;
+case 41:
+#line 482 "parse.y"
+ {
+ yyval = yystack.l_mark[0];
+
+ if ( trlcontxt )
+ {
+ if ( lex_compat || (varlength && headcnt == 0) )
+ /* Both head and trail are
+ * variable-length.
+ */
+ variable_trail_rule = true;
+ else
+ trailcnt = rulelen;
+ }
+ }
+break;
+case 42:
+#line 500 "parse.y"
+ {
+ varlength = true;
+ yyval = mkor( yystack.l_mark[-2], yystack.l_mark[0] );
+ }
+break;
+case 43:
+#line 506 "parse.y"
+ { yyval = yystack.l_mark[0]; }
+break;
+case 44:
+#line 511 "parse.y"
+ {
+ /* This rule is written separately so the
+ * reduction will occur before the trailing
+ * series is parsed.
+ */
+
+ if ( trlcontxt )
+ synerr( _("trailing context used twice") );
+ else
+ trlcontxt = true;
+
+ if ( varlength )
+ /* We hope the trailing context is
+ * fixed-length.
+ */
+ varlength = false;
+ else
+ headcnt = rulelen;
+
+ rulelen = 0;
+
+ current_state_type = STATE_TRAILING_CONTEXT;
+ yyval = yystack.l_mark[-1];
+ }
+break;
+case 45:
+#line 538 "parse.y"
+ {
+ /* This is where concatenation of adjacent patterns
+ * gets done.
+ */
+ yyval = link_machines( yystack.l_mark[-1], yystack.l_mark[0] );
+ }
+break;
+case 46:
+#line 546 "parse.y"
+ { yyval = yystack.l_mark[0]; }
+break;
+case 47:
+#line 549 "parse.y"
+ {
+ varlength = true;
+
+ if ( yystack.l_mark[-3] > yystack.l_mark[-1] || yystack.l_mark[-3] < 0 )
+ {
+ synerr( _("bad iteration values") );
+ yyval = yystack.l_mark[-5];
+ }
+ else
+ {
+ if ( yystack.l_mark[-3] == 0 )
+ {
+ if ( yystack.l_mark[-1] <= 0 )
+ {
+ synerr(
+ _("bad iteration values") );
+ yyval = yystack.l_mark[-5];
+ }
+ else
+ yyval = mkopt(
+ mkrep( yystack.l_mark[-5], 1, yystack.l_mark[-1] ) );
+ }
+ else
+ yyval = mkrep( yystack.l_mark[-5], yystack.l_mark[-3], yystack.l_mark[-1] );
+ }
+ }
+break;
+case 48:
+#line 577 "parse.y"
+ {
+ varlength = true;
+
+ if ( yystack.l_mark[-2] <= 0 )
+ {
+ synerr( _("iteration value must be positive") );
+ yyval = yystack.l_mark[-4];
+ }
+
+ else
+ yyval = mkrep( yystack.l_mark[-4], yystack.l_mark[-2], INFINITE_REPEAT );
+ }
+break;
+case 49:
+#line 591 "parse.y"
+ {
+ /* The series could be something like "(foo)",
+ * in which case we have no idea what its length
+ * is, so we punt here.
+ */
+ varlength = true;
+
+ if ( yystack.l_mark[-1] <= 0 )
+ {
+ synerr( _("iteration value must be positive")
+ );
+ yyval = yystack.l_mark[-3];
+ }
+
+ else
+ yyval = link_machines( yystack.l_mark[-3],
+ copysingl( yystack.l_mark[-3], yystack.l_mark[-1] - 1 ) );
+ }
+break;
+case 50:
+#line 613 "parse.y"
+ {
+ varlength = true;
+
+ yyval = mkclos( yystack.l_mark[-1] );
+ }
+break;
+case 51:
+#line 620 "parse.y"
+ {
+ varlength = true;
+ yyval = mkposcl( yystack.l_mark[-1] );
+ }
+break;
+case 52:
+#line 626 "parse.y"
+ {
+ varlength = true;
+ yyval = mkopt( yystack.l_mark[-1] );
+ }
+break;
+case 53:
+#line 632 "parse.y"
+ {
+ varlength = true;
+
+ if ( yystack.l_mark[-3] > yystack.l_mark[-1] || yystack.l_mark[-3] < 0 )
+ {
+ synerr( _("bad iteration values") );
+ yyval = yystack.l_mark[-5];
+ }
+ else
+ {
+ if ( yystack.l_mark[-3] == 0 )
+ {
+ if ( yystack.l_mark[-1] <= 0 )
+ {
+ synerr(
+ _("bad iteration values") );
+ yyval = yystack.l_mark[-5];
+ }
+ else
+ yyval = mkopt(
+ mkrep( yystack.l_mark[-5], 1, yystack.l_mark[-1] ) );
+ }
+ else
+ yyval = mkrep( yystack.l_mark[-5], yystack.l_mark[-3], yystack.l_mark[-1] );
+ }
+ }
+break;
+case 54:
+#line 660 "parse.y"
+ {
+ varlength = true;
+
+ if ( yystack.l_mark[-2] <= 0 )
+ {
+ synerr( _("iteration value must be positive") );
+ yyval = yystack.l_mark[-4];
+ }
+
+ else
+ yyval = mkrep( yystack.l_mark[-4], yystack.l_mark[-2], INFINITE_REPEAT );
+ }
+break;
+case 55:
+#line 674 "parse.y"
+ {
+ /* The singleton could be something like "(foo)",
+ * in which case we have no idea what its length
+ * is, so we punt here.
+ */
+ varlength = true;
+
+ if ( yystack.l_mark[-1] <= 0 )
+ {
+ synerr( _("iteration value must be positive") );
+ yyval = yystack.l_mark[-3];
+ }
+
+ else
+ yyval = link_machines( yystack.l_mark[-3],
+ copysingl( yystack.l_mark[-3], yystack.l_mark[-1] - 1 ) );
+ }
+break;
+case 56:
+#line 693 "parse.y"
+ {
+ if ( ! madeany )
+ {
+ /* Create the '.' character class. */
+ ccldot = cclinit();
+ ccladd( ccldot, '\n' );
+ cclnegate( ccldot );
+
+ if ( useecs )
+ mkeccl( ccltbl + cclmap[ccldot],
+ ccllen[ccldot], nextecm,
+ ecgroup, csize, csize );
+
+ /* Create the (?s:'.') character class. */
+ cclany = cclinit();
+ cclnegate( cclany );
+
+ if ( useecs )
+ mkeccl( ccltbl + cclmap[cclany],
+ ccllen[cclany], nextecm,
+ ecgroup, csize, csize );
+
+ madeany = true;
+ }
+
+ ++rulelen;
+
+ if (sf_dot_all())
+ yyval = mkstate( -cclany );
+ else
+ yyval = mkstate( -ccldot );
+ }
+break;
+case 57:
+#line 727 "parse.y"
+ {
+ /* Sort characters for fast searching.
+ */
+ qsort( ccltbl + cclmap[yystack.l_mark[0]], (size_t) ccllen[yystack.l_mark[0]], sizeof (*ccltbl), cclcmp );
+
+ if ( useecs )
+ mkeccl( ccltbl + cclmap[yystack.l_mark[0]], ccllen[yystack.l_mark[0]],
+ nextecm, ecgroup, csize, csize );
+
+ ++rulelen;
+
+ if (ccl_has_nl[yystack.l_mark[0]])
+ rule_has_nl[num_rules] = true;
+
+ yyval = mkstate( -yystack.l_mark[0] );
+ }
+break;
+case 58:
+#line 745 "parse.y"
+ {
+ ++rulelen;
+
+ if (ccl_has_nl[yystack.l_mark[0]])
+ rule_has_nl[num_rules] = true;
+
+ yyval = mkstate( -yystack.l_mark[0] );
+ }
+break;
+case 59:
+#line 755 "parse.y"
+ { yyval = yystack.l_mark[-1]; }
+break;
+case 60:
+#line 758 "parse.y"
+ { yyval = yystack.l_mark[-1]; }
+break;
+case 61:
+#line 761 "parse.y"
+ {
+ ++rulelen;
+
+ if (yystack.l_mark[0] == nlch)
+ rule_has_nl[num_rules] = true;
+
+ if (sf_case_ins() && has_case(yystack.l_mark[0]))
+ /* create an alternation, as in (a|A) */
+ yyval = mkor (mkstate(yystack.l_mark[0]), mkstate(reverse_case(yystack.l_mark[0])));
+ else
+ yyval = mkstate( yystack.l_mark[0] );
+ }
+break;
+case 62:
+#line 775 "parse.y"
+ { yyval = ccl_set_diff (yystack.l_mark[-2], yystack.l_mark[0]); }
+break;
+case 63:
+#line 776 "parse.y"
+ { yyval = ccl_set_union (yystack.l_mark[-2], yystack.l_mark[0]); }
+break;
+case 65:
+#line 782 "parse.y"
+ { yyval = yystack.l_mark[-1]; }
+break;
+case 66:
+#line 785 "parse.y"
+ {
+ cclnegate( yystack.l_mark[-1] );
+ yyval = yystack.l_mark[-1];
+ }
+break;
+case 67:
+#line 792 "parse.y"
+ {
+
+ if (sf_case_ins())
+ {
+
+ /* If one end of the range has case and the other
+ * does not, or the cases are different, then we're not
+ * sure what range the user is trying to express.
+ * Examples: [@-z] or [S-t]
+ */
+ if (has_case (yystack.l_mark[-2]) != has_case (yystack.l_mark[0])
+ || (has_case (yystack.l_mark[-2]) && (b_islower (yystack.l_mark[-2]) != b_islower (yystack.l_mark[0])))
+ || (has_case (yystack.l_mark[-2]) && (b_isupper (yystack.l_mark[-2]) != b_isupper (yystack.l_mark[0]))))
+ format_warn3 (
+ _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"),
+ yystack.l_mark[-2], yystack.l_mark[0]);
+
+ /* If the range spans uppercase characters but not
+ * lowercase (or vice-versa), then should we automatically
+ * include lowercase characters in the range?
+ * Example: [@-_] spans [a-z] but not [A-Z]
+ */
+ else if (!has_case (yystack.l_mark[-2]) && !has_case (yystack.l_mark[0]) && !range_covers_case (yystack.l_mark[-2], yystack.l_mark[0]))
+ format_warn3 (
+ _("the character range [%c-%c] is ambiguous in a case-insensitive scanner"),
+ yystack.l_mark[-2], yystack.l_mark[0]);
+ }
+
+ if ( yystack.l_mark[-2] > yystack.l_mark[0] )
+ synerr( _("negative range in character class") );
+
+ else
+ {
+ for ( i = yystack.l_mark[-2]; i <= yystack.l_mark[0]; ++i )
+ ccladd( yystack.l_mark[-3], i );
+
+ /* Keep track if this ccl is staying in
+ * alphabetical order.
+ */
+ cclsorted = cclsorted && (yystack.l_mark[-2] > lastchar);
+ lastchar = yystack.l_mark[0];
+
+ /* Do it again for upper/lowercase */
+ if (sf_case_ins() && has_case(yystack.l_mark[-2]) && has_case(yystack.l_mark[0])){
+ yystack.l_mark[-2] = reverse_case (yystack.l_mark[-2]);
+ yystack.l_mark[0] = reverse_case (yystack.l_mark[0]);
+
+ for ( i = yystack.l_mark[-2]; i <= yystack.l_mark[0]; ++i )
+ ccladd( yystack.l_mark[-3], i );
+
+ cclsorted = cclsorted && (yystack.l_mark[-2] > lastchar);
+ lastchar = yystack.l_mark[0];
+ }
+
+ }
+
+ yyval = yystack.l_mark[-3];
+ }
+break;
+case 68:
+#line 852 "parse.y"
+ {
+ ccladd( yystack.l_mark[-1], yystack.l_mark[0] );
+ cclsorted = cclsorted && (yystack.l_mark[0] > lastchar);
+ lastchar = yystack.l_mark[0];
+
+ /* Do it again for upper/lowercase */
+ if (sf_case_ins() && has_case(yystack.l_mark[0])){
+ yystack.l_mark[0] = reverse_case (yystack.l_mark[0]);
+ ccladd (yystack.l_mark[-1], yystack.l_mark[0]);
+
+ cclsorted = cclsorted && (yystack.l_mark[0] > lastchar);
+ lastchar = yystack.l_mark[0];
+ }
+
+ yyval = yystack.l_mark[-1];
+ }
+break;
+case 69:
+#line 870 "parse.y"
+ {
+ /* Too hard to properly maintain cclsorted. */
+ cclsorted = false;
+ yyval = yystack.l_mark[-1];
+ }
+break;
+case 70:
+#line 877 "parse.y"
+ {
+ cclsorted = true;
+ lastchar = 0;
+ currccl = yyval = cclinit();
+ }
+break;
+case 71:
+#line 885 "parse.y"
+ { CCL_EXPR(isalnum); }
+break;
+case 72:
+#line 886 "parse.y"
+ { CCL_EXPR(isalpha); }
+break;
+case 73:
+#line 887 "parse.y"
+ { CCL_EXPR(IS_BLANK); }
+break;
+case 74:
+#line 888 "parse.y"
+ { CCL_EXPR(iscntrl); }
+break;
+case 75:
+#line 889 "parse.y"
+ { CCL_EXPR(isdigit); }
+break;
+case 76:
+#line 890 "parse.y"
+ { CCL_EXPR(isgraph); }
+break;
+case 77:
+#line 891 "parse.y"
+ {
+ CCL_EXPR(islower);
+ if (sf_case_ins())
+ CCL_EXPR(isupper);
+ }
+break;
+case 78:
+#line 896 "parse.y"
+ { CCL_EXPR(isprint); }
+break;
+case 79:
+#line 897 "parse.y"
+ { CCL_EXPR(ispunct); }
+break;
+case 80:
+#line 898 "parse.y"
+ { CCL_EXPR(isspace); }
+break;
+case 81:
+#line 899 "parse.y"
+ { CCL_EXPR(isxdigit); }
+break;
+case 82:
+#line 900 "parse.y"
+ {
+ CCL_EXPR(isupper);
+ if (sf_case_ins())
+ CCL_EXPR(islower);
+ }
+break;
+case 83:
+#line 906 "parse.y"
+ { CCL_NEG_EXPR(isalnum); }
+break;
+case 84:
+#line 907 "parse.y"
+ { CCL_NEG_EXPR(isalpha); }
+break;
+case 85:
+#line 908 "parse.y"
+ { CCL_NEG_EXPR(IS_BLANK); }
+break;
+case 86:
+#line 909 "parse.y"
+ { CCL_NEG_EXPR(iscntrl); }
+break;
+case 87:
+#line 910 "parse.y"
+ { CCL_NEG_EXPR(isdigit); }
+break;
+case 88:
+#line 911 "parse.y"
+ { CCL_NEG_EXPR(isgraph); }
+break;
+case 89:
+#line 912 "parse.y"
+ { CCL_NEG_EXPR(isprint); }
+break;
+case 90:
+#line 913 "parse.y"
+ { CCL_NEG_EXPR(ispunct); }
+break;
+case 91:
+#line 914 "parse.y"
+ { CCL_NEG_EXPR(isspace); }
+break;
+case 92:
+#line 915 "parse.y"
+ { CCL_NEG_EXPR(isxdigit); }
+break;
+case 93:
+#line 916 "parse.y"
+ {
+ if ( sf_case_ins() )
+ lwarn(_("[:^lower:] is ambiguous in case insensitive scanner"));
+ else
+ CCL_NEG_EXPR(islower);
+ }
+break;
+case 94:
+#line 922 "parse.y"
+ {
+ if ( sf_case_ins() )
+ lwarn(_("[:^upper:] ambiguous in case insensitive scanner"));
+ else
+ CCL_NEG_EXPR(isupper);
+ }
+break;
+case 95:
+#line 931 "parse.y"
+ {
+ if ( yystack.l_mark[0] == nlch )
+ rule_has_nl[num_rules] = true;
+
+ ++rulelen;
+
+ if (sf_case_ins() && has_case(yystack.l_mark[0]))
+ yyval = mkor (mkstate(yystack.l_mark[0]), mkstate(reverse_case(yystack.l_mark[0])));
+ else
+ yyval = mkstate (yystack.l_mark[0]);
+
+ yyval = link_machines( yystack.l_mark[-1], yyval);
+ }
+break;
+case 96:
+#line 946 "parse.y"
+ { yyval = mkstate( SYM_EPSILON ); }
+break;
+#line 1788 "parse.c"
+ }
+ yystack.s_mark -= yym;
+ yystate = *yystack.s_mark;
+ yystack.l_mark -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yystack.s_mark = YYFINAL;
+ *++yystack.l_mark = yyval;
+ if (yychar < 0)
+ {
+ yychar = YYLEX;
+ if (yychar < 0) yychar = YYEOF;
+#if YYDEBUG
+ if (yydebug)
+ {
+ if ((yys = yyname[YYTRANSLATE(yychar)]) == NULL) yys = yyname[YYUNDFTOKEN];
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == YYEOF) goto yyaccept;
+ goto yyloop;
+ }
+ if (((yyn = yygindex[yym]) != 0) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == (YYINT) yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
+#endif
+ if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack) == YYENOMEM) goto yyoverflow;
+ *++yystack.s_mark = (YYINT) yystate;
+ *++yystack.l_mark = yyval;
+ goto yyloop;
+
+yyoverflow:
+ YYERROR_CALL("yacc stack overflow");
+
+yyabort:
+ yyfreestack(&yystack);
+ return (1);
+
+yyaccept:
+ yyfreestack(&yystack);
+ return (0);
+}
diff --git a/usr.bin/lex/initparse.h b/usr.bin/lex/initparse.h
new file mode 100644
index 000000000000..b630d282c635
--- /dev/null
+++ b/usr.bin/lex/initparse.h
@@ -0,0 +1,45 @@
+#define CHAR 257
+#define NUMBER 258
+#define SECTEND 259
+#define SCDECL 260
+#define XSCDECL 261
+#define NAME 262
+#define PREVCCL 263
+#define EOF_OP 264
+#define TOK_OPTION 265
+#define TOK_OUTFILE 266
+#define TOK_PREFIX 267
+#define TOK_YYCLASS 268
+#define TOK_HEADER_FILE 269
+#define TOK_EXTRA_TYPE 270
+#define TOK_TABLES_FILE 271
+#define CCE_ALNUM 272
+#define CCE_ALPHA 273
+#define CCE_BLANK 274
+#define CCE_CNTRL 275
+#define CCE_DIGIT 276
+#define CCE_GRAPH 277
+#define CCE_LOWER 278
+#define CCE_PRINT 279
+#define CCE_PUNCT 280
+#define CCE_SPACE 281
+#define CCE_UPPER 282
+#define CCE_XDIGIT 283
+#define CCE_NEG_ALNUM 284
+#define CCE_NEG_ALPHA 285
+#define CCE_NEG_BLANK 286
+#define CCE_NEG_CNTRL 287
+#define CCE_NEG_DIGIT 288
+#define CCE_NEG_GRAPH 289
+#define CCE_NEG_LOWER 290
+#define CCE_NEG_PRINT 291
+#define CCE_NEG_PUNCT 292
+#define CCE_NEG_SPACE 293
+#define CCE_NEG_UPPER 294
+#define CCE_NEG_XDIGIT 295
+#define CCL_OP_DIFF 296
+#define CCL_OP_UNION 297
+#define BEGIN_REPEAT_POSIX 298
+#define END_REPEAT_POSIX 299
+#define BEGIN_REPEAT_FLEX 300
+#define END_REPEAT_FLEX 301
diff --git a/usr.bin/lex/initscan.c b/usr.bin/lex/initscan.c
new file mode 100644
index 000000000000..5c2701d060da
--- /dev/null
+++ b/usr.bin/lex/initscan.c
@@ -0,0 +1,5241 @@
+
+#line 2 "<stdout>"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined(__FreeBSD__) || \
+ (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+ #define YY_LINENO_REWIND_TO(ptr)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ int yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+#define yy_current_buffer YY_CURRENT_BUFFER
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = NULL;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart ( FILE *input_file );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
+void yy_delete_buffer ( YY_BUFFER_STATE b );
+void yy_flush_buffer ( YY_BUFFER_STATE b );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state ( void );
+
+static void yyensure_buffer_stack ( void );
+static void yy_load_buffer_state ( void );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
+
+void *yyalloc ( yy_size_t );
+void *yyrealloc ( void *, yy_size_t );
+void yyfree ( void * );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+typedef flex_uint8_t YY_CHAR;
+
+FILE *yyin = NULL, *yyout = NULL;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+int yylineno = 1;
+
+extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state ( void );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state );
+static int yy_get_next_buffer ( void );
+static void yynoreturn yy_fatal_error ( const char* msg );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+#define YY_NUM_RULES 253
+#define YY_END_OF_BUFFER 254
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static const flex_int16_t yy_accept[1114] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 246, 246, 40, 40,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 21, 21,
+ 239, 239, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 21, 21,
+ 250, 250, 239, 239, 254, 252, 9, 20, 252, 18,
+ 1, 19, 252, 252, 252, 252, 17, 163, 148, 149,
+ 163, 141, 163, 160, 161, 162, 162, 163, 163, 163,
+ 162, 147, 137, 163, 163, 139, 140, 135, 136, 135,
+ 134, 133, 134, 246, 247, 247, 40, 42, 40, 41,
+
+ 40, 40, 41, 41, 41, 50, 49, 51, 252, 169,
+ 169, 164, 169, 165, 166, 168, 170, 218, 219, 218,
+ 216, 215, 217, 171, 173, 171, 172, 171, 185, 185,
+ 185, 185, 187, 189, 187, 187, 187, 187, 188, 228,
+ 233, 228, 232, 231, 234, 229, 229, 229, 234, 234,
+ 226, 227, 252, 130, 252, 21, 23, 21, 22, 22,
+ 22, 235, 241, 235, 236, 242, 242, 242, 224, 224,
+ 225, 224, 224, 224, 224, 224, 224, 224, 129, 53,
+ 52, 129, 129, 129, 129, 54, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+
+ 129, 129, 129, 129, 129, 129, 129, 36, 33, 36,
+ 34, 48, 45, 252, 48, 48, 44, 43, 175, 174,
+ 176, 177, 178, 179, 180, 181, 182, 31, 32, 31,
+ 30, 28, 29, 28, 27, 22, 250, 251, 251, 237,
+ 237, 238, 9, 20, 0, 18, 1, 19, 0, 0,
+ 0, 16, 10, 0, 0, 0, 0, 4, 16, 5,
+ 0, 2, 17, 148, 149, 0, 0, 0, 143, 0,
+ 159, 157, 0, 153, 153, 0, 243, 243, 243, 0,
+ 0, 142, 0, 147, 137, 0, 0, 0, 139, 140,
+ 152, 138, 0, 136, 134, 133, 131, 132, 246, 244,
+
+ 245, 40, 42, 40, 40, 37, 38, 0, 50, 49,
+ 51, 0, 164, 0, 164, 167, 168, 219, 215, 173,
+ 0, 183, 184, 189, 186, 228, 233, 0, 0, 221,
+ 229, 229, 229, 0, 130, 0, 21, 23, 24, 235,
+ 241, 240, 239, 240, 0, 0, 225, 220, 0, 0,
+ 53, 52, 0, 128, 0, 0, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 55, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 0, 35,
+ 34, 48, 45, 46, 47, 31, 32, 29, 26, 25,
+
+ 250, 248, 249, 237, 0, 16, 10, 0, 14, 0,
+ 0, 0, 0, 0, 4, 16, 5, 0, 6, 0,
+ 144, 0, 145, 0, 158, 0, 153, 153, 0, 153,
+ 153, 153, 243, 243, 155, 154, 0, 156, 138, 146,
+ 0, 152, 0, 131, 132, 40, 40, 0, 39, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 230, 229, 229, 0, 0, 220, 0, 0,
+ 0, 0, 129, 129, 129, 129, 129, 129, 65, 129,
+ 129, 129, 70, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 0, 0,
+ 0, 0, 14, 0, 0, 0, 0, 0, 0, 4,
+ 8, 5, 0, 153, 153, 153, 153, 153, 153, 153,
+ 243, 156, 0, 0, 40, 40, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 229, 229,
+ 0, 0, 56, 57, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 71, 72, 129, 129, 129, 129,
+ 77, 78, 129, 129, 129, 129, 129, 129, 129, 83,
+
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 92,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 0,
+ 0, 0, 0, 15, 0, 0, 0, 0, 0, 8,
+ 8, 8, 0, 153, 153, 153, 153, 153, 153, 153,
+ 0, 0, 40, 40, 214, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 229, 229,
+ 0, 0, 58, 129, 60, 129, 62, 129, 129, 129,
+ 129, 68, 129, 129, 129, 73, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 86, 129, 129,
+
+ 129, 129, 90, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 0, 0, 0, 0, 3, 0, 0,
+ 0, 8, 7, 8, 0, 153, 153, 153, 0, 0,
+ 40, 40, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 222, 223, 222, 223,
+ 129, 61, 129, 129, 129, 129, 129, 129, 129, 125,
+ 129, 129, 129, 129, 129, 129, 129, 129, 123, 129,
+ 85, 129, 88, 129, 89, 129, 129, 129, 104, 0,
+ 129, 94, 129, 0, 95, 0, 0, 0, 0, 0,
+
+ 12, 0, 13, 0, 151, 0, 150, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 129, 129, 129, 129, 129, 66, 129, 69, 129,
+ 129, 129, 129, 129, 129, 122, 129, 82, 129, 129,
+ 87, 129, 91, 102, 124, 0, 0, 0, 0, 0,
+ 0, 129, 129, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 150, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 129, 129,
+
+ 129, 129, 129, 67, 129, 129, 129, 129, 79, 129,
+ 129, 129, 129, 129, 129, 0, 0, 113, 0, 0,
+ 0, 0, 0, 0, 93, 129, 0, 0, 114, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 11, 0,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 84, 129, 129, 0,
+ 0, 0, 0, 0, 0, 115, 0, 103, 0, 0,
+ 0, 0, 0, 116, 0, 0, 0, 0, 0, 201,
+
+ 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+ 212, 0, 129, 129, 129, 129, 129, 121, 129, 129,
+ 75, 129, 129, 129, 129, 129, 0, 0, 109, 0,
+ 119, 117, 110, 0, 0, 0, 120, 118, 0, 0,
+ 0, 0, 0, 0, 213, 129, 129, 129, 129, 129,
+ 125, 74, 129, 81, 129, 126, 129, 105, 107, 0,
+ 106, 108, 0, 0, 0, 0, 0, 0, 0, 129,
+ 63, 129, 129, 129, 129, 76, 129, 111, 112, 97,
+ 0, 0, 0, 0, 98, 129, 129, 129, 129, 129,
+ 127, 96, 0, 100, 0, 129, 129, 129, 66, 129,
+
+ 99, 101, 129, 64, 129, 129, 129, 67, 129, 129,
+ 80, 59, 0
+ } ;
+
+static const YY_CHAR yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 4, 4, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 6, 7, 8, 9, 1, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 19, 19,
+ 19, 19, 19, 19, 20, 21, 22, 23, 1, 24,
+ 25, 26, 27, 1, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 44,
+ 53, 54, 55, 56, 57, 1, 58, 59, 60, 61,
+
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 44, 74, 75, 76, 77, 78, 79, 80,
+ 81, 44, 82, 83, 84, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static const YY_CHAR yy_meta[85] =
+ { 0,
+ 1, 1, 2, 1, 3, 4, 1, 1, 5, 6,
+ 1, 7, 8, 9, 1, 10, 1, 11, 12, 12,
+ 12, 12, 13, 1, 1, 1, 1, 14, 14, 14,
+ 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 16, 17, 18, 1, 19, 14, 14, 14,
+ 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 20, 1, 21
+ } ;
+
+static const flex_int16_t yy_base[1221] =
+ { 0,
+ 0, 84, 167, 250, 171, 184, 135, 142, 220, 231,
+ 196, 200, 334, 0, 3627, 3625, 211, 416, 203, 212,
+ 189, 225, 266, 417, 500, 0, 207, 208, 234, 421,
+ 424, 436, 583, 588, 669, 0, 294, 304, 584, 751,
+ 579, 580, 417, 576, 287, 306, 241, 441, 595, 608,
+ 169, 238, 440, 754, 3680, 4511, 325, 4511, 3676, 0,
+ 446, 4511, 3673, 430, 827, 3661, 0, 4511, 758, 4511,
+ 3650, 4511, 453, 3621, 4511, 4511, 3619, 3584, 129, 746,
+ 445, 766, 4511, 3604, 198, 3582, 4511, 4511, 4511, 3600,
+ 0, 3599, 214, 0, 3506, 3483, 0, 4511, 3532, 4511,
+
+ 420, 119, 3481, 3478, 3446, 0, 3526, 4511, 3520, 4511,
+ 482, 3520, 3518, 4511, 3455, 0, 4511, 4511, 4511, 3504,
+ 4511, 598, 4511, 4511, 4511, 3499, 4511, 754, 4511, 3477,
+ 759, 180, 4511, 4511, 3467, 0, 3442, 762, 4511, 0,
+ 4511, 3459, 4511, 3406, 3434, 0, 562, 167, 3393, 3370,
+ 4511, 4511, 326, 4511, 420, 0, 4511, 3418, 3402, 3366,
+ 3342, 0, 4511, 3368, 4511, 3317, 444, 3314, 4511, 471,
+ 4511, 3354, 3271, 3337, 572, 189, 3295, 3285, 4511, 3332,
+ 4511, 3307, 3303, 585, 594, 4511, 746, 734, 744, 754,
+ 763, 770, 0, 755, 748, 763, 818, 789, 240, 822,
+
+ 762, 381, 802, 791, 813, 824, 577, 4511, 4511, 3302,
+ 871, 0, 4511, 3302, 3250, 3231, 4511, 4511, 4511, 4511,
+ 4511, 4511, 4511, 4511, 4511, 4511, 4511, 0, 4511, 3279,
+ 4511, 4511, 4511, 3276, 3260, 3259, 0, 3221, 3214, 0,
+ 3264, 4511, 835, 4511, 3262, 0, 903, 4511, 3257, 842,
+ 817, 0, 0, 910, 914, 918, 922, 0, 814, 0,
+ 457, 4511, 0, 943, 4511, 3241, 3141, 483, 4511, 3217,
+ 3212, 4511, 826, 556, 903, 930, 4511, 757, 0, 3134,
+ 3131, 4511, 3129, 964, 4511, 3190, 3110, 3174, 3161, 4511,
+ 0, 4511, 896, 4511, 0, 3172, 0, 0, 0, 4511,
+
+ 4511, 0, 4511, 910, 913, 4511, 4511, 602, 0, 3169,
+ 4511, 957, 3164, 3161, 3127, 4511, 0, 4511, 976, 4511,
+ 1020, 4511, 4511, 4511, 4511, 0, 4511, 3116, 0, 4511,
+ 0, 926, 930, 644, 4511, 662, 0, 4511, 4511, 0,
+ 4511, 4511, 3071, 3121, 794, 3037, 4511, 0, 934, 932,
+ 3117, 4511, 3091, 4511, 938, 939, 0, 940, 738, 956,
+ 802, 3059, 876, 978, 933, 933, 939, 948, 964, 1030,
+ 938, 958, 976, 968, 0, 996, 4511, 999, 1057, 1068,
+ 981, 1079, 1077, 1080, 1074, 1068, 1070, 1120, 3062, 4511,
+ 1014, 0, 4511, 4511, 4511, 0, 4511, 4511, 4511, 4511,
+
+ 0, 4511, 4511, 0, 1078, 0, 0, 1153, 4511, 3063,
+ 1166, 1077, 1076, 1091, 0, 1089, 0, 1018, 4511, 1022,
+ 4511, 1025, 4511, 1035, 4511, 1091, 1067, 1138, 1162, 1242,
+ 1177, 1308, 1105, 0, 4511, 4511, 2954, 1198, 4511, 4511,
+ 1144, 0, 1137, 0, 0, 1161, 1156, 1123, 4511, 1202,
+ 1308, 1309, 1310, 1319, 3013, 1312, 1311, 1327, 1320, 1321,
+ 1323, 1382, 4511, 1172, 1166, 2589, 2537, 0, 1178, 1169,
+ 1169, 1298, 1315, 1324, 1330, 1321, 1330, 1323, 0, 1341,
+ 1332, 1348, 0, 1346, 1350, 1348, 1361, 1350, 1367, 2573,
+ 1370, 1366, 1380, 1382, 1382, 1385, 1378, 1387, 1391, 1400,
+
+ 1393, 1403, 1406, 1414, 1400, 1401, 1404, 1429, 1419, 1424,
+ 1428, 1425, 1436, 1435, 1430, 1441, 1442, 1432, 1432, 1450,
+ 1209, 1508, 4511, 1215, 1512, 1219, 1461, 1455, 1451, 0,
+ 1143, 0, 1461, 1534, 1600, 1636, 204, 2525, 1606, 1681,
+ 4511, 4511, 1453, 1463, 1591, 1442, 2524, 1599, 1604, 1600,
+ 1607, 1605, 1611, 1608, 1650, 1620, 1606, 1614, 1613, 1654,
+ 1663, 1652, 1661, 1666, 1682, 1664, 1693, 1694, 1655, 1674,
+ 1662, 1675, 4511, 4511, 1683, 1676, 1677, 1683, 1697, 1692,
+ 1731, 1711, 1702, 1718, 0, 0, 1719, 1706, 1716, 1735,
+ 0, 0, 2553, 1722, 1732, 2540, 1725, 1722, 1733, 0,
+
+ 1727, 1747, 1740, 1739, 1735, 1752, 1739, 1740, 1746, 0,
+ 1750, 1763, 1760, 1750, 1752, 1759, 1777, 1762, 1778, 1769,
+ 1783, 1778, 2514, 4511, 1224, 1230, 1772, 1783, 1780, 0,
+ 1507, 1234, 2364, 732, 2273, 1809, 1845, 1430, 1076, 1585,
+ 1797, 2286, 1785, 1807, 4511, 1811, 1814, 1829, 1835, 1821,
+ 1808, 1822, 1845, 1859, 1860, 1862, 1868, 1869, 1870, 1825,
+ 1888, 1890, 1876, 1891, 1874, 1902, 1894, 1898, 1795, 1891,
+ 1882, 1899, 0, 1887, 0, 1892, 0, 2260, 1900, 1891,
+ 1909, 0, 1904, 2253, 1902, 0, 1916, 1907, 1918, 2227,
+ 1912, 1909, 1924, 2201, 1908, 1918, 1922, 0, 1934, 1925,
+
+ 1931, 1947, 0, 1936, 1942, 1941, 1953, 2103, 1957, 1958,
+ 1952, 2085, 1950, 1951, 1950, 1969, 1956, 2133, 1515, 1961,
+ 1971, 2002, 4511, 2117, 2038, 1981, 1592, 1842, 2025, 1983,
+ 0, 0, 1972, 1990, 1999, 1987, 1994, 2008, 2005, 2007,
+ 2015, 2023, 2016, 2021, 2017, 2024, 2022, 2026, 2030, 2029,
+ 2037, 2035, 2045, 2051, 2054, 2061, 0, 0, 4511, 4511,
+ 1922, 0, 2049, 2039, 2050, 2053, 2051, 2051, 2054, 1831,
+ 2073, 2064, 2077, 2073, 2081, 2082, 2072, 2085, 0, 2091,
+ 0, 2074, 0, 1824, 0, 2091, 2094, 2082, 0, 2116,
+ 2088, 0, 2092, 2133, 0, 1728, 2097, 2095, 1714, 1678,
+
+ 4511, 2135, 4511, 2096, 4511, 1726, 4511, 1703, 1612, 1601,
+ 1514, 1500, 1477, 1377, 1373, 1333, 1274, 1203, 2133, 2128,
+ 2148, 2151, 2144, 2150, 2156, 2158, 2161, 2163, 2184, 2167,
+ 2164, 2157, 2151, 2159, 2158, 2173, 0, 2165, 0, 2166,
+ 2182, 2173, 2179, 2178, 2186, 0, 2185, 0, 2187, 2193,
+ 0, 2202, 0, 0, 0, 2204, 2187, 2201, 2224, 2200,
+ 2222, 2213, 2219, 2230, 2199, 2227, 2239, 2222, 2225, 1162,
+ 1158, 2228, 2278, 4511, 1112, 1109, 1081, 1063, 1057, 984,
+ 976, 969, 923, 913, 910, 931, 895, 891, 887, 881,
+ 874, 856, 848, 843, 840, 804, 788, 2259, 2248, 2258,
+
+ 2265, 2264, 2241, 0, 2254, 2265, 2268, 2279, 0, 2262,
+ 2268, 2271, 2266, 2278, 2283, 2289, 2273, 4511, 2280, 2281,
+ 2281, 2300, 2283, 2281, 0, 2303, 2307, 2292, 4511, 2302,
+ 2304, 2319, 2303, 2307, 2309, 2328, 2309, 2357, 4511, 2362,
+ 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511,
+ 4511, 746, 725, 597, 577, 441, 426, 420, 267, 253,
+ 247, 230, 183, 181, 2317, 2338, 2342, 2330, 2336, 2343,
+ 2339, 2331, 2334, 2350, 2341, 2345, 0, 2350, 2346, 2344,
+ 2349, 2361, 2364, 2367, 2359, 4511, 2357, 0, 2358, 2362,
+ 2379, 2383, 2375, 4511, 2388, 2375, 2382, 2377, 2389, 4511,
+
+ 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511, 4511,
+ 4511, 122, 2399, 2398, 2382, 2391, 2391, 0, 2407, 2408,
+ 0, 2397, 2398, 2420, 2417, 2414, 2418, 2426, 4511, 2414,
+ 4511, 4511, 4511, 2422, 2429, 2419, 4511, 4511, 2417, 2437,
+ 2435, 2425, 2428, 2428, 4511, 2431, 2445, 2445, 2447, 2452,
+ 0, 0, 2461, 0, 2444, 0, 2459, 4511, 4511, 2452,
+ 4511, 4511, 2454, 2465, 2452, 2467, 2471, 2470, 2476, 2481,
+ 0, 2468, 2465, 2465, 2485, 0, 2465, 4511, 4511, 4511,
+ 2489, 2491, 2479, 2488, 4511, 2501, 2491, 2498, 2503, 2490,
+ 0, 4511, 2497, 4511, 2510, 2500, 2502, 2500, 0, 2514,
+
+ 4511, 4511, 2516, 0, 2523, 2508, 2509, 0, 2528, 2531,
+ 0, 0, 4511, 2593, 2614, 2635, 2656, 2677, 2698, 2719,
+ 2740, 2761, 2782, 2803, 2824, 2845, 2866, 2887, 2908, 2929,
+ 2950, 2971, 2992, 3013, 3025, 3044, 3055, 3074, 3095, 3108,
+ 3127, 3148, 3169, 3190, 3202, 3221, 3242, 3263, 3280, 3292,
+ 3311, 3332, 3353, 3374, 3395, 3408, 2553, 3423, 3444, 3463,
+ 3484, 3505, 3517, 3536, 3557, 2569, 3057, 3578, 3590, 3609,
+ 3630, 3651, 2558, 3663, 3684, 3705, 3726, 3747, 3768, 3789,
+ 3810, 3831, 3843, 3862, 3879, 3891, 3910, 3931, 3952, 3973,
+ 3994, 4007, 4022, 4043, 4062, 4083, 4104, 4125, 4146, 4167,
+
+ 4179, 4189, 4208, 4229, 4250, 2561, 4262, 4283, 4304, 4325,
+ 4346, 4367, 3028, 4379, 4398, 4419, 4432, 4447, 4468, 4489
+ } ;
+
+static const flex_int16_t yy_def[1221] =
+ { 0,
+ 1113, 1113, 1114, 1114, 1115, 1116, 1117, 1117, 1118, 1118,
+ 1119, 1119, 1113, 13, 1120, 1120, 1121, 1121, 1122, 1122,
+ 1123, 1123, 1124, 1124, 1113, 25, 1125, 1125, 1126, 1126,
+ 1127, 1127, 1128, 1128, 1113, 35, 1129, 1129, 1130, 1130,
+ 1120, 1120, 1120, 1120, 1131, 1131, 1132, 1132, 1126, 1126,
+ 1133, 1133, 1134, 1134, 1113, 1113, 1113, 1113, 1113, 1135,
+ 1113, 1113, 1113, 1113, 1136, 1113, 1137, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1138, 1139,
+ 1140, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1141, 1113, 1141, 1142, 1113, 1113, 1143, 1113, 1143, 1113,
+
+ 1143, 1143, 1113, 1113, 1113, 1144, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1145, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1139, 1113, 1113,
+ 1139, 1146, 1113, 1113, 1113, 1147, 1113, 1139, 1113, 1148,
+ 1113, 1148, 1113, 1149, 1113, 1150, 1150, 1150, 1113, 1113,
+ 1113, 1113, 1151, 1113, 1151, 1152, 1113, 1152, 1113, 1113,
+ 1113, 1153, 1113, 1153, 1113, 1113, 1154, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1155, 1113, 1113, 1113, 1156, 1156, 1156, 1156,
+ 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1157, 1156, 1156,
+
+ 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1113, 1113, 1158,
+ 1113, 1159, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1160, 1113, 1160,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1161, 1113, 1113, 1162,
+ 1162, 1113, 1113, 1113, 1113, 1163, 1113, 1113, 1113, 1113,
+ 1113, 1164, 1165, 1113, 1113, 1113, 1113, 1166, 1164, 1167,
+ 1168, 1113, 1169, 1113, 1113, 1113, 1113, 1170, 1113, 1113,
+ 1113, 1113, 1113, 1171, 1171, 1172, 1113, 1113, 1173, 1113,
+ 1113, 1113, 1174, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1175, 1113, 1113, 1113, 1176, 1113, 1177, 1178, 1179, 1113,
+
+ 1113, 1180, 1113, 1180, 1180, 1113, 1113, 1181, 1182, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1183, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1184, 1113, 1113, 1185, 1113,
+ 1186, 1186, 1186, 1187, 1113, 1187, 1188, 1113, 1113, 1189,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1190, 1113, 1113,
+ 1113, 1113, 1191, 1113, 1113, 1113, 1192, 1192, 1192, 1192,
+ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
+ 1192, 1192, 1192, 1192, 1192, 1192, 1113, 1192, 1192, 1192,
+ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1193, 1113,
+ 1113, 1194, 1113, 1113, 1113, 1195, 1113, 1113, 1113, 1113,
+
+ 1196, 1113, 1113, 1197, 1113, 1198, 1199, 1200, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1201, 1198, 1202, 1203, 1113, 1203,
+ 1113, 1204, 1113, 1204, 1113, 1113, 1205, 1205, 1205, 1113,
+ 1205, 1205, 1113, 1206, 1113, 1113, 1207, 1113, 1113, 1113,
+ 1113, 1208, 1113, 1209, 1210, 1211, 1211, 1212, 1113, 1212,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1113, 1214, 1214, 1113, 1215, 1216, 1113, 1113,
+ 1113, 1113, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113, 1113,
+ 1200, 1200, 1113, 1200, 1200, 1113, 1113, 1113, 1113, 1201,
+ 1218, 1202, 1113, 1113, 1205, 432, 430, 430, 1205, 432,
+ 1113, 1113, 1113, 1113, 1211, 1211, 1113, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1214, 1214,
+ 1113, 1113, 1113, 1113, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113,
+ 1113, 1113, 1113, 1113, 1200, 1200, 1113, 1113, 1113, 1218,
+ 1218, 1218, 1113, 534, 534, 1205, 432, 1205, 1205, 1205,
+ 1113, 1113, 1211, 1211, 1113, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1214, 1214,
+ 1113, 1113, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1113, 1113, 1113, 1113, 1113, 1219, 1113,
+ 1113, 1218, 1113, 1218, 1113, 1205, 1205, 1205, 1113, 1113,
+ 1211, 1211, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1214, 1214, 1113, 1113,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113,
+ 1217, 1217, 1217, 1113, 1217, 1113, 1113, 1113, 1113, 1219,
+
+ 1113, 1219, 1113, 1113, 1113, 1113, 1113, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1217, 1217, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1220, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1217, 1217,
+
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1217, 1217, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1220, 1113, 1220,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1213, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1217, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1217,
+ 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1113, 1113, 1113, 1113, 1217, 1217, 1217, 1217, 1217,
+
+ 1113, 1113, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 0, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113
+ } ;
+
+static const flex_int16_t yy_nxt[4596] =
+ { 0,
+ 56, 57, 58, 56, 59, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 56, 56, 56, 56, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 56, 56, 56, 56, 61, 62, 56, 63, 56,
+ 64, 56, 65, 56, 56, 56, 56, 56, 56, 56,
+
+ 56, 66, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 56, 56, 56, 56,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 56, 56, 56, 69, 70,
+ 305, 71, 72, 89, 73, 90, 1045, 74, 75, 76,
+ 76, 275, 276, 76, 77, 92, 89, 95, 90, 96,
+ 78, 56, 93, 76, 95, 323, 96, 107, 108, 305,
+
+ 109, 107, 108, 1012, 109, 125, 291, 126, 127, 154,
+ 154, 155, 155, 119, 125, 120, 126, 127, 333, 79,
+ 80, 238, 98, 239, 99, 121, 638, 56, 100, 122,
+ 122, 122, 122, 98, 323, 99, 157, 1011, 158, 105,
+ 350, 130, 131, 233, 132, 234, 159, 333, 81, 76,
+ 76, 82, 83, 235, 84, 72, 128, 73, 85, 427,
+ 74, 75, 76, 76, 101, 128, 76, 77, 134, 350,
+ 135, 102, 103, 86, 104, 101, 76, 130, 131, 292,
+ 132, 136, 102, 103, 1010, 104, 160, 378, 161, 229,
+ 238, 230, 239, 101, 123, 297, 209, 298, 231, 210,
+
+ 102, 1009, 79, 80, 101, 87, 209, 1008, 229, 210,
+ 230, 102, 211, 211, 211, 211, 378, 231, 137, 138,
+ 139, 1007, 211, 211, 211, 211, 243, 244, 335, 245,
+ 336, 81, 76, 76, 110, 111, 112, 110, 113, 110,
+ 110, 110, 110, 110, 110, 110, 114, 110, 114, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 115,
+ 110, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 110, 110, 110, 110,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 110, 110, 110, 119, 134,
+ 120, 135, 335, 157, 336, 158, 163, 383, 164, 165,
+ 121, 250, 136, 159, 122, 122, 122, 122, 163, 224,
+ 164, 165, 163, 233, 241, 234, 343, 247, 248, 242,
+ 249, 304, 225, 235, 269, 269, 383, 270, 280, 419,
+ 281, 420, 226, 282, 282, 282, 282, 227, 251, 137,
+ 138, 139, 345, 160, 1006, 161, 166, 167, 168, 346,
+ 1005, 304, 225, 312, 313, 423, 314, 424, 166, 167,
+ 168, 226, 166, 167, 168, 1004, 227, 344, 251, 123,
+
+ 140, 140, 141, 140, 142, 143, 140, 140, 140, 144,
+ 140, 140, 140, 140, 140, 140, 140, 145, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 146, 147, 146, 146, 146, 146, 146,
+ 146, 148, 149, 140, 150, 140, 146, 146, 146, 146,
+ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ 146, 146, 146, 147, 146, 146, 146, 146, 146, 146,
+ 148, 151, 140, 152, 170, 171, 213, 172, 214, 170,
+ 171, 173, 172, 332, 219, 219, 173, 157, 224, 158,
+
+ 174, 220, 220, 349, 449, 174, 450, 236, 428, 429,
+ 157, 225, 158, 355, 221, 221, 319, 319, 319, 319,
+ 236, 226, 356, 332, 222, 222, 227, 175, 388, 223,
+ 223, 1003, 175, 349, 176, 177, 215, 178, 216, 176,
+ 177, 225, 178, 355, 221, 221, 335, 160, 336, 161,
+ 226, 1002, 356, 222, 222, 227, 175, 388, 223, 223,
+ 160, 175, 161, 176, 335, 217, 336, 218, 176, 179,
+ 180, 181, 179, 182, 183, 179, 179, 179, 179, 179,
+ 179, 179, 179, 179, 179, 179, 179, 179, 184, 185,
+ 179, 179, 179, 186, 179, 179, 187, 188, 189, 190,
+
+ 191, 192, 193, 194, 195, 193, 193, 196, 197, 198,
+ 199, 200, 193, 201, 202, 203, 204, 205, 206, 193,
+ 207, 179, 179, 179, 179, 179, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 193, 193, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206, 193, 207,
+ 179, 179, 179, 213, 726, 214, 163, 362, 241, 264,
+ 265, 360, 266, 242, 278, 278, 267, 284, 285, 361,
+ 286, 363, 278, 278, 287, 433, 433, 278, 278, 1001,
+ 278, 278, 475, 288, 358, 364, 369, 427, 370, 289,
+ 359, 360, 365, 382, 371, 345, 279, 367, 372, 361,
+
+ 1000, 363, 346, 215, 279, 216, 166, 167, 168, 279,
+ 963, 475, 279, 366, 358, 364, 369, 368, 370, 359,
+ 376, 290, 365, 382, 371, 279, 962, 367, 372, 384,
+ 377, 385, 217, 279, 218, 253, 243, 244, 279, 245,
+ 268, 279, 366, 250, 386, 373, 368, 478, 268, 374,
+ 376, 387, 405, 379, 254, 416, 255, 426, 255, 384,
+ 377, 385, 961, 380, 255, 960, 381, 255, 256, 257,
+ 959, 255, 258, 259, 386, 373, 478, 260, 958, 374,
+ 251, 387, 405, 379, 254, 416, 255, 426, 255, 391,
+ 391, 391, 391, 380, 255, 381, 957, 255, 256, 257,
+
+ 255, 258, 259, 956, 247, 248, 260, 249, 261, 955,
+ 251, 408, 409, 954, 410, 408, 409, 953, 410, 408,
+ 409, 480, 410, 408, 409, 430, 410, 443, 411, 411,
+ 411, 411, 411, 411, 411, 411, 411, 411, 411, 411,
+ 411, 411, 411, 411, 264, 265, 446, 266, 431, 431,
+ 480, 267, 447, 952, 412, 428, 429, 443, 312, 313,
+ 413, 314, 464, 414, 951, 284, 285, 950, 286, 465,
+ 469, 470, 287, 471, 472, 473, 446, 949, 483, 484,
+ 432, 288, 447, 412, 485, 476, 486, 289, 490, 474,
+ 413, 487, 464, 414, 319, 319, 319, 319, 491, 465,
+
+ 469, 470, 477, 471, 472, 473, 481, 483, 484, 432,
+ 482, 492, 499, 485, 493, 476, 486, 490, 474, 290,
+ 419, 487, 420, 948, 419, 268, 420, 423, 491, 424,
+ 947, 477, 391, 391, 391, 391, 481, 423, 946, 424,
+ 482, 492, 499, 493, 494, 495, 268, 451, 452, 453,
+ 454, 455, 455, 456, 455, 455, 455, 455, 457, 455,
+ 455, 455, 458, 455, 455, 459, 455, 460, 455, 455,
+ 461, 455, 488, 494, 495, 462, 489, 451, 452, 453,
+ 454, 455, 455, 456, 455, 455, 455, 455, 457, 455,
+ 455, 455, 458, 455, 459, 455, 460, 455, 455, 461,
+
+ 455, 496, 488, 497, 503, 489, 500, 504, 505, 506,
+ 501, 945, 508, 498, 509, 502, 507, 944, 520, 428,
+ 429, 527, 528, 277, 277, 449, 529, 450, 428, 429,
+ 496, 531, 533, 497, 503, 943, 500, 504, 505, 506,
+ 501, 508, 498, 509, 631, 502, 507, 510, 520, 511,
+ 527, 528, 512, 513, 522, 523, 529, 524, 514, 515,
+ 534, 531, 533, 942, 516, 517, 941, 526, 409, 518,
+ 410, 525, 525, 525, 525, 543, 519, 510, 544, 511,
+ 535, 535, 512, 513, 411, 411, 411, 411, 514, 515,
+ 428, 429, 545, 516, 517, 539, 539, 546, 518, 542,
+
+ 542, 542, 542, 569, 449, 543, 450, 570, 544, 571,
+ 572, 624, 536, 625, 936, 573, 427, 523, 935, 625,
+ 526, 409, 545, 410, 632, 885, 624, 546, 625, 428,
+ 429, 626, 523, 569, 524, 722, 723, 570, 724, 571,
+ 572, 536, 427, 427, 573, 427, 427, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 427, 427, 537,
+ 537, 537, 537, 537, 537, 537, 537, 537, 537, 537,
+ 537, 537, 537, 537, 537, 537, 537, 537, 537, 537,
+ 537, 537, 537, 537, 428, 429, 884, 538, 427, 537,
+
+ 537, 537, 537, 537, 537, 537, 537, 537, 537, 537,
+ 537, 537, 537, 537, 537, 537, 537, 537, 537, 537,
+ 537, 537, 537, 427, 427, 427, 540, 540, 540, 540,
+ 547, 547, 547, 547, 547, 540, 540, 540, 540, 540,
+ 540, 547, 547, 547, 574, 547, 548, 549, 575, 547,
+ 550, 576, 553, 558, 551, 883, 552, 577, 578, 579,
+ 428, 429, 556, 557, 580, 540, 540, 540, 540, 540,
+ 540, 554, 581, 574, 555, 583, 548, 549, 575, 582,
+ 550, 576, 553, 558, 551, 552, 586, 577, 578, 579,
+ 584, 587, 556, 557, 580, 882, 585, 588, 589, 881,
+
+ 554, 591, 581, 555, 1113, 583, 592, 593, 582, 559,
+ 560, 561, 562, 594, 595, 563, 586, 596, 597, 584,
+ 564, 587, 598, 599, 565, 585, 588, 566, 589, 567,
+ 600, 591, 568, 601, 602, 603, 592, 593, 606, 559,
+ 560, 561, 562, 594, 595, 563, 607, 596, 597, 604,
+ 564, 608, 598, 599, 565, 605, 566, 609, 567, 610,
+ 600, 568, 611, 601, 602, 603, 612, 614, 606, 613,
+ 615, 616, 617, 618, 620, 607, 619, 621, 622, 604,
+ 608, 623, 428, 429, 274, 605, 644, 609, 627, 610,
+ 628, 629, 611, 633, 641, 642, 612, 614, 613, 880,
+
+ 615, 616, 617, 618, 620, 619, 621, 622, 631, 522,
+ 523, 623, 524, 626, 523, 644, 524, 801, 627, 802,
+ 628, 629, 879, 633, 641, 642, 525, 525, 525, 525,
+ 525, 525, 525, 525, 427, 427, 878, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 427, 427, 427,
+ 427, 634, 634, 634, 634, 634, 634, 634, 634, 634,
+ 634, 634, 634, 634, 634, 634, 634, 634, 634, 634,
+ 634, 634, 634, 634, 634, 634, 428, 429, 632, 635,
+ 427, 634, 634, 634, 634, 634, 634, 634, 634, 634,
+
+ 634, 634, 634, 634, 634, 634, 634, 634, 634, 634,
+ 634, 634, 634, 634, 634, 427, 427, 427, 636, 636,
+ 643, 547, 547, 877, 639, 639, 547, 547, 547, 547,
+ 547, 648, 651, 547, 876, 547, 547, 428, 429, 646,
+ 650, 647, 547, 653, 428, 429, 649, 655, 656, 657,
+ 643, 658, 428, 429, 637, 637, 637, 637, 428, 429,
+ 652, 648, 651, 637, 637, 637, 637, 637, 637, 646,
+ 650, 647, 547, 653, 547, 649, 547, 655, 656, 657,
+ 801, 658, 802, 547, 669, 547, 547, 661, 547, 652,
+ 654, 671, 659, 637, 637, 637, 637, 637, 637, 640,
+
+ 640, 640, 640, 660, 547, 662, 666, 663, 640, 640,
+ 640, 640, 640, 640, 669, 547, 547, 661, 670, 672,
+ 654, 671, 659, 673, 668, 875, 664, 674, 675, 665,
+ 676, 677, 678, 660, 662, 667, 666, 663, 640, 640,
+ 640, 640, 640, 640, 682, 684, 679, 670, 672, 683,
+ 685, 874, 686, 673, 668, 664, 674, 675, 665, 676,
+ 687, 677, 678, 680, 688, 667, 690, 691, 695, 681,
+ 872, 693, 694, 696, 682, 684, 697, 698, 683, 699,
+ 685, 686, 700, 701, 869, 702, 703, 704, 705, 687,
+ 706, 707, 709, 680, 688, 690, 708, 691, 695, 681,
+
+ 693, 694, 696, 710, 711, 713, 697, 698, 712, 699,
+ 714, 700, 716, 701, 702, 703, 715, 704, 705, 717,
+ 706, 707, 709, 719, 720, 708, 721, 727, 727, 729,
+ 547, 731, 710, 547, 711, 713, 547, 712, 732, 852,
+ 714, 757, 716, 547, 547, 715, 841, 547, 734, 717,
+ 738, 547, 719, 739, 720, 721, 737, 547, 733, 729,
+ 731, 428, 429, 728, 728, 728, 728, 547, 732, 735,
+ 757, 748, 728, 728, 728, 728, 728, 728, 734, 736,
+ 738, 547, 547, 739, 547, 740, 737, 733, 741, 742,
+ 547, 547, 547, 743, 428, 429, 547, 747, 547, 735,
+
+ 748, 744, 728, 728, 728, 728, 728, 728, 736, 745,
+ 547, 746, 547, 547, 753, 740, 547, 750, 741, 742,
+ 547, 749, 758, 743, 547, 751, 752, 747, 759, 754,
+ 760, 744, 761, 756, 762, 764, 755, 832, 766, 745,
+ 767, 746, 768, 771, 753, 765, 770, 750, 772, 773,
+ 775, 749, 758, 776, 751, 777, 752, 759, 779, 754,
+ 760, 761, 780, 756, 762, 764, 755, 766, 781, 782,
+ 767, 783, 768, 771, 765, 770, 784, 785, 772, 773,
+ 775, 786, 776, 787, 789, 777, 788, 779, 791, 792,
+ 793, 780, 795, 796, 547, 797, 798, 781, 799, 782,
+
+ 783, 803, 804, 722, 723, 784, 724, 785, 807, 547,
+ 786, 808, 547, 787, 789, 788, 547, 809, 791, 792,
+ 793, 547, 795, 796, 797, 811, 798, 547, 799, 547,
+ 547, 803, 804, 428, 429, 427, 810, 547, 547, 547,
+ 812, 808, 813, 547, 547, 547, 547, 809, 547, 814,
+ 806, 547, 547, 815, 817, 811, 819, 547, 821, 547,
+ 818, 816, 822, 805, 820, 824, 810, 547, 826, 812,
+ 823, 825, 813, 547, 828, 827, 547, 833, 814, 835,
+ 829, 836, 815, 547, 817, 830, 819, 834, 821, 818,
+ 816, 837, 822, 820, 831, 824, 838, 839, 826, 823,
+
+ 840, 825, 842, 843, 828, 827, 844, 833, 845, 835,
+ 829, 836, 846, 847, 849, 830, 848, 834, 850, 723,
+ 851, 837, 853, 854, 831, 838, 839, 855, 862, 840,
+ 863, 870, 842, 843, 718, 871, 844, 801, 845, 802,
+ 873, 794, 846, 847, 849, 848, 856, 857, 850, 851,
+ 547, 858, 853, 854, 859, 547, 855, 860, 862, 790,
+ 863, 870, 861, 864, 865, 871, 547, 887, 866, 873,
+ 547, 867, 547, 547, 868, 888, 856, 857, 547, 886,
+ 547, 858, 890, 547, 859, 547, 547, 860, 889, 547,
+ 892, 861, 899, 864, 865, 900, 891, 887, 866, 898,
+
+ 901, 867, 893, 902, 868, 888, 547, 894, 886, 895,
+ 904, 897, 890, 903, 906, 896, 778, 905, 889, 907,
+ 892, 908, 899, 909, 900, 891, 910, 911, 912, 898,
+ 901, 893, 902, 913, 914, 916, 894, 917, 895, 904,
+ 897, 918, 774, 903, 906, 896, 905, 923, 907, 928,
+ 915, 908, 909, 924, 925, 919, 910, 911, 912, 920,
+ 926, 927, 921, 913, 914, 916, 917, 929, 769, 933,
+ 934, 918, 922, 937, 930, 763, 923, 931, 928, 915,
+ 939, 547, 940, 924, 925, 919, 969, 932, 965, 920,
+ 926, 927, 921, 966, 967, 968, 970, 929, 933, 934,
+
+ 971, 922, 937, 972, 930, 964, 973, 931, 974, 975,
+ 976, 730, 977, 978, 979, 969, 932, 980, 965, 981,
+ 982, 983, 984, 966, 967, 968, 970, 985, 427, 986,
+ 971, 987, 988, 972, 964, 989, 973, 974, 990, 975,
+ 976, 977, 991, 978, 979, 992, 993, 980, 981, 994,
+ 982, 983, 984, 995, 996, 999, 997, 985, 986, 939,
+ 987, 940, 988, 1013, 939, 989, 940, 990, 1014, 1015,
+ 1016, 1017, 991, 998, 1018, 992, 993, 1019, 994, 1020,
+ 1021, 1022, 995, 996, 999, 1023, 997, 1024, 1025, 725,
+ 1026, 1027, 1013, 1028, 1029, 1030, 1031, 1032, 1014, 1015,
+
+ 1016, 1017, 998, 1033, 1018, 1034, 1035, 1019, 1020, 1021,
+ 1036, 1022, 1037, 1038, 1023, 1039, 1044, 1024, 1025, 1026,
+ 1027, 1040, 1028, 1043, 1029, 1030, 1031, 1032, 1048, 1041,
+ 1046, 1047, 1033, 1042, 1034, 1035, 1049, 1050, 1051, 1052,
+ 1036, 1053, 1037, 1038, 1054, 1039, 1044, 1055, 1056, 1057,
+ 1040, 1058, 1043, 1059, 1060, 1061, 1062, 1048, 1041, 1063,
+ 1046, 1047, 1042, 1064, 1065, 1049, 1050, 1066, 1051, 1052,
+ 1053, 1067, 1068, 1054, 1069, 1070, 1071, 1055, 1056, 1057,
+ 1072, 1058, 1073, 1059, 1060, 1061, 1062, 1074, 1075, 1063,
+ 1076, 1077, 1064, 1078, 1065, 1079, 1080, 1066, 1081, 1082,
+
+ 1067, 1068, 1083, 1069, 1070, 1084, 1071, 1085, 1086, 1087,
+ 1072, 1088, 1073, 1089, 1090, 718, 1091, 1074, 1075, 1076,
+ 1092, 1077, 1093, 1078, 1094, 1079, 1080, 1081, 1095, 1082,
+ 1096, 1097, 1083, 1098, 1099, 1084, 1100, 1085, 1086, 1087,
+ 1088, 1101, 1089, 1102, 1090, 1091, 1103, 1104, 1105, 1106,
+ 1092, 1107, 1093, 1094, 1108, 692, 1109, 1110, 1095, 1111,
+ 1096, 1097, 1112, 1098, 1099, 1100, 375, 375, 689, 434,
+ 1101, 434, 541, 1102, 541, 1103, 1104, 1105, 645, 1106,
+ 427, 1107, 415, 415, 1108, 1109, 1110, 415, 590, 1111,
+ 344, 343, 1112, 68, 68, 68, 68, 68, 68, 68,
+
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97, 106, 106,
+
+ 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106, 106, 106, 106, 106, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+ 118, 118, 118, 118, 118, 118, 118, 118, 118, 118,
+ 118, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+
+ 129, 129, 129, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
+ 153, 153, 153, 153, 153, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 156, 162, 162, 162, 162,
+ 162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
+ 162, 162, 162, 162, 162, 162, 162, 169, 169, 169,
+ 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
+
+ 169, 169, 169, 169, 169, 169, 169, 169, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
+ 228, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+ 232, 232, 237, 237, 237, 237, 237, 237, 237, 237,
+
+ 237, 237, 237, 237, 237, 237, 237, 237, 237, 237,
+ 237, 237, 237, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+ 240, 240, 240, 240, 246, 547, 246, 438, 246, 246,
+ 455, 455, 455, 246, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+ 252, 252, 252, 252, 263, 409, 263, 390, 263, 263,
+ 417, 417, 479, 263, 274, 417, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 277, 354, 277, 277, 277,
+
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 283, 283, 351, 283,
+ 348, 283, 283, 467, 466, 463, 283, 295, 315, 295,
+ 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
+ 295, 295, 295, 295, 295, 295, 295, 295, 299, 299,
+ 299, 299, 299, 299, 299, 299, 299, 299, 299, 299,
+ 299, 299, 299, 313, 299, 315, 299, 299, 299, 302,
+ 310, 302, 302, 296, 302, 302, 302, 302, 302, 302,
+ 302, 302, 302, 302, 441, 302, 440, 302, 302, 302,
+ 309, 439, 285, 309, 309, 309, 309, 309, 309, 309,
+
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 317, 438, 317, 436, 317, 317, 435, 425, 269,
+ 317, 322, 421, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322,
+ 322, 322, 325, 265, 325, 325, 325, 325, 325, 325,
+ 325, 325, 325, 325, 325, 325, 325, 325, 325, 248,
+ 325, 325, 325, 326, 244, 326, 341, 326, 403, 326,
+ 326, 326, 326, 402, 326, 326, 400, 399, 398, 326,
+ 328, 397, 328, 328, 328, 395, 328, 328, 328, 328,
+ 328, 328, 328, 328, 328, 328, 328, 328, 328, 328,
+
+ 328, 331, 394, 331, 393, 331, 331, 390, 354, 352,
+ 331, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 337, 351, 337, 337, 337, 337, 337, 307,
+ 337, 337, 337, 337, 337, 337, 337, 306, 337, 330,
+ 337, 337, 337, 340, 348, 340, 347, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340, 307, 306,
+ 341, 340, 340, 340, 342, 342, 342, 342, 342, 342,
+ 342, 342, 342, 342, 342, 342, 342, 342, 342, 342,
+ 342, 342, 342, 342, 342, 353, 307, 353, 353, 353,
+
+ 353, 353, 353, 353, 353, 353, 353, 353, 353, 353,
+ 353, 353, 353, 353, 353, 353, 357, 357, 306, 339,
+ 338, 357, 357, 389, 307, 389, 389, 389, 389, 389,
+ 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+ 389, 389, 389, 389, 392, 306, 330, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392, 392, 329,
+ 392, 327, 392, 396, 321, 396, 396, 396, 396, 324,
+ 396, 396, 396, 396, 396, 396, 396, 396, 396, 396,
+ 396, 396, 396, 396, 401, 401, 401, 401, 401, 401,
+ 401, 401, 401, 401, 401, 401, 401, 401, 401, 321,
+
+ 401, 320, 401, 401, 401, 404, 318, 404, 404, 404,
+ 316, 404, 404, 404, 404, 404, 404, 404, 404, 404,
+ 313, 315, 311, 404, 404, 404, 246, 310, 246, 308,
+ 246, 246, 307, 306, 303, 246, 406, 301, 406, 406,
+ 406, 406, 406, 406, 406, 406, 406, 406, 406, 406,
+ 406, 406, 406, 406, 406, 406, 406, 407, 300, 407,
+ 407, 407, 407, 407, 407, 407, 407, 407, 407, 407,
+ 407, 407, 407, 407, 407, 407, 407, 407, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418, 418, 263,
+
+ 296, 263, 294, 263, 263, 293, 285, 273, 263, 422,
+ 422, 422, 422, 422, 422, 422, 422, 422, 422, 422,
+ 422, 422, 422, 422, 422, 422, 422, 422, 422, 422,
+ 427, 272, 427, 427, 427, 427, 427, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 271, 427, 427,
+ 427, 274, 265, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
+ 274, 274, 437, 262, 437, 248, 437, 437, 244, 1113,
+ 117, 437, 117, 437, 442, 1113, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+
+ 442, 442, 442, 442, 442, 295, 1113, 295, 295, 295,
+ 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
+ 295, 295, 295, 295, 295, 295, 444, 1113, 444, 444,
+ 444, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+ 444, 444, 444, 444, 444, 444, 444, 445, 1113, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 299, 299,
+ 299, 299, 299, 299, 299, 299, 299, 299, 299, 299,
+ 299, 299, 299, 1113, 299, 1113, 299, 299, 299, 302,
+ 1113, 302, 302, 1113, 302, 302, 302, 302, 302, 302,
+
+ 302, 302, 302, 302, 1113, 302, 1113, 302, 302, 302,
+ 448, 448, 448, 448, 448, 448, 448, 448, 448, 448,
+ 448, 448, 448, 448, 448, 448, 448, 448, 448, 448,
+ 448, 309, 1113, 1113, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 317, 1113, 317, 1113, 317, 317, 1113, 1113,
+ 1113, 317, 326, 1113, 326, 1113, 326, 1113, 326, 326,
+ 326, 326, 1113, 326, 326, 1113, 1113, 1113, 326, 328,
+ 1113, 328, 328, 328, 328, 328, 328, 328, 328, 328,
+ 328, 328, 328, 328, 328, 328, 328, 328, 328, 328,
+
+ 331, 1113, 331, 1113, 331, 331, 1113, 1113, 1113, 331,
+ 334, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 334, 334, 334, 334, 334,
+ 334, 337, 1113, 337, 337, 337, 337, 337, 1113, 337,
+ 337, 337, 337, 337, 337, 337, 1113, 337, 1113, 337,
+ 337, 337, 340, 1113, 340, 1113, 340, 340, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 1113, 1113, 1113,
+ 340, 340, 340, 468, 1113, 468, 468, 468, 468, 468,
+ 468, 468, 468, 468, 468, 468, 468, 468, 468, 468,
+ 468, 468, 468, 468, 353, 1113, 353, 353, 353, 353,
+
+ 353, 353, 353, 353, 353, 353, 353, 353, 353, 353,
+ 353, 353, 353, 353, 353, 357, 357, 1113, 1113, 1113,
+ 357, 357, 389, 1113, 389, 389, 389, 389, 389, 389,
+ 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
+ 389, 389, 389, 392, 1113, 1113, 392, 392, 392, 392,
+ 392, 392, 392, 392, 392, 392, 392, 392, 1113, 392,
+ 1113, 392, 396, 1113, 396, 396, 396, 396, 1113, 396,
+ 396, 396, 396, 396, 396, 396, 396, 396, 396, 396,
+ 396, 396, 396, 401, 401, 401, 401, 401, 401, 401,
+ 401, 401, 401, 401, 401, 401, 401, 401, 1113, 401,
+
+ 1113, 401, 401, 401, 404, 1113, 404, 404, 404, 1113,
+ 404, 404, 404, 404, 404, 404, 404, 404, 404, 1113,
+ 1113, 1113, 404, 404, 404, 406, 1113, 406, 406, 406,
+ 406, 406, 406, 406, 406, 406, 406, 406, 406, 406,
+ 406, 406, 406, 406, 406, 406, 407, 1113, 407, 407,
+ 407, 407, 407, 407, 407, 407, 407, 407, 407, 407,
+ 407, 407, 407, 407, 407, 407, 407, 521, 521, 521,
+ 521, 521, 521, 521, 521, 521, 521, 521, 521, 521,
+ 521, 521, 521, 521, 521, 521, 521, 521, 530, 1113,
+ 530, 1113, 530, 530, 1113, 1113, 1113, 530, 532, 1113,
+
+ 532, 1113, 532, 532, 1113, 1113, 1113, 532, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418, 418, 418,
+ 418, 418, 418, 418, 418, 418, 418, 418, 418, 422,
+ 422, 422, 422, 422, 422, 422, 422, 422, 422, 422,
+ 422, 422, 422, 422, 422, 422, 422, 422, 422, 422,
+ 427, 1113, 427, 427, 427, 427, 427, 427, 427, 427,
+ 427, 427, 427, 427, 427, 427, 427, 1113, 427, 427,
+ 427, 437, 1113, 437, 1113, 437, 437, 1113, 1113, 1113,
+ 437, 1113, 437, 442, 1113, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+
+ 442, 442, 442, 442, 444, 1113, 444, 444, 444, 444,
+ 444, 444, 444, 444, 444, 444, 444, 444, 444, 444,
+ 444, 444, 444, 444, 444, 445, 1113, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 302, 1113, 302, 302,
+ 1113, 302, 302, 302, 302, 302, 302, 302, 302, 302,
+ 302, 1113, 302, 1113, 302, 302, 302, 448, 448, 448,
+ 448, 448, 448, 448, 448, 448, 448, 448, 448, 448,
+ 448, 448, 448, 448, 448, 448, 448, 448, 331, 1113,
+ 331, 1113, 331, 331, 1113, 1113, 1113, 331, 342, 1113,
+
+ 342, 342, 342, 342, 342, 342, 342, 342, 342, 342,
+ 342, 342, 342, 342, 342, 342, 342, 342, 342, 468,
+ 1113, 468, 468, 468, 468, 468, 468, 468, 468, 468,
+ 468, 468, 468, 468, 468, 468, 468, 468, 468, 468,
+ 357, 357, 1113, 1113, 1113, 357, 357, 630, 1113, 630,
+ 630, 630, 630, 630, 630, 630, 630, 630, 630, 630,
+ 630, 630, 630, 630, 630, 630, 630, 630, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 800,
+ 800, 800, 800, 800, 800, 800, 800, 800, 800, 938,
+ 938, 938, 938, 938, 938, 938, 938, 938, 938, 938,
+
+ 938, 938, 938, 938, 938, 938, 938, 938, 938, 938,
+ 55, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113
+
+ } ;
+
+static const flex_int16_t yy_chk[4596] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
+ 102, 3, 3, 5, 3, 5, 1012, 3, 3, 3,
+ 3, 79, 79, 3, 3, 6, 6, 7, 6, 7,
+ 3, 21, 6, 3, 8, 132, 8, 11, 11, 102,
+
+ 11, 12, 12, 964, 12, 19, 85, 19, 19, 27,
+ 28, 27, 28, 17, 20, 17, 20, 20, 148, 3,
+ 3, 51, 9, 51, 9, 17, 537, 22, 9, 17,
+ 17, 17, 17, 10, 132, 10, 29, 963, 29, 10,
+ 176, 21, 21, 47, 21, 47, 29, 148, 3, 3,
+ 3, 4, 4, 47, 4, 4, 19, 4, 4, 537,
+ 4, 4, 4, 4, 9, 20, 4, 4, 23, 176,
+ 23, 9, 9, 4, 9, 10, 4, 22, 22, 85,
+ 22, 23, 10, 10, 962, 10, 29, 199, 29, 45,
+ 52, 45, 52, 9, 17, 93, 37, 93, 45, 37,
+
+ 9, 961, 4, 4, 10, 4, 38, 960, 46, 38,
+ 46, 10, 37, 37, 37, 37, 199, 46, 23, 23,
+ 23, 959, 38, 38, 38, 38, 57, 57, 153, 57,
+ 153, 4, 4, 4, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 18, 24,
+ 18, 24, 155, 30, 155, 30, 31, 202, 31, 31,
+ 18, 64, 24, 30, 18, 18, 18, 18, 32, 43,
+ 32, 32, 53, 48, 53, 48, 167, 61, 61, 53,
+ 61, 101, 43, 48, 73, 73, 202, 73, 81, 261,
+ 81, 261, 43, 81, 81, 81, 81, 43, 64, 24,
+ 24, 24, 170, 30, 958, 30, 31, 31, 31, 170,
+ 957, 101, 43, 111, 111, 268, 111, 268, 32, 32,
+ 32, 43, 53, 53, 53, 956, 43, 167, 64, 18,
+
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 33, 33, 39, 33, 39, 34,
+ 34, 33, 34, 147, 41, 42, 34, 49, 44, 49,
+
+ 33, 41, 42, 175, 308, 34, 308, 49, 274, 274,
+ 50, 44, 50, 184, 41, 42, 122, 122, 122, 122,
+ 50, 44, 185, 147, 41, 42, 44, 33, 207, 41,
+ 42, 955, 34, 175, 33, 33, 39, 33, 39, 34,
+ 34, 44, 34, 184, 41, 42, 334, 49, 334, 49,
+ 44, 954, 185, 41, 42, 44, 33, 207, 41, 42,
+ 50, 34, 50, 33, 336, 39, 336, 39, 34, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 40, 634, 40, 54, 189, 54, 69,
+ 69, 188, 69, 54, 80, 80, 69, 82, 82, 188,
+ 82, 189, 128, 128, 82, 278, 278, 131, 131, 953,
+ 138, 138, 359, 82, 187, 190, 194, 634, 195, 82,
+ 187, 188, 191, 201, 196, 345, 80, 192, 196, 188,
+
+ 952, 189, 345, 40, 128, 40, 54, 54, 54, 131,
+ 897, 359, 138, 191, 187, 190, 194, 192, 195, 187,
+ 198, 82, 191, 201, 196, 80, 896, 192, 196, 203,
+ 198, 204, 40, 128, 40, 65, 243, 243, 131, 243,
+ 69, 138, 191, 250, 205, 197, 192, 361, 82, 197,
+ 198, 206, 251, 200, 65, 259, 65, 273, 65, 203,
+ 198, 204, 895, 200, 65, 894, 200, 65, 65, 65,
+ 893, 65, 65, 65, 205, 197, 361, 65, 892, 197,
+ 250, 206, 251, 200, 65, 259, 65, 273, 65, 211,
+ 211, 211, 211, 200, 65, 200, 891, 65, 65, 65,
+
+ 65, 65, 65, 890, 247, 247, 65, 247, 65, 889,
+ 250, 254, 254, 888, 254, 255, 255, 887, 255, 256,
+ 256, 363, 256, 257, 257, 275, 257, 293, 254, 254,
+ 254, 254, 255, 255, 255, 255, 256, 256, 256, 256,
+ 257, 257, 257, 257, 264, 264, 304, 264, 276, 276,
+ 363, 264, 305, 886, 254, 275, 275, 293, 312, 312,
+ 256, 312, 332, 257, 885, 284, 284, 884, 284, 333,
+ 349, 350, 284, 355, 356, 358, 304, 883, 365, 366,
+ 276, 284, 305, 254, 367, 360, 368, 284, 371, 358,
+ 256, 369, 332, 257, 319, 319, 319, 319, 372, 333,
+
+ 349, 350, 360, 355, 356, 358, 364, 365, 366, 276,
+ 364, 373, 381, 367, 374, 360, 368, 371, 358, 284,
+ 418, 369, 418, 882, 420, 264, 420, 422, 372, 422,
+ 881, 360, 391, 391, 391, 391, 364, 424, 880, 424,
+ 364, 373, 381, 374, 376, 378, 284, 321, 321, 321,
+ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321,
+ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321,
+ 321, 321, 370, 376, 378, 321, 370, 321, 321, 321,
+ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321,
+ 321, 321, 321, 321, 321, 321, 321, 321, 321, 321,
+
+ 321, 379, 370, 380, 383, 370, 382, 383, 384, 385,
+ 382, 879, 386, 380, 387, 382, 385, 878, 405, 427,
+ 427, 412, 413, 433, 433, 448, 414, 448, 639, 639,
+ 379, 416, 426, 380, 383, 877, 382, 383, 384, 385,
+ 382, 386, 380, 387, 531, 382, 385, 388, 405, 388,
+ 412, 413, 388, 388, 408, 408, 414, 408, 388, 388,
+ 428, 416, 426, 876, 388, 388, 875, 411, 411, 388,
+ 411, 408, 408, 408, 408, 441, 388, 388, 443, 388,
+ 429, 429, 388, 388, 411, 411, 411, 411, 388, 388,
+ 428, 428, 446, 388, 388, 431, 431, 447, 388, 438,
+
+ 438, 438, 438, 464, 450, 441, 450, 465, 443, 469,
+ 470, 521, 429, 521, 871, 471, 429, 524, 870, 524,
+ 526, 526, 446, 526, 531, 818, 625, 447, 625, 431,
+ 431, 626, 626, 464, 626, 632, 632, 465, 632, 469,
+ 470, 429, 430, 430, 471, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 817, 430, 430, 430,
+
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 430, 430, 430, 430,
+ 430, 430, 430, 430, 430, 430, 432, 432, 432, 432,
+ 451, 452, 453, 457, 456, 432, 432, 432, 432, 432,
+ 432, 454, 459, 460, 472, 461, 451, 452, 473, 458,
+ 453, 474, 457, 461, 454, 816, 456, 475, 476, 477,
+ 432, 432, 459, 460, 478, 432, 432, 432, 432, 432,
+ 432, 458, 480, 472, 458, 482, 451, 452, 473, 481,
+ 453, 474, 457, 461, 454, 456, 486, 475, 476, 477,
+ 484, 487, 459, 460, 478, 815, 485, 488, 489, 814,
+
+ 458, 491, 480, 458, 462, 482, 492, 493, 481, 462,
+ 462, 462, 462, 494, 495, 462, 486, 496, 497, 484,
+ 462, 487, 498, 499, 462, 485, 488, 462, 489, 462,
+ 500, 491, 462, 501, 502, 503, 492, 493, 505, 462,
+ 462, 462, 462, 494, 495, 462, 506, 496, 497, 504,
+ 462, 507, 498, 499, 462, 504, 462, 508, 462, 509,
+ 500, 462, 510, 501, 502, 503, 511, 513, 505, 512,
+ 514, 515, 516, 517, 519, 506, 518, 519, 519, 504,
+ 507, 520, 638, 638, 638, 504, 546, 508, 527, 509,
+ 528, 529, 510, 533, 543, 544, 511, 513, 512, 813,
+
+ 514, 515, 516, 517, 519, 518, 519, 519, 631, 522,
+ 522, 520, 522, 525, 525, 546, 525, 719, 527, 719,
+ 528, 529, 812, 533, 543, 544, 522, 522, 522, 522,
+ 525, 525, 525, 525, 534, 534, 811, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 631, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+
+ 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 534, 534, 535, 535,
+ 545, 548, 550, 810, 539, 539, 549, 552, 557, 551,
+ 554, 549, 552, 553, 809, 559, 558, 640, 640, 548,
+ 551, 548, 556, 554, 727, 727, 550, 556, 557, 558,
+ 545, 559, 535, 535, 536, 536, 536, 536, 539, 539,
+ 553, 549, 552, 536, 536, 536, 536, 536, 536, 548,
+ 551, 548, 555, 554, 562, 550, 560, 556, 557, 558,
+ 800, 559, 800, 563, 569, 561, 566, 562, 564, 553,
+ 555, 571, 560, 536, 536, 536, 536, 536, 536, 540,
+
+ 540, 540, 540, 561, 565, 563, 566, 564, 540, 540,
+ 540, 540, 540, 540, 569, 567, 568, 562, 570, 572,
+ 555, 571, 560, 575, 568, 808, 565, 576, 577, 565,
+ 578, 579, 580, 561, 563, 567, 566, 564, 540, 540,
+ 540, 540, 540, 540, 582, 584, 581, 570, 572, 583,
+ 587, 806, 588, 575, 568, 565, 576, 577, 565, 578,
+ 589, 579, 580, 581, 590, 567, 594, 595, 599, 581,
+ 799, 597, 598, 601, 582, 584, 602, 603, 583, 604,
+ 587, 588, 605, 606, 796, 607, 608, 609, 611, 589,
+ 612, 613, 615, 581, 590, 594, 614, 595, 599, 581,
+
+ 597, 598, 601, 616, 617, 619, 602, 603, 618, 604,
+ 620, 605, 621, 606, 607, 608, 620, 609, 611, 622,
+ 612, 613, 615, 627, 628, 614, 629, 636, 636, 641,
+ 651, 643, 616, 646, 617, 619, 647, 618, 644, 784,
+ 620, 669, 621, 650, 652, 620, 770, 660, 647, 622,
+ 651, 648, 627, 652, 628, 629, 650, 649, 646, 641,
+ 643, 636, 636, 637, 637, 637, 637, 653, 644, 648,
+ 669, 660, 637, 637, 637, 637, 637, 637, 647, 649,
+ 651, 654, 655, 652, 656, 653, 650, 646, 654, 655,
+ 657, 658, 659, 656, 728, 728, 665, 659, 663, 648,
+
+ 660, 657, 637, 637, 637, 637, 637, 637, 649, 658,
+ 661, 658, 662, 664, 665, 653, 667, 662, 654, 655,
+ 668, 661, 670, 656, 666, 663, 664, 659, 671, 666,
+ 672, 657, 674, 668, 676, 679, 667, 761, 680, 658,
+ 681, 658, 683, 687, 665, 679, 685, 662, 688, 689,
+ 691, 661, 670, 692, 663, 693, 664, 671, 695, 666,
+ 672, 674, 696, 668, 676, 679, 667, 680, 697, 699,
+ 681, 700, 683, 687, 679, 685, 701, 702, 688, 689,
+ 691, 704, 692, 705, 707, 693, 706, 695, 709, 710,
+ 711, 696, 713, 714, 733, 715, 716, 697, 717, 699,
+
+ 700, 720, 721, 722, 722, 701, 722, 702, 730, 736,
+ 704, 733, 734, 705, 707, 706, 737, 734, 709, 710,
+ 711, 735, 713, 714, 715, 736, 716, 739, 717, 740,
+ 738, 720, 721, 726, 726, 726, 735, 741, 743, 745,
+ 737, 733, 738, 744, 747, 742, 746, 734, 748, 739,
+ 729, 750, 749, 740, 742, 736, 744, 752, 746, 751,
+ 743, 741, 747, 725, 745, 749, 735, 753, 751, 737,
+ 748, 750, 738, 754, 753, 752, 755, 763, 739, 764,
+ 754, 765, 740, 756, 742, 755, 744, 763, 746, 743,
+ 741, 766, 747, 745, 756, 749, 767, 768, 751, 748,
+
+ 769, 750, 771, 772, 753, 752, 773, 763, 774, 764,
+ 754, 765, 775, 776, 778, 755, 777, 763, 780, 724,
+ 782, 766, 786, 787, 756, 767, 768, 788, 791, 769,
+ 793, 797, 771, 772, 718, 798, 773, 802, 774, 802,
+ 804, 712, 775, 776, 778, 777, 790, 790, 780, 782,
+ 820, 790, 786, 787, 790, 819, 788, 790, 791, 708,
+ 793, 797, 790, 794, 794, 798, 823, 820, 794, 804,
+ 821, 794, 824, 822, 794, 821, 790, 790, 825, 819,
+ 826, 790, 823, 827, 790, 828, 831, 790, 822, 830,
+ 825, 790, 832, 794, 794, 833, 824, 820, 794, 831,
+
+ 834, 794, 826, 835, 794, 821, 829, 827, 819, 828,
+ 838, 830, 823, 836, 841, 829, 694, 840, 822, 842,
+ 825, 843, 832, 844, 833, 824, 845, 847, 849, 831,
+ 834, 826, 835, 850, 852, 856, 827, 857, 828, 838,
+ 830, 858, 690, 836, 841, 829, 840, 860, 842, 865,
+ 852, 843, 844, 861, 862, 859, 845, 847, 849, 859,
+ 863, 864, 859, 850, 852, 856, 857, 866, 684, 868,
+ 869, 858, 859, 872, 867, 678, 860, 867, 865, 852,
+ 873, 898, 873, 861, 862, 859, 903, 867, 899, 859,
+ 863, 864, 859, 900, 901, 902, 905, 866, 868, 869,
+
+ 906, 859, 872, 907, 867, 898, 908, 867, 910, 911,
+ 912, 642, 913, 914, 915, 903, 867, 916, 899, 917,
+ 919, 920, 921, 900, 901, 902, 905, 922, 635, 923,
+ 906, 924, 926, 907, 898, 927, 908, 910, 928, 911,
+ 912, 913, 930, 914, 915, 931, 932, 916, 917, 933,
+ 919, 920, 921, 934, 935, 937, 936, 922, 923, 938,
+ 924, 938, 926, 965, 940, 927, 940, 928, 966, 967,
+ 968, 969, 930, 936, 970, 931, 932, 971, 933, 972,
+ 973, 974, 934, 935, 937, 975, 936, 976, 978, 633,
+ 979, 980, 965, 981, 982, 983, 984, 985, 966, 967,
+
+ 968, 969, 936, 987, 970, 989, 990, 971, 972, 973,
+ 991, 974, 992, 993, 975, 995, 999, 976, 978, 979,
+ 980, 996, 981, 998, 982, 983, 984, 985, 1015, 997,
+ 1013, 1014, 987, 997, 989, 990, 1016, 1017, 1019, 1020,
+ 991, 1022, 992, 993, 1023, 995, 999, 1024, 1025, 1026,
+ 996, 1027, 998, 1028, 1030, 1034, 1035, 1015, 997, 1036,
+ 1013, 1014, 997, 1039, 1040, 1016, 1017, 1041, 1019, 1020,
+ 1022, 1042, 1043, 1023, 1044, 1046, 1047, 1024, 1025, 1026,
+ 1048, 1027, 1049, 1028, 1030, 1034, 1035, 1050, 1053, 1036,
+ 1055, 1057, 1039, 1060, 1040, 1063, 1064, 1041, 1065, 1066,
+
+ 1042, 1043, 1067, 1044, 1046, 1068, 1047, 1069, 1070, 1072,
+ 1048, 1073, 1049, 1074, 1075, 623, 1077, 1050, 1053, 1055,
+ 1081, 1057, 1082, 1060, 1083, 1063, 1064, 1065, 1084, 1066,
+ 1086, 1087, 1067, 1088, 1089, 1068, 1090, 1069, 1070, 1072,
+ 1073, 1093, 1074, 1095, 1075, 1077, 1096, 1097, 1098, 1100,
+ 1081, 1103, 1082, 1083, 1105, 596, 1106, 1107, 1084, 1109,
+ 1086, 1087, 1110, 1088, 1089, 1090, 1157, 1157, 593, 1173,
+ 1093, 1173, 1206, 1095, 1206, 1096, 1097, 1098, 547, 1100,
+ 538, 1103, 1166, 1166, 1105, 1106, 1107, 1166, 490, 1109,
+ 467, 466, 1110, 1114, 1114, 1114, 1114, 1114, 1114, 1114,
+
+ 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114,
+ 1114, 1114, 1114, 1114, 1115, 1115, 1115, 1115, 1115, 1115,
+ 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115,
+ 1115, 1115, 1115, 1115, 1115, 1116, 1116, 1116, 1116, 1116,
+ 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116,
+ 1116, 1116, 1116, 1116, 1116, 1116, 1117, 1117, 1117, 1117,
+ 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1117,
+ 1117, 1117, 1117, 1117, 1117, 1117, 1117, 1118, 1118, 1118,
+ 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118,
+ 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1119, 1119,
+
+ 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119,
+ 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1120,
+ 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120,
+ 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120,
+ 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121,
+ 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121, 1121,
+ 1121, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122,
+ 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122, 1122,
+ 1122, 1122, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+
+ 1123, 1123, 1123, 1124, 1124, 1124, 1124, 1124, 1124, 1124,
+ 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124, 1124,
+ 1124, 1124, 1124, 1124, 1125, 1125, 1125, 1125, 1125, 1125,
+ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ 1125, 1125, 1125, 1125, 1125, 1126, 1126, 1126, 1126, 1126,
+ 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126,
+ 1126, 1126, 1126, 1126, 1126, 1126, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1128, 1128, 1128,
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128,
+
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1128, 1129, 1129,
+ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129,
+ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1130,
+ 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130,
+ 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130, 1130,
+ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131,
+ 1131, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132,
+ 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132, 1132,
+ 1132, 1132, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133,
+
+ 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133, 1133,
+ 1133, 1133, 1133, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1134, 1134, 1135, 455, 1135, 437, 1135, 1135,
+ 1213, 1213, 1213, 1135, 1136, 1136, 1136, 1136, 1136, 1136,
+ 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136,
+ 1136, 1136, 1136, 1136, 1137, 410, 1137, 389, 1137, 1137,
+ 1167, 1167, 362, 1137, 1138, 1167, 1138, 1138, 1138, 1138,
+ 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138, 1138,
+ 1138, 1138, 1138, 1138, 1138, 1139, 353, 1139, 1139, 1139,
+
+ 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139,
+ 1139, 1139, 1139, 1139, 1139, 1139, 1140, 1140, 351, 1140,
+ 346, 1140, 1140, 344, 343, 328, 1140, 1141, 315, 1141,
+ 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141,
+ 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1142, 1142,
+ 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142,
+ 1142, 1142, 1142, 314, 1142, 313, 1142, 1142, 1142, 1143,
+ 310, 1143, 1143, 296, 1143, 1143, 1143, 1143, 1143, 1143,
+ 1143, 1143, 1143, 1143, 289, 1143, 288, 1143, 1143, 1143,
+ 1144, 287, 286, 1144, 1144, 1144, 1144, 1144, 1144, 1144,
+
+ 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144, 1144,
+ 1144, 1145, 283, 1145, 281, 1145, 1145, 280, 271, 270,
+ 1145, 1146, 267, 1146, 1146, 1146, 1146, 1146, 1146, 1146,
+ 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146,
+ 1146, 1146, 1147, 266, 1147, 1147, 1147, 1147, 1147, 1147,
+ 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 249,
+ 1147, 1147, 1147, 1148, 245, 1148, 241, 1148, 239, 1148,
+ 1148, 1148, 1148, 238, 1148, 1148, 236, 235, 234, 1148,
+ 1149, 230, 1149, 1149, 1149, 216, 1149, 1149, 1149, 1149,
+ 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149,
+
+ 1149, 1150, 215, 1150, 214, 1150, 1150, 210, 183, 182,
+ 1150, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
+ 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151,
+ 1151, 1151, 1152, 180, 1152, 1152, 1152, 1152, 1152, 178,
+ 1152, 1152, 1152, 1152, 1152, 1152, 1152, 177, 1152, 174,
+ 1152, 1152, 1152, 1153, 173, 1153, 172, 1153, 1153, 1153,
+ 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, 168, 166,
+ 164, 1153, 1153, 1153, 1154, 1154, 1154, 1154, 1154, 1154,
+ 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154, 1154,
+ 1154, 1154, 1154, 1154, 1154, 1155, 161, 1155, 1155, 1155,
+
+ 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155,
+ 1155, 1155, 1155, 1155, 1155, 1155, 1156, 1156, 160, 159,
+ 158, 1156, 1156, 1158, 150, 1158, 1158, 1158, 1158, 1158,
+ 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158,
+ 1158, 1158, 1158, 1158, 1159, 149, 145, 1159, 1159, 1159,
+ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 144,
+ 1159, 142, 1159, 1160, 137, 1160, 1160, 1160, 1160, 135,
+ 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160,
+ 1160, 1160, 1160, 1160, 1161, 1161, 1161, 1161, 1161, 1161,
+ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 130,
+
+ 1161, 126, 1161, 1161, 1161, 1162, 120, 1162, 1162, 1162,
+ 115, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162, 1162,
+ 113, 112, 109, 1162, 1162, 1162, 1163, 107, 1163, 105,
+ 1163, 1163, 104, 103, 99, 1163, 1164, 96, 1164, 1164,
+ 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1164,
+ 1164, 1164, 1164, 1164, 1164, 1164, 1164, 1165, 95, 1165,
+ 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165,
+ 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1168, 1168,
+ 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168,
+ 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1168, 1169,
+
+ 92, 1169, 90, 1169, 1169, 86, 84, 78, 1169, 1170,
+ 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170,
+ 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170,
+ 1171, 77, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 74, 1171, 1171,
+ 1171, 1172, 71, 1172, 1172, 1172, 1172, 1172, 1172, 1172,
+ 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172,
+ 1172, 1172, 1174, 66, 1174, 63, 1174, 1174, 59, 55,
+ 16, 1174, 15, 1174, 1175, 0, 1175, 1175, 1175, 1175,
+ 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175, 1175,
+
+ 1175, 1175, 1175, 1175, 1175, 1176, 0, 1176, 1176, 1176,
+ 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176, 1176,
+ 1176, 1176, 1176, 1176, 1176, 1176, 1177, 0, 1177, 1177,
+ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
+ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1178, 0, 1178,
+ 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178,
+ 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1179, 1179,
+ 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179,
+ 1179, 1179, 1179, 0, 1179, 0, 1179, 1179, 1179, 1180,
+ 0, 1180, 1180, 0, 1180, 1180, 1180, 1180, 1180, 1180,
+
+ 1180, 1180, 1180, 1180, 0, 1180, 0, 1180, 1180, 1180,
+ 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181,
+ 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181,
+ 1181, 1182, 0, 0, 1182, 1182, 1182, 1182, 1182, 1182,
+ 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182,
+ 1182, 1182, 1183, 0, 1183, 0, 1183, 1183, 0, 0,
+ 0, 1183, 1184, 0, 1184, 0, 1184, 0, 1184, 1184,
+ 1184, 1184, 0, 1184, 1184, 0, 0, 0, 1184, 1185,
+ 0, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185,
+ 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185,
+
+ 1186, 0, 1186, 0, 1186, 1186, 0, 0, 0, 1186,
+ 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187,
+ 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187, 1187,
+ 1187, 1188, 0, 1188, 1188, 1188, 1188, 1188, 0, 1188,
+ 1188, 1188, 1188, 1188, 1188, 1188, 0, 1188, 0, 1188,
+ 1188, 1188, 1189, 0, 1189, 0, 1189, 1189, 1189, 1189,
+ 1189, 1189, 1189, 1189, 1189, 1189, 1189, 0, 0, 0,
+ 1189, 1189, 1189, 1190, 0, 1190, 1190, 1190, 1190, 1190,
+ 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190,
+ 1190, 1190, 1190, 1190, 1191, 0, 1191, 1191, 1191, 1191,
+
+ 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191,
+ 1191, 1191, 1191, 1191, 1191, 1192, 1192, 0, 0, 0,
+ 1192, 1192, 1193, 0, 1193, 1193, 1193, 1193, 1193, 1193,
+ 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193,
+ 1193, 1193, 1193, 1194, 0, 0, 1194, 1194, 1194, 1194,
+ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 0, 1194,
+ 0, 1194, 1195, 0, 1195, 1195, 1195, 1195, 0, 1195,
+ 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1195, 1195, 1195, 1196, 1196, 1196, 1196, 1196, 1196, 1196,
+ 1196, 1196, 1196, 1196, 1196, 1196, 1196, 1196, 0, 1196,
+
+ 0, 1196, 1196, 1196, 1197, 0, 1197, 1197, 1197, 0,
+ 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 0,
+ 0, 0, 1197, 1197, 1197, 1198, 0, 1198, 1198, 1198,
+ 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198,
+ 1198, 1198, 1198, 1198, 1198, 1198, 1199, 0, 1199, 1199,
+ 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1199,
+ 1199, 1199, 1199, 1199, 1199, 1199, 1199, 1200, 1200, 1200,
+ 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200,
+ 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1201, 0,
+ 1201, 0, 1201, 1201, 0, 0, 0, 1201, 1202, 0,
+
+ 1202, 0, 1202, 1202, 0, 0, 0, 1202, 1203, 1203,
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203,
+ 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1203, 1204,
+ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ 1205, 0, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205,
+ 1205, 1205, 1205, 1205, 1205, 1205, 1205, 0, 1205, 1205,
+ 1205, 1207, 0, 1207, 0, 1207, 1207, 0, 0, 0,
+ 1207, 0, 1207, 1208, 0, 1208, 1208, 1208, 1208, 1208,
+ 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208, 1208,
+
+ 1208, 1208, 1208, 1208, 1209, 0, 1209, 1209, 1209, 1209,
+ 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209,
+ 1209, 1209, 1209, 1209, 1209, 1210, 0, 1210, 1210, 1210,
+ 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210,
+ 1210, 1210, 1210, 1210, 1210, 1210, 1211, 0, 1211, 1211,
+ 0, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211,
+ 1211, 0, 1211, 0, 1211, 1211, 1211, 1212, 1212, 1212,
+ 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212,
+ 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1212, 1214, 0,
+ 1214, 0, 1214, 1214, 0, 0, 0, 1214, 1215, 0,
+
+ 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215,
+ 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1215, 1216,
+ 0, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216,
+ 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216,
+ 1217, 1217, 0, 0, 0, 1217, 1217, 1218, 0, 1218,
+ 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218,
+ 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1219, 1219,
+ 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219,
+ 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1220,
+ 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220,
+
+ 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113
+
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "scan.l"
+/* scan.l - scanner for flex input -*-C-*- */
+#line 4 "scan.l"
+/* Copyright (c) 1990 The Regents of the University of California. */
+/* All rights reserved. */
+
+/* This code is derived from software contributed to Berkeley by */
+/* Vern Paxson. */
+
+/* The United States Government has rights in this work pursuant */
+/* to contract no. DE-AC03-76SF00098 between the United States */
+/* Department of Energy and the University of California. */
+
+/* This file is part of flex. */
+
+/* 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. */
+
+/* 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR */
+/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
+/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
+/* PURPOSE. */
+
+#include "flexdef.h"
+#include "parse.h"
+extern bool tablesverify, tablesext;
+extern int trlcontxt; /* Set in parse.y for each rule. */
+extern const char *escaped_qstart, *escaped_qend;
+extern int yylval;
+
+#define M4QSTART "[""["
+#define M4QEND "]""]"
+
+#define ESCAPED_QSTART "[" M4QEND M4QSTART "[" M4QEND M4QSTART
+#define ESCAPED_QEND M4QEND "]" M4QSTART M4QEND "]" M4QSTART
+
+#define ACTION_ECHO add_action( yytext )
+#define ACTION_IFDEF(def, should_define) \
+ { \
+ if ( should_define ) \
+ action_define( def, 1 ); \
+ }
+
+#define ACTION_ECHO_QSTART add_action (ESCAPED_QSTART)
+#define ACTION_ECHO_QEND add_action (ESCAPED_QEND)
+
+#define ACTION_M4_IFDEF(def, should_define) \
+ do{ \
+ if ( should_define ) \
+ buf_m4_define( &m4defs_buf, def, NULL);\
+ else \
+ buf_m4_undefine( &m4defs_buf, def);\
+ } while(0)
+
+#define MARK_END_OF_PROLOG mark_prolog();
+
+#define YY_DECL \
+ int flexscan(void)
+
+#define RETURNCHAR \
+ yylval = (unsigned char) yytext[0]; \
+ return CHAR;
+
+#define RETURNNAME \
+ if(yyleng < MAXLINE) \
+ { \
+ strncpy( nmstr, yytext, sizeof(nmstr) ); \
+ return NAME; \
+ } \
+ else \
+ do { \
+ synerr(_("Input line too long\n")); \
+ FLEX_EXIT(EXIT_FAILURE); \
+ } while (0)
+
+#define PUT_BACK_STRING(str, start) \
+ { size_t i = strlen( str ); \
+ while ( i > start ) \
+ unput((str)[--i]); \
+ }
+
+#define CHECK_REJECT(str) \
+ if ( all_upper( str ) ) \
+ reject = true;
+
+#define CHECK_YYMORE(str) \
+ if ( all_lower( str ) ) \
+ yymore_used = true;
+
+#define YY_USER_INIT \
+ if ( getenv("POSIXLY_CORRECT") ) \
+ posix_compat = true;
+
+#define START_CODEBLOCK(x) do { \
+ /* Emit the needed line directive... */\
+ if (indented_code == false) { \
+ linenum++; \
+ line_directive_out(NULL, 1); \
+ } \
+ add_action(M4QSTART); \
+ yy_push_state(CODEBLOCK); \
+ if ((indented_code = x)) ACTION_ECHO; \
+} while(0)
+
+#define END_CODEBLOCK do { \
+ yy_pop_state();\
+ add_action(M4QEND); \
+ if (!indented_code) line_directive_out(NULL, 0);\
+} while (0)
+
+#line 1968 "<stdout>"
+
+#line 1970 "<stdout>"
+
+#define INITIAL 0
+#define SECT2 1
+#define SECT2PROLOG 2
+#define SECT3 3
+#define CODEBLOCK 4
+#define PICKUPDEF 5
+#define SC 6
+#define CARETISBOL 7
+#define NUM 8
+#define QUOTE 9
+#define FIRSTCCL 10
+#define CCL 11
+#define ACTION 12
+#define RECOVER 13
+#define COMMENT 14
+#define ACTION_STRING 15
+#define PERCENT_BRACE_ACTION 16
+#define OPTION 17
+#define LINEDIR 18
+#define CODEBLOCK_MATCH_BRACE 19
+#define GROUP_WITH_PARAMS 20
+#define GROUP_MINUS_PARAMS 21
+#define EXTENDED_COMMENT 22
+#define COMMENT_DISCARD 23
+#define CODE_COMMENT 24
+#define SECT3_NOESCAPE 25
+#define CHARACTER_CONSTANT 26
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals ( void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( void );
+
+int yyget_debug ( void );
+
+void yyset_debug ( int debug_flag );
+
+YY_EXTRA_TYPE yyget_extra ( void );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined );
+
+FILE *yyget_in ( void );
+
+void yyset_in ( FILE * _in_str );
+
+FILE *yyget_out ( void );
+
+void yyset_out ( FILE * _out_str );
+
+ int yyget_leng ( void );
+
+char *yyget_text ( void );
+
+int yyget_lineno ( void );
+
+void yyset_lineno ( int _line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( void );
+#else
+extern int yywrap ( void );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput ( int c, char *buf_ptr );
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * );
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( void );
+#else
+static int input ( void );
+#endif
+
+#endif
+
+ static int yy_start_stack_ptr = 0;
+ static int yy_start_stack_depth = 0;
+ static int *yy_start_stack = NULL;
+
+ static void yy_push_state ( int _new_state );
+
+ static void yy_pop_state ( void );
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ {
+#line 159 "scan.l"
+
+#line 161 "scan.l"
+ static int bracelevel, didadef, indented_code;
+ static int doing_rule_action = false;
+ static int option_sense;
+
+ int doing_codeblock = false;
+ int brace_depth=0, brace_start_line=0;
+ char nmdef[MAXLINE];
+
+
+#line 2236 "<stdout>"
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1114 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 4511 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 171 "scan.l"
+START_CODEBLOCK(true);
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 172 "scan.l"
+add_action("/*[""["); yy_push_state( COMMENT );
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 173 "scan.l"
+yy_push_state( LINEDIR );
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 174 "scan.l"
+return SCDECL;
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 175 "scan.l"
+return XSCDECL;
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 176 "scan.l"
+START_CODEBLOCK(false);
+ YY_BREAK
+case 7:
+/* rule 7 can match eol */
+YY_RULE_SETUP
+#line 177 "scan.l"
+{
+ brace_start_line = linenum;
+ ++linenum;
+ buf_linedir( &top_buf, infilename?infilename:"<stdin>", linenum);
+ brace_depth = 1;
+ yy_push_state(CODEBLOCK_MATCH_BRACE);
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 185 "scan.l"
+synerr( _("malformed '%top' directive") );
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 187 "scan.l"
+/* discard */
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 189 "scan.l"
+{
+ sectnum = 2;
+ bracelevel = 0;
+ mark_defs1();
+ line_directive_out(NULL, 1);
+ BEGIN(SECT2PROLOG);
+ return SECTEND;
+ }
+ YY_BREAK
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 198 "scan.l"
+yytext_is_array = false; ++linenum;
+ YY_BREAK
+case 12:
+/* rule 12 can match eol */
+YY_RULE_SETUP
+#line 199 "scan.l"
+yytext_is_array = true; ++linenum;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 201 "scan.l"
+BEGIN(OPTION); return TOK_OPTION;
+ YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 203 "scan.l"
+++linenum; /* ignore */
+ YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 204 "scan.l"
+++linenum; /* ignore */
+ YY_BREAK
+/* xgettext: no-c-format */
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 207 "scan.l"
+synerr( _( "unrecognized '%' directive" ) );
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 209 "scan.l"
+{
+ if(yyleng < MAXLINE)
+ {
+ strncpy( nmstr, yytext, sizeof(nmstr) );
+ }
+ else
+ {
+ synerr( _("Definition name too long\n"));
+ FLEX_EXIT(EXIT_FAILURE);
+ }
+
+ didadef = false;
+ BEGIN(PICKUPDEF);
+ }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 224 "scan.l"
+RETURNNAME;
+ YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 225 "scan.l"
+++linenum; /* allows blank lines in section 1 */
+ YY_BREAK
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 226 "scan.l"
+ACTION_ECHO; ++linenum; /* maybe end of comment line */
+ YY_BREAK
+
+/* */
+case 21:
+YY_RULE_SETUP
+#line 231 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 232 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 23:
+/* rule 23 can match eol */
+YY_RULE_SETUP
+#line 234 "scan.l"
+++linenum; ACTION_ECHO;
+ YY_BREAK
+
+
+case 24:
+YY_RULE_SETUP
+#line 237 "scan.l"
+add_action("*/]""]"); yy_pop_state();
+ YY_BREAK
+
+
+case 25:
+YY_RULE_SETUP
+#line 240 "scan.l"
+ACTION_ECHO; yy_pop_state();
+ YY_BREAK
+
+
+/* This is the same as COMMENT, but is discarded rather than output. */
+case 26:
+YY_RULE_SETUP
+#line 245 "scan.l"
+yy_pop_state();
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 246 "scan.l"
+;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 247 "scan.l"
+;
+ YY_BREAK
+case 29:
+/* rule 29 can match eol */
+YY_RULE_SETUP
+#line 248 "scan.l"
+++linenum;
+ YY_BREAK
+
+
+case 30:
+YY_RULE_SETUP
+#line 252 "scan.l"
+yy_pop_state();
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 253 "scan.l"
+;
+ YY_BREAK
+case 32:
+/* rule 32 can match eol */
+YY_RULE_SETUP
+#line 254 "scan.l"
+++linenum;
+ YY_BREAK
+
+
+case 33:
+/* rule 33 can match eol */
+YY_RULE_SETUP
+#line 258 "scan.l"
+yy_pop_state();
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 259 "scan.l"
+linenum = myctoi( yytext );
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 261 "scan.l"
+{
+ free(infilename);
+ infilename = xstrdup(yytext + 1);
+ infilename[strlen( infilename ) - 1] = '\0';
+ }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 266 "scan.l"
+/* ignore spurious characters */
+ YY_BREAK
+
+
+case 37:
+YY_RULE_SETUP
+#line 269 "scan.l"
+ACTION_ECHO_QSTART;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 270 "scan.l"
+ACTION_ECHO_QEND;
+ YY_BREAK
+
+
+case 39:
+/* rule 39 can match eol */
+YY_RULE_SETUP
+#line 274 "scan.l"
+++linenum; END_CODEBLOCK;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 275 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 276 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 42:
+/* rule 42 can match eol */
+YY_RULE_SETUP
+#line 277 "scan.l"
+{
+ ++linenum;
+ ACTION_ECHO;
+ if ( indented_code ) END_CODEBLOCK;
+ }
+ YY_BREAK
+
+
+case 43:
+YY_RULE_SETUP
+#line 285 "scan.l"
+{
+ if( --brace_depth == 0){
+ /* TODO: Matched. */
+ yy_pop_state();
+ }else
+ buf_strnappend(&top_buf, yytext, yyleng);
+ }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 293 "scan.l"
+{
+ brace_depth++;
+ buf_strnappend(&top_buf, yytext, yyleng);
+ }
+ YY_BREAK
+case 45:
+/* rule 45 can match eol */
+YY_RULE_SETUP
+#line 298 "scan.l"
+{
+ ++linenum;
+ buf_strnappend(&top_buf, yytext, yyleng);
+ }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 303 "scan.l"
+buf_strnappend(&top_buf, escaped_qstart, (int) strlen(escaped_qstart));
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 304 "scan.l"
+buf_strnappend(&top_buf, escaped_qend, (int) strlen(escaped_qend));
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 305 "scan.l"
+{
+ buf_strnappend(&top_buf, yytext, yyleng);
+ }
+ YY_BREAK
+case YY_STATE_EOF(CODEBLOCK_MATCH_BRACE):
+#line 309 "scan.l"
+{
+ linenum = brace_start_line;
+ synerr(_("Unmatched '{'"));
+ yyterminate();
+ }
+ YY_BREAK
+
+
+case 49:
+YY_RULE_SETUP
+#line 318 "scan.l"
+/* separates name and definition */
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 320 "scan.l"
+{
+ if(yyleng < MAXLINE)
+ {
+ strncpy( nmdef, yytext, sizeof(nmdef) );
+ }
+ else
+ {
+ format_synerr( _("Definition value for {%s} too long\n"), nmstr);
+ FLEX_EXIT(EXIT_FAILURE);
+ }
+ /* Skip trailing whitespace. */
+ {
+ size_t i = strlen( nmdef );
+ while (i > 0 && (nmdef[i-1] == ' ' || nmdef[i-1] == '\t'))
+ --i;
+ nmdef[i] = '\0';
+ }
+
+ ndinstal( nmstr, nmdef );
+ didadef = true;
+ }
+ YY_BREAK
+case 51:
+/* rule 51 can match eol */
+YY_RULE_SETUP
+#line 342 "scan.l"
+{
+ if ( ! didadef )
+ synerr( _( "incomplete name definition" ) );
+ BEGIN(INITIAL);
+ ++linenum;
+ }
+ YY_BREAK
+
+
+case 52:
+/* rule 52 can match eol */
+YY_RULE_SETUP
+#line 352 "scan.l"
+++linenum; BEGIN(INITIAL);
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 353 "scan.l"
+option_sense = true;
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 355 "scan.l"
+return '=';
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 357 "scan.l"
+option_sense = ! option_sense;
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 359 "scan.l"
+csize = option_sense ? 128 : 256;
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 360 "scan.l"
+csize = option_sense ? 256 : 128;
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 362 "scan.l"
+long_align = option_sense;
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 363 "scan.l"
+{
+ ACTION_M4_IFDEF( "M4""_YY_ALWAYS_INTERACTIVE", option_sense );
+ interactive = option_sense;
+ }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 367 "scan.l"
+yytext_is_array = option_sense;
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 368 "scan.l"
+backing_up_report = option_sense;
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 369 "scan.l"
+interactive = ! option_sense;
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 370 "scan.l"
+bison_bridge_lval = option_sense;
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 371 "scan.l"
+{ if((bison_bridge_lloc = option_sense))
+ bison_bridge_lval = true;
+ }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 374 "scan.l"
+C_plus_plus = option_sense;
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 375 "scan.l"
+sf_set_case_ins(!option_sense);
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 376 "scan.l"
+sf_set_case_ins(option_sense);
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 377 "scan.l"
+ddebug = option_sense;
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 378 "scan.l"
+spprdflt = ! option_sense;
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 379 "scan.l"
+useecs = option_sense;
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 380 "scan.l"
+{
+ useecs = usemecs = false;
+ use_read = fullspd = true;
+ }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 384 "scan.l"
+{
+ useecs = usemecs = false;
+ use_read = fulltbl = true;
+ }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 388 "scan.l"
+ACTION_IFDEF("YY_NO_INPUT", ! option_sense);
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 389 "scan.l"
+interactive = option_sense;
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 390 "scan.l"
+lex_compat = option_sense;
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 391 "scan.l"
+posix_compat = option_sense;
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 392 "scan.l"
+gen_line_dirs = option_sense;
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 393 "scan.l"
+{
+ ACTION_M4_IFDEF( "M4""_YY_MAIN", option_sense);
+ /* Override yywrap */
+ if( option_sense == true )
+ do_yywrap = false;
+ }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 399 "scan.l"
+usemecs = option_sense;
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 400 "scan.l"
+{
+ ACTION_M4_IFDEF( "M4""_YY_NEVER_INTERACTIVE", option_sense );
+ interactive = !option_sense;
+ }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 404 "scan.l"
+performance_report += option_sense ? 1 : -1;
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 405 "scan.l"
+yytext_is_array = ! option_sense;
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 406 "scan.l"
+use_read = option_sense;
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 407 "scan.l"
+reentrant = option_sense;
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 408 "scan.l"
+reject_really_used = option_sense;
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 409 "scan.l"
+ACTION_M4_IFDEF( "M4""_YY_STACK_USED", option_sense );
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 410 "scan.l"
+do_stdinit = option_sense;
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 411 "scan.l"
+use_stdout = option_sense;
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 412 "scan.l"
+ACTION_IFDEF("YY_NO_UNISTD_H", ! option_sense);
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 413 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_UNPUT", ! option_sense);
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 414 "scan.l"
+printstats = option_sense;
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 415 "scan.l"
+nowarn = ! option_sense;
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 416 "scan.l"
+do_yylineno = option_sense; ACTION_M4_IFDEF("M4""_YY_USE_LINENO", option_sense);
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 417 "scan.l"
+yymore_really_used = option_sense;
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 418 "scan.l"
+do_yywrap = option_sense;
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 420 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_PUSH_STATE", ! option_sense);
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 421 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_POP_STATE", ! option_sense);
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 422 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_TOP_STATE", ! option_sense);
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+#line 424 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BUFFER", ! option_sense);
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+#line 425 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SCAN_BYTES", ! option_sense);
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+#line 426 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SCAN_STRING", ! option_sense);
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+#line 428 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_FLEX_ALLOC", ! option_sense);
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+#line 429 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_FLEX_REALLOC", ! option_sense);
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+#line 430 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_FLEX_FREE", ! option_sense);
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+#line 432 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_DEBUG", ! option_sense);
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+#line 433 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_DEBUG", ! option_sense);
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+#line 434 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_EXTRA", ! option_sense);
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+#line 435 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_EXTRA", ! option_sense);
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+#line 436 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_LENG", ! option_sense);
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+#line 437 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_TEXT", ! option_sense);
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+#line 438 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_LINENO", ! option_sense);
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+#line 439 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_LINENO", ! option_sense);
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+#line 440 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_IN", ! option_sense);
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+#line 441 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_IN", ! option_sense);
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+#line 442 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_OUT", ! option_sense);
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+#line 443 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_OUT", ! option_sense);
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+#line 444 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_LVAL", ! option_sense);
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+#line 445 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_LVAL", ! option_sense);
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+#line 446 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_GET_LLOC", ! option_sense);
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+#line 447 "scan.l"
+ACTION_M4_IFDEF("M4""_YY_NO_SET_LLOC", ! option_sense);
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+#line 449 "scan.l"
+return TOK_EXTRA_TYPE;
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+#line 450 "scan.l"
+return TOK_OUTFILE;
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+#line 451 "scan.l"
+return TOK_PREFIX;
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+#line 452 "scan.l"
+return TOK_YYCLASS;
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+#line 453 "scan.l"
+return TOK_HEADER_FILE;
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+#line 454 "scan.l"
+return TOK_TABLES_FILE;
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+#line 455 "scan.l"
+{
+ tablesverify = option_sense;
+ if(!tablesext && option_sense)
+ tablesext = true;
+ }
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+#line 462 "scan.l"
+{
+ if(yyleng-1 < MAXLINE)
+ {
+ strncpy( nmstr, yytext + 1, sizeof(nmstr) );
+ }
+ else
+ {
+ synerr( _("Option line too long\n"));
+ FLEX_EXIT(EXIT_FAILURE);
+ }
+ nmstr[strlen( nmstr ) - 1] = '\0';
+ return NAME;
+ }
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+#line 476 "scan.l"
+{
+ format_synerr( _( "unrecognized %%option: %s" ),
+ yytext );
+ BEGIN(RECOVER);
+ }
+ YY_BREAK
+
+case 130:
+/* rule 130 can match eol */
+YY_RULE_SETUP
+#line 483 "scan.l"
+++linenum; BEGIN(INITIAL);
+ YY_BREAK
+
+case 131:
+YY_RULE_SETUP
+#line 487 "scan.l"
+++bracelevel; yyless( 2 ); /* eat only %{ */
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+#line 488 "scan.l"
+--bracelevel; yyless( 2 ); /* eat only %} */
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+#line 490 "scan.l"
+START_CODEBLOCK(true); /* indented code in prolog */
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+#line 492 "scan.l"
+{
+ /* non-indented code */
+ if ( bracelevel <= 0 ) {
+ /* not in %{ ... %} */
+ yyless( 0 ); /* put it all back */
+ yy_set_bol( 1 );
+ mark_prolog();
+ BEGIN(SECT2);
+ } else {
+ START_CODEBLOCK(true);
+ }
+ }
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+#line 505 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 136:
+/* rule 136 can match eol */
+YY_RULE_SETUP
+#line 506 "scan.l"
+++linenum; ACTION_ECHO;
+ YY_BREAK
+case YY_STATE_EOF(SECT2PROLOG):
+#line 508 "scan.l"
+{
+ mark_prolog();
+ sectnum = 0;
+ yyterminate(); /* to stop the parser */
+ }
+ YY_BREAK
+
+
+case 137:
+/* rule 137 can match eol */
+YY_RULE_SETUP
+#line 516 "scan.l"
+++linenum; /* allow blank lines in section 2 */
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+#line 518 "scan.l"
+{
+ indented_code = false;
+ doing_codeblock = true;
+ bracelevel = 1;
+ BEGIN(PERCENT_BRACE_ACTION);
+ }
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+#line 525 "scan.l"
+{
+ /* Allow "<" to appear in (?x) patterns. */
+ if (!sf_skip_ws())
+ BEGIN(SC);
+ return '<';
+ }
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+#line 531 "scan.l"
+return '^';
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+#line 532 "scan.l"
+BEGIN(QUOTE); return '"';
+ YY_BREAK
+case 142:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 533 "scan.l"
+{
+ BEGIN(NUM);
+ if ( lex_compat || posix_compat )
+ return BEGIN_REPEAT_POSIX;
+ else
+ return BEGIN_REPEAT_FLEX;
+ }
+ YY_BREAK
+case 143:
+/* rule 143 can match eol */
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+YY_LINENO_REWIND_TO(yy_bp + 1);
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 540 "scan.l"
+return '$';
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+#line 542 "scan.l"
+{
+ bracelevel = 1;
+ BEGIN(PERCENT_BRACE_ACTION);
+
+ if ( in_rule )
+ {
+ doing_rule_action = true;
+ in_rule = false;
+ return '\n';
+ }
+ }
+ YY_BREAK
+case 145:
+/* rule 145 can match eol */
+YY_RULE_SETUP
+#line 553 "scan.l"
+{
+ if (sf_skip_ws()){
+ /* We're in the middle of a (?x: ) pattern. */
+ /* Push back everything starting at the "|" */
+ int amt = (int) (strchr (yytext, '|') - yytext);
+ yyless(amt);
+ }
+ else {
+ add_action("]""]");
+ continued_action = true;
+ ++linenum;
+ return '\n';
+ }
+ }
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+#line 568 "scan.l"
+{
+
+ if (sf_skip_ws()){
+ /* We're in the middle of a (?x: ) pattern. */
+ yy_push_state(COMMENT_DISCARD);
+ }
+ else{
+ yyless( yyleng - 2 ); /* put back '/', '*' */
+ bracelevel = 0;
+ continued_action = false;
+ BEGIN(ACTION);
+ }
+ }
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+#line 582 "scan.l"
+/* allow indented rules */ ;
+ YY_BREAK
+case 148:
+YY_RULE_SETUP
+#line 584 "scan.l"
+{
+ if (sf_skip_ws()){
+ /* We're in the middle of a (?x: ) pattern. */
+ }
+ else{
+ /* This rule is separate from the one below because
+ * otherwise we get variable trailing context, so
+ * we can't build the scanner using -{f,F}.
+ */
+ bracelevel = 0;
+ continued_action = false;
+ BEGIN(ACTION);
+
+ if ( in_rule )
+ {
+ doing_rule_action = true;
+ in_rule = false;
+ return '\n';
+ }
+ }
+ }
+ YY_BREAK
+case 149:
+/* rule 149 can match eol */
+YY_RULE_SETUP
+#line 606 "scan.l"
+{
+ if (sf_skip_ws()){
+ /* We're in the middle of a (?x: ) pattern. */
+ ++linenum;
+ }
+ else{
+ bracelevel = 0;
+ continued_action = false;
+ BEGIN(ACTION);
+ unput( '\n' ); /* so <ACTION> sees it */
+
+ if ( in_rule )
+ {
+ doing_rule_action = true;
+ in_rule = false;
+ return '\n';
+ }
+ }
+ }
+ YY_BREAK
+case 150:
+#line 627 "scan.l"
+case 151:
+YY_RULE_SETUP
+#line 627 "scan.l"
+return EOF_OP;
+ YY_BREAK
+case 152:
+YY_RULE_SETUP
+#line 629 "scan.l"
+{
+ sectnum = 3;
+ BEGIN(no_section3_escape ? SECT3_NOESCAPE : SECT3);
+ outn("/* Begin user sect3 */");
+ yyterminate(); /* to stop the parser */
+
+ }
+ YY_BREAK
+case 153:
+YY_RULE_SETUP
+#line 637 "scan.l"
+{
+ int cclval;
+
+ if(yyleng < MAXLINE)
+ {
+ strncpy( nmstr, yytext, sizeof(nmstr) );
+ }
+ else
+ {
+ synerr( _("Input line too long\n"));
+ FLEX_EXIT(EXIT_FAILURE);
+ }
+
+ /* Check to see if we've already encountered this
+ * ccl.
+ */
+ if (0 /* <--- This "0" effectively disables the reuse of a
+ * character class (purely based on its source text).
+ * The reason it was disabled is so yacc/bison can parse
+ * ccl operations, such as ccl difference and union.
+ */
+ && (cclval = ccllookup( nmstr )) != 0 )
+ {
+ if ( input() != ']' )
+ synerr( _( "bad character class" ) );
+
+ yylval = cclval;
+ ++cclreuse;
+ return PREVCCL;
+ }
+ else
+ {
+ /* We fudge a bit. We know that this ccl will
+ * soon be numbered as lastccl + 1 by cclinit.
+ */
+ cclinstal( nmstr, lastccl + 1 );
+
+ /* Push back everything but the leading bracket
+ * so the ccl can be rescanned.
+ */
+ yyless( 1 );
+
+ BEGIN(FIRSTCCL);
+ return '[';
+ }
+ }
+ YY_BREAK
+case 154:
+YY_RULE_SETUP
+#line 683 "scan.l"
+return CCL_OP_DIFF;
+ YY_BREAK
+case 155:
+YY_RULE_SETUP
+#line 684 "scan.l"
+return CCL_OP_UNION;
+ YY_BREAK
+/* Check for :space: at the end of the rule so we don't
+ * wrap the expanded regex in '(' ')' -- breaking trailing
+ * context.
+ */
+case 156:
+/* rule 156 can match eol */
+YY_RULE_SETUP
+#line 691 "scan.l"
+{
+ char *nmdefptr;
+ int end_is_ws, end_ch;
+
+ end_ch = yytext[yyleng-1];
+ end_is_ws = end_ch != '}' ? 1 : 0;
+
+ if(yyleng-1 < MAXLINE)
+ {
+ strncpy( nmstr, yytext + 1, sizeof(nmstr) );
+ }
+ else
+ {
+ synerr( _("Input line too long\n"));
+ FLEX_EXIT(EXIT_FAILURE);
+ }
+nmstr[yyleng - 2 - end_is_ws] = '\0'; /* chop trailing brace */
+
+ if ( (nmdefptr = ndlookup( nmstr )) == NULL )
+ format_synerr(
+ _( "undefined definition {%s}" ),
+ nmstr );
+
+ else
+ { /* push back name surrounded by ()'s */
+ size_t len = strlen( nmdefptr );
+ if (end_is_ws)
+ unput(end_ch);
+
+ if ( lex_compat || nmdefptr[0] == '^' ||
+ (len > 0 && nmdefptr[len - 1] == '$')
+ || (end_is_ws && trlcontxt && !sf_skip_ws()))
+ { /* don't use ()'s after all */
+ PUT_BACK_STRING(nmdefptr, 0);
+
+ if ( nmdefptr[0] == '^' )
+ BEGIN(CARETISBOL);
+ }
+
+ else
+ {
+ unput(')');
+ PUT_BACK_STRING(nmdefptr, 0);
+ unput('(');
+ }
+ }
+ }
+ YY_BREAK
+case 157:
+YY_RULE_SETUP
+#line 739 "scan.l"
+{
+ if (sf_skip_ws())
+ yy_push_state(COMMENT_DISCARD);
+ else{
+ /* Push back the "*" and return "/" as usual. */
+ yyless(1);
+ return '/';
+ }
+ }
+ YY_BREAK
+case 158:
+YY_RULE_SETUP
+#line 749 "scan.l"
+{
+ if (lex_compat || posix_compat){
+ /* Push back the "?#" and treat it like a normal parens. */
+ yyless(1);
+ sf_push();
+ return '(';
+ }
+ else
+ yy_push_state(EXTENDED_COMMENT);
+ }
+ YY_BREAK
+case 159:
+YY_RULE_SETUP
+#line 759 "scan.l"
+{
+ sf_push();
+ if (lex_compat || posix_compat)
+ /* Push back the "?" and treat it like a normal parens. */
+ yyless(1);
+ else
+ BEGIN(GROUP_WITH_PARAMS);
+ return '(';
+ }
+ YY_BREAK
+case 160:
+YY_RULE_SETUP
+#line 768 "scan.l"
+sf_push(); return '(';
+ YY_BREAK
+case 161:
+YY_RULE_SETUP
+#line 769 "scan.l"
+{
+ if (_sf_top_ix > 0) {
+ sf_pop();
+ return ')';
+ } else
+ synerr(_("unbalanced parenthesis"));
+ }
+ YY_BREAK
+case 162:
+YY_RULE_SETUP
+#line 777 "scan.l"
+return (unsigned char) yytext[0];
+ YY_BREAK
+case 163:
+YY_RULE_SETUP
+#line 778 "scan.l"
+RETURNCHAR;
+ YY_BREAK
+
+
+case 164:
+/* rule 164 can match eol */
+YY_RULE_SETUP
+#line 783 "scan.l"
+++linenum; /* Allow blank lines & continuations */
+ YY_BREAK
+case 165:
+YY_RULE_SETUP
+#line 784 "scan.l"
+return (unsigned char) yytext[0];
+ YY_BREAK
+case 166:
+YY_RULE_SETUP
+#line 785 "scan.l"
+BEGIN(SECT2); return '>';
+ YY_BREAK
+case 167:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 786 "scan.l"
+BEGIN(CARETISBOL); return '>';
+ YY_BREAK
+case 168:
+YY_RULE_SETUP
+#line 787 "scan.l"
+RETURNNAME;
+ YY_BREAK
+case 169:
+YY_RULE_SETUP
+#line 788 "scan.l"
+{
+ format_synerr( _( "bad <start condition>: %s" ),
+ yytext );
+ }
+ YY_BREAK
+
+case 170:
+YY_RULE_SETUP
+#line 794 "scan.l"
+BEGIN(SECT2); return '^';
+ YY_BREAK
+
+case 171:
+YY_RULE_SETUP
+#line 798 "scan.l"
+RETURNCHAR;
+ YY_BREAK
+case 172:
+YY_RULE_SETUP
+#line 799 "scan.l"
+BEGIN(SECT2); return '"';
+ YY_BREAK
+case 173:
+/* rule 173 can match eol */
+YY_RULE_SETUP
+#line 801 "scan.l"
+{
+ synerr( _( "missing quote" ) );
+ BEGIN(SECT2);
+ ++linenum;
+ return '"';
+ }
+ YY_BREAK
+
+
+case 174:
+YY_RULE_SETUP
+#line 810 "scan.l"
+BEGIN(SECT2);
+ YY_BREAK
+case 175:
+YY_RULE_SETUP
+#line 811 "scan.l"
+BEGIN(GROUP_MINUS_PARAMS);
+ YY_BREAK
+case 176:
+YY_RULE_SETUP
+#line 812 "scan.l"
+sf_set_case_ins(1);
+ YY_BREAK
+case 177:
+YY_RULE_SETUP
+#line 813 "scan.l"
+sf_set_dot_all(1);
+ YY_BREAK
+case 178:
+YY_RULE_SETUP
+#line 814 "scan.l"
+sf_set_skip_ws(1);
+ YY_BREAK
+
+
+case 179:
+YY_RULE_SETUP
+#line 817 "scan.l"
+BEGIN(SECT2);
+ YY_BREAK
+case 180:
+YY_RULE_SETUP
+#line 818 "scan.l"
+sf_set_case_ins(0);
+ YY_BREAK
+case 181:
+YY_RULE_SETUP
+#line 819 "scan.l"
+sf_set_dot_all(0);
+ YY_BREAK
+case 182:
+YY_RULE_SETUP
+#line 820 "scan.l"
+sf_set_skip_ws(0);
+ YY_BREAK
+
+
+case 183:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 824 "scan.l"
+BEGIN(CCL); return '^';
+ YY_BREAK
+case 184:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 825 "scan.l"
+return '^';
+ YY_BREAK
+case 185:
+YY_RULE_SETUP
+#line 826 "scan.l"
+BEGIN(CCL); RETURNCHAR;
+ YY_BREAK
+
+
+case 186:
+*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */
+(yy_c_buf_p) = yy_cp = yy_bp + 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 830 "scan.l"
+return '-';
+ YY_BREAK
+case 187:
+YY_RULE_SETUP
+#line 831 "scan.l"
+RETURNCHAR;
+ YY_BREAK
+case 188:
+YY_RULE_SETUP
+#line 832 "scan.l"
+BEGIN(SECT2); return ']';
+ YY_BREAK
+case 189:
+/* rule 189 can match eol */
+YY_RULE_SETUP
+#line 833 "scan.l"
+{
+ synerr( _( "bad character class" ) );
+ BEGIN(SECT2);
+ return ']';
+ }
+ YY_BREAK
+
+
+case 190:
+YY_RULE_SETUP
+#line 841 "scan.l"
+BEGIN(CCL); return CCE_ALNUM;
+ YY_BREAK
+case 191:
+YY_RULE_SETUP
+#line 842 "scan.l"
+BEGIN(CCL); return CCE_ALPHA;
+ YY_BREAK
+case 192:
+YY_RULE_SETUP
+#line 843 "scan.l"
+BEGIN(CCL); return CCE_BLANK;
+ YY_BREAK
+case 193:
+YY_RULE_SETUP
+#line 844 "scan.l"
+BEGIN(CCL); return CCE_CNTRL;
+ YY_BREAK
+case 194:
+YY_RULE_SETUP
+#line 845 "scan.l"
+BEGIN(CCL); return CCE_DIGIT;
+ YY_BREAK
+case 195:
+YY_RULE_SETUP
+#line 846 "scan.l"
+BEGIN(CCL); return CCE_GRAPH;
+ YY_BREAK
+case 196:
+YY_RULE_SETUP
+#line 847 "scan.l"
+BEGIN(CCL); return CCE_LOWER;
+ YY_BREAK
+case 197:
+YY_RULE_SETUP
+#line 848 "scan.l"
+BEGIN(CCL); return CCE_PRINT;
+ YY_BREAK
+case 198:
+YY_RULE_SETUP
+#line 849 "scan.l"
+BEGIN(CCL); return CCE_PUNCT;
+ YY_BREAK
+case 199:
+YY_RULE_SETUP
+#line 850 "scan.l"
+BEGIN(CCL); return CCE_SPACE;
+ YY_BREAK
+case 200:
+YY_RULE_SETUP
+#line 851 "scan.l"
+BEGIN(CCL); return CCE_UPPER;
+ YY_BREAK
+case 201:
+YY_RULE_SETUP
+#line 852 "scan.l"
+BEGIN(CCL); return CCE_XDIGIT;
+ YY_BREAK
+case 202:
+YY_RULE_SETUP
+#line 854 "scan.l"
+BEGIN(CCL); return CCE_NEG_ALNUM;
+ YY_BREAK
+case 203:
+YY_RULE_SETUP
+#line 855 "scan.l"
+BEGIN(CCL); return CCE_NEG_ALPHA;
+ YY_BREAK
+case 204:
+YY_RULE_SETUP
+#line 856 "scan.l"
+BEGIN(CCL); return CCE_NEG_BLANK;
+ YY_BREAK
+case 205:
+YY_RULE_SETUP
+#line 857 "scan.l"
+BEGIN(CCL); return CCE_NEG_CNTRL;
+ YY_BREAK
+case 206:
+YY_RULE_SETUP
+#line 858 "scan.l"
+BEGIN(CCL); return CCE_NEG_DIGIT;
+ YY_BREAK
+case 207:
+YY_RULE_SETUP
+#line 859 "scan.l"
+BEGIN(CCL); return CCE_NEG_GRAPH;
+ YY_BREAK
+case 208:
+YY_RULE_SETUP
+#line 860 "scan.l"
+BEGIN(CCL); return CCE_NEG_LOWER;
+ YY_BREAK
+case 209:
+YY_RULE_SETUP
+#line 861 "scan.l"
+BEGIN(CCL); return CCE_NEG_PRINT;
+ YY_BREAK
+case 210:
+YY_RULE_SETUP
+#line 862 "scan.l"
+BEGIN(CCL); return CCE_NEG_PUNCT;
+ YY_BREAK
+case 211:
+YY_RULE_SETUP
+#line 863 "scan.l"
+BEGIN(CCL); return CCE_NEG_SPACE;
+ YY_BREAK
+case 212:
+YY_RULE_SETUP
+#line 864 "scan.l"
+BEGIN(CCL); return CCE_NEG_UPPER;
+ YY_BREAK
+case 213:
+YY_RULE_SETUP
+#line 865 "scan.l"
+BEGIN(CCL); return CCE_NEG_XDIGIT;
+ YY_BREAK
+case 214:
+YY_RULE_SETUP
+#line 866 "scan.l"
+{
+ format_synerr(
+ _( "bad character class expression: %s" ),
+ yytext );
+ BEGIN(CCL); return CCE_ALNUM;
+ }
+ YY_BREAK
+
+
+case 215:
+YY_RULE_SETUP
+#line 875 "scan.l"
+{
+ yylval = myctoi( yytext );
+ return NUMBER;
+ }
+ YY_BREAK
+case 216:
+YY_RULE_SETUP
+#line 880 "scan.l"
+return ',';
+ YY_BREAK
+case 217:
+YY_RULE_SETUP
+#line 881 "scan.l"
+{
+ BEGIN(SECT2);
+ if ( lex_compat || posix_compat )
+ return END_REPEAT_POSIX;
+ else
+ return END_REPEAT_FLEX;
+ }
+ YY_BREAK
+case 218:
+YY_RULE_SETUP
+#line 889 "scan.l"
+{
+ synerr( _( "bad character inside {}'s" ) );
+ BEGIN(SECT2);
+ return '}';
+ }
+ YY_BREAK
+case 219:
+/* rule 219 can match eol */
+YY_RULE_SETUP
+#line 895 "scan.l"
+{
+ synerr( _( "missing }" ) );
+ BEGIN(SECT2);
+ ++linenum;
+ return '}';
+ }
+ YY_BREAK
+
+
+case 220:
+YY_RULE_SETUP
+#line 905 "scan.l"
+bracelevel = 0;
+ YY_BREAK
+case 221:
+YY_RULE_SETUP
+#line 907 "scan.l"
+ACTION_ECHO; yy_push_state( CODE_COMMENT );
+ YY_BREAK
+
+case 222:
+YY_RULE_SETUP
+#line 910 "scan.l"
+{
+ ACTION_ECHO;
+ CHECK_REJECT(yytext);
+ }
+ YY_BREAK
+case 223:
+YY_RULE_SETUP
+#line 914 "scan.l"
+{
+ ACTION_ECHO;
+ CHECK_YYMORE(yytext);
+ }
+ YY_BREAK
+
+case 224:
+YY_RULE_SETUP
+#line 920 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 225:
+/* rule 225 can match eol */
+YY_RULE_SETUP
+#line 921 "scan.l"
+{
+ ++linenum;
+ ACTION_ECHO;
+ if (bracelevel <= 0 || (doing_codeblock && indented_code)) {
+ if ( doing_rule_action )
+ add_action( "\tYY_BREAK]""]\n" );
+
+ doing_rule_action = doing_codeblock = false;
+ BEGIN(SECT2);
+ }
+ }
+ YY_BREAK
+
+/* Reject and YYmore() are checked for above, in PERCENT_BRACE_ACTION */
+
+case 226:
+YY_RULE_SETUP
+#line 937 "scan.l"
+ACTION_ECHO; ++bracelevel;
+ YY_BREAK
+case 227:
+YY_RULE_SETUP
+#line 938 "scan.l"
+ACTION_ECHO; --bracelevel;
+ YY_BREAK
+case 228:
+YY_RULE_SETUP
+#line 939 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 229:
+YY_RULE_SETUP
+#line 940 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 230:
+YY_RULE_SETUP
+#line 941 "scan.l"
+ACTION_ECHO; /* character constant */
+ YY_BREAK
+case 231:
+YY_RULE_SETUP
+#line 942 "scan.l"
+ACTION_ECHO; BEGIN(CHARACTER_CONSTANT);
+ YY_BREAK
+case 232:
+YY_RULE_SETUP
+#line 943 "scan.l"
+ACTION_ECHO; BEGIN(ACTION_STRING);
+ YY_BREAK
+case 233:
+/* rule 233 can match eol */
+YY_RULE_SETUP
+#line 944 "scan.l"
+{
+ ++linenum;
+ ACTION_ECHO;
+ if (bracelevel <= 0) {
+ if ( doing_rule_action )
+ add_action( "\tYY_BREAK]""]\n" );
+
+ doing_rule_action = false;
+ BEGIN(SECT2);
+ }
+ }
+ YY_BREAK
+case 234:
+YY_RULE_SETUP
+#line 955 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+
+
+case 235:
+YY_RULE_SETUP
+#line 959 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 236:
+YY_RULE_SETUP
+#line 960 "scan.l"
+ACTION_ECHO; BEGIN(ACTION);
+ YY_BREAK
+
+
+case 237:
+YY_RULE_SETUP
+#line 963 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 238:
+YY_RULE_SETUP
+#line 964 "scan.l"
+ACTION_ECHO; BEGIN(ACTION);
+ YY_BREAK
+
+
+case 239:
+/* rule 239 can match eol */
+YY_RULE_SETUP
+#line 967 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 240:
+/* rule 240 can match eol */
+YY_RULE_SETUP
+#line 968 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+case 241:
+/* rule 241 can match eol */
+YY_RULE_SETUP
+#line 969 "scan.l"
+++linenum; ACTION_ECHO; if (bracelevel <= 0) { BEGIN(SECT2); } else { BEGIN(ACTION); }
+ YY_BREAK
+case 242:
+YY_RULE_SETUP
+#line 970 "scan.l"
+ACTION_ECHO;
+ YY_BREAK
+
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(CODE_COMMENT):
+case YY_STATE_EOF(COMMENT_DISCARD):
+case YY_STATE_EOF(ACTION):
+case YY_STATE_EOF(ACTION_STRING):
+case YY_STATE_EOF(CHARACTER_CONSTANT):
+#line 973 "scan.l"
+{
+ synerr( _( "EOF encountered inside an action" ) );
+ yyterminate();
+ }
+ YY_BREAK
+case YY_STATE_EOF(EXTENDED_COMMENT):
+case YY_STATE_EOF(GROUP_WITH_PARAMS):
+case YY_STATE_EOF(GROUP_MINUS_PARAMS):
+#line 978 "scan.l"
+{
+ synerr( _( "EOF encountered inside pattern" ) );
+ yyterminate();
+ }
+ YY_BREAK
+case 243:
+YY_RULE_SETUP
+#line 983 "scan.l"
+{
+ yylval = myesc( (unsigned char *) yytext );
+
+ if ( YY_START == FIRSTCCL )
+ BEGIN(CCL);
+
+ return CHAR;
+ }
+ YY_BREAK
+
+case 244:
+YY_RULE_SETUP
+#line 993 "scan.l"
+fputs(escaped_qstart, yyout);
+ YY_BREAK
+case 245:
+YY_RULE_SETUP
+#line 994 "scan.l"
+fputs(escaped_qend, yyout);
+ YY_BREAK
+case 246:
+/* rule 246 can match eol */
+YY_RULE_SETUP
+#line 995 "scan.l"
+ECHO;
+ YY_BREAK
+case 247:
+YY_RULE_SETUP
+#line 996 "scan.l"
+ECHO;
+ YY_BREAK
+case YY_STATE_EOF(SECT3):
+#line 997 "scan.l"
+{
+ sectnum = 0;
+ yyterminate();
+ }
+ YY_BREAK
+
+
+case 248:
+YY_RULE_SETUP
+#line 1003 "scan.l"
+fprintf(yyout, "[""[%s]""]", escaped_qstart);
+ YY_BREAK
+case 249:
+YY_RULE_SETUP
+#line 1004 "scan.l"
+fprintf(yyout, "[""[%s]""]", escaped_qend);
+ YY_BREAK
+case 250:
+/* rule 250 can match eol */
+YY_RULE_SETUP
+#line 1005 "scan.l"
+ECHO;
+ YY_BREAK
+case 251:
+YY_RULE_SETUP
+#line 1006 "scan.l"
+ECHO;
+ YY_BREAK
+case YY_STATE_EOF(SECT3_NOESCAPE):
+#line 1007 "scan.l"
+{
+ sectnum = 0;
+ yyterminate();
+ }
+ YY_BREAK
+
+case 252:
+/* rule 252 can match eol */
+YY_RULE_SETUP
+#line 1012 "scan.l"
+format_synerr( _( "bad character: %s" ), yytext );
+ YY_BREAK
+case 253:
+YY_RULE_SETUP
+#line 1014 "scan.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+#line 4137 "<stdout>"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(SECT2):
+case YY_STATE_EOF(CODEBLOCK):
+case YY_STATE_EOF(PICKUPDEF):
+case YY_STATE_EOF(SC):
+case YY_STATE_EOF(CARETISBOL):
+case YY_STATE_EOF(NUM):
+case YY_STATE_EOF(QUOTE):
+case YY_STATE_EOF(FIRSTCCL):
+case YY_STATE_EOF(CCL):
+case YY_STATE_EOF(RECOVER):
+case YY_STATE_EOF(PERCENT_BRACE_ACTION):
+case YY_STATE_EOF(OPTION):
+case YY_STATE_EOF(LINEDIR):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = NULL;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1114 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
+
+ YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1114 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 1113);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+ static void yyunput (int c, char * yy_bp )
+{
+ char *yy_cp;
+
+ yy_cp = (yy_c_buf_p);
+
+ /* undo effects of setting up yytext */
+ *yy_cp = (yy_hold_char);
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ int number_to_move = (yy_n_chars) + 2;
+ char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ (yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ (yytext_ptr) = yy_bp;
+ (yy_hold_char) = *yy_cp;
+ (yy_c_buf_p) = yy_cp;
+}
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+#ifdef YY_FLEX_LEX_COMPAT
+ return 0;
+#else
+ return EOF;
+#endif
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree( (void *) b->yy_ch_buf );
+
+ yyfree( (void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ yy_size_t num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return NULL;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = NULL;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (const char * yystr )
+{
+
+ return yy_scan_bytes( yystr, (int) strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+ static void yy_push_state (int _new_state )
+{
+ if ( (yy_start_stack_ptr) >= (yy_start_stack_depth) )
+ {
+ yy_size_t new_size;
+
+ (yy_start_stack_depth) += YY_START_STACK_INCR;
+ new_size = (yy_size_t) (yy_start_stack_depth) * sizeof( int );
+
+ if ( ! (yy_start_stack) )
+ (yy_start_stack) = (int *) yyalloc( new_size );
+
+ else
+ (yy_start_stack) = (int *) yyrealloc(
+ (void *) (yy_start_stack), new_size );
+
+ if ( ! (yy_start_stack) )
+ YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+ }
+
+ (yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;
+
+ BEGIN(_new_state);
+}
+
+ static void yy_pop_state (void)
+{
+ if ( --(yy_start_stack_ptr) < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN((yy_start_stack)[(yy_start_stack_ptr)]);
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (const char* msg )
+{
+ fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ *
+ */
+void yyset_lineno (int _line_number )
+{
+
+ yylineno = _line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * _in_str )
+{
+ yyin = _in_str ;
+}
+
+void yyset_out (FILE * _out_str )
+{
+ yyout = _out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int _bdebug )
+{
+ yy_flex_debug = _bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = NULL;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = NULL;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+ (yy_start_stack_ptr) = 0;
+ (yy_start_stack_depth) = 0;
+ (yy_start_stack) = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = NULL;
+ yyout = NULL;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree( (yy_start_stack) );
+ (yy_start_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, const char * s2, int n )
+{
+
+ int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s )
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return malloc(size);
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return realloc(ptr, size);
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 1014 "scan.l"
+
+
+
+int yywrap(void)
+ {
+ if ( --num_input_files > 0 )
+ {
+ set_input_file( *++input_files );
+ return 0;
+ }
+
+ else
+ return 1;
+ }
+
+
+/* set_input_file - open the given file (if NULL, stdin) for scanning */
+
+void set_input_file( char *file )
+ {
+ if ( file && strcmp( file, "-" ) )
+ {
+ infilename = xstrdup(file);
+ yyin = fopen( infilename, "r" );
+
+ if ( yyin == NULL )
+ lerr( _( "can't open %s" ), file );
+ }
+
+ else
+ {
+ yyin = stdin;
+ infilename = xstrdup("<stdin>");
+ }
+
+ linenum = 1;
+ }
+
diff --git a/usr.bin/lex/initskel.c b/usr.bin/lex/initskel.c
new file mode 100644
index 000000000000..746ad6405c2a
--- /dev/null
+++ b/usr.bin/lex/initskel.c
@@ -0,0 +1,4080 @@
+/* File created from flex.skl via mkskel.sh */
+
+#include "flexdef.h"
+
+const char *skel[] = {
+ "/* A lexical scanner generated by flex */",
+ "",
+ "",
+ "",
+ "m4_changecom",
+ "m4_changequote",
+ "m4_changequote([[, ]])",
+ "",
+ "",
+ "%not-for-header",
+ "%if-c-only",
+ "%if-not-reentrant",
+ "m4_ifelse(M4_YY_PREFIX,yy,,",
+ "#define yy_create_buffer M4_YY_PREFIX[[_create_buffer]]",
+ "#define yy_delete_buffer M4_YY_PREFIX[[_delete_buffer]]",
+ "#define yy_scan_buffer M4_YY_PREFIX[[_scan_buffer]]",
+ "#define yy_scan_string M4_YY_PREFIX[[_scan_string]]",
+ "#define yy_scan_bytes M4_YY_PREFIX[[_scan_bytes]]",
+ "#define yy_init_buffer M4_YY_PREFIX[[_init_buffer]]",
+ "#define yy_flush_buffer M4_YY_PREFIX[[_flush_buffer]]",
+ "#define yy_load_buffer_state M4_YY_PREFIX[[_load_buffer_state]]",
+ "#define yy_switch_to_buffer M4_YY_PREFIX[[_switch_to_buffer]]",
+ "#define yypush_buffer_state M4_YY_PREFIX[[push_buffer_state]]",
+ "#define yypop_buffer_state M4_YY_PREFIX[[pop_buffer_state]]",
+ "#define yyensure_buffer_stack M4_YY_PREFIX[[ensure_buffer_stack]]",
+ "#define yy_flex_debug M4_YY_PREFIX[[_flex_debug]]",
+ "#define yyin M4_YY_PREFIX[[in]]",
+ "#define yyleng M4_YY_PREFIX[[leng]]",
+ "#define yylex M4_YY_PREFIX[[lex]]",
+ "#define yylineno M4_YY_PREFIX[[lineno]]",
+ "#define yyout M4_YY_PREFIX[[out]]",
+ "#define yyrestart M4_YY_PREFIX[[restart]]",
+ "#define yytext M4_YY_PREFIX[[text]]",
+ "#define yywrap M4_YY_PREFIX[[wrap]]",
+ "#define yyalloc M4_YY_PREFIX[[alloc]]",
+ "#define yyrealloc M4_YY_PREFIX[[realloc]]",
+ "#define yyfree M4_YY_PREFIX[[free]]",
+ ")",
+ "%endif",
+ "%endif",
+ "%ok-for-header",
+ "",
+ "#define FLEX_SCANNER",
+ "#define YY_FLEX_MAJOR_VERSION 2",
+ "#define YY_FLEX_MINOR_VERSION 6",
+ "#define YY_FLEX_SUBMINOR_VERSION 4",
+ "#if YY_FLEX_SUBMINOR_VERSION > 0",
+ "#define FLEX_BETA",
+ "#endif",
+ "",
+ "m4_ifdef( [[M4_YY_IN_HEADER]], , [[m4_define([[M4_YY_NOT_IN_HEADER]], [[]])]])",
+ "m4_ifdef( [[M4_YY_REENTRANT]], , [[m4_define([[M4_YY_NOT_REENTRANT]], [[]])]])",
+ "",
+ "m4_ifdef( [[M4_YY_STACK_USED]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]])",
+ "m4_ifdef( [[M4_YY_REENTRANT]], [[m4_define([[M4_YY_HAS_START_STACK_VARS]])]])",
+ "",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_PREFIX]],, [[m4_define([[M4_YY_PREFIX]], [[yy]])]])",
+ "",
+ "",
+ "",
+ "%if-c++-only",
+ " /* The c++ scanner is a mess. The FlexLexer.h header file relies on the",
+ " * following macro. This is required in order to pass the c++-multiple-scanners",
+ " * test in the regression suite. We get reports that it breaks inheritance.",
+ " * We will address this in a future release of flex, or omit the C++ scanner",
+ " * altogether.",
+ " */",
+ " #define yyFlexLexer M4_YY_PREFIX[[FlexLexer]]",
+ "%endif",
+ "",
+ "%if-c-only",
+ "m4_ifelse(M4_YY_PREFIX,yy,,",
+ " ",
+ "[[#ifdef yy_create_buffer",
+ "#define ]]M4_YY_PREFIX[[_create_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_create_buffer ]]M4_YY_PREFIX[[_create_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_delete_buffer",
+ "#define ]]M4_YY_PREFIX[[_delete_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_delete_buffer ]]M4_YY_PREFIX[[_delete_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_scan_buffer",
+ "#define ]]M4_YY_PREFIX[[_scan_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_scan_buffer ]]M4_YY_PREFIX[[_scan_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_scan_string",
+ "#define ]]M4_YY_PREFIX[[_scan_string_ALREADY_DEFINED",
+ "#else",
+ "#define yy_scan_string ]]M4_YY_PREFIX[[_scan_string",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_scan_bytes",
+ "#define ]]M4_YY_PREFIX[[_scan_bytes_ALREADY_DEFINED",
+ "#else",
+ "#define yy_scan_bytes ]]M4_YY_PREFIX[[_scan_bytes",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_init_buffer",
+ "#define ]]M4_YY_PREFIX[[_init_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_init_buffer ]]M4_YY_PREFIX[[_init_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_flush_buffer",
+ "#define ]]M4_YY_PREFIX[[_flush_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_flush_buffer ]]M4_YY_PREFIX[[_flush_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_load_buffer_state",
+ "#define ]]M4_YY_PREFIX[[_load_buffer_state_ALREADY_DEFINED",
+ "#else",
+ "#define yy_load_buffer_state ]]M4_YY_PREFIX[[_load_buffer_state",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_switch_to_buffer",
+ "#define ]]M4_YY_PREFIX[[_switch_to_buffer_ALREADY_DEFINED",
+ "#else",
+ "#define yy_switch_to_buffer ]]M4_YY_PREFIX[[_switch_to_buffer",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yypush_buffer_state",
+ "#define ]]M4_YY_PREFIX[[push_buffer_state_ALREADY_DEFINED",
+ "#else",
+ "#define yypush_buffer_state ]]M4_YY_PREFIX[[push_buffer_state",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yypop_buffer_state",
+ "#define ]]M4_YY_PREFIX[[pop_buffer_state_ALREADY_DEFINED",
+ "#else",
+ "#define yypop_buffer_state ]]M4_YY_PREFIX[[pop_buffer_state",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyensure_buffer_stack",
+ "#define ]]M4_YY_PREFIX[[ensure_buffer_stack_ALREADY_DEFINED",
+ "#else",
+ "#define yyensure_buffer_stack ]]M4_YY_PREFIX[[ensure_buffer_stack",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yylex",
+ "#define ]]M4_YY_PREFIX[[lex_ALREADY_DEFINED",
+ "#else",
+ "#define yylex ]]M4_YY_PREFIX[[lex",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyrestart",
+ "#define ]]M4_YY_PREFIX[[restart_ALREADY_DEFINED",
+ "#else",
+ "#define yyrestart ]]M4_YY_PREFIX[[restart",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yylex_init",
+ "#define ]]M4_YY_PREFIX[[lex_init_ALREADY_DEFINED",
+ "#else",
+ "#define yylex_init ]]M4_YY_PREFIX[[lex_init",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yylex_init_extra",
+ "#define ]]M4_YY_PREFIX[[lex_init_extra_ALREADY_DEFINED",
+ "#else",
+ "#define yylex_init_extra ]]M4_YY_PREFIX[[lex_init_extra",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yylex_destroy",
+ "#define ]]M4_YY_PREFIX[[lex_destroy_ALREADY_DEFINED",
+ "#else",
+ "#define yylex_destroy ]]M4_YY_PREFIX[[lex_destroy",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_debug",
+ "#define ]]M4_YY_PREFIX[[get_debug_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_debug ]]M4_YY_PREFIX[[get_debug",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_debug",
+ "#define ]]M4_YY_PREFIX[[set_debug_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_debug ]]M4_YY_PREFIX[[set_debug",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_extra",
+ "#define ]]M4_YY_PREFIX[[get_extra_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_extra ]]M4_YY_PREFIX[[get_extra",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_extra",
+ "#define ]]M4_YY_PREFIX[[set_extra_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_extra ]]M4_YY_PREFIX[[set_extra",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_in",
+ "#define ]]M4_YY_PREFIX[[get_in_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_in ]]M4_YY_PREFIX[[get_in",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_in",
+ "#define ]]M4_YY_PREFIX[[set_in_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_in ]]M4_YY_PREFIX[[set_in",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_out",
+ "#define ]]M4_YY_PREFIX[[get_out_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_out ]]M4_YY_PREFIX[[get_out",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_out",
+ "#define ]]M4_YY_PREFIX[[set_out_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_out ]]M4_YY_PREFIX[[set_out",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_leng",
+ "#define ]]M4_YY_PREFIX[[get_leng_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_leng ]]M4_YY_PREFIX[[get_leng",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_text",
+ "#define ]]M4_YY_PREFIX[[get_text_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_text ]]M4_YY_PREFIX[[get_text",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyget_lineno",
+ "#define ]]M4_YY_PREFIX[[get_lineno_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_lineno ]]M4_YY_PREFIX[[get_lineno",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_lineno",
+ "#define ]]M4_YY_PREFIX[[set_lineno_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_lineno ]]M4_YY_PREFIX[[set_lineno",
+ "#endif]]",
+ "",
+ " m4_ifdef( [[M4_YY_REENTRANT]],",
+ " [[",
+ " ",
+ "[[#ifdef yyget_column",
+ "#define ]]M4_YY_PREFIX[[get_column_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_column ]]M4_YY_PREFIX[[get_column",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_column",
+ "#define ]]M4_YY_PREFIX[[set_column_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_column ]]M4_YY_PREFIX[[set_column",
+ "#endif]]",
+ "",
+ " ]])",
+ " ",
+ "[[#ifdef yywrap",
+ "#define ]]M4_YY_PREFIX[[wrap_ALREADY_DEFINED",
+ "#else",
+ "#define yywrap ]]M4_YY_PREFIX[[wrap",
+ "#endif]]",
+ "",
+ ")",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ "[[",
+ " ",
+ "[[#ifdef yyget_lval",
+ "#define ]]M4_YY_PREFIX[[get_lval_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_lval ]]M4_YY_PREFIX[[get_lval",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_lval",
+ "#define ]]M4_YY_PREFIX[[set_lval_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_lval ]]M4_YY_PREFIX[[set_lval",
+ "#endif]]",
+ "",
+ "]])",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " ",
+ "[[#ifdef yyget_lloc",
+ "#define ]]M4_YY_PREFIX[[get_lloc_ALREADY_DEFINED",
+ "#else",
+ "#define yyget_lloc ]]M4_YY_PREFIX[[get_lloc",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyset_lloc",
+ "#define ]]M4_YY_PREFIX[[set_lloc_ALREADY_DEFINED",
+ "#else",
+ "#define yyset_lloc ]]M4_YY_PREFIX[[set_lloc",
+ "#endif]]",
+ "",
+ "]])",
+ "",
+ "",
+ "m4_ifelse(M4_YY_PREFIX,yy,,",
+ " ",
+ "[[#ifdef yyalloc",
+ "#define ]]M4_YY_PREFIX[[alloc_ALREADY_DEFINED",
+ "#else",
+ "#define yyalloc ]]M4_YY_PREFIX[[alloc",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyrealloc",
+ "#define ]]M4_YY_PREFIX[[realloc_ALREADY_DEFINED",
+ "#else",
+ "#define yyrealloc ]]M4_YY_PREFIX[[realloc",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyfree",
+ "#define ]]M4_YY_PREFIX[[free_ALREADY_DEFINED",
+ "#else",
+ "#define yyfree ]]M4_YY_PREFIX[[free",
+ "#endif]]",
+ "",
+ ")",
+ "",
+ "%if-c-only",
+ "m4_ifelse(M4_YY_PREFIX,yy,,",
+ "m4_ifdef( [[M4_YY_NOT_REENTRANT]],",
+ "[[",
+ " ",
+ "[[#ifdef yytext",
+ "#define ]]M4_YY_PREFIX[[text_ALREADY_DEFINED",
+ "#else",
+ "#define yytext ]]M4_YY_PREFIX[[text",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyleng",
+ "#define ]]M4_YY_PREFIX[[leng_ALREADY_DEFINED",
+ "#else",
+ "#define yyleng ]]M4_YY_PREFIX[[leng",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyin",
+ "#define ]]M4_YY_PREFIX[[in_ALREADY_DEFINED",
+ "#else",
+ "#define yyin ]]M4_YY_PREFIX[[in",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyout",
+ "#define ]]M4_YY_PREFIX[[out_ALREADY_DEFINED",
+ "#else",
+ "#define yyout ]]M4_YY_PREFIX[[out",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yy_flex_debug",
+ "#define ]]M4_YY_PREFIX[[_flex_debug_ALREADY_DEFINED",
+ "#else",
+ "#define yy_flex_debug ]]M4_YY_PREFIX[[_flex_debug",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yylineno",
+ "#define ]]M4_YY_PREFIX[[lineno_ALREADY_DEFINED",
+ "#else",
+ "#define yylineno ]]M4_YY_PREFIX[[lineno",
+ "#endif]]",
+ "",
+ "]])",
+ ")",
+ "%endif",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_TABLES_EXTERNAL]],",
+ "[[",
+ " ",
+ "[[#ifdef yytables_fload",
+ "#define ]]M4_YY_PREFIX[[tables_fload_ALREADY_DEFINED",
+ "#else",
+ "#define yytables_fload ]]M4_YY_PREFIX[[tables_fload",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yytables_destroy",
+ "#define ]]M4_YY_PREFIX[[tables_destroy_ALREADY_DEFINED",
+ "#else",
+ "#define yytables_destroy ]]M4_YY_PREFIX[[tables_destroy",
+ "#endif]]",
+ "",
+ " ",
+ "[[#ifdef yyTABLES_NAME",
+ "#define ]]M4_YY_PREFIX[[TABLES_NAME_ALREADY_DEFINED",
+ "#else",
+ "#define yyTABLES_NAME ]]M4_YY_PREFIX[[TABLES_NAME",
+ "#endif]]",
+ "",
+ "]])",
+ "",
+ "/* First, we deal with platform-specific or compiler-specific issues. */",
+ "",
+ "/* begin standard C headers. */",
+ "%if-c-only",
+ "#include <stdio.h>",
+ "#include <string.h>",
+ "#include <errno.h>",
+ "#include <stdlib.h>",
+ "%endif",
+ "",
+ "%if-tables-serialization",
+ "#include <sys/types.h>",
+ "#include <netinet/in.h>",
+ "%endif",
+ "/* end standard C headers. */",
+ "",
+ "%if-c-or-c++",
+ "/* flex integer type definitions */",
+ "",
+ "#ifndef FLEXINT_H",
+ "#define FLEXINT_H",
+ "",
+ "/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */",
+ "",
+ "#if defined(__FreeBSD__) || \\",
+ " (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)",
+ "",
+ "/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,",
+ " * if you want the limit (max/min) macros for int types. ",
+ " */",
+ "#ifndef __STDC_LIMIT_MACROS",
+ "#define __STDC_LIMIT_MACROS 1",
+ "#endif",
+ "",
+ "#include <inttypes.h>",
+ "typedef int8_t flex_int8_t;",
+ "typedef uint8_t flex_uint8_t;",
+ "typedef int16_t flex_int16_t;",
+ "typedef uint16_t flex_uint16_t;",
+ "typedef int32_t flex_int32_t;",
+ "typedef uint32_t flex_uint32_t;",
+ "#else",
+ "typedef signed char flex_int8_t;",
+ "typedef short int flex_int16_t;",
+ "typedef int flex_int32_t;",
+ "typedef unsigned char flex_uint8_t; ",
+ "typedef unsigned short int flex_uint16_t;",
+ "typedef unsigned int flex_uint32_t;",
+ "",
+ "/* Limits of integral types. */",
+ "#ifndef INT8_MIN",
+ "#define INT8_MIN (-128)",
+ "#endif",
+ "#ifndef INT16_MIN",
+ "#define INT16_MIN (-32767-1)",
+ "#endif",
+ "#ifndef INT32_MIN",
+ "#define INT32_MIN (-2147483647-1)",
+ "#endif",
+ "#ifndef INT8_MAX",
+ "#define INT8_MAX (127)",
+ "#endif",
+ "#ifndef INT16_MAX",
+ "#define INT16_MAX (32767)",
+ "#endif",
+ "#ifndef INT32_MAX",
+ "#define INT32_MAX (2147483647)",
+ "#endif",
+ "#ifndef UINT8_MAX",
+ "#define UINT8_MAX (255U)",
+ "#endif",
+ "#ifndef UINT16_MAX",
+ "#define UINT16_MAX (65535U)",
+ "#endif",
+ "#ifndef UINT32_MAX",
+ "#define UINT32_MAX (4294967295U)",
+ "#endif",
+ "",
+ "#ifndef SIZE_MAX",
+ "#define SIZE_MAX (~(size_t)0)",
+ "#endif",
+ "",
+ "#endif /* ! C99 */",
+ "",
+ "#endif /* ! FLEXINT_H */",
+ "",
+ "%endif",
+ "",
+ "/* begin standard C++ headers. */",
+ "%if-c++-only",
+ "#include <iostream>",
+ "#include <errno.h>",
+ "#include <cstdlib>",
+ "#include <cstdio>",
+ "#include <cstring>",
+ "/* end standard C++ headers. */",
+ "%endif",
+ "",
+ "/* TODO: this is always defined, so inline it */",
+ "#define yyconst const",
+ "",
+ "#if defined(__GNUC__) && __GNUC__ >= 3",
+ "#define yynoreturn __attribute__((__noreturn__))",
+ "#else",
+ "#define yynoreturn",
+ "#endif",
+ "",
+ "%not-for-header",
+ "/* Returned upon end-of-file. */",
+ "#define YY_NULL 0",
+ "%ok-for-header",
+ "",
+ "%not-for-header",
+ "/* Promotes a possibly negative, possibly signed char to an",
+ " * integer in range [0..255] for use as an array index.",
+ " */",
+ "#define YY_SC_TO_UI(c) ((YY_CHAR) (c))",
+ "%ok-for-header",
+ "",
+ "",
+ "",
+ "%if-reentrant",
+ "",
+ "/* An opaque pointer. */",
+ "#ifndef YY_TYPEDEF_YY_SCANNER_T",
+ "#define YY_TYPEDEF_YY_SCANNER_T",
+ "typedef void* yyscan_t;",
+ "#endif",
+ "",
+ "m4_define( [[M4_YY_DECL_GUTS_VAR]], [[struct yyguts_t * yyg = (struct yyguts_t*)yyscanner]])",
+ "m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[(void)yyg]])",
+ "m4_define( [[YY_G]], [[yyg->$1]])",
+ "",
+ "m4_define( [[M4_YY_PROTO_LAST_ARG]], [[, yyscan_t yyscanner]])",
+ "m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[yyscan_t yyscanner]])",
+ "",
+ "m4_define( [[M4_YY_DEF_LAST_ARG]], [[, yyscan_t yyscanner]])",
+ "m4_define( [[M4_YY_DEF_ONLY_ARG]], [[yyscan_t yyscanner]])",
+ "m4_define( [[M4_YY_DECL_LAST_ARG]], [[yyscan_t yyscanner;]])",
+ "",
+ "m4_define( [[M4_YY_CALL_LAST_ARG]], [[, yyscanner]])",
+ "m4_define( [[M4_YY_CALL_ONLY_ARG]], [[yyscanner]])",
+ "",
+ "m4_define( [[M4_YY_DOC_PARAM]], [[@param yyscanner The scanner object.]])",
+ "",
+ "/* For convenience, these vars (plus the bison vars far below)",
+ " are macros in the reentrant scanner. */",
+ "#define yyin YY_G(yyin_r)",
+ "#define yyout YY_G(yyout_r)",
+ "#define yyextra YY_G(yyextra_r)",
+ "#define yyleng YY_G(yyleng_r)",
+ "#define yytext YY_G(yytext_r)",
+ "#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)",
+ "#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)",
+ "#define yy_flex_debug YY_G(yy_flex_debug_r)",
+ "",
+ "m4_define( [[M4_YY_INCR_LINENO]],",
+ "[[",
+ " do{ yylineno++;",
+ " yycolumn=0;",
+ " }while(0)",
+ "]])",
+ "",
+ "%endif",
+ "",
+ "",
+ "",
+ "%if-not-reentrant",
+ "",
+ "m4_define( [[M4_YY_INCR_LINENO]],",
+ "[[",
+ " yylineno++;",
+ "]])",
+ "",
+ "m4_define( [[M4_YY_DECL_GUTS_VAR]], [[m4_dnl]])",
+ "m4_define( [[M4_YY_NOOP_GUTS_VAR]], [[m4_dnl]])",
+ "m4_define( [[YY_G]], [[($1)]])",
+ "m4_define( [[M4_YY_PROTO_LAST_ARG]])",
+ "m4_define( [[M4_YY_PROTO_ONLY_ARG]], [[void]])",
+ "m4_define( [[M4_YY_DEF_LAST_ARG]])",
+ "",
+ "m4_define( [[M4_YY_DEF_ONLY_ARG]], [[void]])",
+ "m4_define([[M4_YY_DECL_LAST_ARG]])",
+ "m4_define([[M4_YY_CALL_LAST_ARG]])",
+ "m4_define([[M4_YY_CALL_ONLY_ARG]])",
+ "m4_define( [[M4_YY_DOC_PARAM]], )",
+ "",
+ "%endif",
+ "",
+ "",
+ "m4_define( [[YYFARGS1]], [[($1 $2 M4_YY_DEF_LAST_ARG)]])",
+ "m4_define( [[YYFARGS2]], [[($1 $2, $3 $4 M4_YY_DEF_LAST_ARG)]])",
+ "m4_define( [[YYFARGS3]], [[($1 $2, $3 $4, $5 $6 M4_YY_DEF_LAST_ARG)]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Enter a start condition. This macro really ought to take a parameter,",
+ " * but we do it the disgusting crufty way forced on us by the ()-less",
+ " * definition of BEGIN.",
+ " */",
+ "#define BEGIN YY_G(yy_start) = 1 + 2 *",
+ "/* Translate the current start state into a value that can be later handed",
+ " * to BEGIN to return to the state. The YYSTATE alias is for lex",
+ " * compatibility.",
+ " */",
+ "#define YY_START ((YY_G(yy_start) - 1) / 2)",
+ "#define YYSTATE YY_START",
+ "/* Action number for EOF rule of a given start state. */",
+ "#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)",
+ "/* Special action meaning \"start processing a new file\". */",
+ "#define YY_NEW_FILE yyrestart( yyin M4_YY_CALL_LAST_ARG )",
+ "#define YY_END_OF_BUFFER_CHAR 0",
+ "]])",
+ "",
+ "/* Size of default input buffer. */",
+ "#ifndef YY_BUF_SIZE",
+ "#ifdef __ia64__",
+ "/* On IA-64, the buffer size is 16k, not 8k.",
+ " * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.",
+ " * Ditto for the __ia64__ case accordingly.",
+ " */",
+ "#define YY_BUF_SIZE 32768",
+ "#else",
+ "#define YY_BUF_SIZE 16384",
+ "#endif /* __ia64__ */",
+ "#endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* The state buf must be large enough to hold one state per character in the main buffer.",
+ " */",
+ "#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))",
+ "]])",
+ "",
+ "",
+ "#ifndef YY_TYPEDEF_YY_BUFFER_STATE",
+ "#define YY_TYPEDEF_YY_BUFFER_STATE",
+ "typedef struct yy_buffer_state *YY_BUFFER_STATE;",
+ "#endif",
+ "",
+ "#ifndef YY_TYPEDEF_YY_SIZE_T",
+ "#define YY_TYPEDEF_YY_SIZE_T",
+ "typedef size_t yy_size_t;",
+ "#endif",
+ "",
+ "%if-not-reentrant",
+ "extern int yyleng;",
+ "%endif",
+ "",
+ "%if-c-only",
+ "%if-not-reentrant",
+ "extern FILE *yyin, *yyout;",
+ "%endif",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "#define EOB_ACT_CONTINUE_SCAN 0",
+ "#define EOB_ACT_END_OF_FILE 1",
+ "#define EOB_ACT_LAST_MATCH 2",
+ " m4_ifdef( [[M4_YY_USE_LINENO]],",
+ " [[",
+ " /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires",
+ " * access to the local variable yy_act. Since yyless() is a macro, it would break",
+ " * existing scanners that call yyless() from OUTSIDE yylex.",
+ " * One obvious solution it to make yy_act a global. I tried that, and saw",
+ " * a 5% performance hit in a non-yylineno scanner, because yy_act is",
+ " * normally declared as a register variable-- so it is not worth it.",
+ " */",
+ " #define YY_LESS_LINENO(n) \\",
+ " do { \\",
+ " int yyl;\\",
+ " for ( yyl = n; yyl < yyleng; ++yyl )\\",
+ " if ( yytext[yyl] == '\\n' )\\",
+ " --yylineno;\\",
+ " }while(0)",
+ " #define YY_LINENO_REWIND_TO(dst) \\",
+ " do {\\",
+ " const char *p;\\",
+ " for ( p = yy_cp-1; p >= (dst); --p)\\",
+ " if ( *p == '\\n' )\\",
+ " --yylineno;\\",
+ " }while(0)",
+ " ]],",
+ " [[",
+ " #define YY_LESS_LINENO(n)",
+ " #define YY_LINENO_REWIND_TO(ptr)",
+ " ]])",
+ "/* Return all but the first \"n\" matched characters back to the input stream. */",
+ "#define yyless(n) \\",
+ " do \\",
+ " { \\",
+ " /* Undo effects of setting up yytext. */ \\",
+ " int yyless_macro_arg = (n); \\",
+ " YY_LESS_LINENO(yyless_macro_arg);\\",
+ " *yy_cp = YY_G(yy_hold_char); \\",
+ " YY_RESTORE_YY_MORE_OFFSET \\",
+ " YY_G(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \\",
+ " YY_DO_BEFORE_ACTION; /* set up yytext again */ \\",
+ " } \\",
+ " while ( 0 )",
+ "#define unput(c) yyunput( c, YY_G(yytext_ptr) M4_YY_CALL_LAST_ARG )",
+ "]])",
+ "",
+ "#ifndef YY_STRUCT_YY_BUFFER_STATE",
+ "#define YY_STRUCT_YY_BUFFER_STATE",
+ "struct yy_buffer_state",
+ " {",
+ "%if-c-only",
+ " FILE *yy_input_file;",
+ "%endif",
+ "",
+ "%if-c++-only",
+ " std::streambuf* yy_input_file;",
+ "%endif",
+ "",
+ "",
+ " char *yy_ch_buf; /* input buffer */",
+ " char *yy_buf_pos; /* current position in input buffer */",
+ "",
+ " /* Size of input buffer in bytes, not including room for EOB",
+ " * characters.",
+ " */",
+ " int yy_buf_size;",
+ "",
+ " /* Number of characters read into yy_ch_buf, not including EOB",
+ " * characters.",
+ " */",
+ " int yy_n_chars;",
+ "",
+ " /* Whether we \"own\" the buffer - i.e., we know we created it,",
+ " * and can realloc() it to grow it, and should free() it to",
+ " * delete it.",
+ " */",
+ " int yy_is_our_buffer;",
+ "",
+ " /* Whether this is an \"interactive\" input source; if so, and",
+ " * if we're using stdio for input, then we want to use getc()",
+ " * instead of fread(), to make sure we stop fetching input after",
+ " * each newline.",
+ " */",
+ " int yy_is_interactive;",
+ "",
+ " /* Whether we're considered to be at the beginning of a line.",
+ " * If so, '^' rules will be active on the next match, otherwise",
+ " * not.",
+ " */",
+ " int yy_at_bol;",
+ "",
+ " int yy_bs_lineno; /**< The line count. */",
+ " int yy_bs_column; /**< The column count. */",
+ "",
+ "",
+ " /* Whether to try to fill the input buffer when we reach the",
+ " * end of it.",
+ " */",
+ " int yy_fill_buffer;",
+ "",
+ " int yy_buffer_status;",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "#define YY_BUFFER_NEW 0",
+ "#define YY_BUFFER_NORMAL 1",
+ " /* When an EOF's been seen but there's still some text to process",
+ " * then we mark the buffer as YY_EOF_PENDING, to indicate that we",
+ " * shouldn't try reading from the input source any more. We might",
+ " * still have a bunch of tokens to match, though, because of",
+ " * possible backing-up.",
+ " *",
+ " * When we actually see the EOF, we change the status to \"new\"",
+ " * (via yyrestart()), so that the user can continue scanning by",
+ " * just pointing yyin at a new input file.",
+ " */",
+ "#define YY_BUFFER_EOF_PENDING 2",
+ "]])",
+ " };",
+ "#endif /* !YY_STRUCT_YY_BUFFER_STATE */",
+ "",
+ "%if-c-only Standard (non-C++) definition",
+ "%not-for-header",
+ "%if-not-reentrant",
+ "",
+ "/* Stack of input buffers. */",
+ "static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */",
+ "static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */",
+ "static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */",
+ "%endif",
+ "%ok-for-header",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* We provide macros for accessing buffer states in case in the",
+ " * future we want to put the buffer states in a more general",
+ " * \"scanner state\".",
+ " *",
+ " * Returns the top of the stack, or NULL.",
+ " */",
+ "#define YY_CURRENT_BUFFER ( YY_G(yy_buffer_stack) \\",
+ " ? YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)] \\",
+ " : NULL)",
+ "#define yy_current_buffer YY_CURRENT_BUFFER",
+ "/* Same as previous macro, but useful when we know that the buffer stack is not",
+ " * NULL or when we need an lvalue. For internal use only.",
+ " */",
+ "#define YY_CURRENT_BUFFER_LVALUE YY_G(yy_buffer_stack)[YY_G(yy_buffer_stack_top)]",
+ "]])",
+ "",
+ "%if-c-only Standard (non-C++) definition",
+ "",
+ "%if-not-reentrant",
+ "%not-for-header",
+ "/* yy_hold_char holds the character lost when yytext is formed. */",
+ "static char yy_hold_char;",
+ "static int yy_n_chars; /* number of characters read into yy_ch_buf */",
+ "int yyleng;",
+ "",
+ "/* Points to current character in buffer. */",
+ "static char *yy_c_buf_p = NULL;",
+ "static int yy_init = 0; /* whether we need to initialize */",
+ "static int yy_start = 0; /* start state number */",
+ "",
+ "/* Flag which is used to allow yywrap()'s to do buffer switches",
+ " * instead of setting up a fresh yyin. A bit of a hack ...",
+ " */",
+ "static int yy_did_buffer_switch_on_eof;",
+ "%ok-for-header",
+ "%endif",
+ "",
+ "void yyrestart ( FILE *input_file M4_YY_PROTO_LAST_ARG );",
+ "void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG );",
+ "YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size M4_YY_PROTO_LAST_ARG );",
+ "void yy_delete_buffer ( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG );",
+ "void yy_flush_buffer ( YY_BUFFER_STATE b M4_YY_PROTO_LAST_ARG );",
+ "void yypush_buffer_state ( YY_BUFFER_STATE new_buffer M4_YY_PROTO_LAST_ARG );",
+ "void yypop_buffer_state ( M4_YY_PROTO_ONLY_ARG );",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "static void yyensure_buffer_stack ( M4_YY_PROTO_ONLY_ARG );",
+ "static void yy_load_buffer_state ( M4_YY_PROTO_ONLY_ARG );",
+ "static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file M4_YY_PROTO_LAST_ARG );",
+ "#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG)",
+ "]])",
+ "",
+ "YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size M4_YY_PROTO_LAST_ARG );",
+ "YY_BUFFER_STATE yy_scan_string ( const char *yy_str M4_YY_PROTO_LAST_ARG );",
+ "YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len M4_YY_PROTO_LAST_ARG );",
+ "",
+ "%endif",
+ "",
+ "void *yyalloc ( yy_size_t M4_YY_PROTO_LAST_ARG );",
+ "void *yyrealloc ( void *, yy_size_t M4_YY_PROTO_LAST_ARG );",
+ "void yyfree ( void * M4_YY_PROTO_LAST_ARG );",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "#define yy_new_buffer yy_create_buffer",
+ "#define yy_set_interactive(is_interactive) \\",
+ " { \\",
+ " if ( ! YY_CURRENT_BUFFER ){ \\",
+ " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \\",
+ " YY_CURRENT_BUFFER_LVALUE = \\",
+ " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \\",
+ " } \\",
+ " YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \\",
+ " }",
+ "#define yy_set_bol(at_bol) \\",
+ " { \\",
+ " if ( ! YY_CURRENT_BUFFER ){\\",
+ " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG); \\",
+ " YY_CURRENT_BUFFER_LVALUE = \\",
+ " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG); \\",
+ " } \\",
+ " YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \\",
+ " }",
+ "#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)",
+ "]])",
+ "",
+ "%% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "%% [1.5] DFA",
+ "]])",
+ "",
+ "%if-c-only Standard (non-C++) definition",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "static yy_state_type yy_get_previous_state ( M4_YY_PROTO_ONLY_ARG );",
+ "static yy_state_type yy_try_NUL_trans ( yy_state_type current_state M4_YY_PROTO_LAST_ARG);",
+ "static int yy_get_next_buffer ( M4_YY_PROTO_ONLY_ARG );",
+ "static void yynoreturn yy_fatal_error ( const char* msg M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Done after the current pattern has been matched and before the",
+ " * corresponding action - sets up yytext.",
+ " */",
+ "#define YY_DO_BEFORE_ACTION \\",
+ " YY_G(yytext_ptr) = yy_bp; \\",
+ "%% [2.0] code to fiddle yytext and yyleng for yymore() goes here \\",
+ " YY_G(yy_hold_char) = *yy_cp; \\",
+ " *yy_cp = '\\0'; \\",
+ "%% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \\",
+ " YY_G(yy_c_buf_p) = yy_cp;",
+ "%% [4.0] data tables for the DFA and the user's section 1 definitions go here",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_IN_HEADER]], [[#ifdef YY_HEADER_EXPORT_START_CONDITIONS]])",
+ "M4_YY_SC_DEFS",
+ "m4_ifdef( [[M4_YY_IN_HEADER]], [[#endif]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_UNISTD_H]],,",
+ "[[",
+ "#ifndef YY_NO_UNISTD_H",
+ "/* Special case for \"unistd.h\", since it is non-ANSI. We include it way",
+ " * down here because we want the user's section 1 to have been scanned first.",
+ " * The user has a chance to override it with an option.",
+ " */",
+ "%if-c-only",
+ "#include <unistd.h>",
+ "%endif",
+ "%if-c++-only",
+ "#include <unistd.h>",
+ "%endif",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_EXTRA_TYPE_DEFS]],",
+ "[[",
+ "#define YY_EXTRA_TYPE M4_EXTRA_TYPE_DEFS",
+ "]],",
+ "[[",
+ "#ifndef YY_EXTRA_TYPE",
+ "#define YY_EXTRA_TYPE void *",
+ "#endif",
+ "]]",
+ ")",
+ "",
+ "%if-c-only Reentrant structure and macros (non-C++).",
+ "%if-reentrant",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Holds the entire state of the reentrant scanner. */",
+ "struct yyguts_t",
+ " {",
+ "",
+ " /* User-defined. Not touched by flex. */",
+ " YY_EXTRA_TYPE yyextra_r;",
+ "",
+ " /* The rest are the same as the globals declared in the non-reentrant scanner. */",
+ " FILE *yyin_r, *yyout_r;",
+ " size_t yy_buffer_stack_top; /**< index of top of stack. */",
+ " size_t yy_buffer_stack_max; /**< capacity of stack. */",
+ " YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */",
+ " char yy_hold_char;",
+ " int yy_n_chars;",
+ " int yyleng_r;",
+ " char *yy_c_buf_p;",
+ " int yy_init;",
+ " int yy_start;",
+ " int yy_did_buffer_switch_on_eof;",
+ " int yy_start_stack_ptr;",
+ " int yy_start_stack_depth;",
+ " int *yy_start_stack;",
+ " yy_state_type yy_last_accepting_state;",
+ " char* yy_last_accepting_cpos;",
+ "",
+ " int yylineno_r;",
+ " int yy_flex_debug_r;",
+ "",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " yy_state_type *yy_state_buf;",
+ " yy_state_type *yy_state_ptr;",
+ " char *yy_full_match;",
+ " int yy_lp;",
+ "",
+ " /* These are only needed for trailing context rules,",
+ " * but there's no conditional variable for that yet. */",
+ " int yy_looking_for_trail_begin;",
+ " int yy_full_lp;",
+ " int *yy_full_state;",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]],",
+ "[[",
+ " char yytext_r[YYLMAX];",
+ " char *yytext_ptr;",
+ " int yy_more_offset;",
+ " int yy_prev_more_offset;",
+ "]],",
+ "[[",
+ " char *yytext_r;",
+ " int yy_more_flag;",
+ " int yy_more_len;",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ "[[",
+ " YYSTYPE * yylval_r;",
+ "]])",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " YYLTYPE * yylloc_r;",
+ "]])",
+ "",
+ " }; /* end struct yyguts_t */",
+ "]])",
+ "",
+ "",
+ "%if-c-only",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "static int yy_init_globals ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "%endif",
+ "",
+ "%if-reentrant",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ " [[",
+ " /* This must go here because YYSTYPE and YYLTYPE are included",
+ " * from bison output in section 1.*/",
+ " # define yylval YY_G(yylval_r)",
+ " ]])",
+ "",
+ " m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ " [[",
+ " # define yylloc YY_G(yylloc_r)",
+ " ]])",
+ "]])",
+ "",
+ "int yylex_init (yyscan_t* scanner);",
+ "",
+ "int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);",
+ "",
+ "%endif",
+ "",
+ "%endif End reentrant structures and macros.",
+ "",
+ "/* Accessor methods to globals.",
+ " These are made visible to non-reentrant scanners for convenience. */",
+ "",
+ "m4_ifdef( [[M4_YY_NO_DESTROY]],,",
+ "[[",
+ "int yylex_destroy ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_DEBUG]],,",
+ "[[",
+ "int yyget_debug ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_DEBUG]],,",
+ "[[",
+ "void yyset_debug ( int debug_flag M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_EXTRA]],,",
+ "[[",
+ "YY_EXTRA_TYPE yyget_extra ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_EXTRA]],,",
+ "[[",
+ "void yyset_extra ( YY_EXTRA_TYPE user_defined M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_IN]],,",
+ "[[",
+ "FILE *yyget_in ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_IN]],,",
+ "[[",
+ "void yyset_in ( FILE * _in_str M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_OUT]],,",
+ "[[",
+ "FILE *yyget_out ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_OUT]],,",
+ "[[",
+ "void yyset_out ( FILE * _out_str M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_LENG]],,",
+ "[[",
+ " int yyget_leng ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_TEXT]],,",
+ "[[",
+ "char *yyget_text ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_LINENO]],,",
+ "[[",
+ "int yyget_lineno ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_LINENO]],,",
+ "[[",
+ "void yyset_lineno ( int _line_number M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_REENTRANT]],",
+ "[[",
+ "m4_ifdef( [[M4_YY_NO_GET_COLUMN]],,",
+ "[[",
+ "int yyget_column ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_REENTRANT]],",
+ "[[",
+ "m4_ifdef( [[M4_YY_NO_SET_COLUMN]],,",
+ "[[",
+ "void yyset_column ( int _column_no M4_YY_PROTO_LAST_ARG );",
+ "]])",
+ "]])",
+ "",
+ "%if-bison-bridge",
+ "m4_ifdef( [[M4_YY_NO_GET_LVAL]],,",
+ "[[",
+ "YYSTYPE * yyget_lval ( M4_YY_PROTO_ONLY_ARG );",
+ "]])",
+ "",
+ "void yyset_lval ( YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG );",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NO_GET_LLOC]],,",
+ " [[",
+ " YYLTYPE *yyget_lloc ( M4_YY_PROTO_ONLY_ARG );",
+ " ]])",
+ "",
+ " m4_ifdef( [[M4_YY_NO_SET_LLOC]],,",
+ " [[",
+ " void yyset_lloc ( YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG );",
+ " ]])",
+ "]])",
+ "%endif",
+ "",
+ "/* Macros after this point can all be overridden by user definitions in",
+ " * section 1.",
+ " */",
+ "",
+ "#ifndef YY_SKIP_YYWRAP",
+ "#ifdef __cplusplus",
+ "extern \"C\" int yywrap ( M4_YY_PROTO_ONLY_ARG );",
+ "#else",
+ "extern int yywrap ( M4_YY_PROTO_ONLY_ARG );",
+ "#endif",
+ "#endif",
+ "",
+ "%not-for-header",
+ "#ifndef YY_NO_UNPUT",
+ " m4_ifdef( [[M4_YY_NO_UNPUT]],,",
+ " [[",
+ " static void yyunput ( int c, char *buf_ptr M4_YY_PROTO_LAST_ARG);",
+ " ]])",
+ "#endif",
+ "%ok-for-header",
+ "%endif",
+ "",
+ "#ifndef yytext_ptr",
+ "static void yy_flex_strncpy ( char *, const char *, int M4_YY_PROTO_LAST_ARG);",
+ "#endif",
+ "",
+ "#ifdef YY_NEED_STRLEN",
+ "static int yy_flex_strlen ( const char * M4_YY_PROTO_LAST_ARG);",
+ "#endif",
+ "",
+ "#ifndef YY_NO_INPUT",
+ "%if-c-only Standard (non-C++) definition",
+ "%not-for-header",
+ "#ifdef __cplusplus",
+ "static int yyinput ( M4_YY_PROTO_ONLY_ARG );",
+ "#else",
+ "static int input ( M4_YY_PROTO_ONLY_ARG );",
+ "#endif",
+ "%ok-for-header",
+ "%endif",
+ "#endif",
+ "",
+ "",
+ "%if-c-only",
+ "m4_ifdef( [[M4_YY_STACK_USED]],",
+ "[[",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_REENTRANT]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ " [[",
+ " static int yy_start_stack_ptr = 0;",
+ " static int yy_start_stack_depth = 0;",
+ " static int *yy_start_stack = NULL;",
+ " ]])",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NO_PUSH_STATE]],,",
+ " [[",
+ " static void yy_push_state ( int _new_state M4_YY_PROTO_LAST_ARG);",
+ " ]])",
+ " m4_ifdef( [[M4_YY_NO_POP_STATE]],,",
+ " [[",
+ " static void yy_pop_state ( M4_YY_PROTO_ONLY_ARG );",
+ " ]])",
+ " m4_ifdef( [[M4_YY_NO_TOP_STATE]],,",
+ " [[",
+ " static int yy_top_state ( M4_YY_PROTO_ONLY_ARG );",
+ " ]])",
+ "]])",
+ "",
+ "]],",
+ "[[",
+ "m4_define( [[M4_YY_NO_PUSH_STATE]])",
+ "m4_define( [[M4_YY_NO_POP_STATE]])",
+ "m4_define( [[M4_YY_NO_TOP_STATE]])",
+ "]])",
+ "%endif",
+ "",
+ "/* Amount of stuff to slurp up with each read. */",
+ "#ifndef YY_READ_BUF_SIZE",
+ "#ifdef __ia64__",
+ "/* On IA-64, the buffer size is 16k, not 8k */",
+ "#define YY_READ_BUF_SIZE 16384",
+ "#else",
+ "#define YY_READ_BUF_SIZE 8192",
+ "#endif /* __ia64__ */",
+ "#endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Copy whatever the last rule matched to the standard output. */",
+ "#ifndef ECHO",
+ "%if-c-only Standard (non-C++) definition",
+ "/* This used to be an fputs(), but since the string might contain NUL's,",
+ " * we now use fwrite().",
+ " */",
+ "#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)",
+ "%endif",
+ "%if-c++-only C++ definition",
+ "#define ECHO LexerOutput( yytext, yyleng )",
+ "%endif",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Gets input and stuffs it into \"buf\". number of characters read, or YY_NULL,",
+ " * is returned in \"result\".",
+ " */",
+ "#ifndef YY_INPUT",
+ "#define YY_INPUT(buf,result,max_size) \\",
+ "%% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \\",
+ "\\",
+ "%if-c++-only C++ definition \\",
+ " if ( (int)(result = LexerInput( (char *) buf, max_size )) < 0 ) \\",
+ " YY_FATAL_ERROR( \"input in flex scanner failed\" );",
+ "%endif",
+ "",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* No semi-colon after return; correct usage is to write \"yyterminate();\" -",
+ " * we don't want an extra ';' after the \"return\" because that will cause",
+ " * some compilers to complain about unreachable statements.",
+ " */",
+ "#ifndef yyterminate",
+ "#define yyterminate() return YY_NULL",
+ "#endif",
+ "]])",
+ "",
+ "/* Number of entries by which start-condition stack grows. */",
+ "#ifndef YY_START_STACK_INCR",
+ "#define YY_START_STACK_INCR 25",
+ "#endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Report a fatal error. */",
+ "#ifndef YY_FATAL_ERROR",
+ "%if-c-only",
+ "#define YY_FATAL_ERROR(msg) yy_fatal_error( msg M4_YY_CALL_LAST_ARG)",
+ "%endif",
+ "%if-c++-only",
+ "#define YY_FATAL_ERROR(msg) LexerError( msg )",
+ "%endif",
+ "#endif",
+ "]])",
+ "",
+ "%if-tables-serialization structures and prototypes",
+ "#ifdef FLEX_SCANNER",
+ "/*",
+ "dnl tables_shared.h - tables serialization header",
+ "dnl",
+ "dnl Copyright (c) 1990 The Regents of the University of California.",
+ "dnl All rights reserved.",
+ "dnl",
+ "dnl This code is derived from software contributed to Berkeley by",
+ "dnl Vern Paxson.",
+ "dnl",
+ "dnl The United States Government has rights in this work pursuant",
+ "dnl to contract no. DE-AC03-76SF00098 between the United States",
+ "dnl Department of Energy and the University of California.",
+ "dnl",
+ "dnl This file is part of flex.",
+ "dnl",
+ "dnl Redistribution and use in source and binary forms, with or without",
+ "dnl modification, are permitted provided that the following conditions",
+ "dnl are met:",
+ "dnl",
+ "dnl 1. Redistributions of source code must retain the above copyright",
+ "dnl notice, this list of conditions and the following disclaimer.",
+ "dnl 2. Redistributions in binary form must reproduce the above copyright",
+ "dnl notice, this list of conditions and the following disclaimer in the",
+ "dnl documentation and/or other materials provided with the distribution.",
+ "dnl",
+ "dnl Neither the name of the University nor the names of its contributors",
+ "dnl may be used to endorse or promote products derived from this software",
+ "dnl without specific prior written permission.",
+ "dnl",
+ "dnl THIS SOFTWARE IS PROVIDED `AS IS' AND WITHOUT ANY EXPRESS OR",
+ "dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED",
+ "dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR",
+ "dnl PURPOSE.",
+ " ",
+ "dnl",
+ "dnl This file is meant to be included in both the skeleton and the actual",
+ "dnl flex code (hence the name \"_shared\").",
+ "*/",
+ "#ifndef yyskel_static",
+ "#define yyskel_static static",
+ "#endif",
+ "#else",
+ "#ifndef yyskel_static",
+ "#define yyskel_static",
+ "#endif",
+ "#endif",
+ "",
+ "/* Structures and prototypes for serializing flex tables. The",
+ " * binary format is documented in the manual.",
+ " *",
+ " * Design considerations:",
+ " *",
+ " * - The format allows many tables per file.",
+ " * - The tables can be streamed.",
+ " * - All data is stored in network byte order.",
+ " * - We do not hinder future unicode support.",
+ " * - We can lookup tables by name.",
+ " */",
+ "",
+ "/** Magic number for serialized format. */",
+ "#ifndef YYTBL_MAGIC",
+ "#define YYTBL_MAGIC 0xF13C57B1",
+ "#endif",
+ "",
+ "/** Calculate (0-7) = number bytes needed to pad n to next 64-bit boundary. */",
+ "#ifndef yypad64",
+ "#define yypad64(n) ((8-((n)%8))%8)",
+ "#endif",
+ "",
+ "",
+ "#ifndef YYTABLES_TYPES",
+ "#define YYTABLES_TYPES",
+ "/** Possible values for td_id field. Each one corresponds to a",
+ " * scanner table of the same name.",
+ " */",
+ "enum yytbl_id {",
+ " YYTD_ID_ACCEPT = 0x01, /**< 1-dim ints */",
+ " YYTD_ID_BASE = 0x02, /**< 1-dim ints */",
+ " YYTD_ID_CHK = 0x03, /**< 1-dim ints */",
+ " YYTD_ID_DEF = 0x04, /**< 1-dim ints */",
+ " YYTD_ID_EC = 0x05, /**< 1-dim ints */",
+ " YYTD_ID_META = 0x06, /**< 1-dim ints */",
+ " YYTD_ID_NUL_TRANS = 0x07, /**< 1-dim ints, maybe indices */",
+ " YYTD_ID_NXT = 0x08, /**< may be 2 dimensional ints */",
+ " YYTD_ID_RULE_CAN_MATCH_EOL = 0x09, /**< 1-dim ints */",
+ " YYTD_ID_START_STATE_LIST = 0x0A, /**< 1-dim indices into trans tbl */",
+ " YYTD_ID_TRANSITION = 0x0B, /**< structs */",
+ " YYTD_ID_ACCLIST = 0x0C /**< 1-dim ints */",
+ "};",
+ "",
+ "/** bit flags for t_flags field of struct yytbl_data */",
+ "enum yytbl_flags {",
+ " /* These first three are mutually exclusive */",
+ " YYTD_DATA8 = 0x01, /**< data is an array of type flex_int8_t */",
+ " YYTD_DATA16 = 0x02, /**< data is an array of type flex_int16_t */",
+ " YYTD_DATA32 = 0x04, /**< data is an array of type flex_int32_t */",
+ "",
+ " /* These two are mutually exclusive. */",
+ " YYTD_PTRANS = 0x08, /**< data is a list of indexes of entries",
+ " into the expanded yy_transition",
+ " array. See notes in manual. */",
+ " YYTD_STRUCT = 0x10 /**< data consists of yy_trans_info structs */",
+ "};",
+ "",
+ "/* The serialized tables header. */",
+ "struct yytbl_hdr {",
+ " flex_uint32_t th_magic; /**< Must be 0xF13C57B1 (comes from \"Flex Table\") */",
+ " flex_uint32_t th_hsize; /**< Size of this header in bytes. */",
+ " flex_uint32_t th_ssize; /**< Size of this dataset, in bytes, including header. */",
+ " flex_uint16_t th_flags; /**< Currently unused, must be 0 */",
+ " char *th_version; /**< Flex version string. NUL terminated. */",
+ " char *th_name; /**< The name of this table set. NUL terminated. */",
+ "};",
+ "",
+ "/** A single serialized table */",
+ "struct yytbl_data {",
+ " flex_uint16_t td_id; /**< enum yytbl_id table identifier */",
+ " flex_uint16_t td_flags; /**< how to interpret this data */",
+ " flex_uint32_t td_hilen; /**< num elements in highest dimension array */",
+ " flex_uint32_t td_lolen; /**< num elements in lowest dimension array */",
+ " void *td_data; /**< table data */",
+ "};",
+ "#endif",
+ "",
+ "/** Extract corresponding data size_t from td_flags */",
+ "#ifndef YYTDFLAGS2BYTES",
+ "#define YYTDFLAGS2BYTES(td_flags)\\",
+ " (((td_flags) & YYTD_DATA8)\\",
+ " ? sizeof(flex_int8_t)\\",
+ " :(((td_flags) & YYTD_DATA16)\\",
+ " ? sizeof(flex_int16_t)\\",
+ " :sizeof(flex_int32_t)))",
+ "#endif",
+ "",
+ "#ifdef FLEX_SCANNER",
+ "%not-for-header",
+ "#endif",
+ "yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl);",
+ "#ifdef FLEX_SCANNER",
+ "%ok-for-header",
+ "#endif",
+ "",
+ "/* vim:set noexpandtab cindent tabstop=8 softtabstop=0 shiftwidth=8 textwidth=0: */",
+ "",
+ "",
+ "/* Load the DFA tables from the given stream. */",
+ "int yytables_fload (FILE * fp M4_YY_PROTO_LAST_ARG);",
+ "",
+ "/* Unload the tables from memory. */",
+ "int yytables_destroy (M4_YY_PROTO_ONLY_ARG);",
+ "%not-for-header",
+ "",
+ "/** Describes a mapping from a serialized table id to its deserialized state in",
+ " * this scanner. This is the bridge between our \"generic\" deserialization code",
+ " * and the specifics of this scanner.",
+ " */",
+ "struct yytbl_dmap {",
+ " enum yytbl_id dm_id;/**< table identifier */",
+ " void **dm_arr; /**< address of pointer to store the deserialized table. */",
+ " size_t dm_sz; /**< local sizeof() each element in table. */",
+ "};",
+ "",
+ "/** A {0,0,0}-terminated list of structs, forming the map */",
+ "static struct yytbl_dmap yydmap[] =",
+ "{",
+ "%tables-yydmap generated elements",
+ " {0,0,0}",
+ "};",
+ "",
+ "/** A tables-reader object to maintain some state in the read. */",
+ "struct yytbl_reader {",
+ " FILE * fp; /**< input stream */",
+ " flex_uint32_t bread; /**< bytes read since beginning of current tableset */",
+ "};",
+ "",
+ "%endif",
+ "/* end tables serialization structures and prototypes */",
+ "",
+ "%ok-for-header",
+ "",
+ "/* Default declaration of generated scanner - a define so the user can",
+ " * easily add parameters.",
+ " */",
+ "#ifndef YY_DECL",
+ "#define YY_DECL_IS_OURS 1",
+ "%if-c-only Standard (non-C++) definition",
+ "",
+ "",
+ "m4_define( [[M4_YY_LEX_PROTO]], [[(M4_YY_PROTO_ONLY_ARG)]])",
+ "m4_define( [[M4_YY_LEX_DECLARATION]], [[(M4_YY_DEF_ONLY_ARG)]])",
+ "",
+ "m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ "[[",
+ " m4_dnl The bison pure parser is used. Redefine yylex to",
+ " m4_dnl accept the lval parameter.",
+ "",
+ " m4_define( [[M4_YY_LEX_PROTO]], [[\\]]",
+ " [[(YYSTYPE * yylval_param M4_YY_PROTO_LAST_ARG)]])",
+ " m4_define( [[M4_YY_LEX_DECLARATION]], [[\\]]",
+ " [[YYFARGS1(YYSTYPE *,yylval_param)]])",
+ "]])",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " m4_dnl Locations are used. yylex should also accept the ylloc parameter.",
+ "",
+ " m4_define( [[M4_YY_LEX_PROTO]], [[\\]]",
+ " [[(YYSTYPE * yylval_param, YYLTYPE * yylloc_param M4_YY_PROTO_LAST_ARG)]])",
+ " m4_define( [[M4_YY_LEX_DECLARATION]], [[\\]]",
+ " [[YYFARGS2(YYSTYPE *,yylval_param, YYLTYPE *,yylloc_param)]])",
+ "]])",
+ "",
+ "extern int yylex M4_YY_LEX_PROTO;",
+ "",
+ "#define YY_DECL int yylex M4_YY_LEX_DECLARATION",
+ "%endif",
+ "%if-c++-only C++ definition",
+ "#define YY_DECL int yyFlexLexer::yylex()",
+ "%endif",
+ "#endif /* !YY_DECL */",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Code executed at the beginning of each rule, after yytext and yyleng",
+ " * have been set up.",
+ " */",
+ "#ifndef YY_USER_ACTION",
+ "#define YY_USER_ACTION",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* Code executed at the end of each rule. */",
+ "#ifndef YY_BREAK",
+ "#define YY_BREAK /*LINTED*/break;",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "%% [6.0] YY_RULE_SETUP definition goes here",
+ "]])",
+ "",
+ "%not-for-header",
+ "/** The main scanner function which does all the work.",
+ " */",
+ "YY_DECL",
+ "{",
+ " yy_state_type yy_current_state;",
+ " char *yy_cp, *yy_bp;",
+ " int yy_act;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_REENTRANT]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ " [[",
+ " YYSTYPE * yylval;",
+ " ]])",
+ " m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ " [[",
+ " YYLTYPE * yylloc;",
+ " ]])",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_BISON_LVAL]],",
+ "[[",
+ " yylval = yylval_param;",
+ "]])",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " yylloc = yylloc_param;",
+ "]])",
+ "",
+ " if ( !YY_G(yy_init) )",
+ " {",
+ " YY_G(yy_init) = 1;",
+ "",
+ "#ifdef YY_USER_INIT",
+ " YY_USER_INIT;",
+ "#endif",
+ "",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " /* Create the reject buffer large enough to save one state per allowed character. */",
+ " if ( ! YY_G(yy_state_buf) )",
+ " YY_G(yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE M4_YY_CALL_LAST_ARG);",
+ " if ( ! YY_G(yy_state_buf) )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yylex()\" );",
+ "]])",
+ "",
+ " if ( ! YY_G(yy_start) )",
+ " YY_G(yy_start) = 1; /* first start state */",
+ "",
+ " if ( ! yyin )",
+ "%if-c-only",
+ " yyin = stdin;",
+ "%endif",
+ "%if-c++-only",
+ " yyin.rdbuf(std::cin.rdbuf());",
+ "%endif",
+ "",
+ " if ( ! yyout )",
+ "%if-c-only",
+ " yyout = stdout;",
+ "%endif",
+ "%if-c++-only",
+ " yyout.rdbuf(std::cout.rdbuf());",
+ "%endif",
+ "",
+ " if ( ! YY_CURRENT_BUFFER ) {",
+ " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);",
+ " YY_CURRENT_BUFFER_LVALUE =",
+ " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG);",
+ " }",
+ "",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ " }",
+ "",
+ " {",
+ "%% [7.0] user's declarations go here",
+ "",
+ " while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */",
+ " {",
+ "%% [8.0] yymore()-related code goes here",
+ " yy_cp = YY_G(yy_c_buf_p);",
+ "",
+ " /* Support of yytext. */",
+ " *yy_cp = YY_G(yy_hold_char);",
+ "",
+ " /* yy_bp points to the position in yy_ch_buf of the start of",
+ " * the current run.",
+ " */",
+ " yy_bp = yy_cp;",
+ "",
+ "%% [9.0] code to set up and find next match goes here",
+ "",
+ "yy_find_action:",
+ "%% [10.0] code to find the action number goes here",
+ "",
+ " YY_DO_BEFORE_ACTION;",
+ "",
+ "%% [11.0] code for yylineno update goes here",
+ "",
+ "do_action: /* This label is used only to access EOF actions. */",
+ "",
+ "%% [12.0] debug code goes here",
+ "",
+ " switch ( yy_act )",
+ " { /* beginning of action switch */",
+ "%% [13.0] actions go here",
+ "",
+ " case YY_END_OF_BUFFER:",
+ " {",
+ " /* Amount of text matched not including the EOB char. */",
+ " int yy_amount_of_matched_text = (int) (yy_cp - YY_G(yytext_ptr)) - 1;",
+ "",
+ " /* Undo the effects of YY_DO_BEFORE_ACTION. */",
+ " *yy_cp = YY_G(yy_hold_char);",
+ " YY_RESTORE_YY_MORE_OFFSET",
+ "",
+ " if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )",
+ " {",
+ " /* We're scanning a new file or input source. It's",
+ " * possible that this happened because the user",
+ " * just pointed yyin at a new source and called",
+ " * yylex(). If so, then we have to assure",
+ " * consistency between YY_CURRENT_BUFFER and our",
+ " * globals. Here is the right place to do so, because",
+ " * this is the first action (other than possibly a",
+ " * back-up) that will match for the new input source.",
+ " */",
+ " YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;",
+ "%if-c-only",
+ " YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;",
+ "%endif",
+ "%if-c++-only",
+ " YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin.rdbuf();",
+ "%endif",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;",
+ " }",
+ "",
+ " /* Note that here we test for yy_c_buf_p \"<=\" to the position",
+ " * of the first EOB in the buffer, since yy_c_buf_p will",
+ " * already have been incremented past the NUL character",
+ " * (since all states make transitions on EOB to the",
+ " * end-of-buffer state). Contrast this with the test",
+ " * in input().",
+ " */",
+ " if ( YY_G(yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] )",
+ " { /* This was really a NUL. */",
+ " yy_state_type yy_next_state;",
+ "",
+ " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + yy_amount_of_matched_text;",
+ "",
+ " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );",
+ "",
+ " /* Okay, we're now positioned to make the NUL",
+ " * transition. We couldn't have",
+ " * yy_get_previous_state() go ahead and do it",
+ " * for us because it doesn't know how to deal",
+ " * with the possibility of jamming (and we don't",
+ " * want to build jamming into it because then it",
+ " * will run more slowly).",
+ " */",
+ "",
+ " yy_next_state = yy_try_NUL_trans( yy_current_state M4_YY_CALL_LAST_ARG);",
+ "",
+ " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;",
+ "",
+ " if ( yy_next_state )",
+ " {",
+ " /* Consume the NUL. */",
+ " yy_cp = ++YY_G(yy_c_buf_p);",
+ " yy_current_state = yy_next_state;",
+ " goto yy_match;",
+ " }",
+ "",
+ " else",
+ " {",
+ "%% [14.0] code to do back-up for compressed tables and set up yy_cp goes here",
+ " goto yy_find_action;",
+ " }",
+ " }",
+ "",
+ " else switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) )",
+ " {",
+ " case EOB_ACT_END_OF_FILE:",
+ " {",
+ " YY_G(yy_did_buffer_switch_on_eof) = 0;",
+ "",
+ " if ( yywrap( M4_YY_CALL_ONLY_ARG ) )",
+ " {",
+ " /* Note: because we've taken care in",
+ " * yy_get_next_buffer() to have set up",
+ " * yytext, we can now set up",
+ " * yy_c_buf_p so that if some total",
+ " * hoser (like flex itself) wants to",
+ " * call the scanner after we return the",
+ " * YY_NULL, it'll still work - another",
+ " * YY_NULL will get returned.",
+ " */",
+ " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + YY_MORE_ADJ;",
+ "",
+ " yy_act = YY_STATE_EOF(YY_START);",
+ " goto do_action;",
+ " }",
+ "",
+ " else",
+ " {",
+ " if ( ! YY_G(yy_did_buffer_switch_on_eof) )",
+ " YY_NEW_FILE;",
+ " }",
+ " break;",
+ " }",
+ "",
+ " case EOB_ACT_CONTINUE_SCAN:",
+ " YY_G(yy_c_buf_p) =",
+ " YY_G(yytext_ptr) + yy_amount_of_matched_text;",
+ "",
+ " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );",
+ "",
+ " yy_cp = YY_G(yy_c_buf_p);",
+ " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;",
+ " goto yy_match;",
+ "",
+ " case EOB_ACT_LAST_MATCH:",
+ " YY_G(yy_c_buf_p) =",
+ " &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)];",
+ "",
+ " yy_current_state = yy_get_previous_state( M4_YY_CALL_ONLY_ARG );",
+ "",
+ " yy_cp = YY_G(yy_c_buf_p);",
+ " yy_bp = YY_G(yytext_ptr) + YY_MORE_ADJ;",
+ " goto yy_find_action;",
+ " }",
+ " break;",
+ " }",
+ "",
+ " default:",
+ " YY_FATAL_ERROR(",
+ " \"fatal flex scanner internal error--no action found\" );",
+ " } /* end of action switch */",
+ " } /* end of scanning one token */",
+ " } /* end of user's declarations */",
+ "} /* end of yylex */",
+ "%ok-for-header",
+ "",
+ "%if-c++-only",
+ "%not-for-header",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " * This constructor simply maintains backward compatibility.",
+ " * DEPRECATED",
+ " */",
+ "yyFlexLexer::yyFlexLexer( std::istream* arg_yyin, std::ostream* arg_yyout ):",
+ " yyin(arg_yyin ? arg_yyin->rdbuf() : std::cin.rdbuf()),",
+ " yyout(arg_yyout ? arg_yyout->rdbuf() : std::cout.rdbuf())",
+ "{",
+ " ctor_common();",
+ "}",
+ "",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " */",
+ "yyFlexLexer::yyFlexLexer( std::istream& arg_yyin, std::ostream& arg_yyout ):",
+ " yyin(arg_yyin.rdbuf()),",
+ " yyout(arg_yyout.rdbuf())",
+ "{",
+ " ctor_common();",
+ "}",
+ "",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " */",
+ "void yyFlexLexer::ctor_common()",
+ "{",
+ " yy_c_buf_p = 0;",
+ " yy_init = 0;",
+ " yy_start = 0;",
+ " yy_flex_debug = 0;",
+ " yylineno = 1; // this will only get updated if %option yylineno",
+ "",
+ " yy_did_buffer_switch_on_eof = 0;",
+ "",
+ " yy_looking_for_trail_begin = 0;",
+ " yy_more_flag = 0;",
+ " yy_more_len = 0;",
+ " yy_more_offset = yy_prev_more_offset = 0;",
+ "",
+ " yy_start_stack_ptr = yy_start_stack_depth = 0;",
+ " yy_start_stack = NULL;",
+ "",
+ " yy_buffer_stack = NULL;",
+ " yy_buffer_stack_top = 0;",
+ " yy_buffer_stack_max = 0;",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " yy_state_buf = new yy_state_type[YY_STATE_BUF_SIZE];",
+ "]],",
+ "[[",
+ " yy_state_buf = 0;",
+ "]])",
+ "}",
+ "",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " */",
+ "yyFlexLexer::~yyFlexLexer()",
+ "{",
+ " delete [] yy_state_buf;",
+ " yyfree( yy_start_stack M4_YY_CALL_LAST_ARG );",
+ " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);",
+ " yyfree( yy_buffer_stack M4_YY_CALL_LAST_ARG );",
+ "}",
+ "",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " */",
+ "void yyFlexLexer::switch_streams( std::istream& new_in, std::ostream& new_out )",
+ "{",
+ " // was if( new_in )",
+ " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);",
+ " yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE M4_YY_CALL_LAST_ARG) M4_YY_CALL_LAST_ARG);",
+ "",
+ " // was if( new_out )",
+ " yyout.rdbuf(new_out.rdbuf());",
+ "}",
+ "",
+ "/* The contents of this function are C++ specific, so the YY_G macro is not used.",
+ " */",
+ "void yyFlexLexer::switch_streams( std::istream* new_in, std::ostream* new_out )",
+ "{",
+ " if( ! new_in ) {",
+ " new_in = &yyin;",
+ " }",
+ "",
+ " if ( ! new_out ) {",
+ " new_out = &yyout;",
+ " }",
+ "",
+ " switch_streams(*new_in, *new_out);",
+ "}",
+ "",
+ "#ifdef YY_INTERACTIVE",
+ "int yyFlexLexer::LexerInput( char* buf, int /* max_size */ )",
+ "#else",
+ "int yyFlexLexer::LexerInput( char* buf, int max_size )",
+ "#endif",
+ "{",
+ " if ( yyin.eof() || yyin.fail() )",
+ " return 0;",
+ "",
+ "#ifdef YY_INTERACTIVE",
+ " yyin.get( buf[0] );",
+ "",
+ " if ( yyin.eof() )",
+ " return 0;",
+ "",
+ " if ( yyin.bad() )",
+ " return -1;",
+ "",
+ " return 1;",
+ "",
+ "#else",
+ " (void) yyin.read( buf, max_size );",
+ "",
+ " if ( yyin.bad() )",
+ " return -1;",
+ " else",
+ " return yyin.gcount();",
+ "#endif",
+ "}",
+ "",
+ "void yyFlexLexer::LexerOutput( const char* buf, int size )",
+ "{",
+ " (void) yyout.write( buf, size );",
+ "}",
+ "%ok-for-header",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/* yy_get_next_buffer - try to read in a new buffer",
+ " *",
+ " * Returns a code representing an action:",
+ " * EOB_ACT_LAST_MATCH -",
+ " * EOB_ACT_CONTINUE_SCAN - continue scanning from current position",
+ " * EOB_ACT_END_OF_FILE - end of file",
+ " */",
+ "%if-c-only",
+ "static int yy_get_next_buffer (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ "int yyFlexLexer::yy_get_next_buffer()",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;",
+ " char *source = YY_G(yytext_ptr);",
+ " int number_to_move, i;",
+ " int ret_val;",
+ "",
+ " if ( YY_G(yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] )",
+ " YY_FATAL_ERROR(",
+ " \"fatal flex scanner internal error--end of buffer missed\" );",
+ "",
+ " if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )",
+ " { /* Don't try to fill the buffer, so this is an EOF. */",
+ " if ( YY_G(yy_c_buf_p) - YY_G(yytext_ptr) - YY_MORE_ADJ == 1 )",
+ " {",
+ " /* We matched a single character, the EOB, so",
+ " * treat this as a final EOF.",
+ " */",
+ " return EOB_ACT_END_OF_FILE;",
+ " }",
+ "",
+ " else",
+ " {",
+ " /* We matched some text prior to the EOB, first",
+ " * process it.",
+ " */",
+ " return EOB_ACT_LAST_MATCH;",
+ " }",
+ " }",
+ "",
+ " /* Try to read more data. */",
+ "",
+ " /* First move last chars to start of buffer. */",
+ " number_to_move = (int) (YY_G(yy_c_buf_p) - YY_G(yytext_ptr) - 1);",
+ "",
+ " for ( i = 0; i < number_to_move; ++i )",
+ " *(dest++) = *(source++);",
+ "",
+ " if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )",
+ " /* don't do the read, it's not guaranteed to return an EOF,",
+ " * just force an EOF",
+ " */",
+ " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars) = 0;",
+ "",
+ " else",
+ " {",
+ " int num_to_read =",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;",
+ "",
+ " while ( num_to_read <= 0 )",
+ " { /* Not enough room in the buffer - grow it. */",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " YY_FATAL_ERROR(",
+ "\"input buffer overflow, can't enlarge buffer because scanner uses REJECT\" );",
+ "]],",
+ "[[",
+ " /* just a shorter name for the current buffer */",
+ " YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;",
+ "",
+ " int yy_c_buf_p_offset =",
+ " (int) (YY_G(yy_c_buf_p) - b->yy_ch_buf);",
+ "",
+ " if ( b->yy_is_our_buffer )",
+ " {",
+ " int new_size = b->yy_buf_size * 2;",
+ "",
+ " if ( new_size <= 0 )",
+ " b->yy_buf_size += b->yy_buf_size / 8;",
+ " else",
+ " b->yy_buf_size *= 2;",
+ "",
+ " b->yy_ch_buf = (char *)",
+ " /* Include room in for 2 EOB chars. */",
+ " yyrealloc( (void *) b->yy_ch_buf,",
+ " (yy_size_t) (b->yy_buf_size + 2) M4_YY_CALL_LAST_ARG );",
+ " }",
+ " else",
+ " /* Can't grow it, we don't own it. */",
+ " b->yy_ch_buf = NULL;",
+ "",
+ " if ( ! b->yy_ch_buf )",
+ " YY_FATAL_ERROR(",
+ " \"fatal error - scanner input buffer overflow\" );",
+ "",
+ " YY_G(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];",
+ "",
+ " num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -",
+ " number_to_move - 1;",
+ "]])",
+ " }",
+ "",
+ " if ( num_to_read > YY_READ_BUF_SIZE )",
+ " num_to_read = YY_READ_BUF_SIZE;",
+ "",
+ " /* Read in more data. */",
+ " YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),",
+ " YY_G(yy_n_chars), num_to_read );",
+ "",
+ " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);",
+ " }",
+ "",
+ " if ( YY_G(yy_n_chars) == 0 )",
+ " {",
+ " if ( number_to_move == YY_MORE_ADJ )",
+ " {",
+ " ret_val = EOB_ACT_END_OF_FILE;",
+ " yyrestart( yyin M4_YY_CALL_LAST_ARG);",
+ " }",
+ "",
+ " else",
+ " {",
+ " ret_val = EOB_ACT_LAST_MATCH;",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =",
+ " YY_BUFFER_EOF_PENDING;",
+ " }",
+ " }",
+ "",
+ " else",
+ " ret_val = EOB_ACT_CONTINUE_SCAN;",
+ "",
+ " if ((YY_G(yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {",
+ " /* Extend the array by 50%, plus the number we really need. */",
+ " int new_size = YY_G(yy_n_chars) + number_to_move + (YY_G(yy_n_chars) >> 1);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(",
+ " (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size M4_YY_CALL_LAST_ARG );",
+ " if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yy_get_next_buffer()\" );",
+ " /* \"- 2\" to take care of EOB's */",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);",
+ " }",
+ "",
+ " YY_G(yy_n_chars) += number_to_move;",
+ " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;",
+ " YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;",
+ "",
+ " YY_G(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];",
+ "",
+ " return ret_val;",
+ "}",
+ "]])",
+ "",
+ "/* yy_get_previous_state - get the state just before the EOB char was reached */",
+ "",
+ "%if-c-only",
+ "%not-for-header",
+ " static yy_state_type yy_get_previous_state (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ " yy_state_type yyFlexLexer::yy_get_previous_state()",
+ "%endif",
+ "{",
+ " yy_state_type yy_current_state;",
+ " char *yy_cp;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ "%% [15.0] code to get the start state into yy_current_state goes here",
+ "",
+ " for ( yy_cp = YY_G(yytext_ptr) + YY_MORE_ADJ; yy_cp < YY_G(yy_c_buf_p); ++yy_cp )",
+ " {",
+ "%% [16.0] code to find the next state goes here",
+ " }",
+ "",
+ " return yy_current_state;",
+ "}",
+ "",
+ "",
+ "/* yy_try_NUL_trans - try to make a transition on the NUL character",
+ " *",
+ " * synopsis",
+ " * next_state = yy_try_NUL_trans( current_state );",
+ " */",
+ "%if-c-only",
+ " static yy_state_type yy_try_NUL_trans YYFARGS1( yy_state_type, yy_current_state)",
+ "%endif",
+ "%if-c++-only",
+ " yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state )",
+ "%endif",
+ "{",
+ " int yy_is_jam;",
+ " M4_YY_DECL_GUTS_VAR(); /* This var may be unused depending upon options. */",
+ "%% [17.0] code to find the next state, and perhaps do backing up, goes here",
+ "",
+ " M4_YY_NOOP_GUTS_VAR();",
+ " return yy_is_jam ? 0 : yy_current_state;",
+ "}",
+ "",
+ "",
+ "#ifndef YY_NO_UNPUT",
+ "%if-c-only",
+ "m4_ifdef( [[M4_YY_NO_UNPUT]],,",
+ "[[",
+ " static void yyunput YYFARGS2( int,c, char *,yy_bp)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yyunput( int c, char* yy_bp)",
+ "%endif",
+ "{",
+ " char *yy_cp;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " yy_cp = YY_G(yy_c_buf_p);",
+ "",
+ " /* undo effects of setting up yytext */",
+ " *yy_cp = YY_G(yy_hold_char);",
+ "",
+ " if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )",
+ " { /* need to shift things up to make room */",
+ " /* +2 for EOB chars. */",
+ " int number_to_move = YY_G(yy_n_chars) + 2;",
+ " char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];",
+ " char *source =",
+ " &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];",
+ "",
+ " while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )",
+ " *--dest = *--source;",
+ "",
+ " yy_cp += (int) (dest - source);",
+ " yy_bp += (int) (dest - source);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_n_chars =",
+ " YY_G(yy_n_chars) = (int) YY_CURRENT_BUFFER_LVALUE->yy_buf_size;",
+ "",
+ " if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )",
+ " YY_FATAL_ERROR( \"flex scanner push-back overflow\" );",
+ " }",
+ "",
+ " *--yy_cp = (char) c;",
+ "",
+ "%% [18.0] update yylineno here",
+ "m4_ifdef( [[M4_YY_USE_LINENO]],",
+ "[[",
+ " if ( c == '\\n' ){",
+ " --yylineno;",
+ " }",
+ "]])",
+ "",
+ " YY_G(yytext_ptr) = yy_bp;",
+ " YY_G(yy_hold_char) = *yy_cp;",
+ " YY_G(yy_c_buf_p) = yy_cp;",
+ "}",
+ "%if-c-only",
+ "]])",
+ "%endif",
+ "#endif",
+ "",
+ "%if-c-only",
+ "#ifndef YY_NO_INPUT",
+ "#ifdef __cplusplus",
+ " static int yyinput (M4_YY_DEF_ONLY_ARG)",
+ "#else",
+ " static int input (M4_YY_DEF_ONLY_ARG)",
+ "#endif",
+ "",
+ "%endif",
+ "%if-c++-only",
+ " int yyFlexLexer::yyinput()",
+ "%endif",
+ "{",
+ " int c;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);",
+ "",
+ " if ( *YY_G(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )",
+ " {",
+ " /* yy_c_buf_p now points to the character we want to return.",
+ " * If this occurs *before* the EOB characters, then it's a",
+ " * valid NUL; if not, then we've hit the end of the buffer.",
+ " */",
+ " if ( YY_G(yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_G(yy_n_chars)] )",
+ " /* This was really a NUL. */",
+ " *YY_G(yy_c_buf_p) = '\\0';",
+ "",
+ " else",
+ " { /* need more input */",
+ " int offset = (int) (YY_G(yy_c_buf_p) - YY_G(yytext_ptr));",
+ " ++YY_G(yy_c_buf_p);",
+ "",
+ " switch ( yy_get_next_buffer( M4_YY_CALL_ONLY_ARG ) )",
+ " {",
+ " case EOB_ACT_LAST_MATCH:",
+ " /* This happens because yy_g_n_b()",
+ " * sees that we've accumulated a",
+ " * token and flags that we need to",
+ " * try matching the token before",
+ " * proceeding. But for input(),",
+ " * there's no matching to consider.",
+ " * So convert the EOB_ACT_LAST_MATCH",
+ " * to EOB_ACT_END_OF_FILE.",
+ " */",
+ "",
+ " /* Reset buffer status. */",
+ " yyrestart( yyin M4_YY_CALL_LAST_ARG);",
+ "",
+ " /*FALLTHROUGH*/",
+ "",
+ " case EOB_ACT_END_OF_FILE:",
+ " {",
+ " if ( yywrap( M4_YY_CALL_ONLY_ARG ) )",
+ "#ifdef YY_FLEX_LEX_COMPAT",
+ " return 0;",
+ "#else",
+ " return EOF;",
+ "#endif",
+ "",
+ " if ( ! YY_G(yy_did_buffer_switch_on_eof) )",
+ " YY_NEW_FILE;",
+ "#ifdef __cplusplus",
+ " return yyinput(M4_YY_CALL_ONLY_ARG);",
+ "#else",
+ " return input(M4_YY_CALL_ONLY_ARG);",
+ "#endif",
+ " }",
+ "",
+ " case EOB_ACT_CONTINUE_SCAN:",
+ " YY_G(yy_c_buf_p) = YY_G(yytext_ptr) + offset;",
+ " break;",
+ " }",
+ " }",
+ " }",
+ "",
+ " c = *(unsigned char *) YY_G(yy_c_buf_p); /* cast for 8-bit char's */",
+ " *YY_G(yy_c_buf_p) = '\\0'; /* preserve yytext */",
+ " YY_G(yy_hold_char) = *++YY_G(yy_c_buf_p);",
+ "",
+ "%% [19.0] update BOL and yylineno",
+ "",
+ " return c;",
+ "}",
+ "%if-c-only",
+ "#endif /* ifndef YY_NO_INPUT */",
+ "%endif",
+ "",
+ "/** Immediately switch to a different input stream.",
+ " * @param input_file A readable stream.",
+ " * M4_YY_DOC_PARAM",
+ " * @note This function does not reset the start condition to @c INITIAL .",
+ " */",
+ "%if-c-only",
+ " void yyrestart YYFARGS1( FILE *,input_file)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yyrestart( std::istream& input_file )",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " if ( ! YY_CURRENT_BUFFER ){",
+ " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);",
+ " YY_CURRENT_BUFFER_LVALUE =",
+ " yy_create_buffer( yyin, YY_BUF_SIZE M4_YY_CALL_LAST_ARG);",
+ " }",
+ "",
+ " yy_init_buffer( YY_CURRENT_BUFFER, input_file M4_YY_CALL_LAST_ARG);",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ "}",
+ "",
+ "%if-c++-only",
+ "/** Delegate to the new version that takes an istream reference.",
+ " * @param input_file A readable stream.",
+ " * M4_YY_DOC_PARAM",
+ " * @note This function does not reset the start condition to @c INITIAL .",
+ " */",
+ "void yyFlexLexer::yyrestart( std::istream* input_file )",
+ "{",
+ " if( ! input_file ) {",
+ " input_file = &yyin;",
+ " }",
+ " yyrestart( *input_file );",
+ "}",
+ "%endif",
+ "",
+ "/** Switch to a different input buffer.",
+ " * @param new_buffer The new input buffer.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "%if-c-only",
+ " void yy_switch_to_buffer YYFARGS1( YY_BUFFER_STATE ,new_buffer)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " /* TODO. We should be able to replace this entire function body",
+ " * with",
+ " * yypop_buffer_state();",
+ " * yypush_buffer_state(new_buffer);",
+ " */",
+ " yyensure_buffer_stack (M4_YY_CALL_ONLY_ARG);",
+ " if ( YY_CURRENT_BUFFER == new_buffer )",
+ " return;",
+ "",
+ " if ( YY_CURRENT_BUFFER )",
+ " {",
+ " /* Flush out information for old buffer. */",
+ " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);",
+ " }",
+ "",
+ " YY_CURRENT_BUFFER_LVALUE = new_buffer;",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ "",
+ " /* We don't actually know whether we did this switch during",
+ " * EOF (yywrap()) processing, but the only time this flag",
+ " * is looked at is after yywrap() is called, so it's safe",
+ " * to go ahead and always set it.",
+ " */",
+ " YY_G(yy_did_buffer_switch_on_eof) = 1;",
+ "}",
+ "",
+ "",
+ "%if-c-only",
+ "static void yy_load_buffer_state (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_load_buffer_state()",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " YY_G(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;",
+ " YY_G(yytext_ptr) = YY_G(yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;",
+ "%if-c-only",
+ " yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;",
+ "%endif",
+ "%if-c++-only",
+ " yyin.rdbuf(YY_CURRENT_BUFFER_LVALUE->yy_input_file);",
+ "%endif",
+ " YY_G(yy_hold_char) = *YY_G(yy_c_buf_p);",
+ "}",
+ "",
+ "/** Allocate and initialize an input buffer state.",
+ " * @param file A readable stream.",
+ " * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.",
+ " * M4_YY_DOC_PARAM",
+ " * @return the allocated buffer state.",
+ " */",
+ "%if-c-only",
+ " YY_BUFFER_STATE yy_create_buffer YYFARGS2( FILE *,file, int ,size)",
+ "%endif",
+ "%if-c++-only",
+ " YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream& file, int size )",
+ "%endif",
+ "{",
+ " YY_BUFFER_STATE b;",
+ " m4_dnl M4_YY_DECL_GUTS_VAR();",
+ "",
+ " b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG );",
+ " if ( ! b )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );",
+ "",
+ " b->yy_buf_size = size;",
+ "",
+ " /* yy_ch_buf has to be 2 characters longer than the size given because",
+ " * we need to put in 2 end-of-buffer characters.",
+ " */",
+ " b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) M4_YY_CALL_LAST_ARG );",
+ " if ( ! b->yy_ch_buf )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );",
+ "",
+ " b->yy_is_our_buffer = 1;",
+ "",
+ " yy_init_buffer( b, file M4_YY_CALL_LAST_ARG);",
+ "",
+ " return b;",
+ "}",
+ "",
+ "%if-c++-only",
+ "/** Delegate creation of buffers to the new version that takes an istream reference.",
+ " * @param file A readable stream.",
+ " * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.",
+ " * M4_YY_DOC_PARAM",
+ " * @return the allocated buffer state.",
+ " */",
+ " YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( std::istream* file, int size )",
+ "{",
+ " return yy_create_buffer( *file, size );",
+ "}",
+ "%endif",
+ "",
+ "/** Destroy the buffer.",
+ " * @param b a buffer created with yy_create_buffer()",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "%if-c-only",
+ " void yy_delete_buffer YYFARGS1( YY_BUFFER_STATE ,b)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b )",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " if ( ! b )",
+ " return;",
+ "",
+ " if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */",
+ " YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;",
+ "",
+ " if ( b->yy_is_our_buffer )",
+ " yyfree( (void *) b->yy_ch_buf M4_YY_CALL_LAST_ARG );",
+ "",
+ " yyfree( (void *) b M4_YY_CALL_LAST_ARG );",
+ "}",
+ "",
+ "",
+ "/* Initializes or reinitializes a buffer.",
+ " * This function is sometimes called more than once on the same buffer,",
+ " * such as during a yyrestart() or at EOF.",
+ " */",
+ "%if-c-only",
+ " static void yy_init_buffer YYFARGS2( YY_BUFFER_STATE ,b, FILE *,file)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, std::istream& file )",
+ "%endif",
+ "",
+ "{",
+ " int oerrno = errno;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " yy_flush_buffer( b M4_YY_CALL_LAST_ARG);",
+ "",
+ "%if-c-only",
+ " b->yy_input_file = file;",
+ "%endif",
+ "%if-c++-only",
+ " b->yy_input_file = file.rdbuf();",
+ "%endif",
+ " b->yy_fill_buffer = 1;",
+ "",
+ " /* If b is the current buffer, then yy_init_buffer was _probably_",
+ " * called from yyrestart() or through yy_get_next_buffer.",
+ " * In that case, we don't want to reset the lineno or column.",
+ " */",
+ " if (b != YY_CURRENT_BUFFER){",
+ " b->yy_bs_lineno = 1;",
+ " b->yy_bs_column = 0;",
+ " }",
+ "",
+ "%if-c-only",
+ "m4_ifdef( [[M4_YY_ALWAYS_INTERACTIVE]],",
+ "[[",
+ " b->yy_is_interactive = 1;",
+ "]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NEVER_INTERACTIVE]],",
+ " [[",
+ " b->yy_is_interactive = 0;",
+ " ]],",
+ " [[",
+ " b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;",
+ " ]])",
+ "]])",
+ "%endif",
+ "%if-c++-only",
+ " b->yy_is_interactive = 0;",
+ "%endif",
+ " errno = oerrno;",
+ "}",
+ "",
+ "/** Discard all buffered characters. On the next scan, YY_INPUT will be called.",
+ " * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "%if-c-only",
+ " void yy_flush_buffer YYFARGS1( YY_BUFFER_STATE ,b)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b )",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " if ( ! b )",
+ " return;",
+ "",
+ " b->yy_n_chars = 0;",
+ "",
+ " /* We always need two end-of-buffer characters. The first causes",
+ " * a transition to the end-of-buffer state. The second causes",
+ " * a jam in that state.",
+ " */",
+ " b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;",
+ " b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;",
+ "",
+ " b->yy_buf_pos = &b->yy_ch_buf[0];",
+ "",
+ " b->yy_at_bol = 1;",
+ " b->yy_buffer_status = YY_BUFFER_NEW;",
+ "",
+ " if ( b == YY_CURRENT_BUFFER )",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ "}",
+ "",
+ "%if-c-or-c++",
+ "/** Pushes the new state onto the stack. The new state becomes",
+ " * the current state. This function will allocate the stack",
+ " * if necessary.",
+ " * @param new_buffer The new state.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "%if-c-only",
+ "void yypush_buffer_state YYFARGS1(YY_BUFFER_STATE,new_buffer)",
+ "%endif",
+ "%if-c++-only",
+ "void yyFlexLexer::yypush_buffer_state (YY_BUFFER_STATE new_buffer)",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " if (new_buffer == NULL)",
+ " return;",
+ "",
+ " yyensure_buffer_stack(M4_YY_CALL_ONLY_ARG);",
+ "",
+ " /* This block is copied from yy_switch_to_buffer. */",
+ " if ( YY_CURRENT_BUFFER )",
+ " {",
+ " /* Flush out information for old buffer. */",
+ " *YY_G(yy_c_buf_p) = YY_G(yy_hold_char);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = YY_G(yy_c_buf_p);",
+ " YY_CURRENT_BUFFER_LVALUE->yy_n_chars = YY_G(yy_n_chars);",
+ " }",
+ "",
+ " /* Only push if top exists. Otherwise, replace top. */",
+ " if (YY_CURRENT_BUFFER)",
+ " YY_G(yy_buffer_stack_top)++;",
+ " YY_CURRENT_BUFFER_LVALUE = new_buffer;",
+ "",
+ " /* copied from yy_switch_to_buffer. */",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ " YY_G(yy_did_buffer_switch_on_eof) = 1;",
+ "}",
+ "%endif",
+ "",
+ "",
+ "%if-c-or-c++",
+ "/** Removes and deletes the top of the stack, if present.",
+ " * The next element becomes the new top.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "%if-c-only",
+ "void yypop_buffer_state (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ "void yyFlexLexer::yypop_buffer_state (void)",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " if (!YY_CURRENT_BUFFER)",
+ " return;",
+ "",
+ " yy_delete_buffer(YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG);",
+ " YY_CURRENT_BUFFER_LVALUE = NULL;",
+ " if (YY_G(yy_buffer_stack_top) > 0)",
+ " --YY_G(yy_buffer_stack_top);",
+ "",
+ " if (YY_CURRENT_BUFFER) {",
+ " yy_load_buffer_state( M4_YY_CALL_ONLY_ARG );",
+ " YY_G(yy_did_buffer_switch_on_eof) = 1;",
+ " }",
+ "}",
+ "%endif",
+ "",
+ "",
+ "%if-c-or-c++",
+ "/* Allocates the stack if it does not exist.",
+ " * Guarantees space for at least one push.",
+ " */",
+ "%if-c-only",
+ "static void yyensure_buffer_stack (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ "void yyFlexLexer::yyensure_buffer_stack(void)",
+ "%endif",
+ "{",
+ " yy_size_t num_to_alloc;",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " if (!YY_G(yy_buffer_stack)) {",
+ "",
+ " /* First allocation is just for 2 elements, since we don't know if this",
+ " * scanner will even need a stack. We use 2 instead of 1 to avoid an",
+ " * immediate realloc on the next call.",
+ " */",
+ " num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */",
+ " YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc",
+ " (num_to_alloc * sizeof(struct yy_buffer_state*)",
+ " M4_YY_CALL_LAST_ARG);",
+ " if ( ! YY_G(yy_buffer_stack) )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );",
+ "",
+ "",
+ " memset(YY_G(yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));",
+ "",
+ " YY_G(yy_buffer_stack_max) = num_to_alloc;",
+ " YY_G(yy_buffer_stack_top) = 0;",
+ " return;",
+ " }",
+ "",
+ " if (YY_G(yy_buffer_stack_top) >= (YY_G(yy_buffer_stack_max)) - 1){",
+ "",
+ " /* Increase the buffer to prepare for a possible push. */",
+ " yy_size_t grow_size = 8 /* arbitrary grow size */;",
+ "",
+ " num_to_alloc = YY_G(yy_buffer_stack_max) + grow_size;",
+ " YY_G(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc",
+ " (YY_G(yy_buffer_stack),",
+ " num_to_alloc * sizeof(struct yy_buffer_state*)",
+ " M4_YY_CALL_LAST_ARG);",
+ " if ( ! YY_G(yy_buffer_stack) )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );",
+ "",
+ " /* zero only the new slots.*/",
+ " memset(YY_G(yy_buffer_stack) + YY_G(yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));",
+ " YY_G(yy_buffer_stack_max) = num_to_alloc;",
+ " }",
+ "}",
+ "%endif",
+ "",
+ "",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SCAN_BUFFER]],,",
+ "[[",
+ "%if-c-only",
+ "/** Setup the input buffer state to scan directly from a user-specified character buffer.",
+ " * @param base the character buffer",
+ " * @param size the size in bytes of the character buffer",
+ " * M4_YY_DOC_PARAM",
+ " * @return the newly allocated buffer state object.",
+ " */",
+ "YY_BUFFER_STATE yy_scan_buffer YYFARGS2( char *,base, yy_size_t ,size)",
+ "{",
+ " YY_BUFFER_STATE b;",
+ " m4_dnl M4_YY_DECL_GUTS_VAR();",
+ "",
+ " if ( size < 2 ||",
+ " base[size-2] != YY_END_OF_BUFFER_CHAR ||",
+ " base[size-1] != YY_END_OF_BUFFER_CHAR )",
+ " /* They forgot to leave room for the EOB's. */",
+ " return NULL;",
+ "",
+ " b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) M4_YY_CALL_LAST_ARG );",
+ " if ( ! b )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yy_scan_buffer()\" );",
+ "",
+ " b->yy_buf_size = (int) (size - 2); /* \"- 2\" to take care of EOB's */",
+ " b->yy_buf_pos = b->yy_ch_buf = base;",
+ " b->yy_is_our_buffer = 0;",
+ " b->yy_input_file = NULL;",
+ " b->yy_n_chars = b->yy_buf_size;",
+ " b->yy_is_interactive = 0;",
+ " b->yy_at_bol = 1;",
+ " b->yy_fill_buffer = 0;",
+ " b->yy_buffer_status = YY_BUFFER_NEW;",
+ "",
+ " yy_switch_to_buffer( b M4_YY_CALL_LAST_ARG );",
+ "",
+ " return b;",
+ "}",
+ "%endif",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SCAN_STRING]],,",
+ "[[",
+ "%if-c-only",
+ "/** Setup the input buffer state to scan a string. The next call to yylex() will",
+ " * scan from a @e copy of @a str.",
+ " * @param yystr a NUL-terminated string to scan",
+ " * M4_YY_DOC_PARAM",
+ " * @return the newly allocated buffer state object.",
+ " * @note If you want to scan bytes that may contain NUL values, then use",
+ " * yy_scan_bytes() instead.",
+ " */",
+ "YY_BUFFER_STATE yy_scan_string YYFARGS1( const char *, yystr)",
+ "{",
+ " m4_dnl M4_YY_DECL_GUTS_VAR();",
+ "",
+ " return yy_scan_bytes( yystr, (int) strlen(yystr) M4_YY_CALL_LAST_ARG);",
+ "}",
+ "%endif",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SCAN_BYTES]],,",
+ "[[",
+ "%if-c-only",
+ "/** Setup the input buffer state to scan the given bytes. The next call to yylex() will",
+ " * scan from a @e copy of @a bytes.",
+ " * @param yybytes the byte buffer to scan",
+ " * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.",
+ " * M4_YY_DOC_PARAM",
+ " * @return the newly allocated buffer state object.",
+ " */",
+ "YY_BUFFER_STATE yy_scan_bytes YYFARGS2( const char *,yybytes, int ,_yybytes_len)",
+ "{",
+ " YY_BUFFER_STATE b;",
+ " char *buf;",
+ " yy_size_t n;",
+ " int i;",
+ " m4_dnl M4_YY_DECL_GUTS_VAR();",
+ "",
+ " /* Get memory for full buffer, including space for trailing EOB's. */",
+ " n = (yy_size_t) (_yybytes_len + 2);",
+ " buf = (char *) yyalloc( n M4_YY_CALL_LAST_ARG );",
+ " if ( ! buf )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yy_scan_bytes()\" );",
+ "",
+ " for ( i = 0; i < _yybytes_len; ++i )",
+ " buf[i] = yybytes[i];",
+ "",
+ " buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;",
+ "",
+ " b = yy_scan_buffer( buf, n M4_YY_CALL_LAST_ARG);",
+ " if ( ! b )",
+ " YY_FATAL_ERROR( \"bad buffer in yy_scan_bytes()\" );",
+ "",
+ " /* It's okay to grow etc. this buffer, and we should throw it",
+ " * away when we're done.",
+ " */",
+ " b->yy_is_our_buffer = 1;",
+ "",
+ " return b;",
+ "}",
+ "%endif",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_PUSH_STATE]],,",
+ "[[",
+ "%if-c-only",
+ " static void yy_push_state YYFARGS1( int ,_new_state)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_push_state( int _new_state )",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " if ( YY_G(yy_start_stack_ptr) >= YY_G(yy_start_stack_depth) )",
+ " {",
+ " yy_size_t new_size;",
+ "",
+ " YY_G(yy_start_stack_depth) += YY_START_STACK_INCR;",
+ " new_size = (yy_size_t) YY_G(yy_start_stack_depth) * sizeof( int );",
+ "",
+ " if ( ! YY_G(yy_start_stack) )",
+ " YY_G(yy_start_stack) = (int *) yyalloc( new_size M4_YY_CALL_LAST_ARG );",
+ "",
+ " else",
+ " YY_G(yy_start_stack) = (int *) yyrealloc(",
+ " (void *) YY_G(yy_start_stack), new_size M4_YY_CALL_LAST_ARG );",
+ "",
+ " if ( ! YY_G(yy_start_stack) )",
+ " YY_FATAL_ERROR( \"out of memory expanding start-condition stack\" );",
+ " }",
+ "",
+ " YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)++] = YY_START;",
+ "",
+ " BEGIN(_new_state);",
+ "}",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_POP_STATE]],,",
+ "[[",
+ "%if-c-only",
+ " static void yy_pop_state (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ " void yyFlexLexer::yy_pop_state()",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " if ( --YY_G(yy_start_stack_ptr) < 0 )",
+ " YY_FATAL_ERROR( \"start-condition stack underflow\" );",
+ "",
+ " BEGIN(YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr)]);",
+ "}",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_TOP_STATE]],,",
+ "[[",
+ "%if-c-only",
+ " static int yy_top_state (M4_YY_DEF_ONLY_ARG)",
+ "%endif",
+ "%if-c++-only",
+ " int yyFlexLexer::yy_top_state()",
+ "%endif",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return YY_G(yy_start_stack)[YY_G(yy_start_stack_ptr) - 1];",
+ "}",
+ "]])",
+ "",
+ "#ifndef YY_EXIT_FAILURE",
+ "#define YY_EXIT_FAILURE 2",
+ "#endif",
+ "",
+ "%if-c-only",
+ "static void yynoreturn yy_fatal_error YYFARGS1(const char*, msg)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ " fprintf( stderr, \"%s\\n\", msg );",
+ " exit( YY_EXIT_FAILURE );",
+ "}",
+ "%endif",
+ "%if-c++-only",
+ "void yyFlexLexer::LexerError( const char* msg )",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " std::cerr << msg << std::endl;",
+ " exit( YY_EXIT_FAILURE );",
+ "}",
+ "%endif",
+ "",
+ "/* Redefine yyless() so it works in section 3 code. */",
+ "",
+ "#undef yyless",
+ "#define yyless(n) \\",
+ " do \\",
+ " { \\",
+ " /* Undo effects of setting up yytext. */ \\",
+ " int yyless_macro_arg = (n); \\",
+ " YY_LESS_LINENO(yyless_macro_arg);\\",
+ " yytext[yyleng] = YY_G(yy_hold_char); \\",
+ " YY_G(yy_c_buf_p) = yytext + yyless_macro_arg; \\",
+ " YY_G(yy_hold_char) = *YY_G(yy_c_buf_p); \\",
+ " *YY_G(yy_c_buf_p) = '\\0'; \\",
+ " yyleng = yyless_macro_arg; \\",
+ " } \\",
+ " while ( 0 )",
+ "",
+ "",
+ "",
+ "/* Accessor methods (get/set functions) to struct members. */",
+ "",
+ "%if-c-only",
+ "%if-reentrant",
+ "m4_ifdef( [[M4_YY_NO_GET_EXTRA]],,",
+ "[[",
+ "/** Get the user-defined data for this scanner.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "YY_EXTRA_TYPE yyget_extra (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yyextra;",
+ "}",
+ "]])",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_LINENO]],,",
+ "[[",
+ "/** Get the current line number.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "int yyget_lineno (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " m4_ifdef( [[M4_YY_REENTRANT]],",
+ " [[",
+ " if (! YY_CURRENT_BUFFER)",
+ " return 0;",
+ " ]])",
+ " return yylineno;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_REENTRANT]],",
+ "[[",
+ "m4_ifdef( [[M4_YY_NO_GET_COLUMN]],,",
+ "[[",
+ "/** Get the current column number.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "int yyget_column (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " m4_ifdef( [[M4_YY_REENTRANT]],",
+ " [[",
+ " if (! YY_CURRENT_BUFFER)",
+ " return 0;",
+ " ]])",
+ " return yycolumn;",
+ "}",
+ "]])",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_IN]],,",
+ "[[",
+ "/** Get the input stream.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "FILE *yyget_in (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yyin;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_OUT]],,",
+ "[[",
+ "/** Get the output stream.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "FILE *yyget_out (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yyout;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_LENG]],,",
+ "[[",
+ "/** Get the length of the current token.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "int yyget_leng (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yyleng;",
+ "}",
+ "]])",
+ "",
+ "/** Get the current token.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "m4_ifdef( [[M4_YY_NO_GET_TEXT]],,",
+ "[[",
+ "char *yyget_text (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yytext;",
+ "}",
+ "]])",
+ "",
+ "%if-reentrant",
+ "m4_ifdef( [[M4_YY_NO_SET_EXTRA]],,",
+ "[[",
+ "/** Set the user-defined data. This data is never touched by the scanner.",
+ " * @param user_defined The data to be associated with this scanner.",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "void yyset_extra YYFARGS1( YY_EXTRA_TYPE ,user_defined)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yyextra = user_defined ;",
+ "}",
+ "]])",
+ "%endif",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_LINENO]],,",
+ "[[",
+ "/** Set the current line number.",
+ " * @param _line_number line number",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "void yyset_lineno YYFARGS1( int ,_line_number)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " m4_ifdef( [[M4_YY_REENTRANT]],",
+ " [[",
+ " /* lineno is only valid if an input buffer exists. */",
+ " if (! YY_CURRENT_BUFFER )",
+ " YY_FATAL_ERROR( \"yyset_lineno called with no buffer\" );",
+ " ]])",
+ " yylineno = _line_number;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_REENTRANT]],",
+ "[[",
+ "m4_ifdef( [[M4_YY_NO_SET_COLUMN]],,",
+ "[[",
+ "/** Set the current column.",
+ " * @param _column_no column number",
+ " * M4_YY_DOC_PARAM",
+ " */",
+ "void yyset_column YYFARGS1( int , _column_no)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " m4_ifdef( [[M4_YY_REENTRANT]],",
+ " [[",
+ " /* column is only valid if an input buffer exists. */",
+ " if (! YY_CURRENT_BUFFER )",
+ " YY_FATAL_ERROR( \"yyset_column called with no buffer\" );",
+ " ]])",
+ " yycolumn = _column_no;",
+ "}",
+ "]])",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_IN]],,",
+ "[[",
+ "/** Set the input stream. This does not discard the current",
+ " * input buffer.",
+ " * @param _in_str A readable stream.",
+ " * M4_YY_DOC_PARAM",
+ " * @see yy_switch_to_buffer",
+ " */",
+ "void yyset_in YYFARGS1( FILE * ,_in_str)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yyin = _in_str ;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_OUT]],,",
+ "[[",
+ "void yyset_out YYFARGS1( FILE * ,_out_str)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yyout = _out_str ;",
+ "}",
+ "]])",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NO_GET_DEBUG]],,",
+ "[[",
+ "int yyget_debug (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yy_flex_debug;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_DEBUG]],,",
+ "[[",
+ "void yyset_debug YYFARGS1( int ,_bdebug)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yy_flex_debug = _bdebug ;",
+ "}",
+ "]])",
+ "%endif",
+ "",
+ "%if-reentrant",
+ "/* Accessor methods for yylval and yylloc */",
+ "",
+ "%if-bison-bridge",
+ "m4_ifdef( [[M4_YY_NO_GET_LVAL]],,",
+ "[[",
+ "YYSTYPE * yyget_lval (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yylval;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_SET_LVAL]],,",
+ "[[",
+ "void yyset_lval YYFARGS1( YYSTYPE * ,yylval_param)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yylval = yylval_param;",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[<M4_YY_BISON_LLOC>]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NO_GET_LLOC]],,",
+ " [[",
+ "YYLTYPE *yyget_lloc (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " return yylloc;",
+ "}",
+ " ]])",
+ "",
+ " m4_ifdef( [[M4_YY_NO_SET_LLOC]],,",
+ " [[",
+ "void yyset_lloc YYFARGS1( YYLTYPE * ,yylloc_param)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " yylloc = yylloc_param;",
+ "}",
+ " ]])",
+ "]])",
+ "",
+ "%endif",
+ "",
+ "",
+ "/* User-visible API */",
+ "",
+ "/* yylex_init is special because it creates the scanner itself, so it is",
+ " * the ONLY reentrant function that doesn't take the scanner as the last argument.",
+ " * That's why we explicitly handle the declaration, instead of using our macros.",
+ " */",
+ "int yylex_init(yyscan_t* ptr_yy_globals)",
+ "{",
+ " if (ptr_yy_globals == NULL){",
+ " errno = EINVAL;",
+ " return 1;",
+ " }",
+ "",
+ " *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );",
+ "",
+ " if (*ptr_yy_globals == NULL){",
+ " errno = ENOMEM;",
+ " return 1;",
+ " }",
+ "",
+ " /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */",
+ " memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));",
+ "",
+ " return yy_init_globals ( *ptr_yy_globals );",
+ "}",
+ "",
+ "",
+ "/* yylex_init_extra has the same functionality as yylex_init, but follows the",
+ " * convention of taking the scanner as the last argument. Note however, that",
+ " * this is a *pointer* to a scanner, as it will be allocated by this call (and",
+ " * is the reason, too, why this function also must handle its own declaration).",
+ " * The user defined value in the first argument will be available to yyalloc in",
+ " * the yyextra field.",
+ " */",
+ "int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals )",
+ "{",
+ " struct yyguts_t dummy_yyguts;",
+ "",
+ " yyset_extra (yy_user_defined, &dummy_yyguts);",
+ "",
+ " if (ptr_yy_globals == NULL){",
+ " errno = EINVAL;",
+ " return 1;",
+ " }",
+ "",
+ " *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );",
+ "",
+ " if (*ptr_yy_globals == NULL){",
+ " errno = ENOMEM;",
+ " return 1;",
+ " }",
+ "",
+ " /* By setting to 0xAA, we expose bugs in",
+ " yy_init_globals. Leave at 0x00 for releases. */",
+ " memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));",
+ "",
+ " yyset_extra (yy_user_defined, *ptr_yy_globals);",
+ "",
+ " return yy_init_globals ( *ptr_yy_globals );",
+ "}",
+ "",
+ "%endif if-c-only",
+ "",
+ "%if-c-only",
+ "static int yy_init_globals (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " /* Initialization is the same as for the non-reentrant scanner.",
+ " * This function is called from yylex_destroy(), so don't allocate here.",
+ " */",
+ "",
+ "m4_ifdef( [[M4_YY_USE_LINENO]],",
+ "[[",
+ " m4_ifdef( [[M4_YY_NOT_REENTRANT]],",
+ " [[",
+ " /* We do not touch yylineno unless the option is enabled. */",
+ " yylineno = 1;",
+ " ]])",
+ "]])",
+ " YY_G(yy_buffer_stack) = NULL;",
+ " YY_G(yy_buffer_stack_top) = 0;",
+ " YY_G(yy_buffer_stack_max) = 0;",
+ " YY_G(yy_c_buf_p) = NULL;",
+ " YY_G(yy_init) = 0;",
+ " YY_G(yy_start) = 0;",
+ "",
+ "m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]],",
+ "[[",
+ " YY_G(yy_start_stack_ptr) = 0;",
+ " YY_G(yy_start_stack_depth) = 0;",
+ " YY_G(yy_start_stack) = NULL;",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " YY_G(yy_state_buf) = 0;",
+ " YY_G(yy_state_ptr) = 0;",
+ " YY_G(yy_full_match) = 0;",
+ " YY_G(yy_lp) = 0;",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_TEXT_IS_ARRAY]],",
+ "[[",
+ " YY_G(yytext_ptr) = 0;",
+ " YY_G(yy_more_offset) = 0;",
+ " YY_G(yy_prev_more_offset) = 0;",
+ "]])",
+ "",
+ "/* Defined in main.c */",
+ "#ifdef YY_STDINIT",
+ " yyin = stdin;",
+ " yyout = stdout;",
+ "#else",
+ " yyin = NULL;",
+ " yyout = NULL;",
+ "#endif",
+ "",
+ " /* For future reference: Set errno on error, since we are called by",
+ " * yylex_init()",
+ " */",
+ " return 0;",
+ "}",
+ "%endif",
+ "",
+ "",
+ "%if-c-only SNIP! this currently causes conflicts with the c++ scanner",
+ "/* yylex_destroy is for both reentrant and non-reentrant scanners. */",
+ "int yylex_destroy (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ "",
+ " /* Pop the buffer stack, destroying each element. */",
+ " while(YY_CURRENT_BUFFER){",
+ " yy_delete_buffer( YY_CURRENT_BUFFER M4_YY_CALL_LAST_ARG );",
+ " YY_CURRENT_BUFFER_LVALUE = NULL;",
+ " yypop_buffer_state(M4_YY_CALL_ONLY_ARG);",
+ " }",
+ "",
+ " /* Destroy the stack itself. */",
+ " yyfree(YY_G(yy_buffer_stack) M4_YY_CALL_LAST_ARG);",
+ " YY_G(yy_buffer_stack) = NULL;",
+ "",
+ "m4_ifdef( [[M4_YY_HAS_START_STACK_VARS]],",
+ "[[",
+ " /* Destroy the start condition stack. */",
+ " yyfree( YY_G(yy_start_stack) M4_YY_CALL_LAST_ARG );",
+ " YY_G(yy_start_stack) = NULL;",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_USES_REJECT]],",
+ "[[",
+ " yyfree ( YY_G(yy_state_buf) M4_YY_CALL_LAST_ARG);",
+ " YY_G(yy_state_buf) = NULL;",
+ "]])",
+ "",
+ " /* Reset the globals. This is important in a non-reentrant scanner so the next time",
+ " * yylex() is called, initialization will occur. */",
+ " yy_init_globals( M4_YY_CALL_ONLY_ARG);",
+ "",
+ "%if-reentrant",
+ " /* Destroy the main struct (reentrant only). */",
+ " yyfree ( yyscanner M4_YY_CALL_LAST_ARG );",
+ " yyscanner = NULL;",
+ "%endif",
+ " return 0;",
+ "}",
+ "%endif",
+ "",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "/*",
+ " * Internal utility routines.",
+ " */",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "#ifndef yytext_ptr",
+ "static void yy_flex_strncpy YYFARGS3( char*,s1, const char *,s2, int,n)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ "",
+ " int i;",
+ " for ( i = 0; i < n; ++i )",
+ " s1[i] = s2[i];",
+ "}",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NOT_IN_HEADER]],",
+ "[[",
+ "#ifdef YY_NEED_STRLEN",
+ "static int yy_flex_strlen YYFARGS1( const char *,s)",
+ "{",
+ " int n;",
+ " for ( n = 0; s[n]; ++n )",
+ " ;",
+ "",
+ " return n;",
+ "}",
+ "#endif",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_FLEX_ALLOC]],,",
+ "[[",
+ "void *yyalloc YYFARGS1( yy_size_t ,size)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ " return malloc(size);",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_FLEX_REALLOC]],,",
+ "[[",
+ "void *yyrealloc YYFARGS2( void *,ptr, yy_size_t ,size)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ "",
+ " /* The cast to (char *) in the following accommodates both",
+ " * implementations that use char* generic pointers, and those",
+ " * that use void* generic pointers. It works with the latter",
+ " * because both ANSI C and C++ allow castless assignment from",
+ " * any pointer type to void*, and deal with argument conversions",
+ " * as though doing an assignment.",
+ " */",
+ " return realloc(ptr, size);",
+ "}",
+ "]])",
+ "",
+ "m4_ifdef( [[M4_YY_NO_FLEX_FREE]],,",
+ "[[",
+ "void yyfree YYFARGS1( void *,ptr)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ " free( (char *) ptr ); /* see yyrealloc() for (char *) cast */",
+ "}",
+ "]])",
+ "",
+ "%if-tables-serialization definitions",
+ "#ifdef FLEX_SCANNER",
+ "/*",
+ "dnl tables_shared.c - tables serialization code",
+ "dnl ",
+ "dnl Copyright (c) 1990 The Regents of the University of California.",
+ "dnl All rights reserved.",
+ "dnl ",
+ "dnl This code is derived from software contributed to Berkeley by",
+ "dnl Vern Paxson.",
+ "dnl ",
+ "dnl The United States Government has rights in this work pursuant",
+ "dnl to contract no. DE-AC03-76SF00098 between the United States",
+ "dnl Department of Energy and the University of California.",
+ "dnl ",
+ "dnl This file is part of flex.",
+ "dnl ",
+ "dnl Redistribution and use in source and binary forms, with or without",
+ "dnl modification, are permitted provided that the following conditions",
+ "dnl are met:",
+ "dnl ",
+ "dnl 1. Redistributions of source code must retain the above copyright",
+ "dnl notice, this list of conditions and the following disclaimer.",
+ "dnl 2. Redistributions in binary form must reproduce the above copyright",
+ "dnl notice, this list of conditions and the following disclaimer in the",
+ "dnl documentation and/or other materials provided with the distribution.",
+ "dnl ",
+ "dnl Neither the name of the University nor the names of its contributors",
+ "dnl may be used to endorse or promote products derived from this software",
+ "dnl without specific prior written permission.",
+ "dnl ",
+ "dnl THIS SOFTWARE IS PROVIDED `AS IS' AND WITHOUT ANY EXPRESS OR",
+ "dnl IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED",
+ "dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR",
+ "dnl PURPOSE.",
+ "dnl ",
+ "*/",
+ " ",
+ "/* This file is meant to be included in both the skeleton and the actual",
+ " * flex code (hence the name \"_shared\"). ",
+ " */",
+ "#ifndef yyskel_static",
+ "#define yyskel_static static",
+ "#endif",
+ "#else",
+ "#include \"flexdef.h\"",
+ "#include \"tables.h\"",
+ "#ifndef yyskel_static",
+ "#define yyskel_static",
+ "#endif",
+ "#endif",
+ "",
+ "",
+ "/** Get the number of integers in this table. This is NOT the",
+ " * same thing as the number of elements.",
+ " * @param tbl the table",
+ " * @return the number of integers in the table",
+ " */",
+ "yyskel_static flex_int32_t yytbl_calc_total_len (const struct yytbl_data *tbl)",
+ "{",
+ " flex_uint32_t n;",
+ "",
+ " /* total number of ints */",
+ " n = tbl->td_lolen;",
+ " if (tbl->td_hilen > 0)",
+ " n *= tbl->td_hilen;",
+ "",
+ " if (tbl->td_id == YYTD_ID_TRANSITION)",
+ " n *= 2;",
+ " return (flex_int32_t) n;",
+ "}",
+ "",
+ "",
+ "static int yytbl_read8 (void *v, struct yytbl_reader * rd)",
+ "{",
+ " errno = 0;",
+ " if (fread (v, sizeof (flex_uint8_t), 1, rd->fp) != 1){",
+ " errno = EIO;",
+ " return -1;",
+ " }",
+ " rd->bread += (flex_uint32_t) sizeof(flex_uint8_t);",
+ " return 0;",
+ "}",
+ "",
+ "static int yytbl_read16 (void *v, struct yytbl_reader * rd)",
+ "{",
+ " errno = 0;",
+ " if (fread (v, sizeof (flex_uint16_t), 1, rd->fp) != 1){",
+ " errno = EIO;",
+ " return -1;",
+ " }",
+ " *((flex_uint16_t *) v) = ntohs (*((flex_uint16_t *) v));",
+ " rd->bread += (flex_uint32_t) sizeof(flex_uint16_t);",
+ " return 0;",
+ "}",
+ "",
+ "static int yytbl_read32 (void *v, struct yytbl_reader * rd)",
+ "{",
+ " errno = 0;",
+ " if (fread (v, sizeof (flex_uint32_t), 1, rd->fp) != 1){",
+ " errno = EIO;",
+ " return -1;",
+ " }",
+ " *((flex_uint32_t *) v) = ntohl (*((flex_uint32_t *) v));",
+ " rd->bread += (flex_uint32_t) sizeof(flex_uint32_t);",
+ " return 0;",
+ "}",
+ "",
+ "/** Read the header */",
+ "static int yytbl_hdr_read YYFARGS2(struct yytbl_hdr *, th, struct yytbl_reader *, rd)",
+ "{",
+ " size_t bytes;",
+ " memset (th, 0, sizeof (struct yytbl_hdr));",
+ "",
+ " if (yytbl_read32 (&(th->th_magic), rd) != 0)",
+ " return -1;",
+ "",
+ " if (th->th_magic != YYTBL_MAGIC){",
+ " YY_FATAL_ERROR( \"bad magic number\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ "",
+ " if (yytbl_read32 (&(th->th_hsize), rd) != 0",
+ " || yytbl_read32 (&(th->th_ssize), rd) != 0",
+ " || yytbl_read16 (&(th->th_flags), rd) != 0)",
+ " return -1;",
+ "",
+ " /* Sanity check on header size. Greater than 1k suggests some funny business. */",
+ " if (th->th_hsize < 16 || th->th_hsize > 1024){",
+ " YY_FATAL_ERROR( \"insane header size detected\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ "",
+ " /* Allocate enough space for the version and name fields */",
+ " bytes = th->th_hsize - 14;",
+ " th->th_version = (char *) yyalloc (bytes M4_YY_CALL_LAST_ARG);",
+ " if ( ! th->th_version )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yytbl_hdr_read()\" );",
+ "",
+ " /* we read it all into th_version, and point th_name into that data */",
+ " if (fread (th->th_version, 1, bytes, rd->fp) != bytes){",
+ " errno = EIO;",
+ " yyfree(th->th_version M4_YY_CALL_LAST_ARG);",
+ " th->th_version = NULL;",
+ " return -1;",
+ " }",
+ " else",
+ " rd->bread += (flex_uint32_t) bytes;",
+ "",
+ " th->th_name = th->th_version + strlen (th->th_version) + 1;",
+ " return 0;",
+ "}",
+ "",
+ "/** lookup id in the dmap list.",
+ " * @param dmap pointer to first element in list",
+ " * @return NULL if not found.",
+ " */",
+ "static struct yytbl_dmap *yytbl_dmap_lookup YYFARGS2(struct yytbl_dmap *, dmap,",
+ " int, id)",
+ "{",
+ " M4_YY_DECL_GUTS_VAR();",
+ " M4_YY_NOOP_GUTS_VAR();",
+ "",
+ " while (dmap->dm_id)",
+ " if ((int)(dmap->dm_id) == id)",
+ " return dmap;",
+ " else",
+ " dmap++;",
+ " return NULL;",
+ "}",
+ "",
+ "/** Read a table while mapping its contents to the local array.",
+ " * @param dmap used to performing mapping",
+ " * @return 0 on success",
+ " */",
+ "static int yytbl_data_load YYFARGS2(struct yytbl_dmap *, dmap, struct yytbl_reader*, rd)",
+ "{",
+ " struct yytbl_data td;",
+ " struct yytbl_dmap *transdmap=0;",
+ " int len, i, rv, inner_loop_count;",
+ " void *p=0;",
+ "",
+ " memset (&td, 0, sizeof (struct yytbl_data));",
+ "",
+ " if (yytbl_read16 (&td.td_id, rd) != 0",
+ " || yytbl_read16 (&td.td_flags, rd) != 0",
+ " || yytbl_read32 (&td.td_hilen, rd) != 0",
+ " || yytbl_read32 (&td.td_lolen, rd) != 0)",
+ " return -1;",
+ "",
+ " /* Lookup the map for the transition table so we have it in case we need it",
+ " * inside the loop below. This scanner might not even have a transition",
+ " * table, which is ok.",
+ " */",
+ " transdmap = yytbl_dmap_lookup (dmap, YYTD_ID_TRANSITION M4_YY_CALL_LAST_ARG);",
+ "",
+ " if ((dmap = yytbl_dmap_lookup (dmap, td.td_id M4_YY_CALL_LAST_ARG)) == NULL){",
+ " YY_FATAL_ERROR( \"table id not found in map.\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ "",
+ " /* Allocate space for table.",
+ " * The --full yy_transition table is a special case, since we",
+ " * need the dmap.dm_sz entry to tell us the sizeof the individual",
+ " * struct members.",
+ " */",
+ " {",
+ " size_t bytes;",
+ "",
+ " if ((td.td_flags & YYTD_STRUCT))",
+ " bytes = sizeof(struct yy_trans_info) * td.td_lolen * (td.td_hilen ? td.td_hilen : 1);",
+ " else",
+ " bytes = td.td_lolen * (td.td_hilen ? td.td_hilen : 1) * dmap->dm_sz;",
+ "",
+ " if(M4_YY_TABLES_VERIFY)",
+ " /* We point to the array itself */",
+ " p = dmap->dm_arr;",
+ " else",
+ " /* We point to the address of a pointer. */",
+ " *dmap->dm_arr = p = (void *) yyalloc (bytes M4_YY_CALL_LAST_ARG);",
+ " if ( ! p )",
+ " YY_FATAL_ERROR( \"out of dynamic memory in yytbl_data_load()\" );",
+ " }",
+ "",
+ " /* If it's a struct, we read 2 integers to get one element */",
+ " if ((td.td_flags & YYTD_STRUCT) != 0)",
+ " inner_loop_count = 2;",
+ " else",
+ " inner_loop_count = 1;",
+ "",
+ " /* read and map each element.",
+ " * This loop iterates once for each element of the td_data array.",
+ " * Notice that we increment 'i' in the inner loop.",
+ " */",
+ " len = yytbl_calc_total_len (&td);",
+ " for (i = 0; i < len; ){",
+ " int j;",
+ "",
+ "",
+ " /* This loop really executes exactly 1 or 2 times.",
+ " * The second time is to handle the second member of the",
+ " * YYTD_STRUCT for the yy_transition array.",
+ " */",
+ " for (j = 0; j < inner_loop_count; j++, i++) {",
+ " flex_int32_t t32;",
+ "",
+ " /* read into t32 no matter what the real size is. */",
+ " {",
+ " flex_int16_t t16;",
+ " flex_int8_t t8;",
+ "",
+ " switch (YYTDFLAGS2BYTES (td.td_flags)) {",
+ " case sizeof (flex_int32_t):",
+ " rv = yytbl_read32 (&t32, rd);",
+ " break;",
+ " case sizeof (flex_int16_t):",
+ " rv = yytbl_read16 (&t16, rd);",
+ " t32 = t16;",
+ " break;",
+ " case sizeof (flex_int8_t):",
+ " rv = yytbl_read8 (&t8, rd);",
+ " t32 = t8;",
+ " break;",
+ " default:",
+ " YY_FATAL_ERROR( \"invalid td_flags\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ " }",
+ " if (rv != 0)",
+ " return -1;",
+ "",
+ " /* copy into the deserialized array... */",
+ "",
+ " if ((td.td_flags & YYTD_STRUCT)) {",
+ " /* t32 is the j'th member of a two-element struct. */",
+ " void *v;",
+ "",
+ " v = j == 0 ? &(((struct yy_trans_info *) p)->yy_verify)",
+ " : &(((struct yy_trans_info *) p)->yy_nxt);",
+ "",
+ " switch (dmap->dm_sz) {",
+ " case sizeof (flex_int32_t):",
+ " if (M4_YY_TABLES_VERIFY){",
+ " if( ((flex_int32_t *) v)[0] != (flex_int32_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int32_t\" );",
+ " }else",
+ " ((flex_int32_t *) v)[0] = (flex_int32_t) t32;",
+ " break;",
+ " case sizeof (flex_int16_t):",
+ " if (M4_YY_TABLES_VERIFY ){",
+ " if(((flex_int16_t *) v)[0] != (flex_int16_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int16_t\" );",
+ " }else",
+ " ((flex_int16_t *) v)[0] = (flex_int16_t) t32;",
+ " break;",
+ " case sizeof(flex_int8_t):",
+ " if (M4_YY_TABLES_VERIFY ){",
+ " if( ((flex_int8_t *) v)[0] != (flex_int8_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at YYTD_STRUCT flex_int8_t\" );",
+ " }else",
+ " ((flex_int8_t *) v)[0] = (flex_int8_t) t32;",
+ " break;",
+ " default:",
+ " YY_FATAL_ERROR( \"invalid dmap->dm_sz for struct\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ "",
+ " /* if we're done with j, increment p */",
+ " if (j == 1)",
+ " p = (struct yy_trans_info *) p + 1;",
+ " }",
+ " else if ((td.td_flags & YYTD_PTRANS)) {",
+ " /* t32 is an index into the transition array. */",
+ " struct yy_trans_info *v;",
+ "",
+ "",
+ " if (!transdmap){",
+ " YY_FATAL_ERROR( \"transition table not found\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ "",
+ " if( M4_YY_TABLES_VERIFY)",
+ " v = &(((struct yy_trans_info *) (transdmap->dm_arr))[t32]);",
+ " else",
+ " v = &((*((struct yy_trans_info **) (transdmap->dm_arr)))[t32]);",
+ "",
+ " if(M4_YY_TABLES_VERIFY ){",
+ " if( ((struct yy_trans_info **) p)[0] != v)",
+ " YY_FATAL_ERROR( \"tables verification failed at YYTD_PTRANS\" );",
+ " }else",
+ " ((struct yy_trans_info **) p)[0] = v;",
+ "",
+ " /* increment p */",
+ " p = (struct yy_trans_info **) p + 1;",
+ " }",
+ " else {",
+ " /* t32 is a plain int. copy data, then incrememnt p. */",
+ " switch (dmap->dm_sz) {",
+ " case sizeof (flex_int32_t):",
+ " if(M4_YY_TABLES_VERIFY ){",
+ " if( ((flex_int32_t *) p)[0] != (flex_int32_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at flex_int32_t\" );",
+ " }else",
+ " ((flex_int32_t *) p)[0] = (flex_int32_t) t32;",
+ " p = ((flex_int32_t *) p) + 1;",
+ " break;",
+ " case sizeof (flex_int16_t):",
+ " if(M4_YY_TABLES_VERIFY ){",
+ " if( ((flex_int16_t *) p)[0] != (flex_int16_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at flex_int16_t\" );",
+ " }else",
+ " ((flex_int16_t *) p)[0] = (flex_int16_t) t32;",
+ " p = ((flex_int16_t *) p) + 1;",
+ " break;",
+ " case sizeof (flex_int8_t):",
+ " if(M4_YY_TABLES_VERIFY ){",
+ " if( ((flex_int8_t *) p)[0] != (flex_int8_t) t32)",
+ " YY_FATAL_ERROR( \"tables verification failed at flex_int8_t\" );",
+ " }else",
+ " ((flex_int8_t *) p)[0] = (flex_int8_t) t32;",
+ " p = ((flex_int8_t *) p) + 1;",
+ " break;",
+ " default:",
+ " YY_FATAL_ERROR( \"invalid dmap->dm_sz for plain int\" ); /* TODO: not fatal. */",
+ " return -1;",
+ " }",
+ " }",
+ " }",
+ "",
+ " }",
+ "",
+ " /* Now eat padding. */",
+ " {",
+ " int pad;",
+ " pad = yypad64(rd->bread);",
+ " while(--pad >= 0){",
+ " flex_int8_t t8;",
+ " if(yytbl_read8(&t8,rd) != 0)",
+ " return -1;",
+ " }",
+ " }",
+ "",
+ " return 0;",
+ "}",
+ "",
+ "%define-yytables The name for this specific scanner's tables.",
+ "",
+ "/* Find the key and load the DFA tables from the given stream. */",
+ "static int yytbl_fload YYFARGS2(FILE *, fp, const char *, key)",
+ "{",
+ " int rv=0;",
+ " struct yytbl_hdr th;",
+ " struct yytbl_reader rd;",
+ "",
+ " rd.fp = fp;",
+ " th.th_version = NULL;",
+ "",
+ " /* Keep trying until we find the right set of tables or end of file. */",
+ " while (!feof(rd.fp)) {",
+ " rd.bread = 0;",
+ " if (yytbl_hdr_read (&th, &rd M4_YY_CALL_LAST_ARG) != 0){",
+ " rv = -1;",
+ " goto return_rv;",
+ " }",
+ "",
+ " /* A NULL key means choose the first set of tables. */",
+ " if (key == NULL)",
+ " break;",
+ "",
+ " if (strcmp(th.th_name,key) != 0){",
+ " /* Skip ahead to next set */",
+ " fseek(rd.fp, th.th_ssize - th.th_hsize, SEEK_CUR);",
+ " yyfree(th.th_version M4_YY_CALL_LAST_ARG);",
+ " th.th_version = NULL;",
+ " }",
+ " else",
+ " break;",
+ " }",
+ "",
+ " while (rd.bread < th.th_ssize){",
+ " /* Load the data tables */",
+ " if(yytbl_data_load (yydmap,&rd M4_YY_CALL_LAST_ARG) != 0){",
+ " rv = -1;",
+ " goto return_rv;",
+ " }",
+ " }",
+ "",
+ "return_rv:",
+ " if(th.th_version){",
+ " yyfree(th.th_version M4_YY_CALL_LAST_ARG);",
+ " th.th_version = NULL;",
+ " }",
+ "",
+ " return rv;",
+ "}",
+ "",
+ "/** Load the DFA tables for this scanner from the given stream. */",
+ "int yytables_fload YYFARGS1(FILE *, fp)",
+ "{",
+ "",
+ " if( yytbl_fload(fp, YYTABLES_NAME M4_YY_CALL_LAST_ARG) != 0)",
+ " return -1;",
+ " return 0;",
+ "}",
+ "",
+ "/** Destroy the loaded tables, freeing memory, etc.. */",
+ "int yytables_destroy (M4_YY_DEF_ONLY_ARG)",
+ "{",
+ " struct yytbl_dmap *dmap=0;",
+ "",
+ " if(!M4_YY_TABLES_VERIFY){",
+ " /* Walk the dmap, freeing the pointers */",
+ " for(dmap=yydmap; dmap->dm_id; dmap++) {",
+ " void * v;",
+ " v = dmap->dm_arr;",
+ " if(v && *(char**)v){",
+ " yyfree(*(char**)v M4_YY_CALL_LAST_ARG);",
+ " *(char**)v = NULL;",
+ " }",
+ " }",
+ " }",
+ "",
+ " return 0;",
+ "}",
+ "",
+ "/* end table serialization code definitions */",
+ "%endif",
+ "",
+ "",
+ "m4_ifdef([[M4_YY_MAIN]], [[",
+ "int main (void);",
+ "",
+ "int main ()",
+ "{",
+ "",
+ "%if-reentrant",
+ " yyscan_t lexer;",
+ " yylex_init(&lexer);",
+ " yylex( lexer );",
+ " yylex_destroy( lexer);",
+ "",
+ "%endif",
+ "%if-not-reentrant",
+ " yylex();",
+ "%endif",
+ "",
+ " return 0;",
+ "}",
+ "]])",
+ "",
+ "%ok-for-header",
+ "m4_ifdef( [[M4_YY_IN_HEADER]],",
+ "[[",
+ "#undef YY_NEW_FILE",
+ "#undef YY_FLUSH_BUFFER",
+ "#undef yy_set_bol",
+ "#undef yy_new_buffer",
+ "#undef yy_set_interactive",
+ "#undef YY_DO_BEFORE_ACTION",
+ "",
+ "#ifdef YY_DECL_IS_OURS",
+ "#undef YY_DECL_IS_OURS",
+ "#undef YY_DECL",
+ "#endif",
+ "",
+ "[[#ifndef ]]M4_YY_PREFIX[[_create_buffer_ALREADY_DEFINED",
+ "#undef yy_create_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_delete_buffer_ALREADY_DEFINED",
+ "#undef yy_delete_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_scan_buffer_ALREADY_DEFINED",
+ "#undef yy_scan_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_scan_string_ALREADY_DEFINED",
+ "#undef yy_scan_string",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_scan_bytes_ALREADY_DEFINED",
+ "#undef yy_scan_bytes",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_init_buffer_ALREADY_DEFINED",
+ "#undef yy_init_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_flush_buffer_ALREADY_DEFINED",
+ "#undef yy_flush_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_load_buffer_state_ALREADY_DEFINED",
+ "#undef yy_load_buffer_state",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_switch_to_buffer_ALREADY_DEFINED",
+ "#undef yy_switch_to_buffer",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[push_buffer_state_ALREADY_DEFINED",
+ "#undef yypush_buffer_state",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[pop_buffer_state_ALREADY_DEFINED",
+ "#undef yypop_buffer_state",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[ensure_buffer_stack_ALREADY_DEFINED",
+ "#undef yyensure_buffer_stack",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[lex_ALREADY_DEFINED",
+ "#undef yylex",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[restart_ALREADY_DEFINED",
+ "#undef yyrestart",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[lex_init_ALREADY_DEFINED",
+ "#undef yylex_init",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[lex_init_extra_ALREADY_DEFINED",
+ "#undef yylex_init_extra",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[lex_destroy_ALREADY_DEFINED",
+ "#undef yylex_destroy",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_debug_ALREADY_DEFINED",
+ "#undef yyget_debug",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_debug_ALREADY_DEFINED",
+ "#undef yyset_debug",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_extra_ALREADY_DEFINED",
+ "#undef yyget_extra",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_extra_ALREADY_DEFINED",
+ "#undef yyset_extra",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_in_ALREADY_DEFINED",
+ "#undef yyget_in",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_in_ALREADY_DEFINED",
+ "#undef yyset_in",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_out_ALREADY_DEFINED",
+ "#undef yyget_out",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_out_ALREADY_DEFINED",
+ "#undef yyset_out",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_leng_ALREADY_DEFINED",
+ "#undef yyget_leng",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_text_ALREADY_DEFINED",
+ "#undef yyget_text",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_lineno_ALREADY_DEFINED",
+ "#undef yyget_lineno",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_lineno_ALREADY_DEFINED",
+ "#undef yyset_lineno",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_column_ALREADY_DEFINED",
+ "#undef yyget_column",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_column_ALREADY_DEFINED",
+ "#undef yyset_column",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[wrap_ALREADY_DEFINED",
+ "#undef yywrap",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_lval_ALREADY_DEFINED",
+ "#undef yyget_lval",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_lval_ALREADY_DEFINED",
+ "#undef yyset_lval",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[get_lloc_ALREADY_DEFINED",
+ "#undef yyget_lloc",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[set_lloc_ALREADY_DEFINED",
+ "#undef yyset_lloc",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[alloc_ALREADY_DEFINED",
+ "#undef yyalloc",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[realloc_ALREADY_DEFINED",
+ "#undef yyrealloc",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[free_ALREADY_DEFINED",
+ "#undef yyfree",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[text_ALREADY_DEFINED",
+ "#undef yytext",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[leng_ALREADY_DEFINED",
+ "#undef yyleng",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[in_ALREADY_DEFINED",
+ "#undef yyin",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[out_ALREADY_DEFINED",
+ "#undef yyout",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[_flex_debug_ALREADY_DEFINED",
+ "#undef yy_flex_debug",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[lineno_ALREADY_DEFINED",
+ "#undef yylineno",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[tables_fload_ALREADY_DEFINED",
+ "#undef yytables_fload",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[tables_destroy_ALREADY_DEFINED",
+ "#undef yytables_destroy",
+ "#endif]]",
+ "[[#ifndef ]]M4_YY_PREFIX[[TABLES_NAME_ALREADY_DEFINED",
+ "#undef yyTABLES_NAME",
+ "#endif]]",
+ "]])",
+ 0
+};
diff --git a/usr.bin/lex/lex.1 b/usr.bin/lex/lex.1
new file mode 100644
index 000000000000..a97b1863259d
--- /dev/null
+++ b/usr.bin/lex/lex.1
@@ -0,0 +1,4296 @@
+.\"
+.TH FLEX 1 "May 6, 2017" "Version 2.6.4"
+.SH NAME
+flex, lex \- fast lexical analyzer generator
+.SH SYNOPSIS
+.B flex
+.B [\-bcdfhilnpstvwBFILTV78+? \-C[aefFmr] \-ooutput \-Pprefix \-Sskeleton]
+.B [\-\-help \-\-version]
+.I [filename ...]
+.SH OVERVIEW
+This manual describes
+.I flex,
+a tool for generating programs that perform pattern-matching on text.
+The manual includes both tutorial and reference sections:
+.nf
+
+ Description
+ a brief overview of the tool
+
+ Some Simple Examples
+
+ Format Of The Input File
+
+ Patterns
+ the extended regular expressions used by flex
+
+ How The Input Is Matched
+ the rules for determining what has been matched
+
+ Actions
+ how to specify what to do when a pattern is matched
+
+ The Generated Scanner
+ details regarding the scanner that flex produces;
+ how to control the input source
+
+ Start Conditions
+ introducing context into your scanners, and
+ managing "mini-scanners"
+
+ Multiple Input Buffers
+ how to manipulate multiple input sources; how to
+ scan from strings instead of files
+
+ End-of-file Rules
+ special rules for matching the end of the input
+
+ Miscellaneous Macros
+ a summary of macros available to the actions
+
+ Values Available To The User
+ a summary of values available to the actions
+
+ Interfacing With Yacc
+ connecting flex scanners together with yacc parsers
+
+ Options
+ flex command-line options, and the "%option"
+ directive
+
+ Performance Considerations
+ how to make your scanner go as fast as possible
+
+ Generating C++ Scanners
+ the (experimental) facility for generating C++
+ scanner classes
+
+ Incompatibilities With Lex And POSIX
+ how flex differs from AT&T lex and the POSIX lex
+ standard
+
+ Diagnostics
+ those error messages produced by flex (or scanners
+ it generates) whose meanings might not be apparent
+
+ Files
+ files used by flex
+
+ Deficiencies / Bugs
+ known problems with flex
+
+ See Also
+ other documentation, related tools
+
+ Author
+ includes contact information
+
+.fi
+.SH DESCRIPTION
+.I flex
+is a tool for generating
+.I scanners:
+programs which recognize lexical patterns in text.
+.I flex
+reads
+the given input files, or its standard input if no file names are given,
+for a description of a scanner to generate.
+The description is in the form of pairs
+of regular expressions and C code, called
+.I rules.
+.I flex
+generates as output a C source file,
+.B lex.yy.c,
+which defines a routine
+.B yylex().
+This file is compiled and linked with the
+.B \-ll
+library to produce an executable.
+When the executable is run,
+it analyzes its input for occurrences
+of the regular expressions.
+Whenever it finds one, it executes
+the corresponding C code.
+.SH SOME SIMPLE EXAMPLES
+First some simple examples to get the flavor of how one uses
+.I flex.
+The following
+.I flex
+input specifies a scanner which whenever it encounters the string
+"username" will replace it with the user's login name:
+.nf
+
+ %%
+ username printf( "%s", getlogin() );
+
+.fi
+By default, any text not matched by a
+.I flex
+scanner
+is copied to the output, so the net effect of this scanner is
+to copy its input file to its output with each occurrence
+of "username" expanded.
+In this input, there is just one rule.
+"username" is the
+.I pattern
+and the "printf" is the
+.I action.
+The "%%" marks the beginning of the rules.
+.PP
+Here's another simple example:
+.nf
+
+ %{
+ int num_lines = 0, num_chars = 0;
+ %}
+
+ %%
+ \\n ++num_lines; ++num_chars;
+ . ++num_chars;
+
+ %%
+ main()
+ {
+ yylex();
+ printf( "# of lines = %d, # of chars = %d\\n",
+ num_lines, num_chars );
+ }
+
+.fi
+This scanner counts the number of characters and the number
+of lines in its input (it produces no output other than the
+final report on the counts).
+The first line
+declares two globals, "num_lines" and "num_chars", which are accessible
+both inside
+.B yylex()
+and in the
+.B main()
+routine declared after the second "%%".
+There are two rules, one
+which matches a newline ("\\n") and increments both the line count and
+the character count, and one which matches any character other than
+a newline (indicated by the "." regular expression).
+.PP
+A somewhat more complicated example:
+.nf
+
+ /* scanner for a toy Pascal-like language */
+
+ %{
+ /* need this for the call to atof() below */
+ #include <math.h>
+ %}
+
+ DIGIT [0-9]
+ ID [a-z][a-z0-9]*
+
+ %%
+
+ {DIGIT}+ {
+ printf( "An integer: %s (%d)\\n", yytext,
+ atoi( yytext ) );
+ }
+
+ {DIGIT}+"."{DIGIT}* {
+ printf( "A float: %s (%g)\\n", yytext,
+ atof( yytext ) );
+ }
+
+ if|then|begin|end|procedure|function {
+ printf( "A keyword: %s\\n", yytext );
+ }
+
+ {ID} printf( "An identifier: %s\\n", yytext );
+
+ "+"|"-"|"*"|"/" printf( "An operator: %s\\n", yytext );
+
+ "{"[^}\\n]*"}" /* eat up one-line comments */
+
+ [ \\t\\n]+ /* eat up whitespace */
+
+ . printf( "Unrecognized character: %s\\n", yytext );
+
+ %%
+
+ main( argc, argv )
+ int argc;
+ char **argv;
+ {
+ ++argv, --argc; /* skip over program name */
+ if ( argc > 0 )
+ yyin = fopen( argv[0], "r" );
+ else
+ yyin = stdin;
+
+ yylex();
+ }
+
+.fi
+This is the beginnings of a simple scanner for a language like
+Pascal.
+It identifies different types of
+.I tokens
+and reports on what it has seen.
+.PP
+The details of this example will be explained in the following
+sections.
+.SH FORMAT OF THE INPUT FILE
+The
+.I flex
+input file consists of three sections, separated by a line with just
+.B %%
+in it:
+.nf
+
+ definitions
+ %%
+ rules
+ %%
+ user code
+
+.fi
+The
+.I definitions
+section contains declarations of simple
+.I name
+definitions to simplify the scanner specification, and declarations of
+.I start conditions,
+which are explained in a later section.
+.PP
+Name definitions have the form:
+.nf
+
+ name definition
+
+.fi
+The "name" is a word beginning with a letter or an underscore ('_')
+followed by zero or more letters, digits, '_', or '-' (dash).
+The definition is taken to begin at the first non-white-space character
+following the name and continuing to the end of the line.
+The definition can subsequently be referred to using "{name}", which
+will expand to "(definition)".
+For example,
+.nf
+
+ DIGIT [0-9]
+ ID [a-z][a-z0-9]*
+
+.fi
+defines "DIGIT" to be a regular expression which matches a
+single digit, and
+"ID" to be a regular expression which matches a letter
+followed by zero-or-more letters-or-digits.
+A subsequent reference to
+.nf
+
+ {DIGIT}+"."{DIGIT}*
+
+.fi
+is identical to
+.nf
+
+ ([0-9])+"."([0-9])*
+
+.fi
+and matches one-or-more digits followed by a '.' followed
+by zero-or-more digits.
+.PP
+The
+.I rules
+section of the
+.I flex
+input contains a series of rules of the form:
+.nf
+
+ pattern action
+
+.fi
+where the pattern must be unindented and the action must begin
+on the same line.
+.PP
+See below for a further description of patterns and actions.
+.PP
+Finally, the user code section is simply copied to
+.B lex.yy.c
+verbatim.
+It is used for companion routines which call or are called
+by the scanner.
+The presence of this section is optional;
+if it is missing, the second
+.B %%
+in the input file may be skipped, too.
+.PP
+In the definitions and rules sections, any
+.I indented
+text or text enclosed in
+.B %{
+and
+.B %}
+is copied verbatim to the output (with the %{}'s removed).
+The %{}'s must appear unindented on lines by themselves.
+.PP
+In the rules section,
+any indented or %{} text appearing before the
+first rule may be used to declare variables
+which are local to the scanning routine and (after the declarations)
+code which is to be executed whenever the scanning routine is entered.
+Other indented or %{} text in the rule section is still copied to the output,
+but its meaning is not well-defined and it may well cause compile-time
+errors (this feature is present for
+.I POSIX
+compliance; see below for other such features).
+.PP
+In the definitions section (but not in the rules section),
+an unindented comment (i.e., a line
+beginning with "/*") is also copied verbatim to the output up
+to the next "*/".
+.SH PATTERNS
+The patterns in the input are written using an extended set of regular
+expressions.
+These are:
+.nf
+
+ x match the character 'x'
+ . any character (byte) except newline
+ [xyz] a "character class"; in this case, the pattern
+ matches either an 'x', a 'y', or a 'z'
+ [abj-oZ] a "character class" with a range in it; matches
+ an 'a', a 'b', any letter from 'j' through 'o',
+ or a 'Z'
+ [^A-Z] a "negated character class", i.e., any character
+ but those in the class. In this case, any
+ character EXCEPT an uppercase letter.
+ [^A-Z\\n] any character EXCEPT an uppercase letter or
+ a newline
+ r* zero or more r's, where r is any regular expression
+ r+ one or more r's
+ r? zero or one r's (that is, "an optional r")
+ r{2,5} anywhere from two to five r's
+ r{2,} two or more r's
+ r{4} exactly 4 r's
+ {name} the expansion of the "name" definition
+ (see above)
+ "[xyz]\\"foo"
+ the literal string: [xyz]"foo
+ \\X if X is an 'a', 'b', 'f', 'n', 'r', 't', or 'v',
+ then the ANSI-C interpretation of \\x.
+ Otherwise, a literal 'X' (used to escape
+ operators such as '*')
+ \\0 a NUL character (ASCII code 0)
+ \\123 the character with octal value 123
+ \\x2a the character with hexadecimal value 2a
+ (r) match an r; parentheses are used to override
+ precedence (see below)
+
+
+ rs the regular expression r followed by the
+ regular expression s; called "concatenation"
+
+
+ r|s either an r or an s
+
+
+ r/s an r but only if it is followed by an s. The
+ text matched by s is included when determining
+ whether this rule is the "longest match",
+ but is then returned to the input before
+ the action is executed. So the action only
+ sees the text matched by r. This type
+ of pattern is called trailing context".
+ (There are some combinations of r/s that flex
+ cannot match correctly; see notes in the
+ Deficiencies / Bugs section below regarding
+ "dangerous trailing context".)
+ ^r an r, but only at the beginning of a line (i.e.,
+ when just starting to scan, or right after a
+ newline has been scanned).
+ r$ an r, but only at the end of a line (i.e., just
+ before a newline). Equivalent to "r/\\n".
+
+ Note that flex's notion of "newline" is exactly
+ whatever the C compiler used to compile flex
+ interprets '\\n' as; in particular, on some DOS
+ systems you must either filter out \\r's in the
+ input yourself, or explicitly use r/\\r\\n for "r$".
+
+
+ <s>r an r, but only in start condition s (see
+ below for discussion of start conditions)
+ <s1,s2,s3>r
+ same, but in any of start conditions s1,
+ s2, or s3
+ <*>r an r in any start condition, even an exclusive one.
+
+
+ <<EOF>> an end-of-file
+ <s1,s2><<EOF>>
+ an end-of-file when in start condition s1 or s2
+
+.fi
+Note that inside of a character class, all regular expression operators
+lose their special meaning except escape ('\\') and the character class
+operators, '-', ']', and, at the beginning of the class, '^'.
+.PP
+The regular expressions listed above are grouped according to
+precedence, from highest precedence at the top to lowest at the bottom.
+Those grouped together have equal precedence.
+For example,
+.nf
+
+ foo|bar*
+
+.fi
+is the same as
+.nf
+
+ (foo)|(ba(r*))
+
+.fi
+since the '*' operator has higher precedence than concatenation,
+and concatenation higher than alternation ('|').
+This pattern
+therefore matches
+.I either
+the string "foo"
+.I or
+the string "ba" followed by zero-or-more r's.
+To match "foo" or zero-or-more "bar"'s, use:
+.nf
+
+ foo|(bar)*
+
+.fi
+and to match zero-or-more "foo"'s-or-"bar"'s:
+.nf
+
+ (foo|bar)*
+
+.fi
+.PP
+In addition to characters and ranges of characters, character classes
+can also contain character class
+.I expressions.
+These are expressions enclosed inside
+.B [:
+and
+.B :]
+delimiters (which themselves must appear between the '[' and ']' of the
+character class; other elements may occur inside the character class, too).
+The valid expressions are:
+.nf
+
+ [:alnum:] [:alpha:] [:blank:]
+ [:cntrl:] [:digit:] [:graph:]
+ [:lower:] [:print:] [:punct:]
+ [:space:] [:upper:] [:xdigit:]
+
+.fi
+These expressions all designate a set of characters equivalent to
+the corresponding standard C
+.B isXXX
+function.
+For example,
+.B [:alnum:]
+designates those characters for which
+.B isalnum()
+returns true - i.e., any alphabetic or numeric.
+Some systems don't provide
+.B isblank(),
+so flex defines
+.B [:blank:]
+as a blank or a tab.
+.PP
+For example, the following character classes are all equivalent:
+.nf
+
+ [[:alnum:]]
+ [[:alpha:][:digit:]]
+ [[:alpha:]0-9]
+ [a-zA-Z0-9]
+
+.fi
+If your scanner is case-insensitive (the
+.B \-i
+flag), then
+.B [:upper:]
+and
+.B [:lower:]
+are equivalent to
+.B [:alpha:].
+.PP
+Some notes on patterns:
+.IP -
+A negated character class such as the example "[^A-Z]"
+above
+.I will match a newline
+unless "\\n" (or an equivalent escape sequence) is one of the
+characters explicitly present in the negated character class
+(e.g., "[^A-Z\\n]").
+This is unlike how many other regular
+expression tools treat negated character classes, but unfortunately
+the inconsistency is historically entrenched.
+Matching newlines means that a pattern like [^"]* can match the entire
+input unless there's another quote in the input.
+.IP -
+A rule can have at most one instance of trailing context (the '/' operator
+or the '$' operator).
+The start condition, '^', and "<<EOF>>" patterns
+can only occur at the beginning of a pattern, and, as well as with '/' and '$',
+cannot be grouped inside parentheses.
+A '^' which does not occur at
+the beginning of a rule or a '$' which does not occur at the end of
+a rule loses its special properties and is treated as a normal character.
+.IP
+The following are illegal:
+.nf
+
+ foo/bar$
+ <sc1>foo<sc2>bar
+
+.fi
+Note that the first of these, can be written "foo/bar\\n".
+.IP
+The following will result in '$' or '^' being treated as a normal character:
+.nf
+
+ foo|(bar$)
+ foo|^bar
+
+.fi
+If what's wanted is a "foo" or a bar-followed-by-a-newline, the following
+could be used (the special '|' action is explained below):
+.nf
+
+ foo |
+ bar$ /* action goes here */
+
+.fi
+A similar trick will work for matching a foo or a
+bar-at-the-beginning-of-a-line.
+.SH HOW THE INPUT IS MATCHED
+When the generated scanner is run, it analyzes its input looking
+for strings which match any of its patterns.
+If it finds more than
+one match, it takes the one matching the most text (for trailing
+context rules, this includes the length of the trailing part, even
+though it will then be returned to the input).
+If it finds two
+or more matches of the same length, the
+rule listed first in the
+.I flex
+input file is chosen.
+.PP
+Once the match is determined, the text corresponding to the match
+(called the
+.I token)
+is made available in the global character pointer
+.B yytext,
+and its length in the global integer
+.B yyleng.
+The
+.I action
+corresponding to the matched pattern is then executed (a more
+detailed description of actions follows), and then the remaining
+input is scanned for another match.
+.PP
+If no match is found, then the
+.I default rule
+is executed: the next character in the input is considered matched and
+copied to the standard output.
+Thus, the simplest legal
+.I flex
+input is:
+.nf
+
+ %%
+
+.fi
+which generates a scanner that simply copies its input (one character
+at a time) to its output.
+.PP
+Note that
+.B yytext
+can be defined in two different ways: either as a character
+.I pointer
+or as a character
+.I array.
+You can control which definition
+.I flex
+uses by including one of the special directives
+.B %pointer
+or
+.B %array
+in the first (definitions) section of your flex input.
+The default is
+.B %pointer,
+unless you use the
+.B -l
+lex compatibility option, in which case
+.B yytext
+will be an array.
+The advantage of using
+.B %pointer
+is substantially faster scanning and no buffer overflow when matching
+very large tokens (unless you run out of dynamic memory).
+The disadvantage
+is that you are restricted in how your actions can modify
+.B yytext
+(see the next section), and calls to the
+.B unput()
+function destroys the present contents of
+.B yytext,
+which can be a considerable porting headache when moving between different
+.I lex
+versions.
+.PP
+The advantage of
+.B %array
+is that you can then modify
+.B yytext
+to your heart's content, and calls to
+.B unput()
+do not destroy
+.B yytext
+(see below).
+Furthermore, existing
+.I lex
+programs sometimes access
+.B yytext
+externally using declarations of the form:
+.nf
+ extern char yytext[];
+.fi
+This definition is erroneous when used with
+.B %pointer,
+but correct for
+.B %array.
+.PP
+.B %array
+defines
+.B yytext
+to be an array of
+.B YYLMAX
+characters, which defaults to a fairly large value.
+You can change
+the size by simply #define'ing
+.B YYLMAX
+to a different value in the first section of your
+.I flex
+input.
+As mentioned above, with
+.B %pointer
+yytext grows dynamically to accommodate large tokens.
+While this means your
+.B %pointer
+scanner can accommodate very large tokens (such as matching entire blocks
+of comments), bear in mind that each time the scanner must resize
+.B yytext
+it also must rescan the entire token from the beginning, so matching such
+tokens can prove slow.
+.B yytext
+presently does
+.I not
+dynamically grow if a call to
+.B unput()
+results in too much text being pushed back; instead, a run-time error results.
+.PP
+Also note that you cannot use
+.B %array
+with C++ scanner classes
+(the
+.B c++
+option; see below).
+.SH ACTIONS
+Each pattern in a rule has a corresponding action, which can be any
+arbitrary C statement.
+The pattern ends at the first non-escaped
+whitespace character; the remainder of the line is its action.
+If the
+action is empty, then when the pattern is matched the input token
+is simply discarded.
+For example, here is the specification for a program
+which deletes all occurrences of "zap me" from its input:
+.nf
+
+ %%
+ "zap me"
+
+.fi
+(It will copy all other characters in the input to the output since
+they will be matched by the default rule.)
+.PP
+Here is a program which compresses multiple blanks and tabs down to
+a single blank, and throws away whitespace found at the end of a line:
+.nf
+
+ %%
+ [ \\t]+ putchar( ' ' );
+ [ \\t]+$ /* ignore this token */
+
+.fi
+.PP
+If the action contains a '{', then the action spans till the balancing '}'
+is found, and the action may cross multiple lines.
+.I flex
+knows about C strings and comments and won't be fooled by braces found
+within them, but also allows actions to begin with
+.B %{
+and will consider the action to be all the text up to the next
+.B %}
+(regardless of ordinary braces inside the action).
+.PP
+An action consisting solely of a vertical bar ('|') means "same as
+the action for the next rule." See below for an illustration.
+.PP
+Actions can include arbitrary C code, including
+.B return
+statements to return a value to whatever routine called
+.B yylex().
+Each time
+.B yylex()
+is called it continues processing tokens from where it last left
+off until it either reaches
+the end of the file or executes a return.
+.PP
+Actions are free to modify
+.B yytext
+except for lengthening it (adding
+characters to its end--these will overwrite later characters in the
+input stream).
+This however does not apply when using
+.B %array
+(see above); in that case,
+.B yytext
+may be freely modified in any way.
+.PP
+Actions are free to modify
+.B yyleng
+except they should not do so if the action also includes use of
+.B yymore()
+(see below).
+.PP
+There are a number of special directives which can be included within
+an action:
+.IP -
+.B ECHO
+copies yytext to the scanner's output.
+.IP -
+.B BEGIN
+followed by the name of a start condition places the scanner in the
+corresponding start condition (see below).
+.IP -
+.B REJECT
+directs the scanner to proceed on to the "second best" rule which matched the
+input (or a prefix of the input).
+The rule is chosen as described
+above in "How the Input is Matched", and
+.B yytext
+and
+.B yyleng
+set up appropriately.
+It may either be one which matched as much text
+as the originally chosen rule but came later in the
+.I flex
+input file, or one which matched less text.
+For example, the following will both count the
+words in the input and call the routine special() whenever "frob" is seen:
+.nf
+
+ int word_count = 0;
+ %%
+
+ frob special(); REJECT;
+ [^ \\t\\n]+ ++word_count;
+
+.fi
+Without the
+.B REJECT,
+any "frob"'s in the input would not be counted as words, since the
+scanner normally executes only one action per token.
+Multiple
+.B REJECT's
+are allowed, each one finding the next best choice to the currently
+active rule.
+For example, when the following scanner scans the token
+"abcd", it will write "abcdabcaba" to the output:
+.nf
+
+ %%
+ a |
+ ab |
+ abc |
+ abcd ECHO; REJECT;
+ .|\\n /* eat up any unmatched character */
+
+.fi
+(The first three rules share the fourth's action since they use
+the special '|' action.)
+.B REJECT
+is a particularly expensive feature in terms of scanner performance;
+if it is used in
+.I any
+of the scanner's actions it will slow down
+.I all
+of the scanner's matching.
+Furthermore,
+.B REJECT
+cannot be used with the
+.I -Cf
+or
+.I -CF
+options (see below).
+.IP
+Note also that unlike the other special actions,
+.B REJECT
+is a
+.I branch;
+code immediately following it in the action will
+.I not
+be executed.
+.IP -
+.B yymore()
+tells the scanner that the next time it matches a rule, the corresponding
+token should be
+.I appended
+onto the current value of
+.B yytext
+rather than replacing it.
+For example, given the input "mega-kludge"
+the following will write "mega-mega-kludge" to the output:
+.nf
+
+ %%
+ mega- ECHO; yymore();
+ kludge ECHO;
+
+.fi
+First "mega-" is matched and echoed to the output.
+Then "kludge"
+is matched, but the previous "mega-" is still hanging around at the
+beginning of
+.B yytext
+so the
+.B ECHO
+for the "kludge" rule will actually write "mega-kludge".
+.PP
+Two notes regarding use of
+.B yymore().
+First,
+.B yymore()
+depends on the value of
+.I yyleng
+correctly reflecting the size of the current token, so you must not
+modify
+.I yyleng
+if you are using
+.B yymore().
+Second, the presence of
+.B yymore()
+in the scanner's action entails a minor performance penalty in the
+scanner's matching speed.
+.IP -
+.B yyless(n)
+returns all but the first
+.I n
+characters of the current token back to the input stream, where they
+will be rescanned when the scanner looks for the next match.
+.B yytext
+and
+.B yyleng
+are adjusted appropriately (e.g.,
+.B yyleng
+will now be equal to
+.I n
+).
+For example, on the input "foobar" the following will write out
+"foobarbar":
+.nf
+
+ %%
+ foobar ECHO; yyless(3);
+ [a-z]+ ECHO;
+
+.fi
+An argument of 0 to
+.B yyless
+will cause the entire current input string to be scanned again.
+Unless you've
+changed how the scanner will subsequently process its input (using
+.B BEGIN,
+for example), this will result in an endless loop.
+.PP
+Note that
+.B yyless
+is a macro and can only be used in the flex input file, not from
+other source files.
+.IP -
+.B unput(c)
+puts the character
+.I c
+back onto the input stream.
+It will be the next character scanned.
+The following action will take the current token and cause it
+to be rescanned enclosed in parentheses.
+.nf
+
+ {
+ int i;
+ /* Copy yytext because unput() trashes yytext */
+ char *yycopy = strdup( yytext );
+ unput( ')' );
+ for ( i = yyleng - 1; i >= 0; --i )
+ unput( yycopy[i] );
+ unput( '(' );
+ free( yycopy );
+ }
+
+.fi
+Note that since each
+.B unput()
+puts the given character back at the
+.I beginning
+of the input stream, pushing back strings must be done back-to-front.
+.PP
+An important potential problem when using
+.B unput()
+is that if you are using
+.B %pointer
+(the default), a call to
+.B unput()
+.I destroys
+the contents of
+.I yytext,
+starting with its rightmost character and devouring one character to
+the left with each call.
+If you need the value of yytext preserved
+after a call to
+.B unput()
+(as in the above example),
+you must either first copy it elsewhere, or build your scanner using
+.B %array
+instead (see How The Input Is Matched).
+.PP
+Finally, note that you cannot put back
+.B EOF
+to attempt to mark the input stream with an end-of-file.
+.IP -
+.B input()
+reads the next character from the input stream.
+For example,
+the following is one way to eat up C comments:
+.nf
+
+ %%
+ "/*" {
+ int c;
+
+ for ( ; ; )
+ {
+ while ( (c = input()) != '*' &&
+ c != EOF )
+ ; /* eat up text of comment */
+
+ if ( c == '*' )
+ {
+ while ( (c = input()) == '*' )
+ ;
+ if ( c == '/' )
+ break; /* found the end */
+ }
+
+ if ( c == EOF )
+ {
+ error( "EOF in comment" );
+ break;
+ }
+ }
+ }
+
+.fi
+(Note that if the scanner is compiled using
+.B C++,
+then
+.B input()
+is instead referred to as
+.B yyinput(),
+in order to avoid a name clash with the
+.B C++
+stream by the name of
+.I input.)
+.IP -
+.B YY_FLUSH_BUFFER
+flushes the scanner's internal buffer
+so that the next time the scanner attempts to match a token, it will
+first refill the buffer using
+.B YY_INPUT
+(see The Generated Scanner, below).
+This action is a special case
+of the more general
+.B yy_flush_buffer()
+function, described below in the section Multiple Input Buffers.
+.IP -
+.B yyterminate()
+can be used in lieu of a return statement in an action.
+It terminates
+the scanner and returns a 0 to the scanner's caller, indicating "all done".
+By default,
+.B yyterminate()
+is also called when an end-of-file is encountered.
+It is a macro and may be redefined.
+.SH THE GENERATED SCANNER
+The output of
+.I flex
+is the file
+.B lex.yy.c,
+which contains the scanning routine
+.B yylex(),
+a number of tables used by it for matching tokens, and a number
+of auxiliary routines and macros.
+By default,
+.B yylex()
+is declared as follows:
+.nf
+
+ int yylex()
+ {
+ ... various definitions and the actions in here ...
+ }
+
+.fi
+(If your environment supports function prototypes, then it will
+be "int yylex( void )".) This definition may be changed by defining
+the "YY_DECL" macro.
+For example, you could use:
+.nf
+
+ #define YY_DECL float lexscan( a, b ) float a, b;
+
+.fi
+to give the scanning routine the name
+.I lexscan,
+returning a float, and taking two floats as arguments.
+Note that
+if you give arguments to the scanning routine using a
+K&R-style/non-prototyped function declaration, you must terminate
+the definition with a semi-colon (;).
+.PP
+Whenever
+.B yylex()
+is called, it scans tokens from the global input file
+.I yyin
+(which defaults to stdin).
+It continues until it either reaches
+an end-of-file (at which point it returns the value 0) or
+one of its actions executes a
+.I return
+statement.
+.PP
+If the scanner reaches an end-of-file, subsequent calls are undefined
+unless either
+.I yyin
+is pointed at a new input file (in which case scanning continues from
+that file), or
+.B yyrestart()
+is called.
+.B yyrestart()
+takes one argument, a
+.B FILE *
+pointer (which can be nil, if you've set up
+.B YY_INPUT
+to scan from a source other than
+.I yyin),
+and initializes
+.I yyin
+for scanning from that file.
+Essentially there is no difference between
+just assigning
+.I yyin
+to a new input file or using
+.B yyrestart()
+to do so; the latter is available for compatibility with previous versions
+of
+.I flex,
+and because it can be used to switch input files in the middle of scanning.
+It can also be used to throw away the current input buffer, by calling
+it with an argument of
+.I yyin;
+but better is to use
+.B YY_FLUSH_BUFFER
+(see above).
+Note that
+.B yyrestart()
+does
+.I not
+reset the start condition to
+.B INITIAL
+(see Start Conditions, below).
+.PP
+If
+.B yylex()
+stops scanning due to executing a
+.I return
+statement in one of the actions, the scanner may then be called again and it
+will resume scanning where it left off.
+.PP
+By default (and for purposes of efficiency), the scanner uses
+block-reads rather than simple
+.I getc()
+calls to read characters from
+.I yyin.
+The nature of how it gets its input can be controlled by defining the
+.B YY_INPUT
+macro.
+YY_INPUT's calling sequence is "YY_INPUT(buf,result,max_size)".
+Its action is to place up to
+.I max_size
+characters in the character array
+.I buf
+and return in the integer variable
+.I result
+either the
+number of characters read or the constant YY_NULL (0 on Unix systems)
+to indicate EOF.
+The default YY_INPUT reads from the
+global file-pointer "yyin".
+.PP
+A sample definition of YY_INPUT (in the definitions
+section of the input file):
+.nf
+
+ %{
+ #define YY_INPUT(buf,result,max_size) \\
+ { \\
+ int c = getchar(); \\
+ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \\
+ }
+ %}
+
+.fi
+This definition will change the input processing to occur
+one character at a time.
+.PP
+When the scanner receives an end-of-file indication from YY_INPUT,
+it then checks the
+.B yywrap()
+function.
+If
+.B yywrap()
+returns false (zero), then it is assumed that the
+function has gone ahead and set up
+.I yyin
+to point to another input file, and scanning continues.
+If it returns
+true (non-zero), then the scanner terminates, returning 0 to its
+caller.
+Note that in either case, the start condition remains unchanged;
+it does
+.I not
+revert to
+.B INITIAL.
+.PP
+If you do not supply your own version of
+.B yywrap(),
+then you must either use
+.B %option noyywrap
+(in which case the scanner behaves as though
+.B yywrap()
+returned 1), or you must link with
+.B \-ll
+to obtain the default version of the routine, which always returns 1.
+.PP
+Three routines are available for scanning from in-memory buffers rather
+than files:
+.B yy_scan_string(), yy_scan_bytes(),
+and
+.B yy_scan_buffer().
+See the discussion of them below in the section Multiple Input Buffers.
+.PP
+The scanner writes its
+.B ECHO
+output to the
+.I yyout
+global (default, stdout), which may be redefined by the user simply
+by assigning it to some other
+.B FILE
+pointer.
+.SH START CONDITIONS
+.I flex
+provides a mechanism for conditionally activating rules.
+Any rule
+whose pattern is prefixed with "<sc>" will only be active when
+the scanner is in the start condition named "sc".
+For example,
+.nf
+
+ <STRING>[^"]* { /* eat up the string body ... */
+ ...
+ }
+
+.fi
+will be active only when the scanner is in the "STRING" start
+condition, and
+.nf
+
+ <INITIAL,STRING,QUOTE>\\. { /* handle an escape ... */
+ ...
+ }
+
+.fi
+will be active only when the current start condition is
+either "INITIAL", "STRING", or "QUOTE".
+.PP
+Start conditions
+are declared in the definitions (first) section of the input
+using unindented lines beginning with either
+.B %s
+or
+.B %x
+followed by a list of names.
+The former declares
+.I inclusive
+start conditions, the latter
+.I exclusive
+start conditions.
+A start condition is activated using the
+.B BEGIN
+action.
+Until the next
+.B BEGIN
+action is executed, rules with the given start
+condition will be active and
+rules with other start conditions will be inactive.
+If the start condition is
+.I inclusive,
+then rules with no start conditions at all will also be active.
+If it is
+.I exclusive,
+then
+.I only
+rules qualified with the start condition will be active.
+A set of rules contingent on the same exclusive start condition
+describe a scanner which is independent of any of the other rules in the
+.I flex
+input.
+Because of this,
+exclusive start conditions make it easy to specify "mini-scanners"
+which scan portions of the input that are syntactically different
+from the rest (e.g., comments).
+.PP
+If the distinction between inclusive and exclusive start conditions
+is still a little vague, here's a simple example illustrating the
+connection between the two.
+The set of rules:
+.nf
+
+ %s example
+ %%
+
+ <example>foo do_something();
+
+ bar something_else();
+
+.fi
+is equivalent to
+.nf
+
+ %x example
+ %%
+
+ <example>foo do_something();
+
+ <INITIAL,example>bar something_else();
+
+.fi
+Without the
+.B <INITIAL,example>
+qualifier, the
+.I bar
+pattern in the second example wouldn't be active (i.e., couldn't match)
+when in start condition
+.B example.
+If we just used
+.B <example>
+to qualify
+.I bar,
+though, then it would only be active in
+.B example
+and not in
+.B INITIAL,
+while in the first example it's active in both, because in the first
+example the
+.B example
+start condition is an
+.I inclusive
+.B (%s)
+start condition.
+.PP
+Also note that the special start-condition specifier
+.B <*>
+matches every start condition.
+Thus, the above example could also have been written;
+.nf
+
+ %x example
+ %%
+
+ <example>foo do_something();
+
+ <*>bar something_else();
+
+.fi
+.PP
+The default rule (to
+.B ECHO
+any unmatched character) remains active in start conditions.
+It
+is equivalent to:
+.nf
+
+ <*>.|\\n ECHO;
+
+.fi
+.PP
+.B BEGIN(0)
+returns to the original state where only the rules with
+no start conditions are active.
+This state can also be
+referred to as the start-condition "INITIAL", so
+.B BEGIN(INITIAL)
+is equivalent to
+.B BEGIN(0).
+(The parentheses around the start condition name are not required but
+are considered good style.)
+.PP
+.B BEGIN
+actions can also be given as indented code at the beginning
+of the rules section.
+For example, the following will cause
+the scanner to enter the "SPECIAL" start condition whenever
+.B yylex()
+is called and the global variable
+.I enter_special
+is true:
+.nf
+
+ int enter_special;
+
+ %x SPECIAL
+ %%
+ if ( enter_special )
+ BEGIN(SPECIAL);
+
+ <SPECIAL>blahblahblah
+ ...more rules follow...
+
+.fi
+.PP
+To illustrate the uses of start conditions,
+here is a scanner which provides two different interpretations
+of a string like "123.456".
+By default it will treat it as
+three tokens, the integer "123", a dot ('.'), and the integer "456".
+But if the string is preceded earlier in the line by the string
+"expect-floats"
+it will treat it as a single token, the floating-point number
+123.456:
+.nf
+
+ %{
+ #include <math.h>
+ %}
+ %s expect
+
+ %%
+ expect-floats BEGIN(expect);
+
+ <expect>[0-9]+"."[0-9]+ {
+ printf( "found a float, = %f\\n",
+ atof( yytext ) );
+ }
+ <expect>\\n {
+ /* that's the end of the line, so
+ * we need another "expect-number"
+ * before we'll recognize any more
+ * numbers
+ */
+ BEGIN(INITIAL);
+ }
+
+ [0-9]+ {
+ printf( "found an integer, = %d\\n",
+ atoi( yytext ) );
+ }
+
+ "." printf( "found a dot\\n" );
+
+.fi
+Here is a scanner which recognizes (and discards) C comments while
+maintaining a count of the current input line.
+.nf
+
+ %x comment
+ %%
+ int line_num = 1;
+
+ "/*" BEGIN(comment);
+
+ <comment>[^*\\n]* /* eat anything that's not a '*' */
+ <comment>"*"+[^*/\\n]* /* eat up '*'s not followed by '/'s */
+ <comment>\\n ++line_num;
+ <comment>"*"+"/" BEGIN(INITIAL);
+
+.fi
+This scanner goes to a bit of trouble to match as much
+text as possible with each rule.
+In general, when attempting to write
+a high-speed scanner try to match as much possible in each rule, as
+it's a big win.
+.PP
+Note that start-conditions names are really integer values and
+can be stored as such.
+Thus, the above could be extended in the
+following fashion:
+.nf
+
+ %x comment foo
+ %%
+ int line_num = 1;
+ int comment_caller;
+
+ "/*" {
+ comment_caller = INITIAL;
+ BEGIN(comment);
+ }
+
+ ...
+
+ <foo>"/*" {
+ comment_caller = foo;
+ BEGIN(comment);
+ }
+
+ <comment>[^*\\n]* /* eat anything that's not a '*' */
+ <comment>"*"+[^*/\\n]* /* eat up '*'s not followed by '/'s */
+ <comment>\\n ++line_num;
+ <comment>"*"+"/" BEGIN(comment_caller);
+
+.fi
+Furthermore, you can access the current start condition using
+the integer-valued
+.B YY_START
+macro.
+For example, the above assignments to
+.I comment_caller
+could instead be written
+.nf
+
+ comment_caller = YY_START;
+
+.fi
+Flex provides
+.B YYSTATE
+as an alias for
+.B YY_START
+(since that is what's used by AT&T
+.I lex).
+.PP
+Note that start conditions do not have their own name-space; %s's and %x's
+declare names in the same fashion as #define's.
+.PP
+Finally, here's an example of how to match C-style quoted strings using
+exclusive start conditions, including expanded escape sequences (but
+not including checking for a string that's too long):
+.nf
+
+ %x str
+
+ %%
+ char string_buf[MAX_STR_CONST];
+ char *string_buf_ptr;
+
+
+ \\" string_buf_ptr = string_buf; BEGIN(str);
+
+ <str>\\" { /* saw closing quote - all done */
+ BEGIN(INITIAL);
+ *string_buf_ptr = '\\0';
+ /* return string constant token type and
+ * value to parser
+ */
+ }
+
+ <str>\\n {
+ /* error - unterminated string constant */
+ /* generate error message */
+ }
+
+ <str>\\\\[0-7]{1,3} {
+ /* octal escape sequence */
+ int result;
+
+ (void) sscanf( yytext + 1, "%o", &result );
+
+ if ( result > 0xff )
+ /* error, constant is out-of-bounds */
+
+ *string_buf_ptr++ = result;
+ }
+
+ <str>\\\\[0-9]+ {
+ /* generate error - bad escape sequence; something
+ * like '\\48' or '\\0777777'
+ */
+ }
+
+ <str>\\\\n *string_buf_ptr++ = '\\n';
+ <str>\\\\t *string_buf_ptr++ = '\\t';
+ <str>\\\\r *string_buf_ptr++ = '\\r';
+ <str>\\\\b *string_buf_ptr++ = '\\b';
+ <str>\\\\f *string_buf_ptr++ = '\\f';
+
+ <str>\\\\(.|\\n) *string_buf_ptr++ = yytext[1];
+
+ <str>[^\\\\\\n\\"]+ {
+ char *yptr = yytext;
+
+ while ( *yptr )
+ *string_buf_ptr++ = *yptr++;
+ }
+
+.fi
+.PP
+Often, such as in some of the examples above, you wind up writing a
+whole bunch of rules all preceded by the same start condition(s).
+Flex makes this a little easier and cleaner by introducing a notion of
+start condition
+.I scope.
+A start condition scope is begun with:
+.nf
+
+ <SCs>{
+
+.fi
+where
+.I SCs
+is a list of one or more start conditions.
+Inside the start condition
+scope, every rule automatically has the prefix
+.I <SCs>
+applied to it, until a
+.I '}'
+which matches the initial
+.I '{'.
+So, for example,
+.nf
+
+ <ESC>{
+ "\\\\n" return '\\n';
+ "\\\\r" return '\\r';
+ "\\\\f" return '\\f';
+ "\\\\0" return '\\0';
+ }
+
+.fi
+is equivalent to:
+.nf
+
+ <ESC>"\\\\n" return '\\n';
+ <ESC>"\\\\r" return '\\r';
+ <ESC>"\\\\f" return '\\f';
+ <ESC>"\\\\0" return '\\0';
+
+.fi
+Start condition scopes may be nested.
+.PP
+Three routines are available for manipulating stacks of start conditions:
+.TP
+.B void yy_push_state(int new_state)
+pushes the current start condition onto the top of the start condition
+stack and switches to
+.I new_state
+as though you had used
+.B BEGIN new_state
+(recall that start condition names are also integers).
+.TP
+.B void yy_pop_state()
+pops the top of the stack and switches to it via
+.B BEGIN.
+.TP
+.B int yy_top_state()
+returns the top of the stack without altering the stack's contents.
+.PP
+The start condition stack grows dynamically and so has no built-in
+size limitation.
+If memory is exhausted, program execution aborts.
+.PP
+To use start condition stacks, your scanner must include a
+.B %option stack
+directive (see Options below).
+.SH MULTIPLE INPUT BUFFERS
+Some scanners (such as those which support "include" files)
+require reading from several input streams.
+As
+.I flex
+scanners do a large amount of buffering, one cannot control
+where the next input will be read from by simply writing a
+.B YY_INPUT
+which is sensitive to the scanning context.
+.B YY_INPUT
+is only called when the scanner reaches the end of its buffer, which
+may be a long time after scanning a statement such as an "include"
+which requires switching the input source.
+.PP
+To negotiate these sorts of problems,
+.I flex
+provides a mechanism for creating and switching between multiple
+input buffers.
+An input buffer is created by using:
+.nf
+
+ YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+
+.fi
+which takes a
+.I FILE
+pointer and a size and creates a buffer associated with the given
+file and large enough to hold
+.I size
+characters (when in doubt, use
+.B YY_BUF_SIZE
+for the size).
+It returns a
+.B YY_BUFFER_STATE
+handle, which may then be passed to other routines (see below).
+The
+.B YY_BUFFER_STATE
+type is a pointer to an opaque
+.B struct yy_buffer_state
+structure, so you may safely initialize YY_BUFFER_STATE variables to
+.B ((YY_BUFFER_STATE) 0)
+if you wish, and also refer to the opaque structure in order to
+correctly declare input buffers in source files other than that
+of your scanner.
+Note that the
+.I FILE
+pointer in the call to
+.B yy_create_buffer
+is only used as the value of
+.I yyin
+seen by
+.B YY_INPUT;
+if you redefine
+.B YY_INPUT
+so it no longer uses
+.I yyin,
+then you can safely pass a nil
+.I FILE
+pointer to
+.B yy_create_buffer.
+You select a particular buffer to scan from using:
+.nf
+
+ void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+
+.fi
+switches the scanner's input buffer so subsequent tokens will
+come from
+.I new_buffer.
+Note that
+.B yy_switch_to_buffer()
+may be used by yywrap() to set things up for continued scanning, instead
+of opening a new file and pointing
+.I yyin
+at it.
+Note also that switching input sources via either
+.B yy_switch_to_buffer()
+or
+.B yywrap()
+does
+.I not
+change the start condition.
+.nf
+
+ void yy_delete_buffer( YY_BUFFER_STATE buffer )
+
+.fi
+is used to reclaim the storage associated with a buffer.
+(
+.B buffer
+can be nil, in which case the routine does nothing.)
+You can also clear the current contents of a buffer using:
+.nf
+
+ void yy_flush_buffer( YY_BUFFER_STATE buffer )
+
+.fi
+This function discards the buffer's contents,
+so the next time the scanner attempts to match a token from the
+buffer, it will first fill the buffer anew using
+.B YY_INPUT.
+.PP
+.B yy_new_buffer()
+is an alias for
+.B yy_create_buffer(),
+provided for compatibility with the C++ use of
+.I new
+and
+.I delete
+for creating and destroying dynamic objects.
+.PP
+Finally, the
+.B YY_CURRENT_BUFFER
+macro returns a
+.B YY_BUFFER_STATE
+handle to the current buffer.
+.PP
+Here is an example of using these features for writing a scanner
+which expands include files (the
+.B <<EOF>>
+feature is discussed below):
+.nf
+
+ /* the "incl" state is used for picking up the name
+ * of an include file
+ */
+ %x incl
+
+ %{
+ #define MAX_INCLUDE_DEPTH 10
+ YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+ int include_stack_ptr = 0;
+ %}
+
+ %%
+ include BEGIN(incl);
+
+ [a-z]+ ECHO;
+ [^a-z\\n]*\\n? ECHO;
+
+ <incl>[ \\t]* /* eat the whitespace */
+ <incl>[^ \\t\\n]+ { /* got the include file name */
+ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+ {
+ fprintf( stderr, "Includes nested too deeply" );
+ exit( 1 );
+ }
+
+ include_stack[include_stack_ptr++] =
+ YY_CURRENT_BUFFER;
+
+ yyin = fopen( yytext, "r" );
+
+ if ( ! yyin )
+ error( ... );
+
+ yy_switch_to_buffer(
+ yy_create_buffer( yyin, YY_BUF_SIZE ) );
+
+ BEGIN(INITIAL);
+ }
+
+ <<EOF>> {
+ if ( --include_stack_ptr < 0 )
+ {
+ yyterminate();
+ }
+
+ else
+ {
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ yy_switch_to_buffer(
+ include_stack[include_stack_ptr] );
+ }
+ }
+
+.fi
+Three routines are available for setting up input buffers for
+scanning in-memory strings instead of files.
+All of them create
+a new input buffer for scanning the string, and return a corresponding
+.B YY_BUFFER_STATE
+handle (which you should delete with
+.B yy_delete_buffer()
+when done with it).
+They also switch to the new buffer using
+.B yy_switch_to_buffer(),
+so the next call to
+.B yylex()
+will start scanning the string.
+.TP
+.B yy_scan_string(const char *str)
+scans a NUL-terminated string.
+.TP
+.B yy_scan_bytes(const char *bytes, int len)
+scans
+.I len
+bytes (including possibly NUL's)
+starting at location
+.I bytes.
+.PP
+Note that both of these functions create and scan a
+.I copy
+of the string or bytes.
+(This may be desirable, since
+.B yylex()
+modifies the contents of the buffer it is scanning.) You can avoid the
+copy by using:
+.TP
+.B yy_scan_buffer(char *base, yy_size_t size)
+which scans in place the buffer starting at
+.I base,
+consisting of
+.I size
+bytes, the last two bytes of which
+.I must
+be
+.B YY_END_OF_BUFFER_CHAR
+(ASCII NUL).
+These last two bytes are not scanned; thus, scanning
+consists of
+.B base[0]
+through
+.B base[size-2],
+inclusive.
+.IP
+If you fail to set up
+.I base
+in this manner (i.e., forget the final two
+.B YY_END_OF_BUFFER_CHAR
+bytes), then
+.B yy_scan_buffer()
+returns a nil pointer instead of creating a new input buffer.
+.IP
+The type
+.B yy_size_t
+is an integral type to which you can cast an integer expression
+reflecting the size of the buffer.
+.SH END-OF-FILE RULES
+The special rule "<<EOF>>" indicates
+actions which are to be taken when an end-of-file is
+encountered and yywrap() returns non-zero (i.e., indicates
+no further files to process).
+The action must finish
+by doing one of four things:
+.IP -
+assigning
+.I yyin
+to a new input file (in previous versions of flex, after doing the
+assignment you had to call the special action
+.B YY_NEW_FILE;
+this is no longer necessary);
+.IP -
+executing a
+.I return
+statement;
+.IP -
+executing the special
+.B yyterminate()
+action;
+.IP -
+or, switching to a new buffer using
+.B yy_switch_to_buffer()
+as shown in the example above.
+.PP
+<<EOF>> rules may not be used with other
+patterns; they may only be qualified with a list of start
+conditions.
+If an unqualified <<EOF>> rule is given, it
+applies to
+.I all
+start conditions which do not already have <<EOF>> actions.
+To
+specify an <<EOF>> rule for only the initial start condition, use
+.nf
+
+ <INITIAL><<EOF>>
+
+.fi
+.PP
+These rules are useful for catching things like unclosed comments.
+An example:
+.nf
+
+ %x quote
+ %%
+
+ ...other rules for dealing with quotes...
+
+ <quote><<EOF>> {
+ error( "unterminated quote" );
+ yyterminate();
+ }
+ <<EOF>> {
+ if ( *++filelist )
+ yyin = fopen( *filelist, "r" );
+ else
+ yyterminate();
+ }
+
+.fi
+.SH MISCELLANEOUS MACROS
+The macro
+.B YY_USER_ACTION
+can be defined to provide an action
+which is always executed prior to the matched rule's action.
+For example,
+it could be #define'd to call a routine to convert yytext to lower-case.
+When
+.B YY_USER_ACTION
+is invoked, the variable
+.I yy_act
+gives the number of the matched rule (rules are numbered starting with 1).
+Suppose you want to profile how often each of your rules is matched.
+The following would do the trick:
+.nf
+
+ #define YY_USER_ACTION ++ctr[yy_act]
+
+.fi
+where
+.I ctr
+is an array to hold the counts for the different rules.
+Note that the macro
+.B YY_NUM_RULES
+gives the total number of rules (including the default rule, even if
+you use
+.B \-s),
+so a correct declaration for
+.I ctr
+is:
+.nf
+
+ int ctr[YY_NUM_RULES];
+
+.fi
+.PP
+The macro
+.B YY_USER_INIT
+may be defined to provide an action which is always executed before
+the first scan (and before the scanner's internal initializations are done).
+For example, it could be used to call a routine to read
+in a data table or open a logging file.
+.PP
+The macro
+.B yy_set_interactive(is_interactive)
+can be used to control whether the current buffer is considered
+.I interactive.
+An interactive buffer is processed more slowly,
+but must be used when the scanner's input source is indeed
+interactive to avoid problems due to waiting to fill buffers
+(see the discussion of the
+.B \-I
+flag below).
+A non-zero value
+in the macro invocation marks the buffer as interactive, a zero
+value as non-interactive.
+Note that use of this macro overrides
+.B %option interactive ,
+.B %option always-interactive
+or
+.B %option never-interactive
+(see Options below).
+.B yy_set_interactive()
+must be invoked prior to beginning to scan the buffer that is
+(or is not) to be considered interactive.
+.PP
+The macro
+.B yy_set_bol(at_bol)
+can be used to control whether the current buffer's scanning
+context for the next token match is done as though at the
+beginning of a line.
+A non-zero macro argument makes rules anchored with
+ '^' active, while a zero argument makes '^' rules inactive.
+.PP
+The macro
+.B YY_AT_BOL()
+returns true if the next token scanned from the current buffer
+will have '^' rules active, false otherwise.
+.PP
+In the generated scanner, the actions are all gathered in one large
+switch statement and separated using
+.B YY_BREAK,
+which may be redefined.
+By default, it is simply a "break", to separate
+each rule's action from the following rule's.
+Redefining
+.B YY_BREAK
+allows, for example, C++ users to
+#define YY_BREAK to do nothing (while being very careful that every
+rule ends with a "break" or a "return"!) to avoid suffering from
+unreachable statement warnings where because a rule's action ends with
+"return", the
+.B YY_BREAK
+is inaccessible.
+.SH VALUES AVAILABLE TO THE USER
+This section summarizes the various values available to the user
+in the rule actions.
+.IP -
+.B char *yytext
+holds the text of the current token.
+It may be modified but not lengthened
+(you cannot append characters to the end).
+.IP
+If the special directive
+.B %array
+appears in the first section of the scanner description, then
+.B yytext
+is instead declared
+.B char yytext[YYLMAX],
+where
+.B YYLMAX
+is a macro definition that you can redefine in the first section
+if you don't like the default value (generally 8KB).
+Using
+.B %array
+results in somewhat slower scanners, but the value of
+.B yytext
+becomes immune to calls to
+.I input()
+and
+.I unput(),
+which potentially destroy its value when
+.B yytext
+is a character pointer.
+The opposite of
+.B %array
+is
+.B %pointer,
+which is the default.
+.IP
+You cannot use
+.B %array
+when generating C++ scanner classes
+(the
+.B \-+
+flag).
+.IP -
+.B int yyleng
+holds the length of the current token.
+.IP -
+.B FILE *yyin
+is the file which by default
+.I flex
+reads from.
+It may be redefined but doing so only makes sense before
+scanning begins or after an EOF has been encountered.
+Changing it in the midst of scanning will have unexpected results since
+.I flex
+buffers its input; use
+.B yyrestart()
+instead.
+Once scanning terminates because an end-of-file
+has been seen, you can assign
+.I yyin
+at the new input file and then call the scanner again to continue scanning.
+.IP -
+.B void yyrestart( FILE *new_file )
+may be called to point
+.I yyin
+at the new input file.
+The switch-over to the new file is immediate
+(any previously buffered-up input is lost).
+Note that calling
+.B yyrestart()
+with
+.I yyin
+as an argument thus throws away the current input buffer and continues
+scanning the same input file.
+.IP -
+.B FILE *yyout
+is the file to which
+.B ECHO
+actions are done.
+It can be reassigned by the user.
+.IP -
+.B YY_CURRENT_BUFFER
+returns a
+.B YY_BUFFER_STATE
+handle to the current buffer.
+.IP -
+.B YY_START
+returns an integer value corresponding to the current start
+condition.
+You can subsequently use this value with
+.B BEGIN
+to return to that start condition.
+.SH INTERFACING WITH YACC
+One of the main uses of
+.I flex
+is as a companion to the
+.I yacc
+parser-generator.
+.I yacc
+parsers expect to call a routine named
+.B yylex()
+to find the next input token.
+The routine is supposed to
+return the type of the next token as well as putting any associated
+value in the global
+.B yylval.
+To use
+.I flex
+with
+.I yacc,
+one specifies the
+.B \-d
+option to
+.I yacc
+to instruct it to generate the file
+.B y.tab.h
+containing definitions of all the
+.B %tokens
+appearing in the
+.I yacc
+input.
+This file is then included in the
+.I flex
+scanner.
+For example, if one of the tokens is "TOK_NUMBER",
+part of the scanner might look like:
+.nf
+
+ %{
+ #include "y.tab.h"
+ %}
+
+ %%
+
+ [0-9]+ yylval = atoi( yytext ); return TOK_NUMBER;
+
+.fi
+.SH OPTIONS
+.I flex
+has the following options:
+.TP
+.B \-b, --backup
+Generate backing-up information to
+.I lex.backup.
+This is a list of scanner states which require backing up
+and the input characters on which they do so.
+By adding rules one
+can remove backing-up states.
+If
+.I all
+backing-up states are eliminated and
+.B \-Cf
+or
+.B \-CF
+is used, the generated scanner will run faster (see the
+.B \-p
+flag).
+Only users who wish to squeeze every last cycle out of their
+scanners need worry about this option.
+(See the section on Performance Considerations below.)
+.TP
+.B \-c
+is a do-nothing, deprecated option included for POSIX compliance.
+.TP
+.B \-d, \-\-debug
+makes the generated scanner run in
+.I debug
+mode.
+Whenever a pattern is recognized and the global
+.B yy_flex_debug
+is non-zero (which is the default),
+the scanner will write to
+.I stderr
+a line of the form:
+.nf
+
+ --accepting rule at line 53 ("the matched text")
+
+.fi
+The line number refers to the location of the rule in the file
+defining the scanner (i.e., the file that was fed to flex).
+Messages are also generated when the scanner backs up, accepts the
+default rule, reaches the end of its input buffer (or encounters
+a NUL; at this point, the two look the same as far as the scanner's concerned),
+or reaches an end-of-file.
+.TP
+.B \-f, \-\-full
+specifies
+.I fast scanner.
+No table compression is done and stdio is bypassed.
+The result is large but fast.
+This option is equivalent to
+.B \-Cfr
+(see below).
+.TP
+.B \-h, \-\-help
+generates a "help" summary of
+.I flex's
+options to
+.I stdout
+and then exits.
+.B \-?
+and
+.B \-\-help
+are synonyms for
+.B \-h.
+.TP
+.B \-i, \-\-case-insensitive
+instructs
+.I flex
+to generate a
+.I case-insensitive
+scanner.
+The case of letters given in the
+.I flex
+input patterns will
+be ignored, and tokens in the input will be matched regardless of case.
+The matched text given in
+.I yytext
+will have the preserved case (i.e., it will not be folded).
+.TP
+.B \-l, \-\-lex\-compat
+turns on maximum compatibility with the original AT&T
+.I lex
+implementation.
+Note that this does not mean
+.I full
+compatibility.
+Use of this option costs a considerable amount of
+performance, and it cannot be used with the
+.B \-+, -f, -F, -Cf,
+or
+.B -CF
+options.
+For details on the compatibilities it provides, see the section
+"Incompatibilities With Lex And POSIX" below.
+This option also results
+in the name
+.B YY_FLEX_LEX_COMPAT
+being #define'd in the generated scanner.
+.TP
+.B \-n
+is another do-nothing, deprecated option included only for
+POSIX compliance.
+.TP
+.B \-p, \-\-perf\-report
+generates a performance report to stderr.
+The report consists of comments regarding features of the
+.I flex
+input file which will cause a serious loss of performance in the resulting
+scanner.
+If you give the flag twice, you will also get comments regarding
+features that lead to minor performance losses.
+.IP
+Note that the use of
+.B REJECT,
+.B %option yylineno,
+and variable trailing context (see the Deficiencies / Bugs section below)
+entails a substantial performance penalty; use of
+.I yymore(),
+the
+.B ^
+operator,
+and the
+.B \-I
+flag entail minor performance penalties.
+.TP
+.B \-s, \-\-no\-default
+causes the
+.I default rule
+(that unmatched scanner input is echoed to
+.I stdout)
+to be suppressed.
+If the scanner encounters input that does not
+match any of its rules, it aborts with an error.
+This option is
+useful for finding holes in a scanner's rule set.
+.TP
+.B \-t, \-\-stdout
+instructs
+.I flex
+to write the scanner it generates to standard output instead
+of
+.B lex.yy.c.
+.TP
+.B \-v, \-\-verbose
+specifies that
+.I flex
+should write to
+.I stderr
+a summary of statistics regarding the scanner it generates.
+Most of the statistics are meaningless to the casual
+.I flex
+user, but the first line identifies the version of
+.I flex
+(same as reported by
+.B \-V),
+and the next line the flags used when generating the scanner, including
+those that are on by default.
+.TP
+.B \-w, \-\-nowarn
+suppresses warning messages.
+.TP
+.B \-B, \-\-batch
+instructs
+.I flex
+to generate a
+.I batch
+scanner, the opposite of
+.I interactive
+scanners generated by
+.B \-I
+(see below).
+In general, you use
+.B \-B
+when you are
+.I certain
+that your scanner will never be used interactively, and you want to
+squeeze a
+.I little
+more performance out of it.
+If your goal is instead to squeeze out a
+.I lot
+more performance, you should be using the
+.B \-Cf
+or
+.B \-CF
+options (discussed below), which turn on
+.B \-B
+automatically anyway.
+.TP
+.B \-F, \-\-fast
+specifies that the
+.I fast
+scanner table representation should be used (and stdio
+bypassed).
+This representation is about as fast as the full table representation
+.B (-f),
+and for some sets of patterns will be considerably smaller (and for
+others, larger).
+In general, if the pattern set contains both "keywords"
+and a catch-all, "identifier" rule, such as in the set:
+.nf
+
+ "case" return TOK_CASE;
+ "switch" return TOK_SWITCH;
+ ...
+ "default" return TOK_DEFAULT;
+ [a-z]+ return TOK_ID;
+
+.fi
+then you're better off using the full table representation.
+If only
+the "identifier" rule is present and you then use a hash table or some such
+to detect the keywords, you're better off using
+.B -F.
+.IP
+This option is equivalent to
+.B \-CFr
+(see below).
+It cannot be used with
+.B \-+.
+.TP
+.B \-I, \-\-interactive
+instructs
+.I flex
+to generate an
+.I interactive
+scanner.
+An interactive scanner is one that only looks ahead to decide
+what token has been matched if it absolutely must.
+It turns out that
+always looking one extra character ahead, even if the scanner has already
+seen enough text to disambiguate the current token, is a bit faster than
+only looking ahead when necessary.
+But scanners that always look ahead
+give dreadful interactive performance; for example, when a user types
+a newline, it is not recognized as a newline token until they enter
+.I another
+token, which often means typing in another whole line.
+.IP
+.I Flex
+scanners default to
+.I interactive
+unless you use the
+.B \-Cf
+or
+.B \-CF
+table-compression options (see below).
+That's because if you're looking
+for high-performance you should be using one of these options, so if you
+didn't,
+.I flex
+assumes you'd rather trade off a bit of run-time performance for intuitive
+interactive behavior.
+Note also that you
+.I cannot
+use
+.B \-I
+in conjunction with
+.B \-Cf
+or
+.B \-CF.
+Thus, this option is not really needed; it is on by default for all those
+cases in which it is allowed.
+.IP
+Note that if
+.B isatty()
+returns false for the scanner input, flex will revert to batch mode, even if
+.B \-I
+was specified.
+To force interactive mode no matter what, use
+.B %option always-interactive
+(see Options below).
+.IP
+You can force a scanner to
+.I not
+be interactive by using
+.B \-B
+(see above).
+.TP
+.B \-L, \-\-noline
+instructs
+.I flex
+not to generate
+.B #line
+directives.
+Without this option,
+.I flex
+peppers the generated scanner
+with #line directives so error messages in the actions will be correctly
+located with respect to either the original
+.I flex
+input file (if the errors are due to code in the input file), or
+.B lex.yy.c
+(if the errors are
+.I flex's
+fault -- you should report these sorts of errors to the email address
+given below).
+.TP
+.B \-T, \-\-trace
+makes
+.I flex
+run in
+.I trace
+mode.
+It will generate a lot of messages to
+.I stderr
+concerning
+the form of the input and the resultant non-deterministic and deterministic
+finite automata.
+This option is mostly for use in maintaining
+.I flex.
+.TP
+.B \-V, \-\-version
+prints the version number to
+.I stdout
+and exits.
+.B \-\-version
+is a synonym for
+.B \-V.
+.TP
+.B \-7, \-\-7bit
+instructs
+.I flex
+to generate a 7-bit scanner, i.e., one which can only recognize 7-bit
+characters in its input.
+The advantage of using
+.B \-7
+is that the scanner's tables can be up to half the size of those generated
+using the
+.B \-8
+option (see below).
+The disadvantage is that such scanners often hang
+or crash if their input contains an 8-bit character.
+.IP
+Note, however, that unless you generate your scanner using the
+.B \-Cf
+or
+.B \-CF
+table compression options, use of
+.B \-7
+will save only a small amount of table space, and make your scanner
+considerably less portable.
+.I Flex's
+default behavior is to generate an 8-bit scanner unless you use the
+.B \-Cf
+or
+.B \-CF,
+in which case
+.I flex
+defaults to generating 7-bit scanners unless your site was always
+configured to generate 8-bit scanners (as will often be the case
+with non-USA sites).
+You can tell whether flex generated a 7-bit
+or an 8-bit scanner by inspecting the flag summary in the
+.B \-v
+output as described above.
+.IP
+Note that if you use
+.B \-Cfe
+or
+.B \-CFe
+(those table compression options, but also using equivalence classes as
+discussed see below), flex still defaults to generating an 8-bit
+scanner, since usually with these compression options full 8-bit tables
+are not much more expensive than 7-bit tables.
+.TP
+.B \-8, \-\-8bit
+instructs
+.I flex
+to generate an 8-bit scanner, i.e., one which can recognize 8-bit
+characters.
+This flag is only needed for scanners generated using
+.B \-Cf
+or
+.B \-CF,
+as otherwise flex defaults to generating an 8-bit scanner anyway.
+.IP
+See the discussion of
+.B \-7
+above for flex's default behavior and the tradeoffs between 7-bit
+and 8-bit scanners.
+.TP
+.B \-+, \-\-c++
+specifies that you want flex to generate a C++
+scanner class.
+See the section on Generating C++ Scanners below for
+details.
+.TP
+.B \-C[aefFmr]
+controls the degree of table compression and, more generally, trade-offs
+between small scanners and fast scanners.
+.IP
+.B \-Ca, \-\-align
+("align") instructs flex to trade off larger tables in the
+generated scanner for faster performance because the elements of
+the tables are better aligned for memory access and computation.
+On some
+RISC architectures, fetching and manipulating longwords is more efficient
+than with smaller-sized units such as shortwords.
+This option can
+double the size of the tables used by your scanner.
+.IP
+.B \-Ce, \-\-ecs
+directs
+.I flex
+to construct
+.I equivalence classes,
+i.e., sets of characters
+which have identical lexical properties (for example, if the only
+appearance of digits in the
+.I flex
+input is in the character class
+"[0-9]" then the digits '0', '1', ..., '9' will all be put
+in the same equivalence class).
+Equivalence classes usually give
+dramatic reductions in the final table/object file sizes (typically
+a factor of 2-5) and are pretty cheap performance-wise (one array
+look-up per character scanned).
+.IP
+.B \-Cf
+specifies that the
+.I full
+scanner tables should be generated -
+.I flex
+should not compress the
+tables by taking advantages of similar transition functions for
+different states.
+.IP
+.B \-CF
+specifies that the alternative fast scanner representation (described
+above under the
+.B \-F
+flag)
+should be used.
+This option cannot be used with
+.B \-+.
+.IP
+.B \-Cm, \-\-meta-ecs
+directs
+.I flex
+to construct
+.I meta-equivalence classes,
+which are sets of equivalence classes (or characters, if equivalence
+classes are not being used) that are commonly used together.
+Meta-equivalence
+classes are often a big win when using compressed tables, but they
+have a moderate performance impact (one or two "if" tests and one
+array look-up per character scanned).
+.IP
+.B \-Cr, \-\-read
+causes the generated scanner to
+.I bypass
+use of the standard I/O library (stdio) for input.
+Instead of calling
+.B fread()
+or
+.B getc(),
+the scanner will use the
+.B read()
+system call, resulting in a performance gain which varies from system
+to system, but in general is probably negligible unless you are also using
+.B \-Cf
+or
+.B \-CF.
+Using
+.B \-Cr
+can cause strange behavior if, for example, you read from
+.I yyin
+using stdio prior to calling the scanner (because the scanner will miss
+whatever text your previous reads left in the stdio input buffer).
+.IP
+.B \-Cr
+has no effect if you define
+.B YY_INPUT
+(see The Generated Scanner above).
+.IP
+A lone
+.B \-C
+specifies that the scanner tables should be compressed but neither
+equivalence classes nor meta-equivalence classes should be used.
+.IP
+The options
+.B \-Cf
+or
+.B \-CF
+and
+.B \-Cm
+do not make sense together - there is no opportunity for meta-equivalence
+classes if the table is not being compressed.
+Otherwise the options
+may be freely mixed, and are cumulative.
+.IP
+The default setting is
+.B \-Cem,
+which specifies that
+.I flex
+should generate equivalence classes
+and meta-equivalence classes.
+This setting provides the highest degree of table compression.
+You can trade off
+faster-executing scanners at the cost of larger tables with
+the following generally being true:
+.nf
+
+ slowest & smallest
+ -Cem
+ -Cm
+ -Ce
+ -C
+ -C{f,F}e
+ -C{f,F}
+ -C{f,F}a
+ fastest & largest
+
+.fi
+Note that scanners with the smallest tables are usually generated and
+compiled the quickest, so
+during development you will usually want to use the default, maximal
+compression.
+.IP
+.B \-Cfe
+is often a good compromise between speed and size for production
+scanners.
+.TP
+.B \-ooutput, \-\-outputfile=FILE
+directs flex to write the scanner to the file
+.B output
+instead of
+.B lex.yy.c.
+If you combine
+.B \-o
+with the
+.B \-t
+option, then the scanner is written to
+.I stdout
+but its
+.B #line
+directives (see the
+.B \\-L
+option above) refer to the file
+.B output.
+.TP
+.B \-Pprefix, \-\-prefix=STRING
+changes the default
+.I "yy"
+prefix used by
+.I flex
+for all globally-visible variable and function names to instead be
+.I prefix.
+For example,
+.B \-Pfoo
+changes the name of
+.B yytext
+to
+.B footext.
+It also changes the name of the default output file from
+.B lex.yy.c
+to
+.B lex.foo.c.
+Here are all of the names affected:
+.nf
+
+ yy_create_buffer
+ yy_delete_buffer
+ yy_flex_debug
+ yy_init_buffer
+ yy_flush_buffer
+ yy_load_buffer_state
+ yy_switch_to_buffer
+ yyin
+ yyleng
+ yylex
+ yylineno
+ yyout
+ yyrestart
+ yytext
+ yywrap
+
+.fi
+(If you are using a C++ scanner, then only
+.B yywrap
+and
+.B yyFlexLexer
+are affected.)
+Within your scanner itself, you can still refer to the global variables
+and functions using either version of their name; but externally, they
+have the modified name.
+.IP
+This option lets you easily link together multiple
+.I flex
+programs into the same executable.
+Note, though, that using this option also renames
+.B yywrap(),
+so you now
+.I must
+either
+provide your own (appropriately-named) version of the routine for your
+scanner, or use
+.B %option noyywrap,
+as linking with
+.B \-ll
+no longer provides one for you by default.
+.TP
+.B \-Sskeleton_file, \-\-skel=FILE
+overrides the default skeleton file from which
+.I flex
+constructs its scanners.
+You'll never need this option unless you are doing
+.I flex
+maintenance or development.
+.TP
+.B \-X, \-\-posix\-compat
+maximal compatibility with POSIX lex.
+.TP
+.B \-\-yylineno
+track line count in yylineno.
+.TP
+.B \-\-yyclass=NAME
+name of C++ class.
+.TP
+.B \-\-header\-file=FILE
+create a C header file in addition to the scanner.
+.TP
+.B \-\-tables\-file[=FILE]
+write tables to FILE.
+.TP
+.B \\-Dmacro[=defn]
+#define macro defn (default defn is '1').
+.TP
+.B \-R, \-\-reentrant
+generate a reentrant C scanner
+.TP
+.B \-\-bison\-bridge
+scanner for bison pure parser.
+.TP
+.B \-\-bison\-locations
+include yylloc support.
+.TP
+.B \-\-stdinit
+initialize yyin/yyout to stdin/stdout.
+.TP
+.B \-\-noansi\-definitions old\-style function definitions.
+.TP
+.B \-\-noansi\-prototypes
+empty parameter list in prototypes.
+.TP
+.B \-\-nounistd
+do not include <unistd.h>.
+.TP
+.B \-\-noFUNCTION
+do not generate a particular FUNCTION.
+.PP
+.I flex
+also provides a mechanism for controlling options within the
+scanner specification itself, rather than from the flex command-line.
+This is done by including
+.B %option
+directives in the first section of the scanner specification.
+You can specify multiple options with a single
+.B %option
+directive, and multiple directives in the first section of your flex input
+file.
+.PP
+Most options are given simply as names, optionally preceded by the
+word "no" (with no intervening whitespace) to negate their meaning.
+A number are equivalent to flex flags or their negation:
+.nf
+
+ 7bit -7 option
+ 8bit -8 option
+ align -Ca option
+ backup -b option
+ batch -B option
+ c++ -+ option
+
+ caseful or
+ case-sensitive opposite of -i (default)
+
+ case-insensitive or
+ caseless -i option
+
+ debug -d option
+ default opposite of -s option
+ ecs -Ce option
+ fast -F option
+ full -f option
+ interactive -I option
+ lex-compat -l option
+ meta-ecs -Cm option
+ perf-report -p option
+ read -Cr option
+ stdout -t option
+ verbose -v option
+ warn opposite of -w option
+ (use "%option nowarn" for -w)
+
+ array equivalent to "%array"
+ pointer equivalent to "%pointer" (default)
+
+.fi
+Some
+.B %option's
+provide features otherwise not available:
+.TP
+.B always-interactive
+instructs flex to generate a scanner which always considers its input
+"interactive".
+Normally, on each new input file the scanner calls
+.B isatty()
+in an attempt to determine whether
+the scanner's input source is interactive and thus should be read a
+character at a time.
+When this option is used, however, then no
+such call is made.
+.TP
+.B main
+directs flex to provide a default
+.B main()
+program for the scanner, which simply calls
+.B yylex().
+This option implies
+.B noyywrap
+(see below).
+.TP
+.B never-interactive
+instructs flex to generate a scanner which never considers its input
+"interactive" (again, no call made to
+.B isatty()).
+This is the opposite of
+.B always-interactive.
+.TP
+.B stack
+enables the use of start condition stacks (see Start Conditions above).
+.TP
+.B stdinit
+if set (i.e.,
+.B %option stdinit)
+initializes
+.I yyin
+and
+.I yyout
+to
+.I stdin
+and
+.I stdout,
+instead of the default of
+.I nil.
+Some existing
+.I lex
+programs depend on this behavior, even though it is not compliant with
+ANSI C, which does not require
+.I stdin
+and
+.I stdout
+to be compile-time constant.
+.TP
+.B yylineno
+directs
+.I flex
+to generate a scanner that maintains the number of the current line
+read from its input in the global variable
+.B yylineno.
+This option is implied by
+.B %option lex-compat.
+.TP
+.B yywrap
+if unset (i.e.,
+.B %option noyywrap),
+makes the scanner not call
+.B yywrap()
+upon an end-of-file, but simply assume that there are no more
+files to scan (until the user points
+.I yyin
+at a new file and calls
+.B yylex()
+again).
+.PP
+.I flex
+scans your rule actions to determine whether you use the
+.B REJECT
+or
+.B yymore()
+features.
+The
+.B reject
+and
+.B yymore
+options are available to override its decision as to whether you use the
+options, either by setting them (e.g.,
+.B %option reject)
+to indicate the feature is indeed used, or
+unsetting them to indicate it actually is not used
+(e.g.,
+.B %option noyymore).
+.PP
+Three options take string-delimited values, offset with '=':
+.nf
+
+ %option outfile="ABC"
+
+.fi
+is equivalent to
+.B -oABC,
+and
+.nf
+
+ %option prefix="XYZ"
+
+.fi
+is equivalent to
+.B -PXYZ.
+Finally,
+.nf
+
+ %option yyclass="foo"
+
+.fi
+only applies when generating a C++ scanner (
+.B \-+
+option).
+It informs
+.I flex
+that you have derived
+.B foo
+as a subclass of
+.B yyFlexLexer,
+so
+.I flex
+will place your actions in the member function
+.B foo::yylex()
+instead of
+.B yyFlexLexer::yylex().
+It also generates a
+.B yyFlexLexer::yylex()
+member function that emits a run-time error (by invoking
+.B yyFlexLexer::LexerError())
+if called.
+See Generating C++ Scanners, below, for additional information.
+.PP
+A number of options are available for lint purists who want to suppress
+the appearance of unneeded routines in the generated scanner.
+Each of the following, if unset
+(e.g.,
+.B %option nounput
+), results in the corresponding routine not appearing in
+the generated scanner:
+.nf
+
+ input, unput
+ yy_push_state, yy_pop_state, yy_top_state
+ yy_scan_buffer, yy_scan_bytes, yy_scan_string
+
+.fi
+(though
+.B yy_push_state()
+and friends won't appear anyway unless you use
+.B %option stack).
+.SH PERFORMANCE CONSIDERATIONS
+The main design goal of
+.I flex
+is that it generate high-performance scanners.
+It has been optimized
+for dealing well with large sets of rules.
+Aside from the effects on scanner speed of the table compression
+.B \-C
+options outlined above,
+there are a number of options/actions which degrade performance.
+These are, from most expensive to least:
+.nf
+
+ REJECT
+ %option yylineno
+ arbitrary trailing context
+
+ pattern sets that require backing up
+ %array
+ %option interactive
+ %option always-interactive
+
+ '^' beginning-of-line operator
+ yymore()
+
+.fi
+with the first three all being quite expensive and the last two
+being quite cheap.
+Note also that
+.B unput()
+is implemented as a routine call that potentially does quite a bit of
+work, while
+.B yyless()
+is a quite-cheap macro; so if just putting back some excess text you
+scanned, use
+.B yyless().
+.PP
+.B REJECT
+should be avoided at all costs when performance is important.
+It is a particularly expensive option.
+.PP
+Getting rid of backing up is messy and often may be an enormous
+amount of work for a complicated scanner.
+In principal, one begins by using the
+.B \-b
+flag to generate a
+.I lex.backup
+file.
+For example, on the input
+.nf
+
+ %%
+ foo return TOK_KEYWORD;
+ foobar return TOK_KEYWORD;
+
+.fi
+the file looks like:
+.nf
+
+ State #6 is non-accepting -
+ associated rule line numbers:
+ 2 3
+ out-transitions: [ o ]
+ jam-transitions: EOF [ \\001-n p-\\177 ]
+
+ State #8 is non-accepting -
+ associated rule line numbers:
+ 3
+ out-transitions: [ a ]
+ jam-transitions: EOF [ \\001-` b-\\177 ]
+
+ State #9 is non-accepting -
+ associated rule line numbers:
+ 3
+ out-transitions: [ r ]
+ jam-transitions: EOF [ \\001-q s-\\177 ]
+
+ Compressed tables always back up.
+
+.fi
+The first few lines tell us that there's a scanner state in
+which it can make a transition on an 'o' but not on any other
+character, and that in that state the currently scanned text does not match
+any rule.
+The state occurs when trying to match the rules found
+at lines 2 and 3 in the input file.
+If the scanner is in that state and then reads
+something other than an 'o', it will have to back up to find
+a rule which is matched.
+With a bit of headscratching one can see that this must be the
+state it's in when it has seen "fo".
+When this has happened,
+if anything other than another 'o' is seen, the scanner will
+have to back up to simply match the 'f' (by the default rule).
+.PP
+The comment regarding State #8 indicates there's a problem
+when "foob" has been scanned.
+Indeed, on any character other
+than an 'a', the scanner will have to back up to accept "foo".
+Similarly, the comment for State #9 concerns when "fooba" has
+been scanned and an 'r' does not follow.
+.PP
+The final comment reminds us that there's no point going to
+all the trouble of removing backing up from the rules unless
+we're using
+.B \-Cf
+or
+.B \-CF,
+since there's no performance gain doing so with compressed scanners.
+.PP
+The way to remove the backing up is to add "error" rules:
+.nf
+
+ %%
+ foo return TOK_KEYWORD;
+ foobar return TOK_KEYWORD;
+
+ fooba |
+ foob |
+ fo {
+ /* false alarm, not really a keyword */
+ return TOK_ID;
+ }
+
+.fi
+.PP
+Eliminating backing up among a list of keywords can also be
+done using a "catch-all" rule:
+.nf
+
+ %%
+ foo return TOK_KEYWORD;
+ foobar return TOK_KEYWORD;
+
+ [a-z]+ return TOK_ID;
+
+.fi
+This is usually the best solution when appropriate.
+.PP
+Backing up messages tend to cascade.
+With a complicated set of rules it's not uncommon to get hundreds
+of messages.
+If one can decipher them, though, it often
+only takes a dozen or so rules to eliminate the backing up (though
+it's easy to make a mistake and have an error rule accidentally match
+a valid token.
+A possible future
+.I flex
+feature will be to automatically add rules to eliminate backing up).
+.PP
+It's important to keep in mind that you gain the benefits of eliminating
+backing up only if you eliminate
+.I every
+instance of backing up.
+Leaving just one means you gain nothing.
+.PP
+.I Variable
+trailing context (where both the leading and trailing parts do not have
+a fixed length) entails almost the same performance loss as
+.B REJECT
+(i.e., substantial).
+So when possible a rule like:
+.nf
+
+ %%
+ mouse|rat/(cat|dog) run();
+
+.fi
+is better written:
+.nf
+
+ %%
+ mouse/cat|dog run();
+ rat/cat|dog run();
+
+.fi
+or as
+.nf
+
+ %%
+ mouse|rat/cat run();
+ mouse|rat/dog run();
+
+.fi
+Note that here the special '|' action does
+.I not
+provide any savings, and can even make things worse (see
+Deficiencies / Bugs below).
+.LP
+Another area where the user can increase a scanner's performance
+(and one that's easier to implement) arises from the fact that
+the longer the tokens matched, the faster the scanner will run.
+This is because with long tokens the processing of most input
+characters takes place in the (short) inner scanning loop, and
+does not often have to go through the additional work of setting up
+the scanning environment (e.g.,
+.B yytext)
+for the action.
+Recall the scanner for C comments:
+.nf
+
+ %x comment
+ %%
+ int line_num = 1;
+
+ "/*" BEGIN(comment);
+
+ <comment>[^*\\n]*
+ <comment>"*"+[^*/\\n]*
+ <comment>\\n ++line_num;
+ <comment>"*"+"/" BEGIN(INITIAL);
+
+.fi
+This could be sped up by writing it as:
+.nf
+
+ %x comment
+ %%
+ int line_num = 1;
+
+ "/*" BEGIN(comment);
+
+ <comment>[^*\\n]*
+ <comment>[^*\\n]*\\n ++line_num;
+ <comment>"*"+[^*/\\n]*
+ <comment>"*"+[^*/\\n]*\\n ++line_num;
+ <comment>"*"+"/" BEGIN(INITIAL);
+
+.fi
+Now instead of each newline requiring the processing of another
+action, recognizing the newlines is "distributed" over the other rules
+to keep the matched text as long as possible.
+Note that
+.I adding
+rules does
+.I not
+slow down the scanner! The speed of the scanner is independent
+of the number of rules or (modulo the considerations given at the
+beginning of this section) how complicated the rules are with
+regard to operators such as '*' and '|'.
+.PP
+A final example in speeding up a scanner: suppose you want to scan
+through a file containing identifiers and keywords, one per line
+and with no other extraneous characters, and recognize all the
+keywords.
+A natural first approach is:
+.nf
+
+ %%
+ asm |
+ auto |
+ break |
+ ... etc ...
+ volatile |
+ while /* it's a keyword */
+
+ .|\\n /* it's not a keyword */
+
+.fi
+To eliminate the back-tracking, introduce a catch-all rule:
+.nf
+
+ %%
+ asm |
+ auto |
+ break |
+ ... etc ...
+ volatile |
+ while /* it's a keyword */
+
+ [a-z]+ |
+ .|\\n /* it's not a keyword */
+
+.fi
+Now, if it's guaranteed that there's exactly one word per line,
+then we can reduce the total number of matches by a half by
+merging in the recognition of newlines with that of the other
+tokens:
+.nf
+
+ %%
+ asm\\n |
+ auto\\n |
+ break\\n |
+ ... etc ...
+ volatile\\n |
+ while\\n /* it's a keyword */
+
+ [a-z]+\\n |
+ .|\\n /* it's not a keyword */
+
+.fi
+One has to be careful here, as we have now reintroduced backing up
+into the scanner.
+In particular, while
+.I we
+know that there will never be any characters in the input stream
+other than letters or newlines,
+.I flex
+can't figure this out, and it will plan for possibly needing to back up
+when it has scanned a token like "auto" and then the next character
+is something other than a newline or a letter.
+Previously it would
+then just match the "auto" rule and be done, but now it has no "auto"
+rule, only an "auto\\n" rule.
+To eliminate the possibility of backing up,
+we could either duplicate all rules but without final newlines, or,
+since we never expect to encounter such an input and therefore don't
+how it's classified, we can introduce one more catch-all rule, this
+one which doesn't include a newline:
+.nf
+
+ %%
+ asm\\n |
+ auto\\n |
+ break\\n |
+ ... etc ...
+ volatile\\n |
+ while\\n /* it's a keyword */
+
+ [a-z]+\\n |
+ [a-z]+ |
+ .|\\n /* it's not a keyword */
+
+.fi
+Compiled with
+.B \-Cf,
+this is about as fast as one can get a
+.I flex
+scanner to go for this particular problem.
+.PP
+A final note:
+.I flex
+is slow when matching NUL's, particularly when a token contains
+multiple NUL's.
+It's best to write rules which match
+.I short
+amounts of text if it's anticipated that the text will often include NUL's.
+.PP
+Another final note regarding performance: as mentioned above in the section
+How the Input is Matched, dynamically resizing
+.B yytext
+to accommodate huge tokens is a slow process because it presently requires that
+the (huge) token be rescanned from the beginning.
+Thus if performance is
+vital, you should attempt to match "large" quantities of text but not
+"huge" quantities, where the cutoff between the two is at about 8K
+characters/token.
+.SH GENERATING C++ SCANNERS
+.I flex
+provides two different ways to generate scanners for use with C++.
+The first way is to simply compile a scanner generated by
+.I flex
+using a C++ compiler instead of a C compiler.
+You should not encounter
+any compilations errors (please report any you find to the email address
+given in the Author section below).
+You can then use C++ code in your rule actions instead of C code.
+Note that the default input source for your scanner remains
+.I yyin,
+and default echoing is still done to
+.I yyout.
+Both of these remain
+.I FILE *
+variables and not C++
+.I streams.
+.PP
+You can also use
+.I flex
+to generate a C++ scanner class, using the
+.B \-+
+option (or, equivalently,
+.B %option c++),
+which is automatically specified if the name of the flex
+executable ends in a '+', such as
+.I flex++.
+When using this option, flex defaults to generating the scanner to the file
+.B lex.yy.cc
+instead of
+.B lex.yy.c.
+The generated scanner includes the header file
+.I FlexLexer.h,
+which defines the interface to two C++ classes.
+.PP
+The first class,
+.B FlexLexer,
+provides an abstract base class defining the general scanner class
+interface.
+It provides the following member functions:
+.TP
+.B const char* YYText()
+returns the text of the most recently matched token, the equivalent of
+.B yytext.
+.TP
+.B int YYLeng()
+returns the length of the most recently matched token, the equivalent of
+.B yyleng.
+.TP
+.B int lineno() const
+returns the current input line number
+(see
+.B %option yylineno),
+or
+.B 1
+if
+.B %option yylineno
+was not used.
+.TP
+.B void set_debug( int flag )
+sets the debugging flag for the scanner, equivalent to assigning to
+.B yy_flex_debug
+(see the Options section above).
+Note that you must build the scanner using
+.B %option debug
+to include debugging information in it.
+.TP
+.B int debug() const
+returns the current setting of the debugging flag.
+.PP
+Also provided are member functions equivalent to
+.B yy_switch_to_buffer(),
+.B yy_create_buffer()
+(though the first argument is an
+.B std::istream*
+object pointer and not a
+.B FILE*),
+.B yy_flush_buffer(),
+.B yy_delete_buffer(),
+and
+.B yyrestart()
+(again, the first argument is a
+.B std::istream*
+object pointer).
+.PP
+The second class defined in
+.I FlexLexer.h
+is
+.B yyFlexLexer,
+which is derived from
+.B FlexLexer.
+It defines the following additional member functions:
+.TP
+.B
+yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0 )
+constructs a
+.B yyFlexLexer
+object using the given streams for input and output.
+If not specified, the streams default to
+.B cin
+and
+.B cout,
+respectively.
+.TP
+.B virtual int yylex()
+performs the same role is
+.B yylex()
+does for ordinary flex scanners: it scans the input stream, consuming
+tokens, until a rule's action returns a value.
+If you derive a subclass
+.B S
+from
+.B yyFlexLexer
+and want to access the member functions and variables of
+.B S
+inside
+.B yylex(),
+then you need to use
+.B %option yyclass="S"
+to inform
+.I flex
+that you will be using that subclass instead of
+.B yyFlexLexer.
+In this case, rather than generating
+.B yyFlexLexer::yylex(),
+.I flex
+generates
+.B S::yylex()
+(and also generates a dummy
+.B yyFlexLexer::yylex()
+that calls
+.B yyFlexLexer::LexerError()
+if called).
+.TP
+.B
+virtual void switch_streams(std::istream* new_in = 0,
+.B
+std::ostream* new_out = 0)
+reassigns
+.B yyin
+to
+.B new_in
+(if non-nil)
+and
+.B yyout
+to
+.B new_out
+(ditto), deleting the previous input buffer if
+.B yyin
+is reassigned.
+.TP
+.B
+int yylex( std::istream* new_in, std::ostream* new_out = 0 )
+first switches the input streams via
+.B switch_streams( new_in, new_out )
+and then returns the value of
+.B yylex().
+.PP
+In addition,
+.B yyFlexLexer
+defines the following protected virtual functions which you can redefine
+in derived classes to tailor the scanner:
+.TP
+.B
+virtual int LexerInput( char* buf, int max_size )
+reads up to
+.B max_size
+characters into
+.B buf
+and returns the number of characters read.
+To indicate end-of-input, return 0 characters.
+Note that "interactive" scanners (see the
+.B \-B
+and
+.B \-I
+flags) define the macro
+.B YY_INTERACTIVE.
+If you redefine
+.B LexerInput()
+and need to take different actions depending on whether or not
+the scanner might be scanning an interactive input source, you can
+test for the presence of this name via
+.B #ifdef.
+.TP
+.B
+virtual void LexerOutput( const char* buf, int size )
+writes out
+.B size
+characters from the buffer
+.B buf,
+which, while NUL-terminated, may also contain "internal" NUL's if
+the scanner's rules can match text with NUL's in them.
+.TP
+.B
+virtual void LexerError( const char* msg )
+reports a fatal error message.
+The default version of this function writes the message to the stream
+.B cerr
+and exits.
+.PP
+Note that a
+.B yyFlexLexer
+object contains its
+.I entire
+scanning state.
+Thus you can use such objects to create reentrant scanners.
+You can instantiate multiple instances of the same
+.B yyFlexLexer
+class, and you can also combine multiple C++ scanner classes together
+in the same program using the
+.B \-P
+option discussed above.
+.PP
+Finally, note that the
+.B %array
+feature is not available to C++ scanner classes; you must use
+.B %pointer
+(the default).
+.PP
+Here is an example of a simple C++ scanner:
+.nf
+
+ // An example of using the flex C++ scanner class.
+
+ %{
+ int mylineno = 0;
+ %}
+
+ string \\"[^\\n"]+\\"
+
+ ws [ \\t]+
+
+ alpha [A-Za-z]
+ dig [0-9]
+ name ({alpha}|{dig}|\\$)({alpha}|{dig}|[_.\\-/$])*
+ num1 [-+]?{dig}+\\.?([eE][-+]?{dig}+)?
+ num2 [-+]?{dig}*\\.{dig}+([eE][-+]?{dig}+)?
+ number {num1}|{num2}
+
+ %%
+
+ {ws} /* skip blanks and tabs */
+
+ "/*" {
+ int c;
+
+ while((c = yyinput()) != 0)
+ {
+ if(c == '\\n')
+ ++mylineno;
+
+ else if(c == '*')
+ {
+ if((c = yyinput()) == '/')
+ break;
+ else
+ unput(c);
+ }
+ }
+ }
+
+ {number} cout << "number " << YYText() << '\\n';
+
+ \\n mylineno++;
+
+ {name} cout << "name " << YYText() << '\\n';
+
+ {string} cout << "string " << YYText() << '\\n';
+
+ %%
+
+ int main( int /* argc */, char** /* argv */ )
+ {
+ FlexLexer* lexer = new yyFlexLexer;
+ while(lexer->yylex() != 0)
+ ;
+ return 0;
+ }
+.fi
+If you want to create multiple (different) lexer classes, you use the
+.B \-P
+flag (or the
+.B prefix=
+option) to rename each
+.B yyFlexLexer
+to some other
+.B xxFlexLexer.
+You then can include
+.B <FlexLexer.h>
+in your other sources once per lexer class, first renaming
+.B yyFlexLexer
+as follows:
+.nf
+
+ #undef yyFlexLexer
+ #define yyFlexLexer xxFlexLexer
+ #include <FlexLexer.h>
+
+ #undef yyFlexLexer
+ #define yyFlexLexer zzFlexLexer
+ #include <FlexLexer.h>
+
+.fi
+if, for example, you used
+.B %option prefix="xx"
+for one of your scanners and
+.B %option prefix="zz"
+for the other.
+.PP
+IMPORTANT: the present form of the scanning class is
+.I experimental
+and may change considerably between major releases.
+.SH INCOMPATIBILITIES WITH LEX AND POSIX
+.I flex
+is a rewrite of the AT&T Unix
+.I lex
+tool (the two implementations do not share any code, though),
+with some extensions and incompatibilities, both of which
+are of concern to those who wish to write scanners acceptable
+to either implementation.
+Flex is fully compliant with the POSIX
+.I lex
+specification, except that when using
+.B %pointer
+(the default), a call to
+.B unput()
+destroys the contents of
+.B yytext,
+which is counter to the POSIX specification.
+.PP
+In this section we discuss all of the known areas of incompatibility
+between flex, AT&T lex, and the POSIX specification.
+.PP
+.I flex's
+.B \-l
+option turns on maximum compatibility with the original AT&T
+.I lex
+implementation, at the cost of a major loss in the generated scanner's
+performance.
+We note below which incompatibilities can be overcome
+using the
+.B \-l
+option.
+.PP
+.I flex
+is fully compatible with
+.I lex
+with the following exceptions:
+.IP -
+The undocumented
+.I lex
+scanner internal variable
+.B yylineno
+is not supported unless
+.B \-l
+or
+.B %option yylineno
+is used.
+.IP
+.B yylineno
+should be maintained on a per-buffer basis, rather than a per-scanner
+(single global variable) basis.
+.IP
+.B yylineno
+is not part of the POSIX specification.
+.IP -
+The
+.B input()
+routine is not redefinable, though it may be called to read characters
+following whatever has been matched by a rule.
+If
+.B input()
+encounters an end-of-file the normal
+.B yywrap()
+processing is done.
+A ``real'' end-of-file is returned by
+.B input()
+as
+.I EOF.
+.IP
+Input is instead controlled by defining the
+.B YY_INPUT
+macro.
+.IP
+The
+.I flex
+restriction that
+.B input()
+cannot be redefined is in accordance with the POSIX specification,
+which simply does not specify any way of controlling the
+scanner's input other than by making an initial assignment to
+.I yyin.
+.IP -
+The
+.B unput()
+routine is not redefinable.
+This restriction is in accordance with POSIX.
+.IP -
+.I flex
+scanners are not as reentrant as
+.I lex
+scanners.
+In particular, if you have an interactive scanner and
+an interrupt handler which long-jumps out of the scanner, and
+the scanner is subsequently called again, you may get the following
+message:
+.nf
+
+ fatal flex scanner internal error--end of buffer missed
+
+.fi
+To reenter the scanner, first use
+.nf
+
+ yyrestart( yyin );
+
+.fi
+Note that this call will throw away any buffered input; usually this
+isn't a problem with an interactive scanner.
+.IP
+Also note that flex C++ scanner classes
+.I are
+reentrant, so if using C++ is an option for you, you should use
+them instead.
+See "Generating C++ Scanners" above for details.
+.IP -
+.B output()
+is not supported.
+Output from the
+.B ECHO
+macro is done to the file-pointer
+.I yyout
+(default
+.I stdout).
+.IP
+.B output()
+is not part of the POSIX specification.
+.IP -
+.I lex
+does not support exclusive start conditions (%x), though they
+are in the POSIX specification.
+.IP -
+When definitions are expanded,
+.I flex
+encloses them in parentheses.
+With lex, the following:
+.nf
+
+ NAME [A-Z][A-Z0-9]*
+ %%
+ foo{NAME}? printf( "Found it\\n" );
+ %%
+
+.fi
+will not match the string "foo" because when the macro
+is expanded the rule is equivalent to "foo[A-Z][A-Z0-9]*?"
+and the precedence is such that the '?' is associated with
+"[A-Z0-9]*".
+With
+.I flex,
+the rule will be expanded to
+"foo([A-Z][A-Z0-9]*)?" and so the string "foo" will match.
+.IP
+Note that if the definition begins with
+.B ^
+or ends with
+.B $
+then it is
+.I not
+expanded with parentheses, to allow these operators to appear in
+definitions without losing their special meanings.
+But the
+.B <s>, /,
+and
+.B <<EOF>>
+operators cannot be used in a
+.I flex
+definition.
+.IP
+Using
+.B \-l
+results in the
+.I lex
+behavior of no parentheses around the definition.
+.IP
+The POSIX specification is that the definition be enclosed in parentheses.
+.IP -
+Some implementations of
+.I lex
+allow a rule's action to begin on a separate line, if the rule's pattern
+has trailing whitespace:
+.nf
+
+ %%
+ foo|bar<space here>
+ { foobar_action(); }
+
+.fi
+.I flex
+does not support this feature.
+.IP -
+The
+.I lex
+.B %r
+(generate a Ratfor scanner) option is not supported.
+It is not part
+of the POSIX specification.
+.IP -
+After a call to
+.B unput(),
+.I yytext
+is undefined until the next token is matched, unless the scanner
+was built using
+.B %array.
+This is not the case with
+.I lex
+or the POSIX specification.
+The
+.B \-l
+option does away with this incompatibility.
+.IP -
+The precedence of the
+.B {}
+(numeric range) operator is different.
+.I lex
+interprets "abc{1,3}" as "match one, two, or
+three occurrences of 'abc'", whereas
+.I flex
+interprets it as "match 'ab'
+followed by one, two, or three occurrences of 'c'".
+The latter is in agreement with the POSIX specification.
+.IP -
+The precedence of the
+.B ^
+operator is different.
+.I lex
+interprets "^foo|bar" as "match either 'foo' at the beginning of a line,
+or 'bar' anywhere", whereas
+.I flex
+interprets it as "match either 'foo' or 'bar' if they come at the beginning
+of a line".
+The latter is in agreement with the POSIX specification.
+.IP -
+The special table-size declarations such as
+.B %a
+supported by
+.I lex
+are not required by
+.I flex
+scanners;
+.I flex
+ignores them.
+.IP -
+The name
+.B FLEX_SCANNER
+is #define'd so scanners may be written for use with either
+.I flex
+or
+.I lex.
+Scanners also include
+.B YY_FLEX_MAJOR_VERSION
+and
+.B YY_FLEX_MINOR_VERSION
+indicating which version of
+.I flex
+generated the scanner
+(for example, for the 2.5 release, these defines would be 2 and 5
+respectively).
+.PP
+The following
+.I flex
+features are not included in
+.I lex
+or the POSIX specification:
+.nf
+
+ C++ scanners
+ %option
+ start condition scopes
+ start condition stacks
+ interactive/non-interactive scanners
+ yy_scan_string() and friends
+ yyterminate()
+ yy_set_interactive()
+ yy_set_bol()
+ YY_AT_BOL()
+ <<EOF>>
+ <*>
+ YY_DECL
+ YY_START
+ YY_USER_ACTION
+ YY_USER_INIT
+ #line directives
+ %{}'s around actions
+ multiple actions on a line
+
+.fi
+plus almost all of the flex flags.
+The last feature in the list refers to the fact that with
+.I flex
+you can put multiple actions on the same line, separated with
+semi-colons, while with
+.I lex,
+the following
+.nf
+
+ foo handle_foo(); ++num_foos_seen;
+
+.fi
+is (rather surprisingly) truncated to
+.nf
+
+ foo handle_foo();
+
+.fi
+.I flex
+does not truncate the action.
+Actions that are not enclosed in
+braces are simply terminated at the end of the line.
+.SH DIAGNOSTICS
+.I warning, rule cannot be matched
+indicates that the given rule
+cannot be matched because it follows other rules that will
+always match the same text as it.
+For example, in the following "foo" cannot be matched because it comes after
+an identifier "catch-all" rule:
+.nf
+
+ [a-z]+ got_identifier();
+ foo got_foo();
+
+.fi
+Using
+.B REJECT
+in a scanner suppresses this warning.
+.PP
+.I warning,
+.B \-s
+.I
+option given but default rule can be matched
+means that it is possible (perhaps only in a particular start condition)
+that the default rule (match any single character) is the only one
+that will match a particular input.
+Since
+.B \-s
+was given, presumably this is not intended.
+.PP
+.I reject_used_but_not_detected undefined
+or
+.I yymore_used_but_not_detected undefined -
+These errors can occur at compile time.
+They indicate that the scanner uses
+.B REJECT
+or
+.B yymore()
+but that
+.I flex
+failed to notice the fact, meaning that
+.I flex
+scanned the first two sections looking for occurrences of these actions
+and failed to find any, but somehow you snuck some in (via a #include
+file, for example).
+Use
+.B %option reject
+or
+.B %option yymore
+to indicate to flex that you really do use these features.
+.PP
+.I flex scanner jammed -
+a scanner compiled with
+.B \-s
+has encountered an input string which wasn't matched by
+any of its rules.
+This error can also occur due to internal problems.
+.PP
+.I token too large, exceeds YYLMAX -
+your scanner uses
+.B %array
+and one of its rules matched a string longer than the
+.B YYLMAX
+constant (8K bytes by default).
+You can increase the value by
+#define'ing
+.B YYLMAX
+in the definitions section of your
+.I flex
+input.
+.PP
+.I scanner requires \-8 flag to
+.I use the character 'x' -
+Your scanner specification includes recognizing the 8-bit character
+.I 'x'
+and you did not specify the \-8 flag, and your scanner defaulted to 7-bit
+because you used the
+.B \-Cf
+or
+.B \-CF
+table compression options.
+See the discussion of the
+.B \-7
+flag for details.
+.PP
+.I flex scanner push-back overflow -
+you used
+.B unput()
+to push back so much text that the scanner's buffer could not hold
+both the pushed-back text and the current token in
+.B yytext.
+Ideally the scanner should dynamically resize the buffer in this case, but at
+present it does not.
+.PP
+.I
+input buffer overflow, can't enlarge buffer because scanner uses REJECT -
+the scanner was working on matching an extremely large token and needed
+to expand the input buffer.
+This doesn't work with scanners that use
+.B
+REJECT.
+.PP
+.I
+fatal flex scanner internal error--end of buffer missed -
+This can occur in a scanner which is reentered after a long-jump
+has jumped out (or over) the scanner's activation frame.
+Before reentering the scanner, use:
+.nf
+
+ yyrestart( yyin );
+
+.fi
+or, as noted above, switch to using the C++ scanner class.
+.PP
+.I too many start conditions in <> construct! -
+you listed more start conditions in a <> construct than exist (so
+you must have listed at least one of them twice).
+.SH FILES
+.TP
+.B \-ll
+library with which scanners must be linked.
+.TP
+.I lex.yy.c
+generated scanner (called
+.I lexyy.c
+on some systems).
+.TP
+.I lex.yy.cc
+generated C++ scanner class, when using
+.B -+.
+.TP
+.I <FlexLexer.h>
+header file defining the C++ scanner base class,
+.B FlexLexer,
+and its derived class,
+.B yyFlexLexer.
+.TP
+.I flex.skl
+skeleton scanner.
+This file is only used when building flex, not when flex executes.
+.TP
+.I lex.backup
+backing-up information for
+.B \-b
+flag (called
+.I lex.bck
+on some systems).
+.SH DEFICIENCIES / BUGS
+Some trailing context
+patterns cannot be properly matched and generate
+warning messages ("dangerous trailing context").
+These are patterns where the ending of the
+first part of the rule matches the beginning of the second
+part, such as "zx*/xy*", where the 'x*' matches the 'x' at
+the beginning of the trailing context.
+(Note that the POSIX draft
+states that the text matched by such patterns is undefined.)
+.PP
+For some trailing context rules, parts which are actually fixed-length are
+not recognized as such, leading to the above mentioned performance loss.
+In particular, parts using '|' or {n} (such as "foo{3}") are always
+considered variable-length.
+.PP
+Combining trailing context with the special '|' action can result in
+.I fixed
+trailing context being turned into the more expensive
+.I variable
+trailing context.
+For example, in the following:
+.nf
+
+ %%
+ abc |
+ xyz/def
+
+.fi
+.PP
+Use of
+.B unput()
+invalidates yytext and yyleng, unless the
+.B %array
+directive
+or the
+.B \-l
+option has been used.
+.PP
+Pattern-matching of NUL's is substantially slower than matching other
+characters.
+.PP
+Dynamic resizing of the input buffer is slow, as it entails rescanning
+all the text matched so far by the current (generally huge) token.
+.PP
+Due to both buffering of input and read-ahead, you cannot intermix
+calls to <stdio.h> routines, such as, for example,
+.B getchar(),
+with
+.I flex
+rules and expect it to work.
+Call
+.B input()
+instead.
+.PP
+The total table entries listed by the
+.B \-v
+flag excludes the number of table entries needed to determine
+what rule has been matched.
+The number of entries is equal
+to the number of DFA states if the scanner does not use
+.B REJECT,
+and somewhat greater than the number of states if it does.
+.PP
+.B REJECT
+cannot be used with the
+.B \-f
+or
+.B \-F
+options.
+.PP
+The
+.I flex
+internal algorithms need documentation.
+.SH SEE ALSO
+lex(1), yacc(1), sed(1), awk(1).
+.PP
+John Levine, Tony Mason, and Doug Brown,
+.I Lex & Yacc,
+O'Reilly and Associates.
+Be sure to get the 2nd edition.
+.PP
+M. E. Lesk and E. Schmidt,
+.I LEX \- Lexical Analyzer Generator
+.PP
+Alfred Aho, Ravi Sethi and Jeffrey Ullman,
+.I Compilers: Principles, Techniques and Tools,
+Addison-Wesley (1986).
+Describes the pattern-matching techniques used by
+.I flex
+(deterministic finite automata).
+.SH AUTHOR
+Vern Paxson, with the help of many ideas and much inspiration from
+Van Jacobson.
+Original version by Jef Poskanzer.
+The fast table
+representation is a partial implementation of a design done by Van
+Jacobson.
+The implementation was done by Kevin Gong and Vern Paxson.
+.PP
+Thanks to the many
+.I flex
+beta-testers, feedbackers, and contributors, especially Francois Pinard,
+Casey Leedom,
+Robert Abramovitz,
+Stan Adermann, Terry Allen, David Barker-Plummer, John Basrai,
+Neal Becker, Nelson H.F. Beebe, benson@odi.com,
+Karl Berry, Peter A. Bigot, Simon Blanchard,
+Keith Bostic, Frederic Brehm, Ian Brockbank, Kin Cho, Nick Christopher,
+Brian Clapper, J.T. Conklin,
+Jason Coughlin, Bill Cox, Nick Cropper, Dave Curtis, Scott David
+Daniels, Chris G. Demetriou, Theo de Raadt,
+Mike Donahue, Chuck Doucette, Tom Epperly, Leo Eskin,
+Chris Faylor, Chris Flatters, Jon Forrest, Jeffrey Friedl,
+Joe Gayda, Kaveh R. Ghazi, Wolfgang Glunz,
+Eric Goldman, Christopher M. Gould, Ulrich Grepel, Peer Griebel,
+Jan Hajic, Charles Hemphill, NORO Hideo,
+Jarkko Hietaniemi, Scott Hofmann,
+Jeff Honig, Dana Hudes, Eric Hughes, John Interrante,
+Ceriel Jacobs, Michal Jaegermann, Sakari Jalovaara, Jeffrey R. Jones,
+Henry Juengst, Klaus Kaempf, Jonathan I. Kamens, Terrence O Kane,
+Amir Katz, ken@ken.hilco.com, Kevin B. Kenny,
+Steve Kirsch, Winfried Koenig, Marq Kole, Ronald Lamprecht,
+Greg Lee, Rohan Lenard, Craig Leres, John Levine, Steve Liddle,
+David Loffredo, Mike Long,
+Mohamed el Lozy, Brian Madsen, Malte, Joe Marshall,
+Bengt Martensson, Chris Metcalf,
+Luke Mewburn, Jim Meyering, R. Alexander Milowski, Erik Naggum,
+G.T. Nicol, Landon Noll, James Nordby, Marc Nozell,
+Richard Ohnemus, Karsten Pahnke,
+Sven Panne, Roland Pesch, Walter Pelissero, Gaumond
+Pierre, Esmond Pitt, Jef Poskanzer, Joe Rahmeh, Jarmo Raiha,
+Frederic Raimbault, Pat Rankin, Rick Richardson,
+Kevin Rodgers, Kai Uwe Rommel, Jim Roskind, Alberto Santini,
+Andreas Scherer, Darrell Schiebel, Raf Schietekat,
+Doug Schmidt, Philippe Schnoebelen, Andreas Schwab,
+Larry Schwimmer, Alex Siegel, Eckehard Stolz, Jan-Erik Strvmquist,
+Mike Stump, Paul Stuart, Dave Tallman, Ian Lance Taylor,
+Chris Thewalt, Richard M. Timoney, Jodi Tsai,
+Paul Tuinenga, Gary Weik, Frank Whaley, Gerhard Wilhelms, Kent Williams, Ken
+Yap, Ron Zellar, Nathan Zelle, David Zuhn,
+and those whose names have slipped my marginal
+mail-archiving skills but whose contributions are appreciated all the
+same.
+.PP
+Thanks to Keith Bostic, Jon Forrest, Noah Friedman,
+John Gilmore, Craig Leres, John Levine, Bob Mulcahy, G.T.
+Nicol, Francois Pinard, Rich Salz, and Richard Stallman for help with various
+distribution headaches.
+.PP
+Thanks to Esmond Pitt and Earle Horton for 8-bit character support; to
+Benson Margulies and Fred Burke for C++ support; to Kent Williams and Tom
+Epperly for C++ class support; to Ove Ewerlid for support of NUL's; and to
+Eric Hughes for support of multiple buffers.
+.PP
+This work was primarily done when I was with the Real Time Systems Group
+at the Lawrence Berkeley Laboratory in Berkeley, CA.
+Many thanks to all there for the support I received.
+.PP
+Send comments to vern@ee.lbl.gov.
diff --git a/usr.bin/lex/lib/Makefile b/usr.bin/lex/lib/Makefile
new file mode 100644
index 000000000000..3586f94a8957
--- /dev/null
+++ b/usr.bin/lex/lib/Makefile
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+.PATH: ${SRCTOP}/contrib/flex/src
+
+LIB= ln
+SRCS= libmain.c libyywrap.c
+NO_PIC=
+
+.if ${MK_INSTALLLIB} != "no"
+LINKS= ${LIBDIR}/libln.a ${LIBDIR}/libl.a
+LINKS+= ${LIBDIR}/libln.a ${LIBDIR}/libfl.a
+.endif
+
+.include <bsd.lib.mk>
+
diff --git a/usr.bin/lex/lib/Makefile.depend b/usr.bin/lex/lib/Makefile.depend
new file mode 100644
index 000000000000..993ab0638f4a
--- /dev/null
+++ b/usr.bin/lex/lib/Makefile.depend
@@ -0,0 +1,11 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lex/version.awk b/usr.bin/lex/version.awk
new file mode 100644
index 000000000000..ab56ebc41419
--- /dev/null
+++ b/usr.bin/lex/version.awk
@@ -0,0 +1,10 @@
+
+BEGIN {
+ FS = "[ \t\.\"]+"
+}
+
+{
+ if ($1 ~ /^#define$/ && $2 ~ /^VERSION$/) {
+ printf("%s.%s.%s\n", $3, $4, $5);
+ }
+}
diff --git a/usr.bin/limits/Makefile b/usr.bin/limits/Makefile
new file mode 100644
index 000000000000..1c7e91de9e49
--- /dev/null
+++ b/usr.bin/limits/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= limits
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/limits/Makefile.depend b/usr.bin/limits/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/limits/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/limits/limits.1 b/usr.bin/limits/limits.1
new file mode 100644
index 000000000000..0e374acd991b
--- /dev/null
+++ b/usr.bin/limits/limits.1
@@ -0,0 +1,456 @@
+.\" Copyright (c) 1996 David Nugent <davidn@blaze.net.au>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, is permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice immediately at the beginning of the file, without modification,
+.\" 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. This work was done expressly for inclusion into FreeBSD. Other use
+.\" is permitted provided this notation is included.
+.\" 4. Absolutely no warranty of function or purpose is made by the author
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.Dd June 25, 2020
+.Dt LIMITS 1
+.Os
+.Sh NAME
+.Nm limits
+.Nd set or display process resource limits
+.Sh SYNOPSIS
+.Nm
+.Op Fl C Ar class | Fl P Ar pid | Fl U Ar user
+.Op Fl SHB
+.Op Fl ea
+.Op Fl bcdfklmnopstuvw Op Ar val
+.Nm
+.Op Fl C Ar class | Fl U Ar user
+.Op Fl SHB
+.Op Fl bcdfklmnopstuvwy Op Ar val
+.Op Fl E
+.Oo
+.Op Ar name Ns = Ns Ar value ...
+.Ar command
+.Oc
+.Sh DESCRIPTION
+The
+.Nm
+utility either prints or sets kernel resource limits, and may optionally set
+environment variables like
+.Xr env 1
+and run a program with the selected resources.
+Three uses of the
+.Nm
+utility are possible:
+.Bl -tag -width indent
+.It Xo
+.Nm
+.Op Ar limitflags
+.Op Ar name Ns = Ns Ar value ...
+.Ar command
+.Xc
+This usage sets limits according to
+.Ar limitflags ,
+optionally sets environment variables given as
+.Ar name Ns = Ns Ar value
+pairs, and then runs the specified
+.Ar command .
+.It Nm Op Ar limitflags
+This usage determines values of resource settings according to
+.Ar limitflags ,
+does not attempt to set them and outputs these values to
+standard output.
+By default, this will output the current kernel resource settings
+active for the calling process.
+Using the
+.Fl C Ar class
+or
+.Fl U Ar user
+options, you may also display the current resource settings modified
+by the appropriate login class resource limit entries from
+the
+.Xr login.conf 5
+login capabilities database.
+.It Nm Fl e Op Ar limitflags
+This usage determines values of resource settings according to
+.Ar limitflags ,
+but does not set them.
+Like the previous usage, it outputs these values to standard
+output, except that it will emit them in
+.Ic eval
+format, suitable for the calling shell.
+If the shell is known (i.e., it is one of
+.Nm sh , csh , bash , tcsh , ksh , pdksh
+or
+.Nm rc ) ,
+.Nm
+emits
+.Ic limit
+or
+.Ic ulimit
+commands in the format understood by
+that shell.
+If the name of the shell cannot be determined, then the
+.Ic ulimit
+format used by
+.Xr sh 1
+is used.
+.Pp
+This is very useful for setting limits used by scripts, or prior
+launching of daemons and other background tasks with specific
+resource limit settings, and provides the benefit of allowing
+global configuration of maximum resource usage by maintaining a
+central database of settings in the login class database.
+.Pp
+Within a shell script,
+.Nm
+will normally be used with eval within backticks as follows:
+.Pp
+.Dl "eval `limits -e -C daemon`"
+.Pp
+which causes the output of
+.Nm
+to be evaluated and set by the current shell.
+.El
+.Pp
+The value of
+.Ar limitflags
+specified in the above contains one or more of the following options:
+.Bl -tag -width ".Fl C Ar class"
+.It Fl C Ar class
+Use current resource values, modified by the resource entries applicable
+for the login class
+.Ar class .
+.It Fl U Ar user
+Use current resource values, modified by the resource entries applicable
+to the login class the
+.Ar user
+belongs to.
+If user does not belong to any class, then the resource capabilities
+for the
+.Dq Li default
+class are used, if it exists, or the
+.Dq Li root
+class if the user is a superuser account.
+.It Fl P Ar pid
+Select or set limits for the process identified by the
+.Ar pid .
+.It Fl S
+Select display or setting of
+.Dq soft
+(or current) resource limits.
+If specific limits settings follow this switch, only soft limits are
+affected unless overridden later with either the
+.Fl H
+or
+.Fl B
+options.
+.It Fl H
+Select display or setting of
+.Dq hard
+(or maximum) resource limits.
+If specific limits settings follow this switch, only hard limits are
+affected until overridden later with either the
+.Fl S
+or
+.Fl B
+options.
+.It Fl B
+Select display or setting of both
+.Dq soft
+(current) or
+.Dq hard
+(maximum)
+resource limits.
+If specific limits settings follow this switch, both soft and hard
+limits are affected until overridden later with either the
+.Fl S
+or
+.Fl H
+options.
+.It Fl e
+Select
+.Dq "eval mode"
+formatting for output.
+This is valid only in display mode and cannot be used when running a
+command.
+The exact syntax used for output depends upon the type of shell from
+which
+.Nm
+is invoked.
+.It Fl b Op Ar val
+Select or set the
+.Va sbsize
+resource limit.
+.It Fl c Op Ar val
+Select or set (if
+.Ar val
+is specified) the
+.Va coredumpsize
+resource limit.
+A value of 0 disables core dumps.
+.It Fl d Op Ar val
+Select or set (if
+.Ar val
+is specified) the
+.Va datasize
+resource limit.
+.It Fl f Op Ar val
+Select or set the
+.Va filesize
+resource limit.
+.It Fl k Op Ar val
+Select or set the
+.Va kqueues
+resource limit.
+.It Fl l Op Ar val
+Select or set the
+.Va memorylocked
+resource limit.
+.It Fl m Op Ar val
+Select or set the
+.Va memoryuse
+size limit.
+.It Fl n Op Ar val
+Select or set the
+.Va openfiles
+resource limit.
+The system-wide limit on the maximum number of
+open files per process can be viewed by examining the
+.Va kern.maxfilesperproc
+.Xr sysctl 8
+variable.
+The total number of simultaneously open files in the entire
+system is limited to the value displayed by the
+.Va kern.maxfiles
+.Xr sysctl 8
+variable.
+.It Fl o Op Ar val
+Select or set the
+.Va umtxp
+resource limit.
+The limit determines the maximal number of the process-shared locks
+which may be simultaneously created by the processes owned by the
+user, see
+.Xr pthread 3 .
+.It Fl p Op Ar val
+Select or set the
+.Va pseudoterminals
+resource limit.
+.It Fl s Op Ar val
+Select or set the
+.Va stacksize
+resource limit.
+.It Fl t Op Ar val
+Select or set the
+.Va cputime
+resource limit.
+.It Fl u Op Ar val
+Select or set the
+.Va maxproc
+resource limit.
+The system-wide limit on the maximum number of processes
+allowed per UID can be viewed by examining the
+.Va kern.maxprocperuid
+.Xr sysctl 8
+variable.
+The maximum number of processes that can be running simultaneously
+in the entire system is limited to the value of the
+.Va kern.maxproc
+.Xr sysctl 8
+variable.
+.It Fl v Op Ar val
+Select or set the
+.Va virtualmem
+resource limit.
+This limit encompasses the entire VM space for the user process
+and is inclusive of text, data, bss, stack,
+.Xr brk 2 ,
+.Xr sbrk 2
+and
+.Xr mmap 2 Ns 'd
+space.
+.It Fl w Op Ar val
+Select or set the
+.Va swapuse
+resource limit.
+.It Fl y Op Ar val
+Select or set the
+.Va pipebuf
+resource limit.
+.El
+.Pp
+Valid values for
+.Ar val
+in the above set of options consist of either the
+string
+.Dq Li infinity ,
+.Dq Li inf ,
+.Dq Li unlimited
+or
+.Dq Li unlimit
+for an infinite (or kernel-defined maximum)
+limit, or a numeric value optionally followed by a suffix.
+Values which relate to size default to a value in bytes, or one of the
+following suffixes may be used as a multiplier:
+.Pp
+.Bl -tag -offset indent -width 4n -compact
+.It Li b
+512 byte blocks.
+.It Li k
+kilobytes (1024 bytes).
+.It Li m
+megabytes (1024*1024 bytes).
+.It Li g
+gigabytes.
+.It Li t
+terabytes.
+.El
+.Pp
+The
+.Va cputime
+resource defaults to a number of seconds, but a multiplier may be
+used, and as with size values, multiple values separated by a valid
+suffix are added together:
+.Pp
+.Bl -tag -offset indent -width 4n -compact
+.It Li s
+seconds.
+.It Li m
+minutes.
+.It Li h
+hours.
+.It Li d
+days.
+.It Li w
+weeks.
+.It Li y
+365 day years.
+.El
+.Bl -tag -width ".Fl C Ar class"
+.It Fl E
+Cause
+.Nm
+to completely ignore the environment it inherits.
+.It Fl a
+Force all resource settings to be displayed even if
+other specific resource settings have been specified.
+For example, if you wish to disable core dumps when starting up
+the Usenet News system, but wish to set all other resource settings
+as well that apply to the
+.Dq Li news
+account, you might use:
+.Pp
+.Dl "eval `limits -U news -aBec 0`"
+.Pp
+As with the
+.Xr setrlimit 2
+call, only the superuser may raise process
+.Dq hard
+resource limits.
+Non-root users may, however, lower them or change
+.Dq soft
+resource limits
+within to any value below the hard limit.
+When invoked to execute a program, the failure of
+.Nm
+to raise a hard limit is considered a fatal error.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility
+exits with
+.Dv EXIT_FAILURE
+if usage is incorrect in any way; i.e., an invalid
+option, or set/display options are selected in the same invocation,
+.Fl e
+is used when running a program, etc.
+When run in display or eval mode,
+.Nm
+exits with a status of
+.Dv EXIT_SUCCESS .
+When run in command mode and execution of the command succeeds, the exit status
+will be whatever the executed program returns.
+.Sh EXAMPLES
+Show current stack size limit:
+.Bd -literal -offset indent
+$ limits -s
+Resource limits (current):
+ stacksize 524288 kB
+.Ed
+.Pp
+Try to run
+.Xr ls 1
+with 1 byte of
+.Va datasize
+limit:
+.Bd -literal -offset indent
+$ limits -d 1b ls
+Data segment size exceeds process limit
+Abort trap
+.Ed
+.Pp
+Produce
+.Ql eval mode
+output to limit
+.Va sbsize
+to 1 byte.
+Output obtained when command is run from
+.Xr sh 1 :
+.Bd -literal -offset indent
+$ limits -e -b 1b
+ulimit -b 512;
+.Ed
+.Pp
+Same as above from
+.Xr csh 1
+.Bd -literal -offset indent
+% limits -e -b 1b
+limit -h sbsize 512;
+limit sbsize 512;
+.Ed
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr env 1 ,
+.Xr limit 1 ,
+.Xr sh 1 ,
+.Xr getrlimit 2 ,
+.Xr setrlimit 2 ,
+.Xr login_cap 3 ,
+.Xr login.conf 5 ,
+.Xr rctl 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 2.1.7 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An David Nugent Aq Mt davidn@FreeBSD.org .
+.Sh BUGS
+The
+.Nm
+utility does not handle commands with equal
+.Pq Ql =
+signs in their
+names, for obvious reasons.
+.Pp
+The
+.Nm
+utility makes no effort to ensure that resource settings emitted or displayed
+are valid and settable by the current user.
+Only a superuser account may raise hard limits, and when doing so
+the
+.Fx
+kernel will silently lower limits to values less than
+specified if the values given are too high.
diff --git a/usr.bin/limits/limits.c b/usr.bin/limits/limits.c
new file mode 100644
index 000000000000..c53066b52a9f
--- /dev/null
+++ b/usr.bin/limits/limits.c
@@ -0,0 +1,782 @@
+/*-
+ * Copyright (c) 1997 by
+ * David L. Nugent <davidn@blaze.net.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, is permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * 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. This work was done expressly for inclusion into FreeBSD. Other use
+ * is permitted provided this notation is included.
+ * 4. Absolutely no warranty of function or purpose is made by the authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * Display/change(+runprogram)/eval resource limits.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <errno.h>
+#include <pwd.h>
+#include <login_cap.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+enum
+{
+ SH_NONE,
+ SH_SH, /* sh */
+ SH_CSH, /* csh */
+ SH_BASH, /* gnu bash */
+ SH_TCSH, /* tcsh */
+ SH_KSH, /* (pd)ksh */
+ SH_ZSH, /* zsh */
+ SH_RC, /* rc or es */
+ SH_NUMBER
+};
+
+
+/* eval emitter for popular shells.
+ * Why aren't there any standards here? Most shells support either
+ * the csh 'limit' or sh 'ulimit' command, but each varies just
+ * enough that they aren't very compatible from one to the other.
+ */
+static struct {
+ const char * name; /* Name of shell */
+ const char * inf; /* Name used for 'unlimited' resource */
+ const char * cmd; /* Intro text */
+ const char * hard; /* Hard limit text */
+ const char * soft; /* Soft limit text */
+ const char * both; /* Hard+Soft limit text */
+ struct {
+ const char * pfx;
+ const char * sfx;
+ int divisor;
+ } lprm[RLIM_NLIMITS];
+} shellparm[] =
+{
+ { "", "infinity", "Resource limits%s%s:\n", "-max", "-cur", "",
+ {
+ { " cputime%-4s %8s", " secs\n", 1 },
+ { " filesize%-4s %8s", " kB\n", 1024 },
+ { " datasize%-4s %8s", " kB\n", 1024 },
+ { " stacksize%-4s %8s", " kB\n", 1024 },
+ { " coredumpsize%-4s %8s", " kB\n", 1024 },
+ { " memoryuse%-4s %8s", " kB\n", 1024 },
+ { " memorylocked%-4s %8s", " kB\n", 1024 },
+ { " maxprocesses%-4s %8s", "\n", 1 },
+ { " openfiles%-4s %8s", "\n", 1 },
+ { " sbsize%-4s %8s", " bytes\n", 1 },
+ { " vmemoryuse%-4s %8s", " kB\n", 1024 },
+ { " pseudo-terminals%-4s %8s", "\n", 1 },
+ { " swapuse%-4s %8s", " kB\n", 1024 },
+ { " kqueues%-4s %8s", "\n", 1 },
+ { " umtxp%-4s %8s", "\n", 1 },
+ { " pipebuf%-4s %8s", " kB\n", 1024 },
+ }
+ },
+ { "sh", "unlimited", "", " -H", " -S", "",
+ {
+ { "ulimit%s -t %s", ";\n", 1 },
+ { "ulimit%s -f %s", ";\n", 512 },
+ { "ulimit%s -d %s", ";\n", 1024 },
+ { "ulimit%s -s %s", ";\n", 1024 },
+ { "ulimit%s -c %s", ";\n", 512 },
+ { "ulimit%s -m %s", ";\n", 1024 },
+ { "ulimit%s -l %s", ";\n", 1024 },
+ { "ulimit%s -u %s", ";\n", 1 },
+ { "ulimit%s -n %s", ";\n", 1 },
+ { "ulimit%s -b %s", ";\n", 1 },
+ { "ulimit%s -v %s", ";\n", 1024 },
+ { "ulimit%s -p %s", ";\n", 1 },
+ { "ulimit%s -w %s", ";\n", 1024 },
+ { "ulimit%s -k %s", ";\n", 1 },
+ { "ulimit%s -o %s", ";\n", 1 },
+ { "ulimit%s -y %s", ";\n", 1024 },
+ }
+ },
+ { "csh", "unlimited", "", " -h", "", NULL,
+ {
+ { "limit%s cputime %s", ";\n", 1 },
+ { "limit%s filesize %s", ";\n", 1024 },
+ { "limit%s datasize %s", ";\n", 1024 },
+ { "limit%s stacksize %s", ";\n", 1024 },
+ { "limit%s coredumpsize %s", ";\n", 1024 },
+ { "limit%s memoryuse %s", ";\n", 1024 },
+ { "limit%s memorylocked %s", ";\n", 1024 },
+ { "limit%s maxproc %s", ";\n", 1 },
+ { "limit%s openfiles %s", ";\n", 1 },
+ { "limit%s sbsize %s", ";\n", 1 },
+ { "limit%s vmemoryuse %s", ";\n", 1024 },
+ { "limit%s pseudoterminals %s", ";\n", 1 },
+ { "limit%s swapsize %s", ";\n", 1024 },
+ { "limit%s kqueues %s", ";\n", 1 },
+ { "limit%s umtxp %s", ";\n", 1 },
+ }
+ },
+ { "bash|bash2", "unlimited", "", " -H", " -S", "",
+ {
+ { "ulimit%s -t %s", ";\n", 1 },
+ { "ulimit%s -f %s", ";\n", 1024 },
+ { "ulimit%s -d %s", ";\n", 1024 },
+ { "ulimit%s -s %s", ";\n", 1024 },
+ { "ulimit%s -c %s", ";\n", 1024 },
+ { "ulimit%s -m %s", ";\n", 1024 },
+ { "ulimit%s -l %s", ";\n", 1024 },
+ { "ulimit%s -u %s", ";\n", 1 },
+ { "ulimit%s -n %s", ";\n", 1 },
+ { "ulimit%s -b %s", ";\n", 1 },
+ { "ulimit%s -v %s", ";\n", 1024 },
+ { "ulimit%s -p %s", ";\n", 1 },
+ { "ulimit%s -w %s", ";\n", 1024 }
+ }
+ },
+ { "tcsh", "unlimited", "", " -h", "", NULL,
+ {
+ { "limit%s cputime %s", ";\n", 1 },
+ { "limit%s filesize %s", ";\n", 1024 },
+ { "limit%s datasize %s", ";\n", 1024 },
+ { "limit%s stacksize %s", ";\n", 1024 },
+ { "limit%s coredumpsize %s", ";\n", 1024 },
+ { "limit%s memoryuse %s", ";\n", 1024 },
+ { "limit%s memorylocked %s", ";\n", 1024 },
+ { "limit%s maxproc %s", ";\n", 1 },
+ { "limit%s descriptors %s", ";\n", 1 },
+ { "limit%s sbsize %s", ";\n", 1 },
+ { "limit%s vmemoryuse %s", ";\n", 1024 },
+ { "limit%s pseudoterminals %s", ";\n", 1 },
+ { "limit%s swapsize %s", ";\n", 1024 },
+ { "limit%s kqueues %s", ";\n", 1 },
+ { "limit%s umtxp %s", ";\n", 1 },
+ }
+ },
+ { "ksh|pdksh", "unlimited", "", " -H", " -S", "",
+ {
+ { "ulimit%s -t %s", ";\n", 1 },
+ { "ulimit%s -f %s", ";\n", 512 },
+ { "ulimit%s -d %s", ";\n", 1024 },
+ { "ulimit%s -s %s", ";\n", 1024 },
+ { "ulimit%s -c %s", ";\n", 512 },
+ { "ulimit%s -m %s", ";\n", 1024 },
+ { "ulimit%s -l %s", ";\n", 1024 },
+ { "ulimit%s -p %s", ";\n", 1 },
+ { "ulimit%s -n %s", ";\n", 1 },
+ { "ulimit%s -b %s", ";\n", 1 },
+ { "ulimit%s -v %s", ";\n", 1024 },
+ { "ulimit%s -p %s", ";\n", 1 },
+ { "ulimit%s -w %s", ";\n", 1024 }
+ }
+ },
+ { "zsh", "unlimited", "", " -H", " -S", "",
+ {
+ { "ulimit%s -t %s", ";\n", 1 },
+ { "ulimit%s -f %s", ";\n", 512 },
+ { "ulimit%s -d %s", ";\n", 1024 },
+ { "ulimit%s -s %s", ";\n", 1024 },
+ { "ulimit%s -c %s", ";\n", 512 },
+ { "ulimit%s -m %s", ";\n", 1024 },
+ { "ulimit%s -l %s", ";\n", 1024 },
+ { "ulimit%s -u %s", ";\n", 1 },
+ { "ulimit%s -n %s", ";\n", 1 },
+ { "ulimit%s -b %s", ";\n", 1 },
+ { "ulimit%s -v %s", ";\n", 1024 },
+ { "ulimit%s -p %s", ";\n", 1 },
+ { "ulimit%s -w %s", ";\n", 1024 }
+ }
+ },
+ { "rc|es", "unlimited", "", " -h", "", NULL,
+ {
+ { "limit%s cputime %s", ";\n", 1 },
+ { "limit%s filesize %s", ";\n", 1024 },
+ { "limit%s datasize %s", ";\n", 1024 },
+ { "limit%s stacksize %s", ";\n", 1024 },
+ { "limit%s coredumpsize %s", ";\n", 1024 },
+ { "limit%s memoryuse %s", ";\n", 1024 },
+ { "limit%s lockedmemory %s", ";\n", 1024 },
+ { "limit%s processes %s", ";\n", 1 },
+ { "limit%s descriptors %s", ";\n", 1 },
+ { "limit%s sbsize %s", ";\n", 1 },
+ { "limit%s vmemoryuse %s", ";\n", 1024 },
+ { "limit%s pseudoterminals %s", ";\n", 1 },
+ { "limit%s swapuse %s", ";\n", 1024 }
+ }
+ },
+ { NULL, NULL, NULL, NULL, NULL, NULL,
+ { }
+ }
+};
+
+static struct {
+ const char * cap;
+ rlim_t (*func)(login_cap_t *, const char *, rlim_t, rlim_t);
+} resources[RLIM_NLIMITS] = {
+ { "cputime", login_getcaptime },
+ { "filesize", login_getcapsize },
+ { "datasize", login_getcapsize },
+ { "stacksize", login_getcapsize },
+ { "coredumpsize", login_getcapsize },
+ { "memoryuse", login_getcapsize },
+ { "memorylocked", login_getcapsize },
+ { "maxproc", login_getcapnum },
+ { "openfiles", login_getcapnum },
+ { "sbsize", login_getcapsize },
+ { "vmemoryuse", login_getcapsize },
+ { "pseudoterminals",login_getcapnum },
+ { "swapuse", login_getcapsize },
+ { "kqueues", login_getcapnum },
+ { "umtxp", login_getcapnum },
+ { "pipebuf", login_getcapnum },
+};
+
+/*
+ * One letter for each resource levels.
+ * NOTE: There is a dependency on the corresponding
+ * letter index being equal to the resource number.
+ * If sys/resource.h defines are changed, this needs
+ * to be modified accordingly!
+ */
+
+#define RCS_STRING "tfdscmlunbvpwkoy"
+
+static rlim_t resource_num(int which, int ch, const char *str);
+static void usage(void) __dead2;
+static int getshelltype(void);
+static void print_limit(rlim_t limit, unsigned divisor, const char *inf,
+ const char *pfx, const char *sfx, const char *which);
+static void getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp);
+static void setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp);
+extern char **environ;
+
+static const char rcs_string[] = RCS_STRING;
+
+int
+main(int argc, char *argv[])
+{
+ char *p, *cls = NULL;
+ char *cleanenv[1];
+ struct passwd * pwd = NULL;
+ int rcswhich, shelltype;
+ int i, num_limits = 0;
+ int ch, doeval = 0, doall = 0;
+ int rtrn, setproc;
+ login_cap_t * lc = NULL;
+ enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY;
+ enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN;
+ int which_limits[RLIM_NLIMITS];
+ rlim_t set_limits[RLIM_NLIMITS];
+ struct rlimit limits[RLIM_NLIMITS];
+ pid_t pid;
+
+ /* init resource tables */
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ which_limits[i] = 0; /* Don't set/display any */
+ set_limits[i] = RLIM_INFINITY;
+ }
+
+ pid = -1;
+ optarg = NULL;
+ while ((ch = getopt(argc, argv,
+ ":EeC:U:BSHP:ab:c:d:f:l:m:n:s:t:u:v:p:w:k:o:y:")) != -1) {
+ switch(ch) {
+ case 'a':
+ doall = 1;
+ break;
+ case 'E':
+ environ = cleanenv;
+ cleanenv[0] = NULL;
+ break;
+ case 'e':
+ doeval = 1;
+ break;
+ case 'C':
+ cls = optarg;
+ break;
+ case 'U':
+ if ((pwd = getpwnam(optarg)) == NULL) {
+ if (!isdigit(*optarg) ||
+ (pwd = getpwuid(atoi(optarg))) == NULL) {
+ warnx("invalid user `%s'", optarg);
+ usage();
+ }
+ }
+ break;
+ case 'H':
+ type = HARD;
+ break;
+ case 'S':
+ type = SOFT;
+ break;
+ case 'B':
+ type = SOFT|HARD;
+ break;
+ case 'P':
+ if (!isdigit(*optarg) || (pid = atoi(optarg)) < 0) {
+ warnx("invalid pid `%s'", optarg);
+ usage();
+ }
+ break;
+ default:
+ case ':': /* Without arg */
+ if ((p = strchr(rcs_string, optopt)) != NULL) {
+ int rcswhich1 = p - rcs_string;
+ if (optarg && *optarg == '-') { /* 'arg' is actually a switch */
+ --optind; /* back one arg, and make arg NULL */
+ optarg = NULL;
+ }
+ todo = optarg == NULL ? RCSSEL : RCSSET;
+ if (type == ANY)
+ type = BOTH;
+ which_limits[rcswhich1] = optarg ? type : DISPLAYONLY;
+ set_limits[rcswhich1] = resource_num(rcswhich1, optopt, optarg);
+ num_limits++;
+ break;
+ }
+ /* FALLTHRU */
+ case '?':
+ usage();
+ }
+ optarg = NULL;
+ }
+
+ if (pid != -1) {
+ if (cls != NULL) {
+ warnx("-C cannot be used with -P option");
+ usage();
+ }
+ if (pwd != NULL) {
+ warnx("-U cannot be used with -P option");
+ usage();
+ }
+ }
+
+ /* Get current resource values */
+ setproc = 0;
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ if (pid == -1) {
+ getrlimit(i, &limits[i]);
+ } else if (doall || num_limits == 0) {
+ getrlimit_proc(pid, i, &limits[i]);
+ } else if (which_limits[i] != 0) {
+ getrlimit_proc(pid, i, &limits[i]);
+ setproc = 1;
+ }
+ }
+
+ /* If user was specified, get class from that */
+ if (pwd != NULL)
+ lc = login_getpwclass(pwd);
+ else if (cls != NULL && *cls != '\0') {
+ lc = login_getclassbyname(cls, NULL);
+ if (lc == NULL || strcmp(cls, lc->lc_class) != 0)
+ fprintf(stderr, "login class '%s' non-existent, using %s\n",
+ cls, lc?lc->lc_class:"current settings");
+ }
+
+ /* If we have a login class, update resource table from that */
+ if (lc != NULL) {
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ char str[40];
+ rlim_t val;
+
+ /* current value overridden by resourcename or resourcename-cur */
+ sprintf(str, "%s-cur", resources[rcswhich].cap);
+ val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_cur, limits[rcswhich].rlim_cur);
+ limits[rcswhich].rlim_cur = resources[rcswhich].func(lc, str, val, val);
+ /* maximum value overridden by resourcename or resourcename-max */
+ sprintf(str, "%s-max", resources[rcswhich].cap);
+ val = resources[rcswhich].func(lc, resources[rcswhich].cap, limits[rcswhich].rlim_max, limits[rcswhich].rlim_max);
+ limits[rcswhich].rlim_max = resources[rcswhich].func(lc, str, val, val);
+ }
+ }
+
+ /* now, let's determine what we wish to do with all this */
+
+ argv += optind;
+
+ /* If we're setting limits or doing an eval (ie. we're not just
+ * displaying), then check that hard limits are not lower than
+ * soft limits, and force rasing the hard limit if we need to if
+ * we are raising the soft limit, or lower the soft limit if we
+ * are lowering the hard limit.
+ */
+ if ((*argv || doeval) && getuid() == 0) {
+
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ if (limits[rcswhich].rlim_max != RLIM_INFINITY) {
+ if (limits[rcswhich].rlim_cur == RLIM_INFINITY) {
+ limits[rcswhich].rlim_max = RLIM_INFINITY;
+ which_limits[rcswhich] |= HARD;
+ } else if (limits[rcswhich].rlim_cur > limits[rcswhich].rlim_max) {
+ if (which_limits[rcswhich] == SOFT) {
+ limits[rcswhich].rlim_max = limits[rcswhich].rlim_cur;
+ which_limits[rcswhich] |= HARD;
+ } else if (which_limits[rcswhich] == HARD) {
+ limits[rcswhich].rlim_cur = limits[rcswhich].rlim_max;
+ which_limits[rcswhich] |= SOFT;
+ } else {
+ /* else.. if we're specifically setting both to
+ * silly values, then let it error out.
+ */
+ }
+ }
+ }
+ }
+ }
+
+ /* See if we've overridden anything specific on the command line */
+ if (num_limits && todo == RCSSET) {
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ if (which_limits[rcswhich] & HARD)
+ limits[rcswhich].rlim_max = set_limits[rcswhich];
+ if (which_limits[rcswhich] & SOFT)
+ limits[rcswhich].rlim_cur = set_limits[rcswhich];
+ }
+ }
+
+ /* If *argv is not NULL, then we are being asked to
+ * (perhaps) set environment variables and run a program
+ */
+ if (*argv) {
+ if (doeval) {
+ warnx("-e cannot be used with `cmd' option");
+ usage();
+ }
+ if (pid != -1) {
+ warnx("-P cannot be used with `cmd' option");
+ usage();
+ }
+
+ login_close(lc);
+
+ /* set leading environment variables, like eval(1) */
+ while (*argv && (p = strchr(*argv, '='))) {
+ *p = '\0';
+ rtrn = setenv(*argv++, p + 1, 1);
+ *p = '=';
+ if (rtrn == -1)
+ err(EXIT_FAILURE, "setenv %s", *argv);
+ }
+
+ /* Set limits */
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ if (doall || num_limits == 0 || which_limits[rcswhich] != 0)
+ if (setrlimit(rcswhich, &limits[rcswhich]) == -1)
+ err(1, "setrlimit %s", resources[rcswhich].cap);
+ }
+
+ if (*argv == NULL)
+ usage();
+
+ execvp(*argv, argv);
+ err(1, "%s", *argv);
+ }
+
+ if (setproc) {
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ if (which_limits[rcswhich] != 0)
+ setrlimit_proc(pid, rcswhich, &limits[rcswhich]);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ shelltype = doeval ? getshelltype() : SH_NONE;
+
+ if (type == ANY) /* Default to soft limits */
+ type = SOFT;
+
+ /* Display limits */
+ printf(shellparm[shelltype].cmd,
+ lc ? " for class " : " (current)",
+ lc ? lc->lc_class : "");
+
+ for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) {
+ if (doall || num_limits == 0 || which_limits[rcswhich] != 0) {
+ if (which_limits[rcswhich] == ANY)
+ which_limits[rcswhich] = type;
+ if (shellparm[shelltype].lprm[rcswhich].pfx) {
+ if (shellparm[shelltype].both && limits[rcswhich].rlim_cur == limits[rcswhich].rlim_max) {
+ print_limit(limits[rcswhich].rlim_max,
+ shellparm[shelltype].lprm[rcswhich].divisor,
+ shellparm[shelltype].inf,
+ shellparm[shelltype].lprm[rcswhich].pfx,
+ shellparm[shelltype].lprm[rcswhich].sfx,
+ shellparm[shelltype].both);
+ } else {
+ if (which_limits[rcswhich] & HARD) {
+ print_limit(limits[rcswhich].rlim_max,
+ shellparm[shelltype].lprm[rcswhich].divisor,
+ shellparm[shelltype].inf,
+ shellparm[shelltype].lprm[rcswhich].pfx,
+ shellparm[shelltype].lprm[rcswhich].sfx,
+ shellparm[shelltype].hard);
+ }
+ if (which_limits[rcswhich] & SOFT) {
+ print_limit(limits[rcswhich].rlim_cur,
+ shellparm[shelltype].lprm[rcswhich].divisor,
+ shellparm[shelltype].inf,
+ shellparm[shelltype].lprm[rcswhich].pfx,
+ shellparm[shelltype].lprm[rcswhich].sfx,
+ shellparm[shelltype].soft);
+ }
+ }
+ }
+ }
+ }
+
+ login_close(lc);
+ exit(EXIT_SUCCESS);
+}
+
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: limits [-C class|-P pid|-U user] [-eaSHBE] "
+ "[-bcdfklmnostuvpw [val]] [[name=val ...] cmd]\n");
+ exit(EXIT_FAILURE);
+}
+
+static void
+print_limit(rlim_t limit, unsigned divisor, const char * inf, const char * pfx, const char * sfx, const char * which)
+{
+ char numbr[64];
+
+ if (limit == RLIM_INFINITY)
+ strlcpy(numbr, inf, sizeof(numbr));
+ else
+ sprintf(numbr, "%jd", (intmax_t)((limit + divisor/2) / divisor));
+ printf(pfx, which, numbr);
+ printf(sfx, which);
+
+}
+
+
+static rlim_t
+resource_num(int which, int ch, const char *str)
+{
+ rlim_t res = RLIM_INFINITY;
+
+ if (str != NULL &&
+ !(strcasecmp(str, "inf") == 0 ||
+ strcasecmp(str, "infinity") == 0 ||
+ strcasecmp(str, "unlimit") == 0 ||
+ strcasecmp(str, "unlimited") == 0)) {
+ const char * s = str;
+ char *e;
+
+ switch (which) {
+ case RLIMIT_CPU: /* time values */
+ errno = 0;
+ res = 0;
+ while (*s) {
+ rlim_t tim = strtoq(s, &e, 0);
+ if (e == NULL || e == s || errno)
+ break;
+ switch (*e++) {
+ case 0: /* end of string */
+ e--;
+ default:
+ case 's': case 'S': /* seconds */
+ break;
+ case 'm': case 'M': /* minutes */
+ tim *= 60L;
+ break;
+ case 'h': case 'H': /* hours */
+ tim *= (60L * 60L);
+ break;
+ case 'd': case 'D': /* days */
+ tim *= (60L * 60L * 24L);
+ break;
+ case 'w': case 'W': /* weeks */
+ tim *= (60L * 60L * 24L * 7L);
+ break;
+ case 'y': case 'Y': /* Years */
+ tim *= (60L * 60L * 24L * 365L);
+ }
+ s = e;
+ res += tim;
+ }
+ break;
+ case RLIMIT_FSIZE: /* Size values */
+ case RLIMIT_DATA:
+ case RLIMIT_STACK:
+ case RLIMIT_CORE:
+ case RLIMIT_RSS:
+ case RLIMIT_MEMLOCK:
+ case RLIMIT_SBSIZE:
+ case RLIMIT_VMEM:
+ case RLIMIT_SWAP:
+ case RLIMIT_PIPEBUF:
+ errno = 0;
+ res = 0;
+ while (*s) {
+ rlim_t mult, tim = strtoq(s, &e, 0);
+ if (e == NULL || e == s || errno)
+ break;
+ switch (*e++) {
+ case 0: /* end of string */
+ e--;
+ default:
+ mult = 1;
+ break;
+ case 'b': case 'B': /* 512-byte blocks */
+ mult = 512;
+ break;
+ case 'k': case 'K': /* 1024-byte Kilobytes */
+ mult = 1024;
+ break;
+ case 'm': case 'M': /* 1024-k kbytes */
+ mult = 1024 * 1024;
+ break;
+ case 'g': case 'G': /* 1Gbyte */
+ mult = 1024 * 1024 * 1024;
+ break;
+ case 't': case 'T': /* 1TBte */
+ mult = 1024LL * 1024LL * 1024LL * 1024LL;
+ break;
+ }
+ s = e;
+ res += (tim * mult);
+ }
+ break;
+ case RLIMIT_NPROC:
+ case RLIMIT_NOFILE:
+ case RLIMIT_NPTS:
+ case RLIMIT_KQUEUES:
+ case RLIMIT_UMTXP:
+ res = strtoq(s, &e, 0);
+ s = e;
+ break;
+ }
+ if (*s) {
+ warnx("invalid value -%c `%s'", ch, str);
+ usage();
+ }
+ }
+ return res;
+}
+
+
+static int
+getshellbyname(const char * shell)
+{
+ int i;
+ const char * q;
+ const char * p = strrchr(shell, '/');
+
+ p = p ? p+1 : shell;
+ for (i = 0; (q = shellparm[i].name) != NULL; i++) {
+ while (*q) {
+ int j = strcspn(q, "|");
+
+ if (j == 0)
+ break;
+ if (strncmp(p, q, j) == 0)
+ return i;
+ if (*(q += j))
+ ++q;
+ }
+ }
+ return SH_SH;
+}
+
+
+/*
+ * Determine the type of shell our parent process is
+ * This is quite tricky, not 100% reliable and probably
+ * not nearly as thorough as it should be. Basically, this
+ * is a "best guess" only, but hopefully will work in
+ * most cases.
+ */
+
+static int
+getshelltype(void)
+{
+ pid_t ppid = getppid();
+
+ if (ppid != 1) {
+ struct kinfo_proc kp;
+ struct stat st;
+ char path[MAXPATHLEN];
+ char * shell = getenv("SHELL");
+ int mib[4];
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[3] = ppid;
+
+ if (shell != NULL && stat(shell, &st) != -1) {
+ struct stat st1;
+
+ mib[2] = KERN_PROC_PATHNAME;
+ len = sizeof(path);
+ if (sysctl(mib, 4, path, &len, NULL, 0) != -1) {
+ /* $SHELL is actual shell? */
+ if (stat(path, &st1) != -1 && memcmp(&st, &st1, sizeof st) == 0)
+ return getshellbyname(shell);
+ }
+ }
+ mib[2] = KERN_PROC_PID;
+ len = sizeof(kp);
+ if (sysctl(mib, 4, &kp, &len, NULL, 0) != -1)
+ return getshellbyname(kp.ki_comm);
+ }
+ return SH_SH;
+}
+
+static void
+getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp)
+{
+ int error;
+ int name[5];
+ size_t len;
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_RLIMIT;
+ name[3] = pid;
+ name[4] = resource;
+ len = sizeof(*rlp);
+ error = sysctl(name, 5, rlp, &len, NULL, 0);
+ if (error == -1)
+ err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid);
+ if (len != sizeof(*rlp))
+ errx(EXIT_FAILURE, "sysctl() returns wrong size");
+}
+
+static void
+setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp)
+{
+ int error;
+ int name[5];
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_RLIMIT;
+ name[3] = pid;
+ name[4] = resource;
+ error = sysctl(name, 5, NULL, 0, rlp, sizeof(*rlp));
+ if (error == -1)
+ err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid);
+}
diff --git a/usr.bin/limits/tests/Makefile b/usr.bin/limits/tests/Makefile
new file mode 100644
index 000000000000..7098c21aa454
--- /dev/null
+++ b/usr.bin/limits/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH+= limits_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/limits/tests/Makefile.depend b/usr.bin/limits/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/limits/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/limits/tests/limits_test.sh b/usr.bin/limits/tests/limits_test.sh
new file mode 100755
index 000000000000..fd7b50b0945a
--- /dev/null
+++ b/usr.bin/limits/tests/limits_test.sh
@@ -0,0 +1,92 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+#
+
+# Make sure time(1) is consistent with the FreeBSD time command and not the
+# shell interpretation of time(1)
+TIME=/usr/bin/time
+
+validate_time_output()
+{
+ local time_output=$1
+
+ # RLIMIT_CPU is enforced by a 1-second timer. Allow 3 + 1 + a little.
+ atf_check awk '
+ /^(user|sys) / {
+ sum += $2
+ }
+ END {
+ if (sum < 3 || sum >= 4.5) {
+ print(sum);
+ exit(1);
+ }
+ }
+ ' < $time_output
+}
+
+atf_test_case cputime_hard_flag cleanup
+cputime_hard_flag_body()
+{
+
+ atf_check -o match:'cputime[[:space:]]+3 secs' \
+ limits -H -t 3 limits -H
+ atf_check -o match:'cputime[[:space:]]+3 secs' \
+ limits -H -t 3 limits -S
+ atf_check -e save:time_output -s signal:sigkill \
+ $TIME -p limits -H -t 3 sh -c 'while : ; do : ; done'
+ validate_time_output time_output
+}
+cputime_hard_flag_cleanup()
+{
+ rm -f time_output
+}
+
+SIGXCPU=24 # atf_check doesn't know sigxcpu
+
+atf_test_case cputime_soft_flag cleanup
+cputime_soft_flag_body()
+{
+
+ atf_check -o match:'cputime-max[[:space:]]+infinity secs' \
+ limits -S -t 3 limits -H
+ atf_check -o match:'cputime-cur[[:space:]]+3 secs' \
+ limits -S -t 3 limits -S
+ atf_check -e save:time_output -s signal:$SIGXCPU \
+ $TIME -p limits -S -t 3 sh -c 'while : ; do : ; done'
+ validate_time_output time_output
+}
+cputime_soft_flag_cleanup()
+{
+ rm -f time_output
+}
+
+atf_init_test_cases()
+{
+
+ atf_add_test_case cputime_hard_flag
+ atf_add_test_case cputime_soft_flag
+}
diff --git a/usr.bin/locale/Makefile b/usr.bin/locale/Makefile
new file mode 100644
index 000000000000..33b72ae07b2c
--- /dev/null
+++ b/usr.bin/locale/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PROG= locale
+CFLAGS+= -I${SRCTOP}/lib/libc/locale
+LIBADD+= sbuf
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/locale/Makefile.depend b/usr.bin/locale/Makefile.depend
new file mode 100644
index 000000000000..cde253fc72ce
--- /dev/null
+++ b/usr.bin/locale/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsbuf \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/locale/locale.1 b/usr.bin/locale/locale.1
new file mode 100644
index 000000000000..c26d10e8ad17
--- /dev/null
+++ b/usr.bin/locale/locale.1
@@ -0,0 +1,116 @@
+.\"
+.\" Copyright (c) 2003 Alexey Zelkin <phantom@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 November 18, 2012
+.Dt LOCALE 1
+.Os
+.Sh NAME
+.Nm locale
+.Nd get locale-specific information
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | m
+.Nm
+.Fl k
+.Ic list
+.Op Ar prefix
+.Nm
+.Op Fl ck
+.Op Ar keyword ...
+.Sh DESCRIPTION
+The
+.Nm
+utility is supposed to provide most locale specific information to
+the standard output.
+.Pp
+When
+.Nm
+is invoked without arguments, it will print out a summary of the current
+locale environment, subject to the environment settings and
+internal status.
+.Pp
+When
+.Nm
+is invoked with the
+.Ar keyword
+arguments, and no options are specified, it will print out the
+values of all keywords specified, using the current locale settings.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Print names of all available locales.
+While looking for locales,
+.Nm
+will respect the
+.Ev PATH_LOCALE
+environment variable, and use it instead of the system's default locale
+directory.
+.It Fl c
+Print the category name for all selected keywords.
+If no keywords are selected, print the category name for all defined
+keywords.
+.It Fl k
+Print the names and values of all selected keywords.
+If no keywords are selected, print the names and values of all defined
+keywords.
+.It Fl m
+Print names of all available charmaps.
+.El
+.Sh IMPLEMENTATION NOTES
+The special
+.Pf ( Fx
+specific) keyword
+.Cm list
+can be used to retrieve the human readable list of all available keywords.
+If so,
+a prefix string can be defined to limit the amount of keywords returned.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr setlocale 3
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2004 .
+The
+.Ev LC_CTYPE ,
+.Ev LC_MESSAGES
+and
+.Ev NLSPATH
+environment variables are not interpreted.
+.Sh BUGS
+Since
+.Fx
+does not support
+.Em charmap Ns s
+in their
+.Tn POSIX
+meaning,
+.Nm
+emulates the
+.Fl m
+option using the CODESETs listing of all available locales.
diff --git a/usr.bin/locale/locale.c b/usr.bin/locale/locale.c
new file mode 100644
index 000000000000..19df77504573
--- /dev/null
+++ b/usr.bin/locale/locale.c
@@ -0,0 +1,936 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002, 2003 Alexey Zelkin <phantom@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * XXX: implement missing era_* (LC_TIME) keywords (require libc &
+ * nl_langinfo(3) extensions)
+ *
+ * XXX: correctly handle reserved 'charmap' keyword and '-m' option (require
+ * localedef(1) implementation). Currently it's handled via
+ * nl_langinfo(CODESET).
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sbuf.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "setlocale.h"
+
+/* Local prototypes */
+char *format_grouping(char *);
+void init_locales_list(void);
+void list_charmaps(void);
+void list_locales(void);
+const char *lookup_localecat(int);
+char *kwval_lconv(int);
+int kwval_lookup(const char *, char **, int *, int *, int *);
+int showdetails(const char *);
+void showkeywordslist(char *substring);
+void showlocale(void);
+void usage(void);
+
+/* Global variables */
+static StringList *locales = NULL;
+
+static int all_locales = 0;
+static int all_charmaps = 0;
+static int prt_categories = 0;
+static int prt_keywords = 0;
+
+static const struct _lcinfo {
+ const char *name;
+ int id;
+} lcinfo [] = {
+ { "LC_CTYPE", LC_CTYPE },
+ { "LC_COLLATE", LC_COLLATE },
+ { "LC_TIME", LC_TIME },
+ { "LC_NUMERIC", LC_NUMERIC },
+ { "LC_MONETARY", LC_MONETARY },
+ { "LC_MESSAGES", LC_MESSAGES }
+};
+#define NLCINFO nitems(lcinfo)
+
+/* ids for values not referenced by nl_langinfo() */
+enum {
+ KW_GROUPING,
+ KW_INT_CURR_SYMBOL,
+ KW_CURRENCY_SYMBOL,
+ KW_MON_DECIMAL_POINT,
+ KW_MON_THOUSANDS_SEP,
+ KW_MON_GROUPING,
+ KW_POSITIVE_SIGN,
+ KW_NEGATIVE_SIGN,
+ KW_INT_FRAC_DIGITS,
+ KW_FRAC_DIGITS,
+ KW_P_CS_PRECEDES,
+ KW_P_SEP_BY_SPACE,
+ KW_N_CS_PRECEDES,
+ KW_N_SEP_BY_SPACE,
+ KW_P_SIGN_POSN,
+ KW_N_SIGN_POSN,
+ KW_INT_P_CS_PRECEDES,
+ KW_INT_P_SEP_BY_SPACE,
+ KW_INT_N_CS_PRECEDES,
+ KW_INT_N_SEP_BY_SPACE,
+ KW_INT_P_SIGN_POSN,
+ KW_INT_N_SIGN_POSN,
+ KW_TIME_DAY,
+ KW_TIME_ABDAY,
+ KW_TIME_MON,
+ KW_TIME_ABMON,
+ KW_TIME_AM_PM
+};
+
+enum {
+ TYPE_NUM,
+ TYPE_STR,
+ TYPE_UNQ
+};
+
+enum {
+ SRC_LINFO,
+ SRC_LCONV,
+ SRC_LTIME
+};
+
+static const struct _kwinfo {
+ const char *name;
+ int type;
+ int catid; /* LC_* */
+ int source;
+ int value_ref;
+ const char *comment;
+} kwinfo [] = {
+ { "charmap", TYPE_STR, LC_CTYPE, SRC_LINFO,
+ CODESET, "" }, /* hack */
+
+ /* LC_MONETARY - POSIX */
+ { "int_curr_symbol", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_INT_CURR_SYMBOL, "" },
+ { "currency_symbol", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_CURRENCY_SYMBOL, "" },
+ { "mon_decimal_point", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_MON_DECIMAL_POINT, "" },
+ { "mon_thousands_sep", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_MON_THOUSANDS_SEP, "" },
+ { "mon_grouping", TYPE_UNQ, LC_MONETARY, SRC_LCONV,
+ KW_MON_GROUPING, "" },
+ { "positive_sign", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_POSITIVE_SIGN, "" },
+ { "negative_sign", TYPE_STR, LC_MONETARY, SRC_LCONV,
+ KW_NEGATIVE_SIGN, "" },
+ { "int_frac_digits", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_FRAC_DIGITS, "" },
+ { "frac_digits", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_FRAC_DIGITS, "" },
+ { "p_cs_precedes", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_P_CS_PRECEDES, "" },
+ { "p_sep_by_space", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_P_SEP_BY_SPACE, "" },
+ { "n_cs_precedes", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_N_CS_PRECEDES, "" },
+ { "n_sep_by_space", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_N_SEP_BY_SPACE, "" },
+ { "p_sign_posn", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_P_SIGN_POSN, "" },
+ { "n_sign_posn", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_N_SIGN_POSN, "" },
+ { "int_p_cs_precedes", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_P_CS_PRECEDES, "" },
+ { "int_p_sep_by_space", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_P_SEP_BY_SPACE, "" },
+ { "int_n_cs_precedes", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_N_CS_PRECEDES, "" },
+ { "int_n_sep_by_space", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_N_SEP_BY_SPACE, "" },
+ { "int_p_sign_posn", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_P_SIGN_POSN, "" },
+ { "int_n_sign_posn", TYPE_NUM, LC_MONETARY, SRC_LCONV,
+ KW_INT_N_SIGN_POSN, "" },
+
+ /* LC_NUMERIC - POSIX */
+ { "decimal_point", TYPE_STR, LC_NUMERIC, SRC_LINFO,
+ RADIXCHAR, "" },
+ { "thousands_sep", TYPE_STR, LC_NUMERIC, SRC_LINFO,
+ THOUSEP, "" },
+ { "grouping", TYPE_UNQ, LC_NUMERIC, SRC_LCONV,
+ KW_GROUPING, "" },
+ /* LC_NUMERIC - local additions */
+ { "radixchar", TYPE_STR, LC_NUMERIC, SRC_LINFO,
+ RADIXCHAR, "Same as decimal_point (FreeBSD only)" }, /* compat */
+ { "thousep", TYPE_STR, LC_NUMERIC, SRC_LINFO,
+ THOUSEP, "Same as thousands_sep (FreeBSD only)" }, /* compat */
+
+ /* LC_TIME - POSIX */
+ { "abday", TYPE_STR, LC_TIME, SRC_LTIME,
+ KW_TIME_ABDAY, "" },
+ { "day", TYPE_STR, LC_TIME, SRC_LTIME,
+ KW_TIME_DAY, "" },
+ { "abmon", TYPE_STR, LC_TIME, SRC_LTIME,
+ KW_TIME_ABMON, "" },
+ { "mon", TYPE_STR, LC_TIME, SRC_LTIME,
+ KW_TIME_MON, "" },
+ { "d_t_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ D_T_FMT, "" },
+ { "d_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ D_FMT, "" },
+ { "t_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ T_FMT, "" },
+ { "am_pm", TYPE_STR, LC_TIME, SRC_LTIME,
+ KW_TIME_AM_PM, "" },
+ { "t_fmt_ampm", TYPE_STR, LC_TIME, SRC_LINFO,
+ T_FMT_AMPM, "" },
+ { "era", TYPE_UNQ, LC_TIME, SRC_LINFO,
+ ERA, "(unavailable)" },
+ { "era_d_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ ERA_D_FMT, "(unavailable)" },
+ { "era_d_t_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ ERA_D_T_FMT, "(unavailable)" },
+ { "era_t_fmt", TYPE_STR, LC_TIME, SRC_LINFO,
+ ERA_T_FMT, "(unavailable)" },
+ { "alt_digits", TYPE_UNQ, LC_TIME, SRC_LINFO,
+ ALT_DIGITS, "" },
+ /* LC_TIME - local additions */
+ { "abday_1", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_1, "(FreeBSD only)" },
+ { "abday_2", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_2, "(FreeBSD only)" },
+ { "abday_3", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_3, "(FreeBSD only)" },
+ { "abday_4", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_4, "(FreeBSD only)" },
+ { "abday_5", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_5, "(FreeBSD only)" },
+ { "abday_6", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_6, "(FreeBSD only)" },
+ { "abday_7", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABDAY_7, "(FreeBSD only)" },
+ { "day_1", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_1, "(FreeBSD only)" },
+ { "day_2", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_2, "(FreeBSD only)" },
+ { "day_3", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_3, "(FreeBSD only)" },
+ { "day_4", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_4, "(FreeBSD only)" },
+ { "day_5", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_5, "(FreeBSD only)" },
+ { "day_6", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_6, "(FreeBSD only)" },
+ { "day_7", TYPE_STR, LC_TIME, SRC_LINFO,
+ DAY_7, "(FreeBSD only)" },
+ { "abmon_1", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_1, "(FreeBSD only)" },
+ { "abmon_2", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_2, "(FreeBSD only)" },
+ { "abmon_3", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_3, "(FreeBSD only)" },
+ { "abmon_4", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_4, "(FreeBSD only)" },
+ { "abmon_5", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_5, "(FreeBSD only)" },
+ { "abmon_6", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_6, "(FreeBSD only)" },
+ { "abmon_7", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_7, "(FreeBSD only)" },
+ { "abmon_8", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_8, "(FreeBSD only)" },
+ { "abmon_9", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_9, "(FreeBSD only)" },
+ { "abmon_10", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_10, "(FreeBSD only)" },
+ { "abmon_11", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_11, "(FreeBSD only)" },
+ { "abmon_12", TYPE_STR, LC_TIME, SRC_LINFO,
+ ABMON_12, "(FreeBSD only)" },
+ { "mon_1", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_1, "(FreeBSD only)" },
+ { "mon_2", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_2, "(FreeBSD only)" },
+ { "mon_3", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_3, "(FreeBSD only)" },
+ { "mon_4", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_4, "(FreeBSD only)" },
+ { "mon_5", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_5, "(FreeBSD only)" },
+ { "mon_6", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_6, "(FreeBSD only)" },
+ { "mon_7", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_7, "(FreeBSD only)" },
+ { "mon_8", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_8, "(FreeBSD only)" },
+ { "mon_9", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_9, "(FreeBSD only)" },
+ { "mon_10", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_10, "(FreeBSD only)" },
+ { "mon_11", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_11, "(FreeBSD only)" },
+ { "mon_12", TYPE_STR, LC_TIME, SRC_LINFO,
+ MON_12, "(FreeBSD only)" },
+ { "altmon_1", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_1, "(FreeBSD only)" },
+ { "altmon_2", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_2, "(FreeBSD only)" },
+ { "altmon_3", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_3, "(FreeBSD only)" },
+ { "altmon_4", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_4, "(FreeBSD only)" },
+ { "altmon_5", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_5, "(FreeBSD only)" },
+ { "altmon_6", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_6, "(FreeBSD only)" },
+ { "altmon_7", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_7, "(FreeBSD only)" },
+ { "altmon_8", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_8, "(FreeBSD only)" },
+ { "altmon_9", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_9, "(FreeBSD only)" },
+ { "altmon_10", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_10, "(FreeBSD only)" },
+ { "altmon_11", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_11, "(FreeBSD only)" },
+ { "altmon_12", TYPE_STR, LC_TIME, SRC_LINFO,
+ ALTMON_12, "(FreeBSD only)" },
+ { "am_str", TYPE_STR, LC_TIME, SRC_LINFO,
+ AM_STR, "(FreeBSD only)" },
+ { "pm_str", TYPE_STR, LC_TIME, SRC_LINFO,
+ PM_STR, "(FreeBSD only)" },
+ { "d_md_order", TYPE_STR, LC_TIME, SRC_LINFO,
+ D_MD_ORDER, "(FreeBSD only)" }, /* local */
+
+ /* LC_MESSAGES - POSIX */
+ { "yesexpr", TYPE_STR, LC_MESSAGES, SRC_LINFO,
+ YESEXPR, "" },
+ { "noexpr", TYPE_STR, LC_MESSAGES, SRC_LINFO,
+ NOEXPR, "" },
+ /* LC_MESSAGES - local additions */
+ { "yesstr", TYPE_STR, LC_MESSAGES, SRC_LINFO,
+ YESSTR, "(POSIX legacy)" }, /* compat */
+ { "nostr", TYPE_STR, LC_MESSAGES, SRC_LINFO,
+ NOSTR, "(POSIX legacy)" } /* compat */
+
+};
+#define NKWINFO (nitems(kwinfo))
+
+static const char *boguslocales[] = { "UTF-8" };
+#define NBOGUS (nitems(boguslocales))
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ int tmp;
+
+ while ((ch = getopt(argc, argv, "ackms:")) != -1) {
+ switch (ch) {
+ case 'a':
+ all_locales = 1;
+ break;
+ case 'c':
+ prt_categories = 1;
+ break;
+ case 'k':
+ prt_keywords = 1;
+ break;
+ case 'm':
+ all_charmaps = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* validate arguments */
+ if (all_locales && all_charmaps)
+ usage();
+ if ((all_locales || all_charmaps) && argc > 0)
+ usage();
+ if ((all_locales || all_charmaps) && (prt_categories || prt_keywords))
+ usage();
+
+ /* process '-a' */
+ if (all_locales) {
+ list_locales();
+ exit(0);
+ }
+
+ /* process '-m' */
+ if (all_charmaps) {
+ list_charmaps();
+ exit(0);
+ }
+
+ /* check for special case '-k list' */
+ tmp = 0;
+ if (prt_keywords && argc > 0)
+ while (tmp < argc)
+ if (strcasecmp(argv[tmp++], "list") == 0) {
+ showkeywordslist(argv[tmp]);
+ exit(0);
+ }
+
+ /* process '-c', '-k', or command line arguments. */
+ if (prt_categories || prt_keywords || argc > 0) {
+ if (prt_keywords || argc > 0)
+ setlocale(LC_ALL, "");
+ if (argc > 0) {
+ while (argc > 0) {
+ if (showdetails(*argv) != 0)
+ exit(EXIT_FAILURE);
+ argv++;
+ argc--;
+ }
+ } else {
+ uint i;
+ for (i = 0; i < nitems(kwinfo); i++)
+ showdetails(kwinfo[i].name);
+ }
+ exit(0);
+ }
+
+ /* no arguments, show current locale state */
+ showlocale();
+
+ return (0);
+}
+
+void
+usage(void)
+{
+ printf("Usage: locale [ -a | -m ]\n"
+ " locale -k list [prefix]\n"
+ " locale [ -ck ] [keyword ...]\n");
+ exit(1);
+}
+
+/*
+ * Output information about all available locales
+ *
+ * XXX actually output of this function does not guarantee that locale
+ * is really available to application, since it can be broken or
+ * inconsistent thus setlocale() will fail. Maybe add '-V' function to
+ * also validate these locales?
+ */
+void
+list_locales(void)
+{
+ size_t i;
+
+ init_locales_list();
+ for (i = 0; i < locales->sl_cur; i++) {
+ printf("%s\n", locales->sl_str[i]);
+ }
+}
+
+/*
+ * qsort() helper function
+ */
+static int
+scmp(const void *s1, const void *s2)
+{
+ return strcmp(*(const char * const *)s1, *(const char * const *)s2);
+}
+
+/*
+ * Output information about all available charmaps
+ *
+ * XXX this function is doing a task in hackish way, i.e. by scaning
+ * list of locales, spliting their codeset part and building list of
+ * them.
+ */
+void
+list_charmaps(void)
+{
+ size_t i;
+ char *s, *cs;
+ StringList *charmaps;
+
+ /* initialize StringList */
+ charmaps = sl_init();
+ if (charmaps == NULL)
+ err(1, "could not allocate memory");
+
+ /* fetch locales list */
+ init_locales_list();
+
+ /* split codesets and build their list */
+ for (i = 0; i < locales->sl_cur; i++) {
+ s = locales->sl_str[i];
+ if ((cs = strchr(s, '.')) != NULL) {
+ cs++;
+ if (sl_find(charmaps, cs) == NULL)
+ sl_add(charmaps, cs);
+ }
+ }
+
+ /* add US-ASCII, if not yet added */
+ if (sl_find(charmaps, "US-ASCII") == NULL)
+ sl_add(charmaps, strdup("US-ASCII"));
+
+ /* sort the list */
+ qsort(charmaps->sl_str, charmaps->sl_cur, sizeof(char *), scmp);
+
+ /* print results */
+ for (i = 0; i < charmaps->sl_cur; i++) {
+ printf("%s\n", charmaps->sl_str[i]);
+ }
+}
+
+/*
+ * Retrieve sorted list of system locales (or user locales, if PATH_LOCALE
+ * environment variable is set)
+ */
+void
+init_locales_list(void)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ size_t i;
+ int bogus;
+
+ /* why call this function twice ? */
+ if (locales != NULL)
+ return;
+
+ /* initialize StringList */
+ locales = sl_init();
+ if (locales == NULL)
+ err(1, "could not allocate memory");
+
+ /* get actual locales directory name */
+ if (__detect_path_locale() != 0)
+ err(1, "unable to find locales storage");
+
+ /* open locales directory */
+ dirp = opendir(_PathLocale);
+ if (dirp == NULL)
+ err(1, "could not open directory '%s'", _PathLocale);
+
+ /* scan directory and store its contents except "." and ".." */
+ while ((dp = readdir(dirp)) != NULL) {
+ if (*(dp->d_name) == '.')
+ continue; /* exclude "." and ".." */
+ for (bogus = i = 0; i < NBOGUS; i++)
+ if (strncmp(dp->d_name, boguslocales[i],
+ strlen(boguslocales[i])) == 0)
+ bogus = 1;
+ if (!bogus)
+ sl_add(locales, strdup(dp->d_name));
+ }
+ closedir(dirp);
+
+ /* make sure that 'POSIX' and 'C' locales are present in the list.
+ * POSIX 1003.1-2001 requires presence of 'POSIX' name only here, but
+ * we also list 'C' for constistency
+ */
+ if (sl_find(locales, "POSIX") == NULL)
+ sl_add(locales, strdup("POSIX"));
+
+ if (sl_find(locales, "C") == NULL)
+ sl_add(locales, strdup("C"));
+
+ /* make output nicer, sort the list */
+ qsort(locales->sl_str, locales->sl_cur, sizeof(char *), scmp);
+}
+
+/*
+ * Show current locale status, depending on environment variables
+ */
+void
+showlocale(void)
+{
+ size_t i;
+ const char *lang, *vval, *eval;
+
+ setlocale(LC_ALL, "");
+
+ lang = getenv("LANG");
+ if (lang == NULL) {
+ lang = "";
+ }
+ printf("LANG=%s\n", lang);
+ /* XXX: if LANG is null, then set it to "C" to get implied values? */
+
+ for (i = 0; i < NLCINFO; i++) {
+ vval = setlocale(lcinfo[i].id, NULL);
+ eval = getenv(lcinfo[i].name);
+ if (eval != NULL && !strcmp(eval, vval)
+ && strcmp(lang, vval)) {
+ /*
+ * Appropriate environment variable set, its value
+ * is valid and not overridden by LC_ALL
+ *
+ * XXX: possible side effect: if both LANG and
+ * overridden environment variable are set into same
+ * value, then it'll be assumed as 'implied'
+ */
+ printf("%s=%s\n", lcinfo[i].name, vval);
+ } else {
+ printf("%s=\"%s\"\n", lcinfo[i].name, vval);
+ }
+ }
+
+ vval = getenv("LC_ALL");
+ if (vval == NULL) {
+ vval = "";
+ }
+ printf("LC_ALL=%s\n", vval);
+}
+
+char *
+format_grouping(char *binary)
+{
+ static char rval[64];
+ const char *cp;
+ size_t roff;
+ int len;
+
+ /*
+ * XXX This check will need to be modified if/when localeconv() is
+ * fixed (PR172215).
+ */
+ if (*binary == CHAR_MAX)
+ return (binary);
+
+ rval[0] = '\0';
+ roff = 0;
+ for (cp = binary; *cp != '\0'; ++cp) {
+#if CHAR_MIN != 0
+ if (*cp < 0)
+ break; /* garbage input */
+#endif
+ len = snprintf(&rval[roff], sizeof(rval) - roff, "%u;", *cp);
+ if (len < 0 || (unsigned)len >= sizeof(rval) - roff)
+ break; /* insufficient space for output */
+ roff += len;
+ if (*cp == CHAR_MAX)
+ break; /* special termination */
+ }
+
+ /* Truncate at the last successfully snprintf()ed semicolon. */
+ if (roff != 0)
+ rval[roff - 1] = '\0';
+
+ return (&rval[0]);
+}
+
+/*
+ * keyword value lookup helper for values accessible via localeconv()
+ */
+char *
+kwval_lconv(int id)
+{
+ struct lconv *lc;
+ char *rval;
+
+ rval = NULL;
+ lc = localeconv();
+ switch (id) {
+ case KW_GROUPING:
+ rval = format_grouping(lc->grouping);
+ break;
+ case KW_INT_CURR_SYMBOL:
+ rval = lc->int_curr_symbol;
+ break;
+ case KW_CURRENCY_SYMBOL:
+ rval = lc->currency_symbol;
+ break;
+ case KW_MON_DECIMAL_POINT:
+ rval = lc->mon_decimal_point;
+ break;
+ case KW_MON_THOUSANDS_SEP:
+ rval = lc->mon_thousands_sep;
+ break;
+ case KW_MON_GROUPING:
+ rval = format_grouping(lc->mon_grouping);
+ break;
+ case KW_POSITIVE_SIGN:
+ rval = lc->positive_sign;
+ break;
+ case KW_NEGATIVE_SIGN:
+ rval = lc->negative_sign;
+ break;
+ case KW_INT_FRAC_DIGITS:
+ rval = &(lc->int_frac_digits);
+ break;
+ case KW_FRAC_DIGITS:
+ rval = &(lc->frac_digits);
+ break;
+ case KW_P_CS_PRECEDES:
+ rval = &(lc->p_cs_precedes);
+ break;
+ case KW_P_SEP_BY_SPACE:
+ rval = &(lc->p_sep_by_space);
+ break;
+ case KW_N_CS_PRECEDES:
+ rval = &(lc->n_cs_precedes);
+ break;
+ case KW_N_SEP_BY_SPACE:
+ rval = &(lc->n_sep_by_space);
+ break;
+ case KW_P_SIGN_POSN:
+ rval = &(lc->p_sign_posn);
+ break;
+ case KW_N_SIGN_POSN:
+ rval = &(lc->n_sign_posn);
+ break;
+ case KW_INT_P_CS_PRECEDES:
+ rval = &(lc->int_p_cs_precedes);
+ break;
+ case KW_INT_P_SEP_BY_SPACE:
+ rval = &(lc->int_p_sep_by_space);
+ break;
+ case KW_INT_N_CS_PRECEDES:
+ rval = &(lc->int_n_cs_precedes);
+ break;
+ case KW_INT_N_SEP_BY_SPACE:
+ rval = &(lc->int_n_sep_by_space);
+ break;
+ case KW_INT_P_SIGN_POSN:
+ rval = &(lc->int_p_sign_posn);
+ break;
+ case KW_INT_N_SIGN_POSN:
+ rval = &(lc->int_n_sign_posn);
+ break;
+ default:
+ break;
+ }
+ return (rval);
+}
+
+/*
+ * keyword value lookup helper for LC_TIME keywords not accessible
+ * via nl_langinfo() or localeconv()
+ */
+static char *
+kwval_ltime(int id)
+{
+ char *rval;
+ struct sbuf *kwsbuf;
+ nl_item i, s_item = 0, e_item = 0;
+
+ switch (id) {
+ case KW_TIME_DAY:
+ s_item = DAY_1;
+ e_item = DAY_7;
+ break;
+ case KW_TIME_ABDAY:
+ s_item = ABDAY_1;
+ e_item = ABDAY_7;
+ break;
+ case KW_TIME_MON:
+ s_item = MON_1;
+ e_item = MON_12;
+ break;
+ case KW_TIME_ABMON:
+ s_item = ABMON_1;
+ e_item = ABMON_12;
+ break;
+ case KW_TIME_AM_PM:
+ if (asprintf(&rval, "%s;%s",
+ nl_langinfo(AM_STR),
+ nl_langinfo(PM_STR)) == -1)
+ err(1, "asprintf");
+ return (rval);
+ }
+
+ kwsbuf = sbuf_new_auto();
+ if (kwsbuf == NULL)
+ err(1, "sbuf");
+ for (i = s_item; i <= e_item; i++) {
+ (void) sbuf_cat(kwsbuf, nl_langinfo(i));
+ if (i != e_item)
+ (void) sbuf_cat(kwsbuf, ";");
+ }
+ (void) sbuf_finish(kwsbuf);
+ rval = strdup(sbuf_data(kwsbuf));
+ if (rval == NULL)
+ err(1, "strdup");
+ sbuf_delete(kwsbuf);
+ return (rval);
+}
+
+/*
+ * keyword value and properties lookup
+ */
+int
+kwval_lookup(const char *kwname, char **kwval, int *cat, int *type, int *alloc)
+{
+ int rval;
+ size_t i;
+ static char nastr[3] = "-1";
+
+ rval = 0;
+ *alloc = 0;
+ for (i = 0; i < NKWINFO; i++) {
+ if (strcasecmp(kwname, kwinfo[i].name) == 0) {
+ rval = 1;
+ *cat = kwinfo[i].catid;
+ *type = kwinfo[i].type;
+ switch (kwinfo[i].source) {
+ case SRC_LINFO:
+ *kwval = nl_langinfo(kwinfo[i].value_ref);
+ break;
+ case SRC_LCONV:
+ *kwval = kwval_lconv(kwinfo[i].value_ref);
+ /*
+ * XXX This check will need to be modified
+ * if/when localeconv() is fixed (PR172215).
+ */
+ if (**kwval == CHAR_MAX) {
+ if (*type == TYPE_NUM)
+ *type = TYPE_UNQ;
+ *kwval = nastr;
+ }
+ break;
+ case SRC_LTIME:
+ *kwval = kwval_ltime(kwinfo[i].value_ref);
+ *alloc = 1;
+ break;
+ }
+ break;
+ }
+ }
+
+ return (rval);
+}
+
+/*
+ * Show details about requested keyword according to '-k' and/or '-c'
+ * command line options specified.
+ */
+int
+showdetails(const char *kw)
+{
+ int type, cat, tmpval, alloc;
+ char *kwval;
+
+ if (kwval_lookup(kw, &kwval, &cat, &type, &alloc) == 0) {
+ /* Invalid keyword specified */
+ fprintf(stderr, "Unknown keyword: `%s'\n", kw);
+ return (1);
+ }
+
+ if (prt_categories) {
+ if (prt_keywords)
+ printf("%-20s ", lookup_localecat(cat));
+ else
+ printf("%-20s\t%s\n", kw, lookup_localecat(cat));
+ }
+
+ if (prt_keywords) {
+ switch (type) {
+ case TYPE_NUM:
+ tmpval = (char)*kwval;
+ printf("%s=%d\n", kw, tmpval);
+ break;
+ case TYPE_STR:
+ printf("%s=\"%s\"\n", kw, kwval);
+ break;
+ case TYPE_UNQ:
+ printf("%s=%s\n", kw, kwval);
+ break;
+ }
+ }
+
+ if (!prt_categories && !prt_keywords) {
+ switch (type) {
+ case TYPE_NUM:
+ tmpval = (char)*kwval;
+ printf("%d\n", tmpval);
+ break;
+ case TYPE_STR:
+ case TYPE_UNQ:
+ printf("%s\n", kwval);
+ break;
+ }
+ }
+
+ if (alloc)
+ free(kwval);
+
+ return (0);
+}
+
+/*
+ * Convert locale category id into string
+ */
+const char *
+lookup_localecat(int cat)
+{
+ size_t i;
+
+ for (i = 0; i < NLCINFO; i++)
+ if (lcinfo[i].id == cat) {
+ return (lcinfo[i].name);
+ }
+ return ("UNKNOWN");
+}
+
+/*
+ * Show list of keywords
+ */
+void
+showkeywordslist(char *substring)
+{
+ size_t i;
+
+#define FMT "%-20s %-12s %-7s %-20s\n"
+
+ if (substring == NULL)
+ printf("List of available keywords\n\n");
+ else
+ printf("List of available keywords starting with '%s'\n\n",
+ substring);
+ printf(FMT, "Keyword", "Category", "Type", "Comment");
+ printf("-------------------- ------------ ------- --------------------\n");
+ for (i = 0; i < NKWINFO; i++) {
+ if (substring != NULL) {
+ if (strncmp(kwinfo[i].name, substring,
+ strlen(substring)) != 0)
+ continue;
+ }
+ printf(FMT,
+ kwinfo[i].name,
+ lookup_localecat(kwinfo[i].catid),
+ (kwinfo[i].type == TYPE_NUM) ? "number" : "string",
+ kwinfo[i].comment);
+ }
+}
diff --git a/usr.bin/locale/tests/Makefile b/usr.bin/locale/tests/Makefile
new file mode 100644
index 000000000000..7b26f0632607
--- /dev/null
+++ b/usr.bin/locale/tests/Makefile
@@ -0,0 +1,14 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= locale_test
+
+${PACKAGE}FILES+= k_flag_posix_monetary.out
+${PACKAGE}FILES+= k_flag_posix_numeric.out
+${PACKAGE}FILES+= k_flag_posix_time.out
+${PACKAGE}FILES+= k_flag_posix_messages.out
+${PACKAGE}FILES+= no_flags_posix_monetary.out
+${PACKAGE}FILES+= no_flags_posix_numeric.out
+${PACKAGE}FILES+= no_flags_posix_time.out
+${PACKAGE}FILES+= no_flags_posix_messages.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/locale/tests/Makefile.depend b/usr.bin/locale/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/locale/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/locale/tests/k_flag_posix_messages.out b/usr.bin/locale/tests/k_flag_posix_messages.out
new file mode 100644
index 000000000000..7765f69f799b
--- /dev/null
+++ b/usr.bin/locale/tests/k_flag_posix_messages.out
@@ -0,0 +1,2 @@
+yesexpr="^[yY]"
+noexpr="^[nN]"
diff --git a/usr.bin/locale/tests/k_flag_posix_monetary.out b/usr.bin/locale/tests/k_flag_posix_monetary.out
new file mode 100644
index 000000000000..768f9579e43e
--- /dev/null
+++ b/usr.bin/locale/tests/k_flag_posix_monetary.out
@@ -0,0 +1,21 @@
+int_curr_symbol=""
+currency_symbol=""
+mon_decimal_point=""
+mon_thousands_sep=""
+mon_grouping=-1
+positive_sign=""
+negative_sign=""
+int_frac_digits=-1
+frac_digits=-1
+p_cs_precedes=-1
+p_sep_by_space=-1
+n_cs_precedes=-1
+n_sep_by_space=-1
+p_sign_posn=-1
+n_sign_posn=-1
+int_p_cs_precedes=-1
+int_n_cs_precedes=-1
+int_p_sep_by_space=-1
+int_n_sep_by_space=-1
+int_p_sign_posn=-1
+int_n_sign_posn=-1
diff --git a/usr.bin/locale/tests/k_flag_posix_numeric.out b/usr.bin/locale/tests/k_flag_posix_numeric.out
new file mode 100644
index 000000000000..473e4e045a02
--- /dev/null
+++ b/usr.bin/locale/tests/k_flag_posix_numeric.out
@@ -0,0 +1,3 @@
+decimal_point="."
+thousands_sep=""
+grouping=-1
diff --git a/usr.bin/locale/tests/k_flag_posix_time.out b/usr.bin/locale/tests/k_flag_posix_time.out
new file mode 100644
index 000000000000..cece623846d1
--- /dev/null
+++ b/usr.bin/locale/tests/k_flag_posix_time.out
@@ -0,0 +1,14 @@
+abday="Sun;Mon;Tue;Wed;Thu;Fri;Sat"
+day="Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday"
+abmon="Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec"
+mon="January;February;March;April;May;June;July;August;September;October;November;December"
+d_t_fmt="%a %b %e %H:%M:%S %Y"
+d_fmt="%m/%d/%y"
+t_fmt="%H:%M:%S"
+am_pm="AM;PM"
+t_fmt_ampm="%I:%M:%S %p"
+era=
+era_d_fmt=""
+era_t_fmt=""
+era_d_t_fmt=""
+alt_digits=
diff --git a/usr.bin/locale/tests/locale_test.sh b/usr.bin/locale/tests/locale_test.sh
new file mode 100755
index 000000000000..859816f499c2
--- /dev/null
+++ b/usr.bin/locale/tests/locale_test.sh
@@ -0,0 +1,182 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2019 Yuri Pankov
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case k_flag_posix
+k_flag_posix_head()
+{
+ atf_set "descr" \
+ "Verify output of 'locale -k' for all POSIX specified keywords"
+}
+k_flag_posix_body()
+{
+ export LC_ALL="C"
+
+ # LC_MONETARY
+ atf_check -o file:"$(atf_get_srcdir)/k_flag_posix_monetary.out" \
+ locale -k \
+ int_curr_symbol \
+ currency_symbol \
+ mon_decimal_point \
+ mon_thousands_sep \
+ mon_grouping \
+ positive_sign \
+ negative_sign \
+ int_frac_digits \
+ frac_digits \
+ p_cs_precedes \
+ p_sep_by_space \
+ n_cs_precedes \
+ n_sep_by_space \
+ p_sign_posn \
+ n_sign_posn \
+ int_p_cs_precedes \
+ int_n_cs_precedes \
+ int_p_sep_by_space \
+ int_n_sep_by_space \
+ int_p_sign_posn \
+ int_n_sign_posn
+
+ # LC_NUMERIC
+ atf_check -o file:"$(atf_get_srcdir)/k_flag_posix_numeric.out" \
+ locale -k \
+ decimal_point \
+ thousands_sep \
+ grouping
+
+ # LC_TIME
+ atf_check -o file:"$(atf_get_srcdir)/k_flag_posix_time.out" \
+ locale -k \
+ abday \
+ day \
+ abmon \
+ mon \
+ d_t_fmt \
+ d_fmt \
+ t_fmt \
+ am_pm \
+ t_fmt_ampm \
+ era \
+ era_d_fmt \
+ era_t_fmt \
+ era_d_t_fmt \
+ alt_digits
+
+ # LC_MESSAGES
+ atf_check -o file:"$(atf_get_srcdir)/k_flag_posix_messages.out" \
+ locale -k \
+ yesexpr \
+ noexpr
+}
+
+atf_test_case no_flags_posix
+no_flags_posix_head()
+{
+ atf_set "descr" \
+ "Verify output of 'locale' for all POSIX specified keywords"
+}
+no_flags_posix_body()
+{
+ export LC_ALL="C"
+
+ # LC_MONETARY
+ atf_check -o file:"$(atf_get_srcdir)/no_flags_posix_monetary.out" \
+ locale \
+ int_curr_symbol \
+ currency_symbol \
+ mon_decimal_point \
+ mon_thousands_sep \
+ mon_grouping \
+ positive_sign \
+ negative_sign \
+ int_frac_digits \
+ frac_digits \
+ p_cs_precedes \
+ p_sep_by_space \
+ n_cs_precedes \
+ n_sep_by_space \
+ p_sign_posn \
+ n_sign_posn \
+ int_p_cs_precedes \
+ int_n_cs_precedes \
+ int_p_sep_by_space \
+ int_n_sep_by_space \
+ int_p_sign_posn \
+ int_n_sign_posn
+
+ # LC_NUMERIC
+ atf_check -o file:"$(atf_get_srcdir)/no_flags_posix_numeric.out" \
+ locale \
+ decimal_point \
+ thousands_sep \
+ grouping
+
+ # LC_TIME
+ atf_check -o file:"$(atf_get_srcdir)/no_flags_posix_time.out" \
+ locale \
+ abday \
+ day \
+ abmon \
+ mon \
+ d_t_fmt \
+ d_fmt \
+ t_fmt \
+ am_pm \
+ t_fmt_ampm \
+ era \
+ era_d_fmt \
+ era_t_fmt \
+ era_d_t_fmt \
+ alt_digits
+
+ # LC_MESSAGES
+ atf_check -o file:"$(atf_get_srcdir)/no_flags_posix_messages.out" \
+ locale \
+ yesexpr \
+ noexpr
+}
+
+atf_test_case k_flag_unknown_kw
+k_flag_unknown_kw_head()
+{
+ atf_set "descr" \
+ "Verify 'locale -k' exit status is '1' for unknown keywords"
+}
+k_flag_unknown_kw_body()
+{
+ export LC_ALL="C"
+
+ # Hopefully the keyword will stay nonexistent
+ atf_check -s exit:1 -o empty -e ignore locale -k nonexistent
+}
+
+
+atf_init_test_cases()
+{
+ atf_add_test_case k_flag_posix
+ atf_add_test_case no_flags_posix
+ atf_add_test_case k_flag_unknown_kw
+}
diff --git a/usr.bin/locale/tests/no_flags_posix_messages.out b/usr.bin/locale/tests/no_flags_posix_messages.out
new file mode 100644
index 000000000000..4289d617955e
--- /dev/null
+++ b/usr.bin/locale/tests/no_flags_posix_messages.out
@@ -0,0 +1,2 @@
+^[yY]
+^[nN]
diff --git a/usr.bin/locale/tests/no_flags_posix_monetary.out b/usr.bin/locale/tests/no_flags_posix_monetary.out
new file mode 100644
index 000000000000..e6ccb0b189ea
--- /dev/null
+++ b/usr.bin/locale/tests/no_flags_posix_monetary.out
@@ -0,0 +1,21 @@
+
+
+
+
+-1
+
+
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
+-1
diff --git a/usr.bin/locale/tests/no_flags_posix_numeric.out b/usr.bin/locale/tests/no_flags_posix_numeric.out
new file mode 100644
index 000000000000..4032f82a120d
--- /dev/null
+++ b/usr.bin/locale/tests/no_flags_posix_numeric.out
@@ -0,0 +1,3 @@
+.
+
+-1
diff --git a/usr.bin/locale/tests/no_flags_posix_time.out b/usr.bin/locale/tests/no_flags_posix_time.out
new file mode 100644
index 000000000000..7dd09d48545e
--- /dev/null
+++ b/usr.bin/locale/tests/no_flags_posix_time.out
@@ -0,0 +1,14 @@
+Sun;Mon;Tue;Wed;Thu;Fri;Sat
+Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday
+Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec
+January;February;March;April;May;June;July;August;September;October;November;December
+%a %b %e %H:%M:%S %Y
+%m/%d/%y
+%H:%M:%S
+AM;PM
+%I:%M:%S %p
+
+
+
+
+
diff --git a/usr.bin/localedef/Makefile b/usr.bin/localedef/Makefile
new file mode 100644
index 000000000000..bfc51d33c653
--- /dev/null
+++ b/usr.bin/localedef/Makefile
@@ -0,0 +1,27 @@
+PROG= localedef
+SRCS= charmap.c \
+ collate.c \
+ ctype.c \
+ localedef.c \
+ messages.c \
+ monetary.c \
+ numeric.c \
+ parser.y \
+ scanner.c \
+ time.c \
+ wide.c
+
+WARNS?= 3
+${SRCS:M*.c}: parser.h
+parser.h: parser.y
+
+IGNORE_PRAGMA= yes
+
+CFLAGS+= -I. -I${.CURDIR}
+.if defined(BOOTSTRAPPING)
+CFLAGS+= -I${.CURDIR}/bootstrap
+.endif
+CFLAGS+= -I${SRCTOP}/lib/libc/locale
+CFLAGS+= -I${SRCTOP}/lib/libc/stdtime
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/localedef/Makefile.depend b/usr.bin/localedef/Makefile.depend
new file mode 100644
index 000000000000..c2fea3d32305
--- /dev/null
+++ b/usr.bin/localedef/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/localedef/README b/usr.bin/localedef/README
new file mode 100644
index 000000000000..4d97371941c8
--- /dev/null
+++ b/usr.bin/localedef/README
@@ -0,0 +1,11 @@
+While there are tools called "localedef" in Solaris and Linux, this
+tool does not share heritage with any other implementation. It was
+written independently by Garrett D'Amore while employed at Nexenta
+Systems, and thus carries the Nexenta Copyright.
+
+It was initially released under the CDDL license, but on 4 July 2014,
+Nexenta reissued the source under the BSD 2-clause license. This
+code is part of the Illumos project.
+
+see:
+https://github.com/Nexenta/illumos-nexenta/commit/cf17542a37fc83d0ae093777e30d480423858c29
diff --git a/usr.bin/localedef/bootstrap/_ctype.h b/usr.bin/localedef/bootstrap/_ctype.h
new file mode 100644
index 000000000000..435faf16b809
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/_ctype.h
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * We have to ensure that we use the same constants as the target system when
+ * bootstrapping localedef so that we generate compatible databases.
+ */
+#ifndef __FreeBSD__
+typedef int __ct_rune_t; /* arg type for ctype funcs */
+typedef __ct_rune_t __rune_t; /* rune_t (see above) */
+typedef __ct_rune_t __wint_t; /* wint_t (see above) */
+#endif
+#include "../../include/_ctype.h"
diff --git a/usr.bin/localedef/bootstrap/bootstrap_xlocale_private.h b/usr.bin/localedef/bootstrap/bootstrap_xlocale_private.h
new file mode 100644
index 000000000000..10ff0bb87a5c
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/bootstrap_xlocale_private.h
@@ -0,0 +1,55 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 _LOCALDEF_BOOTSTRAP_XLOCALE_PRIVATE_H
+#define _LOCALDEF_BOOTSTRAP_XLOCALE_PRIVATE_H
+/*
+ * Avoid pulling in anything from the real xlocale_private.h.
+ * Unfortunately, we can't simply add a local xlocale_private.h to include
+ * it instead of the real file, since xlocale_private.h is included with double
+ * quotes from the same directory and therefore the real file will be selected.
+ */
+#define _XLOCALE_PRIVATE__H_
+
+typedef struct _localedef_bootstrap_xlocale* localedef_bootstrap_locale_t;
+struct localedef_bootstrap_xlocale_component {
+ char unused;
+};
+
+/* This must agree with the definition in xlocale_private.h. */
+#define XLOCALE_DEF_VERSION_LEN 12
+
+#endif /* _LOCALDEF_BOOTSTRAP_XLOCALE_PRIVATE_H */
diff --git a/usr.bin/localedef/bootstrap/collate.h b/usr.bin/localedef/bootstrap/collate.h
new file mode 100644
index 000000000000..7cb6bf719014
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/collate.h
@@ -0,0 +1,38 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "namespace.h"
+#include "../../../lib/libc/locale/collate.h"
+#include "un-namespace.h"
diff --git a/usr.bin/localedef/bootstrap/ctype.h b/usr.bin/localedef/bootstrap/ctype.h
new file mode 100644
index 000000000000..6c9532540219
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/ctype.h
@@ -0,0 +1,53 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+#pragma once
+#include <sys/cdefs.h>
+#include_next <ctype.h>
+
+/*
+ * On macOS isxdigit(), etc are defined in _ctype.h, but we have to include the
+ * target _ctype.h so that localedef uses the correct values.
+ * To fix macOS bootstrap, provide a declaration of isxdigit(), etc. here in
+ * a macro-safe way.
+ */
+__BEGIN_DECLS
+int (isalpha)(int);
+int (isascii)(int);
+int (isdigit)(int);
+int (isgraph)(int);
+int (islower)(int);
+int (isxdigit)(int);
+__END_DECLS
diff --git a/usr.bin/localedef/bootstrap/limits.h b/usr.bin/localedef/bootstrap/limits.h
new file mode 100644
index 000000000000..252e1c175c70
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/limits.h
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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_next <limits.h>
+
+#ifndef COLL_WEIGHTS_MAX
+#error "COLL_WEIGHTS_MAX missing"
+#endif
+
+#if COLL_WEIGHTS_MAX != 10
+#pragma message("Changing value of COLL_WEIGHTS_MAX")
+#undef COLL_WEIGHTS_MAX
+#define COLL_WEIGHTS_MAX 10
+#endif
diff --git a/usr.bin/localedef/bootstrap/lmessages.h b/usr.bin/localedef/bootstrap/lmessages.h
new file mode 100644
index 000000000000..965fcda69f98
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/lmessages.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "namespace.h"
+#define lc_messages_T localedef_bootstrap_lc_messages_T
+#include "../../../lib/libc/locale/lmessages.h"
+#include "un-namespace.h"
diff --git a/usr.bin/localedef/bootstrap/lmonetary.h b/usr.bin/localedef/bootstrap/lmonetary.h
new file mode 100644
index 000000000000..f5b50cab8cb4
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/lmonetary.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "namespace.h"
+#define lc_numeric_T localedef_bootstrap_lc_numeric_T
+#include "../../../lib/libc/locale/lmonetary.h"
+#include "un-namespace.h"
diff --git a/usr.bin/localedef/bootstrap/lnumeric.h b/usr.bin/localedef/bootstrap/lnumeric.h
new file mode 100644
index 000000000000..cebe61a46998
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/lnumeric.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "namespace.h"
+#define lc_monetary_T localedef_bootstrap_lc_monetary_T
+#include "../../../lib/libc/locale/lnumeric.h"
+#include "un-namespace.h"
diff --git a/usr.bin/localedef/bootstrap/namespace.h b/usr.bin/localedef/bootstrap/namespace.h
new file mode 100644
index 000000000000..6e14172994d5
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/namespace.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "bootstrap_xlocale_private.h"
+
+#define locale_t localedef_bootstrap_locale_t
+#define xlocale_collate localedef_bootstrap_xlocale_collate
+#define xlocale_component localedef_bootstrap_xlocale_component
+#define xlocale_monetary localedef_bootstrap_xlocale_monetary
+#define xlocale_numeric localedef_bootstrap_xlocale_numeric
diff --git a/usr.bin/localedef/bootstrap/timelocal.h b/usr.bin/localedef/bootstrap/timelocal.h
new file mode 100644
index 000000000000..b54bf5d333da
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/timelocal.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 "namespace.h"
+#define lc_time_T localedef_bootstrap_lc_time_T
+#include "../../../lib/libc/stdtime/timelocal.h"
+#include "un-namespace.h"
diff --git a/usr.bin/localedef/bootstrap/un-namespace.h b/usr.bin/localedef/bootstrap/un-namespace.h
new file mode 100644
index 000000000000..1bd9914bdc05
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/un-namespace.h
@@ -0,0 +1,40 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+#undef locale_t
+#undef xlocale_collate
+#undef xlocale_component
+#undef xlocale_monetary
+#undef xlocale_numeric
diff --git a/usr.bin/localedef/bootstrap/xlocale.h b/usr.bin/localedef/bootstrap/xlocale.h
new file mode 100644
index 000000000000..d418f4ae1cd4
--- /dev/null
+++ b/usr.bin/localedef/bootstrap/xlocale.h
@@ -0,0 +1,53 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2018-2020 Alex Richardson <arichardson@FreeBSD.org>
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory (Department of Computer Science and
+ * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
+ * DARPA SSITH research programme.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#pragma once
+
+/*
+ * This header only exists to avoid pulling in the host xlocale.h from the
+ * libc-internal headers. New versions of glibc include bits/types/locale.h
+ * from stdlib.h and so get their own locale_t (and don't provide xlocale.h),
+ * but older versions include xlocale.h and expect to have a __locale_t. Thus
+ * we provide dummy definitions of both so the (unused) prototypes don't give
+ * errors.
+ */
+
+#ifdef locale_t
+#error "Dummy xlocale.h included inside bootstrapping namespace context"
+#endif
+
+typedef struct __dummy_host_locale *__locale_t;
+typedef __locale_t locale_t;
diff --git a/usr.bin/localedef/charmap.c b/usr.bin/localedef/charmap.c
new file mode 100644
index 000000000000..a8d723163e74
--- /dev/null
+++ b/usr.bin/localedef/charmap.c
@@ -0,0 +1,395 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * CHARMAP file handling for localedef.
+ */
+
+#include <sys/types.h>
+#include <sys/tree.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stddef.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+
+
+typedef struct charmap {
+ const char *name;
+ wchar_t wc;
+ RB_ENTRY(charmap) rb_sym;
+ RB_ENTRY(charmap) rb_wc;
+} charmap_t;
+
+static int cmap_compare_sym(const void *n1, const void *n2);
+static int cmap_compare_wc(const void *n1, const void *n2);
+
+static RB_HEAD(cmap_sym, charmap) cmap_sym;
+static RB_HEAD(cmap_wc, charmap) cmap_wc;
+
+RB_GENERATE_STATIC(cmap_sym, charmap, rb_sym, cmap_compare_sym);
+RB_GENERATE_STATIC(cmap_wc, charmap, rb_wc, cmap_compare_wc);
+
+/*
+ * Array of POSIX specific portable characters.
+ */
+
+static const struct {
+ const char *name;
+ int ch;
+} portable_chars[] = {
+ { "NUL", '\0' },
+ { "SOH", '\x01' },
+ { "STX", '\x02' },
+ { "ETX", '\x03' },
+ { "EOT", '\x04' },
+ { "ENQ", '\x05' },
+ { "ACK", '\x06' },
+ { "BEL", '\a' },
+ { "alert", '\a' },
+ { "BS", '\b' },
+ { "backspace", '\b' },
+ { "HT", '\t' },
+ { "tab", '\t' },
+ { "LF", '\n' },
+ { "newline", '\n' },
+ { "VT", '\v' },
+ { "vertical-tab", '\v' },
+ { "FF", '\f' },
+ { "form-feed", '\f' },
+ { "CR", '\r' },
+ { "carriage-return", '\r' },
+ { "SO", '\x0e' },
+ { "SI", '\x0f' },
+ { "DLE", '\x10' },
+ { "DC1", '\x11' },
+ { "DC2", '\x12' },
+ { "DC3", '\x13' },
+ { "DC4", '\x14' },
+ { "NAK", '\x15' },
+ { "SYN", '\x16' },
+ { "ETB", '\x17' },
+ { "CAN", '\x18' },
+ { "EM", '\x19' },
+ { "SUB", '\x1a' },
+ { "ESC", '\x1b' },
+ { "FS", '\x1c' },
+ { "IS4", '\x1c' },
+ { "GS", '\x1d' },
+ { "IS3", '\x1d' },
+ { "RS", '\x1e' },
+ { "IS2", '\x1e' },
+ { "US", '\x1f' },
+ { "IS1", '\x1f' },
+ { "DEL", '\x7f' },
+ { "space", ' ' },
+ { "exclamation-mark", '!' },
+ { "quotation-mark", '"' },
+ { "number-sign", '#' },
+ { "dollar-sign", '$' },
+ { "percent-sign", '%' },
+ { "ampersand", '&' },
+ { "apostrophe", '\'' },
+ { "left-parenthesis", '(' },
+ { "right-parenthesis", ')' },
+ { "asterisk", '*' },
+ { "plus-sign", '+' },
+ { "comma", ','},
+ { "hyphen-minus", '-' },
+ { "hyphen", '-' },
+ { "full-stop", '.' },
+ { "period", '.' },
+ { "slash", '/' },
+ { "solidus", '/' },
+ { "zero", '0' },
+ { "one", '1' },
+ { "two", '2' },
+ { "three", '3' },
+ { "four", '4' },
+ { "five", '5' },
+ { "six", '6' },
+ { "seven", '7' },
+ { "eight", '8' },
+ { "nine", '9' },
+ { "colon", ':' },
+ { "semicolon", ';' },
+ { "less-than-sign", '<' },
+ { "equals-sign", '=' },
+ { "greater-than-sign", '>' },
+ { "question-mark", '?' },
+ { "commercial-at", '@' },
+ { "left-square-bracket", '[' },
+ { "backslash", '\\' },
+ { "reverse-solidus", '\\' },
+ { "right-square-bracket", ']' },
+ { "circumflex", '^' },
+ { "circumflex-accent", '^' },
+ { "low-line", '_' },
+ { "underscore", '_' },
+ { "grave-accent", '`' },
+ { "left-brace", '{' },
+ { "left-curly-bracket", '{' },
+ { "vertical-line", '|' },
+ { "right-brace", '}' },
+ { "right-curly-bracket", '}' },
+ { "tilde", '~' },
+ { "A", 'A' },
+ { "B", 'B' },
+ { "C", 'C' },
+ { "D", 'D' },
+ { "E", 'E' },
+ { "F", 'F' },
+ { "G", 'G' },
+ { "H", 'H' },
+ { "I", 'I' },
+ { "J", 'J' },
+ { "K", 'K' },
+ { "L", 'L' },
+ { "M", 'M' },
+ { "N", 'N' },
+ { "O", 'O' },
+ { "P", 'P' },
+ { "Q", 'Q' },
+ { "R", 'R' },
+ { "S", 'S' },
+ { "T", 'T' },
+ { "U", 'U' },
+ { "V", 'V' },
+ { "W", 'W' },
+ { "X", 'X' },
+ { "Y", 'Y' },
+ { "Z", 'Z' },
+ { "a", 'a' },
+ { "b", 'b' },
+ { "c", 'c' },
+ { "d", 'd' },
+ { "e", 'e' },
+ { "f", 'f' },
+ { "g", 'g' },
+ { "h", 'h' },
+ { "i", 'i' },
+ { "j", 'j' },
+ { "k", 'k' },
+ { "l", 'l' },
+ { "m", 'm' },
+ { "n", 'n' },
+ { "o", 'o' },
+ { "p", 'p' },
+ { "q", 'q' },
+ { "r", 'r' },
+ { "s", 's' },
+ { "t", 't' },
+ { "u", 'u' },
+ { "v", 'v' },
+ { "w", 'w' },
+ { "x", 'x' },
+ { "y", 'y' },
+ { "z", 'z' },
+ { NULL, 0 }
+};
+
+static int
+cmap_compare_sym(const void *n1, const void *n2)
+{
+ const charmap_t *c1 = n1;
+ const charmap_t *c2 = n2;
+ int rv;
+
+ rv = strcmp(c1->name, c2->name);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+static int
+cmap_compare_wc(const void *n1, const void *n2)
+{
+ const charmap_t *c1 = n1;
+ const charmap_t *c2 = n2;
+
+ return ((c1->wc < c2->wc) ? -1 : (c1->wc > c2->wc) ? 1 : 0);
+}
+
+void
+init_charmap(void)
+{
+ RB_INIT(&cmap_sym);
+
+ RB_INIT(&cmap_wc);
+}
+
+static void
+add_charmap_impl(const char *sym, wchar_t wc, int nodups)
+{
+ charmap_t srch;
+ charmap_t *n = NULL;
+
+ srch.wc = wc;
+ srch.name = sym;
+
+ /*
+ * also possibly insert the wide mapping, although note that there
+ * can only be one of these per wide character code.
+ */
+ if ((wc != (wchar_t)-1) && ((RB_FIND(cmap_wc, &cmap_wc, &srch)) == NULL)) {
+ if ((n = calloc(1, sizeof (*n))) == NULL) {
+ errf("out of memory");
+ return;
+ }
+ n->wc = wc;
+ RB_INSERT(cmap_wc, &cmap_wc, n);
+ }
+
+ if (sym) {
+ if (RB_FIND(cmap_sym, &cmap_sym, &srch) != NULL) {
+ if (nodups) {
+ errf("duplicate character definition");
+ }
+ return;
+ }
+ if ((n == NULL) && ((n = calloc(1, sizeof (*n))) == NULL)) {
+ errf("out of memory");
+ return;
+ }
+ n->wc = wc;
+ n->name = sym;
+
+ RB_INSERT(cmap_sym, &cmap_sym, n);
+ }
+}
+
+void
+add_charmap(const char *sym, int c)
+{
+ add_charmap_impl(sym, c, 1);
+}
+
+void
+add_charmap_undefined(char *sym)
+{
+ charmap_t srch;
+ charmap_t *cm = NULL;
+
+ srch.name = sym;
+ cm = RB_FIND(cmap_sym, &cmap_sym, &srch);
+
+ if ((undefok == 0) && ((cm == NULL) || (cm->wc == (wchar_t)-1))) {
+ warn("undefined symbol <%s>", sym);
+ add_charmap_impl(sym, -1, 0);
+ } else {
+ free(sym);
+ }
+}
+
+void
+add_charmap_range(char *s, char *e, int wc)
+{
+ int ls, le;
+ int si;
+ int sn, en;
+ int i;
+
+ static const char *digits = "0123456789";
+
+ ls = strlen(s);
+ le = strlen(e);
+
+ if (((si = strcspn(s, digits)) == 0) || (si == ls) ||
+ (strncmp(s, e, si) != 0) ||
+ ((int)strspn(s + si, digits) != (ls - si)) ||
+ ((int)strspn(e + si, digits) != (le - si)) ||
+ ((sn = atoi(s + si)) > ((en = atoi(e + si))))) {
+ errf("malformed charmap range");
+ return;
+ }
+
+ s[si] = 0;
+
+ for (i = sn; i <= en; i++) {
+ char *nn;
+ (void) asprintf(&nn, "%s%0*u", s, ls - si, i);
+ if (nn == NULL) {
+ errf("out of memory");
+ return;
+ }
+
+ add_charmap_impl(nn, wc, 1);
+ wc++;
+ }
+ free(s);
+ free(e);
+}
+
+void
+add_charmap_char(const char *name, int val)
+{
+ add_charmap_impl(name, val, 0);
+}
+
+/*
+ * POSIX insists that certain entries be present, even when not in the
+ * original charmap file.
+ */
+void
+add_charmap_posix(void)
+{
+ int i;
+
+ for (i = 0; portable_chars[i].name; i++) {
+ add_charmap_char(portable_chars[i].name, portable_chars[i].ch);
+ }
+}
+
+int
+lookup_charmap(const char *sym, wchar_t *wc)
+{
+ charmap_t srch;
+ charmap_t *n;
+
+ srch.name = sym;
+ n = RB_FIND(cmap_sym, &cmap_sym, &srch);
+ if (n && n->wc != (wchar_t)-1) {
+ if (wc)
+ *wc = n->wc;
+ return (0);
+ }
+ return (-1);
+}
+
+int
+check_charmap(wchar_t wc)
+{
+ charmap_t srch;
+
+ srch.wc = wc;
+ return (RB_FIND(cmap_wc, &cmap_wc, &srch) ? 0 : -1);
+}
diff --git a/usr.bin/localedef/collate.c b/usr.bin/localedef/collate.c
new file mode 100644
index 000000000000..830235036044
--- /dev/null
+++ b/usr.bin/localedef/collate.c
@@ -0,0 +1,1329 @@
+/*-
+ * Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_COLLATE database generation routines for localedef.
+ */
+
+#include <sys/types.h>
+#include <sys/tree.h>
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <limits.h>
+#include "localedef.h"
+#include "parser.h"
+#include "collate.h"
+
+_Static_assert(COLL_WEIGHTS_MAX == 10, "This code assumes a value of 10");
+
+/*
+ * Design notes.
+ *
+ * It will be extremely helpful to the reader if they have access to
+ * the localedef and locale file format specifications available.
+ * Latest versions of these are available from www.opengroup.org.
+ *
+ * The design for the collation code is a bit complex. The goal is a
+ * single collation database as described in collate.h (in
+ * libc/port/locale). However, there are some other tidbits:
+ *
+ * a) The substitution entries are now a directly indexable array. A
+ * priority elsewhere in the table is taken as an index into the
+ * substitution table if it has a high bit (COLLATE_SUBST_PRIORITY)
+ * set. (The bit is cleared and the result is the index into the
+ * table.
+ *
+ * b) We eliminate duplicate entries into the substitution table.
+ * This saves a lot of space.
+ *
+ * c) The priorities for each level are "compressed", so that each
+ * sorting level has consecutively numbered priorities starting at 1.
+ * (O is reserved for the ignore priority.) This means sort levels
+ * which only have a few distinct priorities can represent the
+ * priority level in fewer bits, which makes the strxfrm output
+ * smaller.
+ *
+ * d) We record the total number of priorities so that strxfrm can
+ * figure out how many bytes to expand a numeric priority into.
+ *
+ * e) For the UNDEFINED pass (the last pass), we record the maximum
+ * number of bits needed to uniquely prioritize these entries, so that
+ * the last pass can also use smaller strxfrm output when possible.
+ *
+ * f) Priorities with the sign bit set are verboten. This works out
+ * because no active character set needs that bit to carry significant
+ * information once the character is in wide form.
+ *
+ * To process the entire data to make the database, we actually run
+ * multiple passes over the data.
+ *
+ * The first pass, which is done at parse time, identifies elements,
+ * substitutions, and such, and records them in priority order. As
+ * some priorities can refer to other priorities, using forward
+ * references, we use a table of references indicating whether the
+ * priority's value has been resolved, or whether it is still a
+ * reference.
+ *
+ * The second pass walks over all the items in priority order, noting
+ * that they are used directly, and not just an indirect reference.
+ * This is done by creating a "weight" structure for the item. The
+ * weights are stashed in an RB tree sorted by relative "priority".
+ *
+ * The third pass walks over all the weight structures, in priority
+ * order, and assigns a new monotonically increasing (per sort level)
+ * weight value to them. These are the values that will actually be
+ * written to the file.
+ *
+ * The fourth pass just writes the data out.
+ */
+
+/*
+ * In order to resolve the priorities, we create a table of priorities.
+ * Entries in the table can be in one of three states.
+ *
+ * UNKNOWN is for newly allocated entries, and indicates that nothing
+ * is known about the priority. (For example, when new entries are created
+ * for collating-symbols, this is the value assigned for them until the
+ * collating symbol's order has been determined.
+ *
+ * RESOLVED is used for an entry where the priority indicates the final
+ * numeric weight.
+ *
+ * REFER is used for entries that reference other entries. Typically
+ * this is used for forward references. A collating-symbol can never
+ * have this value.
+ *
+ * The "pass" field is used during final resolution to aid in detection
+ * of referencing loops. (For example <A> depends on <B>, but <B> has its
+ * priority dependent on <A>.)
+ */
+typedef enum {
+ UNKNOWN, /* priority is totally unknown */
+ RESOLVED, /* priority value fully resolved */
+ REFER /* priority is a reference (index) */
+} res_t;
+
+typedef struct weight {
+ int32_t pri;
+ int opt;
+ RB_ENTRY(weight) entry;
+} weight_t;
+
+typedef struct priority {
+ res_t res;
+ int32_t pri;
+ int pass;
+ int lineno;
+} collpri_t;
+
+#define NUM_WT collinfo.directive_count
+
+/*
+ * These are the abstract collating symbols, which are just a symbolic
+ * way to reference a priority.
+ */
+struct collsym {
+ char *name;
+ int32_t ref;
+ RB_ENTRY(collsym) entry;
+};
+
+/*
+ * These are also abstract collating symbols, but we allow them to have
+ * different priorities at different levels.
+ */
+typedef struct collundef {
+ char *name;
+ int32_t ref[COLL_WEIGHTS_MAX];
+ RB_ENTRY(collundef) entry;
+} collundef_t;
+
+/*
+ * These are called "chains" in libc. This records the fact that two
+ * more characters should be treated as a single collating entity when
+ * they appear together. For example, in Spanish <C><h> gets collated
+ * as a character between <C> and <D>.
+ */
+struct collelem {
+ char *symbol;
+ wchar_t *expand;
+ int32_t ref[COLL_WEIGHTS_MAX];
+ RB_ENTRY(collelem) rb_bysymbol;
+ RB_ENTRY(collelem) rb_byexpand;
+};
+
+/*
+ * Individual characters have a sequence of weights as well.
+ */
+typedef struct collchar {
+ wchar_t wc;
+ int32_t ref[COLL_WEIGHTS_MAX];
+ RB_ENTRY(collchar) entry;
+} collchar_t;
+
+/*
+ * Substitution entries. The key is itself a priority. Note that
+ * when we create one of these, we *automatically* wind up with a
+ * fully resolved priority for the key, because creation of
+ * substitutions creates a resolved priority at the same time.
+ */
+typedef struct subst{
+ int32_t key;
+ int32_t ref[COLLATE_STR_LEN];
+ RB_ENTRY(subst) entry;
+ RB_ENTRY(subst) entry_ref;
+} subst_t;
+
+static RB_HEAD(collsyms, collsym) collsyms;
+static RB_HEAD(collundefs, collundef) collundefs;
+static RB_HEAD(elem_by_symbol, collelem) elem_by_symbol;
+static RB_HEAD(elem_by_expand, collelem) elem_by_expand;
+static RB_HEAD(collchars, collchar) collchars;
+static RB_HEAD(substs, subst) substs[COLL_WEIGHTS_MAX];
+static RB_HEAD(substs_ref, subst) substs_ref[COLL_WEIGHTS_MAX];
+static RB_HEAD(weights, weight) weights[COLL_WEIGHTS_MAX];
+static int32_t nweight[COLL_WEIGHTS_MAX];
+
+/*
+ * This is state tracking for the ellipsis token. Note that we start
+ * the initial values so that the ellipsis logic will think we got a
+ * magic starting value of NUL. It starts at minus one because the
+ * starting point is exclusive -- i.e. the starting point is not
+ * itself handled by the ellipsis code.
+ */
+static int currorder = EOF;
+static int lastorder = EOF;
+static collelem_t *currelem;
+static collchar_t *currchar;
+static collundef_t *currundef;
+static wchar_t ellipsis_start = 0;
+static int32_t ellipsis_weights[COLL_WEIGHTS_MAX];
+
+/*
+ * We keep a running tally of weights.
+ */
+static int nextpri = 1;
+static int nextsubst[COLL_WEIGHTS_MAX] = { 0 };
+
+/*
+ * This array collects up the weights for each level.
+ */
+static int32_t order_weights[COLL_WEIGHTS_MAX];
+static int curr_weight = 0;
+static int32_t subst_weights[COLLATE_STR_LEN];
+static int curr_subst = 0;
+
+/*
+ * Some initial priority values.
+ */
+static int32_t pri_undefined[COLL_WEIGHTS_MAX];
+static int32_t pri_ignore;
+
+static collate_info_t collinfo;
+static int32_t subst_count[COLL_WEIGHTS_MAX];
+static int32_t chain_count;
+static int32_t large_count;
+
+static collpri_t *prilist = NULL;
+static int numpri = 0;
+static int maxpri = 0;
+
+static void start_order(int);
+
+static int32_t
+new_pri(void)
+{
+ int i;
+
+ if (numpri >= maxpri) {
+ maxpri = maxpri ? maxpri * 2 : 1024;
+ prilist = realloc(prilist, sizeof (collpri_t) * maxpri);
+ if (prilist == NULL) {
+ fprintf(stderr,"out of memory\n");
+ return (-1);
+ }
+ for (i = numpri; i < maxpri; i++) {
+ prilist[i].res = UNKNOWN;
+ prilist[i].pri = 0;
+ prilist[i].pass = 0;
+ }
+ }
+ return (numpri++);
+}
+
+static collpri_t *
+get_pri(int32_t ref)
+{
+ if ((ref < 0) || (ref > numpri)) {
+ INTERR;
+ return (NULL);
+ }
+ return (&prilist[ref]);
+}
+
+static void
+set_pri(int32_t ref, int32_t v, res_t res)
+{
+ collpri_t *pri;
+
+ pri = get_pri(ref);
+
+ if ((res == REFER) && ((v < 0) || (v >= numpri))) {
+ INTERR;
+ }
+
+ /* Resolve self references */
+ if ((res == REFER) && (ref == v)) {
+ v = nextpri;
+ res = RESOLVED;
+ }
+
+ if (pri->res != UNKNOWN) {
+ warn("repeated item in order list (first on %d)",
+ pri->lineno);
+ return;
+ }
+ pri->lineno = lineno;
+ pri->pri = v;
+ pri->res = res;
+}
+
+static int32_t
+resolve_pri(int32_t ref)
+{
+ collpri_t *pri;
+ static int32_t pass = 0;
+
+ pri = get_pri(ref);
+ pass++;
+ while (pri->res == REFER) {
+ if (pri->pass == pass) {
+ /* report a line with the circular symbol */
+ lineno = pri->lineno;
+ fprintf(stderr,"circular reference in order list\n");
+ return (-1);
+ }
+ if ((pri->pri < 0) || (pri->pri >= numpri)) {
+ INTERR;
+ return (-1);
+ }
+ pri->pass = pass;
+ pri = &prilist[pri->pri];
+ }
+
+ if (pri->res == UNKNOWN) {
+ return (-1);
+ }
+ if (pri->res != RESOLVED)
+ INTERR;
+
+ return (pri->pri);
+}
+
+static int
+weight_compare(const void *n1, const void *n2)
+{
+ int32_t k1 = ((const weight_t *)n1)->pri;
+ int32_t k2 = ((const weight_t *)n2)->pri;
+
+ return (k1 < k2 ? -1 : k1 > k2 ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(weights, weight, entry, weight_compare);
+
+static int
+collsym_compare(const void *n1, const void *n2)
+{
+ const collsym_t *c1 = n1;
+ const collsym_t *c2 = n2;
+ int rv;
+
+ rv = strcmp(c1->name, c2->name);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(collsyms, collsym, entry, collsym_compare);
+
+static int
+collundef_compare(const void *n1, const void *n2)
+{
+ const collundef_t *c1 = n1;
+ const collundef_t *c2 = n2;
+ int rv;
+
+ rv = strcmp(c1->name, c2->name);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(collundefs, collundef, entry, collundef_compare);
+
+static int
+element_compare_symbol(const void *n1, const void *n2)
+{
+ const collelem_t *c1 = n1;
+ const collelem_t *c2 = n2;
+ int rv;
+
+ rv = strcmp(c1->symbol, c2->symbol);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(elem_by_symbol, collelem, rb_bysymbol, element_compare_symbol);
+
+static int
+element_compare_expand(const void *n1, const void *n2)
+{
+ const collelem_t *c1 = n1;
+ const collelem_t *c2 = n2;
+ int rv;
+
+ rv = wcscmp(c1->expand, c2->expand);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(elem_by_expand, collelem, rb_byexpand, element_compare_expand);
+
+static int
+collchar_compare(const void *n1, const void *n2)
+{
+ wchar_t k1 = ((const collchar_t *)n1)->wc;
+ wchar_t k2 = ((const collchar_t *)n2)->wc;
+
+ return (k1 < k2 ? -1 : k1 > k2 ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(collchars, collchar, entry, collchar_compare);
+
+static int
+subst_compare(const void *n1, const void *n2)
+{
+ int32_t k1 = ((const subst_t *)n1)->key;
+ int32_t k2 = ((const subst_t *)n2)->key;
+
+ return (k1 < k2 ? -1 : k1 > k2 ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(substs, subst, entry, subst_compare);
+
+static int
+subst_compare_ref(const void *n1, const void *n2)
+{
+ const wchar_t *c1 = ((const subst_t *)n1)->ref;
+ const wchar_t *c2 = ((const subst_t *)n2)->ref;
+ int rv;
+
+ rv = wcscmp(c1, c2);
+ return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
+}
+
+RB_GENERATE_STATIC(substs_ref, subst, entry_ref, subst_compare_ref);
+
+void
+init_collate(void)
+{
+ int i;
+
+ RB_INIT(&collsyms);
+
+ RB_INIT(&collundefs);
+
+ RB_INIT(&elem_by_symbol);
+
+ RB_INIT(&elem_by_expand);
+
+ RB_INIT(&collchars);
+
+ for (i = 0; i < COLL_WEIGHTS_MAX; i++) {
+ RB_INIT(&substs[i]);
+ RB_INIT(&substs_ref[i]);
+ RB_INIT(&weights[i]);
+ nweight[i] = 1;
+ }
+
+ (void) memset(&collinfo, 0, sizeof (collinfo));
+
+ /* allocate some initial priorities */
+ pri_ignore = new_pri();
+
+ set_pri(pri_ignore, 0, RESOLVED);
+
+ for (i = 0; i < COLL_WEIGHTS_MAX; i++) {
+ pri_undefined[i] = new_pri();
+
+ /* we will override this later */
+ set_pri(pri_undefined[i], COLLATE_MAX_PRIORITY, UNKNOWN);
+ }
+}
+
+void
+define_collsym(char *name)
+{
+ collsym_t *sym;
+
+ if ((sym = calloc(1, sizeof(*sym))) == NULL) {
+ fprintf(stderr,"out of memory\n");
+ return;
+ }
+ sym->name = name;
+ sym->ref = new_pri();
+
+ if (RB_FIND(collsyms, &collsyms, sym) != NULL) {
+ /*
+ * This should never happen because we are only called
+ * for undefined symbols.
+ */
+ free(sym);
+ INTERR;
+ return;
+ }
+ RB_INSERT(collsyms, &collsyms, sym);
+}
+
+collsym_t *
+lookup_collsym(char *name)
+{
+ collsym_t srch;
+
+ srch.name = name;
+ return (RB_FIND(collsyms, &collsyms, &srch));
+}
+
+collelem_t *
+lookup_collelem(char *symbol)
+{
+ collelem_t srch;
+
+ srch.symbol = symbol;
+ return (RB_FIND(elem_by_symbol, &elem_by_symbol, &srch));
+}
+
+static collundef_t *
+get_collundef(char *name)
+{
+ collundef_t srch;
+ collundef_t *ud;
+ int i;
+
+ srch.name = name;
+ if ((ud = RB_FIND(collundefs, &collundefs, &srch)) == NULL) {
+ if (((ud = calloc(1, sizeof(*ud))) == NULL) ||
+ ((ud->name = strdup(name)) == NULL)) {
+ fprintf(stderr,"out of memory\n");
+ free(ud);
+ return (NULL);
+ }
+ for (i = 0; i < NUM_WT; i++) {
+ ud->ref[i] = new_pri();
+ }
+ RB_INSERT(collundefs, &collundefs, ud);
+ }
+ add_charmap_undefined(name);
+ return (ud);
+}
+
+static collchar_t *
+get_collchar(wchar_t wc, int create)
+{
+ collchar_t srch;
+ collchar_t *cc;
+ int i;
+
+ srch.wc = wc;
+ cc = RB_FIND(collchars, &collchars, &srch);
+ if ((cc == NULL) && create) {
+ if ((cc = calloc(1, sizeof(*cc))) == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return (NULL);
+ }
+ for (i = 0; i < NUM_WT; i++) {
+ cc->ref[i] = new_pri();
+ }
+ cc->wc = wc;
+ RB_INSERT(collchars, &collchars, cc);
+ }
+ return (cc);
+}
+
+void
+end_order_collsym(collsym_t *sym)
+{
+ start_order(T_COLLSYM);
+ /* update the weight */
+
+ set_pri(sym->ref, nextpri, RESOLVED);
+ nextpri++;
+}
+
+void
+end_order(void)
+{
+ int i;
+ int32_t pri;
+ int32_t ref;
+ collpri_t *p;
+
+ /* advance the priority/weight */
+ pri = nextpri;
+
+ switch (currorder) {
+ case T_CHAR:
+ for (i = 0; i < NUM_WT; i++) {
+ if (((ref = order_weights[i]) < 0) ||
+ ((p = get_pri(ref)) == NULL) ||
+ (p->pri == -1)) {
+ /* unspecified weight is a self reference */
+ set_pri(currchar->ref[i], pri, RESOLVED);
+ } else {
+ set_pri(currchar->ref[i], ref, REFER);
+ }
+ order_weights[i] = -1;
+ }
+
+ /* leave a cookie trail in case next symbol is ellipsis */
+ ellipsis_start = currchar->wc + 1;
+ currchar = NULL;
+ break;
+
+ case T_ELLIPSIS:
+ /* save off the weights were we can find them */
+ for (i = 0; i < NUM_WT; i++) {
+ ellipsis_weights[i] = order_weights[i];
+ order_weights[i] = -1;
+ }
+ break;
+
+ case T_COLLELEM:
+ if (currelem == NULL) {
+ INTERR;
+ } else {
+ for (i = 0; i < NUM_WT; i++) {
+
+ if (((ref = order_weights[i]) < 0) ||
+ ((p = get_pri(ref)) == NULL) ||
+ (p->pri == -1)) {
+ set_pri(currelem->ref[i], pri,
+ RESOLVED);
+ } else {
+ set_pri(currelem->ref[i], ref, REFER);
+ }
+ order_weights[i] = -1;
+ }
+ }
+ break;
+
+ case T_UNDEFINED:
+ for (i = 0; i < NUM_WT; i++) {
+ if (((ref = order_weights[i]) < 0) ||
+ ((p = get_pri(ref)) == NULL) ||
+ (p->pri == -1)) {
+ set_pri(pri_undefined[i], -1, RESOLVED);
+ } else {
+ set_pri(pri_undefined[i], ref, REFER);
+ }
+ order_weights[i] = -1;
+ }
+ break;
+
+ case T_SYMBOL:
+ for (i = 0; i < NUM_WT; i++) {
+ if (((ref = order_weights[i]) < 0) ||
+ ((p = get_pri(ref)) == NULL) ||
+ (p->pri == -1)) {
+ set_pri(currundef->ref[i], pri, RESOLVED);
+ } else {
+ set_pri(currundef->ref[i], ref, REFER);
+ }
+ order_weights[i] = -1;
+ }
+ break;
+
+ default:
+ INTERR;
+ }
+
+ nextpri++;
+}
+
+static void
+start_order(int type)
+{
+ int i;
+
+ lastorder = currorder;
+ currorder = type;
+
+ /* this is used to protect ELLIPSIS processing */
+ if ((lastorder == T_ELLIPSIS) && (type != T_CHAR)) {
+ fprintf(stderr, "character value expected\n");
+ }
+
+ for (i = 0; i < COLL_WEIGHTS_MAX; i++) {
+ order_weights[i] = -1;
+ }
+ curr_weight = 0;
+}
+
+void
+start_order_undefined(void)
+{
+ start_order(T_UNDEFINED);
+}
+
+void
+start_order_symbol(char *name)
+{
+ currundef = get_collundef(name);
+ start_order(T_SYMBOL);
+}
+
+void
+start_order_char(wchar_t wc)
+{
+ collchar_t *cc;
+ int32_t ref;
+
+ start_order(T_CHAR);
+
+ /*
+ * If we last saw an ellipsis, then we need to close the range.
+ * Handle that here. Note that we have to be careful because the
+ * items *inside* the range are treated exclusiveley to the items
+ * outside of the range. The ends of the range can have quite
+ * different weights than the range members.
+ */
+ if (lastorder == T_ELLIPSIS) {
+ int i;
+
+ if (wc < ellipsis_start) {
+ fprintf(stderr, "malformed range!\n");
+ return;
+ }
+ while (ellipsis_start < wc) {
+ /*
+ * pick all of the saved weights for the
+ * ellipsis. note that -1 encodes for the
+ * ellipsis itself, which means to take the
+ * current relative priority.
+ */
+ if ((cc = get_collchar(ellipsis_start, 1)) == NULL) {
+ INTERR;
+ return;
+ }
+ for (i = 0; i < NUM_WT; i++) {
+ collpri_t *p;
+ if (((ref = ellipsis_weights[i]) == -1) ||
+ ((p = get_pri(ref)) == NULL) ||
+ (p->pri == -1)) {
+ set_pri(cc->ref[i], nextpri, RESOLVED);
+ } else {
+ set_pri(cc->ref[i], ref, REFER);
+ }
+ ellipsis_weights[i] = 0;
+ }
+ ellipsis_start++;
+ nextpri++;
+ }
+ }
+
+ currchar = get_collchar(wc, 1);
+}
+
+void
+start_order_collelem(collelem_t *e)
+{
+ start_order(T_COLLELEM);
+ currelem = e;
+}
+
+void
+start_order_ellipsis(void)
+{
+ int i;
+
+ start_order(T_ELLIPSIS);
+
+ if (lastorder != T_CHAR) {
+ fprintf(stderr, "illegal starting point for range\n");
+ return;
+ }
+
+ for (i = 0; i < NUM_WT; i++) {
+ ellipsis_weights[i] = order_weights[i];
+ }
+}
+
+void
+define_collelem(char *name, wchar_t *wcs)
+{
+ collelem_t *e;
+ int i;
+
+ if (wcslen(wcs) >= COLLATE_STR_LEN) {
+ fprintf(stderr,"expanded collation element too long\n");
+ return;
+ }
+
+ if ((e = calloc(1, sizeof(*e))) == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+ e->expand = wcs;
+ e->symbol = name;
+
+ /*
+ * This is executed before the order statement, so we don't
+ * know how many priorities we *really* need. We allocate one
+ * for each possible weight. Not a big deal, as collating-elements
+ * prove to be quite rare.
+ */
+ for (i = 0; i < COLL_WEIGHTS_MAX; i++) {
+ e->ref[i] = new_pri();
+ }
+
+ /* A character sequence can only reduce to one element. */
+ if ((RB_FIND(elem_by_symbol, &elem_by_symbol, e) != NULL) ||
+ (RB_FIND(elem_by_expand, &elem_by_expand, e) != NULL)) {
+ fprintf(stderr, "duplicate collating element definition\n");
+ free(e);
+ return;
+ }
+ RB_INSERT(elem_by_symbol, &elem_by_symbol, e);
+ RB_INSERT(elem_by_expand, &elem_by_expand, e);
+}
+
+void
+add_order_bit(int kw)
+{
+ uint8_t bit = DIRECTIVE_UNDEF;
+
+ switch (kw) {
+ case T_FORWARD:
+ bit = DIRECTIVE_FORWARD;
+ break;
+ case T_BACKWARD:
+ bit = DIRECTIVE_BACKWARD;
+ break;
+ case T_POSITION:
+ bit = DIRECTIVE_POSITION;
+ break;
+ default:
+ INTERR;
+ break;
+ }
+ collinfo.directive[collinfo.directive_count] |= bit;
+}
+
+void
+add_order_directive(void)
+{
+ if (collinfo.directive_count >= COLL_WEIGHTS_MAX) {
+ fprintf(stderr, "too many directives (max %d)\n", COLL_WEIGHTS_MAX);
+ return;
+ }
+ collinfo.directive_count++;
+}
+
+static void
+add_order_pri(int32_t ref)
+{
+ if (curr_weight >= NUM_WT) {
+ fprintf(stderr, "too many weights (max %d)\n", NUM_WT);
+ return;
+ }
+ order_weights[curr_weight] = ref;
+ curr_weight++;
+}
+
+void
+add_order_collsym(collsym_t *s)
+{
+ add_order_pri(s->ref);
+}
+
+void
+add_order_char(wchar_t wc)
+{
+ collchar_t *cc;
+
+ if ((cc = get_collchar(wc, 1)) == NULL) {
+ INTERR;
+ return;
+ }
+
+ add_order_pri(cc->ref[curr_weight]);
+}
+
+void
+add_order_collelem(collelem_t *e)
+{
+ add_order_pri(e->ref[curr_weight]);
+}
+
+void
+add_order_ignore(void)
+{
+ add_order_pri(pri_ignore);
+}
+
+void
+add_order_symbol(char *sym)
+{
+ collundef_t *c;
+ if ((c = get_collundef(sym)) == NULL) {
+ INTERR;
+ return;
+ }
+ add_order_pri(c->ref[curr_weight]);
+}
+
+void
+add_order_ellipsis(void)
+{
+ /* special NULL value indicates self reference */
+ add_order_pri(0);
+}
+
+void
+add_order_subst(void)
+{
+ subst_t srch;
+ subst_t *s;
+ int i;
+
+ (void) memset(&srch, 0, sizeof (srch));
+ for (i = 0; i < curr_subst; i++) {
+ srch.ref[i] = subst_weights[i];
+ subst_weights[i] = 0;
+ }
+ s = RB_FIND(substs_ref, &substs_ref[curr_weight], &srch);
+
+ if (s == NULL) {
+ if ((s = calloc(1, sizeof(*s))) == NULL) {
+ fprintf(stderr,"out of memory\n");
+ return;
+ }
+ s->key = new_pri();
+
+ /*
+ * We use a self reference for our key, but we set a
+ * high bit to indicate that this is a substitution
+ * reference. This will expedite table lookups later,
+ * and prevent table lookups for situations that don't
+ * require it. (In short, its a big win, because we
+ * can skip a lot of binary searching.)
+ */
+ set_pri(s->key,
+ (nextsubst[curr_weight] | COLLATE_SUBST_PRIORITY),
+ RESOLVED);
+ nextsubst[curr_weight] += 1;
+
+ for (i = 0; i < curr_subst; i++) {
+ s->ref[i] = srch.ref[i];
+ }
+
+ RB_INSERT(substs_ref, &substs_ref[curr_weight], s);
+
+ if (RB_FIND(substs, &substs[curr_weight], s) != NULL) {
+ INTERR;
+ return;
+ }
+ RB_INSERT(substs, &substs[curr_weight], s);
+ }
+ curr_subst = 0;
+
+
+ /*
+ * We are using the current (unique) priority as a search key
+ * in the substitution table.
+ */
+ add_order_pri(s->key);
+}
+
+static void
+add_subst_pri(int32_t ref)
+{
+ if (curr_subst >= COLLATE_STR_LEN) {
+ fprintf(stderr,"substitution string is too long\n");
+ return;
+ }
+ subst_weights[curr_subst] = ref;
+ curr_subst++;
+}
+
+void
+add_subst_char(wchar_t wc)
+{
+ collchar_t *cc;
+
+
+ if (((cc = get_collchar(wc, 1)) == NULL) ||
+ (cc->wc != wc)) {
+ INTERR;
+ return;
+ }
+ /* we take the weight for the character at that position */
+ add_subst_pri(cc->ref[curr_weight]);
+}
+
+void
+add_subst_collelem(collelem_t *e)
+{
+ add_subst_pri(e->ref[curr_weight]);
+}
+
+void
+add_subst_collsym(collsym_t *s)
+{
+ add_subst_pri(s->ref);
+}
+
+void
+add_subst_symbol(char *ptr)
+{
+ collundef_t *cu;
+
+ if ((cu = get_collundef(ptr)) != NULL) {
+ add_subst_pri(cu->ref[curr_weight]);
+ }
+}
+
+void
+add_weight(int32_t ref, int pass)
+{
+ weight_t srch;
+ weight_t *w;
+
+ srch.pri = resolve_pri(ref);
+
+ /* No translation of ignores */
+ if (srch.pri == 0)
+ return;
+
+ /* Substitution priorities are not weights */
+ if (srch.pri & COLLATE_SUBST_PRIORITY)
+ return;
+
+ if (RB_FIND(weights, &weights[pass], &srch) != NULL)
+ return;
+
+ if ((w = calloc(1, sizeof(*w))) == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+ w->pri = srch.pri;
+ RB_INSERT(weights, &weights[pass], w);
+}
+
+void
+add_weights(int32_t *refs)
+{
+ int i;
+ for (i = 0; i < NUM_WT; i++) {
+ add_weight(refs[i], i);
+ }
+}
+
+int32_t
+get_weight(int32_t ref, int pass)
+{
+ weight_t srch;
+ weight_t *w;
+ int32_t pri;
+
+ pri = resolve_pri(ref);
+ if (pri & COLLATE_SUBST_PRIORITY) {
+ return (pri);
+ }
+ if (pri <= 0) {
+ return (pri);
+ }
+ srch.pri = pri;
+ if ((w = RB_FIND(weights, &weights[pass], &srch)) == NULL) {
+ INTERR;
+ return (-1);
+ }
+ return (w->opt);
+}
+
+wchar_t *
+wsncpy(wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ wchar_t *os1 = s1;
+
+ n++;
+ while (--n > 0 && (*s1++ = htote(*s2++)) != 0)
+ continue;
+ if (n > 0)
+ while (--n > 0)
+ *s1++ = 0;
+ return (os1);
+}
+
+#define RB_COUNT(x, name, head, cnt) do { \
+ (cnt) = 0; \
+ RB_FOREACH(x, name, (head)) { \
+ (cnt)++; \
+ } \
+} while (0)
+
+#define RB_NUMNODES(type, name, head, cnt) do { \
+ type *t; \
+ cnt = 0; \
+ RB_FOREACH(t, name, head) { \
+ cnt++; \
+ } \
+} while (0)
+
+void
+dump_collate(void)
+{
+ FILE *f;
+ int i, j, n;
+ size_t sz;
+ int32_t pri;
+ collelem_t *ce;
+ collchar_t *cc;
+ subst_t *sb;
+ char fmt_version[COLLATE_FMT_VERSION_LEN];
+ char def_version[XLOCALE_DEF_VERSION_LEN];
+ collate_char_t chars[UCHAR_MAX + 1];
+ collate_large_t *large;
+ collate_subst_t *subst[COLL_WEIGHTS_MAX];
+ collate_chain_t *chain;
+
+ /*
+ * We have to run through a preliminary pass to identify all the
+ * weights that we use for each sorting level.
+ */
+ for (i = 0; i < NUM_WT; i++) {
+ add_weight(pri_ignore, i);
+ }
+ for (i = 0; i < NUM_WT; i++) {
+ RB_FOREACH(sb, substs, &substs[i]) {
+ for (j = 0; sb->ref[j]; j++) {
+ add_weight(sb->ref[j], i);
+ }
+ }
+ }
+ RB_FOREACH(ce, elem_by_expand, &elem_by_expand) {
+ add_weights(ce->ref);
+ }
+ RB_FOREACH(cc, collchars, &collchars) {
+ add_weights(cc->ref);
+ }
+
+ /*
+ * Now we walk the entire set of weights, removing the gaps
+ * in the weights. This gives us optimum usage. The walk
+ * occurs in priority.
+ */
+ for (i = 0; i < NUM_WT; i++) {
+ weight_t *w;
+ RB_FOREACH(w, weights, &weights[i]) {
+ w->opt = nweight[i];
+ nweight[i] += 1;
+ }
+ }
+
+ (void) memset(&chars, 0, sizeof (chars));
+ (void) memset(fmt_version, 0, COLLATE_FMT_VERSION_LEN);
+ (void) strlcpy(fmt_version, COLLATE_FMT_VERSION, sizeof (fmt_version));
+ (void) memset(def_version, 0, XLOCALE_DEF_VERSION_LEN);
+ if (version)
+ (void) strlcpy(def_version, version, sizeof (def_version));
+
+ /*
+ * We need to make sure we arrange for the UNDEFINED field
+ * to show up. Also, set the total weight counts.
+ */
+ for (i = 0; i < NUM_WT; i++) {
+ if (resolve_pri(pri_undefined[i]) == -1) {
+ set_pri(pri_undefined[i], -1, RESOLVED);
+ /* they collate at the end of everything else */
+ collinfo.undef_pri[i] = htote(COLLATE_MAX_PRIORITY);
+ }
+ collinfo.pri_count[i] = htote(nweight[i]);
+ }
+
+ collinfo.pri_count[NUM_WT] = htote(max_wide());
+ collinfo.undef_pri[NUM_WT] = htote(COLLATE_MAX_PRIORITY);
+ collinfo.directive[NUM_WT] = DIRECTIVE_UNDEFINED;
+
+ /*
+ * Ordinary character priorities
+ */
+ for (i = 0; i <= UCHAR_MAX; i++) {
+ if ((cc = get_collchar(i, 0)) != NULL) {
+ for (j = 0; j < NUM_WT; j++) {
+ chars[i].pri[j] =
+ htote(get_weight(cc->ref[j], j));
+ }
+ } else {
+ for (j = 0; j < NUM_WT; j++) {
+ chars[i].pri[j] =
+ htote(get_weight(pri_undefined[j], j));
+ }
+ /*
+ * Per POSIX, for undefined characters, we
+ * also have to add a last item, which is the
+ * character code.
+ */
+ chars[i].pri[NUM_WT] = htote(i);
+ }
+ }
+
+ /*
+ * Substitution tables
+ */
+ for (i = 0; i < NUM_WT; i++) {
+ collate_subst_t *st = NULL;
+ subst_t *temp;
+ RB_COUNT(temp, substs, &substs[i], n);
+ subst_count[i] = n;
+ if ((st = calloc(n, sizeof(collate_subst_t))) == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+ n = 0;
+ RB_FOREACH(sb, substs, &substs[i]) {
+ if ((st[n].key = resolve_pri(sb->key)) < 0) {
+ /* by definition these resolve! */
+ INTERR;
+ }
+ if (st[n].key != (n | COLLATE_SUBST_PRIORITY)) {
+ INTERR;
+ }
+ st[n].key = htote(st[n].key);
+ for (j = 0; sb->ref[j]; j++) {
+ st[n].pri[j] = htote(get_weight(sb->ref[j],
+ i));
+ }
+ n++;
+ }
+ if (n != subst_count[i])
+ INTERR;
+ subst[i] = st;
+ }
+
+
+ /*
+ * Chains, i.e. collating elements
+ */
+ RB_NUMNODES(collelem_t, elem_by_expand, &elem_by_expand, chain_count);
+ chain = calloc(chain_count, sizeof(collate_chain_t));
+ if (chain == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+ n = 0;
+ RB_FOREACH(ce, elem_by_expand, &elem_by_expand) {
+ (void) wsncpy(chain[n].str, ce->expand, COLLATE_STR_LEN);
+ for (i = 0; i < NUM_WT; i++) {
+ chain[n].pri[i] = htote(get_weight(ce->ref[i], i));
+ }
+ n++;
+ }
+ if (n != chain_count)
+ INTERR;
+
+ /*
+ * Large (> UCHAR_MAX) character priorities
+ */
+ RB_NUMNODES(collchar_t, collchars, &collchars, n);
+ large = calloc(n, sizeof(collate_large_t));
+ if (large == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+
+ i = 0;
+ RB_FOREACH(cc, collchars, &collchars) {
+ int undef = 0;
+ /* we already gathered those */
+ if (cc->wc <= UCHAR_MAX)
+ continue;
+ for (j = 0; j < NUM_WT; j++) {
+ if ((pri = get_weight(cc->ref[j], j)) < 0) {
+ undef = 1;
+ }
+ if (undef && (pri >= 0)) {
+ /* if undefined, then all priorities are */
+ INTERR;
+ } else {
+ large[i].pri.pri[j] = htote(pri);
+ }
+ }
+ if (!undef) {
+ large[i].val = htote(cc->wc);
+ large_count = i++;
+ }
+ }
+
+ if ((f = open_category()) == NULL) {
+ return;
+ }
+
+ /* Time to write the entire data set out */
+
+ for (i = 0; i < NUM_WT; i++)
+ collinfo.subst_count[i] = htote(subst_count[i]);
+ collinfo.chain_count = htote(chain_count);
+ collinfo.large_count = htote(large_count);
+
+ if ((wr_category(fmt_version, COLLATE_FMT_VERSION_LEN, f) < 0) ||
+ (wr_category(def_version, XLOCALE_DEF_VERSION_LEN, f) < 0) ||
+ (wr_category(&collinfo, sizeof (collinfo), f) < 0) ||
+ (wr_category(&chars, sizeof (chars), f) < 0)) {
+ return;
+ }
+
+ for (i = 0; i < NUM_WT; i++) {
+ sz = sizeof (collate_subst_t) * subst_count[i];
+ if (wr_category(subst[i], sz, f) < 0) {
+ return;
+ }
+ }
+ sz = sizeof (collate_chain_t) * chain_count;
+ if (wr_category(chain, sz, f) < 0) {
+ return;
+ }
+ sz = sizeof (collate_large_t) * large_count;
+ if (wr_category(large, sz, f) < 0) {
+ return;
+ }
+
+ close_category(f);
+}
diff --git a/usr.bin/localedef/ctype.c b/usr.bin/localedef/ctype.c
new file mode 100644
index 000000000000..ab7b76e57b2d
--- /dev/null
+++ b/usr.bin/localedef/ctype.c
@@ -0,0 +1,484 @@
+/*-
+ * Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2012 Garrett D'Amore <garrett@damore.org> All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_CTYPE database generation routines for localedef.
+ */
+#include <sys/cdefs.h>
+#include <sys/tree.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include <wchar.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+
+/* Always include the defines for the target: */
+#define _DONT_USE_CTYPE_INLINE_ /* Avoid dependencies on runetype.h */
+#include "_ctype.h"
+#include "runefile.h"
+
+
+/* Needed for bootstrapping, _CTYPE_N */
+#ifndef _CTYPE_N
+#define _CTYPE_N 0x00400000L
+#endif
+
+#define _ISUPPER _CTYPE_U
+#define _ISLOWER _CTYPE_L
+#define _ISDIGIT _CTYPE_D
+#define _ISXDIGIT _CTYPE_X
+#define _ISSPACE _CTYPE_S
+#define _ISBLANK _CTYPE_B
+#define _ISALPHA _CTYPE_A
+#define _ISPUNCT _CTYPE_P
+#define _ISGRAPH _CTYPE_G
+#define _ISPRINT _CTYPE_R
+#define _ISCNTRL _CTYPE_C
+#define _E1 _CTYPE_Q
+#define _E2 _CTYPE_I
+#define _E3 0
+#define _E4 _CTYPE_N
+#define _E5 _CTYPE_T
+
+static wchar_t last_ctype;
+static int ctype_compare(const void *n1, const void *n2);
+
+typedef struct ctype_node {
+ wchar_t wc;
+ int32_t ctype;
+ int32_t toupper;
+ int32_t tolower;
+ RB_ENTRY(ctype_node) entry;
+} ctype_node_t;
+
+static RB_HEAD(ctypes, ctype_node) ctypes;
+RB_GENERATE_STATIC(ctypes, ctype_node, entry, ctype_compare);
+
+static int
+ctype_compare(const void *n1, const void *n2)
+{
+ const ctype_node_t *c1 = n1;
+ const ctype_node_t *c2 = n2;
+
+ return (c1->wc < c2->wc ? -1 : c1->wc > c2->wc ? 1 : 0);
+}
+
+void
+init_ctype(void)
+{
+ RB_INIT(&ctypes);
+}
+
+
+static void
+add_ctype_impl(ctype_node_t *ctn)
+{
+ switch (last_kw) {
+ case T_ISUPPER:
+ ctn->ctype |= (_ISUPPER | _ISALPHA | _ISGRAPH | _ISPRINT);
+ break;
+ case T_ISLOWER:
+ ctn->ctype |= (_ISLOWER | _ISALPHA | _ISGRAPH | _ISPRINT);
+ break;
+ case T_ISALPHA:
+ ctn->ctype |= (_ISALPHA | _ISGRAPH | _ISPRINT);
+ break;
+ case T_ISDIGIT:
+ ctn->ctype |= (_ISDIGIT | _ISGRAPH | _ISPRINT | _ISXDIGIT | _E4);
+ break;
+ case T_ISSPACE:
+ /*
+ * This can be troublesome as <form-feed>, <newline>,
+ * <carriage-return>, <tab>, and <vertical-tab> are defined both
+ * as space and cntrl, and POSIX doesn't allow cntrl/print
+ * combination. We will take care of this in dump_ctype().
+ */
+ ctn->ctype |= (_ISSPACE | _ISPRINT);
+ break;
+ case T_ISCNTRL:
+ ctn->ctype |= _ISCNTRL;
+ break;
+ case T_ISGRAPH:
+ ctn->ctype |= (_ISGRAPH | _ISPRINT);
+ break;
+ case T_ISPRINT:
+ ctn->ctype |= _ISPRINT;
+ break;
+ case T_ISPUNCT:
+ ctn->ctype |= (_ISPUNCT | _ISGRAPH | _ISPRINT);
+ break;
+ case T_ISXDIGIT:
+ ctn->ctype |= (_ISXDIGIT | _ISPRINT);
+ break;
+ case T_ISBLANK:
+ ctn->ctype |= (_ISBLANK | _ISSPACE);
+ break;
+ case T_ISPHONOGRAM:
+ ctn->ctype |= (_E1 | _ISPRINT | _ISGRAPH);
+ break;
+ case T_ISIDEOGRAM:
+ ctn->ctype |= (_E2 | _ISPRINT | _ISGRAPH);
+ break;
+ case T_ISENGLISH:
+ ctn->ctype |= (_E3 | _ISPRINT | _ISGRAPH);
+ break;
+ case T_ISNUMBER:
+ ctn->ctype |= (_E4 | _ISPRINT | _ISGRAPH);
+ break;
+ case T_ISSPECIAL:
+ ctn->ctype |= (_E5 | _ISPRINT | _ISGRAPH);
+ break;
+ case T_ISALNUM:
+ /*
+ * We can't do anything with this. The character
+ * should already be specified as a digit or alpha.
+ */
+ break;
+ default:
+ errf("not a valid character class");
+ }
+}
+
+static ctype_node_t *
+get_ctype(wchar_t wc)
+{
+ ctype_node_t srch;
+ ctype_node_t *ctn;
+
+ srch.wc = wc;
+ if ((ctn = RB_FIND(ctypes, &ctypes, &srch)) == NULL) {
+ if ((ctn = calloc(1, sizeof (*ctn))) == NULL) {
+ errf("out of memory");
+ return (NULL);
+ }
+ ctn->wc = wc;
+
+ RB_INSERT(ctypes, &ctypes, ctn);
+ }
+ return (ctn);
+}
+
+void
+add_ctype(int val)
+{
+ ctype_node_t *ctn;
+
+ if ((ctn = get_ctype(val)) == NULL) {
+ INTERR;
+ return;
+ }
+ add_ctype_impl(ctn);
+ last_ctype = ctn->wc;
+}
+
+void
+add_ctype_range(wchar_t end)
+{
+ ctype_node_t *ctn;
+ wchar_t cur;
+
+ if (end < last_ctype) {
+ errf("malformed character range (%u ... %u))",
+ last_ctype, end);
+ return;
+ }
+ for (cur = last_ctype + 1; cur <= end; cur++) {
+ if ((ctn = get_ctype(cur)) == NULL) {
+ INTERR;
+ return;
+ }
+ add_ctype_impl(ctn);
+ }
+ last_ctype = end;
+
+}
+
+/*
+ * A word about widths: if the width mask is specified, then libc
+ * unconditionally honors it. Otherwise, it assumes printable
+ * characters have width 1, and non-printable characters have width
+ * -1 (except for NULL which is special with width 0). Hence, we have
+ * no need to inject defaults here -- the "default" unset value of 0
+ * indicates that libc should use its own logic in wcwidth as described.
+ */
+void
+add_width(int wc, int width)
+{
+ ctype_node_t *ctn;
+
+ if ((ctn = get_ctype(wc)) == NULL) {
+ INTERR;
+ return;
+ }
+ ctn->ctype &= ~(_CTYPE_SWM);
+ switch (width) {
+ case 0:
+ ctn->ctype |= _CTYPE_SW0;
+ break;
+ case 1:
+ ctn->ctype |= _CTYPE_SW1;
+ break;
+ case 2:
+ ctn->ctype |= _CTYPE_SW2;
+ break;
+ case 3:
+ ctn->ctype |= _CTYPE_SW3;
+ break;
+ }
+}
+
+void
+add_width_range(int start, int end, int width)
+{
+ for (; start <= end; start++) {
+ add_width(start, width);
+ }
+}
+
+void
+add_caseconv(int val, int wc)
+{
+ ctype_node_t *ctn;
+
+ ctn = get_ctype(val);
+ if (ctn == NULL) {
+ INTERR;
+ return;
+ }
+
+ switch (last_kw) {
+ case T_TOUPPER:
+ ctn->toupper = wc;
+ break;
+ case T_TOLOWER:
+ ctn->tolower = wc;
+ break;
+ default:
+ INTERR;
+ break;
+ }
+}
+
+void
+dump_ctype(void)
+{
+ FILE *f;
+ _FileRuneLocale rl;
+ ctype_node_t *ctn, *last_ct, *last_lo, *last_up;
+ _FileRuneEntry *ct = NULL;
+ _FileRuneEntry *lo = NULL;
+ _FileRuneEntry *up = NULL;
+ wchar_t wc;
+ uint32_t runetype_ext_nranges;
+ uint32_t maplower_ext_nranges;
+ uint32_t mapupper_ext_nranges;
+
+ (void) memset(&rl, 0, sizeof (rl));
+ runetype_ext_nranges = 0;
+ last_ct = NULL;
+ maplower_ext_nranges = 0;
+ last_lo = NULL;
+ mapupper_ext_nranges = 0;
+ last_up = NULL;
+
+ if ((f = open_category()) == NULL)
+ return;
+
+ (void) memcpy(rl.magic, _FILE_RUNE_MAGIC_1, 8);
+ (void) strlcpy(rl.encoding, get_wide_encoding(), sizeof (rl.encoding));
+
+ /*
+ * Initialize the identity map.
+ */
+ for (wc = 0; (unsigned)wc < _CACHED_RUNES; wc++) {
+ rl.maplower[wc] = htote(wc);
+ rl.mapupper[wc] = htote(wc);
+ }
+
+ RB_FOREACH(ctn, ctypes, &ctypes) {
+ int conflict = 0;
+
+ wc = ctn->wc;
+
+ /*
+ * POSIX requires certain portable characters have
+ * certain types. Add them if they are missing.
+ */
+ if ((wc >= 1) && (wc <= 127)) {
+ if ((wc >= 'A') && (wc <= 'Z'))
+ ctn->ctype |= _ISUPPER;
+ if ((wc >= 'a') && (wc <= 'z'))
+ ctn->ctype |= _ISLOWER;
+ if ((wc >= '0') && (wc <= '9'))
+ ctn->ctype |= _ISDIGIT;
+ if (wc == ' ')
+ ctn->ctype |= _ISPRINT;
+ if (strchr(" \f\n\r\t\v", (char)wc) != NULL)
+ ctn->ctype |= _ISSPACE;
+ if (strchr("0123456789ABCDEFabcdef", (char)wc) != NULL)
+ ctn->ctype |= _ISXDIGIT;
+ if (strchr(" \t", (char)wc))
+ ctn->ctype |= _ISBLANK;
+
+ /*
+ * Technically these settings are only
+ * required for the C locale. However, it
+ * turns out that because of the historical
+ * version of isprint(), we need them for all
+ * locales as well. Note that these are not
+ * necessarily valid punctation characters in
+ * the current language, but ispunct() needs
+ * to return TRUE for them.
+ */
+ if (strchr("!\"'#$%&()*+,-./:;<=>?@[\\]^_`{|}~",
+ (char)wc))
+ ctn->ctype |= _ISPUNCT;
+ }
+
+ /*
+ * POSIX also requires that certain types imply
+ * others. Add any inferred types here.
+ */
+ if (ctn->ctype & (_ISUPPER |_ISLOWER))
+ ctn->ctype |= _ISALPHA;
+ if (ctn->ctype & _ISDIGIT)
+ ctn->ctype |= _ISXDIGIT;
+ if (ctn->ctype & _ISBLANK)
+ ctn->ctype |= _ISSPACE;
+ if (ctn->ctype & (_ISALPHA|_ISDIGIT|_ISXDIGIT))
+ ctn->ctype |= _ISGRAPH;
+ if (ctn->ctype & _ISGRAPH)
+ ctn->ctype |= _ISPRINT;
+
+ /*
+ * POSIX requires that certain combinations are invalid.
+ * Try fixing the cases we know about (see add_ctype_impl()).
+ */
+ if ((ctn->ctype & (_ISSPACE|_ISCNTRL)) == (_ISSPACE|_ISCNTRL))
+ ctn->ctype &= ~_ISPRINT;
+
+ /*
+ * Finally, don't flag remaining cases as a fatal error,
+ * and just warn about them.
+ */
+ if ((ctn->ctype & _ISALPHA) &&
+ (ctn->ctype & (_ISPUNCT|_ISDIGIT)))
+ conflict++;
+ if ((ctn->ctype & _ISPUNCT) &&
+ (ctn->ctype & (_ISDIGIT|_ISALPHA|_ISXDIGIT)))
+ conflict++;
+ if ((ctn->ctype & _ISSPACE) && (ctn->ctype & _ISGRAPH))
+ conflict++;
+ if ((ctn->ctype & _ISCNTRL) && (ctn->ctype & _ISPRINT))
+ conflict++;
+ if ((wc == ' ') && (ctn->ctype & (_ISPUNCT|_ISGRAPH)))
+ conflict++;
+
+ if (conflict) {
+ warn("conflicting classes for character 0x%x (%x)",
+ wc, ctn->ctype);
+ }
+ /*
+ * Handle the lower 256 characters using the simple
+ * optimization. Note that if we have not defined the
+ * upper/lower case, then we identity map it.
+ */
+ if ((unsigned)wc < _CACHED_RUNES) {
+ rl.runetype[wc] = htote(ctn->ctype);
+ if (ctn->tolower)
+ rl.maplower[wc] = htote(ctn->tolower);
+ if (ctn->toupper)
+ rl.mapupper[wc] = htote(ctn->toupper);
+ continue;
+ }
+
+ if ((last_ct != NULL) && (last_ct->ctype == ctn->ctype) &&
+ (last_ct->wc + 1 == wc)) {
+ ct[runetype_ext_nranges - 1].max = htote(wc);
+ } else {
+ runetype_ext_nranges++;
+ ct = realloc(ct, sizeof (*ct) * runetype_ext_nranges);
+ ct[runetype_ext_nranges - 1].min = htote(wc);
+ ct[runetype_ext_nranges - 1].max = htote(wc);
+ ct[runetype_ext_nranges - 1].map =
+ htote(ctn->ctype);
+ }
+ last_ct = ctn;
+ if (ctn->tolower == 0) {
+ last_lo = NULL;
+ } else if ((last_lo != NULL) &&
+ (last_lo->tolower + 1 == ctn->tolower)) {
+ lo[maplower_ext_nranges - 1].max = htote(wc);
+ last_lo = ctn;
+ } else {
+ maplower_ext_nranges++;
+ lo = realloc(lo, sizeof (*lo) * maplower_ext_nranges);
+ lo[maplower_ext_nranges - 1].min = htote(wc);
+ lo[maplower_ext_nranges - 1].max = htote(wc);
+ lo[maplower_ext_nranges - 1].map =
+ htote(ctn->tolower);
+ last_lo = ctn;
+ }
+
+ if (ctn->toupper == 0) {
+ last_up = NULL;
+ } else if ((last_up != NULL) &&
+ (last_up->toupper + 1 == ctn->toupper)) {
+ up[mapupper_ext_nranges-1].max = htote(wc);
+ last_up = ctn;
+ } else {
+ mapupper_ext_nranges++;
+ up = realloc(up, sizeof (*up) * mapupper_ext_nranges);
+ up[mapupper_ext_nranges - 1].min = htote(wc);
+ up[mapupper_ext_nranges - 1].max = htote(wc);
+ up[mapupper_ext_nranges - 1].map =
+ htote(ctn->toupper);
+ last_up = ctn;
+ }
+ }
+
+ rl.runetype_ext_nranges = htote(runetype_ext_nranges);
+ rl.maplower_ext_nranges = htote(maplower_ext_nranges);
+ rl.mapupper_ext_nranges = htote(mapupper_ext_nranges);
+ if ((wr_category(&rl, sizeof (rl), f) < 0) ||
+ (wr_category(ct, sizeof (*ct) * runetype_ext_nranges, f) < 0) ||
+ (wr_category(lo, sizeof (*lo) * maplower_ext_nranges, f) < 0) ||
+ (wr_category(up, sizeof (*up) * mapupper_ext_nranges, f) < 0)) {
+ return;
+ }
+
+ close_category(f);
+}
diff --git a/usr.bin/localedef/localedef.1 b/usr.bin/localedef/localedef.1
new file mode 100644
index 000000000000..be37715f490d
--- /dev/null
+++ b/usr.bin/localedef/localedef.1
@@ -0,0 +1,278 @@
+.\" Copyright (c) 1992, X/Open Company Limited All Rights Reserved
+.\" Portions Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved
+.\" Portions Copyright 2013 DEY Storage Systems, Inc.
+.\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for
+.\" permission to reproduce portions of its copyrighted documentation.
+.\" Original documentation from The Open Group can be obtained online at
+.\" http://www.opengroup.org/bookstore/.
+.\" The Institute of Electrical and Electronics Engineers and The Open Group,
+.\" have given us permission to reprint portions of their documentation. In
+.\" the following statement, the phrase "this text" refers to portions of the
+.\" system documentation. Portions of this text are reprinted and reproduced
+.\" in electronic form in the Sun OS Reference Manual, from IEEE Std 1003.1,
+.\" 2004 Edition, Standard for Information Technology -- Portable Operating
+.\" System Interface (POSIX), The Open Group Base Specifications Issue 6,
+.\" Copyright (C) 2001-2004 by the Institute of Electrical and Electronics
+.\" Engineers, Inc and The Open Group. In the event of any discrepancy between
+.\" these versions and the original IEEE and The Open Group Standard, the
+.\" original IEEE and The Open Group Standard is the referee document. The
+.\" original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\" This notice shall appear on any product containing this material.
+.\" The contents of this file are subject to the terms of the Common
+.\" Development and Distribution License (the "License"). You may not use
+.\" this file except in compliance with the License.
+.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or
+.\" http://www.opensolaris.org/os/licensing. See the License for the specific
+.\" language governing permissions and limitations under the License.
+.\" When distributing Covered Code, include this CDDL HEADER in each file and
+.\" include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable,
+.\" add the following below this CDDL HEADER, with the fields enclosed by
+.\" brackets "[]" replaced with your own identifying information:
+.\" Portions Copyright [yyyy] [name of copyright owner]
+.\"
+.Dd June 29, 2023
+.Dt LOCALEDEF 1
+.Os
+.Sh NAME
+.Nm localedef
+.Nd define locale environment
+.Sh SYNOPSIS
+.Nm
+.Op Fl bcDlUv
+.Op Fl f Ar charmap
+.Op Fl i Ar sourcefile
+.Op Fl u Ar codeset
+.Op Fl w Ar widthfile
+.Ar localename
+.Sh DESCRIPTION
+The
+.Nm
+utility converts source definitions for locale categories
+into a format usable by the functions and utilities whose operational behavior
+is determined by the setting of the locale environment variables; see
+.Xr environ 7 .
+.Pp
+The utility reads source definitions for one or more locale categories
+belonging to the same locale from the file named in the
+.Fl i
+option (if specified) or from standard input.
+.Pp
+Each category source definition is identified by the corresponding environment
+variable name and terminated by an
+.Sy END
+.Em category-name
+statement.
+The following categories are supported:
+.Bl -tag -width ".Ev LC_MONETARY"
+.It Ev LC_CTYPE
+Defines character classification and case conversion.
+.It Ev LC_COLLATE
+Defines collation rules.
+.It Ev LC_MONETARY
+Defines the format and symbols used in formatting of monetary information.
+.It Ev LC_NUMERIC
+Defines the decimal delimiter, grouping and grouping symbol for non-monetary
+numeric editing.
+.It Ev LC_TIME
+Defines the format and content of date and time information.
+.It Ev LC_MESSAGES
+Defines the format and values of affirmative and negative responses.
+.El
+.Pp
+The following options are supported:
+.Bl -tag -width indent
+.It Fl b
+Use big-endian byte order for output.
+.It Fl c
+Creates permanent output even if warning messages have been issued.
+.It Fl D
+BSD-style
+output.
+Rather than the default of creating the
+.Ar localename
+directory and creating files like
+.Pa LC_CTYPE ,
+.Pa LC_COLLATE ,
+etc.\& in that directory,
+the output file names have the format
+.Dq <localename>.<category>
+and are dumped to the current directory.
+.It Fl f Ar charmap
+Specifies the pathname of a file containing a mapping of character symbols and
+collating element symbols to actual character encodings.
+This option must be specified if symbolic names (other than collating symbols
+defined in a
+.Sy collating-symbol
+keyword) are used.
+If the
+.Fl f
+option is not present, the default character mapping will be used.
+.It Fl i Ar sourcefile
+The path name of a file containing the source definitions.
+If this option is not present, source definitions will be read from
+standard input.
+.It Fl l
+Use little-endian byte order for output.
+.It Fl u Ar codeset
+Specifies the name of a codeset used as the target mapping of character symbols
+and collating element symbols whose encoding values are defined in terms of the
+ISO/IEC 10646-1:2000 standard position constant values.
+See
+.Sx NOTES .
+.It Fl U
+Ignore the presence of character symbols that have no matching character
+definition.
+This facilitates the use of a common locale definition file to be used across multiple
+encodings, even when some symbols are not present in a given encoding.
+.It Fl v
+Emit verbose debugging output on standard output.
+.It Fl w Ar widthfile
+The path name of the file containing character screen width definitions.
+If not supplied, then default screen widths will be assumed, which will
+generally not account for East Asian encodings requiring more than a single
+character cell to display, nor for combining or accent marks that occupy
+no additional screen width.
+.It Fl V Ar version
+Specifies a version string describing the version of the locale definition.
+This string can be retrieved with
+.Xr querylocale 3 ,
+and is intended to allow applications to detect locale definition changes.
+Currently it is stored only for the
+.Sy LC_COLLATE
+category.
+.El
+.Pp
+The following operands are required:
+.Bl -tag -width ".Ar localename"
+.It Ar localename
+Identifies the locale.
+If the name contains one or more slash characters,
+.Ar localename
+will be interpreted as a path name where the created locale
+definitions will be stored.
+This capability may be restricted to users with appropriate privileges.
+(As a consequence of specifying one
+.Ar localename ,
+although several categories can be processed in one execution, only categories
+belonging to the same locale can be processed.)
+.El
+.Sh OUTPUT
+.Nm
+creates a directory of files that represents the locale's data,
+unless instructed otherwise by the
+.Fl D (
+BSD
+output) option.
+The contants of this directory should generally be copied into the
+appropriate subdirectory of
+.Pa /usr/share/locale
+in order the definitions to be visible to programs linked with libc.
+.Sh ENVIRONMENT
+See
+.Xr environ 7
+for definitions of the following environment variables that affect the
+execution of
+.Nm :
+.Ev LANG ,
+.Ev LC_ALL ,
+.Ev LC_COLLATE ,
+.Ev LC_CTYPE ,
+.Ev LC_MESSAGES ,
+.Ev LC_MONETARY ,
+.Ev LC_MUMERIC ,
+.Ev LC_TIME ,
+and
+.Ev NLSPATH .
+.Sh EXIT STATUS
+The following exit values are returned:
+.Bl -tag -width XX
+.It 0
+No errors occurred and the locales were successfully created.
+.It 1
+Warnings occurred and the locales were successfully created.
+.It 2
+The locale specification exceeded implementation limits or the coded character
+set or sets used were not supported by the implementation, and no locale was
+created.
+.It >3
+Warnings or errors occurred and no output was created.
+.El
+.Pp
+If an error is detected, no permanent output will be created.
+.Sh SEE ALSO
+.Xr locale 1 ,
+.Xr iconv_open 3 ,
+.Xr nl_langinfo 3 ,
+.Xr querylocale 3 ,
+.Xr strftime 3 ,
+.Xr environ 7
+.Sh WARNINGS
+If warnings occur, permanent output will be created if the
+.Fl c
+option was specified.
+The following conditions will cause warning messages to be issued:
+.Bl -bullet
+.It
+If a symbolic name not found in the
+.Pa charmap
+file is used for the descriptions of the
+.Sy LC_CTYPE
+or
+.Sy LC_COLLATE
+categories (for other categories, this will be an error condition).
+.It
+If optional keywords not supported by the implementation are present in the
+source.
+.El
+.Sh NOTES
+When the
+.Fl u
+option is used, the
+.Ar codeset
+option-argument is interpreted as a name of a codeset to which the
+ISO/IEC 10646-1:2000 standard position constant values are converted.
+Both the ISO/IEC 10646-1:2000 standard position constant values and
+other formats (decimal, hexadecimal, or octal) are valid as encoding
+values within the charmap file.
+The
+.Ar codeset
+can be any codeset that is supported by the
+.Fn iconv_open 3
+function.
+.Pp
+When conflicts occur between the charmap specification of
+.Ar codeset ,
+.Em mb_cur_max ,
+or
+.Em mb_cur_min
+and the corresponding value for the codeset represented by the
+.Fl u
+option-argument
+.Ar codeset ,
+the
+.Nm
+utility fails with an error.
+.Pp
+When conflicts occur between the charmap encoding values specified for symbolic
+names of characters of the portable character set and the character encoding
+values defined by the US-ASCII, the result is unspecified.
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 11 .
+.Pp
+It was written by
+.An Garrett D'Amore
+.Aq Mt garrett@nexenta.com
+for illumos.
+.An John Marino
+.Aq Mt draco@marino.st
+provided the alternations necessary to compile cleanly on
+.Dx .
+.An Baptiste Daroussin
+.Aq Mt bapt@FreeBSD.org
+ported it to
+.Fx
+and converted it to
+.Xr tree 3 .
diff --git a/usr.bin/localedef/localedef.c b/usr.bin/localedef/localedef.c
new file mode 100644
index 000000000000..5ff146d6f655
--- /dev/null
+++ b/usr.bin/localedef/localedef.c
@@ -0,0 +1,379 @@
+/*-
+ * Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * POSIX localedef.
+ */
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <limits.h>
+#include <locale.h>
+#include <dirent.h>
+#include "collate.h"
+#include "localedef.h"
+#include "parser.h"
+
+#ifndef TEXT_DOMAIN
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+
+static int bsd = 0;
+static int byteorder = 0;
+int verbose = 0;
+int undefok = 0;
+int warnok = 0;
+static char *locname = NULL;
+static char locpath[PATH_MAX];
+char *version = NULL;
+
+const char *
+category_name(void)
+{
+ switch (get_category()) {
+ case T_CHARMAP:
+ return ("CHARMAP");
+ case T_WIDTH:
+ return ("WIDTH");
+ case T_COLLATE:
+ return ("LC_COLLATE");
+ case T_CTYPE:
+ return ("LC_CTYPE");
+ case T_MESSAGES:
+ return ("LC_MESSAGES");
+ case T_MONETARY:
+ return ("LC_MONETARY");
+ case T_NUMERIC:
+ return ("LC_NUMERIC");
+ case T_TIME:
+ return ("LC_TIME");
+ default:
+ INTERR;
+ return (NULL);
+ }
+}
+
+static char *
+category_file(void)
+{
+ if (bsd)
+ (void) snprintf(locpath, sizeof (locpath), "%s.%s",
+ locname, category_name());
+ else
+ (void) snprintf(locpath, sizeof (locpath), "%s/%s",
+ locname, category_name());
+ return (locpath);
+}
+
+FILE *
+open_category(void)
+{
+ FILE *file;
+
+ if (verbose) {
+ (void) printf("Writing category %s: ", category_name());
+ (void) fflush(stdout);
+ }
+
+ /* make the parent directory */
+ if (!bsd)
+ (void) mkdir(dirname(category_file()), 0755);
+
+ /*
+ * note that we have to regenerate the file name, as dirname
+ * clobbered it.
+ */
+ file = fopen(category_file(), "w");
+ if (file == NULL) {
+ errf("%s", strerror(errno));
+ return (NULL);
+ }
+ return (file);
+}
+
+void
+close_category(FILE *f)
+{
+ if (fchmod(fileno(f), 0644) < 0) {
+ (void) fclose(f);
+ (void) unlink(category_file());
+ errf("%s", strerror(errno));
+ }
+ if (fclose(f) < 0) {
+ (void) unlink(category_file());
+ errf("%s", strerror(errno));
+ }
+ if (verbose) {
+ (void) fprintf(stdout, "done.\n");
+ (void) fflush(stdout);
+ }
+}
+
+/*
+ * This function is used when copying the category from another
+ * locale. Note that the copy is actually performed using a hard
+ * link for efficiency.
+ */
+void
+copy_category(char *src)
+{
+ char srcpath[PATH_MAX];
+ int rv;
+
+ (void) snprintf(srcpath, sizeof (srcpath), "%s/%s",
+ src, category_name());
+ rv = access(srcpath, R_OK);
+ if ((rv != 0) && (strchr(srcpath, '/') == NULL)) {
+ /* Maybe we should try the system locale */
+ (void) snprintf(srcpath, sizeof (srcpath),
+ "/usr/lib/locale/%s/%s", src, category_name());
+ rv = access(srcpath, R_OK);
+ }
+
+ if (rv != 0) {
+ fprintf(stderr,"source locale data unavailable: %s\n", src);
+ return;
+ }
+
+ if (verbose > 1) {
+ (void) printf("Copying category %s from %s: ",
+ category_name(), src);
+ (void) fflush(stdout);
+ }
+
+ /* make the parent directory */
+ if (!bsd)
+ (void) mkdir(dirname(category_file()), 0755);
+
+ if (link(srcpath, category_file()) != 0) {
+ fprintf(stderr,"unable to copy locale data: %s\n",
+ strerror(errno));
+ return;
+ }
+ if (verbose > 1) {
+ (void) printf("done.\n");
+ }
+}
+
+int
+putl_category(const char *s, FILE *f)
+{
+ if (s && fputs(s, f) == EOF) {
+ (void) fclose(f);
+ (void) unlink(category_file());
+ errf("%s", strerror(errno));
+ return (EOF);
+ }
+ if (fputc('\n', f) == EOF) {
+ (void) fclose(f);
+ (void) unlink(category_file());
+ errf("%s", strerror(errno));
+ return (EOF);
+ }
+ return (0);
+}
+
+int
+wr_category(void *buf, size_t sz, FILE *f)
+{
+ if (!sz) {
+ return (0);
+ }
+ if (fwrite(buf, sz, 1, f) < 1) {
+ (void) fclose(f);
+ (void) unlink(category_file());
+ errf("%s", strerror(errno));
+ return (EOF);
+ }
+ return (0);
+}
+
+uint32_t
+htote(uint32_t arg)
+{
+
+ if (byteorder == 4321)
+ return (htobe32(arg));
+ else if (byteorder == 1234)
+ return (htole32(arg));
+ else
+ return (arg);
+}
+
+int yyparse(void);
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr, "Usage: localedef [options] localename\n");
+ (void) fprintf(stderr, "[options] are:\n");
+ (void) fprintf(stderr, " -D : BSD-style output\n");
+ (void) fprintf(stderr, " -b : big-endian output\n");
+ (void) fprintf(stderr, " -c : ignore warnings\n");
+ (void) fprintf(stderr, " -l : little-endian output\n");
+ (void) fprintf(stderr, " -v : verbose output\n");
+ (void) fprintf(stderr, " -U : ignore undefined symbols\n");
+ (void) fprintf(stderr, " -f charmap : use given charmap file\n");
+ (void) fprintf(stderr, " -u encoding : assume encoding\n");
+ (void) fprintf(stderr, " -w widths : use screen widths file\n");
+ (void) fprintf(stderr, " -i locsrc : source file for locale\n");
+ (void) fprintf(stderr, " -V version : version string for locale\n");
+ exit(4);
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ char *lfname = NULL;
+ char *cfname = NULL;
+ char *wfname = NULL;
+ DIR *dir;
+
+ init_charmap();
+ init_collate();
+ init_ctype();
+ init_messages();
+ init_monetary();
+ init_numeric();
+ init_time();
+
+#if YYDEBUG
+ yydebug = 0;
+#endif
+
+ (void) setlocale(LC_ALL, "");
+
+ while ((c = getopt(argc, argv, "blw:i:cf:u:vUDV:")) != -1) {
+ switch (c) {
+ case 'D':
+ bsd = 1;
+ break;
+ case 'b':
+ case 'l':
+ if (byteorder != 0)
+ usage();
+ byteorder = c == 'b' ? 4321 : 1234;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'i':
+ lfname = optarg;
+ break;
+ case 'u':
+ set_wide_encoding(optarg);
+ break;
+ case 'f':
+ cfname = optarg;
+ break;
+ case 'U':
+ undefok++;
+ break;
+ case 'c':
+ warnok++;
+ break;
+ case 'w':
+ wfname = optarg;
+ break;
+ case '?':
+ usage();
+ break;
+ case 'V':
+ version = optarg;
+ break;
+ }
+ }
+
+ if ((argc - 1) != (optind)) {
+ usage();
+ }
+ locname = argv[argc - 1];
+ if (verbose) {
+ (void) printf("Processing locale %s.\n", locname);
+ }
+
+ if (version && strlen(version) >= XLOCALE_DEF_VERSION_LEN) {
+ (void) fprintf(stderr, "Version string too long.\n");
+ exit(1);
+ }
+
+ if (cfname) {
+ if (verbose)
+ (void) printf("Loading charmap %s.\n", cfname);
+ reset_scanner(cfname);
+ (void) yyparse();
+ }
+
+ if (wfname) {
+ if (verbose)
+ (void) printf("Loading widths %s.\n", wfname);
+ reset_scanner(wfname);
+ (void) yyparse();
+ }
+
+ if (verbose) {
+ (void) printf("Loading POSIX portable characters.\n");
+ }
+ add_charmap_posix();
+
+ if (lfname) {
+ reset_scanner(lfname);
+ } else {
+ reset_scanner(NULL);
+ }
+
+ /* make the directory for the locale if not already present */
+ if (!bsd) {
+ while ((dir = opendir(locname)) == NULL) {
+ if ((errno != ENOENT) ||
+ (mkdir(locname, 0755) < 0)) {
+ errf("%s", strerror(errno));
+ }
+ }
+ (void) closedir(dir);
+ (void) mkdir(dirname(category_file()), 0755);
+ }
+
+ (void) yyparse();
+ if (verbose) {
+ (void) printf("All done.\n");
+ }
+ return (warnings ? 1 : 0);
+}
diff --git a/usr.bin/localedef/localedef.h b/usr.bin/localedef/localedef.h
new file mode 100644
index 000000000000..34299033214c
--- /dev/null
+++ b/usr.bin/localedef/localedef.h
@@ -0,0 +1,177 @@
+/*-
+ * Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * POSIX localedef.
+ */
+
+/* Common header files. */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int com_char;
+extern int esc_char;
+extern int mb_cur_max;
+extern int mb_cur_min;
+extern int last_kw;
+extern int verbose;
+#if YYDEBUG
+extern int yydebug;
+#endif
+extern int lineno;
+extern int undefok; /* mostly ignore undefined symbols */
+extern int warnok;
+extern int warnings;
+
+extern char *version;
+
+int yylex(void);
+void yyerror(const char *);
+_Noreturn void errf(const char *, ...) __printflike(1, 2);
+void warn(const char *, ...) __printflike(1, 2);
+
+int putl_category(const char *, FILE *);
+int wr_category(void *, size_t, FILE *);
+FILE *open_category(void);
+void close_category(FILE *);
+void copy_category(char *);
+const char *category_name(void);
+
+int get_category(void);
+int get_symbol(void);
+int get_escaped(int);
+int get_wide(void);
+void reset_scanner(const char *);
+void scan_to_eol(void);
+void add_wcs(wchar_t);
+void add_tok(int);
+wchar_t *get_wcs(void);
+
+uint32_t htote(uint32_t);
+
+/* charmap.c - CHARMAP handling */
+void init_charmap(void);
+void add_charmap(const char *, int);
+void add_charmap_undefined(char *);
+void add_charmap_posix(void);
+void add_charmap_range(char *, char *, int);
+void add_charmap_char(const char *name, int val);
+int lookup_charmap(const char *, wchar_t *);
+int check_charmap_undefined(char *);
+int check_charmap(wchar_t);
+
+/* collate.o - LC_COLLATE handling */
+typedef struct collelem collelem_t;
+typedef struct collsym collsym_t;
+void init_collate(void);
+void define_collsym(char *);
+void define_collelem(char *, wchar_t *);
+void add_order_directive(void);
+void add_order_bit(int);
+void dump_collate(void);
+collsym_t *lookup_collsym(char *);
+collelem_t *lookup_collelem(char *);
+void start_order_collelem(collelem_t *);
+void start_order_undefined(void);
+void start_order_symbol(char *);
+void start_order_char(wchar_t);
+void start_order_ellipsis(void);
+void end_order_collsym(collsym_t *);
+void end_order(void);
+void add_weight(int32_t, int);
+void add_weights(int32_t *);
+void add_weight_num(int);
+void add_order_collelem(collelem_t *);
+void add_order_collsym(collsym_t *);
+void add_order_char(wchar_t);
+void add_order_ignore(void);
+void add_order_ellipsis(void);
+void add_order_symbol(char *);
+void add_order_subst(void);
+void add_subst_char(wchar_t);
+void add_subst_collsym(collsym_t *);
+void add_subst_collelem(collelem_t *);
+void add_subst_symbol(char *);
+int32_t get_weight(int32_t, int);
+wchar_t * wsncpy(wchar_t *, const wchar_t *, size_t);
+
+
+/* ctype.c - LC_CTYPE handling */
+void init_ctype(void);
+void add_ctype(int);
+void add_ctype_range(wchar_t);
+void add_width(int, int);
+void add_width_range(int, int, int);
+void add_caseconv(int, int);
+void dump_ctype(void);
+
+/* messages.c - LC_MESSAGES handling */
+void init_messages(void);
+void add_message(wchar_t *);
+void dump_messages(void);
+
+/* monetary.c - LC_MONETARY handling */
+void init_monetary(void);
+void add_monetary_str(wchar_t *);
+void add_monetary_num(int);
+void reset_monetary_group(void);
+void add_monetary_group(int);
+void dump_monetary(void);
+
+/* numeric.c - LC_NUMERIC handling */
+void init_numeric(void);
+void add_numeric_str(wchar_t *);
+void reset_numeric_group(void);
+void add_numeric_group(int);
+void dump_numeric(void);
+
+/* time.c - LC_TIME handling */
+void init_time(void);
+void add_time_str(wchar_t *);
+void reset_time_list(void);
+void add_time_list(wchar_t *);
+void check_time_list(void);
+void dump_time(void);
+
+/* wide.c - Wide character handling. */
+int to_wide(wchar_t *, const char *);
+int to_mbs(char *, wchar_t);
+int to_mb(char *, wchar_t);
+char *to_mb_string(const wchar_t *);
+void set_wide_encoding(const char *);
+void werr(const char *, ...);
+const char *get_wide_encoding(void);
+int max_wide(void);
+
+//#define _(x) gettext(x)
+#define INTERR fprintf(stderr,"internal fault (%s:%d)\n", __FILE__, __LINE__)
diff --git a/usr.bin/localedef/messages.c b/usr.bin/localedef/messages.c
new file mode 100644
index 000000000000..6b8eb9d684dd
--- /dev/null
+++ b/usr.bin/localedef/messages.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_MESSAGES database generation routines for localedef.
+ */
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+#include "lmessages.h"
+
+static struct lc_messages_T msgs;
+
+void
+init_messages(void)
+{
+ (void) memset(&msgs, 0, sizeof (msgs));
+}
+
+void
+add_message(wchar_t *wcs)
+{
+ char *str;
+
+ if ((str = to_mb_string(wcs)) == NULL) {
+ INTERR;
+ return;
+ }
+ free(wcs);
+
+ switch (last_kw) {
+ case T_YESSTR:
+ msgs.yesstr = str;
+ break;
+ case T_NOSTR:
+ msgs.nostr = str;
+ break;
+ case T_YESEXPR:
+ msgs.yesexpr = str;
+ break;
+ case T_NOEXPR:
+ msgs.noexpr = str;
+ break;
+ default:
+ free(str);
+ INTERR;
+ break;
+ }
+}
+
+void
+dump_messages(void)
+{
+ FILE *f;
+ char *ptr;
+
+ if (msgs.yesstr == NULL) {
+ warn("missing field 'yesstr'");
+ msgs.yesstr = "";
+ }
+ if (msgs.nostr == NULL) {
+ warn("missing field 'nostr'");
+ msgs.nostr = "";
+ }
+
+ /*
+ * CLDR likes to add : separated lists for yesstr and nostr.
+ * Legacy Solaris code does not seem to grok this. Fix it.
+ */
+ if ((ptr = strchr(msgs.yesstr, ':')) != NULL)
+ *ptr = 0;
+ if ((ptr = strchr(msgs.nostr, ':')) != NULL)
+ *ptr = 0;
+
+ if ((f = open_category()) == NULL) {
+ return;
+ }
+
+ if ((putl_category(msgs.yesexpr, f) == EOF) ||
+ (putl_category(msgs.noexpr, f) == EOF) ||
+ (putl_category(msgs.yesstr, f) == EOF) ||
+ (putl_category(msgs.nostr, f) == EOF)) {
+ return;
+ }
+ close_category(f);
+}
diff --git a/usr.bin/localedef/monetary.c b/usr.bin/localedef/monetary.c
new file mode 100644
index 000000000000..7a77ac7e256c
--- /dev/null
+++ b/usr.bin/localedef/monetary.c
@@ -0,0 +1,209 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_MONETARY database generation routines for localedef.
+ */
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+#include "lmonetary.h"
+
+static struct lc_monetary_T mon;
+
+void
+init_monetary(void)
+{
+ (void) memset(&mon, 0, sizeof (mon));
+}
+
+void
+add_monetary_str(wchar_t *wcs)
+{
+ char *str;
+
+ if ((str = to_mb_string(wcs)) == NULL) {
+ INTERR;
+ return;
+ }
+ free(wcs);
+ switch (last_kw) {
+ case T_INT_CURR_SYMBOL:
+ mon.int_curr_symbol = str;
+ break;
+ case T_CURRENCY_SYMBOL:
+ mon.currency_symbol = str;
+ break;
+ case T_MON_DECIMAL_POINT:
+ mon.mon_decimal_point = str;
+ break;
+ case T_MON_THOUSANDS_SEP:
+ mon.mon_thousands_sep = str;
+ break;
+ case T_POSITIVE_SIGN:
+ mon.positive_sign = str;
+ break;
+ case T_NEGATIVE_SIGN:
+ mon.negative_sign = str;
+ break;
+ default:
+ free(str);
+ INTERR;
+ break;
+ }
+}
+
+void
+add_monetary_num(int n)
+{
+ char *str = NULL;
+
+ (void) asprintf(&str, "%d", n);
+ if (str == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return;
+ }
+
+ switch (last_kw) {
+ case T_INT_FRAC_DIGITS:
+ mon.int_frac_digits = str;
+ break;
+ case T_FRAC_DIGITS:
+ mon.frac_digits = str;
+ break;
+ case T_P_CS_PRECEDES:
+ mon.p_cs_precedes = str;
+ break;
+ case T_P_SEP_BY_SPACE:
+ mon.p_sep_by_space = str;
+ break;
+ case T_N_CS_PRECEDES:
+ mon.n_cs_precedes = str;
+ break;
+ case T_N_SEP_BY_SPACE:
+ mon.n_sep_by_space = str;
+ break;
+ case T_P_SIGN_POSN:
+ mon.p_sign_posn = str;
+ break;
+ case T_N_SIGN_POSN:
+ mon.n_sign_posn = str;
+ break;
+ case T_INT_P_CS_PRECEDES:
+ mon.int_p_cs_precedes = str;
+ break;
+ case T_INT_N_CS_PRECEDES:
+ mon.int_n_cs_precedes = str;
+ break;
+ case T_INT_P_SEP_BY_SPACE:
+ mon.int_p_sep_by_space = str;
+ break;
+ case T_INT_N_SEP_BY_SPACE:
+ mon.int_n_sep_by_space = str;
+ break;
+ case T_INT_P_SIGN_POSN:
+ mon.int_p_sign_posn = str;
+ break;
+ case T_INT_N_SIGN_POSN:
+ mon.int_n_sign_posn = str;
+ break;
+ case T_MON_GROUPING:
+ mon.mon_grouping = str;
+ break;
+ default:
+ INTERR;
+ break;
+ }
+}
+
+void
+reset_monetary_group(void)
+{
+ free((char *)mon.mon_grouping);
+ mon.mon_grouping = NULL;
+}
+
+void
+add_monetary_group(int n)
+{
+ char *s = NULL;
+
+ if (mon.mon_grouping == NULL) {
+ (void) asprintf(&s, "%d", n);
+ } else {
+ (void) asprintf(&s, "%s;%d", mon.mon_grouping, n);
+ }
+ if (s == NULL)
+ fprintf(stderr, "out of memory\n");
+
+ free((char *)mon.mon_grouping);
+ mon.mon_grouping = s;
+}
+
+void
+dump_monetary(void)
+{
+ FILE *f;
+
+ if ((f = open_category()) == NULL) {
+ return;
+ }
+
+ if ((putl_category(mon.int_curr_symbol, f) == EOF) ||
+ (putl_category(mon.currency_symbol, f) == EOF) ||
+ (putl_category(mon.mon_decimal_point, f) == EOF) ||
+ (putl_category(mon.mon_thousands_sep, f) == EOF) ||
+ (putl_category(mon.mon_grouping, f) == EOF) ||
+ (putl_category(mon.positive_sign, f) == EOF) ||
+ (putl_category(mon.negative_sign, f) == EOF) ||
+ (putl_category(mon.int_frac_digits, f) == EOF) ||
+ (putl_category(mon.frac_digits, f) == EOF) ||
+ (putl_category(mon.p_cs_precedes, f) == EOF) ||
+ (putl_category(mon.p_sep_by_space, f) == EOF) ||
+ (putl_category(mon.n_cs_precedes, f) == EOF) ||
+ (putl_category(mon.n_sep_by_space, f) == EOF) ||
+ (putl_category(mon.p_sign_posn, f) == EOF) ||
+ (putl_category(mon.n_sign_posn, f) == EOF) ||
+ (putl_category(mon.int_p_cs_precedes, f) == EOF) ||
+ (putl_category(mon.int_n_cs_precedes, f) == EOF) ||
+ (putl_category(mon.int_p_sep_by_space, f) == EOF) ||
+ (putl_category(mon.int_n_sep_by_space, f) == EOF) ||
+ (putl_category(mon.int_p_sign_posn, f) == EOF) ||
+ (putl_category(mon.int_n_sign_posn, f) == EOF)) {
+ return;
+ }
+ close_category(f);
+}
diff --git a/usr.bin/localedef/numeric.c b/usr.bin/localedef/numeric.c
new file mode 100644
index 000000000000..5533b7c10e1a
--- /dev/null
+++ b/usr.bin/localedef/numeric.c
@@ -0,0 +1,117 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_NUMERIC database generation routines for localedef.
+ */
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+#include "lnumeric.h"
+
+static struct lc_numeric_T numeric;
+
+void
+init_numeric(void)
+{
+ (void) memset(&numeric, 0, sizeof (numeric));
+}
+
+void
+add_numeric_str(wchar_t *wcs)
+{
+ char *str;
+
+ if ((str = to_mb_string(wcs)) == NULL) {
+ INTERR;
+ return;
+ }
+ free(wcs);
+
+ switch (last_kw) {
+ case T_DECIMAL_POINT:
+ numeric.decimal_point = str;
+ break;
+ case T_THOUSANDS_SEP:
+ numeric.thousands_sep = str;
+ break;
+ default:
+ free(str);
+ INTERR;
+ break;
+ }
+}
+
+void
+reset_numeric_group(void)
+{
+ free((char *)numeric.grouping);
+ numeric.grouping = NULL;
+}
+
+void
+add_numeric_group(int n)
+{
+ char *s;
+
+ if (numeric.grouping == NULL) {
+ (void) asprintf(&s, "%d", n);
+ } else {
+ (void) asprintf(&s, "%s;%d", numeric.grouping, n);
+ }
+ if (s == NULL)
+ fprintf(stderr, "out of memory\n");
+
+ free((char *)numeric.grouping);
+ numeric.grouping = s;
+}
+
+void
+dump_numeric(void)
+{
+ FILE *f;
+
+ if ((f = open_category()) == NULL) {
+ return;
+ }
+
+ if ((putl_category(numeric.decimal_point, f) == EOF) ||
+ (putl_category(numeric.thousands_sep, f) == EOF) ||
+ (putl_category(numeric.grouping, f) == EOF)) {
+ return;
+ }
+ close_category(f);
+}
diff --git a/usr.bin/localedef/parser.y b/usr.bin/localedef/parser.y
new file mode 100644
index 000000000000..23b3b54f8a6e
--- /dev/null
+++ b/usr.bin/localedef/parser.y
@@ -0,0 +1,703 @@
+%{
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * POSIX localedef grammar.
+ */
+
+#include <wchar.h>
+#include <stdio.h>
+#include <limits.h>
+#include "localedef.h"
+
+%}
+%union {
+ int num;
+ wchar_t wc;
+ char *token;
+ collsym_t *collsym;
+ collelem_t *collelem;
+}
+
+%token T_CODE_SET
+%token T_MB_CUR_MAX
+%token T_MB_CUR_MIN
+%token T_COM_CHAR
+%token T_ESC_CHAR
+%token T_LT
+%token T_GT
+%token T_NL
+%token T_SEMI
+%token T_COMMA
+%token T_ELLIPSIS
+%token T_RPAREN
+%token T_LPAREN
+%token T_QUOTE
+%token T_NULL
+%token T_WS
+%token T_END
+%token T_COPY
+%token T_CHARMAP
+%token T_WIDTH
+%token T_CTYPE
+%token T_ISUPPER
+%token T_ISLOWER
+%token T_ISALPHA
+%token T_ISDIGIT
+%token T_ISPUNCT
+%token T_ISXDIGIT
+%token T_ISSPACE
+%token T_ISPRINT
+%token T_ISGRAPH
+%token T_ISBLANK
+%token T_ISCNTRL
+%token T_ISALNUM
+%token T_ISSPECIAL
+%token T_ISPHONOGRAM
+%token T_ISIDEOGRAM
+%token T_ISENGLISH
+%token T_ISNUMBER
+%token T_TOUPPER
+%token T_TOLOWER
+%token T_COLLATE
+%token T_COLLATING_SYMBOL
+%token T_COLLATING_ELEMENT
+%token T_ORDER_START
+%token T_ORDER_END
+%token T_FORWARD
+%token T_BACKWARD
+%token T_POSITION
+%token T_FROM
+%token T_UNDEFINED
+%token T_IGNORE
+%token T_MESSAGES
+%token T_YESSTR
+%token T_NOSTR
+%token T_YESEXPR
+%token T_NOEXPR
+%token T_MONETARY
+%token T_INT_CURR_SYMBOL
+%token T_CURRENCY_SYMBOL
+%token T_MON_DECIMAL_POINT
+%token T_MON_THOUSANDS_SEP
+%token T_POSITIVE_SIGN
+%token T_NEGATIVE_SIGN
+%token T_MON_GROUPING
+%token T_INT_FRAC_DIGITS
+%token T_FRAC_DIGITS
+%token T_P_CS_PRECEDES
+%token T_P_SEP_BY_SPACE
+%token T_N_CS_PRECEDES
+%token T_N_SEP_BY_SPACE
+%token T_P_SIGN_POSN
+%token T_N_SIGN_POSN
+%token T_INT_P_CS_PRECEDES
+%token T_INT_N_CS_PRECEDES
+%token T_INT_P_SEP_BY_SPACE
+%token T_INT_N_SEP_BY_SPACE
+%token T_INT_P_SIGN_POSN
+%token T_INT_N_SIGN_POSN
+%token T_NUMERIC
+%token T_DECIMAL_POINT
+%token T_THOUSANDS_SEP
+%token T_GROUPING
+%token T_TIME
+%token T_ABDAY
+%token T_DAY
+%token T_ABMON
+%token T_MON
+%token T_ERA
+%token T_ERA_D_FMT
+%token T_ERA_T_FMT
+%token T_ERA_D_T_FMT
+%token T_ALT_DIGITS
+%token T_D_T_FMT
+%token T_D_FMT
+%token T_T_FMT
+%token T_AM_PM
+%token T_T_FMT_AMPM
+%token T_DATE_FMT
+%token <wc> T_CHAR
+%token <token> T_NAME
+%token <num> T_NUMBER
+%token <token> T_SYMBOL
+%token <collsym> T_COLLSYM
+%token <collelem> T_COLLELEM
+
+%%
+
+localedef : setting_list categories
+ | categories
+ ;
+
+string : T_QUOTE charlist T_QUOTE
+ | T_QUOTE T_QUOTE
+ ;
+
+charlist : charlist T_CHAR
+ {
+ add_wcs($2);
+ }
+ | T_CHAR
+ {
+ add_wcs($1);
+ }
+ ;
+
+setting_list : setting_list setting
+ | setting
+ ;
+
+
+setting : T_COM_CHAR T_CHAR T_NL
+ {
+ com_char = $2;
+ }
+ | T_ESC_CHAR T_CHAR T_NL
+ {
+ esc_char = $2;
+ }
+ | T_MB_CUR_MAX T_NUMBER T_NL
+ {
+ mb_cur_max = $2;
+ }
+ | T_MB_CUR_MIN T_NUMBER T_NL
+ {
+ mb_cur_min = $2;
+ }
+ | T_CODE_SET string T_NL
+ {
+ wchar_t *w = get_wcs();
+ set_wide_encoding(to_mb_string(w));
+ free(w);
+ }
+ | T_CODE_SET T_NAME T_NL
+ {
+ set_wide_encoding($2);
+ }
+ ;
+
+copycat : T_COPY T_NAME T_NL
+ {
+ copy_category($2);
+ }
+ | T_COPY string T_NL
+ {
+ wchar_t *w = get_wcs();
+ copy_category(to_mb_string(w));
+ free(w);
+ }
+ ;
+
+categories : categories category
+ | category
+ ;
+
+
+category : charmap
+ | messages
+ | monetary
+ | ctype
+ | collate
+ | numeric
+ | time
+ ;
+
+
+charmap : T_CHARMAP T_NL charmap_list T_END T_CHARMAP T_NL
+ | T_WIDTH T_NL width_list T_END T_WIDTH T_NL
+ ;
+
+
+charmap_list : charmap_list charmap_entry
+ | charmap_entry
+ ;
+
+
+charmap_entry : T_SYMBOL T_CHAR
+ {
+ add_charmap($1, $2);
+ scan_to_eol();
+ }
+ | T_SYMBOL T_ELLIPSIS T_SYMBOL T_CHAR
+ {
+ add_charmap_range($1, $3, $4);
+ scan_to_eol();
+ }
+ | T_NL
+ ;
+
+width_list : width_list width_entry
+ | width_entry
+ ;
+
+width_entry : T_CHAR T_NUMBER T_NL
+ {
+ add_width($1, $2);
+ }
+ | T_SYMBOL T_NUMBER T_NL
+ {
+ add_charmap_undefined($1);
+ }
+ | T_CHAR T_ELLIPSIS T_CHAR T_NUMBER T_NL
+ {
+ add_width_range($1, $3, $4);
+ }
+ | T_SYMBOL T_ELLIPSIS T_SYMBOL T_NUMBER T_NL
+ {
+ add_charmap_undefined($1);
+ add_charmap_undefined($3);
+ }
+ | T_CHAR T_ELLIPSIS T_SYMBOL T_NUMBER T_NL
+ {
+ add_width($1, $4);
+ add_charmap_undefined($3);
+ }
+ | T_SYMBOL T_ELLIPSIS T_CHAR T_NUMBER T_NL
+ {
+ add_width($3, $4);
+ add_charmap_undefined($1);
+ }
+ | T_NL
+ ;
+
+ctype : T_CTYPE T_NL ctype_list T_END T_CTYPE T_NL
+ {
+ dump_ctype();
+ }
+ | T_CTYPE T_NL copycat T_END T_CTYPE T_NL
+ ;
+
+ctype_list : ctype_list ctype_kw
+ | ctype_kw
+ ;
+
+ctype_kw : T_ISUPPER cc_list T_NL
+ | T_ISLOWER cc_list T_NL
+ | T_ISALPHA cc_list T_NL
+ | T_ISDIGIT cc_list T_NL
+ | T_ISPUNCT cc_list T_NL
+ | T_ISXDIGIT cc_list T_NL
+ | T_ISSPACE cc_list T_NL
+ | T_ISPRINT cc_list T_NL
+ | T_ISGRAPH cc_list T_NL
+ | T_ISBLANK cc_list T_NL
+ | T_ISCNTRL cc_list T_NL
+ | T_ISALNUM cc_list T_NL
+ | T_ISSPECIAL cc_list T_NL
+ | T_ISENGLISH cc_list T_NL
+ | T_ISNUMBER cc_list T_NL
+ | T_ISIDEOGRAM cc_list T_NL
+ | T_ISPHONOGRAM cc_list T_NL
+ | T_TOUPPER conv_list T_NL
+ | T_TOLOWER conv_list T_NL
+ ;
+
+cc_list : cc_list T_SEMI cc_range_end
+ | cc_list T_SEMI cc_char
+ | cc_char
+ ;
+
+cc_range_end : T_ELLIPSIS T_SEMI T_CHAR
+ {
+ add_ctype_range($3);
+ }
+ ;
+
+cc_char : T_CHAR
+ {
+ add_ctype($1);
+ }
+ | T_SYMBOL
+ {
+ add_charmap_undefined($1);
+ }
+ ;
+
+conv_list : conv_list T_SEMI conv_pair
+ | conv_pair
+ ;
+
+
+conv_pair : T_LPAREN T_CHAR T_COMMA T_CHAR T_RPAREN
+ {
+ add_caseconv($2, $4);
+ }
+ | T_LPAREN T_SYMBOL T_COMMA T_CHAR T_RPAREN
+ {
+ add_charmap_undefined($2);
+ }
+ | T_LPAREN T_SYMBOL T_COMMA T_SYMBOL T_RPAREN
+ {
+ add_charmap_undefined($2);
+ add_charmap_undefined($4);
+ }
+ | T_LPAREN T_CHAR T_COMMA T_SYMBOL T_RPAREN
+ {
+ add_charmap_undefined($4);
+ }
+ ;
+
+collate : T_COLLATE T_NL coll_order T_END T_COLLATE T_NL
+ {
+ dump_collate();
+ }
+ | T_COLLATE T_NL coll_optional coll_order T_END T_COLLATE T_NL
+ {
+ dump_collate();
+ }
+ | T_COLLATE T_NL copycat T_END T_COLLATE T_NL
+ ;
+
+
+coll_optional : coll_optional coll_symbols
+ | coll_optional coll_elements
+ | coll_symbols
+ | coll_elements
+ ;
+
+
+coll_symbols : T_COLLATING_SYMBOL T_SYMBOL T_NL
+ {
+ define_collsym($2);
+ }
+ ;
+
+
+coll_elements : T_COLLATING_ELEMENT T_SYMBOL T_FROM string T_NL
+ {
+ define_collelem($2, get_wcs());
+ }
+ ;
+
+coll_order : T_ORDER_START T_NL order_list T_ORDER_END T_NL
+ {
+ /* If no order list supplied default to one forward */
+ add_order_bit(T_FORWARD);
+ add_order_directive();
+ }
+ | T_ORDER_START order_args T_NL order_list T_ORDER_END T_NL
+ ;
+
+
+order_args : order_args T_SEMI order_arg
+ {
+ add_order_directive();
+ }
+ | order_arg
+ {
+ add_order_directive();
+ }
+ ;
+
+order_arg : order_arg T_COMMA order_dir
+ | order_dir
+ ;
+
+order_dir : T_FORWARD
+ {
+ add_order_bit(T_FORWARD);
+ }
+ | T_BACKWARD
+ {
+ add_order_bit(T_BACKWARD);
+ }
+ | T_POSITION
+ {
+ add_order_bit(T_POSITION);
+ }
+ ;
+
+order_list : order_list order_item
+ | order_item
+ ;
+
+order_item : T_COLLSYM T_NL
+ {
+ end_order_collsym($1);
+ }
+ | order_itemkw T_NL
+ {
+ end_order();
+ }
+ | order_itemkw order_weights T_NL
+ {
+ end_order();
+ }
+ ;
+
+order_itemkw : T_CHAR
+ {
+ start_order_char($1);
+ }
+ | T_ELLIPSIS
+ {
+ start_order_ellipsis();
+ }
+ | T_COLLELEM
+ {
+ start_order_collelem($1);
+ }
+ | T_UNDEFINED
+ {
+ start_order_undefined();
+ }
+ | T_SYMBOL
+ {
+ start_order_symbol($1);
+ }
+ ;
+
+order_weights : order_weights T_SEMI order_weight
+ | order_weights T_SEMI
+ | order_weight
+ ;
+
+order_weight : T_COLLELEM
+ {
+ add_order_collelem($1);
+ }
+ | T_COLLSYM
+ {
+ add_order_collsym($1);
+ }
+ | T_CHAR
+ {
+ add_order_char($1);
+ }
+ | T_ELLIPSIS
+ {
+ add_order_ellipsis();
+ }
+ | T_IGNORE
+ {
+ add_order_ignore();
+ }
+ | T_SYMBOL
+ {
+ add_order_symbol($1);
+ }
+ | T_QUOTE order_str T_QUOTE
+ {
+ add_order_subst();
+ }
+ ;
+
+order_str : order_str order_stritem
+ | order_stritem
+ ;
+
+order_stritem : T_CHAR
+ {
+ add_subst_char($1);
+ }
+ | T_COLLSYM
+ {
+ add_subst_collsym($1);
+ }
+ | T_COLLELEM
+ {
+ add_subst_collelem($1);
+ }
+ | T_SYMBOL
+ {
+ add_subst_symbol($1);
+ }
+ ;
+
+messages : T_MESSAGES T_NL messages_list T_END T_MESSAGES T_NL
+ {
+ dump_messages();
+ }
+ | T_MESSAGES T_NL copycat T_END T_MESSAGES T_NL
+ ;
+
+messages_list : messages_list messages_item
+ | messages_item
+ ;
+
+messages_kw : T_YESSTR
+ | T_NOSTR
+ | T_YESEXPR
+ | T_NOEXPR
+ ;
+
+messages_item : messages_kw string T_NL
+ {
+ add_message(get_wcs());
+ }
+ ;
+
+monetary : T_MONETARY T_NL monetary_list T_END T_MONETARY T_NL
+ {
+ dump_monetary();
+ }
+ | T_MONETARY T_NL copycat T_END T_MONETARY T_NL
+ ;
+
+monetary_list : monetary_list monetary_kw
+ | monetary_kw
+ ;
+
+monetary_strkw : T_INT_CURR_SYMBOL
+ | T_CURRENCY_SYMBOL
+ | T_MON_DECIMAL_POINT
+ | T_MON_THOUSANDS_SEP
+ | T_POSITIVE_SIGN
+ | T_NEGATIVE_SIGN
+ ;
+
+monetary_numkw : T_INT_FRAC_DIGITS
+ | T_FRAC_DIGITS
+ | T_P_CS_PRECEDES
+ | T_P_SEP_BY_SPACE
+ | T_N_CS_PRECEDES
+ | T_N_SEP_BY_SPACE
+ | T_P_SIGN_POSN
+ | T_N_SIGN_POSN
+ | T_INT_P_CS_PRECEDES
+ | T_INT_N_CS_PRECEDES
+ | T_INT_P_SEP_BY_SPACE
+ | T_INT_N_SEP_BY_SPACE
+ | T_INT_P_SIGN_POSN
+ | T_INT_N_SIGN_POSN
+ ;
+
+monetary_kw : monetary_strkw string T_NL
+ {
+ add_monetary_str(get_wcs());
+ }
+ | monetary_numkw T_NUMBER T_NL
+ {
+ add_monetary_num($2);
+ }
+ | T_MON_GROUPING mon_group_list T_NL
+ ;
+
+mon_group_list : T_NUMBER
+ {
+ reset_monetary_group();
+ add_monetary_group($1);
+ }
+ | mon_group_list T_SEMI T_NUMBER
+ {
+ add_monetary_group($3);
+ }
+ ;
+
+
+numeric : T_NUMERIC T_NL numeric_list T_END T_NUMERIC T_NL
+ {
+ dump_numeric();
+ }
+ | T_NUMERIC T_NL copycat T_END T_NUMERIC T_NL
+ ;
+
+
+numeric_list : numeric_list numeric_item
+ | numeric_item
+ ;
+
+
+numeric_item : numeric_strkw string T_NL
+ {
+ add_numeric_str(get_wcs());
+ }
+ | T_GROUPING group_list T_NL
+ ;
+
+numeric_strkw : T_DECIMAL_POINT
+ | T_THOUSANDS_SEP
+ ;
+
+
+group_list : T_NUMBER
+ {
+ reset_numeric_group();
+ add_numeric_group($1);
+ }
+ | group_list T_SEMI T_NUMBER
+ {
+ add_numeric_group($3);
+ }
+ ;
+
+
+time : T_TIME T_NL time_kwlist T_END T_TIME T_NL
+ {
+ dump_time();
+ }
+ | T_TIME T_NL copycat T_END T_NUMERIC T_NL
+ ;
+
+time_kwlist : time_kwlist time_kw
+ | time_kw
+ ;
+
+time_kw : time_strkw string T_NL
+ {
+ add_time_str(get_wcs());
+ }
+ | time_listkw time_list T_NL
+ {
+ check_time_list();
+ }
+ ;
+
+time_listkw : T_ABDAY
+ | T_DAY
+ | T_ABMON
+ | T_MON
+ | T_ERA
+ | T_ALT_DIGITS
+ | T_AM_PM
+ ;
+
+time_strkw : T_ERA_D_T_FMT
+ | T_ERA_T_FMT
+ | T_ERA_D_FMT
+ | T_D_T_FMT
+ | T_D_FMT
+ | T_T_FMT
+ | T_T_FMT_AMPM
+ | T_DATE_FMT
+ ;
+
+time_list : time_list T_SEMI string
+ {
+ add_time_list(get_wcs());
+ }
+ | string
+ {
+ reset_time_list();
+ add_time_list(get_wcs());
+ }
+ ;
diff --git a/usr.bin/localedef/scanner.c b/usr.bin/localedef/scanner.c
new file mode 100644
index 000000000000..c6d45a993f28
--- /dev/null
+++ b/usr.bin/localedef/scanner.c
@@ -0,0 +1,864 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file contains the "scanner", which tokenizes the input files
+ * for localedef for processing by the higher level grammar processor.
+ */
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <assert.h>
+#include "localedef.h"
+#include "parser.h"
+
+int com_char = '#';
+int esc_char = '\\';
+int mb_cur_min = 1;
+int mb_cur_max = 1;
+int lineno = 1;
+int warnings = 0;
+int is_stdin = 1;
+FILE *input;
+static int nextline;
+//static FILE *input = stdin;
+static const char *filename = "<stdin>";
+static int instring = 0;
+static int escaped = 0;
+
+/*
+ * Token space ... grows on demand.
+ */
+static char *token = NULL;
+static int tokidx;
+static int toksz = 0;
+static int hadtok = 0;
+
+/*
+ * Wide string space ... grows on demand.
+ */
+static wchar_t *widestr = NULL;
+static int wideidx = 0;
+static int widesz = 0;
+
+/*
+ * The last keyword seen. This is useful to trigger the special lexer rules
+ * for "copy" and also collating symbols and elements.
+ */
+int last_kw = 0;
+static int category = T_END;
+
+static struct token {
+ int id;
+ const char *name;
+} keywords[] = {
+ { T_COM_CHAR, "comment_char" },
+ { T_ESC_CHAR, "escape_char" },
+ { T_END, "END" },
+ { T_COPY, "copy" },
+ { T_MESSAGES, "LC_MESSAGES" },
+ { T_YESSTR, "yesstr" },
+ { T_YESEXPR, "yesexpr" },
+ { T_NOSTR, "nostr" },
+ { T_NOEXPR, "noexpr" },
+ { T_MONETARY, "LC_MONETARY" },
+ { T_INT_CURR_SYMBOL, "int_curr_symbol" },
+ { T_CURRENCY_SYMBOL, "currency_symbol" },
+ { T_MON_DECIMAL_POINT, "mon_decimal_point" },
+ { T_MON_THOUSANDS_SEP, "mon_thousands_sep" },
+ { T_POSITIVE_SIGN, "positive_sign" },
+ { T_NEGATIVE_SIGN, "negative_sign" },
+ { T_MON_GROUPING, "mon_grouping" },
+ { T_INT_FRAC_DIGITS, "int_frac_digits" },
+ { T_FRAC_DIGITS, "frac_digits" },
+ { T_P_CS_PRECEDES, "p_cs_precedes" },
+ { T_P_SEP_BY_SPACE, "p_sep_by_space" },
+ { T_N_CS_PRECEDES, "n_cs_precedes" },
+ { T_N_SEP_BY_SPACE, "n_sep_by_space" },
+ { T_P_SIGN_POSN, "p_sign_posn" },
+ { T_N_SIGN_POSN, "n_sign_posn" },
+ { T_INT_P_CS_PRECEDES, "int_p_cs_precedes" },
+ { T_INT_N_CS_PRECEDES, "int_n_cs_precedes" },
+ { T_INT_P_SEP_BY_SPACE, "int_p_sep_by_space" },
+ { T_INT_N_SEP_BY_SPACE, "int_n_sep_by_space" },
+ { T_INT_P_SIGN_POSN, "int_p_sign_posn" },
+ { T_INT_N_SIGN_POSN, "int_n_sign_posn" },
+ { T_COLLATE, "LC_COLLATE" },
+ { T_COLLATING_SYMBOL, "collating-symbol" },
+ { T_COLLATING_ELEMENT, "collating-element" },
+ { T_FROM, "from" },
+ { T_ORDER_START, "order_start" },
+ { T_ORDER_END, "order_end" },
+ { T_FORWARD, "forward" },
+ { T_BACKWARD, "backward" },
+ { T_POSITION, "position" },
+ { T_IGNORE, "IGNORE" },
+ { T_UNDEFINED, "UNDEFINED" },
+ { T_NUMERIC, "LC_NUMERIC" },
+ { T_DECIMAL_POINT, "decimal_point" },
+ { T_THOUSANDS_SEP, "thousands_sep" },
+ { T_GROUPING, "grouping" },
+ { T_TIME, "LC_TIME" },
+ { T_ABDAY, "abday" },
+ { T_DAY, "day" },
+ { T_ABMON, "abmon" },
+ { T_MON, "mon" },
+ { T_D_T_FMT, "d_t_fmt" },
+ { T_D_FMT, "d_fmt" },
+ { T_T_FMT, "t_fmt" },
+ { T_AM_PM, "am_pm" },
+ { T_T_FMT_AMPM, "t_fmt_ampm" },
+ { T_ERA, "era" },
+ { T_ERA_D_FMT, "era_d_fmt" },
+ { T_ERA_T_FMT, "era_t_fmt" },
+ { T_ERA_D_T_FMT, "era_d_t_fmt" },
+ { T_ALT_DIGITS, "alt_digits" },
+ { T_CTYPE, "LC_CTYPE" },
+ { T_ISUPPER, "upper" },
+ { T_ISLOWER, "lower" },
+ { T_ISALPHA, "alpha" },
+ { T_ISDIGIT, "digit" },
+ { T_ISPUNCT, "punct" },
+ { T_ISXDIGIT, "xdigit" },
+ { T_ISSPACE, "space" },
+ { T_ISPRINT, "print" },
+ { T_ISGRAPH, "graph" },
+ { T_ISBLANK, "blank" },
+ { T_ISCNTRL, "cntrl" },
+ /*
+ * These entries are local additions, and not specified by
+ * TOG. Note that they are not guaranteed to be accurate for
+ * all locales, and so applications should not depend on them.
+ */
+ { T_ISSPECIAL, "special" },
+ { T_ISENGLISH, "english" },
+ { T_ISPHONOGRAM, "phonogram" },
+ { T_ISIDEOGRAM, "ideogram" },
+ { T_ISNUMBER, "number" },
+ /*
+ * We have to support this in the grammar, but it would be a
+ * syntax error to define a character as one of these without
+ * also defining it as an alpha or digit. We ignore it in our
+ * parsing.
+ */
+ { T_ISALNUM, "alnum" },
+ { T_TOUPPER, "toupper" },
+ { T_TOLOWER, "tolower" },
+
+ /*
+ * These are keywords used in the charmap file. Note that
+ * Solaris originally used angle brackets to wrap some of them,
+ * but we removed that to simplify our parser. The first of these
+ * items are "global items."
+ */
+ { T_CHARMAP, "CHARMAP" },
+ { T_WIDTH, "WIDTH" },
+
+ { -1, NULL },
+};
+
+/*
+ * These special words are only used in a charmap file, enclosed in <>.
+ */
+static struct token symwords[] = {
+ { T_COM_CHAR, "comment_char" },
+ { T_ESC_CHAR, "escape_char" },
+ { T_CODE_SET, "code_set_name" },
+ { T_MB_CUR_MAX, "mb_cur_max" },
+ { T_MB_CUR_MIN, "mb_cur_min" },
+ { -1, NULL },
+};
+
+static int categories[] = {
+ T_CHARMAP,
+ T_CTYPE,
+ T_COLLATE,
+ T_MESSAGES,
+ T_MONETARY,
+ T_NUMERIC,
+ T_TIME,
+ T_WIDTH,
+ 0
+};
+
+void
+reset_scanner(const char *fname)
+{
+ if (fname == NULL) {
+ filename = "<stdin>";
+ is_stdin = 1;
+ } else {
+ if (!is_stdin)
+ (void) fclose(input);
+ if ((input = fopen(fname, "r")) == NULL) {
+ perror("fopen");
+ exit(4);
+ } else {
+ is_stdin = 0;
+ }
+ filename = fname;
+ }
+ com_char = '#';
+ esc_char = '\\';
+ instring = 0;
+ escaped = 0;
+ lineno = 1;
+ nextline = 1;
+ tokidx = 0;
+ wideidx = 0;
+}
+
+#define hex(x) \
+ (isdigit(x) ? (x - '0') : ((islower(x) ? (x - 'a') : (x - 'A')) + 10))
+#define isodigit(x) ((x >= '0') && (x <= '7'))
+
+static int
+scanc(void)
+{
+ int c;
+
+ if (is_stdin)
+ c = getc(stdin);
+ else
+ c = getc(input);
+ lineno = nextline;
+ if (c == '\n') {
+ nextline++;
+ }
+ return (c);
+}
+
+static void
+unscanc(int c)
+{
+ if (c == '\n') {
+ nextline--;
+ }
+ if (ungetc(c, is_stdin ? stdin : input) < 0) {
+ yyerror("ungetc failed");
+ }
+}
+
+static int
+scan_hex_byte(void)
+{
+ int c1, c2;
+ int v;
+
+ c1 = scanc();
+ if (!isxdigit(c1)) {
+ yyerror("malformed hex digit");
+ return (0);
+ }
+ c2 = scanc();
+ if (!isxdigit(c2)) {
+ yyerror("malformed hex digit");
+ return (0);
+ }
+ v = ((hex(c1) << 4) | hex(c2));
+ return (v);
+}
+
+static int
+scan_dec_byte(void)
+{
+ int c1, c2, c3;
+ int b;
+
+ c1 = scanc();
+ if (!isdigit(c1)) {
+ yyerror("malformed decimal digit");
+ return (0);
+ }
+ b = c1 - '0';
+ c2 = scanc();
+ if (!isdigit(c2)) {
+ yyerror("malformed decimal digit");
+ return (0);
+ }
+ b *= 10;
+ b += (c2 - '0');
+ c3 = scanc();
+ if (!isdigit(c3)) {
+ unscanc(c3);
+ } else {
+ b *= 10;
+ b += (c3 - '0');
+ }
+ return (b);
+}
+
+static int
+scan_oct_byte(void)
+{
+ int c1, c2, c3;
+ int b;
+
+ b = 0;
+
+ c1 = scanc();
+ if (!isodigit(c1)) {
+ yyerror("malformed octal digit");
+ return (0);
+ }
+ b = c1 - '0';
+ c2 = scanc();
+ if (!isodigit(c2)) {
+ yyerror("malformed octal digit");
+ return (0);
+ }
+ b *= 8;
+ b += (c2 - '0');
+ c3 = scanc();
+ if (!isodigit(c3)) {
+ unscanc(c3);
+ } else {
+ b *= 8;
+ b += (c3 - '0');
+ }
+ return (b);
+}
+
+void
+add_tok(int c)
+{
+ if ((tokidx + 1) >= toksz) {
+ toksz += 64;
+ if ((token = realloc(token, toksz)) == NULL) {
+ yyerror("out of memory");
+ tokidx = 0;
+ toksz = 0;
+ return;
+ }
+ }
+
+ token[tokidx++] = (char)c;
+ token[tokidx] = 0;
+}
+void
+add_wcs(wchar_t c)
+{
+ if ((wideidx + 1) >= widesz) {
+ widesz += 64;
+ widestr = realloc(widestr, (widesz * sizeof (wchar_t)));
+ if (widestr == NULL) {
+ yyerror("out of memory");
+ wideidx = 0;
+ widesz = 0;
+ return;
+ }
+ }
+
+ widestr[wideidx++] = c;
+ widestr[wideidx] = 0;
+}
+
+wchar_t *
+get_wcs(void)
+{
+ wchar_t *ws = widestr;
+ wideidx = 0;
+ widestr = NULL;
+ widesz = 0;
+ if (ws == NULL) {
+ if ((ws = wcsdup(L"")) == NULL) {
+ yyerror("out of memory");
+ }
+ }
+ return (ws);
+}
+
+static int
+get_byte(void)
+{
+ int c;
+
+ if ((c = scanc()) != esc_char) {
+ unscanc(c);
+ return (EOF);
+ }
+ c = scanc();
+
+ switch (c) {
+ case 'd':
+ case 'D':
+ return (scan_dec_byte());
+ case 'x':
+ case 'X':
+ return (scan_hex_byte());
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ /* put the character back so we can get it */
+ unscanc(c);
+ return (scan_oct_byte());
+ default:
+ unscanc(c);
+ unscanc(esc_char);
+ return (EOF);
+ }
+}
+
+int
+get_escaped(int c)
+{
+ switch (c) {
+ case 'n':
+ return ('\n');
+ case 'r':
+ return ('\r');
+ case 't':
+ return ('\t');
+ case 'f':
+ return ('\f');
+ case 'v':
+ return ('\v');
+ case 'b':
+ return ('\b');
+ case 'a':
+ return ('\a');
+ default:
+ return (c);
+ }
+}
+
+int
+get_wide(void)
+{
+ static char mbs[MB_LEN_MAX + 1] = "";
+ static int mbi = 0;
+ int c;
+ wchar_t wc;
+
+ if (mb_cur_max >= (int)sizeof (mbs)) {
+ yyerror("max multibyte character size too big");
+ mbi = 0;
+ return (T_NULL);
+ }
+ for (;;) {
+ if ((mbi == mb_cur_max) || ((c = get_byte()) == EOF)) {
+ /*
+ * end of the byte sequence reached, but no
+ * valid wide decoding. fatal error.
+ */
+ mbi = 0;
+ yyerror("not a valid character encoding");
+ return (T_NULL);
+ }
+ mbs[mbi++] = c;
+ mbs[mbi] = 0;
+
+ /* does it decode? */
+ if (to_wide(&wc, mbs) >= 0) {
+ break;
+ }
+ }
+
+ mbi = 0;
+ if ((category != T_CHARMAP) && (category != T_WIDTH)) {
+ if (check_charmap(wc) < 0) {
+ yyerror("no symbolic name for character");
+ return (T_NULL);
+ }
+ }
+
+ yylval.wc = wc;
+ return (T_CHAR);
+}
+
+int
+get_symbol(void)
+{
+ int c;
+
+ while ((c = scanc()) != EOF) {
+ if (escaped) {
+ escaped = 0;
+ if (c == '\n')
+ continue;
+ add_tok(get_escaped(c));
+ continue;
+ }
+ if (c == esc_char) {
+ escaped = 1;
+ continue;
+ }
+ if (c == '\n') { /* well that's strange! */
+ yyerror("unterminated symbolic name");
+ continue;
+ }
+ if (c == '>') { /* end of symbol */
+
+ /*
+ * This restarts the token from the beginning
+ * the next time we scan a character. (This
+ * token is complete.)
+ */
+
+ if (token == NULL) {
+ yyerror("missing symbolic name");
+ return (T_NULL);
+ }
+ tokidx = 0;
+
+ /*
+ * A few symbols are handled as keywords outside
+ * of the normal categories.
+ */
+ if (category == T_END) {
+ int i;
+ for (i = 0; symwords[i].name != 0; i++) {
+ if (strcmp(token, symwords[i].name) ==
+ 0) {
+ last_kw = symwords[i].id;
+ return (last_kw);
+ }
+ }
+ }
+ /*
+ * Contextual rule: Only literal characters are
+ * permitted in CHARMAP. Anywhere else the symbolic
+ * forms are fine.
+ */
+ if ((category != T_CHARMAP) &&
+ (lookup_charmap(token, &yylval.wc)) != -1) {
+ return (T_CHAR);
+ }
+ if ((yylval.collsym = lookup_collsym(token)) != NULL) {
+ return (T_COLLSYM);
+ }
+ if ((yylval.collelem = lookup_collelem(token)) !=
+ NULL) {
+ return (T_COLLELEM);
+ }
+ /* its an undefined symbol */
+ yylval.token = strdup(token);
+ token = NULL;
+ toksz = 0;
+ tokidx = 0;
+ return (T_SYMBOL);
+ }
+ add_tok(c);
+ }
+
+ yyerror("unterminated symbolic name");
+ return (EOF);
+}
+
+int
+get_category(void)
+{
+ return (category);
+}
+
+static int
+consume_token(void)
+{
+ int len = tokidx;
+ int i;
+
+ tokidx = 0;
+ if (token == NULL)
+ return (T_NULL);
+
+ /*
+ * this one is special, because we don't want it to alter the
+ * last_kw field.
+ */
+ if (strcmp(token, "...") == 0) {
+ return (T_ELLIPSIS);
+ }
+
+ /* search for reserved words first */
+ for (i = 0; keywords[i].name; i++) {
+ int j;
+ if (strcmp(keywords[i].name, token) != 0) {
+ continue;
+ }
+
+ last_kw = keywords[i].id;
+
+ /* clear the top level category if we're done with it */
+ if (last_kw == T_END) {
+ category = T_END;
+ }
+
+ /* set the top level category if we're changing */
+ for (j = 0; categories[j]; j++) {
+ if (categories[j] != last_kw)
+ continue;
+ category = last_kw;
+ }
+
+ return (keywords[i].id);
+ }
+
+ /* maybe its a numeric constant? */
+ if (isdigit(*token) || (*token == '-' && isdigit(token[1]))) {
+ char *eptr;
+ yylval.num = strtol(token, &eptr, 10);
+ if (*eptr != 0)
+ yyerror("malformed number");
+ return (T_NUMBER);
+ }
+
+ /*
+ * A single lone character is treated as a character literal.
+ * To avoid duplication of effort, we stick in the charmap.
+ */
+ if (len == 1) {
+ yylval.wc = token[0];
+ return (T_CHAR);
+ }
+
+ /* anything else is treated as a symbolic name */
+ yylval.token = strdup(token);
+ token = NULL;
+ toksz = 0;
+ tokidx = 0;
+ return (T_NAME);
+}
+
+void
+scan_to_eol(void)
+{
+ int c;
+ while ((c = scanc()) != '\n') {
+ if (c == EOF) {
+ /* end of file without newline! */
+ errf("missing newline");
+ return;
+ }
+ }
+ assert(c == '\n');
+}
+
+int
+yylex(void)
+{
+ int c;
+
+ while ((c = scanc()) != EOF) {
+
+ /* special handling for quoted string */
+ if (instring) {
+ if (escaped) {
+ escaped = 0;
+
+ /* if newline, just eat and forget it */
+ if (c == '\n')
+ continue;
+
+ if (strchr("xXd01234567", c)) {
+ unscanc(c);
+ unscanc(esc_char);
+ return (get_wide());
+ }
+ yylval.wc = get_escaped(c);
+ return (T_CHAR);
+ }
+ if (c == esc_char) {
+ escaped = 1;
+ continue;
+ }
+ switch (c) {
+ case '<':
+ return (get_symbol());
+ case '>':
+ /* oops! should generate syntax error */
+ return (T_GT);
+ case '"':
+ instring = 0;
+ return (T_QUOTE);
+ default:
+ yylval.wc = c;
+ return (T_CHAR);
+ }
+ }
+
+ /* escaped characters first */
+ if (escaped) {
+ escaped = 0;
+ if (c == '\n') {
+ /* eat the newline */
+ continue;
+ }
+ hadtok = 1;
+ if (tokidx) {
+ /* an escape mid-token is nonsense */
+ return (T_NULL);
+ }
+
+ /* numeric escapes are treated as wide characters */
+ if (strchr("xXd01234567", c)) {
+ unscanc(c);
+ unscanc(esc_char);
+ return (get_wide());
+ }
+
+ add_tok(get_escaped(c));
+ continue;
+ }
+
+ /* if it is the escape charter itself note it */
+ if (c == esc_char) {
+ escaped = 1;
+ continue;
+ }
+
+ /* remove from the comment char to end of line */
+ if (c == com_char) {
+ while (c != '\n') {
+ if ((c = scanc()) == EOF) {
+ /* end of file without newline! */
+ return (EOF);
+ }
+ }
+ assert(c == '\n');
+ if (!hadtok) {
+ /*
+ * If there were no tokens on this line,
+ * then just pretend it didn't exist at all.
+ */
+ continue;
+ }
+ hadtok = 0;
+ return (T_NL);
+ }
+
+ if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) {
+ /*
+ * These are all token delimiters. If there
+ * is a token already in progress, we need to
+ * process it.
+ */
+ unscanc(c);
+ return (consume_token());
+ }
+
+ switch (c) {
+ case '\n':
+ if (!hadtok) {
+ /*
+ * If the line was completely devoid of tokens,
+ * then just ignore it.
+ */
+ continue;
+ }
+ /* we're starting a new line, reset the token state */
+ hadtok = 0;
+ return (T_NL);
+ case ',':
+ hadtok = 1;
+ return (T_COMMA);
+ case ';':
+ hadtok = 1;
+ return (T_SEMI);
+ case '(':
+ hadtok = 1;
+ return (T_LPAREN);
+ case ')':
+ hadtok = 1;
+ return (T_RPAREN);
+ case '>':
+ hadtok = 1;
+ return (T_GT);
+ case '<':
+ /* symbol start! */
+ hadtok = 1;
+ return (get_symbol());
+ case ' ':
+ case '\t':
+ /* whitespace, just ignore it */
+ continue;
+ case '"':
+ hadtok = 1;
+ instring = 1;
+ return (T_QUOTE);
+ default:
+ hadtok = 1;
+ add_tok(c);
+ continue;
+ }
+ }
+ return (EOF);
+}
+
+void
+yyerror(const char *msg)
+{
+ (void) fprintf(stderr, "%s: %d: error: %s\n",
+ filename, lineno, msg);
+ exit(4);
+}
+
+void
+errf(const char *fmt, ...)
+{
+ char *msg;
+
+ va_list va;
+ va_start(va, fmt);
+ (void) vasprintf(&msg, fmt, va);
+ va_end(va);
+
+ (void) fprintf(stderr, "%s: %d: error: %s\n",
+ filename, lineno, msg);
+ free(msg);
+ exit(4);
+}
+
+void
+warn(const char *fmt, ...)
+{
+ char *msg;
+
+ va_list va;
+ va_start(va, fmt);
+ (void) vasprintf(&msg, fmt, va);
+ va_end(va);
+
+ (void) fprintf(stderr, "%s: %d: warning: %s\n",
+ filename, lineno, msg);
+ free(msg);
+ warnings++;
+ if (!warnok)
+ exit(4);
+}
diff --git a/usr.bin/localedef/time.c b/usr.bin/localedef/time.c
new file mode 100644
index 000000000000..7a56e244c921
--- /dev/null
+++ b/usr.bin/localedef/time.c
@@ -0,0 +1,275 @@
+/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * LC_TIME database generation routines for localedef.
+ */
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include "localedef.h"
+#include "parser.h"
+#include "timelocal.h"
+
+struct lc_time_T tm;
+
+void
+init_time(void)
+{
+ (void) memset(&tm, 0, sizeof (tm));
+}
+
+void
+add_time_str(wchar_t *wcs)
+{
+ char *str;
+
+ if ((str = to_mb_string(wcs)) == NULL) {
+ INTERR;
+ return;
+ }
+ free(wcs);
+
+ switch (last_kw) {
+ case T_D_T_FMT:
+ tm.c_fmt = str;
+ break;
+ case T_D_FMT:
+ tm.x_fmt = str;
+ break;
+ case T_T_FMT:
+ tm.X_fmt = str;
+ break;
+ case T_T_FMT_AMPM:
+ tm.ampm_fmt = str;
+ break;
+ case T_DATE_FMT:
+ /*
+ * This one is a Solaris extension, Too bad date just
+ * doesn't use %c, which would be simpler.
+ */
+ tm.date_fmt = str;
+ break;
+ case T_ERA_D_FMT:
+ case T_ERA_T_FMT:
+ case T_ERA_D_T_FMT:
+ /* Silently ignore it. */
+ free(str);
+ break;
+ default:
+ free(str);
+ INTERR;
+ break;
+ }
+}
+
+static void
+add_list(const char *ptr[], char *str, int limit)
+{
+ int i;
+ for (i = 0; i < limit; i++) {
+ if (ptr[i] == NULL) {
+ ptr[i] = str;
+ return;
+ }
+ }
+ fprintf(stderr,"too many list elements\n");
+}
+
+void
+add_time_list(wchar_t *wcs)
+{
+ char *str;
+
+ if ((str = to_mb_string(wcs)) == NULL) {
+ INTERR;
+ return;
+ }
+ free(wcs);
+
+ switch (last_kw) {
+ case T_ABMON:
+ add_list(tm.mon, str, 12);
+ break;
+ case T_MON:
+ add_list(tm.month, str, 12);
+ break;
+ case T_ABDAY:
+ add_list(tm.wday, str, 7);
+ break;
+ case T_DAY:
+ add_list(tm.weekday, str, 7);
+ break;
+ case T_AM_PM:
+ if (tm.am == NULL) {
+ tm.am = str;
+ } else if (tm.pm == NULL) {
+ tm.pm = str;
+ } else {
+ fprintf(stderr,"too many list elements\n");
+ free(str);
+ }
+ break;
+ case T_ALT_DIGITS:
+ case T_ERA:
+ free(str);
+ break;
+ default:
+ free(str);
+ INTERR;
+ break;
+ }
+}
+
+void
+check_time_list(void)
+{
+ switch (last_kw) {
+ case T_ABMON:
+ if (tm.mon[11] != NULL)
+ return;
+ break;
+ case T_MON:
+ if (tm.month[11] != NULL)
+ return;
+ break;
+ case T_ABDAY:
+ if (tm.wday[6] != NULL)
+ return;
+ break;
+ case T_DAY:
+ if (tm.weekday[6] != NULL)
+ return;
+ break;
+ case T_AM_PM:
+ if (tm.pm != NULL)
+ return;
+ break;
+ case T_ERA:
+ case T_ALT_DIGITS:
+ return;
+ default:
+ fprintf(stderr,"unknown list\n");
+ break;
+ }
+
+ fprintf(stderr,"too few items in list (%d)\n", last_kw);
+}
+
+void
+reset_time_list(void)
+{
+ int i;
+ switch (last_kw) {
+ case T_ABMON:
+ for (i = 0; i < 12; i++) {
+ free((char *)tm.mon[i]);
+ tm.mon[i] = NULL;
+ }
+ break;
+ case T_MON:
+ for (i = 0; i < 12; i++) {
+ free((char *)tm.month[i]);
+ tm.month[i] = NULL;
+ }
+ break;
+ case T_ABDAY:
+ for (i = 0; i < 7; i++) {
+ free((char *)tm.wday[i]);
+ tm.wday[i] = NULL;
+ }
+ break;
+ case T_DAY:
+ for (i = 0; i < 7; i++) {
+ free((char *)tm.weekday[i]);
+ tm.weekday[i] = NULL;
+ }
+ break;
+ case T_AM_PM:
+ free((char *)tm.am);
+ tm.am = NULL;
+ free((char *)tm.pm);
+ tm.pm = NULL;
+ break;
+ }
+}
+
+void
+dump_time(void)
+{
+ FILE *f;
+ int i;
+
+ if ((f = open_category()) == NULL) {
+ return;
+ }
+
+ for (i = 0; i < 12; i++) {
+ if (putl_category(tm.mon[i], f) == EOF) {
+ return;
+ }
+ }
+ for (i = 0; i < 12; i++) {
+ if (putl_category(tm.month[i], f) == EOF) {
+ return;
+ }
+ }
+ for (i = 0; i < 7; i++) {
+ if (putl_category(tm.wday[i], f) == EOF) {
+ return;
+ }
+ }
+ for (i = 0; i < 7; i++) {
+ if (putl_category(tm.weekday[i], f) == EOF) {
+ return;
+ }
+ }
+
+ /*
+ * NOTE: If date_fmt is not specified, then we'll default to
+ * using the %c for date. This is reasonable for most
+ * locales, although for reasons that I don't understand
+ * Solaris historically has had a separate format for date.
+ */
+ if ((putl_category(tm.X_fmt, f) == EOF) ||
+ (putl_category(tm.x_fmt, f) == EOF) ||
+ (putl_category(tm.c_fmt, f) == EOF) ||
+ (putl_category(tm.am, f) == EOF) ||
+ (putl_category(tm.pm, f) == EOF) ||
+ (putl_category(tm.date_fmt ? tm.date_fmt : tm.c_fmt, f) == EOF) ||
+ (putl_category(tm.ampm_fmt, f) == EOF)) {
+ return;
+ }
+ close_category(f);
+}
diff --git a/usr.bin/localedef/wide.c b/usr.bin/localedef/wide.c
new file mode 100644
index 000000000000..062e120e6912
--- /dev/null
+++ b/usr.bin/localedef/wide.c
@@ -0,0 +1,664 @@
+/*-
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Garrett D'Amore <garrett@damore.org> All rights reserved.
+ * Copyright 2015 John Marino <draco@marino.st>
+ *
+ * This source code is derived from the illumos localedef command, and
+ * provided under BSD-style license terms by Nexenta Systems, 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.
+ *
+ * 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.
+ */
+
+/*
+ * The functions in this file convert from the standard multibyte forms
+ * to the wide character forms used internally by libc. Unfortunately,
+ * this approach means that we need a method for each and every encoding.
+ */
+#include <sys/cdefs.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <sys/types.h>
+#include "localedef.h"
+
+static int towide_none(wchar_t *, const char *, unsigned);
+static int towide_utf8(wchar_t *, const char *, unsigned);
+static int towide_big5(wchar_t *, const char *, unsigned);
+static int towide_gbk(wchar_t *, const char *, unsigned);
+static int towide_gb2312(wchar_t *, const char *, unsigned);
+static int towide_gb18030(wchar_t *, const char *, unsigned);
+static int towide_mskanji(wchar_t *, const char *, unsigned);
+static int towide_euccn(wchar_t *, const char *, unsigned);
+static int towide_eucjp(wchar_t *, const char *, unsigned);
+static int towide_euckr(wchar_t *, const char *, unsigned);
+static int towide_euctw(wchar_t *, const char *, unsigned);
+
+static int tomb_none(char *, wchar_t);
+static int tomb_utf8(char *, wchar_t);
+static int tomb_mbs(char *, wchar_t);
+
+static int (*_towide)(wchar_t *, const char *, unsigned) = towide_none;
+static int (*_tomb)(char *, wchar_t) = tomb_none;
+static char _encoding_buffer[20] = {'N','O','N','E'};
+static const char *_encoding = _encoding_buffer;
+static int _nbits = 7;
+
+/*
+ * Table of supported encodings. We only bother to list the multibyte
+ * encodings here, because single byte locales are handed by "NONE".
+ */
+static struct {
+ const char *name;
+ /* the name that the underlying libc implemenation uses */
+ const char *cname;
+ /* the maximum number of bits required for priorities */
+ int nbits;
+ int (*towide)(wchar_t *, const char *, unsigned);
+ int (*tomb)(char *, wchar_t);
+} mb_encodings[] = {
+ /*
+ * UTF8 values max out at 0x1fffff (although in theory there could
+ * be later extensions, but it won't happen.) This means we only need
+ * 21 bits to be able to encode the entire range of priorities.
+ */
+ { "UTF-8", "UTF-8", 21, towide_utf8, tomb_utf8 },
+ { "UTF8", "UTF-8", 21, towide_utf8, tomb_utf8 },
+ { "utf8", "UTF-8", 21, towide_utf8, tomb_utf8 },
+ { "utf-8", "UTF-8", 21, towide_utf8, tomb_utf8 },
+
+ { "EUC-CN", "EUC-CN", 16, towide_euccn, tomb_mbs },
+ { "eucCN", "EUC-CN", 16, towide_euccn, tomb_mbs },
+ /*
+ * Because the 3-byte form of EUC-JP use the same leading byte,
+ * only 17 bits required to provide unique priorities. (The low
+ * bit of that first byte is set.) By setting this value low,
+ * we can get by with only 3 bytes in the strxfrm expansion.
+ */
+ { "EUC-JP", "EUC-JP", 17, towide_eucjp, tomb_mbs },
+ { "eucJP", "EUC-JP", 17, towide_eucjp, tomb_mbs },
+
+ { "EUC-KR", "EUC-KR", 16, towide_euckr, tomb_mbs },
+ { "eucKR", "EUC-KR", 16, towide_euckr, tomb_mbs },
+ /*
+ * EUC-TW uses 2 bytes most of the time, but 4 bytes if the
+ * high order byte is 0x8E. However, with 4 byte encodings,
+ * the third byte will be A0-B0. So we only need to consider
+ * the lower order 24 bits for collation.
+ */
+ { "EUC-TW", "EUC-TW", 24, towide_euctw, tomb_mbs },
+ { "eucTW", "EUC-TW", 24, towide_euctw, tomb_mbs },
+
+ { "MS_Kanji", "MSKanji", 16, towide_mskanji, tomb_mbs },
+ { "MSKanji", "MSKanji", 16, towide_mskanji, tomb_mbs },
+ { "PCK", "MSKanji", 16, towide_mskanji, tomb_mbs },
+ { "SJIS", "MSKanji", 16, towide_mskanji, tomb_mbs },
+ { "Shift_JIS", "MSKanji", 16, towide_mskanji, tomb_mbs },
+
+ { "BIG5", "BIG5", 16, towide_big5, tomb_mbs },
+ { "big5", "BIG5", 16, towide_big5, tomb_mbs },
+ { "Big5", "BIG5", 16, towide_big5, tomb_mbs },
+
+ { "GBK", "GBK", 16, towide_gbk, tomb_mbs },
+
+ /*
+ * GB18030 can get away with just 31 bits. This is because the
+ * high order bit is always set for 4 byte values, and the
+ * at least one of the other bits in that 4 byte value will
+ * be non-zero.
+ */
+ { "GB18030", "GB18030", 31, towide_gb18030, tomb_mbs },
+
+ /*
+ * This should probably be an aliase for euc-cn, or vice versa.
+ */
+ { "GB2312", "GB2312", 16, towide_gb2312, tomb_mbs },
+
+ { NULL, NULL, 0, 0, 0 },
+};
+
+static char *
+show_mb(const char *mb)
+{
+ static char buf[64];
+
+ /* ASCII stuff we just print */
+ if (isascii(*mb) && isgraph(*mb)) {
+ buf[0] = *mb;
+ buf[1] = 0;
+ return (buf);
+ }
+ buf[0] = 0;
+ while (*mb != 0) {
+ char scr[8];
+ (void) snprintf(scr, sizeof (scr), "\\x%02x", *mb);
+ (void) strlcat(buf, scr, sizeof (buf));
+ mb++;
+ }
+ return (buf);
+}
+
+static char *widemsg;
+
+void
+werr(const char *fmt, ...)
+{
+ char *msg;
+
+ va_list va;
+ va_start(va, fmt);
+ (void) vasprintf(&msg, fmt, va);
+ va_end(va);
+
+ free(widemsg);
+ widemsg = msg;
+}
+
+/*
+ * This is used for 8-bit encodings.
+ */
+int
+towide_none(wchar_t *c, const char *mb, unsigned n __unused)
+{
+ if (mb_cur_max != 1) {
+ werr("invalid or unsupported multibyte locale");
+ return (-1);
+ }
+ *c = (uint8_t)*mb;
+ return (1);
+}
+
+int
+tomb_none(char *mb, wchar_t wc)
+{
+ if (mb_cur_max != 1) {
+ werr("invalid or unsupported multibyte locale");
+ return (-1);
+ }
+ *(uint8_t *)mb = (wc & 0xff);
+ mb[1] = 0;
+ return (1);
+}
+
+/*
+ * UTF-8 stores wide characters in UTF-32 form.
+ */
+int
+towide_utf8(wchar_t *wc, const char *mb, unsigned n)
+{
+ wchar_t c;
+ int nb;
+ wchar_t lv; /* lowest legal value */
+ int i;
+ const uint8_t *s = (const uint8_t *)mb;
+
+ c = *s;
+
+ if ((c & 0x80) == 0) {
+ /* 7-bit ASCII */
+ *wc = c;
+ return (1);
+ } else if ((c & 0xe0) == 0xc0) {
+ /* u80-u7ff - two bytes encoded */
+ nb = 2;
+ lv = 0x80;
+ c &= ~0xe0;
+ } else if ((c & 0xf0) == 0xe0) {
+ /* u800-uffff - three bytes encoded */
+ nb = 3;
+ lv = 0x800;
+ c &= ~0xf0;
+ } else if ((c & 0xf8) == 0xf0) {
+ /* u1000-u1fffff - four bytes encoded */
+ nb = 4;
+ lv = 0x1000;
+ c &= ~0xf8;
+ } else {
+ /* 5 and 6 byte encodings are not legal unicode */
+ werr("utf8 encoding too large (%s)", show_mb(mb));
+ return (-1);
+ }
+ if (nb > (int)n) {
+ werr("incomplete utf8 sequence (%s)", show_mb(mb));
+ return (-1);
+ }
+
+ for (i = 1; i < nb; i++) {
+ if (((s[i]) & 0xc0) != 0x80) {
+ werr("illegal utf8 byte (%x)", s[i]);
+ return (-1);
+ }
+ c <<= 6;
+ c |= (s[i] & 0x3f);
+ }
+
+ if (c < lv) {
+ werr("illegal redundant utf8 encoding (%s)", show_mb(mb));
+ return (-1);
+ }
+ *wc = c;
+ return (nb);
+}
+
+int
+tomb_utf8(char *mb, wchar_t wc)
+{
+ uint8_t *s = (uint8_t *)mb;
+ uint8_t msk;
+ int cnt;
+ int i;
+
+ if (wc <= 0x7f) {
+ s[0] = wc & 0x7f;
+ s[1] = 0;
+ return (1);
+ }
+ if (wc <= 0x7ff) {
+ cnt = 2;
+ msk = 0xc0;
+ } else if (wc <= 0xffff) {
+ cnt = 3;
+ msk = 0xe0;
+ } else if (wc <= 0x1fffff) {
+ cnt = 4;
+ msk = 0xf0;
+ } else {
+ werr("illegal uf8 char (%x)", wc);
+ return (-1);
+ }
+ for (i = cnt - 1; i; i--) {
+ s[i] = (wc & 0x3f) | 0x80;
+ wc >>= 6;
+ }
+ s[0] = (msk) | wc;
+ s[cnt] = 0;
+ return (cnt);
+}
+
+/*
+ * Several encodings share a simplistic dual byte encoding. In these
+ * forms, they all indicate that a two byte sequence is to be used if
+ * the first byte has its high bit set. They all store this simple
+ * encoding as a 16-bit value, although a great many of the possible
+ * code points are not used in most character sets. This gives a possible
+ * set of just over 32,000 valid code points.
+ *
+ * 0x00 - 0x7f - 1 byte encoding
+ * 0x80 - 0x7fff - illegal
+ * 0x8000 - 0xffff - 2 byte encoding
+ */
+
+static int
+towide_dbcs(wchar_t *wc, const char *mb, unsigned n)
+{
+ wchar_t c;
+
+ c = *(const uint8_t *)mb;
+
+ if ((c & 0x80) == 0) {
+ /* 7-bit */
+ *wc = c;
+ return (1);
+ }
+ if (n < 2) {
+ werr("incomplete character sequence (%s)", show_mb(mb));
+ return (-1);
+ }
+
+ /* Store both bytes as a single 16-bit wide. */
+ c <<= 8;
+ c |= (uint8_t)(mb[1]);
+ *wc = c;
+ return (2);
+}
+
+/*
+ * Most multibyte locales just convert the wide character to the multibyte
+ * form by stripping leading null bytes, and writing the 32-bit quantity
+ * in big-endian order.
+ */
+int
+tomb_mbs(char *mb, wchar_t wc)
+{
+ uint8_t *s = (uint8_t *)mb;
+ int n = 0, c;
+
+ if ((wc & 0xff000000U) != 0) {
+ n = 4;
+ } else if ((wc & 0x00ff0000U) != 0) {
+ n = 3;
+ } else if ((wc & 0x0000ff00U) != 0) {
+ n = 2;
+ } else {
+ n = 1;
+ }
+ c = n;
+ while (n) {
+ n--;
+ s[n] = wc & 0xff;
+ wc >>= 8;
+ }
+ /* ensure null termination */
+ s[c] = 0;
+ return (c);
+}
+
+
+/*
+ * big5 is a simple dual byte character set.
+ */
+int
+towide_big5(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_dbcs(wc, mb, n));
+}
+
+/*
+ * GBK encodes wides in the same way that big5 does, the high order
+ * bit of the first byte indicates a double byte character.
+ */
+int
+towide_gbk(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_dbcs(wc, mb, n));
+}
+
+/*
+ * GB2312 is another DBCS. Its cleaner than others in that the second
+ * byte does not encode ASCII, but it supports characters.
+ */
+int
+towide_gb2312(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_dbcs(wc, mb, n));
+}
+
+/*
+ * GB18030. This encodes as 8, 16, or 32-bits.
+ * 7-bit values are in 1 byte, 4 byte sequences are used when
+ * the second byte encodes 0x30-39 and all other sequences are 2 bytes.
+ */
+int
+towide_gb18030(wchar_t *wc, const char *mb, unsigned n)
+{
+ wchar_t c;
+
+ c = *(const uint8_t *)mb;
+
+ if ((c & 0x80) == 0) {
+ /* 7-bit */
+ *wc = c;
+ return (1);
+ }
+ if (n < 2) {
+ werr("incomplete character sequence (%s)", show_mb(mb));
+ return (-1);
+ }
+
+ /* pull in the second byte */
+ c <<= 8;
+ c |= (uint8_t)(mb[1]);
+
+ if (((c & 0xff) >= 0x30) && ((c & 0xff) <= 0x39)) {
+ if (n < 4) {
+ werr("incomplete 4-byte character sequence (%s)",
+ show_mb(mb));
+ return (-1);
+ }
+ c <<= 8;
+ c |= (uint8_t)(mb[2]);
+ c <<= 8;
+ c |= (uint8_t)(mb[3]);
+ *wc = c;
+ return (4);
+ }
+
+ *wc = c;
+ return (2);
+}
+
+/*
+ * MS-Kanji (aka SJIS) is almost a clean DBCS like the others, but it
+ * also has a range of single byte characters above 0x80. (0xa1-0xdf).
+ */
+int
+towide_mskanji(wchar_t *wc, const char *mb, unsigned n)
+{
+ wchar_t c;
+
+ c = *(const uint8_t *)mb;
+
+ if ((c < 0x80) || ((c > 0xa0) && (c < 0xe0))) {
+ /* 7-bit */
+ *wc = c;
+ return (1);
+ }
+
+ if (n < 2) {
+ werr("incomplete character sequence (%s)", show_mb(mb));
+ return (-1);
+ }
+
+ /* Store both bytes as a single 16-bit wide. */
+ c <<= 8;
+ c |= (uint8_t)(mb[1]);
+ *wc = c;
+ return (2);
+}
+
+/*
+ * EUC forms. EUC encodings are "variable". FreeBSD carries some additional
+ * variable data to encode these, but we're going to treat each as independent
+ * instead. Its the only way we can sensibly move forward.
+ *
+ * Note that the way in which the different EUC forms vary is how wide
+ * CS2 and CS3 are and what the first byte of them is.
+ */
+static int
+towide_euc_impl(wchar_t *wc, const char *mb, unsigned n,
+ uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
+{
+ int i;
+ int width = 2;
+ wchar_t c;
+
+ c = *(const uint8_t *)mb;
+
+ /*
+ * All variations of EUC encode 7-bit ASCII as one byte, and use
+ * additional bytes for more than that.
+ */
+ if ((c & 0x80) == 0) {
+ /* 7-bit */
+ *wc = c;
+ return (1);
+ }
+
+ /*
+ * All EUC variants reserve 0xa1-0xff to identify CS1, which
+ * is always two bytes wide. Note that unused CS will be zero,
+ * and that cannot be true because we know that the high order
+ * bit must be set.
+ */
+ if (c >= 0xa1) {
+ width = 2;
+ } else if (c == cs2) {
+ width = cs2width;
+ } else if (c == cs3) {
+ width = cs3width;
+ }
+
+ if ((int)n < width) {
+ werr("incomplete character sequence (%s)", show_mb(mb));
+ return (-1);
+ }
+
+ for (i = 1; i < width; i++) {
+ /* pull in the next byte */
+ c <<= 8;
+ c |= (uint8_t)(mb[i]);
+ }
+
+ *wc = c;
+ return (width);
+}
+
+/*
+ * EUC-CN encodes as follows:
+ *
+ * Code set 0 (ASCII): 0x21-0x7E
+ * Code set 1 (CNS 11643-1992 Plane 1): 0xA1A1-0xFEFE
+ * Code set 2: unused
+ * Code set 3: unused
+ */
+int
+towide_euccn(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_euc_impl(wc, mb, n, 0x8e, 4, 0, 0));
+}
+
+/*
+ * EUC-JP encodes as follows:
+ *
+ * Code set 0 (ASCII or JIS X 0201-1976 Roman): 0x21-0x7E
+ * Code set 1 (JIS X 0208): 0xA1A1-0xFEFE
+ * Code set 2 (half-width katakana): 0x8EA1-0x8EDF
+ * Code set 3 (JIS X 0212-1990): 0x8FA1A1-0x8FFEFE
+ */
+int
+towide_eucjp(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_euc_impl(wc, mb, n, 0x8e, 2, 0x8f, 3));
+}
+
+/*
+ * EUC-KR encodes as follows:
+ *
+ * Code set 0 (ASCII or KS C 5636-1993): 0x21-0x7E
+ * Code set 1 (KS C 5601-1992): 0xA1A1-0xFEFE
+ * Code set 2: unused
+ * Code set 3: unused
+ */
+int
+towide_euckr(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_euc_impl(wc, mb, n, 0, 0, 0, 0));
+}
+
+/*
+ * EUC-TW encodes as follows:
+ *
+ * Code set 0 (ASCII): 0x21-0x7E
+ * Code set 1 (CNS 11643-1992 Plane 1): 0xA1A1-0xFEFE
+ * Code set 2 (CNS 11643-1992 Planes 1-16): 0x8EA1A1A1-0x8EB0FEFE
+ * Code set 3: unused
+ */
+int
+towide_euctw(wchar_t *wc, const char *mb, unsigned n)
+{
+ return (towide_euc_impl(wc, mb, n, 0x8e, 4, 0, 0));
+}
+
+/*
+ * Public entry points.
+ */
+
+int
+to_wide(wchar_t *wc, const char *mb)
+{
+ /* this won't fail hard */
+ return (_towide(wc, mb, strlen(mb)));
+}
+
+int
+to_mb(char *mb, wchar_t wc)
+{
+ int rv;
+
+ if ((rv = _tomb(mb, wc)) < 0) {
+ warn("%s", widemsg);
+ free(widemsg);
+ widemsg = NULL;
+ }
+ return (rv);
+}
+
+char *
+to_mb_string(const wchar_t *wcs)
+{
+ char *mbs;
+ char *ptr;
+ int len;
+
+ mbs = malloc((wcslen(wcs) * mb_cur_max) + 1);
+ if (mbs == NULL) {
+ warn("out of memory");
+ return (NULL);
+ }
+ ptr = mbs;
+ while (*wcs) {
+ if ((len = to_mb(ptr, *wcs)) < 0) {
+ INTERR;
+ free(mbs);
+ return (NULL);
+ }
+ wcs++;
+ ptr += len;
+ }
+ *ptr = 0;
+ return (mbs);
+}
+
+void
+set_wide_encoding(const char *encoding)
+{
+ int i;
+
+ _towide = towide_none;
+ _tomb = tomb_none;
+ _nbits = 8;
+
+ snprintf(_encoding_buffer, sizeof(_encoding_buffer), "NONE:%s",
+ encoding);
+ for (i = 0; mb_encodings[i].name; i++) {
+ if (strcasecmp(encoding, mb_encodings[i].name) == 0) {
+ _towide = mb_encodings[i].towide;
+ _tomb = mb_encodings[i].tomb;
+ _encoding = mb_encodings[i].cname;
+ _nbits = mb_encodings[i].nbits;
+ break;
+ }
+ }
+}
+
+const char *
+get_wide_encoding(void)
+{
+ return (_encoding);
+}
+
+int
+max_wide(void)
+{
+ return ((int)((1U << _nbits) - 1));
+}
diff --git a/usr.bin/locate/Makefile b/usr.bin/locate/Makefile
new file mode 100644
index 000000000000..b1f74a2d443d
--- /dev/null
+++ b/usr.bin/locate/Makefile
@@ -0,0 +1,4 @@
+
+SUBDIR= bigram code locate
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/locate/Makefile.inc b/usr.bin/locate/Makefile.inc
new file mode 100644
index 000000000000..a247370497a9
--- /dev/null
+++ b/usr.bin/locate/Makefile.inc
@@ -0,0 +1,3 @@
+LIBEXECDIR?= /usr/libexec
+
+WARNS?= 0
diff --git a/usr.bin/locate/bigram/Makefile b/usr.bin/locate/bigram/Makefile
new file mode 100644
index 000000000000..1cd04c88496a
--- /dev/null
+++ b/usr.bin/locate/bigram/Makefile
@@ -0,0 +1,6 @@
+PROG= locate.bigram
+MAN=
+BINDIR= ${LIBEXECDIR}
+CFLAGS+= -I${.CURDIR}/../locate
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/locate/bigram/Makefile.depend b/usr.bin/locate/bigram/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/locate/bigram/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/locate/bigram/locate.bigram.c b/usr.bin/locate/bigram/locate.bigram.c
new file mode 100644
index 000000000000..494aa2299c7d
--- /dev/null
+++ b/usr.bin/locate/bigram/locate.bigram.c
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods.
+ *
+ * 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.
+ *
+ * locate.bigram - list bigrams for /usr/libexec/locate.mklocatedb script
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "locate.h"
+
+u_char buf1[LOCATE_PATH_MAX] = " ";
+u_char buf2[LOCATE_PATH_MAX];
+unsigned long bigram[UCHAR_MAX + 1][UCHAR_MAX + 1];
+
+int
+main(void)
+{
+ u_char *cp;
+ u_char *oldpath = buf1, *path = buf2;
+ u_int i, j;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ while (fgets(path, sizeof(buf2), stdin) != NULL) {
+
+ /*
+ * We don't need remove newline character '\n'.
+ * '\n' is less than ASCII_MIN and will be later
+ * ignored at output.
+ */
+
+
+ /* skip longest common prefix */
+ for (cp = path; *cp == *oldpath; cp++, oldpath++)
+ if (*cp == '\0')
+ break;
+
+ while (*cp != '\0' && *(cp + 1) != '\0') {
+ bigram[(u_char)*cp][(u_char)*(cp + 1)]++;
+ cp += 2;
+ }
+
+ /* swap pointers */
+ if (path == buf1) {
+ path = buf2;
+ oldpath = buf1;
+ } else {
+ path = buf1;
+ oldpath = buf2;
+ }
+ }
+ if (!feof(stdin) || ferror(stdin))
+ err(1, "stdin");
+
+
+ /* output, boundary check */
+ for (i = ASCII_MIN; i <= ASCII_MAX; i++)
+ for (j = ASCII_MIN; j <= ASCII_MAX; j++)
+ if (bigram[i][j] != 0)
+ printf("%lu %c%c\n", bigram[i][j], i, j);
+
+ exit(0);
+}
diff --git a/usr.bin/locate/code/Makefile b/usr.bin/locate/code/Makefile
new file mode 100644
index 000000000000..e50f1f202937
--- /dev/null
+++ b/usr.bin/locate/code/Makefile
@@ -0,0 +1,6 @@
+PROG= locate.code
+CFLAGS+=-I${.CURDIR}/../locate
+MAN=
+BINDIR= ${LIBEXECDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/locate/code/Makefile.depend b/usr.bin/locate/code/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/locate/code/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/locate/code/locate.code.c b/usr.bin/locate/code/locate.code.c
new file mode 100644
index 000000000000..08bbee9a2b1f
--- /dev/null
+++ b/usr.bin/locate/code/locate.code.c
@@ -0,0 +1,233 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods.
+ *
+ * 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.
+ */
+
+/*
+ * PURPOSE: sorted list compressor (works with a modified 'find'
+ * to encode/decode a filename database)
+ *
+ * USAGE: bigram < list > bigrams
+ * process bigrams (see updatedb) > common_bigrams
+ * code common_bigrams < list > squozen_list
+ *
+ * METHOD: Uses 'front compression' (see ";login:", Volume 8, Number 1
+ * February/March 1983, p. 8). Output format is, per line, an
+ * offset differential count byte followed by a partially bigram-
+ * encoded ascii residue. A bigram is a two-character sequence,
+ * the first 128 most common of which are encoded in one byte.
+ *
+ * EXAMPLE: For simple front compression with no bigram encoding,
+ * if the input is... then the output is...
+ *
+ * /usr/src 0 /usr/src
+ * /usr/src/cmd/aardvark.c 8 /cmd/aardvark.c
+ * /usr/src/cmd/armadillo.c 14 armadillo.c
+ * /usr/tmp/zoo 5 tmp/zoo
+ *
+ * The codes are:
+ *
+ * 0-28 likeliest differential counts + offset to make nonnegative
+ * 30 switch code for out-of-range count to follow in next word
+ * 31 an 8 bit char followed
+ * 128-255 bigram codes (128 most common, as determined by 'updatedb')
+ * 32-127 single character (printable) ascii residue (ie, literal)
+ *
+ * The locate database store any character except newline ('\n')
+ * and NUL ('\0'). The 8-bit character support don't wast extra
+ * space until you have characters in file names less than 32
+ * or greather than 127.
+ *
+ *
+ * SEE ALSO: updatedb.sh, ../bigram/locate.bigram.c
+ *
+ * AUTHOR: James A. Woods, Informatics General Corp.,
+ * NASA Ames Research Center, 10/82
+ * 8-bit file names characters:
+ * Wolfram Schneider, Berlin September 1996
+ */
+
+#include <sys/param.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "locate.h"
+
+#define BGBUFSIZE (NBG * 2) /* size of bigram buffer */
+
+u_char buf1[LOCATE_PATH_MAX] = " ";
+u_char buf2[LOCATE_PATH_MAX];
+u_char bigrams[BGBUFSIZE + 1] = { 0 };
+
+/* use a lookup array instead a function, 3x faster than linear search */
+int big [UCHAR_MAX + 1][UCHAR_MAX + 1];
+#define BGINDEX(x) (big[(u_char)*x][(u_char)*(x + 1)])
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ u_char *cp, *oldpath, *path;
+ int ch, code, count, diffcount, oldcount;
+ u_int i, j;
+ FILE *fp;
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ if ((fp = fopen(argv[0], "r")) == NULL)
+ err(1, "%s", argv[0]);
+
+ /* First copy bigram array to stdout. */
+ if (fgets(bigrams, BGBUFSIZE + 1, fp) == NULL) {
+ if (!feof(fp) || ferror(fp))
+ err(1, "get bigram array");
+ }
+
+ if (fwrite(bigrams, 1, BGBUFSIZE, stdout) != BGBUFSIZE)
+ err(1, "stdout");
+ (void)fclose(fp);
+
+ /* init lookup table */
+ for (i = 0; i < UCHAR_MAX + 1; i++)
+ for (j = 0; j < UCHAR_MAX + 1; j++)
+ big[i][j] = -1;
+
+ for (cp = bigrams, i = 0; *cp != '\0'; i += 2, cp += 2)
+ big[(u_char)*cp][(u_char)*(cp + 1)] = i;
+
+ oldpath = buf1;
+ path = buf2;
+ oldcount = 0;
+
+ while (fgets(path, sizeof(buf2), stdin) != NULL) {
+
+ /* skip empty lines */
+ if (*path == '\n')
+ continue;
+
+ /* remove newline */
+ for (cp = path; *cp != '\0'; cp++) {
+ /* chop newline */
+ if (*cp == '\n')
+ *cp = '\0';
+ }
+
+ /* Skip longest common prefix. */
+ for (cp = path; *cp == *oldpath; cp++, oldpath++)
+ if (*cp == '\0')
+ break;
+
+ count = cp - path;
+ diffcount = count - oldcount + OFFSET;
+ oldcount = count;
+ if (diffcount < 0 || diffcount > 2 * OFFSET) {
+ if (putchar(SWITCH) == EOF ||
+ putw(diffcount, stdout) == EOF)
+ err(1, "stdout");
+ } else
+ if (putchar(diffcount) == EOF)
+ err(1, "stdout");
+
+ while (*cp != '\0') {
+ /* print *two* characters */
+
+ if ((code = BGINDEX(cp)) != -1) {
+ /*
+ * print *one* as bigram
+ * Found, so mark byte with
+ * parity bit.
+ */
+ if (putchar((code / 2) | PARITY) == EOF)
+ err(1, "stdout");
+ cp += 2;
+ }
+
+ else {
+ for (i = 0; i < 2; i++) {
+ if (*cp == '\0')
+ break;
+
+ /* print umlauts in file names */
+ if (*cp < ASCII_MIN ||
+ *cp > ASCII_MAX) {
+ if (putchar(UMLAUT) == EOF ||
+ putchar(*cp++) == EOF)
+ err(1, "stdout");
+ }
+
+ else {
+ /* normal character */
+ if(putchar(*cp++) == EOF)
+ err(1, "stdout");
+ }
+ }
+
+ }
+ }
+
+ if (path == buf1) { /* swap pointers */
+ path = buf2;
+ oldpath = buf1;
+ } else {
+ path = buf1;
+ oldpath = buf2;
+ }
+ }
+
+ /* Non-zero status if there were errors */
+ if (fflush(stdout) != 0 || ferror(stdout))
+ errx(1, "stdout");
+
+ exit(0);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: locate.code common_bigrams < list > squozen_list\n");
+ exit(1);
+}
diff --git a/usr.bin/locate/locate/Makefile b/usr.bin/locate/locate/Makefile
new file mode 100644
index 000000000000..64822fd2ef63
--- /dev/null
+++ b/usr.bin/locate/locate/Makefile
@@ -0,0 +1,17 @@
+CONFS= locate.rc
+PROG= locate
+SRCS= util.c locate.c
+CFLAGS+= -I${.CURDIR} -DMMAP
+SCRIPTS=updatedb.sh mklocatedb.sh concatdb.sh
+MAN= locate.1 locate.updatedb.8
+
+WARNS?= 2
+
+SCRIPTSDIR= ${LIBEXECDIR}
+.for script in ${SCRIPTS}
+SCRIPTSNAME_${script}= locate.${script:R}
+.endfor
+MLINKS+= locate.updatedb.8 updatedb.8
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.bin/locate/locate/Makefile.depend b/usr.bin/locate/locate/Makefile.depend
new file mode 100644
index 000000000000..344a5d0e9310
--- /dev/null
+++ b/usr.bin/locate/locate/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/locate/locate/concatdb.sh b/usr.bin/locate/locate/concatdb.sh
new file mode 100644
index 000000000000..9693017ec676
--- /dev/null
+++ b/usr.bin/locate/locate/concatdb.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) September 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# concatdb - concatenate locate databases
+#
+# usage: concatdb database1 ... databaseN > newdb
+#
+# Please note: the sequence of databases is important.
+#
+
+# stop on first error
+set -e
+set -o pipefail
+
+# The directory containing locate subprograms
+: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
+
+PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
+: ${TMPDIR:=/var/tmp}; export TMPDIR;
+
+# utilities to built locate database
+: ${bigram:=locate.bigram}
+: ${code:=locate.code}
+: ${sort:=sort}
+: ${locate:=locate}
+
+if [ $# -lt 2 ]; then
+ echo 'usage: concatdb databases1 ... databaseN > newdb'
+ exit 1
+fi
+
+bigrams=$(mktemp -t bigrams)
+trap 'rm -f $bigrams' 0 1 2 3 5 10 15
+
+for db
+do
+ $locate -d $db /
+done | $bigram | $sort -nr | \
+ awk 'NR <= 128 && /^[ \t]*[1-9][0-9]*[ \t]+..$/ { printf("%s", substr($0, length($0)-1, 2)) }' > $bigrams
+
+for db
+do
+ $locate -d $db /
+done | $code $bigrams
+
+#EOF
diff --git a/usr.bin/locate/locate/fastfind.c b/usr.bin/locate/locate/fastfind.c
new file mode 100644
index 000000000000..60cb2ba5faaa
--- /dev/null
+++ b/usr.bin/locate/locate/fastfind.c
@@ -0,0 +1,343 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods.
+ *
+ * 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.
+ */
+
+
+#ifndef _LOCATE_STATISTIC_
+#define _LOCATE_STATISTIC_
+
+void
+statistic (FILE *fp, char *path_fcodes)
+{
+ long lines, chars, size, size_nbg, big, zwerg, umlaut;
+ u_char *p, *s;
+ int c;
+ int count, longest_path;
+ int error = 0;
+ u_char bigram1[NBG], bigram2[NBG], path[LOCATE_PATH_MAX];
+
+ for (c = 0, p = bigram1, s = bigram2; c < NBG; c++) {
+ p[c] = check_bigram_char(getc(fp));
+ s[c] = check_bigram_char(getc(fp));
+ }
+
+ lines = chars = big = zwerg = umlaut = longest_path = 0;
+ size = NBG + NBG;
+
+ for (c = getc(fp), count = 0; c != EOF; size++) {
+ if (c == SWITCH) {
+ count += getwf(fp) - OFFSET;
+ size += sizeof(int);
+ zwerg++;
+ } else
+ count += c - OFFSET;
+
+ if (count < 0 || count >= LOCATE_PATH_MAX) {
+ /* stop on error and display the statstics anyway */
+ warnx("corrupted database: %s %d", path_fcodes, count);
+ error = 1;
+ break;
+ }
+
+ for (p = path + count; (c = getc(fp)) > SWITCH; size++)
+ if (c < PARITY) {
+ if (c == UMLAUT) {
+ c = getc(fp);
+ size++;
+ umlaut++;
+ }
+ p++;
+ } else {
+ /* bigram char */
+ big++;
+ p += 2;
+ }
+
+ p++;
+ lines++;
+ chars += (p - path);
+ if ((p - path) > longest_path)
+ longest_path = p - path;
+ }
+
+ /* size without bigram db */
+ size_nbg = size - (2 * NBG);
+
+ (void)printf("\nDatabase: %s\n", path_fcodes);
+ (void)printf("Compression: Front: %2.2f%%, ", chars > 0 ? (size_nbg + big) / (chars / (float)100) : 0);
+ (void)printf("Bigram: %2.2f%%, ", big > 0 ? (size_nbg - big) / (size_nbg / (float)100) : 0);
+ /* incl. bigram db overhead */
+ (void)printf("Total: %2.2f%%\n", chars > 0 ? size / (chars / (float)100) : 0);
+ (void)printf("Filenames: %ld, ", lines);
+ (void)printf("Characters: %ld, ", chars);
+ (void)printf("Database size: %ld\n", size);
+ (void)printf("Bigram characters: %ld, ", big);
+ (void)printf("Integers: %ld, ", zwerg);
+ (void)printf("8-Bit characters: %ld\n", umlaut);
+ printf("Longest path: %d\n", longest_path > 0 ? longest_path - 1 : 0);
+
+ /* non zero exit on corrupt database */
+ if (error)
+ exit(error);
+}
+#endif /* _LOCATE_STATISTIC_ */
+
+extern char separator;
+
+void
+#ifdef FF_MMAP
+
+
+#ifdef FF_ICASE
+fastfind_mmap_icase
+#else
+fastfind_mmap
+#endif /* FF_ICASE */
+(char *pathpart, caddr_t paddr, off_t len, char *database)
+
+
+#else /* MMAP */
+
+
+#ifdef FF_ICASE
+fastfind_icase
+#else
+fastfind
+#endif /* FF_ICASE */
+
+(FILE *fp, char *pathpart, char *database)
+
+
+#endif /* MMAP */
+
+{
+ u_char *p, *s, *patend, *q, *foundchar;
+ int c, cc;
+ int count, found, globflag;
+ u_char *cutoff;
+ u_char bigram1[NBG], bigram2[NBG], path[LOCATE_PATH_MAX + 2];
+
+#ifdef FF_ICASE
+ /* use a lookup table for case insensitive search */
+ u_char table[UCHAR_MAX + 1];
+
+ tolower_word(pathpart);
+#endif /* FF_ICASE*/
+
+ /* init bigram table */
+#ifdef FF_MMAP
+ for (c = 0, p = bigram1, s = bigram2; c < NBG; c++, len-= 2) {
+ p[c] = check_bigram_char(*paddr++);
+ s[c] = check_bigram_char(*paddr++);
+ }
+#else
+ for (c = 0, p = bigram1, s = bigram2; c < NBG; c++) {
+ p[c] = check_bigram_char(getc(fp));
+ s[c] = check_bigram_char(getc(fp));
+ }
+#endif /* FF_MMAP */
+
+ /* find optimal (last) char for searching */
+ for (p = pathpart; *p != '\0'; p++)
+ if (strchr(LOCATE_REG, *p) != NULL)
+ break;
+
+ if (*p == '\0')
+ globflag = 0;
+ else
+ globflag = 1;
+
+ p = pathpart;
+ patend = patprep(p);
+ cc = *patend;
+
+#ifdef FF_ICASE
+ /* set patend char to true */
+ for (c = 0; c < UCHAR_MAX + 1; c++)
+ table[c] = 0;
+
+ table[TOLOWER(*patend)] = 1;
+ table[toupper(*patend)] = 1;
+#endif /* FF_ICASE */
+
+
+ /* main loop */
+ found = count = 0;
+ foundchar = 0;
+
+#ifdef FF_MMAP
+ c = (u_char)*paddr++;
+ len--;
+
+ for (; len > 0; ) {
+#else
+ c = getc(fp);
+ for (; c != EOF; ) {
+#endif /* FF_MMAP */
+
+ /* go forward or backward */
+ if (c == SWITCH) { /* big step, an integer */
+#ifdef FF_MMAP
+ if (len < sizeof(int))
+ errx(1, "corrupted database: %s", database);
+
+ count += getwm(paddr) - OFFSET;
+ len -= INTSIZE;
+ paddr += INTSIZE;
+#else
+ count += getwf(fp) - OFFSET;
+#endif /* FF_MMAP */
+ } else { /* slow step, =< 14 chars */
+ count += c - OFFSET;
+ }
+
+ if (count < 0 || count >= LOCATE_PATH_MAX)
+ errx(1, "corrupted database: %s %d", database, count);
+
+ /* overlay old path */
+ p = path + count;
+ foundchar = p - 1;
+
+#ifdef FF_MMAP
+ for (; len > 0;) {
+ c = (u_char)*paddr++;
+ len--;
+#else
+ for (;;) {
+ c = getc(fp);
+#endif /* FF_MMAP */
+ /*
+ * == UMLAUT: 8 bit char followed
+ * <= SWITCH: offset
+ * >= PARITY: bigram
+ * rest: single ascii char
+ *
+ * offset < SWITCH < UMLAUT < ascii < PARITY < bigram
+ */
+ if (c < PARITY) {
+ if (c <= UMLAUT) {
+ if (c == UMLAUT) {
+#ifdef FF_MMAP
+ c = (u_char)*paddr++;
+ len--;
+#else
+ c = getc(fp);
+#endif /* FF_MMAP */
+
+ } else
+ break; /* SWITCH */
+ }
+#ifdef FF_ICASE
+ if (table[c])
+#else
+ if (c == cc)
+#endif /* FF_ICASE */
+ foundchar = p;
+ *p++ = c;
+ }
+ else {
+ /* bigrams are parity-marked */
+ TO7BIT(c);
+
+#ifndef FF_ICASE
+ if (bigram1[c] == cc ||
+ bigram2[c] == cc)
+#else
+
+ if (table[bigram1[c]] ||
+ table[bigram2[c]])
+#endif /* FF_ICASE */
+ foundchar = p + 1;
+
+ *p++ = bigram1[c];
+ *p++ = bigram2[c];
+ }
+
+ if (p - path >= LOCATE_PATH_MAX)
+ errx(1, "corrupted database: %s %td", database, p - path);
+
+ }
+
+ if (found) { /* previous line matched */
+ cutoff = path;
+ *p-- = '\0';
+ foundchar = p;
+ } else if (foundchar >= path + count) { /* a char matched */
+ *p-- = '\0';
+ cutoff = path + count;
+ } else /* nothing to do */
+ continue;
+
+ found = 0;
+ for (s = foundchar; s >= cutoff; s--) {
+ if (*s == cc
+#ifdef FF_ICASE
+ || TOLOWER(*s) == cc
+#endif /* FF_ICASE */
+ ) { /* fast first char check */
+ for (p = patend - 1, q = s - 1; *p != '\0';
+ p--, q--)
+ if (*q != *p
+#ifdef FF_ICASE
+ && TOLOWER(*q) != *p
+#endif /* FF_ICASE */
+ )
+ break;
+ if (*p == '\0') { /* fast match success */
+ found = 1;
+ if (!globflag ||
+#ifndef FF_ICASE
+ !fnmatch(pathpart, path, 0))
+#else
+ !fnmatch(pathpart, path,
+ FNM_CASEFOLD))
+#endif /* !FF_ICASE */
+ {
+ if (f_silent)
+ counter++;
+ else if (f_limit) {
+ counter++;
+ if (f_limit >= counter)
+ (void)printf("%s%c",path,separator);
+ else
+ errx(0, "[show only %ld lines]", counter - 1);
+ } else
+ (void)printf("%s%c",path,separator);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/usr.bin/locate/locate/locate.1 b/usr.bin/locate/locate/locate.1
new file mode 100644
index 000000000000..4999722acfc5
--- /dev/null
+++ b/usr.bin/locate/locate/locate.1
@@ -0,0 +1,268 @@
+.\" Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd December 11, 2020
+.Dt LOCATE 1
+.Os
+.Sh NAME
+.Nm locate
+.Nd find filenames quickly
+.Sh SYNOPSIS
+.Nm
+.Op Fl 0Scims
+.Op Fl l Ar limit
+.Op Fl d Ar database
+.Ar pattern ...
+.Sh DESCRIPTION
+The
+.Nm
+program searches a database for all pathnames which match the specified
+.Ar pattern .
+The database is recomputed periodically (usually weekly or daily),
+and contains the pathnames
+of all files which are publicly accessible.
+.Pp
+Shell globbing and quoting characters
+.Dq ( * ,
+.Dq \&? ,
+.Dq \e ,
+.Dq \&[
+and
+.Dq \&] )
+may be used in
+.Ar pattern ,
+although they will have to be escaped from the shell.
+Preceding any character with a backslash
+.Pq Dq \e
+eliminates any special
+meaning which it may have.
+The matching differs in that no characters must be matched explicitly,
+including slashes
+.Pq Dq / .
+.Pp
+As a special case, a pattern containing no globbing characters
+.Pq Dq foo
+is matched as though it were
+.Dq *foo* .
+.Pp
+Historically, locate only stored characters between 32 and 127.
+The
+current implementation stores any character except newline
+.Pq Sq \en
+and
+.Dv NUL
+.Pq Sq \e0 .
+The 8-bit character support does not waste extra space for
+plain ASCII file names.
+Characters less than 32 or greater than 127
+are stored in 2 bytes.
+.Pp
+The following options are available:
+.Bl -tag -width 10n
+.It Fl 0
+Print pathnames separated by an ASCII
+.Dv NUL
+character (character code 0) instead of default NL
+(newline, character code 10).
+.It Fl S
+Print some statistics about the database and exit.
+.It Fl c
+Suppress normal output; instead print a count of matching file names.
+.It Fl d Ar database
+Search in
+.Ar database
+instead of the default file name database.
+Multiple
+.Fl d
+options are allowed.
+Each additional
+.Fl d
+option adds the specified database to the list
+of databases to be searched.
+.Pp
+The option
+.Ar database
+may be a colon-separated list of databases.
+A single colon is a reference
+to the default database.
+.Bd -literal
+$ locate -d $HOME/lib/mydb: foo
+.Ed
+.Pp
+will first search string
+.Dq foo
+in
+.Pa $HOME/lib/mydb
+and then in
+.Pa /var/db/locate.database .
+.Bd -literal
+$ locate -d $HOME/lib/mydb::/cdrom/locate.database foo
+.Ed
+.Pp
+will first search string
+.Dq foo
+in
+.Pa $HOME/lib/mydb
+and then in
+.Pa /var/db/locate.database
+and then in
+.Pa /cdrom/locate.database .
+.Pp
+.Dl "$ locate -d db1 -d db2 -d db3 pattern"
+.Pp
+is the same as
+.Pp
+.Dl "$ locate -d db1:db2:db3 pattern"
+.Pp
+or
+.Pp
+.Dl "$ locate -d db1:db2 -d db3 pattern"
+.Pp
+If
+.Fl
+is given as the database name, standard input will be read instead.
+For example, you can compress your database
+and use:
+.Bd -literal
+$ zcat database.gz | locate -d - pattern
+.Ed
+.Pp
+This might be useful on machines with a fast CPU and little RAM and slow
+I/O.
+Note: you can only use
+.Em one
+pattern for stdin.
+.It Fl i
+Ignore case distinctions in both the pattern and the database.
+.It Fl l Ar number
+Limit output to
+.Ar number
+of file names and exit.
+.It Fl m
+Use
+.Xr mmap 2
+instead of the
+.Xr stdio 3
+library.
+This is the default behavior
+and is faster in most cases.
+.It Fl s
+Use the
+.Xr stdio 3
+library instead of
+.Xr mmap 2 .
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width LOCATE_PATH -compact
+.It Pa LOCATE_PATH
+path to the locate database if set and not empty, ignored if the
+.Fl d
+option was specified.
+.El
+.Sh FILES
+.Bl -tag -width /etc/periodic/weekly/310.locate -compact
+.It Pa /var/db/locate.database
+locate database
+.It Pa /usr/libexec/locate.updatedb
+Script to update the locate database
+.It Pa /etc/periodic/weekly/310.locate
+Script that starts the database rebuild
+.El
+.Sh SEE ALSO
+.Xr find 1 ,
+.Xr whereis 1 ,
+.Xr which 1 ,
+.Xr fnmatch 3 ,
+.Xr locate.updatedb 8
+.Rs
+.%A Woods, James A.
+.%D 1983
+.%T "Finding Files Fast"
+.%J ";login"
+.%V 8:1
+.%P pp. 8-10
+.Re
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Bx 4.4 .
+Many new features were
+added in
+.Fx 2.2 .
+.Sh BUGS
+The
+.Nm
+program may fail to list some files that are present, or may
+list files that have been removed from the system.
+This is because
+locate only reports files that are present in the database, which is
+typically only regenerated once a week by the
+.Pa /etc/periodic/weekly/310.locate
+script.
+Use
+.Xr find 1
+to locate files that are of a more transitory nature.
+.Pp
+The
+.Nm
+database is typically built by user
+.Dq nobody
+and the
+.Xr locate.updatedb 8
+utility skips directories
+which are not readable for user
+.Dq nobody ,
+group
+.Dq nobody ,
+or
+world.
+For example, if your HOME directory is not world-readable,
+.Em none
+of your files are
+in the database.
+.Pp
+The
+.Nm
+database is not byte order independent.
+It is not possible
+to share the databases between machines with different byte order.
+The current
+.Nm
+implementation understands databases in host byte order or
+network byte order if both architectures use the same integer size.
+So on a
+.Fx Ns /i386
+machine
+(little endian), you can read
+a locate database which was built on SunOS/sparc machine
+(big endian, net).
+.Pp
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/locate/locate/locate.c b/usr.bin/locate/locate/locate.c
new file mode 100644
index 000000000000..f2b78f9a3501
--- /dev/null
+++ b/usr.bin/locate/locate/locate.c
@@ -0,0 +1,337 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods.
+ *
+ * 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.
+ */
+
+/*
+ * Ref: Usenix ;login:, Vol 8, No 1, February/March, 1983, p. 8.
+ *
+ * Locate scans a file list for the full pathname of a file given only part
+ * of the name. The list has been processed with with "front-compression"
+ * and bigram coding. Front compression reduces space by a factor of 4-5,
+ * bigram coding by a further 20-25%.
+ *
+ * The codes are:
+ *
+ * 0-28 likeliest differential counts + offset to make nonnegative
+ * 30 switch code for out-of-range count to follow in next word
+ * 31 an 8 bit char followed
+ * 128-255 bigram codes (128 most common, as determined by 'updatedb')
+ * 32-127 single character (printable) ascii residue (ie, literal)
+ *
+ * A novel two-tiered string search technique is employed:
+ *
+ * First, a metacharacter-free subpattern and partial pathname is matched
+ * BACKWARDS to avoid full expansion of the pathname list. The time savings
+ * is 40-50% over forward matching, which cannot efficiently handle
+ * overlapped search patterns and compressed path residue.
+ *
+ * Then, the actual shell glob-style regular expression (if in this form) is
+ * matched against the candidate pathnames using the slower routines provided
+ * in the standard 'find'.
+ */
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <err.h>
+#include <fnmatch.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef MMAP
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/mman.h>
+# include <fcntl.h>
+#endif
+
+#include "locate.h"
+#include "pathnames.h"
+
+
+int f_mmap; /* use mmap */
+int f_icase; /* ignore case */
+int f_stdin; /* read database from stdin */
+int f_statistic; /* print statistic */
+int f_silent; /* suppress output, show only count of matches */
+long f_limit; /* limit number of output lines, 0 == infinite */
+long counter; /* counter for matches [-c] */
+char separator='\n'; /* line separator */
+
+u_char myctype[UCHAR_MAX + 1];
+
+void usage(void);
+void statistic(FILE *, char *);
+void fastfind(FILE *, char *, char *);
+void fastfind_icase(FILE *, char *, char *);
+void fastfind_mmap(char *, caddr_t, off_t, char *);
+void fastfind_mmap_icase(char *, caddr_t, off_t, char *);
+void search_mmap(char *, char **);
+void search_fopen(char *, char **);
+unsigned long cputime(void);
+
+extern char **colon(char **, char*, char*);
+extern int getwm(caddr_t);
+extern int getwf(FILE *);
+extern u_char *tolower_word(u_char *);
+extern int check_bigram_char(int);
+extern char *patprep(char *);
+extern void rebuild_message(char *db);
+extern int check_size(char *db);
+
+int
+main(int argc, char **argv)
+{
+ int ch;
+ char **dbv = NULL;
+ char *path_fcodes; /* locate database */
+#ifdef MMAP
+ f_mmap = 1; /* mmap is default */
+#endif
+ (void) setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "0Scd:il:ms")) != -1)
+ switch(ch) {
+ case '0': /* 'find -print0' style */
+ separator = '\0';
+ break;
+ case 'S': /* statistic lines */
+ f_statistic = 1;
+ break;
+ case 'l': /* limit number of output lines, 0 == infinite */
+ f_limit = atol(optarg);
+ if (f_limit < 0 )
+ errx(1, "invalid argument for -l: '%s'", optarg);
+ break;
+ case 'd': /* database */
+ dbv = colon(dbv, optarg, _PATH_FCODES);
+ break;
+ case 'i': /* ignore case */
+ f_icase = 1;
+ break;
+ case 'm': /* mmap */
+#ifdef MMAP
+ f_mmap = 1;
+#else
+ warnx("mmap(2) not implemented");
+#endif
+ break;
+ case 's': /* stdio lib */
+ f_mmap = 0;
+ break;
+ case 'c': /* suppress output, show only count of matches */
+ f_silent = 1;
+ break;
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ /* to few arguments */
+ if (argc < 1 && !(f_statistic))
+ usage();
+
+ /* no (valid) database as argument */
+ if (dbv == NULL || *dbv == NULL) {
+ /* try to read database from environment */
+ if ((path_fcodes = getenv("LOCATE_PATH")) == NULL ||
+ *path_fcodes == '\0')
+ /* use default database */
+ dbv = colon(dbv, _PATH_FCODES, _PATH_FCODES);
+ else /* $LOCATE_PATH */
+ dbv = colon(dbv, path_fcodes, _PATH_FCODES);
+ }
+
+ if (f_icase && UCHAR_MAX < 4096) /* init tolower lookup table */
+ for (ch = 0; ch < UCHAR_MAX + 1; ch++)
+ myctype[ch] = tolower(ch);
+
+ /* foreach database ... */
+ while((path_fcodes = *dbv) != NULL) {
+ dbv++;
+
+ if (!strcmp(path_fcodes, "-"))
+ f_stdin = 1;
+ else
+ f_stdin = 0;
+
+#ifndef MMAP
+ f_mmap = 0; /* be paranoid */
+#endif
+ if (!f_mmap || f_stdin || f_statistic)
+ search_fopen(path_fcodes, argv);
+ else
+ search_mmap(path_fcodes, argv);
+ }
+
+ if (f_silent)
+ printf("%ld\n", counter);
+ exit(0);
+}
+
+/*
+ * Arguments:
+ * db database
+ * s search strings
+ */
+void
+search_fopen(char *db, char **s)
+{
+ FILE *fp;
+
+ /* can only read stdin once */
+ if (f_stdin) {
+ fp = stdin;
+ if (*(s+1) != NULL) {
+ warnx("read database from stdin, use only `%s' as pattern", *s);
+ *(s+1) = NULL;
+ }
+ }
+ else {
+ if (!check_size(db))
+ exit(1);
+
+ if ((fp = fopen(db, "r")) == NULL) {
+ warn("`%s'", db);
+ rebuild_message(db);
+ exit(1);
+ }
+ }
+
+ /* count only chars or lines */
+ if (f_statistic) {
+ statistic(fp, db);
+ (void)fclose(fp);
+ return;
+ }
+
+ /* foreach search string ... */
+ while(*s != NULL) {
+ if (!f_stdin &&
+ fseek(fp, (long)0, SEEK_SET) == -1)
+ err(1, "fseek to begin of ``%s''\n", db);
+
+ if (f_icase)
+ fastfind_icase(fp, *s, db);
+ else
+ fastfind(fp, *s, db);
+ s++;
+ }
+ (void)fclose(fp);
+}
+
+#ifdef MMAP
+/*
+ * Arguments:
+ * db database
+ * s search strings
+ */
+void
+search_mmap(char *db, char **s)
+{
+ struct stat sb;
+ int fd;
+ caddr_t p;
+ off_t len;
+
+ if (!check_size(db))
+ exit(1);
+
+ if (stat(db, &sb) == -1)
+ err(1, "stat");
+
+ len = sb.st_size;
+
+ if ((fd = open(db, O_RDONLY)) == -1) {
+ warn("%s", db);
+ rebuild_message(db);
+ exit(1);
+ }
+
+ if ((p = mmap((caddr_t)0, (size_t)len,
+ PROT_READ, MAP_SHARED,
+ fd, (off_t)0)) == MAP_FAILED)
+ err(1, "mmap ``%s''", db);
+
+ /* foreach search string ... */
+ while (*s != NULL) {
+ if (f_icase)
+ fastfind_mmap_icase(*s, p, len, db);
+ else
+ fastfind_mmap(*s, p, len, db);
+ s++;
+ }
+
+ if (munmap(p, (size_t)len) == -1)
+ warn("munmap %s\n", db);
+
+ (void)close(fd);
+}
+#endif /* MMAP */
+
+void
+usage ()
+{
+ (void)fprintf(stderr,
+ "usage: locate [-0Scims] [-l limit] [-d database] pattern ...\n\n");
+ (void)fprintf(stderr,
+ "default database: `%s' or $LOCATE_PATH\n", _PATH_FCODES);
+ exit(1);
+}
+
+
+/* load fastfind functions */
+
+/* statistic */
+/* fastfind_mmap, fastfind_mmap_icase */
+#ifdef MMAP
+#undef FF_MMAP
+#undef FF_ICASE
+
+#define FF_MMAP
+#include "fastfind.c"
+#define FF_ICASE
+#include "fastfind.c"
+#endif /* MMAP */
+
+/* fopen */
+/* fastfind, fastfind_icase */
+#undef FF_MMAP
+#undef FF_ICASE
+#include "fastfind.c"
+#define FF_ICASE
+#include "fastfind.c"
diff --git a/usr.bin/locate/locate/locate.h b/usr.bin/locate/locate/locate.h
new file mode 100644
index 000000000000..7579fcec2816
--- /dev/null
+++ b/usr.bin/locate/locate/locate.h
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+ * Copyright (c) 1989, 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.
+ */
+
+/* Symbolic constants shared by locate.c and code.c */
+
+#define NBG 128 /* number of bigrams considered */
+#define OFFSET 14 /* abs value of max likely diff */
+#define PARITY 0200 /* parity bit */
+#define SWITCH 30 /* switch code */
+#define UMLAUT 31 /* an 8 bit char followed */
+
+/* 0-28 likeliest differential counts + offset to make nonnegative */
+#define LDC_MIN 0
+#define LDC_MAX 28
+
+/* 128-255 bigram codes (128 most common, as determined by 'updatedb') */
+#define BIGRAM_MIN (UCHAR_MAX - SCHAR_MAX)
+#define BIGRAM_MAX UCHAR_MAX
+
+/* 32-127 single character (printable) ascii residue (ie, literal) */
+#define ASCII_MIN 32
+#define ASCII_MAX SCHAR_MAX
+
+/* #define TO7BIT(x) (x = ( ((u_char)x) & SCHAR_MAX )) */
+#define TO7BIT(x) (x = x & SCHAR_MAX )
+
+
+#if UCHAR_MAX >= 4096
+ define TOLOWER(ch) tolower(ch)
+#else
+
+extern u_char myctype[UCHAR_MAX + 1];
+#define TOLOWER(ch) (myctype[ch])
+#endif
+
+#define INTSIZE (sizeof(int))
+
+#define LOCATE_REG "*?[]\\" /* fnmatch(3) meta characters */
+
+/* max. path length for locate. Should be at least 1024 (PATH_MAX), but can be longer */
+#ifndef LOCATE_PATH_MAX
+#define LOCATE_PATH_MAX (1*1024)
+#endif
+
diff --git a/usr.bin/locate/locate/locate.rc b/usr.bin/locate/locate/locate.rc
new file mode 100644
index 000000000000..f004dea19508
--- /dev/null
+++ b/usr.bin/locate/locate/locate.rc
@@ -0,0 +1,32 @@
+#
+# /etc/locate.rc - command script for updatedb(8)
+#
+
+#
+# All commented values are the defaults
+#
+# temp directory
+#TMPDIR="/tmp"
+
+# the actual database
+#FCODES="/var/db/locate.database"
+
+# directories to be put in the database
+#SEARCHPATHS="/"
+
+# paths unwanted in output
+#PRUNEPATHS="/tmp /usr/tmp /var/tmp /var/db/freebsd-update"
+
+# directories unwanted in output
+#PRUNEDIRS=".zfs"
+
+# filesystems allowed. Beware: a non-listed filesystem will be pruned
+# and if the SEARCHPATHS starts in such a filesystem locate will build
+# an empty database.
+#
+# the default list contains all local file systems that are not synthetic,
+# loopback mounts, or read-only, according to lsvfs.
+#
+# be careful if you add 'nfs' or other network file system types or file
+# systems that generally reside on slow or removable devices like cd9660
+#FILESYSTEMS="ufs ext2fs zfs xfs"
diff --git a/usr.bin/locate/locate/locate.updatedb.8 b/usr.bin/locate/locate/locate.updatedb.8
new file mode 100644
index 000000000000..fff851575571
--- /dev/null
+++ b/usr.bin/locate/locate/locate.updatedb.8
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1996
+.\" Mike Pritchard <mpp@FreeBSD.org>. 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Mike Pritchard.
+.\" 4. Neither the name of the author 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 AUTHOR 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.
+.\"
+.Dd February 11, 1996
+.Dt LOCATE.UPDATEDB 8
+.Os
+.Sh NAME
+.Nm locate.updatedb
+.Nd update locate database
+.Sh SYNOPSIS
+.Nm /usr/libexec/locate.updatedb
+.Sh DESCRIPTION
+The
+.Nm
+utility updates the database used by
+.Xr locate 1 .
+It is typically run once a week by the
+.Pa /etc/periodic/weekly/310.locate
+script.
+.Pp
+The contents of the newly built database can be controlled by the
+.Pa /etc/locate.rc
+file.
+.Sh ENVIRONMENT
+.Bl -tag -width /var/db/locate.database -compact
+.It Pa LOCATE_CONFIG
+path to the configuration file
+.El
+.Sh FILES
+.Bl -tag -width /var/db/locate.database -compact
+.It Pa /var/db/locate.database
+the default database
+.It Pa /etc/locate.rc
+the configuration file
+.El
+.Sh SEE ALSO
+.Xr locate 1 ,
+.Xr periodic 8
+.Rs
+.%A Woods, James A.
+.%D 1983
+.%T "Finding Files Fast"
+.%J ";login"
+.%V 8:1
+.%P pp. 8-10
+.Re
diff --git a/usr.bin/locate/locate/mklocatedb.sh b/usr.bin/locate/locate/mklocatedb.sh
new file mode 100644
index 000000000000..40727fdd9e7a
--- /dev/null
+++ b/usr.bin/locate/locate/mklocatedb.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) September 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# mklocatedb - build locate database
+#
+# usage: mklocatedb [-presort] < filelist > database
+#
+
+# stop on first error
+set -e
+set -o pipefail
+
+# The directory containing locate subprograms
+: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
+: ${TMPDIR:=/var/tmp}; export TMPDIR
+
+PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
+
+# utilities to built locate database
+: ${bigram:=locate.bigram}
+: ${code:=locate.code}
+: ${locate:=locate}
+: ${sort:=sort}
+
+sort_opt="-u -T $TMPDIR -S 20%"
+
+bigrams=$(mktemp -t mklocatedb.bigrams)
+filelist=$(mktemp -t mklocatedb.filelist)
+
+trap 'rm -f $bigrams $filelist' 0 1 2 3 5 10 15
+
+# Input already sorted
+if [ X"$1" = "X-presort" ]; then
+ shift;
+
+ # Locate database bootstrapping
+ # 1. first build a temp database without bigram compression
+ # 2. create the bigram from the temp database
+ # 3. create the real locate database with bigram compression.
+ #
+ # This scheme avoid large temporary files in /tmp
+
+ $code $bigrams > $filelist
+ $locate -d $filelist / | $bigram | $sort -nr | \
+ awk 'NR <= 128 && /^[ \t]*[1-9][0-9]*[ \t]+..$/ { printf("%s", substr($0, length($0)-1, 2)) }' > $bigrams
+ $locate -d $filelist / | $code $bigrams
+else
+ $sort $sort_opt > $filelist
+ $bigram < $filelist | $sort -nr | \
+ awk 'NR <= 128 && /^[ \t]*[1-9][0-9]*[ \t]+..$/ { printf("%s", substr($0, length($0)-1, 2)) }' > $bigrams
+ $code $bigrams < $filelist
+fi
+
+#EOF
diff --git a/usr.bin/locate/locate/pathnames.h b/usr.bin/locate/locate/pathnames.h
new file mode 100644
index 000000000000..ed6426cc3db3
--- /dev/null
+++ b/usr.bin/locate/locate/pathnames.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_FCODES "/var/db/locate.database"
diff --git a/usr.bin/locate/locate/updatedb.sh b/usr.bin/locate/locate/updatedb.sh
new file mode 100644
index 000000000000..7d42cbb2260d
--- /dev/null
+++ b/usr.bin/locate/locate/updatedb.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) September 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# updatedb - update locate database for local mounted filesystems
+#
+
+if [ "$(id -u)" = "0" ]; then
+ echo ">>> WARNING" 1>&2
+ echo ">>> Executing updatedb as root. This WILL reveal all filenames" 1>&2
+ echo ">>> on your machine to all login users, which is a security risk." 1>&2
+fi
+: ${LOCATE_CONFIG="/etc/locate.rc"}
+if [ -f "$LOCATE_CONFIG" -a -r "$LOCATE_CONFIG" ]; then
+ . $LOCATE_CONFIG
+fi
+
+# The directory containing locate subprograms
+: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
+: ${TMPDIR:=/tmp}; export TMPDIR
+if ! TMPDIR=$(mktemp -d $TMPDIR/locateXXXXXXXXXX); then
+ exit 1
+fi
+tmp=$TMPDIR/_updatedb$$
+trap 'rc=$?; rm -f $tmp; rmdir $TMPDIR; trap - 0; exit $rc' 0 1 2 3 5 10 15
+
+PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
+
+: ${mklocatedb:=locate.mklocatedb} # make locate database program
+: ${FCODES:=/var/db/locate.database} # the database
+: ${SEARCHPATHS="/"} # directories to be put in the database
+: ${PRUNEPATHS="/tmp /usr/tmp /var/tmp /var/db/freebsd-update"} # unwanted directories
+: ${PRUNEDIRS=".zfs"} # unwanted directories, in any parent
+: ${FILESYSTEMS="$(lsvfs | tail -n +3 | \
+ egrep -vw "loopback|network|synthetic|read-only|0" | \
+ cut -d " " -f1)"} # allowed filesystems
+: ${find:=find}
+
+if [ -z "$SEARCHPATHS" ]; then
+ echo "$0: empty variable SEARCHPATHS" >&2; exit 1
+fi
+if [ -z "$FILESYSTEMS" ]; then
+ echo "$0: empty variable FILESYSTEMS" >&2; exit 1
+fi
+
+# Make a list a paths to exclude in the locate run
+excludes="! (" or=""
+for fstype in $FILESYSTEMS
+do
+ excludes="$excludes $or -fstype $fstype"
+ or="-or"
+done
+excludes="$excludes ) -prune"
+
+if [ -n "$PRUNEPATHS" ]; then
+ for path in $PRUNEPATHS; do
+ excludes="$excludes -or -path $path -prune"
+ done
+fi
+
+if [ -n "$PRUNEDIRS" ]; then
+ for dir in $PRUNEDIRS; do
+ excludes="$excludes -or -name $dir -type d -prune"
+ done
+fi
+
+# search locally
+if $find -s $SEARCHPATHS $excludes -or -print 2>/dev/null |
+ $mklocatedb -presort > $tmp
+then
+ if ! grep -aq / $tmp; then
+ echo "updatedb: locate database $tmp is empty" >&2
+ exit 1
+ fi
+ cat $tmp >$FCODES
+fi
diff --git a/usr.bin/locate/locate/util.c b/usr.bin/locate/locate/util.c
new file mode 100644
index 000000000000..2fae5225f5a0
--- /dev/null
+++ b/usr.bin/locate/locate/util.c
@@ -0,0 +1,297 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1995-2022 Wolfram Schneider <wosch@FreeBSD.org>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods.
+ *
+ * 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>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "locate.h"
+#include "pathnames.h"
+
+char **colon(char **, char*, char*);
+char *patprep(char *);
+u_char *tolower_word(u_char *);
+int getwm(caddr_t);
+int getwf(FILE *);
+int check_bigram_char(int);
+
+/*
+ * Validate bigram chars. If the test failed the database is corrupt
+ * or the database is obviously not a locate database.
+ */
+int
+check_bigram_char(int ch)
+{
+ /* legal bigram: 0, ASCII_MIN ... ASCII_MAX */
+ if (ch == 0 ||
+ (ch >= ASCII_MIN && ch <= ASCII_MAX))
+ return (ch);
+
+ errx(1,
+ "locate database header corrupt, bigram char outside 0, %d-%d: %d",
+ ASCII_MIN, ASCII_MAX, ch);
+ exit(1);
+}
+
+/* split a colon separated string into a char vector
+ *
+ * "bla:foo" -> {"foo", "bla"}
+ * "bla:" -> {"foo", dot}
+ * "bla" -> {"bla"}
+ * "" -> do nothing
+ *
+ */
+char **
+colon(char **dbv, char *path, char *dot)
+{
+ int vlen, slen;
+ char *c, *ch, *p;
+ char **pv;
+
+ if (dbv == NULL) {
+ if ((dbv = malloc(sizeof(char *))) == NULL)
+ err(1, "malloc");
+ *dbv = NULL;
+ }
+
+ /* empty string */
+ if (*path == '\0') {
+ warnx("empty database name, ignored");
+ return (dbv);
+ }
+
+ /* length of string vector */
+ for(vlen = 0, pv = dbv; *pv != NULL; pv++, vlen++);
+
+ for (ch = c = path; ; ch++) {
+ if (*ch == ':' ||
+ (!*ch && !(*(ch - 1) == ':' && ch == 1+ path))) {
+ /* single colon -> dot */
+ if (ch == c)
+ p = dot;
+ else {
+ /* a string */
+ slen = ch - c;
+ if ((p = malloc(sizeof(char) * (slen + 1)))
+ == NULL)
+ err(1, "malloc");
+ bcopy(c, p, slen);
+ *(p + slen) = '\0';
+ }
+ /* increase dbv with element p */
+ if ((dbv = realloc(dbv, sizeof(char *) * (vlen + 2)))
+ == NULL)
+ err(1, "realloc");
+ *(dbv + vlen) = p;
+ *(dbv + ++vlen) = NULL;
+ c = ch + 1;
+ }
+ if (*ch == '\0')
+ break;
+ }
+ return (dbv);
+}
+
+/*
+ * extract last glob-free subpattern in name for fast pre-match; prepend
+ * '\0' for backwards match; return end of new pattern
+ */
+static char globfree[100];
+
+char *
+patprep(char *name)
+{
+ char *endmark, *p, *subp;
+
+ subp = globfree;
+ *subp++ = '\0'; /* set first element to '\0' */
+ p = name + strlen(name) - 1;
+
+ /* skip trailing metacharacters */
+ for (; p >= name; p--)
+ if (strchr(LOCATE_REG, *p) == NULL)
+ break;
+
+ /*
+ * check if maybe we are in a character class
+ *
+ * 'foo.[ch]'
+ * |----< p
+ */
+ if (p >= name &&
+ (strchr(p, '[') != NULL || strchr(p, ']') != NULL)) {
+ for (p = name; *p != '\0'; p++)
+ if (*p == ']' || *p == '[')
+ break;
+ p--;
+
+ /*
+ * cannot find a non-meta character, give up
+ * '*\*[a-z]'
+ * |-------< p
+ */
+ if (p >= name && strchr(LOCATE_REG, *p) != NULL)
+ p = name - 1;
+ }
+
+ if (p < name)
+ /* only meta chars: "???", force '/' search */
+ *subp++ = '/';
+
+ else {
+ for (endmark = p; p >= name; p--)
+ if (strchr(LOCATE_REG, *p) != NULL)
+ break;
+ for (++p;
+ (p <= endmark) && subp < (globfree + sizeof(globfree));)
+ *subp++ = *p++;
+ }
+ *subp = '\0';
+ return (--subp);
+}
+
+/* tolower word */
+u_char *
+tolower_word(u_char *word)
+{
+ u_char *p;
+
+ for(p = word; *p != '\0'; p++)
+ *p = TOLOWER(*p);
+
+ return (word);
+}
+
+
+/*
+ * Read integer from mmap pointer.
+ * Essentially a simple ``return *(int *)p'' but avoids sigbus
+ * for integer alignment (SunOS 4.x, 5.x).
+ *
+ * Convert network byte order to host byte order if necessary.
+ * So we can read a locate database on FreeBSD/i386 (little endian)
+ * which was built on SunOS/sparc (big endian).
+ */
+
+int
+getwm(caddr_t p)
+{
+ union {
+ char buf[INTSIZE];
+ int i;
+ } u;
+ int i, hi;
+
+ /* the integer is stored by an offset of 14 (!!!) */
+ int i_max = LOCATE_PATH_MAX + OFFSET;
+ int i_min = -(LOCATE_PATH_MAX - OFFSET);
+
+ for (i = 0; i < (int)INTSIZE; i++)
+ u.buf[i] = *p++;
+
+ i = u.i;
+
+ if (i >= i_max || i <= i_min) {
+ hi = ntohl(i);
+ if (hi >= i_max || hi <= i_min)
+ errx(1, "integer out of range: %d < %d < %d",
+ i_min, abs(i) < abs(hi) ? i : hi, i_max);
+ return (hi);
+ }
+ return (i);
+}
+
+/*
+ * Read integer from stream.
+ *
+ * Convert network byte order to host byte order if necessary.
+ * So we can read on FreeBSD/i386 (little endian) a locate database
+ * which was built on SunOS/sparc (big endian).
+ */
+
+int
+getwf(FILE *fp)
+{
+ int word, hword;
+ int i_max = LOCATE_PATH_MAX + OFFSET;
+ int i_min = -(LOCATE_PATH_MAX - OFFSET);
+
+ word = getw(fp);
+
+ if (word >= i_max || word <= i_min) {
+ hword = ntohl(word);
+ if (hword >= i_max || hword <= i_min)
+ errx(1, "integer out of range: %d < %d < %d",
+ i_min, abs(word) < abs(hword) ? word : hword, i_max);
+ return (hword);
+ }
+ return (word);
+}
+
+void
+rebuild_message(char *db)
+{
+ /* only for the default locate database */
+ if (strcmp(_PATH_FCODES, db) == 0) {
+ fprintf(stderr, "\nTo create a new database, please run the following command as root:\n\n");
+ fprintf(stderr, " /etc/periodic/weekly/310.locate\n\n");
+ }
+}
+
+int
+check_size(char *db)
+{
+ struct stat sb;
+ off_t len;
+
+ if (stat(db, &sb) == -1) {
+ warnx("the locate database '%s' does not exist.", db);
+ rebuild_message(db);
+ return (0);
+ }
+ len = sb.st_size;
+
+ if (len < (2 * NBG)) {
+ warnx("the locate database '%s' is smaller than %d bytes large.", db, (2 * NBG));
+ rebuild_message(db);
+ return (0);
+ }
+
+ return (1);
+}
diff --git a/usr.bin/lock/Makefile b/usr.bin/lock/Makefile
new file mode 100644
index 000000000000..48fd0ba5e1ed
--- /dev/null
+++ b/usr.bin/lock/Makefile
@@ -0,0 +1,7 @@
+PROG= lock
+BINOWN= root
+BINMODE=4555
+
+LIBADD= pam
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lock/Makefile.depend b/usr.bin/lock/Makefile.depend
new file mode 100644
index 000000000000..0665960a2cd2
--- /dev/null
+++ b/usr.bin/lock/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libpam/libpam \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lock/lock.1 b/usr.bin/lock/lock.1
new file mode 100644
index 000000000000..a221d1b33840
--- /dev/null
+++ b/usr.bin/lock/lock.1
@@ -0,0 +1,89 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
+.\" Copyright (c) 1987, 1990, 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.
+.\"
+.Dd December 11, 2020
+.Dt LOCK 1
+.Os
+.Sh NAME
+.Nm lock
+.Nd reserve a terminal
+.Sh SYNOPSIS
+.Nm
+.Op Fl npv
+.Op Fl t Ar timeout
+.Sh DESCRIPTION
+The
+.Nm
+utility requests a password from the user, reads it again for verification
+and then will normally not relinquish the terminal until the password is
+repeated.
+There are two other conditions under which it will terminate: it
+will timeout after some interval of time and it may be killed by someone
+with the appropriate permission.
+.Pp
+The following options are available:
+.Bl -tag -width "-t timeout"
+.It Fl n
+Do not use a timeout value.
+Terminal will be locked forever.
+.It Fl p
+A password is not requested, instead the user's current login password
+is used.
+.It Fl t Ar timeout
+The time limit (default 15 minutes) is changed to
+.Ar timeout
+minutes.
+.It Fl v
+Disable switching virtual terminals while this terminal is locked.
+This option is implemented in a way similar to the
+.Fl S
+option of
+.Xr vidcontrol 1 ,
+and thus has the same restrictions.
+It is only available if the terminal in question is a
+.Xr syscons 4
+or
+.Xr vt 4
+virtual terminal.
+.El
+.Sh EXAMPLES
+Lock the terminal for 5 minutes, disable switching virtual terminals and
+require the user's login password to unlock:
+.Pp
+.Dl $ lock -p -t 5 -v
+.Sh SEE ALSO
+.Xr vidcontrol 1 ,
+.Xr syscons 4 ,
+.Xr vt 4
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/lock/lock.c b/usr.bin/lock/lock.c
new file mode 100644
index 000000000000..f2f13f6e56f8
--- /dev/null
+++ b/usr.bin/lock/lock.c
@@ -0,0 +1,301 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Bob Toxen.
+ *
+ * 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.
+ */
+
+/*
+ * Lock a terminal up until the given key is entered or the given
+ * interval times out.
+ *
+ * Timeout interval is by default TIMEOUT, it can be changed with
+ * an argument of the form -time where time is in minutes
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/consio.h>
+
+#include <err.h>
+#include <ctype.h>
+#include <errno.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+#include <security/openpam.h> /* for openpam_ttyconv() */
+
+#define TIMEOUT 15
+
+static void quit(int);
+static void bye(int);
+static void hi(int);
+static void usage(void) __dead2;
+
+static struct timeval timeout;
+static struct timeval zerotime;
+static struct termios tty, ntty;
+static long nexttime; /* keep the timeout time */
+static int no_timeout; /* lock terminal forever */
+static int vtyunlock; /* Unlock flag and code. */
+
+/*ARGSUSED*/
+int
+main(int argc, char **argv)
+{
+ static const struct pam_conv pamc = { &openpam_ttyconv, NULL };
+ pam_handle_t *pamh;
+ struct passwd *pw;
+ struct itimerval ntimer, otimer;
+ struct tm *timp;
+ time_t timval;
+ int ch, failures, pam_err, sectimeout, usemine, vtylock;
+ char *ap, *ttynam, *tzn;
+ char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ];
+
+ openlog("lock", 0, LOG_AUTH);
+
+ pam_err = PAM_SYSTEM_ERR; /* pacify GCC */
+
+ sectimeout = TIMEOUT;
+ pamh = NULL;
+ pw = NULL;
+ usemine = 0;
+ no_timeout = 0;
+ vtylock = 0;
+ while ((ch = getopt(argc, argv, "npt:v")) != -1)
+ switch((char)ch) {
+ case 't':
+ if ((sectimeout = atoi(optarg)) <= 0)
+ errx(1, "illegal timeout value");
+ break;
+ case 'p':
+ usemine = 1;
+ if (!(pw = getpwuid(getuid())))
+ errx(1, "unknown uid %d", getuid());
+ break;
+ case 'n':
+ no_timeout = 1;
+ break;
+ case 'v':
+ vtylock = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ timeout.tv_sec = sectimeout * 60;
+
+ if (!usemine) { /* -p with PAM or S/key needs privs */
+ /* discard privs */
+ if (setuid(getuid()) != 0)
+ errx(1, "setuid failed");
+ }
+
+ if (tcgetattr(0, &tty)) /* get information for header */
+ exit(1);
+ gethostname(hostname, sizeof(hostname));
+ if (!(ttynam = ttyname(0)))
+ errx(1, "not a terminal?");
+ if (strncmp(ttynam, _PATH_DEV, strlen(_PATH_DEV)) == 0)
+ ttynam += strlen(_PATH_DEV);
+ timval = time(NULL);
+ nexttime = timval + (sectimeout * 60);
+ timp = localtime(&timval);
+ ap = asctime(timp);
+ tzn = timp->tm_zone;
+
+ (void)signal(SIGINT, quit);
+ (void)signal(SIGQUIT, quit);
+ ntty = tty; ntty.c_lflag &= ~ECHO;
+ (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &ntty);
+
+ if (usemine) {
+ pam_err = pam_start("lock", pw->pw_name, &pamc, &pamh);
+ if (pam_err != PAM_SUCCESS)
+ err(1, "pam_start: %s", pam_strerror(NULL, pam_err));
+ } else {
+ /* get key and check again */
+ (void)printf("Key: ");
+ if (!fgets(s, sizeof(s), stdin) || *s == '\n')
+ quit(0);
+ (void)printf("\nAgain: ");
+ /*
+ * Don't need EOF test here, if we get EOF, then s1 != s
+ * and the right things will happen.
+ */
+ (void)fgets(s1, sizeof(s1), stdin);
+ (void)putchar('\n');
+ if (strcmp(s1, s)) {
+ (void)printf("\07lock: passwords didn't match.\n");
+ (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty);
+ exit(1);
+ }
+ s[0] = '\0';
+ }
+
+ /* set signal handlers */
+ (void)signal(SIGINT, hi);
+ (void)signal(SIGQUIT, hi);
+ (void)signal(SIGTSTP, hi);
+ (void)signal(SIGALRM, bye);
+
+ ntimer.it_interval = zerotime;
+ ntimer.it_value = timeout;
+ if (!no_timeout)
+ setitimer(ITIMER_REAL, &ntimer, &otimer);
+ if (vtylock) {
+ /*
+ * If this failed, we want to err out; warn isn't good
+ * enough, since we don't want the user to think that
+ * everything is nice and locked because they got a
+ * "Key:" prompt.
+ */
+ if (ioctl(0, VT_LOCKSWITCH, &vtylock) == -1) {
+ (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty);
+ err(1, "locking vty");
+ }
+ vtyunlock = 0x2;
+ }
+
+ /* header info */
+ if (pw != NULL)
+ (void)printf("lock: %s using %s on %s.", pw->pw_name,
+ ttynam, hostname);
+ else
+ (void)printf("lock: %s on %s.", ttynam, hostname);
+ if (no_timeout)
+ (void)printf(" no timeout.");
+ else
+ (void)printf(" timeout in %d minute%s.", sectimeout,
+ sectimeout != 1 ? "s" : "");
+ if (vtylock)
+ (void)printf(" vty locked.");
+ (void)printf("\ntime now is %.20s%s%s", ap, tzn, ap + 19);
+
+ failures = 0;
+
+ for (;;) {
+ if (usemine) {
+ pam_err = pam_authenticate(pamh, 0);
+ if (pam_err == PAM_SUCCESS)
+ break;
+
+ if (pam_err != PAM_AUTH_ERR &&
+ pam_err != PAM_USER_UNKNOWN &&
+ pam_err != PAM_MAXTRIES) {
+ syslog(LOG_ERR, "pam_authenticate: %s",
+ pam_strerror(pamh, pam_err));
+ }
+
+ goto tryagain;
+ }
+ (void)printf("Key: ");
+ if (!fgets(s, sizeof(s), stdin)) {
+ clearerr(stdin);
+ hi(0);
+ goto tryagain;
+ }
+ if (!strcmp(s, s1))
+ break;
+ (void)printf("\07\n");
+ failures++;
+ if (getuid() == 0)
+ syslog(LOG_NOTICE, "%d ROOT UNLOCK FAILURE%s (%s on %s)",
+ failures, failures > 1 ? "S": "", ttynam, hostname);
+tryagain:
+ if (tcgetattr(0, &ntty) && (errno != EINTR))
+ exit(1);
+ sleep(1); /* to discourage guessing */
+ }
+ if (getuid() == 0)
+ syslog(LOG_NOTICE, "ROOT UNLOCK ON hostname %s port %s",
+ hostname, ttynam);
+ if (usemine)
+ (void)pam_end(pamh, pam_err);
+ quit(0);
+ return(0); /* not reached */
+}
+
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: lock [-npv] [-t timeout]\n");
+ exit(1);
+}
+
+static void
+hi(int signo __unused)
+{
+ time_t timval;
+
+ timval = time(NULL);
+ (void)printf("lock: type in the unlock key. ");
+ if (no_timeout) {
+ (void)putchar('\n');
+ } else {
+ (void)printf("timeout in %jd:%jd minutes\n",
+ (intmax_t)(nexttime - timval) / 60,
+ (intmax_t)(nexttime - timval) % 60);
+ }
+}
+
+static void
+quit(int signo __unused)
+{
+ (void)putchar('\n');
+ (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty);
+ if (vtyunlock)
+ (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock);
+ exit(0);
+}
+
+static void
+bye(int signo __unused)
+{
+ if (!no_timeout) {
+ (void)tcsetattr(0, TCSADRAIN|TCSASOFT, &tty);
+ if (vtyunlock)
+ (void)ioctl(0, VT_LOCKSWITCH, &vtyunlock);
+ (void)printf("lock: timeout\n");
+ exit(1);
+ }
+}
diff --git a/usr.bin/lockf/Makefile b/usr.bin/lockf/Makefile
new file mode 100644
index 000000000000..36740dbd3a95
--- /dev/null
+++ b/usr.bin/lockf/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= lockf
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lockf/Makefile.depend b/usr.bin/lockf/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/lockf/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lockf/lockf.1 b/usr.bin/lockf/lockf.1
new file mode 100644
index 000000000000..d73033101632
--- /dev/null
+++ b/usr.bin/lockf/lockf.1
@@ -0,0 +1,260 @@
+.\"
+.\" Copyright (C) 1998 John D. Polstra. 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY JOHN D. POLSTRA 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 JOHN D. POLSTRA 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 November 25, 2023
+.Dt LOCKF 1
+.Os
+.Sh NAME
+.Nm lockf
+.Nd execute a command while holding a file lock
+.Sh SYNOPSIS
+.Nm
+.Op Fl knsw
+.Op Fl t Ar seconds
+.Ar file
+.Ar command
+.Op Ar arguments
+.Nm
+.Op Fl s
+.Op Fl t Ar seconds
+.Ar fd
+.Sh DESCRIPTION
+The
+.Nm
+utility acquires an exclusive lock on a
+.Ar file ,
+creating it if necessary,
+.Bf Em
+and removing the file on exit unless explicitly told not to.
+.Ef
+While holding the lock, it executes a
+.Ar command
+with optional
+.Ar arguments .
+After the
+.Ar command
+completes,
+.Nm
+releases the lock, and removes the
+.Ar file
+unless the
+.Fl k
+option is specified.
+.Bx Ns -style
+locking is used, as described in
+.Xr flock 2 ;
+the mere existence of the
+.Ar file
+is not considered to constitute a lock.
+.Pp
+.Nm
+may also be used to operate on a file descriptor instead of a file.
+If no
+.Ar command
+is supplied, then
+.Ar fd
+must be a file descriptor.
+The version with a
+.Ar command
+may also be used with a file descriptor by supplying it as a path
+.Pa /dev/fd/N ,
+where N is the desired file descriptor.
+The
+.Fl k
+option is implied when a file descriptor is in use, and the
+.Fl n
+and
+.Fl w
+options are silently ignored.
+This can be used to lock inside a shell script.
+.Pp
+If the
+.Nm
+utility is being used to facilitate concurrency between a number
+of processes, it is recommended that the
+.Fl k
+option be used.
+This will guarantee lock ordering, as well as implement
+a performance enhanced algorithm which minimizes CPU load associated
+with concurrent unlink, drop and re-acquire activity.
+It should be noted
+that if the
+.Fl k
+option is not used, then no guarantees around lock ordering can be made.
+.Pp
+The following options are supported:
+.Bl -tag -width ".Fl t Ar seconds"
+.It Fl k
+Causes the lock file to be kept (not removed) after the command
+completes.
+.It Fl s
+Causes
+.Nm
+to operate silently.
+Failure to acquire the lock is indicated only in the exit status.
+.It Fl n
+Causes
+.Nm
+to fail if the specified lock
+.Ar file
+does not exist.
+If
+.Fl n
+is not specified,
+.Nm
+will create
+.Ar file
+if necessary.
+.It Fl t Ar seconds
+Specifies a timeout for waiting for the lock.
+By default,
+.Nm
+waits indefinitely to acquire the lock.
+If a timeout is specified with this option,
+.Nm
+will wait at most the given number of
+.Ar seconds
+before giving up.
+A timeout of 0 may be given, in which case
+.Nm
+will fail unless it can acquire the lock immediately.
+When a lock times out,
+.Ar command
+is
+.Em not
+executed.
+.It Fl w
+Causes
+.Nm
+to open
+.Ar file
+for writing rather than reading.
+This is necessary on filesystems (including NFSv4) where a file which
+has been opened read-only cannot be exclusively locked.
+.El
+.Pp
+In no event will
+.Nm
+break a lock that is held by another process.
+.Sh EXIT STATUS
+If
+.Nm
+successfully acquires the lock, it returns the exit status produced by
+.Ar command .
+Otherwise, it returns one of the exit codes defined in
+.Xr sysexits 3 ,
+as follows:
+.Bl -tag -width ".Dv EX_CANTCREAT"
+.It Dv EX_TEMPFAIL
+The specified lock file was already locked by another process.
+.It Dv EX_CANTCREAT
+The
+.Nm
+utility
+was unable to create the lock file, e.g., because of insufficient access
+privileges.
+.It Dv EX_UNAVAILABLE
+The
+.Fl n
+option is specified and the specified lock file does not exist.
+.It Dv EX_USAGE
+There was an error on the
+.Nm
+command line.
+.It Dv EX_OSERR
+A system call (e.g.,
+.Xr fork 2 )
+failed unexpectedly.
+.It Dv EX_SOFTWARE
+The
+.Ar command
+did not exit normally,
+but may have been signaled or stopped.
+.El
+.Sh EXAMPLES
+The first job takes a lock and sleeps for 5 seconds in the background.
+The second job tries to get the lock and timeouts after 1 second (PID numbers
+will differ):
+.Bd -literal -offset indent
+$ lockf mylock sleep 5 & lockf -t 1 mylock echo "Success"
+[1] 94410
+lockf: mylock: already locked
+.Ed
+.Pp
+The first job takes a lock and sleeps for 1 second in the background.
+The second job waits up to 5 seconds to take the lock and echoes the message on
+success (PID numbers will differ):
+.Bd -literal -offset indent
+$ lockf mylock sleep 1 & lockf -t 5 mylock echo "Success"
+[1] 19995
+Success
+[1]+ Done lockf mylock sleep 1
+.Ed
+Lock a file and run a script, return immediately if the lock is not
+available. Do not delete the file afterward so lock order is
+guaranteed.
+.Pp
+.Dl $ lockf -t 0 -k /tmp/my.lock myscript
+.Pp
+Protect a section of a shell script with a lock, wait up to 5 seconds
+for it to become available.
+Note that the shell script has opened the lock file
+.Fa /tmp/my.lock ,
+and
+.Nm
+is performing the lock call exclusively via the passed in file descriptor (9).
+In this case
+.Fl k
+is implied, and
+.Fl w
+has no effect because the file has already been opened by the shell.
+This example assumes that
+.Ql >
+is implemented in the shell by opening and truncating
+.Pa /tmp/my.lock ,
+rather than by replacing the lock file.
+.Bd -literal -offset indent
+(
+ lockf -s -t 5 9
+ if [ $? -ne 0 ]; then
+ echo "Failed to obtain lock"
+ exit 1
+ fi
+
+ echo Start
+ # Do some stuff
+ echo End
+) 9>/tmp/my.lock
+.Ed
+.Sh SEE ALSO
+.Xr flock 2 ,
+.Xr lockf 3 ,
+.Xr sysexits 3
+.Sh HISTORY
+A
+.Nm
+utility first appeared in
+.Fx 2.2 .
+.Sh AUTHORS
+.An John Polstra Aq Mt jdp@polstra.com
diff --git a/usr.bin/lockf/lockf.c b/usr.bin/lockf/lockf.c
new file mode 100644
index 000000000000..7f88753d1743
--- /dev/null
+++ b/usr.bin/lockf/lockf.c
@@ -0,0 +1,352 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 1997 John D. Polstra. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN D. POLSTRA 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 JOHN D. POLSTRA 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/wait.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#define FDLOCK_PREFIX "/dev/fd/"
+
+union lock_subject {
+ long subj_fd;
+ const char *subj_name;
+};
+
+static int acquire_lock(union lock_subject *subj, int flags, int silent);
+static void cleanup(void);
+static void killed(int sig);
+static void timeout(int sig);
+static void usage(void) __dead2;
+static void wait_for_lock(const char *name);
+
+static const char *lockname;
+static int lockfd = -1;
+static int keep;
+static int fdlock;
+static volatile sig_atomic_t timed_out;
+
+/*
+ * Check if fdlock is implied by the given `lockname`. We'll write the fd that
+ * is represented by it out to ofd, and the caller is expected to do any
+ * necessary validation on it.
+ */
+static int
+fdlock_implied(const char *name, long *ofd)
+{
+ char *endp;
+ long fd;
+
+ if (strncmp(name, FDLOCK_PREFIX, sizeof(FDLOCK_PREFIX) - 1) != 0)
+ return (0);
+
+ /* Skip past the prefix. */
+ name += sizeof(FDLOCK_PREFIX) - 1;
+ errno = 0;
+ fd = strtol(name, &endp, 10);
+ if (errno != 0 || *endp != '\0')
+ return (0);
+
+ *ofd = fd;
+ return (1);
+}
+
+/*
+ * Execute an arbitrary command while holding a file lock.
+ */
+int
+main(int argc, char **argv)
+{
+ int ch, flags, silent, status;
+ long long waitsec;
+ pid_t child;
+ union lock_subject subj;
+
+ silent = keep = 0;
+ flags = O_CREAT | O_RDONLY;
+ waitsec = -1; /* Infinite. */
+ while ((ch = getopt(argc, argv, "knst:w")) != -1) {
+ switch (ch) {
+ case 'k':
+ keep = 1;
+ break;
+ case 'n':
+ flags &= ~O_CREAT;
+ break;
+ case 's':
+ silent = 1;
+ break;
+ case 't':
+ {
+ const char *errstr;
+
+ waitsec = strtonum(optarg, 0, UINT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(EX_USAGE,
+ "invalid timeout \"%s\"", optarg);
+ }
+ break;
+ case 'w':
+ flags = (flags & ~O_RDONLY) | O_WRONLY;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+
+ lockname = argv[0];
+
+ argc--;
+ argv++;
+
+ /*
+ * If there aren't any arguments left, then we must be in fdlock mode.
+ */
+ if (argc == 0 && *lockname != '/') {
+ fdlock = 1;
+ subj.subj_fd = -1;
+ } else {
+ fdlock = fdlock_implied(lockname, &subj.subj_fd);
+ if (argc == 0 && !fdlock) {
+ fprintf(stderr, "Expected fd, got '%s'\n", lockname);
+ usage();
+ }
+ }
+
+ if (fdlock) {
+ if (subj.subj_fd < 0) {
+ char *endp;
+
+ errno = 0;
+ subj.subj_fd = strtol(lockname, &endp, 10);
+ if (errno != 0 || *endp != '\0') {
+ fprintf(stderr, "Expected fd, got '%s'\n",
+ lockname);
+ usage();
+ }
+ }
+
+ if (subj.subj_fd < 0 || subj.subj_fd > INT_MAX) {
+ fprintf(stderr, "fd '%ld' out of range\n",
+ subj.subj_fd);
+ usage();
+ }
+ } else {
+ subj.subj_name = lockname;
+ }
+
+ if (waitsec > 0) { /* Set up a timeout. */
+ struct sigaction act;
+
+ act.sa_handler = timeout;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0; /* Note that we do not set SA_RESTART. */
+ sigaction(SIGALRM, &act, NULL);
+ alarm((unsigned int)waitsec);
+ }
+ /*
+ * If the "-k" option is not given, then we must not block when
+ * acquiring the lock. If we did, then the lock holder would
+ * unlink the file upon releasing the lock, and we would acquire
+ * a lock on a file with no directory entry. Then another
+ * process could come along and acquire the same lock. To avoid
+ * this problem, we separate out the actions of waiting for the
+ * lock to be available and of actually acquiring the lock.
+ *
+ * That approach produces behavior that is technically correct;
+ * however, it causes some performance & ordering problems for
+ * locks that have a lot of contention. First, it is unfair in
+ * the sense that a released lock isn't necessarily granted to
+ * the process that has been waiting the longest. A waiter may
+ * be starved out indefinitely. Second, it creates a thundering
+ * herd situation each time the lock is released.
+ *
+ * When the "-k" option is used, the unlink race no longer
+ * exists. In that case we can block while acquiring the lock,
+ * avoiding the separate step of waiting for the lock. This
+ * yields fairness and improved performance.
+ */
+ lockfd = acquire_lock(&subj, flags | O_NONBLOCK, silent);
+ while (lockfd == -1 && !timed_out && waitsec != 0) {
+ if (keep || fdlock)
+ lockfd = acquire_lock(&subj, flags, silent);
+ else {
+ wait_for_lock(lockname);
+ lockfd = acquire_lock(&subj, flags | O_NONBLOCK,
+ silent);
+ }
+ }
+ if (waitsec > 0)
+ alarm(0);
+ if (lockfd == -1) { /* We failed to acquire the lock. */
+ if (silent)
+ exit(EX_TEMPFAIL);
+ errx(EX_TEMPFAIL, "%s: already locked", lockname);
+ }
+
+ /* At this point, we own the lock. */
+
+ /* Nothing else to do for FD lock, just exit */
+ if (argc == 0) {
+ assert(fdlock);
+ return 0;
+ }
+
+ if (atexit(cleanup) == -1)
+ err(EX_OSERR, "atexit failed");
+ if ((child = fork()) == -1)
+ err(EX_OSERR, "cannot fork");
+ if (child == 0) { /* The child process. */
+ close(lockfd);
+ execvp(argv[0], argv);
+ warn("%s", argv[0]);
+ _exit(1);
+ }
+ /* This is the parent process. */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, killed);
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+ if (waitpid(child, &status, 0) == -1)
+ exit(EX_OSERR);
+ return (WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE);
+}
+
+/*
+ * Try to acquire a lock on the given file/fd, creating the file if
+ * necessary. The flags argument is O_NONBLOCK or 0, depending on
+ * whether we should wait for the lock. Returns an open file descriptor
+ * on success, or -1 on failure.
+ */
+static int
+acquire_lock(union lock_subject *subj, int flags, int silent)
+{
+ int fd;
+
+ if (fdlock) {
+ assert(subj->subj_fd >= 0 && subj->subj_fd <= INT_MAX);
+ fd = (int)subj->subj_fd;
+
+ if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return (-1);
+ err(EX_CANTCREAT, "cannot lock fd %d", fd);
+ }
+ } else if ((fd = open(subj->subj_name, O_EXLOCK|flags, 0666)) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return (-1);
+ else if (errno == ENOENT && (flags & O_CREAT) == 0) {
+ if (!silent)
+ warn("%s", subj->subj_name);
+ exit(EX_UNAVAILABLE);
+ }
+ err(EX_CANTCREAT, "cannot open %s", subj->subj_name);
+ }
+ return (fd);
+}
+
+/*
+ * Remove the lock file.
+ */
+static void
+cleanup(void)
+{
+
+ if (keep || fdlock)
+ flock(lockfd, LOCK_UN);
+ else
+ unlink(lockname);
+}
+
+/*
+ * Signal handler for SIGTERM. Cleans up the lock file, then re-raises
+ * the signal.
+ */
+static void
+killed(int sig)
+{
+
+ cleanup();
+ signal(sig, SIG_DFL);
+ if (kill(getpid(), sig) == -1)
+ _Exit(EX_OSERR);
+}
+
+/*
+ * Signal handler for SIGALRM.
+ */
+static void
+timeout(int sig __unused)
+{
+
+ timed_out = 1;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: lockf [-knsw] [-t seconds] file command [arguments]\n"
+ " lockf [-s] [-t seconds] fd\n");
+ exit(EX_USAGE);
+}
+
+/*
+ * Wait until it might be possible to acquire a lock on the given file.
+ * If the file does not exist, return immediately without creating it.
+ */
+static void
+wait_for_lock(const char *name)
+{
+ int fd;
+
+ if ((fd = open(name, O_RDONLY|O_EXLOCK, 0666)) == -1) {
+ if (errno == ENOENT || errno == EINTR)
+ return;
+ err(EX_CANTCREAT, "cannot open %s", name);
+ }
+ close(fd);
+}
diff --git a/usr.bin/lockf/tests/Makefile b/usr.bin/lockf/tests/Makefile
new file mode 100644
index 000000000000..a7c6f45290c9
--- /dev/null
+++ b/usr.bin/lockf/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= lockf_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/lockf/tests/Makefile.depend b/usr.bin/lockf/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/lockf/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lockf/tests/lockf_test.sh b/usr.bin/lockf/tests/lockf_test.sh
new file mode 100644
index 000000000000..d73c7590653d
--- /dev/null
+++ b/usr.bin/lockf/tests/lockf_test.sh
@@ -0,0 +1,241 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023 Klara, 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+# sysexits(3)
+: ${EX_USAGE:=64}
+: ${EX_UNAVAILABLE:=69}
+: ${EX_CANTCREAT:=73}
+: ${EX_TEMPFAIL:=75}
+
+atf_test_case badargs
+badargs_body()
+{
+ atf_check -s exit:${EX_USAGE} -e not-empty lockf
+ atf_check -s exit:${EX_USAGE} -e not-empty lockf "testlock"
+}
+
+atf_test_case basic
+basic_body()
+{
+ # Something innocent so that it does eventually go away without our
+ # intervention.
+ lockf "testlock" sleep 10 &
+ lpid=$!
+
+ # Make sure that the lock exists...
+ while ! test -e "testlock"; do
+ sleep 0.1
+ done
+
+ # Attempt both verbose and silent re-lock
+ atf_check -s exit:${EX_TEMPFAIL} -e not-empty \
+ lockf -t 0 "testlock" sleep 0
+ atf_check -s exit:${EX_TEMPFAIL} -e empty \
+ lockf -t 0 -s "testlock" sleep 0
+
+ # Make sure it cleans up after the initial sleep 10 is over.
+ wait "$lpid"
+ atf_check test ! -e "testlock"
+}
+
+atf_test_case fdlock
+fdlock_body()
+{
+ # First, make sure we don't get a false positive -- existing uses with
+ # numeric filenames shouldn't switch to being fdlocks automatically.
+ atf_check lockf -k "9" sleep 0
+ atf_check test -e "9"
+ rm "9"
+
+ subexit_lockfail=1
+ subexit_created=2
+ subexit_lockok=3
+ subexit_concurrent=4
+ (
+ lockf -s -t 0 9
+ if [ $? -ne 0 ]; then
+ exit "$subexit_lockfail"
+ fi
+
+ if [ -e "9" ]; then
+ exit "$subexit_created"
+ fi
+ ) 9> "testlock1"
+ rc=$?
+
+ atf_check test "$rc" -eq 0
+
+ sub_delay=5
+
+ # But is it actually locking? Child 1 will acquire the lock and then
+ # signal that it's ok for the second child to try. The second child
+ # will try to acquire the lock and fail immediately, signal that it
+ # tried, then try again with an indefinite timeout. On that one, we'll
+ # just check how long we ended up waiting -- it should be at least
+ # $sub_delay.
+ (
+ lockf -s -t 0 /dev/fd/9
+ if [ $? -ne 0 ]; then
+ exit "$subexit_lockfail"
+ fi
+
+ # Signal
+ touch ".lock_acquired"
+
+ while [ ! -e ".lock_attempted" ]; do
+ sleep 0.5
+ done
+
+ sleep "$sub_delay"
+
+ if [ -e ".lock_acquired_again" ]; then
+ exit "$subexit_concurrent"
+ fi
+ ) 9> "testlock2" &
+ lpid1=$!
+
+ (
+ while [ ! -e ".lock_acquired" ]; do
+ sleep 0.5
+ done
+
+ # Got the signal, try
+ lockf -s -t 0 9
+ if [ $? -ne "${EX_TEMPFAIL}" ]; then
+ exit "$subexit_lockok"
+ fi
+
+ touch ".lock_attempted"
+ start=$(date +"%s")
+ lockf -s 9
+ touch ".lock_acquired_again"
+ now=$(date +"%s")
+ elapsed=$((now - start))
+
+ if [ "$elapsed" -lt "$sub_delay" ]; then
+ exit "$subexit_concurrent"
+ fi
+ ) 9> "testlock2" &
+ lpid2=$!
+
+ wait "$lpid1"
+ status1=$?
+
+ wait "$lpid2"
+ status2=$?
+
+ atf_check test "$status1" -eq 0
+ atf_check test "$status2" -eq 0
+}
+
+atf_test_case keep
+keep_body()
+{
+ lockf -k "testlock" sleep 10 &
+ lpid=$!
+
+ # Make sure that the lock exists now...
+ while ! test -e "testlock"; do
+ sleep 0.5
+ done
+
+ kill "$lpid"
+ wait "$lpid"
+
+ # And it still exits after the lock has been relinquished.
+ atf_check test -e "testlock"
+}
+
+atf_test_case needfile
+needfile_body()
+{
+ # Hopefully the clock doesn't jump.
+ start=$(date +"%s")
+
+ # Should fail if the lockfile does not yet exist.
+ atf_check -s exit:"${EX_UNAVAILABLE}" lockf -sn "testlock" sleep 30
+
+ # It's hard to guess how quickly we should have finished that; one would
+ # hope that it exits fast, but to be safe we specified a sleep 30 under
+ # lock so that we have a good margin below that duration that we can
+ # safely test to make sure we didn't actually execute the program, more
+ # or less.
+ now=$(date +"%s")
+ tpass=$((now - start))
+ atf_check test "$tpass" -lt 10
+}
+
+atf_test_case timeout
+timeout_body()
+{
+ lockf "testlock" sleep 30 &
+ lpid=$!
+
+ while ! test -e "testlock"; do
+ sleep 0.5
+ done
+
+ start=$(date +"%s")
+ timeout=2
+ atf_check -s exit:${EX_TEMPFAIL} lockf -st "$timeout" "testlock" sleep 0
+
+ # We should have taken no less than our timeout, at least.
+ now=$(date +"%s")
+ tpass=$((now - start))
+ atf_check test "$tpass" -ge "$timeout"
+
+ kill "$lpid"
+ wait "$lpid" || true
+}
+
+atf_test_case wrlock
+wrlock_head()
+{
+ atf_set "require.user" "unprivileged"
+}
+wrlock_body()
+{
+ touch "testlock"
+ chmod -w "testlock"
+
+ # Demonstrate that we can lock the file normally, but -w fails if we
+ # can't write.
+ atf_check lockf -kt 0 "testlock" sleep 0
+ atf_check -s exit:${EX_CANTCREAT} -e not-empty \
+ lockf -wt 0 "testlock" sleep 0
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case badargs
+ atf_add_test_case basic
+ atf_add_test_case fdlock
+ atf_add_test_case keep
+ atf_add_test_case needfile
+ atf_add_test_case timeout
+ atf_add_test_case wrlock
+}
diff --git a/usr.bin/logger/Makefile b/usr.bin/logger/Makefile
new file mode 100644
index 000000000000..85870b85a4dc
--- /dev/null
+++ b/usr.bin/logger/Makefile
@@ -0,0 +1,17 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= logger
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_syslog
+CFLAGS+=-DWITH_CASPER
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/logger/Makefile.depend b/usr.bin/logger/Makefile.depend
new file mode 100644
index 000000000000..30bbe05ce056
--- /dev/null
+++ b/usr.bin/logger/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcasper/services/cap_syslog \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/logger/logger.1 b/usr.bin/logger/logger.1
new file mode 100644
index 000000000000..e117df33a165
--- /dev/null
+++ b/usr.bin/logger/logger.1
@@ -0,0 +1,181 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd July 3, 2023
+.Dt LOGGER 1
+.Os
+.Sh NAME
+.Nm logger
+.Nd make entries in the system log
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46Ais
+.Op Fl f Ar file
+.Op Fl H Ar hostname
+.Op Fl h Ar host
+.Op Fl P Ar port
+.Op Fl p Ar pri
+.Op Fl S Ar addr Ns \&: Ns Ar port
+.Op Fl t Ar tag
+.Op Ar message ...
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a shell command interface to the
+.Xr syslog 3
+system log module.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl 4
+Force
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Force
+.Nm
+to use IPv6 addresses only.
+.It Fl A
+By default,
+.Nm
+tries to send the message to only one address,
+even if the host has more than one A or AAAA record.
+If this option is specified,
+.Nm
+tries to send the message to all addresses.
+.It Fl i
+Log the process id of the logger process
+with each line.
+This flag is ignored and the process id is always logged.
+See also
+.Fl t .
+.It Fl s
+Log the message to standard error, as well as the system log.
+.It Fl f Ar file
+Read the contents of the specified file into syslog.
+This option is ignored when a message is also specified.
+.It Fl H Ar hostname
+Set the hostname in the header of the message to specified value.
+If not specified, host part of
+.Xr gethostname 3
+will be used.
+.It Fl h Ar host
+Send the message to the remote system
+.Ar host
+instead of logging it locally.
+Note that
+.Nm
+currently supports
+.Li AF_INET
+.Pq IPv4 ,
+.Li AF_INET6
+.Pq IPv6 ,
+and
+.Li AF_LOCAL
+.Pq Unix-domain socket
+address families.
+The following address formats are valid in
+.Ar host :
+.Pp
+.Bl -tag -width "AF_LOCAL" -compact
+.It Li AF_INET
+192.168.2.1
+.It Li AF_INET6
+2001:db8::1
+.It Li AF_LOCAL
+.Pa /var/run/log
+.El
+.It Fl P Ar port
+Send the message to the specified
+.Ar port
+number on a remote system,
+which can be specified as a service name
+or as a decimal number.
+The default is
+.Dq Li syslog .
+If an unknown service name is used,
+.Nm
+prints a warning and falls back to port 514.
+.It Fl p Ar pri
+Enter the message with the specified priority.
+The priority may be specified numerically or as a
+.Li facility.level
+pair.
+For example,
+.Dq Fl p Li local3.info
+logs the message(s) as
+.Ar info Ns rmational
+level in the
+.Ar local3
+facility.
+The default is
+.Dq Li user.notice .
+.It Fl S Ar addr Ns \&: Ns Ar port
+Specify source address and/or source port when using
+.Fl h
+option.
+The same address will be used for all of the remote addresses
+when
+.Fl A
+flag is enabled.
+Note that a numeric IPv6 address in
+.Ar addr
+must be enclosed with
+.Dq \&[
+and
+.Dq \&] .
+.It Fl t Ar tag
+Mark every line in the log with the specified
+.Ar tag
+rather than the default of current login name.
+Use
+.Fl t Ar tag[N]
+to insert specific decimal process id instead of id of
+.Nm .
+.It Ar message
+Write the message to log; if not specified, and the
+.Fl f
+flag is not
+provided, standard input is logged.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Bd -literal -offset indent -compact
+logger System rebooted
+
+logger \-p local0.notice \-t HOSTIDM \-f /dev/idmc
+.Ed
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr syslogd 8
+.Sh STANDARDS
+The
+.Nm
+command is expected to be
+.St -p1003.2
+compatible.
diff --git a/usr.bin/logger/logger.c b/usr.bin/logger/logger.c
new file mode 100644
index 000000000000..d16f387291e6
--- /dev/null
+++ b/usr.bin/logger/logger.c
@@ -0,0 +1,440 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_syslog.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+
+#define sstosa(ss) ((struct sockaddr *)(void *)ss)
+
+struct socks {
+ int sk_sock;
+ int sk_addrlen;
+ struct sockaddr_storage sk_addr;
+};
+
+static int decode(char *, const CODE *);
+static int pencode(char *);
+static ssize_t socksetup(const char *, const char *, const char *,
+ struct socks **);
+static void logmessage(int, const char *, const char *, const char *,
+ struct socks *, ssize_t, const char *);
+static void usage(void);
+
+static cap_channel_t *capsyslog;
+#ifdef INET6
+static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
+#else
+static int family = PF_INET; /* protocol family (IPv4 only) */
+#endif
+static int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
+
+/*
+ * logger -- read and log utility
+ *
+ * Reads from an input and arranges to write the result on the system
+ * log.
+ */
+int
+main(int argc, char *argv[])
+{
+ cap_channel_t *capcas;
+ struct socks *socks;
+ ssize_t nsock;
+ time_t now;
+ int ch, logflags, pri;
+ char *tag, *host, buf[1024], *timestamp, tbuf[26],
+ *hostname, hbuf[MAXHOSTNAMELEN], *pristr;
+ const char *svcname, *src;
+
+ tag = NULL;
+ host = NULL;
+ hostname = NULL;
+ svcname = "syslog";
+ src = NULL;
+ socks = NULL;
+ pri = LOG_USER | LOG_NOTICE;
+ pristr = NULL;
+ logflags = 0;
+ unsetenv("TZ");
+ while ((ch = getopt(argc, argv, "46Af:H:h:iP:p:S:st:")) != -1)
+ switch((char)ch) {
+ case '4':
+ family = PF_INET;
+ break;
+#ifdef INET6
+ case '6':
+ family = PF_INET6;
+ break;
+#endif
+ case 'A':
+ send_to_all++;
+ break;
+ case 'f': /* file to log */
+ if (freopen(optarg, "r", stdin) == NULL)
+ err(1, "%s", optarg);
+ setvbuf(stdin, 0, _IONBF, 0);
+ break;
+ case 'H': /* hostname to set in message header */
+ hostname = optarg;
+ break;
+ case 'h': /* hostname to deliver to */
+ host = optarg;
+ break;
+ case 'i': /* log process id also */
+ logflags |= LOG_PID;
+ break;
+ case 'P': /* service name or port number */
+ svcname = optarg;
+ break;
+ case 'p': /* priority */
+ pristr = optarg;
+ break;
+ case 's': /* log to standard error */
+ logflags |= LOG_PERROR;
+ break;
+ case 'S': /* source address */
+ src = optarg;
+ break;
+ case 't': /* tag */
+ tag = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (host) {
+ nsock = socksetup(src, host, svcname, &socks);
+ if (nsock <= 0)
+ errx(1, "socket");
+ } else {
+ if (src)
+ errx(1, "-h option is missing.");
+ nsock = 0;
+ }
+
+ capcas = cap_init();
+ if (capcas == NULL)
+ err(1, "Unable to contact Casper");
+ caph_cache_catpages();
+ caph_cache_tzdata();
+ if (nsock == 0) {
+ if (caph_enter_casper() < 0)
+ err(1, "Unable to enter capability mode");
+ }
+ capsyslog = cap_service_open(capcas, "system.syslog");
+ if (capsyslog == NULL)
+ err(1, "Unable to open system.syslog service");
+ cap_close(capcas);
+
+ if (pristr != NULL)
+ pri = pencode(pristr);
+ if (tag == NULL)
+ tag = getlogin();
+ /* setup for logging */
+ if (host == NULL)
+ cap_openlog(capsyslog, tag, logflags, 0);
+
+ if (hostname == NULL) {
+ hostname = hbuf;
+ (void )gethostname(hbuf, MAXHOSTNAMELEN);
+ *strchrnul(hostname, '.') = '\0';
+ }
+
+ timestamp = tbuf + 4;
+
+ /* log input line if appropriate */
+ if (argc > 0) {
+ char *p, *endp;
+ size_t len;
+
+ (void )time(&now);
+ (void )ctime_r(&now, tbuf);
+ tbuf[19] = '\0';
+
+ for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
+ len = strlen(*argv);
+ if (p + len > endp && p > buf) {
+ logmessage(pri, timestamp, hostname, tag,
+ socks, nsock, buf);
+ p = buf;
+ }
+ if (len > sizeof(buf) - 1)
+ logmessage(pri, timestamp, hostname, tag,
+ socks, nsock, *argv++);
+ else {
+ if (p != buf)
+ *p++ = ' ';
+ bcopy(*argv++, p, len);
+ *(p += len) = '\0';
+ }
+ }
+ if (p != buf)
+ logmessage(pri, timestamp, hostname, tag, socks, nsock,
+ buf);
+ } else
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ (void )time(&now);
+ (void )ctime_r(&now, tbuf);
+ tbuf[19] = '\0';
+
+ logmessage(pri, timestamp, hostname, tag, socks, nsock,
+ buf);
+ }
+ exit(0);
+}
+
+static ssize_t
+socksetup(const char *src, const char *dst, const char *svcname,
+ struct socks **socks)
+{
+ struct addrinfo hints, *res, *res0;
+ struct sockaddr_storage *ss_src[AF_MAX];
+ struct socks *sk;
+ ssize_t nsock = 0;
+ int error, maxs;
+
+ memset(&ss_src[0], 0, sizeof(ss_src));
+ if (src) {
+ char *p, *p0, *hs, *hbuf, *sbuf;
+
+ hbuf = sbuf = NULL;
+ p0 = p = strdup(src);
+ if (p0 == NULL)
+ err(1, "strdup failed");
+ hs = p0; /* point to search ":" */
+#ifdef INET6
+ /* -S option supports IPv6 addr in "[2001:db8::1]:service". */
+ if (*p0 == '[') {
+ p = strchr(p0, ']');
+ if (p == NULL)
+ errx(1, "\"]\" not found in src addr");
+ *p = '\0';
+ /* hs points just after ']' (':' or '\0'). */
+ hs = p + 1;
+ /*
+ * p points just after '[' while it points hs
+ * in the case of [].
+ */
+ p = ((p0 + 1) == (hs - 1)) ? hs : p0 + 1;
+ }
+#endif
+ if (*p != '\0') {
+ /* (p == hs) means ":514" or "[]:514". */
+ hbuf = (p == hs && *p == ':') ? NULL : p;
+ p = strchr(hs, ':');
+ if (p != NULL) {
+ *p = '\0';
+ sbuf = (*(p + 1) != '\0') ? p + 1 : NULL;
+ }
+ }
+ hints = (struct addrinfo){
+ .ai_family = family,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = AI_PASSIVE
+ };
+ error = getaddrinfo(hbuf, sbuf, &hints, &res0);
+ if (error)
+ errx(1, "%s: %s", gai_strerror(error), src);
+ for (res = res0; res; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ if (ss_src[res->ai_family] != NULL)
+ continue;
+ ss_src[res->ai_family] =
+ malloc(sizeof(struct sockaddr_storage));
+ if (ss_src[res->ai_family] == NULL)
+ err(1, "malloc failed");
+ memcpy(ss_src[res->ai_family], res->ai_addr,
+ res->ai_addrlen);
+ }
+ }
+ freeaddrinfo(res0);
+ free(p0);
+ }
+
+ /* resolve hostname */
+ hints = (struct addrinfo){
+ .ai_family = family,
+ .ai_socktype = SOCK_DGRAM
+ };
+ error = getaddrinfo(dst, svcname, &hints, &res0);
+ if (error == EAI_SERVICE) {
+ warnx("%s/udp: unknown service", svcname);
+ error = getaddrinfo(dst, "514", &hints, &res0);
+ }
+ if (error)
+ errx(1, "%s: %s", gai_strerror(error), dst);
+ /* count max number of sockets we may open */
+ maxs = 0;
+ for (res = res0; res; res = res->ai_next)
+ maxs++;
+ sk = calloc(maxs, sizeof(*sk));
+ if (sk == NULL)
+ errx(1, "couldn't allocate memory for sockets");
+ for (res = res0; res; res = res->ai_next) {
+ int s;
+
+ s = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (s < 0)
+ continue;
+ if (src && ss_src[res->ai_family] == NULL)
+ errx(1, "address family mismatch");
+
+ if (ss_src[res->ai_family]) {
+ error = bind(s, sstosa(ss_src[res->ai_family]),
+ ss_src[res->ai_family]->ss_len);
+ if (error < 0)
+ err(1, "bind");
+ }
+ sk[nsock] = (struct socks){
+ .sk_addrlen = res->ai_addrlen,
+ .sk_sock = s
+ };
+ memcpy(&sk[nsock].sk_addr, res->ai_addr, res->ai_addrlen);
+ nsock++;
+ }
+ freeaddrinfo(res0);
+
+ *socks = sk;
+ return (nsock);
+}
+
+/*
+ * Send the message to syslog, either on the local host, or on a remote host
+ */
+static void
+logmessage(int pri, const char *timestamp, const char *hostname,
+ const char *tag, struct socks *sk, ssize_t nsock, const char *buf)
+{
+ char *line;
+ int len, i, lsent;
+
+ if (nsock == 0) {
+ cap_syslog(capsyslog, pri, "%s", buf);
+ return;
+ }
+ if ((len = asprintf(&line, "<%d>%s %s %s: %s", pri, timestamp,
+ hostname, tag, buf)) == -1)
+ errx(1, "asprintf");
+
+ lsent = -1;
+ for (i = 0; i < nsock; i++) {
+ lsent = sendto(sk[i].sk_sock, line, len, 0,
+ sstosa(&sk[i].sk_addr), sk[i].sk_addrlen);
+ if (lsent == len && !send_to_all)
+ break;
+ }
+ if (lsent != len) {
+ if (lsent == -1)
+ warn("sendto");
+ else
+ warnx("sendto: short send - %d bytes", lsent);
+ }
+
+ free(line);
+}
+
+/*
+ * Decode a symbolic name to a numeric value
+ */
+static int
+pencode(char *s)
+{
+ char *save;
+ int fac, lev;
+
+ for (save = s; *s && *s != '.'; ++s);
+ if (*s) {
+ *s = '\0';
+ fac = decode(save, facilitynames);
+ if (fac < 0)
+ errx(1, "unknown facility name: %s", save);
+ *s++ = '.';
+ }
+ else {
+ fac = 0;
+ s = save;
+ }
+ lev = decode(s, prioritynames);
+ if (lev < 0)
+ errx(1, "unknown priority name: %s", save);
+ return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
+}
+
+static int
+decode(char *name, const CODE *codetab)
+{
+ const CODE *c;
+
+ if (isdigit(*name))
+ return (atoi(name));
+
+ for (c = codetab; c->c_name; c++)
+ if (!strcasecmp(name, c->c_name))
+ return (c->c_val);
+
+ return (-1);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s\n",
+ "logger [-46Ais] [-f file] [-h host] [-P port] [-p pri] [-t tag]\n"
+ " [-S addr:port] [message ...]"
+ );
+ exit(1);
+}
diff --git a/usr.bin/login/Makefile b/usr.bin/login/Makefile
new file mode 100644
index 000000000000..b88796e97691
--- /dev/null
+++ b/usr.bin/login/Makefile
@@ -0,0 +1,34 @@
+.include <src.opts.mk>
+.include <src.tools.mk>
+
+PACKAGE= runtime
+
+CONFS= fbtab login.conf motd.template login.access
+PROG= login
+SRCS= login.c login_fbtab.c
+CFLAGS+=-DLOGALL
+LIBADD= util pam
+
+WARNS?= 5
+
+.if ${MK_AUDIT} != "no"
+SRCS+= login_audit.c
+CFLAGS+= -DUSE_BSM_AUDIT
+LIBADD+= bsm
+.endif
+
+.if ${MK_SETUID_LOGIN} != "no"
+BINOWN= root
+BINMODE=4555
+PRECIOUSPROG=
+.endif
+
+.include <bsd.endian.mk>
+afterinstallconfig:
+ ${CAP_MKDB_CMD} ${CAP_MKDB_ENDIAN} ${DESTDIR}/etc/login.conf
+.if defined(NO_ROOT) && defined(METALOG)
+ echo ".${DISTBASE}/etc/login.conf.db type=file mode=0644 uname=root gname=wheel" | \
+ cat -l >> ${METALOG}
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/login/Makefile.depend b/usr.bin/login/Makefile.depend
new file mode 100644
index 000000000000..dcba122adac8
--- /dev/null
+++ b/usr.bin/login/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libpam/libpam \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/login/Makefile.depend.options b/usr.bin/login/Makefile.depend.options
new file mode 100644
index 000000000000..87c69612fea8
--- /dev/null
+++ b/usr.bin/login/Makefile.depend.options
@@ -0,0 +1,5 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= AUDIT
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/login/README b/usr.bin/login/README
new file mode 100644
index 000000000000..ede4366f91f7
--- /dev/null
+++ b/usr.bin/login/README
@@ -0,0 +1,10 @@
+This login has additional functionalities. They are all based on (part of)
+Wietse Venema's logdaemon package.
+
+
+The following defines can be used:
+
+- LOGALL to log all logins
+
+
+-Guido
diff --git a/usr.bin/login/fbtab b/usr.bin/login/fbtab
new file mode 100644
index 000000000000..ba2544eca9eb
--- /dev/null
+++ b/usr.bin/login/fbtab
@@ -0,0 +1,3 @@
+#
+#/dev/ttyv0 0600 /dev/console
+#/dev/ttyv0 0600 /dev/pcaudio:/dev/pcaudioctl
diff --git a/usr.bin/login/login.1 b/usr.bin/login/login.1
new file mode 100644
index 000000000000..8c24c4bda9f0
--- /dev/null
+++ b/usr.bin/login/login.1
@@ -0,0 +1,161 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd September 29, 2022
+.Dt LOGIN 1
+.Os
+.Sh NAME
+.Nm login
+.Nd log into the computer
+.Sh SYNOPSIS
+.Nm
+.Op Fl fp
+.Op Fl h Ar hostname
+.Op Ar user
+.Sh DESCRIPTION
+The
+.Nm
+utility logs users (and pseudo-users) into the computer system.
+.Pp
+If no user is specified, or if a user is specified and authentication
+of the user fails,
+.Nm
+prompts for a user name.
+Authentication of users is configurable via
+.Xr pam 8 .
+Password authentication is the default.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl f
+When a user name is specified, this option indicates that proper
+authentication has already been done and that no password need be
+requested.
+This option may only be used by the super-user or when an already
+logged in user is logging in as themselves.
+.It Fl h
+Specify the host from which the connection was received.
+It is used by various daemons such as
+.Nm telnetd .
+This option may only be used by the super-user.
+.It Fl p
+By default,
+.Nm
+discards any previous environment.
+The
+.Fl p
+option disables this behavior.
+.El
+.Pp
+Login access can be controlled via
+.Xr login.access 5
+or the login class in
+.Xr login.conf 5 ,
+which provides
+allow and deny records based on time, tty and remote host name.
+.Pp
+If the file
+.Pa /etc/fbtab
+exists,
+.Nm
+changes the protection and ownership of certain devices specified in this
+file.
+.Pp
+Immediately after logging a user in,
+.Nm
+displays the system copyright notice, the date and time the user last
+logged in, the message of the day as well as other information.
+If the file
+.Pa .hushlogin
+exists in the user's home directory, all of these messages are suppressed.
+This is to simplify logins for non-human users, such as
+.Xr uucp 1 .
+.Pp
+The
+.Nm
+utility enters information into the environment (see
+.Xr environ 7 )
+specifying the user's home directory (HOME), command interpreter (SHELL),
+search path (PATH), terminal type (TERM) and user name (both LOGNAME and
+USER).
+Other environment variables may be set due to entries in the login
+class capabilities database, for the login class assigned in the
+user's system passwd record.
+The login class also controls the maximum and current process resource
+limits granted to a login, process priorities and many other aspects of
+a user's login environment.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Pp
+The
+.Nm
+utility will submit an audit record when login succeeds or fails.
+Failure to determine the current auditing state will
+result in an error exit from
+.Nm .
+.Sh FILES
+.Bl -tag -width ".Pa /etc/security/audit_control" -compact
+.It Pa /etc/fbtab
+changes device protections
+.It Pa /etc/login.conf
+login class capabilities database
+.It Pa /var/run/motd
+message-of-the-day
+.It Pa /var/mail/user
+system mailboxes
+.It Pa \&.hushlogin
+makes login quieter
+.It Pa /etc/pam.d/login
+.Xr pam 8
+configuration file
+.It Pa /etc/security/audit_user
+user flags for auditing
+.It Pa /etc/security/audit_control
+global flags for auditing
+.El
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr chpass 1 ,
+.Xr csh 1 ,
+.Xr newgrp 1 ,
+.Xr passwd 1 ,
+.Xr rlogin 1 ,
+.Xr getpass 3 ,
+.Xr fbtab 5 ,
+.Xr login.access 5 ,
+.Xr login.conf 5 ,
+.Xr environ 7
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v6 .
diff --git a/usr.bin/login/login.access b/usr.bin/login/login.access
new file mode 100644
index 000000000000..05609df8355e
--- /dev/null
+++ b/usr.bin/login/login.access
@@ -0,0 +1,45 @@
+#
+# Login access control table.
+#
+# When someone logs in, the table is scanned for the first entry that
+# matches the (user, host) combination, or, in case of non-networked
+# logins, the first entry that matches the (user, tty) combination. The
+# permissions field of that table entry determines whether the login will
+# be accepted or refused.
+#
+# Format of the login access control table is three fields separated by a
+# ":" character:
+#
+# permission : users : origins
+#
+# The first field should be a "+" (access granted) or "-" (access denied)
+# character. The second field should be a list of one or more login names,
+# group names, or ALL (always matches). The third field should be a list
+# of one or more tty names (for non-networked logins), host names, domain
+# names (begin with "."), host addresses, internet network numbers (end
+# with "."), ALL (always matches) or LOCAL (matches any string that does
+# not contain a "." character). If you run NIS you can use @netgroupname
+# in host or user patterns.
+#
+# The EXCEPT operator makes it possible to write very compact rules.
+#
+# The group file is searched only when a name does not match that of the
+# logged-in user. Only groups are matched in which users are explicitly
+# listed: the program does not look at a user's primary group id value.
+#
+##############################################################################
+#
+# Disallow console logins to all but a few accounts.
+#
+#-:ALL EXCEPT wheel shutdown sync:console
+#
+# Disallow non-local logins to privileged accounts (group wheel).
+#
+#-:wheel:ALL EXCEPT LOCAL .win.tue.nl
+#
+# Some accounts are not allowed to login from anywhere:
+#
+#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL
+#
+# All other accounts are allowed to login from anywhere.
+#
diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c
new file mode 100644
index 000000000000..6a0c6a5b6bbc
--- /dev/null
+++ b/usr.bin/login/login.c
@@ -0,0 +1,1034 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technologies, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+/*
+ * login [ name ]
+ * login -h hostname (for telnetd, etc.)
+ * login -f name (for pre-authenticated login: datakit, xterm, etc.)
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <login_cap.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ttyent.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+#include "login.h"
+#include "pathnames.h"
+
+static int auth_pam(void);
+static void bail(int, int);
+static void bail_internal(int, int, int);
+static int export(const char *);
+static void export_pam_environment(void);
+static int motd(const char *);
+static void badlogin(char *);
+static char *getloginname(void);
+static void pam_syslog(const char *);
+static void pam_cleanup(void);
+static void refused(const char *, const char *, int);
+static const char *stypeof(char *);
+static void sigint(int);
+static void timedout(int);
+static void bail_sig(int);
+static void usage(void);
+
+#define TTYGRPNAME "tty" /* group to own ttys */
+#define DEFAULT_BACKOFF 3
+#define DEFAULT_RETRIES 10
+#define DEFAULT_PROMPT "login: "
+#define DEFAULT_PASSWD_PROMPT "Password:"
+#define TERM_UNKNOWN "su"
+#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
+#define NO_SLEEP_EXIT 0
+#define SLEEP_EXIT 5
+
+/*
+ * This bounds the time given to login. Not a define so it can
+ * be patched on machines where it's too small.
+ */
+static u_int timeout = 300;
+
+/* Buffer for signal handling of timeout */
+static jmp_buf timeout_buf;
+
+char pwbuf[1024];
+struct passwd pwres;
+struct passwd *pwd;
+static int failures;
+
+static char *envinit[1]; /* empty environment list */
+
+/*
+ * Command line flags and arguments
+ */
+static int fflag; /* -f: do not perform authentication */
+static int hflag; /* -h: login from remote host */
+static char *hostname; /* hostname from command line */
+static int pflag; /* -p: preserve environment */
+
+/*
+ * User name
+ */
+static char *username; /* user name */
+static char *olduser; /* previous user name */
+
+/*
+ * Prompts
+ */
+static char default_prompt[] = DEFAULT_PROMPT;
+static const char *prompt;
+static char default_passwd_prompt[] = DEFAULT_PASSWD_PROMPT;
+static const char *passwd_prompt;
+
+static char *tty;
+
+/*
+ * PAM data
+ */
+static pam_handle_t *pamh = NULL;
+static struct pam_conv pamc = { openpam_ttyconv, NULL };
+static int pam_err;
+static int pam_silent = PAM_SILENT;
+static int pam_cred_established;
+static int pam_session_established;
+
+int
+main(int argc, char *argv[])
+{
+ struct group *gr;
+ struct stat st;
+ int retries, backoff;
+ int ask, ch, cnt, quietlog, rootlogin, rval;
+ uid_t uid, euid;
+ gid_t egid;
+ char *term;
+ char *p, *ttyn;
+ char tname[sizeof(_PATH_TTY) + 10];
+ char *arg0;
+ const char *tp;
+ const char *shell = NULL;
+ login_cap_t *lc = NULL;
+ login_cap_t *lc_user = NULL;
+ pid_t pid;
+ sigset_t mask, omask;
+ struct sigaction sa;
+#ifdef USE_BSM_AUDIT
+ char auditsuccess = 1;
+#endif
+
+ sa.sa_flags = SA_RESTART;
+ (void)sigfillset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGHUP, &sa, NULL);
+ if (setjmp(timeout_buf)) {
+ if (failures)
+ badlogin(username);
+ (void)fprintf(stderr, "Login timed out after %d seconds\n",
+ timeout);
+ bail(NO_SLEEP_EXIT, 0);
+ }
+ sa.sa_handler = timedout;
+ (void)sigaction(SIGALRM, &sa, NULL);
+ (void)alarm(timeout);
+ (void)setpriority(PRIO_PROCESS, 0, 0);
+
+ openlog("login", LOG_CONS, LOG_AUTH);
+
+ uid = getuid();
+ euid = geteuid();
+ egid = getegid();
+
+ while ((ch = getopt(argc, argv, "fh:p")) != -1)
+ switch (ch) {
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ if (uid != 0)
+ errx(1, "-h option: %s", strerror(EPERM));
+ if (strlen(optarg) >= MAXHOSTNAMELEN)
+ errx(1, "-h option: %s: exceeds maximum "
+ "hostname size", optarg);
+ hflag = 1;
+ hostname = optarg;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case '?':
+ default:
+ if (uid == 0)
+ syslog(LOG_ERR, "invalid flag %c", ch);
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ username = strdup(*argv);
+ if (username == NULL)
+ err(1, "strdup()");
+ ask = 0;
+ } else {
+ ask = 1;
+ }
+
+ setproctitle("-%s", getprogname());
+
+ closefrom(3);
+
+ /*
+ * Get current TTY
+ */
+ ttyn = ttyname(STDIN_FILENO);
+ if (ttyn == NULL || *ttyn == '\0') {
+ (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
+ ttyn = tname;
+ }
+ if (strncmp(ttyn, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
+ tty = ttyn + sizeof _PATH_DEV - 1;
+ else
+ tty = ttyn;
+
+ /*
+ * Get "login-retries" & "login-backoff" from default class
+ */
+ lc = login_getclass(NULL);
+ prompt = login_getcapstr(lc, "login_prompt",
+ default_prompt, default_prompt);
+ passwd_prompt = login_getcapstr(lc, "passwd_prompt",
+ default_passwd_prompt, default_passwd_prompt);
+ retries = login_getcapnum(lc, "login-retries",
+ DEFAULT_RETRIES, DEFAULT_RETRIES);
+ backoff = login_getcapnum(lc, "login-backoff",
+ DEFAULT_BACKOFF, DEFAULT_BACKOFF);
+ login_close(lc);
+ lc = NULL;
+
+ /*
+ * Try to authenticate the user until we succeed or time out.
+ */
+ for (cnt = 0;; ask = 1) {
+ if (ask) {
+ fflag = 0;
+ if (olduser != NULL)
+ free(olduser);
+ olduser = username;
+ username = getloginname();
+ }
+ rootlogin = 0;
+
+ /*
+ * Note if trying multiple user names; log failures for
+ * previous user name, but don't bother logging one failure
+ * for nonexistent name (mistyped username).
+ */
+ if (failures && strcmp(olduser, username) != 0) {
+ if (failures > (pwd ? 0 : 1))
+ badlogin(olduser);
+ }
+
+ /*
+ * Load the PAM policy and set some variables
+ */
+ pam_err = pam_start("login", username, &pamc, &pamh);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_start()");
+#ifdef USE_BSM_AUDIT
+ au_login_fail("PAM Error", 1);
+#endif
+ bail(NO_SLEEP_EXIT, 1);
+ }
+ pam_err = pam_set_item(pamh, PAM_TTY, tty);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_set_item(PAM_TTY)");
+#ifdef USE_BSM_AUDIT
+ au_login_fail("PAM Error", 1);
+#endif
+ bail(NO_SLEEP_EXIT, 1);
+ }
+ pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_set_item(PAM_RHOST)");
+#ifdef USE_BSM_AUDIT
+ au_login_fail("PAM Error", 1);
+#endif
+ bail(NO_SLEEP_EXIT, 1);
+ }
+
+ (void)getpwnam_r(username, &pwres, pwbuf, sizeof(pwbuf), &pwd);
+ if (pwd != NULL && pwd->pw_uid == 0)
+ rootlogin = 1;
+
+ /*
+ * If the -f option was specified and the caller is
+ * root or the caller isn't changing their uid, don't
+ * authenticate.
+ */
+ if (pwd != NULL && fflag &&
+ (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) {
+ /* already authenticated */
+ rval = 0;
+#ifdef USE_BSM_AUDIT
+ auditsuccess = 0; /* opened a terminal window only */
+#endif
+ } else {
+ fflag = 0;
+ (void)setpriority(PRIO_PROCESS, 0, -4);
+ rval = auth_pam();
+ (void)setpriority(PRIO_PROCESS, 0, 0);
+ }
+
+ if (pwd != NULL && rval == 0)
+ break;
+
+ pam_cleanup();
+
+ /*
+ * We are not exiting here, but this corresponds to a failed
+ * login event, so set exitstatus to 1.
+ */
+#ifdef USE_BSM_AUDIT
+ au_login_fail("Login incorrect", 1);
+#endif
+
+ (void)printf("Login incorrect\n");
+ failures++;
+
+ pwd = NULL;
+
+ /*
+ * Allow up to 'retry' (10) attempts, but start
+ * backing off after 'backoff' (3) attempts.
+ */
+ if (++cnt > backoff) {
+ if (cnt >= retries) {
+ badlogin(username);
+ bail(SLEEP_EXIT, 1);
+ }
+ sleep((u_int)((cnt - backoff) * 5));
+ }
+ }
+
+ /* committed to login -- turn off timeout */
+ (void)alarm((u_int)0);
+
+ (void)sigemptyset(&mask);
+ (void)sigaddset(&mask, SIGHUP);
+ (void)sigaddset(&mask, SIGTERM);
+ (void)sigprocmask(SIG_BLOCK, &mask, &omask);
+ sa.sa_handler = bail_sig;
+ (void)sigaction(SIGHUP, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
+
+ endpwent();
+
+#ifdef USE_BSM_AUDIT
+ /* Audit successful login. */
+ if (auditsuccess)
+ au_login_success();
+#endif
+
+ /*
+ * This needs to happen before login_getpwclass to support
+ * home directories on GSS-API authenticated NFS where the
+ * kerberos credentials need to be saved so that the kernel
+ * can authenticate to the NFS server.
+ */
+ pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_setcred()");
+ bail(NO_SLEEP_EXIT, 1);
+ }
+ pam_cred_established = 1;
+
+ /*
+ * Establish the login class.
+ */
+ lc = login_getpwclass(pwd);
+ lc_user = login_getuserclass(pwd);
+
+ if (!(quietlog = login_getcapbool(lc_user, "hushlogin", 0)))
+ quietlog = login_getcapbool(lc, "hushlogin", 0);
+
+ /*
+ * Switching needed for NFS with root access disabled.
+ *
+ * XXX: This change fails to modify the additional groups for the
+ * process, and as such, may restrict rights normally granted
+ * through those groups.
+ */
+ (void)setegid(pwd->pw_gid);
+ (void)seteuid(rootlogin ? 0 : pwd->pw_uid);
+ if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) {
+ if (login_getcapbool(lc, "requirehome", 0))
+ refused("Home directory not available", "HOMEDIR", 1);
+ if (chdir("/") < 0)
+ refused("Cannot find root directory", "ROOTDIR", 1);
+ if (!quietlog || *pwd->pw_dir)
+ printf("No home directory.\nLogging in with home = \"/\".\n");
+ pwd->pw_dir = strdup("/");
+ if (pwd->pw_dir == NULL) {
+ syslog(LOG_NOTICE, "strdup(): %m");
+ bail(SLEEP_EXIT, 1);
+ }
+ }
+ (void)seteuid(euid);
+ (void)setegid(egid);
+ if (!quietlog) {
+ quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
+ if (!quietlog)
+ pam_silent = 0;
+ }
+
+ shell = login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell);
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = strdup(_PATH_BSHELL);
+ if (pwd->pw_shell == NULL) {
+ syslog(LOG_NOTICE, "strdup(): %m");
+ bail(SLEEP_EXIT, 1);
+ }
+ if (*shell == '\0') /* Not overridden */
+ shell = pwd->pw_shell;
+ if ((shell = strdup(shell)) == NULL) {
+ syslog(LOG_NOTICE, "strdup(): %m");
+ bail(SLEEP_EXIT, 1);
+ }
+
+ /*
+ * Set device protections, depending on what terminal the
+ * user is logged in. This feature is used on Suns to give
+ * console users better privacy.
+ */
+ login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);
+
+ /*
+ * Clear flags of the tty. None should be set, and when the
+ * user sets them otherwise, this can cause the chown to fail.
+ * Since it isn't clear that flags are useful on character
+ * devices, we just clear them.
+ *
+ * We don't log in the case of EOPNOTSUPP because dev might be
+ * on NFS, which doesn't support chflags.
+ *
+ * We don't log in the EROFS because that means that /dev is on
+ * a read only file system and we assume that the permissions there
+ * are sane.
+ */
+ if (ttyn != tname && chflags(ttyn, 0))
+ if (errno != EOPNOTSUPP && errno != EROFS)
+ syslog(LOG_ERR, "chflags(%s): %m", ttyn);
+ if (ttyn != tname && chown(ttyn, pwd->pw_uid,
+ (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid))
+ if (errno != EROFS)
+ syslog(LOG_ERR, "chown(%s): %m", ttyn);
+
+#ifdef LOGALL
+ /*
+ * Syslog each successful login, so we don't have to watch
+ * hundreds of wtmp or lastlogin files.
+ */
+ if (hflag)
+ syslog(LOG_INFO, "login from %s on %s as %s",
+ hostname, tty, pwd->pw_name);
+ else
+ syslog(LOG_INFO, "login on %s as %s",
+ tty, pwd->pw_name);
+#endif
+
+ /*
+ * If fflag is on, assume caller/authenticator has logged root
+ * login.
+ */
+ if (rootlogin && fflag == 0) {
+ if (hflag)
+ syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
+ username, tty, hostname);
+ else
+ syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s",
+ username, tty);
+ }
+
+ /*
+ * Destroy environment unless user has requested its
+ * preservation - but preserve TERM in all cases
+ */
+ term = getenv("TERM");
+ if (!pflag)
+ environ = envinit;
+ if (term != NULL)
+ setenv("TERM", term, 0);
+
+ /*
+ * PAM modules might add supplementary groups during pam_setcred().
+ */
+ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) {
+ syslog(LOG_ERR, "setusercontext() failed - exiting");
+ bail(NO_SLEEP_EXIT, 1);
+ }
+
+ pam_err = pam_setcred(pamh, pam_silent|PAM_REINITIALIZE_CRED);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_setcred()");
+ bail(NO_SLEEP_EXIT, 1);
+ }
+
+ pam_err = pam_open_session(pamh, pam_silent);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_open_session()");
+ bail(NO_SLEEP_EXIT, 1);
+ }
+ pam_session_established = 1;
+
+ /*
+ * We must fork() before setuid() because we need to call
+ * pam_close_session() as root.
+ */
+ pid = fork();
+ if (pid < 0) {
+ err(1, "fork");
+ } else if (pid != 0) {
+ /*
+ * Parent: wait for child to finish, then clean up
+ * session.
+ *
+ * If we get SIGHUP or SIGTERM, clean up the session
+ * and exit right away. This will make the terminal
+ * inaccessible and send SIGHUP to the foreground
+ * process group.
+ */
+ int status;
+ setproctitle("-%s [pam]", getprogname());
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+ waitpid(pid, &status, 0);
+ (void)sigprocmask(SIG_BLOCK, &mask, NULL);
+ bail(NO_SLEEP_EXIT, 0);
+ }
+
+ /*
+ * NOTICE: We are now in the child process!
+ */
+
+ /*
+ * Add any environment variables the PAM modules may have set.
+ */
+ export_pam_environment();
+
+ /*
+ * We're done with PAM now; our parent will deal with the rest.
+ */
+ pam_end(pamh, 0);
+ pamh = NULL;
+
+ /*
+ * We don't need to be root anymore, so set the login name and
+ * the UID.
+ */
+ if (setlogin(username) != 0) {
+ syslog(LOG_ERR, "setlogin(%s): %m - exiting", username);
+ bail(NO_SLEEP_EXIT, 1);
+ }
+ if (setusercontext(lc, pwd, pwd->pw_uid,
+ LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) {
+ syslog(LOG_ERR, "setusercontext() failed - exiting");
+ exit(1);
+ }
+
+ (void)setenv("SHELL", pwd->pw_shell, 1);
+ (void)setenv("HOME", pwd->pw_dir, 1);
+ /* Overwrite "term" from login.conf(5) for any known TERM */
+ if (term == NULL && (tp = stypeof(tty)) != NULL)
+ (void)setenv("TERM", tp, 1);
+ else
+ (void)setenv("TERM", TERM_UNKNOWN, 0);
+ (void)setenv("LOGNAME", username, 1);
+ (void)setenv("USER", username, 1);
+ (void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);
+
+ if (!quietlog) {
+ const char *cw;
+
+ cw = login_getcapstr(lc, "welcome", NULL, NULL);
+ if (cw != NULL && access(cw, F_OK) == 0)
+ motd(cw);
+ else
+ motd(_PATH_MOTDFILE);
+
+ if (login_getcapbool(lc_user, "nocheckmail", 0) == 0 &&
+ login_getcapbool(lc, "nocheckmail", 0) == 0) {
+ char *cx;
+
+ /* $MAIL may have been set by class. */
+ cx = getenv("MAIL");
+ if (cx == NULL) {
+ asprintf(&cx, "%s/%s",
+ _PATH_MAILDIR, pwd->pw_name);
+ }
+ if (cx && stat(cx, &st) == 0 && st.st_size != 0)
+ (void)printf("You have %smail.\n",
+ (st.st_mtime > st.st_atime) ? "new " : "");
+ if (getenv("MAIL") == NULL)
+ free(cx);
+ }
+ }
+
+ login_close(lc_user);
+ login_close(lc);
+
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGALRM, &sa, NULL);
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
+ (void)sigaction(SIGHUP, &sa, NULL);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGTSTP, &sa, NULL);
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ /*
+ * Login shells have a leading '-' in front of argv[0]
+ */
+ p = strrchr(pwd->pw_shell, '/');
+ if (asprintf(&arg0, "-%s", p ? p + 1 : pwd->pw_shell) >= MAXPATHLEN) {
+ syslog(LOG_ERR, "user: %s: shell exceeds maximum pathname size",
+ username);
+ errx(1, "shell exceeds maximum pathname size");
+ } else if (arg0 == NULL) {
+ err(1, "asprintf()");
+ }
+
+ execlp(shell, arg0, (char *)0);
+ err(1, "%s", shell);
+
+ /*
+ * That's it, folks!
+ */
+}
+
+/*
+ * Attempt to authenticate the user using PAM. Returns 0 if the user is
+ * authenticated, or 1 if not authenticated. If some sort of PAM system
+ * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
+ * function returns -1. This can be used as an indication that we should
+ * fall back to a different authentication mechanism.
+ */
+static int
+auth_pam(void)
+{
+ const char *tmpl_user;
+ const void *item;
+ int rval;
+
+ pam_err = pam_authenticate(pamh, pam_silent);
+ switch (pam_err) {
+
+ case PAM_SUCCESS:
+ /*
+ * With PAM we support the concept of a "template"
+ * user. The user enters a login name which is
+ * authenticated by PAM, usually via a remote service
+ * such as RADIUS or TACACS+. If authentication
+ * succeeds, a different but related "template" name
+ * is used for setting the credentials, shell, and
+ * home directory. The name the user enters need only
+ * exist on the remote authentication server, but the
+ * template name must be present in the local password
+ * database.
+ *
+ * This is supported by two various mechanisms in the
+ * individual modules. However, from the application's
+ * point of view, the template user is always passed
+ * back as a changed value of the PAM_USER item.
+ */
+ pam_err = pam_get_item(pamh, PAM_USER, &item);
+ if (pam_err == PAM_SUCCESS) {
+ tmpl_user = (const char *)item;
+ if (strcmp(username, tmpl_user) != 0) {
+ (void)getpwnam_r(tmpl_user, &pwres, pwbuf,
+ sizeof(pwbuf), &pwd);
+ }
+ } else {
+ pam_syslog("pam_get_item(PAM_USER)");
+ }
+ rval = 0;
+ break;
+
+ case PAM_AUTH_ERR:
+ case PAM_USER_UNKNOWN:
+ case PAM_MAXTRIES:
+ rval = 1;
+ break;
+
+ default:
+ pam_syslog("pam_authenticate()");
+ rval = -1;
+ break;
+ }
+
+ if (rval == 0) {
+ pam_err = pam_acct_mgmt(pamh, pam_silent);
+ switch (pam_err) {
+ case PAM_SUCCESS:
+ break;
+ case PAM_NEW_AUTHTOK_REQD:
+ pam_err = pam_chauthtok(pamh,
+ pam_silent|PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (pam_err != PAM_SUCCESS) {
+ pam_syslog("pam_chauthtok()");
+ rval = 1;
+ }
+ break;
+ default:
+ pam_syslog("pam_acct_mgmt()");
+ rval = 1;
+ break;
+ }
+ }
+
+ if (rval != 0) {
+ pam_end(pamh, pam_err);
+ pamh = NULL;
+ }
+ return (rval);
+}
+
+/*
+ * Export any environment variables PAM modules may have set
+ */
+static void
+export_pam_environment(void)
+{
+ char **pam_env;
+ char **pp;
+
+ pam_env = pam_getenvlist(pamh);
+ if (pam_env != NULL) {
+ for (pp = pam_env; *pp != NULL; pp++) {
+ (void)export(*pp);
+ free(*pp);
+ }
+ }
+}
+
+/*
+ * Perform sanity checks on an environment variable:
+ * - Make sure there is an '=' in the string.
+ * - Make sure the string doesn't run on too long.
+ * - Do not export certain variables. This list was taken from the
+ * Solaris pam_putenv(3) man page.
+ * Then export it.
+ */
+static int
+export(const char *s)
+{
+ static const char *noexport[] = {
+ "SHELL", "HOME", "LOGNAME", "MAIL", "CDPATH",
+ "IFS", "PATH", NULL
+ };
+ char *p;
+ const char **pp;
+ size_t n;
+ int rv;
+
+ if (strlen(s) > 1024 || (p = strchr(s, '=')) == NULL)
+ return (0);
+ if (strncmp(s, "LD_", 3) == 0)
+ return (0);
+ for (pp = noexport; *pp != NULL; pp++) {
+ n = strlen(*pp);
+ if (s[n] == '=' && strncmp(s, *pp, n) == 0)
+ return (0);
+ }
+ *p = '\0';
+ rv = setenv(s, p + 1, 1);
+ *p = '=';
+ if (rv == -1)
+ return (0);
+ return (1);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: login [-fp] [-h hostname] [username]\n");
+ exit(1);
+}
+
+/*
+ * Prompt user and read login name from stdin.
+ */
+static char *
+getloginname(void)
+{
+ char *nbuf, *p;
+ int ch;
+
+ nbuf = malloc(MAXLOGNAME);
+ if (nbuf == NULL)
+ err(1, "malloc()");
+ do {
+ (void)printf("%s", prompt);
+ for (p = nbuf; (ch = getchar()) != '\n'; ) {
+ if (ch == EOF) {
+ badlogin(username);
+ bail(NO_SLEEP_EXIT, 0);
+ }
+ if (p < nbuf + MAXLOGNAME - 1)
+ *p++ = ch;
+ }
+ } while (p == nbuf);
+
+ *p = '\0';
+ if (nbuf[0] == '-') {
+ pam_silent = 0;
+ memmove(nbuf, nbuf + 1, strlen(nbuf));
+ } else {
+ pam_silent = PAM_SILENT;
+ }
+ return nbuf;
+}
+
+/*
+ * SIGINT handler for motd().
+ */
+static volatile int motdinterrupt;
+static void
+sigint(int signo __unused)
+{
+ motdinterrupt = 1;
+}
+
+/*
+ * Display the contents of a file (such as /etc/motd).
+ */
+static int
+motd(const char *motdfile)
+{
+ struct sigaction newint, oldint;
+ FILE *f;
+ int ch;
+
+ if ((f = fopen(motdfile, "r")) == NULL)
+ return (-1);
+ motdinterrupt = 0;
+ newint.sa_handler = sigint;
+ newint.sa_flags = 0;
+ sigfillset(&newint.sa_mask);
+ sigaction(SIGINT, &newint, &oldint);
+ while ((ch = fgetc(f)) != EOF && !motdinterrupt)
+ putchar(ch);
+ sigaction(SIGINT, &oldint, NULL);
+ if (ch != EOF || ferror(f)) {
+ fclose(f);
+ return (-1);
+ }
+ fclose(f);
+ return (0);
+}
+
+/*
+ * SIGALRM handler, to enforce login prompt timeout.
+ *
+ * XXX This can potentially confuse the hell out of PAM. We should
+ * XXX instead implement a conversation function that returns
+ * XXX PAM_CONV_ERR when interrupted by a signal, and have the signal
+ * XXX handler just set a flag.
+ */
+static void
+timedout(int signo __unused)
+{
+
+ longjmp(timeout_buf, signo);
+}
+
+static void
+badlogin(char *name)
+{
+
+ if (failures == 0)
+ return;
+ if (hflag) {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
+ failures, failures > 1 ? "S" : "", hostname);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s FROM %s, %s",
+ failures, failures > 1 ? "S" : "", hostname, name);
+ } else {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
+ failures, failures > 1 ? "S" : "", tty);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s ON %s, %s",
+ failures, failures > 1 ? "S" : "", tty, name);
+ }
+ failures = 0;
+}
+
+const char *
+stypeof(char *ttyid)
+{
+ struct ttyent *t;
+
+ if (ttyid != NULL && *ttyid != '\0') {
+ t = getttynam(ttyid);
+ if (t != NULL && t->ty_type != NULL)
+ return (t->ty_type);
+ }
+ return (NULL);
+}
+
+static void
+refused(const char *msg, const char *rtype, int lout)
+{
+
+ if (msg != NULL)
+ printf("%s.\n", msg);
+ if (hflag)
+ syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s",
+ pwd->pw_name, rtype, hostname, tty);
+ else
+ syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) ON TTY %s",
+ pwd->pw_name, rtype, tty);
+ if (lout)
+ bail(SLEEP_EXIT, 1);
+}
+
+/*
+ * Log a PAM error
+ */
+static void
+pam_syslog(const char *msg)
+{
+ syslog(LOG_ERR, "%s: %s", msg, pam_strerror(pamh, pam_err));
+}
+
+/*
+ * Shut down PAM
+ */
+static void
+pam_cleanup(void)
+{
+
+ if (pamh != NULL) {
+ if (pam_session_established) {
+ pam_err = pam_close_session(pamh, 0);
+ if (pam_err != PAM_SUCCESS)
+ pam_syslog("pam_close_session()");
+ }
+ pam_session_established = 0;
+ if (pam_cred_established) {
+ pam_err = pam_setcred(pamh, pam_silent|PAM_DELETE_CRED);
+ if (pam_err != PAM_SUCCESS)
+ pam_syslog("pam_setcred()");
+ }
+ pam_cred_established = 0;
+ pam_end(pamh, pam_err);
+ pamh = NULL;
+ }
+}
+
+static void
+bail_internal(int sec, int eval, int signo)
+{
+ struct sigaction sa;
+
+ pam_cleanup();
+#ifdef USE_BSM_AUDIT
+ if (pwd != NULL)
+ audit_logout();
+#endif
+ (void)sleep(sec);
+ if (signo == 0)
+ exit(eval);
+ else {
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = 0;
+ (void)sigemptyset(&sa.sa_mask);
+ (void)sigaction(signo, &sa, NULL);
+ (void)sigaddset(&sa.sa_mask, signo);
+ (void)sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
+ raise(signo);
+ exit(128 + signo);
+ }
+}
+
+/*
+ * Exit, optionally after sleeping a few seconds
+ */
+static void
+bail(int sec, int eval)
+{
+ bail_internal(sec, eval, 0);
+}
+
+/*
+ * Exit because of a signal.
+ * This is not async-signal safe, so only call async-signal safe functions
+ * while the signal is unmasked.
+ */
+static void
+bail_sig(int signo)
+{
+ bail_internal(NO_SLEEP_EXIT, 0, signo);
+}
diff --git a/usr.bin/login/login.conf b/usr.bin/login/login.conf
new file mode 100644
index 000000000000..1069da17b4db
--- /dev/null
+++ b/usr.bin/login/login.conf
@@ -0,0 +1,332 @@
+# login.conf - login class capabilities database.
+#
+# Remember to rebuild the database after each change to this file:
+#
+# cap_mkdb /etc/login.conf
+#
+# This file controls resource limits, accounting limits and
+# default user environment settings.
+#
+#
+
+# Default settings effectively disable resource limits, see the
+# examples below for a starting point to enable them.
+
+# defaults
+# These settings are used by login(1) by default for classless users
+# Note that entries like "cputime" set both "cputime-cur" and "cputime-max"
+#
+# Note that since a colon ':' is used to separate capability entries,
+# a \c escape sequence must be used to embed a literal colon in the
+# value or name of a capability (see the ``CGETNUM AND CGETSTR SYNTAX
+# AND SEMANTICS'' section of getcap(3) for more escape sequences).
+
+default:\
+ :passwd_format=sha512:\
+ :copyright=/etc/COPYRIGHT:\
+ :welcome=/var/run/motd:\
+ :setenv=BLOCKSIZE=K:\
+ :mail=/var/mail/$:\
+ :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:\
+ :nologin=/var/run/nologin:\
+ :cputime=unlimited:\
+ :datasize=unlimited:\
+ :stacksize=unlimited:\
+ :memorylocked=64K:\
+ :memoryuse=unlimited:\
+ :filesize=unlimited:\
+ :coredumpsize=unlimited:\
+ :openfiles=unlimited:\
+ :maxproc=unlimited:\
+ :sbsize=unlimited:\
+ :vmemoryuse=unlimited:\
+ :swapuse=unlimited:\
+ :pseudoterminals=unlimited:\
+ :kqueues=unlimited:\
+ :umtxp=unlimited:\
+ :pipebuf=unlimited:\
+ :priority=0:\
+ :ignoretime@:\
+ :umask=022:\
+ :charset=UTF-8:\
+ :lang=C.UTF-8:
+
+#
+# A collection of common class names - forward them all to 'default'
+# (login would normally do this anyway, but having a class name
+# here suppresses the diagnostic)
+#
+standard:\
+ :tc=default:
+xuser:\
+ :tc=default:
+staff:\
+ :tc=default:
+
+# This PATH may be clobbered by individual applications. Notably, by default,
+# rc(8), service(8), and cron(8) will all override it with a default PATH that
+# may not include /usr/local/sbin and /usr/local/bin when starting services or
+# jobs.
+daemon:\
+ :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin:\
+ :mail@:\
+ :memorylocked=128M:\
+ :tc=default:
+news:\
+ :tc=default:
+dialer:\
+ :tc=default:
+
+#
+# Root can always login
+#
+# N.B. login_getpwclass(3) will use this entry for the root account,
+# in preference to 'default'.
+root:\
+ :ignorenologin:\
+ :memorylocked=unlimited:\
+ :tc=default:
+
+#
+# Russian Users Accounts. Setup proper environment variables.
+#
+russian|Russian Users Accounts:\
+ :charset=UTF-8:\
+ :lang=ru_RU.UTF-8:\
+ :tc=default:
+
+
+######################################################################
+######################################################################
+##
+## Example entries
+##
+######################################################################
+######################################################################
+
+## Example defaults
+## These settings are used by login(1) by default for classless users
+## Note that entries like "cputime" set both "cputime-cur" and "cputime-max"
+#
+#default:\
+# :cputime=infinity:\
+# :datasize-cur=22M:\
+# :stacksize-cur=8M:\
+# :memorylocked-cur=10M:\
+# :memoryuse-cur=30M:\
+# :filesize=infinity:\
+# :coredumpsize=infinity:\
+# :maxproc-cur=64:\
+# :openfiles-cur=64:\
+# :priority=0:\
+# :requirehome@:\
+# :umask=022:\
+# :tc=auth-defaults:
+#
+#
+##
+## standard - standard user defaults
+##
+#standard:\
+# :copyright=/etc/COPYRIGHT:\
+# :welcome=/var/run/motd:\
+# :setenv=BLOCKSIZE=K:\
+# :mail=/var/mail/$:\
+# :path=~/bin /bin /usr/bin /usr/local/bin:\
+# :manpath=/usr/share/man /usr/local/man:\
+# :nologin=/var/run/nologin:\
+# :cputime=1h30m:\
+# :datasize=8M:\
+# :vmemoryuse=100M:\
+# :stacksize=2M:\
+# :memorylocked=4M:\
+# :memoryuse=8M:\
+# :filesize=8M:\
+# :coredumpsize=8M:\
+# :openfiles=24:\
+# :maxproc=32:\
+# :priority=0:\
+# :requirehome:\
+# :passwordtime=90d:\
+# :umask=002:\
+# :ignoretime@:\
+# :tc=default:
+#
+#
+##
+## users of X (needs more resources!)
+##
+#xuser:\
+# :manpath=/usr/share/man /usr/local/man:\
+# :cputime=4h:\
+# :datasize=12M:\
+# :vmemoryuse=infinity:\
+# :stacksize=4M:\
+# :filesize=8M:\
+# :memoryuse=16M:\
+# :openfiles=32:\
+# :maxproc=48:\
+# :tc=standard:
+#
+#
+##
+## Staff users - few restrictions and allow login anytime
+##
+#staff:\
+# :ignorenologin:\
+# :ignoretime:\
+# :requirehome@:\
+# :accounted@:\
+# :path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\
+# :umask=022:\
+# :tc=standard:
+#
+#
+##
+## root - fallback for root logins
+##
+#root:\
+# :path=~/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\
+# :cputime=infinity:\
+# :datasize=infinity:\
+# :stacksize=infinity:\
+# :memorylocked=infinity:\
+# :memoryuse=infinity:\
+# :filesize=infinity:\
+# :coredumpsize=infinity:\
+# :openfiles=infinity:\
+# :maxproc=infinity:\
+# :memoryuse-cur=32M:\
+# :maxproc-cur=64:\
+# :openfiles-cur=1024:\
+# :priority=0:\
+# :requirehome@:\
+# :umask=022:\
+# :tc=auth-root-defaults:
+#
+#
+##
+## Settings used by /etc/rc
+##
+#daemon:\
+# :coredumpsize@:\
+# :coredumpsize-cur=0:\
+# :datasize=infinity:\
+# :datasize-cur@:\
+# :maxproc=512:\
+# :maxproc-cur@:\
+# :memoryuse-cur=64M:\
+# :memorylocked-cur=64M:\
+# :openfiles=1024:\
+# :openfiles-cur@:\
+# :stacksize=16M:\
+# :stacksize-cur@:\
+# :tc=default:
+#
+#
+##
+## Settings used by news subsystem
+##
+#news:\
+# :path=/usr/local/news/bin /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin:\
+# :cputime=infinity:\
+# :filesize=128M:\
+# :datasize-cur=64M:\
+# :stacksize-cur=32M:\
+# :coredumpsize-cur=0:\
+# :maxmemorysize-cur=128M:\
+# :memorylocked=32M:\
+# :maxproc=128:\
+# :openfiles=256:\
+# :tc=default:
+#
+#
+##
+## The dialer class should be used for a dialup PPP account
+## Welcome messages/news suppressed
+##
+#dialer:\
+# :hushlogin:\
+# :requirehome@:\
+# :cputime=unlimited:\
+# :filesize=2M:\
+# :datasize=2M:\
+# :stacksize=4M:\
+# :coredumpsize=0:\
+# :memoryuse=4M:\
+# :memorylocked=1M:\
+# :maxproc=16:\
+# :openfiles=32:\
+# :tc=standard:
+#
+#
+##
+## Site full-time 24/7 PPP connection
+## - no time accounting, restricted to access via dialin lines
+##
+#site:\
+# :ignoretime:\
+# :passwordtime@:\
+# :refreshtime@:\
+# :refreshperiod@:\
+# :sessionlimit@:\
+# :autodelete@:\
+# :expireperiod@:\
+# :graceexpire@:\
+# :gracetime@:\
+# :warnexpire@:\
+# :warnpassword@:\
+# :idletime@:\
+# :sessiontime@:\
+# :daytime@:\
+# :weektime@:\
+# :monthtime@:\
+# :warntime@:\
+# :accounted@:\
+# :tc=dialer:\
+# :tc=staff:
+#
+#
+##
+## Example standard accounting entries for subscriber levels
+##
+#
+#subscriber|Subscribers:\
+# :accounted:\
+# :refreshtime=180d:\
+# :refreshperiod@:\
+# :sessionlimit@:\
+# :autodelete=30d:\
+# :expireperiod=180d:\
+# :graceexpire=7d:\
+# :gracetime=10m:\
+# :warnexpire=7d:\
+# :warnpassword=7d:\
+# :idletime=30m:\
+# :sessiontime=4h:\
+# :daytime=6h:\
+# :weektime=40h:\
+# :monthtime=120h:\
+# :warntime=4h:\
+# :tc=standard:
+#
+#
+##
+## Subscriber accounts. These accounts have their login times
+## accounted and have access limits applied.
+##
+#subppp|PPP Subscriber Accounts:\
+# :tc=dialer:\
+# :tc=subscriber:
+#
+#
+#subshell|Shell Subscriber Accounts:\
+# :tc=subscriber:
+#
+##
+## If you want some of the accounts to use traditional UNIX DES based
+## password hashes.
+##
+#des_users:\
+# :passwd_format=des:\
+# :tc=default:
diff --git a/usr.bin/login/login.h b/usr.bin/login/login.h
new file mode 100644
index 000000000000..11760428d5ae
--- /dev/null
+++ b/usr.bin/login/login.h
@@ -0,0 +1,37 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2001 FreeBSD, 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.
+ *
+ * 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.
+ */
+
+void login_fbtab(char *, uid_t, gid_t);
+
+#ifdef USE_BSM_AUDIT
+void au_login_success(void);
+void au_login_fail(const char *errmsg, int na);
+void audit_logout(void);
+#endif
+
+extern char **environ;
+extern struct passwd *pwd;
diff --git a/usr.bin/login/login_audit.c b/usr.bin/login/login_audit.c
new file mode 100644
index 000000000000..1f2ec4d80cc9
--- /dev/null
+++ b/usr.bin/login/login_audit.c
@@ -0,0 +1,203 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2005 Apple Computer, Inc.
+ * All rights reserved.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * 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 Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include <sys/types.h>
+
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "login.h"
+
+/*
+ * Audit data
+ */
+static au_tid_t tid;
+
+/*
+ * The following tokens are included in the audit record for a successful
+ * login: header, subject, return.
+ */
+void
+au_login_success(void)
+{
+ token_t *tok;
+ int aufd;
+ au_mask_t aumask;
+ auditinfo_t auinfo;
+ uid_t uid = pwd->pw_uid;
+ gid_t gid = pwd->pw_gid;
+ pid_t pid = getpid();
+ int au_cond;
+
+ /* If we are not auditing, don't cut an audit record; just return. */
+ if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
+ if (errno == ENOSYS)
+ return;
+ errx(1, "could not determine audit condition");
+ }
+ if (au_cond == AUC_NOAUDIT)
+ return;
+
+ /* Compute and set the user's preselection mask. */
+ if (au_user_mask(pwd->pw_name, &aumask) == -1)
+ errx(1, "could not calculate audit mask");
+
+ /* Set the audit info for the user. */
+ auinfo.ai_auid = uid;
+ auinfo.ai_asid = pid;
+ bcopy(&tid, &auinfo.ai_termid, sizeof(auinfo.ai_termid));
+ bcopy(&aumask, &auinfo.ai_mask, sizeof(auinfo.ai_mask));
+ if (setaudit(&auinfo) != 0)
+ err(1, "setaudit failed");
+
+ if ((aufd = au_open()) == -1)
+ errx(1, "audit error: au_open() failed");
+
+ if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid,
+ pid, &tid)) == NULL)
+ errx(1, "audit error: au_to_subject32() failed");
+ au_write(aufd, tok);
+
+ if ((tok = au_to_return32(0, 0)) == NULL)
+ errx(1, "audit error: au_to_return32() failed");
+ au_write(aufd, tok);
+
+ if (au_close(aufd, 1, AUE_login) == -1)
+ errx(1, "audit record was not committed.");
+}
+
+/*
+ * The following tokens are included in the audit record for failed
+ * login attempts: header, subject, text, return.
+ */
+void
+au_login_fail(const char *errmsg, int na)
+{
+ token_t *tok;
+ int aufd;
+ int au_cond;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid = getpid();
+
+ /* If we are not auditing, don't cut an audit record; just return. */
+ if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
+ if (errno == ENOSYS)
+ return;
+ errx(1, "could not determine audit condition");
+ }
+ if (au_cond == AUC_NOAUDIT)
+ return;
+
+ if ((aufd = au_open()) == -1)
+ errx(1, "audit error: au_open() failed");
+
+ if (na) {
+ /*
+ * Non attributable event. Assuming that login is not called
+ * within a user's session => auid,asid == -1.
+ */
+ if ((tok = au_to_subject32(-1, geteuid(), getegid(), -1, -1,
+ pid, -1, &tid)) == NULL)
+ errx(1, "audit error: au_to_subject32() failed");
+ } else {
+ /* We know the subject -- so use its value instead. */
+ uid = pwd->pw_uid;
+ gid = pwd->pw_gid;
+ if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid,
+ gid, pid, pid, &tid)) == NULL)
+ errx(1, "audit error: au_to_subject32() failed");
+ }
+ au_write(aufd, tok);
+
+ /* Include the error message. */
+ if ((tok = au_to_text(errmsg)) == NULL)
+ errx(1, "audit error: au_to_text() failed");
+ au_write(aufd, tok);
+
+ if ((tok = au_to_return32(1, errno)) == NULL)
+ errx(1, "audit error: au_to_return32() failed");
+ au_write(aufd, tok);
+
+ if (au_close(aufd, 1, AUE_login) == -1)
+ errx(1, "audit error: au_close() was not committed");
+}
+
+/*
+ * The following tokens are included in the audit record for a logout:
+ * header, subject, return.
+ */
+void
+audit_logout(void)
+{
+ token_t *tok;
+ int aufd;
+ uid_t uid = pwd->pw_uid;
+ gid_t gid = pwd->pw_gid;
+ pid_t pid = getpid();
+ int au_cond;
+
+ /* If we are not auditing, don't cut an audit record; just return. */
+ if (auditon(A_GETCOND, &au_cond, sizeof(au_cond)) < 0) {
+ if (errno == ENOSYS)
+ return;
+ errx(1, "could not determine audit condition");
+ }
+ if (au_cond == AUC_NOAUDIT)
+ return;
+
+ if ((aufd = au_open()) == -1)
+ errx(1, "audit error: au_open() failed");
+
+ /* The subject that is created (euid, egid of the current process). */
+ if ((tok = au_to_subject32(uid, geteuid(), getegid(), uid, gid, pid,
+ pid, &tid)) == NULL)
+ errx(1, "audit error: au_to_subject32() failed");
+ au_write(aufd, tok);
+
+ if ((tok = au_to_return32(0, 0)) == NULL)
+ errx(1, "audit error: au_to_return32() failed");
+ au_write(aufd, tok);
+
+ if (au_close(aufd, 1, AUE_logout) == -1)
+ errx(1, "audit record was not committed.");
+}
diff --git a/usr.bin/login/login_fbtab.c b/usr.bin/login/login_fbtab.c
new file mode 100644
index 000000000000..5c846534d0c4
--- /dev/null
+++ b/usr.bin/login/login_fbtab.c
@@ -0,0 +1,139 @@
+/************************************************************************
+* Copyright 1995 by Wietse Venema. All rights reserved.
+*
+* This material was originally written and compiled by Wietse Venema at
+* Eindhoven University of Technology, The Netherlands, in 1990, 1991,
+* 1992, 1993, 1994 and 1995.
+*
+* Redistribution and use in source and binary forms are permitted
+* provided that this entire copyright notice is duplicated in all such
+* copies.
+*
+* This software is provided "as is" and without any expressed or implied
+* warranties, including, without limitation, the implied warranties of
+* merchantibility and fitness for any particular purpose.
+************************************************************************/
+/*
+ SYNOPSIS
+ void login_fbtab(tty, uid, gid)
+ char *tty;
+ uid_t uid;
+ gid_t gid;
+
+ DESCRIPTION
+ This module implements device security as described in the
+ SunOS 4.1.x fbtab(5) and SunOS 5.x logindevperm(4) manual
+ pages. The program first looks for /etc/fbtab. If that file
+ cannot be opened it attempts to process /etc/logindevperm.
+ We expect entries with the following format:
+
+ Comments start with a # and extend to the end of the line.
+
+ Blank lines or lines with only a comment are ignored.
+
+ All other lines consist of three fields delimited by
+ whitespace: a login device (/dev/console), an octal
+ permission number (0600), and a ":"-delimited list of
+ devices (/dev/kbd:/dev/mouse). All device names are
+ absolute paths. A path that ends in "*" refers to all
+ directory entries except "." and "..".
+
+ If the tty argument (relative path) matches a login device
+ name (absolute path), the permissions of the devices in the
+ ":"-delimited list are set as specified in the second
+ field, and their ownership is changed to that of the uid
+ and gid arguments.
+
+ DIAGNOSTICS
+ Problems are reported via the syslog daemon with severity
+ LOG_ERR.
+
+ BUGS
+ This module uses strtok(3), which may cause conflicts with other
+ uses of that same routine.
+
+ AUTHOR
+ Wietse Venema (wietse@wzv.win.tue.nl)
+ Eindhoven University of Technology
+ The Netherlands
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "login.h"
+#include "pathnames.h"
+
+static void login_protect(const char *, char *, int, uid_t, gid_t);
+
+#define WSPACE " \t\n"
+
+/* login_fbtab - apply protections specified in /etc/fbtab or logindevperm */
+
+void
+login_fbtab(char *tty, uid_t uid, gid_t gid)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ char *devname;
+ char *cp;
+ int prot;
+ const char *table;
+
+ if ((fp = fopen(table = _PATH_FBTAB, "r")) == NULL
+ && (fp = fopen(table = _PATH_LOGINDEVPERM, "r")) == NULL)
+ return;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ if ((cp = strchr(buf, '#')))
+ *cp = 0; /* strip comment */
+ if ((cp = devname = strtok(buf, WSPACE)) == NULL)
+ continue; /* empty or comment */
+ if (strncmp(devname, _PATH_DEV, sizeof _PATH_DEV - 1) != 0
+ || (cp = strtok(NULL, WSPACE)) == NULL
+ || *cp != '0'
+ || sscanf(cp, "%o", &prot) == 0
+ || prot == 0
+ || (prot & 0777) != prot
+ || (cp = strtok(NULL, WSPACE)) == NULL) {
+ syslog(LOG_ERR, "%s: bad entry: %s", table, cp ? cp : "(null)");
+ continue;
+ }
+ if (strcmp(devname + 5, tty) == 0) {
+ for (cp = strtok(cp, ":"); cp; cp = strtok(NULL, ":")) {
+ login_protect(table, cp, prot, uid, gid);
+ }
+ }
+ }
+ fclose(fp);
+}
+
+/* login_protect - protect one device entry */
+
+static void
+login_protect(const char *table, char *pattern, int mask, uid_t uid, gid_t gid)
+{
+ glob_t gl;
+ char *path;
+ unsigned int i;
+
+ if (glob(pattern, GLOB_NOSORT, NULL, &gl) != 0)
+ return;
+ for (i = 0; i < gl.gl_pathc; i++) {
+ path = gl.gl_pathv[i];
+ /* clear flags of the device */
+ if (chflags(path, 0) && errno != ENOENT && errno != EOPNOTSUPP)
+ syslog(LOG_ERR, "%s: chflags(%s): %m", table, path);
+ if (chmod(path, mask) && errno != ENOENT)
+ syslog(LOG_ERR, "%s: chmod(%s): %m", table, path);
+ if (chown(path, uid, gid) && errno != ENOENT)
+ syslog(LOG_ERR, "%s: chown(%s): %m", table, path);
+ }
+ globfree(&gl);
+}
diff --git a/usr.bin/login/motd.template b/usr.bin/login/motd.template
new file mode 100644
index 000000000000..e743370ca0a2
--- /dev/null
+++ b/usr.bin/login/motd.template
@@ -0,0 +1,20 @@
+
+Welcome to FreeBSD!
+
+Release Notes, Errata: https://www.FreeBSD.org/releases/
+Security Advisories: https://www.FreeBSD.org/security/
+FreeBSD Handbook: https://www.FreeBSD.org/handbook/
+FreeBSD FAQ: https://www.FreeBSD.org/faq/
+Questions List: https://www.FreeBSD.org/lists/questions/
+FreeBSD Forums: https://forums.FreeBSD.org/
+
+Documents installed with the system are in the /usr/local/share/doc/freebsd/
+directory, or can be installed later with: pkg install en-freebsd-doc
+For other languages, replace "en" with a language code like de or fr.
+
+Show the version of FreeBSD installed: freebsd-version ; uname -a
+Please include that output and any error messages when posting questions.
+Introduction to manual pages: man man
+FreeBSD directory layout: man hier
+
+To change this login announcement, see motd(5).
diff --git a/usr.bin/login/pathnames.h b/usr.bin/login/pathnames.h
new file mode 100644
index 000000000000..25de2baa75ec
--- /dev/null
+++ b/usr.bin/login/pathnames.h
@@ -0,0 +1,37 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <paths.h>
+
+#define _PATH_HUSHLOGIN ".hushlogin"
+#define _PATH_MOTDFILE "/var/run/motd"
+#define _PATH_FBTAB "/etc/fbtab"
+#define _PATH_LOGINDEVPERM "/etc/logindevperm"
diff --git a/usr.bin/logins/Makefile b/usr.bin/logins/Makefile
new file mode 100644
index 000000000000..44989870b319
--- /dev/null
+++ b/usr.bin/logins/Makefile
@@ -0,0 +1,3 @@
+PROG= logins
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/logins/Makefile.depend b/usr.bin/logins/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/logins/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/logins/logins.1 b/usr.bin/logins/logins.1
new file mode 100644
index 000000000000..2b6f27d71f1d
--- /dev/null
+++ b/usr.bin/logins/logins.1
@@ -0,0 +1,102 @@
+.\"-
+.\" Copyright (c) 2004 Dag-Erling Smørgrav
+.\" 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 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 AUTHOR 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 March 6, 2004
+.Dt LOGINS 1
+.Os
+.Sh NAME
+.Nm logins
+.Nd display account information
+.Sh SYNOPSIS
+.Nm
+.Op Fl admopstux
+.Op Fl g Ar groups
+.Op Fl l Ar logins
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about user and system accounts.
+.Pp
+The following options are available:
+.Bl -tag -width ".Fl g Ar groups"
+.It Fl a
+Display information about the password change and account expiration
+times for each account.
+.It Fl d
+Select accounts with duplicate UIDs.
+.It Fl g Ar groups
+Select accounts that are members of the specified groups.
+If multiple group names are specified, they must be separated with
+commas.
+.It Fl l Ar logins
+Select accounts matching the specified login names.
+If multiple names are specified, they must be separated with commas.
+.It Fl m
+Show information about secondary groups.
+.It Fl o
+Display the information for each account on a single line of
+colon-separated fields.
+.It Fl p
+Select accounts with no password.
+.It Fl s
+Select system accounts.
+These are currently defined as accounts with UIDs below 1000, plus the
+.Dq Li nobody
+account (UID 65534).
+.It Fl t
+Sort selected accounts by name rather than by UID.
+.It Fl u
+Select user accounts.
+These are currently defined as accounts with UIDs above 1000, except
+the
+.Dq Li nobody
+account (UID 65534).
+.It Fl x
+Display information about each account's home directory and shell.
+.El
+.Pp
+If multiple selection options are specified, all accounts matching any
+of the selection criteria will be displayed.
+.Pp
+If no selection options are specified, all accounts will be displayed.
+.Sh SEE ALSO
+.Xr getgrent 3 ,
+.Xr getpwent 3 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr pw 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 4.10 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org
+based on similar utilities in other operating systems.
diff --git a/usr.bin/logins/logins.c b/usr.bin/logins/logins.c
new file mode 100644
index 000000000000..683abf321547
--- /dev/null
+++ b/usr.bin/logins/logins.c
@@ -0,0 +1,406 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2004 Dag-Erling Smørgrav
+ * 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
+ * in this position and unchanged.
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+struct xpasswd {
+ char *pw_name;
+ char *pw_passwd;
+ uid_t pw_uid;
+ gid_t pw_gid;
+ time_t pw_change;
+ char *pw_class;
+ char *pw_gecos;
+ char *pw_dir;
+ char *pw_shell;
+ time_t pw_expire;
+ int pw_selected;
+};
+
+struct xgroup {
+ char *gr_name;
+ char *gr_passwd;
+ gid_t gr_gid;
+ char *gr_mem;
+};
+
+static int everything = 1;
+static int a_flag;
+static int d_flag;
+static const char *g_args;
+static const char *l_args;
+static int m_flag;
+static int o_flag;
+static int p_flag;
+static int s_flag;
+static int t_flag;
+static int u_flag;
+static int x_flag;
+
+static int
+member(const char *elem, const char *list)
+{
+ char *p;
+ int len;
+
+ p = strstr(list, elem);
+ len = strlen(elem);
+
+ return (p != NULL &&
+ (p == list || p[-1] == ',') &&
+ (p[len] == '\0' || p[len] == ','));
+}
+
+static void *
+xmalloc(size_t size)
+{
+ void *newptr;
+
+ if ((newptr = malloc(size)) == NULL)
+ err(1, "malloc()");
+ return (newptr);
+}
+
+static void *
+xrealloc(void *ptr, size_t size)
+{
+ void *newptr;
+
+ if ((newptr = realloc(ptr, size)) == NULL)
+ err(1, "realloc()");
+ return (newptr);
+}
+
+static char *
+xstrdup(const char *str)
+{
+ char *dupstr;
+
+ if ((dupstr = strdup(str)) == NULL)
+ err(1, "strdup()");
+ return (dupstr);
+}
+
+static struct xgroup *grps;
+static size_t grpsz;
+static size_t ngrps;
+
+static void
+get_groups(void)
+{
+ struct group *grp;
+ size_t len;
+ int i;
+
+ setgrent();
+ for (;;) {
+ if (ngrps == grpsz) {
+ grpsz += grpsz ? grpsz : 128;
+ grps = xrealloc(grps, grpsz * sizeof *grps);
+ }
+ if ((grp = getgrent()) == NULL)
+ break;
+ grps[ngrps].gr_name = xstrdup(grp->gr_name);
+ grps[ngrps].gr_passwd = xstrdup(grp->gr_passwd);
+ grps[ngrps].gr_gid = grp->gr_gid;
+ grps[ngrps].gr_mem = xstrdup("");
+ for (i = 0, len = 1; grp->gr_mem[i] != NULL; ++i)
+ len += strlen(grp->gr_mem[i]) + 1;
+ grps[ngrps].gr_mem = xmalloc(len);
+ for (i = 0, len = 0; grp->gr_mem[i] != NULL; ++i)
+ len += sprintf(grps[ngrps].gr_mem + len,
+ i ? ",%s" : "%s", grp->gr_mem[i]);
+ grps[ngrps].gr_mem[len] = '\0';
+ ngrps++;
+ }
+ endgrent();
+}
+
+static struct xgroup *
+find_group_bygid(gid_t gid)
+{
+ unsigned int i;
+
+ for (i = 0; i < ngrps; ++i)
+ if (grps[i].gr_gid == gid)
+ return (&grps[i]);
+ return (NULL);
+}
+
+#if 0
+static struct xgroup *
+find_group_byname(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ngrps; ++i)
+ if (strcmp(grps[i].gr_name, name) == 0)
+ return (&grps[i]);
+ return (NULL);
+}
+#endif
+
+static struct xpasswd *pwds;
+static size_t pwdsz;
+static size_t npwds;
+
+static int
+pwd_cmp_byname(const void *ap, const void *bp)
+{
+ const struct passwd *a = ap;
+ const struct passwd *b = bp;
+
+ return (strcmp(a->pw_name, b->pw_name));
+}
+
+static int
+pwd_cmp_byuid(const void *ap, const void *bp)
+{
+ const struct passwd *a = ap;
+ const struct passwd *b = bp;
+
+ return (a->pw_uid - b->pw_uid);
+}
+
+static void
+get_users(void)
+{
+ struct passwd *pwd;
+
+ setpwent();
+ for (;;) {
+ if (npwds == pwdsz) {
+ pwdsz += pwdsz ? pwdsz : 128;
+ pwds = xrealloc(pwds, pwdsz * sizeof *pwds);
+ }
+ if ((pwd = getpwent()) == NULL)
+ break;
+ pwds[npwds].pw_name = xstrdup(pwd->pw_name);
+ pwds[npwds].pw_passwd = xstrdup(pwd->pw_passwd);
+ pwds[npwds].pw_uid = pwd->pw_uid;
+ pwds[npwds].pw_gid = pwd->pw_gid;
+ pwds[npwds].pw_change = pwd->pw_change;
+ pwds[npwds].pw_class = xstrdup(pwd->pw_class);
+ pwds[npwds].pw_gecos = xstrdup(pwd->pw_gecos);
+ pwds[npwds].pw_dir = xstrdup(pwd->pw_dir);
+ pwds[npwds].pw_shell = xstrdup(pwd->pw_shell);
+ pwds[npwds].pw_expire = pwd->pw_expire;
+ pwds[npwds].pw_selected = 0;
+ npwds++;
+ }
+ endpwent();
+}
+
+static void
+select_users(void)
+{
+ unsigned int i, j;
+ struct xgroup *grp;
+ struct xpasswd *pwd;
+
+ for (i = 0, pwd = pwds; i < npwds; ++i, ++pwd) {
+ if (everything) {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ if (d_flag)
+ if ((i > 0 && pwd->pw_uid == pwd[-1].pw_uid) ||
+ (i < npwds - 1 && pwd->pw_uid == pwd[1].pw_uid)) {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ if (g_args) {
+ for (j = 0, grp = grps; j < ngrps; ++j, ++grp) {
+ if (member(grp->gr_name, g_args) &&
+ member(pwd->pw_name, grp->gr_mem)) {
+ pwd->pw_selected = 1;
+ break;
+ }
+ }
+ if (pwd->pw_selected)
+ continue;
+ }
+ if (l_args)
+ if (member(pwd->pw_name, l_args)) {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ if (p_flag)
+ if (pwd->pw_passwd[0] == '\0') {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ if (s_flag)
+ if (pwd->pw_uid < 1000 || pwd->pw_uid == 65534) {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ if (u_flag)
+ if (pwd->pw_uid >= 1000 && pwd->pw_uid != 65534) {
+ pwd->pw_selected = 1;
+ continue;
+ }
+ }
+}
+
+static void
+sort_users(void)
+{
+ if (t_flag)
+ mergesort(pwds, npwds, sizeof *pwds, pwd_cmp_byname);
+ else
+ mergesort(pwds, npwds, sizeof *pwds, pwd_cmp_byuid);
+}
+
+static void
+display_user(struct xpasswd *pwd)
+{
+ struct xgroup *grp;
+ unsigned int i;
+ char cbuf[16], ebuf[16];
+ struct tm *tm;
+
+ grp = find_group_bygid(pwd->pw_gid);
+ printf(o_flag ? "%s:%ld:%s:%ld:%s" : "%-15s %-7ld %-15s %-7ld %s\n",
+ pwd->pw_name, (long)pwd->pw_uid, grp ? grp->gr_name : "",
+ (long)pwd->pw_gid, pwd->pw_gecos);
+ if (m_flag) {
+ for (i = 0, grp = grps; i < ngrps; ++i, ++grp) {
+ if (grp->gr_gid == pwd->pw_gid ||
+ !member(pwd->pw_name, grp->gr_mem))
+ continue;
+ printf(o_flag ? "%s:%s:%ld" : "%24s%-15s %-7ld\n",
+ "", grp->gr_name, (long)grp->gr_gid);
+ }
+ }
+ if (x_flag) {
+ printf(o_flag ? "%s:%s" : "%24s%s\n", "", pwd->pw_dir);
+ printf(o_flag ? "%s:%s" : "%24s%s\n", "", pwd->pw_shell);
+ }
+ if (a_flag) {
+ tm = gmtime(&pwd->pw_change);
+ strftime(cbuf, sizeof(cbuf), pwd->pw_change ? "%F" : "0", tm);
+ tm = gmtime(&pwd->pw_expire);
+ strftime(ebuf, sizeof(ebuf), pwd->pw_expire ? "%F" : "0", tm);
+ printf(o_flag ? "%s:%s:%s" : "%24s%s %s\n", "", cbuf, ebuf);
+ }
+ if (o_flag)
+ printf("\n");
+}
+
+static void
+list_users(void)
+{
+ struct xpasswd *pwd;
+ unsigned int i;
+
+ for (i = 0, pwd = pwds; i < npwds; ++i, ++pwd)
+ if (pwd->pw_selected)
+ display_user(pwd);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: logins [-admopstux] [-g group] [-l login]\n");
+ exit(1);
+}
+
+int
+main(int argc, char * const argv[])
+{
+ int o;
+
+ while ((o = getopt(argc, argv, "adg:l:mopstux")) != -1)
+ switch (o) {
+ case 'a':
+ a_flag = 1;
+ break;
+ case 'd':
+ everything = 0;
+ d_flag = 1;
+ break;
+ case 'g':
+ everything = 0;
+ g_args = optarg;
+ break;
+ case 'l':
+ everything = 0;
+ l_args = optarg;
+ break;
+ case 'm':
+ m_flag = 1;
+ break;
+ case 'o':
+ o_flag = 1;
+ break;
+ case 'p':
+ everything = 0;
+ p_flag = 1;
+ break;
+ case 's':
+ everything = 0;
+ s_flag = 1;
+ break;
+ case 't':
+ t_flag = 1;
+ break;
+ case 'u':
+ everything = 0;
+ u_flag = 1;
+ break;
+ case 'x':
+ x_flag = 1;
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ usage();
+
+ get_groups();
+ get_users();
+ select_users();
+ sort_users();
+ list_users();
+ exit(0);
+}
diff --git a/usr.bin/logname/Makefile b/usr.bin/logname/Makefile
new file mode 100644
index 000000000000..b7422cbd53ae
--- /dev/null
+++ b/usr.bin/logname/Makefile
@@ -0,0 +1,3 @@
+PROG= logname
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/logname/Makefile.depend b/usr.bin/logname/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/logname/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/logname/logname.1 b/usr.bin/logname/logname.1
new file mode 100644
index 000000000000..b9c322c52f9e
--- /dev/null
+++ b/usr.bin/logname/logname.1
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 9, 1993
+.Dt LOGNAME 1
+.Os
+.Sh NAME
+.Nm logname
+.Nd display user's login name
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility writes the user's login name to standard output followed by
+a newline.
+.Pp
+The
+.Nm
+utility explicitly ignores the
+.Ev LOGNAME
+and
+.Ev USER
+environment variables
+because the environment cannot be trusted.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr who 1 ,
+.Xr whoami 1 ,
+.Xr getlogin 2
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.2 .
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.bin/logname/logname.c b/usr.bin/logname/logname.c
new file mode 100644
index 000000000000..e5eb81ff61ed
--- /dev/null
+++ b/usr.bin/logname/logname.c
@@ -0,0 +1,61 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993, 1994
+ * 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.
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void usage(void);
+
+int
+main(int argc, char *argv[] __unused)
+{
+ char *p;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ if (argc != 1)
+ usage();
+ if ((p = getlogin()) == NULL)
+ err(1, NULL);
+ (void)printf("%s\n", p);
+ exit(0);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: logname\n");
+ exit(1);
+}
diff --git a/usr.bin/look/Makefile b/usr.bin/look/Makefile
new file mode 100644
index 000000000000..e1331bfdce0d
--- /dev/null
+++ b/usr.bin/look/Makefile
@@ -0,0 +1,3 @@
+PROG= look
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/look/Makefile.depend b/usr.bin/look/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/look/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/look/look.1 b/usr.bin/look/look.1
new file mode 100644
index 000000000000..7d0b74b43486
--- /dev/null
+++ b/usr.bin/look/look.1
@@ -0,0 +1,152 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd December 29, 2020
+.Dt LOOK 1
+.Os
+.Sh NAME
+.Nm look
+.Nd display lines beginning with a given string
+.Sh SYNOPSIS
+.Nm
+.Op Fl df
+.Op Fl t Ar termchar
+.Ar string
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays any lines in
+.Ar file
+which contain
+.Ar string
+as a prefix.
+As
+.Nm
+performs a binary search, the lines in
+.Ar file
+must be sorted.
+.Pp
+If
+.Ar file
+is not specified, the file
+.Pa /usr/share/dict/words
+is used, only alphanumeric characters are compared and the case of
+alphabetic characters is ignored.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl d , -alphanum
+Dictionary character set and order, i.e., only alphanumeric characters
+are compared.
+.It Fl f , -ignore-case
+Ignore the case of alphabetic characters.
+.It Fl t , -terminate Ar termchar
+Specify a string termination character, i.e., only the characters
+in
+.Ar string
+up to and including the first occurrence of
+.Ar termchar
+are compared.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of the
+.Nm
+utility.
+Their effect is described in
+.Xr environ 7 .
+.Sh FILES
+.Bl -tag -width /usr/share/dict/words -compact
+.It Pa /usr/share/dict/words
+the dictionary
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 if one or more lines were found and displayed,
+1 if no lines were found, and >1 if an error occurred.
+.Sh EXAMPLES
+Look for lines starting with
+.Ql xylen
+in the file
+.Pa /usr/share/dict/words :
+.Bd -literal -offset indent
+$ look xylen
+xylene
+xylenol
+xylenyl
+.Ed
+.Pp
+Same as above, but do not consider any characters in
+.Ar string
+beyond the first
+.Ql e .
+Note that
+.Fl f
+is implicit since we are searching the default file
+.Pa /usr/share/dict/words :
+.Bd -literal -offset indent
+$ look -t e xylen
+Xyleborus
+xylem
+xylene
+xylenol
+xylenyl
+xyletic
+.Ed
+.Sh COMPATIBILITY
+The original manual page stated that tabs and blank characters participated
+in comparisons when the
+.Fl d
+option was specified.
+This was incorrect and the current man page matches the historic
+implementation.
+.Pp
+The
+.Fl a
+and
+.Fl -alternative
+flags are ignored for compatibility.
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr sort 1
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v7 .
+.Sh BUGS
+Lines are not compared according to the current locale's collating
+order.
+Input files must be sorted with
+.Ev LC_COLLATE
+set to
+.Ql C .
diff --git a/usr.bin/look/look.c b/usr.bin/look/look.c
new file mode 100644
index 000000000000..9486fed65b56
--- /dev/null
+++ b/usr.bin/look/look.c
@@ -0,0 +1,349 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems, 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.
+ */
+
+/*
+ * look -- find lines in a sorted list.
+ *
+ * The man page said that TABs and SPACEs participate in -d comparisons.
+ * In fact, they were ignored. This implements historic practice, not
+ * the manual page.
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "pathnames.h"
+
+static char _path_words[] = _PATH_WORDS;
+
+#define EQUAL 0
+#define GREATER 1
+#define LESS (-1)
+
+static int dflag, fflag;
+
+static char *binary_search(wchar_t *, unsigned char *, unsigned char *);
+static int compare(wchar_t *, unsigned char *, unsigned char *);
+static char *linear_search(wchar_t *, unsigned char *, unsigned char *);
+static int look(wchar_t *, unsigned char *, unsigned char *);
+static wchar_t *prepkey(const char *, wchar_t);
+static void print_from(wchar_t *, unsigned char *, unsigned char *);
+
+static void usage(void) __dead2;
+
+static struct option longopts[] = {
+ { "alternative",no_argument, NULL, 'a' },
+ { "alphanum", no_argument, NULL, 'd' },
+ { "ignore-case",no_argument, NULL, 'i' },
+ { "terminate", required_argument, NULL, 't'},
+ { NULL, 0, NULL, 0 },
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ int ch, fd, match;
+ wchar_t termchar;
+ unsigned char *back, *front;
+ unsigned const char *file;
+ wchar_t *key;
+
+ (void) setlocale(LC_CTYPE, "");
+
+ file = _path_words;
+ termchar = L'\0';
+ while ((ch = getopt_long(argc, argv, "+adft:", longopts, NULL)) != -1)
+ switch(ch) {
+ case 'a':
+ /* COMPATIBILITY */
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 't':
+ if (mbrtowc(&termchar, optarg, MB_LEN_MAX, NULL) !=
+ strlen(optarg))
+ errx(2, "invalid termination character");
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+ if (argc == 1) /* But set -df by default. */
+ dflag = fflag = 1;
+ key = prepkey(*argv++, termchar);
+ if (argc >= 2)
+ file = *argv++;
+
+ match = 1;
+
+ do {
+ if ((fd = open(file, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
+ err(2, "%s", file);
+ if ((uintmax_t)sb.st_size > (uintmax_t)SIZE_T_MAX)
+ errx(2, "%s: %s", file, strerror(EFBIG));
+ if (sb.st_size == 0) {
+ close(fd);
+ continue;
+ }
+ if ((front = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED, fd, (off_t)0)) == MAP_FAILED)
+ err(2, "%s", file);
+ back = front + sb.st_size;
+ match *= (look(key, front, back));
+ close(fd);
+ } while (argc-- > 2 && (file = *argv++));
+
+ exit(match);
+}
+
+static wchar_t *
+prepkey(const char *string, wchar_t termchar)
+{
+ const char *readp;
+ wchar_t *key, *writep;
+ wchar_t ch;
+ size_t clen;
+
+ /*
+ * Reformat search string and convert to wide character representation
+ * to avoid doing it multiple times later.
+ */
+ if ((key = malloc(sizeof(wchar_t) * (strlen(string) + 1))) == NULL)
+ err(2, NULL);
+ readp = string;
+ writep = key;
+ while ((clen = mbrtowc(&ch, readp, MB_LEN_MAX, NULL)) != 0) {
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ errc(2, EILSEQ, NULL);
+ if (fflag)
+ ch = towlower(ch);
+ if (!dflag || iswalnum(ch))
+ *writep++ = ch;
+ readp += clen;
+ }
+ *writep = L'\0';
+ if (termchar != L'\0' && (writep = wcschr(key, termchar)) != NULL)
+ *++writep = L'\0';
+ return (key);
+}
+
+static int
+look(wchar_t *string, unsigned char *front, unsigned char *back)
+{
+
+ front = binary_search(string, front, back);
+ front = linear_search(string, front, back);
+
+ if (front)
+ print_from(string, front, back);
+ return (front ? 0 : 1);
+}
+
+
+/*
+ * Binary search for "string" in memory between "front" and "back".
+ *
+ * This routine is expected to return a pointer to the start of a line at
+ * *or before* the first word matching "string". Relaxing the constraint
+ * this way simplifies the algorithm.
+ *
+ * Invariants:
+ * front points to the beginning of a line at or before the first
+ * matching string.
+ *
+ * back points to the beginning of a line at or after the first
+ * matching line.
+ *
+ * Base of the Invariants.
+ * front = NULL;
+ * back = EOF;
+ *
+ * Advancing the Invariants:
+ *
+ * p = first newline after halfway point from front to back.
+ *
+ * If the string at "p" is not greater than the string to match,
+ * p is the new front. Otherwise it is the new back.
+ *
+ * Termination:
+ *
+ * The definition of the routine allows it return at any point,
+ * since front is always at or before the line to print.
+ *
+ * In fact, it returns when the chosen "p" equals "back". This
+ * implies that there exists a string is least half as long as
+ * (back - front), which in turn implies that a linear search will
+ * be no more expensive than the cost of simply printing a string or two.
+ *
+ * Trying to continue with binary search at this point would be
+ * more trouble than it's worth.
+ */
+#define SKIP_PAST_NEWLINE(p, back) \
+ while (p < back && *p++ != '\n');
+
+static char *
+binary_search(wchar_t *string, unsigned char *front, unsigned char *back)
+{
+ unsigned char *p;
+
+ p = front + (back - front) / 2;
+ SKIP_PAST_NEWLINE(p, back);
+
+ /*
+ * If the file changes underneath us, make sure we don't
+ * infinitely loop.
+ */
+ while (p < back && back > front) {
+ if (compare(string, p, back) == GREATER)
+ front = p;
+ else
+ back = p;
+ p = front + (back - front) / 2;
+ SKIP_PAST_NEWLINE(p, back);
+ }
+ return (front);
+}
+
+/*
+ * Find the first line that starts with string, linearly searching from front
+ * to back.
+ *
+ * Return NULL for no such line.
+ *
+ * This routine assumes:
+ *
+ * o front points at the first character in a line.
+ * o front is before or at the first line to be printed.
+ */
+static char *
+linear_search(wchar_t *string, unsigned char *front, unsigned char *back)
+{
+ while (front < back) {
+ switch (compare(string, front, back)) {
+ case EQUAL: /* Found it. */
+ return (front);
+ case LESS: /* No such string. */
+ return (NULL);
+ case GREATER: /* Keep going. */
+ break;
+ }
+ SKIP_PAST_NEWLINE(front, back);
+ }
+ return (NULL);
+}
+
+/*
+ * Print as many lines as match string, starting at front.
+ */
+static void
+print_from(wchar_t *string, unsigned char *front, unsigned char *back)
+{
+ for (; front < back && compare(string, front, back) == EQUAL; ++front) {
+ for (; front < back && *front != '\n'; ++front)
+ if (putchar(*front) == EOF)
+ err(2, "stdout");
+ if (putchar('\n') == EOF)
+ err(2, "stdout");
+ }
+}
+
+/*
+ * Return LESS, GREATER, or EQUAL depending on how the string1 compares with
+ * string2 (s1 ??? s2).
+ *
+ * o Matches up to len(s1) are EQUAL.
+ * o Matches up to len(s2) are GREATER.
+ *
+ * Compare understands about the -f and -d flags, and treats comparisons
+ * appropriately.
+ *
+ * The string "s1" is null terminated. The string s2 is '\n' terminated (or
+ * "back" terminated).
+ */
+static int
+compare(wchar_t *s1, unsigned char *s2, unsigned char *back)
+{
+ wchar_t ch1, ch2;
+ size_t len2;
+
+ for (; *s1 && s2 < back && *s2 != '\n'; ++s1, s2 += len2) {
+ ch1 = *s1;
+ len2 = mbrtowc(&ch2, s2, back - s2, NULL);
+ if (len2 == (size_t)-1 || len2 == (size_t)-2) {
+ ch2 = *s2;
+ len2 = 1;
+ }
+ if (fflag)
+ ch2 = towlower(ch2);
+ if (dflag && !iswalnum(ch2)) {
+ /* Ignore character in comparison. */
+ --s1;
+ continue;
+ }
+ if (ch1 != ch2)
+ return (ch1 < ch2 ? LESS : GREATER);
+ }
+ return (*s1 ? GREATER : EQUAL);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: look [-df] [-t char] string [file ...]\n");
+ exit(2);
+}
diff --git a/usr.bin/look/pathnames.h b/usr.bin/look/pathnames.h
new file mode 100644
index 000000000000..e0c3296fc1ab
--- /dev/null
+++ b/usr.bin/look/pathnames.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_WORDS "/usr/share/dict/words"
diff --git a/usr.bin/lorder/Makefile b/usr.bin/lorder/Makefile
new file mode 100644
index 000000000000..5dc868f96c7e
--- /dev/null
+++ b/usr.bin/lorder/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+SCRIPTS=lorder.sh
+MAN= lorder.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lorder/Makefile.depend b/usr.bin/lorder/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/lorder/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lorder/lorder.1 b/usr.bin/lorder/lorder.1
new file mode 100644
index 000000000000..18c53b6cb918
--- /dev/null
+++ b/usr.bin/lorder/lorder.1
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd February 27, 2024
+.Dt LORDER 1
+.Os
+.Sh NAME
+.Nm lorder
+.Nd list dependencies for object files
+.Sh SYNOPSIS
+.Nm
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility uses
+.Xr nm 1
+to determine interdependencies between object files and library
+archives listed on its command line.
+It then outputs a list of pairs of file names such that the first file
+in each pair references at least one symbol defined by the second.
+.Pp
+The output is normally used with
+.Xr tsort 1
+when a library is created to determine the optimum ordering of the
+object modules so that all references may be resolved in a single
+pass of the loader.
+.Pp
+Similarly, when linking static binaries,
+.Nm
+and
+.Xr tsort 1
+can be used to sort libraries in order of dependency.
+.Pp
+While contemporary linkers no longer require the use of
+.Nm ,
+it is provided for the benefit of legacy code bases and build
+systems which still insist on it.
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It Ev NM
+Path to the
+.Xr nm 1
+binary, defaults to
+.Dq Li nm .
+.It Ev NMFLAGS
+Flags to pass to
+.Xr nm 1 .
+.El
+.Sh EXAMPLES
+.Bd -literal -offset indent
+ar cr library.a `lorder ${OBJS} | tsort`
+cc -o foo ${OBJS} `lorder ${STATIC_LIBS} | tsort`
+.Ed
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr nm 1 ,
+.Xr ranlib 1 ,
+.Xr tsort 1
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v7 .
+.Sh CAVEATS
+The
+.Nm
+utility will not work properly if given file names with spaces or
+newlines in them.
diff --git a/usr.bin/lorder/lorder.sh b/usr.bin/lorder/lorder.sh
new file mode 100644
index 000000000000..c6d69b2d1b0b
--- /dev/null
+++ b/usr.bin/lorder/lorder.sh
@@ -0,0 +1,110 @@
+#!/bin/sh -
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 1990, 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.
+
+export LC_CTYPE=C
+export LC_COLLATE=C
+set -e
+
+usage() {
+ echo "usage: lorder file ..." >&2
+ exit 1
+}
+
+while getopts "" opt ; do
+ case $opt in
+ *)
+ usage
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+if [ $# -eq 0 ] ; then
+ usage
+fi
+
+#
+# Create temporary files.
+#
+N=$(mktemp -t _nm_)
+R=$(mktemp -t _reference_)
+S=$(mktemp -t _symbol_)
+T=$(mktemp -t _temp_)
+NM=${NM:-nm}
+
+#
+# Remove temporary files on termination.
+#
+trap "rm -f $N $R $S $T" EXIT 1 2 3 13 15
+
+#
+# A line matching " [RTDW] " indicates that the input defines a symbol
+# with external linkage; put it in the symbol file.
+#
+# A line matching " U " indicates that the input references an
+# undefined symbol; put it in the reference file.
+#
+${NM} ${NMFLAGS} -go "$@" >$N
+sed -e "
+ / [RTDW] / {
+ s/:.* [RTDW] / /
+ w $S
+ d
+ }
+ / U / {
+ s/:.* U / /
+ w $R
+ }
+ d
+" <$N
+
+#
+# Elide entries representing a reference to a symbol from within the
+# library that defines it.
+#
+sort -u -o $S $S
+sort -u -o $R $R
+comm -23 $R $S >$T
+mv $T $R
+
+#
+# Make sure that all inputs get into the output.
+#
+for i ; do
+ echo "$i" "$i"
+done
+
+#
+# Sort references and symbols on the second field (the symbol), join
+# on that field, and print out the file names.
+#
+sort -k 2 -o $R $R
+sort -k 2 -o $S $S
+join -j 2 -o 1.1 -o 2.1 $R $S
diff --git a/usr.bin/lorder/tests/Makefile b/usr.bin/lorder/tests/Makefile
new file mode 100644
index 000000000000..21207f413a8d
--- /dev/null
+++ b/usr.bin/lorder/tests/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= tests
+ATF_TESTS_SH= lorder_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/lorder/tests/Makefile.depend b/usr.bin/lorder/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/lorder/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lorder/tests/lorder_test.sh b/usr.bin/lorder/tests/lorder_test.sh
new file mode 100644
index 000000000000..a4276b2dcfe6
--- /dev/null
+++ b/usr.bin/lorder/tests/lorder_test.sh
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2024 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+atf_test_case noargs
+noargs_head() {
+ atf_set descr "No arguments"
+}
+noargs_body() {
+ atf_check -s exit:1 -e match:"^usage:" \
+ lorder
+}
+
+atf_test_case onearg
+onearg_head() {
+ atf_set descr "One argument"
+}
+onearg_body() {
+ echo "void a(void) { }" >a.c
+ cc -o a.o -c a.c
+ echo "a.o a.o" >output
+ atf_check -o file:output \
+ lorder *.o
+}
+
+atf_test_case dashdash
+dashdash_head() {
+ atf_set descr "One argument"
+}
+dashdash_body() {
+ echo "void a(void) { }" >a.c
+ cc -o a.o -c a.c
+ echo "a.o a.o" >output
+ atf_check -o file:output \
+ lorder -- *.o
+}
+
+atf_test_case nonexistent
+nonexistent_head() {
+ atf_set descr "Nonexistent file"
+}
+nonexistent_body() {
+ atf_check -s not-exit:0 -e match:"No such file" -o empty \
+ lorder nonexistent.o
+}
+
+atf_test_case invalid
+invalid_head() {
+ atf_set descr "Invalid file"
+}
+invalid_body() {
+ echo "not an object file" >invalid.o
+ atf_check -s not-exit:0 -e match:"not recognized" -o empty \
+ lorder invalid.o
+}
+
+atf_test_case objects
+objects_head() {
+ atf_set descr "Order objects"
+}
+objects_body() {
+ echo "void a(void) { }" >a.c
+ echo "void a(void); void b(void) { a(); }" >b.c
+ echo "void b(void); void c(void) { b(); }" >c.c
+ for n in a b c ; do
+ cc -o $n.o -c $n.c
+ echo "$n.o $n.o"
+ done >output
+ echo "b.o a.o" >>output
+ echo "c.o b.o" >>output
+ atf_check -o file:output \
+ lorder *.o
+}
+
+atf_test_case archives
+archives_head() {
+ atf_set descr "Order archives"
+}
+archives_body() {
+ echo "void a(void) { }" >a.c
+ echo "void a(void); void b(void) { a(); }" >b.c
+ echo "void b(void); void c(void) { b(); }" >c.c
+ echo "void e(void); void d(void) { e(); }" >d.c
+ echo "void d(void); void e(void) { d(); }" >e.c
+ for n in a b c d e ; do
+ cc -o $n.o -c $n.c
+ done
+ for n in a b c ; do
+ ar -crs $n.a $n.o
+ echo "$n.a $n.a"
+ done >output
+ ar -crs z.a d.o e.o
+ echo "z.a z.a" >>output
+ echo "b.a a.a" >>output
+ echo "c.a b.a" >>output
+ atf_check -o file:output \
+ lorder *.a
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case noargs
+ atf_add_test_case onearg
+ atf_add_test_case dashdash
+ atf_add_test_case nonexistent
+ atf_add_test_case invalid
+ atf_add_test_case objects
+ atf_add_test_case archives
+}
diff --git a/usr.bin/lsvfs/Makefile b/usr.bin/lsvfs/Makefile
new file mode 100644
index 000000000000..70c8f642897a
--- /dev/null
+++ b/usr.bin/lsvfs/Makefile
@@ -0,0 +1,3 @@
+PROG= lsvfs
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lsvfs/Makefile.depend b/usr.bin/lsvfs/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/lsvfs/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/lsvfs/lsvfs.1 b/usr.bin/lsvfs/lsvfs.1
new file mode 100644
index 000000000000..9871df32fa96
--- /dev/null
+++ b/usr.bin/lsvfs/lsvfs.1
@@ -0,0 +1,70 @@
+.\" Garrett A. Wollman, September 1994
+.\" This file is in the public domain.
+.\"
+.Dd December 28, 2020
+.Dt LSVFS 1
+.Os
+.Sh NAME
+.Nm lsvfs
+.Nd list installed virtual file systems
+.Sh SYNOPSIS
+.Nm
+.Op Ar vfsname Ar ...
+.Sh DESCRIPTION
+The
+.Nm
+command lists information about the currently loaded virtual file system
+modules.
+When
+.Ar vfsname
+arguments are given,
+.Nm
+lists information about the specified VFS modules.
+Otherwise,
+.Nm
+lists all currently loaded modules.
+The information is as follows:
+.Pp
+.Bl -tag -compact -width Filesystem
+.It Filesystem
+the name of the file system, as would be used in the
+.Ar type
+parameter to
+.Xr mount 2
+and the
+.Fl t
+option to
+.Xr mount 8
+.It Num
+the filesystem type number.
+.It Refs
+the number of references to this VFS; i.e., the number of currently
+mounted file systems of this type
+.It Flags
+flag bits.
+.El
+.Sh EXAMPLES
+Show information about the
+.Ql ufs
+and
+.Xr devfs 4
+filesystems and check the number of mounts for the former:
+.Bd -literal -offset indent
+$ lsvfs ufs devfs
+Filesystem Num Refs Flags
+-------------------------------- ---------- ----- ---------------
+ufs 0x00000035 2
+devfs 0x00000071 1 synthetic, jail
+
+$ mount -t ufs | wc -l
+ 2
+.Ed
+.Sh SEE ALSO
+.Xr mount 2 ,
+.Xr getvfsbyname 3 ,
+.Xr mount 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.Fx 2.0 .
diff --git a/usr.bin/lsvfs/lsvfs.c b/usr.bin/lsvfs/lsvfs.c
new file mode 100644
index 000000000000..04ed38e8d978
--- /dev/null
+++ b/usr.bin/lsvfs/lsvfs.c
@@ -0,0 +1,99 @@
+/*
+ * lsvfs - list loaded VFSes
+ * Garrett A. Wollman, September 1994
+ * This file is in the public domain.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FMT "%-32.32s 0x%08x %5d %s\n"
+#define HDRFMT "%-32.32s %10s %5.5s %s\n"
+#define DASHES "-------------------------------- " \
+ "---------- ----- ---------------\n"
+
+static struct flaglist {
+ int flag;
+ const char str[32]; /* must be longer than the longest one. */
+} fl[] = {
+ { .flag = VFCF_STATIC, .str = "static", },
+ { .flag = VFCF_NETWORK, .str = "network", },
+ { .flag = VFCF_READONLY, .str = "read-only", },
+ { .flag = VFCF_SYNTHETIC, .str = "synthetic", },
+ { .flag = VFCF_LOOPBACK, .str = "loopback", },
+ { .flag = VFCF_UNICODE, .str = "unicode", },
+ { .flag = VFCF_JAIL, .str = "jail", },
+ { .flag = VFCF_DELEGADMIN, .str = "delegated-administration", },
+};
+
+static const char *fmt_flags(int);
+
+int
+main(int argc, char **argv)
+{
+ struct xvfsconf vfc, *xvfsp;
+ size_t buflen;
+ int cnt, i, rv = 0;
+
+ argc--, argv++;
+
+ printf(HDRFMT, "Filesystem", "Num", "Refs", "Flags");
+ fputs(DASHES, stdout);
+
+ if (argc > 0) {
+ for (; argc > 0; argc--, argv++) {
+ if (getvfsbyname(*argv, &vfc) == 0) {
+ printf(FMT, vfc.vfc_name, vfc.vfc_typenum,
+ vfc.vfc_refcount, fmt_flags(vfc.vfc_flags));
+ } else {
+ warnx("VFS %s unknown or not loaded", *argv);
+ rv++;
+ }
+ }
+ } else {
+ if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0)
+ err(1, "sysctl(vfs.conflist)");
+ xvfsp = malloc(buflen);
+ if (xvfsp == NULL)
+ errx(1, "malloc failed");
+ if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0)
+ err(1, "sysctl(vfs.conflist)");
+ cnt = buflen / sizeof(struct xvfsconf);
+
+ for (i = 0; i < cnt; i++) {
+ printf(FMT, xvfsp[i].vfc_name, xvfsp[i].vfc_typenum,
+ xvfsp[i].vfc_refcount,
+ fmt_flags(xvfsp[i].vfc_flags));
+ }
+ free(xvfsp);
+ }
+
+ return (rv);
+}
+
+static const char *
+fmt_flags(int flags)
+{
+ static char buf[sizeof(struct flaglist) * sizeof(fl)];
+ int i;
+
+ buf[0] = '\0';
+ for (i = 0; i < (int)nitems(fl); i++) {
+ if ((flags & fl[i].flag) != 0) {
+ strlcat(buf, fl[i].str, sizeof(buf));
+ strlcat(buf, ", ", sizeof(buf));
+ }
+ }
+
+ /* Zap the trailing comma + space. */
+ if (buf[0] != '\0')
+ buf[strlen(buf) - 2] = '\0';
+ return (buf);
+}
diff --git a/usr.bin/lzmainfo/Makefile b/usr.bin/lzmainfo/Makefile
new file mode 100644
index 000000000000..471d9055e8c7
--- /dev/null
+++ b/usr.bin/lzmainfo/Makefile
@@ -0,0 +1,19 @@
+PROG= lzmainfo
+
+XZDIR= ${SRCTOP}/contrib/xz/src
+LZMALIBDIR= ${SRCTOP}/lib/liblzma
+
+.PATH: ${XZDIR}/lzmainfo
+SRCS+= lzmainfo.c
+
+.PATH: ${XZDIR}/common
+SRCS+= tuklib_progname.c \
+ tuklib_exit.c
+
+CFLAGS+= -DHAVE_CONFIG_H \
+ -I${LZMALIBDIR} \
+ -I${XZDIR}/common
+
+LIBADD= lzma
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/lzmainfo/Makefile.depend b/usr.bin/lzmainfo/Makefile.depend
new file mode 100644
index 000000000000..b6a7bfecc03d
--- /dev/null
+++ b/usr.bin/lzmainfo/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/liblzma \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/m4/Makefile b/usr.bin/m4/Makefile
new file mode 100644
index 000000000000..f39d613e08d7
--- /dev/null
+++ b/usr.bin/m4/Makefile
@@ -0,0 +1,33 @@
+# $OpenBSD: Makefile,v 1.13 2014/05/12 19:11:19 espie Exp $
+
+# -DEXTENDED
+# if you want the paste & spaste macros.
+
+.include <src.opts.mk>
+
+PROG= m4
+CFLAGS+=-DEXTENDED -I${.CURDIR} -I${SRCTOP}/lib/libopenbsd
+LIBADD= m openbsd
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c parser.y
+.if target(bootstrap_m4_tokenizer)
+# When crossbuilding on non-FreeBSD we need to first build m4 with pre-generated
+# tokenizer files and the build the real m4 once we have lex+yacc.
+SRCS+= tokenizer.c
+.else
+SRCS+= tokenizer.l
+.endif
+
+GENFILES= tokenizer.c parser.c parser.h
+WARNS?= 3
+
+tokenizer.o: parser.h
+
+CLEANFILES+= parser.c parser.h tokenizer.o tokenizer.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/m4/Makefile.depend b/usr.bin/m4/Makefile.depend
new file mode 100644
index 000000000000..ac0fcff6439b
--- /dev/null
+++ b/usr.bin/m4/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libopenbsd \
+ lib/msun \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/m4/NOTES b/usr.bin/m4/NOTES
new file mode 100644
index 000000000000..d60f80eb5765
--- /dev/null
+++ b/usr.bin/m4/NOTES
@@ -0,0 +1,64 @@
+m4 - macro processor
+
+PD m4 is based on the macro tool distributed with the software
+tools (VOS) package, and described in the "SOFTWARE TOOLS" and
+"SOFTWARE TOOLS IN PASCAL" books. It has been expanded to include
+most of the command set of SysV m4, the standard UN*X macro processor.
+
+Since both PD m4 and UN*X m4 are based on SOFTWARE TOOLS macro,
+there may be certain implementation similarities between
+the two. The PD m4 was produced without ANY references to m4
+sources.
+
+written by: Ozan S. Yigit
+
+References:
+
+ Software Tools distribution: macro
+
+ Kernighan, Brian W. and P. J. Plauger, SOFTWARE
+ TOOLS IN PASCAL, Addison-Wesley, Mass. 1981
+
+ Kernighan, Brian W. and P. J. Plauger, SOFTWARE
+ TOOLS, Addison-Wesley, Mass. 1976
+
+ Kernighan, Brian W. and Dennis M. Ritchie,
+ THE M4 MACRO PROCESSOR, Unix Programmer's Manual,
+ Seventh Edition, Vol. 2, Bell Telephone Labs, 1979
+
+ System V man page for M4
+
+
+Implementation Notes:
+
+[1] PD m4 uses a different (and simpler) stack mechanism than the one
+ described in Software Tools and Software Tools in Pascal books.
+ The triple stack thing is replaced with a single stack containing
+ the call frames and the arguments. Each frame is back-linked to a
+ previous stack frame, which enables us to rewind the stack after
+ each nested call is completed. Each argument is a character pointer
+ to the beginning of the argument string within the string space.
+ The only exceptions to this are (*) arg 0 and arg 1, which are
+ the macro definition and macro name strings, stored dynamically
+ for the hash table.
+
+ . .
+ | . | <-- sp | . |
+ +-------+ +-----+
+ | arg 3 ------------------------------->| str |
+ +-------+ | . |
+ | arg 2 --------------+ .
+ +-------+ |
+ * | | |
+ +-------+ | +-----+
+ | plev | <-- fp +---------------->| str |
+ +-------+ | . |
+ | type | .
+ +-------+
+ | prcf -----------+ plev: paren level
+ +-------+ | type: call type
+ | . | | prcf: prev. call frame
+ . |
+ +-------+ |
+ | <----------+
+ +-------+
diff --git a/usr.bin/m4/TEST/ack.m4 b/usr.bin/m4/TEST/ack.m4
new file mode 100644
index 000000000000..d922709bcb3e
--- /dev/null
+++ b/usr.bin/m4/TEST/ack.m4
@@ -0,0 +1,36 @@
+# $OpenBSD: ack.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: ack.m4,v 1.4 1995/09/28 05:37:54 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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(ack, `ifelse($1,0,incr($2),$2,0,`ack(DECR($1),1)',
+`ack(DECR($1), ack($1,DECR($2)))')')
diff --git a/usr.bin/m4/TEST/hanoi.m4 b/usr.bin/m4/TEST/hanoi.m4
new file mode 100644
index 000000000000..c1d789060b1f
--- /dev/null
+++ b/usr.bin/m4/TEST/hanoi.m4
@@ -0,0 +1,41 @@
+# $OpenBSD: hanoi.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: hanoi.m4,v 1.4 1995/09/28 05:37:56 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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(hanoi, `trans(A, B, C, $1)')
+
+define(moved,`move disk from $1 to $2
+')
+
+define(trans, `ifelse($4,1,`moved($1,$2)',
+ `trans($1,$3,$2,DECR($4))moved($1,$2)trans($3,$2,$1,DECR($4))')')
diff --git a/usr.bin/m4/TEST/hash.m4 b/usr.bin/m4/TEST/hash.m4
new file mode 100644
index 000000000000..5b595000ea93
--- /dev/null
+++ b/usr.bin/m4/TEST/hash.m4
@@ -0,0 +1,51 @@
+# $OpenBSD: hash.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: hash.m4,v 1.4 1995/09/28 05:37:58 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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.
+#
+
+dnl This probably will not run on any m4 that cannot
+dnl handle char constants in eval.
+dnl
+changequote(<,>) define(HASHVAL,99) dnl
+define(hash,<eval(str(substr($1,1),0)%HASHVAL)>) dnl
+define(str,
+ <ifelse($1,",$2,
+ <str(substr(<$1>,1),<eval($2+'substr($1,0,1)')>)>)
+ >) dnl
+define(KEYWORD,<$1,hash($1),>) dnl
+define(TSTART,
+<struct prehash {
+ char *keyword;
+ int hashval;
+} keytab[] = {>) dnl
+define(TEND,< "",0
+};>) dnl
diff --git a/usr.bin/m4/TEST/math.m4 b/usr.bin/m4/TEST/math.m4
new file mode 100644
index 000000000000..e8cae3333b4e
--- /dev/null
+++ b/usr.bin/m4/TEST/math.m4
@@ -0,0 +1,180 @@
+dnl A regression test for m4 C operators (ksb,petef)
+dnl If you think you have a short-circuiting m4, run us m4 -DSHORCIRCUIT=yes
+dnl
+dnl first level of precedence
+ifelse(expr(-7),-7,,`failed -
+')dnl
+ifelse(expr(- -2),2,,`failed -
+')dnl
+ifelse(expr(!0),1,,`failed !
+')dnl
+ifelse(expr(!7),0,,`failed !
+')dnl
+ifelse(expr(~-1),0,,`failed ~
+')dnl
+dnl next level of precedence
+ifelse(expr(3*5),15,,`failed *
+')dnl
+ifelse(expr(3*0),0,,`failed *
+')dnl
+ifelse(expr(11/2),5,,`failed /
+')dnl
+ifelse(expr(1/700),0,,`failed /
+')dnl
+ifelse(expr(10%5),0,,`failed %
+')dnl
+ifelse(expr(2%5),2,,`failed %
+')dnl
+ifelse(expr(2%-1),0,,`failed %
+')dnl
+dnl next level of precedence
+ifelse(expr(2+2),4,,`failed +
+')dnl
+ifelse(expr(2+-2),0,,`failed +
+')dnl
+ifelse(expr(2- -2),4,,`failed -
+')dnl
+ifelse(expr(2-2),0,,`failed -
+')dnl
+dnl next level of precedence
+ifelse(expr(1<<4),16,,`failed <<
+')dnl
+ifelse(expr(16>>4),1,,`failed >>
+')dnl
+dnl next level of precedence
+ifelse(expr(4<4),0,,`failed <
+')dnl
+ifelse(expr(4<5),1,,`failed <
+')dnl
+ifelse(expr(4<3),0,,`failed <
+')dnl
+ifelse(expr(4>4),0,,`failed >
+')dnl
+ifelse(expr(4>5),0,,`failed >
+')dnl
+ifelse(expr(4>3),1,,`failed >
+')dnl
+ifelse(expr(4<=4),1,,`failed <=
+')dnl
+ifelse(expr(4<=5),1,,`failed <=
+')dnl
+ifelse(expr(4<=3),0,,`failed <=
+')dnl
+ifelse(expr(4>=4),1,,`failed >=
+')dnl
+ifelse(expr(4>=5),0,,`failed >=
+')dnl
+ifelse(expr(4>=3),1,,`failed >=
+')dnl
+dnl next level of precedence
+ifelse(expr(1==1),1,,`failed ==
+')dnl
+ifelse(expr(1==-1),0,,`failed ==
+')dnl
+ifelse(expr(1!=1),0,,`failed !=
+')dnl
+ifelse(expr(1!=2),1,,`failed !=
+')dnl
+dnl next level of precedence
+ifelse(expr(3&5),1,,`failed &
+')dnl
+ifelse(expr(8&7),0,,`failed &
+')dnl
+dnl next level of precedence
+ifelse(expr(1^1),0,,`failed ^
+')dnl
+ifelse(expr(21^5),16,,`failed ^
+')dnl
+dnl next level of precedence
+ifelse(expr(1|1),1,,`failed |
+')dnl
+ifelse(expr(21|5),21,,`failed |
+')dnl
+ifelse(expr(100|1),101,,`failed |
+')dnl
+dnl next level of precedence
+ifelse(expr(1&&1),1,,`failed &&
+')dnl
+ifelse(expr(0&&1),0,,`failed &&
+')dnl
+ifelse(expr(1&&0),0,,`failed &&
+')dnl
+ifelse(SHORTCIRCUIT,`yes',`ifelse(expr(0&&10/0),0,,`failed && shortcircuit
+')')dnl
+dnl next level of precedence
+ifelse(expr(1||1),1,,`failed ||
+')dnl
+ifelse(expr(1||0),1,,`failed ||
+')dnl
+ifelse(expr(0||0),0,,`failed ||
+')dnl
+ifelse(SHORTCIRCUIT,`yes',`ifelse(expr(1||10/0),1,,`failed || shortcircuit
+')')dnl
+dnl next level of precedence
+ifelse(expr(0 ? 2 : 5),5,,`failed ?:
+')dnl
+ifelse(expr(1 ? 2 : 5),2,,`failed ?:
+')dnl
+ifelse(SHORTCIRCUIT,`yes',`ifelse(expr(0 ? 10/0 : 7),7,,`failed ?: shortcircuit
+')')dnl
+ifelse(SHORTCIRCUIT,`yes',`ifelse(expr(1 ? 7 : 10/0),7,,`failed ?: shortcircuit
+')')dnl
+dnl operator precedence
+ifelse(expr(!0*-2),-2,,`precedence wrong, ! *
+')dnl
+ifelse(expr(~8/~2),3,,`precedence wrong ~ /
+')dnl
+ifelse(expr(~-20%7),5,,`precedence wrong ~ %
+')dnl
+ifelse(expr(3*2+100),106,,`precedence wrong * +
+')dnl
+ifelse(expr(3+2*100),203,,`precedence wrong + *
+')dnl
+ifelse(expr(2%5-6/3),0,,`precedence wrong % -
+')dnl
+ifelse(expr(2/5-5%3),-2,,`precedence wrong / -
+')dnl
+ifelse(expr(2+5%5+1),3,,`precedence wrong % +
+')dnl
+ifelse(expr(7+9<<1),32,,`precedence wrong + <<
+')dnl
+ifelse(expr(35-3>>2),8,,`precedence wrong - >>
+')dnl
+ifelse(expr(9<10<<5),1,,`precedence wrong << <
+')dnl
+ifelse(expr(9>10<<5),0,,`precedence wrong << >
+')dnl
+ifelse(expr(32>>2<32),1,,`precedence wrong >> <
+')dnl
+ifelse(expr(9<=10<<5),1,,`precedence wrong << <
+')dnl
+ifelse(expr(5<<1<=20>>1),1,,`precedence wrong << <=
+')dnl
+ifelse(expr(5<<1>=20>>1),1,,`precedence wrong << >=
+')dnl
+ifelse(expr(0<7==5>=5),1,,`precedence wrong < ==
+')dnl
+ifelse(expr(0<7!=5>=5),0,,`precedence wrong < !=
+')dnl
+ifelse(expr(0>7==5>=5),0,,`precedence wrong > ==
+')dnl
+ifelse(expr(0>7!=5>=5),1,,`precedence wrong > !=
+')dnl
+ifelse(expr(1&7==7),1,,`precedence wrong & ==
+')dnl
+ifelse(expr(0&7!=6),0,,`precedence wrong & !=
+')dnl
+ifelse(expr(9&1|5),5,,`precedence wrong & |
+')dnl
+ifelse(expr(9&1^5),4,,`precedence wrong & ^
+')dnl
+ifelse(expr(9^1|5),13,,`precedence wrong ^ |
+')dnl
+ifelse(expr(5|0&&1),1,,`precedence wrong | &&
+')dnl
+ifelse(expr(5&&0||0&&5||5),1,,`precedence wrong && ||
+')dnl
+ifelse(expr(0 || 1 ? 0 : 1),0,,`precedence wrong || ?:
+')dnl
+ifelse(expr(5&&(0||0)&&(5||5)),0,,`precedence wrong || parens
+')dnl
diff --git a/usr.bin/m4/TEST/sqroot.m4 b/usr.bin/m4/TEST/sqroot.m4
new file mode 100644
index 000000000000..0c28b35dff87
--- /dev/null
+++ b/usr.bin/m4/TEST/sqroot.m4
@@ -0,0 +1,41 @@
+# $OpenBSD: sqroot.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: sqroot.m4,v 1.4 1995/09/28 05:38:01 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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(square_root,
+ `ifelse(eval($1<0),1,negative-square-root,
+ `square_root_aux($1, 1, eval(($1+1)/2))')')
+define(square_root_aux,
+ `ifelse($3, $2, $3,
+ $3, eval($1/$2), $3,
+ `square_root_aux($1, $3, eval(($3+($1/$3))/2))')')
diff --git a/usr.bin/m4/TEST/string.m4 b/usr.bin/m4/TEST/string.m4
new file mode 100644
index 000000000000..2079272409f4
--- /dev/null
+++ b/usr.bin/m4/TEST/string.m4
@@ -0,0 +1,41 @@
+# $OpenBSD: string.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: string.m4,v 1.4 1995/09/28 05:38:03 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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(string,`integer $1(len(substr($2,1)))
+str($1,substr($2,1),0)
+data $1(len(substr($2,1)))/EOS/
+')
+
+define(str,`ifelse($2,",,data $1(incr($3))/`LET'substr($2,0,1)/
+`str($1,substr($2,1),incr($3))')')
diff --git a/usr.bin/m4/TEST/test.m4 b/usr.bin/m4/TEST/test.m4
new file mode 100644
index 000000000000..2668b3dfe1f9
--- /dev/null
+++ b/usr.bin/m4/TEST/test.m4
@@ -0,0 +1,239 @@
+# $OpenBSD: test.m4,v 1.3 2003/06/03 02:56:11 millert Exp $
+# $NetBSD: test.m4,v 1.4 1995/09/28 05:38:05 tls Exp $
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Ozan Yigit.
+#
+# 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 file for mp (not comprehensive)
+#
+# v7 m4 does not have `decr'.
+#
+define(DECR,`eval($1-1)')
+#
+# include string macros
+#
+include(string.m4)
+#
+# create some fortrash strings for an even uglier language
+#
+string(TEXT, "text")
+string(DATA, "data")
+string(BEGIN, "begin")
+string(END, "end")
+string(IF, "if")
+string(THEN, "then")
+string(ELSE, "else")
+string(CASE, "case")
+string(REPEAT, "repeat")
+string(WHILE, "while")
+string(DEFAULT, "default")
+string(UNTIL, "until")
+string(FUNCTION, "function")
+string(PROCEDURE, "procedure")
+string(EXTERNAL, "external")
+string(FORWARD, "forward")
+string(TYPE, "type")
+string(VAR, "var")
+string(CONST, "const")
+string(PROGRAM, "program")
+string(INPUT, "input")
+string(OUTPUT, "output")
+#
+divert(2)
+diversion #1
+divert(3)
+diversion #2
+divert(4)
+diversion #3
+divert(5)
+diversion #4
+divert(0)
+define(abc,xxx)
+ifdef(`abc',defined,undefined)
+#
+# v7 m4 does this wrong. The right output is
+# this is A vEry lon sEntEnCE
+# see m4 documentation for translit.
+#
+translit(`this is a very long sentence', abcdefg, ABCDEF)
+#
+# include towers-of-hanoi
+#
+include(hanoi.m4)
+#
+# some reasonable set of disks
+#
+hanoi(6)
+#
+# include ackermann's function
+#
+include(ack.m4)
+#
+# something like (3,3) will blow away un*x m4.
+#
+ack(2,3)
+#
+# include a square_root function for fixed nums
+#
+include(sqroot.m4)
+#
+# some square roots.
+#
+square_root(15)
+square_root(100)
+square_root(-4)
+square_root(21372)
+#
+# some textual material for enjoyment.
+#
+[taken from the 'Clemson University Computer Newsletter',
+ September 1981, pp. 6-7]
+
+I am a wizard in the magical Kingdom of Transformation and I
+slay dragons for a living. Actually, I am a systems programmer.
+One of the problems with systems programming is explaining to
+non-computer enthusiasts what that is. All of the terms I use to
+describe my job are totally meaningless to them. Usually my response
+to questions about my work is to say as little as possible. For
+instance, if someone asks what happened at work this week, I say
+"Nothing much" and then I change the subject.
+
+With the assistance of my brother, a mechanical engineer, I have devised
+an analogy that everyone can understand. The analogy describes the
+"Kingdom of Transformation" where travelers wander and are magically
+transformed. This kingdom is the computer and the travelers are information.
+The purpose of the computer is to change information to a more meaningful
+forma. The law of conservation applies here: The computer never creates
+and never intentionally destroys data. With no further ado, let us travel
+to the Kingdom of Transformation:
+
+In a land far, far away, there is a magical kingdom called the Kingdom of
+Transformation. A king rules over this land and employs a Council of
+Wizardry. The main purpose of this kingdom is to provide a way for
+neighboring kingdoms to transform citizens into more useful citizens. This
+is done by allowing the citizens to enter the kingdom at one of its ports
+and to travel any of the many routes in the kingdom. They are magically
+transformed along the way. The income of the Kingdom of Transformation
+comes from the many toll roads within its boundaries.
+
+The Kingdom of Transformation was created when several kingdoms got
+together and discovered a mutual need for new talents and abilities for
+citizens. They employed CTK, Inc. (Creators of Transformation, Inc.) to
+create this kingdom. CTK designed the country, its transportation routes,
+and its laws of transformation, and created the major highway system.
+
+Hazards
+=======
+
+Because magic is not truly controllable, CTK invariably, but unknowingly,
+creates dragons. Dragons are huge fire-breathing beasts which sometimes
+injure or kill travelers. Fortunately, they do not travel, but always
+remain near their den.
+
+Other hazards also exist which are potentially harmful. As the roads
+become older and more weatherbeaten, pot-holes will develop, trees will
+fall on travelers, etc. CTK maintenance men are called to fix these
+problems.
+
+Wizards
+=======
+
+The wizards play a major role in creating and maintaining the kingdom but
+get little credit for their work because it is performed secretly. The
+wizards do not wan the workers or travelers to learn their incantations
+because many laws would be broken and chaos would result.
+
+CTK's grand design is always general enough to be applicable in many
+different situations. As a result, it is often difficult to use. The
+first duty of the wizards is to tailor the transformation laws so as to be
+more beneficial and easier to use in their particular environment.
+
+After creation of the kingdom, a major duty of the wizards is to search for
+and kill dragons. If travelers do not return on time or if they return
+injured, the ruler of the country contacts the wizards. If the wizards
+determine that the injury or death occurred due to the traveler's
+negligence, they provide the traveler's country with additional warnings.
+If not, they must determine if the cause was a road hazard or a dragon. If
+the suspect a road hazard, they call in a CTK maintenance man to locate the
+hazard and to eliminate it, as in repairing the pothole in the road. If
+they think that cause was a dragon, then they must find and slay it.
+
+The most difficult part of eliminating a dragon is finding it. Sometimes
+the wizard magically knows where the dragon's lair it, but often the wizard
+must send another traveler along the same route and watch to see where he
+disappears. This sounds like a failsafe method for finding dragons (and a
+suicide mission for thr traveler) but the second traveler does not always
+disappear. Some dragons eat any traveler who comes too close; others are
+very picky.
+
+The wizards may call in CTK who designed the highway system and
+transformation laws to help devise a way to locate the dragon. CTK also
+helps provide the right spell or incantation to slay the dragon. (There is
+no general spell to slay dragons; each dragon must be eliminated with a
+different spell.)
+
+Because neither CTK nor wizards are perfect, spells to not always work
+correctly. At best, nothing happens when the wrong spell is uttered. At
+worst, the dragon becomes a much larger dragon or multiplies into several
+smaller ones. In either case, new spells must be found.
+
+If all existing dragons are quiet (i.e. have eaten sufficiently), wizards
+have time to do other things. They hide in castles and practice spells and
+incatations. They also devise shortcuts for travelers and new laws of
+transformation.
+
+Changes in the Kingdom
+======================
+
+As new transformation kingdoms are created and old ones are maintained,
+CTK, Inc. is constantly learning new things. It learns ways to avoid
+creating some of the dragons that they have previously created. It also
+discovers new and better laws of transformation. As a result, CTK will
+periodically create a new grand design which is far better than the old.
+The wizards determine when is a good time to implement this new design.
+This is when the tourist season is slow or when no important travelers
+(VIPs) are to arrive. The kingdom must be closed for the actual
+implementation and is leter reopened as a new and better place to go.
+
+A final question you might ask is what happens when the number of tourists
+becomes too great for the kingdom to handle in a reasonable period of time
+(i.e., the tourist lines at the ports are too long). The Kingdom of
+Transformation has three options: (1) shorten the paths that a tourist must
+travel, or (2) convince CTK to develop a faster breed of horses so that the
+travelers can finish sooner, or (3) annex more territories so that the
+kingdom can handle more travelers.
+
+Thus ends the story of the Kingdom of Transformation. I hope this has
+explained my job to you: I slay dragons for a living.
+
+#
+#should do an automatic undivert..
+#
diff --git a/usr.bin/m4/eval.c b/usr.bin/m4/eval.c
new file mode 100644
index 000000000000..82218eb9ba1c
--- /dev/null
+++ b/usr.bin/m4/eval.c
@@ -0,0 +1,1035 @@
+/* $OpenBSD: eval.c,v 1.78 2019/06/28 05:35:34 deraadt Exp $ */
+/* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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/cdefs.h>
+/*
+ * eval.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+#include "pathnames.h"
+
+static void dodefn(const char *);
+static void dopushdef(const char *, const char *);
+static void dodump(const char *[], int);
+static void dotrace(const char *[], int, int);
+static void doifelse(const char *[], int);
+static int doincl(const char *);
+static int dopaste(const char *);
+static void dochq(const char *[], int);
+static void dochc(const char *[], int);
+static void dom4wrap(const char *);
+static void dodiv(int);
+static void doundiv(const char *[], int);
+static void dosub(const char *[], int);
+static void map(char *, const char *, const char *, const char *);
+static const char *handledash(char *, char *, const char *);
+static void expand_builtin(const char *[], int, int);
+static void expand_macro(const char *[], int);
+static void dump_one_def(const char *, struct macro_definition *);
+
+unsigned long expansion_id;
+
+/*
+ * eval - eval all macros and builtins calls
+ * argc - number of elements in argv.
+ * argv - element vector :
+ * argv[0] = definition of a user
+ * macro or NULL if built-in.
+ * argv[1] = name of the macro or
+ * built-in.
+ * argv[2] = parameters to user-defined
+ * . macro or built-in.
+ * .
+ *
+ * A call in the form of macro-or-builtin() will result in:
+ * argv[0] = nullstr
+ * argv[1] = macro-or-builtin
+ * argv[2] = nullstr
+ *
+ * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
+ */
+void
+eval(const char *argv[], int argc, int td, int is_traced)
+{
+ size_t mark = SIZE_MAX;
+
+ expansion_id++;
+ if (td & RECDEF)
+ m4errx(1, "expanding recursive definition for %s.", argv[1]);
+ if (is_traced)
+ mark = trace(argv, argc, infile+ilevel);
+ if (td == MACRTYPE)
+ expand_macro(argv, argc);
+ else
+ expand_builtin(argv, argc, td);
+ if (mark != SIZE_MAX)
+ finish_trace(mark);
+}
+
+/*
+ * expand_builtin - evaluate built-in macros.
+ */
+void
+expand_builtin(const char *argv[], int argc, int td)
+{
+ int c, n;
+ const char *errstr;
+ int ac;
+ static int sysval = 0;
+
+#ifdef DEBUG
+ printf("argc = %d\n", argc);
+ for (n = 0; n < argc; n++)
+ printf("argv[%d] = %s\n", n, argv[n]);
+ fflush(stdout);
+#endif
+
+ /*
+ * if argc == 3 and argv[2] is null, then we
+ * have macro-or-builtin() type call. We adjust
+ * argc to avoid further checking..
+ */
+ /* we keep the initial value for those built-ins that differentiate
+ * between builtin() and builtin.
+ */
+ ac = argc;
+
+ if (argc == 3 && !*(argv[2]) && !mimic_gnu)
+ argc--;
+
+ switch (td & TYPEMASK) {
+
+ case DEFITYPE:
+ if (argc > 2)
+ dodefine(argv[2], (argc > 3) ? argv[3] : null);
+ break;
+
+ case PUSDTYPE:
+ if (argc > 2)
+ dopushdef(argv[2], (argc > 3) ? argv[3] : null);
+ break;
+
+ case DUMPTYPE:
+ dodump(argv, argc);
+ break;
+
+ case TRACEONTYPE:
+ dotrace(argv, argc, 1);
+ break;
+
+ case TRACEOFFTYPE:
+ dotrace(argv, argc, 0);
+ break;
+
+ case EXPRTYPE:
+ /*
+ * doexpr - evaluate arithmetic
+ * expression
+ */
+ {
+ int base = 10;
+ int maxdigits = 0;
+ const char *errstr;
+
+ if (argc > 3) {
+ base = strtonum(argv[3], 2, 36, &errstr);
+ if (errstr) {
+ m4errx(1, "expr: base is %s: %s.",
+ errstr, argv[3]);
+ }
+ }
+ if (argc > 4) {
+ maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
+ if (errstr) {
+ m4errx(1, "expr: maxdigits is %s: %s.",
+ errstr, argv[4]);
+ }
+ }
+ if (argc > 2)
+ pbnumbase(expr(argv[2]), base, maxdigits);
+ break;
+ }
+
+ case IFELTYPE:
+ doifelse(argv, argc);
+ break;
+
+ case IFDFTYPE:
+ /*
+ * doifdef - select one of two
+ * alternatives based on the existence of
+ * another definition
+ */
+ if (argc > 3) {
+ if (lookup_macro_definition(argv[2]) != NULL)
+ pbstr(argv[3]);
+ else if (argc > 4)
+ pbstr(argv[4]);
+ }
+ break;
+
+ case LENGTYPE:
+ /*
+ * dolen - find the length of the
+ * argument
+ */
+ pbnum((argc > 2) ? strlen(argv[2]) : 0);
+ break;
+
+ case INCRTYPE:
+ /*
+ * doincr - increment the value of the
+ * argument
+ */
+ if (argc > 2) {
+ n = strtonum(argv[2], INT_MIN, INT_MAX-1, &errstr);
+ if (errstr != NULL)
+ m4errx(1, "incr: argument is %s: %s.",
+ errstr, argv[2]);
+ pbnum(n + 1);
+ }
+ break;
+
+ case DECRTYPE:
+ /*
+ * dodecr - decrement the value of the
+ * argument
+ */
+ if (argc > 2) {
+ n = strtonum(argv[2], INT_MIN+1, INT_MAX, &errstr);
+ if (errstr)
+ m4errx(1, "decr: argument is %s: %s.",
+ errstr, argv[2]);
+ pbnum(n - 1);
+ }
+ break;
+
+ case SYSCTYPE:
+ /*
+ * dosys - execute system command
+ */
+ if (argc > 2) {
+ fflush(stdout);
+ sysval = system(argv[2]);
+ }
+ break;
+
+ case SYSVTYPE:
+ /*
+ * dosysval - return value of the last
+ * system call.
+ *
+ */
+ pbnum(sysval);
+ break;
+
+ case ESYSCMDTYPE:
+ if (argc > 2)
+ doesyscmd(argv[2]);
+ break;
+ case INCLTYPE:
+ if (argc > 2) {
+ if (!doincl(argv[2])) {
+ if (mimic_gnu) {
+ warn("%s at line %lu: include(%s)",
+ CURRENT_NAME, CURRENT_LINE, argv[2]);
+ exit_code = 1;
+ if (fatal_warns) {
+ killdiv();
+ exit(exit_code);
+ }
+ } else
+ err(1, "%s at line %lu: include(%s)",
+ CURRENT_NAME, CURRENT_LINE, argv[2]);
+ }
+ }
+ break;
+
+ case SINCTYPE:
+ if (argc > 2)
+ (void) doincl(argv[2]);
+ break;
+#ifdef EXTENDED
+ case PASTTYPE:
+ if (argc > 2)
+ if (!dopaste(argv[2]))
+ err(1, "%s at line %lu: paste(%s)",
+ CURRENT_NAME, CURRENT_LINE, argv[2]);
+ break;
+
+ case SPASTYPE:
+ if (argc > 2)
+ (void) dopaste(argv[2]);
+ break;
+ case FORMATTYPE:
+ doformat(argv, argc);
+ break;
+#endif
+ case CHNQTYPE:
+ dochq(argv, ac);
+ break;
+
+ case CHNCTYPE:
+ dochc(argv, argc);
+ break;
+
+ case SUBSTYPE:
+ /*
+ * dosub - select substring
+ *
+ */
+ if (argc > 3)
+ dosub(argv, argc);
+ break;
+
+ case SHIFTYPE:
+ /*
+ * doshift - push back all arguments
+ * except the first one (i.e. skip
+ * argv[2])
+ */
+ if (argc > 3) {
+ for (n = argc - 1; n > 3; n--) {
+ pbstr(rquote);
+ pbstr(argv[n]);
+ pbstr(lquote);
+ pushback(COMMA);
+ }
+ pbstr(rquote);
+ pbstr(argv[3]);
+ pbstr(lquote);
+ }
+ break;
+
+ case DIVRTYPE:
+ if (argc > 2) {
+ n = strtonum(argv[2], INT_MIN, INT_MAX, &errstr);
+ if (errstr)
+ m4errx(1, "divert: argument is %s: %s.",
+ errstr, argv[2]);
+ if (n != 0) {
+ dodiv(n);
+ break;
+ }
+ }
+ active = stdout;
+ oindex = 0;
+ break;
+
+ case UNDVTYPE:
+ doundiv(argv, argc);
+ break;
+
+ case DIVNTYPE:
+ /*
+ * dodivnum - return the number of
+ * current output diversion
+ */
+ pbnum(oindex);
+ break;
+
+ case UNDFTYPE:
+ /*
+ * doundefine - undefine a previously
+ * defined macro(s) or m4 keyword(s).
+ */
+ if (argc > 2)
+ for (n = 2; n < argc; n++)
+ macro_undefine(argv[n]);
+ break;
+
+ case POPDTYPE:
+ /*
+ * dopopdef - remove the topmost
+ * definitions of macro(s) or m4
+ * keyword(s).
+ */
+ if (argc > 2)
+ for (n = 2; n < argc; n++)
+ macro_popdef(argv[n]);
+ break;
+
+ case MKTMTYPE:
+ /*
+ * dotemp - create a temporary file
+ */
+ if (argc > 2) {
+ int fd;
+ char *temp;
+
+ temp = xstrdup(argv[2]);
+
+ fd = mkstemp(temp);
+ if (fd == -1)
+ err(1,
+ "%s at line %lu: couldn't make temp file %s",
+ CURRENT_NAME, CURRENT_LINE, argv[2]);
+ close(fd);
+ pbstr(temp);
+ free(temp);
+ }
+ break;
+
+ case TRNLTYPE:
+ /*
+ * dotranslit - replace all characters in
+ * the source string that appears in the
+ * "from" string with the corresponding
+ * characters in the "to" string.
+ */
+ if (argc > 3) {
+ char *temp;
+
+ temp = xalloc(strlen(argv[2])+1, NULL);
+ if (argc > 4)
+ map(temp, argv[2], argv[3], argv[4]);
+ else
+ map(temp, argv[2], argv[3], null);
+ pbstr(temp);
+ free(temp);
+ } else if (argc > 2)
+ pbstr(argv[2]);
+ break;
+
+ case INDXTYPE:
+ /*
+ * doindex - find the index of the second
+ * argument string in the first argument
+ * string. -1 if not present.
+ */
+ pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
+ break;
+
+ case ERRPTYPE:
+ /*
+ * doerrp - print the arguments to stderr
+ * file
+ */
+ if (argc > 2) {
+ for (n = 2; n < argc; n++)
+ fprintf(stderr, "%s ", argv[n]);
+ fprintf(stderr, "\n");
+ }
+ break;
+
+ case DNLNTYPE:
+ /*
+ * dodnl - eat-up-to and including
+ * newline
+ */
+ while ((c = gpbc()) != '\n' && c != EOF)
+ ;
+ break;
+
+ case M4WRTYPE:
+ /*
+ * dom4wrap - set up for
+ * wrap-up/wind-down activity
+ */
+ if (argc > 2)
+ dom4wrap(argv[2]);
+ break;
+
+ case EXITTYPE:
+ /*
+ * doexit - immediate exit from m4.
+ */
+ killdiv();
+ exit((argc > 2) ? atoi(argv[2]) : 0);
+ break;
+
+ case DEFNTYPE:
+ if (argc > 2)
+ for (n = 2; n < argc; n++)
+ dodefn(argv[n]);
+ break;
+
+ case INDIRTYPE: /* Indirect call */
+ if (argc > 2)
+ doindir(argv, argc);
+ break;
+
+ case BUILTINTYPE: /* Builtins only */
+ if (argc > 2)
+ dobuiltin(argv, argc);
+ break;
+
+ case PATSTYPE:
+ if (argc > 2)
+ dopatsubst(argv, argc);
+ break;
+ case REGEXPTYPE:
+ if (argc > 2)
+ doregexp(argv, argc);
+ break;
+ case LINETYPE:
+ doprintlineno(infile+ilevel);
+ break;
+ case FILENAMETYPE:
+ doprintfilename(infile+ilevel);
+ break;
+ case SELFTYPE:
+ pbstr(rquote);
+ pbstr(argv[1]);
+ pbstr(lquote);
+ break;
+ default:
+ m4errx(1, "eval: major botch.");
+ break;
+ }
+}
+
+/*
+ * expand_macro - user-defined macro expansion
+ */
+void
+expand_macro(const char *argv[], int argc)
+{
+ const char *t;
+ const char *p;
+ int n;
+ int argno;
+
+ t = argv[0]; /* defn string as a whole */
+ p = t;
+ while (*p)
+ p++;
+ p--; /* last character of defn */
+ while (p > t) {
+ if (*(p - 1) != ARGFLAG)
+ PUSHBACK(*p);
+ else {
+ switch (*p) {
+
+ case '#':
+ pbnum(argc - 2);
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if ((argno = *p - '0') < argc - 1)
+ pbstr(argv[argno + 1]);
+ break;
+ case '*':
+ if (argc > 2) {
+ for (n = argc - 1; n > 2; n--) {
+ pbstr(argv[n]);
+ pushback(COMMA);
+ }
+ pbstr(argv[2]);
+ }
+ break;
+ case '@':
+ if (argc > 2) {
+ for (n = argc - 1; n > 2; n--) {
+ pbstr(rquote);
+ pbstr(argv[n]);
+ pbstr(lquote);
+ pushback(COMMA);
+ }
+ pbstr(rquote);
+ pbstr(argv[2]);
+ pbstr(lquote);
+ }
+ break;
+ default:
+ PUSHBACK(*p);
+ PUSHBACK('$');
+ break;
+ }
+ p--;
+ }
+ p--;
+ }
+ if (p == t) /* do last character */
+ PUSHBACK(*p);
+}
+
+
+/*
+ * dodefine - install definition in the table
+ */
+void
+dodefine(const char *name, const char *defn)
+{
+ if (!*name && !mimic_gnu)
+ m4errx(1, "null definition.");
+ else
+ macro_define(name, defn);
+}
+
+/*
+ * dodefn - push back a quoted definition of
+ * the given name.
+ */
+static void
+dodefn(const char *name)
+{
+ struct macro_definition *p;
+
+ if ((p = lookup_macro_definition(name)) != NULL) {
+ if ((p->type & TYPEMASK) == MACRTYPE) {
+ pbstr(rquote);
+ pbstr(p->defn);
+ pbstr(lquote);
+ } else {
+ pbstr(p->defn);
+ pbstr(BUILTIN_MARKER);
+ }
+ }
+}
+
+/*
+ * dopushdef - install a definition in the hash table
+ * without removing a previous definition. Since
+ * each new entry is entered in *front* of the
+ * hash bucket, it hides a previous definition from
+ * lookup.
+ */
+static void
+dopushdef(const char *name, const char *defn)
+{
+ if (!*name && !mimic_gnu)
+ m4errx(1, "null definition.");
+ else
+ macro_pushdef(name, defn);
+}
+
+/*
+ * dump_one_def - dump the specified definition.
+ */
+static void
+dump_one_def(const char *name, struct macro_definition *p)
+{
+ if (!traceout)
+ traceout = stderr;
+ if (mimic_gnu) {
+ if ((p->type & TYPEMASK) == MACRTYPE)
+ fprintf(traceout, "%s:\t%s\n", name, p->defn);
+ else {
+ fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
+ }
+ } else
+ fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
+}
+
+/*
+ * dodumpdef - dump the specified definitions in the hash
+ * table to stderr. If nothing is specified, the entire
+ * hash table is dumped.
+ */
+static void
+dodump(const char *argv[], int argc)
+{
+ int n;
+ struct macro_definition *p;
+
+ if (argc > 2) {
+ for (n = 2; n < argc; n++)
+ if ((p = lookup_macro_definition(argv[n])) != NULL)
+ dump_one_def(argv[n], p);
+ } else
+ macro_for_all(dump_one_def);
+}
+
+/*
+ * dotrace - mark some macros as traced/untraced depending upon on.
+ */
+static void
+dotrace(const char *argv[], int argc, int on)
+{
+ int n;
+
+ if (argc > 2) {
+ for (n = 2; n < argc; n++)
+ mark_traced(argv[n], on);
+ } else
+ mark_traced(NULL, on);
+}
+
+/*
+ * doifelse - select one of two alternatives - loop.
+ */
+static void
+doifelse(const char *argv[], int argc)
+{
+ while (argc > 4) {
+ if (STREQ(argv[2], argv[3])) {
+ pbstr(argv[4]);
+ break;
+ } else if (argc == 6) {
+ pbstr(argv[5]);
+ break;
+ } else {
+ argv += 3;
+ argc -= 3;
+ }
+ }
+}
+
+/*
+ * doinclude - include a given file.
+ */
+static int
+doincl(const char *ifile)
+{
+ if (ilevel + 1 == MAXINP)
+ m4errx(1, "too many include files.");
+ if (fopen_trypath(infile+ilevel+1, ifile) != NULL) {
+ ilevel++;
+ bbase[ilevel] = bufbase = bp;
+ return (1);
+ } else
+ return (0);
+}
+
+#ifdef EXTENDED
+/*
+ * dopaste - include a given file without any
+ * macro processing.
+ */
+static int
+dopaste(const char *pfile)
+{
+ FILE *pf;
+ int c;
+
+ if ((pf = fopen(pfile, "r")) != NULL) {
+ if (synch_lines)
+ fprintf(active, "#line 1 \"%s\"\n", pfile);
+ while ((c = getc(pf)) != EOF)
+ putc(c, active);
+ (void) fclose(pf);
+ emit_synchline();
+ return (1);
+ } else
+ return (0);
+}
+#endif
+
+/*
+ * dochq - change quote characters
+ */
+static void
+dochq(const char *argv[], int ac)
+{
+ if (ac == 2) {
+ lquote[0] = LQUOTE; lquote[1] = EOS;
+ rquote[0] = RQUOTE; rquote[1] = EOS;
+ } else {
+ strlcpy(lquote, argv[2], sizeof(lquote));
+ if (ac > 3) {
+ strlcpy(rquote, argv[3], sizeof(rquote));
+ } else {
+ rquote[0] = ECOMMT; rquote[1] = EOS;
+ }
+ }
+}
+
+/*
+ * dochc - change comment characters
+ */
+static void
+dochc(const char *argv[], int argc)
+{
+/* XXX Note that there is no difference between no argument and a single
+ * empty argument.
+ */
+ if (argc == 2) {
+ scommt[0] = EOS;
+ ecommt[0] = EOS;
+ } else {
+ strlcpy(scommt, argv[2], sizeof(scommt));
+ if (argc == 3) {
+ ecommt[0] = ECOMMT; ecommt[1] = EOS;
+ } else {
+ strlcpy(ecommt, argv[3], sizeof(ecommt));
+ }
+ }
+}
+
+/*
+ * dom4wrap - expand text at EOF
+ */
+static void
+dom4wrap(const char *text)
+{
+ if (wrapindex >= maxwraps) {
+ if (maxwraps == 0)
+ maxwraps = 16;
+ else
+ maxwraps *= 2;
+ m4wraps = xreallocarray(m4wraps, maxwraps, sizeof(*m4wraps),
+ "too many m4wraps");
+ }
+ m4wraps[wrapindex++] = xstrdup(text);
+}
+
+/*
+ * dodivert - divert the output to a temporary file
+ */
+static void
+dodiv(int n)
+{
+ int fd;
+
+ oindex = n;
+ if (n >= maxout) {
+ if (mimic_gnu)
+ resizedivs(n + 10);
+ else
+ n = 0; /* bitbucket */
+ }
+
+ if (n < 0)
+ n = 0; /* bitbucket */
+ if (outfile[n] == NULL) {
+ char fname[] = _PATH_DIVNAME;
+
+ if ((fd = mkstemp(fname)) == -1 ||
+ unlink(fname) == -1 ||
+ (outfile[n] = fdopen(fd, "w+")) == NULL)
+ err(1, "%s: cannot divert", fname);
+ }
+ active = outfile[n];
+}
+
+/*
+ * doundivert - undivert a specified output, or all
+ * other outputs, in numerical order.
+ */
+static void
+doundiv(const char *argv[], int argc)
+{
+ int ind;
+ int n;
+
+ if (argc > 2) {
+ for (ind = 2; ind < argc; ind++) {
+ const char *errstr;
+ n = strtonum(argv[ind], 1, INT_MAX, &errstr);
+ if (errstr) {
+ if (errno == EINVAL && mimic_gnu)
+ getdivfile(argv[ind]);
+ } else {
+ if (n < maxout && outfile[n] != NULL)
+ getdiv(n);
+ }
+ }
+ }
+ else
+ for (n = 1; n < maxout; n++)
+ if (outfile[n] != NULL)
+ getdiv(n);
+}
+
+/*
+ * dosub - select substring
+ */
+static void
+dosub(const char *argv[], int argc)
+{
+ const char *ap, *fc, *k;
+ int nc;
+
+ ap = argv[2]; /* target string */
+#ifdef EXPR
+ fc = ap + expr(argv[3]); /* first char */
+#else
+ fc = ap + atoi(argv[3]); /* first char */
+#endif
+ nc = strlen(fc);
+ if (argc >= 5)
+#ifdef EXPR
+ nc = min(nc, expr(argv[4]));
+#else
+ nc = min(nc, atoi(argv[4]));
+#endif
+ if (fc >= ap && fc < ap + strlen(ap))
+ for (k = fc + nc - 1; k >= fc; k--)
+ pushback(*k);
+}
+
+/*
+ * map:
+ * map every character of s1 that is specified in from
+ * into s3 and replace in s. (source s1 remains untouched)
+ *
+ * This is derived from the a standard implementation of map(s,from,to)
+ * function of ICON language. Within mapvec, we replace every character
+ * of "from" with the corresponding character in "to".
+ * If "to" is shorter than "from", than the corresponding entries are null,
+ * which means that those characters disappear altogether.
+ */
+static void
+map(char *dest, const char *src, const char *from, const char *to)
+{
+ const char *tmp;
+ unsigned char sch, dch;
+ static char frombis[257];
+ static char tobis[257];
+ int i;
+ char seen[256];
+ static unsigned char mapvec[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+ 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
+ 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+ };
+
+ if (*src) {
+ if (mimic_gnu) {
+ /*
+ * expand character ranges on the fly
+ */
+ from = handledash(frombis, frombis + 256, from);
+ to = handledash(tobis, tobis + 256, to);
+ }
+ tmp = from;
+ /*
+ * create a mapping between "from" and
+ * "to"
+ */
+ for (i = 0; i < 256; i++)
+ seen[i] = 0;
+ while (*from) {
+ if (!seen[(unsigned char)(*from)]) {
+ mapvec[(unsigned char)(*from)] = (unsigned char)(*to);
+ seen[(unsigned char)(*from)] = 1;
+ }
+ from++;
+ if (*to)
+ to++;
+ }
+
+ while (*src) {
+ sch = (unsigned char)(*src++);
+ dch = mapvec[sch];
+ if ((*dest = (char)dch))
+ dest++;
+ }
+ /*
+ * restore all the changed characters
+ */
+ while (*tmp) {
+ mapvec[(unsigned char)(*tmp)] = (unsigned char)(*tmp);
+ tmp++;
+ }
+ }
+ *dest = '\0';
+}
+
+
+/*
+ * handledash:
+ * use buffer to copy the src string, expanding character ranges
+ * on the way.
+ */
+static const char *
+handledash(char *buffer, char *end, const char *src)
+{
+ char *p;
+
+ p = buffer;
+ while(*src) {
+ if (src[1] == '-' && src[2]) {
+ unsigned char i;
+ if ((unsigned char)src[0] <= (unsigned char)src[2]) {
+ for (i = (unsigned char)src[0];
+ i <= (unsigned char)src[2]; i++) {
+ *p++ = i;
+ if (p == end) {
+ *p = '\0';
+ return buffer;
+ }
+ }
+ } else {
+ for (i = (unsigned char)src[0];
+ i >= (unsigned char)src[2]; i--) {
+ *p++ = i;
+ if (p == end) {
+ *p = '\0';
+ return buffer;
+ }
+ }
+ }
+ src += 3;
+ } else
+ *p++ = *src++;
+ if (p == end)
+ break;
+ }
+ *p = '\0';
+ return buffer;
+}
diff --git a/usr.bin/m4/expr.c b/usr.bin/m4/expr.c
new file mode 100644
index 000000000000..7910403d74f0
--- /dev/null
+++ b/usr.bin/m4/expr.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: expr.c,v 1.18 2010/09/07 19:58:09 marco Exp $ */
+/*
+ * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/cdefs.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include "mdef.h"
+#include "extern.h"
+
+int32_t end_result;
+static const char *copy_toeval;
+int yyerror(const char *msg);
+
+extern void yy_scan_string(const char *);
+extern int yyparse(void);
+
+int
+yyerror(const char *msg)
+{
+ fprintf(stderr, "m4: %s in expr %s\n", msg, copy_toeval);
+ return(0);
+}
+
+int
+expr(const char *toeval)
+{
+ copy_toeval = toeval;
+ yy_scan_string(toeval);
+ yyparse();
+ return end_result;
+}
diff --git a/usr.bin/m4/extern.h b/usr.bin/m4/extern.h
new file mode 100644
index 000000000000..94eb66314bf4
--- /dev/null
+++ b/usr.bin/m4/extern.h
@@ -0,0 +1,181 @@
+/* $OpenBSD: extern.h,v 1.55 2017/06/15 13:48:42 bcallah Exp $ */
+/* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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.c */
+extern void eval(const char *[], int, int, int);
+extern void dodefine(const char *, const char *);
+extern unsigned long expansion_id;
+
+/* expr.c */
+extern int expr(const char *);
+
+/* gnum4.c */
+extern void addtoincludepath(const char *);
+extern struct input_file *fopen_trypath(struct input_file *, const char *);
+extern void doindir(const char *[], int);
+extern void dobuiltin(const char *[], int);
+extern void dopatsubst(const char *[], int);
+extern void doregexp(const char *[], int);
+
+extern void doprintlineno(struct input_file *);
+extern void doprintfilename(struct input_file *);
+
+extern void doesyscmd(const char *);
+extern void getdivfile(const char *);
+extern void doformat(const char *[], int);
+
+extern void m4_warnx(const char *, ...);
+
+/* look.c */
+
+#define FLAG_UNTRACED 0
+#define FLAG_TRACED 1
+#define FLAG_NO_TRACE 2
+
+extern void init_macros(void);
+extern ndptr lookup(const char *);
+extern void mark_traced(const char *, int);
+extern struct ohash macros;
+
+extern struct macro_definition *lookup_macro_definition(const char *);
+extern void macro_define(const char *, const char *);
+extern void macro_pushdef(const char *, const char *);
+extern void macro_popdef(const char *);
+extern void macro_undefine(const char *);
+extern void setup_builtin(const char *, unsigned int);
+extern void macro_for_all(void (*)(const char *, struct macro_definition *));
+#define macro_getdef(p) ((p)->d)
+#define macro_name(p) ((p)->name)
+#define macro_builtin_type(p) ((p)->builtin_type)
+#define is_traced(p) ((p)->trace_flags == FLAG_NO_TRACE ? (trace_flags & TRACE_ALL) : (p)->trace_flags)
+
+extern ndptr macro_getbuiltin(const char *);
+
+/* main.c */
+extern void outputstr(const char *);
+extern void do_emit_synchline(void);
+extern int exit_code;
+#define emit_synchline() do { if (synch_lines) do_emit_synchline(); } while(0)
+
+/* misc.c */
+extern void chrsave(int);
+extern char *compute_prevep(void);
+extern void getdiv(int);
+extern ptrdiff_t indx(const char *, const char *);
+extern void initspaces(void);
+extern void killdiv(void);
+extern void onintr(int);
+extern void pbnum(int);
+extern void pbnumbase(int, int, int);
+extern void pbunsigned(unsigned long);
+extern void pbstr(const char *);
+extern void pushback(int);
+extern void *xalloc(size_t, const char *, ...) __printf0like(2, 3);
+extern void *xcalloc(size_t, size_t, const char *, ...) __printf0like(3, 4);
+extern void *xrealloc(void *, size_t, const char *, ...) __printf0like(3, 4);
+extern void *xreallocarray(void *, size_t, size_t, const char *, ...) __printf0like(4, 5);
+extern char *xstrdup(const char *);
+extern void usage(void);
+extern void resizedivs(int);
+extern size_t buffer_mark(void);
+extern void dump_buffer(FILE *, size_t);
+extern void m4errx(int, const char *, ...) __dead2 __printf0like(2, 3);
+
+extern int obtain_char(struct input_file *);
+extern void set_input(struct input_file *, FILE *, const char *);
+extern void release_input(struct input_file *);
+
+/* speeded-up versions of chrsave/pushback */
+#define PUSHBACK(c) \
+ do { \
+ if (bp >= endpbb) \
+ enlarge_bufspace(); \
+ *bp++ = (c); \
+ } while(0)
+
+#define CHRSAVE(c) \
+ do { \
+ if (ep >= endest) \
+ enlarge_strspace(); \
+ *ep++ = (c); \
+ } while(0)
+
+/* and corresponding exposure for local symbols */
+extern void enlarge_bufspace(void);
+extern void enlarge_strspace(void);
+extern unsigned char *endpbb;
+extern char *endest;
+
+/* trace.c */
+extern unsigned int trace_flags;
+#define TRACE_ALL 512
+extern void trace_file(const char *);
+extern size_t trace(const char **, int, struct input_file *);
+extern void finish_trace(size_t);
+extern void set_trace_flags(const char *);
+extern FILE *traceout;
+
+extern stae *mstack; /* stack of m4 machine */
+extern char *sstack; /* shadow stack, for string space extension */
+extern FILE *active; /* active output file pointer */
+extern struct input_file infile[];/* input file stack (0=stdin) */
+extern FILE **outfile; /* diversion array(0=bitbucket) */
+extern int maxout; /* maximum number of diversions */
+extern int fp; /* m4 call frame pointer */
+extern int ilevel; /* input file stack pointer */
+extern int oindex; /* diversion index. */
+extern int sp; /* current m4 stack pointer */
+extern unsigned char *bp; /* first available character */
+extern unsigned char *buf; /* push-back buffer */
+extern unsigned char *bufbase; /* buffer base for this ilevel */
+extern unsigned char *bbase[]; /* buffer base per ilevel */
+extern char ecommt[MAXCCHARS+1];/* end character for comment */
+extern char *ep; /* first free char in strspace */
+extern char lquote[MAXCCHARS+1];/* left quote character (`) */
+extern char **m4wraps; /* m4wrap string default. */
+extern int maxwraps; /* size of m4wraps array */
+extern int wrapindex; /* current index in m4wraps */
+
+extern const char *null; /* as it says.. just a null. */
+extern char rquote[MAXCCHARS+1];/* right quote character (') */
+extern char scommt[MAXCCHARS+1];/* start character for comment */
+extern int synch_lines; /* line synchronisation directives */
+
+extern int mimic_gnu; /* behaves like gnu-m4 */
+extern int prefix_builtins; /* prefix builtin macros with m4_ */
+extern int error_warns; /* make warnings cause exit_code = 1 */
+extern int fatal_warns; /* make warnings fatal */
diff --git a/usr.bin/m4/gnum4.c b/usr.bin/m4/gnum4.c
new file mode 100644
index 000000000000..ecd89b5c8b6a
--- /dev/null
+++ b/usr.bin/m4/gnum4.c
@@ -0,0 +1,694 @@
+/* $OpenBSD: gnum4.c,v 1.52 2017/08/21 21:41:13 deraadt Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 Marc Espie
+ *
+ * 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 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/cdefs.h>
+/*
+ * functions needed to support gnu-m4 extensions, including a fake freezing
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <err.h>
+#include <paths.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+
+
+int mimic_gnu = 0;
+
+/*
+ * Support for include path search
+ * First search in the current directory.
+ * If not found, and the path is not absolute, include path kicks in.
+ * First, -I options, in the order found on the command line.
+ * Then M4PATH env variable
+ */
+
+static struct path_entry {
+ char *name;
+ struct path_entry *next;
+} *first, *last;
+
+static struct path_entry *new_path_entry(const char *);
+static void ensure_m4path(void);
+static struct input_file *dopath(struct input_file *, const char *);
+
+static struct path_entry *
+new_path_entry(const char *dirname)
+{
+ struct path_entry *n;
+
+ n = malloc(sizeof(struct path_entry));
+ if (!n)
+ errx(1, "out of memory");
+ n->name = xstrdup(dirname);
+ n->next = 0;
+ return n;
+}
+
+void
+addtoincludepath(const char *dirname)
+{
+ struct path_entry *n;
+
+ n = new_path_entry(dirname);
+
+ if (last) {
+ last->next = n;
+ last = n;
+ }
+ else
+ last = first = n;
+}
+
+static void
+ensure_m4path(void)
+{
+ static int envpathdone = 0;
+ char *envpath;
+ char *sweep;
+ char *path;
+
+ if (envpathdone)
+ return;
+ envpathdone = TRUE;
+ envpath = getenv("M4PATH");
+ if (!envpath)
+ return;
+ /* for portability: getenv result is read-only */
+ envpath = xstrdup(envpath);
+ for (sweep = envpath;
+ (path = strsep(&sweep, ":")) != NULL;)
+ addtoincludepath(path);
+ free(envpath);
+}
+
+static
+struct input_file *
+dopath(struct input_file *i, const char *filename)
+{
+ char path[PATH_MAX];
+ struct path_entry *pe;
+ FILE *f;
+
+ for (pe = first; pe; pe = pe->next) {
+ snprintf(path, sizeof(path), "%s/%s", pe->name, filename);
+ if ((f = fopen(path, "r")) != NULL) {
+ set_input(i, f, path);
+ return i;
+ }
+ }
+ return NULL;
+}
+
+struct input_file *
+fopen_trypath(struct input_file *i, const char *filename)
+{
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (f != NULL) {
+ set_input(i, f, filename);
+ return i;
+ }
+ if (filename[0] == '/')
+ return NULL;
+
+ ensure_m4path();
+
+ return dopath(i, filename);
+}
+
+void
+doindir(const char *argv[], int argc)
+{
+ ndptr n;
+ struct macro_definition *p = NULL;
+
+ n = lookup(argv[2]);
+ if (n == NULL || (p = macro_getdef(n)) == NULL)
+ m4errx(1, "indir: undefined macro %s.", argv[2]);
+ argv[1] = p->defn;
+
+ eval(argv+1, argc-1, p->type, is_traced(n));
+}
+
+void
+dobuiltin(const char *argv[], int argc)
+{
+ ndptr p;
+
+ argv[1] = NULL;
+ p = macro_getbuiltin(argv[2]);
+ if (p != NULL)
+ eval(argv+1, argc-1, macro_builtin_type(p), is_traced(p));
+ else
+ m4errx(1, "unknown builtin %s.", argv[2]);
+}
+
+
+/* We need some temporary buffer space, as pb pushes BACK and substitution
+ * proceeds forward... */
+static char *buffer;
+static size_t bufsize = 0;
+static size_t current = 0;
+
+static void addchars(const char *, size_t);
+static void addchar(int);
+static char *twiddle(const char *);
+static char *getstring(void);
+static void exit_regerror(int, regex_t *, const char *);
+static void do_subst(const char *, regex_t *, const char *, const char *,
+ regmatch_t *);
+static void do_regexpindex(const char *, regex_t *, const char *, regmatch_t *);
+static void do_regexp(const char *, regex_t *, const char *, const char *,
+ regmatch_t *);
+static void add_sub(int, const char *, regex_t *, regmatch_t *);
+static void add_replace(const char *, regex_t *, const char *, regmatch_t *);
+#define addconstantstring(s) addchars((s), sizeof(s)-1)
+
+static void
+addchars(const char *c, size_t n)
+{
+ if (n == 0)
+ return;
+ while (current + n > bufsize) {
+ if (bufsize == 0)
+ bufsize = 1024;
+ else if (bufsize <= SIZE_MAX/2) {
+ bufsize *= 2;
+ } else {
+ errx(1, "size overflow");
+ }
+ buffer = xrealloc(buffer, bufsize, NULL);
+ }
+ memcpy(buffer+current, c, n);
+ current += n;
+}
+
+static void
+addchar(int c)
+{
+ if (current +1 > bufsize) {
+ if (bufsize == 0)
+ bufsize = 1024;
+ else
+ bufsize *= 2;
+ buffer = xrealloc(buffer, bufsize, NULL);
+ }
+ buffer[current++] = c;
+}
+
+static char *
+getstring(void)
+{
+ addchar('\0');
+ current = 0;
+ return buffer;
+}
+
+
+static void
+exit_regerror(int er, regex_t *re, const char *source)
+{
+ size_t errlen;
+ char *errbuf;
+
+ errlen = regerror(er, re, NULL, 0);
+ errbuf = xalloc(errlen,
+ "malloc in regerror: %lu", (unsigned long)errlen);
+ regerror(er, re, errbuf, errlen);
+ m4errx(1, "regular expression error in %s: %s.", source, errbuf);
+}
+
+/* warnx() plus check to see if we need to change exit code or exit .
+ * -E flag functionality.
+ */
+void
+m4_warnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warnx(fmt, ap);
+ va_end(ap);
+
+ if (fatal_warns)
+ exit(1);
+ if (error_warns)
+ exit_code = 1;
+}
+
+static void
+add_sub(int n, const char *string, regex_t *re, regmatch_t *pm)
+{
+ if (n > (int)re->re_nsub)
+ m4_warnx("No subexpression %d", n);
+ /* Subexpressions that did not match are
+ * not an error. */
+ else if (pm[n].rm_so != -1 &&
+ pm[n].rm_eo != -1) {
+ addchars(string + pm[n].rm_so,
+ pm[n].rm_eo - pm[n].rm_so);
+ }
+}
+
+/* Add replacement string to the output buffer, recognizing special
+ * constructs and replacing them with substrings of the original string.
+ */
+static void
+add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm)
+{
+ const char *p;
+
+ for (p = replace; *p != '\0'; p++) {
+ if (*p == '&' && !mimic_gnu) {
+ add_sub(0, string, re, pm);
+ continue;
+ }
+ if (*p == '\\') {
+ if (p[1] == '\\') {
+ addchar(p[1]);
+ p++;
+ continue;
+ }
+ if (p[1] == '&') {
+ if (mimic_gnu)
+ add_sub(0, string, re, pm);
+ else
+ addchar(p[1]);
+ p++;
+ continue;
+ }
+ if (isdigit((unsigned char)p[1])) {
+ add_sub(*(++p) - '0', string, re, pm);
+ continue;
+ }
+ }
+ addchar(*p);
+ }
+}
+
+static void
+do_subst(const char *string, regex_t *re, const char *source,
+ const char *replace, regmatch_t *pm)
+{
+ int error;
+ int flags = 0;
+ const char *last_match = NULL;
+
+ while ((error = regexec(re, string, re->re_nsub+1, pm, flags)) == 0) {
+ if (pm[0].rm_eo != 0) {
+ if (string[pm[0].rm_eo-1] == '\n')
+ flags = 0;
+ else
+ flags = REG_NOTBOL;
+ }
+
+ /* NULL length matches are special... We use the `vi-mode'
+ * rule: don't allow a NULL-match at the last match
+ * position.
+ */
+ if (pm[0].rm_so == pm[0].rm_eo &&
+ string + pm[0].rm_so == last_match) {
+ if (*string == '\0')
+ return;
+ addchar(*string);
+ if (*string++ == '\n')
+ flags = 0;
+ else
+ flags = REG_NOTBOL;
+ continue;
+ }
+ last_match = string + pm[0].rm_so;
+ addchars(string, pm[0].rm_so);
+ add_replace(string, re, replace, pm);
+ string += pm[0].rm_eo;
+ }
+ if (error != REG_NOMATCH)
+ exit_regerror(error, re, source);
+ pbstr(string);
+}
+
+static void
+do_regexp(const char *string, regex_t *re, const char *source,
+ const char *replace, regmatch_t *pm)
+{
+ int error;
+
+ switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) {
+ case 0:
+ add_replace(string, re, replace, pm);
+ pbstr(getstring());
+ break;
+ case REG_NOMATCH:
+ break;
+ default:
+ exit_regerror(error, re, source);
+ }
+}
+
+static void
+do_regexpindex(const char *string, regex_t *re, const char *source,
+ regmatch_t *pm)
+{
+ int error;
+
+ switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) {
+ case 0:
+ pbunsigned(pm[0].rm_so);
+ break;
+ case REG_NOMATCH:
+ pbnum(-1);
+ break;
+ default:
+ exit_regerror(error, re, source);
+ }
+}
+
+/* In Gnu m4 mode, parentheses for backmatch don't work like POSIX 1003.2
+ * says. So we twiddle with the regexp before passing it to regcomp.
+ */
+static char *
+twiddle(const char *p)
+{
+ /* + at start of regexp is a normal character for Gnu m4 */
+ if (*p == '^') {
+ addchar(*p);
+ p++;
+ }
+ if (*p == '+') {
+ addchar('\\');
+ }
+ /* This could use strcspn for speed... */
+ while (*p != '\0') {
+ if (*p == '\\') {
+ switch(p[1]) {
+ case '(':
+ case ')':
+ case '|':
+ addchar(p[1]);
+ break;
+ case 'w':
+ addconstantstring("[_a-zA-Z0-9]");
+ break;
+ case 'W':
+ addconstantstring("[^_a-zA-Z0-9]");
+ break;
+ case '<':
+ addconstantstring("[[:<:]]");
+ break;
+ case '>':
+ addconstantstring("[[:>:]]");
+ break;
+ default:
+ addchars(p, 2);
+ break;
+ }
+ p+=2;
+ continue;
+ }
+ if (*p == '(' || *p == ')' || *p == '|')
+ addchar('\\');
+
+ addchar(*p);
+ p++;
+ }
+ return getstring();
+}
+
+/* patsubst(string, regexp, opt replacement) */
+/* argv[2]: string
+ * argv[3]: regexp
+ * argv[4]: opt rep
+ */
+void
+dopatsubst(const char *argv[], int argc)
+{
+ if (argc <= 3) {
+ m4_warnx("Too few arguments to patsubst");
+ return;
+ }
+ /* special case: empty regexp */
+ if (argv[3][0] == '\0') {
+ const char *s;
+ size_t len;
+ if (argc > 4 && argv[4])
+ len = strlen(argv[4]);
+ else
+ len = 0;
+ for (s = argv[2]; *s != '\0'; s++) {
+ addchars(argv[4], len);
+ addchar(*s);
+ }
+ } else {
+ int error;
+ regex_t re;
+ regmatch_t *pmatch;
+ int mode = REG_EXTENDED;
+ const char *source;
+ size_t l = strlen(argv[3]);
+
+ if (!mimic_gnu ||
+ (argv[3][0] == '^') ||
+ (l > 0 && argv[3][l-1] == '$'))
+ mode |= REG_NEWLINE;
+
+ source = mimic_gnu ? twiddle(argv[3]) : argv[3];
+ error = regcomp(&re, source, mode);
+ if (error != 0)
+ exit_regerror(error, &re, source);
+
+ pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t),
+ NULL);
+ do_subst(argv[2], &re, source,
+ argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch);
+ free(pmatch);
+ regfree(&re);
+ }
+ pbstr(getstring());
+}
+
+void
+doregexp(const char *argv[], int argc)
+{
+ int error;
+ regex_t re;
+ regmatch_t *pmatch;
+ const char *source;
+
+ if (argc <= 3) {
+ m4_warnx("Too few arguments to regexp");
+ return;
+ }
+ /* special gnu case */
+ if (argv[3][0] == '\0' && mimic_gnu) {
+ if (argc == 4 || argv[4] == NULL)
+ return;
+ else
+ pbstr(argv[4]);
+ }
+ source = mimic_gnu ? twiddle(argv[3]) : argv[3];
+ error = regcomp(&re, source, REG_EXTENDED|REG_NEWLINE);
+ if (error != 0)
+ exit_regerror(error, &re, source);
+
+ pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), NULL);
+ if (argc == 4 || argv[4] == NULL)
+ do_regexpindex(argv[2], &re, source, pmatch);
+ else
+ do_regexp(argv[2], &re, source, argv[4], pmatch);
+ free(pmatch);
+ regfree(&re);
+}
+
+void
+doformat(const char *argv[], int argc)
+{
+ const char *format = argv[2];
+ int pos = 3;
+ int left_padded;
+ long width;
+ size_t l;
+ const char *thisarg = NULL;
+ char temp[2];
+ long extra;
+
+ while (*format != 0) {
+ if (*format != '%') {
+ addchar(*format++);
+ continue;
+ }
+
+ format++;
+ if (*format == '%') {
+ addchar(*format++);
+ continue;
+ }
+ if (*format == 0) {
+ addchar('%');
+ break;
+ }
+
+ if (*format == '*') {
+ format++;
+ if (pos >= argc)
+ m4errx(1,
+ "Format with too many format specifiers.");
+ width = strtol(argv[pos++], NULL, 10);
+ } else {
+ width = strtol(format, __DECONST(char **,&format), 10);
+ }
+ if (width < 0) {
+ left_padded = 1;
+ width = -width;
+ } else {
+ left_padded = 0;
+ }
+ if (*format == '.') {
+ format++;
+ if (*format == '*') {
+ format++;
+ if (pos >= argc)
+ m4errx(1,
+ "Format with too many format specifiers.");
+ extra = strtol(argv[pos++], NULL, 10);
+ } else {
+ extra = strtol(format, __DECONST(char **, &format), 10);
+ }
+ } else {
+ extra = LONG_MAX;
+ }
+ if (pos >= argc)
+ m4errx(1, "Format with too many format specifiers.");
+ switch(*format) {
+ case 's':
+ thisarg = argv[pos++];
+ break;
+ case 'c':
+ temp[0] = strtoul(argv[pos++], NULL, 10);
+ temp[1] = 0;
+ thisarg = temp;
+ break;
+ default:
+ m4errx(1, "Unsupported format specification: %s.",
+ argv[2]);
+ }
+ format++;
+ l = strlen(thisarg);
+ if ((long)l > extra)
+ l = extra;
+ if (!left_padded) {
+ while ((long)l < width--)
+ addchar(' ');
+ }
+ addchars(thisarg, l);
+ if (left_padded) {
+ while ((long)l < width--)
+ addchar(' ');
+ }
+ }
+ pbstr(getstring());
+}
+
+void
+doesyscmd(const char *cmd)
+{
+ int p[2];
+ pid_t cpid;
+ char *argv[4];
+ int cc;
+ int status;
+
+ /* Follow gnu m4 documentation: first flush buffers. */
+ fflush(NULL);
+
+ argv[0] = __DECONST(char *, "sh");
+ argv[1] = __DECONST(char *, "-c");
+ argv[2] = __DECONST(char *, cmd);
+ argv[3] = NULL;
+
+ /* Just set up standard output, share stderr and stdin with m4 */
+ if (pipe(p) == -1)
+ err(1, "bad pipe");
+ switch(cpid = fork()) {
+ case -1:
+ err(1, "bad fork");
+ /* NOTREACHED */
+ case 0:
+ (void) close(p[0]);
+ (void) dup2(p[1], 1);
+ (void) close(p[1]);
+ execv(_PATH_BSHELL, argv);
+ exit(1);
+ default:
+ /* Read result in two stages, since m4's buffer is
+ * pushback-only. */
+ (void) close(p[1]);
+ do {
+ char result[BUFSIZE];
+ cc = read(p[0], result, sizeof result);
+ if (cc > 0)
+ addchars(result, cc);
+ } while (cc > 0 || (cc == -1 && errno == EINTR));
+
+ (void) close(p[0]);
+ while (waitpid(cpid, &status, 0) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ pbstr(getstring());
+ }
+}
+
+void
+getdivfile(const char *name)
+{
+ FILE *f;
+ int c;
+
+ f = fopen(name, "r");
+ if (!f)
+ return;
+
+ while ((c = getc(f))!= EOF)
+ putc(c, active);
+ (void) fclose(f);
+}
diff --git a/usr.bin/m4/look.c b/usr.bin/m4/look.c
new file mode 100644
index 000000000000..d7ad94b18bd0
--- /dev/null
+++ b/usr.bin/m4/look.c
@@ -0,0 +1,339 @@
+/* $OpenBSD: look.c,v 1.24 2014/12/21 09:33:12 espie Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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/cdefs.h>
+/*
+ * look.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <ohash.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+
+static void *hash_calloc(size_t, size_t, void *);
+static void hash_free(void *, void *);
+static void *element_alloc(size_t, void *);
+static void setup_definition(struct macro_definition *, const char *,
+ const char *);
+static void free_definition(char *);
+static void keep(char *);
+static int string_in_use(const char *);
+
+static struct ohash_info macro_info = {
+ offsetof(struct ndblock, name),
+ NULL, hash_calloc, hash_free, element_alloc };
+
+struct ohash macros;
+
+/* Support routines for hash tables. */
+void *
+hash_calloc(size_t n, size_t s, void *u __unused)
+{
+ void *storage = xcalloc(n, s, "hash alloc");
+ return storage;
+}
+
+void
+hash_free(void *p, void *u __unused)
+{
+ free(p);
+}
+
+void *
+element_alloc(size_t s, void *u __unused)
+{
+ return xalloc(s, "element alloc");
+}
+
+void
+init_macros(void)
+{
+ ohash_init(&macros, 10, &macro_info);
+}
+
+/*
+ * find name in the hash table
+ */
+ndptr
+lookup(const char *name)
+{
+ return ohash_find(&macros, ohash_qlookup(&macros, name));
+}
+
+struct macro_definition *
+lookup_macro_definition(const char *name)
+{
+ ndptr p;
+
+ p = ohash_find(&macros, ohash_qlookup(&macros, name));
+ if (p)
+ return p->d;
+ else
+ return NULL;
+}
+
+static void
+setup_definition(struct macro_definition *d, const char *defn, const char *name)
+{
+ ndptr p;
+
+ if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 &&
+ (p = macro_getbuiltin(defn+sizeof(BUILTIN_MARKER)-1)) != NULL) {
+ d->type = macro_builtin_type(p);
+ d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
+ } else {
+ if (!*defn)
+ d->defn = __DECONST(char *, null);
+ else
+ d->defn = xstrdup(defn);
+ d->type = MACRTYPE;
+ }
+ if (STREQ(name, defn))
+ d->type |= RECDEF;
+}
+
+static ndptr
+create_entry(const char *name)
+{
+ const char *end = NULL;
+ unsigned int i;
+ ndptr n;
+
+ i = ohash_qlookupi(&macros, name, &end);
+ n = ohash_find(&macros, i);
+ if (n == NULL) {
+ n = ohash_create_entry(&macro_info, name, &end);
+ ohash_insert(&macros, i, n);
+ n->trace_flags = FLAG_NO_TRACE;
+ n->builtin_type = MACRTYPE;
+ n->d = NULL;
+ }
+ return n;
+}
+
+void
+macro_define(const char *name, const char *defn)
+{
+ ndptr n = create_entry(name);
+ if (n->d != NULL) {
+ if (n->d->defn != null)
+ free_definition(n->d->defn);
+ } else {
+ n->d = xalloc(sizeof(struct macro_definition), NULL);
+ n->d->next = NULL;
+ }
+ setup_definition(n->d, defn, name);
+}
+
+void
+macro_pushdef(const char *name, const char *defn)
+{
+ ndptr n;
+ struct macro_definition *d;
+
+ n = create_entry(name);
+ d = xalloc(sizeof(struct macro_definition), NULL);
+ d->next = n->d;
+ n->d = d;
+ setup_definition(n->d, defn, name);
+}
+
+void
+macro_undefine(const char *name)
+{
+ ndptr n = lookup(name);
+ if (n != NULL) {
+ struct macro_definition *r, *r2;
+
+ for (r = n->d; r != NULL; r = r2) {
+ r2 = r->next;
+ if (r->defn != null)
+ free(r->defn);
+ free(r);
+ }
+ n->d = NULL;
+ }
+}
+
+void
+macro_popdef(const char *name)
+{
+ ndptr n = lookup(name);
+
+ if (n != NULL) {
+ struct macro_definition *r = n->d;
+ if (r != NULL) {
+ n->d = r->next;
+ if (r->defn != null)
+ free(r->defn);
+ free(r);
+ }
+ }
+}
+
+void
+macro_for_all(void (*f)(const char *, struct macro_definition *))
+{
+ ndptr n;
+ unsigned int i;
+
+ for (n = ohash_first(&macros, &i); n != NULL;
+ n = ohash_next(&macros, &i))
+ if (n->d != NULL)
+ f(n->name, n->d);
+}
+
+void
+setup_builtin(const char *name, unsigned int type)
+{
+ ndptr n;
+ char *name2;
+
+ if (prefix_builtins) {
+ name2 = xalloc(strlen(name)+3+1, NULL);
+ memcpy(name2, "m4_", 3);
+ memcpy(name2 + 3, name, strlen(name)+1);
+ } else
+ name2 = xstrdup(name);
+
+ n = create_entry(name2);
+ n->builtin_type = type;
+ n->d = xalloc(sizeof(struct macro_definition), NULL);
+ n->d->defn = name2;
+ n->d->type = type;
+ n->d->next = NULL;
+}
+
+void
+mark_traced(const char *name, int on)
+{
+ ndptr p;
+ unsigned int i;
+
+ if (name == NULL) {
+ if (on)
+ trace_flags |= TRACE_ALL;
+ else
+ trace_flags &= ~TRACE_ALL;
+ for (p = ohash_first(&macros, &i); p != NULL;
+ p = ohash_next(&macros, &i))
+ p->trace_flags = FLAG_NO_TRACE;
+ } else {
+ p = create_entry(name);
+ p->trace_flags = on;
+ }
+}
+
+ndptr
+macro_getbuiltin(const char *name)
+{
+ ndptr p;
+
+ p = lookup(name);
+ if (p == NULL || p->builtin_type == MACRTYPE)
+ return NULL;
+ else
+ return p;
+}
+
+/* XXX things are slightly more complicated than they seem.
+ * a macro may actually be "live" (in the middle of an expansion
+ * on the stack.
+ * So we actually may need to place it in an array for later...
+ */
+
+static int kept_capacity = 0;
+static int kept_size = 0;
+static char **kept = NULL;
+
+static void
+keep(char *ptr)
+{
+ if (kept_capacity <= kept_size) {
+ if (kept_capacity)
+ kept_capacity *= 2;
+ else
+ kept_capacity = 50;
+ kept = xreallocarray(kept, kept_capacity,
+ sizeof(char *), "Out of memory while saving %d strings\n",
+ kept_capacity);
+ }
+ kept[kept_size++] = ptr;
+}
+
+static int
+string_in_use(const char *ptr)
+{
+ int i;
+ for (i = 0; i <= sp; i++) {
+ if (sstack[i] == STORAGE_MACRO && mstack[i].sstr == ptr)
+ return 1;
+ }
+ return 0;
+}
+
+
+static void
+free_definition(char *ptr)
+{
+ int i;
+
+ /* first try to free old strings */
+ for (i = 0; i < kept_size; i++) {
+ if (!string_in_use(kept[i])) {
+ kept_size--;
+ free(kept[i]);
+ if (i != kept_size)
+ kept[i] = kept[kept_size];
+ i--;
+ }
+ }
+
+ /* then deal with us */
+ if (string_in_use(ptr))
+ keep(ptr);
+ else
+ free(ptr);
+}
+
diff --git a/usr.bin/m4/m4.1 b/usr.bin/m4/m4.1
new file mode 100644
index 000000000000..8b02ad2e7240
--- /dev/null
+++ b/usr.bin/m4/m4.1
@@ -0,0 +1,561 @@
+.\" $NetBSD: m4.1,v 1.23 2012/04/08 22:00:39 wiz Exp $
+.\"
+.\" Copyright (c) 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Ozan Yigit at York University.
+.\"
+.\" 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.
+.\"
+.Dd June 21, 2023
+.Dt M4 1
+.Os
+.Sh NAME
+.Nm m4
+.Nd macro language processor
+.Sh SYNOPSIS
+.Nm
+.Op Fl EGgPs
+.Oo
+.Sm off
+.Fl D Ar name Op No = Ar value
+.Sm on
+.Oc
+.Op Fl d Oo Oo +- Oc Ns Ar flags Oc
+.Op Fl I Ar dirname
+.Op Fl o Ar filename
+.Op Fl t Ar macro
+.Op Fl U Ns Ar name
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a macro processor that can be used as a front end to any
+language (e.g., C, ratfor, fortran, lex, and yacc).
+If no input files are given,
+.Nm
+reads from the standard input,
+otherwise files specified on the command line are
+processed in the given order.
+Input files can be regular files, files in the m4 include paths, or a
+single dash
+.Pq Sq - ,
+denoting standard input.
+.Nm
+writes
+the processed text to the standard output, unless told otherwise.
+.Pp
+Macro calls have the form name(argument1[, argument2, ..., argumentN]).
+.Pp
+There cannot be any space following the macro name and the open
+parenthesis
+.Pq Sq \&( .
+If the macro name is not followed by an open
+parenthesis it is processed with no arguments.
+.Pp
+Macro names consist of a leading alphabetic or underscore
+possibly followed by alphanumeric or underscore characters, e.g.,
+valid macro names match the pattern
+.Dq [a-zA-Z_][a-zA-Z0-9_]* .
+.Pp
+In arguments to macros, leading unquoted space, tab, and newline
+.Pq Sq \en
+characters are ignored.
+To quote strings, use left and right single quotes
+.Pq e.g., Sq \ \&this is a string with a leading space .
+You can change the quote characters with the
+.Ic changequote
+built-in macro.
+.Pp
+Most built-ins do not make any sense without arguments, and hence are not
+recognized as special when not followed by an open parenthesis.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl D Ns Ar name Ns Oo = Ns Ar value Oc , Fl -define Ns = Ns Ar name Ns Oo = Ns Ar value Oc
+Define the symbol
+.Ar name
+to have some value (or
+.Dv NULL ) .
+.It Fl d Oo Oo +|- Oc Ns Ar flags Oc , Fl -debug Ns = Ns Oo Oo +|- Oc Ns Ar flags Oc
+Set or unset trace flags.
+The trace flags are as follows:
+.Bl -tag -width Ds
+.It Ar a
+print macro arguments.
+.It Ar c
+print macro expansion over several lines.
+.It Ar e
+print result of macro expansion.
+.It Ar f
+print filename location.
+.It Ar l
+print line number.
+.It Ar q
+quote arguments and expansion with the current quotes.
+.It Ar t
+start with all macros traced.
+.It Ar x
+number macro expansions.
+.It Ar V
+turn on all options.
+.El
+.Pp
+If
+.Qq +
+or
+.Qq -
+is used, the specified flags are added to or removed from the set of
+active trace flags, respectively; otherwise, the specified flags
+replace the set of active trace flags.
+.Pp
+Specifying this option without an argument is equivalent to specifying
+it with the argument
+.Qq aeq .
+.Pp
+By default, trace is set to
+.Qq eq .
+.It Fl E , Fl -fatal-warnings
+Set warnings to be fatal.
+When a single
+.Fl E
+flag is specified, if warnings are issued, execution
+continues but
+.Nm
+will exit with a non-zero exit status.
+When multiple
+.Fl E
+flags are specified, execution will halt upon issuing the
+first warning and
+.Nm
+will exit with a non-zero exit status.
+This behavior matches GNU m4 1.4.9 and later.
+.It Fl G , Fl -traditional
+Disable GNU compatibility mode (see
+.Fl g
+below).
+.It Fl g , Fl -gnu
+Enable GNU compatibility mode.
+In this mode,
+.Ic translit
+handles simple character ranges (e.g.,
+.Sq a-z ) ,
+regular expressions mimic Emacs behavior,
+multiple
+.Ic m4wrap
+calls are handled as a stack,
+the number of diversions is unlimited,
+empty names for macro definitions are allowed,
+.Ic undivert
+can be used to include files,
+and
+.Ic eval
+understands
+.Sq 0rbase:value
+numbers.
+.It Fl I Ar dirname , Fl -include Ns = Ns Ar dirname
+Add directory
+.Ar dirname
+to the include path.
+.It Fl o Ar filename , Fl -error-output Ns = Ns Ar filename
+Send trace output to
+.Ar filename .
+.It Fl P , Fl -prefix-builtins
+Prefix all built-in macros with
+.Sq m4_ .
+For example, instead of writing
+.Ic define ,
+use
+.Ic m4_define .
+.It Fl s , Fl -synclines
+Output line synchronization directives, suitable for
+.Xr cpp 1 .
+.It Fl t Ar macro , Fl -trace Ns = Ns Ar macro
+Turn tracing on for
+.Ar macro .
+.It Fl U Ns Ar name , Fl -undefine Ns = Ns Ar name
+Undefine the symbol
+.Ar name .
+.El
+.Sh SYNTAX
+.Nm
+provides the following built-in macros.
+They may be redefined, losing their original meaning.
+Return values are null unless otherwise stated.
+.Bl -tag -width changequote
+.It Fn builtin name
+Calls a built-in by its
+.Fa name ,
+overriding possible redefinitions.
+.It Fn changecom startcomment endcomment
+Changes the start comment and end comment sequences.
+Comment sequences may be up to five characters long.
+The default values are the hash sign
+and the newline character.
+.Bd -literal -offset indent
+# This is a comment
+.Ed
+.Pp
+With no arguments, comments are turned off.
+With one single argument, the end comment sequence is set
+to the newline character.
+.It Fn changequote beginquote endquote
+Defines the open quote and close quote sequences.
+Quote sequences may be up to five characters long.
+The default values are the backquote character and the quote
+character.
+.Bd -literal -offset indent
+`Here is a quoted string'
+.Ed
+.Pp
+With no arguments, the default quotes are restored.
+With one single argument, the close quote sequence is set
+to the newline character.
+.It Fn decr arg
+Decrements the argument
+.Fa arg
+by 1.
+The argument
+.Fa arg
+must be a valid numeric string.
+.It Fn define name value
+Define a new macro named by the first argument
+.Fa name
+to have the
+value of the second argument
+.Fa value .
+Each occurrence of
+.Sq $n
+(where
+.Ar n
+is 0 through 9) is replaced by the
+.Ar n Ns 'th
+argument.
+.Sq $0
+is the name of the calling macro.
+Undefined arguments are replaced by a null string.
+.Sq $#
+is replaced by the number of arguments;
+.Sq $*
+is replaced by all arguments comma separated;
+.Sq $@
+is the same as
+.Sq $*
+but all arguments are quoted against further expansion.
+.It Fn defn name ...
+Returns the quoted definition for each argument.
+This can be used to rename
+macro definitions (even for built-in macros).
+.It Fn divert num
+There are 10 output queues (numbered 0-9).
+At the end of processing
+.Nm
+concatenates all the queues in numerical order to produce the
+final output.
+Initially the output queue is 0.
+The divert
+macro allows you to select a new output queue (an invalid argument
+passed to divert causes output to be discarded).
+.It Ic divnum
+Returns the current output queue number.
+.It Ic dnl
+Discard input characters up to and including the next newline.
+.It Fn dumpdef name ...
+Prints the names and definitions for the named items, or for everything
+if no arguments are passed.
+.It Fn errprint msg
+Prints the first argument on the standard error output stream.
+.It Fn esyscmd cmd
+Passes its first argument to a shell and returns the shell's standard output.
+Note that the shell shares its standard input and standard error with
+.Nm .
+.It Fn eval expr[,radix[,minimum]]
+Computes the first argument as an arithmetic expression using 32-bit
+arithmetic.
+Operators are the standard C ternary, arithmetic, logical,
+shift, relational, bitwise, and parentheses operators.
+You can specify
+octal, decimal, and hexadecimal numbers as in C.
+The optional second argument
+.Fa radix
+specifies the radix for the result and the optional third argument
+.Fa minimum
+specifies the minimum number of digits in the result.
+.It Fn expr expr
+This is an alias for
+.Ic eval .
+.It Fn format formatstring arg1 ...
+Returns
+.Fa formatstring
+with escape sequences substituted with
+.Fa arg1
+and following arguments, in a way similar to
+.Xr printf 3 .
+This built-in is only available in GNU-m4 compatibility mode, and the only
+parameters implemented are there for autoconf compatibility:
+left-padding flag, an optional field width, a maximum field width,
+*-specified field widths, and the %s and %c data type.
+.It Fn ifdef name yes no
+If the macro named by the first argument is defined then return the second
+argument, otherwise the third.
+If there is no third argument, the value is
+.Dv NULL .
+The word
+.Qq unix
+is predefined.
+.It Fn ifelse a b yes ...
+If the first argument
+.Fa a
+matches the second argument
+.Fa b
+then
+.Fn ifelse
+returns
+the third argument
+.Fa yes .
+If the match fails the three arguments are
+discarded and the next three arguments are used until there is
+zero or one arguments left, either this last argument or
+.Dv NULL
+is returned if no other matches were found.
+.It Fn include name
+Returns the contents of the file specified in the first argument.
+If the file is not found as is, look through the include path:
+first the directories specified with
+.Fl I
+on the command line, then the environment variable
+.Ev M4PATH ,
+as a colon-separated list of directories.
+Include aborts with an error message if the file cannot be included.
+.It Fn incr arg
+Increments the argument by 1.
+The argument must be a valid numeric string.
+.It Fn index string substring
+Returns the index of the second argument in the first argument (e.g.,
+.Ic index(the quick brown fox jumped, fox)
+returns 16).
+If the second
+argument is not found index returns \-1.
+.It Fn indir macro arg1 ...
+Indirectly calls the macro whose name is passed as the first argument,
+with the remaining arguments passed as first, ... arguments.
+.It Fn len arg
+Returns the number of characters in the first argument.
+Extra arguments
+are ignored.
+.It Fn m4exit code
+Immediately exits with the return value specified by the first argument,
+0 if none.
+.It Fn m4wrap todo
+Allows you to define what happens at the final
+.Dv EOF ,
+usually for cleanup purposes (e.g.,
+.Ic m4wrap("cleanup(tempfile)")
+causes the macro cleanup to be
+invoked after all other processing is done).
+.Pp
+Multiple calls to
+.Fn m4wrap
+get inserted in sequence at the final
+.Dv EOF .
+.It Fn maketemp template
+Like
+.Ic mkstemp .
+.It Fn mkstemp template
+Invokes
+.Xr mkstemp 3
+on the first argument, and returns the modified string.
+This can be used to create unique
+temporary file names.
+.It Fn paste file
+Includes the contents of the file specified by the first argument without
+any macro processing.
+Aborts with an error message if the file cannot be
+included.
+.It Fn patsubst string regexp replacement
+Substitutes a regular expression in a string with a replacement string.
+Usual substitution patterns apply: an ampersand
+.Pq Sq \&&
+is replaced by the string matching the regular expression.
+The string
+.Sq \e# ,
+where
+.Sq #
+is a digit, is replaced by the corresponding back-reference.
+.It Fn popdef arg ...
+Restores the
+.Ic pushdef Ns ed
+definition for each argument.
+.It Fn pushdef macro def
+Takes the same arguments as
+.Ic define ,
+but it saves the definition on a
+stack for later retrieval by
+.Fn popdef .
+.It Fn regexp string regexp replacement
+Finds a regular expression in a string.
+If no further arguments are given,
+it returns the first match position or \-1 if no match.
+If a third argument
+is provided, it returns the replacement string, with sub-patterns replaced.
+.It Fn shift arg1 ...
+Returns all but the first argument, the remaining arguments are
+quoted and pushed back with commas in between.
+The quoting
+nullifies the effect of the extra scan that will subsequently be
+performed.
+.It Fn sinclude file
+Similar to
+.Ic include ,
+except it ignores any errors.
+.It Fn spaste file
+Similar to
+.Fn paste ,
+except it ignores any errors.
+.It Fn substr string offset length
+Returns a substring of the first argument starting at the offset specified
+by the second argument and the length specified by the third argument.
+If no third argument is present it returns the rest of the string.
+.It Fn syscmd cmd
+Passes the first argument to the shell.
+Nothing is returned.
+.It Ic sysval
+Returns the return value from the last
+.Ic syscmd .
+.It Fn traceon arg ...
+Enables tracing of macro expansions for the given arguments, or for all
+macros if no argument is given.
+.It Fn traceoff arg ...
+Disables tracing of macro expansions for the given arguments, or for all
+macros if no argument is given.
+.It Fn translit string mapfrom mapto
+Transliterate the characters in the first argument from the set
+given by the second argument to the set given by the third.
+You cannot use
+.Xr tr 1
+style abbreviations.
+.It Fn undefine name1 ...
+Removes the definition for the macros specified by its arguments.
+.It Fn undivert arg ...
+Flushes the named output queues (or all queues if no arguments).
+.It Ic unix
+A pre-defined macro for testing the OS platform.
+.It Ic __line__
+Returns the current file's line number.
+.It Ic __file__
+Returns the current file's name.
+.El
+.Sh EXIT STATUS
+.Ex -std m4
+.Pp
+But note that the
+.Ic m4exit
+macro can modify the exit status, as can the
+.Fl E
+flag.
+.Sh SEE ALSO
+.Rs
+.\" 4.4BSD PSD:17
+.%A B. W. Kernighan
+.%A D. M. Ritchie
+.%I AT&T Bell Laboratories
+.%T The M4 Macro Processor
+.%R Computing Science Technical Report
+.%N 59
+.%D July 1977
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl dEGgIPot
+and the macros
+.Ic builtin ,
+.Ic esyscmd ,
+.Ic expr ,
+.Ic format ,
+.Ic indir ,
+.Ic paste ,
+.Ic patsubst ,
+.Ic regexp ,
+.Ic spaste ,
+.Ic unix ,
+.Ic __line__ ,
+and
+.Ic __file__
+are extensions to that specification.
+.Pp
+.Ic maketemp
+is not supposed to be a synonym for
+.Ic mkstemp ,
+but instead to be an insecure temporary file name creation function.
+It is marked by
+.St -p1003.1-2008
+as being obsolescent and should not be used if portability is a concern.
+.Pp
+The output format of
+.Ic traceon
+and
+.Ic dumpdef
+are not specified in any standard,
+are likely to change and should not be relied upon.
+The current format of tracing is closely modelled on
+.Nm gnu-m4 ,
+to allow
+.Nm autoconf
+to work.
+.Pp
+The built-ins
+.Ic pushdef
+and
+.Ic popdef
+handle macro definitions as a stack.
+However,
+.Ic define
+interacts with the stack in an undefined way.
+In this implementation,
+.Ic define
+replaces the top-most definition only.
+Other implementations may erase all definitions on the stack instead.
+.Pp
+All built-ins do expand without arguments in many other
+.Nm .
+.Pp
+Many other
+.Nm
+have dire size limitations with respect to buffer sizes.
+.Sh AUTHORS
+.An -nosplit
+.An Ozan Yigit Aq Mt oz@sis.yorku.ca
+and
+.An Richard A. O'Keefe Aq Mt ok@goanna.cs.rmit.OZ.AU .
+.Pp
+GNU-m4 compatibility extensions by
+.An Marc Espie Aq Mt espie@cvs.openbsd.org .
diff --git a/usr.bin/m4/main.c b/usr.bin/m4/main.c
new file mode 100644
index 000000000000..d68069cb10a8
--- /dev/null
+++ b/usr.bin/m4/main.c
@@ -0,0 +1,660 @@
+/* $OpenBSD: main.c,v 1.87 2017/06/15 13:48:42 bcallah Exp $ */
+/* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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.c
+ * Facility: m4 macro processor
+ * by: oz
+ */
+#include <sys/cdefs.h>
+#include <assert.h>
+#include <signal.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <ohash.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+#include "pathnames.h"
+
+static const char *shortopts = "+D:d::EGgI:o:Pst:U:";
+static const struct option longopts[] = {
+ { "define", required_argument, NULL, 'D' },
+ { "debug", optional_argument, NULL, 'd' },
+ { "fatal-warnings", no_argument, NULL, 'E' },
+ { "traditional", no_argument, NULL, 'G' },
+ { "gnu", no_argument, NULL, 'g' },
+ { "include", required_argument, NULL, 'I' },
+ { "error-output", required_argument, NULL, 'o' },
+ { "prefix-builtins", no_argument, NULL, 'P' },
+ { "synclines", no_argument, NULL, 's' },
+ { "trace", required_argument, NULL, 't' },
+ { "undefine", required_argument, NULL, 'U' },
+ { NULL, 0, NULL, 0 },
+};
+
+stae *mstack; /* stack of m4 machine */
+char *sstack; /* shadow stack, for string space extension */
+static size_t STACKMAX; /* current maximum size of stack */
+int sp; /* current m4 stack pointer */
+int fp; /* m4 call frame pointer */
+struct input_file infile[MAXINP];/* input file stack (0=stdin) */
+FILE **outfile; /* diversion array(0=bitbucket)*/
+int maxout;
+FILE *active; /* active output file pointer */
+int ilevel = 0; /* input file stack pointer */
+int oindex = 0; /* diversion index.. */
+const char *null = ""; /* as it says.. just a null.. */
+char **m4wraps = NULL; /* m4wraps array. */
+int maxwraps = 0; /* size of m4wraps array */
+int wrapindex = 0; /* current offset in m4wraps */
+char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */
+char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */
+char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */
+char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */
+int synch_lines = 0; /* line synchronisation for C preprocessor */
+int prefix_builtins = 0; /* -P option to prefix builtin keywords */
+int error_warns = 0; /* -E option to make warnings exit_code = 1 */
+int fatal_warns = 0; /* -E -E option to make warnings fatal */
+
+struct keyblk {
+ const char *knam; /* keyword name */
+ int ktyp; /* keyword type */
+};
+
+static struct keyblk keywrds[] = { /* m4 keywords to be installed */
+ { "include", INCLTYPE },
+ { "sinclude", SINCTYPE },
+ { "define", DEFITYPE },
+ { "defn", DEFNTYPE },
+ { "divert", DIVRTYPE | NOARGS },
+ { "expr", EXPRTYPE },
+ { "eval", EXPRTYPE },
+ { "substr", SUBSTYPE },
+ { "ifelse", IFELTYPE },
+ { "ifdef", IFDFTYPE },
+ { "len", LENGTYPE },
+ { "incr", INCRTYPE },
+ { "decr", DECRTYPE },
+ { "dnl", DNLNTYPE | NOARGS },
+ { "changequote", CHNQTYPE | NOARGS },
+ { "changecom", CHNCTYPE | NOARGS },
+ { "index", INDXTYPE },
+#ifdef EXTENDED
+ { "paste", PASTTYPE },
+ { "spaste", SPASTYPE },
+ /* Newer extensions, needed to handle gnu-m4 scripts */
+ { "indir", INDIRTYPE},
+ { "builtin", BUILTINTYPE},
+ { "patsubst", PATSTYPE},
+ { "regexp", REGEXPTYPE},
+ { "esyscmd", ESYSCMDTYPE},
+ { "__file__", FILENAMETYPE | NOARGS},
+ { "__line__", LINETYPE | NOARGS},
+#endif
+ { "popdef", POPDTYPE },
+ { "pushdef", PUSDTYPE },
+ { "dumpdef", DUMPTYPE | NOARGS },
+ { "shift", SHIFTYPE | NOARGS },
+ { "translit", TRNLTYPE },
+ { "undefine", UNDFTYPE },
+ { "undivert", UNDVTYPE | NOARGS },
+ { "divnum", DIVNTYPE | NOARGS },
+ { "maketemp", MKTMTYPE },
+ { "mkstemp", MKTMTYPE },
+ { "errprint", ERRPTYPE | NOARGS },
+ { "m4wrap", M4WRTYPE | NOARGS },
+ { "m4exit", EXITTYPE | NOARGS },
+ { "syscmd", SYSCTYPE },
+ { "sysval", SYSVTYPE | NOARGS },
+ { "traceon", TRACEONTYPE | NOARGS },
+ { "traceoff", TRACEOFFTYPE | NOARGS },
+
+ { "unix", SELFTYPE | NOARGS },
+};
+
+#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
+
+extern int optind;
+extern char *optarg;
+
+#define MAXRECORD 50
+static struct position {
+ char *name;
+ unsigned long line;
+} quotes[MAXRECORD], paren[MAXRECORD];
+
+static void record(struct position *, int);
+static void dump_stack(struct position *, int);
+
+static void macro(void);
+static void initkwds(void);
+static ndptr inspect(int, char *);
+static int do_look_ahead(int, const char *);
+static void reallyoutputstr(const char *);
+static void reallyputchar(int);
+
+static void enlarge_stack(void);
+
+int main(int, char *[]);
+
+int exit_code = 0;
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int n;
+ char *p;
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+
+ init_macros();
+ initspaces();
+ STACKMAX = INITSTACKMAX;
+
+ mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL);
+ sstack = xalloc(STACKMAX, NULL);
+
+ maxout = 0;
+ outfile = NULL;
+ resizedivs(MAXOUT);
+
+ while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
+ switch(c) {
+
+ case 'D': /* define something..*/
+ for (p = optarg; *p; p++)
+ if (*p == '=')
+ break;
+ if (*p)
+ *p++ = EOS;
+ dodefine(optarg, p);
+ break;
+ case 'E': /* like GNU m4 1.4.9+ */
+ if (error_warns == 0)
+ error_warns = 1;
+ else
+ fatal_warns = 1;
+ break;
+ case 'I':
+ addtoincludepath(optarg);
+ break;
+ case 'P':
+ prefix_builtins = 1;
+ break;
+ case 'U': /* undefine... */
+ macro_popdef(optarg);
+ break;
+ case 'G':
+ mimic_gnu = 0;
+ break;
+ case 'g':
+ mimic_gnu = 1;
+ break;
+ case 'd':
+ set_trace_flags(optarg ? optarg : "aeq");
+ break;
+ case 's':
+ synch_lines = 1;
+ break;
+ case 't':
+ mark_traced(optarg, 1);
+ break;
+ case 'o':
+ trace_file(optarg);
+ break;
+ case '?':
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ initkwds();
+ if (mimic_gnu)
+ setup_builtin("format", FORMATTYPE);
+
+ active = stdout; /* default active output */
+ bbase[0] = bufbase;
+ if (!argc) {
+ sp = -1; /* stack pointer initialized */
+ fp = 0; /* frame pointer initialized */
+ set_input(infile+0, stdin, "stdin");
+ /* default input (naturally) */
+ macro();
+ } else
+ for (; argc--; ++argv) {
+ p = *argv;
+ if (p[0] == '-' && p[1] == EOS)
+ set_input(infile, stdin, "stdin");
+ else if (fopen_trypath(infile, p) == NULL)
+ err(1, "%s", p);
+ sp = -1;
+ fp = 0;
+ macro();
+ release_input(infile);
+ }
+
+ if (wrapindex) {
+ int i;
+
+ ilevel = 0; /* in case m4wrap includes.. */
+ bufbase = bp = buf; /* use the entire buffer */
+ if (mimic_gnu) {
+ while (wrapindex != 0) {
+ for (i = 0; i < wrapindex; i++)
+ pbstr(m4wraps[i]);
+ wrapindex =0;
+ macro();
+ }
+ } else {
+ for (i = 0; i < wrapindex; i++) {
+ pbstr(m4wraps[i]);
+ macro();
+ }
+ }
+ }
+
+ if (active != stdout)
+ active = stdout; /* reset output just in case */
+ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */
+ if (outfile[n] != NULL)
+ getdiv(n);
+ /* remove bitbucket if used */
+ if (outfile[0] != NULL) {
+ (void) fclose(outfile[0]);
+ }
+
+ return exit_code;
+}
+
+/*
+ * Look ahead for `token'.
+ * (on input `t == token[0]')
+ * Used for comment and quoting delimiters.
+ * Returns 1 if `token' present; copied to output.
+ * 0 if `token' not found; all characters pushed back
+ */
+static int
+do_look_ahead(int t, const char *token)
+{
+ int i;
+
+ assert((unsigned char)t == (unsigned char)token[0]);
+
+ for (i = 1; *++token; i++) {
+ t = gpbc();
+ if (t == EOF || (unsigned char)t != (unsigned char)*token) {
+ pushback(t);
+ while (--i)
+ pushback(*--token);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define LOOK_AHEAD(t, token) (t != EOF && \
+ (unsigned char)(t)==(unsigned char)(token)[0] && \
+ do_look_ahead(t,token))
+
+/*
+ * macro - the work horse..
+ */
+static void
+macro(void)
+{
+ char token[MAXTOK+1];
+ int t, l;
+ ndptr p;
+ int nlpar;
+
+ cycle {
+ t = gpbc();
+
+ if (LOOK_AHEAD(t,lquote)) { /* strip quotes */
+ nlpar = 0;
+ record(quotes, nlpar++);
+ /*
+ * Opening quote: scan forward until matching
+ * closing quote has been found.
+ */
+ do {
+
+ l = gpbc();
+ if (LOOK_AHEAD(l,rquote)) {
+ if (--nlpar > 0)
+ outputstr(rquote);
+ } else if (LOOK_AHEAD(l,lquote)) {
+ record(quotes, nlpar++);
+ outputstr(lquote);
+ } else if (l == EOF) {
+ if (nlpar == 1)
+ warnx("unclosed quote:");
+ else
+ warnx("%d unclosed quotes:", nlpar);
+ dump_stack(quotes, nlpar);
+ exit(1);
+ } else {
+ if (nlpar > 0) {
+ if (sp < 0)
+ reallyputchar(l);
+ else
+ CHRSAVE(l);
+ }
+ }
+ }
+ while (nlpar != 0);
+ } else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
+ reallyoutputstr(scommt);
+
+ for(;;) {
+ t = gpbc();
+ if (LOOK_AHEAD(t, ecommt)) {
+ reallyoutputstr(ecommt);
+ break;
+ }
+ if (t == EOF)
+ break;
+ reallyputchar(t);
+ }
+ } else if (t == '_' || isalpha(t)) {
+ p = inspect(t, token);
+ if (p != NULL)
+ pushback(l = gpbc());
+ if (p == NULL || (l != LPAREN &&
+ (macro_getdef(p)->type & NEEDARGS) != 0))
+ outputstr(token);
+ else {
+ /*
+ * real thing.. First build a call frame:
+ */
+ pushf(fp); /* previous call frm */
+ pushf(macro_getdef(p)->type); /* type of the call */
+ pushf(is_traced(p));
+ pushf(0); /* parenthesis level */
+ fp = sp; /* new frame pointer */
+ /*
+ * now push the string arguments:
+ */
+ pushdef(p); /* defn string */
+ pushs1((char *)macro_name(p)); /* macro name */
+ pushs(ep); /* start next..*/
+
+ if (l != LPAREN && PARLEV == 0) {
+ /* no bracks */
+ chrsave(EOS);
+
+ if (sp == (int)STACKMAX)
+ errx(1, "internal stack overflow");
+ eval((const char **) mstack+fp+1, 2,
+ CALTYP, TRACESTATUS);
+
+ ep = PREVEP; /* flush strspace */
+ sp = PREVSP; /* previous sp.. */
+ fp = PREVFP; /* rewind stack...*/
+ }
+ }
+ } else if (t == EOF) {
+ if (!mimic_gnu /* you can puke right there */
+ && sp > -1 && ilevel <= 0) {
+ warnx( "unexpected end of input, unclosed parenthesis:");
+ dump_stack(paren, PARLEV);
+ exit(1);
+ }
+ if (ilevel <= 0)
+ break; /* all done thanks.. */
+ release_input(infile+ilevel--);
+ emit_synchline();
+ bufbase = bbase[ilevel];
+ continue;
+ } else if (sp < 0) { /* not in a macro at all */
+ reallyputchar(t); /* output directly.. */
+ }
+
+ else switch(t) {
+
+ case LPAREN:
+ if (PARLEV > 0)
+ chrsave(t);
+ while (isspace(l = gpbc())) /* skip blank, tab, nl.. */
+ if (PARLEV > 0)
+ chrsave(l);
+ pushback(l);
+ record(paren, PARLEV++);
+ break;
+
+ case RPAREN:
+ if (--PARLEV > 0)
+ chrsave(t);
+ else { /* end of argument list */
+ chrsave(EOS);
+
+ if (sp == (int)STACKMAX)
+ errx(1, "internal stack overflow");
+
+ eval((const char **) mstack+fp+1, sp-fp,
+ CALTYP, TRACESTATUS);
+
+ ep = PREVEP; /* flush strspace */
+ sp = PREVSP; /* previous sp.. */
+ fp = PREVFP; /* rewind stack...*/
+ }
+ break;
+
+ case COMMA:
+ if (PARLEV == 1) {
+ chrsave(EOS); /* new argument */
+ while (isspace(l = gpbc()))
+ ;
+ pushback(l);
+ pushs(ep);
+ } else
+ chrsave(t);
+ break;
+
+ default:
+ if (LOOK_AHEAD(t, scommt)) {
+ char *p;
+ for (p = scommt; *p; p++)
+ chrsave(*p);
+ for(;;) {
+ t = gpbc();
+ if (LOOK_AHEAD(t, ecommt)) {
+ for (p = ecommt; *p; p++)
+ chrsave(*p);
+ break;
+ }
+ if (t == EOF)
+ break;
+ CHRSAVE(t);
+ }
+ } else
+ CHRSAVE(t); /* stack the char */
+ break;
+ }
+ }
+}
+
+/*
+ * output string directly, without pushing it for reparses.
+ */
+void
+outputstr(const char *s)
+{
+ if (sp < 0)
+ reallyoutputstr(s);
+ else
+ while (*s)
+ CHRSAVE(*s++);
+}
+
+void
+reallyoutputstr(const char *s)
+{
+ if (synch_lines) {
+ while (*s) {
+ fputc(*s, active);
+ if (*s++ == '\n') {
+ infile[ilevel].synch_lineno++;
+ if (infile[ilevel].synch_lineno !=
+ infile[ilevel].lineno)
+ do_emit_synchline();
+ }
+ }
+ } else
+ fputs(s, active);
+}
+
+void
+reallyputchar(int c)
+{
+ putc(c, active);
+ if (synch_lines && c == '\n') {
+ infile[ilevel].synch_lineno++;
+ if (infile[ilevel].synch_lineno != infile[ilevel].lineno)
+ do_emit_synchline();
+ }
+}
+
+/*
+ * build an input token..
+ * consider only those starting with _ or A-Za-z.
+ */
+static ndptr
+inspect(int c, char *tp)
+{
+ char *name = tp;
+ char *etp = tp+MAXTOK;
+ ndptr p;
+
+ *tp++ = c;
+
+ while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
+ *tp++ = c;
+ if (c != EOF)
+ PUSHBACK(c);
+ *tp = EOS;
+ /* token is too long, it won't match anything, but it can still
+ * be output. */
+ if (tp == ep) {
+ outputstr(name);
+ while (isalnum(c = gpbc()) || c == '_') {
+ if (sp < 0)
+ reallyputchar(c);
+ else
+ CHRSAVE(c);
+ }
+ *name = EOS;
+ return NULL;
+ }
+
+ p = ohash_find(&macros, ohash_qlookupi(&macros, name, (const char **)&tp));
+ if (p == NULL)
+ return NULL;
+ if (macro_getdef(p) == NULL)
+ return NULL;
+ return p;
+}
+
+/*
+ * initkwds - initialise m4 keywords as fast as possible.
+ * This very similar to install, but without certain overheads,
+ * such as calling lookup. Malloc is not used for storing the
+ * keyword strings, since we simply use the static pointers
+ * within keywrds block.
+ */
+static void
+initkwds(void)
+{
+ unsigned int type;
+ int i;
+
+ for (i = 0; i < (int)MAXKEYS; i++) {
+ type = keywrds[i].ktyp & TYPEMASK;
+ if ((keywrds[i].ktyp & NOARGS) == 0)
+ type |= NEEDARGS;
+ setup_builtin(keywrds[i].knam, type);
+ }
+}
+
+static void
+record(struct position *t, int lev)
+{
+ if (lev < MAXRECORD) {
+ t[lev].name = CURRENT_NAME;
+ t[lev].line = CURRENT_LINE;
+ }
+}
+
+static void
+dump_stack(struct position *t, int lev)
+{
+ int i;
+
+ for (i = 0; i < lev; i++) {
+ if (i == MAXRECORD) {
+ fprintf(stderr, " ...\n");
+ break;
+ }
+ fprintf(stderr, " %s at line %lu\n",
+ t[i].name, t[i].line);
+ }
+}
+
+
+static void
+enlarge_stack(void)
+{
+ STACKMAX += STACKMAX/2;
+ mstack = xreallocarray(mstack, STACKMAX, sizeof(stae),
+ "Evaluation stack overflow (%lu)",
+ (unsigned long)STACKMAX);
+ sstack = xrealloc(sstack, STACKMAX,
+ "Evaluation stack overflow (%lu)",
+ (unsigned long)STACKMAX);
+}
diff --git a/usr.bin/m4/mdef.h b/usr.bin/m4/mdef.h
new file mode 100644
index 000000000000..d4fa5b0e0c14
--- /dev/null
+++ b/usr.bin/m4/mdef.h
@@ -0,0 +1,237 @@
+/* $OpenBSD: mdef.h,v 1.33 2015/11/03 16:21:47 deraadt Exp $ */
+/* $NetBSD: mdef.h,v 1.7 1996/01/13 23:25:27 pk Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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.
+ */
+
+#ifdef __GNUC__
+# define UNUSED __attribute__((__unused__))
+#else
+# define UNUSED
+#endif
+
+#define MACRTYPE 1
+#define DEFITYPE 2
+#define EXPRTYPE 3
+#define SUBSTYPE 4
+#define IFELTYPE 5
+#define LENGTYPE 6
+#define CHNQTYPE 7
+#define SYSCTYPE 8
+#define UNDFTYPE 9
+#define INCLTYPE 10
+#define SINCTYPE 11
+#define PASTTYPE 12
+#define SPASTYPE 13
+#define INCRTYPE 14
+#define IFDFTYPE 15
+#define PUSDTYPE 16
+#define POPDTYPE 17
+#define SHIFTYPE 18
+#define DECRTYPE 19
+#define DIVRTYPE 20
+#define UNDVTYPE 21
+#define DIVNTYPE 22
+#define MKTMTYPE 23
+#define ERRPTYPE 24
+#define M4WRTYPE 25
+#define TRNLTYPE 26
+#define DNLNTYPE 27
+#define DUMPTYPE 28
+#define CHNCTYPE 29
+#define INDXTYPE 30
+#define SYSVTYPE 31
+#define EXITTYPE 32
+#define DEFNTYPE 33
+#define SELFTYPE 34
+#define INDIRTYPE 35
+#define BUILTINTYPE 36
+#define PATSTYPE 37
+#define FILENAMETYPE 38
+#define LINETYPE 39
+#define REGEXPTYPE 40
+#define ESYSCMDTYPE 41
+#define TRACEONTYPE 42
+#define TRACEOFFTYPE 43
+#define FORMATTYPE 44
+
+#define BUILTIN_MARKER "__builtin_"
+
+#define TYPEMASK 63 /* Keep bits really corresponding to a type. */
+#define RECDEF 256 /* Pure recursive def, don't expand it */
+#define NOARGS 512 /* builtin needs no args */
+#define NEEDARGS 1024 /* mark builtin that need args with this */
+
+/*
+ * m4 special characters
+ */
+
+#define ARGFLAG '$'
+#define LPAREN '('
+#define RPAREN ')'
+#define LQUOTE '`'
+#define RQUOTE '\''
+#define COMMA ','
+#define SCOMMT '#'
+#define ECOMMT '\n'
+
+/*
+ * other important constants
+ */
+
+#define EOS '\0'
+#define MAXINP 10 /* maximum include files */
+#define MAXOUT 10 /* maximum # of diversions */
+#define BUFSIZE 4096 /* starting size of pushback buffer */
+#define INITSTACKMAX 4096 /* starting size of call stack */
+#define STRSPMAX 4096 /* starting size of string space */
+#define MAXTOK 512 /* maximum chars in a tokn */
+#define MAXCCHARS 5 /* max size of comment/quote delim */
+
+#define ALL 1
+#define TOP 0
+
+#define TRUE 1
+#define FALSE 0
+#define cycle for(;;)
+
+/*
+ * m4 data structures
+ */
+
+typedef struct ndblock *ndptr;
+
+struct macro_definition {
+ struct macro_definition *next;
+ char *defn; /* definition.. */
+ unsigned int type; /* type of the entry.. */
+};
+
+
+struct ndblock { /* hashtable structure */
+ unsigned int builtin_type;
+ unsigned int trace_flags;
+ struct macro_definition *d;
+ char name[1]; /* entry name.. */
+};
+
+typedef union { /* stack structure */
+ int sfra; /* frame entry */
+ char *sstr; /* string entry */
+} stae;
+
+struct input_file {
+ FILE *file;
+ char *name;
+ unsigned long lineno;
+ unsigned long synch_lineno; /* used for -s */
+ int c;
+};
+
+#define STORAGE_STRSPACE 0
+#define STORAGE_MACRO 1
+#define STORAGE_OTHER 2
+
+#define CURRENT_NAME (infile[ilevel].name)
+#define CURRENT_LINE (infile[ilevel].lineno)
+/*
+ * macros for readibility and/or speed
+ *
+ * gpbc() - get a possibly pushed-back character
+ * pushf() - push a call frame entry onto stack
+ * pushs() - push a string pointer onto stack
+ */
+#define gpbc() (bp > bufbase) ? *--bp : obtain_char(infile+ilevel)
+#define pushf(x) \
+ do { \
+ if (++sp == (int)STACKMAX) \
+ enlarge_stack();\
+ mstack[sp].sfra = (x); \
+ sstack[sp] = STORAGE_OTHER; \
+ } while (0)
+
+#define pushs(x) \
+ do { \
+ if (++sp == (int)STACKMAX) \
+ enlarge_stack();\
+ mstack[sp].sstr = (x); \
+ sstack[sp] = STORAGE_STRSPACE; \
+ } while (0)
+
+#define pushs1(x) \
+ do { \
+ if (++sp == (int)STACKMAX) \
+ enlarge_stack();\
+ mstack[sp].sstr = (x); \
+ sstack[sp] = STORAGE_OTHER; \
+ } while (0)
+
+#define pushdef(p) \
+ do { \
+ if (++sp == (int)STACKMAX) \
+ enlarge_stack();\
+ mstack[sp].sstr = macro_getdef(p)->defn;\
+ sstack[sp] = STORAGE_MACRO; \
+ } while (0)
+
+
+/*
+ * . .
+ * | . | <-- sp | . |
+ * +-------+ +-----+
+ * | arg 3 ----------------------->| str |
+ * +-------+ | . |
+ * | arg 2 ---PREVEP-----+ .
+ * +-------+ |
+ * . | | |
+ * +-------+ | +-----+
+ * | plev | PARLEV +-------->| str |
+ * +-------+ | . |
+ * | type | CALTYP .
+ * +-------+
+ * | prcf ---PREVFP--+
+ * +-------+ |
+ * | . | PREVSP |
+ * . |
+ * +-------+ |
+ * | <----------+
+ * +-------+
+ *
+ */
+#define PARLEV (mstack[fp].sfra)
+#define CALTYP (mstack[fp-2].sfra)
+#define TRACESTATUS (mstack[fp-1].sfra)
+#define PREVEP (mstack[fp+3].sstr)
+#define PREVSP (fp-4)
+#define PREVFP (mstack[fp-3].sfra)
diff --git a/usr.bin/m4/misc.c b/usr.bin/m4/misc.c
new file mode 100644
index 000000000000..d641ec56afeb
--- /dev/null
+++ b/usr.bin/m4/misc.c
@@ -0,0 +1,469 @@
+/* $OpenBSD: misc.c,v 1.47 2017/06/15 13:48:42 bcallah Exp $ */
+/* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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 <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <err.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+#include "pathnames.h"
+
+
+char *ep; /* first free char in strspace */
+static char *strspace; /* string space for evaluation */
+char *endest; /* end of string space */
+static size_t strsize = STRSPMAX;
+static size_t bufsize = BUFSIZE;
+
+unsigned char *buf; /* push-back buffer */
+unsigned char *bufbase; /* the base for current ilevel */
+unsigned char *bbase[MAXINP]; /* the base for each ilevel */
+unsigned char *bp; /* first available character */
+unsigned char *endpbb; /* end of push-back buffer */
+
+
+/*
+ * find the index of second str in the first str.
+ */
+ptrdiff_t
+indx(const char *s1, const char *s2)
+{
+ char *t;
+
+ t = strstr(s1, s2);
+ if (t == NULL)
+ return (-1);
+ else
+ return (t - s1);
+}
+/*
+ * pushback - push character back onto input
+ */
+void
+pushback(int c)
+{
+ if (c == EOF)
+ return;
+ if (bp >= endpbb)
+ enlarge_bufspace();
+ *bp++ = c;
+}
+
+/*
+ * pbstr - push string back onto input
+ * pushback is replicated to improve
+ * performance.
+ */
+void
+pbstr(const char *s)
+{
+ size_t n;
+
+ n = strlen(s);
+ while (endpbb - bp <= (long)n)
+ enlarge_bufspace();
+ while (n > 0)
+ *bp++ = s[--n];
+}
+
+/*
+ * pbnum - convert number to string, push back on input.
+ */
+void
+pbnum(int n)
+{
+ pbnumbase(n, 10, 0);
+}
+
+void
+pbnumbase(int n, int base, int d)
+{
+ static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ int num;
+ int printed = 0;
+
+ if (base > 36)
+ m4errx(1, "base %d > 36: not supported.", base);
+
+ if (base < 2)
+ m4errx(1, "bad base %d for conversion.", base);
+
+ num = (n < 0) ? -n : n;
+ do {
+ pushback(digits[num % base]);
+ printed++;
+ }
+ while ((num /= base) > 0);
+
+ if (n < 0)
+ printed++;
+ while (printed++ < d)
+ pushback('0');
+
+ if (n < 0)
+ pushback('-');
+}
+
+/*
+ * pbunsigned - convert unsigned long to string, push back on input.
+ */
+void
+pbunsigned(unsigned long n)
+{
+ do {
+ pushback(n % 10 + '0');
+ }
+ while ((n /= 10) > 0);
+}
+
+void
+initspaces(void)
+{
+ int i;
+
+ strspace = xalloc(strsize+1, NULL);
+ ep = strspace;
+ endest = strspace+strsize;
+ buf = xalloc(bufsize, NULL);
+ bufbase = buf;
+ bp = buf;
+ endpbb = buf + bufsize;
+ for (i = 0; i < MAXINP; i++)
+ bbase[i] = buf;
+}
+
+void
+enlarge_strspace(void)
+{
+ char *newstrspace;
+ int i;
+
+ strsize *= 2;
+ newstrspace = malloc(strsize + 1);
+ if (!newstrspace)
+ errx(1, "string space overflow");
+ memcpy(newstrspace, strspace, strsize/2);
+ for (i = 0; i <= sp; i++)
+ if (sstack[i] == STORAGE_STRSPACE)
+ mstack[i].sstr = (mstack[i].sstr - strspace)
+ + newstrspace;
+ ep = (ep-strspace) + newstrspace;
+ free(strspace);
+ strspace = newstrspace;
+ endest = strspace + strsize;
+}
+
+void
+enlarge_bufspace(void)
+{
+ unsigned char *newbuf;
+ int i;
+
+ bufsize += bufsize/2;
+ newbuf = xrealloc(buf, bufsize, "too many characters pushed back");
+ for (i = 0; i < MAXINP; i++)
+ bbase[i] = (bbase[i]-buf)+newbuf;
+ bp = (bp-buf)+newbuf;
+ bufbase = (bufbase-buf)+newbuf;
+ buf = newbuf;
+ endpbb = buf+bufsize;
+}
+
+/*
+ * chrsave - put single char on string space
+ */
+void
+chrsave(int c)
+{
+ if (ep >= endest)
+ enlarge_strspace();
+ *ep++ = c;
+}
+
+/*
+ * read in a diversion file, and dispose it.
+ */
+void
+getdiv(int n)
+{
+ int c;
+
+ if (active == outfile[n])
+ m4errx(1, "undivert: diversion still active.");
+ rewind(outfile[n]);
+ while ((c = getc(outfile[n])) != EOF)
+ putc(c, active);
+ (void) fclose(outfile[n]);
+ outfile[n] = NULL;
+}
+
+void
+onintr(int signo __unused)
+{
+#define intrmessage "m4: interrupted.\n"
+ write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1);
+ _exit(1);
+}
+
+/*
+ * killdiv - get rid of the diversion files
+ */
+void
+killdiv(void)
+{
+ int n;
+
+ for (n = 0; n < maxout; n++)
+ if (outfile[n] != NULL) {
+ (void) fclose(outfile[n]);
+ }
+}
+
+extern char *__progname;
+
+void
+m4errx(int eval, const char *fmt, ...)
+{
+ fprintf(stderr, "%s: ", __progname);
+ fprintf(stderr, "%s at line %lu: ", CURRENT_NAME, CURRENT_LINE);
+ if (fmt != NULL) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+ fprintf(stderr, "\n");
+ exit(eval);
+}
+
+/*
+ * resizedivs: allocate more diversion files */
+void
+resizedivs(int n)
+{
+ int i;
+
+ outfile = xreallocarray(outfile, n, sizeof(FILE *),
+ "too many diverts %d", n);
+ for (i = maxout; i < n; i++)
+ outfile[i] = NULL;
+ maxout = n;
+}
+
+void *
+xalloc(size_t n, const char *fmt, ...)
+{
+ void *p = malloc(n);
+
+ if (p == NULL) {
+ if (fmt == NULL)
+ err(1, "malloc");
+ else {
+ va_list va;
+
+ va_start(va, fmt);
+ verr(1, fmt, va);
+ va_end(va);
+ }
+ }
+ return p;
+}
+
+void *
+xcalloc(size_t n, size_t s, const char *fmt, ...)
+{
+ void *p = calloc(n, s);
+
+ if (p == NULL) {
+ if (fmt == NULL)
+ err(1, "calloc");
+ else {
+ va_list va;
+
+ va_start(va, fmt);
+ verr(1, fmt, va);
+ va_end(va);
+ }
+ }
+ return p;
+}
+
+void *
+xrealloc(void *old, size_t n, const char *fmt, ...)
+{
+ char *p = realloc(old, n);
+
+ if (p == NULL) {
+ free(old);
+ if (fmt == NULL)
+ err(1, "realloc");
+ else {
+ va_list va;
+
+ va_start(va, fmt);
+ verr(1, fmt, va);
+ va_end(va);
+ }
+ }
+ return p;
+}
+
+void *
+xreallocarray(void *old, size_t s1, size_t s2, const char *fmt, ...)
+{
+ void *p = reallocarray(old, s1, s2);
+
+ if (p == NULL) {
+ free(old);
+ if (fmt == NULL)
+ err(1, "reallocarray");
+ else {
+ va_list va;
+
+ va_start(va, fmt);
+ verr(1, fmt, va);
+ va_end(va);
+ }
+ }
+ return p;
+}
+
+char *
+xstrdup(const char *s)
+{
+ char *p = strdup(s);
+ if (p == NULL)
+ err(1, "strdup");
+ return p;
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: m4 [-EgPs] [-Dname[=value]] [-d flags] "
+ "[-I dirname] [-o filename]\n"
+ "\t[-t macro] [-Uname] [file ...]\n");
+ exit(1);
+}
+
+int
+obtain_char(struct input_file *f)
+{
+ if (f->c == EOF)
+ return EOF;
+
+ f->c = fgetc(f->file);
+ if (f->c == '\n')
+ f->lineno++;
+
+ return f->c;
+}
+
+void
+set_input(struct input_file *f, FILE *real, const char *name)
+{
+ f->file = real;
+ f->lineno = 1;
+ f->c = 0;
+ f->name = xstrdup(name);
+ emit_synchline();
+}
+
+void
+do_emit_synchline(void)
+{
+ fprintf(active, "#line %lu \"%s\"\n",
+ infile[ilevel].lineno, infile[ilevel].name);
+ infile[ilevel].synch_lineno = infile[ilevel].lineno;
+}
+
+void
+release_input(struct input_file *f)
+{
+ if (ferror(f->file))
+ errx(1, "Fatal error reading from %s\n", f->name);
+ if (f->file != stdin)
+ fclose(f->file);
+ f->c = EOF;
+ /*
+ * XXX can't free filename, as there might still be
+ * error information pointing to it.
+ */
+}
+
+void
+doprintlineno(struct input_file *f)
+{
+ pbunsigned(f->lineno);
+}
+
+void
+doprintfilename(struct input_file *f)
+{
+ pbstr(rquote);
+ pbstr(f->name);
+ pbstr(lquote);
+}
+
+/*
+ * buffer_mark/dump_buffer: allows one to save a mark in a buffer,
+ * and later dump everything that was added since then to a file.
+ */
+size_t
+buffer_mark(void)
+{
+ return bp - buf;
+}
+
+
+void
+dump_buffer(FILE *f, size_t m)
+{
+ unsigned char *s;
+
+ for (s = bp; s-buf > (long)m;)
+ fputc(*--s, f);
+}
diff --git a/usr.bin/m4/parser.y b/usr.bin/m4/parser.y
new file mode 100644
index 000000000000..90307e9f68ac
--- /dev/null
+++ b/usr.bin/m4/parser.y
@@ -0,0 +1,84 @@
+%{
+/* $OpenBSD: parser.y,v 1.7 2012/04/12 17:00:11 espie Exp $ */
+/*
+ * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <math.h>
+#include <stdint.h>
+#define YYSTYPE int32_t
+extern int32_t end_result;
+extern int yylex(void);
+extern int yyerror(const char *);
+%}
+%token NUMBER
+%token ERROR
+%left LOR
+%left LAND
+%left '|'
+%left '^'
+%left '&'
+%left EQ NE
+%left '<' LE '>' GE
+%left LSHIFT RSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right EXPONENT
+%right UMINUS UPLUS '!' '~'
+
+%%
+
+top : expr { end_result = $1; }
+ ;
+expr : expr '+' expr { $$ = $1 + $3; }
+ | expr '-' expr { $$ = $1 - $3; }
+ | expr EXPONENT expr { $$ = pow($1, $3); }
+ | expr '*' expr { $$ = $1 * $3; }
+ | expr '/' expr {
+ if ($3 == 0) {
+ yyerror("division by zero");
+ exit(1);
+ }
+ $$ = $1 / $3;
+ }
+ | expr '%' expr {
+ if ($3 == 0) {
+ yyerror("modulo zero");
+ exit(1);
+ }
+ $$ = $1 % $3;
+ }
+ | expr LSHIFT expr { $$ = $1 << $3; }
+ | expr RSHIFT expr { $$ = $1 >> $3; }
+ | expr '<' expr { $$ = $1 < $3; }
+ | expr '>' expr { $$ = $1 > $3; }
+ | expr LE expr { $$ = $1 <= $3; }
+ | expr GE expr { $$ = $1 >= $3; }
+ | expr EQ expr { $$ = $1 == $3; }
+ | expr NE expr { $$ = $1 != $3; }
+ | expr '&' expr { $$ = $1 & $3; }
+ | expr '^' expr { $$ = $1 ^ $3; }
+ | expr '|' expr { $$ = $1 | $3; }
+ | expr LAND expr { $$ = $1 && $3; }
+ | expr LOR expr { $$ = $1 || $3; }
+ | '(' expr ')' { $$ = $2; }
+ | '-' expr %prec UMINUS { $$ = -$2; }
+ | '+' expr %prec UPLUS { $$ = $2; }
+ | '!' expr { $$ = !$2; }
+ | '~' expr { $$ = ~$2; }
+ | NUMBER
+ ;
+%%
+
diff --git a/usr.bin/m4/pathnames.h b/usr.bin/m4/pathnames.h
new file mode 100644
index 000000000000..fa8d547f71be
--- /dev/null
+++ b/usr.bin/m4/pathnames.h
@@ -0,0 +1,38 @@
+/* $OpenBSD: pathnames.h,v 1.6 2015/11/03 16:21:47 deraadt Exp $ */
+/* $NetBSD: pathnames.h,v 1.6 1995/09/29 00:27:55 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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 _PATH_DIVNAME "/tmp/m4.0XXXXXXXXXX" /* unix diversion files */
diff --git a/usr.bin/m4/stdd.h b/usr.bin/m4/stdd.h
new file mode 100644
index 000000000000..377dcba7b41a
--- /dev/null
+++ b/usr.bin/m4/stdd.h
@@ -0,0 +1,55 @@
+/* $OpenBSD: stdd.h,v 1.6 2010/09/07 19:58:09 marco Exp $ */
+/* $NetBSD: stdd.h,v 1.2 1995/09/28 05:37:50 tls Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ozan Yigit at York University.
+ *
+ * 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.
+ */
+
+/*
+ * standard defines
+ */
+
+#define max(a,b) ((a) > (b)? (a): (b))
+#define min(a,b) ((a) < (b)? (a): (b))
+
+#define iswhite(c) ((c) == ' ' || (c) == '\t')
+
+/*
+ * STREQ is an optimised strcmp(a,b)==0
+ * STREQN is an optimised strncmp(a,b,n)==0; assumes n > 0
+ */
+#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
+#define STREQN(a, b, n) ((a)[0] == (b)[0] && strncmp(a, b, n) == 0)
+
+#define YES 1
+#define NO 0
diff --git a/usr.bin/m4/tests/Makefile b/usr.bin/m4/tests/Makefile
new file mode 100644
index 000000000000..45245d75e85d
--- /dev/null
+++ b/usr.bin/m4/tests/Makefile
@@ -0,0 +1,49 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= args.m4
+${PACKAGE}FILES+= args2.m4
+${PACKAGE}FILES+= comments.m4
+${PACKAGE}FILES+= esyscmd.m4
+${PACKAGE}FILES+= eval.m4
+${PACKAGE}FILES+= ff_after_dnl.m4.uu
+${PACKAGE}FILES+= gnueval.m4
+${PACKAGE}FILES+= gnuformat.m4
+${PACKAGE}FILES+= gnupatterns.m4
+${PACKAGE}FILES+= gnupatterns2.m4
+${PACKAGE}FILES+= gnuprefix.m4
+${PACKAGE}FILES+= gnusofterror.m4
+${PACKAGE}FILES+= includes.aux
+${PACKAGE}FILES+= includes.m4
+${PACKAGE}FILES+= m4wrap3.m4
+${PACKAGE}FILES+= patterns.m4
+${PACKAGE}FILES+= quotes.m4
+${PACKAGE}FILES+= redef.m4
+${PACKAGE}FILES+= regress.args.out
+${PACKAGE}FILES+= regress.args2.out
+${PACKAGE}FILES+= regress.comments.out
+${PACKAGE}FILES+= regress.esyscmd.out
+${PACKAGE}FILES+= regress.eval.out
+${PACKAGE}FILES+= regress.ff_after_dnl.out
+${PACKAGE}FILES+= regress.gnueval.out
+${PACKAGE}FILES+= regress.gnuformat.out
+${PACKAGE}FILES+= regress.gnupatterns.out
+${PACKAGE}FILES+= regress.gnupatterns2.out
+${PACKAGE}FILES+= regress.gnuprefix.out
+${PACKAGE}FILES+= regress.gnusofterror.out
+${PACKAGE}FILES+= regress.gnutranslit2.out
+${PACKAGE}FILES+= regress.includes.out
+${PACKAGE}FILES+= regress.m4wrap3.out
+${PACKAGE}FILES+= regress.patterns.out
+${PACKAGE}FILES+= regress.quotes.out
+${PACKAGE}FILES+= regress.redef.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.strangequotes.out
+${PACKAGE}FILES+= regress.translit.out
+${PACKAGE}FILES+= regress.translit2.out
+${PACKAGE}FILES+= strangequotes.m4.uu
+${PACKAGE}FILES+= translit.m4
+${PACKAGE}FILES+= translit2.m4
+
+.include <bsd.test.mk>
diff --git a/usr.bin/m4/tests/Makefile.depend b/usr.bin/m4/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/m4/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/m4/tests/args.m4 b/usr.bin/m4/tests/args.m4
new file mode 100644
index 000000000000..2be7c3fd51fc
--- /dev/null
+++ b/usr.bin/m4/tests/args.m4
@@ -0,0 +1,8 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/args.m4,v 1.1 2001/10/10 23:23:59 espie Exp $
+dnl Expanding all arguments
+define(`A', `first form: $@, second form $*')dnl
+define(`B', `C')dnl
+A(1,2,`B')
+dnl indirection means macro can get called with argc == 2 !
+indir(`A',1,2,`B')
+indir(`A')
diff --git a/usr.bin/m4/tests/args2.m4 b/usr.bin/m4/tests/args2.m4
new file mode 100644
index 000000000000..22f75a0e13af
--- /dev/null
+++ b/usr.bin/m4/tests/args2.m4
@@ -0,0 +1,4 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/args2.m4,v 1.1 2008/08/16 09:57:12 espie Exp $
+dnl Preserving spaces within nested parentheses
+define(`foo',`$1')dnl
+foo(( check for embedded spaces))
diff --git a/usr.bin/m4/tests/comments.m4 b/usr.bin/m4/tests/comments.m4
new file mode 100644
index 000000000000..e94165a19079
--- /dev/null
+++ b/usr.bin/m4/tests/comments.m4
@@ -0,0 +1,58 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/comments.m4,v 1.1 2005/09/06 15:33:21 espie Exp $
+dnl checking the way changecom works.
+1: normal
+define(`comment', `COMMENT')dnl
+define(`p', 'XXX')dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+2: `changecom(>>)dnl'
+changecom(>>)dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+3: `changecom dnl'
+changecom dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+4: `changecom()dnl'
+changecom()dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+5: `changecom(,)dnl'
+changecom(,)dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+6: `changecom(`p',q)dnl'
+changecom(`p',q)dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+7: `changecom(`p')dnl'
+changecom(`p')dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
+
+8: `changecom(#)dnl'
+changecom(#)dnl
+# this is a comment
+>> this is a comment
+p this is a comment
+p this is a comment q comment too
diff --git a/usr.bin/m4/tests/esyscmd.m4 b/usr.bin/m4/tests/esyscmd.m4
new file mode 100644
index 000000000000..a9b83c478e48
--- /dev/null
+++ b/usr.bin/m4/tests/esyscmd.m4
@@ -0,0 +1,42 @@
+changequote(`{',`}')dnl
+dnl
+esyscmd({sh -c "m4<<EOF
+define(_bp,hi there a)
+define(_comb,
+_bp($1$2)
+_bp($2$1)
+)
+define(bp,
+_comb(aaaa,foo0)
+_comb(bbbb,foo0)
+_comb(cccc,foo0)
+_comb(dddd,foo0)
+_comb(aaaa,foo0)
+_comb(bbbb,foo0)
+_comb(cccc,foo0)
+_comb(dddd,foo0)
+)
+bp(a00)
+bp(b00)
+bp(c00)
+bp(d00)
+bp(e00)
+bp(f00)
+bp(g00)
+bp(h00)
+bp(i00)
+bp(j00)
+bp(k00)
+bp(l00)
+bp(m00)
+bp(n00)
+bp(o00)
+bp(p00)
+bp(q00)
+bp(r00)
+bp(s00)
+bp(t00)
+bp(u00)
+bp(v00)
+bp(w00)
+EOF"})dnl
diff --git a/usr.bin/m4/tests/eval.m4 b/usr.bin/m4/tests/eval.m4
new file mode 100644
index 000000000000..1d3f886d0d89
--- /dev/null
+++ b/usr.bin/m4/tests/eval.m4
@@ -0,0 +1,5 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/eval.m4,v 1.1 2004/05/12 21:24:37 espie Exp $
+dnl expr parser
+eval(224&127)
+eval(224|127)
+eval(224&&127)
diff --git a/usr.bin/m4/tests/ff_after_dnl.m4.uu b/usr.bin/m4/tests/ff_after_dnl.m4.uu
new file mode 100644
index 000000000000..565090612757
--- /dev/null
+++ b/usr.bin/m4/tests/ff_after_dnl.m4.uu
@@ -0,0 +1,10 @@
+$OpenBSD: src/regress/usr.bin/m4/ff_after_dnl.m4.uu,v 1.1.1.1 2000/07/01 00:31:01 espie Exp $
+$NetBSD: ff_after_dnl.m4.uu,v 1.1 1997/12/30 23:30:53 cgd Exp $
+
+begin 644 ff_after_dnl.m4
+M"0E42$E3(%-(3U5,1"!32$]7(%50("A,24Y%(#$I"F1N;`D)5$A)4R!32$]5
+M3$0@3D]4(%-(3U<@55`@*$Q)3D4@,BD*9&YL_PD)5$A)4R!32$]53$0@3D]4
+M(%-(3U<@55`@*$Q)3D4@,RD*9&YL"?\)5$A)4R!32$]53$0@3D]4(%-(3U<@
+K55`@*$Q)3D4@-"D*"0E42$E3(%-(3U5,1"!32$]7(%50("A,24Y%(#4I"E<@
+`
+end
diff --git a/usr.bin/m4/tests/gnueval.m4 b/usr.bin/m4/tests/gnueval.m4
new file mode 100644
index 000000000000..c0911ac8aef2
--- /dev/null
+++ b/usr.bin/m4/tests/gnueval.m4
@@ -0,0 +1,6 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/gnueval.m4,v 1.1 2012/04/12 16:58:15 espie Exp $
+dnl exponentiation is right associative
+eval(`4**2**3')
+dnl priority between unary operators and *
+eval(`4**2*3')
+eval(`-4**3')
diff --git a/usr.bin/m4/tests/gnuformat.m4 b/usr.bin/m4/tests/gnuformat.m4
new file mode 100644
index 000000000000..b9cf8b7d92cc
--- /dev/null
+++ b/usr.bin/m4/tests/gnuformat.m4
@@ -0,0 +1 @@
+format(`a%15sa%%b%-15sbc%3scd%-3sd', `string', `pouet', `toolong', `toolong2')
diff --git a/usr.bin/m4/tests/gnupatterns.m4 b/usr.bin/m4/tests/gnupatterns.m4
new file mode 100644
index 000000000000..8670d1c44f41
--- /dev/null
+++ b/usr.bin/m4/tests/gnupatterns.m4
@@ -0,0 +1,3 @@
+patsubst(`string with a + to replace with a minus', `+', `minus')
+patsubst(`string with aaaaa to replace with a b', `a+', `b')
+patsubst(`+string with a starting + to replace with a minus', `^+', `minus')
diff --git a/usr.bin/m4/tests/gnupatterns2.m4 b/usr.bin/m4/tests/gnupatterns2.m4
new file mode 100644
index 000000000000..43de995db81e
--- /dev/null
+++ b/usr.bin/m4/tests/gnupatterns2.m4
@@ -0,0 +1,5 @@
+define(`zoinx',dnl
+`patsubst($1,\(\w+\)\(\W*\),\1 )')dnl
+zoinx(acosl asinl atanl \
+ cosl sinl tanl \
+ coshl sinhl tanhl)
diff --git a/usr.bin/m4/tests/gnuprefix.m4 b/usr.bin/m4/tests/gnuprefix.m4
new file mode 100644
index 000000000000..fff9784ed2cc
--- /dev/null
+++ b/usr.bin/m4/tests/gnuprefix.m4
@@ -0,0 +1,2 @@
+dumpdef()
+m4_dumpdef()
diff --git a/usr.bin/m4/tests/gnusofterror.m4 b/usr.bin/m4/tests/gnusofterror.m4
new file mode 100644
index 000000000000..5cf88ab3a149
--- /dev/null
+++ b/usr.bin/m4/tests/gnusofterror.m4
@@ -0,0 +1,3 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/gnusofterror.m4,v 1.1 2012/04/12 16:58:15 espie Exp $
+include(`hey I do not exit')dnl
+abc
diff --git a/usr.bin/m4/tests/includes.aux b/usr.bin/m4/tests/includes.aux
new file mode 100644
index 000000000000..efb8a692d100
--- /dev/null
+++ b/usr.bin/m4/tests/includes.aux
@@ -0,0 +1,2 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/includes.aux,v 1.1 2008/08/16 10:02:32 espie Exp $
+hello world dnl
diff --git a/usr.bin/m4/tests/includes.m4 b/usr.bin/m4/tests/includes.m4
new file mode 100644
index 000000000000..bd9c22dfbd07
--- /dev/null
+++ b/usr.bin/m4/tests/includes.m4
@@ -0,0 +1,4 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/includes.m4,v 1.1 2008/08/16 10:02:32 espie Exp $
+dnl Check that include can occur within parameters
+define(`foo', include(includes.aux))dnl
+foo
diff --git a/usr.bin/m4/tests/legacy_test.sh b/usr.bin/m4/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/m4/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/m4/tests/m4wrap3.m4 b/usr.bin/m4/tests/m4wrap3.m4
new file mode 100644
index 000000000000..bcfc788cb59d
--- /dev/null
+++ b/usr.bin/m4/tests/m4wrap3.m4
@@ -0,0 +1,11 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/m4wrap3.m4,v 1.1 2005/03/02 10:12:41 espie Exp $
+dnl Another test, this time for multiple wrappers
+dnl Check the behavior in presence of recursive m4wraps
+dnl both for POSIX m4 and for gnu-m4 mode
+m4wrap(`this is
+')dnl
+m4wrap(`a string
+')dnl
+m4wrap(`m4wrap(`recurse
+')')dnl
+normal m4 stuff
diff --git a/usr.bin/m4/tests/patterns.m4 b/usr.bin/m4/tests/patterns.m4
new file mode 100644
index 000000000000..48e63449815a
--- /dev/null
+++ b/usr.bin/m4/tests/patterns.m4
@@ -0,0 +1,11 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/patterns.m4,v 1.4 2003/06/08 20:11:45 espie Exp $
+patsubst(`quote s in string', `(s)', `\\\1')
+patsubst(`check whether subst
+over several lines
+works as expected', `^', `>>>')
+patsubst(`# This is a line to zap
+# and a second line
+keep this one', `^ *#.*
+')
+dnl Special case: empty regexp
+patsubst(`empty regexp',`',`a ')
diff --git a/usr.bin/m4/tests/quotes.m4 b/usr.bin/m4/tests/quotes.m4
new file mode 100644
index 000000000000..376cc1e42c0c
--- /dev/null
+++ b/usr.bin/m4/tests/quotes.m4
@@ -0,0 +1,57 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/quotes.m4,v 1.2 2005/09/06 15:33:21 espie Exp $
+dnl Checking the way changequote() is supposed to work
+define(`string',`STRING')dnl
+1: normal
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+2: kill quotes
+changequote()dnl
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+3: normal changed quote
+changequote([,])dnl
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+4: empty quotes, kill them too
+changequote(,)dnl
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+5: start quote only
+changequote(`)dnl
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+6: normal quotes are back
+changequote
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
+
+7: start quote+empty end quote
+changequote([,)dnl
+`quoted string'
+[quoted string]
+normal string
+`half quoted string
+going up to that string'
diff --git a/usr.bin/m4/tests/redef.m4 b/usr.bin/m4/tests/redef.m4
new file mode 100644
index 000000000000..4def2df15e21
--- /dev/null
+++ b/usr.bin/m4/tests/redef.m4
@@ -0,0 +1,16 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/redef.m4,v 1.2 2001/09/27 22:40:58 espie Exp $
+dnl check all properties of builtin are passed on, including args behavior
+define(`mybuiltin',defn(`builtin'))dnl
+builtin mybuiltin
+define(`mydefine',defn(`define'))dnl
+mydefine(`mydefn',defn(`defn'))dnl
+mydefine(`myundefine',mydefn(`undefine'))dnl
+myundefine(`defn')dnl
+myundefine(`define')dnl
+myundefine(`undefine')dnl
+mydefine(`mydef2',mydefn(`mydefine'))dnl
+mydefine(`mydef', mydefn(`define'))dnl
+myundefine(`mydefine')dnl
+mydef2(`A',`B')dnl
+mydef(`C',`D')dnl
+A C
diff --git a/usr.bin/m4/tests/regress.args.out b/usr.bin/m4/tests/regress.args.out
new file mode 100644
index 000000000000..aaa890010a59
--- /dev/null
+++ b/usr.bin/m4/tests/regress.args.out
@@ -0,0 +1,3 @@
+first form: 1,2,B, second form 1,2,C
+first form: 1,2,B, second form 1,2,C
+first form: , second form
diff --git a/usr.bin/m4/tests/regress.args2.out b/usr.bin/m4/tests/regress.args2.out
new file mode 100644
index 000000000000..74bdbd6e5958
--- /dev/null
+++ b/usr.bin/m4/tests/regress.args2.out
@@ -0,0 +1 @@
+( check for embedded spaces)
diff --git a/usr.bin/m4/tests/regress.comments.out b/usr.bin/m4/tests/regress.comments.out
new file mode 100644
index 000000000000..157f107a8a22
--- /dev/null
+++ b/usr.bin/m4/tests/regress.comments.out
@@ -0,0 +1,47 @@
+1: normal
+# this is a comment
+>> this is a COMMENT
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
+
+2: changecom(>>)dnl
+# this is a COMMENT
+>> this is a comment
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
+
+3: changecom dnl
+ # this is a COMMENT
+>> this is a COMMENT
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
+
+4: changecom()dnl
+# this is a COMMENT
+>> this is a COMMENT
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
+
+5: changecom(,)dnl
+# this is a COMMENT
+>> this is a COMMENT
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
+
+6: changecom(`p',q)dnl
+# this is a COMMENT
+>> this is a COMMENT
+p this is a comment
+p this is a comment q COMMENT too
+
+7: changecom(`p')dnl
+# this is a COMMENT
+>> this is a COMMENT
+p this is a comment
+p this is a comment q comment too
+
+8: changecom(#)dnl
+# this is a comment
+>> this is a COMMENT
+'XXX' this is a COMMENT
+'XXX' this is a COMMENT q COMMENT too
diff --git a/usr.bin/m4/tests/regress.esyscmd.out b/usr.bin/m4/tests/regress.esyscmd.out
new file mode 100644
index 000000000000..89a1d06578a2
--- /dev/null
+++ b/usr.bin/m4/tests/regress.esyscmd.out
@@ -0,0 +1,578 @@
+
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+hi there a
+hi there a
+
+
diff --git a/usr.bin/m4/tests/regress.eval.out b/usr.bin/m4/tests/regress.eval.out
new file mode 100644
index 000000000000..7298b3f43840
--- /dev/null
+++ b/usr.bin/m4/tests/regress.eval.out
@@ -0,0 +1,3 @@
+96
+255
+1
diff --git a/usr.bin/m4/tests/regress.ff_after_dnl.out b/usr.bin/m4/tests/regress.ff_after_dnl.out
new file mode 100644
index 000000000000..8e51f1ea05c5
--- /dev/null
+++ b/usr.bin/m4/tests/regress.ff_after_dnl.out
@@ -0,0 +1,2 @@
+ THIS SHOULD SHOW UP (LINE 1)
+ THIS SHOULD SHOW UP (LINE 5)
diff --git a/usr.bin/m4/tests/regress.gnueval.out b/usr.bin/m4/tests/regress.gnueval.out
new file mode 100644
index 000000000000..6d7fd49ca21b
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnueval.out
@@ -0,0 +1,3 @@
+65536
+48
+-64
diff --git a/usr.bin/m4/tests/regress.gnuformat.out b/usr.bin/m4/tests/regress.gnuformat.out
new file mode 100644
index 000000000000..3f484d61d4d9
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnuformat.out
@@ -0,0 +1 @@
+a stringa%bpouet bctoolongcdtoolong2d
diff --git a/usr.bin/m4/tests/regress.gnupatterns.out b/usr.bin/m4/tests/regress.gnupatterns.out
new file mode 100644
index 000000000000..8e3110301932
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnupatterns.out
@@ -0,0 +1,3 @@
+string with a minus to replace with a minus
+string with b to replbce with b b
+minusstring with a starting + to replace with a minus
diff --git a/usr.bin/m4/tests/regress.gnupatterns2.out b/usr.bin/m4/tests/regress.gnupatterns2.out
new file mode 100644
index 000000000000..c45944ab60a1
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnupatterns2.out
@@ -0,0 +1 @@
+acosl asinl atanl cosl sinl tanl coshl sinhl tanhl
diff --git a/usr.bin/m4/tests/regress.gnuprefix.out b/usr.bin/m4/tests/regress.gnuprefix.out
new file mode 100644
index 000000000000..186421d8650b
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnuprefix.out
@@ -0,0 +1,46 @@
+`m4_ifelse' `m4_ifelse'
+`m4_dnl' `m4_dnl'
+`m4_expr' `m4_expr'
+`m4_builtin' `m4_builtin'
+`m4_popdef' `m4_popdef'
+`m4_eval' `m4_eval'
+`m4_len' `m4_len'
+`m4_indir' `m4_indir'
+`m4_sinclude' `m4_sinclude'
+`m4_index' `m4_index'
+`m4_traceoff' `m4_traceoff'
+`m4___file__' `m4___file__'
+`m4_unix' `m4_unix'
+`m4_mkstemp' `m4_mkstemp'
+`m4_changecom' `m4_changecom'
+`m4_defn' `m4_defn'
+`m4_decr' `m4_decr'
+`m4_translit' `m4_translit'
+`m4_patsubst' `m4_patsubst'
+`m4_dumpdef' `m4_dumpdef'
+`m4___line__' `m4___line__'
+`m4_esyscmd' `m4_esyscmd'
+`m4_traceon' `m4_traceon'
+`m4_incr' `m4_incr'
+`m4_shift' `m4_shift'
+`m4_syscmd' `m4_syscmd'
+`m4_include' `m4_include'
+`m4_pushdef' `m4_pushdef'
+`m4_paste' `m4_paste'
+`m4_regexp' `m4_regexp'
+`m4_changequote' `m4_changequote'
+`m4_undivert' `m4_undivert'
+`m4_m4exit' `m4_m4exit'
+`m4_substr' `m4_substr'
+`m4_m4wrap' `m4_m4wrap'
+`m4_ifdef' `m4_ifdef'
+`m4_sysval' `m4_sysval'
+`m4_divert' `m4_divert'
+`m4_maketemp' `m4_maketemp'
+`m4_spaste' `m4_spaste'
+`m4_define' `m4_define'
+`m4_undefine' `m4_undefine'
+`m4_divnum' `m4_divnum'
+`m4_errprint' `m4_errprint'
+dumpdef()
+
diff --git a/usr.bin/m4/tests/regress.gnusofterror.out b/usr.bin/m4/tests/regress.gnusofterror.out
new file mode 100644
index 000000000000..5c23eb237b6c
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnusofterror.out
@@ -0,0 +1,2 @@
+m4: gnusofterror.m4 at line 2: include(hey I do not exit): No such file or directory
+abc
diff --git a/usr.bin/m4/tests/regress.gnutranslit2.out b/usr.bin/m4/tests/regress.gnutranslit2.out
new file mode 100644
index 000000000000..5c88e734a07d
--- /dev/null
+++ b/usr.bin/m4/tests/regress.gnutranslit2.out
@@ -0,0 +1,6 @@
+[HAVE_abc def h/]
+[HAVE_abc~def~h/]
+ABCDEFGHIJ
+ABCDEFGHIJ
+ABC-0980-ZYX
+ABC-0980-ZYX
diff --git a/usr.bin/m4/tests/regress.includes.out b/usr.bin/m4/tests/regress.includes.out
new file mode 100644
index 000000000000..4a1f4754cfdd
--- /dev/null
+++ b/usr.bin/m4/tests/regress.includes.out
@@ -0,0 +1 @@
+hello world
diff --git a/usr.bin/m4/tests/regress.m4wrap3.out b/usr.bin/m4/tests/regress.m4wrap3.out
new file mode 100644
index 000000000000..51b43f42d14e
--- /dev/null
+++ b/usr.bin/m4/tests/regress.m4wrap3.out
@@ -0,0 +1,4 @@
+normal m4 stuff
+this is
+a string
+recurse
diff --git a/usr.bin/m4/tests/regress.patterns.out b/usr.bin/m4/tests/regress.patterns.out
new file mode 100644
index 000000000000..c273b589d772
--- /dev/null
+++ b/usr.bin/m4/tests/regress.patterns.out
@@ -0,0 +1,6 @@
+quote \s in \string
+>>>check whether subst
+>>>over several lines
+>>>works as expected
+keep this one
+a ea ma pa ta ya a ra ea ga ea xa p
diff --git a/usr.bin/m4/tests/regress.quotes.out b/usr.bin/m4/tests/regress.quotes.out
new file mode 100644
index 000000000000..cf34ba42a8d0
--- /dev/null
+++ b/usr.bin/m4/tests/regress.quotes.out
@@ -0,0 +1,49 @@
+m4: unclosed quote:
+ quotes.m4 at line 54
+1: normal
+quoted string
+[quoted STRING]
+normal STRING
+half quoted string
+going up to that string
+
+2: kill quotes
+`quoted STRING'
+[quoted STRING]
+normal STRING
+`half quoted STRING
+going up to that STRING'
+
+3: normal changed quote
+`quoted STRING'
+quoted string
+normal STRING
+`half quoted STRING
+going up to that STRING'
+
+4: empty quotes, kill them too
+`quoted STRING'
+[quoted STRING]
+normal STRING
+`half quoted STRING
+going up to that STRING'
+
+5: start quote only
+quoted string'[quoted STRING]
+normal STRING
+half quoted stringgoing up to that STRING'
+
+6: normal quotes are back
+
+quoted string
+[quoted STRING]
+normal STRING
+half quoted string
+going up to that string
+
+7: start quote+empty end quote
+`quoted STRING'
+quoted string]
+normal string
+`half quoted string
+going up to that string'
diff --git a/usr.bin/m4/tests/regress.redef.out b/usr.bin/m4/tests/regress.redef.out
new file mode 100644
index 000000000000..ee482f013a86
--- /dev/null
+++ b/usr.bin/m4/tests/regress.redef.out
@@ -0,0 +1,2 @@
+builtin mybuiltin
+B C
diff --git a/usr.bin/m4/tests/regress.sh b/usr.bin/m4/tests/regress.sh
new file mode 100644
index 000000000000..39c9103db8d9
--- /dev/null
+++ b/usr.bin/m4/tests/regress.sh
@@ -0,0 +1,32 @@
+
+echo 1..21
+
+test_m4() {
+ m4 "${@}" 2>&1 | sed -e "s,${SRCDIR}/,,g"
+}
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`args', `test_m4 ${SRCDIR}/args.m4')
+REGRESSION_TEST(`args2', `test_m4 ${SRCDIR}/args2.m4')
+REGRESSION_TEST(`comments', `test_m4 ${SRCDIR}/comments.m4')
+REGRESSION_TEST(`esyscmd', `test_m4 ${SRCDIR}/esyscmd.m4')
+REGRESSION_TEST(`eval', `test_m4 ${SRCDIR}/eval.m4')
+REGRESSION_TEST(`ff_after_dnl', `uudecode -o /dev/stdout ${SRCDIR}/ff_after_dnl.m4.uu | m4')
+REGRESSION_TEST(`gnueval', `test_m4 -g ${SRCDIR}/gnueval.m4')
+REGRESSION_TEST(`gnuformat', `test_m4 -g ${SRCDIR}/gnuformat.m4')
+REGRESSION_TEST(`gnupatterns', `test_m4 -g ${SRCDIR}/gnupatterns.m4')
+REGRESSION_TEST(`gnupatterns2', `test_m4 -g ${SRCDIR}/gnupatterns2.m4')
+REGRESSION_TEST(`gnuprefix', `test_m4 -P ${SRCDIR}/gnuprefix.m4 2>&1')
+REGRESSION_TEST(`gnusofterror', `test_m4 -g ${SRCDIR}/gnusofterror.m4 2>&1')
+REGRESSION_TEST(`gnutranslit2', `test_m4 -g ${SRCDIR}/translit2.m4')
+REGRESSION_TEST(`includes', `test_m4 -I${SRCDIR} ${SRCDIR}/includes.m4')
+REGRESSION_TEST(`m4wrap3', `test_m4 ${SRCDIR}/m4wrap3.m4')
+REGRESSION_TEST(`patterns', `test_m4 ${SRCDIR}/patterns.m4')
+REGRESSION_TEST(`quotes', `test_m4 ${SRCDIR}/quotes.m4 2>&1')
+REGRESSION_TEST(`strangequotes', `uudecode -o /dev/stdout ${SRCDIR}/strangequotes.m4.uu | m4')
+REGRESSION_TEST(`redef', `test_m4 ${SRCDIR}/redef.m4')
+REGRESSION_TEST(`translit', `test_m4 ${SRCDIR}/translit.m4')
+REGRESSION_TEST(`translit2', `test_m4 ${SRCDIR}/translit2.m4')
+
+REGRESSION_END()
diff --git a/usr.bin/m4/tests/regress.strangequotes.out b/usr.bin/m4/tests/regress.strangequotes.out
new file mode 100644
index 000000000000..f19297b58296
--- /dev/null
+++ b/usr.bin/m4/tests/regress.strangequotes.out
@@ -0,0 +1 @@
+4 to 5
diff --git a/usr.bin/m4/tests/regress.translit.out b/usr.bin/m4/tests/regress.translit.out
new file mode 100644
index 000000000000..54abdd3a6d0b
--- /dev/null
+++ b/usr.bin/m4/tests/regress.translit.out
@@ -0,0 +1 @@
+onkp
diff --git a/usr.bin/m4/tests/regress.translit2.out b/usr.bin/m4/tests/regress.translit2.out
new file mode 100644
index 000000000000..5c561770fa4d
--- /dev/null
+++ b/usr.bin/m4/tests/regress.translit2.out
@@ -0,0 +1,6 @@
+[HAVE_abc def h/]
+[HAVE_abc~def~h/]
+ABCDEFGHIJ
+A12345678J
+ABC-0980-ZYX
+Abc-0980-Zyx
diff --git a/usr.bin/m4/tests/strangequotes.m4.uu b/usr.bin/m4/tests/strangequotes.m4.uu
new file mode 100644
index 000000000000..43c3e3e53446
--- /dev/null
+++ b/usr.bin/m4/tests/strangequotes.m4.uu
@@ -0,0 +1,7 @@
+$OpenBSD: src/regress/usr.bin/m4/strangequotes.m4.uu,v 1.2 2001/09/19 19:15:08 espie Exp $
+
+begin 644 strangequotes.m4
+M8VAA;F=E<75O=&4HJRR[*61N;`ID969I;F4HJT&[+""K)#$@=&\@)#*[*61N
+*;`I!*#0L(#4I"F4H
+`
+end
diff --git a/usr.bin/m4/tests/translit.m4 b/usr.bin/m4/tests/translit.m4
new file mode 100644
index 000000000000..77b4fe0f1934
--- /dev/null
+++ b/usr.bin/m4/tests/translit.m4
@@ -0,0 +1,3 @@
+dnl $OpenBSD: src/regress/usr.bin/m4/translit.m4,v 1.1 2010/03/23 20:11:52 espie Exp $
+dnl first one should match, not second one
+translit(`onk*', `**', `p_')
diff --git a/usr.bin/m4/tests/translit2.m4 b/usr.bin/m4/tests/translit2.m4
new file mode 100644
index 000000000000..5c53a57cf3c2
--- /dev/null
+++ b/usr.bin/m4/tests/translit2.m4
@@ -0,0 +1,8 @@
+translit(`[HAVE_abc/def.h
+]', `
+/.', `/ ')
+translit(`[HAVE_abc/def.h=]', `=/.', `/~~')
+translit(`0123456789', `0123456789', `ABCDEFGHIJ')
+translit(`0123456789', `[0-9]', `[A-J]')
+translit(`abc-0980-zyx', `abcdefghijklmnopqrstuvwxyz', `ABCDEFGHIJKLMNOPQRSTUVWXYZ')
+translit(`abc-0980-zyx', `[a-z]', `[A-Z]')
diff --git a/usr.bin/m4/tokenizer.l b/usr.bin/m4/tokenizer.l
new file mode 100644
index 000000000000..b7339a7562cc
--- /dev/null
+++ b/usr.bin/m4/tokenizer.l
@@ -0,0 +1,114 @@
+%option nounput noinput
+%{
+/* $OpenBSD: tokenizer.l,v 1.9 2017/06/15 13:48:42 bcallah Exp $ */
+/*
+ * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "parser.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdint.h>
+#include <limits.h>
+
+extern void m4_warnx(const char *, ...);
+extern int mimic_gnu;
+extern int32_t yylval;
+
+int32_t number(void);
+int32_t parse_radix(void);
+extern int yylex(void);
+
+#define YY_DECL int yylex(void)
+%}
+
+delim [ \t\n]
+ws {delim}+
+hex 0[xX][0-9a-fA-F]+
+oct 0[0-7]*
+dec [1-9][0-9]*
+radix 0[rR][0-9]+:[0-9a-zA-Z]+
+
+%option noyywrap
+
+%%
+{ws} {/* just skip it */}
+{hex}|{oct}|{dec} { yylval = number(); return(NUMBER); }
+{radix} { if (mimic_gnu) {
+ yylval = parse_radix(); return(NUMBER);
+ } else {
+ return(ERROR);
+ }
+ }
+"<=" { return(LE); }
+">=" { return(GE); }
+"<<" { return(LSHIFT); }
+">>" { return(RSHIFT); }
+"==" { return(EQ); }
+"!=" { return(NE); }
+"&&" { return(LAND); }
+"||" { return(LOR); }
+"**" { if (mimic_gnu) { return (EXPONENT); } }
+. { return yytext[0]; }
+%%
+
+int32_t
+number(void)
+{
+ long l;
+
+ errno = 0;
+ l = strtol(yytext, NULL, 0);
+ if (((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) ||
+ l > INT32_MAX || l < INT32_MIN) {
+ m4_warnx("numeric overflow in expr: %s", yytext);
+ }
+ return l;
+}
+
+int32_t
+parse_radix(void)
+{
+ long base;
+ char *next;
+ long l;
+ int d;
+
+ l = 0;
+ base = strtol(yytext+2, &next, 0);
+ if (base > 36 || next == NULL) {
+ m4_warnx("error in number %s", yytext);
+ } else {
+ next++;
+ while (*next != 0) {
+ if (*next >= '0' && *next <= '9')
+ d = *next - '0';
+ else if (*next >= 'a' && *next <= 'z')
+ d = *next - 'a' + 10;
+ else {
+ assert(*next >= 'A' && *next <= 'Z');
+ d = *next - 'A' + 10;
+ }
+ if (d >= base) {
+ m4_warnx("error in number %s", yytext);
+ return 0;
+ }
+ l = base * l + d;
+ next++;
+ }
+ }
+ return l;
+}
+
diff --git a/usr.bin/m4/trace.c b/usr.bin/m4/trace.c
new file mode 100644
index 000000000000..fe84c5ee405f
--- /dev/null
+++ b/usr.bin/m4/trace.c
@@ -0,0 +1,198 @@
+/* $OpenBSD: trace.c,v 1.16 2010/09/07 19:58:09 marco Exp $ */
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2001 Marc Espie.
+ *
+ * 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 OPENBSD PROJECT 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 OPENBSD
+ * PROJECT 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/cdefs.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mdef.h"
+#include "stdd.h"
+#include "extern.h"
+
+FILE *traceout;
+
+#define TRACE_ARGS 1
+#define TRACE_EXPANSION 2
+#define TRACE_QUOTE 4
+#define TRACE_FILENAME 8
+#define TRACE_LINENO 16
+#define TRACE_CONT 32
+#define TRACE_ID 64
+#define TRACE_NEWFILE 128 /* not implemented yet */
+#define TRACE_INPUT 256 /* not implemented yet */
+
+static unsigned int letter_to_flag(int);
+static void print_header(struct input_file *);
+static int frame_level(void);
+
+
+unsigned int trace_flags = TRACE_QUOTE | TRACE_EXPANSION;
+
+void
+trace_file(const char *name)
+{
+
+ if (traceout && traceout != stderr)
+ fclose(traceout);
+ traceout = fopen(name, "w");
+ if (!traceout)
+ err(1, "can't open %s", name);
+}
+
+static unsigned int
+letter_to_flag(int c)
+{
+ switch(c) {
+ case 'a':
+ return TRACE_ARGS;
+ case 'e':
+ return TRACE_EXPANSION;
+ case 'q':
+ return TRACE_QUOTE;
+ case 'c':
+ return TRACE_CONT;
+ case 'x':
+ return TRACE_ID;
+ case 'f':
+ return TRACE_FILENAME;
+ case 'l':
+ return TRACE_LINENO;
+ case 'p':
+ return TRACE_NEWFILE;
+ case 'i':
+ return TRACE_INPUT;
+ case 't':
+ return TRACE_ALL;
+ case 'V':
+ return ~0;
+ default:
+ return 0;
+ }
+}
+
+void
+set_trace_flags(const char *s)
+{
+ char mode = 0;
+ unsigned int f = 0;
+
+ if (*s == '+' || *s == '-')
+ mode = *s++;
+ while (*s)
+ f |= letter_to_flag(*s++);
+ switch(mode) {
+ case 0:
+ trace_flags = f;
+ break;
+ case '+':
+ trace_flags |= f;
+ break;
+ case '-':
+ trace_flags &= ~f;
+ break;
+ }
+}
+
+static int
+frame_level(void)
+{
+ int level;
+ int framep;
+
+ for (framep = fp, level = 0; framep != 0;
+ level++,framep = mstack[framep-3].sfra)
+ ;
+ return level;
+}
+
+static void
+print_header(struct input_file *inp)
+{
+ fprintf(traceout, "m4trace:");
+ if (trace_flags & TRACE_FILENAME)
+ fprintf(traceout, "%s:", inp->name);
+ if (trace_flags & TRACE_LINENO)
+ fprintf(traceout, "%lu:", inp->lineno);
+ fprintf(traceout, " -%d- ", frame_level());
+ if (trace_flags & TRACE_ID)
+ fprintf(traceout, "id %lu: ", expansion_id);
+}
+
+size_t
+trace(const char *argv[], int argc, struct input_file *inp)
+{
+ if (!traceout)
+ traceout = stderr;
+ print_header(inp);
+ if (trace_flags & TRACE_CONT) {
+ fprintf(traceout, "%s ...\n", argv[1]);
+ print_header(inp);
+ }
+ fprintf(traceout, "%s", argv[1]);
+ if ((trace_flags & TRACE_ARGS) && argc > 2) {
+ char delim[3];
+ int i;
+
+ delim[0] = LPAREN;
+ delim[1] = EOS;
+ for (i = 2; i < argc; i++) {
+ fprintf(traceout, "%s%s%s%s", delim,
+ (trace_flags & TRACE_QUOTE) ? lquote : "",
+ argv[i],
+ (trace_flags & TRACE_QUOTE) ? rquote : "");
+ delim[0] = COMMA;
+ delim[1] = ' ';
+ delim[2] = EOS;
+ }
+ fprintf(traceout, "%c", RPAREN);
+ }
+ if (trace_flags & TRACE_CONT) {
+ fprintf(traceout, " -> ???\n");
+ print_header(inp);
+ fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]);
+ }
+ if (trace_flags & TRACE_EXPANSION)
+ return buffer_mark();
+ else {
+ fprintf(traceout, "\n");
+ return SIZE_MAX;
+ }
+}
+
+void
+finish_trace(size_t mark)
+{
+ fprintf(traceout, " -> ");
+ if (trace_flags & TRACE_QUOTE)
+ fprintf(traceout, "%s", lquote);
+ dump_buffer(traceout, mark);
+ if (trace_flags & TRACE_QUOTE)
+ fprintf(traceout, "%s", rquote);
+ fprintf(traceout, "\n");
+}
diff --git a/usr.bin/mail/Makefile b/usr.bin/mail/Makefile
new file mode 100644
index 000000000000..c20060d88ebf
--- /dev/null
+++ b/usr.bin/mail/Makefile
@@ -0,0 +1,20 @@
+CONFS= misc/mail.rc
+PROG= mail
+SRCS= version.c cmd1.c cmd2.c cmd3.c cmdtab.c collect.c edit.c fio.c \
+ getname.c head.c v7.local.c lex.c list.c main.c names.c popen.c \
+ quit.c send.c strings.c temp.c tty.c util.c vars.c
+FILES= mail.help mail.tildehelp
+FILESDIR= ${SHAREDIR}/misc
+EFILES= mail.rc
+LINKS= ${BINDIR}/mail ${BINDIR}/Mail ${BINDIR}/mail ${BINDIR}/mailx
+MLINKS= mail.1 Mail.1 mail.1 mailx.1
+
+WARNS?= 2
+
+.PATH: ${.CURDIR}/misc
+
+etc-mailrc:
+ cd ${.CURDIR}/misc; ${INSTALL} -o root -g wheel \
+ -m 644 ${EFILES} ${DESTDIR}/etc
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mail/Makefile.depend b/usr.bin/mail/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/mail/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mail/cmd1.c b/usr.bin/mail/cmd1.c
new file mode 100644
index 000000000000..8ea361efab93
--- /dev/null
+++ b/usr.bin/mail/cmd1.c
@@ -0,0 +1,469 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * User commands.
+ */
+
+/*
+ * Print the current active headings.
+ * Don't change dot if invoker didn't give an argument.
+ */
+
+static int screen;
+
+int
+headers(void *v)
+{
+ int *msgvec = v;
+ int n, mesg, flag, size;
+ struct message *mp;
+
+ size = screensize();
+ n = msgvec[0];
+ if (n != 0)
+ screen = (n-1)/size;
+ if (screen < 0)
+ screen = 0;
+ mp = &message[screen * size];
+ if (mp >= &message[msgCount])
+ mp = &message[msgCount - size];
+ if (mp < &message[0])
+ mp = &message[0];
+ flag = 0;
+ mesg = mp - &message[0];
+ if (dot != &message[n-1])
+ dot = mp;
+ for (; mp < &message[msgCount]; mp++) {
+ mesg++;
+ if (mp->m_flag & MDELETED)
+ continue;
+ if (flag++ >= size)
+ break;
+ printhead(mesg);
+ }
+ if (flag == 0) {
+ printf("No more mail.\n");
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Scroll to the next/previous screen
+ */
+int
+scroll(void *v)
+{
+ char *arg = v;
+ int s, size;
+ int cur[1];
+
+ cur[0] = 0;
+ size = screensize();
+ s = screen;
+ switch (*arg) {
+ case 0:
+ case '+':
+ s++;
+ if (s * size >= msgCount) {
+ printf("On last screenful of messages\n");
+ return (0);
+ }
+ screen = s;
+ break;
+
+ case '-':
+ if (--s < 0) {
+ printf("On first screenful of messages\n");
+ return (0);
+ }
+ screen = s;
+ break;
+
+ default:
+ printf("Unrecognized scrolling command \"%s\"\n", arg);
+ return (1);
+ }
+ return (headers(cur));
+}
+
+/*
+ * Compute screen size.
+ */
+int
+screensize(void)
+{
+ int s;
+ char *cp;
+
+ if ((cp = value("screen")) != NULL && (s = atoi(cp)) > 0)
+ return (s);
+ return (screenheight - 4);
+}
+
+/*
+ * Print out the headlines for each message
+ * in the passed message list.
+ */
+int
+from(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+
+ for (ip = msgvec; *ip != 0; ip++)
+ printhead(*ip);
+ if (--ip >= msgvec)
+ dot = &message[*ip - 1];
+ return (0);
+}
+
+/*
+ * Print out the header of a specific message.
+ * This is a slight improvement to the standard one.
+ */
+void
+printhead(int mesg)
+{
+ struct message *mp;
+ char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
+ char pbuf[BUFSIZ];
+ struct headline hl;
+ int subjlen;
+ char *name;
+
+ mp = &message[mesg-1];
+ (void)readline(setinput(mp), headline, LINESIZE);
+ if ((subjline = hfield("subject", mp)) == NULL)
+ subjline = hfield("subj", mp);
+ /*
+ * Bletch!
+ */
+ curind = dot == mp ? '>' : ' ';
+ dispc = ' ';
+ if (mp->m_flag & MSAVED)
+ dispc = '*';
+ if (mp->m_flag & MPRESERVE)
+ dispc = 'P';
+ if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
+ dispc = 'N';
+ if ((mp->m_flag & (MREAD|MNEW)) == 0)
+ dispc = 'U';
+ if (mp->m_flag & MBOX)
+ dispc = 'M';
+ parse(headline, &hl, pbuf);
+ sprintf(wcount, "%3ld/%-5ld", mp->m_lines, mp->m_size);
+ subjlen = screenwidth - 50 - strlen(wcount);
+ name = value("show-rcpt") != NULL ?
+ skin(hfield("to", mp)) : nameof(mp, 0);
+ if (subjline == NULL || subjlen < 0) /* pretty pathetic */
+ printf("%c%c%3d %-20.20s %16.16s %s\n",
+ curind, dispc, mesg, name, hl.l_date, wcount);
+ else
+ printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n",
+ curind, dispc, mesg, name, hl.l_date, wcount,
+ subjlen, subjline);
+}
+
+/*
+ * Print out the value of dot.
+ */
+int
+pdot(void *arg __unused)
+{
+ printf("%td\n", dot - &message[0] + 1);
+ return (0);
+}
+
+/*
+ * Print out all the possible commands.
+ */
+int
+pcmdlist(void *arg __unused)
+{
+ extern const struct cmd cmdtab[];
+ const struct cmd *cp;
+ int cc;
+
+ printf("Commands are:\n");
+ for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) {
+ cc += strlen(cp->c_name) + 2;
+ if (cc > 72) {
+ printf("\n");
+ cc = strlen(cp->c_name) + 2;
+ }
+ if ((cp+1)->c_name != NULL)
+ printf("%s, ", cp->c_name);
+ else
+ printf("%s\n", cp->c_name);
+ }
+ return (0);
+}
+
+/*
+ * Paginate messages, honor ignored fields.
+ */
+int
+more(void *v)
+{
+ int *msgvec = v;
+
+ return (type1(msgvec, 1, 1));
+}
+
+/*
+ * Paginate messages, even printing ignored fields.
+ */
+int
+More(void *v)
+{
+ int *msgvec = v;
+
+ return (type1(msgvec, 0, 1));
+}
+
+/*
+ * Type out messages, honor ignored fields.
+ */
+int
+type(void *v)
+{
+ int *msgvec = v;
+
+ return (type1(msgvec, 1, 0));
+}
+
+/*
+ * Type out messages, even printing ignored fields.
+ */
+int
+Type(void *v)
+{
+ int *msgvec = v;
+
+ return (type1(msgvec, 0, 0));
+}
+
+/*
+ * Type out the messages requested.
+ */
+static jmp_buf pipestop;
+int
+type1(int *msgvec, int doign, int page)
+{
+ int nlines, *ip;
+ struct message *mp;
+ char *cp;
+ FILE *obuf;
+
+ obuf = stdout;
+ if (setjmp(pipestop))
+ goto close_pipe;
+ if (value("interactive") != NULL &&
+ (page || (cp = value("crt")) != NULL)) {
+ nlines = 0;
+ if (!page) {
+ for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++)
+ nlines += message[*ip - 1].m_lines;
+ }
+ if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) {
+ cp = value("PAGER");
+ if (cp == NULL || *cp == '\0')
+ cp = _PATH_LESS;
+ obuf = Popen(cp, "w");
+ if (obuf == NULL) {
+ warnx("%s", cp);
+ obuf = stdout;
+ } else
+ (void)signal(SIGPIPE, brokpipe);
+ }
+ }
+
+ /*
+ * Send messages to the output.
+ *
+ */
+ for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) {
+ mp = &message[*ip - 1];
+ touch(mp);
+ dot = mp;
+ if (value("quiet") == NULL)
+ fprintf(obuf, "Message %d:\n", *ip);
+ (void)sendmessage(mp, obuf, doign ? ignore : 0, NULL);
+ }
+
+close_pipe:
+ if (obuf != stdout) {
+ /*
+ * Ignore SIGPIPE so it can't cause a duplicate close.
+ */
+ (void)signal(SIGPIPE, SIG_IGN);
+ (void)Pclose(obuf);
+ (void)signal(SIGPIPE, SIG_DFL);
+ }
+ return (0);
+}
+
+/*
+ * Respond to a broken pipe signal --
+ * probably caused by quitting more.
+ */
+/*ARGSUSED*/
+void
+brokpipe(int signo __unused)
+{
+ longjmp(pipestop, 1);
+}
+
+/*
+ * Print the top so many lines of each desired message.
+ * The number of lines is taken from the variable "toplines"
+ * and defaults to 5.
+ */
+int
+top(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+ struct message *mp;
+ int c, topl, lines, lineb;
+ char *valtop, linebuf[LINESIZE];
+ FILE *ibuf;
+
+ topl = 5;
+ valtop = value("toplines");
+ if (valtop != NULL) {
+ topl = atoi(valtop);
+ if (topl < 0 || topl > 10000)
+ topl = 5;
+ }
+ lineb = 1;
+ for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
+ mp = &message[*ip - 1];
+ touch(mp);
+ dot = mp;
+ if (value("quiet") == NULL)
+ printf("Message %d:\n", *ip);
+ ibuf = setinput(mp);
+ c = mp->m_lines;
+ if (!lineb)
+ printf("\n");
+ for (lines = 0; lines < c && lines <= topl; lines++) {
+ if (readline(ibuf, linebuf, sizeof(linebuf)) < 0)
+ break;
+ puts(linebuf);
+ lineb = strspn(linebuf, " \t") == strlen(linebuf);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Touch all the given messages so that they will
+ * get mboxed.
+ */
+int
+stouch(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+
+ for (ip = msgvec; *ip != 0; ip++) {
+ dot = &message[*ip-1];
+ dot->m_flag |= MTOUCH;
+ dot->m_flag &= ~MPRESERVE;
+ }
+ return (0);
+}
+
+/*
+ * Make sure all passed messages get mboxed.
+ */
+int
+mboxit(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+
+ for (ip = msgvec; *ip != 0; ip++) {
+ dot = &message[*ip-1];
+ dot->m_flag |= MTOUCH|MBOX;
+ dot->m_flag &= ~MPRESERVE;
+ }
+ return (0);
+}
+
+/*
+ * List the folders the user currently has.
+ */
+int
+folders(void *arg __unused)
+{
+ char dirname[PATHSIZE];
+ char *cmd;
+
+ if (getfold(dirname, sizeof(dirname)) < 0) {
+ printf("No value set for \"folder\"\n");
+ return (1);
+ }
+ if ((cmd = value("LISTER")) == NULL)
+ cmd = "ls";
+ (void)run_command(cmd, 0, -1, -1, dirname, NULL);
+ return (0);
+}
+
+/*
+ * Update the mail file with any new messages that have
+ * come in since we started reading mail.
+ */
+int
+inc(void *v __unused)
+{
+ int nmsg, mdot;
+
+ nmsg = incfile();
+
+ if (nmsg == 0)
+ printf("No new mail.\n");
+ else if (nmsg > 0) {
+ mdot = newfileinfo(msgCount - nmsg);
+ dot = &message[mdot - 1];
+ } else
+ printf("\"inc\" command failed...\n");
+
+ return (0);
+}
diff --git a/usr.bin/mail/cmd2.c b/usr.bin/mail/cmd2.c
new file mode 100644
index 000000000000..5c670b7867e7
--- /dev/null
+++ b/usr.bin/mail/cmd2.c
@@ -0,0 +1,510 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <sys/wait.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * More user commands.
+ */
+
+extern int wait_status;
+
+/*
+ * If any arguments were given, go to the next applicable argument
+ * following dot, otherwise, go to the next applicable message.
+ * If given as first command with no arguments, print first message.
+ */
+int
+next(void *v)
+{
+ struct message *mp;
+ int *msgvec = v;
+ int *ip, *ip2, list[2], mdot;
+
+ if (*msgvec != 0) {
+
+ /*
+ * If some messages were supplied, find the
+ * first applicable one following dot using
+ * wrap around.
+ */
+
+ mdot = dot - &message[0] + 1;
+
+ /*
+ * Find the first message in the supplied
+ * message list which follows dot.
+ */
+
+ for (ip = msgvec; *ip != 0; ip++)
+ if (*ip > mdot)
+ break;
+ if (*ip == 0)
+ ip = msgvec;
+ ip2 = ip;
+ do {
+ mp = &message[*ip2 - 1];
+ if ((mp->m_flag & MDELETED) == 0) {
+ dot = mp;
+ goto hitit;
+ }
+ if (*ip2 != 0)
+ ip2++;
+ if (*ip2 == 0)
+ ip2 = msgvec;
+ } while (ip2 != ip);
+ printf("No messages applicable\n");
+ return (1);
+ }
+
+ /*
+ * If this is the first command, select message 1.
+ * Note that this must exist for us to get here at all.
+ */
+
+ if (!sawcom)
+ goto hitit;
+
+ /*
+ * Just find the next good message after dot, no
+ * wraparound.
+ */
+
+ for (mp = dot+1; mp < &message[msgCount]; mp++)
+ if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
+ break;
+ if (mp >= &message[msgCount]) {
+ printf("At EOF\n");
+ return (0);
+ }
+ dot = mp;
+hitit:
+ /*
+ * Print dot.
+ */
+
+ list[0] = dot - &message[0] + 1;
+ list[1] = 0;
+ return (type(list));
+}
+
+/*
+ * Save a message in a file. Mark the message as saved
+ * so we can discard when the user quits.
+ */
+int
+save(void *v)
+{
+ char *str = v;
+
+ return (save1(str, 1, "save", saveignore));
+}
+
+/*
+ * Copy a message to a file without affected its saved-ness
+ */
+int
+copycmd(void *v)
+{
+ char *str = v;
+
+ return (save1(str, 0, "copy", saveignore));
+}
+
+/*
+ * Save/copy the indicated messages at the end of the passed file name.
+ * If mark is true, mark the message "saved."
+ */
+int
+save1(char str[], int mark, const char *cmd, struct ignoretab *ignore)
+{
+ struct message *mp;
+ char *file;
+ const char *disp;
+ int f, *msgvec, *ip;
+ FILE *obuf;
+
+ msgvec = (int *)salloc((msgCount + 2) * sizeof(*msgvec));
+ if ((file = snarf(str, &f)) == NULL)
+ return (1);
+ if (!f) {
+ *msgvec = first(0, MMNORM);
+ if (*msgvec == 0) {
+ printf("No messages to %s.\n", cmd);
+ return (1);
+ }
+ msgvec[1] = 0;
+ }
+ if (f && getmsglist(str, msgvec, 0) < 0)
+ return (1);
+ if ((file = expand(file)) == NULL)
+ return (1);
+ printf("\"%s\" ", file);
+ (void)fflush(stdout);
+ if (access(file, 0) >= 0)
+ disp = "[Appended]";
+ else
+ disp = "[New file]";
+ if ((obuf = Fopen(file, "a")) == NULL) {
+ warn((char *)NULL);
+ return (1);
+ }
+ for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
+ mp = &message[*ip - 1];
+ touch(mp);
+ if (sendmessage(mp, obuf, ignore, NULL) < 0) {
+ warnx("%s", file);
+ (void)Fclose(obuf);
+ return (1);
+ }
+ if (mark)
+ mp->m_flag |= MSAVED;
+ }
+ (void)fflush(obuf);
+ if (ferror(obuf))
+ warn("%s", file);
+ (void)Fclose(obuf);
+ printf("%s\n", disp);
+ return (0);
+}
+
+/*
+ * Write the indicated messages at the end of the passed
+ * file name, minus header and trailing blank line.
+ */
+int
+swrite(void *v)
+{
+ char *str = v;
+
+ return (save1(str, 1, "write", ignoreall));
+}
+
+/*
+ * Snarf the file from the end of the command line and
+ * return a pointer to it. If there is no file attached,
+ * just return NULL. Put a null in front of the file
+ * name so that the message list processing won't see it,
+ * unless the file name is the only thing on the line, in
+ * which case, return 0 in the reference flag variable.
+ */
+
+char *
+snarf(char *linebuf, int *flag)
+{
+ char *cp;
+
+ *flag = 1;
+ cp = strlen(linebuf) + linebuf - 1;
+
+ /*
+ * Strip away trailing blanks.
+ */
+
+ while (cp > linebuf && isspace((unsigned char)*cp))
+ cp--;
+ *++cp = '\0';
+
+ /*
+ * Now search for the beginning of the file name.
+ */
+
+ while (cp > linebuf && !isspace((unsigned char)*cp))
+ cp--;
+ if (*cp == '\0') {
+ printf("No file specified.\n");
+ return (NULL);
+ }
+ if (isspace((unsigned char)*cp))
+ *cp++ = '\0';
+ else
+ *flag = 0;
+ return (cp);
+}
+
+/*
+ * Delete messages.
+ */
+int
+deletecmd(void *v)
+{
+ int *msgvec = v;
+
+ delm(msgvec);
+ return (0);
+}
+
+/*
+ * Delete messages, then type the new dot.
+ */
+int
+deltype(void *v)
+{
+ int *msgvec = v;
+ int list[2];
+ int lastdot;
+
+ lastdot = dot - &message[0] + 1;
+ if (delm(msgvec) >= 0) {
+ list[0] = dot - &message[0] + 1;
+ if (list[0] > lastdot) {
+ touch(dot);
+ list[1] = 0;
+ return (type(list));
+ }
+ printf("At EOF\n");
+ } else
+ printf("No more messages\n");
+ return (0);
+}
+
+/*
+ * Delete the indicated messages.
+ * Set dot to some nice place afterwards.
+ * Internal interface.
+ */
+int
+delm(int *msgvec)
+{
+ struct message *mp;
+ int *ip, last;
+
+ last = 0;
+ for (ip = msgvec; *ip != 0; ip++) {
+ mp = &message[*ip - 1];
+ touch(mp);
+ mp->m_flag |= MDELETED|MTOUCH;
+ mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
+ last = *ip;
+ }
+ if (last != 0) {
+ dot = &message[last-1];
+ last = first(0, MDELETED);
+ if (last != 0) {
+ dot = &message[last-1];
+ return (0);
+ }
+ else {
+ dot = &message[0];
+ return (-1);
+ }
+ }
+
+ /*
+ * Following can't happen -- it keeps lint happy
+ */
+
+ return (-1);
+}
+
+/*
+ * Undelete the indicated messages.
+ */
+int
+undeletecmd(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+ struct message *mp;
+
+ for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
+ mp = &message[*ip - 1];
+ touch(mp);
+ dot = mp;
+ mp->m_flag &= ~MDELETED;
+ }
+ return (0);
+}
+
+/*
+ * Interactively dump core on "core"
+ */
+int
+core(void *arg __unused)
+{
+ int pid;
+
+ switch (pid = fork()) {
+ case -1:
+ warn("fork");
+ return (1);
+ case 0:
+ abort();
+ _exit(1);
+ }
+ printf("Okie dokie");
+ (void)fflush(stdout);
+ wait_child(pid);
+ if (WIFSIGNALED(wait_status) && WCOREDUMP(wait_status))
+ printf(" -- Core dumped.\n");
+ else
+ printf(" -- Can't dump core.\n");
+ return (0);
+}
+
+/*
+ * Clobber as many bytes of stack as the user requests.
+ */
+int
+clobber(void *arg)
+{
+ char **argv = arg;
+ int times;
+
+ if (argv[0] == 0)
+ times = 1;
+ else
+ times = (atoi(argv[0]) + 511) / 512;
+ clob1(times);
+ return (0);
+}
+
+/*
+ * Clobber the stack.
+ */
+void
+clob1(int n)
+{
+ char buf[512];
+ char *cp;
+
+ if (n <= 0)
+ return;
+ for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
+ ;
+ clob1(n - 1);
+}
+
+/*
+ * Add the given header fields to the retained list.
+ * If no arguments, print the current list of retained fields.
+ */
+int
+retfield(void *v)
+{
+ char **list = v;
+
+ return (ignore1(list, ignore + 1, "retained"));
+}
+
+/*
+ * Add the given header fields to the ignored list.
+ * If no arguments, print the current list of ignored fields.
+ */
+int
+igfield(void *v)
+{
+ char **list = v;
+
+ return (ignore1(list, ignore, "ignored"));
+}
+
+int
+saveretfield(void *v)
+{
+ char **list = v;
+
+ return (ignore1(list, saveignore + 1, "retained"));
+}
+
+int
+saveigfield(void *v)
+{
+ char **list = v;
+
+ return (ignore1(list, saveignore, "ignored"));
+}
+
+int
+ignore1(char **list, struct ignoretab *tab, const char *which)
+{
+ char field[LINESIZE];
+ char **ap;
+ struct ignore *igp;
+ int h;
+
+ if (*list == NULL)
+ return (igshow(tab, which));
+ for (ap = list; *ap != 0; ap++) {
+ istrncpy(field, *ap, sizeof(field));
+ if (member(field, tab))
+ continue;
+ h = hash(field);
+ igp = calloc(1, sizeof(struct ignore));
+ igp->i_field = calloc((unsigned)strlen(field) + 1,
+ sizeof(char));
+ strcpy(igp->i_field, field);
+ igp->i_link = tab->i_head[h];
+ tab->i_head[h] = igp;
+ tab->i_count++;
+ }
+ return (0);
+}
+
+/*
+ * Print out all currently retained fields.
+ */
+int
+igshow(struct ignoretab *tab, const char *which)
+{
+ int h;
+ struct ignore *igp;
+ char **ap, **ring;
+
+ if (tab->i_count == 0) {
+ printf("No fields currently being %s.\n", which);
+ return (0);
+ }
+ ring = (char **)salloc((tab->i_count + 1) * sizeof(char *));
+ ap = ring;
+ for (h = 0; h < HSHSIZE; h++)
+ for (igp = tab->i_head[h]; igp != NULL; igp = igp->i_link)
+ *ap++ = igp->i_field;
+ *ap = 0;
+ qsort(ring, tab->i_count, sizeof(char *), igcomp);
+ for (ap = ring; *ap != 0; ap++)
+ printf("%s\n", *ap);
+ return (0);
+}
+
+/*
+ * Compare two names for sorting ignored field list.
+ */
+int
+igcomp(const void *l, const void *r)
+{
+
+ return (strcmp(*(const char **)l, *(const char **)r));
+}
diff --git a/usr.bin/mail/cmd3.c b/usr.bin/mail/cmd3.c
new file mode 100644
index 000000000000..fbc71ca87db4
--- /dev/null
+++ b/usr.bin/mail/cmd3.c
@@ -0,0 +1,723 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Still more user commands.
+ */
+
+/*
+ * Process a shell escape by saving signals, ignoring signals,
+ * and forking a sh -c
+ */
+int
+shell(void *str)
+{
+ sig_t sigint = signal(SIGINT, SIG_IGN);
+ char *sh;
+ char cmd[BUFSIZ];
+
+ if (strlcpy(cmd, str, sizeof(cmd)) >= sizeof(cmd))
+ return (1);
+ if (bangexp(cmd, sizeof(cmd)) < 0)
+ return (1);
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+ (void)run_command(sh, 0, -1, -1, "-c", cmd, NULL);
+ (void)signal(SIGINT, sigint);
+ printf("!\n");
+ return (0);
+}
+
+/*
+ * Fork an interactive shell.
+ */
+/*ARGSUSED*/
+int
+dosh(void *str __unused)
+{
+ sig_t sigint = signal(SIGINT, SIG_IGN);
+ char *sh;
+
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+ (void)run_command(sh, 0, -1, -1, NULL);
+ (void)signal(SIGINT, sigint);
+ printf("\n");
+ return (0);
+}
+
+/*
+ * Expand the shell escape by expanding unescaped !'s into the
+ * last issued command where possible.
+ */
+int
+bangexp(char *str, size_t strsize)
+{
+ char bangbuf[BUFSIZ];
+ static char lastbang[BUFSIZ];
+ char *cp, *cp2;
+ int n, changed = 0;
+
+ cp = str;
+ cp2 = bangbuf;
+ n = sizeof(bangbuf);
+ while (*cp != '\0') {
+ if (*cp == '!') {
+ if (n < (int)strlen(lastbang)) {
+overf:
+ printf("Command buffer overflow\n");
+ return (-1);
+ }
+ changed++;
+ if (strlcpy(cp2, lastbang, sizeof(bangbuf) - (cp2 - bangbuf))
+ >= sizeof(bangbuf) - (cp2 - bangbuf))
+ goto overf;
+ cp2 += strlen(lastbang);
+ n -= strlen(lastbang);
+ cp++;
+ continue;
+ }
+ if (*cp == '\\' && cp[1] == '!') {
+ if (--n <= 1)
+ goto overf;
+ *cp2++ = '!';
+ cp += 2;
+ changed++;
+ }
+ if (--n <= 1)
+ goto overf;
+ *cp2++ = *cp++;
+ }
+ *cp2 = 0;
+ if (changed) {
+ printf("!%s\n", bangbuf);
+ (void)fflush(stdout);
+ }
+ if (strlcpy(str, bangbuf, strsize) >= strsize)
+ goto overf;
+ if (strlcpy(lastbang, bangbuf, sizeof(lastbang)) >= sizeof(lastbang))
+ goto overf;
+ return (0);
+}
+
+/*
+ * Print out a nice help message from some file or another.
+ */
+
+int
+help(void *arg __unused)
+{
+ int c;
+ FILE *f;
+
+ if ((f = Fopen(_PATH_HELP, "r")) == NULL) {
+ warn("%s", _PATH_HELP);
+ return (1);
+ }
+ while ((c = getc(f)) != EOF)
+ putchar(c);
+ (void)Fclose(f);
+ return (0);
+}
+
+/*
+ * Change user's working directory.
+ */
+int
+schdir(void *v)
+{
+ char **arglist = v;
+ char *cp;
+
+ if (*arglist == NULL) {
+ if (homedir == NULL)
+ return (1);
+ cp = homedir;
+ } else
+ if ((cp = expand(*arglist)) == NULL)
+ return (1);
+ if (chdir(cp) < 0) {
+ warn("%s", cp);
+ return (1);
+ }
+ return (0);
+}
+
+int
+respond(void *v)
+{
+ int *msgvec = v;
+
+ if (value("Replyall") == NULL && value("flipr") == NULL)
+ return (dorespond(msgvec));
+ else
+ return (doRespond(msgvec));
+}
+
+/*
+ * Reply to a list of messages. Extract each name from the
+ * message header and send them off to mail1()
+ */
+int
+dorespond(int *msgvec)
+{
+ struct message *mp;
+ char *cp, *rcv, *replyto;
+ char **ap;
+ struct name *np;
+ struct header head;
+
+ if (msgvec[1] != 0) {
+ printf("Sorry, can't reply to multiple messages at once\n");
+ return (1);
+ }
+ mp = &message[msgvec[0] - 1];
+ touch(mp);
+ dot = mp;
+ if ((rcv = skin(hfield("from", mp))) == NULL)
+ rcv = skin(nameof(mp, 1));
+ if ((replyto = skin(hfield("reply-to", mp))) != NULL)
+ np = extract(replyto, GTO);
+ else if ((cp = skin(hfield("to", mp))) != NULL)
+ np = extract(cp, GTO);
+ else
+ np = NULL;
+ np = elide(np);
+ /*
+ * Delete my name from the reply list,
+ * and with it, all my alternate names.
+ */
+ np = delname(np, myname);
+ if (altnames)
+ for (ap = altnames; *ap != NULL; ap++)
+ np = delname(np, *ap);
+ if (np != NULL && replyto == NULL)
+ np = cat(np, extract(rcv, GTO));
+ else if (np == NULL) {
+ if (replyto != NULL)
+ printf("Empty reply-to field -- replying to author\n");
+ np = extract(rcv, GTO);
+ }
+ head.h_to = np;
+ if ((head.h_subject = hfield("subject", mp)) == NULL)
+ head.h_subject = hfield("subj", mp);
+ head.h_subject = reedit(head.h_subject);
+ if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) {
+ np = elide(extract(cp, GCC));
+ np = delname(np, myname);
+ if (altnames != 0)
+ for (ap = altnames; *ap != NULL; ap++)
+ np = delname(np, *ap);
+ head.h_cc = np;
+ } else
+ head.h_cc = NULL;
+ head.h_bcc = NULL;
+ head.h_smopts = NULL;
+ head.h_replyto = value("REPLYTO");
+ head.h_inreplyto = skin(hfield("message-id", mp));
+ mail1(&head, 1);
+ return (0);
+}
+
+/*
+ * Modify the message subject to begin with "Re:" if
+ * it does not already.
+ */
+char *
+reedit(char *subj)
+{
+ char *newsubj;
+
+ if (subj == NULL)
+ return (NULL);
+ if ((subj[0] == 'r' || subj[0] == 'R') &&
+ (subj[1] == 'e' || subj[1] == 'E') &&
+ subj[2] == ':')
+ return (subj);
+ newsubj = salloc(strlen(subj) + 5);
+ sprintf(newsubj, "Re: %s", subj);
+ return (newsubj);
+}
+
+/*
+ * Preserve the named messages, so that they will be sent
+ * back to the system mailbox.
+ */
+int
+preserve(void *v)
+{
+ int *msgvec = v;
+ int *ip, mesg;
+ struct message *mp;
+
+ if (edit) {
+ printf("Cannot \"preserve\" in edit mode\n");
+ return (1);
+ }
+ for (ip = msgvec; *ip != 0; ip++) {
+ mesg = *ip;
+ mp = &message[mesg-1];
+ mp->m_flag |= MPRESERVE;
+ mp->m_flag &= ~MBOX;
+ dot = mp;
+ }
+ return (0);
+}
+
+/*
+ * Mark all given messages as unread.
+ */
+int
+unread(void *v)
+{
+ int *msgvec = v;
+ int *ip;
+
+ for (ip = msgvec; *ip != 0; ip++) {
+ dot = &message[*ip-1];
+ dot->m_flag &= ~(MREAD|MTOUCH);
+ dot->m_flag |= MSTATUS;
+ }
+ return (0);
+}
+
+/*
+ * Print the size of each message.
+ */
+int
+messize(void *v)
+{
+ int *msgvec = v;
+ struct message *mp;
+ int *ip, mesg;
+
+ for (ip = msgvec; *ip != 0; ip++) {
+ mesg = *ip;
+ mp = &message[mesg-1];
+ printf("%d: %ld/%ld\n", mesg, mp->m_lines, mp->m_size);
+ }
+ return (0);
+}
+
+/*
+ * Quit quickly. If we are sourcing, just pop the input level
+ * by returning an error.
+ */
+int
+rexit(void *v)
+{
+ if (sourcing)
+ return (1);
+ exit(0);
+ /*NOTREACHED*/
+}
+
+/*
+ * Set or display a variable value. Syntax is similar to that
+ * of csh.
+ */
+int
+set(void *v)
+{
+ char **arglist = v;
+ struct var *vp;
+ char *cp, *cp2;
+ char varbuf[BUFSIZ], **ap, **p;
+ int errs, h, s;
+
+ if (*arglist == NULL) {
+ for (h = 0, s = 1; h < HSHSIZE; h++)
+ for (vp = variables[h]; vp != NULL; vp = vp->v_link)
+ s++;
+ ap = (char **)salloc(s * sizeof(*ap));
+ for (h = 0, p = ap; h < HSHSIZE; h++)
+ for (vp = variables[h]; vp != NULL; vp = vp->v_link)
+ *p++ = vp->v_name;
+ *p = NULL;
+ sort(ap);
+ for (p = ap; *p != NULL; p++)
+ printf("%s\t%s\n", *p, value(*p));
+ return (0);
+ }
+ errs = 0;
+ for (ap = arglist; *ap != NULL; ap++) {
+ cp = *ap;
+ cp2 = varbuf;
+ while (cp2 < varbuf + sizeof(varbuf) - 1 && *cp != '=' && *cp != '\0')
+ *cp2++ = *cp++;
+ *cp2 = '\0';
+ if (*cp == '\0')
+ cp = "";
+ else
+ cp++;
+ if (equal(varbuf, "")) {
+ printf("Non-null variable name required\n");
+ errs++;
+ continue;
+ }
+ assign(varbuf, cp);
+ }
+ return (errs);
+}
+
+/*
+ * Unset a bunch of variable values.
+ */
+int
+unset(void *v)
+{
+ char **arglist = v;
+ struct var *vp, *vp2;
+ int errs, h;
+ char **ap;
+
+ errs = 0;
+ for (ap = arglist; *ap != NULL; ap++) {
+ if ((vp2 = lookup(*ap)) == NULL) {
+ if (getenv(*ap))
+ unsetenv(*ap);
+ else if (!sourcing) {
+ printf("\"%s\": undefined variable\n", *ap);
+ errs++;
+ }
+ continue;
+ }
+ h = hash(*ap);
+ if (vp2 == variables[h]) {
+ variables[h] = variables[h]->v_link;
+ vfree(vp2->v_name);
+ vfree(vp2->v_value);
+ (void)free(vp2);
+ continue;
+ }
+ for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link)
+ ;
+ vp->v_link = vp2->v_link;
+ vfree(vp2->v_name);
+ vfree(vp2->v_value);
+ (void)free(vp2);
+ }
+ return (errs);
+}
+
+/*
+ * Put add users to a group.
+ */
+int
+group(void *v)
+{
+ char **argv = v;
+ struct grouphead *gh;
+ struct group *gp;
+ char **ap, *gname, **p;
+ int h, s;
+
+ if (*argv == NULL) {
+ for (h = 0, s = 1; h < HSHSIZE; h++)
+ for (gh = groups[h]; gh != NULL; gh = gh->g_link)
+ s++;
+ ap = (char **)salloc(s * sizeof(*ap));
+ for (h = 0, p = ap; h < HSHSIZE; h++)
+ for (gh = groups[h]; gh != NULL; gh = gh->g_link)
+ *p++ = gh->g_name;
+ *p = NULL;
+ sort(ap);
+ for (p = ap; *p != NULL; p++)
+ printgroup(*p);
+ return (0);
+ }
+ if (argv[1] == NULL) {
+ printgroup(*argv);
+ return (0);
+ }
+ gname = *argv;
+ h = hash(gname);
+ if ((gh = findgroup(gname)) == NULL) {
+ if ((gh = calloc(1, sizeof(*gh))) == NULL)
+ err(1, "Out of memory");
+ gh->g_name = vcopy(gname);
+ gh->g_list = NULL;
+ gh->g_link = groups[h];
+ groups[h] = gh;
+ }
+
+ /*
+ * Insert names from the command list into the group.
+ * Who cares if there are duplicates? They get tossed
+ * later anyway.
+ */
+
+ for (ap = argv+1; *ap != NULL; ap++) {
+ if ((gp = calloc(1, sizeof(*gp))) == NULL)
+ err(1, "Out of memory");
+ gp->ge_name = vcopy(*ap);
+ gp->ge_link = gh->g_list;
+ gh->g_list = gp;
+ }
+ return (0);
+}
+
+/*
+ * Sort the passed string vecotor into ascending dictionary
+ * order.
+ */
+void
+sort(char **list)
+{
+ char **ap;
+
+ for (ap = list; *ap != NULL; ap++)
+ ;
+ if (ap-list < 2)
+ return;
+ qsort(list, ap-list, sizeof(*list), diction);
+}
+
+/*
+ * Do a dictionary order comparison of the arguments from
+ * qsort.
+ */
+int
+diction(const void *a, const void *b)
+{
+ return (strcmp(*(const char **)a, *(const char **)b));
+}
+
+/*
+ * The do nothing command for comments.
+ */
+
+/*ARGSUSED*/
+int
+null(void *arg __unused)
+{
+ return (0);
+}
+
+/*
+ * Change to another file. With no argument, print information about
+ * the current file.
+ */
+int
+file(void *arg)
+{
+ char **argv = arg;
+
+ if (argv[0] == NULL) {
+ newfileinfo(0);
+ return (0);
+ }
+ if (setfile(*argv) < 0)
+ return (1);
+ announce();
+ return (0);
+}
+
+/*
+ * Expand file names like echo
+ */
+int
+echo(void *arg)
+{
+ char **argv = arg;
+ char **ap, *cp;
+
+ for (ap = argv; *ap != NULL; ap++) {
+ cp = *ap;
+ if ((cp = expand(cp)) != NULL) {
+ if (ap != argv)
+ printf(" ");
+ printf("%s", cp);
+ }
+ }
+ printf("\n");
+ return (0);
+}
+
+int
+Respond(void *msgvec)
+{
+ if (value("Replyall") == NULL && value("flipr") == NULL)
+ return (doRespond(msgvec));
+ else
+ return (dorespond(msgvec));
+}
+
+/*
+ * Reply to a series of messages by simply mailing to the senders
+ * and not messing around with the To: and Cc: lists as in normal
+ * reply.
+ */
+int
+doRespond(int msgvec[])
+{
+ struct header head;
+ struct message *mp;
+ int *ap;
+ char *cp, *mid;
+
+ head.h_to = NULL;
+ for (ap = msgvec; *ap != 0; ap++) {
+ mp = &message[*ap - 1];
+ touch(mp);
+ dot = mp;
+ if ((cp = skin(hfield("from", mp))) == NULL)
+ cp = skin(nameof(mp, 2));
+ head.h_to = cat(head.h_to, extract(cp, GTO));
+ mid = skin(hfield("message-id", mp));
+ }
+ if (head.h_to == NULL)
+ return (0);
+ mp = &message[msgvec[0] - 1];
+ if ((head.h_subject = hfield("subject", mp)) == NULL)
+ head.h_subject = hfield("subj", mp);
+ head.h_subject = reedit(head.h_subject);
+ head.h_cc = NULL;
+ head.h_bcc = NULL;
+ head.h_smopts = NULL;
+ head.h_replyto = value("REPLYTO");
+ head.h_inreplyto = mid;
+ mail1(&head, 1);
+ return (0);
+}
+
+/*
+ * Conditional commands. These allow one to parameterize one's
+ * .mailrc and do some things if sending, others if receiving.
+ */
+int
+ifcmd(void *arg)
+{
+ char **argv = arg;
+ char *cp;
+
+ if (cond != CANY) {
+ printf("Illegal nested \"if\"\n");
+ return (1);
+ }
+ cond = CANY;
+ cp = argv[0];
+ switch (*cp) {
+ case 'r': case 'R':
+ cond = CRCV;
+ break;
+
+ case 's': case 'S':
+ cond = CSEND;
+ break;
+
+ default:
+ printf("Unrecognized if-keyword: \"%s\"\n", cp);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Implement 'else'. This is pretty simple -- we just
+ * flip over the conditional flag.
+ */
+int
+elsecmd(void *arg __unused)
+{
+
+ switch (cond) {
+ case CANY:
+ printf("\"Else\" without matching \"if\"\n");
+ return (1);
+
+ case CSEND:
+ cond = CRCV;
+ break;
+
+ case CRCV:
+ cond = CSEND;
+ break;
+
+ default:
+ printf("Mail's idea of conditions is screwed up\n");
+ cond = CANY;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * End of if statement. Just set cond back to anything.
+ */
+int
+endifcmd(void *arg __unused)
+{
+
+ if (cond == CANY) {
+ printf("\"Endif\" without matching \"if\"\n");
+ return (1);
+ }
+ cond = CANY;
+ return (0);
+}
+
+/*
+ * Set the list of alternate names.
+ */
+int
+alternates(void *arg)
+{
+ char **namelist = arg;
+ int c;
+ char **ap, **ap2, *cp;
+
+ c = argcount(namelist) + 1;
+ if (c == 1) {
+ if (altnames == 0)
+ return (0);
+ for (ap = altnames; *ap != NULL; ap++)
+ printf("%s ", *ap);
+ printf("\n");
+ return (0);
+ }
+ if (altnames != 0)
+ (void)free(altnames);
+ if ((altnames = calloc((unsigned)c, sizeof(char *))) == NULL)
+ err(1, "Out of memory");
+ for (ap = namelist, ap2 = altnames; *ap != NULL; ap++, ap2++) {
+ cp = calloc((unsigned)strlen(*ap) + 1, sizeof(char));
+ strcpy(cp, *ap);
+ *ap2 = cp;
+ }
+ *ap2 = 0;
+ return (0);
+}
diff --git a/usr.bin/mail/cmdtab.c b/usr.bin/mail/cmdtab.c
new file mode 100644
index 000000000000..8c5ed43a03ae
--- /dev/null
+++ b/usr.bin/mail/cmdtab.c
@@ -0,0 +1,115 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "def.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Define all of the command names and bindings.
+ */
+
+const struct cmd cmdtab[] = {
+ /* msgmask msgflag */
+ /* command function argtype result & mask */
+ /* ------- -------- ------- ------ ------- */
+ { "next", next, NDMLIST, 0, MMNDEL },
+ { "alias", group, M|RAWLIST, 0, 1000 },
+ { "print", type, MSGLIST, 0, MMNDEL },
+ { "type", type, MSGLIST, 0, MMNDEL },
+ { "Type", Type, MSGLIST, 0, MMNDEL },
+ { "Print", Type, MSGLIST, 0, MMNDEL },
+ { "visual", visual, I|MSGLIST, 0, MMNORM },
+ { "top", top, MSGLIST, 0, MMNDEL },
+ { "touch", stouch, W|MSGLIST, 0, MMNDEL },
+ { "preserve", preserve, W|MSGLIST, 0, MMNDEL },
+ { "delete", deletecmd, W|P|MSGLIST, 0, MMNDEL },
+ { "dp", deltype, W|MSGLIST, 0, MMNDEL },
+ { "dt", deltype, W|MSGLIST, 0, MMNDEL },
+ { "undelete", undeletecmd, P|MSGLIST, MDELETED,MMNDEL },
+ { "unset", unset, M|RAWLIST, 1, 1000 },
+ { "mail", sendmail, R|M|I|STRLIST, 0, 0 },
+ { "mbox", mboxit, W|MSGLIST, 0, 0 },
+ { "more", more, MSGLIST, 0, MMNDEL },
+ { "page", more, MSGLIST, 0, MMNDEL },
+ { "More", More, MSGLIST, 0, MMNDEL },
+ { "Page", More, MSGLIST, 0, MMNDEL },
+ { "unread", unread, MSGLIST, 0, MMNDEL },
+ { "!", shell, I|STRLIST, 0, 0 },
+ { "copy", copycmd, M|STRLIST, 0, 0 },
+ { "chdir", schdir, M|RAWLIST, 0, 1 },
+ { "cd", schdir, M|RAWLIST, 0, 1 },
+ { "save", save, STRLIST, 0, 0 },
+ { "source", source, M|RAWLIST, 1, 1 },
+ { "set", set, M|RAWLIST, 0, 1000 },
+ { "shell", dosh, I|NOLIST, 0, 0 },
+ { "version", pversion, M|NOLIST, 0, 0 },
+ { "group", group, M|RAWLIST, 0, 1000 },
+ { "write", swrite, STRLIST, 0, 0 },
+ { "from", from, MSGLIST, 0, MMNORM },
+ { "file", file, T|M|RAWLIST, 0, 1 },
+ { "folder", file, T|M|RAWLIST, 0, 1 },
+ { "folders", folders, T|M|NOLIST, 0, 0 },
+ { "?", help, M|NOLIST, 0, 0 },
+ { "z", scroll, M|STRLIST, 0, 0 },
+ { "headers", headers, MSGLIST, 0, MMNDEL },
+ { "help", help, M|NOLIST, 0, 0 },
+ { "=", pdot, NOLIST, 0, 0 },
+ { "Reply", Respond, R|I|MSGLIST, 0, MMNDEL },
+ { "Respond", Respond, R|I|MSGLIST, 0, MMNDEL },
+ { "reply", respond, R|I|MSGLIST, 0, MMNDEL },
+ { "respond", respond, R|I|MSGLIST, 0, MMNDEL },
+ { "edit", editor, I|MSGLIST, 0, MMNORM },
+ { "echo", echo, M|RAWLIST, 0, 1000 },
+ { "quit", quitcmd, NOLIST, 0, 0 },
+ { "list", pcmdlist, M|NOLIST, 0, 0 },
+ { "xit", rexit, M|NOLIST, 0, 0 },
+ { "exit", rexit, M|NOLIST, 0, 0 },
+ { "size", messize, MSGLIST, 0, MMNDEL },
+ { "hold", preserve, W|MSGLIST, 0, MMNDEL },
+ { "if", ifcmd, F|M|RAWLIST, 1, 1 },
+ { "else", elsecmd, F|M|RAWLIST, 0, 0 },
+ { "endif", endifcmd, F|M|RAWLIST, 0, 0 },
+ { "alternates", alternates, M|RAWLIST, 0, 1000 },
+ { "ignore", igfield, M|RAWLIST, 0, 1000 },
+ { "discard", igfield, M|RAWLIST, 0, 1000 },
+ { "retain", retfield, M|RAWLIST, 0, 1000 },
+ { "saveignore", saveigfield, M|RAWLIST, 0, 1000 },
+ { "savediscard",saveigfield, M|RAWLIST, 0, 1000 },
+ { "saveretain", saveretfield, M|RAWLIST, 0, 1000 },
+/* { "Header", Header, STRLIST, 0, 1000 }, */
+ { "core", core, M|NOLIST, 0, 0 },
+ { "#", null, M|NOLIST, 0, 0 },
+ { "clobber", clobber, M|RAWLIST, 0, 1 },
+ { "inc", inc, T|NOLIST, 0, 0 },
+ { 0, 0, 0, 0, 0 }
+};
diff --git a/usr.bin/mail/collect.c b/usr.bin/mail/collect.c
new file mode 100644
index 000000000000..0c310b15b234
--- /dev/null
+++ b/usr.bin/mail/collect.c
@@ -0,0 +1,725 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Collect input from standard input, handling
+ * ~ escapes.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Read a message from standard input and return a read file to it
+ * or NULL on error.
+ */
+
+/*
+ * The following hokiness with global variables is so that on
+ * receipt of an interrupt signal, the partial message can be salted
+ * away on dead.letter.
+ */
+
+static sig_t saveint; /* Previous SIGINT value */
+static sig_t savehup; /* Previous SIGHUP value */
+static sig_t savetstp; /* Previous SIGTSTP value */
+static sig_t savettou; /* Previous SIGTTOU value */
+static sig_t savettin; /* Previous SIGTTIN value */
+static FILE *collf; /* File for saving away */
+static int hadintr; /* Have seen one SIGINT so far */
+
+static jmp_buf colljmp; /* To get back to work */
+static int colljmp_p; /* whether to long jump */
+static jmp_buf collabort; /* To end collection with error */
+
+FILE *
+collect(struct header *hp, int printheaders)
+{
+ FILE *fbuf;
+ int lc, cc, escape, eofcount, fd, c, t;
+ char linebuf[LINESIZE], tempname[PATHSIZE], *cp, getsub;
+ sigset_t nset;
+ int longline, lastlong, rc; /* So we don't make 2 or more lines
+ out of a long input line. */
+
+ collf = NULL;
+ /*
+ * Start catching signals from here, but we're still die on interrupts
+ * until we're in the main loop.
+ */
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGINT);
+ (void)sigaddset(&nset, SIGHUP);
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
+ (void)signal(SIGINT, collint);
+ if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN)
+ (void)signal(SIGHUP, collhup);
+ savetstp = signal(SIGTSTP, collstop);
+ savettou = signal(SIGTTOU, collstop);
+ savettin = signal(SIGTTIN, collstop);
+ if (setjmp(collabort) || setjmp(colljmp)) {
+ (void)rm(tempname);
+ goto err;
+ }
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+
+ noreset++;
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.RsXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (collf = Fdopen(fd, "w+")) == NULL) {
+ warn("%s", tempname);
+ goto err;
+ }
+ (void)rm(tempname);
+
+ /*
+ * If we are going to prompt for a subject,
+ * refrain from printing a newline after
+ * the headers (since some people mind).
+ */
+ t = GTO|GSUBJECT|GCC|GNL;
+ getsub = 0;
+ if (hp->h_subject == NULL && value("interactive") != NULL &&
+ (value("ask") != NULL || value("asksub") != NULL))
+ t &= ~GNL, getsub++;
+ if (printheaders) {
+ puthead(hp, stdout, t);
+ (void)fflush(stdout);
+ }
+ if ((cp = value("escape")) != NULL)
+ escape = *cp;
+ else
+ escape = ESCAPE;
+ eofcount = 0;
+ hadintr = 0;
+ longline = 0;
+
+ if (!setjmp(colljmp)) {
+ if (getsub)
+ grabh(hp, GSUBJECT);
+ } else {
+ /*
+ * Come here for printing the after-signal message.
+ * Duplicate messages won't be printed because
+ * the write is aborted if we get a SIGTTOU.
+ */
+cont:
+ if (hadintr) {
+ (void)fflush(stdout);
+ fprintf(stderr,
+ "\n(Interrupt -- one more to kill letter)\n");
+ } else {
+ printf("(continue)\n");
+ (void)fflush(stdout);
+ }
+ }
+ for (;;) {
+ colljmp_p = 1;
+ c = readline(stdin, linebuf, LINESIZE);
+ colljmp_p = 0;
+ if (c < 0) {
+ if (value("interactive") != NULL &&
+ value("ignoreeof") != NULL && ++eofcount < 25) {
+ printf("Use \".\" to terminate letter\n");
+ continue;
+ }
+ break;
+ }
+ lastlong = longline;
+ longline = c == LINESIZE - 1;
+ eofcount = 0;
+ hadintr = 0;
+ if (linebuf[0] == '.' && linebuf[1] == '\0' &&
+ value("interactive") != NULL && !lastlong &&
+ (value("dot") != NULL || value("ignoreeof") != NULL))
+ break;
+ if (linebuf[0] != escape || value("interactive") == NULL ||
+ lastlong) {
+ if (putline(collf, linebuf, !longline) < 0)
+ goto err;
+ continue;
+ }
+ c = linebuf[1];
+ switch (c) {
+ default:
+ /*
+ * On double escape, just send the single one.
+ * Otherwise, it's an error.
+ */
+ if (c == escape) {
+ if (putline(collf, &linebuf[1], !longline) < 0)
+ goto err;
+ else
+ break;
+ }
+ printf("Unknown tilde escape.\n");
+ break;
+ case 'C':
+ /*
+ * Dump core.
+ */
+ core(NULL);
+ break;
+ case '!':
+ /*
+ * Shell escape, send the balance of the
+ * line to sh -c.
+ */
+ shell(&linebuf[2]);
+ break;
+ case ':':
+ case '_':
+ /*
+ * Escape to command mode, but be nice!
+ */
+ execute(&linebuf[2], 1);
+ goto cont;
+ case '.':
+ /*
+ * Simulate end of file on input.
+ */
+ goto out;
+ case 'q':
+ /*
+ * Force a quit of sending mail.
+ * Act like an interrupt happened.
+ */
+ hadintr++;
+ collint(SIGINT);
+ exit(1);
+ case 'x':
+ /*
+ * Exit, do not save in dead.letter.
+ */
+ goto err;
+ case 'h':
+ /*
+ * Grab a bunch of headers.
+ */
+ grabh(hp, GTO|GSUBJECT|GCC|GBCC);
+ goto cont;
+ case 't':
+ /*
+ * Add to the To list.
+ */
+ hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO));
+ break;
+ case 's':
+ /*
+ * Set the Subject line.
+ */
+ cp = &linebuf[2];
+ while (isspace((unsigned char)*cp))
+ cp++;
+ hp->h_subject = savestr(cp);
+ break;
+ case 'R':
+ /*
+ * Set the Reply-To line.
+ */
+ cp = &linebuf[2];
+ while (isspace((unsigned char)*cp))
+ cp++;
+ hp->h_replyto = savestr(cp);
+ break;
+ case 'c':
+ /*
+ * Add to the CC list.
+ */
+ hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC));
+ break;
+ case 'b':
+ /*
+ * Add to the BCC list.
+ */
+ hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC));
+ break;
+ case 'i':
+ case 'A':
+ case 'a':
+ /*
+ * Insert named variable in message.
+ */
+ switch(c) {
+ case 'i':
+ cp = &linebuf[2];
+ while(isspace((unsigned char)*cp))
+ cp++;
+ break;
+ case 'a':
+ cp = "sign";
+ break;
+ case 'A':
+ cp = "Sign";
+ break;
+ default:
+ goto err;
+ }
+
+ if(*cp != '\0' && (cp = value(cp)) != NULL) {
+ printf("%s\n", cp);
+ if(putline(collf, cp, 1) < 0)
+ goto err;
+ }
+
+ break;
+ case 'd':
+ /*
+ * Read in the dead letter file.
+ */
+ if (strlcpy(linebuf + 2, getdeadletter(),
+ sizeof(linebuf) - 2)
+ >= sizeof(linebuf) - 2) {
+ printf("Line buffer overflow\n");
+ break;
+ }
+ /* FALLTHROUGH */
+ case 'r':
+ case '<':
+ /*
+ * Invoke a file:
+ * Search for the file name,
+ * then open it and copy the contents to collf.
+ */
+ cp = &linebuf[2];
+ while (isspace((unsigned char)*cp))
+ cp++;
+ if (*cp == '\0') {
+ printf("Interpolate what file?\n");
+ break;
+ }
+ cp = expand(cp);
+ if (cp == NULL)
+ break;
+ if (*cp == '!') {
+ /*
+ * Insert stdout of command.
+ */
+ char *sh;
+ int nullfd, tempfd, rc;
+ char tempname2[PATHSIZE];
+
+ if ((nullfd = open(_PATH_DEVNULL, O_RDONLY, 0))
+ == -1) {
+ warn(_PATH_DEVNULL);
+ break;
+ }
+
+ (void)snprintf(tempname2, sizeof(tempname2),
+ "%s/mail.ReXXXXXXXXXX", tmpdir);
+ if ((tempfd = mkstemp(tempname2)) == -1 ||
+ (fbuf = Fdopen(tempfd, "w+")) == NULL) {
+ warn("%s", tempname2);
+ break;
+ }
+ (void)unlink(tempname2);
+
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+
+ rc = run_command(sh, 0, nullfd, fileno(fbuf),
+ "-c", cp+1, NULL);
+
+ close(nullfd);
+
+ if (rc < 0) {
+ (void)Fclose(fbuf);
+ break;
+ }
+
+ if (fsize(fbuf) == 0) {
+ fprintf(stderr,
+ "No bytes from command \"%s\"\n",
+ cp+1);
+ (void)Fclose(fbuf);
+ break;
+ }
+
+ rewind(fbuf);
+ } else if (isdir(cp)) {
+ printf("%s: Directory\n", cp);
+ break;
+ } else if ((fbuf = Fopen(cp, "r")) == NULL) {
+ warn("%s", cp);
+ break;
+ }
+ printf("\"%s\" ", cp);
+ (void)fflush(stdout);
+ lc = 0;
+ cc = 0;
+ while ((rc = readline(fbuf, linebuf, LINESIZE)) >= 0) {
+ if (rc != LINESIZE - 1)
+ lc++;
+ if ((t = putline(collf, linebuf,
+ rc != LINESIZE - 1)) < 0) {
+ (void)Fclose(fbuf);
+ goto err;
+ }
+ cc += t;
+ }
+ (void)Fclose(fbuf);
+ printf("%d/%d\n", lc, cc);
+ break;
+ case 'w':
+ /*
+ * Write the message on a file.
+ */
+ cp = &linebuf[2];
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0') {
+ fprintf(stderr, "Write what file!?\n");
+ break;
+ }
+ if ((cp = expand(cp)) == NULL)
+ break;
+ rewind(collf);
+ exwrite(cp, collf, 1);
+ break;
+ case 'm':
+ case 'M':
+ case 'f':
+ case 'F':
+ /*
+ * Interpolate the named messages, if we
+ * are in receiving mail mode. Does the
+ * standard list processing garbage.
+ * If ~f is given, we don't shift over.
+ */
+ if (forward(linebuf + 2, collf, tempname, c) < 0)
+ goto err;
+ goto cont;
+ case '?':
+ if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) {
+ warn("%s", _PATH_TILDE);
+ break;
+ }
+ while ((t = getc(fbuf)) != EOF)
+ (void)putchar(t);
+ (void)Fclose(fbuf);
+ break;
+ case 'p':
+ /*
+ * Print out the current state of the
+ * message without altering anything.
+ */
+ rewind(collf);
+ printf("-------\nMessage contains:\n");
+ puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
+ while ((t = getc(collf)) != EOF)
+ (void)putchar(t);
+ goto cont;
+ case '|':
+ /*
+ * Pipe message through command.
+ * Collect output as new message.
+ */
+ rewind(collf);
+ mespipe(collf, &linebuf[2]);
+ goto cont;
+ case 'v':
+ case 'e':
+ /*
+ * Edit the current message.
+ * 'e' means to use EDITOR
+ * 'v' means to use VISUAL
+ */
+ rewind(collf);
+ mesedit(collf, c);
+ goto cont;
+ }
+ }
+ goto out;
+err:
+ if (collf != NULL) {
+ (void)Fclose(collf);
+ collf = NULL;
+ }
+out:
+ if (collf != NULL)
+ rewind(collf);
+ noreset--;
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ (void)signal(SIGINT, saveint);
+ (void)signal(SIGHUP, savehup);
+ (void)signal(SIGTSTP, savetstp);
+ (void)signal(SIGTTOU, savettou);
+ (void)signal(SIGTTIN, savettin);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+ return (collf);
+}
+
+/*
+ * Write a file, ex-like if f set.
+ */
+int
+exwrite(char name[], FILE *fp, int f)
+{
+ FILE *of;
+ int c, lc;
+ long cc;
+ struct stat junk;
+
+ if (f) {
+ printf("\"%s\" ", name);
+ (void)fflush(stdout);
+ }
+ if (stat(name, &junk) >= 0 && S_ISREG(junk.st_mode)) {
+ if (!f)
+ fprintf(stderr, "%s: ", name);
+ fprintf(stderr, "File exists\n");
+ return (-1);
+ }
+ if ((of = Fopen(name, "w")) == NULL) {
+ warn((char *)NULL);
+ return (-1);
+ }
+ lc = 0;
+ cc = 0;
+ while ((c = getc(fp)) != EOF) {
+ cc++;
+ if (c == '\n')
+ lc++;
+ (void)putc(c, of);
+ if (ferror(of)) {
+ warnx("%s", name);
+ (void)Fclose(of);
+ return (-1);
+ }
+ }
+ (void)Fclose(of);
+ printf("%d/%ld\n", lc, cc);
+ (void)fflush(stdout);
+ return (0);
+}
+
+/*
+ * Edit the message being collected on fp.
+ * On return, make the edit file the new temp file.
+ */
+void
+mesedit(FILE *fp, int c)
+{
+ sig_t sigint = signal(SIGINT, SIG_IGN);
+ FILE *nf = run_editor(fp, (off_t)-1, c, 0);
+
+ if (nf != NULL) {
+ (void)fseeko(nf, (off_t)0, SEEK_END);
+ collf = nf;
+ (void)Fclose(fp);
+ }
+ (void)signal(SIGINT, sigint);
+}
+
+/*
+ * Pipe the message through the command.
+ * Old message is on stdin of command;
+ * New message collected from stdout.
+ * Sh -c must return 0 to accept the new message.
+ */
+void
+mespipe(FILE *fp, char cmd[])
+{
+ FILE *nf;
+ int fd;
+ sig_t sigint = signal(SIGINT, SIG_IGN);
+ char *sh, tempname[PATHSIZE];
+
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.ReXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (nf = Fdopen(fd, "w+")) == NULL) {
+ warn("%s", tempname);
+ goto out;
+ }
+ (void)rm(tempname);
+ /*
+ * stdin = current message.
+ * stdout = new message.
+ */
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+ if (run_command(sh,
+ 0, fileno(fp), fileno(nf), "-c", cmd, NULL) < 0) {
+ (void)Fclose(nf);
+ goto out;
+ }
+ if (fsize(nf) == 0) {
+ fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
+ (void)Fclose(nf);
+ goto out;
+ }
+ /*
+ * Take new files.
+ */
+ (void)fseeko(nf, (off_t)0, SEEK_END);
+ collf = nf;
+ (void)Fclose(fp);
+out:
+ (void)signal(SIGINT, sigint);
+}
+
+/*
+ * Interpolate the named messages into the current
+ * message, preceding each line with a tab.
+ * Return a count of the number of characters now in
+ * the message, or -1 if an error is encountered writing
+ * the message temporary. The flag argument is 'm' if we
+ * should shift over and 'f' if not.
+ */
+int
+forward(char ms[], FILE *fp, char *fn, int f)
+{
+ int *msgvec;
+ struct ignoretab *ig;
+ char *tabst;
+
+ msgvec = (int *)salloc((msgCount+1) * sizeof(*msgvec));
+ if (msgvec == NULL)
+ return (0);
+ if (getmsglist(ms, msgvec, 0) < 0)
+ return (0);
+ if (*msgvec == 0) {
+ *msgvec = first(0, MMNORM);
+ if (*msgvec == 0) {
+ printf("No appropriate messages\n");
+ return (0);
+ }
+ msgvec[1] = 0;
+ }
+ if (f == 'f' || f == 'F')
+ tabst = NULL;
+ else if ((tabst = value("indentprefix")) == NULL)
+ tabst = "\t";
+ ig = isupper((unsigned char)f) ? NULL : ignore;
+ printf("Interpolating:");
+ for (; *msgvec != 0; msgvec++) {
+ struct message *mp = message + *msgvec - 1;
+
+ touch(mp);
+ printf(" %d", *msgvec);
+ if (sendmessage(mp, fp, ig, tabst) < 0) {
+ warnx("%s", fn);
+ return (-1);
+ }
+ }
+ printf("\n");
+ return (0);
+}
+
+/*
+ * Print (continue) when continued after ^Z.
+ */
+/*ARGSUSED*/
+void
+collstop(int s)
+{
+ sig_t old_action = signal(s, SIG_DFL);
+ sigset_t nset;
+
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, s);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+ (void)kill(0, s);
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ (void)signal(s, old_action);
+ if (colljmp_p) {
+ colljmp_p = 0;
+ hadintr = 0;
+ longjmp(colljmp, 1);
+ }
+}
+
+/*
+ * On interrupt, come here to save the partial message in ~/dead.letter.
+ * Then jump out of the collection loop.
+ */
+/*ARGSUSED*/
+void
+collint(int s __unused)
+{
+ /*
+ * the control flow is subtle, because we can be called from ~q.
+ */
+ if (!hadintr) {
+ if (value("ignore") != NULL) {
+ printf("@");
+ (void)fflush(stdout);
+ clearerr(stdin);
+ return;
+ }
+ hadintr = 1;
+ longjmp(colljmp, 1);
+ }
+ rewind(collf);
+ if (value("nosave") == NULL)
+ savedeadletter(collf);
+ longjmp(collabort, 1);
+}
+
+/*ARGSUSED*/
+void
+collhup(int s __unused)
+{
+ rewind(collf);
+ savedeadletter(collf);
+ /*
+ * Let's pretend nobody else wants to clean up,
+ * a true statement at this time.
+ */
+ exit(1);
+}
+
+void
+savedeadletter(FILE *fp)
+{
+ FILE *dbuf;
+ int c;
+ char *cp;
+
+ if (fsize(fp) == 0)
+ return;
+ cp = getdeadletter();
+ c = umask(077);
+ dbuf = Fopen(cp, "a");
+ (void)umask(c);
+ if (dbuf == NULL)
+ return;
+ while ((c = getc(fp)) != EOF)
+ (void)putc(c, dbuf);
+ (void)Fclose(dbuf);
+ rewind(fp);
+}
diff --git a/usr.bin/mail/def.h b/usr.bin/mail/def.h
new file mode 100644
index 000000000000..298e489a36ae
--- /dev/null
+++ b/usr.bin/mail/def.h
@@ -0,0 +1,272 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Author: Kurt Shoens (UCB) March 25, 1978
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+#define APPEND /* New mail goes to end of mailbox */
+
+#define ESCAPE '~' /* Default escape for sending */
+#define NMLSIZE 1024 /* max names in a message list */
+#define PATHSIZE MAXPATHLEN /* Size of pathnames throughout */
+#define HSHSIZE 59 /* Hash size for aliases and vars */
+#define LINESIZE BUFSIZ /* max readable line width */
+#define STRINGSIZE ((unsigned)128) /* Dynamic allocation units */
+#define MAXARGC 1024 /* Maximum list of raw strings */
+#define MAXEXP 25 /* Maximum expansion of aliases */
+
+#define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */
+
+struct message {
+ short m_flag; /* flags, see below */
+ short m_offset; /* offset in block of message */
+ long m_block; /* block number of this message */
+ long m_size; /* Bytes in the message */
+ long m_lines; /* Lines in the message */
+};
+
+/*
+ * flag bits.
+ */
+
+#define MUSED (1<<0) /* entry is used, but this bit isn't */
+#define MDELETED (1<<1) /* entry has been deleted */
+#define MSAVED (1<<2) /* entry has been saved */
+#define MTOUCH (1<<3) /* entry has been noticed */
+#define MPRESERVE (1<<4) /* keep entry in sys mailbox */
+#define MMARK (1<<5) /* message is marked! */
+#define MODIFY (1<<6) /* message has been modified */
+#define MNEW (1<<7) /* message has never been seen */
+#define MREAD (1<<8) /* message has been read sometime. */
+#define MSTATUS (1<<9) /* message status has changed */
+#define MBOX (1<<10) /* Send this to mbox, regardless */
+
+/*
+ * Given a file address, determine the block number it represents.
+ */
+#define blockof(off) ((int)((off) / 4096))
+#define boffsetof(off) ((int)((off) % 4096))
+#define positionof(block, offset) ((off_t)(block) * 4096 + (offset))
+
+/*
+ * Format of the command description table.
+ * The actual table is declared and initialized
+ * in lex.c
+ */
+struct cmd {
+ const char *c_name; /* Name of command */
+ int (*c_func)(void *); /* Implementor of the command */
+ short c_argtype; /* Type of arglist (see below) */
+ short c_msgflag; /* Required flags of messages */
+ short c_msgmask; /* Relevant flags of messages */
+};
+
+/* Yechh, can't initialize unions */
+
+#define c_minargs c_msgflag /* Minimum argcount for RAWLIST */
+#define c_maxargs c_msgmask /* Max argcount for RAWLIST */
+
+/*
+ * Argument types.
+ */
+
+#define MSGLIST 0 /* Message list type */
+#define STRLIST 1 /* A pure string */
+#define RAWLIST 2 /* Shell string list */
+#define NOLIST 3 /* Just plain 0 */
+#define NDMLIST 4 /* Message list, no defaults */
+
+#define P 040 /* Autoprint dot after command */
+#define I 0100 /* Interactive command bit */
+#define M 0200 /* Legal from send mode bit */
+#define W 0400 /* Illegal when read only bit */
+#define F 01000 /* Is a conditional command */
+#define T 02000 /* Is a transparent command */
+#define R 04000 /* Cannot be called from collect */
+
+/*
+ * Oft-used mask values
+ */
+
+#define MMNORM (MDELETED|MSAVED)/* Look at both save and delete bits */
+#define MMNDEL MDELETED /* Look only at deleted bit */
+
+/*
+ * Structure used to return a break down of a head
+ * line (hats off to Bill Joy!)
+ */
+
+struct headline {
+ char *l_from; /* The name of the sender */
+ char *l_tty; /* His tty string (if any) */
+ char *l_date; /* The entire date string */
+};
+
+#define GTO 1 /* Grab To: line */
+#define GSUBJECT 2 /* Likewise, Subject: line */
+#define GCC 4 /* And the Cc: line */
+#define GBCC 8 /* And also the Bcc: line */
+#define GREPLYTO 0x10 /* And the Reply-To: line */
+#define GINREPLYTO 0x20 /* The In-Reply-To: line */
+#define GMASK (GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO)
+ /* Mask of places from whence */
+
+#define GNL 0x40 /* Print blank line after */
+#define GDEL 0x80 /* Entity removed from list */
+#define GCOMMA 0x100 /* detract puts in commas */
+
+/*
+ * Structure used to pass about the current
+ * state of the user-typed message header.
+ */
+
+struct header {
+ struct name *h_bcc; /* Blind carbon copies */
+ struct name *h_cc; /* Carbon copies string */
+ struct name *h_smopts; /* Sendmail options */
+ struct name *h_to; /* Dynamic "To:" string */
+ char *h_inreplyto; /* Reference */
+ char *h_replyto; /* Reply address */
+ char *h_subject; /* Subject string */
+};
+
+/*
+ * Structure of namelist nodes used in processing
+ * the recipients of mail and aliases and all that
+ * kind of stuff.
+ */
+
+struct name {
+ struct name *n_flink; /* Forward link in list. */
+ struct name *n_blink; /* Backward list link */
+ short n_type; /* From which list it came */
+ char *n_name; /* This fella's name */
+};
+
+/*
+ * Structure of a variable node. All variables are
+ * kept on a singly-linked list of these, rooted by
+ * "variables"
+ */
+
+struct var {
+ struct var *v_link; /* Forward link to next variable */
+ char *v_name; /* The variable's name */
+ char *v_value; /* And it's current value */
+};
+
+struct group {
+ struct group *ge_link; /* Next person in this group */
+ char *ge_name; /* This person's user name */
+};
+
+struct grouphead {
+ struct grouphead *g_link; /* Next grouphead in list */
+ char *g_name; /* Name of this group */
+ struct group *g_list; /* Users in group. */
+};
+
+/*
+ * Structure of the hash table of ignored header fields
+ */
+struct ignoretab {
+ int i_count; /* Number of entries */
+ struct ignore {
+ struct ignore *i_link; /* Next ignored field in bucket */
+ char *i_field; /* This ignored field */
+ } *i_head[HSHSIZE];
+};
+
+/*
+ * Token values returned by the scanner used for argument lists.
+ * Also, sizes of scanner-related things.
+ */
+
+#define TEOL 0 /* End of the command line */
+#define TNUMBER 1 /* A message number */
+#define TDASH 2 /* A simple dash */
+#define TSTRING 3 /* A string (possibly containing -) */
+#define TDOT 4 /* A "." */
+#define TUP 5 /* An "^" */
+#define TDOLLAR 6 /* A "$" */
+#define TSTAR 7 /* A "*" */
+#define TOPEN 8 /* An '(' */
+#define TCLOSE 9 /* A ')' */
+#define TPLUS 10 /* A '+' */
+#define TERROR 11 /* A lexical error */
+
+#define REGDEP 2 /* Maximum regret depth. */
+#define STRINGLEN 1024 /* Maximum length of string token */
+
+/*
+ * Constants for conditional commands. These describe whether
+ * we should be executing stuff or not.
+ */
+
+#define CANY 0 /* Execute in send or receive mode */
+#define CRCV 1 /* Execute in receive mode only */
+#define CSEND 2 /* Execute in send mode only */
+
+/*
+ * Kludges to handle the change from setexit / reset to setjmp / longjmp
+ */
+
+#define setexit() setjmp(srbuf)
+#define reset(x) longjmp(srbuf, x)
+
+/*
+ * Truncate a file to the last character written. This is
+ * useful just before closing an old file that was opened
+ * for read/write.
+ */
+#define trunc(stream) { \
+ (void)fflush(stream); \
+ (void)ftruncate(fileno(stream), ftello(stream)); \
+}
diff --git a/usr.bin/mail/edit.c b/usr.bin/mail/edit.c
new file mode 100644
index 000000000000..1a03c5d4e186
--- /dev/null
+++ b/usr.bin/mail/edit.c
@@ -0,0 +1,208 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Perform message editing functions.
+ */
+
+/*
+ * Edit a message list.
+ */
+int
+editor(void *msgvec)
+{
+
+ return (edit1(msgvec, 'e'));
+}
+
+/*
+ * Invoke the visual editor on a message list.
+ */
+int
+visual(void *msgvec)
+{
+
+ return (edit1(msgvec, 'v'));
+}
+
+/*
+ * Edit a message by writing the message into a funnily-named file
+ * (which should not exist) and forking an editor on it.
+ * We get the editor from the stuff above.
+ */
+int
+edit1(int *msgvec, int type)
+{
+ int c, i;
+ FILE *fp;
+ struct message *mp;
+ off_t size;
+
+ /*
+ * Deal with each message to be edited . . .
+ */
+ for (i = 0; i < msgCount && msgvec[i]; i++) {
+ sig_t sigint;
+
+ if (i > 0) {
+ char buf[100];
+ char *p;
+
+ printf("Edit message %d [ynq]? ", msgvec[i]);
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ break;
+ for (p = buf; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (*p == 'q')
+ break;
+ if (*p == 'n')
+ continue;
+ }
+ dot = mp = &message[msgvec[i] - 1];
+ touch(mp);
+ sigint = signal(SIGINT, SIG_IGN);
+ fp = run_editor(setinput(mp), mp->m_size, type, readonly);
+ if (fp != NULL) {
+ (void)fseeko(otf, (off_t)0, SEEK_END);
+ size = ftello(otf);
+ mp->m_block = blockof(size);
+ mp->m_offset = boffsetof(size);
+ mp->m_size = (long)fsize(fp);
+ mp->m_lines = 0;
+ mp->m_flag |= MODIFY;
+ rewind(fp);
+ while ((c = getc(fp)) != EOF) {
+ if (c == '\n')
+ mp->m_lines++;
+ if (putc(c, otf) == EOF)
+ break;
+ }
+ if (ferror(otf))
+ warnx("/tmp");
+ (void)Fclose(fp);
+ }
+ (void)signal(SIGINT, sigint);
+ }
+ return (0);
+}
+
+/*
+ * Run an editor on the file at "fpp" of "size" bytes,
+ * and return a new file pointer.
+ * Signals must be handled by the caller.
+ * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
+ */
+FILE *
+run_editor(FILE *fp, off_t size, int type, int readonly)
+{
+ FILE *nf = NULL;
+ int t;
+ time_t modtime;
+ char *edit, tempname[PATHSIZE];
+ struct stat statb;
+
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.ReXXXXXXXXXX", tmpdir);
+ if ((t = mkstemp(tempname)) == -1 ||
+ (nf = Fdopen(t, "w")) == NULL) {
+ warn("%s", tempname);
+ goto out;
+ }
+ if (readonly && fchmod(t, 0400) == -1) {
+ warn("%s", tempname);
+ (void)rm(tempname);
+ goto out;
+ }
+ if (size >= 0)
+ while (--size >= 0 && (t = getc(fp)) != EOF)
+ (void)putc(t, nf);
+ else
+ while ((t = getc(fp)) != EOF)
+ (void)putc(t, nf);
+ (void)fflush(nf);
+ if (fstat(fileno(nf), &statb) < 0)
+ modtime = 0;
+ else
+ modtime = statb.st_mtime;
+ if (ferror(nf)) {
+ (void)Fclose(nf);
+ warnx("%s", tempname);
+ (void)rm(tempname);
+ nf = NULL;
+ goto out;
+ }
+ if (Fclose(nf) < 0) {
+ warn("%s", tempname);
+ (void)rm(tempname);
+ nf = NULL;
+ goto out;
+ }
+ nf = NULL;
+ if ((edit = value(type == 'e' ? "EDITOR" : "VISUAL")) == NULL)
+ edit = type == 'e' ? _PATH_EX : _PATH_VI;
+ if (run_command(edit, 0, -1, -1, tempname, NULL) < 0) {
+ (void)rm(tempname);
+ goto out;
+ }
+ /*
+ * If in read only mode or file unchanged, just remove the editor
+ * temporary and return.
+ */
+ if (readonly) {
+ (void)rm(tempname);
+ goto out;
+ }
+ if (stat(tempname, &statb) < 0) {
+ warn("%s", tempname);
+ goto out;
+ }
+ if (modtime == statb.st_mtime) {
+ (void)rm(tempname);
+ goto out;
+ }
+ /*
+ * Now switch to new file.
+ */
+ if ((nf = Fopen(tempname, "a+")) == NULL) {
+ warn("%s", tempname);
+ (void)rm(tempname);
+ goto out;
+ }
+ (void)rm(tempname);
+out:
+ return (nf);
+}
diff --git a/usr.bin/mail/extern.h b/usr.bin/mail/extern.h
new file mode 100644
index 000000000000..efcba2141512
--- /dev/null
+++ b/usr.bin/mail/extern.h
@@ -0,0 +1,250 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+struct name *cat(struct name *, struct name *);
+struct name *delname(struct name *, char *);
+struct name *elide(struct name *);
+struct name *extract(char *, int);
+struct name *gexpand(struct name *, struct grouphead *, int, int);
+struct name *nalloc(char *, int);
+struct name *outof(struct name *, FILE *, struct header *);
+struct name *put(struct name *, struct name *);
+struct name *tailof(struct name *);
+struct name *usermap(struct name *);
+FILE *Fdopen(int, const char *);
+FILE *Fopen(const char *, const char *);
+FILE *Popen(char *, const char *);
+FILE *collect(struct header *, int);
+char *copyin(char *, char **);
+char *detract(struct name *, int);
+char *expand(char *);
+char *getdeadletter(void);
+char *getname(uid_t);
+char *hfield(const char *, struct message *);
+FILE *infix(struct header *, FILE *);
+char *ishfield(char *, char *, const char *);
+char *name1(struct message *, int);
+char *nameof(struct message *, int);
+char *nextword(char *, char *);
+char *readtty(const char *, char *);
+char *reedit(char *);
+FILE *run_editor(FILE *, off_t, int, int);
+char *salloc(int);
+char *savestr(char *);
+FILE *setinput(struct message *);
+char *skin(char *);
+char *skip_comment(char *);
+char *snarf(char *, int *);
+char *username(void);
+char *value(const char *);
+char *vcopy(const char *);
+char *yankword(char *, char *);
+char *yanklogin(char *, char *);
+int Fclose(FILE *);
+int More(void *);
+int Pclose(FILE *);
+int Respond(void *);
+int Type(void *);
+int doRespond(int *);
+int dorespond(int *);
+void alter(char *);
+int alternates(void *);
+void announce(void);
+int append(struct message *, FILE *);
+int argcount(char **);
+void assign(const char *, const char *);
+int bangexp(char *, size_t);
+void brokpipe(int);
+int charcount(char *, int);
+int check(int, int);
+void clob1(int);
+int clobber(void *);
+void close_all_files(void);
+int cmatch(char *, char *);
+void collhup(int);
+void collint(int);
+void collstop(int);
+void commands(void);
+int copycmd(void *v);
+int core(void *);
+int count(struct name *);
+int deletecmd(void *);
+int delm(int *);
+int deltype(void *);
+void demail(void);
+int diction(const void *, const void *);
+int dosh(void *);
+int echo(void *);
+int edit1(int *, int);
+int editor(void *);
+void edstop(void);
+int elsecmd(void *);
+int endifcmd(void *);
+int evalcol(int);
+int execute(char *, int);
+int exwrite(char *, FILE *, int);
+void fail(const char *, const char *);
+int file(void *);
+struct grouphead *
+ findgroup(char *);
+void findmail(char *, char *, int);
+int first(int, int);
+void fixhead(struct header *, struct name *);
+void fmt(const char *, struct name *, FILE *, int);
+int folders(void *);
+int forward(char *, FILE *, char *, int);
+void free_child(int);
+int from(void *);
+off_t fsize(FILE *);
+int getfold(char *, int);
+int gethfield(FILE *, char *, int, char **);
+int getmsglist(char *, int *, int);
+int getrawlist(char *, char **, int);
+uid_t getuserid(char *);
+int grabh(struct header *, int);
+int group(void *);
+void hangup(int);
+int hash(const char *);
+void hdrstop(int);
+int headers(void *);
+int help(void *);
+void holdsigs(void);
+int ifcmd(void *);
+int igcomp(const void *, const void *);
+int igfield(void *);
+int ignore1(char **, struct ignoretab *, const char *);
+int igshow(struct ignoretab *, const char *);
+int inc(void *);
+int incfile(void);
+void intr(int);
+int isdate(char *);
+int isdir(char *);
+int isfileaddr(char *);
+int ishead(char *);
+int isign(const char *, struct ignoretab [2]);
+int isprefix(const char *, const char *);
+void istrncpy(char *, const char *, size_t);
+const struct cmd *
+ lex(char *);
+void load(char *);
+struct var *
+ lookup(const char *);
+int mail(struct name *,
+ struct name *, struct name *, struct name *, char *, char *);
+void mail1(struct header *, int);
+void makemessage(FILE *, int);
+void mark(int);
+int markall(char *, int);
+int matchsender(char *, int);
+int matchfield(char *, int);
+int mboxit(void *);
+int member(char *, struct ignoretab *);
+void mesedit(FILE *, int);
+void mespipe(FILE *, char *);
+int messize(void *);
+int metamess(int, int);
+int more(void *);
+int newfileinfo(int);
+int next(void *);
+int null(void *);
+void parse(char *, struct headline *, char *);
+int pcmdlist(void *);
+int pdot(void *);
+void prepare_child(sigset_t *, int, int);
+int preserve(void *);
+void prettyprint(struct name *);
+void printgroup(char *);
+void printhead(int);
+int puthead(struct header *, FILE *, int);
+int putline(FILE *, char *, int);
+int pversion(void *);
+void quit(void);
+int quitcmd(void *);
+int readline(FILE *, char *, int);
+void register_file(FILE *, int, int);
+void regret(int);
+void relsesigs(void);
+int respond(void *);
+int retfield(void *);
+int rexit(void *);
+int rm(char *);
+int run_command(char *, sigset_t *, int, int, ...);
+int save(void *v);
+int save1(char *, int, const char *, struct ignoretab *);
+void savedeadletter(FILE *);
+int saveigfield(void *);
+int savemail(char *, FILE *);
+int saveretfield(void *);
+int scan(char **);
+void scaninit(void);
+int schdir(void *);
+int screensize(void);
+int scroll(void *);
+int sendmessage(struct message *, FILE *, struct ignoretab *, char *);
+int sendmail(void *);
+int set(void *);
+int setfile(char *);
+void setmsize(int);
+void setptr(FILE *, off_t);
+void setscreensize(void);
+int shell(void *);
+void sigchild(int);
+void sort(char **);
+int source(void *);
+void spreserve(void);
+void sreset(void);
+int start_command(char *, sigset_t *, int, int, ...);
+void statusput(struct message *, FILE *, char *);
+void stop(int);
+int stouch(void *);
+int swrite(void *);
+void tinit(void);
+int top(void *);
+void touch(struct message *);
+void ttyint(int);
+void ttystop(int);
+int type(void *);
+int type1(int *, int, int);
+int undeletecmd(void *);
+void unmark(int);
+char **unpack(struct name *);
+int unread(void *);
+void unregister_file(FILE *);
+int unset(void *);
+int unstack(void);
+void vfree(char *);
+int visual(void *);
+int wait_child(int);
+int wait_command(int);
+int writeback(FILE *);
+
+extern char *__progname;
+extern char *tmpdir;
diff --git a/usr.bin/mail/fio.c b/usr.bin/mail/fio.c
new file mode 100644
index 000000000000..6a31f2a5e361
--- /dev/null
+++ b/usr.bin/mail/fio.c
@@ -0,0 +1,445 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <sys/file.h>
+#include <sys/wait.h>
+
+#include <unistd.h>
+#include <paths.h>
+#include <errno.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * File I/O.
+ */
+
+extern int wait_status;
+
+/*
+ * Set up the input pointers while copying the mail file into /tmp.
+ */
+void
+setptr(FILE *ibuf, off_t offset)
+{
+ int c, count;
+ char *cp, *cp2;
+ struct message this;
+ FILE *mestmp;
+ int maybe, inhead;
+ char linebuf[LINESIZE], pathbuf[PATHSIZE];
+ int omsgCount;
+
+ /* Get temporary file. */
+ (void)snprintf(pathbuf, sizeof(pathbuf), "%s/mail.XXXXXXXXXX", tmpdir);
+ if ((c = mkstemp(pathbuf)) == -1 || (mestmp = Fdopen(c, "r+")) == NULL)
+ err(1, "can't open %s", pathbuf);
+ (void)rm(pathbuf);
+
+ if (offset == 0) {
+ msgCount = 0;
+ } else {
+ /* Seek into the file to get to the new messages */
+ (void)fseeko(ibuf, offset, SEEK_SET);
+ /*
+ * We need to make "offset" a pointer to the end of
+ * the temp file that has the copy of the mail file.
+ * If any messages have been edited, this will be
+ * different from the offset into the mail file.
+ */
+ (void)fseeko(otf, (off_t)0, SEEK_END);
+ offset = ftello(otf);
+ }
+ omsgCount = msgCount;
+ maybe = 1;
+ inhead = 0;
+ this.m_flag = MUSED|MNEW;
+ this.m_size = 0;
+ this.m_lines = 0;
+ this.m_block = 0;
+ this.m_offset = 0;
+ for (;;) {
+ if (fgets(linebuf, sizeof(linebuf), ibuf) == NULL) {
+ if (append(&this, mestmp))
+ errx(1, "temporary file");
+ makemessage(mestmp, omsgCount);
+ return;
+ }
+ count = strlen(linebuf);
+ /*
+ * Transforms lines ending in <CR><LF> to just <LF>.
+ * This allows mail to be able to read Eudora mailboxes.
+ */
+ if (count >= 2 && linebuf[count - 1] == '\n' &&
+ linebuf[count - 2] == '\r') {
+ count--;
+ linebuf[count - 1] = '\n';
+ }
+
+ (void)fwrite(linebuf, sizeof(*linebuf), count, otf);
+ if (ferror(otf))
+ errx(1, "/tmp");
+ if (count)
+ linebuf[count - 1] = '\0';
+ if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
+ msgCount++;
+ if (append(&this, mestmp))
+ errx(1, "temporary file");
+ this.m_flag = MUSED|MNEW;
+ this.m_size = 0;
+ this.m_lines = 0;
+ this.m_block = blockof(offset);
+ this.m_offset = boffsetof(offset);
+ inhead = 1;
+ } else if (linebuf[0] == 0) {
+ inhead = 0;
+ } else if (inhead) {
+ for (cp = linebuf, cp2 = "status";; cp++) {
+ if ((c = *cp2++) == '\0') {
+ while (isspace((unsigned char)*cp++))
+ ;
+ if (cp[-1] != ':')
+ break;
+ while ((c = *cp++) != '\0')
+ if (c == 'R')
+ this.m_flag |= MREAD;
+ else if (c == 'O')
+ this.m_flag &= ~MNEW;
+ inhead = 0;
+ break;
+ }
+ if (*cp != c && *cp != toupper((unsigned char)c))
+ break;
+ }
+ }
+ offset += count;
+ this.m_size += count;
+ this.m_lines++;
+ maybe = linebuf[0] == 0;
+ }
+}
+
+/*
+ * Drop the passed line onto the passed output buffer.
+ * If a write error occurs, return -1, else the count of
+ * characters written, including the newline if requested.
+ */
+int
+putline(FILE *obuf, char *linebuf, int outlf)
+{
+ int c;
+
+ c = strlen(linebuf);
+ (void)fwrite(linebuf, sizeof(*linebuf), c, obuf);
+ if (outlf) {
+ fprintf(obuf, "\n");
+ c++;
+ }
+ if (ferror(obuf))
+ return (-1);
+ return (c);
+}
+
+/*
+ * Read up a line from the specified input into the line
+ * buffer. Return the number of characters read. Do not
+ * include the newline (or carriage return) at the end.
+ */
+int
+readline(FILE *ibuf, char *linebuf, int linesize)
+{
+ int n;
+
+ clearerr(ibuf);
+ if (fgets(linebuf, linesize, ibuf) == NULL)
+ return (-1);
+ n = strlen(linebuf);
+ if (n > 0 && linebuf[n - 1] == '\n')
+ linebuf[--n] = '\0';
+ if (n > 0 && linebuf[n - 1] == '\r')
+ linebuf[--n] = '\0';
+ return (n);
+}
+
+/*
+ * Return a file buffer all ready to read up the
+ * passed message pointer.
+ */
+FILE *
+setinput(struct message *mp)
+{
+
+ (void)fflush(otf);
+ if (fseeko(itf,
+ positionof(mp->m_block, mp->m_offset), SEEK_SET) < 0)
+ err(1, "fseeko");
+ return (itf);
+}
+
+/*
+ * Take the data out of the passed ghost file and toss it into
+ * a dynamically allocated message structure.
+ */
+void
+makemessage(FILE *f, int omsgCount)
+{
+ size_t size;
+ struct message *nmessage;
+
+ size = (msgCount + 1) * sizeof(struct message);
+ nmessage = (struct message *)realloc(message, size);
+ if (nmessage == NULL)
+ errx(1, "Insufficient memory for %d messages\n",
+ msgCount);
+ if (omsgCount == 0 || message == NULL)
+ dot = nmessage;
+ else
+ dot = nmessage + (dot - message);
+ message = nmessage;
+ size -= (omsgCount + 1) * sizeof(struct message);
+ (void)fflush(f);
+ (void)lseek(fileno(f), (off_t)sizeof(*message), 0);
+ if (read(fileno(f), (void *)&message[omsgCount], size) != size)
+ errx(1, "Message temporary file corrupted");
+ message[msgCount].m_size = 0;
+ message[msgCount].m_lines = 0;
+ (void)Fclose(f);
+}
+
+/*
+ * Append the passed message descriptor onto the temp file.
+ * If the write fails, return 1, else 0
+ */
+int
+append(struct message *mp, FILE *f)
+{
+ return (fwrite((char *)mp, sizeof(*mp), 1, f) != 1);
+}
+
+/*
+ * Delete a file, but only if the file is a plain file.
+ */
+int
+rm(char *name)
+{
+ struct stat sb;
+
+ if (stat(name, &sb) < 0)
+ return (-1);
+ if (!S_ISREG(sb.st_mode)) {
+ errno = EISDIR;
+ return (-1);
+ }
+ return (unlink(name));
+}
+
+static int sigdepth; /* depth of holdsigs() */
+static sigset_t nset, oset;
+/*
+ * Hold signals SIGHUP, SIGINT, and SIGQUIT.
+ */
+void
+holdsigs(void)
+{
+
+ if (sigdepth++ == 0) {
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGHUP);
+ (void)sigaddset(&nset, SIGINT);
+ (void)sigaddset(&nset, SIGQUIT);
+ (void)sigprocmask(SIG_BLOCK, &nset, &oset);
+ }
+}
+
+/*
+ * Release signals SIGHUP, SIGINT, and SIGQUIT.
+ */
+void
+relsesigs(void)
+{
+
+ if (--sigdepth == 0)
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+/*
+ * Determine the size of the file possessed by
+ * the passed buffer.
+ */
+off_t
+fsize(FILE *iob)
+{
+ struct stat sbuf;
+
+ if (fstat(fileno(iob), &sbuf) < 0)
+ return (0);
+ return (sbuf.st_size);
+}
+
+/*
+ * Evaluate the string given as a new mailbox name.
+ * Supported meta characters:
+ * % for my system mail box
+ * %user for user's system mail box
+ * # for previous file
+ * & invoker's mbox file
+ * +file file in folder directory
+ * any shell meta character
+ * Return the file name as a dynamic string.
+ */
+char *
+expand(char *name)
+{
+ char xname[PATHSIZE];
+ char cmdbuf[PATHSIZE]; /* also used for file names */
+ int pid, l;
+ char *cp, *sh;
+ int pivec[2];
+ struct stat sbuf;
+
+ /*
+ * The order of evaluation is "%" and "#" expand into constants.
+ * "&" can expand into "+". "+" can expand into shell meta characters.
+ * Shell meta characters expand into constants.
+ * This way, we make no recursive expansion.
+ */
+ switch (*name) {
+ case '%':
+ findmail(name[1] ? name + 1 : myname, xname, sizeof(xname));
+ return (savestr(xname));
+ case '#':
+ if (name[1] != 0)
+ break;
+ if (prevfile[0] == 0) {
+ printf("No previous file\n");
+ return (NULL);
+ }
+ return (savestr(prevfile));
+ case '&':
+ if (name[1] == 0 && (name = value("MBOX")) == NULL)
+ name = "~/mbox";
+ /* fall through */
+ }
+ if (name[0] == '+' && getfold(cmdbuf, sizeof(cmdbuf)) >= 0) {
+ (void)snprintf(xname, sizeof(xname), "%s/%s", cmdbuf, name + 1);
+ name = savestr(xname);
+ }
+ /* catch the most common shell meta character */
+ if (name[0] == '~' && homedir != NULL &&
+ (name[1] == '/' || name[1] == '\0')) {
+ (void)snprintf(xname, sizeof(xname), "%s%s", homedir, name + 1);
+ name = savestr(xname);
+ }
+ if (!strpbrk(name, "~{[*?$`'\"\\"))
+ return (savestr(name));
+ if (pipe(pivec) < 0) {
+ warn("pipe");
+ return (NULL);
+ }
+ (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+ pid = start_command(sh, 0, -1, pivec[1], "-c", cmdbuf, NULL);
+ if (pid < 0) {
+ (void)close(pivec[0]);
+ (void)close(pivec[1]);
+ return (NULL);
+ }
+ (void)close(pivec[1]);
+ l = read(pivec[0], xname, BUFSIZ);
+ (void)close(pivec[0]);
+ if (wait_child(pid) < 0 && WIFSIGNALED(wait_status) &&
+ WTERMSIG(wait_status) != SIGPIPE) {
+ fprintf(stderr, "\"%s\": Expansion failed.\n", name);
+ return (NULL);
+ }
+ if (l < 0) {
+ warn("read");
+ return (NULL);
+ }
+ if (l == 0) {
+ fprintf(stderr, "\"%s\": No match.\n", name);
+ return (NULL);
+ }
+ if (l == BUFSIZ) {
+ fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name);
+ return (NULL);
+ }
+ xname[l] = '\0';
+ for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
+ ;
+ cp[1] = '\0';
+ if (strchr(xname, ' ') && stat(xname, &sbuf) < 0) {
+ fprintf(stderr, "\"%s\": Ambiguous.\n", name);
+ return (NULL);
+ }
+ return (savestr(xname));
+}
+
+/*
+ * Determine the current folder directory name.
+ */
+int
+getfold(char *name, int namelen)
+{
+ char *folder;
+ int copylen;
+
+ if ((folder = value("folder")) == NULL)
+ return (-1);
+ if (*folder == '/')
+ copylen = strlcpy(name, folder, namelen);
+ else
+ copylen = snprintf(name, namelen, "%s/%s",
+ homedir ? homedir : ".", folder);
+ return (copylen < 0 || copylen >= namelen ? (-1) : (0));
+}
+
+/*
+ * Return the name of the dead.letter file.
+ */
+char *
+getdeadletter(void)
+{
+ char *cp;
+
+ if ((cp = value("DEAD")) == NULL || (cp = expand(cp)) == NULL)
+ cp = expand("~/dead.letter");
+ else if (*cp != '/') {
+ char buf[PATHSIZE];
+
+ (void)snprintf(buf, sizeof(buf), "~/%s", cp);
+ cp = expand(buf);
+ }
+ return (cp);
+}
diff --git a/usr.bin/mail/getname.c b/usr.bin/mail/getname.c
new file mode 100644
index 000000000000..85721b1d16ae
--- /dev/null
+++ b/usr.bin/mail/getname.c
@@ -0,0 +1,63 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <pwd.h>
+#include "extern.h"
+
+/* Getname / getuserid for those with hashed passwd data base). */
+
+/*
+ * Search the passwd file for a uid. Return name on success, NULL on failure.
+ */
+char *
+getname(uid_t uid)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwuid(uid)) == NULL)
+ return (NULL);
+ return (pw->pw_name);
+}
+
+/*
+ * Convert the passed name to a user id and return it. Return -1
+ * on error.
+ */
+uid_t
+getuserid(char name[])
+{
+ struct passwd *pw;
+
+ if ((pw = getpwnam(name)) == NULL)
+ return (-1);
+ return (pw->pw_uid);
+}
diff --git a/usr.bin/mail/glob.h b/usr.bin/mail/glob.h
new file mode 100644
index 000000000000..74967b539c73
--- /dev/null
+++ b/usr.bin/mail/glob.h
@@ -0,0 +1,96 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * A bunch of global variable declarations lie herein.
+ * def.h must be included first.
+ */
+
+extern int msgCount; /* Count of messages read in */
+extern int rcvmode; /* True if receiving mail */
+extern int sawcom; /* Set after first command */
+extern char *Tflag; /* -T temp file for netnews */
+extern int senderr; /* An error while checking */
+extern int edit; /* Indicates editing a file */
+extern int readonly; /* Will be unable to rewrite file */
+extern int noreset; /* String resets suspended */
+extern int sourcing; /* Currently reading variant file */
+extern int loading; /* Loading user definitions */
+extern int cond; /* Current state of conditional exc. */
+extern FILE *itf; /* Input temp file buffer */
+extern FILE *otf; /* Output temp file buffer */
+extern int image; /* File descriptor for image of msg */
+extern FILE *input; /* Current command input file */
+extern char mailname[PATHSIZE]; /* Name of current file */
+extern char prevfile[PATHSIZE]; /* Name of previous file */
+extern char *homedir; /* Path name of home directory */
+extern char *myname; /* My login name */
+extern off_t mailsize; /* Size of system mailbox */
+extern int lexnumber; /* Number of TNUMBER from scan() */
+extern char lexstring[STRINGLEN]; /* String from TSTRING, scan() */
+extern int regretp; /* Pointer to TOS of regret tokens */
+extern int regretstack[REGDEP]; /* Stack of regretted tokens */
+extern char *string_stack[REGDEP]; /* Stack of regretted strings */
+extern int numberstack[REGDEP]; /* Stack of regretted numbers */
+extern struct message *dot; /* Pointer to current message */
+extern struct message *message; /* The actual message structure */
+extern struct var *variables[HSHSIZE]; /* Pointer to active var list */
+extern struct grouphead *groups[HSHSIZE];/* Pointer to active groups */
+extern struct ignoretab ignore[2]; /* ignored and retained fields
+ 0 is ignore, 1 is retain */
+extern struct ignoretab saveignore[2]; /* ignored and retained fields
+ on save to folder */
+extern struct ignoretab ignoreall[2]; /* special, ignore all headers */
+extern char **altnames; /* List of alternate names for user */
+extern int debug; /* Debug flag set */
+extern int screenwidth; /* Screen width, or best guess */
+extern int screenheight; /* Screen height, or best guess,
+ for "header" command */
+extern int realscreenheight; /* the real screen height */
+
+#include <setjmp.h>
+
+extern jmp_buf srbuf;
+
+
+/*
+ * The pointers for the string allocation routines,
+ * there are NSPACE independent areas.
+ * The first holds STRINGSIZE bytes, the next
+ * twice as much, and so on.
+ */
+
+#define NSPACE 25 /* Total number of string spaces */
+extern struct strings {
+ char *s_topFree; /* Beginning of this area */
+ char *s_nextFree; /* Next alloctable place here */
+ unsigned s_nleft; /* Number of bytes left here */
+} stringdope[NSPACE];
diff --git a/usr.bin/mail/head.c b/usr.bin/mail/head.c
new file mode 100644
index 000000000000..2e27581c9d5d
--- /dev/null
+++ b/usr.bin/mail/head.c
@@ -0,0 +1,269 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Routines for processing and detecting headlines.
+ */
+
+/*
+ * See if the passed line buffer is a mail header.
+ * Return true if yes. Note the extreme pains to
+ * accommodate all funny formats.
+ */
+int
+ishead(char linebuf[])
+{
+ struct headline hl;
+ char parbuf[BUFSIZ];
+
+ if (strncmp(linebuf, "From ", 5) != 0)
+ return (0);
+ parse(linebuf, &hl, parbuf);
+ if (hl.l_date == NULL) {
+ fail(linebuf, "No date field");
+ return (0);
+ }
+ if (!isdate(hl.l_date)) {
+ fail(linebuf, "Date field not legal date");
+ return (0);
+ }
+ /*
+ * I guess we got it!
+ */
+ return (1);
+}
+
+void
+fail(const char *linebuf __unused, const char *reason __unused)
+{
+
+ /*
+ if (value("debug") == NULL)
+ return;
+ fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
+ */
+}
+
+/*
+ * Split a headline into its useful components.
+ * Copy the line into dynamic string space, then set
+ * pointers into the copied line in the passed headline
+ * structure. Actually, it scans.
+ */
+void
+parse(char line[], struct headline *hl, char pbuf[])
+{
+ char *cp, *sp;
+ char word[LINESIZE];
+
+ hl->l_from = NULL;
+ hl->l_tty = NULL;
+ hl->l_date = NULL;
+ cp = line;
+ sp = pbuf;
+ /*
+ * Skip over "From" first.
+ */
+ cp = nextword(cp, word);
+ /*
+ * Check for missing return-path.
+ */
+ if (isdate(cp)) {
+ hl->l_date = copyin(cp, &sp);
+ return;
+ }
+ cp = nextword(cp, word);
+ if (strlen(word) > 0)
+ hl->l_from = copyin(word, &sp);
+ if (cp != NULL && strncmp(cp, "tty", 3) == 0) {
+ cp = nextword(cp, word);
+ hl->l_tty = copyin(word, &sp);
+ }
+ if (cp != NULL)
+ hl->l_date = copyin(cp, &sp);
+}
+
+/*
+ * Copy the string on the left into the string on the right
+ * and bump the right (reference) string pointer by the length.
+ * Thus, dynamically allocate space in the right string, copying
+ * the left string into it.
+ */
+char *
+copyin(char *src, char **space)
+{
+ char *cp, *top;
+
+ top = cp = *space;
+ while ((*cp++ = *src++) != '\0')
+ ;
+ *space = cp;
+ return (top);
+}
+
+/*
+ * Test to see if the passed string is a ctime(3) generated
+ * date string as documented in the manual. The template
+ * below is used as the criterion of correctness.
+ * Also, we check for a possible trailing time zone using
+ * the tmztype template.
+ *
+ * If the mail file is created by Sys V (Solaris), there are
+ * no seconds in the time. If the mail is created by another
+ * program such as imapd, it might have timezone as
+ * <-|+>nnnn (-0800 for instance) at the end.
+ */
+
+/*
+ * 'A' An upper case char
+ * 'a' A lower case char
+ * ' ' A space
+ * '0' A digit
+ * 'O' A digit or space
+ * 'p' A punctuation char
+ * 'P' A punctuation char or space
+ * ':' A colon
+ * 'N' A new line
+ */
+
+static char *date_formats[] = {
+ "Aaa Aaa O0 00:00:00 0000", /* Mon Jan 01 23:59:59 2001 */
+ "Aaa Aaa O0 00:00:00 AAA 0000", /* Mon Jan 01 23:59:59 PST 2001 */
+ "Aaa Aaa O0 00:00:00 0000 p0000", /* Mon Jan 01 23:59:59 2001 -0800 */
+ "Aaa Aaa O0 00:00 0000", /* Mon Jan 01 23:59 2001 */
+ "Aaa Aaa O0 00:00 AAA 0000", /* Mon Jan 01 23:59 PST 2001 */
+ "Aaa Aaa O0 00:00 0000 p0000", /* Mon Jan 01 23:59 2001 -0800 */
+ NULL
+};
+
+int
+isdate(char date[])
+{
+ int i;
+
+ for(i = 0; date_formats[i] != NULL; i++) {
+ if (cmatch(date, date_formats[i]))
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Match the given string (cp) against the given template (tp).
+ * Return 1 if they match, 0 if they don't
+ */
+int
+cmatch(char *cp, char *tp)
+{
+
+ while (*cp != '\0' && *tp != '\0')
+ switch (*tp++) {
+ case 'a':
+ if (!islower((unsigned char)*cp++))
+ return (0);
+ break;
+ case 'A':
+ if (!isupper((unsigned char)*cp++))
+ return (0);
+ break;
+ case ' ':
+ if (*cp++ != ' ')
+ return (0);
+ break;
+ case '0':
+ if (!isdigit((unsigned char)*cp++))
+ return (0);
+ break;
+ case 'O':
+ if (*cp != ' ' && !isdigit((unsigned char)*cp))
+ return (0);
+ cp++;
+ break;
+ case 'p':
+ if (!ispunct((unsigned char)*cp++))
+ return (0);
+ break;
+ case 'P':
+ if (*cp != ' ' && !ispunct((unsigned char)*cp))
+ return (0);
+ cp++;
+ break;
+ case ':':
+ if (*cp++ != ':')
+ return (0);
+ break;
+ case 'N':
+ if (*cp++ != '\n')
+ return (0);
+ break;
+ }
+ if (*cp != '\0' || *tp != '\0')
+ return (0);
+ return (1);
+}
+
+/*
+ * Collect a liberal (space, tab delimited) word into the word buffer
+ * passed. Also, return a pointer to the next word following that,
+ * or NULL if none follow.
+ */
+char *
+nextword(char *wp, char *wbuf)
+{
+ int c;
+
+ if (wp == NULL) {
+ *wbuf = '\0';
+ return (NULL);
+ }
+ while ((c = *wp++) != '\0' && c != ' ' && c != '\t') {
+ *wbuf++ = c;
+ if (c == '"') {
+ while ((c = *wp++) != '\0' && c != '"')
+ *wbuf++ = c;
+ if (c == '"')
+ *wbuf++ = c;
+ else
+ wp--;
+ }
+ }
+ *wbuf = '\0';
+ for (; c == ' ' || c == '\t'; c = *wp++)
+ ;
+ if (c == '\0')
+ return (NULL);
+ return (wp - 1);
+}
diff --git a/usr.bin/mail/lex.c b/usr.bin/mail/lex.c
new file mode 100644
index 000000000000..1043dd2d4706
--- /dev/null
+++ b/usr.bin/mail/lex.c
@@ -0,0 +1,693 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <errno.h>
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Lexical processing of commands.
+ */
+
+static const char *prompt = "& ";
+
+extern const struct cmd cmdtab[];
+extern const char *version;
+
+/*
+ * Set up editing on the given file name.
+ * If the first character of name is %, we are considered to be
+ * editing the file, otherwise we are reading our mail which has
+ * signficance for mbox and so forth.
+ *
+ * If the -e option is being passed to mail, this function has a
+ * tri-state return code: -1 on error, 0 on no mail, 1 if there is
+ * mail.
+ */
+int
+setfile(char *name)
+{
+ FILE *ibuf;
+ int checkmode, i, fd;
+ struct stat stb;
+ char isedit = *name != '%' || getuserid(myname) != getuid();
+ char *who = name[1] ? name + 1 : myname;
+ char tempname[PATHSIZE];
+ static int shudclob;
+
+ checkmode = value("checkmode") != NULL;
+ if ((name = expand(name)) == NULL)
+ return (-1);
+
+ if ((ibuf = Fopen(name, "r")) == NULL) {
+ if (!isedit && errno == ENOENT)
+ goto nomail;
+ warn("%s", name);
+ return (-1);
+ }
+
+ if (fstat(fileno(ibuf), &stb) < 0) {
+ warn("fstat");
+ (void)Fclose(ibuf);
+ return (-1);
+ }
+
+ if (S_ISDIR(stb.st_mode) || !S_ISREG(stb.st_mode)) {
+ (void)Fclose(ibuf);
+ errno = S_ISDIR(stb.st_mode) ? EISDIR : EINVAL;
+ warn("%s", name);
+ return (-1);
+ }
+
+ /*
+ * Looks like all will be well. We must now relinquish our
+ * hold on the current set of stuff. Must hold signals
+ * while we are reading the new file, else we will ruin
+ * the message[] data structure.
+ */
+
+ holdsigs();
+ if (shudclob)
+ quit();
+
+ /*
+ * Copy the messages into /tmp
+ * and set pointers.
+ */
+
+ readonly = 0;
+ if ((i = open(name, 1)) < 0)
+ readonly++;
+ else
+ (void)close(i);
+ if (shudclob) {
+ (void)fclose(itf);
+ (void)fclose(otf);
+ }
+ shudclob = 1;
+ edit = isedit;
+ strlcpy(prevfile, mailname, sizeof(prevfile));
+ if (name != mailname)
+ strlcpy(mailname, name, sizeof(mailname));
+ mailsize = fsize(ibuf);
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.RxXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 || (otf = fdopen(fd, "w")) == NULL)
+ err(1, "%s", tempname);
+ (void)fcntl(fileno(otf), F_SETFD, 1);
+ if ((itf = fopen(tempname, "r")) == NULL)
+ err(1, "%s", tempname);
+ (void)fcntl(fileno(itf), F_SETFD, 1);
+ (void)rm(tempname);
+ setptr(ibuf, 0);
+ setmsize(msgCount);
+ /*
+ * New mail may have arrived while we were reading
+ * the mail file, so reset mailsize to be where
+ * we really are in the file...
+ */
+ mailsize = ftello(ibuf);
+ (void)Fclose(ibuf);
+ relsesigs();
+ sawcom = 0;
+
+ if ((checkmode || !edit) && msgCount == 0) {
+nomail:
+ if (!checkmode) {
+ fprintf(stderr, "No mail for %s\n", who);
+ return (-1);
+ } else
+ return (0);
+ }
+ return (checkmode ? 1 : 0);
+}
+
+/*
+ * Incorporate any new mail that has arrived since we first
+ * started reading mail.
+ */
+int
+incfile(void)
+{
+ off_t newsize;
+ int omsgCount = msgCount;
+ FILE *ibuf;
+
+ ibuf = Fopen(mailname, "r");
+ if (ibuf == NULL)
+ return (-1);
+ holdsigs();
+ newsize = fsize(ibuf);
+ if (newsize == 0)
+ return (-1); /* mail box is now empty??? */
+ if (newsize < mailsize)
+ return (-1); /* mail box has shrunk??? */
+ if (newsize == mailsize)
+ return (0); /* no new mail */
+ setptr(ibuf, mailsize);
+ setmsize(msgCount);
+ mailsize = ftello(ibuf);
+ (void)Fclose(ibuf);
+ relsesigs();
+ return (msgCount - omsgCount);
+}
+
+static int *msgvec;
+static int reset_on_stop; /* do a reset() if stopped */
+
+/*
+ * Interpret user commands one by one. If standard input is not a tty,
+ * print no prompt.
+ */
+void
+commands(void)
+{
+ int n, eofloop = 0;
+ char linebuf[LINESIZE];
+
+ if (!sourcing) {
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGINT, intr);
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGHUP, hangup);
+ (void)signal(SIGTSTP, stop);
+ (void)signal(SIGTTOU, stop);
+ (void)signal(SIGTTIN, stop);
+ }
+ setexit();
+ for (;;) {
+ /*
+ * Print the prompt, if needed. Clear out
+ * string space, and flush the output.
+ */
+ if (!sourcing && value("interactive") != NULL) {
+ if ((value("autoinc") != NULL) && (incfile() > 0))
+ printf("New mail has arrived.\n");
+ reset_on_stop = 1;
+ printf("%s", prompt);
+ }
+ (void)fflush(stdout);
+ sreset();
+ /*
+ * Read a line of commands from the current input
+ * and handle end of file specially.
+ */
+ n = 0;
+ for (;;) {
+ if (readline(input, &linebuf[n], LINESIZE - n) < 0) {
+ if (n == 0)
+ n = -1;
+ break;
+ }
+ if ((n = strlen(linebuf)) == 0)
+ break;
+ n--;
+ if (linebuf[n] != '\\')
+ break;
+ linebuf[n++] = ' ';
+ }
+ reset_on_stop = 0;
+ if (n < 0) {
+ /* eof */
+ if (loading)
+ break;
+ if (sourcing) {
+ unstack();
+ continue;
+ }
+ if (value("interactive") != NULL &&
+ value("ignoreeof") != NULL &&
+ ++eofloop < 25) {
+ printf("Use \"quit\" to quit.\n");
+ continue;
+ }
+ break;
+ }
+ eofloop = 0;
+ if (execute(linebuf, 0))
+ break;
+ }
+}
+
+/*
+ * Execute a single command.
+ * Command functions return 0 for success, 1 for error, and -1
+ * for abort. A 1 or -1 aborts a load or source. A -1 aborts
+ * the interactive command loop.
+ * Contxt is non-zero if called while composing mail.
+ */
+int
+execute(char linebuf[], int contxt)
+{
+ char word[LINESIZE];
+ char *arglist[MAXARGC];
+ const struct cmd *com;
+ char *cp, *cp2;
+ int c, muvec[2];
+ int e = 1;
+
+ /*
+ * Strip the white space away from the beginning
+ * of the command, then scan out a word, which
+ * consists of anything except digits and white space.
+ *
+ * Handle ! escapes differently to get the correct
+ * lexical conventions.
+ */
+
+ for (cp = linebuf; isspace((unsigned char)*cp); cp++)
+ ;
+ if (*cp == '!') {
+ if (sourcing) {
+ printf("Can't \"!\" while sourcing\n");
+ goto out;
+ }
+ shell(cp+1);
+ return (0);
+ }
+ cp2 = word;
+ while (*cp != '\0' && strchr(" \t0123456789$^.:/-+*'\"", *cp) == NULL)
+ *cp2++ = *cp++;
+ *cp2 = '\0';
+
+ /*
+ * Look up the command; if not found, bitch.
+ * Normally, a blank command would map to the
+ * first command in the table; while sourcing,
+ * however, we ignore blank lines to eliminate
+ * confusion.
+ */
+
+ if (sourcing && *word == '\0')
+ return (0);
+ com = lex(word);
+ if (com == NULL) {
+ printf("Unknown command: \"%s\"\n", word);
+ goto out;
+ }
+
+ /*
+ * See if we should execute the command -- if a conditional
+ * we always execute it, otherwise, check the state of cond.
+ */
+
+ if ((com->c_argtype & F) == 0)
+ if ((cond == CRCV && !rcvmode) || (cond == CSEND && rcvmode))
+ return (0);
+
+ /*
+ * Process the arguments to the command, depending
+ * on the type he expects. Default to an error.
+ * If we are sourcing an interactive command, it's
+ * an error.
+ */
+
+ if (!rcvmode && (com->c_argtype & M) == 0) {
+ printf("May not execute \"%s\" while sending\n",
+ com->c_name);
+ goto out;
+ }
+ if (sourcing && com->c_argtype & I) {
+ printf("May not execute \"%s\" while sourcing\n",
+ com->c_name);
+ goto out;
+ }
+ if (readonly && com->c_argtype & W) {
+ printf("May not execute \"%s\" -- message file is read only\n",
+ com->c_name);
+ goto out;
+ }
+ if (contxt && com->c_argtype & R) {
+ printf("Cannot recursively invoke \"%s\"\n", com->c_name);
+ goto out;
+ }
+ switch (com->c_argtype & ~(F|P|I|M|T|W|R)) {
+ case MSGLIST:
+ /*
+ * A message list defaulting to nearest forward
+ * legal message.
+ */
+ if (msgvec == 0) {
+ printf("Illegal use of \"message list\"\n");
+ break;
+ }
+ if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0)
+ break;
+ if (c == 0) {
+ *msgvec = first(com->c_msgflag, com->c_msgmask);
+ msgvec[1] = 0;
+ }
+ if (*msgvec == 0) {
+ printf("No applicable messages\n");
+ break;
+ }
+ e = (*com->c_func)(msgvec);
+ break;
+
+ case NDMLIST:
+ /*
+ * A message list with no defaults, but no error
+ * if none exist.
+ */
+ if (msgvec == 0) {
+ printf("Illegal use of \"message list\"\n");
+ break;
+ }
+ if (getmsglist(cp, msgvec, com->c_msgflag) < 0)
+ break;
+ e = (*com->c_func)(msgvec);
+ break;
+
+ case STRLIST:
+ /*
+ * Just the straight string, with
+ * leading blanks removed.
+ */
+ while (isspace((unsigned char)*cp))
+ cp++;
+ e = (*com->c_func)(cp);
+ break;
+
+ case RAWLIST:
+ /*
+ * A vector of strings, in shell style.
+ */
+ if ((c = getrawlist(cp, arglist,
+ sizeof(arglist) / sizeof(*arglist))) < 0)
+ break;
+ if (c < com->c_minargs) {
+ printf("%s requires at least %d arg(s)\n",
+ com->c_name, com->c_minargs);
+ break;
+ }
+ if (c > com->c_maxargs) {
+ printf("%s takes no more than %d arg(s)\n",
+ com->c_name, com->c_maxargs);
+ break;
+ }
+ e = (*com->c_func)(arglist);
+ break;
+
+ case NOLIST:
+ /*
+ * Just the constant zero, for exiting,
+ * eg.
+ */
+ e = (*com->c_func)(0);
+ break;
+
+ default:
+ errx(1, "Unknown argtype");
+ }
+
+out:
+ /*
+ * Exit the current source file on
+ * error.
+ */
+ if (e) {
+ if (e < 0)
+ return (1);
+ if (loading)
+ return (1);
+ if (sourcing)
+ unstack();
+ return (0);
+ }
+ if (com == NULL)
+ return (0);
+ if (value("autoprint") != NULL && com->c_argtype & P)
+ if ((dot->m_flag & MDELETED) == 0) {
+ muvec[0] = dot - &message[0] + 1;
+ muvec[1] = 0;
+ type(muvec);
+ }
+ if (!sourcing && (com->c_argtype & T) == 0)
+ sawcom = 1;
+ return (0);
+}
+
+/*
+ * Set the size of the message vector used to construct argument
+ * lists to message list functions.
+ */
+void
+setmsize(int sz)
+{
+
+ if (msgvec != NULL)
+ (void)free(msgvec);
+ msgvec = calloc((unsigned)(sz + 1), sizeof(*msgvec));
+}
+
+/*
+ * Find the correct command in the command table corresponding
+ * to the passed command "word"
+ */
+
+const struct cmd *
+lex(char word[])
+{
+ const struct cmd *cp;
+
+ /*
+ * ignore trailing chars after `#'
+ *
+ * lines with beginning `#' are comments
+ * spaces before `#' are ignored in execute()
+ */
+
+ if (*word == '#')
+ *(word+1) = '\0';
+
+
+ for (cp = &cmdtab[0]; cp->c_name != NULL; cp++)
+ if (isprefix(word, cp->c_name))
+ return (cp);
+ return (NULL);
+}
+
+/*
+ * Determine if as1 is a valid prefix of as2.
+ * Return true if yep.
+ */
+int
+isprefix(const char *as1, const char *as2)
+{
+ const char *s1, *s2;
+
+ s1 = as1;
+ s2 = as2;
+ while (*s1++ == *s2)
+ if (*s2++ == '\0')
+ return (1);
+ return (*--s1 == '\0');
+}
+
+/*
+ * The following gets called on receipt of an interrupt. This is
+ * to abort printout of a command, mainly.
+ * Dispatching here when command() is inactive crashes rcv.
+ * Close all open files except 0, 1, 2, and the temporary.
+ * Also, unstack all source files.
+ */
+
+static int inithdr; /* am printing startup headers */
+
+void
+intr(int s __unused)
+{
+
+ noreset = 0;
+ if (!inithdr)
+ sawcom++;
+ inithdr = 0;
+ while (sourcing)
+ unstack();
+
+ close_all_files();
+
+ if (image >= 0) {
+ (void)close(image);
+ image = -1;
+ }
+ fprintf(stderr, "Interrupt\n");
+ reset(0);
+}
+
+/*
+ * When we wake up after ^Z, reprint the prompt.
+ */
+void
+stop(int s)
+{
+ sig_t old_action = signal(s, SIG_DFL);
+ sigset_t nset;
+
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, s);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+ (void)kill(0, s);
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ (void)signal(s, old_action);
+ if (reset_on_stop) {
+ reset_on_stop = 0;
+ reset(0);
+ }
+}
+
+/*
+ * Branch here on hangup signal and simulate "exit".
+ */
+void
+hangup(int s __unused)
+{
+
+ /* nothing to do? */
+ exit(1);
+}
+
+/*
+ * Announce the presence of the current Mail version,
+ * give the message count, and print a header listing.
+ */
+void
+announce(void)
+{
+ int vec[2], mdot;
+
+ mdot = newfileinfo(0);
+ vec[0] = mdot;
+ vec[1] = 0;
+ dot = &message[mdot - 1];
+ if (msgCount > 0 && value("noheader") == NULL) {
+ inithdr++;
+ headers(vec);
+ inithdr = 0;
+ }
+}
+
+/*
+ * Announce information about the file we are editing.
+ * Return a likely place to set dot.
+ */
+int
+newfileinfo(int omsgCount)
+{
+ struct message *mp;
+ int u, n, mdot, d, s;
+ char fname[PATHSIZE+1], zname[PATHSIZE+1], *ename;
+
+ for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++)
+ if (mp->m_flag & MNEW)
+ break;
+ if (mp >= &message[msgCount])
+ for (mp = &message[omsgCount]; mp < &message[msgCount]; mp++)
+ if ((mp->m_flag & MREAD) == 0)
+ break;
+ if (mp < &message[msgCount])
+ mdot = mp - &message[0] + 1;
+ else
+ mdot = omsgCount + 1;
+ s = d = 0;
+ for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) {
+ if (mp->m_flag & MNEW)
+ n++;
+ if ((mp->m_flag & MREAD) == 0)
+ u++;
+ if (mp->m_flag & MDELETED)
+ d++;
+ if (mp->m_flag & MSAVED)
+ s++;
+ }
+ ename = mailname;
+ if (getfold(fname, sizeof(fname) - 1) >= 0) {
+ strcat(fname, "/");
+ if (strncmp(fname, mailname, strlen(fname)) == 0) {
+ (void)snprintf(zname, sizeof(zname), "+%s",
+ mailname + strlen(fname));
+ ename = zname;
+ }
+ }
+ printf("\"%s\": ", ename);
+ if (msgCount == 1)
+ printf("1 message");
+ else
+ printf("%d messages", msgCount);
+ if (n > 0)
+ printf(" %d new", n);
+ if (u-n > 0)
+ printf(" %d unread", u);
+ if (d > 0)
+ printf(" %d deleted", d);
+ if (s > 0)
+ printf(" %d saved", s);
+ if (readonly)
+ printf(" [Read only]");
+ printf("\n");
+ return (mdot);
+}
+
+/*
+ * Print the current version number.
+ */
+
+int
+pversion(void *arg __unused)
+{
+
+ printf("Version %s\n", version);
+ return (0);
+}
+
+/*
+ * Load a file of user definitions.
+ */
+void
+load(char *name)
+{
+ FILE *in, *oldin;
+
+ if ((in = Fopen(name, "r")) == NULL)
+ return;
+ oldin = input;
+ input = in;
+ loading = 1;
+ sourcing = 1;
+ commands();
+ loading = 0;
+ sourcing = 0;
+ input = oldin;
+ (void)Fclose(in);
+}
diff --git a/usr.bin/mail/list.c b/usr.bin/mail/list.c
new file mode 100644
index 000000000000..6d15a65e7662
--- /dev/null
+++ b/usr.bin/mail/list.c
@@ -0,0 +1,810 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <ctype.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Message list handling.
+ */
+
+/*
+ * Convert the user string of message numbers and
+ * store the numbers into vector.
+ *
+ * Returns the count of messages picked up or -1 on error.
+ */
+int
+getmsglist(char *buf, int *vector, int flags)
+{
+ int *ip;
+ struct message *mp;
+
+ if (msgCount == 0) {
+ *vector = 0;
+ return (0);
+ }
+ if (markall(buf, flags) < 0)
+ return (-1);
+ ip = vector;
+ for (mp = &message[0]; mp < &message[msgCount]; mp++)
+ if (mp->m_flag & MMARK)
+ *ip++ = mp - &message[0] + 1;
+ *ip = 0;
+ return (ip - vector);
+}
+
+/*
+ * Mark all messages that the user wanted from the command
+ * line in the message structure. Return 0 on success, -1
+ * on error.
+ */
+
+/*
+ * Bit values for colon modifiers.
+ */
+
+#define CMNEW 01 /* New messages */
+#define CMOLD 02 /* Old messages */
+#define CMUNREAD 04 /* Unread messages */
+#define CMDELETED 010 /* Deleted messages */
+#define CMREAD 020 /* Read messages */
+
+/*
+ * The following table describes the letters which can follow
+ * the colon and gives the corresponding modifier bit.
+ */
+
+static struct coltab {
+ char co_char; /* What to find past : */
+ int co_bit; /* Associated modifier bit */
+ int co_mask; /* m_status bits to mask */
+ int co_equal; /* ... must equal this */
+} coltab[] = {
+ { 'n', CMNEW, MNEW, MNEW },
+ { 'o', CMOLD, MNEW, 0 },
+ { 'u', CMUNREAD, MREAD, 0 },
+ { 'd', CMDELETED, MDELETED, MDELETED},
+ { 'r', CMREAD, MREAD, MREAD },
+ { 0, 0, 0, 0 }
+};
+
+static int lastcolmod;
+
+int
+markall(char buf[], int f)
+{
+ char **np;
+ int i;
+ struct message *mp;
+ char *namelist[NMLSIZE], *bufp;
+ int tok, beg, mc, star, other, valdot, colmod, colresult;
+
+ valdot = dot - &message[0] + 1;
+ colmod = 0;
+ for (i = 1; i <= msgCount; i++)
+ unmark(i);
+ bufp = buf;
+ mc = 0;
+ np = &namelist[0];
+ scaninit();
+ tok = scan(&bufp);
+ star = 0;
+ other = 0;
+ beg = 0;
+ while (tok != TEOL) {
+ switch (tok) {
+ case TNUMBER:
+number:
+ if (star) {
+ printf("No numbers mixed with *\n");
+ return (-1);
+ }
+ mc++;
+ other++;
+ if (beg != 0) {
+ if (check(lexnumber, f))
+ return (-1);
+ for (i = beg; i <= lexnumber; i++)
+ if (f == MDELETED || (message[i - 1].m_flag & MDELETED) == 0)
+ mark(i);
+ beg = 0;
+ break;
+ }
+ beg = lexnumber;
+ if (check(beg, f))
+ return (-1);
+ tok = scan(&bufp);
+ regret(tok);
+ if (tok != TDASH) {
+ mark(beg);
+ beg = 0;
+ }
+ break;
+
+ case TPLUS:
+ if (beg != 0) {
+ printf("Non-numeric second argument\n");
+ return (-1);
+ }
+ i = valdot;
+ do {
+ i++;
+ if (i > msgCount) {
+ printf("Referencing beyond EOF\n");
+ return (-1);
+ }
+ } while ((message[i - 1].m_flag & MDELETED) != f);
+ mark(i);
+ break;
+
+ case TDASH:
+ if (beg == 0) {
+ i = valdot;
+ do {
+ i--;
+ if (i <= 0) {
+ printf("Referencing before 1\n");
+ return (-1);
+ }
+ } while ((message[i - 1].m_flag & MDELETED) != f);
+ mark(i);
+ }
+ break;
+
+ case TSTRING:
+ if (beg != 0) {
+ printf("Non-numeric second argument\n");
+ return (-1);
+ }
+ other++;
+ if (lexstring[0] == ':') {
+ colresult = evalcol(lexstring[1]);
+ if (colresult == 0) {
+ printf("Unknown colon modifier \"%s\"\n",
+ lexstring);
+ return (-1);
+ }
+ colmod |= colresult;
+ }
+ else
+ *np++ = savestr(lexstring);
+ break;
+
+ case TDOLLAR:
+ case TUP:
+ case TDOT:
+ lexnumber = metamess(lexstring[0], f);
+ if (lexnumber == -1)
+ return (-1);
+ goto number;
+
+ case TSTAR:
+ if (other) {
+ printf("Can't mix \"*\" with anything\n");
+ return (-1);
+ }
+ star++;
+ break;
+
+ case TERROR:
+ return (-1);
+ }
+ tok = scan(&bufp);
+ }
+ lastcolmod = colmod;
+ *np = NULL;
+ mc = 0;
+ if (star) {
+ for (i = 0; i < msgCount; i++)
+ if ((message[i].m_flag & MDELETED) == f) {
+ mark(i+1);
+ mc++;
+ }
+ if (mc == 0) {
+ printf("No applicable messages.\n");
+ return (-1);
+ }
+ return (0);
+ }
+
+ /*
+ * If no numbers were given, mark all of the messages,
+ * so that we can unmark any whose sender was not selected
+ * if any user names were given.
+ */
+
+ if ((np > namelist || colmod != 0) && mc == 0)
+ for (i = 1; i <= msgCount; i++)
+ if ((message[i-1].m_flag & MDELETED) == f)
+ mark(i);
+
+ /*
+ * If any names were given, go through and eliminate any
+ * messages whose senders were not requested.
+ */
+
+ if (np > namelist) {
+ for (i = 1; i <= msgCount; i++) {
+ for (mc = 0, np = &namelist[0]; *np != NULL; np++)
+ if (**np == '/') {
+ if (matchfield(*np, i)) {
+ mc++;
+ break;
+ }
+ }
+ else {
+ if (matchsender(*np, i)) {
+ mc++;
+ break;
+ }
+ }
+ if (mc == 0)
+ unmark(i);
+ }
+
+ /*
+ * Make sure we got some decent messages.
+ */
+
+ mc = 0;
+ for (i = 1; i <= msgCount; i++)
+ if (message[i-1].m_flag & MMARK) {
+ mc++;
+ break;
+ }
+ if (mc == 0) {
+ printf("No applicable messages from {%s",
+ namelist[0]);
+ for (np = &namelist[1]; *np != NULL; np++)
+ printf(", %s", *np);
+ printf("}\n");
+ return (-1);
+ }
+ }
+
+ /*
+ * If any colon modifiers were given, go through and
+ * unmark any messages which do not satisfy the modifiers.
+ */
+
+ if (colmod != 0) {
+ for (i = 1; i <= msgCount; i++) {
+ struct coltab *colp;
+
+ mp = &message[i - 1];
+ for (colp = &coltab[0]; colp->co_char != '\0'; colp++)
+ if (colp->co_bit & colmod)
+ if ((mp->m_flag & colp->co_mask)
+ != colp->co_equal)
+ unmark(i);
+
+ }
+ for (mp = &message[0]; mp < &message[msgCount]; mp++)
+ if (mp->m_flag & MMARK)
+ break;
+ if (mp >= &message[msgCount]) {
+ struct coltab *colp;
+
+ printf("No messages satisfy");
+ for (colp = &coltab[0]; colp->co_char != '\0'; colp++)
+ if (colp->co_bit & colmod)
+ printf(" :%c", colp->co_char);
+ printf("\n");
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Turn the character after a colon modifier into a bit
+ * value.
+ */
+int
+evalcol(int col)
+{
+ struct coltab *colp;
+
+ if (col == 0)
+ return (lastcolmod);
+ for (colp = &coltab[0]; colp->co_char != '\0'; colp++)
+ if (colp->co_char == col)
+ return (colp->co_bit);
+ return (0);
+}
+
+/*
+ * Check the passed message number for legality and proper flags.
+ * If f is MDELETED, then either kind will do. Otherwise, the message
+ * has to be undeleted.
+ */
+int
+check(int mesg, int f)
+{
+ struct message *mp;
+
+ if (mesg < 1 || mesg > msgCount) {
+ printf("%d: Invalid message number\n", mesg);
+ return (-1);
+ }
+ mp = &message[mesg-1];
+ if (f != MDELETED && (mp->m_flag & MDELETED) != 0) {
+ printf("%d: Inappropriate message\n", mesg);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Scan out the list of string arguments, shell style
+ * for a RAWLIST.
+ */
+int
+getrawlist(char line[], char **argv, int argc)
+{
+ char c, *cp, *cp2, quotec;
+ int argn;
+ char *linebuf;
+ size_t linebufsize = BUFSIZ;
+
+ if ((linebuf = malloc(linebufsize)) == NULL)
+ err(1, "Out of memory");
+
+ argn = 0;
+ cp = line;
+ for (;;) {
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (*cp == '\0')
+ break;
+ if (argn >= argc - 1) {
+ printf(
+ "Too many elements in the list; excess discarded.\n");
+ break;
+ }
+ cp2 = linebuf;
+ quotec = '\0';
+ while ((c = *cp) != '\0') {
+ /* Allocate more space if necessary */
+ if (cp2 - linebuf == linebufsize - 1) {
+ linebufsize += BUFSIZ;
+ if ((linebuf = realloc(linebuf, linebufsize)) == NULL)
+ err(1, "Out of memory");
+ cp2 = linebuf + linebufsize - BUFSIZ - 1;
+ }
+ cp++;
+ if (quotec != '\0') {
+ if (c == quotec)
+ quotec = '\0';
+ else if (c == '\\')
+ switch (c = *cp++) {
+ case '\0':
+ *cp2++ = '\\';
+ cp--;
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c -= '0';
+ if (*cp >= '0' && *cp <= '7')
+ c = c * 8 + *cp++ - '0';
+ if (*cp >= '0' && *cp <= '7')
+ c = c * 8 + *cp++ - '0';
+ *cp2++ = c;
+ break;
+ case 'b':
+ *cp2++ = '\b';
+ break;
+ case 'f':
+ *cp2++ = '\f';
+ break;
+ case 'n':
+ *cp2++ = '\n';
+ break;
+ case 'r':
+ *cp2++ = '\r';
+ break;
+ case 't':
+ *cp2++ = '\t';
+ break;
+ case 'v':
+ *cp2++ = '\v';
+ break;
+ default:
+ *cp2++ = c;
+ }
+ else if (c == '^') {
+ c = *cp++;
+ if (c == '?')
+ *cp2++ = '\177';
+ /* null doesn't show up anyway */
+ else if ((c >= 'A' && c <= '_') ||
+ (c >= 'a' && c <= 'z'))
+ *cp2++ = c & 037;
+ else {
+ *cp2++ = '^';
+ cp--;
+ }
+ } else
+ *cp2++ = c;
+ } else if (c == '"' || c == '\'')
+ quotec = c;
+ else if (c == ' ' || c == '\t')
+ break;
+ else
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+ argv[argn++] = savestr(linebuf);
+ }
+ argv[argn] = NULL;
+ (void)free(linebuf);
+ return (argn);
+}
+
+/*
+ * scan out a single lexical item and return its token number,
+ * updating the string pointer passed **p. Also, store the value
+ * of the number or string scanned in lexnumber or lexstring as
+ * appropriate. In any event, store the scanned `thing' in lexstring.
+ */
+
+static struct lex {
+ char l_char;
+ char l_token;
+} singles[] = {
+ { '$', TDOLLAR },
+ { '.', TDOT },
+ { '^', TUP },
+ { '*', TSTAR },
+ { '-', TDASH },
+ { '+', TPLUS },
+ { '(', TOPEN },
+ { ')', TCLOSE },
+ { 0, 0 }
+};
+
+int
+scan(char **sp)
+{
+ char *cp, *cp2;
+ int c;
+ struct lex *lp;
+ int quotec;
+
+ if (regretp >= 0) {
+ strcpy(lexstring, string_stack[regretp]);
+ lexnumber = numberstack[regretp];
+ return (regretstack[regretp--]);
+ }
+ cp = *sp;
+ cp2 = lexstring;
+ c = *cp++;
+
+ /*
+ * strip away leading white space.
+ */
+
+ while (c == ' ' || c == '\t')
+ c = *cp++;
+
+ /*
+ * If no characters remain, we are at end of line,
+ * so report that.
+ */
+
+ if (c == '\0') {
+ *sp = --cp;
+ return (TEOL);
+ }
+
+ /*
+ * If the leading character is a digit, scan
+ * the number and convert it on the fly.
+ * Return TNUMBER when done.
+ */
+
+ if (isdigit((unsigned char)c)) {
+ lexnumber = 0;
+ while (isdigit((unsigned char)c)) {
+ lexnumber = lexnumber*10 + c - '0';
+ *cp2++ = c;
+ c = *cp++;
+ }
+ *cp2 = '\0';
+ *sp = --cp;
+ return (TNUMBER);
+ }
+
+ /*
+ * Check for single character tokens; return such
+ * if found.
+ */
+
+ for (lp = &singles[0]; lp->l_char != '\0'; lp++)
+ if (c == lp->l_char) {
+ lexstring[0] = c;
+ lexstring[1] = '\0';
+ *sp = cp;
+ return (lp->l_token);
+ }
+
+ /*
+ * We've got a string! Copy all the characters
+ * of the string into lexstring, until we see
+ * a null, space, or tab.
+ * If the lead character is a " or ', save it
+ * and scan until you get another.
+ */
+
+ quotec = 0;
+ if (c == '\'' || c == '"') {
+ quotec = c;
+ c = *cp++;
+ }
+ while (c != '\0') {
+ if (c == quotec) {
+ cp++;
+ break;
+ }
+ if (quotec == 0 && (c == ' ' || c == '\t'))
+ break;
+ if (cp2 - lexstring < STRINGLEN-1)
+ *cp2++ = c;
+ c = *cp++;
+ }
+ if (quotec && c == '\0') {
+ fprintf(stderr, "Missing %c\n", quotec);
+ return (TERROR);
+ }
+ *sp = --cp;
+ *cp2 = '\0';
+ return (TSTRING);
+}
+
+/*
+ * Unscan the named token by pushing it onto the regret stack.
+ */
+void
+regret(int token)
+{
+ if (++regretp >= REGDEP)
+ errx(1, "Too many regrets");
+ regretstack[regretp] = token;
+ lexstring[STRINGLEN-1] = '\0';
+ string_stack[regretp] = savestr(lexstring);
+ numberstack[regretp] = lexnumber;
+}
+
+/*
+ * Reset all the scanner global variables.
+ */
+void
+scaninit(void)
+{
+ regretp = -1;
+}
+
+/*
+ * Find the first message whose flags & m == f and return
+ * its message number.
+ */
+int
+first(int f, int m)
+{
+ struct message *mp;
+
+ if (msgCount == 0)
+ return (0);
+ f &= MDELETED;
+ m &= MDELETED;
+ for (mp = dot; mp < &message[msgCount]; mp++)
+ if ((mp->m_flag & m) == f)
+ return (mp - message + 1);
+ for (mp = dot-1; mp >= &message[0]; mp--)
+ if ((mp->m_flag & m) == f)
+ return (mp - message + 1);
+ return (0);
+}
+
+/*
+ * See if the passed name sent the passed message number. Return true
+ * if so.
+ */
+int
+matchsender(char *str, int mesg)
+{
+ char *cp;
+
+ /* null string matches nothing instead of everything */
+ if (*str == '\0')
+ return (0);
+
+ cp = nameof(&message[mesg - 1], 0);
+ return (strcasestr(cp, str) != NULL);
+}
+
+/*
+ * See if the passed name received the passed message number. Return true
+ * if so.
+ */
+
+static char *to_fields[] = { "to", "cc", "bcc", NULL };
+
+static int
+matchto(char *str, int mesg)
+{
+ struct message *mp;
+ char *cp, **to;
+
+ str++;
+
+ /* null string matches nothing instead of everything */
+ if (*str == '\0')
+ return (0);
+
+ mp = &message[mesg - 1];
+
+ for (to = to_fields; *to != NULL; to++) {
+ cp = hfield(*to, mp);
+ if (cp != NULL && strcasestr(cp, str) != NULL)
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * See if the given substring is contained within the specified field. If
+ * 'searchheaders' is set, then the form '/x:y' will be accepted and matches
+ * any message with the substring 'y' in field 'x'. If 'x' is omitted or
+ * 'searchheaders' is not set, then the search matches any messages
+ * with the substring 'y' in the 'Subject'. The search is case insensitive.
+ *
+ * The form '/to:y' is a special case, and will match all messages
+ * containing the substring 'y' in the 'To', 'Cc', or 'Bcc' header
+ * fields. The search for 'to' is case sensitive, so that '/To:y' can
+ * be used to limit the search to just the 'To' field.
+ */
+
+static char lastscan[STRINGLEN];
+int
+matchfield(char *str, int mesg)
+{
+ struct message *mp;
+ char *cp, *cp2;
+
+ str++;
+ if (*str == '\0')
+ str = lastscan;
+ else
+ strlcpy(lastscan, str, sizeof(lastscan));
+ mp = &message[mesg-1];
+
+ /*
+ * Now look, ignoring case, for the word in the string.
+ */
+
+ if (value("searchheaders") && (cp = strchr(str, ':')) != NULL) {
+ /* Check for special case "/to:" */
+ if (strncmp(str, "to:", 3) == 0)
+ return (matchto(cp, mesg));
+ *cp++ = '\0';
+ cp2 = hfield(*str != '\0' ? str : "subject", mp);
+ cp[-1] = ':';
+ str = cp;
+ cp = cp2;
+ } else
+ cp = hfield("subject", mp);
+
+ if (cp == NULL)
+ return (0);
+
+ return (strcasestr(cp, str) != NULL);
+}
+
+/*
+ * Mark the named message by setting its mark bit.
+ */
+void
+mark(int mesg)
+{
+ int i;
+
+ i = mesg;
+ if (i < 1 || i > msgCount)
+ errx(1, "Bad message number to mark");
+ message[i-1].m_flag |= MMARK;
+}
+
+/*
+ * Unmark the named message.
+ */
+void
+unmark(int mesg)
+{
+ int i;
+
+ i = mesg;
+ if (i < 1 || i > msgCount)
+ errx(1, "Bad message number to unmark");
+ message[i-1].m_flag &= ~MMARK;
+}
+
+/*
+ * Return the message number corresponding to the passed meta character.
+ */
+int
+metamess(int meta, int f)
+{
+ int c, m;
+ struct message *mp;
+
+ c = meta;
+ switch (c) {
+ case '^':
+ /*
+ * First 'good' message left.
+ */
+ for (mp = &message[0]; mp < &message[msgCount]; mp++)
+ if ((mp->m_flag & MDELETED) == f)
+ return (mp - &message[0] + 1);
+ printf("No applicable messages\n");
+ return (-1);
+
+ case '$':
+ /*
+ * Last 'good message left.
+ */
+ for (mp = &message[msgCount-1]; mp >= &message[0]; mp--)
+ if ((mp->m_flag & MDELETED) == f)
+ return (mp - &message[0] + 1);
+ printf("No applicable messages\n");
+ return (-1);
+
+ case '.':
+ /*
+ * Current message.
+ */
+ m = dot - &message[0] + 1;
+ if ((dot->m_flag & MDELETED) != f) {
+ printf("%d: Inappropriate message\n", m);
+ return (-1);
+ }
+ return (m);
+
+ default:
+ printf("Unknown metachar (%c)\n", c);
+ return (-1);
+ }
+}
diff --git a/usr.bin/mail/mail.1 b/usr.bin/mail/mail.1
new file mode 100644
index 000000000000..7ec2cf818f4e
--- /dev/null
+++ b/usr.bin/mail/mail.1
@@ -0,0 +1,1270 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd August 8, 2018
+.Dt MAIL 1
+.Os
+.Sh NAME
+.Nm mail ,
+.Nm Mail ,
+.Nm mailx
+.Nd send and receive mail
+.Sh SYNOPSIS
+.Nm
+.Op Fl dEiInv
+.Op Fl s Ar subject
+.Op Fl c Ar cc-addr
+.Op Fl b Ar bcc-addr
+.Op Fl F
+.Ar to-addr ...
+.Op Fl Ar sendmail-option ...
+.Nm
+.Op Fl dEHiInNv
+.Op Fl F
+.Fl f
+.Op Ar name
+.Nm
+.Op Fl dEHiInNv
+.Op Fl F
+.Op Fl u Ar user
+.Nm
+.Op Fl d
+.Fl e
+.Op Fl f Ar name
+.Sh INTRODUCTION
+The
+.Nm
+utility is an intelligent mail processing system, which has
+a command syntax reminiscent of
+.Xr ed 1
+with lines replaced by messages.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl v
+Verbose mode.
+The details of
+delivery are displayed on the user's terminal.
+.It Fl d
+Debugging mode.
+See the
+.Va debug
+mail option for details.
+.It Fl e
+Test for the presence of mail in the (by default, system)
+mailbox.
+An exit status of 0 is returned if
+it has mail; otherwise, an exit status
+of 1 is returned.
+.It Fl H
+Write a header summary only, then exit.
+.It Fl E
+Do not send messages with an empty body.
+This is useful for piping errors from
+.Xr cron 8
+scripts.
+.It Fl i
+Ignore tty interrupt signals.
+This is
+particularly useful when using
+.Nm
+on noisy phone lines.
+.It Fl I
+Force
+.Nm
+to run in interactive mode even when
+input is not a terminal.
+In particular, the
+.Ql ~
+special
+character when sending mail is only active in interactive mode.
+.It Fl n
+Inhibit reading the system-wide
+.Pa mail.rc
+files upon startup.
+.It Fl N
+Inhibit the initial display of message headers
+when reading mail or editing a mail folder.
+.It Fl s Ar subject
+Specify
+.Ar subject
+on command line.
+(Only the first argument after the
+.Fl s
+flag is used as a subject; be careful to quote subjects
+containing spaces.)
+.It Fl c Ar cc-addr
+Send carbon copies to
+.Ar cc-addr
+list of users.
+The
+.Ar cc-addr
+argument should be a comma-separated list of names.
+.It Fl b Ar bcc-addr
+Send blind carbon copies to
+.Ar bcc-addr
+list of users.
+The
+.Ar bcc-addr
+argument should be a comma-separated list of names.
+.It Fl f Op Ar mbox
+Read in the contents of your
+.Pa mbox
+(or the specified file)
+for processing; when you
+.Ic quit ,
+.Nm
+writes undeleted messages back to this file.
+.It Fl F
+Record the message in a file named after the first
+recipient.
+The name is the login-name portion of the
+address found first on the
+.Dq Li To:
+line in the mail header.
+Overrides the
+.Va record
+variable, if set.
+.It Fl u Ar user
+Is equivalent to:
+.Pp
+.Dl "mail -f /var/mail/user"
+.El
+.Ss "Startup Actions"
+At startup time
+.Nm
+will execute commands in the system command files
+.Pa /usr/share/misc/mail.rc ,
+.Pa /usr/local/etc/mail.rc
+and
+.Pa /etc/mail.rc
+in order, unless explicitly told not to by the use of the
+.Fl n
+option.
+Next, the commands in the user's personal command file
+.Pa ~/.mailrc
+are executed.
+The
+.Nm
+utility then examines its command line options to determine whether a
+new message is to be sent, or whether an existing mailbox is to
+be read.
+.Ss "Sending Mail"
+To send a message to one or more people,
+.Nm
+can be invoked with arguments which are the names of people to
+whom the mail will be sent.
+You are then expected to type in
+your message, followed
+by a
+.Aq Li control-D
+at the beginning of a line.
+The section below
+.Sx "Replying To or Originating Mail" ,
+describes some features of
+.Nm
+available to help you compose your letter.
+.Ss "Reading Mail"
+In normal usage
+.Nm
+is given no arguments and checks your mail out of the
+post office, then
+prints out a one line header of each message found.
+The current message is initially the first message (numbered 1)
+and can be printed using the
+.Ic print
+command (which can be abbreviated
+.Ic p ) .
+You can move among the messages much as you move between lines in
+.Xr ed 1 ,
+with the commands
+.Ic +
+and
+.Ic \-
+moving backwards and forwards, and
+simple numbers.
+.Ss "Disposing of Mail"
+After examining a message you can
+.Ic delete
+.Pq Ic d
+the message or
+.Ic reply
+.Pq Ic r
+to it.
+Deletion causes the
+.Nm
+program to forget about the message.
+This is not irreversible; the message can be
+.Ic undeleted
+.Pq Ic u
+by giving its number, or the
+.Nm
+session can be aborted by giving the
+.Ic exit
+.Pq Ic x
+command.
+Deleted messages will, however, usually disappear never to be seen again.
+.Ss "Specifying Messages"
+Commands such as
+.Ic print
+and
+.Ic delete
+can be given a list of message numbers as arguments to apply
+to a number of messages at once.
+Thus
+.Dq Li "delete 1 2"
+deletes messages 1 and 2, while
+.Dq Li "delete 1\-5"
+deletes messages 1 through 5.
+The special name
+.Ql *
+addresses all messages, and
+.Ql $
+addresses
+the last message; thus the command
+.Ic top
+which prints the first few lines of a message could be used in
+.Dq Li "top *"
+to print the first few lines of all messages.
+.Ss "Replying To or Originating Mail"
+You can use the
+.Ic reply
+command to
+set up a response to a message, sending it back to the
+person who it was from.
+Text you then type in, up to an end-of-file,
+defines the contents of the message.
+While you are composing a message,
+.Nm
+treats lines beginning with the character
+.Ql ~
+specially.
+For instance, typing
+.Ic ~m
+(alone on a line) will place a copy
+of the current message into the response right shifting it by a tabstop
+(see
+.Va indentprefix
+variable, below).
+Other escapes will set up subject fields, add and delete recipients
+to the message and allow you to escape to an editor to revise the
+message or to a shell to run some commands.
+(These options
+are given in the summary below.)
+.Ss "Ending a Mail Processing Session"
+You can end a
+.Nm
+session with the
+.Ic quit
+.Pq Ic q
+command.
+Messages which have been examined go to your
+.Pa mbox
+file unless they have been deleted in which case they are discarded.
+Unexamined messages go back to the post office.
+(See the
+.Fl f
+option above).
+.Ss "Personal and System Wide Distribution Lists"
+It is also possible to create a personal distribution lists so that,
+for instance, you can send mail to
+.Dq Li cohorts
+and have it go
+to a group of people.
+Such lists can be defined by placing a line like
+.Pp
+.Dl "alias cohorts bill ozalp jkf mark kridle@ucbcory"
+.Pp
+in the file
+.Pa .mailrc
+in your home directory.
+The current list of such aliases can be displayed with the
+.Ic alias
+command in
+.Nm .
+System wide distribution lists can be created by editing
+.Pa /etc/mail/aliases ,
+see
+.Xr aliases 5
+and
+.Xr sendmail 8 ;
+these are kept in a different syntax.
+In mail you send, personal aliases will be expanded in mail sent
+to others so that they will be able to
+.Ic reply
+to the recipients.
+System wide
+aliases
+are not expanded when the mail is sent,
+but any reply returned to the machine will have the system wide
+alias expanded as all mail goes through
+.Xr sendmail 8 .
+.Ss "Network Mail (ARPA, UUCP, Berknet)"
+.Pp
+The
+.Nm
+utility has a number of options which can be set in the
+.Pa .mailrc
+file to alter its behavior; thus
+.Dq Li "set askcc"
+enables the
+.Va askcc
+feature.
+(These options are summarized below.)
+.Sh SUMMARY
+(Adapted from the
+.%T "Mail Reference Manual" . )
+.Pp
+Each command is typed on a line by itself, and may take arguments
+following the command word.
+The command need not be typed in its
+entirety \(em the first command which matches the typed prefix is used.
+For commands which take message lists as arguments, if no message
+list is given, then the next message forward which satisfies the
+command's requirements is used.
+If there are no messages forward of
+the current message, the search proceeds backwards, and if there are no
+good messages at all,
+.Nm
+types
+.Dq Li "No applicable messages"
+and
+aborts the command.
+.Bl -tag -width indent
+.It Ic \-
+Print out the preceding message.
+If given a numeric
+argument
+.Ar n ,
+goes to the
+.Ar n Ns 'th
+previous message and prints it.
+.It Ic #
+ignore the remainder of the line as a comment.
+.It Ic \&?
+Prints a brief summary of commands.
+.It Ic \&!
+Executes the shell
+(see
+.Xr sh 1
+and
+.Xr csh 1 )
+command which follows.
+.It Ic Print
+.Pq Ic P
+Like
+.Ic print
+but also prints out ignored header fields.
+See also
+.Ic print , ignore
+and
+.Ic retain .
+.It Ic Reply
+.Pq Ic R
+Reply to originator.
+Does not reply to other
+recipients of the original message.
+.It Ic Type
+.Pq Ic T
+Identical to the
+.Ic Print
+command.
+.It Ic alias
+.Pq Ic a
+With no arguments, prints out all currently-defined aliases.
+With one
+argument, prints out that alias.
+With more than one argument, creates
+a new alias or changes an old one.
+.It Ic alternates
+.Pq Ic alt
+The
+.Ic alternates
+command is useful if you have accounts on several machines.
+It can be used to inform
+.Nm
+that the listed addresses are really you.
+When you
+.Ic reply
+to messages,
+.Nm
+will not send a copy of the message to any of the addresses
+listed on the
+.Ic alternates
+list.
+If the
+.Ic alternates
+command is given with no argument, the current set of alternative
+names is displayed.
+.It Ic chdir
+.Pq Ic c
+Changes the user's working directory to that specified, if given.
+If
+no directory is given, then changes to the user's login directory.
+.It Ic copy
+.Pq Ic co
+The
+.Ic copy
+command does the same thing that
+.Ic save
+does, except that it does not mark the messages it
+is used on for deletion when you
+.Ic quit .
+.It Ic delete
+.Pq Ic d
+Takes a list of messages as argument and marks them all as deleted.
+Deleted messages will not be saved in
+.Pa mbox ,
+nor will they be available for most other commands.
+.It Ic dp
+(also
+.Ic dt )
+Deletes the current message and prints the next message.
+If there is no next message,
+.Nm
+says
+.Dq Li "at EOF" .
+.It Ic edit
+.Pq Ic e
+Takes a list of messages and points the text editor at each one in
+turn.
+On return from the editor, the message is read back in.
+.It Ic exit
+.Ic ( ex
+or
+.Ic x )
+Effects an immediate return to the shell without
+modifying the user's system mailbox, his
+.Pa mbox
+file, or his edit file in
+.Fl f .
+.It Ic file
+.Pq Ic fi
+The same as
+.Ic folder .
+.It Ic folders
+List the names of the folders in your folder directory.
+.It Ic folder
+.Pq Ic fo
+The
+.Ic folder
+command switches to a new mail file or folder.
+With no
+arguments, it tells you which file you are currently reading.
+If you give it an argument, it will write out changes (such
+as deletions) you have made in the current file and read in
+the new file.
+Some special conventions are recognized for
+the name.
+.Ql #
+means the previous file,
+.Ql %
+means your system mailbox,
+.Dq Li % Ns Ar user
+means user's system mailbox,
+.Ql &
+means your
+.Pa mbox
+file, and
+.Dq Li + Ns Ar folder
+means a file in your folder
+directory.
+.It Ic from
+.Pq Ic f
+Takes a list of messages and prints their message headers.
+.It Ic headers
+.Pq Ic h
+Lists the current range of headers, which is an 18-message group.
+If
+a
+.Ql +
+argument is given, then the next 18-message group is printed, and if
+a
+.Ql \-
+argument is given, the previous 18-message group is printed.
+.It Ic help
+A synonym for
+.Ic \&? .
+.It Ic hold
+.Ic ( ho ,
+also
+.Ic preserve )
+Takes a message list and marks each
+message therein to be saved in the
+user's system mailbox instead of in
+.Pa mbox .
+Does not override the
+.Ic delete
+command.
+.It Ic ignore
+Add the list of header fields named to the
+.Ar ignored list .
+Header fields in the ignore list are not printed
+on your terminal when you print a message.
+This
+command is very handy for suppression of certain machine-generated
+header fields.
+The
+.Ic Type
+and
+.Ic Print
+commands can be used to print a message in its entirety, including
+ignored fields.
+If
+.Ic ignore
+is executed with no arguments, it lists the current set of
+ignored fields.
+.It Ic inc
+Incorporate any new messages that have arrived while mail
+is being read.
+The new messages are added to the end of the message list,
+and the current message is reset to be the first new mail message.
+This does not renumber the existing message list, nor
+does it cause any changes made so far to be saved.
+.It Ic mail
+.Pq Ic m
+Takes as argument login names and distribution group names and sends
+mail to those people.
+.It Ic mbox
+Indicate that a list of messages be sent to
+.Pa mbox
+in your home directory when you quit.
+This is the default
+action for messages if you do
+.Em not
+have the
+.Ic hold
+option set.
+.It Ic more
+.Pq Ic mo
+Takes a list of messages and invokes the pager on that list.
+.It Ic next
+.Ic ( n ,
+like
+.Ic +
+or
+.Tn CR )
+Goes to the next message in sequence and types it.
+With an argument list, types the next matching message.
+.It Ic preserve
+.Pq Ic pre
+A synonym for
+.Ic hold .
+.It Ic print
+.Pq Ic p
+Takes a message list and types out each message on the user's terminal.
+.It Ic quit
+.Pq Ic q
+Terminates the session, saving all undeleted, unsaved messages in
+the user's
+.Pa mbox
+file in his login directory, preserving all messages marked with
+.Ic hold
+or
+.Ic preserve
+or never referenced
+in his system mailbox, and removing all other messages from his system
+mailbox.
+If new mail has arrived during the session, the message
+.Dq Li "You have new mail"
+is given.
+If given while editing a
+mailbox file with the
+.Fl f
+flag, then the edit file is rewritten.
+A return to the shell is
+effected, unless the rewrite of edit file fails, in which case the user
+can escape with the
+.Ic exit
+command.
+.It Ic reply
+.Pq Ic r
+Takes a message list and sends mail to the sender and all
+recipients of the specified message.
+The default message must not be deleted.
+.It Ic respond
+A synonym for
+.Ic reply .
+.It Ic retain
+Add the list of header fields named to the
+.Em "retained list" .
+Only the header fields in the retained list
+are shown on your terminal when you print a message.
+All other header fields are suppressed.
+The
+.Ic type
+and
+.Ic print
+commands can be used to print a message in its entirety.
+If
+.Ic retain
+is executed with no arguments, it lists the current set of
+retained fields.
+.It Ic save
+.Pq Ic s
+Takes a message list and a filename and appends each message in
+turn to the end of the file.
+The filename in quotes, followed by the line
+count and character count is echoed on the user's terminal.
+.It Ic set
+.Pq Ic se
+With no arguments, prints all variable values.
+Otherwise, sets
+option.
+Arguments are of the form
+.Ar option Ns Li = Ns Ar value
+(no space before or after
+.Ql = )
+or
+.Ar option .
+Quotation marks may be placed around any part of the assignment statement to
+quote blanks or tabs, i.e.\&
+.Dq Li "set indentprefix=\*q->\*q"
+.It Ic saveignore
+.Ic Saveignore
+is to
+.Ic save
+what
+.Ic ignore
+is to
+.Ic print
+and
+.Ic type .
+Header fields thus marked are filtered out when
+saving a message by
+.Ic save
+or when automatically saving to
+.Pa mbox .
+.It Ic saveretain
+.Ic Saveretain
+is to
+.Ic save
+what
+.Ic retain
+is to
+.Ic print
+and
+.Ic type .
+Header fields thus marked are the only ones saved
+with a message when saving by
+.Ic save
+or when automatically saving to
+.Pa mbox .
+.Ic Saveretain
+overrides
+.Ic saveignore .
+.It Ic shell
+.Pq Ic sh
+Invokes an interactive version of the shell.
+.It Ic size
+Takes a message list and prints out the size in characters of each
+message.
+.It Ic source
+The
+.Ic source
+command reads
+commands from a file.
+.It Ic top
+Takes a message list and prints the top few lines of each.
+The number of
+lines printed is controlled by the variable
+.Va toplines
+and defaults to 5.
+.It Ic type
+.Pq Ic t
+A synonym for
+.Ic print .
+.It Ic unalias
+Takes a list of names defined by
+.Ic alias
+commands and discards the remembered groups of users.
+The group names
+no longer have any significance.
+.It Ic undelete
+.Pq Ic u
+Takes a message list and marks each message as
+.Em not
+being deleted.
+.It Ic unread
+.Pq Ic U
+Takes a message list and marks each message as
+.Em not
+having been read.
+.It Ic unset
+Takes a list of option names and discards their remembered values;
+the inverse of
+.Ic set .
+.It Ic visual
+.Pq Ic v
+Takes a message list and invokes the display editor on each message.
+.It Ic write
+.Pq Ic w
+Similar to
+.Ic save ,
+except that
+.Em only
+the message body
+.Em ( without
+the header) is saved.
+Extremely useful for such tasks as sending and receiving source
+program text over the message system.
+.It Ic xit
+.Pq Ic x
+A synonym for
+.Ic exit .
+.It Ic z
+The
+.Nm
+utility presents message headers in windowfuls as described under the
+.Ic headers
+command.
+You can move
+.Nm Ns 's
+attention forward to the next window with the
+.Ic z
+command.
+Also, you can move to the previous window by using
+.Ic z\- .
+.El
+.Ss Tilde/Escapes
+Here is a summary of the tilde escapes,
+which are used when composing messages to perform
+special functions.
+Tilde escapes are only recognized at the beginning
+of lines.
+The name
+.Dq "tilde escape"
+is somewhat of a misnomer since the actual escape character can be set
+by the option
+.Va escape .
+.Bl -tag -width indent
+.It Ic ~a
+Inserts the autograph string from the sign= option into the message.
+.It Ic ~A
+Inserts the autograph string from the Sign= option into the message.
+.It Ic ~b Ar name ...
+Add the given names to the list of carbon copy recipients but do not make
+the names visible in the Cc: line
+.Dq ( blind
+carbon copy).
+.It Ic ~c Ar name ...
+Add the given names to the list of carbon copy recipients.
+.It Ic ~d
+Read the file
+.Pa dead.letter
+from your home directory into the message.
+.It Ic ~e
+Invoke the text editor on the message collected so far.
+After the
+editing session is finished, you may continue appending text to the
+message.
+.It Ic ~f Ar messages
+Read the named messages into the message being sent.
+If no messages are specified, read in the current message.
+Message headers currently being ignored (by the
+.Ic ignore
+or
+.Ic retain
+command) are not included.
+.It Ic ~F Ar messages
+Identical to
+.Ic ~f ,
+except all message headers are included.
+.It Ic ~h
+Edit the message header fields by typing each one in turn and allowing
+the user to append text to the end or modify the field by using the
+current terminal erase and kill characters.
+.It Ic ~i Ar string
+Inserts the value of the named option into the text of the message.
+.It Ic ~m Ar messages
+Read the named messages into the message being sent, indented by a
+tab or by the value of
+.Va indentprefix .
+If no messages are specified,
+read the current message.
+Message headers currently being ignored (by the
+.Ic ignore
+or
+.Ic retain
+command) are not included.
+.It Ic ~M Ar messages
+Identical to
+.Ic ~m ,
+except all message headers are included.
+.It Ic ~p
+Print out the message collected so far, prefaced by the message header
+fields.
+.It Ic ~q
+Abort the message being sent, copying the message to
+.Pa dead.letter
+in your home directory if
+.Va save
+is set.
+.It Ic ~r Ar filename , Ic ~r Li \&! Ns Ar command
+.It Ic ~< Ar filename , Ic ~< Li \&! Ns Ar command
+Read the named file into the message.
+If the argument begins with a
+.Ql \&! ,
+the rest of the string is taken as an arbitrary system command and is
+executed, with the standard output inserted into the message.
+.It Ic ~R Ar string
+Use
+.Ar string
+as the Reply-To field.
+.It Ic ~s Ar string
+Cause the named string to become the current subject field.
+.It Ic ~t Ar name ...
+Add the given names to the direct recipient list.
+.It Ic ~v
+Invoke an alternative editor (defined by the
+.Ev VISUAL
+environment variable) on the
+message collected so far.
+Usually, the alternative editor will be a
+screen editor.
+After you quit the editor, you may resume appending
+text to the end of your message.
+.It Ic ~w Ar filename
+Write the message onto the named file.
+.It Ic ~x
+Exits as with
+.Ic ~q ,
+except the message is not saved in
+.Pa dead.letter .
+.It Ic ~! Ar command
+Execute the indicated shell command, then return to the message.
+.It Ic ~| Ar command , Ic ~^ Ar command
+Pipe the message through the command as a filter.
+If the command gives
+no output or terminates abnormally, retain the original text of the
+message.
+The command
+.Xr fmt 1
+is often used as
+.Ar command
+to rejustify the message.
+.It Ic ~: Ar mail-command , Ic ~_ Ar mail-command
+Execute the given
+.Nm
+command.
+Not all commands, however, are allowed.
+.It Ic ~.
+Simulate end-of-file on input.
+.It Ic ~?
+Print a summary of the available command escapes.
+.It Ic ~~ Ar string
+Insert the string of text in the message prefaced by a single
+.Ql ~ .
+If
+you have changed the escape character, then you should double
+that character in order to send it.
+.El
+.Ss "Mail Options"
+Options can be set with the
+.Ic set
+command
+and can be disabled with the
+.Ic unset
+or
+.Ic set Cm no Ns Ar name
+commands.
+Options may be either binary, in which case it is only
+significant to see whether they are set or not; or string, in which
+case the actual value is of interest.
+If an option is not set,
+.Nm
+will look for an environment variable of the same name.
+The available options include the following:
+.Bl -tag -width indent
+.It Va append
+Causes messages saved in
+.Pa mbox
+to be appended to the end rather than prepended.
+This should always be set (preferably in one of the system-wide
+.Pa mail.rc
+files).
+Default is
+.Va noappend .
+.It Va ask , asksub
+Causes
+.Nm
+to prompt you for the subject of each message you send.
+If
+you respond with simply a newline, no subject field will be sent.
+Default is
+.Va asksub .
+.It Va askbcc
+Causes you to be prompted for additional blind carbon copy recipients at the
+end of each message.
+Responding with a newline indicates your
+satisfaction with the current list.
+Default is
+.Va noaskbcc .
+.It Va askcc
+Causes you to be prompted for additional carbon copy recipients at the
+end of each message.
+Responding with a newline indicates your
+satisfaction with the current list.
+Default is
+.Va noaskcc .
+.It Va autoinc
+Causes new mail to be automatically incorporated when it arrives.
+Setting this is similar to issuing the
+.Ic inc
+command at each prompt, except that the current message is not
+reset when new mail arrives.
+Default is
+.Va noautoinc .
+.It Va autoprint
+Causes the
+.Ic delete
+command to behave like
+.Ic dp ;
+thus, after deleting a message, the next one will be typed
+automatically.
+Default is
+.Va noautoprint .
+.It Va crt
+The valued option
+.Va crt
+is used as a threshold to determine how long a message must
+be before
+.Ev PAGER
+is used to read it.
+If
+.Va crt
+is set without a value,
+then the height of the terminal screen stored in the system
+is used to compute the threshold (see
+.Xr stty 1 ) .
+Default is
+.Va nocrt .
+.It Va debug
+Setting the binary option
+.Va debug
+is the same as specifying
+.Fl d
+on the command line and causes
+.Nm
+to output all sorts of information useful for debugging
+.Nm .
+In case
+.Nm
+is invoked in this mode to send mail, all preparations
+will be performed and reported about, but the mail will
+not be actually sent.
+Default is
+.Va nodebug .
+.It Va dot
+The binary option
+.Va dot
+causes
+.Nm
+to interpret a period alone on a line as the terminator
+of a message you are sending.
+Default is
+.Va nodot .
+.It Va escape
+If defined, the first character of this option gives the character to
+use in place of
+.Ql ~
+to denote escapes.
+.It Va flipr
+Reverses the sense of
+.Ic reply
+and
+.Ic Reply
+commands.
+Default is
+.Va noflipr .
+.It Va folder
+The name of the directory to use for storing folders of
+messages.
+If this name begins with a
+.Ql / ,
+.Nm
+considers it to be an absolute pathname; otherwise, the
+folder directory is found relative to your home directory.
+.It Va header
+If defined, initially display message headers when reading mail or
+editing a mail folder.
+Default is
+.Va header .
+This option can be disabled by giving the
+.Fl N
+flag on the command line.
+.It Va hold
+This option is used to hold messages in the system mailbox
+by default.
+Default is
+.Va nohold .
+.It Va ignore
+Causes interrupt signals from your terminal to be ignored and echoed as
+.Li @ Ns 's.
+Default is
+.Va noignore .
+.It Va ignoreeof
+An option related to
+.Va dot
+is
+.Va ignoreeof
+which makes
+.Nm
+refuse to accept a
+.Aq Li control-D
+as the end of a message.
+.Ar Ignoreeof
+also applies to
+.Nm
+command mode.
+Default is
+.Va noignoreeof .
+.It Va indentprefix
+String used by the
+.Ic ~m
+tilde escape for indenting messages, in place of
+the normal tab character
+.Pq Li ^I .
+Be sure to quote the value if it contains
+spaces or tabs.
+.It Va metoo
+Usually, when a group is expanded that contains the sender, the sender
+is removed from the expansion.
+Setting this option causes the sender
+to be included in the group.
+Default is
+.Va nometoo .
+.It Va quiet
+Suppresses the printing of the version when first invoked.
+Default is
+.Va noquiet .
+.It Va record
+If defined, gives the pathname of the file used to record all outgoing
+mail.
+If not defined, outgoing mail is not saved.
+Default is
+.Va norecord .
+.It Va Replyall
+Reverses the sense of
+.Ic reply
+and
+.Ic Reply
+commands.
+Default is
+.Va noReplyall .
+.It Va save
+If this option is set, and you abort a message with two
+.Tn RUBOUT
+(erase or delete),
+.Nm
+will copy the partial letter to the file
+.Pa dead.letter
+in your home directory.
+Default is
+.Va save .
+.It Va searchheaders
+If this option is set, then a message-list specifier in the form
+.Dq Li / Ns Ar x Ns : Ns Ar y
+will expand to all messages containing the substring
+.Ar y
+in the header field
+.Ar x .
+The string search is case insensitive.
+If
+.Ar x
+is omitted, it will default to the
+.Dq Li Subject
+header field.
+The form
+.Dq Li /to: Ns Ar y
+is a special case, and will expand
+to all messages containing the substring
+.Ar y
+in the
+.Dq Li To ,
+.Dq Li Cc
+or
+.Dq Li Bcc
+header fields.
+The check for
+.Qq Li "to"
+is case sensitive, so that
+.Dq Li /To: Ns Ar y
+can be used to limit the search for
+.Ar y
+to just the
+.Dq Li To:
+field.
+Default is
+.Va nosearchheaders .
+.It Va toplines
+If defined, gives the number of lines of a message to be printed out
+with the
+.Ic top
+command; normally, the first five lines are printed.
+.It Va verbose
+Setting the option
+.Va verbose
+is the same as using the
+.Fl v
+flag on the command line.
+When
+.Nm
+runs in verbose mode,
+the actual delivery of messages is displayed on the user's
+terminal.
+Default is
+.Va noverbose .
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev REPLYTO"
+.It Ev DEAD
+Pathname of the file to save partial messages to in case of interrupts
+or delivery errors.
+Default is
+.Pa ~/dead.letter .
+.It Ev EDITOR
+Pathname of the text editor to use in the
+.Ic edit
+command and
+.Ic ~e
+escape.
+If not defined, then a default editor is used.
+.It Ev HOME
+Pathname of the user's home directory.
+.It Ev LISTER
+Pathname of the directory lister to use in the
+.Ic folders
+command.
+Default is
+.Pa /bin/ls .
+.It Ev MAIL
+Location of the user's mailbox.
+Default is
+.Pa /var/mail .
+.It Ev MAILRC
+Pathname of file containing initial
+.Nm
+commands.
+Default is
+.Pa ~/.mailrc .
+.It Ev MBOX
+The name of the mailbox file.
+It can be the name of a folder.
+The default is
+.Pa mbox
+in the user's home directory.
+.It Ev PAGER
+Pathname of the program to use in the
+.Ic more
+command or when
+.Va crt
+variable is set.
+The default paginator
+.Xr less 1
+is used if this option is not defined.
+.It Ev REPLYTO
+If set, will be used to initialize the Reply-To field for outgoing
+messages.
+.It Ev SHELL
+Pathname of the shell to use in the
+.Ic \&!
+command and the
+.Ic ~!
+escape.
+A default shell is used if this option is
+not defined.
+.It Ev TMPDIR
+Pathname of the directory used for creating temporary files.
+.It Ev VISUAL
+Pathname of the text editor to use in the
+.Ic visual
+command and
+.Ic ~v
+escape.
+.It Ev USER
+Login name of the user executing mail.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /usr/share/misc/mail.*help" -compact
+.It Pa /var/mail/*
+Post office.
+.It Pa ~/mbox
+User's old mail.
+.It Pa ~/.mailrc
+File giving initial
+.Nm
+commands.
+This can be overridden by setting the
+.Ev MAILRC
+environment variable.
+.It Pa /tmp/R*
+Temporary files.
+.It Pa /usr/share/misc/mail.*help
+Help files.
+.Pp
+.It Pa /usr/share/misc/mail.rc
+.It Pa /usr/local/etc/mail.rc
+.It Pa /etc/mail.rc
+System-wide initialization files.
+Each file will be sourced, in order,
+if it exists.
+.El
+.Sh SEE ALSO
+.Xr fmt 1 ,
+.Xr newaliases 1 ,
+.Xr vacation 1 ,
+.Xr aliases 5 ,
+.Xr sendmail 8
+.Sh HISTORY
+A
+.Nm
+command
+appeared in
+.At v1 .
+This man page is derived from
+.%T "The Mail Reference Manual"
+originally written by
+.An Kurt Shoens .
+.Sh BUGS
+There are some flags that are not documented here.
+Most are
+not useful to the general user.
+.Pp
+Usually,
+.Nm
+is just a link to
+.Nm Mail
+and
+.Nm mailx ,
+which can be confusing.
+.Pp
+The name of the
+.Ic alternates
+list is incorrect English (it should be
+.Dq alternatives ) ,
+but is retained for compatibility.
diff --git a/usr.bin/mail/main.c b/usr.bin/mail/main.c
new file mode 100644
index 000000000000..86a1a964ac3c
--- /dev/null
+++ b/usr.bin/mail/main.c
@@ -0,0 +1,378 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Startup -- interface with user.
+ */
+int msgCount;
+int rcvmode;
+int sawcom;
+char *Tflag;
+int senderr;
+int edit;
+int readonly;
+int noreset;
+int sourcing;
+int loading;
+int cond;
+FILE *itf;
+FILE *otf;
+int image;
+FILE *input;
+char mailname[PATHSIZE];
+char prevfile[PATHSIZE];
+char *homedir;
+char *myname;
+off_t mailsize;
+int lexnumber;
+char lexstring[STRINGLEN];
+int regretp;
+int regretstack[REGDEP];
+char *string_stack[REGDEP];
+int numberstack[REGDEP];
+struct message *dot;
+struct message *message;
+struct var *variables[HSHSIZE];
+struct grouphead *groups[HSHSIZE];
+struct ignoretab ignore[2];
+
+struct ignoretab saveignore[2];
+
+struct ignoretab ignoreall[2];
+char **altnames;
+int debug;
+int screenwidth;
+int screenheight;
+
+int realscreenheight;
+
+jmp_buf srbuf;
+
+static jmp_buf hdrjmp;
+
+extern const char *version;
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ struct name *to, *cc, *bcc, *smopts;
+ char *subject, *replyto;
+ char *ef, *rc;
+ char nosrc = 0;
+ sig_t prevint;
+
+ /*
+ * Set up a reasonable environment.
+ * Figure out whether we are being run interactively,
+ * start the SIGCHLD catcher, and so forth.
+ */
+ (void)signal(SIGCHLD, sigchild);
+ if (isatty(0))
+ assign("interactive", "");
+ image = -1;
+ /*
+ * Now, determine how we are being used.
+ * We successively pick off - flags.
+ * If there is anything left, it is the base of the list
+ * of users to mail to. Argp will be set to point to the
+ * first of these users.
+ */
+ ef = NULL;
+ to = NULL;
+ cc = NULL;
+ bcc = NULL;
+ smopts = NULL;
+ subject = NULL;
+ while ((i = getopt(argc, argv, "FEHINT:b:c:edfins:u:v")) != -1) {
+ switch (i) {
+ case 'T':
+ /*
+ * Next argument is temp file to write which
+ * articles have been read/deleted for netnews.
+ */
+ Tflag = optarg;
+ if ((i = open(Tflag, O_CREAT | O_TRUNC | O_WRONLY,
+ 0600)) < 0)
+ err(1, "%s", Tflag);
+ (void)close(i);
+ break;
+ case 'u':
+ /*
+ * Next argument is person to pretend to be.
+ */
+ myname = optarg;
+ unsetenv("MAIL");
+ break;
+ case 'i':
+ /*
+ * User wants to ignore interrupts.
+ * Set the variable "ignore"
+ */
+ assign("ignore", "");
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'e':
+ /*
+ * User wants to check mail and exit.
+ */
+ assign("checkmode", "");
+ break;
+ case 'H':
+ /*
+ * User wants a header summary only.
+ */
+ assign("headersummary", "");
+ break;
+ case 'F':
+ /*
+ * User wants to record messages to files
+ * named after first recipient username.
+ */
+ assign("recordrecip", "");
+ break;
+ case 's':
+ /*
+ * Give a subject field for sending from
+ * non terminal
+ */
+ subject = optarg;
+ break;
+ case 'f':
+ /*
+ * User is specifying file to "edit" with Mail,
+ * as opposed to reading system mailbox.
+ * If no argument is given after -f, we read his
+ * mbox file.
+ *
+ * getopt() can't handle optional arguments, so here
+ * is an ugly hack to get around it.
+ */
+ if ((argv[optind] != NULL) && (argv[optind][0] != '-'))
+ ef = argv[optind++];
+ else
+ ef = "&";
+ break;
+ case 'n':
+ /*
+ * User doesn't want to source /usr/lib/Mail.rc
+ */
+ nosrc++;
+ break;
+ case 'N':
+ /*
+ * Avoid initial header printing.
+ */
+ assign("noheader", "");
+ break;
+ case 'v':
+ /*
+ * Send mailer verbose flag
+ */
+ assign("verbose", "");
+ break;
+ case 'I':
+ /*
+ * We're interactive
+ */
+ assign("interactive", "");
+ break;
+ case 'c':
+ /*
+ * Get Carbon Copy Recipient list
+ */
+ cc = cat(cc, nalloc(optarg, GCC));
+ break;
+ case 'b':
+ /*
+ * Get Blind Carbon Copy Recipient list
+ */
+ bcc = cat(bcc, nalloc(optarg, GBCC));
+ break;
+ case 'E':
+ /*
+ * Don't send empty files.
+ */
+ assign("dontsendempty", "");
+ break;
+ case '?':
+ fprintf(stderr, "\
+Usage: %s [-dEiInv] [-s subject] [-c cc-addr] [-b bcc-addr] [-F] to-addr ...\n\
+ %*s [-sendmail-option ...]\n\
+ %s [-dEHiInNv] [-F] -f [name]\n\
+ %s [-dEHiInNv] [-F] [-u user]\n\
+ %s [-d] -e [-f name]\n", __progname, (int)strlen(__progname), "",
+ __progname, __progname, __progname);
+ exit(1);
+ }
+ }
+ for (i = optind; (argv[i] != NULL) && (*argv[i] != '-'); i++)
+ to = cat(to, nalloc(argv[i], GTO));
+ for (; argv[i] != NULL; i++)
+ smopts = cat(smopts, nalloc(argv[i], 0));
+ /*
+ * Check for inconsistent arguments.
+ */
+ if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL))
+ errx(1, "You must specify direct recipients with -s, -c, or -b.");
+ if (ef != NULL && to != NULL)
+ errx(1, "Cannot give -f and people to send to.");
+ tinit();
+ setscreensize();
+ input = stdin;
+ rcvmode = !to;
+ spreserve();
+ if (!nosrc) {
+ char *s, *path_rc;
+
+ if ((path_rc = malloc(sizeof(_PATH_MASTER_RC))) == NULL)
+ err(1, "malloc(path_rc) failed");
+
+ strcpy(path_rc, _PATH_MASTER_RC);
+ while ((s = strsep(&path_rc, ":")) != NULL)
+ if (*s != '\0')
+ load(s);
+ }
+ /*
+ * Expand returns a savestr, but load only uses the file name
+ * for fopen, so it's safe to do this.
+ */
+ if ((rc = getenv("MAILRC")) == NULL)
+ rc = "~/.mailrc";
+ load(expand(rc));
+
+ replyto = value("REPLYTO");
+ if (!rcvmode) {
+ mail(to, cc, bcc, smopts, subject, replyto);
+ /*
+ * why wait?
+ */
+ exit(senderr);
+ }
+
+ if(value("checkmode") != NULL) {
+ if (ef == NULL)
+ ef = "%";
+ if (setfile(ef) <= 0)
+ /* Either an error has occurred, or no mail */
+ exit(1);
+ else
+ exit(0);
+ /* NOTREACHED */
+ }
+
+ /*
+ * Ok, we are reading mail.
+ * Decide whether we are editing a mailbox or reading
+ * the system mailbox, and open up the right stuff.
+ */
+ if (ef == NULL)
+ ef = "%";
+ if (setfile(ef) < 0)
+ exit(1); /* error already reported */
+ if (setjmp(hdrjmp) == 0) {
+ if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN)
+ (void)signal(SIGINT, hdrstop);
+ if (value("quiet") == NULL)
+ printf("Mail version %s. Type ? for help.\n",
+ version);
+ announce();
+ (void)fflush(stdout);
+ (void)signal(SIGINT, prevint);
+ }
+
+ /* If we were in header summary mode, it's time to exit. */
+ if (value("headersummary") != NULL)
+ exit(0);
+
+ commands();
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
+ quit();
+ exit(0);
+}
+
+/*
+ * Interrupt printing of the headers.
+ */
+/*ARGSUSED*/
+void
+hdrstop(int signo __unused)
+{
+
+ (void)fflush(stdout);
+ fprintf(stderr, "\nInterrupt\n");
+ longjmp(hdrjmp, 1);
+}
+
+/*
+ * Compute what the screen size for printing headers should be.
+ * We use the following algorithm for the height:
+ * If baud rate < 1200, use 9
+ * If baud rate = 1200, use 14
+ * If baud rate > 1200, use 24 or ws_row
+ * Width is either 80 or ws_col;
+ */
+void
+setscreensize(void)
+{
+ struct termios tbuf;
+ struct winsize ws;
+ speed_t speed;
+
+ if (ioctl(1, TIOCGWINSZ, (char *)&ws) < 0)
+ ws.ws_col = ws.ws_row = 0;
+ if (tcgetattr(1, &tbuf) < 0)
+ speed = B9600;
+ else
+ speed = cfgetospeed(&tbuf);
+ if (speed < B1200)
+ screenheight = 9;
+ else if (speed == B1200)
+ screenheight = 14;
+ else if (ws.ws_row != 0)
+ screenheight = ws.ws_row;
+ else
+ screenheight = 24;
+ if ((realscreenheight = ws.ws_row) == 0)
+ realscreenheight = 24;
+ if ((screenwidth = ws.ws_col) == 0)
+ screenwidth = 80;
+}
diff --git a/usr.bin/mail/misc/mail.help b/usr.bin/mail/misc/mail.help
new file mode 100644
index 000000000000..f5c5dd2de0cd
--- /dev/null
+++ b/usr.bin/mail/misc/mail.help
@@ -0,0 +1,23 @@
+ Mail Commands
+t <message list> type messages
+n goto and type next message
+e <message list> edit messages
+f <message list> give head lines of messages
+d <message list> delete messages
+s <message list> file append messages to file
+u <message list> undelete messages
+R <message list> reply to message senders
+r <message list> reply to message senders and all recipients
+pre <message list> make messages go back to /var/mail
+m <user list> mail to specific users
+q quit, saving unresolved messages in mbox
+x quit, do not remove system mailbox
+h print out active message headers
+! shell escape
+cd [directory] chdir to directory or home if none given
+
+A <message list> consists of integers, ranges of same, or user names separated
+by spaces. If omitted, Mail uses the last message typed.
+
+A <user list> consists of user names or aliases separated by spaces.
+Aliases are defined in .mailrc in your home directory.
diff --git a/usr.bin/mail/misc/mail.rc b/usr.bin/mail/misc/mail.rc
new file mode 100644
index 000000000000..2293b3c1acf2
--- /dev/null
+++ b/usr.bin/mail/misc/mail.rc
@@ -0,0 +1,2 @@
+set append dot save ask crt
+ignore Received Message-Id Resent-Message-Id Status Mail-From Return-Path Via
diff --git a/usr.bin/mail/misc/mail.tildehelp b/usr.bin/mail/misc/mail.tildehelp
new file mode 100644
index 000000000000..47201d30088e
--- /dev/null
+++ b/usr.bin/mail/misc/mail.tildehelp
@@ -0,0 +1,36 @@
+-----------------------------------------------------------
+The following ~ escapes are defined:
+~? Print this message
+~~ Quote a single tilde
+~. Simulate end-of-file on input
+~A Equivalent to: ~i Sign
+~a Equivalent to: ~i sign
+~b users Add users to Bcc list
+~c users Add users to Cc list
+~C Dump core
+~d Read in dead.letter
+~e Edit the message buffer
+~f messages Read in messages
+~F messages Same as ~f, but keep all header lines
+~h Prompt for Subject and To, Cc, and Bcc lists
+~i name Insert the value of the named variable
+~m messages Read in messages, right shifted by a tab
+~M messages Same as ~m, but keep all header lines
+~p Print the message buffer
+~q Quit, save partial message in dead.letter
+~r file Read a file into the message buffer
+~r !command Insert the output of the command
+~< file Same as ~r
+~< !command Same as ~r
+~R address Set Reply-to to address
+~s subject Set Subject to subject
+~t users Add users to the To list
+~v Invoke display editor on message
+~w file Write message onto file
+~x Quit, do not save to dead.letter
+~! command Invoke the shell
+~| command Pipe the message through the command
+~^ command Same as ~|
+~_ mail-cmd Perform the command-level request
+~: mail-cmd Same as ~_
+-----------------------------------------------------------
diff --git a/usr.bin/mail/names.c b/usr.bin/mail/names.c
new file mode 100644
index 000000000000..502487055ff9
--- /dev/null
+++ b/usr.bin/mail/names.c
@@ -0,0 +1,756 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Handle name lists.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Allocate a single element of a name list,
+ * initialize its name field to the passed
+ * name and return it.
+ */
+struct name *
+nalloc(char str[], int ntype)
+{
+ struct name *np;
+
+ np = (struct name *)salloc(sizeof(*np));
+ np->n_flink = NULL;
+ np->n_blink = NULL;
+ np->n_type = ntype;
+ np->n_name = savestr(str);
+ return (np);
+}
+
+/*
+ * Find the tail of a list and return it.
+ */
+struct name *
+tailof(struct name *name)
+{
+ struct name *np;
+
+ np = name;
+ if (np == NULL)
+ return (NULL);
+ while (np->n_flink != NULL)
+ np = np->n_flink;
+ return (np);
+}
+
+/*
+ * Extract a list of names from a line,
+ * and make a list of names from it.
+ * Return the list or NULL if none found.
+ */
+struct name *
+extract(char *line, int ntype)
+{
+ char *cp, *nbuf;
+ struct name *top, *np, *t;
+
+ if (line == NULL || *line == '\0')
+ return (NULL);
+ if ((nbuf = malloc(strlen(line) + 1)) == NULL)
+ err(1, "Out of memory");
+ top = NULL;
+ np = NULL;
+ cp = line;
+ while ((cp = yankword(cp, nbuf)) != NULL) {
+ t = nalloc(nbuf, ntype);
+ if (top == NULL)
+ top = t;
+ else
+ np->n_flink = t;
+ t->n_blink = np;
+ np = t;
+ }
+ (void)free(nbuf);
+ return (top);
+}
+
+/*
+ * Turn a list of names into a string of the same names.
+ */
+char *
+detract(struct name *np, int ntype)
+{
+ int s, comma;
+ char *cp, *top;
+ struct name *p;
+
+ comma = ntype & GCOMMA;
+ if (np == NULL)
+ return (NULL);
+ ntype &= ~GCOMMA;
+ s = 0;
+ if (debug && comma)
+ fprintf(stderr, "detract asked to insert commas\n");
+ for (p = np; p != NULL; p = p->n_flink) {
+ if (ntype && (p->n_type & GMASK) != ntype)
+ continue;
+ s += strlen(p->n_name) + 1;
+ if (comma)
+ s++;
+ }
+ if (s == 0)
+ return (NULL);
+ s += 2;
+ top = salloc(s);
+ cp = top;
+ for (p = np; p != NULL; p = p->n_flink) {
+ if (ntype && (p->n_type & GMASK) != ntype)
+ continue;
+ cp += strlcpy(cp, p->n_name, strlen(p->n_name) + 1);
+ if (comma && p->n_flink != NULL)
+ *cp++ = ',';
+ *cp++ = ' ';
+ }
+ *--cp = '\0';
+ if (comma && *--cp == ',')
+ *cp = '\0';
+ return (top);
+}
+
+/*
+ * Grab a single word (liberal word)
+ * Throw away things between ()'s, and take anything between <>.
+ */
+char *
+yankword(char *ap, char *wbuf)
+{
+ char *cp, *cp2;
+
+ cp = ap;
+ for (;;) {
+ if (*cp == '\0')
+ return (NULL);
+ if (*cp == '(') {
+ int nesting = 0;
+
+ while (*cp != '\0') {
+ switch (*cp++) {
+ case '(':
+ nesting++;
+ break;
+ case ')':
+ --nesting;
+ break;
+ }
+ if (nesting <= 0)
+ break;
+ }
+ } else if (*cp == ' ' || *cp == '\t' || *cp == ',')
+ cp++;
+ else
+ break;
+ }
+ if (*cp == '<')
+ for (cp2 = wbuf; *cp && (*cp2++ = *cp++) != '>';)
+ ;
+ else
+ for (cp2 = wbuf; *cp != '\0' && strchr(" \t,(", *cp) == NULL;
+ *cp2++ = *cp++)
+ ;
+ *cp2 = '\0';
+ return (cp);
+}
+
+/*
+ * Grab a single login name (liberal word)
+ * Throw away things between ()'s, take anything between <>,
+ * and look for words before metacharacters %, @, !.
+ */
+char *
+yanklogin(char *ap, char *wbuf)
+{
+ char *cp, *cp2, *cp_temp;
+ int n;
+
+ cp = ap;
+ for (;;) {
+ if (*cp == '\0')
+ return (NULL);
+ if (*cp == '(') {
+ int nesting = 0;
+
+ while (*cp != '\0') {
+ switch (*cp++) {
+ case '(':
+ nesting++;
+ break;
+ case ')':
+ --nesting;
+ break;
+ }
+ if (nesting <= 0)
+ break;
+ }
+ } else if (*cp == ' ' || *cp == '\t' || *cp == ',')
+ cp++;
+ else
+ break;
+ }
+
+ /*
+ * Now, let's go forward till we meet the needed character,
+ * and step one word back.
+ */
+
+ /* First, remember current point. */
+ cp_temp = cp;
+ n = 0;
+
+ /*
+ * Note that we look ahead in a cycle. This is safe, since
+ * non-end of string is checked first.
+ */
+ while(*cp != '\0' && strchr("@%!", *(cp + 1)) == NULL)
+ cp++;
+
+ /*
+ * Now, start stepping back to the first non-word character,
+ * while counting the number of symbols in a word.
+ */
+ while(cp != cp_temp && strchr(" \t,<>", *(cp - 1)) == NULL) {
+ n++;
+ cp--;
+ }
+
+ /* Finally, grab the word forward. */
+ cp2 = wbuf;
+ while(n >= 0) {
+ *cp2++=*cp++;
+ n--;
+ }
+
+ *cp2 = '\0';
+ return (cp);
+}
+
+/*
+ * For each recipient in the passed name list with a /
+ * in the name, append the message to the end of the named file
+ * and remove him from the recipient list.
+ *
+ * Recipients whose name begins with | are piped through the given
+ * program and removed.
+ */
+struct name *
+outof(struct name *names, FILE *fo, struct header *hp)
+{
+ int c, ispipe;
+ struct name *np, *top;
+ time_t now;
+ char *date, *fname;
+ FILE *fout, *fin;
+
+ top = names;
+ np = names;
+ (void)time(&now);
+ date = ctime(&now);
+ while (np != NULL) {
+ if (!isfileaddr(np->n_name) && np->n_name[0] != '|') {
+ np = np->n_flink;
+ continue;
+ }
+ ispipe = np->n_name[0] == '|';
+ if (ispipe)
+ fname = np->n_name+1;
+ else
+ fname = expand(np->n_name);
+
+ /*
+ * See if we have copied the complete message out yet.
+ * If not, do so.
+ */
+
+ if (image < 0) {
+ int fd;
+ char tempname[PATHSIZE];
+
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.ReXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (fout = Fdopen(fd, "a")) == NULL) {
+ warn("%s", tempname);
+ senderr++;
+ goto cant;
+ }
+ image = open(tempname, O_RDWR);
+ (void)rm(tempname);
+ if (image < 0) {
+ warn("%s", tempname);
+ senderr++;
+ (void)Fclose(fout);
+ goto cant;
+ }
+ (void)fcntl(image, F_SETFD, 1);
+ fprintf(fout, "From %s %s", myname, date);
+ puthead(hp, fout,
+ GTO|GSUBJECT|GCC|GREPLYTO|GINREPLYTO|GNL);
+ while ((c = getc(fo)) != EOF)
+ (void)putc(c, fout);
+ rewind(fo);
+ fprintf(fout, "\n");
+ (void)fflush(fout);
+ if (ferror(fout)) {
+ warn("%s", tempname);
+ senderr++;
+ (void)Fclose(fout);
+ goto cant;
+ }
+ (void)Fclose(fout);
+ }
+
+ /*
+ * Now either copy "image" to the desired file
+ * or give it as the standard input to the desired
+ * program as appropriate.
+ */
+
+ if (ispipe) {
+ int pid;
+ char *sh;
+ sigset_t nset;
+
+ /*
+ * XXX
+ * We can't really reuse the same image file,
+ * because multiple piped recipients will
+ * share the same lseek location and trample
+ * on one another.
+ */
+ if ((sh = value("SHELL")) == NULL)
+ sh = _PATH_CSHELL;
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGHUP);
+ (void)sigaddset(&nset, SIGINT);
+ (void)sigaddset(&nset, SIGQUIT);
+ pid = start_command(sh, &nset, image, -1, "-c", fname,
+ NULL);
+ if (pid < 0) {
+ senderr++;
+ goto cant;
+ }
+ free_child(pid);
+ } else {
+ int f;
+ if ((fout = Fopen(fname, "a")) == NULL) {
+ warn("%s", fname);
+ senderr++;
+ goto cant;
+ }
+ if ((f = dup(image)) < 0) {
+ warn("dup");
+ fin = NULL;
+ } else
+ fin = Fdopen(f, "r");
+ if (fin == NULL) {
+ fprintf(stderr, "Can't reopen image\n");
+ (void)Fclose(fout);
+ senderr++;
+ goto cant;
+ }
+ rewind(fin);
+ while ((c = getc(fin)) != EOF)
+ (void)putc(c, fout);
+ if (ferror(fout)) {
+ warnx("%s", fname);
+ senderr++;
+ (void)Fclose(fout);
+ (void)Fclose(fin);
+ goto cant;
+ }
+ (void)Fclose(fout);
+ (void)Fclose(fin);
+ }
+cant:
+ /*
+ * In days of old we removed the entry from the
+ * the list; now for sake of header expansion
+ * we leave it in and mark it as deleted.
+ */
+ np->n_type |= GDEL;
+ np = np->n_flink;
+ }
+ if (image >= 0) {
+ (void)close(image);
+ image = -1;
+ }
+ return (top);
+}
+
+/*
+ * Determine if the passed address is a local "send to file" address.
+ * If any of the network metacharacters precedes any slashes, it can't
+ * be a filename. We cheat with .'s to allow path names like ./...
+ */
+int
+isfileaddr(char *name)
+{
+ char *cp;
+
+ if (*name == '+')
+ return (1);
+ for (cp = name; *cp != '\0'; cp++) {
+ if (*cp == '!' || *cp == '%' || *cp == '@')
+ return (0);
+ if (*cp == '/')
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Map all of the aliased users in the invoker's mailrc
+ * file and insert them into the list.
+ * Changed after all these months of service to recursively
+ * expand names (2/14/80).
+ */
+
+struct name *
+usermap(struct name *names)
+{
+ struct name *new, *np, *cp;
+ struct grouphead *gh;
+ int metoo;
+
+ new = NULL;
+ np = names;
+ metoo = (value("metoo") != NULL);
+ while (np != NULL) {
+ if (np->n_name[0] == '\\') {
+ cp = np->n_flink;
+ new = put(new, np);
+ np = cp;
+ continue;
+ }
+ gh = findgroup(np->n_name);
+ cp = np->n_flink;
+ if (gh != NULL)
+ new = gexpand(new, gh, metoo, np->n_type);
+ else
+ new = put(new, np);
+ np = cp;
+ }
+ return (new);
+}
+
+/*
+ * Recursively expand a group name. We limit the expansion to some
+ * fixed level to keep things from going haywire.
+ * Direct recursion is not expanded for convenience.
+ */
+
+struct name *
+gexpand(struct name *nlist, struct grouphead *gh, int metoo, int ntype)
+{
+ struct group *gp;
+ struct grouphead *ngh;
+ struct name *np;
+ static int depth;
+ char *cp;
+
+ if (depth > MAXEXP) {
+ printf("Expanding alias to depth larger than %d\n", MAXEXP);
+ return (nlist);
+ }
+ depth++;
+ for (gp = gh->g_list; gp != NULL; gp = gp->ge_link) {
+ cp = gp->ge_name;
+ if (*cp == '\\')
+ goto quote;
+ if (strcmp(cp, gh->g_name) == 0)
+ goto quote;
+ if ((ngh = findgroup(cp)) != NULL) {
+ nlist = gexpand(nlist, ngh, metoo, ntype);
+ continue;
+ }
+quote:
+ np = nalloc(cp, ntype);
+ /*
+ * At this point should allow to expand
+ * to self if only person in group
+ */
+ if (gp == gh->g_list && gp->ge_link == NULL)
+ goto skip;
+ if (!metoo && strcmp(cp, myname) == 0)
+ np->n_type |= GDEL;
+skip:
+ nlist = put(nlist, np);
+ }
+ depth--;
+ return (nlist);
+}
+
+/*
+ * Concatenate the two passed name lists, return the result.
+ */
+struct name *
+cat(struct name *n1, struct name *n2)
+{
+ struct name *tail;
+
+ if (n1 == NULL)
+ return (n2);
+ if (n2 == NULL)
+ return (n1);
+ tail = tailof(n1);
+ tail->n_flink = n2;
+ n2->n_blink = tail;
+ return (n1);
+}
+
+/*
+ * Unpack the name list onto a vector of strings.
+ * Return an error if the name list won't fit.
+ */
+char **
+unpack(struct name *np)
+{
+ char **ap, **top;
+ struct name *n;
+ int t, extra, metoo, verbose;
+
+ n = np;
+ if ((t = count(n)) == 0)
+ errx(1, "No names to unpack");
+ /*
+ * Compute the number of extra arguments we will need.
+ * We need at least two extra -- one for "mail" and one for
+ * the terminating 0 pointer. Additional spots may be needed
+ * to pass along -f to the host mailer.
+ */
+ extra = 2;
+ extra++;
+ metoo = value("metoo") != NULL;
+ if (metoo)
+ extra++;
+ verbose = value("verbose") != NULL;
+ if (verbose)
+ extra++;
+ top = (char **)salloc((t + extra) * sizeof(*top));
+ ap = top;
+ *ap++ = "sendmail";
+ *ap++ = "-i";
+ if (metoo)
+ *ap++ = "-m";
+ if (verbose)
+ *ap++ = "-v";
+ for (; n != NULL; n = n->n_flink)
+ if ((n->n_type & GDEL) == 0)
+ *ap++ = n->n_name;
+ *ap = NULL;
+ return (top);
+}
+
+/*
+ * Remove all of the duplicates from the passed name list by
+ * insertion sorting them, then checking for dups.
+ * Return the head of the new list.
+ */
+struct name *
+elide(struct name *names)
+{
+ struct name *np, *t, *new;
+ struct name *x;
+
+ if (names == NULL)
+ return (NULL);
+ new = names;
+ np = names;
+ np = np->n_flink;
+ if (np != NULL)
+ np->n_blink = NULL;
+ new->n_flink = NULL;
+ while (np != NULL) {
+ t = new;
+ while (strcasecmp(t->n_name, np->n_name) < 0) {
+ if (t->n_flink == NULL)
+ break;
+ t = t->n_flink;
+ }
+
+ /*
+ * If we ran out of t's, put the new entry after
+ * the current value of t.
+ */
+
+ if (strcasecmp(t->n_name, np->n_name) < 0) {
+ t->n_flink = np;
+ np->n_blink = t;
+ t = np;
+ np = np->n_flink;
+ t->n_flink = NULL;
+ continue;
+ }
+
+ /*
+ * Otherwise, put the new entry in front of the
+ * current t. If at the front of the list,
+ * the new guy becomes the new head of the list.
+ */
+
+ if (t == new) {
+ t = np;
+ np = np->n_flink;
+ t->n_flink = new;
+ new->n_blink = t;
+ t->n_blink = NULL;
+ new = t;
+ continue;
+ }
+
+ /*
+ * The normal case -- we are inserting into the
+ * middle of the list.
+ */
+
+ x = np;
+ np = np->n_flink;
+ x->n_flink = t;
+ x->n_blink = t->n_blink;
+ t->n_blink->n_flink = x;
+ t->n_blink = x;
+ }
+
+ /*
+ * Now the list headed up by new is sorted.
+ * Go through it and remove duplicates.
+ */
+
+ np = new;
+ while (np != NULL) {
+ t = np;
+ while (t->n_flink != NULL &&
+ strcasecmp(np->n_name, t->n_flink->n_name) == 0)
+ t = t->n_flink;
+ if (t == np || t == NULL) {
+ np = np->n_flink;
+ continue;
+ }
+
+ /*
+ * Now t points to the last entry with the same name
+ * as np. Make np point beyond t.
+ */
+
+ np->n_flink = t->n_flink;
+ if (t->n_flink != NULL)
+ t->n_flink->n_blink = np;
+ np = np->n_flink;
+ }
+ return (new);
+}
+
+/*
+ * Put another node onto a list of names and return
+ * the list.
+ */
+struct name *
+put(struct name *list, struct name *node)
+{
+ node->n_flink = list;
+ node->n_blink = NULL;
+ if (list != NULL)
+ list->n_blink = node;
+ return (node);
+}
+
+/*
+ * Determine the number of undeleted elements in
+ * a name list and return it.
+ */
+int
+count(struct name *np)
+{
+ int c;
+
+ for (c = 0; np != NULL; np = np->n_flink)
+ if ((np->n_type & GDEL) == 0)
+ c++;
+ return (c);
+}
+
+/*
+ * Delete the given name from a namelist.
+ */
+struct name *
+delname(struct name *np, char name[])
+{
+ struct name *p;
+
+ for (p = np; p != NULL; p = p->n_flink)
+ if (strcasecmp(p->n_name, name) == 0) {
+ if (p->n_blink == NULL) {
+ if (p->n_flink != NULL)
+ p->n_flink->n_blink = NULL;
+ np = p->n_flink;
+ continue;
+ }
+ if (p->n_flink == NULL) {
+ if (p->n_blink != NULL)
+ p->n_blink->n_flink = NULL;
+ continue;
+ }
+ p->n_blink->n_flink = p->n_flink;
+ p->n_flink->n_blink = p->n_blink;
+ }
+ return (np);
+}
+
+/*
+ * Pretty print a name list
+ * Uncomment it if you need it.
+ */
+
+/*
+void
+prettyprint(struct name *name)
+{
+ struct name *np;
+
+ np = name;
+ while (np != NULL) {
+ fprintf(stderr, "%s(%d) ", np->n_name, np->n_type);
+ np = np->n_flink;
+ }
+ fprintf(stderr, "\n");
+}
+*/
diff --git a/usr.bin/mail/pathnames.h b/usr.bin/mail/pathnames.h
new file mode 100644
index 000000000000..0b773a3e569c
--- /dev/null
+++ b/usr.bin/mail/pathnames.h
@@ -0,0 +1,38 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <paths.h>
+
+#define _PATH_EX "/usr/bin/ex"
+#define _PATH_HELP "/usr/share/misc/mail.help"
+#define _PATH_TILDE "/usr/share/misc/mail.tildehelp"
+#define _PATH_MASTER_RC "/usr/share/misc/mail.rc:" _PATH_LOCALBASE "/etc/mail.rc:/etc/mail.rc"
+#define _PATH_LESS "/usr/bin/less"
diff --git a/usr.bin/mail/popen.c b/usr.bin/mail/popen.c
new file mode 100644
index 000000000000..69326bdb260c
--- /dev/null
+++ b/usr.bin/mail/popen.c
@@ -0,0 +1,406 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include "extern.h"
+
+#define READ 0
+#define WRITE 1
+
+struct fp {
+ FILE *fp;
+ int pipe;
+ pid_t pid;
+ struct fp *link;
+};
+static struct fp *fp_head;
+
+struct child {
+ pid_t pid;
+ char done;
+ char free;
+ int status;
+ struct child *link;
+};
+static struct child *child, *child_freelist = NULL;
+
+static void delchild(struct child *);
+static pid_t file_pid(FILE *);
+static pid_t start_commandv(char *, sigset_t *, int, int, va_list);
+
+FILE *
+Fopen(const char *path, const char *mode)
+{
+ FILE *fp;
+
+ if ((fp = fopen(path, mode)) != NULL) {
+ register_file(fp, 0, 0);
+ (void)fcntl(fileno(fp), F_SETFD, 1);
+ }
+ return (fp);
+}
+
+FILE *
+Fdopen(int fd, const char *mode)
+{
+ FILE *fp;
+
+ if ((fp = fdopen(fd, mode)) != NULL) {
+ register_file(fp, 0, 0);
+ (void)fcntl(fileno(fp), F_SETFD, 1);
+ }
+ return (fp);
+}
+
+int
+Fclose(FILE *fp)
+{
+
+ unregister_file(fp);
+ return (fclose(fp));
+}
+
+FILE *
+Popen(char *cmd, const char *mode)
+{
+ int p[2];
+ int myside, hisside, fd0, fd1;
+ pid_t pid;
+ sigset_t nset;
+ FILE *fp;
+
+ if (pipe(p) < 0)
+ return (NULL);
+ (void)fcntl(p[READ], F_SETFD, 1);
+ (void)fcntl(p[WRITE], F_SETFD, 1);
+ if (*mode == 'r') {
+ myside = p[READ];
+ hisside = fd0 = fd1 = p[WRITE];
+ } else {
+ myside = p[WRITE];
+ hisside = fd0 = p[READ];
+ fd1 = -1;
+ }
+ (void)sigemptyset(&nset);
+ pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL);
+ if (pid < 0) {
+ (void)close(p[READ]);
+ (void)close(p[WRITE]);
+ return (NULL);
+ }
+ (void)close(hisside);
+ if ((fp = fdopen(myside, mode)) != NULL)
+ register_file(fp, 1, pid);
+ return (fp);
+}
+
+int
+Pclose(FILE *ptr)
+{
+ int i;
+ sigset_t nset, oset;
+
+ i = file_pid(ptr);
+ unregister_file(ptr);
+ (void)fclose(ptr);
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGINT);
+ (void)sigaddset(&nset, SIGHUP);
+ (void)sigprocmask(SIG_BLOCK, &nset, &oset);
+ i = wait_child(i);
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+ return (i);
+}
+
+void
+close_all_files(void)
+{
+
+ while (fp_head != NULL)
+ if (fp_head->pipe)
+ (void)Pclose(fp_head->fp);
+ else
+ (void)Fclose(fp_head->fp);
+}
+
+void
+register_file(FILE *fp, int pipe, pid_t pid)
+{
+ struct fp *fpp;
+
+ if ((fpp = malloc(sizeof(*fpp))) == NULL)
+ err(1, "Out of memory");
+ fpp->fp = fp;
+ fpp->pipe = pipe;
+ fpp->pid = pid;
+ fpp->link = fp_head;
+ fp_head = fpp;
+}
+
+void
+unregister_file(FILE *fp)
+{
+ struct fp **pp, *p;
+
+ for (pp = &fp_head; (p = *pp) != NULL; pp = &p->link)
+ if (p->fp == fp) {
+ *pp = p->link;
+ (void)free(p);
+ return;
+ }
+ errx(1, "Invalid file pointer");
+ /*NOTREACHED*/
+}
+
+pid_t
+file_pid(FILE *fp)
+{
+ struct fp *p;
+
+ for (p = fp_head; p != NULL; p = p->link)
+ if (p->fp == fp)
+ return (p->pid);
+ errx(1, "Invalid file pointer");
+ /*NOTREACHED*/
+}
+
+/*
+ * Run a command without a shell, with optional arguments and splicing
+ * of stdin (-1 means none) and stdout. The command name can be a sequence
+ * of words.
+ * Signals must be handled by the caller.
+ * "nset" contains the signals to ignore in the new process.
+ * SIGINT is enabled unless it's in "nset".
+ */
+static pid_t
+start_commandv(char *cmd, sigset_t *nset, int infd, int outfd, va_list args)
+{
+ pid_t pid;
+
+ if ((pid = fork()) < 0) {
+ warn("fork");
+ return (-1);
+ }
+ if (pid == 0) {
+ char *argv[100];
+ int i = getrawlist(cmd, argv, sizeof(argv) / sizeof(*argv));
+
+ while ((argv[i++] = va_arg(args, char *)))
+ ;
+ argv[i] = NULL;
+ prepare_child(nset, infd, outfd);
+ execvp(argv[0], argv);
+ warn("%s", argv[0]);
+ _exit(1);
+ }
+ return (pid);
+}
+
+int
+run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)
+{
+ pid_t pid;
+ va_list args;
+
+ va_start(args, outfd);
+ pid = start_commandv(cmd, nset, infd, outfd, args);
+ va_end(args);
+ if (pid < 0)
+ return -1;
+ return wait_command(pid);
+}
+
+int
+start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)
+{
+ va_list args;
+ int r;
+
+ va_start(args, outfd);
+ r = start_commandv(cmd, nset, infd, outfd, args);
+ va_end(args);
+ return r;
+}
+
+void
+prepare_child(sigset_t *nset, int infd, int outfd)
+{
+ int i;
+ sigset_t eset;
+
+ /*
+ * All file descriptors other than 0, 1, and 2 are supposed to be
+ * close-on-exec.
+ */
+ if (infd >= 0)
+ dup2(infd, 0);
+ if (outfd >= 0)
+ dup2(outfd, 1);
+ for (i = 1; i < NSIG; i++)
+ if (nset != NULL && sigismember(nset, i))
+ (void)signal(i, SIG_IGN);
+ if (nset == NULL || !sigismember(nset, SIGINT))
+ (void)signal(SIGINT, SIG_DFL);
+ (void)sigemptyset(&eset);
+ (void)sigprocmask(SIG_SETMASK, &eset, NULL);
+}
+
+int
+wait_command(pid_t pid)
+{
+
+ if (wait_child(pid) < 0) {
+ printf("Fatal error in process.\n");
+ return (-1);
+ }
+ return (0);
+}
+
+static struct child *
+findchild(pid_t pid, int dont_alloc)
+{
+ struct child **cpp;
+
+ for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
+ cpp = &(*cpp)->link)
+ ;
+ if (*cpp == NULL) {
+ if (dont_alloc)
+ return(NULL);
+ if (child_freelist) {
+ *cpp = child_freelist;
+ child_freelist = (*cpp)->link;
+ } else {
+ *cpp = malloc(sizeof(struct child));
+ if (*cpp == NULL)
+ err(1, "malloc");
+ }
+ (*cpp)->pid = pid;
+ (*cpp)->done = (*cpp)->free = 0;
+ (*cpp)->link = NULL;
+ }
+ return (*cpp);
+}
+
+static void
+delchild(struct child *cp)
+{
+ struct child **cpp;
+
+ for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
+ ;
+ *cpp = cp->link;
+ cp->link = child_freelist;
+ child_freelist = cp;
+}
+
+/*ARGSUSED*/
+void
+sigchild(int signo __unused)
+{
+ pid_t pid;
+ int status;
+ struct child *cp;
+ int save_errno;
+
+ save_errno = errno;
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ cp = findchild(pid, 1);
+ if (cp == NULL)
+ continue;
+ if (cp->free)
+ delchild(cp);
+ else {
+ cp->done = 1;
+ cp->status = status;
+ }
+ }
+ errno = save_errno;
+}
+
+int wait_status;
+
+/*
+ * Wait for a specific child to die.
+ */
+int
+wait_child(pid_t pid)
+{
+ struct child *cp;
+ sigset_t nset, oset;
+ pid_t rv = 0;
+
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGCHLD);
+ (void)sigprocmask(SIG_BLOCK, &nset, &oset);
+ /*
+ * If we have not already waited on the pid (via sigchild)
+ * wait on it now. Otherwise, use the wait status stashed
+ * by sigchild.
+ */
+ cp = findchild(pid, 1);
+ if (cp == NULL || !cp->done)
+ rv = waitpid(pid, &wait_status, 0);
+ else
+ wait_status = cp->status;
+ if (cp != NULL)
+ delchild(cp);
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+ if (rv == -1 || (WIFEXITED(wait_status) && WEXITSTATUS(wait_status)))
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Mark a child as don't care.
+ */
+void
+free_child(pid_t pid)
+{
+ struct child *cp;
+ sigset_t nset, oset;
+
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGCHLD);
+ (void)sigprocmask(SIG_BLOCK, &nset, &oset);
+ if ((cp = findchild(pid, 0)) != NULL) {
+ if (cp->done)
+ delchild(cp);
+ else
+ cp->free = 1;
+ }
+ (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+}
diff --git a/usr.bin/mail/quit.c b/usr.bin/mail/quit.c
new file mode 100644
index 000000000000..6b69461ca6f4
--- /dev/null
+++ b/usr.bin/mail/quit.c
@@ -0,0 +1,489 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Rcv -- receive mail rationally.
+ *
+ * Termination processing.
+ */
+
+/*
+ * The "quit" command.
+ */
+int
+quitcmd(void *arg __unused)
+{
+ /*
+ * If we are sourcing, then return 1 so execute() can handle it.
+ * Otherwise, return -1 to abort command loop.
+ */
+ if (sourcing)
+ return (1);
+ return (-1);
+}
+
+/*
+ * Save all of the undetermined messages at the top of "mbox"
+ * Save all untouched messages back in the system mailbox.
+ * Remove the system mailbox, if none saved there.
+ */
+void
+quit(void)
+{
+ int mcount, p, modify, autohold, anystat, holdbit, nohold;
+ FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
+ struct message *mp;
+ int c, fd;
+ struct stat minfo;
+ char *mbox, tempname[PATHSIZE];
+
+ /*
+ * If we are read only, we can't do anything,
+ * so just return quickly.
+ */
+ if (readonly)
+ return;
+ /*
+ * If editing (not reading system mail box), then do the work
+ * in edstop()
+ */
+ if (edit) {
+ edstop();
+ return;
+ }
+
+ /*
+ * See if there any messages to save in mbox. If no, we
+ * can save copying mbox to /tmp and back.
+ *
+ * Check also to see if any files need to be preserved.
+ * Delete all untouched messages to keep them out of mbox.
+ * If all the messages are to be preserved, just exit with
+ * a message.
+ */
+
+ fbuf = Fopen(mailname, "r");
+ if (fbuf == NULL)
+ goto newmail;
+ (void)flock(fileno(fbuf), LOCK_EX);
+ rbuf = NULL;
+ if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
+ printf("New mail has arrived.\n");
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.RqXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (rbuf = Fdopen(fd, "w")) == NULL)
+ goto newmail;
+#ifdef APPEND
+ (void)fseeko(fbuf, mailsize, SEEK_SET);
+ while ((c = getc(fbuf)) != EOF)
+ (void)putc(c, rbuf);
+#else
+ p = minfo.st_size - mailsize;
+ while (p-- > 0) {
+ c = getc(fbuf);
+ if (c == EOF)
+ goto newmail;
+ (void)putc(c, rbuf);
+ }
+#endif
+ (void)Fclose(rbuf);
+ if ((rbuf = Fopen(tempname, "r")) == NULL)
+ goto newmail;
+ (void)rm(tempname);
+ }
+
+ /*
+ * Adjust the message flags in each message.
+ */
+
+ anystat = 0;
+ autohold = value("hold") != NULL;
+ holdbit = autohold ? MPRESERVE : MBOX;
+ nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
+ if (value("keepsave") != NULL)
+ nohold &= ~MSAVED;
+ for (mp = &message[0]; mp < &message[msgCount]; mp++) {
+ if (mp->m_flag & MNEW) {
+ mp->m_flag &= ~MNEW;
+ mp->m_flag |= MSTATUS;
+ }
+ if (mp->m_flag & MSTATUS)
+ anystat++;
+ if ((mp->m_flag & MTOUCH) == 0)
+ mp->m_flag |= MPRESERVE;
+ if ((mp->m_flag & nohold) == 0)
+ mp->m_flag |= holdbit;
+ }
+ modify = 0;
+ if (Tflag != NULL) {
+ if ((readstat = Fopen(Tflag, "w")) == NULL)
+ Tflag = NULL;
+ }
+ for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
+ if (mp->m_flag & MBOX)
+ c++;
+ if (mp->m_flag & MPRESERVE)
+ p++;
+ if (mp->m_flag & MODIFY)
+ modify++;
+ if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
+ char *id;
+
+ if ((id = hfield("article-id", mp)) != NULL)
+ fprintf(readstat, "%s\n", id);
+ }
+ }
+ if (Tflag != NULL)
+ (void)Fclose(readstat);
+ if (p == msgCount && !modify && !anystat) {
+ printf("Held %d message%s in %s\n",
+ p, p == 1 ? "" : "s", mailname);
+ (void)Fclose(fbuf);
+ return;
+ }
+ if (c == 0) {
+ if (p != 0) {
+ writeback(rbuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+ goto cream;
+ }
+
+ /*
+ * Create another temporary file and copy user's mbox file
+ * darin. If there is no mbox, copy nothing.
+ * If he has specified "append" don't copy his mailbox,
+ * just copy saveable entries at the end.
+ */
+
+ mbox = expand("&");
+ mcount = c;
+ if (value("append") == NULL) {
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.RmXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (obuf = Fdopen(fd, "w")) == NULL) {
+ warn("%s", tempname);
+ (void)Fclose(fbuf);
+ return;
+ }
+ if ((ibuf = Fopen(tempname, "r")) == NULL) {
+ warn("%s", tempname);
+ (void)rm(tempname);
+ (void)Fclose(obuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+ (void)rm(tempname);
+ if ((abuf = Fopen(mbox, "r")) != NULL) {
+ while ((c = getc(abuf)) != EOF)
+ (void)putc(c, obuf);
+ (void)Fclose(abuf);
+ }
+ if (ferror(obuf)) {
+ warnx("%s", tempname);
+ (void)Fclose(ibuf);
+ (void)Fclose(obuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+ (void)Fclose(obuf);
+ if ((fd = open(mbox, O_CREAT | O_TRUNC | O_WRONLY, 0600)) >= 0)
+ (void)close(fd);
+ if ((obuf = Fopen(mbox, "r+")) == NULL) {
+ warn("%s", mbox);
+ (void)Fclose(ibuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+ }
+ if (value("append") != NULL) {
+ if ((obuf = Fopen(mbox, "a")) == NULL) {
+ warn("%s", mbox);
+ (void)Fclose(fbuf);
+ return;
+ }
+ (void)fchmod(fileno(obuf), 0600);
+ }
+ for (mp = &message[0]; mp < &message[msgCount]; mp++)
+ if (mp->m_flag & MBOX)
+ if (sendmessage(mp, obuf, saveignore, NULL) < 0) {
+ warnx("%s", mbox);
+ (void)Fclose(ibuf);
+ (void)Fclose(obuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+
+ /*
+ * Copy the user's old mbox contents back
+ * to the end of the stuff we just saved.
+ * If we are appending, this is unnecessary.
+ */
+
+ if (value("append") == NULL) {
+ rewind(ibuf);
+ c = getc(ibuf);
+ while (c != EOF) {
+ (void)putc(c, obuf);
+ if (ferror(obuf))
+ break;
+ c = getc(ibuf);
+ }
+ (void)Fclose(ibuf);
+ }
+ (void)fflush(obuf);
+ trunc(obuf);
+ if (ferror(obuf)) {
+ warn("%s", mbox);
+ (void)Fclose(obuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+ (void)Fclose(obuf);
+ if (mcount == 1)
+ printf("Saved 1 message in mbox\n");
+ else
+ printf("Saved %d messages in mbox\n", mcount);
+
+ /*
+ * Now we are ready to copy back preserved files to
+ * the system mailbox, if any were requested.
+ */
+
+ if (p != 0) {
+ writeback(rbuf);
+ (void)Fclose(fbuf);
+ return;
+ }
+
+ /*
+ * Finally, remove his /var/mail file.
+ * If new mail has arrived, copy it back.
+ */
+
+cream:
+ if (rbuf != NULL) {
+ abuf = Fopen(mailname, "r+");
+ if (abuf == NULL)
+ goto newmail;
+ while ((c = getc(rbuf)) != EOF)
+ (void)putc(c, abuf);
+ (void)Fclose(rbuf);
+ trunc(abuf);
+ (void)Fclose(abuf);
+ alter(mailname);
+ (void)Fclose(fbuf);
+ return;
+ }
+ demail();
+ (void)Fclose(fbuf);
+ return;
+
+newmail:
+ printf("Thou hast new mail.\n");
+ if (fbuf != NULL)
+ (void)Fclose(fbuf);
+}
+
+/*
+ * Preserve all the appropriate messages back in the system
+ * mailbox, and print a nice message indicated how many were
+ * saved. On any error, just return -1. Else return 0.
+ * Incorporate the any new mail that we found.
+ */
+int
+writeback(FILE *res)
+{
+ struct message *mp;
+ int p, c;
+ FILE *obuf;
+
+ p = 0;
+ if ((obuf = Fopen(mailname, "r+")) == NULL) {
+ warn("%s", mailname);
+ return (-1);
+ }
+#ifndef APPEND
+ if (res != NULL)
+ while ((c = getc(res)) != EOF)
+ (void)putc(c, obuf);
+#endif
+ for (mp = &message[0]; mp < &message[msgCount]; mp++)
+ if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) {
+ p++;
+ if (sendmessage(mp, obuf, NULL, NULL) < 0) {
+ warnx("%s", mailname);
+ (void)Fclose(obuf);
+ return (-1);
+ }
+ }
+#ifdef APPEND
+ if (res != NULL)
+ while ((c = getc(res)) != EOF)
+ (void)putc(c, obuf);
+#endif
+ (void)fflush(obuf);
+ trunc(obuf);
+ if (ferror(obuf)) {
+ warn("%s", mailname);
+ (void)Fclose(obuf);
+ return (-1);
+ }
+ if (res != NULL)
+ (void)Fclose(res);
+ (void)Fclose(obuf);
+ alter(mailname);
+ if (p == 1)
+ printf("Held 1 message in %s\n", mailname);
+ else
+ printf("Held %d messages in %s\n", p, mailname);
+ return (0);
+}
+
+/*
+ * Terminate an editing session by attempting to write out the user's
+ * file from the temporary. Save any new stuff appended to the file.
+ */
+void
+edstop(void)
+{
+ int gotcha, c;
+ struct message *mp;
+ FILE *obuf, *ibuf, *readstat;
+ struct stat statb;
+ char tempname[PATHSIZE];
+
+ if (readonly)
+ return;
+ holdsigs();
+ if (Tflag != NULL) {
+ if ((readstat = Fopen(Tflag, "w")) == NULL)
+ Tflag = NULL;
+ }
+ for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
+ if (mp->m_flag & MNEW) {
+ mp->m_flag &= ~MNEW;
+ mp->m_flag |= MSTATUS;
+ }
+ if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
+ gotcha++;
+ if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
+ char *id;
+
+ if ((id = hfield("article-id", mp)) != NULL)
+ fprintf(readstat, "%s\n", id);
+ }
+ }
+ if (Tflag != NULL)
+ (void)Fclose(readstat);
+ if (!gotcha || Tflag != NULL)
+ goto done;
+ ibuf = NULL;
+ if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
+ int fd;
+
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mbox.XXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (obuf = Fdopen(fd, "w")) == NULL) {
+ warn("%s", tempname);
+ relsesigs();
+ reset(0);
+ }
+ if ((ibuf = Fopen(mailname, "r")) == NULL) {
+ warn("%s", mailname);
+ (void)Fclose(obuf);
+ (void)rm(tempname);
+ relsesigs();
+ reset(0);
+ }
+ (void)fseeko(ibuf, mailsize, SEEK_SET);
+ while ((c = getc(ibuf)) != EOF)
+ (void)putc(c, obuf);
+ (void)Fclose(ibuf);
+ (void)Fclose(obuf);
+ if ((ibuf = Fopen(tempname, "r")) == NULL) {
+ warn("%s", tempname);
+ (void)rm(tempname);
+ relsesigs();
+ reset(0);
+ }
+ (void)rm(tempname);
+ }
+ printf("\"%s\" ", mailname);
+ (void)fflush(stdout);
+ if ((obuf = Fopen(mailname, "r+")) == NULL) {
+ warn("%s", mailname);
+ relsesigs();
+ reset(0);
+ }
+ trunc(obuf);
+ c = 0;
+ for (mp = &message[0]; mp < &message[msgCount]; mp++) {
+ if ((mp->m_flag & MDELETED) != 0)
+ continue;
+ c++;
+ if (sendmessage(mp, obuf, NULL, NULL) < 0) {
+ warnx("%s", mailname);
+ relsesigs();
+ reset(0);
+ }
+ }
+ gotcha = (c == 0 && ibuf == NULL);
+ if (ibuf != NULL) {
+ while ((c = getc(ibuf)) != EOF)
+ (void)putc(c, obuf);
+ (void)Fclose(ibuf);
+ }
+ (void)fflush(obuf);
+ if (ferror(obuf)) {
+ warn("%s", mailname);
+ relsesigs();
+ reset(0);
+ }
+ (void)Fclose(obuf);
+ if (gotcha) {
+ (void)rm(mailname);
+ printf("removed\n");
+ } else
+ printf("complete\n");
+ (void)fflush(stdout);
+
+done:
+ relsesigs();
+}
diff --git a/usr.bin/mail/rcv.h b/usr.bin/mail/rcv.h
new file mode 100644
index 000000000000..87e688b58043
--- /dev/null
+++ b/usr.bin/mail/rcv.h
@@ -0,0 +1,40 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * This file is included by normal files which want both
+ * globals and declarations.
+ */
+
+#include "def.h"
+#include "glob.h"
diff --git a/usr.bin/mail/send.c b/usr.bin/mail/send.c
new file mode 100644
index 000000000000..b4fbd4cbfd8a
--- /dev/null
+++ b/usr.bin/mail/send.c
@@ -0,0 +1,584 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Mail to others.
+ */
+
+/*
+ * Send message described by the passed pointer to the
+ * passed output buffer. Return -1 on error.
+ * Adjust the status: field if need be.
+ * If doign is given, suppress ignored header fields.
+ * prefix is a string to prepend to each output line.
+ */
+int
+sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
+ char *prefix)
+{
+ long count;
+ FILE *ibuf;
+ char *cp, *cp2, line[LINESIZE];
+ int ishead, infld, ignoring, dostat, firstline;
+ int c = 0, length, prefixlen;
+
+ /*
+ * Compute the prefix string, without trailing whitespace
+ */
+ if (prefix != NULL) {
+ cp2 = 0;
+ for (cp = prefix; *cp != '\0'; cp++)
+ if (*cp != ' ' && *cp != '\t')
+ cp2 = cp;
+ prefixlen = cp2 == NULL ? 0 : cp2 - prefix + 1;
+ }
+ ibuf = setinput(mp);
+ count = mp->m_size;
+ ishead = 1;
+ dostat = doign == 0 || !isign("status", doign);
+ infld = 0;
+ firstline = 1;
+ /*
+ * Process headers first
+ */
+ while (count > 0 && ishead) {
+ if (fgets(line, sizeof(line), ibuf) == NULL)
+ break;
+ count -= length = strlen(line);
+ if (firstline) {
+ /*
+ * First line is the From line, so no headers
+ * there to worry about
+ */
+ firstline = 0;
+ ignoring = doign == ignoreall;
+ } else if (line[0] == '\n') {
+ /*
+ * If line is blank, we've reached end of
+ * headers, so force out status: field
+ * and note that we are no longer in header
+ * fields
+ */
+ if (dostat) {
+ statusput(mp, obuf, prefix);
+ dostat = 0;
+ }
+ ishead = 0;
+ ignoring = doign == ignoreall;
+ } else if (infld && (line[0] == ' ' || line[0] == '\t')) {
+ /*
+ * If this line is a continuation (via space or tab)
+ * of a previous header field, just echo it
+ * (unless the field should be ignored).
+ * In other words, nothing to do.
+ */
+ } else {
+ /*
+ * Pick up the header field if we have one.
+ */
+ for (cp = line; (c = *cp++) != '\0' && c != ':' &&
+ !isspace((unsigned char)c);)
+ ;
+ cp2 = --cp;
+ while (isspace((unsigned char)*cp++))
+ ;
+ if (cp[-1] != ':') {
+ /*
+ * Not a header line, force out status:
+ * This happens in uucp style mail where
+ * there are no headers at all.
+ */
+ if (dostat) {
+ statusput(mp, obuf, prefix);
+ dostat = 0;
+ }
+ if (doign != ignoreall)
+ /* add blank line */
+ (void)putc('\n', obuf);
+ ishead = 0;
+ ignoring = 0;
+ } else {
+ /*
+ * If it is an ignored field and
+ * we care about such things, skip it.
+ */
+ *cp2 = '\0'; /* temporarily null terminate */
+ if (doign && isign(line, doign))
+ ignoring = 1;
+ else if ((line[0] == 's' || line[0] == 'S') &&
+ strcasecmp(line, "status") == 0) {
+ /*
+ * If the field is "status," go compute
+ * and print the real Status: field
+ */
+ if (dostat) {
+ statusput(mp, obuf, prefix);
+ dostat = 0;
+ }
+ ignoring = 1;
+ } else {
+ ignoring = 0;
+ *cp2 = c; /* restore */
+ }
+ infld = 1;
+ }
+ }
+ if (!ignoring) {
+ /*
+ * Strip trailing whitespace from prefix
+ * if line is blank.
+ */
+ if (prefix != NULL) {
+ if (length > 1)
+ fputs(prefix, obuf);
+ else
+ (void)fwrite(prefix, sizeof(*prefix),
+ prefixlen, obuf);
+ }
+ (void)fwrite(line, sizeof(*line), length, obuf);
+ if (ferror(obuf))
+ return (-1);
+ }
+ }
+ /*
+ * Copy out message body
+ */
+ if (doign == ignoreall)
+ count--; /* skip final blank line */
+ if (prefix != NULL)
+ while (count > 0) {
+ if (fgets(line, sizeof(line), ibuf) == NULL) {
+ c = 0;
+ break;
+ }
+ count -= c = strlen(line);
+ /*
+ * Strip trailing whitespace from prefix
+ * if line is blank.
+ */
+ if (c > 1)
+ fputs(prefix, obuf);
+ else
+ (void)fwrite(prefix, sizeof(*prefix),
+ prefixlen, obuf);
+ (void)fwrite(line, sizeof(*line), c, obuf);
+ if (ferror(obuf))
+ return (-1);
+ }
+ else
+ while (count > 0) {
+ c = count < LINESIZE ? count : LINESIZE;
+ if ((c = fread(line, sizeof(*line), c, ibuf)) <= 0)
+ break;
+ count -= c;
+ if (fwrite(line, sizeof(*line), c, obuf) != c)
+ return (-1);
+ }
+ if (doign == ignoreall && c > 0 && line[c - 1] != '\n')
+ /* no final blank line */
+ if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
+ return (-1);
+ return (0);
+}
+
+/*
+ * Output a reasonable looking status field.
+ */
+void
+statusput(struct message *mp, FILE *obuf, char *prefix)
+{
+ char statout[3];
+ char *cp = statout;
+
+ if (mp->m_flag & MREAD)
+ *cp++ = 'R';
+ if ((mp->m_flag & MNEW) == 0)
+ *cp++ = 'O';
+ *cp = '\0';
+ if (statout[0] != '\0')
+ fprintf(obuf, "%sStatus: %s\n",
+ prefix == NULL ? "" : prefix, statout);
+}
+
+/*
+ * Interface between the argument list and the mail1 routine
+ * which does all the dirty work.
+ */
+int
+mail(struct name *to, struct name *cc, struct name *bcc, struct name *smopts,
+ char *subject, char *replyto)
+{
+ struct header head;
+
+ head.h_to = to;
+ head.h_subject = subject;
+ head.h_cc = cc;
+ head.h_bcc = bcc;
+ head.h_smopts = smopts;
+ head.h_replyto = replyto;
+ head.h_inreplyto = NULL;
+ mail1(&head, 0);
+ return (0);
+}
+
+
+/*
+ * Send mail to a bunch of user names. The interface is through
+ * the mail routine below.
+ */
+int
+sendmail(void *str)
+{
+ struct header head;
+
+ head.h_to = extract(str, GTO);
+ head.h_subject = NULL;
+ head.h_cc = NULL;
+ head.h_bcc = NULL;
+ head.h_smopts = NULL;
+ head.h_replyto = value("REPLYTO");
+ head.h_inreplyto = NULL;
+ mail1(&head, 0);
+ return (0);
+}
+
+/*
+ * Mail a message on standard input to the people indicated
+ * in the passed header. (Internal interface).
+ */
+void
+mail1(struct header *hp, int printheaders)
+{
+ char *cp;
+ char *nbuf;
+ int pid;
+ char **namelist;
+ struct name *to, *nsto;
+ FILE *mtf;
+
+ /*
+ * Collect user's mail from standard input.
+ * Get the result as mtf.
+ */
+ if ((mtf = collect(hp, printheaders)) == NULL)
+ return;
+ if (value("interactive") != NULL) {
+ if (value("askcc") != NULL || value("askbcc") != NULL) {
+ if (value("askcc") != NULL)
+ grabh(hp, GCC);
+ if (value("askbcc") != NULL)
+ grabh(hp, GBCC);
+ } else {
+ printf("EOT\n");
+ (void)fflush(stdout);
+ }
+ }
+ if (fsize(mtf) == 0) {
+ if (value("dontsendempty") != NULL)
+ goto out;
+ if (hp->h_subject == NULL)
+ printf("No message, no subject; hope that's ok\n");
+ else
+ printf("Null message body; hope that's ok\n");
+ }
+ /*
+ * Now, take the user names from the combined
+ * to and cc lists and do all the alias
+ * processing.
+ */
+ senderr = 0;
+ to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
+ if (to == NULL) {
+ printf("No recipients specified\n");
+ senderr++;
+ }
+ /*
+ * Look through the recipient list for names with /'s
+ * in them which we write to as files directly.
+ */
+ to = outof(to, mtf, hp);
+ if (senderr)
+ savedeadletter(mtf);
+ to = elide(to);
+ if (count(to) == 0)
+ goto out;
+ if (value("recordrecip") != NULL) {
+ /*
+ * Before fixing the header, save old To:.
+ * We do this because elide above has sorted To: list, and
+ * we would like to save message in a file named by the first
+ * recipient the user has entered, not the one being the first
+ * after sorting happened.
+ */
+ if ((nsto = malloc(sizeof(struct name))) == NULL)
+ err(1, "Out of memory");
+ bcopy(hp->h_to, nsto, sizeof(struct name));
+ }
+ fixhead(hp, to);
+ if ((mtf = infix(hp, mtf)) == NULL) {
+ fprintf(stderr, ". . . message lost, sorry.\n");
+ return;
+ }
+ namelist = unpack(cat(hp->h_smopts, to));
+ if (debug) {
+ char **t;
+
+ printf("Sendmail arguments:");
+ for (t = namelist; *t != NULL; t++)
+ printf(" \"%s\"", *t);
+ printf("\n");
+ goto out;
+ }
+ if (value("recordrecip") != NULL) {
+ /*
+ * Extract first recipient username from saved To: and use it
+ * as a filename.
+ */
+ if ((nbuf = malloc(strlen(detract(nsto, 0)) + 1)) == NULL)
+ err(1, "Out of memory");
+ if ((cp = yanklogin(detract(nsto, 0), nbuf)) != NULL)
+ (void)savemail(expand(nbuf), mtf);
+ free(nbuf);
+ free(nsto);
+ } else if ((cp = value("record")) != NULL)
+ (void)savemail(expand(cp), mtf);
+ /*
+ * Fork, set up the temporary mail file as standard
+ * input for "mail", and exec with the user list we generated
+ * far above.
+ */
+ pid = fork();
+ if (pid == -1) {
+ warn("fork");
+ savedeadletter(mtf);
+ goto out;
+ }
+ if (pid == 0) {
+ sigset_t nset;
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, SIGHUP);
+ (void)sigaddset(&nset, SIGINT);
+ (void)sigaddset(&nset, SIGQUIT);
+ (void)sigaddset(&nset, SIGTSTP);
+ (void)sigaddset(&nset, SIGTTIN);
+ (void)sigaddset(&nset, SIGTTOU);
+ prepare_child(&nset, fileno(mtf), -1);
+ if ((cp = value("sendmail")) != NULL)
+ cp = expand(cp);
+ else
+ cp = _PATH_SENDMAIL;
+ execv(cp, namelist);
+ warn("%s", cp);
+ _exit(1);
+ }
+ if (value("verbose") != NULL)
+ (void)wait_child(pid);
+ else
+ free_child(pid);
+out:
+ (void)Fclose(mtf);
+}
+
+/*
+ * Fix the header by glopping all of the expanded names from
+ * the distribution list into the appropriate fields.
+ */
+void
+fixhead(struct header *hp, struct name *tolist)
+{
+ struct name *np;
+
+ hp->h_to = NULL;
+ hp->h_cc = NULL;
+ hp->h_bcc = NULL;
+ for (np = tolist; np != NULL; np = np->n_flink) {
+ /* Don't copy deleted addresses to the header */
+ if (np->n_type & GDEL)
+ continue;
+ if ((np->n_type & GMASK) == GTO)
+ hp->h_to =
+ cat(hp->h_to, nalloc(np->n_name, np->n_type));
+ else if ((np->n_type & GMASK) == GCC)
+ hp->h_cc =
+ cat(hp->h_cc, nalloc(np->n_name, np->n_type));
+ else if ((np->n_type & GMASK) == GBCC)
+ hp->h_bcc =
+ cat(hp->h_bcc, nalloc(np->n_name, np->n_type));
+ }
+}
+
+/*
+ * Prepend a header in front of the collected stuff
+ * and return the new file.
+ */
+FILE *
+infix(struct header *hp, FILE *fi)
+{
+ FILE *nfo, *nfi;
+ int c, fd;
+ char tempname[PATHSIZE];
+
+ (void)snprintf(tempname, sizeof(tempname),
+ "%s/mail.RsXXXXXXXXXX", tmpdir);
+ if ((fd = mkstemp(tempname)) == -1 ||
+ (nfo = Fdopen(fd, "w")) == NULL) {
+ warn("%s", tempname);
+ return (fi);
+ }
+ if ((nfi = Fopen(tempname, "r")) == NULL) {
+ warn("%s", tempname);
+ (void)Fclose(nfo);
+ (void)rm(tempname);
+ return (fi);
+ }
+ (void)rm(tempname);
+ (void)puthead(hp, nfo,
+ GTO|GSUBJECT|GCC|GBCC|GREPLYTO|GINREPLYTO|GNL|GCOMMA);
+ c = getc(fi);
+ while (c != EOF) {
+ (void)putc(c, nfo);
+ c = getc(fi);
+ }
+ if (ferror(fi)) {
+ warnx("read");
+ rewind(fi);
+ return (fi);
+ }
+ (void)fflush(nfo);
+ if (ferror(nfo)) {
+ warn("%s", tempname);
+ (void)Fclose(nfo);
+ (void)Fclose(nfi);
+ rewind(fi);
+ return (fi);
+ }
+ (void)Fclose(nfo);
+ (void)Fclose(fi);
+ rewind(nfi);
+ return (nfi);
+}
+
+/*
+ * Dump the to, subject, cc header on the
+ * passed file buffer.
+ */
+int
+puthead(struct header *hp, FILE *fo, int w)
+{
+ int gotcha;
+
+ gotcha = 0;
+ if (hp->h_to != NULL && w & GTO)
+ fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
+ if (hp->h_subject != NULL && w & GSUBJECT)
+ fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
+ if (hp->h_cc != NULL && w & GCC)
+ fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
+ if (hp->h_bcc != NULL && w & GBCC)
+ fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
+ if (hp->h_replyto != NULL && w & GREPLYTO)
+ fprintf(fo, "Reply-To: %s\n", hp->h_replyto), gotcha++;
+ if (hp->h_inreplyto != NULL && w & GINREPLYTO)
+ fprintf(fo, "In-Reply-To: <%s>\n", hp->h_inreplyto), gotcha++;
+ if (gotcha && w & GNL)
+ (void)putc('\n', fo);
+ return (0);
+}
+
+/*
+ * Format the given header line to not exceed 72 characters.
+ */
+void
+fmt(const char *str, struct name *np, FILE *fo, int comma)
+{
+ int col, len;
+
+ comma = comma ? 1 : 0;
+ col = strlen(str);
+ if (col)
+ fputs(str, fo);
+ for (; np != NULL; np = np->n_flink) {
+ if (np->n_flink == NULL)
+ comma = 0;
+ len = strlen(np->n_name);
+ col++; /* for the space */
+ if (col + len + comma > 72 && col > 4) {
+ fprintf(fo, "\n ");
+ col = 4;
+ } else
+ fprintf(fo, " ");
+ fputs(np->n_name, fo);
+ if (comma)
+ fprintf(fo, ",");
+ col += len + comma;
+ }
+ fprintf(fo, "\n");
+}
+
+/*
+ * Save the outgoing mail on the passed file.
+ */
+
+/*ARGSUSED*/
+int
+savemail(char name[], FILE *fi)
+{
+ FILE *fo;
+ char buf[BUFSIZ];
+ int i;
+ time_t now;
+ mode_t saved_umask;
+
+ saved_umask = umask(077);
+ fo = Fopen(name, "a");
+ umask(saved_umask);
+
+ if (fo == NULL) {
+ warn("%s", name);
+ return (-1);
+ }
+ (void)time(&now);
+ fprintf(fo, "From %s %s", myname, ctime(&now));
+ while ((i = fread(buf, 1, sizeof(buf), fi)) > 0)
+ (void)fwrite(buf, 1, i, fo);
+ fprintf(fo, "\n");
+ (void)fflush(fo);
+ if (ferror(fo))
+ warn("%s", name);
+ (void)Fclose(fo);
+ rewind(fi);
+ return (0);
+}
diff --git a/usr.bin/mail/strings.c b/usr.bin/mail/strings.c
new file mode 100644
index 000000000000..b3cc217dbded
--- /dev/null
+++ b/usr.bin/mail/strings.c
@@ -0,0 +1,120 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * String allocation routines.
+ * Strings handed out here are reclaimed at the top of the command
+ * loop each time, so they need not be freed.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+struct strings stringdope[NSPACE];
+
+/*
+ * Allocate size more bytes of space and return the address of the
+ * first byte to the caller. An even number of bytes are always
+ * allocated so that the space will always be on a word boundary.
+ * The string spaces are of exponentially increasing size, to satisfy
+ * the occasional user with enormous string size requests.
+ */
+
+char *
+salloc(int size)
+{
+ char *t;
+ int s, index;
+ struct strings *sp;
+
+ s = size;
+ s += (sizeof(char *) - 1);
+ s &= ~(sizeof(char *) - 1);
+ index = 0;
+ for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) {
+ if (sp->s_topFree == NULL && (STRINGSIZE << index) >= s)
+ break;
+ if (sp->s_nleft >= s)
+ break;
+ index++;
+ }
+ if (sp >= &stringdope[NSPACE])
+ errx(1, "String too large");
+ if (sp->s_topFree == NULL) {
+ index = sp - &stringdope[0];
+ if ((sp->s_topFree = malloc(STRINGSIZE << index)) == NULL)
+ err(1, "No room for space %d", index);
+ sp->s_nextFree = sp->s_topFree;
+ sp->s_nleft = STRINGSIZE << index;
+ }
+ sp->s_nleft -= s;
+ t = sp->s_nextFree;
+ sp->s_nextFree += s;
+ return (t);
+}
+
+/*
+ * Reset the string area to be empty.
+ * Called to free all strings allocated
+ * since last reset.
+ */
+void
+sreset(void)
+{
+ struct strings *sp;
+ int index;
+
+ if (noreset)
+ return;
+ index = 0;
+ for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) {
+ if (sp->s_topFree == NULL)
+ continue;
+ sp->s_nextFree = sp->s_topFree;
+ sp->s_nleft = STRINGSIZE << index;
+ index++;
+ }
+}
+
+/*
+ * Make the string area permanent.
+ * Meant to be called in main, after initialization.
+ */
+void
+spreserve(void)
+{
+ struct strings *sp;
+
+ for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++)
+ sp->s_topFree = NULL;
+}
diff --git a/usr.bin/mail/temp.c b/usr.bin/mail/temp.c
new file mode 100644
index 000000000000..34a473af0e38
--- /dev/null
+++ b/usr.bin/mail/temp.c
@@ -0,0 +1,82 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Give names to all the temporary files that we will need.
+ */
+
+char *tmpdir;
+
+void
+tinit(void)
+{
+ char *cp;
+
+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+ tmpdir = _PATH_TMP;
+ if ((tmpdir = strdup(tmpdir)) == NULL)
+ errx(1, "Out of memory");
+ /* Strip trailing '/' if necessary */
+ cp = tmpdir + strlen(tmpdir) - 1;
+ while (cp > tmpdir && *cp == '/') {
+ *cp = '\0';
+ cp--;
+ }
+
+ /*
+ * It's okay to call savestr in here because main will
+ * do a spreserve() after us.
+ */
+ if (myname != NULL) {
+ if (getuserid(myname) < 0)
+ errx(1, "\"%s\" is not a user of this system", myname);
+ } else {
+ if ((cp = username()) == NULL) {
+ myname = "ubluit";
+ if (rcvmode)
+ errx(1, "Who are you!?");
+ } else
+ myname = savestr(cp);
+ }
+ if ((cp = getenv("HOME")) == NULL || *cp == '\0' ||
+ strlen(cp) >= PATHSIZE)
+ homedir = NULL;
+ else
+ homedir = savestr(cp);
+ if (debug)
+ printf("user = %s, homedir = %s\n", myname,
+ homedir ? homedir : "NONE");
+}
diff --git a/usr.bin/mail/tty.c b/usr.bin/mail/tty.c
new file mode 100644
index 000000000000..937a43bb3789
--- /dev/null
+++ b/usr.bin/mail/tty.c
@@ -0,0 +1,288 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Generally useful tty stuff.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+static cc_t c_erase; /* Current erase char */
+static cc_t c_kill; /* Current kill char */
+static jmp_buf rewrite; /* Place to go when continued */
+static jmp_buf intjmp; /* Place to go when interrupted */
+#ifndef TIOCSTI
+static int ttyset; /* We must now do erase/kill */
+#endif
+
+/*
+ * Read all relevant header fields.
+ */
+
+int
+grabh(struct header *hp, int gflags)
+{
+ struct termios ttybuf;
+ volatile sig_t saveint;
+ sig_t savetstp;
+ sig_t savettou;
+ sig_t savettin;
+ int errs;
+#ifndef TIOCSTI
+ sig_t savequit;
+#else
+# ifdef TIOCEXT
+ int extproc, flag;
+# endif /* TIOCEXT */
+#endif /* TIOCSTI */
+
+ savetstp = signal(SIGTSTP, SIG_DFL);
+ savettou = signal(SIGTTOU, SIG_DFL);
+ savettin = signal(SIGTTIN, SIG_DFL);
+ errs = 0;
+#ifndef TIOCSTI
+ ttyset = 0;
+#endif
+ if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
+ warn("tcgetattr(stdin)");
+ return (-1);
+ }
+ c_erase = ttybuf.c_cc[VERASE];
+ c_kill = ttybuf.c_cc[VKILL];
+#ifndef TIOCSTI
+ ttybuf.c_cc[VERASE] = _POSIX_VDISABLE;
+ ttybuf.c_cc[VKILL] = _POSIX_VDISABLE;
+ if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
+ (void)signal(SIGINT, SIG_DFL);
+ if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
+ (void)signal(SIGQUIT, SIG_DFL);
+#else
+# ifdef TIOCEXT
+ extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
+ if (extproc) {
+ flag = 0;
+ if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
+ warn("TIOCEXT: off");
+ }
+# endif /* TIOCEXT */
+ if (setjmp(intjmp))
+ goto out;
+ saveint = signal(SIGINT, ttyint);
+#endif
+ if (gflags & GTO) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_to != NULL)
+ ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
+#endif
+ hp->h_to =
+ extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
+ }
+ if (gflags & GSUBJECT) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_subject != NULL)
+ ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
+#endif
+ hp->h_subject = readtty("Subject: ", hp->h_subject);
+ }
+ if (gflags & GCC) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_cc != NULL)
+ ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
+#endif
+ hp->h_cc =
+ extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
+ }
+ if (gflags & GBCC) {
+#ifndef TIOCSTI
+ if (!ttyset && hp->h_bcc != NULL)
+ ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
+#endif
+ hp->h_bcc =
+ extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
+ }
+#ifdef TIOCSTI
+out:
+#endif
+ (void)signal(SIGTSTP, savetstp);
+ (void)signal(SIGTTOU, savettou);
+ (void)signal(SIGTTIN, savettin);
+#ifndef TIOCSTI
+ ttybuf.c_cc[VERASE] = c_erase;
+ ttybuf.c_cc[VKILL] = c_kill;
+ if (ttyset)
+ tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
+ (void)signal(SIGQUIT, savequit);
+#else
+# ifdef TIOCEXT
+ if (extproc) {
+ flag = 1;
+ if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
+ warn("TIOCEXT: on");
+ }
+# endif /* TIOCEXT */
+#endif
+ (void)signal(SIGINT, saveint);
+ return (errs);
+}
+
+/*
+ * Read up a header from standard input.
+ * The source string has the preliminary contents to
+ * be read.
+ *
+ */
+
+char *
+readtty(const char *pr, char src[])
+{
+ char canonb[BUFSIZ];
+#ifdef TIOCSTI
+ char ch;
+#endif
+ int c;
+ char *cp, *cp2;
+
+ fputs(pr, stdout);
+ (void)fflush(stdout);
+ if (src != NULL && strlen(src) > BUFSIZ - 2) {
+ printf("too long to edit\n");
+ return (src);
+ }
+#ifndef TIOCSTI
+ if (src != NULL)
+ strlcpy(canonb, src, sizeof(canonb));
+ else
+ *canonb = '\0';
+ fputs(canonb, stdout);
+ (void)fflush(stdout);
+#else
+ cp = src == NULL ? "" : src;
+ while ((c = *cp++) != '\0') {
+ if ((c_erase != _POSIX_VDISABLE && c == c_erase) ||
+ (c_kill != _POSIX_VDISABLE && c == c_kill)) {
+ ch = '\\';
+ ioctl(0, TIOCSTI, &ch);
+ }
+ ch = c;
+ ioctl(0, TIOCSTI, &ch);
+ }
+ cp = canonb;
+ *cp = '\0';
+#endif
+ cp2 = cp;
+ while (cp2 < canonb + BUFSIZ)
+ *cp2++ = '\0';
+ cp2 = cp;
+ if (setjmp(rewrite))
+ goto redo;
+ (void)signal(SIGTSTP, ttystop);
+ (void)signal(SIGTTOU, ttystop);
+ (void)signal(SIGTTIN, ttystop);
+ clearerr(stdin);
+ while (cp2 < canonb + BUFSIZ) {
+ c = getc(stdin);
+ if (c == EOF || c == '\n')
+ break;
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+ (void)signal(SIGTSTP, SIG_DFL);
+ (void)signal(SIGTTOU, SIG_DFL);
+ (void)signal(SIGTTIN, SIG_DFL);
+ if (c == EOF && ferror(stdin)) {
+redo:
+ cp = strlen(canonb) > 0 ? canonb : NULL;
+ clearerr(stdin);
+ return (readtty(pr, cp));
+ }
+#ifndef TIOCSTI
+ if (cp == NULL || *cp == '\0')
+ return (src);
+ cp2 = cp;
+ if (!ttyset)
+ return (strlen(canonb) > 0 ? savestr(canonb) : NULL);
+ while (*cp != '\0') {
+ c = *cp++;
+ if (c_erase != _POSIX_VDISABLE && c == c_erase) {
+ if (cp2 == canonb)
+ continue;
+ if (cp2[-1] == '\\') {
+ cp2[-1] = c;
+ continue;
+ }
+ cp2--;
+ continue;
+ }
+ if (c_kill != _POSIX_VDISABLE && c == c_kill) {
+ if (cp2 == canonb)
+ continue;
+ if (cp2[-1] == '\\') {
+ cp2[-1] = c;
+ continue;
+ }
+ cp2 = canonb;
+ continue;
+ }
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+#endif
+ if (equal("", canonb))
+ return (NULL);
+ return (savestr(canonb));
+}
+
+/*
+ * Receipt continuation.
+ */
+void
+ttystop(int s)
+{
+ sig_t old_action = signal(s, SIG_DFL);
+ sigset_t nset;
+
+ (void)sigemptyset(&nset);
+ (void)sigaddset(&nset, s);
+ (void)sigprocmask(SIG_BLOCK, &nset, NULL);
+ kill(0, s);
+ (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
+ (void)signal(s, old_action);
+ longjmp(rewrite, 1);
+}
+
+void
+ttyint(int s __unused)
+{
+ longjmp(intjmp, 1);
+}
diff --git a/usr.bin/mail/util.c b/usr.bin/mail/util.c
new file mode 100644
index 000000000000..ce53c7108a0d
--- /dev/null
+++ b/usr.bin/mail/util.c
@@ -0,0 +1,593 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/time.h>
+
+#include <fcntl.h>
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Auxiliary functions.
+ */
+
+static char *save2str(char *, char *);
+
+/*
+ * Return a pointer to a dynamic copy of the argument.
+ */
+char *
+savestr(char *str)
+{
+ char *new;
+ int size = strlen(str) + 1;
+
+ if ((new = salloc(size)) != NULL)
+ bcopy(str, new, size);
+ return (new);
+}
+
+/*
+ * Make a copy of new argument incorporating old one.
+ */
+static char *
+save2str(char *str, char *old)
+{
+ char *new;
+ int newsize = strlen(str) + 1;
+ int oldsize = old ? strlen(old) + 1 : 0;
+
+ if ((new = salloc(newsize + oldsize)) != NULL) {
+ if (oldsize) {
+ bcopy(old, new, oldsize);
+ new[oldsize - 1] = ' ';
+ }
+ bcopy(str, new + oldsize, newsize);
+ }
+ return (new);
+}
+
+/*
+ * Touch the named message by setting its MTOUCH flag.
+ * Touched messages have the effect of not being sent
+ * back to the system mailbox on exit.
+ */
+void
+touch(struct message *mp)
+{
+
+ mp->m_flag |= MTOUCH;
+ if ((mp->m_flag & MREAD) == 0)
+ mp->m_flag |= MREAD|MSTATUS;
+}
+
+/*
+ * Test to see if the passed file name is a directory.
+ * Return true if it is.
+ */
+int
+isdir(char name[])
+{
+ struct stat sbuf;
+
+ if (stat(name, &sbuf) < 0)
+ return (0);
+ return (S_ISDIR(sbuf.st_mode));
+}
+
+/*
+ * Count the number of arguments in the given string raw list.
+ */
+int
+argcount(char **argv)
+{
+ char **ap;
+
+ for (ap = argv; *ap++ != NULL;)
+ ;
+ return (ap - argv - 1);
+}
+
+/*
+ * Return the desired header line from the passed message
+ * pointer (or NULL if the desired header field is not available).
+ */
+char *
+hfield(const char *field, struct message *mp)
+{
+ FILE *ibuf;
+ char linebuf[LINESIZE];
+ int lc;
+ char *hfield;
+ char *colon, *oldhfield = NULL;
+
+ ibuf = setinput(mp);
+ if ((lc = mp->m_lines - 1) < 0)
+ return (NULL);
+ if (readline(ibuf, linebuf, LINESIZE) < 0)
+ return (NULL);
+ while (lc > 0) {
+ if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
+ return (oldhfield);
+ if ((hfield = ishfield(linebuf, colon, field)) != NULL)
+ oldhfield = save2str(hfield, oldhfield);
+ }
+ return (oldhfield);
+}
+
+/*
+ * Return the next header field found in the given message.
+ * Return >= 0 if something found, < 0 elsewise.
+ * "colon" is set to point to the colon in the header.
+ * Must deal with \ continuations & other such fraud.
+ */
+int
+gethfield(FILE *f, char linebuf[], int rem, char **colon)
+{
+ char line2[LINESIZE];
+ char *cp, *cp2;
+ int c;
+
+ for (;;) {
+ if (--rem < 0)
+ return (-1);
+ if ((c = readline(f, linebuf, LINESIZE)) <= 0)
+ return (-1);
+ for (cp = linebuf; isprint((unsigned char)*cp) && *cp != ' ' && *cp != ':';
+ cp++)
+ ;
+ if (*cp != ':' || cp == linebuf)
+ continue;
+ /*
+ * I guess we got a headline.
+ * Handle wraparounding
+ */
+ *colon = cp;
+ cp = linebuf + c;
+ for (;;) {
+ while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
+ ;
+ cp++;
+ if (rem <= 0)
+ break;
+ ungetc(c = getc(f), f);
+ if (c != ' ' && c != '\t')
+ break;
+ if ((c = readline(f, line2, LINESIZE)) < 0)
+ break;
+ rem--;
+ for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
+ ;
+ c -= cp2 - line2;
+ if (cp + c >= linebuf + LINESIZE - 2)
+ break;
+ *cp++ = ' ';
+ bcopy(cp2, cp, c);
+ cp += c;
+ }
+ *cp = 0;
+ return (rem);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Check whether the passed line is a header line of
+ * the desired breed. Return the field body, or 0.
+ */
+
+char*
+ishfield(char *linebuf, char *colon, const char *field)
+{
+ char *cp = colon;
+
+ *cp = 0;
+ if (strcasecmp(linebuf, field) != 0) {
+ *cp = ':';
+ return (0);
+ }
+ *cp = ':';
+ for (cp++; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ return (cp);
+}
+
+/*
+ * Copy a string and lowercase the result.
+ * dsize: space left in buffer (including space for NULL)
+ */
+void
+istrncpy(char *dest, const char *src, size_t dsize)
+{
+
+ strlcpy(dest, src, dsize);
+ for (; *dest; dest++)
+ *dest = tolower((unsigned char)*dest);
+}
+
+/*
+ * The following code deals with input stacking to do source
+ * commands. All but the current file pointer are saved on
+ * the stack.
+ */
+
+static int ssp; /* Top of file stack */
+struct sstack {
+ FILE *s_file; /* File we were in. */
+ int s_cond; /* Saved state of conditionals */
+ int s_loading; /* Loading .mailrc, etc. */
+};
+#define SSTACK_SIZE 64 /* XXX was NOFILE. */
+static struct sstack sstack[SSTACK_SIZE];
+
+/*
+ * Pushdown current input file and switch to a new one.
+ * Set the global flag "sourcing" so that others will realize
+ * that they are no longer reading from a tty (in all probability).
+ */
+int
+source(void *arg)
+{
+ char **arglist = arg;
+ FILE *fi;
+ char *cp;
+
+ if ((cp = expand(*arglist)) == NULL)
+ return (1);
+ if ((fi = Fopen(cp, "r")) == NULL) {
+ warn("%s", cp);
+ return (1);
+ }
+ if (ssp >= SSTACK_SIZE - 1) {
+ printf("Too much \"sourcing\" going on.\n");
+ (void)Fclose(fi);
+ return (1);
+ }
+ sstack[ssp].s_file = input;
+ sstack[ssp].s_cond = cond;
+ sstack[ssp].s_loading = loading;
+ ssp++;
+ loading = 0;
+ cond = CANY;
+ input = fi;
+ sourcing++;
+ return (0);
+}
+
+/*
+ * Pop the current input back to the previous level.
+ * Update the "sourcing" flag as appropriate.
+ */
+int
+unstack(void)
+{
+ if (ssp <= 0) {
+ printf("\"Source\" stack over-pop.\n");
+ sourcing = 0;
+ return (1);
+ }
+ (void)Fclose(input);
+ if (cond != CANY)
+ printf("Unmatched \"if\"\n");
+ ssp--;
+ cond = sstack[ssp].s_cond;
+ loading = sstack[ssp].s_loading;
+ input = sstack[ssp].s_file;
+ if (ssp == 0)
+ sourcing = loading;
+ return (0);
+}
+
+/*
+ * Touch the indicated file.
+ * This is nifty for the shell.
+ */
+void
+alter(char *name)
+{
+ struct timespec ts[2];
+
+ (void)clock_gettime(CLOCK_REALTIME, &ts[0]);
+ ts[0].tv_sec++;
+ ts[1].tv_sec = 0;
+ ts[1].tv_nsec = UTIME_OMIT;
+ (void)utimensat(AT_FDCWD, name, ts, 0);
+}
+
+/*
+ * Get sender's name from this message. If the message has
+ * a bunch of arpanet stuff in it, we may have to skin the name
+ * before returning it.
+ */
+char *
+nameof(struct message *mp, int reptype)
+{
+ char *cp, *cp2;
+
+ cp = skin(name1(mp, reptype));
+ if (reptype != 0 || charcount(cp, '!') < 2)
+ return (cp);
+ cp2 = strrchr(cp, '!');
+ cp2--;
+ while (cp2 > cp && *cp2 != '!')
+ cp2--;
+ if (*cp2 == '!')
+ return (cp2 + 1);
+ return (cp);
+}
+
+/*
+ * Start of a "comment".
+ * Ignore it.
+ */
+char *
+skip_comment(char *cp)
+{
+ int nesting = 1;
+
+ for (; nesting > 0 && *cp; cp++) {
+ switch (*cp) {
+ case '\\':
+ if (cp[1])
+ cp++;
+ break;
+ case '(':
+ nesting++;
+ break;
+ case ')':
+ nesting--;
+ break;
+ }
+ }
+ return (cp);
+}
+
+/*
+ * Skin an arpa net address according to the RFC 822 interpretation
+ * of "host-phrase."
+ */
+char *
+skin(char *name)
+{
+ char *nbuf, *bufend, *cp, *cp2;
+ int c, gotlt, lastsp;
+
+ if (name == NULL)
+ return (NULL);
+ if (strchr(name, '(') == NULL && strchr(name, '<') == NULL
+ && strchr(name, ' ') == NULL)
+ return (name);
+
+ /* We assume that length(input) <= length(output) */
+ if ((nbuf = malloc(strlen(name) + 1)) == NULL)
+ err(1, "Out of memory");
+ gotlt = 0;
+ lastsp = 0;
+ bufend = nbuf;
+ for (cp = name, cp2 = bufend; (c = *cp++) != '\0'; ) {
+ switch (c) {
+ case '(':
+ cp = skip_comment(cp);
+ lastsp = 0;
+ break;
+
+ case '"':
+ /*
+ * Start of a "quoted-string".
+ * Copy it in its entirety.
+ */
+ while ((c = *cp) != '\0') {
+ cp++;
+ if (c == '"')
+ break;
+ if (c != '\\')
+ *cp2++ = c;
+ else if ((c = *cp) != '\0') {
+ *cp2++ = c;
+ cp++;
+ }
+ }
+ lastsp = 0;
+ break;
+
+ case ' ':
+ if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ')
+ cp += 3, *cp2++ = '@';
+ else
+ if (cp[0] == '@' && cp[1] == ' ')
+ cp += 2, *cp2++ = '@';
+ else
+ lastsp = 1;
+ break;
+
+ case '<':
+ cp2 = bufend;
+ gotlt++;
+ lastsp = 0;
+ break;
+
+ case '>':
+ if (gotlt) {
+ gotlt = 0;
+ while ((c = *cp) != '\0' && c != ',') {
+ cp++;
+ if (c == '(')
+ cp = skip_comment(cp);
+ else if (c == '"')
+ while ((c = *cp) != '\0') {
+ cp++;
+ if (c == '"')
+ break;
+ if (c == '\\' && *cp != '\0')
+ cp++;
+ }
+ }
+ lastsp = 0;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ if (lastsp) {
+ lastsp = 0;
+ *cp2++ = ' ';
+ }
+ *cp2++ = c;
+ if (c == ',' && !gotlt &&
+ (*cp == ' ' || *cp == '"' || *cp == '<')) {
+ *cp2++ = ' ';
+ while (*cp == ' ')
+ cp++;
+ lastsp = 0;
+ bufend = cp2;
+ }
+ }
+ }
+ *cp2 = '\0';
+
+ if ((cp = realloc(nbuf, strlen(nbuf) + 1)) != NULL)
+ nbuf = cp;
+ return (nbuf);
+}
+
+/*
+ * Fetch the sender's name from the passed message.
+ * Reptype can be
+ * 0 -- get sender's name for display purposes
+ * 1 -- get sender's name for reply
+ * 2 -- get sender's name for Reply
+ */
+char *
+name1(struct message *mp, int reptype)
+{
+ char namebuf[LINESIZE];
+ char linebuf[LINESIZE];
+ char *cp, *cp2;
+ FILE *ibuf;
+ int first = 1;
+
+ if ((cp = hfield("from", mp)) != NULL)
+ return (cp);
+ if (reptype == 0 && (cp = hfield("sender", mp)) != NULL)
+ return (cp);
+ ibuf = setinput(mp);
+ namebuf[0] = '\0';
+ if (readline(ibuf, linebuf, LINESIZE) < 0)
+ return (savestr(namebuf));
+newname:
+ for (cp = linebuf; *cp != '\0' && *cp != ' '; cp++)
+ ;
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ for (cp2 = &namebuf[strlen(namebuf)];
+ *cp != '\0' && *cp != ' ' && *cp != '\t' &&
+ cp2 < namebuf + LINESIZE - 1;)
+ *cp2++ = *cp++;
+ *cp2 = '\0';
+ if (readline(ibuf, linebuf, LINESIZE) < 0)
+ return (savestr(namebuf));
+ if ((cp = strchr(linebuf, 'F')) == NULL)
+ return (savestr(namebuf));
+ if (strncmp(cp, "From", 4) != 0)
+ return (savestr(namebuf));
+ while ((cp = strchr(cp, 'r')) != NULL) {
+ if (strncmp(cp, "remote", 6) == 0) {
+ if ((cp = strchr(cp, 'f')) == NULL)
+ break;
+ if (strncmp(cp, "from", 4) != 0)
+ break;
+ if ((cp = strchr(cp, ' ')) == NULL)
+ break;
+ cp++;
+ if (first) {
+ cp2 = namebuf;
+ first = 0;
+ } else
+ cp2 = strrchr(namebuf, '!') + 1;
+ strlcpy(cp2, cp, sizeof(namebuf) - (cp2 - namebuf) - 1);
+ strcat(namebuf, "!");
+ goto newname;
+ }
+ cp++;
+ }
+ return (savestr(namebuf));
+}
+
+/*
+ * Count the occurrences of c in str
+ */
+int
+charcount(char *str, int c)
+{
+ char *cp;
+ int i;
+
+ for (i = 0, cp = str; *cp != '\0'; cp++)
+ if (*cp == c)
+ i++;
+ return (i);
+}
+
+/*
+ * See if the given header field is supposed to be ignored.
+ */
+int
+isign(const char *field, struct ignoretab ignore[2])
+{
+ char realfld[LINESIZE];
+
+ if (ignore == ignoreall)
+ return (1);
+ /*
+ * Lower-case the string, so that "Status" and "status"
+ * will hash to the same place.
+ */
+ istrncpy(realfld, field, sizeof(realfld));
+ if (ignore[1].i_count > 0)
+ return (!member(realfld, ignore + 1));
+ else
+ return (member(realfld, ignore));
+}
+
+int
+member(char *realfield, struct ignoretab *table)
+{
+ struct ignore *igp;
+
+ for (igp = table->i_head[hash(realfield)]; igp != NULL; igp = igp->i_link)
+ if (*igp->i_field == *realfield &&
+ equal(igp->i_field, realfield))
+ return (1);
+ return (0);
+}
diff --git a/usr.bin/mail/v7.local.c b/usr.bin/mail/v7.local.c
new file mode 100644
index 000000000000..6390b4235ace
--- /dev/null
+++ b/usr.bin/mail/v7.local.c
@@ -0,0 +1,90 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Version 7
+ *
+ * Local routines that are installation dependent.
+ */
+
+#include "rcv.h"
+#include <fcntl.h>
+#include "extern.h"
+
+/*
+ * Locate the user's mailbox file (ie, the place where new, unread
+ * mail is queued).
+ */
+void
+findmail(char *user, char *buf, int buflen)
+{
+ char *tmp = getenv("MAIL");
+
+ if (tmp == NULL)
+ (void)snprintf(buf, buflen, "%s/%s", _PATH_MAILDIR, user);
+ else
+ (void)strlcpy(buf, tmp, buflen);
+}
+
+/*
+ * Get rid of the queued mail.
+ */
+void
+demail(void)
+{
+ int fd;
+
+ if (value("keep") != NULL || rm(mailname) < 0)
+ if ((fd = open(mailname, O_CREAT | O_TRUNC | O_WRONLY, 0600)) >=
+ 0)
+ (void)close(fd);
+}
+
+/*
+ * Discover user login name.
+ */
+char *
+username(void)
+{
+ char *np;
+ uid_t uid;
+
+ if ((np = getenv("USER")) != NULL)
+ return (np);
+ if ((np = getenv("LOGNAME")) != NULL)
+ return (np);
+ if ((np = getname(uid = getuid())) != NULL)
+ return (np);
+ printf("Cannot associate a name with uid %u\n", (unsigned)uid);
+ return (NULL);
+}
diff --git a/usr.bin/mail/vars.c b/usr.bin/mail/vars.c
new file mode 100644
index 000000000000..e55ac7c37779
--- /dev/null
+++ b/usr.bin/mail/vars.c
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include "rcv.h"
+#include "extern.h"
+
+/*
+ * Mail -- a mail program
+ *
+ * Variable handling stuff.
+ */
+
+/*
+ * Assign a value to a variable.
+ */
+void
+assign(const char *name, const char *value)
+{
+ struct var *vp;
+ int h;
+
+ h = hash(name);
+ vp = lookup(name);
+ if (vp == NULL) {
+ if ((vp = calloc(1, sizeof(*vp))) == NULL)
+ err(1, "Out of memory");
+ vp->v_name = vcopy(name);
+ vp->v_link = variables[h];
+ variables[h] = vp;
+ }
+ else
+ vfree(vp->v_value);
+ vp->v_value = vcopy(value);
+}
+
+/*
+ * Free up a variable string. We do not bother to allocate
+ * strings whose value is "" since they are expected to be frequent.
+ * Thus, we cannot free same!
+ */
+void
+vfree(char *cp)
+{
+ if (*cp != '\0')
+ (void)free(cp);
+}
+
+/*
+ * Copy a variable value into permanent (ie, not collected after each
+ * command) space. Do not bother to alloc space for ""
+ */
+
+char *
+vcopy(const char *str)
+{
+ char *new;
+ unsigned len;
+
+ if (*str == '\0')
+ return ("");
+ len = strlen(str) + 1;
+ if ((new = malloc(len)) == NULL)
+ err(1, "Out of memory");
+ bcopy(str, new, (int)len);
+ return (new);
+}
+
+/*
+ * Get the value of a variable and return it.
+ * Look in the environment if its not available locally.
+ */
+
+char *
+value(const char *name)
+{
+ struct var *vp;
+
+ if ((vp = lookup(name)) == NULL)
+ return (getenv(name));
+ return (vp->v_value);
+}
+
+/*
+ * Locate a variable and return its variable
+ * node.
+ */
+
+struct var *
+lookup(const char *name)
+{
+ struct var *vp;
+
+ for (vp = variables[hash(name)]; vp != NULL; vp = vp->v_link)
+ if (*vp->v_name == *name && equal(vp->v_name, name))
+ return (vp);
+ return (NULL);
+}
+
+/*
+ * Locate a group name and return it.
+ */
+
+struct grouphead *
+findgroup(char name[])
+{
+ struct grouphead *gh;
+
+ for (gh = groups[hash(name)]; gh != NULL; gh = gh->g_link)
+ if (*gh->g_name == *name && equal(gh->g_name, name))
+ return (gh);
+ return (NULL);
+}
+
+/*
+ * Print a group out on stdout
+ */
+void
+printgroup(char name[])
+{
+ struct grouphead *gh;
+ struct group *gp;
+
+ if ((gh = findgroup(name)) == NULL) {
+ printf("\"%s\": not a group\n", name);
+ return;
+ }
+ printf("%s\t", gh->g_name);
+ for (gp = gh->g_list; gp != NULL; gp = gp->ge_link)
+ printf(" %s", gp->ge_name);
+ printf("\n");
+}
+
+/*
+ * Hash the passed string and return an index into
+ * the variable or group hash table.
+ */
+int
+hash(const char *name)
+{
+ int h = 0;
+
+ while (*name != '\0') {
+ h <<= 2;
+ h += *name++;
+ }
+ if (h < 0 && (h = -h) < 0)
+ h = 0;
+ return (h % HSHSIZE);
+}
diff --git a/usr.bin/mail/version.c b/usr.bin/mail/version.c
new file mode 100644
index 000000000000..c44f8539a73a
--- /dev/null
+++ b/usr.bin/mail/version.c
@@ -0,0 +1,36 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * Just keep track of the date/sid of this version of Mail.
+ * Load this file first to get a "total" Mail version.
+ */
+const char *version = "8.1 6/6/93";
diff --git a/usr.bin/man/Makefile b/usr.bin/man/Makefile
new file mode 100644
index 000000000000..9c9098270735
--- /dev/null
+++ b/usr.bin/man/Makefile
@@ -0,0 +1,6 @@
+SCRIPTS= man.sh
+LINKS= ${BINDIR}/man ${BINDIR}/manpath
+
+MAN= man.1 manpath.1 man.conf.5
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/man/Makefile.depend b/usr.bin/man/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/man/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/man/man.1 b/usr.bin/man/man.1
new file mode 100644
index 000000000000..820d6a5b33a9
--- /dev/null
+++ b/usr.bin/man/man.1
@@ -0,0 +1,424 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2010 Gordon Tetlow
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 January 24, 2025
+.Dt MAN 1
+.Os
+.Sh NAME
+.Nm man
+.Nd display online manual documentation pages
+.Sh SYNOPSIS
+.Nm
+.Op Fl adho
+.Op Fl t | w
+.Op Fl M Ar manpath
+.Op Fl P Ar pager
+.Op Fl S Ar mansect
+.Op Fl m Ar arch Ns Op : Ns Ar machine
+.Op Fl p Op Ar eprtv
+.Op Ar mansect
+.Ar page | Ar
+.Nm
+.Fl K | f | k
+.Ar expression ...
+.Sh DESCRIPTION
+The
+.Nm
+utility finds and displays online manual documentation pages.
+If
+.Ar mansect
+is provided,
+.Nm
+restricts the search to the specific section of the manual.
+.Pp
+The sections of the manual are:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+.Fx
+General Commands Manual
+.It
+.Fx
+System Calls Manual
+.It
+.Fx
+Library Functions Manual
+.It
+.Fx
+Kernel Interfaces Manual
+.It
+.Fx
+File Formats Manual
+.It
+.Fx
+Games Manual
+.It
+.Fx
+Miscellaneous Information Manual
+.It
+.Fx
+System Manager's Manual
+.It
+.Fx
+Kernel Developer's Manual
+.El
+.Pp
+Options that
+.Nm
+understands:
+.Bl -tag -width indent
+.It Fl K Ar expression
+Search full text of all manual pages for an extended regular
+.Ar expression ,
+as described in
+.Xr re_format 7 .
+This option requires
+.Xr mandoc 1 .
+This is a slow operation.
+.It Fl M Ar manpath
+Force a specific colon separated manual path instead of the default
+search path.
+See
+.Ev MANPATH
+in
+.Sx ENVIRONMENT .
+.It Fl P Ar pager
+Use specified pager.
+Defaults to
+.Ql less -sR
+if color support is enabled, or
+.Ql less -s .
+Overrides the
+.Ev MANPAGER
+environment variable, which in turn overrides the
+.Ev PAGER
+environment variable.
+.It Fl S Ar mansect
+Restrict manual sections searched to the specified colon delimited list.
+Defaults to
+.Ql 1:8:2:3:3lua:n:4:5:6:7:9:l .
+Overrides the
+.Ev MANSECT
+environment variable.
+.It Fl a
+Display all manual pages instead of just the first found for each
+.Ar page
+argument.
+.It Fl d
+Print extra debugging information.
+Repeat for increased verbosity.
+Does not display the manual page.
+.It Fl f Ar expression
+Search names of all manual pages for an extended regular
+.Ar expression ,
+emulating
+.Xr whatis 1 .
+.It Fl h
+Display short help message and exit.
+.It Fl k Ar expression
+Search names and descriptions of all manual pages for an extended regular
+.Ar expression ,
+emulating basic functionality of
+.Xr apropos 1 .
+.It Fl m Ar arch Ns Op : Ns Ar machine
+Override the default architecture and machine settings allowing lookup of
+other platform specific manual pages.
+See
+.Sx IMPLEMENTATION NOTES
+for how this option changes the default behavior.
+Overrides the
+.Ev MACHINE_ARCH
+and
+.Ev MACHINE
+environment variables.
+.It Fl o
+Force use of non-localized manual pages.
+See
+.Sx IMPLEMENTATION NOTES
+for how locale specific searches work.
+Overrides the
+.Ev LC_ALL , LC_CTYPE ,
+and
+.Ev LANG
+environment variables.
+.It Fl p Op Cm eprtv
+Use the list of given preprocessors before running
+.Xr nroff 1 Pq Pa ports/textproc/groff
+or
+.Xr troff 1 Pq Pa ports/textproc/groff .
+Valid preprocessors arguments:
+.Pp
+.Bl -tag -width indent -compact
+.It Cm e
+.Xr eqn 1 Pq Pa ports/textproc/groff
+.It Cm p
+.Xr pic 1 Pq Pa ports/textproc/groff
+.It Cm r
+.Xr refer 1 Pq Pa ports/textproc/groff
+.It Cm t
+.Xr tbl 1 Pq Pa ports/textproc/groff
+.It Cm v
+.Xr vgrind 1
+.El
+.Pp
+Overrides the
+.Ev MANROFFSEQ
+environment variable.
+.It Fl t
+Send manual page source through
+.Xr troff 1 Pq Pa ports/textproc/groff
+allowing transformation of the manual pages to other formats.
+.It Fl w
+Display the location of the manual page instead of the contents of
+the manual page.
+.El
+.Sh IMPLEMENTATION NOTES
+.Ss Locale Specific Searches
+The
+.Nm
+utility supports manual pages in different locales.
+The search behavior is dictated by the first of three
+environment variables with a nonempty string:
+.Ev LC_ALL , LC_CTYPE ,
+or
+.Ev LANG .
+If set,
+.Nm
+will search for locale specific manual pages using the following logic:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Va lang Ns _ Ns Va country . Ns Va charset
+.It
+.Va lang . Ns Va charset
+.It
+.Li en . Ns Va charset
+.El
+.Pp
+For example, if
+.Ev LC_ALL
+is set to
+.Ql ja_JP.eucJP ,
+.Nm
+will search the following paths when considering section 1 manual pages in
+.Pa /usr/share/man :
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Pa /usr/share/man/ja_JP.eucJP/man1
+.It
+.Pa /usr/share/man/ja.eucJP/man1
+.It
+.Pa /usr/share/man/en.eucJP/man1
+.It
+.Pa /usr/share/man/man1
+.El
+.Ss Platform Specific Searches
+The
+.Nm
+utility supports platform specific manual pages.
+The search behavior is dictated by the
+.Fl m
+option or the
+.Ev MACHINE_ARCH
+and
+.Ev MACHINE
+environment variables.
+For example, if
+.Ev MACHINE_ARCH
+is set to
+.Ql aarch64
+and
+.Ev MACHINE
+is set to
+.Ql arm64 ,
+.Nm
+will search the following paths when considering section 4 manual pages in
+.Pa /usr/share/man :
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Pa /usr/share/man/man4/aarch64
+.It
+.Pa /usr/share/man/man4/arm64
+.It
+.Pa /usr/share/man/man4
+.El
+.Ss Displaying Specific Manual Files
+The
+.Nm
+utility also supports displaying a specific manual page if passed a path
+to the file as long as it contains a
+.Ql /
+character.
+.Sh ENVIRONMENT
+The following environment variables affect the execution of
+.Nm :
+.Bl -tag -width indent
+.It Ev LC_ALL , Ev LC_CTYPE , Ev LANG
+Used to find locale specific manual pages.
+Valid values can be found by running the
+.Xr locale 1
+command.
+See
+.Sx IMPLEMENTATION NOTES
+for details.
+Influenced by the
+.Fl o
+option.
+.It Ev MACHINE_ARCH , Ev MACHINE
+Used to find platform specific manual pages.
+If unset, the output of
+.Ql sysctl Va hw.machine_arch
+and
+.Ql sysctl Va hw.machine
+is used respectively.
+See
+.Sx IMPLEMENTATION NOTES
+for details.
+Corresponds to the
+.Fl m
+option.
+.It Ev MANPATH
+A colon
+.Pq Ql \&:
+separated list of directories to check for manual pages.
+Invalid paths, or paths without manual databases, are ignored.
+Overridden by
+.Fl M .
+If
+.Ev MANPATH
+begins with a colon, it is appended to the default list;
+if it ends with a colon, it is prepended to the default list;
+or if it contains two adjacent colons,
+the standard search path is inserted between the colons.
+If none of these conditions are met, it overrides the
+standard search path.
+See
+.Xr manpath 1 .
+.It Ev MANROFFSEQ
+Used to determine the preprocessors for the manual source before running
+.Xr nroff 1 Pq Pa ports/textproc/groff
+or
+.Xr troff 1 Pq Pa ports/textproc/groff .
+If unset, defaults to
+.Xr tbl 1 Pq Pa ports/textproc/groff .
+Corresponds to the
+.Fl p
+option.
+.It Ev MANSECT
+Restricts manual sections searched to the specified colon delimited list.
+Corresponds to the
+.Fl S
+option.
+.It Ev MANWIDTH
+If set to a numeric value, used as the width manpages should be displayed.
+Otherwise, if set to a special value
+.Ql tty ,
+and output is to a terminal,
+the pages may be displayed over the whole width of the screen.
+.It Ev MANCOLOR
+If set, enables color support.
+.It Ev MANPAGER
+Program used to display files.
+.Pp
+If unset, and color support is enabled,
+.Ql less -sR
+is used.
+.Pp
+If unset, and color support is disabled, then
+.Ev PAGER
+is used.
+If that has no value either,
+.Ql less -s
+is used.
+.El
+.Sh FILES
+.Bl -tag -width "/usr/local/etc/man.d/*.conf" -compact
+.It Pa /etc/man.conf
+System configuration file
+.It Pa /usr/local/etc/man.d/*.conf
+Local configuration files
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show the manual page for
+.Xr stat 2 :
+.Pp
+.Dl $ man 2 stat
+.Pp
+Show all manual pages for
+.Ql stat :
+.Pp
+.Dl $ man -a stat
+.Pp
+List manual pages which match the regular expression either in the title or in
+the body:
+.Pp
+.Dl $ man -k '\e<copy\e>.*archive'
+.Pp
+Show the manual page for
+.Xr ls 1
+using
+.Xr cat 1
+as the pager:
+.Pp
+.Dl $ man -P cat ls
+.Pp
+Show the location of the
+.Xr ls 1
+manual page:
+.Pp
+.Dl $ man -w ls
+.Pp
+Show a manual page in the current working directory:
+.Pp
+.Dl $ man ./man.1
+.Pp
+Show the location of manual pages in sections 1 and 8 which contain the word
+.Ql arm :
+.Pp
+.Dl $ man -w -K '\e<arm\e>' -S 1:8
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr intro 1 ,
+.Xr mandoc 1 ,
+.Xr manpath 1 ,
+.Xr whatis 1 ,
+.Xr intro 2 ,
+.Xr intro 3 ,
+.Xr intro 3lua ,
+.Xr intro 4 ,
+.Xr intro 5 ,
+.Xr man.conf 5 ,
+.Xr intro 6 ,
+.Xr intro 7 ,
+.Xr mdoc 7 ,
+.Xr re_format 7 ,
+.Xr intro 8 ,
+.Xr intro 9
diff --git a/usr.bin/man/man.conf.5 b/usr.bin/man/man.conf.5
new file mode 100644
index 000000000000..90595bb6d498
--- /dev/null
+++ b/usr.bin/man/man.conf.5
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2010 Gordon Tetlow
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 June 3, 2011
+.Dt MAN.CONF 5
+.Os
+.Sh NAME
+.Nm man.conf
+.Nd
+.Xr man 1
+and
+.Xr manpath 1
+configuration files
+.Sh DESCRIPTION
+The
+.Nm
+file is used to configure the manual search path, locales, and utility set for
+.Xr man 1
+and its related utilities.
+During initialization,
+.Xr man 1
+reads the configuration files located at
+.Pa /usr/local/etc/man.d/*.conf
+and
+.Pa /etc/man.conf .
+.Pp
+The files contained in
+.Pa /usr/local/etc/man.d/*.conf
+are intended to be used by the
+.Xr ports 7
+system for extending the manual set to support additional paths and locales.
+.Pa /etc/man.conf
+is intended to be used by the local administrator to set additional policy.
+.Pp
+Currently supported configuration variables include:
+.Bl -tag -width 12n -offset indent
+.It MANCONFIG
+Overrides the default location to import additional manual configuration files.
+Defaults to
+.Pa /usr/local/etc/man.d/*.conf .
+.It MANPATH
+Adds the specified directory to the manual search path.
+.It MANLOCALE
+Indicates support is available for the given locale.
+.El
+.Pp
+For pages in a given language, overriding the default toolset for
+display is supported via the following definitions:
+.Pp
+.Bl -tag -width 12n -offset indent -compact
+.It EQN Ns _ Ns Va LANG
+.It NROFF Ns _ Ns Va LANG
+.It PIC Ns _ Ns Va LANG
+.It TBL Ns _ Ns Va LANG
+.It TROFF Ns _ Ns Va LANG
+.It REFER Ns _ Ns Va LANG
+.It VGRIND Ns _ Ns Va LANG
+.El
+.Pp
+See the
+.Sx EXAMPLES
+section for how to use these variables.
+.Sh IMPLEMENTATION NOTES
+The parser used for this utility is very basic and only supports comment
+characters (#) at the beginning of a line.
+.Sh FILES
+.Bl -tag -width "Pa /usr/local/etc/man.d/*.conf" -compact
+.It Pa /etc/man.conf
+System configuration file.
+.It Pa /usr/local/etc/man.d/*.conf
+Local configuration files.
+.El
+.Sh EXAMPLES
+A perl port that needs to install additional manual pages outside of the
+default location could install a file in
+.Pa /usr/local/etc/man.d/perl.conf
+with the following contents:
+.Bd -literal -offset indent
+# Add perl man pages to search path
+MANPATH /usr/local/lib/perl5/5.8.9/man
+MANPATH /usr/local/lib/perl5/5.8.9/perl/man
+.Ed
+.Pp
+A Japanese localization port could install a custom toolset and include a
+file in
+.Pa /usr/local/etc/man.d/ja-man-doc.conf
+with the following contents:
+.Bd -literal -offset indent
+# Setup Japanese toolset
+MANLOCALE ja_JP.eucJP
+EQN_JA /usr/local/bin/geqn
+PIC_JA /usr/local/bin/gpic
+TBL_JA /usr/local/bin/gtbl
+NROFF_JA /usr/local/bin/groff -mandoc -dlang=ja_JP.eucJP
+TROFF_JA /usr/local/bin/groff -mandoc -dlang=ja_JP.euc.jp
+.Ed
+.Pp
+If the system administrator decides to override the
+.Va LOCALBASE
+.Xr make 1
+variable causing all
+.Xr ports 7
+to be installed into
+.Pa /opt
+instead of
+.Pa /usr/local ,
+specifying the following in
+.Pa /etc/man.conf
+will accommodate this change:
+.Bd -literal -offset indent
+# Look for additional configuration files
+MANCONFIG /opt/etc/man.d/*.conf
+.Ed
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr man 1 ,
+.Xr manpath 1 ,
+.Xr whatis 1
diff --git a/usr.bin/man/man.sh b/usr.bin/man/man.sh
new file mode 100755
index 000000000000..68a4b3a40588
--- /dev/null
+++ b/usr.bin/man/man.sh
@@ -0,0 +1,1119 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2010 Gordon Tetlow
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+# Rendering a manual page is fast. Even a manual page several 100k in size
+# takes less than a CPU second. If it takes much longer, it is very likely
+# that a tool like mandoc(1) is running in an infinite loop. In this case
+# it is better to terminate it.
+ulimit -t 20
+
+# do not ignore the exit status of roff tools
+set -o pipefail
+
+# Usage: add_to_manpath path
+# Adds a variable to manpath while ensuring we don't have duplicates.
+# Returns true if we were able to add something. False otherwise.
+add_to_manpath() {
+ case "$manpath" in
+ *:$1) decho " Skipping duplicate manpath entry $1" 2 ;;
+ $1:*) decho " Skipping duplicate manpath entry $1" 2 ;;
+ *:$1:*) decho " Skipping duplicate manpath entry $1" 2 ;;
+ *) if [ -d "$1" ]; then
+ decho " Adding $1 to manpath"
+ manpath="$manpath:$1"
+ return 0
+ fi
+ ;;
+ esac
+
+ return 1
+}
+
+# Usage: build_manlocales
+# Builds a correct MANLOCALES variable.
+build_manlocales() {
+ # If the user has set manlocales, who are we to argue.
+ if [ -n "$MANLOCALES" ]; then
+ return
+ fi
+
+ parse_configs
+
+ # Trim leading colon
+ MANLOCALES=${manlocales#:}
+
+ decho "Available manual locales: $MANLOCALES"
+}
+
+# Usage: build_mansect
+# Builds a correct MANSECT variable.
+build_mansect() {
+ # If the user has set mansect, who are we to argue.
+ if [ -n "$MANSECT" ]; then
+ return
+ fi
+
+ parse_configs
+
+ # Trim leading colon
+ MANSECT=${mansect#:}
+
+ if [ -z "$MANSECT" ]; then
+ MANSECT=$man_default_sections
+ fi
+ decho "Using manual sections: $MANSECT"
+}
+
+# Usage: build_manpath
+# Builds a correct MANPATH variable.
+build_manpath() {
+ local IFS
+
+ # If the user has set a manpath, who are we to argue.
+ if [ -n "$MANPATH" ]; then
+ case "$MANPATH" in
+ *:) PREPEND_MANPATH=${MANPATH} ;;
+ :*) APPEND_MANPATH=${MANPATH} ;;
+ *::*)
+ PREPEND_MANPATH=${MANPATH%%::*}
+ APPEND_MANPATH=${MANPATH#*::}
+ ;;
+ *) return ;;
+ esac
+ fi
+
+ if [ -n "$PREPEND_MANPATH" ]; then
+ IFS=:
+ for path in $PREPEND_MANPATH; do
+ add_to_manpath "$path"
+ done
+ unset IFS
+ fi
+
+ search_path
+
+ decho "Adding default manpath entries"
+ IFS=:
+ for path in $man_default_path; do
+ add_to_manpath "$path"
+ done
+ unset IFS
+
+ parse_configs
+
+ if [ -n "$APPEND_MANPATH" ]; then
+ IFS=:
+ for path in $APPEND_MANPATH; do
+ add_to_manpath "$path"
+ done
+ unset IFS
+ fi
+ # Trim leading colon
+ MANPATH=${manpath#:}
+
+ decho "Using manual path: $MANPATH"
+}
+
+# Usage: check_cat catglob
+# Checks to see if a cat glob is available.
+check_cat() {
+ if exists "$1"; then
+ use_cat=yes
+ catpage=$found
+ setup_cattool "$catpage"
+ decho " Found catpage \"$catpage\""
+ return 0
+ else
+ return 1
+ fi
+}
+
+# Usage: check_man manglob catglob
+# Given 2 globs, figures out if the manglob is available, if so, check to
+# see if the catglob is also available and up to date.
+check_man() {
+ if exists "$1"; then
+ # We have a match, check for a cat page
+ manpage=$found
+ setup_cattool "$manpage"
+ decho " Found manpage \"$manpage\""
+
+ if [ -n "${use_width}" ]; then
+ # non-standard width
+ unset use_cat
+ decho " Skipping catpage: non-standard page width"
+ elif exists "$2" && is_newer $found "$manpage"; then
+ # cat page found and is newer, use that
+ use_cat=yes
+ catpage=$found
+ setup_cattool "$catpage"
+ decho " Using catpage \"$catpage\""
+ else
+ # no cat page or is older
+ unset use_cat
+ decho " Skipping catpage: not found or old"
+ fi
+ return 0
+ fi
+
+ return 1
+}
+
+# Usage: decho "string" [debuglevel]
+# Echoes to stderr string prefaced with -- if high enough debuglevel.
+decho() {
+ if [ $debug -ge ${2:-1} ]; then
+ echo "-- $1" >&2
+ fi
+}
+
+# Usage: exists glob
+#
+# Returns true if glob resolves to a real file and store the first
+# found filename in the variable $found
+exists() {
+ if [ -z "$1" ]; then
+ return 1
+ fi
+
+ local IFS
+
+ # Don't accidentally inherit callers IFS (breaks perl manpages)
+ unset IFS
+
+ # Use some globbing tricks in the shell to determine if a file
+ # exists or not.
+ set +f
+ for file in "$1"*
+ do
+ if [ -r "$file" ]; then
+ found="$file"
+ set -f
+ return 0
+ fi
+ done
+ set -f
+
+ return 1
+}
+
+# Usage: find_file path section subdir pagename
+# Returns: true if something is matched and found.
+# Search the given path/section combo for a given page.
+find_file() {
+ local manroot catroot mann man0 catn cat0
+
+ manroot="$1/man$2"
+ catroot="$1/cat$2"
+ if [ -n "$3" ]; then
+ manroot="$manroot/$3"
+ catroot="$catroot/$3"
+ fi
+
+ if [ ! -d "$manroot" -a ! -d "$catroot" ]; then
+ return 1
+ fi
+ decho " Searching directory $manroot" 2
+
+ mann="$manroot/$4.$2"
+ man0="$manroot/$4.0"
+ catn="$catroot/$4.$2"
+ cat0="$catroot/$4.0"
+
+ # This is the behavior as seen by the original man utility.
+ # Let's not change that which doesn't seem broken.
+ if check_man "$mann" "$catn"; then
+ return 0
+ elif check_man "$man0" "$cat0"; then
+ return 0
+ elif check_cat "$catn"; then
+ return 0
+ elif check_cat "$cat0"; then
+ return 0
+ fi
+
+ return 1
+}
+
+# Usage: is_newer file1 file2
+# Returns true if file1 is newer than file2 as calculated by mtime.
+is_newer() {
+ if ! [ "$1" -ot "$2" ]; then
+ decho " mtime: $1 not older than $2" 3
+ return 0
+ else
+ decho " mtime: $1 older than $2" 3
+ return 1
+ fi
+}
+
+# Usage: manpath_parse_args "$@"
+# Parses commandline options for manpath.
+manpath_parse_args() {
+ local cmd_arg
+
+ OPTIND=1
+ while getopts 'Ldq' cmd_arg; do
+ case "${cmd_arg}" in
+ L) Lflag=Lflag ;;
+ d) debug=$(( $debug + 1 )) ;;
+ q) qflag=qflag ;;
+ *) manpath_usage ;;
+ esac
+ done >&2
+}
+
+# Usage: manpath_usage
+# Display usage for the manpath(1) utility.
+manpath_usage() {
+ echo 'usage: manpath [-Ldq]' >&2
+ exit 1
+}
+
+# Usage: manpath_warnings
+# Display some warnings to stderr.
+manpath_warnings() {
+ if [ -n "$Lflag" -a -n "$MANLOCALES" ]; then
+ echo "(Warning: MANLOCALES environment variable set)" >&2
+ fi
+}
+
+# Usage: man_check_for_so path
+# Returns: True if able to resolve the file, false if it ended in tears.
+# Detects the presence of the .so directive and causes the file to be
+# redirected to another source file.
+man_check_for_so() {
+ local IFS line tstr
+
+ unset IFS
+ if [ -n "$catpage" ]; then
+ return 0
+ fi
+
+ # We need to loop to accommodate multiple .so directives.
+ while true
+ do
+ line=$($cattool "$manpage" 2>/dev/null | grep -E -m1 -v '^\.\\"[ ]*|^[ ]*$')
+ case "$line" in
+ '.so /'*) break ;; # ignore absolute path
+ '.so '*) trim "${line#.so}"
+ decho "$manpage includes $tstr"
+ # Glob and check for the file.
+ if ! check_man "$1/$tstr" ""; then
+ decho " Unable to find $tstr"
+ return 1
+ fi
+ ;;
+ *) break ;;
+ esac
+ done
+
+ return 0
+}
+
+# Usage: man_display_page
+# Display either the manpage or catpage depending on the use_cat variable
+man_display_page() {
+ local IFS pipeline testline
+
+ # We are called with IFS set to colon. This causes really weird
+ # things to happen for the variables that have spaces in them.
+ unset IFS
+
+ # If we are supposed to use a catpage and we aren't using troff(1)
+ # just zcat the catpage and we are done.
+ if [ -z "$tflag" -a -n "$use_cat" ]; then
+ if [ -n "$wflag" ]; then
+ echo "$catpage (source: \"$manpage\")"
+ ret=0
+ else
+ if [ $debug -gt 0 ]; then
+ decho "Command: $cattool \"$catpage\" | $MANPAGER"
+ ret=0
+ else
+ $cattool "$catpage" | $MANPAGER
+ ret=$?
+ fi
+ fi
+ return
+ fi
+
+ # Okay, we are using the manpage, do we just need to output the
+ # name of the manpage?
+ if [ -n "$wflag" ]; then
+ echo "$manpage"
+ ret=0
+ return
+ fi
+
+ if [ -n "$use_width" ]; then
+ mandoc_args="-O width=${use_width}"
+ fi
+ testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1"
+ if [ -n "$tflag" ]; then
+ pipeline="mandoc -Tps $mandoc_args"
+ else
+ pipeline="mandoc $mandoc_args | $MANPAGER"
+ fi
+
+ if ! $cattool "$manpage" | eval "$testline"; then
+ if which -s groff; then
+ man_display_page_groff
+ else
+ echo "This manpage needs groff(1) to be rendered" >&2
+ echo "First install groff(1): " >&2
+ echo "pkg install groff " >&2
+ ret=1
+ fi
+ return
+ fi
+
+ if [ $debug -gt 0 ]; then
+ decho "Command: $cattool \"$manpage\" | eval \"$pipeline\""
+ ret=0
+ else
+ $cattool "$manpage" | eval "$pipeline"
+ ret=$?
+ fi
+}
+
+# Usage: man_display_page_groff
+# Display the manpage using groff
+man_display_page_groff() {
+ local EQN NROFF PIC TBL TROFF REFER VGRIND
+ local IFS l nroff_dev pipeline preproc_arg tool
+
+ # So, we really do need to parse the manpage. First, figure out the
+ # device flag (-T) we have to pass to eqn(1) and groff(1). Then,
+ # setup the pipeline of commands based on the user's request.
+
+ # If the manpage is from a particular charset, we need to setup nroff
+ # to properly output for the correct device.
+ case "${manpage}" in
+ *.${man_charset}/*)
+ # I don't pretend to know this; I'm just copying from the
+ # previous version of man(1).
+ case "$man_charset" in
+ KOI8-R) nroff_dev="koi8-r" ;;
+ ISO8859-1) nroff_dev="latin1" ;;
+ ISO8859-15) nroff_dev="latin1" ;;
+ UTF-8) nroff_dev="utf8" ;;
+ *) nroff_dev="ascii" ;;
+ esac
+
+ NROFF="$NROFF -T$nroff_dev"
+ EQN="$EQN -T$nroff_dev"
+
+ # Iff the manpage is from the locale and not just the charset,
+ # then we need to define the locale string.
+ case "${manpage}" in
+ */${man_lang}_${man_country}.${man_charset}/*)
+ NROFF="$NROFF -dlocale=$man_lang.$man_charset"
+ ;;
+ */${man_lang}.${man_charset}/*)
+ NROFF="$NROFF -dlocale=$man_lang.$man_charset"
+ ;;
+ esac
+
+ # Allow language specific calls to override the default
+ # set of utilities.
+ l=$(echo $man_lang | tr [:lower:] [:upper:])
+ for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do
+ eval "$tool=\${${tool}_$l:-\$$tool}"
+ done
+ ;;
+ *) NROFF="$NROFF -Tascii"
+ EQN="$EQN -Tascii"
+ ;;
+ esac
+
+ if [ -z "$MANCOLOR" ]; then
+ NROFF="$NROFF -P-c"
+ fi
+
+ if [ -n "${use_width}" ]; then
+ NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n"
+ fi
+
+ if [ -n "$MANROFFSEQ" ]; then
+ set -- -$MANROFFSEQ
+ OPTIND=1
+ while getopts 'egprtv' preproc_arg; do
+ case "${preproc_arg}" in
+ e) pipeline="$pipeline | $EQN" ;;
+ g) ;; # Ignore for compatibility.
+ p) pipeline="$pipeline | $PIC" ;;
+ r) pipeline="$pipeline | $REFER" ;;
+ t) pipeline="$pipeline | $TBL" ;;
+ v) pipeline="$pipeline | $VGRIND" ;;
+ *) usage ;;
+ esac
+ done
+ # Strip the leading " | " from the resulting pipeline.
+ pipeline="${pipeline#" | "}"
+ else
+ pipeline="$TBL"
+ fi
+
+ if [ -n "$tflag" ]; then
+ pipeline="$pipeline | $TROFF"
+ else
+ pipeline="$pipeline | $NROFF | $MANPAGER"
+ fi
+
+ if [ $debug -gt 0 ]; then
+ decho "Command: $cattool \"$manpage\" | eval \"$pipeline\""
+ ret=0
+ else
+ $cattool "$manpage" | eval "$pipeline"
+ ret=$?
+ fi
+}
+
+# Usage: man_find_and_display page
+# Search through the manpaths looking for the given page.
+man_find_and_display() {
+ local found_page locpath p path sect
+
+ # Check to see if it's a file. But only if it has a '/' in
+ # the filename.
+ case "$1" in
+ */*) if [ -f "$1" -a -r "$1" ]; then
+ decho "Found a usable page, displaying that"
+ unset use_cat
+ manpage="$1"
+ setup_cattool "$manpage"
+ p=$(cd "$(dirname "$manpage")" && pwd)
+ case "$(basename "$p")" in
+ man*|cat*) p=$p/.. ;;
+ *) p=$p/../.. ;;
+ esac
+ if man_check_for_so "$p"; then
+ found_page=yes
+ man_display_page
+ fi
+ return
+ fi
+ ;;
+ esac
+
+ IFS=:
+ for sect in $MANSECT; do
+ decho "Searching section $sect" 2
+ for path in $MANPATH; do
+ for locpath in $locpaths; do
+ p=$path/$locpath
+ p=${p%/.} # Rid ourselves of the trailing /.
+
+ # Check if there is a MACHINE specific manpath.
+ if find_file $p $sect $MACHINE "$1"; then
+ if man_check_for_so $p; then
+ found_page=yes
+ man_display_page
+ if [ -n "$aflag" ]; then
+ continue 2
+ else
+ return
+ fi
+ fi
+ fi
+
+ # Check if there is a MACHINE_ARCH
+ # specific manpath.
+ if find_file $p $sect $MACHINE_ARCH "$1"; then
+ if man_check_for_so $p; then
+ found_page=yes
+ man_display_page
+ if [ -n "$aflag" ]; then
+ continue 2
+ else
+ return
+ fi
+ fi
+ fi
+
+ # Check plain old manpath.
+ if find_file $p $sect '' "$1"; then
+ if man_check_for_so $p; then
+ found_page=yes
+ man_display_page
+ if [ -n "$aflag" ]; then
+ continue 2
+ else
+ return
+ fi
+ fi
+ fi
+ done
+ done
+ done
+ unset IFS
+
+ # Nothing? Well, we are done then.
+ if [ -z "$found_page" ]; then
+ echo "No manual entry for \"$1\"" >&2
+ ret=1
+ return
+ fi
+}
+
+# Usage: man_parse_opts "$@"
+# Parses commandline options for man.
+man_parse_opts() {
+ local cmd_arg
+
+ OPTIND=1
+ while getopts 'K:M:P:S:adfhkm:op:tw' cmd_arg; do
+ case "${cmd_arg}" in
+ K) Kflag=Kflag
+ REGEXP=$OPTARG ;;
+ M) MANPATH=$OPTARG ;;
+ P) MANPAGER=$OPTARG ;;
+ S) MANSECT=$OPTARG ;;
+ a) aflag=aflag ;;
+ d) debug=$(( $debug + 1 )) ;;
+ f) fflag=fflag ;;
+ h) man_usage 0 ;;
+ k) kflag=kflag ;;
+ m) mflag=$OPTARG ;;
+ o) oflag=oflag ;;
+ p) MANROFFSEQ=$OPTARG ;;
+ t) tflag=tflag ;;
+ w) wflag=wflag ;;
+ *) man_usage ;;
+ esac
+ done >&2
+
+ shift $(( $OPTIND - 1 ))
+
+ # Check the args for incompatible options.
+
+ case "${Kflag}${fflag}${kflag}${tflag}${wflag}" in
+ Kflagfflag*) echo "Incompatible options: -K and -f"; man_usage ;;
+ Kflag*kflag*) echo "Incompatible options: -K and -k"; man_usage ;;
+ Kflag*tflag) echo "Incompatible options: -K and -t"; man_usage ;;
+ fflagkflag*) echo "Incompatible options: -f and -k"; man_usage ;;
+ fflag*tflag*) echo "Incompatible options: -f and -t"; man_usage ;;
+ fflag*wflag) echo "Incompatible options: -f and -w"; man_usage ;;
+ *kflagtflag*) echo "Incompatible options: -k and -t"; man_usage ;;
+ *kflag*wflag) echo "Incompatible options: -k and -w"; man_usage ;;
+ *tflagwflag) echo "Incompatible options: -t and -w"; man_usage ;;
+ esac
+
+ # Short circuit for whatis(1) and apropos(1)
+ if [ -n "$fflag" ]; then
+ do_whatis "$@"
+ exit
+ fi
+
+ if [ -n "$kflag" ]; then
+ do_apropos "$@"
+ exit
+ fi
+}
+
+# Usage: man_setup
+# Setup various trivial but essential variables.
+man_setup() {
+ # Setup machine and architecture variables.
+ if [ -n "$mflag" ]; then
+ MACHINE_ARCH=${mflag%%:*}
+ MACHINE=${mflag##*:}
+ fi
+ if [ -z "$MACHINE_ARCH" ]; then
+ MACHINE_ARCH=$($SYSCTL -n hw.machine_arch)
+ fi
+ if [ -z "$MACHINE" ]; then
+ MACHINE=$($SYSCTL -n hw.machine)
+ fi
+ decho "Using architecture: $MACHINE_ARCH:$MACHINE"
+
+ setup_pager
+ build_manpath
+ build_mansect
+ man_setup_locale
+ man_setup_width
+}
+
+# Usage: man_setup_width
+# Set up page width.
+man_setup_width() {
+ local sizes
+
+ unset use_width
+ case "$MANWIDTH" in
+ [0-9]*)
+ if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then
+ use_width=$MANWIDTH
+ fi
+ ;;
+ [Tt][Tt][Yy])
+ if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then
+ set -- $sizes
+ if [ $2 -gt 80 ]; then
+ use_width=$(($2-2))
+ fi
+ fi
+ ;;
+ esac
+ if [ -n "$use_width" ]; then
+ decho "Using non-standard page width: ${use_width}"
+ else
+ decho 'Using standard page width'
+ fi
+}
+
+# Usage: man_setup_locale
+# Setup necessary locale variables.
+man_setup_locale() {
+ local lang_cc
+ local locstr
+
+ locpaths='.'
+ man_charset='US-ASCII'
+
+ # Setup locale information.
+ if [ -n "$oflag" ]; then
+ decho 'Using non-localized manpages'
+ else
+ # Use the locale tool to give us proper locale information
+ eval $( $LOCALE )
+
+ if [ -n "$LANG" ]; then
+ locstr=$LANG
+ else
+ locstr=$LC_CTYPE
+ fi
+
+ case "$locstr" in
+ C) ;;
+ C.UTF-8) ;;
+ POSIX) ;;
+ [a-z][a-z]_[A-Z][A-Z]\.*)
+ lang_cc="${locstr%.*}"
+ man_lang="${locstr%_*}"
+ man_country="${lang_cc#*_}"
+ man_charset="${locstr#*.}"
+ locpaths="$locstr"
+ locpaths="$locpaths:$man_lang.$man_charset"
+ if [ "$man_lang" != "en" ]; then
+ locpaths="$locpaths:en.$man_charset"
+ fi
+ locpaths="$locpaths:."
+ ;;
+ *) echo 'Unknown locale, assuming C' >&2
+ ;;
+ esac
+ fi
+
+ decho "Using locale paths: $locpaths"
+}
+
+# Usage: man_usage [exitcode]
+# Display usage for the man utility.
+man_usage() {
+ echo 'Usage:'
+ echo ' man [-adho] [-t | -w] [-M manpath] [-P pager] [-S mansect]'
+ echo ' [-m arch[:machine]] [-p [eprtv]] [mansect] page [...]'
+ echo ' man -K | -f | -k expression [...] -- Search manual pages'
+
+ # When exit'ing with -h, it's not an error.
+ exit ${1:-1}
+}
+
+# Usage: parse_configs
+# Reads the end-user adjustable config files.
+parse_configs() {
+ local IFS file files
+
+ if [ -n "$parsed_configs" ]; then
+ return
+ fi
+
+ unset IFS
+
+ # Read the global config first in case the user wants
+ # to override config_local.
+ if [ -r "$config_global" ]; then
+ parse_file "$config_global"
+ fi
+
+ # Glob the list of files to parse.
+ set +f
+ files=$(echo $config_local)
+ set -f
+
+ for file in $files; do
+ if [ -r "$file" ]; then
+ parse_file "$file"
+ fi
+ done
+
+ parsed_configs='yes'
+}
+
+# Usage: parse_file file
+# Reads the specified config files.
+parse_file() {
+ local file line tstr var
+
+ file="$1"
+ decho "Parsing config file: $file"
+ while read line; do
+ decho " $line" 2
+ case "$line" in
+ \#*) decho " Comment" 3
+ ;;
+ MANPATH*) decho " MANPATH" 3
+ trim "${line#MANPATH}"
+ add_to_manpath "$tstr"
+ ;;
+ MANLOCALE*) decho " MANLOCALE" 3
+ trim "${line#MANLOCALE}"
+ manlocales="$manlocales:$tstr"
+ ;;
+ MANCONFIG*) decho " MANCONFIG" 3
+ trim "${line#MANCONFIG}"
+ config_local="$tstr"
+ ;;
+ MANSECT*) decho " MANSECT" 3
+ trim "${line#MANSECT}"
+ mansect="$mansect:$tstr"
+ ;;
+ # Set variables in the form of FOO_BAR
+ *_*[\ \ ]*) var="${line%%[\ \ ]*}"
+ trim "${line#$var}"
+ eval "$var=\"$tstr\""
+ decho " Parsed $var" 3
+ ;;
+ esac
+ done < "$file"
+}
+
+# Usage: search_path
+# Traverse $PATH looking for manpaths.
+search_path() {
+ local IFS p path
+
+ decho "Searching PATH for man directories"
+
+ IFS=:
+ for path in $PATH; do
+ if add_to_manpath "$path/man"; then
+ :
+ elif add_to_manpath "$path/MAN"; then
+ :
+ else
+ case "$path" in
+ */bin) p="${path%/bin}/share/man"
+ add_to_manpath "$p"
+ p="${path%/bin}/man"
+ add_to_manpath "$p"
+ ;;
+ esac
+ fi
+ done
+ unset IFS
+
+ if [ -z "$manpath" ]; then
+ decho ' Unable to find any manpaths, using default'
+ manpath=$man_default_path
+ fi
+}
+
+# Usage: search_whatis cmd [arglist]
+# Do the heavy lifting for apropos/whatis
+search_whatis() {
+ local IFS bad cmd f good key keywords loc opt out path rval wlist
+
+ cmd="$1"
+ shift
+
+ whatis_parse_args "$@"
+
+ build_manpath
+ build_manlocales
+ setup_pager
+
+ if [ "$cmd" = "whatis" ]; then
+ opt="-w"
+ fi
+
+ f='whatis'
+
+ IFS=:
+ for path in $MANPATH; do
+ if [ \! -d "$path" ]; then
+ decho "Skipping non-existent path: $path" 2
+ continue
+ fi
+
+ if [ -f "$path/$f" -a -r "$path/$f" ]; then
+ decho "Found whatis: $path/$f"
+ wlist="$wlist $path/$f"
+ fi
+
+ for loc in $MANLOCALES; do
+ if [ -f "$path/$loc/$f" -a -r "$path/$loc/$f" ]; then
+ decho "Found whatis: $path/$loc/$f"
+ wlist="$wlist $path/$loc/$f"
+ fi
+ done
+ done
+ unset IFS
+
+ if [ -z "$wlist" ]; then
+ echo "$cmd: no whatis databases in $MANPATH" >&2
+ exit 1
+ fi
+
+ rval=0
+ for key in $keywords; do
+ out=$(grep -Ehi $opt -- "$key" $wlist)
+ if [ -n "$out" ]; then
+ good="$good\\n$out"
+ else
+ bad="$bad\\n$key: nothing appropriate"
+ rval=1
+ fi
+ done
+
+ # Strip leading carriage return.
+ good=${good#\\n}
+ bad=${bad#\\n}
+
+ if [ -n "$good" ]; then
+ printf '%b\n' "$good" | $MANPAGER
+ fi
+
+ if [ -n "$bad" ]; then
+ printf '%b\n' "$bad" >&2
+ fi
+
+ exit $rval
+}
+
+# Usage: setup_cattool page
+# Finds an appropriate decompressor based on extension
+setup_cattool() {
+ case "$1" in
+ *.bz) cattool='/usr/bin/bzcat' ;;
+ *.bz2) cattool='/usr/bin/bzcat' ;;
+ *.gz) cattool='/usr/bin/gzcat' ;;
+ *.lzma) cattool='/usr/bin/lzcat' ;;
+ *.xz) cattool='/usr/bin/xzcat' ;;
+ *.zst) cattool='/usr/bin/zstdcat' ;;
+ *) cattool='/usr/bin/zcat -f' ;;
+ esac
+}
+
+# Usage: setup_pager
+# Correctly sets $MANPAGER
+setup_pager() {
+ # Setup pager.
+ if [ -z "$MANPAGER" ]; then
+ if [ -n "$MANCOLOR" ]; then
+ MANPAGER="less -sR"
+ else
+ if [ -n "$PAGER" ]; then
+ MANPAGER="$PAGER"
+ else
+ MANPAGER="less -s"
+ fi
+ fi
+ fi
+ decho "Using pager: $MANPAGER"
+}
+
+# Usage: trim string
+# Trims whitespace from beginning and end of a variable
+trim() {
+ tstr=$1
+ while true; do
+ case "$tstr" in
+ [\ \ ]*) tstr="${tstr##[\ \ ]}" ;;
+ *[\ \ ]) tstr="${tstr%%[\ \ ]}" ;;
+ *) break ;;
+ esac
+ done
+}
+
+# Usage: whatis_parse_args "$@"
+# Parse commandline args for whatis and apropos.
+whatis_parse_args() {
+ local cmd_arg
+ OPTIND=1
+ while getopts 'd' cmd_arg; do
+ case "${cmd_arg}" in
+ d) debug=$(( $debug + 1 )) ;;
+ *) whatis_usage ;;
+ esac
+ done >&2
+
+ shift $(( $OPTIND - 1 ))
+
+ keywords="$*"
+}
+
+# Usage: whatis_usage
+# Display usage for the whatis/apropos utility.
+whatis_usage() {
+ echo "usage: $cmd [-d] keyword [...]"
+ exit 1
+}
+
+
+
+# Supported commands
+do_apropos() {
+ [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/apropos) ] && \
+ exec apropos "$@"
+ search_whatis apropos "$@"
+}
+
+# Usage: do_full_search reg_exp
+# Do a full search of the regular expression passed
+# as parameter in all man pages
+do_full_search() {
+ local gflags re
+ re=${1}
+
+ # Build grep(1) flags
+ gflags="-H"
+
+ # wflag implies -l for grep(1)
+ if [ -n "$wflag" ]; then
+ gflags="${gflags} -l"
+ fi
+
+ gflags="${gflags} --label"
+
+ set +f
+ for mpath in $(echo "${MANPATH}" | tr : '[:blank:]'); do
+ for section in $(echo "${MANSECT}" | tr : '[:blank:]'); do
+ for manfile in ${mpath}/man${section}/*.${section}*; do
+ mandoc "${manfile}" 2>/dev/null |
+ grep -E ${gflags} "${manfile}" -e "${re}"
+ done
+ done
+ done
+ set -f
+}
+
+do_man() {
+ local IFS
+
+ man_parse_opts "$@"
+ man_setup
+
+ shift $(( $OPTIND - 1 ))
+ IFS=:
+ for sect in $MANSECT; do
+ if [ "$sect" = "$1" ]; then
+ decho "Detected manual section as first arg: $1"
+ MANSECT="$1"
+ shift
+ break
+ fi
+ done
+ unset IFS
+ pages="$*"
+
+ if [ -z "$pages" -a -z "${Kflag}" ]; then
+ echo 'What manual page do you want?' >&2
+ exit 1
+ fi
+
+ if [ ! -z "${Kflag}" ]; then
+ # Short circuit because -K flag does a sufficiently
+ # different thing like not showing the man page at all
+ do_full_search "${REGEXP}"
+ fi
+
+ for page in "$@"; do
+ decho "Searching for \"$page\""
+ man_find_and_display "$page"
+ done
+
+ exit ${ret:-0}
+}
+
+do_manpath() {
+ manpath_parse_args "$@"
+ if [ -z "$qflag" ]; then
+ manpath_warnings
+ fi
+ if [ -n "$Lflag" ]; then
+ build_manlocales
+ echo $MANLOCALES
+ else
+ build_manpath
+ echo $MANPATH
+ fi
+ exit 0
+}
+
+do_whatis() {
+ [ $(stat -f %i /usr/bin/man) -ne $(stat -f %i /usr/bin/whatis) ] && \
+ exec whatis "$@"
+ search_whatis whatis "$@"
+}
+
+# User's PATH setting decides on the groff-suite to pick up.
+EQN=eqn
+NROFF='groff -S -P-h -Wall -mtty-char -mandoc'
+PIC=pic
+REFER=refer
+TBL=tbl
+TROFF='groff -S -mandoc'
+VGRIND=vgrind
+
+LOCALE=/usr/bin/locale
+STTY=/bin/stty
+SYSCTL=/sbin/sysctl
+
+debug=0
+man_default_sections='1:8:2:3:3lua:n:4:5:6:7:9:l'
+man_default_path='/usr/share/man:/usr/share/openssl/man:/usr/local/share/man:/usr/local/man'
+cattool='/usr/bin/zcat -f'
+
+config_global='/etc/man.conf'
+
+# This can be overridden via a setting in /etc/man.conf.
+config_local='/usr/local/etc/man.d/*.conf'
+
+# Set noglobbing for now. I don't want spurious globbing.
+set -f
+
+case "$0" in
+*apropos) do_apropos "$@" ;;
+*manpath) do_manpath "$@" ;;
+*whatis) do_whatis "$@" ;;
+*) do_man "$@" ;;
+esac
diff --git a/usr.bin/man/manpath.1 b/usr.bin/man/manpath.1
new file mode 100644
index 000000000000..ac9e3b2db5a7
--- /dev/null
+++ b/usr.bin/man/manpath.1
@@ -0,0 +1,118 @@
+.\"-
+.\" SPDX-License-Identifer: BSD-2-Clause
+.\"
+.\" Copyright (c) 2010 Gordon Tetlow
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 March 11, 2017
+.Dt MANPATH 1
+.Os
+.Sh NAME
+.Nm manpath
+.Nd display search path for manual pages
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ldq
+.Sh DESCRIPTION
+The
+.Nm
+utility determines the user's manual search path from
+the user's
+.Ev PATH ,
+and local configuration files.
+This result is echoed to the standard output.
+.Bl -tag -width "-L"
+.It Fl L
+Output manual locales list instead of the manual path.
+.It Fl d
+Print extra debugging information.
+.It Fl q
+Suppresses warning messages.
+.El
+.Sh IMPLEMENTATION NOTES
+The
+.Nm
+utility constructs the manual path from two sources:
+.Bl -enum -compact
+.It
+From each component of the user's
+.Ev PATH
+for the first of:
+.Bl -dash -compact
+.It
+.Pa pathname/man
+.It
+.Pa pathname/MAN
+.It
+If pathname ends with /bin:
+.Pa pathname/../share/man
+and
+.Pa pathname/../man
+.El
+.It
+The configuration files listed in the
+.Sx FILES
+section for
+.Va MANPATH
+entries.
+.El
+The information from these locations is then concatenated together.
+.Pp
+If the
+.Fl L
+flag is set, the
+.Nm
+utility will search the configuration files listed in the
+.Sx FILES
+section for
+.Va MANLOCALE
+entries.
+.Sh ENVIRONMENT
+The following environment variables affect the execution of
+.Nm :
+.Bl -tag -width "MANLOCALES"
+.It Ev MANLOCALES
+If set with the
+.Fl L
+flag, causes the utility to display a warning and the value, overriding any
+other configuration found on the system.
+.It Ev MANPATH
+If set, causes the utility to display a warning and the value, overriding
+any other configuration found on the system.
+.It Ev PATH
+Influences the manual path as described in the
+.Sx IMPLEMENTATION NOTES .
+.El
+.Sh FILES
+.Bl -tag -width "/usr/local/etc/man.d/*.conf" -compact
+.It Pa /etc/man.conf
+System configuration file.
+.It Pa /usr/local/etc/man.d/*.conf
+Local configuration files.
+.El
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr man 1 ,
+.Xr whatis 1 ,
+.Xr man.conf 5
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
new file mode 100644
index 000000000000..c5255b1468fd
--- /dev/null
+++ b/usr.bin/mandoc/Makefile
@@ -0,0 +1,107 @@
+.include <src.opts.mk>
+
+MANDOCDIR= ${SRCTOP}/contrib/mandoc
+.PATH: ${MANDOCDIR}
+
+PROG= mandoc
+MAN= mandoc.1 eqn.7 mandoc_char.7 tbl.7 man.7 mdoc.7 roff.7
+MLINKS= mandoc.1 mdocml.1
+.if ${MK_MAN_UTILS} != no
+MAN+= apropos.1 makewhatis.8
+MLINKS+= apropos.1 whatis.1
+LINKS= ${BINDIR}/mandoc ${BINDIR}/whatis \
+ ${BINDIR}/mandoc ${BINDIR}/makewhatis \
+ ${BINDIR}/mandoc ${BINDIR}/apropos
+.elif defined(BOOTSTRAPPING)
+.error MK_MAN_UTILS should be set to yes when bootstrapping
+.endif
+
+LIBMAN_SRCS= man.c \
+ man_macro.c \
+ man_validate.c
+
+LIBMDOC_SRCS= arch.c \
+ att.c \
+ lib.c \
+ mdoc.c \
+ mdoc_argv.c \
+ mdoc_macro.c \
+ mdoc_markdown.c \
+ mdoc_state.c \
+ mdoc_validate.c \
+ st.c \
+
+LIBROFF_SRCS= eqn.c \
+ roff.c \
+ roff_escape.c \
+ roff_html.c \
+ roff_term.c \
+ roff_validate.c \
+ tbl.c \
+ tbl_data.c \
+ tbl_layout.c \
+ tbl_opts.c \
+
+LIB_SRCS= ${LIBMAN_SRCS} \
+ ${LIBMDOC_SRCS} \
+ ${LIBROFF_SRCS} \
+ chars.c \
+ mandoc.c \
+ mandoc_aux.c \
+ mandoc_dbg.c \
+ mandoc_msg.c \
+ mandoc_ohash.c \
+ mandoc_xr.c \
+ msec.c \
+ preconv.c \
+ read.c \
+ compat_recallocarray.c \
+
+HTML_SRCS= eqn_html.c \
+ html.c \
+ man_html.c \
+ mdoc_html.c \
+ tbl_html.c
+
+MAN_SRCS= mdoc_man.c
+
+TERM_SRCS= eqn_term.c \
+ man_term.c \
+ mdoc_term.c \
+ term.c \
+ term_ascii.c \
+ term_ps.c \
+ term_tab.c \
+ term_tag.c \
+ tbl_term.c
+
+DBM_SRCS= dbm.c \
+ dbm_map.c \
+ mansearch.c
+
+DBA_SRCS= dba.c \
+ dba_array.c \
+ dba_read.c \
+ dba_write.c \
+ mandocdb.c
+
+SRCS= ${LIB_SRCS} \
+ ${HTML_SRCS} \
+ ${MAN_SRCS} \
+ ${TERM_SRCS} \
+ ${DBM_SRCS} \
+ ${DBA_SRCS} \
+ main.c \
+ manpath.c \
+ out.c \
+ tag.c \
+ tree.c
+
+WARNS?= 3
+CFLAGS+= -DHAVE_CONFIG_H \
+ -I${SRCTOP}/lib/libopenbsd/
+# This can be removed after swtiching to newer gcc
+CFLAGS.gcc+= -Wno-format
+LIBADD= openbsd z
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mandoc/Makefile.depend b/usr.bin/mandoc/Makefile.depend
new file mode 100644
index 000000000000..1ef59bd6711b
--- /dev/null
+++ b/usr.bin/mandoc/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libopenbsd \
+ lib/libz \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mdo/Makefile b/usr.bin/mdo/Makefile
new file mode 100644
index 000000000000..e20f2719fc82
--- /dev/null
+++ b/usr.bin/mdo/Makefile
@@ -0,0 +1,4 @@
+PROG= mdo
+SRCS= mdo.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mdo/mdo.1 b/usr.bin/mdo/mdo.1
new file mode 100644
index 000000000000..ae89481ddb2b
--- /dev/null
+++ b/usr.bin/mdo/mdo.1
@@ -0,0 +1,44 @@
+.\"-
+.\" Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.Dd May 22, 2024
+.Dt MDO 1
+.Os
+.Sh NAME
+.Nm mdo
+.Nd execute commands as another user
+.Sh SYNOPSIS
+.Nm
+.Op Fl u Ar username
+.Op Fl i
+.Op command Op args
+.Sh DESCRIPTION
+The
+.Nm
+utility executes the specified
+.Ar command
+as user
+.Ar username .
+.Pp
+If no
+.Ar username
+is provided it defaults to the
+.Va root
+user.
+If no
+.Ar command
+is specified, it will execute the shell specified as
+.Va SHELL
+environnement variable, falling back on
+.Pa /bin/sh .
+.Pp
+The
+.Fl i
+option can be used to only call
+.Fn setuid
+and keep the group from the calling user.
+.Sh SEE ALSO
+.Xr su 1 ,
+.Xr mac_do 4
diff --git a/usr.bin/mdo/mdo.c b/usr.bin/mdo/mdo.c
new file mode 100644
index 000000000000..8435fc17f26f
--- /dev/null
+++ b/usr.bin/mdo/mdo.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/limits.h>
+#include <sys/ucred.h>
+
+#include <err.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: mdo [-u username] [-i] [--] [command [args]]\n");
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd *pw;
+ const char *username = "root";
+ struct setcred wcred = SETCRED_INITIALIZER;
+ u_int setcred_flags = 0;
+ bool uidonly = false;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "u:i")) != -1) {
+ switch (ch) {
+ case 'u':
+ username = optarg;
+ break;
+ case 'i':
+ uidonly = true;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((pw = getpwnam(username)) == NULL) {
+ if (strspn(username, "0123456789") == strlen(username)) {
+ const char *errp = NULL;
+ uid_t uid = strtonum(username, 0, UID_MAX, &errp);
+ if (errp != NULL)
+ err(EXIT_FAILURE, "invalid user ID '%s'",
+ username);
+ pw = getpwuid(uid);
+ }
+ if (pw == NULL)
+ err(EXIT_FAILURE, "invalid username '%s'", username);
+ }
+
+ wcred.sc_uid = wcred.sc_ruid = wcred.sc_svuid = pw->pw_uid;
+ setcred_flags |= SETCREDF_UID | SETCREDF_RUID | SETCREDF_SVUID;
+
+ if (!uidonly) {
+ /*
+ * If there are too many groups specified for some UID, setting
+ * the groups will fail. We preserve this condition by
+ * allocating one more group slot than allowed, as
+ * getgrouplist() itself is just some getter function and thus
+ * doesn't (and shouldn't) check the limit, and to allow
+ * setcred() to actually check for overflow.
+ */
+ const long ngroups_alloc = sysconf(_SC_NGROUPS_MAX) + 2;
+ gid_t *const groups = malloc(sizeof(*groups) * ngroups_alloc);
+ int ngroups = ngroups_alloc;
+
+ if (groups == NULL)
+ err(EXIT_FAILURE, "cannot allocate memory for groups");
+
+ getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+
+ wcred.sc_gid = wcred.sc_rgid = wcred.sc_svgid = pw->pw_gid;
+ wcred.sc_supp_groups = groups + 1;
+ wcred.sc_supp_groups_nb = ngroups - 1;
+ setcred_flags |= SETCREDF_GID | SETCREDF_RGID | SETCREDF_SVGID |
+ SETCREDF_SUPP_GROUPS;
+ }
+
+ if (setcred(setcred_flags, &wcred, sizeof(wcred)) != 0)
+ err(EXIT_FAILURE, "calling setcred() failed");
+
+ if (*argv == NULL) {
+ const char *sh = getenv("SHELL");
+ if (sh == NULL)
+ sh = _PATH_BSHELL;
+ execlp(sh, sh, "-i", NULL);
+ } else {
+ execvp(argv[0], argv);
+ }
+ err(EXIT_FAILURE, "exec failed");
+}
diff --git a/usr.bin/mesg/Makefile b/usr.bin/mesg/Makefile
new file mode 100644
index 000000000000..02a02d89bd36
--- /dev/null
+++ b/usr.bin/mesg/Makefile
@@ -0,0 +1,3 @@
+PROG= mesg
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mesg/Makefile.depend b/usr.bin/mesg/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/mesg/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mesg/mesg.1 b/usr.bin/mesg/mesg.1
new file mode 100644
index 000000000000..cb7169ebfd8b
--- /dev/null
+++ b/usr.bin/mesg/mesg.1
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1987, 1990, 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.
+.\"
+.Dd May 5, 2002
+.Dt MESG 1
+.Os
+.Sh NAME
+.Nm mesg
+.Nd display (do not display) messages from other users
+.Sh SYNOPSIS
+.Nm
+.Op Cm n | Cm y
+.Sh DESCRIPTION
+The
+.Nm
+utility is invoked by a user to control write access others
+have to a terminal device.
+Write access is allowed by default, and programs such as
+.Xr talk 1
+and
+.Xr write 1
+may display messages on the terminal.
+.Pp
+The first terminal device in the sequence of devices associated with standard
+input, standard output and standard error is affected.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Cm n
+Disallow messages.
+.It Cm y
+Permit messages to be displayed.
+.El
+.Pp
+If no arguments are given,
+.Nm
+displays the present message status to the standard output.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width flag -compact -offset indent
+.It Li "\ 0"
+Messages are allowed.
+.It Li "\ 1"
+Messages are not allowed.
+.It Li ">1"
+An error has occurred.
+.El
+.Sh EXAMPLES
+Disallow messages from other users to the current terminal:
+.Pp
+.Dl "mesg n"
+.Pp
+Allow messages from other users to
+.Pa ttyp1
+(assuming you are also logged in on that terminal):
+.Pp
+.Dl "mesg y </dev/ttyp1"
+.Sh COMPATIBILITY
+Previous versions of the
+.Nm
+utility wrote the message status to the standard error output and
+affected the terminal attached to standard error without first trying the
+standard input or output devices.
+.Sh SEE ALSO
+.Xr biff 1 ,
+.Xr talk 1 ,
+.Xr wall 1 ,
+.Xr write 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/mesg/mesg.c b/usr.bin/mesg/mesg.c
new file mode 100644
index 000000000000..833cf6f036df
--- /dev/null
+++ b/usr.bin/mesg/mesg.c
@@ -0,0 +1,100 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ char *tty;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((tty = ttyname(STDIN_FILENO)) == NULL &&
+ (tty = ttyname(STDOUT_FILENO)) == NULL &&
+ (tty = ttyname(STDERR_FILENO)) == NULL)
+ err(2, "ttyname");
+ if (stat(tty, &sb) < 0)
+ err(2, "%s", tty);
+
+ if (*argv == NULL) {
+ if (sb.st_mode & S_IWGRP) {
+ (void)puts("is y");
+ exit(0);
+ }
+ (void)puts("is n");
+ exit(1);
+ }
+
+ switch (*argv[0]) {
+ case 'y':
+ if (chmod(tty, sb.st_mode | S_IWGRP) < 0)
+ err(2, "%s", tty);
+ exit(0);
+ case 'n':
+ if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0)
+ err(2, "%s", tty);
+ exit(1);
+ }
+
+ usage();
+ return(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: mesg [n | y]\n");
+ exit(2);
+}
diff --git a/usr.bin/mididump/Makefile b/usr.bin/mididump/Makefile
new file mode 100644
index 000000000000..758bbb3a1189
--- /dev/null
+++ b/usr.bin/mididump/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= mididump
+SRCS= ${PROG}.c
+MAN= ${PROG}.1
+LIBADD+= m
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mididump/mididump.1 b/usr.bin/mididump/mididump.1
new file mode 100644
index 000000000000..7b2bc649eb24
--- /dev/null
+++ b/usr.bin/mididump/mididump.1
@@ -0,0 +1,80 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2024 The FreeBSD Foundation
+.\"
+.\" Portions of this software were developed by Christos Margiolis
+.\" <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 September 14, 2024
+.Dt MIDIDUMP 1
+.Os
+.Sh NAME
+.Nm mididump
+.Nd dump MIDI events
+.Sh SYNOPSIS
+.Nm
+.Op Fl t
+.Ar device
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to dump MIDI 1.0 events in real-time.
+.Pp
+The options are as follows:
+.Bl -tag -width "-t"
+.It Fl t
+Print "Timing Clock" events.
+These events are not printed by default, as they tend to clutter output.
+.El
+.Pp
+The
+.Ar device
+argument corresponds to the MIDI device (e.g.
+.Pa /dev/umidi0.0 ) .
+.Sh SEE ALSO
+.Rs
+.%T Summary of MIDI 1.0 Messages
+.%U https://midi.org/summary-of-midi-1-0-messages
+.Re
+.Rs
+.%T Expanded MIDI 1.0 Messages List (Status Bytes)
+.%U https://midi.org/expanded-midi-1-0-messages-list
+.Re
+.Rs
+.%T Standard MIDI-File Format Spec. 1.1, updated
+.%U https://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html
+.Re
+.Rs
+.%T MIDI CC List for Continuous Controllers
+.%U https://anotherproducer.com/online-tools-for-musicians/midi-cc-list/
+.Re
+.Sh AUTHORS
+The
+.Nm
+utility was implemented by
+.An Christos Margiolis Aq Mt christos@FreeBSD.org
+under sponsorship from the
+.Fx
+Foundation.
diff --git a/usr.bin/mididump/mididump.c b/usr.bin/mididump/mididump.c
new file mode 100644
index 000000000000..8ebcce547ac4
--- /dev/null
+++ b/usr.bin/mididump/mididump.c
@@ -0,0 +1,320 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 The FreeBSD Foundation
+ *
+ * This software was developed by Christos Margiolis <christos@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/soundcard.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NOTE2OCTAVE(n) (n / 12 - 1)
+#define NOTE2FREQ(n) (440 * pow(2.0f, ((float)n - 69) / 12))
+#define CHAN_MASK 0x0f
+
+static struct note {
+ const char *name;
+ const char *alt;
+} notes[] = {
+ { "C", NULL },
+ { "C#", "Db" },
+ { "D", NULL },
+ { "D#", "Eb" },
+ { "E", NULL },
+ { "F", NULL },
+ { "F#", "Gb" },
+ { "G", NULL },
+ { "G#", "Ab" },
+ { "A", NULL },
+ { "A#", "Bb" },
+ { "B", NULL },
+};
+
+/* Hardcoded values are not defined in sys/soundcard.h. */
+static const char *ctls[] = {
+ [CTL_BANK_SELECT] = "Bank Select",
+ [CTL_MODWHEEL] = "Modulation Wheel",
+ [CTL_BREATH] = "Breath Controller",
+ [0x03] = "Undefined",
+ [CTL_FOOT] = "Foot Pedal",
+ [CTL_PORTAMENTO_TIME] = "Portamento Time",
+ [CTL_DATA_ENTRY] = "Data Entry",
+ [CTL_MAIN_VOLUME] = "Volume",
+ [CTL_BALANCE] = "Balance",
+ [0x09] = "Undefined",
+ [CTL_PAN] = "Pan",
+ [CTL_EXPRESSION] = "Expression",
+ [0x0c] = "Effect Controller 1",
+ [0x0d] = "Effect Controller 2",
+ [0x0e] = "Undefined",
+ [0x0f] = "Undefined",
+ [CTL_GENERAL_PURPOSE1] = "General Purpose 1",
+ [CTL_GENERAL_PURPOSE2] = "General Purpose 2",
+ [CTL_GENERAL_PURPOSE3] = "General Purpose 3",
+ [CTL_GENERAL_PURPOSE4] = "General Purpose 4",
+ [0x14 ... 0x1f] = "Undefined",
+ [0x20 ... 0x3f] = "LSB Controller",
+ [CTL_DAMPER_PEDAL] = "Damper Pedal (Sustain)",
+ [CTL_PORTAMENTO] = "Portamento",
+ [CTL_SOSTENUTO] = "Sostenuto Pedal",
+ [CTL_SOFT_PEDAL] = "Soft Pedal",
+ [0x44] = "Legato Foot-Switch",
+ [CTL_HOLD2] = "Hold 2",
+ [0x46] = "Sound Controller 1",
+ [0x47] = "Sound Controller 2",
+ [0x48] = "Sound Controller 3",
+ [0x49] = "Sound Controller 4",
+ [0x4a] = "Sound Controller 5",
+ [0x4b] = "Sound Controller 6",
+ [0x4c] = "Sound Controller 7",
+ [0x4d] = "Sound Controller 8",
+ [0x4e] = "Sound Controller 9",
+ [0x4f] = "Sound Controller 10",
+ [CTL_GENERAL_PURPOSE5] = "General Purpose 5",
+ [CTL_GENERAL_PURPOSE6] = "General Purpose 6",
+ [CTL_GENERAL_PURPOSE7] = "General Purpose 7",
+ [CTL_GENERAL_PURPOSE8] = "General Purpose 8",
+ [0x54] = "Portamento CC",
+ [0x55 ... 0x57] = "Undefined",
+ [0x58] = "Hi-Res Velocity Prefix",
+ [0x59 ... 0x5a] = "Undefined",
+ [CTL_EXT_EFF_DEPTH] = "Effect 1 Depth",
+ [CTL_TREMOLO_DEPTH] = "Effect 2 Depth",
+ [CTL_CHORUS_DEPTH] = "Effect 3 Depth",
+ [CTL_DETUNE_DEPTH] = "Effect 4 Depth",
+ [CTL_PHASER_DEPTH] = "Effect 5 Depth",
+ [CTL_DATA_INCREMENT] = "Data Increment",
+ [CTL_DATA_DECREMENT] = "Data Decrement",
+ [CTL_NONREG_PARM_NUM_LSB] = "NRPN (LSB)",
+ [CTL_NONREG_PARM_NUM_MSB] = "NRPN (MSB)",
+ [CTL_REGIST_PARM_NUM_LSB] = "RPN (LSB)",
+ [CTL_REGIST_PARM_NUM_MSB] = "RPN (MSB)",
+ [0x66 ... 0x77] = "Undefined",
+ /* Channel mode messages */
+ [0x78] = "All Sound Off",
+ [0x79] = "Reset All Controllers",
+ [0x7a] = "Local On/Off Switch",
+ [0x7b] = "All Notes Off",
+ [0x7c] = "Omni Mode Off",
+ [0x7d] = "Omni Mode On",
+ [0x7e] = "Mono Mode",
+ [0x7f] = "Poly Mode",
+};
+
+static void __dead2
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-t] device\n", getprogname());
+ exit(1);
+}
+
+static uint8_t
+read_byte(int fd)
+{
+ uint8_t byte;
+
+ if (read(fd, &byte, sizeof(byte)) < (ssize_t)sizeof(byte))
+ err(1, "read");
+
+ return (byte);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct note *pn;
+ char buf[16];
+ int fd, ch, tflag = 0;
+ uint8_t event, chan, b1, b2;
+
+ while ((ch = getopt(argc, argv, "t")) != -1) {
+ switch (ch) {
+ case 't':
+ tflag = 1;
+ break;
+ case '?': /* FALLTHROUGH */
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ if ((fd = open(*argv, O_RDONLY)) < 0)
+ err(1, "open(%s)", *argv);
+
+ for (;;) {
+ event = read_byte(fd);
+ if (!(event & 0x80))
+ continue;
+ chan = (event & CHAN_MASK) + 1;
+
+ switch (event) {
+ case 0x80 ... 0x8f: /* FALLTHROUGH */
+ case 0x90 ... 0x9f:
+ b1 = read_byte(fd);
+ b2 = read_byte(fd);
+ pn = &notes[b1 % nitems(notes)];
+ snprintf(buf, sizeof(buf), "%s%d", pn->name,
+ NOTE2OCTAVE(b1));
+ if (pn->alt != NULL) {
+ snprintf(buf + strlen(buf), sizeof(buf),
+ "/%s%d", pn->alt, NOTE2OCTAVE(b1));
+ }
+ printf("Note %-3s channel=%d, "
+ "note=%d (%s, %.2fHz), velocity=%d\n",
+ (event >= 0x80 && event <= 0x8f) ? "off" : "on",
+ chan, b1, buf, NOTE2FREQ(b1), b2);
+ break;
+ case 0xa0 ... 0xaf:
+ b1 = read_byte(fd);
+ b2 = read_byte(fd);
+ printf("Polyphonic aftertouch channel=%d, note=%d, "
+ "pressure=%d\n",
+ chan, b1, b2);
+ break;
+ case 0xb0 ... 0xbf:
+ b1 = read_byte(fd);
+ b2 = read_byte(fd);
+ if (b1 > nitems(ctls) - 1)
+ break;
+ printf("Control/Mode change channel=%d, "
+ "control=%d (%s), value=%d",
+ chan, b1, ctls[b1], b2);
+ if (b1 >= 0x40 && b1 <= 0x45) {
+ if (b2 <= 63)
+ printf(" (off)");
+ else
+ printf(" (on)");
+ }
+ if (b1 == 0x7a) {
+ if (b2 == 0)
+ printf(" (off)");
+ else if (b2 == 127)
+ printf(" (on");
+ }
+ putchar('\n');
+ break;
+ case 0xc0 ... 0xcf:
+ b1 = read_byte(fd);
+ printf("Program change channel=%d, "
+ "program=%d\n",
+ chan, b1);
+ break;
+ case 0xd0 ... 0xdf:
+ b1 = read_byte(fd);
+ printf("Channel aftertouch channel=%d, "
+ "pressure=%d\n",
+ chan, b1);
+ break;
+ case 0xe0 ... 0xef:
+ /* TODO Improve */
+ b1 = read_byte(fd);
+ b2 = read_byte(fd);
+ printf("Pitch bend channel=%d, change=%d\n",
+ chan, b1 | b2 << 7);
+ break;
+ case 0xf0:
+ printf("SysEx vendorid=");
+ b1 = read_byte(fd);
+ printf("0x%02x", b1);
+ if (b1 == 0) {
+ printf(" 0x%02x 0x%02x",
+ read_byte(fd), read_byte(fd));
+ }
+ printf(" data=");
+ for (;;) {
+ b1 = read_byte(fd);
+ printf("0x%02x ", b1);
+ /* End of SysEx (EOX) */
+ if (b1 == 0xf7)
+ break;
+ }
+ putchar('\n');
+ break;
+ case 0xf2:
+ b1 = read_byte(fd);
+ b2 = read_byte(fd);
+ printf("Song position pointer ptr=%d\n",
+ b1 | b2 << 7);
+ break;
+ case 0xf3:
+ b1 = read_byte(fd);
+ printf("Song select song=%d\n", b1);
+ break;
+ case 0xf6:
+ printf("Tune request\n");
+ break;
+ case 0xf7:
+ printf("End of SysEx (EOX)\n");
+ break;
+ case 0xf8:
+ if (tflag)
+ printf("Timing clock\n");
+ break;
+ case 0xfa:
+ printf("Start\n");
+ break;
+ case 0xfb:
+ printf("Continue\n");
+ break;
+ case 0xfc:
+ printf("Stop\n");
+ break;
+ case 0xfe:
+ printf("Active sensing\n");
+ break;
+ case 0xff:
+ printf("System reset\n");
+ break;
+ case 0xf1: /* TODO? MIDI time code qtr. frame */
+ case 0xf4: /* Undefined (reserved) */
+ case 0xf5:
+ case 0xf9:
+ case 0xfd:
+ break;
+ default:
+ printf("Unknown event type: 0x%02x\n", event);
+ break;
+ }
+ }
+
+ close(fd);
+
+ return (0);
+}
diff --git a/usr.bin/ministat/Makefile b/usr.bin/ministat/Makefile
new file mode 100644
index 000000000000..b0291fc9be6b
--- /dev/null
+++ b/usr.bin/ministat/Makefile
@@ -0,0 +1,13 @@
+PROG= ministat
+
+LIBADD= m
+
+.include <bsd.prog.mk>
+
+test: ${PROG}
+ ./${PROG} < ${.CURDIR}/chameleon
+ ./${PROG} ${.CURDIR}/chameleon
+ ./${PROG} ${.CURDIR}/iguana ${.CURDIR}/chameleon
+ ./${PROG} -c 80 ${.CURDIR}/iguana ${.CURDIR}/chameleon
+ ./${PROG} -s -c 80 ${.CURDIR}/chameleon ${.CURDIR}/iguana
+ ./${PROG} -s -c 80 ${.CURDIR}/chameleon ${.CURDIR}/iguana ${.CURDIR}/iguana
diff --git a/usr.bin/ministat/Makefile.depend b/usr.bin/ministat/Makefile.depend
new file mode 100644
index 000000000000..866f7ef5d25b
--- /dev/null
+++ b/usr.bin/ministat/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ministat/README b/usr.bin/ministat/README
new file mode 100644
index 000000000000..b2be580ffbd8
--- /dev/null
+++ b/usr.bin/ministat/README
@@ -0,0 +1,49 @@
+
+A small tool to do the statistics legwork on benchmarks etc.
+
+Prepare your data into two files, one number per line
+run
+ ./ministat data_before data_after
+
+and see what it says.
+
+You need at least three data points in each data set, but the more
+you have the better your result generally gets.
+
+Here are two typical outputs:
+
+x _1
++ _2
++--------------------------------------------------------------------------+
+|x + x+ x x x + ++ |
+| |_________|______AM_______________|__A___________M_______________||
++--------------------------------------------------------------------------+
+ N Min Max Median Avg Stddev
+x 5 36060 36138 36107 36105.6 31.165686
++ 5 36084 36187 36163 36142.6 49.952978
+No difference proven at 95.0% confidence
+
+Here nothing can be concluded from the numbers. It _may_ be possible to
+prove something if many more measurements are made, but with only five
+measurements, nothing is proven.
+
+
+x _1
++ _2
++--------------------------------------------------------------------------+
+| + |
+| x + +|
+|x x x x + +|
+| |_______________A_____M_________| |_M___A____| |
++--------------------------------------------------------------------------+
+ N Min Max Median Avg Stddev
+x 5 0.133 0.137 0.136 0.1354 0.0015165751
++ 5 0.139 0.14 0.139 0.1394 0.00054772256
+Difference at 95.0% confidence
+ 0.004 +/- 0.00166288
+ 2.95421% +/- 1.22812%
+ (Student's t, pooled s = 0.00114018)
+
+Here we have a clearcut difference, not very big, but clear and unambiguous.
+
+
diff --git a/usr.bin/ministat/chameleon b/usr.bin/ministat/chameleon
new file mode 100644
index 000000000000..ed1bfdbc4773
--- /dev/null
+++ b/usr.bin/ministat/chameleon
@@ -0,0 +1,5 @@
+150
+400
+720
+500
+930
diff --git a/usr.bin/ministat/iguana b/usr.bin/ministat/iguana
new file mode 100644
index 000000000000..acf77a0e318c
--- /dev/null
+++ b/usr.bin/ministat/iguana
@@ -0,0 +1,7 @@
+50
+200
+150
+400
+750
+400
+150
diff --git a/usr.bin/ministat/ministat.1 b/usr.bin/ministat/ministat.1
new file mode 100644
index 000000000000..cef7caa7b9d9
--- /dev/null
+++ b/usr.bin/ministat/ministat.1
@@ -0,0 +1,137 @@
+.\"
+.\" Copyright (c) 2007 Poul-Henning Kamp
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 November 10, 2012
+.Dt MINISTAT 1
+.Os
+.Sh NAME
+.Nm ministat
+.Nd statistics utility
+.Sh SYNOPSIS
+.Nm
+.Op Fl Anqs
+.Op Fl C Ar column
+.Op Fl c Ar confidence_level
+.Op Fl d Ar delimiter
+.Op Fl w Op width
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+command calculates fundamental statistical properties of numeric data
+in the specified files or, if no file is specified, standard input.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl A
+Just report the statistics of the input and relative comparisons,
+suppress the ASCII-art plot.
+.It Fl n
+Just report the raw statistics of the input, suppress the ASCII-art plot
+and the relative comparisons.
+.It Fl q
+Suppress printing of summary statistics and data-set names; typically for use
+alongside
+.Fl n .
+.It Fl s
+Print the average/median/stddev bars on separate lines in the ASCII-art
+plot, to avoid overlap.
+.It Fl C Ar column
+Specify which column of data to use.
+By default the first column in the input file(s) are used.
+.It Fl c Ar confidence_level
+Specify desired confidence level for Student's T analysis.
+Possible values are 80, 90, 95, 98, 99 and 99.5 %
+.It Fl d Ar delimiter
+Specifies the column delimiter characters, default is SPACE and TAB.
+See
+.Xr strtok 3
+for details.
+.It Fl w Ar width
+Width of ASCII-art plot in characters.
+The default is the terminal width, or 74 if standard output is not a
+terminal.
+.El
+.Pp
+A sample output could look like this:
+.Bd -literal -offset indent
+ $ ministat -s -w 60 iguana chameleon
+ x iguana
+ + chameleon
+ +------------------------------------------------------------+
+ |x * x * + + x +|
+ | |________M______A_______________| |
+ | |________________M__A___________________| |
+ +------------------------------------------------------------+
+ N Min Max Median Avg Stddev
+ x 7 50 750 200 300 238.04761
+ + 5 150 930 500 540 299.08193
+ No difference proven at 95.0% confidence
+.Ed
+.Pp
+If
+.Nm
+tells you, as in the example above, that there is no difference
+proven at 95% confidence, the two data sets you gave it are for
+all statistical purposes identical.
+.Pp
+You have the option of lowering your standards by specifying a
+lower confidence level:
+.Bd -literal -offset indent
+ $ ministat -s -w 60 -c 80 iguana chameleon
+ x iguana
+ + chameleon
+ +------------------------------------------------------------+
+ |x * x * + + x +|
+ | |________M______A_______________| |
+ | |________________M__A___________________| |
+ +------------------------------------------------------------+
+ N Min Max Median Avg Stddev
+ x 7 50 750 200 300 238.04761
+ + 5 150 930 500 540 299.08193
+ Difference at 80.0% confidence
+ 240 +/- 212.215
+ 80% +/- 70.7384%
+ (Student's t, pooled s = 264.159)
+.Ed
+.Pp
+But a lower standard does not make your data any better, and the
+example is only included here to show the format of the output when
+a statistical difference is proven according to Student's T method.
+.Sh SEE ALSO
+Any mathematics text on basic statistics, for instances Larry Gonicks
+excellent "Cartoon Guide to Statistics" which supplied the above example.
+.Sh HISTORY
+The
+.Nm
+command was written by Poul-Henning Kamp out of frustration
+over all the bogus benchmark claims made by people with no
+understanding of the importance of uncertainty and statistics.
+.Pp
+From
+.Fx 5.2
+it has lived in the source tree as a developer tool, graduating
+to the installed system from
+.Fx 8.0 .
diff --git a/usr.bin/ministat/ministat.c b/usr.bin/ministat/ministat.c
new file mode 100644
index 000000000000..6967841a339f
--- /dev/null
+++ b/usr.bin/ministat/ministat.c
@@ -0,0 +1,691 @@
+/*-
+ * SPDX-License-Identifier: Beerware
+ *
+ * ----------------------------------------------------------------------------
+ * "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/capsicum.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/ttycom.h>
+
+#include <assert.h>
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NSTUDENT 100
+#define NCONF 6
+static double const studentpct[] = { 80, 90, 95, 98, 99, 99.5 };
+static double const student[NSTUDENT + 1][NCONF] = {
+/* inf */ { 1.282, 1.645, 1.960, 2.326, 2.576, 3.090 },
+/* 1. */ { 3.078, 6.314, 12.706, 31.821, 63.657, 318.313 },
+/* 2. */ { 1.886, 2.920, 4.303, 6.965, 9.925, 22.327 },
+/* 3. */ { 1.638, 2.353, 3.182, 4.541, 5.841, 10.215 },
+/* 4. */ { 1.533, 2.132, 2.776, 3.747, 4.604, 7.173 },
+/* 5. */ { 1.476, 2.015, 2.571, 3.365, 4.032, 5.893 },
+/* 6. */ { 1.440, 1.943, 2.447, 3.143, 3.707, 5.208 },
+/* 7. */ { 1.415, 1.895, 2.365, 2.998, 3.499, 4.782 },
+/* 8. */ { 1.397, 1.860, 2.306, 2.896, 3.355, 4.499 },
+/* 9. */ { 1.383, 1.833, 2.262, 2.821, 3.250, 4.296 },
+/* 10. */ { 1.372, 1.812, 2.228, 2.764, 3.169, 4.143 },
+/* 11. */ { 1.363, 1.796, 2.201, 2.718, 3.106, 4.024 },
+/* 12. */ { 1.356, 1.782, 2.179, 2.681, 3.055, 3.929 },
+/* 13. */ { 1.350, 1.771, 2.160, 2.650, 3.012, 3.852 },
+/* 14. */ { 1.345, 1.761, 2.145, 2.624, 2.977, 3.787 },
+/* 15. */ { 1.341, 1.753, 2.131, 2.602, 2.947, 3.733 },
+/* 16. */ { 1.337, 1.746, 2.120, 2.583, 2.921, 3.686 },
+/* 17. */ { 1.333, 1.740, 2.110, 2.567, 2.898, 3.646 },
+/* 18. */ { 1.330, 1.734, 2.101, 2.552, 2.878, 3.610 },
+/* 19. */ { 1.328, 1.729, 2.093, 2.539, 2.861, 3.579 },
+/* 20. */ { 1.325, 1.725, 2.086, 2.528, 2.845, 3.552 },
+/* 21. */ { 1.323, 1.721, 2.080, 2.518, 2.831, 3.527 },
+/* 22. */ { 1.321, 1.717, 2.074, 2.508, 2.819, 3.505 },
+/* 23. */ { 1.319, 1.714, 2.069, 2.500, 2.807, 3.485 },
+/* 24. */ { 1.318, 1.711, 2.064, 2.492, 2.797, 3.467 },
+/* 25. */ { 1.316, 1.708, 2.060, 2.485, 2.787, 3.450 },
+/* 26. */ { 1.315, 1.706, 2.056, 2.479, 2.779, 3.435 },
+/* 27. */ { 1.314, 1.703, 2.052, 2.473, 2.771, 3.421 },
+/* 28. */ { 1.313, 1.701, 2.048, 2.467, 2.763, 3.408 },
+/* 29. */ { 1.311, 1.699, 2.045, 2.462, 2.756, 3.396 },
+/* 30. */ { 1.310, 1.697, 2.042, 2.457, 2.750, 3.385 },
+/* 31. */ { 1.309, 1.696, 2.040, 2.453, 2.744, 3.375 },
+/* 32. */ { 1.309, 1.694, 2.037, 2.449, 2.738, 3.365 },
+/* 33. */ { 1.308, 1.692, 2.035, 2.445, 2.733, 3.356 },
+/* 34. */ { 1.307, 1.691, 2.032, 2.441, 2.728, 3.348 },
+/* 35. */ { 1.306, 1.690, 2.030, 2.438, 2.724, 3.340 },
+/* 36. */ { 1.306, 1.688, 2.028, 2.434, 2.719, 3.333 },
+/* 37. */ { 1.305, 1.687, 2.026, 2.431, 2.715, 3.326 },
+/* 38. */ { 1.304, 1.686, 2.024, 2.429, 2.712, 3.319 },
+/* 39. */ { 1.304, 1.685, 2.023, 2.426, 2.708, 3.313 },
+/* 40. */ { 1.303, 1.684, 2.021, 2.423, 2.704, 3.307 },
+/* 41. */ { 1.303, 1.683, 2.020, 2.421, 2.701, 3.301 },
+/* 42. */ { 1.302, 1.682, 2.018, 2.418, 2.698, 3.296 },
+/* 43. */ { 1.302, 1.681, 2.017, 2.416, 2.695, 3.291 },
+/* 44. */ { 1.301, 1.680, 2.015, 2.414, 2.692, 3.286 },
+/* 45. */ { 1.301, 1.679, 2.014, 2.412, 2.690, 3.281 },
+/* 46. */ { 1.300, 1.679, 2.013, 2.410, 2.687, 3.277 },
+/* 47. */ { 1.300, 1.678, 2.012, 2.408, 2.685, 3.273 },
+/* 48. */ { 1.299, 1.677, 2.011, 2.407, 2.682, 3.269 },
+/* 49. */ { 1.299, 1.677, 2.010, 2.405, 2.680, 3.265 },
+/* 50. */ { 1.299, 1.676, 2.009, 2.403, 2.678, 3.261 },
+/* 51. */ { 1.298, 1.675, 2.008, 2.402, 2.676, 3.258 },
+/* 52. */ { 1.298, 1.675, 2.007, 2.400, 2.674, 3.255 },
+/* 53. */ { 1.298, 1.674, 2.006, 2.399, 2.672, 3.251 },
+/* 54. */ { 1.297, 1.674, 2.005, 2.397, 2.670, 3.248 },
+/* 55. */ { 1.297, 1.673, 2.004, 2.396, 2.668, 3.245 },
+/* 56. */ { 1.297, 1.673, 2.003, 2.395, 2.667, 3.242 },
+/* 57. */ { 1.297, 1.672, 2.002, 2.394, 2.665, 3.239 },
+/* 58. */ { 1.296, 1.672, 2.002, 2.392, 2.663, 3.237 },
+/* 59. */ { 1.296, 1.671, 2.001, 2.391, 2.662, 3.234 },
+/* 60. */ { 1.296, 1.671, 2.000, 2.390, 2.660, 3.232 },
+/* 61. */ { 1.296, 1.670, 2.000, 2.389, 2.659, 3.229 },
+/* 62. */ { 1.295, 1.670, 1.999, 2.388, 2.657, 3.227 },
+/* 63. */ { 1.295, 1.669, 1.998, 2.387, 2.656, 3.225 },
+/* 64. */ { 1.295, 1.669, 1.998, 2.386, 2.655, 3.223 },
+/* 65. */ { 1.295, 1.669, 1.997, 2.385, 2.654, 3.220 },
+/* 66. */ { 1.295, 1.668, 1.997, 2.384, 2.652, 3.218 },
+/* 67. */ { 1.294, 1.668, 1.996, 2.383, 2.651, 3.216 },
+/* 68. */ { 1.294, 1.668, 1.995, 2.382, 2.650, 3.214 },
+/* 69. */ { 1.294, 1.667, 1.995, 2.382, 2.649, 3.213 },
+/* 70. */ { 1.294, 1.667, 1.994, 2.381, 2.648, 3.211 },
+/* 71. */ { 1.294, 1.667, 1.994, 2.380, 2.647, 3.209 },
+/* 72. */ { 1.293, 1.666, 1.993, 2.379, 2.646, 3.207 },
+/* 73. */ { 1.293, 1.666, 1.993, 2.379, 2.645, 3.206 },
+/* 74. */ { 1.293, 1.666, 1.993, 2.378, 2.644, 3.204 },
+/* 75. */ { 1.293, 1.665, 1.992, 2.377, 2.643, 3.202 },
+/* 76. */ { 1.293, 1.665, 1.992, 2.376, 2.642, 3.201 },
+/* 77. */ { 1.293, 1.665, 1.991, 2.376, 2.641, 3.199 },
+/* 78. */ { 1.292, 1.665, 1.991, 2.375, 2.640, 3.198 },
+/* 79. */ { 1.292, 1.664, 1.990, 2.374, 2.640, 3.197 },
+/* 80. */ { 1.292, 1.664, 1.990, 2.374, 2.639, 3.195 },
+/* 81. */ { 1.292, 1.664, 1.990, 2.373, 2.638, 3.194 },
+/* 82. */ { 1.292, 1.664, 1.989, 2.373, 2.637, 3.193 },
+/* 83. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.191 },
+/* 84. */ { 1.292, 1.663, 1.989, 2.372, 2.636, 3.190 },
+/* 85. */ { 1.292, 1.663, 1.988, 2.371, 2.635, 3.189 },
+/* 86. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.188 },
+/* 87. */ { 1.291, 1.663, 1.988, 2.370, 2.634, 3.187 },
+/* 88. */ { 1.291, 1.662, 1.987, 2.369, 2.633, 3.185 },
+/* 89. */ { 1.291, 1.662, 1.987, 2.369, 2.632, 3.184 },
+/* 90. */ { 1.291, 1.662, 1.987, 2.368, 2.632, 3.183 },
+/* 91. */ { 1.291, 1.662, 1.986, 2.368, 2.631, 3.182 },
+/* 92. */ { 1.291, 1.662, 1.986, 2.368, 2.630, 3.181 },
+/* 93. */ { 1.291, 1.661, 1.986, 2.367, 2.630, 3.180 },
+/* 94. */ { 1.291, 1.661, 1.986, 2.367, 2.629, 3.179 },
+/* 95. */ { 1.291, 1.661, 1.985, 2.366, 2.629, 3.178 },
+/* 96. */ { 1.290, 1.661, 1.985, 2.366, 2.628, 3.177 },
+/* 97. */ { 1.290, 1.661, 1.985, 2.365, 2.627, 3.176 },
+/* 98. */ { 1.290, 1.661, 1.984, 2.365, 2.627, 3.175 },
+/* 99. */ { 1.290, 1.660, 1.984, 2.365, 2.626, 3.175 },
+/* 100. */ { 1.290, 1.660, 1.984, 2.364, 2.626, 3.174 }
+};
+
+#define MAX_DS 8
+static char symbol[MAX_DS] = { ' ', 'x', '+', '*', '%', '#', '@', 'O' };
+
+struct dataset {
+ char *name;
+ double *points;
+ size_t lpoints;
+ double sy, syy;
+ size_t n;
+};
+
+static struct dataset *
+NewSet(void)
+{
+ struct dataset *ds;
+
+ ds = calloc(1, sizeof *ds);
+ assert(ds != NULL);
+ ds->lpoints = 100000;
+ ds->points = calloc(ds->lpoints, sizeof(*ds->points));
+ assert(ds->points != NULL);
+ ds->syy = NAN;
+ return(ds);
+}
+
+static void
+AddPoint(struct dataset *ds, double a)
+{
+ double *dp;
+
+ if (ds->n >= ds->lpoints) {
+ dp = ds->points;
+ ds->lpoints *= 4;
+ ds->points = calloc(ds->lpoints, sizeof(*ds->points));
+ assert(ds->points != NULL);
+ memcpy(ds->points, dp, sizeof *dp * ds->n);
+ free(dp);
+ }
+ ds->points[ds->n++] = a;
+ ds->sy += a;
+}
+
+static double
+Min(const struct dataset *ds)
+{
+
+ return (ds->points[0]);
+}
+
+static double
+Max(const struct dataset *ds)
+{
+
+ return (ds->points[ds->n -1]);
+}
+
+static double
+Avg(const struct dataset *ds)
+{
+
+ return(ds->sy / ds->n);
+}
+
+static double
+Median(const struct dataset *ds)
+{
+ const size_t m = ds->n / 2;
+
+ if ((ds->n % 2) == 0)
+ return ((ds->points[m] + (ds->points[m - 1])) / 2);
+ return (ds->points[m]);
+}
+
+static double
+Var(struct dataset *ds)
+{
+ size_t z;
+ const double a = Avg(ds);
+
+ if (isnan(ds->syy)) {
+ ds->syy = 0.0;
+ for (z = 0; z < ds->n; z++)
+ ds->syy += (ds->points[z] - a) * (ds->points[z] - a);
+ }
+
+ return (ds->syy / (ds->n - 1.0));
+}
+
+static double
+Stddev(struct dataset *ds)
+{
+
+ return sqrt(Var(ds));
+}
+
+static void
+VitalsHead(void)
+{
+
+ printf(" N Min Max Median Avg Stddev\n");
+}
+
+static void
+Vitals(struct dataset *ds, int flag)
+{
+
+ printf("%c %3zu %13.8g %13.8g %13.8g %13.8g %13.8g", symbol[flag],
+ ds->n, Min(ds), Max(ds), Median(ds), Avg(ds), Stddev(ds));
+ printf("\n");
+}
+
+static void
+Relative(struct dataset *ds, struct dataset *rs, int confidx)
+{
+ double spool, s, d, e, t;
+ double re;
+ size_t z;
+
+ z = ds->n + rs->n - 2;
+ if (z > NSTUDENT)
+ t = student[0][confidx];
+ else
+ t = student[z][confidx];
+ spool = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs);
+ spool /= ds->n + rs->n - 2;
+ spool = sqrt(spool);
+ s = spool * sqrt(1.0 / ds->n + 1.0 / rs->n);
+ d = Avg(ds) - Avg(rs);
+ e = t * s;
+
+ re = (ds->n - 1) * Var(ds) + (rs->n - 1) * Var(rs) *
+ (Avg(ds) * Avg(ds)) / (Avg(rs) * Avg(rs));
+ re *= (ds->n + rs->n) / (ds->n * rs->n * (ds->n + rs->n - 2.0));
+ re = t * sqrt(re);
+
+ if (fabs(d) > e) {
+ printf("Difference at %.1f%% confidence\n", studentpct[confidx]);
+ printf(" %g +/- %g\n", d, e);
+ printf(" %g%% +/- %g%%\n", d * 100 / Avg(rs), re * 100 / Avg(rs));
+ printf(" (Student's t, pooled s = %g)\n", spool);
+ } else {
+ printf("No difference proven at %.1f%% confidence\n",
+ studentpct[confidx]);
+ }
+}
+
+struct plot {
+ double min;
+ double max;
+ double span;
+ int width;
+
+ double x0, dx;
+ size_t height;
+ char *data;
+ char **bar;
+ int separate_bars;
+ int num_datasets;
+};
+
+static struct plot plot;
+
+static void
+SetupPlot(int width, int separate, int num_datasets)
+{
+ struct plot *pl;
+
+ pl = &plot;
+ pl->width = width;
+ pl->height = 0;
+ pl->data = NULL;
+ pl->bar = NULL;
+ pl->separate_bars = separate;
+ pl->num_datasets = num_datasets;
+ pl->min = 999e99;
+ pl->max = -999e99;
+}
+
+static void
+AdjPlot(double a)
+{
+ struct plot *pl;
+
+ pl = &plot;
+ if (a < pl->min)
+ pl->min = a;
+ if (a > pl->max)
+ pl->max = a;
+ pl->span = pl->max - pl->min;
+ pl->dx = pl->span / (pl->width - 1.0);
+ pl->x0 = pl->min - .5 * pl->dx;
+}
+
+static void
+DimPlot(struct dataset *ds)
+{
+ AdjPlot(Min(ds));
+ AdjPlot(Max(ds));
+ AdjPlot(Avg(ds) - Stddev(ds));
+ AdjPlot(Avg(ds) + Stddev(ds));
+}
+
+static void
+PlotSet(struct dataset *ds, int val)
+{
+ struct plot *pl;
+ int i, x;
+ size_t m, j, z;
+ size_t n;
+ int bar;
+ double av, sd;
+
+ pl = &plot;
+ if (pl->span == 0)
+ return;
+
+ if (pl->separate_bars)
+ bar = val-1;
+ else
+ bar = 0;
+
+ if (pl->bar == NULL) {
+ pl->bar = calloc(pl->num_datasets, sizeof(char *));
+ assert(pl->bar != NULL);
+ }
+
+ if (pl->bar[bar] == NULL) {
+ pl->bar[bar] = malloc(pl->width);
+ assert(pl->bar[bar] != NULL);
+ memset(pl->bar[bar], 0, pl->width);
+ }
+
+ m = 1;
+ i = -1;
+ j = 0;
+ /* Set m to max(j) + 1, to allocate required memory */
+ for (n = 0; n < ds->n; n++) {
+ x = (ds->points[n] - pl->x0) / pl->dx;
+ if (x == i) {
+ j++;
+ if (j > m)
+ m = j;
+ } else {
+ j = 1;
+ i = x;
+ }
+ }
+ m += 1;
+ if (m > pl->height) {
+ pl->data = realloc(pl->data, pl->width * m);
+ assert(pl->data != NULL);
+ memset(pl->data + pl->height * pl->width, 0,
+ (m - pl->height) * pl->width);
+ }
+ pl->height = m;
+ i = -1;
+ for (n = 0; n < ds->n; n++) {
+ x = (ds->points[n] - pl->x0) / pl->dx;
+ if (x == i) {
+ j++;
+ } else {
+ j = 1;
+ i = x;
+ }
+ pl->data[j * pl->width + x] |= val;
+ }
+ av = Avg(ds);
+ sd = Stddev(ds);
+ if (!isnan(sd)) {
+ x = ((av - sd) - pl->x0) / pl->dx;
+ m = ((av + sd) - pl->x0) / pl->dx;
+ pl->bar[bar][m] = '|';
+ pl->bar[bar][x] = '|';
+ for (z = x + 1; z < m; z++)
+ if (pl->bar[bar][z] == 0)
+ pl->bar[bar][z] = '_';
+ }
+ x = (Median(ds) - pl->x0) / pl->dx;
+ pl->bar[bar][x] = 'M';
+ x = (av - pl->x0) / pl->dx;
+ pl->bar[bar][x] = 'A';
+}
+
+static void
+DumpPlot(void)
+{
+ struct plot *pl;
+ int i, j, k;
+ size_t z;
+
+ pl = &plot;
+ if (pl->span == 0) {
+ printf("[no plot, span is zero width]\n");
+ return;
+ }
+
+ putchar('+');
+ for (i = 0; i < pl->width; i++)
+ putchar('-');
+ putchar('+');
+ putchar('\n');
+ for (z = 1; z < pl->height; z++) {
+ putchar('|');
+ for (j = 0; j < pl->width; j++) {
+ k = pl->data[(pl->height - z) * pl->width + j];
+ if (k >= 0 && k < MAX_DS)
+ putchar(symbol[k]);
+ else
+ printf("[%02x]", k);
+ }
+ putchar('|');
+ putchar('\n');
+ }
+ for (i = 0; i < pl->num_datasets; i++) {
+ if (pl->bar[i] == NULL)
+ continue;
+ putchar('|');
+ for (j = 0; j < pl->width; j++) {
+ k = pl->bar[i][j];
+ if (k == 0)
+ k = ' ';
+ putchar(k);
+ }
+ putchar('|');
+ putchar('\n');
+ }
+ putchar('+');
+ for (i = 0; i < pl->width; i++)
+ putchar('-');
+ putchar('+');
+ putchar('\n');
+}
+
+static int
+dbl_cmp(const void *a, const void *b)
+{
+ const double *aa = a;
+ const double *bb = b;
+
+ if (*aa < *bb)
+ return (-1);
+ else if (*aa > *bb)
+ return (1);
+ else
+ return (0);
+}
+
+static struct dataset *
+ReadSet(FILE *f, const char *n, int column, const char *delim)
+{
+ char buf[BUFSIZ], *p, *t;
+ struct dataset *s;
+ double d;
+ int line;
+ int i;
+
+ s = NewSet();
+ s->name = strdup(n);
+ assert(s->name != NULL);
+ line = 0;
+ while (fgets(buf, sizeof buf, f) != NULL) {
+ line++;
+
+ i = strlen(buf);
+ while (i > 0 && isspace(buf[i - 1]))
+ buf[--i] = '\0';
+ for (i = 1, t = strtok(buf, delim);
+ t != NULL && *t != '#';
+ i++, t = strtok(NULL, delim)) {
+ if (i == column)
+ break;
+ }
+ if (t == NULL || *t == '#')
+ continue;
+
+ d = strtod(t, &p);
+ if (p != NULL && *p != '\0')
+ errx(2, "Invalid data on line %d in %s", line, n);
+ if (*buf != '\0')
+ AddPoint(s, d);
+ }
+ if (s->n < 3) {
+ fprintf(stderr,
+ "Dataset %s must contain at least 3 data points\n", n);
+ exit (2);
+ }
+ qsort(s->points, s->n, sizeof *s->points, dbl_cmp);
+ return (s);
+}
+
+static void
+usage(char const *whine)
+{
+ int i;
+
+ fprintf(stderr, "%s\n", whine);
+ fprintf(stderr,
+ "Usage: ministat [-C column] [-c confidence] [-d delimiter(s)] [-Anqs] [-w width] [file [file ...]]\n");
+ fprintf(stderr, "\tconfidence = {");
+ for (i = 0; i < NCONF; i++) {
+ fprintf(stderr, "%s%g%%",
+ i ? ", " : "",
+ studentpct[i]);
+ }
+ fprintf(stderr, "}\n");
+ fprintf(stderr, "\t-A : print statistics only. suppress the graph.\n");
+ fprintf(stderr, "\t-C : column number to extract (starts and defaults to 1)\n");
+ fprintf(stderr, "\t-d : delimiter(s) string, default to \" \\t\"\n");
+ fprintf(stderr, "\t-n : print summary statistics only, no graph/test\n");
+ fprintf(stderr, "\t-q : suppress printing summary-statistics headers and data-set names\n");
+ fprintf(stderr, "\t-s : print avg/median/stddev bars on separate lines\n");
+ fprintf(stderr, "\t-w : width of graph/test output (default 74 or terminal width)\n");
+ exit (2);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *setfilenames[MAX_DS - 1];
+ struct dataset *ds[MAX_DS - 1];
+ FILE *setfiles[MAX_DS - 1];
+ int nds;
+ double a;
+ const char *delim = " \t";
+ char *p;
+ int c, i, ci;
+ int column = 1;
+ int flag_s = 0;
+ int flag_n = 0;
+ int flag_q = 0;
+ int termwidth = 74;
+ int suppress_plot = 0;
+
+ if (isatty(STDOUT_FILENO)) {
+ struct winsize wsz;
+
+ if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
+ termwidth = atoi(p);
+ else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) != -1 &&
+ wsz.ws_col > 0)
+ termwidth = wsz.ws_col - 2;
+ }
+
+ ci = -1;
+ while ((c = getopt(argc, argv, "AC:c:d:snqw:")) != -1)
+ switch (c) {
+ case 'A':
+ suppress_plot = 1;
+ break;
+ case 'C':
+ column = strtol(optarg, &p, 10);
+ if (p != NULL && *p != '\0')
+ usage("Invalid column number.");
+ if (column <= 0)
+ usage("Column number should be positive.");
+ break;
+ case 'c':
+ a = strtod(optarg, &p);
+ if (p != NULL && *p != '\0')
+ usage("Not a floating point number");
+ for (i = 0; i < NCONF; i++)
+ if (a == studentpct[i])
+ ci = i;
+ if (ci == -1)
+ usage("No support for confidence level");
+ break;
+ case 'd':
+ if (*optarg == '\0')
+ usage("Can't use empty delimiter string");
+ delim = optarg;
+ break;
+ case 'n':
+ flag_n = 1;
+ break;
+ case 'q':
+ flag_q = 1;
+ break;
+ case 's':
+ flag_s = 1;
+ break;
+ case 'w':
+ termwidth = strtol(optarg, &p, 10);
+ if (p != NULL && *p != '\0')
+ usage("Invalid width, not a number.");
+ if (termwidth < 0)
+ usage("Unable to move beyond left margin.");
+ break;
+ default:
+ usage("Unknown option");
+ break;
+ }
+ if (ci == -1)
+ ci = 2;
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ setfilenames[0] = "<stdin>";
+ setfiles[0] = stdin;
+ nds = 1;
+ } else {
+ if (argc > (MAX_DS - 1))
+ usage("Too many datasets.");
+ nds = argc;
+ for (i = 0; i < nds; i++) {
+ setfilenames[i] = argv[i];
+ if (!strcmp(argv[i], "-"))
+ setfiles[0] = stdin;
+ else
+ setfiles[i] = fopen(argv[i], "r");
+ if (setfiles[i] == NULL)
+ err(2, "Cannot open %s", argv[i]);
+ }
+ }
+
+ if (caph_limit_stdio() < 0)
+ err(2, "capsicum");
+
+ for (i = 0; i < nds; i++)
+ if (caph_limit_stream(fileno(setfiles[i]), CAPH_READ) < 0)
+ err(2, "unable to limit rights for %s",
+ setfilenames[i]);
+
+ /* Enter Capsicum sandbox. */
+ if (caph_enter() < 0)
+ err(2, "unable to enter capability mode");
+
+ for (i = 0; i < nds; i++) {
+ ds[i] = ReadSet(setfiles[i], setfilenames[i], column, delim);
+ if (setfiles[i] != stdin)
+ fclose(setfiles[i]);
+ }
+
+ if (!flag_q) {
+ for (i = 0; i < nds; i++)
+ printf("%c %s\n", symbol[i+1], ds[i]->name);
+ }
+
+ if (!flag_n && !suppress_plot) {
+ SetupPlot(termwidth, flag_s, nds);
+ for (i = 0; i < nds; i++)
+ DimPlot(ds[i]);
+ for (i = 0; i < nds; i++)
+ PlotSet(ds[i], i + 1);
+ DumpPlot();
+ }
+ if (!flag_q)
+ VitalsHead();
+ Vitals(ds[0], 1);
+ for (i = 1; i < nds; i++) {
+ Vitals(ds[i], i + 1);
+ if (!flag_n)
+ Relative(ds[i], ds[0], ci);
+ }
+ exit(0);
+}
diff --git a/usr.bin/mkcsmapper/Makefile b/usr.bin/mkcsmapper/Makefile
new file mode 100644
index 000000000000..d8e8dfab4f7d
--- /dev/null
+++ b/usr.bin/mkcsmapper/Makefile
@@ -0,0 +1,15 @@
+.PATH: ${SRCTOP}/lib/libc/iconv
+
+PROG= mkcsmapper
+.if defined(BOOTSTRAPPING)
+# When bootstrapping, the host libc might not contain these expected symbols
+# so compile them directly into the binary.
+SRCS= citrus_bcs.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_lookup_factory.c citrus_pivot_factory.c
+.endif
+LDFLAGS+= -L${SRCTOP}/lib/libc
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+.include "${.CURDIR}/Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkcsmapper/Makefile.depend b/usr.bin/mkcsmapper/Makefile.depend
new file mode 100644
index 000000000000..12b15914f2b6
--- /dev/null
+++ b/usr.bin/mkcsmapper/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkcsmapper/Makefile.inc b/usr.bin/mkcsmapper/Makefile.inc
new file mode 100644
index 000000000000..7189f83ba534
--- /dev/null
+++ b/usr.bin/mkcsmapper/Makefile.inc
@@ -0,0 +1,7 @@
+.include <bsd.compiler.mk>
+
+SRCS+= lex.l yacc.y
+CFLAGS+= -I${.CURDIR} -I${SRCTOP}/usr.bin/mkcsmapper \
+ -I${SRCTOP}/lib/libc/iconv \
+ -I${SRCTOP}/lib/libiconv_modules/mapper_std
+CFLAGS.gcc+= --param max-inline-insns-single=64
diff --git a/usr.bin/mkcsmapper/ldef.h b/usr.bin/mkcsmapper/ldef.h
new file mode 100644
index 000000000000..c5b10a87cd26
--- /dev/null
+++ b/usr.bin/mkcsmapper/ldef.h
@@ -0,0 +1,42 @@
+/* $NetBSD: ldef.h,v 1.2 2006/09/09 14:35:17 tnozaki Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003, 2006 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+
+typedef struct {
+ u_int32_t begin;
+ u_int32_t end;
+ u_int32_t width;
+} linear_zone_t;
+
+extern int debug;
+extern int linenumber;
+extern int yyerror(const char *);
+extern int yylex(void);
diff --git a/usr.bin/mkcsmapper/lex.l b/usr.bin/mkcsmapper/lex.l
new file mode 100644
index 000000000000..74d86f90e25f
--- /dev/null
+++ b/usr.bin/mkcsmapper/lex.l
@@ -0,0 +1,110 @@
+/* $NetBSD: lex.l,v 1.4 2006/02/09 22:03:15 dogcow Exp $ */
+
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/endian.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ldef.h"
+#include "yacc.h"
+
+#define YY_DECL int yylex(void)
+
+int linenumber = 1;
+%}
+%option noinput
+%option nounput
+
+%x COMMENT
+
+%%
+
+[ \t]+ { }
+#.*[\n]|"//".*[\n]|[\n] { linenumber++; return (R_LN); }
+
+"/*" { BEGIN COMMENT; }
+<COMMENT>"*/" { BEGIN 0; }
+<COMMENT>[\n] { linenumber++; }
+<COMMENT>. { }
+<COMMENT><<EOF>> {
+ yyerror("unexpected file end (unterminated comment)\n");
+ exit(1);
+ }
+
+"="|"/"|"-" { return ((int)yytext[0]); }
+
+([1-9][0-9]*)|(0[0-9]*)|(0[xX][0-9A-Fa-f]+) {
+ yylval.i_value = strtoul(yytext, NULL, 0);
+ return (L_IMM);
+ }
+
+"TYPE" { return (R_TYPE); }
+"NAME" { return (R_NAME); }
+"SRC_ZONE" { return (R_SRC_ZONE); }
+"DST_INVALID" { return (R_DST_INVALID); }
+"DST_ILSEQ" { return (R_DST_ILSEQ); }
+"DST_UNIT_BITS" { return (R_DST_UNIT_BITS); }
+"BEGIN_MAP" { return (R_BEGIN_MAP); }
+"END_MAP" { return (R_END_MAP); }
+"INVALID" { return (R_INVALID); }
+"ILSEQ" { return (R_ILSEQ); }
+"OOB_MODE" { return (R_OOB_MODE); }
+"ROWCOL" { return (R_ROWCOL); }
+
+\"([^\"\n]*(\\\")?)*\"|\'([^\'\n]*(\\\')?)*\' {
+ size_t len;
+
+ len = strlen(yytext);
+ yylval.s_value = malloc(len - 1);
+ strlcpy(yylval.s_value, yytext + 1, len - 1);
+ return (L_STRING);
+ }
+[^ =/\-0-9\t\n][^ \t\n]* {
+ yylval.s_value = strdup(yytext);
+ return (L_STRING);
+ }
+
+%%
+
+#ifndef yywrap
+int
+yywrap(void)
+{
+
+ return (1);
+}
+#endif
diff --git a/usr.bin/mkcsmapper/mkcsmapper.1 b/usr.bin/mkcsmapper/mkcsmapper.1
new file mode 100644
index 000000000000..b1c9325f854b
--- /dev/null
+++ b/usr.bin/mkcsmapper/mkcsmapper.1
@@ -0,0 +1,88 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained at
+.\" https://www.opengroup.org/membership/forums/platform/unix
+.\"
+.Dd July 9, 2016
+.Dt MKCSMAPPER 1
+.Os
+.Sh NAME
+.Nm mkcsmapper
+.Nd generates hashed conversion data for
+.Xr iconv 3
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl m | Fl p
+.Op Fl o Ar outfile
+.Op Ar infile
+.Sh DESCRIPTION
+The
+.Nm
+utility generates binary conversion data from plain text conversion tables
+for the
+.Xr iconv 3
+library.
+The conversion data has two components:
+The conversion mapping between specific character encodings.
+A pivot file, which the possible source and destination encoding
+pairs or the set of mappings to use for a compound encoding.
+.Pp
+The following options are available:
+.Bl -tag -width XoXoutfileXX
+.It Fl d
+Turns on debug mode.
+.It Fl m
+Generate mapping data from
+.Ar infile .
+.It Fl o Ar outfile
+Put generated binary data to
+.Ar outfile .
+.It Fl p
+Generate pivot data from
+.Ar outfile .
+.El
+.Sh EXIT STATUS
+.Ex -std mkcsmapper
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr mkesdb 1 ,
+.Xr iconv 3
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 2.0 ,
+and made its appearance in
+.Fx 9.0 .
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq Mt gabor@FreeBSD.org .
diff --git a/usr.bin/mkcsmapper/yacc.y b/usr.bin/mkcsmapper/yacc.y
new file mode 100644
index 000000000000..85bd525b315f
--- /dev/null
+++ b/usr.bin/mkcsmapper/yacc.y
@@ -0,0 +1,728 @@
+/* $NetBSD: yacc.y,v 1.11 2016/06/28 09:22:16 wiz Exp $ */
+
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003, 2006 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+#include "ldef.h"
+
+#ifndef __packed
+#define __packed
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_mapper_std_file.h"
+#include "citrus_region.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup_factory.h"
+#include "citrus_pivot_factory.h"
+
+extern FILE *yyin;
+
+int debug = 0;
+
+static linear_zone_t rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX];
+static char *map_name;
+static char *output = NULL;
+static void *table = NULL;
+static size_t rowcol_len = 0;
+static size_t table_size;
+static u_int32_t done_flag = 0;
+static u_int32_t dst_ilseq, dst_invalid, dst_unit_bits, oob_mode;
+static u_int32_t rowcol_bits = 0, rowcol_mask = 0;
+static u_int32_t src_next;
+static int map_type;
+static void (*putfunc)(void *, size_t, u_int32_t) = NULL;
+
+#define DF_TYPE 0x00000001
+#define DF_NAME 0x00000002
+#define DF_SRC_ZONE 0x00000004
+#define DF_DST_INVALID 0x00000008
+#define DF_DST_ILSEQ 0x00000010
+#define DF_DST_UNIT_BITS 0x00000020
+#define DF_OOB_MODE 0x00000040
+
+static void dump_file(void);
+static void setup_map(void);
+static void set_type(int);
+static void set_name(char *);
+static void set_src_zone(u_int32_t);
+static void set_dst_invalid(u_int32_t);
+static void set_dst_ilseq(u_int32_t);
+static void set_dst_unit_bits(u_int32_t);
+static void set_oob_mode(u_int32_t);
+static int check_src(u_int32_t, u_int32_t);
+static void store(const linear_zone_t *, u_int32_t, int);
+static void put8(void *, size_t, u_int32_t);
+static void put16(void *, size_t, u_int32_t);
+static void put32(void *, size_t, u_int32_t);
+static void set_range(u_int32_t, u_int32_t);
+static void set_src(linear_zone_t *, u_int32_t, u_int32_t);
+%}
+
+%union {
+ u_int32_t i_value;
+ char *s_value;
+ linear_zone_t lz_value;
+}
+
+%token R_TYPE R_NAME R_SRC_ZONE R_DST_UNIT_BITS
+%token R_DST_INVALID R_DST_ILSEQ
+%token R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL
+%token R_ILSEQ R_OOB_MODE
+%token R_LN
+%token <i_value> L_IMM
+%token <s_value> L_STRING
+
+%type <lz_value> src
+%type <i_value> dst types oob_mode_sel zone
+
+%%
+
+file : property mapping lns
+ { dump_file(); }
+
+property : /* empty */
+ | property R_LN
+ | property name
+ | property type
+ | property src_zone
+ | property dst_invalid
+ | property dst_ilseq
+ | property dst_unit_bits
+ | property oob_mode
+
+name : R_NAME L_STRING { set_name($2); $2 = NULL; }
+type : R_TYPE types { set_type($2); }
+types : R_ROWCOL { $$ = R_ROWCOL; }
+range : L_IMM '-' L_IMM { set_range($1, $3); }
+
+ranges : /* empty */
+ | ranges range '/'
+
+src_zone : R_SRC_ZONE zone { set_src_zone($2); }
+zone : range {
+ $$ = 32;
+ }
+ | range '/' range '/' ranges L_IMM {
+ $$ = $6;
+ }
+
+dst_invalid : R_DST_INVALID L_IMM { set_dst_invalid($2); }
+dst_ilseq : R_DST_ILSEQ L_IMM { set_dst_ilseq($2); }
+dst_unit_bits : R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); }
+oob_mode : R_OOB_MODE oob_mode_sel { set_oob_mode($2); }
+
+oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
+ | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
+
+mapping : begin_map map_elems R_END_MAP
+begin_map : R_BEGIN_MAP lns { setup_map(); }
+
+map_elems : /* empty */
+ | map_elems map_elem lns
+
+map_elem : src '=' dst
+ { store(&$1, $3, 0); }
+ | src '=' L_IMM '-'
+ { store(&$1, $3, 1); }
+dst : L_IMM
+ {
+ $$ = $1;
+ }
+ | R_INVALID
+ {
+ $$ = dst_invalid;
+ }
+ | R_ILSEQ
+ {
+ $$ = dst_ilseq;
+ }
+
+src : /* empty */
+ {
+ set_src(&$$, src_next, src_next);
+ }
+ | L_IMM
+ {
+ set_src(&$$, $1, $1);
+ }
+ | L_IMM '-' L_IMM
+ {
+ set_src(&$$, $1, $3);
+ }
+ | '-' L_IMM
+ {
+ set_src(&$$, src_next, $2);
+ }
+lns : R_LN
+ | lns R_LN
+
+%%
+
+static void
+warning(const char *s)
+{
+
+ fprintf(stderr, "%s in %d\n", s, linenumber);
+}
+
+int
+yyerror(const char *s)
+{
+
+ warning(s);
+ exit(1);
+}
+
+void
+put8(void *ptr, size_t ofs, u_int32_t val)
+{
+
+ *((u_int8_t *)ptr + ofs) = val;
+}
+
+void
+put16(void *ptr, size_t ofs, u_int32_t val)
+{
+
+ u_int16_t oval = htons(val);
+ memcpy((u_int16_t *)ptr + ofs, &oval, 2);
+}
+
+void
+put32(void *ptr, size_t ofs, u_int32_t val)
+{
+
+ u_int32_t oval = htonl(val);
+ memcpy((u_int32_t *)ptr + ofs, &oval, 4);
+}
+
+static void
+alloc_table(void)
+{
+ linear_zone_t *p;
+ size_t i;
+ uint32_t val = 0;
+
+ i = rowcol_len;
+ p = &rowcol[--i];
+ table_size = p->width;
+ while (i > 0) {
+ p = &rowcol[--i];
+ table_size *= p->width;
+ }
+ table = (void *)malloc(table_size * dst_unit_bits / 8);
+ if (table == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ switch (oob_mode) {
+ case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
+ val = dst_invalid;
+ break;
+ case _CITRUS_MAPPER_STD_OOB_ILSEQ:
+ val = dst_ilseq;
+ break;
+ default:
+ break;
+ }
+ for (i = 0; i < table_size; i++)
+ (*putfunc)(table, i, val);
+}
+
+static void
+setup_map(void)
+{
+
+ if ((done_flag & DF_SRC_ZONE)==0) {
+ fprintf(stderr, "SRC_ZONE is mandatory.\n");
+ exit(1);
+ }
+ if ((done_flag & DF_DST_UNIT_BITS)==0) {
+ fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
+ exit(1);
+ }
+
+ if ((done_flag & DF_DST_INVALID) == 0)
+ dst_invalid = 0xFFFFFFFF;
+ if ((done_flag & DF_DST_ILSEQ) == 0)
+ dst_ilseq = 0xFFFFFFFE;
+ if ((done_flag & DF_OOB_MODE) == 0)
+ oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
+
+ alloc_table();
+}
+
+static void
+create_rowcol_info(struct _region *r)
+{
+ void *ptr;
+ size_t i, len, ofs;
+
+ ofs = 0;
+ ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
+ if (ptr == NULL)
+ err(EXIT_FAILURE, "malloc");
+ put32(ptr, ofs, rowcol_bits); ofs++;
+ put32(ptr, ofs, dst_invalid); ofs++;
+
+ /* XXX: keep backward compatibility */
+ switch (rowcol_len) {
+ case 1:
+ put32(ptr, ofs, 0); ofs++;
+ put32(ptr, ofs, 0); ofs++;
+ /*FALLTHROUGH*/
+ case 2:
+ len = 0;
+ break;
+ default:
+ len = rowcol_len;
+ }
+ for (i = 0; i < rowcol_len; ++i) {
+ put32(ptr, ofs, rowcol[i].begin); ofs++;
+ put32(ptr, ofs, rowcol[i].end); ofs++;
+ }
+ put32(ptr, ofs, dst_unit_bits); ofs++;
+ put32(ptr, ofs, len); ofs++;
+
+ _region_init(r, ptr, ofs * 4);
+}
+
+
+static void
+create_rowcol_ext_ilseq_info(struct _region *r)
+{
+ void *ptr;
+ size_t ofs;
+
+ ofs = 0;
+ ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
+ if (ptr == NULL)
+ err(EXIT_FAILURE, "malloc");
+
+ put32(ptr, ofs, oob_mode); ofs++;
+ put32(ptr, ofs, dst_ilseq); ofs++;
+
+ _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
+}
+
+#define CHKERR(ret, func, a) \
+do { \
+ ret = func a; \
+ if (ret) \
+ errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
+} while (/*CONSTCOND*/0)
+
+static void
+dump_file(void)
+{
+ struct _db_factory *df;
+ struct _region data;
+ void *serialized;
+ FILE *fp;
+ size_t size;
+ int ret;
+
+ /*
+ * build database
+ */
+ CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
+
+ /* store type */
+ CHKERR(ret, _db_factory_addstr_by_s,
+ (df, _CITRUS_MAPPER_STD_SYM_TYPE, _CITRUS_MAPPER_STD_TYPE_ROWCOL));
+
+ /* store info */
+ create_rowcol_info(&data);
+ CHKERR(ret, _db_factory_add_by_s,
+ (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1));
+
+ /* ilseq extension */
+ create_rowcol_ext_ilseq_info(&data);
+ CHKERR(ret, _db_factory_add_by_s,
+ (df, _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &data, 1));
+
+ /* store table */
+ _region_init(&data, table, table_size*dst_unit_bits/8);
+ CHKERR(ret, _db_factory_add_by_s,
+ (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1));
+
+ /*
+ * dump database to file
+ */
+ fp = output ? fopen(output, "wb") : stdout;
+
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+
+ /* dump database body */
+ size = _db_factory_calc_size(df);
+ serialized = malloc(size);
+ _region_init(&data, serialized, size);
+ CHKERR(ret, _db_factory_serialize,
+ (df, _CITRUS_MAPPER_STD_MAGIC, &data));
+ if (fwrite(serialized, size, 1, fp) != 1)
+ err(EXIT_FAILURE, "fwrite");
+
+ fclose(fp);
+}
+
+static void
+/*ARGSUSED*/
+set_type(int type)
+{
+
+ if (done_flag & DF_TYPE) {
+ warning("TYPE is duplicated. ignored this one");
+ return;
+ }
+
+ map_type = type;
+
+ done_flag |= DF_TYPE;
+}
+
+static void
+/*ARGSUSED*/
+set_name(char *str)
+{
+
+ if (done_flag & DF_NAME) {
+ warning("NAME is duplicated. ignored this one");
+ return;
+ }
+
+ map_name = str;
+
+ done_flag |= DF_NAME;
+}
+
+static void
+set_src_zone(u_int32_t val)
+{
+ linear_zone_t *p;
+ size_t i;
+
+ if (done_flag & DF_SRC_ZONE) {
+ warning("SRC_ZONE is duplicated. ignored this one");
+ return;
+ }
+ rowcol_bits = val;
+
+ /* sanity check */
+ switch (rowcol_bits) {
+ case 8: case 16: case 32:
+ if (rowcol_len <= 32 / rowcol_bits)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ goto bad;
+ }
+ rowcol_mask = 1u << (rowcol_bits - 1);
+ rowcol_mask |= rowcol_mask - 1;
+ for (i = 0; i < rowcol_len; ++i) {
+ p = &rowcol[i];
+ if (p->end > rowcol_mask)
+ goto bad;
+ }
+ done_flag |= DF_SRC_ZONE;
+ return;
+
+bad:
+ yyerror("Illegal argument for SRC_ZONE");
+}
+
+static void
+set_dst_invalid(u_int32_t val)
+{
+
+ if (done_flag & DF_DST_INVALID) {
+ warning("DST_INVALID is duplicated. ignored this one");
+ return;
+ }
+
+ dst_invalid = val;
+
+ done_flag |= DF_DST_INVALID;
+}
+
+static void
+set_dst_ilseq(u_int32_t val)
+{
+
+ if (done_flag & DF_DST_ILSEQ) {
+ warning("DST_ILSEQ is duplicated. ignored this one");
+ return;
+ }
+
+ dst_ilseq = val;
+
+ done_flag |= DF_DST_ILSEQ;
+}
+
+static void
+set_oob_mode(u_int32_t val)
+{
+
+ if (done_flag & DF_OOB_MODE) {
+ warning("OOB_MODE is duplicated. ignored this one");
+ return;
+ }
+
+ oob_mode = val;
+
+ done_flag |= DF_OOB_MODE;
+}
+
+static void
+set_dst_unit_bits(u_int32_t val)
+{
+
+ if (done_flag & DF_DST_UNIT_BITS) {
+ warning("DST_UNIT_BITS is duplicated. ignored this one");
+ return;
+ }
+
+ switch (val) {
+ case 8:
+ putfunc = &put8;
+ dst_unit_bits = val;
+ break;
+ case 16:
+ putfunc = &put16;
+ dst_unit_bits = val;
+ break;
+ case 32:
+ putfunc = &put32;
+ dst_unit_bits = val;
+ break;
+ default:
+ yyerror("Illegal argument for DST_UNIT_BITS");
+ }
+ done_flag |= DF_DST_UNIT_BITS;
+}
+
+static int
+check_src(u_int32_t begin, u_int32_t end)
+{
+ linear_zone_t *p;
+ size_t i;
+ u_int32_t m, n;
+
+ if (begin > end)
+ return (1);
+ if (begin < end) {
+ m = begin & ~rowcol_mask;
+ n = end & ~rowcol_mask;
+ if (m != n)
+ return (1);
+ }
+ for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) {
+ i -= rowcol_bits;
+ m = (begin >> i) & rowcol_mask;
+ if (m < p->begin || m > p->end)
+ return (1);
+ }
+ if (begin < end) {
+ n = end & rowcol_mask;
+ --p;
+ if (n < p->begin || n > p->end)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+store(const linear_zone_t *lz, u_int32_t dst, int inc)
+{
+ linear_zone_t *p;
+ size_t i, ofs;
+ u_int32_t n;
+
+ ofs = 0;
+ for (i = rowcol_len * rowcol_bits, p = &rowcol[0]; i > 0; ++p) {
+ i -= rowcol_bits;
+ n = ((lz->begin >> i) & rowcol_mask) - p->begin;
+ ofs = (ofs * p->width) + n;
+ }
+ n = lz->width;
+ while (n-- > 0) {
+ (*putfunc)(table, ofs++, dst);
+ if (inc)
+ dst++;
+ }
+}
+
+static void
+set_range(u_int32_t begin, u_int32_t end)
+{
+ linear_zone_t *p;
+
+ if (rowcol_len >= _CITRUS_MAPPER_STD_ROWCOL_MAX)
+ goto bad;
+ p = &rowcol[rowcol_len++];
+
+ if (begin > end)
+ goto bad;
+ p->begin = begin, p->end = end;
+ p->width = end - begin + 1;
+
+ return;
+
+bad:
+ yyerror("Illegal argument for SRC_ZONE");
+}
+
+static void
+set_src(linear_zone_t *lz, u_int32_t begin, u_int32_t end)
+{
+
+ if (check_src(begin, end) != 0)
+ yyerror("illegal zone");
+
+ lz->begin = begin, lz->end = end;
+ lz->width = end - begin + 1;
+
+ src_next = end + 1;
+}
+
+static void
+do_mkdb(FILE *in)
+{
+ FILE *out;
+ int ret;
+
+ /* dump DB to file */
+ out = output ? fopen(output, "wb") : stdout;
+
+ if (out == NULL)
+ err(EXIT_FAILURE, "fopen");
+
+ ret = _lookup_factory_convert(out, in);
+ fclose(out);
+ if (ret && output)
+ unlink(output); /* dump failure */
+}
+
+static void
+do_mkpv(FILE *in)
+{
+ FILE *out;
+ int ret;
+
+ /* dump pivot to file */
+ out = output ? fopen(output, "wb") : stdout;
+
+ if (out == NULL)
+ err(EXIT_FAILURE, "fopen");
+
+ ret = _pivot_factory_convert(out, in);
+ fclose(out);
+ if (ret && output)
+ unlink(output); /* dump failure */
+ if (ret)
+ errx(EXIT_FAILURE, "%s\n", strerror(ret));
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s [-d] [-m|-p] [-o outfile] [infile]\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *in = NULL;
+ int ch, mkdb = 0, mkpv = 0;
+
+ while ((ch = getopt(argc, argv, "do:mp")) != EOF) {
+ switch (ch) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'o':
+ output = strdup(optarg);
+ break;
+ case 'm':
+ mkdb = 1;
+ break;
+ case 'p':
+ mkpv = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ switch (argc) {
+ case 0:
+ in = stdin;
+ break;
+ case 1:
+ in = fopen(argv[0], "r");
+ if (!in)
+ err(EXIT_FAILURE, "%s", argv[0]);
+ break;
+ default:
+ usage();
+ }
+
+ if (mkdb)
+ do_mkdb(in);
+ else if (mkpv)
+ do_mkpv(in);
+ else {
+ yyin = in;
+ yyparse();
+ }
+
+ return (0);
+}
diff --git a/usr.bin/mkcsmapper_static/Makefile b/usr.bin/mkcsmapper_static/Makefile
new file mode 100644
index 000000000000..777f29bd9403
--- /dev/null
+++ b/usr.bin/mkcsmapper_static/Makefile
@@ -0,0 +1,15 @@
+.PATH: ${SRCTOP}/lib/libc/iconv ${SRCTOP}/usr.bin/mkcsmapper
+
+PROG= mkcsmapper_static
+SRCS= citrus_bcs.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_lookup_factory.c citrus_pivot_factory.c
+MAN=
+NO_SHARED= yes
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+build-tools: mkcsmapper_static
+
+.include "${SRCTOP}/usr.bin/mkcsmapper/Makefile.inc"
+.include <bsd.prog.mk>
+
+${PROG}: ${BUILD_TOOLS_META}
diff --git a/usr.bin/mkdep/Makefile b/usr.bin/mkdep/Makefile
new file mode 100644
index 000000000000..3a0500c9510c
--- /dev/null
+++ b/usr.bin/mkdep/Makefile
@@ -0,0 +1,5 @@
+SCRIPTS= mkdep.gcc.sh
+MAN= mkdep.1
+SCRIPTSNAME= mkdep
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkdep/Makefile.depend b/usr.bin/mkdep/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/mkdep/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkdep/Makefile.depend.host b/usr.bin/mkdep/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/mkdep/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkdep/Makefile.depend.options b/usr.bin/mkdep/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/mkdep/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/mkdep/mkdep.1 b/usr.bin/mkdep/mkdep.1
new file mode 100644
index 000000000000..d8444df07034
--- /dev/null
+++ b/usr.bin/mkdep/mkdep.1
@@ -0,0 +1,126 @@
+.\" Copyright (c) 1987, 1990, 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.
+.\"
+.Dd October 23, 2015
+.Dt MKDEP 1
+.Os
+.Sh NAME
+.Nm mkdep
+.Nd construct Makefile dependency list
+.Sh SYNOPSIS
+.Nm
+.Op Fl ap
+.Op Fl f Ar file
+.Op Ar flags
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility takes a set of flags for the C compiler and a list
+of C source files as arguments and constructs a set of include
+file dependencies which are written into the file ``.depend''.
+An example of its use in a Makefile might be:
+.Bd -literal -offset indent
+CFLAGS= -O -I../include
+SRCS= file1.c file2.c
+
+depend:
+ mkdep ${CFLAGS} ${SRCS}
+.Ed
+.Pp
+where the macro SRCS is the list of C source files and the macro
+CFLAGS is the list of flags for the C compiler.
+.Pp
+The user has the ability to change the preprocessor and preprocessor options
+used.
+For instance, to use
+.Sy cc
+as the preprocessor and to ignore system
+headers, one would use
+.Bd -literal -offset indent
+depend:
+ env MKDEP_CPP="cc -E" MKDEP_CPP_OPTS=-MM mkdep \\
+ ${CFLAGS} ${SRCS}
+.Ed
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Append to the output file,
+so that multiple
+.Nm Ns 's
+may be run from a single Makefile.
+.It Fl f
+Write the include file dependencies to
+.Ar file ,
+instead of the default ``.depend''.
+.It Fl p
+Cause
+.Nm
+to produce dependencies of the form:
+.Bd -literal -offset indent
+program: program.c
+.Ed
+.Pp
+so that subsequent makes will produce
+.Ar program
+directly from its C module rather than using an intermediate
+.Pa \&.o
+module.
+This is useful for programs whose source is contained in a single
+module.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width MKDEP_CPP_OPTS
+.It Ev CC
+Specifies the C compiler to use.
+The specified compiler is expected to have
+options consistent with the GNU C compiler.
+The default is
+.Sy cc .
+.It Ev MKDEP_CPP
+Specifies the preprocessor to use.
+The default is "${CC} -E".
+.It Ev MKDEP_CPP_OPTS
+Specifies the non-CFLAGS options for the preprocessor.
+The default is
+"-M".
+.El
+.Sh FILES
+.Bl -tag -width .depend -compact
+.It Pa .depend
+File containing list of dependencies.
+.El
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr cpp 1 ,
+.Xr make 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 Tahoe .
diff --git a/usr.bin/mkdep/mkdep.gcc.sh b/usr.bin/mkdep/mkdep.gcc.sh
new file mode 100644
index 000000000000..43cc848d851b
--- /dev/null
+++ b/usr.bin/mkdep/mkdep.gcc.sh
@@ -0,0 +1,95 @@
+#!/bin/sh -
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 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.
+
+D=.depend # default dependency file is .depend
+append=0
+pflag=
+
+while :
+ do case "$1" in
+ # -a appends to the depend file
+ -a)
+ append=1
+ shift ;;
+
+ # -f allows you to select a makefile name
+ -f)
+ D=$2
+ shift; shift ;;
+
+ # the -p flag produces "program: program.c" style dependencies
+ # so .o's don't get produced
+ -p)
+ pflag=p
+ shift ;;
+ *)
+ break ;;
+ esac
+done
+
+case $# in 0)
+ echo 'usage: mkdep [-ap] [-f file] [flags] file ...' >&2
+ exit 1;;
+esac
+
+TMP=_mkdep$$
+trap 'rm -f $TMP ; trap 2 ; kill -2 $$' 1 2 3 13 15
+trap 'rm -f $TMP' 0
+
+# For C sources, mkdep must use exactly the same cpp and predefined flags
+# as the compiler would. This is easily arranged by letting the compiler
+# pick the cpp. mkdep must be told the cpp to use for exceptional cases.
+CC=${CC-"cc"}
+MKDEP_CPP=${MKDEP_CPP-"${CC} -E"}
+MKDEP_CPP_OPTS=${MKDEP_CPP_OPTS-"-M"};
+
+echo "# $@" > $TMP # store arguments for debugging
+
+if $MKDEP_CPP $MKDEP_CPP_OPTS "$@" >> $TMP; then :
+else
+ echo 'mkdep: compile failed' >&2
+ exit 1
+fi
+
+case x$pflag in
+ x) case $append in
+ 0) sed -e 's; \./; ;g' < $TMP > $D;;
+ *) sed -e 's; \./; ;g' < $TMP >> $D;;
+ esac
+ ;;
+ *) case $append in
+ 0) sed -e 's;\.o:;:;' -e 's; \./; ;g' < $TMP > $D;;
+ *) sed -e 's;\.o:;:;' -e 's; \./; ;g' < $TMP >> $D;;
+ esac
+ ;;
+esac
+
+exit $?
diff --git a/usr.bin/mkdep/mkdep.sh b/usr.bin/mkdep/mkdep.sh
new file mode 100644
index 000000000000..bda5f60cfee7
--- /dev/null
+++ b/usr.bin/mkdep/mkdep.sh
@@ -0,0 +1,107 @@
+#!/bin/sh -
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 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.
+#
+
+PATH=/bin:/usr/bin:/usr/ucb:/usr/old/bin
+export PATH
+
+D=.depend # default dependency file is .depend
+append=0
+
+while :
+ do case "$1" in
+ # -a appends to the depend file
+ -a)
+ append=1
+ shift ;;
+
+ # -f allows you to select a makefile name
+ -f)
+ D=$2
+ shift; shift ;;
+
+ # the -p flag produces "program: program.c" style dependencies
+ # so .o's don't get produced
+ -p)
+ SED='s;\.o ; ;'
+ shift ;;
+ *)
+ break ;;
+ esac
+done
+
+if [ $# = 0 ] ; then
+ echo 'usage: mkdep [-p] [-f depend_file] [cc_flags] file ...'
+ exit 1
+fi
+
+TMP=/tmp/mkdep$$
+
+trap 'rm -f $TMP ; trap 2 ; kill -2 $$' 1 2 3 13 15
+
+cc -M $* |
+sed "
+ s; \./; ;g
+ /\.c:$/d
+ $SED" |
+awk '{
+ if ($1 != prev) {
+ if (rec != "")
+ print rec;
+ rec = $0;
+ prev = $1;
+ }
+ else {
+ if (length(rec $2) > 78) {
+ print rec;
+ rec = $0;
+ }
+ else
+ rec = rec " " $2
+ }
+}
+END {
+ print rec
+}' > $TMP
+
+if [ $? != 0 ]; then
+ echo 'mkdep: compile failed.'
+ rm -f $TMP
+ exit 1
+fi
+
+if [ $append = 1 ]; then
+ cat $TMP >> $D
+ rm -f $TMP
+else
+ mv $TMP $D
+fi
+exit 0
diff --git a/usr.bin/mkesdb/Makefile b/usr.bin/mkesdb/Makefile
new file mode 100644
index 000000000000..275a8f65cb1a
--- /dev/null
+++ b/usr.bin/mkesdb/Makefile
@@ -0,0 +1,14 @@
+.PATH: ${SRCTOP}/lib/libc/iconv
+
+PROG= mkesdb
+.if defined(BOOTSTRAPPING)
+# When bootstrapping, the host libc might not contain these expected symbols
+# so compile them directly into the binary.
+SRCS= citrus_bcs.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_lookup_factory.c
+.endif
+
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+.include "${.CURDIR}/Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkesdb/Makefile.depend b/usr.bin/mkesdb/Makefile.depend
new file mode 100644
index 000000000000..c2fea3d32305
--- /dev/null
+++ b/usr.bin/mkesdb/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ usr.bin/yacc.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkesdb/Makefile.inc b/usr.bin/mkesdb/Makefile.inc
new file mode 100644
index 000000000000..ffc3f4505fb2
--- /dev/null
+++ b/usr.bin/mkesdb/Makefile.inc
@@ -0,0 +1,3 @@
+SRCS+= lex.l yacc.y
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../mkesdb \
+ -I${.CURDIR}/../../lib/libc/iconv
diff --git a/usr.bin/mkesdb/ldef.h b/usr.bin/mkesdb/ldef.h
new file mode 100644
index 000000000000..27ef9663f06e
--- /dev/null
+++ b/usr.bin/mkesdb/ldef.h
@@ -0,0 +1,40 @@
+/* $NetBSD: ldef.h,v 1.2 2005/06/27 01:23:59 fvdl Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+extern int linenumber;
+extern int yyerror(const char *);
+extern int yylex(void);
+
+struct named_csid {
+ STAILQ_ENTRY(named_csid) ci_entry;
+ char *ci_symbol;
+ u_int32_t ci_csid;
+};
+STAILQ_HEAD(named_csid_list, named_csid);
diff --git a/usr.bin/mkesdb/lex.l b/usr.bin/mkesdb/lex.l
new file mode 100644
index 000000000000..2b17a337d6e7
--- /dev/null
+++ b/usr.bin/mkesdb/lex.l
@@ -0,0 +1,103 @@
+/* $NetBSD: lex.l,v 1.3 2006/02/09 22:03:15 dogcow Exp $ */
+
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ldef.h"
+#include "yacc.h"
+
+#define YY_DECL int yylex(void)
+
+int linenumber = 1;
+%}
+%option noinput
+%option nounput
+
+%x COMMENT
+
+%%
+
+[ \t]+ { }
+#.*[\n]|"//".*[\n]|[\n] { linenumber++; return (R_LN); }
+
+"/*" { BEGIN COMMENT; }
+<COMMENT>"*/" { BEGIN 0; }
+<COMMENT>[\n] { linenumber++; }
+<COMMENT>. { }
+<COMMENT><<EOF>> {
+ yyerror("unexpected file end (unterminated comment)\n");
+ exit(1);
+ }
+
+([1-9][0-9]*)|(0[0-9]*)|(0[xX][0-9A-Fa-f]+) {
+ yylval.i_value = strtoul(yytext, NULL, 0);
+ return (L_IMM);
+ }
+
+"NAME" { return (R_NAME); }
+"ENCODING" { return (R_ENCODING); }
+"VARIABLE" { return (R_VARIABLE); }
+"DEFCSID" { return (R_DEFCSID); }
+"INVALID" { return (R_INVALID); }
+
+\"([^\"\n]*(\\\")?)*\"|\'([^\'\n]*(\\\')?)*\' {
+ size_t len;
+
+ len = strlen(yytext);
+ yylval.s_value = malloc(len - 1);
+ strlcpy(yylval.s_value, yytext + 1, len - 1);
+ return (L_STRING);
+ }
+[^ =/\-0-9\t\n][^ \t\n]* {
+ yylval.s_value = strdup(yytext);
+ return (L_STRING);
+ }
+
+%%
+
+#ifndef yywrap
+int
+yywrap(void)
+{
+
+ return (1);
+}
+#endif
diff --git a/usr.bin/mkesdb/mkesdb.1 b/usr.bin/mkesdb/mkesdb.1
new file mode 100644
index 000000000000..0e4f02b1bbd8
--- /dev/null
+++ b/usr.bin/mkesdb/mkesdb.1
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" https://www.opengroup.org/membership/forums/platform/unix
+.\"
+.Dd November 1, 2009
+.Dt MKESDB 1
+.Os
+.Sh NAME
+.Nm mkesdb
+.Nd generates conversion catalog for
+.Xr iconv 3
+.Sh SYNOPSIS
+.Nm
+.Op Fl md
+.Fl o
+.Ar outfile
+.Ar infile
+.Sh DESCRIPTION
+The
+.Nm
+utility generates conversion catalog for the
+.Xr iconv 3
+library.
+The generated data includes a list of supported encodings
+and their most important characteristics, like the pluggable
+module to use
+.Pp
+The following options are available:
+.Bl -tag -width 0123
+.It Fl d
+Turns on debug mode.
+.It Fl m
+Process directory catalog or alias file.
+If not specified, the input file is treated as an encoding description.
+.It Fl o Ar outfile
+Put generated binary data to
+.Ar outfile .
+.El
+.Sh EXIT STATUS
+.Ex -std mkesdb
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr mkcsmapper 1 ,
+.Xr iconv 3
+.Sh HISTORY
+.Nm
+first appeared in
+.Nx 2.0 , and made its appearance in
+.Fx 9.0 .
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq Mt gabor@FreeBSD.org .
diff --git a/usr.bin/mkesdb/yacc.y b/usr.bin/mkesdb/yacc.y
new file mode 100644
index 000000000000..9758fa9dd4c4
--- /dev/null
+++ b/usr.bin/mkesdb/yacc.y
@@ -0,0 +1,332 @@
+/* $NetBSD: yacc.y,v 1.4 2005/06/02 02:09:25 lukem Exp $ */
+
+%{
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c)2003 Citrus Project,
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/queue.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_region.h"
+#include "citrus_esdb_file.h"
+#include "citrus_db_hash.h"
+#include "citrus_db_factory.h"
+#include "citrus_lookup_factory.h"
+
+#include "ldef.h"
+
+extern FILE *yyin;
+
+static struct named_csid_list named_csids;
+static char *encoding, *name, *output = NULL, *variable;
+static u_int32_t invalid;
+static int debug = 0, num_csids = 0, use_invalid = 0;
+
+static void dump_file(void);
+static void register_named_csid(char *, u_int32_t);
+static void set_invalid(u_int32_t);
+static void set_prop_string(const char *, char **, char **);
+%}
+%union {
+ u_int32_t i_value;
+ char *s_value;
+}
+
+%token R_NAME R_ENCODING R_VARIABLE R_DEFCSID R_INVALID
+%token R_LN
+%token <i_value> L_IMM
+%token <s_value> L_STRING
+
+%%
+
+file : property
+ { dump_file(); }
+
+property : /* empty */
+ | property R_LN
+ | property name R_LN
+ | property encoding R_LN
+ | property variable R_LN
+ | property defcsid R_LN
+ | property invalid R_LN
+
+name : R_NAME L_STRING
+ {
+ set_prop_string("NAME", &name, &$2);
+ }
+
+encoding : R_ENCODING L_STRING
+ {
+ set_prop_string("ENCODING", &encoding, &$2);
+ }
+variable : R_VARIABLE L_STRING
+ {
+ set_prop_string("VARIABLE", &variable, &$2);
+ }
+defcsid : R_DEFCSID L_STRING L_IMM
+ {
+ register_named_csid($2, $3);
+ $2 = NULL;
+ }
+invalid : R_INVALID L_IMM
+ {
+ set_invalid($2);
+ }
+%%
+
+int
+yyerror(const char *s)
+{
+
+ fprintf(stderr, "%s in %d\n", s, linenumber);
+
+ return (0);
+}
+
+#define CHKERR(ret, func, a) \
+do { \
+ ret = func a; \
+ if (ret) \
+ errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
+} while (/*CONSTCOND*/0)
+static void
+dump_file(void)
+{
+ struct _db_factory *df;
+ struct _region data;
+ struct named_csid *csid;
+ FILE *fp;
+ char buf[100];
+ void *serialized;
+ size_t size;
+ int i, ret;
+
+ ret = 0;
+ if (!name) {
+ fprintf(stderr, "NAME is mandatory.\n");
+ ret = 1;
+ }
+ if (!encoding) {
+ fprintf(stderr, "ENCODING is mandatory.\n");
+ ret = 1;
+ }
+ if (ret)
+ exit(1);
+
+ /*
+ * build database
+ */
+ CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
+
+ /* store version */
+ CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_VERSION,
+ _CITRUS_ESDB_VERSION));
+
+ /* store encoding */
+ CHKERR(ret, _db_factory_addstr_by_s, (df, _CITRUS_ESDB_SYM_ENCODING,
+ encoding));
+
+ /* store variable */
+ if (variable)
+ CHKERR(ret, _db_factory_addstr_by_s,
+ (df, _CITRUS_ESDB_SYM_VARIABLE, variable));
+
+ /* store invalid */
+ if (use_invalid)
+ CHKERR(ret, _db_factory_add32_by_s, (df,
+ _CITRUS_ESDB_SYM_INVALID, invalid));
+
+ /* store num of charsets */
+ CHKERR(ret, _db_factory_add32_by_s, (df, _CITRUS_ESDB_SYM_NUM_CHARSETS,
+ num_csids));
+ i = 0;
+ STAILQ_FOREACH(csid, &named_csids, ci_entry) {
+ snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d",
+ i);
+ CHKERR(ret, _db_factory_addstr_by_s,
+ (df, buf, csid->ci_symbol));
+ snprintf(buf, sizeof(buf), _CITRUS_ESDB_SYM_CSID_PREFIX "%d",
+ i);
+ CHKERR(ret, _db_factory_add32_by_s, (df, buf, csid->ci_csid));
+ i++;
+ }
+
+ /*
+ * dump database to file
+ */
+ fp = output ? fopen(output, "wb") : stdout;
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+
+ /* dump database body */
+ size = _db_factory_calc_size(df);
+ serialized = malloc(size);
+ _region_init(&data, serialized, size);
+ CHKERR(ret, _db_factory_serialize, (df, _CITRUS_ESDB_MAGIC, &data));
+ if (fwrite(serialized, size, 1, fp) != 1)
+ err(EXIT_FAILURE, "fwrite");
+
+ fclose(fp);
+}
+
+static void
+set_prop_string(const char *res, char **store, char **data)
+{
+ char buf[256];
+
+ if (*store) {
+ snprintf(buf, sizeof(buf),
+ "%s is duplicated. ignored the one", res);
+ yyerror(buf);
+ return;
+ }
+
+ *store = *data;
+ *data = NULL;
+}
+
+static void
+set_invalid(u_int32_t inv)
+{
+
+ invalid = inv;
+ use_invalid = 1;
+}
+
+static void
+register_named_csid(char *sym, u_int32_t val)
+{
+ struct named_csid *csid;
+
+ STAILQ_FOREACH(csid, &named_csids, ci_entry) {
+ if (strcmp(csid->ci_symbol, sym) == 0) {
+ yyerror("multiply defined CSID");
+ exit(1);
+ }
+ }
+
+ csid = malloc(sizeof(*csid));
+ if (csid == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ csid->ci_symbol = sym;
+ csid->ci_csid = val;
+ STAILQ_INSERT_TAIL(&named_csids, csid, ci_entry);
+ num_csids++;
+}
+
+static void
+do_mkdb(FILE *in)
+{
+ FILE *out;
+ int ret;
+
+ /* dump DB to file */
+ out = output ? fopen(output, "wb") : stdout;
+ if (out == NULL)
+ err(EXIT_FAILURE, "fopen");
+
+ ret = _lookup_factory_convert(out, in);
+ fclose(out);
+ if (ret && output)
+ unlink(output); /* dump failure */
+ if (ret)
+ errx(EXIT_FAILURE, "%s\n", strerror(ret));
+}
+
+static void
+usage(void)
+{
+ errx(EXIT_FAILURE,
+ "usage:\n"
+ "\t%s [-d] [-o outfile] [infile]\n"
+ "\t%s -m [-d] [-o outfile] [infile]",
+ getprogname(), getprogname());
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *in = NULL;
+ int ch, mkdb = 0;
+
+ while ((ch = getopt(argc, argv, "do:m")) != EOF) {
+ switch (ch) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'o':
+ output = strdup(optarg);
+ break;
+ case 'm':
+ mkdb = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ switch (argc) {
+ case 0:
+ in = stdin;
+ break;
+ case 1:
+ in = fopen(argv[0], "r");
+ if (!in)
+ err(EXIT_FAILURE, "%s", argv[0]);
+ break;
+ default:
+ usage();
+ }
+
+ if (mkdb)
+ do_mkdb(in);
+ else {
+ STAILQ_INIT(&named_csids);
+ yyin = in;
+ yyparse();
+ }
+
+ return (0);
+}
diff --git a/usr.bin/mkesdb_static/Makefile b/usr.bin/mkesdb_static/Makefile
new file mode 100644
index 000000000000..3d41dbafeac5
--- /dev/null
+++ b/usr.bin/mkesdb_static/Makefile
@@ -0,0 +1,15 @@
+.PATH: ${SRCTOP}/lib/libc/iconv ${SRCTOP}/usr.bin/mkesdb
+
+PROG= mkesdb_static
+SRCS= citrus_bcs.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_lookup_factory.c
+MAN=
+NO_SHARED= yes
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+build-tools: mkesdb_static
+
+.include "${SRCTOP}/usr.bin/mkesdb/Makefile.inc"
+.include <bsd.prog.mk>
+
+${PROG}: ${BUILD_TOOLS_META}
diff --git a/usr.bin/mkfifo/Makefile b/usr.bin/mkfifo/Makefile
new file mode 100644
index 000000000000..aa19b2abf758
--- /dev/null
+++ b/usr.bin/mkfifo/Makefile
@@ -0,0 +1,3 @@
+PROG= mkfifo
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkfifo/Makefile.depend b/usr.bin/mkfifo/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/mkfifo/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkfifo/mkfifo.1 b/usr.bin/mkfifo/mkfifo.1
new file mode 100644
index 000000000000..ccb841904d76
--- /dev/null
+++ b/usr.bin/mkfifo/mkfifo.1
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd January 5, 1994
+.Dt MKFIFO 1
+.Os
+.Sh NAME
+.Nm mkfifo
+.Nd make fifos
+.Sh SYNOPSIS
+.Nm
+.Op Fl m Ar mode
+.Ar fifo_name ...
+.Sh DESCRIPTION
+The
+.Nm
+utility creates the fifos requested, in the order specified.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl m
+Set the file permission bits of the created fifos to the
+specified mode, ignoring the
+.Xr umask 2
+of the calling process.
+The
+.Ar mode
+argument takes any format that can be specified to the
+.Xr chmod 1
+command.
+If a symbolic mode is specified, the op symbols
+.Ql +
+(plus) and
+.Ql -
+(hyphen) are interpreted relative to an assumed initial mode of
+.Dq Li a=rw
+(read and write permissions for all).
+.El
+.Pp
+If the
+.Fl m
+option is not specified, fifos are created with mode
+.Li 0666
+modified by the
+.Xr umask 2
+of the calling process.
+The
+.Nm
+utility requires write permission in the parent directory.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr mkdir 1 ,
+.Xr rm 1 ,
+.Xr mkfifo 2 ,
+.Xr mknod 2 ,
+.Xr mknod 8
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compliant.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.bin/mkfifo/mkfifo.c b/usr.bin/mkfifo/mkfifo.c
new file mode 100644
index 000000000000..9fdc298f980d
--- /dev/null
+++ b/usr.bin/mkfifo/mkfifo.c
@@ -0,0 +1,98 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BASEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | \
+ S_IROTH | S_IWOTH
+
+static void usage(void) __dead2;
+
+static int f_mode;
+
+int
+main(int argc, char *argv[])
+{
+ const char *modestr = NULL;
+ const void *modep;
+ mode_t fifomode;
+ int ch, exitval;
+
+ while ((ch = getopt(argc, argv, "m:")) != -1)
+ switch(ch) {
+ case 'm':
+ f_mode = 1;
+ modestr = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (argv[0] == NULL)
+ usage();
+
+ if (f_mode) {
+ umask(0);
+ errno = 0;
+ if ((modep = setmode(modestr)) == NULL) {
+ if (errno)
+ err(1, "setmode");
+ errx(1, "invalid file mode: %s", modestr);
+ }
+ fifomode = getmode(modep, BASEMODE);
+ } else {
+ fifomode = BASEMODE;
+ }
+
+ for (exitval = 0; *argv != NULL; ++argv)
+ if (mkfifo(*argv, fifomode) < 0) {
+ warn("%s", *argv);
+ exitval = 1;
+ }
+ exit(exitval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: mkfifo [-m mode] fifo_name ...\n");
+ exit(1);
+}
diff --git a/usr.bin/mkimg/Makefile b/usr.bin/mkimg/Makefile
new file mode 100644
index 000000000000..9e39b7abc956
--- /dev/null
+++ b/usr.bin/mkimg/Makefile
@@ -0,0 +1,37 @@
+.include <src.opts.mk>
+
+PROG= mkimg
+SRCS+= format.c image.c mkimg.c scheme.c uuid.c
+MAN= mkimg.1
+
+MKIMG_VERSION=20161016
+mkimg.o: Makefile
+
+CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION}
+CFLAGS+=-DSPARSE_WRITE
+CFLAGS+=-I${SRCTOP}/sys/sys/disk
+
+# List of formats to support
+SRCS+= \
+ qcow.c \
+ raw.c \
+ vhd.c \
+ vhdx.c \
+ vmdk.c
+
+# List of schemes to support
+SRCS+= \
+ apm.c \
+ bsd.c \
+ ebr.c \
+ gpt.c \
+ mbr.c
+
+BINDIR?=/usr/bin
+
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkimg/Makefile.depend b/usr.bin/mkimg/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/mkimg/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkimg/Makefile.depend.host b/usr.bin/mkimg/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/mkimg/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkimg/Makefile.depend.options b/usr.bin/mkimg/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/mkimg/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/mkimg/apm.c b/usr.bin/mkimg/apm.c
new file mode 100644
index 000000000000..259a7533c27c
--- /dev/null
+++ b/usr.bin/mkimg/apm.c
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <apm.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static struct mkimg_alias apm_aliases[] = {
+ { ALIAS_FREEBSD, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD) },
+ { ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(APM_ENT_TYPE_APPLE_BOOT) },
+ { ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_NANDFS) },
+ { ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_SWAP) },
+ { ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_UFS) },
+ { ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_VINUM) },
+ { ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(APM_ENT_TYPE_FREEBSD_ZFS) },
+ { ALIAS_NONE, 0 }
+};
+
+static lba_t
+apm_metadata(u_int where, lba_t blk)
+{
+
+ blk += (where == SCHEME_META_IMG_START) ? nparts + 2 : 0;
+ return (round_block(blk));
+}
+
+static int
+apm_write(lba_t imgsz, void *bootcode __unused)
+{
+ u_char *buf;
+ struct apm_ddr *ddr;
+ struct apm_ent *ent;
+ struct part *part;
+ int error;
+
+ buf = calloc(nparts + 2, secsz);
+ if (buf == NULL)
+ return (ENOMEM);
+ ddr = (void *)buf;
+ be16enc(&ddr->ddr_sig, APM_DDR_SIG);
+ be16enc(&ddr->ddr_blksize, secsz);
+ be32enc(&ddr->ddr_blkcount, imgsz);
+
+ /* partition entry for the partition table itself. */
+ ent = (void *)(buf + secsz);
+ be16enc(&ent->ent_sig, APM_ENT_SIG);
+ be32enc(&ent->ent_pmblkcnt, nparts + 1);
+ be32enc(&ent->ent_start, 1);
+ be32enc(&ent->ent_size, nparts + 1);
+ strncpy(ent->ent_type, APM_ENT_TYPE_SELF, sizeof(ent->ent_type));
+ strncpy(ent->ent_name, "Apple", sizeof(ent->ent_name));
+
+ TAILQ_FOREACH(part, &partlist, link) {
+ ent = (void *)(buf + (part->index + 2) * secsz);
+ be16enc(&ent->ent_sig, APM_ENT_SIG);
+ be32enc(&ent->ent_pmblkcnt, nparts + 1);
+ be32enc(&ent->ent_start, part->block);
+ be32enc(&ent->ent_size, part->size);
+ strncpy(ent->ent_type, ALIAS_TYPE2PTR(part->type),
+ sizeof(ent->ent_type));
+ if (part->label != NULL)
+ strncpy(ent->ent_name, part->label,
+ sizeof(ent->ent_name));
+ }
+
+ error = image_write(0, buf, nparts + 2);
+ free(buf);
+ return (error);
+}
+
+static struct mkimg_scheme apm_scheme = {
+ .name = "apm",
+ .description = "Apple Partition Map",
+ .aliases = apm_aliases,
+ .metadata = apm_metadata,
+ .write = apm_write,
+ .nparts = 4096,
+ .labellen = APM_ENT_NAMELEN - 1,
+ .maxsecsz = 4096
+};
+
+SCHEME_DEFINE(apm_scheme);
diff --git a/usr.bin/mkimg/bsd.c b/usr.bin/mkimg/bsd.c
new file mode 100644
index 000000000000..17933c01ac07
--- /dev/null
+++ b/usr.bin/mkimg/bsd.c
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <bsd.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static struct mkimg_alias bsd_aliases[] = {
+ { ALIAS_FREEBSD_NANDFS, ALIAS_INT2TYPE(FS_NANDFS) },
+ { ALIAS_FREEBSD_SWAP, ALIAS_INT2TYPE(FS_SWAP) },
+ { ALIAS_FREEBSD_UFS, ALIAS_INT2TYPE(FS_BSDFFS) },
+ { ALIAS_FREEBSD_VINUM, ALIAS_INT2TYPE(FS_VINUM) },
+ { ALIAS_FREEBSD_ZFS, ALIAS_INT2TYPE(FS_ZFS) },
+ { ALIAS_NONE, 0 }
+};
+
+static lba_t
+bsd_metadata(u_int where, lba_t blk)
+{
+
+ if (where == SCHEME_META_IMG_START)
+ blk += BSD_BOOTBLOCK_SIZE / secsz;
+ else if (where == SCHEME_META_IMG_END)
+ blk = round_cylinder(blk);
+ else
+ blk = round_block(blk);
+ return (blk);
+}
+
+static int
+bsd_write(lba_t imgsz, void *bootcode)
+{
+ u_char *buf, *p;
+ struct disklabel *d;
+ struct partition *dp;
+ struct part *part;
+ int bsdparts, error, n;
+ uint16_t checksum;
+
+ buf = malloc(BSD_BOOTBLOCK_SIZE);
+ if (buf == NULL)
+ return (ENOMEM);
+ if (bootcode != NULL) {
+ memcpy(buf, bootcode, BSD_BOOTBLOCK_SIZE);
+ memset(buf + secsz, 0, sizeof(struct disklabel));
+ } else
+ memset(buf, 0, BSD_BOOTBLOCK_SIZE);
+
+ bsdparts = nparts + 1; /* Account for c partition */
+ if (bsdparts < BSD_NPARTS_MIN)
+ bsdparts = BSD_NPARTS_MIN;
+
+ d = (void *)(buf + secsz);
+ le32enc(&d->d_magic, BSD_MAGIC);
+ le32enc(&d->d_secsize, secsz);
+ le32enc(&d->d_nsectors, nsecs);
+ le32enc(&d->d_ntracks, nheads);
+ le32enc(&d->d_ncylinders, ncyls);
+ le32enc(&d->d_secpercyl, nsecs * nheads);
+ le32enc(&d->d_secperunit, imgsz);
+ le16enc(&d->d_rpm, 3600);
+ le32enc(&d->d_magic2, BSD_MAGIC);
+ le16enc(&d->d_npartitions, bsdparts);
+ le32enc(&d->d_bbsize, BSD_BOOTBLOCK_SIZE);
+
+ dp = &d->d_partitions[BSD_PART_RAW];
+ le32enc(&dp->p_size, imgsz);
+ TAILQ_FOREACH(part, &partlist, link) {
+ n = part->index + ((part->index >= BSD_PART_RAW) ? 1 : 0);
+ dp = &d->d_partitions[n];
+ le32enc(&dp->p_size, part->size);
+ le32enc(&dp->p_offset, part->block);
+ le32enc(&dp->p_fsize, 0);
+ dp->p_fstype = ALIAS_TYPE2INT(part->type);
+ dp->p_frag = 0;
+ le16enc(&dp->p_cpg, 0);
+ }
+
+ dp = &d->d_partitions[bsdparts];
+ checksum = 0;
+ for (p = (void *)d; p < (u_char *)dp; p += 2)
+ checksum ^= le16dec(p);
+ le16enc(&d->d_checksum, checksum);
+
+ error = image_write(0, buf, BSD_BOOTBLOCK_SIZE / secsz);
+ free(buf);
+ return (error);
+}
+
+static struct mkimg_scheme bsd_scheme = {
+ .name = "bsd",
+ .description = "BSD disk label",
+ .aliases = bsd_aliases,
+ .metadata = bsd_metadata,
+ .write = bsd_write,
+ .nparts = BSD_NPARTS_MAX - 1,
+ .bootcode = BSD_BOOTBLOCK_SIZE,
+ .maxsecsz = 512
+};
+
+SCHEME_DEFINE(bsd_scheme);
diff --git a/usr.bin/mkimg/ebr.c b/usr.bin/mkimg/ebr.c
new file mode 100644
index 000000000000..4d6adbb3b8ba
--- /dev/null
+++ b/usr.bin/mkimg/ebr.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbr.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static struct mkimg_alias ebr_aliases[] = {
+ { ALIAS_FAT16B, ALIAS_INT2TYPE(DOSPTYP_FAT16) },
+ { ALIAS_FAT32, ALIAS_INT2TYPE(DOSPTYP_FAT32) },
+ { ALIAS_FAT32LBA, ALIAS_INT2TYPE(DOSPTYP_FAT32LBA) },
+ { ALIAS_FREEBSD, ALIAS_INT2TYPE(DOSPTYP_386BSD) },
+ { ALIAS_NONE, 0 }
+};
+
+static lba_t
+ebr_metadata(u_int where, lba_t blk)
+{
+
+ blk += (where == SCHEME_META_PART_BEFORE) ? 1 : 0;
+ return (round_track(blk));
+}
+
+static void
+ebr_chs(u_char *cylp, u_char *hdp, u_char *secp, lba_t lba)
+{
+ u_int cyl, hd, sec;
+
+ mkimg_chs(lba, 1023, &cyl, &hd, &sec);
+ *cylp = cyl;
+ *hdp = hd;
+ *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
+}
+
+static int
+ebr_write(lba_t imgsz __unused, void *bootcode __unused)
+{
+ u_char *ebr;
+ struct dos_partition *dp;
+ struct part *part, *next;
+ lba_t block, size;
+ int error;
+
+ ebr = malloc(secsz);
+ if (ebr == NULL)
+ return (ENOMEM);
+ memset(ebr, 0, secsz);
+ le16enc(ebr + DOSMAGICOFFSET, DOSMAGIC);
+
+ error = 0;
+ TAILQ_FOREACH(part, &partlist, link) {
+ block = part->block - nsecs;
+ size = round_track(part->size);
+ dp = (void *)(ebr + DOSPARTOFF);
+ ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect, nsecs);
+ dp->dp_typ = ALIAS_TYPE2INT(part->type);
+ ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
+ part->block + size - 1);
+ le32enc(&dp->dp_start, nsecs);
+ le32enc(&dp->dp_size, size);
+
+ /* Add link entry */
+ next = TAILQ_NEXT(part, link);
+ if (next != NULL) {
+ size = round_track(next->size);
+ dp++;
+ ebr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
+ next->block - nsecs);
+ dp->dp_typ = DOSPTYP_EXT;
+ ebr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
+ next->block + size - 1);
+ le32enc(&dp->dp_start, next->block - nsecs);
+ le32enc(&dp->dp_size, size + nsecs);
+ }
+
+ error = image_write(block, ebr, 1);
+ if (error)
+ break;
+
+ memset(ebr + DOSPARTOFF, 0, 2 * DOSPARTSIZE);
+ }
+
+ free(ebr);
+ return (error);
+}
+
+static struct mkimg_scheme ebr_scheme = {
+ .name = "ebr",
+ .description = "Extended Boot Record",
+ .aliases = ebr_aliases,
+ .metadata = ebr_metadata,
+ .write = ebr_write,
+ .nparts = 4096,
+ .maxsecsz = 4096
+};
+
+SCHEME_DEFINE(ebr_scheme);
diff --git a/usr.bin/mkimg/endian.h b/usr.bin/mkimg/endian.h
new file mode 100644
index 000000000000..e9dc2b44b9b7
--- /dev/null
+++ b/usr.bin/mkimg/endian.h
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _MKIMG_ENDIAN_H_
+#define _MKIMG_ENDIAN_H_
+
+#include <stdint.h>
+
+static __inline uint16_t
+be16dec(const void *pp)
+{
+ uint8_t const *p = (uint8_t const *)pp;
+
+ return ((p[0] << 8) | p[1]);
+}
+
+static __inline void
+be16enc(void *pp, uint16_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ p[0] = (u >> 8) & 0xff;
+ p[1] = u & 0xff;
+}
+
+static __inline void
+be32enc(void *pp, uint32_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ p[0] = (u >> 24) & 0xff;
+ p[1] = (u >> 16) & 0xff;
+ p[2] = (u >> 8) & 0xff;
+ p[3] = u & 0xff;
+}
+
+static __inline void
+be64enc(void *pp, uint64_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ be32enc(p, (uint32_t)(u >> 32));
+ be32enc(p + 4, (uint32_t)(u & 0xffffffffU));
+}
+
+static __inline uint16_t
+le16dec(const void *pp)
+{
+ uint8_t const *p = (uint8_t const *)pp;
+
+ return ((p[1] << 8) | p[0]);
+}
+
+static __inline void
+le16enc(void *pp, uint16_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+}
+
+static __inline void
+le32enc(void *pp, uint32_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+ p[2] = (u >> 16) & 0xff;
+ p[3] = (u >> 24) & 0xff;
+}
+
+static __inline void
+le64enc(void *pp, uint64_t u)
+{
+ uint8_t *p = (uint8_t *)pp;
+
+ le32enc(p, (uint32_t)(u & 0xffffffffU));
+ le32enc(p + 4, (uint32_t)(u >> 32));
+}
+
+#endif /* _MKIMG_ENDIAN_H_ */
diff --git a/usr.bin/mkimg/format.c b/usr.bin/mkimg/format.c
new file mode 100644
index 000000000000..6730c22ca153
--- /dev/null
+++ b/usr.bin/mkimg/format.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+
+#include "image.h"
+#include "format.h"
+
+static struct mkimg_format *first;
+static struct mkimg_format *format;
+
+struct mkimg_format *
+format_iterate(struct mkimg_format *f)
+{
+
+ return ((f == NULL) ? first : f->next);
+}
+
+void
+format_register(struct mkimg_format *f)
+{
+
+ f->next = first;
+ first = f;
+}
+
+int
+format_resize(lba_t end)
+{
+
+ if (format == NULL)
+ return (ENOSYS);
+ return (format->resize(end));
+}
+
+int
+format_select(const char *spec)
+{
+ struct mkimg_format *f;
+
+ f = NULL;
+ while ((f = format_iterate(f)) != NULL) {
+ if (strcasecmp(spec, f->name) == 0) {
+ format = f;
+ return (0);
+ }
+ }
+ return (EINVAL);
+}
+
+struct mkimg_format *
+format_selected(void)
+{
+
+ return (format);
+}
+
+int
+format_write(int fd)
+{
+ int error;
+
+ if (format == NULL)
+ return (ENOSYS);
+ error = format->write(fd);
+ return (error);
+}
diff --git a/usr.bin/mkimg/format.h b/usr.bin/mkimg/format.h
new file mode 100644
index 000000000000..304af4586da8
--- /dev/null
+++ b/usr.bin/mkimg/format.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _MKIMG_FORMAT_H_
+#define _MKIMG_FORMAT_H_
+
+struct mkimg_format {
+ struct mkimg_format *next;
+ const char *name;
+ const char *description;
+ int (*resize)(lba_t);
+ int (*write)(int);
+};
+
+#define FORMAT_DEFINE(nm) \
+static void format_register_##nm(void) __attribute__((constructor)); \
+static void format_register_##nm(void) { format_register(&nm); }
+
+struct mkimg_format *format_iterate(struct mkimg_format *);
+void format_register(struct mkimg_format *);
+int format_select(const char *);
+struct mkimg_format *format_selected(void);
+
+int format_resize(lba_t);
+int format_write(int);
+
+#endif /* _MKIMG_FORMAT_H_ */
diff --git a/usr.bin/mkimg/gpt.c b/usr.bin/mkimg/gpt.c
new file mode 100644
index 000000000000..ed3f008c394f
--- /dev/null
+++ b/usr.bin/mkimg/gpt.c
@@ -0,0 +1,296 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gpt.h>
+#include <mbr.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static mkimg_uuid_t gpt_uuid_efi = GPT_ENT_TYPE_EFI;
+static mkimg_uuid_t gpt_uuid_freebsd = GPT_ENT_TYPE_FREEBSD;
+static mkimg_uuid_t gpt_uuid_freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
+static mkimg_uuid_t gpt_uuid_freebsd_nandfs = GPT_ENT_TYPE_FREEBSD_NANDFS;
+static mkimg_uuid_t gpt_uuid_freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
+static mkimg_uuid_t gpt_uuid_freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
+static mkimg_uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
+static mkimg_uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
+static mkimg_uuid_t gpt_uuid_mbr = GPT_ENT_TYPE_MBR;
+static mkimg_uuid_t gpt_uuid_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
+static mkimg_uuid_t gpt_uuid_prep_boot = GPT_ENT_TYPE_PREP_BOOT;
+
+static struct mkimg_alias gpt_aliases[] = {
+ { ALIAS_EFI, ALIAS_PTR2TYPE(&gpt_uuid_efi) },
+ { ALIAS_FREEBSD, ALIAS_PTR2TYPE(&gpt_uuid_freebsd) },
+ { ALIAS_FREEBSD_BOOT, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_boot) },
+ { ALIAS_FREEBSD_NANDFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_nandfs) },
+ { ALIAS_FREEBSD_SWAP, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_swap) },
+ { ALIAS_FREEBSD_UFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_ufs) },
+ { ALIAS_FREEBSD_VINUM, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_vinum) },
+ { ALIAS_FREEBSD_ZFS, ALIAS_PTR2TYPE(&gpt_uuid_freebsd_zfs) },
+ { ALIAS_MBR, ALIAS_PTR2TYPE(&gpt_uuid_mbr) },
+ { ALIAS_NTFS, ALIAS_PTR2TYPE(&gpt_uuid_ms_basic_data) },
+ { ALIAS_PPCBOOT, ALIAS_PTR2TYPE(&gpt_uuid_prep_boot) },
+ { ALIAS_NONE, 0 } /* Keep last! */
+};
+
+/* CRC32 code derived from work by Gary S. Brown. */
+static const uint32_t crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32_t
+crc32(const void *buf, size_t sz)
+{
+ const uint8_t *p = (const uint8_t *)buf;
+ uint32_t crc = ~0U;
+
+ while (sz--)
+ crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ return (crc ^ ~0U);
+}
+
+/*
+ * Return the number of sectors needed to store the partition table.
+ */
+static u_int
+gpt_tblsz(void)
+{
+ u_int eps; /* Entries per Sector */
+
+ /*
+ * Count the number of sectors needed for the GPT Entry Array to store
+ * the number of partitions defined for this image. Enforce the 16kB
+ * minimum space for the GPT Entry Array per UEFI v2.10 Section 5.3.
+ */
+ eps = secsz / sizeof(struct gpt_ent);
+ return (MAX(howmany(GPT_MIN_RESERVED, secsz), howmany(nparts, eps)));
+}
+
+static lba_t
+gpt_metadata(u_int where, lba_t blk)
+{
+
+ if (where == SCHEME_META_IMG_START || where == SCHEME_META_IMG_END) {
+ blk += gpt_tblsz();
+ blk += (where == SCHEME_META_IMG_START) ? 2 : 1;
+ }
+ return (round_block(blk));
+}
+
+static int
+gpt_write_pmbr(lba_t blks, void *bootcode)
+{
+ u_char *pmbr;
+ uint32_t secs;
+ int error;
+
+ secs = (blks > UINT32_MAX) ? UINT32_MAX : (uint32_t)blks - 1;
+
+ pmbr = malloc(secsz);
+ if (pmbr == NULL)
+ return (errno);
+ if (bootcode != NULL) {
+ memcpy(pmbr, bootcode, DOSPARTOFF);
+ memset(pmbr + DOSPARTOFF, 0, secsz - DOSPARTOFF);
+ } else
+ memset(pmbr, 0, secsz);
+ pmbr[DOSPARTOFF + 2] = 2;
+ pmbr[DOSPARTOFF + 4] = 0xee;
+ pmbr[DOSPARTOFF + 5] = 0xff;
+ pmbr[DOSPARTOFF + 6] = 0xff;
+ pmbr[DOSPARTOFF + 7] = 0xff;
+ le32enc(pmbr + DOSPARTOFF + 8, 1);
+ le32enc(pmbr + DOSPARTOFF + 12, secs);
+ le16enc(pmbr + DOSMAGICOFFSET, DOSMAGIC);
+ error = image_write(0, pmbr, 1);
+ free(pmbr);
+ return (error);
+}
+
+static struct gpt_ent *
+gpt_mktbl(u_int tblsz)
+{
+ mkimg_uuid_t uuid;
+ struct gpt_ent *tbl, *ent;
+ struct part *part;
+ int c, idx;
+
+ tbl = calloc(tblsz, secsz);
+ if (tbl == NULL)
+ return (NULL);
+
+ TAILQ_FOREACH(part, &partlist, link) {
+ ent = tbl + part->index;
+ mkimg_uuid_enc(&ent->ent_type, ALIAS_TYPE2PTR(part->type));
+ mkimg_uuid(&uuid);
+ mkimg_uuid_enc(&ent->ent_uuid, &uuid);
+ le64enc(&ent->ent_lba_start, part->block);
+ le64enc(&ent->ent_lba_end, part->block + part->size - 1);
+ if (part->label != NULL) {
+ idx = 0;
+ while ((c = part->label[idx]) != '\0') {
+ le16enc(ent->ent_name + idx, c);
+ idx++;
+ }
+ }
+ }
+ return (tbl);
+}
+
+static int
+gpt_write_hdr(struct gpt_hdr *hdr, uint64_t self, uint64_t alt, uint64_t tbl)
+{
+ uint32_t crc;
+
+ le64enc(&hdr->hdr_lba_self, self);
+ le64enc(&hdr->hdr_lba_alt, alt);
+ le64enc(&hdr->hdr_lba_table, tbl);
+ hdr->hdr_crc_self = 0;
+ crc = crc32(hdr, offsetof(struct gpt_hdr, padding));
+ le64enc(&hdr->hdr_crc_self, crc);
+ return (image_write(self, hdr, 1));
+}
+
+static int
+gpt_write(lba_t imgsz, void *bootcode)
+{
+ mkimg_uuid_t uuid;
+ struct gpt_ent *tbl;
+ struct gpt_hdr *hdr;
+ uint32_t crc;
+ u_int tblsz;
+ int error;
+
+ /* PMBR */
+ error = gpt_write_pmbr(imgsz, bootcode);
+ if (error)
+ return (error);
+
+ /* GPT table(s) */
+ tblsz = gpt_tblsz();
+ tbl = gpt_mktbl(tblsz);
+ if (tbl == NULL)
+ return (errno);
+ error = image_write(2, tbl, tblsz);
+ if (error)
+ goto out;
+ error = image_write(imgsz - (tblsz + 1), tbl, tblsz);
+ if (error)
+ goto out;
+
+ /* GPT header(s) */
+ hdr = malloc(secsz);
+ if (hdr == NULL) {
+ error = errno;
+ goto out;
+ }
+ memset(hdr, 0, secsz);
+ memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
+ le32enc(&hdr->hdr_revision, GPT_HDR_REVISION);
+ le32enc(&hdr->hdr_size, offsetof(struct gpt_hdr, padding));
+ le64enc(&hdr->hdr_lba_start, 2 + tblsz);
+ le64enc(&hdr->hdr_lba_end, imgsz - tblsz - 2);
+ mkimg_uuid(&uuid);
+ mkimg_uuid_enc(&hdr->hdr_uuid, &uuid);
+ le32enc(&hdr->hdr_entries, tblsz * secsz / sizeof(struct gpt_ent));
+ le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent));
+ crc = crc32(tbl, tblsz * secsz);
+ le32enc(&hdr->hdr_crc_table, crc);
+ error = gpt_write_hdr(hdr, 1, imgsz - 1, 2);
+ if (!error)
+ error = gpt_write_hdr(hdr, imgsz - 1, 1, imgsz - tblsz - 1);
+ free(hdr);
+
+ out:
+ free(tbl);
+ return (error);
+}
+
+static struct mkimg_scheme gpt_scheme = {
+ .name = "gpt",
+ .description = "GUID Partition Table",
+ .aliases = gpt_aliases,
+ .metadata = gpt_metadata,
+ .write = gpt_write,
+ .nparts = 4096,
+ .labellen = 36,
+ .bootcode = 512,
+ .maxsecsz = 4096
+};
+
+SCHEME_DEFINE(gpt_scheme);
diff --git a/usr.bin/mkimg/image.c b/usr.bin/mkimg/image.c
new file mode 100644
index 000000000000..07aaf1a6c0ea
--- /dev/null
+++ b/usr.bin/mkimg/image.c
@@ -0,0 +1,753 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "mkimg.h"
+
+#ifndef MAP_NOCORE
+#define MAP_NOCORE 0
+#endif
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC 0
+#endif
+
+#ifndef SEEK_DATA
+#define SEEK_DATA -1
+#endif
+#ifndef SEEK_HOLE
+#define SEEK_HOLE -1
+#endif
+
+struct chunk {
+ TAILQ_ENTRY(chunk) ch_list;
+ size_t ch_size; /* Size of chunk in bytes. */
+ lba_t ch_block; /* Block address in image. */
+ union {
+ struct {
+ off_t ofs; /* Offset in backing file. */
+ int fd; /* FD of backing file. */
+ } file;
+ struct {
+ void *ptr; /* Pointer to data in memory */
+ } mem;
+ } ch_u;
+ u_int ch_type;
+#define CH_TYPE_ZEROES 0 /* Chunk is a gap (no data). */
+#define CH_TYPE_FILE 1 /* File-backed chunk. */
+#define CH_TYPE_MEMORY 2 /* Memory-backed chunk */
+};
+
+static TAILQ_HEAD(chunk_head, chunk) image_chunks;
+static u_int image_nchunks;
+
+static char image_swap_file[PATH_MAX];
+static int image_swap_fd = -1;
+static u_int image_swap_pgsz;
+static off_t image_swap_size;
+
+static lba_t image_size;
+
+static int
+is_empty_sector(void *buf)
+{
+ uint64_t *p = buf;
+ size_t n, max;
+
+ assert(((uintptr_t)p & 3) == 0);
+
+ max = secsz / sizeof(uint64_t);
+ for (n = 0; n < max; n++) {
+ if (p[n] != 0UL)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Swap file handlng.
+ */
+
+static off_t
+image_swap_alloc(size_t size)
+{
+ off_t ofs;
+ size_t unit;
+
+ unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz;
+ assert((unit & (unit - 1)) == 0);
+
+ size = (size + unit - 1) & ~(unit - 1);
+
+ ofs = image_swap_size;
+ image_swap_size += size;
+ if (ftruncate(image_swap_fd, image_swap_size) == -1) {
+ image_swap_size = ofs;
+ ofs = -1LL;
+ }
+ return (ofs);
+}
+
+/*
+ * Image chunk handling.
+ */
+
+static struct chunk *
+image_chunk_find(lba_t blk)
+{
+ static struct chunk *last = NULL;
+ struct chunk *ch;
+
+ ch = (last != NULL && last->ch_block <= blk)
+ ? last : TAILQ_FIRST(&image_chunks);
+ while (ch != NULL) {
+ if (ch->ch_block <= blk &&
+ (lba_t)(ch->ch_block + (ch->ch_size / secsz)) > blk) {
+ last = ch;
+ break;
+ }
+ ch = TAILQ_NEXT(ch, ch_list);
+ }
+ return (ch);
+}
+
+static size_t
+image_chunk_grow(struct chunk *ch, size_t sz)
+{
+ size_t dsz, newsz;
+
+ newsz = ch->ch_size + sz;
+ if (newsz > ch->ch_size) {
+ ch->ch_size = newsz;
+ return (0);
+ }
+ /* We would overflow -- create new chunk for remainder. */
+ dsz = SIZE_MAX - ch->ch_size;
+ assert(dsz < sz);
+ ch->ch_size = SIZE_MAX;
+ return (sz - dsz);
+}
+
+static struct chunk *
+image_chunk_memory(struct chunk *ch, lba_t blk)
+{
+ struct chunk *new;
+ void *ptr;
+
+ ptr = calloc(1, secsz);
+ if (ptr == NULL)
+ return (NULL);
+
+ if (ch->ch_block < blk) {
+ new = malloc(sizeof(*new));
+ if (new == NULL) {
+ free(ptr);
+ return (NULL);
+ }
+ memcpy(new, ch, sizeof(*new));
+ ch->ch_size = (blk - ch->ch_block) * secsz;
+ new->ch_block = blk;
+ new->ch_size -= ch->ch_size;
+ TAILQ_INSERT_AFTER(&image_chunks, ch, new, ch_list);
+ image_nchunks++;
+ ch = new;
+ }
+
+ if (ch->ch_size > secsz) {
+ new = malloc(sizeof(*new));
+ if (new == NULL) {
+ free(ptr);
+ return (NULL);
+ }
+ memcpy(new, ch, sizeof(*new));
+ ch->ch_size = secsz;
+ new->ch_block++;
+ new->ch_size -= secsz;
+ TAILQ_INSERT_AFTER(&image_chunks, ch, new, ch_list);
+ image_nchunks++;
+ }
+
+ ch->ch_type = CH_TYPE_MEMORY;
+ ch->ch_u.mem.ptr = ptr;
+ return (ch);
+}
+
+static int
+image_chunk_skipto(lba_t to)
+{
+ struct chunk *ch;
+ lba_t from;
+ size_t sz;
+
+ ch = TAILQ_LAST(&image_chunks, chunk_head);
+ from = (ch != NULL) ? ch->ch_block + (ch->ch_size / secsz) : 0LL;
+
+ assert(from <= to);
+
+ /* Nothing to do? */
+ if (from == to)
+ return (0);
+ /* Avoid bugs due to overflows. */
+ if ((uintmax_t)(to - from) > (uintmax_t)(SIZE_MAX / secsz))
+ return (EFBIG);
+ sz = (to - from) * secsz;
+ if (ch != NULL && ch->ch_type == CH_TYPE_ZEROES) {
+ sz = image_chunk_grow(ch, sz);
+ if (sz == 0)
+ return (0);
+ from = ch->ch_block + (ch->ch_size / secsz);
+ }
+ ch = malloc(sizeof(*ch));
+ if (ch == NULL)
+ return (ENOMEM);
+ memset(ch, 0, sizeof(*ch));
+ ch->ch_block = from;
+ ch->ch_size = sz;
+ ch->ch_type = CH_TYPE_ZEROES;
+ TAILQ_INSERT_TAIL(&image_chunks, ch, ch_list);
+ image_nchunks++;
+ return (0);
+}
+
+static int
+image_chunk_append(lba_t blk, size_t sz, off_t ofs, int fd)
+{
+ struct chunk *ch;
+
+ ch = TAILQ_LAST(&image_chunks, chunk_head);
+ if (ch != NULL && ch->ch_type == CH_TYPE_FILE) {
+ if (fd == ch->ch_u.file.fd &&
+ blk == (lba_t)(ch->ch_block + (ch->ch_size / secsz)) &&
+ ofs == (off_t)(ch->ch_u.file.ofs + ch->ch_size)) {
+ sz = image_chunk_grow(ch, sz);
+ if (sz == 0)
+ return (0);
+ blk = ch->ch_block + (ch->ch_size / secsz);
+ ofs = ch->ch_u.file.ofs + ch->ch_size;
+ }
+ }
+ ch = malloc(sizeof(*ch));
+ if (ch == NULL)
+ return (ENOMEM);
+ memset(ch, 0, sizeof(*ch));
+ ch->ch_block = blk;
+ ch->ch_size = sz;
+ ch->ch_type = CH_TYPE_FILE;
+ ch->ch_u.file.ofs = ofs;
+ ch->ch_u.file.fd = fd;
+ TAILQ_INSERT_TAIL(&image_chunks, ch, ch_list);
+ image_nchunks++;
+ return (0);
+}
+
+static int
+image_chunk_copyin(lba_t blk, void *buf, size_t sz, off_t ofs, int fd)
+{
+ uint8_t *p = buf;
+ int error;
+
+ error = 0;
+ sz = (sz + secsz - 1) & ~(secsz - 1);
+ while (!error && sz > 0) {
+ if (is_empty_sector(p))
+ error = image_chunk_skipto(blk + 1);
+ else
+ error = image_chunk_append(blk, secsz, ofs, fd);
+ blk++;
+ p += secsz;
+ sz -= secsz;
+ ofs += secsz;
+ }
+ return (error);
+}
+
+/*
+ * File mapping support.
+ */
+
+static void *
+image_file_map(int fd, off_t ofs, size_t sz, off_t *iofp)
+{
+ void *ptr;
+ size_t unit;
+ int flags, prot;
+ off_t x;
+
+ /* On Linux anyway ofs must also be page aligned */
+ if ((x = (ofs % image_swap_pgsz)) != 0) {
+ ofs -= x;
+ sz += x;
+ *iofp = x;
+ } else
+ *iofp = 0;
+ unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz;
+ assert((unit & (unit - 1)) == 0);
+
+ flags = MAP_NOCORE | MAP_NOSYNC | MAP_SHARED;
+ /* Allow writing to our swap file only. */
+ prot = PROT_READ | ((fd == image_swap_fd) ? PROT_WRITE : 0);
+ sz = (sz + unit - 1) & ~(unit - 1);
+ ptr = mmap(NULL, sz, prot, flags, fd, ofs);
+ return ((ptr == MAP_FAILED) ? NULL : ptr);
+}
+
+static int
+image_file_unmap(void *buffer, size_t sz)
+{
+ size_t unit;
+
+ unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz;
+ sz = (sz + unit - 1) & ~(unit - 1);
+ if (madvise(buffer, sz, MADV_DONTNEED) != 0)
+ warn("madvise");
+ munmap(buffer, sz);
+ return (0);
+}
+
+/*
+ * Input/source file handling.
+ */
+
+static int
+image_copyin_stream(lba_t blk, int fd, uint64_t *sizep)
+{
+ char *buffer;
+ uint64_t bytesize;
+ off_t swofs;
+ size_t iosz;
+ ssize_t rdsz;
+ int error;
+ off_t iof;
+
+ /*
+ * This makes sure we're doing I/O in multiples of the page
+ * size as well as of the sector size. 2MB is the minimum
+ * by virtue of secsz at least 512 bytes and the page size
+ * at least 4K bytes.
+ */
+ iosz = secsz * image_swap_pgsz;
+
+ bytesize = 0;
+ do {
+ swofs = image_swap_alloc(iosz);
+ if (swofs == -1LL)
+ return (errno);
+ buffer = image_file_map(image_swap_fd, swofs, iosz, &iof);
+ if (buffer == NULL)
+ return (errno);
+ rdsz = read(fd, &buffer[iof], iosz);
+ if (rdsz > 0)
+ error = image_chunk_copyin(blk, &buffer[iof], rdsz, swofs,
+ image_swap_fd);
+ else if (rdsz < 0)
+ error = errno;
+ else
+ error = 0;
+ image_file_unmap(buffer, iosz);
+ /* XXX should we relinguish unused swap space? */
+ if (error)
+ return (error);
+
+ bytesize += rdsz;
+ blk += (rdsz + secsz - 1) / secsz;
+ } while (rdsz > 0);
+
+ if (sizep != NULL)
+ *sizep = bytesize;
+ return (0);
+}
+
+static int
+image_copyin_mapped(lba_t blk, int fd, uint64_t *sizep)
+{
+ off_t cur, data, end, hole, pos, iof;
+ void *mp;
+ char *buf;
+ uint64_t bytesize;
+ size_t iosz, sz;
+ int error;
+
+ /*
+ * We'd like to know the size of the file and we must
+ * be able to seek in order to mmap(2). If this isn't
+ * possible, then treat the file as a stream/pipe.
+ */
+ end = lseek(fd, 0L, SEEK_END);
+ if (end == -1L)
+ return (image_copyin_stream(blk, fd, sizep));
+
+ /*
+ * We need the file opened for the duration and our
+ * caller is going to close the file. Make a dup(2)
+ * so that control the faith of the descriptor.
+ */
+ fd = dup(fd);
+ if (fd == -1)
+ return (errno);
+
+ iosz = secsz * image_swap_pgsz;
+
+ bytesize = 0;
+ cur = pos = 0;
+ error = 0;
+ while (!error && cur < end) {
+ hole = lseek(fd, cur, SEEK_HOLE);
+ if (hole == -1)
+ hole = end;
+ data = lseek(fd, cur, SEEK_DATA);
+ if (data == -1)
+ data = end;
+
+ /*
+ * Treat the entire file as data if sparse files
+ * are not supported by the underlying file system.
+ */
+ if (hole == end && data == end)
+ data = cur;
+
+ if (cur == hole && data > hole) {
+ hole = pos;
+ pos = data & ~((uint64_t)secsz - 1);
+
+ blk += (pos - hole) / secsz;
+ error = image_chunk_skipto(blk);
+
+ bytesize += pos - hole;
+ cur = data;
+ } else if (cur == data && hole > data) {
+ data = pos;
+ pos = (hole + secsz - 1) & ~((uint64_t)secsz - 1);
+
+ while (data < pos) {
+ sz = (pos - data > (off_t)iosz)
+ ? iosz : (size_t)(pos - data);
+
+ buf = mp = image_file_map(fd, data, sz, &iof);
+ if (mp != NULL) {
+ buf += iof;
+ error = image_chunk_copyin(blk, buf,
+ sz, data, fd);
+ image_file_unmap(mp, sz);
+ } else
+ error = errno;
+
+ blk += sz / secsz;
+ bytesize += sz;
+ data += sz;
+ }
+ cur = hole;
+ } else {
+ /*
+ * I don't know what this means or whether it
+ * can happen at all...
+ */
+ assert(0);
+ }
+ }
+ if (error)
+ close(fd);
+ if (!error && sizep != NULL)
+ *sizep = bytesize;
+ return (error);
+}
+
+int
+image_copyin(lba_t blk, int fd, uint64_t *sizep)
+{
+ struct stat sb;
+ int error;
+
+ error = image_chunk_skipto(blk);
+ if (!error) {
+ if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode))
+ error = image_copyin_stream(blk, fd, sizep);
+ else
+ error = image_copyin_mapped(blk, fd, sizep);
+ }
+ return (error);
+}
+
+/*
+ * Output/sink file handling.
+ */
+
+int
+image_copyout(int fd)
+{
+ int error;
+
+ error = image_copyout_region(fd, 0, image_size);
+ if (!error)
+ error = image_copyout_done(fd);
+ return (error);
+}
+
+int
+image_copyout_done(int fd)
+{
+ off_t ofs;
+ int error;
+
+ ofs = lseek(fd, 0L, SEEK_CUR);
+ if (ofs == -1)
+ return (0);
+ error = (ftruncate(fd, ofs) == -1) ? errno : 0;
+ return (error);
+}
+
+static int
+image_copyout_memory(int fd, size_t size, void *ptr)
+{
+
+ if (write(fd, ptr, size) == -1)
+ return (errno);
+ return (0);
+}
+
+int
+image_copyout_zeroes(int fd, size_t count)
+{
+ static uint8_t *zeroes = NULL;
+ size_t sz;
+ int error;
+
+ if (lseek(fd, (off_t)count, SEEK_CUR) != -1)
+ return (0);
+
+ /*
+ * If we can't seek, we must write.
+ */
+
+ if (zeroes == NULL) {
+ zeroes = calloc(1, secsz);
+ if (zeroes == NULL)
+ return (ENOMEM);
+ }
+
+ while (count > 0) {
+ sz = (count > secsz) ? secsz : count;
+ error = image_copyout_memory(fd, sz, zeroes);
+ if (error)
+ return (error);
+ count -= sz;
+ }
+ return (0);
+}
+
+static int
+image_copyout_file(int fd, size_t size, int ifd, off_t iofs)
+{
+ void *mp;
+ char *buf;
+ size_t iosz, sz;
+ int error;
+ off_t iof;
+
+ iosz = secsz * image_swap_pgsz;
+
+ while (size > 0) {
+ sz = (size > iosz) ? iosz : size;
+ buf = mp = image_file_map(ifd, iofs, sz, &iof);
+ if (buf == NULL)
+ return (errno);
+ buf += iof;
+ error = image_copyout_memory(fd, sz, buf);
+ image_file_unmap(mp, sz);
+ if (error)
+ return (error);
+ size -= sz;
+ iofs += sz;
+ }
+ return (0);
+}
+
+int
+image_copyout_region(int fd, lba_t blk, lba_t size)
+{
+ struct chunk *ch;
+ size_t ofs, sz;
+ int error;
+
+ size *= secsz;
+
+ error = 0;
+ while (!error && size > 0) {
+ ch = image_chunk_find(blk);
+ if (ch == NULL) {
+ error = EINVAL;
+ break;
+ }
+ ofs = (blk - ch->ch_block) * secsz;
+ sz = ch->ch_size - ofs;
+ sz = ((lba_t)sz < size) ? sz : (size_t)size;
+ switch (ch->ch_type) {
+ case CH_TYPE_ZEROES:
+ error = image_copyout_zeroes(fd, sz);
+ break;
+ case CH_TYPE_FILE:
+ error = image_copyout_file(fd, sz, ch->ch_u.file.fd,
+ ch->ch_u.file.ofs + ofs);
+ break;
+ case CH_TYPE_MEMORY:
+ error = image_copyout_memory(fd, sz, ch->ch_u.mem.ptr);
+ break;
+ default:
+ assert(0);
+ }
+ size -= sz;
+ blk += sz / secsz;
+ }
+ return (error);
+}
+
+int
+image_data(lba_t blk, lba_t size)
+{
+ struct chunk *ch;
+ lba_t lim;
+
+ while (1) {
+ ch = image_chunk_find(blk);
+ if (ch == NULL)
+ return (0);
+ if (ch->ch_type != CH_TYPE_ZEROES)
+ return (1);
+ lim = ch->ch_block + (ch->ch_size / secsz);
+ if (lim >= blk + size)
+ return (0);
+ size -= lim - blk;
+ blk = lim;
+ }
+ /*NOTREACHED*/
+}
+
+lba_t
+image_get_size(void)
+{
+
+ return (image_size);
+}
+
+int
+image_set_size(lba_t blk)
+{
+ int error;
+
+ error = image_chunk_skipto(blk);
+ if (!error)
+ image_size = blk;
+ return (error);
+}
+
+int
+image_write(lba_t blk, void *buf, ssize_t len)
+{
+ struct chunk *ch;
+
+ while (len > 0) {
+ if (!is_empty_sector(buf)) {
+ ch = image_chunk_find(blk);
+ if (ch == NULL)
+ return (ENXIO);
+ /* We may not be able to write to files. */
+ if (ch->ch_type == CH_TYPE_FILE)
+ return (EINVAL);
+ if (ch->ch_type == CH_TYPE_ZEROES) {
+ ch = image_chunk_memory(ch, blk);
+ if (ch == NULL)
+ return (ENOMEM);
+ }
+ assert(ch->ch_type == CH_TYPE_MEMORY);
+ memcpy(ch->ch_u.mem.ptr, buf, secsz);
+ }
+ blk++;
+ buf = (char *)buf + secsz;
+ len--;
+ }
+ return (0);
+}
+
+static void
+image_cleanup(void)
+{
+ struct chunk *ch;
+
+ while ((ch = TAILQ_FIRST(&image_chunks)) != NULL) {
+ switch (ch->ch_type) {
+ case CH_TYPE_FILE:
+ /* We may be closing the same file multiple times. */
+ if (ch->ch_u.file.fd != -1)
+ close(ch->ch_u.file.fd);
+ break;
+ case CH_TYPE_MEMORY:
+ free(ch->ch_u.mem.ptr);
+ break;
+ default:
+ break;
+ }
+ TAILQ_REMOVE(&image_chunks, ch, ch_list);
+ free(ch);
+ }
+ if (image_swap_fd != -1)
+ close(image_swap_fd);
+ unlink(image_swap_file);
+}
+
+int
+image_init(void)
+{
+ const char *tmpdir;
+
+ TAILQ_INIT(&image_chunks);
+ image_nchunks = 0;
+
+ image_swap_size = 0;
+ image_swap_pgsz = getpagesize();
+
+ if (atexit(image_cleanup) == -1)
+ return (errno);
+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+ tmpdir = _PATH_TMP;
+ snprintf(image_swap_file, sizeof(image_swap_file), "%s/mkimg-XXXXXX",
+ tmpdir);
+ image_swap_fd = mkstemp(image_swap_file);
+ if (image_swap_fd == -1)
+ return (errno);
+ return (0);
+}
diff --git a/usr.bin/mkimg/image.h b/usr.bin/mkimg/image.h
new file mode 100644
index 000000000000..53dd3dc2df8a
--- /dev/null
+++ b/usr.bin/mkimg/image.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _MKIMG_IMAGE_H_
+#define _MKIMG_IMAGE_H_
+
+#include <stdint.h>
+
+typedef int64_t lba_t;
+
+int image_copyin(lba_t blk, int fd, uint64_t *sizep);
+int image_copyout(int fd);
+int image_copyout_done(int fd);
+int image_copyout_region(int fd, lba_t blk, lba_t size);
+int image_copyout_zeroes(int fd, size_t count);
+int image_data(lba_t blk, lba_t size);
+lba_t image_get_size(void);
+int image_init(void);
+int image_set_size(lba_t blk);
+int image_write(lba_t blk, void *buf, ssize_t len);
+
+#endif /* _MKIMG_IMAGE_H_ */
diff --git a/usr.bin/mkimg/mbr.c b/usr.bin/mkimg/mbr.c
new file mode 100644
index 000000000000..7bda01c72e6a
--- /dev/null
+++ b/usr.bin/mkimg/mbr.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbr.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static struct mkimg_alias mbr_aliases[] = {
+ { ALIAS_EBR, ALIAS_INT2TYPE(DOSPTYP_EXT) },
+ { ALIAS_EFI, ALIAS_INT2TYPE(DOSPTYP_EFI) },
+ { ALIAS_FAT16B, ALIAS_INT2TYPE(DOSPTYP_FAT16) },
+ { ALIAS_FAT32, ALIAS_INT2TYPE(DOSPTYP_FAT32) },
+ { ALIAS_FAT32LBA, ALIAS_INT2TYPE(DOSPTYP_FAT32LBA) },
+ { ALIAS_FREEBSD, ALIAS_INT2TYPE(DOSPTYP_386BSD) },
+ { ALIAS_NTFS, ALIAS_INT2TYPE(DOSPTYP_NTFS) },
+ { ALIAS_PPCBOOT, ALIAS_INT2TYPE(DOSPTYP_PPCBOOT) },
+ { ALIAS_NONE, 0 } /* Keep last! */
+};
+
+static lba_t
+mbr_metadata(u_int where, lba_t blk)
+{
+
+ blk += (where == SCHEME_META_IMG_START) ? 1 : 0;
+ return (round_track(blk));
+}
+
+static void
+mbr_chs(u_char *cylp, u_char *hdp, u_char *secp, lba_t lba)
+{
+ u_int cyl, hd, sec;
+
+ mkimg_chs(lba, 1023, &cyl, &hd, &sec);
+ *cylp = cyl;
+ *hdp = hd;
+ *secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
+}
+
+static int
+mbr_write(lba_t imgsz __unused, void *bootcode)
+{
+ u_char *mbr;
+ struct dos_partition *dpbase, *dp;
+ struct part *part;
+ lba_t size;
+ int error;
+
+ mbr = malloc(secsz);
+ if (mbr == NULL)
+ return (ENOMEM);
+ if (bootcode != NULL) {
+ memcpy(mbr, bootcode, DOSPARTOFF);
+ memset(mbr + DOSPARTOFF, 0, secsz - DOSPARTOFF);
+ } else
+ memset(mbr, 0, secsz);
+ le16enc(mbr + DOSMAGICOFFSET, DOSMAGIC);
+ dpbase = (void *)(mbr + DOSPARTOFF);
+ TAILQ_FOREACH(part, &partlist, link) {
+ size = round_track(part->size);
+ dp = dpbase + part->index;
+ if (active_partition != 0)
+ dp->dp_flag =
+ (part->index + 1 == active_partition) ? 0x80 : 0;
+ else
+ dp->dp_flag =
+ (part->index == 0 && bootcode != NULL) ? 0x80 : 0;
+ mbr_chs(&dp->dp_scyl, &dp->dp_shd, &dp->dp_ssect,
+ part->block);
+ dp->dp_typ = ALIAS_TYPE2INT(part->type);
+ mbr_chs(&dp->dp_ecyl, &dp->dp_ehd, &dp->dp_esect,
+ part->block + size - 1);
+ le32enc(&dp->dp_start, part->block);
+ le32enc(&dp->dp_size, size);
+ }
+ error = image_write(0, mbr, 1);
+ free(mbr);
+ return (error);
+}
+
+static struct mkimg_scheme mbr_scheme = {
+ .name = "mbr",
+ .description = "Master Boot Record",
+ .aliases = mbr_aliases,
+ .metadata = mbr_metadata,
+ .write = mbr_write,
+ .bootcode = 512,
+ .nparts = NDOSPART,
+ .maxsecsz = 4096
+};
+
+SCHEME_DEFINE(mbr_scheme);
diff --git a/usr.bin/mkimg/mkimg.1 b/usr.bin/mkimg/mkimg.1
new file mode 100644
index 000000000000..82bbee53a267
--- /dev/null
+++ b/usr.bin/mkimg/mkimg.1
@@ -0,0 +1,412 @@
+.\" Copyright (c) 2013, 2014 Juniper Networks, Inc.
+.\" 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.
+.\"
+.\" 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.
+.\"
+.Dd March 12, 2024
+.Dt MKIMG 1
+.Os
+.Sh NAME
+.Nm mkimg
+.Nd "utility to make disk images"
+.Sh SYNOPSIS
+.Nm
+.Op Fl H Ar heads
+.Op Fl P Ar blksz
+.Op Fl S Ar secsz
+.Op Fl T Ar tracksz
+.Op Fl b Ar bootcode
+.Op Fl c Ar min_capacity
+.Op Fl C Ar max_capacity
+.Op Fl -capacity Ar capacity
+.Op Fl f Ar format
+.Op Fl o Ar outfile
+.Op Fl a Ar active
+.Op Fl v
+.Op Fl y
+.Op Fl s Ar scheme Op Fl p Ar partition ...
+.Nm
+.Fl -formats | Fl -schemes | Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+utility creates a disk image from the raw partition contents specified with
+the
+.Ar partition
+argument(s) and using the partitioning scheme specified with the
+.Ar scheme
+argument.
+The disk image is written to
+.Ar stdout
+by default or the file specified with the
+.Ar outfile
+argument.
+The image file is a raw disk image by default, but the format of the
+image file can be specified with the
+.Ar format
+argument.
+Most formats require seekable output, except of raw disk image.
+.Pp
+The disk image can be made bootable by specifying the scheme-specific boot
+block contents with the
+.Ar bootcode
+argument and,
+depending on the scheme,
+with a boot partition.
+The contents of such a boot partition is provided like any other partition
+and the
+.Nm
+utility does not treat it any differently from other partitions.
+.Pp
+Some partitioning schemes need a disk geometry and for those the
+.Nm
+utility accepts the
+.Ar tracksz
+and
+.Ar heads
+arguments, specifying the number of sectors per track and the number of
+heads per cylinder (resp.)
+.Pp
+Both the logical and physical sector size can be specified and for that the
+.Nm
+utility
+accepts the
+.Ar secsz
+and
+.Ar blksz
+arguments.
+The
+.Ar secsz
+argument is used to specify the logical sector size.
+This is the sector size reported by a disk when queried for its capacity.
+Modern disks use a larger sector size internally,
+referred to as block size by the
+.Nm
+utility and this can be specified by the
+.Ar blksz
+argument.
+The
+.Nm
+utility will use the (physical) block size to determine the start of
+partitions and to round the size of the disk image.
+.Pp
+The
+.Fl c
+option can be used to specify a minimal capacity for the disk image.
+Use this option without the
+.Fl s
+and
+.Fl p
+options to create an empty disk image with the given (virtual) size.
+An empty partition table can be written to the disk when specifying a
+partitioning scheme with the
+.Fl s
+option, but without specifying any partitions.
+When the size required for all the partitions is larger than the
+given capacity, then the disk image will be larger than the capacity
+given.
+.Pp
+The
+.Fl C
+option specifies a maximum capacity for the disk image.
+If the combined sizes of the given partitions exceed the size given with
+.Fl C ,
+image creation fails.
+.Pp
+The
+.Fl -capacity
+option is a shorthand to specify the minimum and maximum capacity at the
+same time.
+.Pp
+The
+.Fl v
+option increases the level of output that the
+.Nm
+utility prints.
+.Pp
+The
+.Fl y
+option is used for testing purposes only and is not to be used in production.
+When present, the
+.Nm
+utility will generate predictable values for Universally Unique Identifiers
+(UUIDs) and time stamps so that consecutive runs of the
+.Nm
+utility will create images that are identical.
+.Pp
+The
+.Ar active
+option marks a partition as active, if the partitioning
+scheme supports it.
+Currently, only the
+.Ar mbr
+scheme supports this concept.
+By default,
+.Nm
+will only mark the first partition as active when boot code is
+specified.
+Use the
+.Ar active
+option to override the active partition.
+The number specified corresponds to the number after the 's' in the
+partition's
+.Xr geom 8
+name.
+No partitions are marked active when the value is 0.
+.Pp
+A set of long options exist to query about the
+.Nm
+utility itself.
+Options in this set should be given by themselves because the
+.Nm
+utility exits immediately after providing the requested information.
+The version of the
+.Nm
+utility is printed when the
+.Fl -version
+option is given.
+The list of supported output formats is printed when the
+.Fl -formats
+option is given and the list of supported partitioning schemes is printed
+when the
+.Fl -schemes
+option is given.
+Both the format and scheme lists a space-separated lists for easy handling
+in scripts.
+.Pp
+For a more descriptive list of supported partitioning schemes or supported
+output format, or for a detailed description of how to specify partitions,
+run the
+.Nm
+utility without any arguments.
+This will print a usage message with all the necessary details.
+.Sh DISK FORMATS
+The
+.Nm
+utility supports a number of output file formats.
+A short description of these is given below.
+.Ss QCOW and QCOW2
+QCOW stands for "QEMU Copy On Write".
+It's a sparse file format akin to VHD and VMDK and QCOW represents the
+first version.
+QCOW2 represents version 2 of the file format.
+Version 2 is not backward compatible with version 1 and adds support for
+snapshots among other things.
+The QCOW file formats are natively supported by QEMU and Xen.
+To write QCOW, specify
+.Fl f Ar qcow
+on the command line.
+To write version 2 QCOW, specify
+.Fl f Ar qcow2
+on the command line.
+The preferred file extension is ".qcow" and ".qcow2" for QCOW and QCOW2
+(resp.), but ".qcow" is sometimes used for version 2 files as well.
+.Ss RAW file format
+This file format is a sector by sector representation of an actual disk.
+There is no extra information that describes or relates to the format itself.
+The size of the file is the size of the (virtual) disk.
+This file format is suitable for being copied onto a disk with utilities
+like
+.Nm dd .
+To write a raw disk file, either omit the
+.Fl f
+option, or specify
+.Fl f Ar raw
+on the command line.
+The preferred file extension is one of ".img" or ".raw", but there's no
+real convention for it.
+.Ss Dynamic VHD and Fixed VHD
+Microsoft's "Virtual Hard Disk" file formats.
+The dynamic format is a sparse format akin to QCOW and VMDK.
+The fixed format is effectively a raw format with a footer appended to the
+file and as such it's often indistinguishable from the raw format.
+The fixed file format has been added to support Microsoft's Azure platform
+and due to inconsistencies in interpretation of the footer is not compatible
+with utilities like
+.Nm qemu
+when it is specifically instructed to interpreted the file as a VHD file.
+By default
+.Nm qemu
+will treat the file as a raw disk file, which mostly works fine.
+To have
+.Nm
+create a dynamic VHD file, specify
+.Fl f Ar vhd
+on the command line.
+To create a fixed VHD file for use by Azure, specify
+.Fl f Ar vhdf
+on the command line.
+The preferred file extension is ".vhd".
+.Ss Dynamic VHDX
+Microsoft's "Virtual Hard Disk v2" file formats, the
+successor to VHD.
+VHDX is the required format for the 2nd generation Hyper-V VMs.
+To have
+.Nm
+create a dynamic VHDX file, specify
+.Fl f Ar vhdx
+on the command line.
+The preferred file extension is ".vhdx".
+.Ss VMDK
+VMware's "Virtual Machine Disk" file format.
+It's a sparse file format akin to QCOW and VHD and supported by many
+virtualization solutions.
+To create a VMDK file, specify
+.Fl f Ar vmdk
+on the command line.
+The preferred file extension is ".vmdk".
+.Pp
+Not all virtualization solutions support all file formats, but often those
+virtualization environments have utilities to convert from one format to
+another.
+Note however that conversion may require that the virtual disk size is
+changed to match the constraints of the output format and this may invalidate
+the contents of the disk image.
+For example, the GUID Partition Table (GPT) scheme has a header in the last
+sector on the disk.
+When changing the disk size, the GPT must be changed so that the last header
+is moved accordingly.
+This is typically not part of the conversion process.
+If possible, use an output format specifically for the environment in which
+the file is intended to be used.
+.Sh PARTITION SPECIFICATION
+An option
+.Fl p
+may be used multiple times to specify a list of created partition entries.
+A specification that is a single dash indicates an unused partition entry.
+Otherwise, a partition specification has the following format:
+.Bd -literal -offset indent
+<type> ':' <kind> <contents>
+.Ed
+.Bl -tag -width indent
+.It Cm type
+the partition type alias (f.e.: freebsd-swap)
+that may be optionally followed by a '/' separator
+and a label for partitioning schemes that feature partition labels
+(see the
+.Sx EXAMPLES
+Section below)
+.It Cm kind
+the interpretation of the contents specification:
+.Bl -tag -width indent
+.It Cm ':'
+contents holds the size of an empty partition,
+a number that may be suffixed with one of K, M, G, T, P or E
+(either upper or lower case) following the SI power of two convention
+(see also
+.Xr expand_number 3 )
+.It Cm '='
+contents holds the name of a file to read
+.It Cm '-'
+contents holds a command to run; the output of which is the contents
+of the partition.
+Multi-word strings should be quoted according to the shell rules.
+.El
+.It Cm contents
+the specification of a partition's contents
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width "TMPDIR" -compact
+.It Ev TMPDIR
+Directory to put temporary files in; default is
+.Pa /tmp .
+.El
+.Sh EXAMPLES
+To create a bootable disk image that is partitioned using the GPT scheme and
+containing a root file system that was previously created using
+.Xr makefs 8
+and also containing a swap partition, run the
+.Nm
+utility as follows:
+.Dl % mkimg -s gpt -b /boot/pmbr -p freebsd-boot:=/boot/gptboot \
+-p freebsd-ufs:=root-file-system.ufs -p freebsd-swap::1G \
+-o gpt.img
+.Pp
+The command line given above results in a raw image file.
+This is because no output format was given.
+To create a VMDK image for example, add the
+.Fl f Ar vmdk
+argument to the
+.Nm
+utility and name the output file accordingly.
+.Pp
+A nested partitioning scheme is created by running the
+.Nm
+utility twice.
+The output of the first will be fed as the contents of a partition to the
+second.
+This can be done using a temporary file, like so:
+.Dl % mkimg -s bsd -b /boot/boot -p freebsd-ufs:=root-file-system.ufs \
+-p freebsd-swap::1G -o /tmp/bsd.img
+.Dl % mkimg -s mbr -b /boot/mbr -p freebsd:=/tmp/bsd.img -o mbr-bsd.img
+.Pp
+Alternatively, the
+.Nm
+utility can be run in a cascaded fashion, whereby the output of the
+first is fed directly into the second.
+To do this, run the
+.Nm
+utility as follows:
+.Dl % mkimg -s mbr -b /boot/mbr -p freebsd:-'mkimg -s bsd -b /boot/boot \
+-p freebsd-ufs:=root-file-system.ufs -p freebsd-swap::1G' -o mbr-bsd.img
+.Pp
+To accommodate the need to have partitions named or numbered in a certain
+way, the
+.Nm
+utility allows for the specification of empty partitions.
+For example, to create an image that is compatible with partition layouts
+found in
+.Pa /etc/disktab ,
+the 'd' partition often needs to be skipped.
+This is accomplished by inserting an unused partition after the first 2
+partition specifications.
+It is worth noting at this time that the BSD scheme will automatically
+skip the 'c' partition by virtue of it referring to the entire disk.
+To create an image that is compatible with the qp120at disk, use the
+.Nm
+utility as follows:
+.Dl % mkimg -s bsd -b /boot/boot -p freebsd-ufs:=root-file-system.ufs \
+-p freebsd-swap::20M -p- -p- -p- -p- -p freebsd-ufs:=usr-file-system.ufs \
+-o bsd.img
+.Pp
+For partitioning schemes that feature partition labels, the
+.Nm
+utility supports assigning labels to the partitions specified.
+In the following example the file system partition is labeled as 'backup':
+.Dl % mkimg -s gpt -p freebsd-ufs/backup:=file-system.ufs -o gpt.img
+.Sh SEE ALSO
+.Xr dd 1 ,
+.Xr expand_number 3 ,
+.Xr gpart 8 ,
+.Xr makefs 8 ,
+.Xr mdconfig 8 ,
+.Xr newfs 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 10.1 .
+.Sh AUTHORS
+The
+.Nm
+utility and manpage were written by
+.An Marcel Moolenaar Aq Mt marcel@FreeBSD.org .
diff --git a/usr.bin/mkimg/mkimg.c b/usr.bin/mkimg/mkimg.c
new file mode 100644
index 000000000000..3cd9b03c06e9
--- /dev/null
+++ b/usr.bin/mkimg/mkimg.c
@@ -0,0 +1,744 @@
+/*-
+ * Copyright (c) 2013,2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/stat.h>
+#include <errno.h>
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libutil.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+#define LONGOPT_FORMATS 0x01000001
+#define LONGOPT_SCHEMES 0x01000002
+#define LONGOPT_VERSION 0x01000003
+#define LONGOPT_CAPACITY 0x01000004
+
+static struct option longopts[] = {
+ { "formats", no_argument, NULL, LONGOPT_FORMATS },
+ { "schemes", no_argument, NULL, LONGOPT_SCHEMES },
+ { "version", no_argument, NULL, LONGOPT_VERSION },
+ { "capacity", required_argument, NULL, LONGOPT_CAPACITY },
+ { NULL, 0, NULL, 0 }
+};
+
+static uint64_t min_capacity = 0;
+static uint64_t max_capacity = 0;
+
+struct partlisthead partlist = TAILQ_HEAD_INITIALIZER(partlist);
+u_int nparts = 0;
+
+u_int unit_testing;
+u_int verbose;
+
+u_int ncyls = 0;
+u_int nheads = 1;
+u_int nsecs = 1;
+u_int secsz = 512;
+u_int blksz = 0;
+uint32_t active_partition = 0;
+
+static void
+print_formats(int usage)
+{
+ struct mkimg_format *f;
+ const char *sep;
+
+ if (usage) {
+ fprintf(stderr, " formats:\n");
+ f = NULL;
+ while ((f = format_iterate(f)) != NULL) {
+ fprintf(stderr, "\t%s\t- %s\n", f->name,
+ f->description);
+ }
+ } else {
+ sep = "";
+ f = NULL;
+ while ((f = format_iterate(f)) != NULL) {
+ printf("%s%s", sep, f->name);
+ sep = " ";
+ }
+ putchar('\n');
+ }
+}
+
+static void
+print_schemes(int usage)
+{
+ struct mkimg_scheme *s;
+ const char *sep;
+
+ if (usage) {
+ fprintf(stderr, " schemes:\n");
+ s = NULL;
+ while ((s = scheme_iterate(s)) != NULL) {
+ fprintf(stderr, "\t%s\t- %s\n", s->name,
+ s->description);
+ }
+ } else {
+ sep = "";
+ s = NULL;
+ while ((s = scheme_iterate(s)) != NULL) {
+ printf("%s%s", sep, s->name);
+ sep = " ";
+ }
+ putchar('\n');
+ }
+}
+
+static void
+print_version(void)
+{
+ u_int width;
+
+#ifdef __LP64__
+ width = 64;
+#else
+ width = 32;
+#endif
+ printf("mkimg %u (%u-bit)\n", MKIMG_VERSION, width);
+}
+
+static void
+usage(const char *why)
+{
+
+ warnx("error: %s", why);
+ fputc('\n', stderr);
+ fprintf(stderr, "usage: %s <options>\n", getprogname());
+
+ fprintf(stderr, " options:\n");
+ fprintf(stderr, "\t--formats\t- list image formats\n");
+ fprintf(stderr, "\t--schemes\t- list partition schemes\n");
+ fprintf(stderr, "\t--version\t- show version information\n");
+ fputc('\n', stderr);
+ fprintf(stderr, "\t-a <num>\t- mark num'th partition as active\n");
+ fprintf(stderr, "\t-b <file>\t- file containing boot code\n");
+ fprintf(stderr, "\t-c <num>\t- minimum capacity (in bytes) of the disk\n");
+ fprintf(stderr, "\t-C <num>\t- maximum capacity (in bytes) of the disk\n");
+ fprintf(stderr, "\t-f <format>\n");
+ fprintf(stderr, "\t-o <file>\t- file to write image into\n");
+ fprintf(stderr, "\t-p <partition>\n");
+ fprintf(stderr, "\t-s <scheme>\n");
+ fprintf(stderr, "\t-v\t\t- increase verbosity\n");
+ fprintf(stderr, "\t-y\t\t- [developers] enable unit test\n");
+ fprintf(stderr, "\t-H <num>\t- number of heads to simulate\n");
+ fprintf(stderr, "\t-P <num>\t- physical sector size\n");
+ fprintf(stderr, "\t-S <num>\t- logical sector size\n");
+ fprintf(stderr, "\t-T <num>\t- number of tracks to simulate\n");
+ fputc('\n', stderr);
+ print_formats(1);
+ fputc('\n', stderr);
+ print_schemes(1);
+ fputc('\n', stderr);
+ fprintf(stderr, " partition specification:\n");
+ fprintf(stderr, "\t<t>[/<l>]::<size>[:[+]<offset>]\t- "
+ "empty partition of given size and\n\t\t\t\t\t"
+ " optional relative or absolute offset\n");
+ fprintf(stderr, "\t<t>[/<l>]:=<file>[:[+]offset]\t- partition "
+ "content and size are\n\t\t\t\t\t"
+ " determined by the named file and\n"
+ "\t\t\t\t\t optional relative or absolute offset\n");
+ fprintf(stderr, "\t<t>[/<l>]:-<cmd>\t\t- partition content and size "
+ "are taken\n\t\t\t\t\t from the output of the command to run\n");
+ fprintf(stderr, "\t-\t\t\t\t- unused partition entry\n");
+ fprintf(stderr, "\t where:\n");
+ fprintf(stderr, "\t\t<t>\t- scheme neutral partition type\n");
+ fprintf(stderr, "\t\t<l>\t- optional scheme-dependent partition "
+ "label\n");
+
+ exit(EX_USAGE);
+}
+
+static int
+parse_uint32(uint32_t *valp, uint32_t min, uint32_t max, const char *arg)
+{
+ uint64_t val;
+
+ if (expand_number(arg, &val) == -1)
+ return (errno);
+ if (val > UINT_MAX || val < (uint64_t)min || val > (uint64_t)max)
+ return (EINVAL);
+ *valp = (uint32_t)val;
+ return (0);
+}
+
+static int
+parse_uint64(uint64_t *valp, uint64_t min, uint64_t max, const char *arg)
+{
+ uint64_t val;
+
+ if (expand_number(arg, &val) == -1)
+ return (errno);
+ if (val < min || val > max)
+ return (EINVAL);
+ *valp = val;
+ return (0);
+}
+
+static int
+pwr_of_two(u_int nr)
+{
+
+ return (((nr & (nr - 1)) == 0) ? 1 : 0);
+}
+
+/*
+ * A partition specification has the following format:
+ * <type> ':' <kind> <contents>
+ * where:
+ * type the partition type alias
+ * kind the interpretation of the contents specification
+ * ':' contents holds the size of an empty partition
+ * '=' contents holds the name of a file to read
+ * '-' contents holds a command to run; the output of
+ * which is the contents of the partition.
+ * contents the specification of a partition's contents
+ *
+ * A specification that is a single dash indicates an unused partition
+ * entry.
+ */
+static int
+parse_part(const char *spec)
+{
+ struct part *part;
+ char *sep;
+ size_t len;
+ int error;
+
+ if (strcmp(spec, "-") == 0) {
+ nparts++;
+ return (0);
+ }
+
+ part = calloc(1, sizeof(struct part));
+ if (part == NULL)
+ return (ENOMEM);
+
+ sep = strchr(spec, ':');
+ if (sep == NULL) {
+ error = EINVAL;
+ goto errout;
+ }
+ len = sep - spec + 1;
+ if (len < 2) {
+ error = EINVAL;
+ goto errout;
+ }
+ part->alias = malloc(len);
+ if (part->alias == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
+ strlcpy(part->alias, spec, len);
+ spec = sep + 1;
+
+ switch (*spec) {
+ case ':':
+ part->kind = PART_KIND_SIZE;
+ break;
+ case '=':
+ part->kind = PART_KIND_FILE;
+ break;
+ case '-':
+ part->kind = PART_KIND_PIPE;
+ break;
+ default:
+ error = EINVAL;
+ goto errout;
+ }
+ spec++;
+
+ part->contents = strdup(spec);
+ if (part->contents == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
+
+ spec = part->alias;
+ sep = strchr(spec, '/');
+ if (sep != NULL) {
+ *sep++ = '\0';
+ if (strlen(part->alias) == 0 || strlen(sep) == 0) {
+ error = EINVAL;
+ goto errout;
+ }
+ part->label = strdup(sep);
+ if (part->label == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
+ }
+
+ part->index = nparts;
+ TAILQ_INSERT_TAIL(&partlist, part, link);
+ nparts++;
+ return (0);
+
+ errout:
+ if (part->alias != NULL)
+ free(part->alias);
+ free(part);
+ return (error);
+}
+
+#if defined(SPARSE_WRITE)
+ssize_t
+sparse_write(int fd, const void *ptr, size_t sz)
+{
+ const char *buf, *p;
+ off_t ofs;
+ size_t len;
+ ssize_t wr, wrsz;
+
+ buf = ptr;
+ wrsz = 0;
+ p = memchr(buf, 0, sz);
+ while (sz > 0) {
+ len = (p != NULL) ? (size_t)(p - buf) : sz;
+ if (len > 0) {
+ len = (len + secsz - 1) & ~(secsz - 1);
+ if (len > sz)
+ len = sz;
+ wr = write(fd, buf, len);
+ if (wr < 0)
+ return (-1);
+ } else {
+ while (len < sz && *p++ == '\0')
+ len++;
+ if (len < sz)
+ len &= ~(secsz - 1);
+ if (len == 0)
+ continue;
+ ofs = lseek(fd, len, SEEK_CUR);
+ if (ofs < 0)
+ return (-1);
+ wr = len;
+ }
+ buf += wr;
+ sz -= wr;
+ wrsz += wr;
+ p = memchr(buf, 0, sz);
+ }
+ return (wrsz);
+}
+#endif /* SPARSE_WRITE */
+
+void
+mkimg_chs(lba_t lba, u_int maxcyl, u_int *cylp, u_int *hdp, u_int *secp)
+{
+ u_int hd, sec;
+
+ *cylp = *hdp = *secp = ~0U;
+ if (nsecs == 1 || nheads == 1)
+ return;
+
+ sec = lba % nsecs + 1;
+ lba /= nsecs;
+ hd = lba % nheads;
+ lba /= nheads;
+ if (lba > maxcyl)
+ return;
+
+ *cylp = lba;
+ *hdp = hd;
+ *secp = sec;
+}
+
+static int
+capacity_resize(lba_t end)
+{
+ lba_t min_capsz, max_capsz;
+
+ min_capsz = (min_capacity + secsz - 1) / secsz;
+ max_capsz = (max_capacity + secsz - 1) / secsz;
+
+ if (max_capsz != 0 && end > max_capsz)
+ return (ENOSPC);
+ if (end >= min_capsz)
+ return (0);
+
+ return (image_set_size(min_capsz));
+}
+
+static void
+mkimg_validate(void)
+{
+ struct part *part, *part2;
+ lba_t start, end, start2, end2;
+ int i, j;
+
+ i = 0;
+
+ TAILQ_FOREACH(part, &partlist, link) {
+ start = part->block;
+ end = part->block + part->size;
+ j = i + 1;
+ part2 = TAILQ_NEXT(part, link);
+ if (part2 == NULL)
+ break;
+
+ TAILQ_FOREACH_FROM(part2, &partlist, link) {
+ start2 = part2->block;
+ end2 = part2->block + part2->size;
+
+ if ((start >= start2 && start < end2) ||
+ (end > start2 && end <= end2)) {
+ errx(1, "partition %d overlaps partition %d",
+ i, j);
+ }
+
+ j++;
+ }
+
+ i++;
+ }
+}
+
+static void
+mkimg(void)
+{
+ FILE *fp;
+ struct part *part;
+ lba_t block, blkoffset;
+ uint64_t bytesize, byteoffset;
+ char *size, *offset;
+ bool abs_offset;
+ int error, fd;
+
+ /* First check partition information */
+ TAILQ_FOREACH(part, &partlist, link) {
+ error = scheme_check_part(part);
+ if (error)
+ errc(EX_DATAERR, error, "partition %d", part->index+1);
+ }
+
+ block = scheme_metadata(SCHEME_META_IMG_START, 0);
+ abs_offset = false;
+ TAILQ_FOREACH(part, &partlist, link) {
+ byteoffset = blkoffset = 0;
+ abs_offset = false;
+
+ /* Look for an offset. Set size too if we can. */
+ switch (part->kind) {
+ case PART_KIND_SIZE:
+ case PART_KIND_FILE:
+ offset = part->contents;
+ size = strsep(&offset, ":");
+ if (part->kind == PART_KIND_SIZE &&
+ expand_number(size, &bytesize) == -1)
+ error = errno;
+ if (offset != NULL) {
+ if (*offset != '+')
+ abs_offset = true;
+ else
+ offset++;
+ if (expand_number(offset, &byteoffset) == -1)
+ error = errno;
+ }
+ break;
+ }
+
+ /* Work out exactly where the partition starts. */
+ blkoffset = (byteoffset + secsz - 1) / secsz;
+ if (abs_offset)
+ block = scheme_metadata(SCHEME_META_PART_ABSOLUTE,
+ blkoffset);
+ else
+ block = scheme_metadata(SCHEME_META_PART_BEFORE,
+ block + blkoffset);
+ part->block = block;
+
+ if (verbose)
+ fprintf(stderr, "partition %d: starting block %llu "
+ "... ", part->index + 1, (long long)part->block);
+
+ /* Pull in partition contents, set size if we haven't yet. */
+ switch (part->kind) {
+ case PART_KIND_FILE:
+ fd = open(part->contents, O_RDONLY, 0);
+ if (fd != -1) {
+ error = image_copyin(block, fd, &bytesize);
+ close(fd);
+ } else
+ error = errno;
+ break;
+ case PART_KIND_PIPE:
+ fp = popen(part->contents, "r");
+ if (fp != NULL) {
+ fd = fileno(fp);
+ error = image_copyin(block, fd, &bytesize);
+ pclose(fp);
+ } else
+ error = errno;
+ break;
+ }
+ if (error)
+ errc(EX_IOERR, error, "partition %d", part->index + 1);
+ part->size = (bytesize + secsz - 1) / secsz;
+ if (verbose) {
+ bytesize = part->size * secsz;
+ fprintf(stderr, "size %llu bytes (%llu blocks)\n",
+ (long long)bytesize, (long long)part->size);
+ if (abs_offset) {
+ fprintf(stderr,
+ " location %llu bytes (%llu blocks)\n",
+ (long long)byteoffset,
+ (long long)blkoffset);
+ } else if (blkoffset > 0) {
+ fprintf(stderr,
+ " offset %llu bytes (%llu blocks)\n",
+ (long long)byteoffset,
+ (long long)blkoffset);
+ }
+ }
+ block = scheme_metadata(SCHEME_META_PART_AFTER,
+ part->block + part->size);
+ }
+
+ mkimg_validate();
+
+ block = scheme_metadata(SCHEME_META_IMG_END, block);
+ error = image_set_size(block);
+ if (!error) {
+ error = capacity_resize(block);
+ block = image_get_size();
+ }
+ if (!error) {
+ error = format_resize(block);
+ block = image_get_size();
+ }
+ if (error)
+ errc(EX_IOERR, error, "image sizing");
+ ncyls = block / (nsecs * nheads);
+ error = scheme_write(block);
+ if (error)
+ errc(EX_IOERR, error, "writing metadata");
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *format_name;
+ int bcfd, outfd;
+ int c, error;
+
+ bcfd = -1;
+ outfd = 1; /* Write to stdout by default */
+ while ((c = getopt_long(argc, argv, "a:b:c:C:f:o:p:s:vyH:P:S:T:",
+ longopts, NULL)) != -1) {
+ switch (c) {
+ case 'a': /* ACTIVE PARTITION, if supported */
+ error = parse_uint32(&active_partition, 1, 100, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "Partition ordinal");
+ break;
+ case 'b': /* BOOT CODE */
+ if (bcfd != -1)
+ usage("multiple bootcode given");
+ bcfd = open(optarg, O_RDONLY, 0);
+ if (bcfd == -1)
+ err(EX_UNAVAILABLE, "%s", optarg);
+ break;
+ case 'c': /* MINIMUM CAPACITY */
+ error = parse_uint64(&min_capacity, 1, INT64_MAX, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "minimum capacity in bytes");
+ break;
+ case 'C': /* MAXIMUM CAPACITY */
+ error = parse_uint64(&max_capacity, 1, INT64_MAX, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "maximum capacity in bytes");
+ break;
+ case 'f': /* OUTPUT FORMAT */
+ if (format_selected() != NULL)
+ usage("multiple formats given");
+ error = format_select(optarg);
+ if (error)
+ errc(EX_DATAERR, error, "format");
+ break;
+ case 'o': /* OUTPUT FILE */
+ if (outfd != 1)
+ usage("multiple output files given");
+ outfd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ if (outfd == -1)
+ err(EX_CANTCREAT, "%s", optarg);
+ break;
+ case 'p': /* PARTITION */
+ error = parse_part(optarg);
+ if (error)
+ errc(EX_DATAERR, error, "partition");
+ break;
+ case 's': /* SCHEME */
+ if (scheme_selected() != NULL)
+ usage("multiple schemes given");
+ error = scheme_select(optarg);
+ if (error)
+ errc(EX_DATAERR, error, "scheme");
+ break;
+ case 'y':
+ unit_testing++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'H': /* GEOMETRY: HEADS */
+ error = parse_uint32(&nheads, 1, 255, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "number of heads");
+ break;
+ case 'P': /* GEOMETRY: PHYSICAL SECTOR SIZE */
+ error = parse_uint32(&blksz, 512, INT_MAX+1U, optarg);
+ if (error == 0 && !pwr_of_two(blksz))
+ error = EINVAL;
+ if (error)
+ errc(EX_DATAERR, error, "physical sector size");
+ break;
+ case 'S': /* GEOMETRY: LOGICAL SECTOR SIZE */
+ error = parse_uint32(&secsz, 512, INT_MAX+1U, optarg);
+ if (error == 0 && !pwr_of_two(secsz))
+ error = EINVAL;
+ if (error)
+ errc(EX_DATAERR, error, "logical sector size");
+ break;
+ case 'T': /* GEOMETRY: TRACK SIZE */
+ error = parse_uint32(&nsecs, 1, 63, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "track size");
+ break;
+ case LONGOPT_FORMATS:
+ print_formats(0);
+ exit(EX_OK);
+ /*NOTREACHED*/
+ case LONGOPT_SCHEMES:
+ print_schemes(0);
+ exit(EX_OK);
+ /*NOTREACHED*/
+ case LONGOPT_VERSION:
+ print_version();
+ exit(EX_OK);
+ /*NOTREACHED*/
+ case LONGOPT_CAPACITY:
+ error = parse_uint64(&min_capacity, 1, INT64_MAX, optarg);
+ if (error)
+ errc(EX_DATAERR, error, "capacity in bytes");
+ max_capacity = min_capacity;
+ break;
+ default:
+ usage("unknown option");
+ }
+ }
+
+ if (argc > optind)
+ usage("trailing arguments");
+ if (scheme_selected() == NULL && nparts > 0)
+ usage("no scheme");
+ if (nparts == 0 && min_capacity == 0)
+ usage("no partitions");
+ if (max_capacity != 0 && min_capacity > max_capacity)
+ usage("minimum capacity cannot be larger than the maximum one");
+
+ if (secsz > blksz) {
+ if (blksz != 0)
+ errx(EX_DATAERR, "the physical block size cannot "
+ "be smaller than the sector size");
+ blksz = secsz;
+ }
+
+ if (secsz > scheme_max_secsz())
+ errx(EX_DATAERR, "maximum sector size supported is %u; "
+ "size specified is %u", scheme_max_secsz(), secsz);
+
+ if (nparts > scheme_max_parts())
+ errx(EX_DATAERR, "%d partitions supported; %d given",
+ scheme_max_parts(), nparts);
+
+ if (format_selected() == NULL)
+ format_select("raw");
+
+ if (bcfd != -1) {
+ error = scheme_bootcode(bcfd);
+ close(bcfd);
+ if (error)
+ errc(EX_DATAERR, error, "boot code");
+ }
+
+ format_name = format_selected()->name;
+ if (verbose) {
+ fprintf(stderr, "Logical sector size: %u\n", secsz);
+ fprintf(stderr, "Physical block size: %u\n", blksz);
+ fprintf(stderr, "Sectors per track: %u\n", nsecs);
+ fprintf(stderr, "Number of heads: %u\n", nheads);
+ fputc('\n', stderr);
+ if (scheme_selected())
+ fprintf(stderr, "Partitioning scheme: %s\n",
+ scheme_selected()->name);
+ fprintf(stderr, "Output file format: %s\n",
+ format_name);
+ fputc('\n', stderr);
+ }
+
+#if defined(SPARSE_WRITE)
+ /*
+ * sparse_write() fails if output is not seekable so fail early
+ * not wasting some load unless output format is raw
+ */
+ if (strcmp("raw", format_name) &&
+ lseek(outfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
+ errx(EX_USAGE, "%s: output must be seekable", format_name);
+#endif
+
+ error = image_init();
+ if (error)
+ errc(EX_OSERR, error, "cannot initialize");
+
+ mkimg();
+
+ if (verbose) {
+ fputc('\n', stderr);
+ fprintf(stderr, "Number of cylinders: %u\n", ncyls);
+ }
+
+ error = format_write(outfd);
+ if (error)
+ errc(EX_IOERR, error, "writing image");
+
+ return (0);
+}
diff --git a/usr.bin/mkimg/mkimg.h b/usr.bin/mkimg/mkimg.h
new file mode 100644
index 000000000000..e85f77de0ec7
--- /dev/null
+++ b/usr.bin/mkimg/mkimg.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _MKIMG_MKIMG_H_
+#define _MKIMG_MKIMG_H_
+
+#include <sys/queue.h>
+#include <sys/types.h>
+
+struct part {
+ TAILQ_ENTRY(part) link;
+ char *alias; /* Partition type alias. */
+ char *contents; /* Contents/size specification. */
+ u_int kind; /* Content kind. */
+#define PART_UNDEF 0
+#define PART_KIND_FILE 1
+#define PART_KIND_PIPE 2
+#define PART_KIND_SIZE 3
+ u_int index; /* Partition index (0-based). */
+ uintptr_t type; /* Scheme-specific partition type. */
+ lba_t block; /* Block-offset of partition in image. */
+ lba_t size; /* Size in blocks of partition. */
+ char *label; /* Partition label. */
+};
+
+extern TAILQ_HEAD(partlisthead, part) partlist;
+extern u_int nparts;
+
+extern u_int unit_testing;
+extern u_int verbose;
+
+extern u_int ncyls;
+extern u_int nheads;
+extern u_int nsecs;
+extern u_int secsz; /* Logical block size. */
+extern u_int blksz; /* Physical block size. */
+extern uint32_t active_partition;
+
+static inline lba_t
+round_block(lba_t n)
+{
+ lba_t b = blksz / secsz;
+ return ((n + b - 1) & ~(b - 1));
+}
+
+static inline lba_t
+round_cylinder(lba_t n)
+{
+ u_int cyl = nsecs * nheads;
+ u_int r = n % cyl;
+ return ((r == 0) ? n : n + cyl - r);
+}
+
+static inline lba_t
+round_track(lba_t n)
+{
+ u_int r = n % nsecs;
+ return ((r == 0) ? n : n + nsecs - r);
+}
+
+#if !defined(SPARSE_WRITE)
+#define sparse_write write
+#else
+ssize_t sparse_write(int, const void *, size_t);
+#endif
+
+void mkimg_chs(lba_t, u_int, u_int *, u_int *, u_int *);
+
+struct mkimg_uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+};
+typedef struct mkimg_uuid mkimg_uuid_t;
+
+void mkimg_uuid(mkimg_uuid_t *);
+void mkimg_uuid_enc(void *, const mkimg_uuid_t *);
+
+#ifdef __linux__
+# if !defined(__unused)
+# define __unused __attribute__ ((__unused__))
+# endif
+#endif
+
+#endif /* _MKIMG_MKIMG_H_ */
diff --git a/usr.bin/mkimg/qcow.c b/usr.bin/mkimg/qcow.c
new file mode 100644
index 000000000000..2dc3e5498420
--- /dev/null
+++ b/usr.bin/mkimg/qcow.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "endian.h"
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+/* Default cluster sizes. */
+#define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */
+#define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */
+
+/* Flag bits in cluster offsets */
+#define QCOW_CLSTR_COMPRESSED (1ULL << 62)
+#define QCOW_CLSTR_COPIED (1ULL << 63)
+
+struct qcow_header {
+ uint32_t magic;
+#define QCOW_MAGIC 0x514649fb
+ uint32_t version;
+#define QCOW_VERSION_1 1
+#define QCOW_VERSION_2 2
+ uint64_t path_offset;
+ uint32_t path_length;
+ uint32_t clstr_log2sz; /* v2 only */
+ uint64_t disk_size;
+ union {
+ struct {
+ uint8_t clstr_log2sz;
+ uint8_t l2_log2sz;
+ uint16_t _pad;
+ uint32_t encryption;
+ uint64_t l1_offset;
+ } v1;
+ struct {
+ uint32_t encryption;
+ uint32_t l1_entries;
+ uint64_t l1_offset;
+ uint64_t refcnt_offset;
+ uint32_t refcnt_clstrs;
+ uint32_t snapshot_count;
+ uint64_t snapshot_offset;
+ } v2;
+ } u;
+};
+
+static u_int clstr_log2sz;
+
+static uint64_t
+round_clstr(uint64_t ofs)
+{
+ uint64_t clstrsz;
+
+ clstrsz = 1UL << clstr_log2sz;
+ return ((ofs + clstrsz - 1) & ~(clstrsz - 1));
+}
+
+static int
+qcow_resize(lba_t imgsz, u_int version)
+{
+ uint64_t imagesz;
+
+ switch (version) {
+ case QCOW_VERSION_1:
+ clstr_log2sz = QCOW1_CLSTR_LOG2SZ;
+ break;
+ case QCOW_VERSION_2:
+ clstr_log2sz = QCOW2_CLSTR_LOG2SZ;
+ break;
+ default:
+ assert(0);
+ }
+
+ imagesz = round_clstr(imgsz * secsz);
+
+ if (verbose)
+ fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n",
+ (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz));
+
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+qcow1_resize(lba_t imgsz)
+{
+
+ return (qcow_resize(imgsz, QCOW_VERSION_1));
+}
+
+static int
+qcow2_resize(lba_t imgsz)
+{
+
+ return (qcow_resize(imgsz, QCOW_VERSION_2));
+}
+
+static int
+qcow_write(int fd, u_int version)
+{
+ struct qcow_header *hdr;
+ uint64_t *l1tbl, *l2tbl, *rctbl;
+ uint16_t *rcblk;
+ uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz;
+ uint64_t clstr_rcblks, clstr_rctblsz;
+ uint64_t n, imagesz, nclstrs, ofs, ofsflags;
+ lba_t blk, blkofs, blk_imgsz;
+ u_int l1clno, l2clno, rcclno;
+ u_int blk_clstrsz, refcnt_clstrs;
+ u_int clstrsz, l1idx, l2idx;
+ int error;
+
+ assert(clstr_log2sz != 0);
+
+ clstrsz = 1U << clstr_log2sz;
+ blk_clstrsz = clstrsz / secsz;
+ blk_imgsz = image_get_size();
+ imagesz = blk_imgsz * secsz;
+ clstr_imgsz = imagesz >> clstr_log2sz;
+ clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz;
+ clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz;
+ nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1;
+ clstr_rcblks = clstr_rctblsz = 0;
+ do {
+ n = clstr_rcblks + clstr_rctblsz;
+ clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
+ clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
+ } while (n < (clstr_rcblks + clstr_rctblsz));
+
+ /*
+ * We got all the sizes in clusters. Start the layout.
+ * 0 - header
+ * 1 - L1 table
+ * 2 - RC table (v2 only)
+ * 3 - L2 tables
+ * 4 - RC block (v2 only)
+ * 5 - data
+ */
+
+ l1clno = 1;
+ rcclno = 0;
+ rctbl = l2tbl = l1tbl = NULL;
+ rcblk = NULL;
+
+ hdr = calloc(1, clstrsz);
+ if (hdr == NULL)
+ return (errno);
+
+ be32enc(&hdr->magic, QCOW_MAGIC);
+ be32enc(&hdr->version, version);
+ be64enc(&hdr->disk_size, imagesz);
+ switch (version) {
+ case QCOW_VERSION_1:
+ ofsflags = 0;
+ l2clno = l1clno + clstr_l1tblsz;
+ hdr->u.v1.clstr_log2sz = clstr_log2sz;
+ hdr->u.v1.l2_log2sz = clstr_log2sz - 3;
+ be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno);
+ break;
+ case QCOW_VERSION_2:
+ ofsflags = QCOW_CLSTR_COPIED;
+ rcclno = l1clno + clstr_l1tblsz;
+ l2clno = rcclno + clstr_rctblsz;
+ be32enc(&hdr->clstr_log2sz, clstr_log2sz);
+ be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls);
+ be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno);
+ be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno);
+ refcnt_clstrs = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
+ be32enc(&hdr->u.v2.refcnt_clstrs, refcnt_clstrs);
+ break;
+ default:
+ assert(0);
+ }
+
+ if (sparse_write(fd, hdr, clstrsz) < 0) {
+ error = errno;
+ goto out;
+ }
+
+ free(hdr);
+ hdr = NULL;
+
+ ofs = clstrsz * l2clno;
+ nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz;
+
+ l1tbl = calloc(clstr_l1tblsz, clstrsz);
+ if (l1tbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ for (n = 0; n < clstr_imgsz; n++) {
+ blk = n * blk_clstrsz;
+ if (image_data(blk, blk_clstrsz)) {
+ nclstrs++;
+ l1idx = n >> (clstr_log2sz - 3);
+ if (l1tbl[l1idx] == 0) {
+ be64enc(l1tbl + l1idx, ofs + ofsflags);
+ ofs += clstrsz;
+ nclstrs++;
+ }
+ }
+ }
+
+ if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) {
+ error = errno;
+ goto out;
+ }
+
+ clstr_rcblks = 0;
+ do {
+ n = clstr_rcblks;
+ clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
+ } while (n < clstr_rcblks);
+
+ if (rcclno > 0) {
+ rctbl = calloc(clstr_rctblsz, clstrsz);
+ if (rctbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ for (n = 0; n < clstr_rcblks; n++) {
+ be64enc(rctbl + n, ofs);
+ ofs += clstrsz;
+ nclstrs++;
+ }
+ if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) {
+ error = errno;
+ goto out;
+ }
+ free(rctbl);
+ rctbl = NULL;
+ }
+
+ l2tbl = malloc(clstrsz);
+ if (l2tbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) {
+ if (l1tbl[l1idx] == 0)
+ continue;
+ memset(l2tbl, 0, clstrsz);
+ blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3);
+ for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) {
+ blk = blkofs + (lba_t)l2idx * blk_clstrsz;
+ if (blk >= blk_imgsz)
+ break;
+ if (image_data(blk, blk_clstrsz)) {
+ be64enc(l2tbl + l2idx, ofs + ofsflags);
+ ofs += clstrsz;
+ }
+ }
+ if (sparse_write(fd, l2tbl, clstrsz) < 0) {
+ error = errno;
+ goto out;
+ }
+ }
+
+ free(l2tbl);
+ l2tbl = NULL;
+ free(l1tbl);
+ l1tbl = NULL;
+
+ if (rcclno > 0) {
+ rcblk = calloc(clstr_rcblks, clstrsz);
+ if (rcblk == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ for (n = 0; n < nclstrs; n++)
+ be16enc(rcblk + n, 1);
+ if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) {
+ error = errno;
+ goto out;
+ }
+ free(rcblk);
+ rcblk = NULL;
+ }
+
+ error = 0;
+ for (n = 0; n < clstr_imgsz; n++) {
+ blk = n * blk_clstrsz;
+ if (image_data(blk, blk_clstrsz)) {
+ error = image_copyout_region(fd, blk, blk_clstrsz);
+ if (error)
+ break;
+ }
+ }
+ if (!error)
+ error = image_copyout_done(fd);
+
+ out:
+ if (rcblk != NULL)
+ free(rcblk);
+ if (l2tbl != NULL)
+ free(l2tbl);
+ if (rctbl != NULL)
+ free(rctbl);
+ if (l1tbl != NULL)
+ free(l1tbl);
+ if (hdr != NULL)
+ free(hdr);
+ return (error);
+}
+
+static int
+qcow1_write(int fd)
+{
+
+ return (qcow_write(fd, QCOW_VERSION_1));
+}
+
+static int
+qcow2_write(int fd)
+{
+
+ return (qcow_write(fd, QCOW_VERSION_2));
+}
+
+static struct mkimg_format qcow1_format = {
+ .name = "qcow",
+ .description = "QEMU Copy-On-Write, version 1",
+ .resize = qcow1_resize,
+ .write = qcow1_write,
+};
+FORMAT_DEFINE(qcow1_format);
+
+static struct mkimg_format qcow2_format = {
+ .name = "qcow2",
+ .description = "QEMU Copy-On-Write, version 2",
+ .resize = qcow2_resize,
+ .write = qcow2_write,
+};
+FORMAT_DEFINE(qcow2_format);
diff --git a/usr.bin/mkimg/raw.c b/usr.bin/mkimg/raw.c
new file mode 100644
index 000000000000..2de674b908ac
--- /dev/null
+++ b/usr.bin/mkimg/raw.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "format.h"
+
+static int
+raw_resize(lba_t imgsz __unused)
+{
+
+ return (0);
+}
+
+static int
+raw_write(int fd)
+{
+
+ return (image_copyout(fd));
+}
+
+static struct mkimg_format raw_format = {
+ .name = "raw",
+ .description = "Raw Disk",
+ .resize = raw_resize,
+ .write = raw_write,
+};
+
+FORMAT_DEFINE(raw_format);
diff --git a/usr.bin/mkimg/scheme.c b/usr.bin/mkimg/scheme.c
new file mode 100644
index 000000000000..85ed94013e8d
--- /dev/null
+++ b/usr.bin/mkimg/scheme.c
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2013,2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "mkimg.h"
+#include "scheme.h"
+
+static struct {
+ const char *name;
+ enum alias alias;
+} scheme_alias[] = {
+ { "ebr", ALIAS_EBR },
+ { "efi", ALIAS_EFI },
+ { "fat16b", ALIAS_FAT16B },
+ { "fat32", ALIAS_FAT32 },
+ { "fat32lba", ALIAS_FAT32LBA },
+ { "freebsd", ALIAS_FREEBSD },
+ { "freebsd-boot", ALIAS_FREEBSD_BOOT },
+ { "freebsd-nandfs", ALIAS_FREEBSD_NANDFS },
+ { "freebsd-swap", ALIAS_FREEBSD_SWAP },
+ { "freebsd-ufs", ALIAS_FREEBSD_UFS },
+ { "freebsd-vinum", ALIAS_FREEBSD_VINUM },
+ { "freebsd-zfs", ALIAS_FREEBSD_ZFS },
+ { "mbr", ALIAS_MBR },
+ { "ntfs", ALIAS_NTFS },
+ { "prepboot", ALIAS_PPCBOOT },
+ { NULL, ALIAS_NONE } /* Keep last! */
+};
+
+static struct mkimg_scheme *first;
+static struct mkimg_scheme *scheme;
+static void *bootcode;
+
+static enum alias
+scheme_parse_alias(const char *name)
+{
+ u_int idx;
+
+ idx = 0;
+ while (scheme_alias[idx].name != NULL) {
+ if (strcasecmp(scheme_alias[idx].name, name) == 0)
+ return (scheme_alias[idx].alias);
+ idx++;
+ }
+ return (ALIAS_NONE);
+}
+
+struct mkimg_scheme *
+scheme_iterate(struct mkimg_scheme *s)
+{
+
+ return ((s == NULL) ? first : s->next);
+}
+
+void
+scheme_register(struct mkimg_scheme *s)
+{
+ s->next = first;
+ first = s;
+}
+
+int
+scheme_select(const char *spec)
+{
+ struct mkimg_scheme *s;
+
+ s = NULL;
+ while ((s = scheme_iterate(s)) != NULL) {
+ if (strcasecmp(spec, s->name) == 0) {
+ scheme = s;
+ return (0);
+ }
+ }
+ return (EINVAL);
+}
+
+struct mkimg_scheme *
+scheme_selected(void)
+{
+
+ return (scheme);
+}
+
+int
+scheme_bootcode(int fd)
+{
+ struct stat sb;
+
+ if (scheme == NULL || scheme->bootcode == 0)
+ return (ENXIO);
+
+ if (fstat(fd, &sb) == -1)
+ return (errno);
+ if (sb.st_size > scheme->bootcode)
+ return (EFBIG);
+
+ bootcode = malloc(scheme->bootcode);
+ if (bootcode == NULL)
+ return (ENOMEM);
+ memset(bootcode, 0, scheme->bootcode);
+ if (read(fd, bootcode, sb.st_size) != sb.st_size) {
+ free(bootcode);
+ bootcode = NULL;
+ return (errno);
+ }
+ return (0);
+}
+
+int
+scheme_check_part(struct part *p)
+{
+ struct mkimg_alias *iter;
+ enum alias alias;
+
+ assert(scheme != NULL);
+
+ /* Check the partition type alias */
+ alias = scheme_parse_alias(p->alias);
+ if (alias == ALIAS_NONE)
+ return (EINVAL);
+
+ iter = scheme->aliases;
+ while (iter->alias != ALIAS_NONE) {
+ if (alias == iter->alias)
+ break;
+ iter++;
+ }
+ if (iter->alias == ALIAS_NONE)
+ return (EINVAL);
+ p->type = iter->type;
+
+ /* Validate the optional label. */
+ if (p->label != NULL) {
+ if (strlen(p->label) > scheme->labellen)
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+u_int
+scheme_max_parts(void)
+{
+
+ return ((scheme == NULL) ? 0 : scheme->nparts);
+}
+
+u_int
+scheme_max_secsz(void)
+{
+
+ return ((scheme == NULL) ? INT_MAX+1U : scheme->maxsecsz);
+}
+
+lba_t
+scheme_metadata(u_int where, lba_t start)
+{
+
+ return ((scheme == NULL) ? start : scheme->metadata(where, start));
+}
+
+int
+scheme_write(lba_t end)
+{
+
+ return ((scheme == NULL) ? 0 : scheme->write(end, bootcode));
+}
diff --git a/usr.bin/mkimg/scheme.h b/usr.bin/mkimg/scheme.h
new file mode 100644
index 000000000000..52614255595f
--- /dev/null
+++ b/usr.bin/mkimg/scheme.h
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2013,2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _MKIMG_SCHEME_H_
+#define _MKIMG_SCHEME_H_
+
+enum alias {
+ ALIAS_NONE, /* Keep first! */
+ /* start */
+ ALIAS_EBR,
+ ALIAS_EFI,
+ ALIAS_FAT16B,
+ ALIAS_FAT32,
+ ALIAS_FAT32LBA,
+ ALIAS_FREEBSD,
+ ALIAS_FREEBSD_BOOT,
+ ALIAS_FREEBSD_NANDFS,
+ ALIAS_FREEBSD_SWAP,
+ ALIAS_FREEBSD_UFS,
+ ALIAS_FREEBSD_VINUM,
+ ALIAS_FREEBSD_ZFS,
+ ALIAS_MBR,
+ ALIAS_NTFS,
+ ALIAS_PPCBOOT,
+ /* end */
+ ALIAS_COUNT /* Keep last! */
+};
+
+struct mkimg_alias {
+ u_int alias;
+ uintptr_t type;
+#define ALIAS_PTR2TYPE(p) (uintptr_t)(p)
+#define ALIAS_INT2TYPE(i) (i)
+#define ALIAS_TYPE2PTR(p) (void *)(p)
+#define ALIAS_TYPE2INT(i) (i)
+};
+
+struct mkimg_scheme {
+ struct mkimg_scheme *next;
+ const char *name;
+ const char *description;
+ struct mkimg_alias *aliases;
+ lba_t (*metadata)(u_int, lba_t);
+#define SCHEME_META_IMG_START 1
+#define SCHEME_META_IMG_END 2
+#define SCHEME_META_PART_BEFORE 3
+#define SCHEME_META_PART_AFTER 4
+#define SCHEME_META_PART_ABSOLUTE 5
+ int (*write)(lba_t, void *);
+ u_int nparts;
+ u_int labellen;
+ u_int bootcode;
+ u_int maxsecsz;
+};
+
+#define SCHEME_DEFINE(nm) \
+static void scheme_register_##nm(void) __attribute__((constructor)); \
+static void scheme_register_##nm(void) { scheme_register(&nm); }
+
+struct mkimg_scheme *scheme_iterate(struct mkimg_scheme *);
+void scheme_register(struct mkimg_scheme *);
+int scheme_select(const char *);
+struct mkimg_scheme *scheme_selected(void);
+
+int scheme_bootcode(int fd);
+int scheme_check_part(struct part *);
+u_int scheme_max_parts(void);
+u_int scheme_max_secsz(void);
+lba_t scheme_metadata(u_int, lba_t);
+int scheme_write(lba_t);
+
+#endif /* _MKIMG_SCHEME_H_ */
diff --git a/usr.bin/mkimg/tests/Makefile b/usr.bin/mkimg/tests/Makefile
new file mode 100644
index 000000000000..0cd08b6f1230
--- /dev/null
+++ b/usr.bin/mkimg/tests/Makefile
@@ -0,0 +1,37 @@
+.PATH: ${.CURDIR}
+
+PACKAGE= tests
+
+_REBASE_SCRIPT= mkimg_test
+ATF_TESTS_SH= ${_REBASE_SCRIPT}
+
+SOURCES!= cd ${.CURDIR}; echo *.hex
+${PACKAGE}FILES+= ${SOURCES:S,.hex,,g}
+
+.for f in ${${PACKAGE}FILES}
+$f: $f.hex
+ sed -e '/^#.*/D' < ${.ALLSRC} > ${.TARGET}
+.endfor
+
+# Note: Pre-generating this test file saves a lot of time when building on
+# emulated platforms such as QEMU. It can take about 2-5 seconds to generate
+# the test file using jot (depending on the emulated architecture) and this
+# is done for each of the 168 test configurations.
+# The effect is even more pronounced on CHERI-RISCV QEMU (emulating CHERI inside
+# QEMU adds additional run-time overhead): Running the apm_1x1_512_raw without
+# the pre-generated file takes about 108 seconds of which 102 seconds (over 95%)
+# were spent running jot -b. It's even worse on CHERI-MIPS QEMU: 187 seconds
+# for jot -b P 2097152 > /dev/null. By using a pre-generated 4MB file, the
+# slowest test variant (vtoc8_63x255_4096_vhdx) now only takes 29 seconds (of
+# which 26s are spent in hexdump -C) instead of previously 2min30s.
+${PACKAGE}FILES+= partition_data_4M.bin
+partition_data_4M.bin: Makefile
+ jot -b P 2097152 > ${.TARGET} || rm -f ${.TARGET}
+
+CLEANFILES+= ${${PACKAGE}FILES}}
+
+rebase: partition_data_4M.bin ${_REBASE_SCRIPT} .PHONY
+ cd ${.CURDIR}; PATH=${.OBJDIR}/..:$${PATH}:/usr/bin:/bin \
+ /usr/libexec/atf-sh ${.OBJDIR}/${_REBASE_SCRIPT} -s ${.OBJDIR} rebase
+
+.include <bsd.test.mk>
diff --git a/usr.bin/mkimg/tests/Makefile.depend b/usr.bin/mkimg/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/mkimg/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.hex
new file mode 100644
index 000000000000..70f7bc9ca1c3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.hex
@@ -0,0 +1,549 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 10 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00005010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00005210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00005220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00005240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00005440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00005610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00005640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.hex
new file mode 100644
index 000000000000..e851208bfa0c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.hex
@@ -0,0 +1,79 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 45 52 02 00 00 00 21 80 00 00 00 00 00 00 00 00 |ER....!.........|
+00050010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00050210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00050220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00050240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00050440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00050610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00050640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00051000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00451000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.hex
new file mode 100644
index 000000000000..b0c234ff00da
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.hex
@@ -0,0 +1,27 @@
+00000000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00421000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.hex
new file mode 100644
index 000000000000..7f044f9f39c3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.hex
@@ -0,0 +1,59 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 45 52 02 00 00 00 21 34 00 00 00 00 00 00 00 00 |ER....!4........|
+00000a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c00 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000c10 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000c20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c30 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000c40 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e30 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000e40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001030 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.hex
new file mode 100644
index 000000000000..616f8290df6e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.hex
@@ -0,0 +1,35 @@
+00000000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdx.hex
new file mode 100644
index 000000000000..fc421fe31724
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdx.hex
@@ -0,0 +1,78 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 45 52 02 00 00 00 80 00 00 00 00 00 00 00 00 00 |ER..............|
+00400010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00400210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00400220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00400240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00400440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00400610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00400640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00401000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00801000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.hex
new file mode 100644
index 000000000000..99651b4b47c3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.hex
@@ -0,0 +1,321 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00004210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00004220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00004240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00004440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00004610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00004640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.hex
new file mode 100644
index 000000000000..a3ba126e058d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.hex
@@ -0,0 +1,545 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 20 00 |.............B .|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005230 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005280 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000052a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000052b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000052c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.hex
new file mode 100644
index 000000000000..79ed083bfaaf
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.hex
@@ -0,0 +1,75 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050230 01 00 00 00 80 21 00 00 01 00 00 00 80 21 00 00 |.....!.......!..|
+00050240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050280 00 00 00 00 57 45 56 82 9f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000502a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000502b0 01 00 00 00 80 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000502c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.hex
new file mode 100644
index 000000000000..e2e8cfa79fb7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.hex
@@ -0,0 +1,23 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000230 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.hex
new file mode 100644
index 000000000000..46d7d59d059d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.hex
@@ -0,0 +1,55 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000c00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000c30 01 00 00 00 34 21 00 00 01 00 00 00 34 21 00 00 |....4!......4!..|
+00000c40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c80 00 00 00 00 57 45 56 82 2b 0c 08 00 00 20 00 00 |....WEV.+.... ..|
+00000c90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ca0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000cb0 01 00 00 00 34 21 00 00 00 00 00 00 00 00 00 00 |....4!..........|
+00000cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000d10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000d20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.hex
new file mode 100644
index 000000000000..1ed322341ed1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.hex
@@ -0,0 +1,31 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000230 01 00 00 00 00 28 00 00 01 00 00 00 00 28 00 00 |.....(.......(..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1f 05 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 00 28 00 00 00 00 00 00 00 00 00 00 |.....(..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdx.hex
new file mode 100644
index 000000000000..9f4ea01ad88f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdx.hex
@@ -0,0 +1,74 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400230 01 00 00 00 00 80 00 00 01 00 00 00 00 80 00 00 |................|
+00400240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400280 00 00 00 00 57 45 56 82 1f ad 08 00 00 20 00 00 |....WEV...... ..|
+00400290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004002b0 01 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 |................|
+004002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.hex
new file mode 100644
index 000000000000..a54df88c0e15
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.hex
@@ -0,0 +1,315 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004230 01 00 00 00 00 28 00 00 01 00 00 00 00 28 00 00 |.....(.......(..|
+00004240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004280 00 00 00 00 57 45 56 82 1f 05 08 00 00 20 00 00 |....WEV...... ..|
+00004290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000042a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000042b0 01 00 00 00 00 28 00 00 00 00 00 00 00 00 00 00 |.....(..........|
+000042c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.hex
new file mode 100644
index 000000000000..89172925a81f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.hex
@@ -0,0 +1,553 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 30 00 |.............B0.|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000051c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000054a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000054b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000054c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.hex
new file mode 100644
index 000000000000..b235e2c29c29
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.hex
@@ -0,0 +1,80 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000501c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00050440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000504a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000504b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000504c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.hex
new file mode 100644
index 000000000000..74246b392477
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.hex
@@ -0,0 +1,30 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.hex
new file mode 100644
index 000000000000..8ad7f268ff39
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.hex
@@ -0,0 +1,62 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+00000bc0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000e00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000e20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000e30 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000e40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000e50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000e90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ea0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000eb0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+00000ec0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000f10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000f20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00403000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.hex
new file mode 100644
index 000000000000..e6f3f309c284
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.hex
@@ -0,0 +1,38 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdx.hex
new file mode 100644
index 000000000000..848f3c9aeedf
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdx.hex
@@ -0,0 +1,79 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+004001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00400440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00400490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+004004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.hex
new file mode 100644
index 000000000000..2ce4aadf9d7a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.hex
@@ -0,0 +1,322 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000041c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00004440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00004490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000044a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000044b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000044c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.hex
new file mode 100644
index 000000000000..ab899b3e5ec2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.hex
@@ -0,0 +1,579 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 a0 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002030 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002040 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002050 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002060 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002070 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002080 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002090 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020a0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020b0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020c0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020d0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020e0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020f0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002100 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002110 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002120 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002130 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002140 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002150 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002160 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002170 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002180 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002190 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021a0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021b0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021c0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021d0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021e0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021f0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002200 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002210 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002220 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002230 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002240 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002250 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002260 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002270 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002280 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002290 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022a0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022b0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022c0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022d0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022e0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022f0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002300 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002310 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002320 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002330 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002340 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002350 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002360 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002370 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002380 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002390 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023a0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023b0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023c0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023d0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023e0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023f0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002400 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002410 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002420 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002430 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002440 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002450 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002460 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002470 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002480 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002490 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024a0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024b0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024c0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024d0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024e0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024f0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002500 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002510 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002520 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002530 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002540 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002550 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002560 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002570 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002580 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002590 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025a0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025b0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025c0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025d0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025e0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025f0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002600 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002610 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002620 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002630 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002640 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002650 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002660 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002670 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002680 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002690 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026a0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026b0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026c0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026d0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026e0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026f0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002700 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002710 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002720 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002730 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002740 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002750 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002760 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002770 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002780 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002790 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027a0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027b0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027c0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027d0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027e0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027f0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002800 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002810 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002820 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002830 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002840 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002850 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002860 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002870 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002880 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002890 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028a0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028b0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028c0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028d0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028e0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028f0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002900 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002910 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002920 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002930 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002940 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002950 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002960 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002970 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002980 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002990 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029a0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029b0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029c0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029d0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029e0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029f0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a00 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a10 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a20 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a30 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a40 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a50 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a60 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a70 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a80 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a90 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002aa0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ab0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ac0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ad0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ae0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002af0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b00 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b10 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b20 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b30 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b40 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b50 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b60 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b70 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b80 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b90 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002ba0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bb0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bc0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bd0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002be0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bf0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c00 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c10 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c20 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c30 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c40 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c50 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c60 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c70 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c80 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c90 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002ca0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cb0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cc0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cd0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002ce0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cf0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d00 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d10 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d20 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d30 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d40 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d50 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d60 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d70 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d80 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d90 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002da0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002db0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dc0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002dd0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002de0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002df0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e00 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e10 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e20 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e30 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e40 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e50 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e60 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e70 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e80 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e90 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002ea0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002eb0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ec0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ed0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ee0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ef0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f00 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f10 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f20 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f30 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f40 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f50 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f60 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f70 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f80 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f90 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fa0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fb0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fc0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fd0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fe0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002ff0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003000 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003010 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003020 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003030 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003040 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003080 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003090 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030a0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030b0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030c0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003100 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003110 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003120 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003130 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003140 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003150 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003160 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003170 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003180 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003190 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031a0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031b0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031c0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003200 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003210 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003220 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003230 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003240 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003280 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003290 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032a0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032b0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032c0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003300 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003310 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003320 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003330 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003340 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003380 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003390 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033a0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033b0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033c0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003400 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003410 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003420 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003430 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003440 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003480 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003490 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034a0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034b0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034c0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003500 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003510 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003520 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003530 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003540 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003580 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003590 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035a0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035b0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035c0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003600 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003610 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003620 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003630 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003640 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003680 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003690 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036a0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036b0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036c0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003700 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003710 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003720 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003730 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003740 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003750 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003760 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003770 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003780 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003790 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037a0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037b0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037c0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003800 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003810 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003820 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003830 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003840 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003880 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003890 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038a0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038b0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038c0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003900 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003910 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003920 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003930 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003940 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003980 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003990 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039a0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039b0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039c0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a00 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a10 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a20 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a30 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a40 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a80 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a90 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003aa0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ab0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ac0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b00 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b10 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b20 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b30 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b40 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b80 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b90 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003ba0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bb0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bc0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c00 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c10 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c20 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c30 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c40 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c80 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c90 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003ca0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cb0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cc0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d00 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d10 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d20 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d30 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d40 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d80 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d90 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003da0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003db0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dc0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e00 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e10 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e20 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e30 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e40 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e80 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e90 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003ea0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003eb0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ec0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f00 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f10 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f20 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f30 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f40 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f80 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f90 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fa0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fb0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fc0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004000 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004010 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004020 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004120 00 00 00 00 00 00 00 00 00 00 00 00 00 40 60 00 |.............@`.|
+00004130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004140 00 00 00 00 00 00 00 00 00 00 00 00 00 40 70 00 |.............@p.|
+00004150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000051c0 02 00 ee ff ff ff 01 00 00 00 4f 21 00 00 00 00 |..........O!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00005210 5a 6f 4f 0c 00 00 00 00 01 00 00 00 00 00 00 00 |ZoO.............|
+00005220 4f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |O!......".......|
+00005230 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00005240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00005250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00005260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00005420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00005430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000054a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000054b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00406e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00406e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00406e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00406e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00406ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00406eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00407e10 51 9d 2a 3e 00 00 00 00 4f 21 00 00 00 00 00 00 |Q.*>....O!......|
+00407e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00407e30 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00407e40 03 03 03 03 03 03 03 03 2f 21 00 00 00 00 00 00 |......../!......|
+00407e50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00407e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.hex
new file mode 100644
index 000000000000..a2d342d06a42
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.hex
@@ -0,0 +1,101 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 80 00 00 00 00 46 00 00 00 00 00 00 00 00 00 00 |.....F..........|
+00030220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000501c0 02 00 ee ff ff ff 01 00 00 00 7f 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00050210 7d b3 cb 21 00 00 00 00 01 00 00 00 00 00 00 00 |}..!............|
+00050220 7f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.!......".......|
+00050230 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+00050240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00050250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00050260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00050420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00050430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000504a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000504b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00055000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00455000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0046be20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+0046be30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0046bea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+0046beb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046fe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0046fe10 ed cb cc 05 00 00 00 00 7f 21 00 00 00 00 00 00 |.........!......|
+0046fe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0046fe30 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+0046fe40 03 03 03 03 03 03 03 03 5f 21 00 00 00 00 00 00 |........_!......|
+0046fe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+0046fe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00470000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.hex
new file mode 100644
index 000000000000..dae6b78a65f8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.hex
@@ -0,0 +1,48 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 4f 21 00 00 00 00 |..........O!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 5a 6f 4f 0c 00 00 00 00 01 00 00 00 00 00 00 00 |ZoO.............|
+00000220 4f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |O!......".......|
+00000230 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00425e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00425e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00425e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00425e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00425e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00425e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00425ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00425eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00429e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00429e10 51 9d 2a 3e 00 00 00 00 4f 21 00 00 00 00 00 00 |Q.*>....O!......|
+00429e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00429e30 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00429e40 03 03 03 03 03 03 03 03 2f 21 00 00 00 00 00 00 |......../!......|
+00429e50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00429e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042a000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.hex
new file mode 100644
index 000000000000..0de167c0e198
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.hex
@@ -0,0 +1,80 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 f0 00 |....Wi2k.....B..|
+00000030 00 00 00 00 00 42 f0 00 00 7e 04 11 00 00 00 03 |.....B...~......|
+00000040 ff ff f5 cd 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00000050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+00000bc0 02 00 ee ff ff ff 01 00 00 00 77 21 00 00 00 00 |..........w!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000c10 11 1d d2 4b 00 00 00 00 01 00 00 00 00 00 00 00 |...K............|
+00000c20 77 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |w!......".......|
+00000c30 56 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |V!..............|
+00000c40 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000c50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00000ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00000eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042bc00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0042bc10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0042bc20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+0042bc30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042bc80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0042bc90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0042bca0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+0042bcb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042fc00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0042fc10 9c 15 29 8d 00 00 00 00 77 21 00 00 00 00 00 00 |..).....w!......|
+0042fc20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0042fc30 56 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |V!..............|
+0042fc40 03 03 03 03 03 03 03 03 57 21 00 00 00 00 00 00 |........W!......|
+0042fc50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+0042fc60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 f0 00 |....Wi2k.....B..|
+00600e30 00 00 00 00 00 42 f0 00 00 7e 04 11 00 00 00 03 |.....B...~......|
+00600e40 ff ff f5 cd 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00600e50 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.hex
new file mode 100644
index 000000000000..bd8601eccc50
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.hex
@@ -0,0 +1,56 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 c4 60 24 d3 00 00 00 00 01 00 00 00 00 00 00 00 |.`$.............|
+00000220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00000230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+004fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+004fbe20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+004fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+004fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004fbea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+004fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+004ffe10 aa 6f 0f ab 00 00 00 00 ff 27 00 00 00 00 00 00 |.o.......'......|
+004ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+004ffe30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+004ffe40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+004ffe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+004ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef 84 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00500050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdx.hex
new file mode 100644
index 000000000000..4d4542d9a686
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdx.hex
@@ -0,0 +1,99 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+004001c0 02 00 ee ff ff ff 01 00 00 00 ff 7f 00 00 00 00 |................|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00400210 f9 27 e5 be 00 00 00 00 01 00 00 00 00 00 00 00 |.'..............|
+00400220 ff 7f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00400230 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+00400240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00400250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00400260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00400420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00400430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+004004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00405000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00805000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+013fbe20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+013fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+013fbea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+013fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+013ffe10 47 76 13 47 00 00 00 00 ff 7f 00 00 00 00 00 00 |Gv.G............|
+013ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+013ffe30 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+013ffe40 03 03 03 03 03 03 03 03 df 7f 00 00 00 00 00 00 |................|
+013ffe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+013ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.hex
new file mode 100644
index 000000000000..35b354c7310b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.hex
@@ -0,0 +1,348 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00000610 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00000620 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00000630 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00000640 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00000650 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00000660 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00000670 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00000680 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00000690 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000006a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000006b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000006c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000006d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000006e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000006f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00000700 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00000710 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00000720 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00000730 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00000740 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00000750 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00000760 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00000770 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00000780 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00000790 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000007a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000007b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000007c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000007d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000007e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000007f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00000800 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00000810 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00000820 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00000830 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00000840 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00000850 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00000860 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00000870 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00000880 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00000890 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+000008a0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+000008b0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+000008c0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+000008d0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+000008e0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+000008f0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00000900 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00000910 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00000920 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00000930 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00000940 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00000950 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00000960 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00000970 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00000980 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00000990 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+000009a0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+000009b0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+000009c0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+000009d0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+000009e0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+000009f0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00000a00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00000a10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00000a20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00000a30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00000a40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00000a50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00000a60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00000a70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00000a80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00000a90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00000aa0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00000ab0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00000ac0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00000ad0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00000ae0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00000af0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00000b00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00000b10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00000b20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00000b30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00000b40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00000b50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00000b60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00000b70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00000b80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00000b90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00000ba0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00000bb0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00000bc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00000bd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00000be0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00000bf0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00000c00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00000c10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00000c20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00000c30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00000c40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00000c50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00000c60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00000c70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00000c80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00000c90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00000ca0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00000cb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00000cc0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00000cd0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00000ce0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00000cf0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00000d00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00000d10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00000d20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00000d30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00000d40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00000d50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00000d60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00000d70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00000d80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00000d90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00000da0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00000db0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00000dc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00000dd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00000de0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00000df0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00000e00 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000ff0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00001810 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00001820 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00001830 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00001840 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00001850 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00001860 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00001870 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00001880 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00001890 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000018a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000018b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000018c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000018d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000018e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000018f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00001900 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00001910 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00001920 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00001930 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00001940 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00001950 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00001960 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00001970 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00001980 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00001990 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000019a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000019b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000019c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000019d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000019e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000019f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00001a00 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00001a10 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00001a20 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00001a30 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00001a40 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00001a50 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00001a60 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00001a70 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00001a80 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00001a90 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+00001aa0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+00001ab0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+00001ac0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+00001ad0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+00001ae0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+00001af0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00001b00 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00001b10 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00001b20 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00001b30 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00001b40 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00001b50 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00001b60 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00001b70 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00001b80 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00001b90 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+00001ba0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+00001bb0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+00001bc0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+00001bd0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+00001be0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+00001bf0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00001c00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00001c10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00001c20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00001c30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00001c40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00001c50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00001c60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00001c70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00001c80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00001c90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00001ca0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00001cb0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00001cc0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00001cd0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00001ce0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00001cf0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00001d00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00001d10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00001d20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00001d30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00001d40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00001d50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00001d60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00001d70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00001d80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00001d90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00001da0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00001db0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00001dc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00001dd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00001de0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00001df0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00001e00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00001e10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00001e20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00001e30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00001e40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00001e50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00001e60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00001e70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00001e80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00001e90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00001ea0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00001eb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00001ec0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00001ed0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00001ee0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00001ef0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00001f00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00001f10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00001f20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00001f30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00001f40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00001f50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00001f60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00001f70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00001f80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00001f90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00001fa0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00001fb0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00001fc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00001fd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00001fe0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00001ff0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00002000 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000021f0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00002200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000041c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00004210 c4 60 24 d3 00 00 00 00 01 00 00 00 00 00 00 00 |.`$.............|
+00004220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00004230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00004240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00004250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00004260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00004420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00004430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000044a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000044b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00409e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00409e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00409ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00409eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040be00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0040be10 aa 6f 0f ab 00 00 00 00 ff 27 00 00 00 00 00 00 |.o.......'......|
+0040be20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0040be30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+0040be40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+0040be50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+0040be60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040c000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.hex
new file mode 100644
index 000000000000..c55a803e281f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.hex
@@ -0,0 +1,555 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 30 00 |.............B0.|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000051c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000054a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000054b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000054c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.hex
new file mode 100644
index 000000000000..21f5d3c3735e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.hex
@@ -0,0 +1,82 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000501c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00050440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000504a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000504b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000504c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.hex
new file mode 100644
index 000000000000..b1a896b30c14
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.hex
@@ -0,0 +1,30 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.hex
new file mode 100644
index 000000000000..b16328b04dba
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.hex
@@ -0,0 +1,62 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+00000bc0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000e00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000e20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000e30 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000e40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000e50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000e90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ea0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000eb0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+00000ec0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000f10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000f20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00403000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.hex
new file mode 100644
index 000000000000..faf6057fccb0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.hex
@@ -0,0 +1,38 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdx.hex
new file mode 100644
index 000000000000..597abaaf495f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdx.hex
@@ -0,0 +1,81 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+004001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00400440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00400490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+004004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.hex
new file mode 100644
index 000000000000..f5e2a17ae763
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.hex
@@ -0,0 +1,324 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000041c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00004440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00004490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000044a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000044b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000044c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.hex
new file mode 100644
index 000000000000..a4ff3455ce96
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.hex
@@ -0,0 +1,551 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 10 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00005010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00005210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00005220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00005240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00005440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00005610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00005640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.hex
new file mode 100644
index 000000000000..d7056c8f81a7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.hex
@@ -0,0 +1,79 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 45 52 02 00 00 00 21 80 00 00 00 00 00 00 00 00 |ER....!.........|
+00050010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00050210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00050220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00050240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00050440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00050610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00050640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00450800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.raw.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.hex
new file mode 100644
index 000000000000..22005720d5fa
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.hex
@@ -0,0 +1,27 @@
+00000000 45 52 02 00 00 00 21 04 00 00 00 00 00 00 00 00 |ER....!.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00420800
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.hex
new file mode 100644
index 000000000000..4dd0db5f7c9c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.hex
@@ -0,0 +1,59 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 45 52 02 00 00 00 21 34 00 00 00 00 00 00 00 00 |ER....!4........|
+00000a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c00 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000c10 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000c20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c30 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000c40 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e30 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000e40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001030 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.hex
new file mode 100644
index 000000000000..92a58cecbff2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.hex
@@ -0,0 +1,35 @@
+00000000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdx.hex
new file mode 100644
index 000000000000..5830cc7799d7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdx.hex
@@ -0,0 +1,78 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 45 52 02 00 00 00 80 00 00 00 00 00 00 00 00 00 |ER..............|
+00400010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00400210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00400220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00400240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00400440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00400610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00400640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00800800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.hex
new file mode 100644
index 000000000000..7dccd5b05557
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.hex
@@ -0,0 +1,321 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00004210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00004220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00004240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00004440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00004610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00004640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.hex
new file mode 100644
index 000000000000..a3ba126e058d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.hex
@@ -0,0 +1,545 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 20 00 |.............B .|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005230 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005280 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000052a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000052b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000052c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.hex
new file mode 100644
index 000000000000..79ed083bfaaf
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.hex
@@ -0,0 +1,75 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050230 01 00 00 00 80 21 00 00 01 00 00 00 80 21 00 00 |.....!.......!..|
+00050240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050280 00 00 00 00 57 45 56 82 9f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000502a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000502b0 01 00 00 00 80 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000502c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.hex
new file mode 100644
index 000000000000..e2e8cfa79fb7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.hex
@@ -0,0 +1,23 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000230 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.hex
new file mode 100644
index 000000000000..46d7d59d059d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.hex
@@ -0,0 +1,55 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000c00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000c30 01 00 00 00 34 21 00 00 01 00 00 00 34 21 00 00 |....4!......4!..|
+00000c40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c80 00 00 00 00 57 45 56 82 2b 0c 08 00 00 20 00 00 |....WEV.+.... ..|
+00000c90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ca0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000cb0 01 00 00 00 34 21 00 00 00 00 00 00 00 00 00 00 |....4!..........|
+00000cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000d10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000d20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.hex
new file mode 100644
index 000000000000..1ed322341ed1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.hex
@@ -0,0 +1,31 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000230 01 00 00 00 00 28 00 00 01 00 00 00 00 28 00 00 |.....(.......(..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1f 05 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 00 28 00 00 00 00 00 00 00 00 00 00 |.....(..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdx.hex
new file mode 100644
index 000000000000..aedd3a533f0a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdx.hex
@@ -0,0 +1,74 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400230 01 00 00 00 00 80 00 00 01 00 00 00 00 80 00 00 |................|
+00400240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400280 00 00 00 00 57 45 56 82 1f ad 08 00 00 20 00 00 |....WEV...... ..|
+00400290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004002b0 01 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 |................|
+004002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.hex
new file mode 100644
index 000000000000..a54df88c0e15
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.hex
@@ -0,0 +1,315 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004220 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004230 01 00 00 00 00 28 00 00 01 00 00 00 00 28 00 00 |.....(.......(..|
+00004240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004280 00 00 00 00 57 45 56 82 1f 05 08 00 00 20 00 00 |....WEV...... ..|
+00004290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000042a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000042b0 01 00 00 00 00 28 00 00 00 00 00 00 00 00 00 00 |.....(..........|
+000042c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.hex
new file mode 100644
index 000000000000..89172925a81f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.hex
@@ -0,0 +1,553 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 30 00 |.............B0.|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000051c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000054a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000054b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000054c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.hex
new file mode 100644
index 000000000000..b235e2c29c29
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.hex
@@ -0,0 +1,80 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000501c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00050440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000504a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000504b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000504c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.hex
new file mode 100644
index 000000000000..74246b392477
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.hex
@@ -0,0 +1,30 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.hex
new file mode 100644
index 000000000000..8ad7f268ff39
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.hex
@@ -0,0 +1,62 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+00000bc0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000e00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000e20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000e30 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000e40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000e50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000e90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ea0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000eb0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+00000ec0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000f10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000f20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00403000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.hex
new file mode 100644
index 000000000000..e6f3f309c284
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.hex
@@ -0,0 +1,38 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdx.hex
new file mode 100644
index 000000000000..f1721d49344c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdx.hex
@@ -0,0 +1,79 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+004001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00400440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00400490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+004004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.hex
new file mode 100644
index 000000000000..2ce4aadf9d7a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.hex
@@ -0,0 +1,322 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff |................|
+000041c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00004440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00004490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000044a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000044b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000044c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.hex
new file mode 100644
index 000000000000..510bbf80e208
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.hex
@@ -0,0 +1,579 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 90 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00002020 00 00 00 00 00 00 60 00 00 00 00 00 00 00 70 00 |......`.......p.|
+00002030 00 00 00 00 00 00 80 00 00 00 00 00 00 00 90 00 |................|
+00002040 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 b0 00 |................|
+00002050 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 d0 00 |................|
+00002060 00 00 00 00 00 00 e0 00 00 00 00 00 00 00 f0 00 |................|
+00002070 00 00 00 00 00 01 00 00 00 00 00 00 00 01 10 00 |................|
+00002080 00 00 00 00 00 01 20 00 00 00 00 00 00 01 30 00 |...... .......0.|
+00002090 00 00 00 00 00 01 40 00 00 00 00 00 00 01 50 00 |......@.......P.|
+000020a0 00 00 00 00 00 01 60 00 00 00 00 00 00 01 70 00 |......`.......p.|
+000020b0 00 00 00 00 00 01 80 00 00 00 00 00 00 01 90 00 |................|
+000020c0 00 00 00 00 00 01 a0 00 00 00 00 00 00 01 b0 00 |................|
+000020d0 00 00 00 00 00 01 c0 00 00 00 00 00 00 01 d0 00 |................|
+000020e0 00 00 00 00 00 01 e0 00 00 00 00 00 00 01 f0 00 |................|
+000020f0 00 00 00 00 00 02 00 00 00 00 00 00 00 02 10 00 |................|
+00002100 00 00 00 00 00 02 20 00 00 00 00 00 00 02 30 00 |...... .......0.|
+00002110 00 00 00 00 00 02 40 00 00 00 00 00 00 02 50 00 |......@.......P.|
+00002120 00 00 00 00 00 02 60 00 00 00 00 00 00 02 70 00 |......`.......p.|
+00002130 00 00 00 00 00 02 80 00 00 00 00 00 00 02 90 00 |................|
+00002140 00 00 00 00 00 02 a0 00 00 00 00 00 00 02 b0 00 |................|
+00002150 00 00 00 00 00 02 c0 00 00 00 00 00 00 02 d0 00 |................|
+00002160 00 00 00 00 00 02 e0 00 00 00 00 00 00 02 f0 00 |................|
+00002170 00 00 00 00 00 03 00 00 00 00 00 00 00 03 10 00 |................|
+00002180 00 00 00 00 00 03 20 00 00 00 00 00 00 03 30 00 |...... .......0.|
+00002190 00 00 00 00 00 03 40 00 00 00 00 00 00 03 50 00 |......@.......P.|
+000021a0 00 00 00 00 00 03 60 00 00 00 00 00 00 03 70 00 |......`.......p.|
+000021b0 00 00 00 00 00 03 80 00 00 00 00 00 00 03 90 00 |................|
+000021c0 00 00 00 00 00 03 a0 00 00 00 00 00 00 03 b0 00 |................|
+000021d0 00 00 00 00 00 03 c0 00 00 00 00 00 00 03 d0 00 |................|
+000021e0 00 00 00 00 00 03 e0 00 00 00 00 00 00 03 f0 00 |................|
+000021f0 00 00 00 00 00 04 00 00 00 00 00 00 00 04 10 00 |................|
+00002200 00 00 00 00 00 04 20 00 00 00 00 00 00 04 30 00 |...... .......0.|
+00002210 00 00 00 00 00 04 40 00 00 00 00 00 00 04 50 00 |......@.......P.|
+00002220 00 00 00 00 00 04 60 00 00 00 00 00 00 04 70 00 |......`.......p.|
+00002230 00 00 00 00 00 04 80 00 00 00 00 00 00 04 90 00 |................|
+00002240 00 00 00 00 00 04 a0 00 00 00 00 00 00 04 b0 00 |................|
+00002250 00 00 00 00 00 04 c0 00 00 00 00 00 00 04 d0 00 |................|
+00002260 00 00 00 00 00 04 e0 00 00 00 00 00 00 04 f0 00 |................|
+00002270 00 00 00 00 00 05 00 00 00 00 00 00 00 05 10 00 |................|
+00002280 00 00 00 00 00 05 20 00 00 00 00 00 00 05 30 00 |...... .......0.|
+00002290 00 00 00 00 00 05 40 00 00 00 00 00 00 05 50 00 |......@.......P.|
+000022a0 00 00 00 00 00 05 60 00 00 00 00 00 00 05 70 00 |......`.......p.|
+000022b0 00 00 00 00 00 05 80 00 00 00 00 00 00 05 90 00 |................|
+000022c0 00 00 00 00 00 05 a0 00 00 00 00 00 00 05 b0 00 |................|
+000022d0 00 00 00 00 00 05 c0 00 00 00 00 00 00 05 d0 00 |................|
+000022e0 00 00 00 00 00 05 e0 00 00 00 00 00 00 05 f0 00 |................|
+000022f0 00 00 00 00 00 06 00 00 00 00 00 00 00 06 10 00 |................|
+00002300 00 00 00 00 00 06 20 00 00 00 00 00 00 06 30 00 |...... .......0.|
+00002310 00 00 00 00 00 06 40 00 00 00 00 00 00 06 50 00 |......@.......P.|
+00002320 00 00 00 00 00 06 60 00 00 00 00 00 00 06 70 00 |......`.......p.|
+00002330 00 00 00 00 00 06 80 00 00 00 00 00 00 06 90 00 |................|
+00002340 00 00 00 00 00 06 a0 00 00 00 00 00 00 06 b0 00 |................|
+00002350 00 00 00 00 00 06 c0 00 00 00 00 00 00 06 d0 00 |................|
+00002360 00 00 00 00 00 06 e0 00 00 00 00 00 00 06 f0 00 |................|
+00002370 00 00 00 00 00 07 00 00 00 00 00 00 00 07 10 00 |................|
+00002380 00 00 00 00 00 07 20 00 00 00 00 00 00 07 30 00 |...... .......0.|
+00002390 00 00 00 00 00 07 40 00 00 00 00 00 00 07 50 00 |......@.......P.|
+000023a0 00 00 00 00 00 07 60 00 00 00 00 00 00 07 70 00 |......`.......p.|
+000023b0 00 00 00 00 00 07 80 00 00 00 00 00 00 07 90 00 |................|
+000023c0 00 00 00 00 00 07 a0 00 00 00 00 00 00 07 b0 00 |................|
+000023d0 00 00 00 00 00 07 c0 00 00 00 00 00 00 07 d0 00 |................|
+000023e0 00 00 00 00 00 07 e0 00 00 00 00 00 00 07 f0 00 |................|
+000023f0 00 00 00 00 00 08 00 00 00 00 00 00 00 08 10 00 |................|
+00002400 00 00 00 00 00 08 20 00 00 00 00 00 00 08 30 00 |...... .......0.|
+00002410 00 00 00 00 00 08 40 00 00 00 00 00 00 08 50 00 |......@.......P.|
+00002420 00 00 00 00 00 08 60 00 00 00 00 00 00 08 70 00 |......`.......p.|
+00002430 00 00 00 00 00 08 80 00 00 00 00 00 00 08 90 00 |................|
+00002440 00 00 00 00 00 08 a0 00 00 00 00 00 00 08 b0 00 |................|
+00002450 00 00 00 00 00 08 c0 00 00 00 00 00 00 08 d0 00 |................|
+00002460 00 00 00 00 00 08 e0 00 00 00 00 00 00 08 f0 00 |................|
+00002470 00 00 00 00 00 09 00 00 00 00 00 00 00 09 10 00 |................|
+00002480 00 00 00 00 00 09 20 00 00 00 00 00 00 09 30 00 |...... .......0.|
+00002490 00 00 00 00 00 09 40 00 00 00 00 00 00 09 50 00 |......@.......P.|
+000024a0 00 00 00 00 00 09 60 00 00 00 00 00 00 09 70 00 |......`.......p.|
+000024b0 00 00 00 00 00 09 80 00 00 00 00 00 00 09 90 00 |................|
+000024c0 00 00 00 00 00 09 a0 00 00 00 00 00 00 09 b0 00 |................|
+000024d0 00 00 00 00 00 09 c0 00 00 00 00 00 00 09 d0 00 |................|
+000024e0 00 00 00 00 00 09 e0 00 00 00 00 00 00 09 f0 00 |................|
+000024f0 00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 10 00 |................|
+00002500 00 00 00 00 00 0a 20 00 00 00 00 00 00 0a 30 00 |...... .......0.|
+00002510 00 00 00 00 00 0a 40 00 00 00 00 00 00 0a 50 00 |......@.......P.|
+00002520 00 00 00 00 00 0a 60 00 00 00 00 00 00 0a 70 00 |......`.......p.|
+00002530 00 00 00 00 00 0a 80 00 00 00 00 00 00 0a 90 00 |................|
+00002540 00 00 00 00 00 0a a0 00 00 00 00 00 00 0a b0 00 |................|
+00002550 00 00 00 00 00 0a c0 00 00 00 00 00 00 0a d0 00 |................|
+00002560 00 00 00 00 00 0a e0 00 00 00 00 00 00 0a f0 00 |................|
+00002570 00 00 00 00 00 0b 00 00 00 00 00 00 00 0b 10 00 |................|
+00002580 00 00 00 00 00 0b 20 00 00 00 00 00 00 0b 30 00 |...... .......0.|
+00002590 00 00 00 00 00 0b 40 00 00 00 00 00 00 0b 50 00 |......@.......P.|
+000025a0 00 00 00 00 00 0b 60 00 00 00 00 00 00 0b 70 00 |......`.......p.|
+000025b0 00 00 00 00 00 0b 80 00 00 00 00 00 00 0b 90 00 |................|
+000025c0 00 00 00 00 00 0b a0 00 00 00 00 00 00 0b b0 00 |................|
+000025d0 00 00 00 00 00 0b c0 00 00 00 00 00 00 0b d0 00 |................|
+000025e0 00 00 00 00 00 0b e0 00 00 00 00 00 00 0b f0 00 |................|
+000025f0 00 00 00 00 00 0c 00 00 00 00 00 00 00 0c 10 00 |................|
+00002600 00 00 00 00 00 0c 20 00 00 00 00 00 00 0c 30 00 |...... .......0.|
+00002610 00 00 00 00 00 0c 40 00 00 00 00 00 00 0c 50 00 |......@.......P.|
+00002620 00 00 00 00 00 0c 60 00 00 00 00 00 00 0c 70 00 |......`.......p.|
+00002630 00 00 00 00 00 0c 80 00 00 00 00 00 00 0c 90 00 |................|
+00002640 00 00 00 00 00 0c a0 00 00 00 00 00 00 0c b0 00 |................|
+00002650 00 00 00 00 00 0c c0 00 00 00 00 00 00 0c d0 00 |................|
+00002660 00 00 00 00 00 0c e0 00 00 00 00 00 00 0c f0 00 |................|
+00002670 00 00 00 00 00 0d 00 00 00 00 00 00 00 0d 10 00 |................|
+00002680 00 00 00 00 00 0d 20 00 00 00 00 00 00 0d 30 00 |...... .......0.|
+00002690 00 00 00 00 00 0d 40 00 00 00 00 00 00 0d 50 00 |......@.......P.|
+000026a0 00 00 00 00 00 0d 60 00 00 00 00 00 00 0d 70 00 |......`.......p.|
+000026b0 00 00 00 00 00 0d 80 00 00 00 00 00 00 0d 90 00 |................|
+000026c0 00 00 00 00 00 0d a0 00 00 00 00 00 00 0d b0 00 |................|
+000026d0 00 00 00 00 00 0d c0 00 00 00 00 00 00 0d d0 00 |................|
+000026e0 00 00 00 00 00 0d e0 00 00 00 00 00 00 0d f0 00 |................|
+000026f0 00 00 00 00 00 0e 00 00 00 00 00 00 00 0e 10 00 |................|
+00002700 00 00 00 00 00 0e 20 00 00 00 00 00 00 0e 30 00 |...... .......0.|
+00002710 00 00 00 00 00 0e 40 00 00 00 00 00 00 0e 50 00 |......@.......P.|
+00002720 00 00 00 00 00 0e 60 00 00 00 00 00 00 0e 70 00 |......`.......p.|
+00002730 00 00 00 00 00 0e 80 00 00 00 00 00 00 0e 90 00 |................|
+00002740 00 00 00 00 00 0e a0 00 00 00 00 00 00 0e b0 00 |................|
+00002750 00 00 00 00 00 0e c0 00 00 00 00 00 00 0e d0 00 |................|
+00002760 00 00 00 00 00 0e e0 00 00 00 00 00 00 0e f0 00 |................|
+00002770 00 00 00 00 00 0f 00 00 00 00 00 00 00 0f 10 00 |................|
+00002780 00 00 00 00 00 0f 20 00 00 00 00 00 00 0f 30 00 |...... .......0.|
+00002790 00 00 00 00 00 0f 40 00 00 00 00 00 00 0f 50 00 |......@.......P.|
+000027a0 00 00 00 00 00 0f 60 00 00 00 00 00 00 0f 70 00 |......`.......p.|
+000027b0 00 00 00 00 00 0f 80 00 00 00 00 00 00 0f 90 00 |................|
+000027c0 00 00 00 00 00 0f a0 00 00 00 00 00 00 0f b0 00 |................|
+000027d0 00 00 00 00 00 0f c0 00 00 00 00 00 00 0f d0 00 |................|
+000027e0 00 00 00 00 00 0f e0 00 00 00 00 00 00 0f f0 00 |................|
+000027f0 00 00 00 00 00 10 00 00 00 00 00 00 00 10 10 00 |................|
+00002800 00 00 00 00 00 10 20 00 00 00 00 00 00 10 30 00 |...... .......0.|
+00002810 00 00 00 00 00 10 40 00 00 00 00 00 00 10 50 00 |......@.......P.|
+00002820 00 00 00 00 00 10 60 00 00 00 00 00 00 10 70 00 |......`.......p.|
+00002830 00 00 00 00 00 10 80 00 00 00 00 00 00 10 90 00 |................|
+00002840 00 00 00 00 00 10 a0 00 00 00 00 00 00 10 b0 00 |................|
+00002850 00 00 00 00 00 10 c0 00 00 00 00 00 00 10 d0 00 |................|
+00002860 00 00 00 00 00 10 e0 00 00 00 00 00 00 10 f0 00 |................|
+00002870 00 00 00 00 00 11 00 00 00 00 00 00 00 11 10 00 |................|
+00002880 00 00 00 00 00 11 20 00 00 00 00 00 00 11 30 00 |...... .......0.|
+00002890 00 00 00 00 00 11 40 00 00 00 00 00 00 11 50 00 |......@.......P.|
+000028a0 00 00 00 00 00 11 60 00 00 00 00 00 00 11 70 00 |......`.......p.|
+000028b0 00 00 00 00 00 11 80 00 00 00 00 00 00 11 90 00 |................|
+000028c0 00 00 00 00 00 11 a0 00 00 00 00 00 00 11 b0 00 |................|
+000028d0 00 00 00 00 00 11 c0 00 00 00 00 00 00 11 d0 00 |................|
+000028e0 00 00 00 00 00 11 e0 00 00 00 00 00 00 11 f0 00 |................|
+000028f0 00 00 00 00 00 12 00 00 00 00 00 00 00 12 10 00 |................|
+00002900 00 00 00 00 00 12 20 00 00 00 00 00 00 12 30 00 |...... .......0.|
+00002910 00 00 00 00 00 12 40 00 00 00 00 00 00 12 50 00 |......@.......P.|
+00002920 00 00 00 00 00 12 60 00 00 00 00 00 00 12 70 00 |......`.......p.|
+00002930 00 00 00 00 00 12 80 00 00 00 00 00 00 12 90 00 |................|
+00002940 00 00 00 00 00 12 a0 00 00 00 00 00 00 12 b0 00 |................|
+00002950 00 00 00 00 00 12 c0 00 00 00 00 00 00 12 d0 00 |................|
+00002960 00 00 00 00 00 12 e0 00 00 00 00 00 00 12 f0 00 |................|
+00002970 00 00 00 00 00 13 00 00 00 00 00 00 00 13 10 00 |................|
+00002980 00 00 00 00 00 13 20 00 00 00 00 00 00 13 30 00 |...... .......0.|
+00002990 00 00 00 00 00 13 40 00 00 00 00 00 00 13 50 00 |......@.......P.|
+000029a0 00 00 00 00 00 13 60 00 00 00 00 00 00 13 70 00 |......`.......p.|
+000029b0 00 00 00 00 00 13 80 00 00 00 00 00 00 13 90 00 |................|
+000029c0 00 00 00 00 00 13 a0 00 00 00 00 00 00 13 b0 00 |................|
+000029d0 00 00 00 00 00 13 c0 00 00 00 00 00 00 13 d0 00 |................|
+000029e0 00 00 00 00 00 13 e0 00 00 00 00 00 00 13 f0 00 |................|
+000029f0 00 00 00 00 00 14 00 00 00 00 00 00 00 14 10 00 |................|
+00002a00 00 00 00 00 00 14 20 00 00 00 00 00 00 14 30 00 |...... .......0.|
+00002a10 00 00 00 00 00 14 40 00 00 00 00 00 00 14 50 00 |......@.......P.|
+00002a20 00 00 00 00 00 14 60 00 00 00 00 00 00 14 70 00 |......`.......p.|
+00002a30 00 00 00 00 00 14 80 00 00 00 00 00 00 14 90 00 |................|
+00002a40 00 00 00 00 00 14 a0 00 00 00 00 00 00 14 b0 00 |................|
+00002a50 00 00 00 00 00 14 c0 00 00 00 00 00 00 14 d0 00 |................|
+00002a60 00 00 00 00 00 14 e0 00 00 00 00 00 00 14 f0 00 |................|
+00002a70 00 00 00 00 00 15 00 00 00 00 00 00 00 15 10 00 |................|
+00002a80 00 00 00 00 00 15 20 00 00 00 00 00 00 15 30 00 |...... .......0.|
+00002a90 00 00 00 00 00 15 40 00 00 00 00 00 00 15 50 00 |......@.......P.|
+00002aa0 00 00 00 00 00 15 60 00 00 00 00 00 00 15 70 00 |......`.......p.|
+00002ab0 00 00 00 00 00 15 80 00 00 00 00 00 00 15 90 00 |................|
+00002ac0 00 00 00 00 00 15 a0 00 00 00 00 00 00 15 b0 00 |................|
+00002ad0 00 00 00 00 00 15 c0 00 00 00 00 00 00 15 d0 00 |................|
+00002ae0 00 00 00 00 00 15 e0 00 00 00 00 00 00 15 f0 00 |................|
+00002af0 00 00 00 00 00 16 00 00 00 00 00 00 00 16 10 00 |................|
+00002b00 00 00 00 00 00 16 20 00 00 00 00 00 00 16 30 00 |...... .......0.|
+00002b10 00 00 00 00 00 16 40 00 00 00 00 00 00 16 50 00 |......@.......P.|
+00002b20 00 00 00 00 00 16 60 00 00 00 00 00 00 16 70 00 |......`.......p.|
+00002b30 00 00 00 00 00 16 80 00 00 00 00 00 00 16 90 00 |................|
+00002b40 00 00 00 00 00 16 a0 00 00 00 00 00 00 16 b0 00 |................|
+00002b50 00 00 00 00 00 16 c0 00 00 00 00 00 00 16 d0 00 |................|
+00002b60 00 00 00 00 00 16 e0 00 00 00 00 00 00 16 f0 00 |................|
+00002b70 00 00 00 00 00 17 00 00 00 00 00 00 00 17 10 00 |................|
+00002b80 00 00 00 00 00 17 20 00 00 00 00 00 00 17 30 00 |...... .......0.|
+00002b90 00 00 00 00 00 17 40 00 00 00 00 00 00 17 50 00 |......@.......P.|
+00002ba0 00 00 00 00 00 17 60 00 00 00 00 00 00 17 70 00 |......`.......p.|
+00002bb0 00 00 00 00 00 17 80 00 00 00 00 00 00 17 90 00 |................|
+00002bc0 00 00 00 00 00 17 a0 00 00 00 00 00 00 17 b0 00 |................|
+00002bd0 00 00 00 00 00 17 c0 00 00 00 00 00 00 17 d0 00 |................|
+00002be0 00 00 00 00 00 17 e0 00 00 00 00 00 00 17 f0 00 |................|
+00002bf0 00 00 00 00 00 18 00 00 00 00 00 00 00 18 10 00 |................|
+00002c00 00 00 00 00 00 18 20 00 00 00 00 00 00 18 30 00 |...... .......0.|
+00002c10 00 00 00 00 00 18 40 00 00 00 00 00 00 18 50 00 |......@.......P.|
+00002c20 00 00 00 00 00 18 60 00 00 00 00 00 00 18 70 00 |......`.......p.|
+00002c30 00 00 00 00 00 18 80 00 00 00 00 00 00 18 90 00 |................|
+00002c40 00 00 00 00 00 18 a0 00 00 00 00 00 00 18 b0 00 |................|
+00002c50 00 00 00 00 00 18 c0 00 00 00 00 00 00 18 d0 00 |................|
+00002c60 00 00 00 00 00 18 e0 00 00 00 00 00 00 18 f0 00 |................|
+00002c70 00 00 00 00 00 19 00 00 00 00 00 00 00 19 10 00 |................|
+00002c80 00 00 00 00 00 19 20 00 00 00 00 00 00 19 30 00 |...... .......0.|
+00002c90 00 00 00 00 00 19 40 00 00 00 00 00 00 19 50 00 |......@.......P.|
+00002ca0 00 00 00 00 00 19 60 00 00 00 00 00 00 19 70 00 |......`.......p.|
+00002cb0 00 00 00 00 00 19 80 00 00 00 00 00 00 19 90 00 |................|
+00002cc0 00 00 00 00 00 19 a0 00 00 00 00 00 00 19 b0 00 |................|
+00002cd0 00 00 00 00 00 19 c0 00 00 00 00 00 00 19 d0 00 |................|
+00002ce0 00 00 00 00 00 19 e0 00 00 00 00 00 00 19 f0 00 |................|
+00002cf0 00 00 00 00 00 1a 00 00 00 00 00 00 00 1a 10 00 |................|
+00002d00 00 00 00 00 00 1a 20 00 00 00 00 00 00 1a 30 00 |...... .......0.|
+00002d10 00 00 00 00 00 1a 40 00 00 00 00 00 00 1a 50 00 |......@.......P.|
+00002d20 00 00 00 00 00 1a 60 00 00 00 00 00 00 1a 70 00 |......`.......p.|
+00002d30 00 00 00 00 00 1a 80 00 00 00 00 00 00 1a 90 00 |................|
+00002d40 00 00 00 00 00 1a a0 00 00 00 00 00 00 1a b0 00 |................|
+00002d50 00 00 00 00 00 1a c0 00 00 00 00 00 00 1a d0 00 |................|
+00002d60 00 00 00 00 00 1a e0 00 00 00 00 00 00 1a f0 00 |................|
+00002d70 00 00 00 00 00 1b 00 00 00 00 00 00 00 1b 10 00 |................|
+00002d80 00 00 00 00 00 1b 20 00 00 00 00 00 00 1b 30 00 |...... .......0.|
+00002d90 00 00 00 00 00 1b 40 00 00 00 00 00 00 1b 50 00 |......@.......P.|
+00002da0 00 00 00 00 00 1b 60 00 00 00 00 00 00 1b 70 00 |......`.......p.|
+00002db0 00 00 00 00 00 1b 80 00 00 00 00 00 00 1b 90 00 |................|
+00002dc0 00 00 00 00 00 1b a0 00 00 00 00 00 00 1b b0 00 |................|
+00002dd0 00 00 00 00 00 1b c0 00 00 00 00 00 00 1b d0 00 |................|
+00002de0 00 00 00 00 00 1b e0 00 00 00 00 00 00 1b f0 00 |................|
+00002df0 00 00 00 00 00 1c 00 00 00 00 00 00 00 1c 10 00 |................|
+00002e00 00 00 00 00 00 1c 20 00 00 00 00 00 00 1c 30 00 |...... .......0.|
+00002e10 00 00 00 00 00 1c 40 00 00 00 00 00 00 1c 50 00 |......@.......P.|
+00002e20 00 00 00 00 00 1c 60 00 00 00 00 00 00 1c 70 00 |......`.......p.|
+00002e30 00 00 00 00 00 1c 80 00 00 00 00 00 00 1c 90 00 |................|
+00002e40 00 00 00 00 00 1c a0 00 00 00 00 00 00 1c b0 00 |................|
+00002e50 00 00 00 00 00 1c c0 00 00 00 00 00 00 1c d0 00 |................|
+00002e60 00 00 00 00 00 1c e0 00 00 00 00 00 00 1c f0 00 |................|
+00002e70 00 00 00 00 00 1d 00 00 00 00 00 00 00 1d 10 00 |................|
+00002e80 00 00 00 00 00 1d 20 00 00 00 00 00 00 1d 30 00 |...... .......0.|
+00002e90 00 00 00 00 00 1d 40 00 00 00 00 00 00 1d 50 00 |......@.......P.|
+00002ea0 00 00 00 00 00 1d 60 00 00 00 00 00 00 1d 70 00 |......`.......p.|
+00002eb0 00 00 00 00 00 1d 80 00 00 00 00 00 00 1d 90 00 |................|
+00002ec0 00 00 00 00 00 1d a0 00 00 00 00 00 00 1d b0 00 |................|
+00002ed0 00 00 00 00 00 1d c0 00 00 00 00 00 00 1d d0 00 |................|
+00002ee0 00 00 00 00 00 1d e0 00 00 00 00 00 00 1d f0 00 |................|
+00002ef0 00 00 00 00 00 1e 00 00 00 00 00 00 00 1e 10 00 |................|
+00002f00 00 00 00 00 00 1e 20 00 00 00 00 00 00 1e 30 00 |...... .......0.|
+00002f10 00 00 00 00 00 1e 40 00 00 00 00 00 00 1e 50 00 |......@.......P.|
+00002f20 00 00 00 00 00 1e 60 00 00 00 00 00 00 1e 70 00 |......`.......p.|
+00002f30 00 00 00 00 00 1e 80 00 00 00 00 00 00 1e 90 00 |................|
+00002f40 00 00 00 00 00 1e a0 00 00 00 00 00 00 1e b0 00 |................|
+00002f50 00 00 00 00 00 1e c0 00 00 00 00 00 00 1e d0 00 |................|
+00002f60 00 00 00 00 00 1e e0 00 00 00 00 00 00 1e f0 00 |................|
+00002f70 00 00 00 00 00 1f 00 00 00 00 00 00 00 1f 10 00 |................|
+00002f80 00 00 00 00 00 1f 20 00 00 00 00 00 00 1f 30 00 |...... .......0.|
+00002f90 00 00 00 00 00 1f 40 00 00 00 00 00 00 1f 50 00 |......@.......P.|
+00002fa0 00 00 00 00 00 1f 60 00 00 00 00 00 00 1f 70 00 |......`.......p.|
+00002fb0 00 00 00 00 00 1f 80 00 00 00 00 00 00 1f 90 00 |................|
+00002fc0 00 00 00 00 00 1f a0 00 00 00 00 00 00 1f b0 00 |................|
+00002fd0 00 00 00 00 00 1f c0 00 00 00 00 00 00 1f d0 00 |................|
+00002fe0 00 00 00 00 00 1f e0 00 00 00 00 00 00 1f f0 00 |................|
+00002ff0 00 00 00 00 00 20 00 00 00 00 00 00 00 20 10 00 |..... ....... ..|
+00003000 00 00 00 00 00 20 20 00 00 00 00 00 00 20 30 00 |..... ...... 0.|
+00003010 00 00 00 00 00 20 40 00 00 00 00 00 00 20 50 00 |..... @...... P.|
+00003020 00 00 00 00 00 20 60 00 00 00 00 00 00 20 70 00 |..... `...... p.|
+00003030 00 00 00 00 00 20 80 00 00 00 00 00 00 20 90 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 a0 00 00 00 00 00 00 20 b0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 c0 00 00 00 00 00 00 20 d0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 e0 00 00 00 00 00 00 20 f0 00 |..... ....... ..|
+00003070 00 00 00 00 00 21 00 00 00 00 00 00 00 21 10 00 |.....!.......!..|
+00003080 00 00 00 00 00 21 20 00 00 00 00 00 00 21 30 00 |.....! ......!0.|
+00003090 00 00 00 00 00 21 40 00 00 00 00 00 00 21 50 00 |.....!@......!P.|
+000030a0 00 00 00 00 00 21 60 00 00 00 00 00 00 21 70 00 |.....!`......!p.|
+000030b0 00 00 00 00 00 21 80 00 00 00 00 00 00 21 90 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 a0 00 00 00 00 00 00 21 b0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 c0 00 00 00 00 00 00 21 d0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 e0 00 00 00 00 00 00 21 f0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 22 00 00 00 00 00 00 00 22 10 00 |....."......."..|
+00003100 00 00 00 00 00 22 20 00 00 00 00 00 00 22 30 00 |....." ......"0.|
+00003110 00 00 00 00 00 22 40 00 00 00 00 00 00 22 50 00 |....."@......"P.|
+00003120 00 00 00 00 00 22 60 00 00 00 00 00 00 22 70 00 |....."`......"p.|
+00003130 00 00 00 00 00 22 80 00 00 00 00 00 00 22 90 00 |....."......."..|
+00003140 00 00 00 00 00 22 a0 00 00 00 00 00 00 22 b0 00 |....."......."..|
+00003150 00 00 00 00 00 22 c0 00 00 00 00 00 00 22 d0 00 |....."......."..|
+00003160 00 00 00 00 00 22 e0 00 00 00 00 00 00 22 f0 00 |....."......."..|
+00003170 00 00 00 00 00 23 00 00 00 00 00 00 00 23 10 00 |.....#.......#..|
+00003180 00 00 00 00 00 23 20 00 00 00 00 00 00 23 30 00 |.....# ......#0.|
+00003190 00 00 00 00 00 23 40 00 00 00 00 00 00 23 50 00 |.....#@......#P.|
+000031a0 00 00 00 00 00 23 60 00 00 00 00 00 00 23 70 00 |.....#`......#p.|
+000031b0 00 00 00 00 00 23 80 00 00 00 00 00 00 23 90 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 a0 00 00 00 00 00 00 23 b0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 c0 00 00 00 00 00 00 23 d0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 e0 00 00 00 00 00 00 23 f0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 24 00 00 00 00 00 00 00 24 10 00 |.....$.......$..|
+00003200 00 00 00 00 00 24 20 00 00 00 00 00 00 24 30 00 |.....$ ......$0.|
+00003210 00 00 00 00 00 24 40 00 00 00 00 00 00 24 50 00 |.....$@......$P.|
+00003220 00 00 00 00 00 24 60 00 00 00 00 00 00 24 70 00 |.....$`......$p.|
+00003230 00 00 00 00 00 24 80 00 00 00 00 00 00 24 90 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 a0 00 00 00 00 00 00 24 b0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 c0 00 00 00 00 00 00 24 d0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 e0 00 00 00 00 00 00 24 f0 00 |.....$.......$..|
+00003270 00 00 00 00 00 25 00 00 00 00 00 00 00 25 10 00 |.....%.......%..|
+00003280 00 00 00 00 00 25 20 00 00 00 00 00 00 25 30 00 |.....% ......%0.|
+00003290 00 00 00 00 00 25 40 00 00 00 00 00 00 25 50 00 |.....%@......%P.|
+000032a0 00 00 00 00 00 25 60 00 00 00 00 00 00 25 70 00 |.....%`......%p.|
+000032b0 00 00 00 00 00 25 80 00 00 00 00 00 00 25 90 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 a0 00 00 00 00 00 00 25 b0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 c0 00 00 00 00 00 00 25 d0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 e0 00 00 00 00 00 00 25 f0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 26 00 00 00 00 00 00 00 26 10 00 |.....&.......&..|
+00003300 00 00 00 00 00 26 20 00 00 00 00 00 00 26 30 00 |.....& ......&0.|
+00003310 00 00 00 00 00 26 40 00 00 00 00 00 00 26 50 00 |.....&@......&P.|
+00003320 00 00 00 00 00 26 60 00 00 00 00 00 00 26 70 00 |.....&`......&p.|
+00003330 00 00 00 00 00 26 80 00 00 00 00 00 00 26 90 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 a0 00 00 00 00 00 00 26 b0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 c0 00 00 00 00 00 00 26 d0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 e0 00 00 00 00 00 00 26 f0 00 |.....&.......&..|
+00003370 00 00 00 00 00 27 00 00 00 00 00 00 00 27 10 00 |.....'.......'..|
+00003380 00 00 00 00 00 27 20 00 00 00 00 00 00 27 30 00 |.....' ......'0.|
+00003390 00 00 00 00 00 27 40 00 00 00 00 00 00 27 50 00 |.....'@......'P.|
+000033a0 00 00 00 00 00 27 60 00 00 00 00 00 00 27 70 00 |.....'`......'p.|
+000033b0 00 00 00 00 00 27 80 00 00 00 00 00 00 27 90 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 a0 00 00 00 00 00 00 27 b0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 c0 00 00 00 00 00 00 27 d0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 e0 00 00 00 00 00 00 27 f0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 28 00 00 00 00 00 00 00 28 10 00 |.....(.......(..|
+00003400 00 00 00 00 00 28 20 00 00 00 00 00 00 28 30 00 |.....( ......(0.|
+00003410 00 00 00 00 00 28 40 00 00 00 00 00 00 28 50 00 |.....(@......(P.|
+00003420 00 00 00 00 00 28 60 00 00 00 00 00 00 28 70 00 |.....(`......(p.|
+00003430 00 00 00 00 00 28 80 00 00 00 00 00 00 28 90 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 a0 00 00 00 00 00 00 28 b0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 c0 00 00 00 00 00 00 28 d0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 e0 00 00 00 00 00 00 28 f0 00 |.....(.......(..|
+00003470 00 00 00 00 00 29 00 00 00 00 00 00 00 29 10 00 |.....).......)..|
+00003480 00 00 00 00 00 29 20 00 00 00 00 00 00 29 30 00 |.....) ......)0.|
+00003490 00 00 00 00 00 29 40 00 00 00 00 00 00 29 50 00 |.....)@......)P.|
+000034a0 00 00 00 00 00 29 60 00 00 00 00 00 00 29 70 00 |.....)`......)p.|
+000034b0 00 00 00 00 00 29 80 00 00 00 00 00 00 29 90 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 a0 00 00 00 00 00 00 29 b0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 c0 00 00 00 00 00 00 29 d0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 e0 00 00 00 00 00 00 29 f0 00 |.....).......)..|
+000034f0 00 00 00 00 00 2a 00 00 00 00 00 00 00 2a 10 00 |.....*.......*..|
+00003500 00 00 00 00 00 2a 20 00 00 00 00 00 00 2a 30 00 |.....* ......*0.|
+00003510 00 00 00 00 00 2a 40 00 00 00 00 00 00 2a 50 00 |.....*@......*P.|
+00003520 00 00 00 00 00 2a 60 00 00 00 00 00 00 2a 70 00 |.....*`......*p.|
+00003530 00 00 00 00 00 2a 80 00 00 00 00 00 00 2a 90 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a a0 00 00 00 00 00 00 2a b0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a c0 00 00 00 00 00 00 2a d0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a e0 00 00 00 00 00 00 2a f0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2b 00 00 00 00 00 00 00 2b 10 00 |.....+.......+..|
+00003580 00 00 00 00 00 2b 20 00 00 00 00 00 00 2b 30 00 |.....+ ......+0.|
+00003590 00 00 00 00 00 2b 40 00 00 00 00 00 00 2b 50 00 |.....+@......+P.|
+000035a0 00 00 00 00 00 2b 60 00 00 00 00 00 00 2b 70 00 |.....+`......+p.|
+000035b0 00 00 00 00 00 2b 80 00 00 00 00 00 00 2b 90 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b a0 00 00 00 00 00 00 2b b0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b c0 00 00 00 00 00 00 2b d0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b e0 00 00 00 00 00 00 2b f0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2c 00 00 00 00 00 00 00 2c 10 00 |.....,.......,..|
+00003600 00 00 00 00 00 2c 20 00 00 00 00 00 00 2c 30 00 |....., ......,0.|
+00003610 00 00 00 00 00 2c 40 00 00 00 00 00 00 2c 50 00 |.....,@......,P.|
+00003620 00 00 00 00 00 2c 60 00 00 00 00 00 00 2c 70 00 |.....,`......,p.|
+00003630 00 00 00 00 00 2c 80 00 00 00 00 00 00 2c 90 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c a0 00 00 00 00 00 00 2c b0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c c0 00 00 00 00 00 00 2c d0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c e0 00 00 00 00 00 00 2c f0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2d 00 00 00 00 00 00 00 2d 10 00 |.....-.......-..|
+00003680 00 00 00 00 00 2d 20 00 00 00 00 00 00 2d 30 00 |.....- ......-0.|
+00003690 00 00 00 00 00 2d 40 00 00 00 00 00 00 2d 50 00 |.....-@......-P.|
+000036a0 00 00 00 00 00 2d 60 00 00 00 00 00 00 2d 70 00 |.....-`......-p.|
+000036b0 00 00 00 00 00 2d 80 00 00 00 00 00 00 2d 90 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d a0 00 00 00 00 00 00 2d b0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d c0 00 00 00 00 00 00 2d d0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d e0 00 00 00 00 00 00 2d f0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2e 00 00 00 00 00 00 00 2e 10 00 |................|
+00003700 00 00 00 00 00 2e 20 00 00 00 00 00 00 2e 30 00 |...... .......0.|
+00003710 00 00 00 00 00 2e 40 00 00 00 00 00 00 2e 50 00 |......@.......P.|
+00003720 00 00 00 00 00 2e 60 00 00 00 00 00 00 2e 70 00 |......`.......p.|
+00003730 00 00 00 00 00 2e 80 00 00 00 00 00 00 2e 90 00 |................|
+00003740 00 00 00 00 00 2e a0 00 00 00 00 00 00 2e b0 00 |................|
+00003750 00 00 00 00 00 2e c0 00 00 00 00 00 00 2e d0 00 |................|
+00003760 00 00 00 00 00 2e e0 00 00 00 00 00 00 2e f0 00 |................|
+00003770 00 00 00 00 00 2f 00 00 00 00 00 00 00 2f 10 00 |...../......./..|
+00003780 00 00 00 00 00 2f 20 00 00 00 00 00 00 2f 30 00 |...../ ....../0.|
+00003790 00 00 00 00 00 2f 40 00 00 00 00 00 00 2f 50 00 |...../@....../P.|
+000037a0 00 00 00 00 00 2f 60 00 00 00 00 00 00 2f 70 00 |...../`....../p.|
+000037b0 00 00 00 00 00 2f 80 00 00 00 00 00 00 2f 90 00 |...../......./..|
+000037c0 00 00 00 00 00 2f a0 00 00 00 00 00 00 2f b0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f c0 00 00 00 00 00 00 2f d0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f e0 00 00 00 00 00 00 2f f0 00 |...../......./..|
+000037f0 00 00 00 00 00 30 00 00 00 00 00 00 00 30 10 00 |.....0.......0..|
+00003800 00 00 00 00 00 30 20 00 00 00 00 00 00 30 30 00 |.....0 ......00.|
+00003810 00 00 00 00 00 30 40 00 00 00 00 00 00 30 50 00 |.....0@......0P.|
+00003820 00 00 00 00 00 30 60 00 00 00 00 00 00 30 70 00 |.....0`......0p.|
+00003830 00 00 00 00 00 30 80 00 00 00 00 00 00 30 90 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 a0 00 00 00 00 00 00 30 b0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 c0 00 00 00 00 00 00 30 d0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 e0 00 00 00 00 00 00 30 f0 00 |.....0.......0..|
+00003870 00 00 00 00 00 31 00 00 00 00 00 00 00 31 10 00 |.....1.......1..|
+00003880 00 00 00 00 00 31 20 00 00 00 00 00 00 31 30 00 |.....1 ......10.|
+00003890 00 00 00 00 00 31 40 00 00 00 00 00 00 31 50 00 |.....1@......1P.|
+000038a0 00 00 00 00 00 31 60 00 00 00 00 00 00 31 70 00 |.....1`......1p.|
+000038b0 00 00 00 00 00 31 80 00 00 00 00 00 00 31 90 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 a0 00 00 00 00 00 00 31 b0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 c0 00 00 00 00 00 00 31 d0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 e0 00 00 00 00 00 00 31 f0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 32 00 00 00 00 00 00 00 32 10 00 |.....2.......2..|
+00003900 00 00 00 00 00 32 20 00 00 00 00 00 00 32 30 00 |.....2 ......20.|
+00003910 00 00 00 00 00 32 40 00 00 00 00 00 00 32 50 00 |.....2@......2P.|
+00003920 00 00 00 00 00 32 60 00 00 00 00 00 00 32 70 00 |.....2`......2p.|
+00003930 00 00 00 00 00 32 80 00 00 00 00 00 00 32 90 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 a0 00 00 00 00 00 00 32 b0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 c0 00 00 00 00 00 00 32 d0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 e0 00 00 00 00 00 00 32 f0 00 |.....2.......2..|
+00003970 00 00 00 00 00 33 00 00 00 00 00 00 00 33 10 00 |.....3.......3..|
+00003980 00 00 00 00 00 33 20 00 00 00 00 00 00 33 30 00 |.....3 ......30.|
+00003990 00 00 00 00 00 33 40 00 00 00 00 00 00 33 50 00 |.....3@......3P.|
+000039a0 00 00 00 00 00 33 60 00 00 00 00 00 00 33 70 00 |.....3`......3p.|
+000039b0 00 00 00 00 00 33 80 00 00 00 00 00 00 33 90 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 a0 00 00 00 00 00 00 33 b0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 c0 00 00 00 00 00 00 33 d0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 e0 00 00 00 00 00 00 33 f0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 34 00 00 00 00 00 00 00 34 10 00 |.....4.......4..|
+00003a00 00 00 00 00 00 34 20 00 00 00 00 00 00 34 30 00 |.....4 ......40.|
+00003a10 00 00 00 00 00 34 40 00 00 00 00 00 00 34 50 00 |.....4@......4P.|
+00003a20 00 00 00 00 00 34 60 00 00 00 00 00 00 34 70 00 |.....4`......4p.|
+00003a30 00 00 00 00 00 34 80 00 00 00 00 00 00 34 90 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 a0 00 00 00 00 00 00 34 b0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 c0 00 00 00 00 00 00 34 d0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 e0 00 00 00 00 00 00 34 f0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 35 00 00 00 00 00 00 00 35 10 00 |.....5.......5..|
+00003a80 00 00 00 00 00 35 20 00 00 00 00 00 00 35 30 00 |.....5 ......50.|
+00003a90 00 00 00 00 00 35 40 00 00 00 00 00 00 35 50 00 |.....5@......5P.|
+00003aa0 00 00 00 00 00 35 60 00 00 00 00 00 00 35 70 00 |.....5`......5p.|
+00003ab0 00 00 00 00 00 35 80 00 00 00 00 00 00 35 90 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 a0 00 00 00 00 00 00 35 b0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 c0 00 00 00 00 00 00 35 d0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 e0 00 00 00 00 00 00 35 f0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 36 00 00 00 00 00 00 00 36 10 00 |.....6.......6..|
+00003b00 00 00 00 00 00 36 20 00 00 00 00 00 00 36 30 00 |.....6 ......60.|
+00003b10 00 00 00 00 00 36 40 00 00 00 00 00 00 36 50 00 |.....6@......6P.|
+00003b20 00 00 00 00 00 36 60 00 00 00 00 00 00 36 70 00 |.....6`......6p.|
+00003b30 00 00 00 00 00 36 80 00 00 00 00 00 00 36 90 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 a0 00 00 00 00 00 00 36 b0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 c0 00 00 00 00 00 00 36 d0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 e0 00 00 00 00 00 00 36 f0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 37 00 00 00 00 00 00 00 37 10 00 |.....7.......7..|
+00003b80 00 00 00 00 00 37 20 00 00 00 00 00 00 37 30 00 |.....7 ......70.|
+00003b90 00 00 00 00 00 37 40 00 00 00 00 00 00 37 50 00 |.....7@......7P.|
+00003ba0 00 00 00 00 00 37 60 00 00 00 00 00 00 37 70 00 |.....7`......7p.|
+00003bb0 00 00 00 00 00 37 80 00 00 00 00 00 00 37 90 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 a0 00 00 00 00 00 00 37 b0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 c0 00 00 00 00 00 00 37 d0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 e0 00 00 00 00 00 00 37 f0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 38 00 00 00 00 00 00 00 38 10 00 |.....8.......8..|
+00003c00 00 00 00 00 00 38 20 00 00 00 00 00 00 38 30 00 |.....8 ......80.|
+00003c10 00 00 00 00 00 38 40 00 00 00 00 00 00 38 50 00 |.....8@......8P.|
+00003c20 00 00 00 00 00 38 60 00 00 00 00 00 00 38 70 00 |.....8`......8p.|
+00003c30 00 00 00 00 00 38 80 00 00 00 00 00 00 38 90 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 a0 00 00 00 00 00 00 38 b0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 c0 00 00 00 00 00 00 38 d0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 e0 00 00 00 00 00 00 38 f0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 39 00 00 00 00 00 00 00 39 10 00 |.....9.......9..|
+00003c80 00 00 00 00 00 39 20 00 00 00 00 00 00 39 30 00 |.....9 ......90.|
+00003c90 00 00 00 00 00 39 40 00 00 00 00 00 00 39 50 00 |.....9@......9P.|
+00003ca0 00 00 00 00 00 39 60 00 00 00 00 00 00 39 70 00 |.....9`......9p.|
+00003cb0 00 00 00 00 00 39 80 00 00 00 00 00 00 39 90 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 a0 00 00 00 00 00 00 39 b0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 c0 00 00 00 00 00 00 39 d0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 e0 00 00 00 00 00 00 39 f0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 3a 00 00 00 00 00 00 00 3a 10 00 |.....:.......:..|
+00003d00 00 00 00 00 00 3a 20 00 00 00 00 00 00 3a 30 00 |.....: ......:0.|
+00003d10 00 00 00 00 00 3a 40 00 00 00 00 00 00 3a 50 00 |.....:@......:P.|
+00003d20 00 00 00 00 00 3a 60 00 00 00 00 00 00 3a 70 00 |.....:`......:p.|
+00003d30 00 00 00 00 00 3a 80 00 00 00 00 00 00 3a 90 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a a0 00 00 00 00 00 00 3a b0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a c0 00 00 00 00 00 00 3a d0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a e0 00 00 00 00 00 00 3a f0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3b 00 00 00 00 00 00 00 3b 10 00 |.....;.......;..|
+00003d80 00 00 00 00 00 3b 20 00 00 00 00 00 00 3b 30 00 |.....; ......;0.|
+00003d90 00 00 00 00 00 3b 40 00 00 00 00 00 00 3b 50 00 |.....;@......;P.|
+00003da0 00 00 00 00 00 3b 60 00 00 00 00 00 00 3b 70 00 |.....;`......;p.|
+00003db0 00 00 00 00 00 3b 80 00 00 00 00 00 00 3b 90 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b a0 00 00 00 00 00 00 3b b0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b c0 00 00 00 00 00 00 3b d0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b e0 00 00 00 00 00 00 3b f0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3c 00 00 00 00 00 00 00 3c 10 00 |.....<.......<..|
+00003e00 00 00 00 00 00 3c 20 00 00 00 00 00 00 3c 30 00 |.....< ......<0.|
+00003e10 00 00 00 00 00 3c 40 00 00 00 00 00 00 3c 50 00 |.....<@......<P.|
+00003e20 00 00 00 00 00 3c 60 00 00 00 00 00 00 3c 70 00 |.....<`......<p.|
+00003e30 00 00 00 00 00 3c 80 00 00 00 00 00 00 3c 90 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c a0 00 00 00 00 00 00 3c b0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c c0 00 00 00 00 00 00 3c d0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c e0 00 00 00 00 00 00 3c f0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3d 00 00 00 00 00 00 00 3d 10 00 |.....=.......=..|
+00003e80 00 00 00 00 00 3d 20 00 00 00 00 00 00 3d 30 00 |.....= ......=0.|
+00003e90 00 00 00 00 00 3d 40 00 00 00 00 00 00 3d 50 00 |.....=@......=P.|
+00003ea0 00 00 00 00 00 3d 60 00 00 00 00 00 00 3d 70 00 |.....=`......=p.|
+00003eb0 00 00 00 00 00 3d 80 00 00 00 00 00 00 3d 90 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d a0 00 00 00 00 00 00 3d b0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d c0 00 00 00 00 00 00 3d d0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d e0 00 00 00 00 00 00 3d f0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3e 00 00 00 00 00 00 00 3e 10 00 |.....>.......>..|
+00003f00 00 00 00 00 00 3e 20 00 00 00 00 00 00 3e 30 00 |.....> ......>0.|
+00003f10 00 00 00 00 00 3e 40 00 00 00 00 00 00 3e 50 00 |.....>@......>P.|
+00003f20 00 00 00 00 00 3e 60 00 00 00 00 00 00 3e 70 00 |.....>`......>p.|
+00003f30 00 00 00 00 00 3e 80 00 00 00 00 00 00 3e 90 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e a0 00 00 00 00 00 00 3e b0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e c0 00 00 00 00 00 00 3e d0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e e0 00 00 00 00 00 00 3e f0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3f 00 00 00 00 00 00 00 3f 10 00 |.....?.......?..|
+00003f80 00 00 00 00 00 3f 20 00 00 00 00 00 00 3f 30 00 |.....? ......?0.|
+00003f90 00 00 00 00 00 3f 40 00 00 00 00 00 00 3f 50 00 |.....?@......?P.|
+00003fa0 00 00 00 00 00 3f 60 00 00 00 00 00 00 3f 70 00 |.....?`......?p.|
+00003fb0 00 00 00 00 00 3f 80 00 00 00 00 00 00 3f 90 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f a0 00 00 00 00 00 00 3f b0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f c0 00 00 00 00 00 00 3f d0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f e0 00 00 00 00 00 00 3f f0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 40 00 00 00 00 00 00 00 40 10 00 |.....@.......@..|
+00004000 00 00 00 00 00 40 20 00 00 00 00 00 00 40 30 00 |.....@ ......@0.|
+00004010 00 00 00 00 00 40 40 00 00 00 00 00 00 40 50 00 |.....@@......@P.|
+00004020 00 00 00 00 00 40 60 00 00 00 00 00 00 00 00 00 |.....@`.........|
+00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004120 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004140 00 00 00 00 00 40 80 00 00 00 00 00 00 00 00 00 |.....@..........|
+00004150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000051c0 02 00 ee ff ff ff 01 00 00 00 47 21 00 00 00 00 |..........G!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00005210 b9 61 9d d5 00 00 00 00 01 00 00 00 00 00 00 00 |.a..............|
+00005220 47 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |G!......".......|
+00005230 26 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |&!..............|
+00005240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00005250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00005260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00005420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00005430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000054a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000054b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00407e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00407e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00407e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00407e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00407ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00407eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00408e10 af e3 04 05 00 00 00 00 47 21 00 00 00 00 00 00 |........G!......|
+00408e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00408e30 26 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |&!..............|
+00408e40 03 03 03 03 03 03 03 03 27 21 00 00 00 00 00 00 |........'!......|
+00408e50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00408e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.hex
new file mode 100644
index 000000000000..9a12f90cb5af
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.hex
@@ -0,0 +1,101 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 80 00 00 00 00 46 00 00 00 00 00 00 00 00 00 00 |.....F..........|
+00030220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000501c0 02 00 ee ff ff ff 01 00 00 00 7f 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00050210 f2 13 00 92 00 00 00 00 01 00 00 00 00 00 00 00 |................|
+00050220 7f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.!......".......|
+00050230 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+00050240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00050250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00050260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00050420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00050430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000504a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000504b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00054400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00454400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0046be20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+0046be30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0046bea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+0046beb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046fe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0046fe10 62 6b 07 b6 00 00 00 00 7f 21 00 00 00 00 00 00 |bk.......!......|
+0046fe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0046fe30 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+0046fe40 03 03 03 03 03 03 03 03 5f 21 00 00 00 00 00 00 |........_!......|
+0046fe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+0046fe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00470000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.hex
new file mode 100644
index 000000000000..b464168daaa4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.hex
@@ -0,0 +1,48 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 42 21 00 00 00 00 |..........B!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 a6 70 3a 54 00 00 00 00 01 00 00 00 00 00 00 00 |.p:T............|
+00000220 42 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |B!......".......|
+00000230 21 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |!!..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00424400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00424410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00424420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00424430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00424480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00424490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004244a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+004244b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00428400 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00428410 75 64 ec d2 00 00 00 00 42 21 00 00 00 00 00 00 |ud......B!......|
+00428420 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00428430 21 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |!!..............|
+00428440 03 03 03 03 03 03 03 03 22 21 00 00 00 00 00 00 |........"!......|
+00428450 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00428460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00428600
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.hex
new file mode 100644
index 000000000000..796166f430ee
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.hex
@@ -0,0 +1,80 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 f0 00 |....Wi2k.....B..|
+00000030 00 00 00 00 00 42 f0 00 00 7e 04 11 00 00 00 03 |.....B...~......|
+00000040 ff ff f5 cd 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00000050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+00000bc0 02 00 ee ff ff ff 01 00 00 00 77 21 00 00 00 00 |..........w!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000c10 9e bd 19 f8 00 00 00 00 01 00 00 00 00 00 00 00 |................|
+00000c20 77 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |w!......".......|
+00000c30 56 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |V!..............|
+00000c40 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000c50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00000ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00000eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042bc00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0042bc10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0042bc20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+0042bc30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042bc80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0042bc90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0042bca0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+0042bcb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042fc00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0042fc10 13 b5 e2 3e 00 00 00 00 77 21 00 00 00 00 00 00 |...>....w!......|
+0042fc20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0042fc30 56 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |V!..............|
+0042fc40 03 03 03 03 03 03 03 03 57 21 00 00 00 00 00 00 |........W!......|
+0042fc50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+0042fc60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 f0 00 |....Wi2k.....B..|
+00600e30 00 00 00 00 00 42 f0 00 00 7e 04 11 00 00 00 03 |.....B...~......|
+00600e40 ff ff f5 cd 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00600e50 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.hex
new file mode 100644
index 000000000000..93b291550be0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.hex
@@ -0,0 +1,56 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 4b c0 ef 60 00 00 00 00 01 00 00 00 00 00 00 00 |K..`............|
+00000220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00000230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+004fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+004fbe20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+004fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+004fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004fbea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+004fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+004ffe10 25 cf c4 18 00 00 00 00 ff 27 00 00 00 00 00 00 |%........'......|
+004ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+004ffe30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+004ffe40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+004ffe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+004ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef 84 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00500050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdx.hex
new file mode 100644
index 000000000000..1aef760fa90a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdx.hex
@@ -0,0 +1,99 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+004001c0 02 00 ee ff ff ff 01 00 00 00 ff 7f 00 00 00 00 |................|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00400210 76 87 2e 0d 00 00 00 00 01 00 00 00 00 00 00 00 |v...............|
+00400220 ff 7f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00400230 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+00400240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00400250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00400260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00400420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00400430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+004004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00404400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00804400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+013fbe20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+013fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+013fbea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+013fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+013ffe10 c8 d6 d8 f4 00 00 00 00 ff 7f 00 00 00 00 00 00 |................|
+013ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+013ffe30 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+013ffe40 03 03 03 03 03 03 03 03 df 7f 00 00 00 00 00 00 |................|
+013ffe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+013ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.hex
new file mode 100644
index 000000000000..51da710db535
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.hex
@@ -0,0 +1,348 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00000610 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00000620 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00000630 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00000640 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00000650 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00000660 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00000670 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00000680 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00000690 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000006a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000006b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000006c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000006d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000006e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000006f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00000700 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00000710 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00000720 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00000730 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00000740 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00000750 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00000760 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00000770 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00000780 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00000790 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000007a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000007b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000007c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000007d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000007e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000007f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00000800 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00000810 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00000820 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00000830 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00000840 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00000850 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00000860 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00000870 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00000880 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00000890 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+000008a0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+000008b0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+000008c0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+000008d0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+000008e0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+000008f0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00000900 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00000910 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00000920 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00000930 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00000940 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00000950 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00000960 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00000970 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00000980 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00000990 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+000009a0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+000009b0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+000009c0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+000009d0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+000009e0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+000009f0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00000a00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00000a10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00000a20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00000a30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00000a40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00000a50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00000a60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00000a70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00000a80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00000a90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00000aa0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00000ab0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00000ac0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00000ad0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00000ae0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00000af0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00000b00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00000b10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00000b20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00000b30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00000b40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00000b50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00000b60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00000b70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00000b80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00000b90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00000ba0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00000bb0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00000bc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00000bd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00000be0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00000bf0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00000c00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00000c10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00000c20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00000c30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00000c40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00000c50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00000c60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00000c70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00000c80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00000c90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00000ca0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00000cb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00000cc0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00000cd0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00000ce0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00000cf0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00000d00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00000d10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00000d20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00000d30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00000d40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00000d50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00000d60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00000d70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00000d80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00000d90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00000da0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00000db0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00000dc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00000dd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00000de0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00000df0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00000e00 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000ff0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00001810 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00001820 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00001830 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00001840 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00001850 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00001860 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00001870 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00001880 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00001890 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000018a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000018b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000018c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000018d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000018e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000018f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00001900 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00001910 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00001920 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00001930 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00001940 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00001950 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00001960 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00001970 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00001980 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00001990 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000019a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000019b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000019c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000019d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000019e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000019f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00001a00 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00001a10 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00001a20 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00001a30 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00001a40 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00001a50 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00001a60 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00001a70 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00001a80 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00001a90 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+00001aa0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+00001ab0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+00001ac0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+00001ad0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+00001ae0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+00001af0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00001b00 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00001b10 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00001b20 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00001b30 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00001b40 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00001b50 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00001b60 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00001b70 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00001b80 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00001b90 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+00001ba0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+00001bb0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+00001bc0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+00001bd0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+00001be0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+00001bf0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00001c00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00001c10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00001c20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00001c30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00001c40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00001c50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00001c60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00001c70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00001c80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00001c90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00001ca0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00001cb0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00001cc0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00001cd0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00001ce0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00001cf0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00001d00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00001d10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00001d20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00001d30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00001d40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00001d50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00001d60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00001d70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00001d80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00001d90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00001da0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00001db0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00001dc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00001dd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00001de0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00001df0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00001e00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00001e10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00001e20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00001e30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00001e40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00001e50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00001e60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00001e70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00001e80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00001e90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00001ea0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00001eb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00001ec0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00001ed0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00001ee0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00001ef0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00001f00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00001f10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00001f20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00001f30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00001f40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00001f50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00001f60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00001f70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00001f80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00001f90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00001fa0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00001fb0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00001fc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00001fd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00001fe0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00001ff0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00002000 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000021f0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00002200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000041c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00004210 4b c0 ef 60 00 00 00 00 01 00 00 00 00 00 00 00 |K..`............|
+00004220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00004230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00004240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00004250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00004260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00004420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00004430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000044a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000044b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00409e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00409e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00409ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00409eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040be00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0040be10 25 cf c4 18 00 00 00 00 ff 27 00 00 00 00 00 00 |%........'......|
+0040be20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0040be30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+0040be40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+0040be50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+0040be60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040c000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.hex
new file mode 100644
index 000000000000..c55a803e281f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.hex
@@ -0,0 +1,555 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 30 00 |.............B0.|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000051c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00005430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00005440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00005490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000054a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000054b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000054c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.hex
new file mode 100644
index 000000000000..21f5d3c3735e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.hex
@@ -0,0 +1,82 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000501c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00050430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00050440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00050490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000504a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000504b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000504c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.hex
new file mode 100644
index 000000000000..b1a896b30c14
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.hex
@@ -0,0 +1,30 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00422200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.hex
new file mode 100644
index 000000000000..b16328b04dba
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.hex
@@ -0,0 +1,62 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00000030 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00000040 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 03 |................|
+00000220 00 20 00 00 ff ff f4 74 00 00 00 00 00 00 00 00 |. .....t........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+00000bc0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000e00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000e20 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000e30 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000e40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000e50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000e90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ea0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000eb0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+00000ec0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000f10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000f20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00403000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00600e10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00600e20 00 02 00 00 57 69 32 6b 00 00 00 00 00 42 68 00 |....Wi2k.....Bh.|
+00600e30 00 00 00 00 00 42 68 00 00 7d 04 11 00 00 00 03 |.....Bh..}......|
+00600e40 ff ff f7 0e 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00600e50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00600e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00601000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.hex
new file mode 100644
index 000000000000..faf6057fccb0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.hex
@@ -0,0 +1,38 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00000430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00000440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00000490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00500010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00500020 00 02 00 00 57 69 32 6b 00 00 00 00 00 50 00 00 |....Wi2k.....P..|
+00500030 00 00 00 00 00 50 00 00 00 96 04 11 00 00 00 02 |.....P..........|
+00500040 ff ff ef b4 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00500050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00500060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00500200
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdx.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdx.hex
new file mode 100644
index 000000000000..06bbcc4e3678
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdx.hex
@@ -0,0 +1,81 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+004001c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00400430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00400440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00400490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004004a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004004b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+004004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.hex b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.hex
new file mode 100644
index 000000000000..f5e2a17ae763
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.hex
@@ -0,0 +1,324 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 30 32 34 30 22 0a 64 64 62 2e 67 65 6f | "10240".ddb.geo|
+000002e0 6d 65 74 72 79 2e 68 65 61 64 73 20 3d 20 22 31 |metry.heads = "1|
+000002f0 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 |".ddb.geometry.s|
+00000300 65 63 74 6f 72 73 20 3d 20 22 31 22 0a 00 00 00 |ectors = "1"....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 30 20 00 00 00 00 00 00 00 00 00 00 | ..0 ..........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 ff |B.B.B.B.B.B.B...|
+000041c0 ff ff a5 ff ff ff 01 00 00 00 10 21 00 00 00 00 |...........!....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004400 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004420 00 00 00 00 00 00 00 00 00 02 00 00 01 00 00 00 |................|
+00004430 01 00 00 00 10 21 00 00 01 00 00 00 10 21 00 00 |.....!.......!..|
+00004440 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 00 00 00 00 57 45 56 82 0f 0c 08 00 00 20 00 00 |....WEV...... ..|
+00004490 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000044a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000044b0 01 00 00 00 10 21 00 00 00 00 00 00 00 00 00 00 |.....!..........|
+000044c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004510 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004520 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.hex
new file mode 100644
index 000000000000..70f7bc9ca1c3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.hex
@@ -0,0 +1,549 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 10 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00005010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00005210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00005220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00005240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00005440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00005610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00005640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.hex
new file mode 100644
index 000000000000..e851208bfa0c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.hex
@@ -0,0 +1,79 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 45 52 02 00 00 00 21 80 00 00 00 00 00 00 00 00 |ER....!.........|
+00050010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00050210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00050220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00050240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00050440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00050610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00050640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00051000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00451000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.hex
new file mode 100644
index 000000000000..b0c234ff00da
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.hex
@@ -0,0 +1,27 @@
+00000000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00421000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.hex
new file mode 100644
index 000000000000..6d2972ab132c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.hex
@@ -0,0 +1,59 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 45 52 02 00 00 00 3e c1 00 00 00 00 00 00 00 00 |ER....>.........|
+00000a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c00 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000c10 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000c20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c30 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000c40 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e30 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000e40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001030 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628c00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00628c10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00628c20 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00628c30 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00628c40 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00628c50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00628c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628e00
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.hex
new file mode 100644
index 000000000000..d61802fad5dc
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.hex
@@ -0,0 +1,35 @@
+00000000 45 52 02 00 00 00 40 00 00 00 00 00 00 00 00 00 |ER....@.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee c0 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00800050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdx.hex
new file mode 100644
index 000000000000..fc421fe31724
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdx.hex
@@ -0,0 +1,78 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 45 52 02 00 00 00 80 00 00 00 00 00 00 00 00 00 |ER..............|
+00400010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00400210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00400220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00400240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00400440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00400610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00400640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00401000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00801000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.hex
new file mode 100644
index 000000000000..d8fb290528c3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.hex
@@ -0,0 +1,321 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 30 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "0".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00004210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00004220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00004240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 4d 00 00 00 00 00 03 00 00 00 08 00 00 20 00 |PM............ .|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00004440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004600 50 4d 00 00 00 00 00 03 00 00 20 08 00 00 01 00 |PM........ .....|
+00004610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00004640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.hex
new file mode 100644
index 000000000000..28e796e95133
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.hex
@@ -0,0 +1,545 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7d 90 00 |.............}..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00005230 ff 00 00 00 01 00 00 00 c1 3e 00 00 c8 3e 00 00 |.........>...>..|
+00005240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00005290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000052a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000052b0 01 00 00 00 c8 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000052c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.hex
new file mode 100644
index 000000000000..e6b97d1b701e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.hex
@@ -0,0 +1,75 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00050230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 3f 00 00 |.........>...?..|
+00050240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00050290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000502a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000502b0 01 00 00 00 00 3f 00 00 00 00 00 00 00 00 00 00 |.....?..........|
+000502c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.hex
new file mode 100644
index 000000000000..0ce1218cbd23
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.hex
@@ -0,0 +1,23 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000230 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d8200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.hex
new file mode 100644
index 000000000000..df70c0401fec
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.hex
@@ -0,0 +1,55 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000c00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000c30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00000c40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000c90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ca0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000cb0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00000cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000d10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000d20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628c00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00628c10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00628c20 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00628c30 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00628c40 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00628c50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00628c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628e00
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.hex
new file mode 100644
index 000000000000..7f9365ff4dc9
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.hex
@@ -0,0 +1,31 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 40 00 00 |.........>...@..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee c0 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00800050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdx.hex
new file mode 100644
index 000000000000..9325656b2372
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdx.hex
@@ -0,0 +1,74 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00400230 ff 00 00 00 02 00 00 00 c1 3e 00 00 00 80 00 00 |.........>......|
+00400240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400280 00 00 00 00 57 45 56 82 1d 13 08 00 00 20 00 00 |....WEV...... ..|
+00400290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004002b0 01 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 |................|
+004002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.hex
new file mode 100644
index 000000000000..76d6c3deb309
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.hex
@@ -0,0 +1,315 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00004230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 40 00 00 |.........>...@..|
+00004240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00004290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000042a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000042b0 01 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
+000042c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.hex
new file mode 100644
index 000000000000..9de588957fb1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.hex
@@ -0,0 +1,558 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002040 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002050 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002060 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002070 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002080 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002090 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+000020a0 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020b0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020c0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020d0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020e0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020f0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+00002100 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002110 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002120 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002130 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002140 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002150 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002160 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002170 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002180 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002190 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+000021a0 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021b0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021c0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021d0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021e0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021f0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+00002200 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002210 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002220 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002230 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002240 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002250 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002260 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002270 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002280 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002290 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+000022a0 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022b0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022c0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022d0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022e0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022f0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+00002300 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002310 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002320 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002330 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002340 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002350 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002360 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002370 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002380 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002390 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+000023a0 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023b0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023c0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023d0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023e0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023f0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+00002400 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002410 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002420 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002430 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002440 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002450 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002460 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002470 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002480 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002490 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+000024a0 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024b0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024c0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024d0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024e0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024f0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+00002500 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002510 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002520 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002530 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002540 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002550 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002560 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002570 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002580 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002590 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+000025a0 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025b0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025c0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025d0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025e0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025f0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+00002600 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002610 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002620 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002630 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002640 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002650 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002660 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002670 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002680 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002690 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+000026a0 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026b0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026c0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026d0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026e0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026f0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+00002700 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002710 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002720 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002730 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002740 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002750 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002760 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002770 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002780 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002790 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+000027a0 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027b0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027c0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027d0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027e0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027f0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+00002800 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002810 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002820 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002830 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002840 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002850 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002860 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002870 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002880 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002890 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+000028a0 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028b0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028c0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028d0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028e0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028f0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+00002900 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002910 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002920 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002930 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002940 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002950 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002960 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002970 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002980 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002990 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+000029a0 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029b0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029c0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029d0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029e0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029f0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+00002a00 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a10 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a20 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a30 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a40 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a50 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a60 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a70 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a80 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a90 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002aa0 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002ab0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ac0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ad0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ae0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002af0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002b00 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b10 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b20 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b30 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b40 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b50 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b60 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b70 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b80 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b90 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002ba0 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002bb0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bc0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bd0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002be0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bf0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002c00 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c10 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c20 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c30 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c40 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c50 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c60 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c70 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c80 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c90 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002ca0 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002cb0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cc0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cd0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002ce0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cf0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002d00 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d10 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d20 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d30 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d40 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d50 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d60 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d70 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d80 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d90 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002da0 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002db0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002dc0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dd0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002de0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002df0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002e00 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e10 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e20 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e30 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e40 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e50 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e60 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e70 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e80 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e90 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002ea0 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002eb0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002ec0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ed0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ee0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ef0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002f00 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f10 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f20 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f30 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f40 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f50 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f60 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f70 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f80 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f90 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002fa0 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fb0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fc0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fd0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fe0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002ff0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00003000 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003010 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003020 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003030 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003040 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003050 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003080 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003090 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+000030a0 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030b0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030c0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030d0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+00003100 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003110 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003120 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003130 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003140 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003150 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003160 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003170 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003180 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003190 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+000031a0 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031b0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031c0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031d0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+00003200 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003210 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003220 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003230 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003240 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003250 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003280 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003290 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+000032a0 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032b0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032c0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032d0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+00003300 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003310 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003320 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003330 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003340 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003350 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003380 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003390 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+000033a0 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033b0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033c0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033d0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+00003400 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003410 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003420 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003430 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003440 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003450 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003480 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003490 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+000034a0 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034b0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034c0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034d0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+00003500 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003510 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003520 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003530 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003540 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003550 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003580 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003590 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+000035a0 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035b0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035c0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035d0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+00003600 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003610 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003620 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003630 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003640 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003650 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003680 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003690 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+000036a0 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036b0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036c0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036d0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+00003700 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003710 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003720 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003730 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003740 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003750 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003760 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003770 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003780 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003790 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+000037a0 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037b0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037c0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037d0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+00003800 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003810 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003820 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003830 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003840 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003850 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003880 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003890 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+000038a0 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038b0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038c0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038d0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+00003900 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003910 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003920 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003930 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003940 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003950 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003980 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003990 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+000039a0 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039b0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039c0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039d0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+00003a00 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a10 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a20 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a30 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a40 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a50 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a80 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a90 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003aa0 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003ab0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ac0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ad0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003b00 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b10 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b20 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b30 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b40 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b50 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b80 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b90 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003ba0 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003bb0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bc0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bd0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003c00 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c10 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c20 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c30 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c40 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c50 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c80 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c90 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003ca0 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003cb0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cc0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cd0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003d00 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d10 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d20 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d30 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d40 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d50 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d80 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d90 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003da0 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003db0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003dc0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dd0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003e00 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e10 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e20 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e30 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e40 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e50 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e80 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e90 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003ea0 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003eb0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003ec0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ed0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003f00 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f10 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f20 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f30 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f40 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f50 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f80 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f90 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003fa0 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fb0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fc0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fd0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00004000 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004010 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004020 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004030 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004040 00 00 00 00 00 40 70 00 00 00 00 00 00 40 80 00 |.....@p......@..|
+00004050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000051c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00007010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00007020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00007030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00007040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00007050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00007090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000070a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000070b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000070c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00007120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00408e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.hex
new file mode 100644
index 000000000000..250d0b8508e2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.hex
@@ -0,0 +1,82 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000501c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00057e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00058000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00058010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00058020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00058030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00058040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00058050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00058090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000580a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000580b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000580c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00058120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00059e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00459e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.hex
new file mode 100644
index 000000000000..716a382cae69
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.hex
@@ -0,0 +1,32 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007e0000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.hex
new file mode 100644
index 000000000000..22c20dc667a5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.hex
@@ -0,0 +1,64 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00000030 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00000040 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 08 |................|
+00000220 00 20 00 00 ff ff f4 6f 00 00 00 00 00 00 00 00 |. .....o........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+00000bc0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008800 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008a00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008a20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008a30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008a40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008a80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008a90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00008aa0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00008ab0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00008ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008b10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008b20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+0000a800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+0040ac00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650a00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00650a10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00650a20 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00650a30 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00650a40 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00650a50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00650a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650c00
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.hex
new file mode 100644
index 000000000000..097d9e00dfe5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.hex
@@ -0,0 +1,40 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+01000010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+01000020 00 02 00 00 57 69 32 6b 00 00 00 00 01 00 00 00 |....Wi2k........|
+01000030 00 00 00 00 01 00 00 00 00 02 ff 3f 00 00 00 02 |...........?....|
+01000040 ff ff ef bd 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+01000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+01000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdx.hex
new file mode 100644
index 000000000000..a23cda98c23e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdx.hex
@@ -0,0 +1,81 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+004001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00408000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00408010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00408020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00408030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00408040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00408050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00408090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+004080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00408120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00409e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00809e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.hex
new file mode 100644
index 000000000000..5c41298f81db
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.hex
@@ -0,0 +1,326 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00000610 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00000620 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00000630 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00000640 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00000650 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00000660 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00000670 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00000680 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00000690 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000006a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000006b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000006c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000006d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000006e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000006f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00000700 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00000710 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00000720 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00000730 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00000740 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00000750 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00000760 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00000770 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00000780 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00000790 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000007a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000007b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000007c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000007d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000007e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000007f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00000800 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00000810 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00000820 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00000830 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00000840 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00000850 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00000860 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00000870 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00000880 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00000890 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+000008a0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+000008b0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+000008c0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+000008d0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+000008e0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+000008f0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00000900 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00000910 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00000920 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00000930 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00000940 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00000950 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00000960 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00000970 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00000980 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00000990 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+000009a0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+000009b0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+000009c0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+000009d0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+000009e0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+000009f0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00000a00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00000a10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00000a20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00000a30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00000a40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00000a50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00000a60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00000a70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00000a80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00000a90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00000aa0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00000ab0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00000ac0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00000ad0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00000ae0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00000af0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00000b00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00000b10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00000b20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00000b30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00000b40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00000b50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00000b60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00000b70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00000b80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00000b90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00000ba0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00000bb0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00000bc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00000bd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00000be0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00000bf0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00000c00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00000c10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00000c20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00000c30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00000c40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00000c50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00000c60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00000c70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00000c80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00000c90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00000ca0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00000cb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00000cc0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00000cd0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00000ce0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00000cf0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00000d00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00000d10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00000d20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00000d30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00000d40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00000d50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00000d60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00000d70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00000d80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00000d90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00000da0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00000db0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00000dc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00000dd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00000de0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00000df0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00000e00 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00000e10 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00000e20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00001810 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00001820 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00001830 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00001840 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00001850 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00001860 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00001870 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00001880 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00001890 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000018a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000018b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000018c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000018d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000018e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000018f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00001900 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00001910 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00001920 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00001930 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00001940 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00001950 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00001960 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00001970 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00001980 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00001990 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000019a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000019b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000019c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000019d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000019e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000019f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00001a00 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00001a10 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00001a20 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00001a30 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00001a40 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00001a50 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00001a60 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00001a70 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00001a80 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00001a90 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+00001aa0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+00001ab0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+00001ac0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+00001ad0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+00001ae0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+00001af0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00001b00 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00001b10 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00001b20 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00001b30 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00001b40 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00001b50 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00001b60 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00001b70 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00001b80 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00001b90 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+00001ba0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+00001bb0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+00001bc0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+00001bd0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+00001be0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+00001bf0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00001c00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00001c10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00001c20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00001c30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00001c40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00001c50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00001c60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00001c70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00001c80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00001c90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00001ca0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00001cb0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00001cc0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00001cd0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00001ce0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00001cf0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00001d00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00001d10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00001d20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00001d30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00001d40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00001d50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00001d60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00001d70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00001d80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00001d90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00001da0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00001db0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00001dc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00001dd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00001de0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00001df0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00001e00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00001e10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00001e20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00001e30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00001e40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00001e50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00001e60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00001e70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00001e80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00001e90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00001ea0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00001eb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00001ec0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00001ed0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00001ee0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00001ef0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00001f00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00001f10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00001f20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00001f30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00001f40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00001f50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00001f60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00001f70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00001f80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00001f90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00001fa0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00001fb0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00001fc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00001fd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00001fe0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00001ff0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00002000 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00002010 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000041c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040a000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.hex
new file mode 100644
index 000000000000..ab899b3e5ec2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.hex
@@ -0,0 +1,579 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 a0 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002030 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002040 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002050 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002060 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002070 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002080 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002090 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020a0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020b0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020c0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020d0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020e0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020f0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002100 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002110 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002120 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002130 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002140 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002150 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002160 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002170 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002180 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002190 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021a0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021b0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021c0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021d0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021e0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021f0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002200 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002210 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002220 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002230 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002240 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002250 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002260 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002270 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002280 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002290 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022a0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022b0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022c0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022d0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022e0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022f0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002300 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002310 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002320 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002330 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002340 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002350 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002360 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002370 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002380 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002390 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023a0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023b0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023c0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023d0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023e0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023f0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002400 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002410 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002420 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002430 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002440 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002450 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002460 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002470 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002480 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002490 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024a0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024b0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024c0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024d0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024e0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024f0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002500 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002510 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002520 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002530 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002540 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002550 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002560 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002570 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002580 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002590 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025a0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025b0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025c0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025d0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025e0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025f0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002600 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002610 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002620 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002630 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002640 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002650 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002660 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002670 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002680 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002690 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026a0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026b0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026c0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026d0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026e0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026f0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002700 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002710 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002720 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002730 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002740 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002750 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002760 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002770 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002780 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002790 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027a0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027b0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027c0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027d0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027e0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027f0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002800 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002810 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002820 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002830 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002840 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002850 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002860 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002870 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002880 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002890 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028a0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028b0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028c0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028d0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028e0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028f0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002900 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002910 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002920 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002930 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002940 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002950 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002960 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002970 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002980 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002990 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029a0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029b0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029c0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029d0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029e0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029f0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a00 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a10 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a20 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a30 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a40 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a50 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a60 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a70 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a80 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a90 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002aa0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ab0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ac0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ad0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ae0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002af0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b00 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b10 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b20 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b30 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b40 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b50 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b60 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b70 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b80 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b90 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002ba0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bb0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bc0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bd0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002be0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bf0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c00 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c10 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c20 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c30 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c40 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c50 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c60 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c70 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c80 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c90 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002ca0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cb0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cc0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cd0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002ce0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cf0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d00 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d10 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d20 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d30 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d40 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d50 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d60 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d70 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d80 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d90 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002da0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002db0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dc0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002dd0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002de0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002df0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e00 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e10 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e20 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e30 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e40 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e50 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e60 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e70 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e80 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e90 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002ea0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002eb0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ec0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ed0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ee0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ef0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f00 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f10 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f20 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f30 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f40 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f50 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f60 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f70 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f80 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f90 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fa0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fb0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fc0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fd0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fe0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002ff0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003000 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003010 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003020 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003030 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003040 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003080 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003090 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030a0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030b0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030c0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003100 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003110 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003120 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003130 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003140 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003150 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003160 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003170 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003180 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003190 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031a0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031b0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031c0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003200 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003210 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003220 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003230 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003240 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003280 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003290 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032a0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032b0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032c0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003300 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003310 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003320 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003330 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003340 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003380 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003390 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033a0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033b0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033c0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003400 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003410 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003420 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003430 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003440 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003480 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003490 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034a0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034b0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034c0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003500 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003510 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003520 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003530 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003540 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003580 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003590 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035a0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035b0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035c0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003600 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003610 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003620 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003630 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003640 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003680 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003690 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036a0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036b0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036c0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003700 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003710 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003720 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003730 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003740 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003750 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003760 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003770 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003780 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003790 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037a0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037b0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037c0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003800 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003810 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003820 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003830 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003840 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003880 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003890 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038a0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038b0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038c0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003900 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003910 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003920 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003930 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003940 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003980 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003990 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039a0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039b0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039c0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a00 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a10 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a20 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a30 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a40 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a80 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a90 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003aa0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ab0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ac0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b00 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b10 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b20 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b30 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b40 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b80 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b90 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003ba0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bb0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bc0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c00 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c10 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c20 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c30 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c40 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c80 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c90 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003ca0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cb0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cc0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d00 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d10 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d20 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d30 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d40 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d80 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d90 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003da0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003db0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dc0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e00 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e10 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e20 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e30 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e40 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e80 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e90 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003ea0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003eb0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ec0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f00 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f10 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f20 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f30 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f40 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f80 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f90 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fa0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fb0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fc0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004000 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004010 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004020 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004120 00 00 00 00 00 00 00 00 00 00 00 00 00 40 60 00 |.............@`.|
+00004130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004140 00 00 00 00 00 00 00 00 00 00 00 00 00 40 70 00 |.............@p.|
+00004150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000051c0 02 00 ee ff ff ff 01 00 00 00 4f 21 00 00 00 00 |..........O!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00005210 5a 6f 4f 0c 00 00 00 00 01 00 00 00 00 00 00 00 |ZoO.............|
+00005220 4f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |O!......".......|
+00005230 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00005240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00005250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00005260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00005420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00005430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000054a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000054b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00406e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00406e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00406e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00406e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00406ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00406eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00407e10 51 9d 2a 3e 00 00 00 00 4f 21 00 00 00 00 00 00 |Q.*>....O!......|
+00407e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00407e30 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00407e40 03 03 03 03 03 03 03 03 2f 21 00 00 00 00 00 00 |......../!......|
+00407e50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00407e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.hex
new file mode 100644
index 000000000000..a2d342d06a42
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.hex
@@ -0,0 +1,101 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 80 00 00 00 00 46 00 00 00 00 00 00 00 00 00 00 |.....F..........|
+00030220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000501c0 02 00 ee ff ff ff 01 00 00 00 7f 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00050210 7d b3 cb 21 00 00 00 00 01 00 00 00 00 00 00 00 |}..!............|
+00050220 7f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.!......".......|
+00050230 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+00050240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00050250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00050260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00050420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00050430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000504a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000504b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00055000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00455000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0046be20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+0046be30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0046bea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+0046beb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046fe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0046fe10 ed cb cc 05 00 00 00 00 7f 21 00 00 00 00 00 00 |.........!......|
+0046fe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0046fe30 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+0046fe40 03 03 03 03 03 03 03 03 5f 21 00 00 00 00 00 00 |........_!......|
+0046fe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+0046fe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00470000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.hex
new file mode 100644
index 000000000000..dae6b78a65f8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.hex
@@ -0,0 +1,48 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 4f 21 00 00 00 00 |..........O!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 5a 6f 4f 0c 00 00 00 00 01 00 00 00 00 00 00 00 |ZoO.............|
+00000220 4f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |O!......".......|
+00000230 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00425e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00425e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00425e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00425e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00425e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00425e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00425ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00425eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00429e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00429e10 51 9d 2a 3e 00 00 00 00 4f 21 00 00 00 00 00 00 |Q.*>....O!......|
+00429e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00429e30 2e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.!..............|
+00429e40 03 03 03 03 03 03 03 03 2f 21 00 00 00 00 00 00 |......../!......|
+00429e50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00429e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0042a000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.hex
new file mode 100644
index 000000000000..0103906c9fa2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.hex
@@ -0,0 +1,84 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 87 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00000050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 00 00 30 07 |.......... ...0.|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+00000bc0 02 00 ee ff ff ff 01 00 00 00 c0 3e 00 00 00 00 |...........>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000c10 ce 88 f5 a8 00 00 00 00 01 00 00 00 00 00 00 00 |................|
+00000c20 c0 3e 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.>......".......|
+00000c30 9f 3e 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.>..............|
+00000c40 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000c50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00000ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00000eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00601000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d5000 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007d5010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+007d5020 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+007d5030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d5080 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007d5090 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+007d50a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+007d50b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d9000 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+007d9010 de cd 9d c3 00 00 00 00 c0 3e 00 00 00 00 00 00 |.........>......|
+007d9020 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+007d9030 9f 3e 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.>..............|
+007d9040 03 03 03 03 03 03 03 03 a0 3e 00 00 00 00 00 00 |.........>......|
+007d9050 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+007d9060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00801000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00801010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00801020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00801030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00801040 ff ff f5 87 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00801050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00801060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00801200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.hex
new file mode 100644
index 000000000000..36210d5dd44d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.hex
@@ -0,0 +1,56 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 ff 3f 00 00 00 00 |...........?....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 b6 c4 c6 f2 00 00 00 00 01 00 00 00 00 00 00 00 |................|
+00000220 ff 3f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.?......".......|
+00000230 de 3f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.?..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+007fbe20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+007fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+007fbea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+007fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+007ffe10 83 d1 f3 46 00 00 00 00 ff 3f 00 00 00 00 00 00 |...F.....?......|
+007ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+007ffe30 de 3f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.?..............|
+007ffe40 03 03 03 03 03 03 03 03 df 3f 00 00 00 00 00 00 |.........?......|
+007ffe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+007ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee 90 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00800050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdx.hex
new file mode 100644
index 000000000000..4d4542d9a686
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdx.hex
@@ -0,0 +1,99 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+004001c0 02 00 ee ff ff ff 01 00 00 00 ff 7f 00 00 00 00 |................|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00400210 f9 27 e5 be 00 00 00 00 01 00 00 00 00 00 00 00 |.'..............|
+00400220 ff 7f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00400230 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+00400240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00400250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00400260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00400420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00400430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004004a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+004004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00405000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00805000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+013fbe20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+013fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+013fbea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+013fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+013ffe10 47 76 13 47 00 00 00 00 ff 7f 00 00 00 00 00 00 |Gv.G............|
+013ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+013ffe30 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+013ffe40 03 03 03 03 03 03 03 03 df 7f 00 00 00 00 00 00 |................|
+013ffe50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+013ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.hex
new file mode 100644
index 000000000000..bf6ba8b9560e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.hex
@@ -0,0 +1,348 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 30 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "0".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00000610 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00000620 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00000630 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00000640 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00000650 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00000660 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00000670 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00000680 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00000690 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000006a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000006b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000006c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000006d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000006e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000006f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00000700 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00000710 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00000720 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00000730 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00000740 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00000750 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00000760 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00000770 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00000780 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00000790 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000007a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000007b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000007c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000007d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000007e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000007f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00000800 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00000810 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00000820 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00000830 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00000840 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00000850 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00000860 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00000870 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00000880 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00000890 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+000008a0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+000008b0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+000008c0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+000008d0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+000008e0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+000008f0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00000900 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00000910 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00000920 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00000930 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00000940 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00000950 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00000960 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00000970 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00000980 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00000990 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+000009a0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+000009b0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+000009c0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+000009d0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+000009e0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+000009f0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00000a00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00000a10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00000a20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00000a30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00000a40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00000a50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00000a60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00000a70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00000a80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00000a90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00000aa0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00000ab0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00000ac0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00000ad0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00000ae0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00000af0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00000b00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00000b10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00000b20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00000b30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00000b40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00000b50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00000b60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00000b70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00000b80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00000b90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00000ba0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00000bb0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00000bc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00000bd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00000be0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00000bf0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00000c00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00000c10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00000c20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00000c30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00000c40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00000c50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00000c60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00000c70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00000c80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00000c90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00000ca0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00000cb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00000cc0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00000cd0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00000ce0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00000cf0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00000d00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00000d10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00000d20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00000d30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00000d40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00000d50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00000d60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00000d70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00000d80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00000d90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00000da0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00000db0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00000dc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00000dd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00000de0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00000df0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00000e00 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000ff0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00001810 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00001820 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00001830 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00001840 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00001850 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00001860 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00001870 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00001880 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00001890 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000018a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000018b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000018c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000018d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000018e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000018f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00001900 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00001910 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00001920 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00001930 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00001940 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00001950 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00001960 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00001970 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00001980 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00001990 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000019a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000019b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000019c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000019d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000019e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000019f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00001a00 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00001a10 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00001a20 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00001a30 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00001a40 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00001a50 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00001a60 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00001a70 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00001a80 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00001a90 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+00001aa0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+00001ab0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+00001ac0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+00001ad0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+00001ae0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+00001af0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00001b00 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00001b10 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00001b20 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00001b30 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00001b40 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00001b50 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00001b60 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00001b70 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00001b80 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00001b90 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+00001ba0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+00001bb0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+00001bc0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+00001bd0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+00001be0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+00001bf0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00001c00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00001c10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00001c20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00001c30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00001c40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00001c50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00001c60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00001c70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00001c80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00001c90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00001ca0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00001cb0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00001cc0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00001cd0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00001ce0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00001cf0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00001d00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00001d10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00001d20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00001d30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00001d40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00001d50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00001d60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00001d70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00001d80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00001d90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00001da0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00001db0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00001dc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00001dd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00001de0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00001df0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00001e00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00001e10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00001e20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00001e30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00001e40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00001e50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00001e60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00001e70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00001e80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00001e90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00001ea0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00001eb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00001ec0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00001ed0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00001ee0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00001ef0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00001f00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00001f10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00001f20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00001f30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00001f40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00001f50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00001f60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00001f70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00001f80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00001f90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00001fa0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00001fb0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00001fc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00001fd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00001fe0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00001ff0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00002000 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000021f0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00002200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000041c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00004210 c4 60 24 d3 00 00 00 00 01 00 00 00 00 00 00 00 |.`$.............|
+00004220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00004230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00004240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00004250 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+00004260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00004420 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00004430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000044a0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+000044b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00409e20 28 00 00 00 00 00 00 00 27 20 00 00 00 00 00 00 |(.......' ......|
+00409e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00409ea0 28 20 00 00 00 00 00 00 27 21 00 00 00 00 00 00 |( ......'!......|
+00409eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040be00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0040be10 aa 6f 0f ab 00 00 00 00 ff 27 00 00 00 00 00 00 |.o.......'......|
+0040be20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0040be30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+0040be40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+0040be50 80 00 00 00 80 00 00 00 8e 5f a6 4d 00 00 00 00 |........._.M....|
+0040be60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040c000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.hex
new file mode 100644
index 000000000000..3e1cdcabe2ff
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.hex
@@ -0,0 +1,560 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002040 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002050 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002060 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002070 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002080 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002090 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+000020a0 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020b0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020c0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020d0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020e0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020f0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+00002100 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002110 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002120 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002130 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002140 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002150 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002160 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002170 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002180 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002190 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+000021a0 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021b0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021c0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021d0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021e0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021f0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+00002200 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002210 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002220 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002230 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002240 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002250 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002260 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002270 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002280 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002290 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+000022a0 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022b0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022c0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022d0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022e0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022f0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+00002300 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002310 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002320 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002330 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002340 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002350 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002360 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002370 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002380 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002390 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+000023a0 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023b0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023c0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023d0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023e0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023f0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+00002400 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002410 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002420 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002430 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002440 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002450 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002460 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002470 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002480 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002490 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+000024a0 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024b0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024c0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024d0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024e0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024f0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+00002500 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002510 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002520 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002530 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002540 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002550 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002560 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002570 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002580 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002590 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+000025a0 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025b0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025c0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025d0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025e0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025f0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+00002600 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002610 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002620 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002630 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002640 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002650 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002660 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002670 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002680 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002690 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+000026a0 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026b0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026c0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026d0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026e0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026f0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+00002700 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002710 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002720 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002730 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002740 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002750 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002760 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002770 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002780 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002790 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+000027a0 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027b0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027c0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027d0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027e0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027f0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+00002800 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002810 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002820 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002830 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002840 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002850 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002860 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002870 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002880 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002890 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+000028a0 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028b0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028c0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028d0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028e0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028f0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+00002900 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002910 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002920 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002930 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002940 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002950 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002960 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002970 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002980 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002990 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+000029a0 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029b0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029c0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029d0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029e0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029f0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+00002a00 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a10 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a20 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a30 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a40 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a50 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a60 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a70 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a80 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a90 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002aa0 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002ab0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ac0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ad0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ae0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002af0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002b00 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b10 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b20 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b30 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b40 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b50 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b60 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b70 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b80 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b90 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002ba0 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002bb0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bc0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bd0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002be0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bf0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002c00 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c10 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c20 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c30 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c40 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c50 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c60 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c70 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c80 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c90 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002ca0 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002cb0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cc0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cd0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002ce0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cf0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002d00 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d10 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d20 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d30 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d40 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d50 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d60 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d70 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d80 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d90 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002da0 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002db0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002dc0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dd0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002de0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002df0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002e00 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e10 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e20 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e30 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e40 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e50 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e60 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e70 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e80 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e90 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002ea0 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002eb0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002ec0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ed0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ee0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ef0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002f00 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f10 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f20 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f30 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f40 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f50 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f60 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f70 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f80 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f90 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002fa0 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fb0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fc0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fd0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fe0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002ff0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00003000 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003010 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003020 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003030 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003040 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003050 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003080 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003090 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+000030a0 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030b0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030c0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030d0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+00003100 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003110 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003120 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003130 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003140 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003150 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003160 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003170 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003180 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003190 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+000031a0 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031b0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031c0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031d0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+00003200 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003210 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003220 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003230 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003240 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003250 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003280 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003290 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+000032a0 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032b0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032c0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032d0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+00003300 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003310 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003320 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003330 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003340 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003350 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003380 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003390 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+000033a0 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033b0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033c0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033d0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+00003400 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003410 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003420 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003430 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003440 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003450 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003480 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003490 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+000034a0 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034b0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034c0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034d0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+00003500 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003510 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003520 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003530 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003540 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003550 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003580 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003590 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+000035a0 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035b0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035c0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035d0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+00003600 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003610 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003620 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003630 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003640 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003650 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003680 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003690 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+000036a0 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036b0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036c0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036d0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+00003700 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003710 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003720 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003730 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003740 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003750 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003760 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003770 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003780 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003790 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+000037a0 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037b0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037c0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037d0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+00003800 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003810 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003820 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003830 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003840 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003850 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003880 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003890 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+000038a0 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038b0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038c0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038d0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+00003900 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003910 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003920 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003930 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003940 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003950 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003980 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003990 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+000039a0 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039b0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039c0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039d0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+00003a00 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a10 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a20 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a30 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a40 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a50 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a80 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a90 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003aa0 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003ab0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ac0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ad0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003b00 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b10 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b20 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b30 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b40 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b50 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b80 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b90 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003ba0 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003bb0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bc0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bd0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003c00 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c10 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c20 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c30 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c40 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c50 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c80 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c90 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003ca0 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003cb0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cc0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cd0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003d00 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d10 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d20 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d30 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d40 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d50 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d80 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d90 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003da0 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003db0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003dc0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dd0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003e00 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e10 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e20 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e30 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e40 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e50 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e80 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e90 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003ea0 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003eb0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003ec0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ed0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003f00 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f10 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f20 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f30 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f40 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f50 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f80 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f90 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003fa0 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fb0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fc0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fd0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00004000 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004010 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004020 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004030 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004040 00 00 00 00 00 40 70 00 00 00 00 00 00 40 80 00 |.....@p......@..|
+00004050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000051c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00007010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00007020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00007030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00007040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00007050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00007090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000070a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000070b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000070c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00007120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00408e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.hex
new file mode 100644
index 000000000000..dd2edf1acea2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.hex
@@ -0,0 +1,84 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000501c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00057e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00058000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00058010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00058020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00058030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00058040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00058050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00058090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000580a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000580b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000580c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00058120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00059e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00459e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.hex
new file mode 100644
index 000000000000..240acc2c5605
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.hex
@@ -0,0 +1,32 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007e0000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.hex
new file mode 100644
index 000000000000..0b5459c5c482
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.hex
@@ -0,0 +1,64 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00000030 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00000040 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 08 |................|
+00000220 00 20 00 00 ff ff f4 6f 00 00 00 00 00 00 00 00 |. .....o........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+00000bc0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008800 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008a00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008a20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008a30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008a40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008a80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008a90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00008aa0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00008ab0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00008ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008b10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008b20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+0000a800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+0040ac00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650a00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00650a10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00650a20 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00650a30 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00650a40 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00650a50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00650a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650c00
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.hex
new file mode 100644
index 000000000000..0e71c22314b2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.hex
@@ -0,0 +1,40 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+01000010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+01000020 00 02 00 00 57 69 32 6b 00 00 00 00 01 00 00 00 |....Wi2k........|
+01000030 00 00 00 00 01 00 00 00 00 02 ff 3f 00 00 00 02 |...........?....|
+01000040 ff ff ef bd 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+01000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+01000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000200
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdx.hex
new file mode 100644
index 000000000000..8bbfcf84fc86
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdx.hex
@@ -0,0 +1,83 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 10 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+004001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00408000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00408010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00408020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00408030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00408040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00408050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00408090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+004080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00408120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00409e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00809e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.hex
new file mode 100644
index 000000000000..a4383f951e3d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.hex
@@ -0,0 +1,328 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00000610 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00000620 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00000630 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00000640 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00000650 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00000660 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00000670 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00000680 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00000690 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000006a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000006b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000006c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000006d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000006e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000006f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00000700 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00000710 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00000720 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00000730 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00000740 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00000750 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00000760 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00000770 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00000780 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00000790 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000007a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000007b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000007c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000007d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000007e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000007f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00000800 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00000810 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00000820 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00000830 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00000840 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00000850 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00000860 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00000870 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00000880 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00000890 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+000008a0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+000008b0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+000008c0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+000008d0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+000008e0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+000008f0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00000900 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00000910 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00000920 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00000930 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00000940 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00000950 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00000960 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00000970 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00000980 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00000990 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+000009a0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+000009b0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+000009c0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+000009d0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+000009e0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+000009f0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00000a00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00000a10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00000a20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00000a30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00000a40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00000a50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00000a60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00000a70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00000a80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00000a90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00000aa0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00000ab0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00000ac0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00000ad0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00000ae0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00000af0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00000b00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00000b10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00000b20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00000b30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00000b40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00000b50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00000b60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00000b70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00000b80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00000b90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00000ba0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00000bb0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00000bc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00000bd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00000be0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00000bf0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00000c00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00000c10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00000c20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00000c30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00000c40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00000c50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00000c60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00000c70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00000c80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00000c90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00000ca0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00000cb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00000cc0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00000cd0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00000ce0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00000cf0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00000d00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00000d10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00000d20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00000d30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00000d40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00000d50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00000d60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00000d70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00000d80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00000d90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00000da0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00000db0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00000dc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00000dd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00000de0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00000df0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00000e00 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00000e10 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00000e20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00001810 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00001820 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00001830 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00001840 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00001850 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00001860 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00001870 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00001880 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00001890 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000018a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000018b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000018c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000018d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000018e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000018f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00001900 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00001910 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00001920 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00001930 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00001940 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00001950 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00001960 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00001970 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00001980 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00001990 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000019a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000019b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000019c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000019d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000019e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000019f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00001a00 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00001a10 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00001a20 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00001a30 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00001a40 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00001a50 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00001a60 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00001a70 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00001a80 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00001a90 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+00001aa0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+00001ab0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+00001ac0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+00001ad0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+00001ae0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+00001af0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00001b00 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00001b10 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00001b20 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00001b30 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00001b40 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00001b50 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00001b60 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00001b70 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00001b80 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00001b90 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+00001ba0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+00001bb0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+00001bc0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+00001bd0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+00001be0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+00001bf0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00001c00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00001c10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00001c20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00001c30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00001c40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00001c50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00001c60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00001c70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00001c80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00001c90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00001ca0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00001cb0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00001cc0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00001cd0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00001ce0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00001cf0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00001d00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00001d10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00001d20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00001d30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00001d40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00001d50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00001d60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00001d70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00001d80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00001d90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00001da0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00001db0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00001dc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00001dd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00001de0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00001df0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00001e00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00001e10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00001e20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00001e30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00001e40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00001e50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00001e60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00001e70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00001e80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00001e90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00001ea0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00001eb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00001ec0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00001ed0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00001ee0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00001ef0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00001f00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00001f10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00001f20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00001f30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00001f40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00001f50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00001f60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00001f70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00001f80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00001f90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00001fa0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00001fb0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00001fc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00001fd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00001fe0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00001ff0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00002000 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00002010 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000041c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040a000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.hex
new file mode 100644
index 000000000000..a4ff3455ce96
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.hex
@@ -0,0 +1,551 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 10 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 00 00 00 |.....@P.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 45 52 02 00 00 00 21 08 00 00 00 00 00 00 00 00 |ER....!.........|
+00005010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00005210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00005220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00005240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00005410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00005440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00005610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00005640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.hex
new file mode 100644
index 000000000000..d7056c8f81a7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.hex
@@ -0,0 +1,79 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 45 52 02 00 00 00 21 80 00 00 00 00 00 00 00 00 |ER....!.........|
+00050010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00050210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00050220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00050240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00050410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00050440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00050610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00050640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00450800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.raw.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.hex
new file mode 100644
index 000000000000..22005720d5fa
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.hex
@@ -0,0 +1,27 @@
+00000000 45 52 02 00 00 00 21 04 00 00 00 00 00 00 00 00 |ER....!.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00420800
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.hex
new file mode 100644
index 000000000000..e05eaffe439b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.hex
@@ -0,0 +1,59 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 45 52 02 00 00 00 3e c1 00 00 00 00 00 00 00 00 |ER....>.........|
+00000a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c00 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000c10 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000c20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c30 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000c40 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e30 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000e40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00001010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001030 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00001040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001200 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00401600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628c00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00628c10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00628c20 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00628c30 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00628c40 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00628c50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00628c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628e00
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.hex
new file mode 100644
index 000000000000..be7315b57927
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.hex
@@ -0,0 +1,35 @@
+00000000 45 52 02 00 00 00 40 00 00 00 00 00 00 00 00 00 |ER....@.........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00000210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00000240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00000440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00000640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee c0 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00800050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdx.hex
new file mode 100644
index 000000000000..5830cc7799d7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdx.hex
@@ -0,0 +1,78 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 45 52 02 00 00 00 80 00 00 00 00 00 00 00 00 00 |ER..............|
+00400010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00400210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00400220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00400240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00400410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00400440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00400610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00400640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00800800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.hex
new file mode 100644
index 000000000000..04634339fce2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.hex
@@ -0,0 +1,321 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 30 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "0".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 45 52 02 00 00 00 28 00 00 00 00 00 00 00 00 00 |ER....(.........|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004200 50 4d 00 00 00 00 00 03 00 00 00 01 00 00 00 03 |PM..............|
+00004210 41 70 70 6c 65 00 00 00 00 00 00 00 00 00 00 00 |Apple...........|
+00004220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004230 41 70 70 6c 65 5f 70 61 72 74 69 74 69 6f 6e 5f |Apple_partition_|
+00004240 6d 61 70 00 00 00 00 00 00 00 00 00 00 00 00 00 |map.............|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 4d 00 00 00 00 00 03 00 00 00 04 00 00 20 00 |PM............ .|
+00004410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004430 46 72 65 65 42 53 44 2d 55 46 53 00 00 00 00 00 |FreeBSD-UFS.....|
+00004440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004600 50 4d 00 00 00 00 00 03 00 00 20 04 00 00 01 00 |PM........ .....|
+00004610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004630 46 72 65 65 42 53 44 2d 73 77 61 70 00 00 00 00 |FreeBSD-swap....|
+00004640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.hex
new file mode 100644
index 000000000000..28e796e95133
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.hex
@@ -0,0 +1,545 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7d 90 00 |.............}..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 60 00 |......P.......`.|
+00002010 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002020 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002030 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002040 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002050 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002060 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+00002070 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+00002080 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+00002090 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020a0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020b0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020c0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+000020d0 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+000020e0 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+000020f0 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002100 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002110 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002120 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002130 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002140 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002150 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002160 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+00002170 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+00002180 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+00002190 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021a0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021b0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021c0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+000021d0 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+000021e0 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+000021f0 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002200 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002210 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002220 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002230 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002240 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002250 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002260 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+00002270 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+00002280 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+00002290 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022a0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022b0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022c0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+000022d0 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+000022e0 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+000022f0 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002300 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002310 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002320 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002330 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002340 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002350 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002360 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+00002370 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+00002380 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+00002390 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023a0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023b0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023c0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+000023d0 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+000023e0 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+000023f0 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002400 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002410 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002420 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002430 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002440 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002450 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002460 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+00002470 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+00002480 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+00002490 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024a0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024b0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024c0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+000024d0 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+000024e0 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+000024f0 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002500 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002510 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002520 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002530 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002540 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002550 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002560 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+00002570 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+00002580 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+00002590 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025a0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025b0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025c0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+000025d0 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+000025e0 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+000025f0 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002600 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002610 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002620 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002630 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002640 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002650 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002660 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+00002670 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+00002680 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+00002690 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026a0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026b0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026c0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+000026d0 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+000026e0 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+000026f0 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002700 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002710 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002720 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002730 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002740 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002750 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002760 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+00002770 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+00002780 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+00002790 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027a0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027b0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027c0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+000027d0 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+000027e0 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+000027f0 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002800 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002810 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002820 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002830 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002840 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002850 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002860 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+00002870 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+00002880 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+00002890 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028a0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028b0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028c0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+000028d0 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+000028e0 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+000028f0 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002900 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002910 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002920 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002930 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002940 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002950 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002960 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+00002970 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+00002980 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+00002990 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029a0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029b0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029c0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+000029d0 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+000029e0 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+000029f0 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a00 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a10 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a20 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a30 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a40 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a50 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a60 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002a70 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002a80 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002a90 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002aa0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ab0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002ac0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002ad0 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002ae0 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002af0 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b00 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b10 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b20 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b30 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b40 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b50 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b60 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002b70 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002b80 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002b90 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002ba0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002bb0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bc0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002bd0 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002be0 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002bf0 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c00 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c10 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c20 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c30 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c40 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c50 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c60 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002c70 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002c80 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002c90 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002ca0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002cb0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cc0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002cd0 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002ce0 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002cf0 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d00 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d10 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d20 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d30 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d40 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d50 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d60 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002d70 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002d80 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002d90 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002da0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002db0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002dc0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002dd0 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002de0 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002df0 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e00 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e10 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e20 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e30 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e40 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e50 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e60 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002e70 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002e80 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002e90 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ea0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002eb0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ec0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002ed0 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002ee0 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002ef0 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f00 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f10 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f20 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f30 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f40 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f50 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f60 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002f70 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002f80 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002f90 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fa0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fb0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002fc0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00002fd0 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00002fe0 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00002ff0 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003000 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003010 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003020 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003030 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003060 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+00003070 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+00003080 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+00003090 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030a0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030b0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+000030e0 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+000030f0 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003100 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003110 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003120 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003130 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003140 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003150 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003160 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+00003170 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+00003180 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+00003190 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031a0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031b0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+000031e0 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+000031f0 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003200 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003210 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003220 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003230 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003260 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+00003270 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+00003280 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+00003290 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032a0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032b0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+000032e0 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+000032f0 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003300 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003310 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003320 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003330 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003360 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+00003370 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+00003380 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+00003390 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033a0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033b0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+000033e0 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+000033f0 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003400 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003410 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003420 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003430 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003460 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+00003470 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+00003480 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+00003490 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034a0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034b0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+000034e0 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+000034f0 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003500 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003510 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003520 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003530 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003560 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+00003570 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+00003580 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+00003590 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035a0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035b0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+000035e0 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+000035f0 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003600 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003610 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003620 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003630 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003660 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+00003670 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+00003680 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+00003690 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036a0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036b0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+000036e0 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+000036f0 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003700 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003710 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003720 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003730 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003740 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003750 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003760 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+00003770 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+00003780 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+00003790 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037a0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037b0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037c0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+000037e0 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+000037f0 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003800 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003810 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003820 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003830 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003860 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+00003870 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+00003880 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+00003890 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038a0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038b0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+000038e0 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+000038f0 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003900 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003910 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003920 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003930 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003960 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+00003970 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+00003980 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+00003990 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039a0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039b0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+000039e0 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+000039f0 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a00 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a10 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a20 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a30 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a60 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003a70 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003a80 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003a90 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003aa0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ab0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003ae0 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003af0 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b00 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b10 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b20 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b30 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b60 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003b70 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003b80 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003b90 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003ba0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003bb0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003be0 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003bf0 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c00 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c10 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c20 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c30 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c60 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003c70 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003c80 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003c90 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003ca0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003cb0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003ce0 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003cf0 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d00 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d10 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d20 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d30 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d60 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003d70 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003d80 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003d90 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003da0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003db0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003de0 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003df0 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e00 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e10 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e20 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e30 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e60 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003e70 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003e80 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003e90 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ea0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003eb0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003ee0 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003ef0 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f00 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f10 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f20 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f30 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f60 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003f70 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003f80 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003f90 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fa0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fb0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00003fe0 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00003ff0 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004000 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00005200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00005210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00005220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00005230 ff 00 00 00 01 00 00 00 c1 3e 00 00 c8 3e 00 00 |.........>...>..|
+00005240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00005250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00005290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000052a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000052b0 01 00 00 00 c8 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000052c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00005320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00407000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.hex
new file mode 100644
index 000000000000..e6b97d1b701e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.hex
@@ -0,0 +1,75 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00050200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00050210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00050220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00050230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 3f 00 00 |.........>...?..|
+00050240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00050250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00050290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000502a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000502b0 01 00 00 00 00 3f 00 00 00 00 00 00 00 00 00 00 |.....?..........|
+000502c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00050320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00052000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00452000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.hex
new file mode 100644
index 000000000000..0ce1218cbd23
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.hex
@@ -0,0 +1,23 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000230 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d8200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.hex
new file mode 100644
index 000000000000..df70c0401fec
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.hex
@@ -0,0 +1,55 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000c00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000c20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000c30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00000c40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000c80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000c90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00000ca0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00000cb0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00000cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000d10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000d20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002a00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628c00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00628c10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00628c20 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00628c30 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00628c40 ff ff f5 b7 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00628c50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00628c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00628e00
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.hex
new file mode 100644
index 000000000000..7f9365ff4dc9
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.hex
@@ -0,0 +1,31 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00000230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 40 00 00 |.........>...@..|
+00000240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00000290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000002b0 01 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
+000002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00000320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00002000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00402000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee c0 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00800050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdx.hex
new file mode 100644
index 000000000000..9f7b997cbea2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdx.hex
@@ -0,0 +1,74 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00400200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00400210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00400220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00400230 ff 00 00 00 02 00 00 00 c1 3e 00 00 00 80 00 00 |.........>......|
+00400240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00400250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400280 00 00 00 00 57 45 56 82 1d 13 08 00 00 20 00 00 |....WEV...... ..|
+00400290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004002a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004002b0 01 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 |................|
+004002c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00400320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00402000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00802000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.hex
new file mode 100644
index 000000000000..76d6c3deb309
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.hex
@@ -0,0 +1,315 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00000610 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00000620 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00000630 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00000640 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00000650 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00000660 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00000670 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00000680 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00000690 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000006a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000006b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000006c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000006d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000006e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000006f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00000700 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00000710 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00000720 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00000730 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00000740 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00000750 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00000760 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00000770 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00000780 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00000790 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000007a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000007b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000007c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000007d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000007e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000007f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00000800 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00000810 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00000820 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00000830 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00000840 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00000850 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00000860 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00000870 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00000880 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00000890 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+000008a0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+000008b0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+000008c0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+000008d0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+000008e0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+000008f0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00000900 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00000910 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00000920 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00000930 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00000940 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00000950 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00000960 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00000970 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00000980 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00000990 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+000009a0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+000009b0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+000009c0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+000009d0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+000009e0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+000009f0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00000a00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00000a10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00000a20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00000a30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00000a40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00000a50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00000a60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00000a70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00000a80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00000a90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00000aa0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00000ab0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00000ac0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00000ad0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00000ae0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00000af0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00000b00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00000b10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00000b20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00000b30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00000b40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00000b50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00000b60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00000b70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00000b80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00000b90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00000ba0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00000bb0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00000bc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00000bd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00000be0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00000bf0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00000c00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00000c10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00000c20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00000c30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00000c40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00000c50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00000c60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00000c70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00000c80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00000c90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00000ca0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00000cb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00000cc0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00000cd0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00000ce0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00000cf0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00000d00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00000d10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00000d20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00000d30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00000d40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00000d50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00000d60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00000d70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00000d80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00000d90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00000da0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00000db0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00000dc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00000dd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00000de0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00000df0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00000e00 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 30 00 00 00 40 00 00 00 50 00 00 00 | ...0...@...P...|
+00001810 60 00 00 00 70 00 00 00 80 00 00 00 90 00 00 00 |`...p...........|
+00001820 a0 00 00 00 b0 00 00 00 c0 00 00 00 d0 00 00 00 |................|
+00001830 e0 00 00 00 f0 00 00 00 00 01 00 00 10 01 00 00 |................|
+00001840 20 01 00 00 30 01 00 00 40 01 00 00 50 01 00 00 | ...0...@...P...|
+00001850 60 01 00 00 70 01 00 00 80 01 00 00 90 01 00 00 |`...p...........|
+00001860 a0 01 00 00 b0 01 00 00 c0 01 00 00 d0 01 00 00 |................|
+00001870 e0 01 00 00 f0 01 00 00 00 02 00 00 10 02 00 00 |................|
+00001880 20 02 00 00 30 02 00 00 40 02 00 00 50 02 00 00 | ...0...@...P...|
+00001890 60 02 00 00 70 02 00 00 80 02 00 00 90 02 00 00 |`...p...........|
+000018a0 a0 02 00 00 b0 02 00 00 c0 02 00 00 d0 02 00 00 |................|
+000018b0 e0 02 00 00 f0 02 00 00 00 03 00 00 10 03 00 00 |................|
+000018c0 20 03 00 00 30 03 00 00 40 03 00 00 50 03 00 00 | ...0...@...P...|
+000018d0 60 03 00 00 70 03 00 00 80 03 00 00 90 03 00 00 |`...p...........|
+000018e0 a0 03 00 00 b0 03 00 00 c0 03 00 00 d0 03 00 00 |................|
+000018f0 e0 03 00 00 f0 03 00 00 00 04 00 00 10 04 00 00 |................|
+00001900 20 04 00 00 30 04 00 00 40 04 00 00 50 04 00 00 | ...0...@...P...|
+00001910 60 04 00 00 70 04 00 00 80 04 00 00 90 04 00 00 |`...p...........|
+00001920 a0 04 00 00 b0 04 00 00 c0 04 00 00 d0 04 00 00 |................|
+00001930 e0 04 00 00 f0 04 00 00 00 05 00 00 10 05 00 00 |................|
+00001940 20 05 00 00 30 05 00 00 40 05 00 00 50 05 00 00 | ...0...@...P...|
+00001950 60 05 00 00 70 05 00 00 80 05 00 00 90 05 00 00 |`...p...........|
+00001960 a0 05 00 00 b0 05 00 00 c0 05 00 00 d0 05 00 00 |................|
+00001970 e0 05 00 00 f0 05 00 00 00 06 00 00 10 06 00 00 |................|
+00001980 20 06 00 00 30 06 00 00 40 06 00 00 50 06 00 00 | ...0...@...P...|
+00001990 60 06 00 00 70 06 00 00 80 06 00 00 90 06 00 00 |`...p...........|
+000019a0 a0 06 00 00 b0 06 00 00 c0 06 00 00 d0 06 00 00 |................|
+000019b0 e0 06 00 00 f0 06 00 00 00 07 00 00 10 07 00 00 |................|
+000019c0 20 07 00 00 30 07 00 00 40 07 00 00 50 07 00 00 | ...0...@...P...|
+000019d0 60 07 00 00 70 07 00 00 80 07 00 00 90 07 00 00 |`...p...........|
+000019e0 a0 07 00 00 b0 07 00 00 c0 07 00 00 d0 07 00 00 |................|
+000019f0 e0 07 00 00 f0 07 00 00 00 08 00 00 10 08 00 00 |................|
+00001a00 20 08 00 00 30 08 00 00 40 08 00 00 50 08 00 00 | ...0...@...P...|
+00001a10 60 08 00 00 70 08 00 00 80 08 00 00 90 08 00 00 |`...p...........|
+00001a20 a0 08 00 00 b0 08 00 00 c0 08 00 00 d0 08 00 00 |................|
+00001a30 e0 08 00 00 f0 08 00 00 00 09 00 00 10 09 00 00 |................|
+00001a40 20 09 00 00 30 09 00 00 40 09 00 00 50 09 00 00 | ...0...@...P...|
+00001a50 60 09 00 00 70 09 00 00 80 09 00 00 90 09 00 00 |`...p...........|
+00001a60 a0 09 00 00 b0 09 00 00 c0 09 00 00 d0 09 00 00 |................|
+00001a70 e0 09 00 00 f0 09 00 00 00 0a 00 00 10 0a 00 00 |................|
+00001a80 20 0a 00 00 30 0a 00 00 40 0a 00 00 50 0a 00 00 | ...0...@...P...|
+00001a90 60 0a 00 00 70 0a 00 00 80 0a 00 00 90 0a 00 00 |`...p...........|
+00001aa0 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 d0 0a 00 00 |................|
+00001ab0 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 10 0b 00 00 |................|
+00001ac0 20 0b 00 00 30 0b 00 00 40 0b 00 00 50 0b 00 00 | ...0...@...P...|
+00001ad0 60 0b 00 00 70 0b 00 00 80 0b 00 00 90 0b 00 00 |`...p...........|
+00001ae0 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 d0 0b 00 00 |................|
+00001af0 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 10 0c 00 00 |................|
+00001b00 20 0c 00 00 30 0c 00 00 40 0c 00 00 50 0c 00 00 | ...0...@...P...|
+00001b10 60 0c 00 00 70 0c 00 00 80 0c 00 00 90 0c 00 00 |`...p...........|
+00001b20 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 d0 0c 00 00 |................|
+00001b30 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 10 0d 00 00 |................|
+00001b40 20 0d 00 00 30 0d 00 00 40 0d 00 00 50 0d 00 00 | ...0...@...P...|
+00001b50 60 0d 00 00 70 0d 00 00 80 0d 00 00 90 0d 00 00 |`...p...........|
+00001b60 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 d0 0d 00 00 |................|
+00001b70 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 10 0e 00 00 |................|
+00001b80 20 0e 00 00 30 0e 00 00 40 0e 00 00 50 0e 00 00 | ...0...@...P...|
+00001b90 60 0e 00 00 70 0e 00 00 80 0e 00 00 90 0e 00 00 |`...p...........|
+00001ba0 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 d0 0e 00 00 |................|
+00001bb0 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 10 0f 00 00 |................|
+00001bc0 20 0f 00 00 30 0f 00 00 40 0f 00 00 50 0f 00 00 | ...0...@...P...|
+00001bd0 60 0f 00 00 70 0f 00 00 80 0f 00 00 90 0f 00 00 |`...p...........|
+00001be0 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 d0 0f 00 00 |................|
+00001bf0 e0 0f 00 00 f0 0f 00 00 00 10 00 00 10 10 00 00 |................|
+00001c00 20 10 00 00 30 10 00 00 40 10 00 00 50 10 00 00 | ...0...@...P...|
+00001c10 60 10 00 00 70 10 00 00 80 10 00 00 90 10 00 00 |`...p...........|
+00001c20 a0 10 00 00 b0 10 00 00 c0 10 00 00 d0 10 00 00 |................|
+00001c30 e0 10 00 00 f0 10 00 00 00 11 00 00 10 11 00 00 |................|
+00001c40 20 11 00 00 30 11 00 00 40 11 00 00 50 11 00 00 | ...0...@...P...|
+00001c50 60 11 00 00 70 11 00 00 80 11 00 00 90 11 00 00 |`...p...........|
+00001c60 a0 11 00 00 b0 11 00 00 c0 11 00 00 d0 11 00 00 |................|
+00001c70 e0 11 00 00 f0 11 00 00 00 12 00 00 10 12 00 00 |................|
+00001c80 20 12 00 00 30 12 00 00 40 12 00 00 50 12 00 00 | ...0...@...P...|
+00001c90 60 12 00 00 70 12 00 00 80 12 00 00 90 12 00 00 |`...p...........|
+00001ca0 a0 12 00 00 b0 12 00 00 c0 12 00 00 d0 12 00 00 |................|
+00001cb0 e0 12 00 00 f0 12 00 00 00 13 00 00 10 13 00 00 |................|
+00001cc0 20 13 00 00 30 13 00 00 40 13 00 00 50 13 00 00 | ...0...@...P...|
+00001cd0 60 13 00 00 70 13 00 00 80 13 00 00 90 13 00 00 |`...p...........|
+00001ce0 a0 13 00 00 b0 13 00 00 c0 13 00 00 d0 13 00 00 |................|
+00001cf0 e0 13 00 00 f0 13 00 00 00 14 00 00 10 14 00 00 |................|
+00001d00 20 14 00 00 30 14 00 00 40 14 00 00 50 14 00 00 | ...0...@...P...|
+00001d10 60 14 00 00 70 14 00 00 80 14 00 00 90 14 00 00 |`...p...........|
+00001d20 a0 14 00 00 b0 14 00 00 c0 14 00 00 d0 14 00 00 |................|
+00001d30 e0 14 00 00 f0 14 00 00 00 15 00 00 10 15 00 00 |................|
+00001d40 20 15 00 00 30 15 00 00 40 15 00 00 50 15 00 00 | ...0...@...P...|
+00001d50 60 15 00 00 70 15 00 00 80 15 00 00 90 15 00 00 |`...p...........|
+00001d60 a0 15 00 00 b0 15 00 00 c0 15 00 00 d0 15 00 00 |................|
+00001d70 e0 15 00 00 f0 15 00 00 00 16 00 00 10 16 00 00 |................|
+00001d80 20 16 00 00 30 16 00 00 40 16 00 00 50 16 00 00 | ...0...@...P...|
+00001d90 60 16 00 00 70 16 00 00 80 16 00 00 90 16 00 00 |`...p...........|
+00001da0 a0 16 00 00 b0 16 00 00 c0 16 00 00 d0 16 00 00 |................|
+00001db0 e0 16 00 00 f0 16 00 00 00 17 00 00 10 17 00 00 |................|
+00001dc0 20 17 00 00 30 17 00 00 40 17 00 00 50 17 00 00 | ...0...@...P...|
+00001dd0 60 17 00 00 70 17 00 00 80 17 00 00 90 17 00 00 |`...p...........|
+00001de0 a0 17 00 00 b0 17 00 00 c0 17 00 00 d0 17 00 00 |................|
+00001df0 e0 17 00 00 f0 17 00 00 00 18 00 00 10 18 00 00 |................|
+00001e00 20 18 00 00 30 18 00 00 40 18 00 00 50 18 00 00 | ...0...@...P...|
+00001e10 60 18 00 00 70 18 00 00 80 18 00 00 90 18 00 00 |`...p...........|
+00001e20 a0 18 00 00 b0 18 00 00 c0 18 00 00 d0 18 00 00 |................|
+00001e30 e0 18 00 00 f0 18 00 00 00 19 00 00 10 19 00 00 |................|
+00001e40 20 19 00 00 30 19 00 00 40 19 00 00 50 19 00 00 | ...0...@...P...|
+00001e50 60 19 00 00 70 19 00 00 80 19 00 00 90 19 00 00 |`...p...........|
+00001e60 a0 19 00 00 b0 19 00 00 c0 19 00 00 d0 19 00 00 |................|
+00001e70 e0 19 00 00 f0 19 00 00 00 1a 00 00 10 1a 00 00 |................|
+00001e80 20 1a 00 00 30 1a 00 00 40 1a 00 00 50 1a 00 00 | ...0...@...P...|
+00001e90 60 1a 00 00 70 1a 00 00 80 1a 00 00 90 1a 00 00 |`...p...........|
+00001ea0 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 d0 1a 00 00 |................|
+00001eb0 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 10 1b 00 00 |................|
+00001ec0 20 1b 00 00 30 1b 00 00 40 1b 00 00 50 1b 00 00 | ...0...@...P...|
+00001ed0 60 1b 00 00 70 1b 00 00 80 1b 00 00 90 1b 00 00 |`...p...........|
+00001ee0 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 d0 1b 00 00 |................|
+00001ef0 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 10 1c 00 00 |................|
+00001f00 20 1c 00 00 30 1c 00 00 40 1c 00 00 50 1c 00 00 | ...0...@...P...|
+00001f10 60 1c 00 00 70 1c 00 00 80 1c 00 00 90 1c 00 00 |`...p...........|
+00001f20 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 d0 1c 00 00 |................|
+00001f30 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 10 1d 00 00 |................|
+00001f40 20 1d 00 00 30 1d 00 00 40 1d 00 00 50 1d 00 00 | ...0...@...P...|
+00001f50 60 1d 00 00 70 1d 00 00 80 1d 00 00 90 1d 00 00 |`...p...........|
+00001f60 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 d0 1d 00 00 |................|
+00001f70 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 10 1e 00 00 |................|
+00001f80 20 1e 00 00 30 1e 00 00 40 1e 00 00 50 1e 00 00 | ...0...@...P...|
+00001f90 60 1e 00 00 70 1e 00 00 80 1e 00 00 90 1e 00 00 |`...p...........|
+00001fa0 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 d0 1e 00 00 |................|
+00001fb0 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 10 1f 00 00 |................|
+00001fc0 20 1f 00 00 30 1f 00 00 40 1f 00 00 50 1f 00 00 | ...0...@...P...|
+00001fd0 60 1f 00 00 70 1f 00 00 80 1f 00 00 90 1f 00 00 |`...p...........|
+00001fe0 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 d0 1f 00 00 |................|
+00001ff0 e0 1f 00 00 f0 1f 00 00 00 20 00 00 10 20 00 00 |......... ... ..|
+00002000 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00004200 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00004210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004220 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00004230 ff 00 00 00 01 00 00 00 c1 3e 00 00 00 40 00 00 |.........>...@..|
+00004240 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00004250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004280 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00004290 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000042a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000042b0 01 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........|
+000042c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004310 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00004320 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00006000 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.hex
new file mode 100644
index 000000000000..9de588957fb1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.hex
@@ -0,0 +1,558 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002040 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002050 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002060 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002070 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002080 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002090 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+000020a0 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020b0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020c0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020d0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020e0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020f0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+00002100 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002110 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002120 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002130 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002140 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002150 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002160 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002170 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002180 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002190 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+000021a0 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021b0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021c0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021d0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021e0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021f0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+00002200 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002210 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002220 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002230 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002240 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002250 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002260 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002270 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002280 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002290 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+000022a0 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022b0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022c0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022d0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022e0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022f0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+00002300 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002310 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002320 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002330 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002340 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002350 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002360 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002370 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002380 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002390 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+000023a0 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023b0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023c0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023d0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023e0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023f0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+00002400 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002410 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002420 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002430 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002440 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002450 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002460 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002470 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002480 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002490 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+000024a0 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024b0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024c0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024d0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024e0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024f0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+00002500 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002510 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002520 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002530 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002540 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002550 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002560 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002570 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002580 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002590 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+000025a0 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025b0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025c0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025d0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025e0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025f0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+00002600 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002610 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002620 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002630 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002640 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002650 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002660 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002670 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002680 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002690 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+000026a0 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026b0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026c0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026d0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026e0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026f0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+00002700 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002710 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002720 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002730 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002740 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002750 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002760 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002770 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002780 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002790 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+000027a0 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027b0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027c0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027d0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027e0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027f0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+00002800 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002810 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002820 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002830 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002840 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002850 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002860 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002870 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002880 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002890 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+000028a0 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028b0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028c0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028d0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028e0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028f0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+00002900 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002910 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002920 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002930 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002940 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002950 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002960 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002970 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002980 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002990 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+000029a0 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029b0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029c0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029d0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029e0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029f0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+00002a00 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a10 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a20 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a30 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a40 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a50 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a60 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a70 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a80 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a90 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002aa0 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002ab0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ac0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ad0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ae0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002af0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002b00 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b10 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b20 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b30 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b40 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b50 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b60 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b70 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b80 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b90 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002ba0 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002bb0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bc0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bd0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002be0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bf0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002c00 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c10 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c20 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c30 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c40 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c50 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c60 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c70 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c80 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c90 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002ca0 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002cb0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cc0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cd0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002ce0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cf0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002d00 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d10 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d20 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d30 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d40 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d50 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d60 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d70 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d80 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d90 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002da0 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002db0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002dc0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dd0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002de0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002df0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002e00 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e10 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e20 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e30 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e40 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e50 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e60 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e70 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e80 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e90 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002ea0 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002eb0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002ec0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ed0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ee0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ef0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002f00 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f10 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f20 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f30 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f40 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f50 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f60 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f70 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f80 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f90 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002fa0 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fb0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fc0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fd0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fe0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002ff0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00003000 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003010 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003020 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003030 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003040 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003050 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003080 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003090 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+000030a0 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030b0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030c0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030d0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+00003100 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003110 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003120 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003130 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003140 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003150 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003160 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003170 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003180 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003190 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+000031a0 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031b0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031c0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031d0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+00003200 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003210 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003220 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003230 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003240 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003250 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003280 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003290 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+000032a0 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032b0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032c0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032d0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+00003300 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003310 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003320 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003330 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003340 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003350 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003380 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003390 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+000033a0 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033b0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033c0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033d0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+00003400 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003410 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003420 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003430 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003440 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003450 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003480 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003490 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+000034a0 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034b0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034c0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034d0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+00003500 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003510 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003520 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003530 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003540 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003550 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003580 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003590 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+000035a0 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035b0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035c0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035d0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+00003600 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003610 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003620 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003630 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003640 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003650 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003680 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003690 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+000036a0 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036b0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036c0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036d0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+00003700 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003710 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003720 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003730 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003740 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003750 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003760 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003770 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003780 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003790 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+000037a0 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037b0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037c0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037d0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+00003800 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003810 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003820 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003830 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003840 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003850 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003880 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003890 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+000038a0 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038b0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038c0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038d0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+00003900 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003910 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003920 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003930 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003940 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003950 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003980 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003990 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+000039a0 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039b0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039c0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039d0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+00003a00 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a10 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a20 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a30 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a40 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a50 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a80 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a90 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003aa0 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003ab0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ac0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ad0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003b00 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b10 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b20 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b30 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b40 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b50 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b80 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b90 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003ba0 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003bb0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bc0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bd0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003c00 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c10 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c20 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c30 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c40 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c50 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c80 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c90 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003ca0 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003cb0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cc0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cd0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003d00 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d10 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d20 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d30 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d40 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d50 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d80 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d90 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003da0 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003db0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003dc0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dd0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003e00 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e10 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e20 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e30 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e40 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e50 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e80 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e90 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003ea0 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003eb0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003ec0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ed0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003f00 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f10 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f20 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f30 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f40 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f50 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f80 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f90 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003fa0 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fb0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fc0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fd0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00004000 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004010 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004020 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004030 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004040 00 00 00 00 00 40 70 00 00 00 00 00 00 40 80 00 |.....@p......@..|
+00004050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000051c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00007010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00007020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00007030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00007040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00007050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00007090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000070a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000070b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000070c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00007120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00408e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.hex
new file mode 100644
index 000000000000..250d0b8508e2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.hex
@@ -0,0 +1,82 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000501c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00057e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00058000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00058010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00058020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00058030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00058040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00058050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00058090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000580a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000580b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000580c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00058120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00059e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00459e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.hex
new file mode 100644
index 000000000000..716a382cae69
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.hex
@@ -0,0 +1,32 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007e0000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.hex
new file mode 100644
index 000000000000..22c20dc667a5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.hex
@@ -0,0 +1,64 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00000030 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00000040 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 08 |................|
+00000220 00 20 00 00 ff ff f4 6f 00 00 00 00 00 00 00 00 |. .....o........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+00000bc0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008800 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008a00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008a20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008a30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008a40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008a80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008a90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00008aa0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00008ab0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00008ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008b10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008b20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+0000a800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+0040ac00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650a00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00650a10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00650a20 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00650a30 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00650a40 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00650a50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00650a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650c00
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.hex
new file mode 100644
index 000000000000..097d9e00dfe5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.hex
@@ -0,0 +1,40 @@
+00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+01000010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+01000020 00 02 00 00 57 69 32 6b 00 00 00 00 01 00 00 00 |....Wi2k........|
+01000030 00 00 00 00 01 00 00 00 00 02 ff 3f 00 00 00 02 |...........?....|
+01000040 ff ff ef bd 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+01000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+01000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdx.hex
new file mode 100644
index 000000000000..08ab31138195
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdx.hex
@@ -0,0 +1,81 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+004001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00408000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00408010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00408020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00408030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00408040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00408050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00408090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+004080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00408120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00409e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00809e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.hex
new file mode 100644
index 000000000000..5c41298f81db
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.hex
@@ -0,0 +1,326 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00000610 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00000620 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00000630 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00000640 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00000650 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00000660 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00000670 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00000680 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00000690 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000006a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000006b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000006c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000006d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000006e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000006f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00000700 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00000710 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00000720 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00000730 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00000740 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00000750 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00000760 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00000770 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00000780 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00000790 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000007a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000007b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000007c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000007d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000007e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000007f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00000800 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00000810 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00000820 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00000830 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00000840 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00000850 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00000860 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00000870 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00000880 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00000890 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+000008a0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+000008b0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+000008c0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+000008d0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+000008e0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+000008f0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00000900 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00000910 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00000920 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00000930 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00000940 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00000950 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00000960 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00000970 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00000980 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00000990 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+000009a0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+000009b0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+000009c0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+000009d0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+000009e0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+000009f0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00000a00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00000a10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00000a20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00000a30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00000a40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00000a50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00000a60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00000a70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00000a80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00000a90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00000aa0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00000ab0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00000ac0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00000ad0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00000ae0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00000af0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00000b00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00000b10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00000b20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00000b30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00000b40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00000b50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00000b60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00000b70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00000b80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00000b90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00000ba0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00000bb0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00000bc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00000bd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00000be0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00000bf0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00000c00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00000c10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00000c20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00000c30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00000c40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00000c50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00000c60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00000c70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00000c80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00000c90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00000ca0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00000cb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00000cc0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00000cd0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00000ce0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00000cf0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00000d00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00000d10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00000d20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00000d30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00000d40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00000d50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00000d60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00000d70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00000d80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00000d90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00000da0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00000db0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00000dc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00000dd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00000de0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00000df0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00000e00 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00000e10 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00000e20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00001810 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00001820 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00001830 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00001840 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00001850 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00001860 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00001870 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00001880 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00001890 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000018a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000018b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000018c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000018d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000018e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000018f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00001900 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00001910 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00001920 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00001930 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00001940 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00001950 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00001960 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00001970 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00001980 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00001990 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000019a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000019b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000019c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000019d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000019e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000019f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00001a00 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00001a10 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00001a20 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00001a30 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00001a40 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00001a50 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00001a60 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00001a70 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00001a80 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00001a90 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+00001aa0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+00001ab0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+00001ac0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+00001ad0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+00001ae0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+00001af0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00001b00 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00001b10 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00001b20 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00001b30 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00001b40 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00001b50 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00001b60 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00001b70 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00001b80 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00001b90 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+00001ba0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+00001bb0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+00001bc0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+00001bd0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+00001be0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+00001bf0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00001c00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00001c10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00001c20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00001c30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00001c40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00001c50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00001c60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00001c70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00001c80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00001c90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00001ca0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00001cb0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00001cc0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00001cd0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00001ce0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00001cf0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00001d00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00001d10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00001d20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00001d30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00001d40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00001d50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00001d60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00001d70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00001d80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00001d90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00001da0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00001db0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00001dc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00001dd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00001de0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00001df0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00001e00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00001e10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00001e20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00001e30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00001e40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00001e50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00001e60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00001e70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00001e80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00001e90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00001ea0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00001eb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00001ec0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00001ed0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00001ee0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00001ef0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00001f00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00001f10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00001f20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00001f30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00001f40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00001f50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00001f60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00001f70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00001f80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00001f90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00001fa0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00001fb0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00001fc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00001fd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00001fe0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00001ff0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00002000 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00002010 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 |................|
+000041c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040a000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.hex
new file mode 100644
index 000000000000..510bbf80e208
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.hex
@@ -0,0 +1,579 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 42 90 00 |.............B..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00002020 00 00 00 00 00 00 60 00 00 00 00 00 00 00 70 00 |......`.......p.|
+00002030 00 00 00 00 00 00 80 00 00 00 00 00 00 00 90 00 |................|
+00002040 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 b0 00 |................|
+00002050 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 d0 00 |................|
+00002060 00 00 00 00 00 00 e0 00 00 00 00 00 00 00 f0 00 |................|
+00002070 00 00 00 00 00 01 00 00 00 00 00 00 00 01 10 00 |................|
+00002080 00 00 00 00 00 01 20 00 00 00 00 00 00 01 30 00 |...... .......0.|
+00002090 00 00 00 00 00 01 40 00 00 00 00 00 00 01 50 00 |......@.......P.|
+000020a0 00 00 00 00 00 01 60 00 00 00 00 00 00 01 70 00 |......`.......p.|
+000020b0 00 00 00 00 00 01 80 00 00 00 00 00 00 01 90 00 |................|
+000020c0 00 00 00 00 00 01 a0 00 00 00 00 00 00 01 b0 00 |................|
+000020d0 00 00 00 00 00 01 c0 00 00 00 00 00 00 01 d0 00 |................|
+000020e0 00 00 00 00 00 01 e0 00 00 00 00 00 00 01 f0 00 |................|
+000020f0 00 00 00 00 00 02 00 00 00 00 00 00 00 02 10 00 |................|
+00002100 00 00 00 00 00 02 20 00 00 00 00 00 00 02 30 00 |...... .......0.|
+00002110 00 00 00 00 00 02 40 00 00 00 00 00 00 02 50 00 |......@.......P.|
+00002120 00 00 00 00 00 02 60 00 00 00 00 00 00 02 70 00 |......`.......p.|
+00002130 00 00 00 00 00 02 80 00 00 00 00 00 00 02 90 00 |................|
+00002140 00 00 00 00 00 02 a0 00 00 00 00 00 00 02 b0 00 |................|
+00002150 00 00 00 00 00 02 c0 00 00 00 00 00 00 02 d0 00 |................|
+00002160 00 00 00 00 00 02 e0 00 00 00 00 00 00 02 f0 00 |................|
+00002170 00 00 00 00 00 03 00 00 00 00 00 00 00 03 10 00 |................|
+00002180 00 00 00 00 00 03 20 00 00 00 00 00 00 03 30 00 |...... .......0.|
+00002190 00 00 00 00 00 03 40 00 00 00 00 00 00 03 50 00 |......@.......P.|
+000021a0 00 00 00 00 00 03 60 00 00 00 00 00 00 03 70 00 |......`.......p.|
+000021b0 00 00 00 00 00 03 80 00 00 00 00 00 00 03 90 00 |................|
+000021c0 00 00 00 00 00 03 a0 00 00 00 00 00 00 03 b0 00 |................|
+000021d0 00 00 00 00 00 03 c0 00 00 00 00 00 00 03 d0 00 |................|
+000021e0 00 00 00 00 00 03 e0 00 00 00 00 00 00 03 f0 00 |................|
+000021f0 00 00 00 00 00 04 00 00 00 00 00 00 00 04 10 00 |................|
+00002200 00 00 00 00 00 04 20 00 00 00 00 00 00 04 30 00 |...... .......0.|
+00002210 00 00 00 00 00 04 40 00 00 00 00 00 00 04 50 00 |......@.......P.|
+00002220 00 00 00 00 00 04 60 00 00 00 00 00 00 04 70 00 |......`.......p.|
+00002230 00 00 00 00 00 04 80 00 00 00 00 00 00 04 90 00 |................|
+00002240 00 00 00 00 00 04 a0 00 00 00 00 00 00 04 b0 00 |................|
+00002250 00 00 00 00 00 04 c0 00 00 00 00 00 00 04 d0 00 |................|
+00002260 00 00 00 00 00 04 e0 00 00 00 00 00 00 04 f0 00 |................|
+00002270 00 00 00 00 00 05 00 00 00 00 00 00 00 05 10 00 |................|
+00002280 00 00 00 00 00 05 20 00 00 00 00 00 00 05 30 00 |...... .......0.|
+00002290 00 00 00 00 00 05 40 00 00 00 00 00 00 05 50 00 |......@.......P.|
+000022a0 00 00 00 00 00 05 60 00 00 00 00 00 00 05 70 00 |......`.......p.|
+000022b0 00 00 00 00 00 05 80 00 00 00 00 00 00 05 90 00 |................|
+000022c0 00 00 00 00 00 05 a0 00 00 00 00 00 00 05 b0 00 |................|
+000022d0 00 00 00 00 00 05 c0 00 00 00 00 00 00 05 d0 00 |................|
+000022e0 00 00 00 00 00 05 e0 00 00 00 00 00 00 05 f0 00 |................|
+000022f0 00 00 00 00 00 06 00 00 00 00 00 00 00 06 10 00 |................|
+00002300 00 00 00 00 00 06 20 00 00 00 00 00 00 06 30 00 |...... .......0.|
+00002310 00 00 00 00 00 06 40 00 00 00 00 00 00 06 50 00 |......@.......P.|
+00002320 00 00 00 00 00 06 60 00 00 00 00 00 00 06 70 00 |......`.......p.|
+00002330 00 00 00 00 00 06 80 00 00 00 00 00 00 06 90 00 |................|
+00002340 00 00 00 00 00 06 a0 00 00 00 00 00 00 06 b0 00 |................|
+00002350 00 00 00 00 00 06 c0 00 00 00 00 00 00 06 d0 00 |................|
+00002360 00 00 00 00 00 06 e0 00 00 00 00 00 00 06 f0 00 |................|
+00002370 00 00 00 00 00 07 00 00 00 00 00 00 00 07 10 00 |................|
+00002380 00 00 00 00 00 07 20 00 00 00 00 00 00 07 30 00 |...... .......0.|
+00002390 00 00 00 00 00 07 40 00 00 00 00 00 00 07 50 00 |......@.......P.|
+000023a0 00 00 00 00 00 07 60 00 00 00 00 00 00 07 70 00 |......`.......p.|
+000023b0 00 00 00 00 00 07 80 00 00 00 00 00 00 07 90 00 |................|
+000023c0 00 00 00 00 00 07 a0 00 00 00 00 00 00 07 b0 00 |................|
+000023d0 00 00 00 00 00 07 c0 00 00 00 00 00 00 07 d0 00 |................|
+000023e0 00 00 00 00 00 07 e0 00 00 00 00 00 00 07 f0 00 |................|
+000023f0 00 00 00 00 00 08 00 00 00 00 00 00 00 08 10 00 |................|
+00002400 00 00 00 00 00 08 20 00 00 00 00 00 00 08 30 00 |...... .......0.|
+00002410 00 00 00 00 00 08 40 00 00 00 00 00 00 08 50 00 |......@.......P.|
+00002420 00 00 00 00 00 08 60 00 00 00 00 00 00 08 70 00 |......`.......p.|
+00002430 00 00 00 00 00 08 80 00 00 00 00 00 00 08 90 00 |................|
+00002440 00 00 00 00 00 08 a0 00 00 00 00 00 00 08 b0 00 |................|
+00002450 00 00 00 00 00 08 c0 00 00 00 00 00 00 08 d0 00 |................|
+00002460 00 00 00 00 00 08 e0 00 00 00 00 00 00 08 f0 00 |................|
+00002470 00 00 00 00 00 09 00 00 00 00 00 00 00 09 10 00 |................|
+00002480 00 00 00 00 00 09 20 00 00 00 00 00 00 09 30 00 |...... .......0.|
+00002490 00 00 00 00 00 09 40 00 00 00 00 00 00 09 50 00 |......@.......P.|
+000024a0 00 00 00 00 00 09 60 00 00 00 00 00 00 09 70 00 |......`.......p.|
+000024b0 00 00 00 00 00 09 80 00 00 00 00 00 00 09 90 00 |................|
+000024c0 00 00 00 00 00 09 a0 00 00 00 00 00 00 09 b0 00 |................|
+000024d0 00 00 00 00 00 09 c0 00 00 00 00 00 00 09 d0 00 |................|
+000024e0 00 00 00 00 00 09 e0 00 00 00 00 00 00 09 f0 00 |................|
+000024f0 00 00 00 00 00 0a 00 00 00 00 00 00 00 0a 10 00 |................|
+00002500 00 00 00 00 00 0a 20 00 00 00 00 00 00 0a 30 00 |...... .......0.|
+00002510 00 00 00 00 00 0a 40 00 00 00 00 00 00 0a 50 00 |......@.......P.|
+00002520 00 00 00 00 00 0a 60 00 00 00 00 00 00 0a 70 00 |......`.......p.|
+00002530 00 00 00 00 00 0a 80 00 00 00 00 00 00 0a 90 00 |................|
+00002540 00 00 00 00 00 0a a0 00 00 00 00 00 00 0a b0 00 |................|
+00002550 00 00 00 00 00 0a c0 00 00 00 00 00 00 0a d0 00 |................|
+00002560 00 00 00 00 00 0a e0 00 00 00 00 00 00 0a f0 00 |................|
+00002570 00 00 00 00 00 0b 00 00 00 00 00 00 00 0b 10 00 |................|
+00002580 00 00 00 00 00 0b 20 00 00 00 00 00 00 0b 30 00 |...... .......0.|
+00002590 00 00 00 00 00 0b 40 00 00 00 00 00 00 0b 50 00 |......@.......P.|
+000025a0 00 00 00 00 00 0b 60 00 00 00 00 00 00 0b 70 00 |......`.......p.|
+000025b0 00 00 00 00 00 0b 80 00 00 00 00 00 00 0b 90 00 |................|
+000025c0 00 00 00 00 00 0b a0 00 00 00 00 00 00 0b b0 00 |................|
+000025d0 00 00 00 00 00 0b c0 00 00 00 00 00 00 0b d0 00 |................|
+000025e0 00 00 00 00 00 0b e0 00 00 00 00 00 00 0b f0 00 |................|
+000025f0 00 00 00 00 00 0c 00 00 00 00 00 00 00 0c 10 00 |................|
+00002600 00 00 00 00 00 0c 20 00 00 00 00 00 00 0c 30 00 |...... .......0.|
+00002610 00 00 00 00 00 0c 40 00 00 00 00 00 00 0c 50 00 |......@.......P.|
+00002620 00 00 00 00 00 0c 60 00 00 00 00 00 00 0c 70 00 |......`.......p.|
+00002630 00 00 00 00 00 0c 80 00 00 00 00 00 00 0c 90 00 |................|
+00002640 00 00 00 00 00 0c a0 00 00 00 00 00 00 0c b0 00 |................|
+00002650 00 00 00 00 00 0c c0 00 00 00 00 00 00 0c d0 00 |................|
+00002660 00 00 00 00 00 0c e0 00 00 00 00 00 00 0c f0 00 |................|
+00002670 00 00 00 00 00 0d 00 00 00 00 00 00 00 0d 10 00 |................|
+00002680 00 00 00 00 00 0d 20 00 00 00 00 00 00 0d 30 00 |...... .......0.|
+00002690 00 00 00 00 00 0d 40 00 00 00 00 00 00 0d 50 00 |......@.......P.|
+000026a0 00 00 00 00 00 0d 60 00 00 00 00 00 00 0d 70 00 |......`.......p.|
+000026b0 00 00 00 00 00 0d 80 00 00 00 00 00 00 0d 90 00 |................|
+000026c0 00 00 00 00 00 0d a0 00 00 00 00 00 00 0d b0 00 |................|
+000026d0 00 00 00 00 00 0d c0 00 00 00 00 00 00 0d d0 00 |................|
+000026e0 00 00 00 00 00 0d e0 00 00 00 00 00 00 0d f0 00 |................|
+000026f0 00 00 00 00 00 0e 00 00 00 00 00 00 00 0e 10 00 |................|
+00002700 00 00 00 00 00 0e 20 00 00 00 00 00 00 0e 30 00 |...... .......0.|
+00002710 00 00 00 00 00 0e 40 00 00 00 00 00 00 0e 50 00 |......@.......P.|
+00002720 00 00 00 00 00 0e 60 00 00 00 00 00 00 0e 70 00 |......`.......p.|
+00002730 00 00 00 00 00 0e 80 00 00 00 00 00 00 0e 90 00 |................|
+00002740 00 00 00 00 00 0e a0 00 00 00 00 00 00 0e b0 00 |................|
+00002750 00 00 00 00 00 0e c0 00 00 00 00 00 00 0e d0 00 |................|
+00002760 00 00 00 00 00 0e e0 00 00 00 00 00 00 0e f0 00 |................|
+00002770 00 00 00 00 00 0f 00 00 00 00 00 00 00 0f 10 00 |................|
+00002780 00 00 00 00 00 0f 20 00 00 00 00 00 00 0f 30 00 |...... .......0.|
+00002790 00 00 00 00 00 0f 40 00 00 00 00 00 00 0f 50 00 |......@.......P.|
+000027a0 00 00 00 00 00 0f 60 00 00 00 00 00 00 0f 70 00 |......`.......p.|
+000027b0 00 00 00 00 00 0f 80 00 00 00 00 00 00 0f 90 00 |................|
+000027c0 00 00 00 00 00 0f a0 00 00 00 00 00 00 0f b0 00 |................|
+000027d0 00 00 00 00 00 0f c0 00 00 00 00 00 00 0f d0 00 |................|
+000027e0 00 00 00 00 00 0f e0 00 00 00 00 00 00 0f f0 00 |................|
+000027f0 00 00 00 00 00 10 00 00 00 00 00 00 00 10 10 00 |................|
+00002800 00 00 00 00 00 10 20 00 00 00 00 00 00 10 30 00 |...... .......0.|
+00002810 00 00 00 00 00 10 40 00 00 00 00 00 00 10 50 00 |......@.......P.|
+00002820 00 00 00 00 00 10 60 00 00 00 00 00 00 10 70 00 |......`.......p.|
+00002830 00 00 00 00 00 10 80 00 00 00 00 00 00 10 90 00 |................|
+00002840 00 00 00 00 00 10 a0 00 00 00 00 00 00 10 b0 00 |................|
+00002850 00 00 00 00 00 10 c0 00 00 00 00 00 00 10 d0 00 |................|
+00002860 00 00 00 00 00 10 e0 00 00 00 00 00 00 10 f0 00 |................|
+00002870 00 00 00 00 00 11 00 00 00 00 00 00 00 11 10 00 |................|
+00002880 00 00 00 00 00 11 20 00 00 00 00 00 00 11 30 00 |...... .......0.|
+00002890 00 00 00 00 00 11 40 00 00 00 00 00 00 11 50 00 |......@.......P.|
+000028a0 00 00 00 00 00 11 60 00 00 00 00 00 00 11 70 00 |......`.......p.|
+000028b0 00 00 00 00 00 11 80 00 00 00 00 00 00 11 90 00 |................|
+000028c0 00 00 00 00 00 11 a0 00 00 00 00 00 00 11 b0 00 |................|
+000028d0 00 00 00 00 00 11 c0 00 00 00 00 00 00 11 d0 00 |................|
+000028e0 00 00 00 00 00 11 e0 00 00 00 00 00 00 11 f0 00 |................|
+000028f0 00 00 00 00 00 12 00 00 00 00 00 00 00 12 10 00 |................|
+00002900 00 00 00 00 00 12 20 00 00 00 00 00 00 12 30 00 |...... .......0.|
+00002910 00 00 00 00 00 12 40 00 00 00 00 00 00 12 50 00 |......@.......P.|
+00002920 00 00 00 00 00 12 60 00 00 00 00 00 00 12 70 00 |......`.......p.|
+00002930 00 00 00 00 00 12 80 00 00 00 00 00 00 12 90 00 |................|
+00002940 00 00 00 00 00 12 a0 00 00 00 00 00 00 12 b0 00 |................|
+00002950 00 00 00 00 00 12 c0 00 00 00 00 00 00 12 d0 00 |................|
+00002960 00 00 00 00 00 12 e0 00 00 00 00 00 00 12 f0 00 |................|
+00002970 00 00 00 00 00 13 00 00 00 00 00 00 00 13 10 00 |................|
+00002980 00 00 00 00 00 13 20 00 00 00 00 00 00 13 30 00 |...... .......0.|
+00002990 00 00 00 00 00 13 40 00 00 00 00 00 00 13 50 00 |......@.......P.|
+000029a0 00 00 00 00 00 13 60 00 00 00 00 00 00 13 70 00 |......`.......p.|
+000029b0 00 00 00 00 00 13 80 00 00 00 00 00 00 13 90 00 |................|
+000029c0 00 00 00 00 00 13 a0 00 00 00 00 00 00 13 b0 00 |................|
+000029d0 00 00 00 00 00 13 c0 00 00 00 00 00 00 13 d0 00 |................|
+000029e0 00 00 00 00 00 13 e0 00 00 00 00 00 00 13 f0 00 |................|
+000029f0 00 00 00 00 00 14 00 00 00 00 00 00 00 14 10 00 |................|
+00002a00 00 00 00 00 00 14 20 00 00 00 00 00 00 14 30 00 |...... .......0.|
+00002a10 00 00 00 00 00 14 40 00 00 00 00 00 00 14 50 00 |......@.......P.|
+00002a20 00 00 00 00 00 14 60 00 00 00 00 00 00 14 70 00 |......`.......p.|
+00002a30 00 00 00 00 00 14 80 00 00 00 00 00 00 14 90 00 |................|
+00002a40 00 00 00 00 00 14 a0 00 00 00 00 00 00 14 b0 00 |................|
+00002a50 00 00 00 00 00 14 c0 00 00 00 00 00 00 14 d0 00 |................|
+00002a60 00 00 00 00 00 14 e0 00 00 00 00 00 00 14 f0 00 |................|
+00002a70 00 00 00 00 00 15 00 00 00 00 00 00 00 15 10 00 |................|
+00002a80 00 00 00 00 00 15 20 00 00 00 00 00 00 15 30 00 |...... .......0.|
+00002a90 00 00 00 00 00 15 40 00 00 00 00 00 00 15 50 00 |......@.......P.|
+00002aa0 00 00 00 00 00 15 60 00 00 00 00 00 00 15 70 00 |......`.......p.|
+00002ab0 00 00 00 00 00 15 80 00 00 00 00 00 00 15 90 00 |................|
+00002ac0 00 00 00 00 00 15 a0 00 00 00 00 00 00 15 b0 00 |................|
+00002ad0 00 00 00 00 00 15 c0 00 00 00 00 00 00 15 d0 00 |................|
+00002ae0 00 00 00 00 00 15 e0 00 00 00 00 00 00 15 f0 00 |................|
+00002af0 00 00 00 00 00 16 00 00 00 00 00 00 00 16 10 00 |................|
+00002b00 00 00 00 00 00 16 20 00 00 00 00 00 00 16 30 00 |...... .......0.|
+00002b10 00 00 00 00 00 16 40 00 00 00 00 00 00 16 50 00 |......@.......P.|
+00002b20 00 00 00 00 00 16 60 00 00 00 00 00 00 16 70 00 |......`.......p.|
+00002b30 00 00 00 00 00 16 80 00 00 00 00 00 00 16 90 00 |................|
+00002b40 00 00 00 00 00 16 a0 00 00 00 00 00 00 16 b0 00 |................|
+00002b50 00 00 00 00 00 16 c0 00 00 00 00 00 00 16 d0 00 |................|
+00002b60 00 00 00 00 00 16 e0 00 00 00 00 00 00 16 f0 00 |................|
+00002b70 00 00 00 00 00 17 00 00 00 00 00 00 00 17 10 00 |................|
+00002b80 00 00 00 00 00 17 20 00 00 00 00 00 00 17 30 00 |...... .......0.|
+00002b90 00 00 00 00 00 17 40 00 00 00 00 00 00 17 50 00 |......@.......P.|
+00002ba0 00 00 00 00 00 17 60 00 00 00 00 00 00 17 70 00 |......`.......p.|
+00002bb0 00 00 00 00 00 17 80 00 00 00 00 00 00 17 90 00 |................|
+00002bc0 00 00 00 00 00 17 a0 00 00 00 00 00 00 17 b0 00 |................|
+00002bd0 00 00 00 00 00 17 c0 00 00 00 00 00 00 17 d0 00 |................|
+00002be0 00 00 00 00 00 17 e0 00 00 00 00 00 00 17 f0 00 |................|
+00002bf0 00 00 00 00 00 18 00 00 00 00 00 00 00 18 10 00 |................|
+00002c00 00 00 00 00 00 18 20 00 00 00 00 00 00 18 30 00 |...... .......0.|
+00002c10 00 00 00 00 00 18 40 00 00 00 00 00 00 18 50 00 |......@.......P.|
+00002c20 00 00 00 00 00 18 60 00 00 00 00 00 00 18 70 00 |......`.......p.|
+00002c30 00 00 00 00 00 18 80 00 00 00 00 00 00 18 90 00 |................|
+00002c40 00 00 00 00 00 18 a0 00 00 00 00 00 00 18 b0 00 |................|
+00002c50 00 00 00 00 00 18 c0 00 00 00 00 00 00 18 d0 00 |................|
+00002c60 00 00 00 00 00 18 e0 00 00 00 00 00 00 18 f0 00 |................|
+00002c70 00 00 00 00 00 19 00 00 00 00 00 00 00 19 10 00 |................|
+00002c80 00 00 00 00 00 19 20 00 00 00 00 00 00 19 30 00 |...... .......0.|
+00002c90 00 00 00 00 00 19 40 00 00 00 00 00 00 19 50 00 |......@.......P.|
+00002ca0 00 00 00 00 00 19 60 00 00 00 00 00 00 19 70 00 |......`.......p.|
+00002cb0 00 00 00 00 00 19 80 00 00 00 00 00 00 19 90 00 |................|
+00002cc0 00 00 00 00 00 19 a0 00 00 00 00 00 00 19 b0 00 |................|
+00002cd0 00 00 00 00 00 19 c0 00 00 00 00 00 00 19 d0 00 |................|
+00002ce0 00 00 00 00 00 19 e0 00 00 00 00 00 00 19 f0 00 |................|
+00002cf0 00 00 00 00 00 1a 00 00 00 00 00 00 00 1a 10 00 |................|
+00002d00 00 00 00 00 00 1a 20 00 00 00 00 00 00 1a 30 00 |...... .......0.|
+00002d10 00 00 00 00 00 1a 40 00 00 00 00 00 00 1a 50 00 |......@.......P.|
+00002d20 00 00 00 00 00 1a 60 00 00 00 00 00 00 1a 70 00 |......`.......p.|
+00002d30 00 00 00 00 00 1a 80 00 00 00 00 00 00 1a 90 00 |................|
+00002d40 00 00 00 00 00 1a a0 00 00 00 00 00 00 1a b0 00 |................|
+00002d50 00 00 00 00 00 1a c0 00 00 00 00 00 00 1a d0 00 |................|
+00002d60 00 00 00 00 00 1a e0 00 00 00 00 00 00 1a f0 00 |................|
+00002d70 00 00 00 00 00 1b 00 00 00 00 00 00 00 1b 10 00 |................|
+00002d80 00 00 00 00 00 1b 20 00 00 00 00 00 00 1b 30 00 |...... .......0.|
+00002d90 00 00 00 00 00 1b 40 00 00 00 00 00 00 1b 50 00 |......@.......P.|
+00002da0 00 00 00 00 00 1b 60 00 00 00 00 00 00 1b 70 00 |......`.......p.|
+00002db0 00 00 00 00 00 1b 80 00 00 00 00 00 00 1b 90 00 |................|
+00002dc0 00 00 00 00 00 1b a0 00 00 00 00 00 00 1b b0 00 |................|
+00002dd0 00 00 00 00 00 1b c0 00 00 00 00 00 00 1b d0 00 |................|
+00002de0 00 00 00 00 00 1b e0 00 00 00 00 00 00 1b f0 00 |................|
+00002df0 00 00 00 00 00 1c 00 00 00 00 00 00 00 1c 10 00 |................|
+00002e00 00 00 00 00 00 1c 20 00 00 00 00 00 00 1c 30 00 |...... .......0.|
+00002e10 00 00 00 00 00 1c 40 00 00 00 00 00 00 1c 50 00 |......@.......P.|
+00002e20 00 00 00 00 00 1c 60 00 00 00 00 00 00 1c 70 00 |......`.......p.|
+00002e30 00 00 00 00 00 1c 80 00 00 00 00 00 00 1c 90 00 |................|
+00002e40 00 00 00 00 00 1c a0 00 00 00 00 00 00 1c b0 00 |................|
+00002e50 00 00 00 00 00 1c c0 00 00 00 00 00 00 1c d0 00 |................|
+00002e60 00 00 00 00 00 1c e0 00 00 00 00 00 00 1c f0 00 |................|
+00002e70 00 00 00 00 00 1d 00 00 00 00 00 00 00 1d 10 00 |................|
+00002e80 00 00 00 00 00 1d 20 00 00 00 00 00 00 1d 30 00 |...... .......0.|
+00002e90 00 00 00 00 00 1d 40 00 00 00 00 00 00 1d 50 00 |......@.......P.|
+00002ea0 00 00 00 00 00 1d 60 00 00 00 00 00 00 1d 70 00 |......`.......p.|
+00002eb0 00 00 00 00 00 1d 80 00 00 00 00 00 00 1d 90 00 |................|
+00002ec0 00 00 00 00 00 1d a0 00 00 00 00 00 00 1d b0 00 |................|
+00002ed0 00 00 00 00 00 1d c0 00 00 00 00 00 00 1d d0 00 |................|
+00002ee0 00 00 00 00 00 1d e0 00 00 00 00 00 00 1d f0 00 |................|
+00002ef0 00 00 00 00 00 1e 00 00 00 00 00 00 00 1e 10 00 |................|
+00002f00 00 00 00 00 00 1e 20 00 00 00 00 00 00 1e 30 00 |...... .......0.|
+00002f10 00 00 00 00 00 1e 40 00 00 00 00 00 00 1e 50 00 |......@.......P.|
+00002f20 00 00 00 00 00 1e 60 00 00 00 00 00 00 1e 70 00 |......`.......p.|
+00002f30 00 00 00 00 00 1e 80 00 00 00 00 00 00 1e 90 00 |................|
+00002f40 00 00 00 00 00 1e a0 00 00 00 00 00 00 1e b0 00 |................|
+00002f50 00 00 00 00 00 1e c0 00 00 00 00 00 00 1e d0 00 |................|
+00002f60 00 00 00 00 00 1e e0 00 00 00 00 00 00 1e f0 00 |................|
+00002f70 00 00 00 00 00 1f 00 00 00 00 00 00 00 1f 10 00 |................|
+00002f80 00 00 00 00 00 1f 20 00 00 00 00 00 00 1f 30 00 |...... .......0.|
+00002f90 00 00 00 00 00 1f 40 00 00 00 00 00 00 1f 50 00 |......@.......P.|
+00002fa0 00 00 00 00 00 1f 60 00 00 00 00 00 00 1f 70 00 |......`.......p.|
+00002fb0 00 00 00 00 00 1f 80 00 00 00 00 00 00 1f 90 00 |................|
+00002fc0 00 00 00 00 00 1f a0 00 00 00 00 00 00 1f b0 00 |................|
+00002fd0 00 00 00 00 00 1f c0 00 00 00 00 00 00 1f d0 00 |................|
+00002fe0 00 00 00 00 00 1f e0 00 00 00 00 00 00 1f f0 00 |................|
+00002ff0 00 00 00 00 00 20 00 00 00 00 00 00 00 20 10 00 |..... ....... ..|
+00003000 00 00 00 00 00 20 20 00 00 00 00 00 00 20 30 00 |..... ...... 0.|
+00003010 00 00 00 00 00 20 40 00 00 00 00 00 00 20 50 00 |..... @...... P.|
+00003020 00 00 00 00 00 20 60 00 00 00 00 00 00 20 70 00 |..... `...... p.|
+00003030 00 00 00 00 00 20 80 00 00 00 00 00 00 20 90 00 |..... ....... ..|
+00003040 00 00 00 00 00 20 a0 00 00 00 00 00 00 20 b0 00 |..... ....... ..|
+00003050 00 00 00 00 00 20 c0 00 00 00 00 00 00 20 d0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 e0 00 00 00 00 00 00 20 f0 00 |..... ....... ..|
+00003070 00 00 00 00 00 21 00 00 00 00 00 00 00 21 10 00 |.....!.......!..|
+00003080 00 00 00 00 00 21 20 00 00 00 00 00 00 21 30 00 |.....! ......!0.|
+00003090 00 00 00 00 00 21 40 00 00 00 00 00 00 21 50 00 |.....!@......!P.|
+000030a0 00 00 00 00 00 21 60 00 00 00 00 00 00 21 70 00 |.....!`......!p.|
+000030b0 00 00 00 00 00 21 80 00 00 00 00 00 00 21 90 00 |.....!.......!..|
+000030c0 00 00 00 00 00 21 a0 00 00 00 00 00 00 21 b0 00 |.....!.......!..|
+000030d0 00 00 00 00 00 21 c0 00 00 00 00 00 00 21 d0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 e0 00 00 00 00 00 00 21 f0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 22 00 00 00 00 00 00 00 22 10 00 |....."......."..|
+00003100 00 00 00 00 00 22 20 00 00 00 00 00 00 22 30 00 |....." ......"0.|
+00003110 00 00 00 00 00 22 40 00 00 00 00 00 00 22 50 00 |....."@......"P.|
+00003120 00 00 00 00 00 22 60 00 00 00 00 00 00 22 70 00 |....."`......"p.|
+00003130 00 00 00 00 00 22 80 00 00 00 00 00 00 22 90 00 |....."......."..|
+00003140 00 00 00 00 00 22 a0 00 00 00 00 00 00 22 b0 00 |....."......."..|
+00003150 00 00 00 00 00 22 c0 00 00 00 00 00 00 22 d0 00 |....."......."..|
+00003160 00 00 00 00 00 22 e0 00 00 00 00 00 00 22 f0 00 |....."......."..|
+00003170 00 00 00 00 00 23 00 00 00 00 00 00 00 23 10 00 |.....#.......#..|
+00003180 00 00 00 00 00 23 20 00 00 00 00 00 00 23 30 00 |.....# ......#0.|
+00003190 00 00 00 00 00 23 40 00 00 00 00 00 00 23 50 00 |.....#@......#P.|
+000031a0 00 00 00 00 00 23 60 00 00 00 00 00 00 23 70 00 |.....#`......#p.|
+000031b0 00 00 00 00 00 23 80 00 00 00 00 00 00 23 90 00 |.....#.......#..|
+000031c0 00 00 00 00 00 23 a0 00 00 00 00 00 00 23 b0 00 |.....#.......#..|
+000031d0 00 00 00 00 00 23 c0 00 00 00 00 00 00 23 d0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 e0 00 00 00 00 00 00 23 f0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 24 00 00 00 00 00 00 00 24 10 00 |.....$.......$..|
+00003200 00 00 00 00 00 24 20 00 00 00 00 00 00 24 30 00 |.....$ ......$0.|
+00003210 00 00 00 00 00 24 40 00 00 00 00 00 00 24 50 00 |.....$@......$P.|
+00003220 00 00 00 00 00 24 60 00 00 00 00 00 00 24 70 00 |.....$`......$p.|
+00003230 00 00 00 00 00 24 80 00 00 00 00 00 00 24 90 00 |.....$.......$..|
+00003240 00 00 00 00 00 24 a0 00 00 00 00 00 00 24 b0 00 |.....$.......$..|
+00003250 00 00 00 00 00 24 c0 00 00 00 00 00 00 24 d0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 e0 00 00 00 00 00 00 24 f0 00 |.....$.......$..|
+00003270 00 00 00 00 00 25 00 00 00 00 00 00 00 25 10 00 |.....%.......%..|
+00003280 00 00 00 00 00 25 20 00 00 00 00 00 00 25 30 00 |.....% ......%0.|
+00003290 00 00 00 00 00 25 40 00 00 00 00 00 00 25 50 00 |.....%@......%P.|
+000032a0 00 00 00 00 00 25 60 00 00 00 00 00 00 25 70 00 |.....%`......%p.|
+000032b0 00 00 00 00 00 25 80 00 00 00 00 00 00 25 90 00 |.....%.......%..|
+000032c0 00 00 00 00 00 25 a0 00 00 00 00 00 00 25 b0 00 |.....%.......%..|
+000032d0 00 00 00 00 00 25 c0 00 00 00 00 00 00 25 d0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 e0 00 00 00 00 00 00 25 f0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 26 00 00 00 00 00 00 00 26 10 00 |.....&.......&..|
+00003300 00 00 00 00 00 26 20 00 00 00 00 00 00 26 30 00 |.....& ......&0.|
+00003310 00 00 00 00 00 26 40 00 00 00 00 00 00 26 50 00 |.....&@......&P.|
+00003320 00 00 00 00 00 26 60 00 00 00 00 00 00 26 70 00 |.....&`......&p.|
+00003330 00 00 00 00 00 26 80 00 00 00 00 00 00 26 90 00 |.....&.......&..|
+00003340 00 00 00 00 00 26 a0 00 00 00 00 00 00 26 b0 00 |.....&.......&..|
+00003350 00 00 00 00 00 26 c0 00 00 00 00 00 00 26 d0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 e0 00 00 00 00 00 00 26 f0 00 |.....&.......&..|
+00003370 00 00 00 00 00 27 00 00 00 00 00 00 00 27 10 00 |.....'.......'..|
+00003380 00 00 00 00 00 27 20 00 00 00 00 00 00 27 30 00 |.....' ......'0.|
+00003390 00 00 00 00 00 27 40 00 00 00 00 00 00 27 50 00 |.....'@......'P.|
+000033a0 00 00 00 00 00 27 60 00 00 00 00 00 00 27 70 00 |.....'`......'p.|
+000033b0 00 00 00 00 00 27 80 00 00 00 00 00 00 27 90 00 |.....'.......'..|
+000033c0 00 00 00 00 00 27 a0 00 00 00 00 00 00 27 b0 00 |.....'.......'..|
+000033d0 00 00 00 00 00 27 c0 00 00 00 00 00 00 27 d0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 e0 00 00 00 00 00 00 27 f0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 28 00 00 00 00 00 00 00 28 10 00 |.....(.......(..|
+00003400 00 00 00 00 00 28 20 00 00 00 00 00 00 28 30 00 |.....( ......(0.|
+00003410 00 00 00 00 00 28 40 00 00 00 00 00 00 28 50 00 |.....(@......(P.|
+00003420 00 00 00 00 00 28 60 00 00 00 00 00 00 28 70 00 |.....(`......(p.|
+00003430 00 00 00 00 00 28 80 00 00 00 00 00 00 28 90 00 |.....(.......(..|
+00003440 00 00 00 00 00 28 a0 00 00 00 00 00 00 28 b0 00 |.....(.......(..|
+00003450 00 00 00 00 00 28 c0 00 00 00 00 00 00 28 d0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 e0 00 00 00 00 00 00 28 f0 00 |.....(.......(..|
+00003470 00 00 00 00 00 29 00 00 00 00 00 00 00 29 10 00 |.....).......)..|
+00003480 00 00 00 00 00 29 20 00 00 00 00 00 00 29 30 00 |.....) ......)0.|
+00003490 00 00 00 00 00 29 40 00 00 00 00 00 00 29 50 00 |.....)@......)P.|
+000034a0 00 00 00 00 00 29 60 00 00 00 00 00 00 29 70 00 |.....)`......)p.|
+000034b0 00 00 00 00 00 29 80 00 00 00 00 00 00 29 90 00 |.....).......)..|
+000034c0 00 00 00 00 00 29 a0 00 00 00 00 00 00 29 b0 00 |.....).......)..|
+000034d0 00 00 00 00 00 29 c0 00 00 00 00 00 00 29 d0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 e0 00 00 00 00 00 00 29 f0 00 |.....).......)..|
+000034f0 00 00 00 00 00 2a 00 00 00 00 00 00 00 2a 10 00 |.....*.......*..|
+00003500 00 00 00 00 00 2a 20 00 00 00 00 00 00 2a 30 00 |.....* ......*0.|
+00003510 00 00 00 00 00 2a 40 00 00 00 00 00 00 2a 50 00 |.....*@......*P.|
+00003520 00 00 00 00 00 2a 60 00 00 00 00 00 00 2a 70 00 |.....*`......*p.|
+00003530 00 00 00 00 00 2a 80 00 00 00 00 00 00 2a 90 00 |.....*.......*..|
+00003540 00 00 00 00 00 2a a0 00 00 00 00 00 00 2a b0 00 |.....*.......*..|
+00003550 00 00 00 00 00 2a c0 00 00 00 00 00 00 2a d0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a e0 00 00 00 00 00 00 2a f0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2b 00 00 00 00 00 00 00 2b 10 00 |.....+.......+..|
+00003580 00 00 00 00 00 2b 20 00 00 00 00 00 00 2b 30 00 |.....+ ......+0.|
+00003590 00 00 00 00 00 2b 40 00 00 00 00 00 00 2b 50 00 |.....+@......+P.|
+000035a0 00 00 00 00 00 2b 60 00 00 00 00 00 00 2b 70 00 |.....+`......+p.|
+000035b0 00 00 00 00 00 2b 80 00 00 00 00 00 00 2b 90 00 |.....+.......+..|
+000035c0 00 00 00 00 00 2b a0 00 00 00 00 00 00 2b b0 00 |.....+.......+..|
+000035d0 00 00 00 00 00 2b c0 00 00 00 00 00 00 2b d0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b e0 00 00 00 00 00 00 2b f0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2c 00 00 00 00 00 00 00 2c 10 00 |.....,.......,..|
+00003600 00 00 00 00 00 2c 20 00 00 00 00 00 00 2c 30 00 |....., ......,0.|
+00003610 00 00 00 00 00 2c 40 00 00 00 00 00 00 2c 50 00 |.....,@......,P.|
+00003620 00 00 00 00 00 2c 60 00 00 00 00 00 00 2c 70 00 |.....,`......,p.|
+00003630 00 00 00 00 00 2c 80 00 00 00 00 00 00 2c 90 00 |.....,.......,..|
+00003640 00 00 00 00 00 2c a0 00 00 00 00 00 00 2c b0 00 |.....,.......,..|
+00003650 00 00 00 00 00 2c c0 00 00 00 00 00 00 2c d0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c e0 00 00 00 00 00 00 2c f0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2d 00 00 00 00 00 00 00 2d 10 00 |.....-.......-..|
+00003680 00 00 00 00 00 2d 20 00 00 00 00 00 00 2d 30 00 |.....- ......-0.|
+00003690 00 00 00 00 00 2d 40 00 00 00 00 00 00 2d 50 00 |.....-@......-P.|
+000036a0 00 00 00 00 00 2d 60 00 00 00 00 00 00 2d 70 00 |.....-`......-p.|
+000036b0 00 00 00 00 00 2d 80 00 00 00 00 00 00 2d 90 00 |.....-.......-..|
+000036c0 00 00 00 00 00 2d a0 00 00 00 00 00 00 2d b0 00 |.....-.......-..|
+000036d0 00 00 00 00 00 2d c0 00 00 00 00 00 00 2d d0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d e0 00 00 00 00 00 00 2d f0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2e 00 00 00 00 00 00 00 2e 10 00 |................|
+00003700 00 00 00 00 00 2e 20 00 00 00 00 00 00 2e 30 00 |...... .......0.|
+00003710 00 00 00 00 00 2e 40 00 00 00 00 00 00 2e 50 00 |......@.......P.|
+00003720 00 00 00 00 00 2e 60 00 00 00 00 00 00 2e 70 00 |......`.......p.|
+00003730 00 00 00 00 00 2e 80 00 00 00 00 00 00 2e 90 00 |................|
+00003740 00 00 00 00 00 2e a0 00 00 00 00 00 00 2e b0 00 |................|
+00003750 00 00 00 00 00 2e c0 00 00 00 00 00 00 2e d0 00 |................|
+00003760 00 00 00 00 00 2e e0 00 00 00 00 00 00 2e f0 00 |................|
+00003770 00 00 00 00 00 2f 00 00 00 00 00 00 00 2f 10 00 |...../......./..|
+00003780 00 00 00 00 00 2f 20 00 00 00 00 00 00 2f 30 00 |...../ ....../0.|
+00003790 00 00 00 00 00 2f 40 00 00 00 00 00 00 2f 50 00 |...../@....../P.|
+000037a0 00 00 00 00 00 2f 60 00 00 00 00 00 00 2f 70 00 |...../`....../p.|
+000037b0 00 00 00 00 00 2f 80 00 00 00 00 00 00 2f 90 00 |...../......./..|
+000037c0 00 00 00 00 00 2f a0 00 00 00 00 00 00 2f b0 00 |...../......./..|
+000037d0 00 00 00 00 00 2f c0 00 00 00 00 00 00 2f d0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f e0 00 00 00 00 00 00 2f f0 00 |...../......./..|
+000037f0 00 00 00 00 00 30 00 00 00 00 00 00 00 30 10 00 |.....0.......0..|
+00003800 00 00 00 00 00 30 20 00 00 00 00 00 00 30 30 00 |.....0 ......00.|
+00003810 00 00 00 00 00 30 40 00 00 00 00 00 00 30 50 00 |.....0@......0P.|
+00003820 00 00 00 00 00 30 60 00 00 00 00 00 00 30 70 00 |.....0`......0p.|
+00003830 00 00 00 00 00 30 80 00 00 00 00 00 00 30 90 00 |.....0.......0..|
+00003840 00 00 00 00 00 30 a0 00 00 00 00 00 00 30 b0 00 |.....0.......0..|
+00003850 00 00 00 00 00 30 c0 00 00 00 00 00 00 30 d0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 e0 00 00 00 00 00 00 30 f0 00 |.....0.......0..|
+00003870 00 00 00 00 00 31 00 00 00 00 00 00 00 31 10 00 |.....1.......1..|
+00003880 00 00 00 00 00 31 20 00 00 00 00 00 00 31 30 00 |.....1 ......10.|
+00003890 00 00 00 00 00 31 40 00 00 00 00 00 00 31 50 00 |.....1@......1P.|
+000038a0 00 00 00 00 00 31 60 00 00 00 00 00 00 31 70 00 |.....1`......1p.|
+000038b0 00 00 00 00 00 31 80 00 00 00 00 00 00 31 90 00 |.....1.......1..|
+000038c0 00 00 00 00 00 31 a0 00 00 00 00 00 00 31 b0 00 |.....1.......1..|
+000038d0 00 00 00 00 00 31 c0 00 00 00 00 00 00 31 d0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 e0 00 00 00 00 00 00 31 f0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 32 00 00 00 00 00 00 00 32 10 00 |.....2.......2..|
+00003900 00 00 00 00 00 32 20 00 00 00 00 00 00 32 30 00 |.....2 ......20.|
+00003910 00 00 00 00 00 32 40 00 00 00 00 00 00 32 50 00 |.....2@......2P.|
+00003920 00 00 00 00 00 32 60 00 00 00 00 00 00 32 70 00 |.....2`......2p.|
+00003930 00 00 00 00 00 32 80 00 00 00 00 00 00 32 90 00 |.....2.......2..|
+00003940 00 00 00 00 00 32 a0 00 00 00 00 00 00 32 b0 00 |.....2.......2..|
+00003950 00 00 00 00 00 32 c0 00 00 00 00 00 00 32 d0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 e0 00 00 00 00 00 00 32 f0 00 |.....2.......2..|
+00003970 00 00 00 00 00 33 00 00 00 00 00 00 00 33 10 00 |.....3.......3..|
+00003980 00 00 00 00 00 33 20 00 00 00 00 00 00 33 30 00 |.....3 ......30.|
+00003990 00 00 00 00 00 33 40 00 00 00 00 00 00 33 50 00 |.....3@......3P.|
+000039a0 00 00 00 00 00 33 60 00 00 00 00 00 00 33 70 00 |.....3`......3p.|
+000039b0 00 00 00 00 00 33 80 00 00 00 00 00 00 33 90 00 |.....3.......3..|
+000039c0 00 00 00 00 00 33 a0 00 00 00 00 00 00 33 b0 00 |.....3.......3..|
+000039d0 00 00 00 00 00 33 c0 00 00 00 00 00 00 33 d0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 e0 00 00 00 00 00 00 33 f0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 34 00 00 00 00 00 00 00 34 10 00 |.....4.......4..|
+00003a00 00 00 00 00 00 34 20 00 00 00 00 00 00 34 30 00 |.....4 ......40.|
+00003a10 00 00 00 00 00 34 40 00 00 00 00 00 00 34 50 00 |.....4@......4P.|
+00003a20 00 00 00 00 00 34 60 00 00 00 00 00 00 34 70 00 |.....4`......4p.|
+00003a30 00 00 00 00 00 34 80 00 00 00 00 00 00 34 90 00 |.....4.......4..|
+00003a40 00 00 00 00 00 34 a0 00 00 00 00 00 00 34 b0 00 |.....4.......4..|
+00003a50 00 00 00 00 00 34 c0 00 00 00 00 00 00 34 d0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 e0 00 00 00 00 00 00 34 f0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 35 00 00 00 00 00 00 00 35 10 00 |.....5.......5..|
+00003a80 00 00 00 00 00 35 20 00 00 00 00 00 00 35 30 00 |.....5 ......50.|
+00003a90 00 00 00 00 00 35 40 00 00 00 00 00 00 35 50 00 |.....5@......5P.|
+00003aa0 00 00 00 00 00 35 60 00 00 00 00 00 00 35 70 00 |.....5`......5p.|
+00003ab0 00 00 00 00 00 35 80 00 00 00 00 00 00 35 90 00 |.....5.......5..|
+00003ac0 00 00 00 00 00 35 a0 00 00 00 00 00 00 35 b0 00 |.....5.......5..|
+00003ad0 00 00 00 00 00 35 c0 00 00 00 00 00 00 35 d0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 e0 00 00 00 00 00 00 35 f0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 36 00 00 00 00 00 00 00 36 10 00 |.....6.......6..|
+00003b00 00 00 00 00 00 36 20 00 00 00 00 00 00 36 30 00 |.....6 ......60.|
+00003b10 00 00 00 00 00 36 40 00 00 00 00 00 00 36 50 00 |.....6@......6P.|
+00003b20 00 00 00 00 00 36 60 00 00 00 00 00 00 36 70 00 |.....6`......6p.|
+00003b30 00 00 00 00 00 36 80 00 00 00 00 00 00 36 90 00 |.....6.......6..|
+00003b40 00 00 00 00 00 36 a0 00 00 00 00 00 00 36 b0 00 |.....6.......6..|
+00003b50 00 00 00 00 00 36 c0 00 00 00 00 00 00 36 d0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 e0 00 00 00 00 00 00 36 f0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 37 00 00 00 00 00 00 00 37 10 00 |.....7.......7..|
+00003b80 00 00 00 00 00 37 20 00 00 00 00 00 00 37 30 00 |.....7 ......70.|
+00003b90 00 00 00 00 00 37 40 00 00 00 00 00 00 37 50 00 |.....7@......7P.|
+00003ba0 00 00 00 00 00 37 60 00 00 00 00 00 00 37 70 00 |.....7`......7p.|
+00003bb0 00 00 00 00 00 37 80 00 00 00 00 00 00 37 90 00 |.....7.......7..|
+00003bc0 00 00 00 00 00 37 a0 00 00 00 00 00 00 37 b0 00 |.....7.......7..|
+00003bd0 00 00 00 00 00 37 c0 00 00 00 00 00 00 37 d0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 e0 00 00 00 00 00 00 37 f0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 38 00 00 00 00 00 00 00 38 10 00 |.....8.......8..|
+00003c00 00 00 00 00 00 38 20 00 00 00 00 00 00 38 30 00 |.....8 ......80.|
+00003c10 00 00 00 00 00 38 40 00 00 00 00 00 00 38 50 00 |.....8@......8P.|
+00003c20 00 00 00 00 00 38 60 00 00 00 00 00 00 38 70 00 |.....8`......8p.|
+00003c30 00 00 00 00 00 38 80 00 00 00 00 00 00 38 90 00 |.....8.......8..|
+00003c40 00 00 00 00 00 38 a0 00 00 00 00 00 00 38 b0 00 |.....8.......8..|
+00003c50 00 00 00 00 00 38 c0 00 00 00 00 00 00 38 d0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 e0 00 00 00 00 00 00 38 f0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 39 00 00 00 00 00 00 00 39 10 00 |.....9.......9..|
+00003c80 00 00 00 00 00 39 20 00 00 00 00 00 00 39 30 00 |.....9 ......90.|
+00003c90 00 00 00 00 00 39 40 00 00 00 00 00 00 39 50 00 |.....9@......9P.|
+00003ca0 00 00 00 00 00 39 60 00 00 00 00 00 00 39 70 00 |.....9`......9p.|
+00003cb0 00 00 00 00 00 39 80 00 00 00 00 00 00 39 90 00 |.....9.......9..|
+00003cc0 00 00 00 00 00 39 a0 00 00 00 00 00 00 39 b0 00 |.....9.......9..|
+00003cd0 00 00 00 00 00 39 c0 00 00 00 00 00 00 39 d0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 e0 00 00 00 00 00 00 39 f0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 3a 00 00 00 00 00 00 00 3a 10 00 |.....:.......:..|
+00003d00 00 00 00 00 00 3a 20 00 00 00 00 00 00 3a 30 00 |.....: ......:0.|
+00003d10 00 00 00 00 00 3a 40 00 00 00 00 00 00 3a 50 00 |.....:@......:P.|
+00003d20 00 00 00 00 00 3a 60 00 00 00 00 00 00 3a 70 00 |.....:`......:p.|
+00003d30 00 00 00 00 00 3a 80 00 00 00 00 00 00 3a 90 00 |.....:.......:..|
+00003d40 00 00 00 00 00 3a a0 00 00 00 00 00 00 3a b0 00 |.....:.......:..|
+00003d50 00 00 00 00 00 3a c0 00 00 00 00 00 00 3a d0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a e0 00 00 00 00 00 00 3a f0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3b 00 00 00 00 00 00 00 3b 10 00 |.....;.......;..|
+00003d80 00 00 00 00 00 3b 20 00 00 00 00 00 00 3b 30 00 |.....; ......;0.|
+00003d90 00 00 00 00 00 3b 40 00 00 00 00 00 00 3b 50 00 |.....;@......;P.|
+00003da0 00 00 00 00 00 3b 60 00 00 00 00 00 00 3b 70 00 |.....;`......;p.|
+00003db0 00 00 00 00 00 3b 80 00 00 00 00 00 00 3b 90 00 |.....;.......;..|
+00003dc0 00 00 00 00 00 3b a0 00 00 00 00 00 00 3b b0 00 |.....;.......;..|
+00003dd0 00 00 00 00 00 3b c0 00 00 00 00 00 00 3b d0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b e0 00 00 00 00 00 00 3b f0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3c 00 00 00 00 00 00 00 3c 10 00 |.....<.......<..|
+00003e00 00 00 00 00 00 3c 20 00 00 00 00 00 00 3c 30 00 |.....< ......<0.|
+00003e10 00 00 00 00 00 3c 40 00 00 00 00 00 00 3c 50 00 |.....<@......<P.|
+00003e20 00 00 00 00 00 3c 60 00 00 00 00 00 00 3c 70 00 |.....<`......<p.|
+00003e30 00 00 00 00 00 3c 80 00 00 00 00 00 00 3c 90 00 |.....<.......<..|
+00003e40 00 00 00 00 00 3c a0 00 00 00 00 00 00 3c b0 00 |.....<.......<..|
+00003e50 00 00 00 00 00 3c c0 00 00 00 00 00 00 3c d0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c e0 00 00 00 00 00 00 3c f0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3d 00 00 00 00 00 00 00 3d 10 00 |.....=.......=..|
+00003e80 00 00 00 00 00 3d 20 00 00 00 00 00 00 3d 30 00 |.....= ......=0.|
+00003e90 00 00 00 00 00 3d 40 00 00 00 00 00 00 3d 50 00 |.....=@......=P.|
+00003ea0 00 00 00 00 00 3d 60 00 00 00 00 00 00 3d 70 00 |.....=`......=p.|
+00003eb0 00 00 00 00 00 3d 80 00 00 00 00 00 00 3d 90 00 |.....=.......=..|
+00003ec0 00 00 00 00 00 3d a0 00 00 00 00 00 00 3d b0 00 |.....=.......=..|
+00003ed0 00 00 00 00 00 3d c0 00 00 00 00 00 00 3d d0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d e0 00 00 00 00 00 00 3d f0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3e 00 00 00 00 00 00 00 3e 10 00 |.....>.......>..|
+00003f00 00 00 00 00 00 3e 20 00 00 00 00 00 00 3e 30 00 |.....> ......>0.|
+00003f10 00 00 00 00 00 3e 40 00 00 00 00 00 00 3e 50 00 |.....>@......>P.|
+00003f20 00 00 00 00 00 3e 60 00 00 00 00 00 00 3e 70 00 |.....>`......>p.|
+00003f30 00 00 00 00 00 3e 80 00 00 00 00 00 00 3e 90 00 |.....>.......>..|
+00003f40 00 00 00 00 00 3e a0 00 00 00 00 00 00 3e b0 00 |.....>.......>..|
+00003f50 00 00 00 00 00 3e c0 00 00 00 00 00 00 3e d0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e e0 00 00 00 00 00 00 3e f0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3f 00 00 00 00 00 00 00 3f 10 00 |.....?.......?..|
+00003f80 00 00 00 00 00 3f 20 00 00 00 00 00 00 3f 30 00 |.....? ......?0.|
+00003f90 00 00 00 00 00 3f 40 00 00 00 00 00 00 3f 50 00 |.....?@......?P.|
+00003fa0 00 00 00 00 00 3f 60 00 00 00 00 00 00 3f 70 00 |.....?`......?p.|
+00003fb0 00 00 00 00 00 3f 80 00 00 00 00 00 00 3f 90 00 |.....?.......?..|
+00003fc0 00 00 00 00 00 3f a0 00 00 00 00 00 00 3f b0 00 |.....?.......?..|
+00003fd0 00 00 00 00 00 3f c0 00 00 00 00 00 00 3f d0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f e0 00 00 00 00 00 00 3f f0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 40 00 00 00 00 00 00 00 40 10 00 |.....@.......@..|
+00004000 00 00 00 00 00 40 20 00 00 00 00 00 00 40 30 00 |.....@ ......@0.|
+00004010 00 00 00 00 00 40 40 00 00 00 00 00 00 40 50 00 |.....@@......@P.|
+00004020 00 00 00 00 00 40 60 00 00 00 00 00 00 00 00 00 |.....@`.........|
+00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004120 00 00 00 00 00 40 70 00 00 00 00 00 00 00 00 00 |.....@p.........|
+00004130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00004140 00 00 00 00 00 40 80 00 00 00 00 00 00 00 00 00 |.....@..........|
+00004150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000051c0 02 00 ee ff ff ff 01 00 00 00 47 21 00 00 00 00 |..........G!....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00005210 b9 61 9d d5 00 00 00 00 01 00 00 00 00 00 00 00 |.a..............|
+00005220 47 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |G!......".......|
+00005230 26 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |&!..............|
+00005240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00005250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00005260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00005420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00005430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00005490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000054a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000054b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00407e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00407e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00407e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00407e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00407ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00407eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408e00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00408e10 af e3 04 05 00 00 00 00 47 21 00 00 00 00 00 00 |........G!......|
+00408e20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00408e30 26 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |&!..............|
+00408e40 03 03 03 03 03 03 03 03 27 21 00 00 00 00 00 00 |........'!......|
+00408e50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00408e60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.hex
new file mode 100644
index 000000000000..9a12f90cb5af
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.hex
@@ -0,0 +1,101 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 43 00 00 |.............C..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 80 00 00 00 00 46 00 00 00 00 00 00 00 00 00 00 |.....F..........|
+00030220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000501c0 02 00 ee ff ff ff 01 00 00 00 7f 21 00 00 00 00 |...........!....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00050210 f2 13 00 92 00 00 00 00 01 00 00 00 00 00 00 00 |................|
+00050220 7f 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.!......".......|
+00050230 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+00050240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00050250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00050260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00050420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00050430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00050490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000504a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000504b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00054400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00454400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+0046be20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+0046be30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046be80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+0046be90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+0046bea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+0046beb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0046fe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0046fe10 62 6b 07 b6 00 00 00 00 7f 21 00 00 00 00 00 00 |bk.......!......|
+0046fe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0046fe30 5e 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |^!..............|
+0046fe40 03 03 03 03 03 03 03 03 5f 21 00 00 00 00 00 00 |........_!......|
+0046fe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+0046fe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00470000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.hex
new file mode 100644
index 000000000000..b464168daaa4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.hex
@@ -0,0 +1,48 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 42 21 00 00 00 00 |..........B!....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 a6 70 3a 54 00 00 00 00 01 00 00 00 00 00 00 00 |.p:T............|
+00000220 42 21 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |B!......".......|
+00000230 21 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |!!..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00424400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00424410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00424420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00424430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00424480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00424490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004244a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+004244b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00428400 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00428410 75 64 ec d2 00 00 00 00 42 21 00 00 00 00 00 00 |ud......B!......|
+00428420 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00428430 21 21 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |!!..............|
+00428440 03 03 03 03 03 03 03 03 22 21 00 00 00 00 00 00 |........"!......|
+00428450 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00428460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00428600
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.hex
new file mode 100644
index 000000000000..94fbb99cbdb9
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.hex
@@ -0,0 +1,84 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00000030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00000040 ff ff f5 87 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00000050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 04 |................|
+00000220 00 20 00 00 ff ff f4 73 00 00 00 00 00 00 00 00 |. .....s........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 00 00 30 07 |.......... ...0.|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+00000bc0 02 00 ee ff ff ff 01 00 00 00 c0 3e 00 00 00 00 |...........>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000c10 41 28 3e 1b 00 00 00 00 01 00 00 00 00 00 00 00 |A(>.............|
+00000c20 c0 3e 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.>......".......|
+00000c30 9f 3e 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.>..............|
+00000c40 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000c50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000c60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00000ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00000eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00405200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00600e00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00601000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d5000 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007d5010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+007d5020 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+007d5030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d5080 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007d5090 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+007d50a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+007d50b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007d9000 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+007d9010 51 6d 56 70 00 00 00 00 c0 3e 00 00 00 00 00 00 |QmVp.....>......|
+007d9020 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+007d9030 9f 3e 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.>..............|
+007d9040 03 03 03 03 03 03 03 03 a0 3e 00 00 00 00 00 00 |.........>......|
+007d9050 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+007d9060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00801000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00801010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00801020 00 02 00 00 57 69 32 6b 00 00 00 00 00 7d 82 00 |....Wi2k.....}..|
+00801030 00 00 00 00 00 7d 82 00 00 01 ff 3f 00 00 00 03 |.....}.....?....|
+00801040 ff ff f5 87 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00801050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00801060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00801200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.hex
new file mode 100644
index 000000000000..3ee432909549
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.hex
@@ -0,0 +1,56 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000001c0 02 00 ee ff ff ff 01 00 00 00 ff 3f 00 00 00 00 |...........?....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00000210 39 64 0d 41 00 00 00 00 01 00 00 00 00 00 00 00 |9d.A............|
+00000220 ff 3f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.?......".......|
+00000230 de 3f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.?..............|
+00000240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00000250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00000490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00404400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+007fbe20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+007fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+007fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+007fbea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+007fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+007ffe10 0c 71 38 f5 00 00 00 00 ff 3f 00 00 00 00 00 00 |.q8......?......|
+007ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+007ffe30 de 3f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.?..............|
+007ffe40 03 03 03 03 03 03 03 03 df 3f 00 00 00 00 00 00 |.........?......|
+007ffe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+007ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00800010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00800020 00 02 00 00 57 69 32 6b 00 00 00 00 00 80 00 00 |....Wi2k........|
+00800030 00 00 00 00 00 80 00 00 00 01 ff 3f 00 00 00 02 |...........?....|
+00800040 ff ff ee 90 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00800050 04 04 04 04 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00800060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00800200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdx.hex
new file mode 100644
index 000000000000..1aef760fa90a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdx.hex
@@ -0,0 +1,99 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+004001c0 02 00 ee ff ff ff 01 00 00 00 ff 7f 00 00 00 00 |................|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00400210 76 87 2e 0d 00 00 00 00 01 00 00 00 00 00 00 00 |v...............|
+00400220 ff 7f 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+00400230 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+00400240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00400250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00400260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00400420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00400430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00400490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+004004a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+004004b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00404400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00804400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+013fbe20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+013fbe30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013fbe80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+013fbe90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+013fbea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+013fbeb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+013ffe00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+013ffe10 c8 d6 d8 f4 00 00 00 00 ff 7f 00 00 00 00 00 00 |................|
+013ffe20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+013ffe30 de 7f 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |................|
+013ffe40 03 03 03 03 03 03 03 03 df 7f 00 00 00 00 00 00 |................|
+013ffe50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+013ffe60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.hex
new file mode 100644
index 000000000000..8311d98ee9c0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.hex
@@ -0,0 +1,348 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 28 00 00 |KDMV.........(..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 30 32 34 30 20 53 50 41 52 |on.RW 10240 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 30 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "0".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00000610 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00000620 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00000630 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00000640 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00000650 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00000660 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00000670 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00000680 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00000690 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000006a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000006b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000006c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000006d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000006e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000006f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00000700 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00000710 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00000720 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00000730 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00000740 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00000750 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00000760 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00000770 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00000780 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00000790 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000007a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000007b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000007c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000007d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000007e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000007f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00000800 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00000810 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00000820 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00000830 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00000840 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00000850 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00000860 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00000870 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00000880 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00000890 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+000008a0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+000008b0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+000008c0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+000008d0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+000008e0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+000008f0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00000900 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00000910 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00000920 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00000930 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00000940 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00000950 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00000960 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00000970 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00000980 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00000990 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+000009a0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+000009b0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+000009c0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+000009d0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+000009e0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+000009f0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00000a00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00000a10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00000a20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00000a30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00000a40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00000a50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00000a60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00000a70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00000a80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00000a90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00000aa0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00000ab0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00000ac0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00000ad0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00000ae0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00000af0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00000b00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00000b10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00000b20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00000b30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00000b40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00000b50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00000b60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00000b70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00000b80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00000b90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00000ba0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00000bb0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00000bc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00000bd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00000be0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00000bf0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00000c00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00000c10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00000c20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00000c30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00000c40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00000c50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00000c60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00000c70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00000c80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00000c90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00000ca0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00000cb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00000cc0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00000cd0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00000ce0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00000cf0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00000d00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00000d10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00000d20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00000d30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00000d40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00000d50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00000d60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00000d70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00000d80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00000d90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00000da0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00000db0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00000dc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00000dd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00000de0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00000df0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00000e00 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00000e10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000ff0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 30 00 00 00 40 00 00 00 | .......0...@...|
+00001810 50 00 00 00 60 00 00 00 70 00 00 00 80 00 00 00 |P...`...p.......|
+00001820 90 00 00 00 a0 00 00 00 b0 00 00 00 c0 00 00 00 |................|
+00001830 d0 00 00 00 e0 00 00 00 f0 00 00 00 00 01 00 00 |................|
+00001840 10 01 00 00 20 01 00 00 30 01 00 00 40 01 00 00 |.... ...0...@...|
+00001850 50 01 00 00 60 01 00 00 70 01 00 00 80 01 00 00 |P...`...p.......|
+00001860 90 01 00 00 a0 01 00 00 b0 01 00 00 c0 01 00 00 |................|
+00001870 d0 01 00 00 e0 01 00 00 f0 01 00 00 00 02 00 00 |................|
+00001880 10 02 00 00 20 02 00 00 30 02 00 00 40 02 00 00 |.... ...0...@...|
+00001890 50 02 00 00 60 02 00 00 70 02 00 00 80 02 00 00 |P...`...p.......|
+000018a0 90 02 00 00 a0 02 00 00 b0 02 00 00 c0 02 00 00 |................|
+000018b0 d0 02 00 00 e0 02 00 00 f0 02 00 00 00 03 00 00 |................|
+000018c0 10 03 00 00 20 03 00 00 30 03 00 00 40 03 00 00 |.... ...0...@...|
+000018d0 50 03 00 00 60 03 00 00 70 03 00 00 80 03 00 00 |P...`...p.......|
+000018e0 90 03 00 00 a0 03 00 00 b0 03 00 00 c0 03 00 00 |................|
+000018f0 d0 03 00 00 e0 03 00 00 f0 03 00 00 00 04 00 00 |................|
+00001900 10 04 00 00 20 04 00 00 30 04 00 00 40 04 00 00 |.... ...0...@...|
+00001910 50 04 00 00 60 04 00 00 70 04 00 00 80 04 00 00 |P...`...p.......|
+00001920 90 04 00 00 a0 04 00 00 b0 04 00 00 c0 04 00 00 |................|
+00001930 d0 04 00 00 e0 04 00 00 f0 04 00 00 00 05 00 00 |................|
+00001940 10 05 00 00 20 05 00 00 30 05 00 00 40 05 00 00 |.... ...0...@...|
+00001950 50 05 00 00 60 05 00 00 70 05 00 00 80 05 00 00 |P...`...p.......|
+00001960 90 05 00 00 a0 05 00 00 b0 05 00 00 c0 05 00 00 |................|
+00001970 d0 05 00 00 e0 05 00 00 f0 05 00 00 00 06 00 00 |................|
+00001980 10 06 00 00 20 06 00 00 30 06 00 00 40 06 00 00 |.... ...0...@...|
+00001990 50 06 00 00 60 06 00 00 70 06 00 00 80 06 00 00 |P...`...p.......|
+000019a0 90 06 00 00 a0 06 00 00 b0 06 00 00 c0 06 00 00 |................|
+000019b0 d0 06 00 00 e0 06 00 00 f0 06 00 00 00 07 00 00 |................|
+000019c0 10 07 00 00 20 07 00 00 30 07 00 00 40 07 00 00 |.... ...0...@...|
+000019d0 50 07 00 00 60 07 00 00 70 07 00 00 80 07 00 00 |P...`...p.......|
+000019e0 90 07 00 00 a0 07 00 00 b0 07 00 00 c0 07 00 00 |................|
+000019f0 d0 07 00 00 e0 07 00 00 f0 07 00 00 00 08 00 00 |................|
+00001a00 10 08 00 00 20 08 00 00 30 08 00 00 40 08 00 00 |.... ...0...@...|
+00001a10 50 08 00 00 60 08 00 00 70 08 00 00 80 08 00 00 |P...`...p.......|
+00001a20 90 08 00 00 a0 08 00 00 b0 08 00 00 c0 08 00 00 |................|
+00001a30 d0 08 00 00 e0 08 00 00 f0 08 00 00 00 09 00 00 |................|
+00001a40 10 09 00 00 20 09 00 00 30 09 00 00 40 09 00 00 |.... ...0...@...|
+00001a50 50 09 00 00 60 09 00 00 70 09 00 00 80 09 00 00 |P...`...p.......|
+00001a60 90 09 00 00 a0 09 00 00 b0 09 00 00 c0 09 00 00 |................|
+00001a70 d0 09 00 00 e0 09 00 00 f0 09 00 00 00 0a 00 00 |................|
+00001a80 10 0a 00 00 20 0a 00 00 30 0a 00 00 40 0a 00 00 |.... ...0...@...|
+00001a90 50 0a 00 00 60 0a 00 00 70 0a 00 00 80 0a 00 00 |P...`...p.......|
+00001aa0 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 c0 0a 00 00 |................|
+00001ab0 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 00 0b 00 00 |................|
+00001ac0 10 0b 00 00 20 0b 00 00 30 0b 00 00 40 0b 00 00 |.... ...0...@...|
+00001ad0 50 0b 00 00 60 0b 00 00 70 0b 00 00 80 0b 00 00 |P...`...p.......|
+00001ae0 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 c0 0b 00 00 |................|
+00001af0 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 00 0c 00 00 |................|
+00001b00 10 0c 00 00 20 0c 00 00 30 0c 00 00 40 0c 00 00 |.... ...0...@...|
+00001b10 50 0c 00 00 60 0c 00 00 70 0c 00 00 80 0c 00 00 |P...`...p.......|
+00001b20 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 c0 0c 00 00 |................|
+00001b30 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 00 0d 00 00 |................|
+00001b40 10 0d 00 00 20 0d 00 00 30 0d 00 00 40 0d 00 00 |.... ...0...@...|
+00001b50 50 0d 00 00 60 0d 00 00 70 0d 00 00 80 0d 00 00 |P...`...p.......|
+00001b60 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 c0 0d 00 00 |................|
+00001b70 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 00 0e 00 00 |................|
+00001b80 10 0e 00 00 20 0e 00 00 30 0e 00 00 40 0e 00 00 |.... ...0...@...|
+00001b90 50 0e 00 00 60 0e 00 00 70 0e 00 00 80 0e 00 00 |P...`...p.......|
+00001ba0 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 c0 0e 00 00 |................|
+00001bb0 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 00 0f 00 00 |................|
+00001bc0 10 0f 00 00 20 0f 00 00 30 0f 00 00 40 0f 00 00 |.... ...0...@...|
+00001bd0 50 0f 00 00 60 0f 00 00 70 0f 00 00 80 0f 00 00 |P...`...p.......|
+00001be0 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 c0 0f 00 00 |................|
+00001bf0 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 00 10 00 00 |................|
+00001c00 10 10 00 00 20 10 00 00 30 10 00 00 40 10 00 00 |.... ...0...@...|
+00001c10 50 10 00 00 60 10 00 00 70 10 00 00 80 10 00 00 |P...`...p.......|
+00001c20 90 10 00 00 a0 10 00 00 b0 10 00 00 c0 10 00 00 |................|
+00001c30 d0 10 00 00 e0 10 00 00 f0 10 00 00 00 11 00 00 |................|
+00001c40 10 11 00 00 20 11 00 00 30 11 00 00 40 11 00 00 |.... ...0...@...|
+00001c50 50 11 00 00 60 11 00 00 70 11 00 00 80 11 00 00 |P...`...p.......|
+00001c60 90 11 00 00 a0 11 00 00 b0 11 00 00 c0 11 00 00 |................|
+00001c70 d0 11 00 00 e0 11 00 00 f0 11 00 00 00 12 00 00 |................|
+00001c80 10 12 00 00 20 12 00 00 30 12 00 00 40 12 00 00 |.... ...0...@...|
+00001c90 50 12 00 00 60 12 00 00 70 12 00 00 80 12 00 00 |P...`...p.......|
+00001ca0 90 12 00 00 a0 12 00 00 b0 12 00 00 c0 12 00 00 |................|
+00001cb0 d0 12 00 00 e0 12 00 00 f0 12 00 00 00 13 00 00 |................|
+00001cc0 10 13 00 00 20 13 00 00 30 13 00 00 40 13 00 00 |.... ...0...@...|
+00001cd0 50 13 00 00 60 13 00 00 70 13 00 00 80 13 00 00 |P...`...p.......|
+00001ce0 90 13 00 00 a0 13 00 00 b0 13 00 00 c0 13 00 00 |................|
+00001cf0 d0 13 00 00 e0 13 00 00 f0 13 00 00 00 14 00 00 |................|
+00001d00 10 14 00 00 20 14 00 00 30 14 00 00 40 14 00 00 |.... ...0...@...|
+00001d10 50 14 00 00 60 14 00 00 70 14 00 00 80 14 00 00 |P...`...p.......|
+00001d20 90 14 00 00 a0 14 00 00 b0 14 00 00 c0 14 00 00 |................|
+00001d30 d0 14 00 00 e0 14 00 00 f0 14 00 00 00 15 00 00 |................|
+00001d40 10 15 00 00 20 15 00 00 30 15 00 00 40 15 00 00 |.... ...0...@...|
+00001d50 50 15 00 00 60 15 00 00 70 15 00 00 80 15 00 00 |P...`...p.......|
+00001d60 90 15 00 00 a0 15 00 00 b0 15 00 00 c0 15 00 00 |................|
+00001d70 d0 15 00 00 e0 15 00 00 f0 15 00 00 00 16 00 00 |................|
+00001d80 10 16 00 00 20 16 00 00 30 16 00 00 40 16 00 00 |.... ...0...@...|
+00001d90 50 16 00 00 60 16 00 00 70 16 00 00 80 16 00 00 |P...`...p.......|
+00001da0 90 16 00 00 a0 16 00 00 b0 16 00 00 c0 16 00 00 |................|
+00001db0 d0 16 00 00 e0 16 00 00 f0 16 00 00 00 17 00 00 |................|
+00001dc0 10 17 00 00 20 17 00 00 30 17 00 00 40 17 00 00 |.... ...0...@...|
+00001dd0 50 17 00 00 60 17 00 00 70 17 00 00 80 17 00 00 |P...`...p.......|
+00001de0 90 17 00 00 a0 17 00 00 b0 17 00 00 c0 17 00 00 |................|
+00001df0 d0 17 00 00 e0 17 00 00 f0 17 00 00 00 18 00 00 |................|
+00001e00 10 18 00 00 20 18 00 00 30 18 00 00 40 18 00 00 |.... ...0...@...|
+00001e10 50 18 00 00 60 18 00 00 70 18 00 00 80 18 00 00 |P...`...p.......|
+00001e20 90 18 00 00 a0 18 00 00 b0 18 00 00 c0 18 00 00 |................|
+00001e30 d0 18 00 00 e0 18 00 00 f0 18 00 00 00 19 00 00 |................|
+00001e40 10 19 00 00 20 19 00 00 30 19 00 00 40 19 00 00 |.... ...0...@...|
+00001e50 50 19 00 00 60 19 00 00 70 19 00 00 80 19 00 00 |P...`...p.......|
+00001e60 90 19 00 00 a0 19 00 00 b0 19 00 00 c0 19 00 00 |................|
+00001e70 d0 19 00 00 e0 19 00 00 f0 19 00 00 00 1a 00 00 |................|
+00001e80 10 1a 00 00 20 1a 00 00 30 1a 00 00 40 1a 00 00 |.... ...0...@...|
+00001e90 50 1a 00 00 60 1a 00 00 70 1a 00 00 80 1a 00 00 |P...`...p.......|
+00001ea0 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 c0 1a 00 00 |................|
+00001eb0 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 00 1b 00 00 |................|
+00001ec0 10 1b 00 00 20 1b 00 00 30 1b 00 00 40 1b 00 00 |.... ...0...@...|
+00001ed0 50 1b 00 00 60 1b 00 00 70 1b 00 00 80 1b 00 00 |P...`...p.......|
+00001ee0 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 c0 1b 00 00 |................|
+00001ef0 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 00 1c 00 00 |................|
+00001f00 10 1c 00 00 20 1c 00 00 30 1c 00 00 40 1c 00 00 |.... ...0...@...|
+00001f10 50 1c 00 00 60 1c 00 00 70 1c 00 00 80 1c 00 00 |P...`...p.......|
+00001f20 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 c0 1c 00 00 |................|
+00001f30 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 00 1d 00 00 |................|
+00001f40 10 1d 00 00 20 1d 00 00 30 1d 00 00 40 1d 00 00 |.... ...0...@...|
+00001f50 50 1d 00 00 60 1d 00 00 70 1d 00 00 80 1d 00 00 |P...`...p.......|
+00001f60 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 c0 1d 00 00 |................|
+00001f70 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 00 1e 00 00 |................|
+00001f80 10 1e 00 00 20 1e 00 00 30 1e 00 00 40 1e 00 00 |.... ...0...@...|
+00001f90 50 1e 00 00 60 1e 00 00 70 1e 00 00 80 1e 00 00 |P...`...p.......|
+00001fa0 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 c0 1e 00 00 |................|
+00001fb0 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 00 1f 00 00 |................|
+00001fc0 10 1f 00 00 20 1f 00 00 30 1f 00 00 40 1f 00 00 |.... ...0...@...|
+00001fd0 50 1f 00 00 60 1f 00 00 70 1f 00 00 80 1f 00 00 |P...`...p.......|
+00001fe0 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 c0 1f 00 00 |................|
+00001ff0 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 00 20 00 00 |............. ..|
+00002000 10 20 00 00 20 20 00 00 30 20 00 00 00 00 00 00 |. .. ..0 ......|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000021f0 00 00 00 00 40 20 00 00 00 00 00 00 50 20 00 00 |....@ ......P ..|
+00002200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 00 00 |B.B.B.B.B.B.B...|
+000041c0 02 00 ee ff ff ff 01 00 00 00 ff 27 00 00 00 00 |...........'....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+00004210 4b c0 ef 60 00 00 00 00 01 00 00 00 00 00 00 00 |K..`............|
+00004220 ff 27 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |.'......".......|
+00004230 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+00004240 03 03 03 03 03 03 03 03 02 00 00 00 00 00 00 00 |................|
+00004250 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+00004260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004400 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004410 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00004420 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00004430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004480 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00004490 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+000044a0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+000044b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006400 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00406400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e00 b6 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e10 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00409e20 22 00 00 00 00 00 00 00 21 20 00 00 00 00 00 00 |".......! ......|
+00409e30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409e80 b5 7c 6e 51 cf 6e d6 11 8f f8 00 02 2d 09 71 2b |.|nQ.n......-.q+|
+00409e90 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 |................|
+00409ea0 22 20 00 00 00 00 00 00 21 21 00 00 00 00 00 00 |" ......!!......|
+00409eb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040be00 45 46 49 20 50 41 52 54 00 00 01 00 5c 00 00 00 |EFI PART....\...|
+0040be10 25 cf c4 18 00 00 00 00 ff 27 00 00 00 00 00 00 |%........'......|
+0040be20 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 |........".......|
+0040be30 de 27 00 00 00 00 00 00 03 03 03 03 03 03 03 03 |.'..............|
+0040be40 03 03 03 03 03 03 03 03 df 27 00 00 00 00 00 00 |.........'......|
+0040be50 80 00 00 00 80 00 00 00 07 2b eb 65 00 00 00 00 |.........+.e....|
+0040be60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040c000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.hex
new file mode 100644
index 000000000000..3e1cdcabe2ff
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.hex
@@ -0,0 +1,560 @@
+00000000 51 46 49 fb 00 00 00 01 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 0c 09 00 00 00 00 00 00 00 00 00 00 00 00 10 00 |................|
+00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001000 00 00 00 00 00 00 20 00 00 00 00 00 00 00 30 00 |...... .......0.|
+00001010 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+00001020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002000 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 |......P.........|
+00002010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00002030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 |..............`.|
+00002040 00 00 00 00 00 00 70 00 00 00 00 00 00 00 80 00 |......p.........|
+00002050 00 00 00 00 00 00 90 00 00 00 00 00 00 00 a0 00 |................|
+00002060 00 00 00 00 00 00 b0 00 00 00 00 00 00 00 c0 00 |................|
+00002070 00 00 00 00 00 00 d0 00 00 00 00 00 00 00 e0 00 |................|
+00002080 00 00 00 00 00 00 f0 00 00 00 00 00 00 01 00 00 |................|
+00002090 00 00 00 00 00 01 10 00 00 00 00 00 00 01 20 00 |.............. .|
+000020a0 00 00 00 00 00 01 30 00 00 00 00 00 00 01 40 00 |......0.......@.|
+000020b0 00 00 00 00 00 01 50 00 00 00 00 00 00 01 60 00 |......P.......`.|
+000020c0 00 00 00 00 00 01 70 00 00 00 00 00 00 01 80 00 |......p.........|
+000020d0 00 00 00 00 00 01 90 00 00 00 00 00 00 01 a0 00 |................|
+000020e0 00 00 00 00 00 01 b0 00 00 00 00 00 00 01 c0 00 |................|
+000020f0 00 00 00 00 00 01 d0 00 00 00 00 00 00 01 e0 00 |................|
+00002100 00 00 00 00 00 01 f0 00 00 00 00 00 00 02 00 00 |................|
+00002110 00 00 00 00 00 02 10 00 00 00 00 00 00 02 20 00 |.............. .|
+00002120 00 00 00 00 00 02 30 00 00 00 00 00 00 02 40 00 |......0.......@.|
+00002130 00 00 00 00 00 02 50 00 00 00 00 00 00 02 60 00 |......P.......`.|
+00002140 00 00 00 00 00 02 70 00 00 00 00 00 00 02 80 00 |......p.........|
+00002150 00 00 00 00 00 02 90 00 00 00 00 00 00 02 a0 00 |................|
+00002160 00 00 00 00 00 02 b0 00 00 00 00 00 00 02 c0 00 |................|
+00002170 00 00 00 00 00 02 d0 00 00 00 00 00 00 02 e0 00 |................|
+00002180 00 00 00 00 00 02 f0 00 00 00 00 00 00 03 00 00 |................|
+00002190 00 00 00 00 00 03 10 00 00 00 00 00 00 03 20 00 |.............. .|
+000021a0 00 00 00 00 00 03 30 00 00 00 00 00 00 03 40 00 |......0.......@.|
+000021b0 00 00 00 00 00 03 50 00 00 00 00 00 00 03 60 00 |......P.......`.|
+000021c0 00 00 00 00 00 03 70 00 00 00 00 00 00 03 80 00 |......p.........|
+000021d0 00 00 00 00 00 03 90 00 00 00 00 00 00 03 a0 00 |................|
+000021e0 00 00 00 00 00 03 b0 00 00 00 00 00 00 03 c0 00 |................|
+000021f0 00 00 00 00 00 03 d0 00 00 00 00 00 00 03 e0 00 |................|
+00002200 00 00 00 00 00 03 f0 00 00 00 00 00 00 04 00 00 |................|
+00002210 00 00 00 00 00 04 10 00 00 00 00 00 00 04 20 00 |.............. .|
+00002220 00 00 00 00 00 04 30 00 00 00 00 00 00 04 40 00 |......0.......@.|
+00002230 00 00 00 00 00 04 50 00 00 00 00 00 00 04 60 00 |......P.......`.|
+00002240 00 00 00 00 00 04 70 00 00 00 00 00 00 04 80 00 |......p.........|
+00002250 00 00 00 00 00 04 90 00 00 00 00 00 00 04 a0 00 |................|
+00002260 00 00 00 00 00 04 b0 00 00 00 00 00 00 04 c0 00 |................|
+00002270 00 00 00 00 00 04 d0 00 00 00 00 00 00 04 e0 00 |................|
+00002280 00 00 00 00 00 04 f0 00 00 00 00 00 00 05 00 00 |................|
+00002290 00 00 00 00 00 05 10 00 00 00 00 00 00 05 20 00 |.............. .|
+000022a0 00 00 00 00 00 05 30 00 00 00 00 00 00 05 40 00 |......0.......@.|
+000022b0 00 00 00 00 00 05 50 00 00 00 00 00 00 05 60 00 |......P.......`.|
+000022c0 00 00 00 00 00 05 70 00 00 00 00 00 00 05 80 00 |......p.........|
+000022d0 00 00 00 00 00 05 90 00 00 00 00 00 00 05 a0 00 |................|
+000022e0 00 00 00 00 00 05 b0 00 00 00 00 00 00 05 c0 00 |................|
+000022f0 00 00 00 00 00 05 d0 00 00 00 00 00 00 05 e0 00 |................|
+00002300 00 00 00 00 00 05 f0 00 00 00 00 00 00 06 00 00 |................|
+00002310 00 00 00 00 00 06 10 00 00 00 00 00 00 06 20 00 |.............. .|
+00002320 00 00 00 00 00 06 30 00 00 00 00 00 00 06 40 00 |......0.......@.|
+00002330 00 00 00 00 00 06 50 00 00 00 00 00 00 06 60 00 |......P.......`.|
+00002340 00 00 00 00 00 06 70 00 00 00 00 00 00 06 80 00 |......p.........|
+00002350 00 00 00 00 00 06 90 00 00 00 00 00 00 06 a0 00 |................|
+00002360 00 00 00 00 00 06 b0 00 00 00 00 00 00 06 c0 00 |................|
+00002370 00 00 00 00 00 06 d0 00 00 00 00 00 00 06 e0 00 |................|
+00002380 00 00 00 00 00 06 f0 00 00 00 00 00 00 07 00 00 |................|
+00002390 00 00 00 00 00 07 10 00 00 00 00 00 00 07 20 00 |.............. .|
+000023a0 00 00 00 00 00 07 30 00 00 00 00 00 00 07 40 00 |......0.......@.|
+000023b0 00 00 00 00 00 07 50 00 00 00 00 00 00 07 60 00 |......P.......`.|
+000023c0 00 00 00 00 00 07 70 00 00 00 00 00 00 07 80 00 |......p.........|
+000023d0 00 00 00 00 00 07 90 00 00 00 00 00 00 07 a0 00 |................|
+000023e0 00 00 00 00 00 07 b0 00 00 00 00 00 00 07 c0 00 |................|
+000023f0 00 00 00 00 00 07 d0 00 00 00 00 00 00 07 e0 00 |................|
+00002400 00 00 00 00 00 07 f0 00 00 00 00 00 00 08 00 00 |................|
+00002410 00 00 00 00 00 08 10 00 00 00 00 00 00 08 20 00 |.............. .|
+00002420 00 00 00 00 00 08 30 00 00 00 00 00 00 08 40 00 |......0.......@.|
+00002430 00 00 00 00 00 08 50 00 00 00 00 00 00 08 60 00 |......P.......`.|
+00002440 00 00 00 00 00 08 70 00 00 00 00 00 00 08 80 00 |......p.........|
+00002450 00 00 00 00 00 08 90 00 00 00 00 00 00 08 a0 00 |................|
+00002460 00 00 00 00 00 08 b0 00 00 00 00 00 00 08 c0 00 |................|
+00002470 00 00 00 00 00 08 d0 00 00 00 00 00 00 08 e0 00 |................|
+00002480 00 00 00 00 00 08 f0 00 00 00 00 00 00 09 00 00 |................|
+00002490 00 00 00 00 00 09 10 00 00 00 00 00 00 09 20 00 |.............. .|
+000024a0 00 00 00 00 00 09 30 00 00 00 00 00 00 09 40 00 |......0.......@.|
+000024b0 00 00 00 00 00 09 50 00 00 00 00 00 00 09 60 00 |......P.......`.|
+000024c0 00 00 00 00 00 09 70 00 00 00 00 00 00 09 80 00 |......p.........|
+000024d0 00 00 00 00 00 09 90 00 00 00 00 00 00 09 a0 00 |................|
+000024e0 00 00 00 00 00 09 b0 00 00 00 00 00 00 09 c0 00 |................|
+000024f0 00 00 00 00 00 09 d0 00 00 00 00 00 00 09 e0 00 |................|
+00002500 00 00 00 00 00 09 f0 00 00 00 00 00 00 0a 00 00 |................|
+00002510 00 00 00 00 00 0a 10 00 00 00 00 00 00 0a 20 00 |.............. .|
+00002520 00 00 00 00 00 0a 30 00 00 00 00 00 00 0a 40 00 |......0.......@.|
+00002530 00 00 00 00 00 0a 50 00 00 00 00 00 00 0a 60 00 |......P.......`.|
+00002540 00 00 00 00 00 0a 70 00 00 00 00 00 00 0a 80 00 |......p.........|
+00002550 00 00 00 00 00 0a 90 00 00 00 00 00 00 0a a0 00 |................|
+00002560 00 00 00 00 00 0a b0 00 00 00 00 00 00 0a c0 00 |................|
+00002570 00 00 00 00 00 0a d0 00 00 00 00 00 00 0a e0 00 |................|
+00002580 00 00 00 00 00 0a f0 00 00 00 00 00 00 0b 00 00 |................|
+00002590 00 00 00 00 00 0b 10 00 00 00 00 00 00 0b 20 00 |.............. .|
+000025a0 00 00 00 00 00 0b 30 00 00 00 00 00 00 0b 40 00 |......0.......@.|
+000025b0 00 00 00 00 00 0b 50 00 00 00 00 00 00 0b 60 00 |......P.......`.|
+000025c0 00 00 00 00 00 0b 70 00 00 00 00 00 00 0b 80 00 |......p.........|
+000025d0 00 00 00 00 00 0b 90 00 00 00 00 00 00 0b a0 00 |................|
+000025e0 00 00 00 00 00 0b b0 00 00 00 00 00 00 0b c0 00 |................|
+000025f0 00 00 00 00 00 0b d0 00 00 00 00 00 00 0b e0 00 |................|
+00002600 00 00 00 00 00 0b f0 00 00 00 00 00 00 0c 00 00 |................|
+00002610 00 00 00 00 00 0c 10 00 00 00 00 00 00 0c 20 00 |.............. .|
+00002620 00 00 00 00 00 0c 30 00 00 00 00 00 00 0c 40 00 |......0.......@.|
+00002630 00 00 00 00 00 0c 50 00 00 00 00 00 00 0c 60 00 |......P.......`.|
+00002640 00 00 00 00 00 0c 70 00 00 00 00 00 00 0c 80 00 |......p.........|
+00002650 00 00 00 00 00 0c 90 00 00 00 00 00 00 0c a0 00 |................|
+00002660 00 00 00 00 00 0c b0 00 00 00 00 00 00 0c c0 00 |................|
+00002670 00 00 00 00 00 0c d0 00 00 00 00 00 00 0c e0 00 |................|
+00002680 00 00 00 00 00 0c f0 00 00 00 00 00 00 0d 00 00 |................|
+00002690 00 00 00 00 00 0d 10 00 00 00 00 00 00 0d 20 00 |.............. .|
+000026a0 00 00 00 00 00 0d 30 00 00 00 00 00 00 0d 40 00 |......0.......@.|
+000026b0 00 00 00 00 00 0d 50 00 00 00 00 00 00 0d 60 00 |......P.......`.|
+000026c0 00 00 00 00 00 0d 70 00 00 00 00 00 00 0d 80 00 |......p.........|
+000026d0 00 00 00 00 00 0d 90 00 00 00 00 00 00 0d a0 00 |................|
+000026e0 00 00 00 00 00 0d b0 00 00 00 00 00 00 0d c0 00 |................|
+000026f0 00 00 00 00 00 0d d0 00 00 00 00 00 00 0d e0 00 |................|
+00002700 00 00 00 00 00 0d f0 00 00 00 00 00 00 0e 00 00 |................|
+00002710 00 00 00 00 00 0e 10 00 00 00 00 00 00 0e 20 00 |.............. .|
+00002720 00 00 00 00 00 0e 30 00 00 00 00 00 00 0e 40 00 |......0.......@.|
+00002730 00 00 00 00 00 0e 50 00 00 00 00 00 00 0e 60 00 |......P.......`.|
+00002740 00 00 00 00 00 0e 70 00 00 00 00 00 00 0e 80 00 |......p.........|
+00002750 00 00 00 00 00 0e 90 00 00 00 00 00 00 0e a0 00 |................|
+00002760 00 00 00 00 00 0e b0 00 00 00 00 00 00 0e c0 00 |................|
+00002770 00 00 00 00 00 0e d0 00 00 00 00 00 00 0e e0 00 |................|
+00002780 00 00 00 00 00 0e f0 00 00 00 00 00 00 0f 00 00 |................|
+00002790 00 00 00 00 00 0f 10 00 00 00 00 00 00 0f 20 00 |.............. .|
+000027a0 00 00 00 00 00 0f 30 00 00 00 00 00 00 0f 40 00 |......0.......@.|
+000027b0 00 00 00 00 00 0f 50 00 00 00 00 00 00 0f 60 00 |......P.......`.|
+000027c0 00 00 00 00 00 0f 70 00 00 00 00 00 00 0f 80 00 |......p.........|
+000027d0 00 00 00 00 00 0f 90 00 00 00 00 00 00 0f a0 00 |................|
+000027e0 00 00 00 00 00 0f b0 00 00 00 00 00 00 0f c0 00 |................|
+000027f0 00 00 00 00 00 0f d0 00 00 00 00 00 00 0f e0 00 |................|
+00002800 00 00 00 00 00 0f f0 00 00 00 00 00 00 10 00 00 |................|
+00002810 00 00 00 00 00 10 10 00 00 00 00 00 00 10 20 00 |.............. .|
+00002820 00 00 00 00 00 10 30 00 00 00 00 00 00 10 40 00 |......0.......@.|
+00002830 00 00 00 00 00 10 50 00 00 00 00 00 00 10 60 00 |......P.......`.|
+00002840 00 00 00 00 00 10 70 00 00 00 00 00 00 10 80 00 |......p.........|
+00002850 00 00 00 00 00 10 90 00 00 00 00 00 00 10 a0 00 |................|
+00002860 00 00 00 00 00 10 b0 00 00 00 00 00 00 10 c0 00 |................|
+00002870 00 00 00 00 00 10 d0 00 00 00 00 00 00 10 e0 00 |................|
+00002880 00 00 00 00 00 10 f0 00 00 00 00 00 00 11 00 00 |................|
+00002890 00 00 00 00 00 11 10 00 00 00 00 00 00 11 20 00 |.............. .|
+000028a0 00 00 00 00 00 11 30 00 00 00 00 00 00 11 40 00 |......0.......@.|
+000028b0 00 00 00 00 00 11 50 00 00 00 00 00 00 11 60 00 |......P.......`.|
+000028c0 00 00 00 00 00 11 70 00 00 00 00 00 00 11 80 00 |......p.........|
+000028d0 00 00 00 00 00 11 90 00 00 00 00 00 00 11 a0 00 |................|
+000028e0 00 00 00 00 00 11 b0 00 00 00 00 00 00 11 c0 00 |................|
+000028f0 00 00 00 00 00 11 d0 00 00 00 00 00 00 11 e0 00 |................|
+00002900 00 00 00 00 00 11 f0 00 00 00 00 00 00 12 00 00 |................|
+00002910 00 00 00 00 00 12 10 00 00 00 00 00 00 12 20 00 |.............. .|
+00002920 00 00 00 00 00 12 30 00 00 00 00 00 00 12 40 00 |......0.......@.|
+00002930 00 00 00 00 00 12 50 00 00 00 00 00 00 12 60 00 |......P.......`.|
+00002940 00 00 00 00 00 12 70 00 00 00 00 00 00 12 80 00 |......p.........|
+00002950 00 00 00 00 00 12 90 00 00 00 00 00 00 12 a0 00 |................|
+00002960 00 00 00 00 00 12 b0 00 00 00 00 00 00 12 c0 00 |................|
+00002970 00 00 00 00 00 12 d0 00 00 00 00 00 00 12 e0 00 |................|
+00002980 00 00 00 00 00 12 f0 00 00 00 00 00 00 13 00 00 |................|
+00002990 00 00 00 00 00 13 10 00 00 00 00 00 00 13 20 00 |.............. .|
+000029a0 00 00 00 00 00 13 30 00 00 00 00 00 00 13 40 00 |......0.......@.|
+000029b0 00 00 00 00 00 13 50 00 00 00 00 00 00 13 60 00 |......P.......`.|
+000029c0 00 00 00 00 00 13 70 00 00 00 00 00 00 13 80 00 |......p.........|
+000029d0 00 00 00 00 00 13 90 00 00 00 00 00 00 13 a0 00 |................|
+000029e0 00 00 00 00 00 13 b0 00 00 00 00 00 00 13 c0 00 |................|
+000029f0 00 00 00 00 00 13 d0 00 00 00 00 00 00 13 e0 00 |................|
+00002a00 00 00 00 00 00 13 f0 00 00 00 00 00 00 14 00 00 |................|
+00002a10 00 00 00 00 00 14 10 00 00 00 00 00 00 14 20 00 |.............. .|
+00002a20 00 00 00 00 00 14 30 00 00 00 00 00 00 14 40 00 |......0.......@.|
+00002a30 00 00 00 00 00 14 50 00 00 00 00 00 00 14 60 00 |......P.......`.|
+00002a40 00 00 00 00 00 14 70 00 00 00 00 00 00 14 80 00 |......p.........|
+00002a50 00 00 00 00 00 14 90 00 00 00 00 00 00 14 a0 00 |................|
+00002a60 00 00 00 00 00 14 b0 00 00 00 00 00 00 14 c0 00 |................|
+00002a70 00 00 00 00 00 14 d0 00 00 00 00 00 00 14 e0 00 |................|
+00002a80 00 00 00 00 00 14 f0 00 00 00 00 00 00 15 00 00 |................|
+00002a90 00 00 00 00 00 15 10 00 00 00 00 00 00 15 20 00 |.............. .|
+00002aa0 00 00 00 00 00 15 30 00 00 00 00 00 00 15 40 00 |......0.......@.|
+00002ab0 00 00 00 00 00 15 50 00 00 00 00 00 00 15 60 00 |......P.......`.|
+00002ac0 00 00 00 00 00 15 70 00 00 00 00 00 00 15 80 00 |......p.........|
+00002ad0 00 00 00 00 00 15 90 00 00 00 00 00 00 15 a0 00 |................|
+00002ae0 00 00 00 00 00 15 b0 00 00 00 00 00 00 15 c0 00 |................|
+00002af0 00 00 00 00 00 15 d0 00 00 00 00 00 00 15 e0 00 |................|
+00002b00 00 00 00 00 00 15 f0 00 00 00 00 00 00 16 00 00 |................|
+00002b10 00 00 00 00 00 16 10 00 00 00 00 00 00 16 20 00 |.............. .|
+00002b20 00 00 00 00 00 16 30 00 00 00 00 00 00 16 40 00 |......0.......@.|
+00002b30 00 00 00 00 00 16 50 00 00 00 00 00 00 16 60 00 |......P.......`.|
+00002b40 00 00 00 00 00 16 70 00 00 00 00 00 00 16 80 00 |......p.........|
+00002b50 00 00 00 00 00 16 90 00 00 00 00 00 00 16 a0 00 |................|
+00002b60 00 00 00 00 00 16 b0 00 00 00 00 00 00 16 c0 00 |................|
+00002b70 00 00 00 00 00 16 d0 00 00 00 00 00 00 16 e0 00 |................|
+00002b80 00 00 00 00 00 16 f0 00 00 00 00 00 00 17 00 00 |................|
+00002b90 00 00 00 00 00 17 10 00 00 00 00 00 00 17 20 00 |.............. .|
+00002ba0 00 00 00 00 00 17 30 00 00 00 00 00 00 17 40 00 |......0.......@.|
+00002bb0 00 00 00 00 00 17 50 00 00 00 00 00 00 17 60 00 |......P.......`.|
+00002bc0 00 00 00 00 00 17 70 00 00 00 00 00 00 17 80 00 |......p.........|
+00002bd0 00 00 00 00 00 17 90 00 00 00 00 00 00 17 a0 00 |................|
+00002be0 00 00 00 00 00 17 b0 00 00 00 00 00 00 17 c0 00 |................|
+00002bf0 00 00 00 00 00 17 d0 00 00 00 00 00 00 17 e0 00 |................|
+00002c00 00 00 00 00 00 17 f0 00 00 00 00 00 00 18 00 00 |................|
+00002c10 00 00 00 00 00 18 10 00 00 00 00 00 00 18 20 00 |.............. .|
+00002c20 00 00 00 00 00 18 30 00 00 00 00 00 00 18 40 00 |......0.......@.|
+00002c30 00 00 00 00 00 18 50 00 00 00 00 00 00 18 60 00 |......P.......`.|
+00002c40 00 00 00 00 00 18 70 00 00 00 00 00 00 18 80 00 |......p.........|
+00002c50 00 00 00 00 00 18 90 00 00 00 00 00 00 18 a0 00 |................|
+00002c60 00 00 00 00 00 18 b0 00 00 00 00 00 00 18 c0 00 |................|
+00002c70 00 00 00 00 00 18 d0 00 00 00 00 00 00 18 e0 00 |................|
+00002c80 00 00 00 00 00 18 f0 00 00 00 00 00 00 19 00 00 |................|
+00002c90 00 00 00 00 00 19 10 00 00 00 00 00 00 19 20 00 |.............. .|
+00002ca0 00 00 00 00 00 19 30 00 00 00 00 00 00 19 40 00 |......0.......@.|
+00002cb0 00 00 00 00 00 19 50 00 00 00 00 00 00 19 60 00 |......P.......`.|
+00002cc0 00 00 00 00 00 19 70 00 00 00 00 00 00 19 80 00 |......p.........|
+00002cd0 00 00 00 00 00 19 90 00 00 00 00 00 00 19 a0 00 |................|
+00002ce0 00 00 00 00 00 19 b0 00 00 00 00 00 00 19 c0 00 |................|
+00002cf0 00 00 00 00 00 19 d0 00 00 00 00 00 00 19 e0 00 |................|
+00002d00 00 00 00 00 00 19 f0 00 00 00 00 00 00 1a 00 00 |................|
+00002d10 00 00 00 00 00 1a 10 00 00 00 00 00 00 1a 20 00 |.............. .|
+00002d20 00 00 00 00 00 1a 30 00 00 00 00 00 00 1a 40 00 |......0.......@.|
+00002d30 00 00 00 00 00 1a 50 00 00 00 00 00 00 1a 60 00 |......P.......`.|
+00002d40 00 00 00 00 00 1a 70 00 00 00 00 00 00 1a 80 00 |......p.........|
+00002d50 00 00 00 00 00 1a 90 00 00 00 00 00 00 1a a0 00 |................|
+00002d60 00 00 00 00 00 1a b0 00 00 00 00 00 00 1a c0 00 |................|
+00002d70 00 00 00 00 00 1a d0 00 00 00 00 00 00 1a e0 00 |................|
+00002d80 00 00 00 00 00 1a f0 00 00 00 00 00 00 1b 00 00 |................|
+00002d90 00 00 00 00 00 1b 10 00 00 00 00 00 00 1b 20 00 |.............. .|
+00002da0 00 00 00 00 00 1b 30 00 00 00 00 00 00 1b 40 00 |......0.......@.|
+00002db0 00 00 00 00 00 1b 50 00 00 00 00 00 00 1b 60 00 |......P.......`.|
+00002dc0 00 00 00 00 00 1b 70 00 00 00 00 00 00 1b 80 00 |......p.........|
+00002dd0 00 00 00 00 00 1b 90 00 00 00 00 00 00 1b a0 00 |................|
+00002de0 00 00 00 00 00 1b b0 00 00 00 00 00 00 1b c0 00 |................|
+00002df0 00 00 00 00 00 1b d0 00 00 00 00 00 00 1b e0 00 |................|
+00002e00 00 00 00 00 00 1b f0 00 00 00 00 00 00 1c 00 00 |................|
+00002e10 00 00 00 00 00 1c 10 00 00 00 00 00 00 1c 20 00 |.............. .|
+00002e20 00 00 00 00 00 1c 30 00 00 00 00 00 00 1c 40 00 |......0.......@.|
+00002e30 00 00 00 00 00 1c 50 00 00 00 00 00 00 1c 60 00 |......P.......`.|
+00002e40 00 00 00 00 00 1c 70 00 00 00 00 00 00 1c 80 00 |......p.........|
+00002e50 00 00 00 00 00 1c 90 00 00 00 00 00 00 1c a0 00 |................|
+00002e60 00 00 00 00 00 1c b0 00 00 00 00 00 00 1c c0 00 |................|
+00002e70 00 00 00 00 00 1c d0 00 00 00 00 00 00 1c e0 00 |................|
+00002e80 00 00 00 00 00 1c f0 00 00 00 00 00 00 1d 00 00 |................|
+00002e90 00 00 00 00 00 1d 10 00 00 00 00 00 00 1d 20 00 |.............. .|
+00002ea0 00 00 00 00 00 1d 30 00 00 00 00 00 00 1d 40 00 |......0.......@.|
+00002eb0 00 00 00 00 00 1d 50 00 00 00 00 00 00 1d 60 00 |......P.......`.|
+00002ec0 00 00 00 00 00 1d 70 00 00 00 00 00 00 1d 80 00 |......p.........|
+00002ed0 00 00 00 00 00 1d 90 00 00 00 00 00 00 1d a0 00 |................|
+00002ee0 00 00 00 00 00 1d b0 00 00 00 00 00 00 1d c0 00 |................|
+00002ef0 00 00 00 00 00 1d d0 00 00 00 00 00 00 1d e0 00 |................|
+00002f00 00 00 00 00 00 1d f0 00 00 00 00 00 00 1e 00 00 |................|
+00002f10 00 00 00 00 00 1e 10 00 00 00 00 00 00 1e 20 00 |.............. .|
+00002f20 00 00 00 00 00 1e 30 00 00 00 00 00 00 1e 40 00 |......0.......@.|
+00002f30 00 00 00 00 00 1e 50 00 00 00 00 00 00 1e 60 00 |......P.......`.|
+00002f40 00 00 00 00 00 1e 70 00 00 00 00 00 00 1e 80 00 |......p.........|
+00002f50 00 00 00 00 00 1e 90 00 00 00 00 00 00 1e a0 00 |................|
+00002f60 00 00 00 00 00 1e b0 00 00 00 00 00 00 1e c0 00 |................|
+00002f70 00 00 00 00 00 1e d0 00 00 00 00 00 00 1e e0 00 |................|
+00002f80 00 00 00 00 00 1e f0 00 00 00 00 00 00 1f 00 00 |................|
+00002f90 00 00 00 00 00 1f 10 00 00 00 00 00 00 1f 20 00 |.............. .|
+00002fa0 00 00 00 00 00 1f 30 00 00 00 00 00 00 1f 40 00 |......0.......@.|
+00002fb0 00 00 00 00 00 1f 50 00 00 00 00 00 00 1f 60 00 |......P.......`.|
+00002fc0 00 00 00 00 00 1f 70 00 00 00 00 00 00 1f 80 00 |......p.........|
+00002fd0 00 00 00 00 00 1f 90 00 00 00 00 00 00 1f a0 00 |................|
+00002fe0 00 00 00 00 00 1f b0 00 00 00 00 00 00 1f c0 00 |................|
+00002ff0 00 00 00 00 00 1f d0 00 00 00 00 00 00 1f e0 00 |................|
+00003000 00 00 00 00 00 1f f0 00 00 00 00 00 00 20 00 00 |............. ..|
+00003010 00 00 00 00 00 20 10 00 00 00 00 00 00 20 20 00 |..... ....... .|
+00003020 00 00 00 00 00 20 30 00 00 00 00 00 00 20 40 00 |..... 0...... @.|
+00003030 00 00 00 00 00 20 50 00 00 00 00 00 00 20 60 00 |..... P...... `.|
+00003040 00 00 00 00 00 20 70 00 00 00 00 00 00 20 80 00 |..... p...... ..|
+00003050 00 00 00 00 00 20 90 00 00 00 00 00 00 20 a0 00 |..... ....... ..|
+00003060 00 00 00 00 00 20 b0 00 00 00 00 00 00 20 c0 00 |..... ....... ..|
+00003070 00 00 00 00 00 20 d0 00 00 00 00 00 00 20 e0 00 |..... ....... ..|
+00003080 00 00 00 00 00 20 f0 00 00 00 00 00 00 21 00 00 |..... .......!..|
+00003090 00 00 00 00 00 21 10 00 00 00 00 00 00 21 20 00 |.....!.......! .|
+000030a0 00 00 00 00 00 21 30 00 00 00 00 00 00 21 40 00 |.....!0......!@.|
+000030b0 00 00 00 00 00 21 50 00 00 00 00 00 00 21 60 00 |.....!P......!`.|
+000030c0 00 00 00 00 00 21 70 00 00 00 00 00 00 21 80 00 |.....!p......!..|
+000030d0 00 00 00 00 00 21 90 00 00 00 00 00 00 21 a0 00 |.....!.......!..|
+000030e0 00 00 00 00 00 21 b0 00 00 00 00 00 00 21 c0 00 |.....!.......!..|
+000030f0 00 00 00 00 00 21 d0 00 00 00 00 00 00 21 e0 00 |.....!.......!..|
+00003100 00 00 00 00 00 21 f0 00 00 00 00 00 00 22 00 00 |.....!......."..|
+00003110 00 00 00 00 00 22 10 00 00 00 00 00 00 22 20 00 |....."......." .|
+00003120 00 00 00 00 00 22 30 00 00 00 00 00 00 22 40 00 |....."0......"@.|
+00003130 00 00 00 00 00 22 50 00 00 00 00 00 00 22 60 00 |....."P......"`.|
+00003140 00 00 00 00 00 22 70 00 00 00 00 00 00 22 80 00 |....."p......"..|
+00003150 00 00 00 00 00 22 90 00 00 00 00 00 00 22 a0 00 |....."......."..|
+00003160 00 00 00 00 00 22 b0 00 00 00 00 00 00 22 c0 00 |....."......."..|
+00003170 00 00 00 00 00 22 d0 00 00 00 00 00 00 22 e0 00 |....."......."..|
+00003180 00 00 00 00 00 22 f0 00 00 00 00 00 00 23 00 00 |.....".......#..|
+00003190 00 00 00 00 00 23 10 00 00 00 00 00 00 23 20 00 |.....#.......# .|
+000031a0 00 00 00 00 00 23 30 00 00 00 00 00 00 23 40 00 |.....#0......#@.|
+000031b0 00 00 00 00 00 23 50 00 00 00 00 00 00 23 60 00 |.....#P......#`.|
+000031c0 00 00 00 00 00 23 70 00 00 00 00 00 00 23 80 00 |.....#p......#..|
+000031d0 00 00 00 00 00 23 90 00 00 00 00 00 00 23 a0 00 |.....#.......#..|
+000031e0 00 00 00 00 00 23 b0 00 00 00 00 00 00 23 c0 00 |.....#.......#..|
+000031f0 00 00 00 00 00 23 d0 00 00 00 00 00 00 23 e0 00 |.....#.......#..|
+00003200 00 00 00 00 00 23 f0 00 00 00 00 00 00 24 00 00 |.....#.......$..|
+00003210 00 00 00 00 00 24 10 00 00 00 00 00 00 24 20 00 |.....$.......$ .|
+00003220 00 00 00 00 00 24 30 00 00 00 00 00 00 24 40 00 |.....$0......$@.|
+00003230 00 00 00 00 00 24 50 00 00 00 00 00 00 24 60 00 |.....$P......$`.|
+00003240 00 00 00 00 00 24 70 00 00 00 00 00 00 24 80 00 |.....$p......$..|
+00003250 00 00 00 00 00 24 90 00 00 00 00 00 00 24 a0 00 |.....$.......$..|
+00003260 00 00 00 00 00 24 b0 00 00 00 00 00 00 24 c0 00 |.....$.......$..|
+00003270 00 00 00 00 00 24 d0 00 00 00 00 00 00 24 e0 00 |.....$.......$..|
+00003280 00 00 00 00 00 24 f0 00 00 00 00 00 00 25 00 00 |.....$.......%..|
+00003290 00 00 00 00 00 25 10 00 00 00 00 00 00 25 20 00 |.....%.......% .|
+000032a0 00 00 00 00 00 25 30 00 00 00 00 00 00 25 40 00 |.....%0......%@.|
+000032b0 00 00 00 00 00 25 50 00 00 00 00 00 00 25 60 00 |.....%P......%`.|
+000032c0 00 00 00 00 00 25 70 00 00 00 00 00 00 25 80 00 |.....%p......%..|
+000032d0 00 00 00 00 00 25 90 00 00 00 00 00 00 25 a0 00 |.....%.......%..|
+000032e0 00 00 00 00 00 25 b0 00 00 00 00 00 00 25 c0 00 |.....%.......%..|
+000032f0 00 00 00 00 00 25 d0 00 00 00 00 00 00 25 e0 00 |.....%.......%..|
+00003300 00 00 00 00 00 25 f0 00 00 00 00 00 00 26 00 00 |.....%.......&..|
+00003310 00 00 00 00 00 26 10 00 00 00 00 00 00 26 20 00 |.....&.......& .|
+00003320 00 00 00 00 00 26 30 00 00 00 00 00 00 26 40 00 |.....&0......&@.|
+00003330 00 00 00 00 00 26 50 00 00 00 00 00 00 26 60 00 |.....&P......&`.|
+00003340 00 00 00 00 00 26 70 00 00 00 00 00 00 26 80 00 |.....&p......&..|
+00003350 00 00 00 00 00 26 90 00 00 00 00 00 00 26 a0 00 |.....&.......&..|
+00003360 00 00 00 00 00 26 b0 00 00 00 00 00 00 26 c0 00 |.....&.......&..|
+00003370 00 00 00 00 00 26 d0 00 00 00 00 00 00 26 e0 00 |.....&.......&..|
+00003380 00 00 00 00 00 26 f0 00 00 00 00 00 00 27 00 00 |.....&.......'..|
+00003390 00 00 00 00 00 27 10 00 00 00 00 00 00 27 20 00 |.....'.......' .|
+000033a0 00 00 00 00 00 27 30 00 00 00 00 00 00 27 40 00 |.....'0......'@.|
+000033b0 00 00 00 00 00 27 50 00 00 00 00 00 00 27 60 00 |.....'P......'`.|
+000033c0 00 00 00 00 00 27 70 00 00 00 00 00 00 27 80 00 |.....'p......'..|
+000033d0 00 00 00 00 00 27 90 00 00 00 00 00 00 27 a0 00 |.....'.......'..|
+000033e0 00 00 00 00 00 27 b0 00 00 00 00 00 00 27 c0 00 |.....'.......'..|
+000033f0 00 00 00 00 00 27 d0 00 00 00 00 00 00 27 e0 00 |.....'.......'..|
+00003400 00 00 00 00 00 27 f0 00 00 00 00 00 00 28 00 00 |.....'.......(..|
+00003410 00 00 00 00 00 28 10 00 00 00 00 00 00 28 20 00 |.....(.......( .|
+00003420 00 00 00 00 00 28 30 00 00 00 00 00 00 28 40 00 |.....(0......(@.|
+00003430 00 00 00 00 00 28 50 00 00 00 00 00 00 28 60 00 |.....(P......(`.|
+00003440 00 00 00 00 00 28 70 00 00 00 00 00 00 28 80 00 |.....(p......(..|
+00003450 00 00 00 00 00 28 90 00 00 00 00 00 00 28 a0 00 |.....(.......(..|
+00003460 00 00 00 00 00 28 b0 00 00 00 00 00 00 28 c0 00 |.....(.......(..|
+00003470 00 00 00 00 00 28 d0 00 00 00 00 00 00 28 e0 00 |.....(.......(..|
+00003480 00 00 00 00 00 28 f0 00 00 00 00 00 00 29 00 00 |.....(.......)..|
+00003490 00 00 00 00 00 29 10 00 00 00 00 00 00 29 20 00 |.....).......) .|
+000034a0 00 00 00 00 00 29 30 00 00 00 00 00 00 29 40 00 |.....)0......)@.|
+000034b0 00 00 00 00 00 29 50 00 00 00 00 00 00 29 60 00 |.....)P......)`.|
+000034c0 00 00 00 00 00 29 70 00 00 00 00 00 00 29 80 00 |.....)p......)..|
+000034d0 00 00 00 00 00 29 90 00 00 00 00 00 00 29 a0 00 |.....).......)..|
+000034e0 00 00 00 00 00 29 b0 00 00 00 00 00 00 29 c0 00 |.....).......)..|
+000034f0 00 00 00 00 00 29 d0 00 00 00 00 00 00 29 e0 00 |.....).......)..|
+00003500 00 00 00 00 00 29 f0 00 00 00 00 00 00 2a 00 00 |.....).......*..|
+00003510 00 00 00 00 00 2a 10 00 00 00 00 00 00 2a 20 00 |.....*.......* .|
+00003520 00 00 00 00 00 2a 30 00 00 00 00 00 00 2a 40 00 |.....*0......*@.|
+00003530 00 00 00 00 00 2a 50 00 00 00 00 00 00 2a 60 00 |.....*P......*`.|
+00003540 00 00 00 00 00 2a 70 00 00 00 00 00 00 2a 80 00 |.....*p......*..|
+00003550 00 00 00 00 00 2a 90 00 00 00 00 00 00 2a a0 00 |.....*.......*..|
+00003560 00 00 00 00 00 2a b0 00 00 00 00 00 00 2a c0 00 |.....*.......*..|
+00003570 00 00 00 00 00 2a d0 00 00 00 00 00 00 2a e0 00 |.....*.......*..|
+00003580 00 00 00 00 00 2a f0 00 00 00 00 00 00 2b 00 00 |.....*.......+..|
+00003590 00 00 00 00 00 2b 10 00 00 00 00 00 00 2b 20 00 |.....+.......+ .|
+000035a0 00 00 00 00 00 2b 30 00 00 00 00 00 00 2b 40 00 |.....+0......+@.|
+000035b0 00 00 00 00 00 2b 50 00 00 00 00 00 00 2b 60 00 |.....+P......+`.|
+000035c0 00 00 00 00 00 2b 70 00 00 00 00 00 00 2b 80 00 |.....+p......+..|
+000035d0 00 00 00 00 00 2b 90 00 00 00 00 00 00 2b a0 00 |.....+.......+..|
+000035e0 00 00 00 00 00 2b b0 00 00 00 00 00 00 2b c0 00 |.....+.......+..|
+000035f0 00 00 00 00 00 2b d0 00 00 00 00 00 00 2b e0 00 |.....+.......+..|
+00003600 00 00 00 00 00 2b f0 00 00 00 00 00 00 2c 00 00 |.....+.......,..|
+00003610 00 00 00 00 00 2c 10 00 00 00 00 00 00 2c 20 00 |.....,......., .|
+00003620 00 00 00 00 00 2c 30 00 00 00 00 00 00 2c 40 00 |.....,0......,@.|
+00003630 00 00 00 00 00 2c 50 00 00 00 00 00 00 2c 60 00 |.....,P......,`.|
+00003640 00 00 00 00 00 2c 70 00 00 00 00 00 00 2c 80 00 |.....,p......,..|
+00003650 00 00 00 00 00 2c 90 00 00 00 00 00 00 2c a0 00 |.....,.......,..|
+00003660 00 00 00 00 00 2c b0 00 00 00 00 00 00 2c c0 00 |.....,.......,..|
+00003670 00 00 00 00 00 2c d0 00 00 00 00 00 00 2c e0 00 |.....,.......,..|
+00003680 00 00 00 00 00 2c f0 00 00 00 00 00 00 2d 00 00 |.....,.......-..|
+00003690 00 00 00 00 00 2d 10 00 00 00 00 00 00 2d 20 00 |.....-.......- .|
+000036a0 00 00 00 00 00 2d 30 00 00 00 00 00 00 2d 40 00 |.....-0......-@.|
+000036b0 00 00 00 00 00 2d 50 00 00 00 00 00 00 2d 60 00 |.....-P......-`.|
+000036c0 00 00 00 00 00 2d 70 00 00 00 00 00 00 2d 80 00 |.....-p......-..|
+000036d0 00 00 00 00 00 2d 90 00 00 00 00 00 00 2d a0 00 |.....-.......-..|
+000036e0 00 00 00 00 00 2d b0 00 00 00 00 00 00 2d c0 00 |.....-.......-..|
+000036f0 00 00 00 00 00 2d d0 00 00 00 00 00 00 2d e0 00 |.....-.......-..|
+00003700 00 00 00 00 00 2d f0 00 00 00 00 00 00 2e 00 00 |.....-..........|
+00003710 00 00 00 00 00 2e 10 00 00 00 00 00 00 2e 20 00 |.............. .|
+00003720 00 00 00 00 00 2e 30 00 00 00 00 00 00 2e 40 00 |......0.......@.|
+00003730 00 00 00 00 00 2e 50 00 00 00 00 00 00 2e 60 00 |......P.......`.|
+00003740 00 00 00 00 00 2e 70 00 00 00 00 00 00 2e 80 00 |......p.........|
+00003750 00 00 00 00 00 2e 90 00 00 00 00 00 00 2e a0 00 |................|
+00003760 00 00 00 00 00 2e b0 00 00 00 00 00 00 2e c0 00 |................|
+00003770 00 00 00 00 00 2e d0 00 00 00 00 00 00 2e e0 00 |................|
+00003780 00 00 00 00 00 2e f0 00 00 00 00 00 00 2f 00 00 |............./..|
+00003790 00 00 00 00 00 2f 10 00 00 00 00 00 00 2f 20 00 |...../......./ .|
+000037a0 00 00 00 00 00 2f 30 00 00 00 00 00 00 2f 40 00 |...../0....../@.|
+000037b0 00 00 00 00 00 2f 50 00 00 00 00 00 00 2f 60 00 |...../P....../`.|
+000037c0 00 00 00 00 00 2f 70 00 00 00 00 00 00 2f 80 00 |...../p....../..|
+000037d0 00 00 00 00 00 2f 90 00 00 00 00 00 00 2f a0 00 |...../......./..|
+000037e0 00 00 00 00 00 2f b0 00 00 00 00 00 00 2f c0 00 |...../......./..|
+000037f0 00 00 00 00 00 2f d0 00 00 00 00 00 00 2f e0 00 |...../......./..|
+00003800 00 00 00 00 00 2f f0 00 00 00 00 00 00 30 00 00 |...../.......0..|
+00003810 00 00 00 00 00 30 10 00 00 00 00 00 00 30 20 00 |.....0.......0 .|
+00003820 00 00 00 00 00 30 30 00 00 00 00 00 00 30 40 00 |.....00......0@.|
+00003830 00 00 00 00 00 30 50 00 00 00 00 00 00 30 60 00 |.....0P......0`.|
+00003840 00 00 00 00 00 30 70 00 00 00 00 00 00 30 80 00 |.....0p......0..|
+00003850 00 00 00 00 00 30 90 00 00 00 00 00 00 30 a0 00 |.....0.......0..|
+00003860 00 00 00 00 00 30 b0 00 00 00 00 00 00 30 c0 00 |.....0.......0..|
+00003870 00 00 00 00 00 30 d0 00 00 00 00 00 00 30 e0 00 |.....0.......0..|
+00003880 00 00 00 00 00 30 f0 00 00 00 00 00 00 31 00 00 |.....0.......1..|
+00003890 00 00 00 00 00 31 10 00 00 00 00 00 00 31 20 00 |.....1.......1 .|
+000038a0 00 00 00 00 00 31 30 00 00 00 00 00 00 31 40 00 |.....10......1@.|
+000038b0 00 00 00 00 00 31 50 00 00 00 00 00 00 31 60 00 |.....1P......1`.|
+000038c0 00 00 00 00 00 31 70 00 00 00 00 00 00 31 80 00 |.....1p......1..|
+000038d0 00 00 00 00 00 31 90 00 00 00 00 00 00 31 a0 00 |.....1.......1..|
+000038e0 00 00 00 00 00 31 b0 00 00 00 00 00 00 31 c0 00 |.....1.......1..|
+000038f0 00 00 00 00 00 31 d0 00 00 00 00 00 00 31 e0 00 |.....1.......1..|
+00003900 00 00 00 00 00 31 f0 00 00 00 00 00 00 32 00 00 |.....1.......2..|
+00003910 00 00 00 00 00 32 10 00 00 00 00 00 00 32 20 00 |.....2.......2 .|
+00003920 00 00 00 00 00 32 30 00 00 00 00 00 00 32 40 00 |.....20......2@.|
+00003930 00 00 00 00 00 32 50 00 00 00 00 00 00 32 60 00 |.....2P......2`.|
+00003940 00 00 00 00 00 32 70 00 00 00 00 00 00 32 80 00 |.....2p......2..|
+00003950 00 00 00 00 00 32 90 00 00 00 00 00 00 32 a0 00 |.....2.......2..|
+00003960 00 00 00 00 00 32 b0 00 00 00 00 00 00 32 c0 00 |.....2.......2..|
+00003970 00 00 00 00 00 32 d0 00 00 00 00 00 00 32 e0 00 |.....2.......2..|
+00003980 00 00 00 00 00 32 f0 00 00 00 00 00 00 33 00 00 |.....2.......3..|
+00003990 00 00 00 00 00 33 10 00 00 00 00 00 00 33 20 00 |.....3.......3 .|
+000039a0 00 00 00 00 00 33 30 00 00 00 00 00 00 33 40 00 |.....30......3@.|
+000039b0 00 00 00 00 00 33 50 00 00 00 00 00 00 33 60 00 |.....3P......3`.|
+000039c0 00 00 00 00 00 33 70 00 00 00 00 00 00 33 80 00 |.....3p......3..|
+000039d0 00 00 00 00 00 33 90 00 00 00 00 00 00 33 a0 00 |.....3.......3..|
+000039e0 00 00 00 00 00 33 b0 00 00 00 00 00 00 33 c0 00 |.....3.......3..|
+000039f0 00 00 00 00 00 33 d0 00 00 00 00 00 00 33 e0 00 |.....3.......3..|
+00003a00 00 00 00 00 00 33 f0 00 00 00 00 00 00 34 00 00 |.....3.......4..|
+00003a10 00 00 00 00 00 34 10 00 00 00 00 00 00 34 20 00 |.....4.......4 .|
+00003a20 00 00 00 00 00 34 30 00 00 00 00 00 00 34 40 00 |.....40......4@.|
+00003a30 00 00 00 00 00 34 50 00 00 00 00 00 00 34 60 00 |.....4P......4`.|
+00003a40 00 00 00 00 00 34 70 00 00 00 00 00 00 34 80 00 |.....4p......4..|
+00003a50 00 00 00 00 00 34 90 00 00 00 00 00 00 34 a0 00 |.....4.......4..|
+00003a60 00 00 00 00 00 34 b0 00 00 00 00 00 00 34 c0 00 |.....4.......4..|
+00003a70 00 00 00 00 00 34 d0 00 00 00 00 00 00 34 e0 00 |.....4.......4..|
+00003a80 00 00 00 00 00 34 f0 00 00 00 00 00 00 35 00 00 |.....4.......5..|
+00003a90 00 00 00 00 00 35 10 00 00 00 00 00 00 35 20 00 |.....5.......5 .|
+00003aa0 00 00 00 00 00 35 30 00 00 00 00 00 00 35 40 00 |.....50......5@.|
+00003ab0 00 00 00 00 00 35 50 00 00 00 00 00 00 35 60 00 |.....5P......5`.|
+00003ac0 00 00 00 00 00 35 70 00 00 00 00 00 00 35 80 00 |.....5p......5..|
+00003ad0 00 00 00 00 00 35 90 00 00 00 00 00 00 35 a0 00 |.....5.......5..|
+00003ae0 00 00 00 00 00 35 b0 00 00 00 00 00 00 35 c0 00 |.....5.......5..|
+00003af0 00 00 00 00 00 35 d0 00 00 00 00 00 00 35 e0 00 |.....5.......5..|
+00003b00 00 00 00 00 00 35 f0 00 00 00 00 00 00 36 00 00 |.....5.......6..|
+00003b10 00 00 00 00 00 36 10 00 00 00 00 00 00 36 20 00 |.....6.......6 .|
+00003b20 00 00 00 00 00 36 30 00 00 00 00 00 00 36 40 00 |.....60......6@.|
+00003b30 00 00 00 00 00 36 50 00 00 00 00 00 00 36 60 00 |.....6P......6`.|
+00003b40 00 00 00 00 00 36 70 00 00 00 00 00 00 36 80 00 |.....6p......6..|
+00003b50 00 00 00 00 00 36 90 00 00 00 00 00 00 36 a0 00 |.....6.......6..|
+00003b60 00 00 00 00 00 36 b0 00 00 00 00 00 00 36 c0 00 |.....6.......6..|
+00003b70 00 00 00 00 00 36 d0 00 00 00 00 00 00 36 e0 00 |.....6.......6..|
+00003b80 00 00 00 00 00 36 f0 00 00 00 00 00 00 37 00 00 |.....6.......7..|
+00003b90 00 00 00 00 00 37 10 00 00 00 00 00 00 37 20 00 |.....7.......7 .|
+00003ba0 00 00 00 00 00 37 30 00 00 00 00 00 00 37 40 00 |.....70......7@.|
+00003bb0 00 00 00 00 00 37 50 00 00 00 00 00 00 37 60 00 |.....7P......7`.|
+00003bc0 00 00 00 00 00 37 70 00 00 00 00 00 00 37 80 00 |.....7p......7..|
+00003bd0 00 00 00 00 00 37 90 00 00 00 00 00 00 37 a0 00 |.....7.......7..|
+00003be0 00 00 00 00 00 37 b0 00 00 00 00 00 00 37 c0 00 |.....7.......7..|
+00003bf0 00 00 00 00 00 37 d0 00 00 00 00 00 00 37 e0 00 |.....7.......7..|
+00003c00 00 00 00 00 00 37 f0 00 00 00 00 00 00 38 00 00 |.....7.......8..|
+00003c10 00 00 00 00 00 38 10 00 00 00 00 00 00 38 20 00 |.....8.......8 .|
+00003c20 00 00 00 00 00 38 30 00 00 00 00 00 00 38 40 00 |.....80......8@.|
+00003c30 00 00 00 00 00 38 50 00 00 00 00 00 00 38 60 00 |.....8P......8`.|
+00003c40 00 00 00 00 00 38 70 00 00 00 00 00 00 38 80 00 |.....8p......8..|
+00003c50 00 00 00 00 00 38 90 00 00 00 00 00 00 38 a0 00 |.....8.......8..|
+00003c60 00 00 00 00 00 38 b0 00 00 00 00 00 00 38 c0 00 |.....8.......8..|
+00003c70 00 00 00 00 00 38 d0 00 00 00 00 00 00 38 e0 00 |.....8.......8..|
+00003c80 00 00 00 00 00 38 f0 00 00 00 00 00 00 39 00 00 |.....8.......9..|
+00003c90 00 00 00 00 00 39 10 00 00 00 00 00 00 39 20 00 |.....9.......9 .|
+00003ca0 00 00 00 00 00 39 30 00 00 00 00 00 00 39 40 00 |.....90......9@.|
+00003cb0 00 00 00 00 00 39 50 00 00 00 00 00 00 39 60 00 |.....9P......9`.|
+00003cc0 00 00 00 00 00 39 70 00 00 00 00 00 00 39 80 00 |.....9p......9..|
+00003cd0 00 00 00 00 00 39 90 00 00 00 00 00 00 39 a0 00 |.....9.......9..|
+00003ce0 00 00 00 00 00 39 b0 00 00 00 00 00 00 39 c0 00 |.....9.......9..|
+00003cf0 00 00 00 00 00 39 d0 00 00 00 00 00 00 39 e0 00 |.....9.......9..|
+00003d00 00 00 00 00 00 39 f0 00 00 00 00 00 00 3a 00 00 |.....9.......:..|
+00003d10 00 00 00 00 00 3a 10 00 00 00 00 00 00 3a 20 00 |.....:.......: .|
+00003d20 00 00 00 00 00 3a 30 00 00 00 00 00 00 3a 40 00 |.....:0......:@.|
+00003d30 00 00 00 00 00 3a 50 00 00 00 00 00 00 3a 60 00 |.....:P......:`.|
+00003d40 00 00 00 00 00 3a 70 00 00 00 00 00 00 3a 80 00 |.....:p......:..|
+00003d50 00 00 00 00 00 3a 90 00 00 00 00 00 00 3a a0 00 |.....:.......:..|
+00003d60 00 00 00 00 00 3a b0 00 00 00 00 00 00 3a c0 00 |.....:.......:..|
+00003d70 00 00 00 00 00 3a d0 00 00 00 00 00 00 3a e0 00 |.....:.......:..|
+00003d80 00 00 00 00 00 3a f0 00 00 00 00 00 00 3b 00 00 |.....:.......;..|
+00003d90 00 00 00 00 00 3b 10 00 00 00 00 00 00 3b 20 00 |.....;.......; .|
+00003da0 00 00 00 00 00 3b 30 00 00 00 00 00 00 3b 40 00 |.....;0......;@.|
+00003db0 00 00 00 00 00 3b 50 00 00 00 00 00 00 3b 60 00 |.....;P......;`.|
+00003dc0 00 00 00 00 00 3b 70 00 00 00 00 00 00 3b 80 00 |.....;p......;..|
+00003dd0 00 00 00 00 00 3b 90 00 00 00 00 00 00 3b a0 00 |.....;.......;..|
+00003de0 00 00 00 00 00 3b b0 00 00 00 00 00 00 3b c0 00 |.....;.......;..|
+00003df0 00 00 00 00 00 3b d0 00 00 00 00 00 00 3b e0 00 |.....;.......;..|
+00003e00 00 00 00 00 00 3b f0 00 00 00 00 00 00 3c 00 00 |.....;.......<..|
+00003e10 00 00 00 00 00 3c 10 00 00 00 00 00 00 3c 20 00 |.....<.......< .|
+00003e20 00 00 00 00 00 3c 30 00 00 00 00 00 00 3c 40 00 |.....<0......<@.|
+00003e30 00 00 00 00 00 3c 50 00 00 00 00 00 00 3c 60 00 |.....<P......<`.|
+00003e40 00 00 00 00 00 3c 70 00 00 00 00 00 00 3c 80 00 |.....<p......<..|
+00003e50 00 00 00 00 00 3c 90 00 00 00 00 00 00 3c a0 00 |.....<.......<..|
+00003e60 00 00 00 00 00 3c b0 00 00 00 00 00 00 3c c0 00 |.....<.......<..|
+00003e70 00 00 00 00 00 3c d0 00 00 00 00 00 00 3c e0 00 |.....<.......<..|
+00003e80 00 00 00 00 00 3c f0 00 00 00 00 00 00 3d 00 00 |.....<.......=..|
+00003e90 00 00 00 00 00 3d 10 00 00 00 00 00 00 3d 20 00 |.....=.......= .|
+00003ea0 00 00 00 00 00 3d 30 00 00 00 00 00 00 3d 40 00 |.....=0......=@.|
+00003eb0 00 00 00 00 00 3d 50 00 00 00 00 00 00 3d 60 00 |.....=P......=`.|
+00003ec0 00 00 00 00 00 3d 70 00 00 00 00 00 00 3d 80 00 |.....=p......=..|
+00003ed0 00 00 00 00 00 3d 90 00 00 00 00 00 00 3d a0 00 |.....=.......=..|
+00003ee0 00 00 00 00 00 3d b0 00 00 00 00 00 00 3d c0 00 |.....=.......=..|
+00003ef0 00 00 00 00 00 3d d0 00 00 00 00 00 00 3d e0 00 |.....=.......=..|
+00003f00 00 00 00 00 00 3d f0 00 00 00 00 00 00 3e 00 00 |.....=.......>..|
+00003f10 00 00 00 00 00 3e 10 00 00 00 00 00 00 3e 20 00 |.....>.......> .|
+00003f20 00 00 00 00 00 3e 30 00 00 00 00 00 00 3e 40 00 |.....>0......>@.|
+00003f30 00 00 00 00 00 3e 50 00 00 00 00 00 00 3e 60 00 |.....>P......>`.|
+00003f40 00 00 00 00 00 3e 70 00 00 00 00 00 00 3e 80 00 |.....>p......>..|
+00003f50 00 00 00 00 00 3e 90 00 00 00 00 00 00 3e a0 00 |.....>.......>..|
+00003f60 00 00 00 00 00 3e b0 00 00 00 00 00 00 3e c0 00 |.....>.......>..|
+00003f70 00 00 00 00 00 3e d0 00 00 00 00 00 00 3e e0 00 |.....>.......>..|
+00003f80 00 00 00 00 00 3e f0 00 00 00 00 00 00 3f 00 00 |.....>.......?..|
+00003f90 00 00 00 00 00 3f 10 00 00 00 00 00 00 3f 20 00 |.....?.......? .|
+00003fa0 00 00 00 00 00 3f 30 00 00 00 00 00 00 3f 40 00 |.....?0......?@.|
+00003fb0 00 00 00 00 00 3f 50 00 00 00 00 00 00 3f 60 00 |.....?P......?`.|
+00003fc0 00 00 00 00 00 3f 70 00 00 00 00 00 00 3f 80 00 |.....?p......?..|
+00003fd0 00 00 00 00 00 3f 90 00 00 00 00 00 00 3f a0 00 |.....?.......?..|
+00003fe0 00 00 00 00 00 3f b0 00 00 00 00 00 00 3f c0 00 |.....?.......?..|
+00003ff0 00 00 00 00 00 3f d0 00 00 00 00 00 00 3f e0 00 |.....?.......?..|
+00004000 00 00 00 00 00 3f f0 00 00 00 00 00 00 40 00 00 |.....?.......@..|
+00004010 00 00 00 00 00 40 10 00 00 00 00 00 00 40 20 00 |.....@.......@ .|
+00004020 00 00 00 00 00 40 30 00 00 00 00 00 00 40 40 00 |.....@0......@@.|
+00004030 00 00 00 00 00 40 50 00 00 00 00 00 00 40 60 00 |.....@P......@`.|
+00004040 00 00 00 00 00 40 70 00 00 00 00 00 00 40 80 00 |.....@p......@..|
+00004050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00005000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000051b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000051c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000051d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000051f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00005200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00006e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00007000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00007010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00007020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00007030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00007040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00007050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00007090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000070a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000070b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000070c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00007120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00408e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00409000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.hex
new file mode 100644
index 000000000000..dd2edf1acea2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.hex
@@ -0,0 +1,84 @@
+00000000 51 46 49 fb 00 00 00 02 00 00 00 00 00 00 00 00 |QFI.............|
+00000010 00 00 00 00 00 00 00 10 00 00 00 00 00 7e 00 00 |.............~..|
+00000020 00 00 00 00 00 00 00 01 00 00 00 00 00 01 00 00 |................|
+00000030 00 00 00 00 00 02 00 00 00 00 00 01 00 00 00 00 |................|
+00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 80 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 |................|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 80 00 00 00 00 05 00 00 80 00 00 00 00 06 00 00 |................|
+00030010 80 00 00 00 00 07 00 00 80 00 00 00 00 08 00 00 |................|
+00030020 80 00 00 00 00 09 00 00 80 00 00 00 00 0a 00 00 |................|
+00030030 80 00 00 00 00 0b 00 00 80 00 00 00 00 0c 00 00 |................|
+00030040 80 00 00 00 00 0d 00 00 80 00 00 00 00 0e 00 00 |................|
+00030050 80 00 00 00 00 0f 00 00 80 00 00 00 00 10 00 00 |................|
+00030060 80 00 00 00 00 11 00 00 80 00 00 00 00 12 00 00 |................|
+00030070 80 00 00 00 00 13 00 00 80 00 00 00 00 14 00 00 |................|
+00030080 80 00 00 00 00 15 00 00 80 00 00 00 00 16 00 00 |................|
+00030090 80 00 00 00 00 17 00 00 80 00 00 00 00 18 00 00 |................|
+000300a0 80 00 00 00 00 19 00 00 80 00 00 00 00 1a 00 00 |................|
+000300b0 80 00 00 00 00 1b 00 00 80 00 00 00 00 1c 00 00 |................|
+000300c0 80 00 00 00 00 1d 00 00 80 00 00 00 00 1e 00 00 |................|
+000300d0 80 00 00 00 00 1f 00 00 80 00 00 00 00 20 00 00 |............. ..|
+000300e0 80 00 00 00 00 21 00 00 80 00 00 00 00 22 00 00 |.....!......."..|
+000300f0 80 00 00 00 00 23 00 00 80 00 00 00 00 24 00 00 |.....#.......$..|
+00030100 80 00 00 00 00 25 00 00 80 00 00 00 00 26 00 00 |.....%.......&..|
+00030110 80 00 00 00 00 27 00 00 80 00 00 00 00 28 00 00 |.....'.......(..|
+00030120 80 00 00 00 00 29 00 00 80 00 00 00 00 2a 00 00 |.....).......*..|
+00030130 80 00 00 00 00 2b 00 00 80 00 00 00 00 2c 00 00 |.....+.......,..|
+00030140 80 00 00 00 00 2d 00 00 80 00 00 00 00 2e 00 00 |.....-..........|
+00030150 80 00 00 00 00 2f 00 00 80 00 00 00 00 30 00 00 |...../.......0..|
+00030160 80 00 00 00 00 31 00 00 80 00 00 00 00 32 00 00 |.....1.......2..|
+00030170 80 00 00 00 00 33 00 00 80 00 00 00 00 34 00 00 |.....3.......4..|
+00030180 80 00 00 00 00 35 00 00 80 00 00 00 00 36 00 00 |.....5.......6..|
+00030190 80 00 00 00 00 37 00 00 80 00 00 00 00 38 00 00 |.....7.......8..|
+000301a0 80 00 00 00 00 39 00 00 80 00 00 00 00 3a 00 00 |.....9.......:..|
+000301b0 80 00 00 00 00 3b 00 00 80 00 00 00 00 3c 00 00 |.....;.......<..|
+000301c0 80 00 00 00 00 3d 00 00 80 00 00 00 00 3e 00 00 |.....=.......>..|
+000301d0 80 00 00 00 00 3f 00 00 80 00 00 00 00 40 00 00 |.....?.......@..|
+000301e0 80 00 00 00 00 41 00 00 80 00 00 00 00 42 00 00 |.....A.......B..|
+000301f0 80 00 00 00 00 43 00 00 80 00 00 00 00 44 00 00 |.....C.......D..|
+00030200 80 00 00 00 00 45 00 00 00 00 00 00 00 00 00 00 |.....E..........|
+00030210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 |................|
+*
+00040080 00 01 00 01 00 01 00 01 00 01 00 01 00 00 00 00 |................|
+00040090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00050000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000501b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000501c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000501d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000501f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00050200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00057e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00058000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00058010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00058020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00058030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00058040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00058050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00058090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000580a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000580b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000580c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00058110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00058120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00059e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00459e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00460000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.hex
new file mode 100644
index 000000000000..240acc2c5605
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.hex
@@ -0,0 +1,32 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+007e0000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.hex
new file mode 100644
index 000000000000..0b5459c5c482
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.hex
@@ -0,0 +1,64 @@
+00000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00000010 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00000020 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00000030 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00000040 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 63 78 73 70 61 72 73 65 ff ff ff ff ff ff ff ff |cxsparse........|
+00000210 00 00 00 00 00 00 06 00 00 01 00 00 00 00 00 08 |................|
+00000220 00 20 00 00 ff ff f4 6f 00 00 00 00 00 00 00 00 |. .....o........|
+00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 00 00 00 04 00 00 10 05 00 00 20 06 ff ff ff ff |.......... .....|
+00000610 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00000a00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00000bb0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+00000bc0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+00000bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008800 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008a00 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008a20 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008a30 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008a40 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008a80 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008a90 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+00008aa0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+00008ab0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+00008ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008b10 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008b20 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+0000a800 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00200a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00200c00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00400c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+*
+00400e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+0040ac00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650a00 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+00650a10 00 00 00 00 00 00 02 00 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+00650a20 00 02 00 00 57 69 32 6b 00 00 00 00 00 fb 04 00 |....Wi2k........|
+00650a30 00 00 00 00 00 fb 04 00 00 02 ff 3f 00 00 00 03 |...........?....|
+00650a40 ff ff f5 b6 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00650a50 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00650a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00650c00
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.hex
new file mode 100644
index 000000000000..0e71c22314b2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.hex
@@ -0,0 +1,40 @@
+00000000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000000 63 6f 6e 65 63 74 69 78 00 00 00 02 00 01 00 00 |conectix........|
+01000010 ff ff ff ff ff ff ff ff 01 23 45 67 2a 69 6d 67 |.........#Eg*img|
+01000020 00 02 00 00 57 69 32 6b 00 00 00 00 01 00 00 00 |....Wi2k........|
+01000030 00 00 00 00 01 00 00 00 00 02 ff 3f 00 00 00 02 |...........?....|
+01000040 ff ff ef bd 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+01000050 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+01000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01000200
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdx.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdx.hex
new file mode 100644
index 000000000000..05ab0dd245cd
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdx.hex
@@ -0,0 +1,83 @@
+00000000 76 68 64 78 66 69 6c 65 00 00 00 00 00 00 00 00 |vhdxfile........|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010000 68 65 61 64 64 db 05 73 00 00 00 00 00 00 00 00 |headd..s........|
+00010010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00010040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00010050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020000 68 65 61 64 13 47 fd f1 01 00 00 00 00 00 00 00 |head.G..........|
+00020010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00020040 00 00 01 00 00 00 10 00 00 00 10 00 00 00 00 00 |................|
+00020050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00030000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00030010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00030020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00030030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00030040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00030050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00040000 72 65 67 69 4c d5 3e 14 02 00 00 00 00 00 00 00 |regiL.>.........|
+00040010 06 a2 7c 8b 90 47 9a 4b b8 fe 57 5f 05 0f 88 6e |..|..G.K..W_...n|
+00040020 00 00 20 00 00 00 00 00 00 00 10 00 00 00 00 00 |.. .............|
+00040030 66 77 c2 2d 23 f6 00 42 9d 64 11 5e 9b fd 4a 08 |fw.-#..B.d.^..J.|
+00040040 00 00 30 00 00 00 00 00 00 00 10 00 00 00 00 00 |..0.............|
+00040050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00200000 6d 65 74 61 64 61 74 61 00 00 05 00 00 00 00 00 |metadata........|
+00200010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00200020 37 67 a1 ca 36 fa 43 4d b3 b6 33 f0 aa 44 e7 6b |7g..6.CM..3..D.k|
+00200030 00 00 01 00 08 00 00 00 04 00 00 00 00 00 00 00 |................|
+00200040 24 42 a5 2f 1b cd 76 48 b2 11 5d be d8 3b f4 b8 |$B./..vH..]..;..|
+00200050 08 00 01 00 08 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200060 ab 12 ca be e6 b2 23 45 93 ef c3 09 e0 00 c7 46 |......#E.......F|
+00200070 10 00 01 00 10 00 00 00 06 00 00 00 00 00 00 00 |................|
+00200080 1d bf 41 81 6f a9 09 47 ba 47 f2 33 a8 fa ab 5f |..A.o..G.G.3..._|
+00200090 20 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 | ...............|
+002000a0 c7 48 a3 cd 5d 44 71 44 9c c9 e9 88 52 51 c5 56 |.H..]DqD....RQ.V|
+002000b0 24 00 01 00 04 00 00 00 06 00 00 00 00 00 00 00 |$...............|
+002000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00210000 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 |................|
+00210010 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
+00210020 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00 |................|
+00210030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00300000 06 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
+00300010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00400000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+004001b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+004001c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+004001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+004001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00400200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00407e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00408000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00408010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00408020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00408030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00408040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00408050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00408090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+004080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+004080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+004080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00408110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00408120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00409e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00809e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+01400000
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.hex b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.hex
new file mode 100644
index 000000000000..a4383f951e3d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.hex
@@ -0,0 +1,328 @@
+00000000 4b 44 4d 56 01 00 00 00 03 00 00 00 00 40 00 00 |KDMV.........@..|
+00000010 00 00 00 00 10 00 00 00 00 00 00 00 01 00 00 00 |................|
+00000020 00 00 00 00 01 00 00 00 00 00 00 00 00 02 00 00 |................|
+00000030 0b 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|
+00000040 20 00 00 00 00 00 00 00 00 0a 20 0d 0a 00 00 00 | ......... .....|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000200 23 20 44 69 73 6b 20 44 65 73 63 72 69 70 74 6f |# Disk Descripto|
+00000210 72 46 69 6c 65 0a 76 65 72 73 69 6f 6e 3d 31 0a |rFile.version=1.|
+00000220 43 49 44 3d 30 30 30 30 30 30 30 30 0a 70 61 72 |CID=00000000.par|
+00000230 65 6e 74 43 49 44 3d 66 66 66 66 66 66 66 66 0a |entCID=ffffffff.|
+00000240 63 72 65 61 74 65 54 79 70 65 3d 22 6d 6f 6e 6f |createType="mono|
+00000250 6c 69 74 68 69 63 53 70 61 72 73 65 22 0a 23 20 |lithicSparse".# |
+00000260 45 78 74 65 6e 74 20 64 65 73 63 72 69 70 74 69 |Extent descripti|
+00000270 6f 6e 0a 52 57 20 31 36 33 38 34 20 53 50 41 52 |on.RW 16384 SPAR|
+00000280 53 45 20 22 22 0a 23 20 54 68 65 20 44 69 73 6b |SE "".# The Disk|
+00000290 20 44 61 74 61 20 42 61 73 65 0a 23 44 44 42 0a | Data Base.#DDB.|
+000002a0 64 64 62 2e 61 64 61 70 74 65 72 54 79 70 65 20 |ddb.adapterType |
+000002b0 3d 20 22 69 64 65 22 0a 64 64 62 2e 67 65 6f 6d |= "ide".ddb.geom|
+000002c0 65 74 72 79 2e 63 79 6c 69 6e 64 65 72 73 20 3d |etry.cylinders =|
+000002d0 20 22 31 22 0a 64 64 62 2e 67 65 6f 6d 65 74 72 | "1".ddb.geometr|
+000002e0 79 2e 68 65 61 64 73 20 3d 20 22 32 35 35 22 0a |y.heads = "255".|
+000002f0 64 64 62 2e 67 65 6f 6d 65 74 72 79 2e 73 65 63 |ddb.geometry.sec|
+00000300 74 6f 72 73 20 3d 20 22 36 33 22 0a 00 00 00 00 |tors = "63".....|
+00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000400 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00000600 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00000610 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00000620 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00000630 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00000640 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00000650 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00000660 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00000670 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00000680 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00000690 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000006a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000006b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000006c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000006d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000006e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000006f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00000700 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00000710 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00000720 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00000730 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00000740 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00000750 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00000760 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00000770 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00000780 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00000790 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000007a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000007b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000007c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000007d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000007e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000007f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00000800 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00000810 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00000820 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00000830 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00000840 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00000850 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00000860 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00000870 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00000880 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00000890 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+000008a0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+000008b0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+000008c0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+000008d0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+000008e0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+000008f0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00000900 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00000910 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00000920 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00000930 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00000940 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00000950 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00000960 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00000970 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00000980 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00000990 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+000009a0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+000009b0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+000009c0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+000009d0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+000009e0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+000009f0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00000a00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00000a10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00000a20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00000a30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00000a40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00000a50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00000a60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00000a70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00000a80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00000a90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00000aa0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00000ab0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00000ac0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00000ad0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00000ae0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00000af0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00000b00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00000b10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00000b20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00000b30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00000b40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00000b50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00000b60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00000b70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00000b80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00000b90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00000ba0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00000bb0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00000bc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00000bd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00000be0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00000bf0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00000c00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00000c10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00000c20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00000c30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00000c40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00000c50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00000c60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00000c70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00000c80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00000c90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00000ca0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00000cb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00000cc0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00000cd0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00000ce0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00000cf0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00000d00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00000d10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00000d20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00000d30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00000d40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00000d50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00000d60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00000d70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00000d80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00000d90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00000da0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00000db0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00000dc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00000dd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00000de0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00000df0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00000e00 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00000e10 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00000e20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001600 0c 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 |................|
+00001610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00001800 20 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 | ...........0...|
+00001810 40 00 00 00 50 00 00 00 60 00 00 00 70 00 00 00 |@...P...`...p...|
+00001820 80 00 00 00 90 00 00 00 a0 00 00 00 b0 00 00 00 |................|
+00001830 c0 00 00 00 d0 00 00 00 e0 00 00 00 f0 00 00 00 |................|
+00001840 00 01 00 00 10 01 00 00 20 01 00 00 30 01 00 00 |........ ...0...|
+00001850 40 01 00 00 50 01 00 00 60 01 00 00 70 01 00 00 |@...P...`...p...|
+00001860 80 01 00 00 90 01 00 00 a0 01 00 00 b0 01 00 00 |................|
+00001870 c0 01 00 00 d0 01 00 00 e0 01 00 00 f0 01 00 00 |................|
+00001880 00 02 00 00 10 02 00 00 20 02 00 00 30 02 00 00 |........ ...0...|
+00001890 40 02 00 00 50 02 00 00 60 02 00 00 70 02 00 00 |@...P...`...p...|
+000018a0 80 02 00 00 90 02 00 00 a0 02 00 00 b0 02 00 00 |................|
+000018b0 c0 02 00 00 d0 02 00 00 e0 02 00 00 f0 02 00 00 |................|
+000018c0 00 03 00 00 10 03 00 00 20 03 00 00 30 03 00 00 |........ ...0...|
+000018d0 40 03 00 00 50 03 00 00 60 03 00 00 70 03 00 00 |@...P...`...p...|
+000018e0 80 03 00 00 90 03 00 00 a0 03 00 00 b0 03 00 00 |................|
+000018f0 c0 03 00 00 d0 03 00 00 e0 03 00 00 f0 03 00 00 |................|
+00001900 00 04 00 00 10 04 00 00 20 04 00 00 30 04 00 00 |........ ...0...|
+00001910 40 04 00 00 50 04 00 00 60 04 00 00 70 04 00 00 |@...P...`...p...|
+00001920 80 04 00 00 90 04 00 00 a0 04 00 00 b0 04 00 00 |................|
+00001930 c0 04 00 00 d0 04 00 00 e0 04 00 00 f0 04 00 00 |................|
+00001940 00 05 00 00 10 05 00 00 20 05 00 00 30 05 00 00 |........ ...0...|
+00001950 40 05 00 00 50 05 00 00 60 05 00 00 70 05 00 00 |@...P...`...p...|
+00001960 80 05 00 00 90 05 00 00 a0 05 00 00 b0 05 00 00 |................|
+00001970 c0 05 00 00 d0 05 00 00 e0 05 00 00 f0 05 00 00 |................|
+00001980 00 06 00 00 10 06 00 00 20 06 00 00 30 06 00 00 |........ ...0...|
+00001990 40 06 00 00 50 06 00 00 60 06 00 00 70 06 00 00 |@...P...`...p...|
+000019a0 80 06 00 00 90 06 00 00 a0 06 00 00 b0 06 00 00 |................|
+000019b0 c0 06 00 00 d0 06 00 00 e0 06 00 00 f0 06 00 00 |................|
+000019c0 00 07 00 00 10 07 00 00 20 07 00 00 30 07 00 00 |........ ...0...|
+000019d0 40 07 00 00 50 07 00 00 60 07 00 00 70 07 00 00 |@...P...`...p...|
+000019e0 80 07 00 00 90 07 00 00 a0 07 00 00 b0 07 00 00 |................|
+000019f0 c0 07 00 00 d0 07 00 00 e0 07 00 00 f0 07 00 00 |................|
+00001a00 00 08 00 00 10 08 00 00 20 08 00 00 30 08 00 00 |........ ...0...|
+00001a10 40 08 00 00 50 08 00 00 60 08 00 00 70 08 00 00 |@...P...`...p...|
+00001a20 80 08 00 00 90 08 00 00 a0 08 00 00 b0 08 00 00 |................|
+00001a30 c0 08 00 00 d0 08 00 00 e0 08 00 00 f0 08 00 00 |................|
+00001a40 00 09 00 00 10 09 00 00 20 09 00 00 30 09 00 00 |........ ...0...|
+00001a50 40 09 00 00 50 09 00 00 60 09 00 00 70 09 00 00 |@...P...`...p...|
+00001a60 80 09 00 00 90 09 00 00 a0 09 00 00 b0 09 00 00 |................|
+00001a70 c0 09 00 00 d0 09 00 00 e0 09 00 00 f0 09 00 00 |................|
+00001a80 00 0a 00 00 10 0a 00 00 20 0a 00 00 30 0a 00 00 |........ ...0...|
+00001a90 40 0a 00 00 50 0a 00 00 60 0a 00 00 70 0a 00 00 |@...P...`...p...|
+00001aa0 80 0a 00 00 90 0a 00 00 a0 0a 00 00 b0 0a 00 00 |................|
+00001ab0 c0 0a 00 00 d0 0a 00 00 e0 0a 00 00 f0 0a 00 00 |................|
+00001ac0 00 0b 00 00 10 0b 00 00 20 0b 00 00 30 0b 00 00 |........ ...0...|
+00001ad0 40 0b 00 00 50 0b 00 00 60 0b 00 00 70 0b 00 00 |@...P...`...p...|
+00001ae0 80 0b 00 00 90 0b 00 00 a0 0b 00 00 b0 0b 00 00 |................|
+00001af0 c0 0b 00 00 d0 0b 00 00 e0 0b 00 00 f0 0b 00 00 |................|
+00001b00 00 0c 00 00 10 0c 00 00 20 0c 00 00 30 0c 00 00 |........ ...0...|
+00001b10 40 0c 00 00 50 0c 00 00 60 0c 00 00 70 0c 00 00 |@...P...`...p...|
+00001b20 80 0c 00 00 90 0c 00 00 a0 0c 00 00 b0 0c 00 00 |................|
+00001b30 c0 0c 00 00 d0 0c 00 00 e0 0c 00 00 f0 0c 00 00 |................|
+00001b40 00 0d 00 00 10 0d 00 00 20 0d 00 00 30 0d 00 00 |........ ...0...|
+00001b50 40 0d 00 00 50 0d 00 00 60 0d 00 00 70 0d 00 00 |@...P...`...p...|
+00001b60 80 0d 00 00 90 0d 00 00 a0 0d 00 00 b0 0d 00 00 |................|
+00001b70 c0 0d 00 00 d0 0d 00 00 e0 0d 00 00 f0 0d 00 00 |................|
+00001b80 00 0e 00 00 10 0e 00 00 20 0e 00 00 30 0e 00 00 |........ ...0...|
+00001b90 40 0e 00 00 50 0e 00 00 60 0e 00 00 70 0e 00 00 |@...P...`...p...|
+00001ba0 80 0e 00 00 90 0e 00 00 a0 0e 00 00 b0 0e 00 00 |................|
+00001bb0 c0 0e 00 00 d0 0e 00 00 e0 0e 00 00 f0 0e 00 00 |................|
+00001bc0 00 0f 00 00 10 0f 00 00 20 0f 00 00 30 0f 00 00 |........ ...0...|
+00001bd0 40 0f 00 00 50 0f 00 00 60 0f 00 00 70 0f 00 00 |@...P...`...p...|
+00001be0 80 0f 00 00 90 0f 00 00 a0 0f 00 00 b0 0f 00 00 |................|
+00001bf0 c0 0f 00 00 d0 0f 00 00 e0 0f 00 00 f0 0f 00 00 |................|
+00001c00 00 10 00 00 10 10 00 00 20 10 00 00 30 10 00 00 |........ ...0...|
+00001c10 40 10 00 00 50 10 00 00 60 10 00 00 70 10 00 00 |@...P...`...p...|
+00001c20 80 10 00 00 90 10 00 00 a0 10 00 00 b0 10 00 00 |................|
+00001c30 c0 10 00 00 d0 10 00 00 e0 10 00 00 f0 10 00 00 |................|
+00001c40 00 11 00 00 10 11 00 00 20 11 00 00 30 11 00 00 |........ ...0...|
+00001c50 40 11 00 00 50 11 00 00 60 11 00 00 70 11 00 00 |@...P...`...p...|
+00001c60 80 11 00 00 90 11 00 00 a0 11 00 00 b0 11 00 00 |................|
+00001c70 c0 11 00 00 d0 11 00 00 e0 11 00 00 f0 11 00 00 |................|
+00001c80 00 12 00 00 10 12 00 00 20 12 00 00 30 12 00 00 |........ ...0...|
+00001c90 40 12 00 00 50 12 00 00 60 12 00 00 70 12 00 00 |@...P...`...p...|
+00001ca0 80 12 00 00 90 12 00 00 a0 12 00 00 b0 12 00 00 |................|
+00001cb0 c0 12 00 00 d0 12 00 00 e0 12 00 00 f0 12 00 00 |................|
+00001cc0 00 13 00 00 10 13 00 00 20 13 00 00 30 13 00 00 |........ ...0...|
+00001cd0 40 13 00 00 50 13 00 00 60 13 00 00 70 13 00 00 |@...P...`...p...|
+00001ce0 80 13 00 00 90 13 00 00 a0 13 00 00 b0 13 00 00 |................|
+00001cf0 c0 13 00 00 d0 13 00 00 e0 13 00 00 f0 13 00 00 |................|
+00001d00 00 14 00 00 10 14 00 00 20 14 00 00 30 14 00 00 |........ ...0...|
+00001d10 40 14 00 00 50 14 00 00 60 14 00 00 70 14 00 00 |@...P...`...p...|
+00001d20 80 14 00 00 90 14 00 00 a0 14 00 00 b0 14 00 00 |................|
+00001d30 c0 14 00 00 d0 14 00 00 e0 14 00 00 f0 14 00 00 |................|
+00001d40 00 15 00 00 10 15 00 00 20 15 00 00 30 15 00 00 |........ ...0...|
+00001d50 40 15 00 00 50 15 00 00 60 15 00 00 70 15 00 00 |@...P...`...p...|
+00001d60 80 15 00 00 90 15 00 00 a0 15 00 00 b0 15 00 00 |................|
+00001d70 c0 15 00 00 d0 15 00 00 e0 15 00 00 f0 15 00 00 |................|
+00001d80 00 16 00 00 10 16 00 00 20 16 00 00 30 16 00 00 |........ ...0...|
+00001d90 40 16 00 00 50 16 00 00 60 16 00 00 70 16 00 00 |@...P...`...p...|
+00001da0 80 16 00 00 90 16 00 00 a0 16 00 00 b0 16 00 00 |................|
+00001db0 c0 16 00 00 d0 16 00 00 e0 16 00 00 f0 16 00 00 |................|
+00001dc0 00 17 00 00 10 17 00 00 20 17 00 00 30 17 00 00 |........ ...0...|
+00001dd0 40 17 00 00 50 17 00 00 60 17 00 00 70 17 00 00 |@...P...`...p...|
+00001de0 80 17 00 00 90 17 00 00 a0 17 00 00 b0 17 00 00 |................|
+00001df0 c0 17 00 00 d0 17 00 00 e0 17 00 00 f0 17 00 00 |................|
+00001e00 00 18 00 00 10 18 00 00 20 18 00 00 30 18 00 00 |........ ...0...|
+00001e10 40 18 00 00 50 18 00 00 60 18 00 00 70 18 00 00 |@...P...`...p...|
+00001e20 80 18 00 00 90 18 00 00 a0 18 00 00 b0 18 00 00 |................|
+00001e30 c0 18 00 00 d0 18 00 00 e0 18 00 00 f0 18 00 00 |................|
+00001e40 00 19 00 00 10 19 00 00 20 19 00 00 30 19 00 00 |........ ...0...|
+00001e50 40 19 00 00 50 19 00 00 60 19 00 00 70 19 00 00 |@...P...`...p...|
+00001e60 80 19 00 00 90 19 00 00 a0 19 00 00 b0 19 00 00 |................|
+00001e70 c0 19 00 00 d0 19 00 00 e0 19 00 00 f0 19 00 00 |................|
+00001e80 00 1a 00 00 10 1a 00 00 20 1a 00 00 30 1a 00 00 |........ ...0...|
+00001e90 40 1a 00 00 50 1a 00 00 60 1a 00 00 70 1a 00 00 |@...P...`...p...|
+00001ea0 80 1a 00 00 90 1a 00 00 a0 1a 00 00 b0 1a 00 00 |................|
+00001eb0 c0 1a 00 00 d0 1a 00 00 e0 1a 00 00 f0 1a 00 00 |................|
+00001ec0 00 1b 00 00 10 1b 00 00 20 1b 00 00 30 1b 00 00 |........ ...0...|
+00001ed0 40 1b 00 00 50 1b 00 00 60 1b 00 00 70 1b 00 00 |@...P...`...p...|
+00001ee0 80 1b 00 00 90 1b 00 00 a0 1b 00 00 b0 1b 00 00 |................|
+00001ef0 c0 1b 00 00 d0 1b 00 00 e0 1b 00 00 f0 1b 00 00 |................|
+00001f00 00 1c 00 00 10 1c 00 00 20 1c 00 00 30 1c 00 00 |........ ...0...|
+00001f10 40 1c 00 00 50 1c 00 00 60 1c 00 00 70 1c 00 00 |@...P...`...p...|
+00001f20 80 1c 00 00 90 1c 00 00 a0 1c 00 00 b0 1c 00 00 |................|
+00001f30 c0 1c 00 00 d0 1c 00 00 e0 1c 00 00 f0 1c 00 00 |................|
+00001f40 00 1d 00 00 10 1d 00 00 20 1d 00 00 30 1d 00 00 |........ ...0...|
+00001f50 40 1d 00 00 50 1d 00 00 60 1d 00 00 70 1d 00 00 |@...P...`...p...|
+00001f60 80 1d 00 00 90 1d 00 00 a0 1d 00 00 b0 1d 00 00 |................|
+00001f70 c0 1d 00 00 d0 1d 00 00 e0 1d 00 00 f0 1d 00 00 |................|
+00001f80 00 1e 00 00 10 1e 00 00 20 1e 00 00 30 1e 00 00 |........ ...0...|
+00001f90 40 1e 00 00 50 1e 00 00 60 1e 00 00 70 1e 00 00 |@...P...`...p...|
+00001fa0 80 1e 00 00 90 1e 00 00 a0 1e 00 00 b0 1e 00 00 |................|
+00001fb0 c0 1e 00 00 d0 1e 00 00 e0 1e 00 00 f0 1e 00 00 |................|
+00001fc0 00 1f 00 00 10 1f 00 00 20 1f 00 00 30 1f 00 00 |........ ...0...|
+00001fd0 40 1f 00 00 50 1f 00 00 60 1f 00 00 70 1f 00 00 |@...P...`...p...|
+00001fe0 80 1f 00 00 90 1f 00 00 a0 1f 00 00 b0 1f 00 00 |................|
+00001ff0 c0 1f 00 00 d0 1f 00 00 e0 1f 00 00 f0 1f 00 00 |................|
+00002000 00 20 00 00 10 20 00 00 20 20 00 00 30 20 00 00 |. ... .. ..0 ..|
+00002010 40 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@ ..............|
+00002020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00004000 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+000041b0 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 80 01 |B.B.B.B.B.B.B...|
+000041c0 01 00 a5 00 3f 01 3f 00 00 00 c1 3e 00 00 00 00 |....?.?....>....|
+000041d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+000041f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+00004200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00007e00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00008000 57 45 56 82 00 00 00 00 00 00 00 00 00 00 00 00 |WEV.............|
+00008010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00008020 00 00 00 00 00 00 00 00 00 02 00 00 3f 00 00 00 |............?...|
+00008030 ff 00 00 00 01 00 00 00 c1 3e 00 00 c1 3e 00 00 |.........>...>..|
+00008040 00 00 00 00 00 00 00 00 10 0e 00 00 00 00 00 00 |................|
+00008050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008080 00 00 00 00 57 45 56 82 1e 13 08 00 00 20 00 00 |....WEV...... ..|
+00008090 00 00 00 00 00 20 00 00 10 00 00 00 00 00 00 00 |..... ..........|
+000080a0 07 00 00 00 00 01 00 00 10 20 00 00 00 00 00 00 |......... ......|
+000080b0 01 00 00 00 c1 3e 00 00 00 00 00 00 00 00 00 00 |.....>..........|
+000080c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+00008110 00 00 00 00 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |....B.B.B.B.B.B.|
+00008120 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a 42 0a |B.B.B.B.B.B.B.B.|
+*
+00009e00 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a 50 0a |P.P.P.P.P.P.P.P.|
+*
+00409e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+*
+0040a000
diff --git a/usr.bin/mkimg/tests/mkimg_test.sh b/usr.bin/mkimg/tests/mkimg_test.sh
new file mode 100755
index 000000000000..7c6593b219ef
--- /dev/null
+++ b/usr.bin/mkimg/tests/mkimg_test.sh
@@ -0,0 +1,161 @@
+
+mkimg_blksz_list="512 4096"
+mkimg_format_list="qcow qcow2 raw vhd vhdf vhdx vmdk"
+mkimg_geom_list="1x1 63x255"
+mkimg_scheme_list="apm bsd ebr gpt mbr"
+
+bootcode()
+{
+ case $1 in
+ bsd) echo 8192 ;;
+ gpt|mbr) echo 512 ;;
+ *) echo 0 ;;
+ esac
+ return 0
+}
+
+mkcontents()
+{
+ local byte count name
+
+ byte=$1
+ count=$2
+
+ name=_tmp-$byte-$count.bin
+ jot -b $byte $(($count/2)) > $name
+ echo $name
+ return 0
+}
+
+makeimage()
+{
+ local blksz bootarg bootsz format geom nhds nsecs partarg pfx scheme
+
+ format=$1
+ scheme=$2
+ blksz=$3
+ geom=$4
+ pfx=$5
+ shift 5
+
+ nsecs=${geom%x*}
+ nhds=${geom#*x}
+
+ bootsz=`bootcode $scheme`
+ if test $bootsz -gt 0; then
+ bootarg="-b `mkcontents B $bootsz`"
+ else
+ bootarg=""
+ fi
+
+ partarg=""
+ for P in $*; do
+ partarg="$partarg -p $P"
+ done
+ if test -z "$partarg"; then
+ local swap ufs
+ swap="-p freebsd-swap::128K"
+ ufs="-p freebsd-ufs:=$(atf_get_srcdir)/partition_data_4M.bin"
+ partarg="$ufs $swap"
+ fi
+
+ imagename=$pfx-$geom-$blksz-$scheme.$format
+
+ mkimg -y -f $format -o $imagename -s $scheme -P $blksz -H $nhds -T $nsecs \
+ $bootarg $partarg
+ echo $imagename
+ return 0
+}
+
+mkimg_rebase()
+{
+ local baseline image result tmpfile update
+
+ image=$1
+ result=$2
+
+ baseline=$image.hex
+ update=yes
+
+ if test -f $baseline; then
+ tmpfile=_tmp-baseline
+ sed -e '/^#.*/D' < $baseline > $tmpfile
+ if diff -u $tmpfile $result; then
+ update=no
+ fi
+ fi
+
+ if test $update = yes; then
+ cat $result > $baseline
+ fi
+
+ rm $image $result _tmp-*
+ return 0
+}
+
+mkimg_test()
+{
+ local blksz format geom scheme
+
+ geom=$1
+ blksz=$2
+ scheme=$3
+ format=$4
+
+ case $scheme in
+ ebr|mbr)
+ bsd=`makeimage raw bsd $blksz $geom _tmp`
+ partinfo="freebsd:=$bsd"
+ ;;
+ *)
+ partinfo=""
+ ;;
+ esac
+ image=`makeimage $format $scheme $blksz $geom img $partinfo`
+ result=$image.out
+ hexdump -C $image > $result
+ if test "x$mkimg_update_baseline" = "xyes"; then
+ mkimg_rebase $image $result
+ else
+ baseline=`atf_get_srcdir`/$image
+ atf_check -s exit:0 diff -u $baseline $result
+ fi
+ return 0
+}
+
+atf_test_case rebase
+rebase_body()
+{
+ local nm
+
+ mkimg_update_baseline=yes
+ for nm in $mkimg_tests; do
+ ${nm}_body
+ done
+ return 0
+}
+
+atf_init_test_cases()
+{
+ local B F G S nm
+
+ for G in $mkimg_geom_list; do
+ for B in $mkimg_blksz_list; do
+ for S in $mkimg_scheme_list; do
+ for F in $mkimg_format_list; do
+ nm="${S}_${G}_${B}_${F}"
+ atf_test_case $nm
+ eval "${nm}_body() { mkimg_test $G $B $S $F; }"
+ mkimg_tests="${mkimg_tests} ${nm}"
+ atf_add_test_case $nm
+ done
+ done
+ done
+ done
+
+ # XXX hack to make updating the baseline easier
+ if test "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value"; then
+ atf_add_test_case rebase
+ fi
+}
+
diff --git a/usr.bin/mkimg/uuid.c b/usr.bin/mkimg/uuid.c
new file mode 100644
index 000000000000..470d92c76293
--- /dev/null
+++ b/usr.bin/mkimg/uuid.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2016 Marcel Moolenaar
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "endian.h"
+#include "image.h"
+#include "mkimg.h"
+
+static void osdep_uuidgen(mkimg_uuid_t *);
+
+#ifdef __APPLE__
+#include <uuid/uuid.h>
+
+static void
+osdep_uuidgen(mkimg_uuid_t *uuid)
+{
+
+ uuid_generate_time((void *)uuid);
+}
+#endif /* __APPLE__ */
+
+#ifdef __FreeBSD__
+#include <sys/uuid.h>
+
+static void
+osdep_uuidgen(mkimg_uuid_t *uuid)
+{
+
+ uuidgen((void *)uuid, 1);
+}
+#endif /* __FreeBSD__ */
+
+#ifdef __linux__
+#include <stdlib.h>
+#include <time.h>
+
+static void
+osdep_uuidgen(mkimg_uuid_t *uuid)
+{
+ struct timeval tv;
+ uint64_t time = 0x01B21DD213814000LL;
+ u_int i;
+ uint16_t seq;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ abort();
+
+ time += (uint64_t)tv.tv_sec * 10000000LL;
+ time += tv.tv_usec * 10;
+
+ uuid->time_low = (uint32_t)time;
+ uuid->time_mid = (uint16_t)(time >> 32);
+ uuid->time_hi_and_version = (uint16_t)(time >> 48) & 0xfff;
+ uuid->time_hi_and_version |= 1 << 12;
+
+ seq = random();
+
+ uuid->clock_seq_hi_and_reserved = (uint8_t)(seq >> 8) & 0x3f;
+ uuid->clock_seq_low = (uint8_t)seq;
+
+ for (i = 0; i < 6; i++)
+ uuid->node[i] = (uint8_t)random();
+ uuid->node[0] |= 0x01;
+}
+#endif /* __linux__ */
+
+void
+mkimg_uuid(mkimg_uuid_t *uuid)
+{
+ static uint8_t gen[sizeof(mkimg_uuid_t)];
+ u_int i;
+
+ if (!unit_testing) {
+ osdep_uuidgen(uuid);
+ return;
+ }
+
+ for (i = 0; i < sizeof(gen); i++)
+ gen[i]++;
+ memcpy(uuid, gen, sizeof(*uuid));
+}
+
+void
+mkimg_uuid_enc(void *buf, const mkimg_uuid_t *uuid)
+{
+ uint8_t *p = buf;
+ u_int i;
+
+ le32enc(p, uuid->time_low);
+ le16enc(p + 4, uuid->time_mid);
+ le16enc(p + 6, uuid->time_hi_and_version);
+ p[8] = uuid->clock_seq_hi_and_reserved;
+ p[9] = uuid->clock_seq_low;
+ for (i = 0; i < 6; i++)
+ p[10 + i] = uuid->node[i];
+}
diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c
new file mode 100644
index 000000000000..1e1f1e7f3c3e
--- /dev/null
+++ b/usr.bin/mkimg/vhd.c
@@ -0,0 +1,412 @@
+/*-
+ * Copyright (c) 2014, 2015 Marcel Moolenaar
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "endian.h"
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+
+/*
+ * General notes:
+ * o File is in network byte order.
+ * o The timestamp is seconds since 1/1/2000 12:00:00 AM UTC
+ *
+ * This file is divided in 3 parts:
+ * 1. Common definitions
+ * 2. Dynamic VHD support
+ * 3. Fixed VHD support
+ */
+
+/*
+ * PART 1: Common definitions
+ */
+
+#define VHD_SECTOR_SIZE 512
+#define VHD_BLOCK_SIZE (4096 * VHD_SECTOR_SIZE) /* 2MB blocks */
+
+struct vhd_geom {
+ uint16_t cylinders;
+ uint8_t heads;
+ uint8_t sectors;
+};
+
+struct vhd_footer {
+ uint64_t cookie;
+#define VHD_FOOTER_COOKIE 0x636f6e6563746978ULL
+ uint32_t features;
+#define VHD_FEATURES_TEMPORARY 0x01
+#define VHD_FEATURES_RESERVED 0x02
+ uint32_t version;
+#define VHD_VERSION 0x00010000
+ uint64_t data_offset;
+ uint32_t timestamp;
+ uint32_t creator_tool;
+#define VHD_CREATOR_TOOL 0x2a696d67 /* FreeBSD mkimg */
+ uint32_t creator_version;
+#define VHD_CREATOR_VERSION 0x00020000
+ uint32_t creator_os;
+#define VHD_CREATOR_OS 0x5769326b /* Wi2k */
+ uint64_t original_size;
+ uint64_t current_size;
+ struct vhd_geom geometry;
+ uint32_t disk_type;
+#define VHD_DISK_TYPE_FIXED 2
+#define VHD_DISK_TYPE_DYNAMIC 3
+#define VHD_DISK_TYPE_DIFF 4
+ uint32_t checksum;
+ mkimg_uuid_t id;
+ uint8_t saved_state;
+ uint8_t _reserved[427];
+};
+#if __has_extension(c_static_assert)
+_Static_assert(sizeof(struct vhd_footer) == VHD_SECTOR_SIZE,
+ "Wrong size for footer");
+#endif
+
+static uint32_t
+vhd_checksum(void *buf, size_t sz)
+{
+ uint8_t *p = buf;
+ uint32_t sum;
+ size_t ofs;
+
+ sum = 0;
+ for (ofs = 0; ofs < sz; ofs++)
+ sum += p[ofs];
+ return (~sum);
+}
+
+static void
+vhd_geometry(uint64_t image_size, struct vhd_geom *geom)
+{
+ lba_t imgsz;
+ long cth;
+
+ imgsz = image_size / VHD_SECTOR_SIZE;
+
+ /* Respect command line options if possible. */
+ if (nheads > 1 && nheads < 256 &&
+ nsecs > 1 && nsecs < 256 &&
+ ncyls < 65536) {
+ geom->cylinders = (ncyls != 0) ? ncyls :
+ imgsz / (nheads * nsecs);
+ geom->heads = nheads;
+ geom->sectors = nsecs;
+ return;
+ }
+
+ if (imgsz > 65536 * 16 * 255)
+ imgsz = 65536 * 16 * 255;
+ if (imgsz >= 65535 * 16 * 63) {
+ geom->cylinders = imgsz / (16 * 255);
+ geom->heads = 16;
+ geom->sectors = 255;
+ return;
+ }
+ geom->sectors = 17;
+ cth = imgsz / 17;
+ geom->heads = (cth + 1023) / 1024;
+ if (geom->heads < 4)
+ geom->heads = 4;
+ if (cth >= (geom->heads * 1024) || geom->heads > 16) {
+ geom->heads = 16;
+ geom->sectors = 31;
+ cth = imgsz / 31;
+ }
+ if (cth >= (geom->heads * 1024)) {
+ geom->heads = 16;
+ geom->sectors = 63;
+ cth = imgsz / 63;
+ }
+ geom->cylinders = cth / geom->heads;
+}
+
+static uint64_t
+vhd_resize(uint64_t origsz)
+{
+ struct vhd_geom geom;
+ uint64_t newsz;
+
+ /*
+ * Round the image size to the pre-determined geometry that
+ * matches the image size. This circular dependency implies
+ * that we need to loop to handle boundary conditions.
+ * The first time, newsz equals origsz and the geometry will
+ * typically yield a new size that's smaller. We keep adding
+ * cylinder's worth of sectors to the new size until its
+ * larger or equal or origsz. But during those iterations,
+ * the geometry can change, so we need to account for that.
+ */
+ newsz = origsz;
+ while (1) {
+ vhd_geometry(newsz, &geom);
+ newsz = (int64_t)geom.cylinders * geom.heads *
+ geom.sectors * VHD_SECTOR_SIZE;
+ if (newsz >= origsz)
+ break;
+ newsz += geom.heads * geom.sectors * VHD_SECTOR_SIZE;
+ }
+ return (newsz);
+}
+
+static uint32_t
+vhd_timestamp(void)
+{
+ time_t t;
+
+ if (!unit_testing) {
+ t = time(NULL);
+ return (t - 0x386d4380);
+ }
+
+ return (0x01234567);
+}
+
+static void
+vhd_make_footer(struct vhd_footer *footer, uint64_t image_size,
+ uint32_t disk_type, uint64_t data_offset)
+{
+ mkimg_uuid_t id;
+
+ memset(footer, 0, sizeof(*footer));
+ be64enc(&footer->cookie, VHD_FOOTER_COOKIE);
+ be32enc(&footer->features, VHD_FEATURES_RESERVED);
+ be32enc(&footer->version, VHD_VERSION);
+ be64enc(&footer->data_offset, data_offset);
+ be32enc(&footer->timestamp, vhd_timestamp());
+ be32enc(&footer->creator_tool, VHD_CREATOR_TOOL);
+ be32enc(&footer->creator_version, VHD_CREATOR_VERSION);
+ be32enc(&footer->creator_os, VHD_CREATOR_OS);
+ be64enc(&footer->original_size, image_size);
+ be64enc(&footer->current_size, image_size);
+ vhd_geometry(image_size, &footer->geometry);
+ be16enc(&footer->geometry.cylinders, footer->geometry.cylinders);
+ be32enc(&footer->disk_type, disk_type);
+ mkimg_uuid(&id);
+ mkimg_uuid_enc(&footer->id, &id);
+ be32enc(&footer->checksum, vhd_checksum(footer, sizeof(*footer)));
+}
+
+/*
+ * PART 2: Dynamic VHD support
+ *
+ * Notes:
+ * o File layout:
+ * copy of disk footer
+ * dynamic disk header
+ * block allocation table (BAT)
+ * data blocks
+ * disk footer
+ */
+
+struct vhd_dyn_header {
+ uint64_t cookie;
+#define VHD_HEADER_COOKIE 0x6378737061727365ULL
+ uint64_t data_offset;
+ uint64_t table_offset;
+ uint32_t version;
+ uint32_t max_entries;
+ uint32_t block_size;
+ uint32_t checksum;
+ mkimg_uuid_t parent_id;
+ uint32_t parent_timestamp;
+ char _reserved1[4];
+ uint16_t parent_name[256]; /* UTF-16 */
+ struct {
+ uint32_t code;
+ uint32_t data_space;
+ uint32_t data_length;
+ uint32_t _reserved;
+ uint64_t data_offset;
+ } parent_locator[8];
+ char _reserved2[256];
+};
+#if __has_extension(c_static_assert)
+_Static_assert(sizeof(struct vhd_dyn_header) == VHD_SECTOR_SIZE * 2,
+ "Wrong size for header");
+#endif
+
+static int
+vhd_dyn_resize(lba_t imgsz)
+{
+ uint64_t imagesz;
+
+ imagesz = vhd_resize(imgsz * secsz);
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+vhd_dyn_write(int fd)
+{
+ struct vhd_footer footer;
+ struct vhd_dyn_header header;
+ uint64_t imgsz, rawsz;
+ lba_t blk, blkcnt, nblks;
+ uint32_t *bat;
+ void *bitmap;
+ size_t batsz;
+ uint32_t sector;
+ int bat_entries, error, entry;
+
+ rawsz = image_get_size() * secsz;
+ imgsz = (rawsz + VHD_BLOCK_SIZE - 1) & ~(VHD_BLOCK_SIZE - 1);
+
+ vhd_make_footer(&footer, rawsz, VHD_DISK_TYPE_DYNAMIC, sizeof(footer));
+ if (sparse_write(fd, &footer, sizeof(footer)) < 0)
+ return (errno);
+
+ bat_entries = imgsz / VHD_BLOCK_SIZE;
+ memset(&header, 0, sizeof(header));
+ be64enc(&header.cookie, VHD_HEADER_COOKIE);
+ be64enc(&header.data_offset, ~0ULL);
+ be64enc(&header.table_offset, sizeof(footer) + sizeof(header));
+ be32enc(&header.version, VHD_VERSION);
+ be32enc(&header.max_entries, bat_entries);
+ be32enc(&header.block_size, VHD_BLOCK_SIZE);
+ be32enc(&header.checksum, vhd_checksum(&header, sizeof(header)));
+ if (sparse_write(fd, &header, sizeof(header)) < 0)
+ return (errno);
+
+ batsz = bat_entries * sizeof(uint32_t);
+ batsz = (batsz + VHD_SECTOR_SIZE - 1) & ~(VHD_SECTOR_SIZE - 1);
+ bat = malloc(batsz);
+ if (bat == NULL)
+ return (errno);
+ memset(bat, 0xff, batsz);
+ blkcnt = VHD_BLOCK_SIZE / secsz;
+ sector = (sizeof(footer) + sizeof(header) + batsz) / VHD_SECTOR_SIZE;
+ for (entry = 0; entry < bat_entries; entry++) {
+ blk = entry * blkcnt;
+ if (image_data(blk, blkcnt)) {
+ be32enc(&bat[entry], sector);
+ sector += (VHD_BLOCK_SIZE / VHD_SECTOR_SIZE) + 1;
+ }
+ }
+ if (sparse_write(fd, bat, batsz) < 0) {
+ free(bat);
+ return (errno);
+ }
+ free(bat);
+
+ bitmap = malloc(VHD_SECTOR_SIZE);
+ if (bitmap == NULL)
+ return (errno);
+ memset(bitmap, 0xff, VHD_SECTOR_SIZE);
+
+ blk = 0;
+ blkcnt = VHD_BLOCK_SIZE / secsz;
+ error = 0;
+ nblks = rawsz / secsz;
+ while (blk < nblks) {
+ if (!image_data(blk, blkcnt)) {
+ blk += blkcnt;
+ continue;
+ }
+ if (sparse_write(fd, bitmap, VHD_SECTOR_SIZE) < 0) {
+ error = errno;
+ break;
+ }
+ /* Handle partial last block */
+ if (blk + blkcnt > nblks)
+ blkcnt = nblks - blk;
+ error = image_copyout_region(fd, blk, blkcnt);
+ if (error)
+ break;
+ blk += blkcnt;
+ }
+ free(bitmap);
+ if (error)
+ return (error);
+ error = image_copyout_zeroes(fd, imgsz - rawsz);
+ if (error)
+ return (error);
+ if (sparse_write(fd, &footer, sizeof(footer)) < 0)
+ return (errno);
+
+ return (0);
+}
+
+static struct mkimg_format vhd_dyn_format = {
+ .name = "vhd",
+ .description = "Virtual Hard Disk",
+ .resize = vhd_dyn_resize,
+ .write = vhd_dyn_write,
+};
+
+FORMAT_DEFINE(vhd_dyn_format);
+
+/*
+ * PART 3: Fixed VHD
+ */
+
+static int
+vhd_fix_resize(lba_t imgsz)
+{
+ uint64_t imagesz;
+
+ imagesz = vhd_resize(imgsz * secsz);
+ /*
+ * Azure demands that images are a whole number of megabytes.
+ */
+ imagesz = (imagesz + 0xfffffULL) & ~0xfffffULL;
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+vhd_fix_write(int fd)
+{
+ struct vhd_footer footer;
+ uint64_t imagesz;
+ int error;
+
+ error = image_copyout(fd);
+ if (error)
+ return (error);
+
+ imagesz = image_get_size() * secsz;
+ vhd_make_footer(&footer, imagesz, VHD_DISK_TYPE_FIXED, ~0ULL);
+ error = (sparse_write(fd, &footer, sizeof(footer)) < 0) ? errno : 0;
+ return (error);
+}
+
+static struct mkimg_format vhd_fix_format = {
+ .name = "vhdf",
+ .description = "Fixed Virtual Hard Disk",
+ .resize = vhd_fix_resize,
+ .write = vhd_fix_write,
+};
+
+FORMAT_DEFINE(vhd_fix_format);
diff --git a/usr.bin/mkimg/vhdx.c b/usr.bin/mkimg/vhdx.c
new file mode 100644
index 000000000000..e280250bd964
--- /dev/null
+++ b/usr.bin/mkimg/vhdx.c
@@ -0,0 +1,533 @@
+/*-
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "endian.h"
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+#define PAYLOAD_BLOCK_SIZE (16*1024*1024)
+#define SIZE_64KB (64*1024)
+#define SIZE_1MB (1024*1024)
+
+#define META_IS_REQUIRED (1 << 2)
+#define META_IS_VIRTUAL_DISK (1 << 1)
+
+#define PAYLOAD_BLOCK_FULLY_PRESENT 6
+#define SB_BLOCK_NOT_PRESENT 0
+#define BAT_ENTRY(offset, flags) (((offset) << 20) | (flags))
+
+/* Regions' UUIDs */
+#define VHDX_REGION_BAT_GUID \
+ {0x2dc27766,0xf623,0x4200,0x9d,0x64,{0x11,0x5e,0x9b,0xfd,0x4a,0x08}}
+#define VHDX_REGION_METADATA_GUID \
+ {0x8b7ca206,0x4790,0x4b9a,0xb8,0xfe,{0x57,0x5f,0x05,0x0f,0x88,0x6e}}
+static mkimg_uuid_t vhdx_bat_guid = VHDX_REGION_BAT_GUID;
+static mkimg_uuid_t vhdx_metadata_guid = VHDX_REGION_METADATA_GUID;
+
+/* Metadata UUIDs */
+#define VHDX_META_FILE_PARAMETERS \
+ {0xcaa16737,0xfa36,0x4d43,0xb3,0xb6,{0x33,0xf0,0xaa,0x44,0xe7,0x6b}}
+#define VHDX_META_VDISK_SIZE \
+ {0x2fa54224,0xcd1b,0x4876,0xb2,0x11,{0x5d,0xbe,0xd8,0x3b,0xf4,0xb8}}
+#define VHDX_META_VDISK_ID \
+ {0xbeca12ab,0xb2e6,0x4523,0x93,0xef,{0xc3,0x09,0xe0,0x00,0xc7,0x46}}
+#define VHDX_META_LOGICAL_SSIZE \
+ {0x8141bf1D,0xa96f,0x4709,0xba,0x47,{0xf2,0x33,0xa8,0xfa,0xab,0x5f}}
+#define VHDX_META_PHYS_SSIZE \
+ {0xcda348c7,0x445d,0x4471,0x9c,0xc9,{0xe9,0x88,0x52,0x51,0xc5,0x56}}
+
+static mkimg_uuid_t vhdx_meta_file_parameters_guid = VHDX_META_FILE_PARAMETERS;
+static mkimg_uuid_t vhdx_meta_vdisk_size_guid = VHDX_META_VDISK_SIZE;
+static mkimg_uuid_t vhdx_meta_vdisk_id_guid = VHDX_META_VDISK_ID;
+static mkimg_uuid_t vhdx_meta_logical_ssize_guid = VHDX_META_LOGICAL_SSIZE;
+static mkimg_uuid_t vhdx_meta_phys_ssize_guid = VHDX_META_PHYS_SSIZE;
+
+struct vhdx_filetype_identifier {
+ uint64_t signature;
+#define VHDX_FILETYPE_ID_SIGNATURE 0x656C696678646876
+ uint8_t creator[512];
+};
+
+struct vhdx_header {
+ uint32_t signature;
+#define VHDX_HEADER_SIGNATURE 0x64616568
+ uint32_t checksum;
+ uint64_t sequence_number;
+ mkimg_uuid_t file_write_guid;
+ mkimg_uuid_t data_write_guid;
+ mkimg_uuid_t log_guid;
+ uint16_t log_version;
+ uint16_t version;
+ uint32_t log_length;
+ uint64_t log_offset;
+ uint8_t _reserved[4016];
+};
+
+struct vhdx_region_table_header {
+ uint32_t signature;
+#define VHDX_REGION_TABLE_HEADER_SIGNATURE 0x69676572
+ uint32_t checksum;
+ uint32_t entry_count;
+ uint32_t _reserved;
+};
+
+struct vhdx_region_table_entry {
+ mkimg_uuid_t guid;
+ uint64_t file_offset;
+ uint32_t length;
+ uint32_t required;
+};
+
+struct vhdx_metadata_table_header {
+ uint64_t signature;
+#define VHDX_METADATA_TABLE_HEADER_SIGNATURE 0x617461646174656D
+ uint16_t _reserved;
+ uint16_t entry_count;
+ uint8_t _reserved2[20];
+};
+
+struct vhdx_metadata_table_entry {
+ mkimg_uuid_t item_id;
+ uint32_t offset;
+ uint32_t length;
+ uint32_t flags;
+ uint32_t _reserved;
+};
+
+#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
+
+static uint32_t crc_c[256] = {
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
+ 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
+ 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
+ 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
+ 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
+ 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
+ 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
+ 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
+ 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
+ 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
+ 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
+ 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
+ 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
+ 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
+ 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
+ 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
+ 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
+ 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
+ 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
+ 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
+ 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
+ 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
+ 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
+ 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
+ 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
+ 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
+ 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
+ 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
+ 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
+ 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
+ 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
+ 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
+ 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
+ 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
+ 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
+ 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
+ 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
+ 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
+ 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
+ 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
+ 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
+ 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
+ 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
+};
+
+static uint32_t
+crc32c(const void *data, uint32_t len)
+{
+ uint32_t i, crc;
+ const uint8_t *buf = (const uint8_t *)data;
+
+ crc = ~0;
+ for (i = 0; i < len; i++)
+ CRC32C(crc, buf[i]);
+ crc = ~crc;
+ return crc;
+}
+
+static int
+vhdx_resize(lba_t imgsz)
+{
+ uint64_t imagesz;
+
+ imagesz = imgsz * secsz;
+ imagesz = (imagesz + PAYLOAD_BLOCK_SIZE - 1) & ~(PAYLOAD_BLOCK_SIZE - 1);
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+vhdx_write_and_pad(int fd, const void *data, size_t data_size, size_t align)
+{
+ size_t pad_size;
+
+ if (sparse_write(fd, data, data_size) < 0)
+ return (errno);
+
+ if (data_size % align == 0)
+ return (0);
+
+ pad_size = align - (data_size % align);
+ return image_copyout_zeroes(fd, pad_size);
+}
+
+static int
+vhdx_write_headers(int fd)
+{
+ int error;
+ struct vhdx_header header;
+ uint32_t checksum;
+
+ /* Write header 1 */
+ memset(&header, 0, sizeof(header));
+ le32enc(&header.signature, VHDX_HEADER_SIGNATURE);
+ le32enc(&header.sequence_number, 0);
+ le16enc(&header.log_version, 0);
+ le16enc(&header.version, 1);
+ le32enc(&header.log_length, SIZE_1MB);
+ le64enc(&header.log_offset, SIZE_1MB);
+ checksum = crc32c(&header, sizeof(header));
+ le32enc(&header.checksum, checksum);
+ error = vhdx_write_and_pad(fd, &header, sizeof(header), SIZE_64KB);
+ if (error)
+ return (error);
+
+ /* Write header 2, and make it active */
+ le32enc(&header.sequence_number, 1);
+ header.checksum = 0;
+ checksum = crc32c(&header, sizeof(header));
+ le32enc(&header.checksum, checksum);
+ return vhdx_write_and_pad(fd, &header, sizeof(header), SIZE_64KB);
+}
+
+static int
+vhdx_write_region_tables(int fd)
+{
+ int error;
+ uint8_t *region_table;
+ struct vhdx_region_table_header header;
+ struct vhdx_region_table_entry entry;
+ uint32_t checksum;
+
+ region_table = malloc(SIZE_64KB);
+ if (region_table == NULL)
+ return errno;
+ memset(region_table, 0, SIZE_64KB);
+
+ memset(&header, 0, sizeof(header));
+ le32enc(&header.signature, VHDX_REGION_TABLE_HEADER_SIGNATURE);
+ le32enc(&header.entry_count, 2);
+ memcpy(region_table, &header, sizeof(header));
+
+ /* Metadata region entry */
+ mkimg_uuid_enc(&entry.guid, &vhdx_metadata_guid);
+ le64enc(&entry.file_offset, 2*SIZE_1MB);
+ le64enc(&entry.length, SIZE_1MB);
+ memcpy(region_table + sizeof(header),
+ &entry, sizeof(entry));
+
+ /* BAT region entry */
+ mkimg_uuid_enc(&entry.guid, &vhdx_bat_guid);
+ le64enc(&entry.file_offset, 3*SIZE_1MB);
+ le64enc(&entry.length, SIZE_1MB);
+ memcpy(region_table + sizeof(header) + sizeof(entry),
+ &entry, sizeof(entry));
+
+ checksum = crc32c(region_table, SIZE_64KB);
+ le32enc(region_table + 4, checksum);
+
+ /* Region Table 1 */
+ if (sparse_write(fd, region_table, SIZE_64KB) < 0) {
+ error = errno;
+ free(region_table);
+ return error;
+ }
+
+ /* Region Table 2 */
+ if (sparse_write(fd, region_table, SIZE_64KB) < 0) {
+ error = errno;
+ free(region_table);
+ return error;
+ }
+
+ free(region_table);
+ return (0);
+}
+
+static int
+vhdx_write_metadata(int fd, uint64_t image_size)
+{
+ int error;
+ uint8_t *metadata;
+ struct vhdx_metadata_table_header header;
+ struct vhdx_metadata_table_entry entry;
+ int header_ptr, data_ptr;
+ mkimg_uuid_t id;
+
+ metadata = malloc(SIZE_1MB);
+ if (metadata == NULL)
+ return errno;
+ memset(metadata, 0, SIZE_1MB);
+
+ memset(&header, 0, sizeof(header));
+ memset(&entry, 0, sizeof(entry));
+
+ le64enc(&header.signature, VHDX_METADATA_TABLE_HEADER_SIGNATURE);
+ le16enc(&header.entry_count, 5);
+ memcpy(metadata, &header, sizeof(header));
+ header_ptr = sizeof(header);
+ data_ptr = SIZE_64KB;
+
+ /* File parameters */
+ mkimg_uuid_enc(&entry.item_id, &vhdx_meta_file_parameters_guid);
+ le32enc(&entry.offset, data_ptr);
+ le32enc(&entry.length, 8);
+ le32enc(&entry.flags, META_IS_REQUIRED);
+ memcpy(metadata + header_ptr, &entry, sizeof(entry));
+ header_ptr += sizeof(entry);
+ le32enc(metadata + data_ptr, PAYLOAD_BLOCK_SIZE);
+ data_ptr += 4;
+ le32enc(metadata + data_ptr, 0);
+ data_ptr += 4;
+
+ /* Virtual Disk Size */
+ mkimg_uuid_enc(&entry.item_id, &vhdx_meta_vdisk_size_guid);
+ le32enc(&entry.offset, data_ptr);
+ le32enc(&entry.length, 8);
+ le32enc(&entry.flags, META_IS_REQUIRED | META_IS_VIRTUAL_DISK);
+ memcpy(metadata + header_ptr, &entry, sizeof(entry));
+ header_ptr += sizeof(entry);
+ le64enc(metadata + data_ptr, image_size);
+ data_ptr += 8;
+
+ /* Virtual Disk ID */
+ mkimg_uuid_enc(&entry.item_id, &vhdx_meta_vdisk_id_guid);
+ le32enc(&entry.offset, data_ptr);
+ le32enc(&entry.length, 16);
+ le32enc(&entry.flags, META_IS_REQUIRED | META_IS_VIRTUAL_DISK);
+ memcpy(metadata + header_ptr, &entry, sizeof(entry));
+ header_ptr += sizeof(entry);
+ mkimg_uuid(&id);
+ mkimg_uuid_enc(metadata + data_ptr, &id);
+ data_ptr += 16;
+
+ /* Logical Sector Size*/
+ mkimg_uuid_enc(&entry.item_id, &vhdx_meta_logical_ssize_guid);
+ le32enc(&entry.offset, data_ptr);
+ le32enc(&entry.length, 4);
+ le32enc(&entry.flags, META_IS_REQUIRED | META_IS_VIRTUAL_DISK);
+ memcpy(metadata + header_ptr, &entry, sizeof(entry));
+ header_ptr += sizeof(entry);
+ le32enc(metadata + data_ptr, secsz);
+ data_ptr += 4;
+
+ /* Physical Sector Size*/
+ mkimg_uuid_enc(&entry.item_id, &vhdx_meta_phys_ssize_guid);
+ le32enc(&entry.offset, data_ptr);
+ le32enc(&entry.length, 4);
+ le32enc(&entry.flags, META_IS_REQUIRED | META_IS_VIRTUAL_DISK);
+ memcpy(metadata + header_ptr, &entry, sizeof(entry));
+ header_ptr += sizeof(entry);
+ le32enc(metadata + data_ptr, blksz);
+ data_ptr += 4;
+
+ if (sparse_write(fd, metadata, SIZE_1MB) < 0) {
+ error = errno;
+ free(metadata);
+ return error;
+ }
+
+ free(metadata);
+ return (0);
+}
+
+static int
+vhdx_write_bat(int fd, uint64_t image_size)
+{
+ int error;
+ uint8_t *bat;
+ int chunk_ratio;
+ uint64_t bat_size, data_block_count, total_bat_entries;
+ uint64_t idx, payload_offset, bat_ptr;
+
+ bat = malloc(SIZE_1MB);
+ if (bat == NULL)
+ return errno;
+ memset(bat, 0, SIZE_1MB);
+
+ chunk_ratio = ((1024*1024*8ULL) * secsz) / PAYLOAD_BLOCK_SIZE;
+ data_block_count = (image_size + PAYLOAD_BLOCK_SIZE - 1) / PAYLOAD_BLOCK_SIZE;
+ total_bat_entries = data_block_count + (data_block_count - 1)/chunk_ratio;
+ bat_size = total_bat_entries * 8;
+ /* round it up to 1Mb */
+ bat_size = (bat_size + SIZE_1MB - 1) & ~(SIZE_1MB - 1);
+
+ /*
+ * Offset to the first payload block
+ * 1Mb of header + 1Mb of log + 1Mb of metadata + XMb BAT
+ */
+ payload_offset = 3 + (bat_size / SIZE_1MB);
+ bat_ptr = 0;
+ for (idx = 0; idx < data_block_count; idx++) {
+ le64enc(bat + bat_ptr,
+ BAT_ENTRY(payload_offset, PAYLOAD_BLOCK_FULLY_PRESENT));
+ bat_ptr += 8;
+ payload_offset += (PAYLOAD_BLOCK_SIZE / SIZE_1MB);
+
+ /* Flush the BAT buffer if required */
+ if (bat_ptr == SIZE_1MB) {
+ if (sparse_write(fd, bat, SIZE_1MB) < 0) {
+ error = errno;
+ free(bat);
+ return error;
+ }
+ memset(bat, 0, SIZE_1MB);
+ bat_ptr = 0;
+ }
+
+ if (((idx + 1) % chunk_ratio) == 0 &&
+ (idx != data_block_count - 1)) {
+ le64enc(bat + bat_ptr,
+ BAT_ENTRY(0, SB_BLOCK_NOT_PRESENT));
+ bat_ptr += 8;
+
+ /* Flush the BAT buffer if required */
+ if (bat_ptr == SIZE_1MB) {
+ if (sparse_write(fd, bat, SIZE_1MB) < 0) {
+ error = errno;
+ free(bat);
+ return error;
+ }
+ memset(bat, 0, SIZE_1MB);
+ bat_ptr = 0;
+ }
+ }
+ }
+
+ if (bat_ptr != 0) {
+ if (sparse_write(fd, bat, SIZE_1MB) < 0) {
+ error = errno;
+ free(bat);
+ return error;
+ }
+ }
+
+ free(bat);
+ return (0);
+}
+
+static int
+vhdx_write(int fd)
+{
+ int error;
+ uint64_t imgsz, rawsz;
+ struct vhdx_filetype_identifier identifier;
+
+ rawsz = image_get_size() * secsz;
+ imgsz = (rawsz + PAYLOAD_BLOCK_SIZE - 1) & ~(PAYLOAD_BLOCK_SIZE - 1);
+
+ memset(&identifier, 0, sizeof(identifier));
+ le64enc(&identifier.signature, VHDX_FILETYPE_ID_SIGNATURE);
+ error = vhdx_write_and_pad(fd, &identifier, sizeof(identifier), SIZE_64KB);
+ if (error)
+ return (error);
+
+ error = vhdx_write_headers(fd);
+ if (error)
+ return (error);
+
+
+ error = vhdx_write_region_tables(fd);
+ if (error)
+ return (error);
+
+ /* Reserved area */
+ error = image_copyout_zeroes(fd, SIZE_1MB - 5*SIZE_64KB);
+
+ /* Log */
+ error = image_copyout_zeroes(fd, SIZE_1MB);
+ if (error)
+ return (error);
+
+ error = vhdx_write_metadata(fd, imgsz);
+ if (error)
+ return (error);
+
+ error = vhdx_write_bat(fd, imgsz);
+ if (error)
+ return (error);
+
+ error = image_copyout(fd);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static struct mkimg_format vhdx_format = {
+ .name = "vhdx",
+ .description = "Virtual Hard Disk, version 2",
+ .resize = vhdx_resize,
+ .write = vhdx_write,
+};
+
+FORMAT_DEFINE(vhdx_format);
diff --git a/usr.bin/mkimg/vmdk.c b/usr.bin/mkimg/vmdk.c
new file mode 100644
index 000000000000..132eb801387a
--- /dev/null
+++ b/usr.bin/mkimg/vmdk.c
@@ -0,0 +1,257 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "endian.h"
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+#define VMDK_IMAGE_ROUND 1048576
+#define VMDK_MIN_GRAIN_SIZE 8192
+#define VMDK_SECTOR_SIZE 512
+
+struct vmdk_header {
+ uint32_t magic;
+#define VMDK_MAGIC 0x564d444b
+ uint32_t version;
+#define VMDK_VERSION 1
+ uint32_t flags;
+#define VMDK_FLAGS_NL_TEST (1 << 0)
+#define VMDK_FLAGS_RGT_USED (1 << 1)
+#define VMDK_FLAGS_COMPRESSED (1 << 16)
+#define VMDK_FLAGS_MARKERS (1 << 17)
+ uint64_t capacity;
+ uint64_t grain_size;
+ uint64_t desc_offset;
+ uint64_t desc_size;
+ uint32_t ngtes;
+#define VMDK_NGTES 512
+ uint64_t rgd_offset;
+ uint64_t gd_offset;
+ uint64_t overhead;
+ uint8_t unclean;
+ uint32_t nl_test;
+#define VMDK_NL_TEST 0x0a200d0a
+ uint16_t compress;
+#define VMDK_COMPRESS_NONE 0
+#define VMDK_COMPRESS_DEFLATE 1
+ char padding[433];
+} __attribute__((__packed__));
+
+static const char desc_fmt[] =
+ "# Disk DescriptorFile\n"
+ "version=%d\n"
+ "CID=%08x\n"
+ "parentCID=ffffffff\n"
+ "createType=\"monolithicSparse\"\n"
+ "# Extent description\n"
+ "RW %ju SPARSE \"%s\"\n"
+ "# The Disk Data Base\n"
+ "#DDB\n"
+ "ddb.adapterType = \"ide\"\n"
+ "ddb.geometry.cylinders = \"%u\"\n"
+ "ddb.geometry.heads = \"%u\"\n"
+ "ddb.geometry.sectors = \"%u\"\n";
+
+static uint64_t grainsz;
+
+static int
+vmdk_resize(lba_t imgsz)
+{
+ uint64_t imagesz;
+
+ imagesz = imgsz * secsz;
+ imagesz = (imagesz + VMDK_IMAGE_ROUND - 1) & ~(VMDK_IMAGE_ROUND - 1);
+ grainsz = (blksz < VMDK_MIN_GRAIN_SIZE) ? VMDK_MIN_GRAIN_SIZE : blksz;
+
+ if (verbose)
+ fprintf(stderr, "VMDK: image size = %ju, grain size = %ju\n",
+ (uintmax_t)imagesz, (uintmax_t)grainsz);
+
+ grainsz /= VMDK_SECTOR_SIZE;
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+vmdk_write(int fd)
+{
+ struct vmdk_header hdr;
+ uint32_t *gt, *gd, *rgd;
+ char *buf, *desc;
+ off_t cur, lim;
+ uint64_t imagesz;
+ lba_t blkofs, blkcnt;
+ size_t gdsz, gtsz;
+ uint32_t sec, cursec;
+ int error, desc_len, n, ngrains, ngts;
+
+ imagesz = (image_get_size() * secsz) / VMDK_SECTOR_SIZE;
+
+ memset(&hdr, 0, sizeof(hdr));
+ le32enc(&hdr.magic, VMDK_MAGIC);
+ le32enc(&hdr.version, VMDK_VERSION);
+ le32enc(&hdr.flags, VMDK_FLAGS_NL_TEST | VMDK_FLAGS_RGT_USED);
+ le64enc(&hdr.capacity, imagesz);
+ le64enc(&hdr.grain_size, grainsz);
+
+ n = asprintf(&desc, desc_fmt, 1 /*version*/, 0 /*CID*/,
+ (uintmax_t)imagesz /*size*/, "" /*name*/,
+ ncyls /*cylinders*/, nheads /*heads*/, nsecs /*sectors*/);
+ if (n == -1)
+ return (ENOMEM);
+
+ desc_len = (n + VMDK_SECTOR_SIZE - 1) & ~(VMDK_SECTOR_SIZE - 1);
+ desc = realloc(desc, desc_len);
+ memset(desc + n, 0, desc_len - n);
+
+ le64enc(&hdr.desc_offset, 1);
+ le64enc(&hdr.desc_size, desc_len / VMDK_SECTOR_SIZE);
+ le32enc(&hdr.ngtes, VMDK_NGTES);
+
+ sec = desc_len / VMDK_SECTOR_SIZE + 1;
+
+ ngrains = imagesz / grainsz;
+ ngts = (ngrains + VMDK_NGTES - 1) / VMDK_NGTES;
+ gdsz = (ngts * sizeof(uint32_t) + VMDK_SECTOR_SIZE - 1) &
+ ~(VMDK_SECTOR_SIZE - 1);
+
+ gd = calloc(1, gdsz);
+ if (gd == NULL) {
+ free(desc);
+ return (ENOMEM);
+ }
+ le64enc(&hdr.gd_offset, sec);
+ sec += gdsz / VMDK_SECTOR_SIZE;
+ for (n = 0; n < ngts; n++) {
+ le32enc(gd + n, sec);
+ sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE;
+ }
+
+ rgd = calloc(1, gdsz);
+ if (rgd == NULL) {
+ free(gd);
+ free(desc);
+ return (ENOMEM);
+ }
+ le64enc(&hdr.rgd_offset, sec);
+ sec += gdsz / VMDK_SECTOR_SIZE;
+ for (n = 0; n < ngts; n++) {
+ le32enc(rgd + n, sec);
+ sec += VMDK_NGTES * sizeof(uint32_t) / VMDK_SECTOR_SIZE;
+ }
+
+ sec = (sec + grainsz - 1) & ~(grainsz - 1);
+
+ if (verbose)
+ fprintf(stderr, "VMDK: overhead = %ju\n",
+ (uintmax_t)(sec * VMDK_SECTOR_SIZE));
+
+ le64enc(&hdr.overhead, sec);
+ be32enc(&hdr.nl_test, VMDK_NL_TEST);
+
+ gt = calloc(ngts, VMDK_NGTES * sizeof(uint32_t));
+ if (gt == NULL) {
+ free(rgd);
+ free(gd);
+ free(desc);
+ return (ENOMEM);
+ }
+ gtsz = ngts * VMDK_NGTES * sizeof(uint32_t);
+
+ cursec = sec;
+ blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz;
+ for (n = 0; n < ngrains; n++) {
+ blkofs = n * blkcnt;
+ if (image_data(blkofs, blkcnt)) {
+ le32enc(gt + n, cursec);
+ cursec += grainsz;
+ }
+ }
+
+ error = 0;
+ if (!error && sparse_write(fd, &hdr, VMDK_SECTOR_SIZE) < 0)
+ error = errno;
+ if (!error && sparse_write(fd, desc, desc_len) < 0)
+ error = errno;
+ if (!error && sparse_write(fd, gd, gdsz) < 0)
+ error = errno;
+ if (!error && sparse_write(fd, gt, gtsz) < 0)
+ error = errno;
+ if (!error && sparse_write(fd, rgd, gdsz) < 0)
+ error = errno;
+ if (!error && sparse_write(fd, gt, gtsz) < 0)
+ error = errno;
+ free(gt);
+ free(rgd);
+ free(gd);
+ free(desc);
+ if (error)
+ return (error);
+
+ cur = VMDK_SECTOR_SIZE + desc_len + (gdsz + gtsz) * 2;
+ lim = sec * VMDK_SECTOR_SIZE;
+ if (cur < lim) {
+ buf = calloc(1, VMDK_SECTOR_SIZE);
+ if (buf == NULL)
+ error = ENOMEM;
+ while (!error && cur < lim) {
+ if (sparse_write(fd, buf, VMDK_SECTOR_SIZE) < 0)
+ error = errno;
+ cur += VMDK_SECTOR_SIZE;
+ }
+ if (buf != NULL)
+ free(buf);
+ }
+ if (error)
+ return (error);
+
+ blkcnt = (grainsz * VMDK_SECTOR_SIZE) / secsz;
+ for (n = 0; n < ngrains; n++) {
+ blkofs = n * blkcnt;
+ if (image_data(blkofs, blkcnt)) {
+ error = image_copyout_region(fd, blkofs, blkcnt);
+ if (error)
+ return (error);
+ }
+ }
+ return (image_copyout_done(fd));
+}
+
+static struct mkimg_format vmdk_format = {
+ .name = "vmdk",
+ .description = "Virtual Machine Disk",
+ .resize = vmdk_resize,
+ .write = vmdk_write,
+};
+
+FORMAT_DEFINE(vmdk_format);
diff --git a/usr.bin/mkstr/Makefile b/usr.bin/mkstr/Makefile
new file mode 100644
index 000000000000..1a691e6d78d5
--- /dev/null
+++ b/usr.bin/mkstr/Makefile
@@ -0,0 +1,5 @@
+PROG= mkstr
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkstr/Makefile.depend b/usr.bin/mkstr/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/mkstr/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkstr/mkstr.1 b/usr.bin/mkstr/mkstr.1
new file mode 100644
index 000000000000..e0203b1040af
--- /dev/null
+++ b/usr.bin/mkstr/mkstr.1
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd June 6, 2015
+.Dt MKSTR 1
+.Os
+.Sh NAME
+.Nm mkstr
+.Nd create an error message file by massaging C source
+.Sh SYNOPSIS
+.Nm
+.Op Fl
+.Ar mesgfile
+.Ar prefix Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility creates a file containing error messages extracted from C source,
+and restructures the same C source, to utilize the created error message
+file.
+The intent of
+.Nm
+was to reduce the size of large programs and
+reduce swapping (see
+.Sx BUGS
+section below).
+.Pp
+The
+.Nm
+utility processes each of the specified files,
+placing a restructured version of the input in a file whose name
+consists of the specified
+.Ar prefix
+and the original name.
+A typical usage of
+.Nm
+is
+.Pp
+.Dl "mkstr pistrings xx *.c"
+.Pp
+This command causes all the error messages from the C source
+files in the current directory to be placed in the file
+.Pa pistrings
+and restructured copies of the sources to be placed in
+files whose names are prefixed with
+.Dq Li xx .
+.Pp
+Options:
+.Bl -tag -width indent
+.It Fl
+Error messages are placed at the end of the specified
+message file for recompiling part of a large
+.Nm Ns ed
+program.
+.El
+.Pp
+The
+.Nm
+utility finds error messages in the source by
+searching for the string
+.Sq Li error("
+in the input stream.
+Each time it occurs, the C string starting at the
+.Ql \&"
+is stored
+in the message file followed by a null character and a new-line character;
+The new source is restructured with
+.Xr lseek 2
+pointers into the error message file for retrieval.
+.Bd -literal -offset indent
+char efilname = "/usr/lib/pi_strings";
+int efil = -1;
+
+error(a1, a2, a3, a4)
+{
+ char buf[256];
+
+ if (efil < 0) {
+ efil = open(efilname, 0);
+ if (efil < 0)
+ err(1, "%s", efilname);
+ }
+ if (lseek(efil, (off_t)a1, SEEK_SET) < 0 ||
+ read(efil, buf, 256) <= 0)
+ err(1, "%s", efilname);
+ printf(buf, a2, a3, a4);
+}
+.Ed
+.Sh SEE ALSO
+.Xr gencat 1 ,
+.Xr xstr 1 ,
+.Xr lseek 2
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 1 .
+.Sh AUTHORS
+.An -nosplit
+.An Bill Joy
+and
+.An Chuck Haley ,
+1977.
+.Sh BUGS
+The
+.Nm
+utility was intended for the limited architecture of the PDP 11 family.
+Very few programs actually use it.
+The memory savings are negligible in modern computers.
diff --git a/usr.bin/mkstr/mkstr.c b/usr.bin/mkstr/mkstr.c
new file mode 100644
index 000000000000..43ddd5fb5574
--- /dev/null
+++ b/usr.bin/mkstr/mkstr.c
@@ -0,0 +1,320 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ungetchar(c) ungetc(c, stdin)
+
+/*
+ * mkstr - create a string error message file by massaging C source
+ *
+ * Bill Joy UCB August 1977
+ *
+ * Modified March 1978 to hash old messages to be able to recompile
+ * without addding messages to the message file (usually)
+ *
+ * Based on an earlier program conceived by Bill Joy and Chuck Haley
+ *
+ * Program to create a string error message file
+ * from a group of C programs. Arguments are the name
+ * of the file where the strings are to be placed, the
+ * prefix of the new files where the processed source text
+ * is to be placed, and the files to be processed.
+ *
+ * The program looks for 'error("' in the source stream.
+ * Whenever it finds this, the following characters from the '"'
+ * to a '"' are replaced by 'seekpt' where seekpt is a
+ * pointer into the error message file.
+ * If the '(' is not immediately followed by a '"' no change occurs.
+ *
+ * The optional '-' causes strings to be added at the end of the
+ * existing error message file for recompilation of single routines.
+ */
+
+static FILE *mesgread, *mesgwrite;
+static char name[100], *np;
+
+void copystr(void);
+int fgetNUL(char *, int, FILE *);
+unsigned hashit(char *, int, unsigned);
+void inithash(void);
+int match(const char *);
+int octdigit(char);
+void process(void);
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ char addon = 0;
+ size_t namelen;
+
+ argc--, argv++;
+ if (argc > 1 && argv[0][0] == '-')
+ addon++, argc--, argv++;
+ if (argc < 3)
+ usage();
+ mesgwrite = fopen(argv[0], addon ? "a" : "w");
+ if (mesgwrite == NULL)
+ err(1, "%s", argv[0]);
+ mesgread = fopen(argv[0], "r");
+ if (mesgread == NULL)
+ err(1, "%s", argv[0]);
+ inithash();
+ argc--, argv++;
+ namelen = strlcpy(name, argv[0], sizeof(name));
+ if (namelen >= sizeof(name)) {
+ errno = ENAMETOOLONG;
+ err(1, "%s", argv[0]);
+ }
+ np = name + namelen;
+ argc--, argv++;
+ do {
+ if (strlcpy(np, argv[0], sizeof(name) - namelen) >=
+ sizeof(name) - namelen) {
+ errno = ENAMETOOLONG;
+ err(1, "%s%s", name, argv[0]);
+ }
+ if (freopen(name, "w", stdout) == NULL)
+ err(1, "%s", name);
+ if (freopen(argv[0], "r", stdin) == NULL)
+ err(1, "%s", argv[0]);
+ process();
+ argc--, argv++;
+ } while (argc > 0);
+ exit(0);
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: mkstr [-] mesgfile prefix file ...\n");
+ exit(1);
+}
+
+void
+process(void)
+{
+ int c;
+
+ for (;;) {
+ c = getchar();
+ if (c == EOF)
+ return;
+ if (c != 'e') {
+ putchar(c);
+ continue;
+ }
+ if (match("error(")) {
+ printf("error(");
+ c = getchar();
+ if (c != '"')
+ putchar(c);
+ else
+ copystr();
+ }
+ }
+}
+
+int
+match(const char *ocp)
+{
+ const char *cp;
+ int c;
+
+ for (cp = ocp + 1; *cp; cp++) {
+ c = getchar();
+ if (c != *cp) {
+ while (ocp < cp)
+ putchar(*ocp++);
+ ungetchar(c);
+ return (0);
+ }
+ }
+ return (1);
+}
+
+void
+copystr(void)
+{
+ int c, ch;
+ char buf[512];
+ char *cp = buf;
+
+ for (;;) {
+ if (cp == buf + sizeof(buf) - 2)
+ errx(1, "message too long");
+ c = getchar();
+ if (c == EOF)
+ break;
+ switch (c) {
+
+ case '"':
+ *cp++ = 0;
+ goto out;
+ case '\\':
+ c = getchar();
+ switch (c) {
+
+ case 'b':
+ c = '\b';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case '\n':
+ continue;
+ case 'f':
+ c = '\f';
+ break;
+ case '0':
+ c = 0;
+ break;
+ case '\\':
+ break;
+ default:
+ if (!octdigit(c))
+ break;
+ c -= '0';
+ ch = getchar();
+ if (!octdigit(ch))
+ break;
+ c <<= 7, c += ch - '0';
+ ch = getchar();
+ if (!octdigit(ch))
+ break;
+ c <<= 3, c+= ch - '0', ch = -1;
+ break;
+ }
+ }
+ *cp++ = c;
+ }
+out:
+ *cp = 0;
+ printf("%d", hashit(buf, 1, 0));
+}
+
+int
+octdigit(char c)
+{
+
+ return (c >= '0' && c <= '7');
+}
+
+void
+inithash(void)
+{
+ char buf[512];
+ int mesgpt = 0;
+
+ rewind(mesgread);
+ while (fgetNUL(buf, sizeof buf, mesgread) != 0) {
+ hashit(buf, 0, mesgpt);
+ mesgpt += strlen(buf) + 2;
+ }
+}
+
+#define NBUCKETS 511
+
+static struct hash {
+ long hval;
+ unsigned hpt;
+ struct hash *hnext;
+} *bucket[NBUCKETS];
+
+unsigned
+hashit(char *str, int really, unsigned fakept)
+{
+ int i;
+ struct hash *hp;
+ char buf[512];
+ long hashval = 0;
+ char *cp;
+
+ if (really)
+ fflush(mesgwrite);
+ for (cp = str; *cp;)
+ hashval = (hashval << 1) + *cp++;
+ i = hashval % NBUCKETS;
+ if (i < 0)
+ i += NBUCKETS;
+ if (really != 0)
+ for (hp = bucket[i]; hp != 0; hp = hp->hnext)
+ if (hp->hval == hashval) {
+ fseek(mesgread, (long) hp->hpt, 0);
+ fgetNUL(buf, sizeof buf, mesgread);
+/*
+ fprintf(stderr, "Got (from %d) %s\n", hp->hpt, buf);
+*/
+ if (strcmp(buf, str) == 0)
+ break;
+ }
+ if (!really || hp == 0) {
+ hp = (struct hash *) calloc(1, sizeof *hp);
+ if (hp == NULL)
+ err(1, NULL);
+ hp->hnext = bucket[i];
+ hp->hval = hashval;
+ hp->hpt = really ? ftell(mesgwrite) : fakept;
+ if (really) {
+ fwrite(str, sizeof (char), strlen(str) + 1, mesgwrite);
+ fwrite("\n", sizeof (char), 1, mesgwrite);
+ }
+ bucket[i] = hp;
+ }
+/*
+ fprintf(stderr, "%s hashed to %ld at %d\n", str, hp->hval, hp->hpt);
+*/
+ return (hp->hpt);
+}
+
+int
+fgetNUL(char *obuf, int rmdr, FILE *file)
+{
+ int c;
+ char *buf = obuf;
+
+ while (--rmdr > 0 && (c = getc(file)) != 0 && c != EOF)
+ *buf++ = c;
+ *buf++ = 0;
+ getc(file);
+ return ((feof(file) || ferror(file)) ? 0 : 1);
+}
diff --git a/usr.bin/mktemp/Makefile b/usr.bin/mktemp/Makefile
new file mode 100644
index 000000000000..2da8049b28f7
--- /dev/null
+++ b/usr.bin/mktemp/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= mktemp
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mktemp/Makefile.depend b/usr.bin/mktemp/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/mktemp/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mktemp/mktemp.1 b/usr.bin/mktemp/mktemp.1
new file mode 100644
index 000000000000..063f25f216dc
--- /dev/null
+++ b/usr.bin/mktemp/mktemp.1
@@ -0,0 +1,235 @@
+.\" 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.
+.\"
+.\" From: $OpenBSD: mktemp.1,v 1.8 1998/03/19 06:13:37 millert Exp $
+.\"
+.Dd August 4, 2022
+.Dt MKTEMP 1
+.Os
+.Sh NAME
+.Nm mktemp
+.Nd make temporary file name (unique)
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl p Ar tmpdir
+.Op Fl q
+.Op Fl t Ar prefix
+.Op Fl u
+.Ar template ...
+.Nm
+.Op Fl d
+.Op Fl p Ar tmpdir
+.Op Fl q
+.Op Fl u
+.Fl t Ar prefix
+.Sh DESCRIPTION
+The
+.Nm
+utility takes each of the given file name templates and overwrites a
+portion of it to create a file name.
+This file name is unique
+and suitable for use by the application.
+The template may be
+any file name with some number of
+.Ql X Ns s
+appended
+to it, for example
+.Pa /tmp/temp.XXXXXXXXXX .
+The trailing
+.Ql X Ns s
+are replaced with the current process number and/or a
+unique letter combination.
+The number of unique file names
+.Nm
+can return depends on the number of
+.Ql X Ns s
+provided; six
+.Ql X Ns s
+will
+result in
+.Nm
+selecting 1 of 56800235584 (62 ** 6) possible file names.
+.Pp
+If
+.Nm
+can successfully generate a unique file name, the file
+is created with mode 0600 (unless the
+.Fl u
+flag is given) and the filename is printed
+to standard output.
+.Pp
+If the
+.Fl t Ar prefix
+option is given,
+.Nm
+will generate a template string based on the
+.Ar prefix
+and the
+.Ev TMPDIR
+environment variable if set.
+If the
+.Fl p
+option is set, then the given
+.Ar tmpdir
+will be used if the
+.Ev TMPDIR
+environment variable is not set.
+Finally,
+.Pa /tmp
+will be used if neither
+.Ev TMPDIR
+or
+.Fl p
+are set and used.
+Care should
+be taken to ensure that it is appropriate to use an environment variable
+potentially supplied by the user.
+.Pp
+If no arguments are passed or if only the
+.Fl d
+flag is passed
+.Nm
+behaves as if
+.Fl t Li tmp
+was supplied.
+.Pp
+Any number of temporary files may be created in a single invocation,
+including one based on the internal template resulting from the
+.Fl t
+flag.
+.Pp
+The
+.Nm
+utility is provided to allow shell scripts to safely use temporary files.
+Traditionally, many shell scripts take the name of the program with
+the pid as a suffix and use that as a temporary file name.
+This
+kind of naming scheme is predictable and the race condition it creates
+is easy for an attacker to win.
+A safer, though still inferior, approach
+is to make a temporary directory using the same naming scheme.
+While
+this does allow one to guarantee that a temporary file will not be
+subverted, it still allows a simple denial of service attack.
+For these
+reasons it is suggested that
+.Nm
+be used instead.
+.Sh OPTIONS
+The available options are as follows:
+.Bl -tag -width indent
+.It Fl d , Fl -directory
+Make a directory instead of a file.
+.It Fl p Ar tmpdir , Fl -tmpdir Ns Oo = Ns Ar tmpdir Oc
+Use
+.Ar tmpdir
+for the
+.Fl t
+flag if the
+.Ev TMPDIR
+environment variable is not set.
+Additionally, any provided
+.Ar template
+arguments will be interpreted relative to the path specified as
+.Ar tmpdir .
+If
+.Ar tmpdir
+is either empty or omitted, then the
+.Ev TMPDIR
+environment variable will be used.
+.It Fl q , Fl -quiet
+Fail silently if an error occurs.
+This is useful if
+a script does not want error output to go to standard error.
+.It Fl t Ar prefix
+Generate a template (using the supplied
+.Ar prefix
+and
+.Ev TMPDIR
+if set) to create a filename template.
+.It Fl u , Fl -dry-run
+Operate in
+.Dq unsafe
+mode.
+The temp file will be unlinked before
+.Nm
+exits.
+This is slightly better than
+.Xr mktemp 3
+but still introduces a race condition.
+Use of this
+option is not encouraged.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The following
+.Xr sh 1
+fragment illustrates a simple use of
+.Nm
+where the script should quit if it cannot get a safe
+temporary file.
+.Bd -literal -offset indent
+tempfoo=`basename $0`
+TMPFILE=`mktemp /tmp/${tempfoo}.XXXXXXXXXX` || exit 1
+echo "program output" >> $TMPFILE
+.Ed
+.Pp
+To allow the use of $TMPDIR:
+.Bd -literal -offset indent
+tempfoo=`basename $0`
+TMPFILE=`mktemp -t ${tempfoo}` || exit 1
+echo "program output" >> $TMPFILE
+.Ed
+.Pp
+In this case, we want the script to catch the error itself.
+.Bd -literal -offset indent
+tempfoo=`basename $0`
+TMPFILE=`mktemp -q /tmp/${tempfoo}.XXXXXXXXXX`
+if [ $? -ne 0 ]; then
+ echo "$0: Can't create temp file, exiting..."
+ exit 1
+fi
+.Ed
+.Sh SEE ALSO
+.Xr mkdtemp 3 ,
+.Xr mkstemp 3 ,
+.Xr mktemp 3 ,
+.Xr environ 7
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.Ox 2.1 .
+This implementation was written independently based on the
+.Ox
+man page, and
+first appeared in
+.Fx 2.2.7 .
+This man page is taken from
+.Ox .
diff --git a/usr.bin/mktemp/mktemp.c b/usr.bin/mktemp/mktemp.c
new file mode 100644
index 000000000000..3be86bf21a02
--- /dev/null
+++ b/usr.bin/mktemp/mktemp.c
@@ -0,0 +1,203 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1994, 1995, 1996, 1998 Peter Wemm <peter@netplex.com.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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 was originally written long ago, originally for a non
+ * BSD-like OS without mkstemp(). It's been modified over the years
+ * to use mkstemp() rather than the original O_CREAT|O_EXCL/fstat/lstat
+ * etc style hacks.
+ * A cleanup, misc options and mkdtemp() calls were added to try and work
+ * more like the OpenBSD version - which was first to publish the interface.
+ */
+
+#include <err.h>
+#include <getopt.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void usage(void) __dead2;
+
+static const struct option long_opts[] = {
+ {"directory", no_argument, NULL, 'd'},
+ {"tmpdir", optional_argument, NULL, 'p'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"dry-run", no_argument, NULL, 'u'},
+ {NULL, no_argument, NULL, 0},
+};
+
+int
+main(int argc, char **argv)
+{
+ int c, fd, ret;
+ const char *prefix, *tmpdir;
+ char *name;
+ int dflag, qflag, tflag, uflag;
+ bool prefer_tmpdir;
+
+ ret = dflag = qflag = tflag = uflag = 0;
+ prefer_tmpdir = true;
+ prefix = "mktemp";
+ name = NULL;
+ tmpdir = NULL;
+
+ while ((c = getopt_long(argc, argv, "dp:qt:u", long_opts, NULL)) != -1)
+ switch (c) {
+ case 'd':
+ dflag++;
+ break;
+
+ case 'p':
+ tmpdir = optarg;
+ if (tmpdir == NULL || *tmpdir == '\0')
+ tmpdir = getenv("TMPDIR");
+
+ /*
+ * We've already done the necessary environment
+ * fallback, skip the later one.
+ */
+ prefer_tmpdir = false;
+ break;
+
+ case 'q':
+ qflag++;
+ break;
+
+ case 't':
+ prefix = optarg;
+ tflag++;
+ break;
+
+ case 'u':
+ uflag++;
+ break;
+
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!tflag && argc < 1) {
+ tflag = 1;
+ prefix = "tmp";
+
+ /*
+ * For this implied -t mode, we actually want to swap the usual
+ * order of precedence: -p, then TMPDIR, then /tmp.
+ */
+ prefer_tmpdir = false;
+ }
+
+ if (tflag) {
+ const char *envtmp;
+ size_t len;
+
+ envtmp = NULL;
+
+ /*
+ * $TMPDIR preferred over `-p` if specified, for compatibility.
+ */
+ if (prefer_tmpdir || tmpdir == NULL)
+ envtmp = getenv("TMPDIR");
+ if (envtmp != NULL)
+ tmpdir = envtmp;
+ if (tmpdir == NULL)
+ tmpdir = _PATH_TMP;
+ len = strlen(tmpdir);
+ if (len > 0 && tmpdir[len - 1] == '/')
+ asprintf(&name, "%s%s.XXXXXXXXXX", tmpdir, prefix);
+ else
+ asprintf(&name, "%s/%s.XXXXXXXXXX", tmpdir, prefix);
+ /* if this fails, the program is in big trouble already */
+ if (name == NULL) {
+ if (qflag)
+ return (1);
+ else
+ errx(1, "cannot generate template");
+ }
+ }
+
+ /* generate all requested files */
+ while (name != NULL || argc > 0) {
+ if (name == NULL) {
+ if (!tflag && tmpdir != NULL)
+ asprintf(&name, "%s/%s", tmpdir, argv[0]);
+ else
+ name = strdup(argv[0]);
+ if (name == NULL)
+ err(1, "%s", argv[0]);
+ argv++;
+ argc--;
+ }
+
+ if (dflag) {
+ if (mkdtemp(name) == NULL) {
+ ret = 1;
+ if (!qflag)
+ warn("mkdtemp failed on %s", name);
+ } else {
+ printf("%s\n", name);
+ if (uflag)
+ rmdir(name);
+ }
+ } else {
+ fd = mkstemp(name);
+ if (fd < 0) {
+ ret = 1;
+ if (!qflag)
+ warn("mkstemp failed on %s", name);
+ } else {
+ close(fd);
+ if (uflag)
+ unlink(name);
+ printf("%s\n", name);
+ }
+ }
+ if (name)
+ free(name);
+ name = NULL;
+ }
+ return (ret);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: mktemp [-d] [-p tmpdir] [-q] [-t prefix] [-u] template "
+ "...\n");
+ fprintf(stderr,
+ " mktemp [-d] [-p tmpdir] [-q] [-u] -t prefix \n");
+ exit (1);
+}
diff --git a/usr.bin/mktemp/tests/Makefile b/usr.bin/mktemp/tests/Makefile
new file mode 100644
index 000000000000..c1de03fd1963
--- /dev/null
+++ b/usr.bin/mktemp/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= mktemp_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/mktemp/tests/Makefile.depend b/usr.bin/mktemp/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/mktemp/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mktemp/tests/mktemp_test.sh b/usr.bin/mktemp/tests/mktemp_test.sh
new file mode 100755
index 000000000000..a2d90eed965c
--- /dev/null
+++ b/usr.bin/mktemp/tests/mktemp_test.sh
@@ -0,0 +1,131 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022 Klara Systems
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case tmpdir_env
+tmpdir_env_body()
+{
+
+ tmpdir="$PWD"
+
+ atf_check -o match:"^$tmpdir/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp -t foo
+}
+
+atf_test_case tmpdir_pflag
+tmpdir_pflag_body()
+{
+
+ mkdir tmp_p tmp_env
+
+ tmpdir="$PWD/tmp_env"
+ export TMPDIR="$tmpdir"
+
+ pflag="$PWD/tmp_p"
+
+ # Basic usage: just -p specified
+ atf_check -o match:"^$pflag/tmp\..+$" \
+ env -u TMPDIR mktemp -p "$pflag"
+ atf_check -o match:"^$pflag/tmp\..+$" \
+ env TMPDIR="$tmpdir" mktemp -p "$pflag"
+
+ # -p with a list of names
+ atf_check -o ignore env -u TMPDIR mktemp -p "$pflag" x y z
+ atf_check test -f "$pflag/x"
+ atf_check test -f "$pflag/y"
+ atf_check test -f "$pflag/z"
+
+ # Checking --tmpdir usage, which should defer to $TMPDIR followed by
+ # /tmp with no value specified.
+ atf_check -o match:"^/tmp/foo\..+$" \
+ env -u TMPDIR mktemp --tmpdir -t foo
+ atf_check -o match:"^$tmpdir/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp --tmpdir -t foo
+
+ # Finally, combined -p -t
+ atf_check -o match:"^$pflag/foo\..+$" \
+ env -u TMPDIR mktemp -p "$pflag" -t foo
+ atf_check -o match:"^$pflag/foo\..+$" \
+ env TMPDIR="$tmpdir" mktemp -p "$pflag" -t foo
+}
+
+atf_test_case tmpdir_pflag_dir
+tmpdir_pflag_dir_body()
+{
+
+ tmpdir="$PWD"
+ atf_check -o save:tmpname \
+ env -u TMPDIR mktemp -d -p "$tmpdir" -t foo
+
+ # Better diagnostics when using -o match: + cat rather than grep.
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+ cdir=$(cat tmpname)
+
+ atf_check test -d "$cdir"
+
+ atf_check -o match:"^$tmpdir/footmp$" \
+ env -u TMPDIR mktemp -d -p "$tmpdir" footmp
+ atf_check test -d "$tmpdir/footmp"
+}
+
+atf_test_case tmpdir_pflag_noarg
+tmpdir_pflag_noarg_body()
+{
+
+ # Without -t, this time; this introduces $TMPDIR without having to use
+ # it.
+ tmpdir="$PWD"
+ atf_check -o save:tmpname \
+ env TMPDIR="$tmpdir" mktemp --tmpdir foo.XXXXXXXX
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+
+ # An empty string gets the same treatment.
+ atf_check -o save:tmpname \
+ env TMPDIR="$tmpdir" mktemp -p '' foo.XXXXXXXX
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+}
+
+atf_test_case tmpdir_tflag_oneslash
+tmpdir_tflag_oneslash_body()
+{
+
+ tmpdir="$PWD"
+
+ # Provided a trailing slash, we shouldn't end up with two trailing
+ # slashes.
+ atf_check -o save:tmpname \
+ env TMPDIR="$tmpdir/" mktemp -t foo
+ atf_check -o match:"^$tmpdir/foo\..+$" cat tmpname
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case tmpdir_env
+ atf_add_test_case tmpdir_pflag
+ atf_add_test_case tmpdir_pflag_dir
+ atf_add_test_case tmpdir_pflag_noarg
+ atf_add_test_case tmpdir_tflag_oneslash
+}
diff --git a/usr.bin/mkuzip/Makefile b/usr.bin/mkuzip/Makefile
new file mode 100644
index 000000000000..a2224f4b6758
--- /dev/null
+++ b/usr.bin/mkuzip/Makefile
@@ -0,0 +1,12 @@
+PROG= mkuzip
+MAN= mkuzip.8
+SRCS= mkuzip.c mkuz_blockcache.c mkuz_lzma.c mkuz_zlib.c mkuz_conveyor.c \
+ mkuz_blk.c mkuz_fqueue.c mkuz_time.c mkuz_insize.c mkuz_zstd.c
+
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib
+
+#CFLAGS+= -DMKUZ_DEBUG
+
+LIBADD= lzma md pthread z zstd
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mkuzip/Makefile.depend b/usr.bin/mkuzip/Makefile.depend
new file mode 100644
index 000000000000..1032458d36ca
--- /dev/null
+++ b/usr.bin/mkuzip/Makefile.depend
@@ -0,0 +1,21 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/liblzma \
+ lib/libmd \
+ lib/libthr \
+ lib/libz \
+ lib/libzstd \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mkuzip/mkuz_blk.c b/usr.bin/mkuzip/mkuz_blk.c
new file mode 100644
index 000000000000..347532a972bf
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_blk.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "mkuzip.h"
+#include "mkuz_blk.h"
+
+struct mkuz_blk *
+mkuz_blk_ctor(size_t blen)
+{
+ struct mkuz_blk *rval;
+
+ rval = mkuz_safe_zmalloc(sizeof(struct mkuz_blk) + blen);
+ rval->alen = blen;
+ rval->br_offset = OFFSET_UNDEF;
+ return (rval);
+}
diff --git a/usr.bin/mkuzip/mkuz_blk.h b/usr.bin/mkuzip/mkuz_blk.h
new file mode 100644
index 000000000000..b25347dc9549
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_blk.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 OFFSET_UNDEF UINT64_MAX
+
+struct mkuz_blk_info {
+ uint64_t offset;
+ size_t len;
+ uint32_t blkno;
+ unsigned char digest[16];
+};
+
+#define MKUZ_BLK_EOF (void *)0x1
+#define MKUZ_BLK_MORE (void *)0x2
+
+struct mkuz_blk {
+ struct mkuz_blk_info info;
+ size_t alen;
+ uint64_t br_offset;
+ unsigned char data[];
+};
+
+struct mkuz_blk *mkuz_blk_ctor(size_t);
diff --git a/usr.bin/mkuzip/mkuz_blk_chain.h b/usr.bin/mkuzip/mkuz_blk_chain.h
new file mode 100644
index 000000000000..bc73e54ed61f
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_blk_chain.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+struct mkuz_blk;
+struct mkuz_bchain_link;
+
+struct mkuz_bchain_link {
+ struct mkuz_blk *this;
+ struct mkuz_bchain_link *prev;
+};
diff --git a/usr.bin/mkuzip/mkuz_blockcache.c b/usr.bin/mkuzip/mkuz_blockcache.c
new file mode 100644
index 000000000000..ffaad69dd7b3
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_blockcache.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if defined(MKUZ_DEBUG)
+# include <assert.h>
+# include <stdio.h>
+#endif
+
+#include "mkuz_blockcache.h"
+#include "mkuz_blk.h"
+
+struct mkuz_blkcache_itm {
+ struct mkuz_blk_info hit;
+ struct mkuz_blkcache_itm *next;
+};
+
+static struct mkuz_blkcache {
+ struct mkuz_blkcache_itm first[256];
+} blkcache;
+
+static int
+verify_match(int fd, const struct mkuz_blk *cbp, struct mkuz_blkcache_itm *bcep)
+{
+ void *vbuf;
+ ssize_t rlen;
+ int rval;
+
+ rval = -1;
+ vbuf = malloc(cbp->info.len);
+ if (vbuf == NULL) {
+ goto e0;
+ }
+ if (lseek(fd, bcep->hit.offset, SEEK_SET) < 0) {
+ goto e1;
+ }
+ rlen = read(fd, vbuf, cbp->info.len);
+ if (rlen < 0 || (unsigned)rlen != cbp->info.len) {
+ goto e2;
+ }
+ rval = (memcmp(cbp->data, vbuf, cbp->info.len) == 0) ? 1 : 0;
+e2:
+ lseek(fd, cbp->info.offset, SEEK_SET);
+e1:
+ free(vbuf);
+e0:
+ return (rval);
+}
+
+#define I2J(x) ((intmax_t)(x))
+#define U2J(x) ((uintmax_t)(x))
+
+static unsigned char
+digest_fold(const unsigned char *mdigest)
+{
+ int i;
+ unsigned char rval;
+
+ rval = mdigest[0];
+ for (i = 1; i < 16; i++) {
+ rval = rval ^ mdigest[i];
+ }
+ return (rval);
+}
+
+struct mkuz_blk_info *
+mkuz_blkcache_regblock(int fd, const struct mkuz_blk *bp)
+{
+ struct mkuz_blkcache_itm *bcep;
+ int rval;
+ unsigned char h;
+
+#if defined(MKUZ_DEBUG)
+ assert((unsigned)lseek(fd, 0, SEEK_CUR) == bp->info.offset);
+#endif
+ h = digest_fold(bp->info.digest);
+ if (blkcache.first[h].hit.len == 0) {
+ bcep = &blkcache.first[h];
+ } else {
+ for (bcep = &blkcache.first[h]; bcep != NULL; bcep = bcep->next) {
+ if (bcep->hit.len != bp->info.len)
+ continue;
+ if (memcmp(bp->info.digest, bcep->hit.digest,
+ sizeof(bp->info.digest)) == 0) {
+ break;
+ }
+ }
+ if (bcep != NULL) {
+ rval = verify_match(fd, bp, bcep);
+ if (rval == 1) {
+#if defined(MKUZ_DEBUG)
+ fprintf(stderr, "cache hit %jd, %jd, %jd, %jd\n",
+ I2J(bcep->hit.blkno), I2J(bcep->hit.offset),
+ I2J(bp->info.offset), I2J(bp->info.len));
+#endif
+ return (&bcep->hit);
+ }
+ if (rval == 0) {
+#if defined(MKUZ_DEBUG)
+ fprintf(stderr, "block MD5 collision, you should try lottery, "
+ "man!\n");
+#endif
+ return (NULL);
+ }
+ warn("verify_match");
+ return (NULL);
+ }
+ bcep = malloc(sizeof(struct mkuz_blkcache_itm));
+ if (bcep == NULL)
+ return (NULL);
+ memset(bcep, '\0', sizeof(struct mkuz_blkcache_itm));
+ bcep->next = blkcache.first[h].next;
+ blkcache.first[h].next = bcep;
+ }
+ bcep->hit = bp->info;
+ return (NULL);
+}
diff --git a/usr.bin/mkuzip/mkuz_blockcache.h b/usr.bin/mkuzip/mkuz_blockcache.h
new file mode 100644
index 000000000000..851ebc4b09a2
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_blockcache.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+struct mkuz_blk;
+
+struct mkuz_blk_info *mkuz_blkcache_regblock(int, const struct mkuz_blk *);
diff --git a/usr.bin/mkuzip/mkuz_cfg.h b/usr.bin/mkuzip/mkuz_cfg.h
new file mode 100644
index 000000000000..a4b024f10361
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_cfg.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+struct mkuz_conveyor;
+
+struct mkuz_cfg {
+ int fdr;
+ int fdw;
+ int verbose;
+ int no_zcomp;
+ int en_dedup;
+ int nworkers;
+ int blksz;
+ const char *iname;
+ off_t isize;
+ const struct mkuz_format *handler;
+ size_t cbound_blksz;
+ int comp_level;
+};
diff --git a/usr.bin/mkuzip/mkuz_cloop.h b/usr.bin/mkuzip/mkuz_cloop.h
new file mode 100644
index 000000000000..33617f4add0a
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_cloop.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/* CLOOP format and related constants */
+
+/*
+ * Integer values (block size, number of blocks, offsets)
+ * are stored in big-endian (network) order on disk.
+ */
+
+#define CLOOP_MAGIC_LEN 128
+#define CLOOP_OFS_COMPR 0x0b
+#define CLOOP_OFS_VERSN (CLOOP_OFS_COMPR + 1)
+
+#define CLOOP_MAJVER_2 '2'
+#define CLOOP_MAJVER_3 '3'
+#define CLOOP_MAJVER_4 '4'
+
+#define CLOOP_COMP_LIBZ 'V'
+#define CLOOP_COMP_LZMA 'L'
+#define CLOOP_COMP_ZSTD 'Z'
+
+struct cloop_header {
+ char magic[CLOOP_MAGIC_LEN]; /* cloop magic */
+ uint32_t blksz; /* block size */
+ uint32_t nblocks; /* number of blocks */
+};
diff --git a/usr.bin/mkuzip/mkuz_conveyor.c b/usr.bin/mkuzip/mkuz_conveyor.c
new file mode 100644
index 000000000000..0dee2342c0d1
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_conveyor.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <err.h>
+#include <inttypes.h>
+#include <md5.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#if defined(MKUZ_DEBUG)
+# include <stdio.h>
+#endif
+
+#include "mkuz_conveyor.h"
+#include "mkuz_cfg.h"
+#include "mkuzip.h"
+#include "mkuz_blk.h"
+#include "mkuz_format.h"
+#include "mkuz_fqueue.h"
+#include "mkuz_blk_chain.h"
+
+static void compute_digest(struct mkuz_blk *);
+
+struct cw_args {
+ struct mkuz_conveyor *cvp;
+ struct mkuz_cfg *cfp;
+};
+
+static void *
+cworker(void *p)
+{
+ struct cw_args *cwp;
+ struct mkuz_cfg *cfp;
+ struct mkuz_blk *oblk, *iblk;
+ struct mkuz_conveyor *cvp;
+ void *c_ctx;
+
+ cwp = (struct cw_args *)p;
+ cfp = cwp->cfp;
+ cvp = cwp->cvp;
+ free(cwp);
+ c_ctx = cfp->handler->f_init(&cfp->comp_level);
+ for (;;) {
+ iblk = mkuz_fqueue_deq(cvp->wrk_queue);
+ if (iblk == MKUZ_BLK_EOF) {
+ /* Let other threads to see the EOF block */
+ mkuz_fqueue_enq(cvp->wrk_queue, iblk);
+ break;
+ }
+ if (cfp->no_zcomp == 0 &&
+ mkuz_memvcmp(iblk->data, '\0', iblk->info.len) != 0) {
+ /* All zeroes block */
+ oblk = mkuz_blk_ctor(0);
+ } else {
+ oblk = mkuz_blk_ctor(cfp->cbound_blksz);
+ cfp->handler->f_compress(c_ctx, iblk, oblk);
+ if (cfp->en_dedup != 0) {
+ compute_digest(oblk);
+ }
+ }
+ oblk->info.blkno = iblk->info.blkno;
+ mkuz_fqueue_enq(cvp->results, oblk);
+ free(iblk);
+ }
+ return (NULL);
+}
+
+static void
+compute_digest(struct mkuz_blk *bp)
+{
+ MD5_CTX mcontext;
+
+ MD5Init(&mcontext);
+ MD5Update(&mcontext, bp->data, bp->info.len);
+ MD5Final(bp->info.digest, &mcontext);
+}
+
+struct mkuz_conveyor *
+mkuz_conveyor_ctor(struct mkuz_cfg *cfp)
+{
+ struct mkuz_conveyor *cp;
+ struct cw_args *cwp;
+ int i, r;
+
+ cp = mkuz_safe_zmalloc(sizeof(struct mkuz_conveyor) +
+ (sizeof(pthread_t) * cfp->nworkers));
+
+ cp->wrk_queue = mkuz_fqueue_ctor(1);
+ cp->results = mkuz_fqueue_ctor(1);
+
+ for (i = 0; i < cfp->nworkers; i++) {
+ cwp = mkuz_safe_zmalloc(sizeof(struct cw_args));
+ cwp->cfp = cfp;
+ cwp->cvp = cp;
+ r = pthread_create(&cp->wthreads[i], NULL, cworker, (void *)cwp);
+ if (r != 0) {
+ errx(1, "mkuz_conveyor_ctor: pthread_create() failed");
+ /* Not reached */
+ }
+ }
+ return (cp);
+}
diff --git a/usr.bin/mkuzip/mkuz_conveyor.h b/usr.bin/mkuzip/mkuz_conveyor.h
new file mode 100644
index 000000000000..092d7e441edc
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_conveyor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+struct mkuz_fifo_queue;
+
+#define ITEMS_PER_WORKER 4
+
+#define MAX_WORKERS_AUTO 24
+
+struct mkuz_conveyor {
+ /*
+ * Work items are places in here, and picked up by workers in a FIFO
+ * fashion.
+ */
+ struct mkuz_fifo_queue *wrk_queue;
+ /*
+ * Results are dropped into this FIFO and consumer is buzzed to pick them
+ * up
+ */
+ struct mkuz_fifo_queue *results;
+
+ pthread_t wthreads[];
+};
+
+struct mkuz_cfg;
+
+struct mkuz_conveyor *mkuz_conveyor_ctor(struct mkuz_cfg *);
diff --git a/usr.bin/mkuzip/mkuz_format.h b/usr.bin/mkuzip/mkuz_format.h
new file mode 100644
index 000000000000..c76264081f9c
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_format.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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_RAW_METHOD(f_compress_bound, size_t, size_t);
+DEFINE_RAW_METHOD(f_init, void *, int *);
+DEFINE_RAW_METHOD(f_compress, void, void *, const struct mkuz_blk *, struct mkuz_blk *);
+
+struct mkuz_format {
+ const char *option;
+ const char *magic;
+ const char *default_sufx;
+ f_compress_bound_t f_compress_bound;
+ f_init_t f_init;
+ f_compress_t f_compress;
+};
diff --git a/usr.bin/mkuzip/mkuz_fqueue.c b/usr.bin/mkuzip/mkuz_fqueue.c
new file mode 100644
index 000000000000..ef823e19d0d7
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_fqueue.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#if defined(MKUZ_DEBUG)
+# include <assert.h>
+#endif
+
+#include "mkuzip.h"
+#include "mkuz_fqueue.h"
+#include "mkuz_conveyor.h"
+#include "mkuz_blk.h"
+#include "mkuz_blk_chain.h"
+
+struct mkuz_fifo_queue *
+mkuz_fqueue_ctor(int wakeup_len)
+{
+ struct mkuz_fifo_queue *fqp;
+
+ fqp = mkuz_safe_zmalloc(sizeof(struct mkuz_fifo_queue));
+ fqp->wakeup_len = wakeup_len;
+ if (pthread_mutex_init(&fqp->mtx, NULL) != 0) {
+ errx(1, "pthread_mutex_init() failed");
+ }
+ if (pthread_cond_init(&fqp->cvar, NULL) != 0) {
+ errx(1, "pthread_cond_init() failed");
+ }
+ return (fqp);
+}
+
+void
+mkuz_fqueue_enq(struct mkuz_fifo_queue *fqp, struct mkuz_blk *bp)
+{
+ struct mkuz_bchain_link *ip;
+
+ ip = mkuz_safe_zmalloc(sizeof(struct mkuz_bchain_link));
+ ip->this = bp;
+
+ pthread_mutex_lock(&fqp->mtx);
+ if (fqp->first != NULL) {
+ fqp->first->prev = ip;
+ } else {
+ fqp->last = ip;
+ }
+ fqp->first = ip;
+ fqp->length += 1;
+ if (fqp->length >= fqp->wakeup_len) {
+ pthread_cond_signal(&fqp->cvar);
+ }
+ pthread_mutex_unlock(&fqp->mtx);
+}
+
+#if defined(NOTYET)
+int
+mkuz_fqueue_enq_all(struct mkuz_fifo_queue *fqp, struct mkuz_bchain_link *cip_f,
+ struct mkuz_bchain_link *cip_l, int clen)
+{
+ int rval;
+
+ pthread_mutex_lock(&fqp->mtx);
+ if (fqp->first != NULL) {
+ fqp->first->prev = cip_l;
+ } else {
+ fqp->last = cip_l;
+ }
+ fqp->first = cip_f;
+ fqp->length += clen;
+ rval = fqp->length;
+ if (fqp->length >= fqp->wakeup_len) {
+ pthread_cond_signal(&fqp->cvar);
+ }
+ pthread_mutex_unlock(&fqp->mtx);
+ return (rval);
+}
+#endif
+
+static int
+mkuz_fqueue_check(struct mkuz_fifo_queue *fqp, cmp_cb_t cmp_cb, void *cap)
+{
+ struct mkuz_bchain_link *ip;
+
+ for (ip = fqp->last; ip != NULL; ip = ip->prev) {
+ if (cmp_cb(ip->this, cap)) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+struct mkuz_blk *
+mkuz_fqueue_deq_when(struct mkuz_fifo_queue *fqp, cmp_cb_t cmp_cb, void *cap)
+{
+ struct mkuz_bchain_link *ip, *newlast, *newfirst, *mip;
+ struct mkuz_blk *bp;
+
+ pthread_mutex_lock(&fqp->mtx);
+ while (fqp->last == NULL || !mkuz_fqueue_check(fqp, cmp_cb, cap)) {
+ pthread_cond_wait(&fqp->cvar, &fqp->mtx);
+ }
+ if (cmp_cb(fqp->last->this, cap)) {
+ mip = fqp->last;
+ fqp->last = mip->prev;
+ if (fqp->last == NULL) {
+#if defined(MKUZ_DEBUG)
+ assert(fqp->length == 1);
+#endif
+ fqp->first = NULL;
+ }
+ } else {
+#if defined(MKUZ_DEBUG)
+ assert(fqp->length > 1);
+#endif
+ newfirst = newlast = fqp->last;
+ mip = NULL;
+ for (ip = fqp->last->prev; ip != NULL; ip = ip->prev) {
+ if (cmp_cb(ip->this, cap)) {
+ mip = ip;
+ continue;
+ }
+ newfirst->prev = ip;
+ newfirst = ip;
+ }
+ newfirst->prev = NULL;
+ fqp->first = newfirst;
+ fqp->last = newlast;
+ }
+ fqp->length -= 1;
+ pthread_mutex_unlock(&fqp->mtx);
+ bp = mip->this;
+ free(mip);
+
+ return bp;
+}
+
+struct mkuz_blk *
+mkuz_fqueue_deq(struct mkuz_fifo_queue *fqp)
+{
+ struct mkuz_bchain_link *ip;
+ struct mkuz_blk *bp;
+
+ pthread_mutex_lock(&fqp->mtx);
+ while (fqp->last == NULL) {
+ pthread_cond_wait(&fqp->cvar, &fqp->mtx);
+ }
+#if defined(MKUZ_DEBUG)
+ assert(fqp->length > 0);
+#endif
+ ip = fqp->last;
+ fqp->last = ip->prev;
+ if (fqp->last == NULL) {
+#if defined(MKUZ_DEBUG)
+ assert(fqp->length == 1);
+#endif
+ fqp->first = NULL;
+ }
+ fqp->length -= 1;
+ pthread_mutex_unlock(&fqp->mtx);
+ bp = ip->this;
+ free(ip);
+
+ return bp;
+}
+
+#if defined(NOTYET)
+struct mkuz_bchain_link *
+mkuz_fqueue_deq_all(struct mkuz_fifo_queue *fqp, int *rclen)
+{
+ struct mkuz_bchain_link *rchain;
+
+ pthread_mutex_lock(&fqp->mtx);
+ while (fqp->last == NULL) {
+ pthread_cond_wait(&fqp->cvar, &fqp->mtx);
+ }
+#if defined(MKUZ_DEBUG)
+ assert(fqp->length > 0);
+#endif
+ rchain = fqp->last;
+ fqp->first = fqp->last = NULL;
+ *rclen = fqp->length;
+ fqp->length = 0;
+ pthread_mutex_unlock(&fqp->mtx);
+ return (rchain);
+}
+#endif
diff --git a/usr.bin/mkuzip/mkuz_fqueue.h b/usr.bin/mkuzip/mkuz_fqueue.h
new file mode 100644
index 000000000000..b37708e546e8
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_fqueue.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+struct mkuz_fifo_queue {
+ pthread_mutex_t mtx;
+ pthread_cond_t cvar;
+ struct mkuz_bchain_link *first;
+ struct mkuz_bchain_link *last;
+ int length;
+ int wakeup_len;
+};
+
+struct mkuz_blk;
+struct mkuz_bchain_link;
+
+DEFINE_RAW_METHOD(cmp_cb, int, const struct mkuz_blk *, void *);
+
+struct mkuz_fifo_queue *mkuz_fqueue_ctor(int);
+void mkuz_fqueue_enq(struct mkuz_fifo_queue *, struct mkuz_blk *);
+struct mkuz_blk *mkuz_fqueue_deq(struct mkuz_fifo_queue *);
+struct mkuz_blk *mkuz_fqueue_deq_when(struct mkuz_fifo_queue *, cmp_cb_t, void *);
+#if defined(NOTYET)
+struct mkuz_bchain_link *mkuz_fqueue_deq_all(struct mkuz_fifo_queue *, int *);
+int mkuz_fqueue_enq_all(struct mkuz_fifo_queue *, struct mkuz_bchain_link *,
+ struct mkuz_bchain_link *, int);
+#endif
diff --git a/usr.bin/mkuzip/mkuz_insize.c b/usr.bin/mkuzip/mkuz_insize.c
new file mode 100644
index 000000000000..f0b2f39229ed
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_insize.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/disk.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "mkuz_cfg.h"
+#include "mkuz_insize.h"
+
+off_t
+mkuz_get_insize(struct mkuz_cfg *cfp)
+{
+ int ffd;
+ off_t ms;
+ struct stat sb;
+ struct statfs statfsbuf;
+
+ if (fstat(cfp->fdr, &sb) != 0) {
+ warn("fstat(%s)", cfp->iname);
+ return (-1);
+ }
+ if ((sb.st_flags & SF_SNAPSHOT) != 0) {
+ if (fstatfs(cfp->fdr, &statfsbuf) != 0) {
+ warn("fstatfs(%s)", cfp->iname);
+ return (-1);
+ }
+ ffd = open(statfsbuf.f_mntfromname, O_RDONLY);
+ if (ffd < 0) {
+ warn("open(%s, O_RDONLY)", statfsbuf.f_mntfromname);
+ return (-1);
+ }
+ if (ioctl(ffd, DIOCGMEDIASIZE, &ms) < 0) {
+ warn("ioctl(DIOCGMEDIASIZE)");
+ close(ffd);
+ return (-1);
+ }
+ close(ffd);
+ sb.st_size = ms;
+ } else if (S_ISCHR(sb.st_mode)) {
+ if (ioctl(cfp->fdr, DIOCGMEDIASIZE, &ms) < 0) {
+ warn("ioctl(DIOCGMEDIASIZE)");
+ return (-1);
+ }
+ sb.st_size = ms;
+ } else if (!S_ISREG(sb.st_mode)) {
+ warnx("%s: not a character device or regular file\n",
+ cfp->iname);
+ return (-1);
+ }
+ return (sb.st_size);
+}
diff --git a/usr.bin/mkuzip/mkuz_insize.h b/usr.bin/mkuzip/mkuz_insize.h
new file mode 100644
index 000000000000..d048023c15df
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_insize.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+off_t mkuz_get_insize(struct mkuz_cfg *);
diff --git a/usr.bin/mkuzip/mkuz_lzma.c b/usr.bin/mkuzip/mkuz_lzma.c
new file mode 100644
index 000000000000..7c713e25aed3
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_lzma.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * Copyright (c) 2011 Aleksandr Rybalko <ray@ddteam.net>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <err.h>
+#include <stdint.h>
+
+#include <lzma.h>
+
+#include "mkuzip.h"
+#include "mkuz_blk.h"
+#include "mkuz_lzma.h"
+
+struct mkuz_lzma {
+ lzma_filter filters[2];
+ lzma_options_lzma opt_lzma;
+ lzma_stream strm;
+};
+
+size_t
+mkuz_lzma_cbound(size_t blksz)
+{
+ return (lzma_stream_buffer_bound(blksz));
+}
+
+void *
+mkuz_lzma_init(int *comp_level)
+{
+ struct mkuz_lzma *ulp;
+
+ if (*comp_level == USE_DEFAULT_LEVEL)
+ *comp_level = LZMA_PRESET_DEFAULT;
+ if (*comp_level < 0 || *comp_level > 9)
+ errx(1, "provided compression level %d is invalid",
+ *comp_level);
+ /* Not reached */
+
+ ulp = mkuz_safe_zmalloc(sizeof(struct mkuz_lzma));
+
+ /* Init lzma encoder */
+ ulp->strm = (lzma_stream)LZMA_STREAM_INIT;
+ if (lzma_lzma_preset(&ulp->opt_lzma, *comp_level))
+ errx(1, "Error loading LZMA preset");
+
+ ulp->filters[0].id = LZMA_FILTER_LZMA2;
+ ulp->filters[0].options = &ulp->opt_lzma;
+ ulp->filters[1].id = LZMA_VLI_UNKNOWN;
+
+ return (void *)ulp;
+}
+
+void
+mkuz_lzma_compress(void *p, const struct mkuz_blk *iblk, struct mkuz_blk *oblk)
+{
+ lzma_ret ret;
+ struct mkuz_lzma *ulp;
+
+ ulp = (struct mkuz_lzma *)p;
+
+ ret = lzma_stream_encoder(&ulp->strm, ulp->filters, LZMA_CHECK_CRC32);
+ if (ret != LZMA_OK) {
+ if (ret == LZMA_MEMLIMIT_ERROR)
+ errx(1, "can't compress data: LZMA_MEMLIMIT_ERROR");
+
+ errx(1, "can't compress data: LZMA compressor ERROR");
+ }
+
+ ulp->strm.next_in = iblk->data;
+ ulp->strm.avail_in = iblk->info.len;
+ ulp->strm.next_out = oblk->data;
+ ulp->strm.avail_out = oblk->alen;
+
+ ret = lzma_code(&ulp->strm, LZMA_FINISH);
+
+ if (ret != LZMA_STREAM_END)
+ errx(1, "lzma_code FINISH failed, code=%d, pos(in=%zd, "
+ "out=%zd)", ret, (iblk->info.len - ulp->strm.avail_in),
+ (oblk->alen - ulp->strm.avail_out));
+
+#if 0
+ lzma_end(&ulp->strm);
+#endif
+
+ oblk->info.len = oblk->alen - ulp->strm.avail_out;
+}
diff --git a/usr.bin/mkuzip/mkuz_lzma.h b/usr.bin/mkuzip/mkuz_lzma.h
new file mode 100644
index 000000000000..de7633c395ca
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_lzma.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * Copyright (c) 2011 Aleksandr Rybalko <ray@ddteam.net>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 DEFAULT_SUFX_LZMA ".ulzma"
+
+/* Format L3.0, since we move to XZ API */
+#define CLOOP_MAGIC_LZMA "#!/bin/sh\n#L3.0\n"
+
+size_t mkuz_lzma_cbound(size_t);
+void *mkuz_lzma_init(int *);
+void mkuz_lzma_compress(void *, const struct mkuz_blk *, struct mkuz_blk *);
diff --git a/usr.bin/mkuzip/mkuz_time.c b/usr.bin/mkuzip/mkuz_time.c
new file mode 100644
index 000000000000..10ad7aead3b5
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_time.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <math.h>
+#include <stdint.h>
+#include <time.h>
+
+#include "mkuz_time.h"
+
+double
+getdtime(void)
+{
+ struct timespec tp;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1)
+ return (-1);
+
+ return timespec2dtime(&tp);
+}
diff --git a/usr.bin/mkuzip/mkuz_time.h b/usr.bin/mkuzip/mkuz_time.h
new file mode 100644
index 000000000000..8cbb05c9c885
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_time.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _RTPP_TIME_H_
+#define _RTPP_TIME_H_
+
+#define SEC(x) ((x)->tv_sec)
+#define NSEC(x) ((x)->tv_nsec)
+
+#define timespec2dtime(s) ((double)SEC(s) + \
+ (double)NSEC(s) / 1000000000.0)
+
+/* Function prototypes */
+double getdtime(void);
+
+#endif
diff --git a/usr.bin/mkuzip/mkuz_zlib.c b/usr.bin/mkuzip/mkuz_zlib.c
new file mode 100644
index 000000000000..57f6079c3c54
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_zlib.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <err.h>
+#include <stdint.h>
+
+#include <zlib.h>
+
+#include "mkuzip.h"
+#include "mkuz_blk.h"
+#include "mkuz_zlib.h"
+
+struct mkuz_zlib {
+ int comp_level;
+};
+
+size_t
+mkuz_zlib_cbound(size_t blksz)
+{
+ return (compressBound(blksz));
+}
+
+void *
+mkuz_zlib_init(int *comp_level)
+{
+ struct mkuz_zlib *zp;
+
+ if (*comp_level == USE_DEFAULT_LEVEL)
+ *comp_level = Z_BEST_COMPRESSION;
+ if (*comp_level < Z_BEST_SPEED || *comp_level > Z_BEST_COMPRESSION)
+ errx(1, "provided compression level %d is invalid",
+ *comp_level);
+ /* Not reached */
+
+ zp = mkuz_safe_zmalloc(sizeof(struct mkuz_zlib));
+ zp->comp_level = *comp_level;
+
+ return (zp);
+}
+
+void
+mkuz_zlib_compress(void *p, const struct mkuz_blk *iblk, struct mkuz_blk *oblk)
+{
+ uLongf destlen_z;
+ struct mkuz_zlib *zp;
+
+ zp = (struct mkuz_zlib *)p;
+
+ destlen_z = oblk->alen;
+ if (compress2(oblk->data, &destlen_z, iblk->data, iblk->info.len,
+ zp->comp_level) != Z_OK) {
+ errx(1, "can't compress data: compress2() failed");
+ /* Not reached */
+ }
+
+ oblk->info.len = (uint32_t)destlen_z;
+}
diff --git a/usr.bin/mkuzip/mkuz_zlib.h b/usr.bin/mkuzip/mkuz_zlib.h
new file mode 100644
index 000000000000..5ecf77bb7284
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_zlib.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 DEFAULT_SUFX_ZLIB ".uzip"
+
+#define CLOOP_MAGIC_ZLIB "#!/bin/sh\n#V2.0 Format\n"
+
+size_t mkuz_zlib_cbound(size_t);
+void *mkuz_zlib_init(int *);
+void mkuz_zlib_compress(void *, const struct mkuz_blk *, struct mkuz_blk *);
diff --git a/usr.bin/mkuzip/mkuz_zstd.c b/usr.bin/mkuzip/mkuz_zstd.c
new file mode 100644
index 000000000000..e188b42ee0d5
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_zstd.c
@@ -0,0 +1,93 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <zstd.h>
+
+#include "mkuzip.h"
+#include "mkuz_blk.h"
+#include "mkuz_zstd.h"
+
+size_t
+mkuz_zstd_cbound(size_t blksz)
+{
+ return (ZSTD_compressBound(blksz));
+}
+
+void *
+mkuz_zstd_init(int *comp_level)
+{
+ ZSTD_CCtx *cctx;
+ size_t rc;
+
+ /* Default chosen for near-parity with mkuzip zlib default. */
+ if (*comp_level == USE_DEFAULT_LEVEL)
+ *comp_level = 9;
+ if (*comp_level < ZSTD_minCLevel() || *comp_level == 0 ||
+ *comp_level > ZSTD_maxCLevel())
+ errx(1, "provided compression level %d is invalid",
+ *comp_level);
+
+ cctx = ZSTD_createCCtx();
+ if (cctx == NULL)
+ errx(1, "could not allocate Zstd context");
+
+ rc = ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel,
+ *comp_level);
+ if (ZSTD_isError(rc))
+ errx(1, "Could not set zstd compression level %d: %s",
+ *comp_level, ZSTD_getErrorName(rc));
+
+ rc = ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
+ if (ZSTD_isError(rc))
+ errx(1, "Could not enable zstd checksum: %s",
+ ZSTD_getErrorName(rc));
+
+ return (cctx);
+}
+
+void
+mkuz_zstd_compress(void *p, const struct mkuz_blk *iblk, struct mkuz_blk *oblk)
+{
+ ZSTD_CCtx *cctx;
+ size_t rc;
+
+ cctx = p;
+
+ rc = ZSTD_compress2(cctx, oblk->data, oblk->alen, iblk->data,
+ iblk->info.len);
+ if (ZSTD_isError(rc))
+ errx(1, "could not compress data: ZSTD_compress2: %s",
+ ZSTD_getErrorName(rc));
+
+ oblk->info.len = rc;
+}
diff --git a/usr.bin/mkuzip/mkuz_zstd.h b/usr.bin/mkuzip/mkuz_zstd.h
new file mode 100644
index 000000000000..ca62d3afd417
--- /dev/null
+++ b/usr.bin/mkuzip/mkuz_zstd.h
@@ -0,0 +1,34 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
+ *
+ * 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 AUTHOR 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 AUTHOR 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 DEFAULT_SUFX_ZSTD ".uzst"
+
+#define CLOOP_MAGIC_ZSTD "#!/bin/sh\n#Z4.0 Format\n"
+
+size_t mkuz_zstd_cbound(size_t);
+void *mkuz_zstd_init(int *);
+void mkuz_zstd_compress(void *, const struct mkuz_blk *, struct mkuz_blk *);
diff --git a/usr.bin/mkuzip/mkuzip.8 b/usr.bin/mkuzip/mkuzip.8
new file mode 100644
index 000000000000..3b3afc626633
--- /dev/null
+++ b/usr.bin/mkuzip/mkuzip.8
@@ -0,0 +1,272 @@
+.\"-
+.\" Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 9, 2019
+.Dt MKUZIP 8
+.Os
+.Sh NAME
+.Nm mkuzip
+.Nd compress disk image for use with
+.Xr geom_uzip 4
+class
+.Sh SYNOPSIS
+.Nm
+.Op Fl dSsvZ
+.Op Fl A Ar compression_algorithm
+.Op Fl C Ar compression_level
+.Op Fl j Ar compression_jobs
+.Op Fl o Ar outfile
+.Op Fl s Ar cluster_size
+.Ar infile
+.Sh DESCRIPTION
+The
+.Nm
+utility compresses a disk image file so that the
+.Xr geom_uzip 4
+class will be able to decompress the resulting image at run-time.
+This allows for a significant reduction of size of disk image at
+the expense of some CPU time required to decompress the data each
+time it is read.
+The
+.Nm
+utility
+works in two phases:
+.Bl -enum
+.It
+An
+.Ar infile
+image is split into clusters; each cluster is compressed.
+.It
+The resulting set of compressed clusters is written to the output file.
+In addition, a
+.Dq table of contents
+header is written which allows for efficient seeking.
+.El
+.Pp
+The options are:
+.Bl -tag -width indent
+.It Fl A Op Ar lzma | Ar zlib | Ar zstd
+Select a specific compression algorithm.
+If this option is not provided, the default is
+.Ar zlib .
+.Pp
+The
+.Ar lzma
+algorithm provides noticeable better compression levels than zlib on the same
+data set.
+It has vastly slower compression speed and moderately slower decompression
+speed.
+.Pp
+The
+.Ar zstd
+algorithm provides better compression levels than zlib on the same data set.
+It also has faster compression and decompression speed than zlib.
+In the very high compression
+.Dq level
+settings, it does not offer quite as high a compression ratio as
+.Ar lzma .
+However, its decompression speed does not suffer at high compression
+.Dq levels .
+.It Fl C Ar compression_level
+Select the integer compression level used to parameterize the chosen
+compression algorithm.
+.Pp
+For any given algorithm, a lesser number selects a faster compression mode.
+A greater number selects a slower compression mode.
+Typically, for the same algorithm, a greater
+.Ar compression_level
+provides better final compression ratio.
+.Pp
+For
+.Ar lzma ,
+the range of valid compression levels is
+.Va 0-9 .
+The
+.Nm
+default for lzma is
+.Va 6 .
+.Pp
+For
+.Ar zlib ,
+the range of valid compression levels is
+.Va 1-9 .
+The
+.Nm
+default for zlib is
+.Va 9 .
+.Pp
+For
+.Ar zstd ,
+the range of valid compression levels is currently
+.Va 1-19 .
+The
+.Nm
+default for zstd is
+.Va 9 .
+.It Fl d
+Enable de-duplication.
+When the option is enabled
+.Nm
+detects identical blocks in the input and replaces each subsequent occurrence
+of such block with pointer to the very first one in the output.
+Setting this option results is moderate decrease of compressed image size,
+typically around 3-5% of a final size of the compressed image.
+.It Fl j Ar compression_jobs
+Specify the number of compression jobs that
+.Nm
+runs in parallel to speed up compression.
+When option is not specified the number of jobs set to be equal
+to the value of
+.Va hw.ncpu
+.Xr sysctl 8
+variable.
+.It Op Fl L
+Legacy flag that indicates the same thing as
+.Dq Fl A Ar lzma .
+.It Fl o Ar outfile
+Name of the output file
+.Ar outfile .
+The default is to use the input name with the suffix
+.Pa .uzip
+for the
+.Xr zlib 3
+compression or
+.Pa .ulzma
+for the
+.Xr lzma 3 .
+.It Fl S
+Print summary about the compression ratio as well as output
+file size after file has been processed.
+.It Fl s Ar cluster_size
+Split the image into clusters of
+.Ar cluster_size
+bytes, 16384 bytes by default.
+The
+.Ar cluster_size
+should be a multiple of 512 bytes.
+.It Fl v
+Display verbose messages.
+.It Fl Z
+Disable zero-block detection and elimination.
+When this option is set,
+.Nm
+compresses blocks of zero bytes just as it would any other block.
+When the option is not set,
+.Nm
+detects and compresses zero blocks in a space-efficient way.
+Setting
+.Fl Z
+increases compressed image sizes slightly, typically less than 0.1%.
+.El
+.Sh IMPLEMENTATION NOTES
+The compression ratio largely depends on the compression algorithm, level, and
+cluster size used.
+For large cluster sizes (16kB and higher), typical overall image compression
+ratios with
+.Xr zlib 3
+are only 1-2% less than those achieved with
+.Xr gzip 1
+over the entire image.
+However, it should be kept in mind that larger cluster sizes lead to higher
+overhead in the
+.Xr geom_uzip 4
+class, as the class has to decompress the whole cluster even if
+only a few bytes from that cluster have to be read.
+.Pp
+Additionally, the threshold at 16-32 kB where a larger cluster size does not
+benefit overall compression ratio is an artifact of the
+.Xr zlib 3
+algorithm in particular.
+.Ar Lzma
+and
+.Ar Zstd will continue to provide better compression ratios as cluster sizes
+are increased, at high enough compression levels.
+The same tradeoff continues to apply: reads in
+.Xr geom_uzip 4
+become more expensive the greater the cluster size.
+.Pp
+The de-duplication is a
+.Fx
+specific feature and while it does not require any changes to on-disk
+compressed image format, however it did require some matching changes to the
+.Xr geom_uzip 4
+to handle resulting images correctly.
+.Pp
+To make use of
+.Ar zstd
+.Nm
+images, the kernel must be configured with
+.Cd ZSTDIO .
+It is enabled by default in many
+.Cd GENERIC
+kernels provided as binary distributions by
+.Fx .
+The status on any particular system can be verified by checking
+.Xr sysctl 8
+.Dv kern.features.geom_uzip_zstd
+for
+.Dq 1 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Pp
+The following describes how to create and mount a uzip image.
+.Pp
+Create a file system image:
+.Bd -literal -offset indent
+makefs /src.img /usr/src
+.Ed
+.Pp
+Create the uzip image, the output file will be named src.img.uzip:
+.Bd -literal -offset indent
+mkuzip /src.img
+.Ed
+.Pp
+Ensure geom_uzip is loaded:
+.Bd -literal -offset indent
+kldload geom_uzip
+.Ed
+.Pp
+Create an MD device backed by the uzip image:
+.Bd -literal -offset indent
+mdconfig -f /src.img.uzip
+.Ed
+.Pp
+Mount the uzip image:
+.Bd -literal -offset indent
+mount -o ro /dev/md0.uzip /mnt
+.Ed
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr xz 1 ,
+.Xr zstd 1 ,
+.Xr zlib 3 ,
+.Xr geom 4 ,
+.Xr geom_uzip 4 ,
+.Xr md 4 ,
+.Xr mdconfig 8 ,
+.Xr mount_cd9660 8
+.Sh AUTHORS
+.An Maxim Sobolev Aq Mt sobomax@FreeBSD.org
diff --git a/usr.bin/mkuzip/mkuzip.c b/usr.bin/mkuzip/mkuzip.c
new file mode 100644
index 000000000000..5d2aa9a48a98
--- /dev/null
+++ b/usr.bin/mkuzip/mkuzip.c
@@ -0,0 +1,502 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/endian.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mkuzip.h"
+#include "mkuz_cloop.h"
+#include "mkuz_blockcache.h"
+#include "mkuz_lzma.h"
+#include "mkuz_zlib.h"
+#include "mkuz_zstd.h"
+#include "mkuz_blk.h"
+#include "mkuz_cfg.h"
+#include "mkuz_conveyor.h"
+#include "mkuz_format.h"
+#include "mkuz_fqueue.h"
+#include "mkuz_time.h"
+#include "mkuz_insize.h"
+
+#define DEFAULT_CLSTSIZE 16384
+
+enum UZ_ALGORITHM {
+ UZ_ZLIB = 0,
+ UZ_LZMA,
+ UZ_ZSTD,
+ UZ_INVALID
+};
+
+static const struct mkuz_format uzip_fmts[] = {
+ [UZ_ZLIB] = {
+ .option = "zlib",
+ .magic = CLOOP_MAGIC_ZLIB,
+ .default_sufx = DEFAULT_SUFX_ZLIB,
+ .f_compress_bound = mkuz_zlib_cbound,
+ .f_init = mkuz_zlib_init,
+ .f_compress = mkuz_zlib_compress,
+ },
+ [UZ_LZMA] = {
+ .option = "lzma",
+ .magic = CLOOP_MAGIC_LZMA,
+ .default_sufx = DEFAULT_SUFX_LZMA,
+ .f_compress_bound = mkuz_lzma_cbound,
+ .f_init = mkuz_lzma_init,
+ .f_compress = mkuz_lzma_compress,
+ },
+ [UZ_ZSTD] = {
+ .option = "zstd",
+ .magic = CLOOP_MAGIC_ZSTD,
+ .default_sufx = DEFAULT_SUFX_ZSTD,
+ .f_compress_bound = mkuz_zstd_cbound,
+ .f_init = mkuz_zstd_init,
+ .f_compress = mkuz_zstd_compress,
+ },
+};
+
+static struct mkuz_blk *readblock(int, u_int32_t);
+static void usage(void) __dead2;
+static void cleanup(void);
+
+static char *cleanfile = NULL;
+
+static int
+cmp_blkno(const struct mkuz_blk *bp, void *p)
+{
+ uint32_t *ap;
+
+ ap = (uint32_t *)p;
+
+ return (bp->info.blkno == *ap);
+}
+
+int main(int argc, char **argv)
+{
+ struct mkuz_cfg cfs;
+ char *oname;
+ uint64_t *toc;
+ int i, io, opt, tmp;
+ struct {
+ int en;
+ FILE *f;
+ } summary;
+ struct iovec iov[2];
+ uint64_t offset, last_offset;
+ struct cloop_header hdr;
+ struct mkuz_conveyor *cvp;
+ struct mkuz_blk_info *chit;
+ size_t ncpusz, ncpu, magiclen;
+ double st, et;
+ enum UZ_ALGORITHM comp_alg;
+ int comp_level;
+
+ st = getdtime();
+
+ ncpusz = sizeof(size_t);
+ if (sysctlbyname("hw.ncpu", &ncpu, &ncpusz, NULL, 0) < 0) {
+ ncpu = 1;
+ } else if (ncpu > MAX_WORKERS_AUTO) {
+ ncpu = MAX_WORKERS_AUTO;
+ }
+
+ memset(&hdr, 0, sizeof(hdr));
+ cfs.blksz = DEFAULT_CLSTSIZE;
+ oname = NULL;
+ cfs.verbose = 0;
+ cfs.no_zcomp = 0;
+ cfs.en_dedup = 0;
+ summary.en = 0;
+ summary.f = stderr;
+ comp_alg = UZ_ZLIB;
+ comp_level = USE_DEFAULT_LEVEL;
+ cfs.nworkers = ncpu;
+ struct mkuz_blk *iblk, *oblk;
+
+ while((opt = getopt(argc, argv, "A:C:o:s:vZdLSj:")) != -1) {
+ switch(opt) {
+ case 'A':
+ for (tmp = UZ_ZLIB; tmp < UZ_INVALID; tmp++) {
+ if (strcmp(uzip_fmts[tmp].option, optarg) == 0)
+ break;
+ }
+ if (tmp == UZ_INVALID)
+ errx(1, "invalid algorithm specified: %s",
+ optarg);
+ /* Not reached */
+ comp_alg = tmp;
+ break;
+ case 'C':
+ comp_level = atoi(optarg);
+ break;
+ case 'o':
+ oname = optarg;
+ break;
+
+ case 's':
+ tmp = atoi(optarg);
+ if (tmp <= 0) {
+ errx(1, "invalid cluster size specified: %s",
+ optarg);
+ /* Not reached */
+ }
+ cfs.blksz = tmp;
+ break;
+
+ case 'v':
+ cfs.verbose = 1;
+ break;
+
+ case 'Z':
+ cfs.no_zcomp = 1;
+ break;
+
+ case 'd':
+ cfs.en_dedup = 1;
+ break;
+
+ case 'L':
+ comp_alg = UZ_LZMA;
+ break;
+
+ case 'S':
+ summary.en = 1;
+ summary.f = stdout;
+ break;
+
+ case 'j':
+ tmp = atoi(optarg);
+ if (tmp <= 0) {
+ errx(1, "invalid number of compression threads"
+ " specified: %s", optarg);
+ /* Not reached */
+ }
+ cfs.nworkers = tmp;
+ break;
+
+ default:
+ usage();
+ /* Not reached */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ usage();
+ /* Not reached */
+ }
+
+ cfs.handler = &uzip_fmts[comp_alg];
+
+ magiclen = strlcpy(hdr.magic, cfs.handler->magic, sizeof(hdr.magic));
+ assert(magiclen < sizeof(hdr.magic));
+
+ if (cfs.en_dedup != 0) {
+ /*
+ * Dedupe requires a version 3 format. Don't downgrade newer
+ * formats.
+ */
+ if (hdr.magic[CLOOP_OFS_VERSN] == CLOOP_MAJVER_2)
+ hdr.magic[CLOOP_OFS_VERSN] = CLOOP_MAJVER_3;
+ hdr.magic[CLOOP_OFS_COMPR] =
+ tolower(hdr.magic[CLOOP_OFS_COMPR]);
+ }
+
+ if (cfs.blksz % DEV_BSIZE != 0)
+ errx(1, "cluster size should be multiple of %d", DEV_BSIZE);
+
+ cfs.cbound_blksz = cfs.handler->f_compress_bound(cfs.blksz);
+ if (cfs.cbound_blksz > MAXPHYS)
+ errx(1, "maximal compressed cluster size %zu greater than MAXPHYS %zu",
+ cfs.cbound_blksz, (size_t)MAXPHYS);
+
+ cfs.handler->f_init(&comp_level);
+ cfs.comp_level = comp_level;
+
+ cfs.iname = argv[0];
+ if (oname == NULL) {
+ asprintf(&oname, "%s%s", cfs.iname, cfs.handler->default_sufx);
+ if (oname == NULL) {
+ err(1, "can't allocate memory");
+ /* Not reached */
+ }
+ }
+
+ signal(SIGHUP, exit);
+ signal(SIGINT, exit);
+ signal(SIGTERM, exit);
+ signal(SIGXCPU, exit);
+ signal(SIGXFSZ, exit);
+ atexit(cleanup);
+
+ cfs.fdr = open(cfs.iname, O_RDONLY);
+ if (cfs.fdr < 0) {
+ err(1, "open(%s)", cfs.iname);
+ /* Not reached */
+ }
+ cfs.isize = mkuz_get_insize(&cfs);
+ if (cfs.isize < 0) {
+ errx(1, "can't determine input image size");
+ /* Not reached */
+ }
+ hdr.nblocks = cfs.isize / cfs.blksz;
+ if ((cfs.isize % cfs.blksz) != 0) {
+ if (cfs.verbose != 0)
+ fprintf(stderr, "file size is not multiple "
+ "of %d, padding data\n", cfs.blksz);
+ hdr.nblocks++;
+ }
+ toc = mkuz_safe_malloc((hdr.nblocks + 1) * sizeof(*toc));
+
+ /*
+ * Initialize last+1 entry with non-heap trash. If final padding is
+ * added later, it may or may not be overwritten with an offset
+ * representing the length of the final compressed block. If not,
+ * initialize to a defined value.
+ */
+ toc[hdr.nblocks] = 0;
+
+ cfs.fdw = open(oname, (cfs.en_dedup ? O_RDWR : O_WRONLY) | O_TRUNC | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (cfs.fdw < 0) {
+ err(1, "open(%s)", oname);
+ /* Not reached */
+ }
+ cleanfile = oname;
+
+ /* Prepare header that we will write later when we have index ready. */
+ iov[0].iov_base = (char *)&hdr;
+ iov[0].iov_len = sizeof(hdr);
+ iov[1].iov_base = (char *)toc;
+ iov[1].iov_len = (hdr.nblocks + 1) * sizeof(*toc);
+ offset = iov[0].iov_len + iov[1].iov_len;
+
+ /* Reserve space for header */
+ lseek(cfs.fdw, offset, SEEK_SET);
+
+ if (cfs.verbose != 0) {
+ fprintf(stderr, "data size %ju bytes, number of clusters "
+ "%u, index length %zu bytes\n", cfs.isize,
+ hdr.nblocks, iov[1].iov_len);
+ }
+
+ cvp = mkuz_conveyor_ctor(&cfs);
+
+ last_offset = 0;
+ iblk = oblk = NULL;
+ for(i = io = 0; iblk != MKUZ_BLK_EOF; i++) {
+ iblk = readblock(cfs.fdr, cfs.blksz);
+ mkuz_fqueue_enq(cvp->wrk_queue, iblk);
+ if (iblk != MKUZ_BLK_EOF &&
+ (i < (cfs.nworkers * ITEMS_PER_WORKER))) {
+ continue;
+ }
+drain:
+ oblk = mkuz_fqueue_deq_when(cvp->results, cmp_blkno, &io);
+ assert(oblk->info.blkno == (unsigned)io);
+ oblk->info.offset = offset;
+ chit = NULL;
+ if (cfs.en_dedup != 0 && oblk->info.len > 0) {
+ chit = mkuz_blkcache_regblock(cfs.fdw, oblk);
+ /*
+ * There should be at least one non-empty block
+ * between us and the backref'ed offset, otherwise
+ * we won't be able to parse that sequence correctly
+ * as it would be indistinguishible from another
+ * empty block.
+ */
+ if (chit != NULL && chit->offset == last_offset) {
+ chit = NULL;
+ }
+ }
+ if (chit != NULL) {
+ toc[io] = htobe64(chit->offset);
+ oblk->info.len = 0;
+ } else {
+ if (oblk->info.len > 0 && write(cfs.fdw, oblk->data,
+ oblk->info.len) < 0) {
+ err(1, "write(%s)", oname);
+ /* Not reached */
+ }
+ toc[io] = htobe64(offset);
+ last_offset = offset;
+ offset += oblk->info.len;
+ }
+ if (cfs.verbose != 0) {
+ fprintf(stderr, "cluster #%d, in %u bytes, "
+ "out len=%lu offset=%lu", io, cfs.blksz,
+ (u_long)oblk->info.len, (u_long)be64toh(toc[io]));
+ if (chit != NULL) {
+ fprintf(stderr, " (backref'ed to #%d)",
+ chit->blkno);
+ }
+ fprintf(stderr, "\n");
+ }
+ free(oblk);
+ io += 1;
+ if (iblk == MKUZ_BLK_EOF) {
+ if (io < i)
+ goto drain;
+ /* Last block, see if we need to add some padding */
+ if ((offset % DEV_BSIZE) == 0)
+ continue;
+ oblk = mkuz_blk_ctor(DEV_BSIZE - (offset % DEV_BSIZE));
+ oblk->info.blkno = io;
+ oblk->info.len = oblk->alen;
+ if (cfs.verbose != 0) {
+ fprintf(stderr, "padding data with %lu bytes "
+ "so that file size is multiple of %d\n",
+ (u_long)oblk->alen, DEV_BSIZE);
+ }
+ mkuz_fqueue_enq(cvp->results, oblk);
+ goto drain;
+ }
+ }
+
+ close(cfs.fdr);
+
+ if (cfs.verbose != 0 || summary.en != 0) {
+ et = getdtime();
+ fprintf(summary.f, "compressed data to %ju bytes, saved %lld "
+ "bytes, %.2f%% decrease, %.2f bytes/sec.\n", offset,
+ (long long)(cfs.isize - offset),
+ 100.0 * (long long)(cfs.isize - offset) /
+ (float)cfs.isize, (float)cfs.isize / (et - st));
+ }
+
+ /* Convert to big endian */
+ hdr.blksz = htonl(cfs.blksz);
+ hdr.nblocks = htonl(hdr.nblocks);
+ /* Write headers into pre-allocated space */
+ lseek(cfs.fdw, 0, SEEK_SET);
+ if (writev(cfs.fdw, iov, 2) < 0) {
+ err(1, "writev(%s)", oname);
+ /* Not reached */
+ }
+ cleanfile = NULL;
+ close(cfs.fdw);
+
+ exit(0);
+}
+
+static struct mkuz_blk *
+readblock(int fd, u_int32_t clstsize)
+{
+ int numread;
+ struct mkuz_blk *rval;
+ static int blockcnt;
+ off_t cpos;
+
+ rval = mkuz_blk_ctor(clstsize);
+
+ rval->info.blkno = blockcnt;
+ blockcnt += 1;
+ cpos = lseek(fd, 0, SEEK_CUR);
+ if (cpos < 0) {
+ err(1, "readblock: lseek() failed");
+ /* Not reached */
+ }
+ rval->info.offset = cpos;
+
+ numread = read(fd, rval->data, clstsize);
+ if (numread < 0) {
+ err(1, "readblock: read() failed");
+ /* Not reached */
+ }
+ if (numread == 0) {
+ free(rval);
+ return MKUZ_BLK_EOF;
+ }
+ rval->info.len = numread;
+ return rval;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: mkuzip [-vZdLS] [-o outfile] [-s cluster_size] "
+ "[-j ncompr] infile\n");
+ exit(1);
+}
+
+void *
+mkuz_safe_malloc(size_t size)
+{
+ void *retval;
+
+ retval = malloc(size);
+ if (retval == NULL) {
+ err(1, "can't allocate memory");
+ /* Not reached */
+ }
+ return retval;
+}
+
+void *
+mkuz_safe_zmalloc(size_t size)
+{
+ void *retval;
+
+ retval = mkuz_safe_malloc(size);
+ bzero(retval, size);
+ return retval;
+}
+
+static void
+cleanup(void)
+{
+
+ if (cleanfile != NULL)
+ unlink(cleanfile);
+}
+
+int
+mkuz_memvcmp(const void *memory, unsigned char val, size_t size)
+{
+ const u_char *mm;
+
+ mm = (const u_char *)memory;
+ return (*mm == val) && memcmp(mm, mm + 1, size - 1) == 0;
+}
diff --git a/usr.bin/mkuzip/mkuzip.h b/usr.bin/mkuzip/mkuzip.h
new file mode 100644
index 000000000000..3bff21d1a1e6
--- /dev/null
+++ b/usr.bin/mkuzip/mkuzip.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2004-2016 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 DEFINE_RAW_METHOD(func, rval, args...) typedef rval (*func##_t)(args)
+
+/* Use an algorithm-specific default level if no explicit level is selected. */
+#define USE_DEFAULT_LEVEL INT_MIN
+
+void *mkuz_safe_malloc(size_t);
+void *mkuz_safe_zmalloc(size_t);
+int mkuz_memvcmp(const void *, unsigned char, size_t);
diff --git a/usr.bin/morse/Makefile b/usr.bin/morse/Makefile
new file mode 100644
index 000000000000..669ece99f898
--- /dev/null
+++ b/usr.bin/morse/Makefile
@@ -0,0 +1,4 @@
+PROG= morse
+MAN= morse.6
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/morse/Makefile.depend b/usr.bin/morse/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/morse/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/morse/morse.6 b/usr.bin/morse/morse.6
new file mode 100644
index 000000000000..96a756102c40
--- /dev/null
+++ b/usr.bin/morse/morse.6
@@ -0,0 +1,210 @@
+.\" Copyright (c) 2000 Alexey Zelkin. All rights reserved.
+.\" Copyright (c) 1988, 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.
+.\"
+.Dd April 16, 2023
+.Dt MORSE 6
+.Os
+.Sh NAME
+.Nm morse
+.Nd reformat input as morse code
+.Sh SYNOPSIS
+.Nm
+.Op Fl elrps
+.Op Fl d Ar device
+.Op Fl w Ar speed
+.Op Fl c Ar speed
+.Op Fl f Ar frequency
+.Op Ar string ...
+.Sh DESCRIPTION
+The
+.Nm
+command reads the given input and reformats it in the form of morse code.
+Acceptable input are command line arguments or the standard input.
+.Pp
+Available options:
+.Bl -tag -width indent
+.It Fl l
+The
+.Fl l
+option produces output suitable for
+.Xr led 4
+devices.
+.It Fl s
+The
+.Fl s
+option produces dots and dashes rather than words.
+.It Fl p
+Send morse the real way.
+This only works if your system has
+.Xr speaker 4
+support.
+.It Fl w Ar speed
+Set the sending speed in words per minute.
+If not specified, the default
+speed of 20 WPM is used.
+.It Fl c Ar speed
+Farnsworth support.
+Set the spacing between characters in words per minute.
+This is independent of the speed
+that the individual characters are sent.
+If not specified, defaults to the effective value of the
+.Fl w
+option.
+.It Fl f Ar frequency
+Set the sidetone frequency to something other than the default 600 Hz.
+.It Fl d Ar device
+Similar to
+.Fl p ,
+but use the RTS line of
+.Ar device
+(which must be a TTY device)
+in order to emit the morse code.
+.It Fl e
+Echo each character before it is sent, used together with either
+.Fl p
+or
+.Fl d .
+.It Fl r
+Decode morse output consisting of dots and dashes (as generated by using
+the
+.Fl s
+option).
+.El
+.Pp
+The
+.Fl w , c
+and
+.Fl f
+flags only work in conjunction with either the
+.Fl p
+or the
+.Fl d
+flag.
+.Pp
+Not all prosigns have corresponding characters.
+Use
+.Ql #
+for
+.Em AS ,
+.Ql &
+for
+.Em SK ,
+.Ql *
+for
+.Em VE
+and
+.Ql %
+for
+.Em BK .
+The more common prosigns are
+.Ql =
+for
+.Em BT ,
+.Ql \&(
+for
+.Em KN
+and
+.Ql +
+for
+.Em AR .
+.Pp
+Using the
+.Fl d
+flag,
+it is possible to key an external device, like a sidetone generator with
+a headset for training purposes, or even your ham radio transceiver.
+For
+the latter, simply connect an NPN transistor to the serial port
+.Ar device ,
+emitter connected to ground, base connected through a resistor
+(few kiloohms) to RTS, collector to the key line of your transceiver
+(assuming the transceiver has a positive key supply voltage and is keyed
+by grounding the key input line).
+A capacitor (some nanofarads) between
+base and ground is advisable to keep stray RF away,
+and to suppress the
+minor glitch that is generated during program startup.
+.Sh ENVIRONMENT
+Your
+.Ev LC_CTYPE
+locale codeset determines how
+characters with the high-order bit set
+are interpreted.
+.Pp
+.Bl -tag -width ".Li ISO8859-15" -compact
+.It Li ISO8859-1
+.It Li ISO8859-15
+Interpret characters with the high-order bit set as Western European characters.
+.Pp
+.It Li KOI8-R
+Interpret characters with the high-order bit set as Cyrillic characters.
+.Pp
+.It Li ISO8859-7
+Interpret characters with the high-order bit set as Greek characters.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /dev/speaker" -compact
+.It Pa /dev/speaker
+.Xr speaker 4
+device file
+.El
+.Sh SEE ALSO
+.Xr speaker 4
+.Rs
+.%I ITU-T Recommendation F.1
+.%R "Operational provisions for the international public telegram service"
+.%O Division B, I. Morse code
+.Re
+.Rs
+.%I ITU-R M.1677-1
+.%R International Morse code
+.%D 2009
+.%U https://www.itu.int/rec/R-REC-M.1677-1-200910-I/
+.Re
+.Sh HISTORY
+Sound support for
+.Nm
+added by
+.An Lyndon Nerenberg (VE6BBM) Aq Mt lyndon@orthanc.ca .
+.Pp
+Ability to key an external device added by
+.An J\(:org Wunsch
+(DL8DTL).
+.Pp
+Farnsworth support for
+.Nm
+added by
+.An Stephen Cravey (N5UUU) .
+.Sh BUGS
+Only understands a few European characters
+(German and French),
+no Asian characters,
+and no continental landline code.
+.Pp
+Sends a bit slower than it should due to system overhead.
+Some people would call this a feature.
diff --git a/usr.bin/morse/morse.c b/usr.bin/morse/morse.c
new file mode 100644
index 000000000000..7d9fcde1e5e3
--- /dev/null
+++ b/usr.bin/morse/morse.c
@@ -0,0 +1,662 @@
+/*-
+ * Copyright (c) 1988, 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.
+ */
+
+/*
+ * Taught to send *real* morse by Lyndon Nerenberg (VE6BBM)
+ * <lyndon@orthanc.ca>
+ */
+
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#ifdef __FreeBSD__
+/* Always use the speaker, let the open fail if -p is selected */
+#define SPEAKER "/dev/speaker"
+#endif
+
+#define WHITESPACE " \t\n"
+#define DELIMITERS " \t"
+
+#ifdef SPEAKER
+#include <dev/speaker/speaker.h>
+#endif
+
+struct morsetab {
+ const char inchar;
+ const char *morse;
+};
+
+static const struct morsetab mtab[] = {
+
+ /* letters */
+
+ {'a', ".-"},
+ {'b', "-..."},
+ {'c', "-.-."},
+ {'d', "-.."},
+ {'e', "."},
+ {'f', "..-."},
+ {'g', "--."},
+ {'h', "...."},
+ {'i', ".."},
+ {'j', ".---"},
+ {'k', "-.-"},
+ {'l', ".-.."},
+ {'m', "--"},
+ {'n', "-."},
+ {'o', "---"},
+ {'p', ".--."},
+ {'q', "--.-"},
+ {'r', ".-."},
+ {'s', "..."},
+ {'t', "-"},
+ {'u', "..-"},
+ {'v', "...-"},
+ {'w', ".--"},
+ {'x', "-..-"},
+ {'y', "-.--"},
+ {'z', "--.."},
+
+ /* digits */
+
+ {'0', "-----"},
+ {'1', ".----"},
+ {'2', "..---"},
+ {'3', "...--"},
+ {'4', "....-"},
+ {'5', "....."},
+ {'6', "-...."},
+ {'7', "--..."},
+ {'8', "---.."},
+ {'9', "----."},
+
+ /* punctuation */
+
+ {',', "--..--"},
+ {'.', ".-.-.-"},
+ {'"', ".-..-."},
+ {'!', "..--."},
+ {'?', "..--.."},
+ {'/', "-..-."},
+ {'-', "-....-"},
+ {'=', "-...-"}, /* BT */
+ {':', "---..."},
+ {';', "-.-.-."},
+ {'(', "-.--."}, /* KN */
+ {')', "-.--.-"},
+ {'$', "...-..-"},
+ {'+', ".-.-."}, /* AR */
+ {'@', ".--.-."}, /* AC */
+ {'_', "..--.-"},
+ {'\'', ".----."},
+
+ /* prosigns without already assigned values */
+
+ {'#', ".-..."}, /* AS */
+ {'&', "...-.-"}, /* SK */
+ {'*', "...-."}, /* VE */
+ {'%', "-...-.-"}, /* BK */
+
+ {'\0', ""}
+};
+
+/*
+ * Code-points for some Latin1 chars in ISO-8859-1 encoding.
+ * UTF-8 encoded chars in the comments.
+ */
+static const struct morsetab iso8859_1tab[] = {
+ {'\340', ".--.-"}, /* à */
+ {'\341', ".--.-"}, /* á */
+ {'\342', ".--.-"}, /* â */
+ {'\344', ".-.-"}, /* ä */
+ {'\347', "-.-.."}, /* ç */
+ {'\350', "..-.."}, /* è */
+ {'\351', "..-.."}, /* é */
+ {'\352', "-..-."}, /* ê */
+ {'\361', "--.--"}, /* ñ */
+ {'\366', "---."}, /* ö */
+ {'\374', "..--"}, /* ü */
+
+ {'\0', ""}
+};
+
+/*
+ * Code-points for some Greek chars in ISO-8859-7 encoding.
+ * UTF-8 encoded chars in the comments.
+ */
+static const struct morsetab iso8859_7tab[] = {
+ /*
+ * This table does not implement:
+ * - the special sequences for the seven diphthongs,
+ * - the punctuation differences.
+ * Implementing these features would introduce too many
+ * special-cases in the program's main loop.
+ * The diphthong sequences are:
+ * alpha iota .-.-
+ * alpha upsilon ..--
+ * epsilon upsilon ---.
+ * eta upsilon ...-
+ * omicron iota ---..
+ * omicron upsilon ..-
+ * upsilon iota .---
+ * The different punctuation symbols are:
+ * ; ..-.-
+ * ! --..--
+ */
+ {'\341', ".-"}, /* α, alpha */
+ {'\334', ".-"}, /* ά, alpha with acute */
+ {'\342', "-..."}, /* β, beta */
+ {'\343', "--."}, /* γ, gamma */
+ {'\344', "-.."}, /* δ, delta */
+ {'\345', "."}, /* ε, epsilon */
+ {'\335', "."}, /* έ, epsilon with acute */
+ {'\346', "--.."}, /* ζ, zeta */
+ {'\347', "...."}, /* η, eta */
+ {'\336', "...."}, /* ή, eta with acute */
+ {'\350', "-.-."}, /* θ, theta */
+ {'\351', ".."}, /* ι, iota */
+ {'\337', ".."}, /* ί, iota with acute */
+ {'\372', ".."}, /* ÏŠ, iota with diaeresis */
+ {'\300', ".."}, /* Î, iota with acute and diaeresis */
+ {'\352', "-.-"}, /* κ, kappa */
+ {'\353', ".-.."}, /* λ, lambda */
+ {'\354', "--"}, /* μ, mu */
+ {'\355', "-."}, /* ν, nu */
+ {'\356', "-..-"}, /* ξ, xi */
+ {'\357', "---"}, /* ο, omicron */
+ {'\374', "---"}, /* ό, omicron with acute */
+ {'\360', ".--."}, /* π, pi */
+ {'\361', ".-."}, /* Ï, rho */
+ {'\363', "..."}, /* σ, sigma */
+ {'\362', "..."}, /* Ï‚, final sigma */
+ {'\364', "-"}, /* Ï„, tau */
+ {'\365', "-.--"}, /* Ï…, upsilon */
+ {'\375', "-.--"}, /* Ï, upsilon with acute */
+ {'\373', "-.--"}, /* Ï‹, upsilon and diaeresis */
+ {'\340', "-.--"}, /* ΰ, upsilon with acute and diaeresis */
+ {'\366', "..-."}, /* φ, phi */
+ {'\367', "----"}, /* χ, chi */
+ {'\370', "--.-"}, /* ψ, psi */
+ {'\371', ".--"}, /* ω, omega */
+ {'\376', ".--"}, /* ÏŽ, omega with acute */
+
+ {'\0', ""}
+};
+
+/*
+ * Code-points for the Cyrillic alphabet in KOI8-R encoding.
+ * UTF-8 encoded chars in the comments.
+ */
+static const struct morsetab koi8rtab[] = {
+ {'\301', ".-"}, /* а, a */
+ {'\302', "-..."}, /* б, be */
+ {'\327', ".--"}, /* в, ve */
+ {'\307', "--."}, /* г, ge */
+ {'\304', "-.."}, /* д, de */
+ {'\305', "."}, /* е, ye */
+ {'\243', "."}, /* Ñ‘, yo, the same as ye */
+ {'\326', "...-"}, /* ж, she */
+ {'\332', "--.."}, /* з, ze */
+ {'\311', ".."}, /* и, i */
+ {'\312', ".---"}, /* й, i kratkoye */
+ {'\313', "-.-"}, /* к, ka */
+ {'\314', ".-.."}, /* л, el */
+ {'\315', "--"}, /* м, em */
+ {'\316', "-."}, /* н, en */
+ {'\317', "---"}, /* о, o */
+ {'\320', ".--."}, /* п, pe */
+ {'\322', ".-."}, /* р, er */
+ {'\323', "..."}, /* Ñ, es */
+ {'\324', "-"}, /* Ñ‚, te */
+ {'\325', "..-"}, /* у, u */
+ {'\306', "..-."}, /* Ñ„, ef */
+ {'\310', "...."}, /* Ñ…, kha */
+ {'\303', "-.-."}, /* ц, ce */
+ {'\336', "---."}, /* ч, che */
+ {'\333', "----"}, /* ш, sha */
+ {'\335', "--.-"}, /* щ, shcha */
+ {'\331', "-.--"}, /* Ñ‹, yi */
+ {'\330', "-..-"}, /* ь, myakhkij znak */
+ {'\334', "..-.."}, /* Ñ, ae */
+ {'\300', "..--"}, /* ÑŽ, yu */
+ {'\321', ".-.-"}, /* Ñ, ya */
+
+ {'\0', ""}
+};
+
+static void show(const char *), play(const char *), morse(char);
+static void decode (char *), fdecode(FILE *);
+static void ttyout(const char *);
+static void sighandler(int);
+
+static int pflag, lflag, rflag, sflag, eflag;
+static int wpm = 20; /* effective words per minute */
+static int cpm; /* effective words per minute between
+ * characters */
+#define FREQUENCY 600
+static int freq = FREQUENCY;
+static char *device; /* for tty-controlled generator */
+
+#define DASH_LEN 3
+#define CHAR_SPACE 3
+#define WORD_SPACE (7 - CHAR_SPACE - 1)
+static float dot_clock;
+static float cdot_clock;
+static int spkr, line;
+static struct termios otty, ntty;
+static int olflags;
+
+#ifdef SPEAKER
+static tone_t sound;
+#define GETOPTOPTS "c:d:ef:lprsw:"
+#define USAGE \
+"usage: morse [-elprs] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
+#else
+#define GETOPTOPTS "c:d:ef:lrsw:"
+#define USAGE \
+"usage: morse [-elrs] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
+
+#endif
+
+static const struct morsetab *hightab;
+
+int
+main(int argc, char *argv[])
+{
+ int ch, lflags;
+ char *p, *codeset;
+
+ while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
+ switch ((char) ch) {
+ case 'c':
+ cpm = atoi(optarg);
+ break;
+ case 'd':
+ device = optarg;
+ break;
+ case 'e':
+ eflag = 1;
+ setvbuf(stdout, 0, _IONBF, 0);
+ break;
+ case 'f':
+ freq = atoi(optarg);
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+#ifdef SPEAKER
+ case 'p':
+ pflag = 1;
+ break;
+#endif
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'w':
+ wpm = atoi(optarg);
+ break;
+ case '?':
+ default:
+ errx(1, USAGE);
+ }
+ if ((sflag && lflag) || (sflag && rflag) || (lflag && rflag)) {
+ errx(1, "morse: only one of -l, -s, and -r allowed\n");
+ }
+ if ((pflag || device) && (sflag || lflag)) {
+ errx(1, "morse: only one of -p, -d and -l, -s allowed\n");
+ }
+ if (cpm == 0) {
+ cpm = wpm;
+ }
+ if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) {
+ errx(1, "morse: insane speed\n");
+ }
+ if ((pflag || device) && (freq == 0)) {
+ freq = FREQUENCY;
+ }
+#ifdef SPEAKER
+ if (pflag) {
+ if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
+ err(1, SPEAKER);
+ }
+ } else
+#endif
+ if (device) {
+ if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
+ err(1, "open tty line");
+ }
+ if (tcgetattr(line, &otty) == -1) {
+ err(1, "tcgetattr() failed");
+ }
+ ntty = otty;
+ ntty.c_cflag |= CLOCAL;
+ tcsetattr(line, TCSANOW, &ntty);
+ lflags = fcntl(line, F_GETFL);
+ lflags &= ~O_NONBLOCK;
+ fcntl(line, F_SETFL, &lflags);
+ ioctl(line, TIOCMGET, &lflags);
+ lflags &= ~TIOCM_RTS;
+ olflags = lflags;
+ ioctl(line, TIOCMSET, &lflags);
+ (void)signal(SIGHUP, sighandler);
+ (void)signal(SIGINT, sighandler);
+ (void)signal(SIGQUIT, sighandler);
+ (void)signal(SIGTERM, sighandler);
+ }
+ if (pflag || device) {
+ dot_clock = wpm / 2.4; /* dots/sec */
+ dot_clock = 1 / dot_clock; /* duration of a dot */
+ dot_clock = dot_clock / 2; /* dot_clock runs at twice */
+ /* the dot rate */
+ dot_clock = dot_clock * 100; /* scale for ioctl */
+
+ cdot_clock = cpm / 2.4; /* dots/sec */
+ cdot_clock = 1 / cdot_clock; /* duration of a dot */
+ cdot_clock = cdot_clock / 2; /* dot_clock runs at twice */
+ /* the dot rate */
+ cdot_clock = cdot_clock * 100; /* scale for ioctl */
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (setlocale(LC_CTYPE, "") != NULL &&
+ *(codeset = nl_langinfo(CODESET)) != '\0') {
+ if (strcmp(codeset, "KOI8-R") == 0)
+ hightab = koi8rtab;
+ else if (strcmp(codeset, "ISO8859-1") == 0 ||
+ strcmp(codeset, "ISO8859-15") == 0)
+ hightab = iso8859_1tab;
+ else if (strcmp(codeset, "ISO8859-7") == 0)
+ hightab = iso8859_7tab;
+ }
+
+ if (lflag) {
+ printf("m");
+ }
+ if (rflag) {
+ if (*argv) {
+ do {
+ p = strtok(*argv, DELIMITERS);
+ if (p == NULL) {
+ decode(*argv);
+ }
+ else {
+ while (p) {
+ decode(p);
+ p = strtok(NULL, DELIMITERS);
+ }
+ }
+ } while (*++argv);
+ putchar('\n');
+ } else {
+ fdecode(stdin);
+ }
+ }
+ else if (*argv) {
+ do {
+ for (p = *argv; *p; ++p) {
+ if (eflag)
+ putchar(*p);
+ morse(*p);
+ }
+ if (eflag)
+ putchar(' ');
+ morse(' ');
+ } while (*++argv);
+ } else {
+ while ((ch = getchar()) != EOF) {
+ if (eflag)
+ putchar(ch);
+ morse(ch);
+ }
+ }
+ if (device)
+ tcsetattr(line, TCSANOW, &otty);
+ exit(0);
+}
+
+static void
+morse(char c)
+{
+ const struct morsetab *m;
+
+ if (isalpha((unsigned char)c))
+ c = tolower((unsigned char)c);
+ if ((c == '\r') || (c == '\n'))
+ c = ' ';
+ if (c == ' ') {
+ if (pflag)
+ play(" ");
+ else if (device)
+ ttyout(" ");
+ else if (lflag)
+ printf("\n");
+ else
+ show("");
+ return;
+ }
+ for (m = ((unsigned char)c < 0x80? mtab: hightab);
+ m != NULL && m->inchar != '\0';
+ m++) {
+ if (m->inchar == c) {
+ if (pflag) {
+ play(m->morse);
+ } else if (device) {
+ ttyout(m->morse);
+ } else
+ show(m->morse);
+ }
+ }
+}
+
+static void
+show(const char *s)
+{
+ if (lflag) {
+ printf("%s ", s);
+ } else if (sflag) {
+ printf(" %s\n", s);
+ } else {
+ for (; *s; ++s)
+ printf(" %s", *s == '.' ? *(s + 1) == '\0' ? "dit" :
+ "di" : "dah");
+ printf("\n");
+ }
+}
+
+static void
+play(const char *s)
+{
+#ifdef SPEAKER
+ const char *c;
+
+ for (c = s; *c != '\0'; c++) {
+ switch (*c) {
+ case '.':
+ sound.frequency = freq;
+ sound.duration = dot_clock;
+ break;
+ case '-':
+ sound.frequency = freq;
+ sound.duration = dot_clock * DASH_LEN;
+ break;
+ case ' ':
+ sound.frequency = 0;
+ sound.duration = cdot_clock * WORD_SPACE;
+ break;
+ default:
+ sound.duration = 0;
+ }
+ if (sound.duration) {
+ if (ioctl(spkr, SPKRTONE, &sound) == -1) {
+ err(1, "ioctl play");
+ }
+ }
+ sound.frequency = 0;
+ sound.duration = dot_clock;
+ if (ioctl(spkr, SPKRTONE, &sound) == -1) {
+ err(1, "ioctl rest");
+ }
+ }
+ sound.frequency = 0;
+ sound.duration = cdot_clock * CHAR_SPACE;
+ ioctl(spkr, SPKRTONE, &sound);
+#endif
+}
+
+static void
+ttyout(const char *s)
+{
+ const char *c;
+ int duration, on, lflags;
+
+ for (c = s; *c != '\0'; c++) {
+ switch (*c) {
+ case '.':
+ on = 1;
+ duration = dot_clock;
+ break;
+ case '-':
+ on = 1;
+ duration = dot_clock * DASH_LEN;
+ break;
+ case ' ':
+ on = 0;
+ duration = cdot_clock * WORD_SPACE;
+ break;
+ default:
+ on = 0;
+ duration = 0;
+ }
+ if (on) {
+ ioctl(line, TIOCMGET, &lflags);
+ lflags |= TIOCM_RTS;
+ ioctl(line, TIOCMSET, &lflags);
+ }
+ duration *= 10000;
+ if (duration)
+ usleep(duration);
+ ioctl(line, TIOCMGET, &lflags);
+ lflags &= ~TIOCM_RTS;
+ ioctl(line, TIOCMSET, &lflags);
+ duration = dot_clock * 10000;
+ usleep(duration);
+ }
+ duration = cdot_clock * CHAR_SPACE * 10000;
+ usleep(duration);
+}
+
+void
+fdecode(FILE *stream)
+{
+ char *n, *p, *s;
+ char buf[BUFSIZ];
+
+ s = buf;
+ while (fgets(s, BUFSIZ - (s - buf), stream)) {
+ p = buf;
+
+ while (*p && isblank(*p)) {
+ p++;
+ }
+ while (*p && isspace(*p)) {
+ p++;
+ putchar (' ');
+ }
+ while (*p) {
+ n = strpbrk(p, WHITESPACE);
+ if (n == NULL) {
+ /* The token was interrupted at the end
+ * of the buffer. Shift it to the begin
+ * of the buffer.
+ */
+ for (s = buf; *p; *s++ = *p++)
+ ;
+ } else {
+ *n = '\0';
+ n++;
+ decode(p);
+ p = n;
+ }
+ }
+ }
+ putchar('\n');
+}
+
+void
+decode(char *p)
+{
+ char c;
+ const struct morsetab *m;
+
+ c = ' ';
+ for (m = mtab; m != NULL && m->inchar != '\0'; m++) {
+ if (strcmp(m->morse, p) == 0) {
+ c = m->inchar;
+ break;
+ }
+ }
+
+ if (c == ' ')
+ for (m = hightab; m != NULL && m->inchar != '\0'; m++) {
+ if (strcmp(m->morse, p) == 0) {
+ c = m->inchar;
+ break;
+ }
+ }
+
+ putchar(c);
+}
+
+static void
+sighandler(int signo)
+{
+
+ ioctl(line, TIOCMSET, &olflags);
+ tcsetattr(line, TCSANOW, &otty);
+
+ signal(signo, SIG_DFL);
+ (void)kill(getpid(), signo);
+}
diff --git a/usr.bin/msgs/Makefile b/usr.bin/msgs/Makefile
new file mode 100644
index 000000000000..f30ced394797
--- /dev/null
+++ b/usr.bin/msgs/Makefile
@@ -0,0 +1,5 @@
+PROG= msgs
+
+LIBADD= tinfow
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/msgs/Makefile.depend b/usr.bin/msgs/Makefile.depend
new file mode 100644
index 000000000000..dd06faaab7bf
--- /dev/null
+++ b/usr.bin/msgs/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/msgs/msgs.1 b/usr.bin/msgs/msgs.1
new file mode 100644
index 000000000000..ea643fd31efc
--- /dev/null
+++ b/usr.bin/msgs/msgs.1
@@ -0,0 +1,229 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd August 8, 2018
+.Dt MSGS 1
+.Os
+.Sh NAME
+.Nm msgs
+.Nd system messages and junk mail program
+.Sh SYNOPSIS
+.Nm
+.Op Fl fhlpq
+.Op Ar number
+.Op Ar \-number
+.Nm
+.Op Fl s
+.Nm
+.Op Fl c
+.Op \-days
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to read system messages.
+These messages are
+sent by mailing to the login `msgs' and should be short
+pieces of information which are suitable to be read once by most users
+of the system.
+.Pp
+The
+.Nm
+utility is normally invoked each time you login, by placing it in the file
+.Pa .login
+(or
+.Pa .profile
+if you use
+.Xr sh 1 ) .
+It will then prompt you with the source and subject of each new message.
+If there is no subject line, the first few non-blank lines of the
+message will be displayed.
+If there is more to the message, you will be told how
+long it is and asked whether you wish to see the rest of the message.
+The possible responses are:
+.Bl -tag -width Fl
+.It Fl y
+Type the rest of the message.
+.It Ic RETURN
+Synonym for y.
+.It Fl n
+Skip this message
+and go on to the next message.
+.It Fl
+Redisplay the last message.
+.It Fl q
+Drop out of
+.Nm ;
+the next time
+.Nm
+will pick up where it last left off.
+.It Fl s
+Append the current message to the file ``Messages'' in the current directory;
+`s\-' will save the previously displayed message.
+A `s' or `s\-' may
+be followed by a space and a file name to receive the message replacing
+the default ``Messages''.
+.It Fl m
+A copy of the specified message is placed in a temporary
+mailbox and
+.Xr mail 1
+is invoked on that mailbox.
+Both `m' and `s' accept a numeric argument in place of the `\-'.
+.El
+.Pp
+The
+.Nm
+utility keeps track of the next message you will see by a number in the file
+.Pa \&.msgsrc
+in your home directory.
+In the directory
+.Pa /var/msgs
+it keeps a set of files whose names are the (sequential) numbers
+of the messages they represent.
+The file
+.Pa /var/msgs/bounds
+shows the low and high number of the messages in the directory
+so that
+.Nm
+can quickly determine if there are no messages for you.
+If the contents of
+.Pa bounds
+is incorrect it can be fixed by removing it;
+.Nm
+will make a new
+.Pa bounds
+file the next time it is run with the
+.Fl s
+option.
+If
+.Nm
+is run with any option other than
+.Fl s ,
+an error will be displayed if
+.Pa /var/msgs/bounds
+does not exist.
+.Pp
+The
+.Fl s
+option is used for setting up the posting of messages.
+The line
+.Pp
+.Dl msgs: \&"\&| /usr/bin/msgs \-s\&"
+.Pp
+should be included in
+.Pa /etc/mail/aliases
+(see
+.Xr newaliases 1 )
+to enable posting of messages.
+.Pp
+The
+.Fl c
+option is used for performing cleanup on
+.Pa /var/msgs .
+A shell script entry to run
+.Nm
+with the
+.Fl c
+option should be placed in
+.Pa /etc/periodic/daily
+(see
+.Xr periodic 8 )
+to run every night.
+This will remove all messages over 21 days old.
+A different expiration may be specified on the command line to override
+the default.
+You must be the superuser to use this option.
+.Pp
+Options when reading messages include:
+.Bl -tag -width Fl
+.It Fl f
+Do not say ``No new messages.''.
+This is useful in a
+.Pa .login
+file since this is often the case here.
+.It Fl q
+Queries whether there are messages, printing
+``There are new messages.'' if there are.
+The command ``msgs \-q'' is often used in login scripts.
+.It Fl h
+Print the first part of messages only.
+.It Fl l
+Cause only locally originated messages to be reported.
+.It Ar num
+A message number can be given
+on the command line, causing
+.Nm
+to start at the specified message rather than at the next message
+indicated by your
+.Pa \&.msgsrc
+file.
+Thus
+.Pp
+.Dl msgs \-h 1
+.Pp
+prints the first part of all messages.
+.It Ar \-number
+Start
+.Ar number
+messages back from the one indicated in the
+.Pa \&.msgsrc
+file, useful for reviews of recent messages.
+.It Fl p
+Pipe long messages through
+.Xr less 1 .
+.El
+.Pp
+Within
+.Nm
+you can also go to any specific message by typing its number when
+.Nm
+requests input as to what to do.
+.Sh ENVIRONMENT
+The
+.Nm
+utility uses the
+.Ev HOME
+and
+.Ev TERM
+environment variables for the default home directory and
+terminal type.
+.Sh FILES
+.Bl -tag -width /var/msgs/* -compact
+.It Pa /var/msgs/*
+database
+.It Pa ~/.msgsrc
+number of next message to be presented
+.El
+.Sh SEE ALSO
+.Xr less 1 ,
+.Xr mail 1 ,
+.Xr aliases 5 ,
+.Xr periodic 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/msgs/msgs.c b/usr.bin/msgs/msgs.c
new file mode 100644
index 000000000000..64e21c5863d4
--- /dev/null
+++ b/usr.bin/msgs/msgs.c
@@ -0,0 +1,896 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * msgs - a user bulletin board program
+ *
+ * usage:
+ * msgs [fhlopq] [[-]number] to read messages
+ * msgs -s to place messages
+ * msgs -c [-days] to clean up the bulletin board
+ *
+ * prompt commands are:
+ * y print message
+ * n flush message, go to next message
+ * q flush message, quit
+ * p print message, turn on 'pipe thru more' mode
+ * P print message, turn off 'pipe thru more' mode
+ * - reprint last message
+ * s[-][<num>] [<filename>] save message
+ * m[-][<num>] mail with message in temp mbox
+ * x exit without flushing this message
+ * <num> print message number <num>
+ */
+
+#define V7 /* will look for TERM in the environment */
+#define OBJECT /* will object to messages without Subjects */
+/* #define REJECT */ /* will reject messages without Subjects
+ (OBJECT must be defined also) */
+/* #define UNBUFFERED *//* use unbuffered output */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <termcap.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include "pathnames.h"
+
+#define CMODE 0644 /* bounds file creation mode */
+#define SUPERUSER 0 /* superuser uid */
+#define DAEMON 1 /* daemon uid */
+#define NLINES 24 /* default number of lines/crt screen */
+#define NDAYS 21 /* default keep time for messages */
+#define DAYS *24*60*60 /* seconds/day */
+#define MSGSRC ".msgsrc" /* user's rc file */
+#define BOUNDS "bounds" /* message bounds file */
+#define NEXT "Next message? [yq]"
+#define MORE "More? [ynq]"
+#define NOMORE "(No more) [q] ?"
+
+static FILE *msgsrc;
+static FILE *newmsg;
+static const char *sep = "-";
+static char inbuf[BUFSIZ];
+static char fname[MAXPATHLEN];
+static char cmdbuf[MAXPATHLEN + MAXPATHLEN];
+static char subj[128];
+static char from[128];
+static char date[128];
+static char *ptr;
+static char *in;
+static bool local;
+static bool ruptible;
+static bool totty;
+static bool seenfrom;
+static bool seensubj;
+static bool blankline;
+static bool printing = false;
+static bool mailing = false;
+static bool quitit = false;
+static bool sending = false;
+static bool intrpflg = false;
+static uid_t uid;
+static int msg;
+static int prevmsg;
+static int lct;
+static int nlines;
+static int Lpp = 0;
+static time_t t;
+static time_t keep;
+
+/* option initialization */
+static bool hdrs = false;
+static bool qopt = false;
+static bool hush = false;
+static bool send_msg = false;
+static bool locomode = false;
+static bool use_pager = false;
+static bool clean = false;
+static bool lastcmd = false;
+static jmp_buf tstpbuf;
+
+static void ask(const char *);
+static void gfrsub(FILE *);
+static int linecnt(FILE *);
+static int next(char *);
+static char *nxtfld(char *);
+static void onsusp(int);
+static void onintr(int);
+static void prmesg(int);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ bool newrc, already;
+ int rcfirst = 0; /* first message to print (from .rc) */
+ int rcback = 0; /* amount to back off of rcfirst */
+ int firstmsg = 0, nextmsg = 0, lastmsg = 0;
+ int blast = 0;
+ struct stat buf; /* stat to check access of bounds */
+ FILE *bounds;
+ char *cp;
+
+#ifdef UNBUFFERED
+ setbuf(stdout, NULL);
+#endif
+ setlocale(LC_ALL, "");
+
+ time(&t);
+ if (setuid(uid = getuid()) != 0)
+ err(1, "setuid failed");
+ ruptible = (signal(SIGINT, SIG_IGN) == SIG_DFL);
+ if (ruptible)
+ signal(SIGINT, SIG_DFL);
+
+ argc--, argv++;
+ while (argc > 0) {
+ if (isdigit(argv[0][0])) { /* starting message # */
+ rcfirst = atoi(argv[0]);
+ }
+ else if (isdigit(argv[0][1])) { /* backward offset */
+ rcback = atoi( &( argv[0][1] ) );
+ }
+ else {
+ ptr = *argv;
+ while (*ptr) switch (*ptr++) {
+
+ case '-':
+ break;
+
+ case 'c':
+ if (uid != SUPERUSER && uid != DAEMON)
+ errx(1,
+ "only the super-user can use the c flag");
+ clean = true;
+ break;
+
+ case 'f': /* silently */
+ hush = true;
+ break;
+
+ case 'h': /* headers only */
+ hdrs = true;
+ break;
+
+ case 'l': /* local msgs only */
+ locomode = true;
+ break;
+
+ case 'o': /* option to save last message */
+ lastcmd = true;
+ break;
+
+ case 'p': /* pipe thru 'more' during long msgs */
+ use_pager = true;
+ break;
+
+ case 'q': /* query only */
+ qopt = true;
+ break;
+
+ case 's': /* sending TO msgs */
+ send_msg = true;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ argc--, argv++;
+ }
+
+ /*
+ * determine current message bounds
+ */
+ snprintf(fname, sizeof(fname), "%s/%s", _PATH_MSGS, BOUNDS);
+
+ /*
+ * Test access rights to the bounds file
+ * This can be a little tricky. if(send_msg), then
+ * we will create it. We assume that if(send_msg),
+ * then you have write permission there.
+ * Else, it better be there, or we bail.
+ */
+ if (!send_msg) {
+ if (stat(fname, &buf) < 0) {
+ if (!hush) {
+ err(errno, "%s", fname);
+ } else {
+ exit(1);
+ }
+ }
+ }
+ bounds = fopen(fname, "r");
+
+ if (bounds != NULL) {
+ fscanf(bounds, "%d %d\n", &firstmsg, &lastmsg);
+ fclose(bounds);
+ blast = lastmsg; /* save upper bound */
+ }
+
+ if (clean)
+ keep = t - (rcback? rcback : NDAYS) DAYS;
+
+ if (clean || bounds == NULL) { /* relocate message bounds */
+ struct dirent *dp;
+ struct stat stbuf;
+ bool seenany = false;
+ DIR *dirp;
+
+ dirp = opendir(_PATH_MSGS);
+ if (dirp == NULL)
+ err(errno, "%s", _PATH_MSGS);
+
+ firstmsg = 32767;
+ lastmsg = 0;
+
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){
+ cp = dp->d_name;
+ int i = 0;
+
+ if (dp->d_ino == 0)
+ continue;
+ if (dp->d_namlen == 0)
+ continue;
+
+ if (clean)
+ snprintf(inbuf, sizeof(inbuf), "%s/%s", _PATH_MSGS, cp);
+
+ while (isdigit(*cp))
+ i = i * 10 + *cp++ - '0';
+ if (*cp)
+ continue; /* not a message! */
+
+ if (clean) {
+ if (stat(inbuf, &stbuf) != 0)
+ continue;
+ if (stbuf.st_mtime < keep
+ && stbuf.st_mode&S_IWRITE) {
+ unlink(inbuf);
+ continue;
+ }
+ }
+
+ if (i > lastmsg)
+ lastmsg = i;
+ if (i < firstmsg)
+ firstmsg = i;
+ seenany = true;
+ }
+ closedir(dirp);
+
+ if (!seenany) {
+ if (blast != 0) /* never lower the upper bound! */
+ lastmsg = blast;
+ firstmsg = lastmsg + 1;
+ }
+ else if (blast > lastmsg)
+ lastmsg = blast;
+
+ if (!send_msg) {
+ bounds = fopen(fname, "w");
+ if (bounds == NULL)
+ err(errno, "%s", fname);
+ chmod(fname, CMODE);
+ fprintf(bounds, "%d %d\n", firstmsg, lastmsg);
+ fclose(bounds);
+ }
+ }
+
+ if (send_msg) {
+ /*
+ * Send mode - place msgs in _PATH_MSGS
+ */
+ bounds = fopen(fname, "w");
+ if (bounds == NULL)
+ err(errno, "%s", fname);
+
+ nextmsg = lastmsg + 1;
+ snprintf(fname, sizeof(fname), "%s/%d", _PATH_MSGS, nextmsg);
+ newmsg = fopen(fname, "w");
+ if (newmsg == NULL)
+ err(errno, "%s", fname);
+ chmod(fname, CMODE);
+
+ fprintf(bounds, "%d %d\n", firstmsg, nextmsg);
+ fclose(bounds);
+
+ sending = true;
+ if (ruptible)
+ signal(SIGINT, onintr);
+
+ if (isatty(fileno(stdin))) {
+ ptr = getpwuid(uid)->pw_name;
+ printf("Message %d:\nFrom %s %sSubject: ",
+ nextmsg, ptr, ctime(&t));
+ fflush(stdout);
+ fgets(inbuf, sizeof inbuf, stdin);
+ putchar('\n');
+ fflush(stdout);
+ fprintf(newmsg, "From %s %sSubject: %s\n",
+ ptr, ctime(&t), inbuf);
+ blankline = seensubj = true;
+ }
+ else
+ blankline = seensubj = false;
+ for (;;) {
+ fgets(inbuf, sizeof inbuf, stdin);
+ if (feof(stdin) || ferror(stdin))
+ break;
+ blankline = (blankline || (inbuf[0] == '\n'));
+ seensubj = (seensubj || (!blankline && (strncmp(inbuf, "Subj", 4) == 0)));
+ fputs(inbuf, newmsg);
+ }
+#ifdef OBJECT
+ if (!seensubj) {
+ printf("NOTICE: Messages should have a Subject field!\n");
+#ifdef REJECT
+ unlink(fname);
+#endif
+ exit(1);
+ }
+#endif
+ exit(ferror(stdin));
+ }
+ if (clean)
+ exit(0);
+
+ /*
+ * prepare to display messages
+ */
+ totty = (isatty(fileno(stdout)) != 0);
+ use_pager = use_pager && totty;
+
+ if ((cp = getenv("HOME")) == NULL || *cp == '\0') {
+ fprintf(stderr, "Error, no home directory!\n");
+ exit(1);
+ }
+ snprintf(fname, sizeof(fname), "%s/%s", cp, MSGSRC);
+ msgsrc = fopen(fname, "r");
+ if (msgsrc) {
+ newrc = false;
+ fscanf(msgsrc, "%d\n", &nextmsg);
+ fclose(msgsrc);
+ if (nextmsg > lastmsg+1) {
+ printf("Warning: bounds have been reset (%d, %d)\n",
+ firstmsg, lastmsg);
+ truncate(fname, (off_t)0);
+ newrc = true;
+ }
+ else if (!rcfirst)
+ rcfirst = nextmsg - rcback;
+ }
+ else
+ newrc = true;
+ msgsrc = fopen(fname, "r+");
+ if (msgsrc == NULL)
+ msgsrc = fopen(fname, "w");
+ if (msgsrc == NULL)
+ err(errno, "%s", fname);
+ if (rcfirst) {
+ if (rcfirst > lastmsg+1) {
+ printf("Warning: the last message is number %d.\n",
+ lastmsg);
+ rcfirst = nextmsg;
+ }
+ if (rcfirst > firstmsg)
+ firstmsg = rcfirst; /* don't set below first msg */
+ }
+ if (newrc) {
+ nextmsg = firstmsg;
+ rewind(msgsrc);
+ fprintf(msgsrc, "%d\n", nextmsg);
+ fflush(msgsrc);
+ }
+
+#ifdef V7
+ if (totty) {
+ struct winsize win;
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1)
+ Lpp = win.ws_row;
+ if (Lpp <= 0) {
+ if (tgetent(inbuf, getenv("TERM")) <= 0
+ || (Lpp = tgetnum("li")) <= 0) {
+ Lpp = NLINES;
+ }
+ }
+ }
+#endif
+ Lpp -= 6; /* for headers, etc. */
+
+ already = false;
+ prevmsg = firstmsg;
+ printing = true;
+ if (ruptible)
+ signal(SIGINT, onintr);
+
+ /*
+ * Main program loop
+ */
+ for (msg = firstmsg; msg <= lastmsg; msg++) {
+
+ snprintf(fname, sizeof(fname), "%s/%d", _PATH_MSGS, msg);
+ newmsg = fopen(fname, "r");
+ if (newmsg == NULL)
+ continue;
+
+ gfrsub(newmsg); /* get From and Subject fields */
+ if (locomode && !local) {
+ fclose(newmsg);
+ continue;
+ }
+
+ if (qopt) { /* This has to be located here */
+ printf("There are new messages.\n");
+ exit(0);
+ }
+
+ if (already && !hdrs)
+ putchar('\n');
+
+ /*
+ * Print header
+ */
+ if (totty)
+ signal(SIGTSTP, onsusp);
+ (void) setjmp(tstpbuf);
+ already = true;
+ nlines = 2;
+ if (seenfrom) {
+ printf("Message %d:\nFrom %s %s", msg, from, date);
+ nlines++;
+ }
+ if (seensubj) {
+ printf("Subject: %s", subj);
+ nlines++;
+ }
+ else {
+ if (seenfrom) {
+ putchar('\n');
+ nlines++;
+ }
+ while (nlines < 6
+ && fgets(inbuf, sizeof inbuf, newmsg)
+ && inbuf[0] != '\n') {
+ fputs(inbuf, stdout);
+ nlines++;
+ }
+ }
+
+ lct = linecnt(newmsg);
+ if (lct)
+ printf("(%d%sline%s) ", lct, seensubj? " " : " more ",
+ (lct == 1) ? "" : "s");
+
+ if (hdrs) {
+ printf("\n-----\n");
+ fclose(newmsg);
+ continue;
+ }
+
+ /*
+ * Ask user for command
+ */
+ if (totty)
+ ask(lct? MORE : (msg==lastmsg? NOMORE : NEXT));
+ else
+ inbuf[0] = 'y';
+ if (totty)
+ signal(SIGTSTP, SIG_DFL);
+cmnd:
+ in = inbuf;
+ switch (*in) {
+ case 'x':
+ /* FALLTHROUGH */
+ case 'X':
+ exit(0);
+ /* NOTREACHED */
+
+ case 'q':
+ /* FALLTHROUGH */
+ case 'Q':
+ quitit = true;
+ printf("--Postponed--\n");
+ exit(0);
+ /* NOTREACHED */
+
+ case 'n':
+ /* FALLTHROUGH */
+ case 'N':
+ if (msg >= nextmsg) sep = "Flushed";
+ prevmsg = msg;
+ break;
+
+ case 'p':
+ /* FALLTHROUGH */
+ case 'P':
+ use_pager = (*in++ == 'p');
+ /* FALLTHROUGH */
+ case '\n':
+ /* FALLTHROUGH */
+ case 'y':
+ default:
+ if (*in == '-') {
+ msg = prevmsg-1;
+ sep = "replay";
+ break;
+ }
+ if (isdigit(*in)) {
+ msg = next(in);
+ sep = in;
+ break;
+ }
+
+ prmesg(nlines + lct + (seensubj? 1 : 0));
+ prevmsg = msg;
+
+ }
+
+ printf("--%s--\n", sep);
+ sep = "-";
+ if (msg >= nextmsg) {
+ nextmsg = msg + 1;
+ rewind(msgsrc);
+ fprintf(msgsrc, "%d\n", nextmsg);
+ fflush(msgsrc);
+ }
+ if (newmsg)
+ fclose(newmsg);
+ if (quitit)
+ break;
+ }
+
+ /*
+ * Make sure .rc file gets updated
+ */
+ if (--msg >= nextmsg) {
+ nextmsg = msg + 1;
+ rewind(msgsrc);
+ fprintf(msgsrc, "%d\n", nextmsg);
+ fflush(msgsrc);
+ }
+ if (already && !quitit && lastcmd && totty) {
+ /*
+ * save or reply to last message?
+ */
+ msg = prevmsg;
+ ask(NOMORE);
+ if (inbuf[0] == '-' || isdigit(inbuf[0]))
+ goto cmnd;
+ }
+ if (!(already || hush || qopt))
+ printf("No new messages.\n");
+ exit(0);
+ /* NOTREACHED */
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: msgs [fhlopq] [[-]number]\n");
+ exit(1);
+}
+
+static void
+prmesg(int length)
+{
+ FILE *outf;
+ char *env_pager;
+
+ if (use_pager && length > Lpp) {
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ if ((env_pager = getenv("PAGER")) == NULL) {
+ snprintf(cmdbuf, sizeof(cmdbuf), _PATH_PAGER, Lpp);
+ } else {
+ snprintf(cmdbuf, sizeof(cmdbuf), "%s", env_pager);
+ }
+ outf = popen(cmdbuf, "w");
+ if (!outf)
+ outf = stdout;
+ else
+ setbuf(outf, (char *)NULL);
+ }
+ else
+ outf = stdout;
+
+ if (seensubj)
+ putc('\n', outf);
+
+ while (fgets(inbuf, sizeof inbuf, newmsg)) {
+ fputs(inbuf, outf);
+ if (ferror(outf)) {
+ clearerr(outf);
+ break;
+ }
+ }
+
+ if (outf != stdout) {
+ pclose(outf);
+ signal(SIGPIPE, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ }
+ else {
+ fflush(stdout);
+ }
+
+ /* force wait on output */
+ tcdrain(fileno(stdout));
+}
+
+static void
+onintr(int unused __unused)
+{
+ signal(SIGINT, onintr);
+ if (mailing)
+ unlink(fname);
+ if (sending) {
+ unlink(fname);
+ puts("--Killed--");
+ exit(1);
+ }
+ if (printing) {
+ putchar('\n');
+ if (hdrs)
+ exit(0);
+ sep = "Interrupt";
+ if (newmsg)
+ fseeko(newmsg, (off_t)0, SEEK_END);
+ intrpflg = true;
+ }
+}
+
+/*
+ * We have just gotten a susp. Suspend and prepare to resume.
+ */
+static void
+onsusp(int unused __unused)
+{
+ signal(SIGTSTP, SIG_DFL);
+ sigsetmask(0);
+ kill(0, SIGTSTP);
+ signal(SIGTSTP, onsusp);
+ if (!mailing)
+ longjmp(tstpbuf, 0);
+}
+
+static int
+linecnt(FILE *f)
+{
+ off_t oldpos = ftello(f);
+ int l = 0;
+ char lbuf[BUFSIZ];
+
+ while (fgets(lbuf, sizeof lbuf, f))
+ l++;
+ clearerr(f);
+ fseeko(f, oldpos, SEEK_SET);
+ return (l);
+}
+
+static int
+next(char *buf)
+{
+ int i;
+ sscanf(buf, "%d", &i);
+ sprintf(buf, "Goto %d", i);
+ return(--i);
+}
+
+static void
+ask(const char *prompt)
+{
+ char inch;
+ int n, cmsg, fd;
+ off_t oldpos;
+ FILE *cpfrom, *cpto;
+
+ printf("%s ", prompt);
+ fflush(stdout);
+ intrpflg = false;
+ (void) fgets(inbuf, sizeof inbuf, stdin);
+ if ((n = strlen(inbuf)) > 0 && inbuf[n - 1] == '\n')
+ inbuf[n - 1] = '\0';
+ if (intrpflg)
+ inbuf[0] = 'x';
+
+ /*
+ * Handle 'mail' and 'save' here.
+ */
+ if ((inch = inbuf[0]) == 's' || inch == 'm') {
+ if (inbuf[1] == '-')
+ cmsg = prevmsg;
+ else if (isdigit(inbuf[1]))
+ cmsg = atoi(&inbuf[1]);
+ else
+ cmsg = msg;
+ snprintf(fname, sizeof(fname), "%s/%d", _PATH_MSGS, cmsg);
+
+ oldpos = ftello(newmsg);
+
+ cpfrom = fopen(fname, "r");
+ if (!cpfrom) {
+ printf("Message %d not found\n", cmsg);
+ ask (prompt);
+ return;
+ }
+
+ if (inch == 's') {
+ in = nxtfld(inbuf);
+ if (*in) {
+ for (n=0; in[n] > ' '; n++) { /* sizeof fname? */
+ fname[n] = in[n];
+ }
+ fname[n] = '\0';
+ }
+ else
+ strcpy(fname, "Messages");
+ fd = open(fname, O_RDWR|O_EXCL|O_CREAT|O_APPEND);
+ }
+ else {
+ strcpy(fname, _PATH_TMP);
+ fd = mkstemp(fname);
+ if (fd != -1) {
+ snprintf(cmdbuf, sizeof(cmdbuf), _PATH_MAIL,
+ fname);
+ mailing = true;
+ }
+ }
+ if (fd == -1 || (cpto = fdopen(fd, "a")) == NULL) {
+ if (fd != -1)
+ close(fd);
+ warn("%s", fname);
+ mailing = false;
+ fseeko(newmsg, oldpos, SEEK_SET);
+ ask(prompt);
+ fclose(cpfrom);
+ return;
+ }
+
+ while ((n = fread(inbuf, 1, sizeof inbuf, cpfrom)))
+ fwrite(inbuf, 1, n, cpto);
+
+ fclose(cpfrom);
+ fclose(cpto);
+ fseeko(newmsg, oldpos, SEEK_SET);/* reposition current message */
+ if (inch == 's')
+ printf("Message %d saved in \"%s\"\n", cmsg, fname);
+ else {
+ system(cmdbuf);
+ unlink(fname);
+ mailing = false;
+ }
+ ask(prompt);
+ }
+}
+
+static void
+gfrsub(FILE *infile)
+{
+ off_t frompos;
+ int count;
+
+ seensubj = seenfrom = false;
+ local = true;
+ subj[0] = from[0] = date[0] = '\0';
+
+ /*
+ * Is this a normal message?
+ */
+ if (fgets(inbuf, sizeof inbuf, infile)) {
+ if (strncmp(inbuf, "From", 4)==0) {
+ /*
+ * expected form starts with From
+ */
+ seenfrom = true;
+ frompos = ftello(infile);
+ ptr = from;
+ in = nxtfld(inbuf);
+ if (*in) {
+ count = sizeof(from) - 1;
+ while (*in && *in > ' ' && count-- > 0) {
+ if (*in == ':' || *in == '@' ||
+ *in == '!')
+ local = false;
+ *ptr++ = *in++;
+ }
+ }
+ *ptr = '\0';
+ if (*(in = nxtfld(in)))
+ strlcpy(date, in, sizeof date);
+ else {
+ date[0] = '\n';
+ date[1] = '\0';
+ }
+ }
+ else {
+ /*
+ * not the expected form
+ */
+ rewind(infile);
+ return;
+ }
+ }
+ else
+ /*
+ * empty file ?
+ */
+ return;
+
+ /*
+ * look for Subject line until EOF or a blank line
+ */
+ while (fgets(inbuf, sizeof inbuf, infile)
+ && !(blankline = (inbuf[0] == '\n'))) {
+ /*
+ * extract Subject line
+ */
+ if (!seensubj && strncmp(inbuf, "Subj", 4)==0) {
+ seensubj = true;
+ frompos = ftello(infile);
+ strlcpy(subj, nxtfld(inbuf), sizeof subj);
+ }
+ }
+ if (!blankline)
+ /*
+ * ran into EOF
+ */
+ fseeko(infile, frompos, SEEK_SET);
+
+ if (!seensubj)
+ /*
+ * for possible use with Mail
+ */
+ strlcpy(subj, "(No Subject)\n", sizeof subj);
+}
+
+static char *
+nxtfld(char *s)
+{
+ if (*s) while (*s && !isspace(*s)) s++; /* skip over this field */
+ if (*s) while (*s && isspace(*s)) s++; /* find start of next field */
+ return (s);
+}
diff --git a/usr.bin/msgs/pathnames.h b/usr.bin/msgs/pathnames.h
new file mode 100644
index 000000000000..26e6019cd155
--- /dev/null
+++ b/usr.bin/msgs/pathnames.h
@@ -0,0 +1,36 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_MSGS "/var/msgs"
+#define _PATH_MAIL "/usr/bin/Mail -f %s"
+#define _PATH_PAGER "/usr/bin/less -%d"
+#undef _PATH_TMP
+#define _PATH_TMP "/tmp/msgXXXXXX"
diff --git a/usr.bin/mt/Makefile b/usr.bin/mt/Makefile
new file mode 100644
index 000000000000..405e195c856b
--- /dev/null
+++ b/usr.bin/mt/Makefile
@@ -0,0 +1,4 @@
+PROG= mt
+LIBADD= mt
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/mt/Makefile.depend b/usr.bin/mt/Makefile.depend
new file mode 100644
index 000000000000..5b7b0f27efa7
--- /dev/null
+++ b/usr.bin/mt/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libexpat \
+ lib/libmt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/mt/mt.1 b/usr.bin/mt/mt.1
new file mode 100644
index 000000000000..4cafdf4437c7
--- /dev/null
+++ b/usr.bin/mt/mt.1
@@ -0,0 +1,693 @@
+.\" Copyright (c) 1981, 1990, 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.
+.\"
+.Dd October 31, 2023
+.Dt MT 1
+.Os
+.Sh NAME
+.Nm mt
+.Nd magnetic tape manipulating program
+.Sh SYNOPSIS
+.Nm
+.Op Fl f Ar tapename
+.Ar command
+.Op Ar count
+.Nm
+.Op Fl f Ar tapename
+.Ar command
+.Ar argument
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to command a magnetic tape drive for operations
+other than reading or writing data.
+.Pp
+The
+.Fl f
+option's
+.Ar tapename
+overrides the
+.Ev TAPE
+environment variable described below.
+.Pp
+The available commands are listed below.
+Only as many
+characters as are required to uniquely identify a command
+need be specified.
+.Pp
+The following commands optionally take a
+.Ar count ,
+which defaults to 1.
+.Bl -tag -width ".Cm erase"
+.It Cm weof
+Write
+.Ar count
+end-of-file (EOF) marks at the current position.
+This returns when the file mark has been written to the media.
+.It Cm weofi
+Write
+.Ar count
+end-of-file (EOF) marks at the current position.
+This returns as soon as the command has been validated by the tape drive.
+.It Cm smk
+Write
+.Ar count
+setmarks at the current position (DDS drives only).
+.It Cm fsf
+Forward space
+.Ar count
+files.
+.It Cm fsr
+Forward space
+.Ar count
+records.
+.It Cm fss
+Forward space
+.Ar count
+setmarks (DDS drives only).
+.It Cm bsf
+Backward space
+.Ar count
+files.
+.It Cm bsr
+Backward space
+.Ar count
+records.
+.It Cm bss
+Backward space
+.Ar count
+setmarks (DDS drives only).
+.It Cm erase
+Erase the tape using a long (often very long) method.
+With a
+.Ar count
+of 0, it will erase the tape using a quick method.
+Operation is not guaranteed if the tape is not at its beginning.
+The tape will be at its beginning upon completion.
+.El
+.Pp
+The following commands ignore
+.Ar count .
+.Bl -tag -width ".Cm geteotmodel"
+.It Cm rdhpos
+Read the hardware block position.
+The block
+number reported is specific for that hardware only.
+With drive data compression especially,
+this position may have more to do with the amount of data
+sent to the drive than the amount of data written to tape.
+Some drives do not support this.
+.It Cm rdspos
+Read the SCSI logical block position.
+This typically is greater than the hardware position
+by the number of end-of-file marks.
+Some drives do not support this.
+.It Cm rewind
+Rewind the tape.
+.It Cm offline , rewoffl
+Rewind the tape and place the drive off line.
+Some drives are never off line.
+.It Cm load
+Load the tape into the drive.
+.It Cm retension
+Re-tension the tape.
+This winds the tape from the current position to the end
+and then to the beginning.
+This sometimes improves subsequent reading and writing,
+particularly for streaming drives.
+Some drives do not support this.
+.It Cm ostatus
+Output status information about the drive.
+For SCSI magnetic tape devices,
+the current operating modes of density, blocksize, and whether compression
+is enabled is reported.
+The current state of the driver (what it thinks that
+it is doing with the device) is reported.
+If the driver knows the relative
+position from BOT (in terms of filemarks and records), it outputs that.
+Note
+that this information is not definitive (only BOT, End of Recorded Media, and
+hardware or SCSI logical block position (if the drive supports such) are
+considered definitive tape positions).
+.Pp
+Also note that this is the old status command, and will be eliminated in
+favor of the new status command (see below) in a future release.
+.It Cm errstat
+Output (and clear) error status information about this device.
+For every normal
+operation (e.g., a read or a write) and every control operation (e.g,, a
+rewind), the driver stores up the last command executed and it is associated
+status and any residual counts (if any).
+This command retrieves and outputs this
+information.
+If possible, this also clears any latched error information.
+.It Cm geteotmodel
+Output the current EOT filemark model.
+The model states how
+many filemarks will be written at close if a tape was being written.
+.It Cm eod , eom
+Wind the tape to the end of the recorded data,
+typically after an EOF mark where another file may be written.
+.It Cm rblim
+Report the block limits of the tape drive, including the minimum and
+maximum block size, and the block granularity if any.
+.El
+.Pp
+The following commands may require an
+.Ar argument .
+.Bl -tag -width ".Cm seteotmodel"
+.It Cm sethpos
+Set the hardware block position.
+The
+.Ar argument
+is a hardware block number to which to position the tape.
+Some drives do not support this.
+.It Cm setspos
+Set the SCSI logical block position.
+The
+.Ar argument
+is a SCSI logical block number to which to position the tape.
+Some drives do not support this.
+.It Cm blocksize
+Set the block size for the drive.
+The
+.Ar argument
+is the number of bytes per block,
+except 0 commands the drive to use variable-length blocks.
+.It Cm seteotmodel
+Set the EOT filemark model to
+.Ar argument
+and output the old and new models.
+Typically this will be 2
+filemarks, but some devices (typically QIC cartridge drives) can
+only write 1 filemark.
+You may only choose a value of
+.Ar 1
+or
+.Ar 2 .
+.It Cm status
+Output status information about the drive.
+For SCSI magnetic tape devices,
+the current operating modes of density, blocksize, and whether compression
+is enabled is reported.
+The current state of the driver (what it thinks that
+it is doing with the device) is reported.
+.Pp
+If the driver knows the relative
+position from BOT (in terms of filemarks and records), it outputs that.
+If the tape drive supports the long form report of the
+.Tn SCSI
+READ POSITION command, the Reported File Number and Reported Record Number
+will be numbers other than -1, and there may be Flags reported as well.
+.Pp
+The BOP flag means that the logical position of the drive is at the
+beginning of the partition.
+.Pp
+The EOP flag means that the logical position of the drive is between Early
+Warning and End of Partition.
+.Pp
+The BPEW flag means that the logical position of the drive is in a
+Programmable Early Warning Zone or on the EOP side of Early Warning.
+.Pp
+Note that the Reported Record Number is the tape block or object number
+relative to the beginning of the partition.
+The Calculated Record Number is the tape block or object number relative
+to the previous file mark.
+.Pp
+Note
+that the Calculated File and Record Numbers are not definitive.
+The Reported File and Record Numbers are definitive, if they are numbers
+other than -1.
+.Bl -tag -width 6n
+.It Fl v
+Print additional status information, such as the maximum supported I/O
+size.
+.It Fl x
+Print all available status data to stdout in XML format.
+.El
+.It Cm getdensity
+Report density support information for the tape drive and any media that is
+loaded.
+Most drives will report at least basic density information similar to that
+reported by
+.Nm status
+command.
+Newer tape drives that conform to the T-10 SSC and newer tape
+specifications may report more detailed information about the types of
+tapes they support and the tape currently in the drive.
+.Bl -tag -width 6n
+.It Fl x
+Print all available density data to stdout in XML format.
+Because density information is currently included in the general status XML
+report used for
+.Nm
+status command, this will be the same XML output via
+.Do
+.Nm
+status
+.Fl x
+.Dc
+.El
+.It Cm param
+Display or set parameters.
+One of
+.Fl l ,
+.Fl s ,
+or
+.Fl x
+must be specified to indicate which operation to perform.
+See
+.Xr sa 4
+for more detailed information on the parameters.
+.Bl -tag -width 8n
+.It Fl l
+List parameters, values and descriptions.
+By default all parameters will be displayed.
+To display a specific parameter, specify the parameter with
+.Fl p .
+.It Fl p Ar name
+Specify the parameter name to list (with
+.Fl l )
+or set (with
+.Fl s ) .
+.It Fl q
+Enable quiet mode for parameter listing.
+This will suppress printing of parameter descriptions.
+.It Fl s Ar value
+Specify the parameter value to set.
+The general type of this argument (integer, unsigned integer, string) is
+determined by the type of the variable indicated by the
+.Xr sa 4
+driver.
+More detailed argument checking is done by the
+.Xr sa 4
+driver.
+.It Fl x
+Print out all parameter information in XML format.
+.El
+.It Cm protect
+Display or set drive protection parameters.
+This is used to control checking and reporting a per-block checksum for
+tape drives that support it.
+Some drives may only support some parameters.
+.Bl -tag -width 8n
+.It Fl b Ar 0|1
+Set the Recover Buffered Data Protected bit.
+If set, this indicates that checksums are transferred with the logical
+blocks transferred by the RECOVERED BUFFERED DATA
+.Tn SCSI
+command.
+.It Fl d
+Disable all protection information settings.
+.It Fl e
+Enable all protection information settings.
+The default protection method used is Reed-Solomon CRC (protection method
+1), as specified in ECMA-319.
+The default protection information length used with Reed-Solomon CRC is
+4 bytes.
+To enable all settings except one more setting, specify the
+.Fl e
+argument and then explicitly disable settings that you do not wish to
+enable.
+For example, specifying
+.Fl e
+.Fl w Ar 0
+will enable all settings except for LBP_W.
+.It Fl l
+List available protection parameters and their current settings.
+.It Fl L Ar len
+Set the length of the protection information in bytes.
+For Reed-Solomon CRC, the protection information length should be 4 bytes.
+.It Fl m Ar num
+Specify the numeric value for the protection method.
+The numeric value for Reed-Solomon CRC is 1.
+.It Fl r Ar 0|1
+Set the LBP_R parameter.
+When set, this indicates that each block read from the tape drive will
+have a checksum at the end.
+.It Fl v
+Enable verbose mode for parameter listing.
+This will include descriptions of each parameter.
+.It Fl w Ar 0|1
+Set the LBP_W parameter.
+When set, this indicates that each block written to the tape drive will have
+a checksum at the end.
+The drive will verify the checksum before writing the block to tape.
+.El
+.It Cm locate
+Set the tape drive's logical position.
+One of
+.Fl b ,
+.Fl e ,
+.Fl f ,
+or
+.Fl s
+must be specified to indicate the type of position.
+If the partition number is specified, the drive will first relocate to the
+given partition (if it exists) and then to the position indicated within
+that partition.
+If the partition number is not specified, the drive will relocate to the
+given position within the current partition.
+.Bl -tag -width 14n
+.It Fl b Ar block_addr
+Relocate to the given tape block or logical object identifier.
+Note that the block number is the Reported Record Number that is relative
+to the beginning of the partition (or beginning of tape).
+.It Fl e
+Relocate to the end of data.
+.It Fl f Ar fileno
+Relocate to the given file number.
+.It Fl p Ar partition
+Specify the partition to change to.
+.It Fl s Ar setmark
+Relocate to the given set mark.
+.El
+.It Cm comp
+Set the drive's compression mode.
+The non-numeric values of
+.Ar argument
+are:
+.Pp
+.Bl -tag -width 9n -compact
+.It off
+Turn compression off.
+.It on
+Turn compression on.
+.It none
+Same as
+.Ar off .
+.It enable
+Same as
+.Ar on .
+.It IDRC
+IBM Improved Data Recording Capability compression (0x10).
+.It DCLZ
+DCLZ compression algorithm (0x20).
+.El
+.Pp
+In addition to the above recognized compression keywords, the user can
+supply a numeric compression algorithm for the drive to use.
+In most
+cases, simply turning the compression
+.Sq on
+will have the desired effect of enabling the default compression algorithm
+supported by the drive.
+If this is not the case (see the
+.Cm status
+display to see which compression algorithm is currently in use), the user
+can manually specify one of the supported compression keywords (above), or
+supply a numeric compression value from the drive's specifications.
+.Pp
+Note that for some older tape drives (for example the Exabyte 8200 and 8500
+series drives) it is necessary to switch to a different density to tell the
+drive to record data in its compressed format.
+If the user attempts to turn compression on while the uncompressed density
+is selected, the drive will return an error.
+This is generally not an issue for modern tape drives.
+.It Cm density
+Set the density for the drive.
+For the density codes, see below.
+The density value could be given either numerically, or as a string,
+corresponding to the
+.Dq Reference
+field.
+If the string is abbreviated, it will be resolved in the order
+shown in the table, and the first matching entry will be used.
+If the
+given string and the resulting canonical density name do not match
+exactly, an informational message is output about what the given
+string has been taken for.
+.El
+.Pp
+The initial version of the density table below was taken from the
+.Sq Historical sequential access density codes
+table (A-1) in Revision 11 of the SCSI-3 Stream Device Commands (SSC)
+working draft, dated November 11, 1997.
+Subsequent additions have come from a number of sources.
+.Pp
+The density codes are:
+.Bd -literal -offset 2n
+0x0 default for device
+0xE reserved for ECMA
+
+Value Width Tracks Density Code Type Reference Note
+ mm in bpmm bpi
+0x01 12.7 (0.5) 9 32 (800) NRZI R X3.22-1983 2
+0x02 12.7 (0.5) 9 63 (1,600) PE R X3.39-1986 2
+0x03 12.7 (0.5) 9 246 (6,250) GCR R X3.54-1986 2
+0x05 6.3 (0.25) 4/9 315 (8,000) GCR C X3.136-1986 1,3
+0x06 12.7 (0.5) 9 126 (3,200) PE R X3.157-1987 2
+0x07 6.3 (0.25) 4 252 (6,400) IMFM C X3.116-1986 1
+0x08 3.81 (0.15) 4 315 (8,000) GCR CS X3.158-1987 1
+0x09 12.7 (0.5) 18 1,491 (37,871) GCR C X3.180 2
+0x0A 12.7 (0.5) 22 262 (6,667) MFM C X3B5/86-199 1
+0x0B 6.3 (0.25) 4 63 (1,600) PE C X3.56-1986 1
+0x0C 12.7 (0.5) 24 500 (12,690) GCR C HI-TC1 1,6
+0x0D 12.7 (0.5) 24 999 (25,380) GCR C HI-TC2 1,6
+0x0F 6.3 (0.25) 15 394 (10,000) GCR C QIC-120 1,6
+0x10 6.3 (0.25) 18 394 (10,000) GCR C QIC-150 1,6
+0x11 6.3 (0.25) 26 630 (16,000) GCR C QIC-320 1,6
+0x12 6.3 (0.25) 30 2,034 (51,667) RLL C QIC-1350 1,6
+0x13 3.81 (0.15) 1 2,400 (61,000) DDS CS X3B5/88-185A 5
+0x14 8.0 (0.315) 1 1,703 (43,245) RLL CS X3.202-1991 5,11
+0x15 8.0 (0.315) 1 1,789 (45,434) RLL CS ECMA TC17 5,12
+0x16 12.7 (0.5) 48 394 (10,000) MFM C X3.193-1990 1
+0x17 12.7 (0.5) 48 1,673 (42,500) MFM C X3B5/91-174 1
+0x18 12.7 (0.5) 112 1,673 (42,500) MFM C X3B5/92-50 1
+0x19 12.7 (0.5) 128 2,460 (62,500) RLL C DLTapeIII 6,7
+0x1A 12.7 (0.5) 128 3,214 (81,633) RLL C DLTapeIV(20) 6,7
+0x1B 12.7 (0.5) 208 3,383 (85,937) RLL C DLTapeIV(35) 6,7
+0x1C 6.3 (0.25) 34 1,654 (42,000) MFM C QIC-385M 1,6
+0x1D 6.3 (0.25) 32 1,512 (38,400) GCR C QIC-410M 1,6
+0x1E 6.3 (0.25) 30 1,385 (36,000) GCR C QIC-1000C 1,6
+0x1F 6.3 (0.25) 30 2,666 (67,733) RLL C QIC-2100C 1,6
+0x20 6.3 (0.25) 144 2,666 (67,733) RLL C QIC-6GB(M) 1,6
+0x21 6.3 (0.25) 144 2,666 (67,733) RLL C QIC-20GB(C) 1,6
+0x22 6.3 (0.25) 42 1,600 (40,640) GCR C QIC-2GB(C) ?
+0x23 6.3 (0.25) 38 2,666 (67,733) RLL C QIC-875M ?
+0x24 3.81 (0.15) 1 2,400 (61,000) CS DDS-2 5
+0x25 3.81 (0.15) 1 3,816 (97,000) CS DDS-3 5
+0x26 3.81 (0.15) 1 3,816 (97,000) CS DDS-4 5
+0x27 8.0 (0.315) 1 3,056 (77,611) RLL CS Mammoth 5
+0x28 12.7 (0.5) 36 1,491 (37,871) GCR C X3.224 1
+0x29 12.7 (0.5)
+0x2A
+0x2B 12.7 (0.5) 3 ? ? ? C X3.267 5
+0x40 12.7 (0.5) 384 4,800 (123,952) C LTO-1
+0x41 12.7 (0.5) 208 3,868 (98,250) RLL C DLTapeIV(40) 6,7
+0x42 12.7 (0.5) 512 7,398 (187,909) C LTO-2
+0x44 12.7 (0.5) 704 9,638 (244,805) C LTO-3
+0x46 12.7 (0.5) 896 12,725 (323,215) C LTO-4
+0x47 3.81 (0.25) ? 6,417 (163,000) CS DAT-72
+0x48 12.7 (0.5) 448 5,236 (133,000) PRML C SDLTapeI(110) 6,8,13
+0x49 12.7 (0.5) 448 7,598 (193,000) PRML C SDLTapeI(160) 6,8
+0x4A 12.7 (0.5) 768 ? PRML C T10000A 10
+0x4B 12.7 (0.5) 1152 ? PRML C T10000B 10
+0x4C 12.7 (0.5) 3584 ? PRML C T10000C 10
+0x4D 12.7 (0.5) 4608 ? PRML C T10000D 10
+0x51 12.7 (0.5) 512 11,800 (299,720) C 3592A1 (unencrypted)
+0x52 12.7 (0.5) 896 11,800 (299,720) C 3592A2 (unencrypted)
+0x53 12.7 (0.5) 1152 13,452 (341,681) C 3592A3 (unencrypted)
+0x54 12.7 (0.5) 2560 19,686 (500,024) C 3592A4 (unencrypted)
+0x55 12.7 (0.5) 5120 20,670 (525,018) C 3592A5 (unencrypted)
+0x56 12.7 (0.5) 7680 20,670 (525,018) C 3592B5 (unencrypted)
+0x57 12.7 (0.5) 8704 21,850 (554,990) C 3592A6 (unencrypted)
+0x58 12.7 (0.5) 1280 15,142 (384,607) C LTO-5
+0x59 12.7 (0.5)18944 21,850 (554,990) C 3592A7 (unencrypted)
+0x5A 12.7 (0.5) 2176 15,142 (384,607) C LTO-6
+0x5C 12.7 (0.5) 3584 19,107 (485,318) C LTO-7
+0x5D 12.7 (0.5) 5376 19,107 (485,318) C LTO-M8 14
+0x5E 12.7 (0.5) 6656 20,669 (524,993) C LTO-8
+0x60 12.7 (0.5) 8960 23,031 (584,987) C LTO-9
+0x71 12.7 (0.5) 512 11,800 (299,720) C 3592A1 (encrypted)
+0x72 12.7 (0.5) 896 11,800 (299,720) C 3592A2 (encrypted)
+0x73 12.7 (0.5) 1152 13,452 (341,681) C 3592A3 (encrypted)
+0x74 12.7 (0.5) 2560 19,686 (500,024) C 3592A4 (encrypted)
+0x75 12.7 (0.5) 5120 20,670 (525,018) C 3592A5 (encrypted)
+0x76 12.7 (0.5) 7680 20,670 (525,018) C 3592B5 (encrypted)
+0x77 12.7 (0.5) 8704 21,850 (554,990) C 3592A6 (encrypted)
+0x79 12.7 (0.5)18944 21,850 (554,990) C 3592A7 (encrypted)
+0x8c 8.0 (0.315) 1 1,789 (45,434) RLL CS EXB-8500c 5,9
+0x90 8.0 (0.315) 1 1,703 (43,245) RLL CS EXB-8200c 5,9
+.Ed
+.Bd -literal -offset 2n
+Code Description Type Description
+---- -------------------------------------- ---- -----------
+NRZI Non return to zero, change on ones R Reel-to-reel
+GCR Group code recording C Cartridge
+PE Phase encoded CS Cassette
+IMFM Inverted modified frequency modulation
+MFM Modified frequency modulation
+DDS DAT data storage
+RLL Run length limited
+PRML Partial Response Maximum Likelihood
+.Ed
+.Bd -literal -offset 2n
+NOTES
+1. Serial recorded.
+2. Parallel recorded.
+3. Old format known as QIC-11.
+5. Helical scan.
+6. This is not an American National Standard. The reference is based
+ on an industry standard definition of the media format.
+7. DLT recording: serially recorded track pairs (DLTapeIII and
+ DLTapeIV(20)), or track quads (DLTapeIV(35) and DLTapeIV(40)).
+8. Super DLT (SDLT) recording: 56 serially recorded logical tracks
+ with 8 physical tracks each.
+9. Vendor-specific Exabyte density code for compressed format.
+10. bpi/bpmm values for the Oracle/StorageTek T10000 tape drives are
+ not listed in the manual. Someone with access to a drive can
+ supply the necessary values by running 'mt getdensity'.
+11. This is Exabyte 8200 uncompressed format. The compressed format
+ density code is 0x90.
+12. This is Exabyte 8500 uncompressed format. The compressed format
+ density code is 0x8c.
+13. This density code (0x48) was also used for DAT-160.
+14. Officially known as LTO-8 Type M, abbreviated M8. This is a pristine
+ LTO-7 cartridge initialized with a higher density format by an LTO-8
+ drive. It cannot be read by an LTO-7 drive. Uncompressed capacity
+ is 9TB, compared to 6TB for LTO-7 and 12TB for LTO-8.
+.Ed
+.Bd -literal -offset 2n
+NOTE ON QIC STREAMERS
+
+The following is a table of Data Cartridge types as used in the 1/4 inch
+tape drives such as the Archive Viper 150, Wangtek 5525ES, and Tandberg
+TDC4220 tape drives:
+
+Value Reference Format Cartridge Type Capacity Tracks Length
+----- --------- ------ -------------- -------- ------ ------
+
+0x05 QIC-11 DC300 15MB 4 300ft
+0x05 QIC-11 DC300XL/P 20MB 4 450ft
+0x05 QIC-11 DC600 27MB 4 600ft
+0x05 X3.136-1986 QIC-24 DC615A 15MB 9 150ft
+0x05 X3.136-1986 QIC-24 DC300XL/P 45MB 9 450ft
+0x05 X3.136-1986 QIC-24 DC600A 60MB 9 600ft
+0x0F QIC-120 QIC-120 DC600A/DC6150 120MB 15 620ft
+0x10 QIC-150 QIC-150 DC600XTD/DC6150 150MB 18 620ft
+0x10 QIC-150 QIC-150 DC6250 250MB 18 1,020ft
+0x11 QIC-320 QIC-525 DC6320 320MB 26 620ft
+0x11 QIC-320 QIC-525 DC6525 525MB 26 1,020ft
+0x1E QIC-1000C QIC-1000 DC9100/DL9135 1.0GB 30 760ft
+0x1E QIC-1000C QIC-1000 DC9150 1.2GB 30 950ft
+0x22 QIC-2GB(C) QIC-2GB DC9200 2.0GB 42 950ft
+0x22 QIC-2GB(C) QIC-2GB DC9250 2.5GB 42 1,200ft
+.Ed
+.Pp
+Notes:
+.Pp
+QIC-24, QIC-120, QIC-150 use fixed blocksize of 512 bytes, QIC-525, QIC-1000
+and QIC-2GB can use blocksize of 1,024 bytes.
+DDS (DAT) drives generally use variable blocks.
+.Pp
+QIC-02 and QIC-36 are interface standards for tape drives.
+The QIC-02 and QIC-36 streamers such as the Wangtek 5250EQ are otherwise
+identical to their SCSI versions (i.e.: Wangtek 5250ES).
+.Pp
+It seems that the 150MB and larger streamers cannot write QIC-24 9 track
+formats, only read them.
+.Pp
+DC600A cartridges marked "10,000ftpi" can only be used as QIC-11, QIC-24,
+and QIC-120 format.
+DC600A cartridges marked 12,500ftpi can be used as both QIC-120 and QIC-150
+format.
+.Pp
+Some manufacturers do not use "DC" on their cartridges.
+Verbatim uses DL, Maxell uses MC, Sony uses QD, Quill uses DQ.
+.Pp
+3M/Imation & Fuji use DC.
+Thus a DL6250, MC-6250, QD6250, DQ6250 are all identical media to a DC6250.
+.Pp
+QIC tape media is not "connected" to the take up reels and will de-spool
+if the tape drive has dust covering the light sensor that looks for the end
+of tape holes in the media.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev TAPE"
+.It Ev TAPE
+This is the pathname of the tape drive.
+The default (if the variable is unset, but not if it is null) is
+.Pa /dev/nsa0 .
+It may be overridden with the
+.Fl f
+option.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /dev/*sa[0-9]*" -compact
+.It Pa /dev/*sa[0-9]*
+SCSI magnetic tape interface
+.El
+.Sh DIAGNOSTICS
+The exit status will be 0 when the drive operations were successful,
+2 when the drive operations were unsuccessful, and 1 for other
+problems like an unrecognized command or a missing drive device.
+.Sh COMPATIBILITY
+Some undocumented commands support old software.
+.Sh SEE ALSO
+.Xr dd 1 ,
+.Xr ioctl 2 ,
+.Xr mtio 4 ,
+.Xr sa 4 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Pp
+Extensions regarding the
+.Xr st 4
+driver appeared in
+.Bx 386 0.1
+as a separate
+.Nm st
+command, and have been merged into the
+.Nm
+command in
+.Fx 2.1 .
+.Pp
+The former
+.Cm eof
+command that used to be a synonym for
+.Cm weof
+has been abandoned in
+.Fx 2.1
+since it was often confused with
+.Cm eom ,
+which is fairly dangerous.
+.Sh BUGS
+The utility cannot be interrupted or killed during a long erase
+(which can be longer than an hour), and it is easy to forget
+that the default erase is long.
+.Pp
+Hardware block numbers do not always correspond to blocks on the tape
+when the drive uses internal compression.
+.Pp
+Erasure is not guaranteed if the tape is not at its beginning.
+.Pp
+Tape-related documentation is poor, here and elsewhere.
diff --git a/usr.bin/mt/mt.c b/usr.bin/mt/mt.c
new file mode 100644
index 000000000000..266bf88c0f72
--- /dev/null
+++ b/usr.bin/mt/mt.c
@@ -0,0 +1,1583 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+/*-
+ * Copyright (c) 2013, 2014, 2015 Spectra Logic Corporation
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * Authors: Ken Merry (Spectra Logic Corporation)
+ */
+
+/*
+ * mt --
+ * magnetic tape manipulation program
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/queue.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include <bsdxml.h>
+#include <mtlib.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_periph.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_sa.h>
+
+/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */
+/* c_flags */
+#define NEED_2ARGS 0x01
+#define ZERO_ALLOWED 0x02
+#define IS_DENSITY 0x04
+#define DISABLE_THIS 0x08
+#define IS_COMP 0x10
+#define USE_GETOPT 0x20
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef MAX
+#define MAX(a, b) (a > b) ? a : b
+#endif
+#define MT_PLURAL(a) (a == 1) ? "" : "s"
+
+typedef enum {
+ MT_CMD_NONE = MTLOAD + 1,
+ MT_CMD_PROTECT,
+ MT_CMD_GETDENSITY
+} mt_commands;
+
+static const struct commands {
+ const char *c_name;
+ unsigned long c_code;
+ int c_ronly;
+ int c_flags;
+} com[] = {
+ { "bsf", MTBSF, 1, 0 },
+ { "bsr", MTBSR, 1, 0 },
+ /* XXX FreeBSD considered "eof" dangerous, since it's being
+ confused with "eom" (and is an alias for "weof" anyway) */
+ { "eof", MTWEOF, 0, DISABLE_THIS },
+ { "fsf", MTFSF, 1, 0 },
+ { "fsr", MTFSR, 1, 0 },
+ { "offline", MTOFFL, 1, 0 },
+ { "load", MTLOAD, 1, 0 },
+ { "rewind", MTREW, 1, 0 },
+ { "rewoffl", MTOFFL, 1, 0 },
+ { "ostatus", MTNOP, 1, 0 },
+ { "weof", MTWEOF, 0, ZERO_ALLOWED },
+ { "weofi", MTWEOFI, 0, ZERO_ALLOWED },
+ { "erase", MTERASE, 0, ZERO_ALLOWED},
+ { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED },
+ { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY },
+ { "eom", MTEOD, 1, 0 },
+ { "eod", MTEOD, 1, 0 },
+ { "smk", MTWSS, 0, 0 },
+ { "wss", MTWSS, 0, 0 },
+ { "fss", MTFSS, 1, 0 },
+ { "bss", MTBSS, 1, 0 },
+ { "comp", MTCOMP, 0, NEED_2ARGS|ZERO_ALLOWED|IS_COMP },
+ { "retension", MTRETENS, 1, 0 },
+ { "rdhpos", MTIOCRDHPOS, 0, 0 },
+ { "rdspos", MTIOCRDSPOS, 0, 0 },
+ { "sethpos", MTIOCHLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED },
+ { "setspos", MTIOCSLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED },
+ { "errstat", MTIOCERRSTAT, 0, 0 },
+ { "setmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED },
+ { "seteotmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED },
+ { "getmodel", MTIOCGETEOTMODEL, 0, 0 },
+ { "geteotmodel", MTIOCGETEOTMODEL, 0, 0 },
+ { "rblim", MTIOCRBLIM, 0, 0},
+ { "getdensity", MT_CMD_GETDENSITY, 0, USE_GETOPT},
+ { "status", MTIOCEXTGET, 0, USE_GETOPT },
+ { "locate", MTIOCEXTLOCATE, 0, USE_GETOPT },
+ { "param", MTIOCPARAMGET, 0, USE_GETOPT },
+ { "protect", MT_CMD_PROTECT, 0, USE_GETOPT },
+ { NULL, 0, 0, 0 }
+};
+
+
+static const char *getblksiz(int);
+static void printreg(const char *, u_int, const char *);
+static void status(struct mtget *);
+static void usage(void) __dead2;
+const char *get_driver_state_str(int dsreg);
+static void st_status (struct mtget *);
+static int mt_locate(int argc, char **argv, int mtfd, const char *tape);
+static int nstatus_print(int argc, char **argv, char *xml_str,
+ struct mt_status_data *status_data);
+static int mt_xml_cmd(unsigned long cmd, int argc, char **argv, int mtfd,
+ const char *tape);
+static int mt_print_density_entry(struct mt_status_entry *density_root, int indent);
+static int mt_print_density_report(struct mt_status_entry *report_root, int indent);
+static int mt_print_density(struct mt_status_entry *density_root, int indent);
+static int mt_getdensity(int argc, char **argv, char *xml_str,
+ struct mt_status_data *status_data);
+static int mt_set_param(int mtfd, struct mt_status_data *status_data,
+ char *param_name, char *param_value);
+static int mt_protect(int argc, char **argv, int mtfd,
+ struct mt_status_data *status_data);
+static int mt_param(int argc, char **argv, int mtfd, char *xml_str,
+ struct mt_status_data *status_data);
+static const char *denstostring (int d);
+static u_int32_t stringtocomp(const char *s);
+static const char *comptostring(u_int32_t comp);
+static void warn_eof(void);
+
+int
+main(int argc, char *argv[])
+{
+ const struct commands *comp;
+ struct mtget mt_status;
+ struct mtop mt_com;
+ int ch, len, mtfd;
+ const char *p, *tape;
+
+ bzero(&mt_com, sizeof(mt_com));
+
+ if ((tape = getenv("TAPE")) == NULL)
+ tape = DEFTAPE;
+
+ while ((ch = getopt(argc, argv, "f:t:")) != -1)
+ switch(ch) {
+ case 'f':
+ case 't':
+ tape = optarg;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ len = strlen(p = *argv++);
+ for (comp = com;; comp++) {
+ if (comp->c_name == NULL)
+ errx(1, "%s: unknown command", p);
+ if (strncmp(p, comp->c_name, len) == 0)
+ break;
+ }
+ if((comp->c_flags & NEED_2ARGS) && argc != 2)
+ usage();
+ if(comp->c_flags & DISABLE_THIS) {
+ warn_eof();
+ }
+ if (comp->c_flags & USE_GETOPT) {
+ argc--;
+ optind = 0;
+ }
+
+ if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0)
+ err(1, "%s", tape);
+ if (comp->c_code != MTNOP) {
+ mt_com.mt_op = comp->c_code;
+ if (*argv) {
+ if (!isdigit(**argv) &&
+ (comp->c_flags & IS_DENSITY)) {
+ const char *dcanon;
+ mt_com.mt_count = mt_density_num(*argv);
+ if (mt_com.mt_count == 0)
+ errx(1, "%s: unknown density", *argv);
+ dcanon = denstostring(mt_com.mt_count);
+ if (strcmp(dcanon, *argv) != 0)
+ printf(
+ "Using \"%s\" as an alias for %s\n",
+ *argv, dcanon);
+ p = "";
+ } else if (!isdigit(**argv) &&
+ (comp->c_flags & IS_COMP)) {
+
+ mt_com.mt_count = stringtocomp(*argv);
+ if ((u_int32_t)mt_com.mt_count == 0xf0f0f0f0)
+ errx(1, "%s: unknown compression",
+ *argv);
+ p = "";
+ } else if ((comp->c_flags & USE_GETOPT) == 0) {
+ char *q;
+ /* allow for hex numbers; useful for density */
+ mt_com.mt_count = strtol(*argv, &q, 0);
+ p = q;
+ }
+ if (((comp->c_flags & USE_GETOPT) == 0)
+ && (((mt_com.mt_count <=
+ ((comp->c_flags & ZERO_ALLOWED)? -1: 0))
+ && ((comp->c_flags & IS_COMP) == 0))
+ || *p))
+ errx(1, "%s: illegal count", *argv);
+ }
+ else
+ mt_com.mt_count = 1;
+ switch (comp->c_code) {
+ case MTIOCERRSTAT:
+ {
+ unsigned int i;
+ union mterrstat umn;
+ struct scsi_tape_errors *s = &umn.scsi_errstat;
+
+ if (ioctl(mtfd, comp->c_code, (caddr_t)&umn) < 0)
+ err(2, "%s", tape);
+ (void)printf("Last I/O Residual: %u\n", s->io_resid);
+ (void)printf(" Last I/O Command:");
+ for (i = 0; i < sizeof (s->io_cdb); i++)
+ (void)printf(" %02X", s->io_cdb[i]);
+ (void)printf("\n");
+ (void)printf(" Last I/O Sense:\n\n\t");
+ for (i = 0; i < sizeof (s->io_sense); i++) {
+ (void)printf(" %02X", s->io_sense[i]);
+ if (((i + 1) & 0xf) == 0) {
+ (void)printf("\n\t");
+ }
+ }
+ (void)printf("\n");
+ (void)printf("Last Control Residual: %u\n",
+ s->ctl_resid);
+ (void)printf(" Last Control Command:");
+ for (i = 0; i < sizeof (s->ctl_cdb); i++)
+ (void)printf(" %02X", s->ctl_cdb[i]);
+ (void)printf("\n");
+ (void)printf(" Last Control Sense:\n\n\t");
+ for (i = 0; i < sizeof (s->ctl_sense); i++) {
+ (void)printf(" %02X", s->ctl_sense[i]);
+ if (((i + 1) & 0xf) == 0) {
+ (void)printf("\n\t");
+ }
+ }
+ (void)printf("\n\n");
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCRDHPOS:
+ case MTIOCRDSPOS:
+ {
+ u_int32_t block;
+ if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0)
+ err(2, "%s", tape);
+ (void)printf("%s: %s block location %u\n", tape,
+ (comp->c_code == MTIOCRDHPOS)? "hardware" :
+ "logical", block);
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCSLOCATE:
+ case MTIOCHLOCATE:
+ {
+ u_int32_t block = (u_int32_t)mt_com.mt_count;
+ if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0)
+ err(2, "%s", tape);
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCGETEOTMODEL:
+ {
+ u_int32_t om;
+ if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0)
+ err(2, "%s", tape);
+ (void)printf("%s: the model is %u filemar%s at EOT\n",
+ tape, om, (om > 1)? "ks" : "k");
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCSETEOTMODEL:
+ {
+ u_int32_t om, nm = (u_int32_t)mt_com.mt_count;
+ if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0)
+ err(2, "%s", tape);
+ if (ioctl(mtfd, comp->c_code, (caddr_t)&nm) < 0)
+ err(2, "%s", tape);
+ (void)printf("%s: old model was %u filemar%s at EOT\n",
+ tape, om, (om > 1)? "ks" : "k");
+ (void)printf("%s: new model is %u filemar%s at EOT\n",
+ tape, nm, (nm > 1)? "ks" : "k");
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCRBLIM:
+ {
+ struct mtrblim rblim;
+
+ bzero(&rblim, sizeof(rblim));
+
+ if (ioctl(mtfd, MTIOCRBLIM, (caddr_t)&rblim) < 0)
+ err(2, "%s", tape);
+ (void)printf("%s:\n"
+ " min blocksize %u byte%s\n"
+ " max blocksize %u byte%s\n"
+ " granularity %u byte%s\n",
+ tape, rblim.min_block_length,
+ MT_PLURAL(rblim.min_block_length),
+ rblim.max_block_length,
+ MT_PLURAL(rblim.max_block_length),
+ (1 << rblim.granularity),
+ MT_PLURAL((1 << rblim.granularity)));
+ exit(0);
+ /* NOTREACHED */
+ }
+ case MTIOCPARAMGET:
+ case MTIOCEXTGET:
+ case MT_CMD_PROTECT:
+ case MT_CMD_GETDENSITY:
+ {
+ int retval = 0;
+
+ retval = mt_xml_cmd(comp->c_code, argc, argv, mtfd,
+ tape);
+
+ exit(retval);
+ }
+ case MTIOCEXTLOCATE:
+ {
+ int retval = 0;
+
+ retval = mt_locate(argc, argv, mtfd, tape);
+
+ exit(retval);
+ }
+ default:
+ break;
+ }
+ if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0)
+ err(1, "%s: %s", tape, comp->c_name);
+ } else {
+ if (ioctl(mtfd, MTIOCGET, &mt_status) < 0)
+ err(1, NULL);
+ status(&mt_status);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+
+static const struct tape_desc {
+ short t_type; /* type of magtape device */
+ const char *t_name; /* printing name */
+ const char *t_dsbits; /* "drive status" register */
+ const char *t_erbits; /* "error" register */
+} tapes[] = {
+ { MT_ISAR, "SCSI tape drive", 0, 0 },
+ { 0, NULL, 0, 0 }
+};
+
+/*
+ * Interpret the status buffer returned
+ */
+static void
+status(struct mtget *bp)
+{
+ const struct tape_desc *mt;
+
+ for (mt = tapes;; mt++) {
+ if (mt->t_type == 0) {
+ (void)printf("%d: unknown tape drive type\n",
+ bp->mt_type);
+ return;
+ }
+ if (mt->t_type == bp->mt_type)
+ break;
+ }
+ if(mt->t_type == MT_ISAR)
+ st_status(bp);
+ else {
+ (void)printf("%s tape drive, residual=%d\n",
+ mt->t_name, bp->mt_resid);
+ printreg("ds", (unsigned short)bp->mt_dsreg, mt->t_dsbits);
+ printreg("\ner", (unsigned short)bp->mt_erreg, mt->t_erbits);
+ (void)putchar('\n');
+ }
+}
+
+/*
+ * Print a register a la the %b format of the kernel's printf.
+ */
+static void
+printreg(const char *s, u_int v, const char *bits)
+{
+ int i, any = 0;
+ char c;
+
+ if (bits && *bits == 8)
+ printf("%s=%o", s, v);
+ else
+ printf("%s=%x", s, v);
+ if (!bits)
+ return;
+ bits++;
+ if (v && bits) {
+ putchar('<');
+ while ((i = *bits++)) {
+ if (v & (1 << (i-1))) {
+ if (any)
+ putchar(',');
+ any = 1;
+ for (; (c = *bits) > 32; bits++)
+ putchar(c);
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ putchar('>');
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: mt [-f device] command [count]\n");
+ exit(1);
+}
+
+static const struct compression_types {
+ u_int32_t comp_number;
+ const char *name;
+} comp_types[] = {
+ { 0x00, "none" },
+ { 0x00, "off" },
+ { 0x10, "IDRC" },
+ { 0x20, "DCLZ" },
+ { 0xffffffff, "enable" },
+ { 0xffffffff, "on" },
+ { 0xf0f0f0f0, NULL}
+};
+
+static const char *
+denstostring(int d)
+{
+ static char buf[20];
+ const char *name = mt_density_name(d);
+
+ if (name == NULL)
+ sprintf(buf, "0x%02x", d);
+ else
+ sprintf(buf, "0x%02x:%s", d, name);
+ return buf;
+}
+
+static const char *
+getblksiz(int bs)
+{
+ static char buf[25];
+ if (bs == 0)
+ return "variable";
+ else {
+ sprintf(buf, "%d bytes", bs);
+ return buf;
+ }
+}
+
+static const char *
+comptostring(u_int32_t comp)
+{
+ static char buf[20];
+ const struct compression_types *ct;
+
+ if (comp == MT_COMP_DISABLED)
+ return "disabled";
+ else if (comp == MT_COMP_UNSUPP)
+ return "unsupported";
+
+ for (ct = comp_types; ct->name; ct++)
+ if (ct->comp_number == comp)
+ break;
+
+ if (ct->comp_number == 0xf0f0f0f0) {
+ sprintf(buf, "0x%x", comp);
+ return(buf);
+ } else
+ return(ct->name);
+}
+
+static u_int32_t
+stringtocomp(const char *s)
+{
+ const struct compression_types *ct;
+ size_t l = strlen(s);
+
+ for (ct = comp_types; ct->name; ct++)
+ if (strncasecmp(ct->name, s, l) == 0)
+ break;
+
+ return(ct->comp_number);
+}
+
+static struct driver_state {
+ int dsreg;
+ const char *desc;
+} driver_states[] = {
+ { MTIO_DSREG_REST, "at rest" },
+ { MTIO_DSREG_RBSY, "Communicating with drive" },
+ { MTIO_DSREG_WR, "Writing" },
+ { MTIO_DSREG_FMK, "Writing Filemarks" },
+ { MTIO_DSREG_ZER, "Erasing" },
+ { MTIO_DSREG_RD, "Reading" },
+ { MTIO_DSREG_FWD, "Spacing Forward" },
+ { MTIO_DSREG_REV, "Spacing Reverse" },
+ { MTIO_DSREG_POS, "Hardware Positioning (direction unknown)" },
+ { MTIO_DSREG_REW, "Rewinding" },
+ { MTIO_DSREG_TEN, "Retensioning" },
+ { MTIO_DSREG_UNL, "Unloading" },
+ { MTIO_DSREG_LD, "Loading" },
+};
+
+const char *
+get_driver_state_str(int dsreg)
+{
+ unsigned int i;
+
+ for (i = 0; i < (sizeof(driver_states)/sizeof(driver_states[0])); i++) {
+ if (driver_states[i].dsreg == dsreg)
+ return (driver_states[i].desc);
+ }
+
+ return (NULL);
+}
+
+static void
+st_status(struct mtget *bp)
+{
+ printf("Mode Density Blocksize bpi "
+ "Compression\n"
+ "Current: %-17s %-12s %-7d %s\n"
+ "---------available modes---------\n"
+ "0: %-17s %-12s %-7d %s\n"
+ "1: %-17s %-12s %-7d %s\n"
+ "2: %-17s %-12s %-7d %s\n"
+ "3: %-17s %-12s %-7d %s\n",
+ denstostring(bp->mt_density), getblksiz(bp->mt_blksiz),
+ mt_density_bp(bp->mt_density, TRUE), comptostring(bp->mt_comp),
+ denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0),
+ mt_density_bp(bp->mt_density0, TRUE), comptostring(bp->mt_comp0),
+ denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1),
+ mt_density_bp(bp->mt_density1, TRUE), comptostring(bp->mt_comp1),
+ denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2),
+ mt_density_bp(bp->mt_density2, TRUE), comptostring(bp->mt_comp2),
+ denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3),
+ mt_density_bp(bp->mt_density3, TRUE), comptostring(bp->mt_comp3));
+
+ if (bp->mt_dsreg != MTIO_DSREG_NIL) {
+ const char sfmt[] = "Current Driver State: %s.\n";
+ printf("---------------------------------\n");
+ const char *state_str;
+
+ state_str = get_driver_state_str(bp->mt_dsreg);
+ if (state_str == NULL) {
+ char foo[32];
+ (void) sprintf(foo, "Unknown state 0x%x", bp->mt_dsreg);
+ printf(sfmt, foo);
+ } else {
+ printf(sfmt, state_str);
+ }
+ }
+ if (bp->mt_resid == 0 && bp->mt_fileno == (daddr_t) -1 &&
+ bp->mt_blkno == (daddr_t) -1)
+ return;
+ printf("---------------------------------\n");
+ printf("File Number: %d\tRecord Number: %d\tResidual Count %d\n",
+ bp->mt_fileno, bp->mt_blkno, bp->mt_resid);
+}
+
+static int
+mt_locate(int argc, char **argv, int mtfd, const char *tape)
+{
+ struct mtlocate mtl;
+ uint64_t logical_id = 0;
+ mt_locate_dest_type dest_type = MT_LOCATE_DEST_FILE;
+ int eod = 0, explicit = 0, immediate = 0;
+ int64_t partition = 0;
+ int block_addr_set = 0, partition_set = 0, file_set = 0, set_set = 0;
+ int c, retval;
+
+ retval = 0;
+ bzero(&mtl, sizeof(mtl));
+
+ while ((c = getopt(argc, argv, "b:eEf:ip:s:")) != -1) {
+ switch (c) {
+ case 'b':
+ /* Block address */
+ logical_id = strtoull(optarg, NULL, 0);
+ dest_type = MT_LOCATE_DEST_OBJECT;
+ block_addr_set = 1;
+ break;
+ case 'e':
+ /* end of data */
+ eod = 1;
+ dest_type = MT_LOCATE_DEST_EOD;
+ break;
+ case 'E':
+ /*
+ * XXX KDM explicit address mode. Should we even
+ * allow this, since the driver doesn't operate in
+ * explicit address mode?
+ */
+ explicit = 1;
+ break;
+ case 'f':
+ /* file number */
+ logical_id = strtoull(optarg, NULL, 0);
+ dest_type = MT_LOCATE_DEST_FILE;
+ file_set = 1;
+ break;
+ case 'i':
+ /*
+ * Immediate address mode. XXX KDM do we want to
+ * implement this? The other commands in the
+ * tape driver will need to be able to handle this.
+ */
+ immediate = 1;
+ break;
+ case 'p':
+ /*
+ * Change partition to the given partition.
+ */
+ partition = strtol(optarg, NULL, 0);
+ partition_set = 1;
+ break;
+ case 's':
+ /* Go to the given set mark */
+ logical_id = strtoull(optarg, NULL, 0);
+ dest_type = MT_LOCATE_DEST_SET;
+ set_set = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * These options are mutually exclusive. The user may only specify
+ * one.
+ */
+ if ((block_addr_set + file_set + eod + set_set) != 1)
+ errx(1, "You must specify only one of -b, -f, -e, or -s");
+
+ mtl.dest_type = dest_type;
+ switch (dest_type) {
+ case MT_LOCATE_DEST_OBJECT:
+ case MT_LOCATE_DEST_FILE:
+ case MT_LOCATE_DEST_SET:
+ mtl.logical_id = logical_id;
+ break;
+ case MT_LOCATE_DEST_EOD:
+ break;
+ }
+
+ if (immediate != 0)
+ mtl.flags |= MT_LOCATE_FLAG_IMMED;
+
+ if (partition_set != 0) {
+ mtl.flags |= MT_LOCATE_FLAG_CHANGE_PART;
+ mtl.partition = partition;
+ }
+
+ if (explicit != 0)
+ mtl.block_address_mode = MT_LOCATE_BAM_EXPLICIT;
+ else
+ mtl.block_address_mode = MT_LOCATE_BAM_IMPLICIT;
+
+ if (ioctl(mtfd, MTIOCEXTLOCATE, &mtl) == -1)
+ err(1, "MTIOCEXTLOCATE ioctl failed on %s", tape);
+
+ return (retval);
+}
+
+typedef enum {
+ MT_PERIPH_NAME = 0,
+ MT_UNIT_NUMBER = 1,
+ MT_VENDOR = 2,
+ MT_PRODUCT = 3,
+ MT_REVISION = 4,
+ MT_COMPRESSION_SUPPORTED = 5,
+ MT_COMPRESSION_ENABLED = 6,
+ MT_COMPRESSION_ALGORITHM = 7,
+ MT_MEDIA_DENSITY = 8,
+ MT_MEDIA_BLOCKSIZE = 9,
+ MT_CALCULATED_FILENO = 10,
+ MT_CALCULATED_REL_BLKNO = 11,
+ MT_REPORTED_FILENO = 12,
+ MT_REPORTED_BLKNO = 13,
+ MT_PARTITION = 14,
+ MT_BOP = 15,
+ MT_EOP = 16,
+ MT_BPEW = 17,
+ MT_DSREG = 18,
+ MT_RESID = 19,
+ MT_FIXED_MODE = 20,
+ MT_SERIAL_NUM = 21,
+ MT_MAXIO = 22,
+ MT_CPI_MAXIO = 23,
+ MT_MAX_BLK = 24,
+ MT_MIN_BLK = 25,
+ MT_BLK_GRAN = 26,
+ MT_MAX_EFF_IOSIZE = 27
+} status_item_index;
+
+static struct mt_status_items {
+ const char *name;
+ struct mt_status_entry *entry;
+} req_status_items[] = {
+ { "periph_name", NULL },
+ { "unit_number", NULL },
+ { "vendor", NULL },
+ { "product", NULL },
+ { "revision", NULL },
+ { "compression_supported", NULL },
+ { "compression_enabled", NULL },
+ { "compression_algorithm", NULL },
+ { "media_density", NULL },
+ { "media_blocksize", NULL },
+ { "calculated_fileno", NULL },
+ { "calculated_rel_blkno", NULL },
+ { "reported_fileno", NULL },
+ { "reported_blkno", NULL },
+ { "partition", NULL },
+ { "bop", NULL },
+ { "eop", NULL },
+ { "bpew", NULL },
+ { "dsreg", NULL },
+ { "residual", NULL },
+ { "fixed_mode", NULL },
+ { "serial_num", NULL },
+ { "maxio", NULL },
+ { "cpi_maxio", NULL },
+ { "max_blk", NULL },
+ { "min_blk", NULL },
+ { "blk_gran", NULL },
+ { "max_effective_iosize", NULL }
+};
+
+int
+nstatus_print(int argc, char **argv, char *xml_str,
+ struct mt_status_data *status_data)
+{
+ unsigned int i;
+ int64_t calculated_fileno, calculated_rel_blkno;
+ int64_t rep_fileno, rep_blkno, partition, resid;
+ char block_str[32];
+ const char *dens_str;
+ int dsreg, bop, eop, bpew;
+ int xml_dump = 0;
+ size_t dens_len;
+ unsigned int field_width;
+ int verbose = 0;
+ int c;
+
+ while ((c = getopt(argc, argv, "xv")) != -1) {
+ switch (c) {
+ case 'x':
+ xml_dump = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (xml_dump != 0) {
+ printf("%s", xml_str);
+ return (0);
+ }
+
+ for (i = 0; i < (sizeof(req_status_items)/sizeof(req_status_items[0]));
+ i++) {
+ char *name;
+
+ name = __DECONST(char *, req_status_items[i].name);
+ req_status_items[i].entry = mt_status_entry_find(status_data,
+ name);
+ if (req_status_items[i].entry == NULL) {
+ errx(1, "Cannot find status entry %s",
+ req_status_items[i].name);
+ }
+ }
+
+ printf("Drive: %s%ju: <%s %s %s> Serial Number: %s\n",
+ req_status_items[MT_PERIPH_NAME].entry->value,
+ (uintmax_t)req_status_items[MT_UNIT_NUMBER].entry->value_unsigned,
+ req_status_items[MT_VENDOR].entry->value,
+ req_status_items[MT_PRODUCT].entry->value,
+ req_status_items[MT_REVISION].entry->value,
+ (req_status_items[MT_SERIAL_NUM].entry->value) ?
+ req_status_items[MT_SERIAL_NUM].entry->value : "none");
+ printf("---------------------------------\n");
+
+ /*
+ * We check to see whether we're in fixed mode or not, and don't
+ * just believe the blocksize. If the SILI bit is turned on, the
+ * blocksize will be set to 4, even though we're doing variable
+ * length (well, multiples of 4) blocks.
+ */
+ if (req_status_items[MT_FIXED_MODE].entry->value_signed == 0)
+ snprintf(block_str, sizeof(block_str), "variable");
+ else
+ snprintf(block_str, sizeof(block_str), "%s",
+ getblksiz(req_status_items[
+ MT_MEDIA_BLOCKSIZE].entry->value_unsigned));
+
+ dens_str = denstostring(req_status_items[
+ MT_MEDIA_DENSITY].entry->value_unsigned);
+ if (dens_str == NULL)
+ dens_len = 0;
+ else
+ dens_len = strlen(dens_str);
+ field_width = MAX(dens_len, 17);
+ printf("Mode %-*s Blocksize bpi Compression\n"
+ "Current: %-*s %-12s %-7d ",
+ field_width, "Density", field_width, dens_str, block_str,
+ mt_density_bp(req_status_items[
+ MT_MEDIA_DENSITY].entry->value_unsigned, TRUE));
+
+ if (req_status_items[MT_COMPRESSION_SUPPORTED].entry->value_signed == 0)
+ printf("unsupported\n");
+ else if (req_status_items[
+ MT_COMPRESSION_ENABLED].entry->value_signed == 0)
+ printf("disabled\n");
+ else {
+ printf("enabled (%s)\n",
+ comptostring(req_status_items[
+ MT_COMPRESSION_ALGORITHM].entry->value_unsigned));
+ }
+
+ dsreg = req_status_items[MT_DSREG].entry->value_signed;
+ if (dsreg != MTIO_DSREG_NIL) {
+ const char sfmt[] = "Current Driver State: %s.\n";
+ printf("---------------------------------\n");
+ const char *state_str;
+
+ state_str = get_driver_state_str(dsreg);
+ if (state_str == NULL) {
+ char foo[32];
+ (void) sprintf(foo, "Unknown state 0x%x", dsreg);
+ printf(sfmt, foo);
+ } else {
+ printf(sfmt, state_str);
+ }
+ }
+ resid = req_status_items[MT_RESID].entry->value_signed;
+ calculated_fileno = req_status_items[
+ MT_CALCULATED_FILENO].entry->value_signed;
+ calculated_rel_blkno = req_status_items[
+ MT_CALCULATED_REL_BLKNO].entry->value_signed;
+ rep_fileno = req_status_items[
+ MT_REPORTED_FILENO].entry->value_signed;
+ rep_blkno = req_status_items[
+ MT_REPORTED_BLKNO].entry->value_signed;
+ bop = req_status_items[MT_BOP].entry->value_signed;
+ eop = req_status_items[MT_EOP].entry->value_signed;
+ bpew = req_status_items[MT_BPEW].entry->value_signed;
+ partition = req_status_items[MT_PARTITION].entry->value_signed;
+
+ printf("---------------------------------\n");
+ printf("Partition: %3jd Calc File Number: %3jd "
+ " Calc Record Number: %jd\n"
+ "Residual: %3jd Reported File Number: %3jd "
+ "Reported Record Number: %jd\n", partition, calculated_fileno,
+ calculated_rel_blkno, resid, rep_fileno, rep_blkno);
+
+ printf("Flags: ");
+ if (bop > 0 || eop > 0 || bpew > 0) {
+ int need_comma = 0;
+
+ if (bop > 0) {
+ printf("BOP");
+ need_comma = 1;
+ }
+ if (eop > 0) {
+ if (need_comma != 0)
+ printf(",");
+ printf("EOP");
+ need_comma = 1;
+ }
+ if (bpew > 0) {
+ if (need_comma != 0)
+ printf(",");
+ printf("BPEW");
+ need_comma = 1;
+ }
+ } else {
+ printf("None");
+ }
+ printf("\n");
+ if (verbose != 0) {
+ printf("---------------------------------\n");
+ printf("Tape I/O parameters:\n");
+ for (i = MT_MAXIO; i <= MT_MAX_EFF_IOSIZE; i++) {
+ printf(" %s (%s): %ju bytes\n",
+ req_status_items[i].entry->desc,
+ req_status_items[i].name,
+ req_status_items[i].entry->value_unsigned);
+ }
+ }
+
+ return (0);
+}
+
+int
+mt_xml_cmd(unsigned long cmd, int argc, char **argv, int mtfd, const char *tape)
+{
+ struct mt_status_data status_data;
+#if 0
+ struct mt_status_entry *entry;
+#endif
+ char *xml_str;
+ int retval;
+ unsigned long ioctl_cmd;
+
+ switch (cmd) {
+ case MT_CMD_PROTECT:
+ case MTIOCPARAMGET:
+ ioctl_cmd = MTIOCPARAMGET;
+ break;
+ default:
+ ioctl_cmd = MTIOCEXTGET;
+ break;
+ }
+
+ retval = mt_get_xml_str(mtfd, ioctl_cmd, &xml_str);
+ if (retval != 0)
+ err(1, "Couldn't get mt XML string");
+
+ retval = mt_get_status(xml_str, &status_data);
+ if (retval != XML_STATUS_OK) {
+ warn("Couldn't get mt status for %s", tape);
+ goto bailout;
+ }
+
+ /*
+ * This gets set if there are memory allocation or other errors in
+ * our parsing of the XML.
+ */
+ if (status_data.error != 0) {
+ warnx("%s", status_data.error_str);
+ retval = 1;
+ goto bailout;
+ }
+#if 0
+ STAILQ_FOREACH(entry, &status_data.entries, links)
+ mt_status_tree_print(entry, 0, NULL);
+#endif
+
+ switch (cmd) {
+ case MTIOCEXTGET:
+ retval = nstatus_print(argc, argv, xml_str, &status_data);
+ break;
+ case MTIOCPARAMGET:
+ retval = mt_param(argc, argv, mtfd, xml_str, &status_data);
+ break;
+ case MT_CMD_PROTECT:
+ retval = mt_protect(argc, argv, mtfd, &status_data);
+ break;
+ case MT_CMD_GETDENSITY:
+ retval = mt_getdensity(argc, argv, xml_str, &status_data);
+ break;
+ }
+
+bailout:
+ if (xml_str != NULL)
+ free(xml_str);
+
+ mt_status_free(&status_data);
+
+ return (retval);
+}
+
+static int
+mt_set_param(int mtfd, struct mt_status_data *status_data, char *param_name,
+ char *param_value)
+{
+ struct mt_status_entry *entry;
+ struct mtparamset param_set;
+
+ entry = mt_status_entry_find(status_data,
+ __DECONST(char *, "mtparamget"));
+ if (entry == NULL)
+ errx(1, "Cannot find parameter root node");
+
+ bzero(&param_set, sizeof(param_set));
+ entry = mt_entry_find(entry, param_name);
+ if (entry == NULL)
+ errx(1, "Unknown parameter name \"%s\"", param_name);
+
+ strlcpy(param_set.value_name, param_name, sizeof(param_set.value_name));
+
+ switch (entry->var_type) {
+ case MT_TYPE_INT:
+ param_set.value.value_signed = strtoll(param_value, NULL, 0);
+ param_set.value_type = MT_PARAM_SET_SIGNED;
+ param_set.value_len = entry->size;
+ break;
+ case MT_TYPE_UINT:
+ param_set.value.value_unsigned = strtoull(param_value, NULL, 0);
+ param_set.value_type = MT_PARAM_SET_UNSIGNED;
+ param_set.value_len = entry->size;
+ break;
+ case MT_TYPE_STRING: {
+ size_t param_len;
+
+ param_len = strlen(param_value) + 1;
+ if (param_len > sizeof(param_set.value.value_fixed_str)) {
+ param_set.value_type = MT_PARAM_SET_VAR_STR;
+ param_set.value.value_var_str = param_value;
+ } else {
+ param_set.value_type = MT_PARAM_SET_FIXED_STR;
+ strlcpy(param_set.value.value_fixed_str, param_value,
+ sizeof(param_set.value.value_fixed_str));
+ }
+ param_set.value_len = param_len;
+ break;
+ }
+ default:
+ errx(1, "Unknown parameter type %d for %s", entry->var_type,
+ param_name);
+ break;
+ }
+
+ if (ioctl(mtfd, MTIOCPARAMSET, &param_set) == -1)
+ err(1, "MTIOCPARAMSET");
+
+ if (param_set.status != MT_PARAM_STATUS_OK)
+ errx(1, "Failed to set %s: %s", param_name,
+ param_set.error_str);
+
+ return (0);
+}
+
+
+typedef enum {
+ MT_PP_LBP_R,
+ MT_PP_LBP_W,
+ MT_PP_RBDP,
+ MT_PP_PI_LENGTH,
+ MT_PP_PROT_METHOD
+} mt_protect_param;
+
+static struct mt_protect_info {
+ const char *name;
+ struct mt_status_entry *entry;
+ uint32_t value;
+} mt_protect_list[] = {
+ { "lbp_r", NULL, 0 },
+ { "lbp_w", NULL, 0 },
+ { "rbdp", NULL, 0 },
+ { "pi_length", NULL, 0 },
+ { "prot_method", NULL, 0 }
+};
+
+#define MT_NUM_PROTECT_PARAMS (sizeof(mt_protect_list)/sizeof(mt_protect_list[0]))
+
+#define MT_PROT_NAME "protection"
+
+static int
+mt_protect(int argc, char **argv, int mtfd, struct mt_status_data *status_data)
+{
+ int retval = 0;
+ int do_enable = 0, do_disable = 0, do_list = 0;
+ int rbdp_set = 0, lbp_w_set = 0, lbp_r_set = 0;
+ int prot_method_set = 0, pi_length_set = 0;
+ int verbose = 0;
+ uint32_t rbdp = 0, lbp_w = 0, lbp_r = 0;
+ uint32_t prot_method = 0, pi_length = 0;
+ struct mt_status_entry *prot_entry, *supported_entry;
+ struct mt_status_entry *entry;
+ struct mtparamset params[MT_NUM_PROTECT_PARAMS];
+ struct mtsetlist param_list;
+ unsigned int i;
+ int c;
+
+ while ((c = getopt(argc, argv, "b:delL:m:r:vw:")) != -1) {
+ switch (c) {
+ case 'b':
+ rbdp_set = 1;
+ rbdp = strtoul(optarg, NULL, 0);
+ if ((rbdp != 0) && (rbdp != 1))
+ errx(1, "valid values for -b are 0 and 1");
+ break;
+ case 'd':
+ do_disable = 1;
+ break;
+ case 'e':
+ do_enable = 1;
+ break;
+ case 'l':
+ do_list = 1;
+ break;
+ case 'L':
+ pi_length_set = 1;
+ pi_length = strtoul(optarg, NULL, 0);
+ if (pi_length > SA_CTRL_DP_PI_LENGTH_MASK)
+ errx(1, "PI length %u > maximum %u",
+ pi_length, SA_CTRL_DP_PI_LENGTH_MASK);
+ break;
+ case 'm':
+ prot_method_set = 1;
+ prot_method = strtoul(optarg, NULL, 0);
+ if (prot_method > SA_CTRL_DP_METHOD_MAX)
+ errx(1, "Method %u > maximum %u",
+ prot_method, SA_CTRL_DP_METHOD_MAX);
+ break;
+ case 'r':
+ lbp_r_set = 1;
+ lbp_r = strtoul(optarg, NULL, 0);
+ if ((lbp_r != 0) && (lbp_r != 1))
+ errx(1, "valid values for -r are 0 and 1");
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'w':
+ lbp_w_set = 1;
+ lbp_w = strtoul(optarg, NULL, 0);
+ if ((lbp_w != 0) && (lbp_r != 1))
+ errx(1, "valid values for -r are 0 and 1");
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((rbdp_set + do_disable + do_enable + do_list + pi_length_set +
+ prot_method_set + lbp_r_set + lbp_w_set) == 0)
+ errx(1, "Need an argument for protect");
+
+ if ((do_disable + do_enable + do_list) != 1)
+ errx(1, "You must specify only one of -e, -d or -l");
+
+ if (do_list != 0) {
+ retval = mt_protect_print(status_data, verbose);
+ goto bailout;
+ }
+ if (do_enable != 0) {
+ /*
+ * Enable protection, but allow the user to override
+ * settings if he doesn't want everything turned on.
+ */
+ if (rbdp_set == 0)
+ rbdp = 1;
+ if (lbp_w_set == 0)
+ lbp_w = 1;
+ if (lbp_r_set == 0)
+ lbp_r = 1;
+ /*
+ * If the user doesn't override it, we default to enabling
+ * Reed-Solomon checkums.
+ */
+ if (prot_method_set == 0)
+ prot_method = SA_CTRL_DP_REED_SOLOMON;
+ if (pi_length_set == 0)
+ pi_length = SA_CTRL_DP_RS_LENGTH;
+ } else if (do_disable != 0) {
+ /*
+ * If the user wants to disable protection, we ignore any
+ * other parameters he has set. Everything gets set to 0.
+ */
+ rbdp = lbp_w = lbp_r = 0;
+ prot_method = pi_length = 0;
+ }
+
+ prot_entry = mt_status_entry_find(status_data,
+ __DECONST(char *, MT_PROT_NAME));
+ if (prot_entry == NULL)
+ errx(1, "Unable to find protection information status");
+
+ supported_entry = mt_entry_find(prot_entry,
+ __DECONST(char *, "protection_supported"));
+ if (supported_entry == NULL)
+ errx(1, "Unable to find protection support information");
+
+ if (((supported_entry->var_type == MT_TYPE_INT)
+ && (supported_entry->value_signed == 0))
+ || ((supported_entry->var_type == MT_TYPE_UINT)
+ && (supported_entry->value_unsigned == 0)))
+ errx(1, "This device does not support protection information");
+
+ mt_protect_list[MT_PP_LBP_R].value = lbp_r;
+ mt_protect_list[MT_PP_LBP_W].value = lbp_w;
+ mt_protect_list[MT_PP_RBDP].value = rbdp;
+ mt_protect_list[MT_PP_PI_LENGTH].value = pi_length;
+ mt_protect_list[MT_PP_PROT_METHOD].value = prot_method;
+
+ bzero(&params, sizeof(params));
+ bzero(&param_list, sizeof(param_list));
+
+ /*
+ * Go through the list and make sure that we have this parameter,
+ * and that it is still an unsigned integer. If not, we've got a
+ * problem.
+ */
+ for (i = 0; i < MT_NUM_PROTECT_PARAMS; i++) {
+ entry = mt_entry_find(prot_entry,
+ __DECONST(char *, mt_protect_list[i].name));
+ if (entry == NULL) {
+ errx(1, "Unable to find parameter %s",
+ mt_protect_list[i].name);
+ }
+ mt_protect_list[i].entry = entry;
+
+ if (entry->var_type != MT_TYPE_UINT)
+ errx(1, "Parameter %s is type %d, not unsigned, "
+ "cannot proceed", mt_protect_list[i].name,
+ entry->var_type);
+ snprintf(params[i].value_name, sizeof(params[i].value_name),
+ "%s.%s", MT_PROT_NAME, mt_protect_list[i].name);
+ /* XXX KDM unify types here */
+ params[i].value_type = MT_PARAM_SET_UNSIGNED;
+ params[i].value_len = sizeof(mt_protect_list[i].value);
+ params[i].value.value_unsigned = mt_protect_list[i].value;
+
+ }
+ param_list.num_params = MT_NUM_PROTECT_PARAMS;
+ param_list.param_len = sizeof(params);
+ param_list.params = params;
+
+ if (ioctl(mtfd, MTIOCSETLIST, &param_list) == -1)
+ err(1, "error issuing MTIOCSETLIST ioctl");
+
+ for (i = 0; i < MT_NUM_PROTECT_PARAMS; i++) {
+ if (params[i].status != MT_PARAM_STATUS_OK) {
+ warnx("%s", params[i].error_str);
+ retval = 1;
+ }
+ }
+bailout:
+
+ return (retval);
+}
+
+static int
+mt_param(int argc, char **argv, int mtfd, char *xml_str,
+ struct mt_status_data *status_data)
+{
+ int list = 0, do_set = 0, xml_dump = 0;
+ char *param_name = NULL, *param_value = NULL;
+ int retval = 0, quiet = 0;
+ int c;
+
+ while ((c = getopt(argc, argv, "lp:qs:x")) != -1) {
+ switch (c) {
+ case 'l':
+ list = 1;
+ break;
+ case 'p':
+ if (param_name != NULL) {
+ warnx("Only one parameter name may be "
+ "specified");
+ retval = 1;
+ goto bailout;
+ }
+ param_name = strdup(optarg);
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 's':
+ if (param_value != NULL) {
+ warnx("Only one parameter value may be "
+ "specified");
+ retval = 1;
+ goto bailout;
+ }
+ param_value = strdup(optarg);
+ do_set = 1;
+ break;
+ case 'x':
+ xml_dump = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((list + do_set + xml_dump) != 1) {
+ warnx("You must specify only one of -s, -l or -x");
+ retval = 1;
+ goto bailout;
+ }
+
+ if (xml_dump != 0) {
+ printf("%s", xml_str);
+ retval = 0;
+ goto bailout;
+ }
+
+ if (do_set != 0) {
+ if (param_name == NULL)
+ errx(1, "You must specify -p with -s");
+
+ retval = mt_set_param(mtfd, status_data, param_name,
+ param_value);
+ } else if (list != 0)
+ retval = mt_param_list(status_data, param_name, quiet);
+
+bailout:
+ free(param_name);
+ free(param_value);
+ return (retval);
+}
+
+int
+mt_print_density_entry(struct mt_status_entry *density_root, int indent)
+{
+ struct mt_status_entry *entry;
+ int retval = 0;
+
+ STAILQ_FOREACH(entry, &density_root->child_entries, links) {
+ if (entry->var_type == MT_TYPE_NODE) {
+ retval = mt_print_density_entry(entry, indent + 2);
+ if (retval != 0)
+ break;
+ else
+ continue;
+ }
+ if ((strcmp(entry->entry_name, "primary_density_code") == 0)
+ || (strcmp(entry->entry_name, "secondary_density_code") == 0)
+ || (strcmp(entry->entry_name, "density_code") == 0)) {
+
+ printf("%*s%s (%s): %s\n", indent, "", entry->desc ?
+ entry->desc : "", entry->entry_name,
+ denstostring(entry->value_unsigned));
+ } else if (strcmp(entry->entry_name, "density_flags") == 0) {
+ printf("%*sMedium Access: ", indent, "");
+ if (entry->value_unsigned & MT_DENS_WRITE_OK) {
+ printf("Read and Write\n");
+ } else {
+ printf("Read Only\n");
+ }
+ printf("%*sDefault Density: %s\n", indent, "",
+ (entry->value_unsigned & MT_DENS_DEFLT) ? "Yes" :
+ "No");
+ printf("%*sDuplicate Density: %s\n", indent, "",
+ (entry->value_unsigned & MT_DENS_DUP) ? "Yes" :
+ "No");
+ } else if (strcmp(entry->entry_name, "media_width") == 0) {
+ printf("%*s%s (%s): %.1f mm\n", indent, "",
+ entry->desc ? entry->desc : "", entry->entry_name,
+ (double)((double)entry->value_unsigned / 10));
+ } else if (strcmp(entry->entry_name, "medium_length") == 0) {
+ printf("%*s%s (%s): %ju m\n", indent, "",
+ entry->desc ? entry->desc : "", entry->entry_name,
+ (uintmax_t)entry->value_unsigned);
+ } else if (strcmp(entry->entry_name, "capacity") == 0) {
+ printf("%*s%s (%s): %ju MB\n", indent, "", entry->desc ?
+ entry->desc : "", entry->entry_name,
+ (uintmax_t)entry->value_unsigned);
+ } else {
+ printf("%*s%s (%s): %s\n", indent, "", entry->desc ?
+ entry->desc : "", entry->entry_name, entry->value);
+ }
+ }
+
+ return (retval);
+}
+
+int
+mt_print_density_report(struct mt_status_entry *report_root, int indent)
+{
+ struct mt_status_entry *mt_report, *media_report;
+ struct mt_status_entry *entry;
+ int retval = 0;
+
+ mt_report = mt_entry_find(report_root,
+ __DECONST(char *, MT_MEDIUM_TYPE_REPORT_NAME));
+ if (mt_report == NULL)
+ return (1);
+
+ media_report = mt_entry_find(report_root,
+ __DECONST(char *, MT_MEDIA_REPORT_NAME));
+ if (media_report == NULL)
+ return (1);
+
+ if ((mt_report->value_signed == 0)
+ && (media_report->value_signed == 0)) {
+ printf("%*sThis tape drive supports the following "
+ "media densities:\n", indent, "");
+ } else if ((mt_report->value_signed == 0)
+ && (media_report->value_signed != 0)) {
+ printf("%*sThe tape currently in this drive supports "
+ "the following media densities:\n", indent, "");
+ } else if ((mt_report->value_signed != 0)
+ && (media_report->value_signed == 0)) {
+ printf("%*sThis tape drive supports the following "
+ "media types:\n", indent, "");
+ } else {
+ printf("%*sThis tape currently in this drive supports "
+ "the following media types:\n", indent, "");
+ }
+
+ STAILQ_FOREACH(entry, &report_root->child_entries, links) {
+ struct mt_status_nv *nv;
+
+ if (strcmp(entry->entry_name, MT_DENSITY_ENTRY_NAME) != 0)
+ continue;
+
+ STAILQ_FOREACH(nv, &entry->nv_list, links) {
+ if (strcmp(nv->name, "num") != 0)
+ continue;
+
+ break;
+ }
+
+ indent += 2;
+
+ printf("%*sDensity Entry", indent, "");
+ if (nv != NULL)
+ printf(" %s", nv->value);
+ printf(":\n");
+
+ retval = mt_print_density_entry(entry, indent + 2);
+
+ indent -= 2;
+ }
+
+ return (retval);
+}
+
+int
+mt_print_density(struct mt_status_entry *density_root, int indent)
+{
+ struct mt_status_entry *entry;
+ int retval = 0;
+
+ /*
+ * We should have this entry for every tape drive. This particular
+ * value is reported via the mode page block header, not the
+ * SCSI REPORT DENSITY SUPPORT command.
+ */
+ entry = mt_entry_find(density_root,
+ __DECONST(char *, MT_MEDIA_DENSITY_NAME));
+ if (entry == NULL)
+ errx(1, "Unable to find node %s", MT_MEDIA_DENSITY_NAME);
+
+ printf("%*sCurrent density: %s\n", indent, "",
+ denstostring(entry->value_unsigned));
+
+ /*
+ * It isn't an error if we don't have any density reports. Tape
+ * drives that don't support the REPORT DENSITY SUPPORT command
+ * won't have any; they will only have the current density entry
+ * above.
+ */
+ STAILQ_FOREACH(entry, &density_root->child_entries, links) {
+ if (strcmp(entry->entry_name, MT_DENSITY_REPORT_NAME) != 0)
+ continue;
+
+ retval = mt_print_density_report(entry, indent);
+ }
+
+ return (retval);
+}
+
+int
+mt_getdensity(int argc, char **argv, char *xml_str,
+ struct mt_status_data *status_data)
+{
+ int retval = 0;
+ int xml_dump = 0;
+ struct mt_status_entry *density_root = NULL;
+ int c;
+
+ while ((c = getopt(argc, argv, "vx")) != -1) {
+ switch (c) {
+ case 'v':
+ /* Ignore. */
+ break;
+ case 'x':
+ xml_dump = 1;
+ break;
+ }
+ }
+
+ if (xml_dump != 0) {
+ printf("%s", xml_str);
+ return (0);
+ }
+
+ density_root = mt_status_entry_find(status_data,
+ __DECONST(char *, MT_DENSITY_ROOT_NAME));
+ if (density_root == NULL)
+ errx(1, "Cannot find density root node %s",
+ MT_DENSITY_ROOT_NAME);
+
+ retval = mt_print_density(density_root, 0);
+
+ return (retval);
+}
+
+static void
+warn_eof(void)
+{
+ fprintf(stderr,
+ "The \"eof\" command has been disabled.\n"
+ "Use \"weof\" if you really want to write end-of-file marks,\n"
+ "or \"eom\" if you rather want to skip to the end of "
+ "recorded medium.\n");
+ exit(1);
+}
diff --git a/usr.bin/nc/Makefile b/usr.bin/nc/Makefile
new file mode 100644
index 000000000000..411f558d7ba3
--- /dev/null
+++ b/usr.bin/nc/Makefile
@@ -0,0 +1,18 @@
+.include <src.opts.mk>
+
+.PATH: ${SRCTOP}/contrib/netcat
+
+PROG= nc
+SRCS= netcat.c atomicio.c socks.c
+
+CFLAGS+=-DIPSEC
+LIBADD= ipsec
+
+.if ${MK_STATS} != "no" && !defined(RESCUE)
+LIBADD+= sbuf stats
+CFLAGS+= -DWITH_STATS
+.endif
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nc/Makefile.depend b/usr.bin/nc/Makefile.depend
new file mode 100644
index 000000000000..6d2fa600c7e4
--- /dev/null
+++ b/usr.bin/nc/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libipsec \
+ lib/libsbuf \
+ lib/libstats \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ncal/Makefile b/usr.bin/ncal/Makefile
new file mode 100644
index 000000000000..85affcf983b5
--- /dev/null
+++ b/usr.bin/ncal/Makefile
@@ -0,0 +1,13 @@
+.include <src.opts.mk>
+
+PROG= ncal
+
+LIBADD= calendar tinfow
+
+LINKS= ${BINDIR}/ncal ${BINDIR}/cal
+MLINKS= ncal.1 cal.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ncal/Makefile.depend b/usr.bin/ncal/Makefile.depend
new file mode 100644
index 000000000000..51ffdb22663e
--- /dev/null
+++ b/usr.bin/ncal/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcalendar \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ncal/ncal.1 b/usr.bin/ncal/ncal.1
new file mode 100644
index 000000000000..2c7c82fd318e
--- /dev/null
+++ b/usr.bin/ncal/ncal.1
@@ -0,0 +1,225 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 1997 Wolfgang Helbig
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 March 7, 2019
+.Dt CAL 1
+.Os
+.Sh NAME
+.Nm cal ,
+.Nm ncal
+.Nd displays a calendar and the date of Easter
+.Sh SYNOPSIS
+.Nm
+.Op Fl 3hjMy
+.Op Fl A Ar number
+.Op Fl B Ar number
+.Oo
+.Op Ar month
+.Ar year
+.Oc
+.Nm
+.Op Fl 3hjM
+.Op Fl A Ar number
+.Op Fl B Ar number
+.Fl m Ar month
+.Op Ar year
+.Nm ncal
+.Op Fl 3hjJpwy
+.Op Fl A Ar number
+.Op Fl B Ar number
+.Op Fl s Ar country_code
+.Oo
+.Op Ar month
+.Ar year
+.Oc
+.Nm ncal
+.Op Fl 3hJeo
+.Op Fl A Ar number
+.Op Fl B Ar number
+.Op Ar year
+.Nm ncal
+.Op Fl CN
+.Op Fl H Ar yyyy-mm-dd
+.Op Fl d Ar yyyy-mm
+.Sh DESCRIPTION
+The
+.Nm
+utility displays a simple calendar in traditional format and
+.Nm ncal
+offers an alternative layout, more options and the date of Easter.
+The new format is a little cramped but it makes a year fit
+on a 25x80 terminal.
+If arguments are not specified,
+the current month is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl h
+Toggle highlighting of today.
+By default highlighting is enabled if stdout is a TTY.
+.It Fl J
+Display Julian Calendar, if combined with the
+.Fl e
+option, display date of Easter according to the Julian Calendar.
+.It Fl e
+Display date of Easter (for western churches).
+.It Fl j
+Display Julian days (days one-based, numbered from January 1).
+.It Fl M
+Display Monday as the first day of the week in
+.Nm cal
+mode.
+.It Fl m Ar month
+Display the specified
+.Ar month .
+If
+.Ar month
+is specified as a decimal number, it may be followed by the letter
+.Ql f
+or
+.Ql p
+to indicate the following or preceding month of that number,
+respectively.
+.It Fl o
+Display date of Orthodox Easter (Greek and Russian
+Orthodox Churches).
+.It Fl p
+Print the country codes and switching days from Julian to Gregorian
+Calendar as they are assumed by
+.Nm ncal .
+The country code as determined from the local environment is marked
+with an asterisk.
+.It Fl s Ar country_code
+Assume the switch from Julian to Gregorian Calendar at the date
+associated with the
+.Ar country_code .
+If not specified,
+.Nm ncal
+tries to guess the switch date from the local environment or
+falls back to September 2, 1752.
+This was when Great
+Britain and her colonies switched to the Gregorian Calendar.
+.It Fl w
+Print the number of the week below each week column.
+.It Fl y
+Display a calendar for the specified year.
+.It Fl 3
+Display the previous, current and next month surrounding today.
+.It Fl A Ar number
+Display the
+.Ar number
+of months after the current month.
+.It Fl B Ar number
+Display the
+.Ar number
+of months before the current month.
+.It Fl C
+Switch to
+.Nm cal
+mode.
+.It Fl N
+Switch to
+.Nm ncal
+mode.
+.It Fl d Ar yyyy-mm
+Use
+.Ar yyyy-mm
+as the current date (for debugging of date selection).
+.It Fl H Ar yyyy-mm-dd
+Use
+.Ar yyyy-mm-dd
+as the current date (for debugging of highlighting).
+.El
+.Pp
+A single parameter specifies the year (1\(en9999) to be displayed;
+note the year must be fully specified:
+.Dq Li cal 89
+will
+.Em not
+display a calendar for 1989.
+Two parameters denote the month and
+year; the month is either a number between 1 and 12, or a full or
+abbreviated name as specified by the current locale.
+Month and
+year default to those of the current system clock and time zone (so
+.Dq Li cal -m 8
+will display a calendar for the month of August in the current
+year).
+.Pp
+Not all options can be used together.
+For example
+.Dq Li -3 -A 2 -B 3 -y -m 7
+would mean:
+show me the three months around the seventh month, three before
+that, two after that and the whole year.
+.Nm ncal
+will warn about these combinations.
+.Pp
+A year starts on January 1.
+.Pp
+Highlighting of dates is disabled if stdout is not a tty.
+.Sh SEE ALSO
+.Xr calendar 3 ,
+.Xr strftime 3
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+X/Open System Interfaces option of the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl 3ehJMopwy ,
+as well as the ability to specify a month name as a single argument,
+are extensions to that specification.
+.Pp
+The week number computed by
+.Fl w
+is compliant with the
+.St -iso8601
+specification.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+The
+.Nm ncal
+command appeared in
+.Fx 2.2.6 .
+.Sh AUTHORS
+The
+.Nm ncal
+command and manual were written by
+.An Wolfgang Helbig Aq Mt helbig@FreeBSD.org .
+.Sh BUGS
+The assignment of Julian\(enGregorian switching dates to country
+codes is historically naive for many countries.
+.Pp
+Not all options are compatible and using them in different orders
+will give varying results.
diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c
new file mode 100644
index 000000000000..dc50dd60bf0b
--- /dev/null
+++ b/usr.bin/ncal/ncal.c
@@ -0,0 +1,1190 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1997 Wolfgang Helbig
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <calendar.h>
+#include <ctype.h>
+#include <err.h>
+#include <langinfo.h>
+#include <libgen.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <term.h>
+#undef lines /* term.h defines this */
+
+/* Width of one month with backward compatibility and in regular mode*/
+#define MONTH_WIDTH_B_J 27
+#define MONTH_WIDTH_B 20
+
+#define MONTH_WIDTH_R_J 24
+#define MONTH_WIDTH_R 18
+
+#define MAX_WIDTH 64
+
+typedef struct date date;
+
+struct monthlines {
+ wchar_t name[MAX_WIDTH + 1];
+ char lines[7][MAX_WIDTH + 1];
+ char weeks[MAX_WIDTH + 1];
+ unsigned int extralen[7];
+};
+
+struct weekdays {
+ wchar_t names[7][4];
+};
+
+/* The switches from Julian to Gregorian in some countries */
+static struct djswitch {
+ const char *cc; /* Country code according to ISO 3166 */
+ const char *nm; /* Name of country */
+ date dt; /* Last day of Julian calendar */
+} switches[] = {
+ {"AL", "Albania", {1912, 11, 30}},
+ {"AT", "Austria", {1583, 10, 5}},
+ {"AU", "Australia", {1752, 9, 2}},
+ {"BE", "Belgium", {1582, 12, 14}},
+ {"BG", "Bulgaria", {1916, 3, 31}},
+ {"CA", "Canada", {1752, 9, 2}},
+ {"CH", "Switzerland", {1655, 2, 28}},
+ {"CN", "China", {1911, 12, 18}},
+ {"CZ", "Czech Republic",{1584, 1, 6}},
+ {"DE", "Germany", {1700, 2, 18}},
+ {"DK", "Denmark", {1700, 2, 18}},
+ {"ES", "Spain", {1582, 10, 4}},
+ {"FI", "Finland", {1753, 2, 17}},
+ {"FR", "France", {1582, 12, 9}},
+ {"GB", "United Kingdom",{1752, 9, 2}},
+ {"GR", "Greece", {1924, 3, 9}},
+ {"HU", "Hungary", {1587, 10, 21}},
+ {"IS", "Iceland", {1700, 11, 16}},
+ {"IT", "Italy", {1582, 10, 4}},
+ {"JP", "Japan", {1918, 12, 18}},
+ {"LT", "Lithuania", {1918, 2, 1}},
+ {"LU", "Luxembourg", {1582, 12, 14}},
+ {"LV", "Latvia", {1918, 2, 1}},
+ {"NL", "Netherlands", {1582, 12, 14}},
+ {"NO", "Norway", {1700, 2, 18}},
+ {"PL", "Poland", {1582, 10, 4}},
+ {"PT", "Portugal", {1582, 10, 4}},
+ {"RO", "Romania", {1919, 3, 31}},
+ {"RU", "Russia", {1918, 1, 31}},
+ {"SI", "Slovenia", {1919, 3, 4}},
+ {"SE", "Sweden", {1753, 2, 17}},
+ {"TR", "Turkey", {1926, 12, 18}},
+ {"US", "United States", {1752, 9, 2}},
+ {"YU", "Yugoslavia", {1919, 3, 4}}
+};
+
+static struct djswitch *dftswitch =
+ switches + sizeof(switches) / sizeof(struct djswitch) - 2;
+ /* default switch (should be "US") */
+
+/* Table used to print day of month and week numbers */
+static char daystr[] = " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
+ " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
+ " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
+ " 48 49 50 51 52 53";
+
+/* Table used to print day of year and week numbers */
+static char jdaystr[] = " 1 2 3 4 5 6 7 8 9"
+ " 10 11 12 13 14 15 16 17 18 19"
+ " 20 21 22 23 24 25 26 27 28 29"
+ " 30 31 32 33 34 35 36 37 38 39"
+ " 40 41 42 43 44 45 46 47 48 49"
+ " 50 51 52 53 54 55 56 57 58 59"
+ " 60 61 62 63 64 65 66 67 68 69"
+ " 70 71 72 73 74 75 76 77 78 79"
+ " 80 81 82 83 84 85 86 87 88 89"
+ " 90 91 92 93 94 95 96 97 98 99"
+ " 100 101 102 103 104 105 106 107 108 109"
+ " 110 111 112 113 114 115 116 117 118 119"
+ " 120 121 122 123 124 125 126 127 128 129"
+ " 130 131 132 133 134 135 136 137 138 139"
+ " 140 141 142 143 144 145 146 147 148 149"
+ " 150 151 152 153 154 155 156 157 158 159"
+ " 160 161 162 163 164 165 166 167 168 169"
+ " 170 171 172 173 174 175 176 177 178 179"
+ " 180 181 182 183 184 185 186 187 188 189"
+ " 190 191 192 193 194 195 196 197 198 199"
+ " 200 201 202 203 204 205 206 207 208 209"
+ " 210 211 212 213 214 215 216 217 218 219"
+ " 220 221 222 223 224 225 226 227 228 229"
+ " 230 231 232 233 234 235 236 237 238 239"
+ " 240 241 242 243 244 245 246 247 248 249"
+ " 250 251 252 253 254 255 256 257 258 259"
+ " 260 261 262 263 264 265 266 267 268 269"
+ " 270 271 272 273 274 275 276 277 278 279"
+ " 280 281 282 283 284 285 286 287 288 289"
+ " 290 291 292 293 294 295 296 297 298 299"
+ " 300 301 302 303 304 305 306 307 308 309"
+ " 310 311 312 313 314 315 316 317 318 319"
+ " 320 321 322 323 324 325 326 327 328 329"
+ " 330 331 332 333 334 335 336 337 338 339"
+ " 340 341 342 343 344 345 346 347 348 349"
+ " 350 351 352 353 354 355 356 357 358 359"
+ " 360 361 362 363 364 365 366";
+
+static int flag_highlight; /* highlighted today */
+static int flag_weeks; /* user wants number of week */
+static int nswitch; /* user defined switch date */
+static int nswitchb; /* switch date for backward compatibility */
+static int highlightdate;
+static bool flag_monday; /* user wants week starts on Monday */
+
+static char *center(char *s, char *t, int w);
+static wchar_t *wcenter(wchar_t *s, wchar_t *t, int w);
+static int firstday(int y, int m);
+static void highlight(char *dst, char *src, int len, int *extraletters);
+static void mkmonthr(int year, int month, int jd_flag,
+ struct monthlines * monthl);
+static void mkmonthb(int year, int month, int jd_flag,
+ struct monthlines * monthl);
+static void mkweekdays(struct weekdays * wds);
+static void monthranger(int year, int m, int jd_flag,
+ int before, int after);
+static void monthrangeb(int year, int m, int jd_flag,
+ int before, int after);
+static int parsemonth(const char *s, int *m, int *y);
+static void printcc(void);
+static void printeaster(int year, int julian, int orthodox);
+static date *sdater(int ndays, struct date * d);
+static date *sdateb(int ndays, struct date * d);
+static int sndaysr(struct date * d);
+static int sndaysb(struct date * d);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct djswitch *p, *q; /* to search user defined switch date */
+ date never = {10000, 1, 1}; /* outside valid range of dates */
+ date ukswitch = {1752, 9, 2};/* switch date for Great Britain */
+ date dt;
+ int ch; /* holds the option character */
+ int m = 0; /* month */
+ int y = 0; /* year */
+ int flag_backward = 0; /* user called cal--backward compat. */
+ int flag_wholeyear = 0; /* user wants the whole year */
+ int flag_julian_cal = 0; /* user wants Julian Calendar */
+ int flag_julian_day = 0; /* user wants the Julian day numbers */
+ int flag_orthodox = 0; /* user wants Orthodox easter */
+ int flag_easter = 0; /* user wants easter date */
+ int flag_3months = 0; /* user wants 3 month display (-3) */
+ int flag_after = 0; /* user wants to see months after */
+ int flag_before = 0; /* user wants to see months before */
+ int flag_specifiedmonth = 0;/* user wants to see this month (-m) */
+ int flag_givenmonth = 0; /* user has specified month [n] */
+ int flag_givenyear = 0; /* user has specified year [n] */
+ char *cp; /* character pointer */
+ char *flag_today = NULL; /* debug: use date as being today */
+ char *flag_month = NULL; /* requested month as string */
+ char *flag_highlightdate = NULL; /* debug: date to highlight */
+ int before, after;
+ const char *locale; /* locale to get country code */
+
+ flag_highlight = isatty(STDOUT_FILENO);
+ flag_weeks = 0;
+ flag_monday = false;
+
+ /*
+ * Use locale to determine the country code,
+ * and use the country code to determine the default
+ * switchdate and date format from the switches table.
+ */
+ if (setlocale(LC_ALL, "") == NULL)
+ warn("setlocale");
+ locale = setlocale(LC_TIME, NULL);
+ if (locale == NULL ||
+ strcmp(locale, "C") == 0 ||
+ strcmp(locale, "POSIX") == 0 ||
+ strcmp(locale, "ASCII") == 0 ||
+ strcmp(locale, "US-ASCII") == 0)
+ locale = "_US";
+ q = switches + sizeof(switches) / sizeof(struct djswitch);
+ for (p = switches; p != q; p++)
+ if ((cp = strstr(locale, p->cc)) != NULL && *(cp - 1) == '_')
+ break;
+ if (p == q) {
+ nswitch = ndaysj(&dftswitch->dt);
+ } else {
+ nswitch = ndaysj(&p->dt);
+ dftswitch = p;
+ }
+
+
+ /*
+ * Get the filename portion of argv[0] and set flag_backward if
+ * this program is called "cal".
+ */
+ if (strncmp(basename(argv[0]), "cal", strlen("cal")) == 0)
+ flag_backward = 1;
+
+ /* Set the switch date to United Kingdom if backwards compatible */
+ if (flag_backward)
+ nswitchb = ndaysj(&ukswitch);
+
+ before = after = -1;
+
+ while ((ch = getopt(argc, argv, "3A:B:Cd:eH:hjJm:Nops:wyM")) != -1)
+ switch (ch) {
+ case '3':
+ flag_3months = 1;
+ break;
+ case 'A':
+ if (flag_after > 0)
+ errx(EX_USAGE, "Double -A specified");
+ flag_after = strtol(optarg, NULL, 10);
+ if (flag_after <= 0)
+ errx(EX_USAGE,
+ "Argument to -A must be positive");
+ break;
+ case 'B':
+ if (flag_before > 0)
+ errx(EX_USAGE, "Double -B specified");
+ flag_before = strtol(optarg, NULL, 10);
+ if (flag_before <= 0)
+ errx(EX_USAGE,
+ "Argument to -B must be positive");
+ break;
+ case 'J':
+ if (flag_backward)
+ usage();
+ nswitch = ndaysj(&never);
+ flag_julian_cal = 1;
+ break;
+ case 'C':
+ flag_backward = 1;
+ break;
+ case 'N':
+ flag_backward = 0;
+ break;
+ case 'd':
+ flag_today = optarg;
+ break;
+ case 'H':
+ flag_highlightdate = optarg;
+ break;
+ case 'h':
+ flag_highlight = !flag_highlight;
+ break;
+ case 'e':
+ if (flag_backward)
+ usage();
+ flag_easter = 1;
+ break;
+ case 'j':
+ flag_julian_day = 1;
+ break;
+ case 'M':
+ flag_monday = true;
+ break;
+ case 'm':
+ if (flag_specifiedmonth)
+ errx(EX_USAGE, "Double -m specified");
+ flag_month = optarg;
+ flag_specifiedmonth = 1;
+ break;
+ case 'o':
+ if (flag_backward)
+ usage();
+ flag_orthodox = 1;
+ flag_easter = 1;
+ break;
+ case 'p':
+ if (flag_backward)
+ usage();
+ printcc();
+ return (0);
+ break;
+ case 's':
+ if (flag_backward)
+ usage();
+ q = switches +
+ sizeof(switches) / sizeof(struct djswitch);
+ for (p = switches;
+ p != q && strcmp(p->cc, optarg) != 0; p++)
+ ;
+ if (p == q)
+ errx(EX_USAGE,
+ "%s: invalid country code", optarg);
+ nswitch = ndaysj(&(p->dt));
+ break;
+ case 'w':
+ if (flag_backward)
+ usage();
+ flag_weeks = 1;
+ break;
+ case 'y':
+ flag_wholeyear = 1;
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 2:
+ if (flag_easter)
+ usage();
+ flag_month = *argv++;
+ flag_givenmonth = 1;
+ m = strtol(flag_month, NULL, 10);
+ /* FALLTHROUGH */
+ case 1:
+ y = atoi(*argv);
+ if (y < 1 || y > 9999)
+ errx(EX_USAGE, "year `%s' not in range 1..9999", *argv);
+ argv++;
+ flag_givenyear = 1;
+ break;
+ case 0:
+ if (flag_today != NULL) {
+ y = strtol(flag_today, NULL, 10);
+ m = strtol(flag_today + 5, NULL, 10);
+ } else {
+ time_t t;
+ struct tm *tm;
+
+ t = time(NULL);
+ tm = localtime(&t);
+ y = tm->tm_year + 1900;
+ m = tm->tm_mon + 1;
+ }
+ break;
+ default:
+ usage();
+ }
+
+ if (flag_month != NULL) {
+ if (parsemonth(flag_month, &m, &y)) {
+ errx(EX_USAGE,
+ "%s is neither a month number (1..12) nor a name",
+ flag_month);
+ }
+ }
+
+ /*
+ * What is not supported:
+ * -3 with -A or -B
+ * -3 displays 3 months, -A and -B change that behaviour.
+ * -3 with -y
+ * -3 displays 3 months, -y says display a whole year.
+ * -3 with a given year but no given month or without -m
+ * -3 displays 3 months, no month specified doesn't make clear
+ * which three months.
+ * -m with a given month
+ * conflicting arguments, both specify the same field.
+ * -y with -m
+ * -y displays the whole year, -m displays a single month.
+ * -y with a given month
+ * -y displays the whole year, the given month displays a single
+ * month.
+ * -y with -A or -B
+ * -y displays the whole year, -A and -B display extra months.
+ */
+
+ /* -3 together with -A or -B. */
+ if (flag_3months && (flag_after || flag_before))
+ errx(EX_USAGE, "-3 together with -A and -B is not supported.");
+ /* -3 together with -y. */
+ if (flag_3months && flag_wholeyear)
+ errx(EX_USAGE, "-3 together with -y is not supported.");
+ /* -3 together with givenyear but no givenmonth. */
+ if (flag_3months && flag_givenyear &&
+ !(flag_givenmonth || flag_specifiedmonth))
+ errx(EX_USAGE,
+ "-3 together with a given year but no given month is "
+ "not supported.");
+ /* -m together with xx xxxx. */
+ if (flag_specifiedmonth && flag_givenmonth)
+ errx(EX_USAGE,
+ "-m together with a given month is not supported.");
+ /* -y together with -m. */
+ if (flag_wholeyear && flag_specifiedmonth)
+ errx(EX_USAGE, "-y together with -m is not supported.");
+ /* -y together with xx xxxx. */
+ if (flag_wholeyear && flag_givenmonth)
+ errx(EX_USAGE, "-y together a given month is not supported.");
+ /* -y together with -A or -B. */
+ if (flag_wholeyear && (flag_before > 0 || flag_after > 0))
+ errx(EX_USAGE, "-y together a -A or -B is not supported.");
+ /* The rest should be fine. */
+
+ /* Select the period to display, in order of increasing priority .*/
+ if (flag_wholeyear ||
+ (flag_givenyear && !(flag_givenmonth || flag_specifiedmonth))) {
+ m = 1;
+ before = 0;
+ after = 11;
+ }
+ if (flag_givenyear && flag_givenmonth) {
+ before = 0;
+ after = 0;
+ }
+ if (flag_specifiedmonth) {
+ before = 0;
+ after = 0;
+ }
+ if (flag_before) {
+ before = flag_before;
+ }
+ if (flag_after) {
+ after = flag_after;
+ }
+ if (flag_3months) {
+ before = 1;
+ after = 1;
+ }
+ if (after == -1)
+ after = 0;
+ if (before == -1)
+ before = 0;
+
+ /* Highlight a specified day or today .*/
+ if (flag_highlightdate != NULL) {
+ dt.y = strtol(flag_highlightdate, NULL, 10);
+ dt.m = strtol(flag_highlightdate + 5, NULL, 10);
+ dt.d = strtol(flag_highlightdate + 8, NULL, 10);
+ } else {
+ time_t t;
+ struct tm *tm1;
+
+ t = time(NULL);
+ tm1 = localtime(&t);
+ dt.y = tm1->tm_year + 1900;
+ dt.m = tm1->tm_mon + 1;
+ dt.d = tm1->tm_mday;
+ }
+ highlightdate = sndaysb(&dt);
+
+ /* And now we finally start to calculate and output calendars. */
+ if (flag_easter)
+ printeaster(y, flag_julian_cal, flag_orthodox);
+ else
+ if (flag_backward)
+ monthrangeb(y, m, flag_julian_day, before, after);
+ else
+ monthranger(y, m, flag_julian_day, before, after);
+ if (ferror(stdout) != 0 || fflush(stdout) != 0)
+ err(1, "stdout");
+ return (0);
+}
+
+static void
+usage(void)
+{
+
+ fputs(
+"Usage: cal [general options] [-hjy] [[month] year]\n"
+" cal [general options] [-hj] [-m month] [year]\n"
+" ncal [general options] [-hJjpwy] [-s country_code] [[month] year]\n"
+" ncal [general options] [-hJeo] [year]\n"
+"General options: [-NCM3] [-A months] [-B months]\n"
+"For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]\n",
+ stderr);
+ exit(EX_USAGE);
+}
+
+/* Print the assumed switches for all countries. */
+static void
+printcc(void)
+{
+ struct djswitch *p;
+ int n; /* number of lines to print */
+ int m; /* offset from left to right table entry on the same line */
+
+#define FSTR "%c%s %-15s%4d-%02d-%02d"
+#define DFLT(p) ((p) == dftswitch ? '*' : ' ')
+#define FSTRARG(p) DFLT(p), (p)->cc, (p)->nm, (p)->dt.y, (p)->dt.m, (p)->dt.d
+
+ n = sizeof(switches) / sizeof(struct djswitch);
+ m = (n + 1) / 2;
+ n /= 2;
+ for (p = switches; p != switches + n; p++)
+ printf(FSTR" "FSTR"\n", FSTRARG(p), FSTRARG(p+m));
+ if (m != n)
+ printf(FSTR"\n", FSTRARG(p));
+}
+
+/* Print the date of easter sunday. */
+static void
+printeaster(int y, int julian, int orthodox)
+{
+ date dt;
+ struct tm tm;
+ char buf[MAX_WIDTH];
+ static int d_first = -1;
+
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+ /* force orthodox easter for years before 1583 */
+ if (y < 1583)
+ orthodox = 1;
+
+ if (orthodox)
+ if (julian)
+ easteroj(y, &dt);
+ else
+ easterog(y, &dt);
+ else
+ easterg(y, &dt);
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = dt.y - 1900;
+ tm.tm_mon = dt.m - 1;
+ tm.tm_mday = dt.d;
+ strftime(buf, sizeof(buf), d_first ? "%e %B %Y" : "%B %e %Y", &tm);
+ printf("%s\n", buf);
+}
+
+#define MW(mw, me) ((mw) + me)
+#define DECREASEMONTH(m, y) \
+ if (--m == 0) { \
+ m = 12; \
+ y--; \
+ }
+#define INCREASEMONTH(m, y) \
+ if (++(m) == 13) { \
+ (m) = 1; \
+ (y)++; \
+ }
+#define M2Y(m) ((m) / 12)
+#define M2M(m) (1 + (m) % 12)
+
+/* Print all months for the period in the range [ before .. y-m .. after ]. */
+static void
+monthrangeb(int y, int m, int jd_flag, int before, int after)
+{
+ struct monthlines year[12];
+ struct weekdays wds;
+ char s[MAX_WIDTH], t[MAX_WIDTH];
+ wchar_t ws[MAX_WIDTH], ws1[MAX_WIDTH];
+ const char *wdss;
+ int i, j;
+ int mpl;
+ int mw;
+ int m1, m2;
+ int printyearheader;
+ int prevyear = -1;
+
+ mpl = jd_flag ? 2 : 3;
+ mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B;
+ wdss = (mpl == 2) ? " " : "";
+
+ while (before != 0) {
+ DECREASEMONTH(m, y);
+ before--;
+ after++;
+ }
+ m1 = y * 12 + m - 1;
+ m2 = m1 + after;
+
+ mkweekdays(&wds);
+
+ /*
+ * The year header is printed when there are more than 'mpl' months
+ * and if the first month is a multitude of 'mpl'.
+ * If not, it will print the year behind every month.
+ */
+ printyearheader = (after >= mpl - 1) && (M2M(m1) - 1) % mpl == 0;
+
+ m = m1;
+ while (m <= m2) {
+ int count = 0;
+ for (i = 0; i != mpl && m + i <= m2; i++) {
+ mkmonthb(M2Y(m + i), M2M(m + i) - 1, jd_flag, year + i);
+ count++;
+ }
+
+ /* Empty line between two rows of months */
+ if (m != m1)
+ printf("\n");
+
+ /* Year at the top. */
+ if (printyearheader && M2Y(m) != prevyear) {
+ sprintf(s, "%d", M2Y(m));
+ printf("%s\n", center(t, s, mpl * mw));
+ prevyear = M2Y(m);
+ }
+
+ /* Month names. */
+ for (i = 0; i < count; i++)
+ if (printyearheader)
+ wprintf(L"%-*ls ",
+ mw, wcenter(ws, year[i].name, mw));
+ else {
+ swprintf(ws, sizeof(ws)/sizeof(ws[0]),
+ L"%-ls %d", year[i].name, M2Y(m + i));
+ wprintf(L"%-*ls ", mw, wcenter(ws1, ws, mw));
+ }
+ printf("\n");
+
+ /* Day of the week names. */
+ for (i = 0; i < count; i++) {
+ wprintf(L"%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ",
+ wdss, wds.names[flag_monday ? 0 : 6],
+ wdss, wds.names[flag_monday ? 1 : 0],
+ wdss, wds.names[flag_monday ? 2 : 1],
+ wdss, wds.names[flag_monday ? 3 : 2],
+ wdss, wds.names[flag_monday ? 4 : 3],
+ wdss, wds.names[flag_monday ? 5 : 4],
+ wdss, wds.names[flag_monday ? 6 : 5]);
+ }
+ printf("\n");
+
+ /* And the days of the month. */
+ for (i = 0; i != 6; i++) {
+ for (j = 0; j < count; j++)
+ printf("%-*s ",
+ MW(mw, year[j].extralen[i]),
+ year[j].lines[i]+1);
+ printf("\n");
+ }
+
+ m += mpl;
+ }
+}
+
+static void
+monthranger(int y, int m, int jd_flag, int before, int after)
+{
+ struct monthlines year[12];
+ struct weekdays wds;
+ char s[MAX_WIDTH], t[MAX_WIDTH];
+ int i, j;
+ int mpl;
+ int mw;
+ int m1, m2;
+ int prevyear = -1;
+ int printyearheader;
+
+ mpl = jd_flag ? 3 : 4;
+ mw = jd_flag ? MONTH_WIDTH_R_J : MONTH_WIDTH_R;
+
+ while (before != 0) {
+ DECREASEMONTH(m, y);
+ before--;
+ after++;
+ }
+ m1 = y * 12 + m - 1;
+ m2 = m1 + after;
+
+ mkweekdays(&wds);
+
+ /*
+ * The year header is printed when there are more than 'mpl' months
+ * and if the first month is a multitude of 'mpl'.
+ * If not, it will print the year behind every month.
+ */
+ printyearheader = (after >= mpl - 1) && (M2M(m1) - 1) % mpl == 0;
+
+ m = m1;
+ while (m <= m2) {
+ int count = 0;
+ for (i = 0; i != mpl && m + i <= m2; i++) {
+ mkmonthr(M2Y(m + i), M2M(m + i) - 1, jd_flag, year + i);
+ count++;
+ }
+
+ /* Empty line between two rows of months. */
+ if (m != m1)
+ printf("\n");
+
+ /* Year at the top. */
+ if (printyearheader && M2Y(m) != prevyear) {
+ sprintf(s, "%d", M2Y(m));
+ printf("%s\n", center(t, s, mpl * mw));
+ prevyear = M2Y(m);
+ }
+
+ /* Month names. */
+ wprintf(L" ");
+ for (i = 0; i < count; i++)
+ if (printyearheader)
+ wprintf(L"%-*ls", mw, year[i].name);
+ else
+ wprintf(L"%-ls %-*d", year[i].name,
+ mw - wcslen(year[i].name) - 1, M2Y(m + i));
+ printf("\n");
+
+ /* And the days of the month. */
+ for (i = 0; i != 7; i++) {
+ /* Week day */
+ wprintf(L"%.2ls", wds.names[i]);
+
+ /* Full months */
+ for (j = 0; j < count; j++)
+ printf("%-*s",
+ MW(mw, year[j].extralen[i]),
+ year[j].lines[i]);
+ printf("\n");
+ }
+
+ /* Week numbers. */
+ if (flag_weeks) {
+ printf(" ");
+ for (i = 0; i < count; i++)
+ printf("%-*s", mw, year[i].weeks);
+ printf("\n");
+ }
+
+ m += mpl;
+ }
+ return;
+}
+
+static void
+mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines)
+{
+
+ struct tm tm; /* for strftime printing local names of
+ * months */
+ date dt; /* handy date */
+ int dw; /* width of numbers */
+ int first; /* first day of month */
+ int firstm; /* first day of first week of month */
+ int i, j, k, l; /* just indices */
+ int last; /* the first day of next month */
+ int jan1 = 0; /* the first day of this year */
+ char *ds; /* pointer to day strings (daystr or
+ * jdaystr) */
+
+ /* Set name of month. */
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_mon = m;
+ wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
+ L"%OB", &tm);
+ mlines->name[0] = towupper(mlines->name[0]);
+
+ /*
+ * Set first and last to the day number of the first day of this
+ * month and the first day of next month respectively. Set jan1 to
+ * the day number of the first day of this year.
+ */
+ first = firstday(y, m + 1);
+ if (m == 11)
+ last = firstday(y + 1, 1);
+ else
+ last = firstday(y, m + 2);
+
+ if (jd_flag)
+ jan1 = firstday(y, 1);
+
+ /*
+ * Set firstm to the day number of monday of the first week of
+ * this month. (This might be in the last month)
+ */
+ firstm = first - weekday(first);
+
+ /* Set ds (daystring) and dw (daywidth) according to the jd_flag. */
+ if (jd_flag) {
+ ds = jdaystr;
+ dw = 4;
+ } else {
+ ds = daystr;
+ dw = 3;
+ }
+
+ /*
+ * Fill the lines with day of month or day of year (julian day)
+ * line index: i, each line is one weekday. column index: j, each
+ * column is one day number. print column index: k.
+ */
+ for (i = 0; i != 7; i++) {
+ l = 0;
+ for (j = firstm + i, k = 0; j < last; j += 7, k += dw) {
+ if (j >= first) {
+ if (jd_flag)
+ dt.d = j - jan1 + 1;
+ else
+ sdater(j, &dt);
+ if (j == highlightdate && flag_highlight)
+ highlight(mlines->lines[i] + k,
+ ds + dt.d * dw, dw, &l);
+ else
+ memcpy(mlines->lines[i] + k + l,
+ ds + dt.d * dw, dw);
+ } else
+ memcpy(mlines->lines[i] + k + l, " ", dw);
+ }
+ mlines->lines[i][k + l] = '\0';
+ mlines->extralen[i] = l;
+ }
+
+ /* fill the weeknumbers. */
+ if (flag_weeks) {
+ for (j = firstm, k = 0; j < last; k += dw, j += 7)
+ if (j <= nswitch)
+ memset(mlines->weeks + k, ' ', dw);
+ else
+ memcpy(mlines->weeks + k,
+ ds + week(j, &i)*dw, dw);
+ mlines->weeks[k] = '\0';
+ }
+}
+
+static void
+mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines)
+{
+
+ struct tm tm; /* for strftime printing local names of
+ * months */
+ date dt; /* handy date */
+ int dw; /* width of numbers */
+ int first; /* first day of month */
+ int firstsm; /* sunday or monday of first week of month */
+ int i, j, k, l; /* just indices */
+ int jan1 = 0; /* the first day of this year */
+ int last; /* the first day of next month */
+ char *ds; /* pointer to day strings (daystr or
+ * jdaystr) */
+
+ /* Set ds (daystring) and dw (daywidth) according to the jd_flag */
+ if (jd_flag) {
+ ds = jdaystr;
+ dw = 4;
+ } else {
+ ds = daystr;
+ dw = 3;
+ }
+
+ /* Set name of month centered. */
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_mon = m;
+ wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
+ L"%OB", &tm);
+ mlines->name[0] = towupper(mlines->name[0]);
+
+ /*
+ * Set first and last to the day number of the first day of this
+ * month and the first day of next month respectively. Set jan1 to
+ * the day number of Jan 1st of this year.
+ */
+ dt.y = y;
+ dt.m = m + 1;
+ dt.d = 1;
+ first = sndaysb(&dt);
+ if (m == 11) {
+ dt.y = y + 1;
+ dt.m = 1;
+ dt.d = 1;
+ } else {
+ dt.y = y;
+ dt.m = m + 2;
+ dt.d = 1;
+ }
+ last = sndaysb(&dt);
+
+ if (jd_flag) {
+ dt.y = y;
+ dt.m = 1;
+ dt.d = 1;
+ jan1 = sndaysb(&dt);
+ }
+
+ /*
+ * Set firstsm to the day number of sunday or monday of the first week
+ * of this month. (This might be in the last month)
+ */
+ if (flag_monday)
+ firstsm = first - weekday(first);
+ else
+ firstsm = first - (weekday(first) + 1) % 7;
+
+ /*
+ * Fill the lines with day of month or day of year (Julian day)
+ * line index: i, each line is one week. column index: j, each
+ * column is one day number. print column index: k.
+ */
+ for (i = 0; i != 6; i++) {
+ l = 0;
+ for (j = firstsm + 7 * i, k = 0; j < last && k != dw * 7;
+ j++, k += dw) {
+ if (j >= first) {
+ if (jd_flag)
+ dt.d = j - jan1 + 1;
+ else
+ sdateb(j, &dt);
+ if (j == highlightdate && flag_highlight)
+ highlight(mlines->lines[i] + k,
+ ds + dt.d * dw, dw, &l);
+ else
+ memcpy(mlines->lines[i] + k + l,
+ ds + dt.d * dw, dw);
+ } else
+ memcpy(mlines->lines[i] + k + l, " ", dw);
+ }
+ if (k == 0)
+ mlines->lines[i][1] = '\0';
+ else
+ mlines->lines[i][k + l] = '\0';
+ mlines->extralen[i] = l;
+ }
+}
+
+/* Put the local names of weekdays into the wds. */
+static void
+mkweekdays(struct weekdays *wds)
+{
+ int i, len, width = 0;
+ struct tm tm;
+ wchar_t buf[20];
+
+ memset(&tm, 0, sizeof(tm));
+
+ for (i = 0; i != 7; i++) {
+ tm.tm_wday = (i+1) % 7;
+ wcsftime(buf, sizeof(buf)/sizeof(buf[0]), L"%a", &tm);
+ for (len = 2; len > 0; --len) {
+ if ((width = wcswidth(buf, len)) <= 2)
+ break;
+ }
+ wmemset(wds->names[i], L'\0', 4);
+ if (width == 1)
+ wds->names[i][0] = L' ';
+ wcsncat(wds->names[i], buf, len);
+ wcsncat(wds->names[i], L" ", 1);
+ }
+}
+
+/*
+ * Compute the day number of the first existing date after the first day in
+ * month. (the first day in month and even the month might not exist!)
+ */
+static int
+firstday(int y, int m)
+{
+ date dt;
+ int nd;
+
+ dt.y = y;
+ dt.m = m;
+ dt.d = 1;
+ nd = sndaysr(&dt);
+ for (;;) {
+ sdater(nd, &dt);
+ if ((dt.m >= m && dt.y == y) || dt.y > y)
+ return (nd);
+ else
+ nd++;
+ }
+ /* NEVER REACHED */
+}
+
+/*
+ * Compute the number of days from date, obey the local switch from
+ * Julian to Gregorian if specified by the user.
+ */
+static int
+sndaysr(struct date *d)
+{
+
+ if (nswitch != 0)
+ if (nswitch < ndaysj(d))
+ return (ndaysg(d));
+ else
+ return (ndaysj(d));
+ else
+ return ndaysg(d);
+}
+
+/*
+ * Compute the number of days from date, obey the switch from
+ * Julian to Gregorian as used by UK and her colonies.
+ */
+static int
+sndaysb(struct date *d)
+{
+
+ if (nswitchb < ndaysj(d))
+ return (ndaysg(d));
+ else
+ return (ndaysj(d));
+}
+
+/* Inverse of sndays. */
+static struct date *
+sdater(int nd, struct date *d)
+{
+
+ if (nswitch < nd)
+ return (gdate(nd, d));
+ else
+ return (jdate(nd, d));
+}
+
+/* Inverse of sndaysb. */
+static struct date *
+sdateb(int nd, struct date *d)
+{
+
+ if (nswitchb < nd)
+ return (gdate(nd, d));
+ else
+ return (jdate(nd, d));
+}
+
+/* Center string t in string s of length w by putting enough leading blanks. */
+static char *
+center(char *s, char *t, int w)
+{
+ char blanks[MAX_WIDTH];
+
+ memset(blanks, ' ', sizeof(blanks));
+ sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t);
+ return (s);
+}
+
+/* Center string t in string s of length w by putting enough leading blanks. */
+static wchar_t *
+wcenter(wchar_t *s, wchar_t *t, int w)
+{
+ char blanks[MAX_WIDTH];
+
+ memset(blanks, ' ', sizeof(blanks));
+ swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
+ return (s);
+}
+
+static int
+parsemonth(const char *s, int *m, int *y)
+{
+ int nm, ny;
+ char *cp;
+ struct tm tm;
+
+ nm = (int)strtol(s, &cp, 10);
+ if (cp != s) {
+ ny = *y;
+ if (*cp == '\0') {
+ ; /* no special action */
+ } else if (*cp == 'f' || *cp == 'F') {
+ if (nm <= *m)
+ ny++;
+ } else if (*cp == 'p' || *cp == 'P') {
+ if (nm >= *m)
+ ny--;
+ } else
+ return (1);
+ if (nm < 1 || nm > 12)
+ return 1;
+ *m = nm;
+ *y = ny;
+ return (0);
+ }
+ if (strptime(s, "%B", &tm) != NULL || strptime(s, "%b", &tm) != NULL) {
+ *m = tm.tm_mon + 1;
+ return (0);
+ }
+ return (1);
+}
+
+static void
+highlight(char *dst, char *src, int len, int *extralen)
+{
+ static int first = 1;
+ static const char *term_so, *term_se;
+
+ if (first) {
+ static char cbuf[512];
+ char tbuf[1024], *b;
+
+ term_se = term_so = NULL;
+
+ /* On how to highlight on this type of terminal (if any). */
+ if (isatty(STDOUT_FILENO) && tgetent(tbuf, NULL) == 1) {
+ b = cbuf;
+ term_so = tgetstr("so", &b);
+ term_se = tgetstr("se", &b);
+ }
+
+ first = 0;
+ }
+
+ /*
+ * This check is not necessary, should have been handled before calling
+ * this function.
+ */
+ if (!flag_highlight) {
+ memcpy(dst, src, len);
+ return;
+ }
+
+ /*
+ * If it is a real terminal, use the data from the termcap database.
+ */
+ if (term_so != NULL && term_se != NULL) {
+ /* separator. */
+ dst[0] = ' ';
+ dst++;
+ /* highlight on. */
+ memcpy(dst, term_so, strlen(term_so));
+ dst += strlen(term_so);
+ /* the actual text. (minus leading space) */
+ len--;
+ src++;
+ memcpy(dst, src, len);
+ dst += len;
+ /* highlight off. */
+ memcpy(dst, term_se, strlen(term_se));
+ *extralen = strlen(term_so) + strlen(term_se);
+ return;
+ }
+
+ /*
+ * Otherwise, print a _, backspace and the letter.
+ */
+ *extralen = 0;
+ /* skip leading space. */
+ src++;
+ len--;
+ /* separator. */
+ dst[0] = ' ';
+ dst++;
+ while (len > 0) {
+ /* _ and backspace. */
+ memcpy(dst, "_\010", 2);
+ dst += 2;
+ *extralen += 2;
+ /* the character. */
+ *dst++ = *src++;
+ len--;
+ }
+ return;
+}
diff --git a/usr.bin/ncal/tests/Makefile b/usr.bin/ncal/tests/Makefile
new file mode 100644
index 000000000000..96b9751c43e1
--- /dev/null
+++ b/usr.bin/ncal/tests/Makefile
@@ -0,0 +1,96 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.b-3m200901-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200901-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200902-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200902-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200903-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200903-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200904-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200904-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200905-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200905-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200906-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200906-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200907-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200907-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200908-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200908-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200909-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200909-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200910-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200910-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200911-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200911-md-nhl.out
+${PACKAGE}FILES+= regress.b-3m200912-jd-nhl.out
+${PACKAGE}FILES+= regress.b-3m200912-md-nhl.out
+${PACKAGE}FILES+= regress.b-y2008-jd-nhl.out
+${PACKAGE}FILES+= regress.b-y2008-md-nhl.out
+${PACKAGE}FILES+= regress.b-y2009-jd-nhl.out
+${PACKAGE}FILES+= regress.b-y2009-md-nhl.out
+${PACKAGE}FILES+= regress.b-y2010-jd-nhl.out
+${PACKAGE}FILES+= regress.b-y2010-md-nhl.out
+${PACKAGE}FILES+= regress.b-y2011-jd-nhl.out
+${PACKAGE}FILES+= regress.b-y2011-md-nhl.out
+${PACKAGE}FILES+= regress.f-3A-nhl.out
+${PACKAGE}FILES+= regress.f-3AB-nhl.out
+${PACKAGE}FILES+= regress.f-3B-nhl.out
+${PACKAGE}FILES+= regress.f-3gy-nhl.out
+${PACKAGE}FILES+= regress.f-3y-nhl.out
+${PACKAGE}FILES+= regress.f-mgm-nhl.out
+${PACKAGE}FILES+= regress.f-yA-nhl.out
+${PACKAGE}FILES+= regress.f-yAB-nhl.out
+${PACKAGE}FILES+= regress.f-yB-nhl.out
+${PACKAGE}FILES+= regress.f-ygm-nhl.out
+${PACKAGE}FILES+= regress.f-ym-nhl.out
+${PACKAGE}FILES+= regress.r-3m200901-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200901-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200902-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200902-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200903-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200903-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200904-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200904-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200905-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200905-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200906-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200906-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200907-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200907-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200908-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200908-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200909-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200909-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200910-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200910-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200911-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200911-md-nhl.out
+${PACKAGE}FILES+= regress.r-3m200912-jd-nhl.out
+${PACKAGE}FILES+= regress.r-3m200912-md-nhl.out
+${PACKAGE}FILES+= regress.r-y2008-jd-nhl.out
+${PACKAGE}FILES+= regress.r-y2008-md-nhl.out
+${PACKAGE}FILES+= regress.r-y2009-jd-nhl.out
+${PACKAGE}FILES+= regress.r-y2009-md-nhl.out
+${PACKAGE}FILES+= regress.r-y2010-jd-nhl.out
+${PACKAGE}FILES+= regress.r-y2010-md-nhl.out
+${PACKAGE}FILES+= regress.r-y2011-jd-nhl.out
+${PACKAGE}FILES+= regress.r-y2011-md-nhl.out
+${PACKAGE}FILES+= regress.s-b-3-nhl.out
+${PACKAGE}FILES+= regress.s-b-A-nhl.out
+${PACKAGE}FILES+= regress.s-b-AB-nhl.out
+${PACKAGE}FILES+= regress.s-b-B-nhl.out
+${PACKAGE}FILES+= regress.s-b-gmgy-nhl.out
+${PACKAGE}FILES+= regress.s-b-m-nhl.out
+${PACKAGE}FILES+= regress.s-b-mgy-nhl.out
+${PACKAGE}FILES+= regress.s-r-3-nhl.out
+${PACKAGE}FILES+= regress.s-r-A-nhl.out
+${PACKAGE}FILES+= regress.s-r-AB-nhl.out
+${PACKAGE}FILES+= regress.s-r-B-nhl.out
+${PACKAGE}FILES+= regress.s-r-gmgy-nhl.out
+${PACKAGE}FILES+= regress.s-r-m-nhl.out
+${PACKAGE}FILES+= regress.s-r-mgy-nhl.out
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/ncal/tests/Makefile.depend b/usr.bin/ncal/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/ncal/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ncal/tests/legacy_test.sh b/usr.bin/ncal/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/ncal/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/ncal/tests/regress.b-3m200901-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200901-jd-nhl.out
new file mode 100644
index 000000000000..65d3619df948
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200901-jd-nhl.out
@@ -0,0 +1,17 @@
+ December 2008 January 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 336 337 338 339 340 341 1 2 3
+342 343 344 345 346 347 348 4 5 6 7 8 9 10
+349 350 351 352 353 354 355 11 12 13 14 15 16 17
+356 357 358 359 360 361 362 18 19 20 21 22 23 24
+363 364 365 366 25 26 27 28 29 30 31
+
+
+ February 2009
+ Su Mo Tu We Th Fr Sa
+ 32 33 34 35 36 37 38
+ 39 40 41 42 43 44 45
+ 46 47 48 49 50 51 52
+ 53 54 55 56 57 58 59
+
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200901-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200901-md-nhl.out
new file mode 100644
index 000000000000..afbdde1efe1c
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200901-md-nhl.out
@@ -0,0 +1,8 @@
+ December 2008 January 2009 February 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 7
+ 7 8 9 10 11 12 13 4 5 6 7 8 9 10 8 9 10 11 12 13 14
+14 15 16 17 18 19 20 11 12 13 14 15 16 17 15 16 17 18 19 20 21
+21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28
+28 29 30 31 25 26 27 28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200902-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200902-jd-nhl.out
new file mode 100644
index 000000000000..33f614d88cf0
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200902-jd-nhl.out
@@ -0,0 +1,18 @@
+ 2009
+ January February
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 32 33 34 35 36 37 38
+ 4 5 6 7 8 9 10 39 40 41 42 43 44 45
+ 11 12 13 14 15 16 17 46 47 48 49 50 51 52
+ 18 19 20 21 22 23 24 53 54 55 56 57 58 59
+ 25 26 27 28 29 30 31
+
+
+ March
+ Su Mo Tu We Th Fr Sa
+ 60 61 62 63 64 65 66
+ 67 68 69 70 71 72 73
+ 74 75 76 77 78 79 80
+ 81 82 83 84 85 86 87
+ 88 89 90
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200902-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200902-md-nhl.out
new file mode 100644
index 000000000000..e81b78e7bb71
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200902-md-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ January February March
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
+ 4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
+11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
+18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
+25 26 27 28 29 30 31 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200903-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200903-jd-nhl.out
new file mode 100644
index 000000000000..5974cbfda290
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200903-jd-nhl.out
@@ -0,0 +1,17 @@
+ February 2009 March 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 32 33 34 35 36 37 38 60 61 62 63 64 65 66
+ 39 40 41 42 43 44 45 67 68 69 70 71 72 73
+ 46 47 48 49 50 51 52 74 75 76 77 78 79 80
+ 53 54 55 56 57 58 59 81 82 83 84 85 86 87
+ 88 89 90
+
+
+ April 2009
+ Su Mo Tu We Th Fr Sa
+ 91 92 93 94
+ 95 96 97 98 99 100 101
+102 103 104 105 106 107 108
+109 110 111 112 113 114 115
+116 117 118 119 120
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200903-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200903-md-nhl.out
new file mode 100644
index 000000000000..4e9f0ebf163f
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200903-md-nhl.out
@@ -0,0 +1,8 @@
+ February 2009 March 2009 April 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6 7 1 2 3 4 5 6 7 1 2 3 4
+ 8 9 10 11 12 13 14 8 9 10 11 12 13 14 5 6 7 8 9 10 11
+15 16 17 18 19 20 21 15 16 17 18 19 20 21 12 13 14 15 16 17 18
+22 23 24 25 26 27 28 22 23 24 25 26 27 28 19 20 21 22 23 24 25
+ 29 30 31 26 27 28 29 30
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200904-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200904-jd-nhl.out
new file mode 100644
index 000000000000..d559f32c441a
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200904-jd-nhl.out
@@ -0,0 +1,18 @@
+ 2009
+ March April
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 60 61 62 63 64 65 66 91 92 93 94
+ 67 68 69 70 71 72 73 95 96 97 98 99 100 101
+ 74 75 76 77 78 79 80 102 103 104 105 106 107 108
+ 81 82 83 84 85 86 87 109 110 111 112 113 114 115
+ 88 89 90 116 117 118 119 120
+
+
+ May
+ Su Mo Tu We Th Fr Sa
+ 121 122
+123 124 125 126 127 128 129
+130 131 132 133 134 135 136
+137 138 139 140 141 142 143
+144 145 146 147 148 149 150
+151
diff --git a/usr.bin/ncal/tests/regress.b-3m200904-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200904-md-nhl.out
new file mode 100644
index 000000000000..0df9a7599402
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200904-md-nhl.out
@@ -0,0 +1,8 @@
+ March 2009 April 2009 May 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6 7 1 2 3 4 1 2
+ 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3 4 5 6 7 8 9
+15 16 17 18 19 20 21 12 13 14 15 16 17 18 10 11 12 13 14 15 16
+22 23 24 25 26 27 28 19 20 21 22 23 24 25 17 18 19 20 21 22 23
+29 30 31 26 27 28 29 30 24 25 26 27 28 29 30
+ 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200905-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200905-jd-nhl.out
new file mode 100644
index 000000000000..35d9c2bf224a
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200905-jd-nhl.out
@@ -0,0 +1,17 @@
+ April 2009 May 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 91 92 93 94 121 122
+ 95 96 97 98 99 100 101 123 124 125 126 127 128 129
+102 103 104 105 106 107 108 130 131 132 133 134 135 136
+109 110 111 112 113 114 115 137 138 139 140 141 142 143
+116 117 118 119 120 144 145 146 147 148 149 150
+ 151
+
+ June 2009
+ Su Mo Tu We Th Fr Sa
+ 152 153 154 155 156 157
+158 159 160 161 162 163 164
+165 166 167 168 169 170 171
+172 173 174 175 176 177 178
+179 180 181
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200905-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200905-md-nhl.out
new file mode 100644
index 000000000000..3ee495d89ae2
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200905-md-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ April May June
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 1 2 1 2 3 4 5 6
+ 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
+12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
+19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
+26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
+ 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200906-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200906-jd-nhl.out
new file mode 100644
index 000000000000..47f95b09611c
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200906-jd-nhl.out
@@ -0,0 +1,18 @@
+ 2009
+ May June
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 121 122 152 153 154 155 156 157
+123 124 125 126 127 128 129 158 159 160 161 162 163 164
+130 131 132 133 134 135 136 165 166 167 168 169 170 171
+137 138 139 140 141 142 143 172 173 174 175 176 177 178
+144 145 146 147 148 149 150 179 180 181
+151
+
+ July
+ Su Mo Tu We Th Fr Sa
+ 182 183 184 185
+186 187 188 189 190 191 192
+193 194 195 196 197 198 199
+200 201 202 203 204 205 206
+207 208 209 210 211 212
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200906-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200906-md-nhl.out
new file mode 100644
index 000000000000..a6c1dcd209bb
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200906-md-nhl.out
@@ -0,0 +1,8 @@
+ May 2009 June 2009 July 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 2 3 4 5 6 1 2 3 4
+ 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
+10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
+17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
+24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
+31
diff --git a/usr.bin/ncal/tests/regress.b-3m200907-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200907-jd-nhl.out
new file mode 100644
index 000000000000..9d9620803f66
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200907-jd-nhl.out
@@ -0,0 +1,17 @@
+ June 2009 July 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 152 153 154 155 156 157 182 183 184 185
+158 159 160 161 162 163 164 186 187 188 189 190 191 192
+165 166 167 168 169 170 171 193 194 195 196 197 198 199
+172 173 174 175 176 177 178 200 201 202 203 204 205 206
+179 180 181 207 208 209 210 211 212
+
+
+ August 2009
+ Su Mo Tu We Th Fr Sa
+ 213
+214 215 216 217 218 219 220
+221 222 223 224 225 226 227
+228 229 230 231 232 233 234
+235 236 237 238 239 240 241
+242 243
diff --git a/usr.bin/ncal/tests/regress.b-3m200907-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200907-md-nhl.out
new file mode 100644
index 000000000000..9b762e2cd76d
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200907-md-nhl.out
@@ -0,0 +1,8 @@
+ June 2009 July 2009 August 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6 1 2 3 4 1
+ 7 8 9 10 11 12 13 5 6 7 8 9 10 11 2 3 4 5 6 7 8
+14 15 16 17 18 19 20 12 13 14 15 16 17 18 9 10 11 12 13 14 15
+21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22
+28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29
+ 30 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200908-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200908-jd-nhl.out
new file mode 100644
index 000000000000..768de3f502ba
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200908-jd-nhl.out
@@ -0,0 +1,18 @@
+ 2009
+ July August
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 182 183 184 185 213
+186 187 188 189 190 191 192 214 215 216 217 218 219 220
+193 194 195 196 197 198 199 221 222 223 224 225 226 227
+200 201 202 203 204 205 206 228 229 230 231 232 233 234
+207 208 209 210 211 212 235 236 237 238 239 240 241
+ 242 243
+
+ September
+ Su Mo Tu We Th Fr Sa
+ 244 245 246 247 248
+249 250 251 252 253 254 255
+256 257 258 259 260 261 262
+263 264 265 266 267 268 269
+270 271 272 273
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200908-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200908-md-nhl.out
new file mode 100644
index 000000000000..339870e7e3ff
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200908-md-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ July August September
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 1 1 2 3 4 5
+ 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
+26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
+ 30 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200909-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200909-jd-nhl.out
new file mode 100644
index 000000000000..befa00da5892
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200909-jd-nhl.out
@@ -0,0 +1,17 @@
+ August 2009 September 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 213 244 245 246 247 248
+214 215 216 217 218 219 220 249 250 251 252 253 254 255
+221 222 223 224 225 226 227 256 257 258 259 260 261 262
+228 229 230 231 232 233 234 263 264 265 266 267 268 269
+235 236 237 238 239 240 241 270 271 272 273
+242 243
+
+ October 2009
+ Su Mo Tu We Th Fr Sa
+ 274 275 276
+277 278 279 280 281 282 283
+284 285 286 287 288 289 290
+291 292 293 294 295 296 297
+298 299 300 301 302 303 304
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200909-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200909-md-nhl.out
new file mode 100644
index 000000000000..4fb27146e034
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200909-md-nhl.out
@@ -0,0 +1,8 @@
+ August 2009 September 2009 October 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 1 2 3 4 5 1 2 3
+ 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10
+ 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17
+16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24
+23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31
+30 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200910-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200910-jd-nhl.out
new file mode 100644
index 000000000000..0a29593f589c
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200910-jd-nhl.out
@@ -0,0 +1,18 @@
+ 2009
+ September October
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 244 245 246 247 248 274 275 276
+249 250 251 252 253 254 255 277 278 279 280 281 282 283
+256 257 258 259 260 261 262 284 285 286 287 288 289 290
+263 264 265 266 267 268 269 291 292 293 294 295 296 297
+270 271 272 273 298 299 300 301 302 303 304
+
+
+ November
+ Su Mo Tu We Th Fr Sa
+305 306 307 308 309 310 311
+312 313 314 315 316 317 318
+319 320 321 322 323 324 325
+326 327 328 329 330 331 332
+333 334
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200910-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200910-md-nhl.out
new file mode 100644
index 000000000000..29cd67e76752
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200910-md-nhl.out
@@ -0,0 +1,8 @@
+ September 2009 October 2009 November 2009
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
+ 6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14
+13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21
+20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28
+27 28 29 30 25 26 27 28 29 30 31 29 30
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200911-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200911-jd-nhl.out
new file mode 100644
index 000000000000..4969cbcfab4e
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200911-jd-nhl.out
@@ -0,0 +1,17 @@
+ October 2009 November 2009
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 274 275 276 305 306 307 308 309 310 311
+277 278 279 280 281 282 283 312 313 314 315 316 317 318
+284 285 286 287 288 289 290 319 320 321 322 323 324 325
+291 292 293 294 295 296 297 326 327 328 329 330 331 332
+298 299 300 301 302 303 304 333 334
+
+
+ December 2009
+ Su Mo Tu We Th Fr Sa
+ 335 336 337 338 339
+340 341 342 343 344 345 346
+347 348 349 350 351 352 353
+354 355 356 357 358 359 360
+361 362 363 364 365
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200911-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200911-md-nhl.out
new file mode 100644
index 000000000000..b1f57ff10ccb
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200911-md-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ October November December
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
+ 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
+11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
+18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
+25 26 27 28 29 30 31 29 30 27 28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.b-3m200912-jd-nhl.out b/usr.bin/ncal/tests/regress.b-3m200912-jd-nhl.out
new file mode 100644
index 000000000000..61480a51807d
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200912-jd-nhl.out
@@ -0,0 +1,19 @@
+ 2009
+ November December
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+305 306 307 308 309 310 311 335 336 337 338 339
+312 313 314 315 316 317 318 340 341 342 343 344 345 346
+319 320 321 322 323 324 325 347 348 349 350 351 352 353
+326 327 328 329 330 331 332 354 355 356 357 358 359 360
+333 334 361 362 363 364 365
+
+
+ 2010
+ January
+ Su Mo Tu We Th Fr Sa
+ 1 2
+ 3 4 5 6 7 8 9
+ 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23
+ 24 25 26 27 28 29 30
+ 31
diff --git a/usr.bin/ncal/tests/regress.b-3m200912-md-nhl.out b/usr.bin/ncal/tests/regress.b-3m200912-md-nhl.out
new file mode 100644
index 000000000000..fd4d22039778
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-3m200912-md-nhl.out
@@ -0,0 +1,8 @@
+ November 2009 December 2009 January 2010
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6 7 1 2 3 4 5 1 2
+ 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9
+15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16
+22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23
+29 30 27 28 29 30 31 24 25 26 27 28 29 30
+ 31
diff --git a/usr.bin/ncal/tests/regress.b-y2008-jd-nhl.out b/usr.bin/ncal/tests/regress.b-y2008-jd-nhl.out
new file mode 100644
index 000000000000..cd423db3e5a0
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2008-jd-nhl.out
@@ -0,0 +1,54 @@
+ 2008
+ January February
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 32 33
+ 6 7 8 9 10 11 12 34 35 36 37 38 39 40
+ 13 14 15 16 17 18 19 41 42 43 44 45 46 47
+ 20 21 22 23 24 25 26 48 49 50 51 52 53 54
+ 27 28 29 30 31 55 56 57 58 59 60
+
+
+ March April
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 61 92 93 94 95 96
+ 62 63 64 65 66 67 68 97 98 99 100 101 102 103
+ 69 70 71 72 73 74 75 104 105 106 107 108 109 110
+ 76 77 78 79 80 81 82 111 112 113 114 115 116 117
+ 83 84 85 86 87 88 89 118 119 120 121
+ 90 91
+
+ May June
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 122 123 124 153 154 155 156 157 158 159
+125 126 127 128 129 130 131 160 161 162 163 164 165 166
+132 133 134 135 136 137 138 167 168 169 170 171 172 173
+139 140 141 142 143 144 145 174 175 176 177 178 179 180
+146 147 148 149 150 151 152 181 182
+
+
+ July August
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 183 184 185 186 187 214 215
+188 189 190 191 192 193 194 216 217 218 219 220 221 222
+195 196 197 198 199 200 201 223 224 225 226 227 228 229
+202 203 204 205 206 207 208 230 231 232 233 234 235 236
+209 210 211 212 213 237 238 239 240 241 242 243
+ 244
+
+ September October
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 245 246 247 248 249 250 275 276 277 278
+251 252 253 254 255 256 257 279 280 281 282 283 284 285
+258 259 260 261 262 263 264 286 287 288 289 290 291 292
+265 266 267 268 269 270 271 293 294 295 296 297 298 299
+272 273 274 300 301 302 303 304 305
+
+
+ November December
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 306 336 337 338 339 340 341
+307 308 309 310 311 312 313 342 343 344 345 346 347 348
+314 315 316 317 318 319 320 349 350 351 352 353 354 355
+321 322 323 324 325 326 327 356 357 358 359 360 361 362
+328 329 330 331 332 333 334 363 364 365 366
+335
diff --git a/usr.bin/ncal/tests/regress.b-y2008-md-nhl.out b/usr.bin/ncal/tests/regress.b-y2008-md-nhl.out
new file mode 100644
index 000000000000..dcd96fcb0527
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2008-md-nhl.out
@@ -0,0 +1,36 @@
+ 2008
+ January February March
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 1 2 1
+ 6 7 8 9 10 11 12 3 4 5 6 7 8 9 2 3 4 5 6 7 8
+13 14 15 16 17 18 19 10 11 12 13 14 15 16 9 10 11 12 13 14 15
+20 21 22 23 24 25 26 17 18 19 20 21 22 23 16 17 18 19 20 21 22
+27 28 29 30 31 24 25 26 27 28 29 23 24 25 26 27 28 29
+ 30 31
+
+ April May June
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
+ 6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14
+13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21
+20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28
+27 28 29 30 25 26 27 28 29 30 31 29 30
+
+
+ July August September
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 1 2 1 2 3 4 5 6
+ 6 7 8 9 10 11 12 3 4 5 6 7 8 9 7 8 9 10 11 12 13
+13 14 15 16 17 18 19 10 11 12 13 14 15 16 14 15 16 17 18 19 20
+20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27
+27 28 29 30 31 24 25 26 27 28 29 30 28 29 30
+ 31
+
+ October November December
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 1 1 2 3 4 5 6
+ 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13
+12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20
+19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27
+26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31
+ 30
diff --git a/usr.bin/ncal/tests/regress.b-y2009-jd-nhl.out b/usr.bin/ncal/tests/regress.b-y2009-jd-nhl.out
new file mode 100644
index 000000000000..db22d05cc642
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2009-jd-nhl.out
@@ -0,0 +1,54 @@
+ 2009
+ January February
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 32 33 34 35 36 37 38
+ 4 5 6 7 8 9 10 39 40 41 42 43 44 45
+ 11 12 13 14 15 16 17 46 47 48 49 50 51 52
+ 18 19 20 21 22 23 24 53 54 55 56 57 58 59
+ 25 26 27 28 29 30 31
+
+
+ March April
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 60 61 62 63 64 65 66 91 92 93 94
+ 67 68 69 70 71 72 73 95 96 97 98 99 100 101
+ 74 75 76 77 78 79 80 102 103 104 105 106 107 108
+ 81 82 83 84 85 86 87 109 110 111 112 113 114 115
+ 88 89 90 116 117 118 119 120
+
+
+ May June
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 121 122 152 153 154 155 156 157
+123 124 125 126 127 128 129 158 159 160 161 162 163 164
+130 131 132 133 134 135 136 165 166 167 168 169 170 171
+137 138 139 140 141 142 143 172 173 174 175 176 177 178
+144 145 146 147 148 149 150 179 180 181
+151
+
+ July August
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 182 183 184 185 213
+186 187 188 189 190 191 192 214 215 216 217 218 219 220
+193 194 195 196 197 198 199 221 222 223 224 225 226 227
+200 201 202 203 204 205 206 228 229 230 231 232 233 234
+207 208 209 210 211 212 235 236 237 238 239 240 241
+ 242 243
+
+ September October
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 244 245 246 247 248 274 275 276
+249 250 251 252 253 254 255 277 278 279 280 281 282 283
+256 257 258 259 260 261 262 284 285 286 287 288 289 290
+263 264 265 266 267 268 269 291 292 293 294 295 296 297
+270 271 272 273 298 299 300 301 302 303 304
+
+
+ November December
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+305 306 307 308 309 310 311 335 336 337 338 339
+312 313 314 315 316 317 318 340 341 342 343 344 345 346
+319 320 321 322 323 324 325 347 348 349 350 351 352 353
+326 327 328 329 330 331 332 354 355 356 357 358 359 360
+333 334 361 362 363 364 365
+
diff --git a/usr.bin/ncal/tests/regress.b-y2009-md-nhl.out b/usr.bin/ncal/tests/regress.b-y2009-md-nhl.out
new file mode 100644
index 000000000000..c9f084ee368e
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2009-md-nhl.out
@@ -0,0 +1,36 @@
+ 2009
+ January February March
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
+ 4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
+11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
+18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
+25 26 27 28 29 30 31 29 30 31
+
+
+ April May June
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 1 2 1 2 3 4 5 6
+ 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
+12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
+19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
+26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
+ 31
+
+ July August September
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 4 1 1 2 3 4 5
+ 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
+26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
+ 30 31
+
+ October November December
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
+ 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
+11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
+18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
+25 26 27 28 29 30 31 29 30 27 28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.b-y2010-jd-nhl.out b/usr.bin/ncal/tests/regress.b-y2010-jd-nhl.out
new file mode 100644
index 000000000000..d7ad9fc415d2
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2010-jd-nhl.out
@@ -0,0 +1,54 @@
+ 2010
+ January February
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 32 33 34 35 36 37
+ 3 4 5 6 7 8 9 38 39 40 41 42 43 44
+ 10 11 12 13 14 15 16 45 46 47 48 49 50 51
+ 17 18 19 20 21 22 23 52 53 54 55 56 57 58
+ 24 25 26 27 28 29 30 59
+ 31
+
+ March April
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 60 61 62 63 64 65 91 92 93
+ 66 67 68 69 70 71 72 94 95 96 97 98 99 100
+ 73 74 75 76 77 78 79 101 102 103 104 105 106 107
+ 80 81 82 83 84 85 86 108 109 110 111 112 113 114
+ 87 88 89 90 115 116 117 118 119 120
+
+
+ May June
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 121 152 153 154 155 156
+122 123 124 125 126 127 128 157 158 159 160 161 162 163
+129 130 131 132 133 134 135 164 165 166 167 168 169 170
+136 137 138 139 140 141 142 171 172 173 174 175 176 177
+143 144 145 146 147 148 149 178 179 180 181
+150 151
+
+ July August
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 182 183 184 213 214 215 216 217 218 219
+185 186 187 188 189 190 191 220 221 222 223 224 225 226
+192 193 194 195 196 197 198 227 228 229 230 231 232 233
+199 200 201 202 203 204 205 234 235 236 237 238 239 240
+206 207 208 209 210 211 212 241 242 243
+
+
+ September October
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 244 245 246 247 274 275
+248 249 250 251 252 253 254 276 277 278 279 280 281 282
+255 256 257 258 259 260 261 283 284 285 286 287 288 289
+262 263 264 265 266 267 268 290 291 292 293 294 295 296
+269 270 271 272 273 297 298 299 300 301 302 303
+ 304
+
+ November December
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 305 306 307 308 309 310 335 336 337 338
+311 312 313 314 315 316 317 339 340 341 342 343 344 345
+318 319 320 321 322 323 324 346 347 348 349 350 351 352
+325 326 327 328 329 330 331 353 354 355 356 357 358 359
+332 333 334 360 361 362 363 364 365
+
diff --git a/usr.bin/ncal/tests/regress.b-y2010-md-nhl.out b/usr.bin/ncal/tests/regress.b-y2010-md-nhl.out
new file mode 100644
index 000000000000..1d8a410d9d92
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2010-md-nhl.out
@@ -0,0 +1,36 @@
+ 2010
+ January February March
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 2 3 4 5 6 1 2 3 4 5 6
+ 3 4 5 6 7 8 9 7 8 9 10 11 12 13 7 8 9 10 11 12 13
+10 11 12 13 14 15 16 14 15 16 17 18 19 20 14 15 16 17 18 19 20
+17 18 19 20 21 22 23 21 22 23 24 25 26 27 21 22 23 24 25 26 27
+24 25 26 27 28 29 30 28 28 29 30 31
+31
+
+ April May June
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 1 2 3 4 5
+ 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
+25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30
+ 30 31
+
+ July August September
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 3 1 2 3 4 5 6 7 1 2 3 4
+ 4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11
+11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18
+18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25
+25 26 27 28 29 30 31 29 30 31 26 27 28 29 30
+
+
+ October November December
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 2 3 4 5 6 1 2 3 4
+ 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
+10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
+17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
+24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
+31
diff --git a/usr.bin/ncal/tests/regress.b-y2011-jd-nhl.out b/usr.bin/ncal/tests/regress.b-y2011-jd-nhl.out
new file mode 100644
index 000000000000..31abb4efa28a
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2011-jd-nhl.out
@@ -0,0 +1,54 @@
+ 2011
+ January February
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 32 33 34 35 36
+ 2 3 4 5 6 7 8 37 38 39 40 41 42 43
+ 9 10 11 12 13 14 15 44 45 46 47 48 49 50
+ 16 17 18 19 20 21 22 51 52 53 54 55 56 57
+ 23 24 25 26 27 28 29 58 59
+ 30 31
+
+ March April
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 60 61 62 63 64 91 92
+ 65 66 67 68 69 70 71 93 94 95 96 97 98 99
+ 72 73 74 75 76 77 78 100 101 102 103 104 105 106
+ 79 80 81 82 83 84 85 107 108 109 110 111 112 113
+ 86 87 88 89 90 114 115 116 117 118 119 120
+
+
+ May June
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+121 122 123 124 125 126 127 152 153 154 155
+128 129 130 131 132 133 134 156 157 158 159 160 161 162
+135 136 137 138 139 140 141 163 164 165 166 167 168 169
+142 143 144 145 146 147 148 170 171 172 173 174 175 176
+149 150 151 177 178 179 180 181
+
+
+ July August
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 182 183 213 214 215 216 217 218
+184 185 186 187 188 189 190 219 220 221 222 223 224 225
+191 192 193 194 195 196 197 226 227 228 229 230 231 232
+198 199 200 201 202 203 204 233 234 235 236 237 238 239
+205 206 207 208 209 210 211 240 241 242 243
+212
+
+ September October
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 244 245 246 274
+247 248 249 250 251 252 253 275 276 277 278 279 280 281
+254 255 256 257 258 259 260 282 283 284 285 286 287 288
+261 262 263 264 265 266 267 289 290 291 292 293 294 295
+268 269 270 271 272 273 296 297 298 299 300 301 302
+ 303 304
+
+ November December
+ Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 305 306 307 308 309 335 336 337
+310 311 312 313 314 315 316 338 339 340 341 342 343 344
+317 318 319 320 321 322 323 345 346 347 348 349 350 351
+324 325 326 327 328 329 330 352 353 354 355 356 357 358
+331 332 333 334 359 360 361 362 363 364 365
+
diff --git a/usr.bin/ncal/tests/regress.b-y2011-md-nhl.out b/usr.bin/ncal/tests/regress.b-y2011-md-nhl.out
new file mode 100644
index 000000000000..d76a44fa7dbd
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.b-y2011-md-nhl.out
@@ -0,0 +1,36 @@
+ 2011
+ January February March
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 1 2 3 4 5 1 2 3 4 5
+ 2 3 4 5 6 7 8 6 7 8 9 10 11 12 6 7 8 9 10 11 12
+ 9 10 11 12 13 14 15 13 14 15 16 17 18 19 13 14 15 16 17 18 19
+16 17 18 19 20 21 22 20 21 22 23 24 25 26 20 21 22 23 24 25 26
+23 24 25 26 27 28 29 27 28 27 28 29 30 31
+30 31
+
+ April May June
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 2 3 4 5 6 7 1 2 3 4
+ 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11
+10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18
+17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25
+24 25 26 27 28 29 30 29 30 31 26 27 28 29 30
+
+
+ July August September
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 2 3 4 5 6 1 2 3
+ 3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10
+10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17
+17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24
+24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30
+31
+
+ October November December
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 1 2 3 4 5 1 2 3
+ 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10
+ 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17
+16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24
+23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31
+30 31
diff --git a/usr.bin/ncal/tests/regress.f-3A-nhl.out b/usr.bin/ncal/tests/regress.f-3A-nhl.out
new file mode 100644
index 000000000000..e7f5e91ed3e8
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-3A-nhl.out
@@ -0,0 +1 @@
+ncal: -3 together with -A and -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-3AB-nhl.out b/usr.bin/ncal/tests/regress.f-3AB-nhl.out
new file mode 100644
index 000000000000..e7f5e91ed3e8
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-3AB-nhl.out
@@ -0,0 +1 @@
+ncal: -3 together with -A and -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-3B-nhl.out b/usr.bin/ncal/tests/regress.f-3B-nhl.out
new file mode 100644
index 000000000000..e7f5e91ed3e8
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-3B-nhl.out
@@ -0,0 +1 @@
+ncal: -3 together with -A and -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-3gy-nhl.out b/usr.bin/ncal/tests/regress.f-3gy-nhl.out
new file mode 100644
index 000000000000..018646fa27d0
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-3gy-nhl.out
@@ -0,0 +1 @@
+ncal: -3 together with a given year but no given month is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-3y-nhl.out b/usr.bin/ncal/tests/regress.f-3y-nhl.out
new file mode 100644
index 000000000000..5b2e00064e66
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-3y-nhl.out
@@ -0,0 +1 @@
+ncal: -3 together with -y is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-mgm-nhl.out b/usr.bin/ncal/tests/regress.f-mgm-nhl.out
new file mode 100644
index 000000000000..5f6c2eb9ee52
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-mgm-nhl.out
@@ -0,0 +1 @@
+ncal: -m together with a given month is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-yA-nhl.out b/usr.bin/ncal/tests/regress.f-yA-nhl.out
new file mode 100644
index 000000000000..ce39ae751705
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-yA-nhl.out
@@ -0,0 +1 @@
+ncal: -y together a -A or -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-yAB-nhl.out b/usr.bin/ncal/tests/regress.f-yAB-nhl.out
new file mode 100644
index 000000000000..ce39ae751705
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-yAB-nhl.out
@@ -0,0 +1 @@
+ncal: -y together a -A or -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-yB-nhl.out b/usr.bin/ncal/tests/regress.f-yB-nhl.out
new file mode 100644
index 000000000000..ce39ae751705
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-yB-nhl.out
@@ -0,0 +1 @@
+ncal: -y together a -A or -B is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-ygm-nhl.out b/usr.bin/ncal/tests/regress.f-ygm-nhl.out
new file mode 100644
index 000000000000..6f898eb8899d
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-ygm-nhl.out
@@ -0,0 +1 @@
+ncal: -y together a given month is not supported.
diff --git a/usr.bin/ncal/tests/regress.f-ym-nhl.out b/usr.bin/ncal/tests/regress.f-ym-nhl.out
new file mode 100644
index 000000000000..1921d923b962
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.f-ym-nhl.out
@@ -0,0 +1 @@
+ncal: -y together with -m is not supported.
diff --git a/usr.bin/ncal/tests/regress.r-3m200901-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200901-jd-nhl.out
new file mode 100644
index 000000000000..26ef49b4ea79
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200901-jd-nhl.out
@@ -0,0 +1,8 @@
+ December 2008 January 2009 February 2009
+Mo 336 343 350 357 364 5 12 19 26 33 40 47 54
+Tu 337 344 351 358 365 6 13 20 27 34 41 48 55
+We 338 345 352 359 366 7 14 21 28 35 42 49 56
+Th 339 346 353 360 1 8 15 22 29 36 43 50 57
+Fr 340 347 354 361 2 9 16 23 30 37 44 51 58
+Sa 341 348 355 362 3 10 17 24 31 38 45 52 59
+Su 342 349 356 363 4 11 18 25 32 39 46 53
diff --git a/usr.bin/ncal/tests/regress.r-3m200901-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200901-md-nhl.out
new file mode 100644
index 000000000000..d197fd360456
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200901-md-nhl.out
@@ -0,0 +1,8 @@
+ December 2008 January 2009 February 2009
+Mo 1 8 15 22 29 5 12 19 26 2 9 16 23
+Tu 2 9 16 23 30 6 13 20 27 3 10 17 24
+We 3 10 17 24 31 7 14 21 28 4 11 18 25
+Th 4 11 18 25 1 8 15 22 29 5 12 19 26
+Fr 5 12 19 26 2 9 16 23 30 6 13 20 27
+Sa 6 13 20 27 3 10 17 24 31 7 14 21 28
+Su 7 14 21 28 4 11 18 25 1 8 15 22
diff --git a/usr.bin/ncal/tests/regress.r-3m200902-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200902-jd-nhl.out
new file mode 100644
index 000000000000..cd8486942afa
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200902-jd-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ January February March
+Mo 5 12 19 26 33 40 47 54 61 68 75 82 89
+Tu 6 13 20 27 34 41 48 55 62 69 76 83 90
+We 7 14 21 28 35 42 49 56 63 70 77 84
+Th 1 8 15 22 29 36 43 50 57 64 71 78 85
+Fr 2 9 16 23 30 37 44 51 58 65 72 79 86
+Sa 3 10 17 24 31 38 45 52 59 66 73 80 87
+Su 4 11 18 25 32 39 46 53 60 67 74 81 88
diff --git a/usr.bin/ncal/tests/regress.r-3m200902-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200902-md-nhl.out
new file mode 100644
index 000000000000..20c35f1df058
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200902-md-nhl.out
@@ -0,0 +1,8 @@
+ January 2009 February 2009 March 2009
+Mo 5 12 19 26 2 9 16 23 2 9 16 23 30
+Tu 6 13 20 27 3 10 17 24 3 10 17 24 31
+We 7 14 21 28 4 11 18 25 4 11 18 25
+Th 1 8 15 22 29 5 12 19 26 5 12 19 26
+Fr 2 9 16 23 30 6 13 20 27 6 13 20 27
+Sa 3 10 17 24 31 7 14 21 28 7 14 21 28
+Su 4 11 18 25 1 8 15 22 1 8 15 22 29
diff --git a/usr.bin/ncal/tests/regress.r-3m200903-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200903-jd-nhl.out
new file mode 100644
index 000000000000..1ca28e0014a6
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200903-jd-nhl.out
@@ -0,0 +1,8 @@
+ February 2009 March 2009 April 2009
+Mo 33 40 47 54 61 68 75 82 89 96 103 110 117
+Tu 34 41 48 55 62 69 76 83 90 97 104 111 118
+We 35 42 49 56 63 70 77 84 91 98 105 112 119
+Th 36 43 50 57 64 71 78 85 92 99 106 113 120
+Fr 37 44 51 58 65 72 79 86 93 100 107 114
+Sa 38 45 52 59 66 73 80 87 94 101 108 115
+Su 32 39 46 53 60 67 74 81 88 95 102 109 116
diff --git a/usr.bin/ncal/tests/regress.r-3m200903-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200903-md-nhl.out
new file mode 100644
index 000000000000..19fc969fb962
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200903-md-nhl.out
@@ -0,0 +1,8 @@
+ February 2009 March 2009 April 2009
+Mo 2 9 16 23 2 9 16 23 30 6 13 20 27
+Tu 3 10 17 24 3 10 17 24 31 7 14 21 28
+We 4 11 18 25 4 11 18 25 1 8 15 22 29
+Th 5 12 19 26 5 12 19 26 2 9 16 23 30
+Fr 6 13 20 27 6 13 20 27 3 10 17 24
+Sa 7 14 21 28 7 14 21 28 4 11 18 25
+Su 1 8 15 22 1 8 15 22 29 5 12 19 26
diff --git a/usr.bin/ncal/tests/regress.r-3m200904-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200904-jd-nhl.out
new file mode 100644
index 000000000000..8b8e77a4acac
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200904-jd-nhl.out
@@ -0,0 +1,8 @@
+ March 2009 April 2009 May 2009
+Mo 61 68 75 82 89 96 103 110 117 124 131 138 145
+Tu 62 69 76 83 90 97 104 111 118 125 132 139 146
+We 63 70 77 84 91 98 105 112 119 126 133 140 147
+Th 64 71 78 85 92 99 106 113 120 127 134 141 148
+Fr 65 72 79 86 93 100 107 114 121 128 135 142 149
+Sa 66 73 80 87 94 101 108 115 122 129 136 143 150
+Su 60 67 74 81 88 95 102 109 116 123 130 137 144 151
diff --git a/usr.bin/ncal/tests/regress.r-3m200904-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200904-md-nhl.out
new file mode 100644
index 000000000000..449127c70354
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200904-md-nhl.out
@@ -0,0 +1,8 @@
+ March 2009 April 2009 May 2009
+Mo 2 9 16 23 30 6 13 20 27 4 11 18 25
+Tu 3 10 17 24 31 7 14 21 28 5 12 19 26
+We 4 11 18 25 1 8 15 22 29 6 13 20 27
+Th 5 12 19 26 2 9 16 23 30 7 14 21 28
+Fr 6 13 20 27 3 10 17 24 1 8 15 22 29
+Sa 7 14 21 28 4 11 18 25 2 9 16 23 30
+Su 1 8 15 22 29 5 12 19 26 3 10 17 24 31
diff --git a/usr.bin/ncal/tests/regress.r-3m200905-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200905-jd-nhl.out
new file mode 100644
index 000000000000..9054a1f109aa
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200905-jd-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ April May June
+Mo 96 103 110 117 124 131 138 145 152 159 166 173 180
+Tu 97 104 111 118 125 132 139 146 153 160 167 174 181
+We 91 98 105 112 119 126 133 140 147 154 161 168 175
+Th 92 99 106 113 120 127 134 141 148 155 162 169 176
+Fr 93 100 107 114 121 128 135 142 149 156 163 170 177
+Sa 94 101 108 115 122 129 136 143 150 157 164 171 178
+Su 95 102 109 116 123 130 137 144 151 158 165 172 179
diff --git a/usr.bin/ncal/tests/regress.r-3m200905-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200905-md-nhl.out
new file mode 100644
index 000000000000..4a6a63555d6f
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200905-md-nhl.out
@@ -0,0 +1,8 @@
+ April 2009 May 2009 June 2009
+Mo 6 13 20 27 4 11 18 25 1 8 15 22 29
+Tu 7 14 21 28 5 12 19 26 2 9 16 23 30
+We 1 8 15 22 29 6 13 20 27 3 10 17 24
+Th 2 9 16 23 30 7 14 21 28 4 11 18 25
+Fr 3 10 17 24 1 8 15 22 29 5 12 19 26
+Sa 4 11 18 25 2 9 16 23 30 6 13 20 27
+Su 5 12 19 26 3 10 17 24 31 7 14 21 28
diff --git a/usr.bin/ncal/tests/regress.r-3m200906-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200906-jd-nhl.out
new file mode 100644
index 000000000000..6eb35eb52455
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200906-jd-nhl.out
@@ -0,0 +1,8 @@
+ May 2009 June 2009 July 2009
+Mo 124 131 138 145 152 159 166 173 180 187 194 201 208
+Tu 125 132 139 146 153 160 167 174 181 188 195 202 209
+We 126 133 140 147 154 161 168 175 182 189 196 203 210
+Th 127 134 141 148 155 162 169 176 183 190 197 204 211
+Fr 121 128 135 142 149 156 163 170 177 184 191 198 205 212
+Sa 122 129 136 143 150 157 164 171 178 185 192 199 206
+Su 123 130 137 144 151 158 165 172 179 186 193 200 207
diff --git a/usr.bin/ncal/tests/regress.r-3m200906-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200906-md-nhl.out
new file mode 100644
index 000000000000..53f1274c7a59
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200906-md-nhl.out
@@ -0,0 +1,8 @@
+ May 2009 June 2009 July 2009
+Mo 4 11 18 25 1 8 15 22 29 6 13 20 27
+Tu 5 12 19 26 2 9 16 23 30 7 14 21 28
+We 6 13 20 27 3 10 17 24 1 8 15 22 29
+Th 7 14 21 28 4 11 18 25 2 9 16 23 30
+Fr 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Sa 2 9 16 23 30 6 13 20 27 4 11 18 25
+Su 3 10 17 24 31 7 14 21 28 5 12 19 26
diff --git a/usr.bin/ncal/tests/regress.r-3m200907-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200907-jd-nhl.out
new file mode 100644
index 000000000000..8c5701a47273
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200907-jd-nhl.out
@@ -0,0 +1,8 @@
+ June 2009 July 2009 August 2009
+Mo 152 159 166 173 180 187 194 201 208 215 222 229 236 243
+Tu 153 160 167 174 181 188 195 202 209 216 223 230 237
+We 154 161 168 175 182 189 196 203 210 217 224 231 238
+Th 155 162 169 176 183 190 197 204 211 218 225 232 239
+Fr 156 163 170 177 184 191 198 205 212 219 226 233 240
+Sa 157 164 171 178 185 192 199 206 213 220 227 234 241
+Su 158 165 172 179 186 193 200 207 214 221 228 235 242
diff --git a/usr.bin/ncal/tests/regress.r-3m200907-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200907-md-nhl.out
new file mode 100644
index 000000000000..f07ea0a5aa14
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200907-md-nhl.out
@@ -0,0 +1,8 @@
+ June 2009 July 2009 August 2009
+Mo 1 8 15 22 29 6 13 20 27 3 10 17 24 31
+Tu 2 9 16 23 30 7 14 21 28 4 11 18 25
+We 3 10 17 24 1 8 15 22 29 5 12 19 26
+Th 4 11 18 25 2 9 16 23 30 6 13 20 27
+Fr 5 12 19 26 3 10 17 24 31 7 14 21 28
+Sa 6 13 20 27 4 11 18 25 1 8 15 22 29
+Su 7 14 21 28 5 12 19 26 2 9 16 23 30
diff --git a/usr.bin/ncal/tests/regress.r-3m200908-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200908-jd-nhl.out
new file mode 100644
index 000000000000..9d5089488bc7
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200908-jd-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ July August September
+Mo 187 194 201 208 215 222 229 236 243 250 257 264 271
+Tu 188 195 202 209 216 223 230 237 244 251 258 265 272
+We 182 189 196 203 210 217 224 231 238 245 252 259 266 273
+Th 183 190 197 204 211 218 225 232 239 246 253 260 267
+Fr 184 191 198 205 212 219 226 233 240 247 254 261 268
+Sa 185 192 199 206 213 220 227 234 241 248 255 262 269
+Su 186 193 200 207 214 221 228 235 242 249 256 263 270
diff --git a/usr.bin/ncal/tests/regress.r-3m200908-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200908-md-nhl.out
new file mode 100644
index 000000000000..e4822eb1f82d
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200908-md-nhl.out
@@ -0,0 +1,8 @@
+ July 2009 August 2009 September 2009
+Mo 6 13 20 27 3 10 17 24 31 7 14 21 28
+Tu 7 14 21 28 4 11 18 25 1 8 15 22 29
+We 1 8 15 22 29 5 12 19 26 2 9 16 23 30
+Th 2 9 16 23 30 6 13 20 27 3 10 17 24
+Fr 3 10 17 24 31 7 14 21 28 4 11 18 25
+Sa 4 11 18 25 1 8 15 22 29 5 12 19 26
+Su 5 12 19 26 2 9 16 23 30 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.r-3m200909-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200909-jd-nhl.out
new file mode 100644
index 000000000000..3bccbf5c333f
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200909-jd-nhl.out
@@ -0,0 +1,8 @@
+ August 2009 September 2009 October 2009
+Mo 215 222 229 236 243 250 257 264 271 278 285 292 299
+Tu 216 223 230 237 244 251 258 265 272 279 286 293 300
+We 217 224 231 238 245 252 259 266 273 280 287 294 301
+Th 218 225 232 239 246 253 260 267 274 281 288 295 302
+Fr 219 226 233 240 247 254 261 268 275 282 289 296 303
+Sa 213 220 227 234 241 248 255 262 269 276 283 290 297 304
+Su 214 221 228 235 242 249 256 263 270 277 284 291 298
diff --git a/usr.bin/ncal/tests/regress.r-3m200909-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200909-md-nhl.out
new file mode 100644
index 000000000000..0c77c2dae762
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200909-md-nhl.out
@@ -0,0 +1,8 @@
+ August 2009 September 2009 October 2009
+Mo 3 10 17 24 31 7 14 21 28 5 12 19 26
+Tu 4 11 18 25 1 8 15 22 29 6 13 20 27
+We 5 12 19 26 2 9 16 23 30 7 14 21 28
+Th 6 13 20 27 3 10 17 24 1 8 15 22 29
+Fr 7 14 21 28 4 11 18 25 2 9 16 23 30
+Sa 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Su 2 9 16 23 30 6 13 20 27 4 11 18 25
diff --git a/usr.bin/ncal/tests/regress.r-3m200910-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200910-jd-nhl.out
new file mode 100644
index 000000000000..f5598e18ca67
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200910-jd-nhl.out
@@ -0,0 +1,8 @@
+ September 2009 October 2009 November 2009
+Mo 250 257 264 271 278 285 292 299 306 313 320 327 334
+Tu 244 251 258 265 272 279 286 293 300 307 314 321 328
+We 245 252 259 266 273 280 287 294 301 308 315 322 329
+Th 246 253 260 267 274 281 288 295 302 309 316 323 330
+Fr 247 254 261 268 275 282 289 296 303 310 317 324 331
+Sa 248 255 262 269 276 283 290 297 304 311 318 325 332
+Su 249 256 263 270 277 284 291 298 305 312 319 326 333
diff --git a/usr.bin/ncal/tests/regress.r-3m200910-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200910-md-nhl.out
new file mode 100644
index 000000000000..18561d291c99
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200910-md-nhl.out
@@ -0,0 +1,8 @@
+ September 2009 October 2009 November 2009
+Mo 7 14 21 28 5 12 19 26 2 9 16 23 30
+Tu 1 8 15 22 29 6 13 20 27 3 10 17 24
+We 2 9 16 23 30 7 14 21 28 4 11 18 25
+Th 3 10 17 24 1 8 15 22 29 5 12 19 26
+Fr 4 11 18 25 2 9 16 23 30 6 13 20 27
+Sa 5 12 19 26 3 10 17 24 31 7 14 21 28
+Su 6 13 20 27 4 11 18 25 1 8 15 22 29
diff --git a/usr.bin/ncal/tests/regress.r-3m200911-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200911-jd-nhl.out
new file mode 100644
index 000000000000..4b8d1dbfdf85
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200911-jd-nhl.out
@@ -0,0 +1,9 @@
+ 2009
+ October November December
+Mo 278 285 292 299 306 313 320 327 334 341 348 355 362
+Tu 279 286 293 300 307 314 321 328 335 342 349 356 363
+We 280 287 294 301 308 315 322 329 336 343 350 357 364
+Th 274 281 288 295 302 309 316 323 330 337 344 351 358 365
+Fr 275 282 289 296 303 310 317 324 331 338 345 352 359
+Sa 276 283 290 297 304 311 318 325 332 339 346 353 360
+Su 277 284 291 298 305 312 319 326 333 340 347 354 361
diff --git a/usr.bin/ncal/tests/regress.r-3m200911-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200911-md-nhl.out
new file mode 100644
index 000000000000..35f137180376
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200911-md-nhl.out
@@ -0,0 +1,8 @@
+ October 2009 November 2009 December 2009
+Mo 5 12 19 26 2 9 16 23 30 7 14 21 28
+Tu 6 13 20 27 3 10 17 24 1 8 15 22 29
+We 7 14 21 28 4 11 18 25 2 9 16 23 30
+Th 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Fr 2 9 16 23 30 6 13 20 27 4 11 18 25
+Sa 3 10 17 24 31 7 14 21 28 5 12 19 26
+Su 4 11 18 25 1 8 15 22 29 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.r-3m200912-jd-nhl.out b/usr.bin/ncal/tests/regress.r-3m200912-jd-nhl.out
new file mode 100644
index 000000000000..66efa298637b
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200912-jd-nhl.out
@@ -0,0 +1,8 @@
+ November 2009 December 2009 January 2010
+Mo 306 313 320 327 334 341 348 355 362 4 11 18 25
+Tu 307 314 321 328 335 342 349 356 363 5 12 19 26
+We 308 315 322 329 336 343 350 357 364 6 13 20 27
+Th 309 316 323 330 337 344 351 358 365 7 14 21 28
+Fr 310 317 324 331 338 345 352 359 1 8 15 22 29
+Sa 311 318 325 332 339 346 353 360 2 9 16 23 30
+Su 305 312 319 326 333 340 347 354 361 3 10 17 24 31
diff --git a/usr.bin/ncal/tests/regress.r-3m200912-md-nhl.out b/usr.bin/ncal/tests/regress.r-3m200912-md-nhl.out
new file mode 100644
index 000000000000..c62332aeb518
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-3m200912-md-nhl.out
@@ -0,0 +1,8 @@
+ November 2009 December 2009 January 2010
+Mo 2 9 16 23 30 7 14 21 28 4 11 18 25
+Tu 3 10 17 24 1 8 15 22 29 5 12 19 26
+We 4 11 18 25 2 9 16 23 30 6 13 20 27
+Th 5 12 19 26 3 10 17 24 31 7 14 21 28
+Fr 6 13 20 27 4 11 18 25 1 8 15 22 29
+Sa 7 14 21 28 5 12 19 26 2 9 16 23 30
+Su 1 8 15 22 29 6 13 20 27 3 10 17 24 31
diff --git a/usr.bin/ncal/tests/regress.r-y2008-jd-nhl.out b/usr.bin/ncal/tests/regress.r-y2008-jd-nhl.out
new file mode 100644
index 000000000000..0ea30ae30549
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2008-jd-nhl.out
@@ -0,0 +1,36 @@
+ 2008
+ January February March
+Mo 7 14 21 28 35 42 49 56 63 70 77 84 91
+Tu 1 8 15 22 29 36 43 50 57 64 71 78 85
+We 2 9 16 23 30 37 44 51 58 65 72 79 86
+Th 3 10 17 24 31 38 45 52 59 66 73 80 87
+Fr 4 11 18 25 32 39 46 53 60 67 74 81 88
+Sa 5 12 19 26 33 40 47 54 61 68 75 82 89
+Su 6 13 20 27 34 41 48 55 62 69 76 83 90
+
+ April May June
+Mo 98 105 112 119 126 133 140 147 154 161 168 175 182
+Tu 92 99 106 113 120 127 134 141 148 155 162 169 176
+We 93 100 107 114 121 128 135 142 149 156 163 170 177
+Th 94 101 108 115 122 129 136 143 150 157 164 171 178
+Fr 95 102 109 116 123 130 137 144 151 158 165 172 179
+Sa 96 103 110 117 124 131 138 145 152 159 166 173 180
+Su 97 104 111 118 125 132 139 146 153 160 167 174 181
+
+ July August September
+Mo 189 196 203 210 217 224 231 238 245 252 259 266 273
+Tu 183 190 197 204 211 218 225 232 239 246 253 260 267 274
+We 184 191 198 205 212 219 226 233 240 247 254 261 268
+Th 185 192 199 206 213 220 227 234 241 248 255 262 269
+Fr 186 193 200 207 214 221 228 235 242 249 256 263 270
+Sa 187 194 201 208 215 222 229 236 243 250 257 264 271
+Su 188 195 202 209 216 223 230 237 244 251 258 265 272
+
+ October November December
+Mo 280 287 294 301 308 315 322 329 336 343 350 357 364
+Tu 281 288 295 302 309 316 323 330 337 344 351 358 365
+We 275 282 289 296 303 310 317 324 331 338 345 352 359 366
+Th 276 283 290 297 304 311 318 325 332 339 346 353 360
+Fr 277 284 291 298 305 312 319 326 333 340 347 354 361
+Sa 278 285 292 299 306 313 320 327 334 341 348 355 362
+Su 279 286 293 300 307 314 321 328 335 342 349 356 363
diff --git a/usr.bin/ncal/tests/regress.r-y2008-md-nhl.out b/usr.bin/ncal/tests/regress.r-y2008-md-nhl.out
new file mode 100644
index 000000000000..18191f6a44b1
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2008-md-nhl.out
@@ -0,0 +1,27 @@
+ 2008
+ January February March April
+Mo 7 14 21 28 4 11 18 25 3 10 17 24 31 7 14 21 28
+Tu 1 8 15 22 29 5 12 19 26 4 11 18 25 1 8 15 22 29
+We 2 9 16 23 30 6 13 20 27 5 12 19 26 2 9 16 23 30
+Th 3 10 17 24 31 7 14 21 28 6 13 20 27 3 10 17 24
+Fr 4 11 18 25 1 8 15 22 29 7 14 21 28 4 11 18 25
+Sa 5 12 19 26 2 9 16 23 1 8 15 22 29 5 12 19 26
+Su 6 13 20 27 3 10 17 24 2 9 16 23 30 6 13 20 27
+
+ May June July August
+Mo 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
+Tu 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
+We 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
+Th 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
+Fr 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
+Sa 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
+Su 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
+
+ September October November December
+Mo 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
+Tu 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
+We 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Th 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
+Fr 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
+Sa 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
+Su 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
diff --git a/usr.bin/ncal/tests/regress.r-y2009-jd-nhl.out b/usr.bin/ncal/tests/regress.r-y2009-jd-nhl.out
new file mode 100644
index 000000000000..3869ace7d6f4
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2009-jd-nhl.out
@@ -0,0 +1,36 @@
+ 2009
+ January February March
+Mo 5 12 19 26 33 40 47 54 61 68 75 82 89
+Tu 6 13 20 27 34 41 48 55 62 69 76 83 90
+We 7 14 21 28 35 42 49 56 63 70 77 84
+Th 1 8 15 22 29 36 43 50 57 64 71 78 85
+Fr 2 9 16 23 30 37 44 51 58 65 72 79 86
+Sa 3 10 17 24 31 38 45 52 59 66 73 80 87
+Su 4 11 18 25 32 39 46 53 60 67 74 81 88
+
+ April May June
+Mo 96 103 110 117 124 131 138 145 152 159 166 173 180
+Tu 97 104 111 118 125 132 139 146 153 160 167 174 181
+We 91 98 105 112 119 126 133 140 147 154 161 168 175
+Th 92 99 106 113 120 127 134 141 148 155 162 169 176
+Fr 93 100 107 114 121 128 135 142 149 156 163 170 177
+Sa 94 101 108 115 122 129 136 143 150 157 164 171 178
+Su 95 102 109 116 123 130 137 144 151 158 165 172 179
+
+ July August September
+Mo 187 194 201 208 215 222 229 236 243 250 257 264 271
+Tu 188 195 202 209 216 223 230 237 244 251 258 265 272
+We 182 189 196 203 210 217 224 231 238 245 252 259 266 273
+Th 183 190 197 204 211 218 225 232 239 246 253 260 267
+Fr 184 191 198 205 212 219 226 233 240 247 254 261 268
+Sa 185 192 199 206 213 220 227 234 241 248 255 262 269
+Su 186 193 200 207 214 221 228 235 242 249 256 263 270
+
+ October November December
+Mo 278 285 292 299 306 313 320 327 334 341 348 355 362
+Tu 279 286 293 300 307 314 321 328 335 342 349 356 363
+We 280 287 294 301 308 315 322 329 336 343 350 357 364
+Th 274 281 288 295 302 309 316 323 330 337 344 351 358 365
+Fr 275 282 289 296 303 310 317 324 331 338 345 352 359
+Sa 276 283 290 297 304 311 318 325 332 339 346 353 360
+Su 277 284 291 298 305 312 319 326 333 340 347 354 361
diff --git a/usr.bin/ncal/tests/regress.r-y2009-md-nhl.out b/usr.bin/ncal/tests/regress.r-y2009-md-nhl.out
new file mode 100644
index 000000000000..43496e9e4da9
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2009-md-nhl.out
@@ -0,0 +1,27 @@
+ 2009
+ January February March April
+Mo 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
+Tu 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
+We 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
+Th 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
+Fr 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
+Sa 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
+Su 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
+
+ May June July August
+Mo 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
+Tu 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
+We 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
+Th 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
+Fr 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
+Sa 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
+Su 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
+
+ September October November December
+Mo 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
+Tu 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
+We 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
+Th 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Fr 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
+Sa 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
+Su 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.r-y2010-jd-nhl.out b/usr.bin/ncal/tests/regress.r-y2010-jd-nhl.out
new file mode 100644
index 000000000000..affd5365c561
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2010-jd-nhl.out
@@ -0,0 +1,36 @@
+ 2010
+ January February March
+Mo 4 11 18 25 32 39 46 53 60 67 74 81 88
+Tu 5 12 19 26 33 40 47 54 61 68 75 82 89
+We 6 13 20 27 34 41 48 55 62 69 76 83 90
+Th 7 14 21 28 35 42 49 56 63 70 77 84
+Fr 1 8 15 22 29 36 43 50 57 64 71 78 85
+Sa 2 9 16 23 30 37 44 51 58 65 72 79 86
+Su 3 10 17 24 31 38 45 52 59 66 73 80 87
+
+ April May June
+Mo 95 102 109 116 123 130 137 144 151 158 165 172 179
+Tu 96 103 110 117 124 131 138 145 152 159 166 173 180
+We 97 104 111 118 125 132 139 146 153 160 167 174 181
+Th 91 98 105 112 119 126 133 140 147 154 161 168 175
+Fr 92 99 106 113 120 127 134 141 148 155 162 169 176
+Sa 93 100 107 114 121 128 135 142 149 156 163 170 177
+Su 94 101 108 115 122 129 136 143 150 157 164 171 178
+
+ July August September
+Mo 186 193 200 207 214 221 228 235 242 249 256 263 270
+Tu 187 194 201 208 215 222 229 236 243 250 257 264 271
+We 188 195 202 209 216 223 230 237 244 251 258 265 272
+Th 182 189 196 203 210 217 224 231 238 245 252 259 266 273
+Fr 183 190 197 204 211 218 225 232 239 246 253 260 267
+Sa 184 191 198 205 212 219 226 233 240 247 254 261 268
+Su 185 192 199 206 213 220 227 234 241 248 255 262 269
+
+ October November December
+Mo 277 284 291 298 305 312 319 326 333 340 347 354 361
+Tu 278 285 292 299 306 313 320 327 334 341 348 355 362
+We 279 286 293 300 307 314 321 328 335 342 349 356 363
+Th 280 287 294 301 308 315 322 329 336 343 350 357 364
+Fr 274 281 288 295 302 309 316 323 330 337 344 351 358 365
+Sa 275 282 289 296 303 310 317 324 331 338 345 352 359
+Su 276 283 290 297 304 311 318 325 332 339 346 353 360
diff --git a/usr.bin/ncal/tests/regress.r-y2010-md-nhl.out b/usr.bin/ncal/tests/regress.r-y2010-md-nhl.out
new file mode 100644
index 000000000000..8649c166a5f8
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2010-md-nhl.out
@@ -0,0 +1,27 @@
+ 2010
+ January February March April
+Mo 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
+Tu 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
+We 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
+Th 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
+Fr 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
+Sa 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
+Su 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
+
+ May June July August
+Mo 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
+Tu 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
+We 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
+Th 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
+Fr 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
+Sa 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
+Su 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
+
+ September October November December
+Mo 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
+Tu 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
+We 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
+Th 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
+Fr 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Sa 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
+Su 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
diff --git a/usr.bin/ncal/tests/regress.r-y2011-jd-nhl.out b/usr.bin/ncal/tests/regress.r-y2011-jd-nhl.out
new file mode 100644
index 000000000000..a4a71c211c69
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2011-jd-nhl.out
@@ -0,0 +1,36 @@
+ 2011
+ January February March
+Mo 3 10 17 24 31 38 45 52 59 66 73 80 87
+Tu 4 11 18 25 32 39 46 53 60 67 74 81 88
+We 5 12 19 26 33 40 47 54 61 68 75 82 89
+Th 6 13 20 27 34 41 48 55 62 69 76 83 90
+Fr 7 14 21 28 35 42 49 56 63 70 77 84
+Sa 1 8 15 22 29 36 43 50 57 64 71 78 85
+Su 2 9 16 23 30 37 44 51 58 65 72 79 86
+
+ April May June
+Mo 94 101 108 115 122 129 136 143 150 157 164 171 178
+Tu 95 102 109 116 123 130 137 144 151 158 165 172 179
+We 96 103 110 117 124 131 138 145 152 159 166 173 180
+Th 97 104 111 118 125 132 139 146 153 160 167 174 181
+Fr 91 98 105 112 119 126 133 140 147 154 161 168 175
+Sa 92 99 106 113 120 127 134 141 148 155 162 169 176
+Su 93 100 107 114 121 128 135 142 149 156 163 170 177
+
+ July August September
+Mo 185 192 199 206 213 220 227 234 241 248 255 262 269
+Tu 186 193 200 207 214 221 228 235 242 249 256 263 270
+We 187 194 201 208 215 222 229 236 243 250 257 264 271
+Th 188 195 202 209 216 223 230 237 244 251 258 265 272
+Fr 182 189 196 203 210 217 224 231 238 245 252 259 266 273
+Sa 183 190 197 204 211 218 225 232 239 246 253 260 267
+Su 184 191 198 205 212 219 226 233 240 247 254 261 268
+
+ October November December
+Mo 276 283 290 297 304 311 318 325 332 339 346 353 360
+Tu 277 284 291 298 305 312 319 326 333 340 347 354 361
+We 278 285 292 299 306 313 320 327 334 341 348 355 362
+Th 279 286 293 300 307 314 321 328 335 342 349 356 363
+Fr 280 287 294 301 308 315 322 329 336 343 350 357 364
+Sa 274 281 288 295 302 309 316 323 330 337 344 351 358 365
+Su 275 282 289 296 303 310 317 324 331 338 345 352 359
diff --git a/usr.bin/ncal/tests/regress.r-y2011-md-nhl.out b/usr.bin/ncal/tests/regress.r-y2011-md-nhl.out
new file mode 100644
index 000000000000..88529320f4b0
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.r-y2011-md-nhl.out
@@ -0,0 +1,27 @@
+ 2011
+ January February March April
+Mo 3 10 17 24 31 7 14 21 28 7 14 21 28 4 11 18 25
+Tu 4 11 18 25 1 8 15 22 1 8 15 22 29 5 12 19 26
+We 5 12 19 26 2 9 16 23 2 9 16 23 30 6 13 20 27
+Th 6 13 20 27 3 10 17 24 3 10 17 24 31 7 14 21 28
+Fr 7 14 21 28 4 11 18 25 4 11 18 25 1 8 15 22 29
+Sa 1 8 15 22 29 5 12 19 26 5 12 19 26 2 9 16 23 30
+Su 2 9 16 23 30 6 13 20 27 6 13 20 27 3 10 17 24
+
+ May June July August
+Mo 2 9 16 23 30 6 13 20 27 4 11 18 25 1 8 15 22 29
+Tu 3 10 17 24 31 7 14 21 28 5 12 19 26 2 9 16 23 30
+We 4 11 18 25 1 8 15 22 29 6 13 20 27 3 10 17 24 31
+Th 5 12 19 26 2 9 16 23 30 7 14 21 28 4 11 18 25
+Fr 6 13 20 27 3 10 17 24 1 8 15 22 29 5 12 19 26
+Sa 7 14 21 28 4 11 18 25 2 9 16 23 30 6 13 20 27
+Su 1 8 15 22 29 5 12 19 26 3 10 17 24 31 7 14 21 28
+
+ September October November December
+Mo 5 12 19 26 3 10 17 24 31 7 14 21 28 5 12 19 26
+Tu 6 13 20 27 4 11 18 25 1 8 15 22 29 6 13 20 27
+We 7 14 21 28 5 12 19 26 2 9 16 23 30 7 14 21 28
+Th 1 8 15 22 29 6 13 20 27 3 10 17 24 1 8 15 22 29
+Fr 2 9 16 23 30 7 14 21 28 4 11 18 25 2 9 16 23 30
+Sa 3 10 17 24 1 8 15 22 29 5 12 19 26 3 10 17 24 31
+Su 4 11 18 25 2 9 16 23 30 6 13 20 27 4 11 18 25
diff --git a/usr.bin/ncal/tests/regress.s-b-3-nhl.out b/usr.bin/ncal/tests/regress.s-b-3-nhl.out
new file mode 100644
index 000000000000..ccb6b3686fc5
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-3-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008 April 2008
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 1 2 3 4 5
+ 3 4 5 6 7 8 9 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+10 11 12 13 14 15 16 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+17 18 19 20 21 22 23 16 17 18 19 20 21 22 20 21 22 23 24 25 26
+24 25 26 27 28 29 23 24 25 26 27 28 29 27 28 29 30
+ 30 31
diff --git a/usr.bin/ncal/tests/regress.s-b-A-nhl.out b/usr.bin/ncal/tests/regress.s-b-A-nhl.out
new file mode 100644
index 000000000000..19149ca65fa4
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-A-nhl.out
@@ -0,0 +1,8 @@
+ March 2008 April 2008
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 1 2 3 4 5
+ 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+ 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+16 17 18 19 20 21 22 20 21 22 23 24 25 26
+23 24 25 26 27 28 29 27 28 29 30
+30 31
diff --git a/usr.bin/ncal/tests/regress.s-b-AB-nhl.out b/usr.bin/ncal/tests/regress.s-b-AB-nhl.out
new file mode 100644
index 000000000000..ccb6b3686fc5
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-AB-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008 April 2008
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1 1 2 3 4 5
+ 3 4 5 6 7 8 9 2 3 4 5 6 7 8 6 7 8 9 10 11 12
+10 11 12 13 14 15 16 9 10 11 12 13 14 15 13 14 15 16 17 18 19
+17 18 19 20 21 22 23 16 17 18 19 20 21 22 20 21 22 23 24 25 26
+24 25 26 27 28 29 23 24 25 26 27 28 29 27 28 29 30
+ 30 31
diff --git a/usr.bin/ncal/tests/regress.s-b-B-nhl.out b/usr.bin/ncal/tests/regress.s-b-B-nhl.out
new file mode 100644
index 000000000000..5d61423bf524
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-B-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008
+Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
+ 1 2 1
+ 3 4 5 6 7 8 9 2 3 4 5 6 7 8
+10 11 12 13 14 15 16 9 10 11 12 13 14 15
+17 18 19 20 21 22 23 16 17 18 19 20 21 22
+24 25 26 27 28 29 23 24 25 26 27 28 29
+ 30 31
diff --git a/usr.bin/ncal/tests/regress.s-b-gmgy-nhl.out b/usr.bin/ncal/tests/regress.s-b-gmgy-nhl.out
new file mode 100644
index 000000000000..562005197876
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-gmgy-nhl.out
@@ -0,0 +1,8 @@
+ January 2007
+Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6
+ 7 8 9 10 11 12 13
+14 15 16 17 18 19 20
+21 22 23 24 25 26 27
+28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.s-b-m-nhl.out b/usr.bin/ncal/tests/regress.s-b-m-nhl.out
new file mode 100644
index 000000000000..37b9ffaeaee0
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-m-nhl.out
@@ -0,0 +1,8 @@
+ January 2008
+Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5
+ 6 7 8 9 10 11 12
+13 14 15 16 17 18 19
+20 21 22 23 24 25 26
+27 28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.s-b-mgy-nhl.out b/usr.bin/ncal/tests/regress.s-b-mgy-nhl.out
new file mode 100644
index 000000000000..562005197876
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-b-mgy-nhl.out
@@ -0,0 +1,8 @@
+ January 2007
+Su Mo Tu We Th Fr Sa
+ 1 2 3 4 5 6
+ 7 8 9 10 11 12 13
+14 15 16 17 18 19 20
+21 22 23 24 25 26 27
+28 29 30 31
+
diff --git a/usr.bin/ncal/tests/regress.s-r-3-nhl.out b/usr.bin/ncal/tests/regress.s-r-3-nhl.out
new file mode 100644
index 000000000000..9a816b77ac06
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-3-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008 April 2008
+Mo 4 11 18 25 3 10 17 24 31 7 14 21 28
+Tu 5 12 19 26 4 11 18 25 1 8 15 22 29
+We 6 13 20 27 5 12 19 26 2 9 16 23 30
+Th 7 14 21 28 6 13 20 27 3 10 17 24
+Fr 1 8 15 22 29 7 14 21 28 4 11 18 25
+Sa 2 9 16 23 1 8 15 22 29 5 12 19 26
+Su 3 10 17 24 2 9 16 23 30 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.s-r-A-nhl.out b/usr.bin/ncal/tests/regress.s-r-A-nhl.out
new file mode 100644
index 000000000000..603c2cf9232d
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-A-nhl.out
@@ -0,0 +1,8 @@
+ March 2008 April 2008
+Mo 3 10 17 24 31 7 14 21 28
+Tu 4 11 18 25 1 8 15 22 29
+We 5 12 19 26 2 9 16 23 30
+Th 6 13 20 27 3 10 17 24
+Fr 7 14 21 28 4 11 18 25
+Sa 1 8 15 22 29 5 12 19 26
+Su 2 9 16 23 30 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.s-r-AB-nhl.out b/usr.bin/ncal/tests/regress.s-r-AB-nhl.out
new file mode 100644
index 000000000000..9a816b77ac06
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-AB-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008 April 2008
+Mo 4 11 18 25 3 10 17 24 31 7 14 21 28
+Tu 5 12 19 26 4 11 18 25 1 8 15 22 29
+We 6 13 20 27 5 12 19 26 2 9 16 23 30
+Th 7 14 21 28 6 13 20 27 3 10 17 24
+Fr 1 8 15 22 29 7 14 21 28 4 11 18 25
+Sa 2 9 16 23 1 8 15 22 29 5 12 19 26
+Su 3 10 17 24 2 9 16 23 30 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.s-r-B-nhl.out b/usr.bin/ncal/tests/regress.s-r-B-nhl.out
new file mode 100644
index 000000000000..94614da866a9
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-B-nhl.out
@@ -0,0 +1,8 @@
+ February 2008 March 2008
+Mo 4 11 18 25 3 10 17 24 31
+Tu 5 12 19 26 4 11 18 25
+We 6 13 20 27 5 12 19 26
+Th 7 14 21 28 6 13 20 27
+Fr 1 8 15 22 29 7 14 21 28
+Sa 2 9 16 23 1 8 15 22 29
+Su 3 10 17 24 2 9 16 23 30
diff --git a/usr.bin/ncal/tests/regress.s-r-gmgy-nhl.out b/usr.bin/ncal/tests/regress.s-r-gmgy-nhl.out
new file mode 100644
index 000000000000..0b42e417a214
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-gmgy-nhl.out
@@ -0,0 +1,8 @@
+ January 2007
+Mo 1 8 15 22 29
+Tu 2 9 16 23 30
+We 3 10 17 24 31
+Th 4 11 18 25
+Fr 5 12 19 26
+Sa 6 13 20 27
+Su 7 14 21 28
diff --git a/usr.bin/ncal/tests/regress.s-r-m-nhl.out b/usr.bin/ncal/tests/regress.s-r-m-nhl.out
new file mode 100644
index 000000000000..34b939dae764
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-m-nhl.out
@@ -0,0 +1,8 @@
+ January 2008
+Mo 7 14 21 28
+Tu 1 8 15 22 29
+We 2 9 16 23 30
+Th 3 10 17 24 31
+Fr 4 11 18 25
+Sa 5 12 19 26
+Su 6 13 20 27
diff --git a/usr.bin/ncal/tests/regress.s-r-mgy-nhl.out b/usr.bin/ncal/tests/regress.s-r-mgy-nhl.out
new file mode 100644
index 000000000000..0b42e417a214
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.s-r-mgy-nhl.out
@@ -0,0 +1,8 @@
+ January 2007
+Mo 1 8 15 22 29
+Tu 2 9 16 23 30
+We 3 10 17 24 31
+Th 4 11 18 25
+Fr 5 12 19 26
+Sa 6 13 20 27
+Su 7 14 21 28
diff --git a/usr.bin/ncal/tests/regress.sh b/usr.bin/ncal/tests/regress.sh
new file mode 100644
index 000000000000..cced1f3f1c72
--- /dev/null
+++ b/usr.bin/ncal/tests/regress.sh
@@ -0,0 +1,79 @@
+
+CAL_BIN="ncal"
+CAL="${CAL_BIN} -C"
+NCAL="${CAL_BIN} -N"
+YEARS="2008 2009 2010 2011"
+ONEYEAR="2009"
+
+echo 1..89
+
+REGRESSION_START($1)
+
+#
+# The first tests are layout tests, to make sure that the output is still the
+# same despite varying months.
+#
+
+# Full year calendars
+
+for y in ${YEARS}; do
+ # Regular calendar, Month days, No-highlight
+ REGRESSION_TEST(`r-y${y}-md-nhl', `$NCAL -h ${y}')
+ # Backwards calendar, Month days, No-highlight
+ REGRESSION_TEST(`b-y${y}-md-nhl', `$CAL -h ${y}')
+ # Regular calendar, Julian days, No-highlight
+ REGRESSION_TEST(`r-y${y}-jd-nhl', `$NCAL -jh ${y}')
+ # Backwards calendar, Julian days, No-highlight
+ REGRESSION_TEST(`b-y${y}-jd-nhl', `$CAL -jh ${y}')
+done
+
+# 3 month calendars
+
+for m in $(jot -w %02d 12); do
+ # Regular calendar, Month days, No-highlight
+ REGRESSION_TEST(`r-3m${ONEYEAR}${m}-md-nhl',
+ `$NCAL -h3 ${m} ${ONEYEAR}')
+ # Backwards calendar, Month days, No-highlight
+ REGRESSION_TEST(`b-3m${ONEYEAR}${m}-md-nhl', `$CAL -h3 ${m} ${ONEYEAR}')
+ # Regular calendar, Julian days, No-highlight
+ REGRESSION_TEST(`r-3m${ONEYEAR}${m}-jd-nhl',
+ `$NCAL -jh3 ${m} ${ONEYEAR}')
+ # Backwards calendar, Julian days, No-highlight
+ REGRESSION_TEST(`b-3m${ONEYEAR}${m}-jd-nhl', `$CAL -jh3 ${m} ${ONEYEAR}')
+done
+
+#
+# The next tests are combinations of the various arguments.
+#
+
+# These should fail
+REGRESSION_TEST(`f-3y-nhl', `$NCAL -3 -y 2>&1')
+REGRESSION_TEST(`f-3A-nhl', `$NCAL -3 -A 3 2>&1')
+REGRESSION_TEST(`f-3B-nhl', `$NCAL -3 -B 3 2>&1')
+REGRESSION_TEST(`f-3gy-nhl', `$NCAL -3 2008 2>&1')
+REGRESSION_TEST(`f-3AB-nhl', `$NCAL -3 -A 3 -B 3 2>&1')
+REGRESSION_TEST(`f-mgm-nhl', `$NCAL -m 3 2 2008 2>&1')
+REGRESSION_TEST(`f-ym-nhl', `$NCAL -y -m 2 2>&1')
+REGRESSION_TEST(`f-ygm-nhl', `$NCAL -y 2 2008 2>&1')
+REGRESSION_TEST(`f-yA-nhl', `$NCAL -y -A 3 2>&1')
+REGRESSION_TEST(`f-yB-nhl', `$NCAL -y -B 3 2>&1')
+REGRESSION_TEST(`f-yAB-nhl', `$NCAL -y -A 3 -B 3 2>&1')
+
+# These should be successful
+
+REGRESSION_TEST(`s-b-3-nhl', `$CAL -d 2008.03 -3')
+REGRESSION_TEST(`s-b-A-nhl', `$CAL -d 2008.03 -A 1')
+REGRESSION_TEST(`s-b-B-nhl', `$CAL -d 2008.03 -B 1')
+REGRESSION_TEST(`s-b-AB-nhl', `$CAL -d 2008.03 -A 1 -B 1')
+REGRESSION_TEST(`s-b-m-nhl', `$CAL -d 2008.03 -m 1')
+REGRESSION_TEST(`s-b-mgy-nhl', `$CAL -d 2008.03 -m 1 2007')
+REGRESSION_TEST(`s-b-gmgy-nhl', `$CAL -d 2008.03 1 2007')
+REGRESSION_TEST(`s-r-3-nhl', `$NCAL -d 2008.03 -3')
+REGRESSION_TEST(`s-r-A-nhl', `$NCAL -d 2008.03 -A 1')
+REGRESSION_TEST(`s-r-B-nhl', `$NCAL -d 2008.03 -B 1')
+REGRESSION_TEST(`s-r-AB-nhl', `$NCAL -d 2008.03 -A 1 -B 1')
+REGRESSION_TEST(`s-r-m-nhl', `$NCAL -d 2008.03 -m 1')
+REGRESSION_TEST(`s-r-mgy-nhl', `$NCAL -d 2008.03 -m 1 2007')
+REGRESSION_TEST(`s-r-gmgy-nhl', `$NCAL -d 2008.03 1 2007')
+
+REGRESSION_END()
diff --git a/usr.bin/ncurses/Makefile b/usr.bin/ncurses/Makefile
new file mode 100644
index 000000000000..33001e6ab568
--- /dev/null
+++ b/usr.bin/ncurses/Makefile
@@ -0,0 +1,40 @@
+PACKAGE= runtime
+
+.include <bsd.own.mk>
+.include "${SRCTOP}/lib/ncurses/config.mk"
+
+.PATH: ${NCURSES_DIR}/progs ${NCURSES_DIR}/man
+
+PROGS= tic tput infocmp toe tabs clear tset
+SRCS.tic= tic.c transform.c dump_entry.c tparm_type.c
+SRCS.tput= tput.c tparm_type.c transform.c dump_entry.c clear_cmd.c reset_cmd.c \
+ tty_settings.c
+SRCS.infocmp= infocmp.c dump_entry.c
+SRCS.tabs= tabs.c tty_settings.c
+SRCS.clear= clear.c clear_cmd.c tty_settings.c
+SRCS.tset= tset.c tty_settings.c transform.c reset_cmd.c
+CFLAGS+= -I${NCURSES_DIR}/progs \
+ -I${NCURSES_DIR}/include \
+ -I${SRCTOP}/lib/ncurses/tinfo \
+ -I${OBJTOP}/lib/ncurses/tinfo \
+ -I${.CURDIR}
+LIBADD= tinfow
+CLEANFILES= termsort.h
+
+termsort.h: MKtermsort.sh
+ sh ${NCURSES_DIR}/progs/MKtermsort.sh ${AWK} ${NCURSES_DIR}/include/Caps > ${.TARGET}
+dump_entry.c: termsort.h
+
+LINKS.tic= ${BINDIR}/tic ${BINDIR}/captoinfo \
+ ${BINDIR}/tic ${BINDIR}/infotocap
+LINKS.tset= ${BINDIR}/tset ${BINDIR}/reset
+
+MLINKS.tic= tic.1 captoinfo.1 \
+ tic.1 infotocap.1
+MLINKS.tset= tset.1 reset.1
+
+.include <bsd.progs.mk>
+
+.SUFFIXES: .1 .1m
+.1m.1:
+ cat ${.IMPSRC} > ${.TARGET}
diff --git a/usr.bin/ncurses/Makefile.depend b/usr.bin/ncurses/Makefile.depend
new file mode 100644
index 000000000000..c6788a7857d3
--- /dev/null
+++ b/usr.bin/ncurses/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ bin/sh.host \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ncurses/transform.h b/usr.bin/ncurses/transform.h
new file mode 100644
index 000000000000..ec255c05c4dd
--- /dev/null
+++ b/usr.bin/ncurses/transform.h
@@ -0,0 +1,10 @@
+#ifndef __TRANSFORM_H
+#define __TRANSFORM_H 1
+#include <progs.priv.h>
+extern bool same_program(const char *, const char *);
+#define PROG_CAPTOINFO "captoinfo"
+#define PROG_INFOTOCAP "infotocap"
+#define PROG_CLEAR "clear"
+#define PROG_RESET "reset"
+#define PROG_INIT "init"
+#endif /* __TRANSFORM_H */
diff --git a/usr.bin/netstat/Makefile b/usr.bin/netstat/Makefile
new file mode 100644
index 000000000000..742de485a6b5
--- /dev/null
+++ b/usr.bin/netstat/Makefile
@@ -0,0 +1,74 @@
+.include <src.opts.mk>
+
+PROG= netstat
+SRCS= if.c inet.c main.c mbuf.c mroute.c netisr.c nl_symbols.c route.c \
+ unix.c mroute6.c ipsec.c bpf.c pfkey.c sctp.c common.c nhops.c nhgrp.c \
+ nl_defs.h
+
+nl_symbols.c: nlist_symbols
+ awk '\
+ BEGIN { \
+ print "#include <sys/param.h>"; \
+ print "#include <nlist.h>"; \
+ print "struct nlist nl[] = {"; \
+ } \
+ !/^\#/ { printf("\t{ .n_name = \"%s\" },\n", $$2); } \
+ END { print "\t{ .n_name = NULL },\n};" } \
+ ' < ${.ALLSRC} > ${.TARGET} || rm -f ${.TARGET}
+nl_defs.h: nlist_symbols
+ awk '\
+ BEGIN { \
+ print "#include <nlist.h>"; \
+ print "extern struct nlist nl[];"; \
+ i = 0; \
+ } \
+ !/^\#/ { printf("\#define\tN%s\t%s\n", toupper($$2), i++); }' \
+ < ${.ALLSRC} > ${.TARGET} || rm -f ${.TARGET}
+CLEANFILES+= nl_symbols.c nl_defs.h
+CFLAGS+= -I${.OBJDIR}
+
+WARNS?= 3
+CFLAGS+=-fno-strict-aliasing
+
+CFLAGS+=-DIPSEC
+CFLAGS+=-DSCTP
+
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+=-DINET
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+SRCS+= inet6.c
+CFLAGS+=-DINET6
+.endif
+
+.if ${MK_OFED} != "no"
+CFLAGS+=-DSDP
+.endif
+
+.if ${MK_PF} != "no"
+CFLAGS+=-DPF
+.endif
+
+BINGRP= kmem
+BINMODE=2555
+LIBADD= kvm memstat xo util
+
+.if ${MK_NETGRAPH_SUPPORT} != "no"
+SRCS+= netgraph.c
+LIBADD+= netgraph
+CFLAGS+=-DNETGRAPH
+.endif
+
+.if ${MK_NETLINK_SUPPORT} != "no"
+SRCS+= route_netlink.c
+.else
+CFLAGS+=-DWITHOUT_NETLINK
+.endif
+
+.if ${MK_JAIL} != "no" && !defined(RESCUE)
+CFLAGS+= -DJAIL
+LIBADD+= jail
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/netstat/Makefile.depend b/usr.bin/netstat/Makefile.depend
new file mode 100644
index 000000000000..9fe03c55bea9
--- /dev/null
+++ b/usr.bin/netstat/Makefile.depend
@@ -0,0 +1,21 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libkvm \
+ lib/libmemstat \
+ lib/libutil \
+ lib/libxo/libxo \
+ usr.bin/awk.host \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/netstat/Makefile.depend.options b/usr.bin/netstat/Makefile.depend.options
new file mode 100644
index 000000000000..b741c9f5954b
--- /dev/null
+++ b/usr.bin/netstat/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= NETGRAPH_SUPPORT
+
+DIRDEPS.NETGRAPH_SUPPORT.yes= lib/libnetgraph
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/netstat/bpf.c b/usr.bin/netstat/bpf.c
new file mode 100644
index 000000000000..5d61da7b4d2b
--- /dev/null
+++ b/usr.bin/netstat/bpf.c
@@ -0,0 +1,167 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005 Christian S.J. Peron
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#include <sys/user.h>
+
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+
+#include "netstat.h"
+
+/* print bpf stats */
+
+static char *
+bpf_pidname(pid_t pid)
+{
+ struct kinfo_proc newkp;
+ int error, mib[4];
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ size = sizeof(newkp);
+ error = sysctl(mib, 4, &newkp, &size, NULL, 0);
+ if (error < 0) {
+ xo_warn("kern.proc.pid failed");
+ return (strdup("??????"));
+ }
+ return (strdup(newkp.ki_comm));
+}
+
+static void
+bpf_flags(struct xbpf_d *bd, char *flagbuf)
+{
+
+ *flagbuf++ = bd->bd_promisc ? 'p' : '-';
+ *flagbuf++ = bd->bd_immediate ? 'i' : '-';
+ *flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
+ *flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' :
+ ((bd->bd_direction == BPF_D_OUT) ? 'o' : 's');
+ *flagbuf++ = bd->bd_feedback ? 'b' : '-';
+ *flagbuf++ = bd->bd_async ? 'a' : '-';
+ *flagbuf++ = bd->bd_locked ? 'l' : '-';
+ *flagbuf++ = '\0';
+
+ if (bd->bd_promisc)
+ xo_emit("{e:promiscuous/}");
+ if (bd->bd_immediate)
+ xo_emit("{e:immediate/}");
+ if (bd->bd_hdrcmplt)
+ xo_emit("{e:header-complete/}");
+ xo_emit("{e:direction}", (bd->bd_direction == BPF_D_IN) ? "input" :
+ (bd->bd_direction == BPF_D_OUT) ? "output" : "bidirectional");
+ if (bd->bd_feedback)
+ xo_emit("{e:feedback/}");
+ if (bd->bd_async)
+ xo_emit("{e:async/}");
+ if (bd->bd_locked)
+ xo_emit("{e:locked/}");
+}
+
+void
+bpf_stats(char *ifname)
+{
+ struct xbpf_d *d, *bd, zerostat;
+ char *pname, flagbuf[12];
+ size_t size;
+
+ if (zflag) {
+ bzero(&zerostat, sizeof(zerostat));
+ if (sysctlbyname("net.bpf.stats", NULL, NULL,
+ &zerostat, sizeof(zerostat)) < 0)
+ xo_warn("failed to zero bpf counters");
+ return;
+ }
+ if (sysctlbyname("net.bpf.stats", NULL, &size,
+ NULL, 0) < 0) {
+ xo_warn("net.bpf.stats");
+ return;
+ }
+ if (size == 0)
+ return;
+ bd = malloc(size);
+ if (bd == NULL) {
+ xo_warn("malloc failed");
+ return;
+ }
+ if (sysctlbyname("net.bpf.stats", bd, &size,
+ NULL, 0) < 0) {
+ xo_warn("net.bpf.stats");
+ free(bd);
+ return;
+ }
+ xo_emit("{T:/%5s} {T:/%6s} {T:/%7s} {T:/%9s} {T:/%9s} {T:/%9s} "
+ "{T:/%5s} {T:/%5s} {T:/%s}\n",
+ "Pid", "Netif", "Flags", "Recv", "Drop", "Match",
+ "Sblen", "Hblen", "Command");
+ xo_open_container("bpf-statistics");
+ xo_open_list("bpf-entry");
+ for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) {
+ if (d->bd_structsize != sizeof(*d)) {
+ xo_warnx("bpf_stats_extended: version mismatch");
+ return;
+ }
+ if (ifname && strcmp(ifname, d->bd_ifname) != 0)
+ continue;
+ xo_open_instance("bpf-entry");
+ pname = bpf_pidname(d->bd_pid);
+ xo_emit("{k:pid/%5d} {k:interface-name/%6s} ",
+ d->bd_pid, d->bd_ifname);
+ bpf_flags(d, flagbuf);
+ xo_emit("{d:flags/%7s} {:received-packets/%9ju} "
+ "{:dropped-packets/%9ju} {:filter-packets/%9ju} "
+ "{:store-buffer-length/%5d} {:hold-buffer-length/%5d} "
+ "{:process/%s}\n",
+ flagbuf, (uintmax_t)d->bd_rcount, (uintmax_t)d->bd_dcount,
+ (uintmax_t)d->bd_fcount, d->bd_slen, d->bd_hlen, pname);
+ free(pname);
+ xo_close_instance("bpf-entry");
+ }
+ xo_close_list("bpf-entry");
+ xo_close_container("bpf-statistics");
+ free(bd);
+}
diff --git a/usr.bin/netstat/common.c b/usr.bin/netstat/common.c
new file mode 100644
index 000000000000..00a3f405ed1e
--- /dev/null
+++ b/usr.bin/netstat/common.c
@@ -0,0 +1,136 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "common.h"
+
+const char *
+fmt_flags(const struct bits *p, int f)
+{
+ static char name[33];
+ char *flags;
+
+ for (flags = name; p->b_mask; p++)
+ if (p->b_mask & f)
+ *flags++ = p->b_val;
+ *flags = '\0';
+ return (name);
+}
+
+void
+print_flags_generic(int flags, const struct bits *pbits, const char *format,
+ const char *tag_name)
+{
+ const struct bits *p;
+ char tag_fmt[64];
+
+ xo_emit(format, fmt_flags(pbits, flags));
+
+ snprintf(tag_fmt, sizeof(tag_fmt), "{le:%s/%%s}", tag_name);
+ xo_open_list(tag_name);
+ for (p = pbits; p->b_mask; p++)
+ if (p->b_mask & flags)
+ xo_emit(tag_fmt, p->b_name);
+ xo_close_list(tag_name);
+}
+
+struct ifmap_entry *
+prepare_ifmap(size_t *pifmap_size)
+{
+ int ifindex = 0, size;
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_dl *sdl;
+
+ struct ifmap_entry *ifmap = NULL;
+ int ifmap_size = 0;
+
+ /*
+ * Retrieve interface list at first
+ * since we need #ifindex -> if_xname match
+ */
+ if (getifaddrs(&ifap) != 0)
+ xo_err(EX_OSERR, "getifaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ ifindex = sdl->sdl_index;
+
+ if (ifindex >= ifmap_size) {
+ size = roundup2(ifindex + 1, 32) *
+ sizeof(struct ifmap_entry);
+ if ((ifmap = realloc(ifmap, size)) == NULL)
+ xo_errx(EX_OSERR, "realloc(%d) failed", size);
+ memset(&ifmap[ifmap_size], 0,
+ size - ifmap_size *
+ sizeof(struct ifmap_entry));
+
+ ifmap_size = roundup2(ifindex + 1, 32);
+ }
+
+ if (*ifmap[ifindex].ifname != '\0')
+ continue;
+
+ strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ);
+ }
+
+ freeifaddrs(ifap);
+
+ *pifmap_size = ifmap_size;
+
+ return (ifmap);
+}
+
diff --git a/usr.bin/netstat/common.h b/usr.bin/netstat/common.h
new file mode 100644
index 000000000000..d5d39902037b
--- /dev/null
+++ b/usr.bin/netstat/common.h
@@ -0,0 +1,90 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ * 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.
+ */
+
+#ifndef _NETSTAT_COMMON_H_
+#define _NETSTAT_COMMON_H_
+
+struct bits {
+ u_long b_mask;
+ char b_val;
+ const char *b_name;
+};
+extern struct bits rt_bits[];
+
+const char *fmt_flags(const struct bits *p, int f);
+void print_flags_generic(int flags, const struct bits *pbits,
+ const char *format, const char *tag_name);
+int p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask,
+ int flags, int width);
+
+struct _wid {
+ int dst;
+ int gw;
+ int flags;
+ int pksent;
+ int mtu;
+ int iface;
+ int expire;
+};
+void set_wid(int fam);
+void pr_rthdr(int af1 __unused);
+extern struct _wid wid;
+void p_flags(int f, const char *format);
+
+bool p_rtable_netlink(int fibnum, int af);
+
+struct ifmap_entry {
+ char ifname[IFNAMSIZ];
+ uint32_t mtu;
+};
+
+struct ifmap_entry *prepare_ifmap(size_t *ifmap_size);
+extern const uint32_t rt_default_weight;
+
+struct rt_msghdr;
+struct nhops_map {
+ uint32_t idx;
+ struct rt_msghdr *rtm;
+};
+
+struct nhops_dump {
+ void *nh_buf;
+ struct nhops_map *nh_map;
+ size_t nh_count;
+};
+
+void dump_nhops_sysctl(int fibnum, int af, struct nhops_dump *nd);
+struct nhop_map;
+void nhop_map_update(struct nhop_map *map, uint32_t idx, char *gw, char *ifname);
+
+
+#endif
+
diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c
new file mode 100644
index 000000000000..1603c7662bbd
--- /dev/null
+++ b/usr.bin/netstat/if.c
@@ -0,0 +1,740 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2013 Gleb Smirnoff <glebius@FreeBSD.org>
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <arpa/inet.h>
+#ifdef PF
+#include <net/pfvar.h>
+#include <net/pflow.h>
+#include <net/if_pfsync.h>
+#endif
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#ifdef INET6
+#include <netdb.h>
+#endif
+#include <signal.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+
+#include "netstat.h"
+
+static void sidewaysintpr(void);
+
+#ifdef PF
+static const char* pfsyncacts[] = {
+ /* PFSYNC_ACT_CLR */ "clear all request",
+ /* PFSYNC_ACT_INS_1301 */ "13.1 state insert",
+ /* PFSYNC_ACT_INS_ACK */ "state inserted ack",
+ /* PFSYNC_ACT_UPD_1301 */ "13.1 state update",
+ /* PFSYNC_ACT_UPD_C */ "compressed state update",
+ /* PFSYNC_ACT_UPD_REQ */ "uncompressed state request",
+ /* PFSYNC_ACT_DEL */ "state delete",
+ /* PFSYNC_ACT_DEL_C */ "compressed state delete",
+ /* PFSYNC_ACT_INS_F */ "fragment insert",
+ /* PFSYNC_ACT_DEL_F */ "fragment delete",
+ /* PFSYNC_ACT_BUS */ "bulk update mark",
+ /* PFSYNC_ACT_TDB */ "TDB replay counter update",
+ /* PFSYNC_ACT_EOF */ "end of frame mark",
+ /* PFSYNC_ACT_INS_1400 */ "state insert",
+ /* PFSYNC_ACT_UPD_1400 */ "state update",
+};
+
+static const char* pfsyncacts_name[] = {
+ /* PFSYNC_ACT_CLR */ "clear-all-request",
+ /* PFSYNC_ACT_INS_1301 */ "state-insert-1301",
+ /* PFSYNC_ACT_INS_ACK */ "state-inserted-ack",
+ /* PFSYNC_ACT_UPD_1301 */ "state-update-1301",
+ /* PFSYNC_ACT_UPD_C */ "compressed-state-update",
+ /* PFSYNC_ACT_UPD_REQ */ "uncompressed-state-request",
+ /* PFSYNC_ACT_DEL */ "state-delete",
+ /* PFSYNC_ACT_DEL_C */ "compressed-state-delete",
+ /* PFSYNC_ACT_INS_F */ "fragment-insert",
+ /* PFSYNC_ACT_DEL_F */ "fragment-delete",
+ /* PFSYNC_ACT_BUS */ "bulk-update-mark",
+ /* PFSYNC_ACT_TDB */ "TDB-replay-counter-update",
+ /* PFSYNC_ACT_EOF */ "end-of-frame-mark",
+ /* PFSYNC_ACT_INS_1400 */ "state-insert",
+ /* PFSYNC_ACT_UPD_1400 */ "state-update",
+};
+
+static void
+pfsync_acts_stats(const char *list, const char *desc, uint64_t *a)
+{
+ int i;
+
+ xo_open_list(list);
+ for (i = 0; i < PFSYNC_ACT_MAX; i++, a++) {
+ if (*a || sflag <= 1) {
+ xo_open_instance(list);
+ xo_emit("\t\t{e:name}{:count/%ju} {N:/%s%s %s}\n",
+ pfsyncacts_name[i], (uintmax_t)(*a),
+ pfsyncacts[i], plural(*a), desc);
+ xo_close_instance(list);
+ }
+ }
+ xo_close_list(list);
+}
+
+/*
+ * Dump pfsync statistics structure.
+ */
+void
+pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct pfsyncstats pfsyncstat;
+
+ if (fetch_stats("net.pfsync.stats", off, &pfsyncstat,
+ sizeof(pfsyncstat), kread) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+
+#define p(f, m) if (pfsyncstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
+
+ p(pfsyncs_ipackets, "\t{:received-inet-packets/%ju} "
+ "{N:/packet%s received (IPv4)}\n");
+ p(pfsyncs_ipackets6, "\t{:received-inet6-packets/%ju} "
+ "{N:/packet%s received (IPv6)}\n");
+ pfsync_acts_stats("input-histogram", "received",
+ &pfsyncstat.pfsyncs_iacts[0]);
+ p(pfsyncs_badif, "\t\t{:dropped-bad-interface/%ju} "
+ "{N:/packet%s discarded for bad interface}\n");
+ p(pfsyncs_badttl, "\t\t{:dropped-bad-ttl/%ju} "
+ "{N:/packet%s discarded for bad ttl}\n");
+ p(pfsyncs_hdrops, "\t\t{:dropped-short-header/%ju} "
+ "{N:/packet%s shorter than header}\n");
+ p(pfsyncs_badver, "\t\t{:dropped-bad-version/%ju} "
+ "{N:/packet%s discarded for bad version}\n");
+ p(pfsyncs_badauth, "\t\t{:dropped-bad-auth/%ju} "
+ "{N:/packet%s discarded for bad HMAC}\n");
+ p(pfsyncs_badact,"\t\t{:dropped-bad-action/%ju} "
+ "{N:/packet%s discarded for bad action}\n");
+ p(pfsyncs_badlen, "\t\t{:dropped-short/%ju} "
+ "{N:/packet%s discarded for short packet}\n");
+ p(pfsyncs_badval, "\t\t{:dropped-bad-values/%ju} "
+ "{N:/state%s discarded for bad values}\n");
+ p(pfsyncs_stale, "\t\t{:dropped-stale-state/%ju} "
+ "{N:/stale state%s}\n");
+ p(pfsyncs_badstate, "\t\t{:dropped-failed-lookup/%ju} "
+ "{N:/failed state lookup\\/insert%s}\n");
+ p(pfsyncs_opackets, "\t{:sent-inet-packets/%ju} "
+ "{N:/packet%s sent (IPv4})\n");
+ p(pfsyncs_opackets6, "\t{:send-inet6-packets/%ju} "
+ "{N:/packet%s sent (IPv6})\n");
+ pfsync_acts_stats("output-histogram", "sent",
+ &pfsyncstat.pfsyncs_oacts[0]);
+ p(pfsyncs_onomem, "\t\t{:discarded-no-memory/%ju} "
+ "{N:/failure%s due to mbuf memory error}\n");
+ p(pfsyncs_oerrors, "\t\t{:send-errors/%ju} "
+ "{N:/send error%s}\n");
+#undef p
+ xo_close_container(name);
+}
+
+void
+pflow_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct pflowstats pflowstat;
+
+ if (fetch_stats("net.pflow.stats", off, &pflowstat,
+ sizeof(pflowstat), kread) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+
+#define p(f, m) if (pflowstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pflowstat.f, plural(pflowstat.f))
+
+ p(pflow_flows, "\t{:flows/%ju} {N:/flow%s sent}\n");
+ p(pflow_packets, "\t{:packets/%ju} {N:/packet%s sent}\n");
+ p(pflow_onomem, "\t{:nomem/%ju} "
+ "{N:/send failed due to mbuf memory error}\n");
+ p(pflow_oerrors, "\t{:send-error/%ju} {N:/send error}\n");
+#undef p
+
+ xo_close_container(name);
+}
+#endif /* PF */
+
+/*
+ * Display a formatted value, or a '-' in the same space.
+ */
+static void
+show_stat(const char *fmt, int width, const char *name,
+ u_long value, short showvalue, int div1000)
+{
+ const char *lsep, *rsep;
+ char newfmt[64];
+
+ lsep = "";
+ if (strncmp(fmt, "LS", 2) == 0) {
+ lsep = " ";
+ fmt += 2;
+ }
+ rsep = " ";
+ if (strncmp(fmt, "NRS", 3) == 0) {
+ rsep = "";
+ fmt += 3;
+ }
+ if (showvalue == 0) {
+ /* Print just dash. */
+ xo_emit("{P:/%s}{D:/%*s}{P:/%s}", lsep, width, "-", rsep);
+ return;
+ }
+
+ /*
+ * XXX: workaround {P:} modifier can't be empty and doesn't seem to
+ * take args... so we need to conditionally include it in the format.
+ */
+#define maybe_pad(pad) do { \
+ if (strlen(pad)) { \
+ snprintf(newfmt, sizeof(newfmt), "{P:%s}", pad); \
+ xo_emit(newfmt); \
+ } \
+} while (0)
+
+ if (hflag) {
+ char buf[5];
+
+ /* Format in human readable form. */
+ humanize_number(buf, sizeof(buf), (int64_t)value, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL | \
+ ((div1000) ? HN_DIVISOR_1000 : 0));
+ maybe_pad(lsep);
+ snprintf(newfmt, sizeof(newfmt), "{:%s/%%%ds}", name, width);
+ xo_emit(newfmt, buf);
+ maybe_pad(rsep);
+ } else {
+ /* Construct the format string. */
+ maybe_pad(lsep);
+ snprintf(newfmt, sizeof(newfmt), "{:%s/%%%d%s}",
+ name, width, fmt);
+ xo_emit(newfmt, value);
+ maybe_pad(rsep);
+ }
+}
+
+/*
+ * Find next multiaddr for a given interface name.
+ */
+static struct ifmaddrs *
+next_ifma(struct ifmaddrs *ifma, const char *name, const sa_family_t family)
+{
+
+ for(; ifma != NULL; ifma = ifma->ifma_next) {
+ struct sockaddr_dl *sdl;
+
+ sdl = (struct sockaddr_dl *)ifma->ifma_name;
+ if (ifma->ifma_addr->sa_family == family &&
+ strcmp(sdl->sdl_data, name) == 0)
+ break;
+ }
+
+ return (ifma);
+}
+
+enum process_op { MEASURE, EMIT };
+
+static void
+process_ifa_addr(enum process_op op, struct ifaddrs *ifa, int *max_net_len,
+ int *max_addr_len, bool *network, bool *link)
+{
+ int net_len, addr_len;
+ const char *nn, *rn;
+
+ if (op == EMIT) {
+ net_len = *max_net_len;
+ addr_len = *max_addr_len;
+ }
+
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_UNSPEC:
+ if (op == MEASURE) {
+ net_len = strlen("none");
+ addr_len = strlen("none");
+ } else {
+ xo_emit("{:network/%-*.*s} ", net_len, net_len,
+ "none");
+ xo_emit("{:address/%-*.*s} ", addr_len, addr_len,
+ "none");
+ }
+ break;
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif /* INET6 */
+ nn = netname(ifa->ifa_addr, ifa->ifa_netmask);
+ rn = routename(ifa->ifa_addr, numeric_addr);
+ if (op == MEASURE) {
+ net_len = strlen(nn);
+ addr_len = strlen(rn);
+ } else {
+ xo_emit("{t:network/%-*s} ", net_len, nn);
+ xo_emit("{t:address/%-*s} ", addr_len, rn);
+ }
+
+ if (network != NULL)
+ *network = true;
+ break;
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sdl;
+ char linknum[sizeof("<Link#32767>")];
+
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ snprintf(linknum, sizeof(linknum), "<Link#%d>", sdl->sdl_index);
+ if (op == MEASURE) {
+ net_len = strlen(linknum);
+ if (sdl->sdl_nlen == 0 &&
+ sdl->sdl_alen == 0 &&
+ sdl->sdl_slen == 0)
+ addr_len = 1;
+ else
+ addr_len = strlen(routename(ifa->ifa_addr, 1));
+ } else {
+ xo_emit("{t:network/%-*.*s} ", net_len, net_len,
+ linknum);
+ if (sdl->sdl_nlen == 0 &&
+ sdl->sdl_alen == 0 &&
+ sdl->sdl_slen == 0)
+ xo_emit("{P:/%*s} ", addr_len, "");
+ else
+ xo_emit("{t:address/%-*.*s} ", addr_len,
+ addr_len, routename(ifa->ifa_addr, 1));
+ }
+ if (link != NULL)
+ *link = true;
+ break;
+ }
+ }
+
+ if (op == MEASURE) {
+ if (net_len > *max_net_len)
+ *max_net_len = net_len;
+ if (addr_len > *max_addr_len)
+ *max_addr_len = addr_len;
+ }
+}
+
+static int
+max_num_len(int max_len, u_long num)
+{
+ int len = 2; /* include space */
+
+ for (; num > 10; len++)
+ num /= 10;
+ return (MAX(max_len, len));
+}
+
+/*
+ * Print a description of the network interfaces.
+ */
+void
+intpr(void (*pfunc)(char *), int af)
+{
+ struct ifaddrs *ifap, *ifa;
+ struct ifmaddrs *ifmap, *ifma;
+ u_int ifn_len_max = 5, ifn_len;
+ u_int net_len = strlen("Network "), addr_len = strlen("Address ");
+ u_int npkt_len = 8, nbyte_len = 10, nerr_len = 5;
+
+ if (interval)
+ return sidewaysintpr();
+
+ if (getifaddrs(&ifap) != 0)
+ xo_err(EX_OSERR, "getifaddrs");
+ if (aflag && getifmaddrs(&ifmap) != 0)
+ xo_err(EX_OSERR, "getifmaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (interface != NULL &&
+ strcmp(ifa->ifa_name, interface) != 0)
+ continue;
+ if (af != AF_UNSPEC && ifa->ifa_addr->sa_family != af)
+ continue;
+ ifn_len = strlen(ifa->ifa_name);
+ if ((ifa->ifa_flags & IFF_UP) == 0)
+ ++ifn_len;
+ ifn_len_max = MAX(ifn_len_max, ifn_len);
+ process_ifa_addr(MEASURE, ifa, &net_len, &addr_len,
+ NULL, NULL);
+
+#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
+ if (!hflag) {
+ npkt_len = max_num_len(npkt_len, IFA_STAT(ipackets));
+ npkt_len = max_num_len(npkt_len, IFA_STAT(opackets));
+ nerr_len = max_num_len(nerr_len, IFA_STAT(ierrors));
+ nerr_len = max_num_len(nerr_len, IFA_STAT(iqdrops));
+ nerr_len = max_num_len(nerr_len, IFA_STAT(collisions));
+ if (dflag)
+ nerr_len = max_num_len(nerr_len,
+ IFA_STAT(oqdrops));
+ if (bflag) {
+ nbyte_len = max_num_len(nbyte_len,
+ IFA_STAT(ibytes));
+ nbyte_len = max_num_len(nbyte_len,
+ IFA_STAT(obytes));
+ }
+ }
+ }
+
+ xo_open_list("interface");
+ if (!pfunc) {
+ xo_emit("{T:/%-*.*s}", ifn_len_max, ifn_len_max, "Name");
+ xo_emit(" {T:/%5.5s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} "
+ "{T:/%*.*s} {T:/%*.*s}",
+ "Mtu", net_len, net_len, "Network", addr_len, addr_len,
+ "Address", npkt_len, npkt_len, "Ipkts",
+ nerr_len, nerr_len, "Ierrs", nerr_len, nerr_len, "Idrop");
+ if (bflag)
+ xo_emit(" {T:/%*.*s}", nbyte_len, nbyte_len, "Ibytes");
+ xo_emit(" {T:/%*.*s} {T:/%*.*s}", npkt_len, npkt_len, "Opkts",
+ nerr_len, nerr_len, "Oerrs");
+ if (bflag)
+ xo_emit(" {T:/%*.*s}", nbyte_len, nbyte_len, "Obytes");
+ xo_emit(" {T:/%*s}", nerr_len, "Coll");
+ if (dflag)
+ xo_emit(" {T:/%*.*s}", nerr_len, nerr_len, "Drop");
+ xo_emit("\n");
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ bool network = false, link = false;
+ char *name, *xname, buf[IFNAMSIZ+1];
+
+ if (interface != NULL && strcmp(ifa->ifa_name, interface) != 0)
+ continue;
+
+ name = ifa->ifa_name;
+
+ if (pfunc) {
+
+ (*pfunc)(name);
+
+ /*
+ * Skip all ifaddrs belonging to same interface.
+ */
+ while(ifa->ifa_next != NULL &&
+ (strcmp(ifa->ifa_next->ifa_name, name) == 0)) {
+ ifa = ifa->ifa_next;
+ }
+ continue;
+ }
+
+ if (af != AF_UNSPEC && ifa->ifa_addr->sa_family != af)
+ continue;
+
+ xo_open_instance("interface");
+
+ if ((ifa->ifa_flags & IFF_UP) == 0) {
+ xname = stpcpy(buf, name);
+ *xname++ = '*';
+ *xname = '\0';
+ xname = buf;
+ } else
+ xname = name;
+
+ xo_emit("{d:/%-*.*s}{etk:name}{eq:flags/0x%x}",
+ ifn_len_max, ifn_len_max, xname, name, ifa->ifa_flags);
+
+#define IFA_MTU(ifa) (((struct if_data *)(ifa)->ifa_data)->ifi_mtu)
+ show_stat("lu", 6, "mtu", IFA_MTU(ifa), IFA_MTU(ifa), 0);
+#undef IFA_MTU
+
+ process_ifa_addr(EMIT, ifa, &net_len, &addr_len,
+ &network, &link);
+
+ show_stat("lu", npkt_len, "received-packets",
+ IFA_STAT(ipackets), link|network, 1);
+ show_stat("lu", nerr_len, "received-errors", IFA_STAT(ierrors),
+ link, 1);
+ show_stat("lu", nerr_len, "dropped-packets", IFA_STAT(iqdrops),
+ link, 1);
+ if (bflag)
+ show_stat("lu", nbyte_len, "received-bytes",
+ IFA_STAT(ibytes), link|network, 0);
+ show_stat("lu", npkt_len, "sent-packets", IFA_STAT(opackets),
+ link|network, 1);
+ show_stat("lu", nerr_len, "send-errors", IFA_STAT(oerrors),
+ link, 1);
+ if (bflag)
+ show_stat("lu", nbyte_len, "sent-bytes",
+ IFA_STAT(obytes), link|network, 0);
+ show_stat("NRSlu", nerr_len, "collisions", IFA_STAT(collisions),
+ link, 1);
+ if (dflag)
+ show_stat("LSlu", nerr_len, "dropped-packets",
+ IFA_STAT(oqdrops), link, 1);
+ xo_emit("\n");
+
+ if (!aflag) {
+ xo_close_instance("interface");
+ continue;
+ }
+
+ /*
+ * Print family's multicast addresses.
+ */
+ xo_open_list("multicast-address");
+ for (ifma = next_ifma(ifmap, ifa->ifa_name,
+ ifa->ifa_addr->sa_family);
+ ifma != NULL;
+ ifma = next_ifma(ifma, ifa->ifa_name,
+ ifa->ifa_addr->sa_family)) {
+ const char *fmt = NULL;
+
+ xo_open_instance("multicast-address");
+ switch (ifma->ifma_addr->sa_family) {
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sdl;
+
+ sdl = (struct sockaddr_dl *)ifma->ifma_addr;
+ if (sdl->sdl_type != IFT_ETHER &&
+ sdl->sdl_type != IFT_FDDI)
+ break;
+ }
+ /* FALLTHROUGH */
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif /* INET6 */
+ fmt = routename(ifma->ifma_addr, numeric_addr);
+ break;
+ }
+ if (fmt) {
+ if (Wflag)
+ xo_emit("{P:/%27s }"
+ "{t:address/%-17s/}", "", fmt);
+ else
+ xo_emit("{P:/%25s }"
+ "{t:address/%-17.17s/}", "", fmt);
+ if (ifma->ifma_addr->sa_family == AF_LINK) {
+ xo_emit(" {:received-packets/%8lu}",
+ IFA_STAT(imcasts));
+ xo_emit("{P:/%*s}", bflag? 17 : 6, "");
+ xo_emit(" {:sent-packets/%8lu}",
+ IFA_STAT(omcasts));
+ }
+ xo_emit("\n");
+ }
+ xo_close_instance("multicast-address");
+ ifma = ifma->ifma_next;
+ }
+ xo_close_list("multicast-address");
+ xo_close_instance("interface");
+ }
+ xo_close_list("interface");
+
+ freeifaddrs(ifap);
+ if (aflag)
+ freeifmaddrs(ifmap);
+}
+
+struct iftot {
+ u_long ift_ip; /* input packets */
+ u_long ift_ie; /* input errors */
+ u_long ift_id; /* input drops */
+ u_long ift_op; /* output packets */
+ u_long ift_oe; /* output errors */
+ u_long ift_od; /* output drops */
+ u_long ift_co; /* collisions */
+ u_long ift_ib; /* input bytes */
+ u_long ift_ob; /* output bytes */
+};
+
+/*
+ * Obtain stats for interface(s).
+ */
+static void
+fill_iftot(struct iftot *st)
+{
+ struct ifaddrs *ifap, *ifa;
+ bool found = false;
+
+ if (getifaddrs(&ifap) != 0)
+ xo_err(EX_OSERR, "getifaddrs");
+
+ bzero(st, sizeof(*st));
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+ if (interface) {
+ if (strcmp(ifa->ifa_name, interface) == 0)
+ found = true;
+ else
+ continue;
+ }
+
+ st->ift_ip += IFA_STAT(ipackets);
+ st->ift_ie += IFA_STAT(ierrors);
+ st->ift_id += IFA_STAT(iqdrops);
+ st->ift_ib += IFA_STAT(ibytes);
+ st->ift_op += IFA_STAT(opackets);
+ st->ift_oe += IFA_STAT(oerrors);
+ st->ift_od += IFA_STAT(oqdrops);
+ st->ift_ob += IFA_STAT(obytes);
+ st->ift_co += IFA_STAT(collisions);
+ }
+
+ if (interface && found == false)
+ xo_err(EX_DATAERR, "interface %s not found", interface);
+
+ freeifaddrs(ifap);
+}
+
+/*
+ * Set a flag to indicate that a signal from the periodic itimer has been
+ * caught.
+ */
+static sig_atomic_t signalled;
+static void
+catchalarm(int signo __unused)
+{
+ signalled = true;
+}
+
+/*
+ * Print a running summary of interface statistics.
+ * Repeat display every interval seconds, showing statistics
+ * collected over that interval. Assumes that interval is non-zero.
+ * First line printed at top of screen is always cumulative.
+ */
+static void
+sidewaysintpr(void)
+{
+ struct iftot ift[2], *new, *old;
+ struct itimerval interval_it;
+ int oldmask, line;
+
+ new = &ift[0];
+ old = &ift[1];
+ fill_iftot(old);
+
+ (void)signal(SIGALRM, catchalarm);
+ signalled = false;
+ interval_it.it_interval.tv_sec = interval;
+ interval_it.it_interval.tv_usec = 0;
+ interval_it.it_value = interval_it.it_interval;
+ setitimer(ITIMER_REAL, &interval_it, NULL);
+ xo_open_list("interface-statistics");
+
+banner:
+ xo_emit("{T:/%17s} {T:/%14s} {T:/%16s}\n", "input",
+ interface != NULL ? interface : "(Total)", "output");
+ xo_emit("{T:/%10s} {T:/%5s} {T:/%5s} {T:/%10s} {T:/%10s} {T:/%5s} "
+ "{T:/%10s} {T:/%5s}",
+ "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes",
+ "colls");
+ if (dflag)
+ xo_emit(" {T:/%5.5s}", "drops");
+ xo_emit("\n");
+ xo_flush();
+ line = 0;
+
+loop:
+ if ((noutputs != 0) && (--noutputs == 0)) {
+ xo_close_list("interface-statistics");
+ return;
+ }
+ oldmask = sigblock(sigmask(SIGALRM));
+ while (!signalled)
+ sigpause(0);
+ signalled = false;
+ sigsetmask(oldmask);
+ line++;
+
+ fill_iftot(new);
+
+ xo_open_instance("stats");
+ show_stat("lu", 10, "received-packets",
+ new->ift_ip - old->ift_ip, 1, 1);
+ show_stat("lu", 5, "received-errors",
+ new->ift_ie - old->ift_ie, 1, 1);
+ show_stat("lu", 5, "dropped-packets",
+ new->ift_id - old->ift_id, 1, 1);
+ show_stat("lu", 10, "received-bytes",
+ new->ift_ib - old->ift_ib, 1, 0);
+ show_stat("lu", 10, "sent-packets",
+ new->ift_op - old->ift_op, 1, 1);
+ show_stat("lu", 5, "send-errors",
+ new->ift_oe - old->ift_oe, 1, 1);
+ show_stat("lu", 10, "sent-bytes",
+ new->ift_ob - old->ift_ob, 1, 0);
+ show_stat("NRSlu", 5, "collisions",
+ new->ift_co - old->ift_co, 1, 1);
+ if (dflag)
+ show_stat("LSlu", 5, "dropped-packets",
+ new->ift_od - old->ift_od, 1, 1);
+ xo_close_instance("stats");
+ xo_emit("\n");
+ xo_flush();
+
+ if (new == &ift[0]) {
+ new = &ift[1];
+ old = &ift[0];
+ } else {
+ new = &ift[0];
+ old = &ift[1];
+ }
+
+ if (line == 21)
+ goto banner;
+ else
+ goto loop;
+
+ /* NOTREACHED */
+}
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
new file mode 100644
index 000000000000..6065a2a7644c
--- /dev/null
+++ b/usr.bin/netstat/inet.c
@@ -0,0 +1,1539 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993, 1995
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/domain.h>
+#define _WANT_PROTOSW
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#define _WANT_SOCKET
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_carp.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif /* INET6 */
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_divert.h>
+#include <netinet/ip_var.h>
+#include <netinet/pim_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "nl_defs.h"
+
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+#ifdef INET
+static void inetprint(const char *, struct in_addr *, int, const char *, int,
+ const int);
+#endif
+#ifdef INET6
+static int udp_done, tcp_done, sdp_done;
+#endif /* INET6 */
+
+static int
+pcblist_sysctl(int proto, const char *name, char **bufp)
+{
+ const char *mibvar;
+ char *buf;
+ size_t len;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ mibvar = "net.inet.tcp.pcblist";
+ break;
+ case IPPROTO_UDP:
+ mibvar = "net.inet.udp.pcblist";
+ break;
+ default:
+ mibvar = "net.inet.raw.pcblist";
+ break;
+ }
+ if (strncmp(name, "sdp", 3) == 0)
+ mibvar = "net.inet.sdp.pcblist";
+ else if (strncmp(name, "divert", 6) == 0)
+ mibvar = "net.inet.divert.pcblist";
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ xo_warn("sysctl: %s", mibvar);
+ return (0);
+ }
+ if ((buf = malloc(len)) == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return (0);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ xo_warn("sysctl: %s", mibvar);
+ free(buf);
+ return (0);
+ }
+ *bufp = buf;
+ return (1);
+}
+
+/*
+ * Copied directly from uipc_socket2.c. We leave out some fields that are in
+ * nested structures that aren't used to avoid extra work.
+ */
+static void
+sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
+{
+ xsb->sb_cc = sb->sb_ccc;
+ xsb->sb_hiwat = sb->sb_hiwat;
+ xsb->sb_mbcnt = sb->sb_mbcnt;
+ xsb->sb_mbmax = sb->sb_mbmax;
+ xsb->sb_lowat = sb->sb_lowat;
+ xsb->sb_flags = sb->sb_flags;
+ xsb->sb_timeo = sb->sb_timeo;
+}
+
+int
+sotoxsocket(struct socket *so, struct xsocket *xso)
+{
+ struct protosw proto;
+ struct domain domain;
+
+ bzero(xso, sizeof *xso);
+ xso->xso_len = sizeof *xso;
+ xso->xso_so = (uintptr_t)so;
+ xso->so_type = so->so_type;
+ xso->so_options = so->so_options;
+ xso->so_linger = so->so_linger;
+ xso->so_state = so->so_state;
+ xso->so_pcb = (uintptr_t)so->so_pcb;
+ if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
+ return (-1);
+ xso->xso_protocol = proto.pr_protocol;
+ if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
+ return (-1);
+ xso->xso_family = domain.dom_family;
+ xso->so_timeo = so->so_timeo;
+ xso->so_error = so->so_error;
+ if ((so->so_options & SO_ACCEPTCONN) != 0) {
+ xso->so_qlen = so->sol_qlen;
+ xso->so_incqlen = so->sol_incqlen;
+ xso->so_qlimit = so->sol_qlimit;
+ } else {
+ sbtoxsockbuf(&so->so_snd, &xso->so_snd);
+ sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
+ xso->so_oobmark = so->so_oobmark;
+ }
+ return (0);
+}
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol. For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+void
+protopr(u_long off, const char *name, int af1, int proto)
+{
+ static int first = 1;
+ int istcp;
+ char *buf;
+ const char *vchar;
+ struct xtcpcb *tp;
+ struct xinpcb *inp;
+ struct xinpgen *xig, *oxig;
+ struct xsocket *so;
+ int fnamelen, cnamelen;
+
+ istcp = 0;
+ switch (proto) {
+ case IPPROTO_TCP:
+#ifdef INET6
+ if (strncmp(name, "sdp", 3) != 0) {
+ if (tcp_done != 0)
+ return;
+ else
+ tcp_done = 1;
+ } else {
+ if (sdp_done != 0)
+ return;
+ else
+ sdp_done = 1;
+ }
+#endif
+ istcp = 1;
+ break;
+ case IPPROTO_UDP:
+#ifdef INET6
+ if (udp_done != 0)
+ return;
+ else
+ udp_done = 1;
+#endif
+ break;
+ }
+
+ if (!pcblist_sysctl(proto, name, &buf))
+ return;
+
+ if (istcp && (cflag || Cflag)) {
+ fnamelen = strlen("Stack");
+ cnamelen = strlen("CC");
+ oxig = xig = (struct xinpgen *)buf;
+ for (xig = (struct xinpgen*)((char *)xig + xig->xig_len);
+ xig->xig_len > sizeof(struct xinpgen);
+ xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
+ tp = (struct xtcpcb *)xig;
+ inp = &tp->xt_inp;
+ if (inp->inp_gencnt > oxig->xig_gen)
+ continue;
+ so = &inp->xi_socket;
+ if (so->xso_protocol != proto)
+ continue;
+ fnamelen = max(fnamelen, (int)strlen(tp->xt_stack));
+ cnamelen = max(cnamelen, (int)strlen(tp->xt_cc));
+ }
+ }
+
+ oxig = xig = (struct xinpgen *)buf;
+ for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+ xig->xig_len > sizeof(struct xinpgen);
+ xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
+ if (istcp) {
+ tp = (struct xtcpcb *)xig;
+ inp = &tp->xt_inp;
+ } else {
+ inp = (struct xinpcb *)xig;
+ }
+ so = &inp->xi_socket;
+
+ /* Ignore sockets for protocols other than the desired one. */
+ if (proto != 0 && so->xso_protocol != proto)
+ continue;
+
+ /* Ignore PCBs which were freed during copyout. */
+ if (inp->inp_gencnt > oxig->xig_gen)
+ continue;
+
+ if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
+#ifdef INET6
+ || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
+#endif /* INET6 */
+ || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
+#ifdef INET6
+ && (inp->inp_vflag & INP_IPV6) == 0
+#endif /* INET6 */
+ ))
+ )
+ continue;
+ if (!aflag &&
+ (
+ (istcp && tp->t_state == TCPS_LISTEN)
+ || (af1 == AF_INET &&
+ inp->inp_laddr.s_addr == INADDR_ANY)
+#ifdef INET6
+ || (af1 == AF_INET6 &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif /* INET6 */
+ || (af1 == AF_UNSPEC &&
+ (((inp->inp_vflag & INP_IPV4) != 0 &&
+ inp->inp_laddr.s_addr == INADDR_ANY)
+#ifdef INET6
+ || ((inp->inp_vflag & INP_IPV6) != 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif
+ ))
+ ))
+ continue;
+
+ if (first) {
+ if (!Lflag) {
+ xo_emit("Active Internet connections");
+ if (aflag)
+ xo_emit(" (including servers)");
+ } else
+ xo_emit(
+ "Current listen queue sizes (qlen/incqlen/maxqlen)");
+ xo_emit("\n");
+ if (Aflag)
+ xo_emit("{T:/%-*s} ", 2 * (int)sizeof(void *),
+ "Tcpcb");
+ if (Lflag)
+ xo_emit((Aflag && !Wflag) ?
+ "{T:/%-5.5s} {T:/%-32.32s} {T:/%-18.18s}" :
+ ((!Wflag || af1 == AF_INET) ?
+ "{T:/%-5.5s} {T:/%-32.32s} {T:/%-22.22s}" :
+ "{T:/%-5.5s} {T:/%-32.32s} {T:/%-45.45s}"),
+ "Proto", "Listen", "Local Address");
+ else if (Tflag)
+ xo_emit((Aflag && !Wflag) ?
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%s}" :
+ ((!Wflag || af1 == AF_INET) ?
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%s}" :
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%s}"),
+ "Proto", "Rexmit", "OOORcv", "0-win",
+ "Local Address", "Foreign Address");
+ else {
+ xo_emit((Aflag && !Wflag) ?
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%-18.18s}" :
+ ((!Wflag || af1 == AF_INET) ?
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%-22.22s}" :
+ "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%-45.45s}"),
+ "Proto", "Recv-Q", "Send-Q",
+ "Local Address", "Foreign Address");
+ if (!xflag && !Rflag)
+ xo_emit(" {T:/%-11.11s}", "(state)");
+ }
+ if (xflag) {
+ xo_emit("{T:/%-6.6s} {T:/%-6.6s} "
+ "{T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} "
+ "{T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s}",
+ "R-HIWA", "S-HIWA", "R-LOWA", "S-LOWA",
+ "R-BCNT", "S-BCNT", "R-BMAX", "S-BMAX");
+ xo_emit(" {T:/%7.7s} {T:/%7.7s} {T:/%7.7s} "
+ "{T:/%7.7s} {T:/%7.7s} {T:/%7.7s}",
+ "rexmt", "persist", "keep", "2msl",
+ "delack", "rcvtime");
+ } else if (Rflag) {
+ xo_emit(" {T:/%8.8s} {T:/%5.5s}",
+ "flowid", "ftype");
+ }
+ if (cflag) {
+ xo_emit(" {T:/%-*.*s}",
+ fnamelen, fnamelen, "Stack");
+ }
+ if (Cflag)
+ xo_emit(" {T:/%-*.*s} {T:/%10.10s}"
+ " {T:/%10.10s} {T:/%5.5s}"
+ " {T:/%3.3s}", cnamelen,
+ cnamelen, "CC",
+ "cwin",
+ "ssthresh",
+ "MSS",
+ "ECN");
+ if (Pflag)
+ xo_emit(" {T:/%s}", "Log ID");
+ xo_emit("\n");
+ first = 0;
+ }
+ if (Lflag && so->so_qlimit == 0)
+ continue;
+ xo_open_instance("socket");
+ if (Aflag)
+ xo_emit("{q:address/%*lx} ", 2 * (int)sizeof(void *),
+ (u_long)so->so_pcb);
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV6) != 0)
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+ "46" : "6";
+ else
+#endif
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+ "4" : "";
+ if (istcp && (tp->t_flags & TF_TOE) != 0)
+ xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", "toe", vchar);
+ else
+ xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", name, vchar);
+ if (Lflag) {
+ char buf1[33];
+
+ snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen,
+ so->so_incqlen, so->so_qlimit);
+ xo_emit("{:listen-queue-sizes/%-32.32s} ", buf1);
+ } else if (Tflag) {
+ if (istcp)
+ xo_emit("{:sent-retransmit-packets/%6u} "
+ "{:received-out-of-order-packets/%6u} "
+ "{:sent-zero-window/%6u} ",
+ tp->t_sndrexmitpack, tp->t_rcvoopack,
+ tp->t_sndzerowin);
+ else
+ xo_emit("{P:/%21s}", "");
+ } else {
+ xo_emit("{:receive-bytes-waiting/%6u} "
+ "{:send-bytes-waiting/%6u} ",
+ so->so_rcv.sb_cc, so->so_snd.sb_cc);
+ }
+ if (numeric_port) {
+#ifdef INET
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint("local", &inp->inp_laddr,
+ (int)inp->inp_lport, name, 1, af1);
+ if (!Lflag)
+ inetprint("remote", &inp->inp_faddr,
+ (int)inp->inp_fport, name, 1, af1);
+ }
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6) {
+ inet6print("local", &inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print("remote", &inp->in6p_faddr,
+ (int)inp->inp_fport, name, 1);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else if (inp->inp_flags & INP_ANONPORT) {
+#ifdef INET
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint("local", &inp->inp_laddr,
+ (int)inp->inp_lport, name, 1, af1);
+ if (!Lflag)
+ inetprint("remote", &inp->inp_faddr,
+ (int)inp->inp_fport, name, 0, af1);
+ }
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6) {
+ inet6print("local", &inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print("remote", &inp->in6p_faddr,
+ (int)inp->inp_fport, name, 0);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else {
+#ifdef INET
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint("local", &inp->inp_laddr,
+ (int)inp->inp_lport, name, 0, af1);
+ if (!Lflag)
+ inetprint("remote", &inp->inp_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport != inp->inp_fport,
+ af1);
+ }
+#endif
+#if defined(INET) && defined(INET6)
+ else
+#endif
+#ifdef INET6
+ if (inp->inp_vflag & INP_IPV6) {
+ inet6print("local", &inp->in6p_laddr,
+ (int)inp->inp_lport, name, 0);
+ if (!Lflag)
+ inet6print("remote", &inp->in6p_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport != inp->inp_fport);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ }
+ if (xflag) {
+ xo_emit("{:receive-high-water/%6u} "
+ "{:send-high-water/%6u} "
+ "{:receive-low-water/%6u} {:send-low-water/%6u} "
+ "{:receive-mbuf-bytes/%6u} {:send-mbuf-bytes/%6u} "
+ "{:receive-mbuf-bytes-max/%6u} "
+ "{:send-mbuf-bytes-max/%6u}",
+ so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+ so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+ so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+ so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+ if (istcp)
+ xo_emit(" {:retransmit-timer/%4d.%02d} "
+ "{:persist-timer/%4d.%02d} "
+ "{:keepalive-timer/%4d.%02d} "
+ "{:msl2-timer/%4d.%02d} "
+ "{:delay-ack-timer/%4d.%02d} "
+ "{:inactivity-timer/%4d.%02d}",
+ tp->tt_rexmt / 1000,
+ (tp->tt_rexmt % 1000) / 10,
+ tp->tt_persist / 1000,
+ (tp->tt_persist % 1000) / 10,
+ tp->tt_keep / 1000,
+ (tp->tt_keep % 1000) / 10,
+ tp->tt_2msl / 1000,
+ (tp->tt_2msl % 1000) / 10,
+ tp->tt_delack / 1000,
+ (tp->tt_delack % 1000) / 10,
+ tp->t_rcvtime / 1000,
+ (tp->t_rcvtime % 1000) / 10);
+ }
+ if (istcp && !Lflag && !xflag && !Tflag && !Rflag) {
+ if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
+ xo_emit("{:tcp-state/%-11d}", tp->t_state);
+ else {
+ xo_emit("{:tcp-state/%-11s}",
+ tcpstates[tp->t_state]);
+#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
+ /* Show T/TCP `hidden state' */
+ if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
+ xo_emit("{:need-syn-or-fin/*}");
+#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
+ }
+ }
+ if (Rflag) {
+ /* XXX: is this right Alfred */
+ xo_emit(" {:flow-id/%08x} {:flow-type/%5d}",
+ inp->inp_flowid,
+ inp->inp_flowtype);
+ }
+ if (istcp) {
+ if (cflag)
+ xo_emit(" {:stack/%-*.*s}",
+
+ fnamelen, fnamelen, tp->xt_stack);
+ if (Cflag)
+ xo_emit(" {:cc/%-*.*s}"
+ " {:snd-cwnd/%10lu}"
+ " {:snd-ssthresh/%10lu}"
+ " {:t-maxseg/%5u} {:ecn/%3s}",
+ cnamelen, cnamelen, tp->xt_cc,
+ tp->t_snd_cwnd, tp->t_snd_ssthresh,
+ tp->t_maxseg,
+ (tp->t_state >= TCPS_ESTABLISHED ?
+ (tp->xt_ecn > 0 ?
+ (tp->xt_ecn == 1 ?
+ "ecn" : "ace")
+ : "off")
+ : "n/a"));
+ if (Pflag)
+ xo_emit(" {:log-id/%s}",
+ tp->xt_logid[0] == '\0' ?
+ "-" : tp->xt_logid);
+ }
+ xo_emit("\n");
+ xo_close_instance("socket");
+ }
+ if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
+ if (oxig->xig_count > xig->xig_count) {
+ xo_emit("Some {d:lost/%s} sockets may have been "
+ "deleted.\n", name);
+ } else if (oxig->xig_count < xig->xig_count) {
+ xo_emit("Some {d:created/%s} sockets may have been "
+ "created.\n", name);
+ } else {
+ xo_emit("Some {d:changed/%s} sockets may have been "
+ "created or deleted.\n", name);
+ }
+ }
+ free(buf);
+}
+
+/*
+ * Dump TCP statistics structure.
+ */
+void
+tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct tcpstat tcpstat;
+ uint64_t tcps_states[TCP_NSTATES];
+
+#ifdef INET6
+ if (tcp_done != 0)
+ return;
+ else
+ tcp_done = 1;
+#endif
+
+ if (fetch_stats("net.inet.tcp.stats", off, &tcpstat,
+ sizeof(tcpstat), kread_counters) != 0)
+ return;
+
+ if (fetch_stats_ro("net.inet.tcp.states", nl[N_TCPS_STATES].n_value,
+ &tcps_states, sizeof(tcps_states), kread_counters) != 0)
+ return;
+
+ xo_open_container("tcp");
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (tcpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f, plural(tcpstat.f))
+#define p1a(f, m) if (tcpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f)
+#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f1, plural(tcpstat.f1), \
+ (uintmax_t )tcpstat.f2, plural(tcpstat.f2))
+#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f1, plural(tcpstat.f1), \
+ (uintmax_t )tcpstat.f2)
+#define p3(f, m) if (tcpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )tcpstat.f, pluralies(tcpstat.f))
+
+ p(tcps_sndtotal, "\t{:sent-packets/%ju} {N:/packet%s sent}\n");
+ p2(tcps_sndpack,tcps_sndbyte, "\t\t{:sent-data-packets/%ju} "
+ "{N:/data packet%s} ({:sent-data-bytes/%ju} {N:/byte%s})\n");
+ p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, "\t\t"
+ "{:sent-retransmitted-packets/%ju} {N:/data packet%s} "
+ "({:sent-retransmitted-bytes/%ju} {N:/byte%s}) "
+ "{N:retransmitted}\n");
+ p(tcps_sndrexmitbad, "\t\t"
+ "{:sent-unnecessary-retransmitted-packets/%ju} "
+ "{N:/data packet%s unnecessarily retransmitted}\n");
+ p(tcps_mturesent, "\t\t{:sent-resends-by-mtu-discovery/%ju} "
+ "{N:/resend%s initiated by MTU discovery}\n");
+ p2a(tcps_sndacks, tcps_delack, "\t\t{:sent-ack-only-packets/%ju} "
+ "{N:/ack-only packet%s/} ({:sent-packets-delayed/%ju} "
+ "{N:delayed})\n");
+ p(tcps_sndurg, "\t\t{:sent-urg-only-packets/%ju} "
+ "{N:/URG only packet%s}\n");
+ p(tcps_sndprobe, "\t\t{:sent-window-probe-packets/%ju} "
+ "{N:/window probe packet%s}\n");
+ p(tcps_sndwinup, "\t\t{:sent-window-update-packets/%ju} "
+ "{N:/window update packet%s}\n");
+ p(tcps_sndctrl, "\t\t{:sent-control-packets/%ju} "
+ "{N:/control packet%s}\n");
+ p(tcps_rcvtotal, "\t{:received-packets/%ju} "
+ "{N:/packet%s received}\n");
+ p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t"
+ "{:received-ack-packets/%ju} {N:/ack%s} "
+ "{N:(for} {:received-ack-bytes/%ju} {N:/byte%s})\n");
+ p(tcps_rcvdupack, "\t\t{:received-duplicate-acks/%ju} "
+ "{N:/duplicate ack%s}\n");
+ p(tcps_tunneled_pkts, "\t\t{:received-udp-tunneled-pkts/%ju} "
+ "{N:/UDP tunneled pkt%s}\n");
+ p(tcps_tunneled_errs, "\t\t{:received-bad-udp-tunneled-pkts/%ju} "
+ "{N:/UDP tunneled pkt cnt with error%s}\n");
+ p(tcps_rcvacktoomuch, "\t\t{:received-acks-for-data-not-yet-sent/%ju} "
+ "{N:/ack%s for data not yet sent}\n");
+ p(tcps_rcvghostack, "\t\t{:received-acks-for-data-never-been-sent/%ju} "
+ "{N:/ack%s for data never been sent (ghost acks)}\n");
+ p(tcps_rcvacktooold, "\t\t{:received-acks-for-data-being-too-old/%ju} "
+ "{N:/ack%s for data being too old}\n");
+ p2(tcps_rcvpack, tcps_rcvbyte, "\t\t"
+ "{:received-in-sequence-packets/%ju} {N:/packet%s} "
+ "({:received-in-sequence-bytes/%ju} {N:/byte%s}) "
+ "{N:received in-sequence}\n");
+ p2(tcps_rcvduppack, tcps_rcvdupbyte, "\t\t"
+ "{:received-completely-duplicate-packets/%ju} "
+ "{N:/completely duplicate packet%s} "
+ "({:received-completely-duplicate-bytes/%ju} {N:/byte%s})\n");
+ p(tcps_pawsdrop, "\t\t{:received-old-duplicate-packets/%ju} "
+ "{N:/old duplicate packet%s}\n");
+ p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, "\t\t"
+ "{:received-some-duplicate-packets/%ju} "
+ "{N:/packet%s with some dup. data} "
+ "({:received-some-duplicate-bytes/%ju} {N:/byte%s duped/})\n");
+ p2(tcps_rcvoopack, tcps_rcvoobyte, "\t\t{:received-out-of-order/%ju} "
+ "{N:/out-of-order packet%s} "
+ "({:received-out-of-order-bytes/%ju} {N:/byte%s})\n");
+ p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, "\t\t"
+ "{:received-after-window-packets/%ju} {N:/packet%s} "
+ "({:received-after-window-bytes/%ju} {N:/byte%s}) "
+ "{N:of data after window}\n");
+ p(tcps_rcvwinprobe, "\t\t{:received-window-probes/%ju} "
+ "{N:/window probe%s}\n");
+ p(tcps_rcvwinupd, "\t\t{:receive-window-update-packets/%ju} "
+ "{N:/window update packet%s}\n");
+ p(tcps_dsack_count, "\t\t{:received-with-dsack-packets/%ju} "
+ "{N:/packet%s received with dsack}\n");
+ p(tcps_dsack_bytes, "\t\t{:received-with-dsack-bytes/%ju} "
+ "{N:/dsack byte%s received (no TLP involved)}\n");
+ p(tcps_dsack_tlp_bytes, "\t\t{:received-with-dsack-bytes-tlp/%ju} "
+ "{N:/dsack byte%s received (TLP responsible)}\n");
+ p(tcps_rcvafterclose, "\t\t{:received-after-close-packets/%ju} "
+ "{N:/packet%s received after close}\n");
+ p(tcps_rcvbadsum, "\t\t{:discard-bad-checksum/%ju} "
+ "{N:/discarded for bad checksum%s}\n");
+ p(tcps_rcvbadoff, "\t\t{:discard-bad-header-offset/%ju} "
+ "{N:/discarded for bad header offset field%s}\n");
+ p1a(tcps_rcvshort, "\t\t{:discard-too-short/%ju} "
+ "{N:discarded because packet too short}\n");
+ p1a(tcps_rcvreassfull, "\t\t{:discard-reassembly-queue-full/%ju} "
+ "{N:discarded due to full reassembly queue}\n");
+ p(tcps_connattempt, "\t{:connection-requests/%ju} "
+ "{N:/connection request%s}\n");
+ p(tcps_accepts, "\t{:connections-accepts/%ju} "
+ "{N:/connection accept%s}\n");
+ p(tcps_badsyn, "\t{:bad-connection-attempts/%ju} "
+ "{N:/bad connection attempt%s}\n");
+ p(tcps_listendrop, "\t{:listen-queue-overflows/%ju} "
+ "{N:/listen queue overflow%s}\n");
+ p(tcps_badrst, "\t{:ignored-in-window-resets/%ju} "
+ "{N:/ignored RSTs in the window%s}\n");
+ p(tcps_connects, "\t{:connections-established/%ju} "
+ "{N:/connection%s established (including accepts)}\n");
+ p(tcps_usedrtt, "\t\t{:connections-hostcache-rtt/%ju} "
+ "{N:/time%s used RTT from hostcache}\n");
+ p(tcps_usedrttvar, "\t\t{:connections-hostcache-rttvar/%ju} "
+ "{N:/time%s used RTT variance from hostcache}\n");
+ p(tcps_usedssthresh, "\t\t{:connections-hostcache-ssthresh/%ju} "
+ "{N:/time%s used slow-start threshold from hostcache}\n");
+ p2(tcps_closed, tcps_drops, "\t{:connections-closed/%ju} "
+ "{N:/connection%s closed (including} "
+ "{:connection-drops/%ju} {N:/drop%s})\n");
+ p(tcps_cachedrtt, "\t\t{:connections-updated-rtt-on-close/%ju} "
+ "{N:/connection%s updated cached RTT on close}\n");
+ p(tcps_cachedrttvar, "\t\t"
+ "{:connections-updated-variance-on-close/%ju} "
+ "{N:/connection%s updated cached RTT variance on close}\n");
+ p(tcps_cachedssthresh, "\t\t"
+ "{:connections-updated-ssthresh-on-close/%ju} "
+ "{N:/connection%s updated cached ssthresh on close}\n");
+ p(tcps_conndrops, "\t{:embryonic-connections-dropped/%ju} "
+ "{N:/embryonic connection%s dropped}\n");
+ p2(tcps_rttupdated, tcps_segstimed, "\t{:segments-updated-rtt/%ju} "
+ "{N:/segment%s updated rtt (of} "
+ "{:segment-update-attempts/%ju} {N:/attempt%s})\n");
+ p(tcps_rexmttimeo, "\t{:retransmit-timeouts/%ju} "
+ "{N:/retransmit timeout%s}\n");
+ p(tcps_timeoutdrop, "\t\t"
+ "{:connections-dropped-by-retransmit-timeout/%ju} "
+ "{N:/connection%s dropped by rexmit timeout}\n");
+ p(tcps_persisttimeo, "\t{:persist-timeout/%ju} "
+ "{N:/persist timeout%s}\n");
+ p(tcps_persistdrop, "\t\t"
+ "{:connections-dropped-by-persist-timeout/%ju} "
+ "{N:/connection%s dropped by persist timeout}\n");
+ p(tcps_finwait2_drops, "\t"
+ "{:connections-dropped-by-finwait2-timeout/%ju} "
+ "{N:/Connection%s (fin_wait_2) dropped because of timeout}\n");
+ p(tcps_keeptimeo, "\t{:keepalive-timeout/%ju} "
+ "{N:/keepalive timeout%s}\n");
+ p(tcps_keepprobe, "\t\t{:keepalive-probes/%ju} "
+ "{N:/keepalive probe%s sent}\n");
+ p(tcps_keepdrops, "\t\t{:connections-dropped-by-keepalives/%ju} "
+ "{N:/connection%s dropped by keepalive}\n");
+ p(tcps_progdrops, "\t{:connections-dropped-due-to-progress-time/%ju} "
+ "{N:/connection%s dropped due to exceeding progress time}\n");
+ p(tcps_predack, "\t{:ack-header-predictions/%ju} "
+ "{N:/correct ACK header prediction%s}\n");
+ p(tcps_preddat, "\t{:data-packet-header-predictions/%ju} "
+ "{N:/correct data packet header prediction%s}\n");
+
+ xo_open_container("syncache");
+
+ p3(tcps_sc_added, "\t{:entries-added/%ju} "
+ "{N:/syncache entr%s added}\n");
+ p1a(tcps_sc_retransmitted, "\t\t{:retransmitted/%ju} "
+ "{N:/retransmitted}\n");
+ p1a(tcps_sc_dupsyn, "\t\t{:duplicates/%ju} {N:/dupsyn}\n");
+ p1a(tcps_sc_dropped, "\t\t{:dropped/%ju} {N:/dropped}\n");
+ p1a(tcps_sc_completed, "\t\t{:completed/%ju} {N:/completed}\n");
+ p1a(tcps_sc_bucketoverflow, "\t\t{:bucket-overflow/%ju} "
+ "{N:/bucket overflow}\n");
+ p1a(tcps_sc_cacheoverflow, "\t\t{:cache-overflow/%ju} "
+ "{N:/cache overflow}\n");
+ p1a(tcps_sc_reset, "\t\t{:reset/%ju} {N:/reset}\n");
+ p1a(tcps_sc_stale, "\t\t{:stale/%ju} {N:/stale}\n");
+ p1a(tcps_sc_aborted, "\t\t{:aborted/%ju} {N:/aborted}\n");
+ p1a(tcps_sc_badack, "\t\t{:bad-ack/%ju} {N:/badack}\n");
+ p1a(tcps_sc_unreach, "\t\t{:unreachable/%ju} {N:/unreach}\n");
+ p(tcps_sc_zonefail, "\t\t{:zone-failures/%ju} {N:/zone failure%s}\n");
+ p(tcps_sc_sendcookie, "\t{:sent-cookies/%ju} {N:/cookie%s sent}\n");
+ p(tcps_sc_recvcookie, "\t{:receivd-cookies/%ju} "
+ "{N:/cookie%s received}\n");
+
+ xo_close_container("syncache");
+
+ xo_open_container("hostcache");
+
+ p3(tcps_hc_added, "\t{:entries-added/%ju} "
+ "{N:/hostcache entr%s added}\n");
+ p1a(tcps_hc_bucketoverflow, "\t\t{:buffer-overflows/%ju} "
+ "{N:/bucket overflow}\n");
+
+ xo_close_container("hostcache");
+
+ xo_open_container("sack");
+
+ p(tcps_sack_recovery_episode, "\t{:recovery-episodes/%ju} "
+ "{N:/SACK recovery episode%s}\n");
+ p(tcps_sack_rexmits, "\t{:segment-retransmits/%ju} "
+ "{N:/segment rexmit%s in SACK recovery episodes}\n");
+ p(tcps_sack_rexmits_tso, "\t{:tso-chunk-retransmits/%ju} "
+ "{N:/tso chunk rexmit%s in SACK recovery episodes}\n");
+ p(tcps_sack_rexmit_bytes, "\t{:byte-retransmits/%ju} "
+ "{N:/byte rexmit%s in SACK recovery episodes}\n");
+ p(tcps_sack_rcv_blocks, "\t{:received-blocks/%ju} "
+ "{N:/SACK option%s (SACK blocks) received}\n");
+ p(tcps_sack_send_blocks, "\t{:sent-option-blocks/%ju} "
+ "{N:/SACK option%s (SACK blocks) sent}\n");
+ p(tcps_sack_lostrexmt, "\t{:lost-retransmissions/%ju} "
+ "{N:/SACK retransmission%s lost}\n");
+ p1a(tcps_sack_sboverflow, "\t{:scoreboard-overflows/%ju} "
+ "{N:/SACK scoreboard overflow}\n");
+
+ xo_close_container("sack");
+ xo_open_container("ecn");
+
+ p(tcps_ecn_rcvce, "\t{:received-ce-packets/%ju} "
+ "{N:/packet%s received with ECN CE bit set}\n");
+ p(tcps_ecn_rcvect0, "\t{:received-ect0-packets/%ju} "
+ "{N:/packet%s received with ECN ECT(0) bit set}\n");
+ p(tcps_ecn_rcvect1, "\t{:received-ect1-packets/%ju} "
+ "{N:/packet%s received with ECN ECT(1) bit set}\n");
+ p(tcps_ecn_sndect0, "\t{:sent-ect0-packets/%ju} "
+ "{N:/packet%s sent with ECN ECT(0) bit set}\n");
+ p(tcps_ecn_sndect1, "\t{:sent-ect1-packets/%ju} "
+ "{N:/packet%s sent with ECN ECT(1) bit set}\n");
+ p(tcps_ecn_shs, "\t{:handshakes/%ju} "
+ "{N:/successful ECN handshake%s}\n");
+ p(tcps_ecn_rcwnd, "\t{:congestion-reductions/%ju} "
+ "{N:/time%s ECN reduced the congestion window}\n");
+
+ p(tcps_ace_nect, "\t{:ace-nonect-syn/%ju} "
+ "{N:/ACE SYN packet%s with Non-ECT}\n");
+ p(tcps_ace_ect0, "\t{:ace-ect0-syn/%ju} "
+ "{N:/ACE SYN packet%s with ECT0}\n");
+ p(tcps_ace_ect1, "\t{:ace-ect1-syn/%ju} "
+ "{N:/ACE SYN packet%s with ECT1}\n");
+ p(tcps_ace_ce, "\t{:ace-ce-syn/%ju} "
+ "{N:/ACE SYN packet%s with CE}\n");
+
+ xo_close_container("ecn");
+ xo_open_container("tcp-signature");
+ p(tcps_sig_rcvgoodsig, "\t{:received-good-signature/%ju} "
+ "{N:/packet%s with matching signature received}\n");
+ p(tcps_sig_rcvbadsig, "\t{:received-bad-signature/%ju} "
+ "{N:/packet%s with bad signature received}\n");
+ p(tcps_sig_err_buildsig, "\t{:failed-make-signature/%ju} "
+ "{N:/time%s failed to make signature due to no SA}\n");
+ p(tcps_sig_err_sigopt, "\t{:no-signature-expected/%ju} "
+ "{N:/time%s unexpected signature received}\n");
+ p(tcps_sig_err_nosigopt, "\t{:no-signature-provided/%ju} "
+ "{N:/time%s no signature provided by segment}\n");
+
+ xo_close_container("tcp-signature");
+ xo_open_container("pmtud");
+
+ p(tcps_pmtud_blackhole_activated, "\t{:pmtud-activated/%ju} "
+ "{N:/Path MTU discovery black hole detection activation%s}\n");
+ p(tcps_pmtud_blackhole_activated_min_mss,
+ "\t{:pmtud-activated-min-mss/%ju} "
+ "{N:/Path MTU discovery black hole detection min MSS activation%s}\n");
+ p(tcps_pmtud_blackhole_failed, "\t{:pmtud-failed/%ju} "
+ "{N:/Path MTU discovery black hole detection failure%s}\n");
+
+ xo_close_container("pmtud");
+ xo_open_container("tw");
+
+ p(tcps_tw_responds, "\t{:tw_responds/%ju} "
+ "{N:/time%s connection in TIME-WAIT responded with ACK}\n");
+ p(tcps_tw_recycles, "\t{:tw_recycles/%ju} "
+ "{N:/time%s connection in TIME-WAIT was actively recycled}\n");
+ p(tcps_tw_resets, "\t{:tw_resets/%ju} "
+ "{N:/time%s connection in TIME-WAIT responded with RST}\n");
+
+ xo_close_container("tw");
+ #undef p
+ #undef p1a
+ #undef p2
+ #undef p2a
+ #undef p3
+
+ xo_open_container("TCP connection count by state");
+ xo_emit("{T:/TCP connection count by state}:\n");
+ for (int i = 0; i < TCP_NSTATES; i++) {
+ /*
+ * XXXGL: is there a way in libxo to use %s
+ * in the "content string" of a format
+ * string? I failed to do that, that's why
+ * a temporary buffer is used to construct
+ * format string for xo_emit().
+ */
+ char fmtbuf[80];
+
+ if (sflag > 1 && tcps_states[i] == 0)
+ continue;
+ snprintf(fmtbuf, sizeof(fmtbuf), "\t{:%s/%%ju} "
+ "{Np:/connection ,connections} in %s state\n",
+ tcpstates[i], tcpstates[i]);
+ xo_emit(fmtbuf, (uintmax_t )tcps_states[i]);
+ }
+ xo_close_container("TCP connection count by state");
+
+ xo_close_container("tcp");
+}
+
+/*
+ * Dump UDP statistics structure.
+ */
+void
+udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct udpstat udpstat;
+ uint64_t delivered;
+
+#ifdef INET6
+ if (udp_done != 0)
+ return;
+ else
+ udp_done = 1;
+#endif
+
+ if (fetch_stats("net.inet.udp.stats", off, &udpstat,
+ sizeof(udpstat), kread_counters) != 0)
+ return;
+
+ xo_open_container("udp");
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (udpstat.f || sflag <= 1) \
+ xo_emit("\t" m, (uintmax_t)udpstat.f, plural(udpstat.f))
+#define p1a(f, m) if (udpstat.f || sflag <= 1) \
+ xo_emit("\t" m, (uintmax_t)udpstat.f)
+
+ p(udps_ipackets, "{:received-datagrams/%ju} "
+ "{N:/datagram%s received}\n");
+ p1a(udps_hdrops, "{:dropped-incomplete-headers/%ju} "
+ "{N:/with incomplete header}\n");
+ p1a(udps_badlen, "{:dropped-bad-data-length/%ju} "
+ "{N:/with bad data length field}\n");
+ p1a(udps_badsum, "{:dropped-bad-checksum/%ju} "
+ "{N:/with bad checksum}\n");
+ p1a(udps_nosum, "{:dropped-no-checksum/%ju} "
+ "{N:/with no checksum}\n");
+ p1a(udps_noport, "{:dropped-no-socket/%ju} "
+ "{N:/dropped due to no socket}\n");
+ p(udps_noportbcast, "{:dropped-broadcast-multicast/%ju} "
+ "{N:/broadcast\\/multicast datagram%s undelivered}\n");
+ p1a(udps_fullsock, "{:dropped-full-socket-buffer/%ju} "
+ "{N:/dropped due to full socket buffers}\n");
+ p1a(udpps_pcbhashmiss, "{:not-for-hashed-pcb/%ju} "
+ "{N:/not for hashed pcb}\n");
+ delivered = udpstat.udps_ipackets -
+ udpstat.udps_hdrops -
+ udpstat.udps_badlen -
+ udpstat.udps_badsum -
+ udpstat.udps_noport -
+ udpstat.udps_noportbcast -
+ udpstat.udps_fullsock;
+ if (delivered || sflag <= 1)
+ xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
+ (uint64_t)delivered);
+ p(udps_opackets, "{:output-packets/%ju} {N:/datagram%s output}\n");
+ /* the next statistic is cumulative in udps_noportbcast */
+ p(udps_filtermcast, "{:multicast-source-filter-matches/%ju} "
+ "{N:/time%s multicast source filter matched}\n");
+#undef p
+#undef p1a
+ xo_close_container("udp");
+}
+
+/*
+ * Dump CARP statistics structure.
+ */
+void
+carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct carpstats carpstat;
+
+ if (fetch_stats("net.inet.carp.stats", off, &carpstat,
+ sizeof(carpstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (carpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)carpstat.f, plural(carpstat.f))
+#define p2(f, m) if (carpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)carpstat.f)
+
+ p(carps_ipackets, "\t{:received-inet-packets/%ju} "
+ "{N:/packet%s received (IPv4)}\n");
+ p(carps_ipackets6, "\t{:received-inet6-packets/%ju} "
+ "{N:/packet%s received (IPv6)}\n");
+ p(carps_badttl, "\t\t{:dropped-wrong-ttl/%ju} "
+ "{N:/packet%s discarded for wrong TTL}\n");
+ p(carps_hdrops, "\t\t{:dropped-short-header/%ju} "
+ "{N:/packet%s shorter than header}\n");
+ p(carps_badsum, "\t\t{:dropped-bad-checksum/%ju} "
+ "{N:/discarded for bad checksum%s}\n");
+ p(carps_badver, "\t\t{:dropped-bad-version/%ju} "
+ "{N:/discarded packet%s with a bad version}\n");
+ p2(carps_badlen, "\t\t{:dropped-short-packet/%ju} "
+ "{N:/discarded because packet too short}\n");
+ p2(carps_badauth, "\t\t{:dropped-bad-authentication/%ju} "
+ "{N:/discarded for bad authentication}\n");
+ p2(carps_badvhid, "\t\t{:dropped-bad-vhid/%ju} "
+ "{N:/discarded for bad vhid}\n");
+ p2(carps_badaddrs, "\t\t{:dropped-bad-address-list/%ju} "
+ "{N:/discarded because of a bad address list}\n");
+ p(carps_opackets, "\t{:sent-inet-packets/%ju} "
+ "{N:/packet%s sent (IPv4)}\n");
+ p(carps_opackets6, "\t{:sent-inet6-packets/%ju} "
+ "{N:/packet%s sent (IPv6)}\n");
+ p2(carps_onomem, "\t\t{:send-failed-memory-error/%ju} "
+ "{N:/send failed due to mbuf memory error}\n");
+#if notyet
+ p(carps_ostates, "\t\t{:send-state-updates/%s} "
+ "{N:/state update%s sent}\n");
+#endif
+#undef p
+#undef p2
+ xo_close_container(name);
+}
+
+/*
+ * Dump IP statistics structure.
+ */
+void
+ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ipstat ipstat;
+
+ if (fetch_stats("net.inet.ip.stats", off, &ipstat,
+ sizeof(ipstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (ipstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )ipstat.f, plural(ipstat.f))
+#define p1a(f, m) if (ipstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t )ipstat.f)
+
+ p(ips_total, "\t{:received-packets/%ju} "
+ "{N:/total packet%s received}\n");
+ p(ips_badsum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/bad header checksum%s}\n");
+ p1a(ips_toosmall, "\t{:dropped-below-minimum-size/%ju} "
+ "{N:/with size smaller than minimum}\n");
+ p1a(ips_tooshort, "\t{:dropped-short-packets/%ju} "
+ "{N:/with data size < data length}\n");
+ p1a(ips_toolong, "\t{:dropped-too-long/%ju} "
+ "{N:/with ip length > max ip packet size}\n");
+ p1a(ips_badhlen, "\t{:dropped-short-header-length/%ju} "
+ "{N:/with header length < data size}\n");
+ p1a(ips_badlen, "\t{:dropped-short-data/%ju} "
+ "{N:/with data length < header length}\n");
+ p1a(ips_badoptions, "\t{:dropped-bad-options/%ju} "
+ "{N:/with bad options}\n");
+ p1a(ips_badvers, "\t{:dropped-bad-version/%ju} "
+ "{N:/with incorrect version number}\n");
+ p(ips_fragments, "\t{:received-fragments/%ju} "
+ "{N:/fragment%s received}\n");
+ p(ips_fragdropped, "\t{:dropped-fragments/%ju} "
+ "{N:/fragment%s dropped (dup or out of space)}\n");
+ p(ips_fragtimeout, "\t{:dropped-fragments-after-timeout/%ju} "
+ "{N:/fragment%s dropped after timeout}\n");
+ p(ips_reassembled, "\t{:reassembled-packets/%ju} "
+ "{N:/packet%s reassembled ok}\n");
+ p(ips_delivered, "\t{:received-local-packets/%ju} "
+ "{N:/packet%s for this host}\n");
+ p(ips_noproto, "\t{:dropped-unknown-protocol/%ju} "
+ "{N:/packet%s for unknown\\/unsupported protocol}\n");
+ p(ips_forward, "\t{:forwarded-packets/%ju} "
+ "{N:/packet%s forwarded}");
+ p(ips_fastforward, " ({:fast-forwarded-packets/%ju} "
+ "{N:/packet%s fast forwarded})");
+ if (ipstat.ips_forward || sflag <= 1)
+ xo_emit("\n");
+ p(ips_cantforward, "\t{:packets-cannot-forward/%ju} "
+ "{N:/packet%s not forwardable}\n");
+ p(ips_notmember, "\t{:received-unknown-multicast-group/%ju} "
+ "{N:/packet%s received for unknown multicast group}\n");
+ p(ips_redirectsent, "\t{:redirects-sent/%ju} "
+ "{N:/redirect%s sent}\n");
+ p(ips_localout, "\t{:sent-packets/%ju} "
+ "{N:/packet%s sent from this host}\n");
+ p(ips_rawout, "\t{:send-packets-fabricated-header/%ju} "
+ "{N:/packet%s sent with fabricated ip header}\n");
+ p(ips_odropped, "\t{:discard-no-mbufs/%ju} "
+ "{N:/output packet%s dropped due to no bufs, etc.}\n");
+ p(ips_noroute, "\t{:discard-no-route/%ju} "
+ "{N:/output packet%s discarded due to no route}\n");
+ p(ips_fragmented, "\t{:sent-fragments/%ju} "
+ "{N:/output datagram%s fragmented}\n");
+ p(ips_ofragments, "\t{:fragments-created/%ju} "
+ "{N:/fragment%s created}\n");
+ p(ips_cantfrag, "\t{:discard-cannot-fragment/%ju} "
+ "{N:/datagram%s that can't be fragmented}\n");
+ p(ips_nogif, "\t{:discard-tunnel-no-gif/%ju} "
+ "{N:/tunneling packet%s that can't find gif}\n");
+ p(ips_badaddr, "\t{:discard-bad-address/%ju} "
+ "{N:/datagram%s with bad address in header}\n");
+#undef p
+#undef p1a
+ xo_close_container(name);
+}
+
+/*
+ * Dump ARP statistics structure.
+ */
+void
+arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct arpstat arpstat;
+
+ if (fetch_stats("net.link.ether.arp.stats", off, &arpstat,
+ sizeof(arpstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (arpstat.f || sflag <= 1) \
+ xo_emit("\t" m, (uintmax_t)arpstat.f, plural(arpstat.f))
+#define p2(f, m) if (arpstat.f || sflag <= 1) \
+ xo_emit("\t" m, (uintmax_t)arpstat.f, pluralies(arpstat.f))
+
+ p(txrequests, "{:sent-requests/%ju} {N:/ARP request%s sent}\n");
+ p(txerrors, "{:sent-failures/%ju} {N:/ARP request%s failed to sent}\n");
+ p2(txreplies, "{:sent-replies/%ju} {N:/ARP repl%s sent}\n");
+ p(rxrequests, "{:received-requests/%ju} "
+ "{N:/ARP request%s received}\n");
+ p2(rxreplies, "{:received-replies/%ju} "
+ "{N:/ARP repl%s received}\n");
+ p(received, "{:received-packets/%ju} "
+ "{N:/ARP packet%s received}\n");
+ p(dropped, "{:dropped-no-entry/%ju} "
+ "{N:/total packet%s dropped due to no ARP entry}\n");
+ p(timeouts, "{:entries-timeout/%ju} "
+ "{N:/ARP entry%s timed out}\n");
+ p(dupips, "{:dropped-duplicate-address/%ju} "
+ "{N:/Duplicate IP%s seen}\n");
+#undef p
+#undef p2
+ xo_close_container(name);
+}
+
+
+
+static const char *icmpnames[ICMP_MAXTYPE + 1] = {
+ "echo reply", /* RFC 792 */
+ "#1",
+ "#2",
+ "destination unreachable", /* RFC 792 */
+ "source quench", /* RFC 792 */
+ "routing redirect", /* RFC 792 */
+ "#6",
+ "#7",
+ "echo", /* RFC 792 */
+ "router advertisement", /* RFC 1256 */
+ "router solicitation", /* RFC 1256 */
+ "time exceeded", /* RFC 792 */
+ "parameter problem", /* RFC 792 */
+ "time stamp", /* RFC 792 */
+ "time stamp reply", /* RFC 792 */
+ "information request", /* RFC 792 */
+ "information request reply", /* RFC 792 */
+ "address mask request", /* RFC 950 */
+ "address mask reply", /* RFC 950 */
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "icmp traceroute", /* RFC 1393 */
+ "datagram conversion error", /* RFC 1475 */
+ "mobile host redirect",
+ "IPv6 where-are-you",
+ "IPv6 i-am-here",
+ "mobile registration req",
+ "mobile registration reply",
+ "domain name request", /* RFC 1788 */
+ "domain name reply", /* RFC 1788 */
+ "icmp SKIP",
+ "icmp photuris", /* RFC 2521 */
+};
+
+/*
+ * Dump ICMP statistics.
+ */
+void
+icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct icmpstat icmpstat;
+ size_t len;
+ int i, first;
+
+ if (fetch_stats("net.inet.icmp.stats", off, &icmpstat,
+ sizeof(icmpstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (icmpstat.f || sflag <= 1) \
+ xo_emit(m, icmpstat.f, plural(icmpstat.f))
+#define p1a(f, m) if (icmpstat.f || sflag <= 1) \
+ xo_emit(m, icmpstat.f)
+#define p2(f, m) if (icmpstat.f || sflag <= 1) \
+ xo_emit(m, icmpstat.f, plurales(icmpstat.f))
+
+ p(icps_error, "\t{:icmp-calls/%lu} "
+ "{N:/call%s to icmp_error}\n");
+ p(icps_oldicmp, "\t{:errors-not-from-message/%lu} "
+ "{N:/error%s not generated in response to an icmp message}\n");
+
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) {
+ if (icmpstat.icps_outhist[i] != 0) {
+ if (first) {
+ xo_open_list("output-histogram");
+ xo_emit("\tOutput histogram:\n");
+ first = 0;
+ }
+ xo_open_instance("output-histogram");
+ if (icmpnames[i] != NULL)
+ xo_emit("\t\t{k:name/%s}: {:count/%lu}\n",
+ icmpnames[i], icmpstat.icps_outhist[i]);
+ else
+ xo_emit("\t\tunknown ICMP #{k:name/%d}: "
+ "{:count/%lu}\n",
+ i, icmpstat.icps_outhist[i]);
+ xo_close_instance("output-histogram");
+ }
+ }
+ if (!first)
+ xo_close_list("output-histogram");
+
+ p(icps_badcode, "\t{:dropped-bad-code/%lu} "
+ "{N:/message%s with bad code fields}\n");
+ p(icps_tooshort, "\t{:dropped-too-short/%lu} "
+ "{N:/message%s less than the minimum length}\n");
+ p(icps_checksum, "\t{:dropped-bad-checksum/%lu} "
+ "{N:/message%s with bad checksum}\n");
+ p(icps_badlen, "\t{:dropped-bad-length/%lu} "
+ "{N:/message%s with bad length}\n");
+ p1a(icps_bmcastecho, "\t{:dropped-multicast-echo/%lu} "
+ "{N:/multicast echo requests ignored}\n");
+ p1a(icps_bmcasttstamp, "\t{:dropped-multicast-timestamp/%lu} "
+ "{N:/multicast timestamp requests ignored}\n");
+
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) {
+ if (icmpstat.icps_inhist[i] != 0) {
+ if (first) {
+ xo_open_list("input-histogram");
+ xo_emit("\tInput histogram:\n");
+ first = 0;
+ }
+ xo_open_instance("input-histogram");
+ if (icmpnames[i] != NULL)
+ xo_emit("\t\t{k:name/%s}: {:count/%lu}\n",
+ icmpnames[i],
+ icmpstat.icps_inhist[i]);
+ else
+ xo_emit(
+ "\t\tunknown ICMP #{k:name/%d}: {:count/%lu}\n",
+ i, icmpstat.icps_inhist[i]);
+ xo_close_instance("input-histogram");
+ }
+ }
+ if (!first)
+ xo_close_list("input-histogram");
+
+ p(icps_reflect, "\t{:sent-packets/%lu} "
+ "{N:/message response%s generated}\n");
+ p2(icps_badaddr, "\t{:discard-invalid-return-address/%lu} "
+ "{N:/invalid return address%s}\n");
+ p(icps_noroute, "\t{:discard-no-route/%lu} "
+ "{N:/no return route%s}\n");
+#undef p
+#undef p1a
+#undef p2
+ if (live) {
+ len = sizeof i;
+ if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) <
+ 0)
+ return;
+ xo_emit("\tICMP address mask responses are "
+ "{q:icmp-address-responses/%sabled}\n", i ? "en" : "dis");
+ }
+
+ xo_close_container(name);
+}
+
+/*
+ * Dump IGMP statistics structure.
+ */
+void
+igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct igmpstat igmpstat;
+ int error, zflag0;
+
+ if (fetch_stats("net.inet.igmp.stats", 0, &igmpstat,
+ sizeof(igmpstat), kread) != 0)
+ return;
+ /*
+ * Reread net.inet.igmp.stats when zflag == 1.
+ * This is because this MIB contains version number and
+ * length of the structure which are not set when clearing
+ * the counters.
+ */
+ zflag0 = zflag;
+ if (zflag) {
+ zflag = 0;
+ error = fetch_stats("net.inet.igmp.stats", 0, &igmpstat,
+ sizeof(igmpstat), kread);
+ zflag = zflag0;
+ if (error)
+ return;
+ }
+
+ if (igmpstat.igps_version != IGPS_VERSION_3) {
+ xo_warnx("%s: version mismatch (%d != %d)", __func__,
+ igmpstat.igps_version, IGPS_VERSION_3);
+ return;
+ }
+ if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
+ xo_warnx("%s: size mismatch (%d != %d)", __func__,
+ igmpstat.igps_len, IGPS_VERSION3_LEN);
+ return;
+ }
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p64(f, m) if (igmpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t) igmpstat.f, plural(igmpstat.f))
+#define py64(f, m) if (igmpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t) igmpstat.f, pluralies(igmpstat.f))
+
+ p64(igps_rcv_total, "\t{:received-messages/%ju} "
+ "{N:/message%s received}\n");
+ p64(igps_rcv_tooshort, "\t{:dropped-too-short/%ju} "
+ "{N:/message%s received with too few bytes}\n");
+ p64(igps_rcv_badttl, "\t{:dropped-wrong-ttl/%ju} "
+ "{N:/message%s received with wrong TTL}\n");
+ p64(igps_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/message%s received with bad checksum}\n");
+ py64(igps_rcv_v1v2_queries, "\t{:received-membership-queries/%ju} "
+ "{N:/V1\\/V2 membership quer%s received}\n");
+ py64(igps_rcv_v3_queries, "\t{:received-v3-membership-queries/%ju} "
+ "{N:/V3 membership quer%s received}\n");
+ py64(igps_rcv_badqueries, "\t{:dropped-membership-queries/%ju} "
+ "{N:/membership quer%s received with invalid field(s)}\n");
+ py64(igps_rcv_gen_queries, "\t{:received-general-queries/%ju} "
+ "{N:/general quer%s received}\n");
+ py64(igps_rcv_group_queries, "\t{:received-group-queries/%ju} "
+ "{N:/group quer%s received}\n");
+ py64(igps_rcv_gsr_queries, "\t{:received-group-source-queries/%ju} "
+ "{N:/group-source quer%s received}\n");
+ py64(igps_drop_gsr_queries, "\t{:dropped-group-source-queries/%ju} "
+ "{N:/group-source quer%s dropped}\n");
+ p64(igps_rcv_reports, "\t{:received-membership-requests/%ju} "
+ "{N:/membership report%s received}\n");
+ p64(igps_rcv_badreports, "\t{:dropped-membership-reports/%ju} "
+ "{N:/membership report%s received with invalid field(s)}\n");
+ p64(igps_rcv_ourreports, "\t"
+ "{:received-membership-reports-matching/%ju} "
+ "{N:/membership report%s received for groups to which we belong}"
+ "\n");
+ p64(igps_rcv_nora, "\t{:received-v3-reports-no-router-alert/%ju} "
+ "{N:/V3 report%s received without Router Alert}\n");
+ p64(igps_snd_reports, "\t{:sent-membership-reports/%ju} "
+ "{N:/membership report%s sent}\n");
+#undef p64
+#undef py64
+ xo_close_container(name);
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim_stats(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
+{
+ struct pimstat pimstat;
+
+ if (fetch_stats("net.inet.pim.stats", off, &pimstat,
+ sizeof(pimstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (pimstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pimstat.f, plural(pimstat.f))
+#define py(f, m) if (pimstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
+
+ p(pims_rcv_total_msgs, "\t{:received-messages/%ju} "
+ "{N:/message%s received}\n");
+ p(pims_rcv_total_bytes, "\t{:received-bytes/%ju} "
+ "{N:/byte%s received}\n");
+ p(pims_rcv_tooshort, "\t{:dropped-too-short/%ju} "
+ "{N:/message%s received with too few bytes}\n");
+ p(pims_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/message%s received with bad checksum}\n");
+ p(pims_rcv_badversion, "\t{:dropped-bad-version/%ju} "
+ "{N:/message%s received with bad version}\n");
+ p(pims_rcv_registers_msgs, "\t{:received-data-register-messages/%ju} "
+ "{N:/data register message%s received}\n");
+ p(pims_rcv_registers_bytes, "\t{:received-data-register-bytes/%ju} "
+ "{N:/data register byte%s received}\n");
+ p(pims_rcv_registers_wrongiif, "\t"
+ "{:received-data-register-wrong-interface/%ju} "
+ "{N:/data register message%s received on wrong iif}\n");
+ p(pims_rcv_badregisters, "\t{:received-bad-registers/%ju} "
+ "{N:/bad register%s received}\n");
+ p(pims_snd_registers_msgs, "\t{:sent-data-register-messages/%ju} "
+ "{N:/data register message%s sent}\n");
+ p(pims_snd_registers_bytes, "\t{:sent-data-register-bytes/%ju} "
+ "{N:/data register byte%s sent}\n");
+#undef p
+#undef py
+ xo_close_container(name);
+}
+
+/*
+ * Dump divert(4) statistics structure.
+ */
+void
+divert_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct divstat divstat;
+
+ if (fetch_stats("net.inet.divert.stats", off, &divstat,
+ sizeof(divstat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (divstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)divstat.f, plural(divstat.f))
+
+ p(div_diverted, "\t{:diverted-packets/%ju} "
+ "{N:/packet%s successfully diverted to userland}\n");
+ p(div_noport, "\t{:noport-fails/%ju} "
+ "{N:/packet%s failed to divert due to no socket bound at port}\n");
+ p(div_outbound, "\t{:outbound-packets/%ju} "
+ "{N:/packet%s successfully re-injected as outbound}\n");
+ p(div_inbound, "\t{:inbound-packets/%ju} "
+ "{N:/packet%s successfully re-injected as inbound}\n");
+#undef p
+ xo_close_container(name);
+}
+
+#ifdef INET
+/*
+ * Pretty print an Internet address (net address + port).
+ */
+static void
+inetprint(const char *container, struct in_addr *in, int port,
+ const char *proto, int num_port, const int af1)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+ size_t alen, plen;
+
+ if (container)
+ xo_open_container(container);
+
+ if (Wflag)
+ snprintf(line, sizeof(line), "%s.", inetname(in));
+ else
+ snprintf(line, sizeof(line), "%.*s.",
+ (Aflag && !num_port) ? 12 : 16, inetname(in));
+ alen = strlen(line);
+ cp = line + alen;
+ if (!num_port && port)
+ sp = getservbyport((int)port, proto);
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - alen,
+ "%.15s ", sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - alen,
+ "%d ", ntohs((u_short)port));
+ width = (Aflag && !Wflag) ? 18 :
+ ((!Wflag || af1 == AF_INET) ? 22 : 45);
+ if (Wflag)
+ xo_emit("{d:target/%-*s} ", width, line);
+ else
+ xo_emit("{d:target/%-*.*s} ", width, width, line);
+
+ plen = strlen(cp) - 1;
+ alen--;
+ xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
+ plen, cp);
+
+ if (container)
+ xo_close_container(container);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(struct in_addr *inp)
+{
+ char *cp;
+ static char line[MAXHOSTNAMELEN];
+ struct hostent *hp;
+
+ cp = 0;
+ if (!numeric_addr && inp->s_addr != INADDR_ANY) {
+ hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+ if (hp) {
+ cp = hp->h_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ if (inp->s_addr == INADDR_ANY)
+ strcpy(line, "*");
+ else if (cp) {
+ strlcpy(line, cp, sizeof(line));
+ } else {
+ inp->s_addr = ntohl(inp->s_addr);
+#define C(x) ((u_int)((x) & 0xff))
+ snprintf(line, sizeof(line), "%u.%u.%u.%u",
+ C(inp->s_addr >> 24), C(inp->s_addr >> 16),
+ C(inp->s_addr >> 8), C(inp->s_addr));
+ }
+ return (line);
+}
+#endif
diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c
new file mode 100644
index 000000000000..5995be299425
--- /dev/null
+++ b/usr.bin/netstat/inet6.c
@@ -0,0 +1,1359 @@
+/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/cdefs.h>
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in_systm.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/pim6_var.h>
+#include <netinet6/raw_ip6.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+static char ntop_buf[INET6_ADDRSTRLEN];
+
+static const char *ip6nh[] = {
+ "hop by hop",
+ "ICMP",
+ "IGMP",
+ "#3",
+ "IP",
+ "#5",
+ "TCP",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "UDP",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "IDP",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "TP",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "IP6",
+ "#42",
+ "routing",
+ "fragment",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "ESP",
+ "AH",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "ICMP6",
+ "no next header",
+ "destination option",
+ "#61",
+ "mobility",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "ISOIP",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "OSPF",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "Ethernet",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "PIM",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "#128",
+ "#129",
+ "#130",
+ "#131",
+ "SCTP",
+ "#133",
+ "#134",
+ "#135",
+ "UDPLite",
+ "#137",
+ "#138",
+ "#139",
+ "#140",
+ "#141",
+ "#142",
+ "#143",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+static const char *srcrule_str[] = {
+ "first candidate",
+ "same address",
+ "appropriate scope",
+ "deprecated address",
+ "home address",
+ "outgoing interface",
+ "matching label",
+ "public/temporary address",
+ "alive interface",
+ "better virtual status",
+ "preferred source",
+ "rule #11",
+ "rule #12",
+ "rule #13",
+ "longest match",
+ "rule #15",
+};
+
+/*
+ * Dump IP6 statistics structure.
+ */
+void
+ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ip6stat ip6stat;
+ int first, i;
+
+ if (fetch_stats("net.inet6.ip6.stats", off, &ip6stat,
+ sizeof(ip6stat), kread_counters) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (ip6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
+#define p1a(f, m) if (ip6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ip6stat.f)
+
+ p(ip6s_total, "\t{:received-packets/%ju} "
+ "{N:/total packet%s received}\n");
+ p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
+ "{N:/with size smaller than minimum}\n");
+ p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
+ "{N:/with data size < data length}\n");
+ p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
+ "{N:/with bad options}\n");
+ p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
+ "{N:/with incorrect version number}\n");
+ p(ip6s_fragments, "\t{:received-fragments/%ju} "
+ "{N:/fragment%s received}\n");
+ p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
+ "{N:/fragment%s dropped (dup or out of space)}\n");
+ p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
+ "{N:/fragment%s dropped after timeout}\n");
+ p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
+ "{N:/fragment%s that exceeded limit}\n");
+ p(ip6s_atomicfrags, "\t{:atomic-fragments/%ju} "
+ "{N:/atomic fragment%s}\n");
+ p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
+ "{N:/packet%s reassembled ok}\n");
+ p(ip6s_delivered, "\t{:received-local-packets/%ju} "
+ "{N:/packet%s for this host}\n");
+ p(ip6s_forward, "\t{:forwarded-packets/%ju} "
+ "{N:/packet%s forwarded}\n");
+ p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
+ "{N:/packet%s not forwardable}\n");
+ p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
+ "{N:/redirect%s sent}\n");
+ p(ip6s_localout, "\t{:sent-packets/%ju} "
+ "{N:/packet%s sent from this host}\n");
+ p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
+ "{N:/packet%s sent with fabricated ip header}\n");
+ p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
+ "{N:/output packet%s dropped due to no bufs, etc.}\n");
+ p(ip6s_noroute, "\t{:discard-no-route/%ju} "
+ "{N:/output packet%s discarded due to no route}\n");
+ p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
+ "{N:/output datagram%s fragmented}\n");
+ p(ip6s_ofragments, "\t{:fragments-created/%ju} "
+ "{N:/fragment%s created}\n");
+ p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
+ "{N:/datagram%s that can't be fragmented}\n");
+ p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
+ "{N:/packet%s that violated scope rules}\n");
+ p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
+ "{N:/multicast packet%s which we don't join}\n");
+ for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
+ if (ip6stat.ip6s_nxthist[i] != 0) {
+ if (first) {
+ xo_emit("\t{T:Input histogram}:\n");
+ xo_open_list("input-histogram");
+ first = 0;
+ }
+ xo_open_instance("input-histogram");
+ xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
+ (uintmax_t)ip6stat.ip6s_nxthist[i]);
+ xo_close_instance("input-histogram");
+ }
+ if (!first)
+ xo_close_list("input-histogram");
+
+ xo_open_container("mbuf-statistics");
+ xo_emit("\t{T:Mbuf statistics}:\n");
+ xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
+ (uintmax_t)ip6stat.ip6s_m1);
+ for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
+ char ifbuf[IFNAMSIZ];
+ if (ip6stat.ip6s_m2m[i] != 0) {
+ if (first) {
+ xo_emit("\t\t{N:two or more mbuf}:\n");
+ xo_open_list("mbuf-data");
+ first = 0;
+ }
+ xo_open_instance("mbuf-data");
+ xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
+ if_indextoname(i, ifbuf),
+ (uintmax_t)ip6stat.ip6s_m2m[i]);
+ xo_close_instance("mbuf-data");
+ }
+ }
+ if (!first)
+ xo_close_list("mbuf-data");
+ xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
+ (uintmax_t)ip6stat.ip6s_mext1);
+ xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
+ "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
+ xo_close_container("mbuf-statistics");
+
+ p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
+ "{N:/packet%s whose headers are not contiguous}\n");
+ p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
+ "{N:/tunneling packet%s that can't find gif}\n");
+ p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
+ "{N:/packet%s discarded because of too many headers}\n");
+
+ /* for debugging source address selection */
+#define PRINT_SCOPESTAT(s,i) do {\
+ switch(i) { /* XXX hardcoding in each case */\
+ case 1:\
+ p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
+ "{N:/interface-local%s}\n"); \
+ break;\
+ case 2:\
+ p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
+ "{N:/link-local%s}\n"); \
+ break;\
+ case 5:\
+ p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
+ "{N:/site-local%s}\n");\
+ break;\
+ case 14:\
+ p(s,"\t\t{ke:name/globals}{:count/%ju} " \
+ "{N:/global%s}\n");\
+ break;\
+ default:\
+ xo_emit("\t\t{qke:name/%#x}{:count/%ju} " \
+ "{N:/addresses scope=%#x}\n",\
+ i, (uintmax_t)ip6stat.s, i); \
+ }\
+ } while (0);
+
+ xo_open_container("source-address-selection");
+ p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
+ "{N:/failure%s of source address selection}\n");
+
+ for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
+ if (ip6stat.ip6s_sources_sameif[i]) {
+ if (first) {
+ xo_open_list("outgoing-interface");
+ xo_emit("\tsource addresses on an outgoing "
+ "I/F\n");
+ first = 0;
+ }
+ xo_open_instance("outgoing-interface");
+ PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
+ xo_close_instance("outgoing-interface");
+ }
+ }
+ if (!first)
+ xo_close_list("outgoing-interface");
+
+ for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
+ if (ip6stat.ip6s_sources_otherif[i]) {
+ if (first) {
+ xo_open_list("non-outgoing-interface");
+ xo_emit("\tsource addresses on a non-outgoing "
+ "I/F\n");
+ first = 0;
+ }
+ xo_open_instance("non-outgoing-interface");
+ PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
+ xo_close_instance("non-outgoing-interface");
+ }
+ }
+ if (!first)
+ xo_close_list("non-outgoing-interface");
+
+ for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
+ if (ip6stat.ip6s_sources_samescope[i]) {
+ if (first) {
+ xo_open_list("same-source");
+ xo_emit("\tsource addresses of same scope\n");
+ first = 0;
+ }
+ xo_open_instance("same-source");
+ PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
+ xo_close_instance("same-source");
+ }
+ }
+ if (!first)
+ xo_close_list("same-source");
+
+ for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
+ if (ip6stat.ip6s_sources_otherscope[i]) {
+ if (first) {
+ xo_open_list("different-scope");
+ xo_emit("\tsource addresses of a different "
+ "scope\n");
+ first = 0;
+ }
+ xo_open_instance("different-scope");
+ PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
+ xo_close_instance("different-scope");
+ }
+ }
+ if (!first)
+ xo_close_list("different-scope");
+
+ for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
+ if (ip6stat.ip6s_sources_deprecated[i]) {
+ if (first) {
+ xo_open_list("deprecated-source");
+ xo_emit("\tdeprecated source addresses\n");
+ first = 0;
+ }
+ xo_open_instance("deprecated-source");
+ PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
+ xo_close_instance("deprecated-source");
+ }
+ }
+ if (!first)
+ xo_close_list("deprecated-source");
+
+ for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
+ if (ip6stat.ip6s_sources_rule[i]) {
+ if (first) {
+ xo_open_list("rules-applied");
+ xo_emit("\t{T:Source addresses selection "
+ "rule applied}:\n");
+ first = 0;
+ }
+ xo_open_instance("rules-applied");
+ xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
+ srcrule_str[i],
+ (uintmax_t)ip6stat.ip6s_sources_rule[i],
+ srcrule_str[i]);
+ xo_close_instance("rules-applied");
+ }
+ }
+ if (!first)
+ xo_close_list("rules-applied");
+
+ xo_close_container("source-address-selection");
+
+#undef p
+#undef p1a
+ xo_close_container(name);
+}
+
+/*
+ * Dump IPv6 per-interface statistics based on RFC 2465.
+ */
+void
+ip6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+
+#define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, \
+ plural(ifr.ifr_ifru.ifru_stat.f))
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ xo_warn("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
+ if (errno != EPFNOSUPPORT)
+ xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
+ goto end;
+ }
+
+ xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
+
+ xo_open_instance("ip6-interface-statistics");
+ xo_emit("{ke:name/%s}", ifr.ifr_name);
+
+ p(ifs6_in_receive, "\t{:received-packets/%ju} "
+ "{N:/total input datagram%s}\n");
+ p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
+ "{N:/datagram%s with invalid header received}\n");
+ p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
+ "{N:/datagram%s exceeded MTU received}\n");
+ p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
+ "{N:/datagram%s with no route received}\n");
+ p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
+ "{N:/datagram%s with invalid dst received}\n");
+ p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
+ "{N:/datagram%s with unknown proto received}\n");
+ p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
+ "{N:/truncated datagram%s received}\n");
+ p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
+ "{N:/input datagram%s discarded}\n");
+ p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
+ "{N:/datagram%s delivered to an upper layer protocol}\n");
+ p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
+ "{N:/datagram%s forwarded to this interface}\n");
+ p(ifs6_out_request, "\t{:sent-packets/%ju} "
+ "{N:/datagram%s sent from an upper layer protocol}\n");
+ p(ifs6_out_discard, "\t{:discard-packets/%ju} "
+ "{N:/total discarded output datagram%s}\n");
+ p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
+ "{N:/output datagram%s fragmented}\n");
+ p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
+ "{N:/output datagram%s failed on fragment}\n");
+ p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
+ "{N:/output datagram%s succeeded on fragment}\n");
+ p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
+ "{N:/incoming datagram%s fragmented}\n");
+ p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
+ "{N:/datagram%s reassembled}\n");
+ p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
+ "{N:/datagram%s failed on reassembly}\n");
+ p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
+ "{N:/multicast datagram%s received}\n");
+ p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
+ "{N:/multicast datagram%s sent}\n");
+
+ end:
+ xo_close_instance("ip6-interface-statistics");
+ close(s);
+
+#undef p
+}
+
+static const char *icmp6names[] = {
+ "#0",
+ "unreach",
+ "packet too big",
+ "time exceed",
+ "parameter problem",
+ "#5",
+ "#6",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "#17",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "#41",
+ "#42",
+ "#43",
+ "#44",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "#50",
+ "#51",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "#58",
+ "#59",
+ "#60",
+ "#61",
+ "#62",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "#80",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "#89",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "#97",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "#103",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "echo",
+ "echo reply",
+ "multicast listener query",
+ "MLDv1 listener report",
+ "MLDv1 listener done",
+ "router solicitation",
+ "router advertisement",
+ "neighbor solicitation",
+ "neighbor advertisement",
+ "redirect",
+ "router renumbering",
+ "node information request",
+ "node information reply",
+ "inverse neighbor solicitation",
+ "inverse neighbor advertisement",
+ "MLDv2 listener report",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+/*
+ * Dump ICMP6 statistics.
+ */
+void
+icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct icmp6stat icmp6stat;
+ int i, first;
+
+ if (fetch_stats("net.inet6.icmp6.stats", off, &icmp6stat,
+ sizeof(icmp6stat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+
+#define p(f, m) if (icmp6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
+#define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)icmp6stat.f)
+
+ p(icp6s_error, "\t{:icmp6-calls/%ju} "
+ "{N:/call%s to icmp6_error}\n");
+ p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
+ "{N:/error%s not generated in response to an icmp6 message}\n");
+ p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
+ "{N:/error%s not generated because of rate limitation}\n");
+#define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (icmp6stat.icp6s_outhist[i] != 0) {
+ if (first) {
+ xo_open_list("output-histogram");
+ xo_emit("\t{T:Output histogram}:\n");
+ first = 0;
+ }
+ xo_open_instance("output-histogram");
+ xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
+ icmp6names[i],
+ (uintmax_t)icmp6stat.icp6s_outhist[i]);
+ xo_close_instance("output-histogram");
+ }
+ if (!first)
+ xo_close_list("output-histogram");
+#undef NELEM
+
+ p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
+ "{N:/message%s with bad code fields}\n");
+ p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
+ "{N:/message%s < minimum length}\n");
+ p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/bad checksum%s}\n");
+ p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
+ "{N:/message%s with bad length}\n");
+ p(icp6s_dropped, "\t{:dropped-no-entry/%ju} "
+ "{N:/total packet%s dropped due to failed NDP resolution}\n");
+#define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (icmp6stat.icp6s_inhist[i] != 0) {
+ if (first) {
+ xo_open_list("input-histogram");
+ xo_emit("\t{T:Input histogram}:\n");
+ first = 0;
+ }
+ xo_open_instance("input-histogram");
+ xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
+ icmp6names[i],
+ (uintmax_t)icmp6stat.icp6s_inhist[i]);
+ xo_close_instance("input-histogram");
+ }
+ if (!first)
+ xo_close_list("input-histogram");
+#undef NELEM
+ xo_emit("\t{T:Histogram of error messages to be generated}:\n");
+ xo_open_container("errors");
+ p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
+ "{N:/no route}\n");
+ p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
+ "{N:/administratively prohibited}\n");
+ p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
+ "{N:/beyond scope}\n");
+ p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
+ "{N:/address unreachable}\n");
+ p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
+ "{N:/port unreachable}\n");
+ p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
+ "{N:/packet too big}\n");
+ p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
+ "{N:/time exceed transit}\n");
+ p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
+ "{N:/time exceed reassembly}\n");
+ p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
+ "{N:/erroneous header field}\n");
+ p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
+ "{N:/unrecognized next header}\n");
+ p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
+ "{N:/unrecognized option}\n");
+ p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
+ "{N:/redirect}\n");
+ p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
+
+ p(icp6s_reflect, "\t{:reflect/%ju} "
+ "{N:/message response%s generated}\n");
+ p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
+ "{N:/message%s with too many ND options}\n");
+ p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
+ "{N:/message%s with bad ND options}\n");
+ p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
+ "{N:/bad neighbor solicitation message%s}\n");
+ p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
+ "{N:/bad neighbor advertisement message%s}\n");
+ p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
+ "{N:/bad router solicitation message%s}\n");
+ p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
+ "{N:/bad router advertisement message%s}\n");
+ p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
+ "{N:/bad redirect message%s}\n");
+ p(icp6s_overflowdefrtr, "\t{:default-routers-overflows/%ju} "
+ "{N:/default routers overflow%s}\n");
+ p(icp6s_overflowprfx, "\t{:prefixes-overflows/%ju} "
+ "{N:/prefix overflow%s}\n");
+ p(icp6s_overflownndp, "\t{:neighbour-entries-overflows/%ju} "
+ "{N:/neighbour entries overflow%s}\n");
+ p(icp6s_overflowredirect, "\t{:redirect-overflows/%ju} "
+ "{N:/redirect overflow%s}\n");
+ p(icp6s_invlhlim, "\t{:dropped-invalid-hop-limit/%ju} "
+ "{N:/message%s with invalid hop limit}\n");
+ xo_close_container("errors");
+ p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
+#undef p
+#undef p_5
+ xo_close_container(name);
+}
+
+/*
+ * Dump ICMPv6 per-interface statistics based on RFC 2466.
+ */
+void
+icmp6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+
+#define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
+ plural(ifr.ifr_ifru.ifru_icmp6stat.f))
+#define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
+ pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ xo_warn("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
+ if (errno != EPFNOSUPPORT)
+ xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
+ goto end;
+ }
+
+ xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
+
+ xo_open_instance("icmp6-interface-statistics");
+ xo_emit("{ke:name/%s}", ifr.ifr_name);
+ p(ifs6_in_msg, "\t{:received-packets/%ju} "
+ "{N:/total input message%s}\n");
+ p(ifs6_in_error, "\t{:received-errors/%ju} "
+ "{N:/total input error message%s}\n");
+ p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
+ "{N:/input destination unreachable error%s}\n");
+ p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
+ "{N:/input administratively prohibited error%s}\n");
+ p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
+ "{N:/input time exceeded error%s}\n");
+ p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
+ "{N:/input parameter problem error%s}\n");
+ p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
+ "{N:/input packet too big error%s}\n");
+ p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
+ "{N:/input echo request%s}\n");
+ p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
+ "{N:/input echo repl%s}\n");
+ p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
+ "{N:/input router solicitation%s}\n");
+ p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
+ "{N:/input router advertisement%s}\n");
+ p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
+ "{N:/input neighbor solicitation%s}\n");
+ p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
+ "{N:/input neighbor advertisement%s}\n");
+ p(ifs6_in_redirect, "\t{received-redirects/%ju} "
+ "{N:/input redirect%s}\n");
+ p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
+ "{N:/input MLD quer%s}\n");
+ p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
+ "{N:/input MLD report%s}\n");
+ p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
+ "{N:/input MLD done%s}\n");
+
+ p(ifs6_out_msg, "\t{:sent-packets/%ju} "
+ "{N:/total output message%s}\n");
+ p(ifs6_out_error, "\t{:sent-errors/%ju} "
+ "{N:/total output error message%s}\n");
+ p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
+ "{N:/output destination unreachable error%s}\n");
+ p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
+ "{N:/output administratively prohibited error%s}\n");
+ p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
+ "{N:/output time exceeded error%s}\n");
+ p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
+ "{N:/output parameter problem error%s}\n");
+ p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
+ "{N:/output packet too big error%s}\n");
+ p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
+ "{N:/output echo request%s}\n");
+ p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
+ "{N:/output echo repl%s}\n");
+ p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
+ "{N:/output router solicitation%s}\n");
+ p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
+ "{N:/output router advertisement%s}\n");
+ p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
+ "{N:/output neighbor solicitation%s}\n");
+ p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
+ "{N:/output neighbor advertisement%s}\n");
+ p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
+ "{N:/output redirect%s}\n");
+ p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
+ "{N:/output MLD quer%s}\n");
+ p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
+ "{N:/output MLD report%s}\n");
+ p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
+ "{N:/output MLD done%s}\n");
+
+end:
+ xo_close_instance("icmp6-interface-statistics");
+ close(s);
+#undef p
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct pim6stat pim6stat;
+
+ if (fetch_stats("net.inet6.pim.stats", off, &pim6stat,
+ sizeof(pim6stat), kread) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+
+#define p(f, m) if (pim6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
+
+ p(pim6s_rcv_total, "\t{:received-packets/%ju} "
+ "{N:/message%s received}\n");
+ p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
+ "{N:/message%s received with too few bytes}\n");
+ p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/message%s received with bad checksum}\n");
+ p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
+ "{N:/message%s received with bad version}\n");
+ p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
+ "{N:/register%s received}\n");
+ p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
+ "{N:/bad register%s received}\n");
+ p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
+ "{N:/register%s sent}\n");
+#undef p
+ xo_close_container(name);
+}
+
+/*
+ * Dump raw ip6 statistics structure.
+ */
+void
+rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct rip6stat rip6stat;
+ u_quad_t delivered;
+
+ if (fetch_stats("net.inet6.ip6.rip6stats", off, &rip6stat,
+ sizeof(rip6stat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+
+#define p(f, m) if (rip6stat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
+
+ p(rip6s_ipackets, "\t{:received-packets/%ju} "
+ "{N:/message%s received}\n");
+ p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
+ "{N:/checksum calculation%s on inbound}\n");
+ p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
+ "{N:/message%s with bad checksum}\n");
+ p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
+ "{N:/message%s dropped due to no socket}\n");
+ p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
+ "{N:/multicast message%s dropped due to no socket}\n");
+ p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
+ "{N:/message%s dropped due to full socket buffers}\n");
+ delivered = rip6stat.rip6s_ipackets -
+ rip6stat.rip6s_badsum -
+ rip6stat.rip6s_nosock -
+ rip6stat.rip6s_nosockmcast -
+ rip6stat.rip6s_fullsock;
+ if (delivered || sflag <= 1)
+ xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
+ (uintmax_t)delivered);
+ p(rip6s_opackets, "\t{:sent-packets/%ju} "
+ "{N:/datagram%s output}\n");
+#undef p
+ xo_close_container(name);
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * Take numeric_addr and numeric_port into consideration.
+ */
+#define GETSERVBYPORT6(port, proto, ret)\
+{\
+ if (strcmp((proto), "tcp6") == 0)\
+ (ret) = getservbyport((int)(port), "tcp");\
+ else if (strcmp((proto), "udp6") == 0)\
+ (ret) = getservbyport((int)(port), "udp");\
+ else\
+ (ret) = getservbyport((int)(port), (proto));\
+};
+
+void
+inet6print(const char *container, struct in6_addr *in6, int port,
+ const char *proto, int numeric)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+ size_t alen, plen;
+
+ if (container)
+ xo_open_container(container);
+
+ snprintf(line, sizeof(line), "%.*s.",
+ Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
+ inet6name(in6));
+ alen = strlen(line);
+ cp = line + alen;
+ if (!numeric && port)
+ GETSERVBYPORT6(port, proto, sp);
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - alen,
+ "%.15s", sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - alen,
+ "%d", ntohs((u_short)port));
+ width = Wflag ? 45 : Aflag ? 18 : 22;
+
+ xo_emit("{d:target/%-*.*s} ", width, width, line);
+
+ plen = strlen(cp);
+ alen--;
+ xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
+ plen, cp);
+
+ if (container)
+ xo_close_container(container);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+
+char *
+inet6name(struct in6_addr *ia6)
+{
+ struct sockaddr_in6 sin6;
+ char hbuf[NI_MAXHOST], *cp;
+ static char line[NI_MAXHOST];
+ static char domain[MAXHOSTNAMELEN];
+ static int first = 1;
+ int flags, error;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
+ strcpy(line, "*");
+ return (line);
+ }
+ if (first && !numeric_addr) {
+ first = 0;
+ if (gethostname(domain, sizeof(domain)) == 0 &&
+ (cp = strchr(domain, '.')))
+ strlcpy(domain, cp + 1, sizeof(domain));
+ else
+ domain[0] = 0;
+ }
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6.sin6_addr, ia6, sizeof(*ia6));
+ sin6.sin6_family = AF_INET6;
+ /* XXX: ia6.s6_addr[2] can contain scopeid. */
+ in6_fillscopeid(&sin6);
+ flags = (numeric_addr) ? NI_NUMERICHOST : 0;
+ error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
+ sizeof(hbuf), NULL, 0, flags);
+ if (error == 0) {
+ if ((flags & NI_NUMERICHOST) == 0 &&
+ (cp = strchr(hbuf, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ strlcpy(line, hbuf, sizeof(line));
+ } else {
+ /* XXX: this should not happen. */
+ snprintf(line, sizeof(line), "%s",
+ inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
+ sizeof(ntop_buf)));
+ }
+ return (line);
+}
+#endif /*INET6*/
diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c
new file mode 100644
index 000000000000..cac42b81325f
--- /dev/null
+++ b/usr.bin/netstat/ipsec.c
@@ -0,0 +1,433 @@
+/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/*-
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+/*-
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ah_var.h>
+#include <netipsec/esp_var.h>
+#include <netipsec/ipcomp_var.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+struct val2str {
+ int val;
+ const char *str;
+};
+
+static struct val2str ipsec_ahnames[] = {
+ { SADB_AALG_NONE, "none", },
+ { SADB_AALG_SHA1HMAC, "hmac-sha1", },
+ { SADB_X_AALG_NULL, "null", },
+ { SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
+ { SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
+ { SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
+ { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+ { SADB_X_AALG_TCP_MD5, "tcp-md5", },
+ { SADB_X_AALG_AES128GMAC, "aes-gmac-128", },
+ { SADB_X_AALG_AES192GMAC, "aes-gmac-192", },
+ { SADB_X_AALG_AES256GMAC, "aes-gmac-256", },
+ { -1, NULL },
+};
+
+static struct val2str ipsec_espnames[] = {
+ { SADB_EALG_NONE, "none", },
+ { SADB_EALG_NULL, "null", },
+ { SADB_X_EALG_AESCBC, "aes-cbc", },
+ { SADB_X_EALG_AESCTR, "aes-ctr", },
+ { SADB_X_EALG_AESGCM16, "aes-gcm-16", },
+ { SADB_X_EALG_AESGMAC, "aes-gmac", },
+ { -1, NULL },
+};
+
+static struct val2str ipsec_compnames[] = {
+ { SADB_X_CALG_NONE, "none", },
+ { SADB_X_CALG_OUI, "oui", },
+ { SADB_X_CALG_DEFLATE, "deflate", },
+ { SADB_X_CALG_LZS, "lzs", },
+ { -1, NULL },
+};
+
+static void
+print_ipsecstats(const char *tag, const struct ipsecstat *ipsecstat)
+{
+ xo_open_container(tag);
+
+#define p(f, m) if (ipsecstat->f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f))
+#define p2(f, m) if (ipsecstat->f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f))
+
+ p(ips_in_polvio, "\t{:dropped-policy-violation/%ju} "
+ "{N:/inbound packet%s violated process security policy}\n");
+ p(ips_in_nomem, "\t{:dropped-no-memory/%ju} "
+ "{N:/inbound packet%s failed due to insufficient memory}\n");
+ p(ips_in_inval, "\t{:dropped-invalid/%ju} "
+ "{N:/invalid inbound packet%s}\n");
+ p(ips_out_polvio, "\t{:discarded-policy-violation/%ju} "
+ "{N:/outbound packet%s violated process security policy}\n");
+ p(ips_out_nosa, "\t{:discarded-no-sa/%ju} "
+ "{N:/outbound packet%s with no SA available}\n");
+ p(ips_out_nomem, "\t{:discarded-no-memory/%ju} "
+ "{N:/outbound packet%s failed due to insufficient memory}\n");
+ p(ips_out_noroute, "\t{:discarded-no-route/%ju} "
+ "{N:/outbound packet%s with no route available}\n");
+ p(ips_out_inval, "\t{:discarded-invalid/%ju} "
+ "{N:/invalid outbound packet%s}\n");
+ p(ips_out_bundlesa, "\t{:send-bundled-sa/%ju} "
+ "{N:/outbound packet%s with bundled SAs}\n");
+ p(ips_spdcache_hits, "\t{:spdcache-hits/%ju} "
+ "{N:/spd cache hit%s}\n");
+ p2(ips_spdcache_misses, "\t{:spdcache-misses/%ju} "
+ "{N:/spd cache miss%s}\n");
+ p(ips_clcopied, "\t{:clusters-copied-during-clone/%ju} "
+ "{N:/cluster%s copied during clone}\n");
+ p(ips_mbinserted, "\t{:mbufs-inserted/%ju} "
+ "{N:/mbuf%s inserted during makespace}\n");
+#undef p2
+#undef p
+ xo_close_container(tag);
+}
+
+void
+ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ipsecstat ipsecstat;
+ const char *tag;
+
+ if (strcmp(name, "ipsec6") == 0) {
+ if (fetch_stats("net.inet6.ipsec6.ipsecstats", off,&ipsecstat,
+ sizeof(ipsecstat), kread_counters) != 0)
+ return;
+ tag = "ipsec6-statistics";
+ } else {
+ if (fetch_stats("net.inet.ipsec.ipsecstats", off, &ipsecstat,
+ sizeof(ipsecstat), kread_counters) != 0)
+ return;
+ tag = "ipsec-statistics";
+ }
+
+ xo_emit("{T:/%s}:\n", name);
+
+ print_ipsecstats(tag, &ipsecstat);
+}
+
+
+static void print_ahstats(const struct ahstat *ahstat);
+static void print_espstats(const struct espstat *espstat);
+static void print_ipcompstats(const struct ipcompstat *ipcompstat);
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist_new(const uint64_t *hist, size_t histmax,
+ const struct val2str *name, const char *title, const char *cname)
+{
+ int first;
+ size_t proto;
+ const struct val2str *p;
+
+ first = 1;
+ for (proto = 0; proto < histmax; proto++) {
+ if (hist[proto] <= 0)
+ continue;
+ if (first) {
+ xo_open_list(cname);
+ xo_emit("\t{T:/%s histogram}:\n", title);
+ first = 0;
+ }
+ xo_open_instance(cname);
+ for (p = name; p && p->str; p++) {
+ if (p->val == (int)proto)
+ break;
+ }
+ if (p && p->str) {
+ xo_emit("\t\t{k:name}: {:count/%ju}\n", p->str,
+ (uintmax_t)hist[proto]);
+ } else {
+ xo_emit("\t\t#{k:name/%lu}: {:count/%ju}\n",
+ (unsigned long)proto, (uintmax_t)hist[proto]);
+ }
+ xo_close_instance(cname);
+ }
+ if (!first)
+ xo_close_list(cname);
+}
+
+static void
+print_ahstats(const struct ahstat *ahstat)
+{
+ xo_open_container("ah-statictics");
+
+#define p(f, n, m) if (ahstat->f || sflag <= 1) \
+ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \
+ (uintmax_t)ahstat->f, plural(ahstat->f))
+#define hist(f, n, t, c) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c))
+
+ p(ahs_hdrops, "dropped-short-header",
+ "packet%s shorter than header shows");
+ p(ahs_nopf, "dropped-bad-protocol",
+ "packet%s dropped; protocol family not supported");
+ p(ahs_notdb, "dropped-no-tdb", "packet%s dropped; no TDB");
+ p(ahs_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR");
+ p(ahs_qfull, "dropped-queue-full", "packet%s dropped; queue full");
+ p(ahs_noxform, "dropped-no-transform",
+ "packet%s dropped; no transform");
+ p(ahs_wrap, "replay-counter-wraps", "replay counter wrap%s");
+ p(ahs_badauth, "dropped-bad-auth",
+ "packet%s dropped; bad authentication detected");
+ p(ahs_badauthl, "dropped-bad-auth-level",
+ "packet%s dropped; bad authentication length");
+ p(ahs_replay, "possile-replay-detected",
+ "possible replay packet%s detected");
+ p(ahs_input, "received-packets", "packet%s in");
+ p(ahs_output, "send-packets", "packet%s out");
+ p(ahs_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB");
+ p(ahs_ibytes, "received-bytes", "byte%s in");
+ p(ahs_obytes, "send-bytes", "byte%s out");
+ p(ahs_toobig, "dropped-too-large",
+ "packet%s dropped; larger than IP_MAXPACKET");
+ p(ahs_pdrops, "dropped-policy-violation",
+ "packet%s blocked due to policy");
+ p(ahs_crypto, "crypto-failures", "crypto processing failure%s");
+ p(ahs_tunnel, "tunnel-failures", "tunnel sanity check failure%s");
+ hist(ahstat->ahs_hist, ipsec_ahnames,
+ "AH output", "ah-output-histogram");
+
+#undef p
+#undef hist
+ xo_close_container("ah-statictics");
+}
+
+void
+ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+ struct ahstat ahstat;
+
+ if (fetch_stats("net.inet.ah.stats", off, &ahstat,
+ sizeof(ahstat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+
+ print_ahstats(&ahstat);
+}
+
+static void
+print_espstats(const struct espstat *espstat)
+{
+ xo_open_container("esp-statictics");
+#define p(f, n, m) if (espstat->f || sflag <= 1) \
+ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \
+ (uintmax_t)espstat->f, plural(espstat->f))
+#define hist(f, n, t, c) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c));
+
+ p(esps_hdrops, "dropped-short-header",
+ "packet%s shorter than header shows");
+ p(esps_nopf, "dropped-bad-protocol",
+ "packet%s dropped; protocol family not supported");
+ p(esps_notdb, "dropped-no-tdb", "packet%s dropped; no TDB");
+ p(esps_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR");
+ p(esps_qfull, "dropped-queue-full", "packet%s dropped; queue full");
+ p(esps_noxform, "dropped-no-transform",
+ "packet%s dropped; no transform");
+ p(esps_badilen, "dropped-bad-length", "packet%s dropped; bad ilen");
+ p(esps_wrap, "replay-counter-wraps", "replay counter wrap%s");
+ p(esps_badenc, "dropped-bad-crypto",
+ "packet%s dropped; bad encryption detected");
+ p(esps_badauth, "dropped-bad-auth",
+ "packet%s dropped; bad authentication detected");
+ p(esps_replay, "possible-replay-detected",
+ "possible replay packet%s detected");
+ p(esps_input, "received-packets", "packet%s in");
+ p(esps_output, "sent-packets", "packet%s out");
+ p(esps_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB");
+ p(esps_ibytes, "receive-bytes", "byte%s in");
+ p(esps_obytes, "sent-bytes", "byte%s out");
+ p(esps_toobig, "dropped-too-large",
+ "packet%s dropped; larger than IP_MAXPACKET");
+ p(esps_pdrops, "dropped-policy-violation",
+ "packet%s blocked due to policy");
+ p(esps_crypto, "crypto-failures", "crypto processing failure%s");
+ p(esps_tunnel, "tunnel-failures", "tunnel sanity check failure%s");
+ hist(espstat->esps_hist, ipsec_espnames,
+ "ESP output", "esp-output-histogram");
+
+#undef p
+#undef hist
+ xo_close_container("esp-statictics");
+}
+
+void
+esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+ struct espstat espstat;
+
+ if (fetch_stats("net.inet.esp.stats", off, &espstat,
+ sizeof(espstat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+
+ print_espstats(&espstat);
+}
+
+static void
+print_ipcompstats(const struct ipcompstat *ipcompstat)
+{
+ xo_open_container("ipcomp-statictics");
+
+#define p(f, n, m) if (ipcompstat->f || sflag <= 1) \
+ xo_emit("\t{:" n "/%ju} {N:/" m "}\n", \
+ (uintmax_t)ipcompstat->f, plural(ipcompstat->f))
+#define hist(f, n, t, c) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t), (c));
+
+ p(ipcomps_hdrops, "dropped-short-header",
+ "packet%s shorter than header shows");
+ p(ipcomps_nopf, "dropped-bad-protocol",
+ "packet%s dropped; protocol family not supported");
+ p(ipcomps_notdb, "dropped-no-tdb", "packet%s dropped; no TDB");
+ p(ipcomps_badkcr, "dropped-bad-kcr", "packet%s dropped; bad KCR");
+ p(ipcomps_qfull, "dropped-queue-full", "packet%s dropped; queue full");
+ p(ipcomps_noxform, "dropped-no-transform",
+ "packet%s dropped; no transform");
+ p(ipcomps_wrap, "replay-counter-wraps", "replay counter wrap%s");
+ p(ipcomps_input, "receive-packets", "packet%s in");
+ p(ipcomps_output, "sent-packets", "packet%s out");
+ p(ipcomps_invalid, "dropped-bad-tdb", "packet%s dropped; invalid TDB");
+ p(ipcomps_ibytes, "received-bytes", "byte%s in");
+ p(ipcomps_obytes, "sent-bytes", "byte%s out");
+ p(ipcomps_toobig, "dropped-too-large",
+ "packet%s dropped; larger than IP_MAXPACKET");
+ p(ipcomps_pdrops, "dropped-policy-violation",
+ "packet%s blocked due to policy");
+ p(ipcomps_crypto, "crypto-failure", "crypto processing failure%s");
+ hist(ipcompstat->ipcomps_hist, ipsec_compnames,
+ "COMP output", "comp-output-histogram");
+ p(ipcomps_threshold, "sent-uncompressed-small-packets",
+ "packet%s sent uncompressed; size < compr. algo. threshold");
+ p(ipcomps_uncompr, "sent-uncompressed-useless-packets",
+ "packet%s sent uncompressed; compression was useless");
+
+#undef p
+#undef hist
+ xo_close_container("ipcomp-statictics");
+}
+
+void
+ipcomp_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
+{
+ struct ipcompstat ipcompstat;
+
+ if (fetch_stats("net.inet.ipcomp.stats", off, &ipcompstat,
+ sizeof(ipcompstat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:/%s}:\n", name);
+
+ print_ipcompstats(&ipcompstat);
+}
+
+#endif /*IPSEC*/
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
new file mode 100644
index 000000000000..4275ea7821df
--- /dev/null
+++ b/usr.bin/netstat/main.c
@@ -0,0 +1,945 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 1993
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#ifdef JAIL
+#include <sys/jail.h>
+#endif
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+
+#ifdef NETGRAPH
+#include <netgraph/ng_socket.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef JAIL
+#include <jail.h>
+#endif
+#include <kvm.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include "netstat.h"
+#include "nl_defs.h"
+#include <libxo/xo.h>
+
+static struct protox {
+ int pr_index; /* index into nlist of cb head */
+ int pr_sindex; /* index into nlist of stat block */
+ u_char pr_wanted; /* 1 if wanted, 0 otherwise */
+ void (*pr_cblocks)(u_long, const char *, int, int);
+ /* control blocks printing routine */
+ void (*pr_stats)(u_long, const char *, int, int);
+ /* statistics printing routine */
+ void (*pr_istats)(char *); /* per/if statistics printing routine */
+ const char *pr_name; /* well-known name */
+ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */
+ int pr_protocol;
+} protox[] = {
+ { -1 , N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { -1 , N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+#ifdef SCTP
+ { -1, N_SCTPSTAT, 1, sctp_protopr,
+ sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
+#endif
+#ifdef SDP
+ { -1, -1, 1, protopr,
+ NULL, NULL, "sdp", 1, IPPROTO_TCP },
+#endif
+ { -1 , -1, 1, protopr,
+ divert_stats, NULL, "divert", 1, 0 },
+ { -1 , N_IPSTAT, 1, protopr,
+ ip_stats, NULL, "ip", 1, IPPROTO_RAW },
+ { -1 , N_ICMPSTAT, 1, protopr,
+ icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
+ { -1 , N_IGMPSTAT, 1, protopr,
+ igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
+#ifdef IPSEC
+ { -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */
+ ipsec_stats, NULL, "ipsec", 1, 0},
+ { -1, N_AHSTAT, 1, NULL,
+ ah_stats, NULL, "ah", 1, 0},
+ { -1, N_ESPSTAT, 1, NULL,
+ esp_stats, NULL, "esp", 1, 0},
+ { -1, N_IPCOMPSTAT, 1, NULL,
+ ipcomp_stats, NULL, "ipcomp", 1, 0},
+#endif
+ { -1 , N_PIMSTAT, 1, protopr,
+ pim_stats, NULL, "pim", 1, IPPROTO_PIM },
+ { -1, N_CARPSTATS, 1, NULL,
+ carp_stats, NULL, "carp", 1, 0 },
+#ifdef PF
+ { -1, N_PFSYNCSTATS, 1, NULL,
+ pfsync_stats, NULL, "pfsync", 1, 0 },
+ { -1, N_PFLOWSTATS, 1, NULL,
+ pflow_stats, NULL, "pflow", 1, 0 },
+#endif
+ { -1, N_ARPSTAT, 1, NULL,
+ arp_stats, NULL, "arp", 1, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+
+#ifdef INET6
+static struct protox ip6protox[] = {
+ { -1 , N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { -1 , N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+ { -1 , N_IP6STAT, 1, protopr,
+ ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
+ { -1 , N_ICMP6STAT, 1, protopr,
+ icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
+#ifdef SDP
+ { -1, -1, 1, protopr,
+ NULL, NULL, "sdp", 1, IPPROTO_TCP },
+#endif
+#ifdef IPSEC
+ { -1, N_IPSEC6STAT, 1, NULL,
+ ipsec_stats, NULL, "ipsec6", 1, 0 },
+#endif
+#ifdef notyet
+ { -1, N_PIM6STAT, 1, NULL,
+ pim6_stats, NULL, "pim6", 1, 0 },
+#endif
+ { -1, N_RIP6STAT, 1, NULL,
+ rip6_stats, NULL, "rip6", 1, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif /*INET6*/
+
+#ifdef IPSEC
+static struct protox pfkeyprotox[] = {
+ { -1, N_PFKEYSTAT, 1, NULL,
+ pfkey_stats, NULL, "pfkey", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif
+
+#ifdef NETGRAPH
+static struct protox netgraphprotox[] = {
+ { N_NGSOCKLIST, -1, 1, netgraphprotopr,
+ NULL, NULL, "ctrl", 0, 0 },
+ { N_NGSOCKLIST, -1, 1, netgraphprotopr,
+ NULL, NULL, "data", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif
+
+static struct protox *protoprotox[] = {
+ protox,
+#ifdef INET6
+ ip6protox,
+#endif
+#ifdef IPSEC
+ pfkeyprotox,
+#endif
+ NULL };
+
+static void printproto(struct protox *, const char *, bool *);
+static void usage(void) __dead2;
+static struct protox *name2protox(const char *);
+static struct protox *knownname(const char *);
+
+static int kresolve_list(struct nlist *_nl);
+
+static kvm_t *kvmd;
+static char *nlistf = NULL, *memf = NULL;
+
+bool Aflag; /* show addresses of protocol control block */
+bool aflag; /* show all sockets (including servers) */
+static bool Bflag; /* show information about bpf consumers */
+bool bflag; /* show i/f total bytes in/out */
+bool cflag; /* show TCP congestion control stack */
+bool Cflag; /* show congestion control algo and vars */
+bool dflag; /* show i/f dropped packets */
+bool gflag; /* show group (multicast) routing or stats */
+bool hflag; /* show counters in human readable format */
+bool iflag; /* show interfaces */
+bool Lflag; /* show size of listen queues */
+bool mflag; /* show memory stats */
+int noutputs = 0; /* how much outputs before we exit */
+u_int numeric_addr = 0; /* show addresses numerically */
+bool numeric_port; /* show ports numerically */
+bool Oflag; /* show nhgrp objects*/
+bool oflag; /* show nexthop objects*/
+bool Pflag; /* show TCP log ID */
+static bool pflag; /* show given protocol */
+static bool Qflag; /* show netisr information */
+bool rflag; /* show routing tables (or routing stats) */
+bool Rflag; /* show flow / RSS statistics */
+int sflag; /* show protocol statistics */
+bool Wflag; /* wide display */
+bool Tflag; /* TCP Information */
+bool xflag; /* extra information, includes all socket buffer info */
+bool zflag; /* zero stats */
+
+int interval; /* repeat interval for i/f stats */
+
+char *interface; /* desired i/f for stats, or NULL for all i/fs */
+int unit; /* unit number for above */
+#ifdef JAIL
+char *jail_name; /* desired jail to operate in */
+#endif
+
+static int af; /* address family */
+int live; /* true if we are examining a live system */
+
+int
+main(int argc, char *argv[])
+{
+ struct protox *tp = NULL; /* for printing cblocks & stats */
+ int ch;
+ int fib = -1;
+ char *endptr;
+ bool first = true;
+#ifdef JAIL
+ int jid;
+#endif
+
+ af = AF_UNSPEC;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(EXIT_FAILURE);
+
+ while ((ch = getopt(argc, argv, "46AaBbCcdF:f:ghI:ij:LlM:mN:nOoPp:Qq:RrSTsuWw:xz"))
+ != -1)
+ switch(ch) {
+ case '4':
+#ifdef INET
+ af = AF_INET;
+#else
+ xo_errx(EX_UNAVAILABLE, "IPv4 support is not compiled in");
+#endif
+ break;
+ case '6':
+#ifdef INET6
+ af = AF_INET6;
+#else
+ xo_errx(EX_UNAVAILABLE, "IPv6 support is not compiled in");
+#endif
+ break;
+ case 'A':
+ Aflag = true;
+ break;
+ case 'a':
+ aflag = true;
+ break;
+ case 'B':
+ Bflag = true;
+ break;
+ case 'b':
+ bflag = true;
+ break;
+ case 'c':
+ cflag = true;
+ break;
+ case 'C':
+ Cflag = true;
+ break;
+ case 'd':
+ dflag = true;
+ break;
+ case 'F':
+ fib = strtol(optarg, &endptr, 0);
+ if (*endptr != '\0' ||
+ (fib == 0 && (errno == EINVAL || errno == ERANGE)))
+ xo_errx(EX_DATAERR, "%s: invalid fib", optarg);
+ break;
+ case 'f':
+ if (strcmp(optarg, "inet") == 0)
+ af = AF_INET;
+#ifdef INET6
+ else if (strcmp(optarg, "inet6") == 0)
+ af = AF_INET6;
+#endif
+#ifdef IPSEC
+ else if (strcmp(optarg, "pfkey") == 0)
+ af = PF_KEY;
+#endif
+ else if (strcmp(optarg, "unix") == 0 ||
+ strcmp(optarg, "local") == 0)
+ af = AF_UNIX;
+#ifdef NETGRAPH
+ else if (strcmp(optarg, "ng") == 0
+ || strcmp(optarg, "netgraph") == 0)
+ af = AF_NETGRAPH;
+#endif
+ else if (strcmp(optarg, "link") == 0)
+ af = AF_LINK;
+ else {
+ xo_errx(EX_DATAERR, "%s: unknown address family",
+ optarg);
+ }
+ break;
+ case 'g':
+ gflag = true;
+ break;
+ case 'h':
+ hflag = true;
+ break;
+ case 'I': {
+ char *cp;
+
+ iflag = true;
+ for (cp = interface = optarg; isalpha(*cp); cp++)
+ continue;
+ unit = atoi(cp);
+ break;
+ }
+ case 'i':
+ iflag = true;
+ break;
+ case 'j':
+#ifdef JAIL
+ if (optarg == NULL)
+ usage();
+ jail_name = optarg;
+#else
+ xo_errx(EX_UNAVAILABLE, "Jail support is not compiled in");
+#endif
+ break;
+ case 'L':
+ Lflag = true;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'm':
+ mflag = true;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ numeric_addr++;
+ numeric_port = true;
+ break;
+ case 'o':
+ oflag = true;
+ break;
+ case 'O':
+ Oflag = true;
+ break;
+ case 'P':
+ Pflag = true;
+ break;
+ case 'p':
+ if ((tp = name2protox(optarg)) == NULL) {
+ xo_errx(EX_DATAERR, "%s: unknown or uninstrumented "
+ "protocol", optarg);
+ }
+ pflag = true;
+ break;
+ case 'Q':
+ Qflag = true;
+ break;
+ case 'q':
+ noutputs = atoi(optarg);
+ if (noutputs != 0)
+ noutputs++;
+ break;
+ case 'r':
+ rflag = true;
+ break;
+ case 'R':
+ Rflag = true;
+ break;
+ case 's':
+ ++sflag;
+ break;
+ case 'S':
+ numeric_addr = 1;
+ break;
+ case 'u':
+ af = AF_UNIX;
+ break;
+ case 'W':
+ case 'l':
+ Wflag = true;
+ break;
+ case 'w':
+ interval = atoi(optarg);
+ iflag = true;
+ break;
+ case 'T':
+ Tflag = true;
+ break;
+ case 'x':
+ xflag = true;
+ break;
+ case 'z':
+ zflag = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ if (isdigit(**argv)) {
+ interval = atoi(*argv);
+ if (interval <= 0)
+ usage();
+ ++argv;
+ iflag = true;
+ }
+ if (*argv) {
+ nlistf = *argv;
+ if (*++argv)
+ memf = *argv;
+ }
+ }
+#endif
+
+#ifdef JAIL
+ if (jail_name != NULL) {
+ jid = jail_getid(jail_name);
+ if (jid == -1)
+ xo_errx(EX_UNAVAILABLE, "Jail not found");
+ if (jail_attach(jid) != 0)
+ xo_errx(EX_UNAVAILABLE, "Cannot attach to jail");
+ }
+#endif
+
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ live = (nlistf == NULL && memf == NULL);
+ if (!live) {
+ if (setgid(getgid()) != 0)
+ xo_err(EX_OSERR, "setgid");
+ /* Load all necessary kvm symbols */
+ kresolve_list(nl);
+ }
+
+ if (xflag && Tflag)
+ xo_errx(EX_USAGE, "-x and -T are incompatible, pick one.");
+
+ if (Bflag) {
+ if (!live)
+ usage();
+ bpf_stats(interface);
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+ if (mflag) {
+ if (!live) {
+ if (kread(0, NULL, 0) == 0)
+ mbpr(kvmd, nl[N_SFSTAT].n_value);
+ } else
+ mbpr(NULL, 0);
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+ if (Qflag) {
+ if (!live) {
+ if (kread(0, NULL, 0) == 0)
+ netisr_stats();
+ } else
+ netisr_stats();
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+#if 0
+ /*
+ * Keep file descriptors open to avoid overhead
+ * of open/close on each call to get* routines.
+ */
+ sethostent(1);
+ setnetent(1);
+#else
+ /*
+ * This does not make sense any more with DNS being default over
+ * the files. Doing a setXXXXent(1) causes a tcp connection to be
+ * used for the queries, which is slower.
+ */
+#endif
+ if (iflag && !sflag) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ intpr(NULL, af);
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+ if (rflag) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ if (sflag)
+ rt_stats();
+ else
+ routepr(fib, af);
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+ if (oflag) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ nhops_print(fib, af);
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+ if (Oflag) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ nhgrp_print(fib, af);
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+
+
+
+ if (gflag) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ if (sflag) {
+ if (af == AF_INET || af == AF_UNSPEC)
+ mrt_stats();
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ mrt6_stats();
+#endif
+ } else {
+ if (af == AF_INET || af == AF_UNSPEC)
+ mroutepr();
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ mroute6pr();
+#endif
+ }
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+
+ if (tp) {
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ printproto(tp, tp->pr_name, &first);
+ if (!first)
+ xo_close_list("socket");
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+ }
+
+ xo_open_container("statistics");
+ xo_set_version(NETSTAT_XO_VERSION);
+ if (af == AF_INET || af == AF_UNSPEC)
+ for (tp = protox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name, &first);
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ for (tp = ip6protox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name, &first);
+#endif /*INET6*/
+#ifdef IPSEC
+ if (af == PF_KEY || af == AF_UNSPEC)
+ for (tp = pfkeyprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name, &first);
+#endif /*IPSEC*/
+#ifdef NETGRAPH
+ if (af == AF_NETGRAPH || af == AF_UNSPEC)
+ for (tp = netgraphprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name, &first);
+#endif /* NETGRAPH */
+ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
+ unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
+ nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value,
+ nl[N_UNP_SPHEAD].n_value, &first);
+
+ if (!first)
+ xo_close_list("socket");
+ xo_close_container("statistics");
+ if (xo_finish() < 0)
+ xo_err(EX_IOERR, "stdout");
+ exit(EX_OK);
+}
+
+static int
+fetch_stats_internal(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn, int zero)
+{
+ int error;
+
+ if (live) {
+ memset(stats, 0, len);
+ if (zero)
+ error = sysctlbyname(sysctlname, NULL, NULL, stats,
+ len);
+ else
+ error = sysctlbyname(sysctlname, stats, &len, NULL, 0);
+ if (error == -1 && errno != ENOENT)
+ xo_warn("sysctl %s", sysctlname);
+ } else {
+ if (off == 0)
+ return (1);
+ error = kreadfn(off, stats, len);
+ }
+ return (error);
+}
+
+int
+fetch_stats(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn)
+{
+
+ return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn,
+ zflag));
+}
+
+int
+fetch_stats_ro(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn)
+{
+
+ return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0));
+}
+
+/*
+ * Print out protocol statistics or control blocks (per sflag).
+ * If the interface was not specifically requested, and the symbol
+ * is not in the namelist, ignore this one.
+ */
+static void
+printproto(struct protox *tp, const char *name, bool *first)
+{
+ void (*pr)(u_long, const char *, int, int);
+ u_long off;
+ bool doingdblocks = false;
+
+ if (sflag) {
+ if (iflag) {
+ if (tp->pr_istats)
+ intpr(tp->pr_istats, af);
+ else if (pflag)
+ xo_message("%s: no per-interface stats routine",
+ tp->pr_name);
+ return;
+ } else {
+ pr = tp->pr_stats;
+ if (!pr) {
+ if (pflag)
+ xo_message("%s: no stats routine",
+ tp->pr_name);
+ return;
+ }
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_sindex < 0) {
+ if (pflag)
+ xo_message("%s: stats routine doesn't "
+ "work on cores", tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_sindex].n_value;
+ }
+ } else {
+ doingdblocks = true;
+ pr = tp->pr_cblocks;
+ if (!pr) {
+ if (pflag)
+ xo_message("%s: no PCB routine", tp->pr_name);
+ return;
+ }
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_index < 0) {
+ if (pflag)
+ xo_message("%s: PCB routine doesn't work on "
+ "cores", tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_index].n_value;
+ }
+ if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
+ af != AF_UNSPEC)) {
+ if (doingdblocks && *first) {
+ xo_open_list("socket");
+ *first = false;
+ }
+
+ (*pr)(off, name, af, tp->pr_protocol);
+ }
+}
+
+static int
+kvmd_init(void)
+{
+ char errbuf[_POSIX2_LINE_MAX];
+
+ if (kvmd != NULL)
+ return (0);
+
+ kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ if (setgid(getgid()) != 0)
+ xo_err(EX_OSERR, "setgid");
+
+ if (kvmd == NULL) {
+ xo_warnx("kvm not available: %s", errbuf);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Resolve symbol list, return 0 on success.
+ */
+static int
+kresolve_list(struct nlist *_nl)
+{
+
+ if ((kvmd == NULL) && (kvmd_init() != 0))
+ return (-1);
+
+ if (_nl[0].n_type != 0)
+ return (0);
+
+ if (kvm_nlist(kvmd, _nl) < 0) {
+ if (nlistf)
+ xo_errx(EX_UNAVAILABLE, "%s: kvm_nlist: %s", nlistf,
+ kvm_geterr(kvmd));
+ else
+ xo_errx(EX_UNAVAILABLE, "kvm_nlist: %s", kvm_geterr(kvmd));
+ }
+
+ return (0);
+}
+
+/*
+ * Wrapper of kvm_dpcpu_setcpu().
+ */
+void
+kset_dpcpu(u_int cpuid)
+{
+
+ if ((kvmd == NULL) && (kvmd_init() != 0))
+ xo_errx(EX_UNAVAILABLE, "%s: kvm is not available", __func__);
+
+ if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0)
+ xo_errx(EX_UNAVAILABLE, "%s: kvm_dpcpu_setcpu(%u): %s", __func__,
+ cpuid, kvm_geterr(kvmd));
+ return;
+}
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(u_long addr, void *buf, size_t size)
+{
+
+ if (kvmd_init() < 0)
+ return (-1);
+
+ if (!buf)
+ return (0);
+ if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
+ xo_warnx("%s", kvm_geterr(kvmd));
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Read single counter(9).
+ */
+uint64_t
+kread_counter(u_long addr)
+{
+
+ if (kvmd_init() < 0)
+ return (-1);
+
+ return (kvm_counter_u64_fetch(kvmd, addr));
+}
+
+/*
+ * Read an array of N counters in kernel memory into array of N uint64_t's.
+ */
+int
+kread_counters(u_long addr, void *buf, size_t size)
+{
+ uint64_t *c;
+ u_long *counters;
+ size_t i, n;
+
+ if (kvmd_init() < 0)
+ return (-1);
+
+ if (size % sizeof(uint64_t) != 0) {
+ xo_warnx("kread_counters: invalid counter set size");
+ return (-1);
+ }
+
+ n = size / sizeof(uint64_t);
+ if ((counters = malloc(n * sizeof(u_long))) == NULL)
+ xo_err(EX_OSERR, "malloc");
+ if (kread(addr, counters, n * sizeof(u_long)) < 0) {
+ free(counters);
+ return (-1);
+ }
+
+ c = buf;
+ for (i = 0; i < n; i++)
+ c[i] = kvm_counter_u64_fetch(kvmd, counters[i]);
+
+ free(counters);
+ return (0);
+}
+
+const char *
+plural(uintmax_t n)
+{
+ return (n != 1 ? "s" : "");
+}
+
+const char *
+plurales(uintmax_t n)
+{
+ return (n != 1 ? "es" : "");
+}
+
+const char *
+pluralies(uintmax_t n)
+{
+ return (n != 1 ? "ies" : "y");
+}
+
+/*
+ * Find the protox for the given "well-known" name.
+ */
+static struct protox *
+knownname(const char *name)
+{
+ struct protox **tpp, *tp;
+
+ for (tpp = protoprotox; *tpp; tpp++)
+ for (tp = *tpp; tp->pr_name; tp++)
+ if (strcmp(tp->pr_name, name) == 0)
+ return (tp);
+ return (NULL);
+}
+
+/*
+ * Find the protox corresponding to name.
+ */
+static struct protox *
+name2protox(const char *name)
+{
+ struct protox *tp;
+ char **alias; /* alias from p->aliases */
+ struct protoent *p;
+
+ /*
+ * Try to find the name in the list of "well-known" names. If that
+ * fails, check if name is an alias for an Internet protocol.
+ */
+ if ((tp = knownname(name)) != NULL)
+ return (tp);
+
+ setprotoent(1); /* make protocol lookup cheaper */
+ while ((p = getprotoent()) != NULL) {
+ /* assert: name not same as p->name */
+ for (alias = p->p_aliases; *alias; alias++)
+ if (strcmp(name, *alias) == 0) {
+ endprotoent();
+ return (knownname(p->p_name));
+ }
+ }
+ endprotoent();
+ return (NULL);
+}
+
+static void
+usage(void)
+{
+ xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: netstat [-j jail] [-46AaCcLnRSTWx] [-f protocol_family | -p protocol]\n"
+" [-M core] [-N system]",
+" netstat [-j jail] -i | -I interface [-46abdhnW] [-f address_family]\n"
+" [-M core] [-N system]",
+" netstat [-j jail] -w wait [-I interface] [-46d] [-M core] [-N system]\n"
+" [-q howmany]",
+" netstat [-j jail] -s [-46sz] [-f protocol_family | -p protocol]\n"
+" [-M core] [-N system]",
+" netstat [-j jail] -i | -I interface -s [-46s]\n"
+" [-f protocol_family | -p protocol] [-M core] [-N system]",
+" netstat [-j jail] -m [-M core] [-N system]",
+" netstat [-j jail] -B [-z] [-I interface]",
+" netstat [-j jail] -r [-46AnW] [-F fibnum] [-f address_family]\n"
+" [-M core] [-N system]",
+" netstat [-j jail] -rs [-s] [-M core] [-N system]",
+" netstat [-j jail] -g [-46W] [-f address_family] [-M core] [-N system]",
+" netstat [-j jail] -gs [-46s] [-f address_family] [-M core] [-N system]",
+" netstat [-j jail] -Q");
+ exit(EX_USAGE);
+}
diff --git a/usr.bin/netstat/mbuf.c b/usr.bin/netstat/mbuf.c
new file mode 100644
index 000000000000..9a43e0115223
--- /dev/null
+++ b/usr.bin/netstat/mbuf.c
@@ -0,0 +1,354 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.
+ * Copyright (c) 2005 Robert N. M. Watson
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sf_buf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <kvm.h>
+#include <memstat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+/*
+ * Print mbuf statistics.
+ */
+void
+mbpr(void *kvmd, u_long mbaddr)
+{
+ struct memory_type_list *mtlp;
+ struct memory_type *mtp;
+ uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
+ uintmax_t mbuf_sleeps;
+ uintmax_t cluster_count, cluster_limit, cluster_free;
+ uintmax_t cluster_failures, cluster_size, cluster_sleeps;
+ uintmax_t packet_count, packet_bytes, packet_free, packet_failures;
+ uintmax_t packet_sleeps;
+ uintmax_t tag_bytes;
+ uintmax_t jumbop_count, jumbop_limit, jumbop_free;
+ uintmax_t jumbop_failures, jumbop_sleeps, jumbop_size;
+ uintmax_t jumbo9_count, jumbo9_limit, jumbo9_free;
+ uintmax_t jumbo9_failures, jumbo9_sleeps, jumbo9_size;
+ uintmax_t jumbo16_count, jumbo16_limit, jumbo16_free;
+ uintmax_t jumbo16_failures, jumbo16_sleeps, jumbo16_size;
+ uintmax_t bytes_inuse, bytes_incache, bytes_total;
+ int nsfbufs, nsfbufspeak, nsfbufsused;
+ struct sfstat sfstat;
+ size_t mlen;
+ int error;
+
+ mtlp = memstat_mtl_alloc();
+ if (mtlp == NULL) {
+ xo_warn("memstat_mtl_alloc");
+ return;
+ }
+
+ /*
+ * Use memstat_*_all() because some mbuf-related memory is in uma(9),
+ * and some malloc(9).
+ */
+ if (live) {
+ if (memstat_sysctl_all(mtlp, 0) < 0) {
+ xo_warnx("memstat_sysctl_all: %s",
+ memstat_strerror(memstat_mtl_geterror(mtlp)));
+ goto out;
+ }
+ } else {
+ if (memstat_kvm_all(mtlp, kvmd) < 0) {
+ error = memstat_mtl_geterror(mtlp);
+ if (error == MEMSTAT_ERROR_KVM)
+ xo_warnx("memstat_kvm_all: %s",
+ kvm_geterr(kvmd));
+ else
+ xo_warnx("memstat_kvm_all: %s",
+ memstat_strerror(error));
+ goto out;
+ }
+ }
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME);
+ goto out;
+ }
+ mbuf_count = memstat_get_count(mtp);
+ mbuf_bytes = memstat_get_bytes(mtp);
+ mbuf_free = memstat_get_free(mtp);
+ mbuf_failures = memstat_get_failures(mtp);
+ mbuf_sleeps = memstat_get_sleeps(mtp);
+ mbuf_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found",
+ MBUF_PACKET_MEM_NAME);
+ goto out;
+ }
+ packet_count = memstat_get_count(mtp);
+ packet_bytes = memstat_get_bytes(mtp);
+ packet_free = memstat_get_free(mtp);
+ packet_sleeps = memstat_get_sleeps(mtp);
+ packet_failures = memstat_get_failures(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found",
+ MBUF_CLUSTER_MEM_NAME);
+ goto out;
+ }
+ cluster_count = memstat_get_count(mtp);
+ cluster_limit = memstat_get_countlimit(mtp);
+ cluster_free = memstat_get_free(mtp);
+ cluster_failures = memstat_get_failures(mtp);
+ cluster_sleeps = memstat_get_sleeps(mtp);
+ cluster_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: malloc type %s not found",
+ MBUF_TAG_MEM_NAME);
+ goto out;
+ }
+ tag_bytes = memstat_get_bytes(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBOP_MEM_NAME);
+ goto out;
+ }
+ jumbop_count = memstat_get_count(mtp);
+ jumbop_limit = memstat_get_countlimit(mtp);
+ jumbop_free = memstat_get_free(mtp);
+ jumbop_failures = memstat_get_failures(mtp);
+ jumbop_sleeps = memstat_get_sleeps(mtp);
+ jumbop_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBO9_MEM_NAME);
+ goto out;
+ }
+ jumbo9_count = memstat_get_count(mtp);
+ jumbo9_limit = memstat_get_countlimit(mtp);
+ jumbo9_free = memstat_get_free(mtp);
+ jumbo9_failures = memstat_get_failures(mtp);
+ jumbo9_sleeps = memstat_get_sleeps(mtp);
+ jumbo9_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME);
+ if (mtp == NULL) {
+ xo_warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBO16_MEM_NAME);
+ goto out;
+ }
+ jumbo16_count = memstat_get_count(mtp);
+ jumbo16_limit = memstat_get_countlimit(mtp);
+ jumbo16_free = memstat_get_free(mtp);
+ jumbo16_failures = memstat_get_failures(mtp);
+ jumbo16_sleeps = memstat_get_sleeps(mtp);
+ jumbo16_size = memstat_get_size(mtp);
+
+ xo_open_container("mbuf-statistics");
+
+ xo_emit("{:mbuf-current/%ju}/{:mbuf-cache/%ju}/{:mbuf-total/%ju} "
+ "{N:mbufs in use (current\\/cache\\/total)}\n",
+ mbuf_count + packet_count, mbuf_free + packet_free,
+ mbuf_count + packet_count + mbuf_free + packet_free);
+
+ xo_emit("{:cluster-current/%ju}/{:cluster-cache/%ju}/"
+ "{:cluster-total/%ju}/{:cluster-max/%ju} "
+ "{N:mbuf clusters in use (current\\/cache\\/total\\/max)}\n",
+ cluster_count - packet_free, cluster_free + packet_free,
+ cluster_count + cluster_free, cluster_limit);
+
+ xo_emit("{:packet-count/%ju}/{:packet-free/%ju} "
+ "{N:mbuf+clusters out of packet secondary zone in use "
+ "(current\\/cache)}\n",
+ packet_count, packet_free);
+
+ xo_emit("{:jumbo-count/%ju}/{:jumbo-cache/%ju}/{:jumbo-total/%ju}/"
+ "{:jumbo-max/%ju} {:jumbo-page-size/%ju}{U:k} {N:(page size)} "
+ "{N:jumbo clusters in use (current\\/cache\\/total\\/max)}\n",
+ jumbop_count, jumbop_free, jumbop_count + jumbop_free,
+ jumbop_limit, jumbop_size / 1024);
+
+ xo_emit("{:jumbo9-count/%ju}/{:jumbo9-cache/%ju}/"
+ "{:jumbo9-total/%ju}/{:jumbo9-max/%ju} "
+ "{N:9k jumbo clusters in use (current\\/cache\\/total\\/max)}\n",
+ jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free,
+ jumbo9_limit);
+
+ xo_emit("{:jumbo16-count/%ju}/{:jumbo16-cache/%ju}/"
+ "{:jumbo16-total/%ju}/{:jumbo16-limit/%ju} "
+ "{N:16k jumbo clusters in use (current\\/cache\\/total\\/max)}\n",
+ jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free,
+ jumbo16_limit);
+
+#if 0
+ xo_emit("{:tag-count/%ju} {N:mbuf tags in use}\n", tag_count);
+#endif
+
+ /*-
+ * Calculate in-use bytes as:
+ * - straight mbuf memory
+ * - mbuf memory in packets
+ * - the clusters attached to packets
+ * - and the rest of the non-packet-attached clusters.
+ * - m_tag memory
+ * This avoids counting the clusters attached to packets in the cache.
+ * This currently excludes sf_buf space.
+ */
+ bytes_inuse =
+ mbuf_bytes + /* straight mbuf memory */
+ packet_bytes + /* mbufs in packets */
+ (packet_count * cluster_size) + /* clusters in packets */
+ /* other clusters */
+ ((cluster_count - packet_count - packet_free) * cluster_size) +
+ tag_bytes +
+ (jumbop_count * jumbop_size) + /* jumbo clusters */
+ (jumbo9_count * jumbo9_size) +
+ (jumbo16_count * jumbo16_size);
+
+ /*
+ * Calculate in-cache bytes as:
+ * - cached straught mbufs
+ * - cached packet mbufs
+ * - cached packet clusters
+ * - cached straight clusters
+ * This currently excludes sf_buf space.
+ */
+ bytes_incache =
+ (mbuf_free * mbuf_size) + /* straight free mbufs */
+ (packet_free * mbuf_size) + /* mbufs in free packets */
+ (packet_free * cluster_size) + /* clusters in free packets */
+ (cluster_free * cluster_size) + /* free clusters */
+ (jumbop_free * jumbop_size) + /* jumbo clusters */
+ (jumbo9_free * jumbo9_size) +
+ (jumbo16_free * jumbo16_size);
+
+ /*
+ * Total is bytes in use + bytes in cache. This doesn't take into
+ * account various other misc data structures, overhead, etc, but
+ * gives the user something useful despite that.
+ */
+ bytes_total = bytes_inuse + bytes_incache;
+
+ xo_emit("{:bytes-in-use/%ju}{U:K}/{:bytes-in-cache/%ju}{U:K}/"
+ "{:bytes-total/%ju}{U:K} "
+ "{N:bytes allocated to network (current\\/cache\\/total)}\n",
+ bytes_inuse / 1024, bytes_incache / 1024, bytes_total / 1024);
+
+ xo_emit("{:mbuf-failures/%ju}/{:cluster-failures/%ju}/"
+ "{:packet-failures/%ju} {N:requests for mbufs denied "
+ "(mbufs\\/clusters\\/mbuf+clusters)}\n",
+ mbuf_failures, cluster_failures, packet_failures);
+ xo_emit("{:mbuf-sleeps/%ju}/{:cluster-sleeps/%ju}/{:packet-sleeps/%ju} "
+ "{N:requests for mbufs delayed "
+ "(mbufs\\/clusters\\/mbuf+clusters)}\n",
+ mbuf_sleeps, cluster_sleeps, packet_sleeps);
+
+ xo_emit("{:jumbop-sleeps/%ju}/{:jumbo9-sleeps/%ju}/"
+ "{:jumbo16-sleeps/%ju} {N:/requests for jumbo clusters delayed "
+ "(%juk\\/9k\\/16k)}\n",
+ jumbop_sleeps, jumbo9_sleeps, jumbo16_sleeps, jumbop_size / 1024);
+ xo_emit("{:jumbop-failures/%ju}/{:jumbo9-failures/%ju}/"
+ "{:jumbo16-failures/%ju} {N:/requests for jumbo clusters denied "
+ "(%juk\\/9k\\/16k)}\n",
+ jumbop_failures, jumbo9_failures, jumbo16_failures,
+ jumbop_size / 1024);
+
+ mlen = sizeof(nsfbufs);
+ if (live &&
+ sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL, 0) == 0 &&
+ sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused, &mlen,
+ NULL, 0) == 0 &&
+ sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak, &mlen,
+ NULL, 0) == 0)
+ xo_emit("{:nsfbufs-current/%d}/{:nsfbufs-peak/%d}/"
+ "{:nsfbufs/%d} "
+ "{N:sfbufs in use (current\\/peak\\/max)}\n",
+ nsfbufsused, nsfbufspeak, nsfbufs);
+
+ if (fetch_stats("kern.ipc.sfstat", mbaddr, &sfstat, sizeof(sfstat),
+ kread_counters) != 0)
+ goto out;
+
+ xo_emit("{:sendfile-syscalls/%ju} {N:sendfile syscalls}\n",
+ (uintmax_t)sfstat.sf_syscalls);
+ xo_emit("{:sendfile-no-io/%ju} "
+ "{N:sendfile syscalls completed without I\\/O request}\n",
+ (uintmax_t)sfstat.sf_noiocnt);
+ xo_emit("{:sendfile-io-count/%ju} "
+ "{N:requests for I\\/O initiated by sendfile}\n",
+ (uintmax_t)sfstat.sf_iocnt);
+ xo_emit("{:sendfile-pages-sent/%ju} "
+ "{N:pages read by sendfile as part of a request}\n",
+ (uintmax_t)sfstat.sf_pages_read);
+ xo_emit("{:sendfile-pages-valid/%ju} "
+ "{N:pages were valid at time of a sendfile request}\n",
+ (uintmax_t)sfstat.sf_pages_valid);
+ xo_emit("{:sendfile-pages-bogus/%ju} "
+ "{N:pages were valid and substituted to bogus page}\n",
+ (uintmax_t)sfstat.sf_pages_bogus);
+ xo_emit("{:sendfile-requested-readahead/%ju} "
+ "{N:pages were requested for read ahead by applications}\n",
+ (uintmax_t)sfstat.sf_rhpages_requested);
+ xo_emit("{:sendfile-readahead/%ju} "
+ "{N:pages were read ahead by sendfile}\n",
+ (uintmax_t)sfstat.sf_rhpages_read);
+ xo_emit("{:sendfile-busy-encounters/%ju} "
+ "{N:times sendfile encountered an already busy page}\n",
+ (uintmax_t)sfstat.sf_busy);
+ xo_emit("{:sfbufs-alloc-failed/%ju} {N:requests for sfbufs denied}\n",
+ (uintmax_t)sfstat.sf_allocfail);
+ xo_emit("{:sfbufs-alloc-wait/%ju} {N:requests for sfbufs delayed}\n",
+ (uintmax_t)sfstat.sf_allocwait);
+out:
+ xo_close_container("mbuf-statistics");
+ memstat_mtl_free(mtlp);
+}
diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c
new file mode 100644
index 000000000000..1577a6ae73ac
--- /dev/null
+++ b/usr.bin/netstat/mroute.c
@@ -0,0 +1,462 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1989 Stephen Deering
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+/*
+ * Print multicast routing structures and statistics.
+ *
+ * MROUTING 1.0
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/protosw.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/igmp.h>
+#include <net/route.h>
+
+#define _NETSTAT 1
+#include <netinet/ip_mroute.h>
+#undef _NETSTAT_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "nl_defs.h"
+
+static void print_bw_meter(struct bw_meter *, int *);
+static void print_mfc(struct mfc *, int, int *);
+
+static void
+print_bw_meter(struct bw_meter *bw_meter, int *banner_printed)
+{
+ char s1[256], s2[256], s3[256];
+ struct timeval now, end, delta;
+
+ gettimeofday(&now, NULL);
+
+ if (! *banner_printed) {
+ xo_open_list("bandwidth-meter");
+ xo_emit(" {T:Bandwidth Meters}\n");
+ xo_emit(" {T:/%-30s}", "Measured(Start|Packets|Bytes)");
+ xo_emit(" {T:/%s}", "Type");
+ xo_emit(" {T:/%-30s}", "Thresh(Interval|Packets|Bytes)");
+ xo_emit(" {T:Remain}");
+ xo_emit("\n");
+ *banner_printed = 1;
+ }
+
+ xo_open_instance("bandwidth-meter");
+
+ /* The measured values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS) {
+ snprintf(s1, sizeof(s1), "%ju",
+ (uintmax_t)bw_meter->bm_measured.b_packets);
+ xo_emit("{e:measured-packets/%ju}",
+ (uintmax_t)bw_meter->bm_measured.b_packets);
+ } else
+ strcpy(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES) {
+ snprintf(s2, sizeof(s2), "%ju",
+ (uintmax_t)bw_meter->bm_measured.b_bytes);
+ xo_emit("{e:measured-bytes/%ju}",
+ (uintmax_t)bw_meter->bm_measured.b_bytes);
+ } else
+ strcpy(s2, "?");
+ xo_emit(" {[:-30}{:start-time/%lu.%06lu}|{q:measured-packets/%s}"
+ "|{q:measured-bytes%s}{]:}",
+ (u_long)bw_meter->bm_start_time.tv_sec,
+ (u_long)bw_meter->bm_start_time.tv_usec, s1, s2);
+
+ /* The type of entry */
+ xo_emit(" {t:type/%-3s}", (bw_meter->bm_flags & BW_METER_GEQ) ? ">=" :
+ (bw_meter->bm_flags & BW_METER_LEQ) ? "<=" : "?");
+
+ /* The threshold values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS) {
+ snprintf(s1, sizeof(s1), "%ju",
+ (uintmax_t)bw_meter->bm_threshold.b_packets);
+ xo_emit("{e:threshold-packets/%ju}",
+ (uintmax_t)bw_meter->bm_threshold.b_packets);
+ } else
+ strcpy(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES) {
+ snprintf(s2, sizeof(s2), "%ju",
+ (uintmax_t)bw_meter->bm_threshold.b_bytes);
+ xo_emit("{e:threshold-bytes/%ju}",
+ (uintmax_t)bw_meter->bm_threshold.b_bytes);
+ } else
+ strcpy(s2, "?");
+
+ xo_emit(" {[:-30}{:threshold-time/%lu.%06lu}|{q:threshold-packets/%s}"
+ "|{q:threshold-bytes%s}{]:}",
+ (u_long)bw_meter->bm_threshold.b_time.tv_sec,
+ (u_long)bw_meter->bm_threshold.b_time.tv_usec, s1, s2);
+
+ /* Remaining time */
+ timeradd(&bw_meter->bm_start_time,
+ &bw_meter->bm_threshold.b_time, &end);
+ if (timercmp(&now, &end, <=)) {
+ timersub(&end, &now, &delta);
+ snprintf(s3, sizeof(s3), "%lu.%06lu",
+ (u_long)delta.tv_sec,
+ (u_long)delta.tv_usec);
+ } else {
+ /* Negative time */
+ timersub(&now, &end, &delta);
+ snprintf(s3, sizeof(s3), "-%lu.06%lu",
+ (u_long)delta.tv_sec,
+ (u_long)delta.tv_usec);
+ }
+ xo_emit(" {:remaining-time/%s}", s3);
+
+ xo_open_instance("bandwidth-meter");
+
+ xo_emit("\n");
+}
+
+static void
+print_mfc(struct mfc *m, int maxvif, int *banner_printed)
+{
+ struct sockaddr_in sin;
+ struct sockaddr *sa = (struct sockaddr *)&sin;
+ struct bw_meter bw_meter, *bwm;
+ int bw_banner_printed;
+ int error;
+ vifi_t vifi;
+
+ bw_banner_printed = 0;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+
+ if (! *banner_printed) {
+ xo_open_list("multicast-forwarding-entry");
+ xo_emit("\n{T:IPv4 Multicast Forwarding Table}\n"
+ " {T:Origin} {T:Group} "
+ " {T:Packets In-Vif} {T:Out-Vifs:Ttls}\n");
+ *banner_printed = 1;
+ }
+
+ memcpy(&sin.sin_addr, &m->mfc_origin, sizeof(sin.sin_addr));
+ xo_emit(" {:origin-address/%-15.15s}", routename(sa, numeric_addr));
+ memcpy(&sin.sin_addr, &m->mfc_mcastgrp, sizeof(sin.sin_addr));
+ xo_emit(" {:group-address/%-15.15s}",
+ routename(sa, numeric_addr));
+ xo_emit(" {:sent-packets/%9lu}", m->mfc_pkt_cnt);
+ xo_emit(" {:parent/%3d} ", m->mfc_parent);
+ xo_open_list("vif-ttl");
+ for (vifi = 0; vifi <= maxvif; vifi++) {
+ if (m->mfc_ttls[vifi] > 0) {
+ xo_open_instance("vif-ttl");
+ xo_emit(" {k:vif/%u}:{:ttl/%u}", vifi,
+ m->mfc_ttls[vifi]);
+ xo_close_instance("vif-ttl");
+ }
+ }
+ xo_close_list("vif-ttl");
+ xo_emit("\n");
+
+ /*
+ * XXX We break the rules and try to use KVM to read the
+ * bandwidth meters, they are not retrievable via sysctl yet.
+ */
+ bwm = m->mfc_bw_meter_leq;
+ while (bwm != NULL) {
+ error = kread((u_long)bwm, (char *)&bw_meter,
+ sizeof(bw_meter));
+ if (error)
+ break;
+ print_bw_meter(&bw_meter, &bw_banner_printed);
+ bwm = bw_meter.bm_mfc_next;
+ }
+ bwm = m->mfc_bw_meter_geq;
+ while (bwm != NULL) {
+ error = kread((u_long)bwm, (char *)&bw_meter,
+ sizeof(bw_meter));
+ if (error)
+ break;
+ print_bw_meter(&bw_meter, &bw_banner_printed);
+ bwm = bw_meter.bm_mfc_next;
+ }
+ if (banner_printed)
+ xo_close_list("bandwidth-meter");
+}
+
+void
+mroutepr(void)
+{
+ struct sockaddr_in sin;
+ struct sockaddr *sa = (struct sockaddr *)&sin;
+ struct vif viftable[MAXVIFS];
+ struct vif *v;
+ struct mfc *m;
+ u_long pmfchashtbl, pmfctablesize, pviftbl;
+ int banner_printed;
+ int saved_numeric_addr;
+ size_t len;
+ vifi_t vifi, maxvif;
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+
+ /*
+ * TODO:
+ * The VIF table will move to hanging off the struct if_info for
+ * each IPv4 configured interface. Currently it is statically
+ * allocated, and retrieved either using KVM or an opaque SYSCTL.
+ *
+ * This can't happen until the API documented in multicast(4)
+ * is itself refactored. The historical reason why VIFs use
+ * a separate ifindex space is entirely due to the legacy
+ * capability of the MROUTING code to create IPIP tunnels on
+ * the fly to support DVMRP. When gif(4) became available, this
+ * functionality was deprecated, as PIM does not use it.
+ */
+ maxvif = 0;
+ pmfchashtbl = pmfctablesize = pviftbl = 0;
+
+ len = sizeof(viftable);
+ if (live) {
+ if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
+ 0) < 0) {
+ xo_warn("sysctl: net.inet.ip.viftable");
+ return;
+ }
+ } else {
+ pmfchashtbl = nl[N_MFCHASHTBL].n_value;
+ pmfctablesize = nl[N_MFCTABLESIZE].n_value;
+ pviftbl = nl[N_VIFTABLE].n_value;
+
+ if (pmfchashtbl == 0 || pmfctablesize == 0 || pviftbl == 0) {
+ xo_warnx("No IPv4 MROUTING kernel support.");
+ return;
+ }
+
+ kread(pviftbl, (char *)viftable, sizeof(viftable));
+ }
+
+ banner_printed = 0;
+ for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
+ if (v->v_lcl_addr.s_addr == 0)
+ continue;
+
+ maxvif = vifi;
+ if (!banner_printed) {
+ xo_emit("\n{T:IPv4 Virtual Interface Table\n"
+ " Vif Thresh Local-Address "
+ "Remote-Address Pkts-In Pkts-Out}\n");
+ banner_printed = 1;
+ xo_open_list("vif");
+ }
+
+ xo_open_instance("vif");
+ memcpy(&sin.sin_addr, &v->v_lcl_addr, sizeof(sin.sin_addr));
+ xo_emit(" {:vif/%2u} {:threshold/%6u} {:route/%-15.15s}",
+ /* opposite math of add_vif() */
+ vifi, v->v_threshold,
+ routename(sa, numeric_addr));
+ memcpy(&sin.sin_addr, &v->v_rmt_addr, sizeof(sin.sin_addr));
+ xo_emit(" {:source/%-15.15s}", (v->v_flags & VIFF_TUNNEL) ?
+ routename(sa, numeric_addr) : "");
+
+ xo_emit(" {:received-packets/%9lu} {:sent-packets/%9lu}\n",
+ v->v_pkt_in, v->v_pkt_out);
+ xo_close_instance("vif");
+ }
+ if (banner_printed)
+ xo_close_list("vif");
+ else
+ xo_emit("\n{T:IPv4 Virtual Interface Table is empty}\n");
+
+ banner_printed = 0;
+
+ /*
+ * TODO:
+ * The MFC table will move into the AF_INET radix trie in future.
+ * In 8.x, it becomes a dynamically allocated structure referenced
+ * by a hashed LIST, allowing more than 256 entries w/o kernel tuning.
+ *
+ * If retrieved via opaque SYSCTL, the kernel will coalesce it into
+ * a static table for us.
+ * If retrieved via KVM, the hash list pointers must be followed.
+ */
+ if (live) {
+ struct mfc *mfctable;
+
+ len = 0;
+ if (sysctlbyname("net.inet.ip.mfctable", NULL, &len, NULL,
+ 0) < 0) {
+ xo_warn("sysctl: net.inet.ip.mfctable");
+ return;
+ }
+
+ mfctable = malloc(len);
+ if (mfctable == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
+ 0) < 0) {
+ free(mfctable);
+ xo_warn("sysctl: net.inet.ip.mfctable");
+ return;
+ }
+
+ m = mfctable;
+ while (len >= sizeof(*m)) {
+ print_mfc(m++, maxvif, &banner_printed);
+ len -= sizeof(*m);
+ }
+ if (banner_printed)
+ xo_close_list("multicast-forwarding-entry");
+ if (len != 0)
+ xo_warnx("print_mfc: %lu trailing bytes", (u_long)len);
+
+ free(mfctable);
+ } else {
+ LIST_HEAD(, mfc) *mfchashtbl;
+ u_long i, mfctablesize;
+ struct mfc mfc;
+ int error;
+
+ error = kread(pmfctablesize, (char *)&mfctablesize,
+ sizeof(u_long));
+ if (error) {
+ xo_warn("kread: mfctablesize");
+ return;
+ }
+
+ len = sizeof(*mfchashtbl) * mfctablesize;
+ mfchashtbl = malloc(len);
+ if (mfchashtbl == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ kread(pmfchashtbl, (char *)&mfchashtbl, len);
+
+ for (i = 0; i < mfctablesize; i++) {
+ LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
+ kread((u_long)m, (char *)&mfc, sizeof(mfc));
+ print_mfc(m, maxvif, &banner_printed);
+ }
+ }
+ if (banner_printed)
+ xo_close_list("multicast-forwarding-entry");
+
+ free(mfchashtbl);
+ }
+
+ if (!banner_printed)
+ xo_emit("\n{T:IPv4 Multicast Forwarding Table is empty}\n");
+
+ xo_emit("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt_stats(void)
+{
+ struct mrtstat mrtstat;
+ u_long mstaddr;
+
+ mstaddr = nl[N_MRTSTAT].n_value;
+
+ if (fetch_stats("net.inet.ip.mrtstat", mstaddr, &mrtstat,
+ sizeof(mrtstat), kread_counters) != 0) {
+ if ((live && errno == ENOENT) || (!live && mstaddr == 0))
+ fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
+ return;
+ }
+
+ xo_emit("{T:IPv4 multicast forwarding}:\n");
+
+#define p(f, m) if (mrtstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)mrtstat.f, plural(mrtstat.f))
+#define p2(f, m) if (mrtstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f))
+
+ xo_open_container("multicast-statistics");
+
+ p(mrts_mfc_lookups, "\t{:cache-lookups/%ju} "
+ "{N:/multicast forwarding cache lookup%s}\n");
+ p2(mrts_mfc_misses, "\t{:cache-misses/%ju} "
+ "{N:/multicast forwarding cache miss%s}\n");
+ p(mrts_upcalls, "\t{:upcalls-total/%ju} "
+ "{N:/upcall%s to multicast routing daemon}\n");
+ p(mrts_upq_ovflw, "\t{:upcall-overflows/%ju} "
+ "{N:/upcall queue overflow%s}\n");
+ p(mrts_upq_sockfull,
+ "\t{:upcalls-dropped-full-buffer/%ju} "
+ "{N:/upcall%s dropped due to full socket buffer}\n");
+ p(mrts_cache_cleanups, "\t{:cache-cleanups/%ju} "
+ "{N:/cache cleanup%s}\n");
+ p(mrts_no_route, "\t{:dropped-no-origin/%ju} "
+ "{N:/datagram%s with no route for origin}\n");
+ p(mrts_bad_tunnel, "\t{:dropped-bad-tunnel/%ju} "
+ "{N:/datagram%s arrived with bad tunneling}\n");
+ p(mrts_cant_tunnel, "\t{:dropped-could-not-tunnel/%ju} "
+ "{N:/datagram%s could not be tunneled}\n");
+ p(mrts_wrong_if, "\t{:dropped-wrong-incoming-interface/%ju} "
+ "{N:/datagram%s arrived on wrong interface}\n");
+ p(mrts_drop_sel, "\t{:dropped-selectively/%ju} "
+ "{N:/datagram%s selectively dropped}\n");
+ p(mrts_q_overflow, "\t{:dropped-queue-overflow/%ju} "
+ "{N:/datagram%s dropped due to queue overflow}\n");
+ p(mrts_pkt2large, "\t{:dropped-too-large/%ju} "
+ "{N:/datagram%s dropped for being too large}\n");
+
+#undef p2
+#undef p
+}
diff --git a/usr.bin/netstat/mroute6.c b/usr.bin/netstat/mroute6.c
new file mode 100644
index 000000000000..0bb44b8292e7
--- /dev/null
+++ b/usr.bin/netstat/mroute6.c
@@ -0,0 +1,274 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause AND BSD-3-Clause
+ *
+ * Copyright (C) 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+/*-
+ * Copyright (c) 1989 Stephen Deering
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <libxo/xo.h>
+
+#define KERNEL 1
+struct sockopt;
+#include <netinet6/ip6_mroute.h>
+#undef KERNEL
+
+#include "netstat.h"
+
+#define WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
+#define WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
+
+void
+mroute6pr(void)
+{
+ struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
+ struct mif6_sctl mif6table[MAXMIFS];
+ struct mf6c mfc;
+ struct rtdetq rte, *rtep;
+ struct mif6_sctl *mifp;
+ mifi_t mifi;
+ int i;
+ int banner_printed;
+ int saved_numeric_addr;
+ mifi_t maxmif = 0;
+ long int waitings;
+ size_t len;
+
+ if (live == 0)
+ return;
+
+ len = sizeof(mif6table);
+ if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len, NULL, 0) <
+ 0) {
+ xo_warn("sysctl: net.inet6.ip6.mif6table");
+ return;
+ }
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+ banner_printed = 0;
+
+ for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
+ char ifname[IFNAMSIZ];
+
+ if (mifp->m6_ifp == 0)
+ continue;
+
+ maxmif = mifi;
+ if (!banner_printed) {
+ xo_open_list("multicast-interface");
+ xo_emit("\n{T:IPv6 Multicast Interface Table}\n"
+ "{T: Mif Rate PhyIF Pkts-In Pkts-Out}\n");
+ banner_printed = 1;
+ }
+
+ xo_open_instance("multicast-interface");
+ xo_emit(" {:mif/%2u} {:rate-limit/%4d}",
+ mifi, mifp->m6_rate_limit);
+ xo_emit(" {:ifname/%5s}", (mifp->m6_flags & MIFF_REGISTER) ?
+ "reg0" : if_indextoname(mifp->m6_ifp, ifname));
+
+ xo_emit(" {:received-packets/%9ju} {:sent-packets/%9ju}\n",
+ (uintmax_t)mifp->m6_pkt_in,
+ (uintmax_t)mifp->m6_pkt_out);
+ xo_close_instance("multicast-interface");
+ }
+ if (banner_printed)
+ xo_open_list("multicast-interface");
+ else
+ xo_emit("\n{T:IPv6 Multicast Interface Table is empty}\n");
+
+ len = sizeof(mf6ctable);
+ if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len, NULL, 0) <
+ 0) {
+ xo_warn("sysctl: net.inet6.ip6.mf6ctable");
+ return;
+ }
+
+ banner_printed = 0;
+
+ for (i = 0; i < MF6CTBLSIZ; ++i) {
+ mfcp = mf6ctable[i];
+ while(mfcp) {
+ kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
+ if (!banner_printed) {
+ xo_open_list("multicast-forwarding-cache");
+ xo_emit("\n"
+ "{T:IPv6 Multicast Forwarding Cache}\n");
+ xo_emit(" {T:%-*.*s} {T:%-*.*s} {T:%s}",
+ WID_ORG, WID_ORG, "Origin",
+ WID_GRP, WID_GRP, "Group",
+ " Packets Waits In-Mif Out-Mifs\n");
+ banner_printed = 1;
+ }
+
+ xo_open_instance("multicast-forwarding-cache");
+
+ xo_emit(" {:origin/%-*.*s}", WID_ORG, WID_ORG,
+ routename(sin6tosa(&mfc.mf6c_origin),
+ numeric_addr));
+ xo_emit(" {:group/%-*.*s}", WID_GRP, WID_GRP,
+ routename(sin6tosa(&mfc.mf6c_mcastgrp),
+ numeric_addr));
+ xo_emit(" {:total-packets/%9ju}",
+ (uintmax_t)mfc.mf6c_pkt_cnt);
+
+ for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
+ waitings++;
+ /* XXX KVM */
+ kread((u_long)rtep, (char *)&rte, sizeof(rte));
+ rtep = rte.next;
+ }
+ xo_emit(" {:waitings/%3ld}", waitings);
+
+ if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
+ xo_emit(" --- ");
+ else
+ xo_emit(" {:parent/%3d} ", mfc.mf6c_parent);
+ xo_open_list("mif");
+ for (mifi = 0; mifi <= maxmif; mifi++) {
+ if (IF_ISSET(mifi, &mfc.mf6c_ifset))
+ xo_emit(" {l:%u}", mifi);
+ }
+ xo_close_list("mif");
+ xo_emit("\n");
+
+ mfcp = mfc.mf6c_next;
+ xo_close_instance("multicast-forwarding-cache");
+ }
+ }
+ if (banner_printed)
+ xo_close_list("multicast-forwarding-cache");
+ else
+ xo_emit("\n{T:IPv6 Multicast Forwarding Table is empty}\n");
+
+ xo_emit("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt6_stats(void)
+{
+ struct mrt6stat mrtstat;
+
+ if (fetch_stats("net.inet6.ip6.mrt6stat", 0, &mrtstat,
+ sizeof(mrtstat), kread_counters) != 0)
+ return;
+
+ xo_open_container("multicast-statistics");
+ xo_emit("{T:IPv6 multicast forwarding}:\n");
+
+#define p(f, m) if (mrtstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)mrtstat.f, plural(mrtstat.f))
+#define p2(f, m) if (mrtstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f))
+
+ p(mrt6s_mfc_lookups, "\t{:cache-lookups/%ju} "
+ "{N:/multicast forwarding cache lookup%s}\n");
+ p2(mrt6s_mfc_misses, "\t{:cache-misses/%ju} "
+ "{N:/multicast forwarding cache miss%s}\n");
+ p(mrt6s_upcalls, "\t{:upcalls/%ju} "
+ "{N:/upcall%s to multicast routing daemon}\n");
+ p(mrt6s_upq_ovflw, "\t{:upcall-overflows/%ju} "
+ "{N:/upcall queue overflow%s}\n");
+ p(mrt6s_upq_sockfull, "\t{:upcalls-dropped-full-buffer/%ju} "
+ "{N:/upcall%s dropped due to full socket buffer}\n");
+ p(mrt6s_cache_cleanups, "\t{:cache-cleanups/%ju} "
+ "{N:/cache cleanup%s}\n");
+ p(mrt6s_no_route, "\t{:dropped-no-origin/%ju} "
+ "{N:/datagram%s with no route for origin}\n");
+ p(mrt6s_bad_tunnel, "\t{:dropped-bad-tunnel/%ju} "
+ "{N:/datagram%s arrived with bad tunneling}\n");
+ p(mrt6s_cant_tunnel, "\t{:dropped-could-not-tunnel/%ju} "
+ "{N:/datagram%s could not be tunneled}\n");
+ p(mrt6s_wrong_if, "\t{:dropped-wrong-incoming-interface/%ju} "
+ "{N:/datagram%s arrived on wrong interface}\n");
+ p(mrt6s_drop_sel, "\t{:dropped-selectively/%ju} "
+ "{N:/datagram%s selectively dropped}\n");
+ p(mrt6s_q_overflow, "\t{:dropped-queue-overflow/%ju} "
+ "{N:/datagram%s dropped due to queue overflow}\n");
+ p(mrt6s_pkt2large, "\t{:dropped-too-large/%ju} "
+ "{N:/datagram%s dropped for being too large}\n");
+
+#undef p2
+#undef p
+ xo_close_container("multicast-statistics");
+}
+#endif /*INET6*/
diff --git a/usr.bin/netstat/netgraph.c b/usr.bin/netstat/netgraph.c
new file mode 100644
index 000000000000..3a4c11de1db8
--- /dev/null
+++ b/usr.bin/netstat/netgraph.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 1996-1999 Whistle Communications, Inc.
+ * All rights reserved.
+ *
+ * Subject to the following obligations and disclaimer of warranty, use and
+ * redistribution of this software, in source or object code forms, with or
+ * without modifications are expressly permitted by Whistle Communications;
+ * provided, however, that:
+ * 1. Any and all reproductions of the source or object code must include the
+ * copyright notice above and the following disclaimer of warranties; and
+ * 2. No rights are granted, in any manner or form, to use Whistle
+ * Communications, Inc. trademarks, including the mark "WHISTLE
+ * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
+ * such appears in the above copyright notice or in the software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
+ * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
+ * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+ * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
+ * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
+ * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
+ * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
+ * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
+ * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#define _WANT_SOCKET
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/linker.h>
+
+#include <net/route.h>
+
+#include <netgraph.h>
+#include <netgraph/ng_message.h>
+#include <netgraph/ng_socket.h>
+#include <netgraph/ng_socketvar.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+static int first = 1;
+static int csock = -1;
+
+void
+netgraphprotopr(u_long off, const char *name, int af1 __unused,
+ int proto __unused)
+{
+ struct ngpcb *this, *next;
+ struct ngpcb ngpcb;
+ struct socket sockb;
+ int debug = 1;
+
+ /* If symbol not found, try looking in the KLD module */
+ if (off == 0) {
+ if (debug)
+ xo_warnx("Error reading symbols from ng_socket.ko");
+ return;
+ }
+
+ /* Get pointer to first socket */
+ kread(off, (char *)&this, sizeof(this));
+
+ /* Get my own socket node */
+ if (csock == -1)
+ NgMkSockNode(NULL, &csock, NULL);
+
+ for (; this != NULL; this = next) {
+ u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
+ struct ng_mesg *resp = (struct ng_mesg *) rbuf;
+ struct nodeinfo *ni = (struct nodeinfo *) resp->data;
+ char path[64];
+
+ /* Read in ngpcb structure */
+ kread((u_long)this, (char *)&ngpcb, sizeof(ngpcb));
+ next = LIST_NEXT(&ngpcb, socks);
+
+ /* Read in socket structure */
+ kread((u_long)ngpcb.ng_socket, (char *)&sockb, sizeof(sockb));
+
+ /* Check type of socket */
+ if (strcmp(name, "ctrl") == 0 && ngpcb.type != NG_CONTROL)
+ continue;
+ if (strcmp(name, "data") == 0 && ngpcb.type != NG_DATA)
+ continue;
+
+ /* Do headline */
+ if (first) {
+ xo_emit("{T:Netgraph sockets}\n");
+ if (Aflag)
+ xo_emit("{T:/%-8.8s} ", "PCB");
+ xo_emit("{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} "
+ "{T:/%-14.14s} {T:/%s}\n",
+ "Type", "Recv-Q", "Send-Q", "Node Address",
+ "#Hooks");
+ first = 0;
+ }
+
+ /* Show socket */
+ if (Aflag)
+ xo_emit("{:address/%8lx} ", (u_long) this);
+ xo_emit("{t:name/%-5.5s} {:receive-bytes-waiting/%6u} "
+ "{:send-byte-waiting/%6u} ",
+ name, sockb.so_rcv.sb_ccc, sockb.so_snd.sb_ccc);
+
+ /* Get info on associated node */
+ if (ngpcb.node_id == 0 || csock == -1)
+ goto finish;
+ snprintf(path, sizeof(path), "[%x]:", ngpcb.node_id);
+ if (NgSendMsg(csock, path,
+ NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0)
+ goto finish;
+ if (NgRecvMsg(csock, resp, sizeof(rbuf), NULL) < 0)
+ goto finish;
+
+ /* Display associated node info */
+ if (*ni->name != '\0')
+ snprintf(path, sizeof(path), "%s:", ni->name);
+ xo_emit("{t:path/%-14.14s} {:hooks/%4d}", path, ni->hooks);
+finish:
+ xo_emit("\n");
+ }
+}
+
diff --git a/usr.bin/netstat/netisr.c b/usr.bin/netstat/netisr.c
new file mode 100644
index 000000000000..1708a8f01c79
--- /dev/null
+++ b/usr.bin/netstat/netisr.c
@@ -0,0 +1,506 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+
+#define _WANT_NETISR_INTERNAL
+#include <net/netisr.h>
+#include <net/netisr_internal.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "nl_defs.h"
+
+/*
+ * Print statistics for the kernel netisr subsystem.
+ */
+static u_int bindthreads;
+static u_int maxthreads;
+static u_int numthreads;
+
+static u_int defaultqlimit;
+static u_int maxqlimit;
+
+static char dispatch_policy[20];
+
+static struct sysctl_netisr_proto *proto_array;
+static u_int proto_array_len;
+
+static struct sysctl_netisr_workstream *workstream_array;
+static u_int workstream_array_len;
+
+static struct sysctl_netisr_work *work_array;
+static u_int work_array_len;
+
+static u_int *nws_array;
+
+static u_int maxprot;
+
+static void
+netisr_dispatch_policy_to_string(u_int policy, char *buf,
+ size_t buflen)
+{
+ const char *str;
+
+ switch (policy) {
+ case NETISR_DISPATCH_DEFAULT:
+ str = "default";
+ break;
+ case NETISR_DISPATCH_DEFERRED:
+ str = "deferred";
+ break;
+ case NETISR_DISPATCH_HYBRID:
+ str = "hybrid";
+ break;
+ case NETISR_DISPATCH_DIRECT:
+ str = "direct";
+ break;
+ default:
+ str = "unknown";
+ break;
+ }
+ snprintf(buf, buflen, "%s", str);
+}
+
+/*
+ * Load a nul-terminated string from KVM up to 'limit', guarantee that the
+ * string in local memory is nul-terminated.
+ */
+static void
+netisr_load_kvm_string(uintptr_t addr, char *dest, u_int limit)
+{
+ u_int i;
+
+ for (i = 0; i < limit; i++) {
+ if (kread(addr + i, &dest[i], sizeof(dest[i])) != 0)
+ xo_errx(EX_OSERR, "%s: kread()", __func__);
+ if (dest[i] == '\0')
+ break;
+ }
+ dest[limit - 1] = '\0';
+}
+
+static const char *
+netisr_proto2name(u_int proto)
+{
+ u_int i;
+
+ for (i = 0; i < proto_array_len; i++) {
+ if (proto_array[i].snp_proto == proto)
+ return (proto_array[i].snp_name);
+ }
+ return ("unknown");
+}
+
+static int
+netisr_protoispresent(u_int proto)
+{
+ u_int i;
+
+ for (i = 0; i < proto_array_len; i++) {
+ if (proto_array[i].snp_proto == proto)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+netisr_load_kvm_config(void)
+{
+ u_int tmp;
+
+ kread(nl[N_NETISR_BINDTHREADS].n_value, &bindthreads, sizeof(u_int));
+ kread(nl[N_NETISR_MAXTHREADS].n_value, &maxthreads, sizeof(u_int));
+ kread(nl[N_NWS_COUNT].n_value, &numthreads, sizeof(u_int));
+ kread(nl[N_NETISR_DEFAULTQLIMIT].n_value, &defaultqlimit,
+ sizeof(u_int));
+ kread(nl[N_NETISR_MAXQLIMIT].n_value, &maxqlimit, sizeof(u_int));
+ kread(nl[N_NETISR_DISPATCH_POLICY].n_value, &tmp, sizeof(u_int));
+
+ netisr_dispatch_policy_to_string(tmp, dispatch_policy,
+ sizeof(dispatch_policy));
+}
+
+static void
+netisr_load_sysctl_uint(const char *name, u_int *p)
+{
+ size_t retlen;
+
+ retlen = sizeof(u_int);
+ if (sysctlbyname(name, p, &retlen, NULL, 0) < 0)
+ xo_err(EX_OSERR, "%s", name);
+ if (retlen != sizeof(u_int))
+ xo_errx(EX_DATAERR, "%s: invalid len %ju", name, (uintmax_t)retlen);
+}
+
+static void
+netisr_load_sysctl_string(const char *name, char *p, size_t len)
+{
+ size_t retlen;
+
+ retlen = len;
+ if (sysctlbyname(name, p, &retlen, NULL, 0) < 0)
+ xo_err(EX_OSERR, "%s", name);
+ p[len - 1] = '\0';
+}
+
+static void
+netisr_load_sysctl_config(void)
+{
+
+ netisr_load_sysctl_uint("net.isr.bindthreads", &bindthreads);
+ netisr_load_sysctl_uint("net.isr.maxthreads", &maxthreads);
+ netisr_load_sysctl_uint("net.isr.numthreads", &numthreads);
+
+ netisr_load_sysctl_uint("net.isr.defaultqlimit", &defaultqlimit);
+ netisr_load_sysctl_uint("net.isr.maxqlimit", &maxqlimit);
+
+ netisr_load_sysctl_string("net.isr.dispatch", dispatch_policy,
+ sizeof(dispatch_policy));
+}
+
+static void
+netisr_load_kvm_proto(void)
+{
+ struct netisr_proto *np_array, *npp;
+ u_int i, protocount;
+ struct sysctl_netisr_proto *snpp;
+ size_t len;
+
+ /*
+ * Kernel compile-time and user compile-time definitions of
+ * NETISR_MAXPROT must match, as we use that to size work arrays.
+ */
+ kread(nl[N_NETISR_MAXPROT].n_value, &maxprot, sizeof(u_int));
+ if (maxprot != NETISR_MAXPROT)
+ xo_errx(EX_DATAERR, "%s: NETISR_MAXPROT mismatch", __func__);
+ len = maxprot * sizeof(*np_array);
+ np_array = malloc(len);
+ if (np_array == NULL)
+ xo_err(EX_OSERR, "%s: malloc", __func__);
+ if (kread(nl[N_NETISR_PROTO].n_value, np_array, len) != 0)
+ xo_errx(EX_DATAERR, "%s: kread(_netisr_proto)", __func__);
+
+ /*
+ * Size and allocate memory to hold only live protocols.
+ */
+ protocount = 0;
+ for (i = 0; i < maxprot; i++) {
+ if (np_array[i].np_name == NULL)
+ continue;
+ protocount++;
+ }
+ proto_array = calloc(protocount, sizeof(*proto_array));
+ if (proto_array == NULL)
+ xo_err(EX_OSERR, "malloc");
+ protocount = 0;
+ for (i = 0; i < maxprot; i++) {
+ npp = &np_array[i];
+ if (npp->np_name == NULL)
+ continue;
+ snpp = &proto_array[protocount];
+ snpp->snp_version = sizeof(*snpp);
+ netisr_load_kvm_string((uintptr_t)npp->np_name,
+ snpp->snp_name, sizeof(snpp->snp_name));
+ snpp->snp_proto = i;
+ snpp->snp_qlimit = npp->np_qlimit;
+ snpp->snp_policy = npp->np_policy;
+ snpp->snp_dispatch = npp->np_dispatch;
+ if (npp->np_m2flow != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_M2FLOW;
+ if (npp->np_m2cpuid != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_M2CPUID;
+ if (npp->np_drainedcpu != NULL)
+ snpp->snp_flags |= NETISR_SNP_FLAGS_DRAINEDCPU;
+ protocount++;
+ }
+ proto_array_len = protocount;
+ free(np_array);
+}
+
+static void
+netisr_load_sysctl_proto(void)
+{
+ size_t len;
+
+ if (sysctlbyname("net.isr.proto", NULL, &len, NULL, 0) < 0)
+ xo_err(EX_OSERR, "net.isr.proto: query len");
+ if (len % sizeof(*proto_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.proto: invalid len");
+ proto_array = malloc(len);
+ if (proto_array == NULL)
+ xo_err(EX_OSERR, "malloc");
+ if (sysctlbyname("net.isr.proto", proto_array, &len, NULL, 0) < 0)
+ xo_err(EX_OSERR, "net.isr.proto: query data");
+ if (len % sizeof(*proto_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.proto: invalid len");
+ proto_array_len = len / sizeof(*proto_array);
+ if (proto_array_len < 1)
+ xo_errx(EX_DATAERR, "net.isr.proto: no data");
+ if (proto_array[0].snp_version != sizeof(proto_array[0]))
+ xo_errx(EX_DATAERR, "net.isr.proto: invalid version");
+}
+
+static void
+netisr_load_kvm_workstream(void)
+{
+ struct netisr_workstream nws;
+ struct sysctl_netisr_workstream *snwsp;
+ struct sysctl_netisr_work *snwp;
+ struct netisr_work *nwp;
+ u_int counter, cpuid, proto, wsid;
+ size_t len;
+
+ len = numthreads * sizeof(*nws_array);
+ nws_array = malloc(len);
+ if (nws_array == NULL)
+ xo_err(EX_OSERR, "malloc");
+ if (kread(nl[N_NWS_ARRAY].n_value, nws_array, len) != 0)
+ xo_errx(EX_OSERR, "%s: kread(_nws_array)", __func__);
+ workstream_array = calloc(numthreads, sizeof(*workstream_array));
+ if (workstream_array == NULL)
+ xo_err(EX_OSERR, "calloc");
+ workstream_array_len = numthreads;
+ work_array = calloc(numthreads * proto_array_len, sizeof(*work_array));
+ if (work_array == NULL)
+ xo_err(EX_OSERR, "calloc");
+ counter = 0;
+ for (wsid = 0; wsid < numthreads; wsid++) {
+ cpuid = nws_array[wsid];
+ kset_dpcpu(cpuid);
+ if (kread(nl[N_NWS].n_value, &nws, sizeof(nws)) != 0)
+ xo_errx(EX_OSERR, "%s: kread(nw)", __func__);
+ snwsp = &workstream_array[wsid];
+ snwsp->snws_version = sizeof(*snwsp);
+ snwsp->snws_wsid = cpuid;
+ snwsp->snws_cpu = cpuid;
+ if (nws.nws_intr_event != NULL)
+ snwsp->snws_flags |= NETISR_SNWS_FLAGS_INTR;
+
+ /*
+ * Extract the CPU's per-protocol work information.
+ */
+ xo_emit("counting to maxprot: {:maxprot/%u}\n", maxprot);
+ for (proto = 0; proto < maxprot; proto++) {
+ if (!netisr_protoispresent(proto))
+ continue;
+ nwp = &nws.nws_work[proto];
+ snwp = &work_array[counter];
+ snwp->snw_version = sizeof(*snwp);
+ snwp->snw_wsid = cpuid;
+ snwp->snw_proto = proto;
+ snwp->snw_len = nwp->nw_len;
+ snwp->snw_watermark = nwp->nw_watermark;
+ snwp->snw_dispatched = nwp->nw_dispatched;
+ snwp->snw_hybrid_dispatched =
+ nwp->nw_hybrid_dispatched;
+ snwp->snw_qdrops = nwp->nw_qdrops;
+ snwp->snw_queued = nwp->nw_queued;
+ snwp->snw_handled = nwp->nw_handled;
+ counter++;
+ }
+ }
+ work_array_len = counter;
+}
+
+static void
+netisr_load_sysctl_workstream(void)
+{
+ size_t len;
+
+ if (sysctlbyname("net.isr.workstream", NULL, &len, NULL, 0) < 0)
+ xo_err(EX_OSERR, "net.isr.workstream: query len");
+ if (len % sizeof(*workstream_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.workstream: invalid len");
+ workstream_array = malloc(len);
+ if (workstream_array == NULL)
+ xo_err(EX_OSERR, "malloc");
+ if (sysctlbyname("net.isr.workstream", workstream_array, &len, NULL,
+ 0) < 0)
+ xo_err(EX_OSERR, "net.isr.workstream: query data");
+ if (len % sizeof(*workstream_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.workstream: invalid len");
+ workstream_array_len = len / sizeof(*workstream_array);
+ if (workstream_array_len < 1)
+ xo_errx(EX_DATAERR, "net.isr.workstream: no data");
+ if (workstream_array[0].snws_version != sizeof(workstream_array[0]))
+ xo_errx(EX_DATAERR, "net.isr.workstream: invalid version");
+}
+
+static void
+netisr_load_sysctl_work(void)
+{
+ size_t len;
+
+ if (sysctlbyname("net.isr.work", NULL, &len, NULL, 0) < 0)
+ xo_err(EX_OSERR, "net.isr.work: query len");
+ if (len % sizeof(*work_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.work: invalid len");
+ work_array = malloc(len);
+ if (work_array == NULL)
+ xo_err(EX_OSERR, "malloc");
+ if (sysctlbyname("net.isr.work", work_array, &len, NULL, 0) < 0)
+ xo_err(EX_OSERR, "net.isr.work: query data");
+ if (len % sizeof(*work_array) != 0)
+ xo_errx(EX_DATAERR, "net.isr.work: invalid len");
+ work_array_len = len / sizeof(*work_array);
+ if (work_array_len < 1)
+ xo_errx(EX_DATAERR, "net.isr.work: no data");
+ if (work_array[0].snw_version != sizeof(work_array[0]))
+ xo_errx(EX_DATAERR, "net.isr.work: invalid version");
+}
+
+static void
+netisr_print_proto(struct sysctl_netisr_proto *snpp)
+{
+ char tmp[20];
+
+ xo_emit("{[:-6}{k:name/%s}{]:}", snpp->snp_name);
+ xo_emit(" {:protocol/%5u}", snpp->snp_proto);
+ xo_emit(" {:queue-limit/%6u}", snpp->snp_qlimit);
+ xo_emit(" {:policy-type/%6s}",
+ (snpp->snp_policy == NETISR_POLICY_SOURCE) ? "source" :
+ (snpp->snp_policy == NETISR_POLICY_FLOW) ? "flow" :
+ (snpp->snp_policy == NETISR_POLICY_CPU) ? "cpu" : "-");
+ netisr_dispatch_policy_to_string(snpp->snp_dispatch, tmp,
+ sizeof(tmp));
+ xo_emit(" {:policy/%8s}", tmp);
+ xo_emit(" {:flags/%s%s%s}\n",
+ (snpp->snp_flags & NETISR_SNP_FLAGS_M2CPUID) ? "C" : "-",
+ (snpp->snp_flags & NETISR_SNP_FLAGS_DRAINEDCPU) ? "D" : "-",
+ (snpp->snp_flags & NETISR_SNP_FLAGS_M2FLOW) ? "F" : "-");
+}
+
+static void
+netisr_print_workstream(struct sysctl_netisr_workstream *snwsp)
+{
+ struct sysctl_netisr_work *snwp;
+ u_int i;
+
+ xo_open_list("work");
+ for (i = 0; i < work_array_len; i++) {
+ snwp = &work_array[i];
+ if (snwp->snw_wsid != snwsp->snws_wsid)
+ continue;
+ xo_open_instance("work");
+ xo_emit("{t:workstream/%4u} ", snwsp->snws_wsid);
+ xo_emit("{t:cpu/%3u} ", snwsp->snws_cpu);
+ xo_emit("{P: }");
+ xo_emit("{t:name/%-6s}", netisr_proto2name(snwp->snw_proto));
+ xo_emit(" {t:length/%5u}", snwp->snw_len);
+ xo_emit(" {t:watermark/%5u}", snwp->snw_watermark);
+ xo_emit(" {t:dispatched/%8ju}", snwp->snw_dispatched);
+ xo_emit(" {t:hybrid-dispatched/%8ju}",
+ snwp->snw_hybrid_dispatched);
+ xo_emit(" {t:queue-drops/%8ju}", snwp->snw_qdrops);
+ xo_emit(" {t:queued/%8ju}", snwp->snw_queued);
+ xo_emit(" {t:handled/%8ju}", snwp->snw_handled);
+ xo_emit("\n");
+ xo_close_instance("work");
+ }
+ xo_close_list("work");
+}
+
+void
+netisr_stats(void)
+{
+ struct sysctl_netisr_workstream *snwsp;
+ struct sysctl_netisr_proto *snpp;
+ u_int i;
+
+ if (live) {
+ netisr_load_sysctl_config();
+ netisr_load_sysctl_proto();
+ netisr_load_sysctl_workstream();
+ netisr_load_sysctl_work();
+ } else {
+ netisr_load_kvm_config();
+ netisr_load_kvm_proto();
+ netisr_load_kvm_workstream(); /* Also does work. */
+ }
+
+ xo_open_container("netisr");
+
+ xo_emit("{T:Configuration}:\n");
+ xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n",
+ "Setting", "Current", "Limit");
+ xo_emit("{T:/%-25s} {T:/%12u} {T:/%12u}\n",
+ "Thread count", numthreads, maxthreads);
+ xo_emit("{T:/%-25s} {T:/%12u} {T:/%12u}\n",
+ "Default queue limit", defaultqlimit, maxqlimit);
+ xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n",
+ "Dispatch policy", dispatch_policy, "n/a");
+ xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n",
+ "Threads bound to CPUs", bindthreads ? "enabled" : "disabled",
+ "n/a");
+ xo_emit("\n");
+
+ xo_emit("{T:Protocols}:\n");
+ xo_emit("{T:/%-6s} {T:/%5s} {T:/%6s} {T:/%-6s} {T:/%-8s} {T:/%-5s}\n",
+ "Name", "Proto", "QLimit", "Policy", "Dispatch", "Flags");
+ xo_open_list("protocol");
+ for (i = 0; i < proto_array_len; i++) {
+ xo_open_instance("protocol");
+ snpp = &proto_array[i];
+ netisr_print_proto(snpp);
+ xo_close_instance("protocol");
+ }
+ xo_close_list("protocol");
+ xo_emit("\n");
+
+ xo_emit("{T:Workstreams}:\n");
+ xo_emit("{T:/%4s} {T:/%3s} ", "WSID", "CPU");
+ xo_emit("{P:/%2s}", "");
+ xo_emit("{T:/%-6s} {T:/%5s} {T:/%5s} {T:/%8s} {T:/%8s} {T:/%8s} "
+ "{T:/%8s} {T:/%8s}\n",
+ "Name", "Len", "WMark", "Disp'd", "HDisp'd", "QDrops", "Queued",
+ "Handled");
+ xo_open_list("workstream");
+ for (i = 0; i < workstream_array_len; i++) {
+ xo_open_instance("workstream");
+ snwsp = &workstream_array[i];
+ netisr_print_workstream(snwsp);
+ xo_close_instance("workstream");
+ }
+ xo_close_list("workstream");
+ xo_close_container("netisr");
+}
diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1
new file mode 100644
index 000000000000..559cb1932080
--- /dev/null
+++ b/usr.bin/netstat/netstat.1
@@ -0,0 +1,944 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd January 29, 2025
+.Dt NETSTAT 1
+.Os
+.Sh NAME
+.Nm netstat
+.Nd show network status and statistics
+.Sh SYNOPSIS
+.Bk -words
+.Bl -tag -width "netstat"
+.It Nm
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46AaCLnPRSTWx
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.It Nm Fl i | I Ar interface
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46abdhnW
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl w Ar wait
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl I Ar interface
+.Op Fl 46d
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl q Ar howmany
+.It Nm Fl s
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46sz
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl i | I Ar interface Fl s
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46s
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl m
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl B
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl z
+.Op Fl I Ar interface
+.It Nm Fl r
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46nW
+.Op Fl F Ar fibnum
+.Op Fl f Ar address_family
+.It Nm Fl rs
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl s
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl g
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46W
+.Op Fl f Ar address_family
+.It Nm Fl gs
+.Op Fl j Ar jail
+.Op Fl -libxo
+.Op Fl 46s
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.It Nm Fl Q
+.Op Fl j Ar jail
+.Op Fl -libxo
+.El
+.Ek
+.Sh DESCRIPTION
+The
+.Nm
+command shows the contents of various network-related
+data structures.
+The arguments passed determine which of the below output formats the
+command uses.
+.Bl -tag -width indent
+.It Xo
+.Bk -words
+.Nm
+.Op Fl 46AaCLnRSTWx
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display a list of active sockets
+(protocol control blocks)
+for each network protocol.
+.Pp
+The default display for active sockets shows the local
+and remote addresses, send and receive queue sizes (in bytes), protocol,
+and the internal state of the protocol.
+Address formats are of the form
+.Dq host.port
+or
+.Dq network.port
+if a socket's address specifies a network but no specific host address.
+When known, the host and network addresses are displayed symbolically
+according to the databases
+.Xr hosts 5
+and
+.Xr networks 5 ,
+respectively.
+If a symbolic name for an address is unknown, or if
+the
+.Fl n
+option is specified, the address is printed numerically, according
+to the address family.
+For more information regarding
+the Internet IPv4
+.Dq dot format ,
+refer to
+.Xr inet 3 .
+Unspecified,
+or
+.Dq wildcard ,
+addresses and ports appear as
+.Dq Li * .
+.Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl 4
+Show IPv4 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl A
+Show the address of a protocol control block (PCB)
+associated with a socket; used for debugging.
+.It Fl a
+Show the state of all sockets;
+normally sockets used by server processes are not shown.
+.It Fl c
+Show the used TCP stack for each session.
+.It Fl C
+Show the congestion control algorithm and diagnostic information of TCP sockets.
+.It Fl L
+Show the size of the various listen queues.
+The first count shows the number of unaccepted connections,
+the second count shows the amount of unaccepted incomplete connections,
+and the third count is the maximum number of queued connections.
+.It Fl n
+Do not resolve numeric addresses and port numbers to names.
+See
+.Sx GENERAL OPTIONS .
+.It Fl P
+Display the log ID for each socket.
+.It Fl R
+Display the flowid and flowtype for each socket.
+flowid is a 32 bit hardware specific identifier for each flow.
+flowtype defines which protocol fields are hashed to produce the id.
+A complete listing is available in
+.Pa sys/mbuf.h
+under
+.Dv M_HASHTYPE_* .
+.It Fl S
+Show network addresses as numbers (as with
+.Fl n )
+but show ports symbolically.
+.It Fl T
+Display diagnostic information from the TCP control block.
+Fields include the number of packets requiring retransmission,
+received out-of-order, and those advertising a zero-sized window.
+.It Fl W
+Avoid truncating addresses even if this causes some fields to overflow.
+.It Fl x
+Display socket buffer and TCP timer statistics for each
+internet socket.
+.Pp
+The
+.Fl x
+flag causes
+.Nm
+to output all the information recorded about data
+stored in the socket buffers.
+The fields are:
+.Bl -column ".Li R-HIWA"
+.It Li R-HIWA Ta Receive buffer high water mark, in bytes.
+.It Li S-HIWA Ta Send buffer high water mark, in bytes.
+.It Li R-LOWA Ta Receive buffer low water mark, in bytes.
+.It Li S-LOWA Ta Send buffer low water mark, in bytes.
+.It Li R-BCNT Ta Receive buffer byte count.
+.It Li S-BCNT Ta Send buffer byte count.
+.It Li R-BMAX Ta Maximum bytes that can be used in the receive buffer.
+.It Li S-BMAX Ta Maximum bytes that can be used in the send buffer.
+.It Li rexmt Ta Time, in seconds, to fire Retransmit Timer, or 0 if not armed.
+.It Li persist Ta Time, in seconds, to fire Retransmit Persistence, or 0 if not armed.
+.It Li keep Ta Time, in seconds, to fire Keep Alive, or 0 if not armed.
+.It Li 2msl Ta Time, in seconds, to fire 2*msl TIME_WAIT Timer, or 0 if not armed.
+.It Li delack Ta Time, in seconds, to fire Delayed ACK Timer, or 0 if not armed.
+.It Li rcvtime Ta Time, in seconds, since last packet received.
+.El
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl p Ar protocol
+Filter by
+.Ar protocol .
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl i | I Ar interface
+.Op Fl 46abdhnW
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Show the state of all network interfaces or a single
+.Ar interface
+which have been auto-configured
+(interfaces statically configured into a system, but not
+located at boot time are not shown).
+An asterisk
+.Pq Dq Li *
+after an interface name indicates that the interface is
+.Dq down .
+.Pp
+When
+.Nm
+is invoked with
+.Fl i
+.Pq all interfaces
+or
+.Fl I Ar interface ,
+it provides a table of cumulative
+statistics regarding packets transferred, errors, and collisions.
+The network addresses of the interface
+and the maximum transmission unit
+.Pq Dq mtu
+are also displayed.
+If both
+.Fl i
+and
+.Fl I
+are specified,
+.Fl I
+overrides any instances of
+.Fl i .
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl a
+Multicast addresses currently in use are shown
+for each Ethernet interface and for each IP interface address.
+Multicast addresses are shown on separate lines following the interface
+address with which they are associated.
+.It Fl b
+Show the number of bytes in and out.
+.It Fl d
+Show the number of dropped output packets.
+.It Fl h
+Print all counters in human readable form.
+.It Fl n
+Do not resolve numeric addresses and port numbers to names.
+See
+.Sx GENERAL OPTIONS .
+.It Fl W
+Avoid truncating addresses even if this causes some fields to overflow.
+See
+.Sx GENERAL OPTIONS .
+However, in most cases field widths are determined automatically with the
+.Fl i
+option, and this option has little effect.
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl w Ar wait
+.Op Fl I Ar interface
+.Op Fl 46d
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl q Ar howmany
+.Op Fl j Ar jail
+.Ek
+.Xc
+At intervals of
+.Ar wait
+seconds, display the information regarding packet traffic on all
+configured network interfaces or a single
+.Ar interface .
+.Pp
+When
+.Nm
+is invoked with the
+.Fl w
+option and a
+.Ar wait
+interval argument, it displays a running count of statistics related to
+network interfaces.
+An obsolescent version of this option used a numeric parameter
+with no option, and is currently supported for backward compatibility.
+By default, this display summarizes information for all interfaces.
+Information for a specific interface may be displayed with the
+.Fl I Ar interface
+option.
+.Bl -tag -width indent
+.It Fl I Ar interface
+Only show information regarding
+.Ar interface
+.It Fl 4
+Show IPv4 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl d
+Show the number of dropped output packets.
+.It Fl M
+Use an alternative core.
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image.
+See
+.Sx GENERAL OPTIONS .
+.It Fl q
+Exit after
+.Ar howmany
+outputs.
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl s
+.Op Fl 46sz
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display system-wide statistics for each network protocol.
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl s
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.It Fl z
+Reset statistic counters after displaying them.
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl p Ar protocol
+Filter by
+.Ar protocol .
+See
+.Sx GENERAL OPTIONS .
+.It Fl M
+Use an alternative core.
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl i | I Ar interface Fl s
+.Op Fl 46s
+.Op Fl f Ar protocol_family | Fl p Ar protocol
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display per-interface statistics for each network protocol.
+If both
+.Fl i
+and
+.Fl I
+are specified,
+.Fl I
+overrides any instances of
+.Fl i .
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl s
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl p Ar protocol
+Filter by
+.Ar protocol .
+See
+.Sx GENERAL OPTIONS .
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl m
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Show statistics recorded by the memory management routines
+.Pq Xr mbuf 9 .
+The network manages a private pool of memory buffers.
+.Bl -tag -width indent
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl B
+.Op Fl z
+.Op Fl I Ar interface
+.Op Fl j Ar jail
+.Ek
+.Xc
+Show statistics about
+.Xr bpf 4
+peers.
+This includes information like
+how many packets have been matched, dropped and received by the
+bpf device, also information about current buffer sizes and device
+states.
+.Pp
+The
+.Xr bpf 4
+flags displayed when
+.Nm
+is invoked with the
+.Fl B
+option represent the underlying parameters of the bpf peer.
+Each flag is
+represented as a single lower case letter.
+The mapping between the letters and flags in order of appearance are:
+.Bl -column ".Li i"
+.It Li p Ta Set if listening promiscuously
+.It Li i Ta Dv BIOCIMMEDIATE No has been set on the device
+.It Li f Ta Dv BIOCGHDRCMPLT No status: source link addresses are being
+filled automatically
+.It Li s Ta Dv BIOCGSEESENT No status: see packets originating locally and
+remotely on the interface.
+.It Li a Ta Packet reception generates a signal
+.It Li l Ta Dv BIOCLOCK No status: descriptor has been locked
+.El
+.Pp
+For more information about these flags, please refer to
+.Xr bpf 4 .
+.Bl -tag -width indent
+.It Fl z
+Reset statistic counters after displaying them.
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl r
+.Op Fl 46AnW
+.Op Fl F Ar fibnum
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display the contents of routing tables.
+.Pp
+When
+.Nm
+is invoked with the routing table option
+.Fl r ,
+it lists the available routes and their status.
+Each route consists of a destination host or network, and a gateway to use
+in forwarding packets.
+The flags field shows a collection of information about the route stored
+as binary choices.
+The individual flags are discussed in more detail in the
+.Xr route 8
+and
+.Xr route 4
+manual pages.
+The mapping between letters and flags is:
+.Bl -column ".Li W" ".Dv RTF_WASCLONED"
+.It Li 1 Ta Dv RTF_PROTO1 Ta "Protocol specific routing flag #1"
+.It Li 2 Ta Dv RTF_PROTO2 Ta "Protocol specific routing flag #2"
+.It Li 3 Ta Dv RTF_PROTO3 Ta "Protocol specific routing flag #3"
+.It Li B Ta Dv RTF_BLACKHOLE Ta "Just discard pkts (during updates)"
+.It Li b Ta Dv RTF_BROADCAST Ta "The route represents a broadcast address"
+.It Li D Ta Dv RTF_DYNAMIC Ta "Created dynamically (by redirect)"
+.It Li G Ta Dv RTF_GATEWAY Ta "Destination requires forwarding by intermediary"
+.It Li H Ta Dv RTF_HOST Ta "Host entry (net otherwise)"
+.It Li L Ta Dv RTF_LLINFO Ta "Valid protocol to link address translation"
+.It Li M Ta Dv RTF_MODIFIED Ta "Modified dynamically (by redirect)"
+.It Li R Ta Dv RTF_REJECT Ta "Host or net unreachable"
+.It Li S Ta Dv RTF_STATIC Ta "Manually added"
+.It Li U Ta Dv RTF_UP Ta "Route usable"
+.It Li X Ta Dv RTF_XRESOLVE Ta "External daemon translates proto to link address"
+.El
+.Pp
+Direct routes are created for each
+interface attached to the local host;
+the gateway field for such entries shows the address of the outgoing interface.
+The refcnt field gives the
+current number of active uses of the route.
+Connection oriented
+protocols normally hold on to a single route for the duration of
+a connection while connectionless protocols obtain a route while sending
+to the same destination.
+The use field provides a count of the number of packets
+sent using that route.
+The interface entry indicates the network interface utilized for the route.
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only.
+See
+.Sx GENERAL OPTIONS .
+.It Fl n
+Do not resolve numeric addresses and port numbers to names.
+See
+.Sx GENERAL OPTIONS .
+.It Fl W
+Show the path MTU for each route, and print interface names with a
+wider field size.
+.It Fl F
+Display the routing table with the number
+.Ar fibnum .
+If the specified
+.Ar fibnum
+is -1 or
+.Fl F
+is not specified,
+the default routing table is displayed.
+.It Fl f
+Display the routing table for a particular
+.Ar address_family .
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl rs
+.Op Fl s
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display routing statistics.
+.Bl -tag -width indent
+.It Fl s
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl g
+.Op Fl 46W
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Display the contents of the multicast virtual interface tables,
+and multicast forwarding caches.
+Entries in these tables will appear only when the kernel is
+actively forwarding multicast sessions.
+This option is applicable only to the
+.Cm inet
+and
+.Cm inet6
+address families.
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl W
+Avoid truncating addresses even if this causes some fields to overflow.
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl gs
+.Op Fl 46s
+.Op Fl f Ar address_family
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl j Ar jail
+.Ek
+.Xc
+Show multicast routing statistics.
+.Bl -tag -width indent
+.It Fl 4
+Show IPv4 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl 6
+Show IPv6 only
+See
+.Sx GENERAL OPTIONS .
+.It Fl s
+If
+.Fl s
+is repeated, counters with a value of zero are suppressed.
+.It Fl f Ar protocol_family
+Filter by
+.Ar protocol_family .
+See
+.Sx GENERAL OPTIONS .
+.It Fl M
+Use an alternative core
+See
+.Sx GENERAL OPTIONS .
+.It Fl N
+Use an alternative kernel image
+See
+.Sx GENERAL OPTIONS .
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.It Xo
+.Bk -words
+.Nm
+.Fl Q
+.Op Fl j Ar jail
+.Ek
+.Xc
+Show
+.Xr netisr 9
+statistics.
+The flags field shows available ISR handlers:
+.Bl -column ".Li W" ".Dv NETISR_SNP_FLAGS_DRAINEDCPU"
+.It Li C Ta Dv NETISR_SNP_FLAGS_M2CPUID Ta "Able to map mbuf to cpu id"
+.It Li D Ta Dv NETISR_SNP_FLAGS_DRAINEDCPU Ta "Has queue drain handler"
+.It Li F Ta Dv NETISR_SNP_FLAGS_M2FLOW Ta "Able to map mbuf to flow id"
+.It Fl j Ar jail
+Run inside a jail.
+See
+.Sx GENERAL OPTIONS .
+.El
+.El
+.Ss GENERAL OPTIONS
+Some options have the general meaning:
+.Bl -tag -width flag
+.It Fl 4
+Is shorthand for
+.Fl f
+.Ar inet
+.Pq Show only IPv4
+.It Fl 6
+Is shorthand for
+.Fl f
+.Ar inet6
+.Pq Show only IPv6
+.It Fl f Ar address_family , Fl p Ar protocol
+Limit display to those records
+of the specified
+.Ar address_family
+or a single
+.Ar protocol .
+The following address families and protocols are recognized:
+.Pp
+.Bl -tag -width ".Cm netgraph , ng Pq Dv AF_NETGRAPH" -compact
+.It Em Family
+.Em Protocols
+.It Cm inet Pq Dv AF_INET
+.Cm divert , icmp , igmp , ip , ipsec , pim, sctp , tcp , udp
+.It Cm inet6 Pq Dv AF_INET6
+.Cm icmp6 , ip6 , ipsec6 , rip6 , sctp , tcp , udp
+.It Cm pfkey Pq Dv PF_KEY
+.Cm pfkey
+.It Cm netgraph , ng Pq Dv AF_NETGRAPH
+.Cm ctrl , data
+.It Cm unix Pq Dv AF_UNIX
+.It Cm link Pq Dv AF_LINK
+.El
+.Pp
+The program will complain if
+.Ar protocol
+is unknown or if there is no statistics routine for it.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the default,
+which is the kernel image the system has booted from.
+.It Fl n
+Show network addresses and ports as numbers.
+Normally
+.Nm
+attempts to resolve addresses and ports,
+and display them symbolically.
+Specifying
+.Fl n
+twice will also disable printing the keyword
+.Qq Dv default
+for the default IPv4 and IPv6 routes when displaying contents of routing
+tables.
+.It Fl W
+Wider output; expand address fields, etc, to avoid truncation.
+Non-numeric values such as domain names may still be truncated; use the
+.Fl n
+option if necessary to avoid ambiguity.
+.It Fl j Ar jail
+Perform the actions inside the
+.Ar jail .
+This allows network state to be accessed even if the
+.Cm netstat
+binary is not available in the
+.Ar jail .
+.El
+.Sh EXAMPLES
+Show packet traffic information (packets, bytes, errors, packet drops, etc) for
+interface re0 updated every 2 seconds and exit after 5 outputs:
+.Bd -literal -offset indent
+$ netstat -w 2 -q 5 -I re0
+.Ed
+.Pp
+Show statistics for ICMP on any interface:
+.Bd -literal -offset indent
+$ netstat -s -p icmp
+.Ed
+.Pp
+Show routing tables:
+.Bd -literal -offset indent
+$ netstat -r
+.Ed
+.Pp
+Same as above, but without resolving numeric addresses and port numbers to
+names:
+.Bd -literal -offset indent
+$ netstat -rn
+.Ed
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr nfsstat 1 ,
+.Xr procstat 1 ,
+.Xr ps 1 ,
+.Xr sockstat 1 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
+.Xr bpf 4 ,
+.Xr inet 4 ,
+.Xr route 4 ,
+.Xr unix 4 ,
+.Xr hosts 5 ,
+.Xr networks 5 ,
+.Xr protocols 5 ,
+.Xr services 5 ,
+.Xr iostat 8 ,
+.Xr route 8 ,
+.Xr vmstat 8 ,
+.Xr mbuf 9
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Pp
+IPv6 support was added by WIDE/KAME project.
+.Sh BUGS
+The notion of errors is ill-defined.
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
new file mode 100644
index 000000000000..1255bfdf2e57
--- /dev/null
+++ b/usr.bin/netstat/netstat.h
@@ -0,0 +1,168 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+
+#define NETSTAT_XO_VERSION "1"
+
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
+#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
+
+extern bool Aflag; /* show addresses of protocol control block */
+extern bool aflag; /* show all sockets (including servers) */
+extern bool bflag; /* show i/f total bytes in/out */
+extern bool cflag; /* show congestion control stats */
+extern bool Cflag; /* show congestion control algo and stack */
+extern bool dflag; /* show i/f dropped packets */
+extern bool gflag; /* show group (multicast) routing or stats */
+extern bool hflag; /* show counters in human readable format */
+extern bool iflag; /* show interfaces */
+extern bool Lflag; /* show size of listen queues */
+extern bool mflag; /* show memory stats */
+extern int noutputs; /* how much outputs before we exit */
+extern u_int numeric_addr; /* show addresses numerically */
+extern bool numeric_port; /* show ports numerically */
+extern bool Pflag; /* show TCP log ID */
+extern bool rflag; /* show routing tables (or routing stats) */
+extern bool Rflag; /* show flowid / RSS information */
+extern int sflag; /* show protocol statistics */
+extern bool Tflag; /* show TCP control block info */
+extern bool Wflag; /* wide display */
+extern bool xflag; /* extended display, includes all socket buffer info */
+extern bool zflag; /* zero stats */
+
+extern int interval; /* repeat interval for i/f stats */
+
+extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
+extern int unit; /* unit number for above */
+
+extern int live; /* true if we are examining a live system */
+
+typedef int kreadfn_t(u_long, void *, size_t);
+int fetch_stats(const char *, u_long, void *, size_t, kreadfn_t);
+int fetch_stats_ro(const char *, u_long, void *, size_t, kreadfn_t);
+
+int kread(u_long addr, void *buf, size_t size);
+uint64_t kread_counter(u_long addr);
+int kread_counters(u_long addr, void *buf, size_t size);
+void kset_dpcpu(u_int);
+const char *plural(uintmax_t);
+const char *plurales(uintmax_t);
+const char *pluralies(uintmax_t);
+
+struct sockaddr;
+struct socket;
+struct xsocket;
+int sotoxsocket(struct socket *, struct xsocket *);
+void protopr(u_long, const char *, int, int);
+void tcp_stats(u_long, const char *, int, int);
+void udp_stats(u_long, const char *, int, int);
+#ifdef SCTP
+void sctp_protopr(u_long, const char *, int, int);
+void sctp_stats(u_long, const char *, int, int);
+#endif
+void arp_stats(u_long, const char *, int, int);
+void divert_stats(u_long, const char *, int, int);
+void ip_stats(u_long, const char *, int, int);
+void icmp_stats(u_long, const char *, int, int);
+void igmp_stats(u_long, const char *, int, int);
+void pim_stats(u_long, const char *, int, int);
+void carp_stats(u_long, const char *, int, int);
+void pfsync_stats(u_long, const char *, int, int);
+void pflow_stats(u_long, const char *, int, int);
+#ifdef IPSEC
+void ipsec_stats(u_long, const char *, int, int);
+void esp_stats(u_long, const char *, int, int);
+void ah_stats(u_long, const char *, int, int);
+void ipcomp_stats(u_long, const char *, int, int);
+#endif
+
+#ifdef INET
+struct in_addr;
+
+char *inetname(struct in_addr *);
+#endif
+
+#ifdef INET6
+struct in6_addr;
+
+char *inet6name(struct in6_addr *);
+void ip6_stats(u_long, const char *, int, int);
+void ip6_ifstats(char *);
+void icmp6_stats(u_long, const char *, int, int);
+void icmp6_ifstats(char *);
+void pim6_stats(u_long, const char *, int, int);
+void rip6_stats(u_long, const char *, int, int);
+void mroute6pr(void);
+void mrt6_stats(void);
+
+struct sockaddr_in6;
+struct in6_addr;
+void in6_fillscopeid(struct sockaddr_in6 *);
+void inet6print(const char *, struct in6_addr *, int, const char *, int);
+#endif /*INET6*/
+
+#ifdef IPSEC
+void pfkey_stats(u_long, const char *, int, int);
+#endif
+
+void mbpr(void *, u_long);
+
+void netisr_stats(void);
+
+void hostpr(u_long, u_long);
+void impstats(u_long, u_long);
+
+void intpr(void (*)(char *), int);
+
+void pr_family(int);
+void rt_stats(void);
+
+char *routename(struct sockaddr *, int);
+const char *netname(struct sockaddr *, struct sockaddr *);
+void routepr(int, int);
+int p_sockaddr(const char *name, struct sockaddr *sa,
+ struct sockaddr *mask, int flags, int width);
+const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
+ int flags);
+
+#ifdef NETGRAPH
+void netgraphprotopr(u_long, const char *, int, int);
+#endif
+
+void unixpr(u_long, u_long, u_long, u_long, u_long, bool *);
+
+void mroutepr(void);
+void mrt_stats(void);
+void bpf_stats(char *);
+void nhops_print(int fibnum, int af);
+void nhgrp_print(int fibnum, int af);
diff --git a/usr.bin/netstat/nhgrp.c b/usr.bin/netstat/nhgrp.c
new file mode 100644
index 000000000000..7cbaa1af94e3
--- /dev/null
+++ b/usr.bin/netstat/nhgrp.c
@@ -0,0 +1,352 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Alexander V. Chernikov
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <net/route/nhop.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+#include <libutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "common.h"
+
+#define WID_GW_DEFAULT(af) (((af) == AF_INET6) ? 40 : 18)
+
+static int wid_gw;
+static int wid_if = 10;
+static int wid_nhidx = 8;
+static int wid_refcnt = 8;
+
+struct nhop_entry {
+ char gw[64];
+ char ifname[IFNAMSIZ];
+};
+
+struct nhop_map {
+ struct nhop_entry *ptr;
+ size_t size;
+};
+static struct nhop_map global_nhop_map;
+
+static struct ifmap_entry *ifmap;
+static size_t ifmap_size;
+
+static struct nhop_entry *
+nhop_get(struct nhop_map *map, uint32_t idx)
+{
+
+ if (idx >= map->size)
+ return (NULL);
+ if (*map->ptr[idx].ifname == '\0')
+ return (NULL);
+ return &map->ptr[idx];
+}
+
+static void
+print_nhgroup_header(int af1 __unused)
+{
+
+ xo_emit("{T:/%-*.*s}{T:/%-*.*s}{T:/%*.*s}{T:/%*.*s}{T:/%*.*s}"
+ "{T:/%*.*s}{T:/%*s}\n",
+ wid_nhidx, wid_nhidx, "GrpIdx",
+ wid_nhidx, wid_nhidx, "NhIdx",
+ wid_nhidx, wid_nhidx, "Weight",
+ wid_nhidx, wid_nhidx, "Slots",
+ wid_gw, wid_gw, "Gateway",
+ wid_if, wid_if, "Netif",
+ wid_refcnt, "Refcnt");
+}
+
+static void
+print_padding(char sym, int len)
+{
+ char buffer[56];
+
+ memset(buffer, sym, sizeof(buffer));
+ buffer[0] = '{';
+ buffer[1] = 'P';
+ buffer[2] = ':';
+ buffer[3] = ' ';
+ buffer[len + 3] = '}';
+ buffer[len + 4] = '\0';
+ xo_emit(buffer);
+}
+
+
+static void
+print_nhgroup_entry_sysctl(const char *name, struct rt_msghdr *rtm,
+ struct nhgrp_external *nhge)
+{
+ char buffer[128];
+ struct nhop_entry *ne;
+ struct nhgrp_nhop_external *ext_cp, *ext_dp;
+ struct nhgrp_container *nhg_cp, *nhg_dp;
+
+ nhg_cp = (struct nhgrp_container *)(nhge + 1);
+ if (nhg_cp->nhgc_type != NHG_C_TYPE_CNHOPS || nhg_cp->nhgc_subtype != 0)
+ return;
+ ext_cp = (struct nhgrp_nhop_external *)(nhg_cp + 1);
+
+ nhg_dp = (struct nhgrp_container *)((char *)nhg_cp + nhg_cp->nhgc_len);
+ if (nhg_dp->nhgc_type != NHG_C_TYPE_DNHOPS || nhg_dp->nhgc_subtype != 0)
+ return;
+ ext_dp = (struct nhgrp_nhop_external *)(nhg_dp + 1);
+
+ xo_open_instance(name);
+
+ snprintf(buffer, sizeof(buffer), "{[:-%d}{:nhgrp-index/%%lu}{]:} ", wid_nhidx);
+
+ xo_emit(buffer, nhge->nhg_idx);
+
+ /* nhidx */
+ print_padding('-', wid_nhidx);
+ /* weight */
+ print_padding('-', wid_nhidx);
+ /* slots */
+ print_padding('-', wid_nhidx);
+ print_padding('-', wid_gw);
+ print_padding('-', wid_if);
+ xo_emit("{t:nhg-refcnt/%*lu}", wid_refcnt, nhge->nhg_refcount);
+ xo_emit("\n");
+
+ xo_open_list("nhop-weights");
+ for (uint32_t i = 0; i < nhg_cp->nhgc_count; i++) {
+ /* TODO: optimize slots calculations */
+ uint32_t slots = 0;
+ for (uint32_t sidx = 0; sidx < nhg_dp->nhgc_count; sidx++) {
+ if (ext_dp[sidx].nh_idx == ext_cp[i].nh_idx)
+ slots++;
+ }
+ xo_open_instance("nhop-weight");
+ print_padding(' ', wid_nhidx);
+ // nh index
+ xo_emit("{t:nh-index/%*lu}", wid_nhidx, ext_cp[i].nh_idx);
+ xo_emit("{t:nh-weight/%*lu}", wid_nhidx, ext_cp[i].nh_weight);
+ xo_emit("{t:nh-slots/%*lu}", wid_nhidx, slots);
+ ne = nhop_get(&global_nhop_map, ext_cp[i].nh_idx);
+ if (ne != NULL) {
+ xo_emit("{t:nh-gw/%*.*s}", wid_gw, wid_gw, ne->gw);
+ xo_emit("{t:nh-interface/%*.*s}", wid_if, wid_if, ne->ifname);
+ }
+ xo_emit("\n");
+ xo_close_instance("nhop-weight");
+ }
+ xo_close_list("nhop-weights");
+ xo_close_instance(name);
+}
+
+static int
+cmp_nhg_idx(const void *_a, const void *_b)
+{
+ const struct nhops_map *a, *b;
+
+ a = _a;
+ b = _b;
+
+ if (a->idx > b->idx)
+ return (1);
+ else if (a->idx < b->idx)
+ return (-1);
+ return (0);
+}
+
+static void
+dump_nhgrp_sysctl(int fibnum, int af, struct nhops_dump *nd)
+{
+ size_t needed;
+ int mib[7];
+ char *buf, *next, *lim;
+ struct rt_msghdr *rtm;
+ struct nhgrp_external *nhg;
+ struct nhops_map *nhg_map;
+ size_t nhg_count, nhg_size;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = af;
+ mib[4] = NET_RT_NHGRP;
+ mib[5] = 0;
+ mib[6] = fibnum;
+ if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.nhgrpdump.%d estimate",
+ af, fibnum);
+ if ((buf = malloc(needed)) == NULL)
+ xo_errx(EX_OSERR, "malloc(%lu)", (unsigned long)needed);
+ if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.nhgrpdump.%d", af, fibnum);
+ lim = buf + needed;
+
+ /*
+ * nexhops groups are received unsorted. Collect everything first,
+ * and sort prior displaying.
+ */
+ nhg_count = 0;
+ nhg_size = 16;
+ nhg_map = calloc(nhg_size, sizeof(struct nhops_map));
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+
+ if (nhg_count >= nhg_size) {
+ nhg_size *= 2;
+ nhg_map = realloc(nhg_map, nhg_size * sizeof(struct nhops_map));
+ }
+
+ nhg = (struct nhgrp_external *)(rtm + 1);
+ nhg_map[nhg_count].idx = nhg->nhg_idx;
+ nhg_map[nhg_count].rtm = rtm;
+ nhg_count++;
+ }
+
+ if (nhg_count > 0)
+ qsort(nhg_map, nhg_count, sizeof(struct nhops_map), cmp_nhg_idx);
+ nd->nh_buf = buf;
+ nd->nh_count = nhg_count;
+ nd->nh_map = nhg_map;
+}
+
+static void
+print_nhgrp_sysctl(int fibnum, int af)
+{
+ struct nhops_dump nd;
+ struct nhgrp_external *nhg;
+ struct rt_msghdr *rtm;
+
+ dump_nhgrp_sysctl(fibnum, af, &nd);
+
+ xo_open_container("nhgrp-table");
+ xo_open_list("rt-family");
+ if (nd.nh_count > 0) {
+ wid_gw = WID_GW_DEFAULT(af);
+ xo_open_instance("rt-family");
+ pr_family(af);
+ xo_open_list("nhgrp-entry");
+
+ print_nhgroup_header(af);
+
+ for (size_t i = 0; i < nd.nh_count; i++) {
+ rtm = nd.nh_map[i].rtm;
+ nhg = (struct nhgrp_external *)(rtm + 1);
+ print_nhgroup_entry_sysctl("nhgrp-entry", rtm, nhg);
+ }
+ }
+ xo_close_list("rt-family");
+ xo_close_container("nhgrp-table");
+ free(nd.nh_buf);
+}
+
+static void
+update_global_map(struct nhop_external *nh)
+{
+ char iface_name[128];
+ char gw_addr[64];
+ struct nhop_addrs *na;
+ struct sockaddr *sa_gw;
+
+ na = (struct nhop_addrs *)((char *)nh + nh->nh_len);
+ sa_gw = (struct sockaddr *)((char *)na + na->gw_sa_off);
+
+ memset(iface_name, 0, sizeof(iface_name));
+ if (nh->ifindex < (uint32_t)ifmap_size) {
+ strlcpy(iface_name, ifmap[nh->ifindex].ifname,
+ sizeof(iface_name));
+ if (*iface_name == '\0')
+ strlcpy(iface_name, "---", sizeof(iface_name));
+ }
+
+ if (nh->nh_flags & NHF_GATEWAY) {
+ const char *cp;
+ cp = fmt_sockaddr(sa_gw, NULL, RTF_HOST);
+ strlcpy(gw_addr, cp, sizeof(gw_addr));
+ } else
+ snprintf(gw_addr, sizeof(gw_addr), "%s/resolve", iface_name);
+
+ nhop_map_update(&global_nhop_map, nh->nh_idx, gw_addr, iface_name);
+}
+
+static void
+prepare_nh_map(int fibnum, int af)
+{
+ struct nhops_dump nd;
+ struct nhop_external *nh;
+ struct rt_msghdr *rtm;
+
+ dump_nhops_sysctl(fibnum, af, &nd);
+
+ for (size_t i = 0; i < nd.nh_count; i++) {
+ rtm = nd.nh_map[i].rtm;
+ nh = (struct nhop_external *)(rtm + 1);
+ update_global_map(nh);
+ }
+
+ free(nd.nh_buf);
+}
+
+void
+nhgrp_print(int fibnum, int af)
+{
+ size_t intsize;
+ int numfibs;
+
+ intsize = sizeof(int);
+ if (fibnum == -1 &&
+ sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
+ fibnum = 0;
+ if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
+ numfibs = 1;
+ if (fibnum < 0 || fibnum > numfibs - 1)
+ xo_errx(EX_USAGE, "%d: invalid fib", fibnum);
+
+ ifmap = prepare_ifmap(&ifmap_size);
+ prepare_nh_map(fibnum, af);
+
+ xo_open_container("route-nhgrp-information");
+ xo_emit("{T:Nexthop groups data}");
+ if (fibnum)
+ xo_emit(" ({L:fib}: {:fib/%d})", fibnum);
+ xo_emit("\n");
+ print_nhgrp_sysctl(fibnum, af);
+ xo_close_container("route-nhgrp-information");
+}
+
diff --git a/usr.bin/netstat/nhops.c b/usr.bin/netstat/nhops.c
new file mode 100644
index 000000000000..48ec2006994e
--- /dev/null
+++ b/usr.bin/netstat/nhops.c
@@ -0,0 +1,477 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <net/route/nhop.h>
+
+#include <netinet/in.h>
+#include <netgraph/ng_socket.h>
+
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "common.h"
+
+/* column widths; each followed by one space */
+#define WID_IF_DEFAULT (Wflag ? IFNAMSIZ : 12) /* width of netif column */
+#ifndef INET6
+#define WID_DST_DEFAULT(af) 18 /* width of destination column */
+#define WID_GW_DEFAULT(af) 18 /* width of gateway column */
+#else
+#define WID_DST_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18)
+#define WID_GW_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
+#endif /*INET6*/
+static int wid_dst;
+static int wid_gw;
+static int wid_flags;
+static int wid_pksent;
+static int wid_mtu;
+static int wid_if;
+static int wid_nhidx;
+static int wid_nhtype;
+static int wid_refcnt;
+static int wid_prepend;
+
+static struct bits nh_bits[] = {
+ { NHF_REJECT, 'R', "reject" },
+ { NHF_BLACKHOLE,'B', "blackhole" },
+ { NHF_REDIRECT, 'r', "redirect" },
+ { NHF_GATEWAY, 'G', "gateway" },
+ { NHF_DEFAULT, 'd', "default" },
+ { NHF_BROADCAST,'b', "broadcast" },
+ { 0 , 0, NULL }
+};
+
+static char *nh_types[] = {
+ "empty", /* 0 */
+ "v4/resolve", /* 1 */
+ "v4/gw",
+ "v6/resolve",
+ "v6/gw"
+};
+
+struct nhop_entry {
+ char gw[64];
+ char ifname[IFNAMSIZ];
+};
+
+struct nhop_map {
+ struct nhop_entry *ptr;
+ size_t size;
+};
+static struct nhop_map global_nhop_map;
+
+static struct nhop_entry *nhop_get(struct nhop_map *map, uint32_t idx);
+
+
+static struct ifmap_entry *ifmap;
+static size_t ifmap_size;
+
+static void
+print_sockaddr_buf(char *buf, size_t bufsize, const struct sockaddr *sa)
+{
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr,
+ buf, bufsize);
+ break;
+ case AF_INET6:
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
+ buf, bufsize);
+ break;
+ default:
+ snprintf(buf, bufsize, "unknown:%d", sa->sa_family);
+ break;
+ }
+}
+
+static int
+print_addr(const char *name, const char *addr, int width)
+{
+ char buf[128];
+ int protrusion;
+
+ if (width < 0) {
+ snprintf(buf, sizeof(buf), "{:%s/%%s} ", name);
+ xo_emit(buf, addr);
+ protrusion = 0;
+ } else {
+ if (Wflag != 0 || numeric_addr) {
+ snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%s}{]:} ",
+ -width, name);
+ xo_emit(buf, addr);
+ protrusion = strlen(addr) - width;
+ if (protrusion < 0)
+ protrusion = 0;
+ } else {
+ snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%-.*s}{]:} ",
+ -width, name);
+ xo_emit(buf, width, addr);
+ protrusion = 0;
+ }
+ }
+ return (protrusion);
+}
+
+
+static void
+print_nhop_header(int af1 __unused)
+{
+
+ if (Wflag) {
+ xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} "
+ "{T:/%*.*s} {T:/%-*.*s} {T:/%*.*s} {T:/%*.*s} {T:/%*.*s} {T:/%*s}\n",
+ wid_nhidx, wid_nhidx, "Idx",
+ wid_nhtype, wid_nhtype, "Type",
+ wid_dst, wid_dst, "IFA",
+ wid_gw, wid_gw, "Gateway",
+ wid_flags, wid_flags, "Flags",
+ wid_pksent, wid_pksent, "Use",
+ wid_mtu, wid_mtu, "Mtu",
+ wid_if, wid_if, "Netif",
+ wid_if, wid_if, "Addrif",
+ wid_refcnt, wid_refcnt, "Refcnt",
+ wid_prepend, "Prepend");
+ } else {
+ xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} "
+ " {T:/%*s}\n",
+ wid_nhidx, wid_nhidx, "Idx",
+ wid_dst, wid_dst, "IFA",
+ wid_gw, wid_gw, "Gateway",
+ wid_flags, wid_flags, "Flags",
+ wid_if, wid_if, "Netif",
+ wid_prepend, "Refcnt");
+ }
+}
+
+void
+nhop_map_update(struct nhop_map *map, uint32_t idx, char *gw, char *ifname)
+{
+ if (idx >= map->size) {
+ uint32_t new_size;
+ size_t sz;
+ if (map->size == 0)
+ new_size = 32;
+ else
+ new_size = map->size * 2;
+ if (new_size <= idx)
+ new_size = roundup2(idx + 1, 32);
+
+ sz = new_size * (sizeof(struct nhop_entry));
+ if ((map->ptr = realloc(map->ptr, sz)) == NULL)
+ xo_errx(EX_OSERR, "realloc(%zu) failed", sz);
+
+ memset(&map->ptr[map->size], 0, (new_size - map->size) * sizeof(struct nhop_entry));
+ map->size = new_size;
+ }
+
+ strlcpy(map->ptr[idx].ifname, ifname, sizeof(map->ptr[idx].ifname));
+ strlcpy(map->ptr[idx].gw, gw, sizeof(map->ptr[idx].gw));
+}
+
+static struct nhop_entry *
+nhop_get(struct nhop_map *map, uint32_t idx)
+{
+
+ if (idx >= map->size)
+ return (NULL);
+ if (*map->ptr[idx].ifname == '\0')
+ return (NULL);
+ return &map->ptr[idx];
+}
+
+static void
+print_nhop_entry_sysctl(const char *name, struct rt_msghdr *rtm, struct nhop_external *nh)
+{
+ char buffer[128];
+ char iface_name[128];
+ int protrusion;
+ char gw_addr[64];
+ struct nhop_addrs *na;
+ struct sockaddr *sa_gw, *sa_ifa;
+
+ xo_open_instance(name);
+
+ snprintf(buffer, sizeof(buffer), "{[:-%d}{:index/%%lu}{]:} ", wid_nhidx);
+ //xo_emit("{t:index/%-lu} ", wid_nhidx, nh->nh_idx);
+ xo_emit(buffer, nh->nh_idx);
+
+ if (Wflag) {
+ char *cp = nh_types[nh->nh_type];
+ xo_emit("{t:type_str/%*s} ", wid_nhtype, cp);
+ }
+ memset(iface_name, 0, sizeof(iface_name));
+ if (nh->ifindex < (uint32_t)ifmap_size) {
+ strlcpy(iface_name, ifmap[nh->ifindex].ifname,
+ sizeof(iface_name));
+ if (*iface_name == '\0')
+ strlcpy(iface_name, "---", sizeof(iface_name));
+ }
+
+ na = (struct nhop_addrs *)((char *)nh + nh->nh_len);
+ //inet_ntop(nh->nh_family, &nh->nh_src, src_addr, sizeof(src_addr));
+ //protrusion = p_addr("ifa", src_addr, wid_dst);
+ sa_gw = (struct sockaddr *)((char *)na + na->gw_sa_off);
+ sa_ifa = (struct sockaddr *)((char *)na + na->src_sa_off);
+ protrusion = p_sockaddr("ifa", sa_ifa, NULL, RTF_HOST, wid_dst);
+
+ if (nh->nh_flags & NHF_GATEWAY) {
+ const char *cp;
+ cp = fmt_sockaddr(sa_gw, NULL, RTF_HOST);
+ strlcpy(gw_addr, cp, sizeof(gw_addr));
+ } else
+ snprintf(gw_addr, sizeof(gw_addr), "%s/resolve", iface_name);
+ protrusion = print_addr("gateway", gw_addr, wid_dst - protrusion);
+
+ nhop_map_update(&global_nhop_map, nh->nh_idx, gw_addr, iface_name);
+
+ snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ",
+ wid_flags - protrusion);
+
+ //p_nhflags(nh->nh_flags, buffer);
+ print_flags_generic(rtm->rtm_flags, rt_bits, buffer, "rt_flags_pretty");
+
+ if (Wflag) {
+ xo_emit("{t:use/%*lu} ", wid_pksent, nh->nh_pksent);
+ xo_emit("{t:mtu/%*lu} ", wid_mtu, nh->nh_mtu);
+ }
+ //printf("IDX: %d IFACE: %s FAMILY: %d TYPE: %d FLAGS: %X GW \n");
+
+ if (Wflag)
+ xo_emit("{t:interface-name/%*s}", wid_if, iface_name);
+ else
+ xo_emit("{t:interface-name/%*.*s}", wid_if, wid_if, iface_name);
+
+ memset(iface_name, 0, sizeof(iface_name));
+ if (nh->aifindex < (uint32_t)ifmap_size && nh->ifindex != nh->aifindex) {
+ strlcpy(iface_name, ifmap[nh->aifindex].ifname,
+ sizeof(iface_name));
+ if (*iface_name == '\0')
+ strlcpy(iface_name, "---", sizeof(iface_name));
+ }
+ if (Wflag)
+ xo_emit("{t:address-interface-name/%*s}", wid_if, iface_name);
+
+ xo_emit("{t:refcount/%*lu} ", wid_refcnt, nh->nh_refcount);
+ if (Wflag && nh->prepend_len) {
+ int max_bytes = MIN(nh->prepend_len, sizeof(buffer) / 2 - 1);
+ for (int i = 0; i < max_bytes; i++)
+ snprintf(&buffer[i * 2], 3, "%02X", nh->nh_prepend[i]);
+ xo_emit(" {:nhop-prepend/%*s}", wid_prepend, buffer);
+ }
+
+ xo_emit("\n");
+ xo_close_instance(name);
+}
+
+static int
+cmp_nh_idx(const void *_a, const void *_b)
+{
+ const struct nhops_map *a, *b;
+
+ a = _a;
+ b = _b;
+
+ if (a->idx > b->idx)
+ return (1);
+ else if (a->idx < b->idx)
+ return (-1);
+ return (0);
+}
+
+void
+dump_nhops_sysctl(int fibnum, int af, struct nhops_dump *nd)
+{
+ size_t needed;
+ int mib[7];
+ char *buf, *next, *lim;
+ struct rt_msghdr *rtm;
+ struct nhop_external *nh;
+ struct nhops_map *nh_map;
+ size_t nh_count, nh_size;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = af;
+ mib[4] = NET_RT_NHOP;
+ mib[5] = 0;
+ mib[6] = fibnum;
+ if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.nhdump.%d estimate", af,
+ fibnum);
+ if ((buf = malloc(needed)) == NULL)
+ xo_errx(EX_OSERR, "malloc(%lu)", (unsigned long)needed);
+ if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.nhdump.%d", af, fibnum);
+ lim = buf + needed;
+
+ /*
+ * nexhops are received unsorted. Collect everything first, sort and then display
+ * sorted.
+ */
+ nh_count = 0;
+ nh_size = 16;
+ nh_map = calloc(nh_size, sizeof(struct nhops_map));
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+
+ if (nh_count >= nh_size) {
+ nh_size *= 2;
+ nh_map = realloc(nh_map, nh_size * sizeof(struct nhops_map));
+ }
+
+ nh = (struct nhop_external *)(rtm + 1);
+ nh_map[nh_count].idx = nh->nh_idx;
+ nh_map[nh_count].rtm = rtm;
+ nh_count++;
+ }
+
+ if (nh_count > 0)
+ qsort(nh_map, nh_count, sizeof(struct nhops_map), cmp_nh_idx);
+ nd->nh_buf = buf;
+ nd->nh_count = nh_count;
+ nd->nh_map = nh_map;
+}
+
+static void
+print_nhops_sysctl(int fibnum, int af)
+{
+ struct nhops_dump nd;
+ struct nhop_external *nh;
+ int fam;
+ struct rt_msghdr *rtm;
+
+ dump_nhops_sysctl(fibnum, af, &nd);
+
+ xo_open_container("nhop-table");
+ xo_open_list("rt-family");
+ if (nd.nh_count > 0) {
+ nh = (struct nhop_external *)(nd.nh_map[0].rtm + 1);
+ fam = nh->nh_family;
+
+ wid_dst = WID_GW_DEFAULT(fam);
+ wid_gw = WID_GW_DEFAULT(fam);
+ wid_nhidx = 5;
+ wid_nhtype = 12;
+ wid_refcnt = 6;
+ wid_flags = 6;
+ wid_pksent = 8;
+ wid_mtu = 6;
+ wid_if = WID_IF_DEFAULT;
+ xo_open_instance("rt-family");
+ pr_family(fam);
+ xo_open_list("nh-entry");
+
+ print_nhop_header(fam);
+
+ for (size_t i = 0; i < nd.nh_count; i++) {
+ rtm = nd.nh_map[i].rtm;
+ nh = (struct nhop_external *)(rtm + 1);
+ print_nhop_entry_sysctl("nh-entry", rtm, nh);
+ }
+
+ xo_close_list("nh-entry");
+ xo_close_instance("rt-family");
+ }
+ xo_close_list("rt-family");
+ xo_close_container("nhop-table");
+ free(nd.nh_buf);
+}
+
+static void
+p_nhflags(int f, const char *format)
+{
+ struct bits *p;
+ char *pretty_name = "nh_flags_pretty";
+
+ xo_emit(format, fmt_flags(nh_bits, f));
+
+ xo_open_list(pretty_name);
+ for (p = nh_bits; p->b_mask; p++)
+ if (p->b_mask & f)
+ xo_emit("{le:nh_flags_pretty/%s}", p->b_name);
+ xo_close_list(pretty_name);
+}
+
+void
+nhops_print(int fibnum, int af)
+{
+ size_t intsize;
+ int numfibs;
+
+ intsize = sizeof(int);
+ if (fibnum == -1 &&
+ sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
+ fibnum = 0;
+ if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
+ numfibs = 1;
+ if (fibnum < 0 || fibnum > numfibs - 1)
+ xo_errx(EX_USAGE, "%d: invalid fib", fibnum);
+
+ ifmap = prepare_ifmap(&ifmap_size);
+
+ xo_open_container("route-nhop-information");
+ xo_emit("{T:Nexthop data}");
+ if (fibnum)
+ xo_emit(" ({L:fib}: {:fib/%d})", fibnum);
+ xo_emit("\n");
+ print_nhops_sysctl(fibnum, af);
+ xo_close_container("route-nhop-information");
+}
+
diff --git a/usr.bin/netstat/nlist_symbols b/usr.bin/netstat/nlist_symbols
new file mode 100644
index 000000000000..30cdd69bc54b
--- /dev/null
+++ b/usr.bin/netstat/nlist_symbols
@@ -0,0 +1,50 @@
+#
+# module_name symbol_name
+all _ahstat
+all _arpstat
+all _carpstats
+all _espstat
+all _icmp6stat
+all _icmpstat
+all _igmpstat
+all _ip6stat
+all _ipcompstat
+all _ipsec4stat
+all _ipsec6stat
+all _ipstat
+all _mf6ctable
+all _mfchashtbl
+all _mfctablesize
+all _mif6table
+all _mrt6stat
+all _mrtstat
+all _netisr_bindthreads
+all _netisr_defaultqlimit
+all _netisr_dispatch_policy
+all _netisr_maxprot
+all _netisr_maxqlimit
+all _netisr_maxthreads
+all _netisr_proto
+all _ngsocklist
+all _nws
+all _nws_array
+all _nws_count
+all _pfkeystat
+all _pfsyncstats
+all _pflowstats
+all _pim6stat
+all _pimstat
+all _rip6stat
+all _rtree
+all _rtstat
+all _sctpstat
+all _sfstat
+all _tcpstat
+all _tcps_states
+all _udpstat
+all _unp_count
+all _unp_dhead
+all _unp_gencnt
+all _unp_shead
+all _unp_sphead
+all _viftable
diff --git a/usr.bin/netstat/pfkey.c b/usr.bin/netstat/pfkey.c
new file mode 100644
index 000000000000..27dd61a0c4e5
--- /dev/null
+++ b/usr.bin/netstat/pfkey.c
@@ -0,0 +1,200 @@
+/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */
+/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+/*-
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#include <netipsec/keysock.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+
+static const char *pfkey_msgtypenames[] = {
+ "reserved", "getspi", "update", "add", "delete",
+ "get", "acquire", "register", "expire", "flush",
+ "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
+ "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
+ "x_spdsetidx", "x_spdexpire", "x_spddelete2"
+};
+
+static const char *pfkey_msgtype_names (int);
+
+
+static const char *
+pfkey_msgtype_names(int x)
+{
+ const int max = nitems(pfkey_msgtypenames);
+ static char buf[20];
+
+ if (x < max && pfkey_msgtypenames[x])
+ return pfkey_msgtypenames[x];
+ snprintf(buf, sizeof(buf), "#%d", x);
+ return buf;
+}
+
+void
+pfkey_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
+{
+ struct pfkeystat pfkeystat;
+ unsigned first, type;
+
+ if (off == 0)
+ return;
+ xo_emit("{T:/%s}:\n", name);
+ xo_open_container(name);
+ kread_counters(off, (char *)&pfkeystat, sizeof(pfkeystat));
+
+#define p(f, m) if (pfkeystat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)pfkeystat.f, plural(pfkeystat.f))
+
+ /* userland -> kernel */
+ p(out_total, "\t{:sent-requests/%ju} "
+ "{N:/request%s sent from userland}\n");
+ p(out_bytes, "\t{:sent-bytes/%ju} "
+ "{N:/byte%s sent from userland}\n");
+ for (first = 1, type = 0;
+ type<sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
+ type++) {
+ if (pfkeystat.out_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ xo_open_list("output-histogram");
+ xo_emit("\t{T:histogram by message type}:\n");
+ first = 0;
+ }
+ xo_open_instance("output-histogram");
+ xo_emit("\t\t{k::type/%s}: {:count/%ju}\n",
+ pfkey_msgtype_names(type),
+ (uintmax_t)pfkeystat.out_msgtype[type]);
+ xo_close_instance("output-histogram");
+ }
+ if (!first)
+ xo_close_list("output-histogram");
+
+ p(out_invlen, "\t{:dropped-bad-length/%ju} "
+ "{N:/message%s with invalid length field}\n");
+ p(out_invver, "\t{:dropped-bad-version/%ju} "
+ "{N:/message%s with invalid version field}\n");
+ p(out_invmsgtype, "\t{:dropped-bad-type/%ju} "
+ "{N:/message%s with invalid message type field}\n");
+ p(out_tooshort, "\t{:dropped-too-short/%ju} "
+ "{N:/message%s too short}\n");
+ p(out_nomem, "\t{:dropped-no-memory/%ju} "
+ "{N:/message%s with memory allocation failure}\n");
+ p(out_dupext, "\t{:dropped-duplicate-extension/%ju} "
+ "{N:/message%s with duplicate extension}\n");
+ p(out_invexttype, "\t{:dropped-bad-extension/%ju} "
+ "{N:/message%s with invalid extension type}\n");
+ p(out_invsatype, "\t{:dropped-bad-sa-type/%ju} "
+ "{N:/message%s with invalid sa type}\n");
+ p(out_invaddr, "\t{:dropped-bad-address-extension/%ju} "
+ "{N:/message%s with invalid address extension}\n");
+
+ /* kernel -> userland */
+ p(in_total, "\t{:received-requests/%ju} "
+ "{N:/request%s sent to userland}\n");
+ p(in_bytes, "\t{:received-bytes/%ju} "
+ "{N:/byte%s sent to userland}\n");
+ for (first = 1, type = 0;
+ type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
+ type++) {
+ if (pfkeystat.in_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ xo_open_list("input-histogram");
+ xo_emit("\t{T:histogram by message type}:\n");
+ first = 0;
+ }
+ xo_open_instance("input-histogram");
+ xo_emit("\t\t{k:type/%s}: {:count/%ju}\n",
+ pfkey_msgtype_names(type),
+ (uintmax_t)pfkeystat.in_msgtype[type]);
+ xo_close_instance("input-histogram");
+ }
+ if (!first)
+ xo_close_list("input-histogram");
+ p(in_msgtarget[KEY_SENDUP_ONE], "\t{:received-one-socket/%ju} "
+ "{N:/message%s toward single socket}\n");
+ p(in_msgtarget[KEY_SENDUP_ALL], "\t{:received-all-sockets/%ju} "
+ "{N:/message%s toward all sockets}\n");
+ p(in_msgtarget[KEY_SENDUP_REGISTERED],
+ "\t{:received-registered-sockets/%ju} "
+ "{N:/message%s toward registered sockets}\n");
+ p(in_nomem, "\t{:discarded-no-memory/%ju} "
+ "{N:/message%s with memory allocation failure}\n");
+#undef p
+ xo_close_container(name);
+}
+#endif /* IPSEC */
diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c
new file mode 100644
index 000000000000..697c7ba2e9e1
--- /dev/null
+++ b/usr.bin/netstat/route.c
@@ -0,0 +1,724 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netgraph/ng_socket.h>
+
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "common.h"
+#include "nl_defs.h"
+
+/*
+ * Definitions for showing gateway flags.
+ */
+struct bits rt_bits[] = {
+ { RTF_UP, 'U', "up" },
+ { RTF_GATEWAY, 'G', "gateway" },
+ { RTF_HOST, 'H', "host" },
+ { RTF_REJECT, 'R', "reject" },
+ { RTF_DYNAMIC, 'D', "dynamic" },
+ { RTF_MODIFIED, 'M', "modified" },
+ { RTF_DONE, 'd', "done" }, /* Completed -- for routing msgs only */
+ { RTF_XRESOLVE, 'X', "xresolve" },
+ { RTF_STATIC, 'S', "static" },
+ { RTF_PROTO1, '1', "proto1" },
+ { RTF_PROTO2, '2', "proto2" },
+ { RTF_PROTO3, '3', "proto3" },
+ { RTF_BLACKHOLE,'B', "blackhole" },
+ { RTF_BROADCAST,'b', "broadcast" },
+#ifdef RTF_LLINFO
+ { RTF_LLINFO, 'L', "llinfo" },
+#endif
+ { 0 , 0, NULL }
+};
+
+#ifdef WITHOUT_NETLINK
+static struct ifmap_entry *ifmap;
+static size_t ifmap_size;
+#endif
+static struct timespec uptime;
+
+static const char *netname4(in_addr_t, in_addr_t);
+#ifdef INET6
+static const char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *);
+#endif
+#ifdef WITHOUT_NETLINK
+static void p_rtable_sysctl(int, int);
+static void p_rtentry_sysctl(const char *name, struct rt_msghdr *);
+#endif
+static void domask(char *, size_t, u_long);
+
+const uint32_t rt_default_weight = RT_DEFAULT_WEIGHT;
+
+/*
+ * Print routing tables.
+ */
+void
+routepr(int fibnum, int af)
+{
+ size_t intsize;
+ int numfibs;
+
+ if (live == 0)
+ return;
+
+ intsize = sizeof(int);
+ if (fibnum == -1 &&
+ sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
+ fibnum = 0;
+ if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
+ numfibs = 1;
+ if (fibnum < 0 || fibnum > numfibs - 1)
+ xo_errx(EX_USAGE, "%d: invalid fib", fibnum);
+ /*
+ * Since kernel & userland use different timebase
+ * (time_uptime vs time_second) and we are reading kernel memory
+ * directly we should do rt_expire --> expire_time conversion.
+ */
+ if (clock_gettime(CLOCK_UPTIME, &uptime) < 0)
+ xo_err(EX_OSERR, "clock_gettime() failed");
+
+ xo_open_container("route-information");
+ xo_emit("{T:Routing tables}");
+ if (fibnum)
+ xo_emit(" ({L:fib}: {:fib/%d})", fibnum);
+ xo_emit("\n");
+#ifdef WITHOUT_NETLINK
+ p_rtable_sysctl(fibnum, af);
+#else
+ p_rtable_netlink(fibnum, af);
+#endif
+ xo_close_container("route-information");
+}
+
+
+/*
+ * Print address family header before a section of the routing table.
+ */
+void
+pr_family(int af1)
+{
+ const char *afname;
+
+ switch (af1) {
+ case AF_INET:
+ afname = "Internet";
+ break;
+#ifdef INET6
+ case AF_INET6:
+ afname = "Internet6";
+ break;
+#endif /*INET6*/
+ case AF_ISO:
+ afname = "ISO";
+ break;
+ case AF_CCITT:
+ afname = "X.25";
+ break;
+ case AF_NETGRAPH:
+ afname = "Netgraph";
+ break;
+ default:
+ afname = NULL;
+ break;
+ }
+ if (afname)
+ xo_emit("\n{k:address-family/%s}:\n", afname);
+ else
+ xo_emit("\n{L:Protocol Family} {k:address-family/%d}:\n", af1);
+}
+
+/* column widths; each followed by one space */
+#define WID_IF_DEFAULT (Wflag ? IFNAMSIZ : 12) /* width of netif column */
+#ifndef INET6
+#define WID_DST_DEFAULT(af) 18 /* width of destination column */
+#define WID_GW_DEFAULT(af) 18 /* width of gateway column */
+#else
+#define WID_DST_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18)
+#define WID_GW_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
+#endif /*INET6*/
+
+struct _wid wid;
+
+/*
+ * Print header for routing table columns.
+ */
+void
+pr_rthdr(int af1 __unused)
+{
+
+ if (Wflag) {
+ xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} "
+ "{T:/%*.*s} {T:/%*.*s} {T:/%*s}\n",
+ wid.dst, wid.dst, "Destination",
+ wid.gw, wid.gw, "Gateway",
+ wid.flags, wid.flags, "Flags",
+ wid.mtu, wid.mtu, "Nhop#",
+ wid.mtu, wid.mtu, "Mtu",
+ wid.iface, wid.iface, "Netif",
+ wid.expire, "Expire");
+ } else {
+ xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} "
+ "{T:/%*s}\n",
+ wid.dst, wid.dst, "Destination",
+ wid.gw, wid.gw, "Gateway",
+ wid.flags, wid.flags, "Flags",
+ wid.iface, wid.iface, "Netif",
+ wid.expire, "Expire");
+ }
+}
+
+void
+set_wid(int fam)
+{
+ wid.dst = WID_DST_DEFAULT(fam);
+ wid.gw = WID_GW_DEFAULT(fam);
+ wid.flags = 6;
+ wid.pksent = 8;
+ wid.mtu = 6;
+ wid.iface = WID_IF_DEFAULT;
+ wid.expire = 6;
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+p_rtable_sysctl(int fibnum, int af)
+{
+ size_t needed;
+ int mib[7];
+ char *buf, *next, *lim;
+ struct rt_msghdr *rtm;
+ struct sockaddr *sa;
+ int fam = AF_UNSPEC;
+ int need_table_close = false;
+
+ ifmap = prepare_ifmap(&ifmap_size);
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = af;
+ mib[4] = NET_RT_DUMP;
+ mib[5] = 0;
+ mib[6] = fibnum;
+ if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d estimate", af,
+ fibnum);
+ if ((buf = malloc(needed)) == NULL)
+ xo_errx(EX_OSERR, "malloc(%lu)", (unsigned long)needed);
+ if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0)
+ xo_err(EX_OSERR, "sysctl: net.route.0.%d.dump.%d", af, fibnum);
+ lim = buf + needed;
+ xo_open_container("route-table");
+ xo_open_list("rt-family");
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ /*
+ * Peek inside header to determine AF
+ */
+ sa = (struct sockaddr *)(rtm + 1);
+ /* Only print family first time. */
+ if (fam != sa->sa_family) {
+ if (need_table_close) {
+ xo_close_list("rt-entry");
+ xo_close_instance("rt-family");
+ }
+ need_table_close = true;
+ fam = sa->sa_family;
+ set_wid(fam);
+ xo_open_instance("rt-family");
+ pr_family(fam);
+ xo_open_list("rt-entry");
+
+ pr_rthdr(fam);
+ }
+ p_rtentry_sysctl("rt-entry", rtm);
+ }
+ if (need_table_close) {
+ xo_close_list("rt-entry");
+ xo_close_instance("rt-family");
+ }
+ xo_close_list("rt-family");
+ xo_close_container("route-table");
+ free(buf);
+}
+
+static void
+p_rtentry_sysctl(const char *name, struct rt_msghdr *rtm)
+{
+ struct sockaddr *sa, *addr[RTAX_MAX];
+ char buffer[128];
+ char prettyname[128];
+ int i, protrusion;
+
+ xo_open_instance(name);
+ sa = (struct sockaddr *)(rtm + 1);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if (rtm->rtm_addrs & (1 << i)) {
+ addr[i] = sa;
+ sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
+ }
+ }
+
+ protrusion = p_sockaddr("destination", addr[RTAX_DST],
+ addr[RTAX_NETMASK],
+ rtm->rtm_flags, wid.dst);
+ protrusion = p_sockaddr("gateway", addr[RTAX_GATEWAY], NULL, RTF_HOST,
+ wid.gw - protrusion);
+ snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ",
+ wid.flags - protrusion);
+ p_flags(rtm->rtm_flags, buffer);
+ /* Output path weight as non-visual property */
+ xo_emit("{e:weight/%u}", rtm->rtm_rmx.rmx_weight);
+ if (Wflag) {
+ /* XXX: use=0? */
+ xo_emit("{t:nhop/%*lu} ", wid.mtu, rtm->rtm_rmx.rmx_nhidx);
+
+ if (rtm->rtm_rmx.rmx_mtu != 0)
+ xo_emit("{t:mtu/%*lu} ", wid.mtu, rtm->rtm_rmx.rmx_mtu);
+ else
+ xo_emit("{P:/%*s} ", wid.mtu, "");
+ }
+
+ memset(prettyname, 0, sizeof(prettyname));
+ if (rtm->rtm_index < ifmap_size) {
+ strlcpy(prettyname, ifmap[rtm->rtm_index].ifname,
+ sizeof(prettyname));
+ if (*prettyname == '\0')
+ strlcpy(prettyname, "---", sizeof(prettyname));
+ }
+
+ if (Wflag)
+ xo_emit("{t:interface-name/%*s}", wid.iface, prettyname);
+ else
+ xo_emit("{t:interface-name/%*.*s}", wid.iface, wid.iface,
+ prettyname);
+ if (rtm->rtm_rmx.rmx_expire) {
+ time_t expire_time;
+
+ if ((expire_time = rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0)
+ xo_emit(" {:expire-time/%*d}", wid.expire,
+ (int)expire_time);
+ }
+
+ xo_emit("\n");
+ xo_close_instance(name);
+}
+#endif
+
+int
+p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask,
+ int flags, int width)
+{
+ const char *cp;
+ char buf[128];
+ int protrusion;
+
+ cp = fmt_sockaddr(sa, mask, flags);
+
+ if (width < 0) {
+ snprintf(buf, sizeof(buf), "{:%s/%%s} ", name);
+ xo_emit(buf, cp);
+ protrusion = 0;
+ } else {
+ if (Wflag != 0 || numeric_addr) {
+ snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%s}{]:} ",
+ -width, name);
+ xo_emit(buf, cp);
+ protrusion = strlen(cp) - width;
+ if (protrusion < 0)
+ protrusion = 0;
+ } else {
+ snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%-.*s}{]:} ",
+ -width, name);
+ xo_emit(buf, width, cp);
+ protrusion = 0;
+ }
+ }
+ return (protrusion);
+}
+
+const char *
+fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
+{
+ static char buf[128];
+ const char *cp;
+
+ if (sa == NULL)
+ return ("null");
+
+ switch(sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ /*
+ * The sa6->sin6_scope_id must be filled here because
+ * this sockaddr is extracted from kmem(4) directly
+ * and has KAME-specific embedded scope id in
+ * sa6->sin6_addr.s6_addr[2].
+ */
+ in6_fillscopeid(satosin6(sa));
+ /* FALLTHROUGH */
+#endif /*INET6*/
+ case AF_INET:
+ if (flags & RTF_HOST)
+ cp = routename(sa, numeric_addr);
+ else if (mask)
+ cp = netname(sa, mask);
+ else
+ cp = netname(sa, NULL);
+ break;
+ case AF_NETGRAPH:
+ {
+ strlcpy(buf, ((struct sockaddr_ng *)sa)->sg_data,
+ sizeof(buf));
+ cp = buf;
+ break;
+ }
+ case AF_LINK:
+ {
+#if 0
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+ /* Interface route. */
+ if (sdl->sdl_nlen)
+ cp = sdl->sdl_data;
+ else
+#endif
+ cp = routename(sa, 1);
+ break;
+ }
+ default:
+ {
+ u_char *s = (u_char *)sa->sa_data, *slim;
+ char *cq, *cqlim;
+
+ cq = buf;
+ slim = sa->sa_len + (u_char *) sa;
+ cqlim = cq + sizeof(buf) - sizeof(" ffff");
+ snprintf(cq, sizeof(buf), "(%d)", sa->sa_family);
+ cq += strlen(cq);
+ while (s < slim && cq < cqlim) {
+ snprintf(cq, sizeof(" ff"), " %02x", *s++);
+ cq += strlen(cq);
+ if (s < slim) {
+ snprintf(cq, sizeof("ff"), "%02x", *s++);
+ cq += strlen(cq);
+ }
+ }
+ cp = buf;
+ }
+ }
+
+ return (cp);
+}
+
+void
+p_flags(int f, const char *format)
+{
+
+ print_flags_generic(f, rt_bits, format, "flags_pretty");
+}
+
+
+char *
+routename(struct sockaddr *sa, int flags)
+{
+ static char line[NI_MAXHOST];
+ int error, f;
+
+ f = (flags) ? NI_NUMERICHOST : 0;
+ error = getnameinfo(sa, sa->sa_len, line, sizeof(line),
+ NULL, 0, f);
+ if (error) {
+ const void *src;
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ src = &satosin(sa)->sin_addr;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ src = &satosin6(sa)->sin6_addr;
+ break;
+#endif /* INET6 */
+ default:
+ return(line);
+ }
+ inet_ntop(sa->sa_family, src, line, sizeof(line) - 1);
+ return (line);
+ }
+ trimdomain(line, strlen(line));
+
+ return (line);
+}
+
+#define NSHIFT(m) ( \
+ (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \
+ (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \
+ (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \
+ 0)
+
+static void
+domask(char *dst, size_t buflen, u_long mask)
+{
+ int b, i;
+
+ if (mask == 0) {
+ *dst = '\0';
+ return;
+ }
+ i = 0;
+ for (b = 0; b < 32; b++)
+ if (mask & (1 << b)) {
+ int bb;
+
+ i = b;
+ for (bb = b+1; bb < 32; bb++)
+ if (!(mask & (1 << bb))) {
+ i = -1; /* noncontig */
+ break;
+ }
+ break;
+ }
+ if (i == -1)
+ snprintf(dst, buflen, "&0x%lx", mask);
+ else
+ snprintf(dst, buflen, "/%d", 32-i);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ */
+const char *
+netname(struct sockaddr *sa, struct sockaddr *mask)
+{
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (mask != NULL)
+ return (netname4(satosin(sa)->sin_addr.s_addr,
+ satosin(mask)->sin_addr.s_addr));
+ else
+ return (netname4(satosin(sa)->sin_addr.s_addr,
+ INADDR_ANY));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ return (netname6(satosin6(sa), satosin6(mask)));
+#endif /* INET6 */
+ default:
+ return (NULL);
+ }
+}
+
+static const char *
+netname4(in_addr_t in, in_addr_t mask)
+{
+ char *cp = 0;
+ static char line[MAXHOSTNAMELEN + sizeof("&0xffffffff")];
+ char nline[INET_ADDRSTRLEN];
+ struct netent *np = 0;
+ in_addr_t i;
+
+ if (numeric_addr < 2 && in == INADDR_ANY && mask == 0) {
+ strlcpy(line, "default", sizeof(line));
+ return (line);
+ }
+
+ /* It is ok to supply host address. */
+ in &= mask;
+
+ i = ntohl(in);
+ if (!numeric_addr && i) {
+ np = getnetbyaddr(i >> NSHIFT(ntohl(mask)), AF_INET);
+ if (np != NULL) {
+ cp = np->n_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ if (cp != NULL)
+ strlcpy(line, cp, sizeof(line));
+ else {
+ inet_ntop(AF_INET, &in, nline, sizeof(nline));
+ strlcpy(line, nline, sizeof(line));
+ domask(line + strlen(line), sizeof(line) - strlen(line), ntohl(mask));
+ }
+
+ return (line);
+}
+
+#undef NSHIFT
+
+#ifdef INET6
+void
+in6_fillscopeid(struct sockaddr_in6 *sa6)
+{
+#if defined(__KAME__)
+ /*
+ * XXX: This is a special workaround for KAME kernels.
+ * sin6_scope_id field of SA should be set in the future.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) ||
+ IN6_IS_ADDR_MC_NODELOCAL(&sa6->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) {
+ if (sa6->sin6_scope_id == 0)
+ sa6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sa6->sin6_addr.s6_addr[2]);
+ sa6->sin6_addr.s6_addr[2] = sa6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+
+/* Mask to length table. To check an invalid value, (length + 1) is used. */
+static const u_char masktolen[256] = {
+ [0xff] = 8 + 1,
+ [0xfe] = 7 + 1,
+ [0xfc] = 6 + 1,
+ [0xf8] = 5 + 1,
+ [0xf0] = 4 + 1,
+ [0xe0] = 3 + 1,
+ [0xc0] = 2 + 1,
+ [0x80] = 1 + 1,
+ [0x00] = 0 + 1,
+};
+
+static const char *
+netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask)
+{
+ static char line[NI_MAXHOST + sizeof("/xxx") - 1];
+ struct sockaddr_in6 addr;
+ char nline[NI_MAXHOST];
+ char maskbuf[sizeof("/xxx")];
+ u_char *p, *lim;
+ u_char masklen;
+ int i;
+ bool illegal = false;
+
+ if (mask) {
+ p = (u_char *)&mask->sin6_addr;
+ for (masklen = 0, lim = p + 16; p < lim; p++) {
+ if (masktolen[*p] > 0) {
+ /* -1 is required. */
+ masklen += (masktolen[*p] - 1);
+ } else
+ illegal = true;
+ }
+ if (illegal)
+ xo_error("illegal prefixlen\n");
+
+ memcpy(&addr, sa6, sizeof(addr));
+ for (i = 0; i < 16; ++i)
+ addr.sin6_addr.s6_addr[i] &=
+ mask->sin6_addr.s6_addr[i];
+ sa6 = &addr;
+ }
+ else
+ masklen = 128;
+
+ if (numeric_addr < 2 && masklen == 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
+ return("default");
+
+ getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, nline, sizeof(nline),
+ NULL, 0, NI_NUMERICHOST);
+ if (numeric_addr)
+ strlcpy(line, nline, sizeof(line));
+ else
+ getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line,
+ sizeof(line), NULL, 0, 0);
+ if (numeric_addr || strcmp(line, nline) == 0) {
+ snprintf(maskbuf, sizeof(maskbuf), "/%d", masklen);
+ strlcat(line, maskbuf, sizeof(line));
+ }
+
+ return (line);
+}
+#endif /*INET6*/
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(void)
+{
+ struct rtstat rtstat;
+
+ if (fetch_stats("net.route.stats", nl[N_RTSTAT].n_value, &rtstat,
+ sizeof(rtstat), kread_counters) != 0)
+ return;
+
+ xo_emit("{T:routing}:\n");
+
+#define p(f, m) if (rtstat.f || sflag <= 1) \
+ xo_emit(m, rtstat.f, plural(rtstat.f))
+
+ p(rts_badredirect, "\t{:bad-redirects/%ju} "
+ "{N:/bad routing redirect%s}\n");
+ p(rts_dynamic, "\t{:dynamically-created/%ju} "
+ "{N:/dynamically created route%s}\n");
+ p(rts_newgateway, "\t{:new-gateways/%ju} "
+ "{N:/new gateway%s due to redirects}\n");
+ p(rts_unreach, "\t{:unreachable-destination/%ju} "
+ "{N:/destination%s found unreachable}\n");
+ p(rts_wildcard, "\t{:wildcard-uses/%ju} "
+ "{N:/use%s of a wildcard route}\n");
+#undef p
+}
diff --git a/usr.bin/netstat/route_netlink.c b/usr.bin/netstat/route_netlink.c
new file mode 100644
index 000000000000..e7b2a1964602
--- /dev/null
+++ b/usr.bin/netstat/route_netlink.c
@@ -0,0 +1,340 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netlink/netlink.h>
+#include <netlink/netlink_route.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_route.h>
+#include <netlink/netlink_snl_route_parsers.h>
+#include <netlink/netlink_snl_route_compat.h>
+
+#include <netinet/in.h>
+#include <netgraph/ng_socket.h>
+
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+#include "common.h"
+#include "nl_defs.h"
+
+
+static void p_rtentry_netlink(struct snl_state *ss, const char *name, struct nlmsghdr *hdr);
+
+static struct ifmap_entry *ifmap;
+static size_t ifmap_size;
+
+/* Generate ifmap using netlink */
+static struct ifmap_entry *
+prepare_ifmap_netlink(struct snl_state *ss, size_t *pifmap_size)
+{
+ struct {
+ struct nlmsghdr hdr;
+ struct ifinfomsg ifmsg;
+ } msg = {
+ .hdr.nlmsg_type = RTM_GETLINK,
+ .hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+ .hdr.nlmsg_seq = snl_get_seq(ss),
+ };
+ msg.hdr.nlmsg_len = sizeof(msg);
+
+ if (!snl_send_message(ss, &msg.hdr))
+ return (NULL);
+
+ struct ifmap_entry *ifmap = NULL;
+ uint32_t ifmap_size = 0;
+ struct nlmsghdr *hdr;
+ struct snl_errmsg_data e = {};
+
+ while ((hdr = snl_read_reply_multi(ss, msg.hdr.nlmsg_seq, &e)) != NULL) {
+ struct snl_parsed_link_simple link = {};
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, &link))
+ continue;
+ if (link.ifi_index >= ifmap_size) {
+ size_t size = roundup2(link.ifi_index + 1, 32) * sizeof(struct ifmap_entry);
+ if ((ifmap = realloc(ifmap, size)) == NULL)
+ xo_errx(EX_OSERR, "realloc(%zu) failed", size);
+ memset(&ifmap[ifmap_size], 0,
+ size - ifmap_size *
+ sizeof(struct ifmap_entry));
+ ifmap_size = roundup2(link.ifi_index + 1, 32);
+ }
+ if (*ifmap[link.ifi_index].ifname != '\0')
+ continue;
+ strlcpy(ifmap[link.ifi_index].ifname, link.ifla_ifname, IFNAMSIZ);
+ ifmap[link.ifi_index].mtu = link.ifla_mtu;
+ }
+ *pifmap_size = ifmap_size;
+ return (ifmap);
+}
+
+static void
+ip6_writemask(struct in6_addr *addr6, uint8_t mask)
+{
+ uint32_t *cp;
+
+ for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
+ *cp++ = 0xFFFFFFFF;
+ if (mask > 0)
+ *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
+}
+
+static void
+gen_mask(int family, int plen, struct sockaddr *sa)
+{
+ if (family == AF_INET6) {
+ struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ .sin6_len = sizeof(struct sockaddr_in6),
+ };
+ ip6_writemask(&sin6.sin6_addr, plen);
+ *((struct sockaddr_in6 *)sa) = sin6;
+ } else if (family == AF_INET) {
+ struct sockaddr_in sin = {
+ .sin_family = AF_INET,
+ .sin_len = sizeof(struct sockaddr_in),
+ .sin_addr.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0),
+ };
+ *((struct sockaddr_in *)sa) = sin;
+ }
+}
+
+static void
+add_scopeid(struct sockaddr *sa, int ifindex)
+{
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ sin6->sin6_scope_id = ifindex;
+ }
+}
+
+static void
+p_path(struct snl_parsed_route *rt, bool is_mpath)
+{
+ struct sockaddr_in6 mask6;
+ struct sockaddr *pmask = (struct sockaddr *)&mask6;
+ char buffer[128];
+ char prettyname[128];
+ int protrusion;
+
+ gen_mask(rt->rtm_family, rt->rtm_dst_len, pmask);
+ add_scopeid(rt->rta_dst, rt->rta_oif);
+ add_scopeid(rt->rta_gw, rt->rta_oif);
+ protrusion = p_sockaddr("destination", rt->rta_dst, pmask, rt->rta_rtflags, wid.dst);
+ protrusion = p_sockaddr("gateway", rt->rta_gw, NULL, RTF_HOST,
+ wid.gw - protrusion);
+ snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ",
+ wid.flags - protrusion);
+ p_flags(rt->rta_rtflags | RTF_UP, buffer);
+ /* Output path weight as non-visual property */
+ xo_emit("{e:weight/%u}", rt->rtax_weight);
+ if (is_mpath)
+ xo_emit("{e:nhg-kidx/%u}", rt->rta_knh_id);
+ else
+ xo_emit("{e:nhop-kidx/%u}", rt->rta_knh_id);
+ if (rt->rta_nh_id != 0) {
+ if (is_mpath)
+ xo_emit("{e:nhg-uidx/%u}", rt->rta_nh_id);
+ else
+ xo_emit("{e:nhop-uidx/%u}", rt->rta_nh_id);
+ }
+
+ memset(prettyname, 0, sizeof(prettyname));
+ if (rt->rta_oif < ifmap_size) {
+ strlcpy(prettyname, ifmap[rt->rta_oif].ifname,
+ sizeof(prettyname));
+ if (*prettyname == '\0')
+ strlcpy(prettyname, "---", sizeof(prettyname));
+ if (rt->rtax_mtu == 0)
+ rt->rtax_mtu = ifmap[rt->rta_oif].mtu;
+ }
+
+ if (Wflag) {
+ /* XXX: use=0? */
+ xo_emit("{t:nhop/%*lu} ", wid.mtu, is_mpath ? 0 : rt->rta_knh_id);
+
+ if (rt->rtax_mtu != 0)
+ xo_emit("{t:mtu/%*lu} ", wid.mtu, rt->rtax_mtu);
+ else {
+ /* use interface mtu */
+ xo_emit("{P:/%*s} ", wid.mtu, "");
+ }
+
+ }
+
+ if (Wflag)
+ xo_emit("{t:interface-name/%*s}", wid.iface, prettyname);
+ else
+ xo_emit("{t:interface-name/%*.*s}", wid.iface, wid.iface,
+ prettyname);
+ if (rt->rta_expires > 0) {
+ xo_emit(" {:expire-time/%*u}", wid.expire, rt->rta_expires);
+ }
+}
+
+static void
+p_rtentry_netlink(struct snl_state *ss, const char *name, struct nlmsghdr *hdr)
+{
+
+ struct snl_parsed_route rt = {};
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &rt))
+ return;
+ if (rt.rtax_weight == 0)
+ rt.rtax_weight = rt_default_weight;
+
+ if (rt.rta_multipath.num_nhops != 0) {
+ uint32_t orig_rtflags = rt.rta_rtflags;
+ uint32_t orig_mtu = rt.rtax_mtu;
+ for (uint32_t i = 0; i < rt.rta_multipath.num_nhops; i++) {
+ struct rta_mpath_nh *nhop = rt.rta_multipath.nhops[i];
+
+ rt.rta_gw = nhop->gw;
+ rt.rta_oif = nhop->ifindex;
+ rt.rtax_weight = nhop->rtnh_weight;
+ rt.rta_rtflags = nhop->rta_rtflags ? nhop->rta_rtflags : orig_rtflags;
+ rt.rtax_mtu = nhop->rtax_mtu ? nhop->rtax_mtu : orig_mtu;
+
+ xo_open_instance(name);
+ p_path(&rt, true);
+ xo_emit("\n");
+ xo_close_instance(name);
+ }
+ return;
+ }
+
+ struct sockaddr_dl sdl_gw = {
+ .sdl_family = AF_LINK,
+ .sdl_len = sizeof(struct sockaddr_dl),
+ .sdl_index = rt.rta_oif,
+ };
+ if (rt.rta_gw == NULL)
+ rt.rta_gw = (struct sockaddr *)&sdl_gw;
+
+ xo_open_instance(name);
+ p_path(&rt, false);
+ xo_emit("\n");
+ xo_close_instance(name);
+}
+
+bool
+p_rtable_netlink(int fibnum, int af)
+{
+ int fam = AF_UNSPEC;
+ int need_table_close = false;
+ struct nlmsghdr *hdr;
+ struct snl_errmsg_data e = {};
+ struct snl_state ss = {};
+
+ if (!snl_init(&ss, NETLINK_ROUTE))
+ return (false);
+
+ ifmap = prepare_ifmap_netlink(&ss, &ifmap_size);
+ if (ifmap == NULL) {
+ snl_free(&ss);
+ return (false);
+ }
+
+ struct {
+ struct nlmsghdr hdr;
+ struct rtmsg rtmsg;
+ struct nlattr nla_fibnum;
+ uint32_t fibnum;
+ } msg = {
+ .hdr.nlmsg_type = RTM_GETROUTE,
+ .hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+ .hdr.nlmsg_seq = snl_get_seq(&ss),
+ .rtmsg.rtm_family = af,
+ .nla_fibnum.nla_len = sizeof(struct nlattr) + sizeof(uint32_t),
+ .nla_fibnum.nla_type = RTA_TABLE,
+ .fibnum = fibnum,
+ };
+ msg.hdr.nlmsg_len = sizeof(msg);
+
+ if (!snl_send_message(&ss, &msg.hdr)) {
+ snl_free(&ss);
+ return (false);
+ }
+
+ xo_open_container("route-table");
+ xo_open_list("rt-family");
+ while ((hdr = snl_read_reply_multi(&ss, msg.hdr.nlmsg_seq, &e)) != NULL) {
+ struct rtmsg *rtm = (struct rtmsg *)(hdr + 1);
+ /* Only print family first time. */
+ if (fam != rtm->rtm_family) {
+ if (need_table_close) {
+ xo_close_list("rt-entry");
+ xo_close_instance("rt-family");
+ }
+ need_table_close = true;
+ fam = rtm->rtm_family;
+ set_wid(fam);
+ xo_open_instance("rt-family");
+ pr_family(fam);
+ xo_open_list("rt-entry");
+ pr_rthdr(fam);
+ }
+ p_rtentry_netlink(&ss, "rt-entry", hdr);
+ snl_clear_lb(&ss);
+ }
+ if (need_table_close) {
+ xo_close_list("rt-entry");
+ xo_close_instance("rt-family");
+ }
+ xo_close_list("rt-family");
+ xo_close_container("route-table");
+ snl_free(&ss);
+ return (true);
+}
+
+
diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c
new file mode 100644
index 000000000000..c3abac407327
--- /dev/null
+++ b/usr.bin/netstat/sctp.c
@@ -0,0 +1,833 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
+ * Copyright (c) 2011, by Michael Tuexen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * b) 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.
+ *
+ * c) Neither the name of Cisco Systems, Inc. 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 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.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/protosw.h>
+
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <netinet/sctp_constants.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+#include <libxo/xo.h>
+
+#ifdef SCTP
+
+static void sctp_statesprint(uint32_t state);
+
+#define NETSTAT_SCTP_STATES_CLOSED 0x0
+#define NETSTAT_SCTP_STATES_BOUND 0x1
+#define NETSTAT_SCTP_STATES_LISTEN 0x2
+#define NETSTAT_SCTP_STATES_COOKIE_WAIT 0x3
+#define NETSTAT_SCTP_STATES_COOKIE_ECHOED 0x4
+#define NETSTAT_SCTP_STATES_ESTABLISHED 0x5
+#define NETSTAT_SCTP_STATES_SHUTDOWN_SENT 0x6
+#define NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED 0x7
+#define NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT 0x8
+#define NETSTAT_SCTP_STATES_SHUTDOWN_PENDING 0x9
+
+static const char *sctpstates[] = {
+ "CLOSED",
+ "BOUND",
+ "LISTEN",
+ "COOKIE_WAIT",
+ "COOKIE_ECHOED",
+ "ESTABLISHED",
+ "SHUTDOWN_SENT",
+ "SHUTDOWN_RECEIVED",
+ "SHUTDOWN_ACK_SENT",
+ "SHUTDOWN_PENDING"
+};
+
+static LIST_HEAD(xladdr_list, xladdr_entry) xladdr_head;
+struct xladdr_entry {
+ struct xsctp_laddr *xladdr;
+ LIST_ENTRY(xladdr_entry) xladdr_entries;
+};
+
+static LIST_HEAD(xraddr_list, xraddr_entry) xraddr_head;
+struct xraddr_entry {
+ struct xsctp_raddr *xraddr;
+ LIST_ENTRY(xraddr_entry) xraddr_entries;
+};
+
+static void
+sctp_print_address(const char *container, union sctp_sockstore *address,
+ int port, int num_port)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+ size_t alen, plen;
+
+ if (container)
+ xo_open_container(container);
+
+ switch (address->sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ snprintf(line, sizeof(line), "%.*s.",
+ Wflag ? 39 : 16, inetname(&address->sin.sin_addr));
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ snprintf(line, sizeof(line), "%.*s.",
+ Wflag ? 39 : 16, inet6name(&address->sin6.sin6_addr));
+ break;
+#endif
+ default:
+ snprintf(line, sizeof(line), "%.*s.",
+ Wflag ? 39 : 16, "");
+ break;
+ }
+ alen = strlen(line);
+ cp = line + alen;
+ if (!num_port && port)
+ sp = getservbyport((int)port, "sctp");
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - alen,
+ "%.15s ", sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - alen,
+ "%d ", ntohs((u_short)port));
+ width = Wflag ? 45 : 22;
+ xo_emit("{d:target/%-*.*s} ", width, width, line);
+
+ plen = strlen(cp) - 1;
+ alen--;
+ xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
+ plen, cp);
+
+ if (container)
+ xo_close_container(container);
+}
+
+static int
+sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
+{
+ int exist_tcb = 0;
+ struct xsctp_tcb *xstcb;
+ struct xsctp_raddr *xraddr;
+ struct xsctp_laddr *xladdr;
+
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ }
+
+ while (*offset < buflen) {
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ if (xstcb->last == 1)
+ break;
+
+ exist_tcb = 1;
+
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ }
+
+ while (*offset < buflen) {
+ xraddr = (struct xsctp_raddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_raddr);
+ if (xraddr->last == 1)
+ break;
+ }
+ }
+
+ /*
+ * If Lflag is set, we don't care about the return value.
+ */
+ if (Lflag)
+ return 0;
+
+ return exist_tcb;
+}
+
+static void
+sctp_process_tcb(struct xsctp_tcb *xstcb,
+ char *buf, const size_t buflen, size_t *offset, int *indent)
+{
+ int i, xl_total = 0, xr_total = 0, x_max;
+ struct xsctp_raddr *xraddr;
+ struct xsctp_laddr *xladdr;
+ struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
+ struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
+
+ LIST_INIT(&xladdr_head);
+ LIST_INIT(&xraddr_head);
+
+ /*
+ * Make `struct xladdr_list' list and `struct xraddr_list' list
+ * to handle the address flexibly.
+ */
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+
+ prev_xl = xl;
+ xl = malloc(sizeof(struct xladdr_entry));
+ if (xl == NULL) {
+ xo_warnx("malloc %lu bytes",
+ (u_long)sizeof(struct xladdr_entry));
+ goto out;
+ }
+ xl->xladdr = xladdr;
+ if (prev_xl == NULL)
+ LIST_INSERT_HEAD(&xladdr_head, xl, xladdr_entries);
+ else
+ LIST_INSERT_AFTER(prev_xl, xl, xladdr_entries);
+ xl_total++;
+ }
+
+ while (*offset < buflen) {
+ xraddr = (struct xsctp_raddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_raddr);
+ if (xraddr->last == 1)
+ break;
+
+ prev_xr = xr;
+ xr = malloc(sizeof(struct xraddr_entry));
+ if (xr == NULL) {
+ xo_warnx("malloc %lu bytes",
+ (u_long)sizeof(struct xraddr_entry));
+ goto out;
+ }
+ xr->xraddr = xraddr;
+ if (prev_xr == NULL)
+ LIST_INSERT_HEAD(&xraddr_head, xr, xraddr_entries);
+ else
+ LIST_INSERT_AFTER(prev_xr, xr, xraddr_entries);
+ xr_total++;
+ }
+
+ /*
+ * Let's print the address infos.
+ */
+ xo_open_list("address");
+ xl = LIST_FIRST(&xladdr_head);
+ xr = LIST_FIRST(&xraddr_head);
+ x_max = MAX(xl_total, xr_total);
+ for (i = 0; i < x_max; i++) {
+ xo_open_instance("address");
+
+ if (((*indent == 0) && i > 0) || *indent > 0)
+ xo_emit("{P:/%-12s} ", " ");
+
+ if (xl != NULL) {
+ sctp_print_address("local", &(xl->xladdr->address),
+ htons(xstcb->local_port), numeric_port);
+ } else {
+ if (Wflag) {
+ xo_emit("{P:/%-45s} ", " ");
+ } else {
+ xo_emit("{P:/%-22s} ", " ");
+ }
+ }
+
+ if (xr != NULL && !Lflag) {
+ sctp_print_address("remote", &(xr->xraddr->address),
+ htons(xstcb->remote_port), numeric_port);
+ }
+
+ if (xl != NULL)
+ xl = LIST_NEXT(xl, xladdr_entries);
+ if (xr != NULL)
+ xr = LIST_NEXT(xr, xraddr_entries);
+
+ if (i == 0 && !Lflag)
+ sctp_statesprint(xstcb->state);
+
+ if (i < x_max)
+ xo_emit("\n");
+ xo_close_instance("address");
+ }
+
+out:
+ /*
+ * Free the list which be used to handle the address.
+ */
+ xl = LIST_FIRST(&xladdr_head);
+ while (xl != NULL) {
+ xl_tmp = LIST_NEXT(xl, xladdr_entries);
+ free(xl);
+ xl = xl_tmp;
+ }
+
+ xr = LIST_FIRST(&xraddr_head);
+ while (xr != NULL) {
+ xr_tmp = LIST_NEXT(xr, xraddr_entries);
+ free(xr);
+ xr = xr_tmp;
+ }
+}
+
+static void
+sctp_process_inpcb(struct xsctp_inpcb *xinpcb,
+ char *buf, const size_t buflen, size_t *offset)
+{
+ int indent = 0, xladdr_total = 0, is_listening = 0;
+ static int first = 1;
+ const char *tname, *pname;
+ struct xsctp_tcb *xstcb;
+ struct xsctp_laddr *xladdr;
+ size_t offset_laddr;
+ int process_closed;
+
+ if (xinpcb->maxqlen > 0)
+ is_listening = 1;
+
+ if (first) {
+ if (!Lflag) {
+ xo_emit("Active SCTP associations");
+ if (aflag)
+ xo_emit(" (including servers)");
+ } else
+ xo_emit("Current listen queue sizes (qlen/maxqlen)");
+ xo_emit("\n");
+ if (Lflag)
+ xo_emit("{T:/%-6.6s} {T:/%-5.5s} {T:/%-8.8s} "
+ "{T:/%-22.22s}\n",
+ "Proto", "Type", "Listen", "Local Address");
+ else
+ if (Wflag)
+ xo_emit("{T:/%-6.6s} {T:/%-5.5s} {T:/%-45.45s} "
+ "{T:/%-45.45s} {T:/%s}\n",
+ "Proto", "Type",
+ "Local Address", "Foreign Address",
+ "(state)");
+ else
+ xo_emit("{T:/%-6.6s} {T:/%-5.5s} {T:/%-22.22s} "
+ "{T:/%-22.22s} {T:/%s}\n",
+ "Proto", "Type",
+ "Local Address", "Foreign Address",
+ "(state)");
+ first = 0;
+ }
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ if ((!aflag && is_listening) ||
+ (Lflag && !is_listening)) {
+ sctp_skip_xinpcb_ifneed(buf, buflen, offset);
+ return;
+ }
+
+ if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ /* Can't distinguish between sctp46 and sctp6 */
+ pname = "sctp46";
+ } else {
+ pname = "sctp4";
+ }
+
+ if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
+ tname = "1to1";
+ else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
+ tname = "1toN";
+ else
+ tname = "????";
+
+ if (Lflag) {
+ char buf1[22];
+
+ snprintf(buf1, sizeof buf1, "%u/%u",
+ xinpcb->qlen, xinpcb->maxqlen);
+ xo_emit("{:protocol/%-6.6s/%s} {:type/%-5.5s/%s} ",
+ pname, tname);
+ xo_emit("{d:queues/%-8.8s}{e:queue-len/%hu}"
+ "{e:max-queue-len/%hu} ",
+ buf1, xinpcb->qlen, xinpcb->maxqlen);
+ }
+
+ offset_laddr = *offset;
+ process_closed = 0;
+
+ xo_open_list("local-address");
+retry:
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last) {
+ if (aflag && !Lflag && (xladdr_total == 0) && process_closed) {
+ xo_open_instance("local-address");
+
+ xo_emit("{:protocol/%-6.6s/%s} "
+ "{:type/%-5.5s/%s} ", pname, tname);
+ if (Wflag) {
+ xo_emit("{P:/%-91.91s/%s} "
+ "{:state/CLOSED}", " ");
+ } else {
+ xo_emit("{P:/%-45.45s/%s} "
+ "{:state/CLOSED}", " ");
+ }
+ xo_close_instance("local-address");
+ }
+ if (process_closed || is_listening) {
+ xo_emit("\n");
+ }
+ break;
+ }
+
+ if (!Lflag && !is_listening && !process_closed)
+ continue;
+
+ xo_open_instance("local-address");
+
+ if (xladdr_total == 0) {
+ if (!Lflag) {
+ xo_emit("{:protocol/%-6.6s/%s} "
+ "{:type/%-5.5s/%s} ", pname, tname);
+ }
+ } else {
+ xo_emit("\n");
+ xo_emit(Lflag ? "{P:/%-21.21s} " : "{P:/%-12.12s} ",
+ " ");
+ }
+ sctp_print_address("local", &(xladdr->address),
+ htons(xinpcb->local_port), numeric_port);
+ if (aflag && !Lflag && xladdr_total == 0) {
+ if (Wflag) {
+ if (process_closed) {
+ xo_emit("{P:/%-45.45s} "
+ "{:state/CLOSED}", " ");
+ } else {
+ xo_emit("{P:/%-45.45s} "
+ "{:state/LISTEN}", " ");
+ }
+ } else {
+ if (process_closed) {
+ xo_emit("{P:/%-22.22s} "
+ "{:state/CLOSED}", " ");
+ } else {
+ xo_emit("{P:/%-22.22s} "
+ "{:state/LISTEN}", " ");
+ }
+ }
+ }
+ xladdr_total++;
+ xo_close_instance("local-address");
+ }
+
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ if (aflag && (xladdr_total == 0) && xstcb->last && !process_closed) {
+ process_closed = 1;
+ *offset = offset_laddr;
+ goto retry;
+ }
+ while (xstcb->last == 0 && *offset < buflen) {
+ xo_emit("{:protocol/%-6.6s/%s} {:type/%-5.5s/%s} ",
+ pname, tname);
+ sctp_process_tcb(xstcb, buf, buflen, offset, &indent);
+ indent++;
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ }
+
+ xo_close_list("local-address");
+}
+
+/*
+ * Print a summary of SCTP connections related to an Internet
+ * protocol.
+ */
+void
+sctp_protopr(u_long off __unused,
+ const char *name __unused, int af1 __unused, int proto)
+{
+ char *buf;
+ const char *mibvar = "net.inet.sctp.assoclist";
+ size_t offset = 0;
+ size_t len = 0;
+ struct xsctp_inpcb *xinpcb;
+
+ if (proto != IPPROTO_SCTP)
+ return;
+
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ xo_warn("sysctl: %s", mibvar);
+ return;
+ }
+ if ((buf = malloc(len)) == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ xo_warn("sysctl: %s", mibvar);
+ free(buf);
+ return;
+ }
+
+ xinpcb = (struct xsctp_inpcb *)(buf + offset);
+ offset += sizeof(struct xsctp_inpcb);
+ while (xinpcb->last == 0 && offset < len) {
+ sctp_process_inpcb(xinpcb, buf, (const size_t)len,
+ &offset);
+
+ xinpcb = (struct xsctp_inpcb *)(buf + offset);
+ offset += sizeof(struct xsctp_inpcb);
+ }
+
+ free(buf);
+}
+
+static void
+sctp_statesprint(uint32_t state)
+{
+ int idx;
+
+ switch (state) {
+ case SCTP_CLOSED:
+ idx = NETSTAT_SCTP_STATES_CLOSED;
+ break;
+ case SCTP_BOUND:
+ idx = NETSTAT_SCTP_STATES_BOUND;
+ break;
+ case SCTP_LISTEN:
+ idx = NETSTAT_SCTP_STATES_LISTEN;
+ break;
+ case SCTP_COOKIE_WAIT:
+ idx = NETSTAT_SCTP_STATES_COOKIE_WAIT;
+ break;
+ case SCTP_COOKIE_ECHOED:
+ idx = NETSTAT_SCTP_STATES_COOKIE_ECHOED;
+ break;
+ case SCTP_ESTABLISHED:
+ idx = NETSTAT_SCTP_STATES_ESTABLISHED;
+ break;
+ case SCTP_SHUTDOWN_SENT:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_SENT;
+ break;
+ case SCTP_SHUTDOWN_RECEIVED:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED;
+ break;
+ case SCTP_SHUTDOWN_ACK_SENT:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT;
+ break;
+ case SCTP_SHUTDOWN_PENDING:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_PENDING;
+ break;
+ default:
+ xo_emit("UNKNOWN {:state/0x%08x}", state);
+ return;
+ }
+
+ xo_emit("{:state/%s}", sctpstates[idx]);
+}
+
+/*
+ * Dump SCTP statistics structure.
+ */
+void
+sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct sctpstat sctpstat;
+
+ if (fetch_stats("net.inet.sctp.stats", off, &sctpstat,
+ sizeof(sctpstat), kread) != 0)
+ return;
+
+ xo_open_container(name);
+ xo_emit("{T:/%s}:\n", name);
+
+#define p(f, m) if (sctpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)sctpstat.f, plural(sctpstat.f))
+#define p1a(f, m) if (sctpstat.f || sflag <= 1) \
+ xo_emit(m, (uintmax_t)sctpstat.f)
+
+ /*
+ * input statistics
+ */
+ p(sctps_recvpackets, "\t{:received-packets/%ju} "
+ "{N:/input packet%s}\n");
+ p(sctps_recvdatagrams, "\t\t{:received-datagrams/%ju} "
+ "{N:/datagram%s}\n");
+ p(sctps_recvpktwithdata, "\t\t{:received-with-data/%ju} "
+ "{N:/packet%s that had data}\n");
+ p(sctps_recvsacks, "\t\t{:received-sack-chunks/%ju} "
+ "{N:/input SACK chunk%s}\n");
+ p(sctps_recvdata, "\t\t{:received-data-chunks/%ju} "
+ "{N:/input DATA chunk%s}\n");
+ p(sctps_recvdupdata, "\t\t{:received-duplicate-data-chunks/%ju} "
+ "{N:/duplicate DATA chunk%s}\n");
+ p(sctps_recvheartbeat, "\t\t{:received-hb-chunks/%ju} "
+ "{N:/input HB chunk%s}\n");
+ p(sctps_recvheartbeatack, "\t\t{:received-hb-ack-chunks/%ju} "
+ "{N:/HB-ACK chunk%s}\n");
+ p(sctps_recvecne, "\t\t{:received-ecne-chunks/%ju} "
+ "{N:/input ECNE chunk%s}\n");
+ p(sctps_recvauth, "\t\t{:received-auth-chunks/%ju} "
+ "{N:/input AUTH chunk%s}\n");
+ p(sctps_recvauthmissing, "\t\t{:dropped-missing-auth/%ju} "
+ "{N:/chunk%s missing AUTH}\n");
+ p(sctps_recvivalhmacid, "\t\t{:dropped-invalid-hmac/%ju} "
+ "{N:/invalid HMAC id%s received}\n");
+ p(sctps_recvivalkeyid, "\t\t{:dropped-invalid-secret/%ju} "
+ "{N:/invalid secret id%s received}\n");
+ p1a(sctps_recvauthfailed, "\t\t{:dropped-auth-failed/%ju} "
+ "{N:/auth failed}\n");
+ p1a(sctps_recvexpress, "\t\t{:received-fast-path/%ju} "
+ "{N:/fast path receives all one chunk}\n");
+ p1a(sctps_recvexpressm, "\t\t{:receives-fast-path-multipart/%ju} "
+ "{N:/fast path multi-part data}\n");
+
+ /*
+ * output statistics
+ */
+ p(sctps_sendpackets, "\t{:sent-packets/%ju} "
+ "{N:/output packet%s}\n");
+ p(sctps_sendsacks, "\t\t{:sent-sacks/%ju} "
+ "{N:/output SACK%s}\n");
+ p(sctps_senddata, "\t\t{:sent-data-chunks/%ju} "
+ "{N:/output DATA chunk%s}\n");
+ p(sctps_sendretransdata, "\t\t{:sent-retransmitted-data-chunks/%ju} "
+ "{N:/retransmitted DATA chunk%s}\n");
+ p(sctps_sendfastretrans, "\t\t"
+ "{:sent-fast-retransmitted-data-chunks/%ju} "
+ "{N:/fast retransmitted DATA chunk%s}\n");
+ p(sctps_sendmultfastretrans, "\t\t"
+ "{:sent-fast-retransmitted-data-chunk-multiple-times/%ju} "
+ "{N:/FR'%s that happened more than once to same chunk}\n");
+ p(sctps_sendheartbeat, "\t\t{:sent-hb-chunks/%ju} "
+ "{N:/output HB chunk%s}\n");
+ p(sctps_sendecne, "\t\t{:sent-ecne-chunks/%ju} "
+ "{N:/output ECNE chunk%s}\n");
+ p(sctps_sendauth, "\t\t{:sent-auth-chunks/%ju} "
+ "{N:/output AUTH chunk%s}\n");
+ p1a(sctps_senderrors, "\t\t{:send-errors/%ju} "
+ "{N:/ip_output error counter}\n");
+
+ /*
+ * PCKDROPREP statistics
+ */
+ xo_emit("\t{T:Packet drop statistics}:\n");
+ xo_open_container("drop-statistics");
+ p1a(sctps_pdrpfmbox, "\t\t{:middle-box/%ju} "
+ "{N:/from middle box}\n");
+ p1a(sctps_pdrpfehos, "\t\t{:end-host/%ju} "
+ "{N:/from end host}\n");
+ p1a(sctps_pdrpmbda, "\t\t{:with-data/%ju} "
+ "{N:/with data}\n");
+ p1a(sctps_pdrpmbct, "\t\t{:non-data/%ju} "
+ "{N:/non-data, non-endhost}\n");
+ p1a(sctps_pdrpbwrpt, "\t\t{:non-endhost/%ju} "
+ "{N:/non-endhost, bandwidth rep only}\n");
+ p1a(sctps_pdrpcrupt, "\t\t{:short-header/%ju} "
+ "{N:/not enough for chunk header}\n");
+ p1a(sctps_pdrpnedat, "\t\t{:short-data/%ju} "
+ "{N:/not enough data to confirm}\n");
+ p1a(sctps_pdrppdbrk, "\t\t{:chunk-break/%ju} "
+ "{N:/where process_chunk_drop said break}\n");
+ p1a(sctps_pdrptsnnf, "\t\t{:tsn-not-found/%ju} "
+ "{N:/failed to find TSN}\n");
+ p1a(sctps_pdrpdnfnd, "\t\t{:reverse-tsn/%ju} "
+ "{N:/attempt reverse TSN lookup}\n");
+ p1a(sctps_pdrpdiwnp, "\t\t{:confirmed-zero-window/%ju} "
+ "{N:/e-host confirms zero-rwnd}\n");
+ p1a(sctps_pdrpdizrw, "\t\t{:middle-box-no-space/%ju} "
+ "{N:/midbox confirms no space}\n");
+ p1a(sctps_pdrpbadd, "\t\t{:bad-data/%ju} "
+ "{N:/data did not match TSN}\n");
+ p(sctps_pdrpmark, "\t\t{:tsn-marked-fast-retransmission/%ju} "
+ "{N:/TSN'%s marked for Fast Retran}\n");
+ xo_close_container("drop-statistics");
+
+ /*
+ * Timeouts
+ */
+ xo_emit("\t{T:Timeouts}:\n");
+ xo_open_container("timeouts");
+ p(sctps_timoiterator, "\t\t{:iterator/%ju} "
+ "{N:/iterator timer%s fired}\n");
+ p(sctps_timodata, "\t\t{:t3-data/%ju} "
+ "{N:/T3 data time out%s}\n");
+ p(sctps_timowindowprobe, "\t\t{:window-probe/%ju} "
+ "{N:/window probe (T3) timer%s fired}\n");
+ p(sctps_timoinit, "\t\t{:init-timer/%ju} "
+ "{N:/INIT timer%s fired}\n");
+ p(sctps_timosack, "\t\t{:sack-timer/%ju} "
+ "{N:/sack timer%s fired}\n");
+ p(sctps_timoshutdown, "\t\t{:shutdown-timer/%ju} "
+ "{N:/shutdown timer%s fired}\n");
+ p(sctps_timoheartbeat, "\t\t{:heartbeat-timer/%ju} "
+ "{N:/heartbeat timer%s fired}\n");
+ p1a(sctps_timocookie, "\t\t{:cookie-timer/%ju} "
+ "{N:/a cookie timeout fired}\n");
+ p1a(sctps_timosecret, "\t\t{:endpoint-changed-cookie/%ju} "
+ "{N:/an endpoint changed its cook}ie"
+ "secret\n");
+ p(sctps_timopathmtu, "\t\t{:pmtu-timer/%ju} "
+ "{N:/PMTU timer%s fired}\n");
+ p(sctps_timoshutdownack, "\t\t{:shutdown-ack-timer/%ju} "
+ "{N:/shutdown ack timer%s fired}\n");
+ p(sctps_timoshutdownguard, "\t\t{:shutdown-guard-timer/%ju} "
+ "{N:/shutdown guard timer%s fired}\n");
+ p(sctps_timostrmrst, "\t\t{:stream-reset-timer/%ju} "
+ "{N:/stream reset timer%s fired}\n");
+ p(sctps_timoearlyfr, "\t\t{:early-fast-retransmission-timer/%ju} "
+ "{N:/early FR timer%s fired}\n");
+ p1a(sctps_timoasconf, "\t\t{:asconf-timer/%ju} "
+ "{N:/an asconf timer fired}\n");
+ p1a(sctps_timoautoclose, "\t\t{:auto-close-timer/%ju} "
+ "{N:/auto close timer fired}\n");
+ p(sctps_timoassockill, "\t\t{:asoc-free-timer/%ju} "
+ "{N:/asoc free timer%s expired}\n");
+ p(sctps_timoinpkill, "\t\t{:input-free-timer/%ju} "
+ "{N:/inp free timer%s expired}\n");
+ xo_close_container("timeouts");
+
+#if 0
+ /*
+ * Early fast retransmission counters
+ */
+ p(sctps_earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n");
+ p(sctps_earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n");
+ p(sctps_earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n");
+ p(sctps_earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n");
+ p(sctps_earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n");
+ p(sctps_earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n");
+ p(sctps_earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n");
+ p(sctps_earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n");
+ p(sctps_earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n");
+ p(sctps_earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n");
+ p(sctps_earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n");
+#endif
+
+ /*
+ * Others
+ */
+ p1a(sctps_hdrops, "\t{:dropped-too-short/%ju} "
+ "{N:/packet shorter than header}\n");
+ p1a(sctps_badsum, "\t{:dropped-bad-checksum/%ju} "
+ "{N:/checksum error}\n");
+ p1a(sctps_noport, "\t{:dropped-no-endpoint/%ju} "
+ "{N:/no endpoint for port}\n");
+ p1a(sctps_badvtag, "\t{:dropped-bad-v-tag/%ju} "
+ "{N:/bad v-tag}\n");
+ p1a(sctps_badsid, "\t{:dropped-bad-sid/%ju} "
+ "{N:/bad SID}\n");
+ p1a(sctps_nomem, "\t{:dropped-no-memory/%ju} "
+ "{N:/no memory}\n");
+ p1a(sctps_fastretransinrtt, "\t{:multiple-fast-retransmits-in-rtt/%ju} "
+ "{N:/number of multiple FR in a RT}T window\n");
+#if 0
+ p(sctps_markedretrans, "\t%ju TODO:sctps_markedretrans\n");
+#endif
+ p1a(sctps_naglesent, "\t{:rfc813-sent/%ju} "
+ "{N:/RFC813 allowed sending}\n");
+ p1a(sctps_naglequeued, "\t{:rfc813-queued/%ju} "
+ "{N:/RFC813 does not allow sending}\n");
+ p1a(sctps_maxburstqueued, "\t{:max-burst-queued/%ju} "
+ "{N:/times max burst prohibited sending}\n");
+ p1a(sctps_ifnomemqueued, "\t{:no-memory-in-interface/%ju} "
+ "{N:/look ahead tells us no memory in interface}\n");
+ p(sctps_windowprobed, "\t{:sent-window-probes/%ju} "
+ "{N:/number%s of window probes sent}\n");
+ p(sctps_lowlevelerr, "\t{:low-level-err/%ju} "
+ "{N:/time%s an output error to clamp down on next user send}\n");
+ p(sctps_lowlevelerrusr, "\t{:low-level-user-error/%ju} "
+ "{N:/time%s sctp_senderrors were caused from a user}\n");
+ p(sctps_datadropchklmt, "\t{:dropped-chunk-limit/%ju} "
+ "{N:/number of in data drop%s due to chunk limit reached}\n");
+ p(sctps_datadroprwnd, "\t{:dropped-rwnd-limit/%ju} "
+ "{N:/number of in data drop%s due to rwnd limit reached}\n");
+ p(sctps_ecnereducedcwnd, "\t{:ecn-reduced-cwnd/%ju} "
+ "{N:/time%s a ECN reduced the cwnd}\n");
+ p1a(sctps_vtagexpress, "\t{:v-tag-express-lookup/%ju} "
+ "{N:/used express lookup via vtag}\n");
+ p1a(sctps_vtagbogus, "\t{:v-tag-collision/%ju} "
+ "{N:/collision in express lookup}\n");
+ p(sctps_primary_randry, "\t{:sender-ran-dry/%ju} "
+ "{N:/time%s the sender ran dry of user data on primary}\n");
+ p1a(sctps_cmt_randry, "\t{:cmt-ran-dry/%ju} "
+ "{N:/same for above}\n");
+ p(sctps_slowpath_sack, "\t{:slow-path-sack/%ju} "
+ "{N:/sack%s the slow way}\n");
+ p(sctps_wu_sacks_sent, "\t{:sent-window-update-only-sack/%ju} "
+ "{N:/window update only sack%s sent}\n");
+ p(sctps_sends_with_flags, "\t{:sent-with-sinfo/%ju} "
+ "{N:/send%s with sinfo_flags !=0}\n");
+ p(sctps_sends_with_unord, "\t{:sent-with-unordered/%ju} "
+ "{N:/unordered send%s}\n");
+ p(sctps_sends_with_eof, "\t{:sent-with-eof/%ju} "
+ "{N:/send%s with EOF flag set}\n");
+ p(sctps_sends_with_abort, "\t{:sent-with-abort/%ju} "
+ "{N:/send%s with ABORT flag set}\n");
+ p(sctps_protocol_drain_calls, "\t{:protocol-drain-called/%ju} "
+ "{N:/time%s protocol drain called}\n");
+ p(sctps_protocol_drains_done, "\t{:protocol-drain/%ju} "
+ "{N:/time%s we did a protocol drain}\n");
+ p(sctps_read_peeks, "\t{:read-with-peek/%ju} "
+ "{N:/time%s recv was called with peek}\n");
+ p(sctps_cached_chk, "\t{:cached-chunks/%ju} "
+ "{N:/cached chunk%s used}\n");
+ p1a(sctps_cached_strmoq, "\t{:cached-output-queue-used/%ju} "
+ "{N:/cached stream oq's used}\n");
+ p(sctps_left_abandon, "\t{:messages-abandoned/%ju} "
+ "{N:/unread message%s abandonded by close}\n");
+ p1a(sctps_send_burst_avoid, "\t{:send-burst-avoidance/%ju} "
+ "{N:/send burst avoidance, already max burst inflight to net}\n");
+ p1a(sctps_send_cwnd_avoid, "\t{:send-cwnd-avoidance/%ju} "
+ "{N:/send cwnd full avoidance, already max burst inflight "
+ "to net}\n");
+ p(sctps_fwdtsn_map_over, "\t{:tsn-map-overruns/%ju} "
+ "{N:/number of map array over-run%s via fwd-tsn's}\n");
+
+#undef p
+#undef p1a
+ xo_close_container(name);
+}
+
+#endif /* SCTP */
diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c
new file mode 100644
index 000000000000..ca9671e812ac
--- /dev/null
+++ b/usr.bin/netstat/unix.c
@@ -0,0 +1,320 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1988, 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.
+ */
+
+#include <sys/cdefs.h>
+/*
+ * Display protocol blocks in the unix domain.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#define _WANT_SOCKET
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#define _WANT_UNPCB
+#include <sys/unpcb.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <strings.h>
+#include <kvm.h>
+#include <libxo/xo.h>
+#include "netstat.h"
+
+static void unixdomainpr(struct xunpcb *, struct xsocket *);
+
+static const char *const socktype[] =
+ { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+
+static int
+pcblist_sysctl(int type, char **bufp)
+{
+ char *buf;
+ size_t len;
+ char mibvar[sizeof "net.local.seqpacket.pcblist"];
+
+ snprintf(mibvar, sizeof(mibvar), "net.local.%s.pcblist", socktype[type]);
+
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ xo_warn("sysctl: %s", mibvar);
+ return (-1);
+ }
+ if ((buf = malloc(len)) == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ xo_warn("sysctl: %s", mibvar);
+ free(buf);
+ return (-2);
+ }
+ *bufp = buf;
+ return (0);
+}
+
+static int
+pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
+{
+ struct unp_head head;
+ struct unpcb *unp, unp0, unp_conn;
+ u_char sun_len;
+ struct socket so;
+ struct xunpgen xug;
+ struct xunpcb xu;
+ unp_gen_t unp_gencnt;
+ u_int unp_count;
+ char *buf, *p;
+ size_t len;
+
+ if (count_off == 0 || gencnt_off == 0)
+ return (-2);
+ if (head_off == 0)
+ return (-1);
+ kread(count_off, &unp_count, sizeof(unp_count));
+ len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
+ if ((buf = malloc(len)) == NULL) {
+ xo_warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ p = buf;
+
+#define COPYOUT(obj, size) do { \
+ if (len < (size)) { \
+ xo_warnx("buffer size exceeded"); \
+ goto fail; \
+ } \
+ bcopy((obj), p, (size)); \
+ len -= (size); \
+ p += (size); \
+} while (0)
+
+#define KREAD(off, buf, len) do { \
+ if (kread((uintptr_t)(off), (buf), (len)) != 0) \
+ goto fail; \
+} while (0)
+
+ /* Write out header. */
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_len = sizeof xug;
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ xug.xug_sogen = 0;
+ COPYOUT(&xug, sizeof xug);
+
+ /* Walk the PCB list. */
+ xu.xu_len = sizeof xu;
+ KREAD(head_off, &head, sizeof(head));
+ LIST_FOREACH(unp, &head, unp_link) {
+ xu.xu_unpp = (uintptr_t)unp;
+ KREAD(unp, &unp0, sizeof (*unp));
+ unp = &unp0;
+
+ if (unp->unp_gencnt > unp_gencnt)
+ continue;
+ if (unp->unp_addr != NULL) {
+ KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
+ KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
+ }
+ if (unp->unp_conn != NULL) {
+ KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
+ if (unp_conn.unp_addr != NULL) {
+ KREAD(unp_conn.unp_addr, &sun_len,
+ sizeof(sun_len));
+ KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
+ }
+ }
+ KREAD(unp->unp_socket, &so, sizeof(so));
+ if (sotoxsocket(&so, &xu.xu_socket) != 0)
+ goto fail;
+ COPYOUT(&xu, sizeof(xu));
+ }
+
+ /* Reread the counts and write the footer. */
+ kread(count_off, &unp_count, sizeof(unp_count));
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ COPYOUT(&xug, sizeof xug);
+
+ *bufp = buf;
+ return (0);
+
+fail:
+ free(buf);
+ return (-1);
+#undef COPYOUT
+#undef KREAD
+}
+
+void
+unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off,
+ u_long sphead_off, bool *first)
+{
+ char *buf;
+ int ret, type;
+ struct xsocket *so;
+ struct xunpgen *xug, *oxug;
+ struct xunpcb *xunp;
+ u_long head_off;
+
+ buf = NULL;
+ for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+ if (live)
+ ret = pcblist_sysctl(type, &buf);
+ else {
+ head_off = 0;
+ switch (type) {
+ case SOCK_STREAM:
+ head_off = shead_off;
+ break;
+
+ case SOCK_DGRAM:
+ head_off = dhead_off;
+ break;
+
+ case SOCK_SEQPACKET:
+ head_off = sphead_off;
+ break;
+ }
+ ret = pcblist_kvm(count_off, gencnt_off, head_off,
+ &buf);
+ }
+ if (ret == -1)
+ continue;
+ if (ret < 0)
+ return;
+
+ oxug = xug = (struct xunpgen *)buf;
+ for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
+ xug->xug_len > sizeof(struct xunpgen);
+ xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
+ xunp = (struct xunpcb *)xug;
+ so = &xunp->xu_socket;
+
+ /* Ignore PCBs which were freed during copyout. */
+ if (xunp->unp_gencnt > oxug->xug_gen)
+ continue;
+ if (*first) {
+ xo_open_list("socket");
+ *first = false;
+ }
+ xo_open_instance("socket");
+ unixdomainpr(xunp, so);
+ xo_close_instance("socket");
+ }
+ if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
+ if (oxug->xug_count > xug->xug_count) {
+ xo_emit("Some {:type/%s} sockets may have "
+ "been {:action/deleted}.\n",
+ socktype[type]);
+ } else if (oxug->xug_count < xug->xug_count) {
+ xo_emit("Some {:type/%s} sockets may have "
+ "been {:action/created}.\n",
+ socktype[type]);
+ } else {
+ xo_emit("Some {:type/%s} sockets may have "
+ "been {:action/created or deleted}",
+ socktype[type]);
+ }
+ }
+ free(buf);
+ }
+}
+
+static void
+unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
+{
+ struct sockaddr_un *sa;
+ static int first = 1;
+ char buf1[33];
+ static const char *titles[2] = {
+ "{T:/%-8.8s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%8.8s} "
+ "{T:/%8.8s} {T:/%8.8s} {T:/%8.8s} {T:Addr}\n",
+ "{T:/%-16.16s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%16.16s} "
+ "{T:/%16.16s} {T:/%16.16s} {T:/%16.16s} {T:Addr}\n"
+ };
+ static const char *format[2] = {
+ "{q:address/%8lx} {t:type/%-6.6s} "
+ "{:receive-bytes-waiting/%6u} "
+ "{:send-bytes-waiting/%6u} "
+ "{q:vnode/%8lx} {q:connection/%8lx} "
+ "{q:first-reference/%8lx} {q:next-reference/%8lx}",
+ "{q:address/%16lx} {t:type/%-6.6s} "
+ "{:receive-bytes-waiting/%6u} "
+ "{:send-bytes-waiting/%6u} "
+ "{q:vnode/%16lx} {q:connection/%16lx} "
+ "{q:first-reference/%16lx} {q:next-reference/%16lx}"
+ };
+ int fmt = (sizeof(void *) == 8) ? 1 : 0;
+
+ sa = (xunp->xu_addr.sun_family == AF_UNIX) ? &xunp->xu_addr : NULL;
+
+ if (first && !Lflag) {
+ xo_emit("{T:Active UNIX domain sockets}\n");
+ xo_emit(titles[fmt],
+ "Address", "Type", "Recv-Q", "Send-Q",
+ "Inode", "Conn", "Refs", "Nextref");
+ first = 0;
+ }
+
+ if (Lflag && so->so_qlimit == 0)
+ return;
+
+ if (Lflag) {
+ snprintf(buf1, sizeof buf1, "%u/%u/%u", so->so_qlen,
+ so->so_incqlen, so->so_qlimit);
+ xo_emit("unix {d:socket/%-32.32s}{e:queue-length/%u}"
+ "{e:incomplete-queue-length/%u}{e:queue-limit/%u}",
+ buf1, so->so_qlen, so->so_incqlen, so->so_qlimit);
+ } else {
+ xo_emit(format[fmt],
+ (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
+ so->so_snd.sb_cc, (long)xunp->unp_vnode,
+ (long)xunp->unp_conn, (long)xunp->xu_firstref,
+ (long)xunp->xu_nextref);
+ }
+ if (sa)
+ xo_emit(" {:path/%.*s}",
+ (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
+ sa->sun_path);
+ xo_emit("\n");
+}
diff --git a/usr.bin/newgrp/Makefile b/usr.bin/newgrp/Makefile
new file mode 100644
index 000000000000..3fcd0292909a
--- /dev/null
+++ b/usr.bin/newgrp/Makefile
@@ -0,0 +1,10 @@
+PROG= newgrp
+
+LIBADD= crypt util
+
+.if defined(ENABLE_SUID_NEWGRP)
+BINMODE= 4555
+PRECIOUSPROG=
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/newgrp/Makefile.depend b/usr.bin/newgrp/Makefile.depend
new file mode 100644
index 000000000000..1a673c53cbc6
--- /dev/null
+++ b/usr.bin/newgrp/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libcrypt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/newgrp/newgrp.1 b/usr.bin/newgrp/newgrp.1
new file mode 100644
index 000000000000..d9701feef0d7
--- /dev/null
+++ b/usr.bin/newgrp/newgrp.1
@@ -0,0 +1,102 @@
+.\" Copyright (c) 2002 Tim J. Robbins.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 February 8, 2013
+.Dt NEWGRP 1
+.Os
+.Sh NAME
+.Nm newgrp
+.Nd change to a new group
+.Sh SYNOPSIS
+.Nm
+.Op Fl l
+.Op Ar group
+.Sh DESCRIPTION
+The
+.Nm
+utility creates a new shell execution environment with modified
+real and effective group IDs.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl l
+Simulate a full login.
+The environment and umask are set to what would be expected if the user
+actually logged in again.
+.El
+.Pp
+If the
+.Ar group
+operand is present, a new shell is started with the specified effective
+and real group IDs.
+The user will be prompted for a password if they are not a member of the
+specified group.
+.Pp
+Otherwise, the real, effective and supplementary group IDs are restored to
+those from the current user's password database entry.
+.Sh EXIT STATUS
+The
+.Nm
+utility attempts to start the shell regardless of whether group IDs
+were successfully changed.
+.Pp
+If an error occurs and the shell cannot be started,
+.Nm
+exits >0.
+Otherwise, the exit status of
+.Nm
+is the exit status of the shell.
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr groups 1 ,
+.Xr login 1 ,
+.Xr sh 1 ,
+.Xr su 1 ,
+.Xr umask 1 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v6 .
+.Sh BUGS
+For security reasons, the
+.Nm
+utility is normally installed without the setuid bit.
+To enable it, run the following command:
+.Bd -literal -offset indent
+chmod u+s /usr/bin/newgrp
+.Ed
+.Pp
+Group passwords are inherently insecure as there is no way to stop
+users obtaining the password hash from the group database.
+Their use is discouraged.
+Instead, users should simply be added to the necessary groups.
diff --git a/usr.bin/newgrp/newgrp.c b/usr.bin/newgrp/newgrp.c
new file mode 100644
index 000000000000..f1da1c8cb1f5
--- /dev/null
+++ b/usr.bin/newgrp/newgrp.c
@@ -0,0 +1,309 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 -- change to a new group
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <limits.h>
+#include <login_cap.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void addgroup(const char *grpname);
+static void doshell(void);
+static int inarray(gid_t, const gid_t[], int);
+static void loginshell(void);
+static void restoregrps(void);
+static void usage(void);
+
+static struct passwd *pwd;
+static uid_t euid;
+
+extern char **environ;
+
+/* Manipulate effective user ID. */
+#define PRIV_START do { \
+ if (seteuid(euid) < 0) \
+ err(1, "seteuid"); \
+ } while (0)
+#define PRIV_END do { \
+ if (seteuid(getuid()) < 0) \
+ err(1, "seteuid"); \
+ } while (0)
+
+int
+main(int argc, char *argv[])
+{
+ int ch, login;
+
+ if ((euid = geteuid()) != 0)
+ warnx("need root permissions to function properly, check setuid bit");
+ if (seteuid(getuid()) < 0)
+ err(1, "seteuid");
+
+ if ((pwd = getpwuid(getuid())) == NULL)
+ errx(1, "unknown user");
+
+ login = 0;
+ while ((ch = getopt(argc, argv, "-l")) != -1) {
+ switch (ch) {
+ case '-': /* Obsolescent */
+ case 'l':
+ login = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 0:
+ restoregrps();
+ break;
+ case 1:
+ addgroup(*argv);
+ break;
+ default:
+ usage();
+ }
+
+ if (seteuid(euid) < 0)
+ err(1, "seteuid");
+ if (setuid(getuid()) < 0)
+ err(1, "setuid");
+
+ if (login)
+ loginshell();
+ else
+ doshell();
+
+ /*NOTREACHED*/
+ exit(1);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: newgrp [-l] [group]\n");
+ exit(1);
+}
+
+static void
+restoregrps(void)
+{
+ int initres, setres;
+
+ PRIV_START;
+ initres = initgroups(pwd->pw_name, pwd->pw_gid);
+ setres = setgid(pwd->pw_gid);
+ PRIV_END;
+
+ if (initres < 0)
+ warn("initgroups");
+ if (setres < 0)
+ warn("setgid");
+}
+
+static void
+addgroup(const char *grpname)
+{
+ gid_t *grps;
+ long lgid, ngrps_max;
+ int dbmember, i, ngrps;
+ gid_t egid;
+ struct group *grp;
+ char *ep, *pass, *cryptpw;
+ char **p;
+
+ egid = getegid();
+
+ /* Try it as a group name, then a group id. */
+ if ((grp = getgrnam(grpname)) == NULL)
+ if ((lgid = strtol(grpname, &ep, 10)) <= 0 || *ep != '\0' ||
+ (grp = getgrgid((gid_t)lgid)) == NULL ) {
+ warnx("%s: bad group name", grpname);
+ return;
+ }
+
+ /*
+ * If the user is not a member of the requested group and the group
+ * has a password, prompt and check it.
+ */
+ dbmember = 0;
+ if (pwd->pw_gid == grp->gr_gid)
+ dbmember = 1;
+ for (p = grp->gr_mem; *p != NULL; p++)
+ if (strcmp(*p, pwd->pw_name) == 0) {
+ dbmember = 1;
+ break;
+ }
+ if (!dbmember && *grp->gr_passwd != '\0' && getuid() != 0) {
+ pass = getpass("Password:");
+ if (pass == NULL)
+ return;
+ cryptpw = crypt(pass, grp->gr_passwd);
+ if (cryptpw == NULL || strcmp(grp->gr_passwd, cryptpw) != 0) {
+ fprintf(stderr, "Sorry\n");
+ return;
+ }
+ }
+
+ ngrps_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ if ((grps = malloc(sizeof(gid_t) * ngrps_max)) == NULL)
+ err(1, "malloc");
+ if ((ngrps = getgroups(ngrps_max, (gid_t *)grps)) < 0) {
+ warn("getgroups");
+ goto end;
+ }
+
+ /* Remove requested gid from supp. list if it exists. */
+ if (grp->gr_gid != egid && inarray(grp->gr_gid, grps, ngrps)) {
+ for (i = 0; i < ngrps; i++)
+ if (grps[i] == grp->gr_gid)
+ break;
+ ngrps--;
+ memmove(&grps[i], &grps[i + 1], (ngrps - i) * sizeof(gid_t));
+ PRIV_START;
+ if (setgroups(ngrps, (const gid_t *)grps) < 0) {
+ PRIV_END;
+ warn("setgroups");
+ goto end;
+ }
+ PRIV_END;
+ }
+
+ PRIV_START;
+ if (setgid(grp->gr_gid)) {
+ PRIV_END;
+ warn("setgid");
+ goto end;
+ }
+ PRIV_END;
+ grps[0] = grp->gr_gid;
+
+ /* Add old effective gid to supp. list if it does not exist. */
+ if (egid != grp->gr_gid && !inarray(egid, grps, ngrps)) {
+ if (ngrps == ngrps_max)
+ warnx("too many groups");
+ else {
+ grps[ngrps++] = egid;
+ PRIV_START;
+ if (setgroups(ngrps, (const gid_t *)grps)) {
+ PRIV_END;
+ warn("setgroups");
+ goto end;
+ }
+ PRIV_END;
+ }
+ }
+end:
+ free(grps);
+}
+
+static int
+inarray(gid_t gid, const gid_t grps[], int ngrps)
+{
+ int i;
+
+ for (i = 0; i < ngrps; i++)
+ if (grps[i] == gid)
+ return (1);
+ return (0);
+}
+
+/*
+ * Set the environment to what would be expected if the user logged in
+ * again; this performs the same steps as su(1)'s -l option.
+ */
+static void
+loginshell(void)
+{
+ char *args[2], **cleanenv, *term, *ticket;
+ const char *shell;
+ login_cap_t *lc;
+
+ shell = pwd->pw_shell;
+ if (*shell == '\0')
+ shell = _PATH_BSHELL;
+ if (chdir(pwd->pw_dir) < 0) {
+ warn("%s", pwd->pw_dir);
+ chdir("/");
+ }
+
+ term = getenv("TERM");
+ ticket = getenv("KRBTKFILE");
+
+ if ((cleanenv = calloc(20, sizeof(char *))) == NULL)
+ err(1, "calloc");
+ *cleanenv = NULL;
+ environ = cleanenv;
+
+ lc = login_getpwclass(pwd);
+ setusercontext(lc, pwd, pwd->pw_uid,
+ LOGIN_SETPATH|LOGIN_SETUMASK|LOGIN_SETENV);
+ login_close(lc);
+ setenv("USER", pwd->pw_name, 1);
+ setenv("SHELL", shell, 1);
+ setenv("HOME", pwd->pw_dir, 1);
+ if (term != NULL)
+ setenv("TERM", term, 1);
+ if (ticket != NULL)
+ setenv("KRBTKFILE", ticket, 1);
+
+ if (asprintf(args, "-%s", shell) < 0)
+ err(1, "asprintf");
+ args[1] = NULL;
+
+ execv(shell, args);
+ err(1, "%s", shell);
+}
+
+static void
+doshell(void)
+{
+ const char *shell;
+
+ shell = pwd->pw_shell;
+ if (*shell == '\0')
+ shell = _PATH_BSHELL;
+ execl(shell, shell, (char *)NULL);
+ err(1, "%s", shell);
+}
diff --git a/usr.bin/nfsstat/Makefile b/usr.bin/nfsstat/Makefile
new file mode 100644
index 000000000000..25e617bc576f
--- /dev/null
+++ b/usr.bin/nfsstat/Makefile
@@ -0,0 +1,8 @@
+PACKAGE= nfs
+
+PROG= nfsstat
+CFLAGS+=-DNFS
+
+LIBADD+= devstat xo
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nfsstat/Makefile.depend b/usr.bin/nfsstat/Makefile.depend
new file mode 100644
index 000000000000..2f69c4252e8b
--- /dev/null
+++ b/usr.bin/nfsstat/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libdevstat \
+ lib/libkvm \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/nfsstat/nfsstat.1 b/usr.bin/nfsstat/nfsstat.1
new file mode 100644
index 000000000000..7d641b50f1ac
--- /dev/null
+++ b/usr.bin/nfsstat/nfsstat.1
@@ -0,0 +1,143 @@
+.\" Copyright (c) 1989, 1990, 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.
+.\"
+.Dd December 28, 2023
+.Dt NFSSTAT 1
+.Os
+.Sh NAME
+.Nm nfsstat
+.Nd display
+.Tn NFS
+statistics
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl cdEemqszW
+.Op Fl w Ar wait
+.Sh DESCRIPTION
+The
+.Nm
+command displays statistics kept about
+.Tn NFS
+client and server activity.
+For the NFSv4 server, the statistics are for operations within the Compound
+RPCs and not the count of RPCs.
+If you wish to compare RPC counts between NFSv3 and NFSv4, you must use
+statistics in the client(s).
+.Pp
+The options are as follows:
+.Bl -tag -width "-w wait"
+.It Fl c
+Only display client side statistics.
+.It Fl d
+Display statistics for the NFS server that are similar to those
+displayed by
+.Xr iostat 8 .
+This includes kilobytes per transfer, transfers per second, and megabytes per
+second for read, write, and all operations.
+It also includes the current queue depth, the busy percentage, and latency
+for all operations.
+If the
+.Fl W
+flag is added, commits per second, commit latency, read latency, and write
+latency are also added to the display.
+The busy percentage shown can exceed 100 at times.
+This is because of the way busy percentages are calculated.
+The busy time is calculated by adding the elapsed time between the
+last time an operation started or finished,
+and the current time.
+If there is only one operation outstanding, the "busy time" time
+will get updated with the total time of that operation.
+That means that the difference in the busy time between the two
+measurement intervals (often 1 second)
+will increase by more than the measurement interval.
+.It Fl e
+Report the extra statistics collected by the NFS client and
+server for NFSv4.
+.It Fl E
+Similar to
+.Fl e
+except that the statistics include NFSv4.1 and NFSv4.2 and the numbers aren't
+clipped at one billion.
+Only one of
+.Fl e
+or
+.Fl E
+can be specified.
+.It Fl M
+Deprecated and ignored.
+.It Fl m
+Report the mount options for all NFS client mounts.
+This option overrides all others and
+.Nm
+will exit after completing the report.
+.It Fl N
+Deprecated and ignored.
+.It Fl s
+Only display server side statistics.
+.It Fl W
+Use wide format with interval short summary.
+This option is especially
+useful when combined with
+.Fl c ,
+.Fl d ,
+or
+.Fl s
+and a time delay.
+.It Fl w Ar wait
+Display a shorter summary of
+.Tn NFS
+activity for both the client and server at
+.Ar wait
+second intervals.
+.It Fl z
+Reset statistics after displaying them.
+.It Fl q
+Do not print headers.
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.El
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr sysctl 3 ,
+.Xr iostat 8 ,
+.Xr nfsdumpstate 8 ,
+.Xr pstat 8 ,
+.Xr vmstat 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.bin/nfsstat/nfsstat.c b/usr.bin/nfsstat/nfsstat.c
new file mode 100644
index 000000000000..20472cf4a129
--- /dev/null
+++ b/usr.bin/nfsstat/nfsstat.c
@@ -0,0 +1,1258 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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.
+ */
+/*-
+ * Copyright (c) 2004, 2008, 2009 Silicon Graphics International Corp.
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <nfs/nfssvc.h>
+
+#include <fs/nfs/nfsproto.h>
+#include <fs/nfs/nfsport.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <nlist.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <devstat.h>
+
+#include <libxo/xo.h>
+
+static int widemode = 0;
+static int zflag = 0;
+static int printtitle = 1;
+static struct nfsstatsv1 ext_nfsstats;
+static int extra_output = 0;
+
+static void intpr(int, int);
+static void printhdr(int, int, int);
+static void usage(void) __dead2;
+static char *sperc1(int, int);
+static char *sperc2(int, int);
+static void exp_intpr(int, int, int);
+static void exp_sidewaysintpr(u_int, int, int, int);
+static void compute_new_stats(struct nfsstatsv1 *cur_stats,
+ struct nfsstatsv1 *prev_stats, int curop, long double etime,
+ long double *mbsec, long double *kb_per_transfer,
+ long double *transfers_per_second, long double *ms_per_transfer,
+ uint64_t *queue_len, long double *busy_pct);
+
+#define DELTA(field) (nfsstats.field - lastst.field)
+
+#define STAT_TYPE_READ 0
+#define STAT_TYPE_WRITE 1
+#define STAT_TYPE_COMMIT 2
+#define NUM_STAT_TYPES 3
+
+struct stattypes {
+ int stat_type;
+ int nfs_type;
+};
+static struct stattypes statstruct[] = {
+ {STAT_TYPE_READ, NFSV4OP_READ},
+ {STAT_TYPE_WRITE, NFSV4OP_WRITE},
+ {STAT_TYPE_COMMIT, NFSV4OP_COMMIT}
+};
+
+#define STAT_TYPE_TO_NFS(stat_type) statstruct[stat_type].nfs_type
+
+#define NFSSTAT_XO_VERSION "1"
+
+int
+main(int argc, char **argv)
+{
+ u_int interval;
+ int clientOnly = -1;
+ int serverOnly = -1;
+ int newStats = 0;
+ int ch;
+ int mntlen, i;
+ char buf[1024];
+ struct statfs *mntbuf;
+ struct nfscl_dumpmntopts dumpmntopts;
+
+ interval = 0;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+ xo_set_version(NFSSTAT_XO_VERSION);
+
+ while ((ch = getopt(argc, argv, "cdEesWM:mN:w:zq")) != -1)
+ switch(ch) {
+ case 'M':
+ printf("*** -M option deprecated, ignored\n\n");
+ break;
+ case 'm':
+ /* Display mount options for NFS mount points. */
+ mntlen = getmntinfo(&mntbuf, MNT_NOWAIT);
+ for (i = 0; i < mntlen; i++) {
+ if (strcmp(mntbuf->f_fstypename, "nfs") == 0) {
+ dumpmntopts.ndmnt_fname =
+ mntbuf->f_mntonname;
+ dumpmntopts.ndmnt_buf = buf;
+ dumpmntopts.ndmnt_blen = sizeof(buf);
+ if (nfssvc(NFSSVC_DUMPMNTOPTS,
+ &dumpmntopts) >= 0)
+ printf("%s on %s\n%s\n",
+ mntbuf->f_mntfromname,
+ mntbuf->f_mntonname, buf);
+ else if (errno == EPERM)
+ xo_errx(1, "Only privileged users"
+ " can use the -m option");
+ }
+ mntbuf++;
+ }
+ exit(0);
+ case 'N':
+ printf("*** -N option deprecated, ignored\n\n");
+ break;
+ case 'W':
+ widemode = 1;
+ break;
+ case 'w':
+ interval = atoi(optarg);
+ break;
+ case 'c':
+ clientOnly = 1;
+ if (serverOnly < 0)
+ serverOnly = 0;
+ break;
+ case 'd':
+ newStats = 1;
+ if (interval == 0)
+ interval = 1;
+ break;
+ case 's':
+ serverOnly = 1;
+ if (clientOnly < 0)
+ clientOnly = 0;
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case 'E':
+ if (extra_output != 0)
+ xo_err(1, "-e and -E are mutually exclusive");
+ extra_output = 2;
+ break;
+ case 'e':
+ if (extra_output != 0)
+ xo_err(1, "-e and -E are mutually exclusive");
+ extra_output = 1;
+ break;
+ case 'q':
+ printtitle = 0;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv)
+ interval = atoi(*argv);
+#endif
+ if (modfind("nfscommon") < 0)
+ xo_err(1, "NFS client/server not loaded");
+
+ if (interval) {
+ exp_sidewaysintpr(interval, clientOnly, serverOnly,
+ newStats);
+ } else {
+ xo_open_container("nfsstat");
+ if (extra_output != 0)
+ exp_intpr(clientOnly, serverOnly, extra_output - 1);
+ else
+ intpr(clientOnly, serverOnly);
+ xo_close_container("nfsstat");
+ }
+
+ if (xo_finish() < 0)
+ xo_err(1, "stdout");
+ exit(0);
+}
+
+/*
+ * Print a description of the nfs stats.
+ */
+static void
+intpr(int clientOnly, int serverOnly)
+{
+ int nfssvc_flag;
+
+ nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
+ if (zflag != 0) {
+ if (clientOnly != 0)
+ nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
+ if (serverOnly != 0)
+ nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
+ }
+ ext_nfsstats.vers = NFSSTATS_V1;
+ if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
+ xo_err(1, "Can't get stats");
+ if (clientOnly) {
+ xo_open_container("clientstats");
+
+ if (printtitle)
+ xo_emit("{T:Client Info:\n");
+
+ xo_open_container("operations");
+ if (printtitle)
+ xo_emit("{T:Rpc Counts:}\n");
+
+ xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}"
+ "{T:Lookup/%13.13s}{T:Readlink/%13.13s}"
+ "{T:Read/%13.13s}{T:Write/%13.13s}"
+ "{T:Create/%13.13s}{T:Remove/%13.13s}\n");
+ xo_emit("{:getattr/%13ju}{:setattr/%13ju}"
+ "{:lookup/%13ju}{:readlink/%13ju}"
+ "{:read/%13ju}{:write/%13ju}"
+ "{:create/%13ju}{:remove/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
+
+ xo_emit("{T:Rename/%13.13s}{T:Link/%13.13s}"
+ "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}"
+ "{T:Rmdir/%13.13s}{T:Readdir/%13.13s}"
+ "{T:RdirPlus/%13.13s}{T:Access/%13.13s}\n");
+ xo_emit("{:rename/%13ju}{:link/%13ju}"
+ "{:symlink/%13ju}{:mkdir/%13ju}"
+ "{:rmdir/%13ju}{:readdir/%13ju}"
+ "{:rdirplus/%13ju}{:access/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
+
+ xo_emit("{T:Mknod/%13.13s}{T:Fsstat/%13.13s}"
+ "{T:Fsinfo/%13.13s}{T:PathConf/%13.13s}"
+ "{T:Commit/%13.13s}\n");
+ xo_emit("{:mknod/%13ju}{:fsstat/%13ju}"
+ "{:fsinfo/%13ju}{:pathconf/%13ju}"
+ "{:commit/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT]);
+
+ xo_close_container("operations");
+
+ xo_open_container("rpcs");
+ if (printtitle)
+ xo_emit("{T:Rpc Info:}\n");
+
+ xo_emit("{T:TimedOut/%13.13s}{T:Invalid/%13.13s}"
+ "{T:X Replies/%13.13s}{T:Retries/%13.13s}"
+ "{T:Requests/%13.13s}\n");
+ xo_emit("{:timedout/%13ju}{:invalid/%13ju}"
+ "{:xreplies/%13ju}{:retries/%13ju}"
+ "{:requests/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpctimeouts,
+ (uintmax_t)ext_nfsstats.rpcinvalid,
+ (uintmax_t)ext_nfsstats.rpcunexpected,
+ (uintmax_t)ext_nfsstats.rpcretries,
+ (uintmax_t)ext_nfsstats.rpcrequests);
+ xo_close_container("rpcs");
+
+ xo_open_container("cache");
+ if (printtitle)
+ xo_emit("{T:Cache Info:}\n");
+
+ xo_emit("{T:Attr Hits/%13.13s}{T:Attr Misses/%13.13s}"
+ "{T:Lkup Hits/%13.13s}{T:Lkup Misses/%13.13s}"
+ "{T:BioR Hits/%13.13s}{T:BioR Misses/%13.13s}"
+ "{T:BioW Hits/%13.13s}{T:BioW Misses/%13.13s}\n");
+ xo_emit("{:attrhits/%13ju}{:attrmisses/%13ju}"
+ "{:lkuphits/%13ju}{:lkupmisses/%13ju}"
+ "{:biorhits/%13ju}{:biormisses/%13ju}"
+ "{:biowhits/%13ju}{:biowmisses/%13ju}\n",
+ (uintmax_t)ext_nfsstats.attrcache_hits,
+ (uintmax_t)ext_nfsstats.attrcache_misses,
+ (uintmax_t)ext_nfsstats.lookupcache_hits,
+ (uintmax_t)ext_nfsstats.lookupcache_misses,
+ (uintmax_t)(ext_nfsstats.biocache_reads -
+ ext_nfsstats.read_bios),
+ (uintmax_t)ext_nfsstats.read_bios,
+ (uintmax_t)(ext_nfsstats.biocache_writes -
+ ext_nfsstats.write_bios),
+ (uintmax_t)ext_nfsstats.write_bios);
+
+ xo_emit("{T:BioRL Hits/%13.13s}{T:BioRL Misses/%13.13s}"
+ "{T:BioD Hits/%13.13s}{T:BioD Misses/%13.13s}"
+ "{T:DirE Hits/%13.13s}{T:DirE Misses/%13.13s}"
+ "{T:Accs Hits/%13.13s}{T:Accs Misses/%13.13s}\n");
+ xo_emit("{:biosrlhits/%13ju}{:biorlmisses/%13ju}"
+ "{:biodhits/%13ju}{:biodmisses/%13ju}"
+ "{:direhits/%13ju}{:diremisses/%13ju}"
+ "{:accshits/%13ju}{:accsmisses/%13ju}\n",
+ (uintmax_t)(ext_nfsstats.biocache_readlinks -
+ ext_nfsstats.readlink_bios),
+ (uintmax_t)ext_nfsstats.readlink_bios,
+ (uintmax_t)(ext_nfsstats.biocache_readdirs -
+ ext_nfsstats.readdir_bios),
+ (uintmax_t)ext_nfsstats.readdir_bios,
+ (uintmax_t)ext_nfsstats.direofcache_hits,
+ (uintmax_t)ext_nfsstats.direofcache_misses,
+ (uintmax_t)ext_nfsstats.accesscache_hits,
+ (uintmax_t)ext_nfsstats.accesscache_misses);
+
+ xo_close_container("cache");
+
+ xo_close_container("clientstats");
+ }
+ if (serverOnly) {
+ xo_open_container("serverstats");
+
+ if (printtitle)
+ xo_emit("{T:Server Info:}\n");
+ xo_open_container("operations");
+
+ xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}"
+ "{T:Lookup/%13.13s}{T:Readlink/%13.13s}"
+ "{T:Read/%13.13s}{T:Write/%13.13s}"
+ "{T:Create/%13.13s}{T:Remove/%13.13s}\n");
+ xo_emit("{:getattr/%13ju}{:setattr/%13ju}"
+ "{:lookup/%13ju}{:readlink/%13ju}"
+ "{:read/%13ju}{:write/%13ju}"
+ "{:create/%13ju}{:remove/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
+
+ xo_emit("{T:Rename/%13.13s}{T:Link/%13.13s}"
+ "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}"
+ "{T:Rmdir/%13.13s}{T:Readdir/%13.13s}"
+ "{T:RdirPlus/%13.13s}{T:Access/%13.13s}\n");
+ xo_emit("{:rename/%13ju}{:link/%13ju}"
+ "{:symlink/%13ju}{:mkdir/%13ju}"
+ "{:rmdir/%13ju}{:readdir/%13ju}"
+ "{:rdirplus/%13ju}{:access/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
+
+ xo_emit("{T:Mknod/%13.13s}{T:Fsstat/%13.13s}"
+ "{T:Fsinfo/%13.13s}{T:PathConf/%13.13s}"
+ "{T:Commit/%13.13s}\n");
+ xo_emit("{:mknod/%13ju}{:fsstat/%13ju}"
+ "{:fsinfo/%13ju}{:pathconf/%13ju}"
+ "{:commit/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]);
+
+ xo_close_container("operations");
+
+ xo_open_container("server");
+
+ if (printtitle)
+ xo_emit("{T:Server Write Gathering:/%13.13s}\n");
+
+ xo_emit("{T:WriteOps/%13.13s}{T:WriteRPC/%13.13s}"
+ "{T:Opsaved/%13.13s}\n");
+ xo_emit("{:writeops/%13ju}{:writerpc/%13ju}"
+ "{:opsaved/%13ju}\n",
+ /*
+ * The new client doesn't do write gathering. It was
+ * only useful for NFSv2.
+ */
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0);
+
+ xo_close_container("server");
+
+ xo_open_container("cache");
+ if (printtitle)
+ xo_emit("{T:Server Cache Stats:/%13.13s}\n");
+ xo_emit("{T:Inprog/%13.13s}"
+ "{T:Non-Idem/%13.13s}{T:Misses/%13.13s}\n");
+ xo_emit("{:inprog/%13ju}{:nonidem/%13ju}{:misses/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvcache_inproghits,
+ (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
+ (uintmax_t)ext_nfsstats.srvcache_misses);
+ xo_close_container("cache");
+
+ xo_close_container("serverstats");
+ }
+}
+
+static void
+printhdr(int clientOnly, int serverOnly, int newStats)
+{
+
+ if (newStats) {
+ printf(" [%s Read %s] [%s Write %s] "
+ "%s[=========== Total ============]\n"
+ " KB/t tps MB/s%s KB/t tps MB/s%s "
+ "%sKB/t tps MB/s ms ql %%b",
+ widemode ? "========" : "=====",
+ widemode ? "========" : "=====",
+ widemode ? "========" : "=====",
+ widemode ? "=======" : "====",
+ widemode ? "[Commit ] " : "",
+ widemode ? " ms" : "",
+ widemode ? " ms" : "",
+ widemode ? "tps ms " : "");
+ } else {
+ printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
+ ((serverOnly && clientOnly) ? " " : " "),
+ "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename",
+ "Access", "Rddir");
+ if (widemode && clientOnly) {
+ printf(" Attr Lkup BioR BioW Accs BioD");
+ }
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+static void
+usage(void)
+{
+ xo_error("usage: nfsstat [-cdEemqszW] [-w wait]\n");
+ exit(1);
+}
+
+static char SPBuf[64][8];
+static int SPIndex;
+
+static char *
+sperc1(int hits, int misses)
+{
+ char *p = SPBuf[SPIndex];
+
+ if (hits + misses) {
+ sprintf(p, "%3d%%",
+ (int)(char)((quad_t)hits * 100 / (hits + misses)));
+ } else {
+ sprintf(p, " -");
+ }
+ SPIndex = (SPIndex + 1) & 63;
+ return(p);
+}
+
+static char *
+sperc2(int ttl, int misses)
+{
+ char *p = SPBuf[SPIndex];
+
+ if (ttl) {
+ sprintf(p, "%3d%%",
+ (int)(char)((quad_t)(ttl - misses) * 100 / ttl));
+ } else {
+ sprintf(p, " -");
+ }
+ SPIndex = (SPIndex + 1) & 63;
+ return(p);
+}
+
+#define DELTA_T(field) \
+ devstat_compute_etime(&cur_stats->field, \
+ (prev_stats ? &prev_stats->field : NULL))
+
+/*
+ * XXX KDM mostly copied from ctlstat. We should commonize the code (and
+ * the devstat code) somehow.
+ */
+static void
+compute_new_stats(struct nfsstatsv1 *cur_stats,
+ struct nfsstatsv1 *prev_stats, int curop,
+ long double etime, long double *mbsec,
+ long double *kb_per_transfer,
+ long double *transfers_per_second,
+ long double *ms_per_transfer, uint64_t *queue_len,
+ long double *busy_pct)
+{
+ uint64_t total_bytes = 0, total_operations = 0;
+ struct bintime total_time_bt;
+ struct timespec total_time_ts;
+
+ bzero(&total_time_bt, sizeof(total_time_bt));
+ bzero(&total_time_ts, sizeof(total_time_ts));
+
+ total_bytes = cur_stats->srvbytes[curop];
+ total_operations = cur_stats->srvops[curop];
+ if (prev_stats != NULL) {
+ total_bytes -= prev_stats->srvbytes[curop];
+ total_operations -= prev_stats->srvops[curop];
+ }
+
+ *mbsec = total_bytes;
+ *mbsec /= 1024 * 1024;
+ if (etime > 0.0) {
+ *busy_pct = DELTA_T(busytime);
+ if (*busy_pct < 0)
+ *busy_pct = 0;
+ *busy_pct /= etime;
+ *busy_pct *= 100;
+ if (*busy_pct < 0)
+ *busy_pct = 0;
+ *mbsec /= etime;
+ } else {
+ *busy_pct = 0;
+ *mbsec = 0;
+ }
+ *kb_per_transfer = total_bytes;
+ *kb_per_transfer /= 1024;
+ if (total_operations > 0)
+ *kb_per_transfer /= total_operations;
+ else
+ *kb_per_transfer = 0;
+ if (etime > 0.0) {
+ *transfers_per_second = total_operations;
+ *transfers_per_second /= etime;
+ } else {
+ *transfers_per_second = 0.0;
+ }
+
+ if (total_operations > 0) {
+ *ms_per_transfer = DELTA_T(srvduration[curop]);
+ *ms_per_transfer /= total_operations;
+ *ms_per_transfer *= 1000;
+ } else
+ *ms_per_transfer = 0.0;
+
+ *queue_len = cur_stats->srvstartcnt - cur_stats->srvdonecnt;
+}
+
+/*
+ * Print a description of the nfs stats for the client/server,
+ * including NFSv4.1.
+ */
+static void
+exp_intpr(int clientOnly, int serverOnly, int nfs41)
+{
+ int nfssvc_flag;
+
+ xo_open_container("nfsv4");
+
+ nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
+ if (zflag != 0) {
+ if (clientOnly != 0)
+ nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
+ if (serverOnly != 0)
+ nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
+ }
+ ext_nfsstats.vers = NFSSTATS_V1;
+ if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
+ xo_err(1, "Can't get stats");
+ if (clientOnly != 0) {
+ xo_open_container("clientstats");
+
+ xo_open_container("operations");
+ if (printtitle) {
+ xo_emit("{T:Client Info:}\n");
+ xo_emit("{T:RPC Counts:}\n");
+ }
+ xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}"
+ "{T:Lookup/%13.13s}{T:Readlink/%13.13s}"
+ "{T:Read/%13.13s}{T:Write/%13.13s}\n");
+ xo_emit("{:getattr/%13ju}{:setattr/%13ju}{:lookup/%13ju}"
+ "{:readlink/%13ju}{:read/%13ju}{:write/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE]);
+ xo_emit("{T:Create/%13.13s}{T:Remove/%13.13s}"
+ "{T:Rename/%13.13s}{T:Link/%13.13s}"
+ "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}\n");
+ xo_emit("{:create/%13ju}{:remove/%13ju}{:rename/%13ju}"
+ "{:link/%13ju}{:symlink/%13ju}{:mkdir/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR]);
+ xo_emit("{T:Rmdir/%13.13s}{T:Readdir/%13.13s}"
+ "{T:RdirPlus/%13.13s}{T:Access/%13.13s}"
+ "{T:Mknod/%13.13s}{T:Fsstat/%13.13s}\n");
+ xo_emit("{:rmdir/%13ju}{:readdir/%13ju}{:rdirplus/%13ju}"
+ "{:access/%13ju}{:mknod/%13ju}{:fsstat/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT]);
+ xo_emit("{T:FSinfo/%13.13s}{T:pathConf/%13.13s}"
+ "{T:Commit/%13.13s}{T:SetClId/%13.13s}"
+ "{T:SetClIdCf/%13.13s}{T:Lock/%13.13s}\n");
+ xo_emit("{:fsinfo/%13ju}{:pathconf/%13ju}{:commit/%13ju}"
+ "{:setclientid/%13ju}{:setclientidcf/%13ju}{:lock/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCK]);
+ xo_emit("{T:LockT/%13.13s}{T:LockU/%13.13s}"
+ "{T:Open/%13.13s}{T:OpenCfr/%13.13s}\n");
+ xo_emit("{:lockt/%13ju}{:locku/%13ju}"
+ "{:open/%13ju}{:opencfr/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKT],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKU],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPEN],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]);
+
+ if (nfs41) {
+ xo_open_container("nfsv41");
+
+ xo_emit("{T:OpenDownGr/%13.13s}{T:Close/%13.13s}\n");
+ xo_emit("{:opendowngr/%13ju}{:close/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENDOWNGRADE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CLOSE]);
+
+ xo_emit("{T:RelLckOwn/%13.13s}{T:FreeStateID/%13.13s}"
+ "{T:PutRootFH/%13.13s}{T:DelegRet/%13.13s}"
+ "{T:GetAcl/%13.13s}{T:SetAcl/%13.13s}\n");
+ xo_emit("{:rellckown/%13ju}{:freestateid/%13ju}"
+ "{:putrootfh/%13ju}{:delegret/%13ju}"
+ "{:getacl/%13ju}{:setacl/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RELEASELCKOWN],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FREESTATEID],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PUTROOTFH],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DELEGRETURN],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETACL],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETACL]);
+
+ xo_emit("{T:ExchangeId/%13.13s}{T:CreateSess/%13.13s}"
+ "{T:DestroySess/%13.13s}{T:DestroyClId/%13.13s}"
+ "{T:LayoutGet/%13.13s}{T:GetDevInfo/%13.13s}\n");
+ xo_emit("{:exchangeid/%13ju}{:createsess/%13ju}"
+ "{:destroysess/%13ju}{:destroyclid/%13ju}"
+ "{:layoutget/%13ju}{:getdevinfo/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_EXCHANGEID],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATESESSION],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYSESSION],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYCLIENT],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTGET],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETDEVICEINFO]);
+
+ xo_emit("{T:LayoutCommit/%13.13s}{T:LayoutReturn/%13.13s}"
+ "{T:ReclaimCompl/%13.13s}{T:ReadDataS/%13.13s}"
+ "{T:WriteDataS/%13.13s}{T:CommitDataS/%13.13s}\n");
+ xo_emit("{:layoutcomit/%13ju}{:layoutreturn/%13ju}"
+ "{:reclaimcompl/%13ju}{:readdatas/%13ju}"
+ "{:writedatas/%13ju}{:commitdatas/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTCOMMIT],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTRETURN],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RECLAIMCOMPL],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITEDS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]);
+
+ xo_emit("{T:OpenLayout/%13.13s}{T:CreateLayout/%13.13s}"
+ "{T:BindConnSess/%13.13s}{T:LookupOpen/%13.13s}"
+ "{T:AppendWrite/%13.13s}\n");
+ xo_emit("{:openlayout/%13ju}{:createlayout/%13ju}"
+ "{:bindconnsess/%13ju}{:lookupopen/%13ju}"
+ "{:appendwrite/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENLAYGET],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATELAYGET],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_BINDCONNTOSESS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUPOPEN],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_APPENDWRITE]);
+
+ xo_close_container("nfsv41");
+
+ xo_open_container("nfsv42");
+
+ xo_emit("{T:IOAdvise/%13.13s}{T:Allocate/%13.13s}"
+ "{T:Copy/%13.13s}{T:Seek/%13.13s}"
+ "{T:SeekDataS/%13.13s}{T:GetExtattr/%13.13s}\n");
+ xo_emit("{:ioadvise/%13ju}{:allocate/%13ju}"
+ "{:copy/%13ju}{:seek/%13ju}"
+ "{:seekdatas/%13ju}{:getextattr/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_IOADVISE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ALLOCATE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COPY],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SEEK],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SEEKDS],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETEXTATTR]);
+
+ xo_emit("{T:SetExtattr/%13.13s}{T:RmExtattr/%13.13s}"
+ "{T:ListExtattr/%13.13s}{T:Deallocate/%13.13s}"
+ "{T:LayoutError/%13.13s}\n");
+ xo_emit("{:setextattr/%13ju}{:rmextattr/%13ju}"
+ "{:listextattr/%13ju}{:deallocate/%13ju}"
+ "{:layouterror/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETEXTATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMEXTATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LISTEXTATTR],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DEALLOCATE],
+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTERROR]);
+
+ xo_close_container("nfsv42");
+ }
+ xo_close_container("operations");
+
+ if (printtitle)
+ xo_emit("{T:Client:}\n");
+ xo_open_container("client");
+ xo_emit("{T:OpenOwner/%13.13s}{T:Opens/%13.13s}"
+ "{T:LockOwner/%13.13s}{T:Locks/%13.13s}"
+ "{T:Delegs/%13.13s}{T:LocalOwn/%13.13s}\n");
+ xo_emit("{:openowner/%13ju}{:opens/%13ju}"
+ "{:lockowner/%13ju}{:locks/%13ju}"
+ "{:delegs/%13ju}{:localown/%13ju}\n",
+ (uintmax_t)ext_nfsstats.clopenowners,
+ (uintmax_t)ext_nfsstats.clopens,
+ (uintmax_t)ext_nfsstats.cllockowners,
+ (uintmax_t)ext_nfsstats.cllocks,
+ (uintmax_t)ext_nfsstats.cldelegates,
+ (uintmax_t)ext_nfsstats.cllocalopenowners);
+
+ xo_emit("{T:LocalOpen/%13.13s}{T:LocalLown/%13.13s}"
+ "{T:LocalLock/%13.13s}{T:Layouts/%13.13s}\n");
+ xo_emit("{:localopen/%13ju}{:locallown/%13ju}"
+ "{:locallock/%13ju}{:layouts/%13ju}\n",
+ (uintmax_t)ext_nfsstats.cllocalopens,
+ (uintmax_t)ext_nfsstats.cllocallockowners,
+ (uintmax_t)ext_nfsstats.cllocallocks,
+ (uintmax_t)ext_nfsstats.cllayouts);
+ xo_close_container("client");
+
+ xo_open_container("rpc");
+ if (printtitle)
+ xo_emit("{T:Rpc Info:}\n");
+ xo_emit("{T:TimedOut/%13.13s}{T:Invalid/%13.13s}"
+ "{T:X Replies/%13.13s}{T:Retries/%13.13s}"
+ "{T:Requests/%13.13s}\n");
+ xo_emit("{:timedout/%13ju}{:invalid/%13ju}"
+ "{:xreplies/%13ju}{:retries/%13ju}"
+ "{:requests/%13ju}\n",
+ (uintmax_t)ext_nfsstats.rpctimeouts,
+ (uintmax_t)ext_nfsstats.rpcinvalid,
+ (uintmax_t)ext_nfsstats.rpcunexpected,
+ (uintmax_t)ext_nfsstats.rpcretries,
+ (uintmax_t)ext_nfsstats.rpcrequests);
+ xo_close_container("rpc");
+
+ xo_open_container("cache");
+ if (printtitle)
+ xo_emit("{T:Cache Info:}\n");
+ xo_emit("{T:Attr Hits/%13.13s}{T:Attr Misses/%13.13s}"
+ "{T:Lkup Hits/%13.13s}{T:Lkup Misses/%13.13s}\n");
+ xo_emit("{:attrhits/%13ju}{:attrmisses/%13ju}"
+ "{:lkuphits/%13ju}{:lkupmisses/%13ju}\n",
+ (uintmax_t)ext_nfsstats.attrcache_hits,
+ (uintmax_t)ext_nfsstats.attrcache_misses,
+ (uintmax_t)ext_nfsstats.lookupcache_hits,
+ (uintmax_t)ext_nfsstats.lookupcache_misses);
+
+ xo_emit("{T:BioR Hits/%13.13s}{T:BioR Misses/%13.13s}"
+ "{T:BioW Hits/%13.13s}{T:BioW Misses/%13.13s}\n");
+ xo_emit("{:biorhits/%13ju}{:biormisses/%13ju}"
+ "{:biowhits/%13ju}{:biowmisses/%13ju}\n",
+ (uintmax_t)(ext_nfsstats.biocache_reads -
+ ext_nfsstats.read_bios),
+ (uintmax_t)ext_nfsstats.read_bios,
+ (uintmax_t)(ext_nfsstats.biocache_writes -
+ ext_nfsstats.write_bios),
+ (uintmax_t)ext_nfsstats.write_bios);
+
+ xo_emit("{T:BioRL Hits/%13.13s}{T:BioRL Misses/%13.13s}"
+ "{T:BioD Hits/%13.13s}{T:BioD Misses/%13.13s}\n");
+ xo_emit("{:biorlhits/%13ju}{:biorlmisses/%13ju}"
+ "{:biodhits/%13ju}{:biodmisses/%13ju}\n",
+ (uintmax_t)(ext_nfsstats.biocache_readlinks -
+ ext_nfsstats.readlink_bios),
+ (uintmax_t)ext_nfsstats.readlink_bios,
+ (uintmax_t)(ext_nfsstats.biocache_readdirs -
+ ext_nfsstats.readdir_bios),
+ (uintmax_t)ext_nfsstats.readdir_bios);
+
+ xo_emit("{T:DirE Hits/%13.13s}{T:DirE Misses/%13.13s}\n");
+ xo_emit("{:direhits/%13ju}{:diremisses/%13ju}\n",
+ (uintmax_t)ext_nfsstats.direofcache_hits,
+ (uintmax_t)ext_nfsstats.direofcache_misses);
+ xo_open_container("cache");
+
+ xo_close_container("clientstats");
+ }
+ if (serverOnly != 0) {
+ xo_open_container("serverstats");
+
+ xo_open_container("operations");
+ if (printtitle)
+ xo_emit("{T:Server Info:}\n");
+ xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}"
+ "{T:Lookup/%13.13s}{T:Readlink/%13.13s}"
+ "{T:Read/%13.13s}{T:Write/%13.13s}\n");
+ xo_emit("{:getattr/%13ju}{:setattr/%13ju}{:lookup/%13ju}"
+ "{:readlink/%13ju}{:read/%13ju}{:write/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE]);
+ xo_emit("{T:Create/%13.13s}{T:Remove/%13.13s}"
+ "{T:Rename/%13.13s}{T:Link/%13.13s}"
+ "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}\n");
+ xo_emit("{:create/%13ju}{:remove/%13ju}{:rename/%13ju}"
+ "{:link/%13ju}{:symlink/%13ju}{:mkdir/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR]);
+ xo_emit("{T:Rmdir/%13.13s}{T:Readdir/%13.13s}"
+ "{T:RdirPlus/%13.13s}{T:Access/%13.13s}"
+ "{T:Mknod/%13.13s}{T:Fsstat/%13.13s}\n");
+ xo_emit("{:rmdir/%13ju}{:readdir/%13ju}{:rdirplus/%13ju}"
+ "{:access/%13ju}{:mknod/%13ju}{:fsstat/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT]);
+ xo_emit("{T:FSinfo/%13.13s}{T:pathConf/%13.13s}"
+ "{T:Commit/%13.13s}{T:LookupP/%13.13s}"
+ "{T:SetClId/%13.13s}{T:SetClIdCf/%13.13s}\n");
+ xo_emit("{:fsinfo/%13ju}{:pathconf/%13ju}{:commit/%13ju}"
+ "{:lookupp/%13ju}{:setclientid/%13ju}{:setclientidcfrm/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
+ xo_emit("{T:Open/%13.13s}{T:OpenAttr/%13.13s}"
+ "{T:OpenDwnGr/%13.13s}{T:OpenCfrm/%13.13s}"
+ "{T:DelePurge/%13.13s}{T:DelRet/%13.13s}\n");
+ xo_emit("{:open/%13ju}{:openattr/%13ju}{:opendwgr/%13ju}"
+ "{:opencfrm/%13ju}{:delepurge/%13ju}{:delreg/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN]);
+ xo_emit("{T:GetFH/%13.13s}{T:Lock/%13.13s}"
+ "{T:LockT/%13.13s}{T:LockU/%13.13s}"
+ "{T:Close/%13.13s}{T:Verify/%13.13s}\n");
+ xo_emit("{:getfh/%13ju}{:lock/%13ju}{:lockt/%13ju}"
+ "{:locku/%13ju}{:close/%13ju}{:verify/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY]);
+ xo_emit("{T:NVerify/%13.13s}{T:PutFH/%13.13s}"
+ "{T:PutPubFH/%13.13s}{T:PutRootFH/%13.13s}"
+ "{T:Renew/%13.13s}{T:RestoreFH/%13.13s}\n");
+ xo_emit("{:nverify/%13ju}{:putfh/%13ju}{:putpubfh/%13ju}"
+ "{:putrootfh/%13ju}{:renew/%13ju}{:restore/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH]);
+ xo_emit("{T:SaveFH/%13.13s}{T:Secinfo/%13.13s}"
+ "{T:RelLockOwn/%13.13s}{T:V4Create/%13.13s}\n");
+ xo_emit("{:savefh/%13ju}{:secinfo/%13ju}{:rellockown/%13ju}"
+ "{:v4create/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]);
+ if (nfs41) {
+ xo_open_container("nfsv41");
+ xo_emit("{T:BackChannelCtrl/%13.13s}{T:BindConnToSess/%13.13s}"
+ "{T:ExchangeID/%13.13s}{T:CreateSess/%13.13s}"
+ "{T:DestroySess/%13.13s}{T:FreeStateID/%13.13s}\n");
+ xo_emit("{:backchannelctrl/%13ju}{:bindconntosess/%13ju}"
+ "{:exchangeid/%13ju}{:createsess/%13ju}"
+ "{:destroysess/%13ju}{:freestateid/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BACKCHANNELCTL],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BINDCONNTOSESS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_EXCHANGEID],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATESESSION],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYSESSION],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FREESTATEID]),
+
+ xo_emit("{T:GetDirDeleg/%13.13s}{T:GetDevInfo/%13.13s}"
+ "{T:GetDevList/%13.13s}{T:layoutCommit/%13.13s}"
+ "{T:LayoutGet/%13.13s}{T:LayoutReturn/%13.13s}\n");
+ xo_emit("{:getdirdeleg/%13ju}{:getdevinfo/%13ju}"
+ "{:getdevlist/%13ju}{:layoutcommit/%13ju}"
+ "{:layoutget/%13ju}{:layoutreturn/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDIRDELEG],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVINFO],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVLIST],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTCOMMIT],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTGET],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTRETURN]);
+
+ xo_emit("{T:SecInfNoName/%13.13s}{T:Sequence/%13.13s}"
+ "{T:SetSSV/%13.13s}{T:TestStateID/%13.13s}"
+ "{T:WantDeleg/%13.13s}{T:DestroyClId/%13.13s}\n");
+ xo_emit("{:secinfnoname/%13ju}{:sequence/%13ju}"
+ "{:setssv/%13ju}{:teststateid/%13ju}{:wantdeleg/%13ju}"
+ "{:destroyclid/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFONONAME],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SEQUENCE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETSSV],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_TESTSTATEID],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WANTDELEG],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYCLIENTID]);
+
+ xo_emit("{T:ReclaimCompl/%13.13s}\n");
+ xo_emit("{:reclaimcompl/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RECLAIMCOMPL]);
+
+ xo_close_container("nfsv41");
+
+ xo_open_container("nfsv42");
+
+ xo_emit("{T:Allocate/%13.13s}{T:Copy/%13.13s}"
+ "{T:CopyNotify/%13.13s}{T:Deallocate/%13.13s}"
+ "{T:IOAdvise/%13.13s}{T:LayoutError/%13.13s}\n");
+ xo_emit("{:allocate/%13ju}{:copy/%13ju}"
+ "{:copynotify/%13ju}{:deallocate/%13ju}"
+ "{:ioadvise/%13ju}{:layouterror/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ALLOCATE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COPY],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COPYNOTIFY],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DEALLOCATE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_IOADVISE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTERROR]);
+
+ xo_emit("{T:LayoutStats/%13.13s}{T:OffloadCncl/%13.13s}"
+ "{T:OffloadStat/%13.13s}{T:ReadPlus/%13.13s}"
+ "{T:Seek/%13.13s}{T:WriteSame/%13.13s}\n");
+ xo_emit("{:layoutstats/%13ju}{:offloadcncl/%13ju}"
+ "{:offloadstat/%13ju}{:readplus/%13ju}"
+ "{:seek/%13ju}{:writesame/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTSTATS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OFFLOADCANCEL],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OFFLOADSTATUS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READPLUS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SEEK],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITESAME]);
+
+ xo_emit("{T:Clone/%13.13s}{T:GetExtattr/%13.13s}"
+ "{T:SetExtattr/%13.13s}{T:ListExtattr/%13.13s}"
+ "{T:RmExtattr/%13.13s}\n");
+ xo_emit("{:clone/%13ju}{:getextattr/%13ju}"
+ "{:setextattr/%13ju}{:listextattr/%13ju}"
+ "{:rmextattr/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLONE],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETXATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETXATTR],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LISTXATTRS],
+ (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVEXATTR]);
+
+ xo_close_container("nfsv42");
+ }
+
+ xo_close_container("operations");
+
+ if (printtitle)
+ xo_emit("{T:Server:}\n");
+ xo_open_container("server");
+ xo_emit("{T:Clients/%13.13s}{T:OpenOwner/%13.13s}"
+ "{T:Opens/%13.13s}{T:LockOwner/%13.13s}{T:Locks/%13.13s}"
+ "{T:Delegs/%13.13s}\n");
+ xo_emit("{:clients/%13ju}{:openowner/%13ju}{:opens/%13ju}"
+ "{:lockowner/%13ju}{:locks/%13ju}{:delegs/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvclients,
+ (uintmax_t)ext_nfsstats.srvopenowners,
+ (uintmax_t)ext_nfsstats.srvopens,
+ (uintmax_t)ext_nfsstats.srvlockowners,
+ (uintmax_t)ext_nfsstats.srvlocks,
+ (uintmax_t)ext_nfsstats.srvdelegates);
+ xo_emit("{T:Layouts/%13.13s}\n");
+ xo_emit("{:layouts/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvlayouts);
+ xo_close_container("server");
+
+ if (printtitle)
+ xo_emit("{T:Server Cache Stats:}\n");
+ xo_open_container("cache");
+ xo_emit("{T:Inprog/%13.13s}"
+ "{T:Non-idem/%13.13s}{T:Misses/%13.13s}"
+ "{T:CacheSize/%13.13s}{T:TCPPeak/%13.13s}\n");
+ xo_emit("{:inprog/%13ju}{:nonidem/%13ju}"
+ "{:misses/%13ju}{:cachesize/%13ju}{:tcppeak/%13ju}\n",
+ (uintmax_t)ext_nfsstats.srvcache_inproghits,
+ (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
+ (uintmax_t)ext_nfsstats.srvcache_misses,
+ (uintmax_t)ext_nfsstats.srvcache_size,
+ (uintmax_t)ext_nfsstats.srvcache_tcppeak);
+ xo_close_container("cache");
+
+ xo_close_container("serverstats");
+ }
+
+ xo_close_container("nfsv4");
+}
+
+static void
+compute_totals(struct nfsstatsv1 *total_stats, struct nfsstatsv1 *cur_stats)
+{
+ int i;
+
+ bzero(total_stats, sizeof(*total_stats));
+ for (i = 0; i < (NFSV42_NOPS + NFSV4OP_FAKENOPS); i++) {
+ total_stats->srvbytes[0] += cur_stats->srvbytes[i];
+ total_stats->srvops[0] += cur_stats->srvops[i];
+ bintime_add(&total_stats->srvduration[0],
+ &cur_stats->srvduration[i]);
+ total_stats->srvrpccnt[i] = cur_stats->srvrpccnt[i];
+ }
+ total_stats->srvstartcnt = cur_stats->srvstartcnt;
+ total_stats->srvdonecnt = cur_stats->srvdonecnt;
+ total_stats->busytime = cur_stats->busytime;
+
+}
+
+/*
+ * Print a running summary of nfs statistics for the experimental client and/or
+ * server.
+ * Repeat display every interval seconds, showing statistics
+ * collected over that interval. Assumes that interval is non-zero.
+ * First line printed at top of screen is always cumulative.
+ */
+static void
+exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly,
+ int newStats)
+{
+ struct nfsstatsv1 nfsstats, lastst, *ext_nfsstatsp;
+ struct nfsstatsv1 curtotal, lasttotal;
+ struct timespec ts, lastts;
+ int hdrcnt = 1;
+
+ ext_nfsstatsp = &lastst;
+ ext_nfsstatsp->vers = NFSSTATS_V1;
+ if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp) < 0)
+ xo_err(1, "Can't get stats");
+ clock_gettime(CLOCK_MONOTONIC, &lastts);
+ compute_totals(&lasttotal, ext_nfsstatsp);
+ sleep(interval);
+
+ for (;;) {
+ ext_nfsstatsp = &nfsstats;
+ ext_nfsstatsp->vers = NFSSTATS_V1;
+ if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp)
+ < 0)
+ xo_err(1, "Can't get stats");
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ if (--hdrcnt == 0) {
+ printhdr(clientOnly, serverOnly, newStats);
+ if (newStats)
+ hdrcnt = 20;
+ else if (clientOnly && serverOnly)
+ hdrcnt = 10;
+ else
+ hdrcnt = 20;
+ }
+ if (clientOnly && newStats == 0) {
+ printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju",
+ ((clientOnly && serverOnly) ? "Client:" : ""),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_GETATTR]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_LOOKUP]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_READLINK]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_READ]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_WRITE]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_RENAME]),
+ (uintmax_t)DELTA(rpccnt[NFSPROC_ACCESS]),
+ (uintmax_t)(DELTA(rpccnt[NFSPROC_READDIR]) +
+ DELTA(rpccnt[NFSPROC_READDIRPLUS]))
+ );
+ if (widemode) {
+ printf(" %s %s %s %s %s %s",
+ sperc1(DELTA(attrcache_hits),
+ DELTA(attrcache_misses)),
+ sperc1(DELTA(lookupcache_hits),
+ DELTA(lookupcache_misses)),
+ sperc2(DELTA(biocache_reads),
+ DELTA(read_bios)),
+ sperc2(DELTA(biocache_writes),
+ DELTA(write_bios)),
+ sperc1(DELTA(accesscache_hits),
+ DELTA(accesscache_misses)),
+ sperc2(DELTA(biocache_readdirs),
+ DELTA(readdir_bios))
+ );
+ }
+ printf("\n");
+ }
+
+ if (serverOnly && newStats) {
+ long double cur_secs, last_secs, etime;
+ long double mbsec;
+ long double kb_per_transfer;
+ long double transfers_per_second;
+ long double ms_per_transfer;
+ uint64_t queue_len;
+ long double busy_pct;
+ int i;
+
+ cur_secs = ts.tv_sec +
+ ((long double)ts.tv_nsec / 1000000000);
+ last_secs = lastts.tv_sec +
+ ((long double)lastts.tv_nsec / 1000000000);
+ etime = cur_secs - last_secs;
+
+ compute_totals(&curtotal, &nfsstats);
+
+ for (i = 0; i < NUM_STAT_TYPES; i++) {
+ compute_new_stats(&nfsstats, &lastst,
+ STAT_TYPE_TO_NFS(i), etime, &mbsec,
+ &kb_per_transfer,
+ &transfers_per_second,
+ &ms_per_transfer, &queue_len,
+ &busy_pct);
+
+ if (i == STAT_TYPE_COMMIT) {
+ if (widemode == 0)
+ continue;
+
+ printf("%2.0Lf %7.2Lf ",
+ transfers_per_second,
+ ms_per_transfer);
+ } else {
+ printf("%5.2Lf %5.0Lf %7.2Lf ",
+ kb_per_transfer,
+ transfers_per_second, mbsec);
+ if (widemode)
+ printf("%5.2Lf ",
+ ms_per_transfer);
+ }
+ }
+
+ compute_new_stats(&curtotal, &lasttotal, 0, etime,
+ &mbsec, &kb_per_transfer, &transfers_per_second,
+ &ms_per_transfer, &queue_len, &busy_pct);
+
+ printf("%5.2Lf %5.0Lf %7.2Lf %5.2Lf %3ju %3.0Lf\n",
+ kb_per_transfer, transfers_per_second, mbsec,
+ ms_per_transfer, queue_len, busy_pct);
+ } else if (serverOnly) {
+ printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju",
+ ((clientOnly && serverOnly) ? "Server:" : ""),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_GETATTR]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_LOOKUP]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_READLINK]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_READ]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_WRITE]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_RENAME]),
+ (uintmax_t)DELTA(srvrpccnt[NFSV4OP_ACCESS]),
+ (uintmax_t)(DELTA(srvrpccnt[NFSV4OP_READDIR]) +
+ DELTA(srvrpccnt[NFSV4OP_READDIRPLUS])));
+ printf("\n");
+ }
+ bcopy(&nfsstats, &lastst, sizeof(lastst));
+ bcopy(&curtotal, &lasttotal, sizeof(lasttotal));
+ lastts = ts;
+ fflush(stdout);
+ sleep(interval);
+ }
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/nice/Makefile b/usr.bin/nice/Makefile
new file mode 100644
index 000000000000..4098b3b39b6f
--- /dev/null
+++ b/usr.bin/nice/Makefile
@@ -0,0 +1,3 @@
+PROG= nice
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nice/Makefile.depend b/usr.bin/nice/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/nice/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/nice/nice.1 b/usr.bin/nice/nice.1
new file mode 100644
index 000000000000..f61f6575fd6e
--- /dev/null
+++ b/usr.bin/nice/nice.1
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd February 24, 2011
+.Dt NICE 1
+.Os
+.Sh NAME
+.Nm nice
+.Nd execute a utility at an altered scheduling priority
+.Sh SYNOPSIS
+.Nm
+.Op Fl n Ar increment
+.Ar utility
+.Op Ar argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility runs
+.Ar utility
+at an altered scheduling priority, by incrementing its
+.Dq nice
+value by the specified
+.Ar increment ,
+or a default value of 10.
+The lower the nice value of a process, the higher its scheduling priority.
+.Pp
+The superuser may specify a negative increment in order to run a utility
+with a higher scheduling priority.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh ENVIRONMENT
+The
+.Ev PATH
+environment variable is used to locate the requested
+.Ar utility
+if the name contains no
+.Ql /
+characters.
+.Sh EXIT STATUS
+If
+.Ar utility
+is invoked, the exit status of
+.Nm
+is the exit status of
+.Ar utility .
+.Pp
+An exit status of 126 indicates
+.Ar utility
+was found, but could not be executed.
+An exit status of 127 indicates
+.Ar utility
+could not be found.
+.Sh EXAMPLES
+Execute utility
+.Sq date
+at priority 5 assuming the priority of the
+shell is 0:
+.Pp
+.Dl "nice -n 5 date"
+.Pp
+Execute utility
+.Sq date
+at priority -19 assuming the priority of the
+shell is 0 and you are the super-user:
+.Pp
+.Dl "nice -n 16 nice -n -35 date"
+.Sh COMPATIBILITY
+The traditional
+.Fl Ns Ar increment
+option has been deprecated but is still supported.
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr idprio 1 ,
+.Xr rtprio 1 ,
+.Xr getpriority 2 ,
+.Xr setpriority 2 ,
+.Xr renice 8
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v4 .
diff --git a/usr.bin/nice/nice.c b/usr.bin/nice/nice.c
new file mode 100644
index 000000000000..d6fda3fc3884
--- /dev/null
+++ b/usr.bin/nice/nice.c
@@ -0,0 +1,98 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define DEFNICE 10
+
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ long niceness = DEFNICE;
+ int ch;
+ char *ep;
+
+ /* Obsolescent syntax: -number, --number */
+ if (argc >= 2 && argv[1][0] == '-' && (argv[1][1] == '-' ||
+ isdigit((unsigned char)argv[1][1])) && strcmp(argv[1], "--") != 0)
+ if (asprintf(&argv[1], "-n%s", argv[1] + 1) < 0)
+ err(1, "asprintf");
+
+ while ((ch = getopt(argc, argv, "n:")) != -1) {
+ switch (ch) {
+ case 'n':
+ errno = 0;
+ niceness = strtol(optarg, &ep, 10);
+ if (ep == optarg || *ep != '\0' || errno ||
+ niceness < INT_MIN || niceness > INT_MAX)
+ errx(1, "%s: invalid nice value", optarg);
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+
+ errno = 0;
+ niceness += getpriority(PRIO_PROCESS, 0);
+ if (errno)
+ warn("getpriority");
+ else if (setpriority(PRIO_PROCESS, 0, (int)niceness))
+ warn("setpriority");
+ execvp(*argv, argv);
+ err(errno == ENOENT ? 127 : 126, "%s", *argv);
+}
+
+void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: nice [-n increment] utility [argument ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/nl/Makefile b/usr.bin/nl/Makefile
new file mode 100644
index 000000000000..66a14832e2a3
--- /dev/null
+++ b/usr.bin/nl/Makefile
@@ -0,0 +1,3 @@
+PROG= nl
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nl/Makefile.depend b/usr.bin/nl/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/nl/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/nl/nl.1 b/usr.bin/nl/nl.1
new file mode 100644
index 000000000000..170a36c8c343
--- /dev/null
+++ b/usr.bin/nl/nl.1
@@ -0,0 +1,284 @@
+.\"
+.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Klaus Klein.
+.\"
+.\" 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 July 24, 2022
+.Dt NL 1
+.Os
+.Sh NAME
+.Nm nl
+.Nd line numbering filter
+.Sh SYNOPSIS
+.Nm
+.Op Fl p
+.Bk -words
+.Op Fl b Ar type
+.Ek
+.Bk -words
+.Op Fl d Ar delim
+.Ek
+.Bk -words
+.Op Fl f Ar type
+.Ek
+.Bk -words
+.Op Fl h Ar type
+.Ek
+.Bk -words
+.Op Fl i Ar incr
+.Ek
+.Bk -words
+.Op Fl l Ar num
+.Ek
+.Bk -words
+.Op Fl n Ar format
+.Ek
+.Bk -words
+.Op Fl s Ar sep
+.Ek
+.Bk -words
+.Op Fl v Ar startnum
+.Ek
+.Bk -words
+.Op Fl w Ar width
+.Ek
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility reads lines from the named
+.Ar file ,
+applies a configurable line numbering filter operation,
+and writes the result to the standard output.
+If
+.Ar file
+is a single dash
+.Pq Sq Fl
+or absent,
+.Nm
+reads from the standard input.
+.Pp
+The
+.Nm
+utility treats the text it reads in terms of logical pages.
+Unless specified otherwise, line numbering is reset at the start of each
+logical page.
+A logical page consists of a header, a body and a footer
+section; empty sections are valid.
+Different line numbering options are
+independently available for header, body and footer sections.
+.Pp
+The starts of logical page sections are signalled by input lines containing
+nothing but one of the following sequences of delimiter characters:
+.Bl -column "\e:\e:\e:" "Start of" -offset indent
+.Em "Line Start of"
+.It "\e:\e:\e: header"
+.It "\e:\e: body"
+.It "\e: footer"
+.El
+.Pp
+If the input does not contain any logical page section signalling directives,
+the text being read is assumed to consist of a single logical page body.
+.Pp
+The following options are available:
+.Bl -tag -width ".Fl v Ar startnum"
+.It Fl b Ar type
+Specify the logical page body lines to be numbered.
+Recognized
+.Ar type
+arguments are:
+.Bl -tag -width indent
+.It Cm a
+Number all lines.
+.It Cm t
+Number only non-empty lines.
+.It Cm n
+No line numbering.
+.It Cm p Ns Ar expr
+Number only those lines that contain the basic regular expression specified
+by
+.Ar expr .
+.El
+.Pp
+The default
+.Ar type
+for logical page body lines is
+.Cm t .
+.It Fl d Ar delim
+Specify the delimiter characters used to indicate the start of a logical
+page section in the input file.
+At most two characters may be specified;
+if only one character is specified, the first character is replaced and the
+second character remains unchanged.
+The default
+.Ar delim
+characters are
+.Dq Li \e: .
+.It Fl f Ar type
+Specify the same as
+.Fl b Ar type
+except for logical page footer lines.
+The default
+.Ar type
+for logical page footer lines is
+.Cm n .
+.It Fl h Ar type
+Specify the same as
+.Fl b Ar type
+except for logical page header lines.
+The default
+.Ar type
+for logical page header lines is
+.Cm n .
+.It Fl i Ar incr
+Specify the increment value used to number logical page lines.
+The default
+.Ar incr
+value is 1.
+.It Fl l Ar num
+If numbering of all lines is specified for the current logical section
+using the corresponding
+.Fl b Cm a ,
+.Fl f Cm a
+or
+.Fl h Cm a
+option,
+specify the number of adjacent blank lines to be considered as one.
+For example,
+.Fl l
+2 results in only the second adjacent blank line being numbered.
+The default
+.Ar num
+value is 1.
+.It Fl n Ar format
+Specify the line numbering output format.
+Recognized
+.Ar format
+arguments are:
+.Bl -tag -width indent -compact
+.It Cm ln
+Left justified.
+.It Cm rn
+Right justified, leading zeros suppressed.
+.It Cm rz
+Right justified, leading zeros kept.
+.El
+.Pp
+The default
+.Ar format
+is
+.Cm rn .
+.It Fl p
+Specify that line numbering should not be restarted at logical page delimiters.
+.It Fl s Ar sep
+Specify the characters used in separating the line number and the corresponding
+text line.
+The default
+.Ar sep
+setting is a single tab character.
+.It Fl v Ar startnum
+Specify the initial value used to number logical page lines; see also the
+description of the
+.Fl p
+option.
+The default
+.Ar startnum
+value is 1.
+.It Fl w Ar width
+Specify the number of characters to be occupied by the line number;
+in case the
+.Ar width
+is insufficient to hold the line number, it will be truncated to its
+.Ar width
+least significant digits.
+The default
+.Ar width
+is 6.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_CTYPE
+and
+.Ev LC_COLLATE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Number all non-blank lines:
+.Bd -literal -offset indent
+$ echo -e "This is\\n\\n\\na simple text" | nl
+ 1 This is
+
+
+ 2 a simple text
+.Ed
+.Pp
+Number all lines including blank ones, with right justified line numbers with
+leading zeroes, starting at 2, with increment of 2 and a custom multi-character
+separator:
+.Bd -literal -offset indent
+$ echo -e "This\\nis\\nan\\n\\n\\nexample" | nl -ba -n rz -i2 -s "->" -v2
+000002->This
+000004->is
+000006->an
+000008->
+000010->
+000012->example
+.Ed
+.Pp
+Number lines matching regular expression for an
+.Em i
+.No followed by either
+.Em m
+.No or
+.Em n
+.Bd -literal -offset indent
+$ echo -e "This is\\na simple text\\nwith multiple\\nlines" | nl -bp'i[mn]'
+ This is
+ 1 a simple text
+ with multiple
+ 2 lines
+.Ed
+.Sh SEE ALSO
+.Xr jot 1 ,
+.Xr pr 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.At III .
+.Sh BUGS
+Input lines are limited to
+.Dv LINE_MAX
+(2048) bytes in length.
diff --git a/usr.bin/nl/nl.c b/usr.bin/nl/nl.c
new file mode 100644
index 000000000000..573e03e4ad0d
--- /dev/null
+++ b/usr.bin/nl/nl.c
@@ -0,0 +1,410 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * 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 <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include <capsicum_helpers.h>
+
+typedef enum {
+ number_all, /* number all lines */
+ number_nonempty, /* number non-empty lines */
+ number_none, /* no line numbering */
+ number_regex /* number lines matching regular expression */
+} numbering_type;
+
+struct numbering_property {
+ const char * const name; /* for diagnostics */
+ numbering_type type; /* numbering type */
+ regex_t expr; /* for type == number_regex */
+};
+
+/* line numbering formats */
+#define FORMAT_LN "%-*d" /* left justified, leading zeros suppressed */
+#define FORMAT_RN "%*d" /* right justified, leading zeros suppressed */
+#define FORMAT_RZ "%0*d" /* right justified, leading zeros kept */
+
+#define FOOTER 0
+#define BODY 1
+#define HEADER 2
+#define NP_LAST HEADER
+
+static struct numbering_property numbering_properties[NP_LAST + 1] = {
+ { .name = "footer", .type = number_none },
+ { .name = "body", .type = number_nonempty },
+ { .name = "header", .type = number_none }
+};
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/*
+ * Maximum number of characters required for a decimal representation of a
+ * (signed) int; courtesy of tzcode.
+ */
+#define INT_STRLEN_MAXIMUM \
+ ((sizeof (int) * CHAR_BIT - 1) * 302 / 1000 + 2)
+
+static void filter(void);
+static void parse_numbering(const char *, int);
+static void usage(void);
+
+/*
+ * Dynamically allocated buffer suitable for string representation of ints.
+ */
+static char *intbuffer;
+
+/* delimiter characters that indicate the start of a logical page section */
+static char delim[2 * MB_LEN_MAX];
+static int delimlen;
+
+/*
+ * Configurable parameters.
+ */
+
+/* line numbering format */
+static const char *format = FORMAT_RN;
+
+/* increment value used to number logical page lines */
+static int incr = 1;
+
+/* number of adjacent blank lines to be considered (and numbered) as one */
+static unsigned int nblank = 1;
+
+/* whether to restart numbering at logical page delimiters */
+static int restart = 1;
+
+/* characters used in separating the line number and the corrsp. text line */
+static const char *sep = "\t";
+
+/* initial value used to number logical page lines */
+static int startnum = 1;
+
+/* number of characters to be used for the line number */
+/* should be unsigned but required signed by `*' precision conversion */
+static int width = 6;
+
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ long val;
+ unsigned long uval;
+ char *ep;
+ size_t intbuffersize, clen;
+ char delim1[MB_LEN_MAX] = { '\\' }, delim2[MB_LEN_MAX] = { ':' };
+ size_t delim1len = 1, delim2len = 1;
+
+ (void)setlocale(LC_ALL, "");
+
+ while ((c = getopt(argc, argv, "pb:d:f:h:i:l:n:s:v:w:")) != -1) {
+ switch (c) {
+ case 'p':
+ restart = 0;
+ break;
+ case 'b':
+ parse_numbering(optarg, BODY);
+ break;
+ case 'd':
+ clen = mbrlen(optarg, MB_CUR_MAX, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ errc(EXIT_FAILURE, EILSEQ, NULL);
+ if (clen != 0) {
+ memcpy(delim1, optarg, delim1len = clen);
+ clen = mbrlen(optarg + delim1len,
+ MB_CUR_MAX, NULL);
+ if (clen == (size_t)-1 ||
+ clen == (size_t)-2)
+ errc(EXIT_FAILURE, EILSEQ, NULL);
+ if (clen != 0) {
+ memcpy(delim2, optarg + delim1len,
+ delim2len = clen);
+ if (optarg[delim1len + clen] != '\0')
+ errx(EXIT_FAILURE,
+ "invalid delim argument -- %s",
+ optarg);
+ }
+ }
+ break;
+ case 'f':
+ parse_numbering(optarg, FOOTER);
+ break;
+ case 'h':
+ parse_numbering(optarg, HEADER);
+ break;
+ case 'i':
+ errno = 0;
+ val = strtol(optarg, &ep, 10);
+ if ((ep != NULL && *ep != '\0') ||
+ ((val == LONG_MIN || val == LONG_MAX) && errno != 0))
+ errx(EXIT_FAILURE,
+ "invalid incr argument -- %s", optarg);
+ incr = (int)val;
+ break;
+ case 'l':
+ errno = 0;
+ uval = strtoul(optarg, &ep, 10);
+ if ((ep != NULL && *ep != '\0') ||
+ (uval == ULONG_MAX && errno != 0))
+ errx(EXIT_FAILURE,
+ "invalid num argument -- %s", optarg);
+ nblank = (unsigned int)uval;
+ break;
+ case 'n':
+ if (strcmp(optarg, "ln") == 0) {
+ format = FORMAT_LN;
+ } else if (strcmp(optarg, "rn") == 0) {
+ format = FORMAT_RN;
+ } else if (strcmp(optarg, "rz") == 0) {
+ format = FORMAT_RZ;
+ } else
+ errx(EXIT_FAILURE,
+ "illegal format -- %s", optarg);
+ break;
+ case 's':
+ sep = optarg;
+ break;
+ case 'v':
+ errno = 0;
+ val = strtol(optarg, &ep, 10);
+ if ((ep != NULL && *ep != '\0') ||
+ ((val == LONG_MIN || val == LONG_MAX) && errno != 0))
+ errx(EXIT_FAILURE,
+ "invalid startnum value -- %s", optarg);
+ startnum = (int)val;
+ break;
+ case 'w':
+ errno = 0;
+ val = strtol(optarg, &ep, 10);
+ if ((ep != NULL && *ep != '\0') ||
+ ((val == LONG_MIN || val == LONG_MAX) && errno != 0))
+ errx(EXIT_FAILURE,
+ "invalid width value -- %s", optarg);
+ width = (int)val;
+ if (!(width > 0))
+ errx(EXIT_FAILURE,
+ "width argument must be > 0 -- %d",
+ width);
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ if (strcmp(argv[0], "-") != 0 &&
+ freopen(argv[0], "r", stdin) == NULL)
+ err(EXIT_FAILURE, "%s", argv[0]);
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ /* Limit standard descriptors and enter capability mode */
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(EXIT_FAILURE, "capsicum");
+
+ /* Generate the delimiter sequence */
+ memcpy(delim, delim1, delim1len);
+ memcpy(delim + delim1len, delim2, delim2len);
+ delimlen = delim1len + delim2len;
+
+ /* Allocate a buffer suitable for preformatting line number. */
+ intbuffersize = max((int)INT_STRLEN_MAXIMUM, width) + 1; /* NUL */
+ if ((intbuffer = malloc(intbuffersize)) == NULL)
+ err(EXIT_FAILURE, "cannot allocate preformatting buffer");
+
+ /* Do the work. */
+ filter();
+
+ exit(EXIT_SUCCESS);
+ /* NOTREACHED */
+}
+
+static void
+filter(void)
+{
+ char *buffer;
+ size_t buffersize;
+ ssize_t linelen;
+ int line; /* logical line number */
+ int section; /* logical page section */
+ unsigned int adjblank; /* adjacent blank lines */
+ int consumed; /* intbuffer measurement */
+ int donumber = 0, idx;
+
+ adjblank = 0;
+ line = startnum;
+ section = BODY;
+
+ buffer = NULL;
+ buffersize = 0;
+ while ((linelen = getline(&buffer, &buffersize, stdin)) > 0) {
+ for (idx = FOOTER; idx <= NP_LAST; idx++) {
+ /* Does it look like a delimiter? */
+ if (delimlen * (idx + 1) > linelen)
+ break;
+ if (memcmp(buffer + delimlen * idx, delim,
+ delimlen) != 0)
+ break;
+ /* Was this the whole line? */
+ if (buffer[delimlen * (idx + 1)] == '\n') {
+ section = idx;
+ adjblank = 0;
+ if (restart)
+ line = startnum;
+ goto nextline;
+ }
+ }
+
+ switch (numbering_properties[section].type) {
+ case number_all:
+ /*
+ * Doing this for number_all only is disputable, but
+ * the standard expresses an explicit dependency on
+ * `-b a' etc.
+ */
+ if (buffer[0] == '\n' && ++adjblank < nblank)
+ donumber = 0;
+ else
+ donumber = 1, adjblank = 0;
+ break;
+ case number_nonempty:
+ donumber = (buffer[0] != '\n');
+ break;
+ case number_none:
+ donumber = 0;
+ break;
+ case number_regex:
+ donumber =
+ (regexec(&numbering_properties[section].expr,
+ buffer, 0, NULL, 0) == 0);
+ break;
+ }
+
+ if (donumber) {
+ /* Note: sprintf() is safe here. */
+ consumed = sprintf(intbuffer, format, width, line);
+ (void)printf("%s",
+ intbuffer + max(0, consumed - width));
+ line += incr;
+ } else {
+ (void)printf("%*s", width, "");
+ }
+ (void)fputs(sep, stdout);
+ (void)fwrite(buffer, linelen, 1, stdout);
+
+ if (ferror(stdout))
+ err(EXIT_FAILURE, "output error");
+nextline:
+ ;
+ }
+
+ if (ferror(stdin))
+ err(EXIT_FAILURE, "input error");
+
+ free(buffer);
+}
+
+/*
+ * Various support functions.
+ */
+
+static void
+parse_numbering(const char *argstr, int section)
+{
+ int error;
+ char errorbuf[NL_TEXTMAX];
+
+ switch (argstr[0]) {
+ case 'a':
+ numbering_properties[section].type = number_all;
+ break;
+ case 'n':
+ numbering_properties[section].type = number_none;
+ break;
+ case 't':
+ numbering_properties[section].type = number_nonempty;
+ break;
+ case 'p':
+ /* If there was a previous expression, throw it away. */
+ if (numbering_properties[section].type == number_regex)
+ regfree(&numbering_properties[section].expr);
+ else
+ numbering_properties[section].type = number_regex;
+
+ /* Compile/validate the supplied regular expression. */
+ if ((error = regcomp(&numbering_properties[section].expr,
+ &argstr[1], REG_NEWLINE|REG_NOSUB)) != 0) {
+ (void)regerror(error,
+ &numbering_properties[section].expr,
+ errorbuf, sizeof (errorbuf));
+ errx(EXIT_FAILURE,
+ "%s expr: %s -- %s",
+ numbering_properties[section].name, errorbuf,
+ &argstr[1]);
+ }
+ break;
+ default:
+ errx(EXIT_FAILURE,
+ "illegal %s line numbering type -- %s",
+ numbering_properties[section].name, argstr);
+ }
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+"usage: nl [-p] [-b type] [-d delim] [-f type] [-h type] [-i incr] [-l num]\n"
+" [-n format] [-s sep] [-v startnum] [-w width] [file]\n");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/nm/Makefile b/usr.bin/nm/Makefile
new file mode 100644
index 000000000000..c4c75725dd1c
--- /dev/null
+++ b/usr.bin/nm/Makefile
@@ -0,0 +1,22 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+NMDIR= ${ELFTCDIR}/nm
+
+.PATH: ${NMDIR}
+
+PROG= nm
+
+LIBADD= dwarf elftc elf
+
+.if ${MK_CASPER} != "no" && !defined(BOOTSTRAPPING) && !defined(NXB_TARGET)
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nm/Makefile.depend b/usr.bin/nm/Makefile.depend
new file mode 100644
index 000000000000..2f0bc69cb09a
--- /dev/null
+++ b/usr.bin/nm/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libdwarf \
+ lib/libelf \
+ lib/libelftc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/nm/Makefile.depend.options b/usr.bin/nm/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/nm/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/nohup/Makefile b/usr.bin/nohup/Makefile
new file mode 100644
index 000000000000..5698f6a5b474
--- /dev/null
+++ b/usr.bin/nohup/Makefile
@@ -0,0 +1,3 @@
+PROG= nohup
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/nohup/Makefile.depend b/usr.bin/nohup/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/nohup/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/nohup/nohup.1 b/usr.bin/nohup/nohup.1
new file mode 100644
index 000000000000..c985ac82cb8d
--- /dev/null
+++ b/usr.bin/nohup/nohup.1
@@ -0,0 +1,119 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 26, 2023
+.Dt NOHUP 1
+.Os
+.Sh NAME
+.Nm nohup
+.Nd invoke a utility immune to hangups
+.Sh SYNOPSIS
+.Nm
+.Op Fl Fl
+.Ar utility
+.Op Ar arguments
+.Sh DESCRIPTION
+The
+.Nm
+utility invokes
+.Ar utility
+with its
+.Ar arguments
+and at this time sets the signal
+.Dv SIGHUP
+to be ignored.
+If the standard output is a terminal, the standard output is
+appended to the file
+.Pa nohup.out
+in the current directory.
+If standard error is a terminal, it is directed to the same place
+as the standard output.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh ENVIRONMENT
+The following variables are utilized by
+.Nm :
+.Bl -tag -width flag
+.It Ev HOME
+If the output file
+.Pa nohup.out
+cannot be created in the current directory, the
+.Nm
+utility uses the directory named by
+.Ev HOME
+to create the file.
+.It Ev PATH
+Used to locate the requested
+.Ar utility
+if the name contains no
+.Ql /
+characters.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Bl -tag -width Ds
+.It 126
+The
+.Ar utility
+was found, but could not be invoked.
+.It 127
+The
+.Ar utility
+could not be found or an error occurred in
+.Nm .
+.El
+.Pp
+Otherwise, the exit status of
+.Nm
+will be that of
+.Ar utility .
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr timeout 1 ,
+.Xr signal 3 ,
+.Xr daemon 8
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+.Sh BUGS
+Two or more instances of
+.Nm
+can append to the same file, which makes for a confusing output.
diff --git a/usr.bin/nohup/nohup.c b/usr.bin/nohup/nohup.c
new file mode 100644
index 000000000000..8300836c857b
--- /dev/null
+++ b/usr.bin/nohup/nohup.c
@@ -0,0 +1,121 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void dofile(void);
+static void usage(void) __dead2;
+
+#define FILENAME "nohup.out"
+/*
+ * POSIX mandates that we exit with:
+ * 126 - If the utility was found, but failed to execute.
+ * 127 - If any other error occurred.
+ */
+#define EXIT_NOEXEC 126
+#define EXIT_NOTFOUND 127
+#define EXIT_MISC 127
+
+int
+main(int argc, char *argv[])
+{
+ int exit_status;
+
+ while (getopt(argc, argv, "") != -1)
+ usage();
+ argc -= optind;
+ argv += optind;
+ if (argc < 1)
+ usage();
+
+ if (isatty(STDOUT_FILENO))
+ dofile();
+ if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
+ /* may have just closed stderr */
+ err(EXIT_MISC, "%s", argv[0]);
+
+ (void)signal(SIGHUP, SIG_IGN);
+
+ execvp(*argv, argv);
+ exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC;
+ err(exit_status, "%s", argv[0]);
+}
+
+static void
+dofile(void)
+{
+ int fd;
+ char path[MAXPATHLEN];
+ const char *p;
+
+ /*
+ * POSIX mandates if the standard output is a terminal, the standard
+ * output is appended to nohup.out in the working directory. Failing
+ * that, it will be appended to nohup.out in the directory obtained
+ * from the HOME environment variable. If file creation is required,
+ * the mode_t is set to S_IRUSR | S_IWUSR.
+ */
+ p = FILENAME;
+ fd = open(p, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+ if (fd != -1)
+ goto dupit;
+ if ((p = getenv("HOME")) != NULL && *p != '\0' &&
+ (size_t)snprintf(path, sizeof(path), "%s/%s", p, FILENAME) <
+ sizeof(path)) {
+ fd = open(p = path, O_RDWR | O_CREAT | O_APPEND,
+ S_IRUSR | S_IWUSR);
+ if (fd != -1)
+ goto dupit;
+ }
+ errx(EXIT_MISC, "can't open a nohup.out file");
+
+dupit:
+ if (dup2(fd, STDOUT_FILENO) == -1)
+ err(EXIT_MISC, NULL);
+ (void)fprintf(stderr, "appending output to %s\n", p);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: nohup [--] utility [arguments]\n");
+ exit(EXIT_MISC);
+}
diff --git a/usr.bin/number/Makefile b/usr.bin/number/Makefile
new file mode 100644
index 000000000000..e2af22dc3697
--- /dev/null
+++ b/usr.bin/number/Makefile
@@ -0,0 +1,4 @@
+PROG= number
+MAN= number.6
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/number/Makefile.depend b/usr.bin/number/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/number/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/number/number.6 b/usr.bin/number/number.6
new file mode 100644
index 000000000000..fb6828c13186
--- /dev/null
+++ b/usr.bin/number/number.6
@@ -0,0 +1,55 @@
+.\" Copyright (c) 1989, 1993, 1994
+.\" 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.
+.\"
+.Dd March 31, 1994
+.Dt NUMBER 6
+.Os
+.Sh NAME
+.Nm number
+.Nd convert Arabic numerals to English
+.Sh SYNOPSIS
+.Nm
+.Op Fl l
+.Op Ar \&# ...
+.Sh DESCRIPTION
+The
+.Nm
+utility prints the English equivalent of the number to the standard
+output, with each 10^3 magnitude displayed on a separate line.
+If no argument is specified,
+.Nm
+reads lines from the standard input.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl l
+Display the number on a single line.
+.El
+.Sh BUGS
+Although
+.Nm
+understand fractions, it does not understand exponents.
diff --git a/usr.bin/number/number.c b/usr.bin/number/number.c
new file mode 100644
index 000000000000..1a1123ec7f94
--- /dev/null
+++ b/usr.bin/number/number.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * 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.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAXNUM 65 /* Biggest number we handle. */
+
+static const char *name1[] = {
+ "", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "ten", "eleven",
+ "twelve", "thirteen", "fourteen", "fifteen",
+ "sixteen", "seventeen", "eighteen", "nineteen",
+},
+ *name2[] = {
+ "", "ten", "twenty", "thirty",
+ "forty", "fifty", "sixty", "seventy",
+ "eighty", "ninety",
+},
+ *name3[] = {
+ "hundred", "thousand", "million", "billion",
+ "trillion", "quadrillion", "quintillion", "sextillion",
+ "septillion", "octillion", "nonillion", "decillion",
+ "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
+ "quindecillion", "sexdecillion",
+ "septendecillion", "octodecillion",
+ "novemdecillion", "vigintillion",
+};
+
+static void convert(char *);
+static int number(char *, int);
+static void pfract(int);
+static int unit(int, char *);
+static void usage(void);
+
+static int lflag;
+
+int
+main(int argc, char *argv[])
+{
+ int ch, first;
+ char line[256];
+
+ lflag = 0;
+ while ((ch = getopt(argc, argv, "l")) != -1)
+ switch (ch) {
+ case 'l':
+ lflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (*argv == NULL)
+ for (first = 1;
+ fgets(line, sizeof(line), stdin) != NULL; first = 0) {
+ if (strchr(line, '\n') == NULL)
+ errx(1, "line too long.");
+ if (!first)
+ (void)printf("...\n");
+ convert(line);
+ }
+ else
+ for (first = 1; *argv != NULL; first = 0, ++argv) {
+ if (!first)
+ (void)printf("...\n");
+ convert(*argv);
+ }
+ exit(0);
+}
+
+static void
+convert(char *line)
+{
+ int flen, len, rval;
+ char *p, *fraction;
+
+ flen = 0;
+ fraction = NULL;
+ for (p = line; *p != '\0' && *p != '\n'; ++p) {
+ if (isblank(*p)) {
+ if (p == line) {
+ ++line;
+ continue;
+ }
+ goto badnum;
+ }
+ if (isdigit(*p))
+ continue;
+ switch (*p) {
+ case '.':
+ if (fraction != NULL)
+ goto badnum;
+ fraction = p + 1;
+ *p = '\0';
+ break;
+ case '-':
+ if (p == line)
+ break;
+ /* FALLTHROUGH */
+ default:
+badnum: errx(1, "illegal number: %s", line);
+ break;
+ }
+ }
+ *p = '\0';
+
+ if ((len = strlen(line)) > MAXNUM ||
+ (fraction != NULL && ((flen = strlen(fraction)) > MAXNUM)))
+ errx(1, "number too large, max %d digits.", MAXNUM);
+
+ if (*line == '-') {
+ (void)printf("minus%s", lflag ? " " : "\n");
+ ++line;
+ --len;
+ }
+
+ rval = len > 0 ? unit(len, line) : 0;
+ if (fraction != NULL && flen != 0)
+ for (p = fraction; *p != '\0'; ++p)
+ if (*p != '0') {
+ if (rval)
+ (void)printf("%sand%s",
+ lflag ? " " : "",
+ lflag ? " " : "\n");
+ if (unit(flen, fraction)) {
+ if (lflag)
+ (void)printf(" ");
+ pfract(flen);
+ rval = 1;
+ }
+ break;
+ }
+ if (!rval)
+ (void)printf("zero%s", lflag ? "" : ".\n");
+ if (lflag)
+ (void)printf("\n");
+}
+
+static int
+unit(int len, char *p)
+{
+ int off, rval;
+
+ rval = 0;
+ if (len > 3) {
+ if (len % 3) {
+ off = len % 3;
+ len -= off;
+ if (number(p, off)) {
+ rval = 1;
+ (void)printf(" %s%s",
+ name3[len / 3], lflag ? " " : ".\n");
+ }
+ p += off;
+ }
+ for (; len > 3; p += 3) {
+ len -= 3;
+ if (number(p, 3)) {
+ rval = 1;
+ (void)printf(" %s%s",
+ name3[len / 3], lflag ? " " : ".\n");
+ }
+ }
+ }
+ if (number(p, len)) {
+ if (!lflag)
+ (void)printf(".\n");
+ rval = 1;
+ }
+ return (rval);
+}
+
+static int
+number(char *p, int len)
+{
+ int val, rval;
+
+ rval = 0;
+ switch (len) {
+ case 3:
+ if (*p != '0') {
+ rval = 1;
+ (void)printf("%s hundred", name1[*p - '0']);
+ }
+ ++p;
+ /* FALLTHROUGH */
+ case 2:
+ val = (p[1] - '0') + (p[0] - '0') * 10;
+ if (val) {
+ if (rval)
+ (void)printf(" ");
+ if (val < 20)
+ (void)printf("%s", name1[val]);
+ else {
+ (void)printf("%s", name2[val / 10]);
+ if (val % 10)
+ (void)printf("-%s", name1[val % 10]);
+ }
+ rval = 1;
+ }
+ break;
+ case 1:
+ if (*p != '0') {
+ rval = 1;
+ (void)printf("%s", name1[*p - '0']);
+ }
+ }
+ return (rval);
+}
+
+static void
+pfract(int len)
+{
+ static char const * const pref[] = { "", "ten-", "hundred-" };
+
+ switch(len) {
+ case 1:
+ (void)printf("tenths.\n");
+ break;
+ case 2:
+ (void)printf("hundredths.\n");
+ break;
+ default:
+ (void)printf("%s%sths.\n", pref[len % 3], name3[len / 3]);
+ break;
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: number [-l] [# ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/objcopy/Makefile b/usr.bin/objcopy/Makefile
new file mode 100644
index 000000000000..101c84cc5206
--- /dev/null
+++ b/usr.bin/objcopy/Makefile
@@ -0,0 +1,42 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+ELFCOPYDIR= ${ELFTCDIR}/elfcopy
+
+.PATH: ${ELFCOPYDIR}
+
+PROG= objcopy
+objcopy.1: elfcopy.1
+ sed -e 's/\.Dt ELFCOPY 1/.Dt OBJCOPY 1/' \
+ -e '/\.Nm elfcopy ,/d' < ${.ALLSRC} > ${.TARGET}
+CLEANFILES+= objcopy.1
+
+SRCS= archive.c ascii.c binary.c main.c pe.c sections.c segments.c symbols.c
+
+WARNS?= 5
+
+LIBADD= archive elftc elf pe
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/libpe -I${ELFTCDIR}/common
+CFLAGS+=-DWITH_PE=1
+
+MAN= ${PROG}.1 strip.1
+
+LINKS= ${BINDIR}/${PROG} ${BINDIR}/strip
+
+# This same hack is in lib/libelf/Makefile and usr.bin/readelf/Makefile
+# We need to link against the correct version of these files. One
+# solution is to include SRCTOP/sys in the include path. This causes
+# problems when a header file in sys depends on a file in another
+# part of the tree, e.g. a machine dependent header.
+#
+SRCS+= sys/elf_common.h
+CLEANDIRS= sys
+CFLAGS+= -I.
+sys/elf_common.h: ${SRCTOP}/sys/${.TARGET} .NOMETA
+ mkdir -p ${.OBJDIR}/sys
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/objcopy/Makefile.depend b/usr.bin/objcopy/Makefile.depend
new file mode 100644
index 000000000000..898aa8b2b146
--- /dev/null
+++ b/usr.bin/objcopy/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libelf \
+ lib/libelftc \
+ lib/libpe \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ofed/Makefile b/usr.bin/ofed/Makefile
new file mode 100644
index 000000000000..59637dbe4760
--- /dev/null
+++ b/usr.bin/ofed/Makefile
@@ -0,0 +1,12 @@
+.include <src.opts.mk>
+
+SUBDIR= \
+ libibverbs \
+ librdmacm \
+ infiniband-diags
+
+SUBDIR.${MK_OFED_EXTRA}+= opensm
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/ofed/infiniband-diags/Makefile b/usr.bin/ofed/infiniband-diags/Makefile
new file mode 100644
index 000000000000..c25b24d5af52
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/Makefile
@@ -0,0 +1,33 @@
+.include <src.opts.mk>
+
+SUBDIR= \
+ ibstat
+
+.if ${MK_OFED_EXTRA} != "no"
+SUBDIR+= \
+ dump_fts \
+ ibaddr \
+ ibcacheedit \
+ ibccconfig \
+ ibccquery \
+ iblinkinfo \
+ ibmirror \
+ ibnetdiscover \
+ ibping \
+ ibportstate \
+ ibqueryerrors \
+ ibroute \
+ ibsysstat \
+ ibtracert \
+ perfquery \
+ saquery \
+ sminfo \
+ smpdump \
+ smpquery \
+ vendstat
+.endif
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
+
diff --git a/usr.bin/ofed/infiniband-diags/Makefile.inc b/usr.bin/ofed/infiniband-diags/Makefile.inc
new file mode 100644
index 000000000000..162fdade24ca
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/Makefile.inc
@@ -0,0 +1,11 @@
+_spath= ${SRCTOP}/contrib/ofed/infiniband-diags
+.PATH: ${_spath}/src ${_spath}/man
+
+BINDIR?= /usr/bin
+SRCS+= ibdiag_common.c ibdiag_sa.c
+CFLAGS+= -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/infiniband
+CFLAGS+= -DHAVE_CONFIG_H=1
+CFLAGS+= -I${_spath} -I${_spath}/src
+LIBADD+= osmcomp ibmad ibumad
+
+WARNS?= 0
diff --git a/usr.bin/ofed/infiniband-diags/dump_fts/Makefile b/usr.bin/ofed/infiniband-diags/dump_fts/Makefile
new file mode 100644
index 000000000000..a08caaa10319
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/dump_fts/Makefile
@@ -0,0 +1,6 @@
+PROG= dump_fts
+SRCS= dump_fts.c
+LIBADD= ibnetdisc
+MAN= dump_fts.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibaddr/Makefile b/usr.bin/ofed/infiniband-diags/ibaddr/Makefile
new file mode 100644
index 000000000000..5e797f4c0d68
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibaddr/Makefile
@@ -0,0 +1,5 @@
+PROG= ibaddr
+SRCS= ibaddr.c
+MAN= ibaddr.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibcacheedit/Makefile b/usr.bin/ofed/infiniband-diags/ibcacheedit/Makefile
new file mode 100644
index 000000000000..87fc509f71aa
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibcacheedit/Makefile
@@ -0,0 +1,6 @@
+PROG= ibcacheedit
+SRCS= ibcacheedit.c
+LIBADD= ibnetdisc
+MAN= ibcacheedit.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibccconfig/Makefile b/usr.bin/ofed/infiniband-diags/ibccconfig/Makefile
new file mode 100644
index 000000000000..0b53a27583fb
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibccconfig/Makefile
@@ -0,0 +1,5 @@
+PROG= ibccconfig
+SRCS= ibccconfig.c
+MAN= ibccconfig.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibccquery/Makefile b/usr.bin/ofed/infiniband-diags/ibccquery/Makefile
new file mode 100644
index 000000000000..90ab8bc77777
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibccquery/Makefile
@@ -0,0 +1,5 @@
+PROG= ibccquery
+SRCS= ibccquery.c
+MAN= ibccquery.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/iblinkinfo/Makefile b/usr.bin/ofed/infiniband-diags/iblinkinfo/Makefile
new file mode 100644
index 000000000000..1075e6ae37ce
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/iblinkinfo/Makefile
@@ -0,0 +1,6 @@
+PROG= iblinkinfo
+SRCS= iblinkinfo.c
+LIBADD= ibnetdisc
+MAN= iblinkinfo.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibmirror/Makefile b/usr.bin/ofed/infiniband-diags/ibmirror/Makefile
new file mode 100644
index 000000000000..bf960827c56f
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibmirror/Makefile
@@ -0,0 +1,5 @@
+PROG= ibmirror
+SRCS= ibmirror.c
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibnetdiscover/Makefile b/usr.bin/ofed/infiniband-diags/ibnetdiscover/Makefile
new file mode 100644
index 000000000000..cbb515883c27
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibnetdiscover/Makefile
@@ -0,0 +1,6 @@
+PROG= ibnetdiscover
+SRCS= ibnetdiscover.c
+LIBADD= ibnetdisc
+MAN= ibnetdiscover.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibping/Makefile b/usr.bin/ofed/infiniband-diags/ibping/Makefile
new file mode 100644
index 000000000000..15a645ad0752
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibping/Makefile
@@ -0,0 +1,5 @@
+PROG= ibping
+SRCS= ibping.c
+MAN= ibping.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibportstate/Makefile b/usr.bin/ofed/infiniband-diags/ibportstate/Makefile
new file mode 100644
index 000000000000..65a67dfd4880
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibportstate/Makefile
@@ -0,0 +1,5 @@
+PROG= ibportstate
+SRCS= ibportstate.c
+MAN= ibportstate.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibqueryerrors/Makefile b/usr.bin/ofed/infiniband-diags/ibqueryerrors/Makefile
new file mode 100644
index 000000000000..a0526b46e8f5
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibqueryerrors/Makefile
@@ -0,0 +1,6 @@
+PROG= ibqueryerrors
+SRCS= ibqueryerrors.c
+LIBADD= ibnetdisc
+MAN= ibqueryerrors.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibroute/Makefile b/usr.bin/ofed/infiniband-diags/ibroute/Makefile
new file mode 100644
index 000000000000..03cea57b8e5e
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibroute/Makefile
@@ -0,0 +1,5 @@
+PROG= ibroute
+SRCS= ibroute.c
+MAN= ibroute.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibstat/Makefile b/usr.bin/ofed/infiniband-diags/ibstat/Makefile
new file mode 100644
index 000000000000..2298970e42b9
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibstat/Makefile
@@ -0,0 +1,5 @@
+PROG= ibstat
+SRCS= ibstat.c
+MAN= ibstat.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibsysstat/Makefile b/usr.bin/ofed/infiniband-diags/ibsysstat/Makefile
new file mode 100644
index 000000000000..a8a72420e9c1
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibsysstat/Makefile
@@ -0,0 +1,5 @@
+PROG= ibsysstat
+SRCS= ibsysstat.c
+MAN= ibsysstat.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/ibtracert/Makefile b/usr.bin/ofed/infiniband-diags/ibtracert/Makefile
new file mode 100644
index 000000000000..8bcd5192ade3
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/ibtracert/Makefile
@@ -0,0 +1,5 @@
+PROG= ibtracert
+SRCS= ibtracert.c
+MAN= ibtracert.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/perfquery/Makefile b/usr.bin/ofed/infiniband-diags/perfquery/Makefile
new file mode 100644
index 000000000000..291cf168218d
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/perfquery/Makefile
@@ -0,0 +1,5 @@
+PROG= perfquery
+SRCS= perfquery.c
+MAN= perfquery.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/saquery/Makefile b/usr.bin/ofed/infiniband-diags/saquery/Makefile
new file mode 100644
index 000000000000..739964215bdc
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/saquery/Makefile
@@ -0,0 +1,5 @@
+PROG= saquery
+SRCS= saquery.c
+MAN= saquery.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/sminfo/Makefile b/usr.bin/ofed/infiniband-diags/sminfo/Makefile
new file mode 100644
index 000000000000..be63fb69fe5c
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/sminfo/Makefile
@@ -0,0 +1,5 @@
+PROG= sminfo
+SRCS= sminfo.c
+MAN= sminfo.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/smpdump/Makefile b/usr.bin/ofed/infiniband-diags/smpdump/Makefile
new file mode 100644
index 000000000000..70fe61c05448
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/smpdump/Makefile
@@ -0,0 +1,5 @@
+PROG= smpdump
+SRCS= smpdump.c
+MAN= smpdump.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/smpquery/Makefile b/usr.bin/ofed/infiniband-diags/smpquery/Makefile
new file mode 100644
index 000000000000..4c716f58387a
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/smpquery/Makefile
@@ -0,0 +1,5 @@
+PROG= smpquery
+SRCS= smpquery.c
+MAN= smpquery.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/infiniband-diags/vendstat/Makefile b/usr.bin/ofed/infiniband-diags/vendstat/Makefile
new file mode 100644
index 000000000000..9fea6878a25f
--- /dev/null
+++ b/usr.bin/ofed/infiniband-diags/vendstat/Makefile
@@ -0,0 +1,5 @@
+PROG= vendstat
+SRCS= vendstat.c
+MAN= vendstat.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/Makefile b/usr.bin/ofed/libibverbs/Makefile
new file mode 100644
index 000000000000..f9aff0070f36
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= FreeBSD-rdma
+
+SUBDIR= \
+asyncwatch \
+devinfo \
+devices \
+rc_pingpong \
+srq_pingpong \
+uc_pingpong \
+ud_pingpong
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/ofed/libibverbs/Makefile.inc b/usr.bin/ofed/libibverbs/Makefile.inc
new file mode 100644
index 000000000000..616c9bd54707
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/Makefile.inc
@@ -0,0 +1,8 @@
+_spath=${SRCTOP}/contrib/ofed/libibverbs
+.PATH: ${_spath}/examples ${_spath}/man
+
+BINDIR?= /usr/bin
+CFLAGS+= -I${_spath}
+LIBADD+= ibverbs mlx4 mlx5 cxgb4 irdma pthread
+
+WARNS?= 2
diff --git a/usr.bin/ofed/libibverbs/asyncwatch/Makefile b/usr.bin/ofed/libibverbs/asyncwatch/Makefile
new file mode 100644
index 000000000000..d7a910bf0944
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/asyncwatch/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_asyncwatch
+MAN= ibv_asyncwatch.1
+SRCS= asyncwatch.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/devices/Makefile b/usr.bin/ofed/libibverbs/devices/Makefile
new file mode 100644
index 000000000000..977d903d80fe
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/devices/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_devices
+MAN= ibv_devices.1
+SRCS= device_list.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/devinfo/Makefile b/usr.bin/ofed/libibverbs/devinfo/Makefile
new file mode 100644
index 000000000000..ef62919d2279
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/devinfo/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_devinfo
+MAN= ibv_devinfo.1
+SRCS= devinfo.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/rc_pingpong/Makefile b/usr.bin/ofed/libibverbs/rc_pingpong/Makefile
new file mode 100644
index 000000000000..2ab8a1419b39
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/rc_pingpong/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_rc_pingpong
+MAN= ibv_rc_pingpong.1
+SRCS= rc_pingpong.c pingpong.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/srq_pingpong/Makefile b/usr.bin/ofed/libibverbs/srq_pingpong/Makefile
new file mode 100644
index 000000000000..f15b021bc6e4
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/srq_pingpong/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_srq_pingpong
+MAN= ibv_srq_pingpong.1
+SRCS= srq_pingpong.c pingpong.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/uc_pingpong/Makefile b/usr.bin/ofed/libibverbs/uc_pingpong/Makefile
new file mode 100644
index 000000000000..69a0e5f72808
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/uc_pingpong/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_uc_pingpong
+MAN= ibv_uc_pingpong.1
+SRCS= uc_pingpong.c pingpong.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/libibverbs/ud_pingpong/Makefile b/usr.bin/ofed/libibverbs/ud_pingpong/Makefile
new file mode 100644
index 000000000000..932658508735
--- /dev/null
+++ b/usr.bin/ofed/libibverbs/ud_pingpong/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ibv_ud_pingpong
+MAN= ibv_ud_pingpong.1
+SRCS= ud_pingpong.c pingpong.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/librdmacm/Makefile b/usr.bin/ofed/librdmacm/Makefile
new file mode 100644
index 000000000000..da14df38fbf2
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/Makefile
@@ -0,0 +1,5 @@
+SUBDIR= ucmatose mckey rping udaddy
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/ofed/librdmacm/Makefile.inc b/usr.bin/ofed/librdmacm/Makefile.inc
new file mode 100644
index 000000000000..74f32fe08b42
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/Makefile.inc
@@ -0,0 +1,8 @@
+_spath=${SRCTOP}/contrib/ofed/librdmacm
+.PATH: ${_spath}/examples ${_spath}/man
+
+BINDIR?= /usr/bin
+CFLAGS+= -I${SRCTOP}/contrib/ofed
+LIBADD+= ibverbs rdmacm irdma mlx4 mlx5 cxgb4 pthread
+
+WARNS?= 0
diff --git a/usr.bin/ofed/librdmacm/mckey/Makefile b/usr.bin/ofed/librdmacm/mckey/Makefile
new file mode 100644
index 000000000000..bdae45765b3f
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/mckey/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= mckey
+MAN= mckey.1
+SRCS= mckey.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/librdmacm/mckey/Makefile.depend b/usr.bin/ofed/librdmacm/mckey/Makefile.depend
new file mode 100644
index 000000000000..fe221dcdedab
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/mckey/Makefile.depend
@@ -0,0 +1,24 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+ lib/ofed/include \
+ lib/ofed/libcxgb4 \
+ lib/ofed/libibverbs \
+ lib/ofed/libirdma \
+ lib/ofed/libmlx4 \
+ lib/ofed/libmlx5 \
+ lib/ofed/librdmacm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ofed/librdmacm/rping/Makefile b/usr.bin/ofed/librdmacm/rping/Makefile
new file mode 100644
index 000000000000..3406c6c576f5
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/rping/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= rping
+MAN= rping.1
+SRCS= rping.c common.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/librdmacm/rping/Makefile.depend b/usr.bin/ofed/librdmacm/rping/Makefile.depend
new file mode 100644
index 000000000000..f89053d7c943
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/rping/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+ lib/ofed/include \
+ lib/ofed/libcxgb4 \
+ lib/ofed/libibverbs \
+ lib/ofed/libirdma \
+ lib/ofed/libmlx4 \
+ lib/ofed/libmlx5 \
+ lib/ofed/librdmacm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ofed/librdmacm/ucmatose/Makefile b/usr.bin/ofed/librdmacm/ucmatose/Makefile
new file mode 100644
index 000000000000..0b4791c5404a
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/ucmatose/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= ucmatose
+MAN= ucmatose.1
+SRCS= cmatose.c common.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/librdmacm/ucmatose/Makefile.depend b/usr.bin/ofed/librdmacm/ucmatose/Makefile.depend
new file mode 100644
index 000000000000..f89053d7c943
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/ucmatose/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+ lib/ofed/include \
+ lib/ofed/libcxgb4 \
+ lib/ofed/libibverbs \
+ lib/ofed/libirdma \
+ lib/ofed/libmlx4 \
+ lib/ofed/libmlx5 \
+ lib/ofed/librdmacm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ofed/librdmacm/udaddy/Makefile b/usr.bin/ofed/librdmacm/udaddy/Makefile
new file mode 100644
index 000000000000..dc4105881d4a
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/udaddy/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= rdma
+PROG= udaddy
+MAN= udaddy.1
+SRCS= udaddy.c common.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ofed/librdmacm/udaddy/Makefile.depend b/usr.bin/ofed/librdmacm/udaddy/Makefile.depend
new file mode 100644
index 000000000000..f89053d7c943
--- /dev/null
+++ b/usr.bin/ofed/librdmacm/udaddy/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libthr \
+ lib/ofed/include \
+ lib/ofed/libcxgb4 \
+ lib/ofed/libibverbs \
+ lib/ofed/libirdma \
+ lib/ofed/libmlx4 \
+ lib/ofed/libmlx5 \
+ lib/ofed/librdmacm \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ofed/opensm/Makefile b/usr.bin/ofed/opensm/Makefile
new file mode 100644
index 000000000000..442a47bb160d
--- /dev/null
+++ b/usr.bin/ofed/opensm/Makefile
@@ -0,0 +1,102 @@
+_spath= ${SRCTOP}/contrib/ofed/opensm/opensm
+.PATH: ${_spath} ${_spath:H}/man
+
+BINDIR?= /usr/bin
+PROG= opensm
+
+SRCS= \
+main.c \
+osm_congestion_control.c \
+osm_console.c \
+osm_console_io.c \
+osm_db_files.c \
+osm_db_pack.c \
+osm_drop_mgr.c \
+osm_dump.c \
+osm_event_plugin.c \
+osm_guid_info_rcv.c \
+osm_guid_mgr.c \
+osm_inform.c \
+osm_lid_mgr.c \
+osm_lin_fwd_rcv.c \
+osm_link_mgr.c \
+osm_mcast_fwd_rcv.c \
+osm_mcast_mgr.c \
+osm_mcast_tbl.c \
+osm_mcm_port.c \
+osm_mesh.c \
+osm_mlnx_ext_port_info_rcv.c \
+osm_mtree.c \
+osm_multicast.c \
+osm_node.c \
+osm_node_desc_rcv.c \
+osm_node_info_rcv.c \
+osm_opensm.c \
+osm_perfmgr.c \
+osm_perfmgr_db.c \
+osm_pkey.c \
+osm_pkey_mgr.c \
+osm_pkey_rcv.c \
+osm_port.c \
+osm_port_info_rcv.c \
+osm_prtn.c \
+osm_prtn_config.c \
+osm_qos.c \
+osm_qos_parser_l.l \
+osm_qos_parser_y.y \
+osm_qos_policy.c \
+osm_remote_sm.c \
+osm_req.c \
+osm_resp.c \
+osm_router.c \
+osm_sa.c \
+osm_sa_class_port_info.c \
+osm_sa_guidinfo_record.c \
+osm_sa_informinfo.c \
+osm_sa_lft_record.c \
+osm_sa_link_record.c \
+osm_sa_mad_ctrl.c \
+osm_sa_mcmember_record.c \
+osm_sa_mft_record.c \
+osm_sa_multipath_record.c \
+osm_sa_node_record.c \
+osm_sa_path_record.c \
+osm_sa_pkey_record.c \
+osm_sa_portinfo_record.c \
+osm_sa_service_record.c \
+osm_sa_slvl_record.c \
+osm_sa_sminfo_record.c \
+osm_sa_sw_info_record.c \
+osm_sa_vlarb_record.c \
+osm_service.c \
+osm_slvl_map_rcv.c \
+osm_sm.c \
+osm_sm_mad_ctrl.c \
+osm_sm_state_mgr.c \
+osm_sminfo_rcv.c \
+osm_state_mgr.c \
+osm_subnet.c \
+osm_sw_info_rcv.c \
+osm_switch.c \
+osm_torus.c \
+osm_trap_rcv.c \
+osm_ucast_cache.c \
+osm_ucast_dfsssp.c \
+osm_ucast_dnup.c \
+osm_ucast_file.c \
+osm_ucast_ftree.c \
+osm_ucast_lash.c \
+osm_ucast_mgr.c \
+osm_ucast_updn.c \
+osm_vl15intf.c \
+osm_vl_arb_rcv.c \
+st.c
+
+MAN= opensm.8
+CFLAGS+= -I${_spath:H} -DHAVE_CONFIG_H=1
+CFLAGS+= -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/infiniband
+LIBADD= opensm osmvendor osmcomp wrap pthread
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pagesize/Makefile b/usr.bin/pagesize/Makefile
new file mode 100644
index 000000000000..56dc6fdb697c
--- /dev/null
+++ b/usr.bin/pagesize/Makefile
@@ -0,0 +1,4 @@
+SCRIPTS=pagesize.sh
+MAN= pagesize.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pagesize/Makefile.depend b/usr.bin/pagesize/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/pagesize/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/pagesize/pagesize.1 b/usr.bin/pagesize/pagesize.1
new file mode 100644
index 000000000000..9ae2c45f58bd
--- /dev/null
+++ b/usr.bin/pagesize/pagesize.1
@@ -0,0 +1,51 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd June 6, 1993
+.Dt PAGESIZE 1
+.Os
+.Sh NAME
+.Nm pagesize
+.Nd print system page size
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility prints the size of a page of memory in bytes, as
+returned by
+.Xr getpagesize 3 .
+This program is useful in constructing portable
+shell scripts.
+.Sh SEE ALSO
+.Xr getpagesize 3
+.Sh HISTORY
+The
+.Nm
+command
+appeared in
+.Bx 4.2 .
diff --git a/usr.bin/pagesize/pagesize.sh b/usr.bin/pagesize/pagesize.sh
new file mode 100644
index 000000000000..14aef04ce39f
--- /dev/null
+++ b/usr.bin/pagesize/pagesize.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 1994
+# 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.
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
+
+exec sysctl -n hw.pagesize
diff --git a/usr.bin/pamtest/Makefile b/usr.bin/pamtest/Makefile
new file mode 100644
index 000000000000..99ee62e03b22
--- /dev/null
+++ b/usr.bin/pamtest/Makefile
@@ -0,0 +1,9 @@
+OPENPAM= ${SRCTOP}/contrib/openpam
+.PATH: ${OPENPAM}/include ${OPENPAM}/bin/pamtest
+
+PROG= pamtest
+SRCS= pamtest.c
+
+LIBADD= pam
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pamtest/Makefile.depend b/usr.bin/pamtest/Makefile.depend
new file mode 100644
index 000000000000..b7d4cb3f9a1f
--- /dev/null
+++ b/usr.bin/pamtest/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libpam/libpam \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/passwd/Makefile b/usr.bin/passwd/Makefile
new file mode 100644
index 000000000000..f8734053deb0
--- /dev/null
+++ b/usr.bin/passwd/Makefile
@@ -0,0 +1,20 @@
+.include <src.opts.mk>
+
+PACKAGE = runtime
+PROG = passwd
+BINOWN = root
+BINMODE = 4555
+PRECIOUSPROG=
+LIBADD = pam
+.if ${MK_NIS} != "no"
+SYMLINKS = passwd ${BINDIR}/yppasswd
+MLINKS = passwd.1 yppasswd.1
+.endif
+
+beforeinstall:
+.for i in passwd yppasswd
+ [ ! -e ${DESTDIR}${BINDIR}/$i ] || \
+ chflags noschg ${DESTDIR}${BINDIR}/$i || true
+.endfor
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/passwd/Makefile.depend b/usr.bin/passwd/Makefile.depend
new file mode 100644
index 000000000000..a8b8ddf9d074
--- /dev/null
+++ b/usr.bin/passwd/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libpam/libpam \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/passwd/passwd.1 b/usr.bin/passwd/passwd.1
new file mode 100644
index 000000000000..23782cb622e4
--- /dev/null
+++ b/usr.bin/passwd/passwd.1
@@ -0,0 +1,231 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd February 14, 2014
+.Dt PASSWD 1
+.Os
+.Sh NAME
+.Nm passwd , yppasswd
+.Nd modify a user's password
+.Sh SYNOPSIS
+.Nm
+.Op Fl l
+.Op Ar user
+.Nm yppasswd
+.Op Fl l
+.Op Fl y
+.Op Fl d Ar domain
+.Op Fl h Ar host
+.Op Fl o
+.Sh DESCRIPTION
+The
+.Nm
+utility changes the user's local, Kerberos, or NIS password.
+If the user is not the super-user,
+.Nm
+first prompts for the current password and will not continue unless the correct
+password is entered.
+.Pp
+When entering the new password, the characters entered do not echo, in order to
+avoid the password being seen by a passer-by.
+The
+.Nm
+utility prompts for the new password twice in order to detect typing errors.
+.Pp
+The total length of the password must be less than
+.Dv _PASSWORD_LEN
+(currently 128 characters).
+.Pp
+Once the password has been verified,
+.Nm
+communicates the new password information to
+the Kerberos authenticating host.
+.Pp
+The following option is available:
+.Bl -tag -width indent
+.It Fl l
+Cause the password to be updated only in the local
+password file, and not with the Kerberos database.
+When changing only the local password,
+.Xr pwd_mkdb 8
+is used to update the password databases.
+.El
+.Pp
+When changing local or NIS password, the next password change date
+is set according to
+.Dq passwordtime
+capability in the user's login class.
+.Pp
+To change another user's Kerberos password, one must first
+run
+.Xr kinit 1
+followed by
+.Nm .
+The super-user is not required to provide a user's current password
+if only the local password is modified.
+.Sh NIS INTERACTION
+The
+.Nm
+utility has built-in support for NIS.
+If a user exists in the NIS password
+database but does not exist locally,
+.Nm
+automatically switches into
+.Nm yppasswd
+mode.
+If the specified
+user does not exist in either the local password database or the
+NIS password maps,
+.Nm
+returns an error.
+.Pp
+When changing an NIS password, unprivileged users are required to provide
+their old password for authentication (the
+.Xr rpc.yppasswdd 8
+daemon requires the original password before
+it will allow any changes to the NIS password maps).
+This restriction applies even to the
+super-user, with one important exception: the password authentication is
+bypassed for the super-user on the NIS master server.
+This means that
+the super-user on the NIS master server can make unrestricted changes to
+anyone's NIS password.
+The super-user on NIS client systems and NIS slave
+servers still needs to provide a password before the update will be processed.
+.Pp
+The following additional options are supported for use with NIS:
+.Bl -tag -width indent
+.It Fl y
+Override
+.Nm Ns 's
+checking heuristics and forces
+it into NIS mode.
+.It Fl l
+When NIS is enabled, the
+.Fl l
+flag can be used to force
+.Nm
+into
+.Dq local only
+mode.
+This flag can be used to change the entry
+for a local user when an NIS user exists with the same login name.
+For example, you will sometimes find entries for system
+.Dq placeholder
+users such as
+.Pa bin
+or
+.Pa daemon
+in both the NIS password maps and the local user database.
+By
+default,
+.Nm
+will try to change the NIS password.
+The
+.Fl l
+flag can be used to change the local password instead.
+.It Fl d Ar domain
+Specify what domain to use when changing an NIS password.
+By default,
+.Nm
+assumes that the system default domain should be used.
+This flag is
+primarily for use by the superuser on the NIS master server: a single
+NIS server can support multiple domains.
+It is also possible that the
+domainname on the NIS master may not be set (it is not necessary for
+an NIS server to also be a client) in which case the
+.Nm
+command needs to be told what domain to operate on.
+.It Fl h Ar host
+Specify the name of an NIS server.
+This option, in conjunction
+with the
+.Fl d
+option, can be used to change an NIS password on a non-local NIS
+server.
+When a domain is specified with the
+.Fl d
+option and
+.Nm
+is unable to determine the name of the NIS master server (possibly because
+the local domainname is not set), the name of the NIS master is assumed to
+be
+.Dq localhost .
+This can be overridden with the
+.Fl h
+flag.
+The specified hostname need not be the name of an NIS master: the
+name of the NIS master for a given map can be determined by querying any
+NIS server (master or slave) in a domain, so specifying the name of a
+slave server will work equally well.
+.It Fl o
+Do not automatically override the password authentication checks for the
+super-user on the NIS master server; assume
+.Dq old
+mode instead.
+This
+flag is of limited practical use but is useful for testing.
+.El
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/master.passwd
+the user database
+.It Pa /etc/passwd
+a Version 7 format password file
+.It Pa /etc/passwd.XXXXXX
+temporary copy of the password file
+.It Pa /etc/login.conf
+login class capabilities database
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr kinit 1 ,
+.Xr login 1 ,
+.Xr login.conf 5 ,
+.Xr passwd 5 ,
+.Xr kerberos 8 ,
+.Xr kpasswdd 8 ,
+.Xr pam_passwdqc 8 ,
+.Xr pw 8 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8
+.Rs
+.%A Robert Morris
+.%A Ken Thompson
+.%T "UNIX password security"
+.Re
+.Sh NOTES
+The
+.Nm yppasswd
+command is really only a link to
+.Nm .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v6 .
diff --git a/usr.bin/passwd/passwd.c b/usr.bin/passwd/passwd.c
new file mode 100644
index 000000000000..f1a25c1f21cb
--- /dev/null
+++ b/usr.bin/passwd/passwd.c
@@ -0,0 +1,163 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2002 Networks Associates Technologies, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by ThinkSec AS and
+ * NAI Labs, the Security Research Division of Network Associates, Inc.
+ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+ * DARPA CHATS research program.
+ *
+ * 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 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 AUTHOR 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>
+
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+static pam_handle_t *pamh;
+static struct pam_conv pamc = {
+ openpam_ttyconv,
+ NULL
+};
+
+static char *yp_domain;
+static char *yp_host;
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: passwd [-ly] [-d domain] [-h host] [user]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char hostname[MAXHOSTNAMELEN];
+ struct passwd *pwd = NULL; /* Keep compiler happy. */
+ int o, pam_err;
+ uid_t uid;
+
+ while ((o = getopt(argc, argv, "d:h:loy")) != -1)
+ switch (o) {
+ case 'd':
+ yp_domain = optarg;
+ break;
+ case 'h':
+ yp_host = optarg;
+ break;
+ case 'l':
+ case 'o':
+ case 'y':
+ /* compatibility */
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ uid = getuid();
+
+ switch (argc) {
+ case 0:
+ if ((pwd = getpwuid(uid)) == NULL)
+ errx(1, "who are you?");
+ break;
+ case 1:
+ if ((pwd = getpwnam(*argv)) == NULL)
+ errx(1, "%s: no such user", *argv);
+ break;
+ default:
+ usage();
+ }
+
+ if (uid != 0 && uid != pwd->pw_uid)
+ errx(1, "permission denied");
+
+ /* check where the user's from */
+ switch (pwd->pw_fields & _PWF_SOURCE) {
+ case _PWF_FILES:
+ fprintf(stderr, "Changing local password for %s\n",
+ pwd->pw_name);
+ break;
+ case _PWF_NIS:
+ fprintf(stderr, "Changing NIS password for %s\n",
+ pwd->pw_name);
+ break;
+ default:
+ /* XXX: Green men ought to be supported via PAM. */
+ errx(1,
+ "Sorry, `passwd' can only change passwords for local or NIS users.");
+ }
+
+#define pam_check(func) do { \
+ if (pam_err != PAM_SUCCESS) { \
+ if (pam_err == PAM_AUTH_ERR || pam_err == PAM_PERM_DENIED || \
+ pam_err == PAM_AUTHTOK_RECOVERY_ERR) \
+ warnx("sorry"); \
+ else \
+ warnx("%s(): %s", func, pam_strerror(pamh, pam_err)); \
+ goto end; \
+ } \
+} while (0)
+
+ /* initialize PAM */
+ pam_err = pam_start("passwd", pwd->pw_name, &pamc, &pamh);
+ pam_check("pam_start");
+
+ pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO));
+ pam_check("pam_set_item");
+ gethostname(hostname, sizeof hostname);
+ pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
+ pam_check("pam_set_item");
+ pam_err = pam_set_item(pamh, PAM_RUSER, getlogin());
+ pam_check("pam_set_item");
+
+ /* set YP domain and host */
+ pam_err = pam_set_data(pamh, "yp_domain", yp_domain, NULL);
+ pam_check("pam_set_data");
+ pam_err = pam_set_data(pamh, "yp_server", yp_host, NULL);
+ pam_check("pam_set_data");
+
+ /* set new password */
+ pam_err = pam_chauthtok(pamh, 0);
+ pam_check("pam_chauthtok");
+
+ end:
+ pam_end(pamh, pam_err);
+ exit(pam_err == PAM_SUCCESS ? 0 : 1);
+}
diff --git a/usr.bin/paste/Makefile b/usr.bin/paste/Makefile
new file mode 100644
index 000000000000..e4f9e6d817b5
--- /dev/null
+++ b/usr.bin/paste/Makefile
@@ -0,0 +1,3 @@
+PROG= paste
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/paste/Makefile.depend b/usr.bin/paste/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/paste/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/paste/paste.1 b/usr.bin/paste/paste.1
new file mode 100644
index 000000000000..1339e8b14f52
--- /dev/null
+++ b/usr.bin/paste/paste.1
@@ -0,0 +1,155 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Adam S. Moskowitz and 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.
+.\"
+.Dd November 6, 2022
+.Dt PASTE 1
+.Os
+.Sh NAME
+.Nm paste
+.Nd merge corresponding or subsequent lines of files
+.Sh SYNOPSIS
+.Nm
+.Op Fl s
+.Op Fl d Ar list
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility concatenates the corresponding lines of the given input files,
+replacing all but the last file's newline characters with a single tab
+character, and writes the resulting lines to standard output.
+If end-of-file is reached on an input file while other input files
+still contain data, the file is treated as if it were an endless source
+of empty lines.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d Ar list
+Use one or more of the provided characters to replace the newline
+characters instead of the default tab.
+The characters in
+.Ar list
+are used circularly, i.e., when
+.Ar list
+is exhausted the first character from
+.Ar list
+is reused.
+This continues until a line from the last input file (in default operation)
+or the last line in each file (using the
+.Fl s
+option) is displayed, at which
+time
+.Nm
+begins selecting characters from the beginning of
+.Ar list
+again.
+.Pp
+The following special characters can also be used in list:
+.Pp
+.Bl -tag -width flag -compact
+.It Li \en
+newline character
+.It Li \et
+tab character
+.It Li \e\e
+backslash character
+.It Li \e0
+Empty string (not a null character).
+.El
+.Pp
+Any other character preceded by a backslash is equivalent to the
+character itself.
+.It Fl s
+Concatenate all of the lines of each separate input file in command line
+order.
+The newline character of every line except the last line in each input
+file is replaced with the tab character, unless otherwise specified by
+the
+.Fl d
+option.
+.El
+.Pp
+If
+.Sq Fl
+is specified for one or more of the input files, the standard
+input is used; standard input is read one line at a time, circularly,
+for each instance of
+.Sq Fl .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+List the files in the current directory in three columns:
+.Pp
+.Dl "ls | paste - - -"
+.Pp
+Combine pairs of lines from a file into single lines:
+.Pp
+.Dl "paste -s -d '\et\en' myfile"
+.Pp
+Number the lines in a file, similar to
+.Xr nl 1 :
+.Pp
+.Dl "sed = myfile | paste - -"
+.Pp
+Create a colon-separated list of directories named
+.Pa bin ,
+suitable
+for use in the
+.Ev PATH
+environment variable:
+.Pp
+.Dl "find / -name bin -type d | paste -s -d : -"
+.Sh SEE ALSO
+.Xr cut 1 ,
+.Xr lam 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.At III
+and has been available since
+.Bx 4.3 Reno .
+.Sh AUTHORS
+.An -nosplit
+The original Bell Labs version was written by
+.An Gottfried W. R. Luderer
+and the
+.Bx
+version by
+.An Adam S. Moskowitz
+and
+.An Marciano Pitargue .
diff --git a/usr.bin/paste/paste.c b/usr.bin/paste/paste.c
new file mode 100644
index 000000000000..8114a85a869a
--- /dev/null
+++ b/usr.bin/paste/paste.c
@@ -0,0 +1,259 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam S. Moskowitz of Menlo Consulting.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+static wchar_t *delim;
+static int delimcnt;
+
+static int parallel(char **);
+static int sequential(char **);
+static int tr(wchar_t *);
+static void usage(void) __dead2;
+
+static wchar_t tab[] = L"\t";
+
+int
+main(int argc, char *argv[])
+{
+ int ch, rval, seq;
+ wchar_t *warg;
+ const char *arg;
+ size_t len;
+
+ setlocale(LC_CTYPE, "");
+
+ seq = 0;
+ while ((ch = getopt(argc, argv, "d:s")) != -1)
+ switch(ch) {
+ case 'd':
+ arg = optarg;
+ len = mbsrtowcs(NULL, &arg, 0, NULL);
+ if (len == (size_t)-1)
+ err(1, "delimiters");
+ warg = malloc((len + 1) * sizeof(*warg));
+ if (warg == NULL)
+ err(1, NULL);
+ arg = optarg;
+ len = mbsrtowcs(warg, &arg, len + 1, NULL);
+ if (len == (size_t)-1)
+ err(1, "delimiters");
+ delimcnt = tr(delim = warg);
+ break;
+ case 's':
+ seq = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (*argv == NULL)
+ usage();
+ if (!delim) {
+ delimcnt = 1;
+ delim = tab;
+ }
+
+ if (seq)
+ rval = sequential(argv);
+ else
+ rval = parallel(argv);
+ exit(rval);
+}
+
+typedef struct _list {
+ struct _list *next;
+ FILE *fp;
+ int cnt;
+ char *name;
+} LIST;
+
+static int
+parallel(char **argv)
+{
+ LIST *lp;
+ int cnt;
+ wint_t ich;
+ wchar_t ch;
+ char *p;
+ LIST *head, *tmp;
+ int opencnt, output;
+
+ for (cnt = 0, head = tmp = NULL; (p = *argv); ++argv, ++cnt) {
+ if ((lp = malloc(sizeof(LIST))) == NULL)
+ err(1, NULL);
+ if (p[0] == '-' && !p[1])
+ lp->fp = stdin;
+ else if (!(lp->fp = fopen(p, "r")))
+ err(1, "%s", p);
+ lp->next = NULL;
+ lp->cnt = cnt;
+ lp->name = p;
+ if (!head)
+ head = tmp = lp;
+ else {
+ tmp->next = lp;
+ tmp = lp;
+ }
+ }
+
+ for (opencnt = cnt; opencnt;) {
+ for (output = 0, lp = head; lp; lp = lp->next) {
+ if (!lp->fp) {
+ if (output && lp->cnt &&
+ (ch = delim[(lp->cnt - 1) % delimcnt]))
+ putwchar(ch);
+ continue;
+ }
+ if ((ich = getwc(lp->fp)) == WEOF) {
+ if (!--opencnt)
+ break;
+ lp->fp = NULL;
+ if (output && lp->cnt &&
+ (ch = delim[(lp->cnt - 1) % delimcnt]))
+ putwchar(ch);
+ continue;
+ }
+ /*
+ * make sure that we don't print any delimiters
+ * unless there's a non-empty file.
+ */
+ if (!output) {
+ output = 1;
+ for (cnt = 0; cnt < lp->cnt; ++cnt)
+ if ((ch = delim[cnt % delimcnt]))
+ putwchar(ch);
+ } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
+ putwchar(ch);
+ if (ich == '\n')
+ continue;
+ do {
+ putwchar(ich);
+ } while ((ich = getwc(lp->fp)) != WEOF && ich != '\n');
+ }
+ if (output)
+ putwchar('\n');
+ }
+
+ return (0);
+}
+
+static int
+sequential(char **argv)
+{
+ FILE *fp;
+ int cnt, failed, needdelim;
+ wint_t ch;
+ char *p;
+
+ failed = 0;
+ for (; (p = *argv); ++argv) {
+ if (p[0] == '-' && !p[1])
+ fp = stdin;
+ else if (!(fp = fopen(p, "r"))) {
+ warn("%s", p);
+ failed = 1;
+ continue;
+ }
+ cnt = needdelim = 0;
+ while ((ch = getwc(fp)) != WEOF) {
+ if (needdelim) {
+ needdelim = 0;
+ if (delim[cnt] != '\0')
+ putwchar(delim[cnt]);
+ if (++cnt == delimcnt)
+ cnt = 0;
+ }
+ if (ch != '\n')
+ putwchar(ch);
+ else
+ needdelim = 1;
+ }
+ if (needdelim)
+ putwchar('\n');
+ if (fp != stdin)
+ (void)fclose(fp);
+ }
+
+ return (failed != 0);
+}
+
+static int
+tr(wchar_t *arg)
+{
+ int cnt;
+ wchar_t ch, *p;
+
+ for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
+ if (ch == '\\')
+ switch(ch = *p++) {
+ case 'n':
+ *arg = '\n';
+ break;
+ case 't':
+ *arg = '\t';
+ break;
+ case '0':
+ *arg = '\0';
+ break;
+ default:
+ *arg = ch;
+ break;
+ } else
+ *arg = ch;
+
+ if (!cnt)
+ errx(1, "no delimiters specified");
+ return(cnt);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: paste [-s] [-d delimiters] file ...\n");
+ exit(1);
+}
diff --git a/usr.bin/patch/Makefile b/usr.bin/patch/Makefile
new file mode 100644
index 000000000000..2ec7806782da
--- /dev/null
+++ b/usr.bin/patch/Makefile
@@ -0,0 +1,12 @@
+# $OpenBSD: Makefile,v 1.4 2005/05/16 15:22:46 espie Exp $
+
+.include <src.opts.mk>
+
+PROG= patch
+
+SRCS= backupfile.c inp.c mkpath.c patch.c pch.c util.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/patch/Makefile.depend b/usr.bin/patch/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/patch/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/patch/backupfile.c b/usr.bin/patch/backupfile.c
new file mode 100644
index 000000000000..630733009eb6
--- /dev/null
+++ b/usr.bin/patch/backupfile.c
@@ -0,0 +1,244 @@
+/*-
+ * Copyright (C) 1990 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * without restriction.
+ *
+ * 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.
+ *
+ * backupfile.c -- make Emacs style backup file names
+ *
+ * David MacKenzie <djm@ai.mit.edu>. Some algorithms adapted from GNU Emacs.
+ *
+ * $OpenBSD: backupfile.c,v 1.20 2009/10/27 23:59:41 deraadt Exp $
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "backupfile.h"
+
+
+#define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
+
+/* Which type of backup file names are generated. */
+enum backup_type backup_type = none;
+
+/*
+ * The extension added to file names to produce a simple (as opposed to
+ * numbered) backup file name.
+ */
+const char *simple_backup_suffix = "~";
+
+static char *concat(const char *, const char *);
+static char *make_version_name(const char *, int);
+static int max_backup_version(const char *, const char *);
+static int version_number(const char *, const char *, size_t);
+static int argmatch(const char *, const char **);
+static void invalid_arg(const char *, const char *, int);
+
+/*
+ * Return the name of the new backup file for file FILE, allocated with
+ * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it
+ * is the root directory. Do not call this function if backup_type == none.
+ */
+char *
+find_backup_file_name(const char *file)
+{
+ char *dir, *base_versions, *tmp_file;
+ int highest_backup;
+
+ if (backup_type == simple)
+ return concat(file, simple_backup_suffix);
+ tmp_file = strdup(file);
+ if (tmp_file == NULL)
+ return NULL;
+ base_versions = concat(basename(tmp_file), ".~");
+ free(tmp_file);
+ if (base_versions == NULL)
+ return NULL;
+ tmp_file = strdup(file);
+ if (tmp_file == NULL) {
+ free(base_versions);
+ return NULL;
+ }
+ dir = dirname(tmp_file);
+ if (dir == NULL) {
+ free(base_versions);
+ free(tmp_file);
+ return NULL;
+ }
+ highest_backup = max_backup_version(base_versions, dir);
+ free(base_versions);
+ free(tmp_file);
+ if (backup_type == numbered_existing && highest_backup == 0)
+ return concat(file, simple_backup_suffix);
+ return make_version_name(file, highest_backup + 1);
+}
+
+/*
+ * Return the number of the highest-numbered backup file for file FILE in
+ * directory DIR. If there are no numbered backups of FILE in DIR, or an
+ * error occurs reading DIR, return 0. FILE should already have ".~" appended
+ * to it.
+ */
+static int
+max_backup_version(const char *file, const char *dir)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int highest_version, this_version;
+ size_t file_name_length;
+
+ dirp = opendir(dir);
+ if (dirp == NULL)
+ return 0;
+
+ highest_version = 0;
+ file_name_length = strlen(file);
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_namlen <= file_name_length)
+ continue;
+
+ this_version = version_number(file, dp->d_name, file_name_length);
+ if (this_version > highest_version)
+ highest_version = this_version;
+ }
+ closedir(dirp);
+ return highest_version;
+}
+
+/*
+ * Return a string, allocated with malloc, containing "FILE.~VERSION~".
+ * Return 0 if out of memory.
+ */
+static char *
+make_version_name(const char *file, int version)
+{
+ char *backup_name;
+
+ if (asprintf(&backup_name, "%s.~%d~", file, version) == -1)
+ return NULL;
+ return backup_name;
+}
+
+/*
+ * If BACKUP is a numbered backup of BASE, return its version number;
+ * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should
+ * already have ".~" appended to it.
+ */
+static int
+version_number(const char *base, const char *backup, size_t base_length)
+{
+ int version;
+ const char *p;
+
+ version = 0;
+ if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
+ for (p = &backup[base_length]; ISDIGIT(*p); ++p)
+ version = version * 10 + *p - '0';
+ if (p[0] != '~' || p[1])
+ version = 0;
+ }
+ return version;
+}
+
+/*
+ * Return the newly-allocated concatenation of STR1 and STR2. If out of
+ * memory, return 0.
+ */
+static char *
+concat(const char *str1, const char *str2)
+{
+ char *newstr;
+
+ if (asprintf(&newstr, "%s%s", str1, str2) == -1)
+ return NULL;
+ return newstr;
+}
+
+/*
+ * If ARG is an unambiguous match for an element of the null-terminated array
+ * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it
+ * does not match any element or -2 if it is ambiguous (is a prefix of more
+ * than one element).
+ */
+static int
+argmatch(const char *arg, const char **optlist)
+{
+ int i; /* Temporary index in OPTLIST. */
+ size_t arglen; /* Length of ARG. */
+ int matchind = -1; /* Index of first nonexact match. */
+ int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
+
+ arglen = strlen(arg);
+
+ /* Test all elements for either exact match or abbreviated matches. */
+ for (i = 0; optlist[i]; i++) {
+ if (!strncmp(optlist[i], arg, arglen)) {
+ if (strlen(optlist[i]) == arglen)
+ /* Exact match found. */
+ return i;
+ else if (matchind == -1)
+ /* First nonexact match found. */
+ matchind = i;
+ else
+ /* Second nonexact match found. */
+ ambiguous = 1;
+ }
+ }
+ if (ambiguous)
+ return -2;
+ else
+ return matchind;
+}
+
+/*
+ * Error reporting for argmatch. KIND is a description of the type of entity
+ * that was being matched. VALUE is the invalid value that was given. PROBLEM
+ * is the return value from argmatch.
+ */
+static void
+invalid_arg(const char *kind, const char *value, int problem)
+{
+ fprintf(stderr, "patch: ");
+ if (problem == -1)
+ fprintf(stderr, "invalid");
+ else /* Assume -2. */
+ fprintf(stderr, "ambiguous");
+ fprintf(stderr, " %s `%s'\n", kind, value);
+}
+
+static const char *backup_args[] = {
+ "none", "never", "simple", "nil", "existing", "t", "numbered", 0
+};
+
+static enum backup_type backup_types[] = {
+ none, simple, simple, numbered_existing,
+ numbered_existing, numbered, numbered
+};
+
+/*
+ * Return the type of backup indicated by VERSION. Unique abbreviations are
+ * accepted.
+ */
+enum backup_type
+get_version(const char *version)
+{
+ int i;
+
+ if (version == NULL || *version == '\0')
+ return numbered_existing;
+ i = argmatch(version, backup_args);
+ if (i >= 0)
+ return backup_types[i];
+ invalid_arg("version control type", version, i);
+ exit(2);
+}
diff --git a/usr.bin/patch/backupfile.h b/usr.bin/patch/backupfile.h
new file mode 100644
index 000000000000..925212be377a
--- /dev/null
+++ b/usr.bin/patch/backupfile.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (C) 1990 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * without restriction.
+ *
+ * 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.
+ *
+ * backupfile.h -- declarations for making Emacs style backup file names
+ *
+ * $OpenBSD: backupfile.h,v 1.6 2003/07/28 18:35:36 otto Exp $
+ */
+
+/* When to make backup files. */
+enum backup_type {
+ /* Never make backups. */
+ none,
+
+ /* Make simple backups of every file. */
+ simple,
+
+ /*
+ * Make numbered backups of files that already have numbered backups,
+ * and simple backups of the others.
+ */
+ numbered_existing,
+
+ /* Make numbered backups of every file. */
+ numbered
+};
+
+extern enum backup_type backup_type;
+extern const char *simple_backup_suffix;
+
+char *find_backup_file_name(const char *file);
+enum backup_type get_version(const char *version);
diff --git a/usr.bin/patch/common.h b/usr.bin/patch/common.h
new file mode 100644
index 000000000000..0e73bd897674
--- /dev/null
+++ b/usr.bin/patch/common.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: common.h,v 1.26 2006/03/11 19:41:30 otto Exp $
+ */
+
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define DEBUGGING
+
+/* constants */
+
+#define MAXHUNKSIZE 200000 /* is this enough lines? */
+#define INITHUNKMAX 125 /* initial dynamic allocation size */
+#define INITLINELEN 4096
+#define BUFFERSIZE 4096
+#define LINENUM_MAX LONG_MAX
+
+#define ORIGEXT ".orig"
+#define REJEXT ".rej"
+
+/* handy definitions */
+
+#define strEQ(s1,s2) (strcmp(s1, s2) == 0)
+#define strnNE(s1,s2,l) (strncmp(s1, s2, l) != 0)
+#define strnEQ(s1,s2,l) (strncmp(s1, s2, l) == 0)
+
+/* typedefs */
+
+typedef long LINENUM; /* must be signed */
+
+/* globals */
+
+extern mode_t filemode;
+
+extern char *buf; /* general purpose buffer */
+extern size_t buf_size; /* size of general purpose buffer */
+
+extern bool using_plan_a; /* try to keep everything in memory */
+extern bool out_of_mem; /* ran out of memory in plan a */
+extern bool nonempty_patchf_seen; /* seen a non-zero-length patch file? */
+
+#define MAXFILEC 2
+
+extern char *filearg[MAXFILEC];
+extern bool ok_to_create_file;
+extern char *outname;
+extern char *origprae;
+
+extern char *TMPOUTNAME;
+extern char *TMPINNAME;
+extern char *TMPREJNAME;
+extern char *TMPPATNAME;
+extern bool toutkeep;
+extern bool trejkeep;
+
+#ifdef DEBUGGING
+extern int debug;
+#endif
+
+extern bool force;
+extern bool batch;
+extern bool verbose;
+extern bool reverse;
+extern bool noreverse;
+extern bool skip_rest_of_patch;
+extern int strippath;
+extern bool canonicalize;
+/* TRUE if -C was specified on command line. */
+extern bool check_only;
+extern bool warn_on_invalid_line;
+extern bool last_line_missing_eol;
+
+
+#define CONTEXT_DIFF 1
+#define NORMAL_DIFF 2
+#define ED_DIFF 3
+#define NEW_CONTEXT_DIFF 4
+#define UNI_DIFF 5
+
+extern int diff_type;
+extern char *revision; /* prerequisite revision, if any */
+extern LINENUM input_lines; /* how long is input file in lines */
+
+extern int posix;
+
diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c
new file mode 100644
index 000000000000..ccc9a39b117b
--- /dev/null
+++ b/usr.bin/patch/inp.c
@@ -0,0 +1,432 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: inp.c,v 1.44 2015/07/26 14:32:19 millert Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <libgen.h>
+#include <paths.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+
+
+/* Input-file-with-indexable-lines abstract type */
+
+static size_t i_size; /* size of the input file */
+static char *i_womp; /* plan a buffer for entire file */
+static char **i_ptr; /* pointers to lines in i_womp */
+static char empty_line[] = { '\0' };
+
+static int tifd = -1; /* plan b virtual string array */
+static char *tibuf[2]; /* plan b buffers */
+static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
+static size_t lines_per_buf; /* how many lines per buffer */
+static size_t tibuflen; /* plan b buffer length */
+static size_t tireclen; /* length of records in tmp file */
+
+static bool rev_in_string(const char *);
+static bool reallocate_lines(size_t *);
+
+/* returns false if insufficient memory */
+static bool plan_a(const char *);
+
+static void plan_b(const char *);
+
+/* New patch--prepare to edit another file. */
+
+void
+re_input(void)
+{
+ if (using_plan_a) {
+ free(i_ptr);
+ i_ptr = NULL;
+ if (i_womp != NULL) {
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ }
+ i_size = 0;
+ } else {
+ using_plan_a = true; /* maybe the next one is smaller */
+ close(tifd);
+ tifd = -1;
+ free(tibuf[0]);
+ free(tibuf[1]);
+ tibuf[0] = tibuf[1] = NULL;
+ tiline[0] = tiline[1] = -1;
+ tireclen = 0;
+ }
+}
+
+/* Construct the line index, somehow or other. */
+
+void
+scan_input(const char *filename)
+{
+ if (!plan_a(filename))
+ plan_b(filename);
+ if (verbose) {
+ say("Patching file %s using Plan %s...\n", filename,
+ (using_plan_a ? "A" : "B"));
+ }
+}
+
+static bool
+reallocate_lines(size_t *lines_allocated)
+{
+ char **p;
+ size_t new_size;
+
+ new_size = *lines_allocated * 3 / 2;
+ p = reallocarray(i_ptr, new_size + 2, sizeof(char *));
+ if (p == NULL) { /* shucks, it was a near thing */
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ free(i_ptr);
+ i_ptr = NULL;
+ *lines_allocated = 0;
+ return false;
+ }
+ *lines_allocated = new_size;
+ i_ptr = p;
+ return true;
+}
+
+/* Try keeping everything in memory. */
+
+static bool
+plan_a(const char *filename)
+{
+ int ifd, statfailed;
+ char *p, *s;
+ struct stat filestat;
+ ptrdiff_t sz;
+ size_t i;
+ size_t iline, lines_allocated;
+
+#ifdef DEBUGGING
+ if (debug & 8)
+ return false;
+#endif
+
+ if (filename == NULL || *filename == '\0')
+ return false;
+
+ statfailed = stat(filename, &filestat);
+ if (statfailed && ok_to_create_file) {
+ if (verbose)
+ say("(Creating file %s...)\n", filename);
+
+ /*
+ * in check_patch case, we still display `Creating file' even
+ * though we're not. The rule is that -C should be as similar
+ * to normal patch behavior as possible
+ */
+ if (check_only)
+ return true;
+ makedirs(filename, true);
+ close(creat(filename, 0666));
+ statfailed = stat(filename, &filestat);
+ }
+ if (statfailed)
+ fatal("can't find %s\n", filename);
+ filemode = filestat.st_mode;
+ if (!S_ISREG(filemode))
+ fatal("%s is not a normal file--can't patch\n", filename);
+ if ((uint64_t)filestat.st_size > SIZE_MAX) {
+ say("block too large to mmap\n");
+ return false;
+ }
+ i_size = (size_t)filestat.st_size;
+ if (out_of_mem) {
+ set_hunkmax(); /* make sure dynamic arrays are allocated */
+ out_of_mem = false;
+ return false; /* force plan b because plan a bombed */
+ }
+ if ((ifd = open(filename, O_RDONLY)) < 0)
+ pfatal("can't open file %s", filename);
+
+ if (i_size) {
+ i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
+ if (i_womp == MAP_FAILED) {
+ perror("mmap failed");
+ i_womp = NULL;
+ close(ifd);
+ return false;
+ }
+ } else {
+ i_womp = NULL;
+ }
+
+ close(ifd);
+ if (i_size)
+ madvise(i_womp, i_size, MADV_SEQUENTIAL);
+
+ /* estimate the number of lines */
+ lines_allocated = i_size / 25;
+ if (lines_allocated < 100)
+ lines_allocated = 100;
+
+ if (!reallocate_lines(&lines_allocated))
+ return false;
+
+ /* now scan the buffer and build pointer array */
+ iline = 1;
+ i_ptr[iline] = i_womp;
+ /*
+ * Testing for NUL here actively breaks files that innocently use NUL
+ * for other reasons. mmap(2) succeeded, just scan the whole buffer.
+ */
+ for (s = i_womp, i = 0; i < i_size; s++, i++) {
+ if (*s == '\n') {
+ if (iline == lines_allocated) {
+ if (!reallocate_lines(&lines_allocated))
+ return false;
+ }
+ /* these are NOT NUL terminated */
+ i_ptr[++iline] = s + 1;
+ }
+ }
+ /* if the last line contains no EOL, append one */
+ if (i_size > 0 && i_womp[i_size - 1] != '\n') {
+ last_line_missing_eol = true;
+ /* fix last line */
+ sz = s - i_ptr[iline];
+ p = malloc(sz + 1);
+ if (p == NULL) {
+ free(i_ptr);
+ i_ptr = NULL;
+ munmap(i_womp, i_size);
+ i_womp = NULL;
+ return false;
+ }
+
+ memcpy(p, i_ptr[iline], sz);
+ p[sz] = '\n';
+ i_ptr[iline] = p;
+ /* count the extra line and make it point to some valid mem */
+ i_ptr[++iline] = empty_line;
+ } else
+ last_line_missing_eol = false;
+
+ input_lines = iline - 1;
+
+ /* now check for revision, if any */
+
+ if (revision != NULL) {
+ if (i_womp == NULL || !rev_in_string(i_womp)) {
+ if (force) {
+ if (verbose)
+ say("Warning: this file doesn't appear "
+ "to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal("this file doesn't appear to be the "
+ "%s version--aborting.\n",
+ revision);
+ } else {
+ ask("This file doesn't appear to be the "
+ "%s version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal("aborted\n");
+ }
+ } else if (verbose)
+ say("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+ return true; /* plan a will work */
+}
+
+/* Keep (virtually) nothing in memory. */
+
+static void
+plan_b(const char *filename)
+{
+ FILE *ifp;
+ size_t i = 0, j, blen = 0, maxlen = 1;
+ ssize_t len;
+ char *p = NULL;
+ bool found_revision = (revision == NULL);
+
+ using_plan_a = false;
+ if ((ifp = fopen(filename, "r")) == NULL)
+ pfatal("can't open file %s", filename);
+ unlink(TMPINNAME);
+ if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
+ pfatal("can't open file %s", TMPINNAME);
+ len = 0;
+ maxlen = 1;
+ while ((len = getline(&p, &blen, ifp)) >= 0) {
+ if (p[len - 1] == '\n')
+ p[len - 1] = '\0';
+ else {
+ /* EOF without EOL */
+ last_line_missing_eol = true;
+ len++;
+ }
+ if (revision != NULL && !found_revision && rev_in_string(p))
+ found_revision = true;
+ if ((size_t)len > maxlen)
+ maxlen = len; /* find longest line */
+ }
+ free(p);
+ if (ferror(ifp))
+ pfatal("can't read file %s", filename);
+
+ if (revision != NULL) {
+ if (!found_revision) {
+ if (force) {
+ if (verbose)
+ say("Warning: this file doesn't appear "
+ "to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal("this file doesn't appear to be the "
+ "%s version--aborting.\n",
+ revision);
+ } else {
+ ask("This file doesn't appear to be the %s "
+ "version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal("aborted\n");
+ }
+ } else if (verbose)
+ say("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+ fseek(ifp, 0L, SEEK_SET); /* rewind file */
+ tireclen = maxlen;
+ tibuflen = maxlen > BUFFERSIZE ? maxlen : BUFFERSIZE;
+ lines_per_buf = tibuflen / maxlen;
+ tibuf[0] = malloc(tibuflen + 1);
+ if (tibuf[0] == NULL)
+ fatal("out of memory\n");
+ tibuf[1] = malloc(tibuflen + 1);
+ if (tibuf[1] == NULL)
+ fatal("out of memory\n");
+ for (i = 1;; i++) {
+ p = tibuf[0] + maxlen * (i % lines_per_buf);
+ if (i % lines_per_buf == 0) /* new block */
+ if (write(tifd, tibuf[0], tibuflen) !=
+ (ssize_t) tibuflen)
+ pfatal("can't write temp file");
+ if (fgets(p, maxlen + 1, ifp) == NULL) {
+ input_lines = i - 1;
+ if (i % lines_per_buf != 0)
+ if (write(tifd, tibuf[0], tibuflen) !=
+ (ssize_t) tibuflen)
+ pfatal("can't write temp file");
+ break;
+ }
+ j = strlen(p);
+ /* These are '\n' terminated strings, so no need to add a NUL */
+ if (j == 0 || p[j - 1] != '\n')
+ p[j] = '\n';
+ }
+ fclose(ifp);
+ close(tifd);
+ if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
+ pfatal("can't reopen file %s", TMPINNAME);
+}
+
+/*
+ * Fetch a line from the input file, \n terminated, not necessarily \0.
+ */
+char *
+ifetch(LINENUM line, int whichbuf)
+{
+ if (line < 1 || line > input_lines) {
+ if (warn_on_invalid_line) {
+ say("No such line %ld in input file, ignoring\n", line);
+ warn_on_invalid_line = false;
+ }
+ return NULL;
+ }
+ if (using_plan_a)
+ return i_ptr[line];
+ else {
+ LINENUM offline = line % lines_per_buf;
+ LINENUM baseline = line - offline;
+
+ if (tiline[0] == baseline)
+ whichbuf = 0;
+ else if (tiline[1] == baseline)
+ whichbuf = 1;
+ else {
+ tiline[whichbuf] = baseline;
+
+ if (lseek(tifd, (off_t) (baseline / lines_per_buf *
+ tibuflen), SEEK_SET) < 0)
+ pfatal("cannot seek in the temporary input file");
+
+ if (read(tifd, tibuf[whichbuf], tibuflen) !=
+ (ssize_t) tibuflen)
+ pfatal("error reading tmp file %s", TMPINNAME);
+ }
+ return tibuf[whichbuf] + (tireclen * offline);
+ }
+}
+
+/*
+ * True if the string argument contains the revision number we want.
+ */
+static bool
+rev_in_string(const char *string)
+{
+ const char *s;
+ size_t patlen;
+
+ if (revision == NULL)
+ return true;
+ patlen = strlen(revision);
+ if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
+ return true;
+ for (s = string; *s; s++) {
+ if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
+ isspace((unsigned char)s[patlen + 1])) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/usr.bin/patch/inp.h b/usr.bin/patch/inp.h
new file mode 100644
index 000000000000..bfdc88a8c570
--- /dev/null
+++ b/usr.bin/patch/inp.h
@@ -0,0 +1,31 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: inp.h,v 1.8 2003/08/15 08:00:51 otto Exp $
+ */
+
+void re_input(void);
+void scan_input(const char *);
+char *ifetch(LINENUM, int);
diff --git a/usr.bin/patch/mkpath.c b/usr.bin/patch/mkpath.c
new file mode 100644
index 000000000000..0fbd58a759a8
--- /dev/null
+++ b/usr.bin/patch/mkpath.c
@@ -0,0 +1,79 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ *
+ * $OpenBSD: mkpath.c,v 1.2 2005/06/20 07:14:06 otto Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+
+int mkpath(char *);
+
+/* Code taken directly from mkdir(1).
+
+ * mkpath -- create directories.
+ * path - path
+ */
+int
+mkpath(char *path)
+{
+ struct stat sb;
+ char *slash;
+ int done = 0;
+
+ slash = path;
+
+ while (!done) {
+ slash += strspn(slash, "/");
+ slash += strcspn(slash, "/");
+
+ done = (*slash == '\0');
+ *slash = '\0';
+
+ if (stat(path, &sb)) {
+ if (errno != ENOENT || (mkdir(path, 0777) &&
+ errno != EEXIST)) {
+ warn("%s", path);
+ return (-1);
+ }
+ } else if (!S_ISDIR(sb.st_mode)) {
+ warnx("%s: %s", path, strerror(ENOTDIR));
+ return (-1);
+ }
+
+ *slash = '/';
+ }
+
+ return (0);
+}
+
diff --git a/usr.bin/patch/patch.1 b/usr.bin/patch/patch.1
new file mode 100644
index 000000000000..cfcd8a99ad61
--- /dev/null
+++ b/usr.bin/patch/patch.1
@@ -0,0 +1,691 @@
+.\"-
+.\" Copyright 1986, Larry Wall
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following condition
+.\" is met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this condition and the following disclaimer.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $OpenBSD: patch.1,v 1.27 2014/04/15 06:26:54 jmc Exp $
+.Dd November 3, 2019
+.Dt PATCH 1
+.Os
+.Sh NAME
+.Nm patch
+.Nd apply a diff file to an original
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl bCcEeflNnRstuv
+.Op Fl B Ar backup-prefix
+.Op Fl D Ar symbol
+.Op Fl d Ar directory
+.Op Fl F Ar max-fuzz
+.Op Fl i Ar patchfile
+.Op Fl o Ar out-file
+.Op Fl p Ar strip-count
+.Op Fl r Ar rej-name
+.Op Fl V Cm t | nil | never | none
+.Op Fl x Ar number
+.Op Fl z Ar backup-ext
+.Op Fl Fl posix
+.Op Ar origfile Op Ar patchfile
+.Ek
+.Nm
+.Pf \*(Lt Ar patchfile
+.Sh DESCRIPTION
+.Nm
+will take a patch file containing any of the four forms of difference
+listing produced by the
+.Xr diff 1
+program and apply those differences to an original file,
+producing a patched version.
+If
+.Ar patchfile
+is omitted, or is a hyphen, the patch will be read from the standard input.
+.Pp
+.Nm
+will attempt to determine the type of the diff listing, unless overruled by a
+.Fl c ,
+.Fl e ,
+.Fl n ,
+or
+.Fl u
+option.
+Context diffs (old-style, new-style, and unified) and
+normal diffs are applied directly by the
+.Nm
+program itself, whereas ed diffs are simply fed to the
+.Xr ed 1
+editor via a pipe.
+.Pp
+If the
+.Ar patchfile
+contains more than one patch,
+.Nm
+will try to apply each of them as if they came from separate patch files.
+This means, among other things, that it is assumed that the name of the file
+to patch must be determined for each diff listing, and that the garbage before
+each diff listing will be examined for interesting things such as file names
+and revision level (see the section on
+.Sx Filename Determination
+below).
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Xo
+.Fl B Ar backup-prefix ,
+.Fl Fl prefix Ar backup-prefix
+.Xc
+Causes the next argument to be interpreted as a prefix to the backup file
+name.
+If this argument is specified, any argument to
+.Fl z
+will be ignored.
+.It Fl b , Fl Fl backup
+Save a backup copy of the file before it is modified.
+By default the original file is saved with a backup extension of
+.Qq .orig
+unless the file already has a numbered backup, in which case a numbered
+backup is made.
+This is equivalent to specifying
+.Qo Fl V Cm existing Qc .
+This option is currently the default, unless
+.Fl -posix
+is specified.
+.It Fl C , Fl Fl check , Fl Fl dry-run
+Checks that the patch would apply cleanly, but does not modify anything.
+.It Fl c , Fl Fl context
+Forces
+.Nm
+to interpret the patch file as a context diff.
+.It Xo
+.Fl D Ar symbol ,
+.Fl Fl ifdef Ar symbol
+.Xc
+Causes
+.Nm
+to use the
+.Qq #ifdef...#endif
+construct to mark changes.
+The argument following will be used as the differentiating symbol.
+Note that, unlike the C compiler, there must be a space between the
+.Fl D
+and the argument.
+.It Xo
+.Fl d Ar directory ,
+.Fl Fl directory Ar directory
+.Xc
+Causes
+.Nm
+to interpret the next argument as a directory,
+and change the working directory to it before doing anything else.
+.It Fl E , Fl Fl remove-empty-files
+Causes
+.Nm
+to remove output files that are empty after the patches have been applied.
+This option is useful when applying patches that create or remove files.
+.It Fl e , Fl Fl ed
+Forces
+.Nm
+to interpret the patch file as an
+.Xr ed 1
+script.
+.It Xo
+.Fl F Ar max-fuzz ,
+.Fl Fl fuzz Ar max-fuzz
+.Xc
+Sets the maximum fuzz factor.
+This option only applies to context diffs, and causes
+.Nm
+to ignore up to that many lines in looking for places to install a hunk.
+Note that a larger fuzz factor increases the odds of a faulty patch.
+The default fuzz factor is 2, and it may not be set to more than
+the number of lines of context in the context diff, ordinarily 3.
+.It Fl f , Fl Fl force
+Forces
+.Nm
+to assume that the user knows exactly what he or she is doing, and to not
+ask any questions.
+It assumes the following:
+skip patches for which a file to patch cannot be found;
+patch files even though they have the wrong version for the
+.Qq Prereq :
+line in the patch;
+and assume that patches are not reversed even if they look like they are.
+This option does not suppress commentary; use
+.Fl s
+for that.
+.It Xo
+.Fl i Ar patchfile ,
+.Fl Fl input Ar patchfile
+.Xc
+Causes the next argument to be interpreted as the input file name
+(i.e., a patchfile).
+This option may be specified multiple times.
+.It Fl l , Fl Fl ignore-whitespace
+Causes the pattern matching to be done loosely, in case the tabs and
+spaces have been munged in your input file.
+Any sequence of whitespace in the pattern line will match any sequence
+in the input file.
+Normal characters must still match exactly.
+Each line of the context must still match a line in the input file.
+.It Fl N , Fl Fl forward
+Causes
+.Nm
+to ignore patches that it thinks are reversed or already applied.
+See also
+.Fl R .
+.It Fl n , Fl Fl normal
+Forces
+.Nm
+to interpret the patch file as a normal diff.
+.It Xo
+.Fl o Ar out-file ,
+.Fl Fl output Ar out-file
+.Xc
+Causes the next argument to be interpreted as the output file name.
+.It Xo
+.Fl p Ar strip-count ,
+.Fl Fl strip Ar strip-count
+.Xc
+Sets the pathname strip count,
+which controls how pathnames found in the patch file are treated,
+in case you keep your files in a different directory than the person who sent
+out the patch.
+The strip count specifies how many slashes are to be stripped from
+the front of the pathname.
+(Any intervening directory names also go away.)
+For example, supposing the file name in the patch file was
+.Pa /u/howard/src/blurfl/blurfl.c :
+.Pp
+Setting
+.Fl p Ns Ar 0
+gives the entire pathname unmodified.
+.Pp
+.Fl p Ns Ar 1
+gives
+.Pp
+.D1 Pa u/howard/src/blurfl/blurfl.c
+.Pp
+without the leading slash.
+.Pp
+.Fl p Ns Ar 4
+gives
+.Pp
+.D1 Pa blurfl/blurfl.c
+.Pp
+Not specifying
+.Fl p
+at all just gives you
+.Pa blurfl.c ,
+unless all of the directories in the leading path
+.Pq Pa u/howard/src/blurfl
+exist and that path is relative,
+in which case you get the entire pathname unmodified.
+Whatever you end up with is looked for either in the current directory,
+or the directory specified by the
+.Fl d
+option.
+.It Fl R , Fl Fl reverse
+Tells
+.Nm
+that this patch was created with the old and new files swapped.
+(Yes, I am afraid that does happen occasionally, human nature being what it
+is.)
+.Nm
+will attempt to swap each hunk around before applying it.
+Rejects will come out in the swapped format.
+The
+.Fl R
+option will not work with ed diff scripts because there is too little
+information to reconstruct the reverse operation.
+.Pp
+If the first hunk of a patch fails,
+.Nm
+will reverse the hunk to see if it can be applied that way.
+If it can, you will be asked if you want to have the
+.Fl R
+option set.
+If it cannot, the patch will continue to be applied normally.
+(Note: this method cannot detect a reversed patch if it is a normal diff
+and if the first command is an append (i.e., it should have been a delete)
+since appends always succeed, due to the fact that a null context will match
+anywhere.
+Luckily, most patches add or change lines rather than delete them, so most
+reversed normal diffs will begin with a delete, which will fail, triggering
+the heuristic.)
+.It Xo
+.Fl r Ar rej-name ,
+.Fl Fl reject-file Ar rej-name
+.Xc
+Causes the next argument to be interpreted as the reject file name.
+.It Xo
+.Fl s , Fl Fl quiet ,
+.Fl Fl silent
+.Xc
+Makes
+.Nm
+do its work silently, unless an error occurs.
+.It Fl t , Fl Fl batch
+Similar to
+.Fl f ,
+in that it suppresses questions, but makes some different assumptions:
+skip patches for which a file to patch cannot be found (the same as
+.Fl f ) ;
+skip patches for which the file has the wrong version for the
+.Qq Prereq :
+line in the patch;
+and assume that patches are reversed if they look like they are.
+.It Fl u , Fl Fl unified
+Forces
+.Nm
+to interpret the patch file as a unified context diff (a unidiff).
+.It Xo
+.Fl V Cm t | nil | never | none ,
+.Fl Fl version-control Cm t | nil | never | none
+.Xc
+Causes the next argument to be interpreted as a method for creating
+backup file names.
+The type of backups made can also be given in the
+.Ev PATCH_VERSION_CONTROL
+or
+.Ev VERSION_CONTROL
+environment variables, which are overridden by this option.
+The
+.Fl B
+option overrides this option, causing the prefix to always be used for
+making backup file names.
+The values of the
+.Ev PATCH_VERSION_CONTROL
+and
+.Ev VERSION_CONTROL
+environment variables and the argument to the
+.Fl V
+option are like the GNU Emacs
+.Dq version-control
+variable; they also recognize synonyms that are more descriptive.
+The valid values are (unique abbreviations are accepted):
+.Bl -tag -width Ds -offset indent
+.It Cm t , numbered
+Always make numbered backups.
+.It Cm nil , existing
+Make numbered backups of files that already have them,
+simple backups of the others.
+.It Cm never , simple
+Always make simple backups.
+.It Cm none
+Do not make backups.
+.El
+.It Fl v , Fl Fl version
+Causes
+.Nm
+to print out its revision header and patch level.
+.It Xo
+.Fl x Ar number ,
+.Fl Fl debug Ar number
+.Xc
+Sets internal debugging flags, and is of interest only to
+.Nm
+patchers.
+.It Xo
+.Fl z Ar backup-ext ,
+.Fl Fl suffix Ar backup-ext
+.Xc
+Causes the next argument to be interpreted as the backup extension, to be
+used in place of
+.Qq .orig .
+.It Fl Fl posix
+Enables strict
+.St -p1003.1-2008
+conformance, specifically:
+.Bl -enum
+.It
+Backup files are not created unless the
+.Fl b
+option is specified.
+.It
+If unspecified, the file name used is the first of the old, new and
+index files that exists.
+.El
+.El
+.Ss Patch Application
+.Nm
+will try to skip any leading garbage, apply the diff,
+and then skip any trailing garbage.
+Thus you could feed an article or message containing a
+diff listing to
+.Nm ,
+and it should work.
+If the entire diff is indented by a consistent amount,
+this will be taken into account.
+.Pp
+With context diffs, and to a lesser extent with normal diffs,
+.Nm
+can detect when the line numbers mentioned in the patch are incorrect,
+and will attempt to find the correct place to apply each hunk of the patch.
+As a first guess, it takes the line number mentioned for the hunk, plus or
+minus any offset used in applying the previous hunk.
+If that is not the correct place,
+.Nm
+will scan both forwards and backwards for a set of lines matching the context
+given in the hunk.
+First
+.Nm
+looks for a place where all lines of the context match.
+If no such place is found, and it is a context diff, and the maximum fuzz factor
+is set to 1 or more, then another scan takes place ignoring the first and last
+line of context.
+If that fails, and the maximum fuzz factor is set to 2 or more,
+the first two and last two lines of context are ignored,
+and another scan is made.
+.Pq The default maximum fuzz factor is 2 .
+.Pp
+If
+.Nm
+cannot find a place to install that hunk of the patch, it will put the hunk
+out to a reject file, which normally is the name of the output file plus
+.Qq .rej .
+(Note that the rejected hunk will come out in context diff form whether the
+input patch was a context diff or a normal diff.
+If the input was a normal diff, many of the contexts will simply be null.)
+The line numbers on the hunks in the reject file may be different than
+in the patch file: they reflect the approximate location patch thinks the
+failed hunks belong in the new file rather than the old one.
+.Pp
+As each hunk is completed, you will be told whether the hunk succeeded or
+failed, and which line (in the new file)
+.Nm
+thought the hunk should go on.
+If this is different from the line number specified in the diff,
+you will be told the offset.
+A single large offset MAY be an indication that a hunk was installed in the
+wrong place.
+You will also be told if a fuzz factor was used to make the match, in which
+case you should also be slightly suspicious.
+.Ss Filename Determination
+If no original file is specified on the command line,
+.Nm
+will try to figure out from the leading garbage what the name of the file
+to edit is.
+When checking a prospective file name, pathname components are stripped
+as specified by the
+.Fl p
+option and the file's existence and writability are checked relative
+to the current working directory (or the directory specified by the
+.Fl d
+option).
+.Pp
+If the diff is a context or unified diff,
+.Nm
+is able to determine the old and new file names from the diff header.
+For context diffs, the
+.Dq old
+file is specified in the line beginning with
+.Qq ***
+and the
+.Dq new
+file is specified in the line beginning with
+.Qq --- .
+For a unified diff, the
+.Dq old
+file is specified in the line beginning with
+.Qq ---
+and the
+.Dq new
+file is specified in the line beginning with
+.Qq +++ .
+If there is an
+.Qq Index :
+line in the leading garbage (regardless of the diff type),
+.Nm
+will use the file name from that line as the
+.Dq index
+file.
+.Pp
+.Nm
+will choose the file name by performing the following steps, with the first
+match used:
+.Bl -enum
+.It
+If
+.Nm
+is operating in strict
+.St -p1003.1-2008
+mode, the first of the
+.Dq old ,
+.Dq new
+and
+.Dq index
+file names that exist is used.
+Otherwise,
+.Nm
+will examine either the
+.Dq old
+and
+.Dq new
+file names or, for a non-context diff, the
+.Dq index
+file name, and choose the file name with the fewest path components,
+the shortest basename, and the shortest total file name length (in that order).
+.It
+If no suitable file was found to patch, the patch file is a context or
+unified diff, and the old file was zero length, the new file name is
+created and used.
+.It
+If the file name still cannot be determined,
+.Nm
+will prompt the user for the file name to use.
+.El
+.Pp
+Additionally, if the leading garbage contains a
+.Qq Prereq:\ \&
+line,
+.Nm
+will take the first word from the prerequisites line (normally a version
+number) and check the input file to see if that word can be found.
+If not,
+.Nm
+will ask for confirmation before proceeding.
+.Pp
+The upshot of all this is that you should be able to say, while in a news
+interface, the following:
+.Pp
+.Dl | patch -d /usr/src/local/blurfl
+.Pp
+and patch a file in the blurfl directory directly from the article containing
+the patch.
+.Ss Backup Files
+By default, the patched version is put in place of the original, with
+the original file backed up to the same name with the extension
+.Qq .orig ,
+or as specified by the
+.Fl B ,
+.Fl V ,
+or
+.Fl z
+options.
+The extension used for making backup files may also be specified in the
+.Ev SIMPLE_BACKUP_SUFFIX
+environment variable, which is overridden by the options above.
+.Pp
+If the backup file is a symbolic or hard link to the original file,
+.Nm
+creates a new backup file name by changing the first lowercase letter
+in the last component of the file's name into uppercase.
+If there are no more lowercase letters in the name,
+it removes the first character from the name.
+It repeats this process until it comes up with a
+backup file that does not already exist or is not linked to the original file.
+.Pp
+You may also specify where you want the output to go with the
+.Fl o
+option; if that file already exists, it is backed up first.
+.Ss Notes For Patch Senders
+There are several things you should bear in mind if you are going to
+be sending out patches:
+.Pp
+First, you can save people a lot of grief by keeping a
+.Pa patchlevel.h
+file which is patched to increment the patch level as the first diff in the
+patch file you send out.
+If you put a
+.Qq Prereq :
+line in with the patch, it will not let them apply
+patches out of order without some warning.
+.Pp
+Second, make sure you have specified the file names right, either in a
+context diff header, or with an
+.Qq Index :
+line.
+If you are patching something in a subdirectory, be sure to tell the patch
+user to specify a
+.Fl p
+option as needed.
+.Pp
+Third, you can create a file by sending out a diff that compares a
+null file to the file you want to create.
+If the file you want to create already exists in the target directory when the
+diff is applied, then
+.Nm
+will identify the patch as potentially reversed and offer to reverse the patch.
+.Pp
+Fourth, take care not to send out reversed patches, since it makes people wonder
+whether they already applied the patch.
+.Pp
+Fifth, while you may be able to get away with putting 582 diff listings into
+one file, it is probably wiser to group related patches into separate files in
+case something goes haywire.
+.Sh ENVIRONMENT
+.Bl -tag -width "PATCH_VERSION_CONTROL" -compact
+.It Ev POSIXLY_CORRECT
+When set,
+.Nm
+behaves as if the
+.Fl Fl posix
+option has been specified.
+.It Ev SIMPLE_BACKUP_SUFFIX
+Extension to use for backup file names instead of
+.Qq .orig .
+.It Ev TMPDIR
+Directory to put temporary files in; default is
+.Pa /tmp .
+.It Ev PATCH_VERSION_CONTROL
+Selects when numbered backup files are made.
+.It Ev VERSION_CONTROL
+Same as
+.Ev PATCH_VERSION_CONTROL .
+.El
+.Sh FILES
+.Bl -tag -width "$TMPDIR/patch*" -compact
+.It Pa $TMPDIR/patch*
+.Nm
+temporary files
+.It Pa /dev/tty
+used to read input when
+.Nm
+prompts the user
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It 0
+Successful completion.
+.It 1
+One or more lines were written to a reject file.
+.It \*(Gt1
+An error occurred.
+.El
+.Pp
+When applying a set of patches in a loop it behooves you to check this
+exit status so you do not apply a later patch to a partially patched file.
+.Sh DIAGNOSTICS
+Too many to list here, but generally indicative that
+.Nm
+couldn't parse your patch file.
+.Pp
+The message
+.Qq Hmm...
+indicates that there is unprocessed text in the patch file and that
+.Nm
+is attempting to intuit whether there is a patch in that text and, if so,
+what kind of patch it is.
+.Sh SEE ALSO
+.Xr diff 1
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification,
+except as detailed above for the
+.Fl -posix
+option.
+.Pp
+The flags
+.Op Fl BCEFfstVvxz
+and
+.Op Fl -posix
+are extensions to that specification.
+.Sh AUTHORS
+.An Larry Wall
+with many other contributors.
+.Sh CAVEATS
+.Nm
+cannot tell if the line numbers are off in an ed script, and can only detect
+bad line numbers in a normal diff when it finds a
+.Qq change
+or a
+.Qq delete
+command.
+A context diff using fuzz factor 3 may have the same problem.
+Until a suitable interactive interface is added, you should probably do
+a context diff in these cases to see if the changes made sense.
+Of course, compiling without errors is a pretty good indication that the patch
+worked, but not always.
+.Pp
+.Nm
+usually produces the correct results, even when it has to do a lot of
+guessing.
+However, the results are guaranteed to be correct only when the patch is
+applied to exactly the same version of the file that the patch was
+generated from.
+.Sh BUGS
+Could be smarter about partial matches, excessively deviant offsets and
+swapped code, but that would take an extra pass.
+.Pp
+Check patch mode
+.Pq Fl C
+will fail if you try to check several patches in succession that build on
+each other.
+The entire
+.Nm
+code would have to be restructured to keep temporary files around so that it
+can handle this situation.
+.Pp
+If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
+#endif),
+.Nm
+is incapable of patching both versions, and, if it works at all, will likely
+patch the wrong one, and tell you that it succeeded to boot.
+.Pp
+If you apply a patch you have already applied,
+.Nm
+will think it is a reversed patch, and offer to un-apply the patch.
+This could be construed as a feature.
diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c
new file mode 100644
index 000000000000..838c721841ea
--- /dev/null
+++ b/usr.bin/patch/patch.c
@@ -0,0 +1,1227 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: patch.c,v 1.54 2014/12/13 10:31:07 tobias Exp $
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+#include "backupfile.h"
+#include "pathnames.h"
+
+mode_t filemode = 0644;
+
+char *buf; /* general purpose buffer */
+size_t buf_size; /* size of the general purpose buffer */
+
+bool using_plan_a = true; /* try to keep everything in memory */
+bool out_of_mem = false; /* ran out of memory in plan a */
+bool nonempty_patchf_seen = false; /* seen nonempty patch file? */
+
+#define MAXFILEC 2
+
+char *filearg[MAXFILEC];
+bool ok_to_create_file = false;
+char *outname = NULL;
+char *origprae = NULL;
+char *TMPOUTNAME;
+char *TMPINNAME;
+char *TMPREJNAME;
+char *TMPPATNAME;
+bool toutkeep = false;
+bool trejkeep = false;
+bool warn_on_invalid_line;
+bool last_line_missing_eol;
+
+#ifdef DEBUGGING
+int debug = 0;
+#endif
+
+bool force = false;
+bool batch = false;
+bool verbose = true;
+bool reverse = false;
+bool noreverse = false;
+bool skip_rest_of_patch = false;
+int strippath = 957;
+bool canonicalize = false;
+bool check_only = false;
+int diff_type = 0;
+char *revision = NULL; /* prerequisite revision, if any */
+LINENUM input_lines = 0; /* how long is input file in lines */
+int posix = 0; /* strict POSIX mode? */
+
+static void reinitialize_almost_everything(void);
+static void get_some_switches(void);
+static LINENUM locate_hunk(LINENUM);
+static void abort_context_hunk(void);
+static void rej_line(int, LINENUM);
+static void abort_hunk(void);
+static void apply_hunk(LINENUM);
+static void init_output(const char *);
+static void init_reject(const char *);
+static void copy_till(LINENUM, bool);
+static bool spew_output(void);
+static void dump_line(LINENUM, bool);
+static bool patch_match(LINENUM, LINENUM, LINENUM);
+static bool similar(const char *, const char *, int);
+static void usage(void);
+static bool handle_creation(bool, bool *);
+
+/* true if -E was specified on command line. */
+static bool remove_empty_files = false;
+
+/* true if -R was specified on command line. */
+static bool reverse_flag_specified = false;
+
+static bool Vflag = false;
+
+/* buffer holding the name of the rejected patch file. */
+static char rejname[PATH_MAX];
+
+/* how many input lines have been irretractibly output */
+static LINENUM last_frozen_line = 0;
+
+static int Argc; /* guess */
+static char **Argv;
+static int Argc_last; /* for restarting plan_b */
+static char **Argv_last;
+
+static FILE *ofp = NULL; /* output file pointer */
+static FILE *rejfp = NULL; /* reject file pointer */
+
+static int filec = 0; /* how many file arguments? */
+static LINENUM last_offset = 0;
+static LINENUM maxfuzz = 2;
+
+/* patch using ifdef, ifndef, etc. */
+static bool do_defines = false;
+/* #ifdef xyzzy */
+static char if_defined[128];
+/* #ifndef xyzzy */
+static char not_defined[128];
+/* #else */
+static const char else_defined[] = "#else\n";
+/* #endif xyzzy */
+static char end_defined[128];
+
+
+/* Apply a set of diffs as appropriate. */
+
+int
+main(int argc, char *argv[])
+{
+ struct stat statbuf;
+ int error = 0, hunk, failed, i, fd;
+ bool out_creating, out_existed, patch_seen, remove_file;
+ bool reverse_seen;
+ LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
+ const char *tmpdir;
+ char *v;
+
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(stderr, NULL, _IOLBF, 0);
+ for (i = 0; i < MAXFILEC; i++)
+ filearg[i] = NULL;
+
+ buf_size = INITLINELEN;
+ buf = malloc((unsigned)(buf_size));
+ if (buf == NULL)
+ fatal("out of memory\n");
+
+ /* Cons up the names of the temporary files. */
+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+ tmpdir = _PATH_TMP;
+ for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
+ ;
+ i++;
+ if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPOUTNAME)) < 0)
+ pfatal("can't create %s", TMPOUTNAME);
+ close(fd);
+
+ if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPINNAME)) < 0)
+ pfatal("can't create %s", TMPINNAME);
+ close(fd);
+
+ if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPREJNAME)) < 0)
+ pfatal("can't create %s", TMPREJNAME);
+ close(fd);
+
+ if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
+ fatal("cannot allocate memory");
+ if ((fd = mkstemp(TMPPATNAME)) < 0)
+ pfatal("can't create %s", TMPPATNAME);
+ close(fd);
+
+ v = getenv("SIMPLE_BACKUP_SUFFIX");
+ if (v)
+ simple_backup_suffix = v;
+ else
+ simple_backup_suffix = ORIGEXT;
+
+ /* parse switches */
+ Argc = argc;
+ Argv = argv;
+ get_some_switches();
+
+ if (!Vflag) {
+ if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
+ v = getenv("VERSION_CONTROL");
+ if (v != NULL || !posix)
+ backup_type = get_version(v); /* OK to pass NULL. */
+ }
+
+ /* make sure we clean up /tmp in case of disaster */
+ set_signals(0);
+
+ patch_seen = false;
+ for (open_patch_file(filearg[1]); there_is_another_patch();
+ reinitialize_almost_everything()) {
+ /* for each patch in patch file */
+
+ if (source_file != NULL && (diff_type == CONTEXT_DIFF ||
+ diff_type == NEW_CONTEXT_DIFF ||
+ diff_type == UNI_DIFF))
+ out_creating = strcmp(source_file, _PATH_DEVNULL) == 0;
+ else
+ out_creating = false;
+ patch_seen = true;
+
+ warn_on_invalid_line = true;
+
+ if (outname == NULL)
+ outname = xstrdup(filearg[0]);
+
+ /*
+ * At this point, we know if we're supposed to be creating the
+ * file and we know if we should be trying to handle a conflict
+ * between the patch and the file already existing. We defer
+ * handling it until hunk processing because we want to swap
+ * the hunk if they opt to reverse it, but we want to make sure
+ * we *can* swap the hunk without running into memory issues
+ * before we offer it. We also want to be verbose if flags or
+ * user decision cause us to skip -- this is explained a little
+ * more later.
+ */
+ out_existed = stat(outname, &statbuf) == 0;
+
+ /* for ed script just up and do it and exit */
+ if (diff_type == ED_DIFF) {
+ do_ed_script();
+ continue;
+ }
+ /* initialize the patched file */
+ if (!skip_rest_of_patch)
+ init_output(TMPOUTNAME);
+
+ /* initialize reject file */
+ init_reject(TMPREJNAME);
+
+ /* find out where all the lines are */
+ if (!skip_rest_of_patch)
+ scan_input(filearg[0]);
+
+ /*
+ * from here on, open no standard i/o files, because
+ * malloc might misfire and we can't catch it easily
+ */
+
+ /* apply each hunk of patch */
+ hunk = 0;
+ failed = 0;
+ reverse_seen = false;
+ out_of_mem = false;
+ remove_file = false;
+ while (another_hunk()) {
+ assert(!out_creating || hunk == 0);
+ hunk++;
+ fuzz = 0;
+
+ /*
+ * There are only three cases in handle_creation() that
+ * results in us skipping hunk location, in order:
+ *
+ * 1.) Potentially reversed but -f/--force'd,
+ * 2.) Potentially reversed but -N/--forward'd
+ * 3.) Reversed and the user's opted to not apply it.
+ *
+ * In all three cases, we still want to inform the user
+ * that we're ignoring it in the standard way, which is
+ * also tied to this hunk processing loop.
+ */
+ if (out_creating)
+ reverse_seen = handle_creation(out_existed,
+ &remove_file);
+
+ mymaxfuzz = pch_context();
+ if (maxfuzz < mymaxfuzz)
+ mymaxfuzz = maxfuzz;
+ if (!skip_rest_of_patch) {
+ do {
+ where = locate_hunk(fuzz);
+ if (hunk == 1 && where == 0 && !force && !reverse_seen) {
+ /* dwim for reversed patch? */
+ if (!pch_swap()) {
+ if (fuzz == 0)
+ say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
+ continue;
+ }
+ reverse = !reverse;
+ /* try again */
+ where = locate_hunk(fuzz);
+ if (where == 0) {
+ /* didn't find it swapped */
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ } else if (noreverse) {
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ say("Ignoring previously applied (or reversed) patch.\n");
+ skip_rest_of_patch = true;
+ } else if (batch) {
+ if (verbose)
+ say("%seversed (or previously applied) patch detected! %s -R.",
+ reverse ? "R" : "Unr",
+ reverse ? "Assuming" : "Ignoring");
+ } else {
+ ask("%seversed (or previously applied) patch detected! %s -R? [y] ",
+ reverse ? "R" : "Unr",
+ reverse ? "Assume" : "Ignore");
+ if (*buf == 'n') {
+ ask("Apply anyway? [n] ");
+ if (*buf != 'y')
+ skip_rest_of_patch = true;
+ else
+ reverse_seen = true;
+ where = 0;
+ reverse = !reverse;
+ if (!pch_swap())
+ /* put it back to normal */
+ fatal("lost hunk on alloc error!\n");
+ }
+ }
+ }
+ } while (!skip_rest_of_patch && where == 0 &&
+ ++fuzz <= mymaxfuzz);
+
+ if (skip_rest_of_patch) { /* just got decided */
+ if (ferror(ofp) || fclose(ofp)) {
+ say("Error writing %s\n",
+ TMPOUTNAME);
+ error = 1;
+ }
+ ofp = NULL;
+ }
+ }
+ newwhere = pch_newfirst() + last_offset;
+ if (skip_rest_of_patch) {
+ abort_hunk();
+ failed++;
+ if (verbose)
+ say("Hunk #%d ignored at %ld.\n",
+ hunk, newwhere);
+ } else if (where == 0) {
+ abort_hunk();
+ failed++;
+ if (verbose)
+ say("Hunk #%d failed at %ld.\n",
+ hunk, newwhere);
+ } else {
+ apply_hunk(where);
+ if (verbose) {
+ say("Hunk #%d succeeded at %ld",
+ hunk, newwhere);
+ if (fuzz != 0)
+ say(" with fuzz %ld", fuzz);
+ if (last_offset)
+ say(" (offset %ld line%s)",
+ last_offset,
+ last_offset == 1L ? "" : "s");
+ say(".\n");
+ }
+ }
+ }
+
+ if (out_of_mem && using_plan_a) {
+ Argc = Argc_last;
+ Argv = Argv_last;
+ say("\n\nRan out of memory using Plan A--trying again...\n\n");
+ if (ofp)
+ fclose(ofp);
+ ofp = NULL;
+ if (rejfp)
+ fclose(rejfp);
+ rejfp = NULL;
+ continue;
+ }
+ if (hunk == 0)
+ fatal("Internal error: hunk should not be 0\n");
+
+ /* finish spewing out the new file */
+ if (!skip_rest_of_patch && !spew_output()) {
+ say("Can't write %s\n", TMPOUTNAME);
+ error = 1;
+ }
+
+ /* and put the output where desired */
+ ignore_signals();
+ if (!skip_rest_of_patch) {
+ char *realout = outname;
+
+ if (!check_only) {
+ if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = true;
+ realout = TMPOUTNAME;
+ chmod(TMPOUTNAME, filemode);
+ } else
+ chmod(outname, filemode);
+
+ /*
+ * remove_file is a per-patch flag indicating
+ * whether it's OK to remove the empty file.
+ * This is specifically set when we're reversing
+ * the creation of a file and it ends up empty.
+ * This is an exception to the global policy
+ * (remove_empty_files) because the user would
+ * likely not expect the reverse of file
+ * creation to leave an empty file laying
+ * around.
+ */
+ if ((remove_empty_files || remove_file) &&
+ stat(realout, &statbuf) == 0 &&
+ statbuf.st_size == 0) {
+ if (verbose)
+ say("Removing %s (empty after patching).\n",
+ realout);
+ unlink(realout);
+ }
+ }
+ }
+ if (ferror(rejfp) || fclose(rejfp)) {
+ say("Error writing %s\n", rejname);
+ error = 1;
+ }
+ rejfp = NULL;
+ if (failed) {
+ error = 1;
+ if (*rejname == '\0') {
+ if (strlcpy(rejname, outname,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("filename %s is too long\n", outname);
+ if (strlcat(rejname, REJEXT,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("filename %s is too long\n", outname);
+ }
+ if (!check_only)
+ say("%d out of %d hunks %s--saving rejects to %s\n",
+ failed, hunk, skip_rest_of_patch ? "ignored" : "failed", rejname);
+ else if (filearg[0] != NULL)
+ say("%d out of %d hunks %s while patching %s\n",
+ failed, hunk, skip_rest_of_patch ? "ignored" : "failed", filearg[0]);
+ else
+ /* File prompt ignored, just note # hunks. */
+ say("%d out of %d hunks %s\n",
+ failed, hunk, skip_rest_of_patch ? "ignored" : "failed");
+ if (!check_only && move_file(TMPREJNAME, rejname) < 0)
+ trejkeep = true;
+ }
+ set_signals(1);
+ }
+
+ if (!patch_seen && nonempty_patchf_seen)
+ error = 2;
+
+ my_exit(error);
+ /* NOTREACHED */
+}
+
+/* Prepare to find the next patch to do in the patch file. */
+
+static void
+reinitialize_almost_everything(void)
+{
+ re_patch();
+ re_input();
+
+ input_lines = 0;
+ last_frozen_line = 0;
+
+ filec = 0;
+ if (!out_of_mem) {
+ free(filearg[0]);
+ filearg[0] = NULL;
+ }
+
+ free(source_file);
+ source_file = NULL;
+
+ free(outname);
+ outname = NULL;
+
+ last_offset = 0;
+ diff_type = 0;
+
+ free(revision);
+ revision = NULL;
+
+ reverse = reverse_flag_specified;
+ skip_rest_of_patch = false;
+
+ get_some_switches();
+}
+
+/* Process switches and filenames. */
+
+static void
+get_some_switches(void)
+{
+ const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
+ static struct option longopts[] = {
+ {"backup", no_argument, 0, 'b'},
+ {"batch", no_argument, 0, 't'},
+ {"check", no_argument, 0, 'C'},
+ {"context", no_argument, 0, 'c'},
+ {"debug", required_argument, 0, 'x'},
+ {"directory", required_argument, 0, 'd'},
+ {"dry-run", no_argument, 0, 'C'},
+ {"ed", no_argument, 0, 'e'},
+ {"force", no_argument, 0, 'f'},
+ {"forward", no_argument, 0, 'N'},
+ {"fuzz", required_argument, 0, 'F'},
+ {"ifdef", required_argument, 0, 'D'},
+ {"input", required_argument, 0, 'i'},
+ {"ignore-whitespace", no_argument, 0, 'l'},
+ {"normal", no_argument, 0, 'n'},
+ {"output", required_argument, 0, 'o'},
+ {"prefix", required_argument, 0, 'B'},
+ {"quiet", no_argument, 0, 's'},
+ {"reject-file", required_argument, 0, 'r'},
+ {"remove-empty-files", no_argument, 0, 'E'},
+ {"reverse", no_argument, 0, 'R'},
+ {"silent", no_argument, 0, 's'},
+ {"strip", required_argument, 0, 'p'},
+ {"suffix", required_argument, 0, 'z'},
+ {"unified", no_argument, 0, 'u'},
+ {"version", no_argument, 0, 'v'},
+ {"version-control", required_argument, 0, 'V'},
+ {"posix", no_argument, &posix, 1},
+ {NULL, 0, 0, 0}
+ };
+ int ch;
+
+ rejname[0] = '\0';
+ Argc_last = Argc;
+ Argv_last = Argv;
+ if (!Argc)
+ return;
+ optreset = optind = 1;
+ while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'b':
+ if (backup_type == none)
+ backup_type = numbered_existing;
+ if (optarg == NULL)
+ break;
+ if (verbose)
+ say("Warning, the ``-b suffix'' option has been"
+ " obsoleted by the -z option.\n");
+ /* FALLTHROUGH */
+ case 'z':
+ /* must directly follow 'b' case for backwards compat */
+ simple_backup_suffix = xstrdup(optarg);
+ break;
+ case 'B':
+ origprae = xstrdup(optarg);
+ break;
+ case 'c':
+ diff_type = CONTEXT_DIFF;
+ break;
+ case 'C':
+ check_only = true;
+ break;
+ case 'd':
+ if (chdir(optarg) < 0)
+ pfatal("can't cd to %s", optarg);
+ break;
+ case 'D':
+ do_defines = true;
+ if (!isalpha((unsigned char)*optarg) && *optarg != '_')
+ fatal("argument to -D is not an identifier\n");
+ snprintf(if_defined, sizeof if_defined,
+ "#ifdef %s\n", optarg);
+ snprintf(not_defined, sizeof not_defined,
+ "#ifndef %s\n", optarg);
+ snprintf(end_defined, sizeof end_defined,
+ "#endif /* %s */\n", optarg);
+ break;
+ case 'e':
+ diff_type = ED_DIFF;
+ break;
+ case 'E':
+ remove_empty_files = true;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'F':
+ maxfuzz = atoi(optarg);
+ break;
+ case 'i':
+ if (++filec == MAXFILEC)
+ fatal("too many file arguments\n");
+ filearg[filec] = xstrdup(optarg);
+ break;
+ case 'l':
+ canonicalize = true;
+ break;
+ case 'n':
+ diff_type = NORMAL_DIFF;
+ break;
+ case 'N':
+ noreverse = true;
+ break;
+ case 'o':
+ outname = xstrdup(optarg);
+ break;
+ case 'p':
+ strippath = atoi(optarg);
+ break;
+ case 'r':
+ if (strlcpy(rejname, optarg,
+ sizeof(rejname)) >= sizeof(rejname))
+ fatal("argument for -r is too long\n");
+ break;
+ case 'R':
+ reverse = true;
+ reverse_flag_specified = true;
+ break;
+ case 's':
+ verbose = false;
+ break;
+ case 't':
+ batch = true;
+ break;
+ case 'u':
+ diff_type = UNI_DIFF;
+ break;
+ case 'v':
+ version();
+ break;
+ case 'V':
+ backup_type = get_version(optarg);
+ Vflag = true;
+ break;
+#ifdef DEBUGGING
+ case 'x':
+ debug = atoi(optarg);
+ break;
+#endif
+ default:
+ if (ch != '\0')
+ usage();
+ break;
+ }
+ }
+ Argc -= optind;
+ Argv += optind;
+
+ if (Argc > 0) {
+ filearg[0] = xstrdup(*Argv++);
+ Argc--;
+ while (Argc > 0) {
+ if (++filec == MAXFILEC)
+ fatal("too many file arguments\n");
+ filearg[filec] = xstrdup(*Argv++);
+ Argc--;
+ }
+ }
+
+ if (getenv("POSIXLY_CORRECT") != NULL)
+ posix = 1;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"usage: patch [-bCcEeflNnRstuv] [-B backup-prefix] [-D symbol] [-d directory]\n"
+" [-F max-fuzz] [-i patchfile] [-o out-file] [-p strip-count]\n"
+" [-r rej-name] [-V t | nil | never | none] [-x number]\n"
+" [-z backup-ext] [--posix] [origfile [patchfile]]\n"
+" patch <patchfile\n");
+ my_exit(EXIT_FAILURE);
+}
+
+/*
+ * Attempt to find the right place to apply this hunk of patch.
+ */
+static LINENUM
+locate_hunk(LINENUM fuzz)
+{
+ LINENUM first_guess = pch_first() + last_offset;
+ LINENUM offset;
+ LINENUM pat_lines = pch_ptrn_lines();
+ LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1;
+ LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context();
+
+ if (pat_lines == 0) { /* null range matches always */
+ if (verbose && fuzz == 0 && (diff_type == CONTEXT_DIFF
+ || diff_type == NEW_CONTEXT_DIFF
+ || diff_type == UNI_DIFF)) {
+ say("Empty context always matches.\n");
+ }
+ if (first_guess == 0) /* empty file */
+ return 1;
+ return (first_guess);
+ }
+ if (max_neg_offset >= first_guess) /* do not try lines < 0 */
+ max_neg_offset = first_guess - 1;
+ if (first_guess <= input_lines && patch_match(first_guess, 0, fuzz))
+ return first_guess;
+ for (offset = 1; ; offset++) {
+ bool check_after = (offset <= max_pos_offset);
+ bool check_before = (offset <= max_neg_offset);
+
+ if (check_after && patch_match(first_guess, offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say("Offset changing from %ld to %ld\n",
+ last_offset, offset);
+#endif
+ last_offset = offset;
+ return first_guess + offset;
+ } else if (check_before && patch_match(first_guess, -offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say("Offset changing from %ld to %ld\n",
+ last_offset, -offset);
+#endif
+ last_offset = -offset;
+ return first_guess - offset;
+ } else if (!check_before && !check_after)
+ return 0;
+ }
+}
+
+/* We did not find the pattern, dump out the hunk so they can handle it. */
+
+static void
+abort_context_hunk(void)
+{
+ LINENUM i;
+ const LINENUM pat_end = pch_end();
+ /*
+ * add in last_offset to guess the same as the previous successful
+ * hunk
+ */
+ const LINENUM oldfirst = pch_first() + last_offset;
+ const LINENUM newfirst = pch_newfirst() + last_offset;
+ const LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
+ const LINENUM newlast = newfirst + pch_repl_lines() - 1;
+ const char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
+ const char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
+
+ fprintf(rejfp, "***************\n");
+ for (i = 0; i <= pat_end; i++) {
+ switch (pch_char(i)) {
+ case '*':
+ if (oldlast < oldfirst)
+ fprintf(rejfp, "*** 0%s\n", stars);
+ else if (oldlast == oldfirst)
+ fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+ else
+ fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst,
+ oldlast, stars);
+ break;
+ case '=':
+ if (newlast < newfirst)
+ fprintf(rejfp, "--- 0%s\n", minuses);
+ else if (newlast == newfirst)
+ fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+ else
+ fprintf(rejfp, "--- %ld,%ld%s\n", newfirst,
+ newlast, minuses);
+ break;
+ case '\n':
+ fprintf(rejfp, "%s", pfetch(i));
+ break;
+ case ' ':
+ case '-':
+ case '+':
+ case '!':
+ fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
+ break;
+ default:
+ fatal("fatal internal error in abort_context_hunk\n");
+ }
+ }
+}
+
+static void
+rej_line(int ch, LINENUM i)
+{
+ size_t len;
+ const char *line = pfetch(i);
+
+ len = strlen(line);
+
+ fprintf(rejfp, "%c%s", ch, line);
+ if (len == 0 || line[len - 1] != '\n') {
+ if (len >= USHRT_MAX)
+ fprintf(rejfp, "\n\\ Line too long\n");
+ else
+ fprintf(rejfp, "\n\\ No newline at end of line\n");
+ }
+}
+
+static void
+abort_hunk(void)
+{
+ LINENUM i, j, split;
+ int ch1, ch2;
+ const LINENUM pat_end = pch_end();
+ const LINENUM oldfirst = pch_first() + last_offset;
+ const LINENUM newfirst = pch_newfirst() + last_offset;
+
+ if (diff_type != UNI_DIFF) {
+ abort_context_hunk();
+ return;
+ }
+ split = -1;
+ for (i = 0; i <= pat_end; i++) {
+ if (pch_char(i) == '=') {
+ split = i;
+ break;
+ }
+ }
+ if (split == -1) {
+ fprintf(rejfp, "malformed hunk: no split found\n");
+ return;
+ }
+ i = 0;
+ j = split + 1;
+ fprintf(rejfp, "@@ -%ld,%ld +%ld,%ld @@\n",
+ pch_ptrn_lines() ? oldfirst : 0,
+ pch_ptrn_lines(), newfirst, pch_repl_lines());
+ while (i < split || j <= pat_end) {
+ ch1 = i < split ? pch_char(i) : -1;
+ ch2 = j <= pat_end ? pch_char(j) : -1;
+ if (ch1 == '-') {
+ rej_line('-', i);
+ i++;
+ } else if (ch1 == ' ' && ch2 == ' ') {
+ rej_line(' ', i);
+ i++;
+ j++;
+ } else if (ch1 == '!' && ch2 == '!') {
+ while (i < split && ch1 == '!') {
+ rej_line('-', i);
+ i++;
+ ch1 = i < split ? pch_char(i) : -1;
+ }
+ while (j <= pat_end && ch2 == '!') {
+ rej_line('+', j);
+ j++;
+ ch2 = j <= pat_end ? pch_char(j) : -1;
+ }
+ } else if (ch1 == '*') {
+ i++;
+ } else if (ch2 == '+' || ch2 == ' ') {
+ rej_line(ch2, j);
+ j++;
+ } else {
+ fprintf(rejfp, "internal error on (%ld %ld %ld)\n",
+ i, split, j);
+ rej_line(ch1, i);
+ rej_line(ch2, j);
+ return;
+ }
+ }
+}
+
+/* We found where to apply it (we hope), so do it. */
+
+static void
+apply_hunk(LINENUM where)
+{
+ LINENUM old = 1;
+ const LINENUM lastline = pch_ptrn_lines();
+ LINENUM new = lastline + 1;
+#define OUTSIDE 0
+#define IN_IFNDEF 1
+#define IN_IFDEF 2
+#define IN_ELSE 3
+ int def_state = OUTSIDE;
+ const LINENUM pat_end = pch_end();
+
+ where--;
+ while (pch_char(new) == '=' || pch_char(new) == '\n')
+ new++;
+
+ while (old <= lastline) {
+ if (pch_char(old) == '-') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ } else if (def_state == IN_IFDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ } else if (new > pat_end) {
+ break;
+ } else if (pch_char(new) == '+') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ } else if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ }
+ }
+ fputs(pfetch(new), ofp);
+ new++;
+ } else if (pch_char(new) != pch_char(old)) {
+ say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
+ pch_hunk_beg() + old,
+ pch_hunk_beg() + new);
+#ifdef DEBUGGING
+ say("oldchar = '%c', newchar = '%c'\n",
+ pch_char(old), pch_char(new));
+#endif
+ my_exit(2);
+ } else if (pch_char(new) == '!') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ }
+ while (pch_char(old) == '!') {
+ if (do_defines) {
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ }
+ if (do_defines) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ while (pch_char(new) == '!') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ } else {
+ if (pch_char(new) != ' ')
+ fatal("Internal error: expected ' '\n");
+ old++;
+ new++;
+ if (do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ def_state = OUTSIDE;
+ }
+ }
+ }
+ if (new <= pat_end && pch_char(new) == '+') {
+ copy_till(where + old - 1, false);
+ if (do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ } else if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ }
+ while (new <= pat_end && pch_char(new) == '+') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ }
+ if (do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ }
+}
+
+/*
+ * Open the new file.
+ */
+static void
+init_output(const char *name)
+{
+ ofp = fopen(name, "w");
+ if (ofp == NULL)
+ pfatal("can't create %s", name);
+}
+
+/*
+ * Open a file to put hunks we can't locate.
+ */
+static void
+init_reject(const char *name)
+{
+ rejfp = fopen(name, "w");
+ if (rejfp == NULL)
+ pfatal("can't create %s", name);
+}
+
+/*
+ * Copy input file to output, up to wherever hunk is to be applied.
+ * If endoffile is true, treat the last line specially since it may
+ * lack a newline.
+ */
+static void
+copy_till(LINENUM lastline, bool endoffile)
+{
+ if (last_frozen_line > lastline)
+ fatal("misordered hunks! output would be garbled\n");
+ while (last_frozen_line < lastline) {
+ if (++last_frozen_line == lastline && endoffile)
+ dump_line(last_frozen_line, !last_line_missing_eol);
+ else
+ dump_line(last_frozen_line, true);
+ }
+}
+
+/*
+ * Finish copying the input file to the output file.
+ */
+static bool
+spew_output(void)
+{
+ int rv;
+
+#ifdef DEBUGGING
+ if (debug & 256)
+ say("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
+#endif
+ if (input_lines)
+ copy_till(input_lines, true); /* dump remainder of file */
+ rv = ferror(ofp) == 0 && fclose(ofp) == 0;
+ ofp = NULL;
+ return rv;
+}
+
+/*
+ * Copy one line from input to output.
+ */
+static void
+dump_line(LINENUM line, bool write_newline)
+{
+ char *s;
+
+ s = ifetch(line, 0);
+ if (s == NULL)
+ return;
+ /* Note: string is not NUL terminated. */
+ for (; *s != '\n'; s++)
+ putc(*s, ofp);
+ if (write_newline)
+ putc('\n', ofp);
+}
+
+/*
+ * Does the patch pattern match at line base+offset?
+ */
+static bool
+patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
+{
+ LINENUM pline = 1 + fuzz;
+ LINENUM iline;
+ LINENUM pat_lines = pch_ptrn_lines() - fuzz;
+ const char *ilineptr;
+ const char *plineptr;
+ size_t plinelen;
+
+ /* Patch does not match if we don't have any more context to use */
+ if (pline > pat_lines)
+ return false;
+ for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
+ ilineptr = ifetch(iline, offset >= 0);
+ if (ilineptr == NULL)
+ return false;
+ plineptr = pfetch(pline);
+ plinelen = pch_line_len(pline);
+ if (canonicalize) {
+ if (!similar(ilineptr, plineptr, plinelen))
+ return false;
+ } else if (strnNE(ilineptr, plineptr, plinelen))
+ return false;
+ if (iline == input_lines) {
+ /*
+ * We are looking at the last line of the file.
+ * If the file has no eol, the patch line should
+ * not have one either and vice-versa. Note that
+ * plinelen > 0.
+ */
+ if (last_line_missing_eol) {
+ if (plineptr[plinelen - 1] == '\n')
+ return false;
+ } else {
+ if (plineptr[plinelen - 1] != '\n')
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/*
+ * Do two lines match with canonicalized white space?
+ */
+static bool
+similar(const char *a, const char *b, int len)
+{
+ while (len) {
+ if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
+ if (!isspace((unsigned char)*a)) /* no corresponding whitespace? */
+ return false;
+ while (len && isspace((unsigned char)*b) && *b != '\n')
+ b++, len--; /* skip pattern whitespace */
+ while (isspace((unsigned char)*a) && *a != '\n')
+ a++; /* skip target whitespace */
+ if (*a == '\n' || *b == '\n')
+ return (*a == *b); /* should end in sync */
+ } else if (*a++ != *b++) /* match non-whitespace chars */
+ return false;
+ else
+ len--; /* probably not necessary */
+ }
+ return true; /* actually, this is not reached */
+ /* since there is always a \n */
+}
+
+static bool
+handle_creation(bool out_existed, bool *remove)
+{
+ bool reverse_seen;
+
+ reverse_seen = false;
+ if (reverse && out_existed) {
+ /*
+ * If the patch creates the file and we're reversing the patch,
+ * then we need to indicate to the patch processor that it's OK
+ * to remove this file.
+ */
+ *remove = true;
+ } else if (!reverse && out_existed) {
+ /*
+ * Otherwise, we need to blow the horn because the patch appears
+ * to be reversed/already applied. For non-batch jobs, we'll
+ * prompt to figure out what we should be trying to do to raise
+ * awareness of the issue. batch (-t) processing suppresses the
+ * questions and just assumes that we're reversed if it looks
+ * like we are, which is always the case if we've reached this
+ * branch.
+ */
+ if (force) {
+ skip_rest_of_patch = true;
+ return (false);
+ }
+ if (noreverse) {
+ /* If -N is supplied, however, we bail out/ignore. */
+ say("Ignoring previously applied (or reversed) patch.\n");
+ skip_rest_of_patch = true;
+ return (false);
+ }
+
+ /* Unreversed... suspicious if the file existed. */
+ if (!pch_swap())
+ fatal("lost hunk on alloc error!\n");
+
+ reverse = !reverse;
+
+ if (batch) {
+ if (verbose)
+ say("Patch creates file that already exists, %s %seversed",
+ reverse ? "Assuming" : "Ignoring",
+ reverse ? "R" : "Unr");
+ } else {
+ ask("Patch creates file that already exists! %s -R? [y] ",
+ reverse ? "Assume" : "Ignore");
+
+ if (*buf == 'n') {
+ ask("Apply anyway? [n]");
+ if (*buf != 'y')
+ /* Don't apply; error out. */
+ skip_rest_of_patch = true;
+ else
+ /* Attempt to apply. */
+ reverse_seen = true;
+ reverse = !reverse;
+ if (!pch_swap())
+ fatal("lost hunk on alloc error!\n");
+ } else {
+ /*
+ * They've opted to assume -R; effectively the
+ * same as the first branch in this function,
+ * but the decision is here rather than in a
+ * prior patch/hunk as in that branch.
+ */
+ *remove = true;
+ }
+ }
+ }
+
+ /*
+ * The return value indicates if we offered a chance to reverse but the
+ * user declined. This keeps the main patch processor in the loop since
+ * we've taken this out of the normal flow of hunk processing to
+ * simplify logic a little bit.
+ */
+ return (reverse_seen);
+}
diff --git a/usr.bin/patch/pathnames.h b/usr.bin/patch/pathnames.h
new file mode 100644
index 000000000000..4d4672fd83f2
--- /dev/null
+++ b/usr.bin/patch/pathnames.h
@@ -0,0 +1,11 @@
+/*-
+ * Placed in the public domain by Todd C. Miller <Todd.Miller@courtesan.com>
+ * on July 29, 2003.
+ *
+ * $OpenBSD: pathnames.h,v 1.1 2003/07/29 20:10:17 millert Exp $
+ */
+
+
+#include <paths.h>
+
+#define _PATH_RED "/bin/red"
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
new file mode 100644
index 000000000000..71f73125a8cb
--- /dev/null
+++ b/usr.bin/patch/pch.c
@@ -0,0 +1,1662 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: pch.c,v 1.43 2014/11/18 17:03:35 tobias Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "pathnames.h"
+
+/* Patch (diff listing) abstract type. */
+
+static off_t p_filesize; /* size of the patch file */
+static LINENUM p_first; /* 1st line number */
+static LINENUM p_newfirst; /* 1st line number of replacement */
+static LINENUM p_ptrn_lines; /* # lines in pattern */
+static LINENUM p_repl_lines; /* # lines in replacement text */
+static LINENUM p_end = -1; /* last line in hunk */
+static LINENUM p_max; /* max allowed value of p_end */
+static LINENUM p_context = 3; /* # of context lines */
+static LINENUM p_input_line = 0; /* current line # from patch file */
+static char **p_line = NULL;/* the text of the hunk */
+static size_t *p_len = NULL; /* length of each line */
+static char *p_char = NULL; /* +, -, and ! */
+static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
+static int p_indent; /* indent to patch */
+static off_t p_base; /* where to intuit this time */
+static LINENUM p_bline; /* line # of p_base */
+static off_t p_start; /* where intuit found a patch */
+static LINENUM p_sline; /* and the line number for it */
+static LINENUM p_hunk_beg; /* line number of current hunk */
+static LINENUM p_efake = -1; /* end of faked up lines--don't free */
+static LINENUM p_bfake = -1; /* beg of faked up lines */
+static FILE *pfp = NULL; /* patch file pointer */
+static char *bestguess = NULL; /* guess at correct filename */
+
+char *source_file;
+
+static void grow_hunkmax(void);
+static int intuit_diff_type(void);
+static void next_intuit_at(off_t, LINENUM);
+static void skip_to(off_t, LINENUM);
+static size_t pgets(bool _do_indent);
+static char *best_name(const struct file_name *, bool);
+static char *posix_name(const struct file_name *, bool);
+static size_t num_components(const char *);
+static LINENUM strtolinenum(char *, char **);
+
+/*
+ * Prepare to look for the next patch in the patch file.
+ */
+void
+re_patch(void)
+{
+ p_first = 0;
+ p_newfirst = 0;
+ p_ptrn_lines = 0;
+ p_repl_lines = 0;
+ p_end = (LINENUM) - 1;
+ p_max = 0;
+ p_indent = 0;
+}
+
+/*
+ * Open the patch file at the beginning of time.
+ */
+void
+open_patch_file(const char *filename)
+{
+ struct stat filestat;
+ int nr, nw;
+
+ if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
+ pfp = fopen(TMPPATNAME, "w");
+ if (pfp == NULL)
+ pfatal("can't create %s", TMPPATNAME);
+ while ((nr = fread(buf, 1, buf_size, stdin)) > 0) {
+ nw = fwrite(buf, 1, nr, pfp);
+ if (nr != nw)
+ pfatal("write error to %s", TMPPATNAME);
+ }
+ if (ferror(pfp) || fclose(pfp))
+ pfatal("can't write %s", TMPPATNAME);
+ filename = TMPPATNAME;
+ }
+ pfp = fopen(filename, "r");
+ if (pfp == NULL)
+ pfatal("patch file %s not found", filename);
+ if (fstat(fileno(pfp), &filestat))
+ pfatal("can't stat %s", filename);
+ p_filesize = filestat.st_size;
+ next_intuit_at(0, 1L); /* start at the beginning */
+ set_hunkmax();
+}
+
+/*
+ * Make sure our dynamically realloced tables are malloced to begin with.
+ */
+void
+set_hunkmax(void)
+{
+ if (p_line == NULL)
+ p_line = malloc(hunkmax * sizeof(char *));
+ if (p_len == NULL)
+ p_len = malloc(hunkmax * sizeof(size_t));
+ if (p_char == NULL)
+ p_char = malloc(hunkmax * sizeof(char));
+}
+
+/*
+ * Enlarge the arrays containing the current hunk of patch.
+ */
+static void
+grow_hunkmax(void)
+{
+ int new_hunkmax = hunkmax * 2;
+
+ if (p_line == NULL || p_len == NULL || p_char == NULL)
+ fatal("Internal memory allocation error\n");
+
+ p_line = reallocf(p_line, new_hunkmax * sizeof(char *));
+ p_len = reallocf(p_len, new_hunkmax * sizeof(size_t));
+ p_char = reallocf(p_char, new_hunkmax * sizeof(char));
+
+ if (p_line != NULL && p_len != NULL && p_char != NULL) {
+ hunkmax = new_hunkmax;
+ return;
+ }
+
+ if (!using_plan_a)
+ fatal("out of memory\n");
+ out_of_mem = true; /* whatever is null will be allocated again */
+ /* from within plan_a(), of all places */
+}
+
+/* True if the remainder of the patch file contains a diff of some sort. */
+
+bool
+there_is_another_patch(void)
+{
+ bool exists = false;
+
+ if (p_base != 0 && p_base >= p_filesize) {
+ if (verbose)
+ say("done\n");
+ return false;
+ }
+ if (p_filesize == 0)
+ return false;
+ nonempty_patchf_seen = true;
+ if (verbose)
+ say("Hmm...");
+ diff_type = intuit_diff_type();
+ if (!diff_type) {
+ if (p_base != 0) {
+ if (verbose)
+ say(" Ignoring the trailing garbage.\ndone\n");
+ } else
+ say(" I can't seem to find a patch in there anywhere.\n");
+ return false;
+ }
+ if (verbose)
+ say(" %sooks like %s to me...\n",
+ (p_base == 0 ? "L" : "The next patch l"),
+ diff_type == UNI_DIFF ? "a unified diff" :
+ diff_type == CONTEXT_DIFF ? "a context diff" :
+ diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
+ diff_type == NORMAL_DIFF ? "a normal diff" :
+ "an ed script");
+ if (p_indent && verbose)
+ say("(Patch is indented %d space%s.)\n", p_indent,
+ p_indent == 1 ? "" : "s");
+ skip_to(p_start, p_sline);
+ while (filearg[0] == NULL) {
+ if (force || batch) {
+ say("No file to patch. Skipping...\n");
+ filearg[0] = xstrdup(bestguess);
+ skip_rest_of_patch = true;
+ return true;
+ }
+ ask("File to patch: ");
+ if (*buf != '\n') {
+ free(bestguess);
+ bestguess = xstrdup(buf);
+ filearg[0] = fetchname(buf, &exists, 0);
+ }
+ /*
+ * fetchname can now return buf = NULL, exists = true, to
+ * indicate to the caller that /dev/null was specified. Retain
+ * previous behavior for now until this can be better evaluted.
+ */
+ if (filearg[0] == NULL || !exists) {
+ int def_skip = *bestguess == '\0';
+ ask("No file found--skip this patch? [%c] ",
+ def_skip ? 'y' : 'n');
+ if (*buf == 'n' || (!def_skip && *buf != 'y'))
+ continue;
+ if (verbose)
+ say("Skipping patch...\n");
+ free(filearg[0]);
+ filearg[0] = fetchname(bestguess, &exists, 0);
+ skip_rest_of_patch = true;
+ return true;
+ }
+ }
+ return true;
+}
+
+static void
+p4_fetchname(struct file_name *name, char *str)
+{
+ char *t, *h;
+
+ /* Skip leading whitespace. */
+ while (isspace((unsigned char)*str))
+ str++;
+
+ /* Remove the file revision number. */
+ for (t = str, h = NULL; *t != '\0' && !isspace((unsigned char)*t); t++)
+ if (*t == '#')
+ h = t;
+ if (h != NULL)
+ *h = '\0';
+
+ name->path = fetchname(str, &name->exists, strippath);
+}
+
+/* Determine what kind of diff is in the remaining part of the patch file. */
+
+static int
+intuit_diff_type(void)
+{
+ off_t this_line = 0, previous_line;
+ off_t first_command_line = -1;
+ LINENUM fcl_line = -1;
+ bool last_line_was_command = false, this_is_a_command = false;
+ bool stars_last_line = false, stars_this_line = false;
+ char *s, *t;
+ int indent, retval;
+ struct file_name names[MAX_FILE];
+ int piece_of_git = 0;
+
+ memset(names, 0, sizeof(names));
+ ok_to_create_file = false;
+ fseeko(pfp, p_base, SEEK_SET);
+ p_input_line = p_bline - 1;
+ for (;;) {
+ previous_line = this_line;
+ last_line_was_command = this_is_a_command;
+ stars_last_line = stars_this_line;
+ this_line = ftello(pfp);
+ indent = 0;
+ p_input_line++;
+ if (pgets(false) == 0) {
+ if (first_command_line >= 0) {
+ /* nothing but deletes!? */
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ } else {
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = 0;
+ goto scan_exit;
+ }
+ }
+ for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
+ if (*s == '\t')
+ indent += 8 - (indent % 8);
+ else
+ indent++;
+ }
+ for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ this_is_a_command = (isdigit((unsigned char)*s) &&
+ (*t == 'd' || *t == 'c' || *t == 'a'));
+ if (first_command_line < 0 && this_is_a_command) {
+ first_command_line = this_line;
+ fcl_line = p_input_line;
+ p_indent = indent; /* assume this for now */
+ }
+ if (!stars_last_line && strnEQ(s, "*** ", 4))
+ names[OLD_FILE].path = fetchname(s + 4,
+ &names[OLD_FILE].exists, strippath);
+ else if (strnEQ(s, "--- ", 4)) {
+ size_t off = 4;
+ if (piece_of_git && strippath == 957 &&
+ strnEQ(s, "--- a/", 6))
+ off = 6;
+ names[NEW_FILE].path = fetchname(s + off,
+ &names[NEW_FILE].exists, strippath);
+ } else if (strnEQ(s, "+++ ", 4)) {
+ /* pretend it is the old name */
+ size_t off = 4;
+ if (piece_of_git && strippath == 957 &&
+ strnEQ(s, "+++ b/", 6))
+ off = 6;
+ names[OLD_FILE].path = fetchname(s + off,
+ &names[OLD_FILE].exists, strippath);
+ } else if (strnEQ(s, "Index:", 6))
+ names[INDEX_FILE].path = fetchname(s + 6,
+ &names[INDEX_FILE].exists, strippath);
+ else if (strnEQ(s, "Prereq:", 7)) {
+ for (t = s + 7; isspace((unsigned char)*t); t++)
+ ;
+ revision = xstrdup(t);
+ for (t = revision;
+ *t && !isspace((unsigned char)*t); t++)
+ ;
+ *t = '\0';
+ if (*revision == '\0') {
+ free(revision);
+ revision = NULL;
+ }
+ } else if (strnEQ(s, "diff --git a/", 13)) {
+ /* Git-style diffs. */
+ piece_of_git = 1;
+ } else if (strnEQ(s, "==== ", 5)) {
+ /* Perforce-style diffs. */
+ if ((t = strstr(s + 5, " - ")) != NULL)
+ p4_fetchname(&names[NEW_FILE], t + 3);
+ p4_fetchname(&names[OLD_FILE], s + 5);
+ }
+ if ((!diff_type || diff_type == ED_DIFF) &&
+ first_command_line >= 0 &&
+ strEQ(s, ".\n")) {
+ p_indent = indent;
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
+ if (strnEQ(s + 4, "0,0", 3))
+ ok_to_create_file = true;
+ p_indent = indent;
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = UNI_DIFF;
+ goto scan_exit;
+ }
+ stars_this_line = strnEQ(s, "********", 8);
+ if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
+ strnEQ(s, "*** ", 4)) {
+ if (strtolinenum(s + 4, &s) == 0)
+ ok_to_create_file = true;
+ /*
+ * If this is a new context diff the character just
+ * at the end of the line is a '*'.
+ */
+ while (*s && *s != '\n')
+ s++;
+ p_indent = indent;
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == NORMAL_DIFF) &&
+ last_line_was_command &&
+ (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ p_indent = indent;
+ retval = NORMAL_DIFF;
+ goto scan_exit;
+ }
+ }
+scan_exit:
+ if (retval == UNI_DIFF) {
+ /* unswap old and new */
+ struct file_name tmp = names[OLD_FILE];
+ names[OLD_FILE] = names[NEW_FILE];
+ names[NEW_FILE] = tmp;
+ }
+
+ /* Invalidated */
+ free(source_file);
+ source_file = NULL;
+
+ if (retval != 0) {
+ /*
+ * If we've successfully determined a diff type, stored in
+ * retval, path == NULL means _PATH_DEVNULL if exists is set.
+ * Explicitly specify it here to make it easier to detect later
+ * on that we're actually creating a file and not that we've
+ * just goofed something up.
+ */
+ if (names[OLD_FILE].path != NULL)
+ source_file = xstrdup(names[OLD_FILE].path);
+ else if (names[OLD_FILE].exists)
+ source_file = xstrdup(_PATH_DEVNULL);
+ }
+ if (filearg[0] == NULL) {
+ if (posix)
+ filearg[0] = posix_name(names, ok_to_create_file);
+ else {
+ /* Ignore the Index: name for context diffs, like GNU */
+ if (names[OLD_FILE].path != NULL ||
+ names[NEW_FILE].path != NULL) {
+ free(names[INDEX_FILE].path);
+ names[INDEX_FILE].path = NULL;
+ }
+ filearg[0] = best_name(names, ok_to_create_file);
+ }
+ }
+
+ free(bestguess);
+ bestguess = NULL;
+ if (filearg[0] != NULL)
+ bestguess = xstrdup(filearg[0]);
+ else if (!ok_to_create_file) {
+ /*
+ * We don't want to create a new file but we need a
+ * filename to set bestguess. Avoid setting filearg[0]
+ * so the file is not created automatically.
+ */
+ if (posix)
+ bestguess = posix_name(names, true);
+ else
+ bestguess = best_name(names, true);
+ }
+ free(names[OLD_FILE].path);
+ free(names[NEW_FILE].path);
+ free(names[INDEX_FILE].path);
+ return retval;
+}
+
+/*
+ * Remember where this patch ends so we know where to start up again.
+ */
+static void
+next_intuit_at(off_t file_pos, LINENUM file_line)
+{
+ p_base = file_pos;
+ p_bline = file_line;
+}
+
+/*
+ * Basically a verbose fseeko() to the actual diff listing.
+ */
+static void
+skip_to(off_t file_pos, LINENUM file_line)
+{
+ size_t len;
+
+ if (p_base > file_pos)
+ fatal("Internal error: seek %lld>%lld\n",
+ (long long)p_base, (long long)file_pos);
+ if (verbose && p_base < file_pos) {
+ fseeko(pfp, p_base, SEEK_SET);
+ say("The text leading up to this was:\n--------------------------\n");
+ while (ftello(pfp) < file_pos) {
+ len = pgets(false);
+ if (len == 0)
+ fatal("Unexpected end of file\n");
+ say("|%s", buf);
+ }
+ say("--------------------------\n");
+ } else
+ fseeko(pfp, file_pos, SEEK_SET);
+ p_input_line = file_line - 1;
+}
+
+/* Make this a function for better debugging. */
+static void
+malformed(void)
+{
+ fatal("malformed patch at line %ld: %s", p_input_line, buf);
+ /* about as informative as "Syntax error" in C */
+}
+
+/*
+ * True if the line has been discarded (i.e. it is a line saying
+ * "\ No newline at end of file".)
+ */
+static bool
+remove_special_line(void)
+{
+ int c;
+
+ c = fgetc(pfp);
+ if (c == '\\') {
+ do {
+ c = fgetc(pfp);
+ } while (c != EOF && c != '\n');
+
+ return true;
+ }
+ if (c != EOF)
+ fseeko(pfp, -1, SEEK_CUR);
+
+ return false;
+}
+
+/*
+ * True if there is more of the current diff listing to process.
+ */
+bool
+another_hunk(void)
+{
+ off_t line_beginning; /* file pos of the current line */
+ LINENUM repl_beginning; /* index of --- line */
+ LINENUM fillcnt; /* #lines of missing ptrn or repl */
+ LINENUM fillsrc; /* index of first line to copy */
+ LINENUM filldst; /* index of first missing line */
+ bool ptrn_spaces_eaten; /* ptrn was slightly malformed */
+ bool repl_could_be_missing; /* no + or ! lines in this hunk */
+ bool repl_missing; /* we are now backtracking */
+ off_t repl_backtrack_position; /* file pos of first repl line */
+ LINENUM repl_patch_line; /* input line number for same */
+ LINENUM ptrn_copiable; /* # of copiable lines in ptrn */
+ char *s;
+ size_t len;
+ int context = 0;
+
+ while (p_end >= 0) {
+ if (p_end == p_efake)
+ p_end = p_bfake; /* don't free twice */
+ else
+ free(p_line[p_end]);
+ p_end--;
+ }
+ p_efake = -1;
+
+ p_max = hunkmax; /* gets reduced when --- found */
+ if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
+ line_beginning = ftello(pfp);
+ repl_beginning = 0;
+ fillcnt = 0;
+ fillsrc = 0;
+ filldst = 0;
+ ptrn_spaces_eaten = false;
+ repl_could_be_missing = true;
+ repl_missing = false;
+ repl_backtrack_position = 0;
+ repl_patch_line = 0;
+ ptrn_copiable = 0;
+
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || strnNE(buf, "********", 8)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ p_context = 100;
+ p_hunk_beg = p_input_line + 1;
+ while (p_end < p_max) {
+ line_beginning = ftello(pfp);
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("unexpected end of file in patch\n");
+ }
+ p_end++;
+ if (p_end >= hunkmax)
+ fatal("Internal error: hunk larger than hunk "
+ "buffer size");
+ p_char[p_end] = *buf;
+ p_line[p_end] = NULL;
+ switch (*buf) {
+ case '*':
+ if (strnEQ(buf, "********", 8)) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ } else
+ fatal("unexpected end of hunk "
+ "at line %ld\n",
+ p_input_line);
+ }
+ if (p_end != 0) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("unexpected *** at line %ld: %s",
+ p_input_line, buf);
+ }
+ context = 0;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ for (s = buf;
+ *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ if (strnEQ(s, "0,0", 3))
+ memmove(s, s + 2, strlen(s + 2) + 1);
+ p_first = strtolinenum(s, &s);
+ if (*s == ',') {
+ for (;
+ *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_ptrn_lines = strtolinenum(s, &s) - p_first + 1;
+ if (p_ptrn_lines < 0)
+ malformed();
+ } else if (p_first)
+ p_ptrn_lines = 1;
+ else {
+ p_ptrn_lines = 0;
+ p_first = 1;
+ }
+ if (p_first >= LINENUM_MAX - p_ptrn_lines ||
+ p_ptrn_lines >= LINENUM_MAX - 6)
+ malformed();
+
+ /* we need this much at least */
+ p_max = p_ptrn_lines + 6;
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ p_max = hunkmax;
+ break;
+ case '-':
+ if (buf[1] == '-') {
+ if (repl_beginning ||
+ (p_end != p_ptrn_lines + 1 +
+ (p_char[p_end - 1] == '\n'))) {
+ if (p_end == 1) {
+ /*
+ * `old' lines were omitted;
+ * set up to fill them in
+ * from 'new' context lines.
+ */
+ p_end = p_ptrn_lines + 1;
+ fillsrc = p_end + 1;
+ filldst = 1;
+ fillcnt = p_ptrn_lines;
+ } else {
+ if (repl_beginning) {
+ if (repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n",
+ p_input_line, p_hunk_beg + repl_beginning);
+ } else {
+ fatal("%s \"---\" at line %ld--check line numbers at line %ld\n",
+ (p_end <= p_ptrn_lines
+ ? "Premature"
+ : "Overdue"),
+ p_input_line, p_hunk_beg);
+ }
+ }
+ }
+ repl_beginning = p_end;
+ repl_backtrack_position = ftello(pfp);
+ repl_patch_line = p_input_line;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ p_char[p_end] = '=';
+ for (s = buf; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_newfirst = strtolinenum(s, &s);
+ if (*s == ',') {
+ for (; *s && !isdigit((unsigned char)*s); s++)
+ ;
+ if (!*s)
+ malformed();
+ p_repl_lines = strtolinenum(s, &s) -
+ p_newfirst + 1;
+ if (p_repl_lines < 0)
+ malformed();
+ } else if (p_newfirst)
+ p_repl_lines = 1;
+ else {
+ p_repl_lines = 0;
+ p_newfirst = 1;
+ }
+ if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
+ p_repl_lines >= LINENUM_MAX - p_end)
+ malformed();
+ p_max = p_repl_lines + p_end;
+ if (p_max > MAXHUNKSIZE)
+ fatal("hunk too large (%ld lines) at line %ld: %s",
+ p_max, p_input_line, buf);
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ if (p_repl_lines != ptrn_copiable &&
+ (p_context != 0 || p_repl_lines != 1))
+ repl_could_be_missing = false;
+ break;
+ }
+ goto change_line;
+ case '+':
+ case '!':
+ repl_could_be_missing = false;
+ change_line:
+ if (buf[1] == '\n' && canonicalize)
+ strlcpy(buf + 1, " \n", buf_size - 1);
+ if (!isspace((unsigned char)buf[1]) &&
+ buf[1] != '>' && buf[1] != '<' &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ if (context >= 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ p_line[p_end] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ if (p_end == p_ptrn_lines) {
+ if (remove_special_line()) {
+ int l;
+
+ l = strlen(p_line[p_end]) - 1;
+ (p_line[p_end])[l] = 0;
+ }
+ }
+ break;
+ case '\t':
+ case '\n': /* assume the 2 spaces got eaten */
+ if (repl_beginning && repl_could_be_missing &&
+ (!ptrn_spaces_eaten ||
+ diff_type == NEW_CONTEXT_DIFF)) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ if (p_end != p_ptrn_lines + 1) {
+ ptrn_spaces_eaten |= (repl_beginning != 0);
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_char[p_end] = ' ';
+ }
+ break;
+ case ' ':
+ if (!isspace((unsigned char)buf[1]) &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_line[p_end] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end--;
+ return false;
+ }
+ break;
+ default:
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = true;
+ goto hunk_done;
+ }
+ malformed();
+ }
+ /* set up p_len for strncmp() so we don't have to */
+ /* assume null termination */
+ if (p_line[p_end])
+ p_len[p_end] = strlen(p_line[p_end]);
+ else
+ p_len[p_end] = 0;
+ }
+
+hunk_done:
+ if (p_end >= 0 && !repl_beginning)
+ fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
+
+ if (repl_missing) {
+
+ /* reset state back to just after --- */
+ p_input_line = repl_patch_line;
+ for (p_end--; p_end > repl_beginning; p_end--)
+ free(p_line[p_end]);
+ fseeko(pfp, repl_backtrack_position, SEEK_SET);
+
+ /* redundant 'new' context lines were omitted - set */
+ /* up to fill them in from the old file context */
+ if (!p_context && p_repl_lines == 1) {
+ p_repl_lines = 0;
+ p_max--;
+ }
+ fillsrc = 1;
+ filldst = repl_beginning + 1;
+ fillcnt = p_repl_lines;
+ p_end = p_max;
+ } else if (!p_context && fillcnt == 1) {
+ /* the first hunk was a null hunk with no context */
+ /* and we were expecting one line -- fix it up. */
+ while (filldst < p_end) {
+ p_line[filldst] = p_line[filldst + 1];
+ p_char[filldst] = p_char[filldst + 1];
+ p_len[filldst] = p_len[filldst + 1];
+ filldst++;
+ }
+#if 0
+ repl_beginning--; /* this doesn't need to be fixed */
+#endif
+ p_end--;
+ p_first++; /* do append rather than insert */
+ fillcnt = 0;
+ p_ptrn_lines = 0;
+ }
+ if (diff_type == CONTEXT_DIFF &&
+ (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
+ if (verbose)
+ say("%s\n%s\n%s\n",
+ "(Fascinating--this is really a new-style context diff but without",
+ "the telltale extra asterisks on the *** line that usually indicate",
+ "the new style...)");
+ diff_type = NEW_CONTEXT_DIFF;
+ }
+ /* if there were omitted context lines, fill them in now */
+ if (fillcnt) {
+ p_bfake = filldst; /* remember where not to free() */
+ p_efake = filldst + fillcnt - 1;
+ while (fillcnt-- > 0) {
+ while (fillsrc <= p_end && p_char[fillsrc] != ' ')
+ fillsrc++;
+ if (fillsrc > p_end)
+ fatal("replacement text or line numbers mangled in hunk at line %ld\n",
+ p_hunk_beg);
+ p_line[filldst] = p_line[fillsrc];
+ p_char[filldst] = p_char[fillsrc];
+ p_len[filldst] = p_len[fillsrc];
+ fillsrc++;
+ filldst++;
+ }
+ while (fillsrc <= p_end && fillsrc != repl_beginning &&
+ p_char[fillsrc] != ' ')
+ fillsrc++;
+#ifdef DEBUGGING
+ if (debug & 64)
+ printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
+ fillsrc, filldst, repl_beginning, p_end + 1);
+#endif
+ if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
+ malformed();
+ if (filldst != p_end + 1 && filldst != repl_beginning)
+ malformed();
+ }
+ if (p_line[p_end] != NULL) {
+ if (remove_special_line()) {
+ p_len[p_end] -= 1;
+ (p_line[p_end])[p_len[p_end]] = 0;
+ }
+ }
+ } else if (diff_type == UNI_DIFF) {
+ LINENUM fillold; /* index of old lines */
+ LINENUM fillnew; /* index of new lines */
+ char ch;
+
+ line_beginning = ftello(pfp); /* file pos of the current line */
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || strnNE(buf, "@@ -", 4)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ s = buf + 4;
+ if (!*s)
+ malformed();
+ p_first = strtolinenum(s, &s);
+ if (*s == ',') {
+ p_ptrn_lines = strtolinenum(s + 1, &s);
+ } else
+ p_ptrn_lines = 1;
+ if (*s == ' ')
+ s++;
+ if (*s != '+' || !*++s)
+ malformed();
+ p_newfirst = strtolinenum(s, &s);
+ if (*s == ',') {
+ p_repl_lines = strtolinenum(s + 1, &s);
+ } else
+ p_repl_lines = 1;
+ if (*s == ' ')
+ s++;
+ if (*s != '@')
+ malformed();
+ if (p_first >= LINENUM_MAX - p_ptrn_lines ||
+ p_newfirst > LINENUM_MAX - p_repl_lines ||
+ p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
+ malformed();
+ if (!p_ptrn_lines)
+ p_first++; /* do append rather than insert */
+ p_max = p_ptrn_lines + p_repl_lines + 1;
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ fillold = 1;
+ fillnew = fillold + p_ptrn_lines;
+ p_end = fillnew + p_repl_lines;
+ snprintf(buf, buf_size, "*** %ld,%ld ****\n", p_first,
+ p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return false;
+ }
+ p_char[0] = '*';
+ snprintf(buf, buf_size, "--- %ld,%ld ----\n", p_newfirst,
+ p_newfirst + p_repl_lines - 1);
+ p_line[fillnew] = savestr(buf);
+ if (out_of_mem) {
+ p_end = 0;
+ return false;
+ }
+ p_char[fillnew++] = '=';
+ p_context = 100;
+ context = 0;
+ p_hunk_beg = p_input_line + 1;
+ while (fillold <= p_ptrn_lines || fillnew <= p_end) {
+ line_beginning = ftello(pfp);
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0) {
+ if (p_max - fillnew < 3) {
+ /* assume blank lines got chopped */
+ strlcpy(buf, " \n", buf_size);
+ } else {
+ fatal("unexpected end of file in patch\n");
+ }
+ }
+ if (*buf == '\t' || *buf == '\n') {
+ ch = ' '; /* assume the space got eaten */
+ s = savestr(buf);
+ } else {
+ ch = *buf;
+ s = savestr(buf + 1);
+ }
+ if (out_of_mem) {
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ return false;
+ }
+ switch (ch) {
+ case '-':
+ if (fillold > p_ptrn_lines) {
+ free(s);
+ p_end = fillnew - 1;
+ malformed();
+ }
+ p_char[fillold] = ch;
+ p_line[fillold] = s;
+ p_len[fillold++] = strlen(s);
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillold - 1] -= 1;
+ s[p_len[fillold - 1]] = 0;
+ }
+ }
+ break;
+ case '=':
+ ch = ' ';
+ /* FALL THROUGH */
+ case ' ':
+ if (fillold > p_ptrn_lines) {
+ free(s);
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ malformed();
+ }
+ context++;
+ p_char[fillold] = ch;
+ p_line[fillold] = s;
+ p_len[fillold++] = strlen(s);
+ s = savestr(s);
+ if (out_of_mem) {
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ return false;
+ }
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillold - 1] -= 1;
+ s[p_len[fillold - 1]] = 0;
+ }
+ }
+ /* FALL THROUGH */
+ case '+':
+ if (fillnew > p_end) {
+ free(s);
+ while (--fillnew > p_ptrn_lines)
+ free(p_line[fillnew]);
+ p_end = fillold - 1;
+ malformed();
+ }
+ p_char[fillnew] = ch;
+ p_line[fillnew] = s;
+ p_len[fillnew++] = strlen(s);
+ if (fillold > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillnew - 1] -= 1;
+ s[p_len[fillnew - 1]] = 0;
+ }
+ }
+ break;
+ default:
+ p_end = fillnew;
+ malformed();
+ }
+ if (ch != ' ' && context > 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ } /* while */
+ } else { /* normal diff--fake it up */
+ char hunk_type;
+ int i;
+ LINENUM min, max;
+
+ line_beginning = ftello(pfp);
+ p_context = 0;
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0 || !isdigit((unsigned char)*buf)) {
+ next_intuit_at(line_beginning, p_input_line);
+ return false;
+ }
+ p_first = strtolinenum(buf, &s);
+ if (*s == ',') {
+ p_ptrn_lines = strtolinenum(s + 1, &s) - p_first + 1;
+ if (p_ptrn_lines < 0)
+ malformed();
+ } else
+ p_ptrn_lines = (*s != 'a');
+ hunk_type = *s;
+ if (hunk_type == 'a')
+ p_first++; /* do append rather than insert */
+ min = strtolinenum(s + 1, &s);
+ if (*s == ',')
+ max = strtolinenum(s + 1, &s);
+ else
+ max = min;
+ if (min < 0 || min > max || max - min == LINENUM_MAX)
+ malformed();
+ if (hunk_type == 'd')
+ min++;
+ p_newfirst = min;
+ p_repl_lines = max - min + 1;
+ if (p_newfirst > LINENUM_MAX - p_repl_lines ||
+ p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
+ malformed();
+ p_end = p_ptrn_lines + p_repl_lines + 1;
+ if (p_end > MAXHUNKSIZE)
+ fatal("hunk too large (%ld lines) at line %ld: %s",
+ p_end, p_input_line, buf);
+ while (p_end >= hunkmax)
+ grow_hunkmax();
+ snprintf(buf, buf_size, "*** %ld,%ld\n", p_first,
+ p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return false;
+ }
+ p_char[0] = '*';
+ for (i = 1; i <= p_ptrn_lines; i++) {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '<')
+ fatal("< expected at line %ld of patch\n",
+ p_input_line);
+ p_line[i] = savestr(buf + 2);
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_char[i] = '-';
+ }
+
+ if (remove_special_line()) {
+ p_len[i - 1] -= 1;
+ (p_line[i - 1])[p_len[i - 1]] = 0;
+ }
+ if (hunk_type == 'c') {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '-')
+ fatal("--- expected at line %ld of patch\n",
+ p_input_line);
+ }
+ snprintf(buf, buf_size, "--- %ld,%ld\n", min, max);
+ p_line[i] = savestr(buf);
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_char[i] = '=';
+ for (i++; i <= p_end; i++) {
+ len = pgets(true);
+ p_input_line++;
+ if (len == 0)
+ fatal("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '>')
+ fatal("> expected at line %ld of patch\n",
+ p_input_line);
+ /* Don't overrun if we don't have enough line */
+ if (len > 2)
+ p_line[i] = savestr(buf + 2);
+ else
+ p_line[i] = savestr("");
+
+ if (out_of_mem) {
+ p_end = i - 1;
+ return false;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_char[i] = '+';
+ }
+
+ if (remove_special_line()) {
+ p_len[i - 1] -= 1;
+ (p_line[i - 1])[p_len[i - 1]] = 0;
+ }
+ }
+ if (reverse) /* backwards patch? */
+ if (!pch_swap())
+ say("Not enough memory to swap next hunk!\n");
+#ifdef DEBUGGING
+ if (debug & 2) {
+ LINENUM i;
+ char special;
+
+ for (i = 0; i <= p_end; i++) {
+ if (i == p_ptrn_lines)
+ special = '^';
+ else
+ special = ' ';
+ fprintf(stderr, "%3ld %c %c %s", i, p_char[i],
+ special, p_line[i]);
+ fflush(stderr);
+ }
+ }
+#endif
+ if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */
+ p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
+ return true;
+}
+
+/*
+ * Input a line from the patch file.
+ * Worry about indentation if do_indent is true.
+ * The line is read directly into the buf global variable which
+ * is resized if necessary in order to hold the complete line.
+ * Returns the number of characters read including the terminating
+ * '\n', if any.
+ */
+size_t
+pgets(bool do_indent)
+{
+ char *line = NULL;
+ ssize_t len = 0;
+ size_t buflen = 0;
+ int indent = 0, skipped = 0;
+
+ if ((len = getline(&line, &buflen, pfp)) >= 0) {
+ char *linep = line;
+ if ((size_t)(len + 1) > buf_size) {
+ while ((size_t)(len + 1) > buf_size)
+ buf_size *= 2;
+ free(buf);
+ buf = malloc(buf_size);
+ if (buf == NULL)
+ fatal("out of memory\n");
+ }
+ if (do_indent == 1 && p_indent) {
+ for (;
+ indent < p_indent && (*line == ' ' || *line == '\t' || *line == 'X');
+ line++, skipped++) {
+ if (*line == '\t')
+ indent += 8 - (indent %7);
+ else
+ indent++;
+ }
+ }
+ memcpy(buf, line, len - skipped);
+ buf[len - skipped] = '\0';
+ line = linep;
+ }
+ free(line);
+ return (len > 0) ? len : 0;
+}
+
+
+/*
+ * Reverse the old and new portions of the current hunk.
+ */
+bool
+pch_swap(void)
+{
+ char **tp_line; /* the text of the hunk */
+ size_t *tp_len; /* length of each line */
+ char *tp_char; /* +, -, and ! */
+ LINENUM i;
+ LINENUM n;
+ bool blankline = false;
+ char *s;
+
+ i = p_first;
+ p_first = p_newfirst;
+ p_newfirst = i;
+
+ /* make a scratch copy */
+
+ tp_line = p_line;
+ tp_len = p_len;
+ tp_char = p_char;
+ p_line = NULL; /* force set_hunkmax to allocate again */
+ p_len = NULL;
+ p_char = NULL;
+ set_hunkmax();
+ if (p_line == NULL || p_len == NULL || p_char == NULL) {
+
+ free(p_line);
+ p_line = tp_line;
+ free(p_len);
+ p_len = tp_len;
+ free(p_char);
+ p_char = tp_char;
+ return false; /* not enough memory to swap hunk! */
+ }
+ /* now turn the new into the old */
+
+ i = p_ptrn_lines + 1;
+ if (tp_char[i] == '\n') { /* account for possible blank line */
+ blankline = true;
+ i++;
+ }
+ if (p_efake >= 0) { /* fix non-freeable ptr range */
+ if (p_efake <= i)
+ n = p_end - i + 1;
+ else
+ n = -i;
+ p_efake += n;
+ p_bfake += n;
+ }
+ for (n = 0; i <= p_end; i++, n++) {
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ if (p_char[n] == '+')
+ p_char[n] = '-';
+ p_len[n] = tp_len[i];
+ }
+ if (blankline) {
+ i = p_ptrn_lines + 1;
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ p_len[n] = tp_len[i];
+ n++;
+ }
+ if (p_char[0] != '=')
+ fatal("Malformed patch at line %ld: expected '=' found '%c'\n",
+ p_input_line, p_char[0]);
+ p_char[0] = '*';
+ for (s = p_line[0]; *s; s++)
+ if (*s == '-')
+ *s = '*';
+
+ /* now turn the old into the new */
+
+ if (p_char[0] != '*')
+ fatal("Malformed patch at line %ld: expected '*' found '%c'\n",
+ p_input_line, p_char[0]);
+ tp_char[0] = '=';
+ for (s = tp_line[0]; *s; s++)
+ if (*s == '*')
+ *s = '-';
+ for (i = 0; n <= p_end; i++, n++) {
+ p_line[n] = tp_line[i];
+ p_char[n] = tp_char[i];
+ if (p_char[n] == '-')
+ p_char[n] = '+';
+ p_len[n] = tp_len[i];
+ }
+
+ if (i != p_ptrn_lines + 1)
+ fatal("Malformed patch at line %ld: expected %ld lines, "
+ "got %ld\n",
+ p_input_line, p_ptrn_lines + 1, i);
+
+ i = p_ptrn_lines;
+ p_ptrn_lines = p_repl_lines;
+ p_repl_lines = i;
+
+ free(tp_line);
+ free(tp_len);
+ free(tp_char);
+
+ return true;
+}
+
+/*
+ * Return the specified line position in the old file of the old context.
+ */
+LINENUM
+pch_first(void)
+{
+ return p_first;
+}
+
+/*
+ * Return the number of lines of old context.
+ */
+LINENUM
+pch_ptrn_lines(void)
+{
+ return p_ptrn_lines;
+}
+
+/*
+ * Return the probable line position in the new file of the first line.
+ */
+LINENUM
+pch_newfirst(void)
+{
+ return p_newfirst;
+}
+
+/*
+ * Return the number of lines in the replacement text including context.
+ */
+LINENUM
+pch_repl_lines(void)
+{
+ return p_repl_lines;
+}
+
+/*
+ * Return the number of lines in the whole hunk.
+ */
+LINENUM
+pch_end(void)
+{
+ return p_end;
+}
+
+/*
+ * Return the number of context lines before the first changed line.
+ */
+LINENUM
+pch_context(void)
+{
+ return p_context;
+}
+
+/*
+ * Return the length of a particular patch line.
+ */
+size_t
+pch_line_len(LINENUM line)
+{
+ return p_len[line];
+}
+
+/*
+ * Return the control character (+, -, *, !, etc) for a patch line.
+ */
+char
+pch_char(LINENUM line)
+{
+ return p_char[line];
+}
+
+/*
+ * Return a pointer to a particular patch line.
+ */
+char *
+pfetch(LINENUM line)
+{
+ return p_line[line];
+}
+
+/*
+ * Return where in the patch file this hunk began, for error messages.
+ */
+LINENUM
+pch_hunk_beg(void)
+{
+ return p_hunk_beg;
+}
+
+/*
+ * Apply an ed script by feeding ed itself.
+ */
+void
+do_ed_script(void)
+{
+ char *t;
+ off_t beginning_of_this_line;
+ FILE *pipefp = NULL;
+ int continuation;
+
+ if (!skip_rest_of_patch) {
+ if (copy_file(filearg[0], TMPOUTNAME) < 0) {
+ unlink(TMPOUTNAME);
+ fatal("can't create temp file %s", TMPOUTNAME);
+ }
+ snprintf(buf, buf_size, "%s%s%s", _PATH_RED,
+ verbose ? " " : " -s ", TMPOUTNAME);
+ pipefp = popen(buf, "w");
+ }
+ for (;;) {
+ beginning_of_this_line = ftello(pfp);
+ if (pgets(true) == 0) {
+ next_intuit_at(beginning_of_this_line, p_input_line);
+ break;
+ }
+ p_input_line++;
+ for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ /* POSIX defines allowed commands as {a,c,d,i,s} */
+ if (isdigit((unsigned char)*buf) &&
+ (*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ if (*t == 's') {
+ for (;;) {
+ continuation = 0;
+ t = strchr(buf, '\0') - 1;
+ while (--t >= buf && *t == '\\')
+ continuation = !continuation;
+ if (!continuation ||
+ pgets(true) == 0)
+ break;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ }
+ } else if (*t != 'd') {
+ while (pgets(true)) {
+ p_input_line++;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ if (strEQ(buf, ".\n"))
+ break;
+ }
+ }
+ } else {
+ next_intuit_at(beginning_of_this_line, p_input_line);
+ break;
+ }
+ }
+ if (pipefp == NULL)
+ return;
+ fprintf(pipefp, "w\n");
+ fprintf(pipefp, "q\n");
+ fflush(pipefp);
+ pclose(pipefp);
+ ignore_signals();
+ if (!check_only) {
+ if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = true;
+ chmod(TMPOUTNAME, filemode);
+ } else
+ chmod(outname, filemode);
+ }
+ set_signals(1);
+}
+
+/*
+ * Choose the name of the file to be patched based on POSIX rules.
+ * NOTE: the POSIX rules are amazingly stupid and we only follow them
+ * if the user specified --posix or set POSIXLY_CORRECT.
+ */
+static char *
+posix_name(const struct file_name *names, bool assume_exists)
+{
+ char *path = NULL;
+ int i;
+
+ /*
+ * POSIX states that the filename will be chosen from one
+ * of the old, new and index names (in that order) if
+ * the file exists relative to CWD after -p stripping.
+ */
+ for (i = 0; i < MAX_FILE; i++) {
+ if (names[i].path != NULL && names[i].exists) {
+ path = names[i].path;
+ break;
+ }
+ }
+ if (path == NULL && !assume_exists) {
+ /*
+ * No files found, check to see if the diff could be
+ * creating a new file.
+ */
+ if (path == NULL && ok_to_create_file &&
+ names[NEW_FILE].path != NULL)
+ path = names[NEW_FILE].path;
+ }
+
+ return path ? xstrdup(path) : NULL;
+}
+
+static char *
+compare_names(const struct file_name *names, bool assume_exists)
+{
+ size_t min_components, min_baselen, min_len, tmp;
+ char *best = NULL;
+ char *path;
+ int i;
+
+ /*
+ * The "best" name is the one with the fewest number of path
+ * components, the shortest basename length, and the shortest
+ * overall length (in that order). We only use the Index: file
+ * if neither of the old or new files could be intuited from
+ * the diff header.
+ */
+ min_components = min_baselen = min_len = SIZE_MAX;
+ for (i = INDEX_FILE; i >= OLD_FILE; i--) {
+ path = names[i].path;
+ if (path == NULL || (!names[i].exists && !assume_exists))
+ continue;
+ if ((tmp = num_components(path)) > min_components)
+ continue;
+ if (tmp < min_components) {
+ min_components = tmp;
+ best = path;
+ }
+ if ((tmp = strlen(basename(path))) > min_baselen)
+ continue;
+ if (tmp < min_baselen) {
+ min_baselen = tmp;
+ best = path;
+ }
+ if ((tmp = strlen(path)) > min_len)
+ continue;
+ min_len = tmp;
+ best = path;
+ }
+ return best;
+}
+
+/*
+ * Choose the name of the file to be patched based the "best" one
+ * available.
+ */
+static char *
+best_name(const struct file_name *names, bool assume_exists)
+{
+ char *best;
+
+ best = compare_names(names, assume_exists);
+
+ /* No match? Check to see if the diff could be creating a new file. */
+ if (best == NULL && ok_to_create_file)
+ best = names[NEW_FILE].path;
+
+ return best ? xstrdup(best) : NULL;
+}
+
+static size_t
+num_components(const char *path)
+{
+ size_t n;
+ const char *cp;
+
+ for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++) {
+ cp++;
+ while (*cp == '/')
+ cp++; /* skip consecutive slashes */
+ }
+ return n;
+}
+
+/*
+ * Convert number at NPTR into LINENUM and save address of first
+ * character that is not a digit in ENDPTR. If conversion is not
+ * possible, call fatal.
+ */
+static LINENUM
+strtolinenum(char *nptr, char **endptr)
+{
+ LINENUM rv;
+ char c;
+ char *p;
+ const char *errstr;
+
+ for (p = nptr; isdigit((unsigned char)*p); p++)
+ ;
+
+ if (p == nptr)
+ malformed();
+
+ c = *p;
+ *p = '\0';
+
+ rv = strtonum(nptr, 0, LINENUM_MAX, &errstr);
+ if (errstr != NULL)
+ fatal("invalid line number at line %ld: `%s' is %s\n",
+ p_input_line, nptr, errstr);
+
+ *p = c;
+ *endptr = p;
+
+ return rv;
+}
diff --git a/usr.bin/patch/pch.h b/usr.bin/patch/pch.h
new file mode 100644
index 000000000000..b6c6363155a5
--- /dev/null
+++ b/usr.bin/patch/pch.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: pch.h,v 1.9 2003/10/31 20:20:45 millert Exp $
+ */
+
+#define OLD_FILE 0
+#define NEW_FILE 1
+#define INDEX_FILE 2
+#define MAX_FILE 3
+
+struct file_name {
+ char *path;
+ bool exists;
+};
+
+extern char *source_file;
+
+void re_patch(void);
+void open_patch_file(const char *);
+void set_hunkmax(void);
+bool there_is_another_patch(void);
+bool another_hunk(void);
+bool pch_swap(void);
+char *pfetch(LINENUM);
+size_t pch_line_len(LINENUM);
+LINENUM pch_first(void);
+LINENUM pch_ptrn_lines(void);
+LINENUM pch_newfirst(void);
+LINENUM pch_repl_lines(void);
+LINENUM pch_end(void);
+LINENUM pch_context(void);
+LINENUM pch_hunk_beg(void);
+char pch_char(LINENUM);
+void do_ed_script(void);
diff --git a/usr.bin/patch/tests/Makefile b/usr.bin/patch/tests/Makefile
new file mode 100644
index 000000000000..bb113b5a260f
--- /dev/null
+++ b/usr.bin/patch/tests/Makefile
@@ -0,0 +1,10 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= unified_patch_test
+
+${PACKAGE}FILES+= PR74127-cline.diff
+${PACKAGE}FILES+= PR74127-good.diff
+${PACKAGE}FILES+= PR74127-repro.diff
+${PACKAGE}FILES+= PR74127.in
+
+.include <bsd.test.mk>
diff --git a/usr.bin/patch/tests/Makefile.depend b/usr.bin/patch/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/patch/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/patch/tests/PR74127-cline.diff b/usr.bin/patch/tests/PR74127-cline.diff
new file mode 100644
index 000000000000..551d86dfca83
--- /dev/null
+++ b/usr.bin/patch/tests/PR74127-cline.diff
@@ -0,0 +1,4 @@
+file.c
+@@ -3,1 +3,1 @@
+- set Log(compressProg) /usr/local/bin/gzip
++ set Log(compressProg) /usr/bin/gzip
diff --git a/usr.bin/patch/tests/PR74127-good.diff b/usr.bin/patch/tests/PR74127-good.diff
new file mode 100644
index 000000000000..fac1726fcb8c
--- /dev/null
+++ b/usr.bin/patch/tests/PR74127-good.diff
@@ -0,0 +1,4 @@
+file.c
+@@ -3,1 +3,1 @@
+- set Log(compressProg) gzip
++ set Log(compressProg) /usr/local/bin/gzip
diff --git a/usr.bin/patch/tests/PR74127-repro.diff b/usr.bin/patch/tests/PR74127-repro.diff
new file mode 100644
index 000000000000..0ad3640ee392
--- /dev/null
+++ b/usr.bin/patch/tests/PR74127-repro.diff
@@ -0,0 +1,4 @@
+file.c
+@@ -5,1 +5,1 @@
+- set Log(compressProg) /usr/local/bin/gzip
++ set Log(compressProg) /usr/bin/gzip
diff --git a/usr.bin/patch/tests/PR74127.in b/usr.bin/patch/tests/PR74127.in
new file mode 100644
index 000000000000..ed295c477cfa
--- /dev/null
+++ b/usr.bin/patch/tests/PR74127.in
@@ -0,0 +1,14 @@
+# This program is used to compress log files
+if {![info exists Log(compressProg)]} {
+ set Log(compressProg) gzip
+}
+
+# Flush interval
+if {![info exists Log(flushInterval)]} {
+ set Log(flushInterval) [expr {60 * 1000}]
+}
+
+# This is used to turn on an alternate debug log file
+if {![info exist Log(debug_log)]} {
+ set Log(debug_log) 0
+}
diff --git a/usr.bin/patch/tests/unified_patch_test.sh b/usr.bin/patch/tests/unified_patch_test.sh
new file mode 100755
index 000000000000..7d4b74182c41
--- /dev/null
+++ b/usr.bin/patch/tests/unified_patch_test.sh
@@ -0,0 +1,170 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case basic
+basic_body()
+{
+ printf "a\nb\nc\nd\ne\nf\ng\nh\ni\n" > foo_full
+ printf "a\nb\nc\n" > foo_start
+ printf "g\nh\ni\n" > foo_end
+ printf "d\ne\nf\n" > foo_middle
+
+ diff -u foo_start foo_full > foo_start2full.diff
+ diff -u foo_end foo_full > foo_end2full.diff
+ diff -u foo_middle foo_full > foo_mid2full.diff
+
+ # Check lengths... each should have all 9 lines + 3 line header
+ atf_check -o inline:"12" -x \
+ "cat foo_start2full.diff | wc -l | tr -d '[:space:]'"
+ atf_check -o inline:"12" -x \
+ "cat foo_end2full.diff | wc -l | tr -d '[:space:]'"
+ atf_check -o inline:"12" -x \
+ "cat foo_mid2full.diff | wc -l | tr -d '[:space:]'"
+
+ # Apply the patch! Should succeed
+ atf_check -o ignore patch foo_start foo_start2full.diff \
+ -o foo_start2full
+ atf_check -o ignore patch foo_end foo_end2full.diff \
+ -o foo_end2full
+ atf_check -o ignore patch foo_middle foo_mid2full.diff \
+ -o foo_mid2full
+
+ # And these should all produce equivalent to the original full
+ atf_check -o ignore diff foo_start2full foo_full
+ atf_check -o ignore diff foo_end2full foo_full
+ atf_check -o ignore diff foo_mid2full foo_full
+}
+
+atf_test_case limited_ctx
+limited_ctx_head()
+{
+ atf_set "descr" "Verify correct behavior with limited context (PR 74127)"
+}
+limited_ctx_body()
+{
+
+ # First; PR74127-repro.diff should not have applied, but it instead
+ # assumed a match and added the modified line at the offset specified...
+ atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
+ "$(atf_get_srcdir)/PR74127.in" \
+ "$(atf_get_srcdir)/PR74127-repro.diff"
+
+ # Let's extend that and make sure a similarly ill-contexted diff does
+ # not apply even with the correct line number
+ atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
+ "$(atf_get_srcdir)/PR74127.in" \
+ "$(atf_get_srcdir)/PR74127-line.diff"
+
+ # Correct line number and correct old line should always work
+ atf_check -o ignore -e ignore patch -o _.out \
+ "$(atf_get_srcdir)/PR74127.in" \
+ "$(atf_get_srcdir)/PR74127-good.diff"
+}
+
+atf_test_case file_creation
+file_creation_body()
+{
+
+ echo "x" > foo
+ diff -u /dev/null foo > foo.diff
+ rm foo
+
+ atf_check -x "patch -s < foo.diff"
+ atf_check -o ignore stat foo
+}
+
+# This test is motivated by long-standing bugs that occasionally slip by in
+# commits. If a file is created by a diff, patch(1) will happily duplicate the
+# contents as many times as you apply the diff. It should instead detect that
+# a source of /dev/null creates the file, so it shouldn't exist. Furthermore,
+# the reverse of creation is deletion -- hence the next test, which ensures that
+# the file is removed if it's empty once the patch is reversed. The size checks
+# are scattered throughout to make sure that we didn't get some kind of false
+# error, and the first size check is merely a sanity check that should be
+# trivially true as this is executed in a sandbox.
+atf_test_case file_nodupe
+file_nodupe_body()
+{
+
+ echo "x" > foo
+ diff -u /dev/null foo > foo.diff
+
+ atf_check -o inline:"2\n" stat -f "%z" foo
+ atf_check -s not-exit:0 -o ignore -x "patch -Ns < foo.diff"
+ atf_check -o inline:"2\n" stat -f "%z" foo
+ atf_check -s not-exit:0 -o ignore -x "patch -fs < foo.diff"
+ atf_check -o inline:"2\n" stat -f "%z" foo
+}
+
+atf_test_case file_removal
+file_removal_body()
+{
+
+ echo "x" > foo
+ diff -u /dev/null foo > foo.diff
+
+ # Check that the file is removed completely if it was sourced from
+ # /dev/null
+ atf_check -x "patch -Rs < foo.diff"
+ atf_check -s not-exit:0 -e ignore stat foo
+
+ # But if it had been modified, we'll only remove the portion that the
+ # patch would have created. This makes us compatible with GNU patch's
+ # behavior, at least. Whether that is the sane action or not is a
+ # question for further study, and then this comment may be removed.
+ printf "x\ny\n" > foo
+ atf_check -x "patch -Rs < foo.diff"
+ atf_check -o inline:"y\n" cat foo
+}
+
+atf_test_case plinelen
+plinelen_body()
+{
+ hello="$(jot -b hello -s, 20000 | tee foo.txt)"
+ cp foo.txt bar.txt
+ echo "world" >>bar.txt
+ cat >foo.diff <<EOF
+--- foo.txt.orig
++++ foo.txt
+@@ -1,1 +1,2 @@
+ $hello
++world
+EOF
+ atf_check -o match:"Hunk #1 succeeded" \
+ patch <foo.diff
+ atf_check -o file:bar.txt cat foo.txt
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case limited_ctx
+ atf_add_test_case file_creation
+ atf_add_test_case file_nodupe
+ atf_add_test_case file_removal
+ atf_add_test_case plinelen
+}
diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c
new file mode 100644
index 000000000000..bb4c97e42112
--- /dev/null
+++ b/usr.bin/patch/util.c
@@ -0,0 +1,423 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: util.c,v 1.35 2010/07/24 01:10:12 ray Exp $
+ */
+
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "util.h"
+#include "backupfile.h"
+#include "pathnames.h"
+
+/* Rename a file, copying it if necessary. */
+
+int
+move_file(const char *from, const char *to)
+{
+ int fromfd;
+ ssize_t i;
+
+ /* to stdout? */
+
+ if (strEQ(to, "-")) {
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to stdout.\n", from);
+#endif
+ fromfd = open(from, O_RDONLY);
+ if (fromfd < 0)
+ pfatal("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, buf_size)) > 0)
+ if (write(STDOUT_FILENO, buf, i) != i)
+ pfatal("write failed");
+ close(fromfd);
+ return 0;
+ }
+ if (backup_file(to) < 0) {
+ say("Can't backup %s, output is in %s: %s\n", to, from,
+ strerror(errno));
+ return -1;
+ }
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to %s.\n", from, to);
+#endif
+ if (rename(from, to) < 0) {
+ if (errno != EXDEV || copy_file(from, to) < 0) {
+ say("Can't create %s, output is in %s: %s\n",
+ to, from, strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Backup the original file. */
+
+int
+backup_file(const char *orig)
+{
+ struct stat filestat;
+ char bakname[PATH_MAX], *s, *simplename;
+ dev_t orig_device;
+ ino_t orig_inode;
+
+ if (backup_type == none || stat(orig, &filestat) != 0)
+ return 0; /* nothing to do */
+ /*
+ * If the user used zero prefixes or suffixes, then
+ * he doesn't want backups. Yet we have to remove
+ * orig to break possible hardlinks.
+ */
+ if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
+ unlink(orig);
+ return 0;
+ }
+ orig_device = filestat.st_dev;
+ orig_inode = filestat.st_ino;
+
+ if (origprae) {
+ if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
+ strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
+ fatal("filename %s too long for buffer\n", origprae);
+ } else {
+ if ((s = find_backup_file_name(orig)) == NULL)
+ fatal("out of memory\n");
+ if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
+ fatal("filename %s too long for buffer\n", s);
+ free(s);
+ }
+
+ if ((simplename = strrchr(bakname, '/')) != NULL)
+ simplename = simplename + 1;
+ else
+ simplename = bakname;
+
+ /*
+ * Find a backup name that is not the same file. Change the
+ * first lowercase char into uppercase; if that isn't
+ * sufficient, chop off the first char and try again.
+ */
+ while (stat(bakname, &filestat) == 0 &&
+ orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
+ /* Skip initial non-lowercase chars. */
+ for (s = simplename; *s && !islower((unsigned char)*s); s++)
+ ;
+ if (*s)
+ *s = toupper((unsigned char)*s);
+ else
+ memmove(simplename, simplename + 1,
+ strlen(simplename + 1) + 1);
+ }
+#ifdef DEBUGGING
+ if (debug & 4)
+ say("Moving %s to %s.\n", orig, bakname);
+#endif
+ if (rename(orig, bakname) < 0) {
+ if (errno != EXDEV || copy_file(orig, bakname) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Copy a file.
+ */
+int
+copy_file(const char *from, const char *to)
+{
+ int tofd, fromfd;
+ ssize_t i;
+
+ tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (tofd < 0)
+ return -1;
+ fromfd = open(from, O_RDONLY, 0);
+ if (fromfd < 0)
+ pfatal("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, buf_size)) > 0)
+ if (write(tofd, buf, i) != i)
+ pfatal("write to %s failed", to);
+ close(fromfd);
+ close(tofd);
+ return 0;
+}
+
+/*
+ * Allocate a unique area for a string.
+ */
+char *
+savestr(const char *s)
+{
+ char *rv;
+
+ if (!s)
+ s = "Oops";
+ rv = strdup(s);
+ if (rv == NULL) {
+ if (using_plan_a)
+ out_of_mem = true;
+ else
+ fatal("out of memory\n");
+ }
+ return rv;
+}
+
+/*
+ * Allocate a unique area for a string. Call fatal if out of memory.
+ */
+char *
+xstrdup(const char *s)
+{
+ char *rv;
+
+ if (!s)
+ s = "Oops";
+ rv = strdup(s);
+ if (rv == NULL)
+ fatal("out of memory\n");
+ return rv;
+}
+
+/*
+ * Vanilla terminal output (buffered).
+ */
+void
+say(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fflush(stdout);
+}
+
+/*
+ * Terminal output, pun intended.
+ */
+void
+fatal(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "patch: **** ");
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ my_exit(2);
+}
+
+/*
+ * Say something from patch, something from the system, then silence . . .
+ */
+void
+pfatal(const char *fmt, ...)
+{
+ va_list ap;
+ int errnum = errno;
+
+ fprintf(stderr, "patch: **** ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, ": %s\n", strerror(errnum));
+ my_exit(2);
+}
+
+/*
+ * Get a response from the user via /dev/tty
+ */
+void
+ask(const char *fmt, ...)
+{
+ va_list ap;
+ ssize_t nr = 0;
+ static int ttyfd = -1;
+
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fflush(stdout);
+ if (ttyfd < 0)
+ ttyfd = open(_PATH_TTY, O_RDONLY);
+ if (ttyfd >= 0) {
+ if ((nr = read(ttyfd, buf, buf_size)) > 0 &&
+ buf[nr - 1] == '\n')
+ buf[nr - 1] = '\0';
+ }
+ if (ttyfd < 0 || nr <= 0) {
+ /* no tty or error reading, pretend user entered 'return' */
+ putchar('\n');
+ buf[0] = '\0';
+ }
+}
+
+/*
+ * How to handle certain events when not in a critical region.
+ */
+void
+set_signals(int reset)
+{
+ static sig_t hupval, intval;
+
+ if (!reset) {
+ hupval = signal(SIGHUP, SIG_IGN);
+ if (hupval != SIG_IGN)
+ hupval = my_exit;
+ intval = signal(SIGINT, SIG_IGN);
+ if (intval != SIG_IGN)
+ intval = my_exit;
+ }
+ signal(SIGHUP, hupval);
+ signal(SIGINT, intval);
+}
+
+/*
+ * How to handle certain events when in a critical region.
+ */
+void
+ignore_signals(void)
+{
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+}
+
+/*
+ * Make sure we'll have the directories to create a file. If `striplast' is
+ * true, ignore the last element of `filename'.
+ */
+
+void
+makedirs(const char *filename, bool striplast)
+{
+ char *tmpbuf;
+
+ if ((tmpbuf = strdup(filename)) == NULL)
+ fatal("out of memory\n");
+
+ if (striplast) {
+ char *s = strrchr(tmpbuf, '/');
+ if (s == NULL) {
+ free(tmpbuf);
+ return; /* nothing to be done */
+ }
+ *s = '\0';
+ }
+ if (mkpath(tmpbuf) != 0)
+ pfatal("creation of %s failed", tmpbuf);
+ free(tmpbuf);
+}
+
+/*
+ * Make filenames more reasonable.
+ */
+char *
+fetchname(const char *at, bool *exists, int strip_leading)
+{
+ char *fullname, *name, *t;
+ int sleading, tab;
+ struct stat filestat;
+
+ if (at == NULL || *at == '\0')
+ return NULL;
+ while (isspace((unsigned char)*at))
+ at++;
+#ifdef DEBUGGING
+ if (debug & 128)
+ say("fetchname %s %d\n", at, strip_leading);
+#endif
+ /* So files can be created by diffing against /dev/null. */
+ if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1)) {
+ *exists = true;
+ return NULL;
+ }
+ name = fullname = t = savestr(at);
+
+ tab = strchr(t, '\t') != NULL;
+ /* Strip off up to `strip_leading' path components and NUL terminate. */
+ for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
+ !isspace((unsigned char)*t)); t++) {
+ if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
+ if (--sleading >= 0)
+ name = t + 1;
+ }
+ *t = '\0';
+
+ /*
+ * If no -p option was given (957 is the default value!), we were
+ * given a relative pathname, and the leading directories that we
+ * just stripped off all exist, put them back on.
+ */
+ if (strip_leading == 957 && name != fullname && *fullname != '/') {
+ name[-1] = '\0';
+ if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
+ name[-1] = '/';
+ name = fullname;
+ }
+ }
+ name = savestr(name);
+ free(fullname);
+
+ *exists = stat(name, &filestat) == 0;
+ return name;
+}
+
+void
+version(void)
+{
+ printf("patch 2.0-12u11 FreeBSD\n");
+ my_exit(EXIT_SUCCESS);
+}
+
+/*
+ * Exit with cleanup.
+ */
+void
+my_exit(int status)
+{
+ unlink(TMPINNAME);
+ if (!toutkeep)
+ unlink(TMPOUTNAME);
+ if (!trejkeep)
+ unlink(TMPREJNAME);
+ unlink(TMPPATNAME);
+ exit(status);
+}
diff --git a/usr.bin/patch/util.h b/usr.bin/patch/util.h
new file mode 100644
index 000000000000..a968a64aa196
--- /dev/null
+++ b/usr.bin/patch/util.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright 1986, Larry Wall
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this condition and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * patch - a program to apply diffs to original files
+ *
+ * -C option added in 1998, original code by Marc Espie, based on FreeBSD
+ * behaviour
+ *
+ * $OpenBSD: util.h,v 1.16 2014/12/13 10:31:07 tobias Exp $
+ */
+
+char *fetchname(const char *, bool *, int);
+int backup_file(const char *);
+int move_file(const char *, const char *);
+int copy_file(const char *, const char *);
+void say(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void fatal(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void pfatal(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+void ask(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+char *savestr(const char *);
+char *xstrdup(const char *);
+void set_signals(int);
+void ignore_signals(void);
+void makedirs(const char *, bool);
+void version(void);
+void my_exit(int) __attribute__((noreturn));
+
+/* in mkpath.c */
+extern int mkpath(char *);
diff --git a/usr.bin/pathchk/Makefile b/usr.bin/pathchk/Makefile
new file mode 100644
index 000000000000..a3ea46c30c5f
--- /dev/null
+++ b/usr.bin/pathchk/Makefile
@@ -0,0 +1,3 @@
+PROG= pathchk
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pathchk/Makefile.depend b/usr.bin/pathchk/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/pathchk/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/pathchk/pathchk.1 b/usr.bin/pathchk/pathchk.1
new file mode 100644
index 000000000000..a90829969517
--- /dev/null
+++ b/usr.bin/pathchk/pathchk.1
@@ -0,0 +1,129 @@
+.\" Copyright (c) 2001, 2002 Chuck Rouillard
+.\" 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.
+.\"
+.Dd May 1, 2010
+.Dt PATHCHK 1
+.Os
+.Sh NAME
+.Nm pathchk
+.Nd check pathnames
+.Sh SYNOPSIS
+.Nm
+.Op Fl pP
+.Ar pathname ...
+.Sh DESCRIPTION
+The
+.Nm
+utility checks whether each of the specified
+.Ar pathname
+arguments is valid or portable.
+.Pp
+A diagnostic message is written for each argument that:
+.Bl -bullet
+.It
+Is longer than
+.Dv PATH_MAX
+bytes.
+.It
+Contains any component longer than
+.Dv NAME_MAX
+bytes.
+(The value of
+.Dv NAME_MAX
+depends on the underlying file system.)
+.It
+Contains a directory component that is not searchable.
+.El
+.Pp
+It is not considered an error if a
+.Ar pathname
+argument contains a nonexistent component as long as a component by that
+name could be created.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl p
+Perform portability checks on the specified
+.Ar pathname
+arguments.
+Diagnostic messages will be written for each argument that:
+.Bl -bullet
+.It
+Is longer than
+.Dv _POSIX_PATH_MAX
+.Pq 255
+bytes.
+.It
+Contains a component longer than
+.Dv _POSIX_NAME_MAX
+.Pq 14
+bytes.
+.It
+Contains any character not in the portable filename character set (that is,
+alphanumeric characters,
+.Ql \&. ,
+.Ql \&-
+and
+.Ql _ ) .
+No component may start with the hyphen
+.Pq Ql \&-
+character.
+.El
+.It Fl P
+In addition to the default or
+.Fl p
+checks, write a diagnostic for each argument that:
+.Bl -bullet
+.It
+Is empty.
+.It
+Contains a component that starts with a hyphen.
+.El
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Check whether the names of files in the current directory are portable to
+other
+.Tn POSIX
+systems:
+.Pp
+.Dl "find . -exec pathchk -p -- {} +"
+.Sh SEE ALSO
+.Xr getconf 1 ,
+.Xr pathconf 2 ,
+.Xr stat 2
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.Fx 5.0 .
diff --git a/usr.bin/pathchk/pathchk.c b/usr.bin/pathchk/pathchk.c
new file mode 100644
index 000000000000..4b9dddf0630b
--- /dev/null
+++ b/usr.bin/pathchk/pathchk.c
@@ -0,0 +1,201 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * pathchk -- check pathnames
+ *
+ * Check whether files could be created with the names specified on the
+ * command line. If -p is specified, check whether the pathname is portable
+ * to all POSIX systems.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int check(const char *);
+static int portable(const char *);
+static void usage(void);
+
+static int pflag; /* Perform portability checks */
+static int Pflag; /* Check for empty paths, leading '-' */
+
+int
+main(int argc, char *argv[])
+{
+ int ch, rval;
+ const char *arg;
+
+ while ((ch = getopt(argc, argv, "pP")) > 0) {
+ switch (ch) {
+ case 'p':
+ pflag = 1;
+ break;
+ case 'P':
+ Pflag = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ usage();
+
+ rval = 0;
+ while ((arg = *argv++) != NULL)
+ rval |= check(arg);
+
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: pathchk [-Pp] pathname ...\n");
+ exit(1);
+}
+
+static int
+check(const char *path)
+{
+ struct stat sb;
+ long complen, namemax, pathmax, svnamemax;
+ int last;
+ char *end, *p, *pathd;
+
+ if ((pathd = strdup(path)) == NULL)
+ err(1, "strdup");
+
+ p = pathd;
+
+ if (Pflag && *p == '\0') {
+ warnx("%s: empty pathname", path);
+ goto bad;
+ }
+ if ((Pflag || pflag) && (*p == '-' || strstr(p, "/-") != NULL)) {
+ warnx("%s: contains a component starting with '-'", path);
+ goto bad;
+ }
+
+ if (!pflag) {
+ errno = 0;
+ namemax = pathconf(*p == '/' ? "/" : ".", _PC_NAME_MAX);
+ if (namemax == -1 && errno != 0)
+ namemax = NAME_MAX;
+ } else
+ namemax = _POSIX_NAME_MAX;
+
+ for (;;) {
+ p += strspn(p, "/");
+ complen = (long)strcspn(p, "/");
+ end = p + complen;
+ last = *end == '\0';
+ *end = '\0';
+
+ if (namemax != -1 && complen > namemax) {
+ warnx("%s: %s: component too long (limit %ld)", path,
+ p, namemax);
+ goto bad;
+ }
+
+ if (!pflag && stat(pathd, &sb) == -1 && errno != ENOENT) {
+ warn("%s: %.*s", path, (int)(strlen(pathd) -
+ complen - 1), pathd);
+ goto bad;
+ }
+
+ if (pflag && !portable(p)) {
+ warnx("%s: %s: component contains non-portable "
+ "character", path, p);
+ goto bad;
+ }
+
+ if (last)
+ break;
+
+ if (!pflag) {
+ errno = 0;
+ svnamemax = namemax;
+ namemax = pathconf(pathd, _PC_NAME_MAX);
+ if (namemax == -1 && errno != 0)
+ namemax = svnamemax;
+ }
+
+ *end = '/';
+ p = end + 1;
+ }
+
+ if (!pflag) {
+ errno = 0;
+ pathmax = pathconf(path, _PC_PATH_MAX);
+ if (pathmax == -1 && errno != 0)
+ pathmax = PATH_MAX;
+ } else
+ pathmax = _POSIX_PATH_MAX;
+ if (pathmax != -1 && strlen(path) >= (size_t)pathmax) {
+ warnx("%s: path too long (limit %ld)", path, pathmax - 1);
+ goto bad;
+ }
+
+ free(pathd);
+ return (0);
+
+bad: free(pathd);
+ return (1);
+}
+
+/*
+ * Check whether a path component contains only portable characters.
+ */
+static int
+portable(const char *path)
+{
+ static const char charset[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789._-";
+ long s;
+
+ s = strspn(path, charset);
+ if (path[s] != '\0')
+ return (0);
+
+ return (1);
+}
diff --git a/usr.bin/perror/Makefile b/usr.bin/perror/Makefile
new file mode 100644
index 000000000000..a83cd29dbc22
--- /dev/null
+++ b/usr.bin/perror/Makefile
@@ -0,0 +1,3 @@
+PROG= perror
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/perror/Makefile.depend b/usr.bin/perror/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/perror/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/perror/perror.1 b/usr.bin/perror/perror.1
new file mode 100644
index 000000000000..6fdc0a2e97a7
--- /dev/null
+++ b/usr.bin/perror/perror.1
@@ -0,0 +1,48 @@
+.\"
+.\" Copyright (c) 2009 Hudson River Trading LLC
+.\" Written by: George V. Neville-Neil <gnn@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 May 12, 2009
+.Dt PERROR 1
+.Os
+.Sh NAME
+.Nm perror
+.Nd "print an error number as a string"
+.Sh SYNOPSIS
+.Nm
+.Ar number
+.Sh DESCRIPTION
+The
+.Nm
+program takes a raw errno value and prints it as a string.
+.Sh SEE ALSO
+.Xr perror 3
+.Sh HISTORY
+The
+.Nm
+program first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An George V. Neville-Neil
diff --git a/usr.bin/perror/perror.c b/usr.bin/perror/perror.c
new file mode 100644
index 000000000000..4ef77aefdd31
--- /dev/null
+++ b/usr.bin/perror/perror.c
@@ -0,0 +1,80 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009 Hudson River Trading LLC
+ * Written by: George V. Neville-Neil <gnn@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/errno.h>
+
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <capsicum_helpers.h>
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ char *cp;
+ char *errstr;
+ long errnum;
+
+ (void) setlocale(LC_MESSAGES, "");
+
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(EXIT_FAILURE, "capsicum");
+
+ if (argc != 2)
+ usage();
+
+ errno = 0;
+
+ errnum = strtol(argv[1], &cp, 0);
+
+ if (errno != 0)
+ err(EXIT_FAILURE, NULL);
+
+ if ((errstr = strerror(errnum)) == NULL)
+ err(EXIT_FAILURE, NULL);
+
+ printf("%s\n", errstr);
+
+ exit(EXIT_SUCCESS);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: perror number\n");
+ exit(EXIT_FAILURE);
+}
+
diff --git a/usr.bin/pom/Makefile b/usr.bin/pom/Makefile
new file mode 100644
index 000000000000..54b62eface74
--- /dev/null
+++ b/usr.bin/pom/Makefile
@@ -0,0 +1,7 @@
+PACKAGE= games
+
+PROG= pom
+MAN= pom.6
+LIBADD= m
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pom/Makefile.depend b/usr.bin/pom/Makefile.depend
new file mode 100644
index 000000000000..866f7ef5d25b
--- /dev/null
+++ b/usr.bin/pom/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/pom/pom.6 b/usr.bin/pom/pom.6
new file mode 100644
index 000000000000..a3dc68b0a46b
--- /dev/null
+++ b/usr.bin/pom/pom.6
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1989, 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.
+.\"
+.Dd July 14, 2010
+.Dt POM 6
+.Os
+.Sh NAME
+.Nm pom
+.Nd display the phase of the moon
+.Sh SYNOPSIS
+.Nm
+.Op Fl p
+.Op Fl d Ar yyyy.mm.dd
+.Op Fl t Ar hh:mm:ss
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the current phase of the moon.
+Useful for selecting software completion target dates and predicting
+managerial behavior.
+.Pp
+Use the
+.Fl p
+option to print just the phase as a percentage.
+.Pp
+Use the arguments
+.Fl d
+and
+.Fl t
+to specify a specific date and time for which the phase of the moon
+has to be calculated.
+If
+.Fl d
+but not
+.Fl t
+has been specified, it will calculate the phase of the moon on that
+day at midnight.
+.Sh SEE ALSO
+`Practical Astronomy with Your Calculator' by Duffett-Smith.
diff --git a/usr.bin/pom/pom.c b/usr.bin/pom/pom.c
new file mode 100644
index 000000000000..db0033373b47
--- /dev/null
+++ b/usr.bin/pom/pom.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software posted to USENET.
+ *
+ * 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.
+ */
+
+/*
+ * Phase of the Moon. Calculates the current phase of the moon.
+ * Based on routines from `Practical Astronomy with Your Calculator',
+ * by Duffett-Smith. Comments give the section from the book that
+ * particular piece of code was adapted from.
+ *
+ * -- Keith E. Brandt VIII 1984
+ *
+ */
+
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+#define EPOCH 85
+#define EPSILONg 279.611371 /* solar ecliptic long at EPOCH */
+#define RHOg 282.680403 /* solar ecliptic long of perigee at EPOCH */
+#define ECCEN 0.01671542 /* solar orbit eccentricity */
+#define lzero 18.251907 /* lunar mean long at EPOCH */
+#define Pzero 192.917585 /* lunar mean long of perigee at EPOCH */
+#define Nzero 55.204723 /* lunar mean long of node at EPOCH */
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+static void adj360(double *);
+static double dtor(double);
+static double potm(double);
+static void usage(char *progname);
+
+int
+main(int argc, char **argv)
+{
+ time_t tt;
+ struct tm GMT, tmd;
+ double days, today, tomorrow;
+ int ch, cnt, pflag = 0;
+ char *odate = NULL, *otime = NULL;
+ char *progname = argv[0];
+
+ if (caph_limit_stdio() < 0)
+ err(1, "unable to limit capabitilities for stdio");
+
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ while ((ch = getopt(argc, argv, "d:pt:")) != -1)
+ switch (ch) {
+ case 'd':
+ odate = optarg;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 't':
+ otime = optarg;
+ break;
+ default:
+ usage(progname);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ usage(progname);
+
+ /* Adjust based on users preferences */
+ time(&tt);
+ if (otime != NULL || odate != NULL) {
+ /* Save today in case -d isn't specified */
+ localtime_r(&tt, &tmd);
+
+ if (odate != NULL) {
+ tmd.tm_year = strtol(odate, NULL, 10) - 1900;
+ tmd.tm_mon = strtol(odate + 5, NULL, 10) - 1;
+ tmd.tm_mday = strtol(odate + 8, NULL, 10);
+ /* Use midnight as the middle of the night */
+ tmd.tm_hour = 0;
+ tmd.tm_min = 0;
+ tmd.tm_sec = 0;
+ tmd.tm_isdst = -1;
+ }
+ if (otime != NULL) {
+ tmd.tm_hour = strtol(otime, NULL, 10);
+ tmd.tm_min = strtol(otime + 3, NULL, 10);
+ tmd.tm_sec = strtol(otime + 6, NULL, 10);
+ tmd.tm_isdst = -1;
+ }
+ tt = mktime(&tmd);
+ }
+
+ gmtime_r(&tt, &GMT);
+ days = (GMT.tm_yday + 1) + ((GMT.tm_hour +
+ (GMT.tm_min / 60.0) + (GMT.tm_sec / 3600.0)) / 24.0);
+ for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt)
+ days += isleap(1900 + cnt) ? 366 : 365;
+ today = potm(days);
+ if (pflag) {
+ (void)printf("%1.0f\n", today);
+ return (0);
+ }
+ (void)printf("The Moon is ");
+ if (today >= 99.5)
+ (void)printf("Full\n");
+ else if (today < 0.5)
+ (void)printf("New\n");
+ else {
+ tomorrow = potm(days + 1);
+ if (today >= 49.5 && today < 50.5)
+ (void)printf("%s\n", tomorrow > today ?
+ "at the First Quarter" : "at the Last Quarter");
+ else {
+ (void)printf("%s ", tomorrow > today ?
+ "Waxing" : "Waning");
+ if (today > 50)
+ (void)printf("Gibbous (%1.0f%% of Full)\n",
+ today);
+ else if (today < 50)
+ (void)printf("Crescent (%1.0f%% of Full)\n",
+ today);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * potm --
+ * return phase of the moon
+ */
+static double
+potm(double days)
+{
+ double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime;
+ double A4, lprime, V, ldprime, D, Nm;
+
+ N = 360 * days / 365.2422; /* sec 42 #3 */
+ adj360(&N);
+ Msol = N + EPSILONg - RHOg; /* sec 42 #4 */
+ adj360(&Msol);
+ Ec = 360 / PI * ECCEN * sin(dtor(Msol)); /* sec 42 #5 */
+ LambdaSol = N + Ec + EPSILONg; /* sec 42 #6 */
+ adj360(&LambdaSol);
+ l = 13.1763966 * days + lzero; /* sec 61 #4 */
+ adj360(&l);
+ Mm = l - (0.1114041 * days) - Pzero; /* sec 61 #5 */
+ adj360(&Mm);
+ Nm = Nzero - (0.0529539 * days); /* sec 61 #6 */
+ adj360(&Nm);
+ Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */
+ Ac = 0.1858 * sin(dtor(Msol)); /* sec 61 #8 */
+ A3 = 0.37 * sin(dtor(Msol));
+ Mmprime = Mm + Ev - Ac - A3; /* sec 61 #9 */
+ Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 61 #10 */
+ A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 61 #11 */
+ lprime = l + Ev + Ec - Ac + A4; /* sec 61 #12 */
+ V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 61 #13 */
+ ldprime = lprime + V; /* sec 61 #14 */
+ D = ldprime - LambdaSol; /* sec 63 #2 */
+ return(50 * (1 - cos(dtor(D)))); /* sec 63 #3 */
+}
+
+/*
+ * dtor --
+ * convert degrees to radians
+ */
+static double
+dtor(double deg)
+{
+
+ return(deg * PI / 180);
+}
+
+/*
+ * adj360 --
+ * adjust value so 0 <= deg <= 360
+ */
+static void
+adj360(double *deg)
+{
+
+ for (;;)
+ if (*deg < 0)
+ *deg += 360;
+ else if (*deg > 360)
+ *deg -= 360;
+ else
+ break;
+}
+
+static void
+usage(char *progname)
+{
+
+ fprintf(stderr, "Usage: %s [-p] [-d yyyy.mm.dd] [-t hh:mm:ss]\n",
+ progname);
+ exit(EX_USAGE);
+}
diff --git a/usr.bin/posixmqcontrol/Makefile b/usr.bin/posixmqcontrol/Makefile
new file mode 100644
index 000000000000..3cbfa8557625
--- /dev/null
+++ b/usr.bin/posixmqcontrol/Makefile
@@ -0,0 +1,4 @@
+PROG= posixmqcontrol
+LIBADD= rt
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/posixmqcontrol/posixmqcontrol.1 b/usr.bin/posixmqcontrol/posixmqcontrol.1
new file mode 100644
index 000000000000..00b1d30dbc50
--- /dev/null
+++ b/usr.bin/posixmqcontrol/posixmqcontrol.1
@@ -0,0 +1,180 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2024 Rick Parrish <unitrunker@unitrunker.net>.
+.\"
+.\" 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 AUTHORS 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 AUTHORS 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 February 19, 2024
+.Dt POSIXMQCONTROL 1
+.Os
+.Sh NAME
+.Nm posixmqcontrol
+.Nd Control POSIX mqueuefs message queues
+.Sh SYNOPSIS
+.Nm
+.Ar create
+.Fl q Ar queue
+.Fl s Ar size
+.Fl d Ar depth
+.Op Fl m Ar mode
+.Op Fl g Ar group
+.Op Fl u Ar user
+.Nm
+.Ar info
+.Fl q Ar queue
+.Nm
+.Ar recv
+.Fl q Ar queue
+.Nm
+.Ar rm
+.Fl q Ar queue
+.Nm
+.Ar send
+.Fl q Ar queue
+.Fl c Ar content
+.Op Fl p Ar priority
+.Sh DESCRIPTION
+The
+.Nm
+command allows separating POSIX message queue administration from application
+stack.
+Defining and adjusting queue attributes can be done without touching
+application code.
+It allows creating queues, inspecting queue metadata, altering group and user
+access to queues, dumping queue contents, and unlinking queues.
+.Pp
+Unlinking removes the name from the system and frees underlying memory.
+.Pp
+The maximum message size, maximum queue size, and current queue size are
+displayed by the
+.Ic info
+subcommand. This output is similar to running
+.Ic cat
+on a mqueuefs queue mounted under a mount point.
+This utility requires the
+.Ic mqueuefs
+kernel module to be loaded but does not require
+.Ic mqueuefs
+to be mounted as a file system.
+.Pp
+The following subcommands are provided:
+.Bl -tag -width truncate
+.It Ic create
+Create the named queues, if they do not already exist.
+More than one queue name may be created. The same maximum queue depth and
+maximum message size are used to create all queues.
+If a queue exists, then depth and size are optional.
+.Pp
+The required
+.Ar size
+and
+.Ar depth
+arguments specify the maximum message size (bytes per message) and maximum queue
+size (depth or number of messages in the queue).
+The optional numerical
+.Ar mode
+argument specifies the initial access mode.
+If the queue exists but does not match the requested size and depth, this
+utility will attempt to recreate the queue by first unlinking and then creating
+it.
+This will fail if the queue is not empty or is opened by other processes.
+.It Ic rm
+Unlink the queues specified - one attempt per queue.
+Failure to unlink one queue does not stop this sub-command from attempting to
+unlink the others.
+.It Ic info
+For each named queue, dispay the maximum message size, maximum queue size,
+current queue depth, user owner id, group owner id, and mode permission bits.
+.It Ic recv
+Wait for a message from a single named queue and display the message to
+standard output.
+.It Ic send
+Send messages to one or more named queues.
+If multiple messages and multiple queues are specified, the utility attempts to
+send all messages to all queues.
+The optional -p priority, if omitted, defaults to MQ_PRIO_MAX / 2 or medium
+priority.
+.El
+.Sh NOTES
+A change of queue geometry (maximum message size and/or maximum number of
+messages) requires destroying and re-creating the queue.
+As a safety feature,
+the create subcommand refuses to destroy a non-empty queue.
+If you use the rm subcommand to destroy a queue, any queued messages are lost.
+To avoid down-time when altering queue attributes, consider creating a new
+queue and configure reading applications to drain both new and old queues.
+Retire the old queue once all writers have been updated to write to the new
+queue.
+.Sh EXIT STATUS
+.Ex -std
+.Bl -bullet
+.It
+EX_NOTAVAILABLE usually means the mqueuefs kernel module is not loaded.
+.It
+EX_USAGE reports one or more incorrect parameters.
+.El
+.Sh EXAMPLES
+.Bl -bullet
+.It
+To retrieve the current message from a named queue,
+.Pa /1 ,
+use the command
+.Dl "posixmqcontrol recv -q /1"
+.It
+To create a queue with the name
+.Pa /2
+with maximum message size 100 and maximum queue depth 10,
+use the command
+.Dl "posixmqcontrol create -q /2 -s 100 -d 10"
+.It
+To send a message to a queue with the name
+.Pa /3
+use the command
+.Dl "posixmqcontrol send -q /3 -c 'some choice words.'"
+.It
+To examine attributes of a queue named
+.Pa /4
+use the command
+.Dl "posixmqcontrol info -q /4"
+.El
+.Sh SEE ALSO
+.Xr mq_getattr 2 ,
+.Xr mq_open 2 ,
+.Xr mq_receive 2 ,
+.Xr mq_send 2 ,
+.Xr mq_setattr 2 ,
+.Xr mq_unlink 2 ,
+.Xr mqueuefs 4
+.Sh BUGS
+mq_timedsend and mq_timedrecv are not implemented.
+info reports a worst-case estimate for QSIZE.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 14.1 .
+.Sh AUTHORS
+The
+.Nm
+command and this manual page were written by
+.An Rick Parrish Aq Mt unitrunker@unitrunker.net.
diff --git a/usr.bin/posixmqcontrol/posixmqcontrol.c b/usr.bin/posixmqcontrol/posixmqcontrol.c
new file mode 100644
index 000000000000..c965b41a1dfb
--- /dev/null
+++ b/usr.bin/posixmqcontrol/posixmqcontrol.c
@@ -0,0 +1,924 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Rick Parrish <unitrunker@unitrunker.net>.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/queue.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <mqueue.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+struct Creation {
+ /* true if the queue exists. */
+ bool exists;
+ /* true if a mode value was specified. */
+ bool set_mode;
+ /* access mode with rwx permission bits. */
+ mode_t mode;
+ /* maximum queue depth. default to an invalid depth. */
+ long depth;
+ /* maximum message size. default to an invalid size. */
+ long size;
+ /* true for blocking I/O and false for non-blocking I/O. */
+ bool block;
+ /* true if a group ID was specified. */
+ bool set_group;
+ /* group ID. */
+ gid_t group;
+ /* true if a user ID was specified. */
+ bool set_user;
+ /* user ID. */
+ uid_t user;
+};
+
+struct element {
+ STAILQ_ENTRY(element) links;
+ const char *text;
+};
+
+static struct element *
+malloc_element(const char *context)
+{
+ struct element *item = malloc(sizeof(struct element));
+
+ if (item == NULL)
+ /* the only non-EX_* prefixed exit code. */
+ err(1, "malloc(%s)", context);
+ return (item);
+}
+
+static STAILQ_HEAD(tqh, element)
+ queues = STAILQ_HEAD_INITIALIZER(queues),
+ contents = STAILQ_HEAD_INITIALIZER(contents);
+/* send defaults to medium priority. */
+static long priority = MQ_PRIO_MAX / 2;
+static struct Creation creation = {
+ .exists = false,
+ .set_mode = false,
+ .mode = 0755,
+ .depth = -1,
+ .size = -1,
+ .block = true,
+ .set_group = false,
+ .group = 0,
+ .set_user = false,
+ .user = 0
+};
+static const mqd_t fail = (mqd_t)-1;
+static const mode_t accepted_mode_bits =
+ S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISTXT;
+
+/* OPTIONS parsing utilitarian */
+
+static void
+parse_long(const char *text, long *capture, const char *knob, const char *name)
+{
+ char *cursor = NULL;
+ long value = strtol(text, &cursor, 10);
+
+ if (cursor > text && *cursor == 0) {
+ *capture = value;
+ } else {
+ warnx("%s %s invalid format [%s].", knob, name, text);
+ }
+}
+
+static void
+parse_unsigned(const char *text, bool *set,
+ unsigned *capture, const char *knob, const char *name)
+{
+ char *cursor = NULL;
+ unsigned value = strtoul(text, &cursor, 8);
+
+ if (cursor > text && *cursor == 0) {
+ *set = true;
+ *capture = value;
+ } else {
+ warnx("%s %s format [%s] ignored.", knob, name, text);
+ }
+}
+
+static bool
+sane_queue(const char *queue)
+{
+ int size = 0;
+
+ if (queue[size] != '/') {
+ warnx("queue name [%-.*s] must start with '/'.", NAME_MAX, queue);
+ return (false);
+ }
+
+ for (size++; queue[size] != 0 && size < NAME_MAX; size++) {
+ if (queue[size] == '/') {
+ warnx("queue name [%-.*s] - only one '/' permitted.",
+ NAME_MAX, queue);
+ return (false);
+ }
+ }
+
+ if (size == NAME_MAX && queue[size] != 0) {
+ warnx("queue name [%-.*s...] may not be longer than %d.",
+ NAME_MAX, queue, NAME_MAX);
+ return (false);
+ }
+ return (true);
+}
+
+/* OPTIONS parsers */
+
+static void
+parse_block(const char *text)
+{
+ if (strcmp(text, "true") == 0 || strcmp(text, "yes") == 0) {
+ creation.block = true;
+ } else if (strcmp(text, "false") == 0 || strcmp(text, "no") == 0) {
+ creation.block = false;
+ } else {
+ char *cursor = NULL;
+ long value = strtol(text, &cursor, 10);
+ if (cursor > text) {
+ creation.block = value != 0;
+ } else {
+ warnx("bad -b block format [%s] ignored.", text);
+ }
+ }
+}
+
+static void
+parse_content(const char *content)
+{
+ struct element *n1 = malloc_element("content");
+
+ n1->text = content;
+ STAILQ_INSERT_TAIL(&contents, n1, links);
+}
+
+static void
+parse_depth(const char *text)
+{
+ parse_long(text, &creation.depth, "-d", "depth");
+}
+
+static void
+parse_group(const char *text)
+{
+ struct group *entry = getgrnam(text);
+
+ if (entry == NULL) {
+ parse_unsigned(text, &creation.set_group,
+ &creation.group, "-g", "group");
+ } else {
+ creation.set_group = true;
+ creation.group = entry->gr_gid;
+ }
+}
+
+static void
+parse_mode(const char *text)
+{
+ char *cursor = NULL;
+ long value = strtol(text, &cursor, 8);
+
+ // verify only accepted mode bits are set.
+ if (cursor > text && *cursor == 0 && (value & accepted_mode_bits) == value) {
+ creation.set_mode = true;
+ creation.mode = (mode_t)value;
+ } else {
+ warnx("impossible -m mode value [%s] ignored.", text);
+ }
+}
+
+static void
+parse_priority(const char *text)
+{
+ char *cursor = NULL;
+ long value = strtol(text, &cursor, 10);
+
+ if (cursor > text && *cursor == 0) {
+ if (value >= 0 && value < MQ_PRIO_MAX) {
+ priority = value;
+ } else {
+ warnx("bad -p priority range [%s] ignored.", text);
+ }
+ } else {
+ warnx("bad -p priority format [%s] ignored.", text);
+ }
+}
+
+static void
+parse_queue(const char *queue)
+{
+ if (sane_queue(queue)) {
+ struct element *n1 = malloc_element("queue name");
+
+ n1->text = queue;
+ STAILQ_INSERT_TAIL(&queues, n1, links);
+ }
+}
+
+static void
+parse_single_queue(const char *queue)
+{
+ if (sane_queue(queue)) {
+ if (STAILQ_EMPTY(&queues)) {
+ struct element *n1 = malloc_element("queue name");
+
+ n1->text = queue;
+ STAILQ_INSERT_TAIL(&queues, n1, links);
+ } else
+ warnx("ignoring extra -q queue [%s].", queue);
+ }
+}
+
+static void
+parse_size(const char *text)
+{
+ parse_long(text, &creation.size, "-s", "size");
+}
+
+static void
+parse_user(const char *text)
+{
+ struct passwd *entry = getpwnam(text);
+ if (entry == NULL) {
+ parse_unsigned(text, &creation.set_user,
+ &creation.user, "-u", "user");
+ } else {
+ creation.set_user = true;
+ creation.user = entry->pw_uid;
+ }
+}
+
+/* OPTIONS validators */
+
+static bool
+validate_always_true(void)
+{
+ return (true);
+}
+
+static bool
+validate_content(void)
+{
+ bool valid = !STAILQ_EMPTY(&contents);
+
+ if (!valid)
+ warnx("no content to send.");
+ return (valid);
+}
+
+static bool
+validate_depth(void)
+{
+ bool valid = creation.exists || creation.depth > 0;
+
+ if (!valid)
+ warnx("-d maximum queue depth not provided.");
+ return (valid);
+}
+
+static bool
+validate_queue(void)
+{
+ bool valid = !STAILQ_EMPTY(&queues);
+
+ if (!valid)
+ warnx("missing -q, or no sane queue name given.");
+ return (valid);
+}
+
+static bool
+validate_single_queue(void)
+{
+ bool valid = !STAILQ_EMPTY(&queues) &&
+ STAILQ_NEXT(STAILQ_FIRST(&queues), links) == NULL;
+
+ if (!valid)
+ warnx("expected one queue.");
+ return (valid);
+}
+
+static bool
+validate_size(void)
+{
+ bool valid = creation.exists || creation.size > 0;
+
+ if (!valid)
+ warnx("-s maximum message size not provided.");
+ return (valid);
+}
+
+/* OPTIONS table handling. */
+
+struct Option {
+ /* points to array of string pointers terminated by a null pointer. */
+ const char **pattern;
+ /* parse argument. */
+ void (*parse)(const char *);
+ /*
+ * displays an error and returns false if this parameter is not valid.
+ * returns true otherwise.
+ */
+ bool (*validate)(void);
+};
+
+/*
+ * parse options by table.
+ * index - current index into argv list.
+ * argc, argv - command line parameters.
+ * options - null terminated list of pointers to options.
+ */
+static void
+parse_options(int index, int argc,
+ const char *argv[], const struct Option **options)
+{
+ while ((index + 1) < argc) {
+ const struct Option **cursor = options;
+ bool match = false;
+ while (*cursor != NULL && !match) {
+ const struct Option *option = cursor[0];
+ const char **pattern = option->pattern;
+
+ while (*pattern != NULL && !match) {
+ const char *knob = *pattern;
+
+ match = strcmp(knob, argv[index]) == 0;
+ if (!match)
+ pattern++;
+ }
+
+ if (match) {
+ option->parse(argv[index + 1]);
+ index += 2;
+ break;
+ }
+ cursor++;
+ }
+
+ if (!match && index < argc) {
+ warnx("skipping [%s].", argv[index]);
+ index++;
+ }
+ }
+
+ if (index < argc) {
+ warnx("skipping [%s].", argv[index]);
+ }
+}
+
+/* options - null terminated list of pointers to options. */
+static bool
+validate_options(const struct Option **options)
+{
+ bool valid = true;
+
+ while (*options != NULL) {
+ const struct Option *option = options[0];
+
+ if (!option->validate())
+ valid = false;
+ options++;
+ }
+ return (valid);
+}
+
+/* SUBCOMMANDS */
+
+/*
+ * queue: name of queue to be created.
+ * q_creation: creation parameters (copied by value).
+ */
+static int
+create(const char *queue, struct Creation q_creation)
+{
+ int flags = O_RDWR;
+ struct mq_attr stuff = {
+ .mq_curmsgs = 0,
+ .mq_maxmsg = q_creation.depth,
+ .mq_msgsize = q_creation.size,
+ .mq_flags = 0
+ };
+
+ if (!q_creation.block) {
+ flags |= O_NONBLOCK;
+ stuff.mq_flags |= O_NONBLOCK;
+ }
+
+ mqd_t handle = mq_open(queue, flags);
+ q_creation.exists = handle != fail;
+ if (!q_creation.exists) {
+ /*
+ * apply size and depth checks here.
+ * if queue exists, we can default to existing depth and size.
+ * but for a new queue, we require that input.
+ */
+ if (validate_size() && validate_depth()) {
+ /* no need to re-apply mode. */
+ q_creation.set_mode = false;
+ flags |= O_CREAT;
+ handle = mq_open(queue, flags, q_creation.mode, &stuff);
+ }
+ }
+
+ if (handle == fail) {
+ errno_t what = errno;
+
+ warnc(what, "mq_open(create)");
+ return (what);
+ }
+
+#ifdef __FreeBSD__
+ /*
+ * undocumented.
+ * See https://bugs.freebsd.org/bugzilla//show_bug.cgi?id=273230
+ */
+ int fd = mq_getfd_np(handle);
+
+ if (fd < 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_getfd_np(create)");
+ mq_close(handle);
+ return (what);
+ }
+ struct stat status = {0};
+ int result = fstat(fd, &status);
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "fstat(create)");
+ mq_close(handle);
+ return (what);
+ }
+
+ /* do this only if group and / or user given. */
+ if (q_creation.set_group || q_creation.set_user) {
+ q_creation.user =
+ q_creation.set_user ? q_creation.user : status.st_uid;
+ q_creation.group =
+ q_creation.set_group ? q_creation.group : status.st_gid;
+ result = fchown(fd, q_creation.user, q_creation.group);
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "fchown(create)");
+ mq_close(handle);
+ return (what);
+ }
+ }
+
+ /* do this only if altering mode of an existing queue. */
+ if (q_creation.exists && q_creation.set_mode &&
+ q_creation.mode != (status.st_mode & accepted_mode_bits)) {
+ result = fchmod(fd, q_creation.mode);
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "fchmod(create)");
+ mq_close(handle);
+ return (what);
+ }
+ }
+#endif /* __FreeBSD__ */
+
+ return (mq_close(handle));
+}
+
+/* queue: name of queue to be removed. */
+static int
+rm(const char *queue)
+{
+ int result = mq_unlink(queue);
+
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_unlink");
+ return (what);
+ }
+
+ return (result);
+}
+
+/* Return the display character for non-zero mode. */
+static char
+dual(mode_t mode, char display)
+{
+ return (mode != 0 ? display : '-');
+}
+
+/* Select one of four display characters based on mode and modifier. */
+static char
+quad(mode_t mode, mode_t modifier)
+{
+ static const char display[] = "-xSs";
+ unsigned index = 0;
+ if (mode != 0)
+ index += 1;
+ if (modifier)
+ index += 2;
+ return (display[index]);
+}
+
+/* queue: name of queue to be inspected. */
+static int
+info(const char *queue)
+{
+ mqd_t handle = mq_open(queue, O_RDONLY);
+
+ if (handle == fail) {
+ errno_t what = errno;
+
+ warnc(what, "mq_open(info)");
+ return (what);
+ }
+
+ struct mq_attr actual;
+
+ int result = mq_getattr(handle, &actual);
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_getattr(info)");
+ return (what);
+ }
+
+ fprintf(stdout,
+ "queue: '%s'\nQSIZE: %lu\nMSGSIZE: %ld\nMAXMSG: %ld\n"
+ "CURMSG: %ld\nflags: %03ld\n",
+ queue, actual.mq_msgsize * actual.mq_curmsgs, actual.mq_msgsize,
+ actual.mq_maxmsg, actual.mq_curmsgs, actual.mq_flags);
+#ifdef __FreeBSD__
+
+ int fd = mq_getfd_np(handle);
+ struct stat status;
+
+ result = fstat(fd, &status);
+ if (result != 0) {
+ warn("fstat(info)");
+ } else {
+ mode_t mode = status.st_mode;
+
+ fprintf(stdout, "UID: %u\nGID: %u\n", status.st_uid, status.st_gid);
+ fprintf(stdout, "MODE: %c%c%c%c%c%c%c%c%c%c\n",
+ dual(mode & S_ISVTX, 's'),
+ dual(mode & S_IRUSR, 'r'),
+ dual(mode & S_IWUSR, 'w'),
+ quad(mode & S_IXUSR, mode & S_ISUID),
+ dual(mode & S_IRGRP, 'r'),
+ dual(mode & S_IWGRP, 'w'),
+ quad(mode & S_IXGRP, mode & S_ISGID),
+ dual(mode & S_IROTH, 'r'),
+ dual(mode & S_IWOTH, 'w'),
+ dual(mode & S_IXOTH, 'x'));
+ }
+#endif /* __FreeBSD__ */
+
+ return (mq_close(handle));
+}
+
+/* queue: name of queue to drain one message. */
+static int
+recv(const char *queue)
+{
+ mqd_t handle = mq_open(queue, O_RDONLY);
+
+ if (handle == fail) {
+ errno_t what = errno;
+
+ warnc(what, "mq_open(recv)");
+ return (what);
+ }
+
+ struct mq_attr actual;
+
+ int result = mq_getattr(handle, &actual);
+
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_attr(recv)");
+ mq_close(handle);
+ return (what);
+ }
+
+ char *text = malloc(actual.mq_msgsize + 1);
+ unsigned q_priority = 0;
+
+ memset(text, 0, actual.mq_msgsize + 1);
+ result = mq_receive(handle, text, actual.mq_msgsize, &q_priority);
+ if (result < 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_receive");
+ mq_close(handle);
+ return (what);
+ }
+
+ fprintf(stdout, "[%u]: %-*.*s\n", q_priority, result, result, text);
+ return (mq_close(handle));
+}
+
+/*
+ * queue: name of queue to send one message.
+ * text: message text.
+ * q_priority: message priority in range of 0 to 63.
+ */
+static int
+send(const char *queue, const char *text, unsigned q_priority)
+{
+ mqd_t handle = mq_open(queue, O_WRONLY);
+
+ if (handle == fail) {
+ errno_t what = errno;
+
+ warnc(what, "mq_open(send)");
+ return (what);
+ }
+
+ struct mq_attr actual;
+
+ int result = mq_getattr(handle, &actual);
+
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_attr(send)");
+ mq_close(handle);
+ return (what);
+ }
+
+ int size = strlen(text);
+
+ if (size > actual.mq_msgsize) {
+ warnx("truncating message to %ld characters.\n", actual.mq_msgsize);
+ size = actual.mq_msgsize;
+ }
+
+ result = mq_send(handle, text, size, q_priority);
+
+ if (result != 0) {
+ errno_t what = errno;
+
+ warnc(what, "mq_send");
+ mq_close(handle);
+ return (what);
+ }
+
+ return (mq_close(handle));
+}
+
+static void
+usage(FILE *file)
+{
+ fprintf(file,
+ "usage:\n\tposixmqcontrol [rm|info|recv] -q <queue>\n"
+ "\tposixmqcontrol create -q <queue> -s <maxsize> -d <maxdepth> "
+ "[ -m <mode> ] [ -b <block> ] [-u <uid> ] [ -g <gid> ]\n"
+ "\tposixmqcontrol send -q <queue> -c <content> "
+ "[-p <priority> ]\n");
+}
+
+/* end of SUBCOMMANDS */
+
+#define _countof(arg) ((sizeof(arg)) / (sizeof((arg)[0])))
+
+/* convert an errno style error code to a sysexits code. */
+static int
+grace(int err_number)
+{
+ static const int xlat[][2] = {
+ /* generally means the mqueuefs driver is not loaded. */
+ {ENOSYS, EX_UNAVAILABLE},
+ /* no such queue name. */
+ {ENOENT, EX_OSFILE},
+ {EIO, EX_IOERR},
+ {ENODEV, EX_IOERR},
+ {ENOTSUP, EX_TEMPFAIL},
+ {EAGAIN, EX_IOERR},
+ {EPERM, EX_NOPERM},
+ {EACCES, EX_NOPERM},
+ {0, EX_OK}
+ };
+
+ for (unsigned i = 0; i < _countof(xlat); i++) {
+ if (xlat[i][0] == err_number)
+ return (xlat[i][1]);
+ }
+
+ return (EX_OSERR);
+}
+
+/* OPTIONS tables */
+
+/* careful: these 'names' arrays must be terminated by a null pointer. */
+static const char *names_queue[] = {"-q", "--queue", "-t", "--topic", NULL};
+static const struct Option option_queue = {
+ .pattern = names_queue,
+ .parse = parse_queue,
+ .validate = validate_queue};
+static const struct Option option_single_queue = {
+ .pattern = names_queue,
+ .parse = parse_single_queue,
+ .validate = validate_single_queue};
+static const char *names_depth[] = {"-d", "--depth", "--maxmsg", NULL};
+static const struct Option option_depth = {
+ .pattern = names_depth,
+ .parse = parse_depth,
+ .validate = validate_always_true};
+static const char *names_size[] = {"-s", "--size", "--msgsize", NULL};
+static const struct Option option_size = {
+ .pattern = names_size,
+ .parse = parse_size,
+ .validate = validate_always_true};
+static const char *names_block[] = {"-b", "--block", NULL};
+static const struct Option option_block = {
+ .pattern = names_block,
+ .parse = parse_block,
+ .validate = validate_always_true};
+static const char *names_content[] = {
+ "-c", "--content", "--data", "--message", NULL};
+static const struct Option option_content = {
+ .pattern = names_content,
+ .parse = parse_content,
+ .validate = validate_content};
+static const char *names_priority[] = {"-p", "--priority", NULL};
+static const struct Option option_priority = {
+ .pattern = names_priority,
+ .parse = parse_priority,
+ .validate = validate_always_true};
+static const char *names_mode[] = {"-m", "--mode", NULL};
+static const struct Option option_mode = {
+ .pattern = names_mode,
+ .parse = parse_mode,
+ .validate = validate_always_true};
+static const char *names_group[] = {"-g", "--gid", NULL};
+static const struct Option option_group = {
+ .pattern = names_group,
+ .parse = parse_group,
+ .validate = validate_always_true};
+static const char *names_user[] = {"-u", "--uid", NULL};
+static const struct Option option_user = {
+ .pattern = names_user,
+ .parse = parse_user,
+ .validate = validate_always_true};
+
+/* careful: these arrays must be terminated by a null pointer. */
+#ifdef __FreeBSD__
+static const struct Option *create_options[] = {
+ &option_queue, &option_depth, &option_size, &option_block,
+ &option_mode, &option_group, &option_user, NULL};
+#else /* !__FreeBSD__ */
+static const struct Option *create_options[] = {
+ &option_queue, &option_depth, &option_size, &option_block,
+ &option_mode, NULL};
+#endif /* __FreeBSD__ */
+static const struct Option *info_options[] = {&option_queue, NULL};
+static const struct Option *unlink_options[] = {&option_queue, NULL};
+static const struct Option *recv_options[] = {&option_single_queue, NULL};
+static const struct Option *send_options[] = {
+ &option_queue, &option_content, &option_priority, NULL};
+
+int
+main(int argc, const char *argv[])
+{
+ STAILQ_INIT(&queues);
+ STAILQ_INIT(&contents);
+
+ if (argc > 1) {
+ const char *verb = argv[1];
+ int index = 2;
+
+ if (strcmp("create", verb) == 0 || strcmp("attr", verb) == 0) {
+ parse_options(index, argc, argv, create_options);
+ if (validate_options(create_options)) {
+ int worst = 0;
+ struct element *itq;
+
+ STAILQ_FOREACH(itq, &queues, links) {
+ const char *queue = itq->text;
+
+ int result = create(queue, creation);
+ if (result != 0)
+ worst = result;
+ }
+
+ return (grace(worst));
+ }
+
+ return (EX_USAGE);
+ } else if (strcmp("info", verb) == 0 || strcmp("cat", verb) == 0) {
+ parse_options(index, argc, argv, info_options);
+ if (validate_options(info_options)) {
+ int worst = 0;
+ struct element *itq;
+
+ STAILQ_FOREACH(itq, &queues, links) {
+ const char *queue = itq->text;
+ int result = info(queue);
+
+ if (result != 0)
+ worst = result;
+ }
+
+ return (grace(worst));
+ }
+
+ return (EX_USAGE);
+ } else if (strcmp("send", verb) == 0) {
+ parse_options(index, argc, argv, send_options);
+ if (validate_options(send_options)) {
+ int worst = 0;
+ struct element *itq;
+
+ STAILQ_FOREACH(itq, &queues, links) {
+ const char *queue = itq->text;
+ struct element *itc;
+
+ STAILQ_FOREACH(itc, &contents, links) {
+ const char *content = itc->text;
+ int result = send(queue, content, priority);
+
+ if (result != 0)
+ worst = result;
+ }
+ }
+
+ return (grace(worst));
+ }
+ return (EX_USAGE);
+ } else if (strcmp("recv", verb) == 0 ||
+ strcmp("receive", verb) == 0) {
+ parse_options(index, argc, argv, recv_options);
+ if (validate_options(recv_options)) {
+ const char *queue = STAILQ_FIRST(&queues)->text;
+ int worst = recv(queue);
+
+ return (grace(worst));
+ }
+
+ return (EX_USAGE);
+ } else if (strcmp("unlink", verb) == 0 ||
+ strcmp("rm", verb) == 0) {
+ parse_options(index, argc, argv, unlink_options);
+ if (validate_options(unlink_options)) {
+ int worst = 0;
+ struct element *itq;
+
+ STAILQ_FOREACH(itq, &queues, links) {
+ const char *queue = itq->text;
+ int result = rm(queue);
+
+ if (result != 0)
+ worst = result;
+ }
+
+ return (grace(worst));
+ }
+
+ return (EX_USAGE);
+ } else if (strcmp("help", verb) == 0) {
+ usage(stdout);
+ return (EX_OK);
+ } else {
+ warnx("Unknown verb [%s]", verb);
+ return (EX_USAGE);
+ }
+ }
+
+ usage(stdout);
+ return (EX_OK);
+}
diff --git a/usr.bin/posixmqcontrol/posixmqcontroltest8qs.sh b/usr.bin/posixmqcontrol/posixmqcontroltest8qs.sh
new file mode 100644
index 000000000000..1048c373bd12
--- /dev/null
+++ b/usr.bin/posixmqcontrol/posixmqcontroltest8qs.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# testing create, info, and send operations applied to multiple queue names at once.
+# recv accepts a single queue name so draining is done one queue at a time.
+subject='posixmqcontrol'
+prefix='/posixmqcontroltest'
+
+list=
+for i in 1 2 3 4 5 6 7 8
+do
+ topic="${prefix}${i}"
+ ${subject} info -q "${topic}" 2>/dev/null
+ if [ $? == 0 ]; then
+ echo "sorry, $topic exists."
+ exit 1
+ fi
+ list="${list} -q ${topic}"
+done
+
+${subject} create -d 2 -s 64 ${list}
+if [ $? != 0 ]; then
+ exit 1
+fi
+
+ignore=$( ${subject} info ${list} )
+if [ $? != 0 ]; then
+ exit 1
+fi
+
+${subject} send -c 'this message sent to all listed queues.' ${list}
+if [ $? != 0 ]; then
+ exit 1
+fi
+
+# we can only drain one message at a time.
+for i in 1 2 3 4 5 6 7 8
+do
+ topic="${prefix}${i}"
+ ignore=$( ${subject} recv -q "${topic}" )
+ if [ $? != 0 ]; then
+ exit 1
+ fi
+done
+
+${subject} rm ${list}
+if [ $? == 0 ]; then
+ echo "Pass!"
+ exit 0
+fi
+
+exit 1
diff --git a/usr.bin/posixmqcontrol/posixmqcontroltest8x64.sh b/usr.bin/posixmqcontrol/posixmqcontroltest8x64.sh
new file mode 100644
index 000000000000..124b33123664
--- /dev/null
+++ b/usr.bin/posixmqcontrol/posixmqcontroltest8x64.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+# exercises create, info, send and recv subcommands.
+
+subject='posixmqcontrol'
+topic='/test123'
+
+${subject} info -q "$topic" 2>/dev/null
+if [ $? == 0 ]; then
+ echo "sorry, $topic exists."
+ exit 1
+fi
+
+# create trivial queue that can hold 8 messages of 64 bytes each.
+${subject} create -q "$topic" -s 64 -d 8
+if [ $? != 0 ]; then
+ exit 1
+fi
+
+info=$(${subject} info -q "$topic")
+if [ $? != 0 ]; then
+ exit 1
+fi
+expected='MSGSIZE: 64'
+actual=$(echo "${info}" | grep 'MSGSIZE: ')
+if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+fi
+expected='MAXMSG: 8'
+actual=$(echo "${info}" | grep 'MAXMSG: ')
+if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+fi
+expected='CURMSG: 0'
+actual=$(echo "${info}" | grep 'CURMSG: ')
+if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+fi
+
+# write eight messages of increasing priority.
+for i in 1 2 3 4 5 6 7 8
+do
+ ${subject} send -q "$topic" -c "message $i" -p "$i"
+ if [ $? != 0 ]; then
+ exit 1
+ fi
+done
+
+info=$(${subject} info -q "$topic")
+if [ $? != 0 ]; then
+ exit
+fi
+expected='CURMSG: 8'
+actual=$(echo "${info}" | grep 'CURMSG: ')
+if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+fi
+
+# expect the eight messages to appear in priority order.
+for i in 8 7 6 5 4 3 2 1
+do
+ expected='['"$i"']: message '"$i"
+ actual=$(${subject} recv -q "$topic")
+ if [ $? != 0 ]; then
+ exit
+ fi
+ if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+ fi
+done
+
+info=$(${subject} info -q "$topic")
+if [ $? != 0 ]; then
+ exit 1
+fi
+expected='CURMSG: 0'
+actual=$(echo "${info}" | grep 'CURMSG: ')
+if [ "$expected" != "$actual" ]; then
+ echo "EXPECTED: $expected"
+ echo " ACTUAL: $actual"
+ exit 1
+fi
+
+${subject} rm -q "$topic"
+if [ $? == 0 ]; then
+ echo "Pass!"
+ exit 0
+fi
+
+exit 1
diff --git a/usr.bin/posixmqcontrol/posixmqcontroltestsane.sh b/usr.bin/posixmqcontrol/posixmqcontroltestsane.sh
new file mode 100644
index 000000000000..5ddb96cdb1b0
--- /dev/null
+++ b/usr.bin/posixmqcontrol/posixmqcontroltestsane.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# test for 'insane' queue names.
+
+subject='posixmqcontrol'
+
+# does sanity check enforce leading slash?
+${subject} info -q missing.leading.slash 2>/dev/null
+code=$?
+if [ $code != 64 ]; then
+ exit 1
+fi
+
+# does sanity check enforce one and only one slash?
+${subject} info -q /to/many/slashes 2>/dev/null
+code=$?
+if [ $code != 64 ]; then
+ exit 1
+fi
+
+# does sanity check enforce length limit?
+${subject} info -q /this.queue.name.is.way.too.long.at.more.than.one.thousand.and.twenty.four.characters.long.because.nobody.needs.to.type.out.something.this.ridiculously.long.than.just.goes.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on.and.on 2>/dev/null
+code=$?
+if [ $code != 64 ]; then
+ exit 1
+fi
+
+echo "Pass!"
+exit 0
diff --git a/usr.bin/posixshmcontrol/Makefile b/usr.bin/posixshmcontrol/Makefile
new file mode 100644
index 000000000000..dc3d268f4a74
--- /dev/null
+++ b/usr.bin/posixshmcontrol/Makefile
@@ -0,0 +1,4 @@
+PROG= posixshmcontrol
+LIBADD= jail util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/posixshmcontrol/posixshmcontrol.1 b/usr.bin/posixshmcontrol/posixshmcontrol.1
new file mode 100644
index 000000000000..bfa43a0bbeab
--- /dev/null
+++ b/usr.bin/posixshmcontrol/posixshmcontrol.1
@@ -0,0 +1,175 @@
+.\" Copyright (c) 2019 The FreeBSD Foundation
+.\"
+.\" This documentation was written by
+.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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 AUTHORS 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 AUTHORS 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 May 25, 2023
+.Dt POSIXSHMCONTROL 1
+.Os
+.Sh NAME
+.Nm posixshmcontrol
+.Nd Control POSIX shared memory segments
+.Sh SYNOPSIS
+.Nm
+.Ar create
+.Op Fl l Ar pagesize
+.Op Fl m Ar mode
+.Op Pa path \&...
+.Nm
+.Ar rm
+.Op Pa path \&...
+.Nm
+.Ar ls
+.Op Fl h
+.Op Fl n
+.Op Fl j Ar jail
+.Nm
+.Ar dump
+.Op Pa path \&...
+.Nm
+.Ar stat
+.Op Fl h
+.Op Fl n
+.Op Pa path \&...
+.Nm
+.Ar truncate
+.Op Fl s Ar length
+.Op Pa path \&...
+.Sh DESCRIPTION
+The
+.Nm
+command manipulates the named POSIX shared memory segments.
+It allows inspecting existing segments, dumping their metadata or contents,
+and unlinking them.
+.Pp
+Unlinking removes the name from the system and, when the last process
+unmaps the segment and closes file descriptor pointing to the segment,
+frees underlying memory.
+.Pp
+The number of hard links as displayed by the
+.Ic stat
+subcommand, is equal to the number of references to the underlying VM
+object.
+It is almost always equal to the number of mappings +1, except
+for transient references.
+.Pp
+The following subcommands are provided:
+.Bl -tag -width truncate
+.It Ic create
+Create segments with the specified paths, if they do not already exist.
+.Pp
+The optional
+.Ar pagesize
+argument specifies the size of the virtual pages used to map the
+object with
+.Xr mmap 2 .
+By default, the system page size is used, but on some platforms a
+larger page size can be specified.
+The size of an object backed by large pages must be a multiple of the
+specified page size.
+The
+.Va hw.pagesizes
+sysctl variable lists the available page sizes.
+.Pp
+The optional numerical
+.Ar mode
+argument specifies the initial access mode.
+.It Ic rm
+Unlink the paths specified.
+.It Ic ls
+List all linked named shared memory segments visible to the caller.
+For each segment, the user and group owner, size, and path are displayed.
+The
+.Fl j
+option limits the output to segments within the specified
+.Ar jail
+name or id.
+.It Ic dump
+Output raw bytes values from the segment to standard output.
+.It Ic stat
+Print metadata for the specified path, in the format similar to the
+.Xr stat 1
+utility.
+.It Ic truncate
+Change the length of the segments.
+Argument to the
+.Fl s
+option specifies new length.
+The human-friendly 'k', 'm', 'g' suffixes can be used, see
+.Xr expand_number 3 .
+If the option is not specified, assumed length is zero.
+.El
+.Pp
+For some commands, the following options may be provided:
+.Bl -tag -width XXX
+.It Fl h
+If specified, requests human-readable display of size, see
+.Xr humanize_number 3 .
+.It Fl n
+Prevent translation of owner and group into symbolic names
+using name-switch services, instead the raw numeric values are printed.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Bl -bullet
+.It
+To show content of the shared memory segment with the path
+.Pa /1 ,
+use the command
+.Dl "posixshmcontrol dump /1 | hexdump -C"
+.It
+To create a segment with the path
+.Pa /2
+and then enlarge it to 1M, use the sequence of commands
+.Dl "posixshmcontrol create /2"
+.Dl "posixshmcontrol truncate -s 1m /2"
+.El
+.Sh SEE ALSO
+.Xr hexdump 1 ,
+.Xr stat 1 ,
+.Xr ftruncate 2 ,
+.Xr mmap 2 ,
+.Xr read 2 ,
+.Xr shm_open 2 ,
+.Xr shm_unlink 2 ,
+.Xr stat 2 ,
+.Xr expand_number 3 ,
+.Xr humanize_number 3 ,
+.Xr shm_create_largepage 3 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 12.1 .
+.Sh AUTHORS
+The
+.Nm
+command and this manual page were written by
+.An Konstantin Belousov Aq Mt kib@freebsd.org
+under sponsorship from The
+.Fx
+Foundation.
diff --git a/usr.bin/posixshmcontrol/posixshmcontrol.c b/usr.bin/posixshmcontrol/posixshmcontrol.c
new file mode 100644
index 000000000000..fde03e495d07
--- /dev/null
+++ b/usr.bin/posixshmcontrol/posixshmcontrol.c
@@ -0,0 +1,592 @@
+/*-
+ * Copyright (c) 2019 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/filio.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <err.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <jail.h>
+#include <libutil.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "Usage:\n"
+ "posixshmcontrol create [-m <mode>] [-l <largepage>] <path> ...\n"
+ "posixshmcontrol rm <path> ...\n"
+ "posixshmcontrol ls [-h] [-n] [-j jail]\n"
+ "posixshmcontrol dump <path> ...\n"
+ "posixshmcontrol stat [-h] [-n] <path> ...\n"
+ "posixshmcontrol truncate [-s <newlen>] <path> ...\n");
+}
+
+static int
+create_one_shm(const char *path, long mode, int idx)
+{
+ int fd;
+
+ if (idx == -1) {
+ fd = shm_open(path, O_RDWR | O_CREAT, mode);
+ if (fd == -1) {
+ warn("create %s", path);
+ return (1);
+ }
+ } else {
+ fd = shm_create_largepage(path, O_RDWR, idx,
+ SHM_LARGEPAGE_ALLOC_DEFAULT, mode);
+ if (fd == -1) {
+ warn("shm_create_largepage %s psind %d", path, idx);
+ return (1);
+ }
+ }
+ close(fd);
+ return (0);
+}
+
+static int
+create_shm(int argc, char **argv)
+{
+ char *end;
+ size_t *pagesizes;
+ long mode;
+ uint64_t pgsz;
+ int c, i, idx, pn, ret, ret1;
+ bool printed;
+
+ mode = 0600;
+ idx = -1;
+ while ((c = getopt(argc, argv, "l:m:")) != -1) {
+ switch (c) {
+ case 'm':
+ errno = 0;
+ mode = strtol(optarg, &end, 0);
+ if (mode == 0 && errno != 0)
+ err(1, "mode");
+ if (*end != '\0')
+ errx(1, "non-integer mode");
+ break;
+ case 'l':
+ if (expand_number(optarg, &pgsz) == -1)
+ err(1, "size");
+ pn = getpagesizes(NULL, 0);
+ if (pn == -1)
+ err(1, "getpagesizes");
+ pagesizes = malloc(sizeof(size_t) * pn);
+ if (pagesizes == NULL)
+ err(1, "malloc");
+ if (getpagesizes(pagesizes, pn) == -1)
+ err(1, "gtpagesizes");
+ for (idx = 0; idx < pn; idx++) {
+ if (pagesizes[idx] == pgsz)
+ break;
+ }
+ if (idx == pn) {
+ fprintf(stderr,
+ "pagesize should be superpagesize, supported sizes:");
+ printed = false;
+ for (i = 0; i < pn; i++) {
+ if (pagesizes[i] == 0 ||
+ pagesizes[i] == (size_t)
+ getpagesize())
+ continue;
+ printed = true;
+ fprintf(stderr, " %zu", pagesizes[i]);
+ }
+ if (!printed)
+ fprintf(stderr, " none");
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ if (pgsz == (uint64_t)getpagesize())
+ errx(1, "pagesize should be large");
+ free(pagesizes);
+ break;
+ case '?':
+ default:
+ usage();
+ return (2);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ usage();
+ return (2);
+ }
+
+ ret = 0;
+ for (i = 0; i < argc; i++) {
+ ret1 = create_one_shm(argv[i], mode, idx);
+ if (ret1 != 0 && ret == 0)
+ ret = ret1;
+ }
+ return (ret);
+}
+
+static int
+delete_one_shm(const char *path)
+{
+ int error, ret;
+
+ error = shm_unlink(path);
+ if (error != 0) {
+ warn("unlink of %s failed", path);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ return (ret);
+}
+
+static int
+delete_shm(int argc, char **argv)
+{
+ int i, ret, ret1;
+
+ if (argc == 1) {
+ usage();
+ return (2);
+ }
+
+ ret = 0;
+ for (i = 1; i < argc; i++) {
+ ret1 = delete_one_shm(argv[i]);
+ if (ret1 != 0 && ret == 0)
+ ret = ret1;
+ }
+ return (ret);
+}
+
+static const char listmib[] = "kern.ipc.posix_shm_list";
+
+static void
+shm_decode_mode(mode_t m, char *str)
+{
+ int i;
+
+ i = 0;
+ str[i++] = (m & S_IRUSR) != 0 ? 'r' : '-';
+ str[i++] = (m & S_IWUSR) != 0 ? 'w' : '-';
+ str[i++] = (m & S_IXUSR) != 0 ? 'x' : '-';
+ str[i++] = (m & S_IRGRP) != 0 ? 'r' : '-';
+ str[i++] = (m & S_IWGRP) != 0 ? 'w' : '-';
+ str[i++] = (m & S_IXGRP) != 0 ? 'x' : '-';
+ str[i++] = (m & S_IROTH) != 0 ? 'r' : '-';
+ str[i++] = (m & S_IWOTH) != 0 ? 'w' : '-';
+ str[i++] = (m & S_IXOTH) != 0 ? 'x' : '-';
+ str[i] = '\0';
+}
+
+static int
+list_shm(int argc, char **argv)
+{
+ char *buf, *bp, *ep, jailpath[MAXPATHLEN], sizebuf[8], str[10];
+ const char *jailparam;
+ const struct kinfo_file *kif;
+ struct stat st;
+ int c, error, fd, jid, mib[3], ret;
+ size_t len, jailpathlen, miblen;
+ bool hsize, jailed, uname;
+
+ hsize = false;
+ jailed = false;
+ uname = true;
+
+ while ((c = getopt(argc, argv, "hj:n")) != -1) {
+ switch (c) {
+ case 'h':
+ hsize = true;
+ break;
+ case 'n':
+ uname = false;
+ break;
+ case 'j':
+ jid = strtoul(optarg, &ep, 10);
+ if (ep > optarg && !*ep) {
+ jailparam = "jid";
+ jailed = jid > 0;
+ } else {
+ jailparam = "name";
+ jailed = true;
+ }
+ if (jailed) {
+ if (jail_getv(0, jailparam, optarg, "path",
+ jailpath, NULL) < 0) {
+ if (errno == ENOENT)
+ warnx("no such jail: %s", optarg);
+ else
+ warnx("%s", jail_errmsg);
+ return (1);
+ }
+ jailpathlen = strlen(jailpath);
+ jailpath[jailpathlen] = '/';
+ }
+ break;
+ default:
+ usage();
+ return (2);
+ }
+ }
+ if (argc != optind) {
+ usage();
+ return (2);
+ }
+
+ miblen = nitems(mib);
+ error = sysctlnametomib(listmib, mib, &miblen);
+ if (error == -1) {
+ warn("cannot translate %s", listmib);
+ return (1);
+ }
+ len = 0;
+ error = sysctl(mib, miblen, NULL, &len, NULL, 0);
+ if (error == -1) {
+ warn("cannot get %s length", listmib);
+ return (1);
+ }
+ len = len * 4 / 3;
+ buf = malloc(len);
+ if (buf == NULL) {
+ warn("malloc");
+ return (1);
+ }
+ error = sysctl(mib, miblen, buf, &len, NULL, 0);
+ if (error != 0) {
+ warn("reading %s", listmib);
+ ret = 1;
+ goto out;
+ }
+ ret = 0;
+ printf("MODE \tOWNER\tGROUP\tSIZE\tPATH\n");
+ for (bp = buf; bp < buf + len; bp += kif->kf_structsize) {
+ kif = (const struct kinfo_file *)(void *)bp;
+ if (kif->kf_structsize == 0)
+ break;
+ if (jailed && strncmp(kif->kf_path, jailpath, jailpathlen + 1))
+ continue;
+ fd = shm_open(kif->kf_path, O_RDONLY, 0);
+ if (fd == -1) {
+ if (errno != EACCES) {
+ warn("open %s", kif->kf_path);
+ ret = 1;
+ }
+ continue;
+ }
+ error = fstat(fd, &st);
+ close(fd);
+ if (error != 0) {
+ warn("stat %s", kif->kf_path);
+ ret = 1;
+ continue;
+ }
+ shm_decode_mode(kif->kf_un.kf_file.kf_file_mode, str);
+ printf("%s\t", str);
+ if (uname) {
+ printf("%s\t%s\t", user_from_uid(st.st_uid, 0),
+ group_from_gid(st.st_gid, 0));
+ } else {
+ printf("%d\t%d\t", st.st_uid, st.st_gid);
+ }
+ if (hsize) {
+ humanize_number(sizebuf, sizeof(sizebuf),
+ kif->kf_un.kf_file.kf_file_size, "", HN_AUTOSCALE,
+ HN_NOSPACE);
+ printf("%s\t", sizebuf);
+ } else {
+ printf("%jd\t",
+ (uintmax_t)kif->kf_un.kf_file.kf_file_size);
+ }
+ printf("%s\n", kif->kf_path);
+ }
+out:
+ free(buf);
+ return (ret);
+}
+
+static int
+read_one_shm(const char *path)
+{
+ char buf[4096];
+ ssize_t size, se;
+ int fd, ret;
+
+ ret = 1;
+ fd = shm_open(path, O_RDONLY, 0);
+ if (fd == -1) {
+ warn("open %s", path);
+ goto out;
+ }
+ for (;;) {
+ size = read(fd, buf, sizeof(buf));
+ if (size > 0) {
+ se = fwrite(buf, 1, size, stdout);
+ if (se < size) {
+ warnx("short write to stdout");
+ goto out;
+ }
+ }
+ if (size == (ssize_t)sizeof(buf))
+ continue;
+ if (size >= 0 && size < (ssize_t)sizeof(buf)) {
+ ret = 0;
+ goto out;
+ }
+ warn("read from %s", path);
+ goto out;
+ }
+out:
+ close(fd);
+ return (ret);
+}
+
+static int
+read_shm(int argc, char **argv)
+{
+ int i, ret, ret1;
+
+ if (argc == 1) {
+ usage();
+ return (2);
+ }
+
+ ret = 0;
+ for (i = 1; i < argc; i++) {
+ ret1 = read_one_shm(argv[i]);
+ if (ret1 != 0 && ret == 0)
+ ret = ret1;
+ }
+ return (ret);
+}
+
+static int
+stat_one_shm(const char *path, bool hsize, bool uname)
+{
+ char sizebuf[8];
+ struct stat st;
+ int error, fd, ret;
+ struct shm_largepage_conf conf_dummy;
+ bool largepage;
+
+ fd = shm_open(path, O_RDONLY, 0);
+ if (fd == -1) {
+ warn("open %s", path);
+ return (1);
+ }
+ ret = 0;
+ error = fstat(fd, &st);
+ if (error == -1) {
+ warn("stat %s", path);
+ ret = 1;
+ } else {
+ printf("path\t%s\n", path);
+ printf("inode\t%jd\n", (uintmax_t)st.st_ino);
+ printf("mode\t%#o\n", st.st_mode);
+ printf("nlink\t%jd\n", (uintmax_t)st.st_nlink);
+ if (uname) {
+ printf("owner\t%s\n", user_from_uid(st.st_uid, 0));
+ printf("group\t%s\n", group_from_gid(st.st_gid, 0));
+ } else {
+ printf("uid\t%d\n", st.st_uid);
+ printf("gid\t%d\n", st.st_gid);
+ }
+ if (hsize) {
+ humanize_number(sizebuf, sizeof(sizebuf),
+ st.st_size, "", HN_AUTOSCALE, HN_NOSPACE);
+ printf("size\t%s\n", sizebuf);
+ } else {
+ printf("size\t%jd\n", (uintmax_t)st.st_size);
+ }
+ printf("atime\t%ld.%09ld\n", (long)st.st_atime,
+ (long)st.st_atim.tv_nsec);
+ printf("mtime\t%ld.%09ld\n", (long)st.st_mtime,
+ (long)st.st_mtim.tv_nsec);
+ printf("ctime\t%ld.%09ld\n", (long)st.st_ctime,
+ (long)st.st_ctim.tv_nsec);
+ printf("birth\t%ld.%09ld\n", (long)st.st_birthtim.tv_sec,
+ (long)st.st_birthtim.tv_nsec);
+ error = ioctl(fd, FIOGSHMLPGCNF, &conf_dummy);
+ largepage = error == 0;
+ if (st.st_blocks != 0 && largepage)
+ printf("pagesz\t%jd\n", roundup((uintmax_t)st.st_size,
+ PAGE_SIZE) / st.st_blocks);
+ else
+ printf("pages\t%jd\n", st.st_blocks);
+ }
+ close(fd);
+ return (ret);
+}
+
+static int
+stat_shm(int argc, char **argv)
+{
+ int c, i, ret, ret1;
+ bool hsize, uname;
+
+ hsize = false;
+ uname = true;
+
+ while ((c = getopt(argc, argv, "hn")) != -1) {
+ switch (c) {
+ case 'h':
+ hsize = true;
+ break;
+ case 'n':
+ uname = false;
+ break;
+ default:
+ usage();
+ return (2);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ usage();
+ return (2);
+ }
+
+ ret = 0;
+ for (i = 0; i < argc; i++) {
+ ret1 = stat_one_shm(argv[i], hsize, uname);
+ if (ret1 != 0 && ret == 0)
+ ret = ret1;
+ }
+ return (ret);
+}
+
+static int
+truncate_one_shm(const char *path, uint64_t newsize)
+{
+ int error, fd, ret;
+
+ ret = 0;
+ fd = shm_open(path, O_RDWR, 0);
+ if (fd == -1) {
+ warn("open %s", path);
+ return (1);
+ }
+ error = ftruncate(fd, newsize);
+ if (error == -1) {
+ warn("truncate %s", path);
+ ret = 1;
+ }
+ close(fd);
+ return (ret);
+}
+
+static int
+truncate_shm(int argc, char **argv)
+{
+ uint64_t newsize;
+ int c, i, ret, ret1;
+
+ newsize = 0;
+ while ((c = getopt(argc, argv, "s:")) != -1) {
+ switch (c) {
+ case 's':
+ if (expand_number(optarg, &newsize) == -1)
+ err(1, "size");
+ break;
+ case '?':
+ default:
+ return (2);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ usage();
+ return (2);
+ }
+
+ ret = 0;
+ for (i = 0; i < argc; i++) {
+ ret1 = truncate_one_shm(argv[i], newsize);
+ if (ret1 != 0 && ret == 0)
+ ret = ret1;
+ }
+ return (ret);
+}
+
+struct opmode {
+ const char *cmd;
+ int (*impl)(int argc, char **argv);
+};
+
+static const struct opmode opmodes[] = {
+ { .cmd = "create", .impl = create_shm},
+ { .cmd = "rm", .impl = delete_shm, },
+ { .cmd = "list", .impl = list_shm },
+ { .cmd = "ls", .impl = list_shm },
+ { .cmd = "dump", .impl = read_shm, },
+ { .cmd = "stat", .impl = stat_shm, },
+ { .cmd = "truncate", .impl = truncate_shm, },
+};
+
+int
+main(int argc, char *argv[])
+{
+ const struct opmode *opmode;
+ int i, ret;
+
+ ret = 0;
+ opmode = NULL;
+
+ if (argc < 2) {
+ usage();
+ exit(2);
+ }
+ for (i = 0; i < (int)nitems(opmodes); i++) {
+ if (strcmp(argv[1], opmodes[i].cmd) == 0) {
+ opmode = &opmodes[i];
+ break;
+ }
+ }
+ if (opmode == NULL) {
+ usage();
+ exit(2);
+ }
+ ret = opmode->impl(argc - 1, argv + 1);
+ exit(ret);
+}
diff --git a/usr.bin/pr/Makefile b/usr.bin/pr/Makefile
new file mode 100644
index 000000000000..965ebc8d4637
--- /dev/null
+++ b/usr.bin/pr/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= pr
+SRCS= pr.c egetopt.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/pr/Makefile.depend b/usr.bin/pr/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/pr/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/pr/egetopt.c b/usr.bin/pr/egetopt.c
new file mode 100644
index 000000000000..cf101bf03020
--- /dev/null
+++ b/usr.bin/pr/egetopt.c
@@ -0,0 +1,211 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1991 Keith Muller.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/cdefs.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "extern.h"
+
+/*
+ * egetopt: get option letter from argument vector (an extended
+ * version of getopt).
+ *
+ * Non standard additions to the ostr specs are:
+ * 1) '?': immediate value following arg is optional (no white space
+ * between the arg and the value)
+ * 2) '#': +/- followed by a number (with an optional sign but
+ * no white space between the arg and the number). The - may be
+ * combined with other options, but the + cannot.
+ */
+
+int eopterr = 1; /* if error message should be printed */
+int eoptind = 1; /* index into parent argv vector */
+int eoptopt; /* character checked for validity */
+char *eoptarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+
+static char emsg[] = "";
+
+int
+egetopt(int nargc, char * const *nargv, const char *ostr)
+{
+ static char *place = emsg; /* option letter processing */
+ char *oli; /* option letter list index */
+ static int delim; /* which option delimiter */
+ char *p;
+ static char savec = '\0';
+
+ if (savec != '\0') {
+ *place = savec;
+ savec = '\0';
+ }
+
+ if (!*place) {
+ /*
+ * update scanning pointer
+ */
+ if ((eoptind >= nargc) ||
+ ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
+ place = emsg;
+ return (-1);
+ }
+
+ delim = (int)*place;
+ if (place[1] && *++place == '-' && !place[1]) {
+ /*
+ * found "--"
+ */
+ ++eoptind;
+ place = emsg;
+ return (-1);
+ }
+ }
+
+ /*
+ * check option letter
+ */
+ if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
+ !(oli = strchr(ostr, eoptopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1 when by itself.
+ */
+ if ((eoptopt == (int)'-') && !*place)
+ return (-1);
+ if (strchr(ostr, '#') && (isdigit(eoptopt) ||
+ (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
+ isdigit(*place)))) {
+ /*
+ * # option: +/- with a number is ok
+ */
+ for (p = place; *p != '\0'; ++p) {
+ if (!isdigit(*p))
+ break;
+ }
+ eoptarg = place-1;
+
+ if (*p == '\0') {
+ place = emsg;
+ ++eoptind;
+ } else {
+ place = p;
+ savec = *p;
+ *place = '\0';
+ }
+ return (delim);
+ }
+
+ if (!*place)
+ ++eoptind;
+ if (eopterr) {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ (void)fprintf(stderr, "%s: illegal option -- %c\n",
+ p, eoptopt);
+ }
+ return (BADCH);
+ }
+ if (delim == (int)'+') {
+ /*
+ * '+' is only allowed with numbers
+ */
+ if (!*place)
+ ++eoptind;
+ if (eopterr) {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ (void)fprintf(stderr,
+ "%s: illegal '+' delimiter with option -- %c\n",
+ p, eoptopt);
+ }
+ return (BADCH);
+ }
+ ++oli;
+ if ((*oli != ':') && (*oli != '?')) {
+ /*
+ * don't need argument
+ */
+ eoptarg = NULL;
+ if (!*place)
+ ++eoptind;
+ return (eoptopt);
+ }
+
+ if (*place) {
+ /*
+ * no white space
+ */
+ eoptarg = place;
+ } else if (*oli == '?') {
+ /*
+ * no arg, but NOT required
+ */
+ eoptarg = NULL;
+ } else if (nargc <= ++eoptind) {
+ /*
+ * no arg, but IS required
+ */
+ place = emsg;
+ if (eopterr) {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n", p,
+ eoptopt);
+ }
+ return (BADCH);
+ } else {
+ /*
+ * arg has white space
+ */
+ eoptarg = nargv[eoptind];
+ }
+ place = emsg;
+ ++eoptind;
+ return (eoptopt);
+}
diff --git a/usr.bin/pr/extern.h b/usr.bin/pr/extern.h
new file mode 100644
index 000000000000..46a69749edf4
--- /dev/null
+++ b/usr.bin/pr/extern.h
@@ -0,0 +1,62 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1991 Keith Muller.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+extern int eopterr;
+extern int eoptind;
+extern int eoptopt;
+extern char *eoptarg;
+
+void addnum(char *, int, int);
+int egetopt(int, char * const *, const char *);
+void flsh_errs(void);
+int horzcol(int, char **);
+int inln(FILE *, char *, int, int *, int, int *);
+int inskip(FILE *, int, int);
+void mfail(void);
+int mulfile(int, char **);
+FILE *nxtfile(int, char **, const char **, char *, int);
+int onecol(int, char **);
+int otln(char *, int, int *, int *, int);
+void pfail(void);
+int prhead(char *, const char *, int);
+int prtail(int, int);
+int setup(int, char **);
+void terminate(int);
+void usage(void);
+int vertcol(int, char **);
diff --git a/usr.bin/pr/pr.1 b/usr.bin/pr/pr.1
new file mode 100644
index 000000000000..f4aeb4650bab
--- /dev/null
+++ b/usr.bin/pr/pr.1
@@ -0,0 +1,386 @@
+.\" Copyright (c) 1991 Keith Muller.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Keith Muller of the University of California, San Diego.
+.\"
+.\" 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.
+.\"
+.Dd July 3, 2004
+.Dt PR 1
+.Os
+.Sh NAME
+.Nm pr
+.Nd print files
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Ar \&+page
+.Ek
+.Bk -words
+.Op Fl Ar column
+.Ek
+.Op Fl adFfmprt
+.Bk -words
+.Oo
+.Op Fl e
+.Op Ar char
+.Op Ar gap
+.Oc
+.Ek
+.Bk -words
+.Op Fl L Ar locale
+.Ek
+.Bk -words
+.Op Fl h Ar header
+.Ek
+.Bk -words
+.Oo
+.Op Fl i
+.Op Ar char
+.Op Ar gap
+.Oc
+.Ek
+.Bk -words
+.Op Fl l Ar lines
+.Ek
+.Bk -words
+.Op Fl o Ar offset
+.Ek
+.Bk -words
+.Oo
+.Op Fl s
+.Op Ar char
+.Oc
+.Ek
+.Bk -words
+.Oo
+.Op Fl n
+.Op Ar char
+.Op Ar width
+.Oc
+.Ek
+.Bk -words
+.Op Fl w Ar width
+.Ek
+.Op -
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility is a printing and pagination filter for text files.
+When multiple input files are specified, each is read, formatted,
+and written to standard output.
+By default, the input is separated into 66-line pages, each with
+.Bl -bullet
+.It
+A 5-line header with the page number, date, time, and
+the pathname of the file.
+.It
+A 5-line trailer consisting of blank lines.
+.El
+.Pp
+If standard output is associated with a terminal,
+diagnostic messages are suppressed until the
+.Nm
+utility has completed processing.
+.Pp
+When multiple column output is specified,
+text columns are of equal width.
+By default text columns are separated by at least one
+.Em <blank> .
+Input lines that do not fit into a text column are truncated.
+Lines are not truncated under single column output.
+.Sh OPTIONS
+In the following option descriptions, column, lines, offset, page, and
+width are positive decimal integers and gap is a nonnegative decimal integer.
+.Bl -tag -width 4n
+.It Ar \&+page
+Begin output at page number
+.Ar page
+of the formatted input.
+.It Fl Ar column
+Produce output that is
+.Ar columns
+wide (default is 1) that is written vertically
+down each column in the order in which the text
+is received from the input file.
+The options
+.Fl e
+and
+.Fl i
+are assumed.
+This option should not be used with
+.Fl m .
+When used with
+.Fl t ,
+the minimum number of lines is used to display the output.
+(To columnify and reshape text files more generally and without additional
+formatting, see the
+.Xr rs 1
+utility.)
+.It Fl a
+Modify the effect of the
+.Fl column
+option so that the columns are filled across the page in a round-robin order
+(e.g., when column is 2, the first input line heads column
+1, the second heads column 2, the third is the second line
+in column 1, etc.).
+This option requires the use of the
+.Fl column
+option.
+.It Fl d
+Produce output that is double spaced.
+An extra
+.Em <newline>
+character is output following every
+.Em <newline>
+found in the input.
+.It Fl e Xo
+.Op Ar char Ns
+.Op Ar gap
+.Xc
+Expand each input
+.Em <tab>
+to the next greater column
+position specified by the formula
+.Ar n*gap+1 ,
+where
+.Em n
+is an integer > 0.
+If
+.Ar gap
+is zero or is omitted the default is 8.
+All
+.Em <tab>
+characters in the input are expanded into the appropriate
+number of
+.Em <space>s .
+If any nondigit character,
+.Ar char ,
+is specified, it is used as the input tab character.
+.It Fl F
+Use a
+.Em <form-feed>
+character for new pages,
+instead of the default behavior that uses a
+sequence of
+.Em <newline>
+characters.
+.It Fl f
+Same as
+.Fl F
+but pause before beginning the first page if standard output is a terminal.
+.It Fl h Ar header
+Use the string
+.Ar header
+to replace the
+.Ar file name
+in the header line.
+.It Fl i Xo
+.Op Ar char Ns
+.Op Ar gap
+.Xc
+In output, replace multiple
+.Em <space>s
+with
+.Em <tab>s
+whenever two or more
+adjacent
+.Em <space>s
+reach column positions
+.Ar gap+1 ,
+.Ar 2*gap+1 ,
+etc.
+If
+.Ar gap
+is zero or omitted, default
+.Em <tab>
+settings at every eighth column position
+is used.
+If any nondigit character,
+.Ar char ,
+is specified, it is used as the output
+.Em <tab>
+character.
+.It Fl L Ar locale
+Use
+.Ar locale
+specified as argument instead of one found in environment.
+Use "C" to reset locale to default.
+.It Fl l Ar lines
+Override the 66 line default and reset the page length to
+.Ar lines .
+If
+.Ar lines
+is not greater than the sum of both the header and trailer
+depths (in lines), the
+.Nm
+utility suppresses output of both the header and trailer, as if the
+.Fl t
+option were in effect.
+.It Fl m
+Merge the contents of multiple files.
+One line from each file specified by a file operand is
+written side by side into text columns of equal fixed widths, in
+terms of the number of column positions.
+The number of text columns depends on the number of
+file operands successfully opened.
+The maximum number of files merged depends on page width and the
+per process open file limit.
+The options
+.Fl e
+and
+.Fl i
+are assumed.
+.It Fl n Xo
+.Op Ar char Ns
+.Op Ar width
+.Xc
+Provide
+.Ar width
+digit line numbering.
+The default for
+.Ar width ,
+if not specified, is 5.
+The number occupies the first
+.Ar width
+column positions of each text column or each line of
+.Fl m
+output.
+If
+.Ar char
+(any nondigit character) is given, it is appended to the line number to
+separate it from whatever follows.
+The default for
+.Ar char
+is a
+.Em <tab> .
+Line numbers longer than
+.Ar width
+columns are truncated.
+.It Fl o Ar offset
+Each line of output is preceded by
+.Ar offset
+.Em <spaces>s .
+If the
+.Fl o
+option is not specified, the default is zero.
+The space taken is in addition to the output line width.
+.It Fl p
+Pause before each page if the standard output is a terminal.
+.Nm
+will write an alert character to standard error and wait for a carriage
+return to be read on the terminal.
+.It Fl r
+Write no diagnostic reports on failure to open a file.
+.It Fl s Ar char
+Separate text columns by the single character
+.Ar char
+instead of by the appropriate number of
+.Em <space>s
+(default for
+.Ar char
+is the
+.Em <tab>
+character).
+.It Fl t
+Print neither the five-line identifying
+header nor the five-line trailer usually supplied for each page.
+Quit printing after the last line of each file without spacing to the
+end of the page.
+.It Fl w Ar width
+Set the width of the line to
+.Ar width
+column positions for multiple text-column output only.
+If the
+.Fl w
+option is not specified and the
+.Fl s
+option is not specified, the default width is 72.
+If the
+.Fl w
+option is not specified and the
+.Fl s
+option is specified, the default width is 512.
+.It Ar file
+A pathname of a file to be printed.
+If no
+.Ar file
+operands are specified, or if a
+.Ar file
+operand is
+.Sq Fl ,
+the standard input is used.
+The standard input is used only if no
+.Ar file
+operands are specified, or if a
+.Ar file
+operand is
+.Sq Fl .
+.El
+.Pp
+The
+.Fl s
+option does not allow the option letter to be separated from its
+argument, and the options
+.Fl e ,
+.Fl i ,
+and
+.Fl n
+require that both arguments, if present, not be separated from the option
+letter.
+.Sh EXIT STATUS
+.Ex -std
+.Sh DIAGNOSTICS
+If
+.Nm
+receives an interrupt while printing to a terminal, it
+flushes all accumulated error messages to the screen before
+terminating.
+.Pp
+Error messages are written to standard error during the printing
+process (if output is redirected) or after all successful
+file printing is complete (when printing to a terminal).
+.Sh SEE ALSO
+.Xr cat 1 ,
+.Xr more 1 ,
+.Xr rs 1
+.Sh STANDARDS
+The
+.Nm
+utility is
+.St -p1003.1-2001
+compatible.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+.Sh BUGS
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/pr/pr.c b/usr.bin/pr/pr.c
new file mode 100644
index 000000000000..7f08d3cd8b71
--- /dev/null
+++ b/usr.bin/pr/pr.c
@@ -0,0 +1,1849 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1991 Keith Muller.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 <ctype.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pr.h"
+#include "extern.h"
+
+/*
+ * pr: a printing and pagination filter. If multiple input files
+ * are specified, each is read, formatted, and written to standard
+ * output. By default, input is separated into 66-line pages, each
+ * with a header that includes the page number, date, time and the
+ * files pathname.
+ *
+ * Complies with posix P1003.2/D11
+ */
+
+/*
+ * parameter variables
+ */
+static int pgnm; /* starting page number */
+static int clcnt; /* number of columns */
+static int colwd; /* column data width - multiple columns */
+static int across; /* mult col flag; write across page */
+static int dspace; /* double space flag */
+static char inchar; /* expand input char */
+static int ingap; /* expand input gap */
+static int pausefst; /* Pause before first page */
+static int pauseall; /* Pause before each page */
+static int formfeed; /* use formfeed as trailer */
+static char *header; /* header name instead of file name */
+static char ochar; /* contract output char */
+static int ogap; /* contract output gap */
+static int lines; /* number of lines per page */
+static int merge; /* merge multiple files in output */
+static char nmchar; /* line numbering append char */
+static int nmwd; /* width of line number field */
+static int offst; /* number of page offset spaces */
+static int nodiag; /* do not report file open errors */
+static char schar; /* text column separation character */
+static int sflag; /* -s option for multiple columns */
+static int nohead; /* do not write head and trailer */
+static int pgwd; /* page width with multiple col output */
+static char *timefrmt; /* time conversion string */
+
+/*
+ * misc globals
+ */
+static FILE *err; /* error message file pointer */
+static int addone; /* page length is odd with double space */
+static int errcnt; /* error count on file processing */
+static char digs[] = "0123456789"; /* page number translation map */
+
+static char fnamedefault[] = FNAME;
+
+int
+main(int argc, char *argv[])
+{
+ int ret_val;
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGINT, terminate);
+ ret_val = setup(argc, argv);
+ if (!ret_val) {
+ /*
+ * select the output format based on options
+ */
+ if (merge)
+ ret_val = mulfile(argc, argv);
+ else if (clcnt == 1)
+ ret_val = onecol(argc, argv);
+ else if (across)
+ ret_val = horzcol(argc, argv);
+ else
+ ret_val = vertcol(argc, argv);
+ free(timefrmt);
+ } else
+ usage();
+ flsh_errs();
+ if (errcnt || ret_val)
+ exit(1);
+ return(0);
+}
+
+/*
+ * Check if we should pause and write an alert character and wait for a
+ * carriage return on /dev/tty.
+ */
+static void
+ttypause(int pagecnt)
+{
+ int pch;
+ FILE *ttyfp;
+
+ if ((pauseall || (pausefst && pagecnt == 1)) &&
+ isatty(STDOUT_FILENO)) {
+ if ((ttyfp = fopen("/dev/tty", "r")) != NULL) {
+ (void)putc('\a', stderr);
+ while ((pch = getc(ttyfp)) != '\n' && pch != EOF)
+ ;
+ (void)fclose(ttyfp);
+ }
+ }
+}
+
+/*
+ * onecol: print files with only one column of output.
+ * Line length is unlimited.
+ */
+int
+onecol(int argc, char *argv[])
+{
+ int cnt = -1;
+ int off;
+ int lrgln;
+ int linecnt;
+ int num;
+ int lncnt;
+ int pagecnt;
+ int ips;
+ int ops;
+ int cps;
+ char *obuf;
+ char *lbuf;
+ char *nbuf;
+ char *hbuf;
+ char *ohbuf;
+ FILE *inf;
+ const char *fname;
+ int mor;
+
+ if (nmwd)
+ num = nmwd + 1;
+ else
+ num = 0;
+ off = num + offst;
+
+ /*
+ * allocate line buffer
+ */
+ if ((obuf = malloc((unsigned)(LBUF + off)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+ /*
+ * allocate header buffer
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ free(obuf);
+ mfail();
+ return(1);
+ }
+
+ ohbuf = hbuf + offst;
+ nbuf = obuf + offst;
+ lbuf = nbuf + num;
+ if (num)
+ nbuf[--num] = nmchar;
+ if (offst) {
+ (void)memset(obuf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ if (pgnm) {
+ /*
+ * skip to specified page
+ */
+ if (inskip(inf, pgnm, lines))
+ continue;
+ pagecnt = pgnm;
+ } else
+ pagecnt = 1;
+ lncnt = 0;
+
+ /*
+ * loop by page
+ */
+ for(;;) {
+ linecnt = 0;
+ lrgln = 0;
+ ops = 0;
+ ips = 0;
+ cps = 0;
+
+ ttypause(pagecnt);
+
+ /*
+ * loop by line
+ */
+ while (linecnt < lines) {
+ /*
+ * input next line
+ */
+ if ((cnt = inln(inf,lbuf,LBUF,&cps,0,&mor)) < 0)
+ break;
+ if (!linecnt && !nohead &&
+ prhead(hbuf, fname, pagecnt))
+ goto err;
+
+ /*
+ * start of new line.
+ */
+ if (!lrgln) {
+ if (num)
+ addnum(nbuf, num, ++lncnt);
+ if (otln(obuf,cnt+off, &ips, &ops, mor))
+ goto err;
+ } else if (otln(lbuf, cnt, &ips, &ops, mor))
+ goto err;
+
+ /*
+ * if line bigger than buffer, get more
+ */
+ if (mor) {
+ lrgln = 1;
+ continue;
+ }
+
+ /*
+ * whole line rcvd. reset tab proc. state
+ */
+ ++linecnt;
+ lrgln = 0;
+ ops = 0;
+ ips = 0;
+ }
+
+ /*
+ * fill to end of page
+ */
+ if (linecnt && prtail(lines-linecnt-lrgln, lrgln))
+ goto err;
+
+ /*
+ * On EOF go to next file
+ */
+ if (cnt < 0)
+ break;
+ ++pagecnt;
+ }
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+ if (eoptind < argc)
+ goto err;
+ free(hbuf);
+ free(obuf);
+ return(0);
+err:
+ free(hbuf);
+ free(obuf);
+ return(1);
+}
+
+/*
+ * vertcol: print files with more than one column of output down a page
+ */
+int
+vertcol(int argc, char *argv[])
+{
+ char *ptbf;
+ char **lstdat = NULL;
+ int i;
+ int j;
+ int cnt = -1;
+ int pln;
+ int *indy = NULL;
+ int cvc;
+ int *lindy = NULL;
+ int lncnt;
+ int stp;
+ int pagecnt;
+ int col = colwd + 1;
+ int mxlen = pgwd + offst + 1;
+ int mclcnt = clcnt - 1;
+ struct vcol *vc = NULL;
+ int mvc;
+ int tvc;
+ int cw = nmwd + 1;
+ int fullcol;
+ char *buf = NULL;
+ char *hbuf = NULL;
+ char *ohbuf;
+ const char *fname;
+ FILE *inf;
+ int ips = 0;
+ int cps = 0;
+ int ops = 0;
+ int mor = 0;
+ int retval = 1;
+
+ /*
+ * allocate page buffer
+ */
+ if ((buf = malloc((unsigned)lines*mxlen*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * allocate page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ goto out;
+ }
+ ohbuf = hbuf + offst;
+ if (offst)
+ (void)memset(hbuf, (int)' ', offst);
+
+ /*
+ * col pointers when no headers
+ */
+ mvc = lines * clcnt;
+ if ((vc =
+ (struct vcol *)malloc((unsigned)mvc*sizeof(struct vcol))) == NULL) {
+ mfail();
+ goto out;
+ }
+
+ /*
+ * pointer into page where last data per line is located
+ */
+ if ((lstdat = (char **)malloc((unsigned)lines*sizeof(char *))) == NULL){
+ mfail();
+ goto out;
+ }
+
+ /*
+ * fast index lookups to locate start of lines
+ */
+ if ((indy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
+ mfail();
+ goto out;
+ }
+ if ((lindy = (int *)malloc((unsigned)lines*sizeof(int))) == NULL) {
+ mfail();
+ goto out;
+ }
+
+ if (nmwd)
+ fullcol = col + cw;
+ else
+ fullcol = col;
+
+ /*
+ * initialize buffer lookup indexes and offset area
+ */
+ for (j = 0; j < lines; ++j) {
+ lindy[j] = j * mxlen;
+ indy[j] = lindy[j] + offst;
+ if (offst) {
+ ptbf = buf + lindy[j];
+ (void)memset(ptbf, (int)' ', offst);
+ ptbf += offst;
+ } else
+ ptbf = buf + indy[j];
+ lstdat[j] = ptbf;
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ if (pgnm) {
+ /*
+ * skip to requested page
+ */
+ if (inskip(inf, pgnm, lines))
+ continue;
+ pagecnt = pgnm;
+ } else
+ pagecnt = 1;
+ lncnt = 0;
+
+ /*
+ * loop by page
+ */
+ for(;;) {
+ ttypause(pagecnt);
+
+ /*
+ * loop by column
+ */
+ cvc = 0;
+ for (i = 0; i < clcnt; ++i) {
+ j = 0;
+ /*
+ * if last column, do not pad
+ */
+ if (i == mclcnt)
+ stp = 1;
+ else
+ stp = 0;
+ /*
+ * loop by line
+ */
+ for(;;) {
+ /*
+ * is this first column
+ */
+ if (!i) {
+ ptbf = buf + indy[j];
+ lstdat[j] = ptbf;
+ } else
+ ptbf = lstdat[j];
+ vc[cvc].pt = ptbf;
+
+ /*
+ * add number
+ */
+ if (nmwd) {
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
+
+ /*
+ * input next line
+ */
+ cnt = inln(inf,ptbf,colwd,&cps,1,&mor);
+ vc[cvc++].cnt = cnt;
+ if (cnt < 0)
+ break;
+ ptbf += cnt;
+
+ /*
+ * pad all but last column on page
+ */
+ if (!stp) {
+ /*
+ * pad to end of column
+ */
+ if (sflag)
+ *ptbf++ = schar;
+ else if ((pln = col-cnt) > 0) {
+ (void)memset(ptbf,
+ (int)' ',pln);
+ ptbf += pln;
+ }
+ }
+ /*
+ * remember last char in line
+ */
+ lstdat[j] = ptbf;
+ if (++j >= lines)
+ break;
+ }
+ if (cnt < 0)
+ break;
+ }
+
+ /*
+ * when -t (no header) is specified the spec requires
+ * the min number of lines. The last page may not have
+ * balanced length columns. To fix this we must reorder
+ * the columns. This is a very slow technique so it is
+ * only used under limited conditions. Without -t, the
+ * balancing of text columns is unspecified. To NOT
+ * balance the last page, add the global variable
+ * nohead to the if statement below e.g.
+ *
+ * if ((cnt < 0) && nohead && cvc ......
+ */
+ --cvc;
+
+ /*
+ * check to see if last page needs to be reordered
+ */
+ if ((cnt < 0) && cvc && ((mvc-cvc) >= clcnt)){
+ pln = cvc/clcnt;
+ if (cvc % clcnt)
+ ++pln;
+
+ /*
+ * print header
+ */
+ if (!nohead && prhead(hbuf, fname, pagecnt))
+ goto out;
+ for (i = 0; i < pln; ++i) {
+ ips = 0;
+ ops = 0;
+ if (offst &&
+ otln(buf,offst,&ips,&ops,1))
+ goto out;
+ tvc = i;
+
+ for (j = 0; j < clcnt; ++j) {
+ /*
+ * determine column length
+ */
+ if (j == mclcnt) {
+ /*
+ * last column
+ */
+ cnt = vc[tvc].cnt;
+ if (nmwd)
+ cnt += cw;
+ } else if (sflag) {
+ /*
+ * single ch between
+ */
+ cnt = vc[tvc].cnt + 1;
+ if (nmwd)
+ cnt += cw;
+ } else
+ cnt = fullcol;
+ if (otln(vc[tvc].pt, cnt, &ips,
+ &ops, 1))
+ goto out;
+ tvc += pln;
+ if (tvc >= cvc)
+ break;
+ }
+ /*
+ * terminate line
+ */
+ if (otln(buf, 0, &ips, &ops, 0))
+ goto out;
+ }
+ /*
+ * pad to end of page
+ */
+ if (prtail((lines - pln), 0))
+ goto out;
+ /*
+ * done with output, go to next file
+ */
+ break;
+ }
+
+ /*
+ * determine how many lines to output
+ */
+ if (i > 0)
+ pln = lines;
+ else
+ pln = j;
+
+ /*
+ * print header
+ */
+ if (pln && !nohead && prhead(hbuf, fname, pagecnt))
+ goto out;
+
+ /*
+ * output each line
+ */
+ for (i = 0; i < pln; ++i) {
+ ptbf = buf + lindy[i];
+ if ((j = lstdat[i] - ptbf) <= offst)
+ break;
+ if (otln(ptbf, j, &ips, &ops, 0))
+ goto out;
+ }
+
+ /*
+ * pad to end of page
+ */
+ if (pln && prtail((lines - pln), 0))
+ goto out;
+
+ /*
+ * if EOF go to next file
+ */
+ if (cnt < 0)
+ break;
+ ++pagecnt;
+ }
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+ if (eoptind < argc)
+ goto out;
+ retval = 0;
+out:
+ free(lindy);
+ free(indy);
+ free(lstdat);
+ free(vc);
+ free(hbuf);
+ free(buf);
+ return(retval);
+}
+
+/*
+ * horzcol: print files with more than one column of output across a page
+ */
+int
+horzcol(int argc, char *argv[])
+{
+ char *ptbf;
+ int pln;
+ int cnt = -1;
+ char *lstdat;
+ int col = colwd + 1;
+ int j;
+ int i;
+ int lncnt;
+ int pagecnt;
+ char *buf;
+ char *hbuf;
+ char *ohbuf;
+ const char *fname;
+ FILE *inf;
+ int ips = 0;
+ int cps = 0;
+ int ops = 0;
+ int mor = 0;
+
+ if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
+ mfail();
+ return(1);
+ }
+
+ /*
+ * page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ free(buf);
+ mfail();
+ return(1);
+ }
+ ohbuf = hbuf + offst;
+ if (offst) {
+ (void)memset(buf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+
+ /*
+ * loop by file
+ */
+ while ((inf = nxtfile(argc, argv, &fname, ohbuf, 0)) != NULL) {
+ if (pgnm) {
+ if (inskip(inf, pgnm, lines))
+ continue;
+ pagecnt = pgnm;
+ } else
+ pagecnt = 1;
+ lncnt = 0;
+
+ /*
+ * loop by page
+ */
+ for(;;) {
+ ttypause(pagecnt);
+
+ /*
+ * loop by line
+ */
+ for (i = 0; i < lines; ++i) {
+ ptbf = buf + offst;
+ lstdat = ptbf;
+ j = 0;
+ /*
+ * loop by col
+ */
+ for(;;) {
+ if (nmwd) {
+ /*
+ * add number to column
+ */
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
+ /*
+ * input line
+ */
+ if ((cnt = inln(inf,ptbf,colwd,&cps,1,
+ &mor)) < 0)
+ break;
+ ptbf += cnt;
+ lstdat = ptbf;
+
+ /*
+ * if last line skip padding
+ */
+ if (++j >= clcnt)
+ break;
+
+ /*
+ * pad to end of column
+ */
+ if (sflag)
+ *ptbf++ = schar;
+ else if ((pln = col - cnt) > 0) {
+ (void)memset(ptbf,(int)' ',pln);
+ ptbf += pln;
+ }
+ }
+
+ /*
+ * determine line length
+ */
+ if ((j = lstdat - buf) <= offst)
+ break;
+ if (!i && !nohead &&
+ prhead(hbuf, fname, pagecnt))
+ goto err;
+ /*
+ * output line
+ */
+ if (otln(buf, j, &ips, &ops, 0))
+ goto err;
+ }
+
+ /*
+ * pad to end of page
+ */
+ if (i && prtail(lines-i, 0))
+ goto err;
+
+ /*
+ * if EOF go to next file
+ */
+ if (cnt < 0)
+ break;
+ ++pagecnt;
+ }
+ if (inf != stdin)
+ (void)fclose(inf);
+ }
+ if (eoptind < argc)
+ goto err;
+ free(hbuf);
+ free(buf);
+ return(0);
+err:
+ free(hbuf);
+ free(buf);
+ return(1);
+}
+
+/*
+ * mulfile: print files with more than one column of output and
+ * more than one file concurrently
+ */
+int
+mulfile(int argc, char *argv[])
+{
+ char *ptbf;
+ int j;
+ int pln;
+ int cnt;
+ char *lstdat;
+ int i;
+ FILE **fbuf = NULL;
+ int actf;
+ int lncnt;
+ int col;
+ int pagecnt;
+ int fproc;
+ char *buf = NULL;
+ char *hbuf = NULL;
+ char *ohbuf;
+ const char *fname;
+ int ips = 0;
+ int cps = 0;
+ int ops = 0;
+ int mor = 0;
+ int retval = 1;
+
+ /*
+ * array of FILE *, one for each operand
+ */
+ if ((fbuf = (FILE **)malloc((unsigned)clcnt*sizeof(FILE *))) == NULL) {
+ mfail();
+ goto out;
+ }
+
+ /*
+ * page header
+ */
+ if ((hbuf = malloc((unsigned)(HDBUF + offst)*sizeof(char))) == NULL) {
+ mfail();
+ goto out;
+ }
+ ohbuf = hbuf + offst;
+
+ /*
+ * do not know how many columns yet. The number of operands provide an
+ * upper bound on the number of columns. We use the number of files
+ * we can open successfully to set the number of columns. The operation
+ * of the merge operation (-m) in relation to unsuccessful file opens
+ * is unspecified by posix.
+ */
+ j = 0;
+ while (j < clcnt) {
+ if ((fbuf[j] = nxtfile(argc, argv, &fname, ohbuf, 1)) == NULL)
+ break;
+ if (pgnm && (inskip(fbuf[j], pgnm, lines)))
+ fbuf[j] = NULL;
+ ++j;
+ }
+
+ /*
+ * if no files, exit
+ */
+ if (!j)
+ goto out;
+
+ /*
+ * calculate page boundaries based on open file count
+ */
+ clcnt = j;
+ if (nmwd) {
+ colwd = (pgwd - clcnt - nmwd)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - nmwd - 2;
+ } else {
+ colwd = (pgwd + 1 - clcnt)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - 1;
+ }
+ if (colwd < 1) {
+ (void)fprintf(err,
+ "pr: page width too small for %d columns\n", clcnt);
+ goto out;
+ }
+ actf = clcnt;
+ col = colwd + 1;
+
+ /*
+ * line buffer
+ */
+ if ((buf = malloc((unsigned)(pgwd+offst+1)*sizeof(char))) == NULL) {
+ mfail();
+ goto out;
+ }
+ if (offst) {
+ (void)memset(buf, (int)' ', offst);
+ (void)memset(hbuf, (int)' ', offst);
+ }
+ if (pgnm)
+ pagecnt = pgnm;
+ else
+ pagecnt = 1;
+ lncnt = 0;
+
+ /*
+ * continue to loop while any file still has data
+ */
+ while (actf > 0) {
+ ttypause(pagecnt);
+
+ /*
+ * loop by line
+ */
+ for (i = 0; i < lines; ++i) {
+ ptbf = buf + offst;
+ lstdat = ptbf;
+ if (nmwd) {
+ /*
+ * add line number to line
+ */
+ addnum(ptbf, nmwd, ++lncnt);
+ ptbf += nmwd;
+ *ptbf++ = nmchar;
+ }
+ j = 0;
+ fproc = 0;
+
+ /*
+ * loop by column
+ */
+ for (j = 0; j < clcnt; ++j) {
+ if (fbuf[j] == NULL) {
+ /*
+ * empty column; EOF
+ */
+ cnt = 0;
+ } else if ((cnt = inln(fbuf[j], ptbf, colwd,
+ &cps, 1, &mor)) < 0) {
+ /*
+ * EOF hit; no data
+ */
+ if (fbuf[j] != stdin)
+ (void)fclose(fbuf[j]);
+ fbuf[j] = NULL;
+ --actf;
+ cnt = 0;
+ } else {
+ /*
+ * process file data
+ */
+ ptbf += cnt;
+ lstdat = ptbf;
+ fproc++;
+ }
+
+ /*
+ * if last ACTIVE column, done with line
+ */
+ if (fproc >= actf)
+ break;
+
+ /*
+ * pad to end of column
+ */
+ if (sflag) {
+ *ptbf++ = schar;
+ } else if ((pln = col - cnt) > 0) {
+ (void)memset(ptbf, (int)' ', pln);
+ ptbf += pln;
+ }
+ }
+
+ /*
+ * calculate data in line
+ */
+ if ((j = lstdat - buf) <= offst)
+ break;
+
+ if (!i && !nohead && prhead(hbuf, fname, pagecnt))
+ goto out;
+
+ /*
+ * output line
+ */
+ if (otln(buf, j, &ips, &ops, 0))
+ goto out;
+
+ /*
+ * if no more active files, done
+ */
+ if (actf <= 0) {
+ ++i;
+ break;
+ }
+ }
+
+ /*
+ * pad to end of page
+ */
+ if (i && prtail(lines-i, 0))
+ goto out;
+ ++pagecnt;
+ }
+ if (eoptind < argc)
+ goto out;
+ retval = 0;
+out:
+ free(buf);
+ free(hbuf);
+ free(fbuf);
+ return(retval);
+}
+
+/*
+ * inln(): input a line of data (unlimited length lines supported)
+ * Input is optionally expanded to spaces
+ *
+ * inf: file
+ * buf: buffer
+ * lim: buffer length
+ * cps: column position 1st char in buffer (large line support)
+ * trnc: throw away data more than lim up to \n
+ * mor: set if more data in line (not truncated)
+ */
+int
+inln(FILE *inf, char *buf, int lim, int *cps, int trnc, int *mor)
+{
+ int col;
+ int gap = ingap;
+ int ch = EOF;
+ char *ptbuf;
+ int chk = (int)inchar;
+
+ ptbuf = buf;
+
+ if (gap) {
+ /*
+ * expanding input option
+ */
+ while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
+ /*
+ * is this the input "tab" char
+ */
+ if (ch == chk) {
+ /*
+ * expand to number of spaces
+ */
+ col = (ptbuf - buf) + *cps;
+ col = gap - (col % gap);
+
+ /*
+ * if more than this line, push back
+ */
+ if ((col > lim) && (ungetc(ch, inf) == EOF))
+ return(1);
+
+ /*
+ * expand to spaces
+ */
+ while ((--col >= 0) && (--lim >= 0))
+ *ptbuf++ = ' ';
+ continue;
+ }
+ if (ch == '\n')
+ break;
+ *ptbuf++ = ch;
+ }
+ } else {
+ /*
+ * no expansion
+ */
+ while ((--lim >= 0) && ((ch = getc(inf)) != EOF)) {
+ if (ch == '\n')
+ break;
+ *ptbuf++ = ch;
+ }
+ }
+ col = ptbuf - buf;
+ if (ch == EOF) {
+ *mor = 0;
+ *cps = 0;
+ if (!col)
+ return(-1);
+ return(col);
+ }
+ if (ch == '\n') {
+ /*
+ * entire line processed
+ */
+ *mor = 0;
+ *cps = 0;
+ return(col);
+ }
+
+ /*
+ * line was larger than limit
+ */
+ if (trnc) {
+ /*
+ * throw away rest of line
+ */
+ while ((ch = getc(inf)) != EOF) {
+ if (ch == '\n')
+ break;
+ }
+ *cps = 0;
+ *mor = 0;
+ } else {
+ /*
+ * save column offset if not truncated
+ */
+ *cps += col;
+ *mor = 1;
+ }
+
+ return(col);
+}
+
+/*
+ * otln(): output a line of data. (Supports unlimited length lines)
+ * output is optionally contracted to tabs
+ *
+ * buf: output buffer with data
+ * cnt: number of chars of valid data in buf
+ * svips: buffer input column position (for large lines)
+ * svops: buffer output column position (for large lines)
+ * mor: output line not complete in this buf; more data to come.
+ * 1 is more, 0 is complete, -1 is no \n's
+ */
+int
+otln(char *buf, int cnt, int *svips, int *svops, int mor)
+{
+ int ops; /* last col output */
+ int ips; /* last col in buf examined */
+ int gap = ogap;
+ int tbps;
+ char *endbuf;
+
+ if (ogap) {
+ /*
+ * contracting on output
+ */
+ endbuf = buf + cnt;
+ ops = *svops;
+ ips = *svips;
+ while (buf < endbuf) {
+ /*
+ * count number of spaces and ochar in buffer
+ */
+ if (*buf == ' ') {
+ ++ips;
+ ++buf;
+ continue;
+ }
+
+ /*
+ * simulate ochar processing
+ */
+ if (*buf == ochar) {
+ ips += gap - (ips % gap);
+ ++buf;
+ continue;
+ }
+
+ /*
+ * got a non space char; contract out spaces
+ */
+ while (ips - ops > 1) {
+ /*
+ * use as many ochar as will fit
+ */
+ if ((tbps = ops + gap - (ops % gap)) > ips)
+ break;
+ if (putchar(ochar) == EOF) {
+ pfail();
+ return(1);
+ }
+ ops = tbps;
+ }
+
+ while (ops < ips) {
+ /*
+ * finish off with spaces
+ */
+ if (putchar(' ') == EOF) {
+ pfail();
+ return(1);
+ }
+ ++ops;
+ }
+
+ /*
+ * output non space char
+ */
+ if (putchar(*buf++) == EOF) {
+ pfail();
+ return(1);
+ }
+ ++ips;
+ ++ops;
+ }
+
+ if (mor > 0) {
+ /*
+ * if incomplete line, save position counts
+ */
+ *svops = ops;
+ *svips = ips;
+ return(0);
+ }
+
+ if (mor < 0) {
+ while (ips - ops > 1) {
+ /*
+ * use as many ochar as will fit
+ */
+ if ((tbps = ops + gap - (ops % gap)) > ips)
+ break;
+ if (putchar(ochar) == EOF) {
+ pfail();
+ return(1);
+ }
+ ops = tbps;
+ }
+ while (ops < ips) {
+ /*
+ * finish off with spaces
+ */
+ if (putchar(' ') == EOF) {
+ pfail();
+ return(1);
+ }
+ ++ops;
+ }
+ return(0);
+ }
+ } else {
+ /*
+ * output is not contracted
+ */
+ if (cnt && (fwrite(buf, sizeof(char), cnt, stdout) <= 0)) {
+ pfail();
+ return(1);
+ }
+ if (mor != 0)
+ return(0);
+ }
+
+ /*
+ * process line end and double space as required
+ */
+ if ((putchar('\n') == EOF) || (dspace && (putchar('\n') == EOF))) {
+ pfail();
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * inskip(): skip over pgcnt pages with lncnt lines per page
+ * file is closed at EOF (if not stdin).
+ *
+ * inf FILE * to read from
+ * pgcnt number of pages to skip
+ * lncnt number of lines per page
+ */
+int
+inskip(FILE *inf, int pgcnt, int lncnt)
+{
+ int c;
+ int cnt;
+
+ while(--pgcnt > 0) {
+ cnt = lncnt;
+ while ((c = getc(inf)) != EOF) {
+ if ((c == '\n') && (--cnt == 0))
+ break;
+ }
+ if (c == EOF) {
+ if (inf != stdin)
+ (void)fclose(inf);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * nxtfile: returns a FILE * to next file in arg list and sets the
+ * time field for this file (or current date).
+ *
+ * buf array to store proper date for the header.
+ * dt if set skips the date processing (used with -m)
+ */
+FILE *
+nxtfile(int argc, char **argv, const char **fname, char *buf, int dt)
+{
+ FILE *inf = NULL;
+ time_t tv_sec;
+ struct tm *timeptr = NULL;
+ struct stat statbuf;
+ static int twice = -1;
+
+ ++twice;
+ if (eoptind >= argc) {
+ /*
+ * no file listed; default, use standard input
+ */
+ if (twice)
+ return(NULL);
+ clearerr(stdin);
+ inf = stdin;
+ if (header != NULL)
+ *fname = header;
+ else
+ *fname = fnamedefault;
+ if (nohead)
+ return(inf);
+ if ((tv_sec = time(NULL)) == -1) {
+ ++errcnt;
+ (void)fprintf(err, "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ eoptind = argc - 1;
+ return(NULL);
+ }
+ timeptr = localtime(&tv_sec);
+ }
+ for (; eoptind < argc; ++eoptind) {
+ if (strcmp(argv[eoptind], "-") == 0) {
+ /*
+ * process a "-" for filename
+ */
+ clearerr(stdin);
+ inf = stdin;
+ if (header != NULL)
+ *fname = header;
+ else
+ *fname = fnamedefault;
+ ++eoptind;
+ if (nohead || (dt && twice))
+ return(inf);
+ if ((tv_sec = time(NULL)) == -1) {
+ ++errcnt;
+ (void)fprintf(err,
+ "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ return(NULL);
+ }
+ timeptr = localtime(&tv_sec);
+ } else {
+ /*
+ * normal file processing
+ */
+ if ((inf = fopen(argv[eoptind], "r")) == NULL) {
+ ++errcnt;
+ if (nodiag)
+ continue;
+ (void)fprintf(err, "pr: cannot open %s, %s\n",
+ argv[eoptind], strerror(errno));
+ continue;
+ }
+ if (header != NULL)
+ *fname = header;
+ else if (dt)
+ *fname = fnamedefault;
+ else
+ *fname = argv[eoptind];
+ ++eoptind;
+ if (nohead || (dt && twice))
+ return(inf);
+
+ if (dt) {
+ if ((tv_sec = time(NULL)) == -1) {
+ ++errcnt;
+ (void)fprintf(err,
+ "pr: cannot get time of day, %s\n",
+ strerror(errno));
+ fclose(inf);
+ return(NULL);
+ }
+ timeptr = localtime(&tv_sec);
+ } else {
+ if (fstat(fileno(inf), &statbuf) < 0) {
+ ++errcnt;
+ (void)fclose(inf);
+ (void)fprintf(err,
+ "pr: cannot stat %s, %s\n",
+ argv[eoptind], strerror(errno));
+ return(NULL);
+ }
+ timeptr = localtime(&(statbuf.st_mtime));
+ }
+ }
+ break;
+ }
+ if (inf == NULL)
+ return(NULL);
+
+ /*
+ * set up time field used in header
+ */
+ if (strftime(buf, HDBUF, timefrmt, timeptr) <= 0) {
+ ++errcnt;
+ if (inf != stdin)
+ (void)fclose(inf);
+ (void)fputs("pr: time conversion failed\n", err);
+ return(NULL);
+ }
+ return(inf);
+}
+
+/*
+ * addnum(): adds the line number to the column
+ * Truncates from the front or pads with spaces as required.
+ * Numbers are right justified.
+ *
+ * buf buffer to store the number
+ * wdth width of buffer to fill
+ * line line number
+ *
+ * NOTE: numbers occupy part of the column. The posix
+ * spec does not specify if -i processing should or should not
+ * occur on number padding. The spec does say it occupies
+ * part of the column. The usage of addnum currently treats
+ * numbers as part of the column so spaces may be replaced.
+ */
+void
+addnum(char *buf, int wdth, int line)
+{
+ char *pt = buf + wdth;
+
+ do {
+ *--pt = digs[line % 10];
+ line /= 10;
+ } while (line && (pt > buf));
+
+ /*
+ * pad with space as required
+ */
+ while (pt > buf)
+ *--pt = ' ';
+}
+
+/*
+ * prhead(): prints the top of page header
+ *
+ * buf buffer with time field (and offset)
+ * cnt number of chars in buf
+ * fname fname field for header
+ * pagcnt page number
+ */
+int
+prhead(char *buf, const char *fname, int pagcnt)
+{
+ int ips = 0;
+ int ops = 0;
+
+ if ((putchar('\n') == EOF) || (putchar('\n') == EOF)) {
+ pfail();
+ return(1);
+ }
+ /*
+ * posix is not clear if the header is subject to line length
+ * restrictions. The specification for header line format
+ * in the spec clearly does not limit length. No pr currently
+ * restricts header length. However if we need to truncate in
+ * a reasonable way, adjust the length of the printf by
+ * changing HDFMT to allow a length max as an argument to printf.
+ * buf (which contains the offset spaces and time field could
+ * also be trimmed
+ *
+ * note only the offset (if any) is processed for tab expansion
+ */
+ if (offst && otln(buf, offst, &ips, &ops, -1))
+ return(1);
+ (void)printf(HDFMT,buf+offst, fname, pagcnt);
+ return(0);
+}
+
+/*
+ * prtail(): pad page with empty lines (if required) and print page trailer
+ * if requested
+ *
+ * cnt number of lines of padding needed
+ * incomp was a '\n' missing from last line output
+ */
+int
+prtail(int cnt, int incomp)
+{
+ if (nohead) {
+ /*
+ * only pad with no headers when incomplete last line
+ */
+ if (incomp &&
+ ((dspace && (putchar('\n') == EOF)) ||
+ (putchar('\n') == EOF))) {
+ pfail();
+ return(1);
+ }
+ /*
+ * but honor the formfeed request
+ */
+ if (formfeed) {
+ if (putchar('\f') == EOF) {
+ pfail();
+ return(1);
+ }
+ }
+ return(0);
+ }
+ /*
+ * if double space output two \n
+ */
+ if (dspace)
+ cnt *= 2;
+
+ /*
+ * if an odd number of lines per page, add an extra \n
+ */
+ if (addone)
+ ++cnt;
+
+ /*
+ * pad page
+ */
+ if (formfeed) {
+ if ((incomp && (putchar('\n') == EOF)) ||
+ (putchar('\f') == EOF)) {
+ pfail();
+ return(1);
+ }
+ return(0);
+ }
+ cnt += TAILLEN;
+ while (--cnt >= 0) {
+ if (putchar('\n') == EOF) {
+ pfail();
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * terminate(): when a SIGINT is recvd
+ */
+void
+terminate(int which_sig __unused)
+{
+ flsh_errs();
+ exit(1);
+}
+
+
+/*
+ * flsh_errs(): output saved up diagnostic messages after all normal
+ * processing has completed
+ */
+void
+flsh_errs(void)
+{
+ char buf[BUFSIZ];
+
+ (void)fflush(stdout);
+ (void)fflush(err);
+ if (err == stderr)
+ return;
+ rewind(err);
+ while (fgets(buf, BUFSIZ, err) != NULL)
+ (void)fputs(buf, stderr);
+}
+
+void
+mfail(void)
+{
+ (void)fputs("pr: memory allocation failed\n", err);
+}
+
+void
+pfail(void)
+{
+ (void)fprintf(err, "pr: write failure, %s\n", strerror(errno));
+}
+
+void
+usage(void)
+{
+ (void)fputs(
+ "usage: pr [+page] [-col] [-adFfmprt] [-e[ch][gap]] [-h header]\n",
+ err);
+ (void)fputs(
+ " [-i[ch][gap]] [-l line] [-n[ch][width]] [-o offset]\n",err);
+ (void)fputs(
+ " [-L locale] [-s[ch]] [-w width] [-] [file ...]\n", err);
+}
+
+/*
+ * setup: Validate command args, initialize and perform sanity
+ * checks on options
+ */
+int
+setup(int argc, char *argv[])
+{
+ int c;
+ int d_first;
+ int eflag = 0;
+ int iflag = 0;
+ int wflag = 0;
+ int cflag = 0;
+ char *Lflag = NULL;
+
+ if (isatty(fileno(stdout))) {
+ /*
+ * defer diagnostics until processing is done
+ */
+ if ((err = tmpfile()) == NULL) {
+ err = stderr;
+ (void)fputs("Cannot defer diagnostic messages\n",stderr);
+ return(1);
+ }
+ } else
+ err = stderr;
+ while ((c = egetopt(argc, argv, "#adFfmrte?h:i?L:l:n?o:ps?w:")) != -1) {
+ switch (c) {
+ case '+':
+ if ((pgnm = atoi(eoptarg)) < 1) {
+ (void)fputs("pr: +page number must be 1 or more\n",
+ err);
+ return(1);
+ }
+ break;
+ case '-':
+ if ((clcnt = atoi(eoptarg)) < 1) {
+ (void)fputs("pr: -columns must be 1 or more\n",err);
+ return(1);
+ }
+ if (clcnt > 1)
+ ++cflag;
+ break;
+ case 'a':
+ ++across;
+ break;
+ case 'd':
+ ++dspace;
+ break;
+ case 'e':
+ ++eflag;
+ if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
+ inchar = *eoptarg++;
+ else
+ inchar = INCHAR;
+ if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
+ if ((ingap = atoi(eoptarg)) < 0) {
+ (void)fputs(
+ "pr: -e gap must be 0 or more\n", err);
+ return(1);
+ }
+ if (ingap == 0)
+ ingap = INGAP;
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -e %s\n", eoptarg);
+ return(1);
+ } else
+ ingap = INGAP;
+ break;
+ case 'f':
+ ++pausefst;
+ /*FALLTHROUGH*/
+ case 'F':
+ ++formfeed;
+ break;
+ case 'h':
+ header = eoptarg;
+ break;
+ case 'i':
+ ++iflag;
+ if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
+ ochar = *eoptarg++;
+ else
+ ochar = OCHAR;
+ if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
+ if ((ogap = atoi(eoptarg)) < 0) {
+ (void)fputs(
+ "pr: -i gap must be 0 or more\n", err);
+ return(1);
+ }
+ if (ogap == 0)
+ ogap = OGAP;
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -i %s\n", eoptarg);
+ return(1);
+ } else
+ ogap = OGAP;
+ break;
+ case 'L':
+ Lflag = eoptarg;
+ break;
+ case 'l':
+ if (!isdigit((unsigned char)*eoptarg) || ((lines=atoi(eoptarg)) < 1)) {
+ (void)fputs(
+ "pr: number of lines must be 1 or more\n",err);
+ return(1);
+ }
+ break;
+ case 'm':
+ ++merge;
+ break;
+ case 'n':
+ if ((eoptarg != NULL) && !isdigit((unsigned char)*eoptarg))
+ nmchar = *eoptarg++;
+ else
+ nmchar = NMCHAR;
+ if ((eoptarg != NULL) && isdigit((unsigned char)*eoptarg)) {
+ if ((nmwd = atoi(eoptarg)) < 1) {
+ (void)fputs(
+ "pr: -n width must be 1 or more\n",err);
+ return(1);
+ }
+ } else if ((eoptarg != NULL) && (*eoptarg != '\0')) {
+ (void)fprintf(err,
+ "pr: invalid value for -n %s\n", eoptarg);
+ return(1);
+ } else
+ nmwd = NMWD;
+ break;
+ case 'o':
+ if (!isdigit((unsigned char)*eoptarg) || ((offst = atoi(eoptarg))< 1)){
+ (void)fputs("pr: -o offset must be 1 or more\n",
+ err);
+ return(1);
+ }
+ break;
+ case 'p':
+ ++pauseall;
+ break;
+ case 'r':
+ ++nodiag;
+ break;
+ case 's':
+ ++sflag;
+ if (eoptarg == NULL)
+ schar = SCHAR;
+ else {
+ schar = *eoptarg++;
+ if (*eoptarg != '\0') {
+ (void)fprintf(err,
+ "pr: invalid value for -s %s\n",
+ eoptarg);
+ return(1);
+ }
+ }
+ break;
+ case 't':
+ ++nohead;
+ break;
+ case 'w':
+ ++wflag;
+ if ((eoptarg == NULL ) ||
+ !isdigit((unsigned char)*eoptarg) ||
+ ((pgwd = atoi(eoptarg)) < 1)){
+ (void)fputs(
+ "pr: -w width must be 1 or more \n",err);
+ return(1);
+ }
+ break;
+ case '?':
+ default:
+ return(1);
+ }
+ }
+
+ /*
+ * default and sanity checks
+ */
+ if (!clcnt) {
+ if (merge) {
+ if ((clcnt = argc - eoptind) <= 1) {
+ clcnt = CLCNT;
+ merge = 0;
+ }
+ } else
+ clcnt = CLCNT;
+ }
+ if (across) {
+ if (clcnt == 1) {
+ (void)fputs("pr: -a flag requires multiple columns\n",
+ err);
+ return(1);
+ }
+ if (merge) {
+ (void)fputs("pr: -m cannot be used with -a\n", err);
+ return(1);
+ }
+ }
+ if (!wflag) {
+ if (sflag)
+ pgwd = SPGWD;
+ else
+ pgwd = PGWD;
+ }
+ if (cflag || merge) {
+ if (!eflag) {
+ inchar = INCHAR;
+ ingap = INGAP;
+ }
+ if (!iflag) {
+ ochar = OCHAR;
+ ogap = OGAP;
+ }
+ }
+ if (cflag) {
+ if (merge) {
+ (void)fputs(
+ "pr: -m cannot be used with multiple columns\n", err);
+ return(1);
+ }
+ if (nmwd) {
+ colwd = (pgwd + 1 - (clcnt * (nmwd + 2)))/clcnt;
+ pgwd = ((colwd + nmwd + 2) * clcnt) - 1;
+ } else {
+ colwd = (pgwd + 1 - clcnt)/clcnt;
+ pgwd = ((colwd + 1) * clcnt) - 1;
+ }
+ if (colwd < 1) {
+ (void)fprintf(err,
+ "pr: page width is too small for %d columns\n",clcnt);
+ return(1);
+ }
+ }
+ if (!lines)
+ lines = LINES;
+
+ /*
+ * make sure long enough for headers. if not disable
+ */
+ if (lines <= HEADLEN + TAILLEN)
+ ++nohead;
+ else if (!nohead)
+ lines -= HEADLEN + TAILLEN;
+
+ /*
+ * adjust for double space on odd length pages
+ */
+ if (dspace) {
+ if (lines == 1)
+ dspace = 0;
+ else {
+ if (lines & 1)
+ ++addone;
+ lines /= 2;
+ }
+ }
+
+ (void) setlocale(LC_TIME, (Lflag != NULL) ? Lflag : "");
+
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+ timefrmt = strdup(d_first ? TIMEFMTD : TIMEFMTM);
+
+ return(0);
+}
diff --git a/usr.bin/pr/pr.h b/usr.bin/pr/pr.h
new file mode 100644
index 000000000000..374d020a44d2
--- /dev/null
+++ b/usr.bin/pr/pr.h
@@ -0,0 +1,73 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1991 Keith Muller.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * parameter defaults
+ */
+#define CLCNT 1
+#define INCHAR '\t'
+#define INGAP 8
+#define OCHAR '\t'
+#define OGAP 8
+#define LINES 66
+#define NMWD 5
+#define NMCHAR '\t'
+#define SCHAR '\t'
+#define PGWD 72
+#define SPGWD 512
+
+/*
+ * misc default values
+ */
+#define HDFMT "%s %s Page %d\n\n\n"
+#define HEADLEN 5
+#define TAILLEN 5
+#define TIMEFMTD "%e %b %H:%M %Y"
+#define TIMEFMTM "%b %e %H:%M %Y"
+#define FNAME ""
+#define LBUF 8192
+#define HDBUF 512
+
+/*
+ * structure for vertical columns. Used to balance cols on last page
+ */
+struct vcol {
+ char *pt; /* ptr to col */
+ int cnt; /* char count */
+};
diff --git a/usr.bin/pr/tests/Makefile b/usr.bin/pr/tests/Makefile
new file mode 100644
index 000000000000..593e03ae1176
--- /dev/null
+++ b/usr.bin/pr/tests/Makefile
@@ -0,0 +1,15 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= basic2_test
+NETBSD_ATF_TESTS_SH= basic
+
+${PACKAGE}FILES+= across.out
+${PACKAGE}FILES+= d_basic.in
+${PACKAGE}FILES+= d_basic.out
+${PACKAGE}FILES+= merge.out
+${PACKAGE}FILES+= other.in
+${PACKAGE}FILES+= threecol.out
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/pr/tests/Makefile.depend b/usr.bin/pr/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/pr/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/pr/tests/across.out b/usr.bin/pr/tests/across.out
new file mode 100644
index 000000000000..248585c94928
--- /dev/null
+++ b/usr.bin/pr/tests/across.out
@@ -0,0 +1,2 @@
+987 654 321 ghi def abc
+foo bar baz
diff --git a/usr.bin/pr/tests/basic2_test.sh b/usr.bin/pr/tests/basic2_test.sh
new file mode 100644
index 000000000000..399873abcc9e
--- /dev/null
+++ b/usr.bin/pr/tests/basic2_test.sh
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2017 Alan Somers
+#
+# 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.
+#
+
+atf_test_case across
+across_head() {
+ atf_set "descr" "Format columns in round-robin order with pr -a"
+}
+across_body() {
+ atf_check -s exit:0 -o file:$(atf_get_srcdir)/across.out \
+ -x "pr -t -a -2 $(atf_get_srcdir)/other.in"
+}
+
+atf_test_case merge
+merge_head() {
+ atf_set "descr" "Merge two files with pr -m"
+}
+merge_body() {
+ atf_check -s ignore -o file:$(atf_get_srcdir)/merge.out \
+ pr -t -m $(atf_get_srcdir)/d_basic.in $(atf_get_srcdir)/other.in
+}
+
+atf_test_case threecol
+threecol_head() {
+ atf_set "descr" "Format a file with three columns"
+}
+threecol_body() {
+ atf_check -s ignore -o file:$(atf_get_srcdir)/threecol.out \
+ pr -t -3 $(atf_get_srcdir)/other.in
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case across
+ atf_add_test_case merge
+ atf_add_test_case threecol
+}
diff --git a/usr.bin/pr/tests/merge.out b/usr.bin/pr/tests/merge.out
new file mode 100644
index 000000000000..6a95b41e8786
--- /dev/null
+++ b/usr.bin/pr/tests/merge.out
@@ -0,0 +1,3 @@
+123 456 789 987 654 321
+abc def ghi ghi def abc
+ foo bar baz
diff --git a/usr.bin/pr/tests/other.in b/usr.bin/pr/tests/other.in
new file mode 100644
index 000000000000..56f7ab42e3bb
--- /dev/null
+++ b/usr.bin/pr/tests/other.in
@@ -0,0 +1,3 @@
+987 654 321
+ghi def abc
+foo bar baz
diff --git a/usr.bin/pr/tests/threecol.out b/usr.bin/pr/tests/threecol.out
new file mode 100644
index 000000000000..5d680168467c
--- /dev/null
+++ b/usr.bin/pr/tests/threecol.out
@@ -0,0 +1 @@
+987 654 321 ghi def abc foo bar baz
diff --git a/usr.bin/primes/Makefile b/usr.bin/primes/Makefile
new file mode 100644
index 000000000000..d2332d6bdd6b
--- /dev/null
+++ b/usr.bin/primes/Makefile
@@ -0,0 +1,6 @@
+PROG= primes
+SRCS= pattern.c pr_tbl.c primes.c spsp.c
+MAN=
+LIBADD= m
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/primes/Makefile.depend b/usr.bin/primes/Makefile.depend
new file mode 100644
index 000000000000..48660f04f954
--- /dev/null
+++ b/usr.bin/primes/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/primes/pattern.c b/usr.bin/primes/pattern.c
new file mode 100644
index 000000000000..2ac84be69979
--- /dev/null
+++ b/usr.bin/primes/pattern.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Landon Curt Noll.
+ *
+ * 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.
+ */
+
+/*
+ * pattern - the Eratosthenes sieve on odd numbers for 3,5,7,11 and 13
+ *
+ * By: Landon Curt Noll chongo@toad.com
+ *
+ * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+ *
+ * To avoid excessive sieves for small factors, we use the table below to
+ * setup our sieve blocks. Each element represents an odd number starting
+ * with 1. All non-zero elements are factors of 3, 5, 7, 11 and 13.
+ */
+
+#include <stddef.h>
+
+#include "primes.h"
+
+const char pattern[] = {
+1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,
+0,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,
+0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,0,0,1,0,1,
+1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,
+1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0,0,
+1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,
+0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,
+0,0,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,0,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,0,0,0,0,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+0,0,0,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,
+1,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,0,0,0,
+1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,
+0,0,0,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,
+0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,0,0,0,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+0,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,
+0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,0,
+1,0,0,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,
+1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,
+0,0,1,0,0,0,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,
+1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,
+1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,
+1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,0,0,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,
+0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,
+0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,
+1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,
+1,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,0,1,0,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+1,0,0,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,
+0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,
+1,0,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,0,
+0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,
+0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,
+1,0,1,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,0,
+0,0,0,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,1,0,0,0,0,1,0,0,0,
+0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,
+0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,0,
+1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,
+1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,0,1,1,0,1,
+1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,0,
+1,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,
+0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,
+1,0,0,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,1,
+0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,1,
+1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,1,0,1,
+0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,
+1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0,
+1,0,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,
+1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,0,
+0,0,1,1,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,1,
+0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,0,0,0,
+1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,
+1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,1,
+1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,1,0,0,0,0,1,1,0,0,
+1,0,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,0,0,1,0,1,0,0,1,
+0,0,1,1,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,
+0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1
+};
+const size_t pattern_size = (sizeof(pattern)/sizeof(pattern[0]));
diff --git a/usr.bin/primes/pr_tbl.c b/usr.bin/primes/pr_tbl.c
new file mode 100644
index 000000000000..70615b35dfcf
--- /dev/null
+++ b/usr.bin/primes/pr_tbl.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Landon Curt Noll.
+ *
+ * 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.
+ */
+
+/*
+ * prime - prime table
+ *
+ * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
+ *
+ * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+ *
+ * We are able to sieve 2^32-1 because this table has primes up to 65537
+ * and 65537^2 > 2^32-1.
+ */
+
+#include <stddef.h>
+
+#include "primes.h"
+
+const ubig prime[] = {
+2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,
+107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,
+211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,
+317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,
+439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,
+569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,
+677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,
+821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,
+947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,
+1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,
+1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,
+1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,
+1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,
+1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,
+1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,
+1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,
+1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,
+1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,
+2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,
+2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,
+2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,
+2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,
+2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,
+2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,
+2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,
+2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,
+3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,
+3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,
+3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,
+3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,
+3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,
+3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,
+3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,
+3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,
+4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,
+4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,
+4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,
+4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,
+4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,
+4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,
+4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,
+4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,
+5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,
+5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,
+5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,
+5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,
+5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,
+5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,
+5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,
+5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,
+6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,
+6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,
+6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,
+6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,
+6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,
+6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,
+6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,
+6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,
+7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,
+7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,
+7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,
+7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,
+7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,
+7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,
+7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,
+8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,
+8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,
+8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,
+8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,
+8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,
+8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,
+8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,
+9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,
+9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,
+9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,
+9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,
+9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,
+9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,
+9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,
+9967,9973,10007,10009,10037,10039,10061,10067,10069,10079,10091,10093,10099,
+10103,10111,10133,10139,10141,10151,10159,10163,10169,10177,10181,10193,10211,
+10223,10243,10247,10253,10259,10267,10271,10273,10289,10301,10303,10313,10321,
+10331,10333,10337,10343,10357,10369,10391,10399,10427,10429,10433,10453,10457,
+10459,10463,10477,10487,10499,10501,10513,10529,10531,10559,10567,10589,10597,
+10601,10607,10613,10627,10631,10639,10651,10657,10663,10667,10687,10691,10709,
+10711,10723,10729,10733,10739,10753,10771,10781,10789,10799,10831,10837,10847,
+10853,10859,10861,10867,10883,10889,10891,10903,10909,10937,10939,10949,10957,
+10973,10979,10987,10993,11003,11027,11047,11057,11059,11069,11071,11083,11087,
+11093,11113,11117,11119,11131,11149,11159,11161,11171,11173,11177,11197,11213,
+11239,11243,11251,11257,11261,11273,11279,11287,11299,11311,11317,11321,11329,
+11351,11353,11369,11383,11393,11399,11411,11423,11437,11443,11447,11467,11471,
+11483,11489,11491,11497,11503,11519,11527,11549,11551,11579,11587,11593,11597,
+11617,11621,11633,11657,11677,11681,11689,11699,11701,11717,11719,11731,11743,
+11777,11779,11783,11789,11801,11807,11813,11821,11827,11831,11833,11839,11863,
+11867,11887,11897,11903,11909,11923,11927,11933,11939,11941,11953,11959,11969,
+11971,11981,11987,12007,12011,12037,12041,12043,12049,12071,12073,12097,12101,
+12107,12109,12113,12119,12143,12149,12157,12161,12163,12197,12203,12211,12227,
+12239,12241,12251,12253,12263,12269,12277,12281,12289,12301,12323,12329,12343,
+12347,12373,12377,12379,12391,12401,12409,12413,12421,12433,12437,12451,12457,
+12473,12479,12487,12491,12497,12503,12511,12517,12527,12539,12541,12547,12553,
+12569,12577,12583,12589,12601,12611,12613,12619,12637,12641,12647,12653,12659,
+12671,12689,12697,12703,12713,12721,12739,12743,12757,12763,12781,12791,12799,
+12809,12821,12823,12829,12841,12853,12889,12893,12899,12907,12911,12917,12919,
+12923,12941,12953,12959,12967,12973,12979,12983,13001,13003,13007,13009,13033,
+13037,13043,13049,13063,13093,13099,13103,13109,13121,13127,13147,13151,13159,
+13163,13171,13177,13183,13187,13217,13219,13229,13241,13249,13259,13267,13291,
+13297,13309,13313,13327,13331,13337,13339,13367,13381,13397,13399,13411,13417,
+13421,13441,13451,13457,13463,13469,13477,13487,13499,13513,13523,13537,13553,
+13567,13577,13591,13597,13613,13619,13627,13633,13649,13669,13679,13681,13687,
+13691,13693,13697,13709,13711,13721,13723,13729,13751,13757,13759,13763,13781,
+13789,13799,13807,13829,13831,13841,13859,13873,13877,13879,13883,13901,13903,
+13907,13913,13921,13931,13933,13963,13967,13997,13999,14009,14011,14029,14033,
+14051,14057,14071,14081,14083,14087,14107,14143,14149,14153,14159,14173,14177,
+14197,14207,14221,14243,14249,14251,14281,14293,14303,14321,14323,14327,14341,
+14347,14369,14387,14389,14401,14407,14411,14419,14423,14431,14437,14447,14449,
+14461,14479,14489,14503,14519,14533,14537,14543,14549,14551,14557,14561,14563,
+14591,14593,14621,14627,14629,14633,14639,14653,14657,14669,14683,14699,14713,
+14717,14723,14731,14737,14741,14747,14753,14759,14767,14771,14779,14783,14797,
+14813,14821,14827,14831,14843,14851,14867,14869,14879,14887,14891,14897,14923,
+14929,14939,14947,14951,14957,14969,14983,15013,15017,15031,15053,15061,15073,
+15077,15083,15091,15101,15107,15121,15131,15137,15139,15149,15161,15173,15187,
+15193,15199,15217,15227,15233,15241,15259,15263,15269,15271,15277,15287,15289,
+15299,15307,15313,15319,15329,15331,15349,15359,15361,15373,15377,15383,15391,
+15401,15413,15427,15439,15443,15451,15461,15467,15473,15493,15497,15511,15527,
+15541,15551,15559,15569,15581,15583,15601,15607,15619,15629,15641,15643,15647,
+15649,15661,15667,15671,15679,15683,15727,15731,15733,15737,15739,15749,15761,
+15767,15773,15787,15791,15797,15803,15809,15817,15823,15859,15877,15881,15887,
+15889,15901,15907,15913,15919,15923,15937,15959,15971,15973,15991,16001,16007,
+16033,16057,16061,16063,16067,16069,16073,16087,16091,16097,16103,16111,16127,
+16139,16141,16183,16187,16189,16193,16217,16223,16229,16231,16249,16253,16267,
+16273,16301,16319,16333,16339,16349,16361,16363,16369,16381,16411,16417,16421,
+16427,16433,16447,16451,16453,16477,16481,16487,16493,16519,16529,16547,16553,
+16561,16567,16573,16603,16607,16619,16631,16633,16649,16651,16657,16661,16673,
+16691,16693,16699,16703,16729,16741,16747,16759,16763,16787,16811,16823,16829,
+16831,16843,16871,16879,16883,16889,16901,16903,16921,16927,16931,16937,16943,
+16963,16979,16981,16987,16993,17011,17021,17027,17029,17033,17041,17047,17053,
+17077,17093,17099,17107,17117,17123,17137,17159,17167,17183,17189,17191,17203,
+17207,17209,17231,17239,17257,17291,17293,17299,17317,17321,17327,17333,17341,
+17351,17359,17377,17383,17387,17389,17393,17401,17417,17419,17431,17443,17449,
+17467,17471,17477,17483,17489,17491,17497,17509,17519,17539,17551,17569,17573,
+17579,17581,17597,17599,17609,17623,17627,17657,17659,17669,17681,17683,17707,
+17713,17729,17737,17747,17749,17761,17783,17789,17791,17807,17827,17837,17839,
+17851,17863,17881,17891,17903,17909,17911,17921,17923,17929,17939,17957,17959,
+17971,17977,17981,17987,17989,18013,18041,18043,18047,18049,18059,18061,18077,
+18089,18097,18119,18121,18127,18131,18133,18143,18149,18169,18181,18191,18199,
+18211,18217,18223,18229,18233,18251,18253,18257,18269,18287,18289,18301,18307,
+18311,18313,18329,18341,18353,18367,18371,18379,18397,18401,18413,18427,18433,
+18439,18443,18451,18457,18461,18481,18493,18503,18517,18521,18523,18539,18541,
+18553,18583,18587,18593,18617,18637,18661,18671,18679,18691,18701,18713,18719,
+18731,18743,18749,18757,18773,18787,18793,18797,18803,18839,18859,18869,18899,
+18911,18913,18917,18919,18947,18959,18973,18979,19001,19009,19013,19031,19037,
+19051,19069,19073,19079,19081,19087,19121,19139,19141,19157,19163,19181,19183,
+19207,19211,19213,19219,19231,19237,19249,19259,19267,19273,19289,19301,19309,
+19319,19333,19373,19379,19381,19387,19391,19403,19417,19421,19423,19427,19429,
+19433,19441,19447,19457,19463,19469,19471,19477,19483,19489,19501,19507,19531,
+19541,19543,19553,19559,19571,19577,19583,19597,19603,19609,19661,19681,19687,
+19697,19699,19709,19717,19727,19739,19751,19753,19759,19763,19777,19793,19801,
+19813,19819,19841,19843,19853,19861,19867,19889,19891,19913,19919,19927,19937,
+19949,19961,19963,19973,19979,19991,19993,19997,20011,20021,20023,20029,20047,
+20051,20063,20071,20089,20101,20107,20113,20117,20123,20129,20143,20147,20149,
+20161,20173,20177,20183,20201,20219,20231,20233,20249,20261,20269,20287,20297,
+20323,20327,20333,20341,20347,20353,20357,20359,20369,20389,20393,20399,20407,
+20411,20431,20441,20443,20477,20479,20483,20507,20509,20521,20533,20543,20549,
+20551,20563,20593,20599,20611,20627,20639,20641,20663,20681,20693,20707,20717,
+20719,20731,20743,20747,20749,20753,20759,20771,20773,20789,20807,20809,20849,
+20857,20873,20879,20887,20897,20899,20903,20921,20929,20939,20947,20959,20963,
+20981,20983,21001,21011,21013,21017,21019,21023,21031,21059,21061,21067,21089,
+21101,21107,21121,21139,21143,21149,21157,21163,21169,21179,21187,21191,21193,
+21211,21221,21227,21247,21269,21277,21283,21313,21317,21319,21323,21341,21347,
+21377,21379,21383,21391,21397,21401,21407,21419,21433,21467,21481,21487,21491,
+21493,21499,21503,21517,21521,21523,21529,21557,21559,21563,21569,21577,21587,
+21589,21599,21601,21611,21613,21617,21647,21649,21661,21673,21683,21701,21713,
+21727,21737,21739,21751,21757,21767,21773,21787,21799,21803,21817,21821,21839,
+21841,21851,21859,21863,21871,21881,21893,21911,21929,21937,21943,21961,21977,
+21991,21997,22003,22013,22027,22031,22037,22039,22051,22063,22067,22073,22079,
+22091,22093,22109,22111,22123,22129,22133,22147,22153,22157,22159,22171,22189,
+22193,22229,22247,22259,22271,22273,22277,22279,22283,22291,22303,22307,22343,
+22349,22367,22369,22381,22391,22397,22409,22433,22441,22447,22453,22469,22481,
+22483,22501,22511,22531,22541,22543,22549,22567,22571,22573,22613,22619,22621,
+22637,22639,22643,22651,22669,22679,22691,22697,22699,22709,22717,22721,22727,
+22739,22741,22751,22769,22777,22783,22787,22807,22811,22817,22853,22859,22861,
+22871,22877,22901,22907,22921,22937,22943,22961,22963,22973,22993,23003,23011,
+23017,23021,23027,23029,23039,23041,23053,23057,23059,23063,23071,23081,23087,
+23099,23117,23131,23143,23159,23167,23173,23189,23197,23201,23203,23209,23227,
+23251,23269,23279,23291,23293,23297,23311,23321,23327,23333,23339,23357,23369,
+23371,23399,23417,23431,23447,23459,23473,23497,23509,23531,23537,23539,23549,
+23557,23561,23563,23567,23581,23593,23599,23603,23609,23623,23627,23629,23633,
+23663,23669,23671,23677,23687,23689,23719,23741,23743,23747,23753,23761,23767,
+23773,23789,23801,23813,23819,23827,23831,23833,23857,23869,23873,23879,23887,
+23893,23899,23909,23911,23917,23929,23957,23971,23977,23981,23993,24001,24007,
+24019,24023,24029,24043,24049,24061,24071,24077,24083,24091,24097,24103,24107,
+24109,24113,24121,24133,24137,24151,24169,24179,24181,24197,24203,24223,24229,
+24239,24247,24251,24281,24317,24329,24337,24359,24371,24373,24379,24391,24407,
+24413,24419,24421,24439,24443,24469,24473,24481,24499,24509,24517,24527,24533,
+24547,24551,24571,24593,24611,24623,24631,24659,24671,24677,24683,24691,24697,
+24709,24733,24749,24763,24767,24781,24793,24799,24809,24821,24841,24847,24851,
+24859,24877,24889,24907,24917,24919,24923,24943,24953,24967,24971,24977,24979,
+24989,25013,25031,25033,25037,25057,25073,25087,25097,25111,25117,25121,25127,
+25147,25153,25163,25169,25171,25183,25189,25219,25229,25237,25243,25247,25253,
+25261,25301,25303,25307,25309,25321,25339,25343,25349,25357,25367,25373,25391,
+25409,25411,25423,25439,25447,25453,25457,25463,25469,25471,25523,25537,25541,
+25561,25577,25579,25583,25589,25601,25603,25609,25621,25633,25639,25643,25657,
+25667,25673,25679,25693,25703,25717,25733,25741,25747,25759,25763,25771,25793,
+25799,25801,25819,25841,25847,25849,25867,25873,25889,25903,25913,25919,25931,
+25933,25939,25943,25951,25969,25981,25997,25999,26003,26017,26021,26029,26041,
+26053,26083,26099,26107,26111,26113,26119,26141,26153,26161,26171,26177,26183,
+26189,26203,26209,26227,26237,26249,26251,26261,26263,26267,26293,26297,26309,
+26317,26321,26339,26347,26357,26371,26387,26393,26399,26407,26417,26423,26431,
+26437,26449,26459,26479,26489,26497,26501,26513,26539,26557,26561,26573,26591,
+26597,26627,26633,26641,26647,26669,26681,26683,26687,26693,26699,26701,26711,
+26713,26717,26723,26729,26731,26737,26759,26777,26783,26801,26813,26821,26833,
+26839,26849,26861,26863,26879,26881,26891,26893,26903,26921,26927,26947,26951,
+26953,26959,26981,26987,26993,27011,27017,27031,27043,27059,27061,27067,27073,
+27077,27091,27103,27107,27109,27127,27143,27179,27191,27197,27211,27239,27241,
+27253,27259,27271,27277,27281,27283,27299,27329,27337,27361,27367,27397,27407,
+27409,27427,27431,27437,27449,27457,27479,27481,27487,27509,27527,27529,27539,
+27541,27551,27581,27583,27611,27617,27631,27647,27653,27673,27689,27691,27697,
+27701,27733,27737,27739,27743,27749,27751,27763,27767,27773,27779,27791,27793,
+27799,27803,27809,27817,27823,27827,27847,27851,27883,27893,27901,27917,27919,
+27941,27943,27947,27953,27961,27967,27983,27997,28001,28019,28027,28031,28051,
+28057,28069,28081,28087,28097,28099,28109,28111,28123,28151,28163,28181,28183,
+28201,28211,28219,28229,28277,28279,28283,28289,28297,28307,28309,28319,28349,
+28351,28387,28393,28403,28409,28411,28429,28433,28439,28447,28463,28477,28493,
+28499,28513,28517,28537,28541,28547,28549,28559,28571,28573,28579,28591,28597,
+28603,28607,28619,28621,28627,28631,28643,28649,28657,28661,28663,28669,28687,
+28697,28703,28711,28723,28729,28751,28753,28759,28771,28789,28793,28807,28813,
+28817,28837,28843,28859,28867,28871,28879,28901,28909,28921,28927,28933,28949,
+28961,28979,29009,29017,29021,29023,29027,29033,29059,29063,29077,29101,29123,
+29129,29131,29137,29147,29153,29167,29173,29179,29191,29201,29207,29209,29221,
+29231,29243,29251,29269,29287,29297,29303,29311,29327,29333,29339,29347,29363,
+29383,29387,29389,29399,29401,29411,29423,29429,29437,29443,29453,29473,29483,
+29501,29527,29531,29537,29567,29569,29573,29581,29587,29599,29611,29629,29633,
+29641,29663,29669,29671,29683,29717,29723,29741,29753,29759,29761,29789,29803,
+29819,29833,29837,29851,29863,29867,29873,29879,29881,29917,29921,29927,29947,
+29959,29983,29989,30011,30013,30029,30047,30059,30071,30089,30091,30097,30103,
+30109,30113,30119,30133,30137,30139,30161,30169,30181,30187,30197,30203,30211,
+30223,30241,30253,30259,30269,30271,30293,30307,30313,30319,30323,30341,30347,
+30367,30389,30391,30403,30427,30431,30449,30467,30469,30491,30493,30497,30509,
+30517,30529,30539,30553,30557,30559,30577,30593,30631,30637,30643,30649,30661,
+30671,30677,30689,30697,30703,30707,30713,30727,30757,30763,30773,30781,30803,
+30809,30817,30829,30839,30841,30851,30853,30859,30869,30871,30881,30893,30911,
+30931,30937,30941,30949,30971,30977,30983,31013,31019,31033,31039,31051,31063,
+31069,31079,31081,31091,31121,31123,31139,31147,31151,31153,31159,31177,31181,
+31183,31189,31193,31219,31223,31231,31237,31247,31249,31253,31259,31267,31271,
+31277,31307,31319,31321,31327,31333,31337,31357,31379,31387,31391,31393,31397,
+31469,31477,31481,31489,31511,31513,31517,31531,31541,31543,31547,31567,31573,
+31583,31601,31607,31627,31643,31649,31657,31663,31667,31687,31699,31721,31723,
+31727,31729,31741,31751,31769,31771,31793,31799,31817,31847,31849,31859,31873,
+31883,31891,31907,31957,31963,31973,31981,31991,32003,32009,32027,32029,32051,
+32057,32059,32063,32069,32077,32083,32089,32099,32117,32119,32141,32143,32159,
+32173,32183,32189,32191,32203,32213,32233,32237,32251,32257,32261,32297,32299,
+32303,32309,32321,32323,32327,32341,32353,32359,32363,32369,32371,32377,32381,
+32401,32411,32413,32423,32429,32441,32443,32467,32479,32491,32497,32503,32507,
+32531,32533,32537,32561,32563,32569,32573,32579,32587,32603,32609,32611,32621,
+32633,32647,32653,32687,32693,32707,32713,32717,32719,32749,32771,32779,32783,
+32789,32797,32801,32803,32831,32833,32839,32843,32869,32887,32909,32911,32917,
+32933,32939,32941,32957,32969,32971,32983,32987,32993,32999,33013,33023,33029,
+33037,33049,33053,33071,33073,33083,33091,33107,33113,33119,33149,33151,33161,
+33179,33181,33191,33199,33203,33211,33223,33247,33287,33289,33301,33311,33317,
+33329,33331,33343,33347,33349,33353,33359,33377,33391,33403,33409,33413,33427,
+33457,33461,33469,33479,33487,33493,33503,33521,33529,33533,33547,33563,33569,
+33577,33581,33587,33589,33599,33601,33613,33617,33619,33623,33629,33637,33641,
+33647,33679,33703,33713,33721,33739,33749,33751,33757,33767,33769,33773,33791,
+33797,33809,33811,33827,33829,33851,33857,33863,33871,33889,33893,33911,33923,
+33931,33937,33941,33961,33967,33997,34019,34031,34033,34039,34057,34061,34123,
+34127,34129,34141,34147,34157,34159,34171,34183,34211,34213,34217,34231,34253,
+34259,34261,34267,34273,34283,34297,34301,34303,34313,34319,34327,34337,34351,
+34361,34367,34369,34381,34403,34421,34429,34439,34457,34469,34471,34483,34487,
+34499,34501,34511,34513,34519,34537,34543,34549,34583,34589,34591,34603,34607,
+34613,34631,34649,34651,34667,34673,34679,34687,34693,34703,34721,34729,34739,
+34747,34757,34759,34763,34781,34807,34819,34841,34843,34847,34849,34871,34877,
+34883,34897,34913,34919,34939,34949,34961,34963,34981,35023,35027,35051,35053,
+35059,35069,35081,35083,35089,35099,35107,35111,35117,35129,35141,35149,35153,
+35159,35171,35201,35221,35227,35251,35257,35267,35279,35281,35291,35311,35317,
+35323,35327,35339,35353,35363,35381,35393,35401,35407,35419,35423,35437,35447,
+35449,35461,35491,35507,35509,35521,35527,35531,35533,35537,35543,35569,35573,
+35591,35593,35597,35603,35617,35671,35677,35729,35731,35747,35753,35759,35771,
+35797,35801,35803,35809,35831,35837,35839,35851,35863,35869,35879,35897,35899,
+35911,35923,35933,35951,35963,35969,35977,35983,35993,35999,36007,36011,36013,
+36017,36037,36061,36067,36073,36083,36097,36107,36109,36131,36137,36151,36161,
+36187,36191,36209,36217,36229,36241,36251,36263,36269,36277,36293,36299,36307,
+36313,36319,36341,36343,36353,36373,36383,36389,36433,36451,36457,36467,36469,
+36473,36479,36493,36497,36523,36527,36529,36541,36551,36559,36563,36571,36583,
+36587,36599,36607,36629,36637,36643,36653,36671,36677,36683,36691,36697,36709,
+36713,36721,36739,36749,36761,36767,36779,36781,36787,36791,36793,36809,36821,
+36833,36847,36857,36871,36877,36887,36899,36901,36913,36919,36923,36929,36931,
+36943,36947,36973,36979,36997,37003,37013,37019,37021,37039,37049,37057,37061,
+37087,37097,37117,37123,37139,37159,37171,37181,37189,37199,37201,37217,37223,
+37243,37253,37273,37277,37307,37309,37313,37321,37337,37339,37357,37361,37363,
+37369,37379,37397,37409,37423,37441,37447,37463,37483,37489,37493,37501,37507,
+37511,37517,37529,37537,37547,37549,37561,37567,37571,37573,37579,37589,37591,
+37607,37619,37633,37643,37649,37657,37663,37691,37693,37699,37717,37747,37781,
+37783,37799,37811,37813,37831,37847,37853,37861,37871,37879,37889,37897,37907,
+37951,37957,37963,37967,37987,37991,37993,37997,38011,38039,38047,38053,38069,
+38083,38113,38119,38149,38153,38167,38177,38183,38189,38197,38201,38219,38231,
+38237,38239,38261,38273,38281,38287,38299,38303,38317,38321,38327,38329,38333,
+38351,38371,38377,38393,38431,38447,38449,38453,38459,38461,38501,38543,38557,
+38561,38567,38569,38593,38603,38609,38611,38629,38639,38651,38653,38669,38671,
+38677,38693,38699,38707,38711,38713,38723,38729,38737,38747,38749,38767,38783,
+38791,38803,38821,38833,38839,38851,38861,38867,38873,38891,38903,38917,38921,
+38923,38933,38953,38959,38971,38977,38993,39019,39023,39041,39043,39047,39079,
+39089,39097,39103,39107,39113,39119,39133,39139,39157,39161,39163,39181,39191,
+39199,39209,39217,39227,39229,39233,39239,39241,39251,39293,39301,39313,39317,
+39323,39341,39343,39359,39367,39371,39373,39383,39397,39409,39419,39439,39443,
+39451,39461,39499,39503,39509,39511,39521,39541,39551,39563,39569,39581,39607,
+39619,39623,39631,39659,39667,39671,39679,39703,39709,39719,39727,39733,39749,
+39761,39769,39779,39791,39799,39821,39827,39829,39839,39841,39847,39857,39863,
+39869,39877,39883,39887,39901,39929,39937,39953,39971,39979,39983,39989,40009,
+40013,40031,40037,40039,40063,40087,40093,40099,40111,40123,40127,40129,40151,
+40153,40163,40169,40177,40189,40193,40213,40231,40237,40241,40253,40277,40283,
+40289,40343,40351,40357,40361,40387,40423,40427,40429,40433,40459,40471,40483,
+40487,40493,40499,40507,40519,40529,40531,40543,40559,40577,40583,40591,40597,
+40609,40627,40637,40639,40693,40697,40699,40709,40739,40751,40759,40763,40771,
+40787,40801,40813,40819,40823,40829,40841,40847,40849,40853,40867,40879,40883,
+40897,40903,40927,40933,40939,40949,40961,40973,40993,41011,41017,41023,41039,
+41047,41051,41057,41077,41081,41113,41117,41131,41141,41143,41149,41161,41177,
+41179,41183,41189,41201,41203,41213,41221,41227,41231,41233,41243,41257,41263,
+41269,41281,41299,41333,41341,41351,41357,41381,41387,41389,41399,41411,41413,
+41443,41453,41467,41479,41491,41507,41513,41519,41521,41539,41543,41549,41579,
+41593,41597,41603,41609,41611,41617,41621,41627,41641,41647,41651,41659,41669,
+41681,41687,41719,41729,41737,41759,41761,41771,41777,41801,41809,41813,41843,
+41849,41851,41863,41879,41887,41893,41897,41903,41911,41927,41941,41947,41953,
+41957,41959,41969,41981,41983,41999,42013,42017,42019,42023,42043,42061,42071,
+42073,42083,42089,42101,42131,42139,42157,42169,42179,42181,42187,42193,42197,
+42209,42221,42223,42227,42239,42257,42281,42283,42293,42299,42307,42323,42331,
+42337,42349,42359,42373,42379,42391,42397,42403,42407,42409,42433,42437,42443,
+42451,42457,42461,42463,42467,42473,42487,42491,42499,42509,42533,42557,42569,
+42571,42577,42589,42611,42641,42643,42649,42667,42677,42683,42689,42697,42701,
+42703,42709,42719,42727,42737,42743,42751,42767,42773,42787,42793,42797,42821,
+42829,42839,42841,42853,42859,42863,42899,42901,42923,42929,42937,42943,42953,
+42961,42967,42979,42989,43003,43013,43019,43037,43049,43051,43063,43067,43093,
+43103,43117,43133,43151,43159,43177,43189,43201,43207,43223,43237,43261,43271,
+43283,43291,43313,43319,43321,43331,43391,43397,43399,43403,43411,43427,43441,
+43451,43457,43481,43487,43499,43517,43541,43543,43573,43577,43579,43591,43597,
+43607,43609,43613,43627,43633,43649,43651,43661,43669,43691,43711,43717,43721,
+43753,43759,43777,43781,43783,43787,43789,43793,43801,43853,43867,43889,43891,
+43913,43933,43943,43951,43961,43963,43969,43973,43987,43991,43997,44017,44021,
+44027,44029,44041,44053,44059,44071,44087,44089,44101,44111,44119,44123,44129,
+44131,44159,44171,44179,44189,44201,44203,44207,44221,44249,44257,44263,44267,
+44269,44273,44279,44281,44293,44351,44357,44371,44381,44383,44389,44417,44449,
+44453,44483,44491,44497,44501,44507,44519,44531,44533,44537,44543,44549,44563,
+44579,44587,44617,44621,44623,44633,44641,44647,44651,44657,44683,44687,44699,
+44701,44711,44729,44741,44753,44771,44773,44777,44789,44797,44809,44819,44839,
+44843,44851,44867,44879,44887,44893,44909,44917,44927,44939,44953,44959,44963,
+44971,44983,44987,45007,45013,45053,45061,45077,45083,45119,45121,45127,45131,
+45137,45139,45161,45179,45181,45191,45197,45233,45247,45259,45263,45281,45289,
+45293,45307,45317,45319,45329,45337,45341,45343,45361,45377,45389,45403,45413,
+45427,45433,45439,45481,45491,45497,45503,45523,45533,45541,45553,45557,45569,
+45587,45589,45599,45613,45631,45641,45659,45667,45673,45677,45691,45697,45707,
+45737,45751,45757,45763,45767,45779,45817,45821,45823,45827,45833,45841,45853,
+45863,45869,45887,45893,45943,45949,45953,45959,45971,45979,45989,46021,46027,
+46049,46051,46061,46073,46091,46093,46099,46103,46133,46141,46147,46153,46171,
+46181,46183,46187,46199,46219,46229,46237,46261,46271,46273,46279,46301,46307,
+46309,46327,46337,46349,46351,46381,46399,46411,46439,46441,46447,46451,46457,
+46471,46477,46489,46499,46507,46511,46523,46549,46559,46567,46573,46589,46591,
+46601,46619,46633,46639,46643,46649,46663,46679,46681,46687,46691,46703,46723,
+46727,46747,46751,46757,46769,46771,46807,46811,46817,46819,46829,46831,46853,
+46861,46867,46877,46889,46901,46919,46933,46957,46993,46997,47017,47041,47051,
+47057,47059,47087,47093,47111,47119,47123,47129,47137,47143,47147,47149,47161,
+47189,47207,47221,47237,47251,47269,47279,47287,47293,47297,47303,47309,47317,
+47339,47351,47353,47363,47381,47387,47389,47407,47417,47419,47431,47441,47459,
+47491,47497,47501,47507,47513,47521,47527,47533,47543,47563,47569,47581,47591,
+47599,47609,47623,47629,47639,47653,47657,47659,47681,47699,47701,47711,47713,
+47717,47737,47741,47743,47777,47779,47791,47797,47807,47809,47819,47837,47843,
+47857,47869,47881,47903,47911,47917,47933,47939,47947,47951,47963,47969,47977,
+47981,48017,48023,48029,48049,48073,48079,48091,48109,48119,48121,48131,48157,
+48163,48179,48187,48193,48197,48221,48239,48247,48259,48271,48281,48299,48311,
+48313,48337,48341,48353,48371,48383,48397,48407,48409,48413,48437,48449,48463,
+48473,48479,48481,48487,48491,48497,48523,48527,48533,48539,48541,48563,48571,
+48589,48593,48611,48619,48623,48647,48649,48661,48673,48677,48679,48731,48733,
+48751,48757,48761,48767,48779,48781,48787,48799,48809,48817,48821,48823,48847,
+48857,48859,48869,48871,48883,48889,48907,48947,48953,48973,48989,48991,49003,
+49009,49019,49031,49033,49037,49043,49057,49069,49081,49103,49109,49117,49121,
+49123,49139,49157,49169,49171,49177,49193,49199,49201,49207,49211,49223,49253,
+49261,49277,49279,49297,49307,49331,49333,49339,49363,49367,49369,49391,49393,
+49409,49411,49417,49429,49433,49451,49459,49463,49477,49481,49499,49523,49529,
+49531,49537,49547,49549,49559,49597,49603,49613,49627,49633,49639,49663,49667,
+49669,49681,49697,49711,49727,49739,49741,49747,49757,49783,49787,49789,49801,
+49807,49811,49823,49831,49843,49853,49871,49877,49891,49919,49921,49927,49937,
+49939,49943,49957,49991,49993,49999,50021,50023,50033,50047,50051,50053,50069,
+50077,50087,50093,50101,50111,50119,50123,50129,50131,50147,50153,50159,50177,
+50207,50221,50227,50231,50261,50263,50273,50287,50291,50311,50321,50329,50333,
+50341,50359,50363,50377,50383,50387,50411,50417,50423,50441,50459,50461,50497,
+50503,50513,50527,50539,50543,50549,50551,50581,50587,50591,50593,50599,50627,
+50647,50651,50671,50683,50707,50723,50741,50753,50767,50773,50777,50789,50821,
+50833,50839,50849,50857,50867,50873,50891,50893,50909,50923,50929,50951,50957,
+50969,50971,50989,50993,51001,51031,51043,51047,51059,51061,51071,51109,51131,
+51133,51137,51151,51157,51169,51193,51197,51199,51203,51217,51229,51239,51241,
+51257,51263,51283,51287,51307,51329,51341,51343,51347,51349,51361,51383,51407,
+51413,51419,51421,51427,51431,51437,51439,51449,51461,51473,51479,51481,51487,
+51503,51511,51517,51521,51539,51551,51563,51577,51581,51593,51599,51607,51613,
+51631,51637,51647,51659,51673,51679,51683,51691,51713,51719,51721,51749,51767,
+51769,51787,51797,51803,51817,51827,51829,51839,51853,51859,51869,51871,51893,
+51899,51907,51913,51929,51941,51949,51971,51973,51977,51991,52009,52021,52027,
+52051,52057,52067,52069,52081,52103,52121,52127,52147,52153,52163,52177,52181,
+52183,52189,52201,52223,52237,52249,52253,52259,52267,52289,52291,52301,52313,
+52321,52361,52363,52369,52379,52387,52391,52433,52453,52457,52489,52501,52511,
+52517,52529,52541,52543,52553,52561,52567,52571,52579,52583,52609,52627,52631,
+52639,52667,52673,52691,52697,52709,52711,52721,52727,52733,52747,52757,52769,
+52783,52807,52813,52817,52837,52859,52861,52879,52883,52889,52901,52903,52919,
+52937,52951,52957,52963,52967,52973,52981,52999,53003,53017,53047,53051,53069,
+53077,53087,53089,53093,53101,53113,53117,53129,53147,53149,53161,53171,53173,
+53189,53197,53201,53231,53233,53239,53267,53269,53279,53281,53299,53309,53323,
+53327,53353,53359,53377,53381,53401,53407,53411,53419,53437,53441,53453,53479,
+53503,53507,53527,53549,53551,53569,53591,53593,53597,53609,53611,53617,53623,
+53629,53633,53639,53653,53657,53681,53693,53699,53717,53719,53731,53759,53773,
+53777,53783,53791,53813,53819,53831,53849,53857,53861,53881,53887,53891,53897,
+53899,53917,53923,53927,53939,53951,53959,53987,53993,54001,54011,54013,54037,
+54049,54059,54083,54091,54101,54121,54133,54139,54151,54163,54167,54181,54193,
+54217,54251,54269,54277,54287,54293,54311,54319,54323,54331,54347,54361,54367,
+54371,54377,54401,54403,54409,54413,54419,54421,54437,54443,54449,54469,54493,
+54497,54499,54503,54517,54521,54539,54541,54547,54559,54563,54577,54581,54583,
+54601,54617,54623,54629,54631,54647,54667,54673,54679,54709,54713,54721,54727,
+54751,54767,54773,54779,54787,54799,54829,54833,54851,54869,54877,54881,54907,
+54917,54919,54941,54949,54959,54973,54979,54983,55001,55009,55021,55049,55051,
+55057,55061,55073,55079,55103,55109,55117,55127,55147,55163,55171,55201,55207,
+55213,55217,55219,55229,55243,55249,55259,55291,55313,55331,55333,55337,55339,
+55343,55351,55373,55381,55399,55411,55439,55441,55457,55469,55487,55501,55511,
+55529,55541,55547,55579,55589,55603,55609,55619,55621,55631,55633,55639,55661,
+55663,55667,55673,55681,55691,55697,55711,55717,55721,55733,55763,55787,55793,
+55799,55807,55813,55817,55819,55823,55829,55837,55843,55849,55871,55889,55897,
+55901,55903,55921,55927,55931,55933,55949,55967,55987,55997,56003,56009,56039,
+56041,56053,56081,56087,56093,56099,56101,56113,56123,56131,56149,56167,56171,
+56179,56197,56207,56209,56237,56239,56249,56263,56267,56269,56299,56311,56333,
+56359,56369,56377,56383,56393,56401,56417,56431,56437,56443,56453,56467,56473,
+56477,56479,56489,56501,56503,56509,56519,56527,56531,56533,56543,56569,56591,
+56597,56599,56611,56629,56633,56659,56663,56671,56681,56687,56701,56711,56713,
+56731,56737,56747,56767,56773,56779,56783,56807,56809,56813,56821,56827,56843,
+56857,56873,56891,56893,56897,56909,56911,56921,56923,56929,56941,56951,56957,
+56963,56983,56989,56993,56999,57037,57041,57047,57059,57073,57077,57089,57097,
+57107,57119,57131,57139,57143,57149,57163,57173,57179,57191,57193,57203,57221,
+57223,57241,57251,57259,57269,57271,57283,57287,57301,57329,57331,57347,57349,
+57367,57373,57383,57389,57397,57413,57427,57457,57467,57487,57493,57503,57527,
+57529,57557,57559,57571,57587,57593,57601,57637,57641,57649,57653,57667,57679,
+57689,57697,57709,57713,57719,57727,57731,57737,57751,57773,57781,57787,57791,
+57793,57803,57809,57829,57839,57847,57853,57859,57881,57899,57901,57917,57923,
+57943,57947,57973,57977,57991,58013,58027,58031,58043,58049,58057,58061,58067,
+58073,58099,58109,58111,58129,58147,58151,58153,58169,58171,58189,58193,58199,
+58207,58211,58217,58229,58231,58237,58243,58271,58309,58313,58321,58337,58363,
+58367,58369,58379,58391,58393,58403,58411,58417,58427,58439,58441,58451,58453,
+58477,58481,58511,58537,58543,58549,58567,58573,58579,58601,58603,58613,58631,
+58657,58661,58679,58687,58693,58699,58711,58727,58733,58741,58757,58763,58771,
+58787,58789,58831,58889,58897,58901,58907,58909,58913,58921,58937,58943,58963,
+58967,58979,58991,58997,59009,59011,59021,59023,59029,59051,59053,59063,59069,
+59077,59083,59093,59107,59113,59119,59123,59141,59149,59159,59167,59183,59197,
+59207,59209,59219,59221,59233,59239,59243,59263,59273,59281,59333,59341,59351,
+59357,59359,59369,59377,59387,59393,59399,59407,59417,59419,59441,59443,59447,
+59453,59467,59471,59473,59497,59509,59513,59539,59557,59561,59567,59581,59611,
+59617,59621,59627,59629,59651,59659,59663,59669,59671,59693,59699,59707,59723,
+59729,59743,59747,59753,59771,59779,59791,59797,59809,59833,59863,59879,59887,
+59921,59929,59951,59957,59971,59981,59999,60013,60017,60029,60037,60041,60077,
+60083,60089,60091,60101,60103,60107,60127,60133,60139,60149,60161,60167,60169,
+60209,60217,60223,60251,60257,60259,60271,60289,60293,60317,60331,60337,60343,
+60353,60373,60383,60397,60413,60427,60443,60449,60457,60493,60497,60509,60521,
+60527,60539,60589,60601,60607,60611,60617,60623,60631,60637,60647,60649,60659,
+60661,60679,60689,60703,60719,60727,60733,60737,60757,60761,60763,60773,60779,
+60793,60811,60821,60859,60869,60887,60889,60899,60901,60913,60917,60919,60923,
+60937,60943,60953,60961,61001,61007,61027,61031,61043,61051,61057,61091,61099,
+61121,61129,61141,61151,61153,61169,61211,61223,61231,61253,61261,61283,61291,
+61297,61331,61333,61339,61343,61357,61363,61379,61381,61403,61409,61417,61441,
+61463,61469,61471,61483,61487,61493,61507,61511,61519,61543,61547,61553,61559,
+61561,61583,61603,61609,61613,61627,61631,61637,61643,61651,61657,61667,61673,
+61681,61687,61703,61717,61723,61729,61751,61757,61781,61813,61819,61837,61843,
+61861,61871,61879,61909,61927,61933,61949,61961,61967,61979,61981,61987,61991,
+62003,62011,62017,62039,62047,62053,62057,62071,62081,62099,62119,62129,62131,
+62137,62141,62143,62171,62189,62191,62201,62207,62213,62219,62233,62273,62297,
+62299,62303,62311,62323,62327,62347,62351,62383,62401,62417,62423,62459,62467,
+62473,62477,62483,62497,62501,62507,62533,62539,62549,62563,62581,62591,62597,
+62603,62617,62627,62633,62639,62653,62659,62683,62687,62701,62723,62731,62743,
+62753,62761,62773,62791,62801,62819,62827,62851,62861,62869,62873,62897,62903,
+62921,62927,62929,62939,62969,62971,62981,62983,62987,62989,63029,63031,63059,
+63067,63073,63079,63097,63103,63113,63127,63131,63149,63179,63197,63199,63211,
+63241,63247,63277,63281,63299,63311,63313,63317,63331,63337,63347,63353,63361,
+63367,63377,63389,63391,63397,63409,63419,63421,63439,63443,63463,63467,63473,
+63487,63493,63499,63521,63527,63533,63541,63559,63577,63587,63589,63599,63601,
+63607,63611,63617,63629,63647,63649,63659,63667,63671,63689,63691,63697,63703,
+63709,63719,63727,63737,63743,63761,63773,63781,63793,63799,63803,63809,63823,
+63839,63841,63853,63857,63863,63901,63907,63913,63929,63949,63977,63997,64007,
+64013,64019,64033,64037,64063,64067,64081,64091,64109,64123,64151,64153,64157,
+64171,64187,64189,64217,64223,64231,64237,64271,64279,64283,64301,64303,64319,
+64327,64333,64373,64381,64399,64403,64433,64439,64451,64453,64483,64489,64499,
+64513,64553,64567,64577,64579,64591,64601,64609,64613,64621,64627,64633,64661,
+64663,64667,64679,64693,64709,64717,64747,64763,64781,64783,64793,64811,64817,
+64849,64853,64871,64877,64879,64891,64901,64919,64921,64927,64937,64951,64969,
+64997,65003,65011,65027,65029,65033,65053,65063,65071,65089,65099,65101,65111,
+65119,65123,65129,65141,65147,65167,65171,65173,65179,65183,65203,65213,65239,
+65257,65267,65269,65287,65293,65309,65323,65327,65353,65357,65371,65381,65393,
+65407,65413,65419,65423,65437,65447,65449,65479,65497,65519,65521,65537
+};
+
+/* pr_limit - largest prime in the prime table */
+const ubig *const pr_limit = &prime[(sizeof(prime)/sizeof(prime[0]))-1];
diff --git a/usr.bin/primes/primes.c b/usr.bin/primes/primes.c
new file mode 100644
index 000000000000..d556a19a1553
--- /dev/null
+++ b/usr.bin/primes/primes.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Landon Curt Noll.
+ *
+ * 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.
+ */
+
+/*
+ * primes - generate a table of primes between two values
+ *
+ * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
+ *
+ * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+ *
+ * usage:
+ * primes [-h] [start [stop]]
+ *
+ * Print primes >= start and < stop. If stop is omitted,
+ * the value 18446744073709551615 (2^64-1) is assumed. If
+ * start is omitted, start is read from standard input.
+ *
+ * validation check: there are 664579 primes between 0 and 10^7
+ */
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <nl_types.h>
+#include <unistd.h>
+
+#include "primes.h"
+
+/*
+ * Eratosthenes sieve table
+ *
+ * We only sieve the odd numbers. The base of our sieve windows are always
+ * odd. If the base of table is 1, table[i] represents 2*i-1. After the
+ * sieve, table[i] == 1 if and only if 2*i-1 is prime.
+ *
+ * We make TABSIZE large to reduce the overhead of inner loop setup.
+ */
+static char table[TABSIZE]; /* Eratosthenes sieve of odd numbers */
+
+static int hflag;
+
+static void primes(ubig, ubig);
+static ubig read_num_buf(void);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ ubig start; /* where to start generating */
+ ubig stop; /* don't generate at or above this value */
+ int ch;
+ char *p;
+
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(1, "cap_enter");
+
+ while ((ch = getopt(argc, argv, "h")) != -1)
+ switch (ch) {
+ case 'h':
+ hflag++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ start = 0;
+ stop = (uint64_t)(-1);
+
+ /*
+ * Convert low and high args. Strtoumax(3) sets errno to
+ * ERANGE if the number is too large, but, if there's
+ * a leading minus sign it returns the negation of the
+ * result of the conversion, which we'd rather disallow.
+ */
+ switch (argc) {
+ case 2:
+ /* Start and stop supplied on the command line. */
+ if (argv[0][0] == '-' || argv[1][0] == '-')
+ errx(1, "negative numbers aren't permitted.");
+
+ errno = 0;
+ start = strtoumax(argv[0], &p, 0);
+ if (errno)
+ err(1, "%s", argv[0]);
+ if (*p != '\0')
+ errx(1, "%s: illegal numeric format.", argv[0]);
+
+ errno = 0;
+ stop = strtoumax(argv[1], &p, 0);
+ if (errno)
+ err(1, "%s", argv[1]);
+ if (*p != '\0')
+ errx(1, "%s: illegal numeric format.", argv[1]);
+ break;
+ case 1:
+ /* Start on the command line. */
+ if (argv[0][0] == '-')
+ errx(1, "negative numbers aren't permitted.");
+
+ errno = 0;
+ start = strtoumax(argv[0], &p, 0);
+ if (errno)
+ err(1, "%s", argv[0]);
+ if (*p != '\0')
+ errx(1, "%s: illegal numeric format.", argv[0]);
+ break;
+ case 0:
+ start = read_num_buf();
+ break;
+ default:
+ usage();
+ }
+
+ if (start > stop)
+ errx(1, "start value must be less than stop value.");
+ primes(start, stop);
+ return (0);
+}
+
+/*
+ * read_num_buf --
+ * This routine returns a number n, where 0 <= n && n <= BIG.
+ */
+static ubig
+read_num_buf(void)
+{
+ ubig val;
+ char *p, buf[LINE_MAX]; /* > max number of digits. */
+
+ for (;;) {
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ if (ferror(stdin))
+ err(1, "stdin");
+ exit(0);
+ }
+ for (p = buf; isblank(*p); ++p);
+ if (*p == '\n' || *p == '\0')
+ continue;
+ if (*p == '-')
+ errx(1, "negative numbers aren't permitted.");
+ errno = 0;
+ val = strtoumax(buf, &p, 0);
+ if (errno)
+ err(1, "%s", buf);
+ if (*p != '\n')
+ errx(1, "%s: illegal numeric format.", buf);
+ return (val);
+ }
+}
+
+/*
+ * primes - sieve and print primes from start up to and but not including stop
+ */
+static void
+primes(ubig start, ubig stop)
+{
+ char *q; /* sieve spot */
+ ubig factor; /* index and factor */
+ char *tab_lim; /* the limit to sieve on the table */
+ const ubig *p; /* prime table pointer */
+ ubig fact_lim; /* highest prime for current block */
+ ubig mod; /* temp storage for mod */
+
+ /*
+ * A number of systems can not convert double values into unsigned
+ * longs when the values are larger than the largest signed value.
+ * We don't have this problem, so we can go all the way to BIG.
+ */
+ if (start < 3) {
+ start = (ubig)2;
+ }
+ if (stop < 3) {
+ stop = (ubig)2;
+ }
+ if (stop <= start) {
+ return;
+ }
+
+ /*
+ * be sure that the values are odd, or 2
+ */
+ if (start != 2 && (start&0x1) == 0) {
+ ++start;
+ }
+ if (stop != 2 && (stop&0x1) == 0) {
+ ++stop;
+ }
+
+ /*
+ * quick list of primes <= pr_limit
+ */
+ if (start <= *pr_limit) {
+ /* skip primes up to the start value */
+ for (p = &prime[0], factor = prime[0];
+ factor < stop && p <= pr_limit; factor = *(++p)) {
+ if (factor >= start) {
+ printf(hflag ? "%" PRIx64 "\n" : "%" PRIu64 "\n", factor);
+ }
+ }
+ /* return early if we are done */
+ if (p <= pr_limit) {
+ return;
+ }
+ start = *pr_limit+2;
+ }
+
+ /*
+ * we shall sieve a bytemap window, note primes and move the window
+ * upward until we pass the stop point
+ */
+ while (start < stop) {
+ /*
+ * factor out 3, 5, 7, 11 and 13
+ */
+ /* initial pattern copy */
+ factor = (start%(2*3*5*7*11*13))/2; /* starting copy spot */
+ memcpy(table, &pattern[factor], pattern_size-factor);
+ /* main block pattern copies */
+ for (fact_lim=pattern_size-factor;
+ fact_lim+pattern_size<=TABSIZE; fact_lim+=pattern_size) {
+ memcpy(&table[fact_lim], pattern, pattern_size);
+ }
+ /* final block pattern copy */
+ memcpy(&table[fact_lim], pattern, TABSIZE-fact_lim);
+
+ /*
+ * sieve for primes 17 and higher
+ */
+ /* note highest useful factor and sieve spot */
+ if (stop-start > TABSIZE+TABSIZE) {
+ tab_lim = &table[TABSIZE]; /* sieve it all */
+ fact_lim = sqrt(start+1.0+TABSIZE+TABSIZE);
+ } else {
+ tab_lim = &table[(stop-start)/2]; /* partial sieve */
+ fact_lim = sqrt(stop+1.0);
+ }
+ /* sieve for factors >= 17 */
+ factor = 17; /* 17 is first prime to use */
+ p = &prime[7]; /* 19 is next prime, pi(19)=7 */
+ do {
+ /* determine the factor's initial sieve point */
+ mod = start%factor;
+ if (mod & 0x1) {
+ q = &table[(factor-mod)/2];
+ } else {
+ q = &table[mod ? factor-(mod/2) : 0];
+ }
+ /* sive for our current factor */
+ for ( ; q < tab_lim; q += factor) {
+ *q = '\0'; /* sieve out a spot */
+ }
+ factor = *p++;
+ } while (factor <= fact_lim);
+
+ /*
+ * print generated primes
+ */
+ for (q = table; q < tab_lim; ++q, start+=2) {
+ if (*q) {
+ if (start > SIEVEMAX) {
+ if (!isprime(start))
+ continue;
+ }
+ printf(hflag ? "%" PRIx64 "\n" : "%" PRIu64 "\n", start);
+ }
+ }
+ }
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: primes [-h] [start [stop]]\n");
+ exit(1);
+}
diff --git a/usr.bin/primes/primes.h b/usr.bin/primes/primes.h
new file mode 100644
index 000000000000..bb497e8a5f9e
--- /dev/null
+++ b/usr.bin/primes/primes.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Landon Curt Noll.
+ *
+ * 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.
+ */
+
+/*
+ * primes - generate a table of primes between two values
+ *
+ * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo
+ *
+ * chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
+ */
+
+#include <stdint.h>
+
+/* ubig is the type that holds a large unsigned value */
+typedef uint64_t ubig; /* must be >=32 bit unsigned value */
+#define BIG ULONG_MAX /* largest value will sieve */
+
+/* bytes in sieve table (must be > 3*5*7*11) */
+#define TABSIZE 256*1024
+
+/*
+ * prime[i] is the (i-1)th prime.
+ *
+ * We are able to sieve 2^32-1 because this byte table yields all primes
+ * up to 65537 and 65537^2 > 2^32-1.
+ */
+extern const ubig prime[];
+extern const ubig *const pr_limit; /* largest prime in the prime array */
+
+/* Maximum size sieving alone can handle. */
+#define SIEVEMAX 4295098368ULL
+
+/*
+ * To avoid excessive sieves for small factors, we use the table below to
+ * setup our sieve blocks. Each element represents an odd number starting
+ * with 1. All non-zero elements are factors of 3, 5, 7, 11 and 13.
+ */
+extern const char pattern[];
+extern const size_t pattern_size; /* length of pattern array */
+
+/* Test for primality using strong pseudoprime tests. */
+int isprime(ubig);
diff --git a/usr.bin/primes/spsp.c b/usr.bin/primes/spsp.c
new file mode 100644
index 000000000000..a07dbab016c1
--- /dev/null
+++ b/usr.bin/primes/spsp.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2014 Colin Percival
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "primes.h"
+
+/* Return a * b % n, where 0 < n. */
+static uint64_t
+mulmod(uint64_t a, uint64_t b, uint64_t n)
+{
+ uint64_t x = 0;
+ uint64_t an = a % n;
+
+ while (b != 0) {
+ if (b & 1) {
+ x += an;
+ if ((x < an) || (x >= n))
+ x -= n;
+ }
+ if (an + an < an)
+ an = an + an - n;
+ else if (an + an >= n)
+ an = an + an - n;
+ else
+ an = an + an;
+ b >>= 1;
+ }
+
+ return (x);
+}
+
+/* Return a^r % n, where 0 < n. */
+static uint64_t
+powmod(uint64_t a, uint64_t r, uint64_t n)
+{
+ uint64_t x = 1;
+
+ while (r != 0) {
+ if (r & 1)
+ x = mulmod(a, x, n);
+ a = mulmod(a, a, n);
+ r >>= 1;
+ }
+
+ return (x);
+}
+
+/* Return non-zero if n is a strong pseudoprime to base p. */
+static int
+spsp(uint64_t n, uint64_t p)
+{
+ uint64_t x;
+ uint64_t r = n - 1;
+ int k = 0;
+
+ /* Compute n - 1 = 2^k * r. */
+ while ((r & 1) == 0) {
+ k++;
+ r >>= 1;
+ }
+
+ /* Compute x = p^r mod n. If x = 1, n is a p-spsp. */
+ x = powmod(p, r, n);
+ if (x == 1)
+ return (1);
+
+ /* Compute x^(2^i) for 0 <= i < n. If any are -1, n is a p-spsp. */
+ while (k > 0) {
+ if (x == n - 1)
+ return (1);
+ x = powmod(x, 2, n);
+ k--;
+ }
+
+ /* Not a p-spsp. */
+ return (0);
+}
+
+/* Test for primality using strong pseudoprime tests. */
+int
+isprime(ubig _n)
+{
+ uint64_t n = _n;
+
+ /*
+ * Values from:
+ * C. Pomerance, J.L. Selfridge, and S.S. Wagstaff, Jr.,
+ * The pseudoprimes to 25 * 10^9, Math. Comp. 35(151):1003-1026, 1980.
+ */
+
+ /* No SPSPs to base 2 less than 2047. */
+ if (!spsp(n, 2))
+ return (0);
+ if (n < 2047ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3 less than 1373653. */
+ if (!spsp(n, 3))
+ return (0);
+ if (n < 1373653ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5 less than 25326001. */
+ if (!spsp(n, 5))
+ return (0);
+ if (n < 25326001ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7 less than 3215031751. */
+ if (!spsp(n, 7))
+ return (0);
+ if (n < 3215031751ULL)
+ return (1);
+
+ /*
+ * Values from:
+ * G. Jaeschke, On strong pseudoprimes to several bases,
+ * Math. Comp. 61(204):915-926, 1993.
+ */
+
+ /* No SPSPs to bases 2,3,5,7,11 less than 2152302898747. */
+ if (!spsp(n, 11))
+ return (0);
+ if (n < 2152302898747ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13 less than 3474749660383. */
+ if (!spsp(n, 13))
+ return (0);
+ if (n < 3474749660383ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13,17 less than 341550071728321. */
+ if (!spsp(n, 17))
+ return (0);
+ if (n < 341550071728321ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13,17,19 less than 341550071728321. */
+ if (!spsp(n, 19))
+ return (0);
+ if (n < 341550071728321ULL)
+ return (1);
+
+ /*
+ * Value from:
+ * Y. Jiang and Y. Deng, Strong pseudoprimes to the first eight prime
+ * bases, Math. Comp. 83(290):2915-2924, 2014.
+ */
+
+ /* No SPSPs to bases 2..23 less than 3825123056546413051. */
+ if (!spsp(n, 23))
+ return (0);
+ if (n < 3825123056546413051)
+ return (1);
+
+ /*
+ * Value from:
+ * J. Sorenson and J. Webster, Strong pseudoprimes to twelve prime
+ * bases, Math. Comp. 86(304):985-1003, 2017.
+ */
+
+ /* No SPSPs to bases 2..37 less than 318665857834031151167461. */
+ if (!spsp(n, 29))
+ return (0);
+ if (!spsp(n, 31))
+ return (0);
+ if (!spsp(n, 37))
+ return (0);
+
+ /* All 64-bit values are less than 318665857834031151167461. */
+ return (1);
+}
diff --git a/usr.bin/printenv/Makefile b/usr.bin/printenv/Makefile
new file mode 100644
index 000000000000..0add0695a1d7
--- /dev/null
+++ b/usr.bin/printenv/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= printenv
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk> \ No newline at end of file
diff --git a/usr.bin/printenv/Makefile.depend b/usr.bin/printenv/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/printenv/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/printenv/printenv.1 b/usr.bin/printenv/printenv.1
new file mode 100644
index 000000000000..e782023e03ac
--- /dev/null
+++ b/usr.bin/printenv/printenv.1
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1980, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd May 12, 2003
+.Dt PRINTENV 1
+.Os
+.Sh NAME
+.Nm printenv
+.Nd print out the environment
+.Sh SYNOPSIS
+.Nm
+.Op Ar name
+.Sh DESCRIPTION
+The
+.Nm
+utility prints out the names and values of the variables in the environment,
+with one name/value pair per line.
+If
+.Ar name
+is specified, only
+its value is printed.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr env 1 ,
+.Xr sh 1 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Nm
+utility is provided for compatibility with earlier
+.Bx
+and
+.Fx
+releases and is not specified by any standards.
+The functionality of
+.Nm
+can be duplicated with the
+.Xr echo 1
+and
+.Xr env 1
+utilities.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/printenv/printenv.c b/usr.bin/printenv/printenv.c
new file mode 100644
index 000000000000..43dbdb0c1378
--- /dev/null
+++ b/usr.bin/printenv/printenv.c
@@ -0,0 +1,91 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 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.
+ */
+
+#include <sys/types.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+void usage(void);
+extern char **environ;
+
+/*
+ * printenv
+ *
+ * Bill Joy, UCB
+ * February, 1979
+ */
+int
+main(int argc, char *argv[])
+{
+ char *cp, **ep;
+ size_t len;
+ int ch;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0) {
+ for (ep = environ; *ep; ep++)
+ (void)printf("%s\n", *ep);
+ exit(0);
+ }
+ len = strlen(*argv);
+ for (ep = environ; *ep; ep++)
+ if (!memcmp(*ep, *argv, len)) {
+ cp = *ep + len;
+ if (*cp == '=') {
+ (void)printf("%s\n", cp + 1);
+ exit(0);
+ }
+ }
+ exit(1);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: printenv [name]\n");
+ exit(1);
+}
diff --git a/usr.bin/printenv/tests/Makefile b/usr.bin/printenv/tests/Makefile
new file mode 100644
index 000000000000..7c5599f222d3
--- /dev/null
+++ b/usr.bin/printenv/tests/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= printenv_test
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/printenv/tests/Makefile.depend b/usr.bin/printenv/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/printenv/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/printenv/tests/printenv_test.sh b/usr.bin/printenv/tests/printenv_test.sh
new file mode 100644
index 000000000000..754ad75d3b5b
--- /dev/null
+++ b/usr.bin/printenv/tests/printenv_test.sh
@@ -0,0 +1,64 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023 The FreeBSD Foundation
+#
+# This software was developed by Yan-Hao Wang <bses30074@gmail.com>
+# under sponsorship from the FreeBSD Foundation.
+#
+# 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 AUTHOR 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 AUTHOR 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
+#
+
+atf_test_case base
+base_head()
+{
+ atf_set "descr" "Check that all reported variables exist with the reported values."
+}
+base_body()
+{
+ printenv | while IFS= read -r env; do
+ env_name=${env%%=*}
+ env_value=${env#*=}
+ expected_value=$(eval echo "\$$env_name")
+ atf_check_equal "${env_value}" "${expected_value}"
+ done
+}
+
+atf_test_case add_delete_env
+add_delete_env_head()
+{
+ atf_set "descr" "New changes to the environment should be reflected in printenv's output"
+}
+add_delete_env_body()
+{
+ env_name=$(date +"%Y%m%d%H%M%S")
+ export "env_${env_name}=value"
+ atf_check -o inline:"value\n" printenv "env_${env_name}"
+ unset "env_${env_name}"
+ atf_check -s exit:1 printenv "env_${env_name}"
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case base
+ atf_add_test_case add_delete_env
+}
diff --git a/usr.bin/printf/Makefile b/usr.bin/printf/Makefile
new file mode 100644
index 000000000000..f6339749708b
--- /dev/null
+++ b/usr.bin/printf/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= printf
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/printf/Makefile.depend b/usr.bin/printf/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/printf/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/printf/printf.1 b/usr.bin/printf/printf.1
new file mode 100644
index 000000000000..373d3ccacc36
--- /dev/null
+++ b/usr.bin/printf/printf.1
@@ -0,0 +1,415 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd July 1, 2020
+.Dt PRINTF 1
+.Os
+.Sh NAME
+.Nm printf
+.Nd formatted output
+.Sh SYNOPSIS
+.Nm
+.Ar format Op Ar arguments ...
+.Sh DESCRIPTION
+The
+.Nm
+utility 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 c , b
+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
+character 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 the
+.St -ansiC ,
+with extensions.
+The characters and their meanings
+are as follows:
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Cm \ea
+Write a <bell> character.
+.It Cm \eb
+Write a <backspace> character.
+.It Cm \ef
+Write a <form-feed> character.
+.It Cm \en
+Write a <new-line> character.
+.It Cm \er
+Write a <carriage return> character.
+.It Cm \et
+Write a <tab> character.
+.It Cm \ev
+Write a <vertical tab> character.
+.It Cm \e\'
+Write a <single quote> character.
+.It Cm \e\e
+Write a backslash character.
+.It Cm \e Ns Ar num
+Write a byte whose
+value is the 1-, 2-, or 3-digit
+octal number
+.Ar num .
+Multibyte characters can be constructed using multiple
+.Cm \e Ns Ar num
+sequences.
+.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 ``alternate form''.
+For
+.Cm b , c , d , s
+and
+.Cm u
+formats, this option has no effect.
+For the
+.Cm o
+formats 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 a , A , e , E , f , F , 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 bytes 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; 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 diouxXfFeEgGaAcsb ) .
+The uppercase formats differ from their lowercase counterparts only in
+that the output of the former is entirely in uppercase.
+The floating-point format specifiers
+.Pq Cm fFeEgGaA
+may be prefixed by an
+.Cm L
+to request that additional precision be used, if available.
+.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 fF
+The
+.Ar argument
+is printed in the style `[\-]ddd.ddd' 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.
+The values \*[If] and \*[Na] are printed as
+.Ql inf
+and
+.Ql nan ,
+respectively.
+.It Cm eE
+The
+.Ar argument
+is printed in the style
+.Cm e
+.Sm off
+.Sq Op - Ar d.ddd No \(+- Ar dd
+.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.
+The values \*[If] and \*[Na] are printed as
+.Ql inf
+and
+.Ql nan ,
+respectively.
+.It Cm gG
+The
+.Ar argument
+is printed in style
+.Cm f
+.Pq Cm F
+or in style
+.Cm e
+.Pq Cm E
+whichever gives full precision in minimum space.
+.It Cm aA
+The
+.Ar argument
+is printed in style
+.Sm off
+.Sq Op - Ar h.hhh No \(+- Li p Ar d
+.Sm on
+where there is one digit before the hexadecimal point and the number
+after is equal to the precision specification for the argument;
+when the precision is missing, enough digits are produced to convey
+the argument's exact double-precision floating-point representation.
+The values \*[If] and \*[Na] are printed as
+.Ql inf
+and
+.Ql nan ,
+respectively.
+.It Cm c
+The first byte of
+.Ar argument
+is printed.
+.It Cm s
+Bytes 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; however if the
+precision is 0 or missing, the string is printed entirely.
+.It Cm b
+As for
+.Cm s ,
+but interpret character escapes in backslash notation in the string
+.Ar argument .
+The permitted escape sequences are slightly different in that
+octal escapes are
+.Cm \e0 Ns Ar num
+instead of
+.Cm \e Ns Ar num
+and that an additional escape sequence
+.Cm \ec
+stops further output from this
+.Nm
+invocation.
+.It Cm n$
+Allows reordering of the output according to
+.Ar argument .
+.It Cm \&%
+Print a `%'; no argument is used.
+.El
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.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.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Print the string
+.Qq hello :
+.Bd -literal -offset indent
+$ printf "%s\en" hello
+hello
+.Ed
+.Pp
+Same as above, but notice that the format string is not quoted and hence we
+do not get the expected behavior:
+.Bd -literal -offset indent
+$ printf %s\en hello
+hellon$
+.Ed
+.Pp
+Print arguments forcing sign only for the first argument:
+.Bd -literal -offset indent
+$ printf "%+d\en%d\en%d\en" 1 -2 13
++1
+-2
+13
+.Ed
+.Pp
+Same as above, but the single format string will be applied to the three
+arguments:
+.Bd -literal -offset indent
+$ printf "%+d\en" 1 -2 13
++1
+-2
++13
+.Ed
+.Pp
+Print number using only two digits after the decimal point:
+.Bd -literal -offset indent
+$ printf "%.2f\en" 31.7456
+31.75
+.Ed
+.Sh COMPATIBILITY
+The traditional
+.Bx
+behavior of converting arguments of numeric formats not beginning
+with a digit to the ASCII
+code of the first character is not supported.
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr echo 1 ,
+.Xr sh 1 ,
+.Xr printf 3
+.Sh STANDARDS
+The
+.Nm
+command is expected to be compatible with the
+.St -p1003.2
+specification.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 Reno .
+It is modeled
+after the standard library function,
+.Xr printf 3 .
+.Sh CAVEATS
+ANSI hexadecimal character constants were deliberately not provided.
+.Pp
+Trying to print a dash ("-") as the first character causes
+.Nm
+to interpret the dash as a program argument.
+.Nm --
+must be used before
+.Ar format .
+.Pp
+If the locale contains multibyte characters
+(such as UTF-8),
+the
+.Cm c
+format and
+.Cm b
+and
+.Cm s
+formats with a precision
+may not operate as expected.
+.Sh BUGS
+Since the floating point numbers are translated from ASCII
+to floating-point and then back again, floating-point precision may be lost.
+(By default, the number is translated to an IEEE-754 double-precision
+value before being printed.
+The
+.Cm L
+modifier may produce additional precision, depending on the hardware platform.)
+.Pp
+The escape sequence \e000 is the string terminator.
+When present in the argument for the
+.Cm b
+format, the argument will be truncated at the \e000 character.
+.Pp
+Multibyte characters are not recognized in format strings (this is only
+a problem if
+.Ql %
+can appear inside a multibyte character).
diff --git a/usr.bin/printf/printf.c b/usr.bin/printf/printf.c
new file mode 100644
index 000000000000..4d12caee154a
--- /dev/null
+++ b/usr.bin/printf/printf.c
@@ -0,0 +1,672 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 1989, 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.
+ */
+/*
+ * Important: This file is used both as a standalone program /usr/bin/printf
+ * and as a builtin for /bin/sh (#define SHELL).
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#ifdef SHELL
+#define main printfcmd
+#include "bltin/bltin.h"
+#include "options.h"
+#endif
+
+#define PF(f, func) do { \
+ if (havewidth) \
+ if (haveprec) \
+ (void)printf(f, fieldwidth, precision, func); \
+ else \
+ (void)printf(f, fieldwidth, func); \
+ else if (haveprec) \
+ (void)printf(f, precision, func); \
+ else \
+ (void)printf(f, func); \
+} while (0)
+
+static int asciicode(void);
+static char *printf_doformat(char *, int *);
+static int escape(char *, int, size_t *);
+static int getchr(void);
+static int getfloating(long double *, int);
+static int getint(int *);
+static int getnum(intmax_t *, uintmax_t *, int);
+static const char
+ *getstr(void);
+static char *mknum(char *, char);
+static void usage(void);
+
+static const char digits[] = "0123456789";
+
+static char end_fmt[1];
+
+static int myargc;
+static char **myargv;
+static char **gargv;
+static char **maxargv;
+
+int
+main(int argc, char *argv[])
+{
+ size_t len;
+ int end, rval;
+ char *format, *fmt, *start;
+#ifndef SHELL
+ int ch;
+
+ (void) setlocale(LC_ALL, "");
+#endif
+
+#ifdef SHELL
+ nextopt("");
+ argc -= argptr - argv;
+ argv = argptr;
+#else
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch (ch) {
+ case '?':
+ default:
+ usage();
+ return (1);
+ }
+ argc -= optind;
+ argv += optind;
+#endif
+
+ if (argc < 1) {
+ usage();
+ return (1);
+ }
+
+#ifdef SHELL
+ INTOFF;
+#endif
+ /*
+ * 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.
+ */
+ fmt = format = *argv;
+ escape(fmt, 1, &len); /* backslash interpretation */
+ rval = end = 0;
+ gargv = ++argv;
+
+ for (;;) {
+ maxargv = gargv;
+
+ myargv = gargv;
+ for (myargc = 0; gargv[myargc]; myargc++)
+ /* nop */;
+ start = fmt;
+ while (fmt < format + len) {
+ if (fmt[0] == '%') {
+ fwrite(start, 1, fmt - start, stdout);
+ if (fmt[1] == '%') {
+ /* %% prints a % */
+ putchar('%');
+ fmt += 2;
+ } else {
+ fmt = printf_doformat(fmt, &rval);
+ if (fmt == NULL || fmt == end_fmt) {
+#ifdef SHELL
+ INTON;
+#endif
+ return (fmt == NULL ? 1 : rval);
+ }
+ end = 0;
+ }
+ start = fmt;
+ } else
+ fmt++;
+ if (gargv > maxargv)
+ maxargv = gargv;
+ }
+ gargv = maxargv;
+
+ if (end == 1) {
+ warnx("missing format character");
+#ifdef SHELL
+ INTON;
+#endif
+ return (1);
+ }
+ fwrite(start, 1, fmt - start, stdout);
+ if (!*gargv) {
+#ifdef SHELL
+ INTON;
+#endif
+ return (rval);
+ }
+ /* Restart at the beginning of the format string. */
+ fmt = format;
+ end = 1;
+ }
+ /* NOTREACHED */
+}
+
+
+static char *
+printf_doformat(char *fmt, int *rval)
+{
+ static const char skip1[] = "#'-+ 0";
+ int fieldwidth, haveprec, havewidth, mod_ldbl, precision;
+ char convch, nextch;
+ char start[strlen(fmt) + 1];
+ char **fargv;
+ char *dptr;
+ int l;
+
+ dptr = start;
+ *dptr++ = '%';
+ *dptr = 0;
+
+ fmt++;
+
+ /* look for "n$" field index specifier */
+ l = strspn(fmt, digits);
+ if ((l > 0) && (fmt[l] == '$')) {
+ int idx = atoi(fmt);
+ if (idx <= myargc) {
+ gargv = &myargv[idx - 1];
+ } else {
+ gargv = &myargv[myargc];
+ }
+ if (gargv > maxargv)
+ maxargv = gargv;
+ fmt += l + 1;
+
+ /* save format argument */
+ fargv = gargv;
+ } else {
+ fargv = NULL;
+ }
+
+ /* skip to field width */
+ while (*fmt && strchr(skip1, *fmt) != NULL) {
+ *dptr++ = *fmt++;
+ *dptr = 0;
+ }
+
+ if (*fmt == '*') {
+
+ fmt++;
+ l = strspn(fmt, digits);
+ if ((l > 0) && (fmt[l] == '$')) {
+ int idx = atoi(fmt);
+ if (fargv == NULL) {
+ warnx("incomplete use of n$");
+ return (NULL);
+ }
+ if (idx <= myargc) {
+ gargv = &myargv[idx - 1];
+ } else {
+ gargv = &myargv[myargc];
+ }
+ fmt += l + 1;
+ } else if (fargv != NULL) {
+ warnx("incomplete use of n$");
+ return (NULL);
+ }
+
+ if (getint(&fieldwidth))
+ return (NULL);
+ if (gargv > maxargv)
+ maxargv = gargv;
+ havewidth = 1;
+
+ *dptr++ = '*';
+ *dptr = 0;
+ } else {
+ havewidth = 0;
+
+ /* skip to possible '.', get following precision */
+ while (isdigit(*fmt)) {
+ *dptr++ = *fmt++;
+ *dptr = 0;
+ }
+ }
+
+ if (*fmt == '.') {
+ /* precision present? */
+ fmt++;
+ *dptr++ = '.';
+
+ if (*fmt == '*') {
+
+ fmt++;
+ l = strspn(fmt, digits);
+ if ((l > 0) && (fmt[l] == '$')) {
+ int idx = atoi(fmt);
+ if (fargv == NULL) {
+ warnx("incomplete use of n$");
+ return (NULL);
+ }
+ if (idx <= myargc) {
+ gargv = &myargv[idx - 1];
+ } else {
+ gargv = &myargv[myargc];
+ }
+ fmt += l + 1;
+ } else if (fargv != NULL) {
+ warnx("incomplete use of n$");
+ return (NULL);
+ }
+
+ if (getint(&precision))
+ return (NULL);
+ if (gargv > maxargv)
+ maxargv = gargv;
+ haveprec = 1;
+ *dptr++ = '*';
+ *dptr = 0;
+ } else {
+ haveprec = 0;
+
+ /* skip to conversion char */
+ while (isdigit(*fmt)) {
+ *dptr++ = *fmt++;
+ *dptr = 0;
+ }
+ }
+ } else
+ haveprec = 0;
+ if (!*fmt) {
+ warnx("missing format character");
+ return (NULL);
+ }
+ *dptr++ = *fmt;
+ *dptr = 0;
+
+ /*
+ * Look for a length modifier. POSIX doesn't have these, so
+ * we only support them for floating-point conversions, which
+ * are extensions. This is useful because the L modifier can
+ * be used to gain extra range and precision, while omitting
+ * it is more likely to produce consistent results on different
+ * architectures. This is not so important for integers
+ * because overflow is the only bad thing that can happen to
+ * them, but consider the command printf %a 1.1
+ */
+ if (*fmt == 'L') {
+ mod_ldbl = 1;
+ fmt++;
+ if (!strchr("aAeEfFgG", *fmt)) {
+ warnx("bad modifier L for %%%c", *fmt);
+ return (NULL);
+ }
+ } else {
+ mod_ldbl = 0;
+ }
+
+ /* save the current arg offset, and set to the format arg */
+ if (fargv != NULL) {
+ gargv = fargv;
+ }
+
+ convch = *fmt;
+ nextch = *++fmt;
+
+ *fmt = '\0';
+ switch (convch) {
+ case 'b': {
+ size_t len;
+ char *p;
+ int getout;
+
+ /* Convert "b" to "s" for output. */
+ start[strlen(start) - 1] = 's';
+ if ((p = strdup(getstr())) == NULL) {
+ warnx("%s", strerror(ENOMEM));
+ return (NULL);
+ }
+ getout = escape(p, 0, &len);
+ PF(start, p);
+ /* Restore format for next loop. */
+
+ free(p);
+ if (getout)
+ return (end_fmt);
+ break;
+ }
+ case 'c': {
+ char p;
+
+ p = getchr();
+ if (p != '\0')
+ PF(start, p);
+ break;
+ }
+ case 's': {
+ const char *p;
+
+ p = getstr();
+ PF(start, p);
+ break;
+ }
+ case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
+ char *f;
+ intmax_t val;
+ uintmax_t uval;
+ int signedconv;
+
+ signedconv = (convch == 'd' || convch == 'i');
+ if ((f = mknum(start, convch)) == NULL)
+ return (NULL);
+ if (getnum(&val, &uval, signedconv))
+ *rval = 1;
+ if (signedconv)
+ PF(f, val);
+ else
+ PF(f, uval);
+ break;
+ }
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'g': case 'G':
+ case 'a': case 'A': {
+ long double p;
+
+ if (getfloating(&p, mod_ldbl))
+ *rval = 1;
+ if (mod_ldbl)
+ PF(start, p);
+ else
+ PF(start, (double)p);
+ break;
+ }
+ default:
+ warnx("illegal format character %c", convch);
+ return (NULL);
+ }
+ *fmt = nextch;
+ /* return the gargv to the next element */
+ return (fmt);
+}
+
+static char *
+mknum(char *str, char ch)
+{
+ static char *copy;
+ static size_t copy_size;
+ char *newcopy;
+ size_t len, newlen;
+
+ len = strlen(str) + 2;
+ if (len > copy_size) {
+ newlen = ((len + 1023) >> 10) << 10;
+ if ((newcopy = realloc(copy, newlen)) == NULL) {
+ warnx("%s", strerror(ENOMEM));
+ return (NULL);
+ }
+ copy = newcopy;
+ copy_size = newlen;
+ }
+
+ memmove(copy, str, len - 3);
+ copy[len - 3] = 'j';
+ copy[len - 2] = ch;
+ copy[len - 1] = '\0';
+ return (copy);
+}
+
+static int
+escape(char *fmt, int percent, size_t *len)
+{
+ char *save, *store, c;
+ int value;
+
+ for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
+ if (c != '\\') {
+ *store = c;
+ continue;
+ }
+ switch (*++fmt) {
+ case '\0': /* EOS, user error */
+ *store = '\\';
+ *++store = '\0';
+ *len = store - save;
+ return (0);
+ case '\\': /* backslash */
+ case '\'': /* single quote */
+ *store = *fmt;
+ break;
+ case 'a': /* bell/alert */
+ *store = '\a';
+ break;
+ case 'b': /* backspace */
+ *store = '\b';
+ break;
+ case 'c':
+ if (!percent) {
+ *store = '\0';
+ *len = store - save;
+ return (1);
+ }
+ *store = 'c';
+ break;
+ case 'f': /* form-feed */
+ *store = '\f';
+ break;
+ case 'n': /* newline */
+ *store = '\n';
+ break;
+ case 'r': /* carriage-return */
+ *store = '\r';
+ break;
+ case 't': /* horizontal tab */
+ *store = '\t';
+ break;
+ case 'v': /* vertical tab */
+ *store = '\v';
+ break;
+ /* octal constant */
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = (!percent && *fmt == '0') ? 4 : 3;
+ for (value = 0;
+ c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
+ value <<= 3;
+ value += *fmt - '0';
+ }
+ --fmt;
+ if (percent && value == '%') {
+ *store++ = '%';
+ *store = '%';
+ } else
+ *store = (char)value;
+ break;
+ default:
+ *store = *fmt;
+ break;
+ }
+ }
+ *store = '\0';
+ *len = store - save;
+ return (0);
+}
+
+static int
+getchr(void)
+{
+ if (!*gargv)
+ return ('\0');
+ return ((int)**gargv++);
+}
+
+static const char *
+getstr(void)
+{
+ if (!*gargv)
+ return ("");
+ return (*gargv++);
+}
+
+static int
+getint(int *ip)
+{
+ intmax_t val;
+ uintmax_t uval;
+ int rval;
+
+ if (getnum(&val, &uval, 1))
+ return (1);
+ rval = 0;
+ if (val < INT_MIN || val > INT_MAX) {
+ warnx("%s: %s", *gargv, strerror(ERANGE));
+ rval = 1;
+ }
+ *ip = (int)val;
+ return (rval);
+}
+
+static int
+getnum(intmax_t *ip, uintmax_t *uip, int signedconv)
+{
+ char *ep;
+ int rval;
+
+ if (!*gargv) {
+ *ip = *uip = 0;
+ return (0);
+ }
+ if (**gargv == '"' || **gargv == '\'') {
+ if (signedconv)
+ *ip = asciicode();
+ else
+ *uip = asciicode();
+ return (0);
+ }
+ rval = 0;
+ errno = 0;
+ if (signedconv)
+ *ip = strtoimax(*gargv, &ep, 0);
+ else
+ *uip = strtoumax(*gargv, &ep, 0);
+ if (ep == *gargv) {
+ warnx("%s: expected numeric value", *gargv);
+ rval = 1;
+ }
+ else if (*ep != '\0') {
+ warnx("%s: not completely converted", *gargv);
+ rval = 1;
+ }
+ if (errno == ERANGE) {
+ warnx("%s: %s", *gargv, strerror(ERANGE));
+ rval = 1;
+ }
+ ++gargv;
+ return (rval);
+}
+
+static int
+getfloating(long double *dp, int mod_ldbl)
+{
+ char *ep;
+ int rval;
+
+ if (!*gargv) {
+ *dp = 0.0;
+ return (0);
+ }
+ if (**gargv == '"' || **gargv == '\'') {
+ *dp = asciicode();
+ return (0);
+ }
+ rval = 0;
+ errno = 0;
+ if (mod_ldbl)
+ *dp = strtold(*gargv, &ep);
+ else
+ *dp = strtod(*gargv, &ep);
+ if (ep == *gargv) {
+ warnx("%s: expected numeric value", *gargv);
+ rval = 1;
+ } else if (*ep != '\0') {
+ warnx("%s: not completely converted", *gargv);
+ rval = 1;
+ }
+ if (errno == ERANGE) {
+ warnx("%s: %s", *gargv, strerror(ERANGE));
+ rval = 1;
+ }
+ ++gargv;
+ return (rval);
+}
+
+static int
+asciicode(void)
+{
+ int ch;
+ wchar_t wch;
+ mbstate_t mbs;
+
+ ch = (unsigned char)**gargv;
+ if (ch == '\'' || ch == '"') {
+ memset(&mbs, 0, sizeof(mbs));
+ switch (mbrtowc(&wch, *gargv + 1, MB_LEN_MAX, &mbs)) {
+ case (size_t)-2:
+ case (size_t)-1:
+ wch = (unsigned char)gargv[0][1];
+ break;
+ case 0:
+ wch = 0;
+ break;
+ }
+ ch = wch;
+ }
+ ++gargv;
+ return (ch);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: printf format [arguments ...]\n");
+}
diff --git a/usr.bin/printf/tests/Makefile b/usr.bin/printf/tests/Makefile
new file mode 100644
index 000000000000..4577434014ad
--- /dev/null
+++ b/usr.bin/printf/tests/Makefile
@@ -0,0 +1,21 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.b.out
+${PACKAGE}FILES+= regress.bwidth.out
+${PACKAGE}FILES+= regress.d.out
+${PACKAGE}FILES+= regress.f.out
+${PACKAGE}FILES+= regress.l1.out
+${PACKAGE}FILES+= regress.l2.out
+${PACKAGE}FILES+= regress.m1.out
+${PACKAGE}FILES+= regress.m2.out
+${PACKAGE}FILES+= regress.m3.out
+${PACKAGE}FILES+= regress.m4.out
+${PACKAGE}FILES+= regress.m5.out
+${PACKAGE}FILES+= regress.missingpos1.out
+${PACKAGE}FILES+= regress.s.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.zero.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/printf/tests/Makefile.depend b/usr.bin/printf/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/printf/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/printf/tests/legacy_test.sh b/usr.bin/printf/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/printf/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/printf/tests/regress.b.out b/usr.bin/printf/tests/regress.b.out
new file mode 100644
index 000000000000..0373d9336f8c
--- /dev/null
+++ b/usr.bin/printf/tests/regress.b.out
@@ -0,0 +1 @@
+abcdef
diff --git a/usr.bin/printf/tests/regress.bwidth.out b/usr.bin/printf/tests/regress.bwidth.out
new file mode 100644
index 000000000000..9e2ff61c869c
--- /dev/null
+++ b/usr.bin/printf/tests/regress.bwidth.out
@@ -0,0 +1 @@
+ a
diff --git a/usr.bin/printf/tests/regress.d.out b/usr.bin/printf/tests/regress.d.out
new file mode 100644
index 000000000000..da83c085263c
--- /dev/null
+++ b/usr.bin/printf/tests/regress.d.out
@@ -0,0 +1 @@
+123, 123,00123,00123,00123
diff --git a/usr.bin/printf/tests/regress.f.out b/usr.bin/printf/tests/regress.f.out
new file mode 100644
index 000000000000..127cb8aebe25
--- /dev/null
+++ b/usr.bin/printf/tests/regress.f.out
@@ -0,0 +1 @@
+42.250000,-42.250 ,inf,nan
diff --git a/usr.bin/printf/tests/regress.l1.out b/usr.bin/printf/tests/regress.l1.out
new file mode 100644
index 000000000000..9be0dc9a9e6f
--- /dev/null
+++ b/usr.bin/printf/tests/regress.l1.out
@@ -0,0 +1 @@
+228
diff --git a/usr.bin/printf/tests/regress.l2.out b/usr.bin/printf/tests/regress.l2.out
new file mode 100644
index 000000000000..9be0dc9a9e6f
--- /dev/null
+++ b/usr.bin/printf/tests/regress.l2.out
@@ -0,0 +1 @@
+228
diff --git a/usr.bin/printf/tests/regress.m1.out b/usr.bin/printf/tests/regress.m1.out
new file mode 100644
index 000000000000..a9e063ee9709
--- /dev/null
+++ b/usr.bin/printf/tests/regress.m1.out
Binary files differ
diff --git a/usr.bin/printf/tests/regress.m2.out b/usr.bin/printf/tests/regress.m2.out
new file mode 100644
index 000000000000..cf1491518235
--- /dev/null
+++ b/usr.bin/printf/tests/regress.m2.out
@@ -0,0 +1,2 @@
+abc
+cdef \ No newline at end of file
diff --git a/usr.bin/printf/tests/regress.m3.out b/usr.bin/printf/tests/regress.m3.out
new file mode 100644
index 000000000000..bbe4e70c33f4
--- /dev/null
+++ b/usr.bin/printf/tests/regress.m3.out
@@ -0,0 +1,4 @@
+%abc
+%def
+%ghi
+%jkl
diff --git a/usr.bin/printf/tests/regress.m4.out b/usr.bin/printf/tests/regress.m4.out
new file mode 100644
index 000000000000..5e0b5d4072a4
--- /dev/null
+++ b/usr.bin/printf/tests/regress.m4.out
@@ -0,0 +1 @@
+0,0.000000,,
diff --git a/usr.bin/printf/tests/regress.m5.out b/usr.bin/printf/tests/regress.m5.out
new file mode 100644
index 000000000000..2838468eb842
--- /dev/null
+++ b/usr.bin/printf/tests/regress.m5.out
@@ -0,0 +1 @@
+-d
diff --git a/usr.bin/printf/tests/regress.missingpos1.out b/usr.bin/printf/tests/regress.missingpos1.out
new file mode 100644
index 000000000000..3b04f033ef26
--- /dev/null
+++ b/usr.bin/printf/tests/regress.missingpos1.out
@@ -0,0 +1 @@
+printf: incomplete use of n$
diff --git a/usr.bin/printf/tests/regress.s.out b/usr.bin/printf/tests/regress.s.out
new file mode 100644
index 000000000000..3d572b93c8f7
--- /dev/null
+++ b/usr.bin/printf/tests/regress.s.out
@@ -0,0 +1 @@
+abc,abc
diff --git a/usr.bin/printf/tests/regress.sh b/usr.bin/printf/tests/regress.sh
new file mode 100644
index 000000000000..18a04a3701a0
--- /dev/null
+++ b/usr.bin/printf/tests/regress.sh
@@ -0,0 +1,31 @@
+
+REGRESSION_START($1)
+
+echo '1..24'
+
+REGRESSION_TEST(`b', `printf "abc%b%b" "def\n" "\cghi"')
+REGRESSION_TEST(`d', `printf "%d,%5d,%.5d,%0*d,%.*d\n" 123 123 123 5 123 5 123')
+REGRESSION_TEST(`f', `printf "%f,%-8.3f,%f,%f\n" +42.25 -42.25 inf nan')
+REGRESSION_TEST(`l1', `LC_ALL=en_US.ISO8859-1 printf "%d\n" $(printf \"\\344)')
+REGRESSION_TEST(`l2', `LC_ALL=en_US.UTF-8 printf "%d\n" $(printf \"\\303\\244)')
+REGRESSION_TEST(`m1', `printf "%c%%%d\0\045\n" abc \"abc')
+REGRESSION_TEST(`m2', `printf "abc\n\cdef"')
+REGRESSION_TEST(`m3', `printf "%%%s\n" abc def ghi jkl')
+REGRESSION_TEST(`m4', `printf "%d,%f,%c,%s\n"')
+REGRESSION_TEST(`m5', `printf -- "-d\n"')
+REGRESSION_TEST(`s', `printf "%.3s,%-5s\n" abcd abc')
+REGRESSION_TEST('zero', `printf "%u%u\n" 15')
+REGRESSION_TEST('zero', `printf "%d%d\n" 15')
+REGRESSION_TEST('zero', `printf "%d%u\n" 15')
+REGRESSION_TEST('zero', `printf "%u%d\n" 15')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*s" 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$s" 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*.*1\$s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*2\$.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$.*2\$s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*.*2\$s" 1 1 1 2>&1')
+REGRESSION_TEST(`bwidth', `printf "%8.2b" "a\nb\n"')
+
+REGRESSION_END()
diff --git a/usr.bin/printf/tests/regress.zero.out b/usr.bin/printf/tests/regress.zero.out
new file mode 100644
index 000000000000..fa8f08cb6ff8
--- /dev/null
+++ b/usr.bin/printf/tests/regress.zero.out
@@ -0,0 +1 @@
+150
diff --git a/usr.bin/proccontrol/Makefile b/usr.bin/proccontrol/Makefile
new file mode 100644
index 000000000000..347063b3b565
--- /dev/null
+++ b/usr.bin/proccontrol/Makefile
@@ -0,0 +1,3 @@
+PROG= proccontrol
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/proccontrol/Makefile.depend b/usr.bin/proccontrol/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/proccontrol/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/proccontrol/proccontrol.1 b/usr.bin/proccontrol/proccontrol.1
new file mode 100644
index 000000000000..817e9b5865bc
--- /dev/null
+++ b/usr.bin/proccontrol/proccontrol.1
@@ -0,0 +1,146 @@
+.\" Copyright (c) 2019 The FreeBSD Foundation
+.\"
+.\" This documentation was written by
+.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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 AUTHORS 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 AUTHORS 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 December 14, 2024
+.Dt PROCCONTROL 1
+.Os
+.Sh NAME
+.Nm proccontrol
+.Nd Control some process execution aspects
+.Sh SYNOPSIS
+.Nm
+.Fl m Ar mode
+.Fl s Ar control
+.Fl p Ar pid | command
+.Nm
+.Fl m Ar mode
+.Fl q
+.Op Fl p Ar pid | command
+.Sh DESCRIPTION
+The
+.Nm
+command modifies the execution parameter of existing process
+specified by the
+.Ar pid
+argument, or starts execution of the new program
+.Ar command
+with the execution parameter set for it.
+.Pp
+Which execution parameter is changed, selected by the mandatory
+parameter
+.Ar mode .
+Possible values for
+.Ar mode
+are:
+.Bl -tag -width logsigexit
+.It Ar aslr
+Control the Address Space Layout Randomization.
+Only applicable to the new process spawned.
+.It Ar trace
+Control the permission for debuggers to attach.
+Note that process is only allowed to enable tracing for itself,
+not for any other process.
+.It Ar trapcap
+Controls the signalling of capability mode access violations.
+.It Ar protmax
+Controls the implicit PROT_MAX application for
+.Xr mmap 2 .
+.It Ar nonewprivs
+Controls disabling the setuid and sgid bits for
+.Xr execve 2 .
+.It Ar wxmap
+Controls the write exclusive execute mode for mappings.
+.It Ar kpti
+Controls the KPTI enable, AMD64 only.
+.It Ar la48
+Control limiting usermode process address space to 48 bits of address,
+AMD64 only, on machines capable of 57-bit addressing.
+.It Ar logsigexit
+Controls the logging of exits due to a signal that would normally cause a core
+dump.
+.El
+.Pp
+The
+.Ar control
+specifies if the selected
+.Ar mode
+should be enabled or disabled.
+Possible values are
+.Ar enable
+and
+.Ar disable ,
+with the default value being
+.Ar enable
+if not specified.
+See
+.Xr procctl 2
+for detailed description of each mode effects and interaction with other
+process control facilities.
+.Pp
+The
+.Fl q
+switch makes the utility query and print the current setting for
+the selected mode.
+The
+.Fl q
+requires the query target process specification with
+.Fl p .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Bl -bullet
+.It
+To disable debuggers attachment to the process 1020, execute
+.Dl "proccontrol -m trace -s disable -p 1020"
+.It
+To execute the
+.Xr uniq 1
+program in a mode where capability access violations cause
+.Dv SIGTRAP
+delivery, do
+.Dl "proccontrol -m trapcap uniq"
+.It
+To query the current ASLR enablement mode for the running
+process 1020, do
+.Dl "proccontrol -m aslr -q -p 1020"
+.El
+.Sh SEE ALSO
+.Xr kill 2 ,
+.Xr procctl 2 ,
+.Xr ptrace 2 ,
+.Xr mitigations 7
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+command and this manual page were written by
+.An Konstantin Belousov Aq Mt kib@freebsd.org
+under sponsorship from The FreeBSD Foundation.
diff --git a/usr.bin/proccontrol/proccontrol.c b/usr.bin/proccontrol/proccontrol.c
new file mode 100644
index 000000000000..3548ca606656
--- /dev/null
+++ b/usr.bin/proccontrol/proccontrol.c
@@ -0,0 +1,429 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/procctl.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+enum mode {
+ MODE_INVALID,
+ MODE_ASLR,
+ MODE_TRACE,
+ MODE_TRAPCAP,
+ MODE_PROTMAX,
+ MODE_STACKGAP,
+ MODE_NO_NEW_PRIVS,
+ MODE_WXMAP,
+#ifdef PROC_KPTI_CTL
+ MODE_KPTI,
+#endif
+#ifdef PROC_LA_CTL
+ MODE_LA57,
+ MODE_LA48,
+#endif
+ MODE_LOGSIGEXIT,
+};
+
+static const struct {
+ enum mode mode;
+ const char *name;
+} modes[] = {
+ { MODE_ASLR, "aslr" },
+ { MODE_TRACE, "trace" },
+ { MODE_TRAPCAP, "trapcap" },
+ { MODE_PROTMAX, "protmax" },
+ { MODE_STACKGAP, "stackgap" },
+ { MODE_NO_NEW_PRIVS, "nonewprivs" },
+ { MODE_WXMAP, "wxmap" },
+#ifdef PROC_KPTI_CTL
+ { MODE_KPTI, "kpti" },
+#endif
+#ifdef PROC_LA_CTL
+ { MODE_LA57, "la57" },
+ { MODE_LA48, "la48" },
+#endif
+ { MODE_LOGSIGEXIT, "logsigexit" },
+};
+
+static pid_t
+str2pid(const char *str)
+{
+ pid_t res;
+ char *tail;
+
+ res = strtol(str, &tail, 0);
+ if (*tail != '\0') {
+ warnx("non-numeric pid");
+ return (-1);
+ }
+ return (res);
+}
+
+static void __dead2
+usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " proccontrol -m mode -s (enable|disable) "
+ "(-p pid | command)\n");
+ fprintf(stderr, " proccontrol -m mode -q [-p pid]\n");
+ fprintf(stderr, "Modes: ");
+ for (size_t i = 0; i < nitems(modes); i++)
+ fprintf(stderr, "%s%s", i == 0 ? "" : "|", modes[i].name);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int arg, ch, error, mode;
+ pid_t pid;
+ bool enable, do_command, query;
+
+ mode = MODE_INVALID;
+ enable = true;
+ pid = -1;
+ query = false;
+ while ((ch = getopt(argc, argv, "m:qs:p:")) != -1) {
+ switch (ch) {
+ case 'm':
+ if (mode != MODE_INVALID)
+ usage();
+ for (size_t i = 0; i < nitems(modes); i++) {
+ if (strcmp(optarg, modes[i].name) == 0) {
+ mode = modes[i].mode;
+ break;
+ }
+ }
+ if (mode == MODE_INVALID)
+ usage();
+ break;
+ case 's':
+ if (strcmp(optarg, "enable") == 0)
+ enable = true;
+ else if (strcmp(optarg, "disable") == 0)
+ enable = false;
+ else
+ usage();
+ break;
+ case 'p':
+ pid = str2pid(optarg);
+ break;
+ case 'q':
+ query = true;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ do_command = argc != 0;
+ if (do_command) {
+ if (pid != -1 || query)
+ usage();
+ pid = getpid();
+ } else if (pid == -1) {
+ if (!query)
+ usage();
+ pid = getpid();
+ }
+
+ if (query) {
+ switch (mode) {
+ case MODE_ASLR:
+ error = procctl(P_PID, pid, PROC_ASLR_STATUS, &arg);
+ break;
+ case MODE_TRACE:
+ error = procctl(P_PID, pid, PROC_TRACE_STATUS, &arg);
+ break;
+ case MODE_TRAPCAP:
+ error = procctl(P_PID, pid, PROC_TRAPCAP_STATUS, &arg);
+ break;
+ case MODE_PROTMAX:
+ error = procctl(P_PID, pid, PROC_PROTMAX_STATUS, &arg);
+ break;
+ case MODE_STACKGAP:
+ error = procctl(P_PID, pid, PROC_STACKGAP_STATUS, &arg);
+ break;
+ case MODE_NO_NEW_PRIVS:
+ error = procctl(P_PID, pid, PROC_NO_NEW_PRIVS_STATUS,
+ &arg);
+ break;
+ case MODE_WXMAP:
+ error = procctl(P_PID, pid, PROC_WXMAP_STATUS, &arg);
+ break;
+#ifdef PROC_KPTI_CTL
+ case MODE_KPTI:
+ error = procctl(P_PID, pid, PROC_KPTI_STATUS, &arg);
+ break;
+#endif
+#ifdef PROC_LA_CTL
+ case MODE_LA57:
+ case MODE_LA48:
+ error = procctl(P_PID, pid, PROC_LA_STATUS, &arg);
+ break;
+#endif
+ case MODE_LOGSIGEXIT:
+ error = procctl(P_PID, pid, PROC_LOGSIGEXIT_STATUS,
+ &arg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ if (error != 0)
+ err(1, "procctl status");
+ switch (mode) {
+ case MODE_ASLR:
+ switch (arg & ~PROC_ASLR_ACTIVE) {
+ case PROC_ASLR_FORCE_ENABLE:
+ printf("force enabled");
+ break;
+ case PROC_ASLR_FORCE_DISABLE:
+ printf("force disabled");
+ break;
+ case PROC_ASLR_NOFORCE:
+ printf("not forced");
+ break;
+ }
+ if ((arg & PROC_ASLR_ACTIVE) != 0)
+ printf(", active\n");
+ else
+ printf(", not active\n");
+ break;
+ case MODE_TRACE:
+ if (arg == -1)
+ printf("disabled\n");
+ else if (arg == 0)
+ printf("enabled, no debugger\n");
+ else
+ printf("enabled, traced by %d\n", arg);
+ break;
+ case MODE_TRAPCAP:
+ switch (arg) {
+ case PROC_TRAPCAP_CTL_ENABLE:
+ printf("enabled\n");
+ break;
+ case PROC_TRAPCAP_CTL_DISABLE:
+ printf("disabled\n");
+ break;
+ }
+ break;
+ case MODE_PROTMAX:
+ switch (arg & ~PROC_PROTMAX_ACTIVE) {
+ case PROC_PROTMAX_FORCE_ENABLE:
+ printf("force enabled");
+ break;
+ case PROC_PROTMAX_FORCE_DISABLE:
+ printf("force disabled");
+ break;
+ case PROC_PROTMAX_NOFORCE:
+ printf("not forced");
+ break;
+ }
+ if ((arg & PROC_PROTMAX_ACTIVE) != 0)
+ printf(", active\n");
+ else
+ printf(", not active\n");
+ break;
+ case MODE_STACKGAP:
+ switch (arg & (PROC_STACKGAP_ENABLE |
+ PROC_STACKGAP_DISABLE)) {
+ case PROC_STACKGAP_ENABLE:
+ printf("enabled\n");
+ break;
+ case PROC_STACKGAP_DISABLE:
+ printf("disabled\n");
+ break;
+ }
+ switch (arg & (PROC_STACKGAP_ENABLE_EXEC |
+ PROC_STACKGAP_DISABLE_EXEC)) {
+ case PROC_STACKGAP_ENABLE_EXEC:
+ printf("enabled after exec\n");
+ break;
+ case PROC_STACKGAP_DISABLE_EXEC:
+ printf("disabled after exec\n");
+ break;
+ }
+ break;
+ case MODE_NO_NEW_PRIVS:
+ switch (arg) {
+ case PROC_NO_NEW_PRIVS_ENABLE:
+ printf("enabled\n");
+ break;
+ case PROC_NO_NEW_PRIVS_DISABLE:
+ printf("disabled\n");
+ break;
+ }
+ break;
+ case MODE_WXMAP:
+ if ((arg & PROC_WX_MAPPINGS_PERMIT) != 0)
+ printf("enabled");
+ else
+ printf("disabled");
+ if ((arg & PROC_WX_MAPPINGS_DISALLOW_EXEC) != 0)
+ printf(", disabled on exec");
+ if ((arg & PROC_WXORX_ENFORCE) != 0)
+ printf(", wxorx enforced");
+ printf("\n");
+ break;
+#ifdef PROC_KPTI_CTL
+ case MODE_KPTI:
+ switch (arg & ~PROC_KPTI_STATUS_ACTIVE) {
+ case PROC_KPTI_CTL_ENABLE_ON_EXEC:
+ printf("enabled");
+ break;
+ case PROC_KPTI_CTL_DISABLE_ON_EXEC:
+ printf("disabled");
+ break;
+ }
+ if ((arg & PROC_KPTI_STATUS_ACTIVE) != 0)
+ printf(", active\n");
+ else
+ printf(", not active\n");
+ break;
+#endif
+#ifdef PROC_LA_CTL
+ case MODE_LA57:
+ case MODE_LA48:
+ switch (arg & ~(PROC_LA_STATUS_LA48 |
+ PROC_LA_STATUS_LA57)) {
+ case PROC_LA_CTL_LA48_ON_EXEC:
+ printf("la48 on exec");
+ break;
+ case PROC_LA_CTL_LA57_ON_EXEC:
+ printf("la57 on exec");
+ break;
+ case PROC_LA_CTL_DEFAULT_ON_EXEC:
+ printf("default on exec");
+ break;
+ }
+ if ((arg & PROC_LA_STATUS_LA48) != 0)
+ printf(", la48 active\n");
+ else if ((arg & PROC_LA_STATUS_LA57) != 0)
+ printf(", la57 active\n");
+ break;
+#endif
+ case MODE_LOGSIGEXIT:
+ switch (arg) {
+ case PROC_LOGSIGEXIT_CTL_NOFORCE:
+ printf("not forced\n");
+ break;
+ case PROC_LOGSIGEXIT_CTL_FORCE_ENABLE:
+ printf("force enabled\n");
+ break;
+ case PROC_LOGSIGEXIT_CTL_FORCE_DISABLE:
+ printf("force disabled\n");
+ break;
+ }
+ break;
+ }
+ } else {
+ switch (mode) {
+ case MODE_ASLR:
+ arg = enable ? PROC_ASLR_FORCE_ENABLE :
+ PROC_ASLR_FORCE_DISABLE;
+ error = procctl(P_PID, pid, PROC_ASLR_CTL, &arg);
+ break;
+ case MODE_TRACE:
+ arg = enable ? PROC_TRACE_CTL_ENABLE :
+ PROC_TRACE_CTL_DISABLE;
+ error = procctl(P_PID, pid, PROC_TRACE_CTL, &arg);
+ break;
+ case MODE_TRAPCAP:
+ arg = enable ? PROC_TRAPCAP_CTL_ENABLE :
+ PROC_TRAPCAP_CTL_DISABLE;
+ error = procctl(P_PID, pid, PROC_TRAPCAP_CTL, &arg);
+ break;
+ case MODE_PROTMAX:
+ arg = enable ? PROC_PROTMAX_FORCE_ENABLE :
+ PROC_PROTMAX_FORCE_DISABLE;
+ error = procctl(P_PID, pid, PROC_PROTMAX_CTL, &arg);
+ break;
+ case MODE_STACKGAP:
+ arg = enable ? PROC_STACKGAP_ENABLE_EXEC :
+ (PROC_STACKGAP_DISABLE |
+ PROC_STACKGAP_DISABLE_EXEC);
+ error = procctl(P_PID, pid, PROC_STACKGAP_CTL, &arg);
+ break;
+ case MODE_NO_NEW_PRIVS:
+ arg = enable ? PROC_NO_NEW_PRIVS_ENABLE :
+ PROC_NO_NEW_PRIVS_DISABLE;
+ error = procctl(P_PID, pid, PROC_NO_NEW_PRIVS_CTL,
+ &arg);
+ break;
+ case MODE_WXMAP:
+ arg = enable ? PROC_WX_MAPPINGS_PERMIT :
+ PROC_WX_MAPPINGS_DISALLOW_EXEC;
+ error = procctl(P_PID, pid, PROC_WXMAP_CTL, &arg);
+ break;
+#ifdef PROC_KPTI_CTL
+ case MODE_KPTI:
+ arg = enable ? PROC_KPTI_CTL_ENABLE_ON_EXEC :
+ PROC_KPTI_CTL_DISABLE_ON_EXEC;
+ error = procctl(P_PID, pid, PROC_KPTI_CTL, &arg);
+ break;
+#endif
+#ifdef PROC_LA_CTL
+ case MODE_LA57:
+ arg = enable ? PROC_LA_CTL_LA57_ON_EXEC :
+ PROC_LA_CTL_DEFAULT_ON_EXEC;
+ error = procctl(P_PID, pid, PROC_LA_CTL, &arg);
+ break;
+ case MODE_LA48:
+ arg = enable ? PROC_LA_CTL_LA48_ON_EXEC :
+ PROC_LA_CTL_DEFAULT_ON_EXEC;
+ error = procctl(P_PID, pid, PROC_LA_CTL, &arg);
+ break;
+#endif
+ case MODE_LOGSIGEXIT:
+ arg = enable ? PROC_LOGSIGEXIT_CTL_FORCE_ENABLE :
+ PROC_LOGSIGEXIT_CTL_FORCE_DISABLE;
+ error = procctl(P_PID, pid, PROC_LOGSIGEXIT_CTL, &arg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ if (error != 0)
+ err(1, "procctl ctl");
+ if (do_command) {
+ error = execvp(argv[0], argv);
+ err(1, "exec");
+ }
+ }
+ exit(0);
+}
diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile
new file mode 100644
index 000000000000..c143e74d516c
--- /dev/null
+++ b/usr.bin/procstat/Makefile
@@ -0,0 +1,39 @@
+.include <src.opts.mk>
+
+PROG= procstat
+MAN= procstat.1
+SRCS= procstat.c \
+ procstat_advlock.c \
+ procstat_args.c \
+ procstat_auxv.c \
+ procstat_basic.c \
+ procstat_bin.c \
+ procstat_cred.c \
+ procstat_cs.c \
+ procstat_files.c \
+ procstat_kqueue.c \
+ procstat_kstack.c \
+ procstat_penv.c \
+ procstat_ptlwpinfo.c \
+ procstat_pwdx.c \
+ procstat_rlimit.c \
+ procstat_rlimitusage.c \
+ procstat_rusage.c \
+ procstat_sigs.c \
+ procstat_threads.c \
+ procstat_vm.c
+
+MLINKS+= procstat.1 pargs.1
+MLINKS+= procstat.1 penv.1
+MLINKS+= procstat.1 pwdx.1
+
+LIBADD+= procstat xo util sbuf
+
+LINKS+= ${BINDIR}/procstat ${BINDIR}/pargs
+LINKS+= ${BINDIR}/procstat ${BINDIR}/penv
+LINKS+= ${BINDIR}/procstat ${BINDIR}/pwdx
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/procstat/Makefile.depend b/usr.bin/procstat/Makefile.depend
new file mode 100644
index 000000000000..a898da3b8ced
--- /dev/null
+++ b/usr.bin/procstat/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libprocstat \
+ lib/libsbuf \
+ lib/libutil \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
new file mode 100644
index 000000000000..3466291ba43c
--- /dev/null
+++ b/usr.bin/procstat/procstat.1
@@ -0,0 +1,901 @@
+.\"-
+.\" Copyright (c) 2007-2009 Robert N. M. Watson
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 April 7, 2022
+.Dt PROCSTAT 1
+.Os
+.Sh NAME
+.Nm procstat
+.Nd get detailed process information
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Ar command
+.Op Ar pid ... | Ar core ...
+.Nm
+.Op Fl -libxo
+.Fl a
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Ar command
+.Nm
+.Op Fl -libxo
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Oo
+.Fl b |
+.Fl c |
+.Fl e |
+.Fl f Oo Fl C Oc |
+.Fl i Oo Fl n Oc |
+.Fl j Oo Fl n Oc |
+.Fl k Oo Fl k Oc |
+.Fl l |
+.Fl r Oo Fl H Oc |
+.Fl s |
+.Fl S |
+.Fl t |
+.Fl v |
+.Fl x
+.Oc
+.Op Ar pid ... | Ar core ...
+.Nm
+.Op Fl -libxo
+.Fl a
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Oo
+.Fl b |
+.Fl c |
+.Fl e |
+.Fl f Oo Fl C Oc |
+.Fl i Oo Fl n Oc |
+.Fl j Oo Fl n Oc |
+.Fl k Oo Fl k Oc |
+.Fl l |
+.Fl r Oo Fl H Oc |
+.Fl s |
+.Fl S |
+.Fl t |
+.Fl v |
+.Fl x
+.Oc
+.Nm
+.Op Fl -libxo
+.Fl L
+.Op Fl h
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar interval
+.Ar core ...
+.Nm pargs
+.Op Fl -libxo
+.Ar pid ...
+.Nm penv
+.Op Fl -libxo
+.Ar pid ...
+.Nm pwdx
+.Op Fl -libxo
+.Ar pid ...
+.Sh DESCRIPTION
+.Nm
+utility displays detailed information about the processes identified by the
+.Ar pid
+arguments, or if the
+.Fl a
+flag is used, all processes.
+It can also display information extracted from a process core file, if
+the core file is specified as the argument.
+.Pp
+The
+.Nm pargs ,
+.Nm penv
+and
+.Nm pwdx
+utilities display the arguments, environment, and current working directory,
+respectively of the process specified by
+.Ar pid
+argument.
+They mimic the behavior of Solaris utilities of the same names.
+.Pp
+If the
+.Fl -libxo
+flag is specified the output is generated via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.Pp
+The following commands are available for
+.Nm :
+.Bl -tag -width indent
+.It Ar advlock
+Print information about advisory locks on files.
+All three types of locks are listed, BSD-style
+.Xr lockf 2 ,
+POSIX-style
+.Xr fcntl 2
+.Va F_SETLK ,
+and remote
+.Xr lockd 8
+locks used by NFSv3.
+.Pp
+Note that neither the
+.Fl a
+option nor
+.Va pid
+list can be used to limit the display of the locks, mostly because
+some types of locks do not have local (or any) owning processes.
+.It Ar argument(s) | Fl c
+Display command line arguments for the process.
+.Pp
+Substring commands are accepted.
+.It Ar auxv | Fl x
+Display ELF auxiliary vector for the process.
+.It Ar basic
+Print basic process statistics (this is the default).
+.It Ar binary | Fl b
+Display binary information for the process.
+.Pp
+Substring commands are accepted.
+.It Ar credential(s) | Fl s
+Display security credential information for the process.
+.Pp
+Substring commands are accepted.
+.It Ar cpuset | Ar cs | Fl S
+Display the cpuset information for the thread.
+.It Ar environment | Fl e
+Display environment variables for the process.
+.Pp
+Substring commands are accepted.
+.It Ar file(s) | Ar fd(s) | Fl f
+Display file descriptor information for the process.
+.Pp
+If the
+.Fl C
+subcommand flag is used then additional capability information is printed.
+.It Ar kqueue(s) Op Fl v
+Display the events registered in the process kqueues.
+The filter name, filter-specific identifier, flags, filter-specific flags,
+system and user data, and event status are displayed.
+If the
+.Fl v
+verbose flag is provided to the subcommand, the values of the ext array
+are displayed as well.
+.Pp
+For flags, a string is printed consisting of the following symbols
+corresponding to set flags:
+.Bl -tag -width X -compact
+.It O
+.Va EV_ONESHOT
+.It C
+.Va EV_CLEAR
+.It R
+.Va EV_RECEIPT
+.It D
+.Va EV_DISPATCH
+.It d
+.Va EV_DROP
+.It 1
+.Va EV_FLAG1
+.It 2
+.Va EV_FLAG2
+.El
+.Pp
+For status:
+.Bl -tag -width X -compact
+.It A
+.Va KNOTE_STATUS_ACTIVE
+.It Q
+.Va KNOTE_STATUS_QUEUED
+.It D
+.Va KNOTE_STATUS_DISABLED
+.It d
+.Va KNOTE_STATUS_DETACHED
+.It K
+.Va KNOTE_STATUS_KQUEUE
+.El
+.It Ar kstack | Fl k
+Display the stacks of kernel threads in the process, excluding stacks of
+threads currently running on a CPU in userspace.
+.Pp
+If the
+.Fl v
+subcommand option is used (or the command flag is repeated), function
+offsets as well as function names are printed.
+.It Ar pargs
+Display arguments for the process.
+.It Ar penv
+Display environment variables for the process.
+.It Ar ptlwpinfo | Fl L
+Display LWP info for the process pertaining to its signal driven exit.
+.It Ar pwdx
+Display current working directory for the process.
+.It Ar rlimit | Fl l
+Display resource limits for the process.
+.It Ar rlimitusage
+Display the usage of the resource limits for the process.
+.It Ar rusage | Fl r
+Display resource usage information for the process.
+.Pp
+If the
+.Fl v
+.Pq or Fl H
+subcommand flag
+is used then per-thread statistics are printed, rather than per-process
+statistics.
+The second field in the table will list the thread ID to which the row of
+information corresponds.
+.It Ar signal(s) | Fl i
+Display signal pending and disposition information for the process.
+.Pp
+If the
+.Fl n
+subcommand option is used, the signal numbers are shown instead of signal
+names.
+.Pp
+Substring commands are accepted.
+.It Ar thread(s) | Fl t
+Display thread information for the process.
+.It Ar tsignal(s) | Fl j
+Display signal pending and blocked information for the process's threads.
+.Pp
+If the
+.Fl n
+subcommand option is used, the signal numbers are shown instead of signal
+names.
+.Pp
+Substring commands are accepted.
+.It Ar vm | Fl v
+Display virtual memory mappings for the process.
+.El
+.Pp
+All options generate output in the format of a table, the first field of
+which is the process ID to which the row of information corresponds.
+The
+.Fl h
+flag may be used to suppress table headers.
+.Pp
+The
+.Fl w
+flag may be used to specify a wait interval at which to repeat the printing
+of the requested process information.
+If the
+.Fl w
+flag is not specified, the output will not repeat.
+.Pp
+Information for VM, file descriptor, and cpuset options is available
+only to the owner of a process or the superuser.
+A cpuset value displayed as -1 means that the information is either invalid
+or not available.
+.Ss Binary Information
+Display the process ID, command, and path to the process binary:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It OSREL
+osreldate for process binary
+.It PATH
+path to process binary (if available)
+.El
+.Ss Command Line Arguments
+Display the process ID, command, and command line arguments:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It ARGS
+command line arguments (if available)
+.El
+.Ss Environment Variables
+Display the process ID, command, and environment variables:
+.Pp
+.Bl -tag -width "ENVIRONMENT" -compact
+.It PID
+process ID
+.It COMM
+command
+.It ENVIRONMENT
+environment variables (if available)
+.El
+.Ss File Descriptors
+Display detailed information about each file descriptor referenced by a
+process, including the process ID, command, file descriptor number, and
+per-file descriptor object information, such as object type and file system
+path.
+By default, the following information will be printed:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It FD
+file descriptor number or cwd/root/jail
+.It T
+file descriptor type
+.It V
+vnode type
+.It FLAGS
+file descriptor flags
+.It REF
+file descriptor reference count
+.It OFFSET
+file descriptor offset
+.It PRO
+network protocol
+.It NAME
+file path or socket addresses (if available)
+.El
+.Pp
+The following file descriptor types may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It e
+POSIX semaphore
+.It E
+eventfd
+.It f
+fifo
+.It h
+shared memory
+.It k
+kqueue
+.It m
+message queue
+.It P
+process descriptor
+.It p
+pipe
+.It s
+socket
+.It t
+pseudo-terminal master
+.It v
+vnode
+.El
+.Pp
+The following vnode types may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It -
+not a vnode
+.It b
+block device
+.It c
+character device
+.It d
+directory
+.It f
+fifo
+.It l
+symbolic link
+.It r
+regular file
+.It s
+socket
+.It x
+revoked device
+.El
+.Pp
+The following file descriptor flags may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It r
+read
+.It w
+write
+.It a
+append
+.It s
+async
+.It f
+fsync
+.It n
+non-blocking
+.It d
+direct I/O
+.It l
+lock held
+.El
+.Pp
+If the
+.Fl C
+flag is specified, the vnode type, reference count, and offset fields will be
+omitted, and a new capabilities field will be included listing capabilities,
+as described in
+.Xr cap_rights_limit 2 ,
+present for each capability descriptor.
+.Pp
+The following network protocols may be displayed (grouped by address family):
+.Pp
+.Dv AF_INET ,
+.Dv AF_INET6
+.Pp
+.Bl -tag -width indent -compact
+.It ICM
+.Dv IPPROTO_ICMP ;
+see
+.Xr icmp 4 .
+.It IP?
+unknown protocol.
+.It RAW
+.Dv IPPROTO_RAW ;
+see
+.Xr ip 4 .
+.It SCT
+.Dv IPPROTO_SCTP ;
+see
+.Xr sctp 4 .
+.It TCP
+.Dv IPPROTO_TCP ;
+see
+.Xr tcp 4 .
+.It UDP
+.Dv IPPROTO_UDP ;
+see
+.Xr udp 4 .
+.El
+.Pp
+.Dv AF_LOCAL
+.Pp
+.Bl -tag -width indent -compact
+.It UDD
+.Dv IPPROTO_UDP ;
+see
+.Xr udp 4 .
+.It UDS
+.Dv IPPROTO_TCP ;
+see
+.Xr tcp 4 .
+.It UD?
+unknown protocol.
+.El
+.Pp
+.Dv AF_DIVERT
+.Pp
+.Bl -tag -width indent -compact
+.It IPD
+.Dv Divert socket; see
+.Xr divert 4 .
+.El
+.Pp
+.Bl -tag -width indent -compact
+.It ?
+unknown address family.
+.El
+.Ss Signal Disposition Information
+Display signal pending and disposition for a process:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It SIG
+signal name
+.It FLAGS
+process signal disposition details, three symbols
+.Bl -tag -width X -compact
+.It P
+if signal is pending in the global process queue; - otherwise.
+.It I
+if signal delivery disposition is
+.Dv SIG_IGN ;
+- otherwise.
+.It C
+if the signal will be caught; - otherwise.
+.El
+.El
+.Pp
+If
+.Fl n
+switch is given, the signal numbers are shown instead of signal names.
+.Ss Thread Signal Information
+Display signal pending and blocked for a process's threads:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It TID
+thread ID
+.It COMM
+command
+.It SIG
+signal name
+.It FLAGS
+thread signal delivery status, two symbols
+.Bl -tag -width X -compact
+.It P
+if signal is pending for the thread, - otherwise
+.It B
+if signal is blocked in the thread signal mask, - if not blocked
+.El
+.El
+.Pp
+The
+.Fl n
+switch has the same effect as for the
+.Fl i
+switch: the signal numbers are shown instead of signal names.
+.Ss Kernel Thread Stacks
+Display kernel thread stacks for a process, allowing further interpretation
+of thread wait channels.
+If the
+.Fl k
+flag is repeated, function offsets, not just function names, are printed.
+.Pp
+This feature requires
+.Cd "options STACK"
+or
+.Cd "options DDB"
+to be compiled into the kernel.
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It TID
+thread ID
+.It COMM
+command
+.It TDNAME
+thread name
+.It KSTACK
+kernel thread call stack
+.El
+.Ss Resource Limits
+Display resource limits for a process:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It RLIMIT
+resource limit name
+.It SOFT
+soft limit
+.It HARD
+hard limit
+.El
+.Ss Resource Usage
+Display resource usage for a process.
+If the
+.Fl H
+flag is specified,
+resource usage for individual threads is displayed instead.
+.Pp
+.Bl -tag -width "RESOURCE" -compact
+.It PID
+process ID
+.It TID
+thread ID
+.Po
+if
+.Fl H
+is specified
+.Pc
+.It COMM
+command
+.It RESOURCE
+resource name
+.It VALUE
+current usage
+.El
+.Ss Security Credentials
+Display process credential information:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It EUID
+effective user ID
+.It RUID
+real user ID
+.It SVUID
+saved user ID
+.It EGID
+effective group ID
+.It RGID
+real group ID
+.It SVGID
+saved group ID
+.It UMASK
+file creation mode mask
+.It FLAGS
+credential flags
+.It GROUPS
+group set
+.El
+.Pp
+The following credential flags may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It C
+capability mode
+.El
+.Ss Thread Information
+Display per-thread information, including process ID, per-thread ID, name,
+CPU, and execution state:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It TID
+thread ID
+.It COMM
+command
+.It TDNAME
+thread name
+.It CPU
+current or most recent CPU run on
+.It PRI
+thread priority
+.It STATE
+thread state
+.It WCHAN
+thread wait channel
+.El
+.Ss Virtual Memory Mappings
+Display process virtual memory mappings, including addresses, mapping
+meta-data, and mapped object information:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It START
+starting address of mapping
+.It END
+ending address of mapping
+.It PRT
+protection flags
+.It RES
+resident pages
+.It PRES
+private resident pages
+.It REF
+reference count
+.It SHD
+shadow page count
+.It FLAG
+mapping flags
+.It TP
+VM object type
+.El
+.Pp
+The following protection flags may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It r
+read
+.It w
+write
+.It x
+execute
+.El
+.Pp
+The following VM object types may be displayed:
+.Pp
+.Bl -tag -width XX -compact
+.It --
+none
+.It dd
+dead
+.It df
+default
+.It dv
+device
+.It md
+device with managed pages
+.Pq GEM/TTM
+.It ph
+physical
+.It sg
+scatter/gather
+.It sw
+swap
+.It vn
+vnode
+.It gd
+guard (pseudo-type)
+.El
+.Pp
+The following mapping flags may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It C
+copy-on-write
+.It N
+needs copy
+.It S
+one or more superpage mappings are used
+.It D
+grows down (top-down stack)
+.It U
+grows up (bottom-up stack)
+.It W
+pages in this range are locked by
+.Xr mlock 2
+or
+.Xr mlockall 2
+.El
+.Ss ELF Auxiliary Vector
+Display ELF auxiliary vector values:
+.Pp
+.Bl -tag -width indent -compact
+.It PID
+process ID
+.It COMM
+command
+.It AUXV
+auxiliary vector name
+.It VALUE
+auxiliary vector value
+.El
+.Ss Advisory Lock Information
+.Bl -tag -width indent -compact
+.It RW
+Read/Write type,
+.Va RO
+for read,
+.Va RW
+for write lock
+.It TYPE
+Type of the lock, one of
+.Va FLOCK
+for
+.Xr flock 2 ,
+.Va FCNTL
+for
+.Xr fcntl 2 ,
+.Va LOCKD
+for remote
+.It PID
+Process id of the owner, for
+.Va FCNTL
+and remote types
+.It SYSID
+Remote system id if applicable
+.It FSID
+File system id where the locked file resize
+.It RDEV
+rdev for the file system
+.It INO
+Unique file identifier (inode number) of the locked file
+on the file system
+.It START
+Start offset of the locked range
+.It LEN
+Length of the locked range.
+Zero means till EOF
+.It PATH
+If available, the path of the locked file
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show binary information about the current shell:
+.Bd -literal -offset indent
+$ procstat binary $$
+ PID COMM OSREL PATH
+46620 bash 1201000 /usr/local/bin/bash
+.Ed
+.Pp
+Same as above but showing information about open file descriptors:
+.Bd -literal -offset indent
+$ procstat files $$
+ PID COMM FD T V FLAGS REF OFFSET PRO NAME
+46620 bash text v r r------- - - - /usr/local/bin/bash
+46620 bash ctty v c rw------ - - - /dev/pts/12
+46620 bash cwd v d r------- - - - /tmp
+46620 bash root v d r------- - - - /
+46620 bash 0 v c rw------ 7 372071 - /dev/pts/12
+46620 bash 1 v c rw------ 7 372071 - /dev/pts/12
+46620 bash 2 v c rw------ 7 372071 - /dev/pts/12
+46620 bash 255 v c rw------ 7 372071 - /dev/pts/12
+.Ed
+.Pp
+Show the arguments used to launch
+.Xr init 8 :
+.Bd -literal -offset indent
+$ procstat arguments 1
+ PID COMM ARGS
+ 1 init /sbin/init --
+.Ed
+.Pp
+Extract binary information from a core dump:
+.Bd -literal -offset indent
+$ procstat binary core.36642
+ PID COMM OSREL PATH
+36642 top 1201000 /usr/bin/top
+.Ed
+.Pp
+Trying to extract information from a core file generated in a different major
+.Fx
+version might show an error like this:
+.Bd -literal -offset indent
+$ procstat mplayer.core
+procstat: kinfo_proc structure size mismatch
+procstat: procstat_getprocs()
+.Ed
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr ps 1 ,
+.Xr sockstat 1 ,
+.Xr cap_enter 2 ,
+.Xr cap_rights_limit 2 ,
+.Xr mlock 2 ,
+.Xr mlockall 2 ,
+.Xr libprocstat 3 ,
+.Xr libxo 3 ,
+.Xr signal 3 ,
+.Xr xo_parse_args 3 ,
+.Xr ddb 4 ,
+.Xr divert 4 ,
+.Xr icmp 4 ,
+.Xr ip 4 ,
+.Xr sctp 4 ,
+.Xr tcp 4 ,
+.Xr udp 4 ,
+.Xr stack 9
+.Sh AUTHORS
+.An Robert N M Watson Aq Mt rwatson@FreeBSD.org .
+.br
+.Xr libxo 3
+support was added by
+.An -nosplit
+Allan Jude
+.Aq Mt allanjude@FreeBSD.org .
+.br
+.An Juraj Lutter
+.Aq Mt juraj@lutter.sk
+added the pargs, penv and pwdx functionality.
+.Sh BUGS
+The display of open file or memory mapping pathnames is implemented using the
+kernel's name cache.
+If a file system does not use the name cache, or the path to a file is not in
+the cache, a path will not be displayed.
+.Pp
+.Nm
+currently supports extracting data only from a live kernel, and not from
+kernel crash dumps.
diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
new file mode 100644
index 000000000000..62076094b073
--- /dev/null
+++ b/usr.bin/procstat/procstat.c
@@ -0,0 +1,653 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007, 2011 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * Copyright (c) 2017 Dell EMC
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "procstat.h"
+
+enum {
+ PS_CMP_NORMAL = 0x00,
+ PS_CMP_PLURAL = 0x01,
+ PS_CMP_SUBSTR = 0x02
+};
+
+struct procstat_cmd {
+ const char *command;
+ const char *xocontainer;
+ const char *usage;
+ void (*cmd)(struct procstat *, struct kinfo_proc *);
+ void (*opt)(int, char * const *);
+ int cmp;
+};
+
+int procstat_opts = 0;
+
+static void cmdopt_none(int argc, char * const argv[]);
+static void cmdopt_verbose(int argc, char * const argv[]);
+static void cmdopt_signals(int argc, char * const argv[]);
+static void cmdopt_rusage(int argc, char * const argv[]);
+static void cmdopt_files(int argc, char * const argv[]);
+static void cmdopt_cpuset(int argc, char * const argv[]);
+static void cmdopt_kqueue(int argc, char * const argv[]);
+
+static const char *progname;
+
+/* aliased program parameters and arguments
+ * - usage field is abused to hold the pointer to the function
+ * displaying program usage
+ */
+static const struct procstat_cmd pacmd_table[] = {
+ /* arguments are the same as for pwdx: pid or core file */
+ { "pargs", "args", NULL, &procstat_pargs, &cmdopt_none,
+ PS_CMP_NORMAL | PS_MODE_COMPAT },
+ { "penv", "env", NULL, &procstat_penv, &cmdopt_none,
+ PS_CMP_NORMAL | PS_MODE_COMPAT },
+ { "pwdx", "pwd", NULL, &procstat_pwdx, &cmdopt_none,
+ PS_CMP_NORMAL | PS_MODE_COMPAT }
+};
+
+/* procstat parameters and arguments */
+static const struct procstat_cmd cmd_table[] = {
+ { "advlock", "advisory_locks", NULL, &procstat_advlocks, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR | PS_MODE_NO_KINFO_PROC },
+ { "argument", "arguments", NULL, &procstat_args, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "auxv", "auxv", NULL, &procstat_auxv, &cmdopt_none, PS_CMP_NORMAL },
+ { "basic", "basic", NULL, &procstat_basic, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "binary", "binary", NULL, &procstat_bin, &cmdopt_none,
+ PS_CMP_SUBSTR },
+ { "cpuset", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL },
+ { "cs", "cs", NULL, &procstat_cs, &cmdopt_cpuset, PS_CMP_NORMAL },
+ { "credential", "credentials", NULL, &procstat_cred, &cmdopt_none,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "environment", "environment", NULL, &procstat_env, &cmdopt_none,
+ PS_CMP_SUBSTR },
+ { "fd", "files", "[-C]", &procstat_files, &cmdopt_files,
+ PS_CMP_PLURAL },
+ { "file", "files", "[-C]", &procstat_files, &cmdopt_files,
+ PS_CMP_PLURAL },
+ { "kqueue", "kqueues", NULL, &procstat_kqueues, &cmdopt_kqueue,
+ PS_CMP_PLURAL },
+ { "kstack", "kstack", "[-v]", &procstat_kstack, &cmdopt_verbose,
+ PS_CMP_NORMAL },
+ { "pargs", "args", NULL, &procstat_pargs, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "penv", "env", NULL, &procstat_penv, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "ptlwpinfo", "ptlwpinfo", NULL, &procstat_ptlwpinfo, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "pwdx", "pwd", NULL, &procstat_pwdx, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "rlimit", "rlimit", NULL, &procstat_rlimit, &cmdopt_none,
+ PS_CMP_NORMAL },
+ { "rlimitusage", "rlimitusage", NULL, &procstat_rlimitusage,
+ &cmdopt_none, PS_CMP_NORMAL },
+ { "rusage", "rusage", "[-Ht]", &procstat_rusage, &cmdopt_rusage,
+ PS_CMP_NORMAL },
+ { "sigfastblock", "sigfastblock", NULL, &procstat_sigfastblock,
+ &cmdopt_none, PS_CMP_NORMAL },
+ { "signal", "signals", "[-n]", &procstat_sigs, &cmdopt_signals,
+ PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "thread", "threads", NULL, &procstat_threads, &cmdopt_none,
+ PS_CMP_PLURAL },
+ { "tsignal", "thread_signals", "[-n]", &procstat_threads_sigs,
+ &cmdopt_signals, PS_CMP_PLURAL | PS_CMP_SUBSTR },
+ { "vm", "vm", NULL, &procstat_vm, &cmdopt_none, PS_CMP_NORMAL }
+};
+
+static void
+usage(const struct procstat_cmd *cmd)
+{
+ size_t i, l;
+ int multi;
+
+ if (cmd == NULL || (cmd->cmp & PS_MODE_COMPAT) == 0) {
+ xo_error("usage: procstat [--libxo] [-h] [-M core] [-N system]"
+ " [-w interval] command\n"
+ " [pid ... | core ...]\n"
+ " procstat [--libxo] -a [-h] [-M core] [-N system] "
+ " [-w interval] command\n"
+ " procstat [--libxo] [-h] [-M core] [-N system]"
+ " [-w interval]\n"
+ " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
+ "-j [-n] | -k [-k] |\n"
+ " -l | -r [-H] | -s | -t | -v | -x] "
+ "[pid ... | core ...]\n"
+ " procstat [--libxo] -a [-h] [-M core] [-N system]"
+ " [-w interval]\n"
+ " [-S | -b | -c | -e | -f [-C] | -i [-n] | "
+ "-j [-n] | -k [-k] |\n"
+ " -l | -r [-H] | -s | -t | -v | -x]\n"
+ " procstat [--libxo] -L [-h] [-M core] [-N system] core ...\n"
+ "Available commands:\n");
+ for (i = 0, l = nitems(cmd_table); i < l; i++) {
+ multi = i + 1 < l && cmd_table[i].cmd ==
+ cmd_table[i + 1].cmd;
+ xo_error(" %s%s%s", multi ? "[" : "",
+ cmd_table[i].command, (cmd_table[i].cmp &
+ PS_CMP_PLURAL) ? "(s)" : "");
+ for (; i + 1 < l && cmd_table[i].cmd ==
+ cmd_table[i + 1].cmd; i++)
+ xo_error(" | %s%s", cmd_table[i + 1].command,
+ (cmd_table[i].cmp & PS_CMP_PLURAL) ?
+ "(s)" : "");
+ if (multi)
+ xo_error("]");
+ if (cmd_table[i].usage != NULL)
+ xo_error(" %s", cmd_table[i].usage);
+ xo_error("\n");
+ }
+ } else {
+ xo_error("usage: %s [--libxo] pid ...\n", progname);
+ }
+ xo_finish();
+ exit(EX_USAGE);
+}
+
+static void
+procstat(const struct procstat_cmd *cmd, struct procstat *prstat,
+ struct kinfo_proc *kipp)
+{
+ char *pidstr = NULL;
+
+ asprintf(&pidstr, "%d", kipp->ki_pid);
+ if (pidstr == NULL)
+ xo_errc(1, ENOMEM, "Failed to allocate memory in procstat()");
+ xo_open_container(pidstr);
+ cmd->cmd(prstat, kipp);
+ xo_close_container(pidstr);
+ free(pidstr);
+}
+
+/*
+ * Sort processes first by pid and then tid.
+ */
+static int
+kinfo_proc_compare(const void *a, const void *b)
+{
+ int i;
+
+ i = ((const struct kinfo_proc *)a)->ki_pid -
+ ((const struct kinfo_proc *)b)->ki_pid;
+ if (i != 0)
+ return (i);
+ i = ((const struct kinfo_proc *)a)->ki_tid -
+ ((const struct kinfo_proc *)b)->ki_tid;
+ return (i);
+}
+
+void
+kinfo_proc_sort(struct kinfo_proc *kipp, int count)
+{
+
+ qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare);
+}
+
+const char *
+kinfo_proc_thread_name(const struct kinfo_proc *kipp)
+{
+ static char name[MAXCOMLEN+1];
+
+ strlcpy(name, kipp->ki_tdname, sizeof(name));
+ strlcat(name, kipp->ki_moretdname, sizeof(name));
+ if (name[0] == '\0' || strcmp(kipp->ki_comm, name) == 0) {
+ name[0] = '-';
+ name[1] = '\0';
+ }
+
+ return (name);
+}
+
+static const struct procstat_cmd *
+getcmdbyprogname(const char *pprogname)
+{
+ const char *ca;
+ size_t i;
+
+ if (pprogname == NULL)
+ return (NULL);
+
+ for (i = 0; i < nitems(pacmd_table); i++) {
+ ca = pacmd_table[i].command;
+ if (ca != NULL && strcmp(ca, pprogname) == 0)
+ return (&pacmd_table[i]);
+ }
+
+ return (NULL);
+}
+
+static const struct procstat_cmd *
+getcmd(const char *str)
+{
+ const struct procstat_cmd *cmd;
+ size_t i, l;
+ int cmp, s;
+
+ if (str == NULL)
+ return (NULL);
+ cmd = NULL;
+ if ((l = strlen(str)) == 0)
+ return (getcmd("basic"));
+ s = l > 1 && strcasecmp(str + l - 1, "s") == 0;
+ for (i = 0; i < nitems(cmd_table); i++) {
+ /*
+ * After the first match substring matches are disabled,
+ * allowing subsequent full matches to take precedence.
+ */
+ if (cmd == NULL && (cmd_table[i].cmp & PS_CMP_SUBSTR))
+ cmp = strncasecmp(str, cmd_table[i].command, l -
+ ((cmd_table[i].cmp & PS_CMP_PLURAL) && s ? 1 : 0));
+ else if ((cmd_table[i].cmp & PS_CMP_PLURAL) && s &&
+ l == strlen(cmd_table[i].command) + 1)
+ cmp = strncasecmp(str, cmd_table[i].command, l - 1);
+ else
+ cmp = strcasecmp(str, cmd_table[i].command);
+ if (cmp == 0)
+ cmd = &cmd_table[i];
+ }
+ return (cmd);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc *p;
+ const struct procstat_cmd *cmd;
+ struct procstat *prstat, *cprstat;
+ char *dummy, *nlistf, *memf;
+ const char *xocontainer;
+ long l;
+ pid_t pid;
+ int aflag, ch, cnt, i, interval;
+
+ interval = 0;
+ cmd = NULL;
+ memf = nlistf = NULL;
+ aflag = 0;
+ argc = xo_parse_args(argc, argv);
+
+ progname = getprogname();
+ cmd = getcmdbyprogname(progname);
+
+ while ((ch = getopt(argc, argv, "abCcefHhijkLlM:N:nrSstvw:x")) != -1) {
+ switch (ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'b':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("binary");
+ break;
+ case 'C':
+ procstat_opts |= PS_OPT_CAPABILITIES;
+ break;
+ case 'c':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("arguments");
+ break;
+ case 'e':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("environment");
+ break;
+ case 'f':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("files");
+ break;
+ case 'H':
+ procstat_opts |= PS_OPT_PERTHREAD;
+ break;
+ case 'h':
+ procstat_opts |= PS_OPT_NOHEADER;
+ break;
+ case 'i':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("signals");
+ break;
+ case 'j':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("tsignals");
+ break;
+ case 'k':
+ if (cmd != NULL && cmd->cmd == procstat_kstack) {
+ if ((procstat_opts & PS_OPT_VERBOSE) != 0)
+ usage(cmd);
+ procstat_opts |= PS_OPT_VERBOSE;
+ } else {
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("kstack");
+ }
+ break;
+ case 'L':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("ptlwpinfo");
+ break;
+ case 'l':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("rlimit");
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ procstat_opts |= PS_OPT_SIGNUM;
+ break;
+ case 'r':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("rusage");
+ break;
+ case 'S':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("cpuset");
+ break;
+ case 's':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("credentials");
+ break;
+ case 't':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("threads");
+ break;
+ case 'v':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("vm");
+ break;
+ case 'w':
+ l = strtol(optarg, &dummy, 10);
+ if (*dummy != '\0')
+ usage(cmd);
+ if (l < 1 || l > INT_MAX)
+ usage(cmd);
+ interval = l;
+ break;
+ case 'x':
+ if (cmd != NULL)
+ usage(cmd);
+ cmd = getcmd("auxv");
+ break;
+ case '?':
+ default:
+ usage(cmd);
+ }
+
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (cmd == NULL && argv[0] != NULL && (cmd = getcmd(argv[0])) != NULL) {
+ if ((procstat_opts & PS_SUBCOMMAND_OPTS) != 0)
+ usage(cmd);
+ if (cmd->opt != NULL) {
+ optreset = 1;
+ optind = 1;
+ cmd->opt(argc, argv);
+ if ((cmd->cmp & PS_MODE_COMPAT) == 0) {
+ argc -= optind;
+ argv += optind;
+ }
+ } else {
+ argc -= 1;
+ argv += 1;
+ }
+ } else {
+ if (cmd == NULL)
+ cmd = getcmd("basic");
+ if (cmd->cmd != procstat_files &&
+ (procstat_opts & PS_OPT_CAPABILITIES) != 0 &&
+ (cmd->cmp & PS_MODE_COMPAT) == 0)
+ usage(cmd);
+ }
+
+ /* Must specify either the -a flag or a list of pids. */
+ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0) &&
+ (cmd->cmp & PS_MODE_NO_KINFO_PROC) == 0)
+ usage(cmd);
+
+ if (memf != NULL)
+ prstat = procstat_open_kvm(nlistf, memf);
+ else
+ prstat = procstat_open_sysctl();
+ if (prstat == NULL)
+ xo_errx(1, "procstat_open()");
+ do {
+ xocontainer = cmd->xocontainer != NULL ? cmd->xocontainer :
+ cmd->command;
+ xo_set_version(PROCSTAT_XO_VERSION);
+ xo_open_container(progname);
+ xo_open_container(xocontainer);
+
+ if ((cmd->cmp & PS_MODE_NO_KINFO_PROC) != 0) {
+ cmd->cmd(prstat, NULL);
+ goto iter;
+ }
+
+ if (aflag) {
+ p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
+ if (p == NULL)
+ xo_errx(1, "procstat_getprocs()");
+ kinfo_proc_sort(p, cnt);
+ for (i = 0; i < cnt; i++) {
+ procstat(cmd, prstat, &p[i]);
+
+ /* Suppress header after first process. */
+ procstat_opts |= PS_OPT_NOHEADER;
+ xo_flush();
+ }
+ procstat_freeprocs(prstat, p);
+ }
+ for (i = 0; i < argc; i++) {
+ l = strtol(argv[i], &dummy, 10);
+ if (*dummy == '\0') {
+ if (l < 0)
+ usage(cmd);
+ pid = l;
+
+ p = procstat_getprocs(prstat, KERN_PROC_PID,
+ pid, &cnt);
+ if (p == NULL)
+ xo_errx(1, "procstat_getprocs()");
+ if (cnt != 0)
+ procstat(cmd, prstat, p);
+ procstat_freeprocs(prstat, p);
+ } else {
+ if ((cmd->cmp & PS_MODE_COMPAT) == 0) {
+ cprstat = procstat_open_core(argv[i]);
+ if (cprstat == NULL) {
+ warnx("procstat_open()");
+ continue;
+ }
+ p = procstat_getprocs(cprstat,
+ KERN_PROC_PID, -1, &cnt);
+ if (p == NULL) {
+ xo_errx(1,
+ "procstat_getprocs()");
+ }
+ if (cnt != 0)
+ procstat(cmd, cprstat, p);
+ procstat_freeprocs(cprstat, p);
+ procstat_close(cprstat);
+ } else {
+ usage(cmd);
+ }
+ }
+ if ((cmd->cmp & PS_MODE_COMPAT) == 0) {
+ /* Suppress header after first process. */
+ procstat_opts |= PS_OPT_NOHEADER;
+ }
+ }
+
+iter:
+ xo_close_container(xocontainer);
+ xo_close_container(progname);
+ xo_finish();
+ if (interval)
+ sleep(interval);
+ } while (interval);
+
+ procstat_close(prstat);
+
+ exit(0);
+}
+
+void
+cmdopt_none(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
+
+void
+cmdopt_verbose(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ procstat_opts |= PS_OPT_VERBOSE;
+ break;
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
+
+void
+cmdopt_signals(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "n")) != -1) {
+ switch (ch) {
+ case 'n':
+ procstat_opts |= PS_OPT_SIGNUM;
+ break;
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
+
+void
+cmdopt_rusage(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Ht")) != -1) {
+ switch (ch) {
+ case 'H':
+ /* FALLTHROUGH */
+ case 't':
+ procstat_opts |= PS_OPT_PERTHREAD;
+ break;
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
+
+void
+cmdopt_files(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "C")) != -1) {
+ switch (ch) {
+ case 'C':
+ procstat_opts |= PS_OPT_CAPABILITIES;
+ break;
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
+
+void
+cmdopt_cpuset(int argc, char * const argv[])
+{
+
+ procstat_opts |= PS_OPT_PERTHREAD;
+ cmdopt_none(argc, argv);
+}
+
+void
+cmdopt_kqueue(int argc, char * const argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ procstat_opts |= PS_OPT_VERBOSE;
+ break;
+ case '?':
+ default:
+ usage(NULL);
+ }
+ }
+}
diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h
new file mode 100644
index 000000000000..e075065315f8
--- /dev/null
+++ b/usr.bin/procstat/procstat.h
@@ -0,0 +1,84 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * Copyright (c) 2017 Dell EMC
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <libxo/xo.h>
+
+#ifndef PROCSTAT_H
+#define PROCSTAT_H
+
+#define PROCSTAT_XO_VERSION "1"
+
+enum {
+ PS_OPT_CAPABILITIES = 0x01,
+ PS_OPT_NOHEADER = 0x02,
+ PS_OPT_PERTHREAD = 0x04,
+ PS_OPT_SIGNUM = 0x08,
+ PS_OPT_VERBOSE = 0x10,
+ PS_MODE_COMPAT = 0x20,
+ PS_MODE_NO_KINFO_PROC = 0x40,
+};
+
+#define PS_SUBCOMMAND_OPTS \
+ (PS_OPT_CAPABILITIES | PS_OPT_SIGNUM | \
+ PS_OPT_PERTHREAD | PS_OPT_VERBOSE)
+
+extern int procstat_opts;
+
+struct kinfo_proc;
+void kinfo_proc_sort(struct kinfo_proc *kipp, int count);
+const char * kinfo_proc_thread_name(const struct kinfo_proc *kipp);
+
+void procstat_advlocks(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_args(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_auxv(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_basic(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_cred(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_cs(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_env(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_kqueues(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_kstack(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_rlimitusage(struct procstat *procstat,
+ struct kinfo_proc *kipp);
+void procstat_pargs(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_penv(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_pwdx(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_rusage(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_sigfastblock(struct procstat *procstat,
+ struct kinfo_proc *kipp);
+void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_threads(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_threads_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
+void procstat_vm(struct procstat *prstat, struct kinfo_proc *kipp);
+
+#endif /* !PROCSTAT_H */
diff --git a/usr.bin/procstat/procstat_advlock.c b/usr.bin/procstat/procstat_advlock.c
new file mode 100644
index 000000000000..2940503817d6
--- /dev/null
+++ b/usr.bin/procstat/procstat_advlock.c
@@ -0,0 +1,102 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_advlocks(struct procstat *prstat, struct kinfo_proc *kipp __unused)
+{
+ struct advlock_list *advl;
+ struct advlock *a;
+ static const char advisory_lock_item[] = "advisory_lock";
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%2s %5s %5s %5s %18s %18s %8s %9s %9s %s}\n",
+ "RW", "TYPE", "PID", "SYSID", "FSID", "RDEV", "INO",
+ "START", "LEN", "PATH");
+
+ xo_open_list(advisory_lock_item);
+ advl = procstat_getadvlock(prstat);
+ if (advl == NULL) {
+ xo_close_list(advisory_lock_item);
+ return;
+ }
+
+ STAILQ_FOREACH(a, advl, next) {
+ xo_open_instance(advisory_lock_item);
+ switch (a->rw) {
+ case PS_ADVLOCK_RO:
+ xo_emit("{:rw/%s} ", "RO");
+ break;
+ case PS_ADVLOCK_RW:
+ xo_emit("{:rw/%s} ", "RW");
+ break;
+ default:
+ xo_emit("{:rw/%s} ", "??");
+ break;
+ }
+ switch (a->type) {
+ case PS_ADVLOCK_TYPE_FLOCK:
+ xo_emit("{:type/%s} ", "FLOCK");
+ break;
+ case PS_ADVLOCK_TYPE_PID:
+ xo_emit("{:type/%s} ", "FCNTL");
+ break;
+ case PS_ADVLOCK_TYPE_REMOTE:
+ xo_emit("{:type/%s} ", "LOCKD");
+ break;
+ default:
+ xo_emit("{:type/%s} ", "?????");
+ break;
+ }
+ xo_emit("{:pid/%5d} ", a->pid);
+ xo_emit("{:sysid/%5d} ", a->sysid);
+ xo_emit("{:fsid/%18#jx} ", (uintmax_t)a->file_fsid);
+ xo_emit("{:rdev/%#18jx} ", (uintmax_t)a->file_rdev);
+ xo_emit("{:ino/%8ju} ", (uintmax_t)a->file_fileid);
+ xo_emit("{:start/%9ju} ", (uintmax_t)a->start);
+ xo_emit("{:len/%9ju} ", (uintmax_t)a->len);
+ xo_emit("{:path/%s}", a->path == NULL ? "" : a->path);
+ xo_emit("\n");
+ xo_close_instance(advisory_lock_item);
+ }
+ xo_close_list(advisory_lock_item);
+ procstat_freeadvlock(prstat, advl);
+}
diff --git a/usr.bin/procstat/procstat_args.c b/usr.bin/procstat/procstat_args.c
new file mode 100644
index 000000000000..2542fe06d487
--- /dev/null
+++ b/usr.bin/procstat/procstat_args.c
@@ -0,0 +1,96 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_args(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ int i;
+ char **args;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ARGS");
+ }
+
+ args = procstat_getargv(procstat, kipp, 0);
+
+ xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
+ kipp->ki_comm);
+
+ if (args == NULL) {
+ xo_emit(" {d:args/-}\n");
+ return;
+ }
+
+ xo_open_list("arguments");
+ for (i = 0; args[i] != NULL; i++)
+ xo_emit(" {l:args/%s}", args[i]);
+ xo_close_list("arguments");
+ xo_emit("\n");
+}
+
+void
+procstat_env(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ int i;
+ char **envs;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ xo_emit("{T:/%5s %-16s %-53s}\n", "PID", "COMM", "ENVIRONMENT");
+ }
+
+ envs = procstat_getenvv(procstat, kipp, 0);
+
+ xo_emit("{k:process_id/%5d/%d} {:command/%-16s/%s}", kipp->ki_pid,
+ kipp->ki_comm);
+
+ if (envs == NULL) {
+ xo_emit(" {d:env/-}\n");
+ return;
+ }
+
+ xo_open_list("environment");
+ for (i = 0; envs[i] != NULL; i++)
+ xo_emit(" {l:env/%s}", envs[i]);
+ xo_close_list("environment");
+ xo_emit("\n");
+}
diff --git a/usr.bin/procstat/procstat_auxv.c b/usr.bin/procstat/procstat_auxv.c
new file mode 100644
index 000000000000..b37e27c65161
--- /dev/null
+++ b/usr.bin/procstat/procstat_auxv.c
@@ -0,0 +1,269 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 Mikolaj Golub
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/elf.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <vm/vm.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ Elf_Auxinfo *auxv;
+ u_int count, i;
+ static char prefix[256];
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %-19s %-16s %-16s}\n", "PID", "COMM", "AUXV",
+ "VALUE");
+
+ auxv = procstat_getauxv(procstat, kipp, &count);
+ if (auxv == NULL)
+ return;
+ snprintf(prefix, sizeof(prefix), "%5d %-19s", kipp->ki_pid,
+ kipp->ki_comm);
+
+ xo_emit("{e:process_id/%5d/%d}{e:command/%-19s/%s}", kipp->ki_pid,
+ kipp->ki_comm);
+
+ for (i = 0; i < count; i++) {
+ switch(auxv[i].a_type) {
+ case AT_NULL:
+ return;
+ case AT_IGNORE:
+ break;
+ case AT_EXECFD:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECFD/%ld}\n",
+ prefix, "AT_EXECFD", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_PHDR:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHDR/%p}\n",
+ prefix, "AT_PHDR", auxv[i].a_un.a_ptr);
+ break;
+ case AT_PHENT:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHENT/%ld}\n",
+ prefix, "AT_PHENT", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_PHNUM:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PHNUM/%ld}\n",
+ prefix, "AT_PHNUM", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_PAGESZ:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESZ/%ld}\n",
+ prefix, "AT_PAGESZ", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_BASE:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BASE/%p}\n",
+ prefix, "AT_BASE", auxv[i].a_un.a_ptr);
+ break;
+ case AT_FLAGS:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_FLAGS/%#lx}\n",
+ prefix, "AT_FLAGS", (u_long)auxv[i].a_un.a_val);
+ break;
+ case AT_ENTRY:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENTRY/%p}\n",
+ prefix, "AT_ENTRY", auxv[i].a_un.a_ptr);
+ break;
+#ifdef AT_NOTELF
+ case AT_NOTELF:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NOTELF/%ld}\n",
+ prefix, "AT_NOTELF", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_UID
+ case AT_UID:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_UID/%ld}\n",
+ prefix, "AT_UID", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_EUID
+ case AT_EUID:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EUID/%ld}\n",
+ prefix, "AT_EUID", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_GID
+ case AT_GID:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_GID/%ld}\n",
+ prefix, "AT_GID", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_EGID
+ case AT_EGID:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EGID/%ld}\n",
+ prefix, "AT_EGID", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+ case AT_EXECPATH:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EXECPATH/%p}\n",
+ prefix, "AT_EXECPATH", auxv[i].a_un.a_ptr);
+ break;
+ case AT_CANARY:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARY/%p}\n",
+ prefix, "AT_CANARY", auxv[i].a_un.a_ptr);
+ break;
+ case AT_CANARYLEN:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_CANARYLEN/%ld}\n",
+ prefix, "AT_CANARYLEN", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_OSRELDATE:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_OSRELDATE/%ld}\n",
+ prefix, "AT_OSRELDATE", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_NCPUS:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_NCPUS/%ld}\n",
+ prefix, "AT_NCPUS", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_PAGESIZES:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PAGESIZES/%p}\n",
+ prefix, "AT_PAGESIZES", auxv[i].a_un.a_ptr);
+ break;
+ case AT_PAGESIZESLEN:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+ "{:AT_PAGESIZESLEN/%ld}\n", prefix,
+ "AT_PAGESIZESLEN", (long)auxv[i].a_un.a_val);
+ break;
+ case AT_STACKPROT:
+ if ((auxv[i].a_un.a_val & VM_PROT_EXECUTE) != 0)
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+ "{:AT_STACKPROT/%s}\n", prefix,
+ "AT_STACKPROT", "EXECUTABLE");
+ else
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+ "{:AT_STACKPROT/%s}\n", prefix,
+ "AT_STACKPROT", "NONEXECUTABLE");
+ break;
+#ifdef AT_TIMEKEEP
+ case AT_TIMEKEEP:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_TIMEKEEP/%p}\n",
+ prefix, "AT_TIMEKEEP", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_EHDRFLAGS
+ case AT_EHDRFLAGS:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_EHDRFLAGS/%#lx}\n",
+ prefix, "AT_EHDRFLAGS", (u_long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_HWCAP
+ case AT_HWCAP:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP/%#lx}\n",
+ prefix, "AT_HWCAP", (u_long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_HWCAP2
+ case AT_HWCAP2:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_HWCAP2/%#lx}\n",
+ prefix, "AT_HWCAP2", (u_long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_BSDFLAGS
+ case AT_BSDFLAGS:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_BSDFLAGS/%#lx}\n",
+ prefix, "AT_BSDFLAGS", (u_long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_ARGC
+ case AT_ARGC:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ARGC/%ld}\n",
+ prefix, "AT_ARGC", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_ARGV
+ case AT_ARGV:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ARGV/%p}\n",
+ prefix, "AT_ARGV", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_ENVC
+ case AT_ENVC:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENVC/%ld}\n",
+ prefix, "AT_ENVC", (long)auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_ENVV
+ case AT_ENVV:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_ENVV/%p}\n",
+ prefix, "AT_ENVV", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_PS_STRINGS
+ case AT_PS_STRINGS:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PS_STRINGS/%p}\n",
+ prefix, "AT_PS_STRINGS", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_FXRNG
+ case AT_FXRNG:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_FXRNG/%p}\n",
+ prefix, "AT_FXRNG", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_KPRELOAD
+ case AT_KPRELOAD:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_KPRELOAD/%p}\n",
+ prefix, "AT_KPRELOAD", auxv[i].a_un.a_ptr);
+ break;
+#endif
+#ifdef AT_USRSTACKBASE
+ case AT_USRSTACKBASE:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+ "{:AT_USRSTACKBASE/%#lx}\n",
+ prefix, "AT_USRSTACKBASE", auxv[i].a_un.a_val);
+ break;
+#endif
+#ifdef AT_USRSTACKLIM
+ case AT_USRSTACKLIM:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}"
+ "{:AT_USRSTACKLIM/%#lx}\n",
+ prefix, "AT_USRSTACKLIM", auxv[i].a_un.a_val);
+ break;
+#endif
+ default:
+ xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n",
+ prefix, auxv[i].a_type, auxv[i].a_un.a_val);
+ break;
+ }
+ }
+ xo_emit("\n");
+ procstat_freeauxv(procstat, auxv);
+}
+
diff --git a/usr.bin/procstat/procstat_basic.c b/usr.bin/procstat/procstat_basic.c
new file mode 100644
index 000000000000..e1e3e363a9f1
--- /dev/null
+++ b/usr.bin/procstat/procstat_basic.c
@@ -0,0 +1,68 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_basic(struct procstat *procstat __unused, struct kinfo_proc *kipp)
+{
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %5s %5s %5s %5s %3s %-8s %-9s %-13s %-12s}\n",
+ "PID", "PPID", "PGID", "SID", "TSID", "THR", "LOGIN",
+ "WCHAN", "EMUL", "COMM");
+
+ xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:parent_process_id/%5d/%d} ", kipp->ki_ppid);
+ xo_emit("{:process_group_id/%5d/%d} ", kipp->ki_pgid);
+ xo_emit("{:session_id/%5d/%d} ", kipp->ki_sid);
+ xo_emit("{:terminal_session_id/%5d/%d} ", kipp->ki_tsid);
+ xo_emit("{:threads/%3d/%d} ", kipp->ki_numthreads);
+ xo_emit("{:login/%-8s/%s} ", strlen(kipp->ki_login) ?
+ kipp->ki_login : "-");
+ if (kipp->ki_kiflag & KI_LOCKBLOCK) {
+ xo_emit("{:lockname/*%-8s/%s} ", strlen(kipp->ki_lockname) ?
+ kipp->ki_lockname : "-");
+ } else {
+ xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ?
+ kipp->ki_wmesg : "-");
+ }
+ xo_emit("{:emulation/%-13s/%s} ", strcmp(kipp->ki_emul, "null") ?
+ kipp->ki_emul : "-");
+ xo_emit("{:command/%-12s/%s}\n", kipp->ki_comm);
+}
diff --git a/usr.bin/procstat/procstat_bin.c b/usr.bin/procstat/procstat_bin.c
new file mode 100644
index 000000000000..04482e5ee1ba
--- /dev/null
+++ b/usr.bin/procstat/procstat_bin.c
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp)
+{
+ int osrel;
+ static char pathname[PATH_MAX];
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %-16s %8s %s}\n", "PID", "COMM", "OSREL",
+ "PATH");
+
+ if (procstat_getpathname(prstat, kipp, pathname, sizeof(pathname)) != 0)
+ return;
+ if (strlen(pathname) == 0)
+ strcpy(pathname, "-");
+ if (procstat_getosrel(prstat, kipp, &osrel) != 0)
+ return;
+
+ xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
+ xo_emit("{:osrel/%8d/%d} ", osrel);
+ xo_emit("{:pathname/%s}\n", pathname);
+}
diff --git a/usr.bin/procstat/procstat_cred.c b/usr.bin/procstat/procstat_cred.c
new file mode 100644
index 000000000000..decb7b9ca7df
--- /dev/null
+++ b/usr.bin/procstat/procstat_cred.c
@@ -0,0 +1,103 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007-2008 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "procstat.h"
+
+static const char *get_umask(struct procstat *procstat,
+ struct kinfo_proc *kipp);
+
+void
+procstat_cred(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ unsigned int i, ngroups;
+ gid_t *groups;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %-16s %5s %5s %5s %5s %5s %5s %5s %5s %-15s}\n",
+ "PID", "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID",
+ "SVGID", "UMASK", "FLAGS", "GROUPS");
+
+ xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:command/%-16s/%s} ", kipp->ki_comm);
+ xo_emit("{:uid/%5d} ", kipp->ki_uid);
+ xo_emit("{:ruid/%5d} ", kipp->ki_ruid);
+ xo_emit("{:svuid/%5d} ", kipp->ki_svuid);
+ xo_emit("{:group/%5d} ", kipp->ki_groups[0]);
+ xo_emit("{:rgid/%5d} ", kipp->ki_rgid);
+ xo_emit("{:svgid/%5d} ", kipp->ki_svgid);
+ xo_emit("{:umask/%5s} ", get_umask(procstat, kipp));
+ xo_emit("{:cr_flags/%s}", kipp->ki_cr_flags & KI_CRF_CAPABILITY_MODE ?
+ "C" : "-");
+ xo_emit("{P: }");
+
+ groups = NULL;
+ /*
+ * We may have too many groups to fit in kinfo_proc's statically
+ * sized storage. If that occurs, attempt to retrieve them using
+ * libprocstat.
+ */
+ if (kipp->ki_cr_flags & KI_CRF_GRP_OVERFLOW)
+ groups = procstat_getgroups(procstat, kipp, &ngroups);
+ if (groups == NULL) {
+ ngroups = kipp->ki_ngroups;
+ groups = kipp->ki_groups;
+ }
+ xo_open_list("groups");
+ for (i = 0; i < ngroups; i++)
+ xo_emit("{D:/%s}{l:groups/%d}", (i > 0) ? "," : "", groups[i]);
+ if (groups != kipp->ki_groups)
+ procstat_freegroups(procstat, groups);
+
+ xo_close_list("groups");
+ xo_emit("\n");
+}
+
+static const char *
+get_umask(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ u_short fd_cmask;
+ static char umask[4];
+
+ if (procstat_getumask(procstat, kipp, &fd_cmask) == 0) {
+ snprintf(umask, 4, "%03o", fd_cmask);
+ return (umask);
+ } else {
+ return ("-");
+ }
+}
diff --git a/usr.bin/procstat/procstat_cs.c b/usr.bin/procstat/procstat_cs.c
new file mode 100644
index 000000000000..39d4174cf06a
--- /dev/null
+++ b/usr.bin/procstat/procstat_cs.c
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/cpuset.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ cpusetid_t cs;
+ cpuset_t mask;
+ struct kinfo_proc *kip;
+ struct sbuf *cpusetbuf;
+ unsigned int count, i;
+ int once, twice, lastcpu, cpu;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s}\n", "PID",
+ "TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK");
+
+ kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ kipp->ki_pid, &count);
+ if (kip == NULL)
+ return;
+ kinfo_proc_sort(kip, count);
+ for (i = 0; i < count; i++) {
+ kipp = &kip[i];
+ xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
+ xo_emit("{:command/%-19s/%s} ", strlen(kipp->ki_comm) ?
+ kipp->ki_comm : "-");
+ xo_emit("{:thread_name/%-19s/%s} ",
+ kinfo_proc_thread_name(kipp));
+ if (kipp->ki_oncpu != 255)
+ xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
+ else if (kipp->ki_lastcpu != 255)
+ xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
+ else
+ xo_emit("{:cpu/%3s/%s} ", "-");
+ if (cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID,
+ kipp->ki_tid, &cs) != 0) {
+ cs = CPUSET_INVALID;
+ }
+ xo_emit("{:cpu_set_id/%4d/%d} ", cs);
+ if ((cs != CPUSET_INVALID) &&
+ (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
+ kipp->ki_tid, sizeof(mask), &mask) == 0)) {
+ lastcpu = -1;
+ once = 0;
+ twice = 0;
+ cpusetbuf = sbuf_new_auto();
+ for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
+ if (CPU_ISSET(cpu, &mask)) {
+ if (once == 0) {
+ sbuf_printf(cpusetbuf, "%d",
+ cpu);
+ once = 1;
+ } else if (cpu == lastcpu + 1) {
+ twice = 1;
+ } else if (twice == 1) {
+ sbuf_printf(cpusetbuf, "-%d,%d",
+ lastcpu, cpu);
+ twice = 0;
+ } else
+ sbuf_printf(cpusetbuf, ",%d",
+ cpu);
+ lastcpu = cpu;
+ }
+ }
+ if (once && twice)
+ sbuf_printf(cpusetbuf, "-%d", lastcpu);
+ if (sbuf_finish(cpusetbuf) != 0)
+ xo_err(1, "Could not generate output");
+ xo_emit("{:cpu_set/%s}", sbuf_data(cpusetbuf));
+ sbuf_delete(cpusetbuf);
+ }
+ xo_emit("\n");
+ }
+ procstat_freeprocs(procstat, kip);
+}
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
new file mode 100644
index 000000000000..bd9bbfc358c9
--- /dev/null
+++ b/usr.bin/procstat/procstat_files.c
@@ -0,0 +1,595 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007-2011 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/capsicum.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/user.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+static const char *
+protocol_to_string(int domain, int type, int protocol)
+{
+
+ switch (domain) {
+ case AF_INET:
+ case AF_INET6:
+ switch (protocol) {
+ case IPPROTO_TCP:
+ return ("TCP");
+ case IPPROTO_UDP:
+ return ("UDP");
+ case IPPROTO_ICMP:
+ return ("ICM");
+ case IPPROTO_RAW:
+ return ("RAW");
+ case IPPROTO_SCTP:
+ return ("SCT");
+ default:
+ return ("IP?");
+ }
+
+ case AF_LOCAL:
+ switch (type) {
+ case SOCK_STREAM:
+ return ("UDS");
+ case SOCK_DGRAM:
+ return ("UDD");
+ default:
+ return ("UD?");
+ }
+ case AF_DIVERT:
+ return ("IPD");
+ break;
+ default:
+ return ("?");
+ }
+}
+
+static void
+addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
+{
+ char buffer2[INET6_ADDRSTRLEN];
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
+ struct sockaddr_un *sun;
+
+ switch (ss->ss_family) {
+ case AF_LOCAL:
+ sun = (struct sockaddr_un *)ss;
+ if (strlen(sun->sun_path) == 0)
+ strlcpy(buffer, "-", buflen);
+ else
+ strlcpy(buffer, sun->sun_path, buflen);
+ break;
+
+ case AF_INET:
+ sin = (struct sockaddr_in *)ss;
+ if (sin->sin_addr.s_addr == INADDR_ANY)
+ snprintf(buffer, buflen, "%s:%d", "*",
+ ntohs(sin->sin_port));
+ else if (inet_ntop(AF_INET, &sin->sin_addr, buffer2,
+ sizeof(buffer2)) != NULL)
+ snprintf(buffer, buflen, "%s:%d", buffer2,
+ ntohs(sin->sin_port));
+ break;
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)ss;
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
+ sizeof(buffer2)) != NULL)
+ snprintf(buffer, buflen, "%s.%d", buffer2,
+ ntohs(sin6->sin6_port));
+ else
+ strlcpy(buffer, "-", buflen);
+ break;
+
+ default:
+ strlcpy(buffer, "", buflen);
+ break;
+ }
+}
+
+static struct cap_desc {
+ uint64_t cd_right;
+ const char *cd_desc;
+} cap_desc[] = {
+ /* General file I/O. */
+ { CAP_READ, "rd" },
+ { CAP_WRITE, "wr" },
+ { CAP_SEEK, "se" },
+ { CAP_MMAP, "mm" },
+ { CAP_CREATE, "cr" },
+ { CAP_FEXECVE, "fe" },
+ { CAP_FSYNC, "fy" },
+ { CAP_FTRUNCATE, "ft" },
+
+ /* VFS methods. */
+ { CAP_FCHDIR, "cd" },
+ { CAP_FCHFLAGS, "cf" },
+ { CAP_FCHMOD, "cm" },
+ { CAP_FCHOWN, "cn" },
+ { CAP_FCHROOT, "ct" },
+ { CAP_FCNTL, "fc" },
+ { CAP_FLOCK, "fl" },
+ { CAP_FPATHCONF, "fp" },
+ { CAP_FSCK, "fk" },
+ { CAP_FSTAT, "fs" },
+ { CAP_FSTATFS, "sf" },
+ { CAP_FUTIMES, "fu" },
+ { CAP_LINKAT_SOURCE, "ls" },
+ { CAP_LINKAT_TARGET, "lt" },
+ { CAP_MKDIRAT, "md" },
+ { CAP_MKFIFOAT, "mf" },
+ { CAP_MKNODAT, "mn" },
+ { CAP_RENAMEAT_SOURCE, "rs" },
+ { CAP_RENAMEAT_TARGET, "rt" },
+ { CAP_SYMLINKAT, "sl" },
+ { CAP_UNLINKAT, "un" },
+
+ /* Lookups - used to constrain *at() calls. */
+ { CAP_LOOKUP, "lo" },
+
+ /* Extended attributes. */
+ { CAP_EXTATTR_GET, "eg" },
+ { CAP_EXTATTR_SET, "es" },
+ { CAP_EXTATTR_DELETE, "ed" },
+ { CAP_EXTATTR_LIST, "el" },
+
+ /* Access Control Lists. */
+ { CAP_ACL_GET, "ag" },
+ { CAP_ACL_SET, "as" },
+ { CAP_ACL_DELETE, "ad" },
+ { CAP_ACL_CHECK, "ac" },
+
+ /* Socket operations. */
+ { CAP_ACCEPT, "at" },
+ { CAP_BIND, "bd" },
+ { CAP_CONNECT, "co" },
+ { CAP_GETPEERNAME, "pn" },
+ { CAP_GETSOCKNAME, "sn" },
+ { CAP_GETSOCKOPT, "gs" },
+ { CAP_LISTEN, "ln" },
+ { CAP_PEELOFF, "pf" },
+ { CAP_SETSOCKOPT, "ss" },
+ { CAP_SHUTDOWN, "sh" },
+
+ /* Mandatory Access Control. */
+ { CAP_MAC_GET, "mg" },
+ { CAP_MAC_SET, "ms" },
+
+ /* Methods on semaphores. */
+ { CAP_SEM_GETVALUE, "sg" },
+ { CAP_SEM_POST, "sp" },
+ { CAP_SEM_WAIT, "sw" },
+
+ /* Event monitoring and posting. */
+ { CAP_EVENT, "ev" },
+ { CAP_KQUEUE_EVENT, "ke" },
+ { CAP_KQUEUE_CHANGE, "kc" },
+
+ /* Strange and powerful rights that should not be given lightly. */
+ { CAP_IOCTL, "io" },
+ { CAP_TTYHOOK, "ty" },
+
+ /* Process management via process descriptors. */
+ { CAP_PDGETPID, "pg" },
+ { CAP_PDWAIT, "pw" },
+ { CAP_PDKILL, "pk" },
+
+ /*
+ * Rights that allow to use bindat(2) and connectat(2) syscalls on a
+ * directory descriptor.
+ */
+ { CAP_BINDAT, "ba" },
+ { CAP_CONNECTAT, "ca" },
+
+ /* Aliases and defines that combine multiple rights. */
+ { CAP_PREAD, "prd" },
+ { CAP_PWRITE, "pwr" },
+
+ { CAP_MMAP_R, "mmr" },
+ { CAP_MMAP_W, "mmw" },
+ { CAP_MMAP_X, "mmx" },
+ { CAP_MMAP_RW, "mrw" },
+ { CAP_MMAP_RX, "mrx" },
+ { CAP_MMAP_WX, "mwx" },
+ { CAP_MMAP_RWX, "mma" },
+
+ { CAP_RECV, "re" },
+ { CAP_SEND, "sd" },
+
+ { CAP_SOCK_CLIENT, "scl" },
+ { CAP_SOCK_SERVER, "ssr" },
+};
+static const u_int cap_desc_count = nitems(cap_desc);
+
+static u_int
+width_capability(cap_rights_t *rightsp)
+{
+ u_int count, i, width;
+
+ count = 0;
+ width = 0;
+ for (i = 0; i < cap_desc_count; i++) {
+ if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
+ width += strlen(cap_desc[i].cd_desc);
+ if (count)
+ width++;
+ count++;
+ }
+ }
+ return (width);
+}
+
+static void
+print_capability(cap_rights_t *rightsp, u_int capwidth)
+{
+ u_int count, i;
+
+ count = 0;
+ for (i = width_capability(rightsp); i < capwidth; i++) {
+ if (i != 0)
+ xo_emit(" ");
+ else
+ xo_emit("-");
+ }
+ xo_open_list("capabilities");
+ for (i = 0; i < cap_desc_count; i++) {
+ if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
+ xo_emit("{D:/%s}{l:capabilities/%s}", count ? "," : "",
+ cap_desc[i].cd_desc);
+ count++;
+ }
+ }
+ xo_close_list("capabilities");
+}
+
+void
+procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct sockstat sock;
+ struct filestat_list *head;
+ struct filestat *fst;
+ const char *str;
+ struct vnstat vn;
+ u_int capwidth, width;
+ int error;
+ char src_addr[PATH_MAX];
+ char dst_addr[PATH_MAX];
+
+ /*
+ * To print the header in capability mode, we need to know the width
+ * of the widest capability string. Even if we get no processes
+ * back, we will print the header, so we defer aborting due to a lack
+ * of processes until after the header logic.
+ */
+ capwidth = 0;
+ head = procstat_getfiles(procstat, kipp, 0);
+ if (head != NULL &&
+ (procstat_opts & PS_OPT_CAPABILITIES) != 0) {
+ STAILQ_FOREACH(fst, head, next) {
+ width = width_capability(&fst->fs_cap_rights);
+ if (width > capwidth)
+ capwidth = width;
+ }
+ if (capwidth < strlen("CAPABILITIES"))
+ capwidth = strlen("CAPABILITIES");
+ }
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ if ((procstat_opts & PS_OPT_CAPABILITIES) != 0)
+ xo_emit("{T:/%5s %-16s %5s %1s %-8s %-*s "
+ "%-3s %-12s}\n", "PID", "COMM", "FD", "T",
+ "FLAGS", capwidth, "CAPABILITIES", "PRO",
+ "NAME");
+ else
+ xo_emit("{T:/%5s %-16s %5s %1s %1s %-8s "
+ "%3s %7s %-3s %-12s}\n", "PID", "COMM", "FD", "T",
+ "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME");
+ }
+
+ if (head == NULL)
+ return;
+ xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+ xo_open_list("files");
+ STAILQ_FOREACH(fst, head, next) {
+ xo_open_instance("files");
+ xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
+ if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
+ xo_emit("{P: }{:fd/%s} ", "ctty");
+ else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
+ xo_emit("{P: }{:fd/%s} ", "cwd");
+ else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
+ xo_emit("{P: }{:fd/%s} ", "jail");
+ else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
+ xo_emit("{P: }{:fd/%s} ", "root");
+ else if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
+ xo_emit("{P: }{:fd/%s} ", "text");
+ else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
+ xo_emit("{:fd/%s} ", "trace");
+ else
+ xo_emit("{:fd/%5d} ", fst->fs_fd);
+
+ switch (fst->fs_type) {
+ case PS_FST_TYPE_VNODE:
+ str = "v";
+ xo_emit("{eq:fd_type/vnode}");
+ break;
+
+ case PS_FST_TYPE_SOCKET:
+ str = "s";
+ xo_emit("{eq:fd_type/socket}");
+ break;
+
+ case PS_FST_TYPE_PIPE:
+ str = "p";
+ xo_emit("{eq:fd_type/pipe}");
+ break;
+
+ case PS_FST_TYPE_FIFO:
+ str = "f";
+ xo_emit("{eq:fd_type/fifo}");
+ break;
+
+ case PS_FST_TYPE_KQUEUE:
+ str = "k";
+ xo_emit("{eq:fd_type/kqueue}");
+ break;
+
+ case PS_FST_TYPE_MQUEUE:
+ str = "m";
+ xo_emit("{eq:fd_type/mqueue}");
+ break;
+
+ case PS_FST_TYPE_SHM:
+ str = "h";
+ xo_emit("{eq:fd_type/shm}");
+ break;
+
+ case PS_FST_TYPE_PTS:
+ str = "t";
+ xo_emit("{eq:fd_type/pts}");
+ break;
+
+ case PS_FST_TYPE_SEM:
+ str = "e";
+ xo_emit("{eq:fd_type/sem}");
+ break;
+
+ case PS_FST_TYPE_PROCDESC:
+ str = "P";
+ xo_emit("{eq:fd_type/procdesc}");
+ break;
+
+ case PS_FST_TYPE_DEV:
+ str = "D";
+ xo_emit("{eq:fd_type/dev}");
+ break;
+
+ case PS_FST_TYPE_EVENTFD:
+ str = "E";
+ xo_emit("{eq:fd_type/eventfd}");
+ break;
+
+ case PS_FST_TYPE_NONE:
+ str = "?";
+ xo_emit("{eq:fd_type/none}");
+ break;
+
+ case PS_FST_TYPE_UNKNOWN:
+ default:
+ str = "?";
+ xo_emit("{eq:fd_type/unknown}");
+ break;
+ }
+ xo_emit("{d:fd_type/%1s/%s} ", str);
+ if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
+ str = "-";
+ if (fst->fs_type == PS_FST_TYPE_VNODE) {
+ error = procstat_get_vnode_info(procstat, fst,
+ &vn, NULL);
+ switch (vn.vn_type) {
+ case PS_FST_VTYPE_VREG:
+ str = "r";
+ xo_emit("{eq:vode_type/regular}");
+ break;
+
+ case PS_FST_VTYPE_VDIR:
+ str = "d";
+ xo_emit("{eq:vode_type/directory}");
+ break;
+
+ case PS_FST_VTYPE_VBLK:
+ str = "b";
+ xo_emit("{eq:vode_type/block}");
+ break;
+
+ case PS_FST_VTYPE_VCHR:
+ str = "c";
+ xo_emit("{eq:vode_type/character}");
+ break;
+
+ case PS_FST_VTYPE_VLNK:
+ str = "l";
+ xo_emit("{eq:vode_type/link}");
+ break;
+
+ case PS_FST_VTYPE_VSOCK:
+ str = "s";
+ xo_emit("{eq:vode_type/socket}");
+ break;
+
+ case PS_FST_VTYPE_VFIFO:
+ str = "f";
+ xo_emit("{eq:vode_type/fifo}");
+ break;
+
+ case PS_FST_VTYPE_VBAD:
+ str = "x";
+ xo_emit("{eq:vode_type/revoked_device}");
+ break;
+
+ case PS_FST_VTYPE_VNON:
+ str = "?";
+ xo_emit("{eq:vode_type/non}");
+ break;
+
+ case PS_FST_VTYPE_UNKNOWN:
+ default:
+ str = "?";
+ xo_emit("{eq:vode_type/unknown}");
+ break;
+ }
+ }
+ xo_emit("{d:vnode_type/%1s/%s} ", str);
+ }
+
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_READ ?
+ "r" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_WRITE ?
+ "w" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_APPEND ?
+ "a" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_ASYNC ?
+ "s" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_SYNC ?
+ "f" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ?
+ "n" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_DIRECT ?
+ "d" : "-");
+ xo_emit("{d:/%s}", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ?
+ "l" : "-");
+ xo_emit(" ");
+ xo_open_list("fd_flags");
+ if (fst->fs_fflags & PS_FST_FFLAG_READ)
+ xo_emit("{elq:fd_flags/read}");
+ if (fst->fs_fflags & PS_FST_FFLAG_WRITE)
+ xo_emit("{elq:fd_flags/write}");
+ if (fst->fs_fflags & PS_FST_FFLAG_APPEND)
+ xo_emit("{elq:fd_flags/append}");
+ if (fst->fs_fflags & PS_FST_FFLAG_ASYNC)
+ xo_emit("{elq:fd_flags/async}");
+ if (fst->fs_fflags & PS_FST_FFLAG_SYNC)
+ xo_emit("{elq:fd_flags/fsync}");
+ if (fst->fs_fflags & PS_FST_FFLAG_NONBLOCK)
+ xo_emit("{elq:fd_flags/nonblocking}");
+ if (fst->fs_fflags & PS_FST_FFLAG_DIRECT)
+ xo_emit("{elq:fd_flags/direct_io}");
+ if (fst->fs_fflags & PS_FST_FFLAG_HASLOCK)
+ xo_emit("{elq:fd_flags/lock_held}");
+ xo_close_list("fd_flags");
+
+ if ((procstat_opts & PS_OPT_CAPABILITIES) == 0) {
+ if (fst->fs_ref_count > -1)
+ xo_emit("{:ref_count/%3d/%d} ",
+ fst->fs_ref_count);
+ else
+ xo_emit("{q:ref_count/%3c/%c} ", '-');
+ if (fst->fs_offset > -1)
+ xo_emit("{:offset/%7jd/%jd} ",
+ (intmax_t)fst->fs_offset);
+ else
+ xo_emit("{q:offset/%7c/%c} ", '-');
+ }
+ if ((procstat_opts & PS_OPT_CAPABILITIES) != 0) {
+ print_capability(&fst->fs_cap_rights, capwidth);
+ xo_emit(" ");
+ }
+ switch (fst->fs_type) {
+ case PS_FST_TYPE_SOCKET:
+ error = procstat_get_socket_info(procstat, fst, &sock,
+ NULL);
+ if (error != 0)
+ break;
+ xo_emit("{:protocol/%-3s/%s} ",
+ protocol_to_string(sock.dom_family,
+ sock.type, sock.proto));
+ if (sock.proto == IPPROTO_TCP ||
+ sock.proto == IPPROTO_SCTP ||
+ sock.type == SOCK_STREAM) {
+ xo_emit("{:sendq/%u} ", sock.sendq);
+ xo_emit("{:recvq/%u} ", sock.recvq);
+ }
+ /*
+ * While generally we like to print two addresses,
+ * local and peer, for sockets, it turns out to be
+ * more useful to print the first non-nul address for
+ * local sockets, as typically they aren't bound and
+ * connected, and the path strings can get long.
+ */
+ if (sock.dom_family == AF_LOCAL) {
+ struct sockaddr_un *sun =
+ (struct sockaddr_un *)&sock.sa_local;
+
+ if (sun->sun_path[0] != 0)
+ addr_to_string(&sock.sa_local,
+ src_addr, sizeof(src_addr));
+ else
+ addr_to_string(&sock.sa_peer,
+ src_addr, sizeof(src_addr));
+ xo_emit("{:path/%s}", src_addr);
+ } else {
+ addr_to_string(&sock.sa_local, src_addr,
+ sizeof(src_addr));
+ addr_to_string(&sock.sa_peer, dst_addr,
+ sizeof(dst_addr));
+ xo_emit("{:path/%s %s}", src_addr, dst_addr);
+ }
+ break;
+
+ default:
+ xo_emit("{:protocol/%-3s/%s} ", "-");
+ xo_emit("{:path/%-18s/%s}", fst->fs_path != NULL ?
+ fst->fs_path : "-");
+ }
+
+ xo_emit("\n");
+ xo_close_instance("files");
+ }
+ xo_close_list("files");
+ procstat_freefiles(procstat, head);
+}
diff --git a/usr.bin/procstat/procstat_kqueue.c b/usr.bin/procstat/procstat_kqueue.c
new file mode 100644
index 000000000000..ce9d2cb42fe2
--- /dev/null
+++ b/usr.bin/procstat/procstat_kqueue.c
@@ -0,0 +1,319 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/event.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "procstat.h"
+
+static const char kqs[] = "kqueues";
+static const char kq[] = "kqueue";
+
+#define FILT_ELEM(name) [-EVFILT_##name] = #name,
+static const char *const filter_names[] = {
+ [0] = "invalid",
+ FILT_ELEM(READ)
+ FILT_ELEM(WRITE)
+ FILT_ELEM(AIO)
+ FILT_ELEM(VNODE)
+ FILT_ELEM(PROC)
+ FILT_ELEM(SIGNAL)
+ FILT_ELEM(TIMER)
+ FILT_ELEM(PROCDESC)
+ FILT_ELEM(FS)
+ FILT_ELEM(LIO)
+ FILT_ELEM(USER)
+ FILT_ELEM(SENDFILE)
+ FILT_ELEM(EMPTY)
+};
+#undef FILT_ELEM
+
+#define PK_FLAG_ELEM(fname, str) { .flag = fname, .dispstr = str }
+#define PK_NAME_ELEM(prefix, fname) { .flag = prefix##fname, .dispstr = #fname }
+#define PK_FLAG_LAST_ELEM() { .flag = -1, .dispstr = NULL }
+struct pk_elem {
+ unsigned int flag;
+ const char *dispstr;
+};
+
+static const struct pk_elem kn_status_names[] = {
+ PK_FLAG_ELEM(KNOTE_STATUS_ACTIVE, "A"),
+ PK_FLAG_ELEM(KNOTE_STATUS_QUEUED, "Q"),
+ PK_FLAG_ELEM(KNOTE_STATUS_DISABLED, "D"),
+ PK_FLAG_ELEM(KNOTE_STATUS_DETACHED, "d"),
+ PK_FLAG_ELEM(KNOTE_STATUS_KQUEUE, "K"),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static const struct pk_elem ev_flags_names[] = {
+ PK_FLAG_ELEM(EV_ONESHOT, "O"),
+ PK_FLAG_ELEM(EV_CLEAR, "C"),
+ PK_FLAG_ELEM(EV_RECEIPT, "R"),
+ PK_FLAG_ELEM(EV_DISPATCH, "D"),
+ PK_FLAG_ELEM(EV_DROP, "d"),
+ PK_FLAG_ELEM(EV_FLAG1, "1"),
+ PK_FLAG_ELEM(EV_FLAG2, "2"),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static char *
+procstat_kqueue_flags(const struct pk_elem *names, unsigned flags, bool commas)
+{
+ char *res;
+ const struct pk_elem *pl;
+ size_t len;
+ int i;
+ bool first;
+
+ first = true;
+ len = 0;
+ for (i = 0;; i++) {
+ pl = &names[i];
+ if (pl->flag == (unsigned)-1)
+ break;
+ if ((flags & pl->flag) != 0) {
+ if (first)
+ first = false;
+ else if (commas)
+ len += sizeof(",");
+ len += strlen(pl->dispstr);
+ }
+ }
+ len++;
+
+ res = malloc(len);
+ first = true;
+ res[0] = '\0';
+ for (i = 0;; i++) {
+ pl = &names[i];
+ if (pl->flag == (unsigned)-1)
+ break;
+ if ((flags & pl->flag) != 0) {
+ if (first)
+ first = false;
+ else if (commas)
+ strlcat(res, ",", len);
+ strlcat(res, pl->dispstr, len);
+ }
+ }
+
+ if (strlen(res) == 0)
+ return (strdup("-"));
+ return (res);
+}
+
+static const struct pk_elem rw_filter_names[] = {
+ PK_NAME_ELEM(NOTE_, LOWAT),
+ PK_NAME_ELEM(NOTE_, FILE_POLL),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static const struct pk_elem user_filter_names[] = {
+ PK_NAME_ELEM(NOTE_, FFAND),
+ PK_NAME_ELEM(NOTE_, FFOR),
+ PK_NAME_ELEM(NOTE_, TRIGGER),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static const struct pk_elem vnode_filter_names[] = {
+ PK_NAME_ELEM(NOTE_, DELETE),
+ PK_NAME_ELEM(NOTE_, WRITE),
+ PK_NAME_ELEM(NOTE_, EXTEND),
+ PK_NAME_ELEM(NOTE_, ATTRIB),
+ PK_NAME_ELEM(NOTE_, LINK),
+ PK_NAME_ELEM(NOTE_, RENAME),
+ PK_NAME_ELEM(NOTE_, REVOKE),
+ PK_NAME_ELEM(NOTE_, OPEN),
+ PK_NAME_ELEM(NOTE_, CLOSE),
+ PK_NAME_ELEM(NOTE_, CLOSE_WRITE),
+ PK_NAME_ELEM(NOTE_, READ),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static const struct pk_elem proc_filter_names[] = {
+ PK_NAME_ELEM(NOTE_, EXIT),
+ PK_NAME_ELEM(NOTE_, FORK),
+ PK_NAME_ELEM(NOTE_, EXEC),
+ PK_NAME_ELEM(NOTE_, TRACK),
+ PK_NAME_ELEM(NOTE_, TRACKERR),
+ PK_NAME_ELEM(NOTE_, CHILD),
+ PK_FLAG_LAST_ELEM(),
+};
+
+static const struct pk_elem timer_filter_names[] = {
+ PK_NAME_ELEM(NOTE_, SECONDS),
+ PK_NAME_ELEM(NOTE_, MSECONDS),
+ PK_NAME_ELEM(NOTE_, USECONDS),
+ PK_NAME_ELEM(NOTE_, NSECONDS),
+ PK_NAME_ELEM(NOTE_, ABSTIME),
+ PK_FLAG_LAST_ELEM(),
+};
+
+#define FILT_ELEM(name) [-EVFILT_##name] = "EVFILT_"#name
+static const struct pk_elem *const filter_pk_names[] = {
+ [0] = NULL,
+ [-EVFILT_READ] = rw_filter_names,
+ [-EVFILT_WRITE] = rw_filter_names,
+ [-EVFILT_AIO] = rw_filter_names,
+ [-EVFILT_VNODE] = vnode_filter_names,
+ [-EVFILT_PROC] = proc_filter_names,
+ [-EVFILT_SIGNAL] = NULL,
+ [-EVFILT_TIMER] = timer_filter_names,
+ [-EVFILT_PROCDESC] = proc_filter_names,
+ [-EVFILT_FS] = NULL,
+ [-EVFILT_LIO] = rw_filter_names,
+ [-EVFILT_USER] = user_filter_names,
+ [-EVFILT_SENDFILE] = NULL,
+ [-EVFILT_EMPTY] = NULL,
+};
+
+static char *
+procstat_kqueue_fflags(int filter, unsigned fflags)
+{
+ const struct pk_elem *names;
+
+ names = NULL;
+ if (filter < 0 && -filter < (int)nitems(filter_pk_names))
+ names = filter_pk_names[-filter];
+ if (names == NULL)
+ return (strdup("-"));
+ return (procstat_kqueue_flags(names, fflags, true));
+}
+
+static const char *
+procstat_kqueue_get_filter_name(int filter)
+{
+ filter = -filter;
+ if (filter < 0 || filter >= (int)nitems(filter_names))
+ filter = 0;
+ return (filter_names[filter]);
+}
+
+static void
+procstat_kqueue(struct procstat *procstat, struct kinfo_proc *kipp, int fd,
+ bool verbose)
+{
+ struct kinfo_knote *kni, *knis;
+ char *flags, *fflags, *status;
+ unsigned int count, i, j;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ errbuf[0] = '\0';
+ knis = procstat_get_kqueue_info(procstat, kipp, fd, &count, errbuf);
+ if (knis == NULL) {
+ warnx("%s\n", errbuf);
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ kni = &knis[i];
+ flags = procstat_kqueue_flags(ev_flags_names,
+ kni->knt_event.flags, false);
+ fflags = procstat_kqueue_fflags(kni->knt_event.filter,
+ kni->knt_event.fflags);
+ status = procstat_kqueue_flags(kn_status_names,
+ kni->knt_status, false);
+ xo_open_instance(kq);
+ xo_emit("{dk:process_id/%7d} ", kipp->ki_pid);
+ xo_emit("{:kqueue_fd/%10d} ", fd);
+ xo_emit("{:filter/%8s} ", procstat_kqueue_get_filter_name(
+ kni->knt_event.filter));
+ xo_emit("{:ident/%10d} ", kni->knt_event.ident);
+ xo_emit("{:flags/%10s} ", flags);
+ xo_emit("{:fflags/%10s} ", fflags);
+ xo_emit("{:data/%#10jx} ", (uintmax_t)kni->knt_event.data);
+ xo_emit("{:udata/%10p} ", (uintmax_t)kni->knt_event.udata);
+ if (verbose) {
+ for (j = 0; j < nitems(kni->knt_event.ext); j++) {
+ xo_emit("{:ext%u/%#10jx} ", j,
+ (uintmax_t)kni->knt_event.ext[j]);
+ }
+ }
+ xo_emit("{:status/%10s}\n", status);
+ free(flags);
+ free(fflags);
+ free(status);
+ xo_close_instance(kq);
+ }
+
+ procstat_freekqinfo(procstat, knis);
+}
+
+void
+procstat_kqueues(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct filestat_list *fl;
+ struct filestat *f;
+ bool verbose;
+
+ verbose = (procstat_opts & PS_OPT_VERBOSE) != 0;
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ if (verbose) {
+ xo_emit("{T:/%7s %10s %8s %10s %10s %10s %10s %10s "
+ "%10s %10s %10s %10s %10s}\n",
+ "PID", "KQFD", "FILTER", "IDENT", "FLAGS", "FFLAGS",
+ "DATA", "UDATA", "EXT0", "EXT1","EXT2","EXT3",
+ "STATUS");
+ } else {
+ xo_emit("{T:/%7s %10s %8s %10s %10s %10s %10s %10s "
+ "%10s}\n",
+ "PID", "KQFD", "FILTER", "IDENT", "FLAGS", "FFLAGS",
+ "DATA", "UDATA", "STATUS");
+ }
+ }
+
+ xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+
+ fl = procstat_getfiles(procstat, kipp, 0);
+ if (fl == NULL)
+ return;
+ xo_open_list(kqs);
+ STAILQ_FOREACH(f, fl, next) {
+ if (f->fs_type != PS_FST_TYPE_KQUEUE)
+ continue;
+ xo_emit("{ek:kqueue/%d}", f->fs_fd);
+ xo_open_list(kq);
+ procstat_kqueue(procstat, kipp, f->fs_fd, verbose);
+ xo_close_list(kq);
+ }
+ xo_close_list(kqs);
+ procstat_freefiles(procstat, fl);
+}
diff --git a/usr.bin/procstat/procstat_kstack.c b/usr.bin/procstat/procstat_kstack.c
new file mode 100644
index 000000000000..49505bcb9efc
--- /dev/null
+++ b/usr.bin/procstat/procstat_kstack.c
@@ -0,0 +1,247 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+/*
+ * Walk the stack trace provided by the kernel and reduce it to what we
+ * actually want to print. This involves stripping true instruction pointers,
+ * frame numbers, and carriage returns as generated by stack(9). If -kk is
+ * specified, print the function and offset, otherwise just the function.
+ */
+enum trace_state { TS_FRAMENUM, TS_PC, TS_AT, TS_FUNC, TS_OFF };
+
+static enum trace_state
+kstack_nextstate(enum trace_state ts)
+{
+
+ switch (ts) {
+ case TS_FRAMENUM:
+ return (TS_PC);
+
+ case TS_PC:
+ return (TS_AT);
+
+ case TS_AT:
+ return (TS_FUNC);
+
+ case TS_FUNC:
+ return (TS_OFF);
+
+ case TS_OFF:
+ return (TS_FRAMENUM);
+
+ default:
+ errx(-1, "kstack_nextstate");
+ }
+}
+
+static void
+kstack_cleanup(const char *old, char *new, int kflag)
+{
+ enum trace_state old_ts, ts;
+ const char *cp_old;
+ char *cp_new;
+
+ ts = TS_FRAMENUM;
+ for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) {
+ switch (*cp_old) {
+ case ' ':
+ case '\n':
+ case '+':
+ old_ts = ts;
+ ts = kstack_nextstate(old_ts);
+ if (old_ts == TS_OFF) {
+ *cp_new = ' ';
+ cp_new++;
+ }
+ if (kflag > 1 && old_ts == TS_FUNC) {
+ *cp_new = '+';
+ cp_new++;
+ }
+ continue;
+ }
+ if (ts == TS_FUNC || (kflag > 1 && ts == TS_OFF)) {
+ *cp_new = *cp_old;
+ cp_new++;
+ }
+ }
+ *cp_new = '\0';
+}
+
+static void
+kstack_cleanup_encoded(const char *old, char *new, int kflag)
+{
+ enum trace_state old_ts, ts;
+ const char *cp_old;
+ char *cp_new, *cp_loop, *cp_tofree, *cp_line;
+
+ ts = TS_FRAMENUM;
+ if (kflag == 1) {
+ for (cp_old = old, cp_new = new; *cp_old != '\0'; cp_old++) {
+ switch (*cp_old) {
+ case '\n':
+ *cp_new = *cp_old;
+ cp_new++;
+ case ' ':
+ case '+':
+ old_ts = ts;
+ ts = kstack_nextstate(old_ts);
+ continue;
+ }
+ if (ts == TS_FUNC) {
+ *cp_new = *cp_old;
+ cp_new++;
+ }
+ }
+ *cp_new = '\0';
+ cp_tofree = cp_loop = strdup(new);
+ } else
+ cp_tofree = cp_loop = strdup(old);
+ while ((cp_line = strsep(&cp_loop, "\n")) != NULL) {
+ if (strlen(cp_line) != 0 && *cp_line != 127)
+ xo_emit("{le:token/%s}", cp_line);
+ }
+ free(cp_tofree);
+}
+
+/*
+ * Sort threads by tid.
+ */
+static int
+kinfo_kstack_compare(const void *a, const void *b)
+{
+
+ return ((const struct kinfo_kstack *)a)->kkst_tid -
+ ((const struct kinfo_kstack *)b)->kkst_tid;
+}
+
+static void
+kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count)
+{
+
+ qsort(kkstp, count, sizeof(*kkstp), kinfo_kstack_compare);
+}
+
+
+void
+procstat_kstack(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_kstack *kkstp, *kkstp_free;
+ struct kinfo_proc *kip, *kip_free;
+ char trace[KKST_MAXLEN], encoded_trace[KKST_MAXLEN];
+ unsigned int i, j;
+ unsigned int kip_count, kstk_count;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %6s %-19s %-19s %-29s}\n", "PID", "TID", "COMM",
+ "TDNAME", "KSTACK");
+
+ kkstp = kkstp_free = procstat_getkstack(procstat, kipp, &kstk_count);
+ if (kkstp == NULL)
+ return;
+
+ /*
+ * We need to re-query for thread information, so don't use *kipp.
+ */
+ kip = kip_free = procstat_getprocs(procstat,
+ KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &kip_count);
+
+ if (kip == NULL) {
+ procstat_freekstack(procstat, kkstp_free);
+ return;
+ }
+
+ kinfo_kstack_sort(kkstp, kstk_count);
+ for (i = 0; i < kstk_count; i++) {
+ kkstp = &kkstp_free[i];
+
+ /*
+ * Look up the specific thread using its tid so we can
+ * display the per-thread command line.
+ */
+ kipp = NULL;
+ for (j = 0; j < kip_count; j++) {
+ kipp = &kip_free[j];
+ if (kkstp->kkst_tid == kipp->ki_tid)
+ break;
+ }
+ if (kipp == NULL)
+ continue;
+
+ xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:thread_id/%6d/%d} ", kkstp->kkst_tid);
+ xo_emit("{:command/%-19s/%s} ", kipp->ki_comm);
+ xo_emit("{:thread_name/%-19s/%s} ",
+ kinfo_proc_thread_name(kipp));
+
+ switch (kkstp->kkst_state) {
+ case KKST_STATE_RUNNING:
+ xo_emit("{:state/%-29s/%s}\n", "<running>");
+ continue;
+
+ case KKST_STATE_SWAPPED:
+ xo_emit("{:state/%-29s/%s}\n", "<swapped>");
+ continue;
+
+ case KKST_STATE_STACKOK:
+ break;
+
+ default:
+ xo_emit("{:state/%-29s/%s}\n", "<unknown>");
+ continue;
+ }
+
+ /*
+ * The kernel generates a trace with carriage returns between
+ * entries, but for a more compact view, we convert carriage
+ * returns to spaces.
+ */
+ kstack_cleanup(kkstp->kkst_trace, trace,
+ (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1);
+ xo_open_list("trace");
+ kstack_cleanup_encoded(kkstp->kkst_trace, encoded_trace,
+ (procstat_opts & PS_OPT_VERBOSE) != 0 ? 2 : 1);
+ xo_close_list("trace");
+ xo_emit("{d:trace/%-29s}\n", trace);
+ }
+ procstat_freekstack(procstat, kkstp_free);
+ procstat_freeprocs(procstat, kip_free);
+}
diff --git a/usr.bin/procstat/procstat_penv.c b/usr.bin/procstat/procstat_penv.c
new file mode 100644
index 000000000000..b8f3c44a7b04
--- /dev/null
+++ b/usr.bin/procstat/procstat_penv.c
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Juraj Lutter <juraj@lutter.sk>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_pargs(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ int i;
+ char **args;
+
+ args = procstat_getargv(procstat, kipp, 0);
+
+ xo_emit("{k:process_id/%d}: {:command/%s/%s}\n", kipp->ki_pid,
+ kipp->ki_comm);
+
+ if (args == NULL) {
+ xo_emit("{d:args/-}\n");
+ } else {
+ for (i = 0; args[i] != NULL; i++) {
+ xo_emit("{Ld:argv[}{Ld:/%d}{Ldwc:]}{l:argv/%s}\n",
+ i, args[i]);
+ }
+ }
+}
+
+void
+procstat_penv(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ int i;
+ char **envs;
+
+ envs = procstat_getenvv(procstat, kipp, 0);
+
+ xo_emit("{k:process_id/%d}: {:command/%s/%s}\n", kipp->ki_pid,
+ kipp->ki_comm);
+
+ if (envs == NULL) {
+ xo_emit("{d:env/-}\n");
+ } else {
+ for (i = 0; envs[i] != NULL; i++) {
+ xo_emit("{Ld:envp[}{Ld:/%d}{Ldwc:]}{l:envp/%s}\n",
+ i, envs[i]);
+ }
+ }
+}
diff --git a/usr.bin/procstat/procstat_ptlwpinfo.c b/usr.bin/procstat/procstat_ptlwpinfo.c
new file mode 100644
index 000000000000..bce5119516e3
--- /dev/null
+++ b/usr.bin/procstat/procstat_ptlwpinfo.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2017 Dell EMC
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+
+#include <libprocstat.h>
+
+#include "procstat.h"
+
+void
+procstat_ptlwpinfo(struct procstat *prstat, struct kinfo_proc *kipp __unused)
+{
+ struct ptrace_lwpinfo *pl;
+ unsigned int count, i;
+
+ pl = procstat_getptlwpinfo(prstat, &count);
+ if (pl == NULL)
+ return;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit(
+ "{T:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{T:/%s}{]:} {T:/%s}\n",
+ "LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID",
+ 2 * sizeof(void *) + 2, "ADDR", "TDNAME");
+
+ xo_open_container("threads");
+ for (i = 0; i < count; i++) {
+ xo_open_container("thread");
+ xo_emit("{:lwpid/%6d} ", pl[i].pl_lwpid);
+ switch (pl[i].pl_event) {
+ case PL_EVENT_NONE:
+ xo_emit("{eq:event/none}{d:event/%7s} ", "none");
+ break;
+ case PL_EVENT_SIGNAL:
+ xo_emit("{eq:event/signal}{d:event/%7s} ", "signal");
+ break;
+ default:
+ xo_emit("{eq:event/unknown}{d:event/%7s} ", "?");
+ break;
+ }
+ if ((pl[i].pl_flags & PL_FLAG_SI) != 0) {
+ siginfo_t *si;
+
+ si = &pl[i].pl_siginfo;
+ xo_emit("{:signal_number/%5d} ", si->si_signo);
+ xo_emit("{:code/%5d} ", si->si_code);
+ xo_emit("{:signal_errno/%5d} ", si->si_errno);
+ xo_emit("{:process_id/%6d} ", si->si_pid);
+ xo_emit("{:user_id/%5d} ", si->si_uid);
+ xo_emit("{[:/%d}{:address/%p}{]:} ",
+ 2 * sizeof(void *) + 2, si->si_addr);
+ } else {
+ xo_emit("{:signal_number/%5s} ", "-");
+ xo_emit("{:code/%5s} ", "-");
+ xo_emit("{:signal_errno/%5s} ", "-");
+ xo_emit("{:process_id/%6s} ", "-");
+ xo_emit("{:user_id/%5s} ", "-");
+ xo_emit("{[:/%d}{:address/%s}{]:} ",
+ 2 * sizeof(void *) + 2, "-");
+ }
+ xo_emit("{:tdname/%s}\n", pl[i].pl_tdname);
+ xo_close_container("thread");
+ }
+ xo_close_container("threads");
+
+ procstat_freeptlwpinfo(prstat, pl);
+}
diff --git a/usr.bin/procstat/procstat_pwdx.c b/usr.bin/procstat/procstat_pwdx.c
new file mode 100644
index 000000000000..ee07dd6ed855
--- /dev/null
+++ b/usr.bin/procstat/procstat_pwdx.c
@@ -0,0 +1,67 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2020 Juraj Lutter <juraj@lutter.sk>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/capsicum.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/user.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_pwdx(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct filestat_list *head;
+ struct filestat *fst;
+
+ head = procstat_getfiles(procstat, kipp, 0);
+ if (head == NULL)
+ return;
+ STAILQ_FOREACH(fst, head, next) {
+ if ((fst->fs_uflags & PS_FST_UFLAG_CDIR) &&
+ (fst->fs_path != NULL)) {
+ xo_emit("{k:process_id/%d}{P:: }", kipp->ki_pid);
+ xo_emit("{:cwd/%s}", fst->fs_path);
+ xo_emit("\n");
+ }
+ }
+ procstat_freefiles(procstat, head);
+}
diff --git a/usr.bin/procstat/procstat_rlimit.c b/usr.bin/procstat/procstat_rlimit.c
new file mode 100644
index 000000000000..c34550295f05
--- /dev/null
+++ b/usr.bin/procstat/procstat_rlimit.c
@@ -0,0 +1,127 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 Mikolaj Golub
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <libutil.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+static struct {
+ const char *name;
+ const char *suffix;
+} rlimit_param[] = {
+ {"cputime", "sec"},
+ {"filesize", "B "},
+ {"datasize", "B "},
+ {"stacksize", "B "},
+ {"coredumpsize", "B "},
+ {"memoryuse", "B "},
+ {"memorylocked", "B "},
+ {"maxprocesses", " "},
+ {"openfiles", " "},
+ {"sbsize", "B "},
+ {"vmemoryuse", "B "},
+ {"pseudo-terminals", " "},
+ {"swapuse", "B "},
+ {"kqueues", " "},
+ {"umtxp", " "},
+ {"pipebuf", "B "},
+};
+
+_Static_assert(nitems(rlimit_param) == RLIM_NLIMITS,
+ "Resource limits have grown. Add new entries to rlimit_param[].");
+
+static const char *
+humanize_rlimit(int indx, rlim_t limit)
+{
+ static char buf[14];
+ int scale;
+
+ if (limit == RLIM_INFINITY)
+ return ("infinity ");
+
+ scale = humanize_number(buf, sizeof(buf) - 1, (int64_t)limit,
+ rlimit_param[indx].suffix, HN_AUTOSCALE | HN_GETSCALE, HN_DECIMAL);
+ (void)humanize_number(buf, sizeof(buf) - 1, (int64_t)limit,
+ rlimit_param[indx].suffix, HN_AUTOSCALE, HN_DECIMAL);
+ /* Pad with one space if there is no suffix prefix. */
+ if (scale == 0)
+ sprintf(buf + strlen(buf), " ");
+ return (buf);
+}
+
+void
+procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp)
+{
+ struct rlimit rlimit;
+ int i;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ xo_emit("{T:/%5s %-16s %-16s %16s %16s}\n",
+ "PID", "COMM", "RLIMIT", "SOFT ", "HARD ");
+ }
+ xo_emit("{ek:process_id/%5d}{e:command/%-16s/%s}", kipp->ki_pid,
+ kipp->ki_comm);
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ if (procstat_getrlimit(prstat, kipp, i, &rlimit) == -1)
+ return;
+ xo_emit("{dk:process_id/%5d} {d:command/%-16s} "
+ "{d:rlimit_param/%-16s} ", kipp->ki_pid, kipp->ki_comm,
+ rlimit_param[i].name);
+
+ xo_open_container(rlimit_param[i].name);
+ if (rlimit.rlim_cur == RLIM_INFINITY)
+ xo_emit("{e:soft_limit/infinity}");
+ else
+ xo_emit("{e:soft_limit/%U}", rlimit.rlim_cur);
+
+ if (rlimit.rlim_max == RLIM_INFINITY)
+ xo_emit("{e:hard_limit/infinity}");
+ else
+ xo_emit("{e:hard_limit/%U}", rlimit.rlim_max);
+ xo_close_container(rlimit_param[i].name);
+
+ xo_emit("{d:rlim_cur/%16s} ",
+ humanize_rlimit(i, rlimit.rlim_cur));
+ xo_emit("{d:rlim_max/%16s}\n",
+ humanize_rlimit(i, rlimit.rlim_max));
+ }
+}
diff --git a/usr.bin/procstat/procstat_rlimitusage.c b/usr.bin/procstat/procstat_rlimitusage.c
new file mode 100644
index 000000000000..f589edd23b02
--- /dev/null
+++ b/usr.bin/procstat/procstat_rlimitusage.c
@@ -0,0 +1,76 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#define _RLIMIT_IDENT
+#include <sys/resource.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libutil.h>
+
+#include "procstat.h"
+
+static const char ru[] = "resource_usage";
+
+void
+procstat_rlimitusage(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ rlim_t *resuse;
+ unsigned int cnt, i;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%7s %12s %4s %18s}\n",
+ "PID", "RESOURCE", "ID", "USAGE");
+
+ xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+
+ resuse = procstat_getrlimitusage(procstat, kipp, &cnt);
+ if (resuse == NULL)
+ return;
+ xo_open_list(ru);
+ for (i = 0; i < cnt; i++) {
+ xo_open_instance(ru);
+ xo_emit("{dk:process_id/%7d} ", kipp->ki_pid);
+ xo_emit("{:resource/%12s} ", i < nitems(rlimit_ident) ?
+ rlimit_ident[i] : "unknown");
+ xo_emit("{:resid/%4d} ", i);
+ xo_emit("{:usage/%18jd}\n", (intmax_t)resuse[i]);
+ xo_close_instance(ru);
+ }
+ xo_close_list(ru);
+ procstat_freerlimitusage(procstat, resuse);
+}
diff --git a/usr.bin/procstat/procstat_rusage.c b/usr.bin/procstat/procstat_rusage.c
new file mode 100644
index 000000000000..1960828fd1f5
--- /dev/null
+++ b/usr.bin/procstat/procstat_rusage.c
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2012 Hudson River Trading LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <libprocstat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libutil.h>
+
+#include "procstat.h"
+
+static struct {
+ const char *ri_name;
+ bool ri_humanize;
+ int ri_scale;
+} rusage_info[] = {
+ { "maximum RSS", true, 1 },
+ { "integral shared memory", true, 1 },
+ { "integral unshared data", true, 1 },
+ { "integral unshared stack", true, 1 },
+ { "page reclaims", false, 0 },
+ { "page faults", false, 0 },
+ { "swaps", false, 0 },
+ { "block reads", false, 0 },
+ { "block writes", false, 0 },
+ { "messages sent", false, 0 },
+ { "messages received", false, 0 },
+ { "signals received", false, 0 },
+ { "voluntary context switches", false, 0 },
+ { "involuntary context switches", false, 0 }
+};
+
+/* xxx days hh:mm:ss.uuuuuu */
+static const char *
+format_time(struct timeval *tv)
+{
+ static char buffer[32];
+ int days, hours, minutes, seconds, used;
+
+ minutes = tv->tv_sec / 60;
+ seconds = tv->tv_sec % 60;
+ hours = minutes / 60;
+ minutes %= 60;
+ days = hours / 24;
+ hours %= 24;
+ used = 0;
+ if (days == 1)
+ used += snprintf(buffer, sizeof(buffer), "1 day ");
+ else if (days > 0)
+ used += snprintf(buffer, sizeof(buffer), "%u days ", days);
+
+ snprintf(buffer + used, sizeof(buffer) - used, "%02u:%02u:%02u.%06u",
+ hours, minutes, seconds, (unsigned int)tv->tv_usec);
+ return (buffer);
+}
+
+static const char *
+format_value(long value, bool humanize, int scale)
+{
+ static char buffer[14];
+
+ if (scale != 0)
+ value <<= scale * 10;
+ if (humanize)
+ humanize_number(buffer, sizeof(buffer), value, "B",
+ scale, HN_DECIMAL);
+ else
+ snprintf(buffer, sizeof(buffer), "%ld ", value);
+ return (buffer);
+}
+
+static void
+print_prefix(struct kinfo_proc *kipp)
+{
+
+ xo_emit("{d:process_id/%5d/%d} ", kipp->ki_pid);
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0)
+ xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
+ xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
+}
+
+static void
+print_rusage(struct kinfo_proc *kipp)
+{
+ long *lp;
+ unsigned int i;
+ char *field, *threadid;
+
+ print_prefix(kipp);
+ xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "user time",
+ format_time(&kipp->ki_rusage.ru_utime));
+ print_prefix(kipp);
+ xo_emit("{d:resource/%-14s} {d:usage/%29s}{P: }\n", "system time",
+ format_time(&kipp->ki_rusage.ru_stime));
+
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
+ asprintf(&threadid, "%d", kipp->ki_tid);
+ if (threadid == NULL)
+ xo_errc(1, ENOMEM,
+ "Failed to allocate memory in print_rusage()");
+ xo_open_container(threadid);
+ xo_emit("{e:thread_id/%d}", kipp->ki_tid);
+ } else {
+ xo_emit("{e:process_id/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%s}", kipp->ki_comm);
+ }
+ xo_emit("{e:user time/%s}", format_time(&kipp->ki_rusage.ru_utime));
+ xo_emit("{e:system time/%s}", format_time(&kipp->ki_rusage.ru_stime));
+
+ lp = &kipp->ki_rusage.ru_maxrss;
+ for (i = 0; i < nitems(rusage_info); i++) {
+ print_prefix(kipp);
+ asprintf(&field, "{e:%s/%%D}", rusage_info[i].ri_name);
+ if (field == NULL)
+ xo_errc(1, ENOMEM,
+ "Failed to allocate memory in print_rusage()");
+ xo_emit(field, *lp);
+ free(field);
+ xo_emit("{d:resource/%-32s} {d:usage/%14s}\n",
+ rusage_info[i].ri_name,
+ format_value(*lp, rusage_info[i].ri_humanize,
+ rusage_info[i].ri_scale));
+ lp++;
+ }
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0) {
+ xo_close_container(threadid);
+ free(threadid);
+ }
+}
+
+void
+procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_proc *kip;
+ unsigned int count, i;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0) {
+ xo_emit("{d:ta/%5s} ", "PID");
+ if ((procstat_opts & PS_OPT_PERTHREAD) != 0)
+ xo_emit("{d:tb/%6s} ", "TID");
+ xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE",
+ "VALUE ");
+ }
+
+ if ((procstat_opts & PS_OPT_PERTHREAD) == 0) {
+ print_rusage(kipp);
+ return;
+ }
+
+ xo_emit("{e:process_id/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%s}", kipp->ki_comm);
+ xo_open_container("threads");
+
+ kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ kipp->ki_pid, &count);
+ if (kip == NULL)
+ return;
+ kinfo_proc_sort(kip, count);
+ for (i = 0; i < count; i++) {
+ print_rusage(&kip[i]);
+ }
+
+ xo_close_container("threads");
+ procstat_freeprocs(procstat, kip);
+}
diff --git a/usr.bin/procstat/procstat_sigs.c b/usr.bin/procstat/procstat_sigs.c
new file mode 100644
index 000000000000..7bea16739b75
--- /dev/null
+++ b/usr.bin/procstat/procstat_sigs.c
@@ -0,0 +1,244 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2010 Konstantin Belousov
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libprocstat.h>
+
+#include "procstat.h"
+
+static void
+procstat_print_signame(int sig)
+{
+ char name[12];
+ int i;
+
+ if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
+ strlcpy(name, sys_signame[sig], sizeof(name));
+ for (i = 0; name[i] != 0; i++)
+ name[i] = toupper(name[i]);
+ xo_emit("{d:signal/%-7s/%s} ", name);
+ xo_open_container(name);
+ } else {
+ xo_emit("{d:signal/%-7d/%d} ", sig);
+ snprintf(name, 12, "%d", sig);
+ xo_open_container(name);
+ }
+}
+
+static void
+procstat_close_signame(int sig)
+{
+ char name[12];
+ int i;
+
+ if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
+ strlcpy(name, sys_signame[sig], sizeof(name));
+ for (i = 0; name[i] != 0; i++)
+ name[i] = toupper(name[i]);
+ xo_close_container(name);
+ } else {
+ snprintf(name, 12, "%d", sig);
+ xo_close_container(name);
+ }
+}
+
+static void
+procstat_print_sig(const sigset_t *set, int sig, char flag)
+{
+ xo_emit("{d:sigmember/%c}", sigismember(set, sig) ? flag : '-');
+ switch (flag) {
+ case 'B':
+ xo_emit("{en:mask/%s}", sigismember(set, sig) ?
+ "true" : "false");
+ break;
+ case 'C':
+ xo_emit("{en:catch/%s}", sigismember(set, sig) ?
+ "true" : "false");
+ break;
+ case 'P':
+ xo_emit("{en:list/%s}", sigismember(set, sig) ?
+ "true" : "false");
+ break;
+ case 'I':
+ xo_emit("{en:ignore/%s}", sigismember(set, sig) ?
+ "true" : "false");
+ break;
+ default:
+ xo_emit("{en:unknown/%s}", sigismember(set, sig) ?
+ "true" : "false");
+ break;
+ }
+}
+
+void
+procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
+{
+ int j;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
+ "FLAGS");
+
+ xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+ xo_open_container("signals");
+ for (j = 1; j <= _SIG_MAXSIG; j++) {
+ xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
+ procstat_print_signame(j);
+ xo_emit(" ");
+ procstat_print_sig(&kipp->ki_siglist, j, 'P');
+ procstat_print_sig(&kipp->ki_sigignore, j, 'I');
+ procstat_print_sig(&kipp->ki_sigcatch, j, 'C');
+ procstat_close_signame(j);
+ xo_emit("\n");
+ }
+ xo_close_container("signals");
+}
+
+void
+procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_proc *kip;
+ int j;
+ unsigned int count, i;
+ char *threadid;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
+ "SIG", "FLAGS");
+
+ kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ kipp->ki_pid, &count);
+ if (kip == NULL)
+ return;
+ xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+ xo_open_container("threads");
+ kinfo_proc_sort(kip, count);
+ for (i = 0; i < count; i++) {
+ kipp = &kip[i];
+ asprintf(&threadid, "%d", kipp->ki_tid);
+ if (threadid == NULL)
+ xo_errc(1, ENOMEM, "Failed to allocate memory in "
+ "procstat_threads_sigs()");
+ xo_open_container(threadid);
+ xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid);
+ xo_open_container("signals");
+
+ for (j = 1; j <= _SIG_MAXSIG; j++) {
+ xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
+ xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
+ procstat_print_signame(j);
+ xo_emit(" ");
+ procstat_print_sig(&kipp->ki_siglist, j, 'P');
+ procstat_print_sig(&kipp->ki_sigmask, j, 'B');
+ procstat_close_signame(j);
+ xo_emit("\n");
+ }
+ xo_close_container("signals");
+ xo_close_container(threadid);
+ free(threadid);
+ }
+ xo_close_container("threads");
+ procstat_freeprocs(procstat, kip);
+}
+
+void
+procstat_sigfastblock(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_proc *kip;
+ char *threadid;
+ uintptr_t sigfastblk_addr;
+ int error, name[4];
+ unsigned int count, i;
+ size_t len;
+ bool has_sigfastblk_addr;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %6s %-16s %-16s}\n", "PID", "TID",
+ "COMM", "SIGFBLK");
+
+ kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ kipp->ki_pid, &count);
+ if (kip == NULL)
+ return;
+ xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
+ xo_open_container("threads");
+ kinfo_proc_sort(kip, count);
+ for (i = 0; i < count; i++) {
+ kipp = &kip[i];
+ len = sizeof(sigfastblk_addr);
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_SIGFASTBLK;
+ name[3] = kipp->ki_tid;
+ error = sysctl(name, 4, &sigfastblk_addr, &len, NULL, 0);
+ if (error < 0) {
+ if (errno != ESRCH && errno != ENOTTY) {
+ warn("sysctl: kern.proc.fastsigblk: %d",
+ kipp->ki_tid);
+ }
+ has_sigfastblk_addr = false;
+ } else
+ has_sigfastblk_addr = true;
+
+ asprintf(&threadid, "%d", kipp->ki_tid);
+ if (threadid == NULL)
+ xo_errc(1, ENOMEM, "Failed to allocate memory in "
+ "procstat_sigfastblock()");
+ xo_open_container(threadid);
+ xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
+ xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
+ xo_emit("{e:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ?
+ (uintmax_t)sigfastblk_addr : (uintmax_t)-1);
+ xo_emit("{d:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ?
+ (uintmax_t)sigfastblk_addr : (uintmax_t)-1);
+ xo_emit("\n");
+ xo_close_container(threadid);
+ free(threadid);
+ }
+ xo_close_container("threads");
+ procstat_freeprocs(procstat, kip);
+}
diff --git a/usr.bin/procstat/procstat_threads.c b/usr.bin/procstat/procstat_threads.c
new file mode 100644
index 000000000000..cebdc25e215c
--- /dev/null
+++ b/usr.bin/procstat/procstat_threads.c
@@ -0,0 +1,133 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_proc *kip;
+ unsigned int count, i;
+ const char *str;
+ char *threadid;
+
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s %-9s}\n", "PID",
+ "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN");
+
+ xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+ xo_emit("{e:command/%s}", strlen(kipp->ki_comm) ?
+ kipp->ki_comm : "-");
+ xo_open_container("threads");
+
+ kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
+ kipp->ki_pid, &count);
+ if (kip == NULL)
+ return;
+ kinfo_proc_sort(kip, count);
+ for (i = 0; i < count; i++) {
+ kipp = &kip[i];
+ asprintf(&threadid, "%d", kipp->ki_tid);
+ if (threadid == NULL)
+ xo_errc(1, ENOMEM, "Failed to allocate memory in "
+ "procstat_threads()");
+ xo_open_container(threadid);
+ xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
+ xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid);
+ xo_emit("{d:command/%-19s/%s} ", strlen(kipp->ki_comm) ?
+ kipp->ki_comm : "-");
+ xo_emit("{:thread_name/%-19s/%s} ",
+ kinfo_proc_thread_name(kipp));
+ if (kipp->ki_oncpu != 255)
+ xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu);
+ else if (kipp->ki_lastcpu != 255)
+ xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu);
+ else
+ xo_emit("{:cpu/%3s/%s} ", "-");
+ xo_emit("{:priority/%4d/%d} ", kipp->ki_pri.pri_level);
+ switch (kipp->ki_stat) {
+ case SRUN:
+ str = "run";
+ break;
+
+ case SSTOP:
+ str = "stop";
+ break;
+
+ case SSLEEP:
+ str = "sleep";
+ break;
+
+ case SLOCK:
+ str = "lock";
+ break;
+
+ case SWAIT:
+ str = "wait";
+ break;
+
+ case SZOMB:
+ str = "zomb";
+ break;
+
+ case SIDL:
+ str = "idle";
+ break;
+
+ default:
+ str = "??";
+ break;
+ }
+ xo_emit("{:run_state/%-7s/%s} ", str);
+ if (kipp->ki_kiflag & KI_LOCKBLOCK) {
+ xo_emit("{:lock_name/*%-8s/%s} ",
+ strlen(kipp->ki_lockname) ?
+ kipp->ki_lockname : "-");
+ } else {
+ xo_emit("{:wait_channel/%-9s/%s} ",
+ strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-");
+ }
+ xo_close_container(threadid);
+ free(threadid);
+ xo_emit("\n");
+ }
+ xo_close_container("threads");
+ procstat_freeprocs(procstat, kip);
+}
diff --git a/usr.bin/procstat/procstat_vm.c b/usr.bin/procstat/procstat_vm.c
new file mode 100644
index 000000000000..78c1e70971d7
--- /dev/null
+++ b/usr.bin/procstat/procstat_vm.c
@@ -0,0 +1,180 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libutil.h>
+
+#include "procstat.h"
+
+void
+procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
+{
+ struct kinfo_vmentry *freep, *kve;
+ int ptrwidth;
+ int i, cnt;
+ const char *str, *lstr;
+
+ ptrwidth = 2*sizeof(void *) + 2;
+ if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+ xo_emit("{T:/%5s %*s %*s %3s %4s %4s %3s %3s %-5s %-2s %-s}\n",
+ "PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
+ "PRES", "REF", "SHD", "FLAG", "TP", "PATH");
+
+ xo_emit("{ek:process_id/%d}", kipp->ki_pid);
+
+ freep = procstat_getvmmap(procstat, kipp, &cnt);
+ if (freep == NULL)
+ return;
+ xo_open_list("vm");
+ for (i = 0; i < cnt; i++) {
+ xo_open_instance("vm");
+ kve = &freep[i];
+ xo_emit("{dk:process_id/%5d} ", kipp->ki_pid);
+ xo_emit("{d:kve_start/%#*jx} ", ptrwidth,
+ (uintmax_t)kve->kve_start);
+ xo_emit("{d:kve_end/%#*jx} ", ptrwidth,
+ (uintmax_t)kve->kve_end);
+ xo_emit("{e:kve_start/%#jx}", (uintmax_t)kve->kve_start);
+ xo_emit("{e:kve_end/%#jx}", (uintmax_t)kve->kve_end);
+ xo_emit("{d:read/%s}", kve->kve_protection & KVME_PROT_READ ?
+ "r" : "-");
+ xo_emit("{d:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
+ "w" : "-");
+ xo_emit("{d:exec/%s} ", kve->kve_protection & KVME_PROT_EXEC ?
+ "x" : "-");
+ xo_open_container("kve_protection");
+ xo_emit("{en:read/%s}", kve->kve_protection & KVME_PROT_READ ?
+ "true" : "false");
+ xo_emit("{en:write/%s}", kve->kve_protection & KVME_PROT_WRITE ?
+ "true" : "false");
+ xo_emit("{en:exec/%s}", kve->kve_protection & KVME_PROT_EXEC ?
+ "true" : "false");
+ xo_close_container("kve_protection");
+ xo_emit("{:kve_resident/%4d/%d} ", kve->kve_resident);
+ xo_emit("{:kve_private_resident/%4d/%d} ",
+ kve->kve_private_resident);
+ xo_emit("{:kve_ref_count/%3d/%d} ", kve->kve_ref_count);
+ xo_emit("{:kve_shadow_count/%3d/%d} ", kve->kve_shadow_count);
+ xo_emit("{d:copy_on_write/%-1s}", kve->kve_flags &
+ KVME_FLAG_COW ? "C" : "-");
+ xo_emit("{d:need_copy/%-1s}", kve->kve_flags &
+ KVME_FLAG_NEEDS_COPY ? "N" : "-");
+ xo_emit("{d:super_pages/%-1s}", kve->kve_flags &
+ KVME_FLAG_SUPER ? "S" : "-");
+ xo_emit("{d:grows_down/%-1s}", kve->kve_flags &
+ KVME_FLAG_GROWS_UP ? "U" : kve->kve_flags &
+ KVME_FLAG_GROWS_DOWN ? "D" : "-");
+ xo_emit("{d:wired/%-1s} ", kve->kve_flags &
+ KVME_FLAG_USER_WIRED ? "W" : "-");
+ xo_open_container("kve_flags");
+ xo_emit("{en:copy_on_write/%s}", kve->kve_flags &
+ KVME_FLAG_COW ? "true" : "false");
+ xo_emit("{en:needs_copy/%s}", kve->kve_flags &
+ KVME_FLAG_NEEDS_COPY ? "true" : "false");
+ xo_emit("{en:super_pages/%s}", kve->kve_flags &
+ KVME_FLAG_SUPER ? "true" : "false");
+ xo_emit("{en:grows_up/%s}", kve->kve_flags &
+ KVME_FLAG_GROWS_UP ? "true" : "false");
+ xo_emit("{en:grows_down/%s}", kve->kve_flags &
+ KVME_FLAG_GROWS_DOWN ? "true" : "false");
+ xo_emit("{en:wired/%s}", kve->kve_flags &
+ KVME_FLAG_USER_WIRED ? "true" : "false");
+ xo_emit("{en:sysvshm/%s}", kve->kve_flags &
+ KVME_FLAG_SYSVSHM ? "true" : "false");
+ xo_close_container("kve_flags");
+ switch (kve->kve_type) {
+ case KVME_TYPE_NONE:
+ str = "--";
+ lstr = "none";
+ break;
+ case KVME_TYPE_DEFAULT:
+ str = "df";
+ lstr = "default";
+ break;
+ case KVME_TYPE_VNODE:
+ str = "vn";
+ lstr = "vnode";
+ break;
+ case KVME_TYPE_SWAP:
+ str = "sw";
+ lstr = "swap";
+ break;
+ case KVME_TYPE_DEVICE:
+ str = "dv";
+ lstr = "device";
+ break;
+ case KVME_TYPE_PHYS:
+ str = "ph";
+ lstr = "physical";
+ break;
+ case KVME_TYPE_DEAD:
+ str = "dd";
+ lstr = "dead";
+ break;
+ case KVME_TYPE_SG:
+ str = "sg";
+ lstr = "scatter/gather";
+ break;
+ case KVME_TYPE_MGTDEVICE:
+ str = "md";
+ lstr = "managed_device";
+ break;
+ case KVME_TYPE_GUARD:
+ str = "gd";
+ lstr = "guard";
+ break;
+ case KVME_TYPE_UNKNOWN:
+ default:
+ str = "??";
+ lstr = "unknown";
+ break;
+ }
+ xo_emit("{d:kve_type/%-2s} ", str);
+ xo_emit("{e:kve_type/%s}", lstr);
+ if ((kve->kve_flags & KVME_FLAG_SYSVSHM) != 0)
+ xo_emit(" {:sysvipc:/sysvshm(%ju:%u)/%ju:%u}",
+ (uintmax_t)kve->kve_vn_fileid,
+ kve->kve_vn_fsid_freebsd11);
+ if ((kve->kve_flags & KVME_FLAG_POSIXSHM) != 0)
+ xo_emit(" {:posixshm:/posixshm@/posixshm}");
+ xo_emit("{:kve_path/%-s/%s}\n", kve->kve_path);
+ xo_close_instance("vm");
+ }
+ xo_close_list("vm");
+ free(freep);
+}
diff --git a/usr.bin/procstat/tests/Makefile b/usr.bin/procstat/tests/Makefile
new file mode 100644
index 000000000000..9309bf30128c
--- /dev/null
+++ b/usr.bin/procstat/tests/Makefile
@@ -0,0 +1,7 @@
+ATF_TESTS_SH+= procstat_test
+
+PROGS+= while1
+
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/procstat/tests/Makefile.depend b/usr.bin/procstat/tests/Makefile.depend
new file mode 100644
index 000000000000..d80b3a4991d1
--- /dev/null
+++ b/usr.bin/procstat/tests/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/procstat/tests/procstat_test.sh b/usr.bin/procstat/tests/procstat_test.sh
new file mode 100755
index 000000000000..0f7be704676b
--- /dev/null
+++ b/usr.bin/procstat/tests/procstat_test.sh
@@ -0,0 +1,162 @@
+#
+# Copyright (c) 2017 Enji Cooper <ngie@FreeBSD.org>
+#
+# 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.
+#
+#
+
+PROG_PID=
+PROG_PATH=$(atf_get_srcdir)/while1
+
+SP='[[:space:]]'
+
+start_program()
+{
+ echo "Starting program in background"
+ PROG_COMM=while1
+ PROG_PATH=$(atf_get_srcdir)/$PROG_COMM
+
+ mkfifo wait_for_start || atf_fail "mkfifo"
+ $PROG_PATH $* >wait_for_start &
+ PROG_PID=$!
+ if ! read dummy <wait_for_start; then
+ atf_fail "Program did not start properly"
+ fi
+ rm wait_for_start
+}
+
+atf_test_case binary_info
+binary_info_head()
+{
+ atf_set "descr" "Checks -b support"
+}
+binary_info_body()
+{
+ start_program bogus-arg
+
+ line_format="$SP*%s$SP+%s$SP+%s$SP+%s$SP*"
+ header_re=$(printf "$line_format" "PID" "COMM" "OSREL" "PATH")
+ line_re=$(printf "$line_format" $PROG_PID $PROG_COMM "[[:digit:]]+" "$PROG_PATH")
+
+ atf_check -o save:procstat.out procstat binary $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+
+ atf_check -o save:procstat.out procstat -b $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+}
+
+atf_test_case command_line_arguments
+command_line_arguments_head()
+{
+ atf_set "descr" "Checks -c support"
+}
+command_line_arguments_body()
+{
+ arguments="my arguments"
+
+ start_program $arguments
+
+ line_format="$SP*%s$SP+%s$SP+%s$SP*"
+ header_re=$(printf "$line_format" "PID" "COMM" "ARGS")
+ line_re=$(printf "$line_format" $PROG_PID "$PROG_COMM" "$PROG_PATH $arguments")
+
+ atf_check -o save:procstat.out procstat arguments $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+
+ atf_check -o save:procstat.out procstat -c $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+}
+
+atf_test_case environment
+environment_head()
+{
+ atf_set "descr" "Checks -e support"
+}
+environment_body()
+{
+ var="MY_VARIABLE=foo"
+ eval "export $var"
+
+ start_program my arguments
+
+ line_format="$SP*%s$SP+%s$SP+%s$SP*"
+ header_re=$(printf "$line_format" "PID" "COMM" "ENVIRONMENT")
+ line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".*$var.*")
+
+ atf_check -o save:procstat.out procstat environment $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+
+ atf_check -o save:procstat.out procstat -e $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" tail -n 1 procstat.out
+}
+
+atf_test_case file_descriptor
+file_descriptor_head()
+{
+ atf_set "descr" "Checks -f support"
+}
+file_descriptor_body()
+{
+ start_program my arguments
+
+ line_format="$SP*%s$SP+%s$SP+%s$SP+%s$SP+%s$SP+%s$SP+%s$SP+%s$SP+%s$SP%s$SP*"
+ header_re=$(printf "$line_format" "PID" "COMM" "FD" "T" "V" "FLAGS" "REF" "OFFSET" "PRO" "NAME")
+ # XXX: write a more sensible feature test
+ line_re=$(printf "$line_format" $PROG_PID $PROG_COMM ".+" ".+" ".+" ".+" ".+" ".+" ".+" ".+")
+
+ atf_check -o save:procstat.out procstat files $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" awk 'NR > 1' procstat.out
+
+ atf_check -o save:procstat.out procstat -f $PROG_PID
+ atf_check -o match:"$header_re" head -n 1 procstat.out
+ atf_check -o match:"$line_re" awk 'NR > 1' procstat.out
+}
+
+atf_test_case kernel_stacks
+kernel_stacks_head()
+{
+ atf_set "descr" "Captures kernel stacks for all visible threads"
+}
+kernel_stacks_body()
+{
+ atf_check -o save:procstat.out procstat -a kstack
+ atf_check -o not-empty awk '{if ($3 == "procstat") print}' procstat.out
+
+ atf_check -o save:procstat.out procstat -kka
+ atf_check -o not-empty awk '{if ($3 == "procstat") print}' procstat.out
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case binary_info
+ atf_add_test_case command_line_arguments
+ atf_add_test_case environment
+ atf_add_test_case file_descriptor
+ atf_add_test_case kernel_stacks
+}
diff --git a/usr.bin/procstat/tests/while1.c b/usr.bin/procstat/tests/while1.c
new file mode 100644
index 000000000000..c81e8193e072
--- /dev/null
+++ b/usr.bin/procstat/tests/while1.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Enji Cooper <ngie@FreeBSD.org>
+ *
+ * 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 <sys/cdefs.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+
+ if (write(STDOUT_FILENO, "started\n", 8) != 8)
+ abort();
+ for (;;)
+ pause();
+}
diff --git a/usr.bin/protect/Makefile b/usr.bin/protect/Makefile
new file mode 100644
index 000000000000..bb7f2fbe7ec2
--- /dev/null
+++ b/usr.bin/protect/Makefile
@@ -0,0 +1,3 @@
+PROG= protect
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/protect/Makefile.depend b/usr.bin/protect/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/protect/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/protect/protect.1 b/usr.bin/protect/protect.1
new file mode 100644
index 000000000000..d518d73dba4d
--- /dev/null
+++ b/usr.bin/protect/protect.1
@@ -0,0 +1,137 @@
+.\" Copyright (c) 2013 Hudson River Trading LLC
+.\" Written by: John H. Baldwin <jhb@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 July 12, 2022
+.Dt PROTECT 1
+.Os
+.Sh NAME
+.Nm protect
+.Nd "protect processes from being killed when swap space is exhausted"
+.Sh SYNOPSIS
+.Nm
+.Op Fl i
+.Ar command
+.Nm
+.Op Fl cdi
+.Fl g Ar pgrp
+.Nm
+.Op Fl cdi
+.Fl p Ar pid
+.Sh DESCRIPTION
+The
+.Nm
+command is used to mark processes as protected.
+The kernel does not kill protected processes when swap space is exhausted.
+Note that this protected state is not inherited by child processes by default.
+.Pp
+The options are:
+.Bl -tag -width command
+.It Fl c
+Remove protection from the specified processes.
+.It Fl d
+Apply the operation to all current children of the specified processes.
+.It Fl i
+Apply the operation to all future children of the specified processes.
+.It Fl g Ar pgrp
+Apply the operation to all processes in the specified process group.
+.It Fl p Ar pid
+Apply the operation to the specified process.
+.It Ar command
+Execute
+.Ar command
+as a protected process.
+.El
+.Pp
+Note that only one of the
+.Fl p
+or
+.Fl g
+flags may be specified when adjusting the state of existing processes.
+.Pp
+Daemons can be protected on startup using
+.Ao Ar name Ac Ns Va _oomprotect
+option from
+.Xr rc.conf 5 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Mark the Xorg server as protected:
+.Pp
+.Dl "pgrep Xorg | xargs protect -p"
+.Pp
+Protect all ssh sessions and their child processes:
+.Pp
+.Dl "pgrep sshd | xargs protect -dip"
+.Pp
+Remove protection from all current and future processes:
+.Pp
+.Dl "protect -cdi -p 1"
+.Pp
+Using
+.Xr ps 1
+to check if the protect flag has been applied to the process:
+.Pp
+.Dl "ps -O flags,flags2 -p 64430"
+.Pp
+.Dl " PID F F2 TT STAT TIME COMMAND"
+.Dl "64430 10104002 00000001 5 S+ 0:00.00 ./main"
+.Dl " ^P ^PI"
+.Pp
+In the above example
+.Nm P
+points at the protected flag and
+.Nm PI
+points at the inheritance flag.
+The process is protected if
+.Nm P
+bit is set to 1.
+All children of this process will also be protected if
+.Nm PI
+bit is set to 1.
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "protect: procctl: Operation not permitted"
+The
+.Nm
+command does not have the required permissions to protect selected processes.
+There are many reasons why this could be the case, e.g.:
+.Bl -dash
+.It
+.Nm
+is not executed by root.
+.It
+.Nm
+is executed inside a
+.Xr jail 8 ,
+which is not supported at the moment.
+.El
+.El
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr procctl 2 ,
+.Xr rc.conf 5
+.Sh BUGS
+If you protect a runaway process that allocates all memory the system will
+deadlock.
diff --git a/usr.bin/protect/protect.c b/usr.bin/protect/protect.c
new file mode 100644
index 000000000000..12c5c53083b1
--- /dev/null
+++ b/usr.bin/protect/protect.c
@@ -0,0 +1,122 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2013 Hudson River Trading LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/procctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: protect [-i] command\n");
+ fprintf(stderr, " protect [-cdi] -g pgrp | -p pid\n");
+ exit(1);
+}
+
+static id_t
+parse_id(char *id)
+{
+ static bool first = true;
+ long value;
+ char *ch;
+
+ if (!first) {
+ warnx("only one -g or -p flag is permitted");
+ usage();
+ }
+ value = strtol(id, &ch, 0);
+ if (*ch != '\0') {
+ warnx("invalid process id");
+ usage();
+ }
+ return (value);
+}
+
+int
+main(int argc, char *argv[])
+{
+ idtype_t idtype;
+ id_t id;
+ int ch, flags;
+ bool descend, inherit, idset;
+
+ idtype = P_PID;
+ id = getpid();
+ flags = PPROT_SET;
+ descend = inherit = idset = false;
+ while ((ch = getopt(argc, argv, "cdig:p:")) != -1)
+ switch (ch) {
+ case 'c':
+ flags = PPROT_CLEAR;
+ break;
+ case 'd':
+ descend = true;
+ break;
+ case 'i':
+ inherit = true;
+ break;
+ case 'g':
+ idtype = P_PGID;
+ id = parse_id(optarg);
+ idset = true;
+ break;
+ case 'p':
+ idtype = P_PID;
+ id = parse_id(optarg);
+ idset = true;
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((idset && argc != 0) || (!idset && (argc == 0 || descend)))
+ usage();
+
+ if (descend)
+ flags |= PPROT_DESCEND;
+ if (inherit)
+ flags |= PPROT_INHERIT;
+ if (procctl(idtype, id, PROC_SPROTECT, &flags) == -1)
+ err(1, "procctl");
+
+ if (argc != 0) {
+ errno = 0;
+ execvp(*argv, argv);
+ err(errno == ENOENT ? 127 : 126, "%s", *argv);
+ }
+ return (0);
+}
diff --git a/usr.bin/quota/Makefile b/usr.bin/quota/Makefile
new file mode 100644
index 000000000000..3b7a6227bc86
--- /dev/null
+++ b/usr.bin/quota/Makefile
@@ -0,0 +1,7 @@
+PROG= quota
+BINOWN= root
+BINMODE=4555
+
+LIBADD= rpcsvc util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/quota/Makefile.depend b/usr.bin/quota/Makefile.depend
new file mode 100644
index 000000000000..b7d3124c4b7a
--- /dev/null
+++ b/usr.bin/quota/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/librpcsvc \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/quota/quota.1 b/usr.bin/quota/quota.1
new file mode 100644
index 000000000000..a31186561ee3
--- /dev/null
+++ b/usr.bin/quota/quota.1
@@ -0,0 +1,173 @@
+.\" Copyright (c) 1983, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Elz at The University of Melbourne.
+.\"
+.\" 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.
+.\"
+.Dd February 3, 2007
+.Dt QUOTA 1
+.Os
+.Sh NAME
+.Nm quota
+.Nd display disk usage and limits
+.Sh SYNOPSIS
+.Nm
+.Op Fl ghlu
+.Op Fl f Ar path
+.Op Fl v | q | r
+.Nm
+.Op Fl hlu
+.Op Fl f Ar path
+.Op Fl v | q | r
+.Ar user ...
+.Nm
+.Fl g
+.Op Fl hl
+.Op Fl f Ar path
+.Op Fl v | q | r
+.Ar group ...
+.Sh DESCRIPTION
+The
+.Nm
+utility displays users' disk usage and limits.
+By default only the user quotas are printed.
+Disk block usage and limits are shown in 1024-byte blocks.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl f Ar path
+Only display quota information for the file system
+that contains the specified path.
+This can be any file within a mounted file system.
+.It Fl g
+Print group quotas for the group
+of which the user is a member.
+.It Fl h
+"Human-readable" output.
+Use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte and Petabyte.
+.It Fl l
+Do not report quotas on
+.Tn NFS
+file systems.
+.It Fl q
+Print a more terse message,
+containing only information
+on file systems where usage is over quota.
+The
+.Fl q
+flag takes precedence over the
+.Fl v
+flag.
+.It Fl r
+Display the raw quota information as it appears in the quota structure.
+Non-zero time values will also be displayed in
+.Xr ctime 3
+format.
+This option implies
+.Fl v
+and will override the
+.Fl q
+flag.
+.It Fl u
+Print the user quotas.
+This is the default unless
+.Fl g
+is specified.
+.It Fl v
+Display quotas on file systems
+where no storage is allocated.
+.El
+.Pp
+Specifying both
+.Fl g
+and
+.Fl u
+displays both the user quotas and the group quotas (for
+the user).
+.Pp
+Only the super-user may use the
+.Fl u
+flag and the optional
+.Ar user
+argument to view the limits of other users.
+Non-super-users can use the
+.Fl g
+flag and optional
+.Ar group
+argument to view only the limits of groups of which they are members.
+.Pp
+The
+.Nm
+utility tries to report the quotas of all mounted file systems.
+If the file system is mounted via
+.Tn NFS ,
+it will attempt to contact the
+.Xr rpc.rquotad 8
+daemon on the
+.Tn NFS
+server.
+For
+.Tn UFS
+file systems, quotas must be turned on in
+.Pa /etc/fstab .
+If
+.Nm
+exits with a non-zero status, one or more file systems
+are over quota or the path specified with the
+.Fl f
+option does not exist.
+.Pp
+If the
+.Fl l
+flag is specified,
+.Nm
+will not check
+.Tn NFS
+file systems.
+.Sh FILES
+.Bl -tag -width quota.group -compact
+.It Pa quota.user
+located at the file system root with user quotas
+.It Pa quota.group
+located at the file system root with group quotas
+.It Pa /etc/fstab
+to find file system names and locations
+.El
+.Sh SEE ALSO
+.Xr quotactl 2 ,
+.Xr ctime 3 ,
+.Xr fstab 5 ,
+.Xr edquota 8 ,
+.Xr quotacheck 8 ,
+.Xr quotaon 8 ,
+.Xr repquota 8 ,
+.Xr rpc.rquotad 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.bin/quota/quota.c b/usr.bin/quota/quota.c
new file mode 100644
index 000000000000..b5d28fd7c184
--- /dev/null
+++ b/usr.bin/quota/quota.c
@@ -0,0 +1,687 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Elz at The University of Melbourne.
+ *
+ * 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.
+ */
+
+/*
+ * Disk quota reporting program.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpcsvc/rquota.h>
+
+#include <ufs/ufs/quota.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fstab.h>
+#include <grp.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static const char *qfextension[] = INITQFNAMES;
+
+struct quotause {
+ struct quotause *next;
+ long flags;
+ struct dqblk dqblk;
+ char fsname[MAXPATHLEN + 1];
+};
+
+static char *timeprt(int64_t seconds);
+static struct quotause *getprivs(long id, int quotatype);
+static void usage(void) __dead2;
+static int showuid(u_long uid);
+static int showgid(u_long gid);
+static int showusrname(char *name);
+static int showgrpname(char *name);
+static int showquotas(int type, u_long id, const char *name);
+static void showrawquotas(int type, u_long id, struct quotause *qup);
+static void heading(int type, u_long id, const char *name, const char *tag);
+static int getufsquota(struct fstab *fs, struct quotause *qup, long id,
+ int quotatype);
+static int getnfsquota(struct statfs *fst, struct quotause *qup, long id,
+ int quotatype);
+static enum clnt_stat callaurpc(char *host, int prognum, int versnum, int procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
+static int alldigits(char *s);
+
+static int hflag;
+static int lflag;
+static int rflag;
+static int qflag;
+static int vflag;
+static char *filename = NULL;
+
+int
+main(int argc, char *argv[])
+{
+ int ngroups;
+ gid_t mygid, gidset[NGROUPS];
+ int i, ch, gflag = 0, uflag = 0, errflag = 0;
+
+ while ((ch = getopt(argc, argv, "f:ghlrquv")) != -1) {
+ switch(ch) {
+ case 'f':
+ filename = optarg;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'h':
+ hflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'q':
+ qflag++;
+ break;
+ case 'r':
+ rflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (!uflag && !gflag)
+ uflag++;
+ if (argc == 0) {
+ if (uflag)
+ errflag += showuid(getuid());
+ if (gflag) {
+ mygid = getgid();
+ ngroups = getgroups(NGROUPS, gidset);
+ if (ngroups < 0)
+ err(1, "getgroups");
+ errflag += showgid(mygid);
+ for (i = 0; i < ngroups; i++)
+ if (gidset[i] != mygid)
+ errflag += showgid(gidset[i]);
+ }
+ return(errflag);
+ }
+ if (uflag && gflag)
+ usage();
+ if (uflag) {
+ for (; argc > 0; argc--, argv++) {
+ if (alldigits(*argv))
+ errflag += showuid(atoi(*argv));
+ else
+ errflag += showusrname(*argv);
+ }
+ return(errflag);
+ }
+ if (gflag) {
+ for (; argc > 0; argc--, argv++) {
+ if (alldigits(*argv))
+ errflag += showgid(atoi(*argv));
+ else
+ errflag += showgrpname(*argv);
+ }
+ }
+ return(errflag);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "%s\n%s\n%s\n",
+ "usage: quota [-ghlu] [-f path] [-v | -q | -r]",
+ " quota [-hlu] [-f path] [-v | -q | -r] user ...",
+ " quota -g [-hl] [-f path] [-v | -q | -r] group ...");
+ exit(1);
+}
+
+/*
+ * Print out quotas for a specified user identifier.
+ */
+static int
+showuid(u_long uid)
+{
+ struct passwd *pwd = getpwuid(uid);
+ const char *name;
+
+ if (pwd == NULL)
+ name = "(no account)";
+ else
+ name = pwd->pw_name;
+ return(showquotas(USRQUOTA, uid, name));
+}
+
+/*
+ * Print out quotas for a specified user name.
+ */
+static int
+showusrname(char *name)
+{
+ struct passwd *pwd = getpwnam(name);
+
+ if (pwd == NULL) {
+ warnx("%s: unknown user", name);
+ return(1);
+ }
+ return(showquotas(USRQUOTA, pwd->pw_uid, name));
+}
+
+/*
+ * Print out quotas for a specified group identifier.
+ */
+static int
+showgid(u_long gid)
+{
+ struct group *grp = getgrgid(gid);
+ const char *name;
+
+ if (grp == NULL)
+ name = "(no entry)";
+ else
+ name = grp->gr_name;
+ return(showquotas(GRPQUOTA, gid, name));
+}
+
+/*
+ * Print out quotas for a specified group name.
+ */
+static int
+showgrpname(char *name)
+{
+ struct group *grp = getgrnam(name);
+
+ if (grp == NULL) {
+ warnx("%s: unknown group", name);
+ return(1);
+ }
+ return(showquotas(GRPQUOTA, grp->gr_gid, name));
+}
+
+static void
+prthumanval(int len, u_int64_t bytes)
+{
+ char buf[len + 1];
+
+ /*
+ * Limit the width to 5 bytes as that is what users expect.
+ */
+ humanize_number(buf, MIN(sizeof(buf), 5), bytes, "",
+ HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+
+ (void)printf(" %*s", len, buf);
+}
+
+static int
+showquotas(int type, u_long id, const char *name)
+{
+ struct quotause *qup;
+ struct quotause *quplist;
+ const char *msgi, *msgb;
+ const char *nam;
+ char *bgrace = NULL, *igrace = NULL;
+ int lines = 0, overquota = 0;
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ quplist = getprivs(id, type);
+ for (qup = quplist; qup; qup = qup->next) {
+ msgi = NULL;
+ if (qup->dqblk.dqb_ihardlimit &&
+ qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit) {
+ overquota++;
+ msgi = "File limit reached on";
+ }
+ else if (qup->dqblk.dqb_isoftlimit &&
+ qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit) {
+ overquota++;
+ if (qup->dqblk.dqb_itime > now)
+ msgi = "In file grace period on";
+ else
+ msgi = "Over file quota on";
+ }
+ msgb = NULL;
+ if (qup->dqblk.dqb_bhardlimit &&
+ qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit) {
+ overquota++;
+ msgb = "Block limit reached on";
+ }
+ else if (qup->dqblk.dqb_bsoftlimit &&
+ qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit) {
+ overquota++;
+ if (qup->dqblk.dqb_btime > now)
+ msgb = "In block grace period on";
+ else
+ msgb = "Over block quota on";
+ }
+ if (rflag) {
+ showrawquotas(type, id, qup);
+ continue;
+ }
+ if (!vflag &&
+ qup->dqblk.dqb_isoftlimit == 0 &&
+ qup->dqblk.dqb_ihardlimit == 0 &&
+ qup->dqblk.dqb_bsoftlimit == 0 &&
+ qup->dqblk.dqb_bhardlimit == 0)
+ continue;
+ if (qflag) {
+ if ((msgi != NULL || msgb != NULL) &&
+ lines++ == 0)
+ heading(type, id, name, "");
+ if (msgi != NULL)
+ printf("\t%s %s\n", msgi, qup->fsname);
+ if (msgb != NULL)
+ printf("\t%s %s\n", msgb, qup->fsname);
+ continue;
+ }
+ if (!vflag &&
+ qup->dqblk.dqb_curblocks == 0 &&
+ qup->dqblk.dqb_curinodes == 0)
+ continue;
+ if (lines++ == 0)
+ heading(type, id, name, "");
+ nam = qup->fsname;
+ if (strlen(qup->fsname) > 15) {
+ printf("%s\n", qup->fsname);
+ nam = "";
+ }
+ printf("%-15s", nam);
+ if (hflag) {
+ prthumanval(7, dbtob(qup->dqblk.dqb_curblocks));
+ printf("%c", (msgb == NULL) ? ' ' : '*');
+ prthumanval(7, dbtob(qup->dqblk.dqb_bsoftlimit));
+ prthumanval(7, dbtob(qup->dqblk.dqb_bhardlimit));
+ } else {
+ printf(" %7ju%c %7ju %7ju",
+ (uintmax_t)dbtob(qup->dqblk.dqb_curblocks)
+ / 1024,
+ (msgb == NULL) ? ' ' : '*',
+ (uintmax_t)dbtob(qup->dqblk.dqb_bsoftlimit)
+ / 1024,
+ (uintmax_t)dbtob(qup->dqblk.dqb_bhardlimit)
+ / 1024);
+ }
+ if (msgb != NULL)
+ bgrace = timeprt(qup->dqblk.dqb_btime);
+ if (msgi != NULL)
+ igrace = timeprt(qup->dqblk.dqb_itime);
+ printf("%8s %6ju%c %6ju %6ju%8s\n"
+ , (msgb == NULL) ? "" : bgrace
+ , (uintmax_t)qup->dqblk.dqb_curinodes
+ , (msgi == NULL) ? ' ' : '*'
+ , (uintmax_t)qup->dqblk.dqb_isoftlimit
+ , (uintmax_t)qup->dqblk.dqb_ihardlimit
+ , (msgi == NULL) ? "" : igrace
+ );
+ if (msgb != NULL)
+ free(bgrace);
+ if (msgi != NULL)
+ free(igrace);
+ }
+ if (!qflag && !rflag && lines == 0)
+ heading(type, id, name, "none");
+ return (overquota);
+}
+
+static void
+showrawquotas(int type, u_long id, struct quotause *qup)
+{
+ time_t t;
+
+ printf("Raw %s quota information for id %lu on %s\n",
+ type == USRQUOTA ? "user" : "group", id, qup->fsname);
+ printf("block hard limit: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_bhardlimit);
+ printf("block soft limit: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_bsoftlimit);
+ printf("current block count: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_curblocks);
+ printf("i-node hard limit: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_ihardlimit);
+ printf("i-node soft limit: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_isoftlimit);
+ printf("current i-node count: %ju\n",
+ (uintmax_t)qup->dqblk.dqb_curinodes);
+ printf("block grace time: %jd",
+ (intmax_t)qup->dqblk.dqb_btime);
+ if (qup->dqblk.dqb_btime != 0) {
+ t = qup->dqblk.dqb_btime;
+ printf(" %s", ctime(&t));
+ } else {
+ printf("\n");
+ }
+ printf("i-node grace time: %jd", (intmax_t)qup->dqblk.dqb_itime);
+ if (qup->dqblk.dqb_itime != 0) {
+ t = qup->dqblk.dqb_itime;
+ printf(" %s", ctime(&t));
+ } else {
+ printf("\n");
+ }
+}
+
+
+static void
+heading(int type, u_long id, const char *name, const char *tag)
+{
+
+ printf("Disk quotas for %s %s (%cid %lu): %s\n", qfextension[type],
+ name, *qfextension[type], id, tag);
+ if (!qflag && tag[0] == '\0') {
+ printf("%-15s %7s %8s %7s %7s %6s %7s %6s%8s\n"
+ , "Filesystem"
+ , "usage"
+ , "quota"
+ , "limit"
+ , "grace"
+ , "files"
+ , "quota"
+ , "limit"
+ , "grace"
+ );
+ }
+}
+
+/*
+ * Calculate the grace period and return a printable string for it.
+ */
+static char *
+timeprt(int64_t seconds)
+{
+ time_t hours, minutes;
+ char *buf;
+ static time_t now;
+
+ if (now == 0)
+ time(&now);
+ if (now > seconds) {
+ if ((buf = strdup("none")) == NULL)
+ errx(1, "strdup() failed in timeprt()");
+ return (buf);
+ }
+ seconds -= now;
+ minutes = (seconds + 30) / 60;
+ hours = (minutes + 30) / 60;
+ if (hours >= 36) {
+ if (asprintf(&buf, "%lddays", ((long)hours + 12) / 24) < 0)
+ errx(1, "asprintf() failed in timeprt(1)");
+ return (buf);
+ }
+ if (minutes >= 60) {
+ if (asprintf(&buf, "%2ld:%ld", (long)minutes / 60,
+ (long)minutes % 60) < 0)
+ errx(1, "asprintf() failed in timeprt(2)");
+ return (buf);
+ }
+ if (asprintf(&buf, "%2ld", (long)minutes) < 0)
+ errx(1, "asprintf() failed in timeprt(3)");
+ return (buf);
+}
+
+/*
+ * Collect the requested quota information.
+ */
+static struct quotause *
+getprivs(long id, int quotatype)
+{
+ struct quotause *qup, *quptail = NULL;
+ struct fstab *fs;
+ struct quotause *quphead;
+ struct statfs *fst;
+ int nfst, i;
+ struct statfs sfb;
+
+ qup = quphead = (struct quotause *)0;
+
+ if (filename != NULL && statfs(filename, &sfb) != 0)
+ err(1, "cannot statfs %s", filename);
+ nfst = getmntinfo(&fst, MNT_NOWAIT);
+ if (nfst == 0)
+ errx(2, "no filesystems mounted!");
+ setfsent();
+ for (i = 0; i < nfst; i++) {
+ if (qup == NULL) {
+ if ((qup = (struct quotause *)malloc(sizeof *qup))
+ == NULL)
+ errx(2, "out of memory");
+ }
+ /*
+ * See if the user requested a specific file system
+ * or specified a file inside a mounted file system.
+ */
+ if (filename != NULL &&
+ strcmp(sfb.f_mntonname, fst[i].f_mntonname) != 0)
+ continue;
+ if (strcmp(fst[i].f_fstypename, "nfs") == 0) {
+ if (lflag)
+ continue;
+ if (getnfsquota(&fst[i], qup, id, quotatype) == 0)
+ continue;
+ } else if (strcmp(fst[i].f_fstypename, "ufs") == 0) {
+ /*
+ * XXX
+ * UFS filesystems must be in /etc/fstab, and must
+ * indicate that they have quotas on (?!) This is quite
+ * unlike SunOS where quotas can be enabled/disabled
+ * on a filesystem independent of /etc/fstab, and it
+ * will still print quotas for them.
+ */
+ if ((fs = getfsspec(fst[i].f_mntfromname)) == NULL)
+ continue;
+ if (getufsquota(fs, qup, id, quotatype) == 0)
+ continue;
+ } else
+ continue;
+ strcpy(qup->fsname, fst[i].f_mntonname);
+ if (quphead == NULL)
+ quphead = qup;
+ else
+ quptail->next = qup;
+ quptail = qup;
+ quptail->next = 0;
+ qup = NULL;
+ }
+ if (qup)
+ free(qup);
+ endfsent();
+ return (quphead);
+}
+
+/*
+ * Check to see if a particular quota is available.
+ */
+static int
+getufsquota(struct fstab *fs, struct quotause *qup, long id, int quotatype)
+{
+ struct quotafile *qf;
+
+ if ((qf = quota_open(fs, quotatype, O_RDONLY)) == NULL)
+ return (0);
+ if (quota_read(qf, &qup->dqblk, id) != 0)
+ return (0);
+ quota_close(qf);
+ return (1);
+}
+
+static int
+getnfsquota(struct statfs *fst, struct quotause *qup, long id, int quotatype)
+{
+ struct ext_getquota_args gq_args;
+ struct getquota_args old_gq_args;
+ struct getquota_rslt gq_rslt;
+ struct dqblk *dqp = &qup->dqblk;
+ struct timeval tv;
+ char *cp, host[NI_MAXHOST];
+ enum clnt_stat call_stat;
+
+ if (fst->f_flags & MNT_LOCAL)
+ return (0);
+
+ /*
+ * must be some form of "hostname:/path"
+ */
+ cp = fst->f_mntfromname;
+ do {
+ cp = strrchr(cp, ':');
+ } while (cp != NULL && *(cp + 1) != '/');
+ if (cp == NULL) {
+ warnx("cannot find hostname for %s", fst->f_mntfromname);
+ return (0);
+ }
+ memset(host, 0, sizeof(host));
+ memcpy(host, fst->f_mntfromname, cp - fst->f_mntfromname);
+ host[sizeof(host) - 1] = '\0';
+
+ /* Avoid attempting the RPC for special amd(8) filesystems. */
+ if (strncmp(fst->f_mntfromname, "pid", 3) == 0 &&
+ strchr(fst->f_mntfromname, '@') != NULL)
+ return (0);
+
+ gq_args.gqa_pathp = cp + 1;
+ gq_args.gqa_id = id;
+ gq_args.gqa_type = quotatype;
+
+ call_stat = callaurpc(host, RQUOTAPROG, EXT_RQUOTAVERS,
+ RQUOTAPROC_GETQUOTA, (xdrproc_t)xdr_ext_getquota_args, (char *)&gq_args,
+ (xdrproc_t)xdr_getquota_rslt, (char *)&gq_rslt);
+ if (call_stat == RPC_PROGVERSMISMATCH || call_stat == RPC_PROGNOTREGISTERED) {
+ if (quotatype == USRQUOTA) {
+ old_gq_args.gqa_pathp = cp + 1;
+ old_gq_args.gqa_uid = id;
+ call_stat = callaurpc(host, RQUOTAPROG, RQUOTAVERS,
+ RQUOTAPROC_GETQUOTA, (xdrproc_t)xdr_getquota_args, (char *)&old_gq_args,
+ (xdrproc_t)xdr_getquota_rslt, (char *)&gq_rslt);
+ } else {
+ /* Old rpc quota does not support group type */
+ return (0);
+ }
+ }
+ if (call_stat != 0)
+ return (call_stat);
+
+ switch (gq_rslt.status) {
+ case Q_NOQUOTA:
+ break;
+ case Q_EPERM:
+ warnx("quota permission error, host: %s",
+ fst->f_mntfromname);
+ break;
+ case Q_OK:
+ gettimeofday(&tv, NULL);
+ /* blocks*/
+ dqp->dqb_bhardlimit =
+ ((uint64_t)gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit *
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize) / DEV_BSIZE;
+ dqp->dqb_bsoftlimit =
+ ((uint64_t)gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit *
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize) / DEV_BSIZE;
+ dqp->dqb_curblocks =
+ ((uint64_t)gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks *
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize) / DEV_BSIZE;
+ /* inodes */
+ dqp->dqb_ihardlimit =
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit;
+ dqp->dqb_isoftlimit =
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit;
+ dqp->dqb_curinodes =
+ gq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles;
+ /* grace times */
+ dqp->dqb_btime =
+ tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft;
+ dqp->dqb_itime =
+ tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft;
+ return (1);
+ default:
+ warnx("bad rpc result, host: %s", fst->f_mntfromname);
+ break;
+ }
+
+ return (0);
+}
+
+static enum clnt_stat
+callaurpc(char *host, int prognum, int versnum, int procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
+{
+ enum clnt_stat clnt_stat;
+ struct timeval timeout, tottimeout;
+
+ CLIENT *client = NULL;
+
+ client = clnt_create(host, prognum, versnum, "udp");
+ if (client == NULL)
+ return ((int)rpc_createerr.cf_stat);
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 6;
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
+
+ client->cl_auth = authunix_create_default();
+ tottimeout.tv_sec = 25;
+ tottimeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, procnum, inproc, in,
+ outproc, out, tottimeout);
+ return (clnt_stat);
+}
+
+static int
+alldigits(char *s)
+{
+ int c;
+
+ c = *s++;
+ do {
+ if (!isdigit(c))
+ return (0);
+ } while ((c = *s++));
+ return (1);
+}
diff --git a/usr.bin/random/Makefile b/usr.bin/random/Makefile
new file mode 100644
index 000000000000..8d0fc2be6f09
--- /dev/null
+++ b/usr.bin/random/Makefile
@@ -0,0 +1,5 @@
+PROG= random
+MAN= random.6
+SRCS= random.c randomize_fd.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/random/Makefile.depend b/usr.bin/random/Makefile.depend
new file mode 100644
index 000000000000..84b8ddd67e34
--- /dev/null
+++ b/usr.bin/random/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/random/random.6 b/usr.bin/random/random.6
new file mode 100644
index 000000000000..3cbcfa1e6085
--- /dev/null
+++ b/usr.bin/random/random.6
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1994
+.\" 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.
+.\"
+.Dd February 15, 2020
+.Dt RANDOM 6
+.Os
+.Sh NAME
+.Nm random
+.Nd random lines from a file or random numbers
+.Sh SYNOPSIS
+.Nm
+.Op Fl elrUuw
+.Op Fl f Ar filename
+.Op Ar denominator
+.Sh DESCRIPTION
+.Nm Random
+has two distinct modes of operations.
+The default is to read lines from standard input and write them to standard
+output with a probability of 1.0 /
+.Ar denominator .
+.Ar ( denominator
+is a real number greater than or equal to 1.0.)
+The default
+.Ar denominator
+for this mode of operation is 2.0, giving each line a 50% chance of
+being displayed.
+.Pp
+The second mode of operation, selected with the
+.Fl f Ar filename
+option, reads the specified file and outputs the randomized contents to
+standard output.
+The contents can be randomized in units of lines (split on newline characters)
+or in units of words (split on space characters as determined by
+.Xr isspace 3 . )
+The default
+.Ar denominator
+for this mode of operation is 1.0, which displays every line.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl e
+If the
+.Fl e
+option is specified,
+.Nm
+does not read or write anything, and simply exits with a random
+exit value of 0 to
+.Ar denominator
+\&- 1, inclusive.
+In this mode,
+.Ar denominator
+must be less than or equal to 256.
+.It Fl f Ar filename
+The
+.Fl f
+option is used to specify the
+.Ar filename
+to read from.
+Standard input is used if
+.Ar filename
+is
+.Sq - .
+.It Fl l
+Randomize the input via newlines (the default).
+.It Fl r
+Do not buffer output.
+.It Fl U
+Reuse any given line or word when creating a randomized output.
+.It Fl u
+Do not select the same line or word from a file more than once (the default).
+This does not guarantee uniqueness if there are two of the
+same tokens in the input.
+.It Fl w
+Randomize words separated by
+.Xr isspace 3
+instead of newlines.
+.El
+.Sh SEE ALSO
+.Xr fortune 6
+.Sh HISTORY
+The
+functionality to randomizing lines and words was added in 2003 by
+.An Sean Chittenden Aq Mt seanc@FreeBSD.org .
+.Sh BUGS
+This tool is a remnant of the "games" collection formerly part of
+.Fx
+base.
+It probably should have been removed to ports with the rest of that collection.
+It does not have a coherent purpose and the motivation for it to be a core base
+utility is nonobvious.
+.Pp
+No index is used when printing out tokens from the list which
+makes it rather slow for large files (10MB+).
diff --git a/usr.bin/random/random.c b/usr.bin/random/random.c
new file mode 100644
index 000000000000..3c45da0b92ac
--- /dev/null
+++ b/usr.bin/random/random.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guy Harris at Network Appliance Corp.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "randomize_fd.h"
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ double denom;
+ int ch, fd, random_exit, randomize_lines, random_type, ret,
+ unique_output, unbuffer_output;
+ bool selected;
+ char *ep;
+ const char *filename;
+
+ denom = 0.;
+ filename = "/dev/fd/0";
+ random_type = RANDOM_TYPE_UNSET;
+ random_exit = randomize_lines = unbuffer_output = 0;
+ unique_output = 1;
+
+ (void)setlocale(LC_CTYPE, "");
+
+ while ((ch = getopt(argc, argv, "ef:hlruUw")) != -1)
+ switch (ch) {
+ case 'e':
+ random_exit = 1;
+ break;
+ case 'f':
+ randomize_lines = 1;
+ if (strcmp(optarg, "-") != 0)
+ filename = optarg;
+ break;
+ case 'l':
+ randomize_lines = 1;
+ random_type = RANDOM_TYPE_LINES;
+ break;
+ case 'r':
+ unbuffer_output = 1;
+ break;
+ case 'u':
+ randomize_lines = 1;
+ unique_output = 1;
+ break;
+ case 'U':
+ randomize_lines = 1;
+ unique_output = 0;
+ break;
+ case 'w':
+ randomize_lines = 1;
+ random_type = RANDOM_TYPE_WORDS;
+ break;
+ default:
+ case '?':
+ usage();
+ /* NOTREACHED */
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 0:
+ denom = (randomize_lines ? 1. : 2.);
+ break;
+ case 1:
+ errno = 0;
+ denom = strtod(*argv, &ep);
+ if (errno == ERANGE)
+ err(1, "%s", *argv);
+ if (denom < 1. || *ep != '\0')
+ errx(1, "denominator is not valid.");
+ if (random_exit && denom > 256.)
+ errx(1, "denominator must be <= 256 for random exit.");
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ /*
+ * Act as a filter, randomly choosing lines of the standard input
+ * to write to the standard output.
+ */
+ if (unbuffer_output)
+ setbuf(stdout, NULL);
+
+ /*
+ * Act as a filter, randomizing lines read in from a given file
+ * descriptor and write the output to standard output.
+ */
+ if (randomize_lines) {
+ if ((fd = open(filename, O_RDONLY, 0)) < 0)
+ err(1, "%s", filename);
+ ret = randomize_fd(fd, random_type, unique_output, denom);
+ if (!random_exit)
+ return(ret);
+ }
+
+ /* Compute a random exit status between 0 and denom - 1. */
+ if (random_exit)
+ return (arc4random_uniform(denom));
+
+ /*
+ * Filter stdin, selecting lines with probability 1/denom, one
+ * character at a time.
+ */
+ do {
+ selected = random_uniform_denom(denom);
+ if (selected) {
+ while ((ch = getchar()) != EOF) {
+ putchar(ch);
+ if (ch == '\n')
+ break;
+ }
+ } else {
+ while ((ch = getchar()) != EOF)
+ if (ch == '\n')
+ break;
+ }
+ if (ferror(stdout))
+ err(2, "stdout");
+ } while (ch != EOF);
+ if (ferror(stdin))
+ err(2, "stdin");
+ exit (0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: random [-elrUuw] [-f filename] [denominator]\n");
+ exit(1);
+}
diff --git a/usr.bin/random/randomize_fd.c b/usr.bin/random/randomize_fd.c
new file mode 100644
index 000000000000..0c505aa1f9f6
--- /dev/null
+++ b/usr.bin/random/randomize_fd.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2003 Sean Chittenden <seanc@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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/param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "randomize_fd.h"
+
+static struct rand_node *rand_root;
+static struct rand_node *rand_tail;
+
+static struct rand_node *
+rand_node_allocate(void)
+{
+ struct rand_node *n;
+
+ n = (struct rand_node *)malloc(sizeof(struct rand_node));
+ if (n == NULL)
+ err(1, "malloc");
+
+ n->len = 0;
+ n->cp = NULL;
+ n->next = NULL;
+ return(n);
+}
+
+static void
+rand_node_free(struct rand_node *n)
+{
+ if (n != NULL) {
+ if (n->cp != NULL)
+ free(n->cp);
+
+ free(n);
+ }
+}
+
+static void
+rand_node_free_rec(struct rand_node *n)
+{
+ if (n != NULL) {
+ if (n->next != NULL)
+ rand_node_free_rec(n->next);
+
+ rand_node_free(n);
+ }
+}
+
+static void
+rand_node_append(struct rand_node *n)
+{
+ if (rand_root == NULL)
+ rand_root = rand_tail = n;
+ else {
+ rand_tail->next = n;
+ rand_tail = n;
+ }
+}
+
+int
+randomize_fd(int fd, int type, int unique, double denom)
+{
+ u_char *buf;
+ u_int slen;
+ u_long i, j, numnode, selected;
+ struct rand_node *n, *prev;
+ int bufleft, eof, fndstr, ret;
+ size_t bufc, buflen;
+ ssize_t len;
+
+ rand_root = rand_tail = NULL;
+ bufc = i = 0;
+ bufleft = eof = fndstr = numnode = 0;
+
+ if (type == RANDOM_TYPE_UNSET)
+ type = RANDOM_TYPE_LINES;
+
+ buflen = sizeof(u_char) * MAXBSIZE;
+ buf = (u_char *)malloc(buflen);
+ if (buf == NULL)
+ err(1, "malloc");
+
+ while (!eof) {
+ /* Check to see if we have bits in the buffer */
+ if (bufleft == 0) {
+ len = read(fd, buf, buflen);
+ if (len == -1)
+ err(1, "read");
+ else if (len == 0) {
+ eof++;
+ break;
+ } else if ((size_t)len < buflen)
+ buflen = (size_t)len;
+
+ bufleft = (int)len;
+ }
+
+ /* Look for a newline */
+ for (i = bufc; i <= buflen && bufleft >= 0; i++, bufleft--) {
+ if (i == buflen) {
+ if (fndstr) {
+ if (!eof) {
+ memmove(buf, &buf[bufc], i - bufc);
+ i -= bufc;
+ bufc = 0;
+ len = read(fd, &buf[i], buflen - i);
+ if (len == -1)
+ err(1, "read");
+ else if (len == 0) {
+ eof++;
+ break;
+ } else if (len < (ssize_t)(buflen - i))
+ buflen = i + (size_t)len;
+
+ bufleft = (int)len;
+ fndstr = 0;
+ }
+ } else {
+ buflen *= 2;
+ buf = (u_char *)realloc(buf, buflen);
+ if (buf == NULL)
+ err(1, "realloc");
+
+ if (!eof) {
+ len = read(fd, &buf[i], buflen - i);
+ if (len == -1)
+ err(1, "read");
+ else if (len == 0) {
+ eof++;
+ break;
+ } else if (len < (ssize_t)(buflen - i))
+ buflen = i + (size_t)len;
+
+ bufleft = (int)len;
+ }
+
+ }
+ }
+
+ if ((type == RANDOM_TYPE_LINES && buf[i] == '\n') ||
+ (type == RANDOM_TYPE_WORDS && isspace(buf[i])) ||
+ (eof && i == buflen - 1)) {
+make_token:
+ if (numnode == UINT32_MAX - 1) {
+ errno = EFBIG;
+ err(1, "too many delimiters");
+ }
+ numnode++;
+ n = rand_node_allocate();
+ if (-1 != (int)i) {
+ slen = i - (u_long)bufc;
+ n->len = slen + 2;
+ n->cp = (u_char *)malloc(slen + 2);
+ if (n->cp == NULL)
+ err(1, "malloc");
+
+ memmove(n->cp, &buf[bufc], slen);
+ n->cp[slen] = buf[i];
+ n->cp[slen + 1] = '\0';
+ bufc = i + 1;
+ }
+ rand_node_append(n);
+ fndstr = 1;
+ }
+ }
+ }
+
+ /* Necessary evil to compensate for files that don't end with a newline */
+ if (bufc != i) {
+ i--;
+ goto make_token;
+ }
+
+ (void)close(fd);
+
+ free(buf);
+
+ for (i = numnode; i > 0; i--) {
+ selected = arc4random_uniform(numnode);
+
+ for (j = 0, prev = n = rand_root; n != NULL; j++, prev = n, n = n->next) {
+ if (j == selected) {
+ if (n->cp == NULL)
+ break;
+
+ if (random_uniform_denom(denom)) {
+ ret = printf("%.*s",
+ (int)n->len - 1, n->cp);
+ if (ret < 0)
+ err(1, "printf");
+ }
+ if (unique) {
+ if (n == rand_root)
+ rand_root = n->next;
+ if (n == rand_tail)
+ rand_tail = prev;
+
+ prev->next = n->next;
+ rand_node_free(n);
+ numnode--;
+ }
+ break;
+ }
+ }
+ }
+
+ fflush(stdout);
+
+ if (!unique)
+ rand_node_free_rec(rand_root);
+
+ return(0);
+}
diff --git a/usr.bin/random/randomize_fd.h b/usr.bin/random/randomize_fd.h
new file mode 100644
index 000000000000..937c0e15e16f
--- /dev/null
+++ b/usr.bin/random/randomize_fd.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2003 Sean Chittenden <seanc@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 __RANDOMIZE_FD__
+#define __RANDOMIZE_FD__
+
+#define RANDOM_TYPE_UNSET 0
+#define RANDOM_TYPE_LINES 1
+#define RANDOM_TYPE_WORDS 2
+
+/* The multiple instance single integer key */
+struct rand_node {
+ u_char *cp;
+ u_int len;
+ struct rand_node *next;
+};
+
+int randomize_fd(int fd, int type, int unique, double denom);
+
+/*
+ * Generates a random number uniformly in the range [0.0, 1.0).
+ */
+static inline double
+random_unit_float(void)
+{
+ static const uint64_t denom = (1ull << 53);
+ static const uint64_t mask = denom - 1;
+
+ uint64_t rand64;
+
+ /*
+ * arc4random_buf(...) in this use generates integer outputs in [0,
+ * UINT64_MAX].
+ *
+ * The double mantissa only has 53 bits, so we uniformly mask off the
+ * high 11 bits and then floating-point divide by 2^53 to achieve a
+ * result in [0, 1).
+ *
+ * We are not allowed to emit 1.0, so denom must be one greater than
+ * the possible range of the preceeding step.
+ */
+ arc4random_buf(&rand64, sizeof(rand64));
+ rand64 &= mask;
+ return ((double)rand64 / denom);
+}
+
+/*
+ * Returns true with probability 1 / denom (a floating point number >= 1).
+ * Otherwise, returns false.
+ */
+static inline bool
+random_uniform_denom(double denom)
+{
+ return ((uint64_t)(denom * random_unit_float()) == 0);
+}
+#endif
diff --git a/usr.bin/rctl/Makefile b/usr.bin/rctl/Makefile
new file mode 100644
index 000000000000..d98e5c1ad9b0
--- /dev/null
+++ b/usr.bin/rctl/Makefile
@@ -0,0 +1,6 @@
+PROG= rctl
+MAN= rctl.8
+
+LIBADD= util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rctl/Makefile.depend b/usr.bin/rctl/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/rctl/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rctl/rctl.8 b/usr.bin/rctl/rctl.8
new file mode 100644
index 000000000000..6f2e37851227
--- /dev/null
+++ b/usr.bin/rctl/rctl.8
@@ -0,0 +1,298 @@
+.\"-
+.\" Copyright (c) 2009 Edward Tomasz Napierala
+.\"
+.\" 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 AUTHOR 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 AUTHOR OR THE VOICES IN HIS HEAD 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 February 26, 2018
+.Dt RCTL 8
+.Os
+.Sh NAME
+.Nm rctl
+.Nd display and update resource limits database
+.Sh SYNOPSIS
+.Nm
+.Op Fl h
+.Op Fl n
+.Op Ar filter Ar ...
+.Nm
+.Fl a
+.Ar rule Ar ...
+.Nm
+.Fl l
+.Op Fl h
+.Op Fl n
+.Ar filter Ar ...
+.Nm
+.Fl r
+.Ar filter Ar ...
+.Nm
+.Fl u
+.Op Fl h
+.Ar filter Ar ...
+.Sh DESCRIPTION
+When called without options, the
+.Nm
+command writes currently defined RCTL rules to standard output.
+.Pp
+If a
+.Ar filter
+argument is specified, only rules matching the filter are displayed.
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a Ar rule
+Add
+.Ar rule
+to the RCTL database.
+.It Fl l Ar filter
+Display rules applicable to the process defined by
+.Ar filter .
+Note that this is different from showing the rules when called without
+any options, as it shows not just the rules with subject equal to that
+of process, but also rules for the user, jail, and login class applicable
+to the process.
+.It Fl r Ar filter
+Remove rules matching
+.Ar filter
+from the RCTL database.
+.It Fl u Ar filter
+Display resource utilization for a subject
+.Po
+.Sy process ,
+.Sy user ,
+.Sy loginclass
+or
+.Sy jail
+.Pc
+matching the
+.Ar filter .
+.It Fl h
+"Human-readable" output.
+Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte.
+.It Fl n
+Display user IDs numerically rather than converting them to a user name.
+.El
+.Pp
+Modifying rules affects all currently running and future processes matching
+the rule.
+.Sh RULE SYNTAX
+Syntax for a rule is subject:subject-id:resource:action=amount/per.
+.Pp
+.Bl -tag -width "subject-id" -compact -offset indent
+.It subject
+defines the kind of entity the rule applies to.
+It can be either
+.Sy process ,
+.Sy user ,
+.Sy loginclass ,
+or
+.Sy jail .
+.It subject-id
+identifies the
+.Em subject .
+It can be a process ID, user name, numerical user ID, login class name from
+.Xr login.conf 5 ,
+or jail name.
+.It resource
+identifies the resource the rule controls.
+See the
+.Sx RESOURCES
+section below for details.
+.It action
+defines what will happen when a process exceeds the allowed
+.Em amount .
+See the
+.Sx ACTIONS
+section below for details.
+.It amount
+defines how much of the resource a process can use before
+the defined
+.Em action
+triggers.
+Resources which limit bytes may use prefixes from
+.Xr expand_number 3 .
+.It per
+defines what entity the
+.Em amount
+gets accounted for.
+For example, rule "loginclass:users:vmemoryuse:deny=100M/process" means
+that each process of any user belonging to login class "users" may allocate
+up to 100MB of virtual memory.
+Rule "loginclass:users:vmemoryuse:deny=100M/user" would mean that for each
+user belonging to the login class "users", the sum of virtual memory allocated
+by all the processes of that user will not exceed 100MB.
+Rule "loginclass:users:vmemoryuse:deny=100M/loginclass" would mean that the sum of
+virtual memory allocated by all processes of all users belonging to that login
+class will not exceed 100MB.
+.El
+.Pp
+A valid rule has all those fields specified, except for
+.Em per ,
+which defaults
+to the value of
+.Em subject .
+.Pp
+A filter is a rule for which one of more fields other than
+.Em per
+is left empty.
+For example, a filter that matches every rule could be written as ":::=/",
+or, in short, ":".
+A filter that matches all the login classes would be "loginclass:".
+A filter that matches all defined rules for
+.Sy maxproc
+resource would be
+"::maxproc".
+.Sh SUBJECTS
+.Bl -column -offset 3n "pseudoterminals" ".Sy username or numerical User ID"
+.It Sy process Ta numerical Process ID
+.It Sy user Ta user name or numerical User ID
+.It Sy loginclass Ta login class from
+.Xr login.conf 5
+.It Sy jail Ta jail name
+.El
+.Sh RESOURCES
+.Bl -column -offset 3n "pseudoterminals"
+.It Sy cputime Ta "CPU time, in seconds"
+.It Sy datasize Ta "data size, in bytes"
+.It Sy stacksize Ta "stack size, in bytes"
+.It Sy coredumpsize Ta "core dump size, in bytes"
+.It Sy memoryuse Ta "resident set size, in bytes"
+.It Sy memorylocked Ta "locked memory, in bytes"
+.It Sy maxproc Ta "number of processes"
+.It Sy openfiles Ta "file descriptor table size"
+.It Sy vmemoryuse Ta "address space limit, in bytes"
+.It Sy pseudoterminals Ta "number of PTYs"
+.It Sy swapuse Ta "swap space that may be reserved or used, in bytes"
+.It Sy nthr Ta "number of threads"
+.It Sy msgqqueued Ta "number of queued SysV messages"
+.It Sy msgqsize Ta "SysV message queue size, in bytes"
+.It Sy nmsgq Ta "number of SysV message queues"
+.It Sy nsem Ta "number of SysV semaphores"
+.It Sy nsemop Ta "number of SysV semaphores modified in a single semop(2) call"
+.It Sy nshm Ta "number of SysV shared memory segments"
+.It Sy shmsize Ta "SysV shared memory size, in bytes"
+.It Sy wallclock Ta "wallclock time, in seconds"
+.It Sy pcpu Ta "%CPU, in percents of a single CPU core"
+.It Sy readbps Ta "filesystem reads, in bytes per second"
+.It Sy writebps Ta "filesystem writes, in bytes per second"
+.It Sy readiops Ta "filesystem reads, in operations per second"
+.It Sy writeiops Ta "filesystem writes, in operations per second"
+.El
+.Sh ACTIONS
+.Bl -column -offset 3n "pseudoterminals"
+.It Sy deny Ta deny the allocation; not supported for
+.Sy cputime ,
+.Sy wallclock ,
+.Sy readbps ,
+.Sy writebps ,
+.Sy readiops ,
+and
+.Sy writeiops
+.It Sy log Ta "log a warning to the console"
+.It Sy devctl Ta "send notification to"
+.Xr devd 8
+using
+.Sy system
+= "RCTL",
+.Sy subsystem
+= "rule",
+.Sy type
+= "matched"
+.It sig* e.g.
+.Sy sigterm ;
+send a signal to the offending process.
+See
+.Xr signal 3
+for a list of supported signals
+.It Sy throttle Ta "slow down process execution"; only supported for
+.Sy readbps ,
+.Sy writebps ,
+.Sy readiops ,
+and
+.Sy writeiops .
+.El
+.Pp
+Not all actions are supported for all resources.
+Attempting to add a rule with an action not supported by a given resource will
+result in error.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Prevent user "joe" from allocating more than 1GB of virtual memory:
+.Dl Nm Fl a Ar user:joe:vmemoryuse:deny=1g
+.Pp
+Remove all RCTL rules:
+.Dl Nm Fl r Ar \&:
+.Pp
+Display resource utilization information for jail named "www":
+.Dl Nm Fl hu Ar jail:www
+.Pp
+Display all the rules applicable to process with PID 512:
+.Dl Nm Fl l Ar process:512
+.Pp
+Display all rules:
+.Dl Nm
+.Pp
+Display all rules matching user "joe":
+.Dl Nm Ar user:joe
+.Pp
+Display all rules matching login classes:
+.Dl Nm Ar loginclass:
+.Sh SEE ALSO
+.Xr cpuset 1 ,
+.Xr rctl 4 ,
+.Xr rctl.conf 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+was developed by
+.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org
+under sponsorship from the FreeBSD Foundation.
+.Sh BUGS
+Limiting
+.Sy memoryuse
+may kill the machine due to thrashing.
+.Pp
+The
+.Sy readiops
+and
+.Sy writeiops
+counters are only approximations.
+Like
+.Sy readbps
+and
+.Sy writebps ,
+they are calculated in the filesystem layer, where it is difficult
+or even impossible to observe actual disk device operations.
+.Pp
+The
+.Sy writebps
+and
+.Sy writeiops
+resources generally account for writes to the filesystem cache,
+not to actual devices.
diff --git a/usr.bin/rctl/rctl.c b/usr.bin/rctl/rctl.c
new file mode 100644
index 000000000000..4227a866dc19
--- /dev/null
+++ b/usr.bin/rctl/rctl.c
@@ -0,0 +1,683 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2010 The FreeBSD Foundation
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/rctl.h>
+#include <sys/sysctl.h>
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <grp.h>
+#include <libutil.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define RCTL_DEFAULT_BUFSIZE 128 * 1024
+
+static int
+parse_user(const char *s, id_t *uidp, const char *unexpanded_rule)
+{
+ char *end;
+ struct passwd *pwd;
+
+ pwd = getpwnam(s);
+ if (pwd != NULL) {
+ *uidp = pwd->pw_uid;
+ return (0);
+ }
+
+ if (!isnumber(s[0])) {
+ warnx("malformed rule '%s': unknown user '%s'",
+ unexpanded_rule, s);
+ return (1);
+ }
+
+ *uidp = strtod(s, &end);
+ if ((size_t)(end - s) != strlen(s)) {
+ warnx("malformed rule '%s': trailing characters "
+ "after numerical id", unexpanded_rule);
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+parse_group(const char *s, id_t *gidp, const char *unexpanded_rule)
+{
+ char *end;
+ struct group *grp;
+
+ grp = getgrnam(s);
+ if (grp != NULL) {
+ *gidp = grp->gr_gid;
+ return (0);
+ }
+
+ if (!isnumber(s[0])) {
+ warnx("malformed rule '%s': unknown group '%s'",
+ unexpanded_rule, s);
+ return (1);
+ }
+
+ *gidp = strtod(s, &end);
+ if ((size_t)(end - s) != strlen(s)) {
+ warnx("malformed rule '%s': trailing characters "
+ "after numerical id", unexpanded_rule);
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Replace human-readable number with its expanded form.
+ */
+static char *
+expand_amount(const char *rule, const char *unexpanded_rule)
+{
+ uint64_t num;
+ const char *subject, *subject_id, *resource, *action, *amount, *per;
+ char *copy, *expanded, *tofree;
+ int ret;
+
+ tofree = copy = strdup(rule);
+ if (copy == NULL) {
+ warn("strdup");
+ return (NULL);
+ }
+
+ subject = strsep(&copy, ":");
+ subject_id = strsep(&copy, ":");
+ resource = strsep(&copy, ":");
+ action = strsep(&copy, "=/");
+ amount = strsep(&copy, "/");
+ per = copy;
+
+ if (amount == NULL || strlen(amount) == 0) {
+ /*
+ * The "copy" has already been tinkered with by strsep().
+ */
+ free(tofree);
+ copy = strdup(rule);
+ if (copy == NULL) {
+ warn("strdup");
+ return (NULL);
+ }
+ return (copy);
+ }
+
+ assert(subject != NULL);
+ assert(subject_id != NULL);
+ assert(resource != NULL);
+ assert(action != NULL);
+
+ if (expand_number(amount, &num)) {
+ warnx("malformed rule '%s': invalid numeric value '%s'",
+ unexpanded_rule, amount);
+ free(tofree);
+ return (NULL);
+ }
+
+ if (per == NULL) {
+ ret = asprintf(&expanded, "%s:%s:%s:%s=%ju",
+ subject, subject_id, resource, action, (uintmax_t)num);
+ } else {
+ ret = asprintf(&expanded, "%s:%s:%s:%s=%ju/%s",
+ subject, subject_id, resource, action, (uintmax_t)num, per);
+ }
+
+ if (ret <= 0) {
+ warn("asprintf");
+ free(tofree);
+ return (NULL);
+ }
+
+ free(tofree);
+
+ return (expanded);
+}
+
+static char *
+expand_rule(const char *rule, bool resolve_ids)
+{
+ id_t id;
+ const char *subject, *textid, *rest;
+ char *copy, *expanded, *resolved, *tofree;
+ int error, ret;
+
+ tofree = copy = strdup(rule);
+ if (copy == NULL) {
+ warn("strdup");
+ return (NULL);
+ }
+
+ subject = strsep(&copy, ":");
+ textid = strsep(&copy, ":");
+ if (textid == NULL) {
+ warnx("malformed rule '%s': missing subject", rule);
+ return (NULL);
+ }
+ if (copy != NULL)
+ rest = copy;
+ else
+ rest = "";
+
+ if (strcasecmp(subject, "u") == 0)
+ subject = "user";
+ else if (strcasecmp(subject, "g") == 0)
+ subject = "group";
+ else if (strcasecmp(subject, "p") == 0)
+ subject = "process";
+ else if (strcasecmp(subject, "l") == 0 ||
+ strcasecmp(subject, "c") == 0 ||
+ strcasecmp(subject, "class") == 0)
+ subject = "loginclass";
+ else if (strcasecmp(subject, "j") == 0)
+ subject = "jail";
+
+ if (resolve_ids &&
+ strcasecmp(subject, "user") == 0 && strlen(textid) > 0) {
+ error = parse_user(textid, &id, rule);
+ if (error != 0) {
+ free(tofree);
+ return (NULL);
+ }
+ ret = asprintf(&resolved, "%s:%d:%s", subject, (int)id, rest);
+ } else if (resolve_ids &&
+ strcasecmp(subject, "group") == 0 && strlen(textid) > 0) {
+ error = parse_group(textid, &id, rule);
+ if (error != 0) {
+ free(tofree);
+ return (NULL);
+ }
+ ret = asprintf(&resolved, "%s:%d:%s", subject, (int)id, rest);
+ } else {
+ ret = asprintf(&resolved, "%s:%s:%s", subject, textid, rest);
+ }
+
+ if (ret <= 0) {
+ warn("asprintf");
+ free(tofree);
+ return (NULL);
+ }
+
+ free(tofree);
+
+ expanded = expand_amount(resolved, rule);
+ free(resolved);
+
+ return (expanded);
+}
+
+static char *
+humanize_ids(char *rule)
+{
+ id_t id;
+ struct passwd *pwd;
+ struct group *grp;
+ const char *subject, *textid, *rest;
+ char *end, *humanized;
+ int ret;
+
+ subject = strsep(&rule, ":");
+ textid = strsep(&rule, ":");
+ if (textid == NULL)
+ errx(1, "rule passed from the kernel didn't contain subject");
+ if (rule != NULL)
+ rest = rule;
+ else
+ rest = "";
+
+ /* Replace numerical user and group ids with names. */
+ if (strcasecmp(subject, "user") == 0) {
+ id = strtod(textid, &end);
+ if ((size_t)(end - textid) != strlen(textid))
+ errx(1, "malformed uid '%s'", textid);
+ pwd = getpwuid(id);
+ if (pwd != NULL)
+ textid = pwd->pw_name;
+ } else if (strcasecmp(subject, "group") == 0) {
+ id = strtod(textid, &end);
+ if ((size_t)(end - textid) != strlen(textid))
+ errx(1, "malformed gid '%s'", textid);
+ grp = getgrgid(id);
+ if (grp != NULL)
+ textid = grp->gr_name;
+ }
+
+ ret = asprintf(&humanized, "%s:%s:%s", subject, textid, rest);
+ if (ret <= 0)
+ err(1, "asprintf");
+
+ return (humanized);
+}
+
+static int
+str2int64(const char *str, int64_t *value)
+{
+ char *end;
+
+ if (str == NULL)
+ return (EINVAL);
+
+ *value = strtoul(str, &end, 10);
+ if ((size_t)(end - str) != strlen(str))
+ return (EINVAL);
+
+ return (0);
+}
+
+static char *
+humanize_amount(char *rule)
+{
+ int64_t num;
+ const char *subject, *subject_id, *resource, *action, *amount, *per;
+ char *copy, *humanized, buf[6], *tofree;
+ int ret;
+
+ tofree = copy = strdup(rule);
+ if (copy == NULL)
+ err(1, "strdup");
+
+ subject = strsep(&copy, ":");
+ subject_id = strsep(&copy, ":");
+ resource = strsep(&copy, ":");
+ action = strsep(&copy, "=/");
+ amount = strsep(&copy, "/");
+ per = copy;
+
+ if (amount == NULL || strlen(amount) == 0 ||
+ str2int64(amount, &num) != 0) {
+ free(tofree);
+ return (rule);
+ }
+
+ assert(subject != NULL);
+ assert(subject_id != NULL);
+ assert(resource != NULL);
+ assert(action != NULL);
+
+ if (humanize_number(buf, sizeof(buf), num, "", HN_AUTOSCALE,
+ HN_DECIMAL | HN_NOSPACE) == -1)
+ err(1, "humanize_number");
+
+ if (per == NULL) {
+ ret = asprintf(&humanized, "%s:%s:%s:%s=%s",
+ subject, subject_id, resource, action, buf);
+ } else {
+ ret = asprintf(&humanized, "%s:%s:%s:%s=%s/%s",
+ subject, subject_id, resource, action, buf, per);
+ }
+
+ if (ret <= 0)
+ err(1, "asprintf");
+
+ free(tofree);
+ return (humanized);
+}
+
+/*
+ * Print rules, one per line.
+ */
+static void
+print_rules(char *rules, int hflag, int nflag)
+{
+ char *rule;
+
+ while ((rule = strsep(&rules, ",")) != NULL) {
+ if (rule[0] == '\0')
+ break; /* XXX */
+ if (nflag == 0)
+ rule = humanize_ids(rule);
+ if (hflag)
+ rule = humanize_amount(rule);
+ printf("%s\n", rule);
+ }
+}
+
+static void
+enosys(void)
+{
+ size_t racct_enable_len;
+ int error;
+ bool racct_enable;
+
+ racct_enable_len = sizeof(racct_enable);
+ error = sysctlbyname("kern.racct.enable",
+ &racct_enable, &racct_enable_len, NULL, 0);
+
+ if (error != 0) {
+ if (errno == ENOENT)
+ errx(1, "RACCT/RCTL support not present in kernel; see rctl(8) for details");
+
+ err(1, "sysctlbyname");
+ }
+
+ if (!racct_enable)
+ errx(1, "RACCT/RCTL present, but disabled; enable using kern.racct.enable=1 tunable");
+}
+
+static int
+add_rule(const char *rule, const char *unexpanded_rule)
+{
+ int error;
+
+ error = rctl_add_rule(rule, strlen(rule) + 1, NULL, 0);
+ if (error != 0) {
+ if (errno == ENOSYS)
+ enosys();
+ warn("failed to add rule '%s'", unexpanded_rule);
+ }
+
+ return (error);
+}
+
+static int
+show_limits(const char *filter, const char *unexpanded_rule,
+ int hflag, int nflag)
+{
+ int error;
+ char *outbuf = NULL;
+ size_t outbuflen = RCTL_DEFAULT_BUFSIZE / 4;
+
+ for (;;) {
+ outbuflen *= 4;
+ outbuf = realloc(outbuf, outbuflen);
+ if (outbuf == NULL)
+ err(1, "realloc");
+ error = rctl_get_limits(filter, strlen(filter) + 1,
+ outbuf, outbuflen);
+ if (error == 0)
+ break;
+ if (errno == ERANGE)
+ continue;
+ if (errno == ENOSYS)
+ enosys();
+ warn("failed to get limits for '%s'", unexpanded_rule);
+ free(outbuf);
+
+ return (error);
+ }
+
+ print_rules(outbuf, hflag, nflag);
+ free(outbuf);
+
+ return (error);
+}
+
+static int
+remove_rule(const char *filter, const char *unexpanded_rule)
+{
+ int error;
+
+ error = rctl_remove_rule(filter, strlen(filter) + 1, NULL, 0);
+ if (error != 0) {
+ if (errno == ENOSYS)
+ enosys();
+ warn("failed to remove rule '%s'", unexpanded_rule);
+ }
+
+ return (error);
+}
+
+static char *
+humanize_usage_amount(char *usage)
+{
+ int64_t num;
+ const char *resource, *amount;
+ char *copy, *humanized, buf[6], *tofree;
+ int ret;
+
+ tofree = copy = strdup(usage);
+ if (copy == NULL)
+ err(1, "strdup");
+
+ resource = strsep(&copy, "=");
+ amount = copy;
+
+ assert(resource != NULL);
+ assert(amount != NULL);
+
+ if (str2int64(amount, &num) != 0 ||
+ humanize_number(buf, sizeof(buf), num, "", HN_AUTOSCALE,
+ HN_DECIMAL | HN_NOSPACE) == -1) {
+ free(tofree);
+ return (usage);
+ }
+
+ ret = asprintf(&humanized, "%s=%s", resource, buf);
+ if (ret <= 0)
+ err(1, "asprintf");
+
+ free(tofree);
+ return (humanized);
+}
+
+/*
+ * Query the kernel about a resource usage and print it out.
+ */
+static int
+show_usage(const char *filter, const char *unexpanded_rule, int hflag)
+{
+ int error;
+ char *copy, *outbuf = NULL, *tmp;
+ size_t outbuflen = RCTL_DEFAULT_BUFSIZE / 4;
+
+ for (;;) {
+ outbuflen *= 4;
+ outbuf = realloc(outbuf, outbuflen);
+ if (outbuf == NULL)
+ err(1, "realloc");
+ error = rctl_get_racct(filter, strlen(filter) + 1,
+ outbuf, outbuflen);
+ if (error == 0)
+ break;
+ if (errno == ERANGE)
+ continue;
+ if (errno == ENOSYS)
+ enosys();
+ warn("failed to show resource consumption for '%s'",
+ unexpanded_rule);
+ free(outbuf);
+
+ return (error);
+ }
+
+ copy = outbuf;
+ while ((tmp = strsep(&copy, ",")) != NULL) {
+ if (tmp[0] == '\0')
+ break; /* XXX */
+
+ if (hflag)
+ tmp = humanize_usage_amount(tmp);
+
+ printf("%s\n", tmp);
+ }
+
+ free(outbuf);
+
+ return (error);
+}
+
+/*
+ * Query the kernel about resource limit rules and print them out.
+ */
+static int
+show_rules(const char *filter, const char *unexpanded_rule,
+ int hflag, int nflag)
+{
+ int error;
+ char *outbuf = NULL;
+ size_t filterlen, outbuflen = RCTL_DEFAULT_BUFSIZE / 4;
+
+ if (filter != NULL)
+ filterlen = strlen(filter) + 1;
+ else
+ filterlen = 0;
+
+ for (;;) {
+ outbuflen *= 4;
+ outbuf = realloc(outbuf, outbuflen);
+ if (outbuf == NULL)
+ err(1, "realloc");
+ error = rctl_get_rules(filter, filterlen, outbuf, outbuflen);
+ if (error == 0)
+ break;
+ if (errno == ERANGE)
+ continue;
+ if (errno == ENOSYS)
+ enosys();
+ warn("failed to show rules for '%s'", unexpanded_rule);
+ free(outbuf);
+
+ return (error);
+ }
+
+ print_rules(outbuf, hflag, nflag);
+ free(outbuf);
+
+ return (error);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: rctl [ -h ] [-a rule | -l filter | -r filter "
+ "| -u filter | filter]\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch, aflag = 0, hflag = 0, nflag = 0, lflag = 0, rflag = 0,
+ uflag = 0;
+ char *rule = NULL, *unexpanded_rule;
+ int i, cumulated_error, error;
+
+ while ((ch = getopt(argc, argv, "ahlnru")) != -1) {
+ switch (ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (aflag + lflag + rflag + uflag > 1)
+ errx(1, "at most one of -a, -l, -r, or -u may be specified");
+
+ if (argc == 0) {
+ if (aflag + lflag + rflag + uflag == 0) {
+ rule = strdup("::");
+ show_rules(rule, rule, hflag, nflag);
+
+ return (0);
+ }
+
+ usage();
+ }
+
+ cumulated_error = 0;
+
+ for (i = 0; i < argc; i++) {
+ unexpanded_rule = argv[i];
+
+ /*
+ * Skip resolving if passed -n _and_ -a. Ignore -n otherwise,
+ * so we can still do "rctl -n u:root" and see the rules without
+ * resolving the UID.
+ */
+ if (aflag != 0 && nflag != 0)
+ rule = expand_rule(unexpanded_rule, false);
+ else
+ rule = expand_rule(unexpanded_rule, true);
+
+ if (rule == NULL) {
+ cumulated_error++;
+ continue;
+ }
+
+ /*
+ * The reason for passing the unexpanded_rule is to make
+ * it easier for the user to search for the problematic
+ * rule in the passed input.
+ */
+ if (aflag) {
+ error = add_rule(rule, unexpanded_rule);
+ } else if (lflag) {
+ error = show_limits(rule, unexpanded_rule,
+ hflag, nflag);
+ } else if (rflag) {
+ error = remove_rule(rule, unexpanded_rule);
+ } else if (uflag) {
+ error = show_usage(rule, unexpanded_rule, hflag);
+ } else {
+ error = show_rules(rule, unexpanded_rule,
+ hflag, nflag);
+ }
+
+ if (error != 0)
+ cumulated_error++;
+
+ free(rule);
+ }
+
+ return (cumulated_error);
+}
diff --git a/usr.bin/readelf/Makefile b/usr.bin/readelf/Makefile
new file mode 100644
index 000000000000..d2a386fb0d40
--- /dev/null
+++ b/usr.bin/readelf/Makefile
@@ -0,0 +1,36 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+READELFDIR= ${ELFTCDIR}/readelf
+
+.PATH: ${READELFDIR}
+
+PROG= readelf
+SRCS= readelf.c
+
+LIBADD= dwarf elftc elf z
+
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+# This same hack is in lib/libelf/Makefile and lib/libdwarf/Makefile
+# We need to link against the correct version of these files. One
+# solution is to include SRCTOP/sys in the include path. This causes
+# problems when a header file in sys depends on a file in another
+# part of the tree, e.g. a machine dependent header.
+#
+SRCS+= sys/elf32.h sys/elf64.h sys/elf_common.h
+CLEANDIRS= sys
+CFLAGS+= -I.
+sys/elf32.h sys/elf64.h sys/elf_common.h: ${SRCTOP}/sys/${.TARGET} .NOMETA
+ mkdir -p ${.OBJDIR}/sys
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/readelf/Makefile.depend b/usr.bin/readelf/Makefile.depend
new file mode 100644
index 000000000000..ddc284fa26a2
--- /dev/null
+++ b/usr.bin/readelf/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libdwarf \
+ lib/libelf \
+ lib/libelftc \
+ lib/libz \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/readelf/Makefile.depend.options b/usr.bin/readelf/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/readelf/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/renice/Makefile b/usr.bin/renice/Makefile
new file mode 100644
index 000000000000..6b99072b24c7
--- /dev/null
+++ b/usr.bin/renice/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= renice
+MAN= renice.8
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/renice/Makefile.depend b/usr.bin/renice/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/renice/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/renice/renice.8 b/usr.bin/renice/renice.8
new file mode 100644
index 000000000000..035beaa08ed1
--- /dev/null
+++ b/usr.bin/renice/renice.8
@@ -0,0 +1,125 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.Dd October 27, 2020
+.Dt RENICE 8
+.Os
+.Sh NAME
+.Nm renice
+.Nd alter priority of running processes
+.Sh SYNOPSIS
+.Nm
+.Ar priority
+.Op Oo Fl gpu Oc Ar target
+.Nm
+.Fl n Ar increment
+.Op Oo Fl gpu Oc Ar target
+.Sh DESCRIPTION
+The
+.Nm
+utility alters the
+scheduling priority of one or more running processes.
+The following
+.Ar target
+parameters are interpreted as process ID's (the default), process group
+ID's, user ID's or user names.
+The
+.Nm Ns 'ing
+of a process group causes all processes in the process group
+to have their scheduling priority altered.
+The
+.Nm Ns 'ing
+of a user causes all processes owned by the user to have
+their scheduling priority altered.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl n
+Instead of changing the specified processes to the given priority,
+interpret the following argument as an increment to be applied to
+the current priority of each process.
+.It Fl g
+Interpret
+.Ar target
+parameters as process group ID's.
+.It Fl p
+Interpret
+.Ar target
+parameters as process ID's (the default).
+.It Fl u
+Interpret
+.Ar target
+parameters as user names or user ID's.
+.El
+.Pp
+Users other than the super-user may only alter the priority of
+processes they own,
+and can only monotonically increase their ``nice value''
+within the range 0 to
+.Dv PRIO_MAX
+(20).
+(This prevents overriding administrative fiats.)
+The super-user
+may alter the priority of any process
+and set the priority to any value in the range
+.Dv PRIO_MIN
+(\-20)
+to
+.Dv PRIO_MAX .
+Useful priorities are:
+20 (the affected processes will run only when nothing else
+in the system wants to),
+0 (the ``base'' scheduling priority),
+anything negative (to make things go very fast).
+.Sh FILES
+.Bl -tag -width /etc/passwd -compact
+.It Pa /etc/passwd
+to map user names to user ID's
+.El
+.Sh EXAMPLES
+Change the priority of process ID's 987 and 32, and
+all processes owned by users daemon and root.
+.Pp
+.Dl "renice +1 987 -u daemon root -p 32"
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr rtprio 1 ,
+.Xr getpriority 2 ,
+.Xr setpriority 2
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.0 .
+.Sh BUGS
+Non super-users cannot increase scheduling priorities of their own processes,
+even if they were the ones that decreased the priorities in the first place.
diff --git a/usr.bin/renice/renice.c b/usr.bin/renice/renice.c
new file mode 100644
index 000000000000..4931a39c0f67
--- /dev/null
+++ b/usr.bin/renice/renice.c
@@ -0,0 +1,179 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1989, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int donice(int, int, int, bool);
+static int getnum(const char *, const char *, int *);
+static void usage(void);
+
+/*
+ * Change the priority (nice) of processes
+ * or groups of processes which are already
+ * running.
+ */
+int
+main(int argc, char *argv[])
+{
+ struct passwd *pwd;
+ bool havedelim = false, haveprio = false, incr = false;
+ int errs = 0, prio = 0, who = 0, which = PRIO_PROCESS;
+
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ if (!havedelim) {
+ /* can occur at any time prior to delimiter */
+ if (strcmp(*argv, "-g") == 0) {
+ which = PRIO_PGRP;
+ continue;
+ }
+ if (strcmp(*argv, "-u") == 0) {
+ which = PRIO_USER;
+ continue;
+ }
+ if (strcmp(*argv, "-p") == 0) {
+ which = PRIO_PROCESS;
+ continue;
+ }
+ if (strcmp(*argv, "--") == 0) {
+ havedelim = true;
+ continue;
+ }
+ if (strcmp(*argv, "-n") == 0) {
+ /* may occur only once, prior to priority */
+ if (haveprio || incr || argc < 2)
+ usage();
+ incr = true;
+ (void)argc--, argv++;
+ /* fall through to priority */
+ }
+ }
+ if (!haveprio) {
+ /* must occur exactly once, prior to target */
+ if (getnum("priority", *argv, &prio))
+ return (1);
+ haveprio = true;
+ continue;
+ }
+ if (which == PRIO_USER) {
+ if ((pwd = getpwnam(*argv)) != NULL)
+ who = pwd->pw_uid;
+ else if (getnum("uid", *argv, &who)) {
+ errs++;
+ continue;
+ } else if (who < 0) {
+ warnx("%s: bad value", *argv);
+ errs++;
+ continue;
+ }
+ } else {
+ if (getnum("pid", *argv, &who)) {
+ errs++;
+ continue;
+ }
+ if (who < 0) {
+ warnx("%s: bad value", *argv);
+ errs++;
+ continue;
+ }
+ }
+ errs += donice(which, who, prio, incr);
+ }
+ if (!haveprio)
+ usage();
+ exit(errs != 0);
+}
+
+static int
+donice(int which, int who, int prio, bool incr)
+{
+ int oldprio;
+
+ errno = 0;
+ oldprio = getpriority(which, who);
+ if (oldprio == -1 && errno) {
+ warn("%d: getpriority", who);
+ return (1);
+ }
+ if (incr)
+ prio = oldprio + prio;
+ if (prio > PRIO_MAX)
+ prio = PRIO_MAX;
+ if (prio < PRIO_MIN)
+ prio = PRIO_MIN;
+ if (setpriority(which, who, prio) < 0) {
+ warn("%d: setpriority", who);
+ return (1);
+ }
+ fprintf(stderr, "%d: old priority %d, new priority %d\n", who,
+ oldprio, prio);
+ return (0);
+}
+
+static int
+getnum(const char *com, const char *str, int *val)
+{
+ long v;
+ char *ep;
+
+ errno = 0;
+ v = strtol(str, &ep, 10);
+ if (v < INT_MIN || v > INT_MAX || errno == ERANGE) {
+ warnx("%s argument %s is out of range.", com, str);
+ return (1);
+ }
+ if (ep == str || *ep != '\0' || errno != 0) {
+ warnx("%s argument %s is invalid.", com, str);
+ return (1);
+ }
+
+ *val = (int)v;
+ return (0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+"usage: renice priority [[-p] pid ...] [[-g] pgrp ...] [[-u] user ...]",
+" renice -n increment [[-p] pid ...] [[-g] pgrp ...] [[-u] user ...]");
+ exit(1);
+}
diff --git a/usr.bin/renice/tests/Makefile b/usr.bin/renice/tests/Makefile
new file mode 100644
index 000000000000..acaf383765bf
--- /dev/null
+++ b/usr.bin/renice/tests/Makefile
@@ -0,0 +1,4 @@
+ATF_TESTS_SH+= renice_test
+TEST_METADATA.renice_test+= is_exclusive="true"
+
+.include <bsd.test.mk>
diff --git a/usr.bin/renice/tests/renice_test.sh b/usr.bin/renice/tests/renice_test.sh
new file mode 100755
index 000000000000..7983eb594716
--- /dev/null
+++ b/usr.bin/renice/tests/renice_test.sh
@@ -0,0 +1,174 @@
+#
+# Copyright (c) 2022-2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+# Name of user to use for -u tests when running as root. Beware that
+# processes owned by that user will be affected by the test.
+TEST_USER=nobody
+
+_renice() {
+ atf_check -o empty -e ignore -s exit:0 renice "$@"
+}
+
+atf_check_nice_value() {
+ local pid=$1
+ local expected=$2
+ local actual="$(ps -o nice= -p $pid)"
+ atf_check test "$actual" -eq "$expected"
+}
+
+atf_test_case renice_abs_pid
+renice_abs_pid_head() {
+ atf_set "descr" "Set a process's nice number to an absolute value"
+}
+renice_abs_pid_body() {
+ local pid nice incr
+ sleep 60 &
+ pid=$!
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice $((nice+incr)) $pid
+ atf_check_nice_value $pid $((nice+incr))
+ kill $pid
+}
+
+atf_test_case renice_rel_pid
+renice_rel_pid_head() {
+ atf_set "descr" "Change a process's nice number by a relative value"
+}
+renice_rel_pid_body() {
+ local pid nice incr
+ sleep 60 &
+ pid=$!
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice -n $incr $pid
+ _renice -p -n $incr $pid
+ _renice -n $incr -p $pid
+ atf_check_nice_value $pid $((nice+incr+incr+incr))
+ kill $pid
+}
+
+atf_test_case renice_abs_pgid
+renice_abs_pgid_head() {
+ atf_set "descr" "Set a process group's nice number to an absolute value"
+}
+renice_abs_pgid_body() {
+ local pid pgid nice incr
+ # make sure target runs in a different pgrp than ours
+ pid="$(sh -mc "sleep 60 >/dev/null & echo \$!")"
+ pgid="$(ps -o pgid= -p $pid)"
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice $((nice+incr)) -g $pgid
+ atf_check_nice_value $pid $((nice+incr))
+ kill $pid
+}
+
+atf_test_case renice_rel_pgid
+renice_rel_pgid_head() {
+ atf_set "descr" "Change a process group's nice number by a relative value"
+}
+renice_rel_pgid_body() {
+ local pid pgid nice incr
+ # make sure target runs in a different pgrp than ours
+ pid="$(sh -mc "sleep 60 >/dev/null & echo \$!")"
+ pgid="$(ps -o pgid= -p $pid)"
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice -g -n $incr $pgid
+ _renice -n $incr -g $pgid
+ atf_check_nice_value $pid $((nice+incr+incr))
+ kill $pid
+}
+
+atf_test_case renice_abs_user
+renice_abs_user_head() {
+ atf_set "descr" "Set a user's processes' nice numbers to an absolute value"
+ atf_set "require.user" "root"
+}
+renice_abs_user_body() {
+ local user pid nice incr
+ pid="$(su -m $TEST_USER -c "/bin/sh -c 'sleep 60 >/dev/null & echo \$!'")"
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice $((nice+incr)) -u $TEST_USER
+ atf_check_nice_value $pid $((nice+incr))
+ kill $pid
+}
+
+atf_test_case renice_rel_user
+renice_rel_user_head() {
+ atf_set "descr" "Change a user's processes' nice numbers by a relative value"
+ atf_set "require.user" "root"
+}
+renice_rel_user_body() {
+ local user pid nice incr
+ pid="$(su -m $TEST_USER -c "/bin/sh -c 'sleep 60 >/dev/null & echo \$!'")"
+ nice="$(ps -o nice= -p $pid)"
+ incr=3
+ _renice -u -n $incr $TEST_USER
+ _renice -n $incr -u $TEST_USER
+ atf_check_nice_value $pid $((nice+incr+incr))
+ kill $pid
+}
+
+atf_test_case renice_delim
+renice_delim_head() {
+ atf_set "descr" "Test various delimiter positions"
+}
+renice_delim_body() {
+ local pid nice incr
+ sleep 60 &
+ pid=$!
+ nice="$(ps -o nice= -p $pid)"
+ incr=0
+ # without -p
+ : $((incr=incr+1))
+ _renice -- $((nice+incr)) $pid
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice $((nice+incr)) -- $pid
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice $((nice+incr)) $pid --
+ atf_check_nice_value $pid $((nice+incr))
+ # with -p
+ : $((incr=incr+1))
+ _renice -p -- $((nice+incr)) $pid
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice -p $((nice+incr)) -- $pid
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice -p $((nice+incr)) $pid --
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice $((nice+incr)) -p -- $pid
+ atf_check_nice_value $pid $((nice+incr))
+ : $((incr=incr+1))
+ _renice $((nice+incr)) -p $pid --
+ atf_check_nice_value $pid $((nice+incr))
+ kill $pid
+}
+
+atf_test_case renice_incr_noarg
+renice_incr_noarg_head() {
+ atf_set "descr" "Do not segfault if -n is given without an argument"
+}
+renice_incr_noarg_body() {
+ atf_check -o empty -e ignore -s exit:1 renice -n
+}
+
+atf_init_test_cases() {
+ atf_add_test_case renice_abs_pid
+ atf_add_test_case renice_rel_pid
+ atf_add_test_case renice_abs_pgid
+ atf_add_test_case renice_rel_pgid
+ atf_add_test_case renice_abs_user
+ atf_add_test_case renice_rel_user
+ atf_add_test_case renice_delim
+ atf_add_test_case renice_incr_noarg
+}
diff --git a/usr.bin/resizewin/Makefile b/usr.bin/resizewin/Makefile
new file mode 100644
index 000000000000..edc1914e2553
--- /dev/null
+++ b/usr.bin/resizewin/Makefile
@@ -0,0 +1,4 @@
+PROG= resizewin
+
+.include <bsd.prog.mk>
+
diff --git a/usr.bin/resizewin/Makefile.depend b/usr.bin/resizewin/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/resizewin/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/resizewin/resizewin.1 b/usr.bin/resizewin/resizewin.1
new file mode 100644
index 000000000000..ba4abe53ea1d
--- /dev/null
+++ b/usr.bin/resizewin/resizewin.1
@@ -0,0 +1,85 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" resizewin
+.\"
+.\" Query terminal for size and inform the kernel
+.\"
+.\" Copyright 2015 EMC / Isilon Storage Division
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 May 9, 2017
+.Dt RESIZEWIN 1
+.Os
+.Sh NAME
+.Nm resizewin
+.Nd update terminal size
+.Sh SYNOPSIS
+.Nm
+.Op Fl z
+.Sh DESCRIPTION
+The
+.Nm
+utility
+queries the terminal emulator for the current window size and updates
+the size known to the kernel using the
+.Dv TIOCSWINSZ
+ioctl.
+.Pp
+The following options are available:
+.Bl -tag -width "-z"
+.It Fl z
+Do nothing unless the current kernel terminal size is zero.
+This is useful when run from a user's profile (shell startup) scripts:
+querying the window size is required for serial lines, but not when
+logging in over the network, as protocols like TELNET or SSH already
+handle the terminal size by themselves.
+.El
+.Pp
+After a terminal window has been resized, running
+.Nm
+updates the kernel's window size to match the new size.
+.Pp
+.Nm
+is functionally similar to
+.Xr resize 1 ,
+which is part of the
+.Xr xterm 1 Pq Pa ports/x11/xterm
+distribution.
+However,
+.Nm
+only works with VT100/ANSI-compatible terminals and does not emit
+commands to set environment variables.
+.Pp
+The terminal is assumed to be VT100/ANSI compatible.
+The VT100/ANSI escape sequences are supported by virtually all modern
+terminals, including xterm, konsole, gnome-terminal, iTerm,
+Terminal.app, and PuTTY.
+.Sh SEE ALSO
+.Xr stty 1 ,
+.Xr tty 4
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 11.0 .
diff --git a/usr.bin/resizewin/resizewin.c b/usr.bin/resizewin/resizewin.c
new file mode 100644
index 000000000000..c6fefd79624c
--- /dev/null
+++ b/usr.bin/resizewin/resizewin.c
@@ -0,0 +1,158 @@
+/*
+ * resizewin
+ *
+ * Query terminal for size and inform the kernel
+ *
+ * Copyright 2015 EMC / Isilon Storage Division
+ *
+ * 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 AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* screen doesn't support ESC[18t (return terminal size) so do it the hard way */
+static const char query[] =
+ "\0337" /* Save cursor position */
+ "\033[r" /* Scroll whole screen */
+ "\033[999;999H" /* Move cursor */
+ "\033[6n" /* Get cursor position */
+ "\0338"; /* Restore cursor position */
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: resizewin [-z]\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct termios old, new;
+ struct winsize w;
+ struct timeval then, now;
+ char data[20];
+ int ch, cnt, error, fd, ret, zflag;
+
+ error = 0;
+ zflag = 0;
+ while ((ch = getopt(argc, argv, "z")) != -1) {
+ switch (ch) {
+ case 'z':
+ zflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ if (argc != 0)
+ usage();
+
+ if ((fd = open("/dev/tty", O_RDWR | O_NONBLOCK)) == -1)
+ exit(1);
+
+ if (zflag) {
+ if (ioctl(fd, TIOCGWINSZ, &w) == -1)
+ exit(1);
+ if (w.ws_row != 0 && w.ws_col != 0)
+ exit(0);
+ }
+
+ /* Disable echo, flush the input, and drain the output */
+ if (tcgetattr(fd, &old) == -1)
+ exit(1);
+
+ new = old;
+ new.c_cflag |= (CLOCAL | CREAD);
+ new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ if (tcsetattr(fd, TCSAFLUSH, &new) == -1)
+ exit(1);
+
+ if (write(fd, query, sizeof(query) - 1) != sizeof(query) - 1) {
+ error = 1;
+ goto out;
+ }
+
+ /* Read the response */
+ bzero(data, sizeof(data));
+ gettimeofday(&then, NULL);
+ cnt = 0;
+ while (1) {
+ ret = read(fd, data + cnt, 1);
+
+ if (ret == -1) {
+ if (errno == EAGAIN) {
+ gettimeofday(&now, NULL);
+ timersub(&now, &then, &now);
+ if (now.tv_sec >= 2) {
+ warnx("timeout reading from terminal");
+ error = 1;
+ goto out;
+ }
+
+ usleep(20000);
+ continue;
+ }
+ error = 1;
+ goto out;
+ }
+ if (data[cnt] == 'R')
+ break;
+
+ cnt++;
+ if (cnt == sizeof(data) - 2) {
+ warnx("response too long");
+ error = 1;
+ goto out;
+ }
+ }
+
+ /* Parse */
+ if (sscanf(data, "\033[%hu;%huR", &w.ws_row, &w.ws_col) != 2) {
+ error = 1;
+ warnx("unable to parse response");
+ goto out;
+ }
+
+ /* Finally, what we want */
+ if (ioctl(fd, TIOCSWINSZ, &w) == -1)
+ error = 1;
+ out:
+ /* Restore echo */
+ tcsetattr(fd, TCSANOW, &old);
+
+ close(fd);
+ exit(error);
+}
diff --git a/usr.bin/rev/Makefile b/usr.bin/rev/Makefile
new file mode 100644
index 000000000000..92540c110938
--- /dev/null
+++ b/usr.bin/rev/Makefile
@@ -0,0 +1,3 @@
+PROG= rev
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rev/Makefile.depend b/usr.bin/rev/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/rev/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rev/rev.1 b/usr.bin/rev/rev.1
new file mode 100644
index 000000000000..0dc448dbc27a
--- /dev/null
+++ b/usr.bin/rev/rev.1
@@ -0,0 +1,49 @@
+.\" Copyright (c) 1985, 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.
+.\"
+.Dd June 27, 2020
+.Dt REV 1
+.Os
+.Sh NAME
+.Nm rev
+.Nd reverse lines of a file
+.Sh SYNOPSIS
+.Nm
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility copies the specified files to the standard output, reversing the
+order of characters in every line.
+If no files are specified, the standard input is read.
+.Sh EXAMPLES
+Reverse the text from stdin:
+.Bd -literal -offset indent
+$ echo -e "reverse \et these\entwo lines" | rev
+eseht esrever
+senil owt
+.Ed
diff --git a/usr.bin/rev/rev.c b/usr.bin/rev/rev.c
new file mode 100644
index 000000000000..4bb113d4b532
--- /dev/null
+++ b/usr.bin/rev/rev.c
@@ -0,0 +1,101 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 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.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ const char *filename;
+ wchar_t *p, *t;
+ FILE *fp;
+ size_t len;
+ int ch, rval;
+
+ setlocale(LC_ALL, "");
+
+ while ((ch = getopt(argc, argv, "")) != -1)
+ switch(ch) {
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ fp = stdin;
+ filename = "stdin";
+ rval = 0;
+ do {
+ if (*argv) {
+ if ((fp = fopen(*argv, "r")) == NULL) {
+ warn("%s", *argv);
+ rval = 1;
+ ++argv;
+ continue;
+ }
+ filename = *argv++;
+ }
+ while ((p = fgetwln(fp, &len)) != NULL) {
+ if (p[len - 1] == '\n')
+ --len;
+ for (t = p + len - 1; t >= p; --t)
+ putwchar(*t);
+ putwchar('\n');
+ }
+ if (ferror(fp)) {
+ warn("%s", filename);
+ clearerr(fp);
+ rval = 1;
+ }
+ (void)fclose(fp);
+ } while(*argv);
+ exit(rval);
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: rev [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/revoke/Makefile b/usr.bin/revoke/Makefile
new file mode 100644
index 000000000000..f468f6483b51
--- /dev/null
+++ b/usr.bin/revoke/Makefile
@@ -0,0 +1,3 @@
+PROG= revoke
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/revoke/Makefile.depend b/usr.bin/revoke/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/revoke/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/revoke/revoke.1 b/usr.bin/revoke/revoke.1
new file mode 100644
index 000000000000..1f584c3e2de0
--- /dev/null
+++ b/usr.bin/revoke/revoke.1
@@ -0,0 +1,54 @@
+.\" Copyright (c) 2009 Ed Schouten <ed@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 June 15, 2009
+.Dt REVOKE 1
+.Os
+.Sh NAME
+.Nm revoke
+.Nd "revoke a character device"
+.Sh SYNOPSIS
+.Nm
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+program revokes the character devices using
+.Xr revoke 2 .
+When used on a TTY, calls like
+.Xr read 2 ,
+.Xr write 2
+and
+.Xr ioctl 2 ,
+will be aborted immediately, effectively causing login sessions to be
+terminated.
+.Sh SEE ALSO
+.Xr revoke 2
+.Sh HISTORY
+The
+.Nm
+program first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An \&Ed Schouten Aq Mt ed@FreeBSD.org
diff --git a/usr.bin/revoke/revoke.c b/usr.bin/revoke/revoke.c
new file mode 100644
index 000000000000..a332a470edd5
--- /dev/null
+++ b/usr.bin/revoke/revoke.c
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2009 Ed Schouten <ed@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: revoke file ...\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char **d;
+ int error = 0;
+
+ if (argc == 1)
+ usage();
+
+ for (d = &argv[1]; *d != NULL; d++) {
+ if (revoke(*d) != 0) {
+ perror(*d);
+ error = 1;
+ }
+ }
+
+ return (error);
+}
diff --git a/usr.bin/rpcgen/Makefile b/usr.bin/rpcgen/Makefile
new file mode 100644
index 000000000000..aafa97fd0c3d
--- /dev/null
+++ b/usr.bin/rpcgen/Makefile
@@ -0,0 +1,5 @@
+PROG= rpcgen
+SRCS= rpc_main.c rpc_clntout.c rpc_cout.c rpc_hout.c rpc_parse.c \
+ rpc_sample.c rpc_scan.c rpc_svcout.c rpc_tblout.c rpc_util.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rpcgen/Makefile.depend b/usr.bin/rpcgen/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/rpcgen/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rpcgen/Makefile.depend.host b/usr.bin/rpcgen/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/rpcgen/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rpcgen/Makefile.depend.options b/usr.bin/rpcgen/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/rpcgen/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/rpcgen/rpc_clntout.c b/usr.bin/rpcgen/rpc_clntout.c
new file mode 100644
index 000000000000..a06ca686a483
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_clntout.c
@@ -0,0 +1,268 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsytsems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <rpc/types.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+static void write_program( definition * );
+static void printbody( proc_list * );
+
+static char RESULT[] = "clnt_res";
+
+
+#define DEFAULT_TIMEOUT 25 /* in seconds */
+
+
+void
+write_stubs(void)
+{
+ list *l;
+ definition *def;
+
+ f_print(fout,
+ "\n/* Default timeout can be changed using clnt_control() */\n");
+ f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
+ DEFAULT_TIMEOUT);
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind == DEF_PROGRAM) {
+ write_program(def);
+ }
+ }
+}
+
+static void
+write_program(definition *def)
+{
+ version_list *vp;
+ proc_list *proc;
+
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ f_print(fout, "\n");
+ if (mtflag == 0) {
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*\n");
+ pvname(proc->proc_name, vp->vers_num);
+ printarglist(proc, RESULT, "clnt", "CLIENT *");
+ } else {
+ f_print(fout, "enum clnt_stat \n");
+ pvname(proc->proc_name, vp->vers_num);
+ printarglist(proc, RESULT, "clnt", "CLIENT *");
+
+ }
+ f_print(fout, "{\n");
+ printbody(proc);
+
+ f_print(fout, "}\n");
+ }
+ }
+}
+
+/*
+ * Writes out declarations of procedure's argument list.
+ * In either ANSI C style, in one of old rpcgen style (pass by reference),
+ * or new rpcgen style (multiple arguments, pass by value);
+ */
+
+/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
+
+void
+printarglist(proc_list *proc, const char *result, const char *addargname,
+ const char *addargtype)
+{
+
+ decl_list *l;
+
+ if (!newstyle) {
+ /* old style: always pass argument by reference */
+ f_print(fout, "(");
+ ptype(proc->args.decls->decl.prefix,
+ proc->args.decls->decl.type, 1);
+
+ if (mtflag) {/* Generate result field */
+ f_print(fout, "*argp, ");
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*%s, %s%s)\n",
+ result, addargtype, addargname);
+ } else
+ f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
+ } else if (streq(proc->args.decls->decl.type, "void")) {
+ /* newstyle, 0 argument */
+ if (mtflag) {
+ f_print(fout, "(");
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*%s, %s%s)\n",
+ result, addargtype, addargname);
+ } else
+ f_print(fout, "(%s%s)\n", addargtype, addargname);
+ } else {
+ /* new style, 1 or multiple arguments */
+ f_print(fout, "(");
+ for (l = proc->args.decls; l != NULL; l = l->next) {
+ pdeclaration(proc->args.argname, &l->decl, 0, ", ");
+ }
+ if (mtflag) {
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*%s, ", result);
+
+ }
+ f_print(fout, "%s%s)\n", addargtype, addargname);
+ }
+}
+
+
+
+static const char *
+ampr(const char *type)
+{
+ if (isvectordef(type, REL_ALIAS)) {
+ return ("");
+ } else {
+ return ("&");
+ }
+}
+
+static void
+printbody(proc_list *proc)
+{
+ decl_list *l;
+ bool_t args2 = (proc->arg_num > 1);
+
+ /*
+ * For new style with multiple arguments, need a structure in which
+ * to stuff the arguments.
+ */
+
+
+ if (newstyle && args2) {
+ f_print(fout, "\t%s", proc->args.argname);
+ f_print(fout, " arg;\n");
+ }
+ if (!mtflag) {
+ f_print(fout, "\tstatic ");
+ if (streq(proc->res_type, "void")) {
+ f_print(fout, "char ");
+ } else {
+ ptype(proc->res_prefix, proc->res_type, 0);
+ }
+ f_print(fout, "%s;\n", RESULT);
+ f_print(fout, "\n");
+ f_print(fout, "\tmemset((char *)%s%s, 0, sizeof (%s));\n",
+ ampr(proc->res_type), RESULT, RESULT);
+
+ }
+ if (newstyle && !args2 &&
+ (streq(proc->args.decls->decl.type, "void"))) {
+ /* newstyle, 0 arguments */
+
+ if (mtflag)
+ f_print(fout, "\t return ");
+ else
+ f_print(fout, "\t if ");
+
+ f_print(fout,
+ "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_void, ",
+ proc->proc_name);
+ f_print(fout,
+ "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
+ stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
+ RESULT);
+
+ if (mtflag)
+ f_print(fout, "\n\t\tTIMEOUT));\n");
+ else
+ f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
+
+ } else if (newstyle && args2) {
+ /*
+ * Newstyle, multiple arguments
+ * stuff arguments into structure
+ */
+ for (l = proc->args.decls; l != NULL; l = l->next) {
+ f_print(fout, "\targ.%s = %s;\n",
+ l->decl.name, l->decl.name);
+ }
+ if (mtflag)
+ f_print(fout, "\treturn ");
+ else
+ f_print(fout, "\tif ");
+ f_print(fout,
+ "(clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s",
+ proc->proc_name,proc->args.argname);
+ f_print(fout,
+ ", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,",
+ stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type),
+ RESULT);
+ if (mtflag)
+ f_print(fout, "\n\t\tTIMEOUT));\n");
+ else
+ f_print(fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n");
+ } else { /* single argument, new or old style */
+ if (!mtflag)
+ f_print(fout,
+ "\tif (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT) != RPC_SUCCESS) {\n",
+ proc->proc_name,
+ stringfix(proc->args.decls->decl.type),
+ (newstyle ? "&" : ""),
+ (newstyle ? proc->args.decls->decl.name : "argp"),
+ stringfix(proc->res_type), ampr(proc->res_type),
+ RESULT);
+ else
+
+ f_print(fout,
+ "\treturn (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT));\n",
+ proc->proc_name,
+ stringfix(proc->args.decls->decl.type),
+ (newstyle ? "&" : ""),
+ (newstyle ? proc->args.decls->decl.name : "argp"),
+ stringfix(proc->res_type), "",
+ RESULT);
+ }
+ if (!mtflag) {
+ f_print(fout, "\t\treturn (NULL);\n");
+ f_print(fout, "\t}\n");
+
+ if (streq(proc->res_type, "void")) {
+ f_print(fout, "\treturn ((void *)%s%s);\n",
+ ampr(proc->res_type), RESULT);
+ } else {
+ f_print(fout, "\treturn (%s%s);\n",
+ ampr(proc->res_type), RESULT);
+ }
+ }
+}
diff --git a/usr.bin/rpcgen/rpc_cout.c b/usr.bin/rpcgen/rpc_cout.c
new file mode 100644
index 000000000000..8c2864847850
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_cout.c
@@ -0,0 +1,710 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_cout.c, XDR routine outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+static void print_header( definition * );
+static void print_trailer( void );
+static void print_stat( int , declaration * );
+static void emit_enum( definition * );
+static void emit_program( definition * );
+static void emit_union( definition * );
+static void emit_struct( definition * );
+static void emit_typedef( definition * );
+static void emit_inline( int, declaration *, int );
+static void emit_single_in_line( int, declaration *, int, relation );
+
+/*
+ * Emit the C-routine for the given definition
+ */
+void
+emit(definition *def)
+{
+ if (def->def_kind == DEF_CONST) {
+ return;
+ }
+ if (def->def_kind == DEF_PROGRAM) {
+ emit_program(def);
+ return;
+ }
+ if (def->def_kind == DEF_TYPEDEF) {
+ /*
+ * now we need to handle declarations like
+ * struct typedef foo foo;
+ * since we dont want this to be expanded into 2 calls to xdr_foo
+ */
+
+ if (strcmp(def->def.ty.old_type, def->def_name) == 0)
+ return;
+ }
+ print_header(def);
+ switch (def->def_kind) {
+ case DEF_UNION:
+ emit_union(def);
+ break;
+ case DEF_ENUM:
+ emit_enum(def);
+ break;
+ case DEF_STRUCT:
+ emit_struct(def);
+ break;
+ case DEF_TYPEDEF:
+ emit_typedef(def);
+ break;
+ /* DEF_CONST and DEF_PROGRAM have already been handled */
+ default:
+ break;
+ }
+ print_trailer();
+}
+
+static int
+findtype(definition *def, const char *type)
+{
+
+ if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
+ return (0);
+ } else {
+ return (streq(def->def_name, type));
+ }
+}
+
+static int
+undefined(const char *type)
+{
+ definition *def;
+
+ def = (definition *) FINDVAL(defined, type, findtype);
+ return (def == NULL);
+}
+
+
+static void
+print_generic_header(const char *procname, int pointerp)
+{
+ f_print(fout, "\n");
+ f_print(fout, "bool_t\n");
+ f_print(fout, "xdr_%s(", procname);
+ f_print(fout, "XDR *xdrs, ");
+ f_print(fout, "%s ", procname);
+ if (pointerp)
+ f_print(fout, "*");
+ f_print(fout, "objp)\n{\n\n");
+}
+
+static void
+print_header(definition *def)
+{
+ print_generic_header(def->def_name,
+ def->def_kind != DEF_TYPEDEF ||
+ !isvectordef(def->def.ty.old_type,
+ def->def.ty.rel));
+ /* Now add Inline support */
+
+ if (inline_size == 0)
+ return;
+ /* May cause lint to complain. but ... */
+ f_print(fout, "\tregister long *buf;\n\n");
+}
+
+static void
+print_prog_header(proc_list *plist)
+{
+ print_generic_header(plist->args.argname, 1);
+}
+
+static void
+print_trailer(void)
+{
+ f_print(fout, "\treturn (TRUE);\n");
+ f_print(fout, "}\n");
+}
+
+
+static void
+print_ifopen(int indent, const char *name)
+{
+ tabify(fout, indent);
+ f_print(fout, "if (!xdr_%s(xdrs", name);
+}
+
+static void
+print_ifarg(const char *arg)
+{
+ f_print(fout, ", %s", arg);
+}
+
+static void
+print_ifsizeof(int indent, const char *prefix, const char *type)
+{
+ if (indent) {
+ f_print(fout, ",\n");
+ tabify(fout, indent);
+ } else {
+ f_print(fout, ", ");
+ }
+ if (streq(type, "bool")) {
+ f_print(fout, "sizeof (bool_t), (xdrproc_t) xdr_bool");
+ } else {
+ f_print(fout, "sizeof (");
+ if (undefined(type) && prefix) {
+ f_print(fout, "%s ", prefix);
+ }
+ f_print(fout, "%s), (xdrproc_t) xdr_%s", type, type);
+ }
+}
+
+static void
+print_ifclose(int indent, int brace)
+{
+ f_print(fout, "))\n");
+ tabify(fout, indent);
+ f_print(fout, "\treturn (FALSE);\n");
+ if (brace)
+ f_print(fout, "\t}\n");
+}
+
+static void
+print_ifstat(int indent, const char *prefix, const char *type, relation rel,
+ const char *amax, const char *objname, const char *name)
+{
+ const char *alt = NULL;
+ int brace = 0;
+
+ switch (rel) {
+ case REL_POINTER:
+ brace = 1;
+ f_print(fout, "\t{\n");
+ f_print(fout, "\t%s **pp = %s;\n", type, objname);
+ print_ifopen(indent, "pointer");
+ print_ifarg("(char **)");
+ f_print(fout, "pp");
+ print_ifsizeof(0, prefix, type);
+ break;
+ case REL_VECTOR:
+ if (streq(type, "string")) {
+ alt = "string";
+ } else if (streq(type, "opaque")) {
+ alt = "opaque";
+ }
+ if (alt) {
+ print_ifopen(indent, alt);
+ print_ifarg(objname);
+ } else {
+ print_ifopen(indent, "vector");
+ print_ifarg("(char *)");
+ f_print(fout, "%s", objname);
+ }
+ print_ifarg(amax);
+ if (!alt) {
+ print_ifsizeof(indent + 1, prefix, type);
+ }
+ break;
+ case REL_ARRAY:
+ if (streq(type, "string")) {
+ alt = "string";
+ } else if (streq(type, "opaque")) {
+ alt = "bytes";
+ }
+ if (streq(type, "string")) {
+ print_ifopen(indent, alt);
+ print_ifarg(objname);
+ } else {
+ if (alt) {
+ print_ifopen(indent, alt);
+ } else {
+ print_ifopen(indent, "array");
+ }
+ print_ifarg("(char **)");
+ if (*objname == '&') {
+ f_print(fout, "%s.%s_val, (u_int *) %s.%s_len",
+ objname, name, objname, name);
+ } else {
+ f_print(fout,
+ "&%s->%s_val, (u_int *) &%s->%s_len",
+ objname, name, objname, name);
+ }
+ }
+ print_ifarg(amax);
+ if (!alt) {
+ print_ifsizeof(indent + 1, prefix, type);
+ }
+ break;
+ case REL_ALIAS:
+ print_ifopen(indent, type);
+ print_ifarg(objname);
+ break;
+ }
+ print_ifclose(indent, brace);
+}
+
+/* ARGSUSED */
+static void
+emit_enum(definition *def __unused)
+{
+ print_ifopen(1, "enum");
+ print_ifarg("(enum_t *)objp");
+ print_ifclose(1, 0);
+}
+
+static void
+emit_program(definition *def)
+{
+ decl_list *dl;
+ version_list *vlist;
+ proc_list *plist;
+
+ for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
+ for (plist = vlist->procs; plist != NULL; plist = plist->next) {
+ if (!newstyle || plist->arg_num < 2)
+ continue; /* old style, or single argument */
+ print_prog_header(plist);
+ for (dl = plist->args.decls; dl != NULL;
+ dl = dl->next)
+ print_stat(1, &dl->decl);
+ print_trailer();
+ }
+}
+
+
+static void
+emit_union(definition *def)
+{
+ declaration *dflt;
+ case_list *cl;
+ declaration *cs;
+ char *object;
+ const char *vecformat = "objp->%s_u.%s";
+ const char *format = "&objp->%s_u.%s";
+
+ print_stat(1, &def->def.un.enum_decl);
+ f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
+ for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
+
+ f_print(fout, "\tcase %s:\n", cl->case_name);
+ if (cl->contflag == 1) /* a continued case statement */
+ continue;
+ cs = &cl->case_decl;
+ if (!streq(cs->type, "void")) {
+ object = xmalloc(strlen(def->def_name) +
+ strlen(format) + strlen(cs->name) + 1);
+ if (isvectordef (cs->type, cs->rel)) {
+ s_print(object, vecformat, def->def_name,
+ cs->name);
+ } else {
+ s_print(object, format, def->def_name,
+ cs->name);
+ }
+ print_ifstat(2, cs->prefix, cs->type, cs->rel,
+ cs->array_max, object, cs->name);
+ free(object);
+ }
+ f_print(fout, "\t\tbreak;\n");
+ }
+ dflt = def->def.un.default_decl;
+ if (dflt != NULL) {
+ if (!streq(dflt->type, "void")) {
+ f_print(fout, "\tdefault:\n");
+ object = xmalloc(strlen(def->def_name) +
+ strlen(format) + strlen(dflt->name) + 1);
+ if (isvectordef (dflt->type, dflt->rel)) {
+ s_print(object, vecformat, def->def_name,
+ dflt->name);
+ } else {
+ s_print(object, format, def->def_name,
+ dflt->name);
+ }
+
+ print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
+ dflt->array_max, object, dflt->name);
+ free(object);
+ f_print(fout, "\t\tbreak;\n");
+ } else {
+ f_print(fout, "\tdefault:\n");
+ f_print(fout, "\t\tbreak;\n");
+ }
+ } else {
+ f_print(fout, "\tdefault:\n");
+ f_print(fout, "\t\treturn (FALSE);\n");
+ }
+
+ f_print(fout, "\t}\n");
+}
+
+static void
+inline_struct(definition *def, int flag)
+{
+ decl_list *dl;
+ int i, size;
+ decl_list *cur, *psav;
+ bas_type *ptr;
+ char *sizestr;
+ const char *plus;
+ char ptemp[256];
+ int indent = 1;
+
+ cur = NULL;
+ if (flag == PUT)
+ f_print(fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n");
+ else
+ f_print(fout, "\t\treturn (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
+
+ i = 0;
+ size = 0;
+ sizestr = NULL;
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next) { /* xxx */
+ /* now walk down the list and check for basic types */
+ if ((dl->decl.prefix == NULL) &&
+ ((ptr = find_type(dl->decl.type)) != NULL) &&
+ ((dl->decl.rel == REL_ALIAS) ||
+ (dl->decl.rel == REL_VECTOR))){
+ if (i == 0)
+ cur = dl;
+ i++;
+
+ if (dl->decl.rel == REL_ALIAS)
+ size += ptr->length;
+ else {
+ /* this code is required to handle arrays */
+ if (sizestr == NULL)
+ plus = "";
+ else
+ plus = " + ";
+
+ if (ptr->length != 1)
+ s_print(ptemp, "%s%s * %d",
+ plus, dl->decl.array_max,
+ ptr->length);
+ else
+ s_print(ptemp, "%s%s", plus,
+ dl->decl.array_max);
+
+ /* now concatenate to sizestr !!!! */
+ if (sizestr == NULL) {
+ sizestr = xstrdup(ptemp);
+ }
+ else{
+ sizestr = xrealloc(sizestr,
+ strlen(sizestr)
+ +strlen(ptemp)+1);
+ sizestr = strcat(sizestr, ptemp);
+ /* build up length of array */
+ }
+ }
+ } else {
+ if (i > 0) {
+ if (sizestr == NULL && size < inline_size){
+ /*
+ * don't expand into inline code
+ * if size < inline_size
+ */
+ while (cur != dl){
+ print_stat(indent + 1, &cur->decl);
+ cur = cur->next;
+ }
+ } else {
+ /* were already looking at a xdr_inlineable structure */
+ tabify(fout, indent + 1);
+ if (sizestr == NULL)
+ f_print(fout, "buf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
+ size);
+ else {
+ if (size == 0)
+ f_print(fout,
+ "buf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
+ sizestr);
+ else
+ f_print(fout,
+ "buf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
+ size, sizestr);
+
+ }
+ f_print(fout, "\n");
+ tabify(fout, indent + 1);
+ f_print(fout,
+ "if (buf == NULL) {\n");
+
+ psav = cur;
+ while (cur != dl){
+ print_stat(indent + 2, &cur->decl);
+ cur = cur->next;
+ }
+
+ f_print(fout, "\n\t\t} else {\n");
+
+ cur = psav;
+ while (cur != dl){
+ emit_inline(indent + 2, &cur->decl, flag);
+ cur = cur->next;
+ }
+
+ tabify(fout, indent + 1);
+ f_print(fout, "}\n");
+ }
+ }
+ size = 0;
+ i = 0;
+ free(sizestr);
+ sizestr = NULL;
+ print_stat(indent + 1, &dl->decl);
+ }
+ }
+
+ if (i > 0) {
+ if (sizestr == NULL && size < inline_size){
+ /* don't expand into inline code if size < inline_size */
+ while (cur != dl){
+ print_stat(indent + 1, &cur->decl);
+ cur = cur->next;
+ }
+ } else {
+ /* were already looking at a xdr_inlineable structure */
+ if (sizestr == NULL)
+ f_print(fout, "\t\tbuf = XDR_INLINE(xdrs, %d * BYTES_PER_XDR_UNIT);",
+ size);
+ else
+ if (size == 0)
+ f_print(fout,
+ "\t\tbuf = XDR_INLINE(xdrs, (%s) * BYTES_PER_XDR_UNIT);",
+ sizestr);
+ else
+ f_print(fout,
+ "\t\tbuf = XDR_INLINE(xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);",
+ size, sizestr);
+
+ f_print(fout, "\n\t\tif (buf == NULL) {\n");
+ psav = cur;
+ while (cur != NULL){
+ print_stat(indent + 2, &cur->decl);
+ cur = cur->next;
+ }
+ f_print(fout, "\t\t} else {\n");
+
+ cur = psav;
+ while (cur != dl){
+ emit_inline(indent + 2, &cur->decl, flag);
+ cur = cur->next;
+ }
+ f_print(fout, "\t\t}\n");
+ }
+ }
+}
+
+static void
+emit_struct(definition *def)
+{
+ decl_list *dl;
+ int j, size, flag;
+ bas_type *ptr;
+ int can_inline;
+
+ if (inline_size == 0) {
+ /* No xdr_inlining at all */
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(1, &dl->decl);
+ return;
+ }
+
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ if (dl->decl.rel == REL_VECTOR &&
+ strcmp(dl->decl.type, "opaque") != 0){
+ f_print(fout, "\tint i;\n");
+ break;
+ }
+
+ size = 0;
+ can_inline = 0;
+ /*
+ * Make a first pass and see if inling is possible.
+ */
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ if ((dl->decl.prefix == NULL) &&
+ ((ptr = find_type(dl->decl.type)) != NULL) &&
+ ((dl->decl.rel == REL_ALIAS)||
+ (dl->decl.rel == REL_VECTOR))){
+ if (dl->decl.rel == REL_ALIAS)
+ size += ptr->length;
+ else {
+ can_inline = 1;
+ break; /* can be inlined */
+ }
+ } else {
+ if (size >= inline_size){
+ can_inline = 1;
+ break; /* can be inlined */
+ }
+ size = 0;
+ }
+ if (size >= inline_size)
+ can_inline = 1;
+
+ if (can_inline == 0){ /* can not inline, drop back to old mode */
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(1, &dl->decl);
+ return;
+ }
+
+ flag = PUT;
+ for (j = 0; j < 2; j++){
+ inline_struct(def, flag);
+ if (flag == PUT)
+ flag = GET;
+ }
+
+ f_print(fout, "\t\treturn (TRUE);\n\t}\n\n");
+
+ /* now take care of XDR_FREE case */
+
+ for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+ print_stat(1, &dl->decl);
+
+}
+
+static void
+emit_typedef(definition *def)
+{
+ const char *prefix = def->def.ty.old_prefix;
+ const char *type = def->def.ty.old_type;
+ const char *amax = def->def.ty.array_max;
+ relation rel = def->def.ty.rel;
+
+ print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
+}
+
+static void
+print_stat(int indent, declaration *dec)
+{
+ const char *prefix = dec->prefix;
+ const char *type = dec->type;
+ const char *amax = dec->array_max;
+ relation rel = dec->rel;
+ char name[256];
+
+ if (isvectordef(type, rel)) {
+ s_print(name, "objp->%s", dec->name);
+ } else {
+ s_print(name, "&objp->%s", dec->name);
+ }
+ print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
+}
+
+
+char *upcase(const char *);
+
+static void
+emit_inline(int indent, declaration *decl, int flag)
+{
+ switch (decl->rel) {
+ case REL_ALIAS :
+ emit_single_in_line(indent, decl, flag, REL_ALIAS);
+ break;
+ case REL_VECTOR :
+ tabify(fout, indent);
+ f_print(fout, "{\n");
+ tabify(fout, indent + 1);
+ f_print(fout, "%s *genp;\n\n", decl->type);
+ tabify(fout, indent + 1);
+ f_print(fout,
+ "for (i = 0, genp = objp->%s;\n", decl->name);
+ tabify(fout, indent + 2);
+ f_print(fout, "i < %s; i++) {\n", decl->array_max);
+ emit_single_in_line(indent + 2, decl, flag, REL_VECTOR);
+ tabify(fout, indent + 1);
+ f_print(fout, "}\n");
+ tabify(fout, indent);
+ f_print(fout, "}\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+emit_single_in_line(int indent, declaration *decl, int flag, relation rel)
+{
+ char *upp_case;
+
+ tabify(fout, indent);
+ if (flag == PUT)
+ f_print(fout, "IXDR_PUT_");
+ else
+ if (rel == REL_ALIAS)
+ f_print(fout, "objp->%s = IXDR_GET_", decl->name);
+ else
+ f_print(fout, "*genp++ = IXDR_GET_");
+
+ upp_case = upcase(decl->type);
+
+ /* hack - XX */
+ if (strcmp(upp_case, "INT") == 0)
+ {
+ free(upp_case);
+ upp_case = strdup("LONG");
+ }
+
+ if (strcmp(upp_case, "U_INT") == 0)
+ {
+ free(upp_case);
+ upp_case = strdup("U_LONG");
+ }
+ if (flag == PUT)
+ if (rel == REL_ALIAS)
+ f_print(fout,
+ "%s(buf, objp->%s);\n", upp_case, decl->name);
+ else
+ f_print(fout, "%s(buf, *genp++);\n", upp_case);
+
+ else
+ f_print(fout, "%s(buf);\n", upp_case);
+ free(upp_case);
+}
+
+char *
+upcase(const char *str)
+{
+ char *ptr, *hptr;
+
+ ptr = (char *)xmalloc(strlen(str)+1);
+
+ hptr = ptr;
+ while (*str != '\0')
+ *ptr++ = toupper(*str++);
+
+ *ptr = '\0';
+ return (hptr);
+}
diff --git a/usr.bin/rpcgen/rpc_hout.c b/usr.bin/rpcgen/rpc_hout.c
new file mode 100644
index 000000000000..9c298930fa93
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_hout.c
@@ -0,0 +1,513 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_hout.c, Header file outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+void storexdrfuncdecl(const char *, int );
+static void pconstdef( definition * );
+static void pstructdef( definition * );
+static void puniondef( definition * );
+static void pprogramdef( definition *, int );
+static void penumdef( definition * );
+static void ptypedef( definition * );
+static void pdefine(const char *, const char *);
+static int undefined2(const char *, const char *);
+static void parglist(proc_list *, const char *);
+static void pprocdef(proc_list *, version_list *, const char *, int);
+
+/*
+ * Print the C-version of an xdr definition
+ */
+void
+print_datadef(definition *def, int headeronly)
+{
+
+ if (def->def_kind == DEF_PROGRAM) /* handle data only */
+ return;
+
+ if (def->def_kind != DEF_CONST) {
+ f_print(fout, "\n");
+ }
+ switch (def->def_kind) {
+ case DEF_STRUCT:
+ pstructdef(def);
+ break;
+ case DEF_UNION:
+ puniondef(def);
+ break;
+ case DEF_ENUM:
+ penumdef(def);
+ break;
+ case DEF_TYPEDEF:
+ ptypedef(def);
+ break;
+ case DEF_PROGRAM:
+ pprogramdef(def, headeronly);
+ break;
+ case DEF_CONST:
+ pconstdef(def);
+ break;
+ }
+ if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) {
+ storexdrfuncdecl(def->def_name,
+ def->def_kind != DEF_TYPEDEF ||
+ !isvectordef(def->def.ty.old_type,
+ def->def.ty.rel));
+ }
+}
+
+
+void
+print_funcdef(definition *def, int headeronly)
+{
+ switch (def->def_kind) {
+ case DEF_PROGRAM:
+ f_print(fout, "\n");
+ pprogramdef(def, headeronly);
+ break;
+ default:
+ break;
+ }
+}
+
+/* store away enough information to allow the XDR functions to be spat
+ out at the end of the file */
+
+void
+storexdrfuncdecl(const char *name, int pointerp)
+{
+ xdrfunc * xdrptr;
+
+ xdrptr = XALLOC(struct xdrfunc);
+
+ xdrptr->name = name;
+ xdrptr->pointerp = pointerp;
+ xdrptr->next = NULL;
+
+ if (xdrfunc_tail == NULL){
+ xdrfunc_head = xdrptr;
+ xdrfunc_tail = xdrptr;
+ } else {
+ xdrfunc_tail->next = xdrptr;
+ xdrfunc_tail = xdrptr;
+ }
+
+
+}
+
+void
+print_xdr_func_def(const char *name, int pointerp)
+{
+ f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name,
+ name, pointerp ? "*" : "");
+}
+
+
+static void
+pconstdef(definition *def)
+{
+ pdefine(def->def_name, def->def.co);
+}
+
+/* print out the definitions for the arguments of functions in the
+ header file
+*/
+static void
+pargdef(definition *def)
+{
+ decl_list *l;
+ version_list *vers;
+ char *name;
+ proc_list *plist;
+
+
+ for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
+ for (plist = vers->procs; plist != NULL;
+ plist = plist->next) {
+
+ if (!newstyle || plist->arg_num < 2) {
+ continue; /* old style or single args */
+ }
+ name = plist->args.argname;
+ f_print(fout, "struct %s {\n", name);
+ for (l = plist->args.decls;
+ l != NULL; l = l->next) {
+ pdeclaration(name, &l->decl, 1,
+ ";\n");
+ }
+ f_print(fout, "};\n");
+ f_print(fout, "typedef struct %s %s;\n",
+ name, name);
+ storexdrfuncdecl(name, 1);
+ f_print(fout, "\n");
+ }
+ }
+}
+
+
+static void
+pstructdef(definition *def)
+{
+ decl_list *l;
+ const char *name = def->def_name;
+
+ f_print(fout, "struct %s {\n", name);
+ for (l = def->def.st.decls; l != NULL; l = l->next) {
+ pdeclaration(name, &l->decl, 1, ";\n");
+ }
+ f_print(fout, "};\n");
+ f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+static void
+puniondef(definition *def)
+{
+ case_list *l;
+ const char *name = def->def_name;
+ declaration *decl;
+
+ f_print(fout, "struct %s {\n", name);
+ decl = &def->def.un.enum_decl;
+ if (streq(decl->type, "bool")) {
+ f_print(fout, "\tbool_t %s;\n", decl->name);
+ } else {
+ f_print(fout, "\t%s %s;\n", decl->type, decl->name);
+ }
+ f_print(fout, "\tunion {\n");
+ for (l = def->def.un.cases; l != NULL; l = l->next) {
+ if (l->contflag == 0)
+ pdeclaration(name, &l->case_decl, 2, ";\n");
+ }
+ decl = def->def.un.default_decl;
+ if (decl && !streq(decl->type, "void")) {
+ pdeclaration(name, decl, 2, ";\n");
+ }
+ f_print(fout, "\t} %s_u;\n", name);
+ f_print(fout, "};\n");
+ f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+static void
+pdefine(const char *name, const char *num)
+{
+ f_print(fout, "#define\t%s %s\n", name, num);
+}
+
+static void
+puldefine(const char *name, const char *num)
+{
+ f_print(fout, "#define\t%s ((unsigned long)(%s))\n", name, num);
+}
+
+static int
+define_printed(proc_list *stop, version_list *start)
+{
+ version_list *vers;
+ proc_list *proc;
+
+ for (vers = start; vers != NULL; vers = vers->next) {
+ for (proc = vers->procs; proc != NULL; proc = proc->next) {
+ if (proc == stop) {
+ return (0);
+ } else if (streq(proc->proc_name, stop->proc_name)) {
+ return (1);
+ }
+ }
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+static void
+pfreeprocdef(const char * name, const char *vers)
+{
+ f_print(fout, "extern int ");
+ pvname(name, vers);
+ f_print(fout, "_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n");
+}
+
+static void
+pdispatch(const char * name, const char *vers)
+{
+
+ f_print(fout, "void ");
+ pvname(name, vers);
+ f_print(fout, "(struct svc_req *rqstp, SVCXPRT *transp);\n");
+}
+
+static void
+pprogramdef(definition *def, int headeronly)
+{
+ version_list *vers;
+ proc_list *proc;
+ const char *ext;
+
+ pargdef(def);
+
+ puldefine(def->def_name, def->def.pr.prog_num);
+ for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
+ if (tblflag) {
+ f_print(fout,
+ "extern struct rpcgen_table %s_%s_table[];\n",
+ locase(def->def_name), vers->vers_num);
+ f_print(fout,
+ "extern %s_%s_nproc;\n",
+ locase(def->def_name), vers->vers_num);
+ }
+ puldefine(vers->vers_name, vers->vers_num);
+
+ f_print(fout, "\n");
+ ext = "extern ";
+ if (headeronly) {
+ f_print(fout, "%s", ext);
+ pdispatch(def->def_name, vers->vers_num);
+ }
+ for (proc = vers->procs; proc != NULL; proc = proc->next) {
+ if (!define_printed(proc, def->def.pr.versions)) {
+ puldefine(proc->proc_name, proc->proc_num);
+ }
+ f_print(fout, "%s", ext);
+ pprocdef(proc, vers, "CLIENT *", 0);
+ f_print(fout, "%s", ext);
+ pprocdef(proc, vers, "struct svc_req *", 1);
+ }
+ pfreeprocdef(def->def_name, vers->vers_num);
+ }
+}
+
+static void
+pprocdef(proc_list *proc, version_list *vp, const char *addargtype, int server_p)
+{
+ if (mtflag) {/* Print MT style stubs */
+ if (server_p)
+ f_print(fout, "bool_t ");
+ else
+ f_print(fout, "enum clnt_stat ");
+ } else {
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "* ");
+ }
+ if (server_p)
+ pvname_svc(proc->proc_name, vp->vers_num);
+ else
+ pvname(proc->proc_name, vp->vers_num);
+
+ parglist(proc, addargtype);
+}
+
+
+
+/* print out argument list of procedure */
+static void
+parglist(proc_list *proc, const char *addargtype)
+{
+ decl_list *dl;
+
+ f_print(fout, "(");
+ if (proc->arg_num < 2 && newstyle &&
+ streq(proc->args.decls->decl.type, "void")) {
+ /* 0 argument in new style: do nothing*/
+ }
+ else {
+ for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
+ ptype(dl->decl.prefix, dl->decl.type, 1);
+ if (!newstyle)
+ f_print(fout, "*");
+ /* old style passes by reference */
+ f_print(fout, ", ");
+ }
+ }
+
+ if (mtflag) {
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*, ");
+ }
+
+ f_print(fout, "%s);\n", addargtype);
+
+}
+
+static void
+penumdef(definition *def)
+{
+ const char *name = def->def_name;
+ enumval_list *l;
+ const char *last = NULL;
+ int count = 0;
+
+ f_print(fout, "enum %s {\n", name);
+ for (l = def->def.en.vals; l != NULL; l = l->next) {
+ f_print(fout, "\t%s", l->name);
+ if (l->assignment) {
+ f_print(fout, " = %s", l->assignment);
+ last = l->assignment;
+ count = 1;
+ } else {
+ if (last == NULL) {
+ f_print(fout, " = %d", count++);
+ } else {
+ f_print(fout, " = %s + %d", last, count++);
+ }
+ }
+ if (l->next)
+ f_print(fout, ",\n");
+ else
+ f_print(fout, "\n");
+ }
+ f_print(fout, "};\n");
+ f_print(fout, "typedef enum %s %s;\n", name, name);
+}
+
+static void
+ptypedef(definition *def)
+{
+ const char *name = def->def_name;
+ const char *old = def->def.ty.old_type;
+ char prefix[8]; /* enough to contain "struct ", including NUL */
+ relation rel = def->def.ty.rel;
+
+
+ if (!streq(name, old)) {
+ if (streq(old, "string")) {
+ old = "char";
+ rel = REL_POINTER;
+ } else if (streq(old, "opaque")) {
+ old = "char";
+ } else if (streq(old, "bool")) {
+ old = "bool_t";
+ }
+ if (undefined2(old, name) && def->def.ty.old_prefix) {
+ s_print(prefix, "%s ", def->def.ty.old_prefix);
+ } else {
+ prefix[0] = 0;
+ }
+ f_print(fout, "typedef ");
+ switch (rel) {
+ case REL_ARRAY:
+ f_print(fout, "struct {\n");
+ f_print(fout, "\tu_int %s_len;\n", name);
+ f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
+ f_print(fout, "} %s", name);
+ break;
+ case REL_POINTER:
+ f_print(fout, "%s%s *%s", prefix, old, name);
+ break;
+ case REL_VECTOR:
+ f_print(fout, "%s%s %s[%s]", prefix, old, name,
+ def->def.ty.array_max);
+ break;
+ case REL_ALIAS:
+ f_print(fout, "%s%s %s", prefix, old, name);
+ break;
+ }
+ f_print(fout, ";\n");
+ }
+}
+
+void
+pdeclaration(const char *name, declaration *dec, int tab, const char *separator)
+{
+ char buf[8]; /* enough to hold "struct ", include NUL */
+ const char *prefix;
+ const char *type;
+
+ if (streq(dec->type, "void")) {
+ return;
+ }
+ tabify(fout, tab);
+ if (streq(dec->type, name) && !dec->prefix) {
+ f_print(fout, "struct ");
+ }
+ if (streq(dec->type, "string")) {
+ f_print(fout, "char *%s", dec->name);
+ } else {
+ prefix = "";
+ if (streq(dec->type, "bool")) {
+ type = "bool_t";
+ } else if (streq(dec->type, "opaque")) {
+ type = "char";
+ } else {
+ if (dec->prefix) {
+ s_print(buf, "%s ", dec->prefix);
+ prefix = buf;
+ }
+ type = dec->type;
+ }
+ switch (dec->rel) {
+ case REL_ALIAS:
+ f_print(fout, "%s%s %s", prefix, type, dec->name);
+ break;
+ case REL_VECTOR:
+ f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
+ dec->array_max);
+ break;
+ case REL_POINTER:
+ f_print(fout, "%s%s *%s", prefix, type, dec->name);
+ break;
+ case REL_ARRAY:
+ f_print(fout, "struct {\n");
+ tabify(fout, tab);
+ f_print(fout, "\tu_int %s_len;\n", dec->name);
+ tabify(fout, tab);
+ f_print(fout,
+ "\t%s%s *%s_val;\n", prefix, type, dec->name);
+ tabify(fout, tab);
+ f_print(fout, "} %s", dec->name);
+ break;
+ }
+ }
+ fputs(separator, fout);
+}
+
+static int
+undefined2(const char *type, const char *stop)
+{
+ list *l;
+ definition *def;
+
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ if (streq(def->def_name, stop)) {
+ return (1);
+ } else if (streq(def->def_name, type)) {
+ return (0);
+ }
+ }
+ }
+ return (1);
+}
diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c
new file mode 100644
index 000000000000..8d5afad86cff
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_main.c
@@ -0,0 +1,1354 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+
+/*
+ * rpc_main.c, Top level of the RPC protocol compiler.
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+
+#include <err.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+static void c_output(const char *, const char *, int, const char *);
+static void h_output(const char *, const char *, int, const char *, int);
+static void l_output(const char *, const char *, int, const char *);
+static void t_output(const char *, const char *, int, const char *);
+static void clnt_output(const char *, const char *, int, const char * );
+static char *generate_guard(const char *);
+static void c_initialize(void);
+
+static void usage(void) __dead2;
+static void options_usage(void);
+static int do_registers(int, const char **);
+static int parseargs(int, const char **, struct commandline *);
+static void svc_output(const char *, const char *, int, const char *);
+static void mkfile_output(struct commandline *);
+static void s_output(int, const char **, const char *, const char *, int, const char *, int, int);
+
+#define EXTEND 1 /* alias for TRUE */
+#define DONT_EXTEND 0 /* alias for FALSE */
+
+static const char *svcclosetime = "120";
+static const char *CPP = NULL;
+static const char CPPFLAGS[] = "-C";
+static char pathbuf[MAXPATHLEN + 1];
+static const char *allv[] = {
+ "rpcgen", "-s", "udp", "-s", "tcp",
+};
+static int allc = nitems(allv);
+static const char *allnv[] = {
+ "rpcgen", "-s", "netpath",
+};
+static int allnc = nitems(allnv);
+
+/*
+ * machinations for handling expanding argument list
+ */
+static void addarg(const char *); /* add another argument to the list */
+static void insarg(int, const char *); /* insert arg at specified location */
+static void checkfiles(const char *, const char *);
+ /* check if out file already exists */
+
+static char **arglist;
+static int argcount = 0;
+static int argmax = 0;
+
+int nonfatalerrors; /* errors */
+int inetdflag = 0; /* Support for inetd is disabled by default, use -I */
+int pmflag = 0; /* Support for port monitors is disabled by default */
+int tirpc_socket = 1; /* TI-RPC on socket, no TLI library */
+int logflag; /* Use syslog instead of fprintf for errors */
+int tblflag; /* Support for dispatch table file */
+int mtflag = 0; /* Support for MT */
+
+#define INLINE 0
+/* length at which to start doing an inline */
+
+int inline_size = INLINE;
+/*
+ * Length at which to start doing an inline. INLINE = default
+ * if 0, no xdr_inline code
+ */
+
+int indefinitewait; /* If started by port monitors, hang till it wants */
+int exitnow; /* If started by port monitors, exit after the call */
+int timerflag; /* TRUE if !indefinite && !exitnow */
+int newstyle; /* newstyle of passing arguments (by value) */
+int CCflag = 0; /* C++ files */
+static int allfiles; /* generate all files */
+int tirpcflag = 1; /* generating code for tirpc, by default */
+xdrfunc *xdrfunc_head = NULL; /* xdr function list */
+xdrfunc *xdrfunc_tail = NULL; /* xdr function list */
+pid_t childpid;
+
+
+int
+main(int argc, const char *argv[])
+{
+ struct commandline cmd;
+
+ (void) memset((char *)&cmd, 0, sizeof (struct commandline));
+ if (!parseargs(argc, argv, &cmd))
+ usage();
+ /*
+ * Only the client and server side stubs are likely to be customized,
+ * so in that case only, check if the outfile exists, and if so,
+ * print an error message and exit.
+ */
+ if (cmd.Ssflag || cmd.Scflag || cmd.makefileflag) {
+ checkfiles(cmd.infile, cmd.outfile);
+ }
+ else
+ checkfiles(cmd.infile, NULL);
+
+ if (cmd.cflag) {
+ c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
+ } else if (cmd.hflag) {
+ h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile,
+ cmd.hflag);
+ } else if (cmd.lflag) {
+ l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
+ } else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
+ s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
+ cmd.outfile, cmd.mflag, cmd.nflag);
+ } else if (cmd.tflag) {
+ t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
+ } else if (cmd.Ssflag) {
+ svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND,
+ cmd.outfile);
+ } else if (cmd.Scflag) {
+ clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND,
+ cmd.outfile);
+ } else if (cmd.makefileflag) {
+ mkfile_output(&cmd);
+ } else {
+ /* the rescans are required, since cpp may effect input */
+ c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
+ reinitialize();
+ h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h", cmd.hflag);
+ reinitialize();
+ l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
+ reinitialize();
+ if (inetdflag || !tirpcflag)
+ s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
+ "_svc.c", cmd.mflag, cmd.nflag);
+ else
+ s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
+ EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
+ if (tblflag) {
+ reinitialize();
+ t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
+ }
+
+ if (allfiles) {
+ reinitialize();
+ svc_output(cmd.infile, "-DRPC_SERVER", EXTEND,
+ "_server.c");
+ reinitialize();
+ clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND,
+ "_client.c");
+
+ }
+ if (allfiles || (cmd.makefileflag == 1)){
+ reinitialize();
+ mkfile_output(&cmd);
+ }
+
+ }
+ exit(nonfatalerrors);
+ /* NOTREACHED */
+}
+
+
+/*
+ * add extension to filename
+ */
+static char *
+extendfile(const char *path, const char *ext)
+{
+ char *res;
+ const char *p;
+ const char *file;
+
+ if ((file = strrchr(path, '/')) == NULL)
+ file = path;
+ else
+ file++;
+ res = xmalloc(strlen(file) + strlen(ext) + 1);
+ p = strrchr(file, '.');
+ if (p == NULL) {
+ p = file + strlen(file);
+ }
+ (void) strcpy(res, file);
+ (void) strcpy(res + (p - file), ext);
+ return (res);
+}
+
+/*
+ * Open output file with given extension
+ */
+static void
+open_output(const char *infile, const char *outfile)
+{
+
+ if (outfile == NULL) {
+ fout = stdout;
+ return;
+ }
+
+ if (infile != NULL && streq(outfile, infile)) {
+ warnx("%s already exists. No output generated", infile);
+ crash();
+ }
+ fout = fopen(outfile, "w");
+ if (fout == NULL) {
+ warn("unable to open %s", outfile);
+ crash();
+ }
+ record_open(outfile);
+
+ return;
+}
+
+static void
+add_warning(void)
+{
+ f_print(fout, "/*\n");
+ f_print(fout, " * Please do not edit this file.\n");
+ f_print(fout, " * It was generated using rpcgen.\n");
+ f_print(fout, " */\n\n");
+}
+
+/* prepend C-preprocessor and flags before arguments */
+static void
+prepend_cpp(void)
+{
+ int idx = 0, quoted;
+ const char *var, *s;
+ char *dupvar, *t, *word;
+
+ if (CPP != NULL)
+ insarg(idx++, CPP);
+ else if ((var = getenv("RPCGEN_CPP")) == NULL)
+ insarg(idx++, "/usr/bin/cpp");
+ else {
+ /*
+ * Parse command line like a shell (but only handle whitespace,
+ * quotes and backslash).
+ */
+ dupvar = malloc(strlen(var) + 1);
+ quoted = 0;
+ word = NULL;
+ for (s = var, t = dupvar; *s; ++s) {
+ switch (quoted) {
+ /* Unquoted */
+ case 0:
+ switch (*s) {
+ case ' ':
+ case '\t':
+ case '\n':
+ if (word != NULL) {
+ *t++ = '\0';
+ insarg(idx++, word);
+ word = NULL;
+ }
+ break;
+ case '\'':
+ if (word == NULL)
+ word = t;
+ quoted = 1;
+ break;
+ case '"':
+ if (word == NULL)
+ word = t;
+ quoted = 2;
+ break;
+ case '\\':
+ switch (*(s + 1)) {
+ case '\0':
+ break;
+ case '\n':
+ ++s;
+ continue;
+ default:
+ ++s;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (word == NULL)
+ word = t;
+ *t++ = *s;
+ break;
+ }
+ break;
+
+ /* Single-quoted */
+ case 1:
+ switch (*s) {
+ case '\'':
+ quoted = 0;
+ break;
+ default:
+ *t++ = *s;
+ break;
+ }
+ break;
+
+ /* Double-quoted */
+ case 2:
+ switch (*s) {
+ case '"':
+ quoted = 0;
+ break;
+ case '\\':
+ switch (*(s + 1)) {
+ case '\0':
+ break;
+ case '$':
+ case '`':
+ case '"':
+ case '\\':
+ ++s;
+ break;
+ case '\n':
+ ++s;
+ continue;
+ default:
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ *t++ = *s;
+ break;
+ }
+ break;
+ }
+ }
+ if (quoted)
+ errx(1, "RPCGEN_CPP: unterminated %c",
+ quoted == 1 ? '\'' : '"');
+ if (word != NULL) {
+ *t++ = '\0';
+ insarg(idx++, word);
+ }
+ free(dupvar);
+ }
+
+ insarg(idx, CPPFLAGS);
+}
+
+/*
+ * Open input file with given define for C-preprocessor
+ */
+static void
+open_input(const char *infile, const char *define)
+{
+ int pd[2];
+
+ infilename = (infile == NULL) ? "<stdin>" : infile;
+ (void) pipe(pd);
+ switch (childpid = fork()) {
+ case 0:
+ prepend_cpp();
+ addarg(define);
+ if (infile)
+ addarg(infile);
+ addarg((char *)NULL);
+ (void) close(1);
+ (void) dup2(pd[1], 1);
+ (void) close(pd[0]);
+ execvp(arglist[0], arglist);
+ err(1, "execvp %s", arglist[0]);
+ case -1:
+ err(1, "fork");
+ }
+ (void) close(pd[1]);
+ fin = fdopen(pd[0], "r");
+ if (fin == NULL) {
+ warn("%s", infilename);
+ crash();
+ }
+}
+
+/* valid tirpc nettypes */
+static const char *valid_ti_nettypes[] =
+{
+ "netpath",
+ "visible",
+ "circuit_v",
+ "datagram_v",
+ "circuit_n",
+ "datagram_n",
+ "udp",
+ "tcp",
+ "raw",
+ NULL
+ };
+
+/* valid inetd nettypes */
+static const char *valid_i_nettypes[] =
+{
+ "udp",
+ "tcp",
+ NULL
+ };
+
+static int
+check_nettype(const char *name, const char *list_to_check[])
+{
+ int i;
+ for (i = 0; list_to_check[i] != NULL; i++) {
+ if (strcmp(name, list_to_check[i]) == 0) {
+ return (1);
+ }
+ }
+ warnx("illegal nettype :\'%s\'", name);
+ return (0);
+}
+
+static const char *
+file_name(const char *file, const char *ext)
+{
+ char *temp;
+ temp = extendfile(file, ext);
+
+ if (access(temp, F_OK) != -1)
+ return (temp);
+ else
+ return (" ");
+
+}
+
+
+static void
+c_output(const char *infile, const char *define, int extend, const char *outfile)
+{
+ definition *def;
+ char *include;
+ const char *outfilename;
+ long tell;
+
+ c_initialize();
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ open_output(infile, outfilename);
+ add_warning();
+ if (infile && (include = extendfile(infile, ".h"))) {
+ f_print(fout, "#include \"%s\"\n", include);
+ free(include);
+ /* .h file already contains rpc/rpc.h */
+ } else
+ f_print(fout, "#include <rpc/rpc.h>\n");
+ tell = ftell(fout);
+ while ( (def = get_definition()) ) {
+ emit(def);
+ }
+ if (extend && tell == ftell(fout)) {
+ (void) unlink(outfilename);
+ }
+}
+
+
+void
+c_initialize(void)
+{
+
+ /* add all the starting basic types */
+ add_type(1, "int");
+ add_type(1, "long");
+ add_type(1, "short");
+ add_type(1, "bool");
+ add_type(1, "u_int");
+ add_type(1, "u_long");
+ add_type(1, "u_short");
+
+}
+
+static const char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
+ char *(*proc)(); \n\
+ xdrproc_t xdr_arg; \n\
+ unsigned len_arg; \n\
+ xdrproc_t xdr_res; \n\
+ unsigned len_res; \n\
+}; \n";
+
+
+char *
+generate_guard(const char *pathname)
+{
+ const char *filename;
+ char *guard, *tmp, *stopat;
+
+ filename = strrchr(pathname, '/'); /* find last component */
+ filename = ((filename == NULL) ? pathname : filename+1);
+ guard = xstrdup(filename);
+ stopat = strrchr(guard, '.');
+
+ /*
+ * Convert to a valid C macro name and make it upper case.
+ * Map macro unfriendly characterss to '_'.
+ */
+ for (tmp = guard; *tmp != '\000'; ++tmp) {
+ if (islower(*tmp))
+ *tmp = toupper(*tmp);
+ else if (isupper(*tmp) || *tmp == '_')
+ /* OK for C */;
+ else if (tmp == guard)
+ *tmp = '_';
+ else if (isdigit(*tmp))
+ /* OK for all but first character */;
+ else if (tmp == stopat) {
+ *tmp = '\0';
+ break;
+ } else
+ *tmp = '_';
+ }
+ /*
+ * Can't have a '_' in front, because it'll end up being "__".
+ * "__" macros shoudln't be used. So, remove all of the
+ * '_' characters from the front.
+ */
+ if (*guard == '_') {
+ for (tmp = guard; *tmp == '_'; ++tmp)
+ ;
+ strcpy(guard, tmp);
+ }
+ tmp = guard;
+ guard = extendfile(guard, "_H_RPCGEN");
+ free(tmp);
+ return (guard);
+}
+
+/*
+ * Compile into an XDR header file
+ */
+
+
+static void
+h_output(const char *infile, const char *define, int extend, const char *outfile, int headeronly)
+{
+ definition *def;
+ const char *outfilename;
+ long tell;
+ const char *guard;
+ list *l;
+ xdrfunc *xdrfuncp;
+ void *tmp = NULL;
+
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ open_output(infile, outfilename);
+ add_warning();
+ if (outfilename || infile){
+ guard = tmp = generate_guard(outfilename ? outfilename: infile);
+ } else
+ guard = "STDIN_";
+
+ f_print(fout, "#ifndef _%s\n#define _%s\n\n", guard,
+ guard);
+
+ f_print(fout, "#include <rpc/rpc.h>\n");
+
+ if (mtflag)
+ f_print(fout, "#include <pthread.h>\n");
+
+ /* put the C++ support */
+ if (!CCflag) {
+ f_print(fout, "\n#ifdef __cplusplus\n");
+ f_print(fout, "extern \"C\" {\n");
+ f_print(fout, "#endif\n\n");
+ }
+
+ /* put in a typedef for quadprecision. Only with Cflag */
+
+ tell = ftell(fout);
+
+ /* print data definitions */
+ while ( (def = get_definition()) ) {
+ print_datadef(def, headeronly);
+ }
+
+ /*
+ * print function declarations.
+ * Do this after data definitions because they might be used as
+ * arguments for functions
+ */
+ for (l = defined; l != NULL; l = l->next) {
+ print_funcdef(l->val, headeronly);
+ }
+ /* Now print all xdr func declarations */
+ if (xdrfunc_head != NULL){
+
+ f_print(fout,
+ "\n/* the xdr functions */\n");
+
+ if (CCflag){
+ f_print(fout, "\n#ifdef __cplusplus\n");
+ f_print(fout, "extern \"C\" {\n");
+ f_print(fout, "#endif\n");
+ }
+
+ xdrfuncp = xdrfunc_head;
+ while (xdrfuncp != NULL){
+ print_xdr_func_def(xdrfuncp->name, xdrfuncp->pointerp);
+ xdrfuncp = xdrfuncp->next;
+ }
+ }
+
+ if (extend && tell == ftell(fout)) {
+ (void) unlink(outfilename);
+ } else if (tblflag) {
+ f_print(fout, rpcgen_table_dcl);
+ }
+
+ f_print(fout, "\n#ifdef __cplusplus\n");
+ f_print(fout, "}\n");
+ f_print(fout, "#endif\n");
+
+ f_print(fout, "\n#endif /* !_%s */\n", guard);
+ free(tmp);
+}
+
+/*
+ * Compile into an RPC service
+ */
+static void
+s_output(int argc, const char *argv[], const char *infile, const char *define,
+ int extend, const char *outfile, int nomain, int netflag)
+{
+ char *include;
+ definition *def;
+ int foundprogram = 0;
+ const char *outfilename;
+
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ open_output(infile, outfilename);
+ add_warning();
+ if (infile && (include = extendfile(infile, ".h"))) {
+ f_print(fout, "#include \"%s\"\n", include);
+ free(include);
+ } else
+ f_print(fout, "#include <rpc/rpc.h>\n");
+
+ f_print(fout, "#include <stdio.h>\n");
+ f_print(fout, "#include <stdlib.h> /* getenv, exit */\n");
+ f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
+ f_print (fout, "#include <string.h> /* strcmp */\n");
+ if (tirpcflag)
+ f_print(fout, "#include <rpc/rpc_com.h>\n");
+ if (strcmp(svcclosetime, "-1") == 0)
+ indefinitewait = 1;
+ else if (strcmp(svcclosetime, "0") == 0)
+ exitnow = 1;
+ else if (inetdflag || pmflag) {
+ f_print(fout, "#include <signal.h>\n");
+ timerflag = 1;
+ }
+
+ if (!tirpcflag && inetdflag)
+ f_print(fout, "#include <sys/ttycom.h> /* TIOCNOTTY */\n");
+ if (inetdflag || pmflag) {
+ f_print(fout, "#ifdef __cplusplus\n");
+ f_print(fout,
+ "#include <sys/sysent.h> /* getdtablesize, open */\n");
+ f_print(fout, "#endif /* __cplusplus */\n");
+ }
+ if (tirpcflag) {
+ f_print(fout, "#include <fcntl.h> /* open */\n");
+ f_print(fout, "#include <unistd.h> /* fork / setsid */\n");
+ f_print(fout, "#include <sys/types.h>\n");
+ }
+
+ f_print(fout, "#include <string.h>\n");
+ if (inetdflag || !tirpcflag) {
+ f_print(fout, "#include <sys/socket.h>\n");
+ f_print(fout, "#include <netinet/in.h>\n");
+ }
+
+ if ((netflag || pmflag) && tirpcflag && !nomain) {
+ f_print(fout, "#include <netconfig.h>\n");
+ }
+ if (tirpcflag)
+ f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
+ if (logflag || inetdflag || pmflag || tirpcflag)
+ f_print(fout, "#include <syslog.h>\n");
+
+ f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
+ if (timerflag)
+ f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n",
+ svcclosetime);
+ while ( (def = get_definition()) ) {
+ foundprogram |= (def->def_kind == DEF_PROGRAM);
+ }
+ if (extend && !foundprogram) {
+ (void) unlink(outfilename);
+ return;
+ }
+ write_most(infile, netflag, nomain);
+ if (!nomain) {
+ if (!do_registers(argc, argv)) {
+ if (outfilename)
+ (void) unlink(outfilename);
+ usage();
+ }
+ write_rest();
+ }
+}
+
+/*
+ * generate client side stubs
+ */
+static void
+l_output(const char *infile, const char *define, int extend, const char *outfile)
+{
+ char *include;
+ definition *def;
+ int foundprogram = 0;
+ const char *outfilename;
+
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ open_output(infile, outfilename);
+ add_warning();
+ f_print (fout, "#include <string.h> /* for memset */\n");
+ if (infile && (include = extendfile(infile, ".h"))) {
+ f_print(fout, "#include \"%s\"\n", include);
+ free(include);
+ } else
+ f_print(fout, "#include <rpc/rpc.h>\n");
+ while ( (def = get_definition()) ) {
+ foundprogram |= (def->def_kind == DEF_PROGRAM);
+ }
+ if (extend && !foundprogram) {
+ (void) unlink(outfilename);
+ return;
+ }
+ write_stubs();
+}
+
+/*
+ * generate the dispatch table
+ */
+static void
+t_output(const char *infile, const char *define, int extend, const char *outfile)
+{
+ definition *def;
+ int foundprogram = 0;
+ const char *outfilename;
+
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ open_output(infile, outfilename);
+ add_warning();
+ while ( (def = get_definition()) ) {
+ foundprogram |= (def->def_kind == DEF_PROGRAM);
+ }
+ if (extend && !foundprogram) {
+ (void) unlink(outfilename);
+ return;
+ }
+ write_tables();
+}
+
+/* sample routine for the server template */
+static void
+svc_output(const char *infile, const char *define, int extend, const char *outfile)
+{
+ definition *def;
+ char *include;
+ const char *outfilename;
+ long tell;
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ checkfiles(infile, outfilename);
+ /*
+ * Check if outfile already exists.
+ * if so, print an error message and exit
+ */
+ open_output(infile, outfilename);
+ add_sample_msg();
+
+ if (infile && (include = extendfile(infile, ".h"))) {
+ f_print(fout, "#include \"%s\"\n", include);
+ free(include);
+ } else
+ f_print(fout, "#include <rpc/rpc.h>\n");
+
+ tell = ftell(fout);
+ while ( (def = get_definition()) ) {
+ write_sample_svc(def);
+ }
+ if (extend && tell == ftell(fout)) {
+ (void) unlink(outfilename);
+ }
+}
+
+/* sample main routine for client */
+static void
+clnt_output(const char *infile, const char *define, int extend, const char *outfile)
+{
+ definition *def;
+ char *include;
+ const char *outfilename;
+ long tell;
+ int has_program = 0;
+
+ open_input(infile, define);
+ outfilename = extend ? extendfile(infile, outfile) : outfile;
+ checkfiles(infile, outfilename);
+ /*
+ * Check if outfile already exists.
+ * if so, print an error message and exit
+ */
+
+ open_output(infile, outfilename);
+ add_sample_msg();
+ if (infile && (include = extendfile(infile, ".h"))) {
+ f_print(fout, "#include \"%s\"\n", include);
+ free(include);
+ } else
+ f_print(fout, "#include <rpc/rpc.h>\n");
+ f_print(fout, "#include <stdio.h>\n");
+ f_print(fout, "#include <stdlib.h>\n");
+ tell = ftell(fout);
+ while ( (def = get_definition()) ) {
+ has_program += write_sample_clnt(def);
+ }
+
+ if (has_program)
+ write_sample_clnt_main();
+
+ if (extend && tell == ftell(fout)) {
+ (void) unlink(outfilename);
+ }
+}
+
+
+static void mkfile_output(struct commandline *cmd)
+{
+ const char *mkfilename, *clientname, *clntname, *xdrname, *hdrname;
+ const char *servername, *svcname, *servprogname, *clntprogname;
+ char *temp, *mkftemp;
+
+ svcname = file_name(cmd->infile, "_svc.c");
+ clntname = file_name(cmd->infile, "_clnt.c");
+ xdrname = file_name(cmd->infile, "_xdr.c");
+ hdrname = file_name(cmd->infile, ".h");
+
+
+ if (allfiles){
+ servername = extendfile(cmd->infile, "_server.c");
+ clientname = extendfile(cmd->infile, "_client.c");
+ }else{
+ servername = " ";
+ clientname = " ";
+ }
+ servprogname = extendfile(cmd->infile, "_server");
+ clntprogname = extendfile(cmd->infile, "_client");
+
+ if (allfiles){
+ mkftemp = xmalloc(strlen("makefile.") +
+ strlen(cmd->infile) + 1);
+ temp = strrchr(cmd->infile, '.');
+ strcpy(mkftemp, "makefile.");
+ (void) strncat(mkftemp, cmd->infile,
+ (temp - cmd->infile));
+ mkfilename = mkftemp;
+ } else
+ mkfilename = cmd->outfile;
+
+
+ checkfiles(NULL, mkfilename);
+ open_output(NULL, mkfilename);
+
+ f_print(fout, "\n# This is a template makefile generated\
+ by rpcgen \n");
+
+ f_print(fout, "\n# Parameters \n\n");
+
+ f_print(fout, "CLIENT = %s\nSERVER = %s\n\n",
+ clntprogname, servprogname);
+ f_print(fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n");
+ f_print(fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n");
+ f_print(fout, "SOURCES.x = %s\n\n", cmd->infile);
+ f_print(fout, "TARGETS_SVC.c = %s %s %s \n",
+ svcname, servername, xdrname);
+ f_print(fout, "TARGETS_CLNT.c = %s %s %s \n",
+ clntname, clientname, xdrname);
+ f_print(fout, "TARGETS = %s %s %s %s %s %s\n\n",
+ hdrname, xdrname, clntname,
+ svcname, clientname, servername);
+
+ f_print(fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \
+$(TARGETS_CLNT.c:%%.c=%%.o) ");
+
+ f_print(fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \
+$(TARGETS_SVC.c:%%.c=%%.o) ");
+
+
+ f_print(fout, "\n# Compiler flags \n");
+ if (mtflag)
+ f_print(fout, "\nCFLAGS += -D_REENTRANT -D_THEAD_SAFE \nLDLIBS += -pthread\n");
+
+ f_print(fout, "RPCGENFLAGS = \n");
+
+ f_print(fout, "\n# Targets \n\n");
+
+ f_print(fout, "all : $(CLIENT) $(SERVER)\n\n");
+ f_print(fout, "$(TARGETS) : $(SOURCES.x) \n");
+ f_print(fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n");
+ if (allfiles) {
+ f_print(fout, "\trpcgen -Sc $(RPCGENFLAGS) $(SOURCES.x) -o %s\n\n", clientname);
+ f_print(fout, "\trpcgen -Ss $(RPCGENFLAGS) $(SOURCES.x) -o %s\n\n", servername);
+ }
+ f_print(fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \
+$(TARGETS_CLNT.c) \n\n");
+
+ f_print(fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \
+$(TARGETS_SVC.c) \n\n");
+ f_print(fout, "$(CLIENT) : $(OBJECTS_CLNT) \n");
+ f_print(fout, "\t$(CC) -o $(CLIENT) $(OBJECTS_CLNT) \
+$(LDLIBS) \n\n");
+ f_print(fout, "$(SERVER) : $(OBJECTS_SVC) \n");
+ f_print(fout, "\t$(CC) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n");
+ f_print(fout, "clean:\n\t rm -f core $(TARGETS) $(OBJECTS_CLNT) \
+$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n");
+}
+
+
+
+/*
+ * Perform registrations for service output
+ * Return 0 if failed; 1 otherwise.
+ */
+static int
+do_registers(int argc, const char *argv[])
+{
+ int i;
+
+ if (inetdflag || !tirpcflag) {
+ for (i = 1; i < argc; i++) {
+ if (streq(argv[i], "-s")) {
+ if (!check_nettype(argv[i + 1],
+ valid_i_nettypes))
+ return (0);
+ write_inetd_register(argv[i + 1]);
+ i++;
+ }
+ }
+ } else {
+ for (i = 1; i < argc; i++)
+ if (streq(argv[i], "-s")) {
+ if (!check_nettype(argv[i + 1],
+ valid_ti_nettypes))
+ return (0);
+ write_nettype_register(argv[i + 1]);
+ i++;
+ } else if (streq(argv[i], "-n")) {
+ write_netid_register(argv[i + 1]);
+ i++;
+ }
+ }
+ return (1);
+}
+
+/*
+ * Extend the argument list
+ */
+static void
+moreargs(void)
+{
+ char **newarglist;
+
+ argmax = argmax == 0 ? 32 : argmax << 1;
+ if (argmax > INT_MAX / 4) {
+ warnx("refusing to allocate too many arguments");
+ crash();
+ }
+ newarglist = realloc(arglist, argmax * sizeof(*arglist));
+ if (newarglist == NULL) {
+ warnx("unable to allocate arglist");
+ crash();
+ }
+ arglist = newarglist;
+}
+
+/*
+ * Add another argument to the arg list
+ */
+static void
+addarg(const char *cp)
+{
+ if (argcount >= argmax)
+ moreargs();
+
+ if (cp != NULL)
+ arglist[argcount++] = xstrdup(cp);
+ else
+ arglist[argcount++] = NULL;
+}
+
+/*
+ * Insert an argument at the specified location
+ */
+static void
+insarg(int place, const char *cp)
+{
+ int i;
+
+ if (argcount >= argmax)
+ moreargs();
+
+ /* Move up existing arguments */
+ for (i = argcount - 1; i >= place; i--)
+ arglist[i + 1] = arglist[i];
+
+ arglist[place] = xstrdup(cp);
+ argcount++;
+}
+
+/*
+ * if input file is stdin and an output file is specified then complain
+ * if the file already exists. Otherwise the file may get overwritten
+ * If input file does not exist, exit with an error
+ */
+
+static void
+checkfiles(const char *infile, const char *outfile)
+{
+
+ struct stat buf;
+
+ if (infile) /* infile ! = NULL */
+ if (stat(infile, &buf) < 0)
+ {
+ warn("%s", infile);
+ crash();
+ }
+ if (outfile) {
+ if (stat(outfile, &buf) < 0)
+ return; /* file does not exist */
+ else {
+ warnx("file '%s' already exists and may be overwritten", outfile);
+ crash();
+ }
+ }
+}
+
+/*
+ * Parse command line arguments
+ */
+static int
+parseargs(int argc, const char *argv[], struct commandline *cmd)
+{
+ int i;
+ int j;
+ char c, ch;
+ char flag[(1 << 8 * sizeof (char))];
+ int nflags;
+
+ cmd->infile = cmd->outfile = NULL;
+ if (argc < 2) {
+ return (0);
+ }
+ allfiles = 0;
+ flag['c'] = 0;
+ flag['h'] = 0;
+ flag['l'] = 0;
+ flag['m'] = 0;
+ flag['o'] = 0;
+ flag['s'] = 0;
+ flag['n'] = 0;
+ flag['t'] = 0;
+ flag['S'] = 0;
+ flag['C'] = 0;
+ flag['M'] = 0;
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ if (cmd->infile) {
+ warnx("cannot specify more than one input file");
+ return (0);
+ }
+ cmd->infile = argv[i];
+ } else {
+ for (j = 1; argv[i][j] != 0; j++) {
+ c = argv[i][j];
+ switch (c) {
+ case 'a':
+ allfiles = 1;
+ break;
+ case 'c':
+ case 'h':
+ case 'l':
+ case 'm':
+ case 't':
+ if (flag[(int)c]) {
+ return (0);
+ }
+ flag[(int)c] = 1;
+ break;
+ case 'S':
+ /*
+ * sample flag: Ss or Sc.
+ * Ss means set flag['S'];
+ * Sc means set flag['C'];
+ * Sm means set flag['M'];
+ */
+ ch = argv[i][++j]; /* get next char */
+ if (ch == 's')
+ ch = 'S';
+ else if (ch == 'c')
+ ch = 'C';
+ else if (ch == 'm')
+ ch = 'M';
+ else
+ return (0);
+
+ if (flag[(int)ch]) {
+ return (0);
+ }
+ flag[(int)ch] = 1;
+ break;
+ case 'C': /* ANSI C syntax */
+ ch = argv[i][j+1]; /* get next char */
+
+ if (ch != 'C')
+ break;
+ CCflag = 1;
+ break;
+ case 'b':
+ /*
+ * Turn TIRPC flag off for
+ * generating backward compatible
+ * code
+ */
+ tirpcflag = 0;
+ break;
+
+ case 'I':
+ inetdflag = 1;
+ break;
+ case 'N':
+ newstyle = 1;
+ break;
+ case 'L':
+ logflag = 1;
+ break;
+ case 'P':
+ pmflag = 1;
+ break;
+ case 'K':
+ if (++i == argc) {
+ return (0);
+ }
+ svcclosetime = argv[i];
+ goto nextarg;
+ case 'T':
+ tblflag = 1;
+ break;
+ case 'M':
+ mtflag = 1;
+ break;
+ case 'i' :
+ if (++i == argc) {
+ return (0);
+ }
+ inline_size = atoi(argv[i]);
+ goto nextarg;
+ case 'n':
+ case 'o':
+ case 's':
+ if (argv[i][j - 1] != '-' ||
+ argv[i][j + 1] != 0) {
+ return (0);
+ }
+ flag[(int)c] = 1;
+ if (++i == argc) {
+ return (0);
+ }
+ if (c == 'o') {
+ if (cmd->outfile) {
+ return (0);
+ }
+ cmd->outfile = argv[i];
+ }
+ goto nextarg;
+ case 'D':
+ if (argv[i][j - 1] != '-') {
+ return (0);
+ }
+ (void) addarg(argv[i]);
+ goto nextarg;
+ case 'Y':
+ if (++i == argc) {
+ return (0);
+ }
+ if (strlcpy(pathbuf, argv[i],
+ sizeof(pathbuf)) >= sizeof(pathbuf)
+ || strlcat(pathbuf, "/cpp",
+ sizeof(pathbuf)) >=
+ sizeof(pathbuf)) {
+ warnx("argument too long");
+ return (0);
+ }
+ CPP = pathbuf;
+ goto nextarg;
+
+
+
+ default:
+ return (0);
+ }
+ }
+ nextarg:
+ ;
+ }
+ }
+
+ cmd->cflag = flag['c'];
+ cmd->hflag = flag['h'];
+ cmd->lflag = flag['l'];
+ cmd->mflag = flag['m'];
+ cmd->nflag = flag['n'];
+ cmd->sflag = flag['s'];
+ cmd->tflag = flag['t'];
+ cmd->Ssflag = flag['S'];
+ cmd->Scflag = flag['C'];
+ cmd->makefileflag = flag['M'];
+
+ if (tirpcflag) {
+ if (inetdflag)
+ pmflag = 0;
+ if ((inetdflag && cmd->nflag)) {
+ /* netid not allowed with inetdflag */
+ warnx("cannot use netid flag with inetd flag");
+ return (0);
+ }
+ } else { /* 4.1 mode */
+ pmflag = 0; /* set pmflag only in tirpcmode */
+ if (cmd->nflag) { /* netid needs TIRPC */
+ warnx("cannot use netid flag without TIRPC");
+ return (0);
+ }
+ }
+
+ if (newstyle && (tblflag || cmd->tflag)) {
+ warnx("cannot use table flags with newstyle");
+ return (0);
+ }
+
+ /* check no conflicts with file generation flags */
+ nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
+ cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag +
+ cmd->Scflag + cmd->makefileflag;
+
+ if (nflags == 0) {
+ if (cmd->outfile != NULL || cmd->infile == NULL) {
+ return (0);
+ }
+ } else if (cmd->infile == NULL &&
+ (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) {
+ warnx("\"infile\" is required for template generation flags");
+ return (0);
+ } if (nflags > 1) {
+ warnx("cannot have more than one file generation flag");
+ return (0);
+ }
+ return (1);
+}
+
+static void
+usage(void)
+{
+ f_print(stderr, "%s\n%s\n%s\n%s\n%s\n",
+ "usage: rpcgen infile",
+ " rpcgen [-abCLNTM] [-Dname[=value]] [-i size]\
+[-I -P [-K seconds]] [-Y path] infile",
+ " rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm]\
+[-o outfile] [infile]",
+ " rpcgen [-s nettype]* [-o outfile] [infile]",
+ " rpcgen [-n netid]* [-o outfile] [infile]");
+ options_usage();
+ exit(1);
+}
+
+static void
+options_usage(void)
+{
+ f_print(stderr, "options:\n");
+ f_print(stderr, "-a\t\tgenerate all files, including samples\n");
+ f_print(stderr, "-b\t\tbackward compatibility mode (generates code \
+for FreeBSD 4.X)\n");
+ f_print(stderr, "-c\t\tgenerate XDR routines\n");
+ f_print(stderr, "-C\t\tANSI C mode\n");
+ f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
+ f_print(stderr, "-h\t\tgenerate header file\n");
+ f_print(stderr, "-i size\t\tsize at which to start generating\
+inline code\n");
+ f_print(stderr, "-I\t\tgenerate code for inetd support in server\n");
+ f_print(stderr, "-K seconds\tserver exits after K seconds of\
+inactivity\n");
+ f_print(stderr, "-l\t\tgenerate client side stubs\n");
+ f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
+ f_print(stderr, "-m\t\tgenerate server side stubs\n");
+ f_print(stderr, "-M\t\tgenerate MT-safe code\n");
+ f_print(stderr, "-n netid\tgenerate server code that supports\
+named netid\n");
+ f_print(stderr, "-N\t\tsupports multiple arguments and\
+call-by-value\n");
+ f_print(stderr, "-o outfile\tname of the output file\n");
+ f_print(stderr, "-P\t\tgenerate code for port monitoring support in server\n");
+ f_print(stderr, "-s nettype\tgenerate server code that supports named\
+nettype\n");
+ f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote\
+procedures\n");
+ f_print(stderr, "-Ss\t\tgenerate sample server code that defines\
+remote procedures\n");
+ f_print(stderr, "-Sm \t\tgenerate makefile template \n");
+
+ f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
+ f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
+ f_print(stderr, "-Y path\t\tpath where cpp is found\n");
+ exit(1);
+}
diff --git a/usr.bin/rpcgen/rpc_parse.c b/usr.bin/rpcgen/rpc_parse.c
new file mode 100644
index 000000000000..8fa84230beb2
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_parse.c
@@ -0,0 +1,620 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_parse.c, Parser for the RPC protocol compiler
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+#define ARGNAME "arg"
+
+static void isdefined( definition * );
+static void def_struct( definition * );
+static void def_program( definition * );
+static void def_enum( definition * );
+static void def_const( definition * );
+static void def_union( definition * );
+static void def_typedef( definition * );
+static void get_declaration( declaration *, defkind );
+static void get_prog_declaration( declaration *, defkind, int );
+static void get_type(const char **, const char **, defkind);
+static void unsigned_dec(const char ** );
+
+/*
+ * return the next definition you see
+ */
+definition *
+get_definition(void)
+{
+ definition *defp;
+ token tok;
+
+ defp = XALLOC(definition);
+ get_token(&tok);
+ switch (tok.kind) {
+ case TOK_STRUCT:
+ def_struct(defp);
+ break;
+ case TOK_UNION:
+ def_union(defp);
+ break;
+ case TOK_TYPEDEF:
+ def_typedef(defp);
+ break;
+ case TOK_ENUM:
+ def_enum(defp);
+ break;
+ case TOK_PROGRAM:
+ def_program(defp);
+ break;
+ case TOK_CONST:
+ def_const(defp);
+ break;
+ case TOK_EOF:
+ free(defp);
+ return (NULL);
+ default:
+ error("definition keyword expected");
+ }
+ scan(TOK_SEMICOLON, &tok);
+ isdefined(defp);
+ return (defp);
+}
+
+static void
+isdefined(definition *defp)
+{
+ STOREVAL(&defined, defp);
+}
+
+static void
+def_struct(definition *defp)
+{
+ token tok;
+ declaration dec;
+ decl_list *decls;
+ decl_list **tailp;
+
+ defp->def_kind = DEF_STRUCT;
+
+ scan(TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan(TOK_LBRACE, &tok);
+ tailp = &defp->def.st.decls;
+ do {
+ get_declaration(&dec, DEF_STRUCT);
+ decls = XALLOC(decl_list);
+ decls->decl = dec;
+ *tailp = decls;
+ tailp = &decls->next;
+ scan(TOK_SEMICOLON, &tok);
+ peek(&tok);
+ } while (tok.kind != TOK_RBRACE);
+ get_token(&tok);
+ *tailp = NULL;
+}
+
+static void
+def_program(definition *defp)
+{
+ token tok;
+ declaration dec;
+ decl_list *decls;
+ decl_list **tailp;
+ version_list *vlist;
+ version_list **vtailp;
+ proc_list *plist;
+ proc_list **ptailp;
+ int num_args;
+ bool_t isvoid = FALSE; /* whether first argument is void */
+ defp->def_kind = DEF_PROGRAM;
+ scan(TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan(TOK_LBRACE, &tok);
+ vtailp = &defp->def.pr.versions;
+ tailp = &defp->def.st.decls;
+ scan(TOK_VERSION, &tok);
+ do {
+ scan(TOK_IDENT, &tok);
+ vlist = XALLOC(version_list);
+ vlist->vers_name = tok.str;
+ scan(TOK_LBRACE, &tok);
+ ptailp = &vlist->procs;
+ do {
+ /* get result type */
+ plist = XALLOC(proc_list);
+ get_type(&plist->res_prefix, &plist->res_type,
+ DEF_PROGRAM);
+ if (streq(plist->res_type, "opaque")) {
+ error("illegal result type");
+ }
+ scan(TOK_IDENT, &tok);
+ plist->proc_name = tok.str;
+ scan(TOK_LPAREN, &tok);
+ /* get args - first one */
+ num_args = 1;
+ isvoid = FALSE;
+ /*
+ * type of DEF_PROGRAM in the first
+ * get_prog_declaration and DEF_STURCT in the next
+ * allows void as argument if it is the only argument
+ */
+ get_prog_declaration(&dec, DEF_PROGRAM, num_args);
+ if (streq(dec.type, "void"))
+ isvoid = TRUE;
+ decls = XALLOC(decl_list);
+ plist->args.decls = decls;
+ decls->decl = dec;
+ tailp = &decls->next;
+ /* get args */
+ while (peekscan(TOK_COMMA, &tok)) {
+ num_args++;
+ get_prog_declaration(&dec, DEF_STRUCT,
+ num_args);
+ decls = XALLOC(decl_list);
+ decls->decl = dec;
+ *tailp = decls;
+ if (streq(dec.type, "void"))
+ isvoid = TRUE;
+ tailp = &decls->next;
+ }
+ /* multiple arguments are only allowed in newstyle */
+ if (!newstyle && num_args > 1) {
+ error("only one argument is allowed");
+ }
+ if (isvoid && num_args > 1) {
+ error("illegal use of void in program definition");
+ }
+ *tailp = NULL;
+ scan(TOK_RPAREN, &tok);
+ scan(TOK_EQUAL, &tok);
+ scan_num(&tok);
+ scan(TOK_SEMICOLON, &tok);
+ plist->proc_num = tok.str;
+ plist->arg_num = num_args;
+ *ptailp = plist;
+ ptailp = &plist->next;
+ peek(&tok);
+ } while (tok.kind != TOK_RBRACE);
+ *ptailp = NULL;
+ *vtailp = vlist;
+ vtailp = &vlist->next;
+ scan(TOK_RBRACE, &tok);
+ scan(TOK_EQUAL, &tok);
+ scan_num(&tok);
+ vlist->vers_num = tok.str;
+ /* make the argument structure name for each arg */
+ for (plist = vlist->procs; plist != NULL;
+ plist = plist->next) {
+ plist->args.argname = make_argname(plist->proc_name,
+ vlist->vers_num);
+ /* free the memory ?? */
+ }
+ scan(TOK_SEMICOLON, &tok);
+ scan2(TOK_VERSION, TOK_RBRACE, &tok);
+ } while (tok.kind == TOK_VERSION);
+ scan(TOK_EQUAL, &tok);
+ scan_num(&tok);
+ defp->def.pr.prog_num = tok.str;
+ *vtailp = NULL;
+}
+
+
+static void
+def_enum(definition *defp)
+{
+ token tok;
+ enumval_list *elist;
+ enumval_list **tailp;
+
+ defp->def_kind = DEF_ENUM;
+ scan(TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan(TOK_LBRACE, &tok);
+ tailp = &defp->def.en.vals;
+ do {
+ scan(TOK_IDENT, &tok);
+ elist = XALLOC(enumval_list);
+ elist->name = tok.str;
+ elist->assignment = NULL;
+ scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
+ if (tok.kind == TOK_EQUAL) {
+ scan_num(&tok);
+ elist->assignment = tok.str;
+ scan2(TOK_COMMA, TOK_RBRACE, &tok);
+ }
+ *tailp = elist;
+ tailp = &elist->next;
+ } while (tok.kind != TOK_RBRACE);
+ *tailp = NULL;
+}
+
+static void
+def_const(definition *defp)
+{
+ token tok;
+
+ defp->def_kind = DEF_CONST;
+ scan(TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan(TOK_EQUAL, &tok);
+ scan2(TOK_IDENT, TOK_STRCONST, &tok);
+ defp->def.co = tok.str;
+}
+
+static void
+def_union(definition *defp)
+{
+ token tok;
+ declaration dec;
+ case_list *cases;
+ case_list **tailp;
+
+ defp->def_kind = DEF_UNION;
+ scan(TOK_IDENT, &tok);
+ defp->def_name = tok.str;
+ scan(TOK_SWITCH, &tok);
+ scan(TOK_LPAREN, &tok);
+ get_declaration(&dec, DEF_UNION);
+ defp->def.un.enum_decl = dec;
+ tailp = &defp->def.un.cases;
+ scan(TOK_RPAREN, &tok);
+ scan(TOK_LBRACE, &tok);
+ scan(TOK_CASE, &tok);
+ while (tok.kind == TOK_CASE) {
+ scan2(TOK_IDENT, TOK_CHARCONST, &tok);
+ cases = XALLOC(case_list);
+ cases->case_name = tok.str;
+ scan(TOK_COLON, &tok);
+ /* now peek at next token */
+ if (peekscan(TOK_CASE, &tok)){
+ do {
+ scan2(TOK_IDENT, TOK_CHARCONST, &tok);
+ cases->contflag = 1;
+ /* continued case statement */
+ *tailp = cases;
+ tailp = &cases->next;
+ cases = XALLOC(case_list);
+ cases->case_name = tok.str;
+ scan(TOK_COLON, &tok);
+ } while (peekscan(TOK_CASE, &tok));
+ }
+
+ get_declaration(&dec, DEF_UNION);
+ cases->case_decl = dec;
+ cases->contflag = 0; /* no continued case statement */
+ *tailp = cases;
+ tailp = &cases->next;
+ scan(TOK_SEMICOLON, &tok);
+
+ scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
+ }
+ *tailp = NULL;
+ if (tok.kind == TOK_DEFAULT) {
+ scan(TOK_COLON, &tok);
+ get_declaration(&dec, DEF_UNION);
+ defp->def.un.default_decl = XALLOC(declaration);
+ *defp->def.un.default_decl = dec;
+ scan(TOK_SEMICOLON, &tok);
+ scan(TOK_RBRACE, &tok);
+ } else {
+ defp->def.un.default_decl = NULL;
+ }
+}
+
+static const char *reserved_words[] =
+{
+ "array",
+ "bytes",
+ "destroy",
+ "free",
+ "getpos",
+ "inline",
+ "pointer",
+ "reference",
+ "setpos",
+ "sizeof",
+ "union",
+ "vector",
+ NULL
+ };
+
+static const char *reserved_types[] =
+{
+ "opaque",
+ "string",
+ NULL
+ };
+
+/*
+ * check that the given name is not one that would eventually result in
+ * xdr routines that would conflict with internal XDR routines.
+ */
+static void
+check_type_name(const char *name, int new_type)
+{
+ int i;
+ char tmp[100];
+
+ for (i = 0; reserved_words[i] != NULL; i++) {
+ if (strcmp(name, reserved_words[i]) == 0) {
+ sprintf(tmp,
+ "illegal (reserved) name :\'%s\' in type definition",
+ name);
+ error(tmp);
+ }
+ }
+ if (new_type) {
+ for (i = 0; reserved_types[i] != NULL; i++) {
+ if (strcmp(name, reserved_types[i]) == 0) {
+ sprintf(tmp,
+ "illegal (reserved) name :\'%s\' in type definition",
+ name);
+ error(tmp);
+ }
+ }
+ }
+}
+
+
+
+static void
+def_typedef(definition *defp)
+{
+ declaration dec;
+
+ defp->def_kind = DEF_TYPEDEF;
+ get_declaration(&dec, DEF_TYPEDEF);
+ defp->def_name = dec.name;
+ check_type_name(dec.name, 1);
+ defp->def.ty.old_prefix = dec.prefix;
+ defp->def.ty.old_type = dec.type;
+ defp->def.ty.rel = dec.rel;
+ defp->def.ty.array_max = dec.array_max;
+}
+
+static void
+get_declaration(declaration *dec, defkind dkind)
+{
+ token tok;
+
+ get_type(&dec->prefix, &dec->type, dkind);
+ dec->rel = REL_ALIAS;
+ if (streq(dec->type, "void")) {
+ return;
+ }
+
+ check_type_name(dec->type, 0);
+ scan2(TOK_STAR, TOK_IDENT, &tok);
+ if (tok.kind == TOK_STAR) {
+ dec->rel = REL_POINTER;
+ scan(TOK_IDENT, &tok);
+ }
+ dec->name = tok.str;
+ if (peekscan(TOK_LBRACKET, &tok)) {
+ if (dec->rel == REL_POINTER) {
+ error("no array-of-pointer declarations -- use typedef");
+ }
+ dec->rel = REL_VECTOR;
+ scan_num(&tok);
+ dec->array_max = tok.str;
+ scan(TOK_RBRACKET, &tok);
+ } else if (peekscan(TOK_LANGLE, &tok)) {
+ if (dec->rel == REL_POINTER) {
+ error("no array-of-pointer declarations -- use typedef");
+ }
+ dec->rel = REL_ARRAY;
+ if (peekscan(TOK_RANGLE, &tok)) {
+ dec->array_max = "~0"; /* unspecified size, use max */
+ } else {
+ scan_num(&tok);
+ dec->array_max = tok.str;
+ scan(TOK_RANGLE, &tok);
+ }
+ }
+ if (streq(dec->type, "opaque")) {
+ if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
+ error("array declaration expected");
+ }
+ } else if (streq(dec->type, "string")) {
+ if (dec->rel != REL_ARRAY) {
+ error("variable-length array declaration expected");
+ }
+ }
+}
+
+
+static void
+get_prog_declaration(declaration *dec, defkind dkind, int num)
+{
+ token tok;
+ char name[10]; /* argument name */
+
+ if (dkind == DEF_PROGRAM) {
+ peek(&tok);
+ if (tok.kind == TOK_RPAREN) { /* no arguments */
+ dec->rel = REL_ALIAS;
+ dec->type = "void";
+ dec->prefix = NULL;
+ dec->name = NULL;
+ return;
+ }
+ }
+ get_type(&dec->prefix, &dec->type, dkind);
+ dec->rel = REL_ALIAS;
+ if (peekscan(TOK_IDENT, &tok)) /* optional name of argument */
+ strcpy(name, tok.str);
+ else
+ sprintf(name, "%s%d", ARGNAME, num);
+ /* default name of argument */
+
+ dec->name = (char *) xstrdup(name);
+ if (streq(dec->type, "void")) {
+ return;
+ }
+
+ if (streq(dec->type, "opaque")) {
+ error("opaque -- illegal argument type");
+ }
+ if (peekscan(TOK_STAR, &tok)) {
+ if (streq(dec->type, "string")) {
+ error("pointer to string not allowed in program arguments");
+ }
+ dec->rel = REL_POINTER;
+ if (peekscan(TOK_IDENT, &tok)) {
+ /* optional name of argument */
+ dec->name = xstrdup(tok.str);
+ }
+ }
+ if (peekscan(TOK_LANGLE, &tok)) {
+ if (!streq(dec->type, "string")) {
+ error("arrays cannot be declared as arguments to procedures -- use typedef");
+ }
+ dec->rel = REL_ARRAY;
+ if (peekscan(TOK_RANGLE, &tok)) {
+ dec->array_max = "~0";
+ /* unspecified size, use max */
+ } else {
+ scan_num(&tok);
+ dec->array_max = tok.str;
+ scan(TOK_RANGLE, &tok);
+ }
+ }
+ if (streq(dec->type, "string")) {
+ if (dec->rel != REL_ARRAY) {
+ /*
+ * .x specifies just string as
+ * type of argument
+ * - make it string<>
+ */
+ dec->rel = REL_ARRAY;
+ dec->array_max = "~0"; /* unspecified size, use max */
+ }
+ }
+}
+
+
+
+static void
+get_type(const char **prefixp, const char **typep, defkind dkind)
+{
+ token tok;
+
+ *prefixp = NULL;
+ get_token(&tok);
+ switch (tok.kind) {
+ case TOK_IDENT:
+ *typep = tok.str;
+ break;
+ case TOK_STRUCT:
+ case TOK_ENUM:
+ case TOK_UNION:
+ *prefixp = tok.str;
+ scan(TOK_IDENT, &tok);
+ *typep = tok.str;
+ break;
+ case TOK_UNSIGNED:
+ unsigned_dec(typep);
+ break;
+ case TOK_SHORT:
+ *typep = "short";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_LONG:
+ *typep = "long";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_HYPER:
+ *typep = "int64_t";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+
+ case TOK_VOID:
+ if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
+ error("voids allowed only inside union and program definitions with one argument");
+ }
+ *typep = tok.str;
+ break;
+ case TOK_STRING:
+ case TOK_OPAQUE:
+ case TOK_CHAR:
+ case TOK_INT:
+ case TOK_FLOAT:
+ case TOK_DOUBLE:
+ case TOK_BOOL:
+ case TOK_QUAD:
+ *typep = tok.str;
+ break;
+ default:
+ error("expected type specifier");
+ }
+}
+
+static void
+unsigned_dec(const char **typep)
+{
+ token tok;
+
+ peek(&tok);
+ switch (tok.kind) {
+ case TOK_CHAR:
+ get_token(&tok);
+ *typep = "u_char";
+ break;
+ case TOK_SHORT:
+ get_token(&tok);
+ *typep = "u_short";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_LONG:
+ get_token(&tok);
+ *typep = "u_long";
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_HYPER:
+ get_token(&tok);
+ *typep = "u_int64_t";
+
+ (void) peekscan(TOK_INT, &tok);
+ break;
+ case TOK_INT:
+ get_token(&tok);
+ *typep = "u_int";
+ break;
+ default:
+ *typep = "u_int";
+ break;
+ }
+}
diff --git a/usr.bin/rpcgen/rpc_parse.h b/usr.bin/rpcgen/rpc_parse.h
new file mode 100644
index 000000000000..91b648c8bb9f
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_parse.h
@@ -0,0 +1,195 @@
+/*
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
+/* The copyright notice above does not evidence any */
+/* actual or intended publication of such source code. */
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+* PROPRIETARY NOTICE (Combined)
+*
+* This source code is unpublished proprietary information
+* constituting, or derived under license from AT&T's UNIX(r) System V.
+* In addition, portions of such source code were derived from Berkeley
+* 4.3 BSD under license from the Regents of the University of
+* California.
+*
+*
+*
+* Copyright Notice
+*
+* Notice of copyright on this source code product does not indicate
+* publication.
+*
+* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
+* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
+* All rights reserved.
+*/
+
+/*
+ * rpc_parse.h, Definitions for the RPCL parser
+ */
+
+enum defkind {
+ DEF_CONST,
+ DEF_STRUCT,
+ DEF_UNION,
+ DEF_ENUM,
+ DEF_TYPEDEF,
+ DEF_PROGRAM
+};
+typedef enum defkind defkind;
+
+typedef const char *const_def;
+
+enum relation {
+ REL_VECTOR, /* fixed length array */
+ REL_ARRAY, /* variable length array */
+ REL_POINTER, /* pointer */
+ REL_ALIAS, /* simple */
+};
+typedef enum relation relation;
+
+struct typedef_def {
+ const char *old_prefix;
+ const char *old_type;
+ relation rel;
+ const char *array_max;
+};
+typedef struct typedef_def typedef_def;
+
+struct enumval_list {
+ const char *name;
+ const char *assignment;
+ struct enumval_list *next;
+};
+typedef struct enumval_list enumval_list;
+
+struct enum_def {
+ enumval_list *vals;
+};
+typedef struct enum_def enum_def;
+
+struct declaration {
+ const char *prefix;
+ const char *type;
+ const char *name;
+ relation rel;
+ const char *array_max;
+};
+typedef struct declaration declaration;
+
+struct decl_list {
+ declaration decl;
+ struct decl_list *next;
+};
+typedef struct decl_list decl_list;
+
+struct struct_def {
+ decl_list *decls;
+};
+typedef struct struct_def struct_def;
+
+struct case_list {
+ const char *case_name;
+ int contflag;
+ declaration case_decl;
+ struct case_list *next;
+};
+typedef struct case_list case_list;
+
+struct union_def {
+ declaration enum_decl;
+ case_list *cases;
+ declaration *default_decl;
+};
+typedef struct union_def union_def;
+
+struct arg_list {
+ char *argname; /* name of struct for arg*/
+ decl_list *decls;
+};
+
+typedef struct arg_list arg_list;
+
+struct proc_list {
+ const char *proc_name;
+ const char *proc_num;
+ arg_list args;
+ int arg_num;
+ const char *res_type;
+ const char *res_prefix;
+ struct proc_list *next;
+};
+typedef struct proc_list proc_list;
+
+struct version_list {
+ const char *vers_name;
+ const char *vers_num;
+ proc_list *procs;
+ struct version_list *next;
+};
+typedef struct version_list version_list;
+
+struct program_def {
+ const char *prog_num;
+ version_list *versions;
+};
+typedef struct program_def program_def;
+
+struct definition {
+ const char *def_name;
+ defkind def_kind;
+ union {
+ const_def co;
+ struct_def st;
+ union_def un;
+ enum_def en;
+ typedef_def ty;
+ program_def pr;
+ } def;
+};
+typedef struct definition definition;
+
+definition *get_definition(void);
+
+
+struct bas_type
+{
+ const char *name;
+ int length;
+ struct bas_type *next;
+};
+
+typedef struct bas_type bas_type;
diff --git a/usr.bin/rpcgen/rpc_sample.c b/usr.bin/rpcgen/rpc_sample.c
new file mode 100644
index 000000000000..783fb0d01031
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_sample.c
@@ -0,0 +1,289 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+
+static char RQSTP[] = "rqstp";
+
+static void write_sample_client(const char *, version_list * );
+static void write_sample_server( definition * );
+static void return_type( proc_list * );
+
+void
+write_sample_svc(definition *def)
+{
+
+ if (def->def_kind != DEF_PROGRAM)
+ return;
+ write_sample_server(def);
+}
+
+
+int
+write_sample_clnt(definition *def)
+{
+ version_list *vp;
+ int count = 0;
+
+ if (def->def_kind != DEF_PROGRAM)
+ return(0);
+ /* generate sample code for each version */
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ write_sample_client(def->def_name, vp);
+ ++count;
+ }
+ return(count);
+}
+
+
+static void
+write_sample_client(const char *program_name, version_list *vp)
+{
+ proc_list *proc;
+ int i;
+ decl_list *l;
+
+ f_print(fout, "\n\nvoid\n");
+ pvname(program_name, vp->vers_num);
+ f_print(fout, "(char *host)\n{\n");
+ f_print(fout, "\tCLIENT *clnt;\n");
+
+ i = 0;
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ f_print(fout, "\t");
+ if (mtflag) {
+ f_print(fout, "enum clnt_stat retval_%d;\n\t", ++i);
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "result_%d;\n", i);
+ } else {
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, " *result_%d;\n",++i);
+ }
+ /* print out declarations for arguments */
+ if(proc->arg_num < 2 && !newstyle) {
+ f_print(fout, "\t");
+ if(!streq(proc->args.decls->decl.type, "void"))
+ ptype(proc->args.decls->decl.prefix,
+ proc->args.decls->decl.type, 1);
+ else
+ f_print(fout, "char * "); /* cannot have "void" type */
+ f_print(fout, " ");
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_arg;\n");
+ } else if (!streq(proc->args.decls->decl.type, "void")) {
+ for (l = proc->args.decls; l != NULL; l = l->next) {
+ f_print(fout, "\t");
+ ptype(l->decl.prefix, l->decl.type, 1);
+ if (strcmp(l->decl.type,"string") >= 1)
+ f_print(fout, " ");
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_%s;\n", l->decl.name);
+ }
+ }
+ }
+
+ /* generate creation of client handle */
+ f_print(fout, "\n#ifndef\tDEBUG\n");
+ f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
+ program_name, vp->vers_name, tirpcflag? "netpath" : "udp");
+ f_print(fout, "\tif (clnt == (CLIENT *) NULL) {\n");
+ f_print(fout, "\t\tclnt_pcreateerror(host);\n");
+ f_print(fout, "\t\texit(1);\n\t}\n");
+ f_print(fout, "#endif\t/* DEBUG */\n\n");
+
+ /* generate calls to procedures */
+ i = 0;
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ if (mtflag)
+ f_print(fout, "\tretval_%d = ",++i);
+ else
+ f_print(fout, "\tresult_%d = ",++i);
+ pvname(proc->proc_name, vp->vers_num);
+ if (proc->arg_num < 2 && !newstyle) {
+ f_print(fout, "(");
+ if(streq(proc->args.decls->decl.type, "void"))
+ /* cast to void * */
+ f_print(fout, "(void *)");
+ f_print(fout, "&");
+ pvname(proc->proc_name, vp->vers_num);
+ if (mtflag)
+ f_print(fout, "_arg, &result_%d, clnt);\n",
+ i);
+ else
+ f_print(fout, "_arg, clnt);\n");
+
+ } else if (streq(proc->args.decls->decl.type, "void")) {
+ if (mtflag)
+ f_print(fout, "(&result_%d, clnt);\n", i);
+ else
+ f_print(fout, "(clnt);\n");
+ }
+ else {
+ f_print(fout, "(");
+ for (l = proc->args.decls; l != NULL; l = l->next) {
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_%s, ", l->decl.name);
+ }
+ if (mtflag)
+ f_print(fout, "&result_%d, ", i);
+
+ f_print(fout, "clnt);\n");
+ }
+ if (mtflag) {
+ f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n", i);
+
+ } else {
+ f_print(fout, "\tif (result_%d == (", i);
+ ptype(proc->res_prefix, proc->res_type, 1);
+ f_print(fout, "*) NULL) {\n");
+ }
+ f_print(fout, "\t\tclnt_perror(clnt, \"call failed\");\n");
+ f_print(fout, "\t}\n");
+ }
+
+ f_print(fout, "#ifndef\tDEBUG\n");
+ f_print(fout, "\tclnt_destroy(clnt);\n");
+ f_print(fout, "#endif\t /* DEBUG */\n");
+ f_print(fout, "}\n");
+}
+
+static void
+write_sample_server(definition *def)
+{
+ version_list *vp;
+ proc_list *proc;
+
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ f_print(fout, "\n");
+ if (!mtflag) {
+ return_type(proc);
+ f_print(fout, "*\n");
+ } else
+ f_print(fout, "bool_t\n");
+ pvname_svc(proc->proc_name, vp->vers_num);
+ printarglist(proc, "result", RQSTP, "struct svc_req *");
+
+ f_print(fout, "{\n");
+ if (!mtflag) {
+ f_print(fout, "\tstatic ");
+ if(!streq(proc->res_type, "void"))
+ return_type(proc);
+ else
+ f_print(fout, "char *");
+ /* cannot have void type */
+ f_print(fout, " result;\n");
+ }
+ else
+ f_print(fout, "\tbool_t retval;\n");
+ f_print(fout,
+ "\n\t/*\n\t * insert server code here\n\t */\n\n");
+
+ if (!mtflag)
+ if(!streq(proc->res_type, "void"))
+ f_print(fout, "\treturn (&result);\n}\n");
+ else /* cast back to void * */
+ f_print(fout, "\treturn((void *) &result);\n}\n");
+ else
+ f_print(fout, "\treturn (retval);\n}\n");
+ }
+ /* put in sample freeing routine */
+ if (mtflag) {
+ f_print(fout, "\nint\n");
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout,"_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n");
+ f_print(fout, "{\n");
+ f_print(fout, "\t(void) xdr_free(xdr_result, result);\n");
+ f_print(fout,
+ "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n");
+ f_print(fout, "\n}\n");
+
+
+ }
+ }
+}
+
+
+
+static void
+return_type(proc_list *plist)
+{
+ ptype(plist->res_prefix, plist->res_type, 1);
+}
+
+void
+add_sample_msg(void)
+{
+ f_print(fout, "/*\n");
+ f_print(fout, " * This is sample code generated by rpcgen.\n");
+ f_print(fout, " * These are only templates and you can use them\n");
+ f_print(fout, " * as a guideline for developing your own functions.\n");
+ f_print(fout, " */\n\n");
+}
+
+void
+write_sample_clnt_main(void)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+
+ f_print(fout, "\n\n");
+ f_print(fout, "int\n");
+ f_print(fout, "main(int argc, char *argv[])\n{\n");
+
+ f_print(fout, "\tchar *host;");
+ f_print(fout, "\n\n\tif (argc < 2) {");
+ f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n");
+ f_print(fout, "\t\texit(1);\n\t}");
+ f_print(fout, "\n\thost = argv[1];\n");
+
+ for (l = defined; l != NULL; l = l->next) {
+ def = l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ continue;
+ }
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout, "\t");
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout, "(host);\n");
+ }
+ }
+ f_print(fout, "}\n");
+}
diff --git a/usr.bin/rpcgen/rpc_scan.c b/usr.bin/rpcgen/rpc_scan.c
new file mode 100644
index 000000000000..d805a1f983a5
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_scan.c
@@ -0,0 +1,488 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_scan.c, Scanner for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+#define startcomment(where) (where[0] == '/' && where[1] == '*')
+#define endcomment(where) (where[-1] == '*' && where[0] == '/')
+
+static int pushed = 0; /* is a token pushed */
+static token lasttok; /* last token, if pushed */
+
+static void unget_token( token * );
+static void findstrconst(char **, const char **);
+static void findchrconst(char **, const char **);
+static void findconst(char **, const char **);
+static void findkind( char **, token * );
+static int cppline( char * );
+static int directive( char * );
+static void printdirective( char * );
+static void docppline(char *, int *, const char **);
+
+/*
+ * scan expecting 1 given token
+ */
+void
+scan(tok_kind expect, token *tokp)
+{
+ get_token(tokp);
+ if (tokp->kind != expect) {
+ expected1(expect);
+ }
+}
+
+/*
+ * scan expecting any of the 2 given tokens
+ */
+void
+scan2(tok_kind expect1, tok_kind expect2, token *tokp)
+{
+ get_token(tokp);
+ if (tokp->kind != expect1 && tokp->kind != expect2) {
+ expected2(expect1, expect2);
+ }
+}
+
+/*
+ * scan expecting any of the 3 given token
+ */
+void
+scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
+{
+ get_token(tokp);
+ if (tokp->kind != expect1 && tokp->kind != expect2
+ && tokp->kind != expect3) {
+ expected3(expect1, expect2, expect3);
+ }
+}
+
+/*
+ * scan expecting a constant, possibly symbolic
+ */
+void
+scan_num(token *tokp)
+{
+ get_token(tokp);
+ switch (tokp->kind) {
+ case TOK_IDENT:
+ break;
+ default:
+ error("constant or identifier expected");
+ }
+}
+
+/*
+ * Peek at the next token
+ */
+void
+peek(token *tokp)
+{
+ get_token(tokp);
+ unget_token(tokp);
+}
+
+/*
+ * Peek at the next token and scan it if it matches what you expect
+ */
+int
+peekscan(tok_kind expect, token *tokp)
+{
+ peek(tokp);
+ if (tokp->kind == expect) {
+ get_token(tokp);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Get the next token, printing out any directive that are encountered.
+ */
+void
+get_token(token *tokp)
+{
+ int commenting;
+ int stat = 0;
+
+
+ if (pushed) {
+ pushed = 0;
+ *tokp = lasttok;
+ return;
+ }
+ commenting = 0;
+ for (;;) {
+ if (*where == 0) {
+ for (;;) {
+ if (!fgets(curline, MAXLINESIZE, fin)) {
+ tokp->kind = TOK_EOF;
+ /* now check if cpp returned non NULL value */
+ waitpid(childpid, &stat, WUNTRACED);
+ if (stat > 0) {
+ /* Set return value from rpcgen */
+ nonfatalerrors = stat >> 8;
+ }
+ *where = 0;
+ return;
+ }
+ linenum++;
+ if (commenting) {
+ break;
+ } else if (cppline(curline)) {
+ docppline(curline, &linenum,
+ &infilename);
+ } else if (directive(curline)) {
+ printdirective(curline);
+ } else {
+ break;
+ }
+ }
+ where = curline;
+ } else if (isspace(*where)) {
+ while (isspace(*where)) {
+ where++; /* eat */
+ }
+ } else if (commenting) {
+ for (where++; *where; where++) {
+ if (endcomment(where)) {
+ where++;
+ commenting--;
+ break;
+ }
+ }
+ } else if (startcomment(where)) {
+ where += 2;
+ commenting++;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * 'where' is not whitespace, comment or directive Must be a token!
+ */
+ switch (*where) {
+ case ':':
+ tokp->kind = TOK_COLON;
+ where++;
+ break;
+ case ';':
+ tokp->kind = TOK_SEMICOLON;
+ where++;
+ break;
+ case ',':
+ tokp->kind = TOK_COMMA;
+ where++;
+ break;
+ case '=':
+ tokp->kind = TOK_EQUAL;
+ where++;
+ break;
+ case '*':
+ tokp->kind = TOK_STAR;
+ where++;
+ break;
+ case '[':
+ tokp->kind = TOK_LBRACKET;
+ where++;
+ break;
+ case ']':
+ tokp->kind = TOK_RBRACKET;
+ where++;
+ break;
+ case '{':
+ tokp->kind = TOK_LBRACE;
+ where++;
+ break;
+ case '}':
+ tokp->kind = TOK_RBRACE;
+ where++;
+ break;
+ case '(':
+ tokp->kind = TOK_LPAREN;
+ where++;
+ break;
+ case ')':
+ tokp->kind = TOK_RPAREN;
+ where++;
+ break;
+ case '<':
+ tokp->kind = TOK_LANGLE;
+ where++;
+ break;
+ case '>':
+ tokp->kind = TOK_RANGLE;
+ where++;
+ break;
+
+ case '"':
+ tokp->kind = TOK_STRCONST;
+ findstrconst(&where, &tokp->str);
+ break;
+ case '\'':
+ tokp->kind = TOK_CHARCONST;
+ findchrconst(&where, &tokp->str);
+ break;
+
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ tokp->kind = TOK_IDENT;
+ findconst(&where, &tokp->str);
+ break;
+
+ default:
+ if (!(isalpha(*where) || *where == '_')) {
+ char buf[100];
+ char *p;
+
+ s_print(buf, "illegal character in file: ");
+ p = buf + strlen(buf);
+ if (isprint(*where)) {
+ s_print(p, "%c", *where);
+ } else {
+ s_print(p, "%d", *where);
+ }
+ error(buf);
+ }
+ findkind(&where, tokp);
+ break;
+ }
+}
+
+static void
+unget_token(token *tokp)
+{
+ lasttok = *tokp;
+ pushed = 1;
+}
+
+static void
+findstrconst(char **str, const char **val)
+{
+ char *p;
+ char *tmp;
+ int size;
+
+ p = *str;
+ do {
+ p++;
+ } while (*p && *p != '"');
+ if (*p == 0) {
+ error("unterminated string constant");
+ }
+ p++;
+ size = p - *str + 1;
+ tmp = xmalloc(size);
+ (void) strlcpy(tmp, *str, size);
+ *val = tmp;
+ *str = p;
+}
+
+static void
+findchrconst(char **str, const char **val)
+{
+ char *p;
+ char *tmp;
+ int size;
+
+ p = *str;
+ do {
+ p++;
+ } while (*p && *p != '\'');
+ if (*p == 0) {
+ error("unterminated string constant");
+ }
+ p++;
+ size = p - *str + 1;
+ if (size != 4) {
+ error("empty char string");
+ }
+ tmp = xmalloc(size);
+ (void) strlcpy(tmp, *str, size);
+ *val = tmp;
+ *str = p;
+}
+
+static void
+findconst(char **str, const char **val)
+{
+ char *p;
+ char *tmp;
+ int size;
+
+ p = *str;
+ if (*p == '0' && *(p + 1) == 'x') {
+ p++;
+ do {
+ p++;
+ } while (isxdigit(*p));
+ } else {
+ do {
+ p++;
+ } while (isdigit(*p));
+ }
+ size = p - *str + 1;
+ tmp = xmalloc(size);
+ (void) strlcpy(tmp, *str, size);
+ *val = tmp;
+ *str = p;
+}
+
+static token symbols[] = {
+ {TOK_CONST, "const"},
+ {TOK_UNION, "union"},
+ {TOK_SWITCH, "switch"},
+ {TOK_CASE, "case"},
+ {TOK_DEFAULT, "default"},
+ {TOK_STRUCT, "struct"},
+ {TOK_TYPEDEF, "typedef"},
+ {TOK_ENUM, "enum"},
+ {TOK_OPAQUE, "opaque"},
+ {TOK_BOOL, "bool"},
+ {TOK_VOID, "void"},
+ {TOK_CHAR, "char"},
+ {TOK_INT, "int"},
+ {TOK_UNSIGNED, "unsigned"},
+ {TOK_SHORT, "short"},
+ {TOK_LONG, "long"},
+ {TOK_HYPER, "hyper"},
+ {TOK_FLOAT, "float"},
+ {TOK_DOUBLE, "double"},
+ {TOK_QUAD, "quadruple"},
+ {TOK_STRING, "string"},
+ {TOK_PROGRAM, "program"},
+ {TOK_VERSION, "version"},
+ {TOK_EOF, "??????"},
+};
+
+static void
+findkind(char **mark, token *tokp)
+{
+ int len;
+ token *s;
+ char *str, *tmp;
+
+ str = *mark;
+ for (s = symbols; s->kind != TOK_EOF; s++) {
+ len = strlen(s->str);
+ if (strncmp(str, s->str, len) == 0) {
+ if (!isalnum(str[len]) && str[len] != '_') {
+ tokp->kind = s->kind;
+ tokp->str = s->str;
+ *mark = str + len;
+ return;
+ }
+ }
+ }
+ tokp->kind = TOK_IDENT;
+ for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
+ tmp = xmalloc(len + 1);
+ (void) strlcpy(tmp, str, len + 1);
+ tokp->str = tmp;
+ *mark = str + len;
+}
+
+static int
+cppline(char *line)
+{
+ return (line == curline && *line == '#');
+}
+
+static int
+directive(char *line)
+{
+ return (line == curline && *line == '%');
+}
+
+static void
+printdirective(char *line)
+{
+ f_print(fout, "%s", line + 1);
+}
+
+static void
+docppline(char *line, int *lineno, const char **fname)
+{
+ char *file;
+ int num;
+ char *p;
+
+ line++;
+ while (isspace(*line)) {
+ line++;
+ }
+ num = atoi(line);
+ while (isdigit(*line)) {
+ line++;
+ }
+ while (isspace(*line)) {
+ line++;
+ }
+ if (*line != '"') {
+ error("preprocessor error");
+ }
+ line++;
+ p = file = xmalloc(strlen(line) + 1);
+ while (*line && *line != '"') {
+ *p++ = *line++;
+ }
+ if (*line == 0) {
+ error("preprocessor error");
+ }
+ *p = 0;
+ if (*file == 0) {
+ *fname = NULL;
+ free(file);
+ } else {
+ *fname = file;
+ }
+ *lineno = num - 1;
+}
diff --git a/usr.bin/rpcgen/rpc_scan.h b/usr.bin/rpcgen/rpc_scan.h
new file mode 100644
index 000000000000..3ab00d8a4d5a
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_scan.h
@@ -0,0 +1,131 @@
+/*
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
+/* The copyright notice above does not evidence any */
+/* actual or intended publication of such source code. */
+
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+* PROPRIETARY NOTICE (Combined)
+*
+* This source code is unpublished proprietary information
+* constituting, or derived under license from AT&T's UNIX(r) System V.
+* In addition, portions of such source code were derived from Berkeley
+* 4.3 BSD under license from the Regents of the University of
+* California.
+*
+*
+*
+* Copyright Notice
+*
+* Notice of copyright on this source code product does not indicate
+* publication.
+*
+* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
+* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
+* All rights reserved.
+*/
+
+/*
+ * rpc_scan.h, Definitions for the RPCL scanner
+ */
+
+/*
+ * kinds of tokens
+ */
+enum tok_kind {
+ TOK_IDENT,
+ TOK_CHARCONST,
+ TOK_STRCONST,
+ TOK_LPAREN,
+ TOK_RPAREN,
+ TOK_LBRACE,
+ TOK_RBRACE,
+ TOK_LBRACKET,
+ TOK_RBRACKET,
+ TOK_LANGLE,
+ TOK_RANGLE,
+ TOK_STAR,
+ TOK_COMMA,
+ TOK_EQUAL,
+ TOK_COLON,
+ TOK_SEMICOLON,
+ TOK_CONST,
+ TOK_STRUCT,
+ TOK_UNION,
+ TOK_SWITCH,
+ TOK_CASE,
+ TOK_DEFAULT,
+ TOK_ENUM,
+ TOK_TYPEDEF,
+ TOK_INT,
+ TOK_SHORT,
+ TOK_LONG,
+ TOK_HYPER,
+ TOK_UNSIGNED,
+ TOK_FLOAT,
+ TOK_DOUBLE,
+ TOK_QUAD,
+ TOK_OPAQUE,
+ TOK_CHAR,
+ TOK_STRING,
+ TOK_BOOL,
+ TOK_VOID,
+ TOK_PROGRAM,
+ TOK_VERSION,
+ TOK_EOF
+};
+typedef enum tok_kind tok_kind;
+
+/*
+ * a token
+ */
+struct token {
+ tok_kind kind;
+ const char *str;
+};
+typedef struct token token;
+
+
+/*
+ * routine interface
+ */
+void scan(tok_kind expect, token *tokp);
+void scan2(tok_kind expect1, tok_kind expect2, token *tokp);
+void scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp);
+void scan_num(token *tokp);
+void peek(token *tokp);
+int peekscan(tok_kind expect, token *tokp);
+void get_token(token *tokp);
diff --git a/usr.bin/rpcgen/rpc_svcout.c b/usr.bin/rpcgen/rpc_svcout.c
new file mode 100644
index 000000000000..2c6849714d75
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_svcout.c
@@ -0,0 +1,1015 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+static char RQSTP[] = "rqstp";
+static char TRANSP[] = "transp";
+static char ARG[] = "argument";
+static char RESULT[] = "result";
+static char ROUTINE[] = "local";
+static char RETVAL[] = "retval";
+
+static char _errbuf[256]; /* For all messages */
+
+void internal_proctype( proc_list * );
+static void write_real_program( definition * );
+static void write_program(definition *, const char *);
+static void printerr(const char *, const char *);
+static void printif(const char *, const char *, const char *, const char *);
+static void write_inetmost(const char *);
+static void print_return(const char *);
+static void print_pmapunset(const char *);
+static void print_err_message(const char *);
+static void write_timeout_func( void );
+static void write_pm_most(const char *, int);
+static void write_rpc_svc_fg(const char *, const char *);
+static void open_log_file(const char *, const char *);
+static void write_msg_out( void );
+
+
+static void
+p_xdrfunc(const char *rname, const char *typename)
+{
+ f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n",
+ rname, stringfix(typename));
+}
+
+void
+internal_proctype(proc_list *plist)
+{
+ f_print(fout, "static ");
+ ptype(plist->res_prefix, plist->res_type, 1);
+ f_print(fout, "*");
+}
+
+
+/*
+ * write most of the service, that is, everything but the registrations.
+ */
+void
+write_most(const char *infile, int netflag, int nomain)
+{
+ if (inetdflag || pmflag) {
+ const char *var_type;
+ var_type = (nomain? "extern" : "static");
+ f_print(fout, "%s int _rpcpmstart;", var_type);
+ f_print(fout, "\t\t/* Started by a port monitor ? */\n");
+ if (!tirpcflag || tirpc_socket) {
+ f_print(fout, "%s int _rpcfdtype;", var_type);
+ f_print(fout, "\n\t\t /* Whether Stream or \
+Datagram ? */\n");
+ }
+
+ if (timerflag) {
+ f_print(fout, " /* States a server can be in \
+wrt request */\n\n");
+ f_print(fout, "#define\t_IDLE 0\n");
+ f_print(fout, "#define\t_SERVED 1\n");
+ f_print(fout, "#define\t_SERVING 2\n\n");
+ f_print(fout, "static int _rpcsvcstate = _IDLE;");
+ f_print(fout, "\t /* Set when a request is \
+serviced */\n");
+
+ if (mtflag) {
+ f_print(fout, "pthread_mutex_t _svcstate_lock;");
+ f_print(fout, "\t\t\t/* Mutex lock for variable _rpcsvcstate */\n");
+
+ }
+
+ }
+
+ write_svc_aux(nomain);
+ }
+ /* write out dispatcher and stubs */
+ write_programs((char *)NULL);
+
+ if (nomain)
+ return;
+
+ f_print(fout, "\nint\n");
+ f_print(fout, "main()\n");
+ f_print(fout, "{\n");
+ if (inetdflag) {
+ write_inetmost(infile);
+ /* Includes call to write_rpc_svc_fg() */
+ } else {
+ if (tirpcflag) {
+ if (netflag) {
+ f_print(fout,
+ "\tregister SVCXPRT *%s;\n", TRANSP);
+ f_print(fout,
+ "\tstruct netconfig *nconf = NULL;\n");
+ }
+ f_print(fout, "\tpid_t pid;\n");
+ f_print(fout, "\tint i;\n");
+ if (pmflag) {
+ if (tirpc_socket) {
+ f_print(fout, "\tstruct sockaddr_storage saddr;\n");
+ f_print(fout, "\tsocklen_t asize = sizeof (saddr);\n\n");
+ } else
+ f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
+ }
+
+ if (mtflag & timerflag)
+ f_print(fout, "\tmutex_init(&_svcstate_lock, USYNC_THREAD, NULL);\n");
+ if (pmflag) {
+ write_pm_most(infile, netflag);
+ f_print(fout, "\telse {\n");
+ write_rpc_svc_fg(infile, "\t\t");
+ f_print(fout, "\t}\n");
+ } else
+ write_rpc_svc_fg(infile, "\t\t");
+
+ } else {
+ f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
+ f_print(fout, "\n");
+ print_pmapunset("\t");
+ }
+ }
+
+ if (logflag && !inetdflag) {
+ open_log_file(infile, "\t");
+ }
+}
+
+/*
+ * write a registration for the given transport
+ */
+void
+write_netid_register(const char *transp)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+ const char *sp;
+ char tmpbuf[32];
+
+ sp = "";
+ f_print(fout, "\n");
+ f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
+ f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
+ (void) sprintf(_errbuf, "cannot find %s netid.", transp);
+ sprintf(tmpbuf, "%s\t\t", sp);
+ print_err_message(tmpbuf);
+ f_print(fout, "%s\t\texit(1);\n", sp);
+ f_print(fout, "%s\t}\n", sp);
+ if (tirpcflag) {
+ f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, ",
+ sp, TRANSP);
+ f_print(fout,"nconf, 0, RPC_MAXDATASIZE, RPC_MAXDATASIZE);\n");
+ } else {
+ f_print(fout,
+ "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
+ sp, TRANSP);
+ }
+ f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
+ (void) sprintf(_errbuf, "cannot create %s service.", transp);
+ print_err_message(tmpbuf);
+ f_print(fout, "%s\t\texit(1);\n", sp);
+ f_print(fout, "%s\t}\n", sp);
+
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ continue;
+ }
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout,
+ "%s\t(void) rpcb_unset(%s, %s, nconf);\n",
+ sp, def->def_name, vp->vers_name);
+ f_print(fout,
+ "%s\tif (!svc_reg(%s, %s, %s, ",
+ sp, TRANSP, def->def_name, vp->vers_name);
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout, ", nconf)) {\n");
+ (void) sprintf(_errbuf,
+ "unable to register (%s, %s, %s).",
+ def->def_name, vp->vers_name, transp);
+ print_err_message(tmpbuf);
+ f_print(fout, "%s\t\texit(1);\n", sp);
+ f_print(fout, "%s\t}\n", sp);
+ }
+ }
+ f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
+}
+
+/*
+ * write a registration for the given transport for TLI
+ */
+void
+write_nettype_register(const char *transp)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ continue;
+ }
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout, "\tif (!svc_create(");
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout, ", %s, %s, \"%s\")) {\n",
+ def->def_name, vp->vers_name, transp);
+ (void) sprintf(_errbuf,
+ "unable to create (%s, %s) for %s.",
+ def->def_name, vp->vers_name, transp);
+ print_err_message("\t\t");
+ f_print(fout, "\t\texit(1);\n");
+ f_print(fout, "\t}\n");
+ }
+ }
+}
+
+/*
+ * write the rest of the service
+ */
+void
+write_rest(void)
+{
+ f_print(fout, "\n");
+ if (inetdflag) {
+ f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
+ (void) sprintf(_errbuf, "could not create a handle");
+ print_err_message("\t\t");
+ f_print(fout, "\t\texit(1);\n");
+ f_print(fout, "\t}\n");
+ if (timerflag) {
+ f_print(fout, "\tif (_rpcpmstart) {\n");
+ f_print(fout,
+ "\t\t(void) signal(SIGALRM, closedown);\n");
+ f_print(fout, "\t\t(void) \
+alarm(_RPCSVC_CLOSEDOWN/2);\n");
+ f_print(fout, "\t}\n");
+ }
+ }
+ f_print(fout, "\tsvc_run();\n");
+ (void) sprintf(_errbuf, "svc_run returned");
+ print_err_message("\t");
+ f_print(fout, "\texit(1);\n");
+ f_print(fout, "\t/* NOTREACHED */\n");
+ f_print(fout, "}\n");
+}
+
+void
+write_programs(const char *storage)
+{
+ list *l;
+ definition *def;
+
+ /* write out stubs for procedure definitions */
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind == DEF_PROGRAM) {
+ write_real_program(def);
+ }
+ }
+
+ /* write out dispatcher for each program */
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind == DEF_PROGRAM) {
+ write_program(def, storage);
+ }
+ }
+
+
+}
+
+/*
+ * write out definition of internal function (e.g. _printmsg_1(...))
+ * which calls server's definition of actual function (e.g. printmsg_1(...)).
+ * Unpacks single user argument of printmsg_1 to call-by-value format
+ * expected by printmsg_1.
+ */
+static void
+write_real_program(definition *def)
+{
+ version_list *vp;
+ proc_list *proc;
+ decl_list *l;
+
+ if (!newstyle) return; /* not needed for old style */
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ f_print(fout, "\n");
+ if (!mtflag)
+ internal_proctype(proc);
+ else
+ f_print(fout, "int");
+ f_print(fout, "\n_");
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "(");
+ /* arg name */
+ if (proc->arg_num > 1)
+ fputs(proc->args.argname, fout);
+ else
+ ptype(proc->args.decls->decl.prefix,
+ proc->args.decls->decl.type, 0);
+ if (mtflag) {
+ f_print(fout, " *argp, void *%s, struct svc_req *%s)\n",
+ RESULT, RQSTP);
+
+
+ }
+ else
+ f_print(fout, " *argp, struct svc_req *%s)\n",
+ RQSTP);
+
+ f_print(fout, "{\n");
+ f_print(fout, "\treturn (");
+ pvname_svc(proc->proc_name, vp->vers_num);
+ f_print(fout, "(");
+ if (proc->arg_num < 2) { /* single argument */
+ if (!streq(proc->args.decls->decl.type, "void"))
+ f_print(fout, "*argp, "); /* non-void */
+ } else {
+ for (l = proc->args.decls; l != NULL;
+ l = l->next)
+ f_print(fout, "argp->%s, ",
+ l->decl.name);
+ }
+ if (mtflag)
+ f_print(fout, "%s, ",RESULT);
+ f_print(fout, "%s));\n}\n", RQSTP);
+ }
+ }
+}
+
+static void
+write_program(definition *def, const char *storage)
+{
+ version_list *vp;
+ proc_list *proc;
+ int filled;
+
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout, "\n");
+ if (storage != NULL) {
+ f_print(fout, "%s ", storage);
+ }
+ f_print(fout, "void\n");
+ pvname(def->def_name, vp->vers_num);
+
+ f_print(fout, "(struct svc_req *%s, ", RQSTP);
+ f_print(fout, "SVCXPRT *%s)\n", TRANSP);
+ f_print(fout, "{\n");
+
+ filled = 0;
+ f_print(fout, "\tunion {\n");
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ if (proc->arg_num < 2) { /* single argument */
+ if (streq(proc->args.decls->decl.type,
+ "void")) {
+ continue;
+ }
+ filled = 1;
+ f_print(fout, "\t\t");
+ ptype(proc->args.decls->decl.prefix,
+ proc->args.decls->decl.type, 0);
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_arg;\n");
+
+ } else {
+ filled = 1;
+ f_print(fout, "\t\t%s", proc->args.argname);
+ f_print(fout, " ");
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_arg;\n");
+ }
+ }
+ if (!filled) {
+ f_print(fout, "\t\tint fill;\n");
+ }
+ f_print(fout, "\t} %s;\n", ARG);
+
+ if (mtflag) {
+ f_print(fout, "\tunion {\n");
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ if (streq(proc->res_type, "void")) {
+ continue;
+ }
+ f_print(fout, "\t\t");
+ ptype(proc->res_prefix, proc->res_type, 0);
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, "_res;\n");
+ }
+ f_print(fout, "\t} %s;\n", RESULT);
+ f_print(fout, "\tbool_t %s;\n", RETVAL);
+
+ } else
+ f_print(fout, "\tchar *%s;\n", RESULT);
+
+ f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
+ if (mtflag)
+ f_print(fout,
+ "\tbool_t (*%s)(char *, void *, struct svc_req *);\n",
+ ROUTINE);
+ else
+ f_print(fout,
+ "\tchar *(*%s)(char *, struct svc_req *);\n",
+ ROUTINE);
+ f_print(fout, "\n");
+
+ if (timerflag) {
+ if (mtflag)
+ f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n");
+
+ f_print(fout, "\t_rpcsvcstate = _SERVING;\n");
+ if (mtflag)
+ f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n");
+ }
+
+ f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
+ if (!nullproc(vp->procs)) {
+ f_print(fout, "\tcase NULLPROC:\n");
+ f_print(fout,
+ "\t\t(void) svc_sendreply(%s,\n\t\t\t"
+ "(xdrproc_t) xdr_void, (char *)NULL);\n",
+ TRANSP);
+ print_return("\t\t");
+ f_print(fout, "\n");
+ }
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ f_print(fout, "\tcase %s:\n", proc->proc_name);
+ if (proc->arg_num < 2) { /* single argument */
+ p_xdrfunc(ARG, proc->args.decls->decl.type);
+ } else {
+ p_xdrfunc(ARG, proc->args.argname);
+ }
+ p_xdrfunc(RESULT, proc->res_type);
+
+ if (mtflag)
+ f_print(fout,
+ "\t\t%s = (bool_t (*) (char *, void *, struct svc_req *))",
+ ROUTINE);
+ else
+ f_print(fout,
+ "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
+ ROUTINE);
+ if (newstyle) { /* new style: calls internal routine */
+ f_print(fout, "_");
+ }
+ if (!newstyle)
+ pvname_svc(proc->proc_name, vp->vers_num);
+ else
+ pvname(proc->proc_name, vp->vers_num);
+ f_print(fout, ";\n");
+ f_print(fout, "\t\tbreak;\n\n");
+ }
+ f_print(fout, "\tdefault:\n");
+ printerr("noproc", TRANSP);
+ print_return("\t\t");
+ f_print(fout, "\t}\n");
+
+ f_print(fout,
+ "\t(void) memset((char *)&%s, 0, sizeof (%s));\n",
+ ARG, ARG);
+ printif("getargs", TRANSP, "(caddr_t) &", ARG);
+ printerr("decode", TRANSP);
+ print_return("\t\t");
+ f_print(fout, "\t}\n");
+
+ if (!mtflag)
+ f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
+ RESULT, ROUTINE, ARG, RQSTP);
+ else
+ f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n",
+ RETVAL, ROUTINE, ARG, RESULT, RQSTP);
+
+
+ if (mtflag)
+ f_print(fout,
+ "\tif (%s > 0 && !svc_sendreply(%s, xdr_%s, (char *)&%s)) {\n",
+ RETVAL, TRANSP, RESULT, RESULT);
+ else
+ f_print(fout,
+ "\tif (%s != NULL && !svc_sendreply(%s, xdr_%s, %s)) {\n",
+ RESULT, TRANSP, RESULT, RESULT);
+
+ printerr("systemerr", TRANSP);
+ f_print(fout, "\t}\n");
+
+ printif("freeargs", TRANSP, "(caddr_t) &", ARG);
+ (void) sprintf(_errbuf, "unable to free arguments");
+ print_err_message("\t\t");
+ f_print(fout, "\t\texit(1);\n");
+ f_print(fout, "\t}\n");
+ /* print out free routine */
+ if (mtflag) {
+ f_print(fout,"\tif (!");
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout,"_freeresult(%s, xdr_%s, (caddr_t) &%s))\n",
+ TRANSP, RESULT, RESULT);
+ (void) sprintf(_errbuf, "unable to free results");
+ print_err_message("\t\t");
+ f_print(fout, "\n");
+ }
+ print_return("\t");
+ f_print(fout, "}\n");
+ }
+}
+
+static void
+printerr(const char *err, const char *transp)
+{
+ f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
+}
+
+static void
+printif(const char *proc, const char *transp, const char *prefix,
+ const char *arg)
+{
+ f_print(fout, "\tif (!svc_%s(%s, xdr_%s, (char *)%s%s)) {\n",
+ proc, transp, arg, prefix, arg);
+}
+
+int
+nullproc(proc_list *proc)
+{
+ for (; proc != NULL; proc = proc->next) {
+ if (streq(proc->proc_num, "0")) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static void
+write_inetmost(const char *infile)
+{
+ f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
+ f_print(fout, "\tint sock;\n");
+ f_print(fout, "\tint proto;\n");
+ f_print(fout, "\tstruct sockaddr_in saddr;\n");
+ f_print(fout, "\tsocklen_t asize = sizeof (saddr);\n");
+ f_print(fout, "\n");
+ f_print(fout,
+ "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
+ f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n\n");
+ f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
+ f_print(fout, "\t\t\texit(1);\n");
+ f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
+ f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
+ f_print(fout, "\t\t\texit(1);\n");
+ f_print(fout, "\t\tsock = 0;\n");
+ f_print(fout, "\t\t_rpcpmstart = 1;\n");
+ f_print(fout, "\t\tproto = 0;\n");
+ open_log_file(infile, "\t\t");
+ f_print(fout, "\t} else {\n");
+ write_rpc_svc_fg(infile, "\t\t");
+ f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
+ print_pmapunset("\t\t");
+ f_print(fout, "\t}\n");
+}
+
+static void
+print_return(const char *space)
+{
+ if (exitnow)
+ f_print(fout, "%sexit(0);\n", space);
+ else {
+ if (timerflag) {
+ if (mtflag)
+ f_print(fout, "%spthread_mutex_lock(&_svcstate_lock);\n", space);
+ f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space);
+ if (mtflag)
+ f_print(fout, "%spthread_mutex_unlock(&_svcstate_lock);\n", space);
+ }
+ f_print(fout, "%sreturn;\n", space);
+ }
+}
+
+static void
+print_pmapunset(const char *space)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind == DEF_PROGRAM) {
+ for (vp = def->def.pr.versions; vp != NULL;
+ vp = vp->next) {
+ f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
+ space, def->def_name, vp->vers_name);
+ }
+ }
+ }
+}
+
+static void
+print_err_message(const char *space)
+{
+ if (logflag)
+ f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf);
+ else if (inetdflag || pmflag)
+ f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
+ else
+ f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
+}
+
+/*
+ * Write the server auxiliary function (_msgout, timeout)
+ */
+void
+write_svc_aux(int nomain)
+{
+ if (!logflag)
+ write_msg_out();
+ if (!nomain)
+ write_timeout_func();
+}
+
+/*
+ * Write the _msgout function
+ */
+
+static void
+write_msg_out(void)
+{
+ f_print(fout, "\n");
+/*
+ * Avoid making _msgout() static -- it's useful to have it visible
+ * in the toplevel RPC server code.
+ */
+ f_print(fout, "static\n");
+ f_print(fout, "void _msgout(const char* msg)\n");
+ f_print(fout, "{\n");
+ f_print(fout, "#ifdef RPC_SVC_FG\n");
+ if (inetdflag || pmflag)
+ f_print(fout, "\tif (_rpcpmstart)\n");
+ f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
+ f_print(fout, "\telse\n");
+ f_print(fout,
+ "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
+ f_print(fout, "#else\n");
+ f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
+ f_print(fout, "#endif\n");
+ f_print(fout, "}\n");
+}
+
+/*
+ * Write the timeout function
+ */
+static void
+write_timeout_func(void)
+{
+ if (!timerflag)
+ return;
+
+ f_print(fout, "\n");
+ f_print(fout, "static void\n");
+ f_print(fout, "closedown(int sig)\n");
+ f_print(fout, "{\n");
+ if (mtflag)
+ f_print(fout, "\tpthread_mutex_lock(&_svcstate_lock);\n");
+ f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\n");
+ f_print(fout, "\t\textern fd_set svc_fdset;\n");
+ f_print(fout, "\t\tstatic int size;\n");
+ f_print(fout, "\t\tint i, openfd;\n");
+ if (tirpcflag && pmflag) {
+ f_print(fout, "\t\tstruct t_info tinfo;\n\n");
+ f_print(fout,
+ "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
+ } else {
+ f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
+ }
+ f_print(fout, "\t\t\texit(0);\n");
+ f_print(fout, "\t\tif (size == 0) {\n");
+ if (tirpcflag) {
+ f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
+ f_print(fout, "\t\t\trl.rlim_max = 0;\n");
+ f_print(fout, "\t\t\tif (getrlimit(RLIMIT_NOFILE, &rl) == -1)\n");
+ f_print(fout, "\t\t\t\treturn;\n");
+ f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0) {\n");
+
+ if (mtflag)
+ f_print(fout, "\t\t\t\tpthread_mutex_unlock(&_svcstate_lock);\n");
+
+ f_print(fout, "\t\t\t\treturn;\n\t\t\t}\n");
+ } else {
+ f_print(fout, "\t\t\tsize = getdtablesize();\n");
+ }
+ f_print(fout, "\t\t}\n");
+ f_print(fout,
+ "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
+ f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
+ f_print(fout, "\t\t\t\topenfd++;\n");
+ f_print(fout, "\t\tif (openfd <= 1)\n");
+ f_print(fout, "\t\t\texit(0);\n");
+ f_print(fout, "\t}\n");
+ f_print(fout, "\tif (_rpcsvcstate == _SERVED)\n");
+ f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n");
+ if (mtflag)
+ f_print(fout, "\tpthread_mutex_unlock(&_svcstate_lock);\n");
+
+ f_print(fout, "\t(void) signal(SIGALRM, closedown);\n");
+ f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
+ f_print(fout, "}\n");
+
+}
+
+/*
+ * Write the most of port monitor support
+ */
+static void
+write_pm_most(const char *infile, int netflag)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+
+ if (tirpc_socket) {
+ f_print(fout,
+ "\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
+ f_print(fout, "\t\tsocklen_t ssize = sizeof (int);\n");
+ } else {
+ f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
+ f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
+ f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
+ }
+ f_print(fout, "\t\tchar *netid;\n");
+ if (!netflag) { /* Not included by -n option */
+ f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
+ f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
+ }
+ if (timerflag)
+ f_print(fout, "\t\tint pmclose;\n");
+/*
+ * Not necessary, defined in /usr/include/stdlib
+ * f_print(fout, "\t\textern char *getenv();\n");
+ */
+ f_print(fout, "\n");
+ if (tirpc_socket) {
+ f_print(fout, "\t\tif (saddr.ss_family != AF_INET &&\n");
+ f_print(fout, "\t\t saddr.ss_family != AF_INET6)\n");
+ f_print(fout, "\t\t\texit(1);\n");
+ f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
+ f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
+ f_print(fout, "\t\t\texit(1);\n");
+ }
+ f_print(fout, "\t\t_rpcpmstart = 1;\n");
+ open_log_file(infile, "\t\t");
+ f_print(fout, "\n\t\tif ((netid = \
+getenv(\"NLSPROVIDER\")) == NULL) {\n");
+
+ if (timerflag) {
+ f_print(fout, "\t\t/* started from inetd */\n");
+ f_print(fout, "\t\t\tpmclose = 1;\n");
+ }
+ f_print(fout,
+ "\t\t} else {\n");
+ f_print(fout, "\t\t\tif ((nconf = getnetconfigent(netid)) == NULL)\n");
+ sprintf(_errbuf, "cannot get transport info");
+ print_err_message("\t\t\t\t");
+ if (timerflag) {
+ if (tirpc_socket)
+ f_print(fout, "\n\t\t\tpmclose = 1;\t/* XXX */\n");
+ else
+ f_print(fout,
+ "\n\t\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
+ }
+ f_print(fout, "\t\t}\n");
+ /*
+ * A kludgy support for inetd services. Inetd only works with
+ * sockmod, and RPC works only with timod, hence all this jugglery
+ */
+ if (!tirpc_socket) {
+ f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
+ f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ");
+ f_print(fout, "ioctl(0, I_PUSH, \"timod\")) {\n");
+ sprintf(_errbuf, "could not get the right module");
+ print_err_message("\t\t\t\t");
+ f_print(fout, "\t\t\t\texit(1);\n");
+ f_print(fout, "\t\t\t}\n");
+ f_print(fout, "\t\t}\n");
+ }
+ if (tirpcflag) {
+ f_print(fout,
+ "\t\tif ((%s = svc_tli_create(0, nconf, NULL, \
+ RPC_MAXDATASIZE, RPC_MAXDATASIZE)) \
+ == NULL) {\n",
+ TRANSP);
+ } else {
+ f_print(fout,
+ "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) \
+ == NULL) {\n",
+ TRANSP);
+ }
+ sprintf(_errbuf, "cannot create server handle");
+ print_err_message("\t\t\t");
+ f_print(fout, "\t\t\texit(1);\n");
+ f_print(fout, "\t\t}\n");
+ f_print(fout, "\t\tif (nconf)\n");
+ f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ continue;
+ }
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout,
+ "\t\tif (!svc_reg(%s, %s, %s, ",
+ TRANSP, def->def_name, vp->vers_name);
+ pvname(def->def_name, vp->vers_num);
+ f_print(fout, ", 0)) {\n");
+ (void) sprintf(_errbuf, "unable to register (%s, %s).",
+ def->def_name, vp->vers_name);
+ print_err_message("\t\t\t");
+ f_print(fout, "\t\t\texit(1);\n");
+ f_print(fout, "\t\t}\n");
+ }
+ }
+ if (timerflag) {
+ f_print(fout, "\t\tif (pmclose) {\n");
+ f_print(fout, "\t\t\t(void) signal(SIGALRM, closedown);\n");
+ f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN/2);\n");
+ f_print(fout, "\t\t}\n");
+ }
+ f_print(fout, "\t\tsvc_run();\n");
+ f_print(fout, "\t\texit(1);\n");
+ f_print(fout, "\t\t/* NOTREACHED */\n");
+ f_print(fout, "\t}");
+}
+
+/*
+ * Support for backgrounding the server if self started.
+ */
+static void
+write_rpc_svc_fg(const char *infile, const char *sp)
+{
+ f_print(fout, "#ifndef RPC_SVC_FG\n");
+ f_print(fout, "%sint size;\n", sp);
+ if (tirpcflag)
+ f_print(fout, "%sstruct rlimit rl;\n", sp);
+ if (inetdflag)
+ f_print(fout, "%sint pid, i;\n\n", sp);
+ f_print(fout, "%spid = fork();\n", sp);
+ f_print(fout, "%sif (pid < 0) {\n", sp);
+ f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
+ f_print(fout, "%s\texit(1);\n", sp);
+ f_print(fout, "%s}\n", sp);
+ f_print(fout, "%sif (pid)\n", sp);
+ f_print(fout, "%s\texit(0);\n", sp);
+ /* get number of file descriptors */
+ if (tirpcflag) {
+ f_print(fout, "%srl.rlim_max = 0;\n", sp);
+ f_print(fout, "%sif (getrlimit(RLIMIT_NOFILE, &rl) == -1) {\n",
+ sp);
+ f_print(fout, "%s\tperror(\"getrlimit\");\n", sp);
+ f_print(fout, "%s\texit(1);\n", sp);
+ f_print(fout, "%s}\n", sp);
+ f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
+ f_print(fout, "%s\texit(1);\n", sp);
+ } else {
+ f_print(fout, "%ssize = getdtablesize();\n", sp);
+ }
+
+ f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp);
+ f_print(fout, "%s\t(void) close(i);\n", sp);
+ /* Redirect stderr and stdout to console */
+ f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp);
+ f_print(fout, "%s(void) dup2(i, 1);\n", sp);
+ f_print(fout, "%s(void) dup2(i, 2);\n", sp);
+ /* This removes control of the controlling terminal */
+ if (tirpcflag)
+ f_print(fout, "%ssetsid();\n", sp);
+ else {
+ f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
+ f_print(fout, "%sif (i >= 0) {\n", sp);
+ f_print(fout,
+ "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);
+ f_print(fout, "%s\t(void) close(i);\n", sp);
+ f_print(fout, "%s}\n", sp);
+ }
+ if (!logflag)
+ open_log_file(infile, sp);
+ f_print(fout, "#endif\n");
+ if (logflag)
+ open_log_file(infile, sp);
+}
+
+static void
+open_log_file(const char *infile, const char *sp)
+{
+ char *s;
+
+ s = strrchr(infile, '.');
+ if (s)
+ *s = '\0';
+ f_print(fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
+ if (s)
+ *s = '.';
+}
+
+
+
+
+/*
+ * write a registration for the given transport for Inetd
+ */
+void
+write_inetd_register(const char *transp)
+{
+ list *l;
+ definition *def;
+ version_list *vp;
+ const char *sp;
+ int isudp;
+ char tmpbuf[32];
+
+ if (inetdflag)
+ sp = "\t";
+ else
+ sp = "";
+ if (streq(transp, "udp"))
+ isudp = 1;
+ else
+ isudp = 0;
+ f_print(fout, "\n");
+ if (inetdflag) {
+ f_print(fout,
+ "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
+ isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
+ }
+ f_print(fout, "%s\t%s = svc%s_create(%s",
+ sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
+ if (!isudp)
+ f_print(fout, ", 0, 0");
+ f_print(fout, ");\n");
+ f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
+ (void) sprintf(_errbuf, "cannot create %s service.", transp);
+ (void) sprintf(tmpbuf, "%s\t\t", sp);
+ print_err_message(tmpbuf);
+ f_print(fout, "%s\t\texit(1);\n", sp);
+ f_print(fout, "%s\t}\n", sp);
+
+ if (inetdflag) {
+ f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
+ f_print(fout, "%s\tproto = IPPROTO_%s;\n",
+ sp, isudp ? "UDP": "TCP");
+ }
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind != DEF_PROGRAM) {
+ continue;
+ }
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
+ sp, TRANSP, def->def_name, vp->vers_name);
+ pvname(def->def_name, vp->vers_num);
+ if (inetdflag)
+ f_print(fout, ", proto)) {\n");
+ else
+ f_print(fout, ", IPPROTO_%s)) {\n",
+ isudp ? "UDP": "TCP");
+ (void) sprintf(_errbuf,
+ "unable to register (%s, %s, %s).",
+ def->def_name, vp->vers_name, transp);
+ print_err_message(tmpbuf);
+ f_print(fout, "%s\t\texit(1);\n", sp);
+ f_print(fout, "%s\t}\n", sp);
+ }
+ }
+ if (inetdflag)
+ f_print(fout, "\t}\n");
+}
diff --git a/usr.bin/rpcgen/rpc_tblout.c b/usr.bin/rpcgen/rpc_tblout.c
new file mode 100644
index 000000000000..dfa4cd8656eb
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_tblout.c
@@ -0,0 +1,162 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
+ * Copyright (C) 1989, Sun Microsystems, Inc.
+ */
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+#define TABSIZE 8
+#define TABCOUNT 5
+#define TABSTOP (TABSIZE*TABCOUNT)
+
+static char tabstr[TABCOUNT+1] = "\t\t\t\t\t";
+
+static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
+static char tbl_end[] = "};\n";
+
+static char null_entry[] = "\n\t(char *(*)())0,\n\
+ \t(xdrproc_t) xdr_void,\t\t\t0,\n\
+ \t(xdrproc_t) xdr_void,\t\t\t0,\n";
+
+
+static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n";
+
+static void write_table( definition * );
+static void printit(const char *, const char *);
+
+void
+write_tables(void)
+{
+ list *l;
+ definition *def;
+
+ f_print(fout, "\n");
+ for (l = defined; l != NULL; l = l->next) {
+ def = (definition *) l->val;
+ if (def->def_kind == DEF_PROGRAM) {
+ write_table(def);
+ }
+ }
+}
+
+static void
+write_table(definition *def)
+{
+ version_list *vp;
+ proc_list *proc;
+ int current;
+ int expected;
+ char progvers[100];
+ int warning;
+
+ for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+ warning = 0;
+ s_print(progvers, "%s_%s",
+ locase(def->def_name), vp->vers_num);
+ /* print the table header */
+ f_print(fout, tbl_hdr, progvers);
+
+ if (nullproc(vp->procs)) {
+ expected = 0;
+ } else {
+ expected = 1;
+ fputs(null_entry, fout);
+ }
+ for (proc = vp->procs; proc != NULL; proc = proc->next) {
+ current = atoi(proc->proc_num);
+ if (current != expected++) {
+ f_print(fout,
+ "\n/*\n * WARNING: table out of order\n */\n");
+ if (warning == 0) {
+ warnx("WARNING %s table is out of order", progvers);
+ warning = 1;
+ nonfatalerrors = 1;
+ }
+ expected = current + 1;
+ }
+ f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION(");
+
+ /* routine to invoke */
+ if( !newstyle )
+ pvname_svc(proc->proc_name, vp->vers_num);
+ else {
+ if( newstyle )
+ f_print( fout, "_"); /* calls internal func */
+ pvname(proc->proc_name, vp->vers_num);
+ }
+ f_print(fout, "),\n");
+
+ /* argument info */
+ if( proc->arg_num > 1 )
+ printit((char*) NULL, proc->args.argname );
+ else
+ /* do we have to do something special for newstyle */
+ printit( proc->args.decls->decl.prefix,
+ proc->args.decls->decl.type );
+ /* result info */
+ printit(proc->res_prefix, proc->res_type);
+ }
+
+ /* print the table trailer */
+ fputs(tbl_end, fout);
+ f_print(fout, tbl_nproc, progvers, progvers, progvers);
+ }
+}
+
+static void
+printit(const char *prefix, const char *type)
+{
+ int len;
+ int tabs;
+
+
+ len = fprintf(fout, "\txdr_%s,", stringfix(type));
+ /* account for leading tab expansion */
+ len += TABSIZE - 1;
+ /* round up to tabs required */
+ tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE;
+ f_print(fout, "%s", &tabstr[TABCOUNT-tabs]);
+
+ if (streq(type, "void")) {
+ f_print(fout, "0");
+ } else {
+ f_print(fout, "sizeof ( ");
+ /* XXX: should "follow" be 1 ??? */
+ ptype(prefix, type, 0);
+ f_print(fout, ")");
+ }
+ f_print(fout, ",\n");
+}
diff --git a/usr.bin/rpcgen/rpc_util.c b/usr.bin/rpcgen/rpc_util.c
new file mode 100644
index 000000000000..25e4963085b4
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_util.c
@@ -0,0 +1,501 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc_util.c, Utility routines for the RPC protocol compiler
+ * Copyright (C) 1989, Sun Microsystems, Inc.
+ */
+#include <err.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "rpc_parse.h"
+#include "rpc_scan.h"
+#include "rpc_util.h"
+
+#define ARGEXT "argument"
+
+char curline[MAXLINESIZE]; /* current read line */
+char *where = curline; /* current point in line */
+int linenum = 0; /* current line number */
+
+const char *infilename; /* input filename */
+
+#define NFILES 7
+static const char *outfiles[NFILES]; /* output file names */
+static int nfiles;
+
+FILE *fout; /* file pointer of current output */
+FILE *fin; /* file pointer of current input */
+
+list *defined; /* list of defined things */
+
+static void printwhere( void );
+
+/*
+ * Reinitialize the world
+ */
+void
+reinitialize(void)
+{
+ memset(curline, 0, MAXLINESIZE);
+ where = curline;
+ linenum = 0;
+ defined = NULL;
+}
+
+/*
+ * string equality
+ */
+int
+streq(const char *a, const char *b)
+{
+ return (strcmp(a, b) == 0);
+}
+
+/*
+ * find a value in a list
+ */
+definition *
+findval(list *lst, const char *val, int (*cmp)(definition *, const char *))
+{
+ for (; lst != NULL; lst = lst->next) {
+ if ((*cmp) (lst->val, val)) {
+ return (lst->val);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * store a value in a list
+ */
+void
+storeval(list **lstp, definition *val)
+{
+ list **l;
+ list *lst;
+
+ for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
+ lst = XALLOC(list);
+ lst->val = val;
+ lst->next = NULL;
+ *l = lst;
+}
+
+static int
+findit(definition *def, const char *type)
+{
+ return (streq(def->def_name, type));
+}
+
+static const char *
+fixit(const char *type, const char *orig)
+{
+ definition *def;
+
+ def = (definition *) FINDVAL(defined, type, findit);
+ if (def == NULL || def->def_kind != DEF_TYPEDEF) {
+ return (orig);
+ }
+ switch (def->def.ty.rel) {
+ case REL_VECTOR:
+ if (streq(def->def.ty.old_type, "opaque"))
+ return ("char");
+ else
+ return (def->def.ty.old_type);
+
+ case REL_ALIAS:
+ return (fixit(def->def.ty.old_type, orig));
+ default:
+ return (orig);
+ }
+}
+
+const char *
+fixtype(const char *type)
+{
+ return (fixit(type, type));
+}
+
+const char *
+stringfix(const char *type)
+{
+ if (streq(type, "string")) {
+ return ("wrapstring");
+ } else {
+ return (type);
+ }
+}
+
+void
+ptype(const char *prefix, const char *type, int follow)
+{
+ if (prefix != NULL) {
+ if (streq(prefix, "enum")) {
+ f_print(fout, "enum ");
+ } else {
+ f_print(fout, "struct ");
+ }
+ }
+ if (streq(type, "bool")) {
+ f_print(fout, "bool_t ");
+ } else if (streq(type, "string")) {
+ f_print(fout, "char *");
+ } else {
+ f_print(fout, "%s ", follow ? fixtype(type) : type);
+ }
+}
+
+static int
+typedefed(definition *def, const char *type)
+{
+ if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
+ return (0);
+ } else {
+ return (streq(def->def_name, type));
+ }
+}
+
+int
+isvectordef(const char *type, relation rel)
+{
+ definition *def;
+
+ for (;;) {
+ switch (rel) {
+ case REL_VECTOR:
+ return (!streq(type, "string"));
+ case REL_ARRAY:
+ return (0);
+ case REL_POINTER:
+ return (0);
+ case REL_ALIAS:
+ def = (definition *) FINDVAL(defined, type, typedefed);
+ if (def == NULL) {
+ return (0);
+ }
+ type = def->def.ty.old_type;
+ rel = def->def.ty.rel;
+ }
+ }
+
+ return (0);
+}
+
+char *
+locase(const char *str)
+{
+ char c;
+ static char buf[100];
+ char *p = buf;
+
+ while ( (c = *str++) ) {
+ *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
+ }
+ *p = 0;
+ return (buf);
+}
+
+void
+pvname_svc(const char *pname, const char *vnum)
+{
+ f_print(fout, "%s_%s_svc", locase(pname), vnum);
+}
+
+void
+pvname(const char *pname, const char *vnum)
+{
+ f_print(fout, "%s_%s", locase(pname), vnum);
+}
+
+/*
+ * print a useful (?) error message, and then die
+ */
+void
+error(const char *msg)
+{
+ printwhere();
+ warnx("%s, line %d: %s", infilename, linenum, msg);
+ crash();
+}
+
+/*
+ * Something went wrong, unlink any files that we may have created and then
+ * die.
+ */
+void __dead2
+crash(void)
+{
+ int i;
+
+ for (i = 0; i < nfiles; i++) {
+ (void) unlink(outfiles[i]);
+ }
+ exit(1);
+}
+
+void
+record_open(const char *file)
+{
+ if (nfiles < NFILES) {
+ outfiles[nfiles++] = file;
+ } else {
+ warnx("too many files");
+ crash();
+ }
+}
+
+static char expectbuf[100];
+static const char *toktostr(tok_kind kind);
+
+/*
+ * error, token encountered was not the expected one
+ */
+void
+expected1(tok_kind exp1)
+{
+ s_print(expectbuf, "expected '%s'",
+ toktostr(exp1));
+ error(expectbuf);
+}
+
+/*
+ * error, token encountered was not one of two expected ones
+ */
+void
+expected2(tok_kind exp1, tok_kind exp2)
+{
+ s_print(expectbuf, "expected '%s' or '%s'",
+ toktostr(exp1),
+ toktostr(exp2));
+ error(expectbuf);
+}
+
+/*
+ * error, token encountered was not one of 3 expected ones
+ */
+void
+expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3)
+{
+ s_print(expectbuf, "expected '%s', '%s' or '%s'",
+ toktostr(exp1),
+ toktostr(exp2),
+ toktostr(exp3));
+ error(expectbuf);
+}
+
+void
+tabify(FILE *f, int tab)
+{
+ while (tab--) {
+ (void) fputc('\t', f);
+ }
+}
+
+
+static token tokstrings[] = {
+ {TOK_IDENT, "identifier"},
+ {TOK_CONST, "const"},
+ {TOK_RPAREN, ")"},
+ {TOK_LPAREN, "("},
+ {TOK_RBRACE, "}"},
+ {TOK_LBRACE, "{"},
+ {TOK_LBRACKET, "["},
+ {TOK_RBRACKET, "]"},
+ {TOK_STAR, "*"},
+ {TOK_COMMA, ","},
+ {TOK_EQUAL, "="},
+ {TOK_COLON, ":"},
+ {TOK_SEMICOLON, ";"},
+ {TOK_UNION, "union"},
+ {TOK_STRUCT, "struct"},
+ {TOK_SWITCH, "switch"},
+ {TOK_CASE, "case"},
+ {TOK_DEFAULT, "default"},
+ {TOK_ENUM, "enum"},
+ {TOK_TYPEDEF, "typedef"},
+ {TOK_INT, "int"},
+ {TOK_SHORT, "short"},
+ {TOK_LONG, "long"},
+ {TOK_UNSIGNED, "unsigned"},
+ {TOK_DOUBLE, "double"},
+ {TOK_FLOAT, "float"},
+ {TOK_CHAR, "char"},
+ {TOK_STRING, "string"},
+ {TOK_OPAQUE, "opaque"},
+ {TOK_BOOL, "bool"},
+ {TOK_VOID, "void"},
+ {TOK_PROGRAM, "program"},
+ {TOK_VERSION, "version"},
+ {TOK_EOF, "??????"}
+};
+
+static const char *
+toktostr(tok_kind kind)
+{
+ token *sp;
+
+ for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
+ return (sp->str);
+}
+
+static void
+printbuf(void)
+{
+ char c;
+ int i;
+ int cnt;
+
+# define TABSIZE 4
+
+ for (i = 0; (c = curline[i]); i++) {
+ if (c == '\t') {
+ cnt = 8 - (i % TABSIZE);
+ c = ' ';
+ } else {
+ cnt = 1;
+ }
+ while (cnt--) {
+ (void) fputc(c, stderr);
+ }
+ }
+}
+
+static void
+printwhere(void)
+{
+ int i;
+ char c;
+ int cnt;
+
+ printbuf();
+ for (i = 0; i < where - curline; i++) {
+ c = curline[i];
+ if (c == '\t') {
+ cnt = 8 - (i % TABSIZE);
+ } else {
+ cnt = 1;
+ }
+ while (cnt--) {
+ (void) fputc('^', stderr);
+ }
+ }
+ (void) fputc('\n', stderr);
+}
+
+char *
+make_argname(const char *pname, const char *vname)
+{
+ char *name;
+
+ name = xmalloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3);
+ sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT);
+ return (name);
+}
+
+bas_type *typ_list_h;
+bas_type *typ_list_t;
+
+void
+add_type(int len, const char *type)
+{
+ bas_type *ptr;
+
+ ptr = XALLOC(bas_type);
+
+ ptr->name = type;
+ ptr->length = len;
+ ptr->next = NULL;
+ if (typ_list_t == NULL)
+ {
+
+ typ_list_t = ptr;
+ typ_list_h = ptr;
+ }
+ else
+ {
+ typ_list_t->next = ptr;
+ typ_list_t = ptr;
+ }
+}
+
+
+bas_type *
+find_type(const char *type)
+{
+ bas_type * ptr;
+
+ ptr = typ_list_h;
+ while (ptr != NULL)
+ {
+ if (strcmp(ptr->name, type) == 0)
+ return (ptr);
+ else
+ ptr = ptr->next;
+ }
+ return (NULL);
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *p;
+
+ if ((p = malloc(size)) == NULL) {
+ warnx("malloc failed");
+ crash();
+ }
+ return (p);
+}
+
+void *
+xrealloc(void *ptr, size_t size)
+{
+ void *p;
+
+ if ((p = realloc(ptr, size)) == NULL) {
+ warnx("realloc failed");
+ crash();
+ }
+ return (p);
+}
+
+char *
+xstrdup(const char *str)
+{
+ char *p;
+
+ if ((p = strdup(str)) == NULL) {
+ warnx("strdup failed");
+ crash();
+ }
+ return (p);
+}
diff --git a/usr.bin/rpcgen/rpc_util.h b/usr.bin/rpcgen/rpc_util.h
new file mode 100644
index 000000000000..9aede3a686dd
--- /dev/null
+++ b/usr.bin/rpcgen/rpc_util.h
@@ -0,0 +1,225 @@
+/*
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
+/* The copyright notice above does not evidence any */
+/* actual or intended publication of such source code. */
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+* PROPRIETARY NOTICE (Combined)
+*
+* This source code is unpublished proprietary information
+* constituting, or derived under license from AT&T's UNIX(r) System V.
+* In addition, portions of such source code were derived from Berkeley
+* 4.3 BSD under license from the Regents of the University of
+* California.
+*
+*
+*
+* Copyright Notice
+*
+* Notice of copyright on this source code product does not indicate
+* publication.
+*
+* (c) 1986,1987,1988.1989 Sun Microsystems, Inc
+* (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
+* All rights reserved.
+*/
+
+/*
+ * rpc_util.h, Useful definitions for the RPC protocol compiler
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+
+#define XALLOC(object) (object *) xmalloc(sizeof(object))
+
+#define s_print (void) sprintf
+#define f_print (void) fprintf
+
+struct list {
+ definition *val;
+ struct list *next;
+};
+typedef struct list list;
+
+struct xdrfunc {
+ const char *name;
+ int pointerp;
+ struct xdrfunc *next;
+};
+typedef struct xdrfunc xdrfunc;
+
+struct commandline {
+ int cflag; /* xdr C routines */
+ int hflag; /* header file */
+ int lflag; /* client side stubs */
+ int mflag; /* server side stubs */
+ int nflag; /* netid flag */
+ int sflag; /* server stubs for the given transport */
+ int tflag; /* dispatch Table file */
+ int Ssflag; /* produce server sample code */
+ int Scflag; /* produce client sample code */
+ int makefileflag; /* Generate a template Makefile */
+ const char *infile; /* input module name */
+ const char *outfile; /* output module name */
+};
+
+#define PUT 1
+#define GET 2
+
+/*
+ * Global variables
+ */
+#define MAXLINESIZE 1024
+extern char curline[MAXLINESIZE];
+extern char *where;
+extern int linenum;
+extern int tirpc_socket;
+
+extern const char *infilename;
+extern FILE *fout;
+extern FILE *fin;
+
+extern list *defined;
+
+
+extern bas_type *typ_list_h;
+extern bas_type *typ_list_t;
+extern xdrfunc *xdrfunc_head, *xdrfunc_tail;
+
+/*
+ * All the option flags
+ */
+extern int inetdflag;
+extern int pmflag;
+extern int tblflag;
+extern int logflag;
+extern int newstyle;
+extern int CCflag; /* C++ flag */
+extern int tirpcflag; /* flag for generating tirpc code */
+extern int inline_size; /* if this is 0, then do not generate inline code */
+extern int mtflag;
+
+/*
+ * Other flags related with inetd jumpstart.
+ */
+extern int indefinitewait;
+extern int exitnow;
+extern int timerflag;
+
+extern int nonfatalerrors;
+
+extern pid_t childpid;
+
+/*
+ * rpc_util routines
+ */
+void reinitialize(void);
+void crash(void) __dead2;
+void add_type(int len, const char *type);
+void storeval(list **lstp, definition *val);
+void *xmalloc(size_t size);
+void *xrealloc(void *ptr, size_t size);
+char *xstrdup(const char *);
+char *make_argname(const char *pname, const char *vname);
+
+#define STOREVAL(list,item) \
+ storeval(list,item)
+
+definition *findval(list *lst, const char *val, int (*cmp)(definition *, const char *));
+
+#define FINDVAL(list,item,finder) \
+ findval(list, item, finder)
+
+const char *fixtype(const char *type);
+const char *stringfix(const char *type);
+char *locase(const char *str);
+void pvname_svc(const char *pname, const char *vnum);
+void pvname(const char *pname, const char *vnum);
+void ptype(const char *prefix, const char *type, int follow);
+int isvectordef(const char *type, relation rel);
+int streq(const char *a, const char *b);
+void error(const char *msg);
+void expected1(tok_kind exp1);
+void expected2(tok_kind exp1, tok_kind exp2);
+void expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3);
+void tabify(FILE *f, int tab);
+void record_open(const char *file);
+bas_type *find_type(const char *type);
+
+/*
+ * rpc_cout routines
+ */
+void emit(definition *def);
+
+/*
+ * rpc_hout routines
+ */
+void pdeclaration(const char *name, declaration *dec, int tab, const char *separator);
+void print_datadef(definition *def, int headeronly);
+void print_funcdef(definition *def, int headeronly);
+void print_xdr_func_def(const char* name, int pointerp);
+
+/*
+ * rpc_svcout routines
+ */
+void write_most(const char *infile, int netflag, int nomain);
+void write_rest(void);
+void write_programs(const char *storage);
+void write_svc_aux(int nomain);
+void write_inetd_register(const char *transp);
+void write_netid_register(const char *transp);
+void write_nettype_register(const char *transp);
+int nullproc(proc_list *proc);
+
+/*
+ * rpc_clntout routines
+ */
+void write_stubs(void);
+void printarglist(proc_list *proc, const char *result, const char *addargname,
+ const char *addargtype);
+
+/*
+ * rpc_tblout routines
+ */
+void write_tables(void);
+
+/*
+ * rpc_sample routines
+ */
+void write_sample_svc(definition *);
+int write_sample_clnt(definition *);
+void write_sample_clnt_main(void);
+void add_sample_msg(void);
diff --git a/usr.bin/rpcgen/rpcgen.1 b/usr.bin/rpcgen/rpcgen.1
new file mode 100644
index 000000000000..2bf084c604b1
--- /dev/null
+++ b/usr.bin/rpcgen/rpcgen.1
@@ -0,0 +1,534 @@
+.\" Copyright 1985-1993 Sun Microsystems, Inc.
+.\"
+.Dd September 2, 2005
+.Dt RPCGEN 1
+.Os
+.Sh NAME
+.Nm rpcgen
+.Nd an RPC protocol compiler
+.Sh SYNOPSIS
+.Nm
+.Ar infile
+.Nm
+.Op Fl a
+.Op Fl b
+.Op Fl C
+.Oo
+.Fl D Ns Ar name Ns Op Ar =value
+.Oc
+.Op Fl i Ar size
+.Op Fl I Fl P Op Fl K Ar seconds
+.Op Fl L
+.Op Fl M
+.Op Fl N
+.Op Fl T
+.Op Fl Y Ar pathname
+.Ar infile
+.Nm
+.Oo
+.Fl c |
+.Fl h |
+.Fl l |
+.Fl m |
+.Fl t |
+.Fl \&Sc |
+.Fl \&Ss |
+.Fl \&Sm
+.Oc
+.Op Fl o Ar outfile
+.Op Ar infile
+.Nm
+.Op Fl s Ar nettype
+.Op Fl o Ar outfile
+.Op Ar infile
+.Nm
+.Op Fl n Ar netid
+.Op Fl o Ar outfile
+.Op Ar infile
+.\" .SH AVAILABILITY
+.\" .LP
+.\" SUNWcsu
+.Sh DESCRIPTION
+The
+.Nm
+utility is a tool that generates C code to implement an
+.Tn RPC
+protocol.
+The input to
+.Nm
+is a language similar to C known as
+.Tn RPC
+Language (Remote Procedure Call Language).
+.Pp
+The
+.Nm
+utility is normally used as in the first synopsis where
+it takes an input file and generates three output files.
+If the
+.Ar infile
+is named
+.Pa proto.x ,
+then
+.Nm
+generates a header in
+.Pa proto.h ,
+XDR routines in
+.Pa proto_xdr.c ,
+server-side stubs in
+.Pa proto_svc.c ,
+and client-side stubs in
+.Pa proto_clnt.c .
+With the
+.Fl T
+option,
+it also generates the
+.Tn RPC
+dispatch table in
+.Pa proto_tbl.i .
+.Pp
+The
+.Nm
+utility can also generate sample client and server files
+that can be customized to suit a particular application.
+The
+.Fl \&Sc ,
+.Fl \&Ss
+and
+.Fl \&Sm
+options generate sample client, server and makefile, respectively.
+The
+.Fl a
+option generates all files, including sample files.
+If the
+.Ar infile
+is
+.Pa proto.x ,
+then the client side sample file is written to
+.Pa proto_client.c ,
+the server side sample file to
+.Pa proto_server.c
+and the sample makefile to
+.Pa makefile.proto .
+.Pp
+If option
+.Fl I
+is set,
+the server created can be started both by the port monitors
+(for example,
+.Xr inetd 8 )
+or by itself.
+When it is started by a port monitor,
+it creates servers only for the transport for which
+the file descriptor
+.Em 0
+was passed.
+The name of the transport may be specified
+by setting up the environment variable
+.Ev NLSPROVIDER .
+When the server generated by
+.Nm
+is executed,
+it creates server handles for all the transports
+specified in
+.Ev NETPATH
+environment variable,
+or if it is unset,
+it creates server handles for all the visible transports from
+.Pa /etc/netconfig
+file.
+Note:
+the transports are chosen at run time and not at compile time.
+When the server is self-started,
+it backgrounds itself by default.
+A special define symbol
+.Em RPC_SVC_FG
+can be used to run the server process in foreground.
+.Pp
+The second synopsis provides special features which allow
+for the creation of more sophisticated
+.Tn RPC
+servers.
+These features include support for user provided
+.Em #defines
+and
+.Tn RPC
+dispatch tables.
+The entries in the
+.Tn RPC
+dispatch table contain:
+.Bl -bullet -offset indent -compact
+.It
+pointers to the service routine corresponding to that procedure,
+.It
+a pointer to the input and output arguments,
+.It
+the size of these routines.
+.El
+A server can use the dispatch table to check authorization
+and then to execute the service routine;
+a client library may use it to deal with the details of storage
+management and XDR data conversion.
+.Pp
+The other three synopses shown above are used when
+one does not want to generate all the output files,
+but only a particular one.
+See the
+.Sx EXAMPLES
+section below for examples of
+.Nm
+usage.
+When
+.Nm
+is executed with the
+.Fl s
+option,
+it creates servers for that particular class of transports.
+When
+executed with the
+.Fl n
+option,
+it creates a server for the transport specified by
+.Ar netid .
+If
+.Ar infile
+is not specified,
+.Nm
+accepts the standard input.
+.Pp
+The C preprocessor,
+.Em cc -E
+is run on the input file before it is actually interpreted by
+.Nm .
+For each type of output file,
+.Nm
+defines a special preprocessor symbol for use by the
+.Nm
+programmer:
+.Bl -tag -width indent
+.It RPC_HDR
+defined when compiling into headers
+.It RPC_XDR
+defined when compiling into XDR routines
+.It RPC_SVC
+defined when compiling into server-side stubs
+.It RPC_CLNT
+defined when compiling into client-side stubs
+.It RPC_TBL
+defined when compiling into RPC dispatch tables
+.El
+.Pp
+Any line beginning with
+.Dq %
+is passed directly into the output file,
+uninterpreted by
+.Nm .
+To specify the path name of the C preprocessor use
+.Fl Y
+flag.
+.Pp
+For every data type referred to in
+.Ar infile ,
+.Nm
+assumes that there exists a
+routine with the string
+.Em xdr_
+prepended to the name of the data type.
+If this routine does not exist in the
+.Tn RPC/XDR
+library, it must be provided.
+Providing an undefined data type
+allows customization of
+.Xr xdr 3
+routines.
+.Sh OPTIONS
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Generate all files, including sample files.
+.It Fl b
+Backward compatibility mode.
+Generate transport specific
+.Tn RPC
+code for older versions
+of the operating system.
+.It Fl c
+Compile into
+.Tn XDR
+routines.
+.It Fl C
+Generate ANSI C code.
+This is always done, the flag is only provided for backwards compatibility.
+.It Fl D Ns Ar name
+.It Fl D Ns Ar name=value
+.\".It Fl D Ns Ar name Ns Op Ar =value
+Define a symbol
+.Ar name .
+Equivalent to the
+.Em #define
+directive in the source.
+If no
+.Ar value
+is given,
+.Ar value
+is defined as
+.Em 1 .
+This option may be specified more than once.
+.It Fl h
+Compile into C data-definitions (a header).
+.Fl T
+option can be used in conjunction to produce a
+header which supports
+.Tn RPC
+dispatch tables.
+.It Fl i Ar size
+Size at which to start generating inline code.
+This option is useful for optimization.
+The default size is 5.
+.Pp
+Note: in order to provide backwards compatibility with the older
+.Nm
+on the
+.Fx
+platform, the default is actually 0 (which means
+that inline code generation is disabled by default).
+You must specify
+a non-zero value explicitly to override this default.
+.It Fl I
+Compile support for
+.Xr inetd 8
+in the server side stubs.
+Such servers can be self-started or can be started by
+.Xr inetd 8 .
+When the server is self-started, it backgrounds itself by default.
+A special define symbol
+.Em RPC_SVC_FG
+can be used to run the
+server process in foreground, or the user may simply compile without
+the
+.Fl I
+option.
+.Pp
+If there are no pending client requests, the
+.Xr inetd 8
+servers exit after 120 seconds (default).
+The default can be changed with the
+.Fl K
+option.
+All the error messages for
+.Xr inetd 8
+servers
+are always logged with
+.Xr syslog 3 .
+.Pp
+Note:
+Contrary to some systems, in
+.Fx
+this option is needed to generate
+servers that can be invoked through portmonitors and
+.Xr inetd 8 .
+.It Fl K Ar seconds
+By default, services created using
+.Nm
+and invoked through
+port monitors wait 120 seconds
+after servicing a request before exiting.
+That interval can be changed using the
+.Fl K
+flag.
+To create a server that exits immediately upon servicing a request,
+use
+.Fl K Ar 0 .
+To create a server that never exits, the appropriate argument is
+.Fl K Ar -1 .
+.Pp
+When monitoring for a server,
+some portmonitors
+.Em always
+spawn a new process in response to a service request.
+If it is known that a server will be used with such a monitor, the
+server should exit immediately on completion.
+For such servers,
+.Nm
+should be used with
+.Fl K Ar 0 .
+.It Fl l
+Compile into client-side stubs.
+.It Fl L
+When the servers are started in foreground, use
+.Xr syslog 3
+to log the server errors instead of printing them on the standard
+error.
+.It Fl m
+Compile into server-side stubs,
+but do not generate a
+.Qq main
+routine.
+This option is useful for doing callback-routines
+and for users who need to write their own
+.Qq main
+routine to do initialization.
+.It Fl M
+Generate multithread-safe stubs for passing arguments and results between
+rpcgen generated code and user written code.
+This option is useful
+for users who want to use threads in their code.
+However, the
+.Xr rpc_svc_calls 3
+functions are not yet MT-safe, which means that rpcgen generated server-side
+code will not be MT-safe.
+.It Fl N
+Allow procedures to have multiple arguments.
+It also uses the style of parameter passing that closely resembles C.
+So, when passing an argument to a remote procedure, you do not have to
+pass a pointer to the argument, but can pass the argument itself.
+This behavior is different from the old style of
+.Nm
+generated code.
+To maintain backward compatibility,
+this option is not the default.
+.It Fl n Ar netid
+Compile into server-side stubs for the transport
+specified by
+.Ar netid .
+There should be an entry for
+.Ar netid
+in the
+netconfig database.
+This option may be specified more than once,
+so as to compile a server that serves multiple transports.
+.It Fl o Ar outfile
+Specify the name of the output file.
+If none is specified,
+standard output is used
+.Fl ( c ,
+.Fl h ,
+.Fl l ,
+.Fl m ,
+.Fl n ,
+.Fl s ,
+.Fl \&Sc ,
+.Fl \&Sm ,
+.Fl \&Ss ,
+and
+.Fl t
+modes only).
+.It Fl P
+Compile support for
+port monitors
+in the server side stubs.
+.Pp
+Note:
+Contrary to some systems, in
+.Fx
+this option is needed to generate
+servers that can be monitored.
+.Pp
+If the
+.Fl I
+option has been specified,
+.Fl P
+is turned off automatically.
+.It Fl s Ar nettype
+Compile into server-side stubs for all the
+transports belonging to the class
+.Ar nettype .
+The supported classes are
+.Em netpath ,
+.Em visible ,
+.Em circuit_n ,
+.Em circuit_v ,
+.Em datagram_n ,
+.Em datagram_v ,
+.Em tcp ,
+and
+.Em udp
+(see
+.Xr rpc 3
+for the meanings associated with these classes).
+This option may be specified more than once.
+Note:
+the transports are chosen at run time and not at compile time.
+.It Fl \&Sc
+Generate sample client code that uses remote procedure calls.
+.It Fl \&Sm
+Generate a sample
+.Pa Makefile
+which can be used for compiling the application.
+.It Fl \&Ss
+Generate sample server code that uses remote procedure calls.
+.It Fl t
+Compile into
+.Tn RPC
+dispatch table.
+.It Fl T
+Generate the code to support
+.Tn RPC
+dispatch tables.
+.Pp
+The options
+.Fl c ,
+.Fl h ,
+.Fl l ,
+.Fl m ,
+.Fl s ,
+.Fl \&Sc ,
+.Fl \&Sm ,
+.Fl \&Ss ,
+and
+.Fl t
+are used exclusively to generate a particular type of file,
+while the options
+.Fl D
+and
+.Fl T
+are global and can be used with the other options.
+.It Fl Y Ar pathname
+Give the name of the directory where
+.Nm
+will start looking for the C-preprocessor.
+.El
+.Sh ENVIRONMENT
+If the
+.Ev RPCGEN_CPP
+environment variable is set, its value is used as the command line of the
+C preprocessor to be run on the input file.
+.Sh EXAMPLES
+The following example:
+.Dl example% rpcgen -T prot.x
+.Pp
+generates all the five files:
+.Pa prot.h ,
+.Pa prot_clnt.c ,
+.Pa prot_svc.c ,
+.Pa prot_xdr.c
+and
+.Pa prot_tbl.i .
+.Pp
+The following example sends the C data-definitions (header)
+to the standard output.
+.Dl example% rpcgen -h prot.x
+.Pp
+To send the test version of the
+.Fl D Ns Ar TEST ,
+server side stubs for
+all the transport belonging to the class
+.Ar datagram_n
+to standard output, use:
+.Dl example% rpcgen -s datagram_n -DTEST prot.x
+.Pp
+To create the server side stubs for the transport indicated
+by
+.Ar netid
+tcp,
+use:
+.Dl example% rpcgen -n tcp -o prot_svc.c prot.x
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr rpc 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr syslog 3 ,
+.Xr xdr 3 ,
+.Xr inetd 8
+.Rs
+.%T The rpcgen chapter in the NETP manual
+.Re
diff --git a/usr.bin/rpcinfo/Makefile b/usr.bin/rpcinfo/Makefile
new file mode 100644
index 000000000000..a55485e4f718
--- /dev/null
+++ b/usr.bin/rpcinfo/Makefile
@@ -0,0 +1,9 @@
+PROG= rpcinfo
+SRCS= rpcinfo.c
+MAN= rpcinfo.8
+
+CFLAGS+= -DPORTMAP
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rpcinfo/Makefile.depend b/usr.bin/rpcinfo/Makefile.depend
new file mode 100644
index 000000000000..90cdaad976de
--- /dev/null
+++ b/usr.bin/rpcinfo/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/rpc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rpcinfo/rpcinfo.8 b/usr.bin/rpcinfo/rpcinfo.8
new file mode 100644
index 000000000000..05a31cd44a42
--- /dev/null
+++ b/usr.bin/rpcinfo/rpcinfo.8
@@ -0,0 +1,339 @@
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $NetBSD: rpcinfo.8,v 1.6 2000/06/02 23:19:38 fvdl Exp $
+.Dd August 18, 1992
+.Dt RPCINFO 8
+.Os
+.Sh NAME
+.Nm rpcinfo
+.Nd report RPC information
+.Sh SYNOPSIS
+.Nm
+.Op Fl m | s
+.Op Ar host
+.Nm
+.Op Ar host
+.Nm
+.Fl T Ar transport
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Fl l
+.Op Fl T Ar transport
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Op Fl n Ar portnum
+.Fl u
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Op Fl n Ar portnum
+.Op Fl t
+.Ar host prognum
+.Op Ar versnum
+.Nm
+.Fl a Ar serv_address
+.Fl T Ar transport
+.Ar prognum
+.Op Ar versnum
+.Nm
+.Fl b
+.Op Fl T Ar transport
+.Ar prognum versnum
+.Nm
+.Fl d
+.Op Fl T Ar transport
+.Ar prognum versnum
+.Sh DESCRIPTION
+The
+.Nm
+utility makes an RPC call to an RPC
+server and reports what it finds.
+.Pp
+In the first synopsis,
+.Nm
+lists all the registered RPC services with
+.Nm rpcbind
+on
+.Ar host .
+If
+.Ar host
+is not specified, the local host is the default.
+If
+.Fl s
+is used, the information is displayed in a concise format.
+.Pp
+In the second synopsis,
+.Nm
+lists all the RPC services registered with
+.Nm rpcbind ,
+version 2.
+Also note that the format of the information
+is different in the first and the second synopsis.
+This is because the second synopsis is an older protocol used to
+collect the information displayed (version 2 of the
+.Nm rpcbind
+protocol).
+.Pp
+The third synopsis makes an RPC call to procedure 0
+of
+.Ar prognum
+and
+.Ar versnum
+on the specified
+.Ar host
+and reports whether a response was received.
+.Ar transport
+is the transport which has to be used for contacting the
+given service.
+The remote address of the service is obtained by
+making a call to the remote
+.Nm rpcbind .
+.Pp
+The
+.Ar prognum
+argument is a number that represents an RPC program number
+If a
+.Ar versnum
+is specified,
+.Nm
+attempts to call that version of the specified
+.Ar prognum .
+Otherwise,
+.Nm
+attempts to find all the registered version
+numbers for the specified
+.Ar prognum
+by calling version 0,
+which is presumed not to exist;
+if it does exist,
+.Nm
+attempts to obtain this information by calling
+an extremely high version number instead,
+and attempts to call each registered version.
+Note:
+the version number is required for
+.Fl b
+and
+.Fl d
+options.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl T Ar transport
+Specify the transport on which the service is required.
+If this option is not specified,
+.Nm
+uses the transport specified in the
+.Ev NETPATH
+environment variable, or if that is unset or empty, the transport
+in the
+.Xr netconfig 5
+database is used.
+This is a generic option,
+and can be used in conjunction with other options as
+shown in the
+.Sx SYNOPSIS .
+.It Fl a Ar serv_address
+Use
+.Ar serv_address
+as the (universal) address for the service on
+.Ar transport
+to ping procedure 0
+of the specified
+.Ar prognum
+and report whether a response was received.
+The
+.Fl T
+option is required with the
+.Fl a
+option.
+.Pp
+If
+.Ar versnum
+is not specified,
+.Nm
+tries to ping all
+available version numbers for that program number.
+This option avoids calls to remote
+.Nm rpcbind
+to find the address of the service.
+The
+.Ar serv_address
+is specified in universal address format of the given transport.
+.It Fl b
+Make an RPC broadcast to procedure 0
+of the specified
+.Ar prognum
+and
+.Ar versnum
+and report all hosts that respond.
+If
+.Ar transport
+is specified, it broadcasts its request only on the
+specified transport.
+If broadcasting is not supported by any
+transport,
+an error message is printed.
+Use of broadcasting should be limited because of the potential for adverse
+effect on other systems.
+.It Fl d
+Delete registration for the RPC service of the specified
+.Ar prognum
+and
+.Ar versnum .
+If
+.Ar transport
+is specified,
+unregister the service on only that transport,
+otherwise unregister the service on all
+the transports on which it was registered.
+Only the owner of a service can delete a registration, except the
+super-user who can delete any service.
+.It Fl l
+Display a list of entries with a given
+.Ar prognum
+and
+.Ar versnum
+on the specified
+.Ar host .
+Entries are returned for all transports
+in the same protocol family as that used to contact the remote
+.Nm rpcbind .
+.It Fl m
+Display a table of statistics of
+.Nm rpcbind
+operations on the given
+.Ar host .
+The table shows statistics for each version of
+.Nm rpcbind
+(versions 2, 3 and 4), giving the number of times each procedure was
+requested and successfully serviced, the number and type of remote call
+requests that were made, and information about RPC address lookups that were
+handled.
+This is useful for monitoring RPC activities on
+.Ar host .
+.It Fl n Ar portnum
+Use
+.Ar portnum
+as the port number for the
+.Fl t
+and
+.Fl u
+options instead of the port number given by
+.Nm rpcbind .
+Use of this option avoids a call to the remote
+.Nm rpcbind
+to find out the address of the service.
+This option is made
+obsolete by the
+.Fl a
+option.
+.It Fl p
+Probe
+.Nm rpcbind
+on
+.Ar host
+using version 2 of the
+.Nm rpcbind
+protocol,
+and display a list of all registered RPC programs.
+If
+.Ar host
+is not specified, it defaults to the local host.
+Note: Version 2 of the
+.Nm rpcbind
+protocol was previously known as the portmapper protocol.
+.It Fl s
+Display a concise list of all registered RPC programs on
+.Ar host .
+If
+.Ar host
+is not specified, it defaults to the local host.
+.It Fl t
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using TCP,
+and report whether a response was received.
+This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.It Fl u
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using UDP,
+and report whether a response was received.
+This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.El
+.Sh EXAMPLES
+To show all of the RPC services registered on the local machine use:
+.Pp
+.Dl "example% rpcinfo"
+.Pp
+To show all of the RPC
+services registered with
+.Nm rpcbind
+on the machine named
+.Dq klaxon
+use:
+.Pp
+.Dl "example% rpcinfo klaxon"
+.Pp
+The information displayed by the above commands can be quite lengthy.
+Use the
+.Fl s
+option to display a more concise list:
+.Pp
+.Dl "example$ rpcinfo -s klaxon"
+.Bl -column "program" "version(s)" "unix,tcp,udp,tcp6,udp6" "nlockmgr" "super-user"
+.It "program version(s) netid(s) service owner"
+.It "100000 2,3,4 unix,tcp,udp,tcp6,udp6 rpcbind super-user"
+.It "100008 1 udp,tcp,udp6,tcp6 walld super-user"
+.It "100002 2,1 udp,udp6 rusersd super-user"
+.It "100001 2,3,4 udp,udp6 rstatd super-user"
+.It "100012 1 udp,tcp sprayd super-user"
+.It "100007 3 udp,tcp ypbind super-user"
+.El
+.Pp
+To show whether the RPC
+service with program number
+.Ar prognum
+and version
+.Ar versnum
+is
+registered on the machine named
+.Dq klaxon
+for the transport TCP
+use:
+.Pp
+.Dl "example% rpcinfo -T tcp klaxon prognum versnum"
+.Pp
+To show all RPC
+services registered with version 2 of the
+.Nm rpcbind
+protocol on the local machine use:
+.Pp
+.Dl "example% rpcinfo -p"
+.Pp
+To delete the registration for version
+1 of the
+.Nm walld
+(program number 100008)
+service for all transports use:
+.Pp
+.Dl "example# rpcinfo -d 100008 1"
+or
+.Dl "example# rpcinfo -d walld 1"
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr netconfig 5 ,
+.Xr rpc 5 ,
+.Xr rpcbind 8
diff --git a/usr.bin/rpcinfo/rpcinfo.c b/usr.bin/rpcinfo/rpcinfo.c
new file mode 100644
index 000000000000..5f2dd4433292
--- /dev/null
+++ b/usr.bin/rpcinfo/rpcinfo.c
@@ -0,0 +1,1665 @@
+/* $NetBSD: rpcinfo.c,v 1.15 2000/10/04 20:09:05 mjl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+#include <sys/cdefs.h>
+/*
+ * rpcinfo: ping a particular rpc program
+ * or dump the registered programs on the remote machine.
+ */
+
+/*
+ * We are for now defining PORTMAP here. It doesn't even compile
+ * unless it is defined.
+ */
+#ifndef PORTMAP
+#define PORTMAP
+#endif
+
+/*
+ * If PORTMAP is defined, rpcinfo will talk to both portmapper and
+ * rpcbind programs; else it talks only to rpcbind. In the latter case
+ * all the portmapper specific options such as -u, -t, -p become void.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/rpcent.h>
+#include <rpc/nettype.h>
+#include <rpc/rpc_com.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <ctype.h>
+
+#ifdef PORTMAP /* Support for version 2 portmapper */
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#endif
+
+#define MAXHOSTLEN 256
+#define MIN_VERS ((u_long) 0)
+#define MAX_VERS ((u_long) 4294967295UL)
+#define UNKNOWN "unknown"
+
+/*
+ * Functions to be performed.
+ */
+#define NONE 0 /* no function */
+#define PMAPDUMP 1 /* dump portmapper registrations */
+#define TCPPING 2 /* ping TCP service */
+#define UDPPING 3 /* ping UDP service */
+#define BROADCAST 4 /* ping broadcast service */
+#define DELETES 5 /* delete registration for the service */
+#define ADDRPING 6 /* pings at the given address */
+#define PROGPING 7 /* pings a program on a given host */
+#define RPCBDUMP 8 /* dump rpcbind registrations */
+#define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */
+#define RPCBADDRLIST 10 /* dump addr list about one prog */
+#define RPCBGETSTAT 11 /* Get statistics */
+
+struct netidlist {
+ char *netid;
+ struct netidlist *next;
+};
+
+struct verslist {
+ int vers;
+ struct verslist *next;
+};
+
+struct rpcbdump_short {
+ u_long prog;
+ struct verslist *vlist;
+ struct netidlist *nlist;
+ struct rpcbdump_short *next;
+ char *owner;
+};
+
+
+
+#ifdef PORTMAP
+static void ip_ping(u_short, const char *, int, char **);
+static CLIENT *clnt_com_create(struct sockaddr_in *, u_long, u_long, int *,
+ const char *);
+static void pmapdump(int, char **);
+static void get_inet_address(struct sockaddr_in *, char *);
+#endif
+
+static bool_t reply_proc(void *, struct netbuf *, struct netconfig *);
+static void brdcst(int, char **);
+static void addrping(char *, char *, int, char **);
+static void progping(char *, int, char **);
+static CLIENT *clnt_addr_create(char *, struct netconfig *, u_long, u_long);
+static CLIENT *clnt_rpcbind_create(char *, int, struct netbuf **);
+static CLIENT *getclnthandle(char *, struct netconfig *, u_long,
+ struct netbuf **);
+static CLIENT *local_rpcb(u_long, u_long);
+static int pstatus(CLIENT *, u_long, u_long);
+static void rpcbdump(int, char *, int, char **);
+static void rpcbgetstat(int, char **);
+static void rpcbaddrlist(char *, int, char **);
+static void deletereg(char *, int, char **);
+static void print_rmtcallstat(int, rpcb_stat *);
+static void print_getaddrstat(int, rpcb_stat *);
+static void usage(void);
+static u_long getprognum(char *);
+static u_long getvers(char *);
+static char *spaces(int);
+static bool_t add_version(struct rpcbdump_short *, u_long);
+static bool_t add_netid(struct rpcbdump_short *, char *);
+
+int
+main(int argc, char **argv)
+{
+ register int c;
+ int errflg;
+ int function;
+ char *netid = NULL;
+ char *address = NULL;
+#ifdef PORTMAP
+ char *strptr;
+ u_short portnum = 0;
+#endif
+
+ function = NONE;
+ errflg = 0;
+#ifdef PORTMAP
+ while ((c = getopt(argc, argv, "a:bdlmn:pstT:u")) != -1) {
+#else
+ while ((c = getopt(argc, argv, "a:bdlmn:sT:")) != -1) {
+#endif
+ switch (c) {
+#ifdef PORTMAP
+ case 'p':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = PMAPDUMP;
+ break;
+
+ case 't':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = TCPPING;
+ break;
+
+ case 'u':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = UDPPING;
+ break;
+
+ case 'n':
+ portnum = (u_short) strtol(optarg, &strptr, 10);
+ if (strptr == optarg || *strptr != '\0')
+ errx(1, "%s is illegal port number", optarg);
+ break;
+#endif
+ case 'a':
+ address = optarg;
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = ADDRPING;
+ break;
+ case 'b':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = BROADCAST;
+ break;
+
+ case 'd':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = DELETES;
+ break;
+
+ case 'l':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBADDRLIST;
+ break;
+
+ case 'm':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBGETSTAT;
+ break;
+
+ case 's':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBDUMP_SHORT;
+ break;
+
+ case 'T':
+ netid = optarg;
+ break;
+ case '?':
+ errflg = 1;
+ break;
+ }
+ }
+
+ if (errflg || ((function == ADDRPING) && !netid))
+ usage();
+
+ if (function == NONE) {
+ if (argc - optind > 1)
+ function = PROGPING;
+ else
+ function = RPCBDUMP;
+ }
+
+ switch (function) {
+#ifdef PORTMAP
+ case PMAPDUMP:
+ if (portnum != 0)
+ usage();
+ pmapdump(argc - optind, argv + optind);
+ break;
+
+ case UDPPING:
+ ip_ping(portnum, "udp", argc - optind, argv + optind);
+ break;
+
+ case TCPPING:
+ ip_ping(portnum, "tcp", argc - optind, argv + optind);
+ break;
+#endif
+ case BROADCAST:
+ brdcst(argc - optind, argv + optind);
+ break;
+ case DELETES:
+ deletereg(netid, argc - optind, argv + optind);
+ break;
+ case ADDRPING:
+ addrping(address, netid, argc - optind, argv + optind);
+ break;
+ case PROGPING:
+ progping(netid, argc - optind, argv + optind);
+ break;
+ case RPCBDUMP:
+ case RPCBDUMP_SHORT:
+ rpcbdump(function, netid, argc - optind, argv + optind);
+ break;
+ case RPCBGETSTAT:
+ rpcbgetstat(argc - optind, argv + optind);
+ break;
+ case RPCBADDRLIST:
+ rpcbaddrlist(netid, argc - optind, argv + optind);
+ break;
+ }
+ return (0);
+}
+
+static CLIENT *
+local_rpcb(u_long prog, u_long vers)
+{
+ void *localhandle;
+ struct netconfig *nconf;
+ CLIENT *clnt;
+
+ localhandle = setnetconfig();
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL) {
+ warnx("getnetconfig: %s", nc_sperror());
+ return (NULL);
+ }
+
+ clnt = clnt_tp_create(NULL, prog, vers, nconf);
+ endnetconfig(localhandle);
+ return clnt;
+}
+
+#ifdef PORTMAP
+static CLIENT *
+clnt_com_create(struct sockaddr_in *addr, u_long prog, u_long vers,
+ int *fdp, const char *trans)
+{
+ CLIENT *clnt;
+
+ if (strcmp(trans, "tcp") == 0) {
+ clnt = clnttcp_create(addr, prog, vers, fdp, 0, 0);
+ } else {
+ struct timeval to;
+
+ to.tv_sec = 5;
+ to.tv_usec = 0;
+ clnt = clntudp_create(addr, prog, vers, to, fdp);
+ }
+ if (clnt == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ if (vers == MIN_VERS)
+ printf("program %lu is not available\n", prog);
+ else
+ printf("program %lu version %lu is not available\n",
+ prog, vers);
+ exit(1);
+ }
+ return (clnt);
+}
+
+/*
+ * If portnum is 0, then go and get the address from portmapper, which happens
+ * transparently through clnt*_create(); If version number is not given, it
+ * tries to find out the version number by making a call to version 0 and if
+ * that fails, it obtains the high order and the low order version number. If
+ * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
+ */
+static void
+ip_ping(u_short portnum, const char *trans, int argc, char **argv)
+{
+ CLIENT *client;
+ int fd = RPC_ANYFD;
+ struct timeval to;
+ struct sockaddr_in addr;
+ enum clnt_stat rpc_stat;
+ u_long prognum, vers, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+
+ if (argc < 2 || argc > 3)
+ usage();
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ prognum = getprognum(argv[1]);
+ get_inet_address(&addr, argv[0]);
+ if (argc == 2) { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ vers = MIN_VERS;
+ } else {
+ vers = getvers(argv[2]);
+ }
+ addr.sin_port = htons(portnum);
+ client = clnt_com_create(&addr, prognum, vers, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void, (char *)NULL,
+ to);
+ if (argc != 2) {
+ /* Version number was known */
+ if (pstatus(client, prognum, vers) < 0)
+ exit(1);
+ (void) CLNT_DESTROY(client);
+ return;
+ }
+ /* Version number not known */
+ (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ (void) CLNT_DESTROY(client);
+ addr.sin_port = htons(portnum);
+ client = clnt_com_create(&addr, prognum, MAX_VERS, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ } else {
+ (void) pstatus(client, prognum, MAX_VERS);
+ exit(1);
+ }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
+ }
+ (void) CLNT_DESTROY(client);
+ for (vers = minvers; vers <= maxvers; vers++) {
+ addr.sin_port = htons(portnum);
+ client = clnt_com_create(&addr, prognum, vers, &fd, trans);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (pstatus(client, prognum, vers) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ }
+ if (failure)
+ exit(1);
+ (void) close(fd);
+ return;
+}
+
+/*
+ * Dump all the portmapper registerations
+ */
+static void
+pmapdump(int argc, char **argv)
+{
+ struct sockaddr_in server_addr;
+ struct pmaplist *head = NULL;
+ int socket = RPC_ANYSOCK;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ char *host = NULL;
+
+ if (argc > 1)
+ usage();
+ if (argc == 1) {
+ host = argv[0];
+ get_inet_address(&server_addr, host);
+ server_addr.sin_port = htons(PMAPPORT);
+ client = clnttcp_create(&server_addr, PMAPPROG, PMAPVERS,
+ &socket, 50, 500);
+ } else
+ client = local_rpcb(PMAPPROG, PMAPVERS);
+
+ if (client == NULL) {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR) {
+ /*
+ * "Misc. TLI error" is not too helpful. Most likely
+ * the connection to the remote server timed out, so
+ * this error is at least less perplexing.
+ */
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
+ clnt_pcreateerror("rpcinfo: can't contact portmapper");
+ exit(1);
+ }
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ clnt_st = CLNT_CALL(client, PMAPPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *)&head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ CLNT_GETERR(client, &err);
+ if (err.re_vers.low > PMAPVERS) {
+ if (host)
+ warnx("%s does not support portmapper."
+ "Try rpcinfo %s instead", host,
+ host);
+ else
+ warnx("local host does not support "
+ "portmapper. Try 'rpcinfo' "
+ "instead");
+ }
+ exit(1);
+ }
+ clnt_perror(client, "rpcinfo: can't contact portmapper");
+ exit(1);
+ }
+ if (head == NULL) {
+ printf("No remote programs registered.\n");
+ } else {
+ printf(" program vers proto port service\n");
+ for (; head != NULL; head = head->pml_next) {
+ printf("%10ld%5ld",
+ head->pml_map.pm_prog,
+ head->pml_map.pm_vers);
+ if (head->pml_map.pm_prot == IPPROTO_UDP)
+ printf("%6s", "udp");
+ else if (head->pml_map.pm_prot == IPPROTO_TCP)
+ printf("%6s", "tcp");
+ else if (head->pml_map.pm_prot == IPPROTO_ST)
+ printf("%6s", "local");
+ else
+ printf("%6ld", head->pml_map.pm_prot);
+ printf("%7ld", head->pml_map.pm_port);
+ rpc = getrpcbynumber(head->pml_map.pm_prog);
+ if (rpc)
+ printf(" %s\n", rpc->r_name);
+ else
+ printf("\n");
+ }
+ }
+}
+
+static void
+get_inet_address(struct sockaddr_in *addr, char *host)
+{
+ struct netconfig *nconf;
+ struct addrinfo hints, *res;
+ int error;
+
+ (void) memset((char *)addr, 0, sizeof (*addr));
+ addr->sin_addr.s_addr = inet_addr(host);
+ if (addr->sin_addr.s_addr == INADDR_NONE ||
+ addr->sin_addr.s_addr == INADDR_ANY) {
+ if ((nconf = __rpc_getconfip("udp")) == NULL &&
+ (nconf = __rpc_getconfip("tcp")) == NULL)
+ errx(1, "couldn't find a suitable transport");
+ else {
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET;
+ if ((error = getaddrinfo(host, "rpcbind", &hints, &res))
+ != 0)
+ errx(1, "%s: %s", host, gai_strerror(error));
+ else {
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ }
+ (void) freenetconfigent(nconf);
+ }
+ } else {
+ addr->sin_family = AF_INET;
+ }
+}
+#endif /* PORTMAP */
+
+/*
+ * reply_proc collects replies from the broadcast.
+ * to get a unique list of responses the output of rpcinfo should
+ * be piped through sort(1) and then uniq(1).
+ */
+
+/*ARGSUSED*/
+static bool_t
+reply_proc(void *res, struct netbuf *who, struct netconfig *nconf)
+ /* void *res; Nothing comes back */
+ /* struct netbuf *who; Who sent us the reply */
+ /* struct netconfig *nconf; On which transport the reply came */
+{
+ char *uaddr;
+ char hostbuf[NI_MAXHOST];
+ const char *hostname;
+ struct sockaddr *sa = (struct sockaddr *)who->buf;
+
+ if (getnameinfo(sa, sa->sa_len, hostbuf, NI_MAXHOST, NULL, 0, 0)) {
+ hostname = UNKNOWN;
+ } else {
+ hostname = hostbuf;
+ }
+ uaddr = taddr2uaddr(nconf, who);
+ if (uaddr == NULL) {
+ printf("%s\t%s\n", UNKNOWN, hostname);
+ } else {
+ printf("%s\t%s\n", uaddr, hostname);
+ free((char *)uaddr);
+ }
+ return (FALSE);
+}
+
+static void
+brdcst(int argc, char **argv)
+{
+ enum clnt_stat rpc_stat;
+ u_long prognum, vers;
+
+ if (argc != 2)
+ usage();
+ prognum = getprognum(argv[0]);
+ vers = getvers(argv[1]);
+ rpc_stat = rpc_broadcast(prognum, vers, NULLPROC,
+ (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, (resultproc_t) reply_proc, NULL);
+ if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
+ errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat));
+ exit(0);
+}
+
+static bool_t
+add_version(struct rpcbdump_short *rs, u_long vers)
+{
+ struct verslist *vl;
+
+ for (vl = rs->vlist; vl; vl = vl->next)
+ if (vl->vers == vers)
+ break;
+ if (vl)
+ return (TRUE);
+ vl = (struct verslist *)malloc(sizeof (struct verslist));
+ if (vl == NULL)
+ return (FALSE);
+ vl->vers = vers;
+ vl->next = rs->vlist;
+ rs->vlist = vl;
+ return (TRUE);
+}
+
+static bool_t
+add_netid(struct rpcbdump_short *rs, char *netid)
+{
+ struct netidlist *nl;
+
+ for (nl = rs->nlist; nl; nl = nl->next)
+ if (strcmp(nl->netid, netid) == 0)
+ break;
+ if (nl)
+ return (TRUE);
+ nl = (struct netidlist *)malloc(sizeof (struct netidlist));
+ if (nl == NULL)
+ return (FALSE);
+ nl->netid = netid;
+ nl->next = rs->nlist;
+ rs->nlist = nl;
+ return (TRUE);
+}
+
+static void
+rpcbdump(int dumptype, char *netid, int argc, char **argv)
+{
+ rpcblist_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ struct netidlist *nl;
+ struct verslist *vl;
+ struct rpcbdump_short *rs, *rs_tail;
+ char buf[256];
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ struct rpcbdump_short *rs_head = NULL;
+
+ if (argc > 1)
+ usage();
+ if (argc == 1) {
+ host = argv[0];
+ if (netid == NULL) {
+ client = clnt_rpcbind_create(host, RPCBVERS, NULL);
+ } else {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ nc_perror("rpcinfo: invalid transport");
+ exit(1);
+ }
+ client = getclnthandle(host, nconf, RPCBVERS, NULL);
+ if (nconf)
+ (void) freenetconfigent(nconf);
+ }
+ } else
+ client = local_rpcb(PMAPPROG, RPCBVERS);
+
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ clnt_st = CLNT_CALL(client, RPCBPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ int vers;
+
+ CLNT_GETERR(client, &err);
+ if (err.re_vers.low == RPCBVERS4) {
+ vers = RPCBVERS4;
+ clnt_control(client, CLSET_VERS, (char *)&vers);
+ clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ } else {
+ if (err.re_vers.high == PMAPVERS) {
+ int high, low;
+ struct pmaplist *pmaphead = NULL;
+ rpcblist_ptr list, prev;
+
+ vers = PMAPVERS;
+ clnt_control(client, CLSET_VERS, (char *)&vers);
+ clnt_st = CLNT_CALL(client, PMAPPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_pmaplist_ptr,
+ (char *)&pmaphead, minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ /*
+ * convert to rpcblist_ptr format
+ */
+ for (head = NULL; pmaphead != NULL;
+ pmaphead = pmaphead->pml_next) {
+ list = (rpcblist *)malloc(sizeof (rpcblist));
+ if (list == NULL)
+ goto error;
+ if (head == NULL)
+ head = list;
+ else
+ prev->rpcb_next = (rpcblist_ptr) list;
+
+ list->rpcb_next = NULL;
+ list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
+ list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
+ if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
+ list->rpcb_map.r_netid = "udp";
+ else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
+ list->rpcb_map.r_netid = "tcp";
+ else {
+#define MAXLONG_AS_STRING "2147483648"
+ list->rpcb_map.r_netid =
+ malloc(strlen(MAXLONG_AS_STRING) + 1);
+ if (list->rpcb_map.r_netid == NULL)
+ goto error;
+ sprintf(list->rpcb_map.r_netid, "%6ld",
+ pmaphead->pml_map.pm_prot);
+ }
+ list->rpcb_map.r_owner = UNKNOWN;
+ low = pmaphead->pml_map.pm_port & 0xff;
+ high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
+ list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX");
+ sprintf(&list->rpcb_map.r_addr[8], "%d.%d",
+ high, low);
+ prev = list;
+ }
+ }
+ }
+ } else { /* any other error */
+failed:
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ }
+ if (head == NULL) {
+ printf("No remote programs registered.\n");
+ } else if (dumptype == RPCBDUMP) {
+ printf(
+" program version netid address service owner\n");
+ for (; head != NULL; head = head->rpcb_next) {
+ printf("%10u%5u ",
+ head->rpcb_map.r_prog, head->rpcb_map.r_vers);
+ printf("%-9s ", head->rpcb_map.r_netid);
+ printf("%-22s", head->rpcb_map.r_addr);
+ rpc = getrpcbynumber(head->rpcb_map.r_prog);
+ if (rpc)
+ printf(" %-10s", rpc->r_name);
+ else
+ printf(" %-10s", "-");
+ printf(" %s\n", head->rpcb_map.r_owner);
+ }
+ } else if (dumptype == RPCBDUMP_SHORT) {
+ for (; head != NULL; head = head->rpcb_next) {
+ for (rs = rs_head; rs; rs = rs->next)
+ if (head->rpcb_map.r_prog == rs->prog)
+ break;
+ if (rs == NULL) {
+ rs = (struct rpcbdump_short *)
+ malloc(sizeof (struct rpcbdump_short));
+ if (rs == NULL)
+ goto error;
+ rs->next = NULL;
+ if (rs_head == NULL) {
+ rs_head = rs;
+ rs_tail = rs;
+ } else {
+ rs_tail->next = rs;
+ rs_tail = rs;
+ }
+ rs->prog = head->rpcb_map.r_prog;
+ rs->owner = head->rpcb_map.r_owner;
+ rs->nlist = NULL;
+ rs->vlist = NULL;
+ }
+ if (add_version(rs, head->rpcb_map.r_vers) == FALSE)
+ goto error;
+ if (add_netid(rs, head->rpcb_map.r_netid) == FALSE)
+ goto error;
+ }
+ printf(
+" program version(s) netid(s) service owner\n");
+ for (rs = rs_head; rs; rs = rs->next) {
+ char *p = buf;
+
+ printf("%10ld ", rs->prog);
+ for (vl = rs->vlist; vl; vl = vl->next) {
+ sprintf(p, "%d", vl->vers);
+ p = p + strlen(p);
+ if (vl->next)
+ sprintf(p++, ",");
+ }
+ printf("%-10s", buf);
+ buf[0] = '\0';
+ for (nl = rs->nlist; nl; nl = nl->next) {
+ strlcat(buf, nl->netid, sizeof(buf));
+ if (nl->next)
+ strlcat(buf, ",", sizeof(buf));
+ }
+ printf("%-32s", buf);
+ rpc = getrpcbynumber(rs->prog);
+ if (rpc)
+ printf(" %-11s", rpc->r_name);
+ else
+ printf(" %-11s", "-");
+ printf(" %s\n", rs->owner);
+ }
+ }
+ clnt_destroy(client);
+ return;
+error: warnx("no memory");
+ return;
+}
+
+static char nullstring[] = "\000";
+
+static void
+rpcbaddrlist(char *netid, int argc, char **argv)
+{
+ rpcb_entry_list_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ RPCB parms;
+ struct netbuf *targaddr;
+
+ if (argc != 3)
+ usage();
+ host = argv[0];
+ if (netid == NULL) {
+ client = clnt_rpcbind_create(host, RPCBVERS4, &targaddr);
+ } else {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL) {
+ nc_perror("rpcinfo: invalid transport");
+ exit(1);
+ }
+ client = getclnthandle(host, nconf, RPCBVERS4, &targaddr);
+ if (nconf)
+ (void) freenetconfigent(nconf);
+ }
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ parms.r_prog = getprognum(argv[1]);
+ parms.r_vers = getvers(argv[2]);
+ parms.r_netid = client->cl_netid;
+ if (targaddr == NULL) {
+ parms.r_addr = nullstring; /* for XDRing */
+ } else {
+ /*
+ * We also send the remote system the address we
+ * used to contact it in case it can help it
+ * connect back with us
+ */
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent(client->cl_netid);
+ if (nconf != NULL) {
+ parms.r_addr = taddr2uaddr(nconf, targaddr);
+ if (parms.r_addr == NULL)
+ parms.r_addr = nullstring;
+ freenetconfigent(nconf);
+ } else {
+ parms.r_addr = nullstring; /* for XDRing */
+ }
+ free(targaddr->buf);
+ free(targaddr);
+ }
+ parms.r_owner = nullstring;
+
+ if (CLNT_CALL(client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb,
+ (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *) &head, minutetimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ if (head == NULL) {
+ printf("No remote programs registered.\n");
+ } else {
+ printf(
+ " program vers tp_family/name/class address\t\t service\n");
+ for (; head != NULL; head = head->rpcb_entry_next) {
+ rpcb_entry *re;
+ char buf[128];
+
+ re = &head->rpcb_entry_map;
+ printf("%10u%3u ",
+ parms.r_prog, parms.r_vers);
+ sprintf(buf, "%s/%s/%s ",
+ re->r_nc_protofmly, re->r_nc_proto,
+ re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
+ re->r_nc_semantics == NC_TPI_COTS ? "cots" :
+ "cots_ord");
+ printf("%-24s", buf);
+ printf("%-24s", re->r_maddr);
+ rpc = getrpcbynumber(parms.r_prog);
+ if (rpc)
+ printf(" %-13s", rpc->r_name);
+ else
+ printf(" %-13s", "-");
+ printf("\n");
+ }
+ }
+ clnt_destroy(client);
+ return;
+}
+
+/*
+ * monitor rpcbind
+ */
+static void
+rpcbgetstat(int argc, char **argv)
+{
+ rpcb_stat_byvers inf;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ char *host;
+ int i, j;
+ rpcbs_addrlist *pa;
+ rpcbs_rmtcalllist *pr;
+ int cnt, flen;
+#define MAXFIELD 64
+ char fieldbuf[MAXFIELD];
+#define MAXLINE 256
+ char linebuf[MAXLINE];
+ char *cp, *lp;
+ const char *pmaphdr[] = {
+ "NULL", "SET", "UNSET", "GETPORT",
+ "DUMP", "CALLIT"
+ };
+ const char *rpcb3hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U"
+ };
+ const char *rpcb4hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
+ };
+
+#define TABSTOP 8
+
+ if (argc >= 1) {
+ host = argv[0];
+ client = clnt_rpcbind_create(host, RPCBVERS4, NULL);
+ } else
+ client = local_rpcb(PMAPPROG, RPCBVERS4);
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo: can't contact rpcbind");
+ exit(1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ memset((char *)&inf, 0, sizeof (rpcb_stat_byvers));
+ if (CLNT_CALL(client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcb_stat_byvers, (char *)&inf, minutetimeout)
+ != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo: can't contact rpcbind: ");
+ exit(1);
+ }
+ printf("PORTMAP (version 2) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_2; i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case PMAPPROC_SET:
+ sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
+ break;
+ case PMAPPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_2_STAT].unsetinfo);
+ break;
+ case PMAPPROC_GETPORT:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case PMAPPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", pmaphdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(pmaphdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT]) {
+ printf("PMAP_RMTCALL call statistics\n");
+ print_rmtcallstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf("\n");
+ }
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT]) {
+ printf("PMAP_GETPORT call statistics\n");
+ print_getaddrstat(RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf("\n");
+ }
+
+ printf("RPCBIND (version 3) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_3; i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case RPCBPROC_SET:
+ sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_3_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", rpcb3hdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(rpcb3hdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT]) {
+ printf("RPCB_RMTCALL (version 3) call statistics\n");
+ print_rmtcallstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf("\n");
+ }
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR]) {
+ printf("RPCB_GETADDR (version 3) call statistics\n");
+ print_getaddrstat(RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf("\n");
+ }
+
+ printf("RPCBIND (version 4) statistics\n");
+
+ for (j = 0; j <= 9; j += 9) { /* Just two iterations for printing */
+ lp = linebuf;
+ for (i = j; i <= MAX(8, rpcb_highproc_4 - 9 + j); i++) {
+ fieldbuf[0] = '\0';
+ switch (i) {
+ case RPCBPROC_SET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_4_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf(fieldbuf, "%d/",
+ inf[RPCBVERS_4_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa;
+ pa = pa->next)
+ cnt += pa->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr;
+ pr = pr->next)
+ cnt += pr->success;
+ sprintf(fieldbuf, "%d/", cnt);
+ break;
+ default: break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen(fieldbuf);
+ /*
+ * XXX: We also add RPCBPROC_GETADDRLIST queries to
+ * RPCB_GETADDR because rpcbind includes the
+ * RPCB_GETADDRLIST successes in RPCB_GETADDR.
+ */
+ if (i != RPCBPROC_GETADDR)
+ sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
+ else
+ sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
+ flen = strlen(fieldbuf);
+ printf("%s%s", rpcb4hdr[i],
+ spaces((TABSTOP * (1 + flen / TABSTOP))
+ - strlen(rpcb4hdr[i])));
+ sprintf(lp, "%s%s", fieldbuf,
+ spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
+ - flen)));
+ lp += (flen + cnt);
+ }
+ printf("\n%s\n", linebuf);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT]) {
+ printf("\n");
+ printf("RPCB_RMTCALL (version 4) call statistics\n");
+ print_rmtcallstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR]) {
+ printf("\n");
+ printf("RPCB_GETADDR (version 4) call statistics\n");
+ print_getaddrstat(RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+ clnt_destroy(client);
+}
+
+/*
+ * Delete registeration for this (prog, vers, netid)
+ */
+static void
+deletereg(char *netid, int argc, char **argv)
+{
+ struct netconfig *nconf = NULL;
+
+ if (argc != 2)
+ usage();
+ if (netid) {
+ nconf = getnetconfigent(netid);
+ if (nconf == NULL)
+ errx(1, "netid %s not supported", netid);
+ }
+ if ((rpcb_unset(getprognum(argv[0]), getvers(argv[1]), nconf)) == 0)
+ errx(1,
+ "could not delete registration for prog %s version %s",
+ argv[0], argv[1]);
+}
+
+/*
+ * Create and return a handle for the given nconf.
+ * Exit if cannot create handle.
+ */
+static CLIENT *
+clnt_addr_create(char *address, struct netconfig *nconf,
+ u_long prog, u_long vers)
+{
+ CLIENT *client;
+ static struct netbuf *nbuf;
+ static int fd = RPC_ANYFD;
+
+ if (fd == RPC_ANYFD) {
+ if ((fd = __rpc_nconf2fd(nconf)) == -1) {
+ rpc_createerr.cf_stat = RPC_TLIERROR;
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ /* Convert the uaddr to taddr */
+ nbuf = uaddr2taddr(nconf, address);
+ if (nbuf == NULL)
+ errx(1, "no address for client handle");
+ }
+ client = clnt_tli_create(fd, nconf, nbuf, prog, vers, 0, 0);
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ return (client);
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is not contacted for this service. The requests are
+ * sent directly to the services themselves.
+ */
+static void
+addrping(char *address, char *netid, int argc, char **argv)
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_long prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+ int fd;
+
+ if (argc < 1 || argc > 2 || (netid == NULL))
+ usage();
+ nconf = getnetconfigent(netid);
+ if (nconf == (struct netconfig *)NULL)
+ errx(1, "could not find %s", netid);
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ prognum = getprognum(argv[0]);
+ if (argc == 1) { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ } else {
+ versnum = getvers(argv[1]);
+ }
+ client = clnt_addr_create(address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (argc == 2) {
+ /* Version number was known */
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
+ }
+ /* Version number not known */
+ (void) CLNT_CONTROL(client, CLSET_FD_NCLOSE, (char *)NULL);
+ (void) CLNT_CONTROL(client, CLGET_FD, (char *)&fd);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ (void) CLNT_DESTROY(client);
+ client = clnt_addr_create(address, nconf, prognum, MAX_VERS);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ } else {
+ (void) pstatus(client, prognum, MAX_VERS);
+ exit(1);
+ }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
+ }
+ (void) CLNT_DESTROY(client);
+ for (versnum = minvers; versnum <= maxvers; versnum++) {
+ client = clnt_addr_create(address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ }
+ (void) close(fd);
+ if (failure)
+ exit(1);
+ return;
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is *contacted* for this service. The requests are
+ * then sent directly to the services themselves.
+ */
+static void
+progping(char *netid, int argc, char **argv)
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_long prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+
+ if (argc < 2 || argc > 3 || (netid == NULL))
+ usage();
+ prognum = getprognum(argv[1]);
+ if (argc == 2) { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ } else {
+ versnum = getvers(argv[2]);
+ }
+ if (netid) {
+ nconf = getnetconfigent(netid);
+ if (nconf == (struct netconfig *)NULL)
+ errx(1, "could not find %s", netid);
+ client = clnt_tp_create(argv[0], prognum, versnum, nconf);
+ } else {
+ client = clnt_create(argv[0], prognum, versnum, "NETPATH");
+ }
+ if (client == (CLIENT *)NULL) {
+ clnt_pcreateerror("rpcinfo");
+ exit(1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (argc == 3) {
+ /* Version number was known */
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
+ }
+ /* Version number not known */
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ versnum = MAX_VERS;
+ (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC,
+ (xdrproc_t) xdr_void, (char *)NULL,
+ (xdrproc_t) xdr_void, (char *)NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH) {
+ clnt_geterr(client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ } else if (rpc_stat == RPC_SUCCESS) {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ } else {
+ (void) pstatus(client, prognum, MAX_VERS);
+ exit(1);
+ }
+ } else {
+ (void) pstatus(client, prognum, (u_long)0);
+ exit(1);
+ }
+ for (versnum = minvers; versnum <= maxvers; versnum++) {
+ (void) CLNT_CONTROL(client, CLSET_VERS, (char *)&versnum);
+ rpc_stat = CLNT_CALL(client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *)NULL, (xdrproc_t) xdr_void,
+ (char *)NULL, to);
+ if (pstatus(client, prognum, versnum) < 0)
+ failure = 1;
+ }
+ (void) CLNT_DESTROY(client);
+ if (failure)
+ exit(1);
+ return;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: rpcinfo [-m | -s] [host]\n");
+#ifdef PORTMAP
+ fprintf(stderr, " rpcinfo -p [host]\n");
+#endif
+ fprintf(stderr, " rpcinfo -T netid host prognum [versnum]\n");
+ fprintf(stderr, " rpcinfo -l host prognum versnum\n");
+#ifdef PORTMAP
+ fprintf(stderr,
+" rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
+#endif
+ fprintf(stderr,
+" rpcinfo -a serv_address -T netid prognum [version]\n");
+ fprintf(stderr, " rpcinfo -b prognum versnum\n");
+ fprintf(stderr, " rpcinfo -d [-T netid] prognum versnum\n");
+ exit(1);
+}
+
+static u_long
+getprognum (char *arg)
+{
+ char *strptr;
+ register struct rpcent *rpc;
+ register u_long prognum;
+ char *tptr = arg;
+
+ while (*tptr && isdigit(*tptr++));
+ if (*tptr || isalpha(*(tptr - 1))) {
+ rpc = getrpcbyname(arg);
+ if (rpc == NULL)
+ errx(1, "%s is unknown service", arg);
+ prognum = rpc->r_number;
+ } else {
+ prognum = strtol(arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0')
+ errx(1, "%s is illegal program number", arg);
+ }
+ return (prognum);
+}
+
+static u_long
+getvers(char *arg)
+{
+ char *strptr;
+ register u_long vers;
+
+ vers = (int) strtol(arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0')
+ errx(1, "%s is illegal version number", arg);
+ return (vers);
+}
+
+/*
+ * This routine should take a pointer to an "rpc_err" structure, rather than
+ * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
+ * a CLIENT structure rather than a pointer to an "rpc_err" structure.
+ * As such, we have to keep the CLIENT structure around in order to print
+ * a good error message.
+ */
+static int
+pstatus(register CLIENT *client, u_long prog, u_long vers)
+{
+ struct rpc_err rpcerr;
+
+ clnt_geterr(client, &rpcerr);
+ if (rpcerr.re_status != RPC_SUCCESS) {
+ clnt_perror(client, "rpcinfo");
+ printf("program %lu version %lu is not available\n",
+ prog, vers);
+ return (-1);
+ } else {
+ printf("program %lu version %lu ready and waiting\n",
+ prog, vers);
+ return (0);
+ }
+}
+
+static CLIENT *
+clnt_rpcbind_create(char *host, int rpcbversnum, struct netbuf **targaddr)
+{
+ static const char *tlist[3] = {
+ "circuit_n", "circuit_v", "datagram_v"
+ };
+ int i;
+ struct netconfig *nconf;
+ CLIENT *clnt = NULL;
+ void *handle;
+
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ for (i = 0; i < 3; i++) {
+ if ((handle = __rpc_setconf(tlist[i])) == NULL)
+ continue;
+ while (clnt == (CLIENT *)NULL) {
+ if ((nconf = __rpc_getconf(handle)) == NULL) {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+ clnt = getclnthandle(host, nconf, rpcbversnum,
+ targaddr);
+ }
+ if (clnt)
+ break;
+ __rpc_endconf(handle);
+ }
+ return (clnt);
+}
+
+static CLIENT*
+getclnthandle(char *host, struct netconfig *nconf,
+ u_long rpcbversnum, struct netbuf **targaddr)
+{
+ struct netbuf addr;
+ struct addrinfo hints, *res;
+ CLIENT *client = NULL;
+
+ /* Get the address of the rpcbind */
+ memset(&hints, 0, sizeof hints);
+ if (getaddrinfo(host, "rpcbind", &hints, &res) != 0) {
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ return (NULL);
+ }
+ addr.len = addr.maxlen = res->ai_addrlen;
+ addr.buf = res->ai_addr;
+ client = clnt_tli_create(RPC_ANYFD, nconf, &addr, RPCBPROG,
+ rpcbversnum, 0, 0);
+ if (client) {
+ if (targaddr != NULL) {
+ *targaddr =
+ (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (*targaddr != NULL) {
+ (*targaddr)->maxlen = addr.maxlen;
+ (*targaddr)->len = addr.len;
+ (*targaddr)->buf = (char *)malloc(addr.len);
+ if ((*targaddr)->buf != NULL) {
+ memcpy((*targaddr)->buf, addr.buf,
+ addr.len);
+ }
+ }
+ }
+ } else {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR) {
+ /*
+ * Assume that the other system is dead; this is a
+ * better error to display to the user.
+ */
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
+ }
+ freeaddrinfo(res);
+ return (client);
+}
+
+static void
+print_rmtcallstat(int rtype, rpcb_stat *infp)
+{
+ register rpcbs_rmtcalllist_ptr pr;
+ struct rpcent *rpc;
+
+ if (rtype == RPCBVERS_4_STAT)
+ printf(
+ "prog\t\tvers\tproc\tnetid\tindirect success failure\n");
+ else
+ printf("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
+ for (pr = infp->rmtinfo; pr; pr = pr->next) {
+ rpc = getrpcbynumber(pr->prog);
+ if (rpc)
+ printf("%-16s", rpc->r_name);
+ else
+ printf("%-16d", pr->prog);
+ printf("%d\t%d\t%s\t",
+ pr->vers, pr->proc, pr->netid);
+ if (rtype == RPCBVERS_4_STAT)
+ printf("%d\t ", pr->indirect);
+ printf("%d\t%d\n", pr->success, pr->failure);
+ }
+}
+
+static void
+print_getaddrstat(int rtype, rpcb_stat *infp)
+{
+ rpcbs_addrlist_ptr al;
+ register struct rpcent *rpc;
+
+ printf("prog\t\tvers\tnetid\t success\tfailure\n");
+ for (al = infp->addrinfo; al; al = al->next) {
+ rpc = getrpcbynumber(al->prog);
+ if (rpc)
+ printf("%-16s", rpc->r_name);
+ else
+ printf("%-16d", al->prog);
+ printf("%d\t%s\t %-12d\t%d\n",
+ al->vers, al->netid,
+ al->success, al->failure);
+ }
+}
+
+static char *
+spaces(int howmany)
+{
+ static char space_array[] = /* 64 spaces */
+ " ";
+
+ if (howmany <= 0 || howmany > sizeof (space_array)) {
+ return ("");
+ }
+ return (&space_array[sizeof (space_array) - howmany - 1]);
+}
diff --git a/usr.bin/rs/Makefile b/usr.bin/rs/Makefile
new file mode 100644
index 000000000000..ed98f6826ce4
--- /dev/null
+++ b/usr.bin/rs/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG_CXX= rs
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rs/Makefile.depend b/usr.bin/rs/Makefile.depend
new file mode 100644
index 000000000000..76a8d2cdc8ca
--- /dev/null
+++ b/usr.bin/rs/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libc++ \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rs/rs.1 b/usr.bin/rs/rs.1
new file mode 100644
index 000000000000..dd0c12c33950
--- /dev/null
+++ b/usr.bin/rs/rs.1
@@ -0,0 +1,244 @@
+.\" Copyright (c) 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.
+.\"
+.Dd April 7, 2015
+.Dt RS 1
+.Os
+.Sh NAME
+.Nm rs
+.Nd reshape a data array
+.Sh SYNOPSIS
+.Nm
+.Oo
+.Fl Oo Cm csCS Oc Ns Op Ar x
+.Oo Cm kKgGw Oc Ns Op Ar N
+.Cm tTeEnyjhHmz
+.Oc
+.Op Ar rows Op Ar cols
+.Sh DESCRIPTION
+The
+.Nm
+utility reads the standard input, interpreting each line as a row
+of blank-separated entries in an array,
+transforms the array according to the options,
+and writes it on the standard output.
+With no arguments it transforms stream input into a columnar
+format convenient for terminal viewing.
+.Pp
+The shape of the input array is deduced from the number of lines
+and the number of columns on the first line.
+If that shape is inconvenient, a more useful one might be
+obtained by skipping some of the input with the
+.Fl k
+option.
+Other options control interpretation of the input columns.
+.Pp
+The shape of the output array is influenced by the
+.Ar rows
+and
+.Ar cols
+specifications, which should be positive integers.
+If only one of them is a positive integer,
+.Nm
+computes a value for the other which will accommodate
+all of the data.
+When necessary, missing data are supplied in a manner
+specified by the options and surplus data are deleted.
+There are options to control presentation of the output columns,
+including transposition of the rows and columns.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c Ns Ar x
+Input columns are delimited by the single character
+.Ar x .
+A missing
+.Ar x
+is taken to be `^I'.
+.It Fl s Ns Ar x
+Like
+.Fl c ,
+but maximal strings of
+.Ar x
+are delimiters.
+.It Fl C Ns Ar x
+Output columns are delimited by the single character
+.Ar x .
+A missing
+.Ar x
+is taken to be `^I'.
+.It Fl S Ns Ar x
+Like
+.Fl C ,
+but padded strings of
+.Ar x
+are delimiters.
+.It Fl t
+Fill in the rows of the output array using the columns of the
+input array, that is, transpose the input while honoring any
+.Ar rows
+and
+.Ar cols
+specifications.
+.It Fl T
+Print the pure transpose of the input, ignoring any
+.Ar rows
+or
+.Ar cols
+specification.
+.It Fl k Ns Ar N
+Ignore the first
+.Ar N
+lines of input.
+.It Fl K Ns Ar N
+Like
+.Fl k ,
+but print the ignored lines.
+.It Fl g Ns Ar N
+The gutter width (inter-column space), normally 2, is taken to be
+.Ar N .
+.It Fl G Ns Ar N
+The gutter width has
+.Ar N
+percent of the maximum column width added to it.
+.It Fl e
+Consider each line of input as an array entry.
+.It Fl n
+On lines having fewer entries than the first line,
+use null entries to pad out the line.
+Normally, missing entries are taken from the next line of input.
+.It Fl y
+If there are too few entries to make up the output dimensions,
+pad the output by recycling the input from the beginning.
+Normally, the output is padded with blanks.
+.It Fl h
+Print the shape of the input array and do nothing else.
+The shape is just the number of lines and the number of
+entries on the first line.
+.It Fl H
+Like
+.Fl h ,
+but also print the length of each line.
+.It Fl j
+Right adjust entries within columns.
+.It Fl w Ns Ar N
+The width of the display, normally 80, is taken to be the positive
+integer
+.Ar N .
+.It Fl m
+Do not trim excess delimiters from the ends of the output array.
+.It Fl z
+Adapt column widths to fit the largest entries appearing in them.
+.El
+.Pp
+With no arguments,
+.Nm
+transposes its input, and assumes one array entry per input line
+unless the first non-ignored line is longer than the display width.
+Option letters which take numerical arguments interpret a missing
+number as zero unless otherwise indicated.
+.Sh EXAMPLES
+The
+.Nm
+utility can be used as a filter to convert the stream output
+of certain programs (e.g.,
+.Xr spell 1 ,
+.Xr du 1 ,
+.Xr file 1 ,
+.Xr look 1 ,
+.Xr nm 1 ,
+.Xr who 1 ,
+and
+.Xr wc 1 )
+into a convenient ``window'' format, as in
+.Bd -literal -offset indent
+% who | rs
+.Ed
+.Pp
+This function has been incorporated into the
+.Xr ls 1
+program, though for most programs with similar output
+.Nm
+suffices.
+.Pp
+To convert stream input into vector output and back again, use
+.Bd -literal -offset indent
+% rs 1 0 | rs 0 1
+.Ed
+.Pp
+A 10 by 10 array of random numbers from 1 to 100 and
+its transpose can be generated with
+.Bd -literal -offset indent
+% jot \-r 100 | rs 10 10 | tee array | rs \-T > tarray
+.Ed
+.Pp
+In the editor
+.Xr vi 1 ,
+a file consisting of a multi-line vector with 9 elements per line
+can undergo insertions and deletions,
+and then be neatly reshaped into 9 columns with
+.Bd -literal -offset indent
+:1,$!rs 0 9
+.Ed
+.Pp
+Finally, to sort a database by the first line of each 4-line field, try
+.Bd -literal -offset indent
+% rs \-eC 0 4 | sort | rs \-c 0 1
+.Ed
+.Sh SEE ALSO
+.Xr jot 1 ,
+.Xr pr 1 ,
+.Xr sort 1 ,
+.Xr vi 1
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+.An John A. Kunze
+.Sh BUGS
+.Bl -item
+.It
+Handles only two dimensional arrays.
+.It
+The algorithm currently reads the whole file into memory,
+so files that do not fit in memory will not be reshaped.
+.It
+Fields cannot be defined yet on character positions.
+.It
+Re-ordering of columns is not yet possible.
+.It
+There are too many options.
+.It
+Multibyte characters are not recognized.
+.It
+Lines longer than
+.Dv LINE_MAX
+(2048) bytes are not processed and result in immediate termination of
+.Nm .
+.El
diff --git a/usr.bin/rs/rs.cc b/usr.bin/rs/rs.cc
new file mode 100644
index 000000000000..8989288e3ec7
--- /dev/null
+++ b/usr.bin/rs/rs.cc
@@ -0,0 +1,462 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+/*
+ * rs - reshape a data array
+ * Author: John Kunze, Office of Comp. Affairs, UCB
+ * BEWARE: lots of unfinished edges
+ */
+
+#include <err.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+static long flags;
+#define TRANSPOSE 000001
+#define MTRANSPOSE 000002
+#define ONEPERLINE 000004
+#define ONEISEPONLY 000010
+#define ONEOSEPONLY 000020
+#define NOTRIMENDCOL 000040
+#define SQUEEZE 000100
+#define SHAPEONLY 000200
+#define DETAILSHAPE 000400
+#define RIGHTADJUST 001000
+#define NULLPAD 002000
+#define RECYCLE 004000
+#define SKIPPRINT 010000
+#define ICOLBOUNDS 020000
+#define OCOLBOUNDS 040000
+#define ONEPERCHAR 0100000
+#define NOARGS 0200000
+
+static short *colwidths;
+static std::vector<char *> elem;
+static char *curline;
+static size_t curlen;
+static size_t irows, icols;
+static size_t orows = 0, ocols = 0;
+static size_t maxlen;
+static int skip;
+static int propgutter;
+static char isep = ' ', osep = ' ';
+static char blank[] = "";
+static size_t owidth = 80, gutter = 2;
+
+static void getargs(int, char *[]);
+static void getfile(void);
+static int get_line(void);
+static long getnum(const char *);
+static void prepfile(void);
+static void prints(char *, int);
+static void putfile(void);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ getargs(argc, argv);
+ getfile();
+ if (flags & SHAPEONLY) {
+ printf("%zu %zu\n", irows, icols);
+ exit(0);
+ }
+ prepfile();
+ putfile();
+ exit(0);
+}
+
+static void
+getfile(void)
+{
+ char *p, *sp;
+ char *endp;
+ int c;
+ int multisep = (flags & ONEISEPONLY ? 0 : 1);
+ int nullpad = flags & NULLPAD;
+ size_t len, padto;
+
+ while (skip--) {
+ c = get_line();
+ if (flags & SKIPPRINT)
+ puts(curline);
+ if (c == EOF)
+ return;
+ }
+ get_line();
+ if (flags & NOARGS && curlen < owidth)
+ flags |= ONEPERLINE;
+ if (flags & ONEPERLINE)
+ icols = 1;
+ else /* count cols on first line */
+ for (p = curline, endp = curline + curlen; p < endp; p++) {
+ if (*p == isep && multisep)
+ continue;
+ icols++;
+ while (*p && *p != isep)
+ p++;
+ }
+ do {
+ if (flags & ONEPERLINE) {
+ elem.push_back(curline);
+ if (maxlen < curlen)
+ maxlen = curlen;
+ irows++;
+ continue;
+ }
+ for (p = curline, endp = curline + curlen; p < endp; p++) {
+ if (*p == isep && multisep)
+ continue; /* eat up column separators */
+ if (*p == isep) /* must be an empty column */
+ elem.push_back(blank);
+ else /* store column entry */
+ elem.push_back(p);
+ sp = p;
+ while (p < endp && *p != isep)
+ p++; /* find end of entry */
+ *p = '\0'; /* mark end of entry */
+ len = p - sp;
+ if (maxlen < len) /* update maxlen */
+ maxlen = len;
+ }
+ irows++; /* update row count */
+ if (nullpad) { /* pad missing entries */
+ padto = irows * icols;
+ elem.resize(padto, blank);
+ }
+ } while (get_line() != EOF);
+}
+
+static void
+putfile(void)
+{
+ size_t i, j, k;
+
+ if (flags & TRANSPOSE)
+ for (i = 0; i < orows; i++) {
+ for (j = i; j < elem.size(); j += orows)
+ prints(elem[j], (j - i) / orows);
+ putchar('\n');
+ }
+ else
+ for (i = k = 0; i < orows; i++) {
+ for (j = 0; j < ocols; j++, k++)
+ if (k < elem.size())
+ prints(elem[k], j);
+ putchar('\n');
+ }
+}
+
+static void
+prints(char *s, int col)
+{
+ int n;
+ char *p = s;
+
+ while (*p)
+ p++;
+ n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
+ if (flags & RIGHTADJUST)
+ while (n-- > 0)
+ putchar(osep);
+ for (p = s; *p; p++)
+ putchar(*p);
+ while (n-- > 0)
+ putchar(osep);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
+ exit(1);
+}
+
+static void
+prepfile(void)
+{
+ size_t i, j;
+ size_t colw, max, n, orig_size, padto;
+
+ if (elem.empty())
+ exit(0);
+ gutter += maxlen * propgutter / 100.0;
+ colw = maxlen + gutter;
+ if (flags & MTRANSPOSE) {
+ orows = icols;
+ ocols = irows;
+ }
+ else if (orows == 0 && ocols == 0) { /* decide rows and cols */
+ ocols = owidth / colw;
+ if (ocols == 0) {
+ warnx("display width %zu is less than column width %zu",
+ owidth, colw);
+ ocols = 1;
+ }
+ if (ocols > elem.size())
+ ocols = elem.size();
+ orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0);
+ }
+ else if (orows == 0) /* decide on rows */
+ orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0);
+ else if (ocols == 0) /* decide on cols */
+ ocols = elem.size() / orows + (elem.size() % orows ? 1 : 0);
+ padto = orows * ocols;
+ orig_size = elem.size();
+ if (flags & RECYCLE) {
+ for (i = 0; elem.size() < padto; i++)
+ elem.push_back(elem[i % orig_size]);
+ }
+ if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
+ errx(1, "malloc");
+ if (flags & SQUEEZE) {
+ if (flags & TRANSPOSE) {
+ auto it = elem.begin();
+ for (i = 0; i < ocols; i++) {
+ max = 0;
+ for (j = 0; it != elem.end() && j < orows; j++)
+ if ((n = strlen(*it++)) > max)
+ max = n;
+ colwidths[i] = max + gutter;
+ }
+ } else {
+ for (i = 0; i < ocols; i++) {
+ max = 0;
+ for (j = i; j < elem.size(); j += ocols)
+ if ((n = strlen(elem[j])) > max)
+ max = n;
+ colwidths[i] = max + gutter;
+ }
+ }
+ }
+ /* for (i = 0; i < orows; i++) {
+ for (j = i; j < elem.size(); j += orows)
+ prints(elem[j], (j - i) / orows);
+ putchar('\n');
+ }
+ else {
+ auto it = elem.begin();
+ for (i = 0; i < orows; i++) {
+ for (j = 0; j < ocols; j++)
+ prints(*it++, j);
+ putchar('\n');
+ }*/
+ else
+ for (i = 0; i < ocols; i++)
+ colwidths[i] = colw;
+ if (!(flags & NOTRIMENDCOL)) {
+ if (flags & RIGHTADJUST)
+ colwidths[0] -= gutter;
+ else
+ colwidths[ocols - 1] = 0;
+ }
+ /*for (i = 0; i < ocols; i++)
+ warnx("%d is colwidths, nelem %zu", colwidths[i], elem.size());*/
+}
+
+#define BSIZE (LINE_MAX * 2)
+static char ibuf[BSIZE];
+
+static int
+get_line(void) /* get line; maintain curline, curlen; manage storage */
+{
+ static int putlength;
+ static char *endblock = ibuf + BSIZE;
+ char *p;
+ int c, i;
+
+ if (irows == 0) {
+ curline = ibuf;
+ putlength = flags & DETAILSHAPE;
+ }
+ else if (skip <= 0) { /* don't waste storage */
+ curline += curlen + 1;
+ if (putlength) { /* print length, recycle storage */
+ printf(" %zu line %zu\n", curlen, irows);
+ curline = ibuf;
+ }
+ }
+ if (!putlength && endblock - curline < LINE_MAX + 1) { /* need storage */
+ /*ww = endblock-curline; tt += ww;*/
+ /*printf("#wasted %d total %d\n",ww,tt);*/
+ if (!(curline = (char *) malloc(BSIZE)))
+ errx(1, "file too large");
+ endblock = curline + BSIZE;
+ /*printf("#endb %d curline %d\n",endblock,curline);*/
+ }
+ for (p = curline, i = 0;; *p++ = c, i++) {
+ if ((c = getchar()) == EOF)
+ break;
+ if (i >= LINE_MAX)
+ errx(1, "maximum line length (%d) exceeded", LINE_MAX);
+ if (c == '\n')
+ break;
+ }
+ *p = '\0';
+ curlen = i;
+ return(c);
+}
+
+static void
+getargs(int ac, char *av[])
+{
+ long val;
+ int ch;
+
+ if (ac == 1) {
+ flags |= NOARGS | TRANSPOSE;
+ }
+
+ while ((ch = getopt(ac, av, "C::EG:HK:S::Tc::eg:hjk:mns::tw:yz")) != -1)
+ switch (ch) {
+ case 'T':
+ flags |= MTRANSPOSE;
+ /* FALLTHROUGH */
+ case 't':
+ flags |= TRANSPOSE;
+ break;
+ case 'c': /* input col. separator */
+ flags |= ONEISEPONLY;
+ /* FALLTHROUGH */
+ case 's': /* one or more allowed */
+ if (optarg != NULL)
+ isep = *optarg;
+ else
+ isep = '\t'; /* default is ^I */
+ break;
+ case 'C':
+ flags |= ONEOSEPONLY;
+ /* FALLTHROUGH */
+ case 'S':
+ if (optarg != NULL)
+ osep = *optarg;
+ else
+ osep = '\t'; /* default is ^I */
+ break;
+ case 'w': /* window width, default 80 */
+ val = getnum(optarg);
+ if (val <= 0)
+ errx(1, "width must be a positive integer");
+ owidth = val;
+ break;
+ case 'K': /* skip N lines */
+ flags |= SKIPPRINT;
+ /* FALLTHROUGH */
+ case 'k': /* skip, do not print */
+ skip = getnum(optarg);
+ if (skip < 1)
+ skip = 1;
+ break;
+ case 'm':
+ flags |= NOTRIMENDCOL;
+ break;
+ case 'g': /* gutter space */
+ gutter = getnum(optarg);
+ break;
+ case 'G':
+ propgutter = getnum(optarg);
+ break;
+ case 'e': /* each line is an entry */
+ flags |= ONEPERLINE;
+ break;
+ case 'E':
+ flags |= ONEPERCHAR;
+ break;
+ case 'j': /* right adjust */
+ flags |= RIGHTADJUST;
+ break;
+ case 'n': /* null padding for missing values */
+ flags |= NULLPAD;
+ break;
+ case 'y':
+ flags |= RECYCLE;
+ break;
+ case 'H': /* print shape only */
+ flags |= DETAILSHAPE;
+ /* FALLTHROUGH */
+ case 'h':
+ flags |= SHAPEONLY;
+ break;
+ case 'z': /* squeeze col width */
+ flags |= SQUEEZE;
+ break;
+ /*case 'p':
+ ipagespace = atoi(optarg); (default is 1)
+ break;*/
+ default:
+ usage();
+ }
+
+ av += optind;
+ ac -= optind;
+
+ /*if (!osep)
+ osep = isep;*/
+ switch (ac) {
+#if 0
+ case 3:
+ opages = atoi(av[2]);
+ /* FALLTHROUGH */
+#endif
+ case 2:
+ val = strtol(av[1], NULL, 10);
+ if (val >= 0)
+ ocols = val;
+ /* FALLTHROUGH */
+ case 1:
+ val = strtol(av[0], NULL, 10);
+ if (val >= 0)
+ orows = val;
+ /* FALLTHROUGH */
+ case 0:
+ break;
+ default:
+ errx(1, "too many arguments");
+ }
+}
+
+static long
+getnum(const char *p)
+{
+ char *ep;
+ long val;
+
+ val = strtol(p, &ep, 10);
+ if (*ep != '\0')
+ errx(1, "invalid integer %s", p);
+ return (val);
+}
diff --git a/usr.bin/rs/tests/Makefile b/usr.bin/rs/tests/Makefile
new file mode 100644
index 000000000000..a11660690401
--- /dev/null
+++ b/usr.bin/rs/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH+= rs_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/rs/tests/rs_test.sh b/usr.bin/rs/tests/rs_test.sh
new file mode 100644
index 000000000000..cb53b08cde96
--- /dev/null
+++ b/usr.bin/rs/tests/rs_test.sh
@@ -0,0 +1,396 @@
+#
+# Copyright 2017 Shivansh
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+
+atf_test_case c_flag
+c_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'c'"
+}
+
+c_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 8
+" rs -c, 2 <<EOF
+1,2,3,4,5,6,7,8
+EOF
+}
+
+atf_test_case s_flag
+s_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 's'"
+}
+
+s_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 8
+" rs -s% 2 <<EOF
+1%%2%%3%4%5%%%6%%%7%8
+EOF
+
+}
+
+atf_test_case C_flag
+C_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'C'"
+}
+
+C_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1,2,3,4,
+5,6,7,8,
+" rs -C, 2 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case S_flag
+S_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'S'"
+}
+
+S_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1,,2,,3,,4
+5,,6,,7,,8
+" rs -S, 2 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case t_flag
+t_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 't'"
+}
+
+t_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 4 7
+2 5 8
+3 6
+" rs -t 3 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case T_flag
+T_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'T'"
+}
+
+T_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1
+2
+3
+" rs -T <<EOF
+1 2 3
+EOF
+}
+
+atf_test_case k_flag
+k_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'k'"
+}
+
+k_flag_body()
+{
+ atf_check -s exit:0 -o inline:"3 4 5
+6 7 8
+" rs -k 1 2 <<EOF
+1 2
+3 4 5 6
+7 8
+EOF
+}
+
+atf_test_case K_flag
+K_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'K'"
+}
+
+K_flag_body()
+{
+ atf_check -s exit:0 -o inline:"
+" rs -K 1 < /dev/null
+}
+
+atf_test_case g_flag
+g_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'g'"
+}
+
+g_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 8
+" rs -g 1 2 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case G_flag
+G_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'G'"
+}
+
+G_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 acbdefghij
+" rs -G 50 2 <<EOF
+1 2 3 4 5 6 7 acbdefghij
+EOF
+}
+
+atf_test_case e_flag
+e_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'e'"
+}
+
+e_flag_body()
+{
+ atf_check -s exit:0 -o inline:"
+" rs -e < /dev/null
+}
+
+atf_test_case n_flag
+n_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'n'"
+}
+
+n_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3
+4 5
+6 7
+" rs -n 0 3 <<EOF
+1 2 3
+4 5
+6 7
+EOF
+}
+
+atf_test_case y_flag
+y_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'y'"
+}
+
+y_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3
+4 5 6
+7 8 1
+" rs -y 3 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case h_flag
+h_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'h'"
+}
+
+h_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 0
+" rs -h < /dev/null
+}
+
+atf_test_case H_flag
+H_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'H'"
+}
+
+H_flag_body()
+{
+ atf_check -s exit:0 -o inline:" 0 line 1
+1 0
+" rs -H < /dev/null
+}
+
+atf_test_case j_flag
+j_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'j'"
+}
+
+j_flag_body()
+{
+ atf_check -s exit:0 -o inline:" 1 2 3
+abc def ghi
+" rs -j 2 <<EOF
+1 2 3 abc def ghi
+EOF
+}
+
+atf_test_case m_flag
+m_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'm'"
+}
+
+m_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3
+abc def ghi
+" rs -m 2 <<EOF
+1 2 3 abc def ghi
+EOF
+}
+
+atf_test_case z_flag
+z_flag_head()
+{
+ atf_set "descr" "Verify the usage of option 'z'"
+}
+
+z_flag_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 acbdefghij
+" rs -z 2 <<EOF
+1 2 3 4 5 6 7 acbdefghij
+EOF
+}
+
+atf_test_case invalid_usage
+invalid_usage_head()
+{
+ atf_set "descr" "Verify that an invalid usage with a supported option produces a valid error message"
+}
+
+invalid_usage_body()
+{
+ atf_check -s not-exit:0 -e inline:"rs: option requires an argument -- w
+usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]
+" rs -w
+}
+
+atf_test_case no_arguments
+no_arguments_head()
+{
+ atf_set "descr" "Verify that rs(1) executes successfully and produces a valid output when invoked without any arguments"
+}
+
+no_arguments_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4 5 6 7 8
+" rs <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case rows_2
+rows_2_head()
+{
+ atf_set "descr" "Simple output with 2 rows"
+}
+
+rows_2_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3 4
+5 6 7 8
+" rs 2 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case rows_3
+rows_3_head()
+{
+ atf_set "descr" "Simple output with 3 rows"
+}
+
+rows_3_body()
+{
+ atf_check -s exit:0 -o inline:"1 2 3
+4 5 6
+7 8
+" rs 3 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_test_case rows_4
+rows_4_head()
+{
+ atf_set "descr" "Simple output with 4 rows"
+}
+
+rows_4_body()
+{
+ atf_check -s exit:0 -o inline:"1 2
+3 4
+5 6
+7 8
+" rs 4 <<EOF
+1 2 3 4 5 6 7 8
+EOF
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case c_flag
+ atf_add_test_case s_flag
+ atf_add_test_case C_flag
+ atf_add_test_case S_flag
+ atf_add_test_case t_flag
+ atf_add_test_case T_flag
+ atf_add_test_case k_flag
+ atf_add_test_case K_flag
+ atf_add_test_case g_flag
+ atf_add_test_case G_flag
+ atf_add_test_case e_flag
+ atf_add_test_case n_flag
+ atf_add_test_case y_flag
+ atf_add_test_case h_flag
+ atf_add_test_case H_flag
+ atf_add_test_case j_flag
+ atf_add_test_case m_flag
+ atf_add_test_case z_flag
+ atf_add_test_case invalid_usage
+ atf_add_test_case no_arguments
+ atf_add_test_case rows_2
+ atf_add_test_case rows_3
+ atf_add_test_case rows_4
+}
diff --git a/usr.bin/rup/Makefile b/usr.bin/rup/Makefile
new file mode 100644
index 000000000000..8cc5dc0f1af0
--- /dev/null
+++ b/usr.bin/rup/Makefile
@@ -0,0 +1,5 @@
+PROG= rup
+
+LIBADD= rpcsvc
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rup/Makefile.depend b/usr.bin/rup/Makefile.depend
new file mode 100644
index 000000000000..210baeaabfd6
--- /dev/null
+++ b/usr.bin/rup/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/librpcsvc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rup/rup.1 b/usr.bin/rup/rup.1
new file mode 100644
index 000000000000..090b1541b23e
--- /dev/null
+++ b/usr.bin/rup/rup.1
@@ -0,0 +1,93 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 1985, 1991 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.
+.\"
+.Dd June 7, 1993
+.Dt RUP 1
+.Os
+.Sh NAME
+.Nm rup
+.Nd remote status display
+.Sh SYNOPSIS
+.Nm
+.Op Ar host ...
+.Sh DESCRIPTION
+The
+.Nm
+utility displays a summary of the current system status of a particular
+.Ar host
+or all hosts on the local network.
+The output shows the current time of day, how long the system has
+been up,
+and the load averages.
+The load average numbers give the number of jobs in the run queue
+averaged over 1, 5 and 15 minutes.
+.Pp
+The
+.Xr rpc.rstatd 8
+daemon must be running on the remote host for this command to
+work.
+The
+.Nm
+utility uses an RPC protocol defined in
+.In rpcsvc/rstat.x .
+.Sh EXAMPLES
+.Bd -literal
+example% rup otherhost
+otherhost 7:36am up 6 days, 16:45, load average: 0.20, 0.23, 0.18
+example%
+.Ed
+.Sh DIAGNOSTICS
+.Bl -diag
+.It rup: RPC: Program not registered
+The
+.Xr rpc.rstatd 8
+daemon has not been started on the remote host.
+.It rup: RPC: Timed out
+A communication error occurred.
+Either the network is
+excessively congested, or the
+.Xr rpc.rstatd 8
+daemon has terminated on the remote host.
+.It rup: RPC: Port mapper failure - RPC: Timed out
+The remote host is not running the portmapper (see
+.Xr rpcbind 8 ) ,
+and cannot accommodate any RPC-based services.
+The host may be down.
+.El
+.Sh SEE ALSO
+.Xr rpc.rstatd 8 ,
+.Xr rpcbind 8
+.Sh HISTORY
+The
+.Nm
+command
+appeared in
+.Tn Sun-OS .
+.Sh BUGS
+The sorting options are not implemented.
diff --git a/usr.bin/rup/rup.c b/usr.bin/rup/rup.c
new file mode 100644
index 000000000000..5f605f55b413
--- /dev/null
+++ b/usr.bin/rup/rup.c
@@ -0,0 +1,240 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1993, John Brezak
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/socket.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#undef FSHIFT /* Use protocol's shift and scale values */
+#undef FSCALE
+
+#include <rpcsvc/rstat.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#define HOST_WIDTH 15
+
+static struct host_list {
+ struct host_list *next;
+ struct in_addr addr;
+} *hosts;
+
+static int
+search_host(struct in_addr addr)
+{
+ struct host_list *hp;
+
+ if (!hosts)
+ return(0);
+
+ for (hp = hosts; hp != NULL; hp = hp->next) {
+ if (hp->addr.s_addr == addr.s_addr)
+ return(1);
+ }
+ return(0);
+}
+
+static void
+remember_host(struct in_addr addr)
+{
+ struct host_list *hp;
+
+ if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
+ errx(1, "no memory");
+ hp->addr.s_addr = addr.s_addr;
+ hp->next = hosts;
+ hosts = hp;
+}
+
+static bool_t
+rstat_reply(statstime *host_stat, struct sockaddr_in *raddrp)
+{
+ struct tm *tmp_time;
+ struct tm host_time;
+ struct tm host_uptime;
+ char days_buf[16];
+ char hours_buf[16];
+ struct hostent *hp;
+ char *host;
+ time_t tmp_time_t;
+
+ if (search_host(raddrp->sin_addr))
+ return(0);
+
+ hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
+ sizeof(struct in_addr), AF_INET);
+ if (hp)
+ host = hp->h_name;
+ else
+ host = inet_ntoa(raddrp->sin_addr);
+
+ /* truncate hostname to fit nicely into field */
+ if (strlen(host) > HOST_WIDTH)
+ host[HOST_WIDTH] = '\0';
+
+ printf("%-*s\t", HOST_WIDTH, host);
+
+ tmp_time_t = host_stat->curtime.tv_sec;
+ tmp_time = localtime(&tmp_time_t);
+ host_time = *tmp_time;
+
+ host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
+
+ tmp_time_t = host_stat->curtime.tv_sec;
+ tmp_time = gmtime(&tmp_time_t);
+ host_uptime = *tmp_time;
+
+ #define updays (host_stat->curtime.tv_sec / 86400)
+ if (host_uptime.tm_yday != 0)
+ sprintf(days_buf, "%3d day%s, ", updays,
+ (updays > 1) ? "s" : "");
+ else
+ days_buf[0] = '\0';
+
+ if (host_uptime.tm_hour != 0)
+ sprintf(hours_buf, "%2d:%02d, ",
+ host_uptime.tm_hour, host_uptime.tm_min);
+ else
+ if (host_uptime.tm_min != 0)
+ sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min);
+ else if (host_stat->curtime.tv_sec < 60)
+ sprintf(hours_buf, "%2d secs, ", host_uptime.tm_sec);
+ else
+ hours_buf[0] = '\0';
+
+ printf(" %2d:%02d%cm up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
+ (host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12,
+ host_time.tm_min,
+ (host_time.tm_hour >= 12) ? 'p' : 'a',
+ days_buf,
+ hours_buf,
+ (double)host_stat->avenrun[0]/FSCALE,
+ (double)host_stat->avenrun[1]/FSCALE,
+ (double)host_stat->avenrun[2]/FSCALE);
+
+ remember_host(raddrp->sin_addr);
+ return(0);
+}
+
+static int
+onehost(char *host)
+{
+ CLIENT *rstat_clnt;
+ statstime host_stat;
+ struct sockaddr_in addr;
+ struct hostent *hp;
+ struct timeval tv;
+
+ hp = gethostbyname(host);
+ if (hp == NULL) {
+ warnx("unknown host \"%s\"", host);
+ return(-1);
+ }
+
+ rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
+ if (rstat_clnt == NULL) {
+ warnx("%s %s", host, clnt_spcreateerror(""));
+ return(-1);
+ }
+
+ bzero((char *)&host_stat, sizeof(host_stat));
+ tv.tv_sec = 15; /* XXX ??? */
+ tv.tv_usec = 0;
+ if (clnt_call(rstat_clnt, RSTATPROC_STATS,
+ (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) {
+ warnx("%s: %s", host, clnt_sperror(rstat_clnt, host));
+ clnt_destroy(rstat_clnt);
+ return(-1);
+ }
+
+ memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(int));
+ rstat_reply(&host_stat, &addr);
+ clnt_destroy(rstat_clnt);
+ return (0);
+}
+
+static void
+allhosts(void)
+{
+ statstime host_stat;
+ enum clnt_stat clnt_stat;
+
+ clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
+ (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_statstime, &host_stat,
+ (resultproc_t)rstat_reply);
+ if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
+ errx(1, "%s", clnt_sperrno(clnt_stat));
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: rup [host ...]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "?")) != -1)
+ switch (ch) {
+ default:
+ usage();
+ }
+
+ setlinebuf(stdout);
+ if (argc == optind)
+ allhosts();
+ else {
+ for (; optind < argc; optind++)
+ (void) onehost(argv[optind]);
+ }
+ exit(0);
+}
diff --git a/usr.bin/ruptime/Makefile b/usr.bin/ruptime/Makefile
new file mode 100644
index 000000000000..5c51c068ae73
--- /dev/null
+++ b/usr.bin/ruptime/Makefile
@@ -0,0 +1,5 @@
+PROG= ruptime
+
+PACKAGE=rcmds
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ruptime/Makefile.depend b/usr.bin/ruptime/Makefile.depend
new file mode 100644
index 000000000000..528bba446e46
--- /dev/null
+++ b/usr.bin/ruptime/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/protocols \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ruptime/ruptime.1 b/usr.bin/ruptime/ruptime.1
new file mode 100644
index 000000000000..effa5716843f
--- /dev/null
+++ b/usr.bin/ruptime/ruptime.1
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1983, 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd August 8, 2017
+.Dt RUPTIME 1
+.Os
+.Sh NAME
+.Nm ruptime
+.Nd show host status of local machines
+.Sh SYNOPSIS
+.Nm
+.Op Fl alrtu
+.Op Ar host ...
+.Sh DESCRIPTION
+The
+.Nm
+utility gives a status line like
+.Xr uptime 1
+for each machine on the local network; these are formed from packets
+broadcast by each host on the network once every three minutes.
+.Pp
+If no operands are given,
+.Nm
+displays uptime status for all machines;
+otherwise only those hosts specified on the command line are displayed.
+If hosts are specified on the command line, the sort order is equivalent
+to the order hosts were specified on the command line.
+.Pp
+Machines for which no status report has been received for 11
+minutes are shown as being down, and machines for which no status
+report has been received for 4 days are not shown in the list at all.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Include all users.
+By default, if a user has not typed to the system for
+an hour or more, then the user will be omitted from the output.
+.It Fl l
+Sort by load average.
+.It Fl r
+Reverse the sort order.
+.It Fl t
+Sort by uptime.
+.It Fl u
+Sort by number of users.
+.El
+.Pp
+The default listing is sorted by host name.
+.Sh FILES
+.Bl -tag -width /var/rwho/whod.* -compact
+.It Pa /var/rwho/whod.*
+data files
+.El
+.Sh SEE ALSO
+.Xr rwho 1 ,
+.Xr uptime 1 ,
+.Xr rwhod 8
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.Bx 4.2 .
diff --git a/usr.bin/ruptime/ruptime.c b/usr.bin/ruptime/ruptime.c
new file mode 100644
index 000000000000..4978e928b5e7
--- /dev/null
+++ b/usr.bin/ruptime/ruptime.c
@@ -0,0 +1,310 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1993, 1994
+ * 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.
+ */
+
+#include <sys/param.h>
+
+#include <protocols/rwhod.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static struct hs {
+ struct whod hs_wd;
+ int hs_nusers;
+} *hs;
+#define LEFTEARTH(h) (now - (h) > 4*24*60*60)
+#define ISDOWN(h) (now - (h)->hs_wd.wd_recvtime > 11 * 60)
+#define WHDRSIZE __offsetof(struct whod, wd_we)
+
+static size_t nhosts;
+static time_t now;
+static int rflg = 1;
+static DIR *dirp;
+
+static int hscmp(const void *, const void *);
+static char *interval(time_t, const char *);
+static int iwidth(int);
+static int lcmp(const void *, const void *);
+static void ruptime(const char *, int, int (*)(const void *, const void *));
+static int tcmp(const void *, const void *);
+static int ucmp(const void *, const void *);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ int (*cmp)(const void *, const void *);
+ int aflg, ch;
+
+ aflg = 0;
+ cmp = hscmp;
+ while ((ch = getopt(argc, argv, "alrut")) != -1)
+ switch (ch) {
+ case 'a':
+ aflg = 1;
+ break;
+ case 'l':
+ cmp = lcmp;
+ break;
+ case 'r':
+ rflg = -1;
+ break;
+ case 't':
+ cmp = tcmp;
+ break;
+ case 'u':
+ cmp = ucmp;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
+ err(1, "%s", _PATH_RWHODIR);
+
+ ruptime(*argv, aflg, cmp);
+ while (*argv++ != NULL) {
+ if (*argv == NULL)
+ break;
+ ruptime(*argv, aflg, cmp);
+ }
+ exit(0);
+}
+
+static char *
+interval(time_t tval, const char *updown)
+{
+ static char resbuf[32];
+ int days, hours, minutes;
+
+ if (tval < 0) {
+ (void)snprintf(resbuf, sizeof(resbuf), "%s ??:??", updown);
+ return (resbuf);
+ }
+ /* Round to minutes. */
+ minutes = (tval + (60 - 1)) / 60;
+ hours = minutes / 60;
+ minutes %= 60;
+ days = hours / 24;
+ hours %= 24;
+ if (days)
+ (void)snprintf(resbuf, sizeof(resbuf),
+ "%s %4d+%02d:%02d", updown, days, hours, minutes);
+ else
+ (void)snprintf(resbuf, sizeof(resbuf),
+ "%s %2d:%02d", updown, hours, minutes);
+ return (resbuf);
+}
+
+/* Width to print a small nonnegative integer. */
+static int
+iwidth(int w)
+{
+ if (w < 10)
+ return (1);
+ if (w < 100)
+ return (2);
+ if (w < 1000)
+ return (3);
+ if (w < 10000)
+ return (4);
+ return (5);
+}
+
+#define HS(a) ((const struct hs *)(a))
+
+/* Alphabetical comparison. */
+static int
+hscmp(const void *a1, const void *a2)
+{
+ return (rflg *
+ strcmp(HS(a1)->hs_wd.wd_hostname, HS(a2)->hs_wd.wd_hostname));
+}
+
+/* Load average comparison. */
+static int
+lcmp(const void *a1, const void *a2)
+{
+ if (ISDOWN(HS(a1)))
+ if (ISDOWN(HS(a2)))
+ return (tcmp(a1, a2));
+ else
+ return (rflg);
+ else if (ISDOWN(HS(a2)))
+ return (-rflg);
+ else
+ return (rflg *
+ (HS(a2)->hs_wd.wd_loadav[0] - HS(a1)->hs_wd.wd_loadav[0]));
+}
+
+static void
+ruptime(const char *host, int aflg, int (*cmp)(const void *, const void *))
+{
+ struct hs *hsp;
+ struct whod *wd;
+ struct whoent *we;
+ struct dirent *dp;
+ int fd, hostnamewidth, i, loadavwidth[3], userswidth, w;
+ size_t hspace;
+ ssize_t cc;
+
+ rewinddir(dirp);
+ hsp = NULL;
+ hostnamewidth = 0;
+ loadavwidth[0] = 4;
+ loadavwidth[1] = 4;
+ loadavwidth[2] = 4;
+ userswidth = 1;
+ (void)time(&now);
+ for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) {
+ if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
+ continue;
+ if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) {
+ warn("%s", dp->d_name);
+ continue;
+ }
+
+ if (nhosts == hspace) {
+ if ((hs =
+ realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL)
+ err(1, NULL);
+ hsp = hs + nhosts;
+ }
+
+ wd = &hsp->hs_wd;
+ cc = read(fd, wd, sizeof(*wd));
+ (void)close(fd);
+ if (cc < (ssize_t)WHDRSIZE)
+ continue;
+
+ if (host != NULL && strcasecmp(wd->wd_hostname, host) != 0)
+ continue;
+ if (LEFTEARTH(wd->wd_recvtime))
+ continue;
+
+ if (hostnamewidth < (int)strlen(wd->wd_hostname))
+ hostnamewidth = (int)strlen(wd->wd_hostname);
+
+ if (!ISDOWN(hsp)) {
+ for (i = 0; i < 3; i++) {
+ w = iwidth(wd->wd_loadav[i] / 100) + 3;
+ if (loadavwidth[i] < w)
+ loadavwidth[i] = w;
+ }
+ for (hsp->hs_nusers = 0, we = &wd->wd_we[0];
+ (char *)(we + 1) <= (char *)wd + cc; we++)
+ if (aflg || we->we_idle < 3600)
+ ++hsp->hs_nusers;
+ if (userswidth < iwidth(hsp->hs_nusers))
+ userswidth = iwidth(hsp->hs_nusers);
+ }
+
+ ++hsp;
+ ++nhosts;
+ }
+ if (nhosts == 0) {
+ if (host == NULL)
+ errx(1, "no hosts in %s", _PATH_RWHODIR);
+ else
+ warnx("host %s not in %s", host, _PATH_RWHODIR);
+ }
+
+ qsort(hs, nhosts, sizeof(hs[0]), cmp);
+ w = userswidth + loadavwidth[0] + loadavwidth[1] + loadavwidth[2];
+ if (hostnamewidth + w > 41)
+ hostnamewidth = 41 - w; /* limit to 79 cols */
+ for (i = 0; i < (int)nhosts; i++) {
+ hsp = &hs[i];
+ wd = &hsp->hs_wd;
+ if (ISDOWN(hsp)) {
+ (void)printf("%-*.*s %s\n",
+ hostnamewidth, hostnamewidth, wd->wd_hostname,
+ interval(now - hsp->hs_wd.wd_recvtime, "down"));
+ continue;
+ }
+ (void)printf(
+ "%-*.*s %s, %*d user%s load %*.2f, %*.2f, %*.2f\n",
+ hostnamewidth, hostnamewidth, wd->wd_hostname,
+ interval((time_t)wd->wd_sendtime -
+ (time_t)wd->wd_boottime, " up"),
+ userswidth, hsp->hs_nusers,
+ hsp->hs_nusers == 1 ? ", " : "s,",
+ loadavwidth[0], wd->wd_loadav[0] / 100.0,
+ loadavwidth[1], wd->wd_loadav[1] / 100.0,
+ loadavwidth[2], wd->wd_loadav[2] / 100.0);
+ }
+ free(hs);
+ hs = NULL;
+}
+
+/* Number of users comparison. */
+static int
+ucmp(const void *a1, const void *a2)
+{
+ if (ISDOWN(HS(a1)))
+ if (ISDOWN(HS(a2)))
+ return (tcmp(a1, a2));
+ else
+ return (rflg);
+ else if (ISDOWN(HS(a2)))
+ return (-rflg);
+ else
+ return (rflg * (HS(a2)->hs_nusers - HS(a1)->hs_nusers));
+}
+
+/* Uptime comparison. */
+static int
+tcmp(const void *a1, const void *a2)
+{
+ return (rflg * (
+ (ISDOWN(HS(a2)) ? HS(a2)->hs_wd.wd_recvtime - now
+ : HS(a2)->hs_wd.wd_sendtime - HS(a2)->hs_wd.wd_boottime)
+ -
+ (ISDOWN(HS(a1)) ? HS(a1)->hs_wd.wd_recvtime - now
+ : HS(a1)->hs_wd.wd_sendtime - HS(a1)->hs_wd.wd_boottime)
+ ));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: ruptime [-alrtu] [host ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/rusers/Makefile b/usr.bin/rusers/Makefile
new file mode 100644
index 000000000000..f3b3a8bd7db0
--- /dev/null
+++ b/usr.bin/rusers/Makefile
@@ -0,0 +1,5 @@
+PROG = rusers
+
+LIBADD= rpcsvc
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rusers/Makefile.depend b/usr.bin/rusers/Makefile.depend
new file mode 100644
index 000000000000..210baeaabfd6
--- /dev/null
+++ b/usr.bin/rusers/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/librpcsvc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rusers/rusers.1 b/usr.bin/rusers/rusers.1
new file mode 100644
index 000000000000..4444c3dbd539
--- /dev/null
+++ b/usr.bin/rusers/rusers.1
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1983, 1990 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.
+.\"
+.Dd April 23, 1991
+.Dt RUSERS 1
+.Os
+.Sh NAME
+.Nm rusers
+.Nd who is logged in to machines on local network
+.Sh SYNOPSIS
+.Nm
+.Op Fl al
+.Op Ar host ...
+.Sh DESCRIPTION
+The
+.Nm
+command produces output similar to
+.Xr who 1 ,
+but for the list of
+.Ar host Ns s
+or all machines on the local
+network.
+For each
+.Ar host
+responding to the
+.Nm
+query,
+the hostname with the names of the users currently logged
+on is printed on each line.
+The
+.Nm
+command will wait for
+one minute to catch late responders.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Print all machines responding even if no one is currently logged in.
+.It Fl l
+Print a long format listing.
+This includes the user name, host name,
+tty that the user is logged in to, the date and time the user
+logged in, the amount of time since the user typed on the keyboard,
+and the remote host they logged in from (if applicable).
+.El
+.Sh DIAGNOSTICS
+.Bl -diag
+.It rusers: RPC: Program not registered
+The
+.Xr rpc.rusersd 8
+daemon has not been started on the remote host.
+.It rusers: RPC: Timed out
+A communication error occurred.
+Either the network is
+excessively congested, or the
+.Xr rpc.rusersd 8
+daemon has terminated on the remote host.
+.It rusers: "RPC: Port mapper failure - RPC: Timed out"
+The remote host is not running the portmapper (see
+.Xr rpcbind 8 ) ,
+and cannot accommodate any RPC-based services.
+The host may be down.
+.El
+.Sh SEE ALSO
+.Xr rwho 1 ,
+.Xr users 1 ,
+.Xr who 1 ,
+.Xr rpc.rusersd 8 ,
+.Xr rpcbind 8
+.Sh HISTORY
+The
+.Nm
+command
+appeared in
+.Em Sun-OS .
+.Sh BUGS
+The sorting options are not implemented.
diff --git a/usr.bin/rusers/rusers.c b/usr.bin/rusers/rusers.c
new file mode 100644
index 000000000000..413de53c304b
--- /dev/null
+++ b/usr.bin/rusers/rusers.c
@@ -0,0 +1,250 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1993, John Brezak
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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/socket.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcsvc/rnusers.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <timeconv.h>
+#include <unistd.h>
+
+#define MAX_INT 0x7fffffff
+#define HOST_WIDTH 20
+#define LINE_WIDTH 15
+
+static int longopt;
+static int allopt;
+
+static struct host_list {
+ struct host_list *next;
+ struct in_addr addr;
+} *hosts;
+
+static int
+search_host(struct in_addr addr)
+{
+ struct host_list *hp;
+
+ if (hosts == NULL)
+ return (0);
+
+ for (hp = hosts; hp != NULL; hp = hp->next) {
+ if (hp->addr.s_addr == addr.s_addr)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+remember_host(struct in_addr addr)
+{
+ struct host_list *hp;
+
+ if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL)
+ errx(1, "no memory");
+ hp->addr.s_addr = addr.s_addr;
+ hp->next = hosts;
+ hosts = hp;
+}
+
+static int
+rusers_reply(void *replyp, struct sockaddr_in *raddrp)
+{
+ unsigned int x;
+ int idle;
+ char date[32], idle_time[64], remote[64];
+ struct hostent *hp;
+ utmpidlearr *up, u;
+ char *host;
+ int days, hours, minutes, seconds;
+
+ up = &u;
+ memcpy(up, replyp, sizeof(*up));
+ if (search_host(raddrp->sin_addr))
+ return (0);
+
+ if (!allopt && up->utmpidlearr_len == 0)
+ return (0);
+
+ hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
+ sizeof(struct in_addr), AF_INET);
+ if (hp != NULL)
+ host = hp->h_name;
+ else
+ host = inet_ntoa(raddrp->sin_addr);
+
+ if (!longopt)
+ printf("%-*s ", HOST_WIDTH, host);
+
+ for (x = 0; x < up->utmpidlearr_len; x++) {
+ time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time);
+ strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1);
+
+ idle = up->utmpidlearr_val[x].ui_idle;
+ sprintf(idle_time, " :%02d", idle);
+ if (idle == MAX_INT)
+ strcpy(idle_time, "??");
+ else if (idle == 0)
+ strcpy(idle_time, "");
+ else {
+ seconds = idle;
+ days = seconds / (60 * 60 * 24);
+ seconds %= (60 * 60 * 24);
+ hours = seconds / (60 * 60);
+ seconds %= (60 * 60);
+ minutes = seconds / 60;
+ seconds %= 60;
+ if (idle > 60)
+ sprintf(idle_time, "%d:%02d", minutes, seconds);
+ if (idle >= (60 * 60))
+ sprintf(idle_time, "%d:%02d:%02d",
+ hours, minutes, seconds);
+ if (idle >= (24 * 60 * 60))
+ sprintf(idle_time, "%d days, %d:%02d:%02d",
+ days, hours, minutes, seconds);
+ }
+
+ strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host,
+ sizeof(remote) - 1);
+ if (strlen(remote) != 0)
+ sprintf(remote, "(%.16s)",
+ up->utmpidlearr_val[x].ui_utmp.ut_host);
+
+ if (longopt)
+ printf("%-8.8s %*s:%-*.*s %-12.12s %6s %.18s\n",
+ up->utmpidlearr_val[x].ui_utmp.ut_name,
+ HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH,
+ up->utmpidlearr_val[x].ui_utmp.ut_line, date,
+ idle_time, remote );
+ else
+ printf("%s ",
+ up->utmpidlearr_val[x].ui_utmp.ut_name);
+ }
+ if (!longopt)
+ putchar('\n');
+
+ remember_host(raddrp->sin_addr);
+ return (0);
+}
+
+static void
+onehost(char *host)
+{
+ utmpidlearr up;
+ CLIENT *rusers_clnt;
+ struct sockaddr_in addr;
+ struct hostent *hp;
+ struct timeval tv;
+
+ hp = gethostbyname(host);
+ if (hp == NULL)
+ errx(1, "unknown host \"%s\"", host);
+
+ rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
+ if (rusers_clnt == NULL)
+ errx(1, "%s", clnt_spcreateerror(""));
+
+ memset(&up, 0, sizeof(up));
+ tv.tv_sec = 15; /* XXX ?? */
+ tv.tv_usec = 0;
+ if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
+ errx(1, "%s", clnt_sperror(rusers_clnt, ""));
+ memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr));
+ rusers_reply(&up, &addr);
+ clnt_destroy(rusers_clnt);
+}
+
+static void
+allhosts(void)
+{
+ utmpidlearr up;
+ enum clnt_stat clnt_stat;
+
+ memset(&up, 0, sizeof(up));
+ clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
+ RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_utmpidlearr, (char *)&up,
+ (resultproc_t)rusers_reply);
+ if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
+ errx(1, "%s", clnt_sperrno(clnt_stat));
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: rusers [-al] [host ...]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "al")) != -1)
+ switch (ch) {
+ case 'a':
+ allopt++;
+ break;
+ case 'l':
+ longopt++;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ setlinebuf(stdout);
+ if (argc == optind)
+ allhosts();
+ else {
+ for (; optind < argc; optind++)
+ (void)onehost(argv[optind]);
+ }
+ exit(0);
+}
diff --git a/usr.bin/rwall/Makefile b/usr.bin/rwall/Makefile
new file mode 100644
index 000000000000..88459adb760f
--- /dev/null
+++ b/usr.bin/rwall/Makefile
@@ -0,0 +1,3 @@
+PROG = rwall
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rwall/Makefile.depend b/usr.bin/rwall/Makefile.depend
new file mode 100644
index 000000000000..a2d89550fa2b
--- /dev/null
+++ b/usr.bin/rwall/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rwall/rwall.1 b/usr.bin/rwall/rwall.1
new file mode 100644
index 000000000000..9ab7775a98fa
--- /dev/null
+++ b/usr.bin/rwall/rwall.1
@@ -0,0 +1,76 @@
+.\" Copyright (c) 1983, 1990 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.
+.\"
+.Dd April 23, 1991
+.Dt RWALL 1
+.Os
+.Sh NAME
+.Nm rwall
+.Nd send a message to users logged on a host
+.Sh SYNOPSIS
+.Nm
+.Ar host
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+command sends a message to the users logged into the specified
+.Ar host .
+The
+message to be sent can be typed in and terminated with EOF or it can
+be in a
+.Ar file .
+.Sh DIAGNOSTICS
+.Bl -diag
+.It rwall: RPC: Program not registered
+The
+.Xr rpc.rwalld 8
+daemon has not been started on the remote host.
+.It rwall: RPC: Timed out
+A communication error occurred.
+Either the network is
+excessively congested, or the
+.Xr rpc.rwalld 8
+daemon has terminated on the remote host.
+.It rwall: RPC: Port mapper failure - RPC: Timed out
+The remote host is not running the portmapper (see
+.Xr rpcbind 8 ) ,
+and cannot accommodate any RPC-based services.
+The host may be down.
+.El
+.Sh SEE ALSO
+.Xr who 1 ,
+.Xr rpc.rwalld 8 ,
+.Xr rpcbind 8
+.Sh HISTORY
+The
+.Nm
+command
+appeared in
+.Em Sun-OS .
+.Sh BUGS
+The sorting options are not implemented.
diff --git a/usr.bin/rwall/rwall.c b/usr.bin/rwall/rwall.c
new file mode 100644
index 000000000000..f4df2580d166
--- /dev/null
+++ b/usr.bin/rwall/rwall.c
@@ -0,0 +1,172 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * Copyright (c) 1988, 1990 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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 is not related to David Wall, whose Stanford Ph.D. thesis
+ * is entitled "Mechanisms for Broadcast and Selective Broadcast".
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/rwall.h>
+#include <err.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static char *mbuf;
+
+static char notty[] = "no tty";
+
+static void makemsg(const char *);
+static void usage(void) __dead2;
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ char *wallhost, res;
+ CLIENT *cl;
+ struct timeval tv;
+
+ if ((argc < 2) || (argc > 3))
+ usage();
+
+ wallhost = argv[1];
+
+ makemsg(argv[2]);
+
+ /*
+ * Create client "handle" used for calling MESSAGEPROG on the
+ * server designated on the command line. We tell the rpc package
+ * to use the "tcp" protocol when contacting the server.
+ */
+ cl = clnt_create(wallhost, WALLPROG, WALLVERS, "udp");
+ if (cl == NULL) {
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+ errx(1, "%s", clnt_spcreateerror(wallhost));
+ }
+
+ tv.tv_sec = 15; /* XXX ?? */
+ tv.tv_usec = 0;
+ if (clnt_call(cl, WALLPROC_WALL, (xdrproc_t)xdr_wrapstring, &mbuf,
+ (xdrproc_t)xdr_void, &res, tv) != RPC_SUCCESS) {
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+ errx(1, "%s", clnt_sperror(cl, wallhost));
+ }
+
+ return (0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: rwall host [file]\n");
+ exit(1);
+}
+
+static void
+makemsg(const char *fname)
+{
+ struct tm *lt;
+ struct passwd *pw;
+ struct stat sbuf;
+ time_t now;
+ FILE *fp;
+ int fd;
+ size_t mbufsize;
+ char *tty, hostname[MAXHOSTNAMELEN], lbuf[256], tmpname[64];
+ const char *whom;
+
+ snprintf(tmpname, sizeof(tmpname), "%s/wall.XXXXXX", _PATH_TMP);
+ if ((fd = mkstemp(tmpname)) == -1 || (fp = fdopen(fd, "r+")) == NULL)
+ err(1, "can't open temporary file");
+ unlink(tmpname);
+
+ whom = getlogin();
+ if (!whom) {
+ pw = getpwuid(getuid());
+ whom = pw ? pw->pw_name : "???";
+ }
+ gethostname(hostname, sizeof(hostname));
+ time(&now);
+ lt = localtime(&now);
+
+ /*
+ * all this stuff is to blank out a square for the message;
+ * we wrap message lines at column 79, not 80, because some
+ * terminals wrap after 79, some do not, and we can't tell.
+ * Which means that we may leave a non-blank character
+ * in column 80, but that can't be helped.
+ */
+ fprintf(fp, "Remote Broadcast Message from %s@%s\n",
+ whom, hostname);
+ tty = ttyname(STDERR_FILENO);
+ if (tty == NULL)
+ tty = notty;
+ fprintf(fp, " (%s) at %d:%02d ...\n", tty,
+ lt->tm_hour, lt->tm_min);
+
+ putc('\n', fp);
+
+ if (fname && !(freopen(fname, "r", stdin)))
+ err(1, "can't read %s", fname);
+ while (fgets(lbuf, sizeof(lbuf), stdin))
+ fputs(lbuf, fp);
+ rewind(fp);
+
+ if (fstat(fd, &sbuf))
+ err(1, "can't stat temporary file");
+ mbufsize = (size_t)sbuf.st_size;
+ mbuf = malloc(mbufsize);
+ if (mbuf == NULL)
+ err(1, "out of memory");
+ if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != (u_int)mbufsize)
+ err(1, "can't read temporary file");
+ close(fd);
+}
diff --git a/usr.bin/rwho/Makefile b/usr.bin/rwho/Makefile
new file mode 100644
index 000000000000..b0d2d9f7faa1
--- /dev/null
+++ b/usr.bin/rwho/Makefile
@@ -0,0 +1,5 @@
+PROG= rwho
+
+PACKAGE=rcmds
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rwho/Makefile.depend b/usr.bin/rwho/Makefile.depend
new file mode 100644
index 000000000000..eeabee06fc3f
--- /dev/null
+++ b/usr.bin/rwho/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/protocols \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/rwho/rwho.1 b/usr.bin/rwho/rwho.1
new file mode 100644
index 000000000000..89fa626ba1a2
--- /dev/null
+++ b/usr.bin/rwho/rwho.1
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd August 8, 2017
+.Dt RWHO 1
+.Os
+.Sh NAME
+.Nm rwho
+.Nd who is logged in on local machines
+.Sh SYNOPSIS
+.Nm
+.Op Fl a
+.Sh DESCRIPTION
+The
+.Nm
+command produces output similar to
+.Xr who 1 ,
+but for all machines on the local network.
+If no report has been
+received from a machine for 11 minutes then
+.Nm
+assumes the machine is down, and does not report users last known
+to be logged into that machine.
+.Pp
+If a user has not typed to the system for a minute or more, then
+.Nm
+reports this idle time.
+.Pp
+The following option is available:
+.Bl -tag -width indent
+.It Fl a
+Include all users.
+By default, if a user has not typed to the system for
+an hour or more, then the user will be omitted from the output.
+.El
+.Sh FILES
+.Bl -tag -width /var/rwho/whod.* -compact
+.It Pa /var/rwho/whod.*
+information about other machines
+.El
+.Sh SEE ALSO
+.Xr ruptime 1 ,
+.Xr who 1 ,
+.Xr rwhod 8
+.Sh HISTORY
+The
+.Nm
+command
+appeared in
+.Bx 4.3 .
+.Sh BUGS
+This is unwieldy when the number of machines
+on the local net is large.
diff --git a/usr.bin/rwho/rwho.c b/usr.bin/rwho/rwho.c
new file mode 100644
index 000000000000..debc1f8567f1
--- /dev/null
+++ b/usr.bin/rwho/rwho.c
@@ -0,0 +1,235 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1993 The Regents of the University of California.
+ * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org>
+ * 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/capsicum.h>
+#include <sys/param.h>
+#include <sys/file.h>
+
+#include <protocols/rwhod.h>
+
+#include <capsicum_helpers.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <timeconv.h>
+#include <unistd.h>
+
+#define NUSERS 1000
+#define WHDRSIZE (ssize_t)(sizeof(wd) - sizeof(wd.wd_we))
+/*
+ * this macro should be shared with ruptime.
+ */
+#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60)
+
+static DIR *dirp;
+static struct whod wd;
+static int nusers;
+static struct myutmp {
+ char myhost[sizeof(wd.wd_hostname)];
+ int myidle;
+ struct outmp myutmp;
+} myutmp[NUSERS];
+
+static time_t now;
+static int aflg;
+
+static void usage(void) __dead2;
+static int utmpcmp(const void *, const void *);
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ struct dirent *dp;
+ int width;
+ ssize_t cc;
+ struct whod *w;
+ struct whoent *we;
+ struct myutmp *mp;
+ cap_rights_t rights;
+ int f, n, i;
+ int d_first;
+ int dfd;
+ time_t ct;
+
+ w = &wd;
+ (void) setlocale(LC_TIME, "");
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+
+ while ((ch = getopt(argc, argv, "a")) != -1) {
+ switch ((char)ch) {
+ case 'a':
+ aflg = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ usage();
+
+ if (chdir(_PATH_RWHODIR) < 0)
+ err(1, "chdir(%s)", _PATH_RWHODIR);
+ if ((dirp = opendir(".")) == NULL)
+ err(1, "opendir(%s)", _PATH_RWHODIR);
+ dfd = dirfd(dirp);
+ mp = myutmp;
+ cap_rights_init(&rights, CAP_READ, CAP_LOOKUP);
+ if (caph_rights_limit(dfd, &rights) < 0)
+ err(1, "cap_rights_limit failed: %s", _PATH_RWHODIR);
+ /*
+ * Cache files required for time(3) and localtime(3) before entering
+ * capability mode.
+ */
+ (void) time(&ct);
+ (void) localtime(&ct);
+ if (caph_enter() < 0)
+ err(1, "cap_enter");
+ (void) time(&now);
+ cap_rights_init(&rights, CAP_READ);
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
+ continue;
+ f = openat(dfd, dp->d_name, O_RDONLY);
+ if (f < 0)
+ continue;
+ if (caph_rights_limit(f, &rights) < 0)
+ err(1, "cap_rights_limit failed: %s", dp->d_name);
+ cc = read(f, (char *)&wd, sizeof(struct whod));
+ if (cc < WHDRSIZE) {
+ (void) close(f);
+ continue;
+ }
+ if (down(w, now) != 0) {
+ (void) close(f);
+ continue;
+ }
+ cc -= WHDRSIZE;
+ we = w->wd_we;
+ for (n = cc / sizeof(struct whoent); n > 0; n--) {
+ if (aflg == 0 && we->we_idle >= 60 * 60) {
+ we++;
+ continue;
+ }
+ if (nusers >= NUSERS)
+ errx(1, "too many users");
+ mp->myutmp = we->we_utmp;
+ mp->myidle = we->we_idle;
+ (void) strcpy(mp->myhost, w->wd_hostname);
+ nusers++;
+ we++;
+ mp++;
+ }
+ (void) close(f);
+ }
+ qsort((char *)myutmp, nusers, sizeof(struct myutmp), utmpcmp);
+ mp = myutmp;
+ width = 0;
+ for (i = 0; i < nusers; i++) {
+ /* append one for the blank and use 8 for the out_line */
+ int j;
+
+ j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line);
+ if (j > width)
+ width = j;
+ mp++;
+ }
+ mp = myutmp;
+ for (i = 0; i < nusers; i++) {
+ char buf[BUFSIZ], cbuf[80];
+ time_t t;
+
+ t = _int_to_time(mp->myutmp.out_time);
+ strftime(cbuf, sizeof(cbuf), d_first ? "%e %b %R" : "%b %e %R",
+ localtime(&t));
+ (void) sprintf(buf, "%s:%-.*s", mp->myhost,
+ (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line);
+ printf("%-*.*s %-*s %s",
+ (int)sizeof(mp->myutmp.out_name),
+ (int)sizeof(mp->myutmp.out_name),
+ mp->myutmp.out_name, width, buf, cbuf);
+ mp->myidle /= 60;
+ if (mp->myidle != 0) {
+ if (aflg != 0) {
+ if (mp->myidle >= 100 * 60)
+ mp->myidle = 100 * 60 - 1;
+ if (mp->myidle >= 60)
+ printf(" %2d", mp->myidle / 60);
+ else
+ printf(" ");
+ } else {
+ printf(" ");
+ }
+ printf(":%02d", mp->myidle % 60);
+ }
+ printf("\n");
+ mp++;
+ }
+ exit(0);
+}
+
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: rwho [-a]\n");
+ exit(1);
+}
+
+#define MYUTMP(a) ((const struct myutmp *)(a))
+
+static int
+utmpcmp(const void *u1, const void *u2)
+{
+ int rc;
+
+ rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name,
+ sizeof(MYUTMP(u2)->myutmp.out_name));
+ if (rc != 0)
+ return (rc);
+ rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost);
+ if (rc != 0)
+ return (rc);
+ return (strncmp(MYUTMP(u1)->myutmp.out_line,
+ MYUTMP(u2)->myutmp.out_line, sizeof(MYUTMP(u2)->myutmp.out_line)));
+}
diff --git a/usr.bin/script/Makefile b/usr.bin/script/Makefile
new file mode 100644
index 000000000000..99cb623ba5a9
--- /dev/null
+++ b/usr.bin/script/Makefile
@@ -0,0 +1,5 @@
+PROG= script
+
+LIBADD= util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/script/Makefile.depend b/usr.bin/script/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/script/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/script/script.1 b/usr.bin/script/script.1
new file mode 100644
index 000000000000..5f40e5af28ff
--- /dev/null
+++ b/usr.bin/script/script.1
@@ -0,0 +1,304 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd October 26, 2022
+.Dt SCRIPT 1
+.Os
+.Sh NAME
+.Nm script
+.Nd make typescript of terminal session
+.Sh SYNOPSIS
+.Nm
+.Op Fl aeFfkqrw
+.Op Fl t Ar time
+.Op Ar file Op Ar command ...
+.Nm
+.Fl p
+.Op Fl deq
+.Op Fl T Ar fmt
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility makes a typescript of everything printed on your terminal.
+It is useful for students who need a hardcopy record of an interactive
+session as proof of an assignment, as the typescript file
+can be printed out later with
+.Xr lpr 1 .
+.Pp
+If the argument
+.Ar file
+is given,
+.Nm
+saves all dialogue in
+.Ar file .
+If no file name is given, the typescript is saved in the file
+.Pa typescript .
+.Pp
+If the argument
+.Ar command
+is given,
+.Nm
+will run the specified command with an optional argument vector
+instead of an interactive shell.
+.Pp
+The following options are available:
+.Bl -tag -width "-F pipe"
+.It Fl a
+Append the output to
+.Ar file
+or
+.Pa typescript ,
+retaining the prior contents.
+.It Fl d
+When playing back a session with the
+.Fl p
+flag, do not sleep between records when playing back a timestamped session.
+.It Fl e
+Accepted for compatibility with
+.Em util-linux
+.Nm .
+The child command exit status is always the exit status of
+.Nm .
+.It Fl F
+Immediately flush output after each write.
+This will allow a user to create a named pipe using
+.Xr mkfifo 1
+and another user may watch the live session using a utility like
+.Xr cat 1 .
+.It Fl f
+Create
+.Ar file.filemon
+or
+.Pa typescript.filemon
+using
+.Xr filemon 4 .
+.It Fl k
+Log keys sent to the program as well as output.
+.It Fl p
+Play back a session recorded with the
+.Fl r
+flag in real time.
+.It Fl q
+Run in quiet mode, omit the start, stop and command status messages.
+.It Fl r
+Record a session with input, output, and timestamping.
+.It Fl t Ar time
+Specify the interval at which the script output file will be flushed
+to disk, in seconds.
+A value of 0
+causes
+.Nm
+to flush after every character I/O event.
+The default interval is
+30 seconds.
+.It Fl T Ar fmt
+Implies
+.Fl p ,
+but just reports the time-stamp of each output.
+This is very useful for assessing the timing of events.
+.Pp
+If
+.Ar fmt
+does not contain any
+.Ql %
+characters, it indicates the default format:
+.Ql %n@ %s [%Y-%m-%d %T]%n ,
+which is useful for both tools and humans to read, should be used.
+Note that time-stamps will only be output when different from the
+previous one.
+.It Fl w
+Forward terminal size changes on
+.Dv SIGWINCH .
+.El
+.Pp
+The script ends when the forked shell (or command) exits (a
+.Em control-D
+to exit
+the Bourne shell
+.Pf ( Xr sh 1 ) ,
+and
+.Em exit ,
+.Em logout
+or
+.Em control-D
+(if
+.Em ignoreeof
+is not set) for the
+C-shell,
+.Xr csh 1 ) .
+.Pp
+Certain interactive commands, such as
+.Xr vi 1 ,
+create garbage in the typescript file.
+The
+.Nm
+utility works best with commands that do not manipulate the screen.
+The results are meant to emulate a hardcopy terminal, not an addressable one.
+.Sh ENVIRONMENT
+The following environment variables are utilized by
+.Nm :
+.Bl -tag -width SCRIPT
+.It Ev SCRIPT
+The
+.Ev SCRIPT
+environment variable is added to the sub-shell.
+If
+.Ev SCRIPT
+already existed in the users environment,
+its value is overwritten within the sub-shell.
+The value of
+.Ev SCRIPT
+is the name of the
+.Ar typescript
+file.
+.It Ev SHELL
+If the variable
+.Ev SHELL
+exists, the shell forked by
+.Nm
+will be that shell.
+If
+.Ev SHELL
+is not set, the Bourne shell
+is assumed.
+.Pq Most shells set this variable automatically .
+.El
+.Sh EXAMPLES
+Record a simple
+.Xr csh 1
+session with no additional details like input, output, and timestamping:
+.Bd -literal -offset indent
+$ SHELL=/bin/csh script
+Script started, output file is typescript
+% date
+Tue Jan 5 15:08:10 UTC 2021
+% exit
+exit
+
+Script done, output file is typescript
+.Ed
+.Pp
+Now, replay the session recorded in the previous example:
+.Bd -literal -offset indent
+$ cat ./typescript
+Script started on Tue Jan 5 15:08:08 2021
+% date
+Tue Jan 5 15:08:10 UTC 2021
+% exit
+exit
+
+Script done on Tue Jan 5 15:08:13 2021
+.Ed
+.Pp
+Record a
+.Xr csh 1
+session, but this time with additional details like timestamping:
+.Bd -literal -offset indent
+$ SHELL=/bin/csh script -r
+Script started, output file is typescript
+% date
+Tue Jan 5 15:17:11 UTC 2021
+% exit
+exit
+
+Script done, output file is typescript
+.Ed
+.Pp
+In order to replay a sessions recorded with the
+.Fl r
+flag, it is necessary to specify
+.Fl p
+.Po
+.Xr cat 1
+will not work because of all the aditional information stored in the session file
+.Pc .
+Also, let us use
+.Fl d
+to print the whole session at once:
+.Bd -literal -offset indent
+$ script -dp ./typescript
+Script started on Tue Jan 5 15:17:09 2021
+% date
+Tue Jan 5 15:17:11 UTC 2021
+% exit
+exit
+
+Script done on Tue Jan 5 15:17:14 2021
+.Ed
+.Sh SEE ALSO
+.Xr csh 1
+.Po
+for the
+.Em history
+mechanism
+.Pc ,
+.Xr filemon 4
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Pp
+The
+.Fl d ,
+.Fl p
+and
+.Fl r
+options first appeared in
+.Nx 2.0
+and were ported to
+.Fx 9.2 .
+.Sh BUGS
+The
+.Nm
+utility places
+.Sy everything
+in the log file, including linefeeds and backspaces.
+This is not what the naive user expects.
+.Pp
+It is not possible to specify a command without also naming the script file
+because of argument parsing compatibility issues.
+.Pp
+When running in
+.Fl k
+mode, echo cancelling is far from ideal.
+The slave terminal mode is checked
+for ECHO mode to check when to avoid manual echo logging.
+This does not
+work when the terminal is in a raw mode where
+the program being run is doing manual echo.
+.Pp
+If
+.Nm
+reads zero bytes from the terminal, it switches to a mode when it
+only attempts to read
+once a second until there is data to read.
+This prevents
+.Nm
+from spinning on zero-byte reads, but might cause a 1-second delay in
+processing of user input.
diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c
new file mode 100644
index 000000000000..cca265b8941b
--- /dev/null
+++ b/usr.bin/script/script.c
@@ -0,0 +1,653 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2010, 2012 David E. O'Brien
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <sys/uio.h>
+#include <sys/endian.h>
+#include <dev/filemon/filemon.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libutil.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#define DEF_BUF 65536
+
+struct stamp {
+ uint64_t scr_len; /* amount of data */
+ uint64_t scr_sec; /* time it arrived in seconds... */
+ uint32_t scr_usec; /* ...and microseconds */
+ uint32_t scr_direction; /* 'i', 'o', etc (also indicates endianness) */
+};
+
+struct buf_elm {
+ TAILQ_ENTRY(buf_elm) link;
+ size_t rpos;
+ size_t len;
+ char ibuf[];
+};
+
+static FILE *fscript;
+static int master, slave;
+static int child;
+static const char *fname;
+static char *fmfname;
+static int fflg, qflg, ttyflg;
+static int usesleep, rawout, showexit;
+static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list);
+static volatile sig_atomic_t doresize;
+
+static struct termios tt;
+
+#ifndef TSTAMP_FMT
+/* useful for tool and human reading */
+# define TSTAMP_FMT "%n@ %s [%Y-%m-%d %T]%n"
+#endif
+static const char *tstamp_fmt = TSTAMP_FMT;
+static int tflg;
+
+static void done(int) __dead2;
+static void doshell(char **);
+static void finish(void);
+static void record(FILE *, char *, size_t, int);
+static void consume(FILE *, off_t, char *, int);
+static void playback(FILE *) __dead2;
+static void usage(void) __dead2;
+static void resizeit(int);
+
+int
+main(int argc, char *argv[])
+{
+ struct termios rtt, stt;
+ struct winsize win;
+ struct timespec tv, *tvp;
+ time_t tvec, start;
+ char obuf[BUFSIZ];
+ char ibuf[BUFSIZ];
+ sigset_t *pselmask, selmask;
+ fd_set rfd, wfd;
+ struct buf_elm *be;
+ ssize_t cc;
+ int aflg, Fflg, kflg, pflg, wflg, ch, k, n, fcm;
+ int flushtime, readstdin;
+ int fm_fd, fm_log;
+
+ aflg = Fflg = kflg = pflg = wflg = 0;
+ doresize = 0;
+ usesleep = 1;
+ rawout = 0;
+ flushtime = 30;
+ fm_fd = -1;
+ showexit = 0;
+
+ /*
+ * For normal operation, we'll leave pselmask == NULL so that pselect(2)
+ * leaves the signal mask alone. If -w is specified, we'll restore the
+ * process signal mask upon entry with SIGWINCH unblocked so that we can
+ * forward resize events properly.
+ */
+ sigemptyset(&selmask);
+ pselmask = NULL;
+
+ while ((ch = getopt(argc, argv, "adeFfkpqrT:t:w")) != -1)
+ switch (ch) {
+ case 'a':
+ aflg = 1;
+ break;
+ case 'd':
+ usesleep = 0;
+ break;
+ case 'e':
+ /* Default behavior, accepted for linux compat. */
+ break;
+ case 'F':
+ Fflg = 1;
+ break;
+ case 'f':
+ fflg = 1;
+ break;
+ case 'k':
+ kflg = 1;
+ break;
+ case 'p':
+ pflg = 1;
+ break;
+ case 'q':
+ qflg = 1;
+ break;
+ case 'r':
+ rawout = 1;
+ break;
+ case 't':
+ flushtime = atoi(optarg);
+ if (flushtime < 0)
+ err(1, "invalid flush time %d", flushtime);
+ break;
+ case 'T':
+ tflg = pflg = 1;
+ if (strchr(optarg, '%'))
+ tstamp_fmt = optarg;
+ break;
+ case 'w':
+ wflg = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ fname = argv[0];
+ argv++;
+ argc--;
+ } else
+ fname = "typescript";
+
+ if ((fscript = fopen(fname, pflg ? "r" : aflg ? "a" : "w")) == NULL)
+ err(1, "%s", fname);
+
+ if (fflg) {
+ asprintf(&fmfname, "%s.filemon", fname);
+ if (!fmfname)
+ err(1, "%s.filemon", fname);
+ if ((fm_fd = open("/dev/filemon", O_RDWR | O_CLOEXEC)) == -1)
+ err(1, "open(\"/dev/filemon\", O_RDWR)");
+ if ((fm_log = open(fmfname,
+ O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
+ err(1, "open(%s)", fmfname);
+ if (ioctl(fm_fd, FILEMON_SET_FD, &fm_log) < 0)
+ err(1, "Cannot set filemon log file descriptor");
+ }
+
+ if (pflg)
+ playback(fscript);
+
+ if (tcgetattr(STDIN_FILENO, &tt) == -1 ||
+ ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) {
+ if (errno != ENOTTY) /* For debugger. */
+ err(1, "tcgetattr/ioctl");
+ if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
+ err(1, "openpty");
+ } else {
+ if (openpty(&master, &slave, NULL, &tt, &win) == -1)
+ err(1, "openpty");
+ ttyflg = 1;
+ }
+ fcm = fcntl(master, F_GETFL);
+ if (fcm == -1)
+ err(1, "master F_GETFL");
+ fcm |= O_NONBLOCK;
+ if (fcntl(master, F_SETFL, fcm) == -1)
+ err(1, "master F_SETFL");
+
+ if (rawout)
+ record(fscript, NULL, 0, 's');
+
+ if (!qflg) {
+ tvec = time(NULL);
+ (void)printf("Script started, output file is %s\n", fname);
+ if (!rawout) {
+ (void)fprintf(fscript, "Script started on %s",
+ ctime(&tvec));
+ if (argv[0]) {
+ showexit = 1;
+ fprintf(fscript, "Command: ");
+ for (k = 0 ; argv[k] ; ++k)
+ fprintf(fscript, "%s%s", k ? " " : "",
+ argv[k]);
+ fprintf(fscript, "\n");
+ }
+ }
+ fflush(fscript);
+ if (fflg) {
+ (void)printf("Filemon started, output file is %s\n",
+ fmfname);
+ }
+ }
+ if (ttyflg) {
+ rtt = tt;
+ cfmakeraw(&rtt);
+ rtt.c_lflag &= ~ECHO;
+ (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
+ }
+
+ assert(fflg ? fm_fd >= 0 : fm_fd < 0);
+
+ child = fork();
+ if (child < 0) {
+ warn("fork");
+ done(1);
+ }
+ if (child == 0) {
+ if (fflg) {
+ int pid;
+
+ pid = getpid();
+ if (ioctl(fm_fd, FILEMON_SET_PID, &pid) < 0)
+ err(1, "Cannot set filemon PID");
+ }
+
+ doshell(argv);
+ }
+ close(slave);
+
+ if (wflg) {
+ struct sigaction sa = { .sa_handler = resizeit };
+ sigset_t smask;
+
+ sigaction(SIGWINCH, &sa, NULL);
+
+ sigemptyset(&smask);
+ sigaddset(&smask, SIGWINCH);
+
+ if (sigprocmask(SIG_BLOCK, &smask, &selmask) != 0)
+ err(1, "Failed to block SIGWINCH");
+
+ /* Just in case SIGWINCH was blocked before we came in. */
+ sigdelset(&selmask, SIGWINCH);
+ pselmask = &selmask;
+ }
+
+ start = tvec = time(0);
+ readstdin = 1;
+ for (;;) {
+ FD_ZERO(&rfd);
+ FD_ZERO(&wfd);
+ FD_SET(master, &rfd);
+ if (readstdin)
+ FD_SET(STDIN_FILENO, &rfd);
+ if (!TAILQ_EMPTY(&obuf_list))
+ FD_SET(master, &wfd);
+ if (!readstdin && ttyflg) {
+ tv.tv_sec = 1;
+ tv.tv_nsec = 0;
+ tvp = &tv;
+ readstdin = 1;
+ } else if (flushtime > 0) {
+ tv.tv_sec = flushtime - (tvec - start);
+ tv.tv_nsec = 0;
+ tvp = &tv;
+ } else {
+ tvp = NULL;
+ }
+ n = pselect(master + 1, &rfd, &wfd, NULL, tvp, pselmask);
+ if (n < 0 && errno != EINTR)
+ break;
+
+ if (doresize) {
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1)
+ ioctl(master, TIOCSWINSZ, &win);
+ doresize = 0;
+ }
+
+ if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
+ cc = read(STDIN_FILENO, ibuf, BUFSIZ);
+ if (cc < 0)
+ break;
+ if (cc == 0) {
+ if (tcgetattr(master, &stt) == 0 &&
+ (stt.c_lflag & ICANON) != 0) {
+ (void)write(master, &stt.c_cc[VEOF], 1);
+ }
+ readstdin = 0;
+ }
+ if (cc > 0) {
+ if (rawout)
+ record(fscript, ibuf, cc, 'i');
+ be = malloc(sizeof(*be) + cc);
+ be->rpos = 0;
+ be->len = cc;
+ memcpy(be->ibuf, ibuf, cc);
+ TAILQ_INSERT_TAIL(&obuf_list, be, link);
+ }
+ }
+ if (n > 0 && FD_ISSET(master, &wfd)) {
+ while ((be = TAILQ_FIRST(&obuf_list)) != NULL) {
+ cc = write(master, be->ibuf + be->rpos,
+ be->len);
+ if (cc == -1) {
+ if (errno == EWOULDBLOCK ||
+ errno == EINTR)
+ break;
+ warn("write master");
+ done(1);
+ }
+ if (cc == 0)
+ break; /* retry later ? */
+ if (kflg && tcgetattr(master, &stt) >= 0 &&
+ ((stt.c_lflag & ECHO) == 0)) {
+ (void)fwrite(be->ibuf + be->rpos,
+ 1, cc, fscript);
+ }
+ be->len -= cc;
+ if (be->len == 0) {
+ TAILQ_REMOVE(&obuf_list, be, link);
+ free(be);
+ } else {
+ be->rpos += cc;
+ }
+ }
+ }
+ if (n > 0 && FD_ISSET(master, &rfd)) {
+ cc = read(master, obuf, sizeof(obuf));
+ if (cc <= 0)
+ break;
+ (void)write(STDOUT_FILENO, obuf, cc);
+ if (rawout)
+ record(fscript, obuf, cc, 'o');
+ else
+ (void)fwrite(obuf, 1, cc, fscript);
+ }
+ tvec = time(0);
+ if (tvec - start >= flushtime) {
+ fflush(fscript);
+ start = tvec;
+ }
+ if (Fflg)
+ fflush(fscript);
+ }
+ finish();
+ done(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: script [-aeFfkpqrw] [-t time] [file [command ...]]\n");
+ (void)fprintf(stderr,
+ " script -p [-deq] [-T fmt] [file]\n");
+ exit(1);
+}
+
+static void
+finish(void)
+{
+ int e, status;
+
+ if (waitpid(child, &status, 0) == child) {
+ if (WIFEXITED(status))
+ e = WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ e = WTERMSIG(status);
+ else /* can't happen */
+ e = 1;
+ done(e);
+ }
+}
+
+static void
+doshell(char **av)
+{
+ const char *shell;
+
+ shell = getenv("SHELL");
+ if (shell == NULL)
+ shell = _PATH_BSHELL;
+
+ (void)close(master);
+ (void)fclose(fscript);
+ free(fmfname);
+ login_tty(slave);
+ setenv("SCRIPT", fname, 1);
+ if (av[0]) {
+ execvp(av[0], av);
+ warn("%s", av[0]);
+ } else {
+ execl(shell, shell, "-i", (char *)NULL);
+ warn("%s", shell);
+ }
+ exit(1);
+}
+
+static void
+done(int eno)
+{
+ time_t tvec;
+
+ if (ttyflg)
+ (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
+ tvec = time(NULL);
+ if (rawout)
+ record(fscript, NULL, 0, 'e');
+ if (!qflg) {
+ if (!rawout) {
+ if (showexit)
+ (void)fprintf(fscript, "\nCommand exit status:"
+ " %d", eno);
+ (void)fprintf(fscript, "\nScript done on %s",
+ ctime(&tvec));
+ }
+ (void)printf("\nScript done, output file is %s\n", fname);
+ if (fflg) {
+ (void)printf("Filemon done, output file is %s\n",
+ fmfname);
+ }
+ }
+ (void)fclose(fscript);
+ (void)close(master);
+ exit(eno);
+}
+
+static void
+record(FILE *fp, char *buf, size_t cc, int direction)
+{
+ struct iovec iov[2];
+ struct stamp stamp;
+ struct timeval tv;
+
+ (void)gettimeofday(&tv, NULL);
+ stamp.scr_len = cc;
+ stamp.scr_sec = tv.tv_sec;
+ stamp.scr_usec = tv.tv_usec;
+ stamp.scr_direction = direction;
+ iov[0].iov_len = sizeof(stamp);
+ iov[0].iov_base = &stamp;
+ iov[1].iov_len = cc;
+ iov[1].iov_base = buf;
+ if (writev(fileno(fp), &iov[0], 2) == -1)
+ err(1, "writev");
+}
+
+static void
+consume(FILE *fp, off_t len, char *buf, int reg)
+{
+ size_t l;
+
+ if (reg) {
+ if (fseeko(fp, len, SEEK_CUR) == -1)
+ err(1, NULL);
+ } else {
+ while (len > 0) {
+ l = MIN(DEF_BUF, len);
+ if (fread(buf, sizeof(char), l, fp) != l)
+ err(1, "cannot read buffer");
+ len -= l;
+ }
+ }
+}
+
+#define swapstamp(stamp) do { \
+ if (stamp.scr_direction > 0xff) { \
+ stamp.scr_len = bswap64(stamp.scr_len); \
+ stamp.scr_sec = bswap64(stamp.scr_sec); \
+ stamp.scr_usec = bswap32(stamp.scr_usec); \
+ stamp.scr_direction = bswap32(stamp.scr_direction); \
+ } \
+} while (0/*CONSTCOND*/)
+
+static void
+termset(void)
+{
+ struct termios traw;
+
+ if (tcgetattr(STDOUT_FILENO, &tt) == -1) {
+ if (errno != ENOTTY) /* For debugger. */
+ err(1, "tcgetattr");
+ return;
+ }
+ ttyflg = 1;
+ traw = tt;
+ cfmakeraw(&traw);
+ traw.c_lflag |= ISIG;
+ (void)tcsetattr(STDOUT_FILENO, TCSANOW, &traw);
+}
+
+static void
+termreset(void)
+{
+ if (ttyflg) {
+ tcsetattr(STDOUT_FILENO, TCSADRAIN, &tt);
+ ttyflg = 0;
+ }
+}
+
+static void
+playback(FILE *fp)
+{
+ struct timespec tsi, tso;
+ struct stamp stamp;
+ struct stat pst;
+ char buf[DEF_BUF];
+ off_t nread, save_len;
+ size_t l;
+ time_t tclock;
+ time_t lclock;
+ int reg;
+
+ if (fstat(fileno(fp), &pst) == -1)
+ err(1, "fstat failed");
+
+ reg = S_ISREG(pst.st_mode);
+ lclock = 0;
+
+ for (nread = 0; !reg || nread < pst.st_size; nread += save_len) {
+ if (fread(&stamp, sizeof(stamp), 1, fp) != 1) {
+ if (reg)
+ err(1, "reading playback header");
+ else
+ break;
+ }
+ swapstamp(stamp);
+ save_len = sizeof(stamp);
+
+ if (reg && stamp.scr_len >
+ (uint64_t)(pst.st_size - save_len) - nread)
+ errx(1, "invalid stamp");
+
+ save_len += stamp.scr_len;
+ tclock = stamp.scr_sec;
+ tso.tv_sec = stamp.scr_sec;
+ tso.tv_nsec = stamp.scr_usec * 1000;
+ if (nread == 0)
+ tsi = tso;
+
+ switch (stamp.scr_direction) {
+ case 's':
+ if (!qflg)
+ (void)printf("Script started on %s",
+ ctime(&tclock));
+ tsi = tso;
+ (void)consume(fp, stamp.scr_len, buf, reg);
+ termset();
+ atexit(termreset);
+ break;
+ case 'e':
+ termreset();
+ if (!qflg)
+ (void)printf("\nScript done on %s",
+ ctime(&tclock));
+ (void)consume(fp, stamp.scr_len, buf, reg);
+ break;
+ case 'i':
+ /* throw input away */
+ (void)consume(fp, stamp.scr_len, buf, reg);
+ break;
+ case 'o':
+ if (tflg) {
+ if (stamp.scr_len == 0)
+ continue;
+ if (tclock - lclock > 0) {
+ l = strftime(buf, sizeof buf, tstamp_fmt,
+ localtime(&tclock));
+ (void)write(STDOUT_FILENO, buf, l);
+ }
+ lclock = tclock;
+ } else {
+ tsi.tv_sec = tso.tv_sec - tsi.tv_sec;
+ tsi.tv_nsec = tso.tv_nsec - tsi.tv_nsec;
+ if (tsi.tv_nsec < 0) {
+ tsi.tv_sec -= 1;
+ tsi.tv_nsec += 1000000000;
+ }
+ if (usesleep)
+ (void)nanosleep(&tsi, NULL);
+ tsi = tso;
+ }
+ while (stamp.scr_len > 0) {
+ l = MIN(DEF_BUF, stamp.scr_len);
+ if (fread(buf, sizeof(char), l, fp) != l)
+ err(1, "cannot read buffer");
+
+ (void)write(STDOUT_FILENO, buf, l);
+ stamp.scr_len -= l;
+ }
+ break;
+ default:
+ errx(1, "invalid direction");
+ }
+ }
+ (void)fclose(fp);
+ exit(0);
+}
+
+static void
+resizeit(int signo __unused)
+{
+ doresize = 1;
+}
diff --git a/usr.bin/sdiff/Makefile b/usr.bin/sdiff/Makefile
new file mode 100644
index 000000000000..03587f373098
--- /dev/null
+++ b/usr.bin/sdiff/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PROG= sdiff
+SRCS= edit.c sdiff.c
+
+MAN1= sdiff.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sdiff/Makefile.depend b/usr.bin/sdiff/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/sdiff/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sdiff/edit.c b/usr.bin/sdiff/edit.c
new file mode 100644
index 000000000000..249cb09ed44e
--- /dev/null
+++ b/usr.bin/sdiff/edit.c
@@ -0,0 +1,208 @@
+/* $OpenBSD: edit.c,v 1.19 2009/06/07 13:29:50 ray Exp $ */
+
+/*
+ * Written by Raymond Lai <ray@cyth.net>.
+ * Public domain.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static void
+cleanup(const char *filename)
+{
+
+ if (unlink(filename))
+ err(2, "could not delete: %s", filename);
+ exit(2);
+}
+
+/*
+ * Execute an editor on the specified pathname, which is interpreted
+ * from the shell. This means flags may be included.
+ *
+ * Returns -1 on error, or the exit value on success.
+ */
+static int
+editit(const char *pathname)
+{
+ sig_t sighup, sigint, sigquit, sigchld;
+ pid_t pid;
+ int saved_errno, st, ret = -1;
+ const char *ed;
+
+ ed = getenv("VISUAL");
+ if (ed == NULL)
+ ed = getenv("EDITOR");
+ if (ed == NULL)
+ ed = _PATH_VI;
+
+ sighup = signal(SIGHUP, SIG_IGN);
+ sigint = signal(SIGINT, SIG_IGN);
+ sigquit = signal(SIGQUIT, SIG_IGN);
+ sigchld = signal(SIGCHLD, SIG_DFL);
+ if ((pid = fork()) == -1)
+ goto fail;
+ if (pid == 0) {
+ execlp(ed, ed, pathname, (char *)NULL);
+ _exit(127);
+ }
+ while (waitpid(pid, &st, 0) == -1)
+ if (errno != EINTR)
+ goto fail;
+ if (!WIFEXITED(st))
+ errno = EINTR;
+ else
+ ret = WEXITSTATUS(st);
+
+ fail:
+ saved_errno = errno;
+ (void)signal(SIGHUP, sighup);
+ (void)signal(SIGINT, sigint);
+ (void)signal(SIGQUIT, sigquit);
+ (void)signal(SIGCHLD, sigchld);
+ errno = saved_errno;
+ return (ret);
+}
+
+/*
+ * Parse edit command. Returns 0 on success, -1 on error.
+ */
+int
+eparse(const char *cmd, const char *left, const char *right)
+{
+ FILE *file;
+ size_t nread;
+ int fd;
+ char *filename;
+ char buf[BUFSIZ], *text;
+
+ /* Skip whitespace. */
+ while (isspace(*cmd))
+ ++cmd;
+
+ text = NULL;
+ switch (*cmd) {
+ case '\0':
+ /* Edit empty file. */
+ break;
+
+ case 'b':
+ /* Both strings. */
+ if (left == NULL)
+ goto RIGHT;
+ if (right == NULL)
+ goto LEFT;
+
+ /* Neither column is blank, so print both. */
+ if (asprintf(&text, "%s\n%s\n", left, right) == -1)
+ err(2, "could not allocate memory");
+ break;
+
+ case 'l':
+LEFT:
+ /* Skip if there is no left column. */
+ if (left == NULL)
+ break;
+
+ if (asprintf(&text, "%s\n", left) == -1)
+ err(2, "could not allocate memory");
+
+ break;
+
+ case 'r':
+RIGHT:
+ /* Skip if there is no right column. */
+ if (right == NULL)
+ break;
+
+ if (asprintf(&text, "%s\n", right) == -1)
+ err(2, "could not allocate memory");
+
+ break;
+
+ default:
+ return (-1);
+ }
+
+ /* Create temp file. */
+ if (asprintf(&filename, "%s/sdiff.XXXXXXXXXX", tmpdir) == -1)
+ err(2, "asprintf");
+ if ((fd = mkstemp(filename)) == -1)
+ err(2, "mkstemp");
+ if (text != NULL) {
+ size_t len;
+ ssize_t nwritten;
+
+ len = strlen(text);
+ if ((nwritten = write(fd, text, len)) == -1 ||
+ (size_t)nwritten != len) {
+ warn("error writing to temp file");
+ cleanup(filename);
+ }
+ }
+ close(fd);
+
+ /* text is no longer used. */
+ free(text);
+
+ /* Edit temp file. */
+ if (editit(filename) == -1) {
+ warn("error editing %s", filename);
+ cleanup(filename);
+ }
+
+ /* Open temporary file. */
+ if (!(file = fopen(filename, "r"))) {
+ warn("could not open edited file: %s", filename);
+ cleanup(filename);
+ }
+
+ /* Copy temporary file contents to output file. */
+ for (nread = sizeof(buf); nread == sizeof(buf);) {
+ size_t nwritten;
+
+ nread = fread(buf, sizeof(*buf), sizeof(buf), file);
+ /* Test for error or end of file. */
+ if (nread != sizeof(buf) &&
+ (ferror(file) || !feof(file))) {
+ warnx("error reading edited file: %s", filename);
+ cleanup(filename);
+ }
+
+ /*
+ * If we have nothing to read, break out of loop
+ * instead of writing nothing.
+ */
+ if (!nread)
+ break;
+
+ /* Write data we just read. */
+ nwritten = fwrite(buf, sizeof(*buf), nread, outfp);
+ if (nwritten != nread) {
+ warnx("error writing to output file");
+ cleanup(filename);
+ }
+ }
+
+ /* We've reached the end of the temporary file, so remove it. */
+ if (unlink(filename))
+ warn("could not delete: %s", filename);
+ fclose(file);
+
+ free(filename);
+
+ return (0);
+}
diff --git a/usr.bin/sdiff/extern.h b/usr.bin/sdiff/extern.h
new file mode 100644
index 000000000000..c9ebaef7d22c
--- /dev/null
+++ b/usr.bin/sdiff/extern.h
@@ -0,0 +1,11 @@
+/* $OpenBSD: extern.h,v 1.5 2009/06/07 13:29:50 ray Exp $ */
+
+/*
+ * Written by Raymond Lai <ray@cyth.net>.
+ * Public domain.
+ */
+
+extern FILE *outfp; /* file to save changes to */
+extern const char *tmpdir;
+
+int eparse(const char *, const char *, const char *);
diff --git a/usr.bin/sdiff/sdiff.1 b/usr.bin/sdiff/sdiff.1
new file mode 100644
index 000000000000..ca6594c6479a
--- /dev/null
+++ b/usr.bin/sdiff/sdiff.1
@@ -0,0 +1,169 @@
+.\" $OpenBSD: sdiff.1,v 1.15 2007/06/29 14:48:07 jmc Exp $
+.\"
+.\" Written by Raymond Lai <ray@cyth.net>.
+.\" Public domain.
+.\"
+.Dd February 16, 2024
+.Dt SDIFF 1
+.Os
+.Sh NAME
+.Nm sdiff
+.Nd side-by-side diff
+.Sh SYNOPSIS
+.Nm
+.Op Fl abdilstHW
+.Op Fl I Ar regexp
+.Op Fl o Ar outfile
+.Op Fl w Ar width
+.Ar file1
+.Ar file2
+.Sh DESCRIPTION
+.Nm
+displays two files side by side,
+with any differences between the two highlighted as follows:
+new lines are marked with
+.Sq \*(Gt ;
+deleted lines are marked with
+.Sq \*(Lt ;
+and changed lines are marked with
+.Sq \*(Ba .
+.Pp
+.Nm
+can also be used to interactively merge two files,
+prompting at each set of differences.
+See the
+.Fl o
+option for an explanation.
+.Pp
+The options are:
+.Bl -tag -width Ds
+.It Fl l -left-column
+Only print the left column for identical lines.
+.It Fl o -output Ar outfile
+Interactively merge
+.Ar file1
+and
+.Ar file2
+into
+.Ar outfile .
+In this mode, the user is prompted for each set of differences.
+See
+.Ev EDITOR
+and
+.Ev VISUAL ,
+below,
+for details of which editor, if any, is invoked.
+.Pp
+The commands are as follows:
+.Bl -tag -width Ds
+.It Cm l | 1
+Choose left set of diffs.
+.It Cm r | 2
+Choose right set of diffs.
+.It Cm s
+Silent mode \(en identical lines are not printed.
+.It Cm v
+Verbose mode \(en identical lines are printed.
+.It Cm e
+Start editing an empty file, which will be merged into
+.Ar outfile
+upon exiting the editor.
+.It Cm e Cm l
+Start editing file with left set of diffs.
+.It Cm e Cm r
+Start editing file with right set of diffs.
+.It Cm e Cm b
+Start editing file with both sets of diffs.
+.It Cm q
+Quit
+.Nm .
+.El
+.It Fl s -suppress-common-lines
+Skip identical lines.
+.It Fl w -width Ar width
+Print a maximum of
+.Ar width
+characters on each line.
+The default is 130 characters.
+.El
+.Pp
+Options passed to
+.Xr diff 1
+are:
+.Bl -tag -width Ds
+.It Fl a -text
+Treat
+.Ar file1
+and
+.Ar file2
+as text files.
+.It Fl b -ignore-space-change
+Ignore trailing blank spaces.
+.It Fl d -minimal
+Minimize diff size.
+.It Fl I -ignore-matching-lines Ar regexp
+Ignore line changes matching
+.Ar regexp .
+All lines in the change must match
+.Ar regexp
+for the change to be ignored.
+.It Fl i -ignore-case
+Do a case-insensitive comparison.
+.It Fl t -expand-tabs
+Expand tabs to spaces.
+.It Fl W -ignore-all-space
+Ignore all spaces.
+.It Fl B -ignore-blank-lines
+Ignore blank lines.
+.It Fl E -ignore-tab-expansion
+Treat tabs and eight spaces as the same.
+.It Fl H -speed-large-files
+Assume scattered small changes in a large file.
+.It Fl -ignore-file-name-case
+Ignore the case of file names.
+.It Fl -no-ignore-file-name-case
+Do not ignore file name case.
+.It Fl -strip-trailing-cr
+Skip identical lines.
+.It Fl -tabsize Ar NUM
+Change the size of tabs (default is 8.)
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev EDITOR , VISUAL
+Specifies an editor to use with the
+.Fl o
+option.
+If both
+.Ev EDITOR
+and
+.Ev VISUAL
+are set,
+.Ev VISUAL
+takes precedence.
+If neither
+.Ev EDITOR
+nor
+.Ev VISUAL
+are set,
+the default is
+.Xr vi 1 .
+.It Ev TMPDIR
+Specifies a directory for temporary files to be created.
+The default is
+.Pa /tmp .
+.El
+.Sh SEE ALSO
+.Xr cmp 1 ,
+.Xr diff 1 ,
+.Xr diff3 1 ,
+.Xr vi 1 ,
+.Xr re_format 7
+.Sh AUTHORS
+.Nm
+was written from scratch for the public domain by
+.An Ray Lai Aq ray@cyth.net .
+.Sh CAVEATS
+Tabs are treated as anywhere from one to eight characters wide,
+depending on the current column.
+Terminals that treat tabs as eight characters wide will look best.
diff --git a/usr.bin/sdiff/sdiff.c b/usr.bin/sdiff/sdiff.c
new file mode 100644
index 000000000000..b796bb4224a8
--- /dev/null
+++ b/usr.bin/sdiff/sdiff.c
@@ -0,0 +1,1178 @@
+/* $OpenBSD: sdiff.c,v 1.36 2015/12/29 19:04:46 gsoares Exp $ */
+
+/*
+ * Written by Raymond Lai <ray@cyth.net>.
+ * Public domain.
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static char diff_path[] = "/usr/bin/diff";
+
+#define WIDTH 126
+/*
+ * Each column must be at least one character wide, plus three
+ * characters between the columns (space, [<|>], space).
+ */
+#define WIDTH_MIN 5
+
+/* 3 kilobytes of chars */
+#define MAX_CHECK 768
+
+/* A single diff line. */
+struct diffline {
+ STAILQ_ENTRY(diffline) diffentries;
+ char *left;
+ char div;
+ char *right;
+};
+
+static void astrcat(char **, const char *);
+static void enqueue(char *, char, char *);
+static char *mktmpcpy(const char *);
+static int istextfile(FILE *);
+static int bindiff(FILE *, char *, FILE *, char *);
+static void freediff(struct diffline *);
+static void int_usage(void);
+static int parsecmd(FILE *, FILE *, FILE *);
+static void printa(FILE *, size_t);
+static void printc(FILE *, size_t, FILE *, size_t);
+static void printcol(const char *, size_t *, const size_t);
+static void printd(FILE *, size_t);
+static void println(const char *, const char, const char *);
+static void processq(void);
+static void prompt(const char *, const char *);
+static void usage(void) __dead2;
+static char *xfgets(FILE *);
+
+static STAILQ_HEAD(, diffline) diffhead = STAILQ_HEAD_INITIALIZER(diffhead);
+static size_t line_width; /* width of a line (two columns and divider) */
+static size_t width; /* width of each column */
+static size_t file1ln, file2ln; /* line number of file1 and file2 */
+static bool Iflag; /* ignore sets matching regexp */
+static bool lflag; /* print only left column for identical lines */
+static bool sflag; /* skip identical lines */
+static bool tflag; /* expand tabs */
+static int tabsize = 8; /* tab size */
+FILE *outfp; /* file to save changes to */
+const char *tmpdir; /* TMPDIR or /tmp */
+
+enum {
+ HELP_OPT = CHAR_MAX + 1,
+ NORMAL_OPT,
+ FCASE_SENSITIVE_OPT,
+ FCASE_IGNORE_OPT,
+ STRIPCR_OPT,
+ TSIZE_OPT,
+ DIFFPROG_OPT,
+};
+
+static struct option longopts[] = {
+ /* options only processed in sdiff */
+ { "suppress-common-lines", no_argument, NULL, 's' },
+ { "width", required_argument, NULL, 'w' },
+
+ { "output", required_argument, NULL, 'o' },
+ { "diff-program", required_argument, NULL, DIFFPROG_OPT },
+
+ /* Options processed by diff. */
+ { "ignore-file-name-case", no_argument, NULL, FCASE_IGNORE_OPT },
+ { "no-ignore-file-name-case", no_argument, NULL, FCASE_SENSITIVE_OPT },
+ { "strip-trailing-cr", no_argument, NULL, STRIPCR_OPT },
+ { "tabsize", required_argument, NULL, TSIZE_OPT },
+ { "help", no_argument, NULL, HELP_OPT },
+ { "text", no_argument, NULL, 'a' },
+ { "ignore-blank-lines", no_argument, NULL, 'B' },
+ { "ignore-space-change", no_argument, NULL, 'b' },
+ { "minimal", no_argument, NULL, 'd' },
+ { "ignore-tab-expansion", no_argument, NULL, 'E' },
+ { "ignore-matching-lines", required_argument, NULL, 'I' },
+ { "ignore-case", no_argument, NULL, 'i' },
+ { "left-column", no_argument, NULL, 'l' },
+ { "expand-tabs", no_argument, NULL, 't' },
+ { "speed-large-files", no_argument, NULL, 'H' },
+ { "ignore-all-space", no_argument, NULL, 'W' },
+
+ { NULL, 0, NULL, '\0'}
+};
+
+static const char *help_msg[] = {
+ "usage: sdiff [-abdilstW] [-I regexp] [-o outfile] [-w width] file1 file2\n",
+ "-l, --left-column: only print the left column for identical lines.",
+ "-o OUTFILE, --output=OUTFILE: interactively merge file1 and file2 into outfile.",
+ "-s, --suppress-common-lines: skip identical lines.",
+ "-w WIDTH, --width=WIDTH: print a maximum of WIDTH characters on each line.",
+ "",
+ "Options passed to diff(1) are:",
+ "\t-a, --text: treat file1 and file2 as text files.",
+ "\t-b, --ignore-trailing-cr: ignore trailing blank spaces.",
+ "\t-d, --minimal: minimize diff size.",
+ "\t-I RE, --ignore-matching-lines=RE: ignore changes whose line matches RE.",
+ "\t-i, --ignore-case: do a case-insensitive comparison.",
+ "\t-t, --expand-tabs: expand tabs to spaces.",
+ "\t-W, --ignore-all-space: ignore all whitespace.",
+ "\t--speed-large-files: assume large file with scattered changes.",
+ "\t--strip-trailing-cr: strip trailing carriage return.",
+ "\t--ignore-file-name-case: ignore case of file names.",
+ "\t--no-ignore-file-name-case: do not ignore file name case",
+ "\t--tabsize NUM: change size of tabs (default 8.)",
+
+ NULL,
+};
+
+/*
+ * Create temporary file if source_file is not a regular file.
+ * Returns temporary file name if one was malloced, NULL if unnecessary.
+ */
+static char *
+mktmpcpy(const char *source_file)
+{
+ struct stat sb;
+ ssize_t rcount;
+ int ifd, ofd;
+ u_char buf[BUFSIZ];
+ char *target_file;
+
+ /* Open input and output. */
+ ifd = open(source_file, O_RDONLY, 0);
+ /* File was opened successfully. */
+ if (ifd != -1) {
+ if (fstat(ifd, &sb) == -1)
+ err(2, "error getting file status from %s", source_file);
+
+ /* Regular file. */
+ if (S_ISREG(sb.st_mode)) {
+ close(ifd);
+ return (NULL);
+ }
+ } else {
+ /* If ``-'' does not exist the user meant stdin. */
+ if (errno == ENOENT && strcmp(source_file, "-") == 0)
+ ifd = STDIN_FILENO;
+ else
+ err(2, "error opening %s", source_file);
+ }
+
+ /* Not a regular file, so copy input into temporary file. */
+ if (asprintf(&target_file, "%s/sdiff.XXXXXXXXXX", tmpdir) == -1)
+ err(2, "asprintf");
+ if ((ofd = mkstemp(target_file)) == -1) {
+ warn("error opening %s", target_file);
+ goto FAIL;
+ }
+ while ((rcount = read(ifd, buf, sizeof(buf))) != -1 &&
+ rcount != 0) {
+ ssize_t wcount;
+
+ wcount = write(ofd, buf, (size_t)rcount);
+ if (-1 == wcount || rcount != wcount) {
+ warn("error writing to %s", target_file);
+ goto FAIL;
+ }
+ }
+ if (rcount == -1) {
+ warn("error reading from %s", source_file);
+ goto FAIL;
+ }
+
+ close(ifd);
+ close(ofd);
+
+ return (target_file);
+
+FAIL:
+ unlink(target_file);
+ exit(2);
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *diffpipe, *file1, *file2;
+ size_t diffargc = 0, flagc = 0, wval = WIDTH;
+ int ch, fd[2], i, ret, status;
+ pid_t pid;
+ const char *errstr, *outfile = NULL;
+ char **diffargv, *diffprog = diff_path, *flagv;
+ char *filename1, *filename2, *tmp1, *tmp2, *s1, *s2;
+ char I_arg[] = "-I";
+ char speed_lf[] = "--speed-large-files";
+
+ /*
+ * Process diff flags.
+ */
+ /*
+ * Allocate memory for diff arguments and NULL.
+ * Each flag has at most one argument, so doubling argc gives an
+ * upper limit of how many diff args can be passed. argv[0],
+ * file1, and file2 won't have arguments so doubling them will
+ * waste some memory; however we need an extra space for the
+ * NULL at the end, so it sort of works out.
+ */
+ if ((diffargv = calloc(argc, sizeof(char *) * 2)) == NULL)
+ err(2, NULL);
+
+ /* Add first argument, the program name. */
+ diffargv[diffargc++] = diffprog;
+
+ /* create a dynamic string for merging single-character options */
+ if ((flagv = malloc(flagc + 2)) == NULL)
+ err(2, NULL);
+ flagv[flagc] = '-';
+ flagv[flagc + 1] = '\0';
+ diffargv[diffargc++] = flagv;
+
+ while ((ch = getopt_long(argc, argv, "aBbdEHI:ilo:stWw:",
+ longopts, NULL)) != -1) {
+ switch (ch) {
+ /* only compatible --long-name-form with diff */
+ case FCASE_IGNORE_OPT:
+ case FCASE_SENSITIVE_OPT:
+ case STRIPCR_OPT:
+ case 'S':
+ break;
+ /* combine no-arg single switches */
+ case 'a':
+ case 'B':
+ case 'b':
+ case 'd':
+ case 'E':
+ case 'i':
+ case 'W':
+ flagc++;
+ flagv = realloc(flagv, flagc + 2);
+ /*
+ * In diff, the 'W' option is 'w' and the 'w' is 'W'.
+ */
+ flagv[flagc] = ch == 'W' ? 'w' : ch;
+ flagv[flagc + 1] = '\0';
+ break;
+ case 'H':
+ diffargv[diffargc++] = speed_lf;
+ break;
+ case DIFFPROG_OPT:
+ diffargv[0] = diffprog = optarg;
+ break;
+ case 'I':
+ Iflag = true;
+ diffargv[diffargc++] = I_arg;
+ diffargv[diffargc++] = optarg;
+ break;
+ case 'l':
+ lflag = true;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 's':
+ sflag = true;
+ break;
+ case 't':
+ tflag = true;
+ break;
+ case 'w':
+ wval = strtonum(optarg, WIDTH_MIN,
+ INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "width is %s: %s", errstr, optarg);
+ break;
+ case HELP_OPT:
+ for (i = 0; help_msg[i] != NULL; i++)
+ printf("%s\n", help_msg[i]);
+ exit(0);
+ break;
+ case TSIZE_OPT:
+ tabsize = strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "tabsize is %s: %s", errstr, optarg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ /* no single-character options were used */
+ if (flagc == 0) {
+ memmove(diffargv + 1, diffargv + 2,
+ sizeof(char *) * (diffargc - 2));
+ diffargc--;
+ free(flagv);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ if (outfile && (outfp = fopen(outfile, "w")) == NULL)
+ err(2, "could not open: %s", optarg);
+
+ if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+ tmpdir = _PATH_TMP;
+
+ filename1 = argv[0];
+ filename2 = argv[1];
+
+ /*
+ * Create temporary files for diff and sdiff to share if file1
+ * or file2 are not regular files. This allows sdiff and diff
+ * to read the same inputs if one or both inputs are stdin.
+ *
+ * If any temporary files were created, their names would be
+ * saved in tmp1 or tmp2. tmp1 should never equal tmp2.
+ */
+ tmp1 = tmp2 = NULL;
+ /* file1 and file2 are the same, so copy to same temp file. */
+ if (strcmp(filename1, filename2) == 0) {
+ if ((tmp1 = mktmpcpy(filename1)))
+ filename1 = filename2 = tmp1;
+ /* Copy file1 and file2 into separate temp files. */
+ } else {
+ if ((tmp1 = mktmpcpy(filename1)))
+ filename1 = tmp1;
+ if ((tmp2 = mktmpcpy(filename2)))
+ filename2 = tmp2;
+ }
+
+ if ((file1 = fopen(filename1, "r")) == NULL)
+ err(2, "could not open %s", filename1);
+ if ((file2 = fopen(filename2, "r")) == NULL)
+ err(2, "could not open %s", filename2);
+ if (!istextfile(file1) || !istextfile(file2)) {
+ ret = bindiff(file1, filename1, file2, filename2);
+ goto done;
+ }
+
+ diffargv[diffargc++] = filename1;
+ diffargv[diffargc++] = filename2;
+ /* Add NULL to end of array to indicate end of array. */
+ diffargv[diffargc++] = NULL;
+
+ /* Subtract column divider and divide by two. */
+ width = (wval - 3) / 2;
+ /* Make sure line_width can fit in size_t. */
+ if (width > (SIZE_MAX - 3) / 2)
+ errx(2, "width is too large: %zu", width);
+ line_width = width * 2 + 3;
+
+ if (pipe(fd))
+ err(2, "pipe");
+
+ if ((pid = fork()) < 0)
+ err(1, "fork()");
+ if (pid == 0) {
+ /* child */
+ /* We don't read from the pipe. */
+ close(fd[0]);
+ if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ _exit(2);
+ /* Free unused descriptor. */
+ close(fd[1]);
+ execvp(diffprog, diffargv);
+ _exit(2);
+ }
+
+ /* parent */
+ /* We don't write to the pipe. */
+ close(fd[1]);
+
+ /* Open pipe to diff command. */
+ if ((diffpipe = fdopen(fd[0], "r")) == NULL)
+ err(2, "could not open diff pipe");
+
+ /* Line numbers start at one. */
+ file1ln = file2ln = 1;
+
+ /* Read and parse diff output. */
+ while (parsecmd(diffpipe, file1, file2) != EOF)
+ ;
+ fclose(diffpipe);
+
+ /* Wait for diff to exit. */
+ if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status) ||
+ WEXITSTATUS(status) >= 2)
+ errx(2, "diff exited abnormally");
+ ret = WEXITSTATUS(status);
+
+ /* No more diffs, so enqueue common lines. */
+ if (lflag)
+ while ((s1 = xfgets(file1)))
+ enqueue(s1, ' ', NULL);
+ else
+ for (;;) {
+ s1 = xfgets(file1);
+ s2 = xfgets(file2);
+ if (s1 || s2)
+ enqueue(s1, ' ', s2);
+ else
+ break;
+ }
+ fclose(file1);
+ fclose(file2);
+ /* Process unmodified lines. */
+ processq();
+
+done:
+ /* Delete and free unneeded temporary files. */
+ if (tmp1 != NULL) {
+ if (unlink(tmp1) != 0)
+ warn("failed to delete %s", tmp1);
+ free(tmp1);
+ }
+ if (tmp2 != NULL) {
+ if (unlink(tmp2) != 0)
+ warn("failed to delete %s", tmp2);
+ free(tmp2);
+ }
+
+ /* Return diff exit status. */
+ free(diffargv);
+ if (flagc > 0)
+ free(flagv);
+ return (ret);
+}
+
+/*
+ * When sdiff detects a binary file as input.
+ */
+static int
+bindiff(FILE *f1, char *fn1, FILE *f2, char *fn2)
+{
+ int ch1, ch2;
+
+ flockfile(f1);
+ flockfile(f2);
+ do {
+ ch1 = getc_unlocked(f1);
+ ch2 = getc_unlocked(f2);
+ } while (ch1 != EOF && ch2 != EOF && ch1 == ch2);
+ funlockfile(f2);
+ funlockfile(f1);
+ if (ferror(f1)) {
+ warn("%s", fn1);
+ return (2);
+ }
+ if (ferror(f2)) {
+ warn("%s", fn2);
+ return (2);
+ }
+ if (ch1 != EOF || ch2 != EOF) {
+ printf("Binary files %s and %s differ\n", fn1, fn2);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Checks whether a file appears to be a text file.
+ */
+static int
+istextfile(FILE *f)
+{
+ int ch, i;
+
+ if (f == NULL)
+ return (1);
+ rewind(f);
+ for (i = 0; i <= MAX_CHECK; i++) {
+ ch = fgetc(f);
+ if (ch == '\0') {
+ rewind(f);
+ return (0);
+ }
+ if (ch == EOF)
+ break;
+ }
+ rewind(f);
+ return (1);
+}
+
+/*
+ * Prints an individual column (left or right), taking into account
+ * that tabs are variable-width. Takes a string, the current column
+ * the cursor is on the screen, and the maximum value of the column.
+ * The column value is updated as we go along.
+ */
+static void
+printcol(const char *s, size_t *col, const size_t col_max)
+{
+
+ for (; *s && *col < col_max; ++s) {
+ size_t new_col;
+
+ switch (*s) {
+ case '\t':
+ /*
+ * If rounding to next multiple of eight causes
+ * an integer overflow, just return.
+ */
+ if (*col > SIZE_MAX - tabsize)
+ return;
+
+ /* Round to next multiple of eight. */
+ new_col = (*col / tabsize + 1) * tabsize;
+
+ /*
+ * If printing the tab goes past the column
+ * width, don't print it and just quit.
+ */
+ if (new_col > col_max)
+ return;
+
+ if (tflag) {
+ do {
+ putchar(' ');
+ } while (++*col < new_col);
+ } else {
+ putchar(*s);
+ *col = new_col;
+ }
+ break;
+ default:
+ ++*col;
+ putchar(*s);
+ }
+ }
+}
+
+/*
+ * Prompts user to either choose between two strings or edit one, both,
+ * or neither.
+ */
+static void
+prompt(const char *s1, const char *s2)
+{
+ char *cmd;
+
+ /* Print command prompt. */
+ putchar('%');
+
+ /* Get user input. */
+ for (; (cmd = xfgets(stdin)); free(cmd)) {
+ const char *p;
+
+ /* Skip leading whitespace. */
+ for (p = cmd; isspace((unsigned char)*p); ++p)
+ ;
+ switch (*p) {
+ case 'e':
+ /* Skip `e'. */
+ ++p;
+ if (eparse(p, s1, s2) == -1)
+ goto USAGE;
+ break;
+ case 'l':
+ case '1':
+ /* Choose left column as-is. */
+ if (s1 != NULL)
+ fprintf(outfp, "%s\n", s1);
+ /* End of command parsing. */
+ break;
+ case 'q':
+ goto QUIT;
+ case 'r':
+ case '2':
+ /* Choose right column as-is. */
+ if (s2 != NULL)
+ fprintf(outfp, "%s\n", s2);
+ /* End of command parsing. */
+ break;
+ case 's':
+ sflag = true;
+ goto PROMPT;
+ case 'v':
+ sflag = false;
+ /* FALLTHROUGH */
+ default:
+ /* Interactive usage help. */
+USAGE:
+ int_usage();
+PROMPT:
+ putchar('%');
+
+ /* Prompt user again. */
+ continue;
+ }
+ free(cmd);
+ return;
+ }
+
+ /*
+ * If there was no error, we received an EOF from stdin, so we
+ * should quit.
+ */
+QUIT:
+ fclose(outfp);
+ exit(0);
+}
+
+/*
+ * Takes two strings, separated by a column divider. NULL strings are
+ * treated as empty columns. If the divider is the ` ' character, the
+ * second column is not printed (-l flag). In this case, the second
+ * string must be NULL. When the second column is NULL, the divider
+ * does not print the trailing space following the divider character.
+ *
+ * Takes into account that tabs can take multiple columns.
+ */
+static void
+println(const char *s1, const char divider, const char *s2)
+{
+ size_t col;
+
+ /* Print first column. Skips if s1 == NULL. */
+ col = 0;
+ if (s1) {
+ /* Skip angle bracket and space. */
+ printcol(s1, &col, width);
+
+ }
+
+ /* Otherwise, we pad this column up to width. */
+ for (; col < width; ++col)
+ putchar(' ');
+
+ /* Only print left column. */
+ if (divider == ' ' && !s2) {
+ printf(" (\n");
+ return;
+ }
+
+ /*
+ * Print column divider. If there is no second column, we don't
+ * need to add the space for padding.
+ */
+ if (!s2) {
+ printf(" %c\n", divider);
+ return;
+ }
+ printf(" %c ", divider);
+ col += 3;
+
+ /* Skip angle bracket and space. */
+ printcol(s2, &col, line_width);
+
+ putchar('\n');
+}
+
+/*
+ * Reads a line from file and returns as a string. If EOF is reached,
+ * NULL is returned. The returned string must be freed afterwards.
+ */
+static char *
+xfgets(FILE *file)
+{
+ size_t linecap;
+ ssize_t l;
+ char *s;
+
+ clearerr(file);
+ linecap = 0;
+ s = NULL;
+
+ if ((l = getline(&s, &linecap, file)) == -1) {
+ if (ferror(file))
+ err(2, "error reading file");
+ return (NULL);
+ }
+
+ if (s[l-1] == '\n')
+ s[l-1] = '\0';
+
+ return (s);
+}
+
+/*
+ * Parse ed commands from diffpipe and print lines from file1 (lines
+ * to change or delete) or file2 (lines to add or change).
+ * Returns EOF or 0.
+ */
+static int
+parsecmd(FILE *diffpipe, FILE *file1, FILE *file2)
+{
+ size_t file1start, file1end, file2start, file2end, n;
+ /* ed command line and pointer to characters in line */
+ char *line, *p, *q;
+ const char *errstr;
+ char c, cmd;
+
+ /* Read ed command. */
+ if (!(line = xfgets(diffpipe)))
+ return (EOF);
+
+ p = line;
+ /* Go to character after line number. */
+ while (isdigit((unsigned char)*p))
+ ++p;
+ c = *p;
+ *p++ = 0;
+ file1start = strtonum(line, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "file1 start is %s: %s", errstr, line);
+
+ /* A range is specified for file1. */
+ if (c == ',') {
+ q = p;
+ /* Go to character after file2end. */
+ while (isdigit((unsigned char)*p))
+ ++p;
+ c = *p;
+ *p++ = 0;
+ file1end = strtonum(q, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "file1 end is %s: %s", errstr, line);
+ if (file1start > file1end)
+ errx(2, "invalid line range in file1: %s", line);
+ } else
+ file1end = file1start;
+
+ cmd = c;
+ /* Check that cmd is valid. */
+ if (!(cmd == 'a' || cmd == 'c' || cmd == 'd'))
+ errx(2, "ed command not recognized: %c: %s", cmd, line);
+
+ q = p;
+ /* Go to character after line number. */
+ while (isdigit((unsigned char)*p))
+ ++p;
+ c = *p;
+ *p++ = 0;
+ file2start = strtonum(q, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "file2 start is %s: %s", errstr, line);
+
+ /*
+ * There should either be a comma signifying a second line
+ * number or the line should just end here.
+ */
+ if (c != ',' && c != '\0')
+ errx(2, "invalid line range in file2: %c: %s", c, line);
+
+ if (c == ',') {
+
+ file2end = strtonum(p, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(2, "file2 end is %s: %s", errstr, line);
+ if (file2start >= file2end)
+ errx(2, "invalid line range in file2: %s", line);
+ } else
+ file2end = file2start;
+
+ /* Appends happen _after_ stated line. */
+ if (cmd == 'a') {
+ if (file1start != file1end)
+ errx(2, "append cannot have a file1 range: %s",
+ line);
+ if (file1start == SIZE_MAX)
+ errx(2, "file1 line range too high: %s", line);
+ file1start = ++file1end;
+ }
+ /*
+ * I'm not sure what the deal is with the line numbers for
+ * deletes, though.
+ */
+ else if (cmd == 'd') {
+ if (file2start != file2end)
+ errx(2, "delete cannot have a file2 range: %s",
+ line);
+ if (file2start == SIZE_MAX)
+ errx(2, "file2 line range too high: %s", line);
+ file2start = ++file2end;
+ }
+
+ /*
+ * Continue reading file1 and file2 until we reach line numbers
+ * specified by diff. Should only happen with -I flag.
+ */
+ for (; file1ln < file1start && file2ln < file2start;
+ ++file1ln, ++file2ln) {
+ char *s1, *s2;
+
+ if (!(s1 = xfgets(file1)))
+ errx(2, "file1 shorter than expected");
+ if (!(s2 = xfgets(file2)))
+ errx(2, "file2 shorter than expected");
+
+ /* If the -l flag was specified, print only left column. */
+ if (lflag) {
+ free(s2);
+ /*
+ * XXX - If -l and -I are both specified, all
+ * unchanged or ignored lines are shown with a
+ * `(' divider. This matches GNU sdiff, but I
+ * believe it is a bug. Just check out:
+ * gsdiff -l -I '^$' samefile samefile.
+ */
+ if (Iflag)
+ enqueue(s1, '(', NULL);
+ else
+ enqueue(s1, ' ', NULL);
+ } else
+ enqueue(s1, ' ', s2);
+ }
+ /* Ignore deleted lines. */
+ for (; file1ln < file1start; ++file1ln) {
+ char *s;
+
+ if (!(s = xfgets(file1)))
+ errx(2, "file1 shorter than expected");
+
+ enqueue(s, '(', NULL);
+ }
+ /* Ignore added lines. */
+ for (; file2ln < file2start; ++file2ln) {
+ char *s;
+
+ if (!(s = xfgets(file2)))
+ errx(2, "file2 shorter than expected");
+
+ /* If -l flag was given, don't print right column. */
+ if (lflag)
+ free(s);
+ else
+ enqueue(NULL, ')', s);
+ }
+
+ /* Process unmodified or skipped lines. */
+ processq();
+
+ switch (cmd) {
+ case 'a':
+ printa(file2, file2end);
+ n = file2end - file2start + 1;
+ break;
+ case 'c':
+ printc(file1, file1end, file2, file2end);
+ n = file1end - file1start + 1 + 1 + file2end - file2start + 1;
+ break;
+ case 'd':
+ printd(file1, file1end);
+ n = file1end - file1start + 1;
+ break;
+ default:
+ errx(2, "invalid diff command: %c: %s", cmd, line);
+ }
+ free(line);
+
+ /* Skip to next ed line. */
+ while (n--) {
+ if (!(line = xfgets(diffpipe)))
+ errx(2, "diff ended early");
+ free(line);
+ }
+
+ return (0);
+}
+
+/*
+ * Queues up a diff line.
+ */
+static void
+enqueue(char *left, char divider, char *right)
+{
+ struct diffline *diffp;
+
+ if (!(diffp = malloc(sizeof(struct diffline))))
+ err(2, "enqueue");
+ diffp->left = left;
+ diffp->div = divider;
+ diffp->right = right;
+ STAILQ_INSERT_TAIL(&diffhead, diffp, diffentries);
+}
+
+/*
+ * Free a diffline structure and its elements.
+ */
+static void
+freediff(struct diffline *diffp)
+{
+
+ free(diffp->left);
+ free(diffp->right);
+ free(diffp);
+}
+
+/*
+ * Append second string into first. Repeated appends to the same string
+ * are cached, making this an O(n) function, where n = strlen(append).
+ */
+static void
+astrcat(char **s, const char *append)
+{
+ /* Length of string in previous run. */
+ static size_t offset = 0;
+ size_t newsiz;
+ /*
+ * String from previous run. Compared to *s to see if we are
+ * dealing with the same string. If so, we can use offset.
+ */
+ static const char *oldstr = NULL;
+ char *newstr;
+
+ /*
+ * First string is NULL, so just copy append.
+ */
+ if (!*s) {
+ if (!(*s = strdup(append)))
+ err(2, "astrcat");
+
+ /* Keep track of string. */
+ offset = strlen(*s);
+ oldstr = *s;
+
+ return;
+ }
+
+ /*
+ * *s is a string so concatenate.
+ */
+
+ /* Did we process the same string in the last run? */
+ /*
+ * If this is a different string from the one we just processed
+ * cache new string.
+ */
+ if (oldstr != *s) {
+ offset = strlen(*s);
+ oldstr = *s;
+ }
+
+ /* Size = strlen(*s) + \n + strlen(append) + '\0'. */
+ newsiz = offset + 1 + strlen(append) + 1;
+
+ /* Resize *s to fit new string. */
+ newstr = realloc(*s, newsiz);
+ if (newstr == NULL)
+ err(2, "astrcat");
+ *s = newstr;
+
+ /* *s + offset should be end of string. */
+ /* Concatenate. */
+ strlcpy(*s + offset, "\n", newsiz - offset);
+ strlcat(*s + offset, append, newsiz - offset);
+
+ /* New string length should be exactly newsiz - 1 characters. */
+ /* Store generated string's values. */
+ offset = newsiz - 1;
+ oldstr = *s;
+}
+
+/*
+ * Process diff set queue, printing, prompting, and saving each diff
+ * line stored in queue.
+ */
+static void
+processq(void)
+{
+ struct diffline *diffp;
+ char divc, *left, *right;
+
+ /* Don't process empty queue. */
+ if (STAILQ_EMPTY(&diffhead))
+ return;
+
+ /* Remember the divider. */
+ divc = STAILQ_FIRST(&diffhead)->div;
+
+ left = NULL;
+ right = NULL;
+ /*
+ * Go through set of diffs, concatenating each line in left or
+ * right column into two long strings, `left' and `right'.
+ */
+ STAILQ_FOREACH(diffp, &diffhead, diffentries) {
+ /*
+ * Print changed lines if -s was given,
+ * print all lines if -s was not given.
+ */
+ if (!sflag || diffp->div == '|' || diffp->div == '<' ||
+ diffp->div == '>')
+ println(diffp->left, diffp->div, diffp->right);
+
+ /* Append new lines to diff set. */
+ if (diffp->left)
+ astrcat(&left, diffp->left);
+ if (diffp->right)
+ astrcat(&right, diffp->right);
+ }
+
+ /* Empty queue and free each diff line and its elements. */
+ while (!STAILQ_EMPTY(&diffhead)) {
+ diffp = STAILQ_FIRST(&diffhead);
+ STAILQ_REMOVE_HEAD(&diffhead, diffentries);
+ freediff(diffp);
+ }
+
+ /* Write to outfp, prompting user if lines are different. */
+ if (outfp)
+ switch (divc) {
+ case ' ': case '(': case ')':
+ fprintf(outfp, "%s\n", left);
+ break;
+ case '|': case '<': case '>':
+ prompt(left, right);
+ break;
+ default:
+ errx(2, "invalid divider: %c", divc);
+ }
+
+ /* Free left and right. */
+ free(left);
+ free(right);
+}
+
+/*
+ * Print lines following an (a)ppend command.
+ */
+static void
+printa(FILE *file, size_t line2)
+{
+ char *line;
+
+ for (; file2ln <= line2; ++file2ln) {
+ if (!(line = xfgets(file)))
+ errx(2, "append ended early");
+ enqueue(NULL, '>', line);
+ }
+ processq();
+}
+
+/*
+ * Print lines following a (c)hange command, from file1ln to file1end
+ * and from file2ln to file2end.
+ */
+static void
+printc(FILE *file1, size_t file1end, FILE *file2, size_t file2end)
+{
+ struct fileline {
+ STAILQ_ENTRY(fileline) fileentries;
+ char *line;
+ };
+ STAILQ_HEAD(, fileline) delqhead = STAILQ_HEAD_INITIALIZER(delqhead);
+
+ /* Read lines to be deleted. */
+ for (; file1ln <= file1end; ++file1ln) {
+ struct fileline *linep;
+ char *line1;
+
+ /* Read lines from both. */
+ if (!(line1 = xfgets(file1)))
+ errx(2, "error reading file1 in delete in change");
+
+ /* Add to delete queue. */
+ if (!(linep = malloc(sizeof(struct fileline))))
+ err(2, "printc");
+ linep->line = line1;
+ STAILQ_INSERT_TAIL(&delqhead, linep, fileentries);
+ }
+
+ /* Process changed lines.. */
+ for (; !STAILQ_EMPTY(&delqhead) && file2ln <= file2end;
+ ++file2ln) {
+ struct fileline *del;
+ char *add;
+
+ /* Get add line. */
+ if (!(add = xfgets(file2)))
+ errx(2, "error reading add in change");
+
+ del = STAILQ_FIRST(&delqhead);
+ enqueue(del->line, '|', add);
+ STAILQ_REMOVE_HEAD(&delqhead, fileentries);
+ /*
+ * Free fileline structure but not its elements since
+ * they are queued up.
+ */
+ free(del);
+ }
+ processq();
+
+ /* Process remaining lines to add. */
+ for (; file2ln <= file2end; ++file2ln) {
+ char *add;
+
+ /* Get add line. */
+ if (!(add = xfgets(file2)))
+ errx(2, "error reading add in change");
+
+ enqueue(NULL, '>', add);
+ }
+ processq();
+
+ /* Process remaining lines to delete. */
+ while (!STAILQ_EMPTY(&delqhead)) {
+ struct fileline *filep;
+
+ filep = STAILQ_FIRST(&delqhead);
+ enqueue(filep->line, '<', NULL);
+ STAILQ_REMOVE_HEAD(&delqhead, fileentries);
+ free(filep);
+ }
+ processq();
+}
+
+/*
+ * Print deleted lines from file, from file1ln to file1end.
+ */
+static void
+printd(FILE *file1, size_t file1end)
+{
+ char *line1;
+
+ /* Print out lines file1ln to line2. */
+ for (; file1ln <= file1end; ++file1ln) {
+ if (!(line1 = xfgets(file1)))
+ errx(2, "file1 ended early in delete");
+ enqueue(line1, '<', NULL);
+ }
+ processq();
+}
+
+/*
+ * Interactive mode usage.
+ */
+static void
+int_usage(void)
+{
+
+ puts("e:\tedit blank diff\n"
+ "eb:\tedit both diffs concatenated\n"
+ "el:\tedit left diff\n"
+ "er:\tedit right diff\n"
+ "l | 1:\tchoose left diff\n"
+ "r | 2:\tchoose right diff\n"
+ "s:\tsilent mode--don't print identical lines\n"
+ "v:\tverbose mode--print identical lines\n"
+ "q:\tquit");
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: sdiff [-abdilstHW] [-I regexp] [-o outfile] [-w width] file1"
+ " file2\n");
+ exit(2);
+}
diff --git a/usr.bin/sdiff/tests/Makefile b/usr.bin/sdiff/tests/Makefile
new file mode 100644
index 000000000000..a849e4a2c0a0
--- /dev/null
+++ b/usr.bin/sdiff/tests/Makefile
@@ -0,0 +1,33 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= sdiff_test
+
+${PACKAGE}FILES+= \
+ d_dot.in \
+ d_flags_l.out \
+ d_flags_s.out \
+ d_flags_w.out \
+ d_iflags_a1.out \
+ d_iflags_a2.out \
+ d_iflags_b1.out \
+ d_iflags_b2.out \
+ d_iflags_c1.out \
+ d_iflags_c2.out \
+ d_iflags_d1.out \
+ d_iflags_d2.out \
+ d_input1 \
+ d_input2 \
+ d_oneline.in \
+ d_oneline_a.out \
+ d_oneline_b.out \
+ d_same.out \
+ d_short.out \
+ d_tabends.in \
+ d_tabends_a.out \
+ d_tabends_b.out \
+ d_tabends_c.out \
+ d_tabs.out \
+ d_tabs1.in \
+ d_tabs2.in
+
+.include <bsd.test.mk>
diff --git a/usr.bin/sdiff/tests/Makefile.depend b/usr.bin/sdiff/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/sdiff/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sdiff/tests/d_dot.in b/usr.bin/sdiff/tests/d_dot.in
new file mode 100644
index 000000000000..9c558e357c41
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_dot.in
@@ -0,0 +1 @@
+.
diff --git a/usr.bin/sdiff/tests/d_flags_l.out b/usr.bin/sdiff/tests/d_flags_l.out
new file mode 100644
index 000000000000..ac8d2ad41e5a
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_flags_l.out
@@ -0,0 +1,102 @@
+Policy: /usr/bin/lynx, Emulation: native (
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ native-__sysctl: permit (
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-close: permit (
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit (
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ native-fsread: filename eq "/tmp" then permit (
+ > native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit (
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit (
+ native-fsread: filename eq "/usr/bin" then permit (
+ native-fsread: filename eq "/usr/games" then permit (
+ native-fsread: filename eq "/usr/include" then permit (
+ native-fsread: filename eq "/usr/lib" then permit (
+ native-fsread: filename match "/usr/lib/libc.so.*" then p <
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t <
+ native-fsread: filename match "/usr/lib/libncurses.so.*" <
+ native-fsread: filename match "/usr/lib/libssl.so.*" then <
+ native-fsread: filename eq "/usr/libdata" then permit (
+ native-fsread: filename eq "/usr/libexec" then permit (
+ native-fsread: filename eq "/usr/lkm" then permit (
+ native-fsread: filename eq "/usr/local" then permit (
+ native-fsread: filename eq "/usr/mdec" then permit (
+ native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then | native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename match "/<non-existent filename>:
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca (
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t (
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" (
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/dev.db" then permit (
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-poll: permit (
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK (
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK (
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_flags_s.out b/usr.bin/sdiff/tests/d_flags_s.out
new file mode 100644
index 000000000000..8af11f3ff4b6
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_flags_s.out
@@ -0,0 +1,79 @@
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ > native-fswrite: filename match "/tmp/lynx-*" then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p <
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t <
+ native-fsread: filename match "/usr/lib/libncurses.so.*" <
+ native-fsread: filename match "/usr/lib/libssl.so.*" then <
+ native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then | native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename match "/<non-existent filename>:
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_flags_w.out b/usr.bin/sdiff/tests/d_flags_w.out
new file mode 100644
index 000000000000..19ea79bf6112
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_flags_w.out
@@ -0,0 +1,102 @@
+Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ native-__sysctl: permit native-__sysctl: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-close: permit native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit
+ > native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit native-fsread: filename match "/tmp/lynx-*/." then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p <
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t <
+ native-fsread: filename match "/usr/lib/libncurses.so.*" <
+ native-fsread: filename match "/usr/lib/libssl.so.*" then <
+ native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then | native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename match "/<non-existent filename>:
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca native-fsread: filename eq "/usr/obj/bin/systrace/.mailca
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db"
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-poll: permit native-poll: permit
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_iflags_a1.out b/usr.bin/sdiff/tests/d_iflags_a1.out
new file mode 100644
index 000000000000..2a0f5328aeb2
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_a1.out
@@ -0,0 +1,100 @@
+Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ native-__sysctl: permit native-__sysctl: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-close: permit native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit native-fswrite: filename match "/tmp/lynx-*" then permit
+ ) native-fsread: filename match "/tmp/lynx-*/." then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename match "/<non-existent filename>:
+ native-fsread: filename eq "/usr/obj" then permit native-fsread: filename eq "/usr/obj/bin/systrace/.mailca
+ native-fsread: filename eq "/usr/obj/bin" then permit native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca (
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t (
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db"
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-poll: permit native-poll: permit
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_iflags_a2.out b/usr.bin/sdiff/tests/d_iflags_a2.out
new file mode 100644
index 000000000000..4e0d349b79e7
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_a2.out
@@ -0,0 +1,96 @@
+Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native
+ native-issetugid: permit <
+ native-mprotect: permit <
+ native-mmap: permit <
+ native-__sysctl: permit native-__sysctl: permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe <
+ native-fstat: permit <
+ native-close: permit native-close: permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit
+ native-munmap: permit | native-fsread: filename match "/<non-existent filename>:
+ native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ > native-fsread: filename eq "/etc/utmp" then permit
+ > native-fsread: filename eq "/home" then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ > native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit (
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "/etc/lynx.cfg" then permit <
+ native-fsread: filename eq "/" then permit <
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then <
+ native-fsread: filename eq "/usr/obj/bin" then permit <
+ native-fcntl: permit <
+ native-getdirentries: permit <
+ native-lseek: permit <
+ native-fsread: filename eq "/usr/obj" then permit <
+ native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/usr/local" then permit native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/home" then permit native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/obj" then permit native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "$HOME/.lynxrc" then permit native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename match "/<non-existent filename>: native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ ) native-fsread: filename eq "/usr/obj/bin/systrace/.mailca
+ ) native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-sigaction: permit <
+ native-ioctl: permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db"
+ native-pread: permit <
+ native-write: permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ native-poll: permit | native-fstat: permit
+ native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit
+ > native-getdirentries: permit
+ > native-getpid: permit
+ native-gettimeofday: permit native-gettimeofday: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit
+ native-sendto: true then permit | native-mmap: permit
+ native-select: permit | native-mprotect: prot eq "PROT_READ" then permit
+ > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC"
+ > native-munmap: permit
+ > native-nanosleep: permit
+ > native-poll: permit
+ > native-pread: permit
+ > native-read: permit
+ native-recvfrom: permit native-recvfrom: permit
+ > native-select: permit
+ > native-sendto: true then permit
+ > native-sigaction: permit
+ > native-sigprocmask: permit
+ > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit
+ native-exit: permit <
diff --git a/usr.bin/sdiff/tests/d_iflags_b1.out b/usr.bin/sdiff/tests/d_iflags_b1.out
new file mode 100644
index 000000000000..3e548b693d08
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_b1.out
@@ -0,0 +1,69 @@
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_iflags_b2.out b/usr.bin/sdiff/tests/d_iflags_b2.out
new file mode 100644
index 000000000000..4504c36ec035
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_b2.out
@@ -0,0 +1,65 @@
+ native-issetugid: permit <
+ native-mprotect: permit <
+ native-mmap: permit <
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe <
+ native-fstat: permit <
+ native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit
+ native-munmap: permit | native-fsread: filename match "/<non-existent filename>:
+ native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ > native-fsread: filename eq "/etc/utmp" then permit
+ > native-fsread: filename eq "/home" then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ > native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "/etc/lynx.cfg" then permit <
+ native-fsread: filename eq "/" then permit <
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then <
+ native-fsread: filename eq "/usr/obj/bin" then permit <
+ native-fcntl: permit <
+ native-getdirentries: permit <
+ native-lseek: permit <
+ native-fsread: filename eq "/usr/obj" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-sigaction: permit <
+ native-ioctl: permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-pread: permit <
+ native-write: permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ native-poll: permit | native-fstat: permit
+ native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit
+ > native-getdirentries: permit
+ > native-getpid: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit
+ native-sendto: true then permit | native-mmap: permit
+ native-select: permit | native-mprotect: prot eq "PROT_READ" then permit
+ > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC"
+ > native-munmap: permit
+ > native-nanosleep: permit
+ > native-poll: permit
+ > native-pread: permit
+ > native-read: permit
+ > native-select: permit
+ > native-sendto: true then permit
+ > native-sigaction: permit
+ > native-sigprocmask: permit
+ > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit
+ native-exit: permit <
diff --git a/usr.bin/sdiff/tests/d_iflags_c1.out b/usr.bin/sdiff/tests/d_iflags_c1.out
new file mode 100644
index 000000000000..e9ac88e54ae1
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_c1.out
@@ -0,0 +1,99 @@
+Policy: /usr/bin/lynx, Emulation: native (
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ native-__sysctl: permit (
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-close: permit (
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit (
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ native-fsread: filename eq "/tmp" then permit (
+ native-fsread: filename match "/tmp/lynx-*/." then permit (
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit (
+ native-fsread: filename eq "/usr/bin" then permit (
+ native-fsread: filename eq "/usr/games" then permit (
+ native-fsread: filename eq "/usr/include" then permit (
+ native-fsread: filename eq "/usr/lib" then permit (
+ native-fsread: filename match "/usr/lib/libc.so.*" then p (
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t (
+ native-fsread: filename match "/usr/lib/libncurses.so.*" (
+ native-fsread: filename match "/usr/lib/libssl.so.*" then (
+ native-fsread: filename eq "/usr/libdata" then permit (
+ native-fsread: filename eq "/usr/libexec" then permit (
+ native-fsread: filename eq "/usr/lkm" then permit (
+ native-fsread: filename eq "/usr/local" then permit (
+ native-fsread: filename eq "/usr/mdec" then permit (
+ native-fsread: filename eq "/usr/obj" then permit (
+ native-fsread: filename eq "/usr/obj/bin" then permit (
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then (
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca (
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t (
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" (
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/dev.db" then permit (
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-poll: permit (
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK (
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK (
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_iflags_c2.out b/usr.bin/sdiff/tests/d_iflags_c2.out
new file mode 100644
index 000000000000..fe7af0ebee54
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_c2.out
@@ -0,0 +1,94 @@
+Policy: /usr/bin/lynx, Emulation: native (
+ native-issetugid: permit <
+ native-mprotect: permit <
+ native-mmap: permit <
+ native-__sysctl: permit (
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe <
+ native-fstat: permit <
+ native-close: permit (
+ native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit
+ native-munmap: permit | native-fsread: filename match "/<non-existent filename>:
+ native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit (
+ native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ > native-fsread: filename eq "/etc/utmp" then permit
+ > native-fsread: filename eq "/home" then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ > native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/tmp" then permit (
+ native-fswrite: filename match "/tmp/lynx-*" then permit (
+ native-fsread: filename match "/tmp/lynx-*/." then permit (
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "/etc/lynx.cfg" then permit <
+ native-fsread: filename eq "/" then permit <
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then <
+ native-fsread: filename eq "/usr/obj/bin" then permit <
+ native-fcntl: permit <
+ native-getdirentries: permit <
+ native-lseek: permit <
+ native-fsread: filename eq "/usr/obj" then permit <
+ native-fsread: filename eq "/usr" then permit (
+ native-fsread: filename eq "/usr/bin" then permit (
+ native-fsread: filename eq "/usr/games" then permit (
+ native-fsread: filename eq "/usr/include" then permit (
+ native-fsread: filename eq "/usr/lib" then permit (
+ native-fsread: filename eq "/usr/libdata" then permit (
+ native-fsread: filename eq "/usr/libexec" then permit (
+ native-fsread: filename eq "/usr/lkm" then permit (
+ native-fsread: filename eq "/usr/local" then permit (
+ native-fsread: filename eq "/usr/mdec" then permit (
+ native-fsread: filename eq "/home" then permit (
+ native-fsread: filename eq "/obj" then permit (
+ native-fsread: filename eq "$HOME/.lynxrc" then permit (
+ native-fsread: filename match "/<non-existent filename>: (
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca (
+ native-fsread: filename eq "$HOME/.mailcap" then permit (
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t (
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-sigaction: permit <
+ native-ioctl: permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" (
+ native-pread: permit <
+ native-write: permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "/var/run/dev.db" then permit (
+ native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ native-poll: permit | native-fstat: permit
+ native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit
+ > native-getdirentries: permit
+ > native-getpid: permit
+ native-gettimeofday: permit (
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit
+ native-sendto: true then permit | native-mmap: permit
+ native-select: permit | native-mprotect: prot eq "PROT_READ" then permit
+ > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC"
+ > native-munmap: permit
+ > native-nanosleep: permit
+ > native-poll: permit
+ > native-pread: permit
+ > native-read: permit
+ native-recvfrom: permit (
+ > native-select: permit
+ > native-sendto: true then permit
+ > native-sigaction: permit
+ > native-sigprocmask: permit
+ > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK (
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit
+ native-exit: permit <
diff --git a/usr.bin/sdiff/tests/d_iflags_d1.out b/usr.bin/sdiff/tests/d_iflags_d1.out
new file mode 100644
index 000000000000..3e548b693d08
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_d1.out
@@ -0,0 +1,69 @@
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ > native-fstat: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/<non-existent filename>: | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "$HOME/.lynxrc" then permit <
+ native-fsread: filename eq "$HOME/.mailcap" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "/obj" then permit <
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permit
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then permit <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_iflags_d2.out b/usr.bin/sdiff/tests/d_iflags_d2.out
new file mode 100644
index 000000000000..4504c36ec035
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_iflags_d2.out
@@ -0,0 +1,65 @@
+ native-issetugid: permit <
+ native-mprotect: permit <
+ native-mmap: permit <
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe <
+ native-fstat: permit <
+ native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit
+ native-munmap: permit | native-fsread: filename match "/<non-existent filename>:
+ native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit
+ > native-fsread: filename eq "/etc/utmp" then permit
+ > native-fsread: filename eq "/home" then permit
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ > native-fsread: filename eq "$HOME/.lynxrc" then permit
+ > native-fsread: filename eq "$HOME/.mailcap" then permit
+ > native-fsread: filename eq "$HOME/.mime.types" then permi
+ > native-fsread: filename eq "$HOME/.terminfo" then permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ > native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "/etc/lynx.cfg" then permit <
+ native-fsread: filename eq "/" then permit <
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then <
+ native-fsread: filename eq "/usr/obj/bin" then permit <
+ native-fcntl: permit <
+ native-getdirentries: permit <
+ native-lseek: permit <
+ native-fsread: filename eq "/usr/obj" then permit <
+ native-fsread: filename eq "$HOME/.mime.types" then permi <
+ native-sigaction: permit <
+ native-ioctl: permit <
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm <
+ native-fsread: filename eq "$HOME/.terminfo" then permit <
+ native-pread: permit <
+ native-write: permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per <
+ native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ native-poll: permit | native-fstat: permit
+ native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit
+ > native-getdirentries: permit
+ > native-getpid: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit
+ native-sendto: true then permit | native-mmap: permit
+ native-select: permit | native-mprotect: prot eq "PROT_READ" then permit
+ > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm
+ > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC"
+ > native-munmap: permit
+ > native-nanosleep: permit
+ > native-poll: permit
+ > native-pread: permit
+ > native-read: permit
+ > native-select: permit
+ > native-sendto: true then permit
+ > native-sigaction: permit
+ > native-sigprocmask: permit
+ > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit
+ native-exit: permit <
diff --git a/usr.bin/sdiff/tests/d_input1 b/usr.bin/sdiff/tests/d_input1
new file mode 100644
index 000000000000..686e8ea22774
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_input1
@@ -0,0 +1,72 @@
+Policy: /usr/bin/lynx, Emulation: native
+ native-__sysctl: permit
+ native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit
+ native-exit: permit
+ native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename eq "/" then permit
+ native-fsread: filename match "/<non-existent filename>: *" then permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-fsread: filename eq "/etc/utmp" then permit
+ native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "$HOME" then permit
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
+ native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "$HOME/.mime.types" then permit
+ native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "$HOME/.terminfo.db" then permit
+ native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/tmp" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" then permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then permit
+ native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
+ native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then permit
+ native-fstat: permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-getdirentries: permit
+ native-getpid: permit
+ native-gettimeofday: permit
+ native-ioctl: permit
+ native-issetugid: permit
+ native-lseek: permit
+ native-mmap: permit
+ native-mprotect: prot eq "PROT_READ" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" then permit
+ native-munmap: permit
+ native-nanosleep: permit
+ native-poll: permit
+ native-pread: permit
+ native-read: permit
+ native-recvfrom: permit
+ native-select: permit
+ native-sendto: true then permit
+ native-sigaction: permit
+ native-sigprocmask: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit
+ native-write: permit
diff --git a/usr.bin/sdiff/tests/d_input2 b/usr.bin/sdiff/tests/d_input2
new file mode 100644
index 000000000000..70e1b57f5fbf
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_input2
@@ -0,0 +1,69 @@
+Policy: /usr/bin/lynx, Emulation: native
+ native-issetugid: permit
+ native-mprotect: permit
+ native-mmap: permit
+ native-__sysctl: permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then permit
+ native-fstat: permit
+ native-close: permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then permit
+ native-read: permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then permit
+ native-munmap: permit
+ native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-getpid: permit
+ native-fsread: filename eq "/tmp" then permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename eq "$HOME" then permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fcntl: permit
+ native-getdirentries: permit
+ native-lseek: permit
+ native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename match "/<non-existent filename>: *" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit
+ native-fsread: filename eq "$HOME/.mime.types" then permit
+ native-sigaction: permit
+ native-ioctl: permit
+ native-fsread: filename eq "$HOME/.terminfo.db" then permit
+ native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
+ native-pread: permit
+ native-write: permit
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
+ native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/etc/utmp" then permit
+ native-poll: permit
+ native-nanosleep: permit
+ native-gettimeofday: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit
+ native-sendto: true then permit
+ native-select: permit
+ native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit
+ native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_oneline.in b/usr.bin/sdiff/tests/d_oneline.in
new file mode 100644
index 000000000000..acbe86c7c895
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_oneline.in
@@ -0,0 +1 @@
+abcd
diff --git a/usr.bin/sdiff/tests/d_oneline_a.out b/usr.bin/sdiff/tests/d_oneline_a.out
new file mode 100644
index 000000000000..18f7c6bd02cb
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_oneline_a.out
@@ -0,0 +1 @@
+ > abcd
diff --git a/usr.bin/sdiff/tests/d_oneline_b.out b/usr.bin/sdiff/tests/d_oneline_b.out
new file mode 100644
index 000000000000..04cad47ce037
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_oneline_b.out
@@ -0,0 +1 @@
+abcd <
diff --git a/usr.bin/sdiff/tests/d_same.out b/usr.bin/sdiff/tests/d_same.out
new file mode 100644
index 000000000000..f929fcf1915b
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_same.out
@@ -0,0 +1,72 @@
+Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native
+ native-__sysctl: permit native-__sysctl: permit
+ native-close: permit native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then p native-connect: sockaddr match "inet-\\\[*\\\]:80" then p
+ native-exit: permit native-exit: permit
+ native-fcntl: cmd eq "F_SETFD" then permit native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename eq "/" then permit native-fsread: filename eq "/" then permit
+ native-fsread: filename match "/<non-existent filename>: native-fsread: filename match "/<non-existent filename>:
+ native-fsread: filename eq "/etc/lynx.cfg" then permit native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-fsread: filename eq "/etc/utmp" then permit native-fsread: filename eq "/etc/utmp" then permit
+ native-fsread: filename eq "/home" then permit native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "$HOME" then permit native-fsread: filename eq "$HOME" then permit
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then per native-fsread: filename eq "$HOME/.lynx-keymaps" then per
+ native-fsread: filename eq "$HOME/.lynxrc" then permit native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "$HOME/.mime.types" then permi native-fsread: filename eq "$HOME/.mime.types" then permi
+ native-fsread: filename eq "$HOME/.terminfo" then permit native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "$HOME/.terminfo.db" then perm native-fsread: filename eq "$HOME/.terminfo.db" then perm
+ native-fsread: filename eq "/obj" then permit native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then p native-fsread: filename match "/usr/lib/libc.so.*" then p
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" t native-fsread: filename match "/usr/lib/libcrypto.so.*" t
+ native-fsread: filename match "/usr/lib/libncurses.so.*" native-fsread: filename match "/usr/lib/libncurses.so.*"
+ native-fsread: filename match "/usr/lib/libssl.so.*" then native-fsread: filename match "/usr/lib/libssl.so.*" then
+ native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj" then permit native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then native-fsread: filename eq "/usr/obj/bin/systrace/." then
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailca native-fsread: filename eq "/usr/obj/bin/systrace/.mailca
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db"
+ native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then pe native-fsread: filename eq "/var/run/ld.so.hints" then pe
+ native-fstat: permit native-fstat: permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-getdirentries: permit native-getdirentries: permit
+ native-getpid: permit native-getpid: permit
+ native-gettimeofday: permit native-gettimeofday: permit
+ native-ioctl: permit native-ioctl: permit
+ native-issetugid: permit native-issetugid: permit
+ native-lseek: permit native-lseek: permit
+ native-mmap: permit native-mmap: permit
+ native-mprotect: prot eq "PROT_READ" then permit native-mprotect: prot eq "PROT_READ" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC"
+ native-munmap: permit native-munmap: permit
+ native-nanosleep: permit native-nanosleep: permit
+ native-poll: permit native-poll: permit
+ native-pread: permit native-pread: permit
+ native-read: permit native-read: permit
+ native-recvfrom: permit native-recvfrom: permit
+ native-select: permit native-select: permit
+ native-sendto: true then permit native-sendto: true then permit
+ native-sigaction: permit native-sigaction: permit
+ native-sigprocmask: permit native-sigprocmask: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK
+ native-write: permit native-write: permit
diff --git a/usr.bin/sdiff/tests/d_short.out b/usr.bin/sdiff/tests/d_short.out
new file mode 100644
index 000000000000..7a334601721c
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_short.out
@@ -0,0 +1,15 @@
+Policy: /usr/bin/lynx, Emulation: native
+ native-issetugid: permit
+ native-mprotect: permit
+ native-mmap: permit
+ native-__sysctl: permit
+ native-close: permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then permit
+ native-read: permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then permit
+ native-munmap: permit
+ native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit
diff --git a/usr.bin/sdiff/tests/d_tabends.in b/usr.bin/sdiff/tests/d_tabends.in
new file mode 100644
index 000000000000..0547049d45cc
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabends.in
@@ -0,0 +1,17 @@
+
+0
+01
+012
+0123
+01234
+012345
+0123456
+01234567
+012345670
+0123456701
+01234567012
+012345670123
+0123456701234
+01234567012345
+012345670123456
+0123456701234567
diff --git a/usr.bin/sdiff/tests/d_tabends_a.out b/usr.bin/sdiff/tests/d_tabends_a.out
new file mode 100644
index 000000000000..423bd02ce1b6
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabends_a.out
@@ -0,0 +1,17 @@
+ <
+0 <
+01 <
+012 <
+0123 <
+01234 <
+012345 <
+0123456 <
+01234567 <
+012345670 <
+0123456701 <
+01234567012 <
+012345670123 <
+0123456701234 <
+0123456701234 <
+0123456701234 <
+0123456701234 <
diff --git a/usr.bin/sdiff/tests/d_tabends_b.out b/usr.bin/sdiff/tests/d_tabends_b.out
new file mode 100644
index 000000000000..b180705452a4
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabends_b.out
@@ -0,0 +1,17 @@
+ >
+ > 0
+ > 01
+ > 012
+ > 0123
+ > 01234
+ > 012345
+ > 0123456
+ > 01234567
+ > 012345670
+ > 0123456701
+ > 01234567012
+ > 012345670123
+ > 0123456701234
+ > 0123456701234
+ > 0123456701234
+ > 0123456701234
diff --git a/usr.bin/sdiff/tests/d_tabends_c.out b/usr.bin/sdiff/tests/d_tabends_c.out
new file mode 100644
index 000000000000..c3013824af74
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabends_c.out
@@ -0,0 +1,17 @@
+ <
+0 <
+01 <
+012 <
+0123 <
+01234 <
+012345 <
+0123456 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
+01234567 <
diff --git a/usr.bin/sdiff/tests/d_tabs.out b/usr.bin/sdiff/tests/d_tabs.out
new file mode 100644
index 000000000000..a67d7b146a38
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabs.out
@@ -0,0 +1,102 @@
+Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native
+ > native-issetugid: permit
+ > native-mprotect: permit
+ > native-mmap: permit
+ native-__sysctl: permit native-__sysctl: permit
+ > native-fsread: filename eq "/var/run/ld.so.hints" the
+ > native-fstat: permit
+ native-close: permit native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" the | native-fsread: filename match "/usr/lib/libssl.so.*"
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" th | native-read: permit
+ native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.
+ native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so
+ native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" th
+ native-fsread: filename match "/<non-existent filenam | native-munmap: permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permi | native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then pe native-fsread: filename eq "/etc/malloc.conf" then pe
+ native-fsread: filename eq "/etc/resolv.conf" then pe | native-getpid: permit
+ native-fsread: filename eq "/etc/utmp" then permit <
+ native-fsread: filename eq "/home" then permit <
+ native-fsread: filename eq "$HOME" then permit <
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then <
+ native-fsread: filename eq "$HOME/.lynxrc" then permi <
+ native-fsread: filename eq "$HOME/.mailcap" then perm <
+ native-fsread: filename eq "$HOME/.mime.types" then p <
+ native-fsread: filename eq "$HOME/.terminfo" then per <
+ native-fsread: filename eq "$HOME/.terminfo.db" then <
+ native-fsread: filename eq "/obj" then permit <
+ native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit
+ > native-fswrite: filename match "/tmp/lynx-*" then per
+ native-fsread: filename match "/tmp/lynx-*/." then pe native-fsread: filename match "/tmp/lynx-*/." then pe
+ > native-fsread: filename eq "$HOME" then permit
+ > native-fsread: filename eq "/etc/lynx.cfg" then permi
+ > native-fsread: filename eq "/" then permit
+ > native-fsread: filename eq "/usr/obj/bin/systrace/."
+ > native-fsread: filename eq "/usr/obj/bin" then permit
+ > native-fcntl: permit
+ > native-getdirentries: permit
+ > native-lseek: permit
+ > native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" th <
+ native-fsread: filename match "/usr/lib/libcrypto.so. <
+ native-fsread: filename match "/usr/lib/libncurses.so <
+ native-fsread: filename match "/usr/lib/libssl.so.*" <
+ native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." | native-fsread: filename eq "$HOME/.lynxrc" then permi
+ > native-fsread: filename match "/<non-existent filenam
+ native-fsread: filename eq "/usr/obj/bin/systrace/.ma native-fsread: filename eq "/usr/obj/bin/systrace/.ma
+ > native-fsread: filename eq "$HOME/.mailcap" then perm
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mi native-fsread: filename eq "/usr/obj/bin/systrace/.mi
+ > native-fsread: filename eq "$HOME/.mime.types" then p
+ > native-sigaction: permit
+ > native-ioctl: permit
+ > native-fsread: filename eq "$HOME/.terminfo.db" then
+ > native-fsread: filename eq "$HOME/.terminfo" then per
+ native-fsread: filename eq "/usr/share/misc/terminfo. native-fsread: filename eq "/usr/share/misc/terminfo.
+ > native-pread: permit
+ > native-write: permit
+ > native-fsread: filename eq "$HOME/.lynx-keymaps" then
+ native-fsread: filename eq "/var/run/dev.db" then per native-fsread: filename eq "/var/run/dev.db" then per
+ native-fsread: filename eq "/var/run/ld.so.hints" the | native-fsread: filename eq "/etc/utmp" then permit
+ native-fstat: permit <
+ native-fswrite: filename match "/tmp/lynx-*" then per <
+ native-getdirentries: permit <
+ native-getpid: permit <
+ native-gettimeofday: permit <
+ native-ioctl: permit <
+ native-issetugid: permit <
+ native-lseek: permit <
+ native-mmap: permit <
+ native-mprotect: prot eq "PROT_READ" then permit <
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then p <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then <
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_E <
+ native-munmap: permit <
+ native-nanosleep: permit <
+ native-poll: permit native-poll: permit
+ native-pread: permit | native-nanosleep: permit
+ native-read: permit | native-gettimeofday: permit
+ native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then pe
+ native-select: permit <
+ native-sendto: true then permit <
+ native-sigaction: permit <
+ native-sigprocmask: permit <
+ native-socket: sockdom eq "AF_INET" and socktype eq " native-socket: sockdom eq "AF_INET" and socktype eq "
+ > native-connect: sockaddr eq "inet-[127.0.0.1]:53" the
+ > native-sendto: true then permit
+ > native-select: permit
+ > native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq " native-socket: sockdom eq "AF_INET" and socktype eq "
+ native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" th
+ > native-exit: permit
diff --git a/usr.bin/sdiff/tests/d_tabs1.in b/usr.bin/sdiff/tests/d_tabs1.in
new file mode 100644
index 000000000000..b5a1834a3397
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabs1.in
@@ -0,0 +1,72 @@
+Policy: /usr/bin/lynx, Emulation: native
+ native-__sysctl: permit
+ native-close: permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit
+ native-exit: permit
+ native-fcntl: cmd eq "F_SETFD" then permit
+ native-fsread: filename eq "/" then permit
+ native-fsread: filename match "/<non-existent filename>: *" then permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-fsread: filename eq "/etc/utmp" then permit
+ native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "$HOME" then permit
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
+ native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "$HOME/.mime.types" then permit
+ native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "$HOME/.terminfo.db" then permit
+ native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "/tmp" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" then permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then permit
+ native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
+ native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then permit
+ native-fstat: permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-getdirentries: permit
+ native-getpid: permit
+ native-gettimeofday: permit
+ native-ioctl: permit
+ native-issetugid: permit
+ native-lseek: permit
+ native-mmap: permit
+ native-mprotect: prot eq "PROT_READ" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit
+ native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" then permit
+ native-munmap: permit
+ native-nanosleep: permit
+ native-poll: permit
+ native-pread: permit
+ native-read: permit
+ native-recvfrom: permit
+ native-select: permit
+ native-sendto: true then permit
+ native-sigaction: permit
+ native-sigprocmask: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit
+ native-write: permit
diff --git a/usr.bin/sdiff/tests/d_tabs2.in b/usr.bin/sdiff/tests/d_tabs2.in
new file mode 100644
index 000000000000..d00f4155d23b
--- /dev/null
+++ b/usr.bin/sdiff/tests/d_tabs2.in
@@ -0,0 +1,69 @@
+Policy: /usr/bin/lynx, Emulation: native
+ native-issetugid: permit
+ native-mprotect: permit
+ native-mmap: permit
+ native-__sysctl: permit
+ native-fsread: filename eq "/var/run/ld.so.hints" then permit
+ native-fstat: permit
+ native-close: permit
+ native-fsread: filename match "/usr/lib/libssl.so.*" then permit
+ native-read: permit
+ native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit
+ native-fsread: filename match "/usr/lib/libncurses.so.*" then permit
+ native-fsread: filename match "/usr/lib/libc.so.*" then permit
+ native-munmap: permit
+ native-sigprocmask: permit
+ native-fsread: filename eq "/etc/malloc.conf" then permit
+ native-getpid: permit
+ native-fsread: filename eq "/tmp" then permit
+ native-fswrite: filename match "/tmp/lynx-*" then permit
+ native-fsread: filename match "/tmp/lynx-*/." then permit
+ native-fsread: filename eq "$HOME" then permit
+ native-fsread: filename eq "/etc/lynx.cfg" then permit
+ native-fsread: filename eq "/" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/." then permit
+ native-fsread: filename eq "/usr/obj/bin" then permit
+ native-fcntl: permit
+ native-getdirentries: permit
+ native-lseek: permit
+ native-fsread: filename eq "/usr/obj" then permit
+ native-fsread: filename eq "/usr" then permit
+ native-fsread: filename eq "/usr/bin" then permit
+ native-fsread: filename eq "/usr/games" then permit
+ native-fsread: filename eq "/usr/include" then permit
+ native-fsread: filename eq "/usr/lib" then permit
+ native-fsread: filename eq "/usr/libdata" then permit
+ native-fsread: filename eq "/usr/libexec" then permit
+ native-fsread: filename eq "/usr/lkm" then permit
+ native-fsread: filename eq "/usr/local" then permit
+ native-fsread: filename eq "/usr/mdec" then permit
+ native-fsread: filename eq "/home" then permit
+ native-fsread: filename eq "/obj" then permit
+ native-fsread: filename eq "$HOME/.lynxrc" then permit
+ native-fsread: filename match "/<non-existent filename>: *" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit
+ native-fsread: filename eq "$HOME/.mailcap" then permit
+ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit
+ native-fsread: filename eq "$HOME/.mime.types" then permit
+ native-sigaction: permit
+ native-ioctl: permit
+ native-fsread: filename eq "$HOME/.terminfo.db" then permit
+ native-fsread: filename eq "$HOME/.terminfo" then permit
+ native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit
+ native-pread: permit
+ native-write: permit
+ native-fsread: filename eq "$HOME/.lynx-keymaps" then permit
+ native-fsread: filename eq "/var/run/dev.db" then permit
+ native-fsread: filename eq "/etc/utmp" then permit
+ native-poll: permit
+ native-nanosleep: permit
+ native-gettimeofday: permit
+ native-fsread: filename eq "/etc/resolv.conf" then permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit
+ native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit
+ native-sendto: true then permit
+ native-select: permit
+ native-recvfrom: permit
+ native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit
+ native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit
+ native-exit: permit
diff --git a/usr.bin/sdiff/tests/sdiff_test.sh b/usr.bin/sdiff/tests/sdiff_test.sh
new file mode 100755
index 000000000000..83ed93503f18
--- /dev/null
+++ b/usr.bin/sdiff/tests/sdiff_test.sh
@@ -0,0 +1,242 @@
+# $NetBSD: t_sdiff.sh,v 1.1 2012/03/17 16:33:15 jruoho Exp $
+#
+# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
+# 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.
+#
+# 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.
+#
+
+atf_test_case flags
+flags_head()
+{
+ atf_set "descr" "Checks -l, -s and -w flags"
+}
+flags_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_flags_l.out -s eq:1 \
+ sdiff -l "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2"
+
+ atf_check -o file:$(atf_get_srcdir)/d_flags_s.out -s eq:1 \
+ sdiff -s "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2"
+
+ atf_check -o file:$(atf_get_srcdir)/d_flags_w.out -s eq:1 \
+ sdiff -w 125 "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2"
+}
+
+atf_test_case iflags
+iflags_head()
+{
+ atf_set "descr" "Checks flags -l, -s and -w combined with -I"
+}
+iflags_body()
+{
+ tail1="-w 125 -I .*filename.* $(atf_get_srcdir)/d_input1 $(atf_get_srcdir)/d_input2"
+ tail2="-w 125 -I .*filename.* $(atf_get_srcdir)/d_input2 $(atf_get_srcdir)/d_input1"
+
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_a1.out -s eq:1 sdiff ${tail1}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_a2.out -s eq:1 sdiff ${tail2}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_b1.out -s eq:1 sdiff -s ${tail1}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_b2.out -s eq:1 sdiff -s ${tail2}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_c1.out -s eq:1 sdiff -l ${tail1}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_c2.out -s eq:1 sdiff -l ${tail2}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_d1.out -s eq:1 sdiff -s ${tail1}
+ atf_check -o file:$(atf_get_srcdir)/d_iflags_d2.out -s eq:1 sdiff -s ${tail2}
+}
+
+atf_test_case tabs
+tabs_head()
+{
+ atf_set "descr" "Checks comparing files containing tabs"
+}
+tabs_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_tabs.out -s eq:1 \
+ sdiff "$(atf_get_srcdir)/d_tabs1.in" "$(atf_get_srcdir)/d_tabs2.in"
+}
+
+atf_test_case tabends
+tabends_head()
+{
+ atf_set "descr" "Checks correct handling of lines ended with tabs"
+}
+tabends_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_tabends_a.out -s eq:1 \
+ sdiff -w30 "$(atf_get_srcdir)/d_tabends.in" /dev/null
+
+ atf_check -o file:$(atf_get_srcdir)/d_tabends_b.out -s eq:1 \
+ sdiff -w30 /dev/null "$(atf_get_srcdir)/d_tabends.in"
+
+ atf_check -o file:$(atf_get_srcdir)/d_tabends_c.out -s eq:1 \
+ sdiff -w19 "$(atf_get_srcdir)/d_tabends.in" /dev/null
+}
+
+atf_test_case merge
+merge_head()
+{
+ atf_set "descr" "Checks interactive merging"
+}
+merge_body()
+{
+ merge_tail="-o merge.out $(atf_get_srcdir)/d_input1 \
+$(atf_get_srcdir)/d_input2 >/dev/null ; cat merge.out"
+
+ cp $(atf_get_srcdir)/d_input* .
+
+ atf_check -o file:d_input1 -x "yes l | sdiff ${merge_tail}"
+ atf_check -o file:d_input2 -x "yes r | sdiff ${merge_tail}"
+
+ atf_check -o file:d_input1 -x \
+ "yes el | EDITOR=cat VISUAL=cat sdiff ${merge_tail}"
+ atf_check -o file:d_input2 -x \
+ "yes er | EDITOR=cat VISUAL=cat sdiff ${merge_tail}"
+
+ atf_check -o file:d_input1 -x "yes l | sdiff -s ${merge_tail}"
+ atf_check -o file:d_input2 -x "yes r | sdiff -s ${merge_tail}"
+ atf_check -o file:d_input1 -x "yes l | sdiff -l ${merge_tail}"
+ atf_check -o file:d_input2 -x "yes r | sdiff -l ${merge_tail}"
+ atf_check -o file:d_input1 -x "yes l | sdiff -ls ${merge_tail}"
+ atf_check -o file:d_input2 -x "yes r | sdiff -ls ${merge_tail}"
+
+ atf_check -o file:d_input1 -x "{ while :; do echo s; echo l; \
+echo v; echo l; done; } | sdiff ${merge_tail}"
+
+ atf_check -o file:d_input2 -x "{ while :; do echo s; echo r; \
+echo v; echo r; done; } | sdiff ${merge_tail}"
+}
+
+atf_test_case same
+same_head()
+{
+ atf_set "descr" "Checks comparing file with itself"
+}
+same_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_same.out \
+ sdiff "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input1"
+}
+
+atf_test_case oneline
+oneline_head()
+{
+ atf_set "descr" "Checks comparing one-line files"
+}
+oneline_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_oneline_a.out -s eq:1 \
+ sdiff /dev/null "$(atf_get_srcdir)/d_oneline.in"
+
+ atf_check -o file:$(atf_get_srcdir)/d_oneline_b.out -s eq:1 \
+ sdiff "$(atf_get_srcdir)/d_oneline.in" /dev/null
+}
+
+atf_test_case dot
+dot_head()
+{
+ atf_set "descr" "Checks comparing with file containing only one character"
+}
+dot_body()
+{
+ echo ". <" > expout
+ atf_check -o file:expout -s eq:1 sdiff "$(atf_get_srcdir)/d_dot.in" /dev/null
+
+ echo " > ." > expout
+ atf_check -o file:expout -s eq:1 sdiff /dev/null "$(atf_get_srcdir)/d_dot.in"
+}
+
+atf_test_case stdin
+stdin_head()
+{
+ atf_set "descr" "Checks reading data from stdin"
+}
+stdin_body()
+{
+ echo " > stdin" > expout
+ atf_check -o file:expout -s eq:1 -x \
+ "echo stdin | sdiff /dev/null /dev/stdin"
+
+ echo "stdin <" > expout
+ atf_check -o file:expout -s eq:1 -x \
+ "echo stdin | sdiff /dev/stdin /dev/null"
+}
+
+atf_test_case short
+short_head()
+{
+ atf_set "descr" "Checks premature stop of merging"
+}
+short_body()
+{
+ atf_check -o file:$(atf_get_srcdir)/d_short.out -x \
+ "printf \"r\\nl\\nr\\nl\" | sdiff -o merge.out $(atf_get_srcdir)/d_input1 \
+$(atf_get_srcdir)/d_input2 >/dev/null ; cat merge.out"
+}
+
+atf_test_case tflag
+tflag_head()
+{
+ atf_set "descr" "Checks tab expansion"
+}
+tflag_body()
+{
+ printf "a\tb\n" >a
+ printf "b\ta\n" >b
+ atf_check -s exit:1 -o match:$'a\tb' \
+ sdiff a b
+ atf_check -s exit:1 -o match:"a {7}b" \
+ sdiff -t a b
+ atf_check -s exit:1 -o match:"a {3}b" \
+ sdiff -t --tabsize 4 a b
+}
+
+atf_test_case binary
+binary_head()
+{
+ atf_set "descr" "Checks binary file handling"
+}
+binary_body()
+{
+ printf "a\0\n" >a
+ printf "b\0\n" >b
+ atf_check -o empty sdiff a a
+ atf_check -o empty sdiff a - <a
+ atf_check -s exit:1 -o match:"Binary files .* differ" \
+ sdiff a b
+ atf_check -s exit:1 -o match:"Binary files .* differ" \
+ sdiff a - <b
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case flags
+ atf_add_test_case iflags
+ atf_add_test_case tabs
+ atf_add_test_case tabends
+ atf_add_test_case merge
+ atf_add_test_case same
+ atf_add_test_case oneline
+ atf_add_test_case dot
+ atf_add_test_case stdin
+ atf_add_test_case short
+ atf_add_test_case tflag
+ atf_add_test_case binary
+}
diff --git a/usr.bin/sdiotool/Makefile b/usr.bin/sdiotool/Makefile
new file mode 100644
index 000000000000..42a237b2cd6c
--- /dev/null
+++ b/usr.bin/sdiotool/Makefile
@@ -0,0 +1,7 @@
+PROG= sdiotool
+SRCS= sdiotool.c cam_sdio.c linux_sdio_compat.c
+
+LIBADD= cam util
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sdiotool/brcmfmac_bus.h b/usr.bin/sdiotool/brcmfmac_bus.h
new file mode 100644
index 000000000000..31f53e32bd52
--- /dev/null
+++ b/usr.bin/sdiotool/brcmfmac_bus.h
@@ -0,0 +1,26 @@
+/*-
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* The level of bus communication with the dongle */
+enum brcmf_bus_state {
+ BRCMF_BUS_DOWN, /* Not ready for frame transfers */
+ BRCMF_BUS_UP /* Ready for frame transfers */
+};
+
+struct brcmf_bus {
+ enum brcmf_bus_state state;
+};
diff --git a/usr.bin/sdiotool/brcmfmac_sdio.h b/usr.bin/sdiotool/brcmfmac_sdio.h
new file mode 100644
index 000000000000..ff4e54957d87
--- /dev/null
+++ b/usr.bin/sdiotool/brcmfmac_sdio.h
@@ -0,0 +1,160 @@
+/*-
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#define SDIO_FUNC_0 0
+#define SDIO_FUNC_1 1
+#define SDIO_FUNC_2 2
+
+#define SDIOD_FBR_SIZE 0x100
+
+/* io_en */
+#define SDIO_FUNC_ENABLE_1 0x02
+#define SDIO_FUNC_ENABLE_2 0x04
+
+/* io_rdys */
+#define SDIO_FUNC_READY_1 0x02
+#define SDIO_FUNC_READY_2 0x04
+
+/* intr_status */
+#define INTR_STATUS_FUNC1 0x2
+#define INTR_STATUS_FUNC2 0x4
+
+/* Maximum number of I/O funcs */
+#define SDIOD_MAX_IOFUNCS 7
+
+/* mask of register map */
+#define REG_F0_REG_MASK 0x7FF
+#define REG_F1_MISC_MASK 0x1FFFF
+
+/* as of sdiod rev 0, supports 3 functions */
+#define SBSDIO_NUM_FUNCTION 3
+
+/* function 0 vendor specific CCCR registers */
+#define SDIO_CCCR_BRCM_CARDCAP 0xf0
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
+#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
+#define SDIO_CCCR_BRCM_SEPINT 0xf2
+
+#define SDIO_SEPINT_MASK 0x01
+#define SDIO_SEPINT_OE 0x02
+#define SDIO_SEPINT_ACT_HI 0x04
+
+/* function 1 miscellaneous registers */
+
+/* sprom command and status */
+#define SBSDIO_SPROM_CS 0x10000
+/* sprom info register */
+#define SBSDIO_SPROM_INFO 0x10001
+/* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_LOW 0x10002
+/* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_DATA_HIGH 0x10003
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_LOW 0x10004
+/* gpio select */
+#define SBSDIO_GPIO_SELECT 0x10005
+/* gpio output */
+#define SBSDIO_GPIO_OUT 0x10006
+/* gpio enable */
+#define SBSDIO_GPIO_EN 0x10007
+/* rev < 7, watermark for sdio device */
+#define SBSDIO_WATERMARK 0x10008
+/* control busy signal generation */
+#define SBSDIO_DEVICE_CTL 0x10009
+
+/* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRLOW 0x1000A
+/* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRMID 0x1000B
+/* SB Address Window High (b31:b24) */
+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C
+/* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_FRAMECTRL 0x1000D
+/* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E
+/* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F
+/* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019
+/* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A
+/* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
+/* Read Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
+/* MesBusyCtl (rev 11) */
+#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
+/* Sdio Core Rev 12 */
+#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
+#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
+
+#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
+
+/* function 1 OCP space */
+
+/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF
+#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000
+/* with b15, maps to 32-bit SB access */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
+
+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+
+#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
+#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
+#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
+/* Address bits from SBADDR regs */
+#define SBSDIO_SBWINDOW_MASK 0xffff8000
+
+#define SDIOH_READ 0 /* Read request */
+#define SDIOH_WRITE 1 /* Write request */
+
+#define SDIOH_DATA_FIX 0 /* Fixed addressing */
+#define SDIOH_DATA_INC 1 /* Incremental addressing */
+
+/* internal return code */
+#define SUCCESS 0
+#define ERROR 1
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#define BRCMF_SDALIGN (1 << 6)
+
+/**
+ * enum brcmf_sdiod_state - the state of the bus.
+ *
+ * @BRCMF_SDIOD_DOWN: Device can be accessed, no DPC.
+ * @BRCMF_SDIOD_DATA: Ready for data transfers, DPC enabled.
+ * @BRCMF_SDIOD_NOMEDIUM: No medium access to dongle possible.
+ */
+enum brcmf_sdiod_state {
+ BRCMF_SDIOD_DOWN,
+ BRCMF_SDIOD_DATA,
+ BRCMF_SDIOD_NOMEDIUM
+};
diff --git a/usr.bin/sdiotool/cam_sdio.c b/usr.bin/sdiotool/cam_sdio.c
new file mode 100644
index 000000000000..0cd8eeb0485a
--- /dev/null
+++ b/usr.bin/sdiotool/cam_sdio.c
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include "cam_sdio.h"
+
+/* Use CMD52 to read or write a single byte */
+int
+sdio_rw_direct(struct cam_device *dev,
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_write,
+ uint8_t *data, uint8_t *resp) {
+ union ccb *ccb;
+ uint32_t flags;
+ uint32_t arg;
+ int retval = 0;
+
+ ccb = cam_getccb(dev);
+ if (ccb == NULL) {
+ warnx("%s: error allocating CCB", __func__);
+ return (-1);
+ }
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(union ccb) - sizeof(struct ccb_hdr));
+
+ flags = MMC_RSP_R5 | MMC_CMD_AC;
+ arg = SD_IO_RW_FUNC(func_number) | SD_IO_RW_ADR(addr);
+ if (is_write)
+ arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(*data);
+
+ cam_fill_mmcio(&ccb->mmcio,
+ /*retries*/ 0,
+ /*cbfcnp*/ NULL,
+ /*flags*/ CAM_DIR_NONE,
+ /*mmc_opcode*/ SD_IO_RW_DIRECT,
+ /*mmc_arg*/ arg,
+ /*mmc_flags*/ flags,
+ /*mmc_data*/ 0,
+ /*timeout*/ 5000);
+
+ if (((retval = cam_send_ccb(dev, ccb)) < 0)
+ || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
+ const char warnstr[] = "error sending command";
+
+ if (retval < 0)
+ warn(warnstr);
+ else
+ warnx(warnstr);
+ return (-1);
+ }
+
+ *resp = ccb->mmcio.cmd.resp[0] & 0xFF;
+ cam_freeccb(ccb);
+ return (retval);
+}
+
+/*
+ * CMD53 -- IO_RW_EXTENDED
+ * Use to read or write memory blocks
+ *
+ * is_increment=1: FIFO mode
+ * blk_count > 0: block mode
+ */
+int
+sdio_rw_extended(struct cam_device *dev,
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_write,
+ caddr_t data, size_t datalen,
+ uint8_t is_increment,
+ uint16_t blk_count) {
+ union ccb *ccb;
+ uint32_t flags;
+ uint32_t arg;
+ uint32_t cam_flags;
+ uint8_t resp;
+ struct mmc_data mmcd;
+ int retval = 0;
+
+ if (blk_count != 0) {
+ warnx("%s: block mode is not supported yet", __func__);
+ return (-1);
+ }
+
+ ccb = cam_getccb(dev);
+ if (ccb == NULL) {
+ warnx("%s: error allocating CCB", __func__);
+ return (-1);
+ }
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(union ccb) - sizeof(struct ccb_hdr));
+
+ flags = MMC_RSP_R5 | MMC_CMD_ADTC;
+ arg = SD_IO_RW_FUNC(func_number) | SD_IO_RW_ADR(addr) |
+ SD_IOE_RW_LEN(datalen);
+
+ if (is_increment)
+ arg |= SD_IO_RW_INCR;
+
+ mmcd.data = data;
+ mmcd.len = datalen;
+ mmcd.xfer_len = 0; /* not used by MMCCAM */
+ mmcd.mrq = NULL; /* not used by MMCCAM */
+
+ if (is_write) {
+ arg |= SD_IO_RW_WR;
+ cam_flags = CAM_DIR_OUT;
+ mmcd.flags = MMC_DATA_WRITE;
+ } else {
+ cam_flags = CAM_DIR_IN;
+ mmcd.flags = MMC_DATA_READ;
+ }
+ cam_fill_mmcio(&ccb->mmcio,
+ /*retries*/ 0,
+ /*cbfcnp*/ NULL,
+ /*flags*/ cam_flags,
+ /*mmc_opcode*/ SD_IO_RW_EXTENDED,
+ /*mmc_arg*/ arg,
+ /*mmc_flags*/ flags,
+ /*mmc_data*/ &mmcd,
+ /*timeout*/ 5000);
+
+ if (((retval = cam_send_ccb(dev, ccb)) < 0)
+ || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
+ const char warnstr[] = "error sending command";
+
+ if (retval < 0)
+ warn(warnstr);
+ else
+ warnx(warnstr);
+ return (-1);
+ }
+
+ resp = ccb->mmcio.cmd.resp[0] & 0xFF;
+ if (resp != 0)
+ warn("Response from CMD53 is not 0?!");
+ cam_freeccb(ccb);
+ return (retval);
+}
+
+
+int
+sdio_read_bool_for_func(struct cam_device *dev, uint32_t addr, uint8_t func_number, uint8_t *is_enab) {
+ uint8_t resp;
+ int ret;
+
+ ret = sdio_rw_direct(dev, 0, addr, 0, NULL, &resp);
+ if (ret < 0)
+ return ret;
+
+ *is_enab = (resp & (1 << func_number)) > 0 ? 1 : 0;
+
+ return (0);
+}
+
+int
+sdio_set_bool_for_func(struct cam_device *dev, uint32_t addr, uint8_t func_number, int enable) {
+ uint8_t resp;
+ int ret;
+ uint8_t is_enabled;
+
+ ret = sdio_rw_direct(dev, 0, addr, 0, NULL, &resp);
+ if (ret != 0)
+ return ret;
+
+ is_enabled = resp & (1 << func_number);
+ if ((is_enabled !=0 && enable == 1) || (is_enabled == 0 && enable == 0))
+ return 0;
+
+ if (enable)
+ resp |= 1 << func_number;
+ else
+ resp &= ~ (1 << func_number);
+
+ ret = sdio_rw_direct(dev, 0, addr, 1, &resp, &resp);
+
+ return ret;
+}
+
+/* Conventional I/O functions */
+uint8_t
+sdio_read_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret) {
+ uint8_t val;
+ *ret = sdio_rw_direct(dev, func_number, addr, 0, NULL, &val);
+ return val;
+}
+
+int
+sdio_write_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint8_t val) {
+ uint8_t _val;
+ return sdio_rw_direct(dev, func_number, addr, 0, &val, &_val);
+}
+
+uint16_t
+sdio_read_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret) {
+ uint16_t val;
+ *ret = sdio_rw_extended(dev, func_number, addr,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* datalen */ sizeof(val),
+ /* is_increment */ 1,
+ /* blk_count */ 0
+ );
+ return val;
+}
+
+
+int
+sdio_write_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint16_t val) {
+ return sdio_rw_extended(dev, func_number, addr,
+ /* is_write */ 1,
+ /* data */ (caddr_t) &val,
+ /* datalen */ sizeof(val),
+ /* is_increment */ 1,
+ /* blk_count */ 0
+ );
+}
+
+uint32_t
+sdio_read_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret) {
+ uint32_t val;
+ *ret = sdio_rw_extended(dev, func_number, addr,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* datalen */ sizeof(val),
+ /* is_increment */ 1,
+ /* blk_count */ 0
+ );
+ return val;
+}
+
+
+int
+sdio_write_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint32_t val) {
+ return sdio_rw_extended(dev, func_number, addr,
+ /* is_write */ 1,
+ /* data */ (caddr_t) &val,
+ /* datalen */ sizeof(val),
+ /* is_increment */ 1,
+ /* blk_count */ 0
+ );
+}
+
+/* Higher-level wrappers for certain management operations */
+int
+sdio_is_func_ready(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab) {
+ return sdio_read_bool_for_func(dev, SD_IO_CCCR_FN_READY, func_number, is_enab);
+}
+
+int
+sdio_is_func_enabled(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab) {
+ return sdio_read_bool_for_func(dev, SD_IO_CCCR_FN_ENABLE, func_number, is_enab);
+}
+
+int
+sdio_func_enable(struct cam_device *dev, uint8_t func_number, int enable) {
+ return sdio_set_bool_for_func(dev, SD_IO_CCCR_FN_ENABLE, func_number, enable);
+}
+
+int
+sdio_is_func_intr_enabled(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab) {
+ return sdio_read_bool_for_func(dev, SD_IO_CCCR_INT_ENABLE, func_number, is_enab);
+}
+
+int
+sdio_func_intr_enable(struct cam_device *dev, uint8_t func_number, int enable) {
+ return sdio_set_bool_for_func(dev, SD_IO_CCCR_INT_ENABLE, func_number, enable);
+}
+
+int
+sdio_card_set_bus_width(struct cam_device *dev, enum mmc_bus_width bw) {
+ int ret;
+ uint8_t ctl_val;
+ ret = sdio_rw_direct(dev, 0, SD_IO_CCCR_BUS_WIDTH, 0, NULL, &ctl_val);
+ if (ret < 0) {
+ warn("Error getting CCCR_BUS_WIDTH value");
+ return ret;
+ }
+ ctl_val &= ~0x3;
+ switch (bw) {
+ case bus_width_1:
+ /* Already set to 1-bit */
+ break;
+ case bus_width_4:
+ ctl_val |= CCCR_BUS_WIDTH_4;
+ break;
+ case bus_width_8:
+ warn("Cannot do 8-bit on SDIO yet");
+ return -1;
+ break;
+ }
+ ret = sdio_rw_direct(dev, 0, SD_IO_CCCR_BUS_WIDTH, 1, &ctl_val, &ctl_val);
+ if (ret < 0) {
+ warn("Error setting CCCR_BUS_WIDTH value");
+ return ret;
+ }
+ return ret;
+}
+
+int
+sdio_func_read_cis(struct cam_device *dev, uint8_t func_number,
+ uint32_t cis_addr, struct cis_info *info) {
+ uint8_t tuple_id, tuple_len, tuple_count;
+ uint32_t addr;
+
+ char *cis1_info[4];
+ int start, i, ch, count, ret;
+ char cis1_info_buf[256];
+
+ tuple_count = 0; /* Use to prevent infinite loop in case of parse errors */
+ memset(cis1_info_buf, 0, 256);
+ do {
+ addr = cis_addr;
+ tuple_id = sdio_read_1(dev, 0, addr++, &ret);
+ if (tuple_id == SD_IO_CISTPL_END)
+ break;
+ if (tuple_id == 0) {
+ cis_addr++;
+ continue;
+ }
+ tuple_len = sdio_read_1(dev, 0, addr++, &ret);
+ if (tuple_len == 0 && tuple_id != 0x00) {
+ warn("Parse error: 0-length tuple %02X\n", tuple_id);
+ return -1;
+ }
+
+ switch (tuple_id) {
+ case SD_IO_CISTPL_VERS_1:
+ addr += 2;
+ for (count = 0, start = 0, i = 0;
+ (count < 4) && ((i + 4) < 256); i++) {
+ ch = sdio_read_1(dev, 0, addr + i, &ret);
+ printf("count=%d, start=%d, i=%d, Got %c (0x%02x)\n", count, start, i, ch, ch);
+ if (ch == 0xff)
+ break;
+ cis1_info_buf[i] = ch;
+ if (ch == 0) {
+ cis1_info[count] =
+ cis1_info_buf + start;
+ start = i + 1;
+ count++;
+ }
+ }
+ printf("Card info:");
+ for (i=0; i<4; i++)
+ if (cis1_info[i])
+ printf(" %s", cis1_info[i]);
+ printf("\n");
+ break;
+ case SD_IO_CISTPL_MANFID:
+ info->man_id = sdio_read_1(dev, 0, addr++, &ret);
+ info->man_id |= sdio_read_1(dev, 0, addr++, &ret) << 8;
+
+ info->prod_id = sdio_read_1(dev, 0, addr++, &ret);
+ info->prod_id |= sdio_read_1(dev, 0, addr++, &ret) << 8;
+ break;
+ case SD_IO_CISTPL_FUNCID:
+ /* not sure if we need to parse it? */
+ break;
+ case SD_IO_CISTPL_FUNCE:
+ if (tuple_len < 4) {
+ printf("FUNCE is too short: %d\n", tuple_len);
+ break;
+ }
+ if (func_number == 0) {
+ /* skip extended_data */
+ addr++;
+ info->max_block_size = sdio_read_1(dev, 0, addr++, &ret);
+ info->max_block_size |= sdio_read_1(dev, 0, addr++, &ret) << 8;
+ } else {
+ info->max_block_size = sdio_read_1(dev, 0, addr + 0xC, &ret);
+ info->max_block_size |= sdio_read_1(dev, 0, addr + 0xD, &ret) << 8;
+ }
+ break;
+ default:
+ warnx("Skipping tuple ID %02X len %02X\n", tuple_id, tuple_len);
+ }
+ cis_addr += tuple_len + 2;
+ tuple_count++;
+ } while (tuple_count < 20);
+
+ return 0;
+}
+
+uint32_t
+sdio_get_common_cis_addr(struct cam_device *dev) {
+ uint32_t addr;
+ int ret;
+
+ addr = sdio_read_1(dev, 0, SD_IO_CCCR_CISPTR, &ret);
+ addr |= sdio_read_1(dev, 0, SD_IO_CCCR_CISPTR + 1, &ret) << 8;
+ addr |= sdio_read_1(dev, 0, SD_IO_CCCR_CISPTR + 2, &ret) << 16;
+
+ if (addr < SD_IO_CIS_START || addr > SD_IO_CIS_START + SD_IO_CIS_SIZE) {
+ warn("Bad CIS address: %04X\n", addr);
+ addr = 0;
+ }
+
+ return addr;
+}
+
+void sdio_card_reset(struct cam_device *dev) {
+ int ret;
+ uint8_t ctl_val;
+ ret = sdio_rw_direct(dev, 0, SD_IO_CCCR_CTL, 0, NULL, &ctl_val);
+ if (ret < 0)
+ errx(1, "Error getting CCCR_CTL value");
+ ctl_val |= CCCR_CTL_RES;
+ ret = sdio_rw_direct(dev, 0, SD_IO_CCCR_CTL, 1, &ctl_val, &ctl_val);
+ if (ret < 0)
+ errx(1, "Error setting CCCR_CTL value");
+}
diff --git a/usr.bin/sdiotool/cam_sdio.h b/usr.bin/sdiotool/cam_sdio.h
new file mode 100644
index 000000000000..10d668951bfe
--- /dev/null
+++ b/usr.bin/sdiotool/cam_sdio.h
@@ -0,0 +1,93 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <err.h>
+#include <libutil.h>
+#include <unistd.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/mmc/mmc_all.h>
+#include <camlib.h>
+
+struct cis_info {
+ uint16_t man_id;
+ uint16_t prod_id;
+ uint16_t max_block_size;
+};
+
+int sdio_rw_direct(struct cam_device *dev,
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_write,
+ uint8_t *data,
+ uint8_t *resp);
+int
+sdio_rw_extended(struct cam_device *dev,
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_write,
+ caddr_t data, size_t datalen,
+ uint8_t is_increment,
+ uint16_t blk_count);
+uint8_t sdio_read_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret);
+int sdio_write_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint8_t val);
+uint16_t sdio_read_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret);
+int sdio_write_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint16_t val);
+uint32_t sdio_read_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret);
+int sdio_write_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint32_t val);
+int sdio_read_bool_for_func(struct cam_device *dev, uint32_t addr, uint8_t func_number, uint8_t *is_enab);
+int sdio_set_bool_for_func(struct cam_device *dev, uint32_t addr, uint8_t func_number, int enable);
+int sdio_is_func_ready(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab);
+int sdio_is_func_enabled(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab);
+int sdio_func_enable(struct cam_device *dev, uint8_t func_number, int enable);
+int sdio_is_func_intr_enabled(struct cam_device *dev, uint8_t func_number, uint8_t *is_enab);
+int sdio_func_intr_enable(struct cam_device *dev, uint8_t func_number, int enable);
+void sdio_card_reset(struct cam_device *dev);
+uint32_t sdio_get_common_cis_addr(struct cam_device *dev);
+int sdio_func_read_cis(struct cam_device *dev, uint8_t func_number,
+ uint32_t cis_addr, struct cis_info *info);
+int sdio_card_set_bus_width(struct cam_device *dev, enum mmc_bus_width bw);
diff --git a/usr.bin/sdiotool/linux_compat.h b/usr.bin/sdiotool/linux_compat.h
new file mode 100644
index 000000000000..58611fe52242
--- /dev/null
+++ b/usr.bin/sdiotool/linux_compat.h
@@ -0,0 +1,56 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2016-2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#ifndef _LINUX_COMPAT_H_
+#define _LINUX_COMPAT_H_
+
+/* Linux compatibility shims */
+#define uint unsigned int
+#define u32 uint32_t
+#define u8 uint8_t
+#define u16 uint16_t
+#define s32 int32_t
+#define bool int8_t
+#define true 1
+#define false 0
+
+#define usleep_range(a, b) usleep(a)
+#define ENOMEDIUM -1
+#define EINVAL -2
+
+#define WARN_ON(cond) ({ \
+ bool __ret = (cond); \
+ if (__ret) { \
+ printf("WARNING %s failed at %s:%d\n", \
+ #cond, __FILE__, __LINE__); \
+ } \
+ (__ret); \
+})
+
+#endif
diff --git a/usr.bin/sdiotool/linux_sdio_compat.c b/usr.bin/sdiotool/linux_sdio_compat.c
new file mode 100644
index 000000000000..7d89bff01dcf
--- /dev/null
+++ b/usr.bin/sdiotool/linux_sdio_compat.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2016-2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <err.h>
+#include <libutil.h>
+#include <unistd.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/mmc/mmc_all.h>
+#include <camlib.h>
+
+#include "linux_compat.h"
+#include "linux_sdio_compat.h"
+#include "cam_sdio.h"
+
+u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret) {
+ return sdio_read_1(func->dev, func->num, addr, err_ret);
+}
+
+unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr, int *err_ret) {
+ return sdio_readb(func, addr, err_ret);
+}
+
+u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret) {
+ return sdio_read_2(func->dev, func->num, addr, err_ret);
+}
+
+u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret) {
+ return sdio_read_4(func->dev, func->num, addr, err_ret);
+}
+
+void sdio_writeb(struct sdio_func *func, u8 b,
+ unsigned int addr, int *err_ret) {
+ *err_ret = sdio_write_1(func->dev, func->num, addr, b);
+}
+
+/* Only writes to the vendor specific CCCR registers
+ * (0xF0 - 0xFF) are permiited. */
+void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
+ unsigned int addr, int *err_ret)
+{
+ if (addr < 0xF0 || addr > 0xFF) {
+ if (err_ret)
+ *err_ret = -EINVAL;
+ return;
+ }
+ sdio_writeb(func, b, addr, err_ret);
+}
+
+void sdio_writew(struct sdio_func *func, u16 b,
+ unsigned int addr, int *err_ret) {
+ *err_ret = sdio_write_2(func->dev, func->num, addr, b);
+}
+
+void sdio_writel(struct sdio_func *func, u32 b,
+ unsigned int addr, int *err_ret) {
+ *err_ret = sdio_write_4(func->dev, func->num, addr, b);
+}
diff --git a/usr.bin/sdiotool/linux_sdio_compat.h b/usr.bin/sdiotool/linux_sdio_compat.h
new file mode 100644
index 000000000000..2b56a74d624f
--- /dev/null
+++ b/usr.bin/sdiotool/linux_sdio_compat.h
@@ -0,0 +1,61 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#ifndef _LINUX_SDIO_COMPAT_H_
+#define _LINUX_SDIO_COMPAT_H_
+
+#include <sys/types.h>
+#include "linux_compat.h"
+
+/* Linux SDIO stack functions and definitions */
+#define SDIO_CCCR_ABORT SD_IO_CCCR_CTL
+#define SDIO_CCCR_IENx SD_IO_CCCR_INT_ENABLE
+
+struct sdio_func {
+ struct cam_device *dev;
+ uint8_t num;
+};
+
+u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret);
+unsigned char sdio_f0_readb(struct sdio_func *func,
+ unsigned int addr, int *err_ret);
+u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret);
+u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret);
+
+void sdio_writeb(struct sdio_func *func, u8 b,
+ unsigned int addr, int *err_ret);
+void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
+ unsigned int addr, int *err_ret);
+void sdio_writew(struct sdio_func *func, u16 b,
+ unsigned int addr, int *err_ret);
+void sdio_writel(struct sdio_func *func, u32 b,
+ unsigned int addr, int *err_ret);
+
+
+#endif
diff --git a/usr.bin/sdiotool/sdiotool.c b/usr.bin/sdiotool/sdiotool.c
new file mode 100644
index 000000000000..448fe830f7dd
--- /dev/null
+++ b/usr.bin/sdiotool/sdiotool.c
@@ -0,0 +1,552 @@
+/*-
+ * Copyright (c) 2016-2017 Ilya Bakulin
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <err.h>
+#include <libutil.h>
+#include <unistd.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/mmc/mmc_all.h>
+#include <camlib.h>
+
+#include "linux_compat.h"
+#include "linux_sdio_compat.h"
+#include "cam_sdio.h"
+#include "brcmfmac_sdio.h"
+#include "brcmfmac_bus.h"
+
+static void probe_bcrm(struct cam_device *dev);
+
+/*
+ * How Linux driver works
+ *
+ * The probing begins by calling brcmf_ops_sdio_probe() which is defined as probe function in struct sdio_driver. http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c#L1126
+ *
+ * The driver does black magic by copying func struct for F2 and setting func number to zero there, to create an F0 func structure :)
+ * Driver state changes to BRCMF_SDIOD_DOWN.
+ * ops_sdio_probe() then calls brcmf_sdio_probe() -- at this point it has filled in sdiodev struct with the pointers to all three functions (F0, F1, F2).
+ *
+ * brcmf_sdiod_probe() sets block sizes for F1 and F2. It sets F1 block size to 64 and F2 to 512, not consulting the values stored in SDIO CCCR / FBR registers!
+ * Then it increases timeout for F2 (what is this?!)
+ * Then it enables F1
+ * Then it attaches "freezer" (without PM this is NOP)
+ * Finally it calls brcmf_sdio_probe() http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c#L4082
+ *
+ * Here high-level workqueues and sg tables are allocated.
+ * It then calls brcmf_sdio_probe_attach()
+ *
+ * Here at the beginning there is a pr_debug() call with brcmf_sdiod_regrl() inside to addr #define SI_ENUM_BASE 0x18000000.
+ * Return value is 0x16044330.
+ * Then turns off PLL: byte-write BRCMF_INIT_CLKCTL1 (0x28) -> SBSDIO_FUNC1_CHIPCLKCSR (0x1000E)
+ * Then it reads value back, should be 0xe8.
+ * Then calls brcmf_chip_attach()
+ *
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c#L1054
+ * This func enumerates and resets all the cores on the dongle.
+ * - brcmf_sdio_buscoreprep(): force clock to ALPAvail req only:
+ * SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ -> SBSDIO_FUNC1_CHIPCLKCSR
+ * Wait up to 15ms to !SBSDIO_ALPAV(clkval) of the value from CLKCSR.
+ * Force ALP:
+ * SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP (0x21)-> SBSDIO_FUNC1_CHIPCLKCSR
+ * Disaable SDIO pullups:
+ * byte 0 -> SBSDIO_FUNC1_SDIOPULLUP (0x0001000f)
+ *
+ * Calls brcmf_chip_recognition()
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c#L908
+ * Read 0x18000000. Get 0x16044330: chip 4330 rev 4
+ * AXI chip, call brcmf_chip_dmp_erom_scan() to get info about all cores.
+ * Then brcmf_chip_cores_check() to check that CPU and RAM are found,
+ *
+ * Setting cores to passive: not clear which of CR4/CA7/CM3 our chip has.
+ * Quite a few r/w calls to different parts of the chip to reset cores....
+ * Finally get_raminfo() called to fill in RAM info:
+ * brcmf_chip_get_raminfo: RAM: base=0x0 size=294912 (0x48000) sr=0 (0x0)
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c#L700
+ *
+ * Then brcmf_chip_setup() is called, this prints and fills in chipcommon rev and PMU caps:
+ * brcmf_chip_setup: ccrev=39, pmurev=12, pmucaps=0x19583c0c
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c#L1015
+ * Bus-specific setup code is NOP for SDIO.
+ *
+ * brcmf_sdio_kso_init() is called.
+ * Here it first reads 0x1 from SBSDIO_FUNC1_SLEEPCSR 0x18000650 and then writes it back... WTF?
+ *
+ * brcmf_sdio_drivestrengthinit() is called
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c#L3630
+ *
+ * Set card control so an SDIO card reset does a WLAN backplane reset
+ * set PMUControl so a backplane reset does PMU state reload
+ * === end of brcmf_sdio_probe_attach ===
+
+ **** Finished reading at http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c#L4152, line 2025 in the dump
+
+ * === How register reading works ===
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c#L357
+ * The address to read from is written to three byte-sized registers of F1:
+ * - SBSDIO_FUNC1_SBADDRLOW 0x1000A
+ * - SBSDIO_FUNC1_SBADDRMID 0x1000B
+ * - SBSDIO_FUNC1_SBADDRHIGH 0x1000C
+ * If this is 32-bit read , a flag is set. The address is ANDed with SBSDIO_SB_OFT_ADDR_MASK which is 0x07FFF.
+ * Then brcmf_sdiod_regrw_helper() is called to read the reply.
+ * http://lxr.free-electrons.com/source/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c#L306
+ * Based on the address it figures out where to read it from (CCCR / FBR in F0, or somewhere in F1).
+ * Reads are retried three times.
+ * 1-byte IO is done with CMD52, more is read with CMD53 with address increment (not FIFO mode).
+ * http://lxr.free-electrons.com/source/drivers/mmc/core/sdio_io.c#L458
+ * ==================================
+ *
+ *
+ */
+
+/* BRCM-specific functions */
+#define SDIOH_API_ACCESS_RETRY_LIMIT 2
+#define SI_ENUM_BASE 0x18000000
+#define REPLY_MAGIC 0x16044330
+#define brcmf_err(fmt, ...) brcmf_dbg(0, fmt, ##__VA_ARGS__)
+#define brcmf_dbg(level, fmt, ...) printf(fmt, ##__VA_ARGS__)
+
+struct brcmf_sdio_dev {
+ struct cam_device *cam_dev;
+ u32 sbwad; /* Save backplane window address */
+ struct brcmf_bus *bus_if;
+ enum brcmf_sdiod_state state;
+ struct sdio_func *func[8];
+};
+
+void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
+void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+ enum brcmf_sdiod_state state);
+static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, u32 addr,
+ u8 regsz, void *data, bool write);
+static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address);
+static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr);
+u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+
+static void bailout(int ret);
+
+static void
+bailout(int ret) {
+ if (ret == 0)
+ return;
+ errx(1, "Operation returned error %d", ret);
+}
+
+void
+brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state)
+{
+ bus->state = state;
+}
+
+void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+ enum brcmf_sdiod_state state)
+{
+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM ||
+ state == sdiodev->state)
+ return;
+
+ //brcmf_dbg(TRACE, "%d -> %d\n", sdiodev->state, state);
+ switch (sdiodev->state) {
+ case BRCMF_SDIOD_DATA:
+ /* any other state means bus interface is down */
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
+ break;
+ case BRCMF_SDIOD_DOWN:
+ /* transition from DOWN to DATA means bus interface is up */
+ if (state == BRCMF_SDIOD_DATA)
+ brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_UP);
+ break;
+ default:
+ break;
+ }
+ sdiodev->state = state;
+}
+
+static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func,
+ uint regaddr, u8 byte) {
+ int err_ret;
+
+ /*
+ * Can only directly write to some F0 registers.
+ * Handle CCCR_IENx and CCCR_ABORT command
+ * as a special case.
+ */
+ if ((regaddr == SDIO_CCCR_ABORT) ||
+ (regaddr == SDIO_CCCR_IENx))
+ sdio_writeb(func, byte, regaddr, &err_ret);
+ else
+ sdio_f0_writeb(func, byte, regaddr, &err_ret);
+
+ return err_ret;
+}
+
+static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn, u32 addr, u8 regsz, void *data, bool write)
+{
+ struct sdio_func *func;
+ int ret = -EINVAL;
+
+ brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+ write, fn, addr, regsz);
+
+ /* only allow byte access on F0 */
+ if (WARN_ON(regsz > 1 && !fn))
+ return -EINVAL;
+ func = sdiodev->func[fn];
+
+ switch (regsz) {
+ case sizeof(u8):
+ if (write) {
+ if (fn)
+ sdio_writeb(func, *(u8 *)data, addr, &ret);
+ else
+ ret = brcmf_sdiod_f0_writeb(func, addr,
+ *(u8 *)data);
+ } else {
+ if (fn)
+ *(u8 *)data = sdio_readb(func, addr, &ret);
+ else
+ *(u8 *)data = sdio_f0_readb(func, addr, &ret);
+ }
+ break;
+ case sizeof(u16):
+ if (write)
+ sdio_writew(func, *(u16 *)data, addr, &ret);
+ else
+ *(u16 *)data = sdio_readw(func, addr, &ret);
+ break;
+ case sizeof(u32):
+ if (write)
+ sdio_writel(func, *(u32 *)data, addr, &ret);
+ else
+ *(u32 *)data = sdio_readl(func, addr, &ret);
+ break;
+ default:
+ brcmf_err("invalid size: %d\n", regsz);
+ break;
+ }
+
+ if (ret)
+ brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
+ write ? "write" : "read", fn, addr, ret);
+
+ return ret;
+}
+
+static int
+brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
+{
+ uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+ int err = 0;
+
+ if (bar0 != sdiodev->sbwad) {
+ err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
+ if (err)
+ return err;
+
+ sdiodev->sbwad = bar0;
+ }
+
+ *addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ if (width == 4)
+ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ return 0;
+}
+
+static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 regsz, void *data, bool write) {
+ u8 func;
+ s32 retry = 0;
+ int ret;
+
+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
+ return -ENOMEDIUM;
+
+ /*
+ * figure out how to read the register based on address range
+ * 0x00 ~ 0x7FF: function 0 CCCR and FBR
+ * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
+ * The rest: function 1 silicon backplane core registers
+ */
+ if ((addr & ~REG_F0_REG_MASK) == 0)
+ func = SDIO_FUNC_0;
+ else
+ func = SDIO_FUNC_1;
+
+ do {
+ if (!write)
+ memset(data, 0, regsz);
+ /* for retry wait for 1 ms till bus get settled down */
+ if (retry)
+ usleep_range(1000, 2000);
+ ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
+ data, write);
+ } while (ret != 0 && ret != -ENOMEDIUM &&
+ retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
+
+ if (ret == -ENOMEDIUM)
+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+ else if (ret != 0) {
+ /*
+ * SleepCSR register access can fail when
+ * waking up the device so reduce this noise
+ * in the logs.
+ */
+ if (addr != SBSDIO_FUNC1_SLEEPCSR)
+ brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
+ write ? "write" : "read", func, addr, ret);
+ else
+ brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
+ write ? "write" : "read", func, addr, ret);
+ }
+ return ret;
+}
+
+static int
+brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
+{
+ int err = 0, i;
+ u8 addr[3];
+
+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
+ return -ENOMEDIUM;
+
+ addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
+ addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
+ addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
+
+ for (i = 0; i < 3; i++) {
+ err = brcmf_sdiod_regrw_helper(sdiodev,
+ SBSDIO_FUNC1_SBADDRLOW + i,
+ sizeof(u8), &addr[i], true);
+ if (err) {
+ brcmf_err("failed at addr: 0x%0x\n",
+ SBSDIO_FUNC1_SBADDRLOW + i);
+ break;
+ }
+ }
+
+ return err;
+}
+
+u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+{
+ u32 data = 0;
+ int retval;
+
+ brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
+ retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
+ if (retval)
+ goto done;
+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
+ false);
+ brcmf_dbg(SDIO, "data:0x%08x\n", data);
+
+done:
+ if (ret)
+ *ret = retval;
+
+ return data;
+}
+
+/********************************************************/
+__unused
+static void
+probe_bcrm(struct cam_device *dev) {
+ uint32_t cis_addr;
+ struct cis_info info;
+
+ sdio_card_set_bus_width(dev, bus_width_4);
+ cis_addr = sdio_get_common_cis_addr(dev);
+ printf("CIS address: %04X\n", cis_addr);
+
+ memset(&info, 0, sizeof(info));
+ sdio_func_read_cis(dev, 0, cis_addr, &info);
+ printf("Vendor 0x%04X product 0x%04X\n", info.man_id, info.prod_id);
+}
+
+__unused static uint8_t*
+mmap_fw() {
+ const char fw_path[] = "/home/kibab/repos/fbsd-bbb/brcm-firmware/brcmfmac4330-sdio.bin";
+ struct stat sb;
+ uint8_t *fw_ptr;
+
+ int fd = open(fw_path, O_RDONLY);
+ if (fd < 0)
+ errx(1, "Cannot open firmware file");
+ if (fstat(fd, &sb) < 0)
+ errx(1, "Cannot get file stat");
+ fw_ptr = mmap(NULL, sb.st_size, PROT_READ, 0, fd, 0);
+ if (fw_ptr == MAP_FAILED)
+ errx(1, "Cannot map the file");
+
+ return fw_ptr;
+}
+
+static void
+usage() {
+ printf("sdiotool -u <pass_dev_unit>\n");
+ exit(0);
+}
+
+struct card_info {
+ uint8_t num_funcs;
+ struct cis_info f[8];
+};
+
+/*
+ * TODO: We should add SDIO card info about at least number of
+ * available functions to struct cam_device and use it instead
+ * of checking for man_id = 0x00 for detecting number of functions
+ */
+static void
+get_sdio_card_info(struct cam_device *dev, struct card_info *ci) {
+ uint32_t cis_addr;
+ uint32_t fbr_addr;
+ int ret;
+
+ cis_addr = sdio_get_common_cis_addr(dev);
+
+ memset(ci, 0, sizeof(struct card_info));
+ sdio_func_read_cis(dev, 0, cis_addr, &ci->f[0]);
+ printf("F0: Vendor 0x%04X product 0x%04X max block size %d bytes\n",
+ ci->f[0].man_id, ci->f[0].prod_id, ci->f[0].max_block_size);
+ for (int i = 1; i <= 7; i++) {
+ fbr_addr = SD_IO_FBR_START * i + 0x9;
+ cis_addr = sdio_read_1(dev, 0, fbr_addr++, &ret);bailout(ret);
+ cis_addr |= sdio_read_1(dev, 0, fbr_addr++, &ret) << 8;
+ cis_addr |= sdio_read_1(dev, 0, fbr_addr++, &ret) << 16;
+ sdio_func_read_cis(dev, i, cis_addr, &ci->f[i]);
+ printf("F%d: Vendor 0x%04X product 0x%04X max block size %d bytes\n",
+ i, ci->f[i].man_id, ci->f[i].prod_id, ci->f[i].max_block_size);
+ if (ci->f[i].man_id == 0) {
+ printf("F%d doesn't exist\n", i);
+ break;
+ }
+ ci->num_funcs++;
+ }
+}
+
+int
+main(int argc, char **argv) {
+ char device[] = "pass";
+ int unit = 0;
+ int func = 0;
+ __unused uint8_t *fw_ptr;
+ int ch;
+ struct cam_device *cam_dev;
+ int ret;
+ struct card_info ci;
+
+ //fw_ptr = mmap_fw();
+
+ while ((ch = getopt(argc, argv, "fu:")) != -1) {
+ switch (ch) {
+ case 'u':
+ unit = (int) strtol(optarg, NULL, 10);
+ break;
+ case 'f':
+ func = (int) strtol(optarg, NULL, 10);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((cam_dev = cam_open_spec_device(device, unit, O_RDWR, NULL)) == NULL)
+ errx(1, "Cannot open device");
+
+ get_sdio_card_info(cam_dev, &ci);
+
+ /* For now, everything non-broadcom is out of the question */
+ if (ci.f[0].man_id != 0x02D0) {
+ printf("The card is not a Broadcom device\n");
+ exit(1);
+ }
+ /* Init structures */
+ struct brcmf_sdio_dev brcmf_dev;
+ struct brcmf_bus bus_if;
+ struct sdio_func f0, f1, f2;
+ bus_if.state = BRCMF_BUS_DOWN;
+ brcmf_dev.cam_dev = cam_dev;
+ brcmf_dev.bus_if = &bus_if;
+ brcmf_dev.state = BRCMF_SDIOD_DOWN;
+
+ /* Fill in functions */
+ brcmf_dev.func[0] = &f0;
+ brcmf_dev.func[1] = &f1;
+ brcmf_dev.func[2] = &f2;
+
+ brcmf_dev.func[0]->dev = brcmf_dev.func[1]->dev
+ = brcmf_dev.func[2]->dev = cam_dev;
+ brcmf_dev.func[0]->num = 0;
+ brcmf_dev.func[1]->num = 1;
+ brcmf_dev.func[2]->num = 2;
+
+ ret = sdio_func_enable(cam_dev, 1, 1);bailout(ret);
+ uint32_t magic = brcmf_sdiod_regrl(&brcmf_dev, 0x18000000, &ret);
+ printf("Magic = %08x\n", magic);
+ if (magic != REPLY_MAGIC) {
+ errx(1, "Reply magic is incorrect: expected %08x, got %08x",
+ REPLY_MAGIC, magic);
+ }
+ cam_close_spec_device(cam_dev);
+}
diff --git a/usr.bin/sed/Makefile b/usr.bin/sed/Makefile
new file mode 100644
index 000000000000..9f999ae8e3e1
--- /dev/null
+++ b/usr.bin/sed/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+PROG= sed
+SRCS= compile.c main.c misc.c process.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sed/Makefile.depend b/usr.bin/sed/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/sed/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sed/Makefile.depend.host b/usr.bin/sed/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/sed/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sed/Makefile.depend.options b/usr.bin/sed/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/sed/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/sed/POSIX b/usr.bin/sed/POSIX
new file mode 100644
index 000000000000..9d3ba01e4936
--- /dev/null
+++ b/usr.bin/sed/POSIX
@@ -0,0 +1,202 @@
+
+Comments on the IEEE P1003.2 Draft 12
+ Part 2: Shell and Utilities
+ Section 4.55: sed - Stream editor
+
+Diomidis Spinellis <dds@doc.ic.ac.uk>
+Keith Bostic <bostic@cs.berkeley.edu>
+
+In the following paragraphs, "wrong" usually means "inconsistent with
+historic practice", as most of the following comments refer to
+undocumented inconsistencies between the historical versions of sed and
+the POSIX 1003.2 standard. All the comments are notes taken while
+implementing a POSIX-compatible version of sed, and should not be
+interpreted as official opinions or criticism towards the POSIX committee.
+All uses of "POSIX" refer to section 4.55, Draft 12 of POSIX 1003.2.
+
+ 1. 32V and BSD derived implementations of sed strip the text
+ arguments of the a, c and i commands of their initial blanks,
+ i.e.
+
+ #!/bin/sed -f
+ a\
+ foo\
+ \ indent\
+ bar
+
+ produces:
+
+ foo
+ indent
+ bar
+
+ POSIX does not specify this behavior as the System V versions of
+ sed do not do this stripping. The argument against stripping is
+ that it is difficult to write sed scripts that have leading blanks
+ if they are stripped. The argument for stripping is that it is
+ difficult to write readable sed scripts unless indentation is allowed
+ and ignored, and leading whitespace is obtainable by entering a
+ backslash in front of it. This implementation follows the BSD
+ historic practice.
+
+ 2. Historical versions of sed required that the w flag be the last
+ flag to an s command as it takes an additional argument. This
+ is obvious, but not specified in POSIX.
+
+ 3. Historical versions of sed required that whitespace follow a w
+ flag to an s command. This is not specified in POSIX. This
+ implementation permits whitespace but does not require it.
+
+ 4. Historical versions of sed permitted any number of whitespace
+ characters to follow the w command. This is not specified in
+ POSIX. This implementation permits whitespace but does not
+ require it.
+
+ 5. The rule for the l command differs from historic practice. Table
+ 2-15 includes the various ANSI C escape sequences, including \\
+ for backslash. Some historical versions of sed displayed two
+ digit octal numbers, too, not three as specified by POSIX. POSIX
+ is a cleanup, and is followed by this implementation.
+
+ 6. The POSIX specification for ! does not specify that for a single
+ command the command must not contain an address specification
+ whereas the command list can contain address specifications. The
+ specification for ! implies that "3!/hello/p" works, and it never
+ has, historically. Note,
+
+ 3!{
+ /hello/p
+ }
+
+ does work.
+
+ 7. POSIX does not specify what happens with consecutive ! commands
+ (e.g. /foo/!!!p). Historic implementations allow any number of
+ !'s without changing the behaviour. (It seems logical that each
+ one might reverse the behaviour.) This implementation follows
+ historic practice.
+
+ 8. Historic versions of sed permitted commands to be separated
+ by semi-colons, e.g. 'sed -ne '1p;2p;3q' printed the first
+ three lines of a file. This is not specified by POSIX.
+ Note, the ; command separator is not allowed for the commands
+ a, c, i, w, r, :, b, t, # and at the end of a w flag in the s
+ command. This implementation follows historic practice and
+ implements the ; separator.
+
+ 9. Historic versions of sed terminated the script if EOF was reached
+ during the execution of the 'n' command, i.e.:
+
+ sed -e '
+ n
+ i\
+ hello
+ ' </dev/null
+
+ did not produce any output. POSIX does not specify this behavior.
+ This implementation follows historic practice.
+
+10. Deleted.
+
+11. Historical implementations do not output the change text of a c
+ command in the case of an address range whose first line number
+ is greater than the second (e.g. 3,1). POSIX requires that the
+ text be output. Since the historic behavior doesn't seem to have
+ any particular purpose, this implementation follows the POSIX
+ behavior.
+
+12. POSIX does not specify whether address ranges are checked and
+ reset if a command is not executed due to a jump. The following
+ program will behave in different ways depending on whether the
+ 'c' command is triggered at the third line, i.e. will the text
+ be output even though line 3 of the input will never logically
+ encounter that command.
+
+ 2,4b
+ 1,3c\
+ text
+
+ Historic implementations did not output the text in the above
+ example. Therefore it was believed that a range whose second
+ address was never matched extended to the end of the input.
+ However, the current practice adopted by this implementation,
+ as well as by those from GNU and SUN, is as follows: The text
+ from the 'c' command still isn't output because the second address
+ isn't actually matched; but the range is reset after all if its
+ second address is a line number. In the above example, only the
+ first line of the input will be deleted.
+
+13. Historical implementations allow an output suppressing #n at the
+ beginning of -e arguments as well as in a script file. POSIX
+ does not specify this. This implementation follows historical
+ practice.
+
+14. POSIX does not explicitly specify how sed behaves if no script is
+ specified. Since the sed Synopsis permits this form of the command,
+ and the language in the Description section states that the input
+ is output, it seems reasonable that it behave like the cat(1)
+ command. Historic sed implementations behave differently for "ls |
+ sed", where they produce no output, and "ls | sed -e#", where they
+ behave like cat. This implementation behaves like cat in both cases.
+
+15. The POSIX requirement to open all w files at the beginning makes
+ sed behave nonintuitively when the w commands are preceded by
+ addresses or are within conditional blocks. This implementation
+ follows historic practice and POSIX, by default, and provides the
+ -a option which opens the files only when they are needed.
+
+16. POSIX does not specify how escape sequences other than \n and \D
+ (where D is the delimiter character) are to be treated. This is
+ reasonable, however, it also doesn't state that the backslash is
+ to be discarded from the output regardless. A strict reading of
+ POSIX would be that "echo xyz | sed s/./\a" would display "\ayz".
+ As historic sed implementations always discarded the backslash,
+ this implementation does as well.
+
+17. POSIX specifies that an address can be "empty". This implies
+ that constructs like ",d" or "1,d" and ",5d" are allowed. This
+ is not true for historic implementations or this implementation
+ of sed.
+
+18. The b t and : commands are documented in POSIX to ignore leading
+ white space, but no mention is made of trailing white space.
+ Historic implementations of sed assigned different locations to
+ the labels "x" and "x ". This is not useful, and leads to subtle
+ programming errors, but it is historic practice and changing it
+ could theoretically break working scripts. This implementation
+ follows historic practice.
+
+19. Although POSIX specifies that reading from files that do not exist
+ from within the script must not terminate the script, it does not
+ specify what happens if a write command fails. Historic practice
+ is to fail immediately if the file cannot be opened or written.
+ This implementation follows historic practice.
+
+20. Historic practice is that the \n construct can be used for either
+ string1 or string2 of the y command. This is not specified by
+ POSIX. This implementation follows historic practice.
+
+21. Deleted.
+
+22. Historic implementations of sed ignore the RE delimiter characters
+ within character classes. This is not specified in POSIX. This
+ implementation follows historic practice.
+
+23. Historic implementations handle empty RE's in a special way: the
+ empty RE is interpreted as if it were the last RE encountered,
+ whether in an address or elsewhere. POSIX does not document this
+ behavior. For example the command:
+
+ sed -e /abc/s//XXX/
+
+ substitutes XXX for the pattern abc. The semantics of "the last
+ RE" can be defined in two different ways:
+
+ 1. The last RE encountered when compiling (lexical/static scope).
+ 2. The last RE encountered while running (dynamic scope).
+
+ While many historical implementations fail on programs depending
+ on scope differences, the SunOS version exhibited dynamic scope
+ behaviour. This implementation does dynamic scoping, as this seems
+ the most useful and in order to remain consistent with historical
+ practice.
diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c
new file mode 100644
index 000000000000..47249c3846fe
--- /dev/null
+++ b/usr.bin/sed/compile.c
@@ -0,0 +1,1071 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "defs.h"
+#include "extern.h"
+
+#define LHSZ 128
+#define LHMASK (LHSZ - 1)
+static struct labhash {
+ struct labhash *lh_next;
+ u_int lh_hash;
+ struct s_command *lh_cmd;
+ int lh_ref;
+} *labels[LHSZ];
+
+static char *compile_addr(char *, struct s_addr *);
+static char *compile_ccl(char **, char *);
+static char *compile_delimited(char *, char *, int);
+static char *compile_flags(char *, struct s_subst *);
+static regex_t *compile_re(char *, int);
+static char *compile_subst(char *, struct s_subst *);
+static char *compile_text(void);
+static char *compile_tr(char *, struct s_tr **);
+static struct s_command
+ **compile_stream(struct s_command **);
+static char *duptoeol(char *, const char *);
+static void enterlabel(struct s_command *);
+static struct s_command
+ *findlabel(char *);
+static void fixuplabel(struct s_command *, struct s_command *);
+static void uselabel(void);
+
+/*
+ * Command specification. This is used to drive the command parser.
+ */
+struct s_format {
+ char code; /* Command code */
+ int naddr; /* Number of address args */
+ enum e_args args; /* Argument type */
+};
+
+static struct s_format cmd_fmts[] = {
+ {'{', 2, GROUP},
+ {'}', 0, ENDGROUP},
+ {'a', 1, TEXT},
+ {'b', 2, BRANCH},
+ {'c', 2, TEXT},
+ {'d', 2, EMPTY},
+ {'D', 2, EMPTY},
+ {'g', 2, EMPTY},
+ {'G', 2, EMPTY},
+ {'h', 2, EMPTY},
+ {'H', 2, EMPTY},
+ {'i', 1, TEXT},
+ {'l', 2, EMPTY},
+ {'n', 2, EMPTY},
+ {'N', 2, EMPTY},
+ {'p', 2, EMPTY},
+ {'P', 2, EMPTY},
+ {'q', 1, EMPTY},
+ {'r', 1, RFILE},
+ {'s', 2, SUBST},
+ {'t', 2, BRANCH},
+ {'w', 2, WFILE},
+ {'x', 2, EMPTY},
+ {'y', 2, TR},
+ {'!', 2, NONSEL},
+ {':', 0, LABEL},
+ {'#', 0, COMMENT},
+ {'=', 1, EMPTY},
+ {'\0', 0, COMMENT},
+};
+
+/* The compiled program. */
+struct s_command *prog;
+
+/*
+ * Compile the program into prog.
+ * Initialise appends.
+ */
+void
+compile(void)
+{
+ *compile_stream(&prog) = NULL;
+ fixuplabel(prog, NULL);
+ uselabel();
+ if (appendnum == 0)
+ appends = NULL;
+ else if ((appends = malloc(sizeof(struct s_appends) * appendnum)) ==
+ NULL)
+ err(1, "malloc");
+ if ((match = malloc((maxnsub + 1) * sizeof(regmatch_t))) == NULL)
+ err(1, "malloc");
+}
+
+#define EATSPACE() do { \
+ if (p) \
+ while (*p && isspace((unsigned char)*p)) \
+ p++; \
+ } while (0)
+
+static struct s_command **
+compile_stream(struct s_command **link)
+{
+ char *p;
+ static char lbuf[_POSIX2_LINE_MAX + 1]; /* To save stack */
+ struct s_command *cmd, *cmd2, *stack;
+ struct s_format *fp;
+ char re[_POSIX2_LINE_MAX + 1];
+ int naddr; /* Number of addresses */
+
+ stack = NULL;
+ for (;;) {
+ if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) {
+ if (stack != NULL)
+ errx(1, "%lu: %s: unexpected EOF (pending }'s)",
+ linenum, fname);
+ return (link);
+ }
+
+semicolon: EATSPACE();
+ if (p) {
+ if (*p == '#' || *p == '\0')
+ continue;
+ else if (*p == ';') {
+ p++;
+ goto semicolon;
+ }
+ }
+ if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL)
+ err(1, "malloc");
+ link = &cmd->next;
+ cmd->startline = cmd->nonsel = 0;
+ /* First parse the addresses */
+ naddr = 0;
+
+/* Valid characters to start an address */
+#define addrchar(c) (strchr("0123456789/\\$", (c)))
+ if (addrchar(*p)) {
+ naddr++;
+ if ((cmd->a1 = malloc(sizeof(struct s_addr))) == NULL)
+ err(1, "malloc");
+ p = compile_addr(p, cmd->a1);
+ EATSPACE(); /* EXTENSION */
+ if (*p == ',') {
+ p++;
+ EATSPACE(); /* EXTENSION */
+ naddr++;
+ if ((cmd->a2 = malloc(sizeof(struct s_addr)))
+ == NULL)
+ err(1, "malloc");
+ p = compile_addr(p, cmd->a2);
+ EATSPACE();
+ } else
+ cmd->a2 = NULL;
+ } else
+ cmd->a1 = cmd->a2 = NULL;
+
+nonsel: /* Now parse the command */
+ if (!*p)
+ errx(1, "%lu: %s: command expected", linenum, fname);
+ cmd->code = *p;
+ for (fp = cmd_fmts; fp->code; fp++)
+ if (fp->code == *p)
+ break;
+ if (!fp->code)
+ errx(1, "%lu: %s: invalid command code %c", linenum, fname, *p);
+ if (naddr > fp->naddr)
+ errx(1,
+ "%lu: %s: command %c expects up to %d address(es), found %d",
+ linenum, fname, *p, fp->naddr, naddr);
+ switch (fp->args) {
+ case NONSEL: /* ! */
+ p++;
+ EATSPACE();
+ cmd->nonsel = 1;
+ goto nonsel;
+ case GROUP: /* { */
+ p++;
+ EATSPACE();
+ cmd->next = stack;
+ stack = cmd;
+ link = &cmd->u.c;
+ if (*p)
+ goto semicolon;
+ break;
+ case ENDGROUP:
+ /*
+ * Short-circuit command processing, since end of
+ * group is really just a noop.
+ */
+ cmd->nonsel = 1;
+ if (stack == NULL)
+ errx(1, "%lu: %s: unexpected }", linenum, fname);
+ cmd2 = stack;
+ stack = cmd2->next;
+ cmd2->next = cmd;
+ /*FALLTHROUGH*/
+ case EMPTY: /* d D g G h H l n N p P q x = \0 */
+ p++;
+ EATSPACE();
+ if (*p == ';') {
+ p++;
+ link = &cmd->next;
+ goto semicolon;
+ }
+ if (*p)
+ errx(1, "%lu: %s: extra characters at the end of %c command",
+ linenum, fname, cmd->code);
+ break;
+ case TEXT: /* a c i */
+ p++;
+ EATSPACE();
+ if (*p != '\\')
+ errx(1,
+"%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code);
+ p++;
+ EATSPACE();
+ if (*p)
+ errx(1,
+ "%lu: %s: extra characters after \\ at the end of %c command",
+ linenum, fname, cmd->code);
+ cmd->t = compile_text();
+ break;
+ case COMMENT: /* \0 # */
+ break;
+ case WFILE: /* w */
+ p++;
+ EATSPACE();
+ if (*p == '\0')
+ errx(1, "%lu: %s: filename expected", linenum, fname);
+ cmd->t = duptoeol(p, "w command");
+ if (aflag)
+ cmd->u.fd = -1;
+ else if ((cmd->u.fd = open(p,
+ O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
+ DEFFILEMODE)) == -1)
+ err(1, "%s", p);
+ break;
+ case RFILE: /* r */
+ p++;
+ EATSPACE();
+ if (*p == '\0')
+ errx(1, "%lu: %s: filename expected", linenum, fname);
+ else
+ cmd->t = duptoeol(p, "read command");
+ break;
+ case BRANCH: /* b t */
+ p++;
+ EATSPACE();
+ if (*p == '\0')
+ cmd->t = NULL;
+ else
+ cmd->t = duptoeol(p, "branch");
+ break;
+ case LABEL: /* : */
+ p++;
+ EATSPACE();
+ cmd->t = duptoeol(p, "label");
+ if (strlen(p) == 0)
+ errx(1, "%lu: %s: empty label", linenum, fname);
+ enterlabel(cmd);
+ break;
+ case SUBST: /* s */
+ p++;
+ if (*p == '\0' || *p == '\\')
+ errx(1,
+"%lu: %s: substitute pattern can not be delimited by newline or backslash",
+ linenum, fname);
+ if ((cmd->u.s = calloc(1, sizeof(struct s_subst))) == NULL)
+ err(1, "malloc");
+ p = compile_delimited(p, re, 0);
+ if (p == NULL)
+ errx(1,
+ "%lu: %s: unterminated substitute pattern", linenum, fname);
+
+ /* Compile RE with no case sensitivity temporarily */
+ if (*re == '\0')
+ cmd->u.s->re = NULL;
+ else
+ cmd->u.s->re = compile_re(re, 0);
+ --p;
+ p = compile_subst(p, cmd->u.s);
+ p = compile_flags(p, cmd->u.s);
+
+ /* Recompile RE with case sensitivity from "I" flag if any */
+ if (*re == '\0')
+ cmd->u.s->re = NULL;
+ else
+ cmd->u.s->re = compile_re(re, cmd->u.s->icase);
+ EATSPACE();
+ if (*p == ';') {
+ p++;
+ link = &cmd->next;
+ goto semicolon;
+ }
+ break;
+ case TR: /* y */
+ p++;
+ p = compile_tr(p, &cmd->u.y);
+ EATSPACE();
+ if (*p == ';') {
+ p++;
+ link = &cmd->next;
+ goto semicolon;
+ }
+ if (*p)
+ errx(1,
+"%lu: %s: extra text at the end of a transform command", linenum, fname);
+ break;
+ }
+ }
+}
+
+static int
+hex2char(const char *in, char *out, int len)
+{
+ long ord;
+ char *endptr, hexbuf[3];
+
+ hexbuf[0] = in[0];
+ hexbuf[1] = len > 1 ? in[1] : '\0';
+ hexbuf[2] = '\0';
+
+ errno = 0;
+ ord = strtol(hexbuf, &endptr, 16);
+ if (*endptr != '\0' || errno != 0)
+ return (ERANGE);
+ *out = (char)ord;
+ return (0);
+}
+
+static bool
+hexdigit(char c)
+{
+ int lc;
+
+ lc = tolower(c);
+ return isdigit(lc) || (lc >= 'a' && lc <= 'f');
+}
+
+static bool
+dohex(const char *in, char *out, int *len)
+{
+ int tmplen;
+
+ if (!hexdigit(in[0]))
+ return (false);
+ tmplen = 1;
+ if (hexdigit(in[1]))
+ ++tmplen;
+ if (hex2char(in, out, tmplen) == 0) {
+ *len = tmplen;
+ return (true);
+ }
+
+ return (false);
+}
+
+/*
+ * Get a delimited string. P points to the delimiter of the string; d points
+ * to a buffer area. Newline and delimiter escapes are processed; other
+ * escapes are ignored.
+ *
+ * Returns a pointer to the first character after the final delimiter or NULL
+ * in the case of a non-terminated string. The character array d is filled
+ * with the processed string.
+ */
+static char *
+compile_delimited(char *p, char *d, int is_tr)
+{
+ int hexlen;
+ char c;
+
+ c = *p++;
+ if (c == '\0')
+ return (NULL);
+ else if (c == '\\')
+ errx(1, "%lu: %s: \\ can not be used as a string delimiter",
+ linenum, fname);
+ else if (c == '\n')
+ errx(1, "%lu: %s: newline can not be used as a string delimiter",
+ linenum, fname);
+ while (*p) {
+ if (*p == '[' && *p != c) {
+ if (!is_tr) {
+ if ((d = compile_ccl(&p, d)) == NULL) {
+ errx(1,
+ "%lu: %s: unbalanced brackets ([])",
+ linenum, fname);
+ }
+ continue;
+ }
+ } else if (*p == '\\' && p[1] == '[') {
+ if (is_tr)
+ p++;
+ else
+ *d++ = *p++;
+ } else if (*p == '\\' && p[1] == c) {
+ p++;
+ } else if (*p == '\\' &&
+ (p[1] == 'n' || p[1] == 'r' || p[1] == 't')) {
+ switch (p[1]) {
+ case 'n':
+ *d++ = '\n';
+ break;
+ case 'r':
+ *d++ = '\r';
+ break;
+ case 't':
+ *d++ = '\t';
+ break;
+ }
+ p += 2;
+ continue;
+ } else if (*p == '\\' && p[1] == 'x') {
+ if (dohex(&p[2], d, &hexlen)) {
+ ++d;
+ p += hexlen + 2;
+ continue;
+ }
+ } else if (*p == '\\' && p[1] == '\\') {
+ if (is_tr)
+ p++;
+ else
+ *d++ = *p++;
+ } else if (*p == c) {
+ *d = '\0';
+ return (p + 1);
+ }
+ *d++ = *p++;
+ }
+ return (NULL);
+}
+
+
+/* compile_ccl: expand a POSIX character class */
+static char *
+compile_ccl(char **sp, char *t)
+{
+ int c, d, hexlen;
+ char *s = *sp;
+
+ *t++ = *s++;
+ if (*s == '^')
+ *t++ = *s++;
+ if (*s == ']')
+ *t++ = *s++;
+ for (; *s && (*t = *s) != ']'; s++, t++) {
+ if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) {
+ *++t = *++s, t++, s++;
+ for (c = *s; (*t = *s) != ']' || c != d; s++, t++)
+ if ((c = *s) == '\0')
+ return NULL;
+ } else if (*s == '\\') {
+ switch (s[1]) {
+ case 'n':
+ *t = '\n';
+ s++;
+ break;
+ case 'r':
+ *t = '\r';
+ s++;
+ break;
+ case 't':
+ *t = '\t';
+ s++;
+ break;
+ case 'x':
+ if (dohex(&s[2], t, &hexlen))
+ s += hexlen + 1;
+ break;
+ }
+ }
+ }
+ return (*s == ']') ? *sp = ++s, ++t : NULL;
+}
+
+/*
+ * Compiles the regular expression in RE and returns a pointer to the compiled
+ * regular expression.
+ * Cflags are passed to regcomp.
+ */
+static regex_t *
+compile_re(char *re, int case_insensitive)
+{
+ regex_t *rep;
+ int eval, flags;
+
+
+ flags = rflags;
+ if (case_insensitive)
+ flags |= REG_ICASE;
+ if ((rep = malloc(sizeof(regex_t))) == NULL)
+ err(1, "malloc");
+ if ((eval = regcomp(rep, re, flags)) != 0)
+ errx(1, "%lu: %s: RE error: %s",
+ linenum, fname, strregerror(eval, rep));
+ if (maxnsub < rep->re_nsub)
+ maxnsub = rep->re_nsub;
+ return (rep);
+}
+
+/*
+ * Compile the substitution string of a regular expression and set res to
+ * point to a saved copy of it. Nsub is the number of parenthesized regular
+ * expressions.
+ */
+static char *
+compile_subst(char *p, struct s_subst *s)
+{
+ static char lbuf[_POSIX2_LINE_MAX + 1];
+ int asize, hexlen, size;
+ u_char ref;
+ char c, *text, *op, *sp;
+ int more = 1, sawesc = 0;
+
+ c = *p++; /* Terminator character */
+ if (c == '\0')
+ return (NULL);
+
+ s->maxbref = 0;
+ s->linenum = linenum;
+ asize = 2 * _POSIX2_LINE_MAX + 1;
+ if ((text = malloc(asize)) == NULL)
+ err(1, "malloc");
+ size = 0;
+ do {
+ op = sp = text + size;
+ for (; *p; p++) {
+ if (*p == '\\' || sawesc) {
+ /*
+ * If this is a continuation from the last
+ * buffer, we won't have a character to
+ * skip over.
+ */
+ if (sawesc)
+ sawesc = 0;
+ else
+ p++;
+
+ if (*p == '\0') {
+ /*
+ * This escaped character is continued
+ * in the next part of the line. Note
+ * this fact, then cause the loop to
+ * exit w/ normal EOL case and reenter
+ * above with the new buffer.
+ */
+ sawesc = 1;
+ p--;
+ continue;
+ } else if (strchr("123456789", *p) != NULL) {
+ *sp++ = '\\';
+ ref = *p - '0';
+ if (s->re != NULL &&
+ ref > s->re->re_nsub)
+ errx(1, "%lu: %s: \\%c not defined in the RE",
+ linenum, fname, *p);
+ if (s->maxbref < ref)
+ s->maxbref = ref;
+ } else {
+ switch (*p) {
+ case '&':
+ case '\\':
+ *sp++ = '\\';
+ break;
+ case 'n':
+ *p = '\n';
+ break;
+ case 'r':
+ *p = '\r';
+ break;
+ case 't':
+ *p = '\t';
+ break;
+ case 'x':
+#define ADVANCE_N(s, n) \
+ do { \
+ char *adv = (s); \
+ while (*(adv + (n) - 1) != '\0') { \
+ *adv = *(adv + (n)); \
+ ++adv; \
+ } \
+ *adv = '\0'; \
+ } while (0);
+ if (dohex(&p[1], p, &hexlen)) {
+ ADVANCE_N(p + 1,
+ hexlen);
+ }
+ break;
+ }
+ }
+ } else if (*p == c) {
+ if (*++p == '\0' && more) {
+ if (cu_fgets(lbuf, sizeof(lbuf), &more))
+ p = lbuf;
+ }
+ *sp++ = '\0';
+ size += sp - op;
+ if ((s->new = realloc(text, size)) == NULL)
+ err(1, "realloc");
+ return (p);
+ } else if (*p == '\n') {
+ errx(1,
+"%lu: %s: unescaped newline inside substitute pattern", linenum, fname);
+ /* NOTREACHED */
+ }
+ *sp++ = *p;
+ }
+ size += sp - op;
+ if (asize - size < _POSIX2_LINE_MAX + 1) {
+ asize *= 2;
+ if ((text = realloc(text, asize)) == NULL)
+ err(1, "realloc");
+ }
+ } while (cu_fgets(p = lbuf, sizeof(lbuf), &more) != NULL);
+ errx(1, "%lu: %s: unterminated substitute in regular expression",
+ linenum, fname);
+ /* NOTREACHED */
+}
+
+/*
+ * Compile the flags of the s command
+ */
+static char *
+compile_flags(char *p, struct s_subst *s)
+{
+ int gn; /* True if we have seen g or n */
+ unsigned long nval;
+ char wfile[_POSIX2_LINE_MAX + 1], *q, *eq;
+
+ s->n = 1; /* Default */
+ s->p = 0;
+ s->wfile = NULL;
+ s->wfd = -1;
+ s->icase = 0;
+ for (gn = 0;;) {
+ EATSPACE(); /* EXTENSION */
+ switch (*p) {
+ case 'g':
+ if (gn)
+ errx(1,
+"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname);
+ gn = 1;
+ s->n = 0;
+ break;
+ case '\0':
+ case '\n':
+ case ';':
+ return (p);
+ case 'p':
+ s->p = 1;
+ break;
+ case 'i':
+ case 'I':
+ s->icase = 1;
+ break;
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ if (gn)
+ errx(1,
+"%lu: %s: more than one number or 'g' in substitute flags", linenum, fname);
+ gn = 1;
+ errno = 0;
+ nval = strtol(p, &p, 10);
+ if (errno == ERANGE || nval > INT_MAX)
+ errx(1,
+"%lu: %s: overflow in the 'N' substitute flag", linenum, fname);
+ s->n = nval;
+ p--;
+ break;
+ case 'w':
+ p++;
+#ifdef HISTORIC_PRACTICE
+ if (*p != ' ') {
+ warnx("%lu: %s: space missing before w wfile", linenum, fname);
+ return (p);
+ }
+#endif
+ EATSPACE();
+ q = wfile;
+ eq = wfile + sizeof(wfile) - 1;
+ while (*p) {
+ if (*p == '\n')
+ break;
+ if (q >= eq)
+ err(1, "wfile too long");
+ *q++ = *p++;
+ }
+ *q = '\0';
+ if (q == wfile)
+ errx(1, "%lu: %s: no wfile specified", linenum, fname);
+ s->wfile = strdup(wfile);
+ if (!aflag && (s->wfd = open(wfile,
+ O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
+ DEFFILEMODE)) == -1)
+ err(1, "%s", wfile);
+ return (p);
+ default:
+ errx(1, "%lu: %s: bad flag in substitute command: '%c'",
+ linenum, fname, *p);
+ break;
+ }
+ p++;
+ }
+}
+
+/*
+ * Compile a translation set of strings into a lookup table.
+ */
+static char *
+compile_tr(char *p, struct s_tr **py)
+{
+ struct s_tr *y;
+ int i;
+ const char *op, *np;
+ char old[_POSIX2_LINE_MAX + 1];
+ char new[_POSIX2_LINE_MAX + 1];
+ size_t oclen, oldlen, nclen, newlen;
+ mbstate_t mbs1, mbs2;
+
+ if ((*py = y = malloc(sizeof(*y))) == NULL)
+ err(1, NULL);
+ y->multis = NULL;
+ y->nmultis = 0;
+
+ if (*p == '\0' || *p == '\\')
+ errx(1,
+ "%lu: %s: transform pattern can not be delimited by newline or backslash",
+ linenum, fname);
+ p = compile_delimited(p, old, 1);
+ if (p == NULL)
+ errx(1, "%lu: %s: unterminated transform source string",
+ linenum, fname);
+ p = compile_delimited(p - 1, new, 1);
+ if (p == NULL)
+ errx(1, "%lu: %s: unterminated transform target string",
+ linenum, fname);
+ EATSPACE();
+ op = old;
+ oldlen = mbsrtowcs(NULL, &op, 0, NULL);
+ if (oldlen == (size_t)-1)
+ err(1, NULL);
+ np = new;
+ newlen = mbsrtowcs(NULL, &np, 0, NULL);
+ if (newlen == (size_t)-1)
+ err(1, NULL);
+ if (newlen != oldlen)
+ errx(1, "%lu: %s: transform strings are not the same length",
+ linenum, fname);
+ if (MB_CUR_MAX == 1) {
+ /*
+ * The single-byte encoding case is easy: generate a
+ * lookup table.
+ */
+ for (i = 0; i <= UCHAR_MAX; i++)
+ y->bytetab[i] = (char)i;
+ for (; *op; op++, np++)
+ y->bytetab[(u_char)*op] = *np;
+ } else {
+ /*
+ * Multi-byte encoding case: generate a lookup table as
+ * above, but only for single-byte characters. The first
+ * bytes of multi-byte characters have their lookup table
+ * entries set to 0, which causes do_tr() to search through
+ * an auxiliary vector of multi-byte mappings.
+ */
+ memset(&mbs1, 0, sizeof(mbs1));
+ memset(&mbs2, 0, sizeof(mbs2));
+ for (i = 0; i <= UCHAR_MAX; i++)
+ y->bytetab[i] = (btowc(i) != WEOF) ? i : 0;
+ while (*op != '\0') {
+ oclen = mbrlen(op, MB_LEN_MAX, &mbs1);
+ if (oclen == (size_t)-1 || oclen == (size_t)-2)
+ errc(1, EILSEQ, NULL);
+ nclen = mbrlen(np, MB_LEN_MAX, &mbs2);
+ if (nclen == (size_t)-1 || nclen == (size_t)-2)
+ errc(1, EILSEQ, NULL);
+ if (oclen == 1 && nclen == 1)
+ y->bytetab[(u_char)*op] = *np;
+ else {
+ y->bytetab[(u_char)*op] = 0;
+ y->multis = realloc(y->multis,
+ (y->nmultis + 1) * sizeof(*y->multis));
+ if (y->multis == NULL)
+ err(1, NULL);
+ i = y->nmultis++;
+ y->multis[i].fromlen = oclen;
+ memcpy(y->multis[i].from, op, oclen);
+ y->multis[i].tolen = nclen;
+ memcpy(y->multis[i].to, np, nclen);
+ }
+ op += oclen;
+ np += nclen;
+ }
+ }
+ return (p);
+}
+
+/*
+ * Compile the text following an a, c, or i command.
+ */
+static char *
+compile_text(void)
+{
+ int asize, esc_nl, size;
+ char *text, *p, *op, *s;
+ char lbuf[_POSIX2_LINE_MAX + 1];
+
+ asize = 2 * _POSIX2_LINE_MAX + 1;
+ if ((text = malloc(asize)) == NULL)
+ err(1, "malloc");
+ size = 0;
+ while (cu_fgets(lbuf, sizeof(lbuf), NULL) != NULL) {
+ op = s = text + size;
+ p = lbuf;
+#ifdef LEGACY_BSDSED_COMPAT
+ EATSPACE();
+#endif
+ for (esc_nl = 0; *p != '\0'; p++) {
+ if (*p == '\\' && p[1] != '\0' && *++p == '\n')
+ esc_nl = 1;
+ *s++ = *p;
+ }
+ size += s - op;
+ if (!esc_nl) {
+ *s = '\0';
+ break;
+ }
+ if (asize - size < _POSIX2_LINE_MAX + 1) {
+ asize *= 2;
+ if ((text = realloc(text, asize)) == NULL)
+ err(1, "realloc");
+ }
+ }
+ text[size] = '\0';
+ if ((p = realloc(text, size + 1)) == NULL)
+ err(1, "realloc");
+ return (p);
+}
+
+/*
+ * Get an address and return a pointer to the first character after
+ * it. Fill the structure pointed to according to the address.
+ */
+static char *
+compile_addr(char *p, struct s_addr *a)
+{
+ char *end, re[_POSIX2_LINE_MAX + 1];
+ int icase;
+
+ icase = 0;
+
+ a->type = 0;
+ switch (*p) {
+ case '\\': /* Context address */
+ ++p;
+ /* FALLTHROUGH */
+ case '/': /* Context address */
+ p = compile_delimited(p, re, 0);
+ if (p == NULL)
+ errx(1, "%lu: %s: unterminated regular expression", linenum, fname);
+ /* Check for case insensitive regexp flag */
+ if (*p == 'I') {
+ icase = 1;
+ p++;
+ }
+ if (*re == '\0')
+ a->u.r = NULL;
+ else
+ a->u.r = compile_re(re, icase);
+ a->type = AT_RE;
+ return (p);
+
+ case '$': /* Last line */
+ a->type = AT_LAST;
+ return (p + 1);
+
+ case '+': /* Relative line number */
+ a->type = AT_RELLINE;
+ p++;
+ /* FALLTHROUGH */
+ /* Line number */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (a->type == 0)
+ a->type = AT_LINE;
+ a->u.l = strtol(p, &end, 10);
+ return (end);
+ default:
+ errx(1, "%lu: %s: expected context address", linenum, fname);
+ return (NULL);
+ }
+}
+
+/*
+ * duptoeol --
+ * Return a copy of all the characters up to \n or \0.
+ */
+static char *
+duptoeol(char *s, const char *ctype)
+{
+ size_t len;
+ int ws;
+ char *p, *start;
+
+ ws = 0;
+ for (start = s; *s != '\0' && *s != '\n'; ++s)
+ ws = isspace((unsigned char)*s);
+ *s = '\0';
+ if (ws)
+ warnx("%lu: %s: whitespace after %s", linenum, fname, ctype);
+ len = s - start + 1;
+ if ((p = malloc(len)) == NULL)
+ err(1, "malloc");
+ return (memmove(p, start, len));
+}
+
+/*
+ * Convert goto label names to addresses, and count a and r commands, in
+ * the given subset of the script. Free the memory used by labels in b
+ * and t commands (but not by :).
+ *
+ * TODO: Remove } nodes
+ */
+static void
+fixuplabel(struct s_command *cp, struct s_command *end)
+{
+
+ for (; cp != end; cp = cp->next)
+ switch (cp->code) {
+ case 'a':
+ case 'r':
+ appendnum++;
+ break;
+ case 'b':
+ case 't':
+ /* Resolve branch target. */
+ if (cp->t == NULL) {
+ cp->u.c = NULL;
+ break;
+ }
+ if ((cp->u.c = findlabel(cp->t)) == NULL)
+ errx(1, "%lu: %s: undefined label '%s'", linenum, fname, cp->t);
+ free(cp->t);
+ break;
+ case '{':
+ /* Do interior commands. */
+ fixuplabel(cp->u.c, cp->next);
+ break;
+ }
+}
+
+/*
+ * Associate the given command label for later lookup.
+ */
+static void
+enterlabel(struct s_command *cp)
+{
+ struct labhash **lhp, *lh;
+ u_char *p;
+ u_int h, c;
+
+ for (h = 0, p = (u_char *)cp->t; (c = *p) != 0; p++)
+ h = (h << 5) + h + c;
+ lhp = &labels[h & LHMASK];
+ for (lh = *lhp; lh != NULL; lh = lh->lh_next)
+ if (lh->lh_hash == h && strcmp(cp->t, lh->lh_cmd->t) == 0)
+ errx(1, "%lu: %s: duplicate label '%s'", linenum, fname, cp->t);
+ if ((lh = malloc(sizeof *lh)) == NULL)
+ err(1, "malloc");
+ lh->lh_next = *lhp;
+ lh->lh_hash = h;
+ lh->lh_cmd = cp;
+ lh->lh_ref = 0;
+ *lhp = lh;
+}
+
+/*
+ * Find the label contained in the command l in the command linked
+ * list cp. L is excluded from the search. Return NULL if not found.
+ */
+static struct s_command *
+findlabel(char *name)
+{
+ struct labhash *lh;
+ u_char *p;
+ u_int h, c;
+
+ for (h = 0, p = (u_char *)name; (c = *p) != 0; p++)
+ h = (h << 5) + h + c;
+ for (lh = labels[h & LHMASK]; lh != NULL; lh = lh->lh_next) {
+ if (lh->lh_hash == h && strcmp(name, lh->lh_cmd->t) == 0) {
+ lh->lh_ref = 1;
+ return (lh->lh_cmd);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * Warn about any unused labels. As a side effect, release the label hash
+ * table space.
+ */
+static void
+uselabel(void)
+{
+ struct labhash *lh, *next;
+ int i;
+
+ for (i = 0; i < LHSZ; i++) {
+ for (lh = labels[i]; lh != NULL; lh = next) {
+ next = lh->lh_next;
+ if (!lh->lh_ref)
+ warnx("%lu: %s: unused label '%s'",
+ linenum, fname, lh->lh_cmd->t);
+ free(lh);
+ }
+ }
+}
diff --git a/usr.bin/sed/defs.h b/usr.bin/sed/defs.h
new file mode 100644
index 000000000000..e21beafb5bd8
--- /dev/null
+++ b/usr.bin/sed/defs.h
@@ -0,0 +1,148 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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.
+ */
+
+/*
+ * Types of address specifications
+ */
+enum e_atype {
+ AT_RE = 1, /* Line that match RE */
+ AT_LINE, /* Specific line */
+ AT_RELLINE, /* Relative line */
+ AT_LAST, /* Last line */
+};
+
+/*
+ * Format of an address
+ */
+struct s_addr {
+ enum e_atype type; /* Address type */
+ union {
+ u_long l; /* Line number */
+ regex_t *r; /* Regular expression */
+ } u;
+};
+
+/*
+ * Substitution command
+ */
+struct s_subst {
+ int n; /* Occurrence to subst. */
+ int p; /* True if p flag */
+ int icase; /* True if I flag */
+ char *wfile; /* NULL if no wfile */
+ int wfd; /* Cached file descriptor */
+ regex_t *re; /* Regular expression */
+ unsigned int maxbref; /* Largest backreference. */
+ u_long linenum; /* Line number. */
+ char *new; /* Replacement text */
+};
+
+/*
+ * Translate command.
+ */
+struct s_tr {
+ unsigned char bytetab[256];
+ struct trmulti {
+ size_t fromlen;
+ char from[MB_LEN_MAX];
+ size_t tolen;
+ char to[MB_LEN_MAX];
+ } *multis;
+ int nmultis;
+};
+
+/*
+ * An internally compiled command.
+ * Initially, label references are stored in t, on a second pass they
+ * are updated to pointers.
+ */
+struct s_command {
+ struct s_command *next; /* Pointer to next command */
+ struct s_addr *a1, *a2; /* Start and end address */
+ u_long startline; /* Start line number or zero */
+ char *t; /* Text for : a c i r w */
+ union {
+ struct s_command *c; /* Command(s) for b t { */
+ struct s_subst *s; /* Substitute command */
+ struct s_tr *y; /* Replace command array */
+ int fd; /* File descriptor for w */
+ } u;
+ char code; /* Command code */
+ u_int nonsel:1; /* True if ! */
+};
+
+/*
+ * Types of command arguments recognised by the parser
+ */
+enum e_args {
+ EMPTY, /* d D g G h H l n N p P q x = \0 */
+ TEXT, /* a c i */
+ NONSEL, /* ! */
+ GROUP, /* { */
+ ENDGROUP, /* } */
+ COMMENT, /* # */
+ BRANCH, /* b t */
+ LABEL, /* : */
+ RFILE, /* r */
+ WFILE, /* w */
+ SUBST, /* s */
+ TR /* y */
+};
+
+/*
+ * Structure containing things to append before a line is read
+ */
+struct s_appends {
+ enum {AP_STRING, AP_FILE} type;
+ char *s;
+ size_t len;
+};
+
+enum e_spflag {
+ APPEND, /* Append to the contents. */
+ REPLACE, /* Replace the contents. */
+};
+
+/*
+ * Structure for a space (process, hold, otherwise).
+ */
+typedef struct {
+ char *space; /* Current space pointer. */
+ size_t len; /* Current length. */
+ int deleted; /* If deleted. */
+ int append_newline; /* If originally terminated by \n. */
+ char *back; /* Backing memory. */
+ size_t blen; /* Backing memory length. */
+} SPACE;
diff --git a/usr.bin/sed/extern.h b/usr.bin/sed/extern.h
new file mode 100644
index 000000000000..1e10ecd1a7f7
--- /dev/null
+++ b/usr.bin/sed/extern.h
@@ -0,0 +1,57 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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.
+ */
+
+extern struct s_command *prog;
+extern struct s_appends *appends;
+extern regmatch_t *match;
+extern size_t maxnsub;
+extern u_long linenum;
+extern unsigned int appendnum;
+extern int aflag, eflag, nflag;
+extern const char *fname, *outfname;
+extern FILE *infile, *outfile;
+extern int rflags; /* regex flags to use */
+extern const char *inplace;
+extern int quit;
+
+void cfclose(struct s_command *, struct s_command *);
+void compile(void);
+void cspace(SPACE *, const char *, size_t, enum e_spflag);
+char *cu_fgets(char *, int, int *);
+int mf_fgets(SPACE *, enum e_spflag);
+int lastline(void);
+void process(void);
+void resetstate(void);
+char *strregerror(int, regex_t *);
diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c
new file mode 100644
index 000000000000..84e1dfa538e6
--- /dev/null
+++ b/usr.bin/sed/main.c
@@ -0,0 +1,544 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2013 Johann 'Myrkraverk' Oskarsson.
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
+#include <regex.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "defs.h"
+#include "extern.h"
+
+/*
+ * Linked list of units (strings and files) to be compiled
+ */
+struct s_compunit {
+ struct s_compunit *next;
+ enum e_cut {CU_FILE, CU_STRING} type;
+ char *s; /* Pointer to string or fname */
+};
+
+/*
+ * Linked list pointer to compilation units and pointer to current
+ * next pointer.
+ */
+static struct s_compunit *script, **cu_nextp = &script;
+
+/*
+ * Linked list of files to be processed
+ */
+struct s_flist {
+ char *fname;
+ struct s_flist *next;
+};
+
+/*
+ * Linked list pointer to files and pointer to current
+ * next pointer.
+ */
+static struct s_flist *files, **fl_nextp = &files;
+
+FILE *infile; /* Current input file */
+FILE *outfile; /* Current output file */
+
+int aflag, eflag, nflag;
+int rflags = 0;
+int quit = 0;
+static int rval; /* Exit status */
+
+static int ispan; /* Whether inplace editing spans across files */
+
+/*
+ * Current file and line number; line numbers restart across compilation
+ * units, but span across input files. The latter is optional if editing
+ * in place.
+ */
+const char *fname; /* File name. */
+const char *outfname; /* Output file name */
+static char oldfname[PATH_MAX]; /* Old file name (for in-place editing) */
+static char tmpfname[PATH_MAX]; /* Temporary file name (for in-place editing) */
+const char *inplace; /* Inplace edit file extension. */
+u_long linenum;
+
+static void add_compunit(enum e_cut, char *);
+static void add_file(char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int c, fflag, fflagstdin;
+ char *temp_arg;
+
+ (void) setlocale(LC_ALL, "");
+
+ fflag = 0;
+ fflagstdin = 0;
+ inplace = NULL;
+
+ while ((c = getopt(argc, argv, "EI:ae:f:i:lnru")) != -1)
+ switch (c) {
+ case 'r': /* Gnu sed compat */
+ case 'E':
+ rflags = REG_EXTENDED;
+ break;
+ case 'I':
+ inplace = optarg;
+ ispan = 1; /* span across input files */
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'e':
+ eflag = 1;
+ if (asprintf(&temp_arg, "%s\n", optarg) == -1)
+ err(1, "asprintf");
+ add_compunit(CU_STRING, temp_arg);
+ break;
+ case 'f':
+ fflag = 1;
+ if (strcmp(optarg, "-") == 0)
+ fflagstdin = 1;
+ add_compunit(CU_FILE, optarg);
+ break;
+ case 'i':
+ inplace = optarg;
+ ispan = 0; /* don't span across input files */
+ break;
+ case 'l':
+ if(setvbuf(stdout, NULL, _IOLBF, 0) != 0)
+ warnx("setting line buffered output failed");
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'u':
+ if(setvbuf(stdout, NULL, _IONBF, 0) != 0)
+ warnx("setting unbuffered output failed");
+ break;
+ default:
+ case '?':
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* First usage case; script is the first arg */
+ if (!eflag && !fflag && *argv) {
+ if (asprintf(&temp_arg, "%s\n", *argv) == -1)
+ err(1, "asprintf");
+ add_compunit(CU_STRING, temp_arg);
+ argv++;
+ }
+
+ compile();
+
+ /* Continue with first and start second usage */
+ if (*argv)
+ for (; *argv; argv++)
+ add_file(*argv);
+ else if (fflagstdin)
+ exit(rval);
+ else
+ add_file(NULL);
+ process();
+ cfclose(prog, NULL);
+ if (fclose(stdout))
+ err(1, "stdout");
+ exit(rval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: %s script [-Ealnru] [-i extension] [file ...]\n"
+ "\t%s [-Ealnu] [-i extension] [-e script] ... [-f script_file]"
+ " ... [file ...]\n", getprogname(), getprogname());
+ exit(1);
+}
+
+/*
+ * Like fgets, but go through the chain of compilation units chaining them
+ * together. Empty strings and files are ignored.
+ */
+char *
+cu_fgets(char *buf, int n, int *more)
+{
+ static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF;
+ static FILE *f; /* Current open file */
+ static char *s; /* Current pointer inside string */
+ static char string_ident[30];
+ char *p;
+
+again:
+ switch (state) {
+ case ST_EOF:
+ if (script == NULL) {
+ if (more != NULL)
+ *more = 0;
+ return (NULL);
+ }
+ linenum = 0;
+ switch (script->type) {
+ case CU_FILE:
+ if (strcmp(script->s, "-") == 0) {
+ f = stdin;
+ fname = "stdin";
+ } else {
+ if ((f = fopen(script->s, "r")) == NULL)
+ err(1, "%s", script->s);
+ fname = script->s;
+ }
+ state = ST_FILE;
+ goto again;
+ case CU_STRING:
+ if (((size_t)snprintf(string_ident,
+ sizeof(string_ident), "\"%s\"", script->s)) >=
+ sizeof(string_ident) - 1)
+ (void)strcpy(string_ident +
+ sizeof(string_ident) - 6, " ...\"");
+ fname = string_ident;
+ s = script->s;
+ state = ST_STRING;
+ goto again;
+ default:
+ __unreachable();
+ }
+ case ST_FILE:
+ if ((p = fgets(buf, n, f)) != NULL) {
+ linenum++;
+ if (linenum == 1 && buf[0] == '#' && buf[1] == 'n')
+ nflag = 1;
+ if (more != NULL)
+ *more = !feof(f);
+ return (p);
+ }
+ script = script->next;
+ (void)fclose(f);
+ state = ST_EOF;
+ goto again;
+ case ST_STRING:
+ if (linenum == 0 && s[0] == '#' && s[1] == 'n')
+ nflag = 1;
+ p = buf;
+ for (;;) {
+ if (n-- <= 1) {
+ *p = '\0';
+ linenum++;
+ if (more != NULL)
+ *more = 1;
+ return (buf);
+ }
+ switch (*s) {
+ case '\0':
+ state = ST_EOF;
+ if (s == script->s) {
+ script = script->next;
+ goto again;
+ } else {
+ script = script->next;
+ *p = '\0';
+ linenum++;
+ if (more != NULL)
+ *more = 0;
+ return (buf);
+ }
+ case '\n':
+ *p++ = '\n';
+ *p = '\0';
+ s++;
+ linenum++;
+ if (more != NULL)
+ *more = 0;
+ return (buf);
+ default:
+ *p++ = *s++;
+ }
+ }
+ }
+ /* NOTREACHED */
+ return (NULL);
+}
+
+/*
+ * Like fgets, but go through the list of files chaining them together.
+ * Set len to the length of the line.
+ */
+int
+mf_fgets(SPACE *sp, enum e_spflag spflag)
+{
+ struct stat sb;
+ ssize_t len;
+ char *dirbuf, *basebuf;
+ static char *p = NULL;
+ static size_t plen = 0;
+ int c;
+ static int firstfile;
+
+ if (infile == NULL) {
+ /* stdin? */
+ if (files->fname == NULL) {
+ if (inplace != NULL)
+ errx(1, "-I or -i may not be used with stdin");
+ infile = stdin;
+ fname = "stdin";
+ outfile = stdout;
+ outfname = "stdout";
+ }
+ firstfile = 1;
+ }
+
+ for (;;) {
+ if (infile != NULL && (c = getc(infile)) != EOF && !quit) {
+ (void)ungetc(c, infile);
+ break;
+ }
+ /* If we are here then either eof or no files are open yet */
+ if (infile == stdin) {
+ sp->len = 0;
+ return (0);
+ }
+ if (infile != NULL) {
+ fclose(infile);
+ if (*oldfname != '\0') {
+ /* if there was a backup file, remove it */
+ unlink(oldfname);
+ /*
+ * Backup the original. Note that hard links
+ * are not supported on all filesystems.
+ */
+ if ((link(fname, oldfname) != 0) &&
+ (rename(fname, oldfname) != 0)) {
+ warn("rename()");
+ if (*tmpfname)
+ unlink(tmpfname);
+ exit(1);
+ }
+ *oldfname = '\0';
+ }
+ if (*tmpfname != '\0') {
+ if (outfile != NULL && outfile != stdout)
+ if (fclose(outfile) != 0) {
+ warn("fclose()");
+ unlink(tmpfname);
+ exit(1);
+ }
+ outfile = NULL;
+ if (rename(tmpfname, fname) != 0) {
+ /* this should not happen really! */
+ warn("rename()");
+ unlink(tmpfname);
+ exit(1);
+ }
+ *tmpfname = '\0';
+ }
+ outfname = NULL;
+ }
+ if (firstfile == 0)
+ files = files->next;
+ else
+ firstfile = 0;
+ if (files == NULL) {
+ sp->len = 0;
+ return (0);
+ }
+ fname = files->fname;
+ if (inplace != NULL) {
+ if (lstat(fname, &sb) != 0)
+ err(1, "%s", fname);
+ if (!S_ISREG(sb.st_mode))
+ errx(1, "%s: %s %s", fname,
+ "in-place editing only",
+ "works for regular files");
+ if (*inplace != '\0') {
+ strlcpy(oldfname, fname,
+ sizeof(oldfname));
+ len = strlcat(oldfname, inplace,
+ sizeof(oldfname));
+ if (len > (ssize_t)sizeof(oldfname))
+ errx(1, "%s: name too long", fname);
+ }
+ if ((dirbuf = strdup(fname)) == NULL ||
+ (basebuf = strdup(fname)) == NULL)
+ err(1, "strdup");
+ len = snprintf(tmpfname, sizeof(tmpfname),
+ "%s/.!%ld!%s", dirname(dirbuf), (long)getpid(),
+ basename(basebuf));
+ free(dirbuf);
+ free(basebuf);
+ if (len >= (ssize_t)sizeof(tmpfname))
+ errx(1, "%s: name too long", fname);
+ unlink(tmpfname);
+ if (outfile != NULL && outfile != stdout)
+ fclose(outfile);
+ if ((outfile = fopen(tmpfname, "w")) == NULL)
+ err(1, "%s", fname);
+ fchown(fileno(outfile), sb.st_uid, sb.st_gid);
+ fchmod(fileno(outfile), sb.st_mode & ALLPERMS);
+ outfname = tmpfname;
+ if (!ispan) {
+ linenum = 0;
+ resetstate();
+ }
+ } else {
+ outfile = stdout;
+ outfname = "stdout";
+ }
+ if ((infile = fopen(fname, "r")) == NULL) {
+ warn("%s", fname);
+ rval = 1;
+ continue;
+ }
+ }
+ /*
+ * We are here only when infile is open and we still have something
+ * to read from it.
+ *
+ * Use getline() so that we can handle essentially infinite input
+ * data. The p and plen are static so each invocation gives
+ * getline() the same buffer which is expanded as needed.
+ */
+ len = getline(&p, &plen, infile);
+ if (len == -1)
+ err(1, "%s", fname);
+ if (len != 0 && p[len - 1] == '\n') {
+ sp->append_newline = 1;
+ len--;
+ } else if (!lastline()) {
+ sp->append_newline = 1;
+ } else {
+ sp->append_newline = 0;
+ }
+ cspace(sp, p, len, spflag);
+
+ linenum++;
+
+ return (1);
+}
+
+/*
+ * Add a compilation unit to the linked list
+ */
+static void
+add_compunit(enum e_cut type, char *s)
+{
+ struct s_compunit *cu;
+
+ if ((cu = malloc(sizeof(struct s_compunit))) == NULL)
+ err(1, "malloc");
+ cu->type = type;
+ cu->s = s;
+ cu->next = NULL;
+ *cu_nextp = cu;
+ cu_nextp = &cu->next;
+}
+
+/*
+ * Add a file to the linked list
+ */
+static void
+add_file(char *s)
+{
+ struct s_flist *fp;
+
+ if ((fp = malloc(sizeof(struct s_flist))) == NULL)
+ err(1, "malloc");
+ fp->next = NULL;
+ *fl_nextp = fp;
+ fp->fname = s;
+ fl_nextp = &fp->next;
+}
+
+static int
+next_files_have_lines(void)
+{
+ struct s_flist *file;
+ FILE *file_fd;
+ int ch;
+
+ file = files;
+ while ((file = file->next) != NULL) {
+ if ((file_fd = fopen(file->fname, "r")) == NULL)
+ continue;
+
+ if ((ch = getc(file_fd)) != EOF) {
+ /*
+ * This next file has content, therefore current
+ * file doesn't contains the last line.
+ */
+ ungetc(ch, file_fd);
+ fclose(file_fd);
+ return (1);
+ }
+
+ fclose(file_fd);
+ }
+
+ return (0);
+}
+
+int
+lastline(void)
+{
+ int ch;
+
+ if (feof(infile)) {
+ return !(
+ (inplace == NULL || ispan) &&
+ next_files_have_lines());
+ }
+ if ((ch = getc(infile)) == EOF) {
+ return !(
+ (inplace == NULL || ispan) &&
+ next_files_have_lines());
+ }
+ ungetc(ch, infile);
+ return (0);
+}
diff --git a/usr.bin/sed/misc.c b/usr.bin/sed/misc.c
new file mode 100644
index 000000000000..3a1aae727054
--- /dev/null
+++ b/usr.bin/sed/misc.c
@@ -0,0 +1,68 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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/cdefs.h>
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "defs.h"
+#include "extern.h"
+
+/*
+ * Return a string for a regular expression error passed. This is overkill,
+ * because of the silly semantics of regerror (we can never know the size of
+ * the buffer).
+ */
+char *
+strregerror(int errcode, regex_t *preg)
+{
+ static char *oe;
+ size_t s;
+
+ if (oe != NULL)
+ free(oe);
+ s = regerror(errcode, preg, NULL, 0);
+ if ((oe = malloc(s)) == NULL)
+ err(1, "malloc");
+ (void)regerror(errcode, preg, oe, s);
+ return (oe);
+}
diff --git a/usr.bin/sed/process.c b/usr.bin/sed/process.c
new file mode 100644
index 000000000000..c177524a528a
--- /dev/null
+++ b/usr.bin/sed/process.c
@@ -0,0 +1,784 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992 Diomidis Spinellis.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Diomidis Spinellis of Imperial College, University of London.
+ *
+ * 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/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "defs.h"
+#include "extern.h"
+
+static SPACE HS, PS, SS, YS;
+#define pd PS.deleted
+#define ps PS.space
+#define psl PS.len
+#define psanl PS.append_newline
+#define hs HS.space
+#define hsl HS.len
+
+static inline int applies(struct s_command *);
+static void do_tr(struct s_tr *);
+static void flush_appends(void);
+static void lputs(char *, size_t);
+static int regexec_e(regex_t *, const char *, int, int, size_t,
+ size_t);
+static void regsub(SPACE *, char *, char *);
+static int substitute(struct s_command *);
+
+struct s_appends *appends; /* Array of pointers to strings to append. */
+static unsigned int appendx; /* Index into appends array. */
+unsigned int appendnum; /* Size of appends array. */
+
+static int lastaddr; /* Set by applies if last address of a range. */
+static int sdone; /* If any substitutes since last line input. */
+ /* Iov structure for 'w' commands. */
+static regex_t *defpreg;
+size_t maxnsub;
+regmatch_t *match;
+
+#define OUT() do { \
+ fwrite(ps, 1, psl, outfile); \
+ if (psanl) fputc('\n', outfile); \
+} while (0)
+
+void
+process(void)
+{
+ struct s_command *cp;
+ SPACE tspace;
+ size_t oldpsl;
+ char *p;
+ int oldpsanl;
+
+ p = NULL;
+ oldpsanl = oldpsl = 0;
+
+ for (linenum = 0; mf_fgets(&PS, REPLACE);) {
+ pd = 0;
+top:
+ cp = prog;
+redirect:
+ while (cp != NULL) {
+ if (!applies(cp)) {
+ cp = cp->next;
+ continue;
+ }
+ switch (cp->code) {
+ case '{':
+ cp = cp->u.c;
+ goto redirect;
+ case 'a':
+ if (appendx >= appendnum)
+ if ((appends = realloc(appends,
+ sizeof(struct s_appends) *
+ (appendnum *= 2))) == NULL)
+ err(1, "realloc");
+ appends[appendx].type = AP_STRING;
+ appends[appendx].s = cp->t;
+ appends[appendx].len = strlen(cp->t);
+ appendx++;
+ break;
+ case 'b':
+ cp = cp->u.c;
+ goto redirect;
+ case 'c':
+ pd = 1;
+ psl = 0;
+ if (cp->a2 == NULL || lastaddr || lastline())
+ (void)fprintf(outfile, "%s", cp->t);
+ goto new;
+ case 'd':
+ pd = 1;
+ goto new;
+ case 'D':
+ if (pd)
+ goto new;
+ if (psl == 0 ||
+ (p = memchr(ps, '\n', psl)) == NULL) {
+ pd = 1;
+ goto new;
+ } else {
+ psl -= (p + 1) - ps;
+ memmove(ps, p + 1, psl);
+ goto top;
+ }
+ case 'g':
+ cspace(&PS, hs, hsl, REPLACE);
+ break;
+ case 'G':
+ cspace(&PS, "\n", 1, APPEND);
+ cspace(&PS, hs, hsl, APPEND);
+ break;
+ case 'h':
+ cspace(&HS, ps, psl, REPLACE);
+ break;
+ case 'H':
+ cspace(&HS, "\n", 1, APPEND);
+ cspace(&HS, ps, psl, APPEND);
+ break;
+ case 'i':
+ (void)fprintf(outfile, "%s", cp->t);
+ break;
+ case 'l':
+ lputs(ps, psl);
+ break;
+ case 'n':
+ if (!nflag && !pd)
+ OUT();
+ flush_appends();
+ if (!mf_fgets(&PS, REPLACE))
+ exit(0);
+ pd = 0;
+ break;
+ case 'N':
+ flush_appends();
+ cspace(&PS, "\n", 1, APPEND);
+ if (!mf_fgets(&PS, APPEND))
+ exit(0);
+ break;
+ case 'p':
+ if (pd)
+ break;
+ OUT();
+ break;
+ case 'P':
+ if (pd)
+ break;
+ if ((p = memchr(ps, '\n', psl)) != NULL) {
+ oldpsl = psl;
+ oldpsanl = psanl;
+ psl = p - ps;
+ psanl = 1;
+ }
+ OUT();
+ if (p != NULL) {
+ psl = oldpsl;
+ psanl = oldpsanl;
+ }
+ break;
+ case 'q':
+ if (inplace == NULL) {
+ if (!nflag && !pd)
+ OUT();
+ flush_appends();
+ exit(0);
+ }
+ quit = 1;
+ break;
+ case 'r':
+ if (appendx >= appendnum)
+ if ((appends = realloc(appends,
+ sizeof(struct s_appends) *
+ (appendnum *= 2))) == NULL)
+ err(1, "realloc");
+ appends[appendx].type = AP_FILE;
+ appends[appendx].s = cp->t;
+ appends[appendx].len = strlen(cp->t);
+ appendx++;
+ break;
+ case 's':
+ sdone |= substitute(cp);
+ break;
+ case 't':
+ if (sdone) {
+ sdone = 0;
+ cp = cp->u.c;
+ goto redirect;
+ }
+ break;
+ case 'w':
+ if (pd)
+ break;
+ if (cp->u.fd == -1 && (cp->u.fd = open(cp->t,
+ O_WRONLY|O_APPEND|O_CREAT|O_TRUNC,
+ DEFFILEMODE)) == -1)
+ err(1, "%s", cp->t);
+ if (write(cp->u.fd, ps, psl) != (ssize_t)psl ||
+ write(cp->u.fd, "\n", 1) != 1)
+ err(1, "%s", cp->t);
+ break;
+ case 'x':
+ /*
+ * If the hold space is null, make it empty
+ * but not null. Otherwise the pattern space
+ * will become null after the swap, which is
+ * an abnormal condition.
+ */
+ if (hs == NULL)
+ cspace(&HS, "", 0, REPLACE);
+ tspace = PS;
+ PS = HS;
+ psanl = tspace.append_newline;
+ HS = tspace;
+ break;
+ case 'y':
+ if (pd || psl == 0)
+ break;
+ do_tr(cp->u.y);
+ break;
+ case ':':
+ case '}':
+ break;
+ case '=':
+ (void)fprintf(outfile, "%lu\n", linenum);
+ }
+ cp = cp->next;
+ } /* for all cp */
+
+new: if (!nflag && !pd)
+ OUT();
+ flush_appends();
+ } /* for all lines */
+}
+
+/*
+ * TRUE if the address passed matches the current program state
+ * (lastline, linenumber, ps).
+ */
+#define MATCH(a) \
+ ((a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1, 0, psl) : \
+ (a)->type == AT_LINE ? linenum == (a)->u.l : lastline())
+
+/*
+ * Return TRUE if the command applies to the current line. Sets the start
+ * line for process ranges. Interprets the non-select (``!'') flag.
+ */
+static inline int
+applies(struct s_command *cp)
+{
+ int r;
+
+ lastaddr = 0;
+ if (cp->a1 == NULL && cp->a2 == NULL)
+ r = 1;
+ else if (cp->a2)
+ if (cp->startline > 0) {
+ switch (cp->a2->type) {
+ case AT_RELLINE:
+ if (linenum - cp->startline <= cp->a2->u.l)
+ r = 1;
+ else {
+ cp->startline = 0;
+ r = 0;
+ }
+ break;
+ default:
+ if (MATCH(cp->a2)) {
+ cp->startline = 0;
+ lastaddr = 1;
+ r = 1;
+ } else if (cp->a2->type == AT_LINE &&
+ linenum > cp->a2->u.l) {
+ /*
+ * We missed the 2nd address due to a
+ * branch, so just close the range and
+ * return false.
+ */
+ cp->startline = 0;
+ r = 0;
+ } else
+ r = 1;
+ }
+ } else if (cp->a1 && MATCH(cp->a1)) {
+ /*
+ * If the second address is a number less than or
+ * equal to the line number first selected, only
+ * one line shall be selected.
+ * -- POSIX 1003.2
+ * Likewise if the relative second line address is zero.
+ */
+ if ((cp->a2->type == AT_LINE &&
+ linenum >= cp->a2->u.l) ||
+ (cp->a2->type == AT_RELLINE && cp->a2->u.l == 0))
+ lastaddr = 1;
+ else {
+ cp->startline = linenum;
+ }
+ r = 1;
+ } else
+ r = 0;
+ else
+ r = MATCH(cp->a1);
+ return (cp->nonsel ? ! r : r);
+}
+
+/*
+ * Reset the sed processor to its initial state.
+ */
+void
+resetstate(void)
+{
+ struct s_command *cp;
+
+ /*
+ * Reset all in-range markers.
+ */
+ for (cp = prog; cp; cp = cp->code == '{' ? cp->u.c : cp->next)
+ if (cp->a2)
+ cp->startline = 0;
+
+ /*
+ * Clear out the hold space.
+ */
+ cspace(&HS, "", 0, REPLACE);
+}
+
+/*
+ * substitute --
+ * Do substitutions in the pattern space. Currently, we build a
+ * copy of the new pattern space in the substitute space structure
+ * and then swap them.
+ */
+static int
+substitute(struct s_command *cp)
+{
+ SPACE tspace;
+ regex_t *re;
+ regoff_t slen;
+ int lastempty, n;
+ regoff_t le = 0;
+ char *s;
+
+ s = ps;
+ re = cp->u.s->re;
+ if (re == NULL) {
+ if (defpreg != NULL && cp->u.s->maxbref > defpreg->re_nsub) {
+ linenum = cp->u.s->linenum;
+ errx(1, "%lu: %s: \\%u not defined in the RE",
+ linenum, fname, cp->u.s->maxbref);
+ }
+ }
+ if (!regexec_e(re, ps, 0, 0, 0, psl))
+ return (0);
+
+ SS.len = 0; /* Clean substitute space. */
+ slen = psl;
+ n = cp->u.s->n;
+ lastempty = 1;
+
+ do {
+ /* Copy the leading retained string. */
+ if (n <= 1 && (match[0].rm_so > le))
+ cspace(&SS, s, match[0].rm_so - le, APPEND);
+
+ /* Skip zero-length matches right after other matches. */
+ if (lastempty || (match[0].rm_so - le) ||
+ match[0].rm_so != match[0].rm_eo) {
+ if (n <= 1) {
+ /* Want this match: append replacement. */
+ regsub(&SS, ps, cp->u.s->new);
+ if (n == 1)
+ n = -1;
+ } else {
+ /* Want a later match: append original. */
+ if (match[0].rm_eo - le)
+ cspace(&SS, s, match[0].rm_eo - le,
+ APPEND);
+ n--;
+ }
+ }
+
+ /* Move past this match. */
+ s = ps + match[0].rm_eo;
+ slen = psl - match[0].rm_eo;
+ le = match[0].rm_eo;
+
+ /*
+ * After a zero-length match, advance one byte,
+ * and at the end of the line, terminate.
+ */
+ if (match[0].rm_so == match[0].rm_eo) {
+ if (slen > 0) {
+ cspace(&SS, s++, 1, APPEND);
+ slen--;
+ le++;
+ } else
+ slen = -1;
+ lastempty = 1;
+ } else
+ lastempty = 0;
+
+ } while (n >= 0 && slen >= 0 &&
+ regexec_e(re, ps, REG_NOTBOL, 0, le, psl));
+
+ /* Did not find the requested number of matches. */
+ if (n > 0)
+ return (0);
+
+ /* Copy the trailing retained string. */
+ if (slen > 0)
+ cspace(&SS, s, slen, APPEND);
+
+ /*
+ * Swap the substitute space and the pattern space, and make sure
+ * that any leftover pointers into stdio memory get lost.
+ */
+ tspace = PS;
+ PS = SS;
+ psanl = tspace.append_newline;
+ SS = tspace;
+ SS.space = SS.back;
+
+ /* Handle the 'p' flag. */
+ if (cp->u.s->p)
+ OUT();
+
+ /* Handle the 'w' flag. */
+ if (cp->u.s->wfile && !pd) {
+ if (cp->u.s->wfd == -1 && (cp->u.s->wfd = open(cp->u.s->wfile,
+ O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, DEFFILEMODE)) == -1)
+ err(1, "%s", cp->u.s->wfile);
+ if (write(cp->u.s->wfd, ps, psl) != (ssize_t)psl ||
+ write(cp->u.s->wfd, "\n", 1) != 1)
+ err(1, "%s", cp->u.s->wfile);
+ }
+ return (1);
+}
+
+/*
+ * do_tr --
+ * Perform translation ('y' command) in the pattern space.
+ */
+static void
+do_tr(struct s_tr *y)
+{
+ SPACE tmp;
+ char c, *p;
+ size_t clen, left;
+ int i;
+
+ if (MB_CUR_MAX == 1) {
+ /*
+ * Single-byte encoding: perform in-place translation
+ * of the pattern space.
+ */
+ for (p = ps; p < &ps[psl]; p++)
+ *p = y->bytetab[(u_char)*p];
+ } else {
+ /*
+ * Multi-byte encoding: perform translation into the
+ * translation space, then swap the translation and
+ * pattern spaces.
+ */
+ /* Clean translation space. */
+ YS.len = 0;
+ for (p = ps, left = psl; left > 0; p += clen, left -= clen) {
+ if ((c = y->bytetab[(u_char)*p]) != '\0') {
+ cspace(&YS, &c, 1, APPEND);
+ clen = 1;
+ continue;
+ }
+ for (i = 0; i < y->nmultis; i++)
+ if (left >= y->multis[i].fromlen &&
+ memcmp(p, y->multis[i].from,
+ y->multis[i].fromlen) == 0)
+ break;
+ if (i < y->nmultis) {
+ cspace(&YS, y->multis[i].to,
+ y->multis[i].tolen, APPEND);
+ clen = y->multis[i].fromlen;
+ } else {
+ cspace(&YS, p, 1, APPEND);
+ clen = 1;
+ }
+ }
+ /* Swap the translation space and the pattern space. */
+ tmp = PS;
+ PS = YS;
+ psanl = tmp.append_newline;
+ YS = tmp;
+ YS.space = YS.back;
+ }
+}
+
+/*
+ * Flush append requests. Always called before reading a line,
+ * therefore it also resets the substitution done (sdone) flag.
+ */
+static void
+flush_appends(void)
+{
+ FILE *f;
+ unsigned int count, idx;
+ char buf[8 * 1024];
+
+ for (idx = 0; idx < appendx; idx++)
+ switch (appends[idx].type) {
+ case AP_STRING:
+ fwrite(appends[idx].s, sizeof(char), appends[idx].len,
+ outfile);
+ break;
+ case AP_FILE:
+ /*
+ * Read files probably shouldn't be cached. Since
+ * it's not an error to read a non-existent file,
+ * it's possible that another program is interacting
+ * with the sed script through the filesystem. It
+ * would be truly bizarre, but possible. It's probably
+ * not that big a performance win, anyhow.
+ */
+ if ((f = fopen(appends[idx].s, "r")) == NULL)
+ break;
+ while ((count = fread(buf, sizeof(char), sizeof(buf), f)))
+ (void)fwrite(buf, sizeof(char), count, outfile);
+ (void)fclose(f);
+ break;
+ }
+ if (ferror(outfile))
+ errx(1, "%s: %s", outfname, strerror(errno ? errno : EIO));
+ appendx = sdone = 0;
+}
+
+static void
+lputs(char *s, size_t len)
+{
+ static const char escapes[] = "\\\a\b\f\r\t\v";
+ int c, col, width;
+ const char *p;
+ struct winsize win;
+ static int termwidth = -1;
+ size_t clen, i;
+ wchar_t wc;
+ mbstate_t mbs;
+
+ if (outfile != stdout)
+ termwidth = 60;
+ if (termwidth == -1) {
+ if ((p = getenv("COLUMNS")) && *p != '\0')
+ termwidth = atoi(p);
+ else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&
+ win.ws_col > 0)
+ termwidth = win.ws_col;
+ else
+ termwidth = 60;
+ }
+ if (termwidth <= 0)
+ termwidth = 1;
+
+ memset(&mbs, 0, sizeof(mbs));
+ col = 0;
+ while (len != 0) {
+ clen = mbrtowc(&wc, s, len, &mbs);
+ if (clen == 0)
+ clen = 1;
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ wc = (unsigned char)*s;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if (wc == '\n') {
+ if (col + 1 >= termwidth)
+ fprintf(outfile, "\\\n");
+ fputc('$', outfile);
+ fputc('\n', outfile);
+ col = 0;
+ } else if (iswprint(wc)) {
+ width = wcwidth(wc);
+ if (col + width >= termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
+ }
+ fwrite(s, 1, clen, outfile);
+ col += width;
+ } else if (wc != L'\0' && (c = wctob(wc)) != EOF &&
+ (p = strchr(escapes, c)) != NULL) {
+ if (col + 2 >= termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
+ }
+ fprintf(outfile, "\\%c", "\\abfrtv"[p - escapes]);
+ col += 2;
+ } else {
+ if (col + 4 * clen >= (unsigned)termwidth) {
+ fprintf(outfile, "\\\n");
+ col = 0;
+ }
+ for (i = 0; i < clen; i++)
+ fprintf(outfile, "\\%03o",
+ (int)(unsigned char)s[i]);
+ col += 4 * clen;
+ }
+ s += clen;
+ len -= clen;
+ }
+ if (col + 1 >= termwidth)
+ fprintf(outfile, "\\\n");
+ (void)fputc('$', outfile);
+ (void)fputc('\n', outfile);
+ if (ferror(outfile))
+ errx(1, "%s: %s", outfname, strerror(errno ? errno : EIO));
+}
+
+static int
+regexec_e(regex_t *preg, const char *string, int eflags, int nomatch,
+ size_t start, size_t stop)
+{
+ int eval;
+
+ if (preg == NULL) {
+ if (defpreg == NULL)
+ errx(1, "first RE may not be empty");
+ } else
+ defpreg = preg;
+
+ /* Set anchors */
+ match[0].rm_so = start;
+ match[0].rm_eo = stop;
+
+ eval = regexec(defpreg, string,
+ nomatch ? 0 : maxnsub + 1, match, eflags | REG_STARTEND);
+ switch(eval) {
+ case 0:
+ return (1);
+ case REG_NOMATCH:
+ return (0);
+ }
+ errx(1, "RE error: %s", strregerror(eval, defpreg));
+ /* NOTREACHED */
+}
+
+/*
+ * regsub - perform substitutions after a regexp match
+ * Based on a routine by Henry Spencer
+ */
+static void
+regsub(SPACE *sp, char *string, char *src)
+{
+ int len, no;
+ char c, *dst;
+
+#define NEEDSP(reqlen) \
+ /* XXX What is the +1 for? */ \
+ if (sp->len + (reqlen) + 1 >= sp->blen) { \
+ sp->blen += (reqlen) + 1024; \
+ if ((sp->space = sp->back = realloc(sp->back, sp->blen)) \
+ == NULL) \
+ err(1, "realloc"); \
+ dst = sp->space + sp->len; \
+ }
+
+ dst = sp->space + sp->len;
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && isdigit((unsigned char)*src))
+ no = *src++ - '0';
+ else
+ no = -1;
+ if (no < 0) { /* Ordinary character. */
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+ NEEDSP(1);
+ *dst++ = c;
+ ++sp->len;
+ } else if (match[no].rm_so != -1 && match[no].rm_eo != -1) {
+ len = match[no].rm_eo - match[no].rm_so;
+ NEEDSP(len);
+ memmove(dst, string + match[no].rm_so, len);
+ dst += len;
+ sp->len += len;
+ }
+ }
+ NEEDSP(1);
+ *dst = '\0';
+}
+
+/*
+ * cspace --
+ * Concatenate space: append the source space to the destination space,
+ * allocating new space as necessary.
+ */
+void
+cspace(SPACE *sp, const char *p, size_t len, enum e_spflag spflag)
+{
+ size_t tlen;
+
+ /* Make sure SPACE has enough memory and ramp up quickly. */
+ tlen = sp->len + len + 1;
+ if (tlen > sp->blen) {
+ sp->blen = tlen + 1024;
+ if ((sp->space = sp->back = realloc(sp->back, sp->blen)) ==
+ NULL)
+ err(1, "realloc");
+ }
+
+ if (spflag == REPLACE)
+ sp->len = 0;
+
+ memmove(sp->space + sp->len, p, len);
+
+ sp->space[sp->len += len] = '\0';
+}
+
+/*
+ * Close all cached opened files and report any errors
+ */
+void
+cfclose(struct s_command *cp, struct s_command *end)
+{
+
+ for (; cp != end; cp = cp->next)
+ switch(cp->code) {
+ case 's':
+ if (cp->u.s->wfd != -1 && close(cp->u.s->wfd))
+ err(1, "%s", cp->u.s->wfile);
+ cp->u.s->wfd = -1;
+ break;
+ case 'w':
+ if (cp->u.fd != -1 && close(cp->u.fd))
+ err(1, "%s", cp->t);
+ cp->u.fd = -1;
+ break;
+ case '{':
+ cfclose(cp->u.c, cp->next);
+ break;
+ }
+}
diff --git a/usr.bin/sed/sed.1 b/usr.bin/sed/sed.1
new file mode 100644
index 000000000000..345f673310d8
--- /dev/null
+++ b/usr.bin/sed/sed.1
@@ -0,0 +1,683 @@
+.\" Copyright (c) 1992, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd December 17, 2024
+.Dt SED 1
+.Os
+.Sh NAME
+.Nm sed
+.Nd stream editor
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ealnru
+.Ar command
+.Op Fl I Ar extension
+.Op Fl i Ar extension
+.Op Ar
+.Nm
+.Op Fl Ealnru
+.Op Fl e Ar command
+.Op Fl f Ar command_file
+.Op Fl I Ar extension
+.Op Fl i Ar extension
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility reads the specified files, or the standard input if no files
+are specified, modifying the input as specified by a list of commands.
+The input is then written to the standard output.
+.Pp
+A single command may be specified as the first argument to
+.Nm .
+Multiple commands may be specified by using the
+.Fl e
+or
+.Fl f
+options.
+All commands are applied to the input in the order they are specified
+regardless of their origin.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl E
+Interpret regular expressions as extended (modern) regular expressions
+rather than basic regular expressions (BRE's).
+The
+.Xr re_format 7
+manual page fully describes both formats.
+.It Fl a
+The files listed as parameters for the
+.Dq w
+functions are created (or truncated) before any processing begins,
+by default.
+The
+.Fl a
+option causes
+.Nm
+to delay opening each file until a command containing the related
+.Dq w
+function is applied to a line of input.
+.It Fl e Ar command
+Append the editing commands specified by the
+.Ar command
+argument
+to the list of commands.
+.It Fl f Ar command_file
+Append the editing commands found in the file
+.Ar command_file
+to the list of commands.
+The editing commands should each be listed on a separate line.
+The commands are read from the standard input if
+.Ar command_file
+is
+.Dq Li - .
+.It Fl I Ar extension
+Edit files in-place, saving backups with the specified
+.Ar extension .
+If a zero-length
+.Ar extension
+is given, no backup will be saved.
+It is not recommended to give a zero-length
+.Ar extension
+when in-place editing files, as you risk corruption or partial content
+in situations where disk space is exhausted, etc.
+.Pp
+Note that in-place editing with
+.Fl I
+still takes place in a single continuous line address space covering
+all files, although each file preserves its individuality instead of
+forming one output stream.
+The line counter is never reset between files, address ranges can span
+file boundaries, and the
+.Dq $
+address matches only the last line of the last file.
+(See
+.Sx "Sed Addresses" . )
+That can lead to unexpected results in many cases of in-place editing,
+where using
+.Fl i
+is desired.
+.It Fl i Ar extension
+Edit files in-place similarly to
+.Fl I ,
+but treat each file independently from other files.
+In particular, line numbers in each file start at 1,
+the
+.Dq $
+address matches the last line of the current file,
+and address ranges are limited to the current file.
+(See
+.Sx "Sed Addresses" . )
+The net result is as though each file were edited by a separate
+.Nm
+instance.
+.It Fl l
+Make output line buffered.
+.It Fl n
+By default, each line of input is echoed to the standard output after
+all of the commands have been applied to it.
+The
+.Fl n
+option suppresses this behavior.
+.It Fl r
+Same as
+.Fl E
+for compatibility with GNU sed.
+.It Fl u
+Make output unbuffered.
+.El
+.Pp
+The form of a
+.Nm
+command is as follows:
+.Pp
+.Dl [address[,address]]function[arguments]
+.Pp
+Whitespace may be inserted before the first address and the function
+portions of the command.
+.Pp
+Normally,
+.Nm
+cyclically copies a line of input, not including its terminating newline
+character, into a
+.Em "pattern space" ,
+(unless there is something left after a
+.Dq D
+function),
+applies all of the commands with addresses that select that pattern space,
+copies the pattern space to the standard output, appending a newline, and
+deletes the pattern space.
+.Pp
+Some of the functions use a
+.Em "hold space"
+to save all or part of the pattern space for subsequent retrieval.
+.Sh "Sed Addresses"
+An address is not required, but if specified must have one of the
+following formats:
+.Bl -bullet -offset indent
+.It
+a number that counts
+input lines
+cumulatively across input files (or in each file independently
+if a
+.Fl i
+option is in effect);
+.It
+a dollar
+.Pq Dq $
+character that addresses the last line of input (or the last line
+of the current file if a
+.Fl i
+option was specified);
+.It
+a context address
+that consists of a regular expression preceded and followed by a
+delimiter.
+The closing delimiter can also optionally be followed by the
+.Dq I
+character, to indicate that the regular expression is to be matched
+in a case-insensitive way.
+.El
+.Pp
+A command line with no addresses selects every pattern space.
+.Pp
+A command line with one address selects all of the pattern spaces
+that match the address.
+.Pp
+A command line with two addresses selects an inclusive range.
+This
+range starts with the first pattern space that matches the first
+address.
+The end of the range is the next following pattern space
+that matches the second address.
+If the second address is a number
+less than or equal to the line number first selected, only that
+line is selected.
+The number in the second address may be prefixed with a
+.Pq Dq \&+
+to specify the number of lines to match after the first pattern.
+In the case when the second address is a context
+address,
+.Nm
+does not re-match the second address against the
+pattern space that matched the first address.
+Starting at the
+first line following the selected range,
+.Nm
+starts looking again for the first address.
+.Pp
+Editing commands can be applied to non-selected pattern spaces by use
+of the exclamation character
+.Pq Dq \&!
+function.
+.Sh "Sed Regular Expressions"
+The regular expressions used in
+.Nm ,
+by default, are basic regular expressions (BREs, see
+.Xr re_format 7
+for more information), but extended (modern) regular expressions can be used
+instead if the
+.Fl E
+flag is given.
+In addition,
+.Nm
+has the following two additions to regular expressions:
+.Pp
+.Bl -enum -compact
+.It
+In a context address, any character other than a backslash
+.Pq Dq \e
+or newline character may be used to delimit the regular expression.
+The opening delimiter needs to be preceded by a backslash
+unless it is a slash.
+For example, the context address
+.Li \exabcx
+is equivalent to
+.Li /abc/ .
+Also, putting a backslash character before the delimiting character
+within the regular expression causes the character to be treated literally.
+For example, in the context address
+.Li \exabc\exdefx ,
+the RE delimiter is an
+.Dq x
+and the second
+.Dq x
+stands for itself, so that the regular expression is
+.Dq abcxdef .
+.Pp
+.It
+The escape sequence \en matches a newline character embedded in the
+pattern space.
+You cannot, however, use a literal newline character in an address or
+in the substitute command.
+.El
+.Pp
+One special feature of
+.Nm
+regular expressions is that they can default to the last regular
+expression used.
+If a regular expression is empty, i.e., just the delimiter characters
+are specified, the last regular expression encountered is used instead.
+The last regular expression is defined as the last regular expression
+used as part of an address or substitute command, and at run-time, not
+compile-time.
+For example, the command
+.Dq /abc/s//XXX/
+will substitute
+.Dq XXX
+for the pattern
+.Dq abc .
+.Sh "Sed Functions"
+In the following list of commands, the maximum number of permissible
+addresses for each command is indicated by [0addr], [1addr], or [2addr],
+representing zero, one, or two addresses.
+.Pp
+The argument
+.Em text
+consists of one or more lines.
+To embed a newline in the text, precede it with a backslash.
+Other backslashes in text are deleted and the following character
+taken literally.
+.Pp
+The
+.Dq r
+and
+.Dq w
+functions take an optional file parameter, which should be separated
+from the function letter by white space.
+Each file given as an argument to
+.Nm
+is created (or its contents truncated) before any input processing begins.
+.Pp
+The
+.Dq b ,
+.Dq r ,
+.Dq s ,
+.Dq t ,
+.Dq w ,
+.Dq y ,
+.Dq \&! ,
+and
+.Dq \&:
+functions all accept additional arguments.
+The following synopses indicate which arguments have to be separated from
+the function letters by white space characters.
+.Pp
+Two of the functions take a function-list.
+This is a list of
+.Nm
+functions separated by newlines, as follows:
+.Bd -literal -offset indent
+{ function
+ function
+ ...
+ function
+}
+.Ed
+.Pp
+The
+.Dq {
+can be preceded by white space and can be followed by white space.
+The function can be preceded by white space.
+The terminating
+.Dq }
+must be preceded by a newline, and may also be preceded by white space.
+.Pp
+.Bl -tag -width "XXXXXX" -compact
+.It [2addr] function-list
+Execute function-list only when the pattern space is selected.
+.Pp
+.It [1addr]a\e
+.It text
+Write
+.Em text
+to standard output immediately before each attempt to read a line of input,
+whether by executing the
+.Dq N
+function or by beginning a new cycle.
+.Pp
+.It [2addr]b[label]
+Branch to the
+.Dq \&:
+function with the specified label.
+If the label is not specified, branch to the end of the script.
+.Pp
+.It [2addr]c\e
+.It text
+Delete the pattern space and start the next cycle.
+With 0 or 1 address or at the end of a 2-address range,
+.Em text
+is written to the standard output.
+.Pp
+.It [2addr]d
+Delete the pattern space and start the next cycle.
+.Pp
+.It [2addr]D
+Delete the initial segment of the pattern space through the first
+newline character and start the next cycle.
+.Pp
+.It [2addr]g
+Replace the contents of the pattern space with the contents of the
+hold space.
+.Pp
+.It [2addr]G
+Append a newline character followed by the contents of the hold space
+to the pattern space.
+.Pp
+.It [2addr]h
+Replace the contents of the hold space with the contents of the
+pattern space.
+.Pp
+.It [2addr]H
+Append a newline character followed by the contents of the pattern space
+to the hold space.
+.Pp
+.It [1addr]i\e
+.It text
+Write
+.Em text
+to the standard output.
+.Pp
+.It [2addr]l
+(The letter ell.)
+Write the pattern space to the standard output in a visually unambiguous
+form.
+This form is as follows:
+.Pp
+.Bl -tag -width "carriage-returnXX" -offset indent -compact
+.It backslash
+\e\e
+.It alert
+\ea
+.It form-feed
+\ef
+.It carriage-return
+\er
+.It tab
+\et
+.It vertical tab
+\ev
+.El
+.Pp
+Nonprintable characters are written as three-digit octal numbers (with a
+preceding backslash) for each byte in the character (most significant byte
+first).
+Long lines are folded, with the point of folding indicated by displaying
+a backslash followed by a newline.
+The end of each line is marked with a
+.Dq $ .
+.Pp
+.It [2addr]n
+Write the pattern space to the standard output if the default output has
+not been suppressed, and replace the pattern space with the next line of
+input.
+.Pp
+.It [2addr]N
+Append the next line of input to the pattern space, using an embedded
+newline character to separate the appended material from the original
+contents.
+Note that the current line number changes.
+.Pp
+.It [2addr]p
+Write the pattern space to standard output.
+.Pp
+.It [2addr]P
+Write the pattern space, up to the first newline character to the
+standard output.
+.Pp
+.It [1addr]q
+Branch to the end of the script and quit without starting a new cycle.
+.Pp
+.It [1addr]r file
+Copy the contents of
+.Em file
+to the standard output immediately before the next attempt to read a
+line of input.
+If
+.Em file
+cannot be read for any reason, it is silently ignored and no error
+condition is set.
+.Pp
+.It [2addr]s/regular expression/replacement/flags
+Substitute the replacement string for the first instance of the regular
+expression in the pattern space.
+Any character other than backslash or newline can be used instead of
+a slash to delimit the RE and the replacement.
+Within the RE and the replacement, the RE delimiter itself can be used as
+a literal character if it is preceded by a backslash.
+.Pp
+An ampersand
+.Pq Dq &
+appearing in the replacement is replaced by the string matching the RE.
+The special meaning of
+.Dq &
+in this context can be suppressed by preceding it by a backslash.
+The string
+.Dq \e# ,
+where
+.Dq #
+is a digit, is replaced by the text matched
+by the corresponding backreference expression (see
+.Xr re_format 7 ) .
+.Pp
+A line can be split by substituting a newline character into it.
+To specify a newline character in the replacement string, precede it with
+a backslash.
+.Pp
+The value of
+.Em flags
+in the substitute function is zero or more of the following:
+.Bl -tag -width "XXXXXX" -offset indent
+.It Ar N
+Make the substitution only for the
+.Ar N Ns 'th
+occurrence of the regular expression in the pattern space.
+.It g
+Make the substitution for all non-overlapping matches of the
+regular expression, not just the first one.
+.It p
+Write the pattern space to standard output if a replacement was made.
+If the replacement string is identical to that which it replaces, it
+is still considered to have been a replacement.
+.It w Em file
+Append the pattern space to
+.Em file
+if a replacement was made.
+If the replacement string is identical to that which it replaces, it
+is still considered to have been a replacement.
+.It i or I
+Match the regular expression in a case-insensitive way.
+.El
+.Pp
+.It [2addr]t [label]
+Branch to the
+.Dq \&:
+function bearing the label if any substitutions have been made since the
+most recent reading of an input line or execution of a
+.Dq t
+function.
+If no label is specified, branch to the end of the script.
+.Pp
+.It [2addr]w Em file
+Append the pattern space to the
+.Em file .
+.Pp
+.It [2addr]x
+Swap the contents of the pattern and hold spaces.
+.Pp
+.It [2addr]y/string1/string2/
+Replace all occurrences of characters in
+.Em string1
+in the pattern space with the corresponding characters from
+.Em string2 .
+Any character other than a backslash or newline can be used instead of
+a slash to delimit the strings.
+Within
+.Em string1
+and
+.Em string2 ,
+a backslash followed by any character other than a newline is that literal
+character, and a backslash followed by an ``n'' is replaced by a newline
+character.
+.Pp
+.It [2addr]!function
+.It [2addr]!function-list
+Apply the function or function-list only to the lines that are
+.Em not
+selected by the address(es).
+.Pp
+.It [0addr]:label
+This function does nothing; it bears a label to which the
+.Dq b
+and
+.Dq t
+commands may branch.
+.Pp
+.It [1addr]=
+Write the line number to the standard output followed by a newline
+character.
+.Pp
+.It [0addr]
+Empty lines are ignored.
+.Pp
+.It [0addr]#
+The
+.Dq #
+and the remainder of the line are ignored (treated as a comment), with
+the single exception that if the first two characters in the file are
+.Dq #n ,
+the default output is suppressed.
+This is the same as specifying the
+.Fl n
+option on the command line.
+.El
+.Sh ENVIRONMENT
+The
+.Ev COLUMNS , LANG , LC_ALL , LC_CTYPE
+and
+.Ev LC_COLLATE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Replace
+.Ql bar
+with
+.Ql baz
+when piped from another command:
+.Bd -literal -offset indent
+echo "An alternate word, like bar, is sometimes used in examples." | sed 's/bar/baz/'
+.Ed
+.Pp
+Using backlashes can sometimes be hard to read and follow:
+.Bd -literal -offset indent
+echo "/home/example" | sed 's/\\/home\\/example/\\/usr\\/local\\/example/'
+.Ed
+.Pp
+Using a different separator can be handy when working with paths:
+.Bd -literal -offset indent
+echo "/home/example" | sed 's#/home/example#/usr/local/example#'
+.Ed
+.Pp
+Replace all occurrences of
+.Ql foo
+with
+.Ql bar
+in the file
+.Pa test.txt ,
+without creating a backup of the file:
+.Bd -literal -offset indent
+sed -i '' -e 's/foo/bar/g' test.txt
+.Ed
+.Sh SEE ALSO
+.Xr awk 1 ,
+.Xr ed 1 ,
+.Xr grep 1 ,
+.Xr regex 3 ,
+.Xr re_format 7
+.Rs
+.\" 4.4BSD USD:15
+.%A Lee E. McMahon
+.%I AT&T Bell Laboratories
+.%T SED \(em A Non-interactive Text Editor
+.%R Computing Science Technical Report
+.%N 77
+.%D January 1979
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2
+specification.
+.Pp
+The
+.Fl E , I , a
+and
+.Fl i
+options, the special meaning of
+.Fl f Cm - ,
+the prefixing
+.Dq \&+
+in the second member of an address range,
+as well as the
+.Dq I
+flag to the address regular expression and substitution command are
+non-standard
+.Fx
+extensions and may not be available on other operating systems.
+.Sh HISTORY
+A
+.Nm
+command, written by
+.An L. E. McMahon ,
+appeared in
+.At v7 .
+.Sh AUTHORS
+.An Diomidis D. Spinellis Aq Mt dds@FreeBSD.org
+.Sh BUGS
+Multibyte characters containing a byte with value 0x5C
+.Tn ( ASCII
+.Ql \e )
+may be incorrectly treated as line continuation characters in arguments to the
+.Dq a ,
+.Dq c
+and
+.Dq i
+commands.
+Multibyte characters cannot be used as delimiters with the
+.Dq s
+and
+.Dq y
+commands.
diff --git a/usr.bin/sed/tests/Makefile b/usr.bin/sed/tests/Makefile
new file mode 100644
index 000000000000..d072e1d65b23
--- /dev/null
+++ b/usr.bin/sed/tests/Makefile
@@ -0,0 +1,42 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= sed2_test
+NETBSD_ATF_TESTS_SH+= sed_test
+TAP_TESTS_SH= legacy_test
+TAP_TESTS_SH+= multi_test
+TEST_METADATA.multi_test+= required_files="/usr/share/dict/words"
+TAP_TESTS_SH+= inplace_race_test
+
+ATF_TESTS_SH_SED_sed_test+= -e 's,atf_expect_fail "PR bin/28126",,g'
+${PACKAGE}FILES+= d_c2048.in
+
+${PACKAGE}FILES+= hanoi.sed
+${PACKAGE}FILES+= math.sed
+${PACKAGE}FILES+= regress.G.out
+${PACKAGE}FILES+= regress.P.out
+${PACKAGE}FILES+= regress.b2a.out
+${PACKAGE}FILES+= regress.bcb.out
+${PACKAGE}FILES+= regress.c0.out
+${PACKAGE}FILES+= regress.c1.out
+${PACKAGE}FILES+= regress.c2.out
+${PACKAGE}FILES+= regress.c3.out
+${PACKAGE}FILES+= regress.hanoi.out
+${PACKAGE}FILES+= regress.icase1.out
+${PACKAGE}FILES+= regress.icase2.out
+${PACKAGE}FILES+= regress.icase3.out
+${PACKAGE}FILES+= regress.icase4.out
+${PACKAGE}FILES+= regress.in
+${PACKAGE}FILES+= regress.math.out
+${PACKAGE}FILES+= regress.not.out
+${PACKAGE}FILES+= regress.psl.out
+${PACKAGE}FILES+= regress.s3.out
+${PACKAGE}FILES+= regress.s4.out
+${PACKAGE}FILES+= regress.s5.out
+${PACKAGE}FILES+= regress.sg.out
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress.y.out
+
+SUBDIR= regress.multitest.out
+
+.include <netbsd-tests.test.mk>
+.include <bsd.test.mk>
diff --git a/usr.bin/sed/tests/Makefile.depend b/usr.bin/sed/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/sed/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sed/tests/hanoi.sed b/usr.bin/sed/tests/hanoi.sed
new file mode 100644
index 000000000000..e93d358b7427
--- /dev/null
+++ b/usr.bin/sed/tests/hanoi.sed
@@ -0,0 +1,98 @@
+# Towers of Hanoi in sed.
+# Ex:
+# Run "sed -f hanoi.sed", and enter:
+#
+# :abcd: : :<CR>
+#
+# note -- TWO carriage returns were once required, this will output the
+# sequence of states involved in moving 4 rings, the largest called "a" and
+# the smallest called "d", from the first to the second of three towers, so
+# that the rings on any tower at any time are in descending order of size.
+# You can start with a different arrangement and a different number of rings,
+# say :ce:b:ax: and it will give the shortest procedure for moving them all
+# to the middle tower. The rules are: the names of the rings must all be
+# lower-case letters, they must be input within 3 fields (representing the
+# towers) and delimited by 4 colons, such that the letters within each field
+# are in alphabetical order (i.e. rings are in descending order of size).
+#
+# For the benefit of anyone who wants to figure out the script, an "internal"
+# line of the form
+# b:0abx:1a2b3 :2 :3x2
+# has the following meaning: the material after the three markers :1, :2,
+# and :3 represents the three towers; in this case the current set-up is
+# ":ab : :x :". The numbers after a, b and x in these fields indicate
+# that the next time it gets a chance, it will move a to tower 2, move b
+# to tower 3, and move x to tower 2. The string after :0 just keeps track
+# of the alphabetical order of the names of the rings. The b at the
+# beginning means that it is now dealing with ring b (either about to move
+# it, or re-evaluating where it should next be moved to).
+#
+# Although this version is "limited" to 26 rings because of the size of the
+# alphabet, one could write a script using the same idea in which the rings
+# were represented by arbitrary [strings][within][brackets], and in place of
+# the built-in line of the script giving the order of the letters of the
+# alphabet, it would accept from the user a line giving the ordering to be
+# assumed, e.g. [ucbvax][decvax][hplabs][foo][bar].
+#
+# George Bergman
+# Math, UC Berkeley 94720 USA
+
+# cleaning, diagnostics
+s/ *//g
+/^$/d
+/[^a-z:]/{a\
+Illegal characters: use only a-z and ":". Try again.
+d
+}
+/^:[a-z]*:[a-z]*:[a-z]*:$/!{a\
+Incorrect format: use\
+\ : string1 : string2 : string3 :<CR>\
+Try again.
+d
+}
+/\([a-z]\).*\1/{a\
+Repeated letters not allowed. Try again.
+d
+}
+# initial formatting
+h
+s/[a-z]/ /g
+G
+s/^:\( *\):\( *\):\( *\):\n:\([a-z]*\):\([a-z]*\):\([a-z]*\):$/:1\4\2\3:2\5\1\3:3\6\1\2:0/
+s/[a-z]/&2/g
+s/^/abcdefghijklmnopqrstuvwxyz/
+:a
+s/^\(.\).*\1.*/&\1/
+s/.//
+/^[^:]/ba
+s/\([^0]*\)\(:0.*\)/\2\1:/
+s/^[^0]*0\(.\)/\1&/
+:b
+# outputting current state without markers
+h
+s/.*:1/:/
+s/[123]//gp
+g
+:c
+# establishing destinations
+/^\(.\).*\1:1/td
+/^\(.\).*:1[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/
+/^\(.\).*:1[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/
+/^\(.\).*:1[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/
+/^\(.\).*:2[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/
+/^\(.\).*:2[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/
+/^\(.\).*:2[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/
+/^\(.\).*:3[^:]*\11/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\32/
+/^\(.\).*:3[^:]*\12/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\31/
+/^\(.\).*:3[^:]*\13/s/^\(.\)\(.*\1\([a-z]\).*\)\3./\3\2\33/
+bc
+# iterate back to find smallest out-of-place ring
+:d
+s/^\(.\)\(:0[^:]*\([^:]\)\1.*:\([123]\)[^:]*\1\)\4/\3\2\4/
+td
+# move said ring (right, resp. left)
+s/^\(.\)\(.*\)\1\([23]\)\(.*:\3[^ ]*\) /\1\2 \4\1\3/
+s/^\(.\)\(.*:\([12]\)[^ ]*\) \(.*\)\1\3/\1\2\1\3\4 /
+tb
+s/.*/Done! Try another, or end with ^D./p
+d
diff --git a/usr.bin/sed/tests/inplace_race_test.sh b/usr.bin/sed/tests/inplace_race_test.sh
new file mode 100644
index 000000000000..86c0a83958e0
--- /dev/null
+++ b/usr.bin/sed/tests/inplace_race_test.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+#-
+# Copyright (c) 2011 Jilles Tjoelker
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+: "${SED=sed}"
+
+# This test really needs an SMP system. On an UP system, it will
+# usually pass even if the race condition exists.
+if command -v cpuset >/dev/null; then
+ case `cpuset -g -p $$` in
+ *,*) ;;
+ *)
+ echo '1..0 # Skipped: not an SMP system'
+ exit 0 ;;
+ esac
+fi
+
+echo "1..1"
+
+data=abababab
+data=$data$data$data$data
+data=$data$data$data$data
+data=$data$data$data$data
+data=$data$data$data$data
+data="BEGIN
+$data
+END"
+for i in 0 1 2 3 4 5 6 7 8 9; do
+ echo "$data" >file$i
+done
+len=${#data}
+
+i=0
+while [ $i -lt 100 ]; do
+ ${SED} -i.prev "s/$i/ab/" file[0-9]
+ i=$((i+1))
+done &
+sedproc=$!
+
+while :; do
+ set -- file[0-9]
+ if [ $# -ne 10 ]; then
+ echo "not ok 1 inplace_race"
+ exit 3
+ fi
+done &
+checkproc=$!
+
+wait $sedproc
+kill $checkproc 2>/dev/null
+wait $checkproc >/dev/null 2>&1
+if [ $? -ne 3 ]; then
+ echo "ok 1 inplace_race"
+fi
diff --git a/usr.bin/sed/tests/legacy_test.sh b/usr.bin/sed/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/sed/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/sed/tests/math.sed b/usr.bin/sed/tests/math.sed
new file mode 100644
index 000000000000..509e6c3e0267
--- /dev/null
+++ b/usr.bin/sed/tests/math.sed
@@ -0,0 +1,438 @@
+# This is ksb's infamous sed calculator. (ksb@sa.fedex.com)
+#
+#
+# $Id: math.sed,v 2.5 1998/08/02 13:23:34 ksb Exp ksb $
+# expr ::= (expr) | expr! |
+# expr ^ expr |
+# -expr | expr * expr | expr / expr | expr % expr |
+# expr + expr | expr - expr |
+# [0-9][0-9]* ;
+# Bugs: some sign combinations don't work, and I got sick of added cases
+# for unary +. Don't depend on signed math working all the time. -- ksb
+#
+# $Compile: echo "4+7*3+2^7/3" | sed -f %f
+
+# make sure the expression is well formed
+s/[ ]//g
+/[*\/^%+-]$/{
+ a\
+ poorly formed expression, dyadic operator on the end
+ q
+}
+/^[*\/^%]/{
+ a\
+ poorly formed expression, leading dyadic operator
+ q
+}
+
+# fill hold space with done token
+x
+s/^.*/done/
+x
+
+# main loop, process operators ((), !, *, /, %, +, and -)
+: loop
+# uncomment the print below to follow the "logic" -- ksb
+#p
+/^[+]/{
+ s///
+ b loop
+}
+/^--/{
+ s///
+ b loop
+}
+# eval parenthesised sub expressions first
+/^\(.*\)(\([^)]*\))\(.*\)$/{
+ H
+ s//\2/
+ x
+ s/^\(.*\)\n\(.*\)(\([^()]*\))\(.*\)$/()\2@\4@\1/
+ x
+ b loop
+}
+# reduce a^b^c -> a^(b^c)
+/\([0-9][0-9]*^\)\([0-9][0-9]*^[0-9][0-9^]*\)/{
+ s//\1(\2)/
+ b loop
+}
+# pull any buried exponents
+/^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)$/{
+ s//\1(\2)/
+ b loop
+}
+/^\(.*[^0-9]\)\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
+ s//\1(\2)\3/
+ b loop
+}
+/^\([0-9][0-9]*^[0-9][0-9]*\)\([^0-9].*\)$/{
+ s//(\1)\2/
+ b loop
+}
+/^\([-]*[0-9]*\)^0*$/{
+ s//1/
+ b loop
+}
+/^\([-]*[0-9]*\)^0*1$/{
+ s//\1/
+ b loop
+}
+/^\([-]*[0-9]*\)^-[0-9]*$/{
+ s//0/
+ b loop
+}
+/^\([-]*\)\([0-9]*\)^\([0-9][0-9]*[13579]\)$/{
+ s//\1\2*((\2*\2)^(\3\/2))/
+ b loop
+}
+/^[-]*\([0-9]*\)^\([0-9][0-9]*[02468]\)$/{
+ s//(\1*\1)^(\2\/2)/
+ b loop
+}
+# single digit powers (2 3,9 4,6,8 5,7
+/^[-]*\([0-9]*\)^0*2$/{
+ s//(\1*\1)/
+ b loop
+}
+/^\([-]*\)\([0-9]*\)^0*\([39]\)$/{
+ s//\1(\2*(\2*\2))^(\3\/3)/
+ b loop
+}
+/^[-]*\([0-9]*\)^0*\([468]\)$/{
+ s//(\1*\1)^(\2\/2)/
+ b loop
+}
+# 5 7
+/^\([-]*[0-9]*\)^\([0-9]*\)$/{
+ s//\1*(\1^(\2-1))/
+ b loop
+}
+# reduce all number factorials
+/^0*[01]!/{
+ s//1/
+ b loop
+}
+/\([*+-/%^]\)0*[01]!/{
+ s//\11/
+ b loop
+}
+/\([0-9]*\)!/{
+ s//(\1-1)!*\1/
+ b loop
+}
+# sign simplifications
+/^-\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
+ s//\1\2\3/
+ b loop
+}
+/^\([0-9]*\)\([*/%]\)-\([0-9]*\)$/{
+ s//-\1\2\3/
+ b loop
+}
+/^-\([0-9][0-9]*\)[+]*-\([0-9][0-9]*\)$/{
+ s//\1+\2/
+ x
+ s/\(.*\)/()-@@\1/
+ x
+ b loop
+}
+/^-\([0-9]*\)[+]\([0-9]\)*$/{
+ s//\2-\1/
+ b loop
+}
+/^-.*[-+*/%].*/{
+ H
+ s/^-//
+ x
+ s/^\(.*\)\n-.*$/()-@@\1/
+ x
+ b loop
+}
+# can we simplify multiplications
+/^\([0-9]*\)\([*][0-9]*[1-9]\)00*$/{
+ H
+ s//\1\2/
+ x
+ s/^\(.*\)\n[0-9]*[*][0-9]*[1-9]\(00*\)$/()@\2@\1/
+ x
+ b loop
+}
+/^\([0-9][1-9]*\)00*\([*][0-9]*\)$/{
+ H
+ s//\1\2/
+ x
+ s/^\(.*\)\n[0-9][1-9]*\(00*\)[*][0-9]*$/()@\2@\1/
+ x
+ b loop
+}
+# can we simplify division (20/30 -> 2/3)
+/^\([0-9][0-9]*\)0\([/%]\)\([0-9][0-9]*\)0$/{
+ s//\1\2\3/
+ b loop
+}
+# n/1 -> n
+/^0*\([0-9][0-9]*\)0[/]0*1$/{
+ s//\1/
+ b loop
+}
+# n%2 -> last_digit(n)%2 (same for 1, BTW) N.B. NO LOOP
+/^[0-9]*\([0-9]\)%0*\([12]\)$/{
+ s//\1%\2/
+}
+# move any mul/divs to the front via parans
+/^\([0-9+]*\)\([-+]\)\([0-9]*[*/][0-9*/]*\)/{
+ s//\1\2(\3)/
+ b loop
+}
+# can we div or mul
+/^[0-9]*[*][0-9]*$/{
+ b mul
+}
+/^[0-9]*[/%]0*$/{
+ i\
+divide by zero
+ d
+}
+/^[0-9]*[/%][0-9]*$/{
+ H
+ s/\([0-9]\).*[/%]/\1-/
+ x
+ s/^\(.*\)\n\([0-9]\)\([0-9]*\)\([/%]\)\([0-9]*\).*$/.\4\3q0r\2-\5@\1/
+ x
+ b loop
+}
+/^\([0-9]*[*/%][0-9]*\)\(.*\)/{
+ H
+ s//\1/
+ x
+ s/^\(.*\)\n\([0-9]*[*/][0-9]*\)\(.*\)$/()@\3@\1/
+ x
+ b loop
+}
+# can we add or subtract -- note subtract hold expression for underflow
+/^[0-9]*[+][0-9]*$/{
+ s/$/=/
+ b add
+}
+/^[0-9][0-9]*-[0-9]*$/{
+ H
+ s/$/=/
+ b sub
+}
+/^\([0-9][0-9]*[-+][0-9]*\)\(.*\)/{
+ H
+ s//\1/
+ x
+ s/^\(.*\)\n\([0-9]*[-+][0-9]*\)\(.*\)$/()@\3@\1/
+ x
+ b loop
+}
+# look in hold space for stack to reduce
+x
+/^done$/{
+ x
+ s/^0*\([0-9][0-9]*\)/\1/
+ p
+ d
+}
+# .[/%] numerator q quotient r remainder-divisor @stack
+/^\./{
+ x
+ /^[^-]/{
+ H
+ x
+ s/.\(.\)\([0-9]*\)q\([^r]*\)r\([0-9]*\)-\([0-9]*\)@\(.*\)\n\(.*\)/.\1\2q\3+1r\7-\5@\6/
+ h
+ s/..[0-9]*q[^r]*r\([0-9]*-[0-9]*\)@.*/\1/
+ b loop
+ }
+ /^-/{
+ g
+ /.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([^@]*\)@.*/{
+ s//\5\2-\6/
+ x
+ s/.\(.\)\([0-9]\)\([0-9]*\)q\([^r]*\)r0*\([0-9]*\)-\([0-9]*\)@\(.*\)/.\1\3q(\4)*10r\5\2-\6@\7/
+ x
+ b loop
+ }
+# no digits to shift on
+ s/^\.[/]q\([^r]*\)r[^@]*@.*/\1/
+ s/^\.[%]q[^r]*r0*\([0-9][0-9]*\)-[^@]*@.*/\1/
+ /^\./{
+ i\
+divide error
+ q
+ }
+ x
+ s/^\.[/%]q[^r]*r[^@]*@\(.*\)/\1/
+ x
+ b loop
+ }
+}
+/^()/{
+ s///
+ x
+ G
+ s/\(.*\)\n\([^@]*\)@\([^@]*\)@\(.*\)/\2\1\3/
+ x
+ s/[^@]*@[^@]*@\(.*\)/\1/
+ x
+ b loop
+}
+i\
+help, stack problem - the hold space
+p
+x
+i\
+and the pat space
+p
+i\
+quit
+q
+
+# turn mul into add until 1*x -> x, 0*x -> 0
+: mul
+/^00*\*.*/{
+ s//0/
+ b loop
+}
+/^0*1\*/{
+ s///
+: leading
+ s/^0*\([0-9][0-9]*\)/\1/
+ b loop
+}
+s/^\([0-9]*\)0\*\([0-9]*\)/\1*\20/
+s/^\([0-9]*\)1\*\([0-9]*\)/\1*\20+\2/
+s/^\([0-9]*\)2\*\([0-9]*\)/\1*\20+(\2+\2)/
+s/^\([0-9]*\)3\*\([0-9]*\)/\1*\20+(\2+\2+\2)/
+s/^\([0-9]*\)4\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2)/
+s/^\([0-9]*\)5\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2)/
+s/^\([0-9]*\)6\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2)/
+s/^\([0-9]*\)7\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2)/
+s/^\([0-9]*\)8\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2)/
+s/^\([0-9]*\)9\*\([0-9]*\)/\1*\20+(\2+\2+\2+\2+\2+\2+\2+\2+\2)/
+/^0*\*[0-9]*[+]*\(.*\)/{
+ s//\1/
+ b loop
+}
+b mul
+
+# get rid of a plus term until 0+x -> x
+: add
+/^[+]\([0-9+*]*\)=/{
+ s//\1/
+ b leading
+}
+/^\([0-9*]*\)[+]=/{
+ s//\1/
+ b loop
+}
+/^\([0-9]*\)0[+]\([0-9]*\)\([0-9]\)=/{
+ s//\1+\2=\3/
+ b add
+}
+/^\([0-9]*\)\([0-9]\)[+]\([0-9]*\)0=/{
+ s//\1+\3=\2/
+ b add
+}
+s/^\([0-9]*\)1[+]/\10+/
+s/^\([0-9]*\)2[+]/\11+/
+s/^\([0-9]*\)3[+]/\12+/
+s/^\([0-9]*\)4[+]/\13+/
+s/^\([0-9]*\)5[+]/\14+/
+s/^\([0-9]*\)6[+]/\15+/
+s/^\([0-9]*\)7[+]/\16+/
+s/^\([0-9]*\)8[+]/\17+/
+s/^\([0-9]*\)9[+]/\18+/
+
+s/9=\([0-9]*\)$/_=\1/
+s/8=\([0-9]*\)$/9=\1/
+s/7=\([0-9]*\)$/8=\1/
+s/6=\([0-9]*\)$/7=\1/
+s/5=\([0-9]*\)$/6=\1/
+s/4=\([0-9]*\)$/5=\1/
+s/3=\([0-9]*\)$/4=\1/
+s/2=\([0-9]*\)$/3=\1/
+s/1=\([0-9]*\)$/2=\1/
+/_/{
+ s//_0/
+ : inc
+ s/9_/_0/
+ s/8_/9/
+ s/7_/8/
+ s/6_/7/
+ s/5_/6/
+ s/4_/5/
+ s/3_/4/
+ s/2_/3/
+ s/1_/2/
+ s/0_/1/
+ s/[+]_/+1/
+ /_/b inc
+}
+b add
+
+# get rid of a sub term until /-0*=/ or underflow
+: sub
+/^\([0-9]*\)-0*=/{
+ s//\1/
+ x
+ s/\(.*\)\n.*$/\1/
+ x
+ b leading
+}
+/^-\([0-9].*\)=/{
+: under
+ g
+ s/.*\n\([0-9]*\)-\([0-9]*\).*/-(\2-\1)/
+ x
+ s/\(.*\)\n.*/\1/
+ x
+ b loop
+}
+/^\([0-9]*\)\([0-9]\)-\([0-9]*\)0=/{
+ s//\1-\3=\2/
+ b sub
+}
+s/1=/0=/
+s/2=/1=/
+s/3=/2=/
+s/4=/3=/
+s/5=/4=/
+s/6=/5=/
+s/7=/6=/
+s/8=/7=/
+s/9=/8=/
+
+s/^\([0-9]*\)1-/\1_-/
+s/^\([0-9]*\)2-/\11-/
+s/^\([0-9]*\)3-/\12-/
+s/^\([0-9]*\)4-/\13-/
+s/^\([0-9]*\)5-/\14-/
+s/^\([0-9]*\)6-/\15-/
+s/^\([0-9]*\)7-/\16-/
+s/^\([0-9]*\)8-/\17-/
+s/^\([0-9]*\)9-/\18-/
+s/^\([0-9]*\)0-/\1'9-/
+s/_/0/
+
+: scarry
+/0'/{
+ s//'9/
+ b scarry
+}
+/^'/{
+ b under
+}
+s/1'/0/
+s/2'/1/
+s/3'/2/
+s/4'/3/
+s/5'/4/
+s/6'/5/
+s/7'/6/
+s/8'/7/
+s/9'/8/
+
+b sub
diff --git a/usr.bin/sed/tests/multi_test.sh b/usr.bin/sed/tests/multi_test.sh
new file mode 100644
index 000000000000..1aef0524092a
--- /dev/null
+++ b/usr.bin/sed/tests/multi_test.sh
@@ -0,0 +1,491 @@
+#!/bin/sh -
+#
+# Copyright (c) 1992 Diomidis Spinellis.
+# 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.
+
+# sed Regression Tests
+#
+# The directory regress.test.out contains the expected test results
+#
+# These are the regression tests mostly created during the development
+# of the BSD sed. Each test should have a unique mark name, which is
+# used for naming the corresponding file in regress.multitest.out.
+
+SRCDIR=$(dirname $0)
+
+main()
+{
+ REGRESS=${SRCDIR}/regress.multitest.out
+ DICT=/usr/share/dict/words
+
+ awk 'END { for (i = 1; i < 15; i++) print "l1_" i}' </dev/null >lines1
+ awk 'END { for (i = 1; i < 10; i++) print "l2_" i}' </dev/null >lines2
+
+ echo "1..130"
+
+ exec 4>&1 5>&2
+ tests
+ exec 1>&4 2>&5
+
+ # Remove temporary files
+ rm -f current.out lines[1-4] script[1-2]
+}
+
+tests()
+{
+ SED=sed
+ MARK=0
+
+ test_args
+ test_addr
+ test_group
+ test_acid
+ test_branch
+ test_pattern
+ test_print
+ test_subst
+ test_error
+ # Handle the result of the last test
+ result
+}
+
+# Display a test's result
+result()
+{
+ if [ "$TODO" = '1' ] ; then
+ TODO='TODO '
+ else
+ TODO=''
+ fi
+ if ! [ -r $REGRESS/${TESTNAME} ] ; then
+ echo "Seeding $REGRESS/${TESTNAME} with current result" 1>&2
+ cp current.out $REGRESS/${TESTNAME}
+ fi
+ if diff -c $REGRESS/${TESTNAME} current.out ; then
+ echo "ok $MARK $TESTNAME # $TODO$OCOMMENT"
+ else
+ echo "not ok $MARK $TESTNAME # $TODO$OCOMMENT"
+ fi 1>&4 2>&5
+}
+
+# Mark the beginning of each test
+mark()
+{
+ [ $MARK -gt 0 ] && result
+ OCOMMENT=$COMMENT
+ MARK=`expr $MARK + 1`
+ TESTNAME=$1
+ exec 1>&4 2>&5
+ exec >"current.out"
+}
+
+test_args()
+{
+ COMMENT='Argument parsing - first type'
+ mark '1.1'
+ $SED 's/^/e1_/p' lines1
+ mark '1.2' ; $SED -n 's/^/e1_/p' lines1
+ mark '1.3'
+ $SED 's/^/e1_/p' <lines1
+ mark '1.4' ; $SED -n 's/^/e1_/p' <lines1
+ COMMENT='Argument parsing - second type'
+ mark '1.4.1'
+ $SED -e '' <lines1
+ echo 's/^/s1_/p' >script1
+ echo 's/^/s2_/p' >script2
+ mark '1.5'
+ $SED -f script1 lines1
+ mark '1.6'
+ $SED -f script1 <lines1
+ mark '1.7'
+ $SED -e 's/^/e1_/p' lines1
+ mark '1.8'
+ $SED -e 's/^/e1_/p' <lines1
+ mark '1.9' ; $SED -n -f script1 lines1
+ mark '1.10' ; $SED -n -f script1 <lines1
+ mark '1.11' ; $SED -n -e 's/^/e1_/p' lines1
+ mark '1.12'
+ $SED -n -e 's/^/e1_/p' <lines1
+ mark '1.13'
+ $SED -e 's/^/e1_/p' -e 's/^/e2_/p' lines1
+ mark '1.14'
+ $SED -f script1 -f script2 lines1
+ mark '1.15'
+ $SED -e 's/^/e1_/p' -f script1 lines1
+ mark '1.16'
+ $SED -e 's/^/e1_/p' lines1 lines1
+ # POSIX D11.2:11251
+ mark '1.17' ; $SED p <lines1 lines1
+cat >script1 <<EOF
+#n
+# A comment
+
+p
+EOF
+ mark '1.18' ; $SED -f script1 <lines1 lines1
+}
+
+test_addr()
+{
+ COMMENT='Address ranges'
+ mark '2.1' ; $SED -n -e '4p' lines1
+ mark '2.2' ; $SED -n -e '20p' lines1 lines2
+ mark '2.3' ; $SED -n -e '$p' lines1
+ mark '2.4' ; $SED -n -e '$p' lines1 lines2
+ mark '2.5' ; $SED -n -e '$a\
+hello' /dev/null
+ mark '2.6' ; $SED -n -e '$p' lines1 /dev/null lines2
+ # Should not print anything
+ mark '2.7' ; $SED -n -e '20p' lines1
+ mark '2.8' ; $SED -n -e '/NOTFOUND/p' lines1
+ mark '2.9' ; $SED -n '/l1_7/p' lines1
+ mark '2.10' ; $SED -n ' /l1_7/ p' lines1
+ mark '2.11' ; $SED -n '\_l1\_7_p' lines1
+ mark '2.12' ; $SED -n '1,4p' lines1
+ mark '2.13' ; $SED -n '1,$p' lines1 lines2
+ mark '2.14' ; $SED -n '1,/l2_9/p' lines1 lines2
+ mark '2.15' ; $SED -n '/4/,$p' lines1 lines2
+ mark '2.16' ; $SED -n '/4/,20p' lines1 lines2
+ mark '2.17' ; $SED -n '/4/,/10/p' lines1 lines2
+ mark '2.18' ; $SED -n '/l2_3/,/l1_8/p' lines1 lines2
+ mark '2.19' ; $SED -n '12,3p' lines1 lines2
+ mark '2.20' ; $SED -n '/l1_7/,3p' lines1 lines2
+ mark '2.21' ; $SED -n '13,+4p' lines1 lines2
+ mark '2.22' ; $SED -n '/l1_6/,+2p' lines1 lines2
+ # For PR bin/192108
+ mark '2.23'; $SED -n '12,+1p' lines1
+}
+
+test_group()
+{
+ COMMENT='Brace and other grouping'
+ mark '3.1' ; $SED -e '
+4,12 {
+ s/^/^/
+ s/$/$/
+ s/_/T/
+}' lines1
+ mark '3.2' ; $SED -e '
+4,12 {
+ s/^/^/
+ /6/,/10/ {
+ s/$/$/
+ /8/ s/_/T/
+ }
+}' lines1
+ mark '3.3' ; $SED -e '
+4,12 !{
+ s/^/^/
+ /6/,/10/ !{
+ s/$/$/
+ /8/ !s/_/T/
+ }
+}' lines1
+ mark '3.4' ; $SED -e '4,12!s/^/^/' lines1
+}
+
+test_acid()
+{
+ COMMENT='Commands a c d and i'
+ mark '4.1' ; $SED -n -e '
+s/^/before_i/p
+20i\
+inserted
+s/^/after_i/p
+' lines1 lines2
+ mark '4.2' ; $SED -n -e '
+5,12s/^/5-12/
+s/^/before_a/p
+/5-12/a\
+appended
+s/^/after_a/p
+' lines1 lines2
+ mark '4.3'
+ $SED -n -e '
+s/^/^/p
+/l1_/a\
+appended
+8,10N
+s/$/$/p
+' lines1 lines2
+ mark '4.4' ; $SED -n -e '
+c\
+hello
+' lines1
+ mark '4.5' ; $SED -n -e '
+8c\
+hello
+' lines1
+ mark '4.6' ; $SED -n -e '
+3,14c\
+hello
+' lines1
+# SunOS and GNU sed behave differently. We follow POSIX
+ mark '4.7' ; $SED -n -e '
+8,3c\
+hello
+' lines1
+ mark '4.8' ; $SED d <lines1
+}
+
+test_branch()
+{
+ COMMENT='Labels and branching'
+ mark '5.1' ; $SED -n -e '
+b label4
+:label3
+s/^/label3_/p
+b end
+:label4
+2,12b label1
+b label2
+:label1
+s/^/label1_/p
+b
+:label2
+s/^/label2_/p
+b label3
+:end
+' lines1
+ mark '5.2'
+ $SED -n -e '
+s/l1_/l2_/
+t ok
+b
+:ok
+s/^/tested /p
+' lines1 lines2
+# SunOS and GNU sed behave as follows: lines 9-$ aren't printed at all
+ mark '5.3' ; $SED -n -e '
+5,8b inside
+1,5 {
+ s/^/^/p
+ :inside
+ s/$/$/p
+}
+' lines1
+# Check that t clears the substitution done flag
+ mark '5.4' ; $SED -n -e '
+1,8s/^/^/
+t l1
+:l1
+t l2
+s/$/$/p
+b
+:l2
+s/^/ERROR/
+' lines1
+# Check that reading a line clears the substitution done flag
+ mark '5.5'
+ $SED -n -e '
+t l2
+1,8s/^/^/p
+2,7N
+b
+:l2
+s/^/ERROR/p
+' lines1
+ mark '5.6' ; $SED 5q lines1
+ mark '5.7' ; $SED -e '
+5i\
+hello
+5q' lines1
+# Branch across block boundary
+ mark '5.8' ; $SED -e '
+{
+:b
+}
+s/l/m/
+tb' lines1
+}
+
+test_pattern()
+{
+COMMENT='Pattern space commands'
+# Check that the pattern space is deleted
+ mark '6.1' ; $SED -n -e '
+c\
+changed
+p
+' lines1
+ mark '6.2' ; $SED -n -e '
+4d
+p
+' lines1
+ mark '6.3'
+ $SED -e 'N;N;N;D' lines1
+ mark '6.4' ; $SED -e '
+2h
+3H
+4g
+5G
+6x
+6p
+6x
+6p
+' lines1
+ mark '6.5' ; $SED -e '4n' lines1
+ mark '6.6' ; $SED -n -e '4n' lines1
+}
+
+test_print()
+{
+ COMMENT='Print and file routines'
+ awk 'END {for (i = 1; i < 256; i++) printf("%c", i);print "\n"}' \
+ </dev/null >lines3
+ # GNU and SunOS sed behave differently here
+ mark '7.1'
+ $SED -n l lines3
+ mark '7.2' ; $SED -e '/l2_/=' lines1 lines2
+ rm -f lines4
+ mark '7.3' ; $SED -e '3,12w lines4' lines1
+ COMMENT='w results'
+ cat lines4
+ mark '7.4' ; $SED -e '4r lines2' lines1
+ mark '7.5' ; $SED -e '5r /dev/dds' lines1
+ mark '7.6' ; $SED -e '6r /dev/null' lines1
+ mark '7.7'
+ sed '200q' $DICT | sed 's$.*$s/^/&/w tmpdir/&$' >script1
+ rm -rf tmpdir
+ mkdir tmpdir
+ $SED -f script1 lines1
+ cat tmpdir/*
+ rm -rf tmpdir
+ mark '7.8'
+ echo line1 > lines3
+ echo "" >> lines3
+ $SED -n -e '$p' lines3 /dev/null
+
+}
+
+test_subst()
+{
+ COMMENT='Substitution commands'
+ mark '8.1' ; $SED -e 's/./X/g' lines1
+ mark '8.2' ; $SED -e 's,.,X,g' lines1
+# SunOS sed thinks we are escaping . as wildcard, not as separator
+ mark '8.3'
+ $SED -e 's.\..X.g' lines1
+ mark '8.4' ; $SED -e 's/[\/]/Q/' lines1
+ mark '8.5' ; $SED -e 's_\__X_' lines1
+ mark '8.6' ; $SED -e 's/./(&)/g' lines1
+ mark '8.7' ; $SED -e 's/./(\&)/g' lines1
+ mark '8.8' ; $SED -e 's/\(.\)\(.\)\(.\)/x\3x\2x\1/g' lines1
+ mark '8.9' ; $SED -e 's/_/u0\
+u1\
+u2/g' lines1
+ mark '8.10'
+ $SED -e 's/./X/4' lines1
+ rm -f lines4
+ mark '8.11' ; $SED -e 's/1/X/w lines4' lines1
+ COMMENT='s wfile results'
+ cat lines4
+ mark '8.12' ; $SED -e 's/[123]/X/g' lines1
+ mark '8.13' ; $SED -e 'y/0123456789/9876543210/' lines1
+ mark '8.14' ;
+ $SED -e 'y10\123456789198765432\101' lines1
+ mark '8.15' ; $SED -e '1N;2y/\n/X/' lines1
+ mark '8.16'
+ echo 'eeefff' | $SED -e '
+ p
+ s/e/X/p
+ :x
+ s//Y/p
+ # Establish limit counter in the hold space
+ # GNU sed version 3.02 enters into an infinite loop here
+ x
+ /.\{10\}/ {
+ s/.*/ERROR/
+ b
+ }
+ s/.*/&./
+ x
+ /f/bx
+ '
+ # POSIX does not say that this should work,
+ # but it does for GNU, BSD, and SunOS
+ mark '8.17' ; $SED -e 's/[/]/Q/' lines1
+
+ COMMENT='[ as an s delimiter and its escapes'
+ mark '8.18' ; $SED -e 's[_[X[' lines1
+ # This is a matter of interpretation
+ # POSIX 1003.1, 2004 says "Within the BRE and the replacement,
+ # the BRE delimiter itself can be used as a *literal* character
+ # if it is preceded by a backslash"
+ # SunOS 5.1 /usr/bin/sed and Mac OS X follow the literal POSIX
+ # interpretation.
+ # GNU sed version 4.1.5 treats \[ as the beginning of a character
+ # set specification (both with --posix and without).
+ mark '8.19' ; sed 's/l/[/' lines1 | $SED -e 's[\[.[X['
+ mark '8.20' ; sed 's/l/[/' lines1 | $SED -e 's[\[.[X\[['
+ COMMENT='\ in y command'
+ mark '8.21'
+ echo 'a\b(c' |
+ $SED 'y%ABCDEFGHIJKLMNOPQRSTUVWXYZ, /\\()"%abcdefghijklmnopqrstuvwxyz,------%'
+ COMMENT='\n in a character class and a BRE'
+ mark '8.22' ; (echo 1; echo 2) | $SED -n '1{;N;s/[\n]/X/;p;}'
+ mark '8.23' ; (echo 1; echo 2) | $SED -n '1{;N;s/\n/X/;p;}'
+}
+
+test_error()
+{
+ COMMENT='Error cases'
+ mark '9.1' ; $SED -x 2>/dev/null ; echo $?
+ mark '9.2' ; $SED -f 2>/dev/null ; echo $?
+ mark '9.3' ; $SED -e 2>/dev/null ; echo $?
+ mark '9.4' ; $SED -f /dev/xyzzyxyzy 2>/dev/null ; echo $?
+ mark '9.5' ; $SED p /dev/xyzzyxyzy 2>/dev/null ; echo $?
+ mark '9.6' ; $SED -f /bin/sh 2>/dev/null ; echo $?
+ mark '9.7' ; $SED '{' 2>/dev/null ; echo $?
+ mark '9.8' ; $SED '{' 2>/dev/null ; echo $?
+ mark '9.9' ; $SED '/hello/' 2>/dev/null ; echo $?
+ mark '9.10' ; $SED '1,/hello/' 2>/dev/null ; echo $?
+ mark '9.11' ; $SED -e '-5p' 2>/dev/null ; echo $?
+ mark '9.12' ; $SED '/jj' 2>/dev/null ; echo $?
+ mark '9.13' ; $SED 'a hello' 2>/dev/null ; echo $?
+ mark '9.14' ; $SED 'a \ hello' 2>/dev/null ; echo $?
+ mark '9.15' ; $SED 'b foo' 2>/dev/null ; echo $?
+ mark '9.16' ; $SED 'd hello' 2>/dev/null ; echo $?
+ mark '9.17' ; $SED 's/aa' 2>/dev/null ; echo $?
+ mark '9.18' ; $SED 's/aa/' 2>/dev/null ; echo $?
+ mark '9.19' ; $SED 's/a/b' 2>/dev/null ; echo $?
+ mark '9.20' ; $SED 's/a/b/c/d' 2>/dev/null ; echo $?
+ mark '9.21' ; $SED 's/a/b/ 1 2' 2>/dev/null ; echo $?
+ mark '9.22' ; $SED 's/a/b/ 1 g' 2>/dev/null ; echo $?
+ mark '9.23' ; $SED 's/a/b/w' 2>/dev/null ; echo $?
+ mark '9.24' ; $SED 'y/aa' 2>/dev/null ; echo $?
+ mark '9.25' ; $SED 'y/aa/b/' 2>/dev/null ; echo $?
+ mark '9.26' ; $SED 'y/aa/' 2>/dev/null ; echo $?
+ mark '9.27' ; $SED 'y/a/b' 2>/dev/null ; echo $?
+ mark '9.28' ; $SED 'y/a/b/c/d' 2>/dev/null ; echo $?
+ mark '9.29' ; $SED '!' 2>/dev/null ; echo $?
+ mark '9.30' ; $SED supercalifrangolisticexprialidociussupercalifrangolisticexcius 2>/dev/null ; echo $?
+ mark '9.31' ; $SED '' /dev/null 2>/dev/null ; echo $?
+}
+
+main
diff --git a/usr.bin/sed/tests/regress.G.out b/usr.bin/sed/tests/regress.G.out
new file mode 100644
index 000000000000..49c277c1bb21
--- /dev/null
+++ b/usr.bin/sed/tests/regress.G.out
@@ -0,0 +1,8 @@
+input
+
+data
+
+for validation
+
+of sed(1)
+
diff --git a/usr.bin/sed/tests/regress.P.out b/usr.bin/sed/tests/regress.P.out
new file mode 100644
index 000000000000..4d3284f8bdd2
--- /dev/null
+++ b/usr.bin/sed/tests/regress.P.out
@@ -0,0 +1,8 @@
+input
+input
+data
+data
+for validation
+for validation
+of sed(1)
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.b2a.out b/usr.bin/sed/tests/regress.b2a.out
new file mode 100644
index 000000000000..a44df51a1b4f
--- /dev/null
+++ b/usr.bin/sed/tests/regress.b2a.out
@@ -0,0 +1,3 @@
+data
+for validation
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.bcb.out b/usr.bin/sed/tests/regress.bcb.out
new file mode 100644
index 000000000000..2a26e6a31193
--- /dev/null
+++ b/usr.bin/sed/tests/regress.bcb.out
@@ -0,0 +1,4 @@
+input
+data
+for validation
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.c0.out b/usr.bin/sed/tests/regress.c0.out
new file mode 100644
index 000000000000..a1f894413ef3
--- /dev/null
+++ b/usr.bin/sed/tests/regress.c0.out
@@ -0,0 +1,4 @@
+foo
+foo
+foo
+foo
diff --git a/usr.bin/sed/tests/regress.c1.out b/usr.bin/sed/tests/regress.c1.out
new file mode 100644
index 000000000000..21af01e3aaac
--- /dev/null
+++ b/usr.bin/sed/tests/regress.c1.out
@@ -0,0 +1,4 @@
+input
+data
+for validation
+foo
diff --git a/usr.bin/sed/tests/regress.c2.out b/usr.bin/sed/tests/regress.c2.out
new file mode 100644
index 000000000000..6c54a8d978ff
--- /dev/null
+++ b/usr.bin/sed/tests/regress.c2.out
@@ -0,0 +1,3 @@
+input
+data
+foo
diff --git a/usr.bin/sed/tests/regress.c3.out b/usr.bin/sed/tests/regress.c3.out
new file mode 100644
index 000000000000..6c54a8d978ff
--- /dev/null
+++ b/usr.bin/sed/tests/regress.c3.out
@@ -0,0 +1,3 @@
+input
+data
+foo
diff --git a/usr.bin/sed/tests/regress.hanoi.out b/usr.bin/sed/tests/regress.hanoi.out
new file mode 100644
index 000000000000..ec39ea263827
--- /dev/null
+++ b/usr.bin/sed/tests/regress.hanoi.out
@@ -0,0 +1,17 @@
+:abcd: : :
+:abc : :d :
+:ab :c :d :
+:ab :cd : :
+:a :cd :b :
+:ad :c :b :
+:ad : :bc :
+:a : :bcd :
+: :a :bcd :
+: :ad :bc :
+:c :ad :b :
+:cd :a :b :
+:cd :ab : :
+:c :ab :d :
+: :abc :d :
+: :abcd: :
+Done! Try another, or end with ^D.
diff --git a/usr.bin/sed/tests/regress.icase1.out b/usr.bin/sed/tests/regress.icase1.out
new file mode 100644
index 000000000000..a610a0bd958f
--- /dev/null
+++ b/usr.bin/sed/tests/regress.icase1.out
@@ -0,0 +1,3 @@
+input
+data
+for validation
diff --git a/usr.bin/sed/tests/regress.icase2.out b/usr.bin/sed/tests/regress.icase2.out
new file mode 100644
index 000000000000..b803373b6a5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.icase2.out
@@ -0,0 +1,4 @@
+input
+data
+for validation
+of Foo(1)
diff --git a/usr.bin/sed/tests/regress.icase3.out b/usr.bin/sed/tests/regress.icase3.out
new file mode 100644
index 000000000000..2a26e6a31193
--- /dev/null
+++ b/usr.bin/sed/tests/regress.icase3.out
@@ -0,0 +1,4 @@
+input
+data
+for validation
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.icase4.out b/usr.bin/sed/tests/regress.icase4.out
new file mode 100644
index 000000000000..b803373b6a5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.icase4.out
@@ -0,0 +1,4 @@
+input
+data
+for validation
+of Foo(1)
diff --git a/usr.bin/sed/tests/regress.in b/usr.bin/sed/tests/regress.in
new file mode 100644
index 000000000000..2a26e6a31193
--- /dev/null
+++ b/usr.bin/sed/tests/regress.in
@@ -0,0 +1,4 @@
+input
+data
+for validation
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.math.out b/usr.bin/sed/tests/regress.math.out
new file mode 100644
index 000000000000..3fdcd7c44cb1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.math.out
@@ -0,0 +1 @@
+67
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.1 b/usr.bin/sed/tests/regress.multitest.out/1.1
new file mode 100644
index 000000000000..70fd43b52148
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.1
@@ -0,0 +1,28 @@
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.10 b/usr.bin/sed/tests/regress.multitest.out/1.10
new file mode 100644
index 000000000000..44f4ec3c9f96
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.10
@@ -0,0 +1,14 @@
+s1_l1_1
+s1_l1_2
+s1_l1_3
+s1_l1_4
+s1_l1_5
+s1_l1_6
+s1_l1_7
+s1_l1_8
+s1_l1_9
+s1_l1_10
+s1_l1_11
+s1_l1_12
+s1_l1_13
+s1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.11 b/usr.bin/sed/tests/regress.multitest.out/1.11
new file mode 100644
index 000000000000..7af945dc059e
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.11
@@ -0,0 +1,14 @@
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.12 b/usr.bin/sed/tests/regress.multitest.out/1.12
new file mode 100644
index 000000000000..7af945dc059e
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.12
@@ -0,0 +1,14 @@
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.13 b/usr.bin/sed/tests/regress.multitest.out/1.13
new file mode 100644
index 000000000000..90582c88b033
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.13
@@ -0,0 +1,42 @@
+e1_l1_1
+e2_e1_l1_1
+e2_e1_l1_1
+e1_l1_2
+e2_e1_l1_2
+e2_e1_l1_2
+e1_l1_3
+e2_e1_l1_3
+e2_e1_l1_3
+e1_l1_4
+e2_e1_l1_4
+e2_e1_l1_4
+e1_l1_5
+e2_e1_l1_5
+e2_e1_l1_5
+e1_l1_6
+e2_e1_l1_6
+e2_e1_l1_6
+e1_l1_7
+e2_e1_l1_7
+e2_e1_l1_7
+e1_l1_8
+e2_e1_l1_8
+e2_e1_l1_8
+e1_l1_9
+e2_e1_l1_9
+e2_e1_l1_9
+e1_l1_10
+e2_e1_l1_10
+e2_e1_l1_10
+e1_l1_11
+e2_e1_l1_11
+e2_e1_l1_11
+e1_l1_12
+e2_e1_l1_12
+e2_e1_l1_12
+e1_l1_13
+e2_e1_l1_13
+e2_e1_l1_13
+e1_l1_14
+e2_e1_l1_14
+e2_e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.14 b/usr.bin/sed/tests/regress.multitest.out/1.14
new file mode 100644
index 000000000000..fd7827485170
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.14
@@ -0,0 +1,42 @@
+s1_l1_1
+s2_s1_l1_1
+s2_s1_l1_1
+s1_l1_2
+s2_s1_l1_2
+s2_s1_l1_2
+s1_l1_3
+s2_s1_l1_3
+s2_s1_l1_3
+s1_l1_4
+s2_s1_l1_4
+s2_s1_l1_4
+s1_l1_5
+s2_s1_l1_5
+s2_s1_l1_5
+s1_l1_6
+s2_s1_l1_6
+s2_s1_l1_6
+s1_l1_7
+s2_s1_l1_7
+s2_s1_l1_7
+s1_l1_8
+s2_s1_l1_8
+s2_s1_l1_8
+s1_l1_9
+s2_s1_l1_9
+s2_s1_l1_9
+s1_l1_10
+s2_s1_l1_10
+s2_s1_l1_10
+s1_l1_11
+s2_s1_l1_11
+s2_s1_l1_11
+s1_l1_12
+s2_s1_l1_12
+s2_s1_l1_12
+s1_l1_13
+s2_s1_l1_13
+s2_s1_l1_13
+s1_l1_14
+s2_s1_l1_14
+s2_s1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.15 b/usr.bin/sed/tests/regress.multitest.out/1.15
new file mode 100644
index 000000000000..7b3700c35617
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.15
@@ -0,0 +1,42 @@
+e1_l1_1
+s1_e1_l1_1
+s1_e1_l1_1
+e1_l1_2
+s1_e1_l1_2
+s1_e1_l1_2
+e1_l1_3
+s1_e1_l1_3
+s1_e1_l1_3
+e1_l1_4
+s1_e1_l1_4
+s1_e1_l1_4
+e1_l1_5
+s1_e1_l1_5
+s1_e1_l1_5
+e1_l1_6
+s1_e1_l1_6
+s1_e1_l1_6
+e1_l1_7
+s1_e1_l1_7
+s1_e1_l1_7
+e1_l1_8
+s1_e1_l1_8
+s1_e1_l1_8
+e1_l1_9
+s1_e1_l1_9
+s1_e1_l1_9
+e1_l1_10
+s1_e1_l1_10
+s1_e1_l1_10
+e1_l1_11
+s1_e1_l1_11
+s1_e1_l1_11
+e1_l1_12
+s1_e1_l1_12
+s1_e1_l1_12
+e1_l1_13
+s1_e1_l1_13
+s1_e1_l1_13
+e1_l1_14
+s1_e1_l1_14
+s1_e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.16 b/usr.bin/sed/tests/regress.multitest.out/1.16
new file mode 100644
index 000000000000..2bfa3fecb86f
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.16
@@ -0,0 +1,56 @@
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.17 b/usr.bin/sed/tests/regress.multitest.out/1.17
new file mode 100644
index 000000000000..0833b5539330
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.17
@@ -0,0 +1,28 @@
+l1_1
+l1_1
+l1_2
+l1_2
+l1_3
+l1_3
+l1_4
+l1_4
+l1_5
+l1_5
+l1_6
+l1_6
+l1_7
+l1_7
+l1_8
+l1_8
+l1_9
+l1_9
+l1_10
+l1_10
+l1_11
+l1_11
+l1_12
+l1_12
+l1_13
+l1_13
+l1_14
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.18 b/usr.bin/sed/tests/regress.multitest.out/1.18
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.18
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.2 b/usr.bin/sed/tests/regress.multitest.out/1.2
new file mode 100644
index 000000000000..7af945dc059e
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.2
@@ -0,0 +1,14 @@
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.3 b/usr.bin/sed/tests/regress.multitest.out/1.3
new file mode 100644
index 000000000000..70fd43b52148
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.3
@@ -0,0 +1,28 @@
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.4 b/usr.bin/sed/tests/regress.multitest.out/1.4
new file mode 100644
index 000000000000..7af945dc059e
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.4
@@ -0,0 +1,14 @@
+e1_l1_1
+e1_l1_2
+e1_l1_3
+e1_l1_4
+e1_l1_5
+e1_l1_6
+e1_l1_7
+e1_l1_8
+e1_l1_9
+e1_l1_10
+e1_l1_11
+e1_l1_12
+e1_l1_13
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.4.1 b/usr.bin/sed/tests/regress.multitest.out/1.4.1
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.4.1
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.5 b/usr.bin/sed/tests/regress.multitest.out/1.5
new file mode 100644
index 000000000000..dfd85f722769
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.5
@@ -0,0 +1,28 @@
+s1_l1_1
+s1_l1_1
+s1_l1_2
+s1_l1_2
+s1_l1_3
+s1_l1_3
+s1_l1_4
+s1_l1_4
+s1_l1_5
+s1_l1_5
+s1_l1_6
+s1_l1_6
+s1_l1_7
+s1_l1_7
+s1_l1_8
+s1_l1_8
+s1_l1_9
+s1_l1_9
+s1_l1_10
+s1_l1_10
+s1_l1_11
+s1_l1_11
+s1_l1_12
+s1_l1_12
+s1_l1_13
+s1_l1_13
+s1_l1_14
+s1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.6 b/usr.bin/sed/tests/regress.multitest.out/1.6
new file mode 100644
index 000000000000..dfd85f722769
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.6
@@ -0,0 +1,28 @@
+s1_l1_1
+s1_l1_1
+s1_l1_2
+s1_l1_2
+s1_l1_3
+s1_l1_3
+s1_l1_4
+s1_l1_4
+s1_l1_5
+s1_l1_5
+s1_l1_6
+s1_l1_6
+s1_l1_7
+s1_l1_7
+s1_l1_8
+s1_l1_8
+s1_l1_9
+s1_l1_9
+s1_l1_10
+s1_l1_10
+s1_l1_11
+s1_l1_11
+s1_l1_12
+s1_l1_12
+s1_l1_13
+s1_l1_13
+s1_l1_14
+s1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.7 b/usr.bin/sed/tests/regress.multitest.out/1.7
new file mode 100644
index 000000000000..70fd43b52148
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.7
@@ -0,0 +1,28 @@
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.8 b/usr.bin/sed/tests/regress.multitest.out/1.8
new file mode 100644
index 000000000000..70fd43b52148
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.8
@@ -0,0 +1,28 @@
+e1_l1_1
+e1_l1_1
+e1_l1_2
+e1_l1_2
+e1_l1_3
+e1_l1_3
+e1_l1_4
+e1_l1_4
+e1_l1_5
+e1_l1_5
+e1_l1_6
+e1_l1_6
+e1_l1_7
+e1_l1_7
+e1_l1_8
+e1_l1_8
+e1_l1_9
+e1_l1_9
+e1_l1_10
+e1_l1_10
+e1_l1_11
+e1_l1_11
+e1_l1_12
+e1_l1_12
+e1_l1_13
+e1_l1_13
+e1_l1_14
+e1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/1.9 b/usr.bin/sed/tests/regress.multitest.out/1.9
new file mode 100644
index 000000000000..44f4ec3c9f96
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/1.9
@@ -0,0 +1,14 @@
+s1_l1_1
+s1_l1_2
+s1_l1_3
+s1_l1_4
+s1_l1_5
+s1_l1_6
+s1_l1_7
+s1_l1_8
+s1_l1_9
+s1_l1_10
+s1_l1_11
+s1_l1_12
+s1_l1_13
+s1_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.1 b/usr.bin/sed/tests/regress.multitest.out/2.1
new file mode 100644
index 000000000000..a7c92f0e1341
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.1
@@ -0,0 +1 @@
+l1_4
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.10 b/usr.bin/sed/tests/regress.multitest.out/2.10
new file mode 100644
index 000000000000..8e6f085d44aa
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.10
@@ -0,0 +1 @@
+l1_7
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.11 b/usr.bin/sed/tests/regress.multitest.out/2.11
new file mode 100644
index 000000000000..8e6f085d44aa
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.11
@@ -0,0 +1 @@
+l1_7
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.12 b/usr.bin/sed/tests/regress.multitest.out/2.12
new file mode 100644
index 000000000000..ddd4976288f1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.12
@@ -0,0 +1,4 @@
+l1_1
+l1_2
+l1_3
+l1_4
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.13 b/usr.bin/sed/tests/regress.multitest.out/2.13
new file mode 100644
index 000000000000..d08d35c6bb19
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.13
@@ -0,0 +1,23 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.14 b/usr.bin/sed/tests/regress.multitest.out/2.14
new file mode 100644
index 000000000000..d08d35c6bb19
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.14
@@ -0,0 +1,23 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.15 b/usr.bin/sed/tests/regress.multitest.out/2.15
new file mode 100644
index 000000000000..1f20a52365b4
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.15
@@ -0,0 +1,20 @@
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.16 b/usr.bin/sed/tests/regress.multitest.out/2.16
new file mode 100644
index 000000000000..4d8dc1e35994
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.16
@@ -0,0 +1,17 @@
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.17 b/usr.bin/sed/tests/regress.multitest.out/2.17
new file mode 100644
index 000000000000..df7978fd5e0f
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.17
@@ -0,0 +1,17 @@
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_14
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.18 b/usr.bin/sed/tests/regress.multitest.out/2.18
new file mode 100644
index 000000000000..c4d558b1d877
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.18
@@ -0,0 +1,7 @@
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.19 b/usr.bin/sed/tests/regress.multitest.out/2.19
new file mode 100644
index 000000000000..7fb81db4511e
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.19
@@ -0,0 +1 @@
+l1_12
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.2 b/usr.bin/sed/tests/regress.multitest.out/2.2
new file mode 100644
index 000000000000..fe925b0ab234
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.2
@@ -0,0 +1 @@
+l2_6
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.20 b/usr.bin/sed/tests/regress.multitest.out/2.20
new file mode 100644
index 000000000000..8e6f085d44aa
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.20
@@ -0,0 +1 @@
+l1_7
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.21 b/usr.bin/sed/tests/regress.multitest.out/2.21
new file mode 100644
index 000000000000..1a9e0660615a
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.21
@@ -0,0 +1,5 @@
+l1_13
+l1_14
+l2_1
+l2_2
+l2_3
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.22 b/usr.bin/sed/tests/regress.multitest.out/2.22
new file mode 100644
index 000000000000..b1827918b488
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.22
@@ -0,0 +1,3 @@
+l1_6
+l1_7
+l1_8
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.23 b/usr.bin/sed/tests/regress.multitest.out/2.23
new file mode 100644
index 000000000000..543c0574e26d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.23
@@ -0,0 +1,2 @@
+l1_12
+l1_13
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.3 b/usr.bin/sed/tests/regress.multitest.out/2.3
new file mode 100644
index 000000000000..6165ce8749cd
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.3
@@ -0,0 +1 @@
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.4 b/usr.bin/sed/tests/regress.multitest.out/2.4
new file mode 100644
index 000000000000..1502f007541d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.4
@@ -0,0 +1 @@
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.5 b/usr.bin/sed/tests/regress.multitest.out/2.5
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.5
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.6 b/usr.bin/sed/tests/regress.multitest.out/2.6
new file mode 100644
index 000000000000..1502f007541d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.6
@@ -0,0 +1 @@
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.7 b/usr.bin/sed/tests/regress.multitest.out/2.7
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.7
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.8 b/usr.bin/sed/tests/regress.multitest.out/2.8
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.8
diff --git a/usr.bin/sed/tests/regress.multitest.out/2.9 b/usr.bin/sed/tests/regress.multitest.out/2.9
new file mode 100644
index 000000000000..8e6f085d44aa
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/2.9
@@ -0,0 +1 @@
+l1_7
diff --git a/usr.bin/sed/tests/regress.multitest.out/3.1 b/usr.bin/sed/tests/regress.multitest.out/3.1
new file mode 100644
index 000000000000..f963b03f1201
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/3.1
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+^l1T4$
+^l1T5$
+^l1T6$
+^l1T7$
+^l1T8$
+^l1T9$
+^l1T10$
+^l1T11$
+^l1T12$
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/3.2 b/usr.bin/sed/tests/regress.multitest.out/3.2
new file mode 100644
index 000000000000..488e94f6bd79
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/3.2
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+^l1_4
+^l1_5
+^l1_6$
+^l1_7$
+^l1T8$
+^l1_9$
+^l1_10$
+^l1_11
+^l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/3.3 b/usr.bin/sed/tests/regress.multitest.out/3.3
new file mode 100644
index 000000000000..5b15dae52aca
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/3.3
@@ -0,0 +1,14 @@
+^l1T1$
+^l1T2$
+^l1T3$
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+^l1T13$
+^l1T14$
diff --git a/usr.bin/sed/tests/regress.multitest.out/3.4 b/usr.bin/sed/tests/regress.multitest.out/3.4
new file mode 100644
index 000000000000..67f03ef62d13
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/3.4
@@ -0,0 +1,14 @@
+^l1_1
+^l1_2
+^l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+^l1_13
+^l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.1 b/usr.bin/sed/tests/regress.multitest.out/4.1
new file mode 100644
index 000000000000..455093ce5d59
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.1
@@ -0,0 +1,47 @@
+before_il1_1
+after_ibefore_il1_1
+before_il1_2
+after_ibefore_il1_2
+before_il1_3
+after_ibefore_il1_3
+before_il1_4
+after_ibefore_il1_4
+before_il1_5
+after_ibefore_il1_5
+before_il1_6
+after_ibefore_il1_6
+before_il1_7
+after_ibefore_il1_7
+before_il1_8
+after_ibefore_il1_8
+before_il1_9
+after_ibefore_il1_9
+before_il1_10
+after_ibefore_il1_10
+before_il1_11
+after_ibefore_il1_11
+before_il1_12
+after_ibefore_il1_12
+before_il1_13
+after_ibefore_il1_13
+before_il1_14
+after_ibefore_il1_14
+before_il2_1
+after_ibefore_il2_1
+before_il2_2
+after_ibefore_il2_2
+before_il2_3
+after_ibefore_il2_3
+before_il2_4
+after_ibefore_il2_4
+before_il2_5
+after_ibefore_il2_5
+before_il2_6
+inserted
+after_ibefore_il2_6
+before_il2_7
+after_ibefore_il2_7
+before_il2_8
+after_ibefore_il2_8
+before_il2_9
+after_ibefore_il2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.2 b/usr.bin/sed/tests/regress.multitest.out/4.2
new file mode 100644
index 000000000000..4161c1c087fc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.2
@@ -0,0 +1,54 @@
+before_al1_1
+after_abefore_al1_1
+before_al1_2
+after_abefore_al1_2
+before_al1_3
+after_abefore_al1_3
+before_al1_4
+after_abefore_al1_4
+before_a5-12l1_5
+after_abefore_a5-12l1_5
+appended
+before_a5-12l1_6
+after_abefore_a5-12l1_6
+appended
+before_a5-12l1_7
+after_abefore_a5-12l1_7
+appended
+before_a5-12l1_8
+after_abefore_a5-12l1_8
+appended
+before_a5-12l1_9
+after_abefore_a5-12l1_9
+appended
+before_a5-12l1_10
+after_abefore_a5-12l1_10
+appended
+before_a5-12l1_11
+after_abefore_a5-12l1_11
+appended
+before_a5-12l1_12
+after_abefore_a5-12l1_12
+appended
+before_al1_13
+after_abefore_al1_13
+before_al1_14
+after_abefore_al1_14
+before_al2_1
+after_abefore_al2_1
+before_al2_2
+after_abefore_al2_2
+before_al2_3
+after_abefore_al2_3
+before_al2_4
+after_abefore_al2_4
+before_al2_5
+after_abefore_al2_5
+before_al2_6
+after_abefore_al2_6
+before_al2_7
+after_abefore_al2_7
+before_al2_8
+after_abefore_al2_8
+before_al2_9
+after_abefore_al2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.3 b/usr.bin/sed/tests/regress.multitest.out/4.3
new file mode 100644
index 000000000000..ccfa19463ef2
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.3
@@ -0,0 +1,56 @@
+^l1_1
+^l1_1$
+appended
+^l1_2
+^l1_2$
+appended
+^l1_3
+^l1_3$
+appended
+^l1_4
+^l1_4$
+appended
+^l1_5
+^l1_5$
+appended
+^l1_6
+^l1_6$
+appended
+^l1_7
+^l1_7$
+appended
+^l1_8
+appended
+^l1_8
+l1_9$
+^l1_10
+appended
+^l1_10
+l1_11$
+^l1_12
+^l1_12$
+appended
+^l1_13
+^l1_13$
+appended
+^l1_14
+^l1_14$
+appended
+^l2_1
+^l2_1$
+^l2_2
+^l2_2$
+^l2_3
+^l2_3$
+^l2_4
+^l2_4$
+^l2_5
+^l2_5$
+^l2_6
+^l2_6$
+^l2_7
+^l2_7$
+^l2_8
+^l2_8$
+^l2_9
+^l2_9$
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.4 b/usr.bin/sed/tests/regress.multitest.out/4.4
new file mode 100644
index 000000000000..94e9a6d3a318
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.4
@@ -0,0 +1,14 @@
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
+hello
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.5 b/usr.bin/sed/tests/regress.multitest.out/4.5
new file mode 100644
index 000000000000..ce013625030b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.5
@@ -0,0 +1 @@
+hello
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.6 b/usr.bin/sed/tests/regress.multitest.out/4.6
new file mode 100644
index 000000000000..ce013625030b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.6
@@ -0,0 +1 @@
+hello
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.7 b/usr.bin/sed/tests/regress.multitest.out/4.7
new file mode 100644
index 000000000000..ce013625030b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.7
@@ -0,0 +1 @@
+hello
diff --git a/usr.bin/sed/tests/regress.multitest.out/4.8 b/usr.bin/sed/tests/regress.multitest.out/4.8
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/4.8
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.1 b/usr.bin/sed/tests/regress.multitest.out/5.1
new file mode 100644
index 000000000000..ac9202e60889
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.1
@@ -0,0 +1,17 @@
+label2_l1_1
+label3_label2_l1_1
+label1_l1_2
+label1_l1_3
+label1_l1_4
+label1_l1_5
+label1_l1_6
+label1_l1_7
+label1_l1_8
+label1_l1_9
+label1_l1_10
+label1_l1_11
+label1_l1_12
+label2_l1_13
+label3_label2_l1_13
+label2_l1_14
+label3_label2_l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.2 b/usr.bin/sed/tests/regress.multitest.out/5.2
new file mode 100644
index 000000000000..ec339f43a94b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.2
@@ -0,0 +1,14 @@
+tested l2_1
+tested l2_2
+tested l2_3
+tested l2_4
+tested l2_5
+tested l2_6
+tested l2_7
+tested l2_8
+tested l2_9
+tested l2_10
+tested l2_11
+tested l2_12
+tested l2_13
+tested l2_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.3 b/usr.bin/sed/tests/regress.multitest.out/5.3
new file mode 100644
index 000000000000..e1ddb547a688
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.3
@@ -0,0 +1,12 @@
+^l1_1
+^l1_1$
+^l1_2
+^l1_2$
+^l1_3
+^l1_3$
+^l1_4
+^l1_4$
+l1_5$
+l1_6$
+l1_7$
+l1_8$
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.4 b/usr.bin/sed/tests/regress.multitest.out/5.4
new file mode 100644
index 000000000000..a9ec85bf470b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.4
@@ -0,0 +1,14 @@
+^l1_1$
+^l1_2$
+^l1_3$
+^l1_4$
+^l1_5$
+^l1_6$
+^l1_7$
+^l1_8$
+l1_9$
+l1_10$
+l1_11$
+l1_12$
+l1_13$
+l1_14$
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.5 b/usr.bin/sed/tests/regress.multitest.out/5.5
new file mode 100644
index 000000000000..6766fea19e1a
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.5
@@ -0,0 +1,5 @@
+^l1_1
+^l1_2
+^l1_4
+^l1_6
+^l1_8
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.6 b/usr.bin/sed/tests/regress.multitest.out/5.6
new file mode 100644
index 000000000000..7ffbba3e3ebe
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.6
@@ -0,0 +1,5 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.7 b/usr.bin/sed/tests/regress.multitest.out/5.7
new file mode 100644
index 000000000000..f15f6e3e92b0
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.7
@@ -0,0 +1,6 @@
+l1_1
+l1_2
+l1_3
+l1_4
+hello
+l1_5
diff --git a/usr.bin/sed/tests/regress.multitest.out/5.8 b/usr.bin/sed/tests/regress.multitest.out/5.8
new file mode 100644
index 000000000000..1557318a76f4
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/5.8
@@ -0,0 +1,14 @@
+m1_1
+m1_2
+m1_3
+m1_4
+m1_5
+m1_6
+m1_7
+m1_8
+m1_9
+m1_10
+m1_11
+m1_12
+m1_13
+m1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.1 b/usr.bin/sed/tests/regress.multitest.out/6.1
new file mode 100644
index 000000000000..78db2a521ed6
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.1
@@ -0,0 +1,14 @@
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
+changed
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.2 b/usr.bin/sed/tests/regress.multitest.out/6.2
new file mode 100644
index 000000000000..77e5cc0ee1e6
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.2
@@ -0,0 +1,13 @@
+l1_1
+l1_2
+l1_3
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.3 b/usr.bin/sed/tests/regress.multitest.out/6.3
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.3
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.4 b/usr.bin/sed/tests/regress.multitest.out/6.4
new file mode 100644
index 000000000000..e9169dc7b242
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.4
@@ -0,0 +1,20 @@
+l1_1
+l1_2
+l1_3
+l1_2
+l1_3
+l1_5
+l1_2
+l1_3
+l1_2
+l1_3
+l1_6
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.5 b/usr.bin/sed/tests/regress.multitest.out/6.5
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.5
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/6.6 b/usr.bin/sed/tests/regress.multitest.out/6.6
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/6.6
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.1 b/usr.bin/sed/tests/regress.multitest.out/7.1
new file mode 100644
index 000000000000..586cac7b36a4
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.1
@@ -0,0 +1,15 @@
+\001\002\003\004\005\006\a\b\t$
+\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\
+\033\034\035\036\037 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF\
+GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\
+\177\200\201\202\203\204\205\206\207\210\211\212\213\214\
+\215\216\217\220\221\222\223\224\225\226\227\230\231\232\
+\233\234\235\236\237\240\241\242\243\244\245\246\247\250\
+\251\252\253\254\255\256\257\260\261\262\263\264\265\266\
+\267\270\271\272\273\274\275\276\277\300\301\302\303\304\
+\305\306\307\310\311\312\313\314\315\316\317\320\321\322\
+\323\324\325\326\327\330\331\332\333\334\335\336\337\340\
+\341\342\343\344\345\346\347\350\351\352\353\354\355\356\
+\357\360\361\362\363\364\365\366\367\370\371\372\373\374\
+\375\376\377$
+$
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.2 b/usr.bin/sed/tests/regress.multitest.out/7.2
new file mode 100644
index 000000000000..cb8d266f483c
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.2
@@ -0,0 +1,32 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+15
+l2_1
+16
+l2_2
+17
+l2_3
+18
+l2_4
+19
+l2_5
+20
+l2_6
+21
+l2_7
+22
+l2_8
+23
+l2_9
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.3 b/usr.bin/sed/tests/regress.multitest.out/7.3
new file mode 100644
index 000000000000..c74225054a00
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.3
@@ -0,0 +1,24 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.4 b/usr.bin/sed/tests/regress.multitest.out/7.4
new file mode 100644
index 000000000000..19a94616a9a9
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.4
@@ -0,0 +1,23 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l2_1
+l2_2
+l2_3
+l2_4
+l2_5
+l2_6
+l2_7
+l2_8
+l2_9
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.5 b/usr.bin/sed/tests/regress.multitest.out/7.5
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.5
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.6 b/usr.bin/sed/tests/regress.multitest.out/7.6
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.6
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.7 b/usr.bin/sed/tests/regress.multitest.out/7.7
new file mode 100644
index 000000000000..7baa93150d2d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.7
@@ -0,0 +1,2814 @@
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+Al1_1
+Al1_2
+Al1_3
+Al1_4
+Al1_5
+Al1_6
+Al1_7
+Al1_8
+Al1_9
+Al1_10
+Al1_11
+Al1_12
+Al1_13
+Al1_14
+AaniaamaaliiaalaaaAl1_1
+AaniaamaaliiaalaaaAl1_2
+AaniaamaaliiaalaaaAl1_3
+AaniaamaaliiaalaaaAl1_4
+AaniaamaaliiaalaaaAl1_5
+AaniaamaaliiaalaaaAl1_6
+AaniaamaaliiaalaaaAl1_7
+AaniaamaaliiaalaaaAl1_8
+AaniaamaaliiaalaaaAl1_9
+AaniaamaaliiaalaaaAl1_10
+AaniaamaaliiaalaaaAl1_11
+AaniaamaaliiaalaaaAl1_12
+AaniaamaaliiaalaaaAl1_13
+AaniaamaaliiaalaaaAl1_14
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+AberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aAl1_1
+aAl1_2
+aAl1_3
+aAl1_4
+aAl1_5
+aAl1_6
+aAl1_7
+aAl1_8
+aAl1_9
+aAl1_10
+aAl1_11
+aAl1_12
+aAl1_13
+aAl1_14
+aaaAl1_1
+aaaAl1_2
+aaaAl1_3
+aaaAl1_4
+aaaAl1_5
+aaaAl1_6
+aaaAl1_7
+aaaAl1_8
+aaaAl1_9
+aaaAl1_10
+aaaAl1_11
+aaaAl1_12
+aaaAl1_13
+aaaAl1_14
+aalaaaAl1_1
+aalaaaAl1_2
+aalaaaAl1_3
+aalaaaAl1_4
+aalaaaAl1_5
+aalaaaAl1_6
+aalaaaAl1_7
+aalaaaAl1_8
+aalaaaAl1_9
+aalaaaAl1_10
+aalaaaAl1_11
+aalaaaAl1_12
+aalaaaAl1_13
+aalaaaAl1_14
+aaliiaalaaaAl1_1
+aaliiaalaaaAl1_2
+aaliiaalaaaAl1_3
+aaliiaalaaaAl1_4
+aaliiaalaaaAl1_5
+aaliiaalaaaAl1_6
+aaliiaalaaaAl1_7
+aaliiaalaaaAl1_8
+aaliiaalaaaAl1_9
+aaliiaalaaaAl1_10
+aaliiaalaaaAl1_11
+aaliiaalaaaAl1_12
+aaliiaalaaaAl1_13
+aaliiaalaaaAl1_14
+aamaaliiaalaaaAl1_1
+aamaaliiaalaaaAl1_2
+aamaaliiaalaaaAl1_3
+aamaaliiaalaaaAl1_4
+aamaaliiaalaaaAl1_5
+aamaaliiaalaaaAl1_6
+aamaaliiaalaaaAl1_7
+aamaaliiaalaaaAl1_8
+aamaaliiaalaaaAl1_9
+aamaaliiaalaaaAl1_10
+aamaaliiaalaaaAl1_11
+aamaaliiaalaaaAl1_12
+aamaaliiaalaaaAl1_13
+aamaaliiaalaaaAl1_14
+aardvarkAaniaamaaliiaalaaaAl1_1
+aardvarkAaniaamaaliiaalaaaAl1_2
+aardvarkAaniaamaaliiaalaaaAl1_3
+aardvarkAaniaamaaliiaalaaaAl1_4
+aardvarkAaniaamaaliiaalaaaAl1_5
+aardvarkAaniaamaaliiaalaaaAl1_6
+aardvarkAaniaamaaliiaalaaaAl1_7
+aardvarkAaniaamaaliiaalaaaAl1_8
+aardvarkAaniaamaaliiaalaaaAl1_9
+aardvarkAaniaamaaliiaalaaaAl1_10
+aardvarkAaniaamaaliiaalaaaAl1_11
+aardvarkAaniaamaaliiaalaaaAl1_12
+aardvarkAaniaamaaliiaalaaaAl1_13
+aardvarkAaniaamaaliiaalaaaAl1_14
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+aberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_1
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_2
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_3
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_4
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_5
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_6
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_7
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_8
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_9
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_10
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_11
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_12
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_13
+abetmentabetaberuncatoraberroscopeaberrometeraberratoraberrationalaberrationaberrateaberrantaberrancyaberranceAberiaAberdonianaberdevineAberdeenabepithymiaabentericAbencerragesabeltreeAbelonianabelmoskAbelmoschusabeliteAbeliteAbeliceaAbelianAbeliaabeleAbelabeighabedabecedaryabecedariumabecedarianabearanceabearabeamAbeabductorabductionabductabducentabducensabduceabdominovesicalabdominovaginalabdominousabdominothoracicabdominoscopyabdominoscopeabdominoposteriorabdominohysterotomyabdominohysterectomyabdominogenitalabdominocysticabdominocentesisabdominocardiacabdominoanteriorabdominallyabdominalianAbdominalesabdominalabdomenabditoryabditiveAbdielabdicatorabdicativeabdicationabdicateabdicantabdicableabdestAbderiteAbderianabdatabdalabcoulombAbbyabbreviatureabbreviatoryabbreviatorabbreviationabbreviatelyabbreviateabbotshipabbotnulliusabbotcyabbotAbbieabbeystedeabbeyabbessabbaticalabbatialAbbassideabbassiabbasiabbasAbbadideabbacyabbacomesAbbaabbabazeabaxileabaxialabaveabatureAbatuaabattoirabatorabatonabatisedabatisabaterabatementabateabatableabastardizeAbassinabaskabasicabasiaabashmentabashlesslyabashlessabashednessabashedlyabashedabashAbasgiabaserabasementabasednessabasedlyabasedabaseabasabarticulationabarticularabarthrosisAbarisAbaramboabaptistonAbantesAbanicabandonmentabandonerabandoneeabandonedlyabandonedabandonableabandonabampereAbamaabaloneabalienationabalienateabaissedabaiserabaisanceabaftabaffAbaditeabacusabaculusabactorabactionabactinallyabactinalabackabacistabaciscusabacinationabacinateabacayabacateabacaabacAbabuaAbabdehabaAbAaruAaroniticAaroniteAaronicalAaronicAaronaardwolfaardvarkAaniaamaaliiaalaaaAl1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/7.8 b/usr.bin/sed/tests/regress.multitest.out/7.8
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/7.8
@@ -0,0 +1 @@
+
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.1 b/usr.bin/sed/tests/regress.multitest.out/8.1
new file mode 100644
index 000000000000..dcf124b44257
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.1
@@ -0,0 +1,14 @@
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.10 b/usr.bin/sed/tests/regress.multitest.out/8.10
new file mode 100644
index 000000000000..86f75c15bc2d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.10
@@ -0,0 +1,14 @@
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X
+l1_X0
+l1_X1
+l1_X2
+l1_X3
+l1_X4
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.11 b/usr.bin/sed/tests/regress.multitest.out/8.11
new file mode 100644
index 000000000000..70a0f11d6373
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.11
@@ -0,0 +1,28 @@
+lX_1
+lX_2
+lX_3
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_10
+lX_11
+lX_12
+lX_13
+lX_14
+lX_1
+lX_2
+lX_3
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_10
+lX_11
+lX_12
+lX_13
+lX_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.12 b/usr.bin/sed/tests/regress.multitest.out/8.12
new file mode 100644
index 000000000000..ded4e9815eb2
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.12
@@ -0,0 +1,14 @@
+lX_X
+lX_X
+lX_X
+lX_4
+lX_5
+lX_6
+lX_7
+lX_8
+lX_9
+lX_X0
+lX_XX
+lX_XX
+lX_XX
+lX_X4
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.13 b/usr.bin/sed/tests/regress.multitest.out/8.13
new file mode 100644
index 000000000000..48646d1ae6f7
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.13
@@ -0,0 +1,14 @@
+l8_8
+l8_7
+l8_6
+l8_5
+l8_4
+l8_3
+l8_2
+l8_1
+l8_0
+l8_89
+l8_88
+l8_87
+l8_86
+l8_85
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.14 b/usr.bin/sed/tests/regress.multitest.out/8.14
new file mode 100644
index 000000000000..48646d1ae6f7
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.14
@@ -0,0 +1,14 @@
+l8_8
+l8_7
+l8_6
+l8_5
+l8_4
+l8_3
+l8_2
+l8_1
+l8_0
+l8_89
+l8_88
+l8_87
+l8_86
+l8_85
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.15 b/usr.bin/sed/tests/regress.multitest.out/8.15
new file mode 100644
index 000000000000..f414bb53eb8c
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.15
@@ -0,0 +1,13 @@
+l1_1Xl1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.16 b/usr.bin/sed/tests/regress.multitest.out/8.16
new file mode 100644
index 000000000000..230cc08121d6
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.16
@@ -0,0 +1,7 @@
+eeefff
+Xeefff
+XYefff
+XYeYff
+XYeYYf
+XYeYYY
+XYeYYY
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.17 b/usr.bin/sed/tests/regress.multitest.out/8.17
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.17
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.18 b/usr.bin/sed/tests/regress.multitest.out/8.18
new file mode 100644
index 000000000000..833e1ba42fc9
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.18
@@ -0,0 +1,14 @@
+l1X1
+l1X2
+l1X3
+l1X4
+l1X5
+l1X6
+l1X7
+l1X8
+l1X9
+l1X10
+l1X11
+l1X12
+l1X13
+l1X14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.19 b/usr.bin/sed/tests/regress.multitest.out/8.19
new file mode 100644
index 000000000000..6536cb82960b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.19
@@ -0,0 +1,14 @@
+X_1
+X_2
+X_3
+X_4
+X_5
+X_6
+X_7
+X_8
+X_9
+X_10
+X_11
+X_12
+X_13
+X_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.2 b/usr.bin/sed/tests/regress.multitest.out/8.2
new file mode 100644
index 000000000000..dcf124b44257
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.2
@@ -0,0 +1,14 @@
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.20 b/usr.bin/sed/tests/regress.multitest.out/8.20
new file mode 100644
index 000000000000..f9adadacab99
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.20
@@ -0,0 +1,14 @@
+X[_1
+X[_2
+X[_3
+X[_4
+X[_5
+X[_6
+X[_7
+X[_8
+X[_9
+X[_10
+X[_11
+X[_12
+X[_13
+X[_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.21 b/usr.bin/sed/tests/regress.multitest.out/8.21
new file mode 100644
index 000000000000..ec4d9e629be3
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.21
@@ -0,0 +1 @@
+a-b-c
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.22 b/usr.bin/sed/tests/regress.multitest.out/8.22
new file mode 100644
index 000000000000..c66dd65b0993
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.22
@@ -0,0 +1 @@
+1X2
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.23 b/usr.bin/sed/tests/regress.multitest.out/8.23
new file mode 100644
index 000000000000..c66dd65b0993
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.23
@@ -0,0 +1 @@
+1X2
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.3 b/usr.bin/sed/tests/regress.multitest.out/8.3
new file mode 100644
index 000000000000..dcf124b44257
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.3
@@ -0,0 +1,14 @@
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
+XXXXX
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.4 b/usr.bin/sed/tests/regress.multitest.out/8.4
new file mode 100644
index 000000000000..3bcc601e03dc
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.4
@@ -0,0 +1,14 @@
+l1_1
+l1_2
+l1_3
+l1_4
+l1_5
+l1_6
+l1_7
+l1_8
+l1_9
+l1_10
+l1_11
+l1_12
+l1_13
+l1_14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.5 b/usr.bin/sed/tests/regress.multitest.out/8.5
new file mode 100644
index 000000000000..833e1ba42fc9
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.5
@@ -0,0 +1,14 @@
+l1X1
+l1X2
+l1X3
+l1X4
+l1X5
+l1X6
+l1X7
+l1X8
+l1X9
+l1X10
+l1X11
+l1X12
+l1X13
+l1X14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.6 b/usr.bin/sed/tests/regress.multitest.out/8.6
new file mode 100644
index 000000000000..47c08aebe065
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.6
@@ -0,0 +1,14 @@
+(l)(1)(_)(1)
+(l)(1)(_)(2)
+(l)(1)(_)(3)
+(l)(1)(_)(4)
+(l)(1)(_)(5)
+(l)(1)(_)(6)
+(l)(1)(_)(7)
+(l)(1)(_)(8)
+(l)(1)(_)(9)
+(l)(1)(_)(1)(0)
+(l)(1)(_)(1)(1)
+(l)(1)(_)(1)(2)
+(l)(1)(_)(1)(3)
+(l)(1)(_)(1)(4)
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.7 b/usr.bin/sed/tests/regress.multitest.out/8.7
new file mode 100644
index 000000000000..0ff0b9e77047
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.7
@@ -0,0 +1,14 @@
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
+(&)(&)(&)(&)(&)
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.8 b/usr.bin/sed/tests/regress.multitest.out/8.8
new file mode 100644
index 000000000000..08bbf8cff586
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.8
@@ -0,0 +1,14 @@
+x_x1xl1
+x_x1xl2
+x_x1xl3
+x_x1xl4
+x_x1xl5
+x_x1xl6
+x_x1xl7
+x_x1xl8
+x_x1xl9
+x_x1xl10
+x_x1xl11
+x_x1xl12
+x_x1xl13
+x_x1xl14
diff --git a/usr.bin/sed/tests/regress.multitest.out/8.9 b/usr.bin/sed/tests/regress.multitest.out/8.9
new file mode 100644
index 000000000000..e0cd8b502e99
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/8.9
@@ -0,0 +1,42 @@
+l1u0
+u1
+u21
+l1u0
+u1
+u22
+l1u0
+u1
+u23
+l1u0
+u1
+u24
+l1u0
+u1
+u25
+l1u0
+u1
+u26
+l1u0
+u1
+u27
+l1u0
+u1
+u28
+l1u0
+u1
+u29
+l1u0
+u1
+u210
+l1u0
+u1
+u211
+l1u0
+u1
+u212
+l1u0
+u1
+u213
+l1u0
+u1
+u214
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.1 b/usr.bin/sed/tests/regress.multitest.out/9.1
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.1
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.10 b/usr.bin/sed/tests/regress.multitest.out/9.10
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.10
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.11 b/usr.bin/sed/tests/regress.multitest.out/9.11
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.11
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.12 b/usr.bin/sed/tests/regress.multitest.out/9.12
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.12
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.13 b/usr.bin/sed/tests/regress.multitest.out/9.13
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.13
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.14 b/usr.bin/sed/tests/regress.multitest.out/9.14
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.14
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.15 b/usr.bin/sed/tests/regress.multitest.out/9.15
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.15
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.16 b/usr.bin/sed/tests/regress.multitest.out/9.16
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.16
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.17 b/usr.bin/sed/tests/regress.multitest.out/9.17
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.17
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.18 b/usr.bin/sed/tests/regress.multitest.out/9.18
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.18
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.19 b/usr.bin/sed/tests/regress.multitest.out/9.19
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.19
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.2 b/usr.bin/sed/tests/regress.multitest.out/9.2
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.2
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.20 b/usr.bin/sed/tests/regress.multitest.out/9.20
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.20
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.21 b/usr.bin/sed/tests/regress.multitest.out/9.21
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.21
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.22 b/usr.bin/sed/tests/regress.multitest.out/9.22
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.22
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.23 b/usr.bin/sed/tests/regress.multitest.out/9.23
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.23
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.24 b/usr.bin/sed/tests/regress.multitest.out/9.24
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.24
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.25 b/usr.bin/sed/tests/regress.multitest.out/9.25
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.25
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.26 b/usr.bin/sed/tests/regress.multitest.out/9.26
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.26
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.27 b/usr.bin/sed/tests/regress.multitest.out/9.27
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.27
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.28 b/usr.bin/sed/tests/regress.multitest.out/9.28
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.28
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.29 b/usr.bin/sed/tests/regress.multitest.out/9.29
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.29
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.3 b/usr.bin/sed/tests/regress.multitest.out/9.3
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.3
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.30 b/usr.bin/sed/tests/regress.multitest.out/9.30
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.30
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.31 b/usr.bin/sed/tests/regress.multitest.out/9.31
new file mode 100644
index 000000000000..573541ac9702
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.31
@@ -0,0 +1 @@
+0
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.4 b/usr.bin/sed/tests/regress.multitest.out/9.4
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.4
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.5 b/usr.bin/sed/tests/regress.multitest.out/9.5
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.5
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.6 b/usr.bin/sed/tests/regress.multitest.out/9.6
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.6
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.7 b/usr.bin/sed/tests/regress.multitest.out/9.7
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.7
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.8 b/usr.bin/sed/tests/regress.multitest.out/9.8
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.8
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/9.9 b/usr.bin/sed/tests/regress.multitest.out/9.9
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/9.9
@@ -0,0 +1 @@
+1
diff --git a/usr.bin/sed/tests/regress.multitest.out/Makefile b/usr.bin/sed/tests/regress.multitest.out/Makefile
new file mode 100644
index 000000000000..1636e64c7b67
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/Makefile
@@ -0,0 +1,136 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/usr.bin/sed/regress.multitest.out
+
+${PACKAGE}FILES+= 1.1
+${PACKAGE}FILES+= 1.10
+${PACKAGE}FILES+= 1.11
+${PACKAGE}FILES+= 1.12
+${PACKAGE}FILES+= 1.13
+${PACKAGE}FILES+= 1.14
+${PACKAGE}FILES+= 1.15
+${PACKAGE}FILES+= 1.16
+${PACKAGE}FILES+= 1.17
+${PACKAGE}FILES+= 1.18
+${PACKAGE}FILES+= 1.2
+${PACKAGE}FILES+= 1.3
+${PACKAGE}FILES+= 1.4
+${PACKAGE}FILES+= 1.4.1
+${PACKAGE}FILES+= 1.5
+${PACKAGE}FILES+= 1.6
+${PACKAGE}FILES+= 1.7
+${PACKAGE}FILES+= 1.8
+${PACKAGE}FILES+= 1.9
+${PACKAGE}FILES+= 2.1
+${PACKAGE}FILES+= 2.10
+${PACKAGE}FILES+= 2.11
+${PACKAGE}FILES+= 2.12
+${PACKAGE}FILES+= 2.13
+${PACKAGE}FILES+= 2.14
+${PACKAGE}FILES+= 2.15
+${PACKAGE}FILES+= 2.16
+${PACKAGE}FILES+= 2.17
+${PACKAGE}FILES+= 2.18
+${PACKAGE}FILES+= 2.19
+${PACKAGE}FILES+= 2.2
+${PACKAGE}FILES+= 2.20
+${PACKAGE}FILES+= 2.21
+${PACKAGE}FILES+= 2.22
+${PACKAGE}FILES+= 2.23
+${PACKAGE}FILES+= 2.3
+${PACKAGE}FILES+= 2.4
+${PACKAGE}FILES+= 2.5
+${PACKAGE}FILES+= 2.6
+${PACKAGE}FILES+= 2.7
+${PACKAGE}FILES+= 2.8
+${PACKAGE}FILES+= 2.9
+${PACKAGE}FILES+= 3.1
+${PACKAGE}FILES+= 3.2
+${PACKAGE}FILES+= 3.3
+${PACKAGE}FILES+= 3.4
+${PACKAGE}FILES+= 4.1
+${PACKAGE}FILES+= 4.2
+${PACKAGE}FILES+= 4.3
+${PACKAGE}FILES+= 4.4
+${PACKAGE}FILES+= 4.5
+${PACKAGE}FILES+= 4.6
+${PACKAGE}FILES+= 4.7
+${PACKAGE}FILES+= 4.8
+${PACKAGE}FILES+= 5.1
+${PACKAGE}FILES+= 5.2
+${PACKAGE}FILES+= 5.3
+${PACKAGE}FILES+= 5.4
+${PACKAGE}FILES+= 5.5
+${PACKAGE}FILES+= 5.6
+${PACKAGE}FILES+= 5.7
+${PACKAGE}FILES+= 5.8
+${PACKAGE}FILES+= 6.1
+${PACKAGE}FILES+= 6.2
+${PACKAGE}FILES+= 6.3
+${PACKAGE}FILES+= 6.4
+${PACKAGE}FILES+= 6.5
+${PACKAGE}FILES+= 6.6
+${PACKAGE}FILES+= 7.1
+${PACKAGE}FILES+= 7.2
+${PACKAGE}FILES+= 7.3
+${PACKAGE}FILES+= 7.4
+${PACKAGE}FILES+= 7.5
+${PACKAGE}FILES+= 7.6
+${PACKAGE}FILES+= 7.7
+${PACKAGE}FILES+= 7.8
+${PACKAGE}FILES+= 8.1
+${PACKAGE}FILES+= 8.10
+${PACKAGE}FILES+= 8.11
+${PACKAGE}FILES+= 8.12
+${PACKAGE}FILES+= 8.13
+${PACKAGE}FILES+= 8.14
+${PACKAGE}FILES+= 8.15
+${PACKAGE}FILES+= 8.16
+${PACKAGE}FILES+= 8.17
+${PACKAGE}FILES+= 8.18
+${PACKAGE}FILES+= 8.19
+${PACKAGE}FILES+= 8.2
+${PACKAGE}FILES+= 8.20
+${PACKAGE}FILES+= 8.21
+${PACKAGE}FILES+= 8.22
+${PACKAGE}FILES+= 8.23
+${PACKAGE}FILES+= 8.3
+${PACKAGE}FILES+= 8.4
+${PACKAGE}FILES+= 8.5
+${PACKAGE}FILES+= 8.6
+${PACKAGE}FILES+= 8.7
+${PACKAGE}FILES+= 8.8
+${PACKAGE}FILES+= 8.9
+${PACKAGE}FILES+= 9.1
+${PACKAGE}FILES+= 9.10
+${PACKAGE}FILES+= 9.11
+${PACKAGE}FILES+= 9.12
+${PACKAGE}FILES+= 9.13
+${PACKAGE}FILES+= 9.14
+${PACKAGE}FILES+= 9.15
+${PACKAGE}FILES+= 9.16
+${PACKAGE}FILES+= 9.17
+${PACKAGE}FILES+= 9.18
+${PACKAGE}FILES+= 9.19
+${PACKAGE}FILES+= 9.2
+${PACKAGE}FILES+= 9.20
+${PACKAGE}FILES+= 9.21
+${PACKAGE}FILES+= 9.22
+${PACKAGE}FILES+= 9.23
+${PACKAGE}FILES+= 9.24
+${PACKAGE}FILES+= 9.25
+${PACKAGE}FILES+= 9.26
+${PACKAGE}FILES+= 9.27
+${PACKAGE}FILES+= 9.28
+${PACKAGE}FILES+= 9.29
+${PACKAGE}FILES+= 9.3
+${PACKAGE}FILES+= 9.30
+${PACKAGE}FILES+= 9.31
+${PACKAGE}FILES+= 9.4
+${PACKAGE}FILES+= 9.5
+${PACKAGE}FILES+= 9.6
+${PACKAGE}FILES+= 9.7
+${PACKAGE}FILES+= 9.8
+${PACKAGE}FILES+= 9.9
+
+.include <bsd.test.mk>
diff --git a/usr.bin/sed/tests/regress.multitest.out/Makefile.depend b/usr.bin/sed/tests/regress.multitest.out/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/sed/tests/regress.multitest.out/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sed/tests/regress.not.out b/usr.bin/sed/tests/regress.not.out
new file mode 100644
index 000000000000..257cc5642cb1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.not.out
@@ -0,0 +1 @@
+foo
diff --git a/usr.bin/sed/tests/regress.psl.out b/usr.bin/sed/tests/regress.psl.out
new file mode 100644
index 000000000000..8b38f4d98eec
--- /dev/null
+++ b/usr.bin/sed/tests/regress.psl.out
@@ -0,0 +1,4 @@
+
+
+
+of sed(1)
diff --git a/usr.bin/sed/tests/regress.s3.out b/usr.bin/sed/tests/regress.s3.out
new file mode 100644
index 000000000000..68dfa9bc84b7
--- /dev/null
+++ b/usr.bin/sed/tests/regress.s3.out
@@ -0,0 +1 @@
+fo,o
diff --git a/usr.bin/sed/tests/regress.s4.out b/usr.bin/sed/tests/regress.s4.out
new file mode 100644
index 000000000000..03914ba82b2d
--- /dev/null
+++ b/usr.bin/sed/tests/regress.s4.out
@@ -0,0 +1 @@
+foo,
diff --git a/usr.bin/sed/tests/regress.s5.out b/usr.bin/sed/tests/regress.s5.out
new file mode 100644
index 000000000000..257cc5642cb1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.s5.out
@@ -0,0 +1 @@
+foo
diff --git a/usr.bin/sed/tests/regress.sg.out b/usr.bin/sed/tests/regress.sg.out
new file mode 100644
index 000000000000..7b24f2c46f74
--- /dev/null
+++ b/usr.bin/sed/tests/regress.sg.out
@@ -0,0 +1 @@
+,f,o,o,
diff --git a/usr.bin/sed/tests/regress.sh b/usr.bin/sed/tests/regress.sh
new file mode 100644
index 000000000000..aed3167c3f07
--- /dev/null
+++ b/usr.bin/sed/tests/regress.sh
@@ -0,0 +1,74 @@
+
+REGRESSION_START($1)
+
+echo '1..26'
+
+REGRESSION_TEST(`G', `sed G <${SRCDIR}/regress.in')
+REGRESSION_TEST(`P', `sed P <${SRCDIR}/regress.in')
+REGRESSION_TEST(`psl', `sed \$!g\;P\;D <${SRCDIR}/regress.in')
+REGRESSION_TEST(`bcb', `sed s/X/$(jot -n -bx -s "" 2043)\\\\zz/ <${SRCDIR}/regress.in')
+REGRESSION_TEST(`y', `echo -n foo | sed y/o/O/')
+REGRESSION_TEST(`sg', `echo foo | sed s/,*/,/g')
+REGRESSION_TEST(`s3', `echo foo | sed s/,*/,/3')
+REGRESSION_TEST(`s4', `echo foo | sed s/,*/,/4')
+REGRESSION_TEST(`s5', `echo foo | sed s/,*/,/5')
+REGRESSION_TEST(`c0', `sed ''`c\
+foo
+''`<${SRCDIR}/regress.in')
+REGRESSION_TEST(`c1', `sed ''`4,$c\
+foo
+''`<${SRCDIR}/regress.in')
+REGRESSION_TEST(`c2', `sed ''`3,9c\
+foo
+''`<${SRCDIR}/regress.in')
+REGRESSION_TEST(`c3', `sed ''`3,/no such string/c\
+foo
+''`<${SRCDIR}/regress.in')
+REGRESSION_TEST(`b2a', `sed ''`2,3b
+1,2d''` <${SRCDIR}/regress.in')
+
+`
+inplace_test()
+{
+ expr="$1"
+ rc=0
+ ns=$(jot 5)
+ ins= outs= _ins=
+ for n in $ns; do
+ jot -w "l${n}_%d" 9 | tee lines.in.$n lines._in.$n | \
+ sed "$expr" > lines.out.$n
+ ins="$ins lines.in.$n"
+ outs="$outs lines.out.$n"
+ _ins="$_ins lines._in.$n"
+ done
+ sed "$expr" $_ins > lines.out
+
+ sed -i "" "$expr" $ins
+ sed -I "" "$expr" $_ins
+
+ for n in $ns; do
+ diff -u lines.out.$n lines.in.$n || rc=1
+ done
+ cat $_ins | diff -u lines.out - || rc=1
+ rm -f $ins $outs $_ins lines.out
+
+ return $rc
+}
+'
+
+REGRESSION_TEST_FREEFORM(`inplace1', `inplace_test 3,6d')
+REGRESSION_TEST_FREEFORM(`inplace2', `inplace_test 8,30d')
+REGRESSION_TEST_FREEFORM(`inplace3', `inplace_test 20,99d')
+REGRESSION_TEST_FREEFORM(`inplace4', `inplace_test "{;{;8,30d;};}"')
+REGRESSION_TEST_FREEFORM(`inplace5', `inplace_test "3x;6G"')
+
+REGRESSION_TEST(`icase1', `sed /SED/Id <${SRCDIR}/regress.in')
+REGRESSION_TEST(`icase2', `sed s/SED/Foo/I <${SRCDIR}/regress.in')
+REGRESSION_TEST(`icase3', `sed s/SED/Foo/ <${SRCDIR}/regress.in')
+REGRESSION_TEST(`icase4', `sed s/SED/Foo/i <${SRCDIR}/regress.in')
+
+REGRESSION_TEST(`hanoi', `echo ":abcd: : :" | sed -f ${SRCDIR}/hanoi.sed')
+REGRESSION_TEST(`math', `echo "4+7*3+2^7/3" | sed -f ${SRCDIR}/math.sed')
+REGRESSION_TEST(`not', `echo foo | sed "1!!s/foo/bar/"')
+
+REGRESSION_END()
diff --git a/usr.bin/sed/tests/regress.y.out b/usr.bin/sed/tests/regress.y.out
new file mode 100644
index 000000000000..22f4f051cef1
--- /dev/null
+++ b/usr.bin/sed/tests/regress.y.out
@@ -0,0 +1 @@
+fOO \ No newline at end of file
diff --git a/usr.bin/sed/tests/sed2_test.sh b/usr.bin/sed/tests/sed2_test.sh
new file mode 100755
index 000000000000..c88e998425a0
--- /dev/null
+++ b/usr.bin/sed/tests/sed2_test.sh
@@ -0,0 +1,209 @@
+#
+# Copyright 2017 Dell EMC.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+#
+
+atf_test_case inplace_hardlink_src
+inplace_hardlink_src_head()
+{
+ atf_set "descr" "Verify -i works with a symlinked source file"
+}
+inplace_hardlink_src_body()
+{
+ echo foo > a
+ atf_check ln a b
+ atf_check sed -i '' -e 's,foo,bar,g' b
+ atf_check -o 'inline:bar\n' -s exit:0 cat b
+ atf_check -s not-exit:0 stat -q '.!'*
+}
+
+atf_test_case inplace_symlink_src
+inplace_symlink_src_head()
+{
+ atf_set "descr" "Verify -i works with a symlinked source file"
+}
+inplace_symlink_src_body()
+{
+ echo foo > a
+ atf_check ln -s a b
+ atf_check -e not-empty -s not-exit:0 sed -i '' -e 's,foo,bar,g' b
+ atf_check -s not-exit:0 stat -q '.!'*
+}
+
+atf_test_case inplace_command_q
+inplace_command_q_head()
+{
+ atf_set "descr" "Verify -i works correctly with the 'q' command"
+}
+inplace_command_q_body()
+{
+ printf '1\n2\n3\n' > a
+ atf_check -o 'inline:1\n2\n' sed '2q' a
+ atf_check sed -i.bak '2q' a
+ atf_check -o 'inline:1\n2\n' cat a
+ atf_check -o 'inline:1\n2\n3\n' cat a.bak
+ atf_check -s not-exit:0 stat -q '.!'*
+}
+
+atf_test_case escape_subst
+escape_subst_head()
+{
+ atf_set "descr" "Verify functional escaping of \\n, \\r, and \\t"
+}
+escape_subst_body()
+{
+ printf "a\nt\\\t\n\tb\n\t\tc\r\n" > a
+ tr -d '\r' < a > b
+ printf "a\tb c\rx\n" > c
+
+ atf_check -o 'inline:a\nt\\t\n' sed '/\t/d' a
+ atf_check -o 'inline:a\nt\\t\n b\n c\r\n' sed 's/\t/ /g' a
+ atf_check -o 'inline:a\nt\\t\n\t\tb\n\t\t\t\tc\r\n' sed 's/\t/\t\t/g' a
+ atf_check -o 'inline:a\nt\n\tb\n\t\tc\r\n' sed 's/\\t//g' a
+ atf_check -o file:b sed 's/\r//' a
+ atf_check -o 'inline:abcx\n' sed 's/[ \r\t]//g' c
+}
+
+atf_test_case hex_subst
+hex_subst_head()
+{
+ atf_set "descr" "Verify proper conversion of hex escapes"
+}
+hex_subst_body()
+{
+ printf "test='foo'" > a
+ printf "test='27foo'" > b
+ printf "\rn" > c
+ printf "xx" > d
+
+ atf_check -o 'inline:test="foo"' sed 's/\x27/"/g' a
+ atf_check -o "inline:'test'='foo'" sed 's/test/\x27test\x27/g' a
+
+ # Make sure we take trailing digits literally.
+ atf_check -o "inline:test=\"foo'" sed 's/\x2727/"/g' b
+
+ # Single digit \x should work as well.
+ atf_check -o "inline:xn" sed 's/\xd/x/' c
+
+ # This should get passed through to the underlying regex engine as
+ # \xx, which is an invalid escape of an ordinary character.
+ atf_check -s exit:1 -e not-empty sed 's/\xx//' d
+}
+
+atf_test_case commands_on_stdin
+commands_on_stdin_head()
+{
+ atf_set "descr" "Verify -f -"
+}
+commands_on_stdin_body()
+{
+ printf "a\n" > a
+ printf "s/a/b/\n" > a_to_b
+ printf "s/b/c/\n" > b_to_c
+ printf "s/c/d/\n" > ./-
+ atf_check -o 'inline:d\n' sed -f a_to_b -f - -f ./- a < b_to_c
+
+ # Verify that nothing is printed if there are no input files provided.
+ printf 'i\\\nx' > insert_x
+ atf_check -o 'empty' sed -f - < insert_x
+}
+
+atf_test_case bracket_y
+bracket_y_head()
+{
+ atf_set "descr" "Verify '[' is ordinary character for 'y' command"
+}
+bracket_y_body()
+{
+ atf_check -e empty -o ignore echo | sed 'y/[/x/'
+ atf_check -e empty -o ignore echo | sed 'y/[]/xy/'
+ atf_check -e empty -o ignore echo | sed 'y/[a]/xyz/'
+ atf_check -e empty -o "inline:zyx" echo '][a' | sed 'y/[a]/xyz/'
+ atf_check -e empty -o "inline:bracket\n" echo 'bra[ke]' | sed 'y/[]/ct/'
+ atf_check -e empty -o "inline:bracket\n" \
+ echo 'bra[ke]' | sed 'y[\[][ct['
+}
+
+atf_test_case minus_e
+minus_e_head()
+{
+ atf_set "descr" "Verify that -e and implicit arg do the same thing"
+}
+minus_e_body()
+{
+ printf "ab\n" > a
+ atf_check -o 'inline:--\nab\n' sed -e $'1 i\\\n--' a
+ atf_check -o 'inline:--\nab\n' sed $'1 i\\\n--' a
+}
+
+atf_test_case command_c
+command_c_head()
+{
+ atf_set "descr" "Verify that the 'c' command starts a new cycle"
+}
+command_c_body()
+{
+ printf "%s\n" a b c d e f > a
+ printf "%s\n" x c d e f > expected
+
+ atf_check -o file:expected sed '
+/a/,/b/c\
+x
+' a
+
+ atf_check -o file:expected sed '
+/a/,/b/c\
+x
+$!N
+' a
+}
+
+atf_test_case command_D
+command_D_head()
+{
+ atf_set "descr" "Test handling of an empty pattern space"
+}
+command_D_body()
+{
+ printf "hello\n\nworld\n" > a
+
+ atf_check -o file:a sed -e 's/^//;P;D' a
+ atf_check -o file:a sed -e 's/^//;$!N;P;D' a
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case inplace_command_q
+ atf_add_test_case inplace_hardlink_src
+ atf_add_test_case inplace_symlink_src
+ atf_add_test_case escape_subst
+ atf_add_test_case commands_on_stdin
+ atf_add_test_case hex_subst
+ atf_add_test_case bracket_y
+ atf_add_test_case minus_e
+ atf_add_test_case command_c
+ atf_add_test_case command_D
+}
diff --git a/usr.bin/seq/Makefile b/usr.bin/seq/Makefile
new file mode 100644
index 000000000000..f8237990e6d3
--- /dev/null
+++ b/usr.bin/seq/Makefile
@@ -0,0 +1,12 @@
+# $NetBSD: Makefile,v 1.3 2009/04/14 22:15:26 lukem Exp $
+
+.include <src.opts.mk>
+
+PROG= seq
+
+LIBADD= m
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/seq/Makefile.depend b/usr.bin/seq/Makefile.depend
new file mode 100644
index 000000000000..9add648af17b
--- /dev/null
+++ b/usr.bin/seq/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/seq/seq.1 b/usr.bin/seq/seq.1
new file mode 100644
index 000000000000..d81dc7052a3c
--- /dev/null
+++ b/usr.bin/seq/seq.1
@@ -0,0 +1,209 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" $NetBSD: seq.1,v 1.8 2013/04/07 17:37:45 jdf Exp $
+.\"
+.\" Copyright (c) 2005 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Brian Ginsbach.
+.\"
+.\" 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 June 20, 2020
+.Dt SEQ 1
+.Os
+.Sh NAME
+.Nm seq
+.Nd print sequences of numbers
+.Sh SYNOPSIS
+.Nm
+.Op Fl w
+.Op Fl f Ar format
+.Op Fl s Ar string
+.Op Fl t Ar string
+.Op Ar first Op Ar incr
+.Ar last
+.Sh DESCRIPTION
+The
+.Nm
+utility prints a sequence of numbers, one per line
+.Pq default ,
+from
+.Ar first
+.Pq default 1 ,
+to near
+.Ar last
+as possible, in increments of
+.Ar incr
+.Pq default 1 .
+When
+.Ar first
+is larger than
+.Ar last ,
+the default
+.Ar incr
+is -1.
+.Pp
+All numbers are interpreted as floating point.
+.Pp
+Normally integer values are printed as decimal integers.
+.Pp
+The
+.Nm
+utility accepts the following options:
+.Bl -tag -width indent
+.It Fl f Ar format , Fl -format Ar format
+Use a
+.Xr printf 3
+style
+.Ar format
+to print each number.
+Only the
+.Cm A ,
+.Cm a ,
+.Cm E ,
+.Cm e ,
+.Cm F ,
+.Cm f ,
+.Cm G ,
+.Cm g ,
+and
+.Cm %
+conversion characters are valid, along with any optional
+flags and an optional numeric minimum field width or precision.
+The
+.Ar format
+can contain character escape sequences in backslash notation as
+defined in
+.St -ansiC .
+The default is
+.Cm %g .
+.It Fl s Ar string , Fl -separator Ar string
+Use
+.Ar string
+to separate numbers.
+The
+.Ar string
+can contain character escape sequences in backslash notation as
+defined in
+.St -ansiC .
+The default is
+.Cm \en .
+.It Fl t Ar string , Fl -terminator Ar string
+Use
+.Ar string
+to terminate sequence of numbers.
+The
+.Ar string
+can contain character escape sequences in backslash notation as
+defined in
+.St -ansiC .
+This option is useful when the default separator
+does not contain a
+.Cm \en .
+.It Fl w , Fl -fixed-width
+Equalize the widths of all numbers by padding with zeros as necessary.
+This option has no effect with the
+.Fl f
+option.
+If any sequence numbers will be printed in exponential notation,
+the default conversion is changed to
+.Cm %e .
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Generate a sequence from 1 to 3 (included) with a default increment of 1:
+.Bd -literal -offset indent
+# seq 1 3
+1
+2
+3
+.Ed
+.Pp
+Generate a sequence from 3 to 1 (included) with a default increment of -1:
+.Bd -literal -offset indent
+# seq 3 1
+3
+2
+1
+.Ed
+.Pp
+Generate a sequence from 0 to 0.1 (included) with an increment of 0.05 and padding
+with leading zeroes.
+.Bd -literal -offset indent
+# seq -w 0 .05 .1
+0.00
+0.05
+0.10
+.Ed
+.Pp
+Generate a sequence from 1 to 3 (included) with a default increment of 1,
+a custom separator string and a custom terminator:
+.Bd -literal -offset indent
+# seq -s "-->" -t "[end of list]\\n" 1 3
+1-->2-->3-->[end of list]
+.Ed
+.Pp
+Generate a sequence from 1 to 2 (included) with an increment of 0.2 and
+print the results with two digits after the decimal point (using a
+.Xr printf 3
+style format):
+.Bd -literal -offset indent
+# seq -f %.2f 1 0.2 2
+1.00
+1.20
+1.40
+1.60
+1.80
+2.00
+.Ed
+.Sh SEE ALSO
+.Xr jot 1 ,
+.Xr printf 1 ,
+.Xr printf 3
+.Sh HISTORY
+The
+.Nm
+command first appeared in Version\~8
+.At .
+A
+.Nm
+command appeared in
+.Nx 3.0 ,
+and was ported to
+.Fx 9.0 .
+This command was based on the command of the same name in
+Plan 9 from Bell Labs and the GNU core utilities.
+The GNU
+.Nm
+command first appeared in the 1.13 shell utilities release.
+.Sh BUGS
+The
+.Fl w
+option does not handle the transition from pure floating point
+to exponent representation very well.
+The
+.Nm
+command is not bug for bug compatible with other implementations.
diff --git a/usr.bin/seq/seq.c b/usr.bin/seq/seq.c
new file mode 100644
index 000000000000..771346df1176
--- /dev/null
+++ b/usr.bin/seq/seq.c
@@ -0,0 +1,508 @@
+/* $NetBSD: seq.c,v 1.7 2010/05/27 08:40:19 dholland Exp $ */
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Brian Ginsbach.
+ *
+ * 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 <sys/cdefs.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <math.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ZERO '0'
+#define SPACE ' '
+
+#define MAX(a, b) (((a) < (b))? (b) : (a))
+#define ISSIGN(c) ((int)(c) == '-' || (int)(c) == '+')
+#define ISEXP(c) ((int)(c) == 'e' || (int)(c) == 'E')
+#define ISODIGIT(c) ((int)(c) >= '0' && (int)(c) <= '7')
+
+/* Globals */
+
+static const char *decimal_point = "."; /* default */
+static char default_format[] = { "%g" }; /* default */
+
+static const struct option long_opts[] = {
+ {"format", required_argument, NULL, 'f'},
+ {"separator", required_argument, NULL, 's'},
+ {"terminator", required_argument, NULL, 't'},
+ {"equal-width", no_argument, NULL, 'w'},
+ {NULL, no_argument, NULL, 0}
+};
+
+/* Prototypes */
+
+static double e_atof(const char *);
+
+static int decimal_places(const char *);
+static int numeric(const char *);
+static int valid_format(const char *);
+
+static char *generate_format(double, double, double, int, char);
+static char *unescape(char *);
+
+/*
+ * The seq command will print out a numeric sequence from 1, the default,
+ * to a user specified upper limit by 1. The lower bound and increment
+ * maybe indicated by the user on the command line. The sequence can
+ * be either whole, the default, or decimal numbers.
+ */
+int
+main(int argc, char *argv[])
+{
+ const char *sep, *term;
+ struct lconv *locale;
+ char pad, *fmt, *cur_print, *last_print, *prev_print;
+ double first, last, incr, prev, cur, step;
+ int c, errflg, equalize;
+
+ pad = ZERO;
+ fmt = NULL;
+ first = 1.0;
+ last = incr = prev = 0.0;
+ c = errflg = equalize = 0;
+ sep = "\n";
+ term = NULL;
+
+ /* Determine the locale's decimal point. */
+ locale = localeconv();
+ if (locale && locale->decimal_point && locale->decimal_point[0] != '\0')
+ decimal_point = locale->decimal_point;
+
+ /*
+ * Process options, but handle negative numbers separately
+ * least they trip up getopt(3).
+ */
+ while ((optind < argc) && !numeric(argv[optind]) &&
+ (c = getopt_long(argc, argv, "+f:hs:t:w", long_opts, NULL)) != -1) {
+
+ switch (c) {
+ case 'f': /* format (plan9) */
+ fmt = optarg;
+ equalize = 0;
+ break;
+ case 's': /* separator (GNU) */
+ sep = unescape(optarg);
+ break;
+ case 't': /* terminator (new) */
+ term = unescape(optarg);
+ break;
+ case 'w': /* equal width (plan9) */
+ if (!fmt)
+ if (equalize++)
+ pad = SPACE;
+ break;
+ case 'h': /* help (GNU) */
+ default:
+ errflg++;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 1 || argc > 3)
+ errflg++;
+
+ if (errflg) {
+ fprintf(stderr,
+ "usage: %s [-w] [-f format] [-s string] [-t string] [first [incr]] last\n",
+ getprogname());
+ exit(1);
+ }
+
+ last = e_atof(argv[argc - 1]);
+
+ if (argc > 1)
+ first = e_atof(argv[0]);
+
+ if (argc > 2) {
+ incr = e_atof(argv[1]);
+ /* Plan 9/GNU don't do zero */
+ if (incr == 0.0)
+ errx(1, "zero %screment", (first < last) ? "in" : "de");
+ }
+
+ /* default is one for Plan 9/GNU work alike */
+ if (incr == 0.0)
+ incr = (first < last) ? 1.0 : -1.0;
+
+ if (incr <= 0.0 && first < last)
+ errx(1, "needs positive increment");
+
+ if (incr >= 0.0 && first > last)
+ errx(1, "needs negative decrement");
+
+ if (fmt != NULL) {
+ if (!valid_format(fmt))
+ errx(1, "invalid format string: `%s'", fmt);
+ fmt = unescape(fmt);
+ if (!valid_format(fmt))
+ errx(1, "invalid format string");
+ /*
+ * XXX to be bug for bug compatible with Plan 9 add a
+ * newline if none found at the end of the format string.
+ */
+ } else
+ fmt = generate_format(first, incr, last, equalize, pad);
+
+ for (step = 1, cur = first; incr > 0 ? cur <= last : cur >= last;
+ cur = first + incr * step++) {
+ if (step > 1)
+ fputs(sep, stdout);
+ printf(fmt, cur);
+ prev = cur;
+ }
+
+ /*
+ * Did we miss the last value of the range in the loop above?
+ *
+ * We might have, so check if the printable version of the last
+ * computed value ('cur') and desired 'last' value are equal. If they
+ * are equal after formatting truncation, but 'cur' and 'prev' are not
+ * equal, it means the exit condition of the loop held true due to a
+ * rounding error and we still need to print 'last'.
+ */
+ if (asprintf(&cur_print, fmt, cur) < 0 ||
+ asprintf(&last_print, fmt, last) < 0 ||
+ asprintf(&prev_print, fmt, prev) < 0) {
+ err(1, "asprintf");
+ }
+ if (strcmp(cur_print, last_print) == 0 &&
+ strcmp(cur_print, prev_print) != 0) {
+ fputs(sep, stdout);
+ fputs(last_print, stdout);
+ }
+ free(cur_print);
+ free(last_print);
+ free(prev_print);
+
+ if (term != NULL) {
+ fputs(sep, stdout);
+ fputs(term, stdout);
+ }
+
+ fputs("\n", stdout);
+
+ return (0);
+}
+
+/*
+ * numeric - verify that string is numeric
+ */
+static int
+numeric(const char *s)
+{
+ int seen_decimal_pt, decimal_pt_len;
+
+ /* skip any sign */
+ if (ISSIGN((unsigned char)*s))
+ s++;
+
+ seen_decimal_pt = 0;
+ decimal_pt_len = strlen(decimal_point);
+ while (*s) {
+ if (!isdigit((unsigned char)*s)) {
+ if (!seen_decimal_pt &&
+ strncmp(s, decimal_point, decimal_pt_len) == 0) {
+ s += decimal_pt_len;
+ seen_decimal_pt = 1;
+ continue;
+ }
+ if (ISEXP((unsigned char)*s)) {
+ s++;
+ if (ISSIGN((unsigned char)*s) ||
+ isdigit((unsigned char)*s)) {
+ s++;
+ continue;
+ }
+ }
+ break;
+ }
+ s++;
+ }
+ return (*s == '\0');
+}
+
+/*
+ * valid_format - validate user specified format string
+ */
+static int
+valid_format(const char *fmt)
+{
+ unsigned conversions = 0;
+
+ while (*fmt != '\0') {
+ /* scan for conversions */
+ if (*fmt != '%') {
+ fmt++;
+ continue;
+ }
+ fmt++;
+
+ /* allow %% but not things like %10% */
+ if (*fmt == '%') {
+ fmt++;
+ continue;
+ }
+
+ /* flags */
+ while (*fmt != '\0' && strchr("#0- +'", *fmt)) {
+ fmt++;
+ }
+
+ /* field width */
+ while (*fmt != '\0' && strchr("0123456789", *fmt)) {
+ fmt++;
+ }
+
+ /* precision */
+ if (*fmt == '.') {
+ fmt++;
+ while (*fmt != '\0' && strchr("0123456789", *fmt)) {
+ fmt++;
+ }
+ }
+
+ /* conversion */
+ switch (*fmt) {
+ case 'A':
+ case 'a':
+ case 'E':
+ case 'e':
+ case 'F':
+ case 'f':
+ case 'G':
+ case 'g':
+ /* floating point formats are accepted */
+ conversions++;
+ break;
+ default:
+ /* anything else is not */
+ return 0;
+ }
+ }
+
+ /* PR 236347 -- user format strings must have a conversion */
+ return (conversions == 1);
+}
+
+/*
+ * unescape - handle C escapes in a string
+ */
+static char *
+unescape(char *orig)
+{
+ char c, *cp, *new = orig;
+ int i;
+
+ for (cp = orig; (*orig = *cp); cp++, orig++) {
+ if (*cp != '\\')
+ continue;
+
+ switch (*++cp) {
+ case 'a': /* alert (bell) */
+ *orig = '\a';
+ continue;
+ case 'b': /* backspace */
+ *orig = '\b';
+ continue;
+ case 'e': /* escape */
+ *orig = '\e';
+ continue;
+ case 'f': /* formfeed */
+ *orig = '\f';
+ continue;
+ case 'n': /* newline */
+ *orig = '\n';
+ continue;
+ case 'r': /* carriage return */
+ *orig = '\r';
+ continue;
+ case 't': /* horizontal tab */
+ *orig = '\t';
+ continue;
+ case 'v': /* vertical tab */
+ *orig = '\v';
+ continue;
+ case '\\': /* backslash */
+ *orig = '\\';
+ continue;
+ case '\'': /* single quote */
+ *orig = '\'';
+ continue;
+ case '\"': /* double quote */
+ *orig = '"';
+ continue;
+ case '0':
+ case '1':
+ case '2':
+ case '3': /* octal */
+ case '4':
+ case '5':
+ case '6':
+ case '7': /* number */
+ for (i = 0, c = 0;
+ ISODIGIT((unsigned char)*cp) && i < 3;
+ i++, cp++) {
+ c <<= 3;
+ c |= (*cp - '0');
+ }
+ *orig = c;
+ --cp;
+ continue;
+ case 'x': /* hexadecimal number */
+ cp++; /* skip 'x' */
+ for (i = 0, c = 0;
+ isxdigit((unsigned char)*cp) && i < 2;
+ i++, cp++) {
+ c <<= 4;
+ if (isdigit((unsigned char)*cp))
+ c |= (*cp - '0');
+ else
+ c |= ((toupper((unsigned char)*cp) -
+ 'A') + 10);
+ }
+ *orig = c;
+ --cp;
+ continue;
+ default:
+ --cp;
+ break;
+ }
+ }
+
+ return (new);
+}
+
+/*
+ * e_atof - convert an ASCII string to a double
+ * exit if string is not a valid double, or if converted value would
+ * cause overflow or underflow
+ */
+static double
+e_atof(const char *num)
+{
+ char *endp;
+ double dbl;
+
+ errno = 0;
+ dbl = strtod(num, &endp);
+
+ if (errno == ERANGE)
+ /* under or overflow */
+ err(2, "%s", num);
+ else if (*endp != '\0')
+ /* "junk" left in number */
+ errx(2, "invalid floating point argument: %s", num);
+
+ /* zero shall have no sign */
+ if (dbl == -0.0)
+ dbl = 0;
+ return (dbl);
+}
+
+/*
+ * decimal_places - count decimal places in a number (string)
+ */
+static int
+decimal_places(const char *number)
+{
+ int places = 0;
+ char *dp;
+
+ /* look for a decimal point */
+ if ((dp = strstr(number, decimal_point))) {
+ dp += strlen(decimal_point);
+
+ while (isdigit((unsigned char)*dp++))
+ places++;
+ }
+ return (places);
+}
+
+/*
+ * generate_format - create a format string
+ *
+ * XXX to be bug for bug compatible with Plan9 and GNU return "%g"
+ * when "%g" prints as "%e" (this way no width adjustments are made)
+ */
+static char *
+generate_format(double first, double incr, double last, int equalize, char pad)
+{
+ static char buf[256];
+ char cc = '\0';
+ int precision, width1, width2, places;
+
+ if (equalize == 0)
+ return (default_format);
+
+ /* figure out "last" value printed */
+ if (first > last)
+ last = first - incr * floor((first - last) / incr);
+ else
+ last = first + incr * floor((last - first) / incr);
+
+ sprintf(buf, "%g", incr);
+ if (strchr(buf, 'e'))
+ cc = 'e';
+ precision = decimal_places(buf);
+
+ width1 = sprintf(buf, "%g", first);
+ if (strchr(buf, 'e'))
+ cc = 'e';
+ if ((places = decimal_places(buf)))
+ width1 -= (places + strlen(decimal_point));
+
+ precision = MAX(places, precision);
+
+ width2 = sprintf(buf, "%g", last);
+ if (strchr(buf, 'e'))
+ cc = 'e';
+ if ((places = decimal_places(buf)))
+ width2 -= (places + strlen(decimal_point));
+
+ if (precision) {
+ sprintf(buf, "%%%c%d.%d%c", pad,
+ MAX(width1, width2) + (int) strlen(decimal_point) +
+ precision, precision, (cc) ? cc : 'f');
+ } else {
+ sprintf(buf, "%%%c%d%c", pad, MAX(width1, width2),
+ (cc) ? cc : 'g');
+ }
+
+ return (buf);
+}
diff --git a/usr.bin/seq/tests/Makefile b/usr.bin/seq/tests/Makefile
new file mode 100644
index 000000000000..a002ff883581
--- /dev/null
+++ b/usr.bin/seq/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= seq_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/seq/tests/Makefile.depend b/usr.bin/seq/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/seq/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/seq/tests/seq_test.sh b/usr.bin/seq/tests/seq_test.sh
new file mode 100755
index 000000000000..342083ab4e1b
--- /dev/null
+++ b/usr.bin/seq/tests/seq_test.sh
@@ -0,0 +1,54 @@
+# Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case float_rounding
+float_rounding_head()
+{
+ atf_set "descr" "Check for correct termination in the face of floating point rounding"
+}
+float_rounding_body()
+{
+ atf_check -o inline:'1\n1.1\n1.2\n' seq 1 0.1 1.2
+}
+
+atf_test_case format_includes_conversion
+format_includes_conversion_head()
+{
+ atf_set "descr" "Check for correct user-provided format strings"
+}
+format_includes_conversion_body()
+{
+ # PR 236347
+ atf_check -s exit:1 -o empty -e match:"invalid format string" \
+ seq -f foo 3
+ atf_check -s exit:0 -o inline:'foo1\nfoo2\n' -e empty \
+ seq -f foo%g 2
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case float_rounding
+ atf_add_test_case format_includes_conversion
+}
diff --git a/usr.bin/shar/Makefile b/usr.bin/shar/Makefile
new file mode 100644
index 000000000000..fc940c06d463
--- /dev/null
+++ b/usr.bin/shar/Makefile
@@ -0,0 +1,4 @@
+SCRIPTS=shar.sh
+MAN= shar.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/shar/Makefile.depend b/usr.bin/shar/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/shar/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/shar/shar.1 b/usr.bin/shar/shar.1
new file mode 100644
index 000000000000..6beb1e84ceab
--- /dev/null
+++ b/usr.bin/shar/shar.1
@@ -0,0 +1,121 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.Dd January 1, 2025
+.Dt SHAR 1
+.Os
+.Sh NAME
+.Nm shar
+.Nd create a shell archive of files
+.Sh DEPRECATION NOTICE
+.Nm
+is obsolete and may not be present in
+.Fx 15
+and later.
+Because shell archives are simultaneously data and code and are typically
+interpreted by
+.Xr sh 1 ,
+they can easily be trojan-horsed and pose a significant security risk to users.
+The
+.Xr tar 1
+utility can still produce shar encodings of files if needed.
+The
+.Pa sysutils/freebsd-shar
+port has been created to maintain this version of
+.Nm
+past its deprecation in base.
+.Sh SYNOPSIS
+.Nm
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+command writes a
+.Xr sh 1
+shell script to the standard output which will recreate the file
+hierarchy specified by the command line operands.
+Directories will be recreated and must be specified before the
+files they contain (the
+.Xr find 1
+utility does this correctly).
+.Pp
+The
+.Nm
+command is normally used for distributing files by
+.Xr ftp 1
+or
+.Xr mail 1 .
+.Sh EXAMPLES
+To create a shell archive of the program
+.Xr ls 1
+and mail it to Rick:
+.Bd -literal -offset indent
+cd ls
+shar `find . -print` \&| mail -s "ls source" rick
+.Ed
+.Pp
+To recreate the program directory:
+.Bd -literal -offset indent
+mkdir ls
+cd ls
+\&...
+<delete header lines and examine mailed archive>
+\&...
+sh archive
+.Ed
+.Sh SEE ALSO
+.Xr compress 1 ,
+.Xr mail 1 ,
+.Xr tar 1 ,
+.Xr uuencode 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Nm
+command makes no provisions for special types of files or files containing
+magic characters.
+The
+.Nm
+command cannot handle files without a newline ('\\n')
+as the last character.
+.Pp
+It is easy to insert trojan horses into
+.Nm
+files.
+It is strongly recommended that all shell archive files be examined
+before running them through
+.Xr sh 1 .
+Archives produced using this implementation of
+.Nm
+may be easily examined with the command:
+.Bd -literal -offset indent
+egrep -av '^[X#]' shar.file
+.Ed
diff --git a/usr.bin/shar/shar.sh b/usr.bin/shar/shar.sh
new file mode 100644
index 000000000000..52c31b419fc4
--- /dev/null
+++ b/usr.bin/shar/shar.sh
@@ -0,0 +1,78 @@
+#!/bin/sh -
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 1990, 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.
+
+if [ $# -eq 0 ]; then
+ echo 'usage: shar file ...' 1>&2
+ exit 64 # EX_USAGE
+fi
+
+for i
+do
+ if [ ! \( -d $i -o -r $i \) ]; then
+ echo "$i inaccessible or not exist" 1>&2
+ exit 66 # EX_NOINPUT
+ fi
+done
+
+cat << EOF
+# This is a shell archive. Save it in a file, remove anything before
+# this line, and then unpack it by entering "sh file". Note, it may
+# create directories; files and directories will be owned by you and
+# have default permissions.
+#
+# This archive contains:
+#
+EOF
+
+for i
+do
+ echo "# $i"
+done
+
+echo "#"
+
+for i
+do
+ if [ -d "$i" ]; then
+ echo "echo c - '$i'"
+ echo "mkdir -p '$i' > /dev/null 2>&1"
+ else
+ md5sum=`echo -n "$i" | md5`
+ echo "echo x - '$i'"
+ echo "sed 's/^X//' >'$i' << '$md5sum'"
+ sed 's/^/X/' "$i" || exit 1
+ echo "$md5sum"
+ fi
+done
+echo exit
+echo ""
+
+exit 0
diff --git a/usr.bin/showmount/Makefile b/usr.bin/showmount/Makefile
new file mode 100644
index 000000000000..55f5de995422
--- /dev/null
+++ b/usr.bin/showmount/Makefile
@@ -0,0 +1,4 @@
+PROG= showmount
+MAN= showmount.8
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/showmount/Makefile.depend b/usr.bin/showmount/Makefile.depend
new file mode 100644
index 000000000000..a2d89550fa2b
--- /dev/null
+++ b/usr.bin/showmount/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/showmount/showmount.8 b/usr.bin/showmount/showmount.8
new file mode 100644
index 000000000000..9dd707ab1373
--- /dev/null
+++ b/usr.bin/showmount/showmount.8
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Rick Macklem at The University of Guelph.
+.\"
+.\" 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.
+.\"
+.Dd March 20, 2016
+.Dt SHOWMOUNT 8
+.Os
+.Sh NAME
+.Nm showmount
+.Nd show remote nfs mounts on host
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | d
+.Op Fl E
+.Op Fl e
+.Op Fl 1
+.Op Fl 3
+.Op Ar host
+.Sh DESCRIPTION
+The
+.Nm
+utility shows status information about the
+.Tn NFS
+server on
+.Ar host .
+By default it prints the names of all hosts that have
+.Tn NFS
+file systems mounted
+on the host.
+See
+.%T "NFS: Network File System Protocol Specification" ,
+RFC 1094,
+Appendix A,
+and
+.%T "NFS: Network File System Version 3 Protocol Specification" ,
+Appendix I,
+for a detailed description of the protocol.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a , Fl -all
+List all mount points in the form:
+.Bd -ragged -offset indent -compact
+.Ar host : Ns Ar dirpath .
+.Ed
+.It Fl d , Fl -directories
+List directory paths of mount points instead of hosts.
+.It Fl E , Fl -exports-script
+Show the
+.Ar host Ns 's
+exports list in a script-friendly format.
+Client addresses and the header are not shown, and special
+characters are escaped.
+.It Fl e , Fl -exports
+Show the
+.Ar host Ns 's
+exports list.
+.It Fl 1
+Use mount protocol Version 1, compatible with legacy servers.
+.It Fl 3
+Ignored for backwards compatibility.
+.El
+.Sh SEE ALSO
+.Xr mount 8 ,
+.Xr mount_nfs 8 ,
+.Xr mountd 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The mount daemon running on the server only has an idea of the actual mounts,
+since the
+.Tn NFS
+server is stateless.
+The
+.Nm
+utility will only display the information
+as accurately as the mount daemon reports it.
diff --git a/usr.bin/showmount/showmount.c b/usr.bin/showmount/showmount.c
new file mode 100644
index 000000000000..df067c36e678
--- /dev/null
+++ b/usr.bin/showmount/showmount.c
@@ -0,0 +1,414 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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/queue.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <err.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpcsvc/mount.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vis.h>
+
+/* Constant defs */
+#define ALL 1
+#define DIRS 2
+
+#define DODUMP 0x1
+#define DOEXPORTS 0x2
+#define DOPARSABLEEXPORTS 0x4
+
+struct mountlist {
+ struct mountlist *ml_left;
+ struct mountlist *ml_right;
+ char ml_host[MNTNAMLEN+1];
+ char ml_dirp[MNTPATHLEN+1];
+};
+
+struct grouplist {
+ struct grouplist *gr_next;
+ char gr_name[MNTNAMLEN+1];
+};
+
+struct exportslist {
+ struct exportslist *ex_next;
+ struct grouplist *ex_groups;
+ char ex_dirp[MNTPATHLEN+1];
+};
+
+static struct mountlist *mntdump;
+static struct exportslist *exportslist;
+static int type = 0;
+
+void print_dump(struct mountlist *);
+static void usage(void) __dead2;
+int xdr_mntdump(XDR *, struct mountlist **);
+int xdr_exportslist(XDR *, struct exportslist **);
+int tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out);
+
+static const struct option long_opts[] = {
+ { "all", no_argument, NULL, 'a' },
+ { "directories", no_argument, NULL, 'd' },
+ { "exports-script", no_argument, NULL, 'E' },
+ { "exports", no_argument, NULL, 'e' },
+ { NULL, 0, NULL, 0 },
+};
+
+/*
+ * This command queries the NFS mount daemon for it's mount list and/or
+ * it's exports list and prints them out.
+ * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
+ * and the "Network File System Protocol XXX.."
+ * for detailed information on the protocol.
+ */
+int
+main(int argc, char **argv)
+{
+ char strvised[MNTPATHLEN * 4 + 1];
+ register struct exportslist *exp;
+ register struct grouplist *grp;
+ register int rpcs = 0, mntvers = 3;
+ const char *host;
+ int ch, estat, nbytes;
+
+ while ((ch = getopt_long(argc, argv, "+adEe13", long_opts, NULL)) != -1)
+ switch (ch) {
+ case 'a':
+ if (type == 0) {
+ type = ALL;
+ rpcs |= DODUMP;
+ } else
+ usage();
+ break;
+ case 'd':
+ if (type == 0) {
+ type = DIRS;
+ rpcs |= DODUMP;
+ } else
+ usage();
+ break;
+ case 'E':
+ rpcs |= DOPARSABLEEXPORTS;
+ break;
+ case 'e':
+ rpcs |= DOEXPORTS;
+ break;
+ case '1':
+ mntvers = 1;
+ break;
+ case '3':
+ mntvers = 3;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((rpcs & DOPARSABLEEXPORTS) != 0) {
+ if ((rpcs & DOEXPORTS) != 0)
+ errx(1, "-E cannot be used with -e");
+ if ((rpcs & DODUMP) != 0)
+ errx(1, "-E cannot be used with -a or -d");
+ }
+
+ if (argc > 0)
+ host = *argv;
+ else
+ host = "localhost";
+
+ if (rpcs == 0)
+ rpcs = DODUMP;
+
+ if (rpcs & DODUMP)
+ if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
+ MOUNTPROC_DUMP, (xdrproc_t)xdr_void, (char *)0,
+ (xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) {
+ clnt_perrno(estat);
+ errx(1, "can't do mountdump rpc");
+ }
+ if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS))
+ if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
+ MOUNTPROC_EXPORT, (xdrproc_t)xdr_void, (char *)0,
+ (xdrproc_t)xdr_exportslist, (char *)&exportslist)) != 0) {
+ clnt_perrno(estat);
+ errx(1, "can't do exports rpc");
+ }
+
+ /* Now just print out the results */
+ if (rpcs & DODUMP) {
+ switch (type) {
+ case ALL:
+ printf("All mount points on %s:\n", host);
+ break;
+ case DIRS:
+ printf("Directories on %s:\n", host);
+ break;
+ default:
+ printf("Hosts on %s:\n", host);
+ break;
+ }
+ print_dump(mntdump);
+ }
+ if (rpcs & DOEXPORTS) {
+ printf("Exports list on %s:\n", host);
+ exp = exportslist;
+ while (exp) {
+ printf("%-34s ", exp->ex_dirp);
+ grp = exp->ex_groups;
+ if (grp == NULL) {
+ printf("Everyone\n");
+ } else {
+ while (grp) {
+ printf("%s ", grp->gr_name);
+ grp = grp->gr_next;
+ }
+ printf("\n");
+ }
+ exp = exp->ex_next;
+ }
+ }
+ if (rpcs & DOPARSABLEEXPORTS) {
+ exp = exportslist;
+ while (exp) {
+ nbytes = strsnvis(strvised, sizeof(strvised),
+ exp->ex_dirp, VIS_GLOB | VIS_NL, "\"'$");
+ if (nbytes == -1)
+ err(1, "strsnvis");
+ printf("%s\n", strvised);
+ exp = exp->ex_next;
+ }
+ }
+ exit(0);
+}
+
+/*
+ * tcp_callrpc has the same interface as callrpc, but tries to
+ * use tcp as transport method in order to handle large replies.
+ */
+int
+tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
+ xdrproc_t inproc, char *in, xdrproc_t outproc, char *out)
+{
+ CLIENT *client;
+ struct timeval timeout;
+ int rval;
+
+ if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL &&
+ (client = clnt_create(host, prognum, versnum, "udp")) == NULL)
+ return ((int) rpc_createerr.cf_stat);
+
+ timeout.tv_sec = 25;
+ timeout.tv_usec = 0;
+ rval = (int) clnt_call(client, procnum,
+ inproc, in,
+ outproc, out,
+ timeout);
+ clnt_destroy(client);
+ return rval;
+}
+
+/*
+ * Xdr routine for retrieving the mount dump list
+ */
+int
+xdr_mntdump(XDR *xdrsp, struct mountlist **mlp)
+{
+ register struct mountlist *mp;
+ register struct mountlist *tp;
+ register struct mountlist **otp;
+ int val, val2;
+ int bool;
+ char *strp;
+
+ *mlp = (struct mountlist *)0;
+ if (!xdr_bool(xdrsp, &bool))
+ return (0);
+ while (bool) {
+ mp = (struct mountlist *)malloc(sizeof(struct mountlist));
+ if (mp == NULL)
+ return (0);
+ mp->ml_left = mp->ml_right = (struct mountlist *)0;
+ strp = mp->ml_host;
+ if (!xdr_string(xdrsp, &strp, MNTNAMLEN)) {
+ free(mp);
+ return (0);
+ }
+ strp = mp->ml_dirp;
+ if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) {
+ free(mp);
+ return (0);
+ }
+
+ /*
+ * Build a binary tree on sorted order of either host or dirp.
+ * Drop any duplications.
+ */
+ if (*mlp == NULL) {
+ *mlp = mp;
+ } else {
+ tp = *mlp;
+ while (tp) {
+ val = strcmp(mp->ml_host, tp->ml_host);
+ val2 = strcmp(mp->ml_dirp, tp->ml_dirp);
+ switch (type) {
+ case ALL:
+ if (val == 0) {
+ if (val2 == 0) {
+ free((caddr_t)mp);
+ goto next;
+ }
+ val = val2;
+ }
+ break;
+ case DIRS:
+ if (val2 == 0) {
+ free((caddr_t)mp);
+ goto next;
+ }
+ val = val2;
+ break;
+ default:
+ if (val == 0) {
+ free((caddr_t)mp);
+ goto next;
+ }
+ break;
+ }
+ if (val < 0) {
+ otp = &tp->ml_left;
+ tp = tp->ml_left;
+ } else {
+ otp = &tp->ml_right;
+ tp = tp->ml_right;
+ }
+ }
+ *otp = mp;
+ }
+next:
+ if (!xdr_bool(xdrsp, &bool))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Xdr routine to retrieve exports list
+ */
+int
+xdr_exportslist(XDR *xdrsp, struct exportslist **exp)
+{
+ register struct exportslist *ep;
+ register struct grouplist *gp;
+ int bool, grpbool;
+ char *strp;
+
+ *exp = (struct exportslist *)0;
+ if (!xdr_bool(xdrsp, &bool))
+ return (0);
+ while (bool) {
+ ep = (struct exportslist *)malloc(sizeof(struct exportslist));
+ if (ep == NULL)
+ return (0);
+ ep->ex_groups = (struct grouplist *)0;
+ strp = ep->ex_dirp;
+ if (!xdr_string(xdrsp, &strp, MNTPATHLEN))
+ return (0);
+ if (!xdr_bool(xdrsp, &grpbool))
+ return (0);
+ while (grpbool) {
+ gp = (struct grouplist *)malloc(sizeof(struct grouplist));
+ if (gp == NULL)
+ return (0);
+ strp = gp->gr_name;
+ if (!xdr_string(xdrsp, &strp, MNTNAMLEN))
+ return (0);
+ gp->gr_next = ep->ex_groups;
+ ep->ex_groups = gp;
+ if (!xdr_bool(xdrsp, &grpbool))
+ return (0);
+ }
+ ep->ex_next = *exp;
+ *exp = ep;
+ if (!xdr_bool(xdrsp, &bool))
+ return (0);
+ }
+ return (1);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n");
+ exit(1);
+}
+
+/*
+ * Print the binary tree in inorder so that output is sorted.
+ */
+void
+print_dump(struct mountlist *mp)
+{
+
+ if (mp == NULL)
+ return;
+ if (mp->ml_left)
+ print_dump(mp->ml_left);
+ switch (type) {
+ case ALL:
+ printf("%s:%s\n", mp->ml_host, mp->ml_dirp);
+ break;
+ case DIRS:
+ printf("%s\n", mp->ml_dirp);
+ break;
+ default:
+ printf("%s\n", mp->ml_host);
+ break;
+ }
+ if (mp->ml_right)
+ print_dump(mp->ml_right);
+}
diff --git a/usr.bin/size/Makefile b/usr.bin/size/Makefile
new file mode 100644
index 000000000000..3951cedbfa05
--- /dev/null
+++ b/usr.bin/size/Makefile
@@ -0,0 +1,22 @@
+.include <src.opts.mk>
+
+PACKAGE= elftoolchain
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+SIZEDIR= ${ELFTCDIR}/size
+
+.PATH: ${SIZEDIR}
+
+PROG= size
+
+LIBADD= elftc elf
+
+.if ${MK_CASPER} != "no" && !defined(BOOTSTRAPPING) && !defined(NXB_TARGET)
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/size/Makefile.depend b/usr.bin/size/Makefile.depend
new file mode 100644
index 000000000000..fff85220223b
--- /dev/null
+++ b/usr.bin/size/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libelf \
+ lib/libelftc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/size/Makefile.depend.options b/usr.bin/size/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/size/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/smbutil/Makefile b/usr.bin/smbutil/Makefile
new file mode 100644
index 000000000000..de80d48282ea
--- /dev/null
+++ b/usr.bin/smbutil/Makefile
@@ -0,0 +1,14 @@
+PROG= smbutil
+PACKAGE= smbutils
+SRCS= smbutil.c dumptree.c login.c lookup.c view.c print.c
+
+LIBADD= smb
+
+CONTRIBDIR= ${SRCTOP}/contrib/smbfs
+CFLAGS+= -I${CONTRIBDIR}/include
+
+WARNS?= 0
+
+.PATH: ${CONTRIBDIR}/smbutil
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/smbutil/Makefile.depend b/usr.bin/smbutil/Makefile.depend
new file mode 100644
index 000000000000..3fb260c870a1
--- /dev/null
+++ b/usr.bin/smbutil/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsmb \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sockstat/Makefile b/usr.bin/sockstat/Makefile
new file mode 100644
index 000000000000..188432dfc27e
--- /dev/null
+++ b/usr.bin/sockstat/Makefile
@@ -0,0 +1,16 @@
+.include <src.opts.mk>
+
+PROG= sockstat
+
+LIBADD= jail
+
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_net
+LIBADD+= cap_netdb
+LIBADD+= cap_pwd
+LIBADD+= cap_sysctl
+CFLAGS+= -DWITH_CASPER
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sockstat/Makefile.depend b/usr.bin/sockstat/Makefile.depend
new file mode 100644
index 000000000000..a03493510d56
--- /dev/null
+++ b/usr.bin/sockstat/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcasper/services/cap_net \
+ lib/libcasper/services/cap_netdb \
+ lib/libcasper/services/cap_pwd \
+ lib/libcasper/services/cap_sysctl \
+ lib/libcompiler_rt \
+ lib/libjail \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1
new file mode 100644
index 000000000000..b13c6afdd9c0
--- /dev/null
+++ b/usr.bin/sockstat/sockstat.1
@@ -0,0 +1,249 @@
+.\"-
+.\" Copyright (c) 1999 Dag-Erling Smørgrav
+.\" 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
+.\" in this position and unchanged.
+.\" 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.
+.\"
+.Dd February 6, 2025
+.Dt SOCKSTAT 1
+.Os
+.Sh NAME
+.Nm sockstat
+.Nd list open sockets
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46ACcfIiLlnqSsUuvw
+.Op Fl j Ar jail
+.Op Fl p Ar ports
+.Op Fl P Ar protocols
+.Sh DESCRIPTION
+The
+.Nm
+command lists open Internet or
+.Ux
+domain sockets.
+.Pp
+The following options are available:
+.Bl -tag -width Fl
+.It Fl 4
+Show
+.Dv AF_INET
+(IPv4) sockets.
+.It Fl 6
+Show
+.Dv AF_INET6
+(IPv6) sockets.
+.It Fl A
+Show the address of a protocol control block (PCB) associated with a socket;
+used for debugging.
+.It Fl C
+Display the congestion control module, if applicable.
+This is currently only implemented for TCP.
+.It Fl c
+Show connected sockets.
+.It Fl f
+Show the FIB number of each socket.
+.It Fl I
+Show the local address of the socket to which the current socket is spliced, if
+any.
+See the
+.Xr setsockopt 2
+.Dv SO_SPLICE
+option for more information.
+.It Fl i
+Display the
+.Dv inp_gencnt .
+.It Fl j Ar jail
+Show only sockets belonging to the specified jail ID or name.
+.It Fl L
+Only show Internet sockets if the local and foreign addresses are not
+in the loopback network prefix
+.Li 127.0.0.0/8 ,
+or do not contain the IPv6 loopback address
+.Li ::1 .
+.It Fl l
+Show listening sockets.
+.It Fl n
+Do not resolve numeric UIDs to user names.
+.It Fl p Ar ports
+Only show Internet sockets if the local or foreign port number
+is on the specified list.
+The
+.Ar ports
+argument is a comma-separated list of port numbers and ranges
+specified as first and last port separated by a dash.
+.It Fl P Ar protocols
+Only show sockets of the specified
+.Ar protocols .
+The
+.Ar protocols
+argument is a comma-separated list of protocol names,
+as they are defined in
+.Xr protocols 5 .
+.It Fl q
+Quiet mode, do not print the header line.
+.It Fl S
+Display the protocol stack, if applicable.
+This is currently only implemented for TCP.
+.It Fl s
+Display the protocol state, if applicable.
+This is currently only implemented for SCTP and TCP.
+.It Fl U
+Display the remote UDP encapsulation port number, if applicable.
+This is currently only implemented for SCTP and TCP.
+.It Fl u
+Show
+.Dv AF_LOCAL
+.Pq Ux
+sockets.
+.It Fl v
+Verbose mode.
+.It Fl w
+Use wider field size for displaying addresses.
+.El
+.Pp
+If neither
+.Fl 4 , 6
+or
+.Fl u
+is specified,
+.Nm
+will list sockets in all three domains.
+.Pp
+If neither
+.Fl c
+or
+.Fl l
+is specified,
+.Nm
+will list both listening and connected sockets.
+.Pp
+The information listed for each
+socket is:
+.Bl -tag -width "FOREIGN ADDRESS"
+.It Li USER
+The user who owns the socket.
+.It Li COMMAND
+The command which holds the socket.
+.It Li PID
+The process ID of the command which holds the socket.
+.It Li FD
+The file descriptor number of the socket.
+.It Li PROTO
+The transport protocol associated with the socket for Internet
+sockets, or the type of socket
+.Pq stream, datagram, or seqpacket
+for
+.Ux
+sockets.
+.It Li LOCAL ADDRESS
+For Internet sockets, this is the address the local end of the socket
+is bound to (see
+.Xr getsockname 2 ) .
+.Pp
+For bound
+.Ux
+sockets, socket's filename is printed.
+For not bound
+.Ux
+sockets, the field is empty.
+.It Li FOREIGN ADDRESS
+For Internet sockets, this is the address the foreign end of the socket
+is bound to (see
+.Xr getpeername 2 ) .
+.Pp
+For bound
+.Ux
+sockets a left arrow followed by the peer list is printed.
+For
+.Ux
+sockets that went through
+.Xr connect 2
+system call a right arrow followed by the peer is printed.
+Peers are printed in square brackets as [PID FD].
+.It Li ID
+The inp_gencnt if
+.Fl i
+is specified (only for TCP or UDP).
+.It Li ENCAPS
+The remote UDP encapsulation port number if
+.Fl U
+is specified (only for SCTP or TCP).
+.It Li PATH STATE
+The path state if
+.Fl s
+is specified (only for SCTP).
+.It Li CONN STATE
+The connection state if
+.Fl s
+is specified (only for SCTP or TCP).
+.It Li STACK
+The protocol stack if
+.Fl S
+is specified (only for TCP).
+.It Li CC
+The congestion control if
+.Fl C
+is specified (only for TCP).
+.El
+.Pp
+If a socket is associated with more than one file descriptor,
+it is shown multiple times.
+If a socket is not associated with any file descriptor,
+the first four columns have no meaning.
+.Sh EXAMPLES
+Show information for IPv4 sockets listening on port 22 using protocol
+TCP:
+.Bd -literal -offset indent
+$ sockstat -4 -l -P tcp -p 22
+.Ed
+.Pp
+Show information for sockets using either TCP or UDP, if neither, the local nor
+the foreign addresses are in the loopback network:
+.Bd -literal -offset indent
+$ sockstat -L -P tcp,udp
+.Ed
+.Pp
+Show TCP IPv6 sockets which are listening and connected (default):
+.Bd -literal -offset indent
+$ sockstat -6 -P tcp
+.Ed
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr procstat 1 ,
+.Xr setfib 1 ,
+.Xr inet 4 ,
+.Xr inet6 4 ,
+.Xr protocols 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 3.1 .
+.Sh AUTHORS
+The
+.Nm
+command and this manual page were written by
+.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org .
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
new file mode 100644
index 000000000000..e1a52c57b3d1
--- /dev/null
+++ b/usr.bin/sockstat/sockstat.c
@@ -0,0 +1,1646 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Dag-Erling Smørgrav
+ * 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
+ * in this position and unchanged.
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/jail.h>
+#include <sys/user.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+
+#include <sys/un.h>
+#include <sys/unpcb.h>
+
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#include <netinet/sctp.h>
+#include <netinet/tcp.h>
+#define TCPSTATES /* load state names */
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_var.h>
+#include <arpa/inet.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <jail.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_net.h>
+#include <casper/cap_netdb.h>
+#include <casper/cap_pwd.h>
+#include <casper/cap_sysctl.h>
+
+#define sstosin(ss) ((struct sockaddr_in *)(ss))
+#define sstosin6(ss) ((struct sockaddr_in6 *)(ss))
+#define sstosun(ss) ((struct sockaddr_un *)(ss))
+#define sstosa(ss) ((struct sockaddr *)(ss))
+
+static bool opt_4; /* Show IPv4 sockets */
+static bool opt_6; /* Show IPv6 sockets */
+static bool opt_A; /* Show kernel address of pcb */
+static bool opt_C; /* Show congestion control */
+static bool opt_c; /* Show connected sockets */
+static bool opt_f; /* Show FIB numbers */
+static bool opt_I; /* Show spliced socket addresses */
+static bool opt_i; /* Show inp_gencnt */
+static int opt_j; /* Show specified jail */
+static bool opt_L; /* Don't show IPv4 or IPv6 loopback sockets */
+static bool opt_l; /* Show listening sockets */
+static bool opt_n; /* Don't resolve UIDs to user names */
+static bool opt_q; /* Don't show header */
+static bool opt_S; /* Show protocol stack if applicable */
+static bool opt_s; /* Show protocol state if applicable */
+static bool opt_U; /* Show remote UDP encapsulation port number */
+static bool opt_u; /* Show Unix domain sockets */
+static u_int opt_v; /* Verbose mode */
+static bool opt_w; /* Wide print area for addresses */
+
+/*
+ * Default protocols to use if no -P was defined.
+ */
+static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" };
+static size_t default_numprotos = nitems(default_protos);
+
+static int *protos; /* protocols to use */
+static size_t numprotos; /* allocated size of protos[] */
+
+static int *ports;
+
+#define INT_BIT (sizeof(int)*CHAR_BIT)
+#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0)
+#define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
+
+struct addr {
+ union {
+ struct sockaddr_storage address;
+ struct { /* unix(4) faddr */
+ kvaddr_t conn;
+ kvaddr_t firstref;
+ kvaddr_t nextref;
+ };
+ };
+ unsigned int encaps_port;
+ int state;
+ struct addr *next;
+};
+
+struct sock {
+ union {
+ RB_ENTRY(sock) socket_tree; /* tree of pcbs with socket */
+ SLIST_ENTRY(sock) socket_list; /* list of pcbs w/o socket */
+ };
+ RB_ENTRY(sock) pcb_tree;
+ kvaddr_t socket;
+ kvaddr_t pcb;
+ kvaddr_t splice_socket;
+ uint64_t inp_gencnt;
+ int shown;
+ int vflag;
+ int family;
+ int proto;
+ int state;
+ int fibnum;
+ const char *protoname;
+ char stack[TCP_FUNCTION_NAME_LEN_MAX];
+ char cc[TCP_CA_NAME_MAX];
+ struct addr *laddr;
+ struct addr *faddr;
+};
+
+static RB_HEAD(socks_t, sock) socks = RB_INITIALIZER(&socks);
+static int64_t
+socket_compare(const struct sock *a, const struct sock *b)
+{
+ return ((int64_t)(a->socket/2 - b->socket/2));
+}
+RB_GENERATE_STATIC(socks_t, sock, socket_tree, socket_compare);
+
+static RB_HEAD(pcbs_t, sock) pcbs = RB_INITIALIZER(&pcbs);
+static int64_t
+pcb_compare(const struct sock *a, const struct sock *b)
+{
+ return ((int64_t)(a->pcb/2 - b->pcb/2));
+}
+RB_GENERATE_STATIC(pcbs_t, sock, pcb_tree, pcb_compare);
+
+static SLIST_HEAD(, sock) nosocks = SLIST_HEAD_INITIALIZER(&nosocks);
+
+struct file {
+ RB_ENTRY(file) file_tree;
+ kvaddr_t xf_data;
+ pid_t xf_pid;
+ uid_t xf_uid;
+ int xf_fd;
+};
+
+static RB_HEAD(files_t, file) ftree = RB_INITIALIZER(&ftree);
+static int64_t
+file_compare(const struct file *a, const struct file *b)
+{
+ return ((int64_t)(a->xf_data/2 - b->xf_data/2));
+}
+RB_GENERATE_STATIC(files_t, file, file_tree, file_compare);
+
+static struct file *files;
+static int nfiles;
+
+static cap_channel_t *capnet;
+static cap_channel_t *capnetdb;
+static cap_channel_t *capsysctl;
+static cap_channel_t *cappwd;
+
+static int
+xprintf(const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = vprintf(fmt, ap);
+ va_end(ap);
+ if (len < 0)
+ err(1, "printf()");
+ return (len);
+}
+
+static bool
+_check_ksize(size_t received_size, size_t expected_size, const char *struct_name)
+{
+ if (received_size != expected_size) {
+ warnx("%s size mismatch: expected %zd, received %zd",
+ struct_name, expected_size, received_size);
+ return false;
+ }
+ return true;
+}
+#define check_ksize(_sz, _struct) (_check_ksize(_sz, sizeof(_struct), #_struct))
+
+static void
+_enforce_ksize(size_t received_size, size_t expected_size, const char *struct_name)
+{
+ if (received_size != expected_size) {
+ errx(1, "fatal: struct %s size mismatch: expected %zd, received %zd",
+ struct_name, expected_size, received_size);
+ }
+}
+#define enforce_ksize(_sz, _struct) (_enforce_ksize(_sz, sizeof(_struct), #_struct))
+
+static int
+get_proto_type(const char *proto)
+{
+ struct protoent *pent;
+
+ if (strlen(proto) == 0)
+ return (0);
+ if (capnetdb != NULL)
+ pent = cap_getprotobyname(capnetdb, proto);
+ else
+ pent = getprotobyname(proto);
+ if (pent == NULL) {
+ warn("cap_getprotobyname");
+ return (-1);
+ }
+ return (pent->p_proto);
+}
+
+static void
+init_protos(int num)
+{
+ int proto_count = 0;
+
+ if (num > 0) {
+ proto_count = num;
+ } else {
+ /* Find the maximum number of possible protocols. */
+ while (getprotoent() != NULL)
+ proto_count++;
+ endprotoent();
+ }
+
+ if ((protos = malloc(sizeof(int) * proto_count)) == NULL)
+ err(1, "malloc");
+ numprotos = proto_count;
+}
+
+static int
+parse_protos(char *protospec)
+{
+ char *prot;
+ int proto_type, proto_index;
+
+ if (protospec == NULL)
+ return (-1);
+
+ init_protos(0);
+ proto_index = 0;
+ while ((prot = strsep(&protospec, ",")) != NULL) {
+ if (strlen(prot) == 0)
+ continue;
+ proto_type = get_proto_type(prot);
+ if (proto_type != -1)
+ protos[proto_index++] = proto_type;
+ }
+ numprotos = proto_index;
+ return (proto_index);
+}
+
+static void
+parse_ports(const char *portspec)
+{
+ const char *p, *q;
+ int port, end;
+
+ if (ports == NULL)
+ if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL)
+ err(1, "calloc()");
+ p = portspec;
+ while (*p != '\0') {
+ if (!isdigit(*p))
+ errx(1, "syntax error in port range");
+ for (q = p; *q != '\0' && isdigit(*q); ++q)
+ /* nothing */ ;
+ for (port = 0; p < q; ++p)
+ port = port * 10 + digittoint(*p);
+ if (port < 0 || port > 65535)
+ errx(1, "invalid port number");
+ SET_PORT(port);
+ switch (*p) {
+ case '-':
+ ++p;
+ break;
+ case ',':
+ ++p;
+ /* fall through */
+ case '\0':
+ default:
+ continue;
+ }
+ for (q = p; *q != '\0' && isdigit(*q); ++q)
+ /* nothing */ ;
+ for (end = 0; p < q; ++p)
+ end = end * 10 + digittoint(*p);
+ if (end < port || end > 65535)
+ errx(1, "invalid port number");
+ while (port++ < end)
+ SET_PORT(port);
+ if (*p == ',')
+ ++p;
+ }
+}
+
+static void
+sockaddr(struct sockaddr_storage *ss, int af, void *addr, int port)
+{
+ struct sockaddr_in *sin4;
+ struct sockaddr_in6 *sin6;
+
+ bzero(ss, sizeof(*ss));
+ switch (af) {
+ case AF_INET:
+ sin4 = sstosin(ss);
+ sin4->sin_len = sizeof(*sin4);
+ sin4->sin_family = af;
+ sin4->sin_port = port;
+ sin4->sin_addr = *(struct in_addr *)addr;
+ break;
+ case AF_INET6:
+ sin6 = sstosin6(ss);
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = af;
+ sin6->sin6_port = port;
+ sin6->sin6_addr = *(struct in6_addr *)addr;
+#define s6_addr16 __u6_addr.__u6_addr16
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(sin6->sin6_addr.s6_addr16[1]);
+ sin6->sin6_addr.s6_addr16[1] = 0;
+ }
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+free_socket(struct sock *sock)
+{
+ struct addr *cur, *next;
+
+ cur = sock->laddr;
+ while (cur != NULL) {
+ next = cur->next;
+ free(cur);
+ cur = next;
+ }
+ cur = sock->faddr;
+ while (cur != NULL) {
+ next = cur->next;
+ free(cur);
+ cur = next;
+ }
+ free(sock);
+}
+
+static void
+gather_sctp(void)
+{
+ struct sock *sock;
+ struct addr *laddr, *prev_laddr, *faddr, *prev_faddr;
+ struct xsctp_inpcb *xinpcb;
+ struct xsctp_tcb *xstcb;
+ struct xsctp_raddr *xraddr;
+ struct xsctp_laddr *xladdr;
+ const char *varname;
+ size_t len, offset;
+ char *buf;
+ int vflag;
+ int no_stcb, local_all_loopback, foreign_all_loopback;
+
+ vflag = 0;
+ if (opt_4)
+ vflag |= INP_IPV4;
+ if (opt_6)
+ vflag |= INP_IPV6;
+
+ varname = "net.inet.sctp.assoclist";
+ if (cap_sysctlbyname(capsysctl, varname, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ err(1, "cap_sysctlbyname()");
+ return;
+ }
+ if ((buf = (char *)malloc(len)) == NULL) {
+ err(1, "malloc()");
+ return;
+ }
+ if (cap_sysctlbyname(capsysctl, varname, buf, &len, 0, 0) < 0) {
+ err(1, "cap_sysctlbyname()");
+ free(buf);
+ return;
+ }
+ xinpcb = (struct xsctp_inpcb *)(void *)buf;
+ offset = sizeof(struct xsctp_inpcb);
+ while ((offset < len) && (xinpcb->last == 0)) {
+ if ((sock = calloc(1, sizeof *sock)) == NULL)
+ err(1, "malloc()");
+ sock->socket = xinpcb->socket;
+ sock->proto = IPPROTO_SCTP;
+ sock->protoname = "sctp";
+ if (xinpcb->maxqlen == 0)
+ sock->state = SCTP_CLOSED;
+ else
+ sock->state = SCTP_LISTEN;
+ if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ sock->family = AF_INET6;
+ /*
+ * Currently there is no way to distinguish between
+ * IPv6 only sockets or dual family sockets.
+ * So mark it as dual socket.
+ */
+ sock->vflag = INP_IPV6 | INP_IPV4;
+ } else {
+ sock->family = AF_INET;
+ sock->vflag = INP_IPV4;
+ }
+ prev_laddr = NULL;
+ local_all_loopback = 1;
+ while (offset < len) {
+ xladdr = (struct xsctp_laddr *)(void *)(buf + offset);
+ offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ if ((laddr = calloc(1, sizeof(struct addr))) == NULL)
+ err(1, "malloc()");
+ switch (xladdr->address.sa.sa_family) {
+ case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ if (!__IN_IS_ADDR_LOOPBACK(
+ &xladdr->address.sin.sin_addr))
+ local_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+ sockaddr(&laddr->address, AF_INET,
+ &xladdr->address.sin.sin_addr,
+ htons(xinpcb->local_port));
+ break;
+ case AF_INET6:
+ if (!IN6_IS_ADDR_LOOPBACK(
+ &xladdr->address.sin6.sin6_addr))
+ local_all_loopback = 0;
+ sockaddr(&laddr->address, AF_INET6,
+ &xladdr->address.sin6.sin6_addr,
+ htons(xinpcb->local_port));
+ break;
+ default:
+ errx(1, "address family %d not supported",
+ xladdr->address.sa.sa_family);
+ }
+ laddr->next = NULL;
+ if (prev_laddr == NULL)
+ sock->laddr = laddr;
+ else
+ prev_laddr->next = laddr;
+ prev_laddr = laddr;
+ }
+ if (sock->laddr == NULL) {
+ if ((sock->laddr =
+ calloc(1, sizeof(struct addr))) == NULL)
+ err(1, "malloc()");
+ sock->laddr->address.ss_family = sock->family;
+ if (sock->family == AF_INET)
+ sock->laddr->address.ss_len =
+ sizeof(struct sockaddr_in);
+ else
+ sock->laddr->address.ss_len =
+ sizeof(struct sockaddr_in6);
+ local_all_loopback = 0;
+ }
+ if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL)
+ err(1, "malloc()");
+ sock->faddr->address.ss_family = sock->family;
+ if (sock->family == AF_INET)
+ sock->faddr->address.ss_len =
+ sizeof(struct sockaddr_in);
+ else
+ sock->faddr->address.ss_len =
+ sizeof(struct sockaddr_in6);
+ no_stcb = 1;
+ while (offset < len) {
+ xstcb = (struct xsctp_tcb *)(void *)(buf + offset);
+ offset += sizeof(struct xsctp_tcb);
+ if (no_stcb) {
+ if (opt_l && (sock->vflag & vflag) &&
+ (!opt_L || !local_all_loopback) &&
+ ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) ||
+ (xstcb->last == 1))) {
+ RB_INSERT(socks_t, &socks, sock);
+ } else {
+ free_socket(sock);
+ }
+ }
+ if (xstcb->last == 1)
+ break;
+ no_stcb = 0;
+ if (opt_c) {
+ if ((sock = calloc(1, sizeof *sock)) == NULL)
+ err(1, "malloc()");
+ sock->socket = xinpcb->socket;
+ sock->proto = IPPROTO_SCTP;
+ sock->protoname = "sctp";
+ sock->state = (int)xstcb->state;
+ if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ sock->family = AF_INET6;
+ /*
+ * Currently there is no way to distinguish
+ * between IPv6 only sockets or dual family
+ * sockets. So mark it as dual socket.
+ */
+ sock->vflag = INP_IPV6 | INP_IPV4;
+ } else {
+ sock->family = AF_INET;
+ sock->vflag = INP_IPV4;
+ }
+ }
+ prev_laddr = NULL;
+ local_all_loopback = 1;
+ while (offset < len) {
+ xladdr = (struct xsctp_laddr *)(void *)(buf +
+ offset);
+ offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ if (!opt_c)
+ continue;
+ laddr = calloc(1, sizeof(struct addr));
+ if (laddr == NULL)
+ err(1, "malloc()");
+ switch (xladdr->address.sa.sa_family) {
+ case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ if (!__IN_IS_ADDR_LOOPBACK(
+ &xladdr->address.sin.sin_addr))
+ local_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+ sockaddr(&laddr->address, AF_INET,
+ &xladdr->address.sin.sin_addr,
+ htons(xstcb->local_port));
+ break;
+ case AF_INET6:
+ if (!IN6_IS_ADDR_LOOPBACK(
+ &xladdr->address.sin6.sin6_addr))
+ local_all_loopback = 0;
+ sockaddr(&laddr->address, AF_INET6,
+ &xladdr->address.sin6.sin6_addr,
+ htons(xstcb->local_port));
+ break;
+ default:
+ errx(1,
+ "address family %d not supported",
+ xladdr->address.sa.sa_family);
+ }
+ laddr->next = NULL;
+ if (prev_laddr == NULL)
+ sock->laddr = laddr;
+ else
+ prev_laddr->next = laddr;
+ prev_laddr = laddr;
+ }
+ prev_faddr = NULL;
+ foreign_all_loopback = 1;
+ while (offset < len) {
+ xraddr = (struct xsctp_raddr *)(void *)(buf +
+ offset);
+ offset += sizeof(struct xsctp_raddr);
+ if (xraddr->last == 1)
+ break;
+ if (!opt_c)
+ continue;
+ faddr = calloc(1, sizeof(struct addr));
+ if (faddr == NULL)
+ err(1, "malloc()");
+ switch (xraddr->address.sa.sa_family) {
+ case AF_INET:
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ if (!__IN_IS_ADDR_LOOPBACK(
+ &xraddr->address.sin.sin_addr))
+ foreign_all_loopback = 0;
+#undef __IN_IS_ADDR_LOOPBACK
+ sockaddr(&faddr->address, AF_INET,
+ &xraddr->address.sin.sin_addr,
+ htons(xstcb->remote_port));
+ break;
+ case AF_INET6:
+ if (!IN6_IS_ADDR_LOOPBACK(
+ &xraddr->address.sin6.sin6_addr))
+ foreign_all_loopback = 0;
+ sockaddr(&faddr->address, AF_INET6,
+ &xraddr->address.sin6.sin6_addr,
+ htons(xstcb->remote_port));
+ break;
+ default:
+ errx(1,
+ "address family %d not supported",
+ xraddr->address.sa.sa_family);
+ }
+ faddr->encaps_port = xraddr->encaps_port;
+ faddr->state = xraddr->state;
+ faddr->next = NULL;
+ if (prev_faddr == NULL)
+ sock->faddr = faddr;
+ else
+ prev_faddr->next = faddr;
+ prev_faddr = faddr;
+ }
+ if (opt_c) {
+ if ((sock->vflag & vflag) &&
+ (!opt_L ||
+ !(local_all_loopback ||
+ foreign_all_loopback))) {
+ RB_INSERT(socks_t, &socks, sock);
+ } else {
+ free_socket(sock);
+ }
+ }
+ }
+ xinpcb = (struct xsctp_inpcb *)(void *)(buf + offset);
+ offset += sizeof(struct xsctp_inpcb);
+ }
+ free(buf);
+}
+
+static void
+gather_inet(int proto)
+{
+ struct xinpgen *xig, *exig;
+ struct xinpcb *xip;
+ struct xtcpcb *xtp = NULL;
+ struct xsocket *so;
+ struct sock *sock;
+ struct addr *laddr, *faddr;
+ const char *varname, *protoname;
+ size_t len, bufsize;
+ void *buf;
+ int retry, vflag;
+
+ vflag = 0;
+ if (opt_4)
+ vflag |= INP_IPV4;
+ if (opt_6)
+ vflag |= INP_IPV6;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ varname = "net.inet.tcp.pcblist";
+ protoname = "tcp";
+ break;
+ case IPPROTO_UDP:
+ varname = "net.inet.udp.pcblist";
+ protoname = "udp";
+ break;
+ case IPPROTO_DIVERT:
+ varname = "net.inet.divert.pcblist";
+ protoname = "div";
+ break;
+ default:
+ errx(1, "protocol %d not supported", proto);
+ }
+
+ buf = NULL;
+ bufsize = 8192;
+ retry = 5;
+ do {
+ for (;;) {
+ if ((buf = realloc(buf, bufsize)) == NULL)
+ err(1, "realloc()");
+ len = bufsize;
+ if (cap_sysctlbyname(capsysctl, varname, buf, &len,
+ NULL, 0) == 0)
+ break;
+ if (errno == ENOENT)
+ goto out;
+ if (errno != ENOMEM || len != bufsize)
+ err(1, "cap_sysctlbyname()");
+ bufsize *= 2;
+ }
+ xig = (struct xinpgen *)buf;
+ exig = (struct xinpgen *)(void *)
+ ((char *)buf + len - sizeof *exig);
+ enforce_ksize(xig->xig_len, struct xinpgen);
+ enforce_ksize(exig->xig_len, struct xinpgen);
+ } while (xig->xig_gen != exig->xig_gen && retry--);
+
+ if (xig->xig_gen != exig->xig_gen && opt_v)
+ warnx("warning: data may be inconsistent");
+
+ for (;;) {
+ xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
+ if (xig >= exig)
+ break;
+ switch (proto) {
+ case IPPROTO_TCP:
+ xtp = (struct xtcpcb *)xig;
+ xip = &xtp->xt_inp;
+ if (!check_ksize(xtp->xt_len, struct xtcpcb))
+ goto out;
+ protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp";
+ break;
+ case IPPROTO_UDP:
+ case IPPROTO_DIVERT:
+ xip = (struct xinpcb *)xig;
+ if (!check_ksize(xip->xi_len, struct xinpcb))
+ goto out;
+ break;
+ default:
+ errx(1, "protocol %d not supported", proto);
+ }
+ so = &xip->xi_socket;
+ if ((xip->inp_vflag & vflag) == 0)
+ continue;
+ if (xip->inp_vflag & INP_IPV4) {
+ if ((xip->inp_fport == 0 && !opt_l) ||
+ (xip->inp_fport != 0 && !opt_c))
+ continue;
+#define __IN_IS_ADDR_LOOPBACK(pina) \
+ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ if (opt_L &&
+ (__IN_IS_ADDR_LOOPBACK(&xip->inp_faddr) ||
+ __IN_IS_ADDR_LOOPBACK(&xip->inp_laddr)))
+ continue;
+#undef __IN_IS_ADDR_LOOPBACK
+ } else if (xip->inp_vflag & INP_IPV6) {
+ if ((xip->inp_fport == 0 && !opt_l) ||
+ (xip->inp_fport != 0 && !opt_c))
+ continue;
+ if (opt_L &&
+ (IN6_IS_ADDR_LOOPBACK(&xip->in6p_faddr) ||
+ IN6_IS_ADDR_LOOPBACK(&xip->in6p_laddr)))
+ continue;
+ } else {
+ if (opt_v)
+ warnx("invalid vflag 0x%x", xip->inp_vflag);
+ continue;
+ }
+ if ((sock = calloc(1, sizeof(*sock))) == NULL)
+ err(1, "malloc()");
+ if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+ err(1, "malloc()");
+ if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+ err(1, "malloc()");
+ sock->socket = so->xso_so;
+ sock->pcb = so->so_pcb;
+ sock->splice_socket = so->so_splice_so;
+ sock->proto = proto;
+ sock->inp_gencnt = xip->inp_gencnt;
+ sock->fibnum = so->so_fibnum;
+ if (xip->inp_vflag & INP_IPV4) {
+ sock->family = AF_INET;
+ sockaddr(&laddr->address, sock->family,
+ &xip->inp_laddr, xip->inp_lport);
+ sockaddr(&faddr->address, sock->family,
+ &xip->inp_faddr, xip->inp_fport);
+ } else if (xip->inp_vflag & INP_IPV6) {
+ sock->family = AF_INET6;
+ sockaddr(&laddr->address, sock->family,
+ &xip->in6p_laddr, xip->inp_lport);
+ sockaddr(&faddr->address, sock->family,
+ &xip->in6p_faddr, xip->inp_fport);
+ }
+ if (proto == IPPROTO_TCP)
+ faddr->encaps_port = xtp->xt_encaps_port;
+ laddr->next = NULL;
+ faddr->next = NULL;
+ sock->laddr = laddr;
+ sock->faddr = faddr;
+ sock->vflag = xip->inp_vflag;
+ if (proto == IPPROTO_TCP) {
+ sock->state = xtp->t_state;
+ memcpy(sock->stack, xtp->xt_stack,
+ TCP_FUNCTION_NAME_LEN_MAX);
+ memcpy(sock->cc, xtp->xt_cc, TCP_CA_NAME_MAX);
+ }
+ sock->protoname = protoname;
+ if (sock->socket != 0)
+ RB_INSERT(socks_t, &socks, sock);
+ else
+ SLIST_INSERT_HEAD(&nosocks, sock, socket_list);
+ }
+out:
+ free(buf);
+}
+
+static void
+gather_unix(int proto)
+{
+ struct xunpgen *xug, *exug;
+ struct xunpcb *xup;
+ struct sock *sock;
+ struct addr *laddr, *faddr;
+ const char *varname, *protoname;
+ size_t len, bufsize;
+ void *buf;
+ int retry;
+
+ switch (proto) {
+ case SOCK_STREAM:
+ varname = "net.local.stream.pcblist";
+ protoname = "stream";
+ break;
+ case SOCK_DGRAM:
+ varname = "net.local.dgram.pcblist";
+ protoname = "dgram";
+ break;
+ case SOCK_SEQPACKET:
+ varname = "net.local.seqpacket.pcblist";
+ protoname = "seqpac";
+ break;
+ default:
+ abort();
+ }
+ buf = NULL;
+ bufsize = 8192;
+ retry = 5;
+ do {
+ for (;;) {
+ if ((buf = realloc(buf, bufsize)) == NULL)
+ err(1, "realloc()");
+ len = bufsize;
+ if (cap_sysctlbyname(capsysctl, varname, buf, &len,
+ NULL, 0) == 0)
+ break;
+ if (errno != ENOMEM || len != bufsize)
+ err(1, "cap_sysctlbyname()");
+ bufsize *= 2;
+ }
+ xug = (struct xunpgen *)buf;
+ exug = (struct xunpgen *)(void *)
+ ((char *)buf + len - sizeof(*exug));
+ if (!check_ksize(xug->xug_len, struct xunpgen) ||
+ !check_ksize(exug->xug_len, struct xunpgen))
+ goto out;
+ } while (xug->xug_gen != exug->xug_gen && retry--);
+
+ if (xug->xug_gen != exug->xug_gen && opt_v)
+ warnx("warning: data may be inconsistent");
+
+ for (;;) {
+ xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len);
+ if (xug >= exug)
+ break;
+ xup = (struct xunpcb *)xug;
+ if (!check_ksize(xup->xu_len, struct xunpcb))
+ goto out;
+ if ((xup->unp_conn == 0 && !opt_l) ||
+ (xup->unp_conn != 0 && !opt_c))
+ continue;
+ if ((sock = calloc(1, sizeof(*sock))) == NULL)
+ err(1, "malloc()");
+ if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+ err(1, "malloc()");
+ if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+ err(1, "malloc()");
+ sock->socket = xup->xu_socket.xso_so;
+ sock->pcb = xup->xu_unpp;
+ sock->proto = proto;
+ sock->family = AF_UNIX;
+ sock->protoname = protoname;
+ if (xup->xu_addr.sun_family == AF_UNIX)
+ laddr->address =
+ *(struct sockaddr_storage *)(void *)&xup->xu_addr;
+ faddr->conn = xup->unp_conn;
+ faddr->firstref = xup->xu_firstref;
+ faddr->nextref = xup->xu_nextref;
+ laddr->next = NULL;
+ faddr->next = NULL;
+ sock->laddr = laddr;
+ sock->faddr = faddr;
+ RB_INSERT(socks_t, &socks, sock);
+ RB_INSERT(pcbs_t, &pcbs, sock);
+ }
+out:
+ free(buf);
+}
+
+static void
+getfiles(void)
+{
+ struct xfile *xfiles;
+ size_t len, olen;
+
+ olen = len = sizeof(*xfiles);
+ if ((xfiles = malloc(len)) == NULL)
+ err(1, "malloc()");
+ while (cap_sysctlbyname(capsysctl, "kern.file", xfiles, &len, 0, 0)
+ == -1) {
+ if (errno != ENOMEM || len != olen)
+ err(1, "cap_sysctlbyname()");
+ olen = len *= 2;
+ if ((xfiles = realloc(xfiles, len)) == NULL)
+ err(1, "realloc()");
+ }
+ if (len > 0)
+ enforce_ksize(xfiles->xf_size, struct xfile);
+ nfiles = len / sizeof(*xfiles);
+
+ if ((files = malloc(nfiles * sizeof(struct file))) == NULL)
+ err(1, "malloc()");
+
+ for (int i = 0; i < nfiles; i++) {
+ files[i].xf_data = xfiles[i].xf_data;
+ files[i].xf_pid = xfiles[i].xf_pid;
+ files[i].xf_uid = xfiles[i].xf_uid;
+ files[i].xf_fd = xfiles[i].xf_fd;
+ RB_INSERT(files_t, &ftree, &files[i]);
+ }
+
+ free(xfiles);
+}
+
+static int
+printaddr(struct sockaddr_storage *ss)
+{
+ struct sockaddr_un *sun;
+ char addrstr[NI_MAXHOST] = { '\0', '\0' };
+ int error, off, port = 0;
+
+ switch (ss->ss_family) {
+ case AF_INET:
+ if (sstosin(ss)->sin_addr.s_addr == INADDR_ANY)
+ addrstr[0] = '*';
+ port = ntohs(sstosin(ss)->sin_port);
+ break;
+ case AF_INET6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr))
+ addrstr[0] = '*';
+ port = ntohs(sstosin6(ss)->sin6_port);
+ break;
+ case AF_UNIX:
+ sun = sstosun(ss);
+ off = (int)((char *)&sun->sun_path - (char *)sun);
+ return (xprintf("%.*s", sun->sun_len - off, sun->sun_path));
+ }
+ if (addrstr[0] == '\0') {
+ error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len,
+ addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+ if (error)
+ errx(1, "cap_getnameinfo()");
+ }
+ if (port == 0)
+ return xprintf("%s:*", addrstr);
+ else
+ return xprintf("%s:%d", addrstr, port);
+}
+
+static const char *
+getprocname(pid_t pid)
+{
+ static struct kinfo_proc proc;
+ size_t len;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)pid;
+ len = sizeof(proc);
+ if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0)
+ == -1) {
+ /* Do not warn if the process exits before we get its name. */
+ if (errno != ESRCH)
+ warn("cap_sysctl()");
+ return ("??");
+ }
+ return (proc.ki_comm);
+}
+
+static int
+getprocjid(pid_t pid)
+{
+ static struct kinfo_proc proc;
+ size_t len;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)pid;
+ len = sizeof(proc);
+ if (cap_sysctl(capsysctl, mib, nitems(mib), &proc, &len, NULL, 0)
+ == -1) {
+ /* Do not warn if the process exits before we get its jid. */
+ if (errno != ESRCH)
+ warn("cap_sysctl()");
+ return (-1);
+ }
+ return (proc.ki_jid);
+}
+
+static int
+check_ports(struct sock *s)
+{
+ int port;
+ struct addr *addr;
+
+ if (ports == NULL)
+ return (1);
+ if ((s->family != AF_INET) && (s->family != AF_INET6))
+ return (1);
+ for (addr = s->laddr; addr != NULL; addr = addr->next) {
+ if (s->family == AF_INET)
+ port = ntohs(sstosin(&addr->address)->sin_port);
+ else
+ port = ntohs(sstosin6(&addr->address)->sin6_port);
+ if (CHK_PORT(port))
+ return (1);
+ }
+ for (addr = s->faddr; addr != NULL; addr = addr->next) {
+ if (s->family == AF_INET)
+ port = ntohs(sstosin(&addr->address)->sin_port);
+ else
+ port = ntohs(sstosin6(&addr->address)->sin6_port);
+ if (CHK_PORT(port))
+ return (1);
+ }
+ return (0);
+}
+
+static const char *
+sctp_conn_state(int state)
+{
+ switch (state) {
+ case SCTP_CLOSED:
+ return "CLOSED";
+ break;
+ case SCTP_BOUND:
+ return "BOUND";
+ break;
+ case SCTP_LISTEN:
+ return "LISTEN";
+ break;
+ case SCTP_COOKIE_WAIT:
+ return "COOKIE_WAIT";
+ break;
+ case SCTP_COOKIE_ECHOED:
+ return "COOKIE_ECHOED";
+ break;
+ case SCTP_ESTABLISHED:
+ return "ESTABLISHED";
+ break;
+ case SCTP_SHUTDOWN_SENT:
+ return "SHUTDOWN_SENT";
+ break;
+ case SCTP_SHUTDOWN_RECEIVED:
+ return "SHUTDOWN_RECEIVED";
+ break;
+ case SCTP_SHUTDOWN_ACK_SENT:
+ return "SHUTDOWN_ACK_SENT";
+ break;
+ case SCTP_SHUTDOWN_PENDING:
+ return "SHUTDOWN_PENDING";
+ break;
+ default:
+ return "UNKNOWN";
+ break;
+ }
+}
+
+static const char *
+sctp_path_state(int state)
+{
+ switch (state) {
+ case SCTP_UNCONFIRMED:
+ return "UNCONFIRMED";
+ break;
+ case SCTP_ACTIVE:
+ return "ACTIVE";
+ break;
+ case SCTP_INACTIVE:
+ return "INACTIVE";
+ break;
+ default:
+ return "UNKNOWN";
+ break;
+ }
+}
+
+static void
+displaysock(struct sock *s, int pos)
+{
+ int first, offset;
+ struct addr *laddr, *faddr;
+
+ while (pos < 30)
+ pos += xprintf(" ");
+ pos += xprintf("%s", s->protoname);
+ if (s->vflag & INP_IPV4)
+ pos += xprintf("4");
+ if (s->vflag & INP_IPV6)
+ pos += xprintf("6");
+ if (s->vflag & (INP_IPV4 | INP_IPV6))
+ pos += xprintf(" ");
+ laddr = s->laddr;
+ faddr = s->faddr;
+ first = 1;
+ while (laddr != NULL || faddr != NULL) {
+ offset = 37;
+ while (pos < offset)
+ pos += xprintf(" ");
+ switch (s->family) {
+ case AF_INET:
+ case AF_INET6:
+ if (laddr != NULL)
+ pos += printaddr(&laddr->address);
+ offset += opt_w ? 46 : 22;
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ if (faddr != NULL)
+ pos += printaddr(&faddr->address);
+ offset += opt_w ? 46 : 22;
+ break;
+ case AF_UNIX:
+ if ((laddr == NULL) || (faddr == NULL))
+ errx(1, "laddr = %p or faddr = %p is NULL",
+ (void *)laddr, (void *)faddr);
+ if (laddr->address.ss_len == 0 && faddr->conn == 0) {
+ pos += xprintf("(not connected)");
+ offset += opt_w ? 92 : 44;
+ break;
+ }
+ /* Local bind(2) address, if any. */
+ if (laddr->address.ss_len > 0)
+ pos += printaddr(&laddr->address);
+ /* Remote peer we connect(2) to, if any. */
+ if (faddr->conn != 0) {
+ struct sock *p;
+
+ pos += xprintf("%s-> ",
+ laddr->address.ss_len > 0 ? " " : "");
+ p = RB_FIND(pcbs_t, &pcbs,
+ &(struct sock){ .pcb = faddr->conn });
+ if (__predict_false(p == NULL)) {
+ /* XXGL: can this happen at all? */
+ pos += xprintf("??");
+ } else if (p->laddr->address.ss_len == 0) {
+ struct file *f;
+
+ f = RB_FIND(files_t, &ftree,
+ &(struct file){ .xf_data =
+ p->socket });
+ if (f != NULL) {
+ pos += xprintf("[%lu %d]",
+ (u_long)f->xf_pid,
+ f->xf_fd);
+ }
+ } else
+ pos += printaddr(&p->laddr->address);
+ }
+ /* Remote peer(s) connect(2)ed to us, if any. */
+ if (faddr->firstref != 0) {
+ struct sock *p;
+ struct file *f;
+ kvaddr_t ref = faddr->firstref;
+ bool fref = true;
+
+ pos += xprintf(" <- ");
+
+ while ((p = RB_FIND(pcbs_t, &pcbs,
+ &(struct sock){ .pcb = ref })) != 0) {
+ f = RB_FIND(files_t, &ftree,
+ &(struct file){ .xf_data =
+ p->socket });
+ if (f != NULL) {
+ pos += xprintf("%s[%lu %d]",
+ fref ? "" : ",",
+ (u_long)f->xf_pid,
+ f->xf_fd);
+ }
+ ref = p->faddr->nextref;
+ fref = false;
+ }
+ }
+ offset += opt_w ? 92 : 44;
+ break;
+ default:
+ abort();
+ }
+ while (pos < offset)
+ pos += xprintf(" ");
+ if (opt_A) {
+ pos += xprintf("0x%16lx", s->pcb);
+ offset += 18;
+ }
+ if (opt_f) {
+ pos += xprintf("%d", s->fibnum);
+ offset += 7;
+ }
+ if (opt_I) {
+ if (s->splice_socket != 0) {
+ struct sock *sp;
+
+ sp = RB_FIND(socks_t, &socks, &(struct sock)
+ { .socket = s->splice_socket });
+ if (sp != NULL) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += printaddr(&sp->laddr->address);
+ } else {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += xprintf("??");
+ offset += opt_w ? 46 : 22;
+ }
+ }
+ offset += opt_w ? 46 : 22;
+ }
+ if (opt_i) {
+ if (s->proto == IPPROTO_TCP ||
+ s->proto == IPPROTO_UDP) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += xprintf("%" PRIu64, s->inp_gencnt);
+ }
+ offset += 9;
+ }
+ if (opt_U) {
+ if (faddr != NULL &&
+ ((s->proto == IPPROTO_SCTP &&
+ s->state != SCTP_CLOSED &&
+ s->state != SCTP_BOUND &&
+ s->state != SCTP_LISTEN) ||
+ (s->proto == IPPROTO_TCP &&
+ s->state != TCPS_CLOSED &&
+ s->state != TCPS_LISTEN))) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += xprintf("%u",
+ ntohs(faddr->encaps_port));
+ }
+ offset += 7;
+ }
+ if (opt_s) {
+ if (faddr != NULL &&
+ s->proto == IPPROTO_SCTP &&
+ s->state != SCTP_CLOSED &&
+ s->state != SCTP_BOUND &&
+ s->state != SCTP_LISTEN) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += xprintf("%s",
+ sctp_path_state(faddr->state));
+ }
+ offset += 13;
+ }
+ if (first) {
+ if (opt_s) {
+ if (s->proto == IPPROTO_SCTP ||
+ s->proto == IPPROTO_TCP) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ switch (s->proto) {
+ case IPPROTO_SCTP:
+ pos += xprintf("%s",
+ sctp_conn_state(s->state));
+ break;
+ case IPPROTO_TCP:
+ if (s->state >= 0 &&
+ s->state < TCP_NSTATES)
+ pos += xprintf("%s",
+ tcpstates[s->state]);
+ else
+ pos += xprintf("?");
+ break;
+ }
+ }
+ offset += 13;
+ }
+ if (opt_S) {
+ if (s->proto == IPPROTO_TCP) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ pos += xprintf("%.*s",
+ TCP_FUNCTION_NAME_LEN_MAX,
+ s->stack);
+ }
+ offset += TCP_FUNCTION_NAME_LEN_MAX + 1;
+ }
+ if (opt_C) {
+ if (s->proto == IPPROTO_TCP) {
+ do
+ pos += xprintf(" ");
+ while (pos < offset);
+ xprintf("%.*s", TCP_CA_NAME_MAX, s->cc);
+ }
+ offset += TCP_CA_NAME_MAX + 1;
+ }
+ }
+ if (laddr != NULL)
+ laddr = laddr->next;
+ if (faddr != NULL)
+ faddr = faddr->next;
+ if ((laddr != NULL) || (faddr != NULL)) {
+ xprintf("\n");
+ pos = 0;
+ }
+ first = 0;
+ }
+ xprintf("\n");
+}
+
+static void
+display(void)
+{
+ struct passwd *pwd;
+ struct file *xf;
+ struct sock *s;
+ int n, pos;
+
+ if (!opt_q) {
+ printf("%-8s %-10s %-5s %-3s %-6s %-*s %-*s",
+ "USER", "COMMAND", "PID", "FD", "PROTO",
+ opt_w ? 45 : 21, "LOCAL ADDRESS",
+ opt_w ? 45 : 21, "FOREIGN ADDRESS");
+ if (opt_A)
+ printf(" %-18s", "PCB KVA");
+ if (opt_f)
+ /* RT_MAXFIBS is 65535. */
+ printf(" %-6s", "FIB");
+ if (opt_I)
+ printf(" %-*s", opt_w ? 45 : 21, "SPLICE ADDRESS");
+ if (opt_i)
+ printf(" %-8s", "ID");
+ if (opt_U)
+ printf(" %-6s", "ENCAPS");
+ if (opt_s) {
+ printf(" %-12s", "PATH STATE");
+ printf(" %-12s", "CONN STATE");
+ }
+ if (opt_S)
+ printf(" %-*.*s", TCP_FUNCTION_NAME_LEN_MAX,
+ TCP_FUNCTION_NAME_LEN_MAX, "STACK");
+ if (opt_C)
+ printf(" %-.*s", TCP_CA_NAME_MAX, "CC");
+ printf("\n");
+ }
+ cap_setpassent(cappwd, 1);
+ for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
+ if (xf->xf_data == 0)
+ continue;
+ if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
+ continue;
+ s = RB_FIND(socks_t, &socks,
+ &(struct sock){ .socket = xf->xf_data});
+ if (s != NULL && check_ports(s)) {
+ s->shown = 1;
+ pos = 0;
+ if (opt_n ||
+ (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
+ pos += xprintf("%lu", (u_long)xf->xf_uid);
+ else
+ pos += xprintf("%s", pwd->pw_name);
+ do
+ pos += xprintf(" ");
+ while (pos < 9);
+ pos += xprintf("%.10s", getprocname(xf->xf_pid));
+ do
+ pos += xprintf(" ");
+ while (pos < 20);
+ pos += xprintf("%5lu", (u_long)xf->xf_pid);
+ do
+ pos += xprintf(" ");
+ while (pos < 26);
+ pos += xprintf("%-3d", xf->xf_fd);
+ displaysock(s, pos);
+ }
+ }
+ if (opt_j >= 0)
+ return;
+ SLIST_FOREACH(s, &nosocks, socket_list) {
+ if (!check_ports(s))
+ continue;
+ pos = xprintf("%-8s %-10s %-5s %-3s",
+ "?", "?", "?", "?");
+ displaysock(s, pos);
+ }
+ RB_FOREACH(s, socks_t, &socks) {
+ if (s->shown)
+ continue;
+ if (!check_ports(s))
+ continue;
+ pos = xprintf("%-8s %-10s %-5s %-3s",
+ "?", "?", "?", "?");
+ displaysock(s, pos);
+ }
+}
+
+static int
+set_default_protos(void)
+{
+ struct protoent *prot;
+ const char *pname;
+ size_t pindex;
+
+ init_protos(default_numprotos);
+
+ for (pindex = 0; pindex < default_numprotos; pindex++) {
+ pname = default_protos[pindex];
+ prot = cap_getprotobyname(capnetdb, pname);
+ if (prot == NULL)
+ err(1, "cap_getprotobyname: %s", pname);
+ protos[pindex] = prot->p_proto;
+ }
+ numprotos = pindex;
+ return (pindex);
+}
+
+/*
+ * Return the vnet property of the jail, or -1 on error.
+ */
+static int
+jail_getvnet(int jid)
+{
+ struct iovec jiov[6];
+ int vnet;
+ size_t len = sizeof(vnet);
+
+ if (sysctlbyname("kern.features.vimage", &vnet, &len, NULL, 0) != 0)
+ return (0);
+
+ vnet = -1;
+ jiov[0].iov_base = __DECONST(char *, "jid");
+ jiov[0].iov_len = sizeof("jid");
+ jiov[1].iov_base = &jid;
+ jiov[1].iov_len = sizeof(jid);
+ jiov[2].iov_base = __DECONST(char *, "vnet");
+ jiov[2].iov_len = sizeof("vnet");
+ jiov[3].iov_base = &vnet;
+ jiov[3].iov_len = sizeof(vnet);
+ jiov[4].iov_base = __DECONST(char *, "errmsg");
+ jiov[4].iov_len = sizeof("errmsg");
+ jiov[5].iov_base = jail_errmsg;
+ jiov[5].iov_len = JAIL_ERRMSGLEN;
+ jail_errmsg[0] = '\0';
+ if (jail_get(jiov, nitems(jiov), 0) < 0) {
+ if (!jail_errmsg[0])
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "jail_get: %s", strerror(errno));
+ return (-1);
+ }
+ return (vnet);
+}
+
+static void
+usage(void)
+{
+ errx(1,
+ "usage: sockstat [-46ACcfIiLlnqSsUuvw] [-j jid] [-p ports] [-P protocols]");
+}
+
+int
+main(int argc, char *argv[])
+{
+ cap_channel_t *capcas;
+ cap_net_limit_t *limit;
+ const char *pwdcmds[] = { "setpassent", "getpwuid" };
+ const char *pwdfields[] = { "pw_name" };
+ int protos_defined = -1;
+ int o, i;
+
+ opt_j = -1;
+ while ((o = getopt(argc, argv, "46ACcfIij:Llnp:P:qSsUuvw")) != -1)
+ switch (o) {
+ case '4':
+ opt_4 = true;
+ break;
+ case '6':
+ opt_6 = true;
+ break;
+ case 'A':
+ opt_A = true;
+ break;
+ case 'C':
+ opt_C = true;
+ break;
+ case 'c':
+ opt_c = true;
+ break;
+ case 'f':
+ opt_f = true;
+ break;
+ case 'I':
+ opt_I = true;
+ break;
+ case 'i':
+ opt_i = true;
+ break;
+ case 'j':
+ opt_j = jail_getid(optarg);
+ if (opt_j < 0)
+ errx(1, "jail_getid: %s", jail_errmsg);
+ break;
+ case 'L':
+ opt_L = true;
+ break;
+ case 'l':
+ opt_l = true;
+ break;
+ case 'n':
+ opt_n = true;
+ break;
+ case 'p':
+ parse_ports(optarg);
+ break;
+ case 'P':
+ protos_defined = parse_protos(optarg);
+ break;
+ case 'q':
+ opt_q = true;
+ break;
+ case 'S':
+ opt_S = true;
+ break;
+ case 's':
+ opt_s = true;
+ break;
+ case 'U':
+ opt_U = true;
+ break;
+ case 'u':
+ opt_u = true;
+ break;
+ case 'v':
+ ++opt_v;
+ break;
+ case 'w':
+ opt_w = true;
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ usage();
+
+ if (opt_j > 0) {
+ switch (jail_getvnet(opt_j)) {
+ case -1:
+ errx(2, "jail_getvnet: %s", jail_errmsg);
+ case JAIL_SYS_NEW:
+ if (jail_attach(opt_j) < 0)
+ err(3, "jail_attach()");
+ /* Set back to -1 for normal output in vnet jail. */
+ opt_j = -1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ capcas = cap_init();
+ if (capcas == NULL)
+ err(1, "Unable to contact Casper");
+ if (caph_enter_casper() < 0)
+ err(1, "Unable to enter capability mode");
+ capnet = cap_service_open(capcas, "system.net");
+ if (capnet == NULL)
+ err(1, "Unable to open system.net service");
+ capnetdb = cap_service_open(capcas, "system.netdb");
+ if (capnetdb == NULL)
+ err(1, "Unable to open system.netdb service");
+ capsysctl = cap_service_open(capcas, "system.sysctl");
+ if (capsysctl == NULL)
+ err(1, "Unable to open system.sysctl service");
+ cappwd = cap_service_open(capcas, "system.pwd");
+ if (cappwd == NULL)
+ err(1, "Unable to open system.pwd service");
+ cap_close(capcas);
+ limit = cap_net_limit_init(capnet, CAPNET_ADDR2NAME);
+ if (limit == NULL)
+ err(1, "Unable to init cap_net limits");
+ if (cap_net_limit(limit) < 0)
+ err(1, "Unable to apply limits");
+ if (cap_pwd_limit_cmds(cappwd, pwdcmds, nitems(pwdcmds)) < 0)
+ err(1, "Unable to apply pwd commands limits");
+ if (cap_pwd_limit_fields(cappwd, pwdfields, nitems(pwdfields)) < 0)
+ err(1, "Unable to apply pwd commands limits");
+
+ if ((!opt_4 && !opt_6) && protos_defined != -1)
+ opt_4 = opt_6 = true;
+ if (!opt_4 && !opt_6 && !opt_u)
+ opt_4 = opt_6 = opt_u = true;
+ if ((opt_4 || opt_6) && protos_defined == -1)
+ protos_defined = set_default_protos();
+ if (!opt_c && !opt_l)
+ opt_c = opt_l = true;
+
+ if (opt_4 || opt_6) {
+ for (i = 0; i < protos_defined; i++)
+ if (protos[i] == IPPROTO_SCTP)
+ gather_sctp();
+ else
+ gather_inet(protos[i]);
+ }
+
+ if (opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) {
+ gather_unix(SOCK_STREAM);
+ gather_unix(SOCK_DGRAM);
+ gather_unix(SOCK_SEQPACKET);
+ }
+ getfiles();
+ display();
+ exit(0);
+}
diff --git a/usr.bin/soelim/Makefile b/usr.bin/soelim/Makefile
new file mode 100644
index 000000000000..00b694d6e0b6
--- /dev/null
+++ b/usr.bin/soelim/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= soelim
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/soelim/Makefile.depend b/usr.bin/soelim/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/soelim/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/soelim/soelim.1 b/usr.bin/soelim/soelim.1
new file mode 100644
index 000000000000..9401c5b35bff
--- /dev/null
+++ b/usr.bin/soelim/soelim.1
@@ -0,0 +1,89 @@
+.\" Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 November 7, 2015
+.Dt SOELIM 1
+.Os
+.Sh NAME
+.Nm soelim
+.Nd interpret .so requests in manpages
+.Sh SYNOPSIS
+.Nm
+.Op Fl Crtv
+.Op Fl I Ar dir
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility
+reads the specified files or the standard input and performs the textual
+inclusion implied by the
+.Xr nroff 1 Pq Pa ports/textproc/groff
+directives of the form:
+.Pp
+.Dl \&.so anotherfile
+.Pp
+If a line starts with:
+.Dq .so anotherfile
+it replaces the line by processing
+.Dq anotherfile .
+Otherwise the line is printed to stdout.
+.Bl -tag -width "-I dir"
+.It Fl C
+Recognise
+.Em .so
+when it is not followed by a space character.
+.It Fl r
+Compatibility with groff's
+.Xr soelim 1
+(does nothing).
+.It Fl t
+Compatibility with groff's
+.Xr soelim 1
+(does nothing).
+.It Fl v
+Compatibility with groff's
+.Xr soelim 1
+(does nothing).
+.It Fl I Ar dir
+This option specifies directories where
+.Nm
+searches for files (both those on the command line and those named in
+.Dq .so
+directive.)
+This option may be specified multiple times.
+The directories will be searched in the order specified.
+.El
+.Pp
+The files are always searched first in the current directory.
+.Pp
+A file specified with an absolute path will be opened directly without
+performing a search.
+.Sh SEE ALSO
+.Xr mandoc 1
+.Sh AUTHORS
+This version of the
+.Nm
+utility was written by
+.An Baptiste Daroussin Aq Mt bapt@freebsd.org .
diff --git a/usr.bin/soelim/soelim.c b/usr.bin/soelim/soelim.c
new file mode 100644
index 000000000000..59328ba04874
--- /dev/null
+++ b/usr.bin/soelim/soelim.c
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
+ * 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
+ * in this position and unchanged.
+ * 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 AUTHOR(S) ``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(S) 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 <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+
+#define C_OPTION 0x1
+
+static StringList *includes;
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
+
+ exit(EXIT_FAILURE);
+}
+
+static FILE *
+soelim_fopen(const char *name)
+{
+ FILE *f;
+ char path[PATH_MAX];
+ size_t i;
+
+ if (strcmp(name, "-") == 0)
+ return (stdin);
+
+ if ((f = fopen(name, "r")) != NULL)
+ return (f);
+
+ if (*name == '/') {
+ warn("can't open '%s'", name);
+ return (NULL);
+ }
+
+ for (i = 0; i < includes->sl_cur; i++) {
+ snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
+ name);
+ if ((f = fopen(path, "r")) != NULL)
+ return (f);
+ }
+
+ warn("can't open '%s'", name);
+
+ return (f);
+}
+
+static int
+soelim_file(FILE *f, int flag)
+{
+ char *line = NULL;
+ char *walk, *cp;
+ size_t linecap = 0;
+ ssize_t linelen;
+
+ if (f == NULL)
+ return (1);
+
+ while ((linelen = getline(&line, &linecap, f)) > 0) {
+ if (strncmp(line, ".so", 3) != 0) {
+ printf("%s", line);
+ continue;
+ }
+
+ walk = line + 3;
+ if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
+ printf("%s", line);
+ continue;
+ }
+
+ while (isspace(*walk))
+ walk++;
+
+ cp = walk;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ *cp = 0;
+ if (cp < line + linelen)
+ cp++;
+
+ if (*walk == '\0') {
+ printf("%s", line);
+ continue;
+ }
+ if (soelim_file(soelim_fopen(walk), flag) == 1) {
+ free(line);
+ return (1);
+ }
+ if (*cp != '\0')
+ printf("%s", cp);
+ }
+
+ free(line);
+ fclose(f);
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch, i;
+ int ret = 0;
+ int flags = 0;
+
+ includes = sl_init();
+ if (includes == NULL)
+ err(EXIT_FAILURE, "sl_init()");
+
+ while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
+ switch (ch) {
+ case 'C':
+ flags |= C_OPTION;
+ break;
+ case 'r':
+ case 'v':
+ case 't':
+ /* stub compatibility with groff's soelim */
+ break;
+ case 'I':
+ sl_add(includes, optarg);
+ break;
+ default:
+ sl_free(includes, 0);
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ ret = soelim_file(stdin, flags);
+
+ for (i = 0; i < argc; i++)
+ ret = soelim_file(soelim_fopen(argv[i]), flags);
+
+ sl_free(includes, 0);
+
+ return (ret);
+}
diff --git a/usr.bin/soelim/tests/Makefile b/usr.bin/soelim/tests/Makefile
new file mode 100644
index 000000000000..6e3b7a25ecc7
--- /dev/null
+++ b/usr.bin/soelim/tests/Makefile
@@ -0,0 +1,12 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= soelim_test
+
+${PACKAGE}FILES+= nonexisting.in \
+ basic.in \
+ basic \
+ basic.out \
+ basic-with-space.in \
+ basic-with-space.out
+
+.include <bsd.test.mk>
diff --git a/usr.bin/soelim/tests/Makefile.depend b/usr.bin/soelim/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/soelim/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/soelim/tests/basic b/usr.bin/soelim/tests/basic
new file mode 100644
index 000000000000..c4fe1dd48c84
--- /dev/null
+++ b/usr.bin/soelim/tests/basic
@@ -0,0 +1 @@
+basic has been included
diff --git a/usr.bin/soelim/tests/basic-with-space.in b/usr.bin/soelim/tests/basic-with-space.in
new file mode 100644
index 000000000000..971d681f6fa2
--- /dev/null
+++ b/usr.bin/soelim/tests/basic-with-space.in
@@ -0,0 +1,3 @@
+This is a test
+.so basic something
+end
diff --git a/usr.bin/soelim/tests/basic-with-space.out b/usr.bin/soelim/tests/basic-with-space.out
new file mode 100644
index 000000000000..290b2c6e0543
--- /dev/null
+++ b/usr.bin/soelim/tests/basic-with-space.out
@@ -0,0 +1,4 @@
+This is a test
+basic has been included
+something
+end
diff --git a/usr.bin/soelim/tests/basic.in b/usr.bin/soelim/tests/basic.in
new file mode 100644
index 000000000000..cd32eb1e9417
--- /dev/null
+++ b/usr.bin/soelim/tests/basic.in
@@ -0,0 +1,3 @@
+This is a test
+.so basic
+end
diff --git a/usr.bin/soelim/tests/basic.out b/usr.bin/soelim/tests/basic.out
new file mode 100644
index 000000000000..db59fbb73ad7
--- /dev/null
+++ b/usr.bin/soelim/tests/basic.out
@@ -0,0 +1,3 @@
+This is a test
+basic has been included
+end
diff --git a/usr.bin/soelim/tests/nonexisting.in b/usr.bin/soelim/tests/nonexisting.in
new file mode 100644
index 000000000000..e07599d62311
--- /dev/null
+++ b/usr.bin/soelim/tests/nonexisting.in
@@ -0,0 +1,3 @@
+This is a test
+.so nonexistingfile
+This is next
diff --git a/usr.bin/soelim/tests/soelim_test.sh b/usr.bin/soelim/tests/soelim_test.sh
new file mode 100755
index 000000000000..7fb70a1f71e9
--- /dev/null
+++ b/usr.bin/soelim/tests/soelim_test.sh
@@ -0,0 +1,102 @@
+
+atf_test_case stdin
+stdin_head()
+{
+ atf_set "descr" "stdin functionality"
+}
+
+stdin_body()
+{
+ # no file after .so
+ atf_check \
+ -o inline:".so\n" \
+ -e empty \
+ -s exit:0 \
+ soelim <<-EOF
+.so
+EOF
+
+ # only space after .so
+ atf_check \
+ -o inline:".so \n" \
+ -e empty \
+ -s exit:0 \
+ soelim <<-EOF
+.so
+EOF
+
+ # explicit stdin
+ atf_check \
+ -o inline:".so\n" \
+ -e empty \
+ -s exit:0 \
+ soelim - <<-EOF
+.so
+EOF
+
+ atf_check \
+ -o empty \
+ -e inline:"soelim: can't open 'afile': No such file or directory\n" \
+ -s exit:1 \
+ soelim <<-EOF
+.so afile
+EOF
+
+ atf_check \
+ -o inline:".soafile\n" \
+ -e empty \
+ -s exit:0 \
+ soelim <<-EOF
+.soafile
+EOF
+
+ atf_check \
+ -o empty \
+ -e inline:"soelim: can't open 'afile': No such file or directory\n" \
+ -s exit:1 \
+ soelim -C <<-EOF
+.soafile
+EOF
+}
+
+atf_test_case files
+files_head()
+{
+ atf_set "descr" "testing files"
+}
+
+files_body()
+{
+ atf_check \
+ -o inline:"This is a test\n" \
+ -e inline:"soelim: can't open 'nonexistingfile': No such file or directory\n" \
+ -s exit:1 \
+ soelim $(atf_get_srcdir)/nonexisting.in
+
+ cp $(atf_get_srcdir)/basic .
+ atf_check \
+ -o file:$(atf_get_srcdir)/basic.out \
+ -e empty \
+ -s exit:0 \
+ soelim $(atf_get_srcdir)/basic.in
+
+ rm -f basic
+ atf_check \
+ -o file:$(atf_get_srcdir)/basic.out \
+ -e empty \
+ -s exit:0 \
+ soelim -I$(atf_get_srcdir) $(atf_get_srcdir)/basic.in
+
+ atf_check \
+ -o file:$(atf_get_srcdir)/basic-with-space.out \
+ -e empty \
+ -s exit:0 \
+ soelim -I$(atf_get_srcdir) $(atf_get_srcdir)/basic-with-space.in
+
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case stdin
+ atf_add_test_case files
+}
diff --git a/usr.bin/sort/Makefile b/usr.bin/sort/Makefile
new file mode 100644
index 000000000000..46cc431edd31
--- /dev/null
+++ b/usr.bin/sort/Makefile
@@ -0,0 +1,24 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+PROG= sort
+SRCS= bwstring.c coll.c file.c mem.c radixsort.c sort.c vsort.c
+
+sort.1: sort.1.in
+ sed ${MAN_SUB} ${.ALLSRC} >${.TARGET}
+
+CLEANFILES+= sort.1
+
+.if ${MK_SORT_THREADS} != "no"
+CFLAGS+= -DSORT_THREADS
+LIBADD= pthread md
+MAN_SUB+= -e 's|%%THREADS%%||g'
+.else
+LIBADD= md
+MAN_SUB+= -e 's|%%THREADS%%|\.\\"|g'
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sort/Makefile.depend b/usr.bin/sort/Makefile.depend
new file mode 100644
index 000000000000..9add648af17b
--- /dev/null
+++ b/usr.bin/sort/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sort/Makefile.depend.options b/usr.bin/sort/Makefile.depend.options
new file mode 100644
index 000000000000..5f27c1f9f587
--- /dev/null
+++ b/usr.bin/sort/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= SORT_THREADS
+
+DIRDEPS.SORT_THREADS.yes= lib/libmd lib/libpthread
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/sort/bwstring.c b/usr.bin/sort/bwstring.c
new file mode 100644
index 000000000000..10679fe631ba
--- /dev/null
+++ b/usr.bin/sort/bwstring.c
@@ -0,0 +1,1047 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <ctype.h>
+#include <errno.h>
+#include <err.h>
+#include <langinfo.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "bwstring.h"
+#include "sort.h"
+
+bool byte_sort;
+
+struct wmonth {
+ wchar_t *mon;
+ wchar_t *ab;
+ wchar_t *alt;
+};
+
+struct cmonth {
+ char *mon;
+ char *ab;
+ char *alt;
+};
+
+static struct wmonth *wmonths;
+static struct cmonth *cmonths;
+
+static int
+populate_cmonth(char **field, const nl_item item, int idx)
+{
+ char *tmp, *m;
+ size_t i, len;
+
+ tmp = nl_langinfo(item);
+ if (debug_sort)
+ printf("month[%d]=%s\n", idx, tmp);
+ if (*tmp == '\0')
+ return (0);
+ m = sort_strdup(tmp);
+ len = strlen(tmp);
+ for (i = 0; i < len; i++)
+ m[i] = toupper(m[i]);
+ *field = m;
+
+ return (1);
+}
+
+static int
+populate_wmonth(wchar_t **field, const nl_item item, int idx)
+{
+ wchar_t *m;
+ char *tmp;
+ size_t i, len;
+
+ tmp = nl_langinfo(item);
+ if (debug_sort)
+ printf("month[%d]=%s\n", idx, tmp);
+ if (*tmp == '\0')
+ return (0);
+ len = strlen(tmp);
+ m = sort_malloc(SIZEOF_WCHAR_STRING(len + 1));
+ if (mbstowcs(m, tmp, len) == ((size_t) - 1)) {
+ sort_free(m);
+ return (0);
+ }
+ m[len] = L'\0';
+ for (i = 0; i < len; i++)
+ m[i] = towupper(m[i]);
+ *field = m;
+
+ return (1);
+}
+
+void
+initialise_months(void)
+{
+ const nl_item mon_item[12] = { MON_1, MON_2, MON_3, MON_4,
+ MON_5, MON_6, MON_7, MON_8, MON_9, MON_10,
+ MON_11, MON_12 };
+ const nl_item ab_item[12] = { ABMON_1, ABMON_2, ABMON_3, ABMON_4,
+ ABMON_5, ABMON_6, ABMON_7, ABMON_8, ABMON_9, ABMON_10,
+ ABMON_11, ABMON_12 };
+#ifdef ALTMON_1
+ const nl_item alt_item[12] = { ALTMON_1, ALTMON_2, ALTMON_3, ALTMON_4,
+ ALTMON_5, ALTMON_6, ALTMON_7, ALTMON_8, ALTMON_9, ALTMON_10,
+ ALTMON_11, ALTMON_12 };
+#endif
+ int i;
+
+ /*
+ * Handle all possible month formats: abbrevation, full name,
+ * standalone name (without case ending).
+ */
+ if (mb_cur_max == 1) {
+ if (cmonths == NULL) {
+ cmonths = sort_malloc(sizeof(struct cmonth) * 12);
+ for (i = 0; i < 12; i++) {
+ if (!populate_cmonth(&cmonths[i].mon,
+ mon_item[i], i))
+ continue;
+ if (!populate_cmonth(&cmonths[i].ab,
+ ab_item[i], i))
+ continue;
+#ifdef ALTMON_1
+ if (!populate_cmonth(&cmonths[i].alt,
+ alt_item[i], i))
+ continue;
+#else
+ cmonths[i].alt = NULL;
+#endif
+ }
+ }
+
+ } else {
+ if (wmonths == NULL) {
+ wmonths = sort_malloc(sizeof(struct wmonth) * 12);
+ for (i = 0; i < 12; i++) {
+ if (!populate_wmonth(&wmonths[i].mon,
+ mon_item[i], i))
+ continue;
+ if (!populate_wmonth(&wmonths[i].ab,
+ ab_item[i], i))
+ continue;
+#ifdef ALTMON_1
+ if (!populate_wmonth(&wmonths[i].alt,
+ alt_item[i], i))
+ continue;
+#else
+ wmonths[i].alt = NULL;
+#endif
+ }
+ }
+ }
+}
+
+/*
+ * Compare two wide-character strings
+ */
+static int
+wide_str_coll(const wchar_t *s1, const wchar_t *s2)
+{
+ int ret;
+
+ errno = 0;
+ ret = wcscoll(s1, s2);
+ if (errno == EILSEQ) {
+ errno = 0;
+ ret = wcscmp(s1, s2);
+ if (errno != 0) {
+ for (size_t i = 0; ; ++i) {
+ wchar_t c1 = s1[i];
+ wchar_t c2 = s2[i];
+ if (c1 == L'\0')
+ return ((c2 == L'\0') ? 0 : -1);
+ if (c2 == L'\0')
+ return (+1);
+ if (c1 == c2)
+ continue;
+ return ((int)(c1 - c2));
+ }
+ }
+ }
+ return (ret);
+}
+
+/* counterparts of wcs functions */
+
+void
+bwsprintf(FILE *f, struct bwstring *bws, const char *prefix, const char *suffix)
+{
+
+ if (mb_cur_max == 1)
+ fprintf(f, "%s%s%s", prefix, bws->cdata.str, suffix);
+ else
+ fprintf(f, "%s%S%s", prefix, bws->wdata.str, suffix);
+}
+
+const void* bwsrawdata(const struct bwstring *bws)
+{
+
+ return (bws->wdata.str);
+}
+
+size_t bwsrawlen(const struct bwstring *bws)
+{
+
+ return ((mb_cur_max == 1) ? bws->cdata.len :
+ SIZEOF_WCHAR_STRING(bws->wdata.len));
+}
+
+size_t
+bws_memsize(const struct bwstring *bws)
+{
+
+ return ((mb_cur_max == 1) ?
+ (bws->cdata.len + 2 + sizeof(struct bwstring)) :
+ (SIZEOF_WCHAR_STRING(bws->wdata.len + 1) + sizeof(struct bwstring)));
+}
+
+void
+bws_setlen(struct bwstring *bws, size_t newlen)
+{
+
+ if (mb_cur_max == 1 && bws && newlen != bws->cdata.len &&
+ newlen <= bws->cdata.len) {
+ bws->cdata.len = newlen;
+ bws->cdata.str[newlen] = '\0';
+ } else if (bws && newlen != bws->wdata.len && newlen <= bws->wdata.len) {
+ bws->wdata.len = newlen;
+ bws->wdata.str[newlen] = L'\0';
+ }
+}
+
+/*
+ * Allocate a new binary string of specified size
+ */
+struct bwstring *
+bwsalloc(size_t sz)
+{
+ struct bwstring *ret;
+
+ if (mb_cur_max == 1) {
+ ret = sort_malloc(sizeof(struct bwstring) + 1 + sz);
+ ret->cdata.len = sz;
+ ret->cdata.str[sz] = '\0';
+ } else {
+ ret = sort_malloc(
+ sizeof(struct bwstring) + SIZEOF_WCHAR_STRING(sz + 1));
+ ret->wdata.len = sz;
+ ret->wdata.str[sz] = L'\0';
+ }
+
+ return (ret);
+}
+
+/*
+ * Create a copy of binary string.
+ * New string size equals the length of the old string.
+ */
+struct bwstring *
+bwsdup(const struct bwstring *s)
+{
+
+ if (s == NULL)
+ return (NULL);
+ else {
+ struct bwstring *ret = bwsalloc(BWSLEN(s));
+
+ if (mb_cur_max == 1)
+ memcpy(ret->cdata.str, s->cdata.str, (s->cdata.len));
+ else
+ memcpy(ret->wdata.str, s->wdata.str,
+ SIZEOF_WCHAR_STRING(s->wdata.len));
+
+ return (ret);
+ }
+}
+
+/*
+ * Create a new binary string from a wide character buffer.
+ */
+struct bwstring *
+bwssbdup(const wchar_t *str, size_t len)
+{
+
+ if (str == NULL)
+ return ((len == 0) ? bwsalloc(0) : NULL);
+ else {
+ struct bwstring *ret;
+
+ ret = bwsalloc(len);
+
+ if (mb_cur_max == 1)
+ for (size_t i = 0; i < len; ++i)
+ ret->cdata.str[i] = (char)str[i];
+ else
+ memcpy(ret->wdata.str, str, SIZEOF_WCHAR_STRING(len));
+
+ return (ret);
+ }
+}
+
+/*
+ * Create a new binary string from a raw binary buffer.
+ */
+struct bwstring *
+bwscsbdup(const unsigned char *str, size_t len)
+{
+ struct bwstring *ret;
+
+ ret = bwsalloc(len);
+
+ if (str) {
+ if (mb_cur_max == 1)
+ memcpy(ret->cdata.str, str, len);
+ else {
+ mbstate_t mbs;
+ const char *s;
+ size_t charlen, chars, cptr;
+
+ chars = 0;
+ cptr = 0;
+ s = (const char *) str;
+
+ memset(&mbs, 0, sizeof(mbs));
+
+ while (cptr < len) {
+ size_t n = mb_cur_max;
+
+ if (n > len - cptr)
+ n = len - cptr;
+ charlen = mbrlen(s + cptr, n, &mbs);
+ switch (charlen) {
+ case 0:
+ /* FALLTHROUGH */
+ case (size_t) -1:
+ /* FALLTHROUGH */
+ case (size_t) -2:
+ ret->wdata.str[chars++] =
+ (unsigned char) s[cptr];
+ ++cptr;
+ break;
+ default:
+ n = mbrtowc(ret->wdata.str + (chars++),
+ s + cptr, charlen, &mbs);
+ if ((n == (size_t)-1) || (n == (size_t)-2))
+ /* NOTREACHED */
+ err(2, "mbrtowc error");
+ cptr += charlen;
+ }
+ }
+
+ ret->wdata.len = chars;
+ ret->wdata.str[ret->wdata.len] = L'\0';
+ }
+ }
+ return (ret);
+}
+
+/*
+ * De-allocate object memory
+ */
+void
+bwsfree(const struct bwstring *s)
+{
+
+ if (s)
+ sort_free(s);
+}
+
+/*
+ * Copy content of src binary string to dst,
+ * with specified number of symbols to be copied.
+ * An offset value can be specified, from the start of src string.
+ * If the capacity of the dst string is not sufficient,
+ * then the data is truncated.
+ */
+struct bwstring *
+bwsnocpy(struct bwstring *dst, const struct bwstring *src, size_t offset,
+ size_t size)
+{
+
+ if (offset >= BWSLEN(src)) {
+ bws_setlen(dst, 0);
+ } else {
+ size_t nums = BWSLEN(src) - offset;
+
+ if (nums > BWSLEN(dst))
+ nums = BWSLEN(dst);
+ if (nums > size)
+ nums = size;
+ if (mb_cur_max == 1) {
+ memcpy(dst->cdata.str, src->cdata.str + offset, nums);
+ dst->cdata.len = nums;
+ dst->cdata.str[nums] = '\0';
+ } else {
+ memcpy(dst->wdata.str, src->wdata.str + offset,
+ SIZEOF_WCHAR_STRING(nums));
+ dst->wdata.len = nums;
+ dst->wdata.str[nums] = L'\0';
+ }
+ }
+ return (dst);
+}
+
+/*
+ * Write binary string to the file.
+ * The output is ended either with '\n' (nl == true)
+ * or '\0' (nl == false).
+ */
+size_t
+bwsfwrite(struct bwstring *bws, FILE *f, bool zero_ended)
+{
+
+ if (mb_cur_max == 1) {
+ size_t len = bws->cdata.len;
+
+ if (!zero_ended) {
+ bws->cdata.str[len] = '\n';
+
+ if (fwrite(bws->cdata.str, len + 1, 1, f) < 1)
+ err(2, NULL);
+
+ bws->cdata.str[len] = '\0';
+ } else if (fwrite(bws->cdata.str, len + 1, 1, f) < 1)
+ err(2, NULL);
+
+ return (len + 1);
+
+ } else {
+ wchar_t eols;
+ size_t printed = 0;
+
+ eols = zero_ended ? btowc('\0') : btowc('\n');
+
+ while (printed < BWSLEN(bws)) {
+ const wchar_t *s = bws->wdata.str + printed;
+
+ if (*s == L'\0') {
+ int nums;
+
+ nums = fwprintf(f, L"%lc", *s);
+
+ if (nums != 1)
+ err(2, NULL);
+ ++printed;
+ } else {
+ int nums;
+
+ nums = fwprintf(f, L"%ls", s);
+
+ if (nums < 1)
+ err(2, NULL);
+ printed += nums;
+ }
+ }
+ fwprintf(f, L"%lc", eols);
+ return (printed + 1);
+ }
+}
+
+int
+bwsncmp(const struct bwstring *bws1, const struct bwstring *bws2,
+ size_t offset, size_t len)
+{
+ size_t cmp_len, len1, len2;
+ int res;
+
+ len1 = BWSLEN(bws1);
+ len2 = BWSLEN(bws2);
+
+ if (len1 <= offset) {
+ return ((len2 <= offset) ? 0 : -1);
+ } else {
+ if (len2 <= offset)
+ return (+1);
+ else {
+ len1 -= offset;
+ len2 -= offset;
+
+ cmp_len = len1;
+
+ if (len2 < cmp_len)
+ cmp_len = len2;
+
+ if (len < cmp_len)
+ cmp_len = len;
+
+ if (mb_cur_max == 1) {
+ const char *s1, *s2;
+
+ s1 = bws1->cdata.str + offset;
+ s2 = bws2->cdata.str + offset;
+
+ res = memcmp(s1, s2, cmp_len);
+
+ } else {
+ const wchar_t *s1, *s2;
+
+ s1 = bws1->wdata.str + offset;
+ s2 = bws2->wdata.str + offset;
+
+ res = memcmp(s1, s2, SIZEOF_WCHAR_STRING(cmp_len));
+ }
+ }
+ }
+
+ if (res == 0) {
+ if (len1 < cmp_len && len1 < len2)
+ res = -1;
+ else if (len2 < cmp_len && len2 < len1)
+ res = +1;
+ }
+
+ return (res);
+}
+
+int
+bwscmp(const struct bwstring *bws1, const struct bwstring *bws2, size_t offset)
+{
+ size_t len1, len2, cmp_len;
+ int res;
+
+ len1 = BWSLEN(bws1);
+ len2 = BWSLEN(bws2);
+
+ len1 -= offset;
+ len2 -= offset;
+
+ cmp_len = len1;
+
+ if (len2 < cmp_len)
+ cmp_len = len2;
+
+ res = bwsncmp(bws1, bws2, offset, cmp_len);
+
+ if (res == 0) {
+ if( len1 < len2)
+ res = -1;
+ else if (len2 < len1)
+ res = +1;
+ }
+
+ return (res);
+}
+
+int
+bws_iterator_cmp(bwstring_iterator iter1, bwstring_iterator iter2, size_t len)
+{
+ wchar_t c1, c2;
+ size_t i;
+
+ for (i = 0; i < len; ++i) {
+ c1 = bws_get_iter_value(iter1);
+ c2 = bws_get_iter_value(iter2);
+ if (c1 != c2)
+ return (c1 - c2);
+ iter1 = bws_iterator_inc(iter1, 1);
+ iter2 = bws_iterator_inc(iter2, 1);
+ }
+
+ return (0);
+}
+
+int
+bwscoll(const struct bwstring *bws1, const struct bwstring *bws2, size_t offset)
+{
+ size_t len1, len2;
+
+ len1 = BWSLEN(bws1);
+ len2 = BWSLEN(bws2);
+
+ if (len1 <= offset)
+ return ((len2 <= offset) ? 0 : -1);
+ else {
+ if (len2 <= offset)
+ return (+1);
+ else {
+ len1 -= offset;
+ len2 -= offset;
+
+ if (mb_cur_max == 1) {
+ const char *s1, *s2;
+
+ s1 = bws1->cdata.str + offset;
+ s2 = bws2->cdata.str + offset;
+
+ if (byte_sort) {
+ int res;
+
+ if (len1 > len2) {
+ res = memcmp(s1, s2, len2);
+ if (!res)
+ res = +1;
+ } else if (len1 < len2) {
+ res = memcmp(s1, s2, len1);
+ if (!res)
+ res = -1;
+ } else
+ res = memcmp(s1, s2, len1);
+
+ return (res);
+
+ } else {
+ int res;
+ size_t i, maxlen;
+
+ i = 0;
+ maxlen = len1;
+
+ if (maxlen > len2)
+ maxlen = len2;
+
+ while (i < maxlen) {
+ /* goto next non-zero part: */
+ while ((i < maxlen) &&
+ !s1[i] && !s2[i])
+ ++i;
+
+ if (i >= maxlen)
+ break;
+
+ if (s1[i] == 0) {
+ if (s2[i] == 0)
+ /* NOTREACHED */
+ err(2, "bwscoll error 01");
+ else
+ return (-1);
+ } else if (s2[i] == 0)
+ return (+1);
+
+ res = strcoll((const char*)(s1 + i), (const char*)(s2 + i));
+ if (res)
+ return (res);
+
+ while ((i < maxlen) &&
+ s1[i] && s2[i])
+ ++i;
+
+ if (i >= maxlen)
+ break;
+
+ if (s1[i] == 0) {
+ if (s2[i] == 0) {
+ ++i;
+ continue;
+ } else
+ return (-1);
+ } else if (s2[i] == 0)
+ return (+1);
+ else
+ /* NOTREACHED */
+ err(2, "bwscoll error 02");
+ }
+
+ if (len1 < len2)
+ return (-1);
+ else if (len1 > len2)
+ return (+1);
+
+ return (0);
+ }
+ } else {
+ const wchar_t *s1, *s2;
+ size_t i, maxlen;
+ int res;
+
+ s1 = bws1->wdata.str + offset;
+ s2 = bws2->wdata.str + offset;
+
+ i = 0;
+ maxlen = len1;
+
+ if (maxlen > len2)
+ maxlen = len2;
+
+ while (i < maxlen) {
+
+ /* goto next non-zero part: */
+ while ((i < maxlen) &&
+ !s1[i] && !s2[i])
+ ++i;
+
+ if (i >= maxlen)
+ break;
+
+ if (s1[i] == 0) {
+ if (s2[i] == 0)
+ /* NOTREACHED */
+ err(2, "bwscoll error 1");
+ else
+ return (-1);
+ } else if (s2[i] == 0)
+ return (+1);
+
+ res = wide_str_coll(s1 + i, s2 + i);
+ if (res)
+ return (res);
+
+ while ((i < maxlen) && s1[i] && s2[i])
+ ++i;
+
+ if (i >= maxlen)
+ break;
+
+ if (s1[i] == 0) {
+ if (s2[i] == 0) {
+ ++i;
+ continue;
+ } else
+ return (-1);
+ } else if (s2[i] == 0)
+ return (+1);
+ else
+ /* NOTREACHED */
+ err(2, "bwscoll error 2");
+ }
+
+ if (len1 < len2)
+ return (-1);
+ else if (len1 > len2)
+ return (+1);
+
+ return (0);
+ }
+ }
+ }
+}
+
+/*
+ * Correction of the system API
+ */
+double
+bwstod(struct bwstring *s0, bool *empty)
+{
+ double ret;
+
+ if (mb_cur_max == 1) {
+ char *end, *s;
+ char *ep;
+
+ s = s0->cdata.str;
+ end = s + s0->cdata.len;
+ ep = NULL;
+
+ while (isblank(*s) && s < end)
+ ++s;
+
+ if (!isprint(*s)) {
+ *empty = true;
+ return (0);
+ }
+
+ ret = strtod((char*)s, &ep);
+ if (ep == s) {
+ *empty = true;
+ return (0);
+ }
+ } else {
+ wchar_t *end, *ep, *s;
+
+ s = s0->wdata.str;
+ end = s + s0->wdata.len;
+ ep = NULL;
+
+ while (iswblank(*s) && s < end)
+ ++s;
+
+ if (!iswprint(*s)) {
+ *empty = true;
+ return (0);
+ }
+
+ ret = wcstod(s, &ep);
+ if (ep == s) {
+ *empty = true;
+ return (0);
+ }
+ }
+
+ *empty = false;
+ return (ret);
+}
+
+/*
+ * A helper function for monthcoll. If a line matches
+ * a month name, it returns (number of the month - 1),
+ * while if there is no match, it just return -1.
+ */
+
+int
+bws_month_score(const struct bwstring *s0)
+{
+
+ if (mb_cur_max == 1) {
+ const char *end, *s;
+
+ s = s0->cdata.str;
+ end = s + s0->cdata.len;
+
+ while (isblank(*s) && s < end)
+ ++s;
+
+ for (int i = 11; i >= 0; --i) {
+ if (cmonths[i].mon && (s == strstr(s, cmonths[i].mon)))
+ return (i);
+ if (cmonths[i].ab && (s == strstr(s, cmonths[i].ab)))
+ return (i);
+ if (cmonths[i].alt && (s == strstr(s, cmonths[i].alt)))
+ return (i);
+ }
+
+ } else {
+ const wchar_t *end, *s;
+
+ s = s0->wdata.str;
+ end = s + s0->wdata.len;
+
+ while (iswblank(*s) && s < end)
+ ++s;
+
+ for (int i = 11; i >= 0; --i) {
+ if (wmonths[i].ab && (s == wcsstr(s, wmonths[i].ab)))
+ return (i);
+ if (wmonths[i].mon && (s == wcsstr(s, wmonths[i].mon)))
+ return (i);
+ if (wmonths[i].alt && (s == wcsstr(s, wmonths[i].alt)))
+ return (i);
+ }
+ }
+
+ return (-1);
+}
+
+/*
+ * Rips out leading blanks (-b).
+ */
+struct bwstring *
+ignore_leading_blanks(struct bwstring *str)
+{
+
+ if (mb_cur_max == 1) {
+ char *dst, *end, *src;
+
+ src = str->cdata.str;
+ dst = src;
+ end = src + str->cdata.len;
+
+ while (src < end && isblank(*src))
+ ++src;
+
+ if (src != dst) {
+ size_t newlen;
+
+ newlen = BWSLEN(str) - (src - dst);
+
+ while (src < end) {
+ *dst = *src;
+ ++dst;
+ ++src;
+ }
+ bws_setlen(str, newlen);
+ }
+ } else {
+ wchar_t *dst, *end, *src;
+
+ src = str->wdata.str;
+ dst = src;
+ end = src + str->wdata.len;
+
+ while (src < end && iswblank(*src))
+ ++src;
+
+ if (src != dst) {
+
+ size_t newlen = BWSLEN(str) - (src - dst);
+
+ while (src < end) {
+ *dst = *src;
+ ++dst;
+ ++src;
+ }
+ bws_setlen(str, newlen);
+
+ }
+ }
+ return (str);
+}
+
+/*
+ * Rips out nonprinting characters (-i).
+ */
+struct bwstring *
+ignore_nonprinting(struct bwstring *str)
+{
+ size_t newlen = BWSLEN(str);
+
+ if (mb_cur_max == 1) {
+ char *dst, *end, *src;
+ char c;
+
+ src = str->cdata.str;
+ dst = src;
+ end = src + str->cdata.len;
+
+ while (src < end) {
+ c = *src;
+ if (isprint(c)) {
+ *dst = c;
+ ++dst;
+ ++src;
+ } else {
+ ++src;
+ --newlen;
+ }
+ }
+ } else {
+ wchar_t *dst, *end, *src;
+ wchar_t c;
+
+ src = str->wdata.str;
+ dst = src;
+ end = src + str->wdata.len;
+
+ while (src < end) {
+ c = *src;
+ if (iswprint(c)) {
+ *dst = c;
+ ++dst;
+ ++src;
+ } else {
+ ++src;
+ --newlen;
+ }
+ }
+ }
+ bws_setlen(str, newlen);
+
+ return (str);
+}
+
+/*
+ * Rips out any characters that are not alphanumeric characters
+ * nor blanks (-d).
+ */
+struct bwstring *
+dictionary_order(struct bwstring *str)
+{
+ size_t newlen = BWSLEN(str);
+
+ if (mb_cur_max == 1) {
+ char *dst, *end, *src;
+ char c;
+
+ src = str->cdata.str;
+ dst = src;
+ end = src + str->cdata.len;
+
+ while (src < end) {
+ c = *src;
+ if (isalnum(c) || isblank(c)) {
+ *dst = c;
+ ++dst;
+ ++src;
+ } else {
+ ++src;
+ --newlen;
+ }
+ }
+ } else {
+ wchar_t *dst, *end, *src;
+ wchar_t c;
+
+ src = str->wdata.str;
+ dst = src;
+ end = src + str->wdata.len;
+
+ while (src < end) {
+ c = *src;
+ if (iswalnum(c) || iswblank(c)) {
+ *dst = c;
+ ++dst;
+ ++src;
+ } else {
+ ++src;
+ --newlen;
+ }
+ }
+ }
+ bws_setlen(str, newlen);
+
+ return (str);
+}
+
+/*
+ * Converts string to lower case(-f).
+ */
+struct bwstring *
+ignore_case(struct bwstring *str)
+{
+
+ if (mb_cur_max == 1) {
+ char *end, *s;
+
+ s = str->cdata.str;
+ end = s + str->cdata.len;
+
+ while (s < end) {
+ *s = toupper(*s);
+ ++s;
+ }
+ } else {
+ wchar_t *end, *s;
+
+ s = str->wdata.str;
+ end = s + str->wdata.len;
+
+ while (s < end) {
+ *s = towupper(*s);
+ ++s;
+ }
+ }
+ return (str);
+}
+
+void
+bws_disorder_warnx(struct bwstring *s, const char *fn, size_t pos)
+{
+
+ if (mb_cur_max == 1)
+ warnx("%s:%zu: disorder: %s", fn, pos + 1, s->cdata.str);
+ else
+ warnx("%s:%zu: disorder: %ls", fn, pos + 1, s->wdata.str);
+}
diff --git a/usr.bin/sort/bwstring.h b/usr.bin/sort/bwstring.h
new file mode 100644
index 000000000000..c9a7d6778fd6
--- /dev/null
+++ b/usr.bin/sort/bwstring.h
@@ -0,0 +1,142 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__BWSTRING_H__)
+#define __BWSTRING_H__
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sysexits.h>
+#include <wchar.h>
+
+#include "sort.h"
+#include "mem.h"
+
+extern bool byte_sort;
+
+/* wchar_t is of 4 bytes: */
+#define SIZEOF_WCHAR_STRING(LEN) ((LEN)*sizeof(wchar_t))
+
+struct wstr {
+ size_t len;
+ wchar_t str[];
+};
+
+struct cstr {
+ size_t len;
+ char str[];
+};
+
+/*
+ * Binary "wide" string
+ */
+struct bwstring
+{
+ union {
+ struct wstr wdata;
+ struct cstr cdata;
+ };
+};
+
+typedef void *bwstring_iterator;
+
+#define BWSLEN(s) ((mb_cur_max == 1) ? (s)->cdata.len : (s)->wdata.len)
+struct bwstring *bwsalloc(size_t sz);
+
+size_t bwsrawlen(const struct bwstring *bws);
+const void* bwsrawdata(const struct bwstring *bws);
+void bws_setlen(struct bwstring *bws, size_t newlen);
+size_t bws_memsize(const struct bwstring *bws);
+double bwstod(struct bwstring *s0, bool *empty);
+int bws_month_score(const struct bwstring *s0);
+
+struct bwstring *ignore_leading_blanks(struct bwstring *str);
+struct bwstring *ignore_nonprinting(struct bwstring *str);
+struct bwstring *dictionary_order(struct bwstring *str);
+struct bwstring *ignore_case(struct bwstring *str);
+
+void bwsprintf(FILE*, struct bwstring*, const char *prefix, const char *suffix);
+void bws_disorder_warnx(struct bwstring *s, const char *fn, size_t pos);
+
+struct bwstring *bwsdup(const struct bwstring *s);
+struct bwstring *bwssbdup(const wchar_t *str, size_t size);
+struct bwstring *bwscsbdup(const unsigned char *str, size_t size);
+void bwsfree(const struct bwstring *s);
+struct bwstring *bwsnocpy(struct bwstring *dst, const struct bwstring *src, size_t offset, size_t size);
+int bwscmp(const struct bwstring *bws1, const struct bwstring *bws2, size_t offset);
+int bwsncmp(const struct bwstring *bws1, const struct bwstring *bws2, size_t offset, size_t len);
+int bwscoll(const struct bwstring *bws1, const struct bwstring *bws2, size_t offset);
+size_t bwsfwrite(struct bwstring *bws, FILE *f, bool zero_ended);
+
+static inline bwstring_iterator
+bws_begin(struct bwstring *bws)
+{
+
+ return ((bwstring_iterator)bws->wdata.str);
+}
+
+static inline bwstring_iterator
+bws_end(struct bwstring *bws)
+{
+
+ return ((mb_cur_max == 1) ?
+ (bwstring_iterator) (bws->cdata.str + bws->cdata.len) :
+ (bwstring_iterator) (bws->wdata.str + bws->wdata.len));
+}
+
+static inline bwstring_iterator
+bws_iterator_inc(bwstring_iterator iter, size_t pos)
+{
+
+ if (mb_cur_max == 1)
+ return ((unsigned char *) iter) + pos;
+ else
+ return ((wchar_t*) iter) + pos;
+}
+
+static inline wchar_t
+bws_get_iter_value(bwstring_iterator iter)
+{
+
+ if (mb_cur_max == 1)
+ return *((unsigned char *) iter);
+ else
+ return *((wchar_t*) iter);
+}
+
+int
+bws_iterator_cmp(bwstring_iterator iter1, bwstring_iterator iter2, size_t len);
+
+#define BWS_GET(bws, pos) ((mb_cur_max == 1) ? (bws->cdata.str[(pos)]) : bws->wdata.str[(pos)])
+
+void initialise_months(void);
+
+#endif /* __BWSTRING_H__ */
diff --git a/usr.bin/sort/coll.c b/usr.bin/sort/coll.c
new file mode 100644
index 000000000000..ff7a9a552dc0
--- /dev/null
+++ b/usr.bin/sort/coll.c
@@ -0,0 +1,1318 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <errno.h>
+#include <err.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <math.h>
+#include <md5.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "coll.h"
+#include "vsort.h"
+
+struct key_specs *keys;
+size_t keys_num = 0;
+
+wint_t symbol_decimal_point = L'.';
+/* there is no default thousands separator in collate rules: */
+wint_t symbol_thousands_sep = 0;
+wint_t symbol_negative_sign = L'-';
+wint_t symbol_positive_sign = L'+';
+
+static int wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset);
+static int gnumcoll(struct key_value*, struct key_value *, size_t offset);
+static int monthcoll(struct key_value*, struct key_value *, size_t offset);
+static int numcoll(struct key_value*, struct key_value *, size_t offset);
+static int hnumcoll(struct key_value*, struct key_value *, size_t offset);
+static int randomcoll(struct key_value*, struct key_value *, size_t offset);
+static int versioncoll(struct key_value*, struct key_value *, size_t offset);
+
+/*
+ * Allocate keys array
+ */
+struct keys_array *
+keys_array_alloc(void)
+{
+ struct keys_array *ka;
+ size_t sz;
+
+ sz = keys_array_size();
+ ka = sort_calloc(1, sz);
+
+ return (ka);
+}
+
+/*
+ * Calculate whether we need key hint space
+ */
+static size_t
+key_hint_size(void)
+{
+
+ return (need_hint ? sizeof(struct key_hint) : 0);
+}
+
+/*
+ * Calculate keys array size
+ */
+size_t
+keys_array_size(void)
+{
+
+ return (keys_num * (sizeof(struct key_value) + key_hint_size()));
+}
+
+/*
+ * Clean data of keys array
+ */
+void
+clean_keys_array(const struct bwstring *s, struct keys_array *ka)
+{
+
+ if (ka) {
+ for (size_t i = 0; i < keys_num; ++i) {
+ const struct key_value *kv;
+
+ kv = get_key_from_keys_array(ka, i);
+ if (kv->k && kv->k != s)
+ bwsfree(kv->k);
+ }
+ memset(ka, 0, keys_array_size());
+ }
+}
+
+/*
+ * Get pointer to a key value in the keys set
+ */
+struct key_value *
+get_key_from_keys_array(struct keys_array *ka, size_t ind)
+{
+
+ return ((struct key_value *)((caddr_t)ka->key +
+ ind * (sizeof(struct key_value) + key_hint_size())));
+}
+
+/*
+ * Set value of a key in the keys set
+ */
+void
+set_key_on_keys_array(struct keys_array *ka, struct bwstring *s, size_t ind)
+{
+
+ if (ka && keys_num > ind) {
+ struct key_value *kv;
+
+ kv = get_key_from_keys_array(ka, ind);
+
+ if (kv->k && kv->k != s)
+ bwsfree(kv->k);
+ kv->k = s;
+ }
+}
+
+/*
+ * Initialize a sort list item
+ */
+struct sort_list_item *
+sort_list_item_alloc(void)
+{
+ struct sort_list_item *si;
+ size_t sz;
+
+ sz = sizeof(struct sort_list_item) + keys_array_size();
+ si = sort_calloc(1, sz);
+
+ return (si);
+}
+
+size_t
+sort_list_item_size(struct sort_list_item *si)
+{
+ size_t ret = 0;
+
+ if (si) {
+ ret = sizeof(struct sort_list_item) + keys_array_size();
+ if (si->str)
+ ret += bws_memsize(si->str);
+ for (size_t i = 0; i < keys_num; ++i) {
+ const struct key_value *kv;
+
+ kv = get_key_from_keys_array(&si->ka, i);
+
+ if (kv->k != si->str)
+ ret += bws_memsize(kv->k);
+ }
+ }
+ return (ret);
+}
+
+/*
+ * Calculate key for a sort list item
+ */
+static void
+sort_list_item_make_key(struct sort_list_item *si)
+{
+
+ preproc(si->str, &(si->ka));
+}
+
+/*
+ * Set value of a sort list item.
+ * Return combined string and keys memory size.
+ */
+void
+sort_list_item_set(struct sort_list_item *si, struct bwstring *str)
+{
+
+ if (si) {
+ clean_keys_array(si->str, &(si->ka));
+ if (si->str) {
+ if (si->str == str) {
+ /* we are trying to reset the same string */
+ return;
+ } else {
+ bwsfree(si->str);
+ si->str = NULL;
+ }
+ }
+ si->str = str;
+ sort_list_item_make_key(si);
+ }
+}
+
+/*
+ * De-allocate a sort list item object memory
+ */
+void
+sort_list_item_clean(struct sort_list_item *si)
+{
+
+ if (si) {
+ clean_keys_array(si->str, &(si->ka));
+ if (si->str) {
+ bwsfree(si->str);
+ si->str = NULL;
+ }
+ }
+}
+
+/*
+ * Skip columns according to specs
+ */
+static size_t
+skip_cols_to_start(const struct bwstring *s, size_t cols, size_t start,
+ bool skip_blanks, bool *empty_key)
+{
+ if (cols < 1)
+ return (BWSLEN(s) + 1);
+
+ if (skip_blanks)
+ while (start < BWSLEN(s) && iswblank(BWS_GET(s,start)))
+ ++start;
+
+ while (start < BWSLEN(s) && cols > 1) {
+ --cols;
+ ++start;
+ }
+
+ if (start >= BWSLEN(s))
+ *empty_key = true;
+
+ return (start);
+}
+
+/*
+ * Skip fields according to specs
+ */
+static size_t
+skip_fields_to_start(const struct bwstring *s, size_t fields, bool *empty_field)
+{
+
+ if (fields < 2) {
+ if (BWSLEN(s) == 0)
+ *empty_field = true;
+ return (0);
+ } else if (!(sort_opts_vals.tflag)) {
+ size_t cpos = 0;
+ bool pb = true;
+
+ while (cpos < BWSLEN(s)) {
+ bool isblank;
+
+ isblank = iswblank(BWS_GET(s, cpos));
+
+ if (isblank && !pb) {
+ --fields;
+ if (fields <= 1)
+ return (cpos);
+ }
+ pb = isblank;
+ ++cpos;
+ }
+ if (fields > 1)
+ *empty_field = true;
+ return (cpos);
+ } else {
+ size_t cpos = 0;
+
+ while (cpos < BWSLEN(s)) {
+ if (BWS_GET(s,cpos) == (wchar_t)sort_opts_vals.field_sep) {
+ --fields;
+ if (fields <= 1)
+ return (cpos + 1);
+ }
+ ++cpos;
+ }
+ if (fields > 1)
+ *empty_field = true;
+ return (cpos);
+ }
+}
+
+/*
+ * Find fields start
+ */
+static void
+find_field_start(const struct bwstring *s, struct key_specs *ks,
+ size_t *field_start, size_t *key_start, bool *empty_field, bool *empty_key)
+{
+
+ *field_start = skip_fields_to_start(s, ks->f1, empty_field);
+ if (!*empty_field)
+ *key_start = skip_cols_to_start(s, ks->c1, *field_start,
+ ks->pos1b, empty_key);
+ else
+ *empty_key = true;
+}
+
+/*
+ * Find end key position
+ */
+static size_t
+find_field_end(const struct bwstring *s, struct key_specs *ks)
+{
+ size_t f2, next_field_start, pos_end;
+ bool empty_field, empty_key;
+
+ empty_field = false;
+ empty_key = false;
+ f2 = ks->f2;
+
+ if (f2 == 0)
+ return (BWSLEN(s) + 1);
+ else {
+ if (ks->c2 == 0) {
+ next_field_start = skip_fields_to_start(s, f2 + 1,
+ &empty_field);
+ if ((next_field_start > 0) && sort_opts_vals.tflag &&
+ ((wchar_t)sort_opts_vals.field_sep == BWS_GET(s,
+ next_field_start - 1)))
+ --next_field_start;
+ } else
+ next_field_start = skip_fields_to_start(s, f2,
+ &empty_field);
+ }
+
+ if (empty_field || (next_field_start >= BWSLEN(s)))
+ return (BWSLEN(s) + 1);
+
+ if (ks->c2) {
+ pos_end = skip_cols_to_start(s, ks->c2, next_field_start,
+ ks->pos2b, &empty_key);
+ if (pos_end < BWSLEN(s))
+ ++pos_end;
+ } else
+ pos_end = next_field_start;
+
+ return (pos_end);
+}
+
+/*
+ * Cut a field according to the key specs
+ */
+static struct bwstring *
+cut_field(const struct bwstring *s, struct key_specs *ks)
+{
+ struct bwstring *ret = NULL;
+
+ if (s && ks) {
+ size_t field_start, key_end, key_start, sz;
+ bool empty_field, empty_key;
+
+ field_start = 0;
+ key_start = 0;
+ empty_field = false;
+ empty_key = false;
+
+ find_field_start(s, ks, &field_start, &key_start,
+ &empty_field, &empty_key);
+
+ if (empty_key)
+ sz = 0;
+ else {
+ key_end = find_field_end(s, ks);
+ sz = (key_end < key_start) ? 0 : (key_end - key_start);
+ }
+
+ ret = bwsalloc(sz);
+ if (sz)
+ bwsnocpy(ret, s, key_start, sz);
+ } else
+ ret = bwsalloc(0);
+
+ return (ret);
+}
+
+/*
+ * Preprocesses a line applying the necessary transformations
+ * specified by command line options and returns the preprocessed
+ * string, which can be used to compare.
+ */
+int
+preproc(struct bwstring *s, struct keys_array *ka)
+{
+
+ if (sort_opts_vals.kflag)
+ for (size_t i = 0; i < keys_num; i++) {
+ struct bwstring *key;
+ struct key_specs *kspecs;
+ struct sort_mods *sm;
+
+ kspecs = &(keys[i]);
+ key = cut_field(s, kspecs);
+
+ sm = &(kspecs->sm);
+ if (sm->dflag)
+ key = dictionary_order(key);
+ else if (sm->iflag)
+ key = ignore_nonprinting(key);
+ if (sm->fflag || sm->Mflag)
+ key = ignore_case(key);
+
+ set_key_on_keys_array(ka, key, i);
+ }
+ else {
+ struct bwstring *ret = NULL;
+ struct sort_mods *sm = default_sort_mods;
+
+ if (sm->bflag) {
+ if (ret == NULL)
+ ret = bwsdup(s);
+ ret = ignore_leading_blanks(ret);
+ }
+ if (sm->dflag) {
+ if (ret == NULL)
+ ret = bwsdup(s);
+ ret = dictionary_order(ret);
+ } else if (sm->iflag) {
+ if (ret == NULL)
+ ret = bwsdup(s);
+ ret = ignore_nonprinting(ret);
+ }
+ if (sm->fflag || sm->Mflag) {
+ if (ret == NULL)
+ ret = bwsdup(s);
+ ret = ignore_case(ret);
+ }
+ if (ret == NULL)
+ set_key_on_keys_array(ka, s, 0);
+ else
+ set_key_on_keys_array(ka, ret, 0);
+ }
+
+ return 0;
+}
+
+cmpcoll_t
+get_sort_func(struct sort_mods *sm)
+{
+
+ if (sm->nflag)
+ return (numcoll);
+ else if (sm->hflag)
+ return (hnumcoll);
+ else if (sm->gflag)
+ return (gnumcoll);
+ else if (sm->Mflag)
+ return (monthcoll);
+ else if (sm->Rflag)
+ return (randomcoll);
+ else if (sm->Vflag)
+ return (versioncoll);
+ else
+ return (wstrcoll);
+}
+
+/*
+ * Compares the given strings. Returns a positive number if
+ * the first precedes the second, a negative number if the second is
+ * the preceding one, and zero if they are equal. This function calls
+ * the underlying collate functions, which done the actual comparison.
+ */
+int
+key_coll(struct keys_array *ps1, struct keys_array *ps2, size_t offset)
+{
+ struct key_value *kv1, *kv2;
+ struct sort_mods *sm;
+ int res = 0;
+
+ for (size_t i = 0; i < keys_num; ++i) {
+ kv1 = get_key_from_keys_array(ps1, i);
+ kv2 = get_key_from_keys_array(ps2, i);
+ sm = &(keys[i].sm);
+
+ if (sm->rflag)
+ res = sm->func(kv2, kv1, offset);
+ else
+ res = sm->func(kv1, kv2, offset);
+
+ if (res)
+ break;
+
+ /* offset applies to only the first key */
+ offset = 0;
+ }
+ return (res);
+}
+
+/*
+ * Compare two strings.
+ * Plain symbol-by-symbol comparison.
+ */
+int
+top_level_str_coll(const struct bwstring *s1, const struct bwstring *s2)
+{
+
+ if (default_sort_mods->rflag) {
+ const struct bwstring *tmp;
+
+ tmp = s1;
+ s1 = s2;
+ s2 = tmp;
+ }
+
+ return (bwscoll(s1, s2, 0));
+}
+
+/*
+ * Compare a string and a sort list item, according to the sort specs.
+ */
+int
+str_list_coll(struct bwstring *str1, struct sort_list_item **ss2)
+{
+ struct keys_array *ka1;
+ int ret = 0;
+
+ ka1 = keys_array_alloc();
+
+ preproc(str1, ka1);
+
+ sort_list_item_make_key(*ss2);
+
+ if (debug_sort) {
+ bwsprintf(stdout, str1, "; s1=<", ">");
+ bwsprintf(stdout, (*ss2)->str, ", s2=<", ">");
+ }
+
+ ret = key_coll(ka1, &((*ss2)->ka), 0);
+
+ if (debug_sort)
+ printf("; cmp1=%d", ret);
+
+ clean_keys_array(str1, ka1);
+ sort_free(ka1);
+
+ if ((ret == 0) && !(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) {
+ ret = top_level_str_coll(str1, ((*ss2)->str));
+ if (debug_sort)
+ printf("; cmp2=%d", ret);
+ }
+
+ if (debug_sort)
+ printf("\n");
+
+ return (ret);
+}
+
+/*
+ * Compare two sort list items, according to the sort specs.
+ */
+int
+list_coll_offset(struct sort_list_item **ss1, struct sort_list_item **ss2,
+ size_t offset)
+{
+ int ret;
+
+ ret = key_coll(&((*ss1)->ka), &((*ss2)->ka), offset);
+
+ if (debug_sort) {
+ if (offset)
+ printf("; offset=%d", (int) offset);
+ bwsprintf(stdout, ((*ss1)->str), "; s1=<", ">");
+ bwsprintf(stdout, ((*ss2)->str), ", s2=<", ">");
+ printf("; cmp1=%d\n", ret);
+ }
+
+ if (ret)
+ return (ret);
+
+ if (!(sort_opts_vals.sflag) && sort_opts_vals.complex_sort) {
+ ret = top_level_str_coll(((*ss1)->str), ((*ss2)->str));
+ if (debug_sort)
+ printf("; cmp2=%d\n", ret);
+ }
+
+ return (ret);
+}
+
+/*
+ * Compare two sort list items, according to the sort specs.
+ */
+int
+list_coll(struct sort_list_item **ss1, struct sort_list_item **ss2)
+{
+
+ return (list_coll_offset(ss1, ss2, 0));
+}
+
+#define LSCDEF(N) \
+static int \
+list_coll_##N(struct sort_list_item **ss1, struct sort_list_item **ss2) \
+{ \
+ \
+ return (list_coll_offset(ss1, ss2, N)); \
+}
+
+LSCDEF(1)
+LSCDEF(2)
+LSCDEF(3)
+LSCDEF(4)
+LSCDEF(5)
+LSCDEF(6)
+LSCDEF(7)
+LSCDEF(8)
+LSCDEF(9)
+LSCDEF(10)
+LSCDEF(11)
+LSCDEF(12)
+LSCDEF(13)
+LSCDEF(14)
+LSCDEF(15)
+LSCDEF(16)
+LSCDEF(17)
+LSCDEF(18)
+LSCDEF(19)
+LSCDEF(20)
+
+listcoll_t
+get_list_call_func(size_t offset)
+{
+ static const listcoll_t lsarray[] = { list_coll, list_coll_1,
+ list_coll_2, list_coll_3, list_coll_4, list_coll_5,
+ list_coll_6, list_coll_7, list_coll_8, list_coll_9,
+ list_coll_10, list_coll_11, list_coll_12, list_coll_13,
+ list_coll_14, list_coll_15, list_coll_16, list_coll_17,
+ list_coll_18, list_coll_19, list_coll_20 };
+
+ if (offset <= 20)
+ return (lsarray[offset]);
+
+ return (list_coll);
+}
+
+/*
+ * Compare two sort list items, only by their original string.
+ */
+int
+list_coll_by_str_only(struct sort_list_item **ss1, struct sort_list_item **ss2)
+{
+
+ return (top_level_str_coll(((*ss1)->str), ((*ss2)->str)));
+}
+
+/*
+ * Maximum size of a number in the string (before or after decimal point)
+ */
+#define MAX_NUM_SIZE (128)
+
+/*
+ * Set suffix value
+ */
+static void setsuffix(wchar_t c, unsigned char *si)
+{
+ switch (c){
+ case L'k':
+ case L'K':
+ *si = 1;
+ break;
+ case L'M':
+ *si = 2;
+ break;
+ case L'G':
+ *si = 3;
+ break;
+ case L'T':
+ *si = 4;
+ break;
+ case L'P':
+ *si = 5;
+ break;
+ case L'E':
+ *si = 6;
+ break;
+ case L'Z':
+ *si = 7;
+ break;
+ case L'Y':
+ *si = 8;
+ break;
+ default:
+ *si = 0;
+ }
+}
+
+/*
+ * Read string s and parse the string into a fixed-decimal-point number.
+ * sign equals -1 if the number is negative (explicit plus is not allowed,
+ * according to GNU sort's "info sort".
+ * The number part before decimal point is in the smain, after the decimal
+ * point is in sfrac, tail is the pointer to the remainder of the string.
+ */
+static int
+read_number(struct bwstring *s0, int *sign, wchar_t *smain, size_t *main_len, wchar_t *sfrac, size_t *frac_len, unsigned char *si)
+{
+ bwstring_iterator s;
+
+ s = bws_begin(s0);
+
+ /* always end the fraction with zero, even if we have no fraction */
+ sfrac[0] = 0;
+
+ while (iswblank(bws_get_iter_value(s)))
+ s = bws_iterator_inc(s, 1);
+
+ if (bws_get_iter_value(s) == (wchar_t)symbol_negative_sign) {
+ *sign = -1;
+ s = bws_iterator_inc(s, 1);
+ }
+
+ // This is '0', not '\0', do not change this
+ while (iswdigit(bws_get_iter_value(s)) &&
+ (bws_get_iter_value(s) == L'0'))
+ s = bws_iterator_inc(s, 1);
+
+ while (bws_get_iter_value(s) && *main_len < MAX_NUM_SIZE) {
+ if (iswdigit(bws_get_iter_value(s))) {
+ smain[*main_len] = bws_get_iter_value(s);
+ s = bws_iterator_inc(s, 1);
+ *main_len += 1;
+ } else if (symbol_thousands_sep &&
+ (bws_get_iter_value(s) == (wchar_t)symbol_thousands_sep))
+ s = bws_iterator_inc(s, 1);
+ else
+ break;
+ }
+
+ smain[*main_len] = 0;
+
+ if (bws_get_iter_value(s) == (wchar_t)symbol_decimal_point) {
+ s = bws_iterator_inc(s, 1);
+ while (iswdigit(bws_get_iter_value(s)) &&
+ *frac_len < MAX_NUM_SIZE) {
+ sfrac[*frac_len] = bws_get_iter_value(s);
+ s = bws_iterator_inc(s, 1);
+ *frac_len += 1;
+ }
+ sfrac[*frac_len] = 0;
+
+ while (*frac_len > 0 && sfrac[*frac_len - 1] == L'0') {
+ --(*frac_len);
+ sfrac[*frac_len] = L'\0';
+ }
+ }
+
+ setsuffix(bws_get_iter_value(s),si);
+
+ if ((*main_len + *frac_len) == 0)
+ *sign = 0;
+
+ return (0);
+}
+
+/*
+ * Implements string sort.
+ */
+static int
+wstrcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
+{
+
+ if (debug_sort) {
+ if (offset)
+ printf("; offset=%d\n", (int) offset);
+ bwsprintf(stdout, kv1->k, "; k1=<", ">");
+ printf("(%zu)", BWSLEN(kv1->k));
+ bwsprintf(stdout, kv2->k, ", k2=<", ">");
+ printf("(%zu)", BWSLEN(kv2->k));
+ }
+
+ return (bwscoll(kv1->k, kv2->k, offset));
+}
+
+/*
+ * Compare two suffixes
+ */
+static inline int
+cmpsuffix(unsigned char si1, unsigned char si2)
+{
+
+ return ((char)si1 - (char)si2);
+}
+
+/*
+ * Implements numeric sort for -n and -h.
+ */
+static int
+numcoll_impl(struct key_value *kv1, struct key_value *kv2,
+ size_t offset __unused, bool use_suffix)
+{
+ struct bwstring *s1, *s2;
+ wchar_t sfrac1[MAX_NUM_SIZE + 1], sfrac2[MAX_NUM_SIZE + 1];
+ wchar_t smain1[MAX_NUM_SIZE + 1], smain2[MAX_NUM_SIZE + 1];
+ int cmp_res, sign1, sign2;
+ size_t frac1, frac2, main1, main2;
+ unsigned char SI1, SI2;
+ bool e1, e2, key1_read, key2_read;
+
+ s1 = kv1->k;
+ s2 = kv2->k;
+ sign1 = sign2 = 0;
+ main1 = main2 = 0;
+ frac1 = frac2 = 0;
+
+ key1_read = key2_read = false;
+
+ if (debug_sort) {
+ bwsprintf(stdout, s1, "; k1=<", ">");
+ bwsprintf(stdout, s2, ", k2=<", ">");
+ }
+
+ if (s1 == s2)
+ return (0);
+
+ if (kv1->hint->status == HS_UNINITIALIZED) {
+ /* read the number from the string */
+ read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1);
+ key1_read = true;
+ kv1->hint->v.nh.n1 = wcstoull(smain1, NULL, 10);
+ if(main1 < 1 && frac1 < 1)
+ kv1->hint->v.nh.empty=true;
+ kv1->hint->v.nh.si = SI1;
+ kv1->hint->status = (kv1->hint->v.nh.n1 != ULLONG_MAX) ?
+ HS_INITIALIZED : HS_ERROR;
+ kv1->hint->v.nh.neg = (sign1 < 0) ? true : false;
+ }
+
+ if (kv2->hint->status == HS_UNINITIALIZED) {
+ /* read the number from the string */
+ read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2,&SI2);
+ key2_read = true;
+ kv2->hint->v.nh.n1 = wcstoull(smain2, NULL, 10);
+ if(main2 < 1 && frac2 < 1)
+ kv2->hint->v.nh.empty=true;
+ kv2->hint->v.nh.si = SI2;
+ kv2->hint->status = (kv2->hint->v.nh.n1 != ULLONG_MAX) ?
+ HS_INITIALIZED : HS_ERROR;
+ kv2->hint->v.nh.neg = (sign2 < 0) ? true : false;
+ }
+
+ if (kv1->hint->status == HS_INITIALIZED && kv2->hint->status ==
+ HS_INITIALIZED) {
+ unsigned long long n1, n2;
+ bool neg1, neg2;
+
+ e1 = kv1->hint->v.nh.empty;
+ e2 = kv2->hint->v.nh.empty;
+
+ if (e1 && e2)
+ return (0);
+
+ neg1 = kv1->hint->v.nh.neg;
+ neg2 = kv2->hint->v.nh.neg;
+
+ if (neg1 && !neg2)
+ return (-1);
+ if (neg2 && !neg1)
+ return (+1);
+
+ if (e1)
+ return (neg2 ? +1 : -1);
+ else if (e2)
+ return (neg1 ? -1 : +1);
+
+
+ if (use_suffix) {
+ cmp_res = cmpsuffix(kv1->hint->v.nh.si, kv2->hint->v.nh.si);
+ if (cmp_res)
+ return (neg1 ? -cmp_res : cmp_res);
+ }
+
+ n1 = kv1->hint->v.nh.n1;
+ n2 = kv2->hint->v.nh.n1;
+ if (n1 < n2)
+ return (neg1 ? +1 : -1);
+ else if (n1 > n2)
+ return (neg1 ? -1 : +1);
+ }
+
+ /* read the numbers from the strings */
+ if (!key1_read)
+ read_number(s1, &sign1, smain1, &main1, sfrac1, &frac1, &SI1);
+ if (!key2_read)
+ read_number(s2, &sign2, smain2, &main2, sfrac2, &frac2, &SI2);
+
+ e1 = ((main1 + frac1) == 0);
+ e2 = ((main2 + frac2) == 0);
+
+ if (e1 && e2)
+ return (0);
+
+ /* we know the result if the signs are different */
+ if (sign1 < 0 && sign2 >= 0)
+ return (-1);
+ if (sign1 >= 0 && sign2 < 0)
+ return (+1);
+
+ if (e1)
+ return ((sign2 < 0) ? +1 : -1);
+ else if (e2)
+ return ((sign1 < 0) ? -1 : +1);
+
+ if (use_suffix) {
+ cmp_res = cmpsuffix(SI1, SI2);
+ if (cmp_res)
+ return ((sign1 < 0) ? -cmp_res : cmp_res);
+ }
+
+ /* if both numbers are empty assume that the strings are equal */
+ if (main1 < 1 && main2 < 1 && frac1 < 1 && frac2 < 1)
+ return (0);
+
+ /*
+ * if the main part is of different size, we know the result
+ * (because the leading zeros are removed)
+ */
+ if (main1 < main2)
+ cmp_res = -1;
+ else if (main1 > main2)
+ cmp_res = +1;
+ /* if the sizes are equal then simple non-collate string compare gives the correct result */
+ else
+ cmp_res = wcscmp(smain1, smain2);
+
+ /* check fraction */
+ if (!cmp_res)
+ cmp_res = wcscmp(sfrac1, sfrac2);
+
+ if (!cmp_res)
+ return (0);
+
+ /* reverse result if the signs are negative */
+ if (sign1 < 0 && sign2 < 0)
+ cmp_res = -cmp_res;
+
+ return (cmp_res);
+}
+
+/*
+ * Implements numeric sort (-n).
+ */
+static int
+numcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
+{
+
+ return (numcoll_impl(kv1, kv2, offset, false));
+}
+
+/*
+ * Implements 'human' numeric sort (-h).
+ */
+static int
+hnumcoll(struct key_value *kv1, struct key_value *kv2, size_t offset)
+{
+
+ return (numcoll_impl(kv1, kv2, offset, true));
+}
+
+/* Use hint space to memoize md5 computations, at least. */
+static void
+randomcoll_init_hint(struct key_value *kv, void *hash)
+{
+
+ memcpy(kv->hint->v.Rh.cached, hash, sizeof(kv->hint->v.Rh.cached));
+ kv->hint->status = HS_INITIALIZED;
+}
+
+/*
+ * Implements random sort (-R).
+ */
+static int
+randomcoll(struct key_value *kv1, struct key_value *kv2,
+ size_t offset __unused)
+{
+ struct bwstring *s1, *s2;
+ MD5_CTX ctx1, ctx2;
+ unsigned char hash1[MD5_DIGEST_LENGTH], hash2[MD5_DIGEST_LENGTH];
+ int cmp;
+
+ s1 = kv1->k;
+ s2 = kv2->k;
+
+ if (debug_sort) {
+ bwsprintf(stdout, s1, "; k1=<", ">");
+ bwsprintf(stdout, s2, ", k2=<", ">");
+ }
+
+ if (s1 == s2)
+ return (0);
+
+ if (kv1->hint->status == HS_INITIALIZED &&
+ kv2->hint->status == HS_INITIALIZED) {
+ cmp = memcmp(kv1->hint->v.Rh.cached,
+ kv2->hint->v.Rh.cached, sizeof(kv1->hint->v.Rh.cached));
+ if (cmp != 0)
+ return (cmp);
+ }
+
+ memcpy(&ctx1, &md5_ctx, sizeof(MD5_CTX));
+ memcpy(&ctx2, &md5_ctx, sizeof(MD5_CTX));
+
+ MD5Update(&ctx1, bwsrawdata(s1), bwsrawlen(s1));
+ MD5Update(&ctx2, bwsrawdata(s2), bwsrawlen(s2));
+
+ MD5Final(hash1, &ctx1);
+ MD5Final(hash2, &ctx2);
+
+ if (kv1->hint->status == HS_UNINITIALIZED)
+ randomcoll_init_hint(kv1, hash1);
+ if (kv2->hint->status == HS_UNINITIALIZED)
+ randomcoll_init_hint(kv2, hash2);
+
+ return (memcmp(hash1, hash2, sizeof(hash1)));
+}
+
+/*
+ * Implements version sort (-V).
+ */
+static int
+versioncoll(struct key_value *kv1, struct key_value *kv2,
+ size_t offset __unused)
+{
+ struct bwstring *s1, *s2;
+
+ s1 = kv1->k;
+ s2 = kv2->k;
+
+ if (debug_sort) {
+ bwsprintf(stdout, s1, "; k1=<", ">");
+ bwsprintf(stdout, s2, ", k2=<", ">");
+ }
+
+ if (s1 == s2)
+ return (0);
+
+ return (vcmp(s1, s2));
+}
+
+/*
+ * Check for minus infinity
+ */
+static inline bool
+huge_minus(double d, int err1)
+{
+
+ if (err1 == ERANGE)
+ if (d == -HUGE_VAL || d == -HUGE_VALF || d == -HUGE_VALL)
+ return (+1);
+
+ return (0);
+}
+
+/*
+ * Check for plus infinity
+ */
+static inline bool
+huge_plus(double d, int err1)
+{
+
+ if (err1 == ERANGE)
+ if (d == HUGE_VAL || d == HUGE_VALF || d == HUGE_VALL)
+ return (+1);
+
+ return (0);
+}
+
+/*
+ * Check whether a function is a NAN
+ */
+static bool
+is_nan(double d)
+{
+
+ return ((d == NAN) || (isnan(d)));
+}
+
+/*
+ * Compare two NANs
+ */
+static int
+cmp_nans(double d1, double d2)
+{
+
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+ return (0);
+}
+
+/*
+ * Implements general numeric sort (-g).
+ */
+static int
+gnumcoll(struct key_value *kv1, struct key_value *kv2,
+ size_t offset __unused)
+{
+ double d1, d2;
+ int err1, err2;
+ bool empty1, empty2, key1_read, key2_read;
+
+ d1 = d2 = 0;
+ err1 = err2 = 0;
+ key1_read = key2_read = false;
+
+ if (debug_sort) {
+ bwsprintf(stdout, kv1->k, "; k1=<", ">");
+ bwsprintf(stdout, kv2->k, "; k2=<", ">");
+ }
+
+ if (kv1->hint->status == HS_UNINITIALIZED) {
+ errno = 0;
+ d1 = bwstod(kv1->k, &empty1);
+ err1 = errno;
+
+ if (empty1)
+ kv1->hint->v.gh.notnum = true;
+ else if (err1 == 0) {
+ kv1->hint->v.gh.d = d1;
+ kv1->hint->v.gh.nan = is_nan(d1);
+ kv1->hint->status = HS_INITIALIZED;
+ } else
+ kv1->hint->status = HS_ERROR;
+
+ key1_read = true;
+ }
+
+ if (kv2->hint->status == HS_UNINITIALIZED) {
+ errno = 0;
+ d2 = bwstod(kv2->k, &empty2);
+ err2 = errno;
+
+ if (empty2)
+ kv2->hint->v.gh.notnum = true;
+ else if (err2 == 0) {
+ kv2->hint->v.gh.d = d2;
+ kv2->hint->v.gh.nan = is_nan(d2);
+ kv2->hint->status = HS_INITIALIZED;
+ } else
+ kv2->hint->status = HS_ERROR;
+
+ key2_read = true;
+ }
+
+ if (kv1->hint->status == HS_INITIALIZED &&
+ kv2->hint->status == HS_INITIALIZED) {
+ if (kv1->hint->v.gh.notnum)
+ return ((kv2->hint->v.gh.notnum) ? 0 : -1);
+ else if (kv2->hint->v.gh.notnum)
+ return (+1);
+
+ if (kv1->hint->v.gh.nan)
+ return ((kv2->hint->v.gh.nan) ?
+ cmp_nans(kv1->hint->v.gh.d, kv2->hint->v.gh.d) :
+ -1);
+ else if (kv2->hint->v.gh.nan)
+ return (+1);
+
+ d1 = kv1->hint->v.gh.d;
+ d2 = kv2->hint->v.gh.d;
+
+ if (d1 < d2)
+ return (-1);
+ else if (d1 > d2)
+ return (+1);
+ else
+ return (0);
+ }
+
+ if (!key1_read) {
+ errno = 0;
+ d1 = bwstod(kv1->k, &empty1);
+ err1 = errno;
+ }
+
+ if (!key2_read) {
+ errno = 0;
+ d2 = bwstod(kv2->k, &empty2);
+ err2 = errno;
+ }
+
+ /* Non-value case: */
+ if (empty1)
+ return (empty2 ? 0 : -1);
+ else if (empty2)
+ return (+1);
+
+ /* NAN case */
+ if (is_nan(d1))
+ return (is_nan(d2) ? cmp_nans(d1, d2) : -1);
+ else if (is_nan(d2))
+ return (+1);
+
+ /* Infinities */
+ if (err1 == ERANGE || err2 == ERANGE) {
+ /* Minus infinity case */
+ if (huge_minus(d1, err1)) {
+ if (huge_minus(d2, err2)) {
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+ return (0);
+ } else
+ return (-1);
+
+ } else if (huge_minus(d2, err2)) {
+ if (huge_minus(d1, err1)) {
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+ return (0);
+ } else
+ return (+1);
+ }
+
+ /* Plus infinity case */
+ if (huge_plus(d1, err1)) {
+ if (huge_plus(d2, err2)) {
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+ return (0);
+ } else
+ return (+1);
+ } else if (huge_plus(d2, err2)) {
+ if (huge_plus(d1, err1)) {
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+ return (0);
+ } else
+ return (-1);
+ }
+ }
+
+ if (d1 < d2)
+ return (-1);
+ if (d1 > d2)
+ return (+1);
+
+ return (0);
+}
+
+/*
+ * Implements month sort (-M).
+ */
+static int
+monthcoll(struct key_value *kv1, struct key_value *kv2, size_t offset __unused)
+{
+ int val1, val2;
+ bool key1_read, key2_read;
+
+ val1 = val2 = 0;
+ key1_read = key2_read = false;
+
+ if (debug_sort) {
+ bwsprintf(stdout, kv1->k, "; k1=<", ">");
+ bwsprintf(stdout, kv2->k, "; k2=<", ">");
+ }
+
+ if (kv1->hint->status == HS_UNINITIALIZED) {
+ kv1->hint->v.Mh.m = bws_month_score(kv1->k);
+ key1_read = true;
+ kv1->hint->status = HS_INITIALIZED;
+ }
+
+ if (kv2->hint->status == HS_UNINITIALIZED) {
+ kv2->hint->v.Mh.m = bws_month_score(kv2->k);
+ key2_read = true;
+ kv2->hint->status = HS_INITIALIZED;
+ }
+
+ if (kv1->hint->status == HS_INITIALIZED) {
+ val1 = kv1->hint->v.Mh.m;
+ key1_read = true;
+ }
+
+ if (kv2->hint->status == HS_INITIALIZED) {
+ val2 = kv2->hint->v.Mh.m;
+ key2_read = true;
+ }
+
+ if (!key1_read)
+ val1 = bws_month_score(kv1->k);
+ if (!key2_read)
+ val2 = bws_month_score(kv2->k);
+
+ if (val1 == val2) {
+ return (0);
+ }
+ if (val1 < val2)
+ return (-1);
+ return (+1);
+}
diff --git a/usr.bin/sort/coll.h b/usr.bin/sort/coll.h
new file mode 100644
index 000000000000..0ae1f20eab38
--- /dev/null
+++ b/usr.bin/sort/coll.h
@@ -0,0 +1,181 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__COLL_H__)
+#define __COLL_H__
+
+#include "bwstring.h"
+#include "sort.h"
+
+/*
+ * Sort hint data for -n
+ */
+struct n_hint
+{
+ unsigned long long n1;
+ unsigned char si;
+ bool empty;
+ bool neg;
+};
+
+/*
+ * Sort hint data for -g
+ */
+struct g_hint
+{
+ double d;
+ bool nan;
+ bool notnum;
+};
+
+/*
+ * Sort hint data for -M
+ */
+struct M_hint
+{
+ int m;
+};
+
+/*
+ * Sort hint data for -R
+ *
+ * This stores the first 12 bytes of the digest rather than the full output to
+ * avoid increasing the size of the 'key_hint' object via the 'v' union.
+ */
+struct R_hint
+{
+ unsigned char cached[12];
+};
+
+/*
+ * Status of a sort hint object
+ */
+typedef enum
+{
+ HS_ERROR = -1, HS_UNINITIALIZED = 0, HS_INITIALIZED = 1
+} hint_status;
+
+/*
+ * Sort hint object
+ */
+struct key_hint
+{
+ hint_status status;
+ union
+ {
+ struct n_hint nh;
+ struct g_hint gh;
+ struct M_hint Mh;
+ struct R_hint Rh;
+ } v;
+};
+
+/*
+ * Key value
+ */
+struct key_value
+{
+ struct bwstring *k; /* key string */
+ struct key_hint hint[0]; /* key sort hint */
+} __packed;
+
+/*
+ * Set of keys container object.
+ */
+struct keys_array
+{
+ struct key_value key[0];
+};
+
+/*
+ * Parsed -k option data
+ */
+struct key_specs
+{
+ struct sort_mods sm;
+ size_t c1;
+ size_t c2;
+ size_t f1;
+ size_t f2;
+ bool pos1b;
+ bool pos2b;
+};
+
+/*
+ * Single entry in sort list.
+ */
+struct sort_list_item
+{
+ struct bwstring *str;
+ struct keys_array ka;
+};
+
+/*
+ * Function type, used to compare two list objects
+ */
+typedef int (*listcoll_t)(struct sort_list_item **ss1, struct sort_list_item **ss2);
+
+extern struct key_specs *keys;
+extern size_t keys_num;
+
+/*
+ * Main localised symbols. These must be wint_t as they may hold WEOF.
+ */
+extern wint_t symbol_decimal_point;
+extern wint_t symbol_thousands_sep;
+extern wint_t symbol_negative_sign;
+extern wint_t symbol_positive_sign;
+
+/* funcs */
+
+cmpcoll_t get_sort_func(struct sort_mods *sm);
+
+struct keys_array *keys_array_alloc(void);
+size_t keys_array_size(void);
+struct key_value *get_key_from_keys_array(struct keys_array *ka, size_t ind);
+void set_key_on_keys_array(struct keys_array *ka, struct bwstring *s, size_t ind);
+void clean_keys_array(const struct bwstring *s, struct keys_array *ka);
+
+struct sort_list_item *sort_list_item_alloc(void);
+void sort_list_item_set(struct sort_list_item *si, struct bwstring *str);
+void sort_list_item_clean(struct sort_list_item *si);
+size_t sort_list_item_size(struct sort_list_item *si);
+
+int preproc(struct bwstring *s, struct keys_array *ka);
+int top_level_str_coll(const struct bwstring *, const struct bwstring *);
+int key_coll(struct keys_array *ks1, struct keys_array *ks2, size_t offset);
+int str_list_coll(struct bwstring *str1, struct sort_list_item **ss2);
+int list_coll_by_str_only(struct sort_list_item **ss1, struct sort_list_item **ss2);
+int list_coll(struct sort_list_item **ss1, struct sort_list_item **ss2);
+int list_coll_offset(struct sort_list_item **ss1, struct sort_list_item **ss2, size_t offset);
+
+listcoll_t get_list_call_func(size_t offset);
+
+#endif /* __COLL_H__ */
diff --git a/usr.bin/sort/file.c b/usr.bin/sort/file.c
new file mode 100644
index 000000000000..339c9b8de270
--- /dev/null
+++ b/usr.bin/sort/file.c
@@ -0,0 +1,1487 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <err.h>
+#include <fcntl.h>
+#if defined(SORT_THREADS)
+#include <pthread.h>
+#endif
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "coll.h"
+#include "file.h"
+#include "radixsort.h"
+
+unsigned long long free_memory = 1000000;
+unsigned long long available_free_memory = 1000000;
+
+bool use_mmap;
+
+const char *tmpdir = "/var/tmp";
+const char *compress_program;
+
+size_t max_open_files = 16;
+
+/*
+ * File reader structure
+ */
+struct file_reader
+{
+ FILE *file;
+ char *fname;
+ char *buffer;
+ unsigned char *mmapaddr;
+ unsigned char *mmapptr;
+ size_t bsz;
+ size_t mmapsize;
+ int fd;
+ char elsymb;
+};
+
+/*
+ * Structure to be used in file merge process.
+ */
+struct file_header
+{
+ struct file_reader *fr;
+ struct sort_list_item *si; /* current top line */
+ size_t file_pos;
+};
+
+/*
+ * List elements of "cleanable" files list.
+ */
+struct CLEANABLE_FILE
+{
+ char *fn;
+ LIST_ENTRY(CLEANABLE_FILE) files;
+};
+
+/*
+ * List header of "cleanable" files list.
+ */
+static LIST_HEAD(CLEANABLE_FILES,CLEANABLE_FILE) tmp_files;
+
+/*
+ * Semaphore to protect the tmp file list.
+ * We use semaphore here because it is signal-safe, according to POSIX.
+ * And semaphore does not require pthread library.
+ */
+static sem_t tmp_files_sem;
+
+static void mt_sort(struct sort_list *list,
+ int (*sort_func)(void *, size_t, size_t,
+ int (*)(const void *, const void *)), const char* fn);
+
+/*
+ * Init tmp files list
+ */
+void
+init_tmp_files(void)
+{
+
+ LIST_INIT(&tmp_files);
+ sem_init(&tmp_files_sem, 0, 1);
+}
+
+/*
+ * Save name of a tmp file for signal cleanup
+ */
+void
+tmp_file_atexit(const char *tmp_file)
+{
+
+ if (tmp_file) {
+ sem_wait(&tmp_files_sem);
+ struct CLEANABLE_FILE *item =
+ sort_malloc(sizeof(struct CLEANABLE_FILE));
+ item->fn = sort_strdup(tmp_file);
+ LIST_INSERT_HEAD(&tmp_files, item, files);
+ sem_post(&tmp_files_sem);
+ }
+}
+
+/*
+ * Clear tmp files
+ */
+void
+clear_tmp_files(void)
+{
+ struct CLEANABLE_FILE *item;
+
+ sem_wait(&tmp_files_sem);
+ LIST_FOREACH(item,&tmp_files,files) {
+ if ((item) && (item->fn))
+ unlink(item->fn);
+ }
+ sem_post(&tmp_files_sem);
+}
+
+/*
+ * Check whether a file is a temporary file
+ */
+static bool
+file_is_tmp(const char* fn)
+{
+ struct CLEANABLE_FILE *item;
+ bool ret = false;
+
+ if (fn) {
+ sem_wait(&tmp_files_sem);
+ LIST_FOREACH(item,&tmp_files,files) {
+ if ((item) && (item->fn))
+ if (strcmp(item->fn, fn) == 0) {
+ ret = true;
+ break;
+ }
+ }
+ sem_post(&tmp_files_sem);
+ }
+
+ return (ret);
+}
+
+/*
+ * Generate new temporary file name
+ */
+char *
+new_tmp_file_name(void)
+{
+ char *ret;
+ int fd;
+
+ if (asprintf(&ret, "%s/.bsdsort.XXXXXXXXXX", tmpdir) == -1)
+ err(2, "asprintf()");
+ if ((fd = mkstemp(ret)) == -1)
+ err(2, "mkstemp()");
+ close(fd);
+
+ tmp_file_atexit(ret);
+ return (ret);
+}
+
+/*
+ * Initialize file list
+ */
+void
+file_list_init(struct file_list *fl, bool tmp)
+{
+
+ if (fl) {
+ memset(fl, 0, sizeof(*fl));
+ fl->tmp = tmp;
+ }
+}
+
+/*
+ * Add a file name to the list
+ */
+void
+file_list_add(struct file_list *fl, const char *fn, bool allocate)
+{
+
+ if (fl && fn) {
+ if (fl->count >= fl->sz || (fl->fns == NULL)) {
+ fl->sz = (fl->sz) * 2 + 1;
+ fl->fns = sort_realloc(fl->fns, fl->sz *
+ sizeof(char *));
+ }
+ fl->fns[fl->count] = allocate ? sort_strdup(fn) : fn;
+ fl->count += 1;
+ }
+}
+
+/*
+ * Populate file list from array of file names
+ */
+void
+file_list_populate(struct file_list *fl, int argc, char **argv, bool allocate)
+{
+
+ if (fl && argv) {
+ int i;
+
+ for (i = 0; i < argc; i++)
+ file_list_add(fl, argv[i], allocate);
+ }
+}
+
+/*
+ * Clean file list data and delete the files,
+ * if this is a list of temporary files
+ */
+void
+file_list_clean(struct file_list *fl)
+{
+
+ if (fl) {
+ if (fl->fns) {
+ size_t i;
+
+ for (i = 0; i < fl->count; i++) {
+ if (fl->fns[i]) {
+ if (fl->tmp)
+ unlink(fl->fns[i]);
+ sort_free(fl->fns[i]);
+ fl->fns[i] = 0;
+ }
+ }
+ sort_free(fl->fns);
+ fl->fns = NULL;
+ }
+ fl->sz = 0;
+ fl->count = 0;
+ fl->tmp = false;
+ }
+}
+
+/*
+ * Init sort list
+ */
+void
+sort_list_init(struct sort_list *l)
+{
+
+ if (l) {
+ memset(l, 0, sizeof(*l));
+ l->memsize = sizeof(struct sort_list);
+ }
+}
+
+/*
+ * Add string to sort list
+ */
+void
+sort_list_add(struct sort_list *l, struct bwstring *str)
+{
+
+ if (l && str) {
+ size_t indx = l->count;
+
+ if ((l->list == NULL) || (indx >= l->size)) {
+ size_t newsize = (l->size + 1) + 1024;
+
+ l->list = sort_realloc(l->list,
+ sizeof(struct sort_list_item*) * newsize);
+ l->memsize += (newsize - l->size) *
+ sizeof(struct sort_list_item*);
+ l->size = newsize;
+ }
+ l->list[indx] = sort_list_item_alloc();
+ sort_list_item_set(l->list[indx], str);
+ l->memsize += sort_list_item_size(l->list[indx]);
+ l->count += 1;
+ }
+}
+
+/*
+ * Clean sort list data
+ */
+void
+sort_list_clean(struct sort_list *l)
+{
+
+ if (l) {
+ if (l->list) {
+ size_t i;
+
+ for (i = 0; i < l->count; i++) {
+ struct sort_list_item *item;
+
+ item = l->list[i];
+
+ if (item) {
+ sort_list_item_clean(item);
+ sort_free(item);
+ l->list[i] = NULL;
+ }
+ }
+ sort_free(l->list);
+ l->list = NULL;
+ }
+ l->count = 0;
+ l->size = 0;
+ l->memsize = sizeof(struct sort_list);
+ }
+}
+
+/*
+ * Write sort list to file
+ */
+void
+sort_list_dump(struct sort_list *l, const char *fn)
+{
+
+ if (l && fn) {
+ FILE *f;
+
+ f = openfile(fn, "w");
+ if (f == NULL)
+ err(2, NULL);
+
+ if (l->list) {
+ size_t i;
+ if (!(sort_opts_vals.uflag)) {
+ for (i = 0; i < l->count; ++i)
+ bwsfwrite(l->list[i]->str, f,
+ sort_opts_vals.zflag);
+ } else {
+ struct sort_list_item *last_printed_item = NULL;
+ struct sort_list_item *item;
+ for (i = 0; i < l->count; ++i) {
+ item = l->list[i];
+ if ((last_printed_item == NULL) ||
+ list_coll(&last_printed_item, &item)) {
+ bwsfwrite(item->str, f, sort_opts_vals.zflag);
+ last_printed_item = item;
+ }
+ }
+ }
+ }
+
+ closefile(f, fn);
+ }
+}
+
+/*
+ * Checks if the given file is sorted. Stops at the first disorder,
+ * prints the disordered line and returns 1.
+ */
+int
+check(const char *fn)
+{
+ struct bwstring *s1, *s2, *s1disorder, *s2disorder;
+ struct file_reader *fr;
+ struct keys_array *ka1, *ka2;
+ int res;
+ size_t pos, posdisorder;
+
+ s1 = s2 = s1disorder = s2disorder = NULL;
+ ka1 = ka2 = NULL;
+
+ fr = file_reader_init(fn);
+
+ res = 0;
+ pos = 1;
+ posdisorder = 1;
+
+ if (fr == NULL) {
+ err(2, NULL);
+ goto end;
+ }
+
+ s1 = file_reader_readline(fr);
+ if (s1 == NULL)
+ goto end;
+
+ ka1 = keys_array_alloc();
+ preproc(s1, ka1);
+
+ s2 = file_reader_readline(fr);
+ if (s2 == NULL)
+ goto end;
+
+ ka2 = keys_array_alloc();
+ preproc(s2, ka2);
+
+ for (;;) {
+
+ if (debug_sort) {
+ bwsprintf(stdout, s2, "s1=<", ">");
+ bwsprintf(stdout, s1, "s2=<", ">");
+ }
+ int cmp = key_coll(ka2, ka1, 0);
+ if (debug_sort)
+ printf("; cmp1=%d", cmp);
+
+ if (!cmp && sort_opts_vals.complex_sort &&
+ !(sort_opts_vals.uflag) && !(sort_opts_vals.sflag)) {
+ cmp = top_level_str_coll(s2, s1);
+ if (debug_sort)
+ printf("; cmp2=%d", cmp);
+ }
+ if (debug_sort)
+ printf("\n");
+
+ if ((sort_opts_vals.uflag && (cmp <= 0)) || (cmp < 0)) {
+ if (!(sort_opts_vals.csilentflag)) {
+ s2disorder = bwsdup(s2);
+ posdisorder = pos;
+ if (debug_sort)
+ s1disorder = bwsdup(s1);
+ }
+ res = 1;
+ goto end;
+ }
+
+ pos++;
+
+ clean_keys_array(s1, ka1);
+ sort_free(ka1);
+ ka1 = ka2;
+ ka2 = NULL;
+
+ bwsfree(s1);
+ s1 = s2;
+
+ s2 = file_reader_readline(fr);
+ if (s2 == NULL)
+ goto end;
+
+ ka2 = keys_array_alloc();
+ preproc(s2, ka2);
+ }
+
+end:
+ if (ka1) {
+ clean_keys_array(s1, ka1);
+ sort_free(ka1);
+ }
+
+ if (s1)
+ bwsfree(s1);
+
+ if (ka2) {
+ clean_keys_array(s2, ka2);
+ sort_free(ka2);
+ }
+
+ if (s2)
+ bwsfree(s2);
+
+ if ((fn == NULL) || (*fn == 0) || (strcmp(fn, "-") == 0)) {
+ for (;;) {
+ s2 = file_reader_readline(fr);
+ if (s2 == NULL)
+ break;
+ bwsfree(s2);
+ }
+ }
+
+ file_reader_free(fr);
+
+ if (s2disorder) {
+ bws_disorder_warnx(s2disorder, fn, posdisorder);
+ if (s1disorder) {
+ bws_disorder_warnx(s1disorder, fn, posdisorder);
+ if (s1disorder != s2disorder)
+ bwsfree(s1disorder);
+ }
+ bwsfree(s2disorder);
+ s1disorder = NULL;
+ s2disorder = NULL;
+ }
+
+ if (res)
+ exit(res);
+
+ return (0);
+}
+
+/*
+ * Opens a file. If the given filename is "-", stdout will be
+ * opened.
+ */
+FILE *
+openfile(const char *fn, const char *mode)
+{
+ FILE *file;
+
+ if (strcmp(fn, "-") == 0)
+ return ((mode && mode[0] == 'r') ? stdin : stdout);
+
+ mode_t orig_file_mask = 0;
+ int is_tmp = file_is_tmp(fn);
+
+ if (is_tmp && (mode[0] == 'w'))
+ orig_file_mask = umask(S_IWGRP | S_IWOTH |
+ S_IRGRP | S_IROTH);
+
+ if (is_tmp && (compress_program != NULL)) {
+ int r;
+ char *cmd;
+
+ fflush(stdout);
+
+ if (mode[0] == 'r')
+ r = asprintf(&cmd, "cat %s | %s -d",
+ fn, compress_program);
+ else if (mode[0] == 'w')
+ r = asprintf(&cmd, "%s > %s",
+ compress_program, fn);
+ else
+ err(2, "%s", getstr(7));
+
+ if (r == -1)
+ err(2, "aspritnf()");
+
+ if ((file = popen(cmd, mode)) == NULL)
+ err(2, NULL);
+ free(cmd);
+ } else
+ if ((file = fopen(fn, mode)) == NULL)
+ err(2, NULL);
+
+ if (is_tmp && (mode[0] == 'w'))
+ umask(orig_file_mask);
+
+ return (file);
+}
+
+/*
+ * Close file
+ */
+void
+closefile(FILE *f, const char *fn)
+{
+ if (f == NULL || f == stdin)
+ return;
+ if (f == stdout) {
+ fflush(f);
+ return;
+ }
+ if (file_is_tmp(fn) && compress_program != NULL) {
+ if(pclose(f)<0)
+ err(2,NULL);
+ } else
+ fclose(f);
+}
+
+/*
+ * Reads a file into the internal buffer.
+ */
+struct file_reader *
+file_reader_init(const char *fsrc)
+{
+ struct file_reader *ret;
+
+ if (fsrc == NULL)
+ fsrc = "-";
+
+ ret = sort_calloc(1, sizeof(struct file_reader));
+
+ ret->elsymb = sort_opts_vals.zflag ? '\0' : '\n';
+ ret->fname = sort_strdup(fsrc);
+
+ if (strcmp(fsrc, "-") && (compress_program == NULL) && use_mmap) {
+
+ do {
+ struct stat stat_buf;
+ void *addr;
+ size_t sz = 0;
+ int fd, flags;
+
+ flags = MAP_NOCORE | MAP_NOSYNC;
+
+ fd = open(fsrc, O_RDONLY);
+ if (fd < 0)
+ err(2, NULL);
+
+ if (fstat(fd, &stat_buf) < 0) {
+ close(fd);
+ break;
+ }
+
+ sz = stat_buf.st_size;
+
+#if defined(MAP_PREFAULT_READ)
+ flags |= MAP_PREFAULT_READ;
+#endif
+
+ addr = mmap(NULL, sz, PROT_READ, flags, fd, 0);
+ if (addr == MAP_FAILED) {
+ close(fd);
+ break;
+ }
+
+ ret->fd = fd;
+ ret->mmapaddr = addr;
+ ret->mmapsize = sz;
+ ret->mmapptr = ret->mmapaddr;
+
+ } while (0);
+ }
+
+ if (ret->mmapaddr == NULL) {
+ ret->file = openfile(fsrc, "r");
+ if (ret->file == NULL)
+ err(2, NULL);
+ }
+
+ return (ret);
+}
+
+struct bwstring *
+file_reader_readline(struct file_reader *fr)
+{
+ struct bwstring *ret = NULL;
+
+ if (fr->mmapaddr) {
+ unsigned char *mmapend;
+
+ mmapend = fr->mmapaddr + fr->mmapsize;
+ if (fr->mmapptr >= mmapend)
+ return (NULL);
+ else {
+ unsigned char *strend;
+ size_t sz;
+
+ sz = mmapend - fr->mmapptr;
+ strend = memchr(fr->mmapptr, fr->elsymb, sz);
+
+ if (strend == NULL) {
+ ret = bwscsbdup(fr->mmapptr, sz);
+ fr->mmapptr = mmapend;
+ } else {
+ ret = bwscsbdup(fr->mmapptr, strend -
+ fr->mmapptr);
+ fr->mmapptr = strend + 1;
+ }
+ }
+ } else {
+ ssize_t len;
+
+ len = getdelim(&fr->buffer, &fr->bsz, fr->elsymb, fr->file);
+ if (len < 0) {
+ if (!feof(fr->file))
+ err(2, NULL);
+ return (NULL);
+ }
+ if (len > 0 && fr->buffer[len - 1] == fr->elsymb)
+ len--;
+ ret = bwscsbdup(fr->buffer, len);
+ }
+
+ return (ret);
+}
+
+static void
+file_reader_clean(struct file_reader *fr)
+{
+
+ if (fr == NULL)
+ return;
+
+ if (fr->mmapaddr)
+ munmap(fr->mmapaddr, fr->mmapsize);
+ if (fr->fd)
+ close(fr->fd);
+
+ free(fr->buffer);
+ closefile(fr->file, fr->fname);
+ free(fr->fname);
+ memset(fr, 0, sizeof(struct file_reader));
+}
+
+void
+file_reader_free(struct file_reader *fr)
+{
+
+ if (fr == NULL)
+ return;
+ file_reader_clean(fr);
+ free(fr);
+}
+
+int
+procfile(const char *fsrc, struct sort_list *list, struct file_list *fl)
+{
+ struct file_reader *fr;
+
+ fr = file_reader_init(fsrc);
+ if (fr == NULL)
+ err(2, NULL);
+
+ /* file browse cycle */
+ for (;;) {
+ struct bwstring *bws;
+
+ bws = file_reader_readline(fr);
+
+ if (bws == NULL)
+ break;
+
+ sort_list_add(list, bws);
+
+ if (list->memsize >= available_free_memory) {
+ char *fn;
+
+ fn = new_tmp_file_name();
+ sort_list_to_file(list, fn);
+ file_list_add(fl, fn, false);
+ sort_list_clean(list);
+ }
+ }
+
+ file_reader_free(fr);
+
+ return (0);
+}
+
+/*
+ * Compare file headers. Files with EOF always go to the end of the list.
+ */
+static int
+file_header_cmp(struct file_header *f1, struct file_header *f2)
+{
+
+ if (f1 == f2)
+ return (0);
+ else {
+ if (f1->fr == NULL) {
+ return ((f2->fr == NULL) ? 0 : +1);
+ } else if (f2->fr == NULL)
+ return (-1);
+ else {
+ int ret;
+
+ ret = list_coll(&(f1->si), &(f2->si));
+ if (!ret)
+ return ((f1->file_pos < f2->file_pos) ? -1 : +1);
+ return (ret);
+ }
+ }
+}
+
+/*
+ * Allocate and init file header structure
+ */
+static void
+file_header_init(struct file_header **fh, const char *fn, size_t file_pos)
+{
+
+ if (fh && fn) {
+ struct bwstring *line;
+
+ *fh = sort_malloc(sizeof(struct file_header));
+ (*fh)->file_pos = file_pos;
+ (*fh)->fr = file_reader_init(fn);
+ if ((*fh)->fr == NULL) {
+ perror(fn);
+ err(2, "%s", getstr(8));
+ }
+ line = file_reader_readline((*fh)->fr);
+ if (line == NULL) {
+ file_reader_free((*fh)->fr);
+ (*fh)->fr = NULL;
+ (*fh)->si = NULL;
+ } else {
+ (*fh)->si = sort_list_item_alloc();
+ sort_list_item_set((*fh)->si, line);
+ }
+ }
+}
+
+/*
+ * Close file
+ */
+static void
+file_header_close(struct file_header **fh)
+{
+
+ if (fh && *fh) {
+ file_reader_free((*fh)->fr);
+ (*fh)->fr = NULL;
+ if ((*fh)->si) {
+ sort_list_item_clean((*fh)->si);
+ sort_free((*fh)->si);
+ (*fh)->si = NULL;
+ }
+ sort_free(*fh);
+ *fh = NULL;
+ }
+}
+
+/*
+ * Swap two array elements
+ */
+static void
+file_header_swap(struct file_header **fh, size_t i1, size_t i2)
+{
+ struct file_header *tmp;
+
+ tmp = fh[i1];
+ fh[i1] = fh[i2];
+ fh[i2] = tmp;
+}
+
+/* heap algorithm ==>> */
+
+/*
+ * See heap sort algorithm
+ * "Raises" last element to its right place
+ */
+static void
+file_header_heap_swim(struct file_header **fh, size_t indx)
+{
+
+ if (indx > 0) {
+ size_t parent_index;
+
+ parent_index = (indx - 1) >> 1;
+
+ if (file_header_cmp(fh[indx], fh[parent_index]) < 0) {
+ /* swap child and parent and continue */
+ file_header_swap(fh, indx, parent_index);
+ file_header_heap_swim(fh, parent_index);
+ }
+ }
+}
+
+/*
+ * Sink the top element to its correct position
+ */
+static void
+file_header_heap_sink(struct file_header **fh, size_t indx, size_t size)
+{
+ size_t left_child_index;
+ size_t right_child_index;
+
+ left_child_index = indx + indx + 1;
+ right_child_index = left_child_index + 1;
+
+ if (left_child_index < size) {
+ size_t min_child_index;
+
+ min_child_index = left_child_index;
+
+ if ((right_child_index < size) &&
+ (file_header_cmp(fh[left_child_index],
+ fh[right_child_index]) > 0))
+ min_child_index = right_child_index;
+ if (file_header_cmp(fh[indx], fh[min_child_index]) > 0) {
+ file_header_swap(fh, indx, min_child_index);
+ file_header_heap_sink(fh, min_child_index, size);
+ }
+ }
+}
+
+/* <<== heap algorithm */
+
+/*
+ * Adds element to the "left" end
+ */
+static void
+file_header_list_rearrange_from_header(struct file_header **fh, size_t size)
+{
+
+ file_header_heap_sink(fh, 0, size);
+}
+
+/*
+ * Adds element to the "right" end
+ */
+static void
+file_header_list_push(struct file_header *f, struct file_header **fh, size_t size)
+{
+
+ fh[size++] = f;
+ file_header_heap_swim(fh, size - 1);
+}
+
+struct last_printed
+{
+ struct bwstring *str;
+};
+
+/*
+ * Prints the current line of the file
+ */
+static void
+file_header_print(struct file_header *fh, FILE *f_out, struct last_printed *lp)
+{
+
+ if (fh && fh->fr && f_out && fh->si && fh->si->str) {
+ if (sort_opts_vals.uflag) {
+ if ((lp->str == NULL) || (str_list_coll(lp->str, &(fh->si)))) {
+ bwsfwrite(fh->si->str, f_out, sort_opts_vals.zflag);
+ if (lp->str)
+ bwsfree(lp->str);
+ lp->str = bwsdup(fh->si->str);
+ }
+ } else
+ bwsfwrite(fh->si->str, f_out, sort_opts_vals.zflag);
+ }
+}
+
+/*
+ * Read next line
+ */
+static void
+file_header_read_next(struct file_header *fh)
+{
+
+ if (fh && fh->fr) {
+ struct bwstring *tmp;
+
+ tmp = file_reader_readline(fh->fr);
+ if (tmp == NULL) {
+ file_reader_free(fh->fr);
+ fh->fr = NULL;
+ if (fh->si) {
+ sort_list_item_clean(fh->si);
+ sort_free(fh->si);
+ fh->si = NULL;
+ }
+ } else {
+ if (fh->si == NULL)
+ fh->si = sort_list_item_alloc();
+ sort_list_item_set(fh->si, tmp);
+ }
+ }
+}
+
+/*
+ * Merge array of "files headers"
+ */
+static void
+file_headers_merge(size_t fnum, struct file_header **fh, FILE *f_out)
+{
+ struct last_printed lp;
+ size_t i;
+
+ memset(&lp, 0, sizeof(lp));
+
+ /*
+ * construct the initial sort structure
+ */
+ for (i = 0; i < fnum; i++)
+ file_header_list_push(fh[i], fh, i);
+
+ while (fh[0]->fr) { /* unfinished files are always in front */
+ /* output the smallest line: */
+ file_header_print(fh[0], f_out, &lp);
+ /* read a new line, if possible: */
+ file_header_read_next(fh[0]);
+ /* re-arrange the list: */
+ file_header_list_rearrange_from_header(fh, fnum);
+ }
+
+ if (lp.str)
+ bwsfree(lp.str);
+}
+
+/*
+ * Merges the given files into the output file, which can be
+ * stdout.
+ */
+static void
+merge_files_array(size_t argc, const char **argv, const char *fn_out)
+{
+
+ if (argv && fn_out) {
+ struct file_header **fh;
+ FILE *f_out;
+ size_t i;
+
+ f_out = openfile(fn_out, "w");
+
+ if (f_out == NULL)
+ err(2, NULL);
+
+ fh = sort_malloc((argc + 1) * sizeof(struct file_header *));
+
+ for (i = 0; i < argc; i++)
+ file_header_init(fh + i, argv[i], (size_t) i);
+
+ file_headers_merge(argc, fh, f_out);
+
+ for (i = 0; i < argc; i++)
+ file_header_close(fh + i);
+
+ sort_free(fh);
+
+ closefile(f_out, fn_out);
+ }
+}
+
+/*
+ * Shrinks the file list until its size smaller than max number of opened files
+ */
+static int
+shrink_file_list(struct file_list *fl)
+{
+
+ if ((fl == NULL) || (size_t) (fl->count) < max_open_files)
+ return (0);
+ else {
+ struct file_list new_fl;
+ size_t indx = 0;
+
+ file_list_init(&new_fl, true);
+ while (indx < fl->count) {
+ char *fnew;
+ size_t num;
+
+ num = fl->count - indx;
+ fnew = new_tmp_file_name();
+
+ if ((size_t) num >= max_open_files)
+ num = max_open_files - 1;
+ merge_files_array(num, fl->fns + indx, fnew);
+ if (fl->tmp) {
+ size_t i;
+
+ for (i = 0; i < num; i++)
+ unlink(fl->fns[indx + i]);
+ }
+ file_list_add(&new_fl, fnew, false);
+ indx += num;
+ }
+ fl->tmp = false; /* already taken care of */
+ file_list_clean(fl);
+
+ fl->count = new_fl.count;
+ fl->fns = new_fl.fns;
+ fl->sz = new_fl.sz;
+ fl->tmp = new_fl.tmp;
+
+ return (1);
+ }
+}
+
+/*
+ * Merge list of files
+ */
+void
+merge_files(struct file_list *fl, const char *fn_out)
+{
+
+ if (fl && fn_out) {
+ while (shrink_file_list(fl));
+
+ merge_files_array(fl->count, fl->fns, fn_out);
+ }
+}
+
+static const char *
+get_sort_method_name(int sm)
+{
+
+ if (sm == SORT_MERGESORT)
+ return "mergesort";
+ else if (sort_opts_vals.sort_method == SORT_RADIXSORT)
+ return "radixsort";
+ else if (sort_opts_vals.sort_method == SORT_HEAPSORT)
+ return "heapsort";
+ else
+ return "quicksort";
+}
+
+/*
+ * Wrapper for qsort
+ */
+static int sort_qsort(void *list, size_t count, size_t elem_size,
+ int (*cmp_func)(const void *, const void *))
+{
+
+ qsort(list, count, elem_size, cmp_func);
+ return (0);
+}
+
+/*
+ * Sort list of lines and writes it to the file
+ */
+void
+sort_list_to_file(struct sort_list *list, const char *outfile)
+{
+ struct sort_mods *sm = &(keys[0].sm);
+
+ if (!(sm->Mflag) && !(sm->Rflag) && !(sm->Vflag) &&
+ !(sm->gflag) && !(sm->hflag) && !(sm->nflag)) {
+ if ((sort_opts_vals.sort_method == SORT_DEFAULT) && byte_sort)
+ sort_opts_vals.sort_method = SORT_RADIXSORT;
+
+ } else if (sort_opts_vals.sort_method == SORT_RADIXSORT)
+ err(2, "%s", getstr(9));
+
+ /*
+ * to handle stable sort and the unique cases in the
+ * right order, we need stable basic algorithm
+ */
+ if (sort_opts_vals.sflag) {
+ switch (sort_opts_vals.sort_method){
+ case SORT_MERGESORT:
+ break;
+ case SORT_RADIXSORT:
+ break;
+ case SORT_DEFAULT:
+ sort_opts_vals.sort_method = SORT_MERGESORT;
+ break;
+ default:
+ errx(2, "%s", getstr(10));
+ }
+ }
+
+ if (sort_opts_vals.sort_method == SORT_DEFAULT)
+ sort_opts_vals.sort_method = DEFAULT_SORT_ALGORITHM;
+
+ if (debug_sort)
+ printf("sort_method=%s\n",
+ get_sort_method_name(sort_opts_vals.sort_method));
+
+ switch (sort_opts_vals.sort_method){
+ case SORT_RADIXSORT:
+ rxsort(list->list, list->count);
+ sort_list_dump(list, outfile);
+ break;
+ case SORT_MERGESORT:
+ mt_sort(list, mergesort, outfile);
+ break;
+ case SORT_HEAPSORT:
+ mt_sort(list, heapsort, outfile);
+ break;
+ case SORT_QSORT:
+ mt_sort(list, sort_qsort, outfile);
+ break;
+ default:
+ mt_sort(list, DEFAULT_SORT_FUNC, outfile);
+ break;
+ }
+}
+
+/******************* MT SORT ************************/
+
+#if defined(SORT_THREADS)
+/* semaphore to count threads */
+static sem_t mtsem;
+
+/* current system sort function */
+static int (*g_sort_func)(void *, size_t, size_t,
+ int(*)(const void *, const void *));
+
+/*
+ * Sort cycle thread (in multi-threaded mode)
+ */
+static void*
+mt_sort_thread(void* arg)
+{
+ struct sort_list *list = arg;
+
+ g_sort_func(list->list, list->count, sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+
+ sem_post(&mtsem);
+
+ return (arg);
+}
+
+/*
+ * Compare sub-lists. Empty sub-lists always go to the end of the list.
+ */
+static int
+sub_list_cmp(struct sort_list *l1, struct sort_list *l2)
+{
+
+ if (l1 == l2)
+ return (0);
+ else {
+ if (l1->count == 0) {
+ return ((l2->count == 0) ? 0 : +1);
+ } else if (l2->count == 0) {
+ return (-1);
+ } else {
+ int ret;
+
+ ret = list_coll(&(l1->list[0]), &(l2->list[0]));
+ if (!ret)
+ return ((l1->sub_list_pos < l2->sub_list_pos) ?
+ -1 : +1);
+ return (ret);
+ }
+ }
+}
+
+/*
+ * Swap two array elements
+ */
+static void
+sub_list_swap(struct sort_list **sl, size_t i1, size_t i2)
+{
+ struct sort_list *tmp;
+
+ tmp = sl[i1];
+ sl[i1] = sl[i2];
+ sl[i2] = tmp;
+}
+
+/* heap algorithm ==>> */
+
+/*
+ * See heap sort algorithm
+ * "Raises" last element to its right place
+ */
+static void
+sub_list_swim(struct sort_list **sl, size_t indx)
+{
+
+ if (indx > 0) {
+ size_t parent_index;
+
+ parent_index = (indx - 1) >> 1;
+
+ if (sub_list_cmp(sl[indx], sl[parent_index]) < 0) {
+ /* swap child and parent and continue */
+ sub_list_swap(sl, indx, parent_index);
+ sub_list_swim(sl, parent_index);
+ }
+ }
+}
+
+/*
+ * Sink the top element to its correct position
+ */
+static void
+sub_list_sink(struct sort_list **sl, size_t indx, size_t size)
+{
+ size_t left_child_index;
+ size_t right_child_index;
+
+ left_child_index = indx + indx + 1;
+ right_child_index = left_child_index + 1;
+
+ if (left_child_index < size) {
+ size_t min_child_index;
+
+ min_child_index = left_child_index;
+
+ if ((right_child_index < size) &&
+ (sub_list_cmp(sl[left_child_index],
+ sl[right_child_index]) > 0))
+ min_child_index = right_child_index;
+ if (sub_list_cmp(sl[indx], sl[min_child_index]) > 0) {
+ sub_list_swap(sl, indx, min_child_index);
+ sub_list_sink(sl, min_child_index, size);
+ }
+ }
+}
+
+/* <<== heap algorithm */
+
+/*
+ * Adds element to the "right" end
+ */
+static void
+sub_list_push(struct sort_list *s, struct sort_list **sl, size_t size)
+{
+
+ sl[size++] = s;
+ sub_list_swim(sl, size - 1);
+}
+
+struct last_printed_item
+{
+ struct sort_list_item *item;
+};
+
+/*
+ * Prints the current line of the file
+ */
+static void
+sub_list_header_print(struct sort_list *sl, FILE *f_out,
+ struct last_printed_item *lp)
+{
+
+ if (sl && sl->count && f_out && sl->list[0]->str) {
+ if (sort_opts_vals.uflag) {
+ if ((lp->item == NULL) || (list_coll(&(lp->item),
+ &(sl->list[0])))) {
+ bwsfwrite(sl->list[0]->str, f_out,
+ sort_opts_vals.zflag);
+ lp->item = sl->list[0];
+ }
+ } else
+ bwsfwrite(sl->list[0]->str, f_out,
+ sort_opts_vals.zflag);
+ }
+}
+
+/*
+ * Read next line
+ */
+static void
+sub_list_next(struct sort_list *sl)
+{
+
+ if (sl && sl->count) {
+ sl->list += 1;
+ sl->count -= 1;
+ }
+}
+
+/*
+ * Merge sub-lists to a file
+ */
+static void
+merge_sub_lists(struct sort_list **sl, size_t n, FILE* f_out)
+{
+ struct last_printed_item lp;
+ size_t i;
+
+ memset(&lp,0,sizeof(lp));
+
+ /* construct the initial list: */
+ for (i = 0; i < n; i++)
+ sub_list_push(sl[i], sl, i);
+
+ while (sl[0]->count) { /* unfinished lists are always in front */
+ /* output the smallest line: */
+ sub_list_header_print(sl[0], f_out, &lp);
+ /* move to a new line, if possible: */
+ sub_list_next(sl[0]);
+ /* re-arrange the list: */
+ sub_list_sink(sl, 0, n);
+ }
+}
+
+/*
+ * Merge sub-lists to a file
+ */
+static void
+merge_list_parts(struct sort_list **parts, size_t n, const char *fn)
+{
+ FILE* f_out;
+
+ f_out = openfile(fn,"w");
+
+ merge_sub_lists(parts, n, f_out);
+
+ closefile(f_out, fn);
+}
+
+#endif /* defined(SORT_THREADS) */
+/*
+ * Multi-threaded sort algorithm "driver"
+ */
+static void
+mt_sort(struct sort_list *list,
+ int(*sort_func)(void *, size_t, size_t, int(*)(const void *, const void *)),
+ const char* fn)
+{
+#if defined(SORT_THREADS)
+ if (nthreads < 2 || list->count < MT_SORT_THRESHOLD) {
+ size_t nthreads_save = nthreads;
+ nthreads = 1;
+#endif
+ /* if single thread or small data, do simple sort */
+ sort_func(list->list, list->count,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+ sort_list_dump(list, fn);
+#if defined(SORT_THREADS)
+ nthreads = nthreads_save;
+ } else {
+ /* multi-threaded sort */
+ struct sort_list **parts;
+ size_t avgsize, cstart, i;
+
+ /* array of sub-lists */
+ parts = sort_malloc(sizeof(struct sort_list*) * nthreads);
+ cstart = 0;
+ avgsize = list->count / nthreads;
+
+ /* set global system sort function */
+ g_sort_func = sort_func;
+
+ /* set sublists */
+ for (i = 0; i < nthreads; ++i) {
+ size_t sz = 0;
+
+ parts[i] = sort_malloc(sizeof(struct sort_list));
+ parts[i]->list = list->list + cstart;
+ parts[i]->memsize = 0;
+ parts[i]->sub_list_pos = i;
+
+ sz = (i == nthreads - 1) ? list->count - cstart :
+ avgsize;
+
+ parts[i]->count = sz;
+
+ parts[i]->size = parts[i]->count;
+
+ cstart += sz;
+ }
+
+ /* init threads counting semaphore */
+ sem_init(&mtsem, 0, 0);
+
+ /* start threads */
+ for (i = 0; i < nthreads; ++i) {
+ pthread_t pth;
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_DETACHED);
+
+ for (;;) {
+ int res = pthread_create(&pth, &attr,
+ mt_sort_thread, parts[i]);
+
+ if (res >= 0)
+ break;
+ if (errno == EAGAIN) {
+ pthread_yield();
+ continue;
+ }
+ err(2, NULL);
+ }
+
+ pthread_attr_destroy(&attr);
+ }
+
+ /* wait for threads completion */
+ for (i = 0; i < nthreads; ++i) {
+ sem_wait(&mtsem);
+ }
+ /* destroy the semaphore - we do not need it anymore */
+ sem_destroy(&mtsem);
+
+ /* merge sorted sub-lists to the file */
+ merge_list_parts(parts, nthreads, fn);
+
+ /* free sub-lists data */
+ for (i = 0; i < nthreads; ++i) {
+ sort_free(parts[i]);
+ }
+ sort_free(parts);
+ }
+#endif /* defined(SORT_THREADS) */
+}
diff --git a/usr.bin/sort/file.h b/usr.bin/sort/file.h
new file mode 100644
index 000000000000..7b513165b57b
--- /dev/null
+++ b/usr.bin/sort/file.h
@@ -0,0 +1,127 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__SORT_FILE_H__)
+#define __SORT_FILE_H__
+
+#include "coll.h"
+#include "sort.h"
+
+#define SORT_DEFAULT 0
+#define SORT_QSORT 1
+#define SORT_MERGESORT 2
+#define SORT_HEAPSORT 3
+#define SORT_RADIXSORT 4
+
+#define DEFAULT_SORT_ALGORITHM SORT_MERGESORT
+#define DEFAULT_SORT_FUNC mergesort
+
+/*
+ * List of data to be sorted.
+ */
+struct sort_list
+{
+ struct sort_list_item **list;
+ unsigned long long memsize;
+ size_t count;
+ size_t size;
+ size_t sub_list_pos;
+};
+
+/*
+ * File reader object
+ */
+struct file_reader;
+
+/*
+ * List of files to be sorted
+ */
+struct file_list
+{
+ const char * *fns;
+ size_t count;
+ size_t sz;
+ bool tmp;
+};
+
+/* memory */
+
+/**/
+
+extern unsigned long long free_memory;
+extern unsigned long long available_free_memory;
+
+/* Are we using mmap ? */
+extern bool use_mmap;
+
+/* temporary file dir */
+
+extern const char *tmpdir;
+
+/*
+ * Max number of simultaneously open files (including the output file).
+ */
+extern size_t max_open_files;
+
+/*
+ * Compress program
+ */
+extern const char* compress_program;
+
+/* funcs */
+
+struct file_reader *file_reader_init(const char *fsrc);
+struct bwstring *file_reader_readline(struct file_reader *fr);
+void file_reader_free(struct file_reader *fr);
+
+void init_tmp_files(void);
+void clear_tmp_files(void);
+char *new_tmp_file_name(void);
+void tmp_file_atexit(const char *tmp_file);
+
+void file_list_init(struct file_list *fl, bool tmp);
+void file_list_add(struct file_list *fl, const char *fn, bool allocate);
+void file_list_populate(struct file_list *fl, int argc, char **argv, bool allocate);
+void file_list_clean(struct file_list *fl);
+
+int check(const char *);
+void merge_files(struct file_list *fl, const char *fn_out);
+FILE *openfile(const char *, const char *);
+void closefile(FILE *, const char *);
+int procfile(const char *fn, struct sort_list *list, struct file_list *fl);
+
+void sort_list_init(struct sort_list *l);
+void sort_list_add(struct sort_list *l, struct bwstring *str);
+void sort_list_clean(struct sort_list *l);
+void sort_list_dump(struct sort_list *l, const char *fn);
+
+void sort_list_to_file(struct sort_list *list, const char *outfile);
+
+#endif /* __SORT_FILE_H__ */
diff --git a/usr.bin/sort/mem.c b/usr.bin/sort/mem.c
new file mode 100644
index 000000000000..ce5ad3b901f4
--- /dev/null
+++ b/usr.bin/sort/mem.c
@@ -0,0 +1,91 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mem.h"
+
+void*
+sort_calloc(size_t nb, size_t size)
+{
+ void *ptr;
+
+ if ((ptr = calloc(nb, size)) == NULL)
+ err(2, NULL);
+ return (ptr);
+}
+
+/*
+ * malloc() wrapper.
+ */
+void *
+sort_malloc(size_t size)
+{
+ void *ptr;
+
+ if ((ptr = malloc(size)) == NULL)
+ err(2, NULL);
+ return (ptr);
+}
+
+/*
+ * free() wrapper.
+ */
+void
+sort_free(const void *ptr)
+{
+
+ if (ptr)
+ free(__DECONST(void *, ptr));
+}
+
+/*
+ * realloc() wrapper.
+ */
+void *
+sort_realloc(void *ptr, size_t size)
+{
+
+ if ((ptr = realloc(ptr, size)) == NULL)
+ err(2, NULL);
+ return (ptr);
+}
+
+char *
+sort_strdup(const char *str)
+{
+ char *dup;
+
+ if ((dup = strdup(str)) == NULL)
+ err(2, NULL);
+ return (dup);
+}
diff --git a/usr.bin/sort/mem.h b/usr.bin/sort/mem.h
new file mode 100644
index 000000000000..4e733efd0f61
--- /dev/null
+++ b/usr.bin/sort/mem.h
@@ -0,0 +1,47 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__SORT_MEM_H__)
+#define __SORT_MEM_H__
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/*
+ * mem.c
+ */
+void *sort_calloc(size_t, size_t);
+void *sort_malloc(size_t);
+void sort_free(const void *ptr);
+void *sort_realloc(void *, size_t);
+char *sort_strdup(const char *);
+
+#endif /* __SORT_MEM_H__ */
diff --git a/usr.bin/sort/radixsort.c b/usr.bin/sort/radixsort.c
new file mode 100644
index 000000000000..5ee998500d30
--- /dev/null
+++ b/usr.bin/sort/radixsort.c
@@ -0,0 +1,722 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * Copyright (C) 2012 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <errno.h>
+#include <err.h>
+#include <langinfo.h>
+#include <math.h>
+#if defined(SORT_THREADS)
+#include <pthread.h>
+#include <semaphore.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <unistd.h>
+
+#include "coll.h"
+#include "radixsort.h"
+
+#define DEFAULT_SORT_FUNC_RADIXSORT mergesort
+
+#define TINY_NODE(sl) ((sl)->tosort_num < 65)
+#define SMALL_NODE(sl) ((sl)->tosort_num < 5)
+
+/* are we sorting in reverse order ? */
+static bool reverse_sort;
+
+/* sort sub-levels array size */
+static const size_t slsz = 256 * sizeof(struct sort_level*);
+
+/* one sort level structure */
+struct sort_level
+{
+ struct sort_level **sublevels;
+ struct sort_list_item **leaves;
+ struct sort_list_item **sorted;
+ struct sort_list_item **tosort;
+ size_t leaves_num;
+ size_t leaves_sz;
+ size_t level;
+ size_t real_sln;
+ size_t start_position;
+ size_t sln;
+ size_t tosort_num;
+ size_t tosort_sz;
+};
+
+/* stack of sort levels ready to be sorted */
+struct level_stack {
+ struct level_stack *next;
+ struct sort_level *sl;
+};
+
+static struct level_stack *g_ls;
+
+#if defined(SORT_THREADS)
+/* stack guarding mutex */
+static pthread_cond_t g_ls_cond;
+static pthread_mutex_t g_ls_mutex;
+
+/* counter: how many items are left */
+static size_t sort_left;
+/* guarding mutex */
+
+/* semaphore to count threads */
+static sem_t mtsem;
+
+/*
+ * Decrement items counter
+ */
+static inline void
+sort_left_dec(size_t n)
+{
+ pthread_mutex_lock(&g_ls_mutex);
+ sort_left -= n;
+ if (sort_left == 0 && nthreads > 1)
+ pthread_cond_broadcast(&g_ls_cond);
+ pthread_mutex_unlock(&g_ls_mutex);
+}
+
+/*
+ * Do we have something to sort ?
+ *
+ * This routine does not need to be locked.
+ */
+static inline bool
+have_sort_left(void)
+{
+ bool ret;
+
+ ret = (sort_left > 0);
+
+ return (ret);
+}
+
+#else
+
+#define sort_left_dec(n)
+
+#endif /* SORT_THREADS */
+
+static void
+_push_ls(struct level_stack *ls)
+{
+
+ ls->next = g_ls;
+ g_ls = ls;
+}
+
+/*
+ * Push sort level to the stack
+ */
+static inline void
+push_ls(struct sort_level *sl)
+{
+ struct level_stack *new_ls;
+
+ new_ls = sort_malloc(sizeof(struct level_stack));
+ new_ls->sl = sl;
+
+#if defined(SORT_THREADS)
+ if (nthreads > 1) {
+ pthread_mutex_lock(&g_ls_mutex);
+ _push_ls(new_ls);
+ pthread_cond_signal(&g_ls_cond);
+ pthread_mutex_unlock(&g_ls_mutex);
+ } else
+#endif
+ _push_ls(new_ls);
+}
+
+/*
+ * Pop sort level from the stack (single-threaded style)
+ */
+static inline struct sort_level*
+pop_ls_st(void)
+{
+ struct sort_level *sl;
+
+ if (g_ls) {
+ struct level_stack *saved_ls;
+
+ sl = g_ls->sl;
+ saved_ls = g_ls;
+ g_ls = g_ls->next;
+ sort_free(saved_ls);
+ } else
+ sl = NULL;
+
+ return (sl);
+}
+
+#if defined(SORT_THREADS)
+
+/*
+ * Pop sort level from the stack (multi-threaded style)
+ */
+static inline struct sort_level*
+pop_ls_mt(void)
+{
+ struct level_stack *saved_ls;
+ struct sort_level *sl;
+
+ pthread_mutex_lock(&g_ls_mutex);
+
+ for (;;) {
+ if (g_ls) {
+ sl = g_ls->sl;
+ saved_ls = g_ls;
+ g_ls = g_ls->next;
+ break;
+ }
+ sl = NULL;
+ saved_ls = NULL;
+
+ if (have_sort_left() == 0)
+ break;
+ pthread_cond_wait(&g_ls_cond, &g_ls_mutex);
+ }
+
+ pthread_mutex_unlock(&g_ls_mutex);
+
+ sort_free(saved_ls);
+
+ return (sl);
+}
+
+#endif /* defined(SORT_THREADS) */
+
+static void
+add_to_sublevel(struct sort_level *sl, struct sort_list_item *item, size_t indx)
+{
+ struct sort_level *ssl;
+
+ ssl = sl->sublevels[indx];
+
+ if (ssl == NULL) {
+ ssl = sort_calloc(1, sizeof(struct sort_level));
+
+ ssl->level = sl->level + 1;
+ sl->sublevels[indx] = ssl;
+
+ ++(sl->real_sln);
+ }
+
+ if (++(ssl->tosort_num) > ssl->tosort_sz) {
+ ssl->tosort_sz = ssl->tosort_num + 128;
+ ssl->tosort = sort_realloc(ssl->tosort,
+ sizeof(struct sort_list_item*) * (ssl->tosort_sz));
+ }
+
+ ssl->tosort[ssl->tosort_num - 1] = item;
+}
+
+static inline void
+add_leaf(struct sort_level *sl, struct sort_list_item *item)
+{
+
+ if (++(sl->leaves_num) > sl->leaves_sz) {
+ sl->leaves_sz = sl->leaves_num + 128;
+ sl->leaves = sort_realloc(sl->leaves,
+ (sizeof(struct sort_list_item*) * (sl->leaves_sz)));
+ }
+ sl->leaves[sl->leaves_num - 1] = item;
+}
+
+static inline int
+get_wc_index(struct sort_list_item *sli, size_t level)
+{
+ const size_t wcfact = (mb_cur_max == 1) ? 1 : sizeof(wchar_t);
+ const struct key_value *kv;
+ const struct bwstring *bws;
+
+ kv = get_key_from_keys_array(&sli->ka, 0);
+ bws = kv->k;
+
+ if ((BWSLEN(bws) * wcfact > level)) {
+ wchar_t res;
+
+ /*
+ * Sort wchar strings a byte at a time, rather than a single
+ * byte from each wchar.
+ */
+ res = (wchar_t)BWS_GET(bws, level / wcfact);
+ /* Sort most-significant byte first. */
+ if (level % wcfact < wcfact - 1)
+ res = (res >> (8 * (wcfact - 1 - (level % wcfact))));
+
+ return (res & 0xff);
+ }
+
+ return (-1);
+}
+
+static void
+place_item(struct sort_level *sl, size_t item)
+{
+ struct sort_list_item *sli;
+ int c;
+
+ sli = sl->tosort[item];
+ c = get_wc_index(sli, sl->level);
+
+ if (c == -1)
+ add_leaf(sl, sli);
+ else
+ add_to_sublevel(sl, sli, c);
+}
+
+static void
+free_sort_level(struct sort_level *sl)
+{
+
+ if (sl) {
+ if (sl->leaves)
+ sort_free(sl->leaves);
+
+ if (sl->level > 0)
+ sort_free(sl->tosort);
+
+ if (sl->sublevels) {
+ struct sort_level *slc;
+ size_t sln;
+
+ sln = sl->sln;
+
+ for (size_t i = 0; i < sln; ++i) {
+ slc = sl->sublevels[i];
+ if (slc)
+ free_sort_level(slc);
+ }
+
+ sort_free(sl->sublevels);
+ }
+
+ sort_free(sl);
+ }
+}
+
+static void
+run_sort_level_next(struct sort_level *sl)
+{
+ const size_t wcfact = (mb_cur_max == 1) ? 1 : sizeof(wchar_t);
+ struct sort_level *slc;
+ size_t i, sln, tosort_num;
+
+ if (sl->sublevels) {
+ sort_free(sl->sublevels);
+ sl->sublevels = NULL;
+ }
+
+ switch (sl->tosort_num) {
+ case 0:
+ goto end;
+ case (1):
+ sl->sorted[sl->start_position] = sl->tosort[0];
+ sort_left_dec(1);
+ goto end;
+ case (2):
+ /*
+ * Radixsort only processes a single byte at a time. In wchar
+ * mode, this can be a subset of the length of a character.
+ * list_coll_offset() offset is in units of wchar, not bytes.
+ * So to calculate the offset, we must divide by
+ * sizeof(wchar_t) and round down to the index of the first
+ * character this level references.
+ */
+ if (list_coll_offset(&(sl->tosort[0]), &(sl->tosort[1]),
+ sl->level / wcfact) > 0) {
+ sl->sorted[sl->start_position++] = sl->tosort[1];
+ sl->sorted[sl->start_position] = sl->tosort[0];
+ } else {
+ sl->sorted[sl->start_position++] = sl->tosort[0];
+ sl->sorted[sl->start_position] = sl->tosort[1];
+ }
+ sort_left_dec(2);
+
+ goto end;
+ default:
+ if (TINY_NODE(sl) || (sl->level > 15)) {
+ listcoll_t func;
+
+ /*
+ * Collate comparison offset is in units of
+ * character-width, so we must divide the level (bytes)
+ * by operating character width (wchar_t or char). See
+ * longer comment above.
+ */
+ func = get_list_call_func(sl->level / wcfact);
+
+ sl->leaves = sl->tosort;
+ sl->leaves_num = sl->tosort_num;
+ sl->leaves_sz = sl->leaves_num;
+ sl->leaves = sort_realloc(sl->leaves,
+ (sizeof(struct sort_list_item *) *
+ (sl->leaves_sz)));
+ sl->tosort = NULL;
+ sl->tosort_num = 0;
+ sl->tosort_sz = 0;
+ sl->sln = 0;
+ sl->real_sln = 0;
+ if (sort_opts_vals.sflag) {
+ if (mergesort(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) func) == -1)
+ /* NOTREACHED */
+ err(2, "Radix sort error 3");
+ } else
+ DEFAULT_SORT_FUNC_RADIXSORT(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) func);
+
+ memcpy(sl->sorted + sl->start_position,
+ sl->leaves, sl->leaves_num *
+ sizeof(struct sort_list_item*));
+
+ sort_left_dec(sl->leaves_num);
+
+ goto end;
+ } else {
+ sl->tosort_sz = sl->tosort_num;
+ sl->tosort = sort_realloc(sl->tosort,
+ sizeof(struct sort_list_item*) * (sl->tosort_sz));
+ }
+ }
+
+ sl->sln = 256;
+ sl->sublevels = sort_calloc(1, slsz);
+
+ sl->real_sln = 0;
+
+ tosort_num = sl->tosort_num;
+ for (i = 0; i < tosort_num; ++i)
+ place_item(sl, i);
+
+ sort_free(sl->tosort);
+ sl->tosort = NULL;
+ sl->tosort_num = 0;
+ sl->tosort_sz = 0;
+
+ if (sl->leaves_num > 1) {
+ if (keys_num > 1) {
+ if (sort_opts_vals.sflag) {
+ mergesort(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+ } else {
+ DEFAULT_SORT_FUNC_RADIXSORT(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+ }
+ } else if (!sort_opts_vals.sflag && sort_opts_vals.complex_sort) {
+ DEFAULT_SORT_FUNC_RADIXSORT(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll_by_str_only);
+ }
+ }
+
+ sl->leaves_sz = sl->leaves_num;
+ sl->leaves = sort_realloc(sl->leaves, (sizeof(struct sort_list_item *) *
+ (sl->leaves_sz)));
+
+ if (!reverse_sort) {
+ memcpy(sl->sorted + sl->start_position, sl->leaves,
+ sl->leaves_num * sizeof(struct sort_list_item*));
+ sl->start_position += sl->leaves_num;
+ sort_left_dec(sl->leaves_num);
+
+ sort_free(sl->leaves);
+ sl->leaves = NULL;
+ sl->leaves_num = 0;
+ sl->leaves_sz = 0;
+
+ sln = sl->sln;
+
+ for (i = 0; i < sln; ++i) {
+ slc = sl->sublevels[i];
+
+ if (slc) {
+ slc->sorted = sl->sorted;
+ slc->start_position = sl->start_position;
+ sl->start_position += slc->tosort_num;
+ if (SMALL_NODE(slc))
+ run_sort_level_next(slc);
+ else
+ push_ls(slc);
+ sl->sublevels[i] = NULL;
+ }
+ }
+
+ } else {
+ size_t n;
+
+ sln = sl->sln;
+
+ for (i = 0; i < sln; ++i) {
+ n = sln - i - 1;
+ slc = sl->sublevels[n];
+
+ if (slc) {
+ slc->sorted = sl->sorted;
+ slc->start_position = sl->start_position;
+ sl->start_position += slc->tosort_num;
+ if (SMALL_NODE(slc))
+ run_sort_level_next(slc);
+ else
+ push_ls(slc);
+ sl->sublevels[n] = NULL;
+ }
+ }
+
+ memcpy(sl->sorted + sl->start_position, sl->leaves,
+ sl->leaves_num * sizeof(struct sort_list_item*));
+ sort_left_dec(sl->leaves_num);
+ }
+
+end:
+ free_sort_level(sl);
+}
+
+/*
+ * Single-threaded sort cycle
+ */
+static void
+run_sort_cycle_st(void)
+{
+ struct sort_level *slc;
+
+ for (;;) {
+ slc = pop_ls_st();
+ if (slc == NULL) {
+ break;
+ }
+ run_sort_level_next(slc);
+ }
+}
+
+#if defined(SORT_THREADS)
+
+/*
+ * Multi-threaded sort cycle
+ */
+static void
+run_sort_cycle_mt(void)
+{
+ struct sort_level *slc;
+
+ for (;;) {
+ slc = pop_ls_mt();
+ if (slc == NULL)
+ break;
+ run_sort_level_next(slc);
+ }
+}
+
+/*
+ * Sort cycle thread (in multi-threaded mode)
+ */
+static void*
+sort_thread(void* arg)
+{
+ run_sort_cycle_mt();
+ sem_post(&mtsem);
+
+ return (arg);
+}
+
+#endif /* defined(SORT_THREADS) */
+
+static void
+run_top_sort_level(struct sort_level *sl)
+{
+ struct sort_level *slc;
+
+ reverse_sort = sort_opts_vals.kflag ? keys[0].sm.rflag :
+ default_sort_mods->rflag;
+
+ sl->start_position = 0;
+ sl->sln = 256;
+ sl->sublevels = sort_calloc(1, slsz);
+
+ for (size_t i = 0; i < sl->tosort_num; ++i)
+ place_item(sl, i);
+
+ if (sl->leaves_num > 1) {
+ if (keys_num > 1) {
+ if (sort_opts_vals.sflag) {
+ mergesort(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+ } else {
+ DEFAULT_SORT_FUNC_RADIXSORT(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll);
+ }
+ } else if (!sort_opts_vals.sflag && sort_opts_vals.complex_sort) {
+ DEFAULT_SORT_FUNC_RADIXSORT(sl->leaves, sl->leaves_num,
+ sizeof(struct sort_list_item *),
+ (int(*)(const void *, const void *)) list_coll_by_str_only);
+ }
+ }
+
+ if (!reverse_sort) {
+ memcpy(sl->tosort + sl->start_position, sl->leaves,
+ sl->leaves_num * sizeof(struct sort_list_item*));
+ sl->start_position += sl->leaves_num;
+ sort_left_dec(sl->leaves_num);
+
+ for (size_t i = 0; i < sl->sln; ++i) {
+ slc = sl->sublevels[i];
+
+ if (slc) {
+ slc->sorted = sl->tosort;
+ slc->start_position = sl->start_position;
+ sl->start_position += slc->tosort_num;
+ push_ls(slc);
+ sl->sublevels[i] = NULL;
+ }
+ }
+
+ } else {
+ size_t n;
+
+ for (size_t i = 0; i < sl->sln; ++i) {
+
+ n = sl->sln - i - 1;
+ slc = sl->sublevels[n];
+
+ if (slc) {
+ slc->sorted = sl->tosort;
+ slc->start_position = sl->start_position;
+ sl->start_position += slc->tosort_num;
+ push_ls(slc);
+ sl->sublevels[n] = NULL;
+ }
+ }
+
+ memcpy(sl->tosort + sl->start_position, sl->leaves,
+ sl->leaves_num * sizeof(struct sort_list_item*));
+
+ sort_left_dec(sl->leaves_num);
+ }
+
+#if defined(SORT_THREADS)
+ if (nthreads < 2) {
+#endif
+ run_sort_cycle_st();
+#if defined(SORT_THREADS)
+ } else {
+ size_t i;
+
+ for(i = 0; i < nthreads; ++i) {
+ pthread_attr_t attr;
+ pthread_t pth;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_DETACHED);
+
+ for (;;) {
+ int res = pthread_create(&pth, &attr,
+ sort_thread, NULL);
+ if (res >= 0)
+ break;
+ if (errno == EAGAIN) {
+ pthread_yield();
+ continue;
+ }
+ err(2, NULL);
+ }
+
+ pthread_attr_destroy(&attr);
+ }
+
+ for (i = 0; i < nthreads; ++i)
+ sem_wait(&mtsem);
+ }
+#endif /* defined(SORT_THREADS) */
+}
+
+static void
+run_sort(struct sort_list_item **base, size_t nmemb)
+{
+ struct sort_level *sl;
+
+#if defined(SORT_THREADS)
+ size_t nthreads_save = nthreads;
+ if (nmemb < MT_SORT_THRESHOLD)
+ nthreads = 1;
+
+ if (nthreads > 1) {
+ pthread_mutexattr_t mattr;
+
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ADAPTIVE_NP);
+
+ pthread_mutex_init(&g_ls_mutex, &mattr);
+ pthread_cond_init(&g_ls_cond, NULL);
+
+ pthread_mutexattr_destroy(&mattr);
+
+ sem_init(&mtsem, 0, 0);
+
+ }
+#endif
+
+ sl = sort_calloc(1, sizeof(struct sort_level));
+
+ sl->tosort = base;
+ sl->tosort_num = nmemb;
+ sl->tosort_sz = nmemb;
+
+#if defined(SORT_THREADS)
+ sort_left = nmemb;
+#endif
+
+ run_top_sort_level(sl);
+
+ free_sort_level(sl);
+
+#if defined(SORT_THREADS)
+ if (nthreads > 1) {
+ sem_destroy(&mtsem);
+ pthread_mutex_destroy(&g_ls_mutex);
+ }
+ nthreads = nthreads_save;
+#endif
+}
+
+void
+rxsort(struct sort_list_item **base, size_t nmemb)
+{
+
+ run_sort(base, nmemb);
+}
diff --git a/usr.bin/sort/radixsort.h b/usr.bin/sort/radixsort.h
new file mode 100644
index 000000000000..4388cfc2951a
--- /dev/null
+++ b/usr.bin/sort/radixsort.h
@@ -0,0 +1,39 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * Copyright (C) 2012 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__SORT_RADIX_H__)
+#define __SORT_RADIX_H__
+
+#include "coll.h"
+#include "sort.h"
+
+void rxsort(struct sort_list_item **base, size_t nmemb);
+
+#endif /* __SORT_RADIX_H__ */
diff --git a/usr.bin/sort/sort.1.in b/usr.bin/sort/sort.1.in
new file mode 100644
index 000000000000..80cc1dcb0282
--- /dev/null
+++ b/usr.bin/sort/sort.1.in
@@ -0,0 +1,632 @@
+.\" $OpenBSD: sort.1,v 1.45 2015/03/19 13:51:10 jmc Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd November 30, 2023
+.Dt SORT 1
+.Os
+.Sh NAME
+.Nm sort
+.Nd sort or merge records (lines) of text and binary files
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl bcCdfghiRMmnrsuVz
+.Sm off
+.Op Fl k\ \& Ar field1 Op , Ar field2
+.Sm on
+.Op Fl S Ar memsize
+.Ek
+.Op Fl T Ar dir
+.Op Fl t Ar char
+.Op Fl o Ar output
+.Op Ar file ...
+.Nm
+.Fl Fl help
+.Nm
+.Fl Fl version
+.Sh DESCRIPTION
+The
+.Nm
+utility sorts text and binary files by lines.
+A line is a record separated from the subsequent record by a
+newline (default) or NUL \'\\0\' character (-z option).
+A record can contain any printable or unprintable characters.
+Comparisons are based on one or more sort keys extracted from
+each line of input, and are performed lexicographically,
+according to the current locale's collating rules and the
+specified command-line options that can tune the actual
+sorting behavior.
+By default, if keys are not given,
+.Nm
+uses entire lines for comparison.
+.Pp
+The command line options are as follows:
+.Bl -tag -width Ds
+.It Fl c , Fl Fl check , Fl C , Fl Fl check=silent|quiet
+Check that the single input file is sorted.
+If the file is not sorted,
+.Nm
+produces the appropriate error messages and exits with code 1,
+otherwise returns 0.
+If
+.Fl C
+or
+.Fl Fl check=silent
+is specified,
+.Nm
+produces no output.
+This is a "silent" version of
+.Fl c .
+.It Fl m , Fl Fl merge
+Merge only.
+The input files are assumed to be pre-sorted.
+If they are not sorted the output order is undefined.
+.It Fl o Ar output , Fl Fl output Ns = Ns Ar output
+Print the output to the
+.Ar output
+file instead of the standard output.
+.It Fl S Ar size , Fl Fl buffer-size Ns = Ns Ar size
+Use
+.Ar size
+for the maximum size of the memory buffer.
+Size modifiers %,b,K,M,G,T,P,E,Z,Y can be used.
+If a memory limit is not explicitly specified,
+.Nm
+takes up to about 90% of available memory.
+If the file size is too big to fit into the memory buffer,
+the temporary disk files are used to perform the sorting.
+.It Fl T Ar dir , Fl Fl temporary-directory Ns = Ns Ar dir
+Store temporary files in the directory
+.Ar dir .
+The default path is the value of the environment variable
+.Ev TMPDIR
+or
+.Pa /var/tmp
+if
+.Ev TMPDIR
+is not defined.
+.It Fl u , Fl Fl unique
+Unique keys.
+Suppress all lines that have a key that is equal to an already
+processed one.
+This option, similarly to
+.Fl s ,
+implies a stable sort.
+If used with
+.Fl c
+or
+.Fl C ,
+.Nm
+also checks that there are no lines with duplicate keys.
+.It Fl s
+Stable sort.
+This option maintains the original record order of records that have
+an equal key.
+This is a non-standard feature, but it is widely accepted and used.
+.It Fl Fl version
+Print the version and silently exits.
+.It Fl Fl help
+Print the help text and silently exits.
+.El
+.Pp
+The following options override the default ordering rules.
+When ordering options appear independently of key field
+specifications, they apply globally to all sort keys.
+When attached to a specific key (see
+.Fl k ) ,
+the ordering options override all global ordering options for
+the key they are attached to.
+.Bl -tag -width indent
+.It Fl b , Fl Fl ignore-leading-blanks
+Ignore leading blank characters when comparing lines.
+.It Fl d , Fl Fl dictionary-order
+Consider only blank spaces and alphanumeric characters in comparisons.
+.It Fl f , Fl Fl ignore-case
+Convert all lowercase characters to their uppercase equivalent
+before comparison, that is, perform case-independent sorting.
+.It Fl g , Fl Fl general-numeric-sort , Fl Fl sort=general-numeric
+Sort by general numerical value.
+As opposed to
+.Fl n ,
+this option handles general floating points.
+It has a more
+permissive format than that allowed by
+.Fl n
+but it has a significant performance drawback.
+.It Fl h , Fl Fl human-numeric-sort , Fl Fl sort=human-numeric
+Sort by numerical value, but take into account the SI suffix,
+if present.
+Sort first by numeric sign (negative, zero, or
+positive); then by SI suffix (either empty, or `k' or `K', or one
+of `MGTPEZY', in that order); and finally by numeric value.
+The SI suffix must immediately follow the number.
+For example, '12345K' sorts before '1M', because M is "larger" than K.
+This sort option is useful for sorting the output of a single invocation
+of 'df' command with
+.Fl h
+or
+.Fl H
+options (human-readable).
+.It Fl i , Fl Fl ignore-nonprinting
+Ignore all non-printable characters.
+.It Fl M , Fl Fl month-sort , Fl Fl sort=month
+Sort by month.
+Unknown strings are considered smaller than the month names.
+.It Fl n , Fl Fl numeric-sort , Fl Fl sort=numeric
+Sort fields numerically by arithmetic value.
+Fields are supposed to have optional blanks in the beginning, an
+optional minus sign, zero or more digits (including decimal point and
+possible thousand separators).
+.It Fl R , Fl Fl random-sort , Fl Fl sort=random
+Sort by a random order.
+This is a random permutation of the inputs except that
+the equal keys sort together.
+It is implemented by hashing the input keys and sorting
+the hash values.
+The hash function is chosen randomly.
+The hash function is randomized by
+.Cm /dev/random
+content, or by file content if it is specified by
+.Fl Fl random-source .
+Even if multiple sort fields are specified,
+the same random hash function is used for all of them.
+.It Fl r , Fl Fl reverse
+Sort in reverse order.
+.It Fl V , Fl Fl version-sort
+Sort version numbers.
+The input lines are treated as file names in form
+PREFIX VERSION SUFFIX, where SUFFIX matches the regular expression
+"(\.([A-Za-z~][A-Za-z0-9~]*)?)*".
+The files are compared by their prefixes and versions (leading
+zeros are ignored in version numbers, see example below).
+If an input string does not match the pattern, then it is compared
+using the byte compare function.
+All string comparisons are performed in C locale, the locale
+environment setting is ignored.
+.Bl -tag -width indent
+.It Example:
+.It $ ls sort* | sort -V
+.It sort-1.022.tgz
+.It sort-1.23.tgz
+.It sort-1.23.1.tgz
+.It sort-1.024.tgz
+.It sort-1.024.003.
+.It sort-1.024.003.tgz
+.It sort-1.024.07.tgz
+.It sort-1.024.009.tgz
+.El
+.El
+.Pp
+The treatment of field separators can be altered using these options:
+.Bl -tag -width indent
+.It Fl b , Fl Fl ignore-leading-blanks
+Ignore leading blank space when determining the start
+and end of a restricted sort key (see
+.Fl k ) .
+If
+.Fl b
+is specified before the first
+.Fl k
+option, it applies globally to all key specifications.
+Otherwise,
+.Fl b
+can be attached independently to each
+.Ar field
+argument of the key specifications.
+.Fl b .
+.It Xo
+.Fl k Ar field1 Ns Op , Ns Ar field2 ,
+.Fl Fl key Ns = Ns Ar field1 Ns Op , Ns Ar field2
+.Xc
+Define a restricted sort key that has the starting position
+.Ar field1 ,
+and optional ending position
+.Ar field2
+of a key field.
+The
+.Fl k
+option may be specified multiple times,
+in which case subsequent keys are compared when earlier keys compare equal.
+The
+.Fl k
+option replaces the obsolete options
+.Cm \(pl Ns Ar pos1
+and
+.Fl Ns Ar pos2 ,
+but the old notation is also supported.
+.It Fl t Ar char , Fl Fl field-separator Ns = Ns Ar char
+Use
+.Ar char
+as a field separator character.
+The initial
+.Ar char
+is not considered to be part of a field when determining key offsets.
+Each occurrence of
+.Ar char
+is significant (for example,
+.Dq Ar charchar
+delimits an empty field).
+If
+.Fl t
+is not specified, the default field separator is a sequence of
+blank space characters, and consecutive blank spaces do
+.Em not
+delimit an empty field, however, the initial blank space
+.Em is
+considered part of a field when determining key offsets.
+To use NUL as field separator, use
+.Fl t
+\'\\0\'.
+.It Fl z , Fl Fl zero-terminated
+Use NUL as record separator.
+By default, records in the files are supposed to be separated by
+the newline characters.
+With this option, NUL (\'\\0\') is used as a record separator character.
+.El
+.Pp
+Other options:
+.Bl -tag -width indent
+.It Fl Fl batch-size Ns = Ns Ar num
+Specify maximum number of files that can be opened by
+.Nm
+at once.
+This option affects behavior when having many input files or using
+temporary files.
+The default value is 16.
+.It Fl Fl compress-program Ns = Ns Ar PROGRAM
+Use PROGRAM to compress temporary files.
+PROGRAM must compress standard input to standard output, when called
+without arguments.
+When called with argument
+.Fl d
+it must decompress standard input to standard output.
+If PROGRAM fails,
+.Nm
+must exit with error.
+An example of PROGRAM that can be used here is bzip2.
+.It Fl Fl random-source Ns = Ns Ar filename
+In random sort, the file content is used as the source of the 'seed' data
+for the hash function choice.
+Two invocations of random sort with the same seed data will use
+the same hash function and will produce the same result if the input is
+also identical.
+By default, file
+.Cm /dev/random
+is used.
+.It Fl Fl debug
+Print some extra information about the sorting process to the
+standard output.
+%%THREADS%%.It Fl Fl parallel
+%%THREADS%%Set the maximum number of execution threads.
+%%THREADS%%Default number equals to the number of CPUs.
+.It Fl Fl files0-from Ns = Ns Ar filename
+Take the input file list from the file
+.Ar filename .
+The file names must be separated by NUL
+(like the output produced by the command "find ... -print0").
+.It Fl Fl radixsort
+Try to use radix sort, if the sort specifications allow.
+The radix sort can only be used for trivial locales (C and POSIX),
+and it cannot be used for numeric or month sort.
+Radix sort is very fast and stable.
+.It Fl Fl mergesort
+Use mergesort.
+This is a universal algorithm that can always be used,
+but it is not always the fastest.
+.It Fl Fl qsort
+Try to use quick sort, if the sort specifications allow.
+This sort algorithm cannot be used with
+.Fl u
+and
+.Fl s .
+.It Fl Fl heapsort
+Try to use heap sort, if the sort specifications allow.
+This sort algorithm cannot be used with
+.Fl u
+and
+.Fl s .
+.It Fl Fl mmap
+Try to use file memory mapping system call.
+It may increase speed in some cases.
+.El
+.Pp
+The following operands are available:
+.Bl -tag -width indent
+.It Ar file
+The pathname of a file to be sorted, merged, or checked.
+If no
+.Ar file
+operands are specified, or if a
+.Ar file
+operand is
+.Fl ,
+the standard input is used.
+.El
+.Pp
+A field is defined as a maximal sequence of characters other than the
+field separator and record separator (newline by default).
+Initial blank spaces are included in the field unless
+.Fl b
+has been specified;
+the first blank space of a sequence of blank spaces acts as the field
+separator and is included in the field (unless
+.Fl t
+is specified).
+For example, all blank spaces at the beginning of a line are
+considered to be part of the first field.
+.Pp
+Fields are specified by the
+.Sm off
+.Fl k\ \& Ar field1 Op , Ar field2
+.Sm on
+command-line option.
+If
+.Ar field2
+is missing, the end of the key defaults to the end of the line.
+.Pp
+The arguments
+.Ar field1
+and
+.Ar field2
+have the form
+.Em m.n
+.Em (m,n > 0)
+and can be followed by one or more of the modifiers
+.Cm b , d , f , i ,
+.Cm n , g , M
+and
+.Cm r ,
+which correspond to the options discussed above.
+When
+.Cm b
+is specified it applies only to
+.Ar field1
+or
+.Ar field2
+where it is specified while the rest of the modifiers
+apply to the whole key field regardless if they are
+specified only with
+.Ar field1
+or
+.Ar field2
+or both.
+A
+.Ar field1
+position specified by
+.Em m.n
+is interpreted as the
+.Em n Ns th
+character from the beginning of the
+.Em m Ns th
+field.
+A missing
+.Em \&.n
+in
+.Ar field1
+means
+.Ql \&.1 ,
+indicating the first character of the
+.Em m Ns th
+field; if the
+.Fl b
+option is in effect,
+.Em n
+is counted from the first non-blank character in the
+.Em m Ns th
+field;
+.Em m Ns \&.1b
+refers to the first non-blank character in the
+.Em m Ns th
+field.
+.No 1\&. Ns Em n
+refers to the
+.Em n Ns th
+character from the beginning of the line;
+if
+.Em n
+is greater than the length of the line, the field is taken to be empty.
+.Pp
+.Em n Ns th
+positions are always counted from the field beginning, even if the field
+is shorter than the number of specified positions.
+Thus, the key can really start from a position in a subsequent field.
+.Pp
+A
+.Ar field2
+position specified by
+.Em m.n
+is interpreted as the
+.Em n Ns th
+character (including separators) from the beginning of the
+.Em m Ns th
+field.
+A missing
+.Em \&.n
+indicates the last character of the
+.Em m Ns th
+field;
+.Em m
+= \&0
+designates the end of a line.
+Thus the option
+.Fl k Ar v.x,w.y
+is synonymous with the obsolete option
+.Cm \(pl Ns Ar v-\&1.x-\&1
+.Fl Ns Ar w-\&1.y ;
+when
+.Em y
+is omitted,
+.Fl k Ar v.x,w
+is synonymous with
+.Cm \(pl Ns Ar v-\&1.x-\&1
+.Fl Ns Ar w\&.0 .
+The obsolete
+.Cm \(pl Ns Ar pos1
+.Fl Ns Ar pos2
+option is still supported, except for
+.Fl Ns Ar w\&.0b ,
+which has no
+.Fl k
+equivalent.
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev LC_COLLATE
+Locale settings to be used to determine the collation for
+sorting records.
+.It Ev LC_CTYPE
+Locale settings to be used to case conversion and classification
+of characters, that is, which characters are considered
+whitespaces, etc.
+.It Ev LC_MESSAGES
+Locale settings that determine the language of output messages
+that
+.Nm
+prints out.
+.It Ev LC_NUMERIC
+Locale settings that determine the number format used in numeric sort.
+.It Ev LC_TIME
+Locale settings that determine the month format used in month sort.
+.It Ev LC_ALL
+Locale settings that override all of the above locale settings.
+This environment variable can be used to set all these settings
+to the same value at once.
+.It Ev LANG
+Used as a last resort to determine different kinds of locale-specific
+behavior if neither the respective environment variable, nor
+.Ev LC_ALL
+are set.
+.It Ev TMPDIR
+Path to the directory in which temporary files will be stored.
+Note that
+.Ev TMPDIR
+may be overridden by the
+.Fl T
+option.
+.It Ev GNUSORT_NUMERIC_COMPATIBILITY
+If defined
+.Fl t
+will not override the locale numeric symbols, that is, thousand
+separators and decimal separators.
+By default, if we specify
+.Fl t
+with the same symbol as the thousand separator or decimal point,
+the symbol will be treated as the field separator.
+Older behavior was less definite; the symbol was treated as both field
+separator and numeric separator, simultaneously.
+This environment variable enables the old behavior.
+.El
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /var/tmp/.bsdsort.PID.*
+Temporary files.
+.It Pa /dev/random
+Default seed file for the random sort.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility shall exit with one of the following values:
+.Pp
+.Bl -tag -width flag -compact
+.It 0
+Successfully sorted the input files or if used with
+.Fl c
+or
+.Fl C ,
+the input file already met the sorting criteria.
+.It 1
+On disorder (or non-uniqueness) with the
+.Fl c
+or
+.Fl C
+options.
+.It 2
+An error occurred.
+.El
+.Sh SEE ALSO
+.Xr comm 1 ,
+.Xr join 1 ,
+.Xr uniq 1
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl ghRMSsTVz
+are extensions to the POSIX specification.
+.Pp
+All long options are extensions to the specification, some of them are
+provided for compatibility with GNU versions and some of them are
+own extensions.
+.Pp
+The old key notations
+.Cm \(pl Ns Ar pos1
+and
+.Fl Ns Ar pos2
+come from older versions of
+.Nm
+and are still supported but their use is highly discouraged.
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.At v1 .
+.Sh AUTHORS
+.An Gabor Kovesdan Aq Mt gabor@FreeBSD.org ,
+.Pp
+.An Oleg Moskalenko Aq Mt mom040267@gmail.com
+.Sh NOTES
+This implementation of
+.Nm
+has no limits on input line length (other than imposed by available
+memory) or any restrictions on bytes allowed within lines.
+.Pp
+The performance depends highly on locale settings,
+efficient choice of sort keys and key complexity.
+The fastest sort is with locale C, on whole lines,
+with option
+.Fl s .
+In general, locale C is the fastest, then single-byte
+locales follow and multi-byte locales as the slowest but
+the correct collation order is always respected.
+As for the key specification, the simpler to process the
+lines the faster the search will be.
+.Pp
+When sorting by arithmetic value, using
+.Fl n
+results in much better performance than
+.Fl g
+so its use is encouraged
+whenever possible.
diff --git a/usr.bin/sort/sort.c b/usr.bin/sort/sort.c
new file mode 100644
index 000000000000..6e4023c43063
--- /dev/null
+++ b/usr.bin/sort/sort.c
@@ -0,0 +1,1331 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <locale.h>
+#include <md5.h>
+#include <regex.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "coll.h"
+#include "file.h"
+#include "sort.h"
+
+#define OPTIONS "bcCdfghik:Mmno:RrsS:t:T:uVz"
+
+static bool need_random;
+
+MD5_CTX md5_ctx;
+
+/*
+ * Default messages to use
+ */
+const char *nlsstr[] = { "",
+/* 1*/"mutually exclusive flags",
+/* 2*/"extra argument not allowed with -c",
+/* 3*/"Unknown feature",
+/* 4*/"Wrong memory buffer specification",
+/* 5*/"0 field in key specs",
+/* 6*/"0 column in key specs",
+/* 7*/"Wrong file mode",
+/* 8*/"Cannot open file for reading",
+/* 9*/"Radix sort cannot be used with these sort options",
+/*10*/"The chosen sort method cannot be used with stable and/or unique sort",
+/*11*/"Invalid key position",
+/*12*/"Usage: %s [-bcCdfigMmnrsuz] [-kPOS1[,POS2] ... ] "
+ "[+POS1 [-POS2]] [-S memsize] [-T tmpdir] [-t separator] "
+ "[-o outfile] [--batch-size size] [--files0-from file] "
+ "[--heapsort] [--mergesort] [--radixsort] [--qsort] "
+ "[--mmap] "
+#if defined(SORT_THREADS)
+ "[--parallel thread_no] "
+#endif
+ "[--human-numeric-sort] "
+ "[--version-sort] [--random-sort [--random-source file]] "
+ "[--compress-program program] [file ...]\n" };
+
+struct sort_opts sort_opts_vals;
+
+bool debug_sort;
+bool need_hint;
+
+size_t mb_cur_max;
+
+#if defined(SORT_THREADS)
+unsigned int ncpu = 1;
+size_t nthreads = 1;
+#endif
+
+static bool gnusort_numeric_compatibility;
+
+static struct sort_mods default_sort_mods_object;
+struct sort_mods * const default_sort_mods = &default_sort_mods_object;
+
+static bool print_symbols_on_debug;
+
+/*
+ * Arguments from file (when file0-from option is used:
+ */
+static size_t argc_from_file0 = (size_t)-1;
+static char **argv_from_file0;
+
+/*
+ * Placeholder symbols for options which have no single-character equivalent
+ */
+enum
+{
+ SORT_OPT = CHAR_MAX + 1,
+ HELP_OPT,
+ FF_OPT,
+ BS_OPT,
+ VERSION_OPT,
+ DEBUG_OPT,
+#if defined(SORT_THREADS)
+ PARALLEL_OPT,
+#endif
+ RANDOMSOURCE_OPT,
+ COMPRESSPROGRAM_OPT,
+ QSORT_OPT,
+ MERGESORT_OPT,
+ HEAPSORT_OPT,
+ RADIXSORT_OPT,
+ MMAP_OPT
+};
+
+#define NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS 6
+static const char mutually_exclusive_flags[NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS] = { 'M', 'n', 'g', 'R', 'h', 'V' };
+
+static struct option long_options[] = {
+ { "batch-size", required_argument, NULL, BS_OPT },
+ { "buffer-size", required_argument, NULL, 'S' },
+ { "check", optional_argument, NULL, 'c' },
+ { "check=silent|quiet", optional_argument, NULL, 'C' },
+ { "compress-program", required_argument, NULL, COMPRESSPROGRAM_OPT },
+ { "debug", no_argument, NULL, DEBUG_OPT },
+ { "dictionary-order", no_argument, NULL, 'd' },
+ { "field-separator", required_argument, NULL, 't' },
+ { "files0-from", required_argument, NULL, FF_OPT },
+ { "general-numeric-sort", no_argument, NULL, 'g' },
+ { "heapsort", no_argument, NULL, HEAPSORT_OPT },
+ { "help",no_argument, NULL, HELP_OPT },
+ { "human-numeric-sort", no_argument, NULL, 'h' },
+ { "ignore-leading-blanks", no_argument, NULL, 'b' },
+ { "ignore-case", no_argument, NULL, 'f' },
+ { "ignore-nonprinting", no_argument, NULL, 'i' },
+ { "key", required_argument, NULL, 'k' },
+ { "merge", no_argument, NULL, 'm' },
+ { "mergesort", no_argument, NULL, MERGESORT_OPT },
+ { "mmap", no_argument, NULL, MMAP_OPT },
+ { "month-sort", no_argument, NULL, 'M' },
+ { "numeric-sort", no_argument, NULL, 'n' },
+ { "output", required_argument, NULL, 'o' },
+#if defined(SORT_THREADS)
+ { "parallel", required_argument, NULL, PARALLEL_OPT },
+#endif
+ { "qsort", no_argument, NULL, QSORT_OPT },
+ { "radixsort", no_argument, NULL, RADIXSORT_OPT },
+ { "random-sort", no_argument, NULL, 'R' },
+ { "random-source", required_argument, NULL, RANDOMSOURCE_OPT },
+ { "reverse", no_argument, NULL, 'r' },
+ { "sort", required_argument, NULL, SORT_OPT },
+ { "stable", no_argument, NULL, 's' },
+ { "temporary-directory",required_argument, NULL, 'T' },
+ { "unique", no_argument, NULL, 'u' },
+ { "version", no_argument, NULL, VERSION_OPT },
+ { "version-sort",no_argument, NULL, 'V' },
+ { "zero-terminated", no_argument, NULL, 'z' },
+ { NULL, no_argument, NULL, 0 }
+};
+
+void fix_obsolete_keys(int *argc, char **argv);
+
+/*
+ * Check where sort modifier is present
+ */
+static bool
+sort_modifier_empty(struct sort_mods *sm)
+{
+
+ if (sm == NULL)
+ return (true);
+ return (!(sm->Mflag || sm->Vflag || sm->nflag || sm->gflag ||
+ sm->rflag || sm->Rflag || sm->hflag || sm->dflag || sm->fflag));
+}
+
+/*
+ * Print out usage text.
+ */
+static void
+usage(bool opt_err)
+{
+ FILE *out;
+
+ out = opt_err ? stderr : stdout;
+
+ fprintf(out, getstr(12), getprogname());
+ if (opt_err)
+ exit(2);
+ exit(0);
+}
+
+/*
+ * Read input file names from a file (file0-from option).
+ */
+static void
+read_fns_from_file0(const char *fn)
+{
+ FILE *f;
+ char *line = NULL;
+ size_t linesize = 0;
+ ssize_t linelen;
+
+ if (fn == NULL)
+ return;
+
+ f = fopen(fn, "r");
+ if (f == NULL)
+ err(2, "%s", fn);
+
+ while ((linelen = getdelim(&line, &linesize, '\0', f)) != -1) {
+ if (*line != '\0') {
+ if (argc_from_file0 == (size_t) - 1)
+ argc_from_file0 = 0;
+ ++argc_from_file0;
+ argv_from_file0 = sort_realloc(argv_from_file0,
+ argc_from_file0 * sizeof(char *));
+ if (argv_from_file0 == NULL)
+ err(2, NULL);
+ argv_from_file0[argc_from_file0 - 1] = line;
+ } else {
+ free(line);
+ }
+ line = NULL;
+ linesize = 0;
+ }
+ if (ferror(f))
+ err(2, "%s: getdelim", fn);
+
+ closefile(f, fn);
+}
+
+/*
+ * Check how much RAM is available for the sort.
+ */
+static void
+set_hw_params(void)
+{
+ long pages, psize;
+
+#if defined(SORT_THREADS)
+ ncpu = 1;
+#endif
+
+ pages = sysconf(_SC_PHYS_PAGES);
+ if (pages < 1) {
+ perror("sysconf pages");
+ pages = 1;
+ }
+ psize = sysconf(_SC_PAGESIZE);
+ if (psize < 1) {
+ perror("sysconf psize");
+ psize = 4096;
+ }
+#if defined(SORT_THREADS)
+ ncpu = (unsigned int)sysconf(_SC_NPROCESSORS_ONLN);
+ if (ncpu < 1)
+ ncpu = 1;
+ else if(ncpu > 32)
+ ncpu = 32;
+
+ nthreads = ncpu;
+#endif
+
+ free_memory = (unsigned long long) pages * (unsigned long long) psize;
+ available_free_memory = free_memory / 2;
+
+ if (available_free_memory < 1024)
+ available_free_memory = 1024;
+}
+
+/*
+ * Convert "plain" symbol to wide symbol, with default value.
+ */
+static void
+conv_mbtowc(wchar_t *wc, const char *c, const wchar_t def)
+{
+
+ if (wc && c) {
+ int res;
+
+ res = mbtowc(wc, c, mb_cur_max);
+ if (res < 1)
+ *wc = def;
+ }
+}
+
+/*
+ * Set current locale symbols.
+ */
+static void
+set_locale(void)
+{
+ struct lconv *lc;
+ const char *locale;
+
+ setlocale(LC_ALL, "");
+
+ mb_cur_max = MB_CUR_MAX;
+
+ lc = localeconv();
+
+ if (lc) {
+ /* obtain LC_NUMERIC info */
+ /* Convert to wide char form */
+ conv_mbtowc(&symbol_decimal_point, lc->decimal_point,
+ symbol_decimal_point);
+ conv_mbtowc(&symbol_thousands_sep, lc->thousands_sep,
+ symbol_thousands_sep);
+ conv_mbtowc(&symbol_positive_sign, lc->positive_sign,
+ symbol_positive_sign);
+ conv_mbtowc(&symbol_negative_sign, lc->negative_sign,
+ symbol_negative_sign);
+ }
+
+ if (getenv("GNUSORT_NUMERIC_COMPATIBILITY"))
+ gnusort_numeric_compatibility = true;
+
+ locale = setlocale(LC_COLLATE, NULL);
+
+ if (locale) {
+ char *tmpl;
+ const char *cclocale;
+
+ tmpl = sort_strdup(locale);
+ cclocale = setlocale(LC_COLLATE, "C");
+ if (cclocale && !strcmp(cclocale, tmpl))
+ byte_sort = true;
+ else {
+ const char *pclocale;
+
+ pclocale = setlocale(LC_COLLATE, "POSIX");
+ if (pclocale && !strcmp(pclocale, tmpl))
+ byte_sort = true;
+ }
+ setlocale(LC_COLLATE, tmpl);
+ sort_free(tmpl);
+ }
+}
+
+/*
+ * Set directory temporary files.
+ */
+static void
+set_tmpdir(void)
+{
+ char *td;
+
+ td = getenv("TMPDIR");
+ if (td != NULL)
+ tmpdir = sort_strdup(td);
+}
+
+/*
+ * Parse -S option.
+ */
+static unsigned long long
+parse_memory_buffer_value(const char *value)
+{
+
+ if (value == NULL)
+ return (available_free_memory);
+ else {
+ char *endptr;
+ unsigned long long membuf;
+
+ endptr = NULL;
+ errno = 0;
+ membuf = strtoll(value, &endptr, 10);
+
+ if (errno != 0) {
+ warn("%s",getstr(4));
+ membuf = available_free_memory;
+ } else {
+ switch (*endptr){
+ case 'Y':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'Z':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'E':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'P':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'T':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'G':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'M':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case '\0':
+ case 'K':
+ membuf *= 1024;
+ /* FALLTHROUGH */
+ case 'b':
+ break;
+ case '%':
+ membuf = (available_free_memory * membuf) /
+ 100;
+ break;
+ default:
+ warnc(EINVAL, "%s", optarg);
+ membuf = available_free_memory;
+ }
+ }
+ return (membuf);
+ }
+}
+
+/*
+ * Signal handler that clears the temporary files.
+ */
+static void
+sig_handler(int sig __unused, siginfo_t *siginfo __unused,
+ void *context __unused)
+{
+
+ clear_tmp_files();
+ exit(-1);
+}
+
+/*
+ * Set signal handler on panic signals.
+ */
+static void
+set_signal_handler(void)
+{
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = &sig_handler;
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction(SIGTERM, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGHUP, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGINT, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGQUIT, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGABRT, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGBUS, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+ if (sigaction(SIGUSR2, &sa, NULL) < 0) {
+ perror("sigaction");
+ return;
+ }
+}
+
+/*
+ * Print "unknown" message and exit with status 2.
+ */
+static void
+unknown(const char *what)
+{
+
+ errx(2, "%s: %s", getstr(3), what);
+}
+
+/*
+ * Check whether contradictory input options are used.
+ */
+static void
+check_mutually_exclusive_flags(char c, bool *mef_flags)
+{
+ int fo_index, mec;
+ bool found_others, found_this;
+
+ found_others = found_this = false;
+ fo_index = 0;
+
+ for (int i = 0; i < NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS; i++) {
+ mec = mutually_exclusive_flags[i];
+
+ if (mec != c) {
+ if (mef_flags[i]) {
+ if (found_this)
+ errx(1, "%c:%c: %s", c, mec, getstr(1));
+ found_others = true;
+ fo_index = i;
+ }
+ } else {
+ if (found_others)
+ errx(1, "%c:%c: %s", c, mutually_exclusive_flags[fo_index], getstr(1));
+ mef_flags[i] = true;
+ found_this = true;
+ }
+ }
+}
+
+/*
+ * Initialise sort opts data.
+ */
+static void
+set_sort_opts(void)
+{
+
+ memset(&default_sort_mods_object, 0,
+ sizeof(default_sort_mods_object));
+ memset(&sort_opts_vals, 0, sizeof(sort_opts_vals));
+ default_sort_mods_object.func =
+ get_sort_func(&default_sort_mods_object);
+}
+
+/*
+ * Set a sort modifier on a sort modifiers object.
+ */
+static bool
+set_sort_modifier(struct sort_mods *sm, int c)
+{
+
+ if (sm == NULL)
+ return (true);
+
+ switch (c){
+ case 'b':
+ sm->bflag = true;
+ break;
+ case 'd':
+ sm->dflag = true;
+ break;
+ case 'f':
+ sm->fflag = true;
+ break;
+ case 'g':
+ sm->gflag = true;
+ need_hint = true;
+ break;
+ case 'i':
+ sm->iflag = true;
+ break;
+ case 'R':
+ sm->Rflag = true;
+ need_hint = true;
+ need_random = true;
+ break;
+ case 'M':
+ initialise_months();
+ sm->Mflag = true;
+ need_hint = true;
+ break;
+ case 'n':
+ sm->nflag = true;
+ need_hint = true;
+ print_symbols_on_debug = true;
+ break;
+ case 'r':
+ sm->rflag = true;
+ break;
+ case 'V':
+ sm->Vflag = true;
+ break;
+ case 'h':
+ sm->hflag = true;
+ need_hint = true;
+ print_symbols_on_debug = true;
+ break;
+ default:
+ return (false);
+ }
+
+ sort_opts_vals.complex_sort = true;
+ sm->func = get_sort_func(sm);
+ return (true);
+}
+
+/*
+ * Parse POS in -k option.
+ */
+static int
+parse_pos(const char *s, struct key_specs *ks, bool *mef_flags, bool second)
+{
+ regmatch_t pmatch[4];
+ regex_t re;
+ char *c, *f;
+ const char *sregexp = "^([0-9]+)(\\.[0-9]+)?([bdfirMngRhV]+)?$";
+ size_t len, nmatch;
+ int ret;
+
+ ret = -1;
+ nmatch = 4;
+ c = f = NULL;
+
+ if (regcomp(&re, sregexp, REG_EXTENDED) != 0)
+ return (-1);
+
+ if (regexec(&re, s, nmatch, pmatch, 0) != 0)
+ goto end;
+
+ if (pmatch[0].rm_eo <= pmatch[0].rm_so)
+ goto end;
+
+ if (pmatch[1].rm_eo <= pmatch[1].rm_so)
+ goto end;
+
+ len = pmatch[1].rm_eo - pmatch[1].rm_so;
+ f = sort_malloc((len + 1) * sizeof(char));
+
+ strncpy(f, s + pmatch[1].rm_so, len);
+ f[len] = '\0';
+
+ if (second) {
+ errno = 0;
+ ks->f2 = (size_t) strtoul(f, NULL, 10);
+ if (errno != 0)
+ err(2, "-k");
+ if (ks->f2 == 0) {
+ warn("%s",getstr(5));
+ goto end;
+ }
+ } else {
+ errno = 0;
+ ks->f1 = (size_t) strtoul(f, NULL, 10);
+ if (errno != 0)
+ err(2, "-k");
+ if (ks->f1 == 0) {
+ warn("%s",getstr(5));
+ goto end;
+ }
+ }
+
+ if (pmatch[2].rm_eo > pmatch[2].rm_so) {
+ len = pmatch[2].rm_eo - pmatch[2].rm_so - 1;
+ c = sort_malloc((len + 1) * sizeof(char));
+
+ strncpy(c, s + pmatch[2].rm_so + 1, len);
+ c[len] = '\0';
+
+ if (second) {
+ errno = 0;
+ ks->c2 = (size_t) strtoul(c, NULL, 10);
+ if (errno != 0)
+ err(2, "-k");
+ } else {
+ errno = 0;
+ ks->c1 = (size_t) strtoul(c, NULL, 10);
+ if (errno != 0)
+ err(2, "-k");
+ if (ks->c1 == 0) {
+ warn("%s",getstr(6));
+ goto end;
+ }
+ }
+ } else {
+ if (second)
+ ks->c2 = 0;
+ else
+ ks->c1 = 1;
+ }
+
+ if (pmatch[3].rm_eo > pmatch[3].rm_so) {
+ regoff_t i = 0;
+
+ for (i = pmatch[3].rm_so; i < pmatch[3].rm_eo; i++) {
+ check_mutually_exclusive_flags(s[i], mef_flags);
+ if (s[i] == 'b') {
+ if (second)
+ ks->pos2b = true;
+ else
+ ks->pos1b = true;
+ } else if (!set_sort_modifier(&(ks->sm), s[i]))
+ goto end;
+ }
+ }
+
+ ret = 0;
+
+end:
+
+ if (c)
+ sort_free(c);
+ if (f)
+ sort_free(f);
+ regfree(&re);
+
+ return (ret);
+}
+
+/*
+ * Parse -k option value.
+ */
+static int
+parse_k(const char *s, struct key_specs *ks)
+{
+ int ret = -1;
+ bool mef_flags[NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS] =
+ { false, false, false, false, false, false };
+
+ if (s && *s) {
+ char *sptr;
+
+ sptr = strchr(s, ',');
+ if (sptr) {
+ size_t size1;
+ char *pos1, *pos2;
+
+ size1 = sptr - s;
+
+ if (size1 < 1)
+ return (-1);
+ pos1 = sort_malloc((size1 + 1) * sizeof(char));
+
+ strncpy(pos1, s, size1);
+ pos1[size1] = '\0';
+
+ ret = parse_pos(pos1, ks, mef_flags, false);
+
+ sort_free(pos1);
+ if (ret < 0)
+ return (ret);
+
+ pos2 = sort_strdup(sptr + 1);
+ ret = parse_pos(pos2, ks, mef_flags, true);
+ sort_free(pos2);
+ } else
+ ret = parse_pos(s, ks, mef_flags, false);
+ }
+
+ return (ret);
+}
+
+/*
+ * Parse POS in +POS -POS option.
+ */
+static int
+parse_pos_obs(const char *s, int *nf, int *nc, char* sopts)
+{
+ regex_t re;
+ regmatch_t pmatch[4];
+ char *c, *f;
+ const char *sregexp = "^([0-9]+)(\\.[0-9]+)?([A-Za-z]+)?$";
+ int ret;
+ size_t len, nmatch;
+
+ ret = -1;
+ nmatch = 4;
+ c = f = NULL;
+ *nc = *nf = 0;
+
+ if (regcomp(&re, sregexp, REG_EXTENDED) != 0)
+ return (-1);
+
+ if (regexec(&re, s, nmatch, pmatch, 0) != 0)
+ goto end;
+
+ if (pmatch[0].rm_eo <= pmatch[0].rm_so)
+ goto end;
+
+ if (pmatch[1].rm_eo <= pmatch[1].rm_so)
+ goto end;
+
+ len = pmatch[1].rm_eo - pmatch[1].rm_so;
+ f = sort_malloc((len + 1) * sizeof(char));
+
+ strncpy(f, s + pmatch[1].rm_so, len);
+ f[len] = '\0';
+
+ errno = 0;
+ *nf = (size_t) strtoul(f, NULL, 10);
+ if (errno != 0)
+ errx(2, "%s", getstr(11));
+
+ if (pmatch[2].rm_eo > pmatch[2].rm_so) {
+ len = pmatch[2].rm_eo - pmatch[2].rm_so - 1;
+ c = sort_malloc((len + 1) * sizeof(char));
+
+ strncpy(c, s + pmatch[2].rm_so + 1, len);
+ c[len] = '\0';
+
+ errno = 0;
+ *nc = (size_t) strtoul(c, NULL, 10);
+ if (errno != 0)
+ errx(2, "%s", getstr(11));
+ }
+
+ if (pmatch[3].rm_eo > pmatch[3].rm_so) {
+
+ len = pmatch[3].rm_eo - pmatch[3].rm_so;
+
+ strncpy(sopts, s + pmatch[3].rm_so, len);
+ sopts[len] = '\0';
+ }
+
+ ret = 0;
+
+end:
+ if (c)
+ sort_free(c);
+ if (f)
+ sort_free(f);
+ regfree(&re);
+
+ return (ret);
+}
+
+/*
+ * "Translate" obsolete +POS1 -POS2 syntax into new -kPOS1,POS2 syntax
+ */
+void
+fix_obsolete_keys(int *argc, char **argv)
+{
+ char sopt[129];
+
+ for (int i = 1; i < *argc; i++) {
+ char *arg1;
+
+ arg1 = argv[i];
+
+ if (strcmp(arg1, "--") == 0) {
+ /* Following arguments are treated as filenames. */
+ break;
+ }
+
+ if (strlen(arg1) > 1 && arg1[0] == '+') {
+ int c1, f1;
+ char sopts1[128];
+
+ sopts1[0] = 0;
+ c1 = f1 = 0;
+
+ if (parse_pos_obs(arg1 + 1, &f1, &c1, sopts1) < 0)
+ continue;
+ else {
+ f1 += 1;
+ c1 += 1;
+ if (i + 1 < *argc) {
+ char *arg2 = argv[i + 1];
+
+ if (strlen(arg2) > 1 &&
+ arg2[0] == '-') {
+ int c2, f2;
+ char sopts2[128];
+
+ sopts2[0] = 0;
+ c2 = f2 = 0;
+
+ if (parse_pos_obs(arg2 + 1,
+ &f2, &c2, sopts2) >= 0) {
+ if (c2 > 0)
+ f2 += 1;
+ sprintf(sopt, "-k%d.%d%s,%d.%d%s",
+ f1, c1, sopts1, f2, c2, sopts2);
+ argv[i] = sort_strdup(sopt);
+ for (int j = i + 1; j + 1 < *argc; j++)
+ argv[j] = argv[j + 1];
+ *argc -= 1;
+ continue;
+ }
+ }
+ }
+ sprintf(sopt, "-k%d.%d%s", f1, c1, sopts1);
+ argv[i] = sort_strdup(sopt);
+ }
+ }
+ }
+}
+
+/*
+ * Seed random sort
+ */
+static void
+get_random_seed(const char *random_source)
+{
+ char randseed[32];
+ struct stat fsb, rsb;
+ ssize_t rd;
+ int rsfd;
+
+ rsfd = -1;
+ rd = sizeof(randseed);
+
+ if (random_source == NULL) {
+ if (getentropy(randseed, sizeof(randseed)) < 0)
+ err(EX_SOFTWARE, "getentropy");
+ goto out;
+ }
+
+ rsfd = open(random_source, O_RDONLY | O_CLOEXEC);
+ if (rsfd < 0)
+ err(EX_NOINPUT, "open: %s", random_source);
+
+ if (fstat(rsfd, &fsb) != 0)
+ err(EX_SOFTWARE, "fstat");
+
+ if (!S_ISREG(fsb.st_mode) && !S_ISCHR(fsb.st_mode))
+ err(EX_USAGE,
+ "random seed isn't a regular file or /dev/random");
+
+ /*
+ * Regular files: read up to maximum seed size and explicitly
+ * reject longer files.
+ */
+ if (S_ISREG(fsb.st_mode)) {
+ if (fsb.st_size > (off_t)sizeof(randseed))
+ errx(EX_USAGE, "random seed is too large (%jd >"
+ " %zu)!", (intmax_t)fsb.st_size,
+ sizeof(randseed));
+ else if (fsb.st_size < 1)
+ errx(EX_USAGE, "random seed is too small ("
+ "0 bytes)");
+
+ memset(randseed, 0, sizeof(randseed));
+
+ rd = read(rsfd, randseed, fsb.st_size);
+ if (rd < 0)
+ err(EX_SOFTWARE, "reading random seed file %s",
+ random_source);
+ if (rd < (ssize_t)fsb.st_size)
+ errx(EX_SOFTWARE, "short read from %s", random_source);
+ } else if (S_ISCHR(fsb.st_mode)) {
+ if (stat("/dev/random", &rsb) < 0)
+ err(EX_SOFTWARE, "stat");
+
+ if (fsb.st_dev != rsb.st_dev ||
+ fsb.st_ino != rsb.st_ino)
+ errx(EX_USAGE, "random seed is a character "
+ "device other than /dev/random");
+
+ if (getentropy(randseed, sizeof(randseed)) < 0)
+ err(EX_SOFTWARE, "getentropy");
+ }
+
+out:
+ if (rsfd >= 0)
+ close(rsfd);
+
+ MD5Init(&md5_ctx);
+ MD5Update(&md5_ctx, randseed, rd);
+}
+
+/*
+ * Main function.
+ */
+int
+main(int argc, char **argv)
+{
+ char *outfile, *real_outfile;
+ char *random_source = NULL;
+ int c, result;
+ bool mef_flags[NUMBER_OF_MUTUALLY_EXCLUSIVE_FLAGS] =
+ { false, false, false, false, false, false };
+
+ result = 0;
+ outfile = sort_strdup("-");
+ real_outfile = NULL;
+
+ struct sort_mods *sm = &default_sort_mods_object;
+
+ init_tmp_files();
+
+ set_signal_handler();
+
+ set_hw_params();
+ set_locale();
+ set_tmpdir();
+ set_sort_opts();
+
+ fix_obsolete_keys(&argc, argv);
+
+ while (((c = getopt_long(argc, argv, OPTIONS, long_options, NULL))
+ != -1)) {
+
+ check_mutually_exclusive_flags(c, mef_flags);
+
+ if (!set_sort_modifier(sm, c)) {
+
+ switch (c) {
+ case 'c':
+ sort_opts_vals.cflag = true;
+ if (optarg) {
+ if (!strcmp(optarg, "diagnose-first"))
+ ;
+ else if (!strcmp(optarg, "silent") ||
+ !strcmp(optarg, "quiet"))
+ sort_opts_vals.csilentflag = true;
+ else if (*optarg)
+ unknown(optarg);
+ }
+ break;
+ case 'C':
+ sort_opts_vals.cflag = true;
+ sort_opts_vals.csilentflag = true;
+ break;
+ case 'k':
+ {
+ sort_opts_vals.complex_sort = true;
+ sort_opts_vals.kflag = true;
+
+ keys_num++;
+ keys = sort_realloc(keys, keys_num *
+ sizeof(struct key_specs));
+ memset(&(keys[keys_num - 1]), 0,
+ sizeof(struct key_specs));
+
+ if (parse_k(optarg, &(keys[keys_num - 1]))
+ < 0) {
+ errc(2, EINVAL, "-k %s", optarg);
+ }
+
+ break;
+ }
+ case 'm':
+ sort_opts_vals.mflag = true;
+ break;
+ case 'o':
+ outfile = sort_realloc(outfile, (strlen(optarg) + 1));
+ strcpy(outfile, optarg);
+ break;
+ case 's':
+ sort_opts_vals.sflag = true;
+ break;
+ case 'S':
+ available_free_memory =
+ parse_memory_buffer_value(optarg);
+ break;
+ case 'T':
+ tmpdir = sort_strdup(optarg);
+ break;
+ case 't':
+ while (strlen(optarg) > 1) {
+ if (optarg[0] != '\\') {
+ errc(2, EINVAL, "%s", optarg);
+ }
+ optarg += 1;
+ if (*optarg == '0') {
+ *optarg = 0;
+ break;
+ }
+ }
+ sort_opts_vals.tflag = true;
+ sort_opts_vals.field_sep = btowc(optarg[0]);
+ if (sort_opts_vals.field_sep == WEOF) {
+ errno = EINVAL;
+ err(2, NULL);
+ }
+ if (!gnusort_numeric_compatibility) {
+ if (symbol_decimal_point == sort_opts_vals.field_sep)
+ symbol_decimal_point = WEOF;
+ if (symbol_thousands_sep == sort_opts_vals.field_sep)
+ symbol_thousands_sep = WEOF;
+ if (symbol_negative_sign == sort_opts_vals.field_sep)
+ symbol_negative_sign = WEOF;
+ if (symbol_positive_sign == sort_opts_vals.field_sep)
+ symbol_positive_sign = WEOF;
+ }
+ break;
+ case 'u':
+ sort_opts_vals.uflag = true;
+ /* stable sort for the correct unique val */
+ sort_opts_vals.sflag = true;
+ break;
+ case 'z':
+ sort_opts_vals.zflag = true;
+ break;
+ case SORT_OPT:
+ if (optarg) {
+ if (!strcmp(optarg, "general-numeric"))
+ set_sort_modifier(sm, 'g');
+ else if (!strcmp(optarg, "human-numeric"))
+ set_sort_modifier(sm, 'h');
+ else if (!strcmp(optarg, "numeric"))
+ set_sort_modifier(sm, 'n');
+ else if (!strcmp(optarg, "month"))
+ set_sort_modifier(sm, 'M');
+ else if (!strcmp(optarg, "random"))
+ set_sort_modifier(sm, 'R');
+ else
+ unknown(optarg);
+ }
+ break;
+#if defined(SORT_THREADS)
+ case PARALLEL_OPT:
+ nthreads = (size_t)(atoi(optarg));
+ if (nthreads < 1)
+ nthreads = 1;
+ if (nthreads > 1024)
+ nthreads = 1024;
+ break;
+#endif
+ case QSORT_OPT:
+ sort_opts_vals.sort_method = SORT_QSORT;
+ break;
+ case MERGESORT_OPT:
+ sort_opts_vals.sort_method = SORT_MERGESORT;
+ break;
+ case MMAP_OPT:
+ use_mmap = true;
+ break;
+ case HEAPSORT_OPT:
+ sort_opts_vals.sort_method = SORT_HEAPSORT;
+ break;
+ case RADIXSORT_OPT:
+ sort_opts_vals.sort_method = SORT_RADIXSORT;
+ break;
+ case RANDOMSOURCE_OPT:
+ random_source = strdup(optarg);
+ break;
+ case COMPRESSPROGRAM_OPT:
+ compress_program = strdup(optarg);
+ break;
+ case FF_OPT:
+ read_fns_from_file0(optarg);
+ break;
+ case BS_OPT:
+ {
+ errno = 0;
+ long mof = strtol(optarg, NULL, 10);
+ if (errno != 0)
+ err(2, "--batch-size");
+ if (mof >= 2)
+ max_open_files = (size_t) mof + 1;
+ }
+ break;
+ case VERSION_OPT:
+ printf("%s\n", VERSION);
+ exit(EXIT_SUCCESS);
+ /* NOTREACHED */
+ break;
+ case DEBUG_OPT:
+ debug_sort = true;
+ break;
+ case HELP_OPT:
+ usage(false);
+ /* NOTREACHED */
+ break;
+ default:
+ usage(true);
+ /* NOTREACHED */
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argv_from_file0) {
+ argc = argc_from_file0;
+ argv = argv_from_file0;
+ }
+
+ if (sort_opts_vals.cflag && sort_opts_vals.mflag)
+ errx(1, "%c:%c: %s", 'm', 'c', getstr(1));
+
+ if (keys_num == 0) {
+ keys_num = 1;
+ keys = sort_realloc(keys, sizeof(struct key_specs));
+ memset(&(keys[0]), 0, sizeof(struct key_specs));
+ keys[0].c1 = 1;
+ keys[0].pos1b = default_sort_mods->bflag;
+ keys[0].pos2b = default_sort_mods->bflag;
+ memcpy(&(keys[0].sm), default_sort_mods,
+ sizeof(struct sort_mods));
+ }
+
+ for (size_t i = 0; i < keys_num; i++) {
+ struct key_specs *ks;
+
+ ks = &(keys[i]);
+
+ if (sort_modifier_empty(&(ks->sm)) && !(ks->pos1b) &&
+ !(ks->pos2b)) {
+ ks->pos1b = sm->bflag;
+ ks->pos2b = sm->bflag;
+ memcpy(&(ks->sm), sm, sizeof(struct sort_mods));
+ }
+
+ ks->sm.func = get_sort_func(&(ks->sm));
+ }
+
+ if (debug_sort) {
+ printf("Memory to be used for sorting: %llu\n",available_free_memory);
+#if defined(SORT_THREADS)
+ printf("Number of CPUs: %d\n",(int)ncpu);
+ nthreads = 1;
+#endif
+ printf("Using collate rules of %s locale\n",
+ setlocale(LC_COLLATE, NULL));
+ if (byte_sort)
+ printf("Byte sort is used\n");
+ if (print_symbols_on_debug) {
+ printf("Decimal Point: <%lc>\n", symbol_decimal_point);
+ if (symbol_thousands_sep)
+ printf("Thousands separator: <%lc>\n",
+ symbol_thousands_sep);
+ printf("Positive sign: <%lc>\n", symbol_positive_sign);
+ printf("Negative sign: <%lc>\n", symbol_negative_sign);
+ }
+ }
+
+ if (need_random)
+ get_random_seed(random_source);
+
+ /* Case when the outfile equals one of the input files: */
+ if (strcmp(outfile, "-")) {
+
+ for(int i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], outfile) == 0) {
+ real_outfile = sort_strdup(outfile);
+ for(;;) {
+ char* tmp = sort_malloc(strlen(outfile) +
+ strlen(".tmp") + 1);
+
+ strcpy(tmp, outfile);
+ strcpy(tmp + strlen(tmp), ".tmp");
+ sort_free(outfile);
+ outfile = tmp;
+ if (access(outfile, F_OK) < 0)
+ break;
+ }
+ tmp_file_atexit(outfile);
+ }
+ }
+ }
+
+#if defined(SORT_THREADS)
+ if ((argc < 1) || (strcmp(outfile, "-") == 0) || (*outfile == 0))
+ nthreads = 1;
+#endif
+
+ if (!sort_opts_vals.cflag && !sort_opts_vals.mflag) {
+ struct file_list fl;
+ struct sort_list list;
+
+ sort_list_init(&list);
+ file_list_init(&fl, true);
+
+ if (argc < 1)
+ procfile("-", &list, &fl);
+ else {
+ while (argc > 0) {
+ procfile(*argv, &list, &fl);
+ --argc;
+ ++argv;
+ }
+ }
+
+ if (fl.count < 1)
+ sort_list_to_file(&list, outfile);
+ else {
+ if (list.count > 0) {
+ char *flast = new_tmp_file_name();
+
+ sort_list_to_file(&list, flast);
+ file_list_add(&fl, flast, false);
+ }
+ merge_files(&fl, outfile);
+ }
+
+ file_list_clean(&fl);
+
+ /*
+ * We are about to exit the program, so we can ignore
+ * the clean-up for speed
+ *
+ * sort_list_clean(&list);
+ */
+
+ } else if (sort_opts_vals.cflag) {
+ result = (argc == 0) ? (check("-")) : (check(*argv));
+ } else if (sort_opts_vals.mflag) {
+ struct file_list fl;
+
+ file_list_init(&fl, false);
+ /* No file arguments remaining means "read from stdin." */
+ if (argc == 0)
+ file_list_add(&fl, "-", true);
+ else
+ file_list_populate(&fl, argc, argv, true);
+ merge_files(&fl, outfile);
+ file_list_clean(&fl);
+ }
+
+ if (real_outfile) {
+ unlink(real_outfile);
+ if (rename(outfile, real_outfile) < 0)
+ err(2, NULL);
+ sort_free(real_outfile);
+ }
+
+ sort_free(outfile);
+
+ return (result);
+}
diff --git a/usr.bin/sort/sort.h b/usr.bin/sort/sort.h
new file mode 100644
index 000000000000..124e5e0666da
--- /dev/null
+++ b/usr.bin/sort/sort.h
@@ -0,0 +1,128 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 !defined(__BSD_SORT_H__)
+#define __BSD_SORT_H__
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sysexits.h>
+#include <wchar.h>
+
+#include <sys/types.h>
+#include <md5.h>
+
+#define VERSION "2.3-FreeBSD"
+
+#define getstr(n) nlsstr[n]
+
+extern const char *nlsstr[];
+
+#if defined(SORT_THREADS)
+#define MT_SORT_THRESHOLD (10000)
+extern unsigned int ncpu;
+extern size_t nthreads;
+#endif
+
+/*
+ * If true, we output some debug information.
+ */
+extern bool debug_sort;
+
+/*
+ * MD5 context for random hash function
+ */
+extern MD5_CTX md5_ctx;
+
+/*
+ * sort.c
+ */
+
+/*
+ * This structure holds main sort options which are NOT affecting the sort ordering.
+ */
+struct sort_opts
+{
+ wint_t field_sep;
+ int sort_method;
+ bool cflag;
+ bool csilentflag;
+ bool kflag;
+ bool mflag;
+ bool sflag;
+ bool uflag;
+ bool zflag;
+ bool tflag;
+ bool complex_sort;
+};
+
+/*
+ * Key value structure forward declaration
+ */
+struct key_value;
+
+/*
+ * Cmp function
+ */
+typedef int (*cmpcoll_t)(struct key_value *kv1, struct key_value *kv2, size_t offset);
+
+/*
+ * This structure holds "sort modifiers" - options which are affecting the sort ordering.
+ */
+struct sort_mods
+{
+ cmpcoll_t func;
+ bool bflag;
+ bool dflag;
+ bool fflag;
+ bool gflag;
+ bool iflag;
+ bool Mflag;
+ bool nflag;
+ bool rflag;
+ bool Rflag;
+ bool Vflag;
+ bool hflag;
+};
+
+extern bool need_hint;
+
+extern struct sort_opts sort_opts_vals;
+
+extern struct sort_mods * const default_sort_mods;
+
+/*
+ * Cached value of MB_CUR_MAX. Because MB_CUR_MAX is used often throughout the program,
+ * this avoids frequent calls to __mb_cur_max.
+ */
+extern size_t mb_cur_max;
+
+#endif /* __BSD_SORT_H__ */
diff --git a/usr.bin/sort/tests/Makefile b/usr.bin/sort/tests/Makefile
new file mode 100644
index 000000000000..7514bf6b300f
--- /dev/null
+++ b/usr.bin/sort/tests/Makefile
@@ -0,0 +1,13 @@
+PACKAGE= tests
+
+NETBSD_ATF_TESTS_SH= sort_test
+ATF_TESTS_SH= sort_monthsort_test
+
+${PACKAGE}FILES+= d_any_char_dflag_out.txt
+${PACKAGE}FILES+= d_any_char_fflag_out.txt
+${PACKAGE}FILES+= d_any_char_iflag_out.txt
+${PACKAGE}FILES+= d_any_char_in.txt
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/sort/tests/Makefile.depend b/usr.bin/sort/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/sort/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/sort/tests/sort_monthsort_test.sh b/usr.bin/sort/tests/sort_monthsort_test.sh
new file mode 100755
index 000000000000..db42981fb107
--- /dev/null
+++ b/usr.bin/sort/tests/sort_monthsort_test.sh
@@ -0,0 +1,159 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023 Christos Margiolis <christos@FreeBSD.org>
+#
+
+get_months_fmt()
+{
+ rm -f in
+ for i in $(seq 12 1); do
+ printf "2000-%02d-01\n" ${i} | xargs -I{} \
+ date -jf "%Y-%m-%d" {} "${1}" >>in
+ done
+}
+
+atf_test_case monthsort_english
+monthsort_english_head()
+{
+ atf_set "descr" "Test the -M flag with English months"
+}
+monthsort_english_body()
+{
+ export LC_TIME="en_US.UTF-8"
+
+ cat >expout <<EOF
+January
+February
+March
+April
+May
+June
+July
+August
+September
+October
+November
+December
+EOF
+
+ # No need to test the rest of the formats (%b and %OB) as %b is a
+ # substring of %B and %OB is the same as %B.
+ get_months_fmt '+%B'
+ atf_check -o file:expout sort -M in
+}
+
+atf_test_case monthsort_all_formats_greek
+monthsort_all_formats_greek_head()
+{
+ atf_set "descr" "Test the -M flag with all possible Greek month formats"
+}
+monthsort_all_formats_greek_body()
+{
+ # Test with the Greek locale, since, unlike English, the
+ # abbreviation/full-name and standalone formats are different.
+ export LC_TIME="el_GR.UTF-8"
+
+ # Abbreviation format (e.g Jan, Ιαν)
+ cat >expout <<EOF
+Ιαν
+Φεβ
+ΜαÏ
+ΑπÏ
+ΜαÎ
+Ιουν
+Ιουλ
+Αυγ
+Σεπ
+Οκτ
+Îοε
+Δεκ
+EOF
+ get_months_fmt '+%b'
+ atf_check -o file:expout sort -M in
+
+ # Full-name format (e.g January, ΙανουαÏίου)
+ cat >expout <<EOF
+ΙανουαÏίου
+ΦεβÏουαÏίου
+ΜαÏτίου
+ΑπÏιλίου
+ΜαÎου
+Ιουνίου
+Ιουλίου
+ΑυγοÏστου
+ΣεπτεμβÏίου
+ΟκτωβÏίου
+ÎοεμβÏίου
+ΔεκεμβÏίου
+EOF
+ get_months_fmt '+%B'
+ atf_check -o file:expout sort -M in
+
+ # Standalone format (e.g January, ΙανουάÏιος)
+ cat >expout <<EOF
+ΙανουάÏιος
+ΦεβÏουάÏιος
+ΜάÏτιος
+ΑπÏίλιος
+Μάϊος
+ΙοÏνιος
+ΙοÏλιος
+ΑÏγουστος
+ΣεπτέμβÏιος
+ΟκτώβÏιος
+ÎοέμβÏιος
+ΔεκέμβÏιος
+EOF
+ get_months_fmt '+%OB'
+ atf_check -o file:expout sort -M in
+}
+
+atf_test_case monthsort_mixed_formats_greek
+monthsort_mixed_formats_greek_head()
+{
+ atf_set "descr" "Test the -M flag with mixed Greek month formats"
+}
+monthsort_mixed_formats_greek_body()
+{
+ export LC_TIME="el_GR.UTF-8"
+
+ cat >in <<EOF
+ΔεκέμβÏιος
+ÎοεμβÏίου
+Οκτ
+Σεπ
+Αυγ
+ΙοÏλιος
+Ιουνίου
+ΜαÎου
+ΑπÏιλίου
+ΜάÏτιος
+ΦεβÏουάÏιος
+ΙανουάÏιος
+EOF
+
+ cat >expout <<EOF
+ΙανουάÏιος
+ΦεβÏουάÏιος
+ΜάÏτιος
+ΑπÏιλίου
+ΜαÎου
+Ιουνίου
+ΙοÏλιος
+Αυγ
+Σεπ
+Οκτ
+ÎοεμβÏίου
+ΔεκέμβÏιος
+EOF
+
+ atf_check -o file:expout sort -M in
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case monthsort_english
+ atf_add_test_case monthsort_all_formats_greek
+ atf_add_test_case monthsort_mixed_formats_greek
+}
diff --git a/usr.bin/sort/vsort.c b/usr.bin/sort/vsort.c
new file mode 100644
index 000000000000..45bcbb532ad5
--- /dev/null
+++ b/usr.bin/sort/vsort.c
@@ -0,0 +1,264 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * Copyright (C) 2012 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <stdlib.h>
+#include <string.h>
+
+#include "sort.h"
+#include "vsort.h"
+
+static inline bool
+isdigit_clocale(wchar_t c)
+{
+
+ return (c >= L'0' && c <= L'9');
+}
+
+static inline bool
+isalpha_clocale(wchar_t c)
+{
+
+ return ((c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z'));
+}
+
+static inline bool
+isalnum_clocale(wchar_t c)
+{
+
+ return ((c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z') ||
+ (c >= L'0' && c <= L'9'));
+}
+
+/*
+ * Find string suffix of format: (\.[A-Za-z~][A-Za-z0-9~]*)*$
+ * Set length of string before suffix.
+ */
+static void
+find_suffix(bwstring_iterator si, bwstring_iterator se, size_t *len)
+{
+ wchar_t c;
+ size_t clen;
+ bool expect_alpha, sfx;
+
+ sfx = false;
+ expect_alpha = false;
+ *len = 0;
+ clen = 0;
+
+ while ((si < se) && (c = bws_get_iter_value(si))) {
+ if (expect_alpha) {
+ expect_alpha = false;
+ if (!isalpha_clocale(c) && (c != L'~'))
+ sfx = false;
+ } else if (c == L'.') {
+ expect_alpha = true;
+ if (!sfx) {
+ sfx = true;
+ *len = clen;
+ }
+ } else if (!isalnum_clocale(c) && (c != L'~'))
+ sfx = false;
+
+ si = bws_iterator_inc(si, 1);
+ ++clen;
+ }
+
+ /* This code must be here to make the implementation compatible
+ * with WORDING of GNU sort documentation.
+ * But the GNU sort implementation is not following its own
+ * documentation. GNU sort allows empty file extensions
+ * (just dot with nothing after); but the regular expression in
+ * their documentation does not allow empty file extensions.
+ * We chose to make our implementation compatible with GNU sort
+ * implementation. If they will ever fix their bug, this code
+ * must be uncommented. Or they may choose to fix the info page,
+ * then the code stays commented.
+ *
+ if (expect_alpha)
+ sfx = false;
+ */
+
+ if (!sfx)
+ *len = clen;
+}
+
+static inline int
+cmp_chars(wchar_t c1, wchar_t c2)
+{
+
+ if (c1 == c2)
+ return (0);
+
+ if (c1 == L'~')
+ return (-1);
+ if (c2 == L'~')
+ return (+1);
+
+ if (isdigit_clocale(c1) || !c1)
+ return ((isdigit_clocale(c2) || !c2) ? 0 : -1);
+
+ if (isdigit_clocale(c2) || !c2)
+ return (+1);
+
+ if (isalpha_clocale(c1))
+ return ((isalpha_clocale(c2)) ? ((int) c1 - (int) c2) : -1);
+
+ if (isalpha_clocale(c2))
+ return (+1);
+
+ return ((int) c1 - (int) c2);
+}
+
+static int
+cmpversions(bwstring_iterator si1, bwstring_iterator se1,
+ bwstring_iterator si2, bwstring_iterator se2)
+{
+ int cmp, diff;
+
+ while ((si1 < se1) || (si2 < se2)) {
+ diff = 0;
+
+ while (((si1 < se1) &&
+ !isdigit_clocale(bws_get_iter_value(si1))) ||
+ ((si2 < se2) && !isdigit_clocale(bws_get_iter_value(si2)))) {
+ wchar_t c1, c2;
+
+ c1 = (si1 < se1) ? bws_get_iter_value(si1) : 0;
+ c2 = (si2 < se2) ? bws_get_iter_value(si2) : 0;
+
+ cmp = cmp_chars(c1, c2);
+ if (cmp)
+ return (cmp);
+
+ if (si1 < se1)
+ si1 = bws_iterator_inc(si1, 1);
+ if (si2 < se2)
+ si2 = bws_iterator_inc(si2, 1);
+ }
+
+ while (bws_get_iter_value(si1) == L'0')
+ si1 = bws_iterator_inc(si1, 1);
+
+ while (bws_get_iter_value(si2) == L'0')
+ si2 = bws_iterator_inc(si2, 1);
+
+ while (isdigit_clocale(bws_get_iter_value(si1)) &&
+ isdigit_clocale(bws_get_iter_value(si2))) {
+ if (!diff)
+ diff = ((int)bws_get_iter_value(si1) -
+ (int)bws_get_iter_value(si2));
+ si1 = bws_iterator_inc(si1, 1);
+ si2 = bws_iterator_inc(si2, 1);
+ }
+
+ if (isdigit_clocale(bws_get_iter_value(si1)))
+ return (1);
+
+ if (isdigit_clocale(bws_get_iter_value(si2)))
+ return (-1);
+
+ if (diff)
+ return (diff);
+ }
+
+ return (0);
+}
+
+/*
+ * Compare two version strings
+ */
+int
+vcmp(struct bwstring *s1, struct bwstring *s2)
+{
+ bwstring_iterator si1, si2;
+ wchar_t c1, c2;
+ size_t len1, len2, slen1, slen2;
+ int cmp_bytes, cmp_res;
+
+ if (s1 == s2)
+ return (0);
+
+ cmp_bytes = bwscmp(s1, s2, 0);
+ if (cmp_bytes == 0)
+ return (0);
+
+ len1 = slen1 = BWSLEN(s1);
+ len2 = slen2 = BWSLEN(s2);
+
+ if (slen1 < 1)
+ return (-1);
+ if (slen2 < 1)
+ return (+1);
+
+ si1 = bws_begin(s1);
+ si2 = bws_begin(s2);
+
+ c1 = bws_get_iter_value(si1);
+ c2 = bws_get_iter_value(si2);
+
+ if (c1 == L'.' && (slen1 == 1))
+ return (-1);
+
+ if (c2 == L'.' && (slen2 == 1))
+ return (+1);
+
+ if (slen1 == 2 && c1 == L'.' &&
+ bws_get_iter_value(bws_iterator_inc(si1, 1)) == L'.')
+ return (-1);
+ if (slen2 == 2 && c2 == L'.' &&
+ bws_get_iter_value(bws_iterator_inc(si2, 1)) == L'.')
+ return (+1);
+
+ if (c1 == L'.' && c2 != L'.')
+ return (-1);
+ if (c1 != L'.' && c2 == L'.')
+ return (+1);
+
+ if (c1 == L'.' && c2 == L'.') {
+ si1 = bws_iterator_inc(si1, 1);
+ si2 = bws_iterator_inc(si2, 1);
+ }
+
+ find_suffix(si1, bws_end(s1), &len1);
+ find_suffix(si2, bws_end(s2), &len2);
+
+ if ((len1 == len2) && (bws_iterator_cmp(si1, si2, len1) == 0))
+ return (cmp_bytes);
+
+ cmp_res = cmpversions(si1, bws_iterator_inc(si1, len1), si2,
+ bws_iterator_inc(si2, len2));
+
+ if (cmp_res == 0)
+ cmp_res = cmp_bytes;
+
+ return (cmp_res);
+}
diff --git a/usr.bin/sort/vsort.h b/usr.bin/sort/vsort.h
new file mode 100644
index 000000000000..28904e595980
--- /dev/null
+++ b/usr.bin/sort/vsort.h
@@ -0,0 +1,38 @@
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2012 Oleg Moskalenko <mom040267@gmail.com>
+ * Copyright (C) 2012 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 _VSORT_H_
+#define _VSORT_H_
+
+#include "bwstring.h"
+
+int vcmp(struct bwstring *s1, struct bwstring *s2);
+
+#endif
diff --git a/usr.bin/split/Makefile b/usr.bin/split/Makefile
new file mode 100644
index 000000000000..99021342ec32
--- /dev/null
+++ b/usr.bin/split/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PROG= split
+
+LIBADD= util
+
+HAS_TESTS= yes
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/split/Makefile.depend b/usr.bin/split/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/split/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/split/split.1 b/usr.bin/split/split.1
new file mode 100644
index 000000000000..bd837f3e9c71
--- /dev/null
+++ b/usr.bin/split/split.1
@@ -0,0 +1,232 @@
+.\" Copyright (c) 1990, 1991, 1993, 1994
+.\" 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.
+.\"
+.Dd May 26, 2023
+.Dt SPLIT 1
+.Os
+.Sh NAME
+.Nm split
+.Nd split a file into pieces
+.Sh SYNOPSIS
+.Nm
+.Op Fl cd
+.Op Fl l Ar line_count
+.Op Fl a Ar suffix_length
+.Op Ar file Op Ar prefix
+.Nm
+.Op Fl cd
+.Fl b Ar byte_count Ns
+.Oo
+.Sm off
+.Cm K | k | M | m | G | g
+.Sm on
+.Oc
+.Op Fl a Ar suffix_length
+.Op Ar file Op Ar prefix
+.Nm
+.Op Fl cd
+.Fl n Ar chunk_count
+.Op Fl a Ar suffix_length
+.Op Ar file Op Ar prefix
+.Nm
+.Op Fl cd
+.Fl p Ar pattern
+.Op Fl a Ar suffix_length
+.Op Ar file Op Ar prefix
+.Sh DESCRIPTION
+The
+.Nm
+utility reads the given
+.Ar file
+and breaks it up into files of 1000 lines each
+(if no options are specified), leaving the
+.Ar file
+unchanged.
+If
+.Ar file
+is a single dash
+.Pq Sq Fl
+or absent,
+.Nm
+reads from the standard input.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a Ar suffix_length
+Use
+.Ar suffix_length
+letters to form the suffix of the file name.
+.It Fl b Ar byte_count Ns Oo
+.Sm off
+.Cm K | k | M | m | G | g
+.Sm on
+.Oc
+Create split files
+.Ar byte_count
+bytes in length.
+If
+.Cm k
+or
+.Cm K
+is appended to the number, the file is split into
+.Ar byte_count
+kilobyte pieces.
+If
+.Cm m
+or
+.Cm M
+is appended to the number, the file is split into
+.Ar byte_count
+megabyte pieces.
+If
+.Cm g
+or
+.Cm G
+is appended to the number, the file is split into
+.Ar byte_count
+gigabyte pieces.
+.It Fl c
+Continue creating files and do not overwrite existing
+output files.
+.It Fl d
+Use a numeric suffix instead of a alphabetic suffix.
+.It Fl l Ar line_count
+Create split files
+.Ar line_count
+lines in length.
+.It Fl n Ar chunk_count
+Split file into
+.Ar chunk_count
+smaller files.
+The first n - 1 files will be of size (size of
+.Ar file
+/
+.Ar chunk_count
+)
+and the last file will contain the remaining bytes.
+.It Fl p Ar pattern
+The file is split whenever an input line matches
+.Ar pattern ,
+which is interpreted as an extended regular expression.
+The matching line will be the first line of the next output file.
+This option is incompatible with the
+.Fl b
+and
+.Fl l
+options.
+.El
+.Pp
+If additional arguments are specified, the first is used as the name
+of the input file which is to be split.
+If a second additional argument is specified, it is used as a prefix
+for the names of the files into which the file is split.
+In this case, each file into which the file is split is named by the
+prefix followed by a lexically ordered suffix using
+.Ar suffix_length
+characters in the range
+.Dq Li a Ns - Ns Li z .
+If
+.Fl a
+is not specified, two letters are used as the initial suffix.
+If the output does not fit into the resulting number of files and the
+.Fl d
+flag is not specified, then the suffix length is automatically extended as
+needed such that all output files continue to sort in lexical order.
+.Pp
+If the
+.Ar prefix
+argument is not specified, the file is split into lexically ordered
+files named with the prefix
+.Dq Li x
+and with suffixes as above.
+.Pp
+By default,
+.Nm
+will overwrite any existing output files.
+If the
+.Fl c
+flag is specified,
+.Nm
+will instead create files with names that do not already exist.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_CTYPE
+and
+.Ev LC_COLLATE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Split input into as many files as needed, so that each file contains at most 2
+lines:
+.Bd -literal -offset indent
+$ echo -e "first line\\nsecond line\\nthird line\\nforth line" | split -l2
+.Ed
+.Pp
+Split input in chunks of 10 bytes using numeric prefixes for file names.
+This generates two files of 10 bytes (x00 and x01) and a third file (x02) with the
+remaining 2 bytes:
+.Bd -literal -offset indent
+$ echo -e "This is 22 bytes long" | split -d -b10
+.Ed
+.Pp
+Split input generating 6 files:
+.Bd -literal -offset indent
+$ echo -e "This is 22 bytes long" | split -n 6
+.Ed
+.Pp
+Split input creating a new file every time a line matches the regular expression
+for a
+.Dq t
+followed by either
+.Dq a
+or
+.Dq u
+thus creating two files:
+.Bd -literal -offset indent
+$ echo -e "stack\\nstock\\nstuck\\nanother line" | split -p 't[au]'
+.Ed
+.Sh SEE ALSO
+.Xr csplit 1 ,
+.Xr re_format 7
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v3 .
+.Pp
+Before
+.Fx 14 ,
+pattern and line matching only operated on lines shorter than 65,536 bytes.
diff --git a/usr.bin/split/split.c b/usr.bin/split/split.c
new file mode 100644
index 000000000000..2724f8a20cde
--- /dev/null
+++ b/usr.bin/split/split.c
@@ -0,0 +1,451 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1993, 1994
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <regex.h>
+#include <sysexits.h>
+
+#define DEFLINE 1000 /* Default num lines per file. */
+
+static off_t bytecnt; /* Byte count to split on. */
+static long chunks; /* Chunks count to split into. */
+static bool clobber = true; /* Whether to overwrite existing output files. */
+static long numlines; /* Line count to split on. */
+static int file_open; /* If a file open. */
+static int ifd = -1, ofd = -1; /* Input/output file descriptors. */
+static char fname[MAXPATHLEN]; /* File name prefix. */
+static regex_t rgx;
+static int pflag;
+static bool dflag;
+static long sufflen = 2; /* File name suffix length. */
+static bool autosfx = true; /* Whether to auto-extend the suffix length. */
+
+static void newfile(void);
+static void split1(void);
+static void split2(void);
+static void split3(void);
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ char errbuf[64];
+ const char *p, *errstr;
+ int ch, error;
+
+ setlocale(LC_ALL, "");
+
+ dflag = false;
+ while ((ch = getopt(argc, argv, "0::1::2::3::4::5::6::7::8::9::a:b:cdl:n:p:")) != -1)
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /*
+ * Undocumented kludge: split was originally designed
+ * to take a number after a dash.
+ */
+ if (numlines != 0)
+ usage();
+ numlines = ch - '0';
+ p = optarg ? optarg : "";
+ while (numlines >= 0 && *p >= '0' && *p <= '9')
+ numlines = numlines * 10 + *p++ - '0';
+ if (numlines <= 0 || *p != '\0')
+ errx(EX_USAGE, "%c%s: line count is invalid",
+ ch, optarg ? optarg : "");
+ break;
+ case 'a': /* Suffix length */
+ sufflen = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: suffix length is %s",
+ optarg, errstr);
+ }
+ if (sufflen == 0) {
+ sufflen = 2;
+ autosfx = true;
+ } else {
+ autosfx = false;
+ }
+ break;
+ case 'b': /* Byte count. */
+ if (expand_number(optarg, &bytecnt) != 0) {
+ errx(EX_USAGE, "%s: byte count is invalid",
+ optarg);
+ }
+ break;
+ case 'c': /* Continue, don't overwrite output files. */
+ clobber = false;
+ break;
+ case 'd': /* Decimal suffix */
+ dflag = true;
+ break;
+ case 'l': /* Line count. */
+ if (numlines != 0)
+ usage();
+ numlines = strtonum(optarg, 1, LONG_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: line count is %s",
+ optarg, errstr);
+ }
+ break;
+ case 'n': /* Chunks. */
+ chunks = strtonum(optarg, 1, LONG_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: number of chunks is %s",
+ optarg, errstr);
+ }
+ break;
+
+ case 'p': /* pattern matching. */
+ error = regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB);
+ if (error != 0) {
+ regerror(error, &rgx, errbuf, sizeof(errbuf));
+ errx(EX_USAGE, "%s: regex is invalid: %s",
+ optarg, errbuf);
+ }
+ pflag = 1;
+ break;
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (argc > 0) { /* Input file. */
+ if (strcmp(*argv, "-") == 0)
+ ifd = STDIN_FILENO;
+ else if ((ifd = open(*argv, O_RDONLY, 0)) < 0)
+ err(EX_NOINPUT, "%s", *argv);
+ ++argv;
+ --argc;
+ }
+ if (argc > 0) { /* File name prefix. */
+ if (strlcpy(fname, *argv, sizeof(fname)) >= sizeof(fname)) {
+ errx(EX_USAGE, "%s: file name prefix is too long",
+ *argv);
+ }
+ ++argv;
+ --argc;
+ }
+ if (argc > 0)
+ usage();
+
+ if (strlen(fname) + (unsigned long)sufflen >= sizeof(fname))
+ errx(EX_USAGE, "suffix is too long");
+ if (pflag && (numlines != 0 || bytecnt != 0 || chunks != 0))
+ usage();
+
+ if (numlines == 0)
+ numlines = DEFLINE;
+ else if (bytecnt != 0 || chunks != 0)
+ usage();
+
+ if (bytecnt != 0 && chunks != 0)
+ usage();
+
+ if (ifd == -1) /* Stdin by default. */
+ ifd = 0;
+
+ if (bytecnt != 0) {
+ split1();
+ exit (0);
+ } else if (chunks != 0) {
+ split3();
+ exit (0);
+ }
+ split2();
+ if (pflag)
+ regfree(&rgx);
+ exit(0);
+}
+
+/*
+ * split1 --
+ * Split the input by bytes.
+ */
+static void
+split1(void)
+{
+ static char bfr[MAXBSIZE];
+ off_t bcnt;
+ char *C;
+ ssize_t dist, len;
+ int nfiles;
+
+ nfiles = 0;
+
+ for (bcnt = 0;;)
+ switch ((len = read(ifd, bfr, sizeof(bfr)))) {
+ case 0:
+ exit(0);
+ case -1:
+ err(EX_IOERR, "read");
+ /* NOTREACHED */
+ default:
+ if (!file_open) {
+ if (chunks == 0 || nfiles < chunks) {
+ newfile();
+ nfiles++;
+ }
+ }
+ if (bcnt + len >= bytecnt) {
+ dist = bytecnt - bcnt;
+ if (write(ofd, bfr, dist) != dist)
+ err(EX_IOERR, "write");
+ len -= dist;
+ for (C = bfr + dist; len >= bytecnt;
+ len -= bytecnt, C += bytecnt) {
+ if (chunks == 0 || nfiles < chunks) {
+ newfile();
+ nfiles++;
+ }
+ if (write(ofd, C, bytecnt) != bytecnt)
+ err(EX_IOERR, "write");
+ }
+ if (len != 0) {
+ if (chunks == 0 || nfiles < chunks) {
+ newfile();
+ nfiles++;
+ }
+ if (write(ofd, C, len) != len)
+ err(EX_IOERR, "write");
+ } else {
+ file_open = 0;
+ }
+ bcnt = len;
+ } else {
+ bcnt += len;
+ if (write(ofd, bfr, len) != len)
+ err(EX_IOERR, "write");
+ }
+ }
+}
+
+/*
+ * split2 --
+ * Split the input by lines.
+ */
+static void
+split2(void)
+{
+ char *buf;
+ size_t bufsize;
+ ssize_t len;
+ long lcnt = 0;
+ FILE *infp;
+
+ buf = NULL;
+ bufsize = 0;
+
+ /* Stick a stream on top of input file descriptor */
+ if ((infp = fdopen(ifd, "r")) == NULL)
+ err(EX_NOINPUT, "fdopen");
+
+ /* Process input one line at a time */
+ while ((errno = 0, len = getline(&buf, &bufsize, infp)) > 0) {
+ /* Check if we need to start a new file */
+ if (pflag) {
+ regmatch_t pmatch;
+
+ pmatch.rm_so = 0;
+ pmatch.rm_eo = len - 1;
+ if (regexec(&rgx, buf, 0, &pmatch, REG_STARTEND) == 0)
+ newfile();
+ } else if (lcnt++ == numlines) {
+ newfile();
+ lcnt = 1;
+ }
+
+ /* Open output file if needed */
+ if (!file_open)
+ newfile();
+
+ /* Write out line */
+ if (write(ofd, buf, len) != len)
+ err(EX_IOERR, "write");
+ }
+
+ /* EOF or error? */
+ if ((len == -1 && errno != 0) || ferror(infp))
+ err(EX_IOERR, "read");
+ else
+ exit(0);
+}
+
+/*
+ * split3 --
+ * Split the input into specified number of chunks
+ */
+static void
+split3(void)
+{
+ struct stat sb;
+
+ if (fstat(ifd, &sb) == -1) {
+ err(1, "stat");
+ /* NOTREACHED */
+ }
+
+ if (chunks > sb.st_size) {
+ errx(1, "can't split into more than %d files",
+ (int)sb.st_size);
+ /* NOTREACHED */
+ }
+
+ bytecnt = sb.st_size / chunks;
+ split1();
+}
+
+
+/*
+ * newfile --
+ * Open a new output file.
+ */
+static void
+newfile(void)
+{
+ long i, maxfiles, tfnum;
+ static long fnum;
+ static char *fpnt;
+ char beg, end;
+ int pattlen;
+ int flags = O_WRONLY | O_CREAT | O_TRUNC;
+
+ if (!clobber)
+ flags |= O_EXCL;
+
+ if (ofd == -1) {
+ if (fname[0] == '\0') {
+ fname[0] = 'x';
+ fpnt = fname + 1;
+ } else {
+ fpnt = fname + strlen(fname);
+ }
+ } else if (close(ofd) != 0)
+ err(1, "%s", fname);
+
+ again:
+ if (dflag) {
+ beg = '0';
+ end = '9';
+ }
+ else {
+ beg = 'a';
+ end = 'z';
+ }
+ pattlen = end - beg + 1;
+
+ /*
+ * If '-a' is not specified, then we automatically expand the
+ * suffix length to accomodate splitting all input. We do this
+ * by moving the suffix pointer (fpnt) forward and incrementing
+ * sufflen by one, thereby yielding an additional two characters
+ * and allowing all output files to sort such that 'cat *' yields
+ * the input in order. I.e., the order is '... xyy xyz xzaaa
+ * xzaab ... xzyzy, xzyzz, xzzaaaa, xzzaaab' and so on.
+ */
+ if (!dflag && autosfx && (fpnt[0] == 'y') &&
+ strspn(fpnt+1, "z") == strlen(fpnt+1)) {
+ /* Ensure the generated filenames will fit into the buffer. */
+ if (strlen(fname) + 2 >= sizeof(fname))
+ errx(EX_USAGE, "combined filenames would be too long");
+
+ fpnt = fname + strlen(fname) - sufflen;
+ fpnt[sufflen + 2] = '\0';
+ fpnt[0] = end;
+ fpnt[1] = beg;
+
+ /* Basename | Suffix
+ * before:
+ * x | yz
+ * after:
+ * xz | a.. */
+ fpnt++;
+ sufflen++;
+
+ /* Reset so we start back at all 'a's in our extended suffix. */
+ fnum = 0;
+ }
+
+ /* maxfiles = pattlen^sufflen, but don't use libm. */
+ for (maxfiles = 1, i = 0; i < sufflen; i++)
+ if (LONG_MAX / pattlen < maxfiles)
+ errx(EX_USAGE, "suffix is too long (max %ld)", i);
+ else
+ maxfiles *= pattlen;
+
+ if (fnum == maxfiles)
+ errx(EX_DATAERR, "too many files");
+
+ /* Generate suffix of sufflen letters */
+ tfnum = fnum;
+ i = sufflen - 1;
+ do {
+ fpnt[i] = tfnum % pattlen + beg;
+ tfnum /= pattlen;
+ } while (i-- > 0);
+ fpnt[sufflen] = '\0';
+
+ ++fnum;
+ if ((ofd = open(fname, flags, DEFFILEMODE)) < 0) {
+ if (!clobber && errno == EEXIST)
+ goto again;
+ err(EX_IOERR, "%s", fname);
+ }
+ file_open = 1;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+"usage: split [-cd] [-l line_count] [-a suffix_length] [file [prefix]]\n"
+" split [-cd] -b byte_count[K|k|M|m|G|g] [-a suffix_length] [file [prefix]]\n"
+" split [-cd] -n chunk_count [-a suffix_length] [file [prefix]]\n"
+" split [-cd] -p pattern [-a suffix_length] [file [prefix]]\n");
+ exit(EX_USAGE);
+}
diff --git a/usr.bin/split/tests/Makefile b/usr.bin/split/tests/Makefile
new file mode 100644
index 000000000000..65f62cff26f1
--- /dev/null
+++ b/usr.bin/split/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH+= split_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/split/tests/Makefile.depend b/usr.bin/split/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/split/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/split/tests/split_test.sh b/usr.bin/split/tests/split_test.sh
new file mode 100755
index 000000000000..48065719055a
--- /dev/null
+++ b/usr.bin/split/tests/split_test.sh
@@ -0,0 +1,274 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022-2023 Klara Systems
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+# sys/param.h
+: ${MAXBSIZE:=65536}
+
+atf_test_case bytes
+bytes_body()
+{
+ printf "aaaa" > foo-aa
+ printf "bb\nc" > foo-ab
+ printf "ccc\n" > foo-ac
+
+ cat foo-* > foo
+ atf_check split -b 4 foo split-
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+
+ # MAXBSIZE is the default buffer size, so we'll split at just a little
+ # bit past the buffer size to make sure that it still properly splits
+ # even when it needs to read again to hit the limit.
+ bsize=$((MAXBSIZE + 12))
+ rm foo-* foo
+ jot -ns "" -b "a" ${bsize} > foo-aa
+ jot -ns "" -b "b" ${bsize} > foo-ab
+ jot -ns "" -b "c" 12 > foo-ac
+
+ cat foo-* > foo
+ atf_check split -b ${bsize} foo split-
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+}
+
+atf_test_case chunks
+chunks_body()
+{
+ jot -ns "" -b "a" 4096 > foo
+ jot -ns "" -b "b" 4096 >> foo
+ jot -ns "" -b "c" 4104 >> foo
+
+ chunks=3
+ jot -ns "" -b "a" 4096 > foo-aa
+ jot -ns "" -b "b" 2 >> foo-aa
+ jot -ns "" -b "b" 4094 > foo-ab
+ jot -ns "" -b "c" 4 >> foo-ab
+ jot -ns "" -b "c" 4100 > foo-ac
+
+ atf_check split -n ${chunks} foo split-
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+}
+
+atf_test_case sensible_lines
+sensible_lines_body()
+{
+ echo "The quick brown fox" > foo-aa
+ echo "jumps over" > foo-ab
+ echo "the lazy dog" > foo-ac
+
+ cat foo-* > foo
+ atf_check split -l 1 foo split-
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+
+ # Try again, make sure that `-` uses stdin as documented.
+ atf_check rm split-*
+ atf_check -x 'split -l 1 - split- < foo'
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+
+ # Finally, try with -l == 2; we should see a 2/1 split instead of the
+ # previous 1/1/1.
+ cat foo-aa foo-ab > foo-aa-ng
+ cat foo-ac > foo-ab-ng
+
+ atf_check rm split-*
+ atf_check split -l 2 foo split-
+
+ atf_check -o file:foo-aa-ng cat split-aa
+ atf_check -o file:foo-ab-ng cat split-ab
+}
+
+atf_test_case long_lines
+long_lines_body()
+{
+
+ # Test file lines will be:
+ # a x MAXBSIZE
+ # b x MAXBSIZE + c x MAXBSIZE
+ # d x 1024
+ #
+ # The historical split(1) implementation wouldn't grow its internal
+ # buffer, so we'd end up with 2/3 split- files being wrong with -l 1.
+ # Notably, split-aa would include most of the first two lines, split-ab
+ # a tiny fraction of the second line, and split-ac the third line.
+ #
+ # Recent split(1) instead grows the buffer until we can either fit the
+ # line or we run out of memory.
+ jot -s "" -b "a" ${MAXBSIZE} > foo-aa
+ jot -ns "" -b "b" ${MAXBSIZE} > foo-ab
+ jot -s "" -b "c" ${MAXBSIZE} >> foo-ab
+ jot -s "" -b "d" 1024 > foo-ac
+
+ cat foo-* > foo
+ atf_check split -l 1 foo split-
+
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+ atf_check -o file:foo-ac cat split-ac
+}
+
+atf_test_case numeric_suffix
+numeric_suffix_body()
+{
+ echo "The quick brown fox" > foo-00
+ echo "jumps over" > foo-01
+ echo "the lazy dog" > foo-02
+
+ cat foo-* > foo
+ atf_check split -d -l 1 foo split-
+
+ atf_check -o file:foo-00 cat split-00
+ atf_check -o file:foo-01 cat split-01
+ atf_check -o file:foo-02 cat split-02
+}
+
+atf_test_case larger_suffix_length
+larger_suffix_length_body()
+{
+ :> foo
+
+ # Generate foo-000 through foo-009, then foo-010 and foo-011
+ for i in $(seq -w 0 11); do
+ len=$((${i##0} + 1))
+ file="foo-0${i}"
+ jot -s "" -b "a" ${len} > ${file}
+ cat ${file} >> foo
+ done
+
+ atf_check split -a 3 -d -l 1 foo split-
+ for i in $(seq -w 0 11); do
+ srcfile="foo-0${i}"
+ splitfile="split-0${i}"
+ atf_check -o file:"${srcfile}" cat "${splitfile}"
+ done
+}
+
+atf_test_case pattern
+pattern_body()
+{
+
+ # Some fake yaml gives us a good realistic use-case for -p, as we can
+ # split on top-level stanzas.
+ cat <<EOF > foo-aa
+cat:
+ aa: true
+ ab: true
+ ac: true
+EOF
+ cat <<EOF > foo-ab
+dog:
+ ba: true
+ bb: true
+ bc: true
+EOF
+
+ cat foo-* > foo
+
+ atf_check split -p "^[^[:space:]]+:" foo split-
+ atf_check -o file:foo-aa cat split-aa
+ atf_check -o file:foo-ab cat split-ab
+}
+
+atf_test_case autoextend
+autoextend_body()
+{
+ seq $((26*25+1)) >input
+ atf_check split -l1 input
+ atf_check -o inline:"$((26*25))\n" cat xyz
+ atf_check -o inline:"$((26*25+1))\n" cat xzaaa
+}
+
+atf_test_case noautoextend
+noautoextend_body()
+{
+ seq $((26*26)) >input
+ atf_check split -a2 -l1 input
+ atf_check -o inline:"$((26*26))\n" cat xzz
+}
+
+atf_test_case reautoextend
+reautoextend_body()
+{
+ seq $((26*25+1)) >input
+ atf_check split -a2 -a0 -l1 input
+ atf_check -o inline:"$((26*25))\n" cat xyz
+ atf_check -o inline:"$((26*25+1))\n" cat xzaaa
+}
+
+atf_test_case continue
+continue_body()
+{
+ echo hello >input
+ atf_check split input
+ atf_check -o file:input cat xaa
+ atf_check -s exit:1 -e ignore cat xab
+ atf_check split -c input
+ atf_check -o file:input cat xab
+}
+
+atf_test_case undocumented_kludge
+undocumented_kludge_body()
+{
+ seq 5000 >input
+ atf_check split -1000 input
+ atf_check -o file:xae seq 4001 5000
+ atf_check split -d1000 input
+ atf_check -o file:x04 seq 4001 5000
+}
+
+atf_test_case duplicate_linecount
+duplicate_linecount_body()
+{
+ atf_check -s exit:64 -e ignore split -5 -5 /dev/null
+ atf_check -s exit:64 -e ignore split -l5 -5 /dev/null
+ atf_check -s exit:64 -e ignore split -5 -l5 /dev/null
+ atf_check -s exit:64 -e ignore split -l5 -l5 /dev/null
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case bytes
+ atf_add_test_case chunks
+ atf_add_test_case sensible_lines
+ atf_add_test_case long_lines
+ atf_add_test_case numeric_suffix
+ atf_add_test_case larger_suffix_length
+ atf_add_test_case pattern
+ atf_add_test_case autoextend
+ atf_add_test_case noautoextend
+ atf_add_test_case reautoextend
+ atf_add_test_case continue
+ atf_add_test_case undocumented_kludge
+ atf_add_test_case duplicate_linecount
+}
diff --git a/usr.bin/ssh-copy-id/Makefile b/usr.bin/ssh-copy-id/Makefile
new file mode 100644
index 000000000000..66a742726d6e
--- /dev/null
+++ b/usr.bin/ssh-copy-id/Makefile
@@ -0,0 +1,5 @@
+SCRIPTS= ssh-copy-id.sh
+MAN= ssh-copy-id.1
+PACKAGE= ssh
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ssh-copy-id/Makefile.depend b/usr.bin/ssh-copy-id/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/ssh-copy-id/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ssh-copy-id/ssh-copy-id.1 b/usr.bin/ssh-copy-id/ssh-copy-id.1
new file mode 100644
index 000000000000..9909aa6f2d91
--- /dev/null
+++ b/usr.bin/ssh-copy-id/ssh-copy-id.1
@@ -0,0 +1,87 @@
+.\"-
+.\" Copyright (c) 2012 Eitan Adler
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 February 28, 2014
+.Dt SSH-COPY-ID 1
+.Os
+.Sh NAME
+.Nm ssh-copy-id
+.Nd copy public keys to a remote host
+.Sh SYNOPSIS
+.Nm
+.Op Fl lv
+.Op Fl i Ar keyfile
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Oo Ar user Ns @ Oc Ns Ar hostname
+.Sh DESCRIPTION
+The
+.Nm
+utility copies public keys to a remote host's
+.Pa ~/.ssh/authorized_keys
+file (creating the file and directory, if required).
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl i Ar file
+Copy the public key contained in
+.Ar file .
+This option can be specified multiple times and can be combined with
+the
+.Fl l
+option.
+If a private key is specified and a public key is found then the public key
+will be used.
+.It Fl l
+Copy the keys currently held by
+.Xr ssh-agent 1 .
+This is the default if the
+.Fl i
+option was not specified.
+.It Fl o Ar ssh-option
+Pass this option directly to
+.Xr ssh 1 .
+This option can be specified multiple times.
+.It Fl p Ar port
+Connect to the specified port on the remote host instead of the
+default.
+.It Fl v
+Pass -v to
+.Xr ssh 1 .
+.El
+.Pp
+The remaining arguments are a list of remote hosts to connect to,
+each one optionally qualified by a user name.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To send a specific key to multiple hosts:
+.Dl $ ssh-copy-id -i /path/to/keyfile.pub user@host1 user@host2 user@host3
+.Sh HISTORY
+The
+.Nm
+utility was written by
+.An Eitan Adler Aq Mt eadler@FreeBSD.org
+as a drop-in replacement for an existing utility included with
+OpenSSH.
diff --git a/usr.bin/ssh-copy-id/ssh-copy-id.sh b/usr.bin/ssh-copy-id/ssh-copy-id.sh
new file mode 100755
index 000000000000..e19a9348a597
--- /dev/null
+++ b/usr.bin/ssh-copy-id/ssh-copy-id.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2012 Eitan Adler
+#
+# 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
+# in this position and unchanged.
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+usage() {
+ echo "usage: ssh-copy-id [-lv] [-i keyfile] [-o option] [-p port] [user@]hostname" >&2
+ exit 1
+}
+
+sendkey() {
+ local h="$1"
+ local k="$2"
+ printf "%s\n" "$k" | ssh $port -S none $options "$user$h" /bin/sh -c \'' \
+ set -e; \
+ umask 077; \
+ keyfile=$HOME/.ssh/authorized_keys ; \
+ mkdir -p -- "$HOME/.ssh/" ; \
+ while read alg key comment ; do \
+ [ -n "$key" ] || continue; \
+ if ! grep -sqwF "$key" "$keyfile"; then \
+ printf "$alg $key $comment\n" >> "$keyfile" ; \
+ fi ; \
+ done ; \
+ if [ -x /sbin/restorecon ]; then \
+ /sbin/restorecon -F "$HOME/.ssh/" "$keyfile" >/dev/null 2>&1 || true ; \
+ fi \
+ '\'
+}
+
+agentKeys() {
+ keys="$(ssh-add -L | grep -v 'The agent has no identities.')$nl$keys"
+}
+
+keys=""
+host=""
+hasarg=""
+user=""
+port=""
+nl="
+"
+options=""
+
+IFS=$nl
+
+while getopts 'i:lo:p:v' arg; do
+ case $arg in
+ i)
+ hasarg="x"
+ if [ -r "${OPTARG}.pub" ]; then
+ keys="$(cat -- "${OPTARG}.pub")$nl$keys"
+ elif [ -r "$OPTARG" ]; then
+ keys="$(cat -- "$OPTARG")$nl$keys"
+ else
+ echo "File $OPTARG not found" >&2
+ exit 1
+ fi
+ ;;
+ l)
+ hasarg="x"
+ agentKeys
+ ;;
+ p)
+ port=-p$nl$OPTARG
+ ;;
+ o)
+ options=$options$nl-o$nl$OPTARG
+ ;;
+ v)
+ options="$options$nl-v"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done >&2
+
+shift $((OPTIND-1))
+
+if [ -z "$hasarg" ]; then
+ agentKeys
+fi
+if [ -z "$keys" ] || [ "$keys" = "$nl" ]; then
+ echo "no keys found" >&2
+ exit 1
+fi
+if [ "$#" -eq 0 ]; then
+ usage
+fi
+
+for host in "$@"; do
+ sendkey "$host" "$keys"
+done
diff --git a/usr.bin/stat/Makefile b/usr.bin/stat/Makefile
new file mode 100644
index 000000000000..1694310a7a6b
--- /dev/null
+++ b/usr.bin/stat/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PROG= stat
+
+LINKS= ${BINDIR}/stat ${BINDIR}/readlink
+MLINKS= stat.1 readlink.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/stat/Makefile.depend b/usr.bin/stat/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/stat/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/stat/stat.1 b/usr.bin/stat/stat.1
new file mode 100644
index 000000000000..2996781fafa6
--- /dev/null
+++ b/usr.bin/stat/stat.1
@@ -0,0 +1,604 @@
+.\" $NetBSD: stat.1,v 1.28 2010/04/05 21:25:01 joerg Exp $
+.\"
+.\" Copyright (c) 2002 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Andrew Brown and Jan Schaumann.
+.\"
+.\" 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 June 22, 2017
+.Dt STAT 1
+.Os
+.Sh NAME
+.Nm stat ,
+.Nm readlink
+.Nd display file status
+.Sh SYNOPSIS
+.Nm
+.Op Fl FHLnq
+.Op Fl f Ar format | Fl l | r | s | x
+.Op Fl t Ar timefmt
+.Op Ar
+.Nm readlink
+.Op Fl fn
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about the file pointed to by
+.Ar file .
+Read, write, or execute permissions of the named file are not required, but
+all directories listed in the pathname leading to the file must be
+searchable.
+If no argument is given,
+.Nm
+displays information about the file descriptor for standard input.
+.Pp
+When invoked as
+.Nm readlink ,
+only the target of the symbolic link is printed.
+If the given argument is not a symbolic link and the
+.Fl f
+option is not specified,
+.Nm readlink
+will print nothing and exit with an error.
+If the
+.Fl f
+option is specified, the output is canonicalized by following every symlink
+in every component of the given path recursively.
+.Nm readlink
+will resolve both absolute and relative paths, and return the absolute pathname
+corresponding to
+.Ar file .
+In this case, the argument does not need to be a symbolic link.
+.Pp
+The information displayed is obtained by calling
+.Xr lstat 2
+with the given argument and evaluating the returned structure.
+The default format displays the
+.Fa st_dev ,
+.Fa st_ino ,
+.Fa st_mode ,
+.Fa st_nlink ,
+.Fa st_uid ,
+.Fa st_gid ,
+.Fa st_rdev ,
+.Fa st_size ,
+.Fa st_atime ,
+.Fa st_mtime ,
+.Fa st_ctime ,
+.Fa st_birthtime ,
+.Fa st_blksize ,
+.Fa st_blocks ,
+and
+.Fa st_flags
+fields, in that order.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl F
+As in
+.Xr ls 1 ,
+display a slash
+.Pq Ql /
+immediately after each pathname that is a directory,
+an asterisk
+.Pq Ql *
+after each that is executable,
+an at sign
+.Pq Ql @
+after each symbolic link,
+a percent sign
+.Pq Ql %
+after each whiteout,
+an equal sign
+.Pq Ql =
+after each socket,
+and a vertical bar
+.Pq Ql |
+after each that is a FIFO.
+The use of
+.Fl F
+implies
+.Fl l .
+.It Fl H
+Treat each argument as the hexadecimal representation of an NFS file handle,
+and use
+.Xr fhstat 2
+instead of
+.Xr lstat 2 .
+This requires root privileges.
+.It Fl L
+Use
+.Xr stat 2
+instead of
+.Xr lstat 2 .
+The information reported by
+.Nm
+will refer to the target of
+.Ar file ,
+if file is a symbolic link, and not to
+.Ar file
+itself.
+If the link is broken or the target does not exist,
+fall back on
+.Xr lstat 2
+and report information about the link.
+.It Fl n
+Do not force a newline to appear at the end of each piece of output.
+.It Fl q
+Suppress failure messages if calls to
+.Xr stat 2
+or
+.Xr lstat 2
+fail.
+When run as
+.Nm readlink ,
+error messages are automatically suppressed.
+.It Fl f Ar format
+Display information using the specified format.
+See the
+.Sx Formats
+section for a description of valid formats.
+.It Fl l
+Display output in
+.Nm ls Fl lT
+format.
+.It Fl r
+Display raw information.
+That is, for all the fields in the
+.Vt stat
+structure,
+display the raw, numerical value (for example, times in seconds since the
+epoch, etc.).
+.It Fl s
+Display information in
+.Dq shell output
+format,
+suitable for initializing variables.
+.It Fl t Ar timefmt
+Display timestamps using the specified format.
+This format is
+passed directly to
+.Xr strftime 3 .
+.It Fl x
+Display information in a more verbose way as known from some
+.Tn Linux
+distributions.
+.El
+.Ss Formats
+Format strings are similar to
+.Xr printf 3
+formats in that they start with
+.Cm % ,
+are then followed by a sequence of formatting characters, and end in
+a character that selects the field of the
+.Vt "struct stat"
+which is to be formatted.
+If the
+.Cm %
+is immediately followed by one of
+.Cm n , t , % ,
+or
+.Cm @ ,
+then a newline character, a tab character, a percent character,
+or the current file number is printed, otherwise the string is
+examined for the following:
+.Pp
+Any of the following optional flags:
+.Bl -tag -width indent
+.It Cm #
+Selects an alternate output form for octal and hexadecimal output.
+Non-zero octal output will have a leading zero, and non-zero
+hexadecimal output will have
+.Dq Li 0x
+prepended to it.
+.It Cm +
+Asserts that a sign indicating whether a number is positive or negative
+should always be printed.
+Non-negative numbers are not usually printed
+with a sign.
+.It Cm -
+Aligns string output to the left of the field, instead of to the right.
+.It Cm 0
+Sets the fill character for left padding to the
+.Ql 0
+character, instead of a space.
+.It space
+Reserves a space at the front of non-negative signed output fields.
+A
+.Sq Cm +
+overrides a space if both are used.
+.El
+.Pp
+Then the following fields:
+.Bl -tag -width indent
+.It Ar size
+An optional decimal digit string specifying the minimum field width.
+.It Ar prec
+An optional precision composed of a decimal point
+.Sq Cm \&.
+and a decimal digit string that indicates the maximum string length,
+the number of digits to appear after the decimal point in floating point
+output, or the minimum number of digits to appear in numeric output.
+.It Ar fmt
+An optional output format specifier which is one of
+.Cm D , O , U , X , F ,
+or
+.Cm S .
+These represent signed decimal output, octal output, unsigned decimal
+output, hexadecimal output, floating point output, and string output,
+respectively.
+Some output formats do not apply to all fields.
+Floating point output only applies to
+.Vt timespec
+fields (the
+.Cm a , m ,
+and
+.Cm c
+fields).
+.Pp
+The special output specifier
+.Cm S
+may be used to indicate that the output, if
+applicable, should be in string format.
+May be used in combination with:
+.Bl -tag -width indent
+.It Cm amc
+Display date in
+.Xr strftime 3
+format.
+.It Cm dr
+Display actual device name.
+.It Cm f
+Display the flags of
+.Ar file
+as in
+.Nm ls Fl lTdo .
+.It Cm gu
+Display group or user name.
+.It Cm p
+Display the mode of
+.Ar file
+as in
+.Nm ls Fl lTd .
+.It Cm N
+Displays the name of
+.Ar file .
+.It Cm T
+Displays the type of
+.Ar file .
+.It Cm Y
+Insert a
+.Dq Li " -\*[Gt] "
+into the output.
+Note that the default output format
+for
+.Cm Y
+is a string, but if specified explicitly, these four characters are
+prepended.
+.El
+.It Ar sub
+An optional sub field specifier (high, middle, low).
+Only applies to
+the
+.Cm p , d , r ,
+and
+.Cm T
+output formats.
+It can be one of the following:
+.Bl -tag -width indent
+.It Cm H
+.Dq High
+\[em]
+specifies the major number for devices from
+.Cm r
+or
+.Cm d ,
+the
+.Dq user
+bits for permissions from the string form of
+.Cm p ,
+the file
+.Dq type
+bits from the numeric forms of
+.Cm p ,
+and the long output form of
+.Cm T .
+.It Cm L
+.Dq Low
+\[em]
+specifies the minor number for devices from
+.Cm r
+or
+.Cm d ,
+the
+.Dq other
+bits for permissions from the string form of
+.Cm p ,
+the
+.Dq user ,
+.Dq group ,
+and
+.Dq other
+bits from the numeric forms of
+.Cm p ,
+and the
+.Nm ls Fl F
+style output character for file type when used with
+.Cm T
+(the use of
+.Cm L
+for this is optional).
+.It Cm M
+.Dq Middle
+\[em]
+specifies the
+.Dq group
+bits for permissions from the
+string output form of
+.Cm p ,
+or the
+.Dq suid ,
+.Dq sgid ,
+and
+.Dq sticky
+bits for the numeric forms of
+.Cm p .
+.El
+.It Ar datum
+A required field specifier, being one of the following:
+.Bl -tag -width indent
+.It Cm d
+Device upon which
+.Ar file
+resides
+.Pq Fa st_dev .
+.It Cm i
+.Ar file Ns 's
+inode number
+.Pq Fa st_ino .
+.It Cm p
+File type and permissions
+.Pq Fa st_mode .
+.It Cm l
+Number of hard links to
+.Ar file
+.Pq Fa st_nlink .
+.It Cm u , g
+User ID and group ID of
+.Ar file Ns 's
+owner
+.Pq Fa st_uid , st_gid .
+.It Cm r
+Device number for character and block device special files
+.Pq Fa st_rdev .
+.It Cm a , m , c , B
+The time
+.Ar file
+was last accessed or modified, or when the inode was last changed, or
+the birth time of the inode
+.Pq Fa st_atime , st_mtime , st_ctime , st_birthtime .
+.It Cm z
+The size of
+.Ar file
+in bytes
+.Pq Fa st_size .
+.It Cm b
+Number of blocks allocated for
+.Ar file
+.Pq Fa st_blocks .
+.It Cm k
+Optimal file system I/O operation block size
+.Pq Fa st_blksize .
+.It Cm f
+User defined flags for
+.Ar file .
+.It Cm v
+Inode generation number
+.Pq Fa st_gen .
+.El
+.Pp
+The following five field specifiers are not drawn directly from the
+data in
+.Vt "struct stat" ,
+but are:
+.Bl -tag -width indent
+.It Cm N
+The name of the file.
+.It Cm R
+The absolute pathname corresponding to the file.
+.It Cm T
+The file type, either as in
+.Nm ls Fl F
+or in a more descriptive form if the
+.Ar sub
+field specifier
+.Cm H
+is given.
+.It Cm Y
+The target of a symbolic link.
+.It Cm Z
+Expands to
+.Dq major,minor
+from the
+.Va rdev
+field for character or block
+special devices and gives size output for all others.
+.El
+.El
+.Pp
+Only the
+.Cm %
+and the field specifier are required.
+Most field specifiers default to
+.Cm U
+as an output form, with the
+exception of
+.Cm p
+which defaults to
+.Cm O ;
+.Cm a , m ,
+and
+.Cm c
+which default to
+.Cm D ;
+and
+.Cm Y , T ,
+and
+.Cm N
+which default to
+.Cm S .
+.Sh EXIT STATUS
+.Ex -std stat readlink
+.Sh EXAMPLES
+If no options are specified, the default format is
+"%d %i %Sp %l %Su %Sg %r %z \e"%Sa\e" \e"%Sm\e" \e"%Sc\e" \e"%SB\e" %k %b %#Xf %N".
+.Bd -literal -offset indent
+\*[Gt] stat /tmp/bar
+0 78852 -rw-r--r-- 1 root wheel 0 0 "Jul 8 10:26:03 2004" "Jul 8 10:26:03 2004" "Jul 8 10:28:13 2004" "Jan 1 09:00:00 1970" 16384 0 0 /tmp/bar
+.Ed
+.Pp
+Given a symbolic link
+.Dq foo
+that points from
+.Pa /tmp/foo
+to
+.Pa / ,
+you would use
+.Nm
+as follows:
+.Bd -literal -offset indent
+\*[Gt] stat -F /tmp/foo
+lrwxrwxrwx 1 jschauma cs 1 Apr 24 16:37:28 2002 /tmp/foo@ -\*[Gt] /
+
+\*[Gt] stat -LF /tmp/foo
+drwxr-xr-x 16 root wheel 512 Apr 19 10:57:54 2002 /tmp/foo/
+.Ed
+.Pp
+To initialize some shell variables, you could use the
+.Fl s
+flag as follows:
+.Bd -literal -offset indent
+\*[Gt] csh
+% eval set `stat -s .cshrc`
+% echo $st_size $st_mtimespec
+1148 1015432481
+
+\*[Gt] sh
+$ eval $(stat -s .profile)
+$ echo $st_size $st_mtimespec
+1148 1015432481
+.Ed
+.Pp
+In order to get a list of file types including files pointed to if the
+file is a symbolic link, you could use the following format:
+.Bd -literal -offset indent
+$ stat -f "%N: %HT%SY" /tmp/*
+/tmp/bar: Symbolic Link -\*[Gt] /tmp/foo
+/tmp/output25568: Regular File
+/tmp/blah: Directory
+/tmp/foo: Symbolic Link -\*[Gt] /
+.Ed
+.Pp
+In order to get a list of the devices, their types and the major and minor
+device numbers, formatted with tabs and linebreaks, you could use the
+following format:
+.Bd -literal -offset indent
+stat -f "Name: %N%n%tType: %HT%n%tMajor: %Hr%n%tMinor: %Lr%n%n" /dev/*
+[...]
+Name: /dev/wt8
+ Type: Block Device
+ Major: 3
+ Minor: 8
+
+Name: /dev/zero
+ Type: Character Device
+ Major: 2
+ Minor: 12
+.Ed
+.Pp
+In order to determine the permissions set on a file separately, you could use
+the following format:
+.Bd -literal -offset indent
+\*[Gt] stat -f "%Sp -\*[Gt] owner=%SHp group=%SMp other=%SLp" .
+drwxr-xr-x -\*[Gt] owner=rwx group=r-x other=r-x
+.Ed
+.Pp
+In order to determine the three files that have been modified most recently,
+you could use the following format:
+.Bd -literal -offset indent
+\*[Gt] stat -f "%m%t%Sm %N" /tmp/* | sort -rn | head -3 | cut -f2-
+Apr 25 11:47:00 2002 /tmp/blah
+Apr 25 10:36:34 2002 /tmp/bar
+Apr 24 16:47:35 2002 /tmp/foo
+.Ed
+.Pp
+To display a file's modification time:
+.Bd -literal -offset indent
+\*[Gt] stat -f %m /tmp/foo
+1177697733
+.Ed
+.Pp
+To display the same modification time in a readable format:
+.Bd -literal -offset indent
+\*[Gt] stat -f %Sm /tmp/foo
+Apr 27 11:15:33 2007
+.Ed
+.Pp
+To display the same modification time in a readable and sortable format:
+.Bd -literal -offset indent
+\*[Gt] stat -f %Sm -t %Y%m%d%H%M%S /tmp/foo
+20070427111533
+.Ed
+.Pp
+To display the same in UTC:
+.Bd -literal -offset indent
+\*[Gt] sh
+$ TZ= stat -f %Sm -t %Y%m%d%H%M%S /tmp/foo
+20070427181533
+.Ed
+.Sh SEE ALSO
+.Xr file 1 ,
+.Xr ls 1 ,
+.Xr lstat 2 ,
+.Xr readlink 2 ,
+.Xr stat 2 ,
+.Xr printf 3 ,
+.Xr strftime 3
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Nx 1.6
+and
+.Fx 4.10 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was written by
+.An Andrew Brown Aq Mt atatat@NetBSD.org .
+This man page was written by
+.An Jan Schaumann Aq Mt jschauma@NetBSD.org .
diff --git a/usr.bin/stat/stat.c b/usr.bin/stat/stat.c
new file mode 100644
index 000000000000..1fd8288728c1
--- /dev/null
+++ b/usr.bin/stat/stat.c
@@ -0,0 +1,1091 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Brown.
+ *
+ * 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 <sys/cdefs.h>
+#if 0
+#ifndef lint
+__RCSID("$NetBSD: stat.c,v 1.33 2011/01/15 22:54:10 njoly Exp $"
+"$OpenBSD: stat.c,v 1.14 2009/06/24 09:44:25 sobrado Exp $");
+#endif
+#endif
+#if HAVE_CONFIG_H
+#include "config.h"
+#else /* HAVE_CONFIG_H */
+#define HAVE_STRUCT_STAT_ST_FLAGS 1
+#define HAVE_STRUCT_STAT_ST_GEN 1
+#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
+#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
+#define HAVE_DEVNAME 1
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <limits.h>
+#include <locale.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#if HAVE_STRUCT_STAT_ST_FLAGS
+#define DEF_F "%#Xf "
+#define RAW_F "%f "
+#define SHELL_F " st_flags=%f"
+#else /* HAVE_STRUCT_STAT_ST_FLAGS */
+#define DEF_F
+#define RAW_F
+#define SHELL_F
+#endif /* HAVE_STRUCT_STAT_ST_FLAGS */
+
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+#define DEF_B "\"%SB\" "
+#define RAW_B "%B "
+#define SHELL_B "st_birthtime=%B "
+#else /* HAVE_STRUCT_STAT_ST_BIRTHTIME */
+#define DEF_B
+#define RAW_B
+#define SHELL_B
+#endif /* HAVE_STRUCT_STAT_ST_BIRTHTIME */
+
+#if HAVE_STRUCT_STAT_ST_ATIM
+#define st_atimespec st_atim
+#define st_ctimespec st_ctim
+#define st_mtimespec st_mtim
+#endif /* HAVE_STRUCT_STAT_ST_ATIM */
+
+#define DEF_FORMAT \
+ "%d %i %Sp %l %Su %Sg %r %z \"%Sa\" \"%Sm\" \"%Sc\" " DEF_B \
+ "%k %b " DEF_F "%N"
+#define RAW_FORMAT "%d %i %#p %l %u %g %r %z %a %m %c " RAW_B \
+ "%k %b " RAW_F "%N"
+#define LS_FORMAT "%Sp %l %Su %Sg %Z %Sm %N%SY"
+#define LSF_FORMAT "%Sp %l %Su %Sg %Z %Sm %N%T%SY"
+#define SHELL_FORMAT \
+ "st_dev=%d st_ino=%i st_mode=%#p st_nlink=%l " \
+ "st_uid=%u st_gid=%g st_rdev=%r st_size=%z " \
+ "st_atime=%a st_mtime=%m st_ctime=%c " SHELL_B \
+ "st_blksize=%k st_blocks=%b" SHELL_F
+#define LINUX_FORMAT \
+ " File: \"%N\"%n" \
+ " Size: %-11z FileType: %HT%n" \
+ " Mode: (%OMp%03OLp/%.10Sp) Uid: (%5u/%8Su) Gid: (%5g/%8Sg)%n" \
+ "Device: %Hd,%Ld Inode: %i Links: %l%n" \
+ "Access: %Sa%n" \
+ "Modify: %Sm%n" \
+ "Change: %Sc%n" \
+ " Birth: %SB"
+
+#define TIME_FORMAT "%b %e %T %Y"
+
+#define FLAG_POUND 0x01
+#define FLAG_SPACE 0x02
+#define FLAG_PLUS 0x04
+#define FLAG_ZERO 0x08
+#define FLAG_MINUS 0x10
+
+/*
+ * These format characters must all be unique, except the magic one.
+ */
+#define FMT_MAGIC '%'
+#define FMT_DOT '.'
+
+#define SIMPLE_NEWLINE 'n'
+#define SIMPLE_TAB 't'
+#define SIMPLE_PERCENT '%'
+#define SIMPLE_NUMBER '@'
+
+#define FMT_POUND '#'
+#define FMT_SPACE ' '
+#define FMT_PLUS '+'
+#define FMT_ZERO '0'
+#define FMT_MINUS '-'
+
+#define FMT_DECIMAL 'D'
+#define FMT_OCTAL 'O'
+#define FMT_UNSIGNED 'U'
+#define FMT_HEX 'X'
+#define FMT_FLOAT 'F'
+#define FMT_STRING 'S'
+
+#define FMTF_DECIMAL 0x01
+#define FMTF_OCTAL 0x02
+#define FMTF_UNSIGNED 0x04
+#define FMTF_HEX 0x08
+#define FMTF_FLOAT 0x10
+#define FMTF_STRING 0x20
+
+#define HIGH_PIECE 'H'
+#define MIDDLE_PIECE 'M'
+#define LOW_PIECE 'L'
+
+#define SHOW_realpath 'R'
+#define SHOW_st_dev 'd'
+#define SHOW_st_ino 'i'
+#define SHOW_st_mode 'p'
+#define SHOW_st_nlink 'l'
+#define SHOW_st_uid 'u'
+#define SHOW_st_gid 'g'
+#define SHOW_st_rdev 'r'
+#define SHOW_st_atime 'a'
+#define SHOW_st_mtime 'm'
+#define SHOW_st_ctime 'c'
+#define SHOW_st_btime 'B'
+#define SHOW_st_size 'z'
+#define SHOW_st_blocks 'b'
+#define SHOW_st_blksize 'k'
+#define SHOW_st_flags 'f'
+#define SHOW_st_gen 'v'
+#define SHOW_symlink 'Y'
+#define SHOW_filetype 'T'
+#define SHOW_filename 'N'
+#define SHOW_sizerdev 'Z'
+
+void usage(const char *);
+void output(const struct stat *, const char *,
+ const char *, int, int);
+int format1(const struct stat *, /* stat info */
+ const char *, /* the file name */
+ const char *, int, /* the format string itself */
+ char *, size_t, /* a place to put the output */
+ int, int, int, int, /* the parsed format */
+ int, int);
+int hex2byte(const char [2]);
+#if HAVE_STRUCT_STAT_ST_FLAGS
+char *xfflagstostr(unsigned long);
+#endif
+
+static const char *timefmt;
+static int linkfail;
+
+#define addchar(s, c, nl) \
+ do { \
+ (void)fputc((c), (s)); \
+ (*nl) = ((c) == '\n'); \
+ } while (0/*CONSTCOND*/)
+
+int
+main(int argc, char *argv[])
+{
+ struct stat st;
+ int ch, rc, errs, am_readlink;
+ int lsF, fmtchar, usestat, nfs_handle, fn, nonl, quiet;
+ const char *statfmt, *options, *synopsis;
+ char dname[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV;
+ fhandle_t fhnd;
+ const char *file;
+
+ am_readlink = 0;
+ lsF = 0;
+ fmtchar = '\0';
+ usestat = 0;
+ nfs_handle = 0;
+ nonl = 0;
+ quiet = 0;
+ linkfail = 0;
+ statfmt = NULL;
+ timefmt = NULL;
+
+ if (strcmp(getprogname(), "readlink") == 0) {
+ am_readlink = 1;
+ options = "fn";
+ synopsis = "[-fn] [file ...]";
+ statfmt = "%Y";
+ fmtchar = 'f';
+ quiet = 1;
+ } else {
+ options = "f:FHlLnqrst:x";
+ synopsis = "[-FLnq] [-f format | -l | -r | -s | -x] "
+ "[-t timefmt] [file|handle ...]";
+ }
+
+ while ((ch = getopt(argc, argv, options)) != -1)
+ switch (ch) {
+ case 'F':
+ lsF = 1;
+ break;
+ case 'H':
+ nfs_handle = 1;
+ break;
+ case 'L':
+ usestat = 1;
+ break;
+ case 'n':
+ nonl = 1;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'f':
+ if (am_readlink) {
+ statfmt = "%R";
+ break;
+ }
+ statfmt = optarg;
+ /* FALLTHROUGH */
+ case 'l':
+ case 'r':
+ case 's':
+ case 'x':
+ if (fmtchar != 0)
+ errx(1, "can't use format '%c' with '%c'",
+ fmtchar, ch);
+ fmtchar = ch;
+ break;
+ case 't':
+ timefmt = optarg;
+ break;
+ default:
+ usage(synopsis);
+ }
+
+ argc -= optind;
+ argv += optind;
+ fn = 1;
+
+ if (fmtchar == '\0') {
+ if (lsF)
+ fmtchar = 'l';
+ else {
+ fmtchar = 'f';
+ statfmt = DEF_FORMAT;
+ }
+ }
+
+ if (lsF && fmtchar != 'l')
+ errx(1, "can't use format '%c' with -F", fmtchar);
+
+ switch (fmtchar) {
+ case 'f':
+ /* statfmt already set */
+ break;
+ case 'l':
+ statfmt = lsF ? LSF_FORMAT : LS_FORMAT;
+ break;
+ case 'r':
+ statfmt = RAW_FORMAT;
+ break;
+ case 's':
+ statfmt = SHELL_FORMAT;
+ break;
+ case 'x':
+ statfmt = LINUX_FORMAT;
+ if (timefmt == NULL)
+ timefmt = "%c";
+ break;
+ default:
+ usage(synopsis);
+ /*NOTREACHED*/
+ }
+
+ if (timefmt == NULL)
+ timefmt = TIME_FORMAT;
+
+ errs = 0;
+ do {
+ if (argc == 0) {
+ if (fdevname_r(STDIN_FILENO, dname +
+ sizeof _PATH_DEV - 1, SPECNAMELEN) != NULL)
+ file = dname;
+ else
+ file = "(stdin)";
+ rc = fstat(STDIN_FILENO, &st);
+ } else {
+ int j;
+
+ file = argv[0];
+ if (nfs_handle) {
+ rc = 0;
+ bzero(&fhnd, sizeof(fhnd));
+ j = MIN(2 * sizeof(fhnd), strlen(file));
+ if ((j & 1) != 0) {
+ rc = -1;
+ } else {
+ while (j) {
+ rc = hex2byte(&file[j - 2]);
+ if (rc == -1)
+ break;
+ ((char*) &fhnd)[j / 2 - 1] = rc;
+ j -= 2;
+ }
+ }
+ if (rc == -1)
+ errno = EINVAL;
+ else
+ rc = fhstat(&fhnd, &st);
+
+ } else if (usestat) {
+ /*
+ * Try stat() and if it fails, fall back to
+ * lstat() just in case we're examining a
+ * broken symlink.
+ */
+ if ((rc = stat(file, &st)) == -1 &&
+ errno == ENOENT &&
+ (rc = lstat(file, &st)) == -1)
+ errno = ENOENT;
+ }
+ else
+ rc = lstat(file, &st);
+ }
+
+ if (rc == -1) {
+ errs = 1;
+ linkfail = 1;
+ if (!quiet)
+ warn("%s", file);
+ }
+ else
+ output(&st, file, statfmt, fn, nonl);
+
+ argv++;
+ argc--;
+ fn++;
+ } while (argc > 0);
+
+ return (am_readlink ? linkfail : errs);
+}
+
+#if HAVE_STRUCT_STAT_ST_FLAGS
+/*
+ * fflagstostr() wrapper that leaks only once
+ */
+char *
+xfflagstostr(unsigned long fflags)
+{
+ static char *str = NULL;
+
+ if (str != NULL)
+ free(str);
+
+ str = fflagstostr(fflags);
+ if (str == NULL)
+ err(1, "fflagstostr");
+ return (str);
+}
+#endif /* HAVE_STRUCT_STAT_ST_FLAGS */
+
+void
+usage(const char *synopsis)
+{
+
+ (void)fprintf(stderr, "usage: %s %s\n", getprogname(), synopsis);
+ exit(1);
+}
+
+/*
+ * Parses a format string.
+ */
+void
+output(const struct stat *st, const char *file,
+ const char *statfmt, int fn, int nonl)
+{
+ int flags, size, prec, ofmt, hilo, what;
+ char buf[PATH_MAX + 4 + 1];
+ const char *subfmt;
+ int nl, t, i;
+
+ nl = 1;
+ while (*statfmt != '\0') {
+
+ /*
+ * Non-format characters go straight out.
+ */
+ if (*statfmt != FMT_MAGIC) {
+ addchar(stdout, *statfmt, &nl);
+ statfmt++;
+ continue;
+ }
+
+ /*
+ * The current format "substring" starts here,
+ * and then we skip the magic.
+ */
+ subfmt = statfmt;
+ statfmt++;
+
+ /*
+ * Some simple one-character "formats".
+ */
+ switch (*statfmt) {
+ case SIMPLE_NEWLINE:
+ addchar(stdout, '\n', &nl);
+ statfmt++;
+ continue;
+ case SIMPLE_TAB:
+ addchar(stdout, '\t', &nl);
+ statfmt++;
+ continue;
+ case SIMPLE_PERCENT:
+ addchar(stdout, '%', &nl);
+ statfmt++;
+ continue;
+ case SIMPLE_NUMBER: {
+ char num[12], *p;
+
+ snprintf(num, sizeof(num), "%d", fn);
+ for (p = &num[0]; *p; p++)
+ addchar(stdout, *p, &nl);
+ statfmt++;
+ continue;
+ }
+ }
+
+ /*
+ * This must be an actual format string. Format strings are
+ * similar to printf(3) formats up to a point, and are of
+ * the form:
+ *
+ * % required start of format
+ * [-# +0] opt. format characters
+ * size opt. field width
+ * . opt. decimal separator, followed by
+ * prec opt. precision
+ * fmt opt. output specifier (string, numeric, etc.)
+ * sub opt. sub field specifier (high, middle, low)
+ * datum required field specifier (size, mode, etc)
+ *
+ * Only the % and the datum selector are required. All data
+ * have reasonable default output forms. The "sub" specifier
+ * only applies to certain data (mode, dev, rdev, filetype).
+ * The symlink output defaults to STRING, yet will only emit
+ * the leading " -> " if STRING is explicitly specified. The
+ * sizerdev datum will generate rdev output for character or
+ * block devices, and size output for all others.
+ */
+ flags = 0;
+ do {
+ if (*statfmt == FMT_POUND)
+ flags |= FLAG_POUND;
+ else if (*statfmt == FMT_SPACE)
+ flags |= FLAG_SPACE;
+ else if (*statfmt == FMT_PLUS)
+ flags |= FLAG_PLUS;
+ else if (*statfmt == FMT_ZERO)
+ flags |= FLAG_ZERO;
+ else if (*statfmt == FMT_MINUS)
+ flags |= FLAG_MINUS;
+ else
+ break;
+ statfmt++;
+ } while (1/*CONSTCOND*/);
+
+ size = -1;
+ if (isdigit((unsigned)*statfmt)) {
+ size = 0;
+ while (isdigit((unsigned)*statfmt)) {
+ size = (size * 10) + (*statfmt - '0');
+ statfmt++;
+ if (size < 0)
+ goto badfmt;
+ }
+ }
+
+ prec = -1;
+ if (*statfmt == FMT_DOT) {
+ statfmt++;
+
+ prec = 0;
+ while (isdigit((unsigned)*statfmt)) {
+ prec = (prec * 10) + (*statfmt - '0');
+ statfmt++;
+ if (prec < 0)
+ goto badfmt;
+ }
+ }
+
+#define fmtcase(x, y) case (y): (x) = (y); statfmt++; break
+#define fmtcasef(x, y, z) case (y): (x) = (z); statfmt++; break
+ switch (*statfmt) {
+ fmtcasef(ofmt, FMT_DECIMAL, FMTF_DECIMAL);
+ fmtcasef(ofmt, FMT_OCTAL, FMTF_OCTAL);
+ fmtcasef(ofmt, FMT_UNSIGNED, FMTF_UNSIGNED);
+ fmtcasef(ofmt, FMT_HEX, FMTF_HEX);
+ fmtcasef(ofmt, FMT_FLOAT, FMTF_FLOAT);
+ fmtcasef(ofmt, FMT_STRING, FMTF_STRING);
+ default:
+ ofmt = 0;
+ break;
+ }
+
+ switch (*statfmt) {
+ fmtcase(hilo, HIGH_PIECE);
+ fmtcase(hilo, MIDDLE_PIECE);
+ fmtcase(hilo, LOW_PIECE);
+ default:
+ hilo = 0;
+ break;
+ }
+
+ switch (*statfmt) {
+ fmtcase(what, SHOW_realpath);
+ fmtcase(what, SHOW_st_dev);
+ fmtcase(what, SHOW_st_ino);
+ fmtcase(what, SHOW_st_mode);
+ fmtcase(what, SHOW_st_nlink);
+ fmtcase(what, SHOW_st_uid);
+ fmtcase(what, SHOW_st_gid);
+ fmtcase(what, SHOW_st_rdev);
+ fmtcase(what, SHOW_st_atime);
+ fmtcase(what, SHOW_st_mtime);
+ fmtcase(what, SHOW_st_ctime);
+ fmtcase(what, SHOW_st_btime);
+ fmtcase(what, SHOW_st_size);
+ fmtcase(what, SHOW_st_blocks);
+ fmtcase(what, SHOW_st_blksize);
+ fmtcase(what, SHOW_st_flags);
+ fmtcase(what, SHOW_st_gen);
+ fmtcase(what, SHOW_symlink);
+ fmtcase(what, SHOW_filetype);
+ fmtcase(what, SHOW_filename);
+ fmtcase(what, SHOW_sizerdev);
+ default:
+ goto badfmt;
+ }
+#undef fmtcasef
+#undef fmtcase
+
+ t = format1(st,
+ file,
+ subfmt, statfmt - subfmt,
+ buf, sizeof(buf),
+ flags, size, prec, ofmt, hilo, what);
+
+ for (i = 0; i < t && i < (int)(sizeof(buf) - 1); i++)
+ addchar(stdout, buf[i], &nl);
+
+ continue;
+
+ badfmt:
+ errx(1, "%.*s: bad format",
+ (int)(statfmt - subfmt + 1), subfmt);
+ }
+
+ if (!nl && !nonl)
+ (void)fputc('\n', stdout);
+ (void)fflush(stdout);
+}
+
+/*
+ * Arranges output according to a single parsed format substring.
+ */
+int
+format1(const struct stat *st,
+ const char *file,
+ const char *fmt, int flen,
+ char *buf, size_t blen,
+ int flags, int size, int prec, int ofmt,
+ int hilo, int what)
+{
+ u_int64_t data;
+ char *stmp, lfmt[24], tmp[20];
+ const char *sdata;
+ char smode[12], sid[12], path[PATH_MAX + 4];
+ const struct timespec *tsp;
+ struct timespec ts;
+ struct tm *tm;
+ int l, small, formats;
+
+ tsp = NULL;
+ formats = 0;
+ small = 0;
+
+ /*
+ * First, pick out the data and tweak it based on hilo or
+ * specified output format (symlink output only).
+ */
+ switch (what) {
+ case SHOW_st_dev:
+ case SHOW_st_rdev:
+ small = (sizeof(st->st_dev) == 4);
+ data = (what == SHOW_st_dev) ? st->st_dev : st->st_rdev;
+#if HAVE_DEVNAME
+ sdata = devname(what == SHOW_st_dev ? st->st_dev :
+ st->st_rdev, S_ISCHR(st->st_mode) ? S_IFCHR :
+ (S_ISBLK(st->st_mode) ? S_IFBLK : 0));
+#endif /* HAVE_DEVNAME */
+ if (hilo == HIGH_PIECE) {
+ data = major(data);
+ hilo = 0;
+ }
+ else if (hilo == LOW_PIECE) {
+ data = minor((unsigned)data);
+ hilo = 0;
+ }
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+#if HAVE_DEVNAME
+ FMTF_STRING;
+#else /* HAVE_DEVNAME */
+ 0;
+#endif /* HAVE_DEVNAME */
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_ino:
+ small = (sizeof(st->st_ino) == 4);
+ data = st->st_ino;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_mode:
+ small = (sizeof(st->st_mode) == 4);
+ data = st->st_mode;
+ strmode(st->st_mode, smode);
+ stmp = smode;
+ l = strlen(stmp);
+ if (stmp[l - 1] == ' ')
+ stmp[--l] = '\0';
+ if (hilo == HIGH_PIECE) {
+ data >>= 12;
+ stmp += 1;
+ stmp[3] = '\0';
+ hilo = 0;
+ }
+ else if (hilo == MIDDLE_PIECE) {
+ data = (data >> 9) & 07;
+ stmp += 4;
+ stmp[3] = '\0';
+ hilo = 0;
+ }
+ else if (hilo == LOW_PIECE) {
+ data &= 0777;
+ stmp += 7;
+ stmp[3] = '\0';
+ hilo = 0;
+ }
+ sdata = stmp;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+ FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_OCTAL;
+ break;
+ case SHOW_st_nlink:
+ small = (sizeof(st->st_dev) == 4);
+ data = st->st_nlink;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_uid:
+ small = (sizeof(st->st_uid) == 4);
+ data = st->st_uid;
+ sdata = user_from_uid(st->st_uid, 1);
+ if (sdata == NULL) {
+ snprintf(sid, sizeof(sid), "(%ld)", (long)st->st_uid);
+ sdata = sid;
+ }
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+ FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_gid:
+ small = (sizeof(st->st_gid) == 4);
+ data = st->st_gid;
+ sdata = group_from_gid(st->st_gid, 1);
+ if (sdata == NULL) {
+ snprintf(sid, sizeof(sid), "(%ld)", (long)st->st_gid);
+ sdata = sid;
+ }
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+ FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_atime:
+ tsp = &st->st_atimespec;
+ /* FALLTHROUGH */
+ case SHOW_st_mtime:
+ if (tsp == NULL)
+ tsp = &st->st_mtimespec;
+ /* FALLTHROUGH */
+ case SHOW_st_ctime:
+ if (tsp == NULL)
+ tsp = &st->st_ctimespec;
+ /* FALLTHROUGH */
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ case SHOW_st_btime:
+ if (tsp == NULL)
+ tsp = &st->st_birthtimespec;
+#endif /* HAVE_STRUCT_STAT_ST_BIRTHTIME */
+ ts = *tsp; /* copy so we can muck with it */
+ small = (sizeof(ts.tv_sec) == 4);
+ data = ts.tv_sec;
+ tm = localtime(&ts.tv_sec);
+ if (tm == NULL) {
+ ts.tv_sec = 0;
+ tm = localtime(&ts.tv_sec);
+ }
+ (void)setlocale(LC_TIME, "");
+ (void)strftime(path, sizeof(path), timefmt, tm);
+ sdata = path;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+ FMTF_FLOAT | FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_DECIMAL;
+ break;
+ case SHOW_st_size:
+ small = (sizeof(st->st_size) == 4);
+ data = st->st_size;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_blocks:
+ small = (sizeof(st->st_blocks) == 4);
+ data = st->st_blocks;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+ case SHOW_st_blksize:
+ small = (sizeof(st->st_blksize) == 4);
+ data = st->st_blksize;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ case SHOW_st_flags:
+ small = (sizeof(st->st_flags) == 4);
+ data = st->st_flags;
+ sdata = xfflagstostr(st->st_flags);
+ if (*sdata == '\0')
+ sdata = "-";
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
+ FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+#endif /* HAVE_STRUCT_STAT_ST_FLAGS */
+#if HAVE_STRUCT_STAT_ST_GEN
+ case SHOW_st_gen:
+ small = (sizeof(st->st_gen) == 4);
+ data = st->st_gen;
+ sdata = NULL;
+ formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
+ if (ofmt == 0)
+ ofmt = FMTF_UNSIGNED;
+ break;
+#endif /* HAVE_STRUCT_STAT_ST_GEN */
+ case SHOW_realpath:
+ small = 0;
+ data = 0;
+ if (file == NULL) {
+ (void)strlcpy(path, "(stdin)", sizeof(path));
+ sdata = path;
+ } else {
+ snprintf(path, sizeof(path), " -> ");
+ if (realpath(file, path + 4) == NULL) {
+ linkfail = 1;
+ l = 0;
+ path[0] = '\0';
+ }
+ sdata = path + (ofmt == FMTF_STRING ? 0 : 4);
+ }
+
+ formats = FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_STRING;
+ break;
+ case SHOW_symlink:
+ small = 0;
+ data = 0;
+ if (S_ISLNK(st->st_mode)) {
+ snprintf(path, sizeof(path), " -> ");
+ l = readlink(file, path + 4, sizeof(path) - 4 - 1);
+ if (l == -1) {
+ linkfail = 1;
+ l = 0;
+ path[0] = '\0';
+ }
+ path[l + 4] = '\0';
+ sdata = path + (ofmt == FMTF_STRING ? 0 : 4);
+ }
+ else {
+ linkfail = 1;
+ sdata = "";
+ }
+ formats = FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_STRING;
+ break;
+ case SHOW_filetype:
+ small = 0;
+ data = 0;
+ sdata = "";
+ if (hilo == 0 || hilo == LOW_PIECE) {
+ switch (st->st_mode & S_IFMT) {
+ case S_IFIFO: sdata = "|"; break;
+ case S_IFDIR: sdata = "/"; break;
+ case S_IFREG:
+ if (st->st_mode &
+ (S_IXUSR | S_IXGRP | S_IXOTH))
+ sdata = "*";
+ break;
+ case S_IFLNK: sdata = "@"; break;
+ case S_IFSOCK: sdata = "="; break;
+#ifdef S_IFWHT
+ case S_IFWHT: sdata = "%"; break;
+#endif /* S_IFWHT */
+#ifdef S_IFDOOR
+ case S_IFDOOR: sdata = ">"; break;
+#endif /* S_IFDOOR */
+ }
+ hilo = 0;
+ }
+ else if (hilo == HIGH_PIECE) {
+ switch (st->st_mode & S_IFMT) {
+ case S_IFIFO: sdata = "Fifo File"; break;
+ case S_IFCHR: sdata = "Character Device"; break;
+ case S_IFDIR: sdata = "Directory"; break;
+ case S_IFBLK: sdata = "Block Device"; break;
+ case S_IFREG: sdata = "Regular File"; break;
+ case S_IFLNK: sdata = "Symbolic Link"; break;
+ case S_IFSOCK: sdata = "Socket"; break;
+#ifdef S_IFWHT
+ case S_IFWHT: sdata = "Whiteout File"; break;
+#endif /* S_IFWHT */
+#ifdef S_IFDOOR
+ case S_IFDOOR: sdata = "Door"; break;
+#endif /* S_IFDOOR */
+ default: sdata = "???"; break;
+ }
+ hilo = 0;
+ }
+ formats = FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_STRING;
+ break;
+ case SHOW_filename:
+ small = 0;
+ data = 0;
+ (void)strlcpy(path, file, sizeof(path));
+ sdata = path;
+ formats = FMTF_STRING;
+ if (ofmt == 0)
+ ofmt = FMTF_STRING;
+ break;
+ case SHOW_sizerdev:
+ if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+ char majdev[20], mindev[20];
+ int l1, l2;
+
+ l1 = format1(st,
+ file,
+ fmt, flen,
+ majdev, sizeof(majdev),
+ flags, size, prec,
+ ofmt, HIGH_PIECE, SHOW_st_rdev);
+ l2 = format1(st,
+ file,
+ fmt, flen,
+ mindev, sizeof(mindev),
+ flags, size, prec,
+ ofmt, LOW_PIECE, SHOW_st_rdev);
+ return (snprintf(buf, blen, "%.*s,%.*s",
+ l1, majdev, l2, mindev));
+ }
+ else {
+ return (format1(st,
+ file,
+ fmt, flen,
+ buf, blen,
+ flags, size, prec,
+ ofmt, 0, SHOW_st_size));
+ }
+ /*NOTREACHED*/
+ default:
+ errx(1, "%.*s: bad format", (int)flen, fmt);
+ }
+
+ /*
+ * If a subdatum was specified but not supported, or an output
+ * format was selected that is not supported, that's an error.
+ */
+ if (hilo != 0 || (ofmt & formats) == 0)
+ errx(1, "%.*s: bad format", (int)flen, fmt);
+
+ /*
+ * Assemble the format string for passing to printf(3).
+ */
+ lfmt[0] = '\0';
+ (void)strcat(lfmt, "%");
+ if (flags & FLAG_POUND)
+ (void)strcat(lfmt, "#");
+ if (flags & FLAG_SPACE)
+ (void)strcat(lfmt, " ");
+ if (flags & FLAG_PLUS)
+ (void)strcat(lfmt, "+");
+ if (flags & FLAG_MINUS)
+ (void)strcat(lfmt, "-");
+ if (flags & FLAG_ZERO)
+ (void)strcat(lfmt, "0");
+
+ /*
+ * Only the timespecs support the FLOAT output format, and that
+ * requires work that differs from the other formats.
+ */
+ if (ofmt == FMTF_FLOAT) {
+ /*
+ * Nothing after the decimal point, so just print seconds.
+ */
+ if (prec == 0) {
+ if (size != -1) {
+ (void)snprintf(tmp, sizeof(tmp), "%d", size);
+ (void)strcat(lfmt, tmp);
+ }
+ (void)strcat(lfmt, "lld");
+ return (snprintf(buf, blen, lfmt,
+ (long long)ts.tv_sec));
+ }
+
+ /*
+ * Unspecified precision gets all the precision we have:
+ * 9 digits.
+ */
+ if (prec == -1)
+ prec = 9;
+
+ /*
+ * Adjust the size for the decimal point and the digits
+ * that will follow.
+ */
+ size -= prec + 1;
+
+ /*
+ * Any leftover size that's legitimate will be used.
+ */
+ if (size > 0) {
+ (void)snprintf(tmp, sizeof(tmp), "%d", size);
+ (void)strcat(lfmt, tmp);
+ }
+ /* Seconds: time_t cast to long long. */
+ (void)strcat(lfmt, "lld");
+
+ /*
+ * The stuff after the decimal point always needs zero
+ * filling.
+ */
+ (void)strcat(lfmt, ".%0");
+
+ /*
+ * We can "print" at most nine digits of precision. The
+ * rest we will pad on at the end.
+ *
+ * Nanoseconds: long.
+ */
+ (void)snprintf(tmp, sizeof(tmp), "%dld", MIN(prec, 9));
+ (void)strcat(lfmt, tmp);
+
+ /*
+ * For precision of less than nine digits, trim off the
+ * less significant figures.
+ */
+ for (; prec < 9; prec++)
+ ts.tv_nsec /= 10;
+
+ /*
+ * Use the format, and then tack on any zeroes that
+ * might be required to make up the requested precision.
+ */
+ l = snprintf(buf, blen, lfmt, (long long)ts.tv_sec, ts.tv_nsec);
+ for (; prec > 9 && l < (int)blen; prec--, l++)
+ (void)strcat(buf, "0");
+ return (l);
+ }
+
+ /*
+ * Add on size and precision, if specified, to the format.
+ */
+ if (size != -1) {
+ (void)snprintf(tmp, sizeof(tmp), "%d", size);
+ (void)strcat(lfmt, tmp);
+ }
+ if (prec != -1) {
+ (void)snprintf(tmp, sizeof(tmp), ".%d", prec);
+ (void)strcat(lfmt, tmp);
+ }
+
+ /*
+ * String output uses the temporary sdata.
+ */
+ if (ofmt == FMTF_STRING) {
+ if (sdata == NULL)
+ errx(1, "%.*s: bad format", (int)flen, fmt);
+ (void)strcat(lfmt, "s");
+ return (snprintf(buf, blen, lfmt, sdata));
+ }
+
+ /*
+ * Ensure that sign extension does not cause bad looking output
+ * for some forms.
+ */
+ if (small && ofmt != FMTF_DECIMAL)
+ data = (u_int32_t)data;
+
+ /*
+ * The four "numeric" output forms.
+ */
+ (void)strcat(lfmt, "ll");
+ switch (ofmt) {
+ case FMTF_DECIMAL: (void)strcat(lfmt, "d"); break;
+ case FMTF_OCTAL: (void)strcat(lfmt, "o"); break;
+ case FMTF_UNSIGNED: (void)strcat(lfmt, "u"); break;
+ case FMTF_HEX: (void)strcat(lfmt, "x"); break;
+ }
+
+ return (snprintf(buf, blen, lfmt, data));
+}
+
+
+#define hex2nibble(c) (c <= '9' ? c - '0' : toupper(c) - 'A' + 10)
+int
+hex2byte(const char c[2]) {
+ if (!(ishexnumber(c[0]) && ishexnumber(c[1])))
+ return -1;
+ return (hex2nibble(c[0]) << 4) + hex2nibble(c[1]);
+}
diff --git a/usr.bin/stat/tests/Makefile b/usr.bin/stat/tests/Makefile
new file mode 100644
index 000000000000..d48648c55916
--- /dev/null
+++ b/usr.bin/stat/tests/Makefile
@@ -0,0 +1,4 @@
+ATF_TESTS_SH+= readlink_test
+ATF_TESTS_SH+= stat_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/stat/tests/Makefile.depend b/usr.bin/stat/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/stat/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/stat/tests/readlink_test.sh b/usr.bin/stat/tests/readlink_test.sh
new file mode 100755
index 000000000000..d0107e0d655e
--- /dev/null
+++ b/usr.bin/stat/tests/readlink_test.sh
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2017 Dell EMC
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case basic
+basic_head()
+{
+ atf_set "descr" "Verify that calling readlink without any flags " \
+ "prints out the symlink target for a file"
+}
+basic_body()
+{
+ atf_check ln -s foo bar
+ atf_check -o inline:'foo\n' readlink bar
+}
+
+atf_test_case f_flag
+f_flag_head()
+{
+ atf_set "descr" "Verify that calling readlink with -f will not emit " \
+ "an error message/exit with a non-zero code"
+}
+f_flag_body()
+{
+ atf_check touch A.file
+ atf_check ln -s nonexistent A.link
+ atf_check -o inline:"nonexistent\n" \
+ -s exit:1 readlink A.file A.link
+ atf_check -o inline:"$(realpath A.file)\n$PWD/nonexistent\n" \
+ -s exit:1 readlink -f A.file A.link
+}
+
+atf_test_case n_flag
+n_flag_head()
+{
+}
+n_flag_body()
+{
+ atf_check ln -s nonexistent.A A
+ atf_check ln -s nonexistent.B B
+ atf_check -o 'inline:nonexistent.A\nnonexistent.B\n' readlink A B
+ atf_check -o 'inline:nonexistent.Anonexistent.B' readlink -n A B
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case f_flag
+ atf_add_test_case n_flag
+}
diff --git a/usr.bin/stat/tests/stat_test.sh b/usr.bin/stat/tests/stat_test.sh
new file mode 100755
index 000000000000..e75fd0c56490
--- /dev/null
+++ b/usr.bin/stat/tests/stat_test.sh
@@ -0,0 +1,245 @@
+#
+# Copyright (c) 2017 Dell EMC
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case F_flag
+F_flag_head()
+{
+ atf_set "descr" "Verify the output format for -F"
+}
+F_flag_body()
+{
+ # TODO: socket, whiteout file
+ atf_check touch a
+ atf_check mkdir b
+ atf_check install -m 0777 /dev/null c
+ atf_check ln -s a d
+ atf_check mkfifo f
+
+ atf_check -o match:'.* a' stat -Fn a
+ atf_check -o match:'.* b/' stat -Fn b
+ atf_check -o match:'.* c\*' stat -Fn c
+ atf_check -o match:'.* d@' stat -Fn d
+ atf_check -o match:'.* f\|' stat -Fn f
+}
+
+atf_test_case l_flag
+l_flag_head()
+{
+ atf_set "descr" "Verify the output format for -l"
+}
+l_flag_body()
+{
+ atf_check touch a
+ atf_check ln a b
+ atf_check ln -s a c
+ atf_check mkdir d
+
+ paths="a b c d"
+
+ ls_out=ls.output
+ stat_out=stat.output
+
+ # NOTE:
+ # - Even though stat -l claims to be equivalent to `ls -lT`, the
+ # whitespace is a bit more liberal in the `ls -lT` output.
+ # - `ls -ldT` is used to not recursively list the contents of
+ # directories.
+ for path in $paths; do
+ atf_check -o save:$ls_out ls -ldT $path
+ cat $ls_out
+ atf_check -o save:$stat_out stat -l $path
+ cat $stat_out
+ echo "Comparing normalized whitespace"
+ atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $ls_out
+ atf_check sed -i '' -E -e 's/[[:space:]]+/ /g' $stat_out
+ atf_check cmp $ls_out $stat_out
+ done
+}
+
+atf_test_case n_flag
+n_flag_head()
+{
+ atf_set "descr" "Verify that -n suppresses newline output for lines"
+}
+n_flag_body()
+{
+ atf_check touch a b
+ atf_check -o inline:"$(stat a | tr -d '\n')" stat -n a
+ atf_check -o inline:"$(stat a b | tr -d '\n')" stat -n a b
+}
+
+atf_test_case q_flag
+q_flag_head()
+{
+ atf_set "descr" "Verify that -q suppresses error messages from l?stat(2)"
+}
+q_flag_body()
+{
+ ln -s nonexistent broken-link
+
+ atf_check -s exit:1 stat -q nonexistent
+ atf_check -s exit:1 stat -q nonexistent
+ atf_check -o not-empty stat -q broken-link
+ atf_check -o not-empty stat -qL broken-link
+}
+
+atf_test_case r_flag
+r_flag_head()
+{
+ atf_set "descr" "Verify that -r displays output in 'raw mode'"
+}
+r_flag_body()
+{
+ atf_check touch a
+ # TODO: add more thorough checks.
+ atf_check -o not-empty stat -r a
+}
+
+atf_test_case s_flag
+s_flag_head()
+{
+ atf_set "descr" "Verify the output format for -s"
+}
+s_flag_body()
+{
+ atf_check touch a
+ atf_check ln a b
+ atf_check ln -s a c
+ atf_check mkdir d
+
+ paths="a b c d"
+
+ # The order/name of each of the fields is specified by stat(1) manpage.
+ fields="st_dev st_ino st_mode st_nlink"
+ fields="$fields st_uid st_gid st_rdev st_size"
+ fields="$fields st_uid st_gid st_mode"
+ fields="$fields st_atime st_mtime st_ctime st_birthtime"
+ fields="$fields st_blksize st_blocks st_flags"
+
+ # NOTE: the following...
+ # - ... relies on set -eu to ensure that the fields are set, as
+ # documented, in stat(1).
+ # - ... uses a subshell to ensure that the eval'ed variables don't
+ # pollute the next iteration's behavior.
+ for path in $paths; do
+ (
+ set -eu
+ eval $(stat -s $path)
+ for field in $fields; do
+ eval "$field=\$$field"
+ done
+ ) || atf_fail 'One or more fields not set by stat(1)'
+ done
+}
+
+atf_test_case t_flag
+t_flag_head()
+{
+ atf_set "descr" "Verify the output format for -t"
+}
+
+t_flag_body()
+{
+ atf_check touch foo
+ atf_check touch -d 1970-01-01T00:00:42 foo
+ atf_check -o inline:'42\n' \
+ stat -t '%s' -f '%a' foo
+ atf_check -o inline:'1970-01-01 00:00:42\n' \
+ stat -t '%F %H:%M:%S' -f '%Sa' foo
+}
+
+x_output_date()
+{
+ local date_format='%a %b %e %H:%M:%S %Y'
+
+ stat -t "$date_format" "$@"
+}
+
+x_output()
+{
+ local path=$1; shift
+
+ local atime_s=$(x_output_date -f '%Sa' $path)
+ local btime_s=$(x_output_date -f '%SB' $path)
+ local ctime_s=$(x_output_date -f '%Sc' $path)
+ local devid=$(stat -f '%Hd,%Ld' $path)
+ local file_type_s=$(stat -f '%HT' $path)
+ local gid=$(stat -f '%5g' $path)
+ local groupname=$(stat -f '%8Sg' $path)
+ local inode=$(stat -f '%i' $path)
+ local mode=$(stat -f '%Mp%Lp' $path)
+ local mode_s=$(stat -f '%Sp' $path)
+ local mtime_s=$(x_output_date -f '%Sm' $path)
+ local nlink=$(stat -f '%l' $path)
+ local size_a=$(stat -f '%-11z' $path)
+ local uid=$(stat -f '%5u' $path)
+ local username=$(stat -f '%8Su' $path)
+
+ cat <<EOF
+ File: "$path"
+ Size: $size_a FileType: $file_type_s
+ Mode: ($mode/$mode_s) Uid: ($uid/$username) Gid: ($gid/$groupname)
+Device: $devid Inode: $inode Links: $nlink
+Access: $atime_s
+Modify: $mtime_s
+Change: $ctime_s
+ Birth: $btime_s
+EOF
+}
+
+atf_test_case x_flag
+x_flag_head()
+{
+ atf_set "descr" "Verify the output format for -x"
+}
+x_flag_body()
+{
+ atf_check touch a
+ atf_check ln a b
+ atf_check ln -s a c
+ atf_check mkdir d
+
+ paths="a b c d"
+
+ for path in $paths; do
+ atf_check -o "inline:$(x_output $path)\n" stat -x $path
+ done
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case F_flag
+ #atf_add_test_case H_flag
+ #atf_add_test_case L_flag
+ #atf_add_test_case f_flag
+ atf_add_test_case l_flag
+ atf_add_test_case n_flag
+ atf_add_test_case q_flag
+ atf_add_test_case r_flag
+ atf_add_test_case s_flag
+ atf_add_test_case t_flag
+ atf_add_test_case x_flag
+}
diff --git a/usr.bin/stdbuf/Makefile b/usr.bin/stdbuf/Makefile
new file mode 100644
index 000000000000..538cea76c519
--- /dev/null
+++ b/usr.bin/stdbuf/Makefile
@@ -0,0 +1,4 @@
+PROG= stdbuf
+SRCS= stdbuf.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/stdbuf/Makefile.depend b/usr.bin/stdbuf/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/stdbuf/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/stdbuf/stdbuf.1 b/usr.bin/stdbuf/stdbuf.1
new file mode 100644
index 000000000000..670c369df112
--- /dev/null
+++ b/usr.bin/stdbuf/stdbuf.1
@@ -0,0 +1,114 @@
+.\" Copyright (c) 2012 Jeremie Le Hen <jlh@FreeBSD.org>
+.\" 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 and documentation 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 AUTHOR 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 AUTHOR 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 April 28, 2012
+.Dt STDBUF 1
+.Os
+.Sh NAME
+.Nm stdbuf
+.Nd change standard streams initial buffering
+.Sh SYNOPSIS
+.Nm
+.Op Fl e Ar bufdef
+.Op Fl i Ar bufdef
+.Op Fl o Ar bufdef
+.Op Ar command Op ...
+.Sh DESCRIPTION
+.Nm
+is used to change the initial buffering of standard input,
+standard output and/or standard error streams for
+.Ar command .
+It relies on
+.Xr libstdbuf 3
+which is loaded and configured by
+.Nm
+through environment variables.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl e Ar bufdef
+Set initial buffering of the standard error stream for
+.Ar command
+as defined by
+.Ar bufdef
+.Pq see Sx BUFFER DEFINITION .
+.It Fl i Ar bufdef
+Set initial buffering of the standard input stream for
+.Ar command
+as defined by
+.Ar bufdef
+.Pq see Sx BUFFER DEFINITION .
+.It Fl o Ar bufdef
+Set initial buffering of the standard output stream for
+.Ar command
+as defined by
+.Ar bufdef
+.Pq see Sx BUFFER DEFINITION .
+.El
+.Sh BUFFER DEFINITION
+Buffer definition is the same as in
+.Xr libstdbuf 3 :
+.Bl -tag -width size -offset indent
+.It Qq 0
+unbuffered
+.It Qq L
+line buffered
+.It Qq B
+fully buffered with the default buffer size
+.It Ar size
+fully buffered with a buffer of
+.Ar size
+bytes (suffixes 'k', 'M' and 'G' are accepted)
+.El
+.Sh EXAMPLES
+In the following example, the stdout stream of the
+.Xr awk 1
+command
+will be fully buffered by default because it does not refer
+to a terminal.
+.Nm
+is used to force it to be line-buffered so
+.Xr vmstat 8 Ns 's
+output will not stall until the full buffer fills.
+.Bd -literal -offset indent
+# vmstat 1 | stdbuf -o L awk '$2 > 1 || $3 > 1' | cat -n
+.Ed
+.Sh SEE ALSO
+.Xr libstdbuf 3 ,
+.Xr setvbuf 3
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 8.4 .
+.Sh AUTHORS
+.An -nosplit
+The original idea of the
+.Nm
+command comes from
+.An Padraig Brady
+who implemented it in the GNU coreutils.
+.An Jeremie Le Hen
+implemented it on
+.Fx .
diff --git a/usr.bin/stdbuf/stdbuf.c b/usr.bin/stdbuf/stdbuf.c
new file mode 100644
index 000000000000..6b09bb6149f5
--- /dev/null
+++ b/usr.bin/stdbuf/stdbuf.c
@@ -0,0 +1,108 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2012 Jeremie Le Hen <jlh@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define LIBSTDBUF "/usr/lib/libstdbuf.so"
+#define LIBSTDBUF32 "/usr/lib32/libstdbuf.so"
+
+static int
+appendenv(const char *key, const char *value)
+{
+ char *curval, *newpair;
+ int ret;
+
+ curval = getenv(key);
+ if (curval == NULL)
+ ret = asprintf(&newpair, "%s=%s", key, value);
+ else
+ ret = asprintf(&newpair, "%s=%s:%s", key, curval, value);
+ if (ret > 0)
+ ret = putenv(newpair);
+ if (ret < 0)
+ warn("Failed to set environment variable: %s", key);
+ return (ret);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: stdbuf [-e 0|L|B|<sz>] [-i 0|L|B|<sz>] [-o 0|L|B|<sz>] "
+ "<cmd> [args ...]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *ibuf, *obuf, *ebuf;
+ int i;
+
+ ibuf = obuf = ebuf = NULL;
+ while ((i = getopt(argc, argv, "e:i:o:")) != -1) {
+ switch (i) {
+ case 'e':
+ ebuf = optarg;
+ break;
+ case 'i':
+ ibuf = optarg;
+ break;
+ case 'o':
+ obuf = optarg;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0)
+ exit(0);
+
+ if (ibuf != NULL && setenv("_STDBUF_I", ibuf, 1) == -1)
+ warn("Failed to set environment variable: %s=%s",
+ "_STDBUF_I", ibuf);
+ if (obuf != NULL && setenv("_STDBUF_O", obuf, 1) == -1)
+ warn("Failed to set environment variable: %s=%s",
+ "_STDBUF_O", obuf);
+ if (ebuf != NULL && setenv("_STDBUF_E", ebuf, 1) == -1)
+ warn("Failed to set environment variable: %s=%s",
+ "_STDBUF_E", ebuf);
+
+ appendenv("LD_PRELOAD", LIBSTDBUF);
+ appendenv("LD_32_PRELOAD", LIBSTDBUF32);
+
+ execvp(argv[0], argv);
+ err(2, "%s", argv[0]);
+}
diff --git a/usr.bin/strings/Makefile b/usr.bin/strings/Makefile
new file mode 100644
index 000000000000..8e2572810947
--- /dev/null
+++ b/usr.bin/strings/Makefile
@@ -0,0 +1,19 @@
+.include <src.opts.mk>
+
+ELFTCDIR= ${SRCTOP}/contrib/elftoolchain
+
+.PATH: ${ELFTCDIR}/strings
+
+PROG= strings
+
+LIBADD= elftc elf
+
+.if ${MK_CASPER} != "no" && !defined(BOOTSTRAPPING) && !defined(NXB_TARGET)
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/strings/Makefile.depend b/usr.bin/strings/Makefile.depend
new file mode 100644
index 000000000000..fff85220223b
--- /dev/null
+++ b/usr.bin/strings/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libelf \
+ lib/libelftc \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/strings/Makefile.depend.options b/usr.bin/strings/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/strings/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/su/Makefile b/usr.bin/su/Makefile
new file mode 100644
index 000000000000..f6d95defa195
--- /dev/null
+++ b/usr.bin/su/Makefile
@@ -0,0 +1,16 @@
+.include <src.opts.mk>
+
+PROG= su
+
+LIBADD= util pam
+
+.if ${MK_AUDIT} != "no"
+CFLAGS+= -DUSE_BSM_AUDIT
+LIBADD+= bsm
+.endif
+
+BINOWN= root
+BINMODE=4555
+PRECIOUSPROG=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/su/Makefile.depend b/usr.bin/su/Makefile.depend
new file mode 100644
index 000000000000..dcba122adac8
--- /dev/null
+++ b/usr.bin/su/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libpam/libpam \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/su/Makefile.depend.options b/usr.bin/su/Makefile.depend.options
new file mode 100644
index 000000000000..87c69612fea8
--- /dev/null
+++ b/usr.bin/su/Makefile.depend.options
@@ -0,0 +1,5 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= AUDIT
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/su/su.1 b/usr.bin/su/su.1
new file mode 100644
index 000000000000..ba4767ff8e1c
--- /dev/null
+++ b/usr.bin/su/su.1
@@ -0,0 +1,247 @@
+.\" Copyright (c) 1988, 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd March 26, 2020
+.Dt SU 1
+.Os
+.Sh NAME
+.Nm su
+.Nd substitute user identity
+.Sh SYNOPSIS
+.Nm
+.Op Fl
+.Op Fl c Ar class
+.Op Fl flms
+.Op Ar login Op Ar args
+.Sh DESCRIPTION
+The
+.Nm
+utility requests appropriate user credentials via PAM
+and switches to that user ID
+(the default user is the superuser).
+A shell is then executed.
+.Pp
+PAM is used to set the policy
+.Xr su 1
+will use.
+In particular, by default only users in the
+.Dq Li wheel
+group can switch to UID 0
+.Pq Dq Li root .
+This group requirement may be changed by modifying the
+.Dq Li pam_group
+section of
+.Pa /etc/pam.d/su .
+See
+.Xr pam_group 8
+for details on how to modify this setting.
+.Pp
+By default, the environment is unmodified with the exception of
+.Ev USER ,
+.Ev HOME ,
+and
+.Ev SHELL .
+.Ev HOME
+and
+.Ev SHELL
+are set to the target login's default values.
+.Ev USER
+is set to the target login, unless the target login has a user ID of 0,
+in which case it is unmodified.
+The invoked shell is the one belonging to the target login.
+This is the traditional behavior of
+.Nm .
+Resource limits and session priority applicable to the original user's
+login class (see
+.Xr login.conf 5 )
+are also normally retained unless the target login has a user ID of 0.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c Ar class
+Use the settings of the specified login class.
+The login class must be defined in
+.Xr login.conf 5 .
+Only allowed for the super-user.
+.It Fl f
+If the invoked shell is
+.Xr csh 1 ,
+this option prevents it from reading the
+.Dq Pa .cshrc
+file.
+.It Fl l
+Simulate a full login.
+The environment is discarded except for
+.Ev HOME ,
+.Ev SHELL ,
+.Ev PATH ,
+.Ev TERM ,
+and
+.Ev USER .
+.Ev HOME
+and
+.Ev SHELL
+are modified as above.
+.Ev USER
+is set to the target login.
+.Ev PATH
+is set to
+.Dq Pa /bin:/usr/bin .
+.Ev TERM
+is imported from your current environment.
+Environment variables may be set or overridden from the login class
+capabilities database according to the class of the target login.
+The invoked shell is the target login's, and
+.Nm
+will change directory to the target login's home directory.
+Resource limits and session priority are modified to that for the
+target account's login class.
+.It Fl
+(no letter) The same as
+.Fl l .
+.It Fl m
+Leave the environment unmodified.
+The invoked shell is your login shell, and no directory changes are made.
+As a security precaution, if the target user's shell is a non-standard
+shell (as defined by
+.Xr getusershell 3 )
+and the caller's real uid is
+non-zero,
+.Nm
+will fail.
+.It Fl s
+Set the MAC label to the user's default label as part of the user
+credential setup.
+Setting the MAC label may fail if the MAC label of the invoking process
+is not sufficient to transition to the user's default MAC label.
+If the label cannot be set,
+.Nm
+will fail.
+.El
+.Pp
+The
+.Fl l
+(or
+.Fl )
+and
+.Fl m
+options are mutually exclusive; the last one specified
+overrides any previous ones.
+.Pp
+If the optional
+.Ar args
+are provided on the command line, they are passed to the login shell of
+the target login.
+Note that all command line arguments before the target login name are
+processed by
+.Nm
+itself, everything after the target login name gets passed to the login
+shell.
+.Pp
+By default (unless the prompt is reset by a startup file) the super-user
+prompt is set to
+.Dq Sy \&#
+to remind one of its awesome power.
+.Sh ENVIRONMENT
+Environment variables used by
+.Nm :
+.Bl -tag -width HOME
+.It Ev HOME
+Default home directory of real user ID unless modified as
+specified above.
+.It Ev PATH
+Default search path of real user ID unless modified as specified above.
+.It Ev TERM
+Provides terminal type which may be retained for the substituted
+user ID.
+.It Ev USER
+The user ID is always the effective ID (the target user ID) after an
+.Nm
+unless the user ID is 0 (root).
+.El
+.Sh FILES
+.Bl -tag -width "/etc/pam.d/su" -compact
+.It Pa /etc/pam.d/su
+PAM configuration for
+.Nm .
+.El
+.Sh EXAMPLES
+.Bl -tag -width 5n -compact
+.It Li "su -m operator -c poweroff"
+Starts a shell as user
+.Li operator ,
+and runs the command
+.Li poweroff .
+You will be asked for operator's password unless your real UID is 0.
+Note that the
+.Fl m
+option is required since user
+.Dq operator
+does not have a valid shell by default.
+In this example,
+.Fl c
+is passed to the shell of the user
+.Dq operator ,
+and is not interpreted as an argument to
+.Nm .
+.It Li "su -m operator -c 'shutdown -p now'"
+Same as above, but the target command consists of more than a
+single word and hence is quoted for use with the
+.Fl c
+option being passed to the shell.
+(Most shells expect the argument to
+.Fl c
+to be a single word).
+.It Li "su -m -c staff operator -c 'shutdown -p now'"
+Same as above, but the target command is run with the resource limits of
+the login class
+.Dq staff .
+Note: in this example, the first
+.Fl c
+option applies to
+.Nm
+while the second is an argument to the shell being invoked.
+.It Li "su -l foo"
+Simulate a login for user foo.
+.It Li "su - foo"
+Same as above.
+.It Li "su -"
+Simulate a login for root.
+.El
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr sh 1 ,
+.Xr group 5 ,
+.Xr login.conf 5 ,
+.Xr passwd 5 ,
+.Xr environ 7 ,
+.Xr pam_group 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c
new file mode 100644
index 000000000000..312a248b11f5
--- /dev/null
+++ b/usr.bin/su/su.c
@@ -0,0 +1,629 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2002, 2005 Networks Associates Technologies, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+/*-
+ * Copyright (c) 1988, 1993, 1994
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#ifdef USE_BSM_AUDIT
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <login_cap.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+
+#define PAM_END() do { \
+ int local_ret; \
+ if (pamh != NULL) { \
+ local_ret = pam_setcred(pamh, PAM_DELETE_CRED); \
+ if (local_ret != PAM_SUCCESS) \
+ syslog(LOG_ERR, "pam_setcred: %s", \
+ pam_strerror(pamh, local_ret)); \
+ if (asthem) { \
+ local_ret = pam_close_session(pamh, 0); \
+ if (local_ret != PAM_SUCCESS) \
+ syslog(LOG_ERR, "pam_close_session: %s",\
+ pam_strerror(pamh, local_ret)); \
+ } \
+ local_ret = pam_end(pamh, local_ret); \
+ if (local_ret != PAM_SUCCESS) \
+ syslog(LOG_ERR, "pam_end: %s", \
+ pam_strerror(pamh, local_ret)); \
+ } \
+} while (0)
+
+
+#define PAM_SET_ITEM(what, item) do { \
+ int local_ret; \
+ local_ret = pam_set_item(pamh, what, item); \
+ if (local_ret != PAM_SUCCESS) { \
+ syslog(LOG_ERR, "pam_set_item(" #what "): %s", \
+ pam_strerror(pamh, local_ret)); \
+ errx(1, "pam_set_item(" #what "): %s", \
+ pam_strerror(pamh, local_ret)); \
+ /* NOTREACHED */ \
+ } \
+} while (0)
+
+enum tristate { UNSET, YES, NO };
+
+static pam_handle_t *pamh = NULL;
+static char **environ_pam;
+
+static char *ontty(void);
+static int chshell(const char *);
+static void usage(void) __dead2;
+static void export_pam_environment(void);
+static int ok_to_export(const char *);
+
+extern char **environ;
+
+int
+main(int argc, char *argv[])
+{
+ static char *cleanenv;
+ struct passwd *pwd = NULL;
+ struct pam_conv conv = { openpam_ttyconv, NULL };
+ enum tristate iscsh;
+ login_cap_t *lc;
+ union {
+ const char **a;
+ char * const *b;
+ } np;
+ uid_t ruid;
+ pid_t child_pid, child_pgrp, pid;
+ int asme, ch, asthem, fastlogin, prio, i, retcode,
+ statusp, setmaclabel;
+ u_int setwhat;
+ char *username, *class, shellbuf[MAXPATHLEN];
+ const char *p, *user, *shell, *mytty, **nargv;
+ const void *v;
+ struct sigaction sa, sa_int, sa_quit, sa_pipe;
+ int temp, fds[2];
+#ifdef USE_BSM_AUDIT
+ const char *aerr;
+ au_id_t auid;
+#endif
+
+ p = shell = class = cleanenv = NULL;
+ asme = asthem = fastlogin = statusp = 0;
+ user = "root";
+ iscsh = UNSET;
+ setmaclabel = 0;
+
+ while ((ch = getopt(argc, argv, "-flmsc:")) != -1)
+ switch ((char)ch) {
+ case 'f':
+ fastlogin = 1;
+ break;
+ case '-':
+ case 'l':
+ asme = 0;
+ asthem = 1;
+ break;
+ case 'm':
+ asme = 1;
+ asthem = 0;
+ break;
+ case 's':
+ setmaclabel = 1;
+ break;
+ case 'c':
+ class = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ if (optind < argc)
+ user = argv[optind++];
+
+ if (user == NULL)
+ usage();
+ /* NOTREACHED */
+
+ /*
+ * Try to provide more helpful debugging output if su(1) is running
+ * non-setuid, or was run from a file system not mounted setuid.
+ */
+ if (geteuid() != 0)
+ errx(1, "not running setuid");
+
+#ifdef USE_BSM_AUDIT
+ if (getauid(&auid) < 0 && errno != ENOSYS) {
+ syslog(LOG_AUTH | LOG_ERR, "getauid: %s", strerror(errno));
+ errx(1, "Permission denied");
+ }
+#endif
+ if (strlen(user) > MAXLOGNAME - 1) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid,
+ EPERM, 1, "username too long: '%s'", user))
+ errx(1, "Permission denied");
+#endif
+ errx(1, "username too long");
+ }
+
+ nargv = malloc(sizeof(char *) * (size_t)(argc + 4));
+ if (nargv == NULL)
+ errx(1, "malloc failure");
+
+ nargv[argc + 3] = NULL;
+ for (i = argc; i >= optind; i--)
+ nargv[i + 3] = argv[i];
+ np.a = &nargv[i + 3];
+
+ argv += optind;
+
+ errno = 0;
+ prio = getpriority(PRIO_PROCESS, 0);
+ if (errno)
+ prio = 0;
+
+ setpriority(PRIO_PROCESS, 0, -2);
+ openlog("su", LOG_CONS, LOG_AUTH);
+
+ /* get current login name, real uid and shell */
+ ruid = getuid();
+ username = getlogin();
+ if (username != NULL)
+ pwd = getpwnam(username);
+ if (pwd == NULL || pwd->pw_uid != ruid)
+ pwd = getpwuid(ruid);
+ if (pwd == NULL) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, EPERM, 1,
+ "unable to determine invoking subject: '%s'", username))
+ errx(1, "Permission denied");
+#endif
+ errx(1, "who are you?");
+ }
+
+ username = strdup(pwd->pw_name);
+ if (username == NULL)
+ err(1, "strdup failure");
+
+ if (asme) {
+ if (pwd->pw_shell != NULL && *pwd->pw_shell != '\0') {
+ /* must copy - pwd memory is recycled */
+ strlcpy(shellbuf, pwd->pw_shell,
+ sizeof(shellbuf));
+ shell = shellbuf;
+ }
+ else {
+ shell = _PATH_BSHELL;
+ iscsh = NO;
+ }
+ }
+
+ /* Do the whole PAM startup thing */
+ retcode = pam_start("su", user, &conv, &pamh);
+ if (retcode != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, retcode));
+ errx(1, "pam_start: %s", pam_strerror(pamh, retcode));
+ }
+
+ PAM_SET_ITEM(PAM_RUSER, username);
+
+ mytty = ttyname(STDERR_FILENO);
+ if (!mytty)
+ mytty = "tty";
+ PAM_SET_ITEM(PAM_TTY, mytty);
+
+ retcode = pam_authenticate(pamh, 0);
+ if (retcode != PAM_SUCCESS) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, EPERM, 1, "bad su %s to %s on %s",
+ username, user, mytty))
+ errx(1, "Permission denied");
+#endif
+ syslog(LOG_AUTH|LOG_WARNING, "BAD SU %s to %s on %s",
+ username, user, mytty);
+ errx(1, "Sorry");
+ }
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, 0, 0, "successful authentication"))
+ errx(1, "Permission denied");
+#endif
+ retcode = pam_get_item(pamh, PAM_USER, &v);
+ if (retcode == PAM_SUCCESS)
+ user = v;
+ else
+ syslog(LOG_ERR, "pam_get_item(PAM_USER): %s",
+ pam_strerror(pamh, retcode));
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, EPERM, 1,
+ "unknown subject: %s", user))
+ errx(1, "Permission denied");
+#endif
+ errx(1, "unknown login: %s", user);
+ }
+
+ retcode = pam_acct_mgmt(pamh, 0);
+ if (retcode == PAM_NEW_AUTHTOK_REQD) {
+ retcode = pam_chauthtok(pamh,
+ PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (retcode != PAM_SUCCESS) {
+#ifdef USE_BSM_AUDIT
+ aerr = pam_strerror(pamh, retcode);
+ if (aerr == NULL)
+ aerr = "Unknown PAM error";
+ if (audit_submit(AUE_su, auid, EPERM, 1,
+ "pam_chauthtok: %s", aerr))
+ errx(1, "Permission denied");
+#endif
+ syslog(LOG_ERR, "pam_chauthtok: %s",
+ pam_strerror(pamh, retcode));
+ errx(1, "Sorry");
+ }
+ }
+ if (retcode != PAM_SUCCESS) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, EPERM, 1, "pam_acct_mgmt: %s",
+ pam_strerror(pamh, retcode)))
+ errx(1, "Permission denied");
+#endif
+ syslog(LOG_ERR, "pam_acct_mgmt: %s",
+ pam_strerror(pamh, retcode));
+ errx(1, "Sorry");
+ }
+
+ /* get target login information */
+ if (class == NULL)
+ lc = login_getpwclass(pwd);
+ else {
+ if (ruid != 0) {
+#ifdef USE_BSM_AUDIT
+ if (audit_submit(AUE_su, auid, EPERM, 1,
+ "only root may use -c"))
+ errx(1, "Permission denied");
+#endif
+ errx(1, "only root may use -c");
+ }
+ lc = login_getclass(class);
+ if (lc == NULL)
+ err(1, "login_getclass");
+ if (lc->lc_class == NULL || strcmp(class, lc->lc_class) != 0)
+ errx(1, "unknown class: %s", class);
+ }
+
+ /* if asme and non-standard target shell, must be root */
+ if (asme) {
+ if (ruid != 0 && !chshell(pwd->pw_shell))
+ errx(1, "permission denied (shell)");
+ }
+ else if (pwd->pw_shell && *pwd->pw_shell) {
+ shell = pwd->pw_shell;
+ iscsh = UNSET;
+ }
+ else {
+ shell = _PATH_BSHELL;
+ iscsh = NO;
+ }
+
+ /* if we're forking a csh, we want to slightly muck the args */
+ if (iscsh == UNSET) {
+ p = strrchr(shell, '/');
+ if (p)
+ ++p;
+ else
+ p = shell;
+ iscsh = strcmp(p, "csh") ? (strcmp(p, "tcsh") ? NO : YES) : YES;
+ }
+ setpriority(PRIO_PROCESS, 0, prio);
+
+ /*
+ * PAM modules might add supplementary groups in pam_setcred(), so
+ * initialize them first.
+ */
+ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) < 0)
+ err(1, "setusercontext");
+
+ retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+ if (retcode != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_setcred: %s",
+ pam_strerror(pamh, retcode));
+ errx(1, "failed to establish credentials.");
+ }
+ if (asthem) {
+ retcode = pam_open_session(pamh, 0);
+ if (retcode != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_open_session: %s",
+ pam_strerror(pamh, retcode));
+ errx(1, "failed to open session.");
+ }
+ }
+
+ /*
+ * We must fork() before setuid() because we need to call
+ * pam_setcred(pamh, PAM_DELETE_CRED) as root.
+ */
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, &sa_int);
+ sigaction(SIGQUIT, &sa, &sa_quit);
+ sigaction(SIGPIPE, &sa, &sa_pipe);
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGTSTP, &sa, NULL);
+ statusp = 1;
+ if (pipe(fds) == -1) {
+ PAM_END();
+ err(1, "pipe");
+ }
+ child_pid = fork();
+ switch (child_pid) {
+ default:
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTTOU, &sa, NULL);
+ close(fds[0]);
+ setpgid(child_pid, child_pid);
+ if (tcgetpgrp(STDERR_FILENO) == getpgrp())
+ tcsetpgrp(STDERR_FILENO, child_pid);
+ close(fds[1]);
+ sigaction(SIGPIPE, &sa_pipe, NULL);
+ while ((pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) {
+ if (WIFSTOPPED(statusp)) {
+ child_pgrp = getpgid(child_pid);
+ if (tcgetpgrp(STDERR_FILENO) == child_pgrp)
+ tcsetpgrp(STDERR_FILENO, getpgrp());
+ kill(getpid(), SIGSTOP);
+ if (tcgetpgrp(STDERR_FILENO) == getpgrp()) {
+ child_pgrp = getpgid(child_pid);
+ tcsetpgrp(STDERR_FILENO, child_pgrp);
+ }
+ kill(child_pid, SIGCONT);
+ statusp = 1;
+ continue;
+ }
+ break;
+ }
+ tcsetpgrp(STDERR_FILENO, getpgrp());
+ if (pid == -1)
+ err(1, "waitpid");
+ PAM_END();
+ exit(WEXITSTATUS(statusp));
+ case -1:
+ PAM_END();
+ err(1, "fork");
+ case 0:
+ close(fds[1]);
+ read(fds[0], &temp, 1);
+ close(fds[0]);
+ sigaction(SIGPIPE, &sa_pipe, NULL);
+ sigaction(SIGINT, &sa_int, NULL);
+ sigaction(SIGQUIT, &sa_quit, NULL);
+
+ /*
+ * Set all user context except for: Environmental variables
+ * Umask Login records (wtmp, etc) Path
+ */
+ setwhat = LOGIN_SETALL & ~(LOGIN_SETENV | LOGIN_SETUMASK |
+ LOGIN_SETLOGIN | LOGIN_SETPATH | LOGIN_SETGROUP |
+ LOGIN_SETMAC);
+ /*
+ * If -s is present, also set the MAC label.
+ */
+ if (setmaclabel)
+ setwhat |= LOGIN_SETMAC;
+ /*
+ * Don't touch resource/priority settings if -m has been used
+ * or -l and -c hasn't, and we're not su'ing to root.
+ */
+ if ((asme || (!asthem && class == NULL)) && pwd->pw_uid)
+ setwhat &= ~(LOGIN_SETPRIORITY | LOGIN_SETRESOURCES);
+ if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) < 0)
+ err(1, "setusercontext");
+
+ if (!asme) {
+ if (asthem) {
+ p = getenv("TERM");
+ environ = &cleanenv;
+ }
+
+ if (asthem || pwd->pw_uid)
+ setenv("USER", pwd->pw_name, 1);
+ setenv("HOME", pwd->pw_dir, 1);
+ setenv("SHELL", shell, 1);
+
+ if (asthem) {
+ /*
+ * Add any environmental variables that the
+ * PAM modules may have set.
+ */
+ environ_pam = pam_getenvlist(pamh);
+ if (environ_pam)
+ export_pam_environment();
+
+ /* set the su'd user's environment & umask */
+ setusercontext(lc, pwd, pwd->pw_uid,
+ LOGIN_SETPATH | LOGIN_SETUMASK |
+ LOGIN_SETENV);
+ if (p)
+ setenv("TERM", p, 1);
+
+ p = pam_getenv(pamh, "HOME");
+ if (chdir(p ? p : pwd->pw_dir) < 0)
+ errx(1, "no directory");
+ }
+ }
+ login_close(lc);
+
+ if (iscsh == YES) {
+ if (fastlogin)
+ *np.a-- = "-f";
+ if (asme)
+ *np.a-- = "-m";
+ }
+ /* csh strips the first character... */
+ *np.a = asthem ? "-su" : iscsh == YES ? "_su" : "su";
+
+ if (ruid != 0)
+ syslog(LOG_NOTICE, "%s to %s%s", username, user,
+ ontty());
+
+ execv(shell, np.b);
+ err(1, "%s", shell);
+ }
+}
+
+static void
+export_pam_environment(void)
+{
+ char **pp;
+ char *p;
+
+ for (pp = environ_pam; *pp != NULL; pp++) {
+ if (ok_to_export(*pp)) {
+ p = strchr(*pp, '=');
+ *p = '\0';
+ setenv(*pp, p + 1, 1);
+ }
+ free(*pp);
+ }
+}
+
+/*
+ * Sanity checks on PAM environmental variables:
+ * - Make sure there is an '=' in the string.
+ * - Make sure the string doesn't run on too long.
+ * - Do not export certain variables. This list was taken from the
+ * Solaris pam_putenv(3) man page.
+ * Note that if the user is chrooted, PAM may have a better idea than we
+ * do of where her home directory is.
+ */
+static int
+ok_to_export(const char *s)
+{
+ static const char *noexport[] = {
+ "SHELL", /* "HOME", */ "LOGNAME", "MAIL", "CDPATH",
+ "IFS", "PATH", NULL
+ };
+ const char **pp;
+ size_t n;
+
+ if (strlen(s) > 1024 || strchr(s, '=') == NULL)
+ return 0;
+ if (strncmp(s, "LD_", 3) == 0)
+ return 0;
+ for (pp = noexport; *pp != NULL; pp++) {
+ n = strlen(*pp);
+ if (s[n] == '=' && strncmp(s, *pp, n) == 0)
+ return 0;
+ }
+ return 1;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: su [-] [-flms] [-c class] [login [args]]\n");
+ exit(1);
+ /* NOTREACHED */
+}
+
+static int
+chshell(const char *sh)
+{
+ int r;
+ char *cp;
+
+ r = 0;
+ setusershell();
+ while ((cp = getusershell()) != NULL && !r)
+ r = (strcmp(cp, sh) == 0);
+ endusershell();
+ return r;
+}
+
+static char *
+ontty(void)
+{
+ char *p;
+ static char buf[MAXPATHLEN + 4];
+
+ buf[0] = 0;
+ p = ttyname(STDERR_FILENO);
+ if (p)
+ snprintf(buf, sizeof(buf), " on %s", p);
+ return buf;
+}
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile
new file mode 100644
index 000000000000..b3ca1a6f962c
--- /dev/null
+++ b/usr.bin/systat/Makefile
@@ -0,0 +1,18 @@
+.include <src.opts.mk>
+
+PROG= systat
+SRCS= cmds.c cmdtab.c devs.c fetch.c iolat.c iostat.c keyboard.c main.c sysput.c \
+ netcmds.c netstat.c pigs.c proc.c swap.c icmp.c \
+ mode.c ip.c sctp.c tcp.c zarc.c \
+ vmstat.c convtbl.c ifcmds.c ifstat.c
+
+.if ${MK_INET6_SUPPORT} != "no"
+SRCS+= icmp6.c ip6.c
+CFLAGS+= -DINET6
+.endif
+
+LIBADD= tinfow ncursesw m devstat kvm util procstat
+
+.include <bsd.prog.mk>
+
+CFLAGS+= -Wno-cast-align -Wno-cast-qual
diff --git a/usr.bin/systat/Makefile.depend b/usr.bin/systat/Makefile.depend
new file mode 100644
index 000000000000..35ba95a89549
--- /dev/null
+++ b/usr.bin/systat/Makefile.depend
@@ -0,0 +1,23 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libdevstat \
+ lib/libkvm \
+ lib/libprocstat \
+ lib/libutil \
+ lib/msun \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/systat/cmds.c b/usr.bin/systat/cmds.c
new file mode 100644
index 000000000000..16267f12b7d8
--- /dev/null
+++ b/usr.bin/systat/cmds.c
@@ -0,0 +1,192 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "systat.h"
+#include "extern.h"
+
+void
+command(const char *cmd)
+{
+ struct cmdtab *p;
+ char *cp, *tmpstr, *tmpstr1;
+ double t;
+
+ tmpstr = tmpstr1 = strdup(cmd);
+ for (cp = tmpstr1; *cp && !isspace(*cp); cp++)
+ ;
+ if (*cp)
+ *cp++ = '\0';
+ if (*tmpstr1 == '\0')
+ goto done;
+ for (; *cp && isspace(*cp); cp++)
+ ;
+ if (strcmp(tmpstr1, "quit") == 0 || strcmp(tmpstr1, "q") == 0)
+ die(0);
+ if (strcmp(tmpstr1, "load") == 0) {
+ load();
+ goto done;
+ }
+ if (strcmp(tmpstr1, "stop") == 0) {
+ delay = 0;
+ mvaddstr(CMDLINE, 0, "Refresh disabled.");
+ clrtoeol();
+ goto done;
+ }
+ if (strcmp(tmpstr1, "help") == 0) {
+ int _col, _len;
+
+ move(CMDLINE, _col = 0);
+ for (p = cmdtab; p->c_name; p++) {
+ _len = strlen(p->c_name);
+ if (_col + _len > COLS)
+ break;
+ addstr(p->c_name); _col += _len;
+ if (_col + 1 < COLS)
+ addch(' ');
+ }
+ clrtoeol();
+ goto done;
+ }
+ t = strtod(tmpstr1, NULL) * 1000000.0;
+ if (t > 0 && t < (double)UINT_MAX)
+ delay = (unsigned int)t;
+ if ((t <= 0 || t > (double)UINT_MAX) &&
+ (strcmp(tmpstr1, "start") == 0 ||
+ strcmp(tmpstr1, "interval") == 0)) {
+ if (*cp != '\0') {
+ t = strtod(cp, NULL) * 1000000.0;
+ if (t <= 0 || t >= (double)UINT_MAX) {
+ error("%d: bad interval.", (int)t);
+ goto done;
+ }
+ }
+ }
+ if (t > 0) {
+ delay = (unsigned int)t;
+ display();
+ status();
+ goto done;
+ }
+ p = lookup(tmpstr1);
+ if (p == (struct cmdtab *)-1) {
+ error("%s: Ambiguous command.", tmpstr1);
+ goto done;
+ }
+ if (p) {
+ if (curcmd == p)
+ goto done;
+ (*curcmd->c_close)(wnd);
+ curcmd->c_flags &= ~CF_INIT;
+ wnd = (*p->c_open)();
+ if (wnd == NULL) {
+ error("Couldn't open new display");
+ wnd = (*curcmd->c_open)();
+ if (wnd == NULL) {
+ error("Couldn't change back to previous cmd");
+ exit(1);
+ }
+ p = curcmd;
+ }
+ if ((p->c_flags & CF_INIT) == 0) {
+ if ((*p->c_init)())
+ p->c_flags |= CF_INIT;
+ else
+ goto done;
+ }
+ curcmd = p;
+ labels();
+ display();
+ status();
+ goto done;
+ }
+ if (curcmd->c_cmd == NULL || !(*curcmd->c_cmd)(tmpstr1, cp))
+ error("%s: Unknown command.", tmpstr1);
+done:
+ free(tmpstr);
+}
+
+struct cmdtab *
+lookup(const char *name)
+{
+ const char *p, *q;
+ struct cmdtab *ct, *found;
+ int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = (struct cmdtab *) 0;
+ for (ct = cmdtab; (p = ct->c_name); ct++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return (ct);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = ct;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return ((struct cmdtab *)-1);
+ return (found);
+}
+
+void
+status(void)
+{
+
+ error("Showing %s, refresh every %d seconds.",
+ curcmd->c_name, delay / 1000000);
+}
+
+int
+prefix(const char *s1, const char *s2)
+{
+
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ return (1);
+ s1++, s2++;
+ }
+ return (*s1 == '\0');
+}
diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c
new file mode 100644
index 000000000000..322f8908aad5
--- /dev/null
+++ b/usr.bin/systat/cmdtab.c
@@ -0,0 +1,85 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+struct cmdtab cmdtab[] = {
+ { "pigs", showpigs, fetchpigs, labelpigs,
+ initpigs, openpigs, closepigs, 0,
+ 0, CF_LOADAV },
+ { "swap", showswap, fetchswap, labelswap,
+ initswap, openswap, closeswap, 0,
+ 0, CF_LOADAV },
+ { "iostat", showiostat, fetchiostat, labeliostat,
+ initiostat, openiostat, closeiostat, cmdiostat,
+ 0, CF_LOADAV },
+ { "vmstat", showkre, fetchkre, labelkre,
+ initkre, openkre, closekre, cmdkre,
+ 0, 0 },
+ { "netstat", shownetstat, fetchnetstat, labelnetstat,
+ initnetstat, opennetstat, closenetstat, cmdnetstat,
+ 0, CF_LOADAV },
+ { "icmp", showicmp, fetchicmp, labelicmp,
+ initicmp, openicmp, closeicmp, cmdmode,
+ reseticmp, CF_LOADAV },
+ { "ip", showip, fetchip, labelip,
+ initip, openip, closeip, cmdmode,
+ resetip, CF_LOADAV },
+#ifdef INET6
+ { "icmp6", showicmp6, fetchicmp6, labelicmp6,
+ initicmp6, openicmp6, closeicmp6, cmdmode,
+ reseticmp6, CF_LOADAV },
+ { "ip6", showip6, fetchip6, labelip6,
+ initip6, openip6, closeip6, cmdmode,
+ resetip6, CF_LOADAV },
+#endif
+ { "sctp", showsctp, fetchsctp, labelsctp,
+ initsctp, opensctp, closesctp, cmdmode,
+ resetsctp, CF_LOADAV },
+ { "tcp", showtcp, fetchtcp, labeltcp,
+ inittcp, opentcp, closetcp, cmdmode,
+ resettcp, CF_LOADAV },
+ { "ifstat", showifstat, fetchifstat, labelifstat,
+ initifstat, openifstat, closeifstat, cmdifstat,
+ 0, CF_LOADAV },
+ { "zarc", showzarc, fetchzarc, labelzarc,
+ initzarc, openzarc, closezarc, 0,
+ resetzarc, CF_ZFSARC },
+ { "iolat", showiolat, fetchiolat, labeliolat,
+ initiolat, openiolat, closeiolat, cmdiolat,
+ 0, CF_LOADAV },
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
+};
+struct cmdtab *curcmd = &cmdtab[0];
diff --git a/usr.bin/systat/convtbl.c b/usr.bin/systat/convtbl.c
new file mode 100644
index 000000000000..1ef1a0e081ab
--- /dev/null
+++ b/usr.bin/systat/convtbl.c
@@ -0,0 +1,150 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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 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 AUTHOR 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 <stdlib.h>
+#include <string.h>
+#include "convtbl.h"
+
+#define BIT (8)
+#define BITS (1)
+#define KILOBIT (1000LL)
+#define MEGABIT (KILOBIT * 1000)
+#define GIGABIT (MEGABIT * 1000)
+#define TERABIT (GIGABIT * 1000)
+
+#define BYTE (1)
+#define BYTES (1)
+#define KILOBYTE (1024LL)
+#define MEGABYTE (KILOBYTE * 1024)
+#define GIGABYTE (MEGABYTE * 1024)
+#define TERABYTE (GIGABYTE * 1024)
+
+struct convtbl {
+ uintmax_t mul;
+ uintmax_t scale;
+ const char *str;
+ const char *name;
+};
+
+static struct convtbl convtbl[] = {
+ /* mul, scale, str, name */
+ [SC_BYTE] = { BYTE, BYTES, "B", "byte" },
+ [SC_KILOBYTE] = { BYTE, KILOBYTE, "KB", "kbyte" },
+ [SC_MEGABYTE] = { BYTE, MEGABYTE, "MB", "mbyte" },
+ [SC_GIGABYTE] = { BYTE, GIGABYTE, "GB", "gbyte" },
+ [SC_TERABYTE] = { BYTE, TERABYTE, "TB", "tbyte" },
+
+ [SC_BIT] = { BIT, BITS, "b", "bit" },
+ [SC_KILOBIT] = { BIT, KILOBIT, "Kb", "kbit" },
+ [SC_MEGABIT] = { BIT, MEGABIT, "Mb", "mbit" },
+ [SC_GIGABIT] = { BIT, GIGABIT, "Gb", "gbit" },
+ [SC_TERABIT] = { BIT, TERABIT, "Tb", "tbit" },
+
+ [SC_AUTO] = { 0, 0, "", "auto" }
+};
+
+static
+struct convtbl *
+get_tbl_ptr(const uintmax_t size, const int scale)
+{
+ uintmax_t tmp;
+ int idx;
+
+ /* If our index is out of range, default to auto-scaling. */
+ idx = scale < SC_AUTO ? scale : SC_AUTO;
+
+ if (idx == SC_AUTO)
+ /*
+ * Simple but elegant algorithm. Count how many times
+ * we can shift our size value right by a factor of ten,
+ * incrementing an index each time. We then use the
+ * index as the array index into the conversion table.
+ */
+ for (tmp = size, idx = SC_KILOBYTE;
+ tmp >= MEGABYTE && idx < SC_BIT - 1;
+ tmp >>= 10, idx++);
+
+ return (&convtbl[idx]);
+}
+
+double
+convert(const uintmax_t size, const int scale)
+{
+ struct convtbl *tp;
+
+ tp = get_tbl_ptr(size, scale);
+ return ((double)size * tp->mul / tp->scale);
+
+}
+
+const char *
+get_string(const uintmax_t size, const int scale)
+{
+ struct convtbl *tp;
+
+ tp = get_tbl_ptr(size, scale);
+ return (tp->str);
+}
+
+int
+get_scale(const char *name)
+{
+ int i;
+
+ for (i = 0; i <= SC_AUTO; i++)
+ if (strcmp(convtbl[i].name, name) == 0)
+ return (i);
+ return (-1);
+}
+
+const char *
+get_helplist(void)
+{
+ int i;
+ size_t len;
+ static char *buf;
+
+ if (buf == NULL) {
+ len = 0;
+ for (i = 0; i <= SC_AUTO; i++)
+ len += strlen(convtbl[i].name) + 2;
+ if ((buf = malloc(len)) != NULL) {
+ buf[0] = '\0';
+ for (i = 0; i <= SC_AUTO; i++) {
+ strcat(buf, convtbl[i].name);
+ if (i < SC_AUTO)
+ strcat(buf, ", ");
+ }
+ } else
+ return ("");
+ }
+ return (buf);
+}
diff --git a/usr.bin/systat/convtbl.h b/usr.bin/systat/convtbl.h
new file mode 100644
index 000000000000..f9e2d664235f
--- /dev/null
+++ b/usr.bin/systat/convtbl.h
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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 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 AUTHOR 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 _CONVTBL_H_
+#define _CONVTBL_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+/*
+ * Keep the order in the enum.
+ */
+enum scale {
+ SC_BYTE,
+ SC_KILOBYTE,
+ SC_MEGABYTE,
+ SC_GIGABYTE,
+ SC_TERABYTE,
+ SC_BIT,
+ SC_KILOBIT,
+ SC_MEGABIT,
+ SC_GIGABIT,
+ SC_TERABIT,
+ SC_AUTO /* KEEP THIS LAST */
+};
+
+extern double convert(const uintmax_t, const int);
+extern const char *get_helplist(void);
+extern int get_scale(const char *);
+extern const char *get_string(const uintmax_t, const int);
+
+#endif /* ! _CONVTBL_H_ */
diff --git a/usr.bin/systat/devs.c b/usr.bin/systat/devs.c
new file mode 100644
index 000000000000..fd7bf9e97524
--- /dev/null
+++ b/usr.bin/systat/devs.c
@@ -0,0 +1,431 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1998 Kenneth D. Merry.
+ * 2015 Yoshihiro Ota
+ * 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 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 AUTHOR 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.
+ */
+/*-
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/devicestat.h>
+#include <sys/resource.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+typedef enum {
+ DS_MATCHTYPE_NONE,
+ DS_MATCHTYPE_SPEC,
+ DS_MATCHTYPE_PATTERN
+} last_match_type;
+
+struct statinfo cur_dev, last_dev, run_dev;
+
+static last_match_type last_type;
+struct device_selection *dev_select;
+long generation;
+int num_devices, num_selected;
+int num_selections;
+long select_generation;
+static struct devstat_match *matches = NULL;
+static int num_matches = 0;
+static char **specified_devices;
+static int num_devices_specified = 0;
+
+static int dsmatchselect(const char *args, devstat_select_mode select_mode,
+ int maxshowdevs, struct statinfo *s1);
+static int dsselect(const char *args, devstat_select_mode select_mode,
+ int maxshowdevs, struct statinfo *s1);
+
+int
+dsinit(int maxshowdevs)
+{
+ /*
+ * Make sure that the userland devstat version matches the kernel
+ * devstat version. If not, exit and print a message informing
+ * the user of his mistake.
+ */
+ if (devstat_checkversion(NULL) < 0)
+ errx(1, "%s", devstat_errbuf);
+
+ if( cur_dev.dinfo ) // init was alreay ran
+ return(1);
+
+ if ((num_devices = devstat_getnumdevs(NULL)) < 0) {
+ warnx("%s", devstat_errbuf);
+ return(0);
+ }
+
+ cur_dev.dinfo = calloc(1, sizeof(struct devinfo));
+ last_dev.dinfo = calloc(1, sizeof(struct devinfo));
+ run_dev.dinfo = calloc(1, sizeof(struct devinfo));
+
+ generation = 0;
+ num_devices = 0;
+ num_selected = 0;
+ num_selections = 0;
+ select_generation = 0;
+ last_type = DS_MATCHTYPE_NONE;
+
+ if (devstat_getdevs(NULL, &cur_dev) == -1)
+ errx(1, "%s", devstat_errbuf);
+
+ num_devices = cur_dev.dinfo->numdevs;
+ generation = cur_dev.dinfo->generation;
+
+ dev_select = NULL;
+
+ /*
+ * At this point, selectdevs will almost surely indicate that the
+ * device list has changed, so we don't look for return values of 0
+ * or 1. If we get back -1, though, there is an error.
+ */
+ if (devstat_selectdevs(&dev_select, &num_selected, &num_selections,
+ &select_generation, generation, cur_dev.dinfo->devices, num_devices,
+ NULL, 0, NULL, 0, DS_SELECT_ADD, maxshowdevs, 0) == -1)
+ errx(1, "%d %s", __LINE__, devstat_errbuf);
+
+ return(1);
+}
+
+
+void
+dsgetinfo(struct statinfo* dev)
+{
+ switch (devstat_getdevs(NULL, dev)) {
+ case -1:
+ errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ num_devices = dev->dinfo->numdevs;
+ generation = dev->dinfo->generation;
+ cmdkre("refresh", NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+int
+dscmd(const char *cmd, const char *args, int maxshowdevs, struct statinfo *s1)
+{
+ int retval;
+
+ if (prefix(cmd, "display") || prefix(cmd, "add"))
+ return(dsselect(args, DS_SELECT_ADDONLY, maxshowdevs, s1));
+ if (prefix(cmd, "ignore") || prefix(cmd, "delete"))
+ return(dsselect(args, DS_SELECT_REMOVE, maxshowdevs, s1));
+ if (prefix(cmd, "show") || prefix(cmd, "only"))
+ return(dsselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
+ if (prefix(cmd, "type") || prefix(cmd, "match"))
+ return(dsmatchselect(args, DS_SELECT_ONLY, maxshowdevs, s1));
+ if (prefix(cmd, "refresh")) {
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation, generation,
+ s1->dinfo->devices, num_devices,
+ (last_type ==DS_MATCHTYPE_PATTERN) ? matches : NULL,
+ (last_type ==DS_MATCHTYPE_PATTERN) ? num_matches : 0,
+ (last_type == DS_MATCHTYPE_SPEC) ?specified_devices : NULL,
+ (last_type == DS_MATCHTYPE_SPEC) ?num_devices_specified : 0,
+ (last_type == DS_MATCHTYPE_NONE) ? DS_SELECT_ADD :
+ DS_SELECT_ADDONLY, maxshowdevs, 0);
+ if (retval == -1) {
+ warnx("%s", devstat_errbuf);
+ return(0);
+ } else if (retval == 1)
+ return(2);
+ }
+ if (prefix(cmd, "drives")) {
+ int i;
+ move(CMDLINE, 0);
+ clrtoeol();
+ for (i = 0; i < num_devices; i++) {
+ printw("%s%d ", s1->dinfo->devices[i].device_name,
+ s1->dinfo->devices[i].unit_number);
+ }
+ return(1);
+ }
+ return(0);
+}
+
+static int
+dsmatchselect(const char *args, devstat_select_mode select_mode, int maxshowdevs,
+ struct statinfo *s1)
+{
+ char **tempstr, *tmpstr, *tmpstr1;
+ char *tstr[100];
+ int num_args = 0;
+ int i;
+ int retval = 0;
+
+ if (!args) {
+ warnx("dsmatchselect: no arguments");
+ return(1);
+ }
+
+ /*
+ * Break the (pipe delimited) input string out into separate
+ * strings.
+ */
+ tmpstr = tmpstr1 = strdup(args);
+ for (tempstr = tstr, num_args = 0;
+ (*tempstr = strsep(&tmpstr1, "|")) != NULL && (num_args < 100);
+ num_args++)
+ if (**tempstr != '\0')
+ if (++tempstr >= &tstr[100])
+ break;
+ free(tmpstr);
+
+ if (num_args > 99) {
+ warnx("dsmatchselect: too many match arguments");
+ return(0);
+ }
+
+ /*
+ * If we've gone through the matching code before, clean out
+ * previously used memory.
+ */
+ if (num_matches > 0) {
+ free(matches);
+ matches = NULL;
+ num_matches = 0;
+ }
+
+ for (i = 0; i < num_args; i++) {
+ if (devstat_buildmatch(tstr[i], &matches, &num_matches) != 0) {
+ warnx("%s", devstat_errbuf);
+ return(0);
+ }
+ }
+ if (num_args > 0) {
+
+ last_type = DS_MATCHTYPE_PATTERN;
+
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation, generation,
+ s1->dinfo->devices, num_devices, matches, num_matches,
+ NULL, 0, select_mode, maxshowdevs, 0);
+ if (retval == -1)
+ err(1, "device selection error");
+ else if (retval == 1)
+ return(2);
+ }
+ return(1);
+}
+
+static int
+dsselect(const char *args, devstat_select_mode select_mode, int maxshowdevs,
+ struct statinfo *s1)
+{
+ char *cp, *tmpstr, *tmpstr1, *buffer;
+ int i;
+ int retval = 0;
+
+ if (!args) {
+ warnx("dsselect: no argument");
+ return(1);
+ }
+
+ /*
+ * If we've gone through this code before, free previously
+ * allocated resources.
+ */
+ if (num_devices_specified > 0) {
+ for (i = 0; i < num_devices_specified; i++)
+ free(specified_devices[i]);
+ free(specified_devices);
+ specified_devices = NULL;
+ num_devices_specified = 0;
+ }
+
+ /* do an initial malloc */
+ specified_devices = (char **)malloc(sizeof(char *));
+
+ tmpstr = tmpstr1 = strdup(args);
+ cp = strchr(tmpstr1, '\n');
+ if (cp)
+ *cp = '\0';
+ for (;;) {
+ for (cp = tmpstr1; *cp && isspace(*cp); cp++)
+ ;
+ tmpstr1 = cp;
+ for (; *cp && !isspace(*cp); cp++)
+ ;
+ if (*cp)
+ *cp++ = '\0';
+ if (cp - tmpstr1 == 0)
+ break;
+ for (i = 0; i < num_devices; i++) {
+ asprintf(&buffer, "%s%d", dev_select[i].device_name,
+ dev_select[i].unit_number);
+ if (strcmp(buffer, tmpstr1) == 0) {
+
+ num_devices_specified++;
+
+ specified_devices =(char **)realloc(
+ specified_devices,
+ sizeof(char *) *
+ num_devices_specified);
+ specified_devices[num_devices_specified -1]=
+ strdup(tmpstr1);
+ free(buffer);
+
+ break;
+ }
+ else
+ free(buffer);
+ }
+ if (i >= num_devices)
+ error("%s: unknown drive", args);
+ tmpstr1 = cp;
+ }
+ free(tmpstr);
+
+ if (num_devices_specified > 0) {
+ last_type = DS_MATCHTYPE_SPEC;
+
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation, generation,
+ s1->dinfo->devices, num_devices, NULL, 0,
+ specified_devices, num_devices_specified,
+ select_mode, maxshowdevs, 0);
+ if (retval == -1)
+ err(1, "%s", devstat_errbuf);
+ else if (retval == 1)
+ return(2);
+ }
+ return(1);
+}
+
+
+void
+dslabel(int maxdrives, int diskcol, int diskrow)
+{
+ int i, j;
+
+ mvprintw(diskrow, diskcol, "Disks");
+ mvprintw(diskrow + 1, diskcol, "KB/t");
+ mvprintw(diskrow + 2, diskcol, "tps");
+ mvprintw(diskrow + 3, diskcol, "MB/s");
+ mvprintw(diskrow + 4, diskcol, "%%busy");
+ /*
+ * For now, we don't support a fourth disk statistic. So there's
+ * no point in providing a label for it. If someone can think of a
+ * fourth useful disk statistic, there is room to add it.
+ */
+ /* mvprintw(diskrow + 4, diskcol, " msps"); */
+ j = 0;
+ for (i = 0; i < num_devices && j < maxdrives; i++)
+ if (dev_select[i].selected) {
+ char tmpstr[80];
+ sprintf(tmpstr, "%s%d", dev_select[i].device_name,
+ dev_select[i].unit_number);
+ mvprintw(diskrow, diskcol + 5 + 6 * j,
+ " %5.5s", tmpstr);
+ j++;
+ }
+}
+
+static void
+dsshow2(int diskcol, int diskrow, int dn, int lc, struct statinfo *now, struct statinfo *then)
+{
+ long double transfers_per_second;
+ long double kb_per_transfer, mb_per_second;
+ long double elapsed_time, device_busy;
+ int di;
+
+ di = dev_select[dn].position;
+
+ if (then != NULL) {
+ /* Calculate relative to previous sample */
+ elapsed_time = now->snap_time - then->snap_time;
+ } else {
+ /* Calculate relative to device creation */
+ elapsed_time = now->snap_time - devstat_compute_etime(
+ &now->dinfo->devices[di].creation_time, NULL);
+ }
+
+ if (devstat_compute_statistics(&now->dinfo->devices[di], then ?
+ &then->dinfo->devices[di] : NULL, elapsed_time,
+ DSM_KB_PER_TRANSFER, &kb_per_transfer,
+ DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
+ DSM_MB_PER_SECOND, &mb_per_second,
+ DSM_BUSY_PCT, &device_busy,
+ DSM_NONE) != 0)
+ errx(1, "%s", devstat_errbuf);
+
+ lc = diskcol + lc * 6;
+ putlongdouble(kb_per_transfer, diskrow + 1, lc, 5, 2, 0);
+ putlongdouble(transfers_per_second, diskrow + 2, lc, 5, 0, 0);
+ putlongdouble(mb_per_second, diskrow + 3, lc, 5, 2, 0);
+ putlongdouble(device_busy, diskrow + 4, lc, 5, 0, 0);
+}
+
+void
+dsshow(int maxdrives, int diskcol, int diskrow, struct statinfo *now, struct statinfo *then)
+{
+ int i, lc;
+
+ for (i = 0, lc = 0; i < num_devices && lc < maxdrives; i++)
+ if (dev_select[i].selected)
+ dsshow2(diskcol, diskrow, i, ++lc, now, then);
+}
diff --git a/usr.bin/systat/devs.h b/usr.bin/systat/devs.h
new file mode 100644
index 000000000000..e5f72f795c13
--- /dev/null
+++ b/usr.bin/systat/devs.h
@@ -0,0 +1,46 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1998 David E. O'Brien
+ * 2015, 2021 Yoshihiro Ota
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 DEVS_H
+#define DEVS_H
+
+#include <devstat.h>
+
+#define DISKHIGHT 5
+
+int dsinit(int);
+void dsgetinfo(struct statinfo *);
+int dscmd(const char *, const char *, int, struct statinfo *);
+
+void dslabel(int, int, int);
+void dsshow(int, int, int, struct statinfo *, struct statinfo *);
+
+extern struct statinfo cur_dev, last_dev, run_dev;
+
+#endif
diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h
new file mode 100644
index 000000000000..8d19aec024b4
--- /dev/null
+++ b/usr.bin/systat/extern.h
@@ -0,0 +1,189 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/cdefs.h>
+#include <fcntl.h>
+#include <kvm.h>
+
+extern struct cmdtab *curcmd;
+extern struct cmdtab cmdtab[];
+extern struct text *xtext;
+extern WINDOW *wnd;
+extern char **dr_name;
+extern char c, *namp, hostname[];
+extern double avenrun[3];
+extern float *dk_mspw;
+extern kvm_t *kd;
+extern long ntext, textp;
+extern int *dk_select;
+extern int CMDLINE;
+extern int dk_ndrive;
+extern int hz, stathz;
+extern double hertz; /* sampling frequency for cp_time and dk_time */
+extern int col;
+extern int nhosts;
+extern int nports;
+extern int protos;
+extern int verbose;
+extern unsigned int delay;
+
+extern int curscale;
+extern char *matchline;
+extern int showpps;
+extern int needsort;
+
+struct in_conninfo;
+
+extern struct device_selection *dev_select;
+extern long generation;
+extern int num_devices;
+extern int num_selected;
+extern int num_selections;
+extern long select_generation;
+
+extern struct nlist namelist[];
+
+int checkhost(struct in_conninfo *);
+int checkport(struct in_conninfo *);
+void closeicmp(WINDOW *);
+void closeicmp6(WINDOW *);
+void closeifstat(WINDOW *);
+void closeiostat(WINDOW *);
+void closeip(WINDOW *);
+void closeip6(WINDOW *);
+void closekre(WINDOW *);
+void closenetstat(WINDOW *);
+void closepigs(WINDOW *);
+void closeswap(WINDOW *);
+void closetcp(WINDOW *);
+int cmdifstat(const char *, const char *);
+int cmdiolat(const char *, const char *);
+int cmdiostat(const char *, const char *);
+int cmdkre(const char *, const char *);
+int cmdnetstat(const char *, const char *);
+struct cmdtab *lookup(const char *);
+void command(const char *);
+void die(int);
+void display(void);
+int dkinit(void);
+int dkcmd(char *, char *);
+void error(const char *fmt, ...) __printflike(1, 2);
+void fetchicmp(void);
+void fetchicmp6(void);
+void fetchifstat(void);
+void fetchip(void);
+void fetchip6(void);
+void fetchiostat(void);
+void fetchkre(void);
+void fetchnetstat(void);
+void fetchpigs(void);
+void fetchswap(void);
+void fetchtcp(void);
+void getsysctl(const char *, void *, size_t);
+int ifcmd(const char *cmd, const char *args);
+int initicmp(void);
+int initicmp6(void);
+int initifstat(void);
+int initip(void);
+int initip6(void);
+int initiostat(void);
+int initkre(void);
+int initnetstat(void);
+int initpigs(void);
+int initswap(void);
+int inittcp(void);
+int keyboard(void);
+int kvm_ckread(void *, void *, int);
+void labelicmp(void);
+void labelicmp6(void);
+void labelifstat(void);
+void labelip(void);
+void labelip6(void);
+void labeliostat(void);
+void labelkre(void);
+void labelnetstat(void);
+void labelpigs(void);
+void labels(void);
+void labelswap(void);
+void labeltcp(void);
+void load(void);
+int netcmd(const char *, const char *);
+void nlisterr(struct nlist []);
+WINDOW *openicmp(void);
+WINDOW *openicmp6(void);
+WINDOW *openifstat(void);
+WINDOW *openip(void);
+WINDOW *openip6(void);
+WINDOW *openiostat(void);
+WINDOW *openkre(void);
+WINDOW *opennetstat(void);
+WINDOW *openpigs(void);
+WINDOW *openswap(void);
+WINDOW *opentcp(void);
+int prefix(const char *, const char *);
+void reseticmp(void);
+void reseticmp6(void);
+void resetip(void);
+void resetip6(void);
+void resettcp(void);
+void showicmp(void);
+void showicmp6(void);
+void showifstat(void);
+void showip(void);
+void showip6(void);
+void showiostat(void);
+void showkre(void);
+void shownetstat(void);
+void showpigs(void);
+void showswap(void);
+void showtcp(void);
+void status(void);
+void suspend(int);
+char *sysctl_dynread(const char *, size_t *);
+void sysputpage(WINDOW* , int, int, int, uint64_t, int);
+void sysputspaces(WINDOW* , int, int, int);
+void sysputstrs(WINDOW* , int, int, int);
+void sysputXs(WINDOW* , int, int, int);
+void sysputuint64(WINDOW* , int, int, int, uint64_t, int);
+void sysputwuint64(WINDOW* , int, int, int, uint64_t, int);
+
+#define SYSTAT_CMD(name) \
+ void close ## name(WINDOW *); \
+ void fetch ## name(void); \
+ int init ## name(void); \
+ void label ## name(void); \
+ WINDOW *open ## name(void); \
+ void reset ## name(void); \
+ void show ## name(void)
+
+SYSTAT_CMD( zarc );
+SYSTAT_CMD( sctp );
+SYSTAT_CMD( iolat );
diff --git a/usr.bin/systat/fetch.c b/usr.bin/systat/fetch.c
new file mode 100644
index 000000000000..63876e4e6fbb
--- /dev/null
+++ b/usr.bin/systat/fetch.c
@@ -0,0 +1,135 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+
+int
+kvm_ckread(void *a, void *b, int l)
+{
+ if (kvm_read(kd, (u_long)a, b, l) != l) {
+ if (verbose)
+ error("error reading kmem at %p", a);
+ return (0);
+ }
+ else
+ return (1);
+}
+
+void
+getsysctl(const char *name, void *ptr, size_t len)
+{
+ size_t nlen = len;
+
+ if (sysctlbyname(name, ptr, &nlen, NULL, 0) != 0) {
+ error("sysctl(%s...) failed: %s", name,
+ strerror(errno));
+ }
+ if (nlen != len) {
+ error("sysctl(%s...) expected %zu, got %zu", name, len, nlen);
+ }
+}
+
+/*
+ * Read sysctl data with variable size. Try some times (with increasing
+ * buffers), fail if still too small.
+ * This is needed sysctls with possibly raplidly increasing data sizes,
+ * but imposes little overhead in the case of constant sizes.
+ * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds
+ * the requested data.
+ * If szp is not NULL, the size of the returned data will be written into *szp.
+ */
+
+/* Some defines: Number of tries. */
+#define SD_NTRIES 10
+/* Percent of over-allocation (initial) */
+#define SD_MARGIN 10
+/*
+ * Factor for over-allocation in percent (the margin is increased by this on
+ * any failed try).
+ */
+#define SD_FACTOR 50
+/* Maximum supported MIB depth */
+#define SD_MAXMIB 16
+
+char *
+sysctl_dynread(const char *n, size_t *szp)
+{
+ char *rv = NULL;
+ int mib[SD_MAXMIB];
+ size_t mibsz = SD_MAXMIB;
+ size_t mrg = SD_MARGIN;
+ size_t sz;
+ int i;
+
+ /* cache the MIB */
+ if (sysctlnametomib(n, mib, &mibsz) == -1) {
+ if (errno == ENOMEM) {
+ error("XXX: SD_MAXMIB too small, please bump!");
+ }
+ return NULL;
+ }
+ for (i = 0; i < SD_NTRIES; i++) {
+ /* get needed buffer size */
+ if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1)
+ break;
+ sz += sz * mrg / 100;
+ if ((rv = (char *)malloc(sz)) == NULL) {
+ error("Out of memory!");
+ return NULL;
+ }
+ if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) {
+ free(rv);
+ rv = NULL;
+ if (errno == ENOMEM) {
+ mrg += mrg * SD_FACTOR / 100;
+ } else
+ break;
+ } else {
+ /* success */
+ if (szp != NULL)
+ *szp = sz;
+ break;
+ }
+ }
+
+ return rv;
+}
diff --git a/usr.bin/systat/icmp.c b/usr.bin/systat/icmp.c
new file mode 100644
index 000000000000..a0d2534e5d87
--- /dev/null
+++ b/usr.bin/systat/icmp.c
@@ -0,0 +1,275 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/* From:
+ "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
+*/
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct icmpstat icmpstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 ICMP Input ICMP Output
+01999999999 total messages 999999999 total messages
+02999999999 with bad code 999999999 errors generated
+03999999999 with bad length 999999999 suppressed - original too short
+04999999999 with bad checksum 999999999 suppressed - original was ICMP
+05999999999 with insufficient data 999999999 responses sent
+06 999999999 suppressed - multicast echo
+07 999999999 suppressed - multicast tstamp
+08
+09 Input Histogram Output Histogram
+10999999999 echo response 999999999 echo response
+11999999999 echo request 999999999 echo request
+12999999999 destination unreachable 999999999 destination unreachable
+13999999999 redirect 999999999 redirect
+14999999999 time-to-live exceeded 999999999 time-to-line exceeded
+15999999999 parameter problem 999999999 parameter problem
+16999999999 router advertisement 999999999 router solicitation
+17
+18
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+openicmp(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeicmp(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labelicmp(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 10, str)
+#define R(row, str) mvwprintw(wnd, row, 45, str);
+ L(0, "ICMP Input"); R(0, "ICMP Output");
+ L(1, "total messages"); R(1, "total messages");
+ L(2, "with bad code"); R(2, "errors generated");
+ L(3, "with bad length"); R(3, "suppressed - original too short");
+ L(4, "with bad checksum"); R(4, "suppressed - original was ICMP");
+ L(5, "with insufficient data"); R(5, "responses sent");
+ R(6, "suppressed - multicast echo");
+ R(7, "suppressed - multicast tstamp");
+ L(9, "Input Histogram"); R(9, "Output Histogram");
+#define B(row, str) L(row, str); R(row, str)
+ B(10, "echo response");
+ B(11, "echo request");
+ B(12, "destination unreachable");
+ B(13, "redirect");
+ B(14, "time-to-live exceeded");
+ B(15, "parameter problem");
+ L(16, "router advertisement"); R(16, "router solicitation");
+#undef L
+#undef R
+#undef B
+}
+
+static void
+domode(struct icmpstat *ret)
+{
+ const struct icmpstat *sub;
+ int i, divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = icmpstat;
+ return;
+ }
+#define DO(stat) ret->stat = (icmpstat.stat - sub->stat) / divisor
+ DO(icps_error);
+ DO(icps_oldshort);
+ DO(icps_oldicmp);
+ for (i = 0; i <= ICMP_MAXTYPE; i++) {
+ DO(icps_outhist[i]);
+ }
+ DO(icps_badcode);
+ DO(icps_tooshort);
+ DO(icps_checksum);
+ DO(icps_badlen);
+ DO(icps_reflect);
+ for (i = 0; i <= ICMP_MAXTYPE; i++) {
+ DO(icps_inhist[i]);
+ }
+ DO(icps_bmcastecho);
+ DO(icps_bmcasttstamp);
+#undef DO
+}
+
+void
+showicmp(void)
+{
+ struct icmpstat stats;
+ u_long totalin, totalout;
+ int i;
+
+ memset(&stats, 0, sizeof stats);
+ domode(&stats);
+ for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) {
+ totalin += stats.icps_inhist[i];
+ totalout += stats.icps_outhist[i];
+ }
+ totalin += stats.icps_badcode + stats.icps_badlen +
+ stats.icps_checksum + stats.icps_tooshort;
+ mvwprintw(wnd, 1, 0, "%9lu", totalin);
+ mvwprintw(wnd, 1, 35, "%9lu", totalout);
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%9lu", stats.stat)
+
+ DO(icps_badcode, 2, 0);
+ DO(icps_badlen, 3, 0);
+ DO(icps_checksum, 4, 0);
+ DO(icps_tooshort, 5, 0);
+ DO(icps_error, 2, 35);
+ DO(icps_oldshort, 3, 35);
+ DO(icps_oldicmp, 4, 35);
+ DO(icps_reflect, 5, 35);
+ DO(icps_bmcastecho, 6, 35);
+ DO(icps_bmcasttstamp, 7, 35);
+#define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \
+ row, 35)
+ DO2(ICMP_ECHOREPLY, 10);
+ DO2(ICMP_ECHO, 11);
+ DO2(ICMP_UNREACH, 12);
+ DO2(ICMP_REDIRECT, 13);
+ DO2(ICMP_TIMXCEED, 14);
+ DO2(ICMP_PARAMPROB, 15);
+ DO(icps_inhist[ICMP_ROUTERADVERT], 16, 0);
+ DO(icps_outhist[ICMP_ROUTERSOLICIT], 16, 35);
+#undef DO
+#undef DO2
+}
+
+int
+initicmp(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_ICMP;
+ name[3] = ICMPCTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting icmpstat size failed");
+ return 0;
+ }
+ if (len > sizeof icmpstat) {
+ error("icmpstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting icmpstat size failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+reseticmp(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_ICMP;
+ name[3] = ICMPCTL_STATS;
+
+ len = sizeof initstat;
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting icmpstat size failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchicmp(void)
+{
+ int name[4];
+ size_t len;
+
+ oldstat = icmpstat;
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_ICMP;
+ name[3] = ICMPCTL_STATS;
+ len = sizeof icmpstat;
+
+ if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0)
+ return;
+}
diff --git a/usr.bin/systat/icmp6.c b/usr.bin/systat/icmp6.c
new file mode 100644
index 000000000000..a25795209c02
--- /dev/null
+++ b/usr.bin/systat/icmp6.c
@@ -0,0 +1,275 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/* From:
+ "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
+*/
+
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct icmp6stat icmp6stat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 ICMPv6 Input ICMPv6 Output
+01999999999 total messages 999999999 total messages
+02999999999 with bad code 999999999 errors generated
+03999999999 with bad length 999999999 suppressed - original too short
+04999999999 with bad checksum 999999999 suppressed - original was ICMP
+05999999999 with insufficient data 999999999 responses sent
+06
+07 Input Histogram Output Histogram
+08999999999 echo response 999999999 echo response
+09999999999 echo request 999999999 echo request
+10999999999 destination unreachable 999999999 destination unreachable
+11999999999 redirect 999999999 redirect
+12999999999 time-to-live exceeded 999999999 time-to-line exceeded
+13999999999 parameter problem 999999999 parameter problem
+14999999999 neighbor solicitation 999999999 neighbor solicitation
+15999999999 neighbor advertisement 999999999 neighbor advertisement
+16999999999 router advertisement 999999999 router solicitation
+17
+18
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+openicmp6(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeicmp6(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labelicmp6(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 10, str)
+#define R(row, str) mvwprintw(wnd, row, 45, str);
+ L(0, "ICMPv6 Input"); R(0, "ICMPv6 Output");
+ L(1, "total messages"); R(1, "total messages");
+ L(2, "with bad code"); R(2, "errors generated");
+ L(3, "with bad length"); R(3, "suppressed - original too short");
+ L(4, "with bad checksum"); R(4, "suppressed - original was ICMP");
+ L(5, "with insufficient data"); R(5, "responses sent");
+
+ L(7, "Input Histogram"); R(7, "Output Histogram");
+#define B(row, str) L(row, str); R(row, str)
+ B(8, "echo response");
+ B(9, "echo request");
+ B(10, "destination unreachable");
+ B(11, "redirect");
+ B(12, "time-to-live exceeded");
+ B(13, "parameter problem");
+ B(14, "neighbor solicitation");
+ B(15, "neighbor advertisement");
+ L(16, "router advertisement"); R(16, "router solicitation");
+#undef L
+#undef R
+#undef B
+}
+
+static void
+domode(struct icmp6stat *ret)
+{
+ const struct icmp6stat *sub;
+ int i, divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = icmp6stat;
+ return;
+ }
+#define DO(stat) ret->stat = (icmp6stat.stat - sub->stat) / divisor
+ DO(icp6s_error);
+ DO(icp6s_tooshort);
+ DO(icp6s_canterror);
+ for (i = 0; i <= ICMP6_MAXTYPE; i++) {
+ DO(icp6s_outhist[i]);
+ }
+ DO(icp6s_badcode);
+ DO(icp6s_tooshort);
+ DO(icp6s_checksum);
+ DO(icp6s_badlen);
+ DO(icp6s_reflect);
+ for (i = 0; i <= ICMP6_MAXTYPE; i++) {
+ DO(icp6s_inhist[i]);
+ }
+#undef DO
+}
+
+void
+showicmp6(void)
+{
+ struct icmp6stat stats;
+ uint64_t totalin, totalout;
+ int i;
+
+ memset(&stats, 0, sizeof stats);
+ domode(&stats);
+ for (i = totalin = totalout = 0; i <= ICMP6_MAXTYPE; i++) {
+ totalin += stats.icp6s_inhist[i];
+ totalout += stats.icp6s_outhist[i];
+ }
+ totalin += stats.icp6s_badcode + stats.icp6s_badlen +
+ stats.icp6s_checksum + stats.icp6s_tooshort;
+ mvwprintw(wnd, 1, 0, "%9"PRIu64, totalin);
+ mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout);
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat)
+
+ DO(icp6s_badcode, 2, 0);
+ DO(icp6s_badlen, 3, 0);
+ DO(icp6s_checksum, 4, 0);
+ DO(icp6s_tooshort, 5, 0);
+ DO(icp6s_error, 2, 35);
+ DO(icp6s_tooshort, 3, 35);
+ DO(icp6s_canterror, 4, 35);
+ DO(icp6s_reflect, 5, 35);
+#define DO2(type, row) DO(icp6s_inhist[type], row, 0); DO(icp6s_outhist[type], \
+ row, 35)
+ DO2(ICMP6_ECHO_REPLY, 8);
+ DO2(ICMP6_ECHO_REQUEST, 9);
+ DO2(ICMP6_DST_UNREACH, 10);
+ DO2(ND_REDIRECT, 11);
+ DO2(ICMP6_TIME_EXCEEDED, 12);
+ DO2(ICMP6_PARAM_PROB, 13);
+ DO2(ND_NEIGHBOR_SOLICIT, 14);
+ DO2(ND_NEIGHBOR_ADVERT, 15);
+ DO(icp6s_inhist[ND_ROUTER_SOLICIT], 16, 0);
+ DO(icp6s_outhist[ND_ROUTER_ADVERT], 16, 35);
+#undef DO
+#undef DO2
+}
+
+int
+initicmp6(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_ICMPV6;
+ name[3] = ICMPV6CTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting icmp6stat size failed");
+ return 0;
+ }
+ if (len > sizeof icmp6stat) {
+ error("icmp6stat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting icmp6stat size failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+reseticmp6(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_ICMPV6;
+ name[3] = ICMPV6CTL_STATS;
+
+ len = sizeof initstat;
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting icmp6stat size failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchicmp6(void)
+{
+ int name[4];
+ size_t len;
+
+ oldstat = icmp6stat;
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_ICMPV6;
+ name[3] = ICMPV6CTL_STATS;
+ len = sizeof icmp6stat;
+
+ if (sysctl(name, 4, &icmp6stat, &len, 0, 0) < 0)
+ return;
+}
+
+#endif
diff --git a/usr.bin/systat/ifcmds.c b/usr.bin/systat/ifcmds.c
new file mode 100644
index 000000000000..7bd7dcb79f63
--- /dev/null
+++ b/usr.bin/systat/ifcmds.c
@@ -0,0 +1,79 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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 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 AUTHOR 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 "systat.h"
+#include "extern.h"
+#include "convtbl.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int curscale = SC_AUTO;
+char *matchline = NULL;
+int showpps = 0;
+int needsort = 0;
+
+int
+ifcmd(const char *cmd, const char *args)
+{
+ int scale;
+
+ if (prefix(cmd, "scale")) {
+ if ((scale = get_scale(args)) != -1)
+ curscale = scale;
+ else {
+ move(CMDLINE, 0);
+ clrtoeol();
+ addstr("what scale? ");
+ addstr(get_helplist());
+ }
+ } else if (prefix(cmd, "match")) {
+ if (args != NULL && *args != '\0' && memcmp(args, "*", 2) != 0) {
+ /* We got a valid match line */
+ if (matchline != NULL)
+ free(matchline);
+ needsort = 1;
+ matchline = strdup(args);
+ } else {
+ /* Empty or * pattern, turn filtering off */
+ if (matchline != NULL)
+ free(matchline);
+ needsort = 1;
+ matchline = NULL;
+ }
+ } else if (prefix(cmd, "pps"))
+ showpps = !showpps;
+ else
+ return (0);
+
+ return (1);
+}
diff --git a/usr.bin/systat/ifstat.c b/usr.bin/systat/ifstat.c
new file mode 100644
index 000000000000..68c17707d643
--- /dev/null
+++ b/usr.bin/systat/ifstat.c
@@ -0,0 +1,514 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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 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 AUTHOR 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 INTIFSTAT_ERRUPTION)
+ * 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/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/if_mib.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "convtbl.h"
+
+ /* Column numbers */
+
+#define C1 0 /* 0-19 */
+#define C2 20 /* 20-39 */
+#define C3 40 /* 40-59 */
+#define C4 60 /* 60-80 */
+#define C5 80 /* Used for label positioning. */
+
+static const int col2 = C2;
+static const int col3 = C3;
+static const int col4 = C4;
+
+static SLIST_HEAD(, if_stat) curlist;
+
+struct if_stat {
+ SLIST_ENTRY(if_stat) link;
+ char display_name[IF_NAMESIZE];
+ char dev_name[IFNAMSIZ]; /* copied from ifmibdata */
+ struct ifmibdata if_mib;
+ struct timeval tv;
+ struct timeval tv_lastchanged;
+ uint64_t if_in_curtraffic;
+ uint64_t if_out_curtraffic;
+ uint64_t if_in_traffic_peak;
+ uint64_t if_out_traffic_peak;
+ uint64_t if_in_curpps;
+ uint64_t if_out_curpps;
+ uint64_t if_in_pps_peak;
+ uint64_t if_out_pps_peak;
+ u_int if_row; /* Index into ifmib sysctl */
+ int if_ypos; /* -1 if not being displayed */
+ bool display;
+ u_int match;
+};
+
+static int needclear = 0;
+static bool displayall = false;
+
+static void format_device_name(struct if_stat *);
+static int getifmibdata(const int, struct ifmibdata *);
+static void sort_interface_list(void);
+static u_int getifnum(void);
+static void clearifstat(void);
+
+#define IFSTAT_ERR(n, s) do { \
+ putchar('\014'); \
+ closeifstat(wnd); \
+ err((n), (s)); \
+} while (0)
+
+#define TOPLINE 3
+#define TOPLABEL \
+" Interface Traffic Peak Total"
+
+#define STARTING_ROW (TOPLINE + 1)
+#define ROW_SPACING (3)
+
+#define IN_col2 (showpps ? ifp->if_in_curpps : ifp->if_in_curtraffic)
+#define OUT_col2 (showpps ? ifp->if_out_curpps : ifp->if_out_curtraffic)
+#define IN_col3 (showpps ? \
+ ifp->if_in_pps_peak : ifp->if_in_traffic_peak)
+#define OUT_col3 (showpps ? \
+ ifp->if_out_pps_peak : ifp->if_out_traffic_peak)
+#define IN_col4 (showpps ? \
+ ifp->if_mib.ifmd_data.ifi_ipackets : ifp->if_mib.ifmd_data.ifi_ibytes)
+#define OUT_col4 (showpps ? \
+ ifp->if_mib.ifmd_data.ifi_opackets : ifp->if_mib.ifmd_data.ifi_obytes)
+
+#define EMPTY_COLUMN " "
+#define CLEAR_COLUMN(y, x) mvprintw((y), (x), "%20s", EMPTY_COLUMN);
+
+#define DOPUTRATE(c, r, d) do { \
+ CLEAR_COLUMN(r, c); \
+ if (showpps) { \
+ mvprintw(r, (c), "%10.3f %cp%s ", \
+ convert(d##_##c, curscale), \
+ *get_string(d##_##c, curscale), \
+ "/s"); \
+ } \
+ else { \
+ mvprintw(r, (c), "%10.3f %s%s ", \
+ convert(d##_##c, curscale), \
+ get_string(d##_##c, curscale), \
+ "/s"); \
+ } \
+} while (0)
+
+#define DOPUTTOTAL(c, r, d) do { \
+ CLEAR_COLUMN((r), (c)); \
+ if (showpps) { \
+ mvprintw((r), (c), "%12.3f %cp ", \
+ convert(d##_##c, SC_AUTO), \
+ *get_string(d##_##c, SC_AUTO)); \
+ } \
+ else { \
+ mvprintw((r), (c), "%12.3f %s ", \
+ convert(d##_##c, SC_AUTO), \
+ get_string(d##_##c, SC_AUTO)); \
+ } \
+} while (0)
+
+#define PUTRATE(c, r) do { \
+ DOPUTRATE(c, (r), IN); \
+ DOPUTRATE(c, (r)+1, OUT); \
+} while (0)
+
+#define PUTTOTAL(c, r) do { \
+ DOPUTTOTAL(c, (r), IN); \
+ DOPUTTOTAL(c, (r)+1, OUT); \
+} while (0)
+
+#define PUTNAME(p) do { \
+ mvprintw(p->if_ypos, 0, "%s", p->display_name); \
+ mvprintw(p->if_ypos, col2-3, "%s", (const char *)"in"); \
+ mvprintw(p->if_ypos+1, col2-3, "%s", (const char *)"out"); \
+} while (0)
+
+WINDOW *
+openifstat(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeifstat(WINDOW *w)
+{
+ struct if_stat *node = NULL;
+
+ while (!SLIST_EMPTY(&curlist)) {
+ node = SLIST_FIRST(&curlist);
+ SLIST_REMOVE_HEAD(&curlist, link);
+ free(node);
+ }
+
+ if (w != NULL) {
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+ }
+
+ return;
+}
+
+void
+labelifstat(void)
+{
+
+ wmove(wnd, TOPLINE, 0);
+ wclrtoeol(wnd);
+ mvprintw(TOPLINE, 0, "%s", TOPLABEL);
+
+ return;
+}
+
+void
+showifstat(void)
+{
+ struct if_stat *ifp = NULL;
+
+ SLIST_FOREACH(ifp, &curlist, link) {
+ if (ifp->if_ypos < LINES - 3 && ifp->if_ypos != -1) {
+ if (!ifp->display || ifp->match == 0) {
+ wmove(wnd, ifp->if_ypos, 0);
+ wclrtoeol(wnd);
+ wmove(wnd, ifp->if_ypos + 1, 0);
+ wclrtoeol(wnd);
+ } else {
+ PUTNAME(ifp);
+ PUTRATE(col2, ifp->if_ypos);
+ PUTRATE(col3, ifp->if_ypos);
+ PUTTOTAL(col4, ifp->if_ypos);
+ }
+ }
+ }
+
+ return;
+}
+
+int
+initifstat(void)
+{
+ struct if_stat *p = NULL;
+ u_int n, i;
+
+ n = getifnum();
+ if (n <= 0)
+ return (-1);
+
+ SLIST_INIT(&curlist);
+
+ for (i = 0; i < n; i++) {
+ p = (struct if_stat *)calloc(1, sizeof(struct if_stat));
+ if (p == NULL)
+ IFSTAT_ERR(1, "out of memory");
+ p->if_row = i+1;
+ if (getifmibdata(p->if_row, &p->if_mib) == -1) {
+ free(p);
+ continue;
+ }
+ SLIST_INSERT_HEAD(&curlist, p, link);
+ format_device_name(p);
+ p->match = 1;
+
+ /*
+ * Initially, we only display interfaces that have
+ * received some traffic unless display-all is on.
+ */
+ if (displayall || p->if_mib.ifmd_data.ifi_ibytes != 0)
+ p->display = true;
+ }
+
+ sort_interface_list();
+
+ return (1);
+}
+
+void
+fetchifstat(void)
+{
+ struct if_stat *ifp = NULL, *temp_var;
+ struct timeval tv, new_tv, old_tv;
+ double elapsed = 0.0;
+ uint64_t new_inb, new_outb, old_inb, old_outb = 0;
+ uint64_t new_inp, new_outp, old_inp, old_outp = 0;
+
+ SLIST_FOREACH_SAFE(ifp, &curlist, link, temp_var) {
+ /*
+ * Grab a copy of the old input/output values before we
+ * call getifmibdata().
+ */
+ old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
+ old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+ old_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
+ old_outp = ifp->if_mib.ifmd_data.ifi_opackets;
+ ifp->tv_lastchanged = ifp->if_mib.ifmd_data.ifi_lastchange;
+
+ (void)gettimeofday(&new_tv, NULL);
+ if (getifmibdata(ifp->if_row, &ifp->if_mib) == -1 ) {
+ /* if a device was removed */
+ SLIST_REMOVE(&curlist, ifp, if_stat, link);
+ free(ifp);
+ needsort = 1;
+ continue;
+ } else if (strcmp(ifp->dev_name, ifp->if_mib.ifmd_name) != 0 ) {
+ /* a device was removed and another one was added */
+ format_device_name(ifp);
+ /* clear to the current value for the new device */
+ old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
+ old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+ old_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
+ old_outp = ifp->if_mib.ifmd_data.ifi_opackets;
+ needsort = 1;
+ }
+
+ new_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
+ new_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+ new_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
+ new_outp = ifp->if_mib.ifmd_data.ifi_opackets;
+
+ /* Display interface if it's received some traffic. */
+ if (!ifp->display && new_inb > 0 && old_inb == 0) {
+ ifp->display = true;
+ needsort = 1;
+ }
+
+ /*
+ * The rest is pretty trivial. Calculate the new values
+ * for our current traffic rates, and while we're there,
+ * see if we have new peak rates.
+ */
+ old_tv = ifp->tv;
+ timersub(&new_tv, &old_tv, &tv);
+ elapsed = tv.tv_sec + (tv.tv_usec * 1e-6);
+
+ ifp->if_in_curtraffic = new_inb - old_inb;
+ ifp->if_out_curtraffic = new_outb - old_outb;
+
+ ifp->if_in_curpps = new_inp - old_inp;
+ ifp->if_out_curpps = new_outp - old_outp;
+
+ /*
+ * Rather than divide by the time specified on the comm-
+ * and line, we divide by ``elapsed'' as this is likely
+ * to be more accurate.
+ */
+ ifp->if_in_curtraffic /= elapsed;
+ ifp->if_out_curtraffic /= elapsed;
+ ifp->if_in_curpps /= elapsed;
+ ifp->if_out_curpps /= elapsed;
+
+ if (ifp->if_in_curtraffic > ifp->if_in_traffic_peak)
+ ifp->if_in_traffic_peak = ifp->if_in_curtraffic;
+
+ if (ifp->if_out_curtraffic > ifp->if_out_traffic_peak)
+ ifp->if_out_traffic_peak = ifp->if_out_curtraffic;
+
+ if (ifp->if_in_curpps > ifp->if_in_pps_peak)
+ ifp->if_in_pps_peak = ifp->if_in_curpps;
+
+ if (ifp->if_out_curpps > ifp->if_out_pps_peak)
+ ifp->if_out_pps_peak = ifp->if_out_curpps;
+
+ ifp->tv.tv_sec = new_tv.tv_sec;
+ ifp->tv.tv_usec = new_tv.tv_usec;
+
+ }
+
+ if (needsort)
+ sort_interface_list();
+
+ return;
+}
+
+/*
+ * We want to right justify our interface names against the first column
+ * (first sixteen or so characters), so we need to do some alignment.
+ * We save original name so that we can find a same spot is take by a
+ * different device.
+ */
+static void
+format_device_name(struct if_stat *ifp)
+{
+
+ if (ifp != NULL ) {
+ snprintf(ifp->display_name, IF_NAMESIZE, "%*s", IF_NAMESIZE-1,
+ ifp->if_mib.ifmd_name);
+ strcpy(ifp->dev_name, ifp->if_mib.ifmd_name);
+ }
+}
+
+static int
+check_match(const char *ifname)
+{
+ char *p = matchline, *ch, t;
+ int match = 0, mlen;
+
+ if (matchline == NULL)
+ return (0);
+
+ /* Strip leading whitespaces */
+ while (*p == ' ')
+ p ++;
+
+ ch = p;
+ while ((mlen = strcspn(ch, " ;,")) != 0) {
+ p = ch + mlen;
+ t = *p;
+ if (p - ch > 0) {
+ *p = '\0';
+ if (fnmatch(ch, ifname, FNM_CASEFOLD) == 0) {
+ *p = t;
+ return (1);
+ }
+ *p = t;
+ ch = p + strspn(p, " ;,");
+ }
+ else {
+ ch = p + strspn(p, " ;,");
+ }
+ }
+
+ return (match);
+}
+
+/*
+ * This function iterates through our list of interfaces, identifying
+ * those that are to be displayed (ifp->display = 1). For each interf-
+ * rface that we're displaying, we generate an appropriate position for
+ * it on the screen (ifp->if_ypos).
+ *
+ * This function is called any time a change is made to an interface's
+ * ``display'' state.
+ */
+void
+sort_interface_list(void)
+{
+ struct if_stat *ifp = NULL;
+ u_int y = 0;
+
+ y = STARTING_ROW;
+ SLIST_FOREACH(ifp, &curlist, link) {
+ if (matchline && !check_match(ifp->if_mib.ifmd_name))
+ ifp->match = 0;
+ else
+ ifp->match = 1;
+ if (ifp->display && ifp->match) {
+ ifp->if_ypos = y;
+ y += ROW_SPACING;
+ }
+ else
+ ifp->if_ypos = -1;
+ }
+
+ needsort = 0;
+ needclear = 1;
+}
+
+static
+unsigned int
+getifnum(void)
+{
+ u_int data = 0;
+ size_t datalen = 0;
+ static int name[] = { CTL_NET,
+ PF_LINK,
+ NETLINK_GENERIC,
+ IFMIB_SYSTEM,
+ IFMIB_IFCOUNT };
+
+ datalen = sizeof(data);
+ if (sysctl(name, 5, (void *)&data, (size_t *)&datalen, (void *)NULL,
+ (size_t)0) != 0)
+ IFSTAT_ERR(1, "sysctl error");
+ return (data);
+}
+
+static int
+getifmibdata(int row, struct ifmibdata *data)
+{
+ int ret = 0;
+ size_t datalen = 0;
+ static int name[] = { CTL_NET,
+ PF_LINK,
+ NETLINK_GENERIC,
+ IFMIB_IFDATA,
+ 0,
+ IFDATA_GENERAL };
+ datalen = sizeof(*data);
+ name[4] = row;
+
+ ret = sysctl(name, 6, (void *)data, (size_t *)&datalen, (void *)NULL,
+ (size_t)0);
+ if ((ret != 0) && (errno != ENOENT))
+ IFSTAT_ERR(2, "sysctl error getting interface data");
+
+ return (ret);
+}
+
+int
+cmdifstat(const char *cmd, const char *args)
+{
+ int retval = 0;
+
+ retval = ifcmd(cmd, args);
+ /* ifcmd() returns 1 on success */
+ if (retval == 1) {
+ if (needclear)
+ clearifstat();
+ }
+ else if (prefix(cmd, "all")) {
+ retval = 1;
+ displayall = true;
+ }
+ return (retval);
+}
+
+static void
+clearifstat(void)
+{
+
+ showifstat();
+ refresh();
+ werase(wnd);
+ labelifstat();
+ needclear = 0;
+}
diff --git a/usr.bin/systat/iolat.c b/usr.bin/systat/iolat.c
new file mode 100644
index 000000000000..9535297df3ee
--- /dev/null
+++ b/usr.bin/systat/iolat.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2021 Netflix, Inc
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+
+#include <devstat.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+#define CAM_BASE "kern.cam"
+#define LATENCY ".latencies"
+#define CAM_IOSCHED_BASE "kern.cam.iosched.bucket_base_us"
+
+#define DEV_NAMSIZE 32
+#define OP_NAMSIZE 16
+#define MAX_LATS 32
+
+static double high_thresh = 500;
+static double med_thresh = 300;
+static bool docolor = true;
+
+static int ndevs;
+static SLIST_HEAD(, iosched_stat) curlist;
+
+struct iosched_op_stat {
+ int nlats;
+ uint64_t lats[MAX_LATS];
+ uint64_t prev_lats[MAX_LATS];
+};
+
+enum { OP_READ = 0, OP_WRITE, OP_TRIM, NUM_OPS };
+static const char *ops[NUM_OPS] = { "read", "write", "trim" };
+#define OP_READ_MASK (1 << OP_READ)
+#define OP_WRITE_MASK (1 << OP_WRITE)
+#define OP_TRIM_MASK (1 << OP_TRIM)
+
+static uint32_t flags = OP_READ_MASK | OP_WRITE_MASK | OP_TRIM_MASK;
+
+struct iosched_stat {
+ SLIST_ENTRY(iosched_stat) link;
+ char dev_name[DEV_NAMSIZE];
+ int unit;
+ struct iosched_op_stat op_stats[NUM_OPS];
+};
+
+static int name2oid(const char *, int *);
+static int walk_sysctl(int *, size_t);
+
+static int
+name2oid(const char *name, int *oidp)
+{
+ int oid[2];
+ int i;
+ size_t j;
+
+ oid[0] = CTL_SYSCTL;
+ oid[1] = CTL_SYSCTL_NAME2OID;
+
+ j = CTL_MAXNAME * sizeof(int);
+ i = sysctl(oid, 2, oidp, &j, name, strlen(name));
+ if (i < 0)
+ return (i);
+ j /= sizeof(int);
+ return (j);
+}
+
+static size_t /* Includes the trailing NUL */
+oid2name(int *oid, size_t nlen, char *name, size_t namlen)
+{
+ int qoid[CTL_MAXNAME + 2];
+ int i;
+ size_t j;
+
+ bzero(name, namlen);
+ qoid[0] = CTL_SYSCTL;
+ qoid[1] = CTL_SYSCTL_NAME;
+ memcpy(qoid + 2, oid, nlen * sizeof(int));
+ j = namlen;
+ i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
+ if (i || !j)
+ err(1, "sysctl name %d %zu %d", i, j, errno);
+ return (j);
+}
+
+static int
+oidfmt(int *oid, int len, u_int *kind)
+{
+ int qoid[CTL_MAXNAME+2];
+ u_char buf[BUFSIZ];
+ int i;
+ size_t j;
+
+ qoid[0] = CTL_SYSCTL;
+ qoid[1] = CTL_SYSCTL_OIDFMT;
+ memcpy(qoid + 2, oid, len * sizeof(int));
+
+ j = sizeof(buf);
+ i = sysctl(qoid, len + 2, buf, &j, 0, 0);
+ if (i)
+ err(1, "sysctl fmt %d %zu %d", i, j, errno);
+ *kind = *(u_int *)buf;
+ return (0);
+}
+
+static int
+split_u64(char *str, const char *delim, uint64_t *buckets, int *nbuckets)
+{
+ int n = *nbuckets, i;
+ char *v;
+
+ memset(buckets, 0, n * sizeof(buckets[0]));
+ for (i = 0; (v = strsep(&str, delim)) != NULL && i < n; i++) {
+ buckets[i] = strtoull(v, NULL, 10);
+ }
+ if (i < n)
+ *nbuckets = i;
+ return (i < n);
+}
+
+static double baselat = 0.000020;
+
+static float
+pest(int permill, uint64_t *lats, int nlat)
+{
+ uint64_t tot, samp;
+ int i;
+ float b1, b2;
+
+ for (tot = 0, i = 0; i < nlat; i++)
+ tot += lats[i];
+ if (tot == 0)
+ return -nanf("");
+ if (tot < (uint64_t)2000 / (1000 - permill))
+ return nanf("");
+ samp = tot * permill / 1000;
+ if (samp < lats[0])
+ return baselat * (float)samp / lats[0]; /* linear interpolation 0 and baselat */
+ for (tot = 0, i = 0; samp >= tot && i < nlat; i++)
+ tot += lats[i];
+ i--;
+ b1 = baselat * (1 << (i - 1));
+ b2 = baselat * (1 << i);
+ /* Should expoentially interpolate between buckets -- doing linear instead */
+ return b1 + (b2 - b1) * (float)(lats[i] - (tot - samp)) / lats[i];
+}
+
+static int
+op2num(const char *op)
+{
+ for (int i = 0; i < NUM_OPS; i++)
+ if (strcmp(op, ops[i]) == 0)
+ return i;
+ return -1;
+}
+
+static struct iosched_op_stat *
+find_dev(const char *dev, int unit, int op)
+{
+ struct iosched_stat *isp;
+ struct iosched_op_stat *iosp;
+
+ SLIST_FOREACH(isp, &curlist, link) {
+ if (strcmp(isp->dev_name, dev) != 0 || isp->unit != unit)
+ continue;
+ iosp = &isp->op_stats[op];
+ return iosp;
+ }
+ return NULL;
+}
+
+static struct iosched_op_stat *
+alloc_dev(const char *dev, int unit, int op)
+{
+ struct iosched_stat *isp;
+ struct iosched_op_stat *iosp;
+
+ isp = malloc(sizeof(*isp));
+ if (isp == NULL)
+ return NULL;
+ strlcpy(isp->dev_name, dev, sizeof(isp->dev_name));
+ isp->unit = unit;
+ SLIST_INSERT_HEAD(&curlist, isp, link);
+ ndevs++;
+ iosp = &isp->op_stats[op];
+ return iosp;
+}
+
+#define E3 1000.0
+static void
+update_dev(const char *dev, int unit, int op, uint64_t *lats, int nlat)
+{
+ struct iosched_op_stat *iosp;
+
+ iosp = find_dev(dev, unit, op);
+ if (iosp == NULL)
+ iosp = alloc_dev(dev, unit, op);
+ if (iosp == NULL)
+ return;
+ iosp->nlats = nlat;
+ memcpy(iosp->prev_lats, iosp->lats, iosp->nlats * sizeof(uint64_t));
+ memcpy(iosp->lats, lats, iosp->nlats * sizeof(uint64_t));
+// printf("%s%d: %-6s %.3f %.3f %.3f %.3f\r\n",
+// dev, unit, operation, E3 * pest(500, lats, nlat), E3 * pest(900, lats, nlat),
+// E3 * pest(990, lats, nlat), E3 * pest(999, lats, nlat));
+}
+
+static int
+walk_sysctl(int *base_oid, size_t len)
+{
+ int qoid[CTL_MAXNAME + 2], oid[CTL_MAXNAME];
+ size_t l1, l2;
+ char name[BUFSIZ];
+
+ if (len > CTL_MAXNAME)
+ err(1, "Length %zd too long", len);
+
+ qoid[0] = CTL_SYSCTL;
+ qoid[1] = CTL_SYSCTL_NEXT;
+ l1 = 2;
+ memcpy(qoid + 2, base_oid, len * sizeof(int));
+ l1 += len;
+ for (;;) {
+ /*
+ * Get the next one or return when we get to the end of the
+ * sysctls in the kernel.
+ */
+ l2 = sizeof(oid);
+ if (sysctl(qoid, l1, oid, &l2, 0, 0) != 0) {
+ if (errno == ENOENT)
+ return (0);
+ err(1, "sysctl(getnext) %zu", l2);
+ }
+
+ l2 /= sizeof(int);
+
+ /*
+ * Bail if we're seeing OIDs that don't have the
+ * same prefix or can't have the same prefix.
+ */
+ if (l2 < len ||
+ memcmp(oid, base_oid, len * sizeof(int)) != 0)
+ return (0);
+
+ /*
+ * Get the name, validate it's one we're looking for,
+ * parse the latency and add to list.
+ */
+ do {
+ int nlat;
+ size_t l3;
+ char val[BUFSIZ];
+ char *walker, *dev, *opstr;
+ uint64_t latvals[MAX_LATS];
+ u_int kind;
+ int unit, op;
+
+ l1 = oid2name(oid, l2, name, sizeof(name));
+ if (strcmp(name + l1 - strlen(LATENCY) - 1, LATENCY) != 0)
+ break;
+ if (oidfmt(oid, l2, &kind) != 0)
+ err(1, "oidfmt");
+ if ((kind & CTLTYPE) != CTLTYPE_STRING)
+ errx(1, "string");
+ l3 = sizeof(val);
+ if (sysctl(oid, l2, val, &l3, 0, 0) != 0)
+ err(1, "sysctl");
+ val[l3] = '\0';
+ nlat = nitems(latvals);
+ if (split_u64(val, ",", latvals, &nlat) == 0)
+ break;
+ walker = name + strlen(CAM_BASE) + 1;
+ dev = strsep(&walker, ".");
+ unit = (int)strtol(strsep(&walker, "."), NULL, 10);
+ strsep(&walker, ".");
+ opstr = strsep(&walker, ".");
+ op = op2num(opstr);
+ if (op < 0)
+ break;
+ update_dev(dev, unit, op, latvals, nlat);
+ } while (false);
+
+ memcpy(qoid + 2, oid, l2 * sizeof(int));
+ l1 = 2 + l2;
+ }
+}
+
+void
+closeiolat(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+static void
+doublecmd(const char *cmd, double *v)
+{
+ const char *p;
+ double tv;
+
+ p = strchr(cmd, '=');
+ if (p == NULL)
+ return; /* XXX Tell the user something? */
+ if (sscanf(p + 1, "%lf", &tv) != 1)
+ return; /* XXX Tell the user something? */
+ *v = tv;
+}
+
+int
+cmdiolat(const char *cmd __unused, const char *args __unused)
+{
+ fprintf(stderr, "CMD IS '%s'\n\n", cmd);
+ if (prefix(cmd, "trim"))
+ flags ^= OP_TRIM_MASK;
+ else if (prefix(cmd, "read"))
+ flags ^= OP_READ_MASK;
+ else if (prefix(cmd, "write"))
+ flags ^= OP_WRITE_MASK;
+ else if (prefix(cmd, "color"))
+ docolor = !docolor;
+ else if (prefix("high", cmd))
+ doublecmd(cmd, &high_thresh);
+ else if (prefix("med", cmd))
+ doublecmd(cmd, &med_thresh);
+ else
+ return (0);
+ wclear(wnd);
+ labeliolat();
+ refresh();
+ return (1);
+}
+
+int
+initiolat(void)
+{
+ int cam[CTL_MAXNAME];
+ uint64_t sbt_base;
+ size_t len = sizeof(sbt_base);
+
+ SLIST_INIT(&curlist);
+
+ baselat = 1e-3; /* old default */
+ if (sysctlbyname(CAM_IOSCHED_BASE, &sbt_base, &len, NULL, 0) == 0)
+ baselat = sbt_base * 1e-6; /* Convert to microseconds */
+
+ name2oid(CAM_BASE, cam);
+ walk_sysctl(cam, 2);
+ return (1);
+}
+
+void
+fetchiolat(void)
+{
+ int cam[CTL_MAXNAME];
+
+ name2oid(CAM_BASE, cam);
+ walk_sysctl(cam, 2);
+}
+
+#define INSET 10
+
+void
+labeliolat(void)
+{
+ int _col, ndrives, lpr, row, j;
+ int regions __unused;
+ struct iosched_stat *isp;
+ char tmpstr[32];
+#define COLWIDTH 29
+#define DRIVESPERLINE ((getmaxx(wnd) - 1 - INSET) / COLWIDTH)
+ ndrives = ndevs; // XXX FILTER XXX
+ regions = howmany(ndrives, DRIVESPERLINE);
+ lpr = 2; /* for headers */
+ for (int i = 0; i < NUM_OPS; i++) {
+ if (flags & (1 << i))
+ lpr++;
+ }
+ row = 0;
+ _col = INSET;
+ j = 2;
+ if (flags & OP_READ_MASK)
+ mvwaddstr(wnd, row + j++, 1, "read");
+ if (flags & OP_WRITE_MASK)
+ mvwaddstr(wnd, row + j++, 1, "write");
+ if (flags & OP_TRIM_MASK)
+ mvwaddstr(wnd, row + j++, 1, "trim");
+ SLIST_FOREACH(isp, &curlist, link) {
+ if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) {
+ _col = INSET;
+ row += lpr + 1;
+ if (row > getmaxy(wnd) - 1 - (lpr + 1))
+ break;
+ j = 2;
+ if (flags & OP_READ_MASK)
+ mvwaddstr(wnd, row + j++, 1, "read");
+ if (flags & OP_WRITE_MASK)
+ mvwaddstr(wnd, row + j++, 1, "write");
+ if (flags & OP_TRIM_MASK)
+ mvwaddstr(wnd, row + j++, 1, "trim");
+ }
+ snprintf(tmpstr, sizeof(tmpstr), "%s%d", isp->dev_name, isp->unit);
+ mvwaddstr(wnd, row, _col + (COLWIDTH - strlen(tmpstr)) / 2, tmpstr);
+ mvwaddstr(wnd, row + 1, _col, " p50 p90 p99 p99.9");
+ _col += COLWIDTH;
+ }
+}
+
+WINDOW *
+openiolat(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+static void
+fmt(float f, char *buf, size_t len)
+{
+ if (isnan(f))
+ strlcpy(buf, " - ", len);
+ else if (f >= 1000.0)
+ snprintf(buf, len, "%6d", (int)f);
+ else if (f >= 100.0)
+ snprintf(buf, len, "%6.1f", f);
+ else if (f >= 10.0)
+ snprintf(buf, len, "%6.2f", f);
+ else
+ snprintf(buf, len, "%6.3f", f);
+}
+
+static void
+latout(double lat, int y, int x)
+{
+ int i;
+ char tmpstr[32];
+
+ fmt(lat, tmpstr, sizeof(tmpstr));
+ if (isnan(lat))
+ i = 4;
+ else if (lat > high_thresh)
+ i = 3;
+ else if (lat > med_thresh)
+ i = 2;
+ else
+ i = 1;
+ if (docolor)
+ wattron(wnd, COLOR_PAIR(i));
+ mvwaddstr(wnd, y, x, tmpstr);
+ if (docolor)
+ wattroff(wnd, COLOR_PAIR(i));
+}
+
+void
+showiolat(void)
+{
+ int _col, ndrives, lpr, row, k;
+ int regions __unused;
+ struct iosched_stat *isp;
+ struct iosched_op_stat *iosp;
+#define COLWIDTH 29
+#define DRIVESPERLINE ((getmaxx(wnd) - 1 - INSET) / COLWIDTH)
+ ndrives = ndevs; // XXX FILTER XXX
+ regions = howmany(ndrives, DRIVESPERLINE);
+ lpr = 2; /* XXX */
+ for (int i = 0; i < NUM_OPS; i++) {
+ if (flags & (1 << i))
+ lpr++;
+ }
+ row = 0;
+ _col = INSET;
+ SLIST_FOREACH(isp, &curlist, link) {
+ if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) {
+ _col = INSET;
+ row += lpr + 1;
+ if (row > getmaxy(wnd) - 1 - (lpr + 1))
+ break;
+ }
+ k = 2;
+ for (int i = 0; i < NUM_OPS; i++) {
+ uint64_t lats[MAX_LATS];
+ int nlats;
+ float p50, p90, p99, p999;
+
+ if ((flags & (1 << i)) == 0)
+ continue;
+ iosp = &isp->op_stats[i];
+ nlats = iosp->nlats;
+ memset(lats, 0, sizeof(lats));
+ for (int j = 0; j < iosp->nlats; j++)
+ lats[j] = iosp->lats[j] - iosp->prev_lats[j];
+ p50 = pest(500, lats, nlats) * E3;
+ p90 = pest(900, lats, nlats) * E3;
+ p99 = pest(990, lats, nlats) * E3;
+ p999 = pest(999, lats, nlats) * E3;
+ latout(p50, row + k, _col);
+ latout(p90, row + k, _col + 7);
+ latout(p99, row + k, _col + 14);
+ latout(p999, row + k, _col + 21);
+ k++;
+ }
+ _col += COLWIDTH;
+ }
+}
diff --git a/usr.bin/systat/iostat.c b/usr.bin/systat/iostat.c
new file mode 100644
index 000000000000..ee1389765b93
--- /dev/null
+++ b/usr.bin/systat/iostat.c
@@ -0,0 +1,384 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1998 Kenneth D. Merry.
+ * 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 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 AUTHOR 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.
+ */
+/*
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+
+#include <devstat.h>
+#include <err.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+static int linesperregion;
+static double etime;
+static bool numbers = false; /* default display bar graphs */
+static bool kbpt = false; /* default ms/seek shown */
+
+static int barlabels(int);
+static void histogram(long double, int, double);
+static int numlabels(int);
+static int devstats(int, int, int);
+static void stat1(int, int);
+
+WINDOW *
+openiostat(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeiostat(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+int
+initiostat(void)
+{
+ /*
+ * This value for maxshowdevs (100) is bogus. I'm not sure exactly
+ * how to calculate it, though.
+ */
+ if (dsinit(7) != 1)
+ return(0);
+
+ return(1);
+}
+
+void
+fetchiostat(void)
+{
+ struct devinfo *tmp_dinfo;
+ size_t len;
+
+ len = sizeof(cur_dev.cp_time);
+ if (sysctlbyname("kern.cp_time", &cur_dev.cp_time, &len, NULL, 0)
+ || len != sizeof(cur_dev.cp_time)) {
+ perror("kern.cp_time");
+ exit (1);
+ }
+ tmp_dinfo = last_dev.dinfo;
+ last_dev.dinfo = cur_dev.dinfo;
+ cur_dev.dinfo = tmp_dinfo;
+
+ last_dev.snap_time = cur_dev.snap_time;
+
+ /*
+ * Here what we want to do is refresh our device stats.
+ * getdevs() returns 1 when the device list has changed.
+ * If the device list has changed, we want to go through
+ * the selection process again, in case a device that we
+ * were previously displaying has gone away.
+ */
+ switch (devstat_getdevs(NULL, &cur_dev)) {
+ case -1:
+ errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ cmdiostat("refresh", NULL);
+ break;
+ default:
+ break;
+ }
+ num_devices = cur_dev.dinfo->numdevs;
+ generation = cur_dev.dinfo->generation;
+
+}
+
+#define INSET 10
+
+void
+labeliostat(void)
+{
+ int row;
+
+ row = 0;
+ wmove(wnd, row, 0); wclrtobot(wnd);
+ mvwaddstr(wnd, row++, INSET,
+ "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
+ mvwaddstr(wnd, row++, 0, "cpu user|");
+ mvwaddstr(wnd, row++, 0, " nice|");
+ mvwaddstr(wnd, row++, 0, " system|");
+ mvwaddstr(wnd, row++, 0, "interrupt|");
+ mvwaddstr(wnd, row++, 0, " idle|");
+ if (numbers)
+ row = numlabels(row + 1);
+ else
+ row = barlabels(row + 1);
+}
+
+static int
+numlabels(int row)
+{
+ int i, _col, regions, ndrives;
+ char tmpstr[32];
+
+#define COLWIDTH 17
+#define DRIVESPERLINE ((getmaxx(wnd) - 1 - INSET) / COLWIDTH)
+ for (ndrives = 0, i = 0; i < num_devices; i++)
+ if (dev_select[i].selected)
+ ndrives++;
+ regions = howmany(ndrives, DRIVESPERLINE);
+ /*
+ * Deduct -regions for blank line after each scrolling region.
+ */
+ linesperregion = (getmaxy(wnd) - 1 - row - regions) / regions;
+ /*
+ * Minimum region contains space for two
+ * label lines and one line of statistics.
+ */
+ if (linesperregion < 3)
+ linesperregion = 3;
+ _col = INSET;
+ for (i = 0; i < num_devices; i++)
+ if (dev_select[i].selected) {
+ if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) {
+ _col = INSET, row += linesperregion + 1;
+ if (row > getmaxy(wnd) - 1 - (linesperregion + 1))
+ break;
+ }
+ snprintf(tmpstr, sizeof(tmpstr), "%s%d", dev_select[i].device_name,
+ dev_select[i].unit_number);
+ mvwaddstr(wnd, row, _col + 4, tmpstr);
+ mvwaddstr(wnd, row + 1, _col, " KB/t tps MB/s ");
+ _col += COLWIDTH;
+ }
+ if (_col)
+ row += linesperregion + 1;
+ return (row);
+}
+
+static int
+barlabels(int row)
+{
+ int i;
+ char tmpstr[32];
+
+ mvwaddstr(wnd, row++, INSET,
+ "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
+ linesperregion = 2 + kbpt;
+ for (i = 0; i < num_devices; i++)
+ if (dev_select[i].selected) {
+ if (row > getmaxy(wnd) - 1 - linesperregion)
+ break;
+ snprintf(tmpstr, sizeof(tmpstr), "%s%d", dev_select[i].device_name,
+ dev_select[i].unit_number);
+ mvwprintw(wnd, row++, 0, "%-5.5s MB/s|",
+ tmpstr);
+ mvwaddstr(wnd, row++, 0, " tps|");
+ if (kbpt)
+ mvwaddstr(wnd, row++, 0, " KB/t|");
+ }
+ return (row);
+}
+
+void
+showiostat(void)
+{
+ long t;
+ int i, row, _col;
+
+#define X(fld) t = cur_dev.fld[i]; cur_dev.fld[i] -= last_dev.fld[i]; last_dev.fld[i] = t
+ etime = 0;
+ for(i = 0; i < CPUSTATES; i++) {
+ X(cp_time);
+ etime += cur_dev.cp_time[i];
+ }
+ if (etime == 0.0)
+ etime = 1.0;
+ etime /= hertz;
+ row = 1;
+ for (i = 0; i < CPUSTATES; i++)
+ stat1(row++, i);
+ if (!numbers) {
+ row += 2;
+ for (i = 0; i < num_devices; i++)
+ if (dev_select[i].selected) {
+ if (row > getmaxy(wnd) - linesperregion)
+ break;
+ row = devstats(row, INSET, i);
+ }
+ return;
+ }
+ _col = INSET;
+ wmove(wnd, row + linesperregion, 0);
+ wdeleteln(wnd);
+ wmove(wnd, row + 3, 0);
+ winsertln(wnd);
+ for (i = 0; i < num_devices; i++)
+ if (dev_select[i].selected) {
+ if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) {
+ _col = INSET, row += linesperregion + 1;
+ if (row > getmaxy(wnd) - 1 - (linesperregion + 1))
+ break;
+ wmove(wnd, row + linesperregion, 0);
+ wdeleteln(wnd);
+ wmove(wnd, row + 3, 0);
+ winsertln(wnd);
+ }
+ (void) devstats(row + 3, _col, i);
+ _col += COLWIDTH;
+ }
+}
+
+static int
+devstats(int row, int _col, int dn)
+{
+ long double transfers_per_second;
+ long double kb_per_transfer, mb_per_second;
+ long double busy_seconds;
+ int di;
+
+ di = dev_select[dn].position;
+
+ busy_seconds = cur_dev.snap_time - last_dev.snap_time;
+
+ if (devstat_compute_statistics(&cur_dev.dinfo->devices[di],
+ &last_dev.dinfo->devices[di], busy_seconds,
+ DSM_KB_PER_TRANSFER, &kb_per_transfer,
+ DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
+ DSM_MB_PER_SECOND, &mb_per_second, DSM_NONE) != 0)
+ errx(1, "%s", devstat_errbuf);
+
+ if (numbers) {
+ mvwprintw(wnd, row, _col, " %5.2Lf %3.0Lf %5.2Lf ",
+ kb_per_transfer, transfers_per_second,
+ mb_per_second);
+ return(row);
+ }
+ wmove(wnd, row++, _col);
+ histogram(mb_per_second, 50, .5);
+ wmove(wnd, row++, _col);
+ histogram(transfers_per_second, 50, .5);
+ if (kbpt) {
+ wmove(wnd, row++, _col);
+ histogram(kb_per_transfer, 50, .5);
+ }
+
+ return(row);
+
+}
+
+static void
+stat1(int row, int o)
+{
+ int i;
+ double dtime;
+
+ dtime = 0.0;
+ for (i = 0; i < CPUSTATES; i++)
+ dtime += cur_dev.cp_time[i];
+ if (dtime == 0.0)
+ dtime = 1.0;
+ wmove(wnd, row, INSET);
+#define CPUSCALE 0.5
+ histogram(100.0 * cur_dev.cp_time[o] / dtime, 50, CPUSCALE);
+}
+
+static void
+histogram(long double val, int colwidth, double scale)
+{
+ char buf[10];
+ int k;
+ int v = (int)(val * scale) + 0.5;
+
+ k = MIN(v, colwidth);
+ if (v > colwidth) {
+ snprintf(buf, sizeof(buf), "%5.2Lf", val);
+ k -= strlen(buf);
+ while (k--)
+ waddch(wnd, 'X');
+ waddstr(wnd, buf);
+ return;
+ }
+ while (k--)
+ waddch(wnd, 'X');
+ wclrtoeol(wnd);
+}
+
+int
+cmdiostat(const char *cmd, const char *args)
+{
+
+ if (prefix(cmd, "kbpt"))
+ kbpt = !kbpt;
+ else if (prefix(cmd, "numbers"))
+ numbers = true;
+ else if (prefix(cmd, "bars"))
+ numbers = false;
+ else if (!dscmd(cmd, args, 100, &cur_dev))
+ return (0);
+ wclear(wnd);
+ labeliostat();
+ refresh();
+ return (1);
+}
diff --git a/usr.bin/systat/ip.c b/usr.bin/systat/ip.c
new file mode 100644
index 000000000000..6cb3787b3f91
--- /dev/null
+++ b/usr.bin/systat/ip.c
@@ -0,0 +1,336 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/* From:
+ "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
+*/
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+struct stat {
+ struct ipstat i;
+ struct udpstat u;
+};
+
+static struct stat curstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 IP Input IP Output
+01999999999 total packets received 999999999 total packets sent
+02999999999 - with bad checksums 999999999 - generated locally
+03999999999 - too short for header 999999999 - output drops
+04999999999 - too short for data 999999999 output fragments generated
+05999999999 - with invalid hlen 999999999 - fragmentation failed
+06999999999 - with invalid length 999999999 destinations unreachable
+07999999999 - with invalid version 999999999 packets output via raw IP
+08999999999 - jumbograms
+09999999999 total fragments received UDP Statistics
+10999999999 - fragments dropped 999999999 total input packets
+11999999999 - fragments timed out 999999999 - too short for header
+12999999999 - packets reassembled ok 999999999 - invalid checksum
+13999999999 packets forwarded 999999999 - no checksum
+14999999999 - unreachable dests 999999999 - invalid length
+15999999999 - redirects generated 999999999 - no socket for dest port
+16999999999 option errors 999999999 - no socket for broadcast
+17999999999 unwanted multicasts 999999999 - socket buffer full
+18999999999 delivered to upper layer 999999999 total output packets
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+openip(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeip(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labelip(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 10, str)
+#define R(row, str) mvwprintw(wnd, row, 45, str);
+ L(0, "IP Input"); R(0, "IP Output");
+ L(1, "total packets received"); R(1, "total packets sent");
+ L(2, "- with bad checksums"); R(2, "- generated locally");
+ L(3, "- too short for header"); R(3, "- output drops");
+ L(4, "- too short for data"); R(4, "output fragments generated");
+ L(5, "- with invalid hlen"); R(5, "- fragmentation failed");
+ L(6, "- with invalid length"); R(6, "destinations unreachable");
+ L(7, "- with invalid version"); R(7, "packets output via raw IP");
+ L(8, "- jumbograms");
+ L(9, "total fragments received"); R(9, "UDP Statistics");
+ L(10, "- fragments dropped"); R(10, "total input packets");
+ L(11, "- fragments timed out"); R(11, "- too short for header");
+ L(12, "- packets reassembled ok"); R(12, "- invalid checksum");
+ L(13, "packets forwarded"); R(13, "- no checksum");
+ L(14, "- unreachable dests"); R(14, "- invalid length");
+ L(15, "- redirects generated"); R(15, "- no socket for dest port");
+ L(16, "option errors"); R(16, "- no socket for broadcast");
+ L(17, "unwanted multicasts"); R(17, "- socket buffer full");
+ L(18, "delivered to upper layer"); R(18, "total output packets");
+#undef L
+#undef R
+}
+
+static void
+domode(struct stat *ret)
+{
+ const struct stat *sub;
+ int divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = curstat;
+ return;
+ }
+#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
+ DO(i.ips_total);
+ DO(i.ips_badsum);
+ DO(i.ips_tooshort);
+ DO(i.ips_toosmall);
+ DO(i.ips_badhlen);
+ DO(i.ips_badlen);
+ DO(i.ips_fragments);
+ DO(i.ips_fragdropped);
+ DO(i.ips_fragtimeout);
+ DO(i.ips_forward);
+ DO(i.ips_cantforward);
+ DO(i.ips_redirectsent);
+ DO(i.ips_noproto);
+ DO(i.ips_delivered);
+ DO(i.ips_localout);
+ DO(i.ips_odropped);
+ DO(i.ips_reassembled);
+ DO(i.ips_fragmented);
+ DO(i.ips_ofragments);
+ DO(i.ips_cantfrag);
+ DO(i.ips_badoptions);
+ DO(i.ips_noroute);
+ DO(i.ips_badvers);
+ DO(i.ips_rawout);
+ DO(i.ips_toolong);
+ DO(i.ips_notmember);
+ DO(u.udps_ipackets);
+ DO(u.udps_hdrops);
+ DO(u.udps_badsum);
+ DO(u.udps_nosum);
+ DO(u.udps_badlen);
+ DO(u.udps_noport);
+ DO(u.udps_noportbcast);
+ DO(u.udps_fullsock);
+ DO(u.udps_opackets);
+#undef DO
+}
+
+void
+showip(void)
+{
+ struct stat stats;
+ uint64_t totalout;
+
+ domode(&stats);
+ totalout = stats.i.ips_forward + stats.i.ips_localout;
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat)
+
+ DO(i.ips_total, 1, 0);
+ mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout);
+ DO(i.ips_badsum, 2, 0);
+ DO(i.ips_localout, 2, 35);
+ DO(i.ips_tooshort, 3, 0);
+ DO(i.ips_odropped, 3, 35);
+ DO(i.ips_toosmall, 4, 0);
+ DO(i.ips_ofragments, 4, 35);
+ DO(i.ips_badhlen, 5, 0);
+ DO(i.ips_cantfrag, 5, 35);
+ DO(i.ips_badlen, 6, 0);
+ DO(i.ips_noroute, 6, 35);
+ DO(i.ips_badvers, 7, 0);
+ DO(i.ips_rawout, 7, 35);
+ DO(i.ips_toolong, 8, 0);
+ DO(i.ips_fragments, 9, 0);
+ DO(i.ips_fragdropped, 10, 0);
+ DO(u.udps_ipackets, 10, 35);
+ DO(i.ips_fragtimeout, 11, 0);
+ DO(u.udps_hdrops, 11, 35);
+ DO(i.ips_reassembled, 12, 0);
+ DO(u.udps_badsum, 12, 35);
+ DO(i.ips_forward, 13, 0);
+ DO(u.udps_nosum, 13, 35);
+ DO(i.ips_cantforward, 14, 0);
+ DO(u.udps_badlen, 14, 35);
+ DO(i.ips_redirectsent, 15, 0);
+ DO(u.udps_noport, 15, 35);
+ DO(i.ips_badoptions, 16, 0);
+ DO(u.udps_noportbcast, 16, 35);
+ DO(i.ips_notmember, 17, 0);
+ DO(u.udps_fullsock, 17, 35);
+ DO(i.ips_delivered, 18, 0);
+ DO(u.udps_opackets, 18, 35);
+#undef DO
+}
+
+int
+initip(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_IP;
+ name[3] = IPCTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting ipstat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat.i) {
+ error("ipstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat.i, &len, 0, 0) < 0) {
+ error("sysctl getting ipstat failed");
+ return 0;
+ }
+ name[2] = IPPROTO_UDP;
+ name[3] = UDPCTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting udpstat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat.u) {
+ error("ipstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat.u, &len, 0, 0) < 0) {
+ error("sysctl getting udpstat failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+resetip(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_IP;
+ name[3] = IPCTL_STATS;
+
+ len = sizeof initstat.i;
+ if (sysctl(name, 4, &initstat.i, &len, 0, 0) < 0) {
+ error("sysctl getting ipstat failed");
+ }
+ name[2] = IPPROTO_UDP;
+ name[3] = UDPCTL_STATS;
+
+ len = sizeof initstat.u;
+ if (sysctl(name, 4, &initstat.u, &len, 0, 0) < 0) {
+ error("sysctl getting udpstat failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchip(void)
+{
+ int name[4];
+ size_t len;
+
+ oldstat = curstat;
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_IP;
+ name[3] = IPCTL_STATS;
+ len = sizeof curstat.i;
+
+ if (sysctl(name, 4, &curstat.i, &len, 0, 0) < 0)
+ return;
+ name[2] = IPPROTO_UDP;
+ name[3] = UDPCTL_STATS;
+ len = sizeof curstat.u;
+
+ if (sysctl(name, 4, &curstat.u, &len, 0, 0) < 0)
+ return;
+}
diff --git a/usr.bin/systat/ip6.c b/usr.bin/systat/ip6.c
new file mode 100644
index 000000000000..f8d7f182d507
--- /dev/null
+++ b/usr.bin/systat/ip6.c
@@ -0,0 +1,299 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/* From:
+ "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp"
+*/
+
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet6/ip6_var.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct ip6stat curstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 IPv6 Input IPv6 Output
+019999999 total packets received 999999999 total packets sent
+029999999 - too short for header 999999999 - generated locally
+039999999 - too short for data 999999999 - output drops
+049999999 - with invalid version 999999999 output fragments generated
+059999999 total fragments received 999999999 - fragmentation failed
+069999999 - fragments dropped 999999999 destinations unreachable
+079999999 - fragments timed out 999999999 packets output via raw IP
+089999999 - fragments overflown
+099999999 - packets reassembled ok Input next-header histogram
+109999999 packets forwarded 999999999 - destination options
+119999999 - unreachable dests 999999999 - hop-by-hop options
+129999999 - redirects generated 999999999 - IPv4
+139999999 option errors 999999999 - TCP
+149999999 unwanted multicasts 999999999 - UDP
+159999999 delivered to upper layer 999999999 - IPv6
+169999999 bad scope packets 999999999 - routing header
+179999999 address selection failed 999999999 - fragmentation header
+18 999999999 - ICMP6
+19 999999999 - none
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+openip6(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeip6(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labelip6(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 10, str)
+#define R(row, str) mvwprintw(wnd, row, 45, str);
+ L(0, "IPv6 Input"); R(0, "IPv6 Output");
+ L(1, "total packets received"); R(1, "total packets sent");
+ L(2, "- too short for header"); R(2, "- generated locally");
+ L(3, "- too short for data"); R(3, "- output drops");
+ L(4, "- with invalid version"); R(4, "output fragments generated");
+ L(5, "total fragments received"); R(5, "- fragmentation failed");
+ L(6, "- fragments dropped"); R(6, "destinations unreachable");
+ L(7, "- fragments timed out"); R(7, "packets output via raw IP");
+ L(8, "- fragments overflown");
+ L(9, "- atomic fragments"); R(9, "Input next-header histogram");
+ L(10, "- packets reassembled ok"); R(10, " - destination options");
+ L(11, "packets forwarded"); R(11, " - hop-by-hop options");
+ L(12, "- unreachable dests"); R(12, " - IPv4");
+ L(13, "- redirects generated"); R(13, " - TCP");
+ L(14, "option errors"); R(14, " - UDP");
+ L(15, "unwanted multicasts"); R(15, " - IPv6");
+ L(16, "delivered to upper layer"); R(16, " - routing header");
+ L(17, "bad scope packets"); R(17, " - fragmentation header");
+ L(18, "address selection failed");R(18, " - ICMP6");
+ R(19, " - none");
+#undef L
+#undef R
+}
+
+static void
+domode(struct ip6stat *ret)
+{
+ const struct ip6stat *sub;
+ int divisor = 1, i;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = curstat;
+ return;
+ }
+#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
+ DO(ip6s_total);
+ DO(ip6s_tooshort);
+ DO(ip6s_toosmall);
+ DO(ip6s_fragments);
+ DO(ip6s_fragdropped);
+ DO(ip6s_fragtimeout);
+ DO(ip6s_fragoverflow);
+ DO(ip6s_atomicfrags);
+ DO(ip6s_forward);
+ DO(ip6s_cantforward);
+ DO(ip6s_redirectsent);
+ DO(ip6s_delivered);
+ DO(ip6s_localout);
+ DO(ip6s_odropped);
+ DO(ip6s_reassembled);
+ DO(ip6s_fragmented);
+ DO(ip6s_ofragments);
+ DO(ip6s_cantfrag);
+ DO(ip6s_badoptions);
+ DO(ip6s_noroute);
+ DO(ip6s_badvers);
+ DO(ip6s_rawout);
+ DO(ip6s_notmember);
+ for (i = 0; i < 256; i++)
+ DO(ip6s_nxthist[i]);
+ DO(ip6s_badscope);
+ DO(ip6s_sources_none);
+#undef DO
+}
+
+void
+showip6(void)
+{
+ struct ip6stat stats;
+ uint64_t totalout;
+
+ domode(&stats);
+ totalout = stats.ip6s_forward + stats.ip6s_localout;
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat)
+
+ DO(ip6s_total, 1, 0);
+ mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout);
+ DO(ip6s_tooshort, 2, 0);
+ DO(ip6s_localout, 2, 35);
+ DO(ip6s_toosmall, 3, 0);
+ DO(ip6s_odropped, 3, 35);
+ DO(ip6s_badvers, 4, 0);
+ DO(ip6s_ofragments, 4, 35);
+ DO(ip6s_fragments, 5, 0);
+ DO(ip6s_cantfrag, 5, 35);
+ DO(ip6s_fragdropped, 6, 0);
+ DO(ip6s_noroute, 6, 35);
+ DO(ip6s_fragtimeout, 7, 0);
+ DO(ip6s_rawout, 7, 35);
+ DO(ip6s_fragoverflow, 8, 0);
+ DO(ip6s_atomicfrags, 9, 0);
+ DO(ip6s_reassembled, 10, 0);
+ DO(ip6s_forward, 11, 0);
+ DO(ip6s_nxthist[IPPROTO_DSTOPTS], 10, 35);
+ DO(ip6s_cantforward, 12, 0);
+ DO(ip6s_nxthist[IPPROTO_HOPOPTS], 11, 35);
+ DO(ip6s_redirectsent, 13, 0);
+ DO(ip6s_nxthist[IPPROTO_IPV4], 12, 35);
+ DO(ip6s_badoptions, 14, 0);
+ DO(ip6s_nxthist[IPPROTO_TCP], 13, 35);
+ DO(ip6s_notmember, 15, 0);
+ DO(ip6s_nxthist[IPPROTO_UDP], 14, 35);
+ DO(ip6s_delivered, 16, 0);
+ DO(ip6s_nxthist[IPPROTO_IPV6], 15, 35);
+ DO(ip6s_badscope, 17, 0);
+ DO(ip6s_nxthist[IPPROTO_ROUTING], 16, 35);
+ DO(ip6s_sources_none, 18, 0);
+ DO(ip6s_nxthist[IPPROTO_FRAGMENT], 17, 35);
+ DO(ip6s_nxthist[IPPROTO_ICMPV6], 18, 35);
+ DO(ip6s_nxthist[IPPROTO_NONE], 19, 35);
+#undef DO
+}
+
+int
+initip6(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_IPV6;
+ name[3] = IPV6CTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting ip6stat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat) {
+ error("ip6stat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting ip6stat failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+resetip6(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_IPV6;
+ name[3] = IPV6CTL_STATS;
+
+ len = sizeof initstat;
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting ipstat failed");
+ }
+
+ oldstat = initstat;
+}
+
+void
+fetchip6(void)
+{
+ int name[4];
+ size_t len;
+
+ oldstat = curstat;
+ name[0] = CTL_NET;
+ name[1] = PF_INET6;
+ name[2] = IPPROTO_IPV6;
+ name[3] = IPV6CTL_STATS;
+ len = sizeof curstat;
+
+ if (sysctl(name, 4, &curstat, &len, 0, 0) < 0)
+ return;
+}
+
+#endif
diff --git a/usr.bin/systat/keyboard.c b/usr.bin/systat/keyboard.c
new file mode 100644
index 000000000000..3d7ee43fd80b
--- /dev/null
+++ b/usr.bin/systat/keyboard.c
@@ -0,0 +1,176 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/select.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "systat.h"
+#include "extern.h"
+
+static char line[80];
+static int keyboard_dispatch(int ch);
+
+int
+keyboard(void)
+{
+ int ch, n;
+ struct timeval last, intvl, now, tm;
+ fd_set rfds;
+
+ /* Set initial timings */
+ gettimeofday(&last, NULL);
+ intvl.tv_sec = delay / 1000000;
+ intvl.tv_usec = delay % 1000000;
+ for (;;) {
+ col = 0;
+ move(CMDLINE, 0);
+ for (;;) {
+ /* Determine interval to sleep */
+ (void)gettimeofday(&now, NULL);
+ tm.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+ tm.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+ while (tm.tv_usec < 0) {
+ tm.tv_usec += 1000000;
+ tm.tv_sec--;
+ }
+ while (tm.tv_usec >= 1000000) {
+ tm.tv_usec -= 1000000;
+ tm.tv_sec++;
+ }
+ if (tm.tv_sec < 0) {
+ /* We have to update screen immediately */
+ display();
+ gettimeofday(&last, NULL);
+ continue;
+ }
+
+ /* Prepare select */
+ FD_ZERO(&rfds);
+ FD_SET(STDIN_FILENO, &rfds);
+ n = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tm);
+
+ if (n > 0) {
+ /* Read event on stdin */
+ ch = getch();
+
+ if (keyboard_dispatch(ch) == 0) {
+ refresh();
+ continue;
+ }
+
+ line[col] = '\0';
+ command(line + 1);
+ /* Refresh delay */
+ intvl.tv_sec = delay / 1000000;
+ intvl.tv_usec = delay % 1000000;
+ refresh();
+ break;
+ }
+
+ if (n < 0 && errno != EINTR)
+ exit(1);
+
+ /* Timeout or signal. Call display another time */
+ display();
+ gettimeofday(&last, NULL);
+ }
+ }
+}
+
+static int
+keyboard_dispatch(int ch)
+{
+
+ if (ch == ERR) {
+ if (errno == EINTR)
+ return 0;
+ exit(1);
+ }
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ if (col == 0) {
+ if (ch == CTRL('l')) {
+ wrefresh(curscr);
+ return 0;
+ }
+ if (ch == CTRL('g')) {
+ status();
+ return 0;
+ }
+ if (ch != ':')
+ return 0;
+ move(CMDLINE, 0);
+ clrtoeol();
+ }
+ if (ch == erasechar() && col > 0) {
+ if (col == 1 && line[0] == ':')
+ return 0;
+ col--;
+ goto doerase;
+ }
+ if (ch == CTRL('w') && col > 0) {
+ while (--col >= 0 && isspace(line[col]))
+ ;
+ col++;
+ while (--col >= 0 && !isspace(line[col]))
+ if (col == 0 && line[0] == ':')
+ return 1;
+ col++;
+ goto doerase;
+ }
+ if (ch == killchar() && col > 0) {
+ col = 0;
+ if (line[0] == ':')
+ col++;
+doerase:
+ move(CMDLINE, col);
+ clrtoeol();
+ return 0;
+ }
+ if (isprint(ch) || ch == ' ') {
+ line[col] = ch;
+ mvaddch(CMDLINE, col, ch);
+ col++;
+ }
+
+ if (col == 0 || (ch != '\r' && ch != '\n'))
+ return 0;
+
+ return 1;
+}
diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c
new file mode 100644
index 000000000000..33fc187e1ab6
--- /dev/null
+++ b/usr.bin/systat/main.c
@@ -0,0 +1,390 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <nlist.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "systat.h"
+#include "extern.h"
+
+static int dellave;
+
+kvm_t *kd;
+double avenrun[3];
+int col;
+unsigned int delay = 5000000; /* in microseconds */
+int verbose = 1; /* to report kvm read errs */
+static struct clockinfo clkinfo;
+double hertz;
+char c;
+char *namp;
+char hostname[MAXHOSTNAMELEN];
+WINDOW *wnd;
+int CMDLINE;
+int use_kvm = 1;
+
+static WINDOW *wload; /* one line window for load average */
+
+struct cmdentry {
+ SLIST_ENTRY(cmdentry) link;
+ char *cmd; /* Command name */
+ char *argv; /* Arguments vector for a command */
+};
+static SLIST_HEAD(, cmdentry) commands;
+
+static void
+parse_cmd_args (int argc, char **argv)
+{
+ int in_command = 0;
+ struct cmdentry *cmd = NULL;
+ double t;
+
+ while (argc) {
+ if (argv[0][0] == '-') {
+ if (in_command)
+ SLIST_INSERT_HEAD(&commands, cmd, link);
+
+ if (memcmp(argv[0], "--", 3) == 0) {
+ in_command = 0; /*-- ends a command explicitly*/
+ argc --, argv ++;
+ continue;
+ }
+ cmd = calloc(1, sizeof(struct cmdentry));
+ if (cmd == NULL)
+ errx(1, "memory allocating failure");
+ cmd->cmd = strdup(&argv[0][1]);
+ if (cmd->cmd == NULL)
+ errx(1, "memory allocating failure");
+ in_command = 1;
+ }
+ else if (!in_command) {
+ t = strtod(argv[0], NULL) * 1000000.0;
+ if (t > 0 && t < (double)UINT_MAX)
+ delay = (unsigned int)t;
+ }
+ else if (cmd != NULL) {
+ cmd->argv = strdup(argv[0]);
+ if (cmd->argv == NULL)
+ errx(1, "memory allocating failure");
+ in_command = 0;
+ SLIST_INSERT_HEAD(&commands, cmd, link);
+ }
+ else
+ errx(1, "invalid arguments list");
+
+ argc--, argv++;
+ }
+ if (in_command && cmd != NULL)
+ SLIST_INSERT_HEAD(&commands, cmd, link);
+
+}
+
+static void
+resize(int signo __unused)
+{
+
+ endwin();
+ refresh();
+ clear();
+
+ CMDLINE = LINES - 1;
+ labels();
+ display();
+ status();
+}
+
+
+int
+main(int argc, char **argv)
+{
+ char errbuf[_POSIX2_LINE_MAX], dummy;
+ size_t size;
+ struct cmdentry *cmd = NULL;
+ short cf, cb;
+
+ (void) setlocale(LC_ALL, "");
+
+ SLIST_INIT(&commands);
+ argc--, argv++;
+ if (argc > 0) {
+ if (argv[0][0] == '-') {
+ struct cmdtab *p;
+
+ p = lookup(&argv[0][1]);
+ if (p == (struct cmdtab *)-1)
+ errx(1, "%s: ambiguous request", &argv[0][1]);
+ if (p == (struct cmdtab *)0)
+ errx(1, "%s: unknown request", &argv[0][1]);
+ curcmd = p;
+ argc--, argv++;
+ }
+ parse_cmd_args (argc, argv);
+
+ }
+ kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+ if (kd != NULL) {
+ /*
+ * Try to actually read something, we may be in a jail, and
+ * have /dev/null opened as /dev/mem.
+ */
+ if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 ||
+ kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) !=
+ sizeof(dummy)) {
+ kvm_close(kd);
+ kd = NULL;
+ }
+ }
+ if (kd == NULL) {
+ /*
+ * Maybe we are lacking permissions? Retry, this time with bogus
+ * devices. We can now use sysctl only.
+ */
+ use_kvm = 0;
+ kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL,
+ O_RDONLY, errbuf);
+ if (kd == NULL) {
+ error("%s", errbuf);
+ exit(1);
+ }
+ }
+ signal(SIGHUP, die);
+ signal(SIGINT, die);
+ signal(SIGQUIT, die);
+ signal(SIGTERM, die);
+ signal(SIGWINCH, resize);
+
+ /*
+ * Initialize display. Load average appears in a one line
+ * window of its own. Current command's display appears in
+ * an overlapping sub-window of stdscr configured by the display
+ * routines to minimize update work by curses.
+ */
+ initscr();
+ start_color();
+ use_default_colors();
+ pair_content(0, &cf, &cb);
+ init_pair(1, COLOR_GREEN, cb);
+ init_pair(2, COLOR_MAGENTA, cb);
+ init_pair(3, COLOR_RED, cb);
+ init_pair(4, COLOR_BLUE, cb);
+ CMDLINE = LINES - 1;
+ wnd = (*curcmd->c_open)();
+ if (wnd == NULL) {
+ warnx("couldn't initialize display");
+ die(0);
+ }
+ wload = newwin(1, 0, 1, 20);
+ if (wload == NULL) {
+ warnx("couldn't set up load average window");
+ die(0);
+ }
+ gethostname(hostname, sizeof (hostname));
+ size = sizeof(clkinfo);
+ if (sysctlbyname("kern.clockrate", &clkinfo, &size, NULL, 0)
+ || size != sizeof(clkinfo)) {
+ error("kern.clockrate");
+ die(0);
+ }
+ hertz = clkinfo.stathz;
+ (*curcmd->c_init)();
+ curcmd->c_flags |= CF_INIT;
+ labels();
+
+ if (curcmd->c_cmd != NULL)
+ SLIST_FOREACH (cmd, &commands, link)
+ if (!curcmd->c_cmd(cmd->cmd, cmd->argv))
+ warnx("command is not understood");
+
+ dellave = 0.0;
+ display();
+ noecho();
+ crmode();
+ keyboard();
+ /*NOTREACHED*/
+
+ return EXIT_SUCCESS;
+}
+
+void
+labels(void)
+{
+ if (curcmd->c_flags & CF_LOADAV) {
+ mvaddstr(0, 20,
+ "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10");
+ mvaddstr(1, 5, "Load Average");
+ }
+ if (curcmd->c_flags & CF_ZFSARC) {
+ mvaddstr(0, 20,
+ " Total MFU MRU Anon Hdr L2Hdr Other");
+ mvaddstr(1, 5, "ZFS ARC ");
+ }
+ (*curcmd->c_label)();
+#ifdef notdef
+ mvprintw(21, 25, "CPU usage on %s", hostname);
+#endif
+ refresh();
+}
+
+void
+display(void)
+{
+ uint64_t arc_stat;
+ unsigned int ui;
+ int i, j;
+
+ /* Get the load average over the last minute. */
+ (void) getloadavg(avenrun, nitems(avenrun));
+ (*curcmd->c_fetch)();
+ if (curcmd->c_flags & CF_LOADAV) {
+ j = 5.0*avenrun[0] + 0.5;
+ dellave -= avenrun[0];
+ if (dellave >= 0.0)
+ c = '<';
+ else {
+ c = '>';
+ dellave = -dellave;
+ }
+ if (dellave < 0.1)
+ c = '|';
+ dellave = avenrun[0];
+ wmove(wload, 0, 0); wclrtoeol(wload);
+ for (i = MIN(j, 50); i > 0; i--)
+ waddch(wload, c);
+ if (j > 50)
+ wprintw(wload, " %4.1f", avenrun[0]);
+ }
+ if (curcmd->c_flags & CF_ZFSARC) {
+ uint64_t arc[7] = {};
+ size_t size = sizeof(arc[0]);
+ if (sysctlbyname("kstat.zfs.misc.arcstats.size",
+ &arc[0], &size, NULL, 0) == 0 ) {
+ GETSYSCTL("vfs.zfs.mfu_size", arc[1]);
+ GETSYSCTL("vfs.zfs.mru_size", arc[2]);
+ GETSYSCTL("vfs.zfs.anon_size", arc[3]);
+ GETSYSCTL("kstat.zfs.misc.arcstats.hdr_size", arc[4]);
+ GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc[5]);
+ GETSYSCTL("kstat.zfs.misc.arcstats.bonus_size", arc[6]);
+ GETSYSCTL("kstat.zfs.misc.arcstats.dnode_size", arc_stat);
+ arc[6] += arc_stat;
+ GETSYSCTL("kstat.zfs.misc.arcstats.dbuf_size", arc_stat);
+ arc[6] += arc_stat;
+ wmove(wload, 0, 0); wclrtoeol(wload);
+ for (ui = 0 ; ui < nitems(arc); ui++)
+ sysputuint64(wload, 0, ui*8+2, 6, arc[ui], 0);
+ }
+ }
+ (*curcmd->c_refresh)();
+ if (curcmd->c_flags & (CF_LOADAV |CF_ZFSARC))
+ wrefresh(wload);
+ wrefresh(wnd);
+ move(CMDLINE, col);
+ refresh();
+}
+
+void
+load(void)
+{
+
+ (void) getloadavg(avenrun, nitems(avenrun));
+ mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f",
+ avenrun[0], avenrun[1], avenrun[2]);
+ clrtoeol();
+}
+
+void
+die(int signo __unused)
+{
+ move(CMDLINE, 0);
+ clrtoeol();
+ refresh();
+ endwin();
+ exit(0);
+}
+
+#include <stdarg.h>
+
+void
+error(const char *fmt, ...)
+{
+ va_list ap;
+ char buf[255];
+ int oy, ox;
+
+ va_start(ap, fmt);
+ if (wnd) {
+ getyx(stdscr, oy, ox);
+ (void) vsnprintf(buf, sizeof(buf), fmt, ap);
+ clrtoeol();
+ standout();
+ mvaddstr(CMDLINE, 0, buf);
+ standend();
+ move(oy, ox);
+ refresh();
+ } else {
+ (void) vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ }
+ va_end(ap);
+}
+
+void
+nlisterr(struct nlist n_list[])
+{
+ int i, n;
+
+ n = 0;
+ clear();
+ mvprintw(2, 10, "systat: nlist: can't find following symbols:");
+ for (i = 0;
+ n_list[i].n_name != NULL && *n_list[i].n_name != '\0'; i++)
+ if (n_list[i].n_value == 0)
+ mvprintw(2 + ++n, 10, "%s", n_list[i].n_name);
+ move(CMDLINE, 0);
+ clrtoeol();
+ refresh();
+ endwin();
+ exit(1);
+}
diff --git a/usr.bin/systat/mode.c b/usr.bin/systat/mode.c
new file mode 100644
index 000000000000..28bc47a92351
--- /dev/null
+++ b/usr.bin/systat/mode.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 1997 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ */
+
+/*
+ * mode.c - mechanisms for dealing with SGI-style modal displays.
+ *
+ * There are four generally-understood useful modes for status displays
+ * of the sort exemplified by the IRIX ``netstat -C'' and ``osview''
+ * programs. We try to follow their example, although the user interface
+ * and terminology slightly differ.
+ *
+ * RATE - the default mode - displays the precise rate of change in
+ * each statistic in units per second, regardless of the actual display
+ * update interval.
+ *
+ * DELTA - displays the change in each statistic over the entire
+ * display update interval (i.e., RATE * interval).
+ *
+ * SINCE - displays the total change in each statistic since the module
+ * was last initialized or reset.
+ *
+ * ABSOLUTE - displays the current value of each statistic.
+ *
+ * In the SGI programs, these modes are selected by the single-character
+ * commands D, W, N, and A. In systat, they are the slightly-harder-to-type
+ * ``mode delta'', etc. The initial value for SINCE mode is initialized
+ * when the module is first started and can be reset using the ``reset''
+ * command (as opposed to the SGI way where changing modes implicitly
+ * resets). A ``mode'' command with no arguments displays the current
+ * mode in the command line.
+ */
+
+
+#include <sys/types.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+enum mode currentmode = display_RATE;
+
+static const char *const modes[] = { "rate", "delta", "since", "absolute" };
+
+int
+cmdmode(const char *cmd, const char *args)
+{
+ if (prefix(cmd, "mode")) {
+ if (args[0] == '\0') {
+ move(CMDLINE, 0);
+ clrtoeol();
+ printw("%s", modes[currentmode]);
+ } else if (prefix(args, "rate")) {
+ currentmode = display_RATE;
+ } else if (prefix(args, "delta")) {
+ currentmode = display_DELTA;
+ } else if (prefix(args, "since")) {
+ currentmode = display_SINCE;
+ } else if (prefix(args, "absolute")) {
+ currentmode = display_ABS;
+ } else {
+ printw("unknown mode `%s'", args);
+ }
+ return 1;
+ }
+ if(prefix(cmd, "reset")) {
+ curcmd->c_reset();
+ return 1;
+ }
+ return 0;
+}
diff --git a/usr.bin/systat/mode.h b/usr.bin/systat/mode.h
new file mode 100644
index 000000000000..046b4d072a59
--- /dev/null
+++ b/usr.bin/systat/mode.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1997 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ */
+
+/*
+ * mode.h - mechanisms for dealing with SGI-style modal displays.
+ */
+
+#ifndef MODE_H
+#define MODE_H 1
+
+enum mode { display_RATE, display_DELTA, display_SINCE, display_ABS };
+
+extern int cmdmode(const char *cmd, const char *args);
+extern enum mode currentmode;
+
+#endif /* MODE_H */
diff --git a/usr.bin/systat/netcmds.c b/usr.bin/systat/netcmds.c
new file mode 100644
index 000000000000..c0bbda7dee8a
--- /dev/null
+++ b/usr.bin/systat/netcmds.c
@@ -0,0 +1,304 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/*
+ * Common network command support routines.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+
+#define streq(a,b) (strcmp(a,b)==0)
+
+static struct hitem {
+ struct in_addr addr;
+ int onoff;
+} *hosts;
+
+int nports, nhosts, protos;
+
+static void changeitems(const char *, int);
+static int selectproto(const char *);
+static void showprotos(void);
+static int selectport(long, int);
+static void showports(void);
+static int selecthost(struct in_addr *, int);
+static void showhosts(void);
+
+int
+netcmd(const char *cmd, const char *args)
+{
+
+ if (prefix(cmd, "proto")) {
+ if (*args == '\0') {
+ move(CMDLINE, 0);
+ clrtoeol();
+ addstr("which proto?");
+ } else if (!selectproto(args)) {
+ error("%s: Unknown protocol.", args);
+ }
+ return (1);
+ }
+ if (prefix(cmd, "ignore") || prefix(cmd, "display")) {
+ changeitems(args, prefix(cmd, "display"));
+ return (1);
+ }
+ if (prefix(cmd, "reset")) {
+ selectproto(0);
+ selecthost(0, 0);
+ selectport(-1, 0);
+ return (1);
+ }
+ if (prefix(cmd, "show")) {
+ move(CMDLINE, 0); clrtoeol();
+ if (*args == '\0') {
+ showprotos();
+ showhosts();
+ showports();
+ return (1);
+ }
+ if (prefix(args, "protos"))
+ showprotos();
+ else if (prefix(args, "hosts"))
+ showhosts();
+ else if (prefix(args, "ports"))
+ showports();
+ else
+ addstr("show what?");
+ return (1);
+ }
+ return (0);
+}
+
+static void
+changeitems(const char *args, int onoff)
+{
+ char *cp, *tmpstr, *tmpstr1;
+ struct servent *sp;
+ struct hostent *hp;
+ struct in_addr in;
+
+ tmpstr = tmpstr1 = strdup(args);
+ cp = strchr(tmpstr1, '\n');
+ if (cp)
+ *cp = '\0';
+ for (;;tmpstr1 = cp) {
+ for (cp = tmpstr1; *cp && isspace(*cp); cp++)
+ ;
+ tmpstr1 = cp;
+ for (; *cp && !isspace(*cp); cp++)
+ ;
+ if (*cp)
+ *cp++ = '\0';
+ if (cp - tmpstr1 == 0)
+ break;
+ sp = getservbyname(tmpstr1,
+ protos == TCP ? "tcp" : protos == UDP ? "udp" : 0);
+ if (sp) {
+ selectport(sp->s_port, onoff);
+ continue;
+ }
+ hp = gethostbyname(tmpstr1);
+ if (hp == NULL) {
+ in.s_addr = inet_addr(tmpstr1);
+ if (in.s_addr == INADDR_NONE) {
+ error("%s: unknown host or port", tmpstr1);
+ continue;
+ }
+ } else
+ in = *(struct in_addr *)hp->h_addr;
+ selecthost(&in, onoff);
+ }
+ free(tmpstr);
+}
+
+static int
+selectproto(const char *proto)
+{
+
+ if (proto == NULL || streq(proto, "all"))
+ protos = TCP | UDP;
+ else if (streq(proto, "tcp"))
+ protos = TCP;
+ else if (streq(proto, "udp"))
+ protos = UDP;
+ else
+ return (0);
+
+ return (protos);
+}
+
+static void
+showprotos(void)
+{
+
+ if ((protos&TCP) == 0)
+ addch('!');
+ addstr("tcp ");
+ if ((protos&UDP) == 0)
+ addch('!');
+ addstr("udp ");
+}
+
+static struct pitem {
+ long port;
+ int onoff;
+} *ports;
+
+static int
+selectport(long port, int onoff)
+{
+ struct pitem *p;
+
+ if (port == -1) {
+ if (ports == NULL)
+ return (0);
+ free((char *)ports), ports = 0;
+ nports = 0;
+ return (1);
+ }
+ for (p = ports; p < ports + nports; p++)
+ if (p->port == port) {
+ p->onoff = onoff;
+ return (0);
+ }
+ if (nports == 0)
+ ports = (struct pitem *)malloc(sizeof (*p));
+ else
+ ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p));
+ p = &ports[nports++];
+ p->port = port;
+ p->onoff = onoff;
+ return (1);
+}
+
+int
+checkport(struct in_conninfo *inc)
+{
+ struct pitem *p;
+
+ if (ports)
+ for (p = ports; p < ports+nports; p++)
+ if (p->port == inc->inc_lport || p->port == inc->inc_fport)
+ return (p->onoff);
+ return (1);
+}
+
+static void
+showports(void)
+{
+ struct pitem *p;
+ struct servent *sp;
+
+ for (p = ports; p < ports+nports; p++) {
+ sp = getservbyport(p->port,
+ protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp");
+ if (!p->onoff)
+ addch('!');
+ if (sp)
+ printw("%s ", sp->s_name);
+ else
+ printw("%ld ", p->port);
+ }
+}
+
+static int
+selecthost(struct in_addr *in, int onoff)
+{
+ struct hitem *p;
+
+ if (in == NULL) {
+ if (hosts == NULL)
+ return (0);
+ free((char *)hosts), hosts = 0;
+ nhosts = 0;
+ return (1);
+ }
+ for (p = hosts; p < hosts+nhosts; p++)
+ if (p->addr.s_addr == in->s_addr) {
+ p->onoff = onoff;
+ return (0);
+ }
+ if (nhosts == 0)
+ hosts = (struct hitem *)malloc(sizeof (*p));
+ else
+ hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p));
+ p = &hosts[nhosts++];
+ p->addr = *in;
+ p->onoff = onoff;
+ return (1);
+}
+
+int
+checkhost(struct in_conninfo *inc)
+{
+ struct hitem *p;
+
+ if (hosts)
+ for (p = hosts; p < hosts+nhosts; p++)
+ if (p->addr.s_addr == inc->inc_laddr.s_addr ||
+ p->addr.s_addr == inc->inc_faddr.s_addr)
+ return (p->onoff);
+ return (1);
+}
+
+static void
+showhosts(void)
+{
+ struct hitem *p;
+ struct hostent *hp;
+
+ for (p = hosts; p < hosts+nhosts; p++) {
+ hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET);
+ if (!p->onoff)
+ addch('!');
+ printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr));
+ }
+}
diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c
new file mode 100644
index 000000000000..6d188bf1dd0d
--- /dev/null
+++ b/usr.bin/systat/netstat.c
@@ -0,0 +1,633 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+
+/*
+ * netstat
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/callout.h>
+#define _WANT_SOCKET
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/route.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+#define _WANT_INPCB
+#include <netinet/in_pcb.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#define _WANT_TCPCB
+#include <netinet/tcp_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+
+static struct netinfo *enter(struct in_conninfo *, uint8_t, int, const char *);
+static void enter_kvm(struct inpcb *, struct socket *, int, const char *);
+static void enter_sysctl(struct xinpcb *, struct xsocket *, int, const char *);
+static void fetchnetstat_kvm(void);
+static void fetchnetstat_sysctl(void);
+static char *inetname(struct sockaddr *);
+static void inetprint(struct sockaddr *, const char *);
+
+#define streq(a,b) (strcmp(a,b)==0)
+#define YMAX(w) (getmaxy(w)-2)
+
+WINDOW *
+opennetstat(void)
+{
+ sethostent(1);
+ setnetent(1);
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+struct netinfo {
+ TAILQ_ENTRY(netinfo) chain;
+ short ni_line; /* line on screen */
+ short ni_seen; /* 0 when not present in list */
+ short ni_flags;
+#define NIF_LACHG 0x1 /* local address changed */
+#define NIF_FACHG 0x2 /* foreign address changed */
+ short ni_state; /* tcp state */
+ const char *ni_proto; /* protocol */
+ struct sockaddr_storage ni_lsa; /* local address */
+ struct sockaddr_storage ni_fsa; /* foreign address */
+ u_int ni_rcvcc; /* rcv buffer character count */
+ u_int ni_sndcc; /* snd buffer character count */
+};
+
+static TAILQ_HEAD(netinfohead, netinfo) netcb = TAILQ_HEAD_INITIALIZER(netcb);
+
+static int aflag = 0;
+static int nflag = 0;
+static int lastrow = 1;
+
+void
+closenetstat(WINDOW *w)
+{
+ struct netinfo *p;
+
+ endhostent();
+ endnetent();
+ TAILQ_FOREACH(p, &netcb, chain) {
+ if (p->ni_line != -1)
+ lastrow--;
+ p->ni_line = -1;
+ }
+ if (w != NULL) {
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+ }
+}
+
+static const char *miblist[] = {
+ "net.inet.tcp.pcblist",
+ "net.inet.udp.pcblist"
+};
+
+static char tcb[] = "tcb", udb[] = "udb";
+
+struct nlist namelist[] = {
+#define X_TCB 0
+ { .n_name = tcb },
+#define X_UDB 1
+ { .n_name = udb },
+ { .n_name = NULL },
+};
+
+int
+initnetstat(void)
+{
+ protos = TCP|UDP;
+ return(1);
+}
+
+void
+fetchnetstat(void)
+{
+ if (use_kvm)
+ fetchnetstat_kvm();
+ else
+ fetchnetstat_sysctl();
+}
+
+static void
+fetchnetstat_kvm(void)
+{
+ struct netinfo *p;
+ struct inpcbhead head;
+ struct socket sockb;
+ struct tcpcb tcpcb;
+ struct inpcb *inpcb;
+ void *off;
+ int istcp;
+
+ if (namelist[X_TCB].n_value == 0)
+ return;
+ TAILQ_FOREACH(p, &netcb, chain)
+ p->ni_seen = 0;
+ if (protos&TCP) {
+ off = NPTR(X_TCB);
+ istcp = 1;
+ }
+ else if (protos&UDP) {
+ off = NPTR(X_UDB);
+ istcp = 0;
+ }
+ else {
+ error("No protocols to display");
+ return;
+ }
+again:
+ KREAD(off, &head, sizeof (struct inpcbhead));
+ LIST_FOREACH(inpcb, &head, inp_list) {
+ KREAD(inpcb, &tcpcb, istcp ? sizeof(tcpcb) : sizeof(inpcb));
+ inpcb = (struct inpcb *)&tcpcb;
+ if (!aflag) {
+ if (inpcb->inp_vflag & INP_IPV4) {
+ if (inpcb->inp_laddr.s_addr == INADDR_ANY)
+ continue;
+ }
+#ifdef INET6
+ else if (inpcb->inp_vflag & INP_IPV6) {
+ if (memcmp(&inpcb->in6p_laddr,
+ &in6addr_any, sizeof(in6addr_any)) == 0)
+ continue;
+ }
+#endif
+ }
+ if (nhosts && !checkhost(&inpcb->inp_inc))
+ continue;
+ if (nports && !checkport(&inpcb->inp_inc))
+ continue;
+ if (istcp) {
+ KREAD(inpcb->inp_socket, &sockb, sizeof (sockb));
+ enter_kvm(inpcb, &sockb, tcpcb.t_state, "tcp");
+ } else
+ enter_kvm(inpcb, &sockb, 0, "udp");
+ }
+ if (istcp && (protos&UDP)) {
+ istcp = 0;
+ off = NPTR(X_UDB);
+ goto again;
+ }
+}
+
+static void
+fetchnetstat_sysctl(void)
+{
+ struct netinfo *p;
+ int idx;
+ struct xinpgen *inpg;
+ char *cur, *end;
+ struct xinpcb *xip = NULL;
+ struct xtcpcb *xtp = NULL;
+ int plen;
+ size_t lsz;
+
+ TAILQ_FOREACH(p, &netcb, chain)
+ p->ni_seen = 0;
+ if (protos&TCP) {
+ idx = 0;
+ } else if (protos&UDP) {
+ idx = 1;
+ } else {
+ error("No protocols to display");
+ return;
+ }
+
+ for (;idx < 2; idx++) {
+ if (idx == 1 && !(protos&UDP))
+ break;
+ inpg = (struct xinpgen *)sysctl_dynread(miblist[idx], &lsz);
+ if (inpg == NULL) {
+ error("sysctl(%s...) failed", miblist[idx]);
+ continue;
+ }
+ /*
+ * We currently do no require a consistent pcb list.
+ * Try to be robust in case of struct size changes
+ */
+ cur = ((char *)inpg) + inpg->xig_len;
+ /* There is also a trailing struct xinpgen */
+ end = ((char *)inpg) + lsz - inpg->xig_len;
+ if (end <= cur) {
+ free(inpg);
+ continue;
+ }
+ if (idx == 0) { /* TCP */
+ xtp = (struct xtcpcb *)cur;
+ plen = xtp->xt_len;
+ } else {
+ xip = (struct xinpcb *)cur;
+ plen = xip->xi_len;
+ }
+ while (cur + plen <= end) {
+ if (idx == 0) { /* TCP */
+ xtp = (struct xtcpcb *)cur;
+ xip = &xtp->xt_inp;
+ } else {
+ xip = (struct xinpcb *)cur;
+ }
+ cur += plen;
+
+ if (!aflag) {
+ if (xip->inp_vflag & INP_IPV4) {
+ if (xip->inp_laddr.s_addr == INADDR_ANY)
+ continue;
+ }
+#ifdef INET6
+ else if (xip->inp_vflag & INP_IPV6) {
+ if (memcmp(&xip->in6p_laddr,
+ &in6addr_any, sizeof(in6addr_any))
+ == 0)
+ continue;
+ }
+#endif
+ }
+ if (nhosts && !checkhost(&xip->inp_inc))
+ continue;
+ if (nports && !checkport(&xip->inp_inc))
+ continue;
+ if (idx == 0)
+ enter_sysctl(xip, &xip->xi_socket,
+ xtp->t_state, "tcp");
+ else
+ enter_sysctl(xip, &xip->xi_socket, 0, "udp");
+ }
+ free(inpg);
+ }
+}
+
+static void
+enter_kvm(struct inpcb *inp, struct socket *so, int state, const char *proto)
+{
+ struct netinfo *p;
+
+ if ((p = enter(&inp->inp_inc, inp->inp_vflag, state, proto)) != NULL) {
+ p->ni_rcvcc = so->so_rcv.sb_ccc;
+ p->ni_sndcc = so->so_snd.sb_ccc;
+ }
+}
+
+static void
+enter_sysctl(struct xinpcb *xip, struct xsocket *so, int state,
+ const char *proto)
+{
+ struct netinfo *p;
+
+ if ((p = enter(&xip->inp_inc, xip->inp_vflag, state, proto)) != NULL) {
+ p->ni_rcvcc = so->so_rcv.sb_cc;
+ p->ni_sndcc = so->so_snd.sb_cc;
+ }
+}
+
+static struct netinfo *
+enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto)
+{
+ struct netinfo *p;
+ struct sockaddr_storage lsa, fsa;
+ struct sockaddr_in *sa4;
+#ifdef INET6
+ struct sockaddr_in6 *sa6;
+#endif
+
+ memset(&lsa, 0, sizeof(lsa));
+ memset(&fsa, 0, sizeof(fsa));
+ if (vflag & INP_IPV4) {
+ sa4 = (struct sockaddr_in *)&lsa;
+ sa4->sin_addr = inc->inc_laddr;
+ sa4->sin_port = inc->inc_lport;
+ sa4->sin_family = AF_INET;
+ sa4->sin_len = sizeof(struct sockaddr_in);
+
+ sa4 = (struct sockaddr_in *)&fsa;
+ sa4->sin_addr = inc->inc_faddr;
+ sa4->sin_port = inc->inc_fport;
+ sa4->sin_family = AF_INET;
+ sa4->sin_len = sizeof(struct sockaddr_in);
+ }
+#ifdef INET6
+ else if (vflag & INP_IPV6) {
+ sa6 = (struct sockaddr_in6 *)&lsa;
+ memcpy(&sa6->sin6_addr, &inc->inc6_laddr,
+ sizeof(struct in6_addr));
+ sa6->sin6_port = inc->inc_lport;
+ sa6->sin6_family = AF_INET6;
+ sa6->sin6_len = sizeof(struct sockaddr_in6);
+
+ sa6 = (struct sockaddr_in6 *)&fsa;
+ memcpy(&sa6->sin6_addr, &inc->inc6_faddr,
+ sizeof(struct in6_addr));
+ sa6->sin6_port = inc->inc_fport;
+ sa6->sin6_family = AF_INET6;
+ sa6->sin6_len = sizeof(struct sockaddr_in6);
+ }
+#endif
+ else
+ return NULL;
+
+ /*
+ * Only take exact matches, any sockets with
+ * previously unbound addresses will be deleted
+ * below in the display routine because they
+ * will appear as ``not seen'' in the kernel
+ * data structures.
+ */
+ TAILQ_FOREACH(p, &netcb, chain) {
+ if (!streq(proto, p->ni_proto))
+ continue;
+ if (p->ni_lsa.ss_family != lsa.ss_family ||
+ memcmp(&p->ni_lsa, &lsa, lsa.ss_len) != 0)
+ continue;
+ if (p->ni_fsa.ss_family == fsa.ss_family &&
+ memcmp(&p->ni_fsa, &fsa, fsa.ss_len) == 0)
+ break;
+ }
+ if (p == NULL) {
+ if ((p = malloc(sizeof(*p))) == NULL) {
+ error("Out of memory");
+ return NULL;
+ }
+ TAILQ_INSERT_HEAD(&netcb, p, chain);
+ p->ni_line = -1;
+ memcpy(&p->ni_lsa, &lsa, lsa.ss_len);
+ memcpy(&p->ni_fsa, &fsa, fsa.ss_len);
+ p->ni_proto = strdup(proto);
+ p->ni_flags = NIF_LACHG|NIF_FACHG;
+ }
+ p->ni_state = state;
+ p->ni_seen = 1;
+ return p;
+}
+
+/* column locations */
+#define LADDR 0
+#define FADDR LADDR+23
+#define PROTO FADDR+23
+#define RCVCC PROTO+6
+#define SNDCC RCVCC+7
+#define STATE SNDCC+7
+
+void
+labelnetstat(void)
+{
+ if (use_kvm && namelist[X_TCB].n_type == 0)
+ return;
+ wmove(wnd, 0, 0); wclrtobot(wnd);
+ mvwaddstr(wnd, 0, LADDR, "Local Address");
+ mvwaddstr(wnd, 0, FADDR, "Foreign Address");
+ mvwaddstr(wnd, 0, PROTO, "Proto");
+ mvwaddstr(wnd, 0, RCVCC, "Recv-Q");
+ mvwaddstr(wnd, 0, SNDCC, "Send-Q");
+ mvwaddstr(wnd, 0, STATE, "(state)");
+}
+
+void
+shownetstat(void)
+{
+ struct netinfo *p, *q;
+ char proto[6];
+ const char *family = "";
+
+ /*
+ * First, delete any connections that have gone
+ * away and adjust the position of connections
+ * below to reflect the deleted line.
+ */
+ p = TAILQ_FIRST(&netcb);
+ while (p != NULL) {
+ if (p->ni_line == -1 || p->ni_seen) {
+ p = TAILQ_NEXT(p, chain);
+ continue;
+ }
+ wmove(wnd, p->ni_line, 0); wdeleteln(wnd);
+ TAILQ_FOREACH(q, &netcb, chain)
+ if (q != p && q->ni_line > p->ni_line) {
+ q->ni_line--;
+ /* this shouldn't be necessary */
+ q->ni_flags |= NIF_LACHG|NIF_FACHG;
+ }
+ lastrow--;
+ q = TAILQ_NEXT(p, chain);
+ TAILQ_REMOVE(&netcb, p, chain);
+ free(p);
+ p = q;
+ }
+ /*
+ * Update existing connections and add new ones.
+ */
+ TAILQ_FOREACH(p, &netcb, chain) {
+ if (p->ni_line == -1) {
+ /*
+ * Add a new entry if possible.
+ */
+ if (lastrow > YMAX(wnd))
+ continue;
+ p->ni_line = lastrow++;
+ p->ni_flags |= NIF_LACHG|NIF_FACHG;
+ }
+ if (p->ni_flags & NIF_LACHG) {
+ wmove(wnd, p->ni_line, LADDR);
+ inetprint((struct sockaddr *)&p->ni_lsa, p->ni_proto);
+ p->ni_flags &= ~NIF_LACHG;
+ }
+ if (p->ni_flags & NIF_FACHG) {
+ wmove(wnd, p->ni_line, FADDR);
+ inetprint((struct sockaddr *)&p->ni_fsa, p->ni_proto);
+ p->ni_flags &= ~NIF_FACHG;
+ }
+#ifdef INET6
+ family = (p->ni_lsa.ss_family == AF_INET) ? "4" : "6";
+#endif
+ snprintf(proto, sizeof(proto), "%s%s", p->ni_proto, family);
+ mvwaddstr(wnd, p->ni_line, PROTO, proto);
+ mvwprintw(wnd, p->ni_line, RCVCC, "%6u", p->ni_rcvcc);
+ mvwprintw(wnd, p->ni_line, SNDCC, "%6u", p->ni_sndcc);
+ if (streq(p->ni_proto, "tcp")) {
+ if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES)
+ mvwprintw(wnd, p->ni_line, STATE, "%d",
+ p->ni_state);
+ else
+ mvwaddstr(wnd, p->ni_line, STATE,
+ tcpstates[p->ni_state]);
+ }
+ wclrtoeol(wnd);
+ }
+ if (lastrow < YMAX(wnd)) {
+ wmove(wnd, lastrow, 0); wclrtobot(wnd);
+ wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd); /* XXX */
+ }
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * If the nflag was specified, use numbers instead of names.
+ */
+static void
+inetprint(struct sockaddr *sa, const char *proto)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int port;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ port = ((struct sockaddr_in *)sa)->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ port = ((struct sockaddr_in6 *)sa)->sin6_port;
+ break;
+#endif
+ default:
+ port = 0;
+ break;
+ }
+ snprintf(line, sizeof(line), "%.*s.", 16, inetname(sa));
+ cp = strchr(line, '\0');
+ if (!nflag && port)
+ sp = getservbyport(port, proto);
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - (cp - line), "%.8s",
+ sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - (cp - line), "%d",
+ ntohs((u_short)port));
+ /* pad to full column to clear any garbage */
+ cp = strchr(line, '\0');
+ while (cp - line < 22)
+ *cp++ = ' ';
+ line[22] = '\0';
+ waddstr(wnd, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+static char *
+inetname(struct sockaddr *sa)
+{
+ char *cp = 0;
+ static char line[NI_MAXHOST];
+ struct hostent *hp;
+ struct in_addr in;
+
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
+ &in6addr_any, sizeof(in6addr_any)) == 0)
+ strcpy(line, "*");
+ else
+ getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
+ nflag ? NI_NUMERICHOST : 0);
+ return (line);
+ }
+#endif
+
+ in = ((struct sockaddr_in *)sa)->sin_addr;
+ if (!nflag && in.s_addr != INADDR_ANY) {
+ hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
+ if (hp)
+ cp = hp->h_name;
+ }
+ if (in.s_addr == INADDR_ANY)
+ strcpy(line, "*");
+ else if (cp)
+ snprintf(line, sizeof(line), "%s", cp);
+ else {
+ in.s_addr = ntohl(in.s_addr);
+#define C(x) ((x) & 0xff)
+ snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24),
+ C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
+ }
+ return (line);
+}
+
+int
+cmdnetstat(const char *cmd, const char *args)
+{
+ if (prefix(cmd, "all")) {
+ aflag = !aflag;
+ goto fixup;
+ }
+ if (prefix(cmd, "numbers") || prefix(cmd, "names")) {
+ struct netinfo *p;
+ int new;
+
+ new = prefix(cmd, "numbers");
+ if (new == nflag)
+ return (1);
+ TAILQ_FOREACH(p, &netcb, chain) {
+ if (p->ni_line == -1)
+ continue;
+ p->ni_flags |= NIF_LACHG|NIF_FACHG;
+ }
+ nflag = new;
+ goto redisplay;
+ }
+ if (!netcmd(cmd, args))
+ return (0);
+fixup:
+ fetchnetstat();
+redisplay:
+ shownetstat();
+ refresh();
+ return (1);
+}
diff --git a/usr.bin/systat/pigs.c b/usr.bin/systat/pigs.c
new file mode 100644
index 000000000000..8a61505858cf
--- /dev/null
+++ b/usr.bin/systat/pigs.c
@@ -0,0 +1,184 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/cdefs.h>
+/*
+ * Pigs display from Bill Reeves at Lucasfilm
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/user.h>
+
+#include <curses.h>
+#include <math.h>
+#include <pwd.h>
+#include <stdlib.h>
+
+#include "systat.h"
+#include "extern.h"
+
+int compar(const void *, const void *);
+
+static int nproc;
+static struct p_times {
+ float pt_pctcpu;
+ struct kinfo_proc *pt_kp;
+} *pt = NULL;
+
+static int fscale;
+static double lccpu;
+
+WINDOW *
+openpigs(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closepigs(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+showpigs(void)
+{
+ int i, j, y, k;
+ const char *uname, *pname;
+ char pidname[30];
+
+ if (nproc == 0)
+ return;
+
+ qsort(pt, nproc, sizeof (struct p_times), compar);
+ y = 1;
+ i = nproc;
+ if (i > getmaxy(wnd)-2)
+ i = getmaxy(wnd)-2;
+ for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
+ uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
+ pname = pt[k].pt_kp->ki_comm;
+ wmove(wnd, y, 0);
+ wclrtoeol(wnd);
+ mvwaddstr(wnd, y, 0, uname);
+ snprintf(pidname, sizeof(pidname), "%10.10s", pname);
+ mvwaddstr(wnd, y, 9, pidname);
+ wmove(wnd, y, 20);
+ for (j = pt[k].pt_pctcpu * 50 + 0.5; j > 0; j--)
+ waddch(wnd, 'X');
+ }
+ wmove(wnd, y, 0); wclrtobot(wnd);
+}
+
+int
+initpigs(void)
+{
+ fixpt_t ccpu;
+ size_t len;
+ int err;
+
+ len = sizeof(ccpu);
+ err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
+ if (err || len != sizeof(ccpu)) {
+ perror("kern.ccpu");
+ return (0);
+ }
+
+ len = sizeof(fscale);
+ err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
+ if (err || len != sizeof(fscale)) {
+ perror("kern.fscale");
+ return (0);
+ }
+
+ lccpu = log((double) ccpu / fscale);
+
+ return(1);
+}
+
+void
+fetchpigs(void)
+{
+ int i;
+ float ftime;
+ float *pctp;
+ struct kinfo_proc *kpp;
+ static int maxnproc = 0;
+
+ if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
+ error("%s", kvm_geterr(kd));
+ nproc = 0;
+ return;
+ }
+ if (nproc > maxnproc) {
+ if ((pt = realloc(pt, nproc * sizeof(*pt))) == NULL) {
+ error("Out of memory");
+ die(0);
+ }
+ maxnproc = nproc;
+ }
+ /*
+ * calculate %cpu for each proc
+ */
+ for (i = 0; i < nproc; i++) {
+ pt[i].pt_kp = &kpp[i];
+ pctp = &pt[i].pt_pctcpu;
+ ftime = kpp[i].ki_swtime;
+ if (ftime == 0 || (kpp[i].ki_flag & P_INMEM) == 0)
+ *pctp = 0;
+ else
+ *pctp = ((double) kpp[i].ki_pctcpu /
+ fscale) / (1.0 - exp(ftime * lccpu));
+ }
+}
+
+void
+labelpigs(void)
+{
+ wmove(wnd, 0, 0);
+ wclrtoeol(wnd);
+ mvwaddstr(wnd, 0, 20,
+ "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
+}
+
+int
+compar(const void *a, const void *b)
+{
+ return (((const struct p_times *) a)->pt_pctcpu >
+ ((const struct p_times *) b)->pt_pctcpu)? -1: 1;
+}
diff --git a/usr.bin/systat/proc.c b/usr.bin/systat/proc.c
new file mode 100644
index 000000000000..25ee286be780
--- /dev/null
+++ b/usr.bin/systat/proc.c
@@ -0,0 +1,296 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Yoshihiro Ota <ota@j.email.ne.jp>
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <curses.h>
+#include <libprocstat.h>
+#include <libutil.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+
+/*
+ * vm objects of swappable types
+ */
+static struct swapvm {
+ uint64_t kvo_me;
+ uint32_t swapped; /* in pages */
+ uint64_t next;
+ pid_t pid; /* to avoid double counting */
+} *swobj = NULL;
+static int nswobj = 0;
+
+static struct procstat *prstat = NULL;
+/*
+ *procstat_getvmmap() is an expensive call and the number of processes running
+ * may also be high. So, maintain an array of pointers for ease of expanding
+ * an array and also swapping pointers are faster than struct.
+ */
+static struct proc_usage {
+ pid_t pid;
+ uid_t uid;
+ char command[COMMLEN + 1];
+ uint64_t total;
+ uint32_t pages;
+} **pu = NULL;
+static int nproc;
+static int proc_compar(const void *, const void *);
+
+static void
+display_proc_line(int idx, int y, uint64_t totalswappages)
+{
+ int offset = 0, rate;
+ const char *uname;
+ char buf[30];
+ uint64_t swapbytes;
+
+ wmove(wnd, y, 0);
+ wclrtoeol(wnd);
+ if (idx >= nproc)
+ return;
+
+ uname = user_from_uid(pu[idx]->uid, 0);
+ swapbytes = ptoa(pu[idx]->pages);
+
+ snprintf(buf, sizeof(buf), "%6d %-10s %-10.10s", pu[idx]->pid, uname,
+ pu[idx]->command);
+ offset = 6 + 1 + 10 + 1 + 10 + 1;
+ mvwaddstr(wnd, y, 0, buf);
+ sysputuint64(wnd, y, offset, 4, swapbytes, 0);
+ offset += 4;
+ mvwaddstr(wnd, y, offset, " / ");
+ offset += 3;
+ sysputuint64(wnd, y, offset, 4, pu[idx]->total, 0);
+ offset += 4;
+
+ rate = pu[idx]->total > 1 ? 100 * swapbytes / pu[idx]->total : 0;
+ snprintf(buf, sizeof(buf), "%3d%%", rate);
+ mvwaddstr(wnd, y, offset, buf);
+ if (rate > 100) /* avoid running over the screen */
+ rate = 100;
+ sysputXs(wnd, y, offset + 5, rate / 10);
+
+ rate = 100 * pu[idx]->pages / totalswappages;
+ snprintf(buf, sizeof(buf), "%3d%%", rate);
+ mvwaddstr(wnd, y, offset + 16, buf);
+ if (rate > 100) /* avoid running over the screen */
+ rate = 100;
+ sysputXs(wnd, y, offset + 21, rate / 10);
+}
+
+static int
+swobj_search(const void *a, const void *b)
+{
+ const uint64_t *aa = a;
+ const struct swapvm *bb = b;
+
+ if (*aa == bb->kvo_me)
+ return (0);
+ return (*aa > bb->kvo_me ? -1 : 1);
+}
+
+static int
+swobj_sort(const void *a, const void *b)
+{
+
+ return ((((const struct swapvm *) a)->kvo_me >
+ ((const struct swapvm *) b)->kvo_me) ? -1 : 1);
+}
+
+static bool
+get_swap_vmobjects(void)
+{
+ static int maxnobj;
+ int cnt, i, next_i, last_nswobj;
+ struct kinfo_vmobject *kvo;
+
+ next_i = nswobj = 0;
+ kvo = kinfo_getswapvmobject(&cnt);
+ if (kvo == NULL) {
+ error("kinfo_getswapvmobject()");
+ return (false);
+ }
+ do {
+ for (i = next_i; i < cnt; i++) {
+ if (kvo[i].kvo_type != KVME_TYPE_DEFAULT &&
+ kvo[i].kvo_type != KVME_TYPE_SWAP)
+ continue;
+ if (nswobj < maxnobj) {
+ swobj[nswobj].kvo_me = kvo[i].kvo_me;
+ swobj[nswobj].swapped = kvo[i].kvo_swapped;
+ swobj[nswobj].next = kvo[i].kvo_backing_obj;
+ swobj[nswobj].pid = 0;
+ next_i = i + 1;
+ }
+ nswobj++;
+ }
+ if (nswobj <= maxnobj)
+ break;
+ /* allocate memory and fill skipped elements */
+ last_nswobj = maxnobj;
+ maxnobj = nswobj;
+ nswobj = last_nswobj;
+ /* allocate more memory and fill missed ones */
+ if ((swobj = reallocf(swobj, maxnobj * sizeof(*swobj))) ==
+ NULL) {
+ error("Out of memory");
+ die(0);
+ }
+ } while (i <= cnt); /* extra safety guard */
+ free(kvo);
+ if (nswobj > 1)
+ qsort(swobj, nswobj, sizeof(swobj[0]), swobj_sort);
+ return (nswobj > 0);
+}
+
+/* This returns the number of swap pages a process uses. */
+static uint32_t
+per_proc_swap_usage(struct kinfo_proc *kipp)
+{
+ int i, cnt;
+ uint32_t pages = 0;
+ uint64_t vmobj;
+ struct kinfo_vmentry *freep, *kve;
+ struct swapvm *vm;
+
+ freep = procstat_getvmmap(prstat, kipp, &cnt);
+ if (freep == NULL)
+ return (pages);
+
+ for (i = 0; i < cnt; i++) {
+ kve = &freep[i];
+ if (kve->kve_type == KVME_TYPE_DEFAULT ||
+ kve->kve_type == KVME_TYPE_SWAP) {
+ vmobj = kve->kve_obj;
+ do {
+ vm = bsearch(&vmobj, swobj, nswobj,
+ sizeof(swobj[0]), swobj_search);
+ if (vm != NULL && vm->pid != kipp->ki_pid) {
+ pages += vm->swapped;
+ vmobj = vm->next;
+ vm->pid = kipp->ki_pid;
+ } else
+ break;
+ } while (vmobj != 0);
+ }
+ }
+ procstat_freevmmap(prstat, freep);
+ return (pages);
+}
+
+void
+procshow(int lcol, int hight, uint64_t totalswappages)
+{
+ int i, y;
+
+ for (i = 0, y = lcol + 1 /* HEADING */; i < hight; i++, y++)
+ display_proc_line(i, y, totalswappages);
+}
+
+int
+procinit(void)
+{
+
+ if (prstat == NULL)
+ prstat = procstat_open_sysctl();
+ return (prstat != NULL);
+}
+
+void
+procgetinfo(void)
+{
+ static int maxnproc = 0;
+ int cnt, i;
+ uint32_t pages;
+ struct kinfo_proc *kipp;
+
+ nproc = 0;
+ if ( ! get_swap_vmobjects() ) /* call failed or nothing is paged-out */
+ return;
+
+ kipp = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
+ if (kipp == NULL) {
+ error("procstat_getprocs()");
+ return;
+ }
+ if (maxnproc < cnt) {
+ if ((pu = realloc(pu, cnt * sizeof(*pu))) == NULL) {
+ error("Out of memory");
+ die(0);
+ }
+ memset(&pu[maxnproc], 0, (cnt - maxnproc) * sizeof(pu[0]));
+ maxnproc = cnt;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ pages = per_proc_swap_usage(&kipp[i]);
+ if (pages == 0)
+ continue;
+ if (pu[nproc] == NULL &&
+ (pu[nproc] = malloc(sizeof(**pu))) == NULL) {
+ error("Out of memory");
+ die(0);
+ }
+ strlcpy(pu[nproc]->command, kipp[i].ki_comm,
+ sizeof(pu[nproc]->command));
+ pu[nproc]->pid = kipp[i].ki_pid;
+ pu[nproc]->uid = kipp[i].ki_uid;
+ pu[nproc]->pages = pages;
+ pu[nproc]->total = kipp[i].ki_size;
+ nproc++;
+ }
+ if (nproc > 1)
+ qsort(pu, nproc, sizeof(*pu), proc_compar);
+ procstat_freeprocs(prstat, kipp);
+}
+
+void
+proclabel(int lcol)
+{
+
+ wmove(wnd, lcol, 0);
+ wclrtoeol(wnd);
+ mvwaddstr(wnd, lcol, 0,
+ "Pid Username Command Swap/Total "
+ "Per-Process Per-System");
+}
+
+int
+proc_compar(const void *a, const void *b)
+{
+ const struct proc_usage *aa = *((const struct proc_usage **)a);
+ const struct proc_usage *bb = *((const struct proc_usage **)b);
+
+ return (aa->pages > bb->pages ? -1 : 1);
+}
diff --git a/usr.bin/systat/sctp.c b/usr.bin/systat/sctp.c
new file mode 100644
index 000000000000..26abbec68da8
--- /dev/null
+++ b/usr.bin/systat/sctp.c
@@ -0,0 +1,354 @@
+/*-
+ * Copyright (c) 2015
+ * The Regents of the University of California. All rights reserved.
+ * Michael Tuexen. 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/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <netinet/sctp.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct sctpstat curstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 SCTP Associations SCTP Packets
+01999999999999 associations initiated 999999999999 packets sent
+02999999999999 associations accepted 999999999999 packets received
+03999999999999 associations restarted 999999999999 - out of the blue
+04999999999999 associations terminated 999999999999 - bad vtag
+05999999999999 associations aborted 999999999999 - bad crc32c
+06
+07 SCTP Timers SCTP Chunks
+08999999999999 init timeouts 999999999999 control chunks sent
+09999999999999 cookie timeouts 999999999999 data chunks sent
+10999999999999 data timeouts 999999999999 - ordered
+11999999999999 delayed sack timeouts 999999999999 - unordered
+12999999999999 shutdown timeouts 999999999999 control chunks received
+13999999999999 shutdown-ack timeouts 999999999999 data chunks received
+14999999999999 shutdown guard timeouts 999999999999 - ordered
+15999999999999 heartbeat timeouts 999999999999 - unordered
+16999999999999 path MTU timeouts
+17999999999999 autoclose timeouts SCTP user messages
+18999999999999 asconf timeouts 999999999999 fragmented
+19999999999999 stream reset timeouts 999999999999 reassembled
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+opensctp(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closesctp(WINDOW *w)
+{
+ if (w != NULL) {
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+ }
+}
+
+void
+labelsctp(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 13, str)
+#define R(row, str) mvwprintw(wnd, row, 51, str);
+ L(0, "SCTP Associations"); R(0, "SCTP Packets");
+ L(1, "associations initiated"); R(1, "packets sent");
+ L(2, "associations accepted"); R(2, "packets received");
+ L(3, "associations restarted"); R(3, "- out of the blue");
+ L(4, "associations terminated"); R(4, "- bad vtag");
+ L(5, "associations aborted"); R(5, "- bad crc32c");
+
+ L(7, "SCTP Timers"); R(7, "SCTP Chunks");
+ L(8, "init timeouts"); R(8, "control chunks sent");
+ L(9, "cookie timeouts"); R(9, "data chunks sent");
+ L(10, "data timeouts"); R(10, "- ordered");
+ L(11, "delayed sack timeouts"); R(11, "- unordered");
+ L(12, "shutdown timeouts"); R(12, "control chunks received");
+ L(13, "shutdown-ack timeouts"); R(13, "data chunks received");
+ L(14, "shutdown guard timeouts"); R(14, "- ordered");
+ L(15, "heartbeat timeouts"); R(15, "- unordered");
+ L(16, "path MTU timeouts");
+ L(17, "autoclose timeouts"); R(17, "SCTP User Messages");
+ L(18, "asconf timeouts"); R(18, "fragmented");
+ L(19, "stream reset timeouts"); R(19, "reassembled");
+#undef L
+#undef R
+}
+
+static void
+domode(struct sctpstat *ret)
+{
+ const struct sctpstat *sub;
+ int divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = curstat;
+ return;
+ }
+#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
+ DO(sctps_currestab);
+ DO(sctps_activeestab);
+ DO(sctps_restartestab);
+ DO(sctps_collisionestab);
+ DO(sctps_passiveestab);
+ DO(sctps_aborted);
+ DO(sctps_shutdown);
+ DO(sctps_outoftheblue);
+ DO(sctps_checksumerrors);
+ DO(sctps_outcontrolchunks);
+ DO(sctps_outorderchunks);
+ DO(sctps_outunorderchunks);
+ DO(sctps_incontrolchunks);
+ DO(sctps_inorderchunks);
+ DO(sctps_inunorderchunks);
+ DO(sctps_fragusrmsgs);
+ DO(sctps_reasmusrmsgs);
+ DO(sctps_outpackets);
+ DO(sctps_inpackets);
+
+ DO(sctps_recvpackets);
+ DO(sctps_recvdatagrams);
+ DO(sctps_recvpktwithdata);
+ DO(sctps_recvsacks);
+ DO(sctps_recvdata);
+ DO(sctps_recvdupdata);
+ DO(sctps_recvheartbeat);
+ DO(sctps_recvheartbeatack);
+ DO(sctps_recvecne);
+ DO(sctps_recvauth);
+ DO(sctps_recvauthmissing);
+ DO(sctps_recvivalhmacid);
+ DO(sctps_recvivalkeyid);
+ DO(sctps_recvauthfailed);
+ DO(sctps_recvexpress);
+ DO(sctps_recvexpressm);
+ DO(sctps_recvswcrc);
+ DO(sctps_recvhwcrc);
+
+ DO(sctps_sendpackets);
+ DO(sctps_sendsacks);
+ DO(sctps_senddata);
+ DO(sctps_sendretransdata);
+ DO(sctps_sendfastretrans);
+ DO(sctps_sendmultfastretrans);
+ DO(sctps_sendheartbeat);
+ DO(sctps_sendecne);
+ DO(sctps_sendauth);
+ DO(sctps_senderrors);
+ DO(sctps_sendswcrc);
+ DO(sctps_sendhwcrc);
+
+ DO(sctps_pdrpfmbox);
+ DO(sctps_pdrpfehos);
+ DO(sctps_pdrpmbda);
+ DO(sctps_pdrpmbct);
+ DO(sctps_pdrpbwrpt);
+ DO(sctps_pdrpcrupt);
+ DO(sctps_pdrpnedat);
+ DO(sctps_pdrppdbrk);
+ DO(sctps_pdrptsnnf);
+ DO(sctps_pdrpdnfnd);
+ DO(sctps_pdrpdiwnp);
+ DO(sctps_pdrpdizrw);
+ DO(sctps_pdrpbadd);
+ DO(sctps_pdrpmark);
+
+ DO(sctps_timoiterator);
+ DO(sctps_timodata);
+ DO(sctps_timowindowprobe);
+ DO(sctps_timoinit);
+ DO(sctps_timosack);
+ DO(sctps_timoshutdown);
+ DO(sctps_timoheartbeat);
+ DO(sctps_timocookie);
+ DO(sctps_timosecret);
+ DO(sctps_timopathmtu);
+ DO(sctps_timoshutdownack);
+ DO(sctps_timoshutdownguard);
+ DO(sctps_timostrmrst);
+ DO(sctps_timoearlyfr);
+ DO(sctps_timoasconf);
+ DO(sctps_timodelprim);
+ DO(sctps_timoautoclose);
+ DO(sctps_timoassockill);
+ DO(sctps_timoinpkill);
+
+ DO(sctps_hdrops);
+ DO(sctps_badsum);
+ DO(sctps_noport);
+ DO(sctps_badvtag);
+ DO(sctps_badsid);
+ DO(sctps_nomem);
+ DO(sctps_fastretransinrtt);
+ DO(sctps_markedretrans);
+ DO(sctps_naglesent);
+ DO(sctps_naglequeued);
+ DO(sctps_maxburstqueued);
+ DO(sctps_ifnomemqueued);
+ DO(sctps_windowprobed);
+ DO(sctps_lowlevelerr);
+ DO(sctps_lowlevelerrusr);
+ DO(sctps_datadropchklmt);
+ DO(sctps_datadroprwnd);
+ DO(sctps_ecnereducedcwnd);
+ DO(sctps_vtagexpress);
+ DO(sctps_vtagbogus);
+ DO(sctps_primary_randry);
+ DO(sctps_cmt_randry);
+ DO(sctps_slowpath_sack);
+ DO(sctps_wu_sacks_sent);
+ DO(sctps_sends_with_flags);
+ DO(sctps_sends_with_unord);
+ DO(sctps_sends_with_eof);
+ DO(sctps_sends_with_abort);
+ DO(sctps_protocol_drain_calls);
+ DO(sctps_protocol_drains_done);
+ DO(sctps_read_peeks);
+ DO(sctps_cached_chk);
+ DO(sctps_cached_strmoq);
+ DO(sctps_left_abandon);
+ DO(sctps_send_burst_avoid);
+ DO(sctps_send_cwnd_avoid);
+ DO(sctps_fwdtsn_map_over);
+ DO(sctps_queue_upd_ecne);
+#undef DO
+}
+
+void
+showsctp(void)
+{
+ struct sctpstat stats;
+
+ memset(&stats, 0, sizeof stats);
+ domode(&stats);
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%12u", stats.stat)
+#define L(row, stat) DO(stat, row, 0)
+#define R(row, stat) DO(stat, row, 38)
+ L(1, sctps_activeestab); R(1, sctps_outpackets);
+ L(2, sctps_passiveestab); R(2, sctps_inpackets);
+ L(3, sctps_restartestab); R(3, sctps_outoftheblue);
+ L(4, sctps_shutdown); R(4, sctps_badvtag);
+ L(5, sctps_aborted); R(5, sctps_checksumerrors);
+
+
+ L(8, sctps_timoinit); R(8, sctps_outcontrolchunks);
+ L(9, sctps_timocookie); R(9, sctps_senddata);
+ L(10, sctps_timodata); R(10, sctps_outorderchunks);
+ L(11, sctps_timosack); R(11, sctps_outunorderchunks);
+ L(12, sctps_timoshutdown); R(12, sctps_incontrolchunks);
+ L(13, sctps_timoshutdownack); R(13, sctps_recvdata);
+ L(14, sctps_timoshutdownguard); R(14, sctps_inorderchunks);
+ L(15, sctps_timoheartbeat); R(15, sctps_inunorderchunks);
+ L(16, sctps_timopathmtu);
+ L(17, sctps_timoautoclose);
+ L(18, sctps_timoasconf); R(18, sctps_fragusrmsgs);
+ L(19, sctps_timostrmrst); R(19, sctps_reasmusrmsgs);
+#undef DO
+#undef L
+#undef R
+}
+
+int
+initsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ len = 0;
+ if (sysctlbyname(name, NULL, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat) {
+ error("sctpstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctlbyname(name, &initstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+resetsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ len = sizeof initstat;
+ if (sysctlbyname(name, &initstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchsctp(void)
+{
+ size_t len;
+ const char *name = "net.inet.sctp.stats";
+
+ oldstat = curstat;
+ len = sizeof curstat;
+ if (sysctlbyname(name, &curstat, &len, NULL, 0) < 0) {
+ error("sysctl getting sctpstat failed");
+ }
+ return;
+}
diff --git a/usr.bin/systat/swap.c b/usr.bin/systat/swap.c
new file mode 100644
index 000000000000..89ed32b5d7f6
--- /dev/null
+++ b/usr.bin/systat/swap.c
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2017, 2020 Yoshihiro Ota
+ *
+ * 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.
+ */
+
+
+
+/*
+ * swapinfo - based on a program of the same name by Kevin Lahey
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <kvm.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <err.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+static int pathlen;
+
+WINDOW *
+openswap(void)
+{
+
+ return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closeswap(WINDOW *w)
+{
+
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+/*
+ * The meat of all the swap stuff is stolen from pstat(8)'s
+ * swapmode(), which is based on a program called swapinfo written by
+ * Kevin Lahey <kml@rokkaku.atl.ga.us>.
+ */
+
+#define NSWAP 16
+
+static struct kvm_swap kvmsw[NSWAP];
+static int kvnsw, okvnsw;
+
+int
+initswap(void)
+{
+ static int once = 0;
+
+ if (once)
+ return (1);
+
+ if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) {
+ error("systat: kvm_getswapinfo failed");
+ return (0);
+ }
+ pathlen = 80 - 50 /* % */ - 5 /* Used */ - 5 /* Size */ - 3 /* space */;
+ dsinit(12);
+ procinit();
+ once = 1;
+
+ return (1);
+}
+
+void
+fetchswap(void)
+{
+
+ okvnsw = kvnsw;
+ if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) {
+ error("systat: kvm_getswapinfo failed");
+ return;
+ }
+
+ struct devinfo *tmp_dinfo;
+
+ tmp_dinfo = last_dev.dinfo;
+ last_dev.dinfo = cur_dev.dinfo;
+ cur_dev.dinfo = tmp_dinfo;
+
+ last_dev.snap_time = cur_dev.snap_time;
+ dsgetinfo(&cur_dev);
+ procgetinfo();
+}
+
+void
+labelswap(void)
+{
+
+ werase(wnd);
+
+ dslabel(12, 0, LINES - DISKHIGHT - 1);
+
+ if (kvnsw <= 0) {
+ mvwprintw(wnd, 0, 0, "(swap not configured)");
+ return;
+ }
+
+ mvwprintw(wnd, 0, 0, "%*s%5s %5s %s",
+ -pathlen, "Device/Path", "Size", "Used",
+ "|0% /10 /20 /30 /40 / 60\\ 70\\ 80\\ 90\\ 100|");
+}
+
+void
+showswap(void)
+{
+ const char *name;
+ int count, i;
+
+ if (kvnsw != okvnsw)
+ labelswap();
+
+ dsshow(12, 0, LINES - DISKHIGHT - 1, &cur_dev, &last_dev);
+
+ if (kvnsw <= 0)
+ return;
+
+ for (i = (kvnsw == 1 ? 0 : kvnsw); i >= 0; i--) {
+ name = i == kvnsw ? "Total" : kvmsw[i].ksw_devname;
+ mvwprintw(wnd, 1 + i, 0, "%-*.*s", pathlen, pathlen - 1, name);
+
+ sysputpage(wnd, i + 1, pathlen, 5, kvmsw[i].ksw_total, 0);
+ sysputpage(wnd, i + 1, pathlen + 5 + 1, 5, kvmsw[i].ksw_used,
+ 0);
+
+ if (kvmsw[i].ksw_used > 0) {
+ count = 50 * kvmsw[i].ksw_used / kvmsw[i].ksw_total;
+ sysputXs(wnd, i + 1, pathlen + 5 + 1 + 5 + 1, count);
+ }
+ wclrtoeol(wnd);
+ }
+ count = kvnsw == 1 ? 2 : 3;
+ proclabel(kvnsw + count);
+ procshow(kvnsw + count, LINES - 5 - kvnsw + 3 - DISKHIGHT + 1,
+ kvmsw[kvnsw].ksw_total);
+}
diff --git a/usr.bin/systat/sysput.c b/usr.bin/systat/sysput.c
new file mode 100644
index 000000000000..6ae0075bb54d
--- /dev/null
+++ b/usr.bin/systat/sysput.c
@@ -0,0 +1,113 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019, 2020 Yoshihiro Ota
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <string.h>
+
+#include "systat.h"
+#include "extern.h"
+
+void
+sysputspaces(WINDOW *wd, int row, int lcol, int width)
+{
+ static char str60[] = " "
+ " ";
+
+ mvwaddstr(wd, row, lcol, str60 + sizeof(str60) - width - 1);
+}
+
+void
+sysputstrs(WINDOW *wd __unused, int row, int lcol, int width)
+{
+ static char str60[] = "********************"
+ "****************************************";
+
+ /*
+ * XXX wnd instead of wd?
+ */
+ mvwaddstr(wnd, row, lcol, str60 + sizeof(str60) - width - 1);
+}
+
+void
+sysputXs(WINDOW *wd __unused, int row, int lcol, int width)
+{
+ static char str60[] = "XXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
+
+ /*
+ * XXX wnd instead of wd?
+ */
+ mvwaddstr(wnd, row, lcol, str60 + sizeof(str60) - width - 1);
+}
+
+void
+sysputuint64(WINDOW *wd, int row, int lcol, int width, uint64_t val, int flags)
+{
+ char *start, wrtbuf[width + width + 1];
+ int len;
+
+ start = wrtbuf;
+ flags |= HN_NOSPACE;
+
+ if (val > INT64_MAX)
+ goto error;
+ else
+ len = humanize_number(&wrtbuf[width], width + 1, val, "",
+ HN_AUTOSCALE, flags);
+ if (len < 0)
+ goto error;
+ else if (len < width)
+ memset(wrtbuf + len, ' ', width - len);
+ start += len;
+
+ mvwaddstr(wd, row, lcol, start);
+ return;
+
+error:
+ sysputstrs(wd, row, lcol, width);
+}
+
+void
+sysputwuint64(WINDOW *wd, int row, int lcol, int width, uint64_t val, int flags)
+{
+ if(val == 0)
+ sysputspaces(wd, row, lcol, width);
+ else
+ sysputuint64(wd, row, lcol, width, val, flags);
+}
+
+void
+sysputpage(WINDOW *wd, int row, int lcol, int width, uint64_t pages, int flags)
+{
+
+ sysputuint64(wd, row, lcol, width, ptoa(pages), flags);
+}
diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1
new file mode 100644
index 000000000000..89ffe30f69bf
--- /dev/null
+++ b/usr.bin/systat/systat.1
@@ -0,0 +1,745 @@
+.\" Copyright (c) 1985, 1990, 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.
+.\"
+.Dd April 1, 2022
+.Dt SYSTAT 1
+.Os
+.Sh NAME
+.Nm systat
+.Nd display system statistics
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ar display
+.Op Ar display-commands
+.Op Ar refresh-interval
+.Sh DESCRIPTION
+The
+.Nm
+utility displays various system statistics in a screen oriented fashion
+using the curses screen display library,
+.Xr ncurses 3 .
+.Pp
+While
+.Nm
+is running the screen is usually divided into two windows (an exception
+is the vmstat display which uses the entire screen).
+The
+upper window depicts the current system load average.
+The
+information displayed in the lower window may vary, depending on
+user commands.
+The last line on the screen is reserved for user
+input and error messages.
+.Pp
+By default
+.Nm
+displays the processes getting the largest percentage of the processor
+in the lower window.
+Other displays show swap space usage, disk I/O statistics (a la
+.Xr iostat 8 ) ,
+virtual memory statistics (a la
+.Xr vmstat 8 ) ,
+TCP/IP statistics,
+and network connections (a la
+.Xr netstat 1 ) .
+.Pp
+Input is interpreted at two different levels.
+A ``global'' command interpreter processes all keyboard input.
+If this command interpreter fails to recognize a command, the
+input line is passed to a per-display command interpreter.
+This
+allows each display to have certain display-specific commands.
+.Pp
+Command line options:
+.Bl -tag -width "refresh_interval"
+.It Fl Ns Ar display
+The
+.Fl
+flag expects
+.Ar display
+to be one of:
+.Ic icmp ,
+.Ic icmp6 ,
+.Ic ifstat ,
+.Ic iolat ,
+.Ic iostat ,
+.Ic ip ,
+.Ic ip6 ,
+.Ic netstat ,
+.Ic pigs ,
+.Ic sctp ,
+.Ic swap ,
+.Ic tcp ,
+.Ic vmstat ,
+or
+.Ic zarc ,
+These displays can also be requested interactively (without the
+.Dq Fl )
+and are described in
+full detail below.
+.It Ar refresh-interval
+The
+.Ar refresh-value
+specifies the screen refresh time interval in seconds.
+Time interval can be fractional.
+.It Ar display-commands
+A list of commands specific to this display.
+These commands can also be entered interactively and are described for
+each display separately below.
+If the command requires arguments, they can be specified as separate
+command line arguments.
+A command line argument
+.Fl -
+will finish display commands.
+For example:
+.Pp
+.Dl Nm Fl ifstat Fl match Ar bge0,em1 Fl pps
+.Pp
+This will display statistics of packets per second for network interfaces
+named as bge0 and em1.
+.Pp
+.Dl Nm Fl iostat Fl numbers Fl - Ar 2.1
+.Pp
+This will display all IO statistics in a numeric format and the information
+will be refreshed each 2.1 seconds.
+.El
+.Pp
+Certain characters cause immediate action by
+.Nm .
+These are
+.Bl -tag -width Fl
+.It Ic \&^L
+Refresh the screen.
+.It Ic \&^G
+Print the name of the current ``display'' being shown in
+the lower window and the refresh interval.
+.It Ic \&:
+Move the cursor to the command line and interpret the input
+line typed as a command.
+While entering a command the
+current character erase, word erase, and line kill characters
+may be used.
+.El
+.Pp
+The following commands are interpreted by the ``global''
+command interpreter.
+.Bl -tag -width Fl
+.It Ic help
+Print the names of the available displays on the command line.
+.It Ic load
+Print the load average over the past 1, 5, and 15 minutes
+on the command line.
+.It Ic stop
+Stop refreshing the screen.
+.It Xo
+.Op Ic start
+.Op Ar number
+.Xc
+Start (continue) refreshing the screen.
+If a second, numeric,
+argument is provided it is interpreted as a refresh interval
+(in seconds).
+Supplying only a number will set the refresh interval to this
+value.
+.It Ic quit
+Exit
+.Nm .
+(This may be abbreviated to
+.Ic q . )
+.El
+.Pp
+The available displays are:
+.Bl -tag -width Ic
+.It Ic pigs
+Display, in the lower window, those processes resident in main
+memory and getting the
+largest portion of the processor (the default display).
+When less than 100% of the
+processor is scheduled to user processes, the remaining time
+is accounted to the ``idle'' process.
+.It Ic icmp
+Display, in the lower window, statistics about messages received and
+transmitted by the Internet Control Message Protocol
+.Pq Dq ICMP .
+The left half of the screen displays information about received
+packets, and the right half displays information regarding transmitted
+packets.
+.Pp
+The
+.Ic icmp
+display understands two commands:
+.Ic mode
+and
+.Ic reset .
+The
+.Ic mode
+command is used to select one of four display modes, given as its argument:
+.Bl -tag -width absoluteXX -compact
+.It Ic rate :
+show the rate of change of each value in packets (the default)
+per second
+.It Ic delta :
+show the rate of change of each value in packets per refresh interval
+.It Ic since :
+show the total change of each value since the display was last reset
+.It Ic absolute :
+show the absolute value of each statistic
+.El
+.Pp
+The
+.Ic reset
+command resets the baseline for
+.Ic since
+mode.
+The
+.Ic mode
+command with no argument will display the current mode in the command
+line.
+.It Ic icmp6
+This display is like the
+.Ic icmp
+display,
+but displays statistics for IPv6 ICMP.
+.It Ic ip
+Otherwise identical to the
+.Ic icmp
+display, except that it displays IP and UDP statistics.
+.It Ic ip6
+Like the
+.Ic ip
+display,
+except that it displays IPv6 statistics.
+It does not display UDP statistics.
+.It Ic sctp
+Like
+.Ic icmp ,
+but with SCTP statistics.
+.It Ic tcp
+Like
+.Ic icmp ,
+but with TCP statistics.
+.It Ic iolat
+Display statistics describing the hardware latencies of I/O operations as
+computed by the
+.Va CAM_IOSCHED_DYNAMIC
+option.
+This option must be in the kernel config file of the running kernel for this
+display to work.
+All devices are displayed as there is currently no way to filter them.
+The statistics displayed for the I/O latencies are the percentiles with
+sufficient data during the polling interval to compute.
+If a value cannot be estimated ``-'' is displayed.
+The P50 (also known as the median), P90, P99 and P99.9 values are computed if
+more than 2, 10, 100 or 1000 operations occurred during the polling interval.
+The latency is the hardware latency values, and does not include any software
+queuing time.
+The latencies are estimated based on histogram data computed by the CAM I/O
+scheduler and represent estimates of the actual value that are only good to
+two or three significant digits.
+The display of latency changes based on the scale of the latency to reflect
+the precision of the estimates and to fit on the available screen space.
+All latencies are reported in milliseconds.
+When color is enabled
+.Bl -bullet
+.It
+Values below the medium latency threshold are displayed in green.
+.It
+Values between the minimum latency and high latency thresholds are displayed
+in magenta.
+.It
+Values above the high latency thresholds are displayed in red.
+.Pp
+When color is disabled, the default foreground and background colors are always
+used.
+.Pp
+The following commands are specific to the
+.Ic iolat
+display; the minimum unambiguous prefix may be supplied.
+.Pp
+.Bl -tag -width Fl -compact
+.It Cm color
+Toggle the use of color in the display.
+The default is on.
+.It Cm hi=XXX
+Set the high latency threshold to XXX milliseconds.
+.It Cm med=XXX
+Set the medium latency threshold to XXX milliseconds.
+.It Cm read
+Toggle the display of statistics about read operations.
+The default is on.
+.It Cm write
+Toggle the display of statistics about write operations.
+The default is on.
+.It Cm trim
+Toggle the display of statistics about trim operations.
+The default is on.
+.El
+.El
+.It Ic iostat
+Display, in the lower window, statistics about processor use
+and disk throughput.
+Statistics on processor use appear as
+bar graphs of the amount of time executing in user mode (``user''),
+in user mode running low priority processes (``nice''), in
+system mode (``system''), in interrupt mode (``interrupt''),
+and idle (``idle'').
+Statistics
+on disk throughput show, for each drive, megabytes per second,
+average number of disk transactions per second, and
+average kilobytes of data per transaction.
+This information may be
+displayed as bar graphs or as rows of numbers which scroll downward.
+Bar
+graphs are shown by default.
+.Pp
+The following commands are specific to the
+.Ic iostat
+display; the minimum unambiguous prefix may be supplied.
+.Pp
+.Bl -tag -width Fl -compact
+.It Cm numbers
+Show the disk I/O statistics in numeric form.
+Values are
+displayed in numeric columns which scroll downward.
+.It Cm bars
+Show the disk I/O statistics in bar graph form (default).
+.It Cm kbpt
+Toggle the display of kilobytes per transaction.
+(the default is to
+not display kilobytes per transaction).
+.El
+.It Ic swap
+Show information about swap space usage on all the
+swap areas compiled into the kernel and processes that are swapped out
+as well as a summary of disk activity.
+.Pp
+The swap areas are displayed first with their name, sizes and
+usage percentage.
+The
+.Ar Used
+column indicates the total blocks used so far;
+the graph shows the percentage of space in use on each partition.
+If there are more than one swap partition in use,
+a total line is also shown.
+Areas known to the kernel, but not in use are shown as not available.
+.Pp
+Below the swap space statistics,
+processes are listed in order of higher swap area usage.
+Pid, username, a part of command line, the total use of swap space
+in bytes, the size of process, as well as per-process swap usage percentage and
+per-system swap space percentage are shown per process.
+.Pp
+At the bottom left is the disk usage display.
+It reports the number of
+kilobytes per transaction, transactions per second, megabytes
+per second and the percentage of the time the disk was busy averaged
+over the refresh period of the display (by default, five seconds).
+The system keeps statistics on most every storage device.
+In general, up
+to seven devices are displayed.
+The devices displayed by default are the
+first devices in the kernel's device list.
+See
+.Xr devstat 3
+and
+.Xr devstat 9
+for details on the devstat system.
+.It Ic vmstat
+Take over the entire display and show a (rather crowded) compendium
+of statistics related to virtual memory usage, process scheduling,
+device interrupts, system name translation caching, disk I/O etc.
+.Pp
+The upper left quadrant of the screen shows the number
+of users logged in and the load average over the last one, five,
+and fifteen minute intervals.
+Below this line are statistics on memory utilization.
+The first row of the table reports memory usage only among
+active processes, that is processes that have run in the previous
+twenty seconds.
+The second row reports on memory usage of all processes.
+The first column reports on the number of kilobytes in physical pages
+claimed by processes.
+The second column reports the number of kilobytes in physical pages that
+are devoted to read only text pages.
+The third and fourth columns report the same two figures for
+virtual pages, that is the number of kilobytes in pages that would be
+needed if all processes had all of their pages.
+Finally the last column shows the number of kilobytes in physical pages
+on the free list.
+.Pp
+Below the memory display is a list of the
+average number of threads (over the last refresh interval)
+that are runnable (`r'), in page wait (`p'),
+in disk wait other than paging (`d'),
+sleeping (`s'), and swapped out but desiring to run (`w').
+The row also shows the average number of context switches
+(`Csw'), traps (`Trp'; includes page faults), system calls (`Sys'),
+interrupts (`Int'), network software interrupts (`Sof'), and page
+faults (`Flt').
+.Pp
+Below the process queue length listing is a numerical listing and
+a bar graph showing the amount of
+system (shown as `='), interrupt (shown as `+'), user (shown as `>'),
+nice (shown as `-'), and idle time (shown as ` ').
+.Pp
+Below the process display are statistics on name translations.
+It lists the number of names translated in the previous interval,
+the number and percentage of the translations that were
+handled by the system wide name translation cache, and
+the number and percentage of the translations that were
+handled by the per process name translation cache.
+.Pp
+To the right of the name translations display are lines showing
+the number of dirty buffers in the buffer cache (`dtbuf'),
+desired maximum size of vnode cache (`desvn'),
+number of vnodes actually allocated (`numvn'),
+and
+number of allocated vnodes that are free (`frevn').
+.Pp
+At the bottom left is the disk usage display.
+It reports the number of
+kilobytes per transaction, transactions per second, megabytes
+per second and the percentage of the time the disk was busy averaged
+over the refresh period of the display (by default, five seconds).
+The system keeps statistics on most every storage device.
+In general, up
+to seven devices are displayed.
+The devices displayed by default are the
+first devices in the kernel's device list.
+See
+.Xr devstat 3
+and
+.Xr devstat 9
+for details on the devstat system.
+.Pp
+Under the date in the upper right hand quadrant are statistics
+on paging and swapping activity.
+The first two columns report the average number of pages
+brought in and out per second over the last refresh interval
+due to page faults and the paging daemon.
+The third and fourth columns report the average number of pages
+brought in and out per second over the last refresh interval
+due to swap requests initiated by the scheduler.
+The first row of the display shows the average
+number of disk transfers per second over the last refresh interval;
+the second row of the display shows the average
+number of pages transferred per second over the last refresh interval.
+.Pp
+Below the paging statistics is a column of lines regarding the virtual
+memory system.
+The first few lines describe,
+in units (except as noted below)
+of pages per second averaged over the sampling interval,
+pages copied on write (`cow'),
+pages zero filled on demand (`zfod'),
+pages optimally zero filled on demand (`ozfod'),
+the ratio of the (average) ozfod / zfod as a percentage (`%ozfod'),
+pages freed by the page daemon (`daefr'),
+pages freed by exiting processes (`prcfr'),
+total pages freed (`totfr'),
+pages reactivated from the free list (`react'),
+the average number of
+times per second that the page daemon was awakened (`pdwak'),
+pages analyzed by the page daemon (`pdpgs'),
+and
+in-transit blocking page faults (`intrn').
+Note that the units are special for `%ozfod' and `pdwak'.
+The next few lines describe,
+as amounts of memory in kilobytes,
+pages wired down (`wire'),
+active pages (`act'),
+inactive pages (`inact'),
+dirty pages queued for laundering (`laund'),
+and
+free pages (`free').
+Note that the values displayed are the current transient ones;
+they are not averages.
+.Pp
+At the bottom of this column is a line showing the
+amount of virtual memory, in kilobytes, mapped into the buffer cache (`buf').
+This statistic is not useful.
+It exists only as a placeholder for the corresponding useful statistic
+(the amount of real memory used to cache disks).
+The most important component of the latter (the amount of real memory
+used by the vm system to cache disks) is not available,
+but can be guessed from the `inact' amount under some system loads.
+.Pp
+Running down the right hand side of the display is a breakdown
+of the interrupts being handled by the system.
+At the top of the list is the total interrupts per second
+over the time interval.
+The rest of the column breaks down the total on a device
+by device basis.
+Only devices that have interrupted at least once since boot time are shown.
+.Pp
+The following commands are specific to the
+.Ic vmstat
+display; the minimum unambiguous prefix may be supplied.
+.Pp
+.Bl -tag -width Ar -compact
+.It Cm boot
+Display cumulative statistics since the system was booted.
+.It Cm run
+Display statistics as a running total from the point this
+command is given.
+.It Cm time
+Display statistics averaged over the refresh interval (the default).
+.It Cm zero
+Reset running statistics to zero.
+.El
+.It Ic zarc
+display arc cache usage and hit/miss statistics.
+.It Ic netstat
+Display, in the lower window, network connections.
+By default,
+network servers awaiting requests are not displayed.
+Each address
+is displayed in the format ``host.port'', with each shown symbolically,
+when possible.
+It is possible to have addresses displayed numerically,
+limit the display to a set of ports, hosts, and/or protocols
+(the minimum unambiguous prefix may be supplied):
+.Pp
+.Bl -tag -width Ar -compact
+.It Cm all
+Toggle the displaying of server processes awaiting requests (this
+is the equivalent of the
+.Fl a
+flag to
+.Xr netstat 1 ) .
+.It Cm numbers
+Display network addresses numerically.
+.It Cm names
+Display network addresses symbolically.
+.It Cm proto Ar protocol
+Display only network connections using the indicated
+.Ar protocol .
+Supported protocols are ``tcp'', ``udp'', and ``all''.
+.It Cm ignore Op Ar items
+Do not display information about connections associated with
+the specified hosts or ports.
+Hosts and ports may be specified
+by name (``vangogh'', ``ftp''), or numerically.
+Host addresses
+use the Internet dot notation (``128.32.0.9'').
+Multiple items
+may be specified with a single command by separating them with
+spaces.
+.It Cm display Op Ar items
+Display information about the connections associated with the
+specified hosts or ports.
+As for
+.Ar ignore ,
+.Op Ar items
+may be names or numbers.
+.It Cm show Op Ar ports\&|hosts
+Show, on the command line, the currently selected protocols,
+hosts, and ports.
+Hosts and ports which are being ignored
+are prefixed with a `!'.
+If
+.Ar ports
+or
+.Ar hosts
+is supplied as an argument to
+.Cm show ,
+then only the requested information will be displayed.
+.It Cm reset
+Reset the port, host, and protocol matching mechanisms to the default
+(any protocol, port, or host).
+.El
+.It Ic ifstat
+Display the network traffic going through active interfaces on the
+system.
+Idle interfaces will not be displayed until they receive some
+traffic.
+.Pp
+For each interface being displayed, the current, peak and total
+statistics are displayed for incoming and outgoing traffic.
+By default,
+the
+.Ic ifstat
+display will automatically scale the units being used so that they are
+in a human-readable format.
+The scaling units used for the current and
+peak
+traffic columns can be altered by the
+.Ic scale
+command.
+.Bl -tag -width ".Cm scale Op Ar units"
+.It Cm scale Op Ar units
+Modify the scale used to display the current and peak traffic over all
+interfaces.
+The following units are recognised: kbit, kbyte, mbit,
+mbyte, gbit, gbyte and auto.
+.It Cm pps
+Show statistics in packets per second instead of bytes/bits per second.
+A subsequent call of
+.Ic pps
+switches this mode off.
+.It Cm match Op Ar patterns
+Display only interfaces that match pattern provided as an argument.
+Patterns should be in shell syntax separated by whitespaces or commas.
+If this command is called without arguments then all interfaces are displayed.
+For example:
+.Pp
+.Dl match em0, bge1
+.Pp
+This will display em0 and bge1 interfaces.
+.Pp
+.Dl match em*, bge*, lo0
+.Pp
+This will display all
+.Ic em
+interfaces, all
+.Ic bge
+interfaces and the loopback interface.
+.El
+.El
+.Pp
+Commands to switch between displays may be abbreviated to the
+minimum unambiguous prefix; for example, ``io'' for ``iostat''.
+Certain information may be discarded when the screen size is
+insufficient for display.
+For example, on a machine with 10
+drives the
+.Ic iostat
+bar graph displays only 3 drives on a 24 line terminal.
+When
+a bar graph would overflow the allotted screen space it is
+truncated and the actual value is printed ``over top'' of the bar.
+.Pp
+The following commands are common to each display which shows
+information about disk drives.
+These commands are used to
+select a set of drives to report on, should your system have
+more drives configured than can normally be displayed on the
+screen.
+.Pp
+.Bl -tag -width Ar -compact
+.It Cm ignore Op Ar drives
+Do not display information about the drives indicated.
+Multiple
+drives may be specified, separated by spaces.
+.It Cm display Op Ar drives
+Display information about the drives indicated.
+Multiple drives
+may be specified, separated by spaces.
+.It Cm only Op Ar drives
+Display only the specified drives.
+Multiple drives may be specified,
+separated by spaces.
+.It Cm drives
+Display a list of available devices.
+.It Cm match Xo
+.Ar type , Ns Ar if , Ns Ar pass
+.Op | Ar ...
+.Xc
+Display devices matching the given pattern.
+The basic matching
+expressions are the same as those used in
+.Xr iostat 8
+with one difference.
+Instead of specifying multiple
+.Fl t
+arguments which are then ORed together, the user instead specifies multiple
+matching expressions joined by the pipe
+.Pq Ql \&|
+character.
+The comma
+separated arguments within each matching expression are ANDed together, and
+then the pipe separated matching expressions are ORed together.
+Any
+device matching the combined expression will be displayed, if there is room
+to display it.
+For example:
+.Pp
+.Dl match da,scsi | cd,ide
+.Pp
+This will display all SCSI Direct Access devices and all IDE CDROM devices.
+.Pp
+.Dl match da | sa | cd,pass
+.Pp
+This will display all Direct Access devices, all Sequential Access devices,
+and all passthrough devices that provide access to CDROM drives.
+.El
+.Sh FILES
+.Bl -tag -width /boot/kernel/kernel -compact
+.It Pa /boot/kernel/kernel
+For the namelist.
+.It Pa /dev/kmem
+For information in main memory.
+.It Pa /etc/hosts
+For host names.
+.It Pa /etc/networks
+For network names.
+.It Pa /etc/services
+For port names.
+.El
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr kvm 3 ,
+.Xr icmp 4 ,
+.Xr icmp6 4 ,
+.Xr ip 4 ,
+.Xr ip6 4 ,
+.Xr tcp 4 ,
+.Xr udp 4 ,
+.Xr gstat 8 ,
+.Xr iostat 8 ,
+.Xr vmstat 8
+.Sh HISTORY
+The
+.Nm
+program appeared in
+.Bx 4.3 .
+The
+.Ic icmp ,
+.Ic ip ,
+and
+.Ic tcp
+displays appeared in
+.Fx 3.0 ;
+the notion of having different display modes for the
+ICMP, IP, TCP, and UDP statistics was stolen from the
+.Fl C
+option to
+.Xr netstat 1
+in Silicon Graphics' IRIX system.
+.Sh BUGS
+Certain displays presume a minimum of 80 characters per line.
+Ifstat does not detect new interfaces.
+The
+.Ic vmstat
+display looks out of place because it is (it was added in as
+a separate display rather than created as a new program).
+The
+.Ic iolat
+command does not implement the common device commands including
+filtering, as it does not use the
+.Xr devstat 3
+mechanism to obtain its statistics.
diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h
new file mode 100644
index 000000000000..55a21a04998a
--- /dev/null
+++ b/usr.bin/systat/systat.h
@@ -0,0 +1,77 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1989, 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.
+ */
+
+#include <sys/stdint.h>
+#include <curses.h>
+
+struct cmdtab {
+ const char *c_name; /* command name */
+ void (*c_refresh)(void); /* display refresh */
+ void (*c_fetch)(void); /* sets up data structures */
+ void (*c_label)(void); /* label display */
+ int (*c_init)(void); /* initialize namelist, etc. */
+ WINDOW *(*c_open)(void); /* open display */
+ void (*c_close)(WINDOW *); /* close display */
+ int (*c_cmd)(const char *, const char *); /* display command interpreter */
+ void (*c_reset)(void); /* reset ``mode since'' display */
+ char c_flags; /* see below */
+};
+
+/*
+ * If we are started with privileges, use a kmem interface for netstat handling,
+ * otherwise use sysctl.
+ * In case of many open sockets, the sysctl handling might become slow.
+ */
+extern int use_kvm;
+
+#define CF_INIT 0x1 /* been initialized */
+#define CF_LOADAV 0x2 /* display w/ load average */
+#define CF_ZFSARC 0x4 /* display w/ ZFS cache usage */
+
+#define TCP 0x1
+#define UDP 0x2
+
+#define MAINWIN_ROW 3 /* top row for the main/lower window */
+
+#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
+#define KREAD(addr, buf, len) kvm_ckread((addr), (buf), (len))
+#define NVAL(indx) namelist[(indx)].n_value
+#define NPTR(indx) (void *)NVAL((indx))
+#define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len))
+
+extern void putint(int, int, int, int);
+extern void putfloat(double, int, int, int, int, int);
+extern void putlongdouble(long double, int, int, int, int, int);
+
+int procinit(void);
+void procgetinfo(void);
+void proclabel(int col);
+void procshow(int col, int hight, uint64_t totalswappages);
diff --git a/usr.bin/systat/tcp.c b/usr.bin/systat/tcp.c
new file mode 100644
index 000000000000..83163a3525a8
--- /dev/null
+++ b/usr.bin/systat/tcp.c
@@ -0,0 +1,319 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+
+static struct tcpstat curstat, initstat, oldstat;
+
+/*-
+--0 1 2 3 4 5 6 7
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+00 TCP Connections TCP Packets
+01999999999999 connections initiated 999999999999 total packets sent
+02999999999999 connections accepted 999999999999 - data
+03999999999999 connections established 999999999999 - data (retransmit by dupack)
+04999999999999 connections dropped 999999999999 - data (retransmit by sack)
+05999999999999 - in embryonic state 999999999999 - ack-only
+06999999999999 - on retransmit timeout 999999999999 - window probes
+07999999999999 - by keepalive 999999999999 - window updates
+08999999999999 - from listen queue 999999999999 - urgent data only
+09 999999999999 - control
+10 999999999999 - resends by PMTU discovery
+11 TCP Timers 999999999999 total packets received
+12999999999999 potential rtt updates 999999999999 - in sequence
+13999999999999 - successful 999999999999 - completely duplicate
+14999999999999 delayed acks sent 999999999999 - with some duplicate data
+15999999999999 retransmit timeouts 999999999999 - out-of-order
+16999999999999 persist timeouts 999999999999 - duplicate acks
+17999999999999 keepalive probes 999999999999 - acks
+18999999999999 - timeouts 999999999999 - window probes
+19 999999999999 - window updates
+20 999999999999 - bad checksum
+--0123456789012345678901234567890123456789012345678901234567890123456789012345
+--0 1 2 3 4 5 6 7
+*/
+
+WINDOW *
+opentcp(void)
+{
+ return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closetcp(WINDOW *w)
+{
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labeltcp(void)
+{
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+#define L(row, str) mvwprintw(wnd, row, 13, str)
+#define R(row, str) mvwprintw(wnd, row, 51, str);
+ L(0, "TCP Connections"); R(0, "TCP Packets");
+ L(1, "connections initiated"); R(1, "total packets sent");
+ L(2, "connections accepted"); R(2, "- data");
+ L(3, "connections established"); R(3, "- data (retransmit by dupack)");
+ L(4, "connections dropped"); R(4, "- data (retransmit by sack)");
+ L(5, "- in embryonic state"); R(5, "- ack-only");
+ L(6, "- on retransmit timeout"); R(6, "- window probes");
+ L(7, "- by keepalive"); R(7, "- window updates");
+ L(8, "- exceeded progress time"); R(8, "- urgent data only");
+ L(9, "- from listen queue"); R(9, "- control");
+ R(10, "- resends by PMTU discovery");
+ L(11, "TCP Timers"); R(11, "total packets received");
+ L(12, "potential rtt updates"); R(12, "- in sequence");
+ L(13, "- successful"); R(13, "- completely duplicate");
+ L(14, "delayed acks sent"); R(14, "- with some duplicate data");
+ L(15, "retransmit timeouts"); R(15, "- out-of-order");
+ L(16, "persist timeouts"); R(16, "- duplicate acks");
+ L(17, "keepalive probes"); R(17, "- acks");
+ L(18, "- timeouts"); R(18, "- window probes");
+ R(19, "- window updates");
+ R(20, "- bad checksum");
+#undef L
+#undef R
+}
+
+static void
+domode(struct tcpstat *ret)
+{
+ const struct tcpstat *sub;
+ int divisor = 1;
+
+ switch(currentmode) {
+ case display_RATE:
+ sub = &oldstat;
+ divisor = (delay > 1000000) ? delay / 1000000 : 1;
+ break;
+ case display_DELTA:
+ sub = &oldstat;
+ break;
+ case display_SINCE:
+ sub = &initstat;
+ break;
+ default:
+ *ret = curstat;
+ return;
+ }
+#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
+ DO(tcps_connattempt);
+ DO(tcps_accepts);
+ DO(tcps_connects);
+ DO(tcps_drops);
+ DO(tcps_conndrops);
+ DO(tcps_closed);
+ DO(tcps_segstimed);
+ DO(tcps_rttupdated);
+ DO(tcps_delack);
+ DO(tcps_timeoutdrop);
+ DO(tcps_rexmttimeo);
+ DO(tcps_persisttimeo);
+ DO(tcps_keeptimeo);
+ DO(tcps_keepprobe);
+ DO(tcps_keepdrops);
+ DO(tcps_progdrops);
+
+ DO(tcps_sndtotal);
+ DO(tcps_sndpack);
+ DO(tcps_sndbyte);
+ DO(tcps_sndrexmitpack);
+ DO(tcps_sack_rexmits);
+ DO(tcps_sndacks);
+ DO(tcps_sndprobe);
+ DO(tcps_sndurg);
+ DO(tcps_sndwinup);
+ DO(tcps_sndctrl);
+
+ DO(tcps_rcvtotal);
+ DO(tcps_rcvpack);
+ DO(tcps_rcvbyte);
+ DO(tcps_rcvbadsum);
+ DO(tcps_rcvbadoff);
+ DO(tcps_rcvshort);
+ DO(tcps_rcvduppack);
+ DO(tcps_rcvdupbyte);
+ DO(tcps_rcvpartduppack);
+ DO(tcps_rcvpartdupbyte);
+ DO(tcps_rcvoopack);
+ DO(tcps_rcvoobyte);
+ DO(tcps_rcvpackafterwin);
+ DO(tcps_rcvbyteafterwin);
+ DO(tcps_rcvafterclose);
+ DO(tcps_rcvwinprobe);
+ DO(tcps_rcvdupack);
+ DO(tcps_rcvacktoomuch);
+ DO(tcps_rcvackpack);
+ DO(tcps_rcvackbyte);
+ DO(tcps_rcvwinupd);
+ DO(tcps_pawsdrop);
+ DO(tcps_predack);
+ DO(tcps_preddat);
+ DO(tcps_pcbcachemiss);
+ DO(tcps_cachedrtt);
+ DO(tcps_cachedrttvar);
+ DO(tcps_cachedssthresh);
+ DO(tcps_usedrtt);
+ DO(tcps_usedrttvar);
+ DO(tcps_usedssthresh);
+ DO(tcps_persistdrop);
+ DO(tcps_badsyn);
+ DO(tcps_mturesent);
+ DO(tcps_listendrop);
+#undef DO
+}
+
+void
+showtcp(void)
+{
+ struct tcpstat stats;
+
+ memset(&stats, 0, sizeof stats);
+ domode(&stats);
+
+#define DO(stat, row, col) \
+ mvwprintw(wnd, row, col, "%12"PRIu64, stats.stat)
+#define L(row, stat) DO(stat, row, 0)
+#define R(row, stat) DO(stat, row, 38)
+ L(1, tcps_connattempt); R(1, tcps_sndtotal);
+ L(2, tcps_accepts); R(2, tcps_sndpack);
+ L(3, tcps_connects); R(3, tcps_sndrexmitpack);
+ L(4, tcps_drops); R(4, tcps_sack_rexmits);
+ L(5, tcps_conndrops); R(5, tcps_sndacks);
+ L(6, tcps_timeoutdrop); R(6, tcps_sndprobe);
+ L(7, tcps_keepdrops); R(7, tcps_sndwinup);
+ L(8, tcps_progdrops); R(8, tcps_sndurg);
+ L(9, tcps_listendrop); R(9, tcps_sndctrl);
+ R(10, tcps_mturesent);
+ R(11, tcps_rcvtotal);
+ L(12, tcps_segstimed); R(12, tcps_rcvpack);
+ L(13, tcps_rttupdated); R(13, tcps_rcvduppack);
+ L(14, tcps_delack); R(14, tcps_rcvpartduppack);
+ L(15, tcps_rexmttimeo); R(15, tcps_rcvoopack);
+ L(16, tcps_persisttimeo); R(16, tcps_rcvdupack);
+ L(17, tcps_keepprobe); R(17, tcps_rcvackpack);
+ L(18, tcps_keeptimeo); R(18, tcps_rcvwinprobe);
+ R(19, tcps_rcvwinupd);
+ R(20, tcps_rcvbadsum);
+#undef DO
+#undef L
+#undef R
+}
+
+int
+inittcp(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_TCP;
+ name[3] = TCPCTL_STATS;
+
+ len = 0;
+ if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
+ error("sysctl getting tcpstat size failed");
+ return 0;
+ }
+ if (len > sizeof curstat) {
+ error("tcpstat structure has grown--recompile systat!");
+ return 0;
+ }
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting tcpstat failed");
+ return 0;
+ }
+ oldstat = initstat;
+ return 1;
+}
+
+void
+resettcp(void)
+{
+ size_t len;
+ int name[4];
+
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_TCP;
+ name[3] = TCPCTL_STATS;
+
+ len = sizeof initstat;
+ if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
+ error("sysctl getting tcpstat failed");
+ }
+ oldstat = initstat;
+}
+
+void
+fetchtcp(void)
+{
+ int name[4];
+ size_t len;
+
+ oldstat = curstat;
+ name[0] = CTL_NET;
+ name[1] = PF_INET;
+ name[2] = IPPROTO_TCP;
+ name[3] = TCPCTL_STATS;
+ len = sizeof curstat;
+
+ if (sysctl(name, 4, &curstat, &len, 0, 0) < 0)
+ return;
+}
diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c
new file mode 100644
index 000000000000..16a8a996d4fb
--- /dev/null
+++ b/usr.bin/systat/vmstat.c
@@ -0,0 +1,817 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1989, 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.
+ */
+
+
+
+/*
+ * Cursed vmstat -- from Robert Elz.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/namei.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm_param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <libutil.h>
+#include <nlist.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+static struct Info {
+ long time[CPUSTATES];
+ uint64_t v_swtch; /* context switches */
+ uint64_t v_trap; /* calls to trap */
+ uint64_t v_syscall; /* calls to syscall() */
+ uint64_t v_intr; /* device interrupts */
+ uint64_t v_soft; /* software interrupts */
+ /*
+ * Virtual memory activity.
+ */
+ uint64_t v_vm_faults; /* number of address memory faults */
+ uint64_t v_io_faults; /* page faults requiring I/O */
+ uint64_t v_cow_faults; /* number of copy-on-writes */
+ uint64_t v_zfod; /* pages zero filled on demand */
+ uint64_t v_ozfod; /* optimized zero fill pages */
+ uint64_t v_swapin; /* swap pager pageins */
+ uint64_t v_swapout; /* swap pager pageouts */
+ uint64_t v_swappgsin; /* swap pager pages paged in */
+ uint64_t v_swappgsout; /* swap pager pages paged out */
+ uint64_t v_vnodein; /* vnode pager pageins */
+ uint64_t v_vnodeout; /* vnode pager pageouts */
+ uint64_t v_vnodepgsin; /* vnode_pager pages paged in */
+ uint64_t v_vnodepgsout; /* vnode pager pages paged out */
+ uint64_t v_intrans; /* intransit blocking page faults */
+ uint64_t v_reactivated; /* number of pages reactivated by pagedaemon */
+ uint64_t v_pdwakeups; /* number of times daemon has awaken from sleep */
+ uint64_t v_pdpages; /* number of pages analyzed by daemon */
+
+ uint64_t v_dfree; /* pages freed by daemon */
+ uint64_t v_pfree; /* pages freed by exiting processes */
+ uint64_t v_tfree; /* total pages freed */
+ /*
+ * Distribution of page usages.
+ */
+ u_int v_free_count; /* number of pages free */
+ u_int v_wire_count; /* number of pages wired down */
+ u_int v_active_count; /* number of pages active */
+ u_int v_inactive_count; /* number of pages inactive */
+ u_int v_laundry_count; /* number of pages in laundry queue */
+ u_long v_kmem_map_size; /* Current kmem allocation size */
+ struct vmtotal Total;
+ struct nchstats nchstats;
+ long nchcount;
+ long *intrcnt;
+ long bufspace;
+ u_long maxvnodes;
+ long numvnodes;
+ long freevnodes;
+ int numdirtybuffers;
+} s, s1, s2, z;
+static u_long kmem_size;
+static u_int v_page_count;
+
+
+#define total s.Total
+#define nchtotal s.nchstats
+#define oldnchtotal s1.nchstats
+
+static enum state { BOOT, TIME, RUN } state = TIME;
+enum divisor { IEC = 0, SI = HN_DIVISOR_1000 };
+
+static void allocinfo(struct Info *);
+static void copyinfo(struct Info *, struct Info *);
+static float cputime(int);
+static void do_putuint64(uint64_t, int, int, int, int);
+static void getinfo(struct Info *);
+static int ucount(void);
+
+static int ncpu;
+static char buf[26];
+static time_t t;
+static double etime;
+static int nintr;
+static long *intrloc;
+static char **intrname;
+static int nextintsrow;
+
+WINDOW *
+openkre(void)
+{
+
+ return (stdscr);
+}
+
+void
+closekre(WINDOW *w)
+{
+
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+}
+
+/*
+ * These constants define where the major pieces are laid out
+ */
+#define STATROW 0 /* uses 1 row and 67 cols */
+#define STATCOL 0
+#define MEMROW 2 /* uses 4 rows and 45 cols */
+#define MEMCOL 0
+#define PAGEROW 1 /* uses 4 rows and 30 cols */
+#define PAGECOL 47
+#define INTSROW 5 /* uses all rows to bottom and 16 cols */
+#define INTSCOL 64
+#define PROCSROW 6 /* uses 3 rows and 20 cols */
+#define PROCSCOL 0
+#define GENSTATROW 7 /* uses 2 rows and 29 cols */
+#define GENSTATCOL 22
+#define VMSTATROW 5 /* uses 17 rows and 12-14 cols */
+#define VMSTATCOL 52
+#define GRAPHROW 10 /* uses 3 rows and 49-51 cols */
+#define GRAPHCOL 0
+#define VNSTATROW 13 /* uses 4 rows and 13 columns */
+#define VNSTATCOL 35
+#define NAMEIROW 14 /* uses 3 rows and 32 cols */
+#define NAMEICOL 0
+#define DISKROW 18 /* uses 5 rows and 47 cols (for 7 drives) */
+#define DISKCOL 0
+
+#define DRIVESPACE 7 /* max # for space */
+
+#define MAXDRIVES DRIVESPACE /* max # to display */
+
+int
+initkre(void)
+{
+ char *cp, *cp1, *cp2, *intrnamebuf, *nextcp;
+ int i;
+ size_t sz;
+
+ if (dsinit(MAXDRIVES) != 1)
+ return(0);
+
+ if (nintr == 0) {
+ if (sysctlbyname("hw.intrcnt", NULL, &sz, NULL, 0) == -1) {
+ error("sysctl(hw.intrcnt...) failed: %s",
+ strerror(errno));
+ return (0);
+ }
+ nintr = sz / sizeof(u_long);
+ intrloc = calloc(nintr, sizeof (long));
+ intrname = calloc(nintr, sizeof (char *));
+ intrnamebuf = sysctl_dynread("hw.intrnames", NULL);
+ if (intrnamebuf == NULL || intrname == NULL ||
+ intrloc == NULL) {
+ error("Out of memory");
+ if (intrnamebuf)
+ free(intrnamebuf);
+ if (intrname)
+ free(intrname);
+ if (intrloc)
+ free(intrloc);
+ nintr = 0;
+ return(0);
+ }
+ for (cp = intrnamebuf, i = 0; i < nintr; i++) {
+ nextcp = cp + strlen(cp) + 1;
+
+ /* Discard trailing spaces. */
+ for (cp1 = nextcp - 1; cp1 > cp && *(cp1 - 1) == ' '; )
+ *--cp1 = '\0';
+
+ /* Convert "irqN: name" to "name irqN". */
+ if (strncmp(cp, "irq", 3) == 0) {
+ cp1 = cp + 3;
+ while (isdigit((u_char)*cp1))
+ cp1++;
+ if (cp1 != cp && *cp1 == ':' &&
+ *(cp1 + 1) == ' ') {
+ sz = strlen(cp);
+ *cp1 = '\0';
+ cp1 = cp1 + 2;
+ cp2 = strdup(cp);
+ bcopy(cp1, cp, sz - (cp1 - cp) + 1);
+ if (sz <= 10 + 4) {
+ strcat(cp, " ");
+ strcat(cp, cp2 + 3);
+ }
+ free(cp2);
+ }
+ }
+
+ /*
+ * Convert "name irqN" to "name N" if the former is
+ * longer than the field width.
+ */
+ if ((cp1 = strstr(cp, "irq")) != NULL &&
+ strlen(cp) > 10)
+ bcopy(cp1 + 3, cp1, strlen(cp1 + 3) + 1);
+
+ intrname[i] = cp;
+ cp = nextcp;
+ }
+ nextintsrow = INTSROW + 2;
+ allocinfo(&s);
+ allocinfo(&s1);
+ allocinfo(&s2);
+ allocinfo(&z);
+ }
+ GETSYSCTL("vm.kmem_size", kmem_size);
+ GETSYSCTL("vm.stats.vm.v_page_count", v_page_count);
+ getinfo(&s2);
+ copyinfo(&s2, &s1);
+ return(1);
+}
+
+void
+fetchkre(void)
+{
+ time_t now;
+ struct tm *tp;
+ static int d_first = -1;
+
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+
+ time(&now);
+ tp = localtime(&now);
+ (void) strftime(buf, sizeof(buf),
+ d_first ? "%e %b %T" : "%b %e %T", tp);
+ getinfo(&s);
+}
+
+void
+labelkre(void)
+{
+ int i;
+
+ clear();
+ mvprintw(STATROW, STATCOL + 6, "users Load");
+ mvprintw(STATROW + 1, STATCOL + 3, "Mem usage: %%Phy %%Kmem");
+ mvprintw(MEMROW, MEMCOL, "Mem: REAL VIRTUAL");
+ mvprintw(MEMROW + 1, MEMCOL, " Tot Share Tot Share");
+ mvprintw(MEMROW + 2, MEMCOL, "Act");
+ mvprintw(MEMROW + 3, MEMCOL, "All");
+
+ mvprintw(MEMROW + 1, MEMCOL + 40, "Free");
+
+ mvprintw(PAGEROW, PAGECOL, " VN PAGER SWAP PAGER");
+ mvprintw(PAGEROW + 1, PAGECOL, " in out in out");
+ mvprintw(PAGEROW + 2, PAGECOL, "count");
+ mvprintw(PAGEROW + 3, PAGECOL, "pages");
+
+ mvprintw(INTSROW, INTSCOL + 1, "Interrupts");
+ mvprintw(INTSROW + 1, INTSCOL + 6, "total");
+
+ mvprintw(VMSTATROW, VMSTATCOL + 6, "ioflt");
+ mvprintw(VMSTATROW + 1, VMSTATCOL + 6, "cow");
+ mvprintw(VMSTATROW + 2, VMSTATCOL + 6, "zfod");
+ mvprintw(VMSTATROW + 3, VMSTATCOL + 6, "ozfod");
+ mvprintw(VMSTATROW + 4, VMSTATCOL + 6 - 1, "%%ozfod");
+ mvprintw(VMSTATROW + 5, VMSTATCOL + 6, "daefr");
+ mvprintw(VMSTATROW + 6, VMSTATCOL + 6, "prcfr");
+ mvprintw(VMSTATROW + 7, VMSTATCOL + 6, "totfr");
+ mvprintw(VMSTATROW + 8, VMSTATCOL + 6, "react");
+ mvprintw(VMSTATROW + 9, VMSTATCOL + 6, "pdwak");
+ mvprintw(VMSTATROW + 10, VMSTATCOL + 6, "pdpgs");
+ mvprintw(VMSTATROW + 11, VMSTATCOL + 6, "intrn");
+ mvprintw(VMSTATROW + 12, VMSTATCOL + 6, "wire");
+ mvprintw(VMSTATROW + 13, VMSTATCOL + 6, "act");
+ mvprintw(VMSTATROW + 14, VMSTATCOL + 6, "inact");
+ mvprintw(VMSTATROW + 15, VMSTATCOL + 6, "laund");
+ mvprintw(VMSTATROW + 16, VMSTATCOL + 6, "free");
+ if (LINES - 1 > VMSTATROW + 17)
+ mvprintw(VMSTATROW + 17, VMSTATCOL + 6, "buf");
+
+ mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
+
+ mvprintw(GRAPHROW, GRAPHCOL,
+ " . %%Sys . %%Intr . %%User . %%Nice . %%Idle");
+ mvprintw(PROCSROW, PROCSCOL, "Proc:");
+ mvprintw(PROCSROW + 1, PROCSCOL, " r p d s w");
+ mvprintw(GRAPHROW + 1, GRAPHCOL,
+ "| | | | | | | | | | |");
+
+ mvprintw(VNSTATROW, VNSTATCOL + 8, "dtbuf");
+ mvprintw(VNSTATROW + 1, VNSTATCOL + 8, "maxvn");
+ mvprintw(VNSTATROW + 2, VNSTATCOL + 8, "numvn");
+ mvprintw(VNSTATROW + 3, VNSTATCOL + 8, "frevn");
+
+ mvprintw(NAMEIROW, NAMEICOL, "Namei Name-cache Dir-cache");
+ mvprintw(NAMEIROW + 1, NAMEICOL,
+ " Calls hits %% hits %%");
+ dslabel(MAXDRIVES, DISKCOL, DISKROW);
+
+ for (i = 0; i < nintr; i++) {
+ if (intrloc[i] == 0)
+ continue;
+ mvprintw(intrloc[i], INTSCOL + 6, "%-10.10s", intrname[i]);
+ }
+}
+
+#define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;}
+#define Q(fld) {t=cur_dev.fld[i]; cur_dev.fld[i]-=last_dev.fld[i]; if(state==TIME) last_dev.fld[i]=t;}
+#define Y(fld) {t = s.fld; s.fld -= s1.fld; if(state == TIME) s1.fld = t;}
+#define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \
+ if(state == TIME) s1.nchstats.fld = t;}
+#define PUTRATE(fld, l, c, w) \
+do { \
+ Y(fld); \
+ sysputwuint64(wnd, l, c, w, (s.fld/etime + 0.5), 0); \
+} while (0)
+#define MAXFAIL 5
+
+static char cpuchar[CPUSTATES] = { '=' , '+', '>', '-', ' ' };
+static char cpuorder[CPUSTATES] = { CP_SYS, CP_INTR, CP_USER, CP_NICE,
+ CP_IDLE };
+
+void
+showkre(void)
+{
+ float f1, f2;
+ int psiz, inttotal;
+ int i, l, lc;
+ static int failcnt = 0;
+
+ etime = 0;
+ for(i = 0; i < CPUSTATES; i++) {
+ X(time);
+ Q(cp_time);
+ etime += s.time[i];
+ }
+ if (etime < 5.0) { /* < 5 ticks - ignore this trash */
+ if (failcnt++ >= MAXFAIL) {
+ clear();
+ mvprintw(2, 10, "The alternate system clock has died!");
+ mvprintw(3, 10, "Reverting to ``pigs'' display.");
+ move(CMDLINE, 0);
+ refresh();
+ failcnt = 0;
+ sleep(5);
+ command("pigs");
+ }
+ return;
+ }
+ failcnt = 0;
+ etime /= hertz;
+ etime /= ncpu;
+ inttotal = 0;
+ for (i = 0; i < nintr; i++) {
+ if (s.intrcnt[i] == 0)
+ continue;
+ X(intrcnt);
+ l = (int)((float)s.intrcnt[i]/etime + 0.5);
+ inttotal += l;
+ if (intrloc[i] == 0) {
+ if (nextintsrow == LINES)
+ continue;
+ intrloc[i] = nextintsrow++;
+ mvprintw(intrloc[i], INTSCOL + 6, "%-10.10s",
+ intrname[i]);
+ }
+ putint(l, intrloc[i], INTSCOL, 5);
+ }
+ putint(inttotal, INTSROW + 1, INTSCOL, 5);
+ Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss);
+ Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); Z(ncs_neghits);
+ s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits +
+ nchtotal.ncs_miss + nchtotal.ncs_long + nchtotal.ncs_neghits;
+ if (state == TIME)
+ s1.nchcount = s.nchcount;
+
+ psiz = 0;
+ f2 = 0.0;
+ for (lc = 0; lc < CPUSTATES; lc++) {
+ i = cpuorder[lc];
+ f1 = cputime(i);
+ f2 += f1;
+ l = (int) ((f2 + 1.0) / 2.0) - psiz;
+ putfloat(f1, GRAPHROW, GRAPHCOL + 10 * lc, 4, 1, 0);
+ move(GRAPHROW + 2, psiz);
+ psiz += l;
+ while (l-- > 0)
+ addch(cpuchar[lc]);
+ }
+
+ putint(ucount(), STATROW, STATCOL, 5);
+ putfloat(avenrun[0], STATROW, STATCOL + 20, 5, 2, 0);
+ putfloat(avenrun[1], STATROW, STATCOL + 26, 5, 2, 0);
+ putfloat(avenrun[2], STATROW, STATCOL + 32, 5, 2, 0);
+ mvaddstr(STATROW, STATCOL + 55, buf);
+ putfloat(100.0 * (v_page_count - total.t_free) / v_page_count,
+ STATROW + 1, STATCOL + 15, 2, 0, 1);
+ putfloat(100.0 * s.v_kmem_map_size / kmem_size,
+ STATROW + 1, STATCOL + 22, 2, 0, 1);
+
+ sysputpage(wnd, MEMROW + 2, MEMCOL + 4, 6, total.t_arm, 0);
+ sysputpage(wnd, MEMROW + 2, MEMCOL + 12, 6, total.t_armshr, 0);
+ sysputpage(wnd, MEMROW + 2, MEMCOL + 20, 6, total.t_avm, 0);
+ sysputpage(wnd, MEMROW + 2, MEMCOL + 29, 6, total.t_avmshr, 0);
+ sysputpage(wnd, MEMROW + 3, MEMCOL + 4, 6, total.t_rm, 0);
+ sysputpage(wnd, MEMROW + 3, MEMCOL + 12, 6, total.t_rmshr, 0);
+ sysputpage(wnd, MEMROW + 3, MEMCOL + 20, 6, total.t_vm, 0);
+ sysputpage(wnd, MEMROW + 3, MEMCOL + 29, 6, total.t_vmshr, 0);
+ sysputpage(wnd, MEMROW + 2, MEMCOL + 38, 6, total.t_free, 0);
+ putint(total.t_rq - 1, PROCSROW + 2, PROCSCOL, 3);
+ putint(total.t_pw, PROCSROW + 2, PROCSCOL + 4, 3);
+ putint(total.t_dw, PROCSROW + 2, PROCSCOL + 8, 3);
+ putint(total.t_sl, PROCSROW + 2, PROCSCOL + 12, 4);
+ putint(total.t_sw, PROCSROW + 2, PROCSCOL + 17, 3);
+ PUTRATE(v_io_faults, VMSTATROW, VMSTATCOL, 5);
+ PUTRATE(v_cow_faults, VMSTATROW + 1, VMSTATCOL, 5);
+ PUTRATE(v_zfod, VMSTATROW + 2, VMSTATCOL, 5);
+ PUTRATE(v_ozfod, VMSTATROW + 3, VMSTATCOL, 5);
+ putint(s.v_zfod != 0 ? (int)(s.v_ozfod * 100.0 / s.v_zfod) : 0,
+ VMSTATROW + 4, VMSTATCOL, 5);
+ PUTRATE(v_dfree, VMSTATROW + 5, VMSTATCOL, 5);
+ PUTRATE(v_pfree, VMSTATROW + 6, VMSTATCOL, 5);
+ PUTRATE(v_tfree, VMSTATROW + 7, VMSTATCOL, 5);
+ PUTRATE(v_reactivated, VMSTATROW + 8, VMSTATCOL, 5);
+ PUTRATE(v_pdwakeups, VMSTATROW + 9, VMSTATCOL, 5);
+ PUTRATE(v_pdpages, VMSTATROW + 10, VMSTATCOL, 5);
+ PUTRATE(v_intrans, VMSTATROW + 11, VMSTATCOL, 5);
+ sysputpage(wnd, VMSTATROW + 12, VMSTATCOL, 5, s.v_wire_count, 0);
+ sysputpage(wnd, VMSTATROW + 13, VMSTATCOL, 5, s.v_active_count, 0);
+ sysputpage(wnd, VMSTATROW + 14, VMSTATCOL, 5, s.v_inactive_count, 0);
+ sysputpage(wnd, VMSTATROW + 15, VMSTATCOL, 5, s.v_laundry_count, 0);
+ sysputpage(wnd, VMSTATROW + 16, VMSTATCOL, 5, s.v_free_count, 0);
+ if (LINES - 1 > VMSTATROW + 17)
+ sysputuint64(wnd, VMSTATROW + 17, VMSTATCOL, 5, s.bufspace, 0);
+ PUTRATE(v_vnodein, PAGEROW + 2, PAGECOL + 6, 5);
+ PUTRATE(v_vnodeout, PAGEROW + 2, PAGECOL + 12, 5);
+ PUTRATE(v_swapin, PAGEROW + 2, PAGECOL + 19, 5);
+ PUTRATE(v_swapout, PAGEROW + 2, PAGECOL + 25, 5);
+ PUTRATE(v_vnodepgsin, PAGEROW + 3, PAGECOL + 6, 5);
+ PUTRATE(v_vnodepgsout, PAGEROW + 3, PAGECOL + 12, 5);
+ PUTRATE(v_swappgsin, PAGEROW + 3, PAGECOL + 19, 5);
+ PUTRATE(v_swappgsout, PAGEROW + 3, PAGECOL + 25, 5);
+ PUTRATE(v_swtch, GENSTATROW + 1, GENSTATCOL, 4);
+ PUTRATE(v_trap, GENSTATROW + 1, GENSTATCOL + 5, 4);
+ PUTRATE(v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 4);
+ PUTRATE(v_intr, GENSTATROW + 1, GENSTATCOL + 15, 4);
+ PUTRATE(v_soft, GENSTATROW + 1, GENSTATCOL + 20, 4);
+ PUTRATE(v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 4);
+ switch(state) {
+ case TIME:
+ dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, &last_dev);
+ break;
+ case RUN:
+ dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, &run_dev);
+ break;
+ case BOOT:
+ dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, NULL);
+ break;
+ }
+ putint(s.numdirtybuffers, VNSTATROW, VNSTATCOL, 7);
+ putint(s.maxvnodes, VNSTATROW + 1, VNSTATCOL, 7);
+ putint(s.numvnodes, VNSTATROW + 2, VNSTATCOL, 7);
+ putint(s.freevnodes, VNSTATROW + 3, VNSTATCOL, 7);
+ putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 8);
+ putint((nchtotal.ncs_goodhits + nchtotal.ncs_neghits),
+ NAMEIROW + 2, NAMEICOL + 9, 7);
+#define nz(x) ((x) ? (x) : 1)
+ putfloat((nchtotal.ncs_goodhits+nchtotal.ncs_neghits) *
+ 100.0 / nz(s.nchcount),
+ NAMEIROW + 2, NAMEICOL + 17, 3, 0, 1);
+ putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 21, 7);
+ putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount),
+ NAMEIROW + 2, NAMEICOL + 29, 3, 0, 1);
+#undef nz
+}
+
+int
+cmdkre(const char *cmd, const char *args)
+{
+ int retval;
+
+ if (prefix(cmd, "run")) {
+ retval = 1;
+ copyinfo(&s2, &s1);
+ switch (devstat_getdevs(NULL, &run_dev)) {
+ case -1:
+ errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ num_devices = run_dev.dinfo->numdevs;
+ generation = run_dev.dinfo->generation;
+ retval = dscmd("refresh", NULL, MAXDRIVES, &cur_dev);
+ if (retval == 2)
+ labelkre();
+ break;
+ default:
+ break;
+ }
+ state = RUN;
+ return (retval);
+ }
+ if (prefix(cmd, "boot")) {
+ state = BOOT;
+ copyinfo(&z, &s1);
+ return (1);
+ }
+ if (prefix(cmd, "time")) {
+ state = TIME;
+ return (1);
+ }
+ if (prefix(cmd, "zero")) {
+ retval = 1;
+ if (state == RUN) {
+ getinfo(&s1);
+ switch (devstat_getdevs(NULL, &run_dev)) {
+ case -1:
+ errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ num_devices = run_dev.dinfo->numdevs;
+ generation = run_dev.dinfo->generation;
+ retval = dscmd("refresh",NULL, MAXDRIVES, &cur_dev);
+ if (retval == 2)
+ labelkre();
+ break;
+ default:
+ break;
+ }
+ }
+ return (retval);
+ }
+ retval = dscmd(cmd, args, MAXDRIVES, &cur_dev);
+
+ if (retval == 2)
+ labelkre();
+
+ return(retval);
+}
+
+/* calculate number of users on the system */
+static int
+ucount(void)
+{
+ int nusers = 0;
+ struct utmpx *ut;
+
+ setutxent();
+ while ((ut = getutxent()) != NULL)
+ if (ut->ut_type == USER_PROCESS)
+ nusers++;
+ endutxent();
+
+ return (nusers);
+}
+
+static float
+cputime(int indx)
+{
+ double lt;
+ int i;
+
+ lt = 0;
+ for (i = 0; i < CPUSTATES; i++)
+ lt += s.time[i];
+ if (lt == 0.0)
+ lt = 1.0;
+ return (s.time[indx] * 100.0 / lt);
+}
+
+void
+putint(int n, int l, int lc, int w)
+{
+
+ do_putuint64(n, l, lc, w, SI);
+}
+
+static void
+do_putuint64(uint64_t n, int l, int lc, int w, int div)
+{
+ int snr;
+ char b[128];
+ char lbuf[128];
+
+ move(l, lc);
+#ifdef DEBUG
+ while (w-- > 0)
+ addch('*');
+ return;
+#endif
+ if (n == 0) {
+ while (w-- > 0)
+ addch(' ');
+ return;
+ }
+ snr = snprintf(b, sizeof(b), "%*ju", w, (uintmax_t)n);
+ if (snr != w) {
+ humanize_number(lbuf, w, n, "", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL | div);
+ snr = snprintf(b, sizeof(b), "%*s", w, lbuf);
+ }
+ if (snr != w) {
+ while (w-- > 0)
+ addch('*');
+ return;
+ }
+ addstr(b);
+}
+
+void
+putfloat(double f, int l, int lc, int w, int d, int nz)
+{
+ int snr;
+ char b[128];
+
+ move(l, lc);
+#ifdef DEBUG
+ while (--w >= 0)
+ addch('*');
+ return;
+#endif
+ if (nz && f == 0.0) {
+ while (--w >= 0)
+ addch(' ');
+ return;
+ }
+ snr = snprintf(b, sizeof(b), "%*.*f", w, d, f);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0f", w, f);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0fk", w - 1, f / 1000);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0fM", w - 1, f / 1000000);
+ if (snr != w) {
+ while (--w >= 0)
+ addch('*');
+ return;
+ }
+ addstr(b);
+}
+
+void
+putlongdouble(long double f, int l, int lc, int w, int d, int nz)
+{
+ int snr;
+ char b[128];
+
+ move(l, lc);
+#ifdef DEBUG
+ while (--w >= 0)
+ addch('*');
+ return;
+#endif
+ if (nz && f == 0.0) {
+ while (--w >= 0)
+ addch(' ');
+ return;
+ }
+ snr = snprintf(b, sizeof(b), "%*.*Lf", w, d, f);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0Lf", w, f);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0Lfk", w - 1, f / 1000);
+ if (snr != w)
+ snr = snprintf(b, sizeof(b), "%*.0LfM", w - 1, f / 1000000);
+ if (snr != w) {
+ while (--w >= 0)
+ addch('*');
+ return;
+ }
+ addstr(b);
+}
+
+static void
+getinfo(struct Info *ls)
+{
+ struct devinfo *tmp_dinfo;
+ size_t size;
+ int mib[2];
+
+ GETSYSCTL("kern.cp_time", ls->time);
+ GETSYSCTL("kern.cp_time", cur_dev.cp_time);
+ GETSYSCTL("vm.stats.sys.v_swtch", ls->v_swtch);
+ GETSYSCTL("vm.stats.sys.v_trap", ls->v_trap);
+ GETSYSCTL("vm.stats.sys.v_syscall", ls->v_syscall);
+ GETSYSCTL("vm.stats.sys.v_intr", ls->v_intr);
+ GETSYSCTL("vm.stats.sys.v_soft", ls->v_soft);
+ GETSYSCTL("vm.stats.vm.v_vm_faults", ls->v_vm_faults);
+ GETSYSCTL("vm.stats.vm.v_io_faults", ls->v_io_faults);
+ GETSYSCTL("vm.stats.vm.v_cow_faults", ls->v_cow_faults);
+ GETSYSCTL("vm.stats.vm.v_zfod", ls->v_zfod);
+ GETSYSCTL("vm.stats.vm.v_ozfod", ls->v_ozfod);
+ GETSYSCTL("vm.stats.vm.v_swapin", ls->v_swapin);
+ GETSYSCTL("vm.stats.vm.v_swapout", ls->v_swapout);
+ GETSYSCTL("vm.stats.vm.v_swappgsin", ls->v_swappgsin);
+ GETSYSCTL("vm.stats.vm.v_swappgsout", ls->v_swappgsout);
+ GETSYSCTL("vm.stats.vm.v_vnodein", ls->v_vnodein);
+ GETSYSCTL("vm.stats.vm.v_vnodeout", ls->v_vnodeout);
+ GETSYSCTL("vm.stats.vm.v_vnodepgsin", ls->v_vnodepgsin);
+ GETSYSCTL("vm.stats.vm.v_vnodepgsout", ls->v_vnodepgsout);
+ GETSYSCTL("vm.stats.vm.v_intrans", ls->v_intrans);
+ GETSYSCTL("vm.stats.vm.v_reactivated", ls->v_reactivated);
+ GETSYSCTL("vm.stats.vm.v_pdwakeups", ls->v_pdwakeups);
+ GETSYSCTL("vm.stats.vm.v_pdpages", ls->v_pdpages);
+ GETSYSCTL("vm.stats.vm.v_dfree", ls->v_dfree);
+ GETSYSCTL("vm.stats.vm.v_pfree", ls->v_pfree);
+ GETSYSCTL("vm.stats.vm.v_tfree", ls->v_tfree);
+ GETSYSCTL("vm.stats.vm.v_free_count", ls->v_free_count);
+ GETSYSCTL("vm.stats.vm.v_wire_count", ls->v_wire_count);
+ GETSYSCTL("vm.stats.vm.v_active_count", ls->v_active_count);
+ GETSYSCTL("vm.stats.vm.v_inactive_count", ls->v_inactive_count);
+ GETSYSCTL("vm.stats.vm.v_laundry_count", ls->v_laundry_count);
+ GETSYSCTL("vfs.bufspace", ls->bufspace);
+ GETSYSCTL("kern.maxvnodes", ls->maxvnodes);
+ GETSYSCTL("vfs.numvnodes", ls->numvnodes);
+ GETSYSCTL("vfs.freevnodes", ls->freevnodes);
+ GETSYSCTL("vfs.cache.nchstats", ls->nchstats);
+ GETSYSCTL("vfs.numdirtybuffers", ls->numdirtybuffers);
+ GETSYSCTL("vm.kmem_map_size", ls->v_kmem_map_size);
+ getsysctl("hw.intrcnt", ls->intrcnt, nintr * sizeof(u_long));
+
+ size = sizeof(ls->Total);
+ mib[0] = CTL_VM;
+ mib[1] = VM_TOTAL;
+ if (sysctl(mib, 2, &ls->Total, &size, NULL, 0) < 0) {
+ error("Can't get kernel info: %s\n", strerror(errno));
+ bzero(&ls->Total, sizeof(ls->Total));
+ }
+ size = sizeof(ncpu);
+ if (sysctlbyname("hw.ncpu", &ncpu, &size, NULL, 0) < 0 ||
+ size != sizeof(ncpu))
+ ncpu = 1;
+
+ tmp_dinfo = last_dev.dinfo;
+ last_dev.dinfo = cur_dev.dinfo;
+ cur_dev.dinfo = tmp_dinfo;
+
+ last_dev.snap_time = cur_dev.snap_time;
+ dsgetinfo(&cur_dev);
+}
+
+static void
+allocinfo(struct Info *ls)
+{
+
+ ls->intrcnt = (long *) calloc(nintr, sizeof(long));
+ if (ls->intrcnt == NULL)
+ errx(2, "out of memory");
+}
+
+static void
+copyinfo(struct Info *from, struct Info *to)
+{
+ long *intrcnt;
+
+ /*
+ * time, wds, seek, and xfer are malloc'd so we have to
+ * save the pointers before the structure copy and then
+ * copy by hand.
+ */
+ intrcnt = to->intrcnt;
+ *to = *from;
+
+ bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int));
+}
diff --git a/usr.bin/systat/zarc.c b/usr.bin/systat/zarc.c
new file mode 100644
index 000000000000..5f9cb8cc1130
--- /dev/null
+++ b/usr.bin/systat/zarc.c
@@ -0,0 +1,236 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2014 - 2017, 2019 Yoshihiro Ota
+ *
+ * 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 AUTHOR 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 AUTHOR 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/sysctl.h>
+
+#include <inttypes.h>
+#include <string.h>
+#include <err.h>
+#include <libutil.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "devs.h"
+
+struct zfield {
+ uint64_t arcstats;
+ uint64_t arcstats_demand_data;
+ uint64_t arcstats_demand_metadata;
+ uint64_t arcstats_prefetch_data;
+ uint64_t arcstats_prefetch_metadata;
+ uint64_t zfetchstats;
+ uint64_t arcstats_l2;
+};
+
+static struct zarcstats {
+ struct zfield hits;
+ struct zfield misses;
+} curstat, initstat, oldstat;
+
+struct zarcrates {
+ struct zfield current;
+ struct zfield total;
+};
+
+static void
+getinfo(struct zarcstats *ls);
+
+WINDOW *
+openzarc(void)
+{
+
+ return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0));
+}
+
+void
+closezarc(WINDOW *w)
+{
+
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+void
+labelzarc(void)
+{
+ int row = 1;
+
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+ mvwprintw(wnd, 0, 31+1, "%4.4s %6.6s %6.6s | Total %4.4s %6.6s %6.6s",
+ "Rate", "Hits", "Misses", "Rate", "Hits", "Misses");
+#define L(str) mvwprintw(wnd, row++, 5, \
+ "%-26.26s: %% | %%", #str)
+ L(arcstats);
+ L(arcstats.demand_data);
+ L(arcstats.demand_metadata);
+ L(arcstats.prefetch_data);
+ L(arcstats.prefetch_metadata);
+ L(zfetchstats);
+ L(arcstats.l2);
+#undef L
+ dslabel(12, 0, 18);
+}
+
+static int
+calc_rate(uint64_t hits, uint64_t misses)
+{
+ if(hits)
+ return 100 * hits / (hits + misses);
+ else
+ return 0;
+}
+
+static void
+domode(struct zarcstats *delta, struct zarcrates *rate)
+{
+#define DO(stat) \
+ delta->hits.stat = (curstat.hits.stat - oldstat.hits.stat); \
+ delta->misses.stat = (curstat.misses.stat - oldstat.misses.stat); \
+ rate->current.stat = calc_rate(delta->hits.stat, delta->misses.stat); \
+ rate->total.stat = calc_rate(curstat.hits.stat, curstat.misses.stat)
+ DO(arcstats);
+ DO(arcstats_demand_data);
+ DO(arcstats_demand_metadata);
+ DO(arcstats_prefetch_data);
+ DO(arcstats_prefetch_metadata);
+ DO(zfetchstats);
+ DO(arcstats_l2);
+ DO(arcstats);
+ DO(arcstats_demand_data);
+ DO(arcstats_demand_metadata);
+ DO(arcstats_prefetch_data);
+ DO(arcstats_prefetch_metadata);
+ DO(zfetchstats);
+ DO(arcstats_l2);
+#undef DO
+}
+
+void
+showzarc(void)
+{
+ int row = 1;
+ struct zarcstats delta = {};
+ struct zarcrates rate = {};
+
+ domode(&delta, &rate);
+
+#define DO(stat, col, width) \
+ sysputuint64(wnd, row, col, width, stat, HN_DIVISOR_1000)
+#define RATES(stat) mvwprintw(wnd, row, 31+1, "%3"PRIu64, rate.current.stat);\
+ mvwprintw(wnd, row, 31+1+5+7+7+8, "%3"PRIu64, rate.total.stat)
+#define HITS(stat) DO(delta.hits.stat, 31+1+5, 6); \
+ DO(curstat.hits.stat, 31+1+5+7+7+8+5, 6)
+#define MISSES(stat) DO(delta.misses.stat, 31+1+5+7, 6); \
+ DO(curstat.misses.stat, 31+1+5+7+7+8+5+7, 6)
+#define E(stat) RATES(stat); HITS(stat); MISSES(stat); ++row
+ E(arcstats);
+ E(arcstats_demand_data);
+ E(arcstats_demand_metadata);
+ E(arcstats_prefetch_data);
+ E(arcstats_prefetch_metadata);
+ E(zfetchstats);
+ E(arcstats_l2);
+#undef DO
+#undef E
+#undef MISSES
+#undef HITS
+#undef RATES
+ dsshow(12, 0, 18, &cur_dev, &last_dev);
+}
+
+int
+initzarc(void)
+{
+ dsinit(12);
+ getinfo(&initstat);
+ curstat = oldstat = initstat;
+
+ return 1;
+}
+
+void
+resetzarc(void)
+{
+
+ initzarc();
+}
+
+static void
+getinfo(struct zarcstats *ls)
+{
+ struct devinfo *tmp_dinfo;
+
+ tmp_dinfo = last_dev.dinfo;
+ last_dev.dinfo = cur_dev.dinfo;
+ cur_dev.dinfo = tmp_dinfo;
+
+ last_dev.snap_time = cur_dev.snap_time;
+ dsgetinfo(&cur_dev);
+
+ size_t size = sizeof(ls->hits.arcstats);
+ if (sysctlbyname("kstat.zfs.misc.arcstats.hits",
+ &ls->hits.arcstats, &size, NULL, 0) != 0)
+ return;
+ GETSYSCTL("kstat.zfs.misc.arcstats.misses",
+ ls->misses.arcstats);
+ GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_hits",
+ ls->hits.arcstats_demand_data);
+ GETSYSCTL("kstat.zfs.misc.arcstats.demand_data_misses",
+ ls->misses.arcstats_demand_data);
+ GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_hits",
+ ls->hits.arcstats_demand_metadata);
+ GETSYSCTL("kstat.zfs.misc.arcstats.demand_metadata_misses",
+ ls->misses.arcstats_demand_metadata);
+ GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_hits",
+ ls->hits.arcstats_prefetch_data);
+ GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_data_misses",
+ ls->misses.arcstats_prefetch_data);
+ GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_hits",
+ ls->hits.arcstats_prefetch_metadata);
+ GETSYSCTL("kstat.zfs.misc.arcstats.prefetch_metadata_misses",
+ ls->misses.arcstats_prefetch_metadata);
+ GETSYSCTL("kstat.zfs.misc.zfetchstats.hits",
+ ls->hits.zfetchstats);
+ GETSYSCTL("kstat.zfs.misc.zfetchstats.misses",
+ ls->misses.zfetchstats);
+ GETSYSCTL("kstat.zfs.misc.arcstats.l2_hits",
+ ls->hits.arcstats_l2);
+ GETSYSCTL("kstat.zfs.misc.arcstats.l2_misses",
+ ls->misses.arcstats_l2);
+}
+
+void
+fetchzarc(void)
+{
+
+ oldstat = curstat;
+ getinfo(&curstat);
+}
diff --git a/usr.bin/tabs/Makefile b/usr.bin/tabs/Makefile
new file mode 100644
index 000000000000..b80b201431c0
--- /dev/null
+++ b/usr.bin/tabs/Makefile
@@ -0,0 +1,5 @@
+PROG= tabs
+
+LIBADD= tinfow
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tabs/Makefile.depend b/usr.bin/tabs/Makefile.depend
new file mode 100644
index 000000000000..dd06faaab7bf
--- /dev/null
+++ b/usr.bin/tabs/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tabs/tabs.1 b/usr.bin/tabs/tabs.1
new file mode 100644
index 000000000000..567b64519bcc
--- /dev/null
+++ b/usr.bin/tabs/tabs.1
@@ -0,0 +1,163 @@
+.\" Copyright (c) 2002 Tim J. Robbins.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 September 9, 2021
+.Dt TABS 1
+.Os
+.Sh NAME
+.Nm tabs
+.Nd set terminal tabs
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ar n | Fl a | a2 | c | c2 | c3 | f | p | s | u
+.Op Cm +m Ns Op Ar n
+.Op Fl T Ar type
+.Nm
+.Op Fl T Ar type
+.Op Cm + Ns Op Ar n
+.Ar n1 Ns Op Ns , Ns Ar n2 , Ns ...
+.Sh DESCRIPTION
+The
+.Nm
+utility displays a series of characters that clear the hardware terminal
+tab settings then initialises tab stops at specified positions, and
+optionally adjusts the margin.
+.Pp
+In the first synopsis form, the tab stops set depend on the command line
+options used, and may be one of the predefined formats or at regular
+intervals.
+.Pp
+In the second synopsis form, tab stops are set at positions
+.Ar n1 , n2 ,
+etc.
+If a position is preceded by a
+.Ql + ,
+it is relative to the previous position set.
+No more than 20 positions may be specified.
+.Pp
+If no tab stops are specified, the
+.Dq standard
+.Ux
+tab width of 8 is used.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl Ar n
+Set a tab stop every
+.Ar n
+columns.
+If
+.Ar n
+is 0, the tab stops are cleared but no new ones are set.
+.It Fl a
+Assembler format (columns 1, 10, 16, 36, 72).
+.It Fl a2
+Assembler format (columns 1, 10, 16, 40, 72).
+.It Fl c
+.Tn COBOL
+normal format (columns 1, 8, 12, 16, 20, 55)
+.It Fl c2
+.Tn COBOL
+compact format (columns 1, 6, 10, 14, 49)
+.It Fl c3
+.Tn COBOL
+compact format (columns 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46,
+50, 54, 58, 62, 67).
+.It Fl f
+.Tn FORTRAN
+format (columns 1, 7, 11, 15, 19, 23).
+.It Fl p
+.Tn PL/1
+format (columns 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53,
+57, 61).
+.It Fl s
+.Tn SNOBOL
+format (columns 1, 10, 55).
+.It Fl u
+Assembler format (columns 1, 12, 20, 44).
+.It Xo
+.Cm +m Ns Op Ar n ,
+.Cm + Ns Op Ar n
+.Xc
+Set an
+.Ar n
+character left margin, or 10 if
+.Ar n
+is omitted.
+.It Fl T Ar type
+Output escape sequence for the terminal type
+.Ar type .
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_CTYPE
+and
+.Ev TERM
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Pp
+The
+.Fl T
+option overrides the setting of the
+.Ev TERM
+environment variable.
+If neither
+.Ev TERM
+nor the
+.Fl T
+option are present,
+.Nm
+will fail.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr expand 1 ,
+.Xr stty 1 ,
+.Xr tput 1 ,
+.Xr unexpand 1 ,
+.Xr termcap 5
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+.Pa /etc/tabs
+appeared in
+.At v1
+which set tabs every 8 on Teletype model 37 and compatible printing terminals
+when printed.
+A
+.Nm
+utility that worked on many terminals appeared in PWB UNIX.
+This implementation was introduced in
+.Fx 5.0 .
+.Sh BUGS
+The current
+.Xr termcap 5
+database does not define the
+.Ql ML
+(set left soft margin) capability for any terminals.
diff --git a/usr.bin/tabs/tabs.c b/usr.bin/tabs/tabs.c
new file mode 100644
index 000000000000..0cc942565ab3
--- /dev/null
+++ b/usr.bin/tabs/tabs.c
@@ -0,0 +1,236 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * tabs -- set terminal tabs
+ *
+ * This utility displays a series of characters that clears the terminal
+ * hardware tab settings, then initialises them to specified values,
+ * and optionally sets a soft margin.
+ */
+
+#include <sys/types.h>
+#include <sys/tty.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <term.h>
+#include <unistd.h>
+
+/* Maximum number of tab stops allowed in table. */
+#define NSTOPS 20
+
+#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
+
+/* Predefined formats, taken from IEEE Std 1003.1-2001. */
+static const struct {
+ const char *name; /* Format name used on cmd. line */
+ long stops[NSTOPS]; /* Column positions */
+} formats[] = {
+ { "a", { 1, 10, 16, 36, 72 } },
+ { "a2", { 1, 10, 16, 40, 72 } },
+ { "c", { 1, 8, 12, 16, 20, 55 } },
+ { "c2", { 1, 6, 10, 14, 49 } },
+ { "c3", { 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58,
+ 62, 67 } },
+ { "f", { 1, 7, 11, 15, 19, 23 } },
+ { "p", { 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57,
+ 61 } },
+ { "s", { 1, 10, 55 } },
+ { "u", { 1, 12, 20, 44 } }
+};
+
+static void gettabs(char *, long *, long *);
+static int ttywidth(void);
+static void usage(void);
+
+int
+main(int argc __unused, char *argv[])
+{
+ long cols, i, inc, j, margin, nstops, stops[NSTOPS];
+ const char *cr, *ct, *st, *ML;
+ char area[1024], *ap, *arg, *end;
+
+ setlocale(LC_ALL, "");
+
+ inc = 8;
+ margin = 0;
+ nstops = -1;
+ while ((arg = *++argv) != NULL && (*arg == '-' || *arg == '+')) {
+ if (*arg == '+') {
+ /* +m[n] or +[n] */
+ if (*++arg == 'm')
+ arg++;
+ if (*arg != '\0') {
+ errno = 0;
+ margin = strtol(arg, &end, 10);
+ if (errno != 0 || *end != '\0' || margin < 0)
+ errx(1, "%s: invalid margin width",
+ arg);
+ } else
+ margin = 10;
+ } else if (isdigit(arg[1])) {
+ /* -n */
+ errno = 0;
+ inc = strtol(arg + 1, &end, 10);
+ if (errno != 0 || *end != '\0' || inc < 0)
+ errx(1, "%s: invalid increment", arg + 1);
+ } else if (arg[1] == 'T') {
+ /* -Ttype or -T type */
+ if (arg[2] != '\0')
+ setenv("TERM", arg + 2, 1);
+ else {
+ if ((arg = *++argv) == NULL)
+ usage();
+ setenv("TERM", arg, 1);
+ }
+ } else if (arg[1] == '-') {
+ arg = *++argv;
+ break;
+ } else {
+ /* Predefined format */
+ for (i = 0; i < (int)NELEMS(formats); i++)
+ if (strcmp(formats[i].name, arg + 1) == 0)
+ break;
+ if (i == NELEMS(formats))
+ usage();
+ for (j = nstops = 0; j < NSTOPS &&
+ formats[i].stops[j] != 0; j++)
+ stops[nstops++] = formats[i].stops[j];
+ }
+ }
+
+ if (arg != NULL) {
+ if (nstops != -1)
+ usage();
+ gettabs(arg, stops, &nstops);
+ }
+
+ /* Initialise terminal, get the strings we need */
+ setupterm(NULL, 1, NULL);
+ ap = area;
+ if ((ct = tgetstr("ct", &ap)) == NULL)
+ errx(1, "terminal cannot clear tabs");
+ if ((st = tgetstr("st", &ap)) == NULL)
+ errx(1, "terminal cannot set tabs");
+ if ((cr = tgetstr("cr", &ap)) == NULL)
+ cr = "\r";
+ ML = tgetstr("ML", &ap);
+ cols = ttywidth();
+
+ /* Clear all tabs. */
+ putp(cr);
+ putp(ct);
+
+ /*
+ * Set soft margin.
+ * XXX Does this actually work?
+ */
+ if (ML != NULL) {
+ printf("%*s", (int)margin, "");
+ putp(ML);
+ } else if (margin != 0)
+ warnx("terminal cannot set left margin");
+
+ /* Optionally output new tab stops. */
+ if (nstops >= 0) {
+ printf("%*s", (int)stops[0] - 1, "");
+ putp(st);
+ for (i = 1; i < nstops; i++) {
+ printf("%*s", (int)(stops[i] - stops[i - 1]), "");
+ putp(st);
+ }
+ } else if (inc > 0) {
+ for (i = 0; i < cols / inc; i++) {
+ putp(st);
+ printf("%*s", (int)inc, "");
+ }
+ putp(st);
+ }
+ putp(cr);
+
+ exit(0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+"usage: tabs [-n|-a|-a2|-c|-c2|-c3|-f|-p|-s|-u] [+m[n]] [-T type]\n");
+ fprintf(stderr,
+" tabs [-T type] [+[n]] n1,[n2,...]\n");
+ exit(1);
+}
+
+static void
+gettabs(char *arg, long stops[], long *nstops)
+{
+ char *tok, *end;
+ long last, stop;
+
+ for (last = *nstops = 0, tok = strtok(arg, ","); tok != NULL;
+ tok = strtok(NULL, ",")) {
+ if (*nstops >= NSTOPS)
+ errx(1, "too many tab stops (limit %d)", NSTOPS);
+ errno = 0;
+ stop = strtol(tok, &end, 10);
+ if (errno != 0 || *end != '\0' || stop <= 0)
+ errx(1, "%s: invalid tab stop", tok);
+ if (*tok == '+') {
+ if (tok == arg)
+ errx(1, "%s: first tab may not be relative",
+ tok);
+ stop += last;
+ }
+ if (last > stop)
+ errx(1, "cannot go backwards");
+ last = stops[(*nstops)++] = stop;
+ }
+}
+
+static int
+ttywidth(void)
+{
+ struct winsize ws;
+ int width;
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
+ width = ws.ws_col;
+ else if ((width = tgetnum("co")) == 0) {
+ width = 80;
+ warnx("cannot find terminal width; defaulted to %d", width);
+ }
+
+ return (width);
+}
diff --git a/usr.bin/tail/Makefile b/usr.bin/tail/Makefile
new file mode 100644
index 000000000000..47c21f7f9318
--- /dev/null
+++ b/usr.bin/tail/Makefile
@@ -0,0 +1,16 @@
+.include <src.opts.mk>
+
+PROG= tail
+SRCS= forward.c misc.c read.c reverse.c tail.c
+LIBADD= util
+
+.if ${MK_CASPER} != "no" && !defined(RESCUE)
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tail/Makefile.depend b/usr.bin/tail/Makefile.depend
new file mode 100644
index 000000000000..7354b9b88616
--- /dev/null
+++ b/usr.bin/tail/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tail/Makefile.depend.options b/usr.bin/tail/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/tail/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/tail/extern.h b/usr.bin/tail/extern.h
new file mode 100644
index 000000000000..f1d1f8c37291
--- /dev/null
+++ b/usr.bin/tail/extern.h
@@ -0,0 +1,77 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#define WR(p, size) do { \
+ ssize_t res; \
+ res = write(STDOUT_FILENO, p, size); \
+ if (res != (ssize_t)size) { \
+ if (res == -1) \
+ oerr(); \
+ else \
+ errx(1, "stdout"); \
+ } \
+} while (0)
+
+#define TAILMAPLEN (4<<20)
+
+struct mapinfo {
+ off_t mapoff;
+ off_t maxoff;
+ size_t maplen;
+ char *start;
+ int fd;
+};
+
+struct file_info {
+ FILE *fp;
+ const char *file_name;
+ struct stat st;
+};
+
+typedef struct file_info file_info_t;
+
+enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
+
+void follow(file_info_t *, enum STYLE, off_t);
+void forward(FILE *, const char *, enum STYLE, off_t, struct stat *);
+void reverse(FILE *, const char *, enum STYLE, off_t, struct stat *);
+
+int bytes(FILE *, const char *, off_t);
+int lines(FILE *, const char *, off_t);
+
+void ierr(const char *);
+void oerr(void);
+int mapprint(struct mapinfo *, off_t, off_t);
+int maparound(struct mapinfo *, off_t);
+void printfn(const char *, int);
+
+extern int Fflag, fflag, qflag, rflag, rval, no_files, vflag;
+extern fileargs_t *fa;
diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c
new file mode 100644
index 000000000000..6d9db94a827f
--- /dev/null
+++ b/usr.bin/tail/forward.c
@@ -0,0 +1,433 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Edward Sze-Tyan Wang.
+ *
+ * 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>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/event.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#include "extern.h"
+
+static void rlines(FILE *, const char *fn, off_t, struct stat *);
+static int show(file_info_t *);
+static void set_events(file_info_t *files);
+
+/* defines for inner loop actions */
+#define USE_SLEEP 0
+#define USE_KQUEUE 1
+#define ADD_EVENTS 2
+
+static struct kevent *ev;
+static int action = USE_SLEEP;
+static int kq;
+
+static const file_info_t *last;
+
+/*
+ * forward -- display the file, from an offset, forward.
+ *
+ * There are eight separate cases for this -- regular and non-regular
+ * files, by bytes or lines and from the beginning or end of the file.
+ *
+ * FBYTES byte offset from the beginning of the file
+ * REG seek
+ * NOREG read, counting bytes
+ *
+ * FLINES line offset from the beginning of the file
+ * REG read, counting lines
+ * NOREG read, counting lines
+ *
+ * RBYTES byte offset from the end of the file
+ * REG seek
+ * NOREG cyclically read characters into a wrap-around buffer
+ *
+ * RLINES
+ * REG mmap the file and step back until reach the correct offset.
+ * NOREG cyclically read lines into a wrap-around array of buffers
+ */
+void
+forward(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
+{
+ int ch;
+
+ switch(style) {
+ case FBYTES:
+ if (off == 0)
+ break;
+ if (S_ISREG(sbp->st_mode) && sbp->st_size > 0) {
+ if (sbp->st_size < off)
+ off = sbp->st_size;
+ if (fseeko(fp, off, SEEK_SET) == -1) {
+ ierr(fn);
+ return;
+ }
+ } else while (off--)
+ if ((ch = getc(fp)) == EOF) {
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ break;
+ }
+ break;
+ case FLINES:
+ if (off == 0)
+ break;
+ for (;;) {
+ if ((ch = getc(fp)) == EOF) {
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ break;
+ }
+ if (ch == '\n' && !--off)
+ break;
+ }
+ break;
+ case RBYTES:
+ if (S_ISREG(sbp->st_mode) && sbp->st_size > 0) {
+ if (sbp->st_size >= off &&
+ fseeko(fp, -off, SEEK_END) == -1) {
+ ierr(fn);
+ return;
+ }
+ } else if (off == 0) {
+ while (getc(fp) != EOF);
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ } else
+ if (bytes(fp, fn, off))
+ return;
+ break;
+ case RLINES:
+ if (S_ISREG(sbp->st_mode) && sbp->st_size > 0)
+ if (!off) {
+ if (fseeko(fp, (off_t)0, SEEK_END) == -1) {
+ ierr(fn);
+ return;
+ }
+ } else
+ rlines(fp, fn, off, sbp);
+ else if (off == 0) {
+ while (getc(fp) != EOF);
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ } else
+ if (lines(fp, fn, off))
+ return;
+ break;
+ default:
+ break;
+ }
+
+ while ((ch = getc(fp)) != EOF)
+ if (putchar(ch) == EOF)
+ oerr();
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ (void)fflush(stdout);
+}
+
+/*
+ * rlines -- display the last offset lines of the file.
+ */
+static void
+rlines(FILE *fp, const char *fn, off_t off, struct stat *sbp)
+{
+ struct mapinfo map;
+ off_t curoff, size;
+ int i;
+
+ if (!(size = sbp->st_size))
+ return;
+ map.start = NULL;
+ map.fd = fileno(fp);
+ map.mapoff = map.maxoff = size;
+
+ /*
+ * Last char is special, ignore whether newline or not. Note that
+ * size == 0 is dealt with above, and size == 1 sets curoff to -1.
+ */
+ curoff = size - 2;
+ while (curoff >= 0) {
+ if (curoff < map.mapoff && maparound(&map, curoff) != 0) {
+ ierr(fn);
+ return;
+ }
+ for (i = curoff - map.mapoff; i >= 0; i--)
+ if (map.start[i] == '\n' && --off == 0)
+ break;
+ /* `i' is either the map offset of a '\n', or -1. */
+ curoff = map.mapoff + i;
+ if (i >= 0)
+ break;
+ }
+ curoff++;
+ if (mapprint(&map, curoff, size - curoff) != 0) {
+ ierr(fn);
+ exit(1);
+ }
+
+ /* Set the file pointer to reflect the length displayed. */
+ if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) {
+ ierr(fn);
+ return;
+ }
+ if (map.start != NULL && munmap(map.start, map.maplen)) {
+ ierr(fn);
+ return;
+ }
+}
+
+static int
+show(file_info_t *file)
+{
+ int ch;
+
+ while ((ch = getc(file->fp)) != EOF) {
+ if (last != file) {
+ if (vflag || (qflag == 0 && no_files > 1))
+ printfn(file->file_name, 1);
+ last = file;
+ }
+ if (putchar(ch) == EOF)
+ oerr();
+ }
+ (void)fflush(stdout);
+ if (ferror(file->fp)) {
+ fclose(file->fp);
+ file->fp = NULL;
+ ierr(file->file_name);
+ return 0;
+ }
+ clearerr(file->fp);
+ return 1;
+}
+
+static void
+set_events(file_info_t *files)
+{
+ int i, n = 0;
+ file_info_t *file;
+ struct timespec ts;
+ struct statfs sf;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+
+ action = USE_KQUEUE;
+ for (i = 0, file = files; i < no_files; i++, file++) {
+ if (!file->fp)
+ continue;
+
+ if (fstatfs(fileno(file->fp), &sf) == 0 &&
+ (sf.f_flags & MNT_LOCAL) == 0) {
+ action = USE_SLEEP;
+ return;
+ }
+
+ if (Fflag && fileno(file->fp) != STDIN_FILENO) {
+ EV_SET(&ev[n], fileno(file->fp), EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE | NOTE_RENAME, 0, 0);
+ n++;
+ }
+ EV_SET(&ev[n], fileno(file->fp), EVFILT_READ,
+ EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
+ n++;
+ }
+
+ if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
+ action = USE_SLEEP;
+ }
+}
+
+/*
+ * follow -- display the file, from an offset, forward.
+ *
+ */
+void
+follow(file_info_t *files, enum STYLE style, off_t off)
+{
+ int active, ev_change, i, n;
+ struct stat sb2;
+ file_info_t *file;
+ FILE *ftmp;
+ struct timespec ts;
+
+ /* Position each of the files */
+ active = 0;
+ for (i = 0, file = files; i < no_files; i++, file++) {
+ if (!file->fp)
+ continue;
+ active = 1;
+ if (vflag || (qflag == 0 && no_files > 1))
+ printfn(file->file_name, 1);
+ forward(file->fp, file->file_name, style, off, &file->st);
+ }
+ if (!Fflag && !active)
+ return;
+
+ last = --file;
+
+ kq = kqueue();
+ if (kq < 0)
+ err(1, "kqueue");
+ /*
+ * The number of kqueue events we track may vary over time and may
+ * even grow past its initial value in the -F case, but it will
+ * never exceed two per file, so just preallocate that.
+ */
+ ev = malloc(no_files * 2 * sizeof(struct kevent));
+ if (ev == NULL)
+ err(1, "failed to allocate memory for kevents");
+ set_events(files);
+
+ for (;;) {
+ ev_change = 0;
+ if (Fflag) {
+ for (i = 0, file = files; i < no_files; i++, file++) {
+ if (!file->fp) {
+ file->fp =
+ fileargs_fopen(fa, file->file_name,
+ "r");
+ if (file->fp != NULL &&
+ fstat(fileno(file->fp), &file->st)
+ == -1) {
+ fclose(file->fp);
+ file->fp = NULL;
+ }
+ if (file->fp != NULL)
+ ev_change++;
+ continue;
+ }
+ if (fileno(file->fp) == STDIN_FILENO)
+ continue;
+ ftmp = fileargs_fopen(fa, file->file_name, "r");
+ if (ftmp == NULL ||
+ fstat(fileno(ftmp), &sb2) == -1) {
+ if (errno != ENOENT)
+ ierr(file->file_name);
+ show(file);
+ if (file->fp != NULL) {
+ fclose(file->fp);
+ file->fp = NULL;
+ }
+ if (ftmp != NULL) {
+ fclose(ftmp);
+ }
+ ev_change++;
+ continue;
+ }
+
+ if (sb2.st_ino != file->st.st_ino ||
+ sb2.st_dev != file->st.st_dev ||
+ sb2.st_nlink == 0) {
+ show(file);
+ if (file->fp != NULL)
+ fclose(file->fp);
+ file->fp = ftmp;
+ memcpy(&file->st, &sb2,
+ sizeof(struct stat));
+ ev_change++;
+ } else {
+ fclose(ftmp);
+ }
+ }
+ }
+
+ for (i = 0, file = files; i < no_files; i++, file++)
+ if (file->fp && !show(file))
+ ev_change++;
+
+ if (ev_change)
+ set_events(files);
+
+ switch (action) {
+ case USE_KQUEUE:
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ /*
+ * In the -F case we set a timeout to ensure that
+ * we re-stat the file at least once every second.
+ * If we've received EINTR, ignore it. Both reasons
+ * for its generation are transient.
+ */
+ do {
+ n = kevent(kq, NULL, 0, ev, 1, Fflag ? &ts : NULL);
+ if (n < 0 && errno != EINTR)
+ err(1, "kevent");
+ } while (n < 0);
+ if (n == 0) {
+ /* timeout */
+ break;
+ } else if (ev->filter == EVFILT_READ && ev->data < 0) {
+ /* file shrank, reposition to end */
+ if (lseek(ev->ident, (off_t)0, SEEK_END) == -1) {
+ ierr(file->file_name);
+ continue;
+ }
+ }
+ break;
+
+ case USE_SLEEP:
+ (void) usleep(250000);
+ break;
+ }
+ }
+}
diff --git a/usr.bin/tail/misc.c b/usr.bin/tail/misc.c
new file mode 100644
index 000000000000..ecabf3436f75
--- /dev/null
+++ b/usr.bin/tail/misc.c
@@ -0,0 +1,128 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Edward Sze-Tyan Wang.
+ *
+ * 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 <sys/mman.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#include "extern.h"
+
+void
+ierr(const char *fname)
+{
+ warn("%s", fname);
+ rval = 1;
+}
+
+void
+oerr(void)
+{
+ err(1, "stdout");
+}
+
+/*
+ * Print `len' bytes from the file associated with `mip', starting at
+ * absolute file offset `startoff'. May move map window.
+ */
+int
+mapprint(struct mapinfo *mip, off_t startoff, off_t len)
+{
+ int n;
+
+ while (len > 0) {
+ if (startoff < mip->mapoff || startoff >= mip->mapoff +
+ (off_t)mip->maplen) {
+ if (maparound(mip, startoff) != 0)
+ return (1);
+ }
+ n = (mip->mapoff + mip->maplen) - startoff;
+ if (n > len)
+ n = len;
+ WR(mip->start + (startoff - mip->mapoff), n);
+ startoff += n;
+ len -= n;
+ }
+ return (0);
+}
+
+/*
+ * Move the map window so that it contains the byte at absolute file
+ * offset `offset'. The start of the map window will be TAILMAPLEN
+ * aligned.
+ */
+int
+maparound(struct mapinfo *mip, off_t offset)
+{
+
+ if (mip->start != NULL && munmap(mip->start, mip->maplen) != 0)
+ return (1);
+
+ mip->mapoff = offset & ~((off_t)TAILMAPLEN - 1);
+ mip->maplen = TAILMAPLEN;
+ if ((off_t)mip->maplen > mip->maxoff - mip->mapoff)
+ mip->maplen = mip->maxoff - mip->mapoff;
+ if (mip->maplen <= 0)
+ abort();
+ if ((mip->start = mmap(NULL, mip->maplen, PROT_READ, MAP_SHARED,
+ mip->fd, mip->mapoff)) == MAP_FAILED)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Print the file name without stdio buffering.
+ */
+void
+printfn(const char *fn, int print_nl)
+{
+
+ if (print_nl)
+ WR("\n", 1);
+ WR("==> ", 4);
+ WR(fn, strlen(fn));
+ WR(" <==\n", 5);
+}
diff --git a/usr.bin/tail/read.c b/usr.bin/tail/read.c
new file mode 100644
index 000000000000..07db98d0def1
--- /dev/null
+++ b/usr.bin/tail/read.c
@@ -0,0 +1,208 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Edward Sze-Tyan Wang.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#include "extern.h"
+
+/*
+ * bytes -- read bytes to an offset from the end and display.
+ *
+ * This is the function that reads to a byte offset from the end of the input,
+ * storing the data in a wrap-around buffer which is then displayed. If the
+ * rflag is set, the data is displayed in lines in reverse order, and this
+ * routine has the usual nastiness of trying to find the newlines. Otherwise,
+ * it is displayed from the character closest to the beginning of the input to
+ * the end.
+ */
+int
+bytes(FILE *fp, const char *fn, off_t off)
+{
+ int ch, len, tlen;
+ char *ep, *p, *t;
+ int wrap;
+ char *sp;
+
+ if ((sp = p = malloc(off)) == NULL)
+ err(1, "failed to allocate memory");
+
+ for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
+ *p = ch;
+ if (++p == ep) {
+ wrap = 1;
+ p = sp;
+ }
+ }
+ if (ferror(fp)) {
+ ierr(fn);
+ free(sp);
+ return 1;
+ }
+
+ if (rflag) {
+ for (t = p - 1, len = 0; t >= sp; --t, ++len)
+ if (*t == '\n' && len) {
+ WR(t + 1, len);
+ len = 0;
+ }
+ if (wrap) {
+ tlen = len;
+ for (t = ep - 1, len = 0; t >= p; --t, ++len)
+ if (*t == '\n') {
+ if (len) {
+ WR(t + 1, len);
+ len = 0;
+ }
+ if (tlen) {
+ WR(sp, tlen);
+ tlen = 0;
+ }
+ }
+ if (len)
+ WR(t + 1, len);
+ if (tlen)
+ WR(sp, tlen);
+ }
+ } else {
+ if (wrap && (len = ep - p))
+ WR(p, len);
+ len = p - sp;
+ if (len)
+ WR(sp, len);
+ }
+
+ free(sp);
+ return 0;
+}
+
+/*
+ * lines -- read lines to an offset from the end and display.
+ *
+ * This is the function that reads to a line offset from the end of the input,
+ * storing the data in an array of buffers which is then displayed. If the
+ * rflag is set, the data is displayed in lines in reverse order, and this
+ * routine has the usual nastiness of trying to find the newlines. Otherwise,
+ * it is displayed from the line closest to the beginning of the input to
+ * the end.
+ */
+int
+lines(FILE *fp, const char *fn, off_t off)
+{
+ struct {
+ int blen;
+ u_int len;
+ char *l;
+ } *llines;
+ int ch, rc;
+ char *p, *sp;
+ int blen, cnt, recno, wrap;
+
+ if ((llines = calloc(off, sizeof(*llines))) == NULL)
+ err(1, "failed to allocate memory");
+ p = sp = NULL;
+ blen = cnt = recno = wrap = 0;
+ rc = 0;
+
+ while ((ch = getc(fp)) != EOF) {
+ if (++cnt > blen) {
+ if ((sp = realloc(sp, blen += 1024)) == NULL)
+ err(1, "failed to allocate memory");
+ p = sp + cnt - 1;
+ }
+ *p++ = ch;
+ if (ch == '\n') {
+ if ((int)llines[recno].blen < cnt) {
+ llines[recno].blen = cnt + 256;
+ if ((llines[recno].l = realloc(llines[recno].l,
+ llines[recno].blen)) == NULL)
+ err(1, "failed to allocate memory");
+ }
+ bcopy(sp, llines[recno].l, llines[recno].len = cnt);
+ cnt = 0;
+ p = sp;
+ if (++recno == off) {
+ wrap = 1;
+ recno = 0;
+ }
+ }
+ }
+ if (ferror(fp)) {
+ ierr(fn);
+ rc = 1;
+ goto done;
+ }
+ if (cnt) {
+ llines[recno].l = sp;
+ sp = NULL;
+ llines[recno].len = cnt;
+ if (++recno == off) {
+ wrap = 1;
+ recno = 0;
+ }
+ }
+
+ if (rflag) {
+ for (cnt = recno - 1; cnt >= 0; --cnt)
+ WR(llines[cnt].l, llines[cnt].len);
+ if (wrap)
+ for (cnt = off - 1; cnt >= recno; --cnt)
+ WR(llines[cnt].l, llines[cnt].len);
+ } else {
+ if (wrap)
+ for (cnt = recno; cnt < off; ++cnt)
+ WR(llines[cnt].l, llines[cnt].len);
+ for (cnt = 0; cnt < recno; ++cnt)
+ WR(llines[cnt].l, llines[cnt].len);
+ }
+done:
+ for (cnt = 0; cnt < off; cnt++)
+ free(llines[cnt].l);
+ free(sp);
+ free(llines);
+ return (rc);
+}
diff --git a/usr.bin/tail/reverse.c b/usr.bin/tail/reverse.c
new file mode 100644
index 000000000000..1fa8784dec6d
--- /dev/null
+++ b/usr.bin/tail/reverse.c
@@ -0,0 +1,280 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Edward Sze-Tyan Wang.
+ *
+ * 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>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#include "extern.h"
+
+static void r_buf(FILE *, const char *);
+static void r_reg(FILE *, const char *, enum STYLE, off_t, struct stat *);
+
+/*
+ * reverse -- display input in reverse order by line.
+ *
+ * There are six separate cases for this -- regular and non-regular
+ * files by bytes, lines or the whole file.
+ *
+ * BYTES display N bytes
+ * REG mmap the file and display the lines
+ * NOREG cyclically read characters into a wrap-around buffer
+ *
+ * LINES display N lines
+ * REG mmap the file and display the lines
+ * NOREG cyclically read lines into a wrap-around array of buffers
+ *
+ * FILE display the entire file
+ * REG mmap the file and display the lines
+ * NOREG cyclically read input into a linked list of buffers
+ */
+void
+reverse(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
+{
+ if (style != REVERSE && off == 0)
+ return;
+
+ if (S_ISREG(sbp->st_mode))
+ r_reg(fp, fn, style, off, sbp);
+ else
+ switch(style) {
+ case FBYTES:
+ case RBYTES:
+ bytes(fp, fn, off);
+ break;
+ case FLINES:
+ case RLINES:
+ lines(fp, fn, off);
+ break;
+ case REVERSE:
+ r_buf(fp, fn);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * r_reg -- display a regular file in reverse order by line.
+ */
+static void
+r_reg(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
+{
+ struct mapinfo map;
+ off_t curoff, size, lineend;
+ int i;
+
+ if (!(size = sbp->st_size))
+ return;
+
+ map.start = NULL;
+ map.mapoff = map.maxoff = size;
+ map.fd = fileno(fp);
+ map.maplen = 0;
+
+ /*
+ * Last char is special, ignore whether newline or not. Note that
+ * size == 0 is dealt with above, and size == 1 sets curoff to -1.
+ */
+ curoff = size - 2;
+ lineend = size;
+ while (curoff >= 0) {
+ if (curoff < map.mapoff ||
+ curoff >= map.mapoff + (off_t)map.maplen) {
+ if (maparound(&map, curoff) != 0) {
+ ierr(fn);
+ return;
+ }
+ }
+ for (i = curoff - map.mapoff; i >= 0; i--) {
+ if (style == RBYTES && --off == 0)
+ break;
+ if (map.start[i] == '\n')
+ break;
+ }
+ /* `i' is either the map offset of a '\n', or -1. */
+ curoff = map.mapoff + i;
+ if (i < 0)
+ continue;
+
+ /* Print the line and update offsets. */
+ if (mapprint(&map, curoff + 1, lineend - curoff - 1) != 0) {
+ ierr(fn);
+ return;
+ }
+ lineend = curoff + 1;
+ curoff--;
+
+ if (style == RLINES)
+ off--;
+
+ if (off == 0 && style != REVERSE) {
+ /* Avoid printing anything below. */
+ curoff = 0;
+ break;
+ }
+ }
+ if (curoff < 0 && mapprint(&map, 0, lineend) != 0) {
+ ierr(fn);
+ return;
+ }
+ if (map.start != NULL && munmap(map.start, map.maplen))
+ ierr(fn);
+}
+
+#define BSZ (128 * 1024)
+typedef struct bfelem {
+ TAILQ_ENTRY(bfelem) entries;
+ size_t len;
+ char l[BSZ];
+} bfelem_t;
+
+/*
+ * r_buf -- display a non-regular file in reverse order by line.
+ *
+ * This is the function that saves the entire input, storing the data in a
+ * doubly linked list of buffers and then displays them in reverse order.
+ * It has the usual nastiness of trying to find the newlines, as there's no
+ * guarantee that a newline occurs anywhere in the file, let alone in any
+ * particular buffer. If we run out of memory, input is discarded (and the
+ * user warned).
+ */
+static void
+r_buf(FILE *fp, const char *fn)
+{
+ struct bfelem *tl, *first = NULL;
+ size_t llen;
+ char *p;
+ off_t enomem = 0;
+ TAILQ_HEAD(bfhead, bfelem) head;
+
+ TAILQ_INIT(&head);
+
+ while (!feof(fp)) {
+ size_t len;
+
+ /*
+ * Allocate a new block and link it into place in a doubly
+ * linked list. If out of memory, toss the LRU block and
+ * keep going.
+ */
+ while ((tl = malloc(sizeof(bfelem_t))) == NULL) {
+ first = TAILQ_FIRST(&head);
+ if (TAILQ_EMPTY(&head))
+ err(1, "failed to allocate memory");
+ enomem += first->len;
+ TAILQ_REMOVE(&head, first, entries);
+ free(first);
+ }
+ TAILQ_INSERT_TAIL(&head, tl, entries);
+
+ /* Fill the block with input data. */
+ len = 0;
+ while ((!feof(fp)) && len < BSZ) {
+ p = tl->l + len;
+ len += fread(p, 1, BSZ - len, fp);
+ if (ferror(fp)) {
+ ierr(fn);
+ return;
+ }
+ }
+
+ tl->len = len;
+ }
+
+ if (enomem) {
+ warnx("warning: %jd bytes discarded", (intmax_t)enomem);
+ rval = 1;
+ }
+
+ /*
+ * Now print the lines in reverse order
+ * Outline:
+ * Scan backward for "\n",
+ * print forward to the end of the buffers
+ * free any buffers that start after the "\n" just found
+ * Loop
+ */
+ tl = TAILQ_LAST(&head, bfhead);
+ first = TAILQ_FIRST(&head);
+ while (tl != NULL) {
+ struct bfelem *temp;
+
+ for (p = tl->l + tl->len - 1, llen = 0; p >= tl->l;
+ --p, ++llen) {
+ int start = (tl == first && p == tl->l);
+
+ if ((*p == '\n') || start) {
+ struct bfelem *tr;
+
+ if (llen && start && *p != '\n')
+ WR(p, llen + 1);
+ else if (llen) {
+ WR(p + 1, llen);
+ if (start && *p == '\n')
+ WR(p, 1);
+ }
+ tr = TAILQ_NEXT(tl, entries);
+ llen = 0;
+ if (tr != NULL) {
+ TAILQ_FOREACH_FROM_SAFE(tr, &head,
+ entries, temp) {
+ if (tr->len)
+ WR(&tr->l, tr->len);
+ TAILQ_REMOVE(&head, tr,
+ entries);
+ free(tr);
+ }
+ }
+ }
+ }
+ tl->len = llen;
+ tl = TAILQ_PREV(tl, bfhead, entries);
+ }
+ TAILQ_REMOVE(&head, first, entries);
+ free(first);
+}
diff --git a/usr.bin/tail/tail.1 b/usr.bin/tail/tail.1
new file mode 100644
index 000000000000..9e13567e01e1
--- /dev/null
+++ b/usr.bin/tail/tail.1
@@ -0,0 +1,216 @@
+.\" Copyright (c) 1980, 1990, 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd November 28, 2023
+.Dt TAIL 1
+.Os
+.Sh NAME
+.Nm tail
+.Nd display the last part of a file
+.Sh SYNOPSIS
+.Nm
+.Op Fl F | f | r
+.Op Fl qv
+.Oo
+.Fl b Ar number | Fl c Ar number | Fl n Ar number
+.Oc
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the contents of
+.Ar file
+or, by default, its standard input, to the standard output.
+.Pp
+The display begins at a byte, line or 512-byte block location in the
+input.
+Numbers having a leading plus
+.Pq Ql +
+sign are relative to the beginning
+of the input, for example,
+.Dq Li "-c +2"
+starts the display at the second
+byte of the input.
+Numbers having a leading minus
+.Pq Ql -
+sign or no explicit sign are
+relative to the end of the input, for example,
+.Dq Li "-n 2"
+displays the last two lines of the input.
+The default starting location is
+.Dq Li "-n 10" ,
+or the last 10 lines of the input.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl b Ar number , Fl -blocks Ns = Ns Ar number
+The location is
+.Ar number
+512-byte blocks.
+.It Fl c Ar number , Fl -bytes Ns = Ns Ar number
+The location is
+.Ar number
+bytes.
+.It Fl f
+The
+.Fl f
+option causes
+.Nm
+to not stop when end of file is reached, but rather to wait for additional
+data to be appended to the input.
+The
+.Fl f
+option is ignored if the standard input is a pipe, but not if it is a FIFO.
+.It Fl F
+The
+.Fl F
+option implies the
+.Fl f
+option, but
+.Nm
+will also check to see if the file being followed has been renamed or rotated.
+The file is closed and reopened when
+.Nm
+detects that the filename being read from has a new inode number.
+.Pp
+If the file being followed does not (yet) exist or if it is removed, tail
+will keep looking and will display the file from the beginning if and when
+it is created.
+.Pp
+The
+.Fl F
+option is the same as the
+.Fl f
+option if reading from standard input rather than a file.
+.It Fl n Ar number , Fl -lines Ns = Ns Ar number
+The location is
+.Ar number
+lines.
+.It Fl q , Fl -quiet , Fl -silent
+Suppresses printing of headers when multiple files are being examined.
+.It Fl r
+The
+.Fl r
+option causes the input to be displayed in reverse order, by line.
+Additionally, this option changes the meaning of the
+.Fl b , c
+and
+.Fl n
+options.
+When the
+.Fl r
+option is specified, these options specify the number of bytes, lines
+or 512-byte blocks to display, instead of the bytes, lines or blocks
+from the beginning or end of the input from which to begin the display.
+The default for the
+.Fl r
+option is to display all of the input.
+.It Fl v , Fl -verbose
+Prepend each file with a header.
+.El
+.Pp
+If more than a single file is specified, or if the
+.Fl v
+option is used, each file is preceded by a
+header consisting of the string
+.Dq Li "==> " Ns Ar XXX Ns Li " <=="
+where
+.Ar XXX
+is the name of the file.
+The
+.Fl q
+flag disables the printing of the header in all cases.
+.Pp
+All
+.Ar number
+arguments may also be specified with size suffixes supported by
+.Xr expand_number 3 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Display the last 500 lines of the file
+.Ar foo :
+.Pp
+.Dl $ tail -n 500 foo
+.Pp
+Keep
+.Pa /var/log/messages
+open, displaying to the standard output anything appended to the file:
+.Pp
+.Dl $ tail -F /var/log/messages
+.Pp
+Read
+.Pa /var/log/messages
+from the beginning and then follow the file as usual:
+.Pp
+.Dl $ tail -F -n +1 /var/log/messages
+.Sh SEE ALSO
+.Xr cat 1 ,
+.Xr head 1 ,
+.Xr sed 1 ,
+.Xr expand_number 3
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2-92
+specification.
+In particular, the
+.Fl F ,
+.Fl b
+and
+.Fl r
+options are extensions to that standard.
+.Pp
+The historic command line syntax of
+.Nm
+is supported by this implementation.
+The only difference between this implementation and historic versions
+of
+.Nm ,
+once the command line syntax translation has been done, is that the
+.Fl b ,
+.Fl c
+and
+.Fl n
+options modify the
+.Fl r
+option, i.e.,
+.Dq Li "-r -c 4"
+displays the last 4 characters of the last line
+of the input, while the historic tail (using the historic syntax
+.Dq Li -4cr )
+would ignore the
+.Fl c
+option and display the last 4 lines of the input.
+.Sh HISTORY
+A
+.Nm
+command appeared in PWB UNIX.
diff --git a/usr.bin/tail/tail.c b/usr.bin/tail/tail.c
new file mode 100644
index 000000000000..fc60a82287df
--- /dev/null
+++ b/usr.bin/tail/tail.c
@@ -0,0 +1,368 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Edward Sze-Tyan Wang.
+ *
+ * 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/capsicum.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#include "extern.h"
+
+int Fflag, fflag, qflag, rflag, rval, no_files, vflag;
+fileargs_t *fa;
+
+static void obsolete(char **);
+static void usage(void) __dead2;
+
+static const struct option long_opts[] =
+{
+ {"blocks", required_argument, NULL, 'b'},
+ {"bytes", required_argument, NULL, 'c'},
+ {"lines", required_argument, NULL, 'n'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"silent", no_argument, NULL, 'q'},
+ {"verbose", no_argument, NULL, 'v'},
+ {NULL, no_argument, NULL, 0}
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ const char *fn;
+ FILE *fp;
+ off_t off;
+ enum STYLE style;
+ int ch, first;
+ file_info_t file, *filep, *files;
+ cap_rights_t rights;
+
+ /*
+ * Tail's options are weird. First, -n10 is the same as -n-10, not
+ * -n+10. Second, the number options are 1 based and not offsets,
+ * so -n+1 is the first line, and -c-1 is the last byte. Third, the
+ * number options for the -r option specify the number of things that
+ * get displayed, not the starting point in the file. The one major
+ * incompatibility in this version as compared to historical versions
+ * is that the 'r' option couldn't be modified by the -lbc options,
+ * i.e. it was always done in lines. This version treats -rc as a
+ * number of characters in reverse order. Finally, the default for
+ * -r is the entire file, not 10 lines.
+ */
+#define ARG(units, forward, backward) { \
+ if (style) \
+ usage(); \
+ if (expand_number(optarg, &off)) \
+ err(1, "illegal offset -- %s", optarg); \
+ if (off > INT64_MAX / units || off < INT64_MIN / units ) \
+ errx(1, "illegal offset -- %s", optarg); \
+ switch(optarg[0]) { \
+ case '+': \
+ if (off) \
+ off -= (units); \
+ style = (forward); \
+ break; \
+ case '-': \
+ off = -off; \
+ /* FALLTHROUGH */ \
+ default: \
+ style = (backward); \
+ break; \
+ } \
+}
+
+ obsolete(argv);
+ style = NOTSET;
+ off = 0;
+ while ((ch = getopt_long(argc, argv, "+Fb:c:fn:qrv", long_opts, NULL)) !=
+ -1)
+ switch(ch) {
+ case 'F': /* -F is superset of (and implies) -f */
+ Fflag = fflag = 1;
+ break;
+ case 'b':
+ ARG(512, FBYTES, RBYTES);
+ break;
+ case 'c':
+ ARG(1, FBYTES, RBYTES);
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'n':
+ ARG(1, FLINES, RLINES);
+ break;
+ case 'q':
+ qflag = 1;
+ vflag = 0;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'v':
+ vflag = 1;
+ qflag = 0;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ no_files = argc ? argc : 1;
+
+ cap_rights_init(&rights, CAP_FSTAT, CAP_FSTATFS, CAP_FCNTL,
+ CAP_MMAP_R);
+ if (fflag)
+ cap_rights_set(&rights, CAP_EVENT);
+ if (caph_rights_limit(STDIN_FILENO, &rights) < 0 ||
+ caph_limit_stderr() < 0 || caph_limit_stdout() < 0)
+ err(1, "unable to limit stdio rights");
+
+ fa = fileargs_init(argc, argv, O_RDONLY, 0, &rights, FA_OPEN);
+ if (fa == NULL)
+ err(1, "unable to init casper");
+
+ caph_cache_catpages();
+ if (caph_enter_casper() < 0)
+ err(1, "unable to enter capability mode");
+
+ /*
+ * If displaying in reverse, don't permit follow option, and convert
+ * style values.
+ */
+ if (rflag) {
+ if (fflag)
+ usage();
+ if (style == FBYTES)
+ style = RBYTES;
+ else if (style == FLINES)
+ style = RLINES;
+ }
+
+ /*
+ * If style not specified, the default is the whole file for -r, and
+ * the last 10 lines if not -r.
+ */
+ if (style == NOTSET) {
+ if (rflag) {
+ off = 0;
+ style = REVERSE;
+ } else {
+ off = 10;
+ style = RLINES;
+ }
+ }
+
+ if (*argv && fflag) {
+ files = malloc(no_files * sizeof(struct file_info));
+ if (files == NULL)
+ err(1, "failed to allocate memory for file descriptors");
+
+ for (filep = files; (fn = *argv++); filep++) {
+ filep->file_name = fn;
+ filep->fp = fileargs_fopen(fa, filep->file_name, "r");
+ if (filep->fp == NULL ||
+ fstat(fileno(filep->fp), &filep->st)) {
+ if (filep->fp != NULL) {
+ fclose(filep->fp);
+ filep->fp = NULL;
+ }
+ if (!Fflag || errno != ENOENT)
+ ierr(filep->file_name);
+ }
+ }
+ follow(files, style, off);
+ free(files);
+ } else if (*argv) {
+ for (first = 1; (fn = *argv++);) {
+ if ((fp = fileargs_fopen(fa, fn, "r")) == NULL ||
+ fstat(fileno(fp), &sb)) {
+ ierr(fn);
+ continue;
+ }
+ if (vflag || (qflag == 0 && argc > 1)) {
+ printfn(fn, !first);
+ first = 0;
+ }
+
+ if (rflag)
+ reverse(fp, fn, style, off, &sb);
+ else
+ forward(fp, fn, style, off, &sb);
+ }
+ } else {
+ fn = "stdin";
+
+ if (fstat(fileno(stdin), &sb)) {
+ ierr(fn);
+ exit(1);
+ }
+
+ /*
+ * Determine if input is a pipe. 4.4BSD will set the SOCKET
+ * bit in the st_mode field for pipes. Fix this then.
+ */
+ if (lseek(fileno(stdin), (off_t)0, SEEK_CUR) == -1 &&
+ errno == ESPIPE) {
+ errno = 0;
+ fflag = 0; /* POSIX.2 requires this. */
+ }
+
+ if (rflag) {
+ reverse(stdin, fn, style, off, &sb);
+ } else if (fflag) {
+ file.file_name = fn;
+ file.fp = stdin;
+ file.st = sb;
+ follow(&file, style, off);
+ } else {
+ forward(stdin, fn, style, off, &sb);
+ }
+ }
+ fileargs_free(fa);
+ exit(rval);
+}
+
+/*
+ * Convert the obsolete argument form into something that getopt can handle.
+ * This means that anything of the form [+-][0-9][0-9]*[lbc][Ffr] that isn't
+ * the option argument for a -b, -c or -n option gets converted.
+ */
+static void
+obsolete(char *argv[])
+{
+ char *ap, *p, *t;
+ size_t len;
+ char *start;
+
+ while ((ap = *++argv)) {
+ /* Return if "--" or not an option of any form. */
+ if (ap[0] != '-') {
+ if (ap[0] != '+')
+ return;
+ } else if (ap[1] == '-')
+ return;
+
+ switch(*++ap) {
+ /* Old-style option. */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+
+ /* Malloc space for dash, new option and argument. */
+ len = strlen(*argv);
+ if ((start = p = malloc(len + 3)) == NULL)
+ err(1, "failed to allocate memory");
+ *p++ = '-';
+
+ /*
+ * Go to the end of the option argument. Save off any
+ * trailing options (-3lf) and translate any trailing
+ * output style characters.
+ */
+ t = *argv + len - 1;
+ if (*t == 'F' || *t == 'f' || *t == 'r') {
+ *p++ = *t;
+ *t-- = '\0';
+ }
+ switch(*t) {
+ case 'b':
+ *p++ = 'b';
+ *t = '\0';
+ break;
+ case 'c':
+ *p++ = 'c';
+ *t = '\0';
+ break;
+ case 'l':
+ *t = '\0';
+ /* FALLTHROUGH */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *p++ = 'n';
+ break;
+ default:
+ errx(1, "illegal option -- %s", *argv);
+ }
+ *p++ = *argv[0];
+ (void)strcpy(p, ap);
+ *argv = start;
+ continue;
+
+ /*
+ * Options w/ arguments, skip the argument and continue
+ * with the next option.
+ */
+ case 'b':
+ case 'c':
+ case 'n':
+ if (!ap[1])
+ ++argv;
+ /* FALLTHROUGH */
+ /* Options w/o arguments, continue with the next option. */
+ case 'F':
+ case 'f':
+ case 'r':
+ continue;
+
+ /* Illegal option, return and let getopt handle it. */
+ default:
+ return;
+ }
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: tail [-F | -f | -r] [-q] [-b # | -c # | -n #]"
+ " [file ...]\n");
+ exit(1);
+}
diff --git a/usr.bin/tail/tests/Makefile b/usr.bin/tail/tests/Makefile
new file mode 100644
index 000000000000..bb8fdc1016e2
--- /dev/null
+++ b/usr.bin/tail/tests/Makefile
@@ -0,0 +1,5 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= tail_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tail/tests/Makefile.depend b/usr.bin/tail/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tail/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tail/tests/tail_test.sh b/usr.bin/tail/tests/tail_test.sh
new file mode 100755
index 000000000000..9c941f8a2c2f
--- /dev/null
+++ b/usr.bin/tail/tests/tail_test.sh
@@ -0,0 +1,451 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2016 Alan Somers
+#
+# 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 AUTHOR 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 AUTHOR 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.
+#
+
+atf_test_case empty_r
+empty_r_head()
+{
+ atf_set "descr" "Reverse an empty file"
+}
+empty_r_body()
+{
+ touch infile expectfile
+ tail -r infile > outfile
+ tail -r < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case file_r
+file_r_head()
+{
+ atf_set "descr" "Reverse a file"
+}
+file_r_body()
+{
+ cat > infile <<HERE
+This is the first line
+This is the second line
+This is the third line
+HERE
+ cat > expectfile << HERE
+This is the third line
+This is the second line
+This is the first line
+HERE
+ tail -r infile > outfile
+ tail -r < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case file_rn2
+file_rn2_head()
+{
+ atf_set "descr" "Reverse the last two lines of a file"
+}
+file_rn2_body()
+{
+ cat > infile <<HERE
+This is the first line
+This is the second line
+This is the third line
+HERE
+ cat > expectfile << HERE
+This is the third line
+This is the second line
+HERE
+ tail -rn2 infile > outfile
+ tail -rn2 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+# Regression test for PR 222671
+# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222671
+atf_test_case pipe_leading_newline_r
+pipe_leading_newline_r_head()
+{
+ atf_set "descr" "Reverse a pipe whose first character is a newline"
+}
+pipe_leading_newline_r_body()
+{
+ cat > expectfile << HERE
+3
+2
+1
+
+HERE
+ printf '\n1\n2\n3\n' | tail -r > outfile
+ printf '\n1\n2\n3\n' | tail -r > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case file_rc28
+file_rc28_head()
+{
+ atf_set "descr" "Reverse a file and display the last 28 characters"
+}
+file_rc28_body()
+{
+ cat > infile <<HERE
+This is the first line
+This is the second line
+This is the third line
+HERE
+ cat > expectfile << HERE
+This is the third line
+line
+HERE
+ tail -rc28 infile > outfile
+ tail -rc28 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case file_rc28
+file_rc28_head()
+{
+ atf_set "descr" "Reverse a file and display the last 28 characters"
+}
+file_rc28_body()
+{
+ cat > infile <<HERE
+This is the first line
+This is the second line
+This is the third line
+HERE
+ cat > expectfile << HERE
+This is the third line
+line
+HERE
+ tail -rc28 infile > outfile
+ tail -rc28 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case longfile_r
+longfile_r_head()
+{
+ atf_set "descr" "Reverse a long file"
+}
+longfile_r_body()
+{
+ jot -w "%0511d" 1030 0 > infile
+ jot -w "%0511d" 1030 1029 0 -1 > expectfile
+ tail -r infile > outfile
+ tail -r < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case longfile_r_enomem
+longfile_r_enomem_head()
+{
+ atf_set "descr" "Reverse a file that's too long to store in RAM"
+}
+longfile_r_enomem_body()
+{
+ # When we reverse a file that's too long for RAM, tail should drop the
+ # first part and just print what it can. We'll check that the last
+ # part is ok
+ {
+ ulimit -v 32768 || atf_skip "Can't adjust ulimit"
+ jot -w "%01023d" 32768 0 | tail -r > outfile ;
+ }
+ if [ "$?" -ne 1 ]; then
+ atf_skip "Didn't get ENOMEM. Adjust test parameters"
+ fi
+ # We don't know how much of the input we dropped. So just check that
+ # the first ten lines of tail's output are the same as the last ten of
+ # the input
+ jot -w "%01023d" 10 32767 0 -1 > expectfile
+ head -n 10 outfile > outtrunc
+ diff expectfile outtrunc
+ atf_check cmp expectfile outtrunc
+}
+
+atf_test_case longfile_r_longlines
+longfile_r_longlines_head()
+{
+ atf_set "descr" "Reverse a long file with extremely long lines"
+}
+longfile_r_longlines_body()
+{
+ jot -s " " -w "%07d" 18000 0 > infile
+ jot -s " " -w "%07d" 18000 18000 >> infile
+ jot -s " " -w "%07d" 18000 36000 >> infile
+ jot -s " " -w "%07d" 18000 36000 > expectfile
+ jot -s " " -w "%07d" 18000 18000 >> expectfile
+ jot -s " " -w "%07d" 18000 0 >> expectfile
+ tail -r infile > outfile
+ tail -r < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case longfile_rc135782
+longfile_rc135782_head()
+{
+ atf_set "descr" "Reverse a long file and print the last 135,782 bytes"
+}
+longfile_rc135782_body()
+{
+ jot -w "%063d" 9000 0 > infile
+ jot -w "%063d" 2121 8999 0 -1 > expectfile
+ echo "0000000000000000000000000000000006878" >> expectfile
+ tail -rc135782 infile > outfile
+ tail -rc135782 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case longfile_rc145782_longlines
+longfile_rc145782_longlines_head()
+{
+ atf_set "descr" "Reverse a long file with extremely long lines and print the last 145,782 bytes"
+}
+longfile_rc145782_longlines_body()
+{
+ jot -s " " -w "%07d" 18000 0 > infile
+ jot -s " " -w "%07d" 18000 18000 >> infile
+ jot -s " " -w "%07d" 18000 36000 >> infile
+ jot -s " " -w "%07d" 18000 36000 > expectfile
+ echo -n "35777 " >> expectfile
+ jot -s " " -w "%07d" 222 35778 >> expectfile
+ tail -rc145782 infile > outfile
+ tail -rc145782 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case longfile_rn2500
+longfile_rn2500_head()
+{
+ atf_set "descr" "Reverse a long file and print the last 2,500 lines"
+}
+longfile_rn2500_body()
+{
+ jot -w "%063d" 9000 0 > infile
+ jot -w "%063d" 2500 8999 0 -1 > expectfile
+ tail -rn2500 infile > outfile
+ tail -rn2500 < infile > outpipe
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile outpipe
+}
+
+atf_test_case broken_pipe
+broken_pipe_head()
+{
+ atf_set "descr" "Do not print bogus errno based output on short writes"
+}
+broken_pipe_body()
+{
+ atf_check -o save:ints seq -f '%128g' 1 1000
+ atf_check -s ignore \
+ -e "inline:tail: stdout\nexit code: 1\n" \
+ -x '(tail -n 856 ints; echo exit code: $? >&2) | sleep 2'
+}
+
+atf_test_case stdin
+stdin_head()
+{
+ atf_set "descr" "Check basic operations on standard input"
+}
+stdin_body()
+{
+ seq 1 5 > infile
+ seq 1 5 > expectfile
+ seq 5 1 > expectfile_r
+
+ tail < infile > outfile
+ tail -r < infile > outfile_r
+
+ atf_check cmp expectfile outfile
+ atf_check cmp expectfile_r outfile_r
+}
+
+atf_test_case follow
+follow_head()
+{
+ atf_set "descr" "Basic regression test for -f"
+}
+follow_body()
+{
+ local pid
+
+ seq 1 5 > expectfile
+ seq 1 3 > infile
+ tail -f infile > outfile &
+ pid=$!
+ sleep 0.1
+ seq 4 5 >> infile
+ sleep 0.1
+ atf_check cmp expectfile outfile
+ atf_check kill $pid
+}
+
+atf_test_case follow_stdin
+follow_stdin_head()
+{
+ atf_set "descr" "Verify that -f works with files piped to standard input"
+}
+follow_stdin_body()
+{
+ local pid
+
+ seq 1 5 > expectfile
+ seq 1 3 > infile
+ tail -f < infile > outfile &
+ pid=$!
+ sleep 0.1
+ seq 4 5 >> infile
+ sleep 0.1
+ atf_check cmp expectfile outfile
+ atf_check kill $pid
+}
+
+atf_test_case follow_create
+follow_create_head()
+{
+ atf_set "descr" "Verify that -F works when a file is created"
+}
+follow_create_body()
+{
+ local pid
+
+ rm -f infile
+ tail -F infile > outfile &
+ pid=$!
+ seq 1 5 >infile
+ sleep 2
+ atf_check cmp infile outfile
+ atf_check kill $pid
+}
+
+atf_test_case follow_rename
+follow_rename_head()
+{
+ atf_set "descr" "Verify that -F works when a file is replaced"
+}
+follow_rename_body()
+{
+ local pid
+
+ seq 1 5 > expectfile
+ seq 1 3 > infile
+ tail -F infile > outfile &
+ pid=$!
+ seq 4 5 > infile_new
+ atf_check mv infile infile_old
+ atf_check mv infile_new infile
+ # tail -F polls for a new file every 1s.
+ sleep 2
+ atf_check cmp expectfile outfile
+ atf_check kill $pid
+}
+
+atf_test_case silent_header
+silent_header_head() {
+ atf_set "descr" "Test tail(1)'s silent header feature"
+}
+silent_header_body() {
+ jot 11 1 11 > file1
+ jot 11 2 12 > file2
+ jot 10 2 11 > expectfile
+ jot 10 3 12 >> expectfile
+ tail -q file1 file2 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case verbose_header
+verbose_header_head() {
+ atf_set "descr" "Test tail(1)'s verbose header feature"
+}
+verbose_header_body() {
+ jot 11 1 11 > file1
+ echo '==> file1 <==' > expectfile
+ jot 10 2 11 >> expectfile
+ tail -v file1 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case si_number
+si_number_head() {
+ atf_set "descr" "Test tail(1)'s SI number feature"
+}
+si_number_body() {
+ jot -b aaaaaaa 129 > file1
+ jot -b aaaaaaa 128 > expectfile
+ tail -c 1k file1 > outfile
+ atf_check cmp outfile expectfile
+ jot 1025 1 1025 > file1
+ jot 1024 2 1025 > expectfile
+ tail -n 1k file1 > outfile
+ atf_check cmp outfile expectfile
+}
+
+atf_test_case no_lf_at_eof
+no_lf_at_eof_head()
+{
+ atf_set "descr" "File does not end in newline"
+}
+no_lf_at_eof_body()
+{
+ printf "a\nb\nc" >infile
+ atf_check -o inline:"c" tail -1 infile
+ atf_check -o inline:"b\nc" tail -2 infile
+ atf_check -o inline:"a\nb\nc" tail -3 infile
+ atf_check -o inline:"a\nb\nc" tail -4 infile
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case empty_r
+ atf_add_test_case file_r
+ atf_add_test_case file_rc28
+ atf_add_test_case file_rn2
+ atf_add_test_case pipe_leading_newline_r
+ # The longfile tests are designed to exercise behavior in r_buf(),
+ # which operates on 128KB blocks
+ atf_add_test_case longfile_r
+ atf_add_test_case longfile_r_enomem
+ atf_add_test_case longfile_r_longlines
+ atf_add_test_case longfile_rc135782
+ atf_add_test_case longfile_rc145782_longlines
+ atf_add_test_case longfile_rn2500
+ atf_add_test_case broken_pipe
+ atf_add_test_case stdin
+ atf_add_test_case follow
+ atf_add_test_case follow_stdin
+ atf_add_test_case follow_create
+ atf_add_test_case follow_rename
+ atf_add_test_case silent_header
+ atf_add_test_case verbose_header
+ atf_add_test_case si_number
+ atf_add_test_case no_lf_at_eof
+}
diff --git a/usr.bin/talk/Makefile b/usr.bin/talk/Makefile
new file mode 100644
index 000000000000..40dfae8a1932
--- /dev/null
+++ b/usr.bin/talk/Makefile
@@ -0,0 +1,7 @@
+PROG= talk
+SRCS= ctl.c ctl_transact.c display.c get_addrs.c get_iface.c get_names.c \
+ init_disp.c invite.c io.c look_up.c msgs.c talk.c
+
+LIBADD= tinfow ncursesw
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/talk/Makefile.depend b/usr.bin/talk/Makefile.depend
new file mode 100644
index 000000000000..7093a46f1b71
--- /dev/null
+++ b/usr.bin/talk/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/protocols \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/talk/ctl.c b/usr.bin/talk/ctl.c
new file mode 100644
index 000000000000..6960708804ce
--- /dev/null
+++ b/usr.bin/talk/ctl.c
@@ -0,0 +1,118 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+/*
+ * This file handles haggling with the various talk daemons to
+ * get a socket to talk to. sockt is opened and connected in
+ * the progress
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <string.h>
+
+#include "talk.h"
+#include "talk_ctl.h"
+
+struct sockaddr_in daemon_addr = { .sin_len = sizeof(daemon_addr), .sin_family = AF_INET };
+struct sockaddr_in ctl_addr = { .sin_len = sizeof(ctl_addr), .sin_family = AF_INET };
+struct sockaddr_in my_addr = { .sin_len = sizeof(my_addr), .sin_family = AF_INET };
+
+ /* inet addresses of the two machines */
+struct in_addr my_machine_addr;
+struct in_addr his_machine_addr;
+
+u_short daemon_port; /* port number of the talk daemon */
+
+int ctl_sockt;
+int sockt;
+int invitation_waiting = 0;
+
+CTL_MSG msg;
+
+void
+open_sockt(void)
+{
+ socklen_t length;
+
+ (void)memset(&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_len = sizeof(my_addr);
+ my_addr.sin_addr = my_machine_addr;
+ my_addr.sin_port = 0;
+ sockt = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockt == -1)
+ p_error("Bad socket");
+ if (bind(sockt, (struct sockaddr *)&my_addr, sizeof(my_addr)) != 0)
+ p_error("Binding local socket");
+ length = sizeof(my_addr);
+ if (getsockname(sockt, (struct sockaddr *)&my_addr, &length) == -1)
+ p_error("Bad address for socket");
+}
+
+/* open the ctl socket */
+void
+open_ctl(void)
+{
+ socklen_t length;
+
+ (void)memset(&ctl_addr, 0, sizeof(ctl_addr));
+ ctl_addr.sin_family = AF_INET;
+ ctl_addr.sin_len = sizeof(my_addr);
+ ctl_addr.sin_port = 0;
+ ctl_addr.sin_addr = my_machine_addr;
+ ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0);
+ if (ctl_sockt == -1)
+ p_error("Bad socket");
+ if (bind(ctl_sockt,
+ (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0)
+ p_error("Couldn't bind to control socket");
+ length = sizeof(ctl_addr);
+ if (getsockname(ctl_sockt,
+ (struct sockaddr *)&ctl_addr, &length) == -1)
+ p_error("Bad address for ctl socket");
+}
+
+/* print_addr is a debug print routine */
+void
+print_addr(struct sockaddr_in addr)
+{
+ int i;
+
+ printf("addr = %lx, port = %o, family = %o zero = ",
+ (u_long)addr.sin_addr.s_addr, addr.sin_port, addr.sin_family);
+ for (i = 0; i<8;i++)
+ printf("%o ", (int)addr.sin_zero[i]);
+ putchar('\n');
+}
diff --git a/usr.bin/talk/ctl_transact.c b/usr.bin/talk/ctl_transact.c
new file mode 100644
index 000000000000..a9672c3839e2
--- /dev/null
+++ b/usr.bin/talk/ctl_transact.c
@@ -0,0 +1,101 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <poll.h>
+
+#include "talk.h"
+#include "talk_ctl.h"
+
+#define CTL_WAIT 2 /* time to wait for a response, in seconds */
+
+/*
+ * SOCKDGRAM is unreliable, so we must repeat messages if we have
+ * not received an acknowledgement within a reasonable amount
+ * of time
+ */
+void
+ctl_transact(struct in_addr target, CTL_MSG lmsg, int type, CTL_RESPONSE *rp)
+{
+ struct pollfd pfd[1];
+ int nready = 0, cc;
+
+ lmsg.type = type;
+ daemon_addr.sin_addr = target;
+ daemon_addr.sin_port = daemon_port;
+ pfd[0].fd = ctl_sockt;
+ pfd[0].events = POLLIN;
+
+ /*
+ * Keep sending the message until a response of
+ * the proper type is obtained.
+ */
+ do {
+ /* resend message until a response is obtained */
+ do {
+ cc = sendto(ctl_sockt, (char *)&lmsg, sizeof (lmsg), 0,
+ (struct sockaddr *)&daemon_addr,
+ sizeof (daemon_addr));
+ if (cc != sizeof (lmsg)) {
+ if (errno == EINTR)
+ continue;
+ p_error("Error on write to talk daemon");
+ }
+ nready = poll(pfd, 1, CTL_WAIT * 1000);
+ if (nready < 0) {
+ if (errno == EINTR)
+ continue;
+ p_error("Error waiting for daemon response");
+ }
+ } while (nready == 0);
+ /*
+ * Keep reading while there are queued messages
+ * (this is not necessary, it just saves extra
+ * request/acknowledgements being sent)
+ */
+ do {
+ cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0);
+ if (cc < 0) {
+ if (errno == EINTR)
+ continue;
+ p_error("Error on read from talk daemon");
+ }
+ nready = poll(pfd, 1, 0);
+ } while (nready > 0 && (rp->vers != TALK_VERSION ||
+ rp->type != type));
+ } while (rp->vers != TALK_VERSION || rp->type != type);
+ rp->id_num = ntohl(rp->id_num);
+ rp->addr.sa_family = ntohs(rp->addr.sa_family);
+}
diff --git a/usr.bin/talk/display.c b/usr.bin/talk/display.c
new file mode 100644
index 000000000000..aafe55204068
--- /dev/null
+++ b/usr.bin/talk/display.c
@@ -0,0 +1,206 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+/*
+ * The window 'manager', initializes curses and handles the actual
+ * displaying of text
+ */
+#include <ctype.h>
+#include <unistd.h>
+#include <wctype.h>
+#define _XOPEN_SOURCE_EXTENDED
+#include <curses.h>
+
+#include "talk.h"
+
+void display(xwin_t *, wchar_t *);
+
+xwin_t my_win;
+xwin_t his_win;
+WINDOW *line_win;
+
+int curses_initialized = 0;
+
+/*
+ * max HAS to be a function, it is called with
+ * an argument of the form --foo at least once.
+ */
+int
+max(int a, int b)
+{
+
+ return (a > b ? a : b);
+}
+
+static cchar_t *
+makecchar(wchar_t in)
+{
+ static cchar_t cc;
+ wchar_t wc[2];
+
+ wc[0] = in;
+ wc[1] = L'\0';
+
+ if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK)
+ p_error("settchar(3) failure");
+
+ return (&cc);
+}
+
+/*
+ * Display a symbol on somebody's window, processing some control
+ * characters while we are at it.
+ */
+void
+display(xwin_t *win, wchar_t *wc)
+{
+
+ /*
+ * Alas, can't use variables in C switch statement.
+ * Workaround these 3 cases with goto.
+ */
+ if (*wc == win->kill)
+ goto kill;
+ else if (*wc == win->cerase)
+ goto cerase;
+ else if (*wc == win->werase)
+ goto werase;
+
+ switch (*wc) {
+ case L'\n':
+ case L'\r':
+ wadd_wch(win->x_win, makecchar(L'\n'));
+ getyx(win->x_win, win->x_line, win->x_col);
+ wrefresh(win->x_win);
+ return;
+
+ case 004:
+ if (win == &my_win) {
+ /* Ctrl-D clears the screen. */
+ werase(my_win.x_win);
+ getyx(my_win.x_win, my_win.x_line, my_win.x_col);
+ wrefresh(my_win.x_win);
+ werase(his_win.x_win);
+ getyx(his_win.x_win, his_win.x_line, his_win.x_col);
+ wrefresh(his_win.x_win);
+ }
+ return;
+
+ /* Erase character. */
+ case 010: /* BS */
+ case 0177: /* DEL */
+cerase:
+ wmove(win->x_win, win->x_line, max(--win->x_col, 0));
+ getyx(win->x_win, win->x_line, win->x_col);
+ waddch(win->x_win, ' ');
+ wmove(win->x_win, win->x_line, win->x_col);
+ getyx(win->x_win, win->x_line, win->x_col);
+ wrefresh(win->x_win);
+ return;
+
+ case 027: /* ^W */
+werase:
+ {
+ /*
+ * On word erase search backwards until we find
+ * the beginning of a word or the beginning of
+ * the line.
+ */
+ int endcol, xcol, c;
+
+ endcol = win->x_col;
+ xcol = endcol - 1;
+ while (xcol >= 0) {
+ c = readwin(win->x_win, win->x_line, xcol);
+ if (c != ' ')
+ break;
+ xcol--;
+ }
+ while (xcol >= 0) {
+ c = readwin(win->x_win, win->x_line, xcol);
+ if (c == ' ')
+ break;
+ xcol--;
+ }
+ wmove(win->x_win, win->x_line, xcol + 1);
+ for (int i = xcol + 1; i < endcol; i++)
+ waddch(win->x_win, ' ');
+ wmove(win->x_win, win->x_line, xcol + 1);
+ getyx(win->x_win, win->x_line, win->x_col);
+ wrefresh(win->x_win);
+ return;
+ }
+
+ case 025: /* ^U */
+kill:
+ wmove(win->x_win, win->x_line, 0);
+ wclrtoeol(win->x_win);
+ getyx(win->x_win, win->x_line, win->x_col);
+ wrefresh(win->x_win);
+ return;
+
+ case L'\f':
+ if (win == &my_win)
+ wrefresh(curscr);
+ return;
+
+ case L'\7':
+ write(STDOUT_FILENO, wc, sizeof(*wc));
+ return;
+ }
+
+
+ if (iswprint(*wc) || *wc == L'\t')
+ wadd_wch(win->x_win, makecchar(*wc));
+ else
+ beep();
+
+ getyx(win->x_win, win->x_line, win->x_col);
+ wrefresh(win->x_win);
+}
+
+/*
+ * Read the character at the indicated position in win
+ */
+int
+readwin(WINDOW *win, int line, int col)
+{
+ int oldline, oldcol;
+ int c;
+
+ getyx(win, oldline, oldcol);
+ wmove(win, line, col);
+ c = winch(win);
+ wmove(win, oldline, oldcol);
+ return (c);
+}
diff --git a/usr.bin/talk/get_addrs.c b/usr.bin/talk/get_addrs.c
new file mode 100644
index 000000000000..49b4a3ee150b
--- /dev/null
+++ b/usr.bin/talk/get_addrs.c
@@ -0,0 +1,61 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+#include <err.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "talk.h"
+#include "talk_ctl.h"
+
+void
+get_addrs(const char *my_machine_name __unused, const char *his_machine_name)
+{
+ struct hostent *hp;
+ struct servent *sp;
+
+ msg.pid = htonl(getpid());
+
+ hp = gethostbyname(his_machine_name);
+ if (hp == NULL)
+ errx(1, "%s: %s", his_machine_name, hstrerror(h_errno));
+ bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
+ if (get_iface(&his_machine_addr, &my_machine_addr) == -1)
+ err(1, "failed to find my interface address");
+ /* find the server's port */
+ sp = getservbyname("ntalk", "udp");
+ if (sp == NULL)
+ errx(1, "ntalk/udp: service is not registered");
+ daemon_port = sp->s_port;
+}
diff --git a/usr.bin/talk/get_iface.c b/usr.bin/talk/get_iface.c
new file mode 100644
index 000000000000..5c69046c680e
--- /dev/null
+++ b/usr.bin/talk/get_iface.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 1994, 1995 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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:
+ * Id: find_interface.c,v 1.1 1995/08/14 16:08:39 wollman Exp
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "talk.h"
+
+/*
+ * Try to find the interface address that is used to route an IP
+ * packet to a remote peer.
+ */
+
+int
+get_iface(struct in_addr *dst, struct in_addr *iface)
+{
+ static struct sockaddr_in local;
+ struct sockaddr_in remote;
+ socklen_t namelen;
+ int s, rv;
+
+ memcpy(&remote.sin_addr, dst, sizeof remote.sin_addr);
+ remote.sin_port = htons(60000);
+ remote.sin_family = AF_INET;
+ remote.sin_len = sizeof remote;
+
+ local.sin_addr.s_addr = htonl(INADDR_ANY);
+ local.sin_port = htons(60000);
+ local.sin_family = AF_INET;
+ local.sin_len = sizeof local;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return -1;
+
+ do {
+ rv = bind(s, (struct sockaddr *)&local, sizeof local);
+ local.sin_port = htons(ntohs(local.sin_port) + 1);
+ } while(rv < 0 && errno == EADDRINUSE);
+
+ if (rv < 0) {
+ close(s);
+ return -1;
+ }
+
+ do {
+ rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
+ remote.sin_port = htons(ntohs(remote.sin_port) + 1);
+ } while(rv < 0 && errno == EADDRINUSE);
+
+ if (rv < 0) {
+ close(s);
+ return -1;
+ }
+
+ namelen = sizeof local;
+ rv = getsockname(s, (struct sockaddr *)&local, &namelen);
+ close(s);
+ if (rv < 0)
+ return -1;
+
+ memcpy(iface, &local.sin_addr, sizeof local.sin_addr);
+ return 0;
+}
diff --git a/usr.bin/talk/get_names.c b/usr.bin/talk/get_names.c
new file mode 100644
index 000000000000..33851b954a1d
--- /dev/null
+++ b/usr.bin/talk/get_names.c
@@ -0,0 +1,111 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "talk.h"
+
+extern CTL_MSG msg;
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: talk person [ttyname]\n");
+ exit(1);
+}
+
+/*
+ * Determine the local and remote user, tty, and machines
+ */
+void
+get_names(int argc, char *argv[])
+{
+ char hostname[MAXHOSTNAMELEN];
+ char *his_name, *my_name;
+ const char *my_machine_name, *his_machine_name;
+ const char *his_tty;
+ char *cp;
+
+ if (argc < 2 )
+ usage();
+ if (!isatty(0))
+ errx(1, "standard input must be a tty, not a pipe or a file");
+ if ((my_name = getlogin()) == NULL) {
+ struct passwd *pw;
+
+ if ((pw = getpwuid(getuid())) == NULL)
+ errx(1, "you don't exist. Go away");
+ my_name = pw->pw_name;
+ }
+ gethostname(hostname, sizeof (hostname));
+ my_machine_name = hostname;
+ /* check for, and strip out, the machine name of the target */
+ cp = argv[1] + strcspn(argv[1], "@:!");
+ if (*cp == '\0') {
+ /* this is a local to local talk */
+ his_name = argv[1];
+ my_machine_name = his_machine_name = "localhost";
+ } else {
+ if (*cp++ == '@') {
+ /* user@host */
+ his_name = argv[1];
+ his_machine_name = cp;
+ } else {
+ /* host!user or host:user */
+ his_name = cp;
+ his_machine_name = argv[1];
+ }
+ *--cp = '\0';
+ }
+ if (argc > 2)
+ his_tty = argv[2]; /* tty name is arg 2 */
+ else
+ his_tty = "";
+ get_addrs(my_machine_name, his_machine_name);
+ /*
+ * Initialize the message template.
+ */
+ msg.vers = TALK_VERSION;
+ msg.addr.sa_family = htons(AF_INET);
+ msg.ctl_addr.sa_family = htons(AF_INET);
+ msg.id_num = htonl(0);
+ strlcpy(msg.l_name, my_name, NAME_SIZE);
+ strlcpy(msg.r_name, his_name, NAME_SIZE);
+ strlcpy(msg.r_tty, his_tty, TTY_SIZE);
+}
diff --git a/usr.bin/talk/init_disp.c b/usr.bin/talk/init_disp.c
new file mode 100644
index 000000000000..724801c2fb3a
--- /dev/null
+++ b/usr.bin/talk/init_disp.c
@@ -0,0 +1,229 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+/*
+ * Initialization code for the display package,
+ * as well as the signal handling routines.
+ */
+
+#include <sys/stat.h>
+
+#include <err.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+
+#include "talk.h"
+
+/*
+ * Make sure the callee can write to the screen
+ */
+void
+check_writeable(void)
+{
+ char *tty;
+ struct stat sb;
+
+ if ((tty = ttyname(STDERR_FILENO)) == NULL)
+ err(1, "ttyname");
+ if (stat(tty, &sb) < 0)
+ err(1, "%s", tty);
+ if (!(sb.st_mode & S_IWGRP))
+ errx(1, "The callee cannot write to this terminal, use \"mesg y\".");
+}
+
+/*
+ * Set up curses, catch the appropriate signals,
+ * and build the various windows.
+ */
+void
+init_display(void)
+{
+ struct sigaction sa;
+
+ if (initscr() == NULL)
+ errx(1, "Terminal type unset or lacking necessary features.");
+ (void) sigaction(SIGTSTP, (struct sigaction *)0, &sa);
+ sigaddset(&sa.sa_mask, SIGALRM);
+ (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
+ curses_initialized = 1;
+ clear();
+ refresh();
+ noecho();
+ crmode();
+ signal(SIGINT, sig_sent);
+ signal(SIGPIPE, sig_sent);
+ signal(SIGWINCH, sig_winch);
+ /* curses takes care of ^Z */
+ my_win.x_nlines = LINES / 2;
+ my_win.x_ncols = COLS;
+ my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0);
+ idlok(my_win.x_win, TRUE);
+ scrollok(my_win.x_win, TRUE);
+ wclear(my_win.x_win);
+
+ his_win.x_nlines = LINES / 2 - 1;
+ his_win.x_ncols = COLS;
+ his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols,
+ my_win.x_nlines+1, 0);
+ idlok(my_win.x_win, TRUE);
+ scrollok(his_win.x_win, TRUE);
+ wclear(his_win.x_win);
+
+ line_win = newwin(1, COLS, my_win.x_nlines, 0);
+#if defined(hline) || defined(whline) || defined(NCURSES_VERSION)
+ whline(line_win, 0, COLS);
+#else
+ box(line_win, '-', '-');
+#endif
+ wrefresh(line_win);
+ /* let them know we are working on it */
+ current_state = "No connection yet";
+}
+
+/*
+ * Trade edit characters with the other talk. By agreement
+ * the first three characters each talk transmits after
+ * connection are the three edit characters.
+ */
+void
+set_edit_chars(void)
+{
+ char buf[3];
+ int cc;
+ struct termios tio;
+
+ tcgetattr(0, &tio);
+ my_win.cerase = tio.c_cc[VERASE];
+ my_win.kill = tio.c_cc[VKILL];
+ my_win.werase = tio.c_cc[VWERASE];
+ if (my_win.cerase == (char)_POSIX_VDISABLE)
+ my_win.kill = CERASE;
+ if (my_win.kill == (char)_POSIX_VDISABLE)
+ my_win.kill = CKILL;
+ if (my_win.werase == (char)_POSIX_VDISABLE)
+ my_win.werase = CWERASE;
+ buf[0] = my_win.cerase;
+ buf[1] = my_win.kill;
+ buf[2] = my_win.werase;
+ cc = write(sockt, buf, sizeof(buf));
+ if (cc != sizeof(buf) )
+ p_error("Lost the connection");
+ cc = read(sockt, buf, sizeof(buf));
+ if (cc != sizeof(buf) )
+ p_error("Lost the connection");
+ his_win.cerase = buf[0];
+ his_win.kill = buf[1];
+ his_win.werase = buf[2];
+}
+
+/* ARGSUSED */
+void
+sig_sent(int signo __unused)
+{
+
+ message("Connection closing. Exiting");
+ quit();
+}
+
+void
+sig_winch(int dummy __unused)
+{
+
+ gotwinch = 1;
+}
+
+/*
+ * All done talking...hang up the phone and reset terminal thingy's
+ */
+void
+quit(void)
+{
+
+ if (curses_initialized) {
+ wmove(his_win.x_win, his_win.x_nlines-1, 0);
+ wclrtoeol(his_win.x_win);
+ wrefresh(his_win.x_win);
+ endwin();
+ }
+ if (invitation_waiting)
+ send_delete();
+ exit(0);
+}
+
+/*
+ * If we get SIGWINCH, recompute both window sizes and refresh things.
+ */
+void
+resize_display(void)
+{
+ struct winsize ws;
+
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 ||
+ (ws.ws_row == LINES && ws.ws_col == COLS))
+ return;
+
+ /* Update curses' internal state with new window size. */
+ resizeterm(ws.ws_row, ws.ws_col);
+
+ /*
+ * Resize each window but wait to refresh the screen until
+ * everything has been drawn so the cursor is in the right spot.
+ */
+ my_win.x_nlines = LINES / 2;
+ my_win.x_ncols = COLS;
+ wresize(my_win.x_win, my_win.x_nlines, my_win.x_ncols);
+ mvwin(my_win.x_win, 0, 0);
+ clearok(my_win.x_win, TRUE);
+
+ his_win.x_nlines = LINES / 2 - 1;
+ his_win.x_ncols = COLS;
+ wresize(his_win.x_win, his_win.x_nlines, his_win.x_ncols);
+ mvwin(his_win.x_win, my_win.x_nlines + 1, 0);
+ clearok(his_win.x_win, TRUE);
+
+ wresize(line_win, 1, COLS);
+ mvwin(line_win, my_win.x_nlines, 0);
+#if defined(NCURSES_VERSION) || defined(whline)
+ whline(line_win, '-', COLS);
+#else
+ wmove(line_win, my_win.x_nlines, 0);
+ box(line_win, '-', '-');
+#endif
+
+ /* Now redraw the screen. */
+ wrefresh(his_win.x_win);
+ wrefresh(line_win);
+ wrefresh(my_win.x_win);
+}
diff --git a/usr.bin/talk/invite.c b/usr.bin/talk/invite.c
new file mode 100644
index 000000000000..c4881ff4c40e
--- /dev/null
+++ b/usr.bin/talk/invite.c
@@ -0,0 +1,188 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+
+#include <err.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "talk_ctl.h"
+#include "talk.h"
+
+/*
+ * There wasn't an invitation waiting, so send a request containing
+ * our sockt address to the remote talk daemon so it can invite
+ * him
+ */
+
+/*
+ * The msg.id's for the invitations
+ * on the local and remote machines.
+ * These are used to delete the
+ * invitations.
+ */
+static int local_id, remote_id;
+static jmp_buf invitebuf;
+
+void
+invite_remote(void)
+{
+ int new_sockt;
+ struct itimerval itimer;
+ CTL_RESPONSE response;
+
+ itimer.it_value.tv_sec = RING_WAIT;
+ itimer.it_value.tv_usec = 0;
+ itimer.it_interval = itimer.it_value;
+ if (listen(sockt, 5) != 0)
+ p_error("Error on attempt to listen for caller");
+ /* copy new style sockaddr to old, swap family (short in old) */
+ msg.addr = *(struct tsockaddr *)&my_addr;
+ msg.addr.sa_family = htons(my_addr.sin_family);
+ msg.id_num = htonl(-1); /* an impossible id_num */
+ invitation_waiting = 1;
+ announce_invite();
+ /*
+ * Shut off the automatic messages for a while,
+ * so we can use the interrupt timer to resend the invitation
+ */
+ end_msgs();
+ setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+ message("Waiting for your party to respond");
+ signal(SIGALRM, re_invite);
+ (void) setjmp(invitebuf);
+ while ((new_sockt = accept(sockt, 0, 0)) < 0) {
+ if (errno == EINTR)
+ continue;
+ p_error("Unable to connect with your party");
+ }
+ close(sockt);
+ sockt = new_sockt;
+
+ /*
+ * Have the daemons delete the invitations now that we
+ * have connected.
+ */
+ current_state = "Waiting for your party to respond";
+ start_msgs();
+
+ msg.id_num = htonl(local_id);
+ ctl_transact(my_machine_addr, msg, DELETE, &response);
+ msg.id_num = htonl(remote_id);
+ ctl_transact(his_machine_addr, msg, DELETE, &response);
+ invitation_waiting = 0;
+}
+
+/*
+ * Routine called on interrupt to re-invite the callee
+ */
+/* ARGSUSED */
+void
+re_invite(int signo __unused)
+{
+
+ message("Ringing your party again");
+ waddch(my_win.x_win, '\n');
+ if (current_line < my_win.x_nlines - 1)
+ current_line++;
+ /* force a re-announce */
+ msg.id_num = htonl(remote_id + 1);
+ announce_invite();
+ longjmp(invitebuf, 1);
+}
+
+static const char *answers[] = {
+ "answer #0", /* SUCCESS */
+ "Your party is not logged on", /* NOT_HERE */
+ "Target machine is too confused to talk to us", /* FAILED */
+ "Target machine does not recognize us", /* MACHINE_UNKNOWN */
+ "Your party is refusing messages", /* PERMISSION_REFUSED */
+ "Target machine can not handle remote talk", /* UNKNOWN_REQUEST */
+ "Target machine indicates protocol mismatch", /* BADVERSION */
+ "Target machine indicates protocol botch (addr)",/* BADADDR */
+ "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */
+};
+#define NANSWERS (sizeof (answers) / sizeof (answers[0]))
+
+/*
+ * Transmit the invitation and process the response
+ */
+void
+announce_invite(void)
+{
+ CTL_RESPONSE response;
+
+ current_state = "Trying to connect to your party's talk daemon";
+ ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
+ remote_id = response.id_num;
+ if (response.answer != SUCCESS) {
+ if (response.answer < NANSWERS)
+ message(answers[response.answer]);
+ quit();
+ }
+ /* leave the actual invitation on my talk daemon */
+ current_state = "Trying to connect to local talk daemon";
+ ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
+ local_id = response.id_num;
+}
+
+/*
+ * Tell the daemon to remove your invitation
+ */
+void
+send_delete(void)
+{
+
+ msg.type = DELETE;
+ /*
+ * This is just an extra clean up, so just send it
+ * and don't wait for an answer
+ */
+ msg.id_num = htonl(remote_id);
+ daemon_addr.sin_addr = his_machine_addr;
+ if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
+ (struct sockaddr *)&daemon_addr,
+ sizeof (daemon_addr)) != sizeof(msg))
+ warn("send_delete (remote)");
+ msg.id_num = htonl(local_id);
+ daemon_addr.sin_addr = my_machine_addr;
+ if (sendto(ctl_sockt, &msg, sizeof (msg), 0,
+ (struct sockaddr *)&daemon_addr,
+ sizeof (daemon_addr)) != sizeof (msg))
+ warn("send_delete (local)");
+}
diff --git a/usr.bin/talk/io.c b/usr.bin/talk/io.c
new file mode 100644
index 000000000000..a2d7fb1818f7
--- /dev/null
+++ b/usr.bin/talk/io.c
@@ -0,0 +1,173 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+/*
+ * This file contains the I/O handling and the exchange of
+ * edit characters. This connection itself is established in
+ * ctl.c
+ */
+
+#include <sys/filio.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <netdb.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#define _XOPEN_SOURCE_EXTENDED
+#include <curses.h>
+
+#include "talk.h"
+#include "talk_ctl.h"
+
+extern void display(xwin_t *, wchar_t *);
+
+volatile sig_atomic_t gotwinch = 0;
+
+/*
+ * The routine to do the actual talking
+ */
+void
+talk(void)
+{
+ struct hostent *hp, *hp2;
+ struct pollfd fds[2];
+ int nb;
+ wchar_t buf[BUFSIZ];
+ char **addr, *his_machine_name;
+ FILE *sockfp;
+
+ his_machine_name = NULL;
+ hp = gethostbyaddr((const char *)&his_machine_addr.s_addr,
+ sizeof(his_machine_addr.s_addr), AF_INET);
+ if (hp != NULL) {
+ hp2 = gethostbyname(hp->h_name);
+ if (hp2 != NULL && hp2->h_addrtype == AF_INET &&
+ hp2->h_length == sizeof(his_machine_addr))
+ for (addr = hp2->h_addr_list; *addr != NULL; addr++)
+ if (memcmp(*addr, &his_machine_addr,
+ sizeof(his_machine_addr)) == 0) {
+ his_machine_name = strdup(hp->h_name);
+ break;
+ }
+ }
+ if (his_machine_name == NULL)
+ his_machine_name = strdup(inet_ntoa(his_machine_addr));
+ snprintf((char *)buf, sizeof(buf), "Connection established with %s@%s.",
+ msg.r_name, his_machine_name);
+ free(his_machine_name);
+ message((char *)buf);
+ write(STDOUT_FILENO, "\007\007\007", 3);
+
+ current_line = 0;
+
+ if ((sockfp = fdopen(sockt, "w+")) == NULL)
+ p_error("fdopen");
+
+ setvbuf(sockfp, NULL, _IONBF, 0);
+ setvbuf(stdin, NULL, _IONBF, 0);
+
+ /*
+ * Wait on both the other process (sockt) and standard input.
+ */
+ for (;;) {
+ fds[0].fd = fileno(stdin);
+ fds[0].events = POLLIN;
+ fds[1].fd = sockt;
+ fds[1].events = POLLIN;
+ nb = poll(fds, 2, INFTIM);
+ if (gotwinch) {
+ resize_display();
+ gotwinch = 0;
+ }
+ if (nb <= 0) {
+ if (errno == EINTR)
+ continue;
+ /* Panic, we don't know what happened. */
+ p_error("Unexpected error from poll");
+ quit();
+ }
+ if (fds[1].revents & POLLIN) {
+ wint_t w;
+
+ /* There is data on sockt. */
+ w = fgetwc(sockfp);
+ if (w == WEOF) {
+ message("Connection closed. Exiting");
+ quit();
+ }
+ display(&his_win, &w);
+ }
+ if (fds[0].revents & POLLIN) {
+ wint_t w;
+
+ if ((w = getwchar()) != WEOF) {
+ display(&my_win, &w);
+ (void )fputwc(w, sockfp);
+ (void )fflush(sockfp);
+ }
+ }
+ }
+}
+
+/*
+ * p_error prints the system error message on the standard location
+ * on the screen and then exits. (i.e. a curses version of perror)
+ */
+void
+p_error(const char *string)
+{
+ wmove(my_win.x_win, current_line, 0);
+ wprintw(my_win.x_win, "[%s : %s (%d)]\n",
+ string, strerror(errno), errno);
+ wrefresh(my_win.x_win);
+ move(LINES-1, 0);
+ refresh();
+ quit();
+}
+
+/*
+ * Display string in the standard location
+ */
+void
+message(const char *string)
+{
+ wmove(my_win.x_win, current_line, 0);
+ wprintw(my_win.x_win, "[%s]\n", string);
+ if (current_line < my_win.x_nlines - 1)
+ current_line++;
+ wrefresh(my_win.x_win);
+}
diff --git a/usr.bin/talk/look_up.c b/usr.bin/talk/look_up.c
new file mode 100644
index 000000000000..739251a80dcb
--- /dev/null
+++ b/usr.bin/talk/look_up.c
@@ -0,0 +1,113 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <protocols/talkd.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "talk_ctl.h"
+#include "talk.h"
+
+/*
+ * See if the local daemon has an invitation for us.
+ */
+int
+check_local(void)
+{
+ CTL_RESPONSE response;
+ CTL_RESPONSE *rp = &response;
+ struct sockaddr addr;
+
+ /* the rest of msg was set up in get_names */
+ /* copy new style sockaddr to old, swap family (short in old) */
+ msg.ctl_addr = *(struct tsockaddr *)&ctl_addr;
+ msg.ctl_addr.sa_family = htons(ctl_addr.sin_family);
+ /* must be initiating a talk */
+ if (!look_for_invite(rp))
+ return (0);
+ /*
+ * There was an invitation waiting for us,
+ * so connect with the other (hopefully waiting) party
+ */
+ current_state = "Waiting to connect with caller";
+ do {
+ if (rp->addr.sa_family != AF_INET)
+ p_error("Response uses invalid network address");
+ (void)memcpy(&addr, &rp->addr.sa_family, sizeof(addr));
+ addr.sa_family = rp->addr.sa_family;
+ addr.sa_len = sizeof(addr);
+ errno = 0;
+ if (connect(sockt, &addr, sizeof(addr)) != -1)
+ return (1);
+ } while (errno == EINTR);
+ if (errno == ECONNREFUSED) {
+ /*
+ * The caller gave up, but his invitation somehow
+ * was not cleared. Clear it and initiate an
+ * invitation. (We know there are no newer invitations,
+ * the talkd works LIFO.)
+ */
+ ctl_transact(his_machine_addr, msg, DELETE, rp);
+ close(sockt);
+ open_sockt();
+ return (0);
+ }
+ p_error("Unable to connect with initiator");
+ /*NOTREACHED*/
+ return (0);
+}
+
+/*
+ * Look for an invitation on 'machine'
+ */
+int
+look_for_invite(CTL_RESPONSE *rp)
+{
+ current_state = "Checking for invitation on caller's machine";
+ ctl_transact(his_machine_addr, msg, LOOK_UP, rp);
+ /* the switch is for later options, such as multiple invitations */
+ switch (rp->answer) {
+
+ case SUCCESS:
+ msg.id_num = htonl(rp->id_num);
+ return (1);
+
+ default:
+ /* there wasn't an invitation waiting for us */
+ return (0);
+ }
+}
diff --git a/usr.bin/talk/msgs.c b/usr.bin/talk/msgs.c
new file mode 100644
index 000000000000..9d95a93a9529
--- /dev/null
+++ b/usr.bin/talk/msgs.c
@@ -0,0 +1,76 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+
+
+/*
+ * A package to display what is happening every MSG_INTERVAL seconds
+ * if we are slow connecting.
+ */
+
+#include <signal.h>
+
+#include "talk.h"
+
+#define MSG_INTERVAL 4
+
+const char *current_state;
+int current_line = 0;
+
+/* ARGSUSED */
+void
+disp_msg(int signo __unused)
+{
+ message(current_state);
+}
+
+void
+start_msgs(void)
+{
+ struct itimerval itimer;
+
+ message(current_state);
+ signal(SIGALRM, disp_msg);
+ itimer.it_value.tv_sec = itimer.it_interval.tv_sec = MSG_INTERVAL;
+ itimer.it_value.tv_usec = itimer.it_interval.tv_usec = 0;
+ setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+}
+
+void
+end_msgs(void)
+{
+ struct itimerval itimer;
+
+ timerclear(&itimer.it_value);
+ timerclear(&itimer.it_interval);
+ setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
+ signal(SIGALRM, SIG_DFL);
+}
diff --git a/usr.bin/talk/talk.1 b/usr.bin/talk/talk.1
new file mode 100644
index 000000000000..47f5f4f421c3
--- /dev/null
+++ b/usr.bin/talk/talk.1
@@ -0,0 +1,156 @@
+.\" Copyright (c) 1983, 1990, 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.
+.\"
+.Dd January 21, 2010
+.Dt TALK 1
+.Os
+.Sh NAME
+.Nm talk
+.Nd talk to another user
+.Sh SYNOPSIS
+.Nm
+.Ar person
+.Op Ar ttyname
+.Sh DESCRIPTION
+The
+.Nm
+utility is a visual communication program which copies lines from your
+terminal to that of another user.
+.Pp
+Options available:
+.Bl -tag -width ttyname
+.It Ar person
+If you wish to talk to someone on your own machine, then
+.Ar person
+is just the person's login name.
+If you wish to talk to a user on
+another host, then
+.Ar person
+is of the form
+.Ql user@host
+or
+.Ql host!user
+or
+.Ql host:user .
+.It Ar ttyname
+If you wish to talk to a user who is logged in more than once, the
+.Ar ttyname
+argument may be used to indicate the appropriate terminal
+name, where
+.Ar ttyname
+is of the form
+.Ql ttyXX .
+.El
+.Pp
+When first called,
+.Nm
+sends the message
+.Bd -literal -offset indent -compact
+Message from TalkDaemon@his_machine...
+talk: connection requested by your_name@your_machine.
+talk: respond with: talk your_name@your_machine
+.Ed
+.Pp
+to the user you wish to talk to.
+At this point, the recipient
+of the message should reply by typing
+.Pp
+.Dl talk \ your_name@your_machine
+.Pp
+It does not matter from which machine the recipient replies, as
+long as his login-name is the same.
+Once communication is established,
+the two parties may type simultaneously, with their output appearing
+in separate windows.
+Typing control-L
+.Ql ^L
+will cause the screen to
+be reprinted.
+Typing control-D
+.Ql ^D
+will clear both parts of your screen to be cleared, while
+the control-D character will be sent to the remote side
+(and just displayed by this
+.Nm
+client).
+Your erase, kill, and word kill characters will
+behave normally.
+To exit, just type your interrupt character;
+.Nm
+then moves the cursor to the bottom of the screen and restores the
+terminal to its previous state.
+.Pp
+Permission to talk may be denied or granted by use of the
+.Xr mesg 1
+command.
+At the outset talking is allowed.
+.Sh FILES
+.Bl -tag -width /var/run/utx.active -compact
+.It Pa /etc/hosts
+to find the recipient's machine
+.It Pa /var/run/utx.active
+to find the recipient's tty
+.El
+.Sh SEE ALSO
+.Xr mail 1 ,
+.Xr mesg 1 ,
+.Xr wall 1 ,
+.Xr who 1 ,
+.Xr write 1 ,
+.Xr talkd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Pp
+In
+.Fx 5.3 ,
+the default behaviour of
+.Nm
+was changed to treat local-to-local talk requests as originating
+and terminating at
+.Em localhost .
+Before this change, it was required that the hostname (as per
+.Xr gethostname 3 )
+resolved to a valid IPv4 address (via
+.Xr gethostbyname 3 ) ,
+making
+.Nm
+unsuitable for use in configurations where
+.Xr talkd 8
+was bound to the loopback interface (normally for security reasons).
+.Sh BUGS
+The version of
+.Nm
+released with
+.Bx 4.3
+uses a protocol that
+is incompatible with the protocol used in the version released with
+.Bx 4.2 .
+.Pp
+Multibyte characters are not recognized.
diff --git a/usr.bin/talk/talk.c b/usr.bin/talk/talk.c
new file mode 100644
index 000000000000..3aaa79373b32
--- /dev/null
+++ b/usr.bin/talk/talk.c
@@ -0,0 +1,70 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <locale.h>
+#include <unistd.h>
+
+#include "talk.h"
+
+/*
+ * talk: A visual form of write. Using sockets, a two way
+ * connection is set up between the two people talking.
+ * With the aid of curses, the screen is split into two
+ * windows, and each users text is added to the window,
+ * one character at a time...
+ *
+ * Written by Kipp Hickman
+ *
+ * Modified to run under 4.1a by Clem Cole and Peter Moore
+ * Modified to run between hosts by Peter Moore, 8/19/82
+ * Modified to run under 4.1c by Peter Moore 3/17/83
+ * Fixed to not run with unwriteable terminals MRVM 28/12/94
+ */
+
+int
+main(int argc, char **argv)
+{
+ (void) setlocale(LC_CTYPE, "");
+
+ get_names(argc, argv);
+ setproctitle(" ");
+ check_writeable();
+ init_display();
+ open_ctl();
+ open_sockt();
+ start_msgs();
+ if (!check_local())
+ invite_remote();
+ end_msgs();
+ set_edit_chars();
+ talk();
+ return 0;
+}
diff --git a/usr.bin/talk/talk.h b/usr.bin/talk/talk.h
new file mode 100644
index 000000000000..83852dfc46b4
--- /dev/null
+++ b/usr.bin/talk/talk.h
@@ -0,0 +1,92 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <protocols/talkd.h>
+#include <curses.h>
+#include <signal.h>
+
+extern int sockt;
+extern int curses_initialized;
+extern int invitation_waiting;
+
+extern const char *current_state;
+extern int current_line;
+
+extern volatile sig_atomic_t gotwinch;
+
+typedef struct xwin {
+ WINDOW *x_win;
+ int x_nlines;
+ int x_ncols;
+ int x_line;
+ int x_col;
+ char kill;
+ char cerase;
+ char werase;
+} xwin_t;
+
+extern xwin_t my_win;
+extern xwin_t his_win;
+extern WINDOW *line_win;
+
+extern void announce_invite(void);
+extern int check_local(void);
+extern void check_writeable(void);
+extern void ctl_transact(struct in_addr,CTL_MSG,int,CTL_RESPONSE *);
+extern void disp_msg(int);
+extern void end_msgs(void);
+extern void get_addrs(const char *, const char *);
+extern int get_iface(struct in_addr *, struct in_addr *);
+extern void get_names(int, char **);
+extern void init_display(void);
+extern void invite_remote(void);
+extern int look_for_invite(CTL_RESPONSE *);
+extern int max(int, int);
+extern void message(const char *);
+extern void open_ctl(void);
+extern void open_sockt(void);
+extern void p_error(const char *);
+extern void print_addr(struct sockaddr_in);
+extern void quit(void);
+extern int readwin(WINDOW *, int, int);
+extern void re_invite(int);
+extern void send_delete(void);
+extern void set_edit_chars(void);
+extern void sig_sent(int);
+extern void sig_winch(int);
+extern void start_msgs(void);
+extern void talk(void);
+extern void resize_display(void);
diff --git a/usr.bin/talk/talk_ctl.h b/usr.bin/talk/talk_ctl.h
new file mode 100644
index 000000000000..771685f3048e
--- /dev/null
+++ b/usr.bin/talk/talk_ctl.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+extern struct sockaddr_in daemon_addr;
+extern struct sockaddr_in ctl_addr;
+extern struct sockaddr_in my_addr;
+extern struct in_addr my_machine_addr;
+extern struct in_addr his_machine_addr;
+extern u_short daemon_port;
+extern int ctl_sockt;
+extern CTL_MSG msg;
diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile
new file mode 100644
index 000000000000..9260315fb30b
--- /dev/null
+++ b/usr.bin/tar/Makefile
@@ -0,0 +1,40 @@
+.include <src.opts.mk>
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+
+PACKAGE= runtime
+PROG= bsdtar
+BSDTAR_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.],,gp;q;}' \
+ ${_LIBARCHIVEDIR}/libarchive/archive.h
+
+.PATH: ${_LIBARCHIVEDIR}/tar
+SRCS= bsdtar.c \
+ cmdline.c \
+ creation_set.c \
+ read.c \
+ subst.c \
+ util.c \
+ write.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+SRCS+= err.c \
+ line_reader.c \
+ passphrase.c
+
+LIBADD= archive
+
+.if ${MK_ICONV} != "no"
+CFLAGS+= -DHAVE_ICONV=1 -DHAVE_ICONV_H=1 -DICONV_CONST=const
+.endif
+
+CFLAGS+= -DBSDTAR_VERSION_STRING=\"${BSDTAR_VERSION_STRING}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+= -I${_LIBARCHIVEDIR}/tar -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe
+SYMLINKS= bsdtar ${BINDIR}/tar
+MLINKS= bsdtar.1 tar.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tar/Makefile.depend b/usr.bin/tar/Makefile.depend
new file mode 100644
index 000000000000..850d785a03af
--- /dev/null
+++ b/usr.bin/tar/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tar/Makefile.depend.host b/usr.bin/tar/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tar/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tar/Makefile.depend.options b/usr.bin/tar/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/tar/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/tar/tests/Makefile b/usr.bin/tar/tests/Makefile
new file mode 100644
index 000000000000..e684ab6b8873
--- /dev/null
+++ b/usr.bin/tar/tests/Makefile
@@ -0,0 +1,130 @@
+PACKAGE= tests
+
+WARNS?= 3
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR= ${TESTSDIR}
+
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+= -I${_LIBARCHIVEDIR}/tar -I${_LIBARCHIVEDIR}/tar/test
+CFLAGS+= -I${_LIBARCHIVEDIR}/test_utils
+
+CFLAGS.test_utils.c+= -Wno-cast-align
+
+# Uncomment to link against dmalloc
+#LDADD+= -L/usr/local/lib -ldmalloc
+#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+
+PROGS+= bsdtar_test
+
+.PATH: ${_LIBARCHIVEDIR}/tar/test
+TESTS_SRCS= \
+ test_0.c \
+ test_basic.c \
+ test_copy.c \
+ test_empty_mtree.c \
+ test_extract_tar_bz2.c \
+ test_extract_tar_grz.c \
+ test_extract_tar_gz.c \
+ test_extract_tar_lrz.c \
+ test_extract_tar_lz.c \
+ test_extract_tar_lz4.c \
+ test_extract_tar_lzma.c \
+ test_extract_tar_lzo.c \
+ test_extract_tar_xz.c \
+ test_extract_tar_zstd.c \
+ test_format_newc.c \
+ test_help.c \
+ test_leading_slash.c \
+ test_missing_file.c \
+ test_option_C_mtree.c \
+ test_option_C_upper.c \
+ test_option_H_upper.c \
+ test_option_L_upper.c \
+ test_option_O_upper.c \
+ test_option_P.c \
+ test_option_T_upper.c \
+ test_option_U_upper.c \
+ test_option_X_upper.c \
+ test_option_a.c \
+ test_option_acls.c \
+ test_option_b.c \
+ test_option_b64encode.c \
+ test_option_exclude.c \
+ test_option_exclude_vcs.c \
+ test_option_fflags.c \
+ test_option_gid_gname.c \
+ test_option_grzip.c \
+ test_option_ignore_zeros.c \
+ test_option_j.c \
+ test_option_k.c \
+ test_option_keep_newer_files.c \
+ test_option_lrzip.c \
+ test_option_lz4.c \
+ test_option_lzma.c \
+ test_option_lzop.c \
+ test_option_n.c \
+ test_option_newer_than.c \
+ test_option_nodump.c \
+ test_option_older_than.c \
+ test_option_passphrase.c \
+ test_option_q.c \
+ test_option_r.c \
+ test_option_s.c \
+ test_option_safe_writes.c \
+ test_option_uid_uname.c \
+ test_option_uuencode.c \
+ test_option_xattrs.c \
+ test_option_xz.c \
+ test_option_z.c \
+ test_option_zstd.c \
+ test_patterns.c \
+ test_print_longpath.c \
+ test_stdio.c \
+ test_strip_components.c \
+ test_symlink_dir.c \
+ test_version.c
+
+SRCS.bsdtar_test= \
+ ${TESTS_SRCS} \
+ list.h
+
+.PATH: ${_LIBARCHIVEDIR}/test_utils
+SRCS.bsdtar_test+= test_main.c \
+ test_utils.c
+
+LIBADD.bsdtar_test= archive
+
+list.h: ${TESTS_SRCS} Makefile
+ @(cd ${_LIBARCHIVEDIR}/tar/test && \
+ grep -h DEFINE_TEST ${.ALLSRC:N*Makefile}) > ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+CLEANFILES+= list.h list.h.tmp
+
+${PACKAGE}FILES+= test_extract.tar.Z.uu
+${PACKAGE}FILES+= test_extract.tar.bz2.uu
+${PACKAGE}FILES+= test_extract.tar.grz.uu
+${PACKAGE}FILES+= test_extract.tar.gz.uu
+${PACKAGE}FILES+= test_extract.tar.lrz.uu
+${PACKAGE}FILES+= test_extract.tar.lz.uu
+${PACKAGE}FILES+= test_extract.tar.lz4.uu
+${PACKAGE}FILES+= test_extract.tar.lzma.uu
+${PACKAGE}FILES+= test_extract.tar.lzo.uu
+${PACKAGE}FILES+= test_extract.tar.xz.uu
+${PACKAGE}FILES+= test_extract.tar.zst.uu
+${PACKAGE}FILES+= test_leading_slash.tar.uu
+${PACKAGE}FILES+= test_option_keep_newer_files.tar.Z.uu
+${PACKAGE}FILES+= test_option_passphrase.zip.uu
+${PACKAGE}FILES+= test_option_s.tar.Z.uu
+${PACKAGE}FILES+= test_patterns_2.tar.uu
+${PACKAGE}FILES+= test_patterns_3.tar.uu
+${PACKAGE}FILES+= test_patterns_4.tar.uu
+${PACKAGE}FILES+= test_print_longpath.tar.Z.uu
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tar/tests/Makefile.depend b/usr.bin/tar/tests/Makefile.depend
new file mode 100644
index 000000000000..5f5ceeb3eee7
--- /dev/null
+++ b/usr.bin/tar/tests/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tar/tests/functional_test.sh b/usr.bin/tar/tests/functional_test.sh
new file mode 100755
index 000000000000..39a73abd0a79
--- /dev/null
+++ b/usr.bin/tar/tests/functional_test.sh
@@ -0,0 +1,50 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+export BSDTAR=$(which tar)
+SRCDIR=$(atf_get_srcdir)
+TESTER="${SRCDIR}/bsdtar_test"
+
+check()
+{
+ local testcase=${1}; shift
+
+ atf_check -o ignore -s exit:0 ${TESTER} -d -r "${SRCDIR}" -v "${testcase}"
+}
+
+atf_init_test_cases()
+{
+ # Redirect stderr to stdout for the usage message because if you don't
+ # kyua list/kyua test will break:
+ # https://github.com/jmmv/kyua/issues/149
+ testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }')
+ for testcase in ${testcases}; do
+ atf_test_case ${testcase}
+ eval "${testcase}_body() { check ${testcase}; }"
+ atf_add_test_case ${testcase}
+ done
+}
diff --git a/usr.bin/tcopy/Makefile b/usr.bin/tcopy/Makefile
new file mode 100644
index 000000000000..73dcd45b2e0f
--- /dev/null
+++ b/usr.bin/tcopy/Makefile
@@ -0,0 +1,4 @@
+PROG= tcopy
+LIBADD= util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tcopy/Makefile.depend b/usr.bin/tcopy/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/tcopy/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tcopy/tcopy.1 b/usr.bin/tcopy/tcopy.1
new file mode 100644
index 000000000000..3f12a807e41e
--- /dev/null
+++ b/usr.bin/tcopy/tcopy.1
@@ -0,0 +1,132 @@
+.\" Copyright (c) 1985, 1990, 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.
+.\"
+.Dd December 20, 2006
+.Dt TCOPY 1
+.Os
+.Sh NAME
+.Nm tcopy
+.Nd copy and/or verify mag tapes
+.Sh SYNOPSIS
+.Nm
+.Op Fl cvx
+.Op Fl s Ar maxblk
+.Oo Ar src Op Ar dest
+.Oc
+.Sh DESCRIPTION
+The
+.Nm
+utility is designed to copy magnetic tapes.
+The only assumption made
+about the tape layout is that there are two sequential EOF marks
+at the end.
+By default, the
+.Nm
+utility will print
+information about the sizes of records and files found
+on the
+.Pa /dev/sa0
+tape, or on the tape specified by the
+.Ar src
+argument.
+If a destination tape is also specified by the
+.Ar dest
+argument, a copy of the source tape will be made.
+The blocking on the
+destination tape will be identical to that used on the source tape.
+Copying
+a tape will yield the same program output as if just printing the sizes.
+.Pp
+The following options are available:
+.Bl -tag -width ".Fl s Ar maxblk"
+.It Fl c
+Copy
+.Ar src
+to
+.Ar dest
+and then verify that the two tapes are identical.
+.It Fl s Ar maxblk
+Specify a maximum block size,
+.Ar maxblk .
+.It Fl v
+Given the two tapes
+.Ar src
+and
+.Ar dest ,
+verify that they are identical.
+.It Fl x
+Output all informational messages to the standard error
+instead of the standard output.
+This option is useful when
+.Ar dest
+is given as
+.Pa /dev/stdout .
+.El
+.Sh SEE ALSO
+.Xr mt 1 ,
+.Xr mtio 4
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Sh BUGS
+.Bl -item
+.It
+Modern tape drives may return a SCSI "Incorrect Length Indicator (ILI)"
+for each read with a different block size that what is on the
+tape, and that slows things down a lot.
+This can be disabled with the
+.Xr mt 1
+command:
+.Bd -literal -offset indent
+$ mt param sili -s 1
+.Ed
+.It
+Writing an image of a tape to a file does not preserve much more than
+the raw data.
+Block size(s) and tape EOF marks are lost which would
+otherwise be preserved in a tape-to-tape copy.
+.It
+End of data (EOD) is determined by two sequential EOF marks
+with no data between them.
+There used to be old systems which typically wrote three EOF's between tape
+files.
+The
+.Nm
+utility will erroneously stop copying early in this case.
+.It
+When using the copy/verify option
+.Fl c ,
+.Nm
+does not rewind the tapes prior to start.
+A rewind is performed
+after writing, prior to the verification stage.
+If one does not start
+at the beginning-of-tape (BOT) then the comparison
+may not be of the intended data.
+.El
diff --git a/usr.bin/tcopy/tcopy.c b/usr.bin/tcopy/tcopy.c
new file mode 100644
index 000000000000..39eae4126324
--- /dev/null
+++ b/usr.bin/tcopy/tcopy.c
@@ -0,0 +1,338 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1985, 1987, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libutil.h>
+#include <paths.h>
+#include <sys/sysctl.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAXREC (64 * 1024)
+#define NOCOUNT (-2)
+
+static int filen, guesslen, maxblk = MAXREC;
+static uint64_t lastrec, record, size, tsize;
+static FILE *msg;
+
+static void *getspace(int);
+static void intr(int);
+static void usage(void) __dead2;
+static void verify(int, int, char *);
+static void writeop(int, int);
+static void rewind_tape(int);
+
+int
+main(int argc, char *argv[])
+{
+ int lastnread, nread, nw, inp, outp;
+ enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
+ sig_t oldsig;
+ int ch, needeof;
+ char *buff;
+ const char *inf;
+ unsigned long maxphys = 0;
+ size_t l_maxphys = sizeof maxphys;
+ uint64_t tmp;
+
+ if (!sysctlbyname("kern.maxphys", &maxphys, &l_maxphys, NULL, 0))
+ maxblk = maxphys;
+
+ msg = stdout;
+ guesslen = 1;
+ outp = -1;
+ while ((ch = getopt(argc, argv, "cs:vx")) != -1)
+ switch((char)ch) {
+ case 'c':
+ op = COPYVERIFY;
+ break;
+ case 's':
+ if (expand_number(optarg, &tmp)) {
+ warnx("illegal block size");
+ usage();
+ }
+ maxblk = tmp;
+ if (maxblk == 0) {
+ warnx("illegal block size");
+ usage();
+ }
+ guesslen = 0;
+ break;
+ case 'v':
+ op = VERIFY;
+ break;
+ case 'x':
+ msg = stderr;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch(argc) {
+ case 0:
+ if (op != READ)
+ usage();
+ inf = _PATH_DEFTAPE;
+ break;
+ case 1:
+ if (op != READ)
+ usage();
+ inf = argv[0];
+ break;
+ case 2:
+ if (op == READ)
+ op = COPY;
+ inf = argv[0];
+ if ((outp = open(argv[1], op == VERIFY ? O_RDONLY :
+ op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0)
+ err(3, "%s", argv[1]);
+ break;
+ default:
+ usage();
+ }
+
+ if ((inp = open(inf, O_RDONLY, 0)) < 0)
+ err(1, "%s", inf);
+
+ buff = getspace(maxblk);
+
+ if (op == VERIFY) {
+ verify(inp, outp, buff);
+ exit(0);
+ }
+
+ if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
+ (void) signal(SIGINT, intr);
+
+ needeof = 0;
+ for (lastnread = NOCOUNT;;) {
+ if ((nread = read(inp, buff, maxblk)) == -1) {
+ while (errno == EINVAL && (maxblk -= 1024)) {
+ nread = read(inp, buff, maxblk);
+ if (nread >= 0)
+ goto r1;
+ }
+ err(1, "read error, file %d, record %ju", filen, (intmax_t)record);
+ } else if (nread != lastnread) {
+ if (lastnread != 0 && lastnread != NOCOUNT) {
+ if (lastrec == 0 && nread == 0)
+ fprintf(msg, "%ju records\n", (intmax_t)record);
+ else if (record - lastrec > 1)
+ fprintf(msg, "records %ju to %ju\n",
+ (intmax_t)lastrec, (intmax_t)record);
+ else
+ fprintf(msg, "record %ju\n", (intmax_t)lastrec);
+ }
+ if (nread != 0)
+ fprintf(msg, "file %d: block size %d: ",
+ filen, nread);
+ (void) fflush(stdout);
+ lastrec = record;
+ }
+r1: guesslen = 0;
+ if (nread > 0) {
+ if (op == COPY || op == COPYVERIFY) {
+ if (needeof) {
+ writeop(outp, MTWEOF);
+ needeof = 0;
+ }
+ nw = write(outp, buff, nread);
+ if (nw != nread) {
+ if (nw == -1) {
+ warn("write error, file %d, record %ju", filen,
+ (intmax_t)record);
+ } else {
+ warnx("write error, file %d, record %ju", filen,
+ (intmax_t)record);
+ warnx("write (%d) != read (%d)", nw, nread);
+ }
+ errx(5, "copy aborted");
+ }
+ }
+ size += nread;
+ record++;
+ } else {
+ if (lastnread <= 0 && lastnread != NOCOUNT) {
+ fprintf(msg, "eot\n");
+ break;
+ }
+ fprintf(msg,
+ "file %d: eof after %ju records: %ju bytes\n",
+ filen, (intmax_t)record, (intmax_t)size);
+ needeof = 1;
+ filen++;
+ tsize += size;
+ size = record = lastrec = 0;
+ lastnread = 0;
+ }
+ lastnread = nread;
+ }
+ fprintf(msg, "total length: %ju bytes\n", (intmax_t)tsize);
+ (void)signal(SIGINT, oldsig);
+ if (op == COPY || op == COPYVERIFY) {
+ writeop(outp, MTWEOF);
+ writeop(outp, MTWEOF);
+ if (op == COPYVERIFY) {
+ rewind_tape(outp);
+ rewind_tape(inp);
+ verify(inp, outp, buff);
+ }
+ }
+ exit(0);
+}
+
+static void
+verify(int inp, int outp, char *outb)
+{
+ int eot, inmaxblk, inn, outmaxblk, outn;
+ char *inb;
+
+ inb = getspace(maxblk);
+ inmaxblk = outmaxblk = maxblk;
+ for (eot = 0;; guesslen = 0) {
+ if ((inn = read(inp, inb, inmaxblk)) == -1) {
+ if (guesslen)
+ while (errno == EINVAL && (inmaxblk -= 1024)) {
+ inn = read(inp, inb, inmaxblk);
+ if (inn >= 0)
+ goto r1;
+ }
+ warn("read error");
+ break;
+ }
+r1: if ((outn = read(outp, outb, outmaxblk)) == -1) {
+ if (guesslen)
+ while (errno == EINVAL && (outmaxblk -= 1024)) {
+ outn = read(outp, outb, outmaxblk);
+ if (outn >= 0)
+ goto r2;
+ }
+ warn("read error");
+ break;
+ }
+r2: if (inn != outn) {
+ fprintf(msg,
+ "%s: tapes have different block sizes; %d != %d.\n",
+ "tcopy", inn, outn);
+ break;
+ }
+ if (!inn) {
+ if (eot++) {
+ fprintf(msg, "tcopy: tapes are identical.\n");
+ free(inb);
+ return;
+ }
+ } else {
+ if (bcmp(inb, outb, inn)) {
+ fprintf(msg,
+ "tcopy: tapes have different data.\n");
+ break;
+ }
+ eot = 0;
+ }
+ }
+ exit(1);
+}
+
+static void
+intr(int signo __unused)
+{
+ if (record) {
+ if (record - lastrec > 1)
+ fprintf(msg, "records %ju to %ju\n", (intmax_t)lastrec, (intmax_t)record);
+ else
+ fprintf(msg, "record %ju\n", (intmax_t)lastrec);
+ }
+ fprintf(msg, "interrupt at file %d: record %ju\n", filen, (intmax_t)record);
+ fprintf(msg, "total length: %ju bytes\n", (uintmax_t)(tsize + size));
+ exit(1);
+}
+
+static void *
+getspace(int blk)
+{
+ void *bp;
+
+ if ((bp = malloc((size_t)blk)) == NULL)
+ errx(11, "no memory");
+ return (bp);
+}
+
+static void
+writeop(int fd, int type)
+{
+ struct mtop op;
+
+ op.mt_op = type;
+ op.mt_count = (daddr_t)1;
+ if (ioctl(fd, MTIOCTOP, (char *)&op) < 0)
+ err(6, "tape op");
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] [src [dest]]\n");
+ exit(1);
+}
+
+static void
+rewind_tape(int fd)
+{
+ struct stat sp;
+
+ if(fstat(fd, &sp))
+ errx(12, "fstat in rewind");
+
+ /*
+ * don't want to do tape ioctl on regular files:
+ */
+ if( S_ISREG(sp.st_mode) ) {
+ if( lseek(fd, 0, SEEK_SET) == -1 )
+ errx(13, "lseek");
+ } else
+ /* assume its a tape */
+ writeop(fd, MTREW);
+}
diff --git a/usr.bin/tee/Makefile b/usr.bin/tee/Makefile
new file mode 100644
index 000000000000..ab7b93575967
--- /dev/null
+++ b/usr.bin/tee/Makefile
@@ -0,0 +1,3 @@
+PROG= tee
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tee/Makefile.depend b/usr.bin/tee/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/tee/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tee/tee.1 b/usr.bin/tee/tee.1
new file mode 100644
index 000000000000..9497a2aa921e
--- /dev/null
+++ b/usr.bin/tee/tee.1
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd October 30, 2022
+.Dt TEE 1
+.Os
+.Sh NAME
+.Nm tee
+.Nd duplicate standard input
+.Sh SYNOPSIS
+.Nm
+.Op Fl ai
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility copies standard input to standard output,
+making a copy in zero or more files.
+The output is unbuffered.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+Append the output to the files rather than
+overwriting them.
+.It Fl i
+Ignore the
+.Dv SIGINT
+signal.
+.El
+.Pp
+The following operands are available:
+.Bl -tag -width indent
+.It Ar file
+A pathname of an output
+.Ar file .
+.El
+.Pp
+The
+.Nm
+utility takes the default action for all signals,
+except in the event of the
+.Fl i
+option.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Send the echoed message both to stdout and to the
+.Pa greetings.txt
+file:
+.Bd -literal -offset indent
+$ echo "Hello" | tee greetings.txt
+Hello
+.Ed
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.At v7 .
diff --git a/usr.bin/tee/tee.c b/usr.bin/tee/tee.c
new file mode 100644
index 000000000000..384fabf40f33
--- /dev/null
+++ b/usr.bin/tee/tee.c
@@ -0,0 +1,146 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct entry {
+ int fd;
+ const char *name;
+ STAILQ_ENTRY(entry) entries;
+};
+static STAILQ_HEAD(, entry) head = STAILQ_HEAD_INITIALIZER(head);
+
+static void add(int, const char *);
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ struct entry *p;
+ int n, fd, rval, wval;
+ char *bp;
+ int append, ch, exitval;
+ char *buf;
+#define BSIZE (8 * 1024)
+
+ append = 0;
+ while ((ch = getopt(argc, argv, "ai")) != -1)
+ switch((char)ch) {
+ case 'a':
+ append = 1;
+ break;
+ case 'i':
+ (void)signal(SIGINT, SIG_IGN);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ if ((buf = malloc(BSIZE)) == NULL)
+ err(1, "malloc");
+
+ if (caph_limit_stdin() == -1 || caph_limit_stderr() == -1)
+ err(EXIT_FAILURE, "unable to limit stdio");
+
+ add(STDOUT_FILENO, "stdout");
+
+ for (exitval = 0; *argv; ++argv)
+ if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND :
+ O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) {
+ warn("%s", *argv);
+ exitval = 1;
+ } else
+ add(fd, *argv);
+
+ if (caph_enter() < 0)
+ err(EXIT_FAILURE, "unable to enter capability mode");
+ while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0)
+ STAILQ_FOREACH(p, &head, entries) {
+ n = rval;
+ bp = buf;
+ do {
+ if ((wval = write(p->fd, bp, n)) == -1) {
+ warn("%s", p->name);
+ exitval = 1;
+ break;
+ }
+ bp += wval;
+ } while (n -= wval);
+ }
+ if (rval < 0)
+ err(1, "read");
+ exit(exitval);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n");
+ exit(1);
+}
+
+static void
+add(int fd, const char *name)
+{
+ struct entry *p;
+ cap_rights_t rights;
+
+ if (fd == STDOUT_FILENO) {
+ if (caph_limit_stdout() == -1)
+ err(EXIT_FAILURE, "unable to limit stdout");
+ } else {
+ cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT);
+ if (caph_rights_limit(fd, &rights) < 0)
+ err(EXIT_FAILURE, "unable to limit rights");
+ }
+
+ if ((p = malloc(sizeof(struct entry))) == NULL)
+ err(1, "malloc");
+ p->fd = fd;
+ p->name = name;
+ STAILQ_INSERT_HEAD(&head, p, entries);
+}
diff --git a/usr.bin/telnet/Makefile b/usr.bin/telnet/Makefile
new file mode 100644
index 000000000000..930d70faa8ba
--- /dev/null
+++ b/usr.bin/telnet/Makefile
@@ -0,0 +1,38 @@
+.include <src.opts.mk>
+
+PACKAGE= telnet
+
+TELNETDIR= ${SRCTOP}/contrib/telnet
+.PATH: ${TELNETDIR}/telnet
+
+PROG= telnet
+
+SRCS= commands.c main.c network.c ring.c sys_bsd.c \
+ telnet.c terminal.c utilities.c
+
+CFLAGS+= -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK -DOPIE \
+ -I${TELNETDIR} -I${TELNETDIR}/libtelnet/
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+
+WARNS?= 2
+
+LIBADD= telnet tinfow
+
+CFLAGS+= -DIPSEC
+LIBADD+= ipsec
+
+.if ${MK_OPENSSL} != "no"
+SRCS+= authenc.c
+CFLAGS+= -DENCRYPTION -DAUTHENTICATION -DIPSEC
+LIBADD+= mp crypto ipsec pam
+.endif
+
+.if ${MK_KERBEROS_SUPPORT} != "no"
+CFLAGS+= -DKRB5 -DFORWARD -Dnet_write=telnet_net_write
+LIBADD+= krb5 roken
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/telnet/Makefile.depend b/usr.bin/telnet/Makefile.depend
new file mode 100644
index 000000000000..b7b44b914ba8
--- /dev/null
+++ b/usr.bin/telnet/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libtelnet \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/telnet/Makefile.depend.options b/usr.bin/telnet/Makefile.depend.options
new file mode 100644
index 000000000000..785c9903c5b3
--- /dev/null
+++ b/usr.bin/telnet/Makefile.depend.options
@@ -0,0 +1,10 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= KERBEROS_SUPPORT OPENSSL
+
+DIRDEPS.OPENSSL.yes= \
+ lib/libipsec \
+ lib/libmp \
+ lib/libpam/libpam \
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/tests/Makefile b/usr.bin/tests/Makefile
new file mode 100644
index 000000000000..e513e315473c
--- /dev/null
+++ b/usr.bin/tests/Makefile
@@ -0,0 +1,8 @@
+PACKAGE= tests
+
+.PATH: ${SRCTOP}/tests
+KYUAFILE= yes
+
+${PACKAGE}FILES+= regress.m4
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tests/Makefile.depend b/usr.bin/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tests/regress.m4 b/usr.bin/tests/regress.m4
new file mode 100644
index 000000000000..9288518915bb
--- /dev/null
+++ b/usr.bin/tests/regress.m4
@@ -0,0 +1,58 @@
+
+dnl A library of routines for doing regression tests for userland utilities.
+
+dnl Start up. We initialise the exit status to 0 (no failure) and change
+dnl into the directory specified by our first argument, which is the
+dnl directory to run the tests inside.
+define(`REGRESSION_START',
+TESTDIR=$1
+if [ -z "$TESTDIR" ]; then
+ TESTDIR=.
+fi
+cd $TESTDIR
+
+STATUS=0)
+
+dnl Check $? to see if we passed or failed. The first parameter is the test
+dnl which passed or failed. It may be nil.
+define(`REGRESSION_PASSFAIL',
+if [ $? -eq 0 ]; then
+ echo "ok - $1 # Test detected no regression. (in $TESTDIR)"
+else
+ STATUS=$?
+ echo "not ok - $1 # Test failed: regression detected. See above. (in $TESTDIR)"
+fi)
+
+dnl An actual test. The first parameter is the test name. The second is the
+dnl command/commands to execute for the actual test. Their exit status is
+dnl checked. It is assumed that the test will output to stdout, and that the
+dnl output to be used to check for regression will be in regress.TESTNAME.out.
+define(`REGRESSION_TEST',
+$2 | diff -u ${SRCDIR:-.}/regress.$1.out -
+REGRESSION_PASSFAIL($1))
+
+dnl A freeform regression test. Only exit status is checked.
+define(`REGRESSION_TEST_FREEFORM',
+$2
+REGRESSION_PASSFAIL($1))
+
+dnl A regression test like REGRESSION_TEST, except only regress.out is used
+dnl for checking output differences. The first argument is the command, the
+dnl second argument (which may be empty) is the test name.
+define(`REGRESSION_TEST_ONE',
+$1 | diff -u ${SRCDIR:-.}/regress.out -
+REGRESSION_PASSFAIL($2))
+
+dnl A fatal error. This will exit with the given status (first argument) and
+dnl print the message (second argument) prefixed with the string "FATAL :" to
+dnl the error stream.
+define(`REGRESSION_FATAL',
+echo "Bail out! $2 (in $TESTDIR)" > /dev/stderr
+exit $1)
+
+dnl Cleanup. Exit with the status code of the last failure. Should probably
+dnl be the number of failed tests, but hey presto, this is what it does. This
+dnl could also clean up potential droppings, if some forms of regression tests
+dnl end up using mktemp(1) or such.
+define(`REGRESSION_END',
+exit $STATUS)
diff --git a/usr.bin/tftp/Makefile b/usr.bin/tftp/Makefile
new file mode 100644
index 000000000000..952246d3fd5d
--- /dev/null
+++ b/usr.bin/tftp/Makefile
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+.PATH: ${SRCTOP}/libexec/tftpd
+
+PROG= tftp
+SRCS= main.c tftp-file.c tftp-io.c tftp-options.c tftp-transfer.c
+SRCS+= tftp-utils.c tftp.c
+CFLAGS+=-I${SRCTOP}/libexec/tftpd
+
+LIBADD= edit
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tftp/Makefile.depend b/usr.bin/tftp/Makefile.depend
new file mode 100644
index 000000000000..771ed4075eda
--- /dev/null
+++ b/usr.bin/tftp/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libedit \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c
new file mode 100644
index 000000000000..8e36c9e04f9b
--- /dev/null
+++ b/usr.bin/tftp/main.c
@@ -0,0 +1,1087 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
+
+/*
+ * TFTP User Program -- Command Interface.
+ */
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/tftp.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <histedit.h>
+#include <netdb.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tftp-utils.h"
+#include "tftp-io.h"
+#include "tftp-options.h"
+#include "tftp.h"
+
+#define MAXLINE (2 * MAXPATHLEN)
+#define TIMEOUT 5 /* secs between rexmt's */
+
+typedef struct sockaddr_storage peeraddr;
+static int connected;
+static char mode[32];
+static jmp_buf toplevel;
+static int txrx_error;
+static int peer;
+
+#define MAX_MARGV 20
+static int margc;
+static char *margv[MAX_MARGV];
+
+int verbose;
+static char *port = NULL;
+
+static void get(int, char **);
+static void help(int, char **);
+static void intr(int);
+static void modecmd(int, char **);
+static void put(int, char **);
+static void quit(int, char **);
+static void setascii(int, char **);
+static void setbinary(int, char **);
+static void setpeer0(char *, const char *);
+static void setpeer(int, char **);
+static void settimeoutpacket(int, char **);
+static void settimeoutnetwork(int, char **);
+static void setdebug(int, char **);
+static void setverbose(int, char **);
+static void showstatus(int, char **);
+static void setblocksize(int, char **);
+static void setblocksize2(int, char **);
+static void setoptions(int, char **);
+static void setrollover(int, char **);
+static void setpacketdrop(int, char **);
+static void setwindowsize(int, char **);
+
+static void command(bool, EditLine *, History *, HistEvent *) __dead2;
+static const char *command_prompt(void);
+
+static void urihandling(char *URI);
+static void getusage(char *);
+static void makeargv(char *line);
+static void putusage(char *);
+static void settftpmode(const char *);
+
+static char *tail(char *);
+static const struct cmd *getcmd(const char *);
+
+#define HELPINDENT (sizeof("connect"))
+
+struct cmd {
+ const char *name;
+ void (*handler)(int, char **);
+ const char *help;
+};
+
+static struct cmd cmdtab[] = {
+ { "connect", setpeer, "connect to remote tftp" },
+ { "mode", modecmd, "set file transfer mode" },
+ { "put", put, "send file" },
+ { "get", get, "receive file" },
+ { "quit", quit, "exit tftp" },
+ { "verbose", setverbose, "toggle verbose mode" },
+ { "status", showstatus, "show current status" },
+ { "binary", setbinary, "set mode to octet" },
+ { "ascii", setascii, "set mode to netascii" },
+ { "rexmt", settimeoutpacket,
+ "set per-packet retransmission timeout[-]" },
+ { "timeout", settimeoutnetwork,
+ "set total retransmission timeout" },
+ { "trace", setdebug, "enable 'debug packet'[-]" },
+ { "debug", setdebug, "enable verbose output" },
+ { "blocksize", setblocksize, "set blocksize[*]" },
+ { "blocksize2", setblocksize2, "set blocksize as a power of 2[**]" },
+ { "rollover", setrollover, "rollover after 64K packets[**]" },
+ { "options", setoptions,
+ "enable or disable RFC2347 style options" },
+ { "help", help, "print help information" },
+ { "packetdrop", setpacketdrop, "artificial packetloss feature" },
+ { "windowsize", setwindowsize, "set windowsize[*]" },
+ { "?", help, "print help information" },
+ { NULL, NULL, NULL }
+};
+
+static struct modes {
+ const char *m_name;
+ const char *m_mode;
+} modes[] = {
+ { "ascii", "netascii" },
+ { "netascii", "netascii" },
+ { "binary", "octet" },
+ { "image", "octet" },
+ { "octet", "octet" },
+ { NULL, NULL }
+};
+
+int
+main(int argc, char *argv[])
+{
+ HistEvent he;
+ static EditLine *el;
+ static History *hist;
+ bool interactive;
+
+ acting_as_client = 1;
+ peer = -1;
+ strcpy(mode, "octet");
+ signal(SIGINT, intr);
+
+ interactive = isatty(STDIN_FILENO);
+ if (interactive) {
+ el = el_init("tftp", stdin, stdout, stderr);
+ hist = history_init();
+ history(hist, &he, H_SETSIZE, 100);
+ el_set(el, EL_HIST, history, hist);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_PROMPT, command_prompt);
+ el_set(el, EL_SIGNAL, 1);
+ el_source(el, NULL);
+ }
+
+ if (argc > 1) {
+ if (setjmp(toplevel) != 0)
+ exit(txrx_error);
+
+ if (strncmp(argv[1], "tftp://", 7) == 0) {
+ urihandling(argv[1]);
+ exit(txrx_error);
+ }
+
+ setpeer(argc, argv);
+ }
+
+ if (setjmp(toplevel) != 0) {
+ if (interactive)
+ el_reset(el);
+ (void)putchar('\n');
+ }
+
+ init_options();
+ command(interactive, el, hist, &he);
+}
+
+/*
+ * RFC3617 handling of TFTP URIs:
+ *
+ * tftpURI = "tftp://" host "/" file [ mode ]
+ * mode = ";" "mode=" ( "netascii" / "octet" )
+ * file = *( unreserved / escaped )
+ * host = <as specified by RFC 2732>
+ * unreserved = <as specified in RFC 2396>
+ * escaped = <as specified in RFC 2396>
+ *
+ * We are cheating a little bit by allowing any mode as specified in the
+ * modes table defined earlier on in this file and mapping it on the real
+ * mode.
+ */
+static void
+urihandling(char *URI)
+{
+ char uri[ARG_MAX];
+ char *host = NULL;
+ char *path = NULL;
+ char *opts = NULL;
+ const char *tmode = "octet";
+ char *s;
+ char line[MAXLINE];
+ int i;
+
+ strlcpy(uri, URI, ARG_MAX);
+ host = uri + 7;
+
+ if ((s = strchr(host, '/')) == NULL) {
+ fprintf(stderr,
+ "Invalid URI: Couldn't find / after hostname\n");
+ exit(1);
+ }
+ *s = '\0';
+ path = s + 1;
+
+ if ((s = strchr(path, ';')) != NULL) {
+ *s = '\0';
+ opts = s + 1;
+
+ if (strncmp(opts, "mode=", 5) == 0) {
+ tmode = opts;
+ tmode += 5;
+
+ for (i = 0; modes[i].m_name != NULL; i++) {
+ if (strcmp(modes[i].m_name, tmode) == 0)
+ break;
+ }
+ if (modes[i].m_name == NULL) {
+ fprintf(stderr, "Invalid mode: '%s'\n", mode);
+ exit(1);
+ }
+ settftpmode(modes[i].m_mode);
+ }
+ } else {
+ settftpmode("octet");
+ }
+
+ setpeer0(host, NULL);
+
+ sprintf(line, "get %s", path);
+ makeargv(line);
+ get(margc, margv);
+}
+
+static char hostname[MAXHOSTNAMELEN];
+
+static void
+setpeer0(char *host, const char *lport)
+{
+ struct addrinfo hints, *res0, *res;
+ int error;
+ const char *cause = "unknown";
+
+ if (connected) {
+ close(peer);
+ peer = -1;
+ }
+ connected = 0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_CANONNAME;
+ if (!lport)
+ lport = "tftp";
+ error = getaddrinfo(host, lport, &hints, &res0);
+ if (error) {
+ warnx("%s", gai_strerror(error));
+ return;
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ if (res->ai_addrlen > sizeof(peeraddr))
+ continue;
+ peer = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (peer < 0) {
+ cause = "socket";
+ continue;
+ }
+
+ memset(&peer_sock, 0, sizeof(peer_sock));
+ peer_sock.ss_family = res->ai_family;
+ peer_sock.ss_len = res->ai_addrlen;
+ if (bind(peer, (struct sockaddr *)&peer_sock, peer_sock.ss_len) < 0) {
+ cause = "bind";
+ close(peer);
+ peer = -1;
+ continue;
+ }
+
+ break;
+ }
+
+ if (peer < 0)
+ warn("%s", cause);
+ else {
+ /* res->ai_addr <= sizeof(peeraddr) is guaranteed */
+ memcpy(&peer_sock, res->ai_addr, res->ai_addrlen);
+ if (res->ai_canonname) {
+ (void) strlcpy(hostname, res->ai_canonname,
+ sizeof(hostname));
+ } else
+ (void) strlcpy(hostname, host, sizeof(hostname));
+ connected = 1;
+ }
+
+ freeaddrinfo(res0);
+}
+
+static void
+setpeer(int argc, char *argv[])
+{
+ char line[MAXLINE];
+
+ if (argc < 2) {
+ strcpy(line, "Connect ");
+ printf("(to) ");
+ fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
+ makeargv(line);
+ argc = margc;
+ argv = margv;
+ }
+ if ((argc < 2) || (argc > 3)) {
+ printf("usage: %s [host [port]]\n", argv[0]);
+ return;
+ }
+ if (argc == 3) {
+ port = argv[2];
+ setpeer0(argv[1], argv[2]);
+ } else
+ setpeer0(argv[1], NULL);
+}
+
+static void
+modecmd(int argc, char *argv[])
+{
+ struct modes *p;
+ const char *sep;
+
+ if (argc < 2) {
+ printf("Using %s mode to transfer files.\n", mode);
+ return;
+ }
+ if (argc == 2) {
+ for (p = modes; p->m_name; p++)
+ if (strcmp(argv[1], p->m_name) == 0)
+ break;
+ if (p->m_name) {
+ settftpmode(p->m_mode);
+ return;
+ }
+ printf("%s: unknown mode\n", argv[1]);
+ /* drop through and print usage message */
+ }
+
+ printf("usage: %s [", argv[0]);
+ sep = " ";
+ for (p = modes; p->m_name != NULL; p++) {
+ printf("%s%s", sep, p->m_name);
+ if (*sep == ' ')
+ sep = " | ";
+ }
+ printf(" ]\n");
+ return;
+}
+
+static void
+setbinary(int argc __unused, char *argv[] __unused)
+{
+
+ settftpmode("octet");
+}
+
+static void
+setascii(int argc __unused, char *argv[] __unused)
+{
+
+ settftpmode("netascii");
+}
+
+static void
+settftpmode(const char *newmode)
+{
+
+ strlcpy(mode, newmode, sizeof(mode));
+ if (verbose)
+ printf("mode set to %s\n", mode);
+}
+
+
+/*
+ * Send file(s).
+ */
+static void
+put(int argc, char *argv[])
+{
+ int fd;
+ int n;
+ char *cp, *targ, *path;
+ char line[MAXLINE];
+ struct stat sb;
+
+ if (argc < 2) {
+ strcpy(line, "send ");
+ printf("(file) ");
+ fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
+ makeargv(line);
+ argc = margc;
+ argv = margv;
+ }
+ if (argc < 2) {
+ putusage(argv[0]);
+ return;
+ }
+ targ = argv[argc - 1];
+ if (strrchr(argv[argc - 1], ':')) {
+ char *lcp;
+
+ for (n = 1; n < argc - 1; n++)
+ if (strchr(argv[n], ':')) {
+ putusage(argv[0]);
+ return;
+ }
+ lcp = argv[argc - 1];
+ targ = strrchr(lcp, ':');
+ *targ++ = 0;
+ if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
+ lcp[strlen(lcp) - 1] = '\0';
+ lcp++;
+ }
+ setpeer0(lcp, NULL);
+ }
+ if (!connected) {
+ printf("No target machine specified.\n");
+ return;
+ }
+ if (argc < 4) {
+ cp = argc == 2 ? tail(targ) : argv[1];
+ fd = open(cp, O_RDONLY);
+ if (fd < 0) {
+ warn("%s", cp);
+ return;
+ }
+
+ if (fstat(fd, &sb) < 0) {
+ warn("%s", cp);
+ close(fd);
+ return;
+ }
+ options_set_request(OPT_TSIZE, "%ju", (uintmax_t)sb.st_size);
+
+ if (verbose)
+ printf("putting %s to %s:%s [%s]\n",
+ cp, hostname, targ, mode);
+ if (xmitfile(peer, port, fd, targ, mode))
+ txrx_error = 1;
+ close(fd);
+ return;
+ }
+ /* this assumes the target is a directory */
+ /* on a remote unix system. hmmmm. */
+ for (n = 1; n < argc - 1; n++) {
+ if (asprintf(&path, "%s/%s", targ, tail(argv[n])) < 0)
+ err(1, "malloc");
+
+ fd = open(argv[n], O_RDONLY);
+ if (fd < 0) {
+ warn("%s", argv[n]);
+ free(path);
+ continue;
+ }
+
+ if (fstat(fd, &sb) < 0) {
+ warn("%s", argv[n]);
+ close(fd);
+ free(path);
+ continue;
+ }
+ options_set_request(OPT_TSIZE, "%ju", (uintmax_t)sb.st_size);
+
+ if (verbose)
+ printf("putting %s to %s:%s [%s]\n",
+ argv[n], hostname, path, mode);
+ if (xmitfile(peer, port, fd, path, mode) != 0)
+ txrx_error = 1;
+ close(fd);
+
+ free(path);
+ }
+}
+
+static void
+putusage(char *s)
+{
+
+ printf("usage: %s file [remotename]\n", s);
+ printf(" %s file host:remotename\n", s);
+ printf(" %s file1 file2 ... fileN [[host:]remote-directory]\n", s);
+}
+
+/*
+ * Receive file(s).
+ */
+static void
+get(int argc, char *argv[])
+{
+ int fd;
+ int n;
+ char *cp;
+ char *src;
+ char line[MAXLINE];
+
+ if (argc < 2) {
+ strcpy(line, "get ");
+ printf("(files) ");
+ fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
+ makeargv(line);
+ argc = margc;
+ argv = margv;
+ }
+ if (argc < 2) {
+ getusage(argv[0]);
+ return;
+ }
+ if (!connected) {
+ for (n = 1; n < argc ; n++)
+ if (strrchr(argv[n], ':') == 0) {
+ printf("No remote host specified and "
+ "no host given for file '%s'\n", argv[n]);
+ getusage(argv[0]);
+ return;
+ }
+ }
+ for (n = 1; n < argc ; n++) {
+ src = strrchr(argv[n], ':');
+ if (src == NULL)
+ src = argv[n];
+ else {
+ char *lcp;
+
+ *src++ = 0;
+ lcp = argv[n];
+ if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
+ lcp[strlen(lcp) - 1] = '\0';
+ lcp++;
+ }
+ setpeer0(lcp, NULL);
+ if (!connected)
+ continue;
+ }
+ if (argc < 4) {
+ cp = argc == 3 ? argv[2] : tail(src);
+ fd = creat(cp, 0644);
+ if (fd < 0) {
+ warn("%s", cp);
+ return;
+ }
+ if (verbose)
+ printf("getting from %s:%s to %s [%s]\n",
+ hostname, src, cp, mode);
+ if (recvfile(peer, port, fd, src, mode) != 0)
+ txrx_error = 1;
+ break;
+ }
+ cp = tail(src); /* new .. jdg */
+ fd = creat(cp, 0644);
+ if (fd < 0) {
+ warn("%s", cp);
+ continue;
+ }
+ if (verbose)
+ printf("getting from %s:%s to %s [%s]\n",
+ hostname, src, cp, mode);
+ if (recvfile(peer, port, fd, src, mode) != 0)
+ txrx_error = 1;
+ }
+}
+
+static void
+getusage(char *s)
+{
+
+ printf("usage: %s file [localname]\n", s);
+ printf(" %s [host:]file [localname]\n", s);
+ printf(" %s [host1:]file1 [host2:]file2 ... [hostN:]fileN\n", s);
+}
+
+static void
+settimeoutpacket(int argc, char *argv[])
+{
+ int t;
+ char line[MAXLINE];
+
+ if (argc < 2) {
+ strcpy(line, "Packet timeout ");
+ printf("(value) ");
+ fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
+ makeargv(line);
+ argc = margc;
+ argv = margv;
+ }
+ if (argc != 2) {
+ printf("usage: %s value\n", argv[0]);
+ return;
+ }
+ t = atoi(argv[1]);
+ if (t < 0) {
+ printf("%s: bad value\n", argv[1]);
+ return;
+ }
+
+ settimeouts(t, timeoutnetwork, maxtimeouts);
+}
+
+static void
+settimeoutnetwork(int argc, char *argv[])
+{
+ int t;
+ char line[MAXLINE];
+
+ if (argc < 2) {
+ strcpy(line, "Network timeout ");
+ printf("(value) ");
+ fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
+ makeargv(line);
+ argc = margc;
+ argv = margv;
+ }
+ if (argc != 2) {
+ printf("usage: %s value\n", argv[0]);
+ return;
+ }
+ t = atoi(argv[1]);
+ if (t < 0) {
+ printf("%s: bad value\n", argv[1]);
+ return;
+ }
+
+ settimeouts(timeoutpacket, t, maxtimeouts);
+}
+
+static void
+showstatus(int argc __unused, char *argv[] __unused)
+{
+
+ printf("Remote host: %s\n",
+ connected ? hostname : "none specified yet");
+ printf("RFC2347 Options support: %s\n",
+ options_rfc_enabled ? "enabled" : "disabled");
+ printf("Non-RFC defined options support: %s\n",
+ options_extra_enabled ? "enabled" : "disabled");
+ printf("Mode: %s\n", mode);
+ printf("Verbose: %s\n", verbose ? "on" : "off");
+ printf("Debug: %s\n", debug_show(debug));
+ printf("Artificial packetloss: %d in 100 packets\n",
+ packetdroppercentage);
+ printf("Segment size: %d bytes\n", segsize);
+ printf("Network timeout: %d seconds\n", timeoutpacket);
+ printf("Maximum network timeout: %d seconds\n", timeoutnetwork);
+ printf("Maximum timeouts: %d \n", maxtimeouts);
+}
+
+static void
+intr(int dummy __unused)
+{
+
+ signal(SIGALRM, SIG_IGN);
+ alarm(0);
+ longjmp(toplevel, -1);
+}
+
+static char *
+tail(char *filename)
+{
+ char *s;
+
+ while (*filename) {
+ s = strrchr(filename, '/');
+ if (s == NULL)
+ break;
+ if (s[1])
+ return (s + 1);
+ *s = '\0';
+ }
+ return (filename);
+}
+
+static const char *
+command_prompt(void)
+{
+
+ return ("tftp> ");
+}
+
+/*
+ * Command parser.
+ */
+static void
+command(bool interactive, EditLine *el, History *hist, HistEvent *hep)
+{
+ const struct cmd *c;
+ const char *bp;
+ char *cp;
+ int len, num;
+ char line[MAXLINE];
+
+ for (;;) {
+ if (interactive) {
+ if ((bp = el_gets(el, &num)) == NULL || num == 0)
+ exit(0);
+ len = MIN(MAXLINE, num);
+ memcpy(line, bp, len);
+ line[len - 1] = '\0';
+ history(hist, hep, H_ENTER, bp);
+ } else {
+ line[0] = 0;
+ if (fgets(line, sizeof line , stdin) == NULL) {
+ if (feof(stdin)) {
+ exit(txrx_error);
+ } else {
+ continue;
+ }
+ }
+ }
+ if ((cp = strchr(line, '\n')))
+ *cp = '\0';
+ if (line[0] == 0)
+ continue;
+ makeargv(line);
+ if (margc == 0)
+ continue;
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == NULL) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ (*c->handler)(margc, margv);
+ }
+}
+
+static const struct cmd *
+getcmd(const char *name)
+{
+ const char *p, *q;
+ const struct cmd *c, *found;
+ ptrdiff_t longest;
+ int nmatches;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; (p = c->name) != NULL; c++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == '\0') /* exact match? */
+ return (c);
+ if (*q == '\0') { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return ((struct cmd *)-1);
+ return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+static void
+makeargv(char *line)
+{
+ char *cp;
+ char **argp = margv;
+
+ margc = 0;
+ if ((cp = strchr(line, '\n')) != NULL)
+ *cp = '\0';
+ for (cp = line; margc < MAX_MARGV - 1 && *cp != '\0';) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ while (*cp != '\0' && !isspace(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ *cp++ = '\0';
+ }
+ *argp++ = 0;
+}
+
+static void
+quit(int argc __unused, char *argv[] __unused)
+{
+
+ exit(txrx_error);
+}
+
+/*
+ * Help command.
+ */
+static void
+help(int argc, char *argv[])
+{
+ const struct cmd *c;
+
+ if (argc == 1) {
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c->name; c++)
+ printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
+
+ printf("\n[-] : You shouldn't use these ones anymore.\n");
+ printf("[*] : RFC2347 options support required.\n");
+ printf("[**] : Non-standard RFC2347 option.\n");
+ return;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command: %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command: %s\n", arg);
+ else
+ printf("%s\n", c->help);
+ }
+}
+
+static void
+setverbose(int argc __unused, char *argv[] __unused)
+{
+
+ verbose = !verbose;
+ printf("Verbose mode %s.\n", verbose ? "on" : "off");
+}
+
+static void
+setoptions(int argc, char *argv[])
+{
+
+ if (argc == 2) {
+ if (strcasecmp(argv[1], "enable") == 0 ||
+ strcasecmp(argv[1], "on") == 0) {
+ options_extra_enabled = 1;
+ options_rfc_enabled = 1;
+ }
+ if (strcasecmp(argv[1], "disable") == 0 ||
+ strcasecmp(argv[1], "off") == 0) {
+ options_extra_enabled = 0;
+ options_rfc_enabled = 0;
+ }
+ if (strcasecmp(argv[1], "extra") == 0)
+ options_extra_enabled = !options_extra_enabled;
+ }
+ printf("Support for RFC2347 style options are now %s.\n",
+ options_rfc_enabled ? "enabled" : "disabled");
+ printf("Support for non-RFC defined options are now %s.\n",
+ options_extra_enabled ? "enabled" : "disabled");
+
+ printf("\nThe following options are available:\n"
+ "\toptions on : enable support for RFC2347 style options\n"
+ "\toptions off : disable support for RFC2347 style options\n"
+ "\toptions extra : toggle support for non-RFC defined options\n"
+ );
+}
+
+static void
+setrollover(int argc, char *argv[])
+{
+
+ if (argc == 2) {
+ if (strcasecmp(argv[1], "never") == 0 ||
+ strcasecmp(argv[1], "none") == 0) {
+ options_set_request(OPT_ROLLOVER, NULL);
+ }
+ if (strcasecmp(argv[1], "1") == 0) {
+ options_set_request(OPT_ROLLOVER, "1");
+ }
+ if (strcasecmp(argv[1], "0") == 0) {
+ options_set_request(OPT_ROLLOVER, "0");
+ }
+ }
+ printf("Support for the rollover options is %s.\n",
+ options[OPT_ROLLOVER].o_request != NULL ? "enabled" : "disabled");
+ if (options[OPT_ROLLOVER].o_request != NULL)
+ printf("Block rollover will be to block %s.\n",
+ options[OPT_ROLLOVER].o_request);
+
+
+ printf("\nThe following rollover options are available:\n"
+ "\trollover 0 : rollover to block zero (default)\n"
+ "\trollover 1 : rollover to block one\n"
+ "\trollover never : do not support the rollover option\n"
+ "\trollover none : do not support the rollover option\n"
+ );
+}
+
+static void
+setdebug(int argc, char *argv[])
+{
+ int i;
+
+ if (argc != 1) {
+ i = 1;
+ while (i < argc)
+ debug ^= debug_find(argv[i++]);
+ }
+ printf("The following debugging is enabled: %s\n", debug_show(debug));
+
+ printf("\nThe following debugs are available:\n");
+ i = 0;
+ while (debugs[i].name != NULL) {
+ printf("\t%s\t%s\n", debugs[i].name, debugs[i].desc);
+ i++;
+ }
+}
+
+static void
+setblocksize(int argc, char *argv[])
+{
+
+ if (!options_rfc_enabled)
+ printf("RFC2347 style options are not enabled "
+ "(but proceeding anyway)\n");
+
+ if (argc != 1) {
+ int size = atoi(argv[1]);
+ size_t max;
+ u_long maxdgram;
+
+ max = sizeof(maxdgram);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ &maxdgram, &max, NULL, 0) < 0) {
+ perror("sysctl: net.inet.udp.maxdgram");
+ return;
+ }
+
+ if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) {
+ printf("Blocksize should be between %d and %d bytes.\n",
+ BLKSIZE_MIN, BLKSIZE_MAX);
+ return;
+ } else if (size > (int)maxdgram - 4) {
+ printf("Blocksize can't be bigger than %ld bytes due "
+ "to the net.inet.udp.maxdgram sysctl limitation.\n",
+ maxdgram - 4);
+ options_set_request(OPT_BLKSIZE, "%ld", maxdgram - 4);
+ } else {
+ options_set_request(OPT_BLKSIZE, "%d", size);
+ }
+ }
+ printf("Blocksize is now %s bytes.\n", options[OPT_BLKSIZE].o_request);
+}
+
+static void
+setblocksize2(int argc, char *argv[])
+{
+
+ if (!options_rfc_enabled || !options_extra_enabled)
+ printf(
+ "RFC2347 style or non-RFC defined options are not enabled "
+ "(but proceeding anyway)\n");
+
+ if (argc != 1) {
+ int size = atoi(argv[1]);
+ int i;
+ size_t max;
+ u_long maxdgram;
+
+ int sizes[] = {
+ 8, 16, 32, 64, 128, 256, 512, 1024,
+ 2048, 4096, 8192, 16384, 32768, 0
+ };
+
+ max = sizeof(maxdgram);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ &maxdgram, &max, NULL, 0) < 0) {
+ perror("sysctl: net.inet.udp.maxdgram");
+ return;
+ }
+
+ for (i = 0; sizes[i] != 0; i++) {
+ if (sizes[i] == size) break;
+ }
+ if (sizes[i] == 0) {
+ printf("Blocksize2 should be a power of two between "
+ "8 and 32768.\n");
+ return;
+ }
+
+ if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) {
+ printf("Blocksize2 should be between "
+ "%d and %d bytes.\n", BLKSIZE_MIN, BLKSIZE_MAX);
+ return;
+ } else if (size > (int)maxdgram - 4) {
+ printf("Blocksize2 can't be bigger than %ld bytes due "
+ "to the net.inet.udp.maxdgram sysctl limitation.\n",
+ maxdgram - 4);
+ for (i = 0; sizes[i+1] != 0; i++) {
+ if ((int)maxdgram < sizes[i+1]) break;
+ }
+ options_set_request(OPT_BLKSIZE2, "%d", sizes[i]);
+ } else {
+ options_set_request(OPT_BLKSIZE2, "%d", size);
+ }
+ }
+ printf("Blocksize2 is now %s bytes.\n",
+ options[OPT_BLKSIZE2].o_request);
+}
+
+static void
+setpacketdrop(int argc, char *argv[])
+{
+
+ if (argc != 1)
+ packetdroppercentage = atoi(argv[1]);
+
+ printf("Randomly %d in 100 packets will be dropped\n",
+ packetdroppercentage);
+}
+
+static void
+setwindowsize(int argc, char *argv[])
+{
+
+ if (!options_rfc_enabled)
+ printf("RFC2347 style options are not enabled "
+ "(but proceeding anyway)\n");
+
+ if (argc != 1) {
+ int size = atoi(argv[1]);
+
+ if (size < WINDOWSIZE_MIN || size > WINDOWSIZE_MAX) {
+ printf("Windowsize should be between %d and %d "
+ "blocks.\n", WINDOWSIZE_MIN, WINDOWSIZE_MAX);
+ return;
+ } else {
+ options_set_request(OPT_WINDOWSIZE, "%d", size);
+ }
+ }
+ printf("Windowsize is now %s blocks.\n",
+ options[OPT_WINDOWSIZE].o_request);
+}
diff --git a/usr.bin/tftp/tests/Makefile b/usr.bin/tftp/tests/Makefile
new file mode 100644
index 000000000000..9d6d6c0bc874
--- /dev/null
+++ b/usr.bin/tftp/tests/Makefile
@@ -0,0 +1,8 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= tftp_test
+BINDIR= ${TESTSDIR}
+
+TEST_METADATA.tftp_test+= is_exclusive="true"
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tftp/tests/Makefile.depend b/usr.bin/tftp/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tftp/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tftp/tests/tftp_test.sh b/usr.bin/tftp/tests/tftp_test.sh
new file mode 100644
index 000000000000..a4c9f3b898e7
--- /dev/null
+++ b/usr.bin/tftp/tests/tftp_test.sh
@@ -0,0 +1,465 @@
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+tftp_dir="${TMPDIR:-/tmp}/tftp.dir"
+inetd_conf="${TMPDIR:-/tmp}/inetd.conf"
+inetd_pid="${TMPDIR:-/tmp}/inetd.pid"
+
+start_tftpd() {
+ if ! [ -z "$(sockstat -PUDP -p69 -q)" ] ; then
+ atf_skip "the tftp port is in use"
+ fi
+ echo "starting inetd for $(atf_get ident)" >&2
+ rm -rf "${tftp_dir}"
+ mkdir "${tftp_dir}"
+ cat >"${inetd_conf}" <<EOF
+tftp dgram udp wait root /usr/libexec/tftpd tftpd -d15 -l ${tftp_dir}
+tftp dgram udp6 wait root /usr/libexec/tftpd tftpd -d15 -l ${tftp_dir}
+EOF
+ /usr/sbin/inetd -a localhost -p "${inetd_pid}" "${inetd_conf}"
+}
+
+stop_tftpd() {
+ echo "stopping inetd for $(atf_get ident)" >&2
+ # Send SIGTERM to inetd, then SIGKILL until it's gone
+ local sig=TERM
+ while pkill -$sig -LF "${inetd_pid}" inetd ; do
+ echo "waiting for inetd to stop" >&2
+ sleep 1
+ sig=KILL
+ done
+ rm -rf "${tftp_dir}" "${inetd_conf}" "${inetd_pid}"
+}
+
+atf_test_case tftp_get_big cleanup
+tftp_get_big_head() {
+ atf_set "descr" "get command with big file"
+ atf_set "require.user" "root"
+}
+tftp_get_big_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/remote.bin"
+ dd if=/dev/urandom of="${remote_file}" bs=1m count=16 status=none
+ local local_file="local.bin"
+ echo "get ${remote_file##*/} ${local_file}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_big_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_host cleanup
+tftp_get_host_head() {
+ atf_set "descr" "get command with host name"
+ atf_set "require.user" "root"
+}
+tftp_get_host_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ echo "get localhost:${remote_file##*/}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_host_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_ipv4 cleanup
+tftp_get_ipv4_head() {
+ atf_set "descr" "get command with ipv4 address"
+ atf_set "require.user" "root"
+}
+tftp_get_ipv4_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ echo "get 127.0.0.1:${remote_file##*/}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_ipv4_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_ipv6 cleanup
+tftp_get_ipv6_head() {
+ atf_set "descr" "get command with ipv6 address"
+ atf_set "require.user" "root"
+}
+tftp_get_ipv6_body() {
+ sysctl -q kern.features.inet6 || atf_skip "This test requires IPv6 support"
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ echo "get [::1]:${remote_file##*/}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_ipv6_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_one cleanup
+tftp_get_one_head() {
+ atf_set "descr" "get command with one argument"
+ atf_set "require.user" "root"
+}
+tftp_get_one_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ echo "get ${remote_file##*/}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_one_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_two cleanup
+tftp_get_two_head() {
+ atf_set "descr" "get command with two arguments"
+ atf_set "require.user" "root"
+}
+tftp_get_two_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="world.txt"
+ echo "get ${remote_file##*/} ${local_file}" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_get_two_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_more cleanup
+tftp_get_more_head() {
+ atf_set "descr" "get command with three or more arguments"
+ atf_set "require.user" "root"
+}
+tftp_get_more_body() {
+ start_tftpd
+ for n in 3 4 5 6 7 ; do
+ echo -n "get" >client-script
+ for f in $(jot -c $n 97) ; do
+ echo "test file $$/$f/$n" >"${tftp_dir}/${f}.txt"
+ echo -n " ${f}.txt" >>client-script
+ rm -f "${f}.txt"
+ done
+ echo >>client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp localhost <client-script
+ for f in $(jot -c $n 97) ; do
+ atf_check cmp -s "${f}.txt" "${tftp_dir}/${f}.txt"
+ done
+ done
+}
+tftp_get_more_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_get_multi_host cleanup
+tftp_get_multi_host_head() {
+ atf_set "descr" "get command with multiple files and host name"
+ atf_set "require.user" "root"
+}
+tftp_get_multi_host_body() {
+ start_tftpd
+ for f in a b c ; do
+ echo "test file $$/$f/$n" >"${tftp_dir}/${f}.txt"
+ rm -f "${f}.txt"
+ done
+ echo "get localhost:a.txt b.txt c.txt" >client-script
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp localhost <client-script
+ for f in a b c ; do
+ atf_check cmp -s "${f}.txt" "${tftp_dir}/${f}.txt"
+ done
+}
+tftp_get_multi_host_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_big cleanup
+tftp_put_big_head() {
+ atf_set "descr" "put command with big file"
+ atf_set "require.user" "root"
+}
+tftp_put_big_body() {
+ start_tftpd
+ local local_file="local.bin"
+ dd if=/dev/urandom of="${local_file}" bs=1m count=16 status=none
+ local remote_file="${tftp_dir}/random.bin"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file} ${remote_file##*/}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_big_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_host cleanup
+tftp_put_host_head() {
+ atf_set "descr" "put command with host name"
+ atf_set "require.user" "root"
+}
+tftp_put_host_body() {
+ start_tftpd
+ local local_file="local.txt"
+ echo "test file $$" >"${local_file}"
+ local remote_file="${tftp_dir}/remote.txt"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file} localhost:${remote_file##*/}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_host_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_ipv4 cleanup
+tftp_put_ipv4_head() {
+ atf_set "descr" "put command with ipv4 address"
+ atf_set "require.user" "root"
+}
+tftp_put_ipv4_body() {
+ start_tftpd
+ local local_file="local.txt"
+ echo "test file $$" >"${local_file}"
+ local remote_file="${tftp_dir}/remote.txt"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file} 127.0.0.1:${remote_file##*/}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_ipv4_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_ipv6 cleanup
+tftp_put_ipv6_head() {
+ atf_set "descr" "put command with ipv6 address"
+ atf_set "require.user" "root"
+}
+tftp_put_ipv6_body() {
+ sysctl -q kern.features.inet6 || atf_skip "This test requires IPv6 support"
+ start_tftpd
+ local local_file="local.txt"
+ echo "test file $$" >"${local_file}"
+ local remote_file="${tftp_dir}/remote.txt"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file} [::1]:${remote_file##*/}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_ipv6_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_one cleanup
+tftp_put_one_head() {
+ atf_set "descr" "put command with one argument"
+ atf_set "require.user" "root"
+}
+tftp_put_one_body() {
+ start_tftpd
+ local local_file="file.txt"
+ echo "test file $$" >"${local_file}"
+ local remote_file="${tftp_dir}/${local_file}"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_one_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_two cleanup
+tftp_put_two_head() {
+ atf_set "descr" "put command with two arguments"
+ atf_set "require.user" "root"
+}
+tftp_put_two_body() {
+ start_tftpd
+ local local_file="local.txt"
+ echo "test file $$" >"${local_file}"
+ local remote_file="${tftp_dir}/remote.txt"
+ truncate -s 0 "${remote_file}"
+ chown nobody:nogroup "${remote_file}"
+ chmod 0666 "${remote_file}"
+ echo "put ${local_file} ${remote_file##*/}" >client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp localhost <client-script
+ atf_check cmp -s "${remote_file}" "${local_file}"
+}
+tftp_put_two_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_more cleanup
+tftp_put_more_head() {
+ atf_set "descr" "put command with three or more arguments"
+ atf_set "require.user" "root"
+}
+tftp_put_more_body() {
+ start_tftpd
+ mkdir "${tftp_dir}/subdir"
+ for n in 2 3 4 5 6 ; do
+ echo -n "put" >client-script
+ for f in $(jot -c $n 97) ; do
+ echo "test file $$/$f/$n" >"${f}.txt"
+ truncate -s 0 "${tftp_dir}/subdir/${f}.txt"
+ chown nobody:nogroup "${tftp_dir}/subdir/${f}.txt"
+ chmod 0666 "${tftp_dir}/subdir/${f}.txt"
+ echo -n " ${f}.txt" >>client-script
+ done
+ echo " subdir" >>client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp localhost <client-script
+ for f in $(jot -c $n 97) ; do
+ atf_check cmp -s "${tftp_dir}/subdir/${f}.txt" "${f}.txt"
+ done
+ done
+}
+tftp_put_more_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_put_multi_host cleanup
+tftp_put_multi_host_head() {
+ atf_set "descr" "put command with multiple files and host name"
+ atf_set "require.user" "root"
+}
+tftp_put_multi_host_body() {
+ start_tftpd
+ mkdir "${tftp_dir}/subdir"
+ echo -n "put" >client-script
+ for f in a b c ; do
+ echo "test file $$/$f" >"${f}.txt"
+ truncate -s 0 "${tftp_dir}/subdir/${f}.txt"
+ chown nobody:nogroup "${tftp_dir}/subdir/${f}.txt"
+ chmod 0666 "${tftp_dir}/subdir/${f}.txt"
+ echo -n " ${f}.txt" >>client-script
+ done
+ echo " localhost:subdir" >>client-script
+ atf_check -o match:"Sent [0-9]+ bytes" \
+ tftp <client-script
+ for f in a b c ; do
+ atf_check cmp -s "${tftp_dir}/subdir/${f}.txt" "${f}.txt"
+ done
+}
+tftp_put_multi_host_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_url_host cleanup
+tftp_url_host_head() {
+ atf_set "descr" "URL with hostname"
+ atf_set "require.user" "root"
+}
+tftp_url_host_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp tftp://localhost/"${remote_file##*/}"
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_url_host_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_url_ipv4 cleanup
+tftp_url_ipv4_head() {
+ atf_set "descr" "URL with IPv4 address"
+ atf_set "require.user" "root"
+}
+tftp_url_ipv4_body() {
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp tftp://127.0.0.1/"${remote_file##*/}"
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_url_ipv4_cleanup() {
+ stop_tftpd
+}
+
+atf_test_case tftp_url_ipv6 cleanup
+tftp_url_ipv6_head() {
+ atf_set "descr" "URL with IPv6 address"
+ atf_set "require.user" "root"
+}
+tftp_url_ipv6_body() {
+ sysctl -q kern.features.inet6 || atf_skip "This test requires IPv6 support"
+ atf_expect_fail "tftp does not support bracketed IPv6 literals in URLs"
+ start_tftpd
+ local remote_file="${tftp_dir}/hello.txt"
+ echo "Hello, $$!" >"${remote_file}"
+ local local_file="${remote_file##*/}"
+ atf_check -o match:"Received [0-9]+ bytes" \
+ tftp tftp://"[::1]"/"${remote_file##*/}"
+ atf_check cmp -s "${local_file}" "${remote_file}"
+}
+tftp_url_ipv6_cleanup() {
+ stop_tftpd
+}
+
+atf_init_test_cases() {
+ atf_add_test_case tftp_get_big
+ atf_add_test_case tftp_get_host
+ atf_add_test_case tftp_get_ipv4
+ atf_add_test_case tftp_get_ipv6
+ atf_add_test_case tftp_get_one
+ atf_add_test_case tftp_get_two
+ atf_add_test_case tftp_get_more
+ atf_add_test_case tftp_get_multi_host
+ atf_add_test_case tftp_put_big
+ atf_add_test_case tftp_put_host
+ atf_add_test_case tftp_put_ipv4
+ atf_add_test_case tftp_put_ipv6
+ atf_add_test_case tftp_put_one
+ atf_add_test_case tftp_put_two
+ atf_add_test_case tftp_put_more
+ atf_add_test_case tftp_put_multi_host
+ atf_add_test_case tftp_url_host
+ atf_add_test_case tftp_url_ipv4
+ atf_add_test_case tftp_url_ipv6
+}
diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1
new file mode 100644
index 000000000000..8e9c3a2178af
--- /dev/null
+++ b/usr.bin/tftp/tftp.1
@@ -0,0 +1,284 @@
+.\" Copyright (c) 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd March 2, 2020
+.Dt TFTP 1
+.Os
+.Sh NAME
+.Nm tftp
+.Nd trivial file transfer program
+.Sh SYNOPSIS
+.Nm
+.Op Ar host Op Ar port
+.Sh DESCRIPTION
+The
+.Nm
+utility is the user interface to the Internet
+.Tn TFTP
+(Trivial File Transfer Protocol),
+which allows users to transfer files to and from a remote machine.
+The remote
+.Ar host
+may be specified on the command line, in which case
+.Nm
+uses
+.Ar host
+as the default host for future transfers (see the
+.Cm connect
+command below).
+.Sh COMMANDS
+Once
+.Nm
+is running, it issues the prompt
+.Dq Li tftp>
+and recognizes the following commands:
+.Pp
+.Bl -tag -width verbose -compact
+.It Cm \&? Ar command-name ...
+Print help information.
+.Pp
+.It Cm ascii
+Shorthand for "mode ascii"
+.Pp
+.It Cm binary
+Shorthand for "mode binary"
+.Pp
+.It Cm blocksize Ar [size]
+Sets the TFTP blksize option in TFTP Read Request or Write Request packets
+to
+.Ar [size]
+as specified in RFC 2348.
+Valid values are between 8 and 65464.
+If no blocksize is specified, then by default a blocksize of 512 bytes
+will be used.
+.Pp
+.It Cm blocksize2 Ar [size]
+Sets the TFTP blksize2 option in TFTP Read Request or Write Request packets
+to
+.Ar [size] .
+Values are restricted to powers of 2 between 8 and 32768.
+This is a non-standard TFTP option.
+.Pp
+.It Cm connect Ar host Op Ar port
+Set the
+.Ar host
+(and optionally
+.Ar port )
+for transfers.
+Note that the
+.Tn TFTP
+protocol, unlike the
+.Tn FTP
+protocol,
+does not maintain connections between transfers; thus, the
+.Cm connect
+command does not actually create a connection,
+but merely remembers what host is to be used for transfers.
+You do not have to use the
+.Cm connect
+command; the remote host can be specified as part of the
+.Cm get
+or
+.Cm put
+commands.
+.Pp
+.It Cm debug Ar level
+Enable or disable debugging levels during verbose output.
+The value of
+.Ar level
+can be one of
+.Cm packet , simple , options ,
+or
+.Cm access .
+.Pp
+.It Cm get Oo Ar host : Oc Ns Ar file Op Ar localname
+.It Cm get Xo
+.Oo Ar host1 : Oc Ns Ar file1
+.Oo Ar host2 : Oc Ns Ar file2 ...
+.Oo Ar hostN : Oc Ns Ar fileN
+.Xc
+Get one or more files from the remote host.
+When using the
+.Ar host
+argument, the
+.Ar host
+will be used as default host for future transfers.
+If
+.Ar localname
+is specified, the file is stored locally as
+.Ar localname ,
+otherwise the original filename is used.
+Note that it is not possible to download two files at a time, only
+one, three, or more than three files, at a time.
+.Pp
+To specify an IPv6 numeric address for a host, wrap it using square
+brackets like
+.Dq Li [3ffe:2900:e00c:ffee::1234] : Ns Ar file
+to disambiguate the
+colons used in the IPv6 address from the colon separating the host and
+the filename.
+.Pp
+.It Cm mode Ar transfer-mode
+Set the mode for transfers;
+.Ar transfer-mode
+may be one of
+.Em ascii
+or
+.Em binary .
+The default is
+.Em binary .
+.Pp
+.It Cm packetdrop [arg]
+Randomly drop
+.Ar arg
+out of 100 packets during a transfer.
+This is a debugging feature.
+.Pp
+.It Cm put Ar file Op Oo Ar host : Oc Ns Ar remotename
+.It Cm put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory
+Put a file or set of files to the remote host.
+When
+.Ar remotename
+is specified, the file is stored remotely as
+.Ar remotename ,
+otherwise the original filename is used.
+If the
+.Ar remote-directory
+argument is used, the remote host is assumed to be a
+.Ux
+machine.
+To specify an IPv6 numeric address for a
+.Ar host ,
+see the example under the
+.Cm get
+command.
+.Pp
+.It Cm options Ar [arg]
+Enable or disable support for TFTP options.
+The valid values of
+.Ar arg
+are
+.Cm on
+(enable RFC 2347 options),
+.Cm off
+(disable RFC 2347 options), and
+.Cm extra
+(toggle support for non-RFC defined options).
+.Pp
+.It Cm quit
+Exit
+.Nm .
+An end of file also exits.
+.Pp
+.It Cm rexmt Ar retransmission-timeout
+Set the per-packet retransmission timeout, in seconds.
+.Pp
+.It Cm rollover [arg]
+Specify the rollover option in TFTP Read Request or Write
+Request packets.
+After 65535 packets have been transmitted, set the block counter to
+.Ar arg .
+Valid values of
+.Ar arg
+are 0 and 1. This is a non-standard TFTP option.
+.Pp
+.It Cm status
+Show current status.
+.Pp
+.It Cm timeout Ar total-transmission-timeout
+Set the total transmission timeout, in seconds.
+.Pp
+.It Cm trace
+Toggle packet tracing.
+.Pp
+.It Cm verbose
+Toggle verbose mode.
+.Pp
+.It Cm windowsize Op Ar size
+Sets the TFTP windowsize option in TFTP Read Request or Write Request packets to
+.Op Ar size
+blocks as specified in RFC 7440.
+Valid values are between 1 and 65535.
+If no windowsize is specified,
+then the default windowsize of 1 block will be used.
+.El
+.Sh SEE ALSO
+.Xr tftpd 8
+.Pp
+The following RFC's are supported:
+.Rs
+.%T RFC 1350: The TFTP Protocol (Revision 2)
+.Re
+.Rs
+.%T RFC 2347: TFTP Option Extension
+.Re
+.Rs
+.%T RFC 2348: TFTP Blocksize Option
+.Re
+.Rs
+.%T RFC 2349: TFTP Timeout Interval and Transfer Size Options
+.Re
+.Rs
+.%T RFC 3617: Uniform Resource Identifier (URI) Scheme and Applicability Statement for the Trivial File Transfer Protocol (TFTP)
+.Re
+.Rs
+.%T RFC 7440: TFTP Windowsize Option
+.Re
+.Pp
+The non-standard
+.Cm rollover
+and
+.Cm blksize2
+TFTP options are mentioned here:
+.Rs
+.%T Extending TFTP
+.%U https://www.compuphase.com/tftp.htm
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Pp
+Edwin Groothuis <edwin@FreeBSD.org> performed a major rewrite of the
+.Xr tftpd 8
+and
+.Nm
+code to support RFC2348.
+.Sh NOTES
+Because there is no user-login or validation within
+the
+.Tn TFTP
+protocol, the remote site will probably have some
+sort of file-access restrictions in place.
+The
+exact methods are specific to each site and therefore
+difficult to document here.
+.Pp
+Files larger than 33488896 octets (65535 blocks) cannot be transferred
+without client and server supporting the TFTP blocksize option (RFC2348),
+or the non-standard TFTP rollover option.
diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c
new file mode 100644
index 000000000000..31a22f416135
--- /dev/null
+++ b/usr.bin/tftp/tftp.c
@@ -0,0 +1,268 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include <sys/cdefs.h>
+/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
+
+/*
+ * TFTP User Program -- Protocol Machines
+ */
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+
+#include <arpa/tftp.h>
+
+#include <assert.h>
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "tftp.h"
+#include "tftp-file.h"
+#include "tftp-utils.h"
+#include "tftp-io.h"
+#include "tftp-transfer.h"
+#include "tftp-options.h"
+
+/*
+ * Send the requested file.
+ */
+int
+xmitfile(int peer, char *port, int fd, char *name, char *mode)
+{
+ struct tftphdr *rp;
+ int n, i, ret = 0;
+ uint16_t block;
+ struct sockaddr_storage serv; /* valid server port number */
+ char recvbuffer[MAXPKTSIZE];
+ struct tftp_stats tftp_stats;
+
+ stats_init(&tftp_stats);
+
+ memset(&serv, 0, sizeof(serv));
+ rp = (struct tftphdr *)recvbuffer;
+
+ if (port == NULL) {
+ struct servent *se;
+ se = getservbyname("tftp", "udp");
+ assert(se != NULL);
+ ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port;
+ } else
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ htons(atoi(port));
+
+ for (i = 0; i < 12; i++) {
+ struct sockaddr_storage from;
+
+ /* Tell the other side what we want to do */
+ if (debug & DEBUG_SIMPLE)
+ printf("Sending %s\n", name);
+
+ n = send_wrq(peer, name, mode);
+ if (n > 0) {
+ printf("Cannot send WRQ packet\n");
+ return -1;
+ }
+
+ /*
+ * The first packet we receive has the new destination port
+ * we have to send the next packets to.
+ */
+ n = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, &from, timeoutpacket);
+
+ /* We got some data! */
+ if (n >= 0) {
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ ((struct sockaddr_in *)&from)->sin_port;
+ break;
+ }
+
+ /* This should be retried */
+ if (n == RP_TIMEOUT) {
+ printf("Try %d, didn't receive answer from remote.\n",
+ i + 1);
+ continue;
+ }
+
+ /* Everything else is fatal */
+ break;
+ }
+ if (i == 12) {
+ printf("Transfer timed out.\n");
+ return -1;
+ }
+ if (rp->th_opcode == ERROR) {
+ printf("Got ERROR, aborted\n");
+ return -1;
+ }
+
+ /*
+ * If the first packet is an OACK instead of an ACK packet,
+ * handle it different.
+ */
+ if (rp->th_opcode == OACK) {
+ if (!options_rfc_enabled) {
+ printf("Got OACK while options are not enabled!\n");
+ send_error(peer, EBADOP);
+ return -1;
+ }
+
+ parse_options(peer, rp->th_stuff, n + 2);
+ }
+
+ if (read_init(fd, NULL, mode) < 0) {
+ warn("read_init()");
+ return -1;
+ }
+
+ block = 1;
+ if (tftp_send(peer, &block, &tftp_stats) != 0)
+ ret = -1;
+
+ read_close();
+ if (tftp_stats.amount > 0)
+ printstats("Sent", verbose, &tftp_stats);
+ return ret;
+}
+
+/*
+ * Receive a file.
+ */
+int
+recvfile(int peer, char *port, int fd, char *name, char *mode)
+{
+ struct tftphdr *rp;
+ uint16_t block;
+ char recvbuffer[MAXPKTSIZE];
+ int n, i, ret = 0;
+ struct tftp_stats tftp_stats;
+
+ stats_init(&tftp_stats);
+
+ rp = (struct tftphdr *)recvbuffer;
+
+ if (port == NULL) {
+ struct servent *se;
+ se = getservbyname("tftp", "udp");
+ assert(se != NULL);
+ ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port;
+ } else
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ htons(atoi(port));
+
+ for (i = 0; i < 12; i++) {
+ struct sockaddr_storage from;
+
+ /* Tell the other side what we want to do */
+ if (debug & DEBUG_SIMPLE)
+ printf("Requesting %s\n", name);
+
+ n = send_rrq(peer, name, mode);
+ if (n > 0) {
+ printf("Cannot send RRQ packet\n");
+ return -1;
+ }
+
+ /*
+ * The first packet we receive has the new destination port
+ * we have to send the next packets to.
+ */
+ n = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, &from, timeoutpacket);
+
+ /* We got something useful! */
+ if (n >= 0) {
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ ((struct sockaddr_in *)&from)->sin_port;
+ break;
+ }
+
+ /* We should retry if this happens */
+ if (n == RP_TIMEOUT) {
+ printf("Try %d, didn't receive answer from remote.\n",
+ i + 1);
+ continue;
+ }
+
+ /* Otherwise it is a fatal error */
+ break;
+ }
+ if (i == 12) {
+ printf("Transfer timed out.\n");
+ return -1;
+ }
+ if (rp->th_opcode == ERROR) {
+ tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg);
+ return -1;
+ }
+
+ if (write_init(fd, NULL, mode) < 0) {
+ warn("write_init");
+ return -1;
+ }
+
+ /*
+ * If the first packet is an OACK packet instead of an DATA packet,
+ * handle it different.
+ */
+ if (rp->th_opcode == OACK) {
+ if (!options_rfc_enabled) {
+ printf("Got OACK while options are not enabled!\n");
+ send_error(peer, EBADOP);
+ return -1;
+ }
+
+ parse_options(peer, rp->th_stuff, n + 2);
+
+ n = send_ack(peer, 0);
+ if (n > 0) {
+ printf("Cannot send ACK on OACK.\n");
+ return -1;
+ }
+ block = 0;
+ if (tftp_receive(peer, &block, &tftp_stats, NULL, 0) != 0)
+ ret = -1;
+ } else {
+ block = 1;
+ if (tftp_receive(peer, &block, &tftp_stats, rp, n) != 0)
+ ret = -1;
+ }
+
+ if (tftp_stats.amount > 0)
+ printstats("Received", verbose, &tftp_stats);
+ return ret;
+}
diff --git a/usr.bin/tftp/tftp.h b/usr.bin/tftp/tftp.h
new file mode 100644
index 000000000000..72f519fd24d0
--- /dev/null
+++ b/usr.bin/tftp/tftp.h
@@ -0,0 +1,36 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+int recvfile(int peer, char *port, int fd, char *name, char *mode);
+int xmitfile(int peer, char *port, int fd, char *name, char *mode);
+
+extern int verbose;
+extern int maxtimeout;
diff --git a/usr.bin/time/Makefile b/usr.bin/time/Makefile
new file mode 100644
index 000000000000..a91e94f20070
--- /dev/null
+++ b/usr.bin/time/Makefile
@@ -0,0 +1,3 @@
+PROG= time
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/time/Makefile.depend b/usr.bin/time/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/time/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/time/time.1 b/usr.bin/time/time.1
new file mode 100644
index 000000000000..e6cfa6affaa1
--- /dev/null
+++ b/usr.bin/time/time.1
@@ -0,0 +1,202 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd July 7, 2020
+.Dt TIME 1
+.Os
+.Sh NAME
+.Nm time
+.Nd time command execution
+.Sh SYNOPSIS
+.Nm
+.Op Fl al
+.Op Fl h | Fl p
+.Op Fl o Ar file
+.Ar utility Op Ar argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+executes and
+times the specified
+.Ar utility .
+After the
+.Ar utility
+finishes,
+.Nm
+writes to the standard error stream,
+(in seconds):
+the total time elapsed,
+the time used to execute the
+.Ar utility
+process and the time consumed by system overhead.
+.Pp
+The following options are available:
+.Bl -tag -width "-o file"
+.It Fl a
+If the
+.Fl o
+flag is used, append to the specified file rather than overwriting
+it.
+Otherwise, this option has no effect.
+.It Fl h
+Print times in a human friendly format.
+Times are printed in minutes, hours,
+etc.\& as appropriate.
+.It Fl l
+The contents of the
+.Em rusage
+structure are printed as well.
+.It Fl o Ar file
+Write the output to
+.Ar file
+instead of stderr.
+If
+.Ar file
+exists and the
+.Fl a
+flag is not specified, the file will be overwritten.
+.It Fl p
+Makes
+.Nm
+output POSIX.2 compliant (each time is printed on its own line).
+.El
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Pp
+If
+.Nm
+receives a
+.Dv SIGINFO
+(see the status argument for
+.Xr stty 1 )
+signal, the current time the given command is running will be written to the
+standard output.
+.Sh ENVIRONMENT
+The
+.Ev PATH
+environment variable is used to locate the requested
+.Ar utility
+if the name contains no
+.Ql /
+characters.
+.Sh EXIT STATUS
+If
+.Ar utility
+could be timed successfully, its exit status is returned.
+If
+.Ar utility
+terminated abnormally, a warning message is output to stderr.
+If the
+.Ar utility
+was found but could not be run, the exit status is 126.
+If no
+.Ar utility
+could be found at all, the exit status is 127.
+If
+.Nm
+encounters any other error, the exit status is between 1 and 125
+included.
+.Sh EXAMPLES
+Time the execution of
+.Xr ls 1
+on an empty directory:
+.Bd -literal -offset indent
+$ /usr/bin/time ls
+ 0.00 real 0.00 user 0.00 sys
+.Ed
+.Pp
+Time the execution of the
+.Xr cp 1
+command and store the result in the
+.Pa times.txt
+file.
+Then execute the command again to make a new copy and add the result to the same
+file:
+.Bd -literal -offset indent
+$ /usr/bin/time -o times.txt cp source.iso copy1.iso
+$ /usr/bin/time -a -o times.txt cp source.iso copy2.iso
+.Ed
+.Pp
+The
+.Pa times.txt
+file will contain the times of both commands:
+.Bd -literal -offset indent
+$ cat times.txt
+ 0.68 real 0.00 user 0.22 sys
+ 0.67 real 0.00 user 0.21 sys
+.Ed
+.Pp
+Time the
+.Xr sleep 1
+command and show the results in a human friendly format.
+Show the contents of the
+.Em rusage
+structure too:
+.Bd -literal -offset indent
+$ /usr/bin/time -l -h -p sleep 5
+real 5.01
+user 0.00
+sys 0.00
+ 0 maximum resident set size
+ 0 average shared memory size
+ 0 average unshared data size
+ 0 average unshared stack size
+ 80 page reclaims
+ 0 page faults
+ 0 swaps
+ 1 block input operations
+ 0 block output operations
+ 0 messages sent
+ 0 messages received
+ 0 signals received
+ 3 voluntary context switches
+ 0 involuntary context switches
+.Ed
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr getrusage 2 ,
+.Xr wait 2
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -iso9945-2-93
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v3 .
diff --git a/usr.bin/time/time.c b/usr.bin/time/time.c
new file mode 100644
index 000000000000..4c1ce06543e3
--- /dev/null
+++ b/usr.bin/time/time.c
@@ -0,0 +1,299 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 1988, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/signal.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static int getstathz(void);
+static void humantime(FILE *, long, long);
+static void showtime(FILE *, struct timespec *, struct timespec *,
+ struct rusage *);
+static void siginfo(int);
+static void usage(void) __dead2;
+
+static volatile sig_atomic_t siginfo_recvd;
+static char decimal_point;
+static struct timespec before_ts;
+static int hflag, pflag;
+
+int
+main(int argc, char **argv)
+{
+ int aflag, ch, lflag, status;
+ int exitonsig;
+ pid_t pid;
+ struct rlimit rl;
+ struct rusage ru;
+ struct timespec after;
+ char *ofn = NULL;
+ FILE *out = stderr;
+
+ (void) setlocale(LC_NUMERIC, "");
+ decimal_point = localeconv()->decimal_point[0];
+
+ aflag = hflag = lflag = pflag = 0;
+ while ((ch = getopt(argc, argv, "ahlo:p")) != -1)
+ switch((char)ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'o':
+ ofn = optarg;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ if (!(argc -= optind))
+ exit(0);
+ argv += optind;
+
+ if (ofn) {
+ if ((out = fopen(ofn, aflag ? "ae" : "we")) == NULL)
+ err(1, "%s", ofn);
+ setvbuf(out, (char *)NULL, _IONBF, (size_t)0);
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC, &before_ts))
+ err(1, "clock_gettime");
+ switch(pid = fork()) {
+ case -1: /* error */
+ err(1, "time");
+ /* NOTREACHED */
+ case 0: /* child */
+ execvp(*argv, argv);
+ err(errno == ENOENT ? 127 : 126, "%s", *argv);
+ /* NOTREACHED */
+ }
+ /* parent */
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGQUIT, SIG_IGN);
+ siginfo_recvd = 0;
+ (void)signal(SIGINFO, siginfo);
+ (void)siginterrupt(SIGINFO, 1);
+ while (wait4(pid, &status, 0, &ru) != pid) {
+ if (siginfo_recvd) {
+ siginfo_recvd = 0;
+ if (clock_gettime(CLOCK_MONOTONIC, &after))
+ err(1, "clock_gettime");
+ getrusage(RUSAGE_CHILDREN, &ru);
+ showtime(stdout, &before_ts, &after, &ru);
+ }
+ }
+ if (clock_gettime(CLOCK_MONOTONIC, &after))
+ err(1, "clock_gettime");
+ if ( ! WIFEXITED(status))
+ warnx("command terminated abnormally");
+ exitonsig = WIFSIGNALED(status) ? WTERMSIG(status) : 0;
+ showtime(out, &before_ts, &after, &ru);
+ if (lflag) {
+ int hz = getstathz();
+ u_long ticks;
+
+ ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) +
+ hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000;
+
+ /*
+ * If our round-off on the tick calculation still puts us at 0,
+ * then always assume at least one tick.
+ */
+ if (ticks == 0)
+ ticks = 1;
+
+ fprintf(out, "%10ld %s\n",
+ ru.ru_maxrss, "maximum resident set size");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_ixrss / ticks, "average shared memory size");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_idrss / ticks, "average unshared data size");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_isrss / ticks, "average unshared stack size");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_minflt, "page reclaims");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_majflt, "page faults");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_nswap, "swaps");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_inblock, "block input operations");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_oublock, "block output operations");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_msgsnd, "messages sent");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_msgrcv, "messages received");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_nsignals, "signals received");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_nvcsw, "voluntary context switches");
+ fprintf(out, "%10ld %s\n",
+ ru.ru_nivcsw, "involuntary context switches");
+ }
+ /*
+ * If the child has exited on a signal, exit on the same
+ * signal, too, in order to reproduce the child's exit status.
+ * However, avoid actually dumping core from the current process.
+ */
+ if (exitonsig) {
+ if (signal(exitonsig, SIG_DFL) == SIG_ERR)
+ warn("signal");
+ else {
+ rl.rlim_max = rl.rlim_cur = 0;
+ if (setrlimit(RLIMIT_CORE, &rl) == -1)
+ warn("setrlimit");
+ kill(getpid(), exitonsig);
+ }
+ }
+ exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: time [-al] [-h | -p] [-o file] utility [argument ...]\n");
+ exit(1);
+}
+
+/*
+ * Return the frequency of the kernel's statistics clock.
+ */
+static int
+getstathz(void)
+{
+ int mib[2];
+ size_t size;
+ struct clockinfo clockrate;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CLOCKRATE;
+ size = sizeof clockrate;
+ if (sysctl(mib, 2, &clockrate, &size, NULL, 0) == -1)
+ err(1, "sysctl kern.clockrate");
+ return clockrate.stathz;
+}
+
+static void
+humantime(FILE *out, long sec, long centisec)
+{
+ long days, hrs, mins;
+
+ days = sec / (60L * 60 * 24);
+ sec %= (60L * 60 * 24);
+ hrs = sec / (60L * 60);
+ sec %= (60L * 60);
+ mins = sec / 60;
+ sec %= 60;
+
+ fprintf(out, "\t");
+ if (days)
+ fprintf(out, "%ldd", days);
+ if (hrs)
+ fprintf(out, "%ldh", hrs);
+ if (mins)
+ fprintf(out, "%ldm", mins);
+ fprintf(out, "%ld%c%02lds", sec, decimal_point, centisec);
+}
+
+static void
+showtime(FILE *out, struct timespec *before, struct timespec *after,
+ struct rusage *ru)
+{
+
+ after->tv_sec -= before->tv_sec;
+ after->tv_nsec -= before->tv_nsec;
+ if (after->tv_nsec < 0)
+ after->tv_sec--, after->tv_nsec += 1000000000;
+
+ if (pflag) {
+ /* POSIX wants output that must look like
+ "real %f\nuser %f\nsys %f\n" and requires
+ at least two digits after the radix. */
+ fprintf(out, "real %jd%c%02ld\n",
+ (intmax_t)after->tv_sec, decimal_point,
+ after->tv_nsec/10000000);
+ fprintf(out, "user %jd%c%02ld\n",
+ (intmax_t)ru->ru_utime.tv_sec, decimal_point,
+ ru->ru_utime.tv_usec/10000);
+ fprintf(out, "sys %jd%c%02ld\n",
+ (intmax_t)ru->ru_stime.tv_sec, decimal_point,
+ ru->ru_stime.tv_usec/10000);
+ } else if (hflag) {
+ humantime(out, after->tv_sec, after->tv_nsec/10000000);
+ fprintf(out, " real\t");
+ humantime(out, ru->ru_utime.tv_sec, ru->ru_utime.tv_usec/10000);
+ fprintf(out, " user\t");
+ humantime(out, ru->ru_stime.tv_sec, ru->ru_stime.tv_usec/10000);
+ fprintf(out, " sys\n");
+ } else {
+ fprintf(out, "%9jd%c%02ld real ",
+ (intmax_t)after->tv_sec, decimal_point,
+ after->tv_nsec/10000000);
+ fprintf(out, "%9jd%c%02ld user ",
+ (intmax_t)ru->ru_utime.tv_sec, decimal_point,
+ ru->ru_utime.tv_usec/10000);
+ fprintf(out, "%9jd%c%02ld sys\n",
+ (intmax_t)ru->ru_stime.tv_sec, decimal_point,
+ ru->ru_stime.tv_usec/10000);
+ }
+}
+
+static void
+siginfo(int sig __unused)
+{
+
+ siginfo_recvd = 1;
+}
diff --git a/usr.bin/tip/Makefile b/usr.bin/tip/Makefile
new file mode 100644
index 000000000000..f33bfe16f17e
--- /dev/null
+++ b/usr.bin/tip/Makefile
@@ -0,0 +1,3 @@
+SUBDIR=tip
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/tip/Makefile.inc b/usr.bin/tip/Makefile.inc
new file mode 100644
index 000000000000..01b5f23410c8
--- /dev/null
+++ b/usr.bin/tip/Makefile.inc
@@ -0,0 +1 @@
+.include "../Makefile.inc"
diff --git a/usr.bin/tip/README b/usr.bin/tip/README
new file mode 100644
index 000000000000..78f8ae8eafe9
--- /dev/null
+++ b/usr.bin/tip/README
@@ -0,0 +1,62 @@
+
+Tip can be configured in a number of ways:
+
+ACU's:
+-----
+
+ACU Define in makefile
+-------------------- ---------------
+BIZCOMP 1022, 1031 BIZ1022, BIZ1031
+DEC DF02-AC, DF03-AC DF02, DF03
+DEC DN-11/Able Quadracall DN11
+Ventel VENTEL
+Vadic 831 V831
+
+New ACU's may be added by editing the ACU description table
+in acutab.c and writing a ``driver''.
+
+ACU usage can be monitored by defining ACULOG in the makefile.
+If this is done and no phone numbers should appear in the
+log file, define PRISTINE in the makefile.
+
+Variables:
+---------
+
+Tip's internal workings revolve around a set of (possibly)
+user defined variables. These are statically initialized
+in vars.c, and from the remote file.
+
+Note that adding or deleting variables requires tip to be completedly
+recompiled, as indexes into the variable table are used to avoid
+expensive lookups. These defines are set in tip.h.
+
+Commands:
+--------
+
+The command dispatch table is defined in cmdtab.c. Commands
+may have attributes such as EXPerimental and PRIVileged (only
+root may execute).
+
+
+
+--------------------------------------------------------------------------
+
+Recent changes about Jan 82
+
+A new, improved version of tip is now available. The most important
+addition is the capacility to specify a phone number with tip. The
+default baud rate is 1200. To use it do:
+
+ tip phone-number
+or
+ tip -300 phone-number
+
+for 300 baud.
+
+A ~^Z command has been added to tip as well.
+
+A new cu program is available that interfaces to the tip program.
+It attempts to give the same user interface as cu but it is really
+the tip program so you have all the advantages of tip. This allows
+cu (actually tip) to search for a free ACU instead of having the
+user specify which one he wants.
diff --git a/usr.bin/tip/TODO b/usr.bin/tip/TODO
new file mode 100644
index 000000000000..b47e649a64ea
--- /dev/null
+++ b/usr.bin/tip/TODO
@@ -0,0 +1,19 @@
+
+1. Rethink protection glitches on REMOTE & PHONES
+ files (setuid/setgid??).
+
+2. Make clean fix for scripting being set in .tiprc
+
+3. change EOFREAD to recognize more general strings.
+
+4. add an option that returns an exit status based on
+ whether resources for the requested operation are available.
+
+5. write a program to list known systems (a quick shell script
+ should do it); people keep forgetting the names.
+
+6. change remote file descriptions so that acu attributes are
+ are attached to a device so that several different devices
+ can be used to get to the same system (perhaps hardwired
+ and phone line). got any ideas here? I'm looking at something
+ like dv=cua1,cul1,dn11;cua2,,df03.
diff --git a/usr.bin/tip/libacu/biz22.c b/usr.bin/tip/libacu/biz22.c
new file mode 100644
index 000000000000..6ef5b1861049
--- /dev/null
+++ b/usr.bin/tip/libacu/biz22.c
@@ -0,0 +1,179 @@
+/* $OpenBSD: biz22.c,v 1.13 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: biz22.c,v 1.6 1997/02/11 09:24:11 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+#define DISCONNECT_CMD "\20\04" /* disconnection string */
+
+static int dialtimeout = 0;
+static jmp_buf timeoutbuf;
+
+static int biz_dialer(char *, char *);
+static void sigALRM(int);
+static int cmd(char *);
+static int detect(char *);
+
+/*
+ * Dial up on a BIZCOMP Model 1022 with either
+ * tone dialing (mod = "V")
+ * pulse dialing (mod = "W")
+ */
+static int
+biz_dialer(char *num, char *mod)
+{
+ int connected = 0;
+ char cbuf[40];
+
+ if (boolean(value(VERBOSE)))
+ printf("\nstarting call...");
+ /*
+ * Disable auto-answer and configure for tone/pulse
+ * dialing
+ */
+ if (cmd("\02K\r")) {
+ printf("can't initialize bizcomp...");
+ return (0);
+ }
+ (void)strlcpy(cbuf, "\02.\r", sizeof cbuf);
+ cbuf[1] = *mod;
+ if (cmd(cbuf)) {
+ printf("can't set dialing mode...");
+ return (0);
+ }
+ (void)snprintf(cbuf, sizeof(cbuf), "\02D%s\r", num);
+ write(FD, cbuf, strlen(cbuf));
+ if (!detect("7\r")) {
+ printf("can't get dial tone...");
+ return (0);
+ }
+ if (boolean(value(VERBOSE)))
+ printf("ringing...");
+ /*
+ * The reply from the BIZCOMP should be:
+ * 2 \r or 7 \r failure
+ * 1 \r success
+ */
+ connected = detect("1\r");
+#ifdef ACULOG
+ if (dialtimeout) {
+ char line[80];
+
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "biz1022", line);
+ }
+#endif
+ if (dialtimeout)
+ biz22_disconnect(); /* insurance */
+ return (connected);
+}
+
+int
+biz22w_dialer(char *num, char *acu)
+{
+ return (biz_dialer(num, "W"));
+}
+
+int
+biz22f_dialer(char *num, char *acu)
+{
+ return (biz_dialer(num, "V"));
+}
+
+void
+biz22_disconnect(void)
+{
+ write(FD, DISCONNECT_CMD, sizeof(DISCONNECT_CMD)-1);
+ sleep(2);
+ tcflush(FD, TCIOFLUSH);
+}
+
+void
+biz22_abort(void)
+{
+ write(FD, "\02", 1);
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ dialtimeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static int
+cmd(char *s)
+{
+ sig_t f;
+ char c;
+
+ write(FD, s, strlen(s));
+ f = signal(SIGALRM, sigALRM);
+ if (setjmp(timeoutbuf)) {
+ biz22_abort();
+ signal(SIGALRM, f);
+ return (1);
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ signal(SIGALRM, f);
+ c &= 0177;
+ return (c != '\r');
+}
+
+static int
+detect(char *s)
+{
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ dialtimeout = 0;
+ while (*s) {
+ if (setjmp(timeoutbuf)) {
+ biz22_abort();
+ break;
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ c &= 0177;
+ if (c != *s++)
+ return (0);
+ }
+ signal(SIGALRM, f);
+ return (dialtimeout == 0);
+}
diff --git a/usr.bin/tip/libacu/biz31.c b/usr.bin/tip/libacu/biz31.c
new file mode 100644
index 000000000000..cd2cc0267b43
--- /dev/null
+++ b/usr.bin/tip/libacu/biz31.c
@@ -0,0 +1,246 @@
+/* $OpenBSD: biz31.c,v 1.10 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: biz31.c,v 1.5 1997/02/11 09:24:14 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+#define MAXRETRY 3 /* sync up retry count */
+#define DISCONNECT_CMD "\21\25\11\24" /* disconnection string */
+
+static int biz_dialer(char *, char *);
+static int bizsync(int);
+static int echo(char *);
+static void sigALRM(int);
+static int detect(char *);
+static int flush(char *);
+static int bizsync(int);
+
+static int timeout = 0;
+static jmp_buf timeoutbuf;
+
+/*
+ * Dial up on a BIZCOMP Model 1031 with either
+ * tone dialing (mod = "f")
+ * pulse dialing (mod = "w")
+ */
+static int
+biz_dialer(char *num, char *mod)
+{
+ int connected = 0;
+
+ if (!bizsync(FD)) {
+ logent(value(HOST), "", "biz", "out of sync");
+ printf("bizcomp out of sync\n");
+ delock(uucplock);
+ exit(0);
+ }
+ if (boolean(value(VERBOSE)))
+ printf("\nstarting call...");
+ echo("#\rk$\r$\n"); /* disable auto-answer */
+ echo("$>$.$ #\r"); /* tone/pulse dialing */
+ echo(mod);
+ echo("$\r$\n");
+ echo("$>$.$ #\re$ "); /* disconnection sequence */
+ echo(DISCONNECT_CMD);
+ echo("\r$\n$\r$\n");
+ echo("$>$.$ #\rr$ "); /* repeat dial */
+ echo(num);
+ echo("\r$\n");
+ if (boolean(value(VERBOSE)))
+ printf("ringing...");
+ /*
+ * The reply from the BIZCOMP should be:
+ * `^G NO CONNECTION\r\n^G\r\n' failure
+ * ` CONNECTION\r\n^G' success
+ */
+ connected = detect(" ");
+#ifdef ACULOG
+ if (timeout) {
+ char line[80];
+
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "biz", line);
+ }
+#endif
+ if (!connected)
+ flush(" NO CONNECTION\r\n\07\r\n");
+ else
+ flush("CONNECTION\r\n\07");
+ if (timeout)
+ biz31_disconnect(); /* insurance */
+ return (connected);
+}
+
+int
+biz31w_dialer(char *num, char *acu)
+{
+ return (biz_dialer(num, "w"));
+}
+
+int
+biz31f_dialer(char *num, char *acu)
+{
+ return (biz_dialer(num, "f"));
+}
+
+void
+biz31_disconnect(void)
+{
+ write(FD, DISCONNECT_CMD, sizeof(DISCONNECT_CMD)-1);
+ sleep(2);
+ tcflush(FD, TCIOFLUSH);
+}
+
+void
+biz31_abort(void)
+{
+ write(FD, "\33", 1);
+}
+
+static int
+echo(char *s)
+{
+ char c;
+
+ while (c = *s++) switch (c) {
+
+ case '$':
+ read(FD, &c, 1);
+ s++;
+ break;
+
+ case '#':
+ c = *s++;
+ write(FD, &c, 1);
+ break;
+
+ default:
+ write(FD, &c, 1);
+ read(FD, &c, 1);
+ }
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ timeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static int
+detect(char *s)
+{
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ timeout = 0;
+ while (*s) {
+ if (setjmp(timeoutbuf)) {
+ printf("\07timeout waiting for reply\n");
+ biz31_abort();
+ break;
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ if (c != *s++)
+ break;
+ }
+ signal(SIGALRM, f);
+ return (timeout == 0);
+}
+
+static int
+flush(char *s)
+{
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ while (*s++) {
+ if (setjmp(timeoutbuf))
+ break;
+ alarm(10);
+ read(FD, &c, 1);
+ alarm(0);
+ }
+ signal(SIGALRM, f);
+ timeout = 0; /* guard against disconnection */
+}
+
+/*
+ * This convoluted piece of code attempts to get
+ * the bizcomp in sync. If you don't have the capacity or nread
+ * call there are gory ways to simulate this.
+ */
+static int
+bizsync(int fd)
+{
+#ifdef FIOCAPACITY
+ struct capacity b;
+# define chars(b) ((b).cp_nbytes)
+# define IOCTL FIOCAPACITY
+#endif
+#ifdef FIONREAD
+ long b;
+# define chars(b) (b)
+# define IOCTL FIONREAD
+#endif
+ int already = 0;
+ char buf[10];
+
+retry:
+ if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0 && chars(b) > 0)
+ tcflush(FD, TCIOFLUSH);
+ write(fd, "\rp>\r", 4);
+ sleep(1);
+ if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0) {
+ if (chars(b) != 10) {
+ nono:
+ if (already > MAXRETRY)
+ return (0);
+ write(fd, DISCONNECT_CMD, 4);
+ sleep(2);
+ already++;
+ goto retry;
+ } else {
+ read(fd, buf, 10);
+ if (strncmp(buf, "p >\r\n\r\n>", 8))
+ goto nono;
+ }
+ }
+ return (1);
+}
diff --git a/usr.bin/tip/libacu/courier.c b/usr.bin/tip/libacu/courier.c
new file mode 100644
index 000000000000..7ff0daa9d1db
--- /dev/null
+++ b/usr.bin/tip/libacu/courier.c
@@ -0,0 +1,346 @@
+/* $OpenBSD: courier.c,v 1.15 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: courier.c,v 1.7 1997/02/11 09:24:16 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1986, 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.
+ */
+
+/*
+ * Routines for calling up on a Courier modem.
+ * Derived from Hayes driver.
+ */
+#include "tip.h"
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#define MAXRETRY 5
+
+static int dialtimeout = 0;
+static int connected = 0;
+static jmp_buf timeoutbuf;
+
+static void sigALRM(int);
+static int cour_swallow(char *);
+static int cour_connect(void);
+static int coursync(void);
+static void cour_write(int, char *, int);
+static void cour_nap(void);
+#ifdef DEBUG
+static void cour_verbose_read(void);
+#endif
+
+int
+cour_dialer(char *num, char *acu)
+{
+ char *cp;
+#ifdef ACULOG
+ char line[80];
+#endif
+ struct termios cntrl;
+
+ if (boolean(value(VERBOSE)))
+ printf("Using \"%s\"\n", acu);
+
+ tcgetattr(FD, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSAFLUSH, &cntrl);
+ /*
+ * Get in synch.
+ */
+ if (!coursync()) {
+badsynch:
+ printf("can't synchronize with courier\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "courier", "can't synch up");
+#endif
+ return (0);
+ }
+ cour_write(FD, "AT E0\r", 6); /* turn off echoing */
+ sleep(1);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ cour_verbose_read();
+#endif
+ tcflush(FD, TCIOFLUSH);
+ cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
+ if (!cour_swallow("\r\nOK\r\n"))
+ goto badsynch;
+ fflush(stdout);
+ cour_write(FD, "AT D", 4);
+ for (cp = num; *cp; cp++)
+ if (*cp == '=')
+ *cp = ',';
+ cour_write(FD, num, strlen(num));
+ cour_write(FD, "\r", 1);
+ connected = cour_connect();
+#ifdef ACULOG
+ if (dialtimeout) {
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "cour", line);
+ }
+#endif
+ if (dialtimeout)
+ cour_disconnect();
+ return (connected);
+}
+
+void
+cour_disconnect(void)
+{
+ /* first hang up the modem*/
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ coursync(); /* reset */
+ close(FD);
+}
+
+void
+cour_abort(void)
+{
+ cour_write(FD, "\r", 1); /* send anything to abort the call */
+ cour_disconnect();
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ printf("\07timeout waiting for reply\n");
+ dialtimeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static int
+cour_swallow(char *match)
+{
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ dialtimeout = 0;
+ do {
+ if (*match =='\0') {
+ signal(SIGALRM, f);
+ return (1);
+ }
+ if (setjmp(timeoutbuf)) {
+ signal(SIGALRM, f);
+ return (0);
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ c &= 0177;
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ putchar(c);
+#endif
+ } while (c == *match++);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ fflush(stdout);
+#endif
+ signal(SIGALRM, SIG_DFL);
+ return (0);
+}
+
+struct baud_msg {
+ char *msg;
+ int baud;
+} baud_msg[] = {
+ { "", B300 },
+ { " 1200", B1200 },
+ { " 2400", B2400 },
+ { " 9600", B9600 },
+ { " 9600/ARQ", B9600 },
+ { 0, 0 },
+};
+
+static int
+cour_connect(void)
+{
+ char c;
+ int nc, nl, n;
+ char dialer_buf[64];
+ struct baud_msg *bm;
+ sig_t f;
+
+ if (cour_swallow("\r\n") == 0)
+ return (0);
+ f = signal(SIGALRM, sigALRM);
+again:
+ nc = 0; nl = sizeof(dialer_buf)-1;
+ bzero(dialer_buf, sizeof(dialer_buf));
+ dialtimeout = 0;
+ for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
+ if (setjmp(timeoutbuf))
+ break;
+ alarm(number(value(DIALTIMEOUT)));
+ n = read(FD, &c, 1);
+ alarm(0);
+ if (n <= 0)
+ break;
+ c &= 0x7f;
+ if (c == '\r') {
+ if (cour_swallow("\n") == 0)
+ break;
+ if (!dialer_buf[0])
+ goto again;
+ if (strcmp(dialer_buf, "RINGING") == 0 &&
+ boolean(value(VERBOSE))) {
+#ifdef DEBUG
+ printf("%s\r\n", dialer_buf);
+#endif
+ goto again;
+ }
+ if (strncmp(dialer_buf, "CONNECT",
+ sizeof("CONNECT")-1) != 0)
+ break;
+ for (bm = baud_msg ; bm->msg ; bm++)
+ if (strcmp(bm->msg,
+ dialer_buf+sizeof("CONNECT")-1) == 0) {
+ struct termios cntrl;
+
+ tcgetattr(FD, &cntrl);
+ cfsetospeed(&cntrl, bm->baud);
+ cfsetispeed(&cntrl, bm->baud);
+ tcsetattr(FD, TCSAFLUSH, &cntrl);
+ signal(SIGALRM, f);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ printf("%s\r\n", dialer_buf);
+#endif
+ return (1);
+ }
+ break;
+ }
+ dialer_buf[nc] = c;
+#ifdef notdef
+ if (boolean(value(VERBOSE)))
+ putchar(c);
+#endif
+ }
+ printf("%s\r\n", dialer_buf);
+ signal(SIGALRM, f);
+ return (0);
+}
+
+/*
+ * This convoluted piece of code attempts to get
+ * the courier in sync.
+ */
+static int
+coursync(void)
+{
+ int already = 0;
+ int len;
+ char buf[40];
+
+ while (already++ < MAXRETRY) {
+ tcflush(FD, TCIOFLUSH);
+ cour_write(FD, "\rAT Z\r", 6); /* reset modem */
+ bzero(buf, sizeof(buf));
+ sleep(1);
+ ioctl(FD, FIONREAD, &len);
+ if (len) {
+ len = read(FD, buf, sizeof(buf));
+#ifdef DEBUG
+ buf[len] = '\0';
+ printf("coursync: (\"%s\")\n\r", buf);
+#endif
+ if (strchr(buf, '0') ||
+ (strchr(buf, 'O') && strchr(buf, 'K')))
+ return(1);
+ }
+ /*
+ * If not strapped for DTR control,
+ * try to get command mode.
+ */
+ sleep(1);
+ cour_write(FD, "+++", 3);
+ sleep(1);
+ /*
+ * Toggle DTR to force anyone off that might have left
+ * the modem connected.
+ */
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ }
+ cour_write(FD, "\rAT Z\r", 6);
+ return (0);
+}
+
+static void
+cour_write(int fd, char *cp, int n)
+{
+#ifdef notdef
+ if (boolean(value(VERBOSE)))
+ write(1, cp, n);
+#endif
+ tcdrain(fd);
+ cour_nap();
+ for ( ; n-- ; cp++) {
+ write(fd, cp, 1);
+ tcdrain(fd);
+ cour_nap();
+ }
+}
+
+#ifdef DEBUG
+static void
+cour_verbose_read(void)
+{
+ int n = 0;
+ char buf[BUFSIZ];
+
+ if (ioctl(FD, FIONREAD, &n) < 0)
+ return;
+ if (n <= 0)
+ return;
+ if (read(FD, buf, n) != n)
+ return;
+ write(1, buf, n);
+}
+#endif
+
+/* Give the courier 50 milliseconds between characters */
+static void
+cour_nap(void)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 50 * 1000000;
+
+ nanosleep(&ts, NULL);
+}
diff --git a/usr.bin/tip/libacu/df.c b/usr.bin/tip/libacu/df.c
new file mode 100644
index 000000000000..5b9cf7186a69
--- /dev/null
+++ b/usr.bin/tip/libacu/df.c
@@ -0,0 +1,129 @@
+/* $OpenBSD: df.c,v 1.9 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: df.c,v 1.4 1995/10/29 00:49:51 pk Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Dial the DF02-AC or DF03-AC
+ */
+
+#include "tip.h"
+
+static jmp_buf Sjbuf;
+
+static int df_dialer(char *, char *, int);
+static void alrm_timeout(int);
+
+int
+df02_dialer(char *num, char *acu)
+{
+ return (df_dialer(num, acu, 0));
+}
+
+int
+df03_dialer(char *num, char *acu)
+{
+ return (df_dialer(num, acu, 1));
+}
+
+static int
+df_dialer(char *num, char *acu, int df03)
+{
+ int f = FD;
+ struct termios cntrl;
+ int speed = 0;
+ char c = '\0';
+
+ tcgetattr(f, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(f, TCSANOW, &cntrl);
+ if (setjmp(Sjbuf)) {
+ printf("connection timed out\r\n");
+ df_disconnect();
+ return (0);
+ }
+ if (boolean(value(VERBOSE)))
+ printf("\ndialing...");
+ fflush(stdout);
+#ifdef TIOCMSET
+ if (df03) {
+ int st = TIOCM_ST; /* secondary Transmit flag */
+
+ tcgetattr(f, &cntrl);
+ speed = cfgetospeed(&cntrl);
+ if (speed != B1200) { /* must dial at 1200 baud */
+ cfsetospeed(&cntrl, B1200);
+ cfsetispeed(&cntrl, B1200);
+ tcsetattr(f, TCSAFLUSH, &cntrl);
+ ioctl(f, TIOCMBIC, &st); /* clear ST for 300 baud */
+ } else
+ ioctl(f, TIOCMBIS, &st); /* set ST for 1200 baud */
+ }
+#endif
+ signal(SIGALRM, alrm_timeout);
+ alarm(5 * strlen(num) + 10);
+ tcflush(f, TCIOFLUSH);
+ write(f, "\001", 1);
+ sleep(1);
+ write(f, "\002", 1);
+ write(f, num, strlen(num));
+ read(f, &c, 1);
+#ifdef TIOCMSET
+ if (df03 && speed != B1200) {
+ cfsetospeed(&cntrl, speed);
+ cfsetispeed(&cntrl, speed);
+ tcsetattr(f, TCSAFLUSH, &cntrl);
+ }
+#endif
+ return (c == 'A');
+}
+
+void
+df_disconnect(void)
+{
+ write(FD, "\001", 1);
+ sleep(1);
+ tcflush(FD, TCIOFLUSH);
+}
+
+void
+df_abort(void)
+{
+ df_disconnect();
+}
+
+/*ARGSUSED*/
+static void
+alrm_timeout(int signo)
+{
+ longjmp(Sjbuf, 1);
+}
diff --git a/usr.bin/tip/libacu/dn11.c b/usr.bin/tip/libacu/dn11.c
new file mode 100644
index 000000000000..8f9f47065d69
--- /dev/null
+++ b/usr.bin/tip/libacu/dn11.c
@@ -0,0 +1,141 @@
+/* $OpenBSD: dn11.c,v 1.9 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: dn11.c,v 1.4 1995/10/29 00:49:53 pk Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Routines for dialing up on DN-11
+ */
+#include "tip.h"
+
+static jmp_buf jmpbuf;
+static pid_t child = -1, dn;
+
+static void alarmtr(int);
+
+int
+dn_dialer(char *num, char *acu)
+{
+ int lt, nw;
+ int timelim;
+ struct termios cntrl;
+
+ if (boolean(value(VERBOSE)))
+ printf("\nstarting call...");
+ if ((dn = open(acu, 1)) < 0) {
+ if (errno == EBUSY)
+ printf("line busy...");
+ else
+ printf("acu open error...");
+ return (0);
+ }
+ if (setjmp(jmpbuf)) {
+ kill(child, SIGKILL);
+ close(dn);
+ return (0);
+ }
+ signal(SIGALRM, alarmtr);
+ timelim = 5 * strlen(num);
+ alarm(timelim < 30 ? 30 : timelim);
+ if ((child = fork()) == 0) {
+ /*
+ * ignore this stuff for aborts
+ */
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ sleep(2);
+ nw = write(dn, num, lt = strlen(num));
+ exit(nw != lt);
+ }
+ /*
+ * open line - will return on carrier
+ */
+ if ((FD = open(DV, 2)) < 0) {
+ if (errno == EIO)
+ printf("lost carrier...");
+ else
+ printf("dialup line open failed...");
+ alarm(0);
+ kill(child, SIGKILL);
+ close(dn);
+ return (0);
+ }
+ alarm(0);
+ tcgetattr(dn, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(dn, TCSANOW, &cntrl);
+ signal(SIGALRM, SIG_DFL);
+ while ((nw = wait(&lt)) != child && nw != -1)
+ ;
+ fflush(stdout);
+ close(dn);
+ if (lt != 0) {
+ close(FD);
+ return (0);
+ }
+ return (1);
+}
+
+/*ARGSUSED*/
+static void
+alarmtr(int signo)
+{
+ alarm(0);
+ longjmp(jmpbuf, 1);
+}
+
+/*
+ * Insurance, for some reason we don't seem to be
+ * hanging up...
+ */
+void
+dn_disconnect(void)
+{
+ sleep(2);
+ if (FD > 0)
+ ioctl(FD, TIOCCDTR, 0);
+ close(FD);
+}
+
+void
+dn_abort(void)
+{
+ sleep(2);
+ if (child > 0)
+ kill(child, SIGKILL);
+ if (dn > 0)
+ close(dn);
+ if (FD > 0)
+ ioctl(FD, TIOCCDTR, 0);
+ close(FD);
+}
diff --git a/usr.bin/tip/libacu/hayes.c b/usr.bin/tip/libacu/hayes.c
new file mode 100644
index 000000000000..efdd7fc8b438
--- /dev/null
+++ b/usr.bin/tip/libacu/hayes.c
@@ -0,0 +1,312 @@
+/* $OpenBSD: hayes.c,v 1.13 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: hayes.c,v 1.6 1997/02/11 09:24:17 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Routines for calling up on a Hayes Modem
+ * (based on the old VenTel driver).
+ * The modem is expected to be strapped for "echo".
+ * Also, the switches enabling the DTR and CD lines
+ * must be set correctly.
+ * NOTICE:
+ * The easy way to hang up a modem is always simply to
+ * clear the DTR signal. However, if the +++ sequence
+ * (which switches the modem back to local mode) is sent
+ * before modem is hung up, removal of the DTR signal
+ * has no effect (except that it prevents the modem from
+ * recognizing commands).
+ * (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
+ */
+/*
+ * TODO:
+ * It is probably not a good idea to switch the modem
+ * state between 'verbose' and terse (status messages).
+ * This should be kicked out and we should use verbose
+ * mode only. This would make it consistent with normal
+ * interactive use thru the command 'tip dialer'.
+ */
+#include "tip.h"
+
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#define min(a,b) ((a < b) ? a : b)
+
+static int dialtimeout = 0;
+static jmp_buf timeoutbuf;
+
+#define DUMBUFLEN 40
+static char dumbuf[DUMBUFLEN];
+
+#define DIALING 1
+#define IDLE 2
+#define CONNECTED 3
+#define FAILED 4
+static int state = IDLE;
+
+static void sigALRM(int);
+static char gobble(char *);
+static void error_rep(char);
+static void goodbye(void);
+static int hay_sync(void);
+
+int
+hay_dialer(char *num, char *acu)
+{
+ char *cp;
+ int connected = 0;
+ char dummy;
+ struct termios cntrl;
+#ifdef ACULOG
+ char line[80];
+#endif
+ if (hay_sync() == 0) /* make sure we can talk to the modem */
+ return(0);
+ if (boolean(value(VERBOSE)))
+ printf("\ndialing...");
+ fflush(stdout);
+ tcgetattr(FD, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSANOW, &cntrl);
+ tcflush(FD, TCIOFLUSH);
+ write(FD, "ATv0\r", 5); /* tell modem to use short status codes */
+ gobble("\r");
+ gobble("\r");
+ write(FD, "ATTD", 4); /* send dial command */
+ for (cp = num; *cp; cp++)
+ if (*cp == '=')
+ *cp = ',';
+ write(FD, num, strlen(num));
+ state = DIALING;
+ write(FD, "\r", 1);
+ connected = 0;
+ if (gobble("\r")) {
+ if ((dummy = gobble("01234")) != '1')
+ error_rep(dummy);
+ else
+ connected = 1;
+ }
+ if (connected)
+ state = CONNECTED;
+ else {
+ state = FAILED;
+ return (connected); /* lets get out of here.. */
+ }
+ tcflush(FD, TCIOFLUSH);
+#ifdef ACULOG
+ if (dialtimeout) {
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "hayes", line);
+ }
+#endif
+ if (dialtimeout)
+ hay_disconnect(); /* insurance */
+ return (connected);
+}
+
+void
+hay_disconnect(void)
+{
+ /* first hang up the modem*/
+#ifdef DEBUG
+ printf("\rdisconnecting modem....\n\r");
+#endif
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ goodbye();
+}
+
+void
+hay_abort(void)
+{
+ write(FD, "\r", 1); /* send anything to abort the call */
+ hay_disconnect();
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ printf("\07timeout waiting for reply\n\r");
+ dialtimeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static char
+gobble(char *match)
+{
+ char c;
+ sig_t f;
+ size_t i;
+ int status = 0;
+
+ f = signal(SIGALRM, sigALRM);
+ dialtimeout = 0;
+#ifdef DEBUG
+ printf("\ngobble: waiting for %s\n", match);
+#endif
+ do {
+ if (setjmp(timeoutbuf)) {
+ signal(SIGALRM, f);
+ return (0);
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ c &= 0177;
+#ifdef DEBUG
+ printf("%c 0x%x ", c, c);
+#endif
+ for (i = 0; i < strlen(match); i++)
+ if (c == match[i])
+ status = c;
+ } while (status == 0);
+ signal(SIGALRM, SIG_DFL);
+#ifdef DEBUG
+ printf("\n");
+#endif
+ return (status);
+}
+
+static void
+error_rep(char c)
+{
+ printf("\n\r");
+ switch (c) {
+
+ case '0':
+ printf("OK");
+ break;
+
+ case '1':
+ printf("CONNECT");
+ break;
+
+ case '2':
+ printf("RING");
+ break;
+
+ case '3':
+ printf("NO CARRIER");
+ break;
+
+ case '4':
+ printf("ERROR in input");
+ break;
+
+ case '5':
+ printf("CONNECT 1200");
+ break;
+
+ default:
+ printf("Unknown Modem error: %c (0x%x)", c, c);
+ }
+ printf("\n\r");
+ return;
+}
+
+/*
+ * set modem back to normal verbose status codes.
+ */
+static void
+goodbye(void)
+{
+ int len;
+ char c;
+
+ tcflush(FD, TCIOFLUSH);
+ if (hay_sync()) {
+ sleep(1);
+#ifndef DEBUG
+ tcflush(FD, TCIOFLUSH);
+#endif
+ write(FD, "ATH0\r", 5); /* insurance */
+#ifndef DEBUG
+ c = gobble("03");
+ if (c != '0' && c != '3') {
+ printf("cannot hang up modem\n\r");
+ printf("please use 'tip dialer' to make sure the line is hung up\n\r");
+ }
+#endif
+ sleep(1);
+ ioctl(FD, FIONREAD, &len);
+#ifdef DEBUG
+ printf("goodbye1: len=%d -- ", len);
+ rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
+ dumbuf[rlen] = '\0';
+ printf("read (%d): %s\r\n", rlen, dumbuf);
+#endif
+ write(FD, "ATv1\r", 5);
+ sleep(1);
+#ifdef DEBUG
+ ioctl(FD, FIONREAD, &len);
+ printf("goodbye2: len=%d -- ", len);
+ rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
+ dumbuf[rlen] = '\0';
+ printf("read (%d): %s\r\n", rlen, dumbuf);
+#endif
+ }
+ tcflush(FD, TCIOFLUSH);
+ ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
+ close(FD);
+}
+
+#define MAXRETRY 5
+
+static int
+hay_sync(void)
+{
+ int len, retry = 0;
+
+ while (retry++ <= MAXRETRY) {
+ write(FD, "AT\r", 3);
+ sleep(1);
+ ioctl(FD, FIONREAD, &len);
+ if (len) {
+ len = read(FD, dumbuf, min(len, DUMBUFLEN));
+ if (strchr(dumbuf, '0') ||
+ (strchr(dumbuf, 'O') && strchr(dumbuf, 'K')))
+ return(1);
+#ifdef DEBUG
+ dumbuf[len] = '\0';
+ printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
+#endif
+ }
+ ioctl(FD, TIOCCDTR, 0);
+ ioctl(FD, TIOCSDTR, 0);
+ }
+ printf("Cannot synchronize with hayes...\n\r");
+ return(0);
+}
diff --git a/usr.bin/tip/libacu/t3000.c b/usr.bin/tip/libacu/t3000.c
new file mode 100644
index 000000000000..9341430787da
--- /dev/null
+++ b/usr.bin/tip/libacu/t3000.c
@@ -0,0 +1,364 @@
+/* $OpenBSD: t3000.c,v 1.14 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: t3000.c,v 1.5 1997/02/11 09:24:18 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+/*
+ * Routines for calling up on a Telebit T3000 modem.
+ * Derived from Courier driver.
+ */
+#include "tip.h"
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#define MAXRETRY 5
+
+static int dialtimeout = 0;
+static int connected = 0;
+static jmp_buf timeoutbuf;
+
+static void sigALRM(int);
+static int t3000_swallow(char *);
+static int t3000_connect(void);
+static int t3000_sync(void);
+static void t3000_write(int, char *, int);
+static void t3000_nap(void);
+#ifdef DEBUG
+static void t3000_verbose_read(void);
+#endif
+
+int
+t3000_dialer(char *num, char *acu)
+{
+ char *cp;
+ struct termios cntrl;
+#ifdef ACULOG
+ char line[80];
+#endif
+
+ if (boolean(value(VERBOSE)))
+ printf("Using \"%s\"\n", acu);
+
+ tcgetattr(FD, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSANOW, &cntrl);
+ /*
+ * Get in synch.
+ */
+ if (!t3000_sync()) {
+badsynch:
+ printf("can't synchronize with t3000\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "t3000", "can't synch up");
+#endif
+ return (0);
+ }
+ t3000_write(FD, "AT E0\r", 6); /* turn off echoing */
+ sleep(1);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ t3000_verbose_read();
+#endif
+ tcflush(FD, TCIOFLUSH);
+ t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18);
+ if (!t3000_swallow("\r\nOK\r\n"))
+ goto badsynch;
+ fflush(stdout);
+ t3000_write(FD, "AT D", 4);
+ for (cp = num; *cp; cp++)
+ if (*cp == '=')
+ *cp = ',';
+ t3000_write(FD, num, strlen(num));
+ t3000_write(FD, "\r", 1);
+ connected = t3000_connect();
+#ifdef ACULOG
+ if (dialtimeout) {
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "t3000", line);
+ }
+#endif
+ if (dialtimeout)
+ t3000_disconnect();
+ return (connected);
+}
+
+void
+t3000_disconnect(void)
+{
+ /* first hang up the modem*/
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ t3000_sync(); /* reset */
+ close(FD);
+}
+
+void
+t3000_abort(void)
+{
+ t3000_write(FD, "\r", 1); /* send anything to abort the call */
+ t3000_disconnect();
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ printf("\07timeout waiting for reply\n");
+ dialtimeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static int
+t3000_swallow(char *match)
+{
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ dialtimeout = 0;
+ do {
+ if (*match =='\0') {
+ signal(SIGALRM, f);
+ return (1);
+ }
+ if (setjmp(timeoutbuf)) {
+ signal(SIGALRM, f);
+ return (0);
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, &c, 1);
+ alarm(0);
+ c &= 0177;
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ putchar(c);
+#endif
+ } while (c == *match++);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ fflush(stdout);
+#endif
+ signal(SIGALRM, SIG_DFL);
+ return (0);
+}
+
+#ifndef B19200 /* XXX */
+#define B19200 EXTA
+#define B38400 EXTB
+#endif
+
+struct tbaud_msg {
+ char *msg;
+ int baud;
+ int baud2;
+} tbaud_msg[] = {
+ { "", B300, 0 },
+ { " 1200", B1200, 0 },
+ { " 2400", B2400, 0 },
+ { " 4800", B4800, 0 },
+ { " 9600", B9600, 0 },
+ { " 14400", B19200, B9600 },
+ { " 19200", B19200, B9600 },
+ { " 38400", B38400, B9600 },
+ { " 57600", B38400, B9600 },
+ { " 7512", B9600, 0 },
+ { " 1275", B2400, 0 },
+ { " 7200", B9600, 0 },
+ { " 12000", B19200, B9600 },
+ { 0, 0, 0 },
+};
+
+static int
+t3000_connect(void)
+{
+ char c;
+ int nc, nl, n;
+ char dialer_buf[64];
+ struct tbaud_msg *bm;
+ sig_t f;
+
+ if (t3000_swallow("\r\n") == 0)
+ return (0);
+ f = signal(SIGALRM, sigALRM);
+again:
+ nc = 0; nl = sizeof(dialer_buf)-1;
+ bzero(dialer_buf, sizeof(dialer_buf));
+ dialtimeout = 0;
+ for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
+ if (setjmp(timeoutbuf))
+ break;
+ alarm(number(value(DIALTIMEOUT)));
+ n = read(FD, &c, 1);
+ alarm(0);
+ if (n <= 0)
+ break;
+ c &= 0x7f;
+ if (c == '\r') {
+ if (t3000_swallow("\n") == 0)
+ break;
+ if (!dialer_buf[0])
+ goto again;
+ if (strcmp(dialer_buf, "RINGING") == 0 &&
+ boolean(value(VERBOSE))) {
+#ifdef DEBUG
+ printf("%s\r\n", dialer_buf);
+#endif
+ goto again;
+ }
+ if (strncmp(dialer_buf, "CONNECT",
+ sizeof("CONNECT")-1) != 0)
+ break;
+ for (bm = tbaud_msg ; bm->msg ; bm++)
+ if (strcmp(bm->msg,
+ dialer_buf+sizeof("CONNECT")-1) == 0) {
+ struct termios cntrl;
+
+ tcgetattr(FD, &cntrl);
+ cfsetospeed(&cntrl, bm->baud);
+ cfsetispeed(&cntrl, bm->baud);
+ tcsetattr(FD, TCSAFLUSH, &cntrl);
+ signal(SIGALRM, f);
+#ifdef DEBUG
+ if (boolean(value(VERBOSE)))
+ printf("%s\r\n", dialer_buf);
+#endif
+ return (1);
+ }
+ break;
+ }
+ dialer_buf[nc] = c;
+#ifdef notdef
+ if (boolean(value(VERBOSE)))
+ putchar(c);
+#endif
+ }
+ printf("%s\r\n", dialer_buf);
+ signal(SIGALRM, f);
+ return (0);
+}
+
+/*
+ * This convoluted piece of code attempts to get
+ * the t3000 in sync.
+ */
+static int
+t3000_sync(void)
+{
+ int already = 0;
+ int len;
+ char buf[40];
+
+ while (already++ < MAXRETRY) {
+ tcflush(FD, TCIOFLUSH);
+ t3000_write(FD, "\rAT Z\r", 6); /* reset modem */
+ bzero(buf, sizeof(buf));
+ sleep(2);
+ ioctl(FD, FIONREAD, &len);
+#if 1
+if (len == 0) len = 1;
+#endif
+ if (len) {
+ len = read(FD, buf, sizeof(buf));
+#ifdef DEBUG
+ buf[len] = '\0';
+ printf("t3000_sync: (\"%s\")\n\r", buf);
+#endif
+ if (strchr(buf, '0') ||
+ (strchr(buf, 'O') && strchr(buf, 'K')))
+ return(1);
+ }
+ /*
+ * If not strapped for DTR control,
+ * try to get command mode.
+ */
+ sleep(1);
+ t3000_write(FD, "+++", 3);
+ sleep(1);
+ /*
+ * Toggle DTR to force anyone off that might have left
+ * the modem connected.
+ */
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ }
+ t3000_write(FD, "\rAT Z\r", 6);
+ return (0);
+}
+
+static void
+t3000_write(int fd, char *cp, int n)
+{
+#ifdef notdef
+ if (boolean(value(VERBOSE)))
+ write(1, cp, n);
+#endif
+ tcdrain(fd);
+ t3000_nap();
+ for ( ; n-- ; cp++) {
+ write(fd, cp, 1);
+ tcdrain(fd);
+ t3000_nap();
+ }
+}
+
+#ifdef DEBUG
+static void
+t3000_verbose_read(void)
+{
+ int n = 0;
+ char buf[BUFSIZ];
+
+ if (ioctl(FD, FIONREAD, &n) < 0)
+ return;
+ if (n <= 0)
+ return;
+ if (read(FD, buf, n) != n)
+ return;
+ write(1, buf, n);
+}
+#endif
+
+/* Give the t3000 50 milliseconds between characters */
+static void
+t3000_nap(void)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 50 * 1000000;
+
+ nanosleep(&ts, NULL);
+}
diff --git a/usr.bin/tip/libacu/v3451.c b/usr.bin/tip/libacu/v3451.c
new file mode 100644
index 000000000000..1f671b5bffd3
--- /dev/null
+++ b/usr.bin/tip/libacu/v3451.c
@@ -0,0 +1,204 @@
+/* $OpenBSD: v3451.c,v 1.9 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: v3451.c,v 1.6 1997/02/11 09:24:20 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Routines for calling up on a Vadic 3451 Modem
+ */
+#include "tip.h"
+
+static jmp_buf Sjbuf;
+
+static void vawrite(char *, int);
+static int expect(char *);
+static void alarmtr(int);
+static int notin(char *, char *);
+static int prefix(char *, char *);
+
+int
+v3451_dialer(char *num, char *acu)
+{
+ sig_t func;
+ int ok;
+ int slow = number(value(BAUDRATE)) < 1200;
+ char phone[50];
+ struct termios cntrl;
+
+ /*
+ * Get in synch
+ */
+ vawrite("I\r", 1 + slow);
+ vawrite("I\r", 1 + slow);
+ vawrite("I\r", 1 + slow);
+ vawrite("\005\r", 2 + slow);
+ if (!expect("READY")) {
+ printf("can't synchronize with vadic 3451\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "vadic", "can't synch up");
+#endif
+ return (0);
+ }
+ tcgetattr(FD, &cntrl);
+ term.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSANOW, &cntrl);
+ sleep(1);
+ vawrite("D\r", 2 + slow);
+ if (!expect("NUMBER?")) {
+ printf("Vadic will not accept dial command\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "vadic", "will not accept dial");
+#endif
+ return (0);
+ }
+ (void)snprintf(phone, sizeof phone, "%s\r", num);
+ vawrite(phone, 1 + slow);
+ if (!expect(phone)) {
+ printf("Vadic will not accept phone number\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "vadic", "will not accept number");
+#endif
+ return (0);
+ }
+ func = signal(SIGINT,SIG_IGN);
+ /*
+ * You cannot interrupt the Vadic when its dialing;
+ * even dropping DTR does not work (definitely a
+ * brain damaged design).
+ */
+ vawrite("\r", 1 + slow);
+ vawrite("\r", 1 + slow);
+ if (!expect("DIALING:")) {
+ printf("Vadic failed to dial\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "vadic", "failed to dial");
+#endif
+ return (0);
+ }
+ if (boolean(value(VERBOSE)))
+ printf("\ndialing...");
+ ok = expect("ON LINE");
+ signal(SIGINT, func);
+ if (!ok) {
+ printf("call failed\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "vadic", "call failed");
+#endif
+ return (0);
+ }
+ tcflush(FD, TCIOFLUSH);
+ return (1);
+}
+
+void
+v3451_disconnect(void)
+{
+ close(FD);
+}
+
+void
+v3451_abort(void)
+{
+ close(FD);
+}
+
+static void
+vawrite(char *cp, int delay)
+{
+ for (; *cp; sleep(delay), cp++)
+ write(FD, cp, 1);
+}
+
+static int
+expect(char *cp)
+{
+ char buf[300];
+ char *rp = buf;
+ int timeout = 30, online = 0;
+
+ if (strcmp(cp, "\"\"") == 0)
+ return (1);
+ *rp = 0;
+ /*
+ * If we are waiting for the Vadic to complete
+ * dialing and get a connection, allow more time
+ * Unfortunately, the Vadic times out 24 seconds after
+ * the last digit is dialed
+ */
+ online = strcmp(cp, "ON LINE") == 0;
+ if (online)
+ timeout = number(value(DIALTIMEOUT));
+ signal(SIGALRM, alarmtr);
+ if (setjmp(Sjbuf))
+ return (0);
+ alarm(timeout);
+ while (notin(cp, buf) && rp < buf + sizeof (buf) - 1) {
+ if (online && notin("FAILED CALL", buf) == 0)
+ return (0);
+ if (read(FD, rp, 1) < 0) {
+ alarm(0);
+ return (0);
+ }
+ if (*rp &= 0177)
+ rp++;
+ *rp = '\0';
+ }
+ alarm(0);
+ return (1);
+}
+
+/*ARGSUSED*/
+static void
+alarmtr(int signo)
+{
+ longjmp(Sjbuf, 1);
+}
+
+static int
+notin(char *sh, char *lg)
+{
+ for (; *lg; lg++)
+ if (prefix(sh, lg))
+ return (0);
+ return (1);
+}
+
+static int
+prefix(char *s1, char *s2)
+{
+ char c;
+
+ while ((c = *s1++) == *s2++)
+ if (c == '\0')
+ return (1);
+ return (c == '\0');
+}
diff --git a/usr.bin/tip/libacu/v831.c b/usr.bin/tip/libacu/v831.c
new file mode 100644
index 000000000000..b233cf55c280
--- /dev/null
+++ b/usr.bin/tip/libacu/v831.c
@@ -0,0 +1,255 @@
+/* $OpenBSD: v831.c,v 1.11 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: v831.c,v 1.5 1996/12/29 10:42:01 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Routines for dialing up on Vadic 831
+ */
+#include "tip.h"
+#include <termios.h>
+
+static jmp_buf jmpbuf;
+static pid_t child = -1;
+
+static void alarmtr(int);
+static int dialit(char *, char *);
+static char * sanitize(char *);
+
+int
+v831_dialer(char *num, char *acu)
+{
+ int status;
+ int timelim;
+ pid_t pid;
+
+ if (boolean(value(VERBOSE)))
+ printf("\nstarting call...");
+#ifdef DEBUG
+ printf ("(acu=%s)\n", acu);
+#endif
+ if ((AC = open(acu, O_RDWR)) < 0) {
+ if (errno == EBUSY)
+ printf("line busy...");
+ else
+ printf("acu open error...");
+ return (0);
+ }
+ if (setjmp(jmpbuf)) {
+ kill(child, SIGKILL);
+ close(AC);
+ return (0);
+ }
+ signal(SIGALRM, alarmtr);
+ timelim = 5 * strlen(num);
+ alarm(timelim < 30 ? 30 : timelim);
+ if ((child = fork()) == 0) {
+ /*
+ * ignore this stuff for aborts
+ */
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ sleep(2);
+ exit(dialit(num, acu) != 'A');
+ }
+ /*
+ * open line - will return on carrier
+ */
+ if ((FD = open(DV, O_RDWR)) < 0) {
+#ifdef DEBUG
+ printf("(after open, errno=%d)\n", errno);
+#endif
+ if (errno == EIO)
+ printf("lost carrier...");
+ else
+ printf("dialup line open failed...");
+ alarm(0);
+ kill(child, SIGKILL);
+ close(AC);
+ return (0);
+ }
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+ while ((pid = wait(&status)) != child && pid != -1)
+ ;
+ if (status) {
+ close(AC);
+ return (0);
+ }
+ return (1);
+}
+
+/*ARGSUSED*/
+static void
+alarmtr(int signo)
+{
+ alarm(0);
+ longjmp(jmpbuf, 1);
+}
+
+/*
+ * Insurance, for some reason we don't seem to be
+ * hanging up...
+ */
+void
+v831_disconnect(void)
+{
+ struct termios cntrl;
+
+ sleep(2);
+#ifdef DEBUG
+ printf("[disconnect: FD=%d]\n", FD);
+#endif
+ if (FD > 0) {
+ ioctl(FD, TIOCCDTR, 0);
+ tcgetattr(FD, &cntrl);
+ cfsetospeed(&cntrl, 0);
+ cfsetispeed(&cntrl, 0);
+ tcsetattr(FD, TCSAFLUSH, &cntrl);
+ ioctl(FD, TIOCNXCL, NULL);
+ }
+ close(FD);
+}
+
+void
+v831_abort(void)
+{
+#ifdef DEBUG
+ printf("[abort: AC=%d]\n", AC);
+#endif
+ sleep(2);
+ if (child > 0)
+ kill(child, SIGKILL);
+ if (FD > 0)
+ ioctl(FD, TIOCNXCL, NULL);
+ close(AC);
+ if (FD > 0)
+ ioctl(FD, TIOCCDTR, 0);
+ close(FD);
+}
+
+/*
+ * Sigh, this probably must be changed at each site.
+ */
+struct vaconfig {
+ char *vc_name;
+ char vc_rack;
+ char vc_modem;
+} vaconfig[] = {
+ { "/dev/cua0",'4','0' },
+ { "/dev/cua1",'4','1' },
+ { NULL, '\0', '\0' }
+};
+
+#define pc(x) (c = x, write(AC,&c,1))
+#define ABORT 01
+#define SI 017
+#define STX 02
+#define ETX 03
+
+static int
+dialit(char *phonenum, char *acu)
+{
+ struct vaconfig *vp;
+ struct termios cntrl;
+ char c;
+ int i;
+
+ phonenum = sanitize(phonenum);
+#ifdef DEBUG
+ printf ("(dial phonenum=%s)\n", phonenum);
+#endif
+ if (*phonenum == '<' && phonenum[1] == 0)
+ return ('Z');
+ for (vp = vaconfig; vp->vc_name; vp++)
+ if (strcmp(vp->vc_name, acu) == 0)
+ break;
+ if (vp->vc_name == 0) {
+ printf("Unable to locate dialer (%s)\n", acu);
+ return ('K');
+ }
+ tcgetattr(AC, &cntrl);
+ cfsetospeed(&cntrl, B2400);
+ cfsetispeed(&cntrl, B2400);
+ cntrl.c_cflag |= PARODD | PARENB;
+ cntrl.c_lflag &= ~(ISIG | ICANON);
+ tcsetattr(AC, TCSANOW, &cntrl);
+ tcflush(AC, TCIOFLUSH);
+ pc(STX);
+ pc(vp->vc_rack);
+ pc(vp->vc_modem);
+ while (*phonenum && *phonenum != '<')
+ pc(*phonenum++);
+ pc(SI);
+ pc(ETX);
+ sleep(1);
+ i = read(AC, &c, 1);
+#ifdef DEBUG
+ printf("read %d chars, char=%c, errno %d\n", i, c, errno);
+#endif
+ if (i != 1)
+ c = 'M';
+ if (c == 'B' || c == 'G') {
+ char cc, oc = c;
+
+ pc(ABORT);
+ read(AC, &cc, 1);
+#ifdef DEBUG
+ printf("abort response=%c\n", cc);
+#endif
+ c = oc;
+ v831_disconnect();
+ }
+ close(AC);
+#ifdef DEBUG
+ printf("dialit: returns %c\n", c);
+#endif
+ return (c);
+}
+
+static char *
+sanitize(char *s)
+{
+ static char buf[128];
+ char *cp;
+
+ for (cp = buf; *s; s++) {
+ if (!isdigit(*s) && *s == '<' && *s != '_')
+ continue;
+ if (*s == '_')
+ *s = '=';
+ *cp++ = *s;
+ }
+ *cp++ = 0;
+ return (buf);
+}
diff --git a/usr.bin/tip/libacu/ventel.c b/usr.bin/tip/libacu/ventel.c
new file mode 100644
index 000000000000..603c18e4b5ef
--- /dev/null
+++ b/usr.bin/tip/libacu/ventel.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: ventel.c,v 1.12 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: ventel.c,v 1.6 1997/02/11 09:24:21 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Routines for calling up on a Ventel Modem
+ * The Ventel is expected to be strapped for local echo (just like uucp)
+ */
+#include "tip.h"
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#define MAXRETRY 5
+
+static int dialtimeout = 0;
+static jmp_buf timeoutbuf;
+
+static void echo(char *);
+static void sigALRM(int);
+static int gobble(char, char *);
+static int vensync(int);
+
+/*
+ * some sleep calls have been replaced by this macro
+ * because some ventel modems require two <cr>s in less than
+ * a second in order to 'wake up'... yes, it is dirty...
+ */
+#define delay(num,denom) busyloop(CPUSPEED*num/denom)
+#define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
+#define DELAY(n) do { long N = (n); while (--N > 0); } while (0)
+#define busyloop(n) do { DELAY(n); } while (0)
+
+int
+ven_dialer(char *num, char *acu)
+{
+ char *cp;
+ int connected = 0;
+ char *msg, line[80];
+ struct termios cntrl;
+
+ /*
+ * Get in synch with a couple of carriage returns
+ */
+ if (!vensync(FD)) {
+ printf("can't synchronize with ventel\n");
+#ifdef ACULOG
+ logent(value(HOST), num, "ventel", "can't synch up");
+#endif
+ return (0);
+ }
+ if (boolean(value(VERBOSE)))
+ printf("\ndialing...");
+ fflush(stdout);
+ tcgetattr(FD, &cntrl);
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSANOW, &cntrl);
+ echo("#k$\r$\n$D$I$A$L$:$ ");
+ for (cp = num; *cp; cp++) {
+ delay(1, 10);
+ write(FD, cp, 1);
+ }
+ delay(1, 10);
+ write(FD, "\r", 1);
+ gobble('\n', line);
+ if (gobble('\n', line))
+ connected = gobble('!', line);
+ tcflush(FD, TCIOFLUSH);
+#ifdef ACULOG
+ if (dialtimeout) {
+ (void)snprintf(line, sizeof line, "%ld second dial timeout",
+ number(value(DIALTIMEOUT)));
+ logent(value(HOST), num, "ventel", line);
+ }
+#endif
+ if (dialtimeout)
+ ven_disconnect(); /* insurance */
+ if (connected || dialtimeout || !boolean(value(VERBOSE)))
+ return (connected);
+ /* call failed, parse response for user */
+ cp = strchr(line, '\r');
+ if (cp)
+ *cp = '\0';
+ for (cp = line; (cp = strchr(cp, ' ')) != NULL; cp++)
+ if (cp[1] == ' ')
+ break;
+ if (cp) {
+ while (*cp == ' ')
+ cp++;
+ msg = cp;
+ while (*cp) {
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ cp++;
+ }
+ printf("%s...", msg);
+ }
+ return (connected);
+}
+
+void
+ven_disconnect(void)
+{
+ close(FD);
+}
+
+void
+ven_abort(void)
+{
+ write(FD, "\03", 1);
+ close(FD);
+}
+
+static void
+echo(char *s)
+{
+ char c;
+
+ while ((c = *s++) != '\0')
+ switch (c) {
+ case '$':
+ read(FD, &c, 1);
+ s++;
+ break;
+
+ case '#':
+ c = *s++;
+ write(FD, &c, 1);
+ break;
+
+ default:
+ write(FD, &c, 1);
+ read(FD, &c, 1);
+ }
+}
+
+/*ARGSUSED*/
+static void
+sigALRM(int signo)
+{
+ printf("\07timeout waiting for reply\n");
+ dialtimeout = 1;
+ longjmp(timeoutbuf, 1);
+}
+
+static int
+gobble(char match, char response[])
+{
+ char *cp = response;
+ sig_t f;
+ char c;
+
+ f = signal(SIGALRM, sigALRM);
+ dialtimeout = 0;
+ do {
+ if (setjmp(timeoutbuf)) {
+ signal(SIGALRM, f);
+ *cp = '\0';
+ return (0);
+ }
+ alarm(number(value(DIALTIMEOUT)));
+ read(FD, cp, 1);
+ alarm(0);
+ c = (*cp++ &= 0177);
+#ifdef notdef
+ if (boolean(value(VERBOSE)))
+ putchar(c);
+#endif
+ } while (c != '\n' && c != match);
+ signal(SIGALRM, SIG_DFL);
+ *cp = '\0';
+ return (c == match);
+}
+
+#define min(a,b) ((a)>(b)?(b):(a))
+/*
+ * This convoluted piece of code attempts to get
+ * the ventel in sync. If you don't have FIONREAD
+ * there are gory ways to simulate this.
+ */
+static int
+vensync(int fd)
+{
+ int already = 0, nread;
+ char buf[60];
+
+ /*
+ * Toggle DTR to force anyone off that might have left
+ * the modem connected, and insure a consistent state
+ * to start from.
+ *
+ * If you don't have the ioctl calls to diddle directly
+ * with DTR, you can always try setting the baud rate to 0.
+ */
+ ioctl(FD, TIOCCDTR, 0);
+ sleep(1);
+ ioctl(FD, TIOCSDTR, 0);
+ while (already < MAXRETRY) {
+ /*
+ * After reseting the modem, send it two \r's to
+ * autobaud on. Make sure to delay between them
+ * so the modem can frame the incoming characters.
+ */
+ write(fd, "\r", 1);
+ delay(1,10);
+ write(fd, "\r", 1);
+ sleep(2);
+ if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
+ perror("tip: ioctl");
+ continue;
+ }
+ while (nread > 0) {
+ read(fd, buf, min(nread, 60));
+ if ((buf[nread - 1] & 0177) == '$')
+ return (1);
+ nread -= min(nread, 60);
+ }
+ sleep(1);
+ already++;
+ }
+ return (0);
+}
diff --git a/usr.bin/tip/tip/Makefile b/usr.bin/tip/tip/Makefile
new file mode 100644
index 000000000000..85c9ea0c1c29
--- /dev/null
+++ b/usr.bin/tip/tip/Makefile
@@ -0,0 +1,60 @@
+# $OpenBSD: Makefile,v 1.11 2006/05/25 08:41:52 jmc Exp $
+#
+# Files are:
+# /etc/remote remote host description file
+# /etc/phones phone number file, owned by ${OWNER} and
+# mode 6??
+# /var/log/aculog ACU accounting file, owned by ${OWNER} and
+# mode 6?? {if ACULOG defined}
+# Presently supports:
+# BIZCOMP
+# DEC DF02-AC, DF03-AC
+# DEC DN-11/Able Quadracall
+# HAYES and Hayes emulators
+# USR COURIER (2400 baud)
+# VENTEL 212+
+# VADIC 831 RS232 adaptor
+# VADIC 3451
+# TELEBIT T3000
+#
+# Configuration defines:
+# DF02, DF03, DN11 ACU's supported
+# BIZ1031, BIZ1022, VENTEL, V831, V3451, HAYES, COURIER, T3000
+# ACULOG turn on tip logging of ACU use
+# PRISTINE no phone #'s put in ACU log file
+# CONNECT worthless command
+# DEFBR default baud rate to make connection at
+# DEFFS default frame size for FTP buffering of
+# writes on local side
+# BUFSIZ buffer sizing from stdio, must be fed
+# explicitly to remcap.c if not 1024
+# CONNECT enable ~C command (connect pgm to remote)
+
+CONFS= phones remote
+PROG= tip
+LINKS= ${BINDIR}/tip ${BINDIR}/cu
+MAN= tip.1 cu.1
+CFLAGS+=-I${.CURDIR} -DDEFBR=9600 -DDEFFS=BUFSIZ -DACULOG -DPRISTINE \
+ -DCONNECT -DV831 -DVENTEL -DHAYES -DCOURIER -DT3000
+WARNS?= 2
+.PATH: ${.CURDIR}/../libacu
+SRCS= acu.c acutab.c cmds.c cmdtab.c cu.c hunt.c log.c partab.c \
+ remote.c tip.c tipout.c uucplock.c value.c vars.c \
+ biz22.c courier.c df.c dn11.c hayes.c t3000.c v3451.c v831.c ventel.c
+
+# -- acutab is configuration dependent, and so depends on the Makefile
+# -- remote.o depends on the Makefile because of DEFBR and DEFFS
+# -- log.o depends on the Makefile because of ACULOG
+acutab.o log.o remote.o: Makefile
+
+# Don't rebuild based on remote.c
+remote: .MADE
+
+.include <bsd.prog.mk>
+
+# Dirty, rotten hack. This can be removed when we are confident that there
+# is no cu(1) with the schg-bit set.
+beforeinstall:
+.if exists(${DESTDIR}${BINDIR}/cu)
+ -chflags noschg ${DESTDIR}${BINDIR}/cu
+.endif
diff --git a/usr.bin/tip/tip/Makefile.depend b/usr.bin/tip/tip/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/tip/tip/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tip/tip/acu.c b/usr.bin/tip/tip/acu.c
new file mode 100644
index 000000000000..a2c672eb888c
--- /dev/null
+++ b/usr.bin/tip/tip/acu.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: acu.c,v 1.12 2006/03/17 14:43:06 moritz Exp $ */
+/* $NetBSD: acu.c,v 1.4 1996/12/29 10:34:03 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+static acu_t *acu = NOACU;
+static int conflag;
+static void acuabort(int);
+static acu_t *acutype(char *);
+static jmp_buf jmpbuf;
+/*
+ * Establish connection for tip
+ *
+ * If DU is true, we should dial an ACU whose type is AT.
+ * The phone numbers are in PN, and the call unit is in CU.
+ *
+ * If the PN is an '@', then we consult the PHONES file for
+ * the phone numbers. This file is /etc/phones, unless overridden
+ * by an exported shell variable.
+ *
+ * The data base files must be in the format:
+ * host-name[ \t]*phone-number
+ * with the possibility of multiple phone numbers
+ * for a single host acting as a rotary (in the order
+ * found in the file).
+ */
+char *
+con(void)
+{
+ char *cp = PN;
+ char *phnum, string[256];
+ FILE *fd;
+ volatile int tried = 0;
+
+ if (!DU) { /* regular connect message */
+ if (CM != NOSTR)
+ parwrite(FD, CM, size(CM));
+ logent(value(HOST), "", DV, "call completed");
+ return (NOSTR);
+ }
+ /*
+ * @ =>'s use data base in PHONES environment variable
+ * otherwise, use /etc/phones
+ */
+ signal(SIGINT, acuabort);
+ signal(SIGQUIT, acuabort);
+ if (setjmp(jmpbuf)) {
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ printf("\ncall aborted\n");
+ logent(value(HOST), "", "", "call aborted");
+ if (acu != NOACU) {
+ setboolean(value(VERBOSE), FALSE);
+ if (conflag)
+ disconnect(NOSTR);
+ else
+ (*acu->acu_abort)();
+ }
+ return ("interrupt");
+ }
+ if ((acu = acutype(AT)) == NOACU)
+ return ("unknown ACU type");
+ if (*cp != '@') {
+ while (*cp) {
+ phnum = cp;
+ cp += strcspn(cp, ",");
+ if (*cp != '\0')
+ *cp++ = '\0';
+
+ if (strlen(phnum) == 0)
+ continue;
+
+ conflag = (*acu->acu_dialer)(phnum, CU);
+ if (conflag)
+ break;
+
+ logent(value(HOST), phnum, acu->acu_name, "call failed");
+ tried++;
+ }
+ } else {
+ if ((fd = fopen(PH, "r")) == NOFILE) {
+ printf("%s: ", PH);
+ return ("can't open phone number file");
+ }
+ while (fgets(string, sizeof(string), fd) != NOSTR) {
+ cp = &string[strcspn(string, " \t\n")];
+ if (*cp != '\0')
+ *cp++ = '\0';
+
+ if (strcmp(string, value(HOST)) != 0)
+ continue;
+
+ cp += strspn(cp, " \t\n");
+ phnum = cp;
+ *(cp + strcspn(cp, ",\n")) = '\0';
+
+ if (strlen(phnum) == 0)
+ continue;
+
+ conflag = (*acu->acu_dialer)(phnum, CU);
+ if (conflag)
+ break;
+
+ logent(value(HOST), phnum, acu->acu_name, "call failed");
+ tried++;
+ }
+ fclose(fd);
+ }
+ if (conflag) {
+ if (CM != NOSTR)
+ parwrite(FD, CM, size(CM));
+ logent(value(HOST), phnum, acu->acu_name, "call completed");
+ return (NOSTR);
+ } else if (!tried) {
+ logent(value(HOST), "", acu->acu_name, "missing phone number");
+ return ("missing phone number");
+ } else {
+ (*acu->acu_abort)();
+ return ("call failed");
+ }
+}
+
+void
+disconnect(char *reason)
+{
+ if (!conflag) {
+ logent(value(HOST), "", DV, "call terminated");
+ return;
+ }
+ if (reason == NOSTR) {
+ logent(value(HOST), "", acu->acu_name, "call terminated");
+ if (boolean(value(VERBOSE)))
+ printf("\r\ndisconnecting...");
+ } else
+ logent(value(HOST), "", acu->acu_name, reason);
+ (*acu->acu_disconnect)();
+}
+
+static void
+acuabort(int s)
+{
+ signal(s, SIG_IGN);
+ longjmp(jmpbuf, 1);
+}
+
+static acu_t *
+acutype(char *s)
+{
+ acu_t *p;
+ extern acu_t acutable[];
+
+ for (p = acutable; p->acu_name != NULL; p++)
+ if (!strcmp(s, p->acu_name))
+ return (p);
+ return (NOACU);
+}
diff --git a/usr.bin/tip/tip/acutab.c b/usr.bin/tip/tip/acutab.c
new file mode 100644
index 000000000000..67cfad514731
--- /dev/null
+++ b/usr.bin/tip/tip/acutab.c
@@ -0,0 +1,81 @@
+/* $OpenBSD: acutab.c,v 1.5 2006/03/17 19:17:13 moritz Exp $ */
+/* $NetBSD: acutab.c,v 1.3 1994/12/08 09:30:41 jtc Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+acu_t acutable[] = {
+#if BIZ1031
+ { "biz31f", biz31f_dialer, biz31_disconnect, biz31_abort },
+ { "biz31w", biz31w_dialer, biz31_disconnect, biz31_abort },
+#endif
+#if BIZ1022
+ { "biz22f", biz22f_dialer, biz22_disconnect, biz22_abort },
+ { "biz22w", biz22w_dialer, biz22_disconnect, biz22_abort },
+#endif
+#if DF02
+ { "df02", df02_dialer, df_disconnect, df_abort },
+#endif
+#if DF03
+ { "df03", df03_dialer, df_disconnect, df_abort },
+#endif
+#if DN11
+ { "dn11", dn_dialer, dn_disconnect, dn_abort },
+#endif
+#ifdef VENTEL
+ { "ventel", ven_dialer, ven_disconnect, ven_abort },
+#endif
+#ifdef HAYES
+ { "hayes", hay_dialer, hay_disconnect, hay_abort },
+#endif
+#ifdef COURIER
+ { "courier", cour_dialer, cour_disconnect, cour_abort },
+#endif
+#ifdef T3000
+ { "t3000", t3000_dialer, t3000_disconnect, t3000_abort },
+#endif
+#ifdef V3451
+#ifndef V831
+ { "vadic", v3451_dialer, v3451_disconnect, v3451_abort },
+#endif
+ { "v3451", v3451_dialer, v3451_disconnect, v3451_abort },
+#endif
+#ifdef V831
+#ifndef V3451
+ { "vadic", v831_dialer, v831_disconnect, v831_abort },
+#endif
+ { "v831", v831_dialer, v831_disconnect, v831_abort },
+#endif
+ { 0, 0, 0, 0 }
+};
+
diff --git a/usr.bin/tip/tip/cmds.c b/usr.bin/tip/tip/cmds.c
new file mode 100644
index 000000000000..28135f5accbd
--- /dev/null
+++ b/usr.bin/tip/tip/cmds.c
@@ -0,0 +1,991 @@
+/* $OpenBSD: cmds.c,v 1.26 2006/06/06 23:24:52 deraadt Exp $ */
+/* $NetBSD: cmds.c,v 1.7 1997/02/11 09:24:03 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+#include "pathnames.h"
+
+#include <vis.h>
+
+/*
+ * tip
+ *
+ * miscellaneous commands
+ */
+
+int quant[] = { 60, 60, 24 };
+
+char null = '\0';
+char *sep[] = { "second", "minute", "hour" };
+static char *argv[10]; /* argument vector for take and put */
+
+static void transfer(char *, int, char *);
+static void stopsnd(int); /* SIGINT handler during file transfers */
+static void intcopy(int); /* interrupt routine for file transfers */
+static void transmit(FILE *, char *, char *);
+static void send(int);
+static void execute(char *);
+static int args(char *, char **, int);
+static void prtime(char *, time_t);
+static void tandem(char *);
+static void hardwareflow(char *);
+void linedisc(char *);
+static int anyof(char *, char *);
+
+/*
+ * FTP - remote ==> local
+ * get a file from the remote host
+ */
+void
+getfl(int c)
+{
+ char buf[256], *cp;
+
+ putchar(c);
+ /*
+ * get the UNIX receiving file's name
+ */
+ if (prompt("Local file name? ", copyname, sizeof(copyname)))
+ return;
+ cp = expand(copyname);
+ if ((sfd = creat(cp, 0666)) < 0) {
+ printf("\r\n%s: cannot creat\r\n", copyname);
+ return;
+ }
+
+ /*
+ * collect parameters
+ */
+ if (prompt("List command for remote system? ", buf, sizeof(buf))) {
+ unlink(copyname);
+ return;
+ }
+ transfer(buf, sfd, value(EOFREAD));
+}
+
+/*
+ * Cu-like take command
+ */
+void
+cu_take(int c)
+{
+ int fd, argc;
+ char line[BUFSIZ], *cp;
+
+ if (prompt("[take] ", copyname, sizeof(copyname)))
+ return;
+ if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 ||
+ argc > 2) {
+ printf("usage: <take> from [to]\r\n");
+ return;
+ }
+ if (argc == 1)
+ argv[1] = argv[0];
+ cp = expand(argv[1]);
+ if ((fd = creat(cp, 0666)) < 0) {
+ printf("\r\n%s: cannot create\r\n", argv[1]);
+ return;
+ }
+ (void)snprintf(line, sizeof(line), "cat %s;echo ''|tr '\\012' '\\01'", argv[0]);
+ transfer(line, fd, "\01");
+}
+
+static jmp_buf intbuf;
+
+/*
+ * Bulk transfer routine --
+ * used by getfl(), cu_take(), and pipefile()
+ */
+static void
+transfer(char *buf, int fd, char *eofchars)
+{
+ int ct, eof;
+ char c, buffer[BUFSIZ];
+ char *p = buffer;
+ size_t cnt;
+ time_t start;
+ sig_t f;
+ char r;
+
+ if (number(value(FRAMESIZE)) > BUFSIZ || number(value(FRAMESIZE)) < 1) {
+ printf("framesize must be >= 1 and <= %d\r\n", BUFSIZ);
+ close(fd);
+ return;
+ }
+
+ parwrite(FD, buf, size(buf));
+ quit = 0;
+ kill(tipout_pid, SIGIOT);
+ read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
+
+ /*
+ * finish command
+ */
+ r = '\r';
+ parwrite(FD, &r, 1);
+ do
+ read(FD, &c, 1);
+ while ((c&STRIP_PAR) != '\n');
+ tcsetattr(0, TCSAFLUSH, &defchars);
+
+ (void) setjmp(intbuf);
+ f = signal(SIGINT, intcopy);
+ start = time(0);
+ for (ct = 0; !quit;) {
+ eof = read(FD, &c, 1) <= 0;
+ c &= STRIP_PAR;
+ if (quit)
+ continue;
+ if (eof || any(c, eofchars))
+ break;
+ if (c == 0)
+ continue; /* ignore nulls */
+ if (c == '\r')
+ continue;
+ *p++ = c;
+
+ if (c == '\n' && boolean(value(VERBOSE)))
+ printf("\r%d", ++ct);
+ if ((cnt = (p-buffer)) == (size_t)number(value(FRAMESIZE))) {
+ if ((size_t)write(fd, buffer, cnt) != cnt) {
+ printf("\r\nwrite error\r\n");
+ quit = 1;
+ }
+ p = buffer;
+ }
+ }
+ if ((cnt = (p-buffer)))
+ if ((size_t)write(fd, buffer, cnt) != cnt)
+ printf("\r\nwrite error\r\n");
+
+ if (boolean(value(VERBOSE)))
+ prtime(" lines transferred in ", time(0)-start);
+ tcsetattr(0, TCSAFLUSH, &term);
+ write(fildes[1], (char *)&ccc, 1);
+ signal(SIGINT, f);
+ close(fd);
+}
+
+/*
+ * FTP - remote ==> local process
+ * send remote input to local process via pipe
+ */
+/*ARGSUSED*/
+void
+pipefile(int c)
+{
+ int pdes[2];
+ char buf[256];
+ int status, p;
+ pid_t cpid;
+
+ if (prompt("Local command? ", buf, sizeof(buf)))
+ return;
+
+ if (pipe(pdes)) {
+ printf("can't establish pipe\r\n");
+ return;
+ }
+
+ if ((cpid = fork()) < 0) {
+ printf("can't fork!\r\n");
+ return;
+ } else if (cpid) {
+ if (prompt("List command for remote system? ", buf, sizeof(buf))) {
+ close(pdes[0]), close(pdes[1]);
+ kill (cpid, SIGKILL);
+ } else {
+ close(pdes[0]);
+ signal(SIGPIPE, intcopy);
+ transfer(buf, pdes[1], value(EOFREAD));
+ signal(SIGPIPE, SIG_DFL);
+ while ((p = wait(&status)) > 0 && p != cpid)
+ ;
+ }
+ } else {
+ int f;
+
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ for (f = 3; f < 20; f++)
+ close(f);
+ execute(buf);
+ printf("can't execl!\r\n");
+ exit(0);
+ }
+}
+
+/*
+ * Interrupt service routine for FTP
+ */
+/*ARGSUSED*/
+static void
+stopsnd(int signo)
+{
+ stop = 1;
+ signal(SIGINT, SIG_IGN);
+}
+
+/*
+ * FTP - local ==> remote
+ * send local file to remote host
+ * terminate transmission with pseudo EOF sequence
+ */
+void
+sendfile(int c)
+{
+ FILE *fp;
+ char *fnamex;
+
+ putchar(c);
+ /*
+ * get file name
+ */
+ if (prompt("Local file name? ", fname, sizeof(fname)))
+ return;
+
+ /*
+ * look up file
+ */
+ fnamex = expand(fname);
+ if ((fp = fopen(fnamex, "r")) == NULL) {
+ printf("%s: cannot open\r\n", fname);
+ return;
+ }
+ transmit(fp, value(EOFWRITE), NULL);
+ if (!boolean(value(ECHOCHECK)))
+ tcdrain(FD);
+}
+
+/*
+ * Bulk transfer routine to remote host --
+ * used by sendfile() and cu_put()
+ */
+static void
+transmit(FILE *fp, char *eofchars, char *command)
+{
+ char *pc, lastc;
+ int c, ccount, lcount;
+ time_t start_t, stop_t;
+ sig_t f;
+
+ kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */
+ stop = 0;
+ f = signal(SIGINT, stopsnd);
+ tcsetattr(0, TCSAFLUSH, &defchars);
+ read(repdes[0], (char *)&ccc, 1);
+ if (command != NULL) {
+ for (pc = command; *pc; pc++)
+ send(*pc);
+ if (boolean(value(ECHOCHECK)))
+ read(FD, (char *)&c, 1); /* trailing \n */
+ else {
+ tcdrain(FD);
+ sleep(5); /* wait for remote stty to take effect */
+ }
+ }
+ lcount = 0;
+ lastc = '\0';
+ start_t = time(0);
+ while (1) {
+ ccount = 0;
+ do {
+ c = getc(fp);
+ if (stop)
+ goto out;
+ if (c == EOF)
+ goto out;
+ if (c == 0177 && !boolean(value(RAWFTP)))
+ continue;
+ lastc = c;
+ if (c < 040) {
+ if (c == '\n') {
+ if (!boolean(value(RAWFTP)))
+ c = '\r';
+ } else if (c == '\t') {
+ if (!boolean(value(RAWFTP))) {
+ if (boolean(value(TABEXPAND))) {
+ send(' ');
+ while ((++ccount % 8) != 0)
+ send(' ');
+ continue;
+ }
+ }
+ } else
+ if (!boolean(value(RAWFTP)))
+ continue;
+ }
+ send(c);
+ } while (c != '\r' && !boolean(value(RAWFTP)));
+ if (boolean(value(VERBOSE)))
+ printf("\r%d", ++lcount);
+ if (boolean(value(ECHOCHECK))) {
+ timedout = 0;
+ alarm((unsigned int)lvalue(ETIMEOUT));
+ do { /* wait for prompt */
+ read(FD, (char *)&c, 1);
+ if (timedout || stop) {
+ if (timedout)
+ printf("\r\ntimed out at eol\r\n");
+ alarm(0);
+ goto out;
+ }
+ } while ((c&STRIP_PAR) != character(value(PROMPT)));
+ alarm(0);
+ }
+ }
+out:
+ if (lastc != '\n' && !boolean(value(RAWFTP)))
+ send('\r');
+ if (eofchars) {
+ for (pc = eofchars; *pc; pc++)
+ send(*pc);
+ }
+ stop_t = time(0);
+ fclose(fp);
+ signal(SIGINT, f);
+ if (boolean(value(VERBOSE))) {
+ if (boolean(value(RAWFTP)))
+ prtime(" chars transferred in ", stop_t-start_t);
+ else
+ prtime(" lines transferred in ", stop_t-start_t);
+ }
+ write(fildes[1], (char *)&ccc, 1);
+ tcsetattr(0, TCSAFLUSH, &term);
+}
+
+/*
+ * Cu-like put command
+ */
+/*ARGSUSED*/
+void
+cu_put(int c)
+{
+ FILE *fp;
+ char line[BUFSIZ];
+ int argc;
+ char *copynamex;
+
+ if (prompt("[put] ", copyname, sizeof(copyname)))
+ return;
+ if ((argc = args(copyname, argv, sizeof(argv)/sizeof(argv[0]))) < 1 ||
+ argc > 2) {
+ printf("usage: <put> from [to]\r\n");
+ return;
+ }
+ if (argc == 1)
+ argv[1] = argv[0];
+ copynamex = expand(argv[0]);
+ if ((fp = fopen(copynamex, "r")) == NULL) {
+ printf("%s: cannot open\r\n", copynamex);
+ return;
+ }
+ if (boolean(value(ECHOCHECK)))
+ (void)snprintf(line, sizeof(line), "cat>%s\r", argv[1]);
+ else
+ (void)snprintf(line, sizeof(line),
+ "stty -echo;cat>%s;stty echo\r", argv[1]);
+ transmit(fp, "\04", line);
+}
+
+/*
+ * FTP - send single character
+ * wait for echo & handle timeout
+ */
+static void
+send(int c)
+{
+ char cc;
+ int retry = 0;
+
+ cc = c;
+ parwrite(FD, &cc, 1);
+ if (number(value(CDELAY)) > 0 && c != '\r')
+ usleep(number(value(CDELAY)));
+ if (!boolean(value(ECHOCHECK))) {
+ if (number(value(LDELAY)) > 0 && c == '\r')
+ usleep(number(value(LDELAY)));
+ return;
+ }
+tryagain:
+ timedout = 0;
+ alarm((unsigned int)lvalue(ETIMEOUT));
+ read(FD, &cc, 1);
+ alarm(0);
+ if (timedout) {
+ printf("\r\ntimeout error (%s)\r\n", ctrl(c));
+ if (retry++ > 3)
+ return;
+ parwrite(FD, &null, 1); /* poke it */
+ goto tryagain;
+ }
+}
+
+/*ARGSUSED*/
+void
+timeout(int signo)
+{
+ signal(SIGALRM, timeout);
+ timedout = 1;
+}
+
+/*
+ * Stolen from consh() -- puts a remote file on the output of a local command.
+ * Identical to consh() except for where stdout goes.
+ */
+void
+pipeout(int c)
+{
+ char buf[256];
+ int status, p;
+ pid_t cpid;
+ time_t start = time(NULL);
+
+ putchar(c);
+ if (prompt("Local command? ", buf, sizeof(buf)))
+ return;
+ kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ tcsetattr(0, TCSAFLUSH, &defchars);
+ read(repdes[0], (char *)&ccc, 1);
+ /*
+ * Set up file descriptors in the child and
+ * let it go...
+ */
+ if ((cpid = fork()) < 0)
+ printf("can't fork!\r\n");
+ else if (cpid) {
+ start = time(NULL);
+ while ((p = wait(&status)) > 0 && p != cpid)
+ ;
+ } else {
+ int i;
+
+ dup2(FD, 1);
+ for (i = 3; i < 20; i++)
+ close(i);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ execute(buf);
+ printf("can't find `%s'\r\n", buf);
+ exit(0);
+ }
+ if (boolean(value(VERBOSE)))
+ prtime("away for ", time(0)-start);
+ write(fildes[1], (char *)&ccc, 1);
+ tcsetattr(0, TCSAFLUSH, &term);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+}
+
+#ifdef CONNECT
+/*
+ * Fork a program with:
+ * 0 <-> remote tty in
+ * 1 <-> remote tty out
+ * 2 <-> local tty stderr
+ */
+void
+consh(int c)
+{
+ char buf[256];
+ int status, p;
+ pid_t cpid;
+ time_t start = time(NULL);
+
+ putchar(c);
+ if (prompt("Local command? ", buf, sizeof(buf)))
+ return;
+ kill(tipout_pid, SIGIOT); /* put TIPOUT into a wait state */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ tcsetattr(0, TCSAFLUSH, &defchars);
+ read(repdes[0], (char *)&ccc, 1);
+ /*
+ * Set up file descriptors in the child and
+ * let it go...
+ */
+ if ((cpid = fork()) < 0)
+ printf("can't fork!\r\n");
+ else if (cpid) {
+ start = time(0);
+ while ((p = wait(&status)) > 0 && p != cpid)
+ ;
+ } else {
+ int i;
+
+ dup2(FD, 0);
+ dup2(3, 1);
+ for (i = 3; i < 20; i++)
+ close(i);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ execute(buf);
+ printf("can't find `%s'\r\n", buf);
+ exit(0);
+ }
+ if (boolean(value(VERBOSE)))
+ prtime("away for ", time(0)-start);
+ write(fildes[1], (char *)&ccc, 1);
+ tcsetattr(0, TCSAFLUSH, &term);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+}
+#endif
+
+/*
+ * Escape to local shell
+ */
+/*ARGSUSED*/
+void
+shell(int c)
+{
+ int status;
+ char *cp;
+ pid_t shpid;
+
+ printf("[sh]\r\n");
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ unraw();
+ if ((shpid = fork())) {
+ while (shpid != wait(&status));
+ raw();
+ printf("\r\n!\r\n");
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ return;
+ } else {
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ if ((cp = strrchr(value(SHELL), '/')) == NULL)
+ cp = value(SHELL);
+ else
+ cp++;
+ shell_uid();
+ execl(value(SHELL), cp, (char *)NULL);
+ printf("\r\ncan't execl!\r\n");
+ exit(1);
+ }
+}
+
+/*
+ * TIPIN portion of scripting
+ * initiate the conversation with TIPOUT
+ */
+void
+setscript(void)
+{
+ char c;
+
+ /*
+ * enable TIPOUT side for dialogue
+ */
+ kill(tipout_pid, SIGEMT);
+ if (boolean(value(SCRIPT)))
+ write(fildes[1], value(RECORD), size(value(RECORD)));
+ write(fildes[1], "\n", 1);
+ /*
+ * wait for TIPOUT to finish
+ */
+ read(repdes[0], &c, 1);
+ if (c == 'n')
+ printf("can't create %s\r\n", value(RECORD));
+}
+
+/*
+ * Change current working directory of
+ * local portion of tip
+ */
+/*ARGSUSED*/
+void
+chdirectory(int c)
+{
+ char dirname[PATH_MAX];
+ char *cp = dirname;
+
+ if (prompt("[cd] ", dirname, sizeof(dirname))) {
+ if (stoprompt)
+ return;
+ cp = value(HOME);
+ }
+ if (chdir(cp) < 0)
+ printf("%s: bad directory\r\n", cp);
+ printf("!\r\n");
+}
+
+void
+tipabort(char *msg)
+{
+
+ signal(SIGTERM, SIG_IGN);
+ kill(tipout_pid, SIGTERM);
+ disconnect(msg);
+ if (msg != NOSTR)
+ printf("\r\n%s", msg);
+ printf("\r\n[EOT]\r\n");
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ unraw();
+ unexcl();
+ exit(0);
+}
+
+/*ARGSUSED*/
+void
+finish(int c)
+{
+ char *dismsg;
+
+ if ((dismsg = value(DISCONNECT)) != NOSTR) {
+ write(FD, dismsg, strlen(dismsg));
+ sleep(5);
+ }
+ tipabort(NOSTR);
+}
+
+/*ARGSUSED*/
+static void
+intcopy(int signo)
+{
+ raw();
+ quit = 1;
+ longjmp(intbuf, 1);
+}
+
+static void
+execute(char *s)
+{
+ char *cp;
+
+ if ((cp = strrchr(value(SHELL), '/')) == NULL)
+ cp = value(SHELL);
+ else
+ cp++;
+ shell_uid();
+ execl(value(SHELL), cp, "-c", s, (char *)NULL);
+}
+
+static int
+args(char *buf, char *a[], int num)
+{
+ char *p = buf, *start;
+ char **parg = a;
+ int n = 0;
+
+ do {
+ while (*p && (*p == ' ' || *p == '\t'))
+ p++;
+ start = p;
+ if (*p)
+ *parg = p;
+ while (*p && (*p != ' ' && *p != '\t'))
+ p++;
+ if (p != start)
+ parg++, n++;
+ if (*p)
+ *p++ = '\0';
+ } while (*p && n < num);
+
+ return(n);
+}
+
+static void
+prtime(char *s, time_t a)
+{
+ int i;
+ int nums[3];
+
+ for (i = 0; i < 3; i++) {
+ nums[i] = (int)(a % quant[i]);
+ a /= quant[i];
+ }
+ printf("%s", s);
+ while (--i >= 0)
+ if (nums[i] || (i == 0 && nums[1] == 0 && nums[2] == 0))
+ printf("%d %s%c ", nums[i], sep[i],
+ nums[i] == 1 ? '\0' : 's');
+ printf("\r\n!\r\n");
+}
+
+/*ARGSUSED*/
+void
+variable(int c)
+{
+ char buf[256];
+
+ if (prompt("[set] ", buf, sizeof(buf)))
+ return;
+ vlex(buf);
+ if (vtable[BEAUTIFY].v_access&CHANGED) {
+ vtable[BEAUTIFY].v_access &= ~CHANGED;
+ kill(tipout_pid, SIGSYS);
+ }
+ if (vtable[SCRIPT].v_access&CHANGED) {
+ vtable[SCRIPT].v_access &= ~CHANGED;
+ setscript();
+ /*
+ * So that "set record=blah script" doesn't
+ * cause two transactions to occur.
+ */
+ if (vtable[RECORD].v_access&CHANGED)
+ vtable[RECORD].v_access &= ~CHANGED;
+ }
+ if (vtable[RECORD].v_access&CHANGED) {
+ vtable[RECORD].v_access &= ~CHANGED;
+ if (boolean(value(SCRIPT)))
+ setscript();
+ }
+ if (vtable[TAND].v_access&CHANGED) {
+ vtable[TAND].v_access &= ~CHANGED;
+ if (boolean(value(TAND)))
+ tandem("on");
+ else
+ tandem("off");
+ }
+ if (vtable[LECHO].v_access&CHANGED) {
+ vtable[LECHO].v_access &= ~CHANGED;
+ HD = boolean(value(LECHO));
+ }
+ if (vtable[PARITY].v_access&CHANGED) {
+ vtable[PARITY].v_access &= ~CHANGED;
+ setparity(NOSTR);
+ }
+ if (vtable[HARDWAREFLOW].v_access&CHANGED) {
+ vtable[HARDWAREFLOW].v_access &= ~CHANGED;
+ if (boolean(value(HARDWAREFLOW)))
+ hardwareflow("on");
+ else
+ hardwareflow("off");
+ }
+ if (vtable[LINEDISC].v_access&CHANGED) {
+ vtable[LINEDISC].v_access &= ~CHANGED;
+ linedisc(NOSTR);
+ }
+}
+
+/*ARGSUSED*/
+void
+listvariables(int c)
+{
+ value_t *p;
+ char *buf;
+ char charbuf[5]; /* for vis(3), 4 chars for encoding, plus nul */
+
+ puts("v\r");
+ for (p = vtable; p->v_name; p++) {
+ fputs(p->v_name, stdout);
+ switch (p->v_type&TMASK) {
+ case STRING:
+ if (p->v_value) {
+ buf = malloc(4*strlen(p->v_value) + 1);
+ if (buf == NULL) {
+ fprintf(stderr, "Unable to malloc()\n");
+ abort();
+ }
+ strvis(buf, p->v_value, VIS_WHITE);
+ printf(" %s", buf);
+ free(buf);
+ }
+ putchar('\r');
+ putchar('\n');
+ break;
+ case NUMBER:
+ printf(" %ld\r\n", number(p->v_value));
+ break;
+ case BOOL:
+ printf(" %s\r\n",
+ !boolean(p->v_value) ? "false" : "true");
+ break;
+ case CHAR:
+ vis(charbuf, character(p->v_value), VIS_WHITE, 0);
+ printf(" %s\r\n", charbuf);
+ break;
+ }
+ }
+}
+
+/*
+ * Turn tandem mode on or off for remote tty.
+ */
+static void
+tandem(char *option)
+{
+ struct termios rmtty;
+
+ tcgetattr(FD, &rmtty);
+ if (strcmp(option, "on") == 0) {
+ rmtty.c_iflag |= IXOFF;
+ term.c_iflag |= IXOFF;
+ } else {
+ rmtty.c_iflag &= ~IXOFF;
+ term.c_iflag &= ~IXOFF;
+ }
+ tcsetattr(FD, TCSADRAIN, &rmtty);
+ tcsetattr(0, TCSADRAIN, &term);
+}
+
+/*
+ * Turn hardware flow control on or off for remote tty.
+ */
+static void
+hardwareflow(char *option)
+{
+ struct termios rmtty;
+
+ tcgetattr(FD, &rmtty);
+ if (strcmp(option, "on") == 0)
+ rmtty.c_iflag |= CRTSCTS;
+ else
+ rmtty.c_iflag &= ~CRTSCTS;
+ tcsetattr(FD, TCSADRAIN, &rmtty);
+}
+
+/*
+ * Change line discipline to the specified one.
+ */
+void
+linedisc(char *option)
+{
+ int ld = (int)(intptr_t)value(LINEDISC);
+
+ ioctl(FD, TIOCSETD, &ld);
+}
+
+/*
+ * Send a break.
+ */
+/*ARGSUSED*/
+void
+genbrk(int c)
+{
+ ioctl(FD, TIOCSBRK, NULL);
+ sleep(1);
+ ioctl(FD, TIOCCBRK, NULL);
+}
+
+/*
+ * Suspend tip
+ */
+void
+suspend(int c)
+{
+ unraw();
+ kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
+ raw();
+}
+
+/*
+ * expand a file name if it includes shell meta characters
+ */
+char *
+expand(char name[])
+{
+ static char xname[BUFSIZ];
+ char cmdbuf[BUFSIZ];
+ int l;
+ char *cp, *Shell;
+ int s, pivec[2];
+ pid_t pid;
+
+ if (!anyof(name, "~{[*?$`'\"\\"))
+ return(name);
+ /* sigint = signal(SIGINT, SIG_IGN); */
+ if (pipe(pivec) < 0) {
+ perror("pipe");
+ /* signal(SIGINT, sigint) */
+ return(name);
+ }
+ (void)snprintf(cmdbuf, sizeof(cmdbuf), "echo %s", name);
+ if ((pid = vfork()) == 0) {
+ Shell = value(SHELL);
+ if (Shell == NOSTR)
+ Shell = _PATH_BSHELL;
+ close(pivec[0]);
+ close(1);
+ dup(pivec[1]);
+ close(pivec[1]);
+ close(2);
+ shell_uid();
+ execl(Shell, Shell, "-c", cmdbuf, (char *)NULL);
+ _exit(1);
+ }
+ if (pid == -1) {
+ perror("fork");
+ close(pivec[0]);
+ close(pivec[1]);
+ return(NOSTR);
+ }
+ close(pivec[1]);
+ l = read(pivec[0], xname, BUFSIZ);
+ close(pivec[0]);
+ while (wait(&s) != pid);
+ ;
+ s &= 0377;
+ if (s != 0 && s != SIGPIPE) {
+ fprintf(stderr, "\"Echo\" failed\n");
+ return(NOSTR);
+ }
+ if (l < 0) {
+ perror("read");
+ return(NOSTR);
+ }
+ if (l == 0) {
+ fprintf(stderr, "\"%s\": No match\n", name);
+ return(NOSTR);
+ }
+ if (l == BUFSIZ) {
+ fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
+ return(NOSTR);
+ }
+ xname[l] = 0;
+ for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
+ ;
+ *++cp = '\0';
+ return(xname);
+}
+
+/*
+ * Are any of the characters in the two strings the same?
+ */
+static int
+anyof(char *s1, char *s2)
+{
+ int c;
+
+ while ((c = *s1++))
+ if (any(c, s2))
+ return(1);
+ return(0);
+}
diff --git a/usr.bin/tip/tip/cmdtab.c b/usr.bin/tip/tip/cmdtab.c
new file mode 100644
index 000000000000..7219a45355ff
--- /dev/null
+++ b/usr.bin/tip/tip/cmdtab.c
@@ -0,0 +1,58 @@
+/* $OpenBSD: cmdtab.c,v 1.7 2006/03/17 14:43:06 moritz Exp $ */
+/* $NetBSD: cmdtab.c,v 1.3 1994/12/08 09:30:46 jtc Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+esctable_t etable[] = {
+ { '!', NORM, "shell", shell },
+ { '<', NORM, "receive file from remote host", getfl },
+ { '>', NORM, "send file to remote host", sendfile },
+ { 't', NORM, "take file from remote UNIX", cu_take },
+ { 'p', NORM, "put file to remote UNIX", cu_put },
+ { '|', NORM, "pipe remote file", pipefile },
+ { '$', NORM, "pipe local command to remote host", pipeout },
+#ifdef CONNECT
+ { 'C', NORM, "connect program to remote host",consh },
+#endif
+ { 'c', NORM, "change directory", chdirectory },
+ { '.', NORM, "exit from tip", finish },
+ {CTRL('d'),NORM,"exit from tip", finish },
+ {CTRL('y'),NORM,"suspend tip (local+remote)", suspend },
+ {CTRL('z'),NORM,"suspend tip (local only)", suspend },
+ { 's', NORM, "set variable", variable },
+ { 'v', NORM, "list variables", listvariables },
+ { '?', NORM, "get this summary", help },
+ { '#', NORM, "send break", genbrk },
+ { '\0', 0, NULL, NULL }
+};
diff --git a/usr.bin/tip/tip/cu.1 b/usr.bin/tip/tip/cu.1
new file mode 100644
index 000000000000..5852a2a6e6d5
--- /dev/null
+++ b/usr.bin/tip/tip/cu.1
@@ -0,0 +1,511 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
+.\" $OpenBSD: cu.1,v 1.3 2006/06/07 06:35:59 mbalmer Exp $
+.\"
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd April 22, 2017
+.Dt CU 1
+.Os
+.Sh NAME
+.Nm cu
+.Nd call UNIX over a serial line
+.Sh SYNOPSIS
+.Nm
+.Op Fl ehot
+.Op Fl a Ar acu
+.Op Fl l Ar line
+.Op Fl s Ar speed | Fl Ar speed
+.Op Ar phone-number
+.Sh DESCRIPTION
+The
+.Nm
+utility
+establishes a full-duplex connection to another machine, giving the
+appearance of being logged in directly on the remote CPU.
+It goes without saying that you must have a login on the machine (or
+equivalent) to which you wish to connect.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a Ar acu
+Set the acu.
+.It Fl e
+Use even parity.
+If both
+.Fl e
+and
+.Fl o
+are given, then no parity is used
+(the default).
+.It Fl h
+Echo characters locally (half-duplex mode).
+.It Fl l Ar line
+Specify the line to use.
+Either of the forms like
+.Pa cuau0
+or
+.Pa /dev/cuau0
+are permitted.
+.It Fl o
+Use odd parity.
+If both
+.Fl e
+and
+.Fl o
+are given, then no parity is used
+(the default).
+.It Fl s Ar speed | Fl Ar speed
+Set the speed of the connection.
+The default is 9600.
+.It Fl t
+Connect via a hard-wired connection to a host on a dial-up line.
+.El
+.Pp
+Typed characters are normally transmitted directly to the remote
+machine (which does the echoing as well).
+A tilde
+.Pq Ql ~
+appearing as the first character of a line is an escape signal; the
+following are recognized:
+.Bl -tag -width indent
+.It Ic ~^D No or Ic ~.
+Drop the connection and exit.
+Only the connection is dropped \(en the login session is not terminated.
+.It Ic ~c Op Ar name
+Change directory to
+.Ar name
+(no argument implies change to home directory).
+.It Ic ~!
+Escape to a shell (exiting the shell will return to
+.Nm ) .
+.It Ic ~>
+Copy file from local to remote.
+The
+.Nm
+utility
+prompts for the name of a local file to transmit.
+.It Ic ~<
+Copy file from remote to local.
+The
+.Nm
+utility
+prompts first for the name of the file to be sent, then for a command
+to be executed on the remote machine.
+.It Ic ~p Ar from Op Ar to
+Send a file to a remote
+.Ux
+host.
+This command causes the remote
+.Ux
+system to run the following command string,
+sending it the
+.Ar from
+file:
+.Pp
+.Dl "stty -echo; cat > 'to'; stty echo"
+.Pp
+If the
+.Ar to
+file is not specified, the
+.Ar from
+file name is used.
+This command is actually a
+.Ux
+specific version of the
+.Ic ~>
+command.
+.It Ic ~t Ar from Op Ar to
+Take a file from a remote
+.Ux
+host.
+As in the
+.Ic ~p
+command, the
+.Ar to
+file defaults to the
+.Ar from
+file name if it is not specified.
+The remote host executes the following command string
+to send the file to
+.Nm :
+.Pp
+.Dl "cat 'from'; echo '' | tr '\e012' '\e01'"
+.It Ic ~|
+Pipe the output from a remote command to a local
+.Ux
+process.
+The command string sent to the local
+.Ux
+system is processed by the shell.
+.It Ic ~$
+Pipe the output from a local
+.Ux
+process to the remote host.
+The command string sent to the local
+.Ux
+system is processed by the shell.
+.It Ic ~C
+Fork a child process on the local system to perform special protocols
+such as
+.Tn XMODEM .
+The child program will be run with the following arrangement of
+file descriptors:
+.Bd -literal -offset indent
+0 <-> remote tty in
+1 <-> remote tty out
+2 <-> local tty stderr
+.Ed
+.It Ic ~#
+Send a
+.Dv BREAK
+to the remote system.
+For systems which do not support the necessary
+.Fn ioctl
+call, the break is simulated by a sequence of line speed changes and
+.Dv DEL
+characters.
+.It Ic ~s
+Set a variable (see the discussion below).
+.It Ic ~v
+List all variables and their values (if set).
+.It Ic ~^Z
+Stop
+.Nm
+(only available with job control).
+.It Ic ~^Y
+Stop only the
+.Dq "local side"
+of
+.Nm
+(only available with job control); the
+.Dq "remote side"
+of
+.Nm ,
+the side that displays output from the remote host, is left running.
+.It Ic ~?
+Get a summary of the tilde escapes.
+.El
+.Pp
+When
+.Nm
+prompts for an argument, for example during setup of a file transfer, the
+line typed may be edited with the standard erase and kill characters.
+A null line in response to a prompt, or an interrupt, will abort the
+dialogue and return the user to the remote machine.
+.Pp
+The
+.Nm
+utility
+guards against multiple users connecting to a remote system by opening
+modems and terminal lines with exclusive access, and by honoring the
+locking protocol used by
+.Xr uucico 8 Pq Pa ports/net/freebsd-uucp .
+.Pp
+During file transfers
+.Nm
+provides a running count of the number of lines transferred.
+When using the
+.Ic ~>
+and
+.Ic ~<
+commands, the
+.Va eofread
+and
+.Va eofwrite
+variables are used to recognize end-of-file when reading, and specify
+end-of-file when writing (see below).
+File transfers normally depend on hardwareflow or tandem mode for flow control.
+If the remote system does not support hardwareflow or tandem mode,
+.Va echocheck
+may be set to indicate that
+.Nm
+should synchronize with the remote system on the echo of each
+transmitted character.
+.Pp
+When
+.Nm
+must dial a phone number to connect to a system, it will print various
+messages indicating its actions.
+The
+.Nm
+utility
+supports a variety of auto-call units and modems with the
+.Va at
+capability in system descriptions.
+.Pp
+Support for Ventel 212+ (ventel), Hayes AT-style (hayes),
+USRobotics Courier (courier), Telebit T3000 (t3000) and
+Racal-Vadic 831 (vadic) units is enabled by default.
+.Pp
+Support for Bizcomp 1031[fw] (biz31[fw]), Bizcomp 1022[fw]
+(biz22[fw]), DEC DF0[23]-AC (df0[23]), DEC DN-11 (dn11) and
+Racal-Vadic 3451 (v3451) units can be added by recompiling
+.Nm
+with the appropriate defines.
+.Pp
+Note that if support for both the Racal-Vadic 831 and 3451 is enabled,
+they are referred to as the v831 and v3451, respectively.
+If only one of the two is supported, it is referred to as vadic.
+.Ss Variables
+The
+.Nm
+utility
+maintains a set of variables which control its operation.
+Some of these variables are read-only to normal users (root is allowed
+to change anything of interest).
+Variables may be displayed and set through the
+.Ic ~s
+escape.
+The syntax for variables is patterned after
+.Xr vi 1
+and
+.Xr Mail 1 .
+Supplying
+.Dq Li all
+as an argument to the set command displays all variables readable by
+the user.
+Alternatively, the user may request display of a particular variable
+by attaching a
+.Ql \&?
+to the end.
+For example,
+.Dq Li escape?
+displays the current escape character.
+.Pp
+Variables are numeric, string, character, or boolean values.
+Boolean variables are set merely by specifying their name; they may be
+reset by prepending a
+.Ql \&!
+to the name.
+Other variable types are set by concatenating an
+.Ql =
+and the value.
+The entire assignment must not have any blanks in it.
+A single set command may be used to interrogate as well as set a
+number of variables.
+Certain common variables have abbreviations.
+The following is a list of common variables, their abbreviations, and
+their default values:
+.Bl -tag -width indent
+.It Va baudrate
+.Pq Vt num
+The baud rate at which the connection was established;
+abbreviated
+.Va ba .
+.It Va beautify
+.Pq Vt bool
+Discard unprintable characters when a session is being
+scripted; abbreviated
+.Va be .
+.It Va dialtimeout
+.Pq Vt num
+When dialing a phone number, the time (in seconds) to wait for a
+connection to be established; abbreviated
+.Va dial .
+.It Va echocheck
+.Pq Vt bool
+Synchronize with the remote host during file transfer by
+waiting for the echo of the last character transmitted; default is
+.Cm off .
+.It Va eofread
+.Pq Vt str
+The set of characters which signify an end-of-transmission
+during a
+.Ic ~<
+file transfer command; abbreviated
+.Va eofr .
+.It Va eofwrite
+.Pq Vt str
+The string sent to indicate end-of-transmission during a
+.Ic ~>
+file transfer command; abbreviated
+.Va eofw .
+.It Va eol
+.Pq Vt str
+The set of characters which indicate an end-of-line.
+The
+.Nm
+utility
+will recognize escape characters only after an end-of-line.
+.It Va escape
+.Pq Vt char
+The command prefix (escape) character; abbreviated
+.Va es ;
+default value is
+.Ql ~ .
+.It Va exceptions
+.Pq Vt str
+The set of characters which should not be discarded due to the
+beautification switch; abbreviated
+.Va ex ;
+default value is
+.Dq Li \et\en\ef\eb .
+.It Va force
+.Pq Vt char
+The character used to force literal data transmission;
+abbreviated
+.Va fo ;
+default value is
+.Ql ^P .
+.It Va framesize
+.Pq Vt num
+The amount of data (in bytes) to buffer between file system
+writes when receiving files; abbreviated
+.Va fr .
+.It Va hardwareflow
+.Pq Vt bool
+Whether hardware flow control (CRTSCTS) is enabled for the
+connection; abbreviated
+.Va hf ;
+default value is
+.Cm off .
+.It Va host
+.Pq Vt str
+The name of the host to which you are connected; abbreviated
+.Va ho .
+.It Va linedisc
+.Pq Vt num
+The line discipline to use; abbreviated
+.Va ld .
+.It Va prompt
+.Pq Vt char
+The character which indicates an end-of-line on the remote
+host; abbreviated
+.Va pr ;
+default value is
+.Ql \en .
+This value is used to synchronize during data transfers.
+The count of lines transferred during a file transfer command is based
+on receipt of this character.
+.It Va raise
+.Pq Vt bool
+Upper case mapping mode; abbreviated
+.Va ra ;
+default value is
+.Cm off .
+When this mode is enabled, all lowercase letters will be mapped to
+uppercase by
+.Nm
+for transmission to the remote machine.
+.It Va raisechar
+.Pq Vt char
+The input character used to toggle uppercase mapping mode;
+abbreviated
+.Va rc ;
+not set by default.
+.It Va record
+.Pq Vt str
+The name of the file in which a session script is recorded;
+abbreviated
+.Va rec .
+.It Va script
+.Pq Vt bool
+Session scripting mode; abbreviated
+.Va sc ;
+default is
+.Cm off .
+When
+.Va script
+is
+.Cm true ,
+.Nm
+will record everything transmitted by the remote machine in the script
+record file specified in
+.Va record .
+If the
+.Va beautify
+switch is on, only printable
+.Tn ASCII
+characters will be included in the script file (those characters
+between 040 and 0177).
+The variable
+.Va exceptions
+is used to indicate characters which are an exception to the normal
+beautification rules.
+.It Va tabexpand
+.Pq Vt bool
+Expand tabs to spaces during file transfers; abbreviated
+.Va tab ;
+default value is
+.Cm false .
+Each tab is expanded to 8 spaces.
+.It Va tandem
+.Pq Vt bool
+Use XON/XOFF flow control to throttle data from the remote host;
+abbreviated
+.Va ta .
+The default value is
+.Cm true .
+.It Va verbose
+.Pq Vt bool
+Verbose mode; abbreviated
+.Va verb ;
+default is
+.Cm true .
+When verbose mode is enabled,
+.Nm
+prints messages while dialing, shows the current number of lines
+transferred during a file transfer operations, and more.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It Ev HOME
+The home directory to use for the
+.Ic ~c
+command.
+.It Ev SHELL
+The name of the shell to use for the
+.Ic ~!
+command; default value is
+.Dq Li /bin/sh .
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /var/spool/lock/LCK..*" -compact
+.It Pa /var/log/aculog
+line access log
+.It Pa /var/spool/lock/LCK..*
+lock file to avoid conflicts with
+.Xr uucp 1 Pq Pa ports/net/freebsd-uucp
+.El
+.Sh EXAMPLES
+Connect to the first USB serial port at the speed of 115200 baud:
+.Bd -literal -offset indent
+cu -s 115200 -l /dev/cuaU0
+.Ed
+.Sh SEE ALSO
+.Xr tip 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+The full set of variables is undocumented and should, probably, be
+pared down.
diff --git a/usr.bin/tip/tip/cu.c b/usr.bin/tip/tip/cu.c
new file mode 100644
index 000000000000..6811432d19c3
--- /dev/null
+++ b/usr.bin/tip/tip/cu.c
@@ -0,0 +1,202 @@
+/* $OpenBSD: cu.c,v 1.19 2006/05/25 08:41:52 jmc Exp $ */
+/* $NetBSD: cu.c,v 1.5 1997/02/11 09:24:05 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+static void cuusage(void);
+
+/*
+ * Botch the interface to look like cu's
+ */
+void
+cumain(int argc, char *argv[])
+{
+ int ch, i, parity;
+ long l;
+ char *cp;
+ static char sbuf[12];
+
+ if (argc < 2)
+ cuusage();
+ CU = DV = NOSTR;
+ BR = DEFBR;
+ parity = 0; /* none */
+
+ /*
+ * We want to accept -# as a speed. It's easiest to look through
+ * the arguments, replace -# with -s#, and let getopt() handle it.
+ */
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] == '-' &&
+ argv[i][1] >= '0' && argv[i][1] <= '9') {
+ asprintf(&cp, "-s%s", argv[i] + 1);
+ if (cp == NULL) {
+ fprintf(stderr,
+ "%s: cannot convert -# to -s#\n",
+ __progname);
+ exit(3);
+ }
+ argv[i] = cp;
+ }
+ }
+
+ while ((ch = getopt(argc, argv, "a:l:s:htoe")) != -1) {
+ switch (ch) {
+ case 'a':
+ CU = optarg;
+ break;
+ case 'l':
+ if (DV != NULL) {
+ fprintf(stderr,
+ "%s: cannot specificy multiple -l options\n",
+ __progname);
+ exit(3);
+ }
+ if (strchr(optarg, '/'))
+ DV = optarg;
+ else
+ asprintf(&DV, "/dev/%s", optarg);
+ break;
+ case 's':
+ l = strtol(optarg, &cp, 10);
+ if (*cp != '\0' || l < 0 || l >= INT_MAX) {
+ fprintf(stderr, "%s: unsupported speed %s\n",
+ __progname, optarg);
+ exit(3);
+ }
+ BR = (int)l;
+ break;
+ case 'h':
+ setboolean(value(LECHO), TRUE);
+ HD = TRUE;
+ break;
+ case 't':
+ HW = 1, DU = -1;
+ break;
+ case 'o':
+ if (parity != 0)
+ parity = 0; /* -e -o */
+ else
+ parity = 1; /* odd */
+ break;
+ case 'e':
+ if (parity != 0)
+ parity = 0; /* -o -e */
+ else
+ parity = -1; /* even */
+ break;
+ default:
+ cuusage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 1:
+ PN = argv[0];
+ break;
+ case 0:
+ break;
+ default:
+ cuusage();
+ break;
+ }
+
+ signal(SIGINT, cleanup);
+ signal(SIGQUIT, cleanup);
+ signal(SIGHUP, cleanup);
+ signal(SIGTERM, cleanup);
+ signal(SIGCHLD, SIG_DFL);
+
+ /*
+ * The "cu" host name is used to define the
+ * attributes of the generic dialer.
+ */
+ (void)snprintf(sbuf, sizeof(sbuf), "cu%ld", BR);
+ if ((i = hunt(sbuf)) == 0) {
+ printf("all ports busy\n");
+ exit(3);
+ }
+ if (i == -1) {
+ printf("link down\n");
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+ setbuf(stdout, NULL);
+ loginit();
+ user_uid();
+ vinit();
+ switch (parity) {
+ case -1:
+ setparity("even");
+ break;
+ case 1:
+ setparity("odd");
+ break;
+ default:
+ setparity("none");
+ break;
+ }
+ setboolean(value(VERBOSE), FALSE);
+ if (HW && ttysetup(BR)) {
+ fprintf(stderr, "%s: unsupported speed %ld\n",
+ __progname, BR);
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+ if (con()) {
+ printf("Connect failed\n");
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(1);
+ }
+ if (!HW && ttysetup(BR)) {
+ fprintf(stderr, "%s: unsupported speed %ld\n",
+ __progname, BR);
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+}
+
+static void
+cuusage(void)
+{
+ fprintf(stderr, "usage: cu [-ehot] [-a acu] [-l line] "
+ "[-s speed | -speed] [phone-number]\n");
+ exit(8);
+}
diff --git a/usr.bin/tip/tip/hunt.c b/usr.bin/tip/tip/hunt.c
new file mode 100644
index 000000000000..f4795091cb88
--- /dev/null
+++ b/usr.bin/tip/tip/hunt.c
@@ -0,0 +1,101 @@
+/* $OpenBSD: hunt.c,v 1.13 2006/03/17 19:39:46 deraadt Exp $ */
+/* $NetBSD: hunt.c,v 1.6 1997/04/20 00:02:10 mellon Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+static jmp_buf deadline;
+static int deadfl;
+
+static void dead(int);
+
+/*ARGSUSED*/
+static void
+dead(int signo)
+{
+ deadfl = 1;
+ longjmp(deadline, 1);
+}
+
+long
+hunt(char *name)
+{
+ char *cp;
+ sig_t f;
+
+ f = signal(SIGALRM, dead);
+ while ((cp = getremote(name))) {
+ deadfl = 0;
+ uucplock = strrchr(cp, '/');
+ if (uucplock == NULL)
+ uucplock = cp;
+ else
+ uucplock++;
+
+ if (uu_lock(uucplock) < 0)
+ continue;
+ /*
+ * Straight through call units, such as the BIZCOMP,
+ * VADIC and the DF, must indicate they're hardwired in
+ * order to get an open file descriptor placed in FD.
+ * Otherwise, as for a DN-11, the open will have to
+ * be done in the "open" routine.
+ */
+ if (!HW)
+ break;
+ if (setjmp(deadline) == 0) {
+ alarm(10);
+ FD = open(cp, (O_RDWR |
+ (boolean(value(DC)) ? O_NONBLOCK : 0)));
+ }
+ alarm(0);
+ if (FD < 0) {
+ perror(cp);
+ deadfl = 1;
+ }
+ if (!deadfl) {
+ struct termios cntrl;
+
+ tcgetattr(FD, &cntrl);
+ if (!boolean(value(DC)))
+ cntrl.c_cflag |= HUPCL;
+ tcsetattr(FD, TCSAFLUSH, &cntrl);
+ ioctl(FD, TIOCEXCL, 0);
+ signal(SIGALRM, SIG_DFL);
+ return ((long)cp);
+ }
+ (void)uu_unlock(uucplock);
+ }
+ signal(SIGALRM, f);
+ return (deadfl ? -1 : (long)cp);
+}
diff --git a/usr.bin/tip/tip/log.c b/usr.bin/tip/tip/log.c
new file mode 100644
index 000000000000..5a3dc6e25ddc
--- /dev/null
+++ b/usr.bin/tip/tip/log.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: log.c,v 1.8 2006/03/16 19:32:46 deraadt Exp $ */
+/* $NetBSD: log.c,v 1.4 1994/12/24 17:56:28 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+#ifdef ACULOG
+static FILE *flog = NULL;
+
+/*
+ * Log file maintenance routines
+ */
+void
+logent(char *group, char *num, char *acu, char *message)
+{
+ char *user, *timestamp;
+ struct passwd *pwd;
+ time_t t;
+
+ if (flog == NULL)
+ return;
+ if (flock(fileno(flog), LOCK_EX) < 0) {
+ perror("flock");
+ return;
+ }
+ if ((user = getlogin()) == NOSTR) {
+ if ((pwd = getpwuid(getuid())) == NOPWD)
+ user = "???";
+ else
+ user = pwd->pw_name;
+ }
+ t = time(0);
+ timestamp = ctime(&t);
+ timestamp[24] = '\0';
+ fprintf(flog, "%s (%s) <%s, %s, %s> %s\n",
+ user, timestamp, group,
+#ifdef PRISTINE
+ "",
+#else
+ num,
+#endif
+ acu, message);
+ (void) fflush(flog);
+ (void) flock(fileno(flog), LOCK_UN);
+}
+
+void
+loginit(void)
+{
+ flog = fopen(value(LOG), "a");
+ if (flog == NULL)
+ fprintf(stderr, "can't open log file %s.\r\n", value(LOG));
+}
+#endif
diff --git a/usr.bin/tip/tip/partab.c b/usr.bin/tip/tip/partab.c
new file mode 100644
index 000000000000..c15482811c67
--- /dev/null
+++ b/usr.bin/tip/tip/partab.c
@@ -0,0 +1,55 @@
+/* $OpenBSD: partab.c,v 1.5 2003/06/03 02:56:18 millert Exp $ */
+/* $NetBSD: partab.c,v 1.4 1996/12/29 10:38:21 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Even parity table for 0-0177
+ */
+const unsigned char evenpartab[] = {
+ 0000,0201,0202,0003,0204,0005,0006,0207,
+ 0210,0011,0012,0213,0014,0215,0216,0017,
+ 0220,0021,0022,0223,0024,0225,0226,0027,
+ 0030,0231,0232,0033,0234,0035,0036,0237,
+ 0240,0041,0042,0243,0044,0245,0246,0047,
+ 0050,0251,0252,0053,0254,0055,0056,0257,
+ 0060,0261,0262,0063,0264,0065,0066,0267,
+ 0270,0071,0072,0273,0074,0275,0276,0077,
+ 0300,0101,0102,0303,0104,0305,0306,0107,
+ 0110,0311,0312,0113,0314,0115,0116,0317,
+ 0120,0321,0322,0123,0324,0125,0126,0327,
+ 0330,0131,0132,0333,0134,0335,0336,0137,
+ 0140,0341,0342,0143,0344,0145,0146,0347,
+ 0350,0151,0152,0353,0154,0355,0356,0157,
+ 0360,0161,0162,0363,0164,0365,0366,0167,
+ 0170,0371,0372,0173,0374,0175,0176,0377,
+};
diff --git a/usr.bin/tip/tip/pathnames.h b/usr.bin/tip/tip/pathnames.h
new file mode 100644
index 000000000000..6bed255589de
--- /dev/null
+++ b/usr.bin/tip/tip/pathnames.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: pathnames.h,v 1.3 2003/06/03 02:56:18 millert Exp $ */
+/* $NetBSD: pathnames.h,v 1.3 1994/12/08 09:30:59 jtc Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#include <paths.h>
+
+#define _PATH_ACULOG "/var/log/aculog"
+#define _PATH_LOCKDIRNAME "/var/spool/lock/LCK..%s"
+#define _PATH_PHONES "/etc/phones"
+#define _PATH_REMOTE "/etc/remote"
diff --git a/usr.bin/tip/tip/phones b/usr.bin/tip/tip/phones
new file mode 100644
index 000000000000..597b0002ec82
--- /dev/null
+++ b/usr.bin/tip/tip/phones
@@ -0,0 +1,5 @@
+# phones -- remote host phone number data base
+# see tip(1), phones(5)
+# examples:
+#system1 9=2225551212
+#system2 9995551212
diff --git a/usr.bin/tip/tip/remote b/usr.bin/tip/tip/remote
new file mode 100644
index 000000000000..3f3f3b701bb6
--- /dev/null
+++ b/usr.bin/tip/tip/remote
@@ -0,0 +1,72 @@
+# remote -- remote host description file
+# see tip(1), remote(5)
+#
+# at ACU type
+# br bit rate (defaults to 9600)
+# cu call unit (default is dv)
+# du make a call flag (dial up)
+# dv device to use for the tty
+# el EOL marks (default is NULL)
+# fs frame size (default is BUFSIZ) -- used in buffering writes on
+# receive operations
+# ie input EOF marks (default is NULL)
+# oe output EOF string (default is NULL)
+# pa The parity type to use: even, odd, none, zero, one (default even)
+# pn phone numbers (@ =>'s search phones file; possibly taken from
+# PHONES environment variable)
+# tc to continue a capability
+
+# Example systems
+unixshell|Unix Access:\
+ :pn=\@:tc=unix57600:
+dosbbs|DOS-based BBS:\
+ :pn=\@:tc=dos57600:
+
+# UNIX system definitions
+unix57600|57600 Baud dial-out to a UNIX system:\
+ :el=^U^C^R^O^D^S^Q:ie=%$:oe=^D:tc=dial57600:
+unix33600|33600 Baud dial-out to a UNIX system:\
+ :el=^U^C^R^O^D^S^Q:ie=%$:oe=^D:tc=dial33600:
+
+# DOS system definitions
+dos57600|57600 Baud dial-out to a DOS system:\
+ :el=^U^C^R^O^D^S^Q:ie=%$:oe=^Z:pa=none:tc=dial57600:
+
+# 33.6k and 56k modems run the com port at 115200 bps to allow for the
+# compression performed in the modem. Note that some serial hardware
+# does not support speeds above 38400 bps and that speeds above that have
+# never been formally standardized. Modern architectures with 16550 or
+# better UARTs typically have no issues with the higher speeds.
+dial57600|57600 Baud Hayes attributes:\
+ br#115200:tc=dial:
+dial33600|33600 Baud Hayes attributes:\
+ br#115200:tc=dial:
+# 14.4k and 28.8k modems ran the port at 4x. Some rare 19.2 baud modems
+# did too, but those aren't included in this example.
+dial28800|28800 Baud Hayes attributes:\
+ br#115200:tc=dial:
+dial14400|14400 Baud Hayes attributes:\
+ br#57600:tc=dial:
+dial|Generic dialing parameters:\
+ :dv=/dev/cuau0:cu=/dev/cuau0:at=hayes:du:pa=none:
+
+# Hardwired line
+cuau0c|cua0c:dv=/dev/cuau0:br#9600:pa=none:
+
+# Finger friendly shortcuts
+uart0|com1:dv=/dev/cuau0:br#9600:pa=none:
+uart1|com2:dv=/dev/cuau1:br#9600:pa=none:
+uart2|com3:dv=/dev/cuau2:br#9600:pa=none:
+uart3|com4:dv=/dev/cuau3:br#9600:pa=none:
+uart4|com5:dv=/dev/cuau4:br#9600:pa=none:
+uart5|com6:dv=/dev/cuau5:br#9600:pa=none:
+uart6|com7:dv=/dev/cuau6:br#9600:pa=none:
+uart7|com8:dv=/dev/cuau7:br#9600:pa=none:
+ucom1:dv=/dev/cuaU0:br#9600:pa=none:
+ucom2:dv=/dev/cuaU1:br#9600:pa=none:
+ucom3:dv=/dev/cuaU2:br#9600:pa=none:
+ucom4:dv=/dev/cuaU3:br#9600:pa=none:
+ucom5:dv=/dev/cuaU4:br#9600:pa=none:
+ucom6:dv=/dev/cuaU5:br#9600:pa=none:
+ucom7:dv=/dev/cuaU6:br#9600:pa=none:
+ucom8:dv=/dev/cuaU7:br#9600:pa=none:
diff --git a/usr.bin/tip/tip/remote.c b/usr.bin/tip/tip/remote.c
new file mode 100644
index 000000000000..00ce25f52b5c
--- /dev/null
+++ b/usr.bin/tip/tip/remote.c
@@ -0,0 +1,228 @@
+/* $OpenBSD: remote.c,v 1.16 2006/06/06 23:24:52 deraadt Exp $ */
+/* $NetBSD: remote.c,v 1.5 1997/04/20 00:02:45 mellon Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pathnames.h"
+#include "tip.h"
+
+/*
+ * Attributes to be gleened from remote host description
+ * data base.
+ */
+static char **caps[] = {
+ &AT, &DV, &CM, &CU, &EL, &IE, &OE, &PN, &PR, &DI,
+ &ES, &EX, &FO, &RC, &RE, &PA
+};
+
+static char *capstrings[] = {
+ "at", "dv", "cm", "cu", "el", "ie", "oe", "pn", "pr",
+ "di", "es", "ex", "fo", "rc", "re", "pa", 0
+};
+
+static char *db_array[3] = { _PATH_REMOTE, 0, 0 };
+
+#define cgetflag(f) (cgetcap(bp, f, ':') != NULL)
+
+static void getremcap(char *);
+
+static void
+getremcap(char *host)
+{
+ char **p, ***q, *bp, *rempath;
+ int stat;
+
+ rempath = getenv("REMOTE");
+ if (rempath != NULL) {
+ if (*rempath != '/')
+ /* we have an entry */
+ cgetset(rempath);
+ else { /* we have a path */
+ db_array[1] = rempath;
+ db_array[2] = _PATH_REMOTE;
+ }
+ }
+
+ if ((stat = cgetent(&bp, db_array, host)) < 0) {
+ if ((DV != NULL) ||
+ (host[0] == '/' && access(DV = host, R_OK | W_OK) == 0)) {
+ CU = DV;
+ HO = host;
+ HW = 1;
+ DU = 0;
+ if (!BR)
+ BR = DEFBR;
+ FS = DEFFS;
+ return;
+ }
+ switch (stat) {
+ case -1:
+ fprintf(stderr, "%s: unknown host %s\n", __progname,
+ host);
+ break;
+ case -2:
+ fprintf(stderr,
+ "%s: can't open host description file\n",
+ __progname);
+ break;
+ case -3:
+ fprintf(stderr,
+ "%s: possible reference loop in host description file\n", __progname);
+ break;
+ }
+ exit(3);
+ }
+
+ for (p = capstrings, q = caps; *p != NULL; p++, q++)
+ if (**q == NULL)
+ cgetstr(bp, *p, *q);
+ if (!BR && (cgetnum(bp, "br", &BR) == -1))
+ BR = DEFBR;
+ if (!LD && (cgetnum(bp, "ld", &LD) == -1))
+ LD = TTYDISC;
+ if (cgetnum(bp, "fs", &FS) == -1)
+ FS = DEFFS;
+ if (DU < 0)
+ DU = 0;
+ else
+ DU = cgetflag("du");
+ if (DV == NOSTR) {
+ fprintf(stderr, "%s: missing device spec\n", host);
+ exit(3);
+ }
+ if (DU && CU == NOSTR)
+ CU = DV;
+ if (DU && PN == NOSTR) {
+ fprintf(stderr, "%s: missing phone number\n", host);
+ exit(3);
+ }
+ if (DU && AT == NOSTR) {
+ fprintf(stderr, "%s: missing acu type\n", host);
+ exit(3);
+ }
+
+ HD = cgetflag("hd");
+
+ /*
+ * This effectively eliminates the "hw" attribute
+ * from the description file
+ */
+ if (!HW)
+ HW = (CU == NOSTR) || (DU && equal(DV, CU));
+ HO = host;
+ /*
+ * see if uppercase mode should be turned on initially
+ */
+ if (cgetflag("ra"))
+ setboolean(value(RAISE), 1);
+ if (cgetflag("ec"))
+ setboolean(value(ECHOCHECK), 1);
+ if (cgetflag("be"))
+ setboolean(value(BEAUTIFY), 1);
+ if (cgetflag("nb"))
+ setboolean(value(BEAUTIFY), 0);
+ if (cgetflag("sc"))
+ setboolean(value(SCRIPT), 1);
+ if (cgetflag("tb"))
+ setboolean(value(TABEXPAND), 1);
+ if (cgetflag("vb"))
+ setboolean(value(VERBOSE), 1);
+ if (cgetflag("nv"))
+ setboolean(value(VERBOSE), 0);
+ if (cgetflag("ta"))
+ setboolean(value(TAND), 1);
+ if (cgetflag("nt"))
+ setboolean(value(TAND), 0);
+ if (cgetflag("rw"))
+ setboolean(value(RAWFTP), 1);
+ if (cgetflag("hd"))
+ setboolean(value(HALFDUPLEX), 1);
+ if (cgetflag("dc"))
+ setboolean(value(DC), 1);
+ if (cgetflag("hf"))
+ setboolean(value(HARDWAREFLOW), 1);
+ if (RE == NOSTR)
+ RE = (char *)"tip.record";
+ if (EX == NOSTR)
+ EX = (char *)"\t\n\b\f";
+ if (ES != NOSTR)
+ vstring("es", ES);
+ if (FO != NOSTR)
+ vstring("fo", FO);
+ if (PR != NOSTR)
+ vstring("pr", PR);
+ if (RC != NOSTR)
+ vstring("rc", RC);
+ if (cgetnum(bp, "dl", &DL) == -1)
+ DL = 0;
+ if (cgetnum(bp, "cl", &CL) == -1)
+ CL = 0;
+ if (cgetnum(bp, "et", &ET) == -1)
+ ET = 10;
+}
+
+char *
+getremote(char *host)
+{
+ char *cp;
+ static char *next;
+ static int lookedup = 0;
+
+ if (!lookedup) {
+ if (host == NOSTR && (host = getenv("HOST")) == NOSTR) {
+ fprintf(stderr, "%s: no host specified\n", __progname);
+ exit(3);
+ }
+ getremcap(host);
+ next = DV;
+ lookedup++;
+ }
+ /*
+ * We return a new device each time we're called (to allow
+ * a rotary action to be simulated)
+ */
+ if (next == NOSTR)
+ return (NOSTR);
+ if ((cp = strchr(next, ',')) == NULL) {
+ DV = next;
+ next = NOSTR;
+ } else {
+ *cp++ = '\0';
+ DV = next;
+ next = cp;
+ }
+ return (DV);
+}
diff --git a/usr.bin/tip/tip/tip.1 b/usr.bin/tip/tip/tip.1
new file mode 100644
index 000000000000..136ba8d28389
--- /dev/null
+++ b/usr.bin/tip/tip/tip.1
@@ -0,0 +1,605 @@
+.\" $OpenBSD: tip.1,v 1.37 2006/06/07 06:35:59 mbalmer Exp $
+.\" $NetBSD: tip.1,v 1.7 1994/12/08 09:31:05 jtc Exp $
+.\"
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd April 28, 2018
+.Dt TIP 1
+.Os
+.Sh NAME
+.Nm tip
+.Nd connect to a remote system
+.Sh SYNOPSIS
+.Nm
+.Op Fl nv
+.Op Fl Ar speed
+.Op Ar system-name
+.Sh DESCRIPTION
+The
+.Nm
+utility
+establishes a full-duplex connection to another machine, giving the
+appearance of being logged in directly on the remote CPU.
+It goes without saying that you must have a login on the machine (or
+equivalent) to which you wish to connect.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl n
+No escape (disable tilde).
+.It Fl v
+Set verbose mode.
+.El
+.Pp
+If
+.Ar speed
+is specified, it will override any baudrate specified in the system
+description being used.
+.Pp
+If neither
+.Ar speed
+nor
+.Ar system-name
+are specified,
+.Ar system-name
+will be set to the value of the
+.Ev HOST
+environment variable.
+.Pp
+If
+.Ar speed
+is specified but
+.Ar system-name
+is not,
+.Ar system-name
+will be set to a value of
+.Dq Li tip
+with
+.Ar speed
+appended.
+For example,
+.Nm Fl 1200
+will set
+.Ar system-name
+to
+.Dq Li tip1200 .
+.Pp
+Typed characters are normally transmitted directly to the remote
+machine (which does the echoing as well).
+A tilde
+.Pq Ql ~
+appearing as the first character of a line is an escape signal; the
+following are recognized:
+.Bl -tag -width indent
+.It Ic ~^D No or Ic ~.
+Drop the connection and exit.
+Only the connection is dropped \(en the login session is not terminated.
+.It Ic ~c Op Ar name
+Change directory to
+.Ar name
+(no argument implies change to home directory).
+.It Ic ~!
+Escape to a shell (exiting the shell will return to
+.Nm ) .
+.It Ic ~>
+Copy file from local to remote.
+The
+.Nm
+utility
+prompts for the name of a local file to transmit.
+.It Ic ~<
+Copy file from remote to local.
+The
+.Nm
+utility
+prompts first for the name of the file to be sent, then for a command
+to be executed on the remote machine.
+.It Ic ~p Ar from Op Ar to
+Send a file to a remote
+.Ux
+host.
+This command causes the remote
+.Ux
+system to run the following command string,
+sending it the
+.Ar from
+file:
+.Pp
+.Dl "stty -echo; cat > 'to'; stty echo"
+.Pp
+If the
+.Ar to
+file is not specified, the
+.Ar from
+file name is used.
+This command is actually a
+.Ux
+specific version of the
+.Ic ~>
+command.
+.It Ic ~t Ar from Op Ar to
+Take a file from a remote
+.Ux
+host.
+As in the
+.Ic ~p
+command, the
+.Ar to
+file defaults to the
+.Ar from
+file name if it is not specified.
+The remote host executes the following command string
+to send the file to
+.Nm :
+.Pp
+.Dl "cat 'from'; echo '' | tr '\e012' '\e01'"
+.It Ic ~|
+Pipe the output from a remote command to a local
+.Ux
+process.
+The command string sent to the local
+.Ux
+system is processed by the shell.
+.It Ic ~$
+Pipe the output from a local
+.Ux
+process to the remote host.
+The command string sent to the local
+.Ux
+system is processed by the shell.
+.It Ic ~C
+Fork a child process on the local system to perform special protocols
+such as
+.Tn XMODEM .
+The child program will be run with the following arrangement of
+file descriptors:
+.Bd -literal -offset indent
+0 <-> remote tty in
+1 <-> remote tty out
+2 <-> local tty stderr
+.Ed
+.It Ic ~#
+Send a
+.Dv BREAK
+to the remote system.
+For systems which do not support the necessary
+.Fn ioctl
+call, the break is simulated by a sequence of line speed changes and
+.Dv DEL
+characters.
+.It Ic ~s
+Set a variable (see the discussion below).
+.It Ic ~v
+List all variables and their values (if set).
+.It Ic ~^Z
+Stop
+.Nm
+(only available with job control).
+.It Ic ~^Y
+Stop only the
+.Dq "local side"
+of
+.Nm
+(only available with job control); the
+.Dq "remote side"
+of
+.Nm ,
+the side that displays output from the remote host, is left running.
+.It Ic ~?
+Get a summary of the tilde escapes.
+.El
+.Pp
+To find the system description, and thus the operating characteristics
+of
+.Ar system-name ,
+.Nm
+searches for a system description with a name identical to
+.Ar system-name .
+The search order is as follows:
+.Bl -enum -offset indent
+.It
+If the environment variable
+.Ev REMOTE
+does not start with a
+.Ql /
+it is assumed to be a system description, and is considered first.
+.It
+If the environment variable
+.Ev REMOTE
+begins with a
+.Ql /
+it is assumed to be a path to a
+.Xr remote 5
+database, and the specified database is searched.
+.It
+The default
+.Xr remote 5
+database,
+.Pa /etc/remote ,
+is searched.
+.El
+.Pp
+See
+.Xr remote 5
+for full documentation on system descriptions.
+.Pp
+The
+.Va br
+capability is used in system descriptions to specify the baud rate
+with which to establish a connection.
+If the value specified is not suitable, the baud rate to be used may
+be given on the command line, e.g.\&
+.Dq Li "tip -300 mds" .
+.Pp
+When
+.Nm
+establishes a connection, it sends out the connection message
+specified in the
+.Va cm
+capability of the system description being used.
+.Pp
+When
+.Nm
+prompts for an argument, for example during setup of a file transfer, the
+line typed may be edited with the standard erase and kill characters.
+A null line in response to a prompt, or an interrupt, will abort the
+dialogue and return the user to the remote machine.
+.Pp
+The
+.Nm
+utility
+guards against multiple users connecting to a remote system by opening
+modems and terminal lines with exclusive access, and by honoring the
+locking protocol used by
+.Xr uucico 8 Pq Pa ports/net/freebsd-uucp .
+.Pp
+During file transfers
+.Nm
+provides a running count of the number of lines transferred.
+When using the
+.Ic ~>
+and
+.Ic ~<
+commands, the
+.Va eofread
+and
+.Va eofwrite
+variables are used to recognize end-of-file when reading, and specify
+end-of-file when writing (see below).
+File transfers normally depend on hardwareflow or tandem mode for flow control.
+If the remote system does not support hardwareflow or tandem mode,
+.Va echocheck
+may be set to indicate that
+.Nm
+should synchronize with the remote system on the echo of each
+transmitted character.
+.Pp
+When
+.Nm
+must dial a phone number to connect to a system, it will print various
+messages indicating its actions.
+The
+.Nm
+utility
+supports a variety of auto-call units and modems with the
+.Va at
+capability in system descriptions.
+.Pp
+Support for Ventel 212+ (ventel), Hayes AT-style (hayes),
+USRobotics Courier (courier), Telebit T3000 (t3000) and
+Racal-Vadic 831 (vadic) units is enabled by default.
+.Pp
+Support for Bizcomp 1031[fw] (biz31[fw]), Bizcomp 1022[fw]
+(biz22[fw]), DEC DF0[23]-AC (df0[23]), DEC DN-11 (dn11) and
+Racal-Vadic 3451 (v3451) units can be added by recompiling
+.Nm
+with the appropriate defines.
+.Pp
+Note that if support for both the Racal-Vadic 831 and 3451 is enabled,
+they are referred to as the v831 and v3451, respectively.
+If only one of the two is supported, it is referred to as vadic.
+.Ss Variables
+The
+.Nm
+utility
+maintains a set of variables which control its operation.
+Some of these variables are read-only to normal users (root is allowed
+to change anything of interest).
+Variables may be displayed and set through the
+.Ic ~s
+escape.
+The syntax for variables is patterned after
+.Xr vi 1
+and
+.Xr Mail 1 .
+Supplying
+.Dq Li all
+as an argument to the set command displays all variables readable by
+the user.
+Alternatively, the user may request display of a particular variable
+by attaching a
+.Ql \&?
+to the end.
+For example,
+.Dq Li escape?
+displays the current escape character.
+.Pp
+Variables are numeric, string, character, or boolean values.
+Boolean variables are set merely by specifying their name; they may be
+reset by prepending a
+.Ql \&!
+to the name.
+Other variable types are set by concatenating an
+.Ql =
+and the value.
+The entire assignment must not have any blanks in it.
+A single set command may be used to interrogate as well as set a
+number of variables.
+Variables may be initialized at run time by placing set commands
+(without the
+.Ic ~s
+prefix) in the initialization file
+.Pa ~/.tiprc ;
+the
+.Fl v
+option additionally causes
+.Nm
+to display the sets as they are made.
+Certain common variables have abbreviations.
+The following is a list of common variables, their abbreviations, and
+their default values:
+.Bl -tag -width indent
+.It Va baudrate
+.Pq Vt num
+The baud rate at which the connection was established;
+abbreviated
+.Va ba .
+.It Va beautify
+.Pq Vt bool
+Discard unprintable characters when a session is being
+scripted; abbreviated
+.Va be .
+.It Va dialtimeout
+.Pq Vt num
+When dialing a phone number, the time (in seconds) to wait for a
+connection to be established; abbreviated
+.Va dial .
+.It Va echocheck
+.Pq Vt bool
+Synchronize with the remote host during file transfer by
+waiting for the echo of the last character transmitted; default is
+.Cm off .
+.It Va eofread
+.Pq Vt str
+The set of characters which signify an end-of-transmission
+during a
+.Ic ~<
+file transfer command; abbreviated
+.Va eofr .
+.It Va eofwrite
+.Pq Vt str
+The string sent to indicate end-of-transmission during a
+.Ic ~>
+file transfer command; abbreviated
+.Va eofw .
+.It Va eol
+.Pq Vt str
+The set of characters which indicate an end-of-line.
+The
+.Nm
+utility
+will recognize escape characters only after an end-of-line.
+.It Va escape
+.Pq Vt char
+The command prefix (escape) character; abbreviated
+.Va es ;
+default value is
+.Ql ~ .
+.It Va exceptions
+.Pq Vt str
+The set of characters which should not be discarded due to the
+beautification switch; abbreviated
+.Va ex ;
+default value is
+.Dq Li \et\en\ef\eb .
+.It Va force
+.Pq Vt char
+The character used to force literal data transmission;
+abbreviated
+.Va fo ;
+default value is
+.Ql ^P .
+.It Va framesize
+.Pq Vt num
+The amount of data (in bytes) to buffer between file system
+writes when receiving files; abbreviated
+.Va fr .
+.It Va hardwareflow
+.Pq Vt bool
+Whether hardware flow control (CRTSCTS) is enabled for the
+connection; abbreviated
+.Va hf ;
+default value is
+.Cm off .
+.It Va host
+.Pq Vt str
+The name of the host to which you are connected; abbreviated
+.Va ho .
+.It Va linedisc
+.Pq Vt num
+The line discipline to use; abbreviated
+.Va ld .
+.It Va prompt
+.Pq Vt char
+The character which indicates an end-of-line on the remote
+host; abbreviated
+.Va pr ;
+default value is
+.Ql \en .
+This value is used to synchronize during data transfers.
+The count of lines transferred during a file transfer command is based
+on receipt of this character.
+.It Va raise
+.Pq Vt bool
+Upper case mapping mode; abbreviated
+.Va ra ;
+default value is
+.Cm off .
+When this mode is enabled, all lowercase letters will be mapped to
+uppercase by
+.Nm
+for transmission to the remote machine.
+.It Va raisechar
+.Pq Vt char
+The input character used to toggle uppercase mapping mode;
+abbreviated
+.Va rc ;
+not set by default.
+.It Va record
+.Pq Vt str
+The name of the file in which a session script is recorded;
+abbreviated
+.Va rec ;
+default value is
+.Pa tip.record .
+.It Va script
+.Pq Vt bool
+Session scripting mode; abbreviated
+.Va sc ;
+default is
+.Cm off .
+When
+.Va script
+is
+.Cm true ,
+.Nm
+will record everything transmitted by the remote machine in the script
+record file specified in
+.Va record .
+If the
+.Va beautify
+switch is on, only printable
+.Tn ASCII
+characters will be included in the script file (those characters
+between 040 and 0177).
+The variable
+.Va exceptions
+is used to indicate characters which are an exception to the normal
+beautification rules.
+.It Va tabexpand
+.Pq Vt bool
+Expand tabs to spaces during file transfers; abbreviated
+.Va tab ;
+default value is
+.Cm false .
+Each tab is expanded to 8 spaces.
+.It Va tandem
+.Pq Vt bool
+Use XON/XOFF flow control to throttle data from the remote host;
+abbreviated
+.Va ta .
+The default value is
+.Cm true
+unless the
+.Va nt
+capability has been specified in
+.Pa /etc/remote ,
+in which case the default value is
+.Cm false .
+.It Va verbose
+.Pq Vt bool
+Verbose mode; abbreviated
+.Va verb ;
+default is
+.Cm true .
+When verbose mode is enabled,
+.Nm
+prints messages while dialing, shows the current number of lines
+transferred during a file transfer operations, and more.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It Ev HOME
+The home directory to use for the
+.Ic ~c
+command.
+.It Ev HOST
+The default value for
+.Ar system-name
+if none is specified via the command line.
+.It Ev PHONES
+A path to a
+.Xr phones 5
+database.
+.It Ev REMOTE
+A system description, or an absolute path to a
+.Xr remote 5
+system description database.
+.It Ev SHELL
+The name of the shell to use for the
+.Ic ~!
+command; default value is
+.Dq Li /bin/sh .
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /var/spool/lock/LCK..*" -compact
+.It Pa ~/.tiprc
+initialization file
+.It Pa tip.record
+record file
+.It Pa /etc/phones
+default
+.Xr phones 5
+file
+.It Pa /etc/remote
+global
+.Xr remote 5
+database
+.It Pa /var/log/aculog
+line access log
+.It Pa /var/spool/lock/LCK..*
+lock file to avoid conflicts with
+.Xr uucp 1 Pq Pa ports/net/freebsd-uucp
+.El
+.Sh EXAMPLES
+Connect to the first USB serial port at the speed of 115200 baud:
+.Bd -literal -offset indent
+tip ucom1 -115200
+.Ed
+.Sh SEE ALSO
+.Xr cu 1 ,
+.Xr phones 5 ,
+.Xr remote 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+The full set of variables is undocumented and should, probably, be
+pared down.
diff --git a/usr.bin/tip/tip/tip.c b/usr.bin/tip/tip/tip.c
new file mode 100644
index 000000000000..9315bffddc84
--- /dev/null
+++ b/usr.bin/tip/tip/tip.c
@@ -0,0 +1,624 @@
+/* $OpenBSD: tip.c,v 1.30 2006/08/18 03:06:18 jason Exp $ */
+/* $NetBSD: tip.c,v 1.13 1997/04/20 00:03:05 mellon Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * tip - UNIX link to other systems
+ * tip [-v] [-speed] system-name
+ * or
+ * cu phone-number [-s speed] [-l line] [-a acu]
+ */
+#define EXTERN
+#include "tip.h"
+#include "pathnames.h"
+
+int disc = TTYDISC; /* tip normally runs this way */
+char PNbuf[256]; /* This limits the size of a number */
+
+static void intprompt(int);
+static void tipin(void);
+static int escape(void);
+
+int
+main(int argc, char *argv[])
+{
+ char *sys = NOSTR, sbuf[12], *p;
+ int i;
+
+ /* XXX preserve previous braindamaged behavior */
+ setboolean(value(DC), TRUE);
+
+ gid = getgid();
+ egid = getegid();
+ uid = getuid();
+ euid = geteuid();
+ if (equal(__progname, "cu")) {
+ cumode = 1;
+ cumain(argc, argv);
+ goto cucommon;
+ }
+
+ if (argc > 4) {
+ fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n");
+ exit(1);
+ }
+ if (!isatty(0)) {
+ fprintf(stderr, "%s: must be interactive\n", __progname);
+ exit(1);
+ }
+
+ for (; argc > 1; argv++, argc--) {
+ if (argv[1][0] != '-')
+ sys = argv[1];
+ else switch (argv[1][1]) {
+
+ case 'v':
+ vflag++;
+ break;
+
+ case 'n':
+ noesc++;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ BR = atoi(&argv[1][1]);
+ break;
+
+ default:
+ fprintf(stderr, "%s: %s, unknown option\n", __progname,
+ argv[1]);
+ break;
+ }
+ }
+
+ if (sys == NOSTR)
+ goto notnumber;
+ if (isalpha(*sys))
+ goto notnumber;
+ /*
+ * System name is really a phone number...
+ * Copy the number then stomp on the original (in case the number
+ * is private, we don't want 'ps' or 'w' to find it).
+ */
+ if (strlen(sys) > sizeof PNbuf - 1) {
+ fprintf(stderr, "%s: phone number too long (max = %d bytes)\n",
+ __progname, (int)sizeof(PNbuf) - 1);
+ exit(1);
+ }
+ strlcpy(PNbuf, sys, sizeof PNbuf - 1);
+ for (p = sys; *p; p++)
+ *p = '\0';
+ PN = PNbuf;
+ (void)snprintf(sbuf, sizeof(sbuf), "tip%ld", BR);
+ sys = sbuf;
+
+notnumber:
+ (void)signal(SIGINT, cleanup);
+ (void)signal(SIGQUIT, cleanup);
+ (void)signal(SIGHUP, cleanup);
+ (void)signal(SIGTERM, cleanup);
+ (void)signal(SIGCHLD, SIG_DFL);
+
+ if ((i = hunt(sys)) == 0) {
+ printf("all ports busy\n");
+ exit(3);
+ }
+ if (i == -1) {
+ printf("link down\n");
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+ setbuf(stdout, NULL);
+ loginit();
+
+ /*
+ * Now that we have the logfile and the ACU open
+ * return to the real uid and gid. These things will
+ * be closed on exit. Swap real and effective uid's
+ * so we can get the original permissions back
+ * for removing the uucp lock.
+ */
+ user_uid();
+
+ /*
+ * Kludge, their's no easy way to get the initialization
+ * in the right order, so force it here
+ */
+ if ((PH = getenv("PHONES")) == NOSTR)
+ PH = _PATH_PHONES;
+ vinit(); /* init variables */
+ setparity("none"); /* set the parity table */
+
+ /*
+ * Hardwired connections require the
+ * line speed set before they make any transmissions
+ * (this is particularly true of things like a DF03-AC)
+ */
+ if (HW && ttysetup(number(value(BAUDRATE)))) {
+ fprintf(stderr, "%s: bad baud rate %ld\n", __progname,
+ number(value(BAUDRATE)));
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+ if ((p = con())) {
+ printf("\07%s\n[EOT]\n", p);
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(1);
+ }
+ if (!HW && ttysetup(number(value(BAUDRATE)))) {
+ fprintf(stderr, "%s: bad baud rate %ld\n", __progname,
+ number(value(BAUDRATE)));
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ exit(3);
+ }
+cucommon:
+ /*
+ * From here down the code is shared with
+ * the "cu" version of tip.
+ */
+
+ i = fcntl(FD, F_GETFL);
+ if (i == -1) {
+ perror("fcntl");
+ cleanup(0);
+ }
+ i = fcntl(FD, F_SETFL, i & ~O_NONBLOCK);
+ if (i == -1) {
+ perror("fcntl");
+ cleanup(0);
+ }
+
+ tcgetattr(0, &defterm);
+ gotdefterm = 1;
+ term = defterm;
+ term.c_lflag &= ~(ICANON|IEXTEN|ECHO);
+ term.c_iflag &= ~(INPCK|ICRNL);
+ term.c_oflag &= ~OPOST;
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ defchars = term;
+ term.c_cc[VINTR] = term.c_cc[VQUIT] = term.c_cc[VSUSP] =
+ term.c_cc[VDSUSP] = term.c_cc[VDISCARD] =
+ term.c_cc[VLNEXT] = _POSIX_VDISABLE;
+ raw();
+
+ pipe(fildes); pipe(repdes);
+ (void)signal(SIGALRM, timeout);
+
+ if (value(LINEDISC) != TTYDISC) {
+ int ld = (int)(intptr_t)value(LINEDISC);
+ ioctl(FD, TIOCSETD, &ld);
+ }
+
+ /*
+ * Everything's set up now:
+ * connection established (hardwired or dialup)
+ * line conditioned (baud rate, mode, etc.)
+ * internal data structures (variables)
+ * so, fork one process for local side and one for remote.
+ */
+ printf(cumode ? "Connected\r\n" : "\07connected\r\n");
+ tipin_pid = getpid();
+ if ((tipout_pid = fork()))
+ tipin();
+ else
+ tipout();
+ exit(0);
+}
+
+void
+cleanup(int signo)
+{
+ daemon_uid();
+ (void)uu_unlock(uucplock);
+ if (odisc)
+ ioctl(0, TIOCSETD, &odisc);
+ unraw();
+ if (signo && tipout_pid) {
+ kill(tipout_pid, signo);
+ wait(NULL);
+ }
+ exit(0);
+}
+
+/*
+ * Muck with user ID's. We are setuid to the owner of the lock
+ * directory when we start. user_uid() reverses real and effective
+ * ID's after startup, to run with the user's permissions.
+ * daemon_uid() switches back to the privileged uid for unlocking.
+ * Finally, to avoid running a shell with the wrong real uid,
+ * shell_uid() sets real and effective uid's to the user's real ID.
+ */
+static int uidswapped;
+
+void
+user_uid(void)
+{
+ if (uidswapped == 0) {
+ seteuid(uid);
+ uidswapped = 1;
+ }
+}
+
+void
+daemon_uid(void)
+{
+
+ if (uidswapped) {
+ seteuid(euid);
+ uidswapped = 0;
+ }
+}
+
+void
+shell_uid(void)
+{
+ setegid(gid);
+ seteuid(uid);
+}
+
+/*
+ * put the controlling keyboard into raw mode
+ */
+void
+raw(void)
+{
+ tcsetattr(0, TCSADRAIN, &term);
+}
+
+
+/*
+ * return keyboard to normal mode
+ */
+void
+unraw(void)
+{
+ if (gotdefterm)
+ tcsetattr(0, TCSADRAIN, &defterm);
+}
+
+/*
+ * give up exclusive tty access
+ */
+void
+unexcl()
+{
+ ioctl(FD, TIOCNXCL, 0);
+}
+
+static jmp_buf promptbuf;
+
+/*
+ * Print string ``s'', then read a string
+ * in from the terminal. Handles signals & allows use of
+ * normal erase and kill characters.
+ */
+int
+prompt(char *s, char *p, size_t sz)
+{
+ int c;
+ char *b = p;
+ sig_t oint, oquit;
+
+ stoprompt = 0;
+ oint = signal(SIGINT, intprompt);
+ oquit = signal(SIGQUIT, SIG_IGN);
+ unraw();
+ printf("%s", s);
+ if (setjmp(promptbuf) == 0)
+ while ((c = getchar()) != EOF && (*p = c) != '\n' && --sz > 0)
+ p++;
+ *p = '\0';
+
+ raw();
+ (void)signal(SIGINT, oint);
+ (void)signal(SIGQUIT, oquit);
+ return (stoprompt || p == b);
+}
+
+/*
+ * Interrupt service routine during prompting
+ */
+/*ARGSUSED*/
+static void
+intprompt(int signo)
+{
+ (void)signal(SIGINT, SIG_IGN);
+ stoprompt = 1;
+ printf("\r\n");
+ longjmp(promptbuf, 1);
+}
+
+/*
+ * ****TIPIN TIPIN****
+ */
+static void
+tipin(void)
+{
+ int bol = 1;
+ int gch;
+ char ch;
+
+ /*
+ * Kinda klugey here...
+ * check for scripting being turned on from the .tiprc file,
+ * but be careful about just using setscript(), as we may
+ * send a SIGEMT before tipout has a chance to set up catching
+ * it; so wait a second, then setscript()
+ */
+ if (boolean(value(SCRIPT))) {
+ sleep(1);
+ setscript();
+ }
+
+ while (1) {
+ gch = getchar();
+ if (gch == EOF)
+ return;
+ gch = gch & STRIP_PAR;
+ if ((gch == character(value(ESCAPE))) && bol) {
+ if (!noesc) {
+ gch = escape();
+ if (gch == EOF)
+ return;
+ if (gch == 0)
+ continue;
+ }
+ } else if (!cumode && gch == character(value(RAISECHAR))) {
+ setboolean(value(RAISE), !boolean(value(RAISE)));
+ continue;
+ } else if (gch == '\r') {
+ bol = 1;
+ ch = gch;
+ parwrite(FD, &ch, 1);
+ if (boolean(value(HALFDUPLEX)))
+ printf("\r\n");
+ continue;
+ } else if (!cumode && gch == character(value(FORCE))) {
+ gch = getchar();
+ if (gch == EOF)
+ return;
+ gch = gch & STRIP_PAR;
+ }
+ bol = any(gch, value(EOL));
+ if (boolean(value(RAISE)) && islower(gch))
+ gch = toupper(gch);
+ ch = gch;
+ parwrite(FD, &ch, 1);
+ if (boolean(value(HALFDUPLEX)))
+ printf("%c", ch);
+ }
+}
+
+extern esctable_t etable[];
+
+/*
+ * Escape handler --
+ * called on recognition of ``escapec'' at the beginning of a line
+ */
+static int
+escape(void)
+{
+ int gch;
+ esctable_t *p;
+ char c = character(value(ESCAPE));
+
+ gch = getchar();
+ if (gch == EOF)
+ return (EOF);
+ gch = gch & STRIP_PAR;
+ for (p = etable; p->e_char; p++)
+ if (p->e_char == gch) {
+ if ((p->e_flags&PRIV) && uid)
+ continue;
+ printf("%s", ctrl(c));
+ (*p->e_func)(gch);
+ return (0);
+ }
+ /* ESCAPE ESCAPE forces ESCAPE */
+ if (c != gch)
+ parwrite(FD, &c, 1);
+ return (gch);
+}
+
+int
+any(int cc, char *p)
+{
+ char c = cc;
+ while (p && *p)
+ if (*p++ == c)
+ return (1);
+ return (0);
+}
+
+size_t
+size(char *s)
+{
+ size_t i = 0;
+
+ while (s && *s++)
+ i++;
+ return (i);
+}
+
+char *
+interp(char *s)
+{
+ static char buf[256];
+ char *p = buf, c, *q;
+
+ while ((c = *s++)) {
+ for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
+ if (*q++ == c) {
+ *p++ = '\\'; *p++ = *q;
+ goto next;
+ }
+ if (c < 040) {
+ *p++ = '^'; *p++ = c + 'A'-1;
+ } else if (c == 0177) {
+ *p++ = '^'; *p++ = '?';
+ } else
+ *p++ = c;
+ next:
+ ;
+ }
+ *p = '\0';
+ return (buf);
+}
+
+char *
+ctrl(char c)
+{
+ static char s[3];
+
+ if (c < 040 || c == 0177) {
+ s[0] = '^';
+ s[1] = c == 0177 ? '?' : c+'A'-1;
+ s[2] = '\0';
+ } else {
+ s[0] = c;
+ s[1] = '\0';
+ }
+ return (s);
+}
+
+/*
+ * Help command
+ */
+void
+help(int c)
+{
+ esctable_t *p;
+
+ printf("%c\r\n", c);
+ for (p = etable; p->e_char; p++) {
+ if ((p->e_flags&PRIV) && uid)
+ continue;
+ printf("%2s", ctrl(character(value(ESCAPE))));
+ printf("%-2s %c %s\r\n", ctrl(p->e_char),
+ p->e_flags&EXP ? '*': ' ', p->e_help);
+ }
+}
+
+/*
+ * Set up the "remote" tty's state
+ */
+int
+ttysetup(int speed)
+{
+ struct termios cntrl;
+
+ if (tcgetattr(FD, &cntrl))
+ return (-1);
+ cfsetspeed(&cntrl, speed);
+ cntrl.c_cflag &= ~(CSIZE|PARENB);
+ cntrl.c_cflag |= CS8;
+ if (boolean(value(DC)))
+ cntrl.c_cflag |= CLOCAL;
+ if (boolean(value(HARDWAREFLOW)))
+ cntrl.c_cflag |= CRTSCTS;
+ cntrl.c_iflag &= ~(ISTRIP|ICRNL);
+ cntrl.c_oflag &= ~OPOST;
+ cntrl.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO);
+ cntrl.c_cc[VMIN] = 1;
+ cntrl.c_cc[VTIME] = 0;
+ if (boolean(value(TAND)))
+ cntrl.c_iflag |= IXOFF;
+ return (tcsetattr(FD, TCSAFLUSH, &cntrl));
+}
+
+static char partab[0200];
+
+/*
+ * Do a write to the remote machine with the correct parity.
+ * We are doing 8 bit wide output, so we just generate a character
+ * with the right parity and output it.
+ */
+void
+parwrite(int fd, char *buf, size_t n)
+{
+ size_t i;
+ char *bp;
+
+ bp = buf;
+ if (bits8 == 0)
+ for (i = 0; i < n; i++) {
+ *bp = partab[(*bp) & 0177];
+ bp++;
+ }
+ if (write(fd, buf, n) < 0) {
+ if (errno == EIO || errno == ENXIO)
+ tipabort("Lost carrier.");
+ /* this is questionable */
+ perror("write");
+ }
+}
+
+/*
+ * Build a parity table with appropriate high-order bit.
+ */
+void
+setparity(char *defparity)
+{
+ int i, flip, clr, set;
+ char *parity;
+ extern const unsigned char evenpartab[];
+
+ if (value(PARITY) == NOSTR)
+ value(PARITY) = defparity;
+ parity = value(PARITY);
+ if (equal(parity, "none")) {
+ bits8 = 1;
+ return;
+ }
+ bits8 = 0;
+ flip = 0;
+ clr = 0377;
+ set = 0;
+ if (equal(parity, "odd"))
+ flip = 0200; /* reverse bit 7 */
+ else if (equal(parity, "zero"))
+ clr = 0177; /* turn off bit 7 */
+ else if (equal(parity, "one"))
+ set = 0200; /* turn on bit 7 */
+ else if (!equal(parity, "even")) {
+ (void) fprintf(stderr, "%s: unknown parity value\r\n", parity);
+ (void) fflush(stderr);
+ }
+ for (i = 0; i < 0200; i++)
+ partab[i] = ((evenpartab[i] ^ flip) | set) & clr;
+}
diff --git a/usr.bin/tip/tip/tip.h b/usr.bin/tip/tip/tip.h
new file mode 100644
index 000000000000..7e65fcb832c5
--- /dev/null
+++ b/usr.bin/tip/tip/tip.h
@@ -0,0 +1,355 @@
+/* $OpenBSD: tip.h,v 1.27 2006/08/18 03:06:18 jason Exp $ */
+/* $NetBSD: tip.h,v 1.7 1997/04/20 00:02:46 mellon Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+/*
+ * tip - terminal interface program
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#include <termios.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+/*
+ * Remote host attributes
+ */
+EXTERN char *DV; /* UNIX device(s) to open */
+EXTERN char *EL; /* chars marking an EOL */
+EXTERN char *CM; /* initial connection message */
+EXTERN char *IE; /* EOT to expect on input */
+EXTERN char *OE; /* EOT to send to complete FT */
+EXTERN char *CU; /* call unit if making a phone call */
+EXTERN char *AT; /* acu type */
+EXTERN char *PN; /* phone number(s) */
+EXTERN char *DI; /* disconnect string */
+EXTERN char *PA; /* parity to be generated */
+
+EXTERN char *PH; /* phone number file */
+EXTERN char *RM; /* remote file name */
+EXTERN char *HO; /* host name */
+
+EXTERN long BR; /* line speed for conversation */
+EXTERN long FS; /* frame size for transfers */
+
+EXTERN short DU; /* this host is dialed up */
+EXTERN short HW; /* this device is hardwired, see hunt.c */
+EXTERN char *ES; /* escape character */
+EXTERN char *EX; /* exceptions */
+EXTERN char *FO; /* force (literal next) char*/
+EXTERN char *RC; /* raise character */
+EXTERN char *RE; /* script record file */
+EXTERN char *PR; /* remote prompt */
+EXTERN long DL; /* line delay for file transfers to remote */
+EXTERN long CL; /* char delay for file transfers to remote */
+EXTERN long ET; /* echocheck timeout */
+EXTERN long LD; /* line disc */
+EXTERN short HD; /* this host is half duplex - do local echo */
+
+/*
+ * String value table
+ */
+typedef
+ struct {
+ char *v_name; /* whose name is it */
+ char v_type; /* for interpreting set's */
+ char v_access; /* protection of touchy ones */
+ char *v_abrev; /* possible abbreviation */
+ char *v_value; /* casted to a union later */
+ }
+ value_t;
+
+#define STRING 01 /* string valued */
+#define BOOL 02 /* true-false value */
+#define NUMBER 04 /* numeric value */
+#define CHAR 010 /* character value */
+
+#define WRITE 01 /* write access to variable */
+#define READ 02 /* read access */
+
+#define CHANGED 01 /* low bit is used to show modification */
+#define PUBLIC 1 /* public access rights */
+#define PRIVATE 03 /* private to definer */
+#define ROOT 05 /* root defined */
+
+#define TRUE 1
+#define FALSE 0
+
+#define ENVIRON 020 /* initialize out of the environment */
+#define IREMOTE 040 /* initialize out of remote structure */
+#define INIT 0100 /* static data space used for initialization */
+#define TMASK 017
+
+/*
+ * Definition of ACU line description
+ */
+typedef
+ struct {
+ char *acu_name;
+ int (*acu_dialer)(char *, char *);
+ void (*acu_disconnect)(void);
+ void (*acu_abort)(void);
+ }
+ acu_t;
+
+#define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */
+
+/*
+ * variable manipulation stuff --
+ * if we defined the value entry in value_t, then we couldn't
+ * initialize it in vars.c, so we cast it as needed to keep lint
+ * happy.
+ */
+
+#define value(v) vtable[v].v_value
+#define lvalue(v) (long)(intptr_t)vtable[v].v_value
+
+#define number(v) ((long)(intptr_t)(v))
+#define boolean(v) ((short)(intptr_t)(v))
+#define character(v) ((char)(intptr_t)(v))
+
+#define setnumber(v,n) do { (v) = (char *)(intptr_t)(n); } while (0)
+#define setboolean(v,n) do { (v) = (char *)(intptr_t)(n); } while (0)
+#define setcharacter(v,n) do { (v) = (char *)(intptr_t)(n); } while (0)
+
+/*
+ * Escape command table definitions --
+ * lookup in this table is performed when ``escapec'' is recognized
+ * at the beginning of a line (as defined by the eolmarks variable).
+*/
+
+typedef
+ struct {
+ char e_char; /* char to match on */
+ char e_flags; /* experimental, privileged */
+ char *e_help; /* help string */
+ void (*e_func)(int); /* command */
+ }
+ esctable_t;
+
+#define NORM 00 /* normal protection, execute anyone */
+#define EXP 01 /* experimental, mark it with a `*' on help */
+#define PRIV 02 /* privileged, root execute only */
+
+extern int vflag; /* verbose during reading of .tiprc file */
+extern int noesc; /* no escape `~' char */
+extern value_t vtable[]; /* variable table */
+
+#ifndef ACULOG
+#define logent(a, b, c, d)
+#define loginit()
+#endif
+
+/*
+ * Definition of indices into variable table so
+ * value(DEFINE) turns into a static address.
+ */
+
+#define BEAUTIFY 0
+#define BAUDRATE 1
+#define DIALTIMEOUT 2
+#define EOFREAD 3
+#define EOFWRITE 4
+#define EOL 5
+#define ESCAPE 6
+#define EXCEPTIONS 7
+#define FORCE 8
+#define FRAMESIZE 9
+#define HOST 10
+#define LOG 11
+#define PHONES 12
+#define PROMPT 13
+#define RAISE 14
+#define RAISECHAR 15
+#define RECORD 16
+#define REMOTE 17
+#define SCRIPT 18
+#define TABEXPAND 19
+#define VERBOSE 20
+#define SHELL 21
+#define HOME 22
+#define ECHOCHECK 23
+#define DISCONNECT 24
+#define TAND 25
+#define LDELAY 26
+#define CDELAY 27
+#define ETIMEOUT 28
+#define RAWFTP 29
+#define HALFDUPLEX 30
+#define LECHO 31
+#define PARITY 32
+#define HARDWAREFLOW 33
+#define LINEDISC 34
+#define DC 35
+
+#define NOVAL ((value_t *)NULL)
+#define NOACU ((acu_t *)NULL)
+#define NOSTR ((char *)NULL)
+#define NOFILE ((FILE *)NULL)
+#define NOPWD ((struct passwd *)0)
+
+EXTERN struct termios term; /* current mode of terminal */
+EXTERN struct termios defterm; /* initial mode of terminal */
+EXTERN struct termios defchars; /* current mode with initial chars */
+EXTERN int gotdefterm;
+
+EXTERN FILE *fscript; /* FILE for scripting */
+
+EXTERN int fildes[2]; /* file transfer synchronization channel */
+EXTERN int repdes[2]; /* read process synchronization channel */
+EXTERN int FD; /* open file descriptor to remote host */
+EXTERN int AC; /* open file descriptor to dialer (v831 only) */
+EXTERN int vflag; /* print .tiprc initialization sequence */
+EXTERN int noesc; /* no `~' escape char */
+EXTERN int sfd; /* for ~< operation */
+EXTERN pid_t tipin_pid; /* pid of tipin */
+EXTERN pid_t tipout_pid; /* pid of tipout */
+EXTERN uid_t uid, euid; /* real and effective user id's */
+EXTERN gid_t gid, egid; /* real and effective group id's */
+EXTERN int stop; /* stop transfer session flag */
+EXTERN int quit; /* same; but on other end */
+EXTERN int intflag; /* recognized interrupt */
+EXTERN int stoprompt; /* for interrupting a prompt session */
+EXTERN int timedout; /* ~> transfer timedout */
+EXTERN int cumode; /* simulating the "cu" program */
+EXTERN int bits8; /* terminal is 8-bit mode */
+#define STRIP_PAR (bits8 ? 0377 : 0177)
+
+EXTERN char fname[PATH_MAX]; /* file name buffer for ~< */
+EXTERN char copyname[PATH_MAX]; /* file name buffer for ~> */
+EXTERN char ccc; /* synchronization character */
+EXTERN char *uucplock; /* name of lock file for uucp's */
+
+EXTERN int odisc; /* initial tty line discipline */
+extern int disc; /* current tty discpline */
+
+extern char *__progname; /* program name */
+
+char *con(void);
+char *ctrl(char);
+char *expand(char *);
+char *getremote(char *);
+char *interp(char *);
+int any(int, char *);
+int biz22w_dialer(char *, char *);
+int biz22f_dialer(char *, char *);
+int biz31w_dialer(char *, char *);
+int biz31f_dialer(char *, char *);
+int cour_dialer(char *, char *);
+int df02_dialer(char *, char *);
+int df03_dialer(char *, char *);
+int dn_dialer(char *, char *);
+int hay_dialer(char *, char *);
+int prompt(char *, char *, size_t);
+size_t size(char *);
+int t3000_dialer(char *, char *);
+int ttysetup(int);
+int uu_lock(char *);
+int uu_unlock(char *);
+int v3451_dialer(char *, char *);
+int v831_dialer(char *, char *);
+int ven_dialer(char *, char *);
+int vstring(char *, char *);
+long hunt(char *);
+void biz22_disconnect(void);
+void biz22_abort(void);
+void biz31_disconnect(void);
+void biz31_abort(void);
+void chdirectory(int);
+void cleanup(int);
+void consh(int);
+void cour_abort(void);
+void cour_disconnect(void);
+void cu_put(int);
+void cu_take(int);
+void cumain(int, char **);
+void daemon_uid(void);
+void df_abort(void);
+void df_disconnect(void);
+void disconnect(char *);
+void dn_abort(void);
+void dn_disconnect(void);
+void finish(int);
+void genbrk(int);
+void getfl(int);
+void hay_abort(void);
+void hay_disconnect(void);
+void help(int);
+void listvariables(int);
+void logent(char *, char *, char *, char *);
+void loginit(void);
+void parwrite(int, char *, size_t);
+void pipefile(int);
+void pipeout(int);
+void raw(void);
+void sendfile(int);
+void setparity(char *);
+void setscript(void);
+void shell(int);
+void shell_uid(void);
+void suspend(int);
+void t3000_disconnect(void);
+void t3000_abort(void);
+void timeout(int);
+void tipabort(char *);
+void tipout(void);
+void user_uid(void);
+void unexcl(void);
+void unraw(void);
+void v3451_abort(void);
+void v3451_disconnect(void);
+void v831_disconnect(void);
+void v831_abort(void);
+void variable(int);
+void ven_disconnect(void);
+void ven_abort(void);
+void vinit(void);
+void vlex(char *);
diff --git a/usr.bin/tip/tip/tipout.c b/usr.bin/tip/tip/tipout.c
new file mode 100644
index 000000000000..be0d5c7c48e2
--- /dev/null
+++ b/usr.bin/tip/tip/tipout.c
@@ -0,0 +1,180 @@
+/* $OpenBSD: tipout.c,v 1.18 2006/05/31 07:03:08 jason Exp $ */
+/* $NetBSD: tipout.c,v 1.5 1996/12/29 10:34:12 cgd Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+/*
+ * tip
+ *
+ * lower fork of tip -- handles passive side
+ * reading from the remote host
+ */
+
+static jmp_buf sigbuf;
+
+static void intIOT(int);
+static void intEMT(int);
+static void intTERM(int);
+static void intSYS(int);
+
+/*
+ * TIPOUT wait state routine --
+ * sent by TIPIN when it wants to posses the remote host
+ */
+/*ARGSUSED*/
+static void
+intIOT(int signo)
+{
+ write(repdes[1],&ccc,1);
+ read(fildes[0], &ccc,1);
+ longjmp(sigbuf, 1);
+}
+
+/*
+ * Scripting command interpreter --
+ * accepts script file name over the pipe and acts accordingly
+ */
+/*ARGSUSED*/
+static void
+intEMT(int signo)
+{
+ char c, line[256];
+ char *pline = line;
+ char reply;
+
+ read(fildes[0], &c, 1);
+ while (c != '\n' && (size_t)(pline - line) < sizeof(line)) {
+ *pline++ = c;
+ read(fildes[0], &c, 1);
+ }
+ *pline = '\0';
+ if (boolean(value(SCRIPT)) && fscript != NULL)
+ fclose(fscript);
+ if (pline == line) {
+ setboolean(value(SCRIPT), FALSE);
+ reply = 'y';
+ } else {
+ if ((fscript = fopen(line, "a")) == NULL)
+ reply = 'n';
+ else {
+ reply = 'y';
+ setboolean(value(SCRIPT), TRUE);
+ }
+ }
+ write(repdes[1], &reply, 1);
+ longjmp(sigbuf, 1);
+}
+
+static void
+intTERM(int signo)
+{
+ if (boolean(value(SCRIPT)) && fscript != NULL)
+ fclose(fscript);
+ if (signo && tipin_pid)
+ kill(tipin_pid, signo);
+ exit(0);
+}
+
+/*ARGSUSED*/
+static void
+intSYS(int signo)
+{
+ setboolean(value(BEAUTIFY), !boolean(value(BEAUTIFY)));
+ longjmp(sigbuf, 1);
+}
+
+/*
+ * ****TIPOUT TIPOUT****
+ */
+void
+tipout(void)
+{
+ char buf[BUFSIZ];
+ char *cp;
+ ssize_t scnt;
+ size_t cnt;
+ sigset_t mask, omask;
+
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGEMT, intEMT); /* attention from TIPIN */
+ signal(SIGTERM, intTERM); /* time to go signal */
+ signal(SIGIOT, intIOT); /* scripting going on signal */
+ signal(SIGHUP, intTERM); /* for dial-ups */
+ signal(SIGSYS, intSYS); /* beautify toggle */
+ (void) setjmp(sigbuf);
+ sigprocmask(SIG_BLOCK, NULL, &omask);
+ for (;;) {
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ scnt = read(FD, buf, BUFSIZ);
+ if (scnt <= 0) {
+ /* lost carrier */
+ if (scnt == 0 ||
+ (scnt < 0 && (errno == EIO || errno == ENXIO))) {
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+ intTERM(SIGHUP);
+ /*NOTREACHED*/
+ }
+ continue;
+ }
+ cnt = scnt;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGEMT);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGIOT);
+ sigaddset(&mask, SIGSYS);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+ for (cp = buf; cp < buf + cnt; cp++)
+ *cp &= STRIP_PAR;
+ write(STDOUT_FILENO, buf, cnt);
+ if (boolean(value(SCRIPT)) && fscript != NULL) {
+ if (!boolean(value(BEAUTIFY))) {
+ fwrite(buf, 1, cnt, fscript);
+ } else {
+ for (cp = buf; cp < buf + cnt; cp++)
+ if ((*cp >= ' ' && *cp <= '~') ||
+ any(*cp, value(EXCEPTIONS)))
+ putc(*cp, fscript);
+ }
+ for (cp = buf; cp < buf + cnt; cp++) {
+ if (!isgraph(*cp)) {
+ fflush(fscript);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/usr.bin/tip/tip/uucplock.c b/usr.bin/tip/tip/uucplock.c
new file mode 100644
index 000000000000..e29cbc149274
--- /dev/null
+++ b/usr.bin/tip/tip/uucplock.c
@@ -0,0 +1,123 @@
+/* $OpenBSD: uucplock.c,v 1.11 2006/03/16 19:32:46 deraadt Exp $ */
+/* $NetBSD: uucplock.c,v 1.7 1997/02/11 09:24:08 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "tip.h"
+#include "pathnames.h"
+
+/*
+ * uucp style locking routines
+ * return: 0 - success
+ * -1 - failure
+ */
+
+int
+uu_lock(char *ttyname)
+{
+ int fd, len;
+ char tbuf[sizeof(_PATH_LOCKDIRNAME) + MAXNAMLEN];
+ char text_pid[81];
+ pid_t pid;
+
+ (void)snprintf(tbuf, sizeof tbuf, _PATH_LOCKDIRNAME, ttyname);
+ fd = open(tbuf, O_RDWR|O_CREAT|O_EXCL, 0660);
+ if (fd < 0) {
+ /*
+ * file is already locked
+ * check to see if the process holding the lock still exists
+ */
+ fd = open(tbuf, O_RDWR, 0);
+ if (fd < 0) {
+ perror(tbuf);
+ fprintf(stderr, "Can't open lock file.\n");
+ return(-1);
+ }
+ len = read(fd, text_pid, sizeof(text_pid)-1);
+ if (len<=0) {
+ perror(tbuf);
+ (void)close(fd);
+ fprintf(stderr, "Can't read lock file.\n");
+ return(-1);
+ }
+ text_pid[len] = 0;
+ pid = atol(text_pid);
+
+ if (kill(pid, 0) == 0 || errno != ESRCH) {
+ (void)close(fd); /* process is still running */
+ return(-1);
+ }
+ /*
+ * The process that locked the file isn't running, so
+ * we'll lock it ourselves
+ */
+ fprintf(stderr, "Stale lock on %s PID=%ld... overriding.\n",
+ ttyname, (long)pid);
+ if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
+ perror(tbuf);
+ (void)close(fd);
+ fprintf(stderr, "Can't seek lock file.\n");
+ return(-1);
+ }
+ /* fall out and finish the locking process */
+ }
+ pid = getpid();
+ (void)snprintf(text_pid, sizeof text_pid, "%10ld\n", (long)pid);
+ len = strlen(text_pid);
+ if (write(fd, text_pid, len) != len) {
+ (void)close(fd);
+ (void)unlink(tbuf);
+ perror("lock write");
+ return(-1);
+ }
+ (void)close(fd);
+ return(0);
+}
+
+int
+uu_unlock(char *ttyname)
+{
+ char tbuf[sizeof(_PATH_LOCKDIRNAME) + MAXNAMLEN];
+
+ (void)snprintf(tbuf, sizeof tbuf, _PATH_LOCKDIRNAME, ttyname);
+ unexcl();
+ return(unlink(tbuf));
+}
diff --git a/usr.bin/tip/tip/value.c b/usr.bin/tip/tip/value.c
new file mode 100644
index 000000000000..4fce98e31361
--- /dev/null
+++ b/usr.bin/tip/tip/value.c
@@ -0,0 +1,355 @@
+/* $OpenBSD: value.c,v 1.14 2006/03/17 22:02:58 moritz Exp $ */
+/* $NetBSD: value.c,v 1.6 1997/02/11 09:24:09 mrg Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+
+#define MIDDLE 35
+
+static value_t *vlookup(char *);
+static void vassign(value_t *, char *);
+static void vtoken(char *);
+static void vprint(value_t *);
+static int vaccess(unsigned int, unsigned int);
+static char *vinterp(char *, int);
+
+static size_t col = 0;
+
+/*
+ * Variable manipulation
+ */
+void
+vinit(void)
+{
+ char file[FILENAME_MAX], *cp;
+ value_t *p;
+ FILE *fp;
+
+ for (p = vtable; p->v_name != NULL; p++) {
+ if (p->v_type&ENVIRON)
+ if ((cp = getenv(p->v_name)))
+ p->v_value = cp;
+ if (p->v_type&IREMOTE) {
+ switch (p->v_type&TMASK) {
+ case STRING:
+ p->v_value = *(char **)p->v_value;
+ break;
+ case NUMBER:
+ setnumber(p->v_value, *(long *)p->v_value);
+ break;
+ case BOOL:
+ setboolean(p->v_value, *(short *)p->v_value);
+ break;
+ case CHAR:
+ setcharacter(p->v_value, *(char *)p->v_value);
+ break;
+ }
+ }
+ }
+ /*
+ * Read the .tiprc file in the HOME directory
+ * for sets
+ */
+ cp = value(HOME);
+ if (cp == NULL) {
+ (void)fprintf(stderr,
+ "$HOME not set. Skipping check for ~/.tiprc\n");
+ } else if (strlen(cp) + sizeof("/.tiprc") > sizeof(file)) {
+ (void)fprintf(stderr, "Home directory path too long: %s\n",
+ value(HOME));
+ } else {
+ snprintf(file, sizeof file, "%s/.tiprc", value(HOME));
+ if ((fp = fopen(file, "r")) != NULL) {
+ char *tp;
+
+ while (fgets(file, sizeof(file)-1, fp) != NULL) {
+ if (vflag)
+ printf("set %s", file);
+ if ((tp = strrchr(file, '\n')))
+ *tp = '\0';
+ vlex(file);
+ }
+ fclose(fp);
+ }
+ }
+ /*
+ * To allow definition of exception prior to fork
+ */
+ vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
+}
+
+/*VARARGS1*/
+static void
+vassign(value_t *p, char *v)
+{
+ if (!vaccess(p->v_access, WRITE)) {
+ printf("access denied\r\n");
+ return;
+ }
+
+ switch (p->v_type&TMASK) {
+ case STRING:
+ if (p->v_value && equal(p->v_value, v))
+ return;
+ if (!(p->v_type&(ENVIRON|INIT)))
+ free(p->v_value);
+ if ((p->v_value = strdup(v)) == NOSTR) {
+ printf("out of core\r\n");
+ return;
+ }
+ p->v_type &= ~(ENVIRON|INIT);
+ break;
+ case NUMBER:
+ if (number(p->v_value) == number(v))
+ return;
+ setnumber(p->v_value, number(v));
+ break;
+ case BOOL:
+ if (boolean(p->v_value) == (*v != '!'))
+ return;
+ setboolean(p->v_value, (*v != '!'));
+ break;
+ case CHAR:
+ if (character(p->v_value) == *v)
+ return;
+ setcharacter(p->v_value, *v);
+ }
+ p->v_access |= CHANGED;
+}
+
+void
+vlex(char *s)
+{
+ value_t *p;
+ char *cp;
+
+ if (equal(s, "all")) {
+ for (p = vtable; p->v_name; p++)
+ if (vaccess(p->v_access, READ))
+ vprint(p);
+ } else {
+ do {
+ if ((cp = vinterp(s, ' ')))
+ cp++;
+ vtoken(s);
+ s = cp;
+ } while (s);
+ }
+ if (col > 0) {
+ printf("\r\n");
+ col = 0;
+ }
+}
+
+static void
+vtoken(char *s)
+{
+ value_t *p;
+ char *cp;
+
+ if ((cp = strchr(s, '='))) {
+ *cp = '\0';
+ if ((p = vlookup(s))) {
+ cp++;
+ if (p->v_type&NUMBER)
+ vassign(p, (char *)(intptr_t)atoi(cp));
+ else {
+ if (strcmp(s, "record") == 0)
+ cp = expand(cp);
+ vassign(p, cp);
+ }
+ return;
+ }
+ } else if ((cp = strchr(s, '?'))) {
+ *cp = '\0';
+ if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
+ vprint(p);
+ return;
+ }
+ } else {
+ if (*s != '!')
+ p = vlookup(s);
+ else
+ p = vlookup(s+1);
+ if (p != NOVAL) {
+ vassign(p, s);
+ return;
+ }
+ }
+ printf("%s: unknown variable\r\n", s);
+}
+
+static void
+vprint(value_t *p)
+{
+ char *cp;
+
+ if (col > 0 && col < MIDDLE)
+ while (col++ < MIDDLE)
+ putchar(' ');
+ col += size(p->v_name);
+ switch (p->v_type&TMASK) {
+
+ case BOOL:
+ if (boolean(p->v_value) == FALSE) {
+ col++;
+ putchar('!');
+ }
+ printf("%s", p->v_name);
+ break;
+
+ case STRING:
+ printf("%s=", p->v_name);
+ col++;
+ if (p->v_value) {
+ cp = interp(p->v_value);
+ col += size(cp);
+ printf("%s", cp);
+ }
+ break;
+
+ case NUMBER:
+ col += 6;
+ printf("%s=%-5ld", p->v_name, number(p->v_value));
+ break;
+
+ case CHAR:
+ printf("%s=", p->v_name);
+ col++;
+ if (p->v_value) {
+ cp = ctrl(character(p->v_value));
+ col += size(cp);
+ printf("%s", cp);
+ }
+ break;
+ }
+ if (col >= MIDDLE) {
+ col = 0;
+ printf("\r\n");
+ return;
+ }
+}
+
+static int
+vaccess(unsigned int mode, unsigned int rw)
+{
+ if (mode & (rw<<PUBLIC))
+ return (1);
+ if (mode & (rw<<PRIVATE))
+ return (1);
+ return ((mode & (rw<<ROOT)) && getuid() == 0);
+}
+
+static value_t *
+vlookup(char *s)
+{
+ value_t *p;
+
+ for (p = vtable; p->v_name; p++)
+ if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
+ return (p);
+ return (NULL);
+}
+
+static char *
+vinterp(char *s, int stop)
+{
+ char *p = s, c;
+ int num;
+
+ while ((c = *s++) && c != stop) {
+ switch (c) {
+
+ case '^':
+ if (*s)
+ *p++ = *s++ - 0100;
+ else
+ *p++ = c;
+ break;
+
+ case '\\':
+ num = 0;
+ c = *s++;
+ if (c >= '0' && c <= '7')
+ num = (num<<3)+(c-'0');
+ else {
+ char *q = "n\nr\rt\tb\bf\f";
+
+ for (; *q; q++)
+ if (c == *q++) {
+ *p++ = *q;
+ goto cont;
+ }
+ *p++ = c;
+ cont:
+ break;
+ }
+ if ((c = *s++) >= '0' && c <= '7') {
+ num = (num<<3)+(c-'0');
+ if ((c = *s++) >= '0' && c <= '7')
+ num = (num<<3)+(c-'0');
+ else
+ s--;
+ } else
+ s--;
+ *p++ = num;
+ break;
+
+ default:
+ *p++ = c;
+ }
+ }
+ *p = '\0';
+ return (c == stop ? s-1 : NULL);
+}
+
+/*
+ * assign variable s with value v (for NUMBER or STRING or CHAR types)
+ */
+int
+vstring(char *s, char *v)
+{
+ value_t *p;
+
+ p = vlookup(s);
+ if (p == 0)
+ return (1);
+ if (p->v_type&NUMBER)
+ vassign(p, (char *)(intptr_t)atoi(v));
+ else {
+ if (strcmp(s, "record") == 0)
+ v = expand(v);
+ vassign(p, v);
+ }
+ return (0);
+}
diff --git a/usr.bin/tip/tip/vars.c b/usr.bin/tip/tip/vars.c
new file mode 100644
index 000000000000..332d6b871ff1
--- /dev/null
+++ b/usr.bin/tip/tip/vars.c
@@ -0,0 +1,116 @@
+/* $OpenBSD: vars.c,v 1.8 2006/08/18 03:06:18 jason Exp $ */
+/* $NetBSD: vars.c,v 1.3 1994/12/08 09:31:19 jtc Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 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.
+ */
+
+#include "tip.h"
+#include "pathnames.h"
+
+/*
+ * Definition of variables
+ */
+value_t vtable[] = {
+ { "beautify", BOOL, (READ|WRITE)<<PUBLIC,
+ "be", (char *)TRUE },
+ { "baudrate", NUMBER|IREMOTE|INIT, (READ<<PUBLIC)|(WRITE<<ROOT),
+ "ba", (char *)&BR },
+ { "dialtimeout",NUMBER, (READ<<PUBLIC)|(WRITE<<ROOT),
+ "dial", (char *)60 },
+ { "eofread", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "eofr", (char *)&IE },
+ { "eofwrite", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "eofw", (char *)&OE },
+ { "eol", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ NOSTR, (char *)&EL },
+ { "escape", CHAR, (READ|WRITE)<<PUBLIC,
+ "es", (char *)'~' },
+ { "exceptions", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
+ "ex", (char *)&EX },
+ { "force", CHAR, (READ|WRITE)<<PUBLIC,
+ "fo", (char *)CTRL('p') },
+ { "framesize", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "fr", (char *)&FS },
+ { "host", STRING|IREMOTE|INIT, READ<<PUBLIC,
+ "ho", (char *)&HO },
+ { "log", STRING|INIT, (READ|WRITE)<<ROOT,
+ NOSTR, _PATH_ACULOG },
+ { "phones", STRING|INIT|IREMOTE, READ<<PUBLIC,
+ NOSTR, (char *)&PH },
+ { "prompt", CHAR, (READ|WRITE)<<PUBLIC,
+ "pr", (char *)'\n' },
+ { "raise", BOOL, (READ|WRITE)<<PUBLIC,
+ "ra", (char *)FALSE },
+ { "raisechar", CHAR, (READ|WRITE)<<PUBLIC,
+ "rc", NOSTR },
+ { "record", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
+ "rec", (char *)&RE },
+ { "remote", STRING|INIT|IREMOTE, READ<<PUBLIC,
+ NOSTR, (char *)&RM },
+ { "script", BOOL, (READ|WRITE)<<PUBLIC,
+ "sc", (char *)FALSE },
+ { "tabexpand", BOOL, (READ|WRITE)<<PUBLIC,
+ "tab", (char *)FALSE },
+ { "verbose", BOOL, (READ|WRITE)<<PUBLIC,
+ "verb", (char *)TRUE },
+ { "SHELL", STRING|ENVIRON|INIT, (READ|WRITE)<<PUBLIC,
+ NULL, _PATH_BSHELL },
+ { "HOME", STRING|ENVIRON, (READ|WRITE)<<PUBLIC,
+ NOSTR, NOSTR },
+ { "echocheck", BOOL, (READ|WRITE)<<PUBLIC,
+ "ec", (char *)FALSE },
+ { "disconnect", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "di", (char *)&DI },
+ { "tandem", BOOL, (READ|WRITE)<<PUBLIC,
+ "ta", (char *)TRUE },
+ { "linedelay", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "ldelay", (char *)&DL },
+ { "chardelay", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "cdelay", (char *)&CL },
+ { "etimeout", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "et", (char *)&ET },
+ { "rawftp", BOOL, (READ|WRITE)<<PUBLIC,
+ "raw", (char *)FALSE },
+ { "halfduplex", BOOL, (READ|WRITE)<<PUBLIC,
+ "hdx", (char *)FALSE },
+ { "localecho", BOOL, (READ|WRITE)<<PUBLIC,
+ "le", (char *)FALSE },
+ { "parity", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
+ "par", (char *)&PA },
+ { "hardwareflow", BOOL, (READ|WRITE)<<PUBLIC,
+ "hf", (char *)FALSE },
+ { "linedisc", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
+ "ld", (char *)&LD },
+ { "direct", BOOL, (READ<<PUBLIC)|(WRITE<<ROOT),
+ "dc", (char *)FALSE },
+ { NOSTR, 0, 0,
+ NOSTR, NOSTR }
+};
diff --git a/usr.bin/top/Makefile b/usr.bin/top/Makefile
new file mode 100644
index 000000000000..007c9b306d23
--- /dev/null
+++ b/usr.bin/top/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= top
+SRCS= commands.c display.c machine.c screen.c top.c \
+ username.c utils.c
+MAN= top.1
+
+LIBADD= tinfow m kvm jail util sbuf
+.include <bsd.prog.mk>
diff --git a/usr.bin/top/Makefile.depend b/usr.bin/top/Makefile.depend
new file mode 100644
index 000000000000..c3ffc7591565
--- /dev/null
+++ b/usr.bin/top/Makefile.depend
@@ -0,0 +1,21 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libjail \
+ lib/libkvm \
+ lib/libsbuf \
+ lib/libutil \
+ lib/msun \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/top/commands.c b/usr.bin/top/commands.c
new file mode 100644
index 000000000000..e65f4ee6c4c4
--- /dev/null
+++ b/usr.bin/top/commands.c
@@ -0,0 +1,518 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * This file contains the routines that implement some of the interactive
+ * mode commands. Note that some of the commands are implemented in-line
+ * in "main". This is necessary because they change the global state of
+ * "top" (i.e.: changing the number of processes to display).
+ */
+
+#include <sys/resource.h>
+#include <sys/signal.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "commands.h"
+#include "top.h"
+#include "machine.h"
+
+static int err_compar(const void *p1, const void *p2);
+
+struct errs /* structure for a system-call error */
+{
+ int errnum; /* value of errno (that is, the actual error) */
+ char *arg; /* argument that caused the error */
+};
+
+static char *err_string(void);
+static int str_adderr(char *str, int len, int err);
+static int str_addarg(char *str, int len, char *arg, bool first);
+
+/*
+ * show_help() - display the help screen; invoked in response to
+ * either 'h' or '?'.
+ */
+
+const struct command all_commands[] =
+{
+ {'C', "toggle the displaying of weighted CPU percentage", false, CMD_wcputog},
+ {'d', "change number of displays to show", false, CMD_displays},
+ {'e', "list errors generated by last \"kill\" or \"renice\" command", false, CMD_errors},
+ {'H', "toggle the displaying of threads", false, CMD_thrtog},
+ {'h', "show this help text", true, CMD_help},
+ {'?', NULL, true, CMD_help},
+ {'/', "filter on command name (+ selects all commands)", false, CMD_grep},
+ {'i', "toggle the displaying of idle processes", false, CMD_idletog},
+ {'I', NULL, false, CMD_idletog},
+ {'j', "toggle the displaying of jail ID", false, CMD_jidtog},
+ {'J', "display processes for only one jail (+ selects all jails)", false, CMD_jail},
+ {'k', "kill processes; send a signal to a list of processes", false, CMD_kill},
+ {'q', "quit" , true, CMD_quit},
+ {'m', "toggle the display between 'cpu' and 'io' modes", false, CMD_viewtog},
+ {'n', "change number of processes to display", false, CMD_number},
+ {'#', NULL, false, CMD_number},
+ {'o', "specify the sort order", false, CMD_order},
+ {'p', "display one process (+ selects all processes)", false, CMD_pid},
+ {'P', "toggle the displaying of per-CPU statistics", false, CMD_pcputog},
+ {'r', "renice a process", false, CMD_renice},
+ {'s', "change number of seconds to delay between updates", false, CMD_delay},
+ {'S', "toggle the displaying of system processes", false, CMD_viewsys},
+ {'a', "toggle the displaying of process titles", false, CMD_showargs},
+ {'T', "toggle the displaying of thread IDs", false, CMD_toggletid},
+ {'t', "toggle the display of this process", false, CMD_selftog},
+ {'u', "display processes for only one user (+ selects all users)", false, CMD_user},
+ {'w', "toggle the display of swap use for each process", false, CMD_swaptog},
+ {'z', "toggle the displaying of the system idle process", false, CMD_kidletog},
+ {' ', "update the display", false, CMD_update},
+ {0, NULL, true, CMD_NONE}
+};
+
+void
+show_help(void)
+{
+ const struct command *curcmd, *nextcmd;
+ char keys[8] = "";
+ _Static_assert(sizeof(keys) >= sizeof("a or b"), "keys right size");
+
+ printf("Top version FreeBSD, %s\n", copyright);
+ curcmd = all_commands;
+ while (curcmd->c != 0) {
+ if (overstrike && !curcmd->available_to_dumb) {
+ ++curcmd;
+ continue;
+ }
+ if (curcmd->desc == NULL) {
+ /* we already printed this */
+ ++curcmd;
+ continue;
+ }
+ nextcmd = curcmd + 1;
+ if (nextcmd->desc == NULL && nextcmd->c != '\0') {
+ sprintf(keys, "%c or %c", curcmd->c, nextcmd->c);
+ } else if (curcmd->c == ' '){
+ /* special case space rather than introducing a "display string" to
+ * the struct */
+ sprintf(keys, "SPC");
+ } else {
+ sprintf(keys, "%c", curcmd->c);
+ }
+ printf("%s\t- %s\n", keys, curcmd->desc);
+ ++curcmd;
+ }
+ if (overstrike)
+ {
+ fputs("\
+ Other commands are also available, but this terminal is not\n\
+ sophisticated enough to handle those commands gracefully.\n", stdout);
+ }
+}
+
+/*
+ * Utility routines that help with some of the commands.
+ */
+
+static char *
+next_field(char *str)
+{
+ if ((str = strchr(str, ' ')) == NULL)
+ {
+ return(NULL);
+ }
+ *str = '\0';
+ while (*++str == ' ') /* loop */;
+
+ /* if there is nothing left of the string, return NULL */
+ /* This fix is dedicated to Greg Earle */
+ return(*str == '\0' ? NULL : str);
+}
+
+static int
+scanint(char *str, int *intp)
+{
+ int val = 0;
+ char ch;
+
+ /* if there is nothing left of the string, flag it as an error */
+ /* This fix is dedicated to Greg Earle */
+ if (*str == '\0')
+ {
+ return(-1);
+ }
+
+ while ((ch = *str++) != '\0')
+ {
+ if (isdigit(ch))
+ {
+ val = val * 10 + (ch - '0');
+ }
+ else if (isspace(ch))
+ {
+ break;
+ }
+ else
+ {
+ return(-1);
+ }
+ }
+ *intp = val;
+ return(0);
+}
+
+/*
+ * Some of the commands make system calls that could generate errors.
+ * These errors are collected up in an array of structures for later
+ * contemplation and display. Such routines return a string containing an
+ * error message, or NULL if no errors occurred. The next few routines are
+ * for manipulating and displaying these errors. We need an upper limit on
+ * the number of errors, so we arbitrarily choose 20.
+ */
+
+#define ERRMAX 20
+
+static struct errs errs[ERRMAX];
+static int errcnt;
+static char err_toomany[] = " too many errors occurred";
+static char err_listem[] =
+ " Many errors occurred. Press `e' to display the list of errors.";
+
+/* These macros get used to reset and log the errors */
+#define ERR_RESET errcnt = 0
+#define ERROR(p, e) if (errcnt >= ERRMAX) \
+ { \
+ return(err_toomany); \
+ } \
+ else \
+ { \
+ errs[errcnt].arg = (p); \
+ errs[errcnt++].errnum = (e); \
+ }
+
+/*
+ * err_string() - return an appropriate error string. This is what the
+ * command will return for displaying. If no errors were logged, then
+ * return NULL. The maximum length of the error string is defined by
+ * "STRMAX".
+ */
+
+#define STRMAX 80
+
+char *
+err_string(void)
+{
+ struct errs *errp;
+ int cnt = 0;
+ bool first = true;
+ int currerr = -1;
+ int stringlen; /* characters still available in "string" */
+ static char string[STRMAX];
+
+ /* if there are no errors, return NULL */
+ if (errcnt == 0)
+ {
+ return(NULL);
+ }
+
+ /* sort the errors */
+ qsort((char *)errs, errcnt, sizeof(struct errs), err_compar);
+
+ /* need a space at the front of the error string */
+ string[0] = ' ';
+ string[1] = '\0';
+ stringlen = STRMAX - 2;
+
+ /* loop thru the sorted list, building an error string */
+ while (cnt < errcnt)
+ {
+ errp = &(errs[cnt++]);
+ if (errp->errnum != currerr)
+ {
+ if (currerr >= 0)
+ {
+ if ((stringlen = str_adderr(string, stringlen, currerr)) < 2)
+ {
+ return(err_listem);
+ }
+ strcat(string, "; "); /* we know there's more */
+ }
+ currerr = errp->errnum;
+ first = true;
+ }
+ if ((stringlen = str_addarg(string, stringlen, errp->arg, first)) ==0)
+ {
+ return(err_listem);
+ }
+ first = false;
+ }
+
+ /* add final message */
+ stringlen = str_adderr(string, stringlen, currerr);
+
+ /* return the error string */
+ return(stringlen == 0 ? err_listem : string);
+}
+
+/*
+ * str_adderr(str, len, err) - add an explanation of error "err" to
+ * the string "str".
+ */
+
+static int
+str_adderr(char *str, int len, int err)
+{
+ const char *msg;
+ int msglen;
+
+ msg = err == 0 ? "Not a number" : strerror(err);
+ msglen = strlen(msg) + 2;
+ if (len <= msglen)
+ {
+ return(0);
+ }
+ strcat(str, ": ");
+ strcat(str, msg);
+ return(len - msglen);
+}
+
+/*
+ * str_addarg(str, len, arg, first) - add the string argument "arg" to
+ * the string "str". This is the first in the group when "first"
+ * is set (indicating that a comma should NOT be added to the front).
+ */
+
+static int
+str_addarg(char str[], int len, char arg[], bool first)
+{
+ int arglen;
+
+ arglen = strlen(arg);
+ if (!first)
+ {
+ arglen += 2;
+ }
+ if (len <= arglen)
+ {
+ return(0);
+ }
+ if (!first)
+ {
+ strcat(str, ", ");
+ }
+ strcat(str, arg);
+ return(len - arglen);
+}
+
+/*
+ * err_compar(p1, p2) - comparison routine used by "qsort"
+ * for sorting errors.
+ */
+
+static int
+err_compar(const void *p1, const void *p2)
+{
+ int result;
+ const struct errs * const g1 = (const struct errs * const)p1;
+ const struct errs * const g2 = (const struct errs * const)p2;
+
+
+
+ if ((result = g1->errnum - g2->errnum) == 0)
+ {
+ return(strcmp(g1->arg, g2->arg));
+ }
+ return(result);
+}
+
+/*
+ * error_count() - return the number of errors currently logged.
+ */
+
+int
+error_count(void)
+{
+ return(errcnt);
+}
+
+/*
+ * show_errors() - display on stdout the current log of errors.
+ */
+
+void
+show_errors(void)
+{
+ int cnt = 0;
+ struct errs *errp = errs;
+
+ printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
+ while (cnt++ < errcnt)
+ {
+ printf("%5s: %s\n", errp->arg,
+ errp->errnum == 0 ? "Not a number" : strerror(errp->errnum));
+ errp++;
+ }
+}
+
+static const char no_proc_specified[] = " no processes specified";
+static const char invalid_signal_number[] = " invalid_signal_number";
+static const char bad_signal_name[] = " bad signal name";
+static const char bad_pri_value[] = " bad priority value";
+
+static int
+signame_to_signum(const char * sig)
+{
+ int n;
+
+ if (strncasecmp(sig, "SIG", 3) == 0)
+ sig += 3;
+ for (n = 1; n < sys_nsig; n++) {
+ if (!strcasecmp(sys_signame[n], sig))
+ return (n);
+ }
+ return (-1);
+}
+
+/*
+ * kill_procs(str) - send signals to processes, much like the "kill"
+ * command does; invoked in response to 'k'.
+ */
+
+const char *
+kill_procs(char *str)
+{
+ char *nptr;
+ int signum = SIGTERM; /* default */
+ int procnum;
+
+ /* reset error array */
+ ERR_RESET;
+
+ /* skip over leading white space */
+ while (isspace(*str)) str++;
+
+ if (str[0] == '-')
+ {
+ /* explicit signal specified */
+ if ((nptr = next_field(str)) == NULL)
+ {
+ return(no_proc_specified);
+ }
+
+ if (isdigit(str[1]))
+ {
+ scanint(str + 1, &signum);
+ if (signum <= 0 || signum >= NSIG)
+ {
+ return(invalid_signal_number);
+ }
+ }
+ else
+ {
+ signum = signame_to_signum(str + 1);
+
+ /* was it ever found */
+ if (signum == -1 )
+ {
+ return(bad_signal_name);
+ }
+ }
+ /* put the new pointer in place */
+ str = nptr;
+ }
+
+ /* loop thru the string, killing processes */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+ else
+ {
+ /* go in for the kill */
+ if (kill(procnum, signum) == -1)
+ {
+ /* chalk up an error */
+ ERROR(str, errno);
+ }
+ }
+ } while ((str = next_field(str)) != NULL);
+
+ /* return appropriate error string */
+ return(err_string());
+}
+
+/*
+ * renice_procs(str) - change the "nice" of processes, much like the
+ * "renice" command does; invoked in response to 'r'.
+ */
+
+const char *
+renice_procs(char *str)
+{
+ char negate;
+ int prio;
+ int procnum;
+
+ ERR_RESET;
+
+ /* allow for negative priority values */
+ if ((negate = (*str == '-')) != 0)
+ {
+ /* move past the minus sign */
+ str++;
+ }
+
+ /* use procnum as a temporary holding place and get the number */
+ procnum = scanint(str, &prio);
+
+ /* negate if necessary */
+ if (negate)
+ {
+ prio = -prio;
+ }
+
+ /* check for validity */
+ if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX)
+ {
+ return(bad_pri_value);
+ }
+
+ /* move to the first process number */
+ if ((str = next_field(str)) == NULL)
+ {
+ return(no_proc_specified);
+ }
+
+ /* loop thru the process numbers, renicing each one */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+
+ if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
+ {
+ ERROR(str, errno);
+ }
+ } while ((str = next_field(str)) != NULL);
+
+ /* return appropriate error string */
+ return(err_string());
+}
+
diff --git a/usr.bin/top/commands.h b/usr.bin/top/commands.h
new file mode 100644
index 000000000000..63ed2f9b6471
--- /dev/null
+++ b/usr.bin/top/commands.h
@@ -0,0 +1,59 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ * Copyright (c) 2016, Randy Westlund
+ */
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+void show_errors(void);
+int error_count(void);
+void show_help(void);
+
+enum cmd_id {
+ CMD_NONE,
+ CMD_redraw,
+ CMD_update,
+ CMD_quit,
+ CMD_help,
+ CMD_grep,
+ CMD_errors,
+ CMD_number,
+ CMD_delay,
+ CMD_displays,
+ CMD_kill,
+ CMD_renice,
+ CMD_idletog,
+ CMD_user,
+ CMD_selftog,
+ CMD_thrtog,
+ CMD_viewtog,
+ CMD_viewsys,
+ CMD_wcputog,
+ CMD_showargs,
+ CMD_jidtog,
+ CMD_kidletog,
+ CMD_pcputog,
+ CMD_jail,
+ CMD_swaptog,
+ CMD_order,
+ CMD_pid ,
+ CMD_toggletid,
+};
+
+struct command {
+ char c;
+ const char * const desc;
+ bool available_to_dumb;
+ enum cmd_id id;
+};
+
+extern const struct command all_commands[];
+
+#endif /* COMMANDS_H */
diff --git a/usr.bin/top/display.c b/usr.bin/top/display.c
new file mode 100644
index 000000000000..b6cde0e63aa7
--- /dev/null
+++ b/usr.bin/top/display.c
@@ -0,0 +1,1361 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * This file contains the routines that display information on the screen.
+ * Each section of the screen has two routines: one for initially writing
+ * all constant and dynamic text, and one for only updating the text that
+ * changes. The prefix "i_" is used on all the "initial" routines and the
+ * prefix "u_" is used for all the "updating" routines.
+ *
+ * ASSUMPTIONS:
+ * None of the "i_" routines use any of the termcap capabilities.
+ * In this way, those routines can be safely used on terminals that
+ * have minimal (or nonexistant) terminal capabilities.
+ *
+ * The routines are called in this order: *_loadave, i_timeofday,
+ * *_procstates, *_cpustates, *_memory, *_message, *_header,
+ * *_process, u_endscreen.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <termcap.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "screen.h" /* interface to screen package */
+#include "layout.h" /* defines for screen position layout */
+#include "display.h"
+#include "top.h"
+#include "machine.h" /* we should eliminate this!!! */
+#include "utils.h"
+
+#ifdef DEBUG
+FILE *debug;
+#endif
+
+static int lmpid = 0;
+static int last_hi = 0; /* used in u_process and u_endscreen */
+static int lastline = 0;
+
+#define lineindex(l) ((l)*screen_width)
+
+
+/* things initialized by display_init and used thruout */
+
+/* buffer of proc information lines for display updating */
+static char *screenbuf = NULL;
+
+static const char * const *procstate_names;
+static const char * const *cpustate_names;
+static const char * const *memory_names;
+static const char * const *arc_names;
+static const char * const *carc_names;
+static const char * const *swap_names;
+
+static int num_procstates;
+static int num_cpustates;
+static int num_memory;
+static int num_swap;
+
+static int *lprocstates;
+static int *lcpustates;
+static int *lmemory;
+static int *lswap;
+
+static int num_cpus;
+static int *cpustate_columns;
+static int cpustate_total_length;
+static int cpustates_column;
+
+static enum { OFF, ON, ERASE } header_status = ON;
+
+static void summary_format(char *, int *, const char * const *);
+static void line_update(char *, char *, int, int);
+
+static int setup_buffer_bufsiz = 0;
+static char * setup_buffer(char *, int);
+
+int x_lastpid = 10;
+int y_lastpid = 0;
+int x_loadave = 33;
+int x_loadave_nompid = 15;
+int y_loadave = 0;
+int x_procstate = 0;
+int y_procstate = 1;
+int x_brkdn = 15;
+int y_brkdn = 1;
+int x_mem = 5;
+int y_mem = 3;
+int x_arc = 5;
+int y_arc = 4;
+int x_carc = 5;
+int y_carc = 5;
+int x_swap = 6;
+int y_swap = 4;
+int y_message = 5;
+int x_header = 0;
+int y_header = 6;
+int x_idlecursor = 0;
+int y_idlecursor = 5;
+int y_procs = 7;
+
+int y_cpustates = 2;
+int Header_lines = 7;
+
+int
+display_resize(void)
+{
+ int lines;
+
+ /* first, deallocate any previous buffer that may have been there */
+ if (screenbuf != NULL)
+ {
+ free(screenbuf);
+ }
+
+ /* calculate the current dimensions */
+ /* if operating in "dumb" mode, we only need one line */
+ lines = smart_terminal ? screen_length - Header_lines : 1;
+
+ if (lines < 0)
+ lines = 0;
+
+ /* now, allocate space for the screen buffer */
+ screenbuf = calloc(lines, screen_width);
+ if (screenbuf == NULL)
+ {
+ /* oops! */
+ return(-1);
+ }
+
+ /* return number of lines available */
+ /* for dumb terminals, pretend like we can show any amount */
+ return(smart_terminal ? lines : Largest);
+}
+
+int
+display_updatecpus(struct statics *statics)
+{
+ int lines;
+ int i;
+
+ /* call resize to do the dirty work */
+ lines = display_resize();
+ if (pcpu_stats)
+ num_cpus = statics->ncpus;
+ else
+ num_cpus = 1;
+ cpustates_column = 5; /* CPU: */
+ if (num_cpus > 1) {
+ cpustates_column += 1 + digits(num_cpus); /* CPU #: */
+ }
+
+ /* fill the "last" array with all -1s, to insure correct updating */
+ for (i = 0; i < num_cpustates * num_cpus; ++i) {
+ lcpustates[i] = -1;
+ }
+
+ return(lines);
+}
+
+int
+display_init(struct statics * statics)
+{
+ int lines;
+ const char * const *pp;
+ int *ip;
+ int i;
+
+ lines = display_updatecpus(statics);
+
+ /* only do the rest if we need to */
+ if (lines > -1)
+ {
+ /* save pointers and allocate space for names */
+ procstate_names = statics->procstate_names;
+ num_procstates = 8;
+ assert(num_procstates > 0);
+ lprocstates = calloc(num_procstates, sizeof(int));
+
+ cpustate_names = statics->cpustate_names;
+
+ swap_names = statics->swap_names;
+ num_swap = 7;
+ assert(num_swap > 0);
+ lswap = calloc(num_swap, sizeof(int));
+ num_cpustates = CPUSTATES;
+ assert(num_cpustates > 0);
+ lcpustates = calloc(num_cpustates * sizeof(int), statics->ncpus);
+ cpustate_columns = calloc(num_cpustates, sizeof(int));
+
+ memory_names = statics->memory_names;
+ num_memory = 7;
+ assert(num_memory > 0);
+ lmemory = calloc(num_memory, sizeof(int));
+
+ arc_names = statics->arc_names;
+ carc_names = statics->carc_names;
+
+ /* calculate starting columns where needed */
+ cpustate_total_length = 0;
+ pp = cpustate_names;
+ ip = cpustate_columns;
+ while (*pp != NULL)
+ {
+ *ip++ = cpustate_total_length;
+ if ((i = strlen(*pp++)) > 0)
+ {
+ cpustate_total_length += i + 8;
+ }
+ }
+ }
+
+ /* return number of lines available */
+ return(lines);
+}
+
+void
+i_loadave(int mpid, double avenrun[])
+{
+ int i;
+
+ /* i_loadave also clears the screen, since it is first */
+ top_clear();
+
+ /* mpid == -1 implies this system doesn't have an _mpid */
+ if (mpid != -1)
+ {
+ printf("last pid: %5d; ", mpid);
+ }
+
+ printf("load averages");
+
+ for (i = 0; i < 3; i++)
+ {
+ printf("%c %7.2f",
+ i == 0 ? ':' : ',',
+ avenrun[i]);
+ }
+ lmpid = mpid;
+}
+
+void
+u_loadave(int mpid, double *avenrun)
+{
+ int i;
+
+ if (mpid != -1)
+ {
+ /* change screen only when value has really changed */
+ if (mpid != lmpid)
+ {
+ Move_to(x_lastpid, y_lastpid);
+ printf("%5d", mpid);
+ lmpid = mpid;
+ }
+
+ /* i remembers x coordinate to move to */
+ i = x_loadave;
+ }
+ else
+ {
+ i = x_loadave_nompid;
+ }
+
+ /* move into position for load averages */
+ Move_to(i, y_loadave);
+
+ /* display new load averages */
+ /* we should optimize this and only display changes */
+ for (i = 0; i < 3; i++)
+ {
+ printf("%s%7.2f",
+ i == 0 ? "" : ", ",
+ avenrun[i]);
+ }
+}
+
+void
+i_timeofday(time_t *tod)
+{
+ /*
+ * Display the current time.
+ * "ctime" always returns a string that looks like this:
+ *
+ * Sun Sep 16 01:03:52 1973
+ * 012345678901234567890123
+ * 1 2
+ *
+ * We want indices 11 thru 18 (length 8).
+ */
+
+ if (smart_terminal)
+ {
+ Move_to(screen_width - 8, 0);
+ }
+ else
+ {
+ fputs(" ", stdout);
+ }
+#ifdef DEBUG
+ {
+ char *foo;
+ foo = ctime(tod);
+ fputs(foo, stdout);
+ }
+#endif
+ printf("%-8.8s\n", &(ctime(tod)[11]));
+ lastline = 1;
+}
+
+static int ltotal = 0;
+static char *procstates_buffer = NULL;
+
+/*
+ * *_procstates(total, brkdn, names) - print the process summary line
+ *
+ * Assumptions: cursor is at the beginning of the line on entry
+ * lastline is valid
+ */
+
+void
+i_procstates(int total, int *brkdn)
+{
+ int i;
+
+ procstates_buffer = setup_buffer(procstates_buffer, 0);
+
+ /* write current number of processes and remember the value */
+ printf("%d %s:", total, ps.thread ? "threads" : "processes");
+ ltotal = total;
+
+ /* put out enough spaces to get to column 15 */
+ i = digits(total);
+ while (i++ < (ps.thread ? 6 : 4))
+ {
+ putchar(' ');
+ }
+
+ /* format and print the process state summary */
+ summary_format(procstates_buffer, brkdn, procstate_names);
+ fputs(procstates_buffer, stdout);
+
+ /* save the numbers for next time */
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+}
+
+void
+u_procstates(int total, int *brkdn)
+{
+ static char *new = NULL;
+ int i;
+
+ new = setup_buffer(new, 0);
+
+ /* update number of processes only if it has changed */
+ if (ltotal != total)
+ {
+ /* move and overwrite */
+ if (x_procstate == 0) {
+ Move_to(x_procstate, y_procstate);
+ }
+ else {
+ /* cursor is already there...no motion needed */
+ assert(lastline == 1);
+ }
+ printf("%d", total);
+
+ /* if number of digits differs, rewrite the label */
+ if (digits(total) != digits(ltotal))
+ {
+ printf(" %s:", ps.thread ? "threads" : "processes");
+ /* put out enough spaces to get to column 15 */
+ i = digits(total);
+ while (i++ < (ps.thread ? 6 : 4))
+ {
+ putchar(' ');
+ }
+ /* cursor may end up right where we want it!!! */
+ }
+
+ /* save new total */
+ ltotal = total;
+ }
+
+ /* see if any of the state numbers has changed */
+ if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
+ {
+ /* format and update the line */
+ summary_format(new, brkdn, procstate_names);
+ line_update(procstates_buffer, new, x_brkdn, y_brkdn);
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+ }
+}
+
+void
+i_cpustates(int *states)
+{
+ int i = 0;
+ int value;
+ const char * const *names;
+ const char *thisname;
+ int *hstates = states;
+ int cpu;
+
+for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ /* print tag and bump lastline */
+ if (num_cpus == 1)
+ printf("\nCPU: ");
+ else {
+ value = printf("\nCPU %d: ", cpu);
+ while (value++ <= cpustates_column)
+ printf(" ");
+ }
+ lastline++;
+
+ /* now walk thru the names and print the line */
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ /* retrieve the value and remember it */
+ value = *states++;
+
+ /* if percentage is >= 1000, print it as 100% */
+ printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
+ (i++ % num_cpustates) == 0 ? "" : ", ",
+ ((float)value)/10.,
+ thisname);
+ }
+ }
+}
+
+ /* copy over values into "last" array */
+ states = hstates;
+ memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
+}
+
+void
+u_cpustates(int *states)
+{
+ int value;
+ const char * const *names;
+ const char *thisname;
+ int *hstates = states;
+ int *lp;
+ int *colp;
+ int cpu;
+
+for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ Move_to(cpustates_column, y_cpustates + cpu);
+ lastline = y_cpustates + cpu;
+ lp = lcpustates + (cpu * num_cpustates);
+ colp = cpustate_columns;
+
+ /* we could be much more optimal about this */
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ /* did the value change since last time? */
+ if (*lp != *states)
+ {
+ /* yes, move and change */
+ Move_to(cpustates_column + *colp, y_cpustates + cpu);
+ lastline = y_cpustates + cpu;
+
+ /* retrieve value and remember it */
+ value = *states;
+
+ /* if percentage is >= 1000, print it as 100% */
+ printf((value >= 1000 ? "%4.0f" : "%4.1f"),
+ ((double)value)/10.);
+
+ /* remember it for next time */
+ *lp = value;
+ }
+ }
+
+ /* increment and move on */
+ lp++;
+ states++;
+ colp++;
+ }
+}
+
+ states = hstates;
+}
+
+void
+z_cpustates(void)
+{
+ int i = 0;
+ const char * const *names;
+ const char *thisname;
+ int cpu, value;
+
+ for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ /* show tag and bump lastline */
+ if (num_cpus == 1)
+ printf("\nCPU: ");
+ else {
+ value = printf("\nCPU %d: ", cpu);
+ while (value++ <= cpustates_column)
+ printf(" ");
+ }
+ lastline++;
+
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
+ }
+ }
+ }
+
+ /* fill the "last" array with all -1s, to insure correct updating */
+ for (i = 0; i < num_cpustates * num_cpus; ++i) {
+ lcpustates[i] = -1;
+ }
+}
+
+/*
+ * *_memory(stats) - print "Memory: " followed by the memory summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_memory ONLY: cursor is on the previous line
+ */
+
+static char *memory_buffer = NULL;
+
+void
+i_memory(int *stats)
+{
+ memory_buffer = setup_buffer(memory_buffer, 0);
+
+ fputs("\nMem: ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(memory_buffer, stats, memory_names);
+ fputs(memory_buffer, stdout);
+}
+
+void
+u_memory(int *stats)
+{
+ static char *new = NULL;
+
+ new = setup_buffer(new, 0);
+
+ /* format the new line */
+ summary_format(new, stats, memory_names);
+ line_update(memory_buffer, new, x_mem, y_mem);
+}
+
+/*
+ * *_arc(stats) - print "ARC: " followed by the ARC summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_arc ONLY: cursor is on the previous line
+ */
+static char *arc_buffer = NULL;
+
+void
+i_arc(int *stats)
+{
+ arc_buffer = setup_buffer(arc_buffer, 0);
+
+ if (arc_names == NULL)
+ return;
+
+ fputs("\nARC: ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(arc_buffer, stats, arc_names);
+ fputs(arc_buffer, stdout);
+}
+
+void
+u_arc(int *stats)
+{
+ static char *new = NULL;
+
+ new = setup_buffer(new, 0);
+
+ if (arc_names == NULL)
+ return;
+
+ /* format the new line */
+ summary_format(new, stats, arc_names);
+ line_update(arc_buffer, new, x_arc, y_arc);
+}
+
+
+/*
+ * *_carc(stats) - print "Compressed ARC: " followed by the summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_carc ONLY: cursor is on the previous line
+ */
+static char *carc_buffer = NULL;
+
+void
+i_carc(int *stats)
+{
+ carc_buffer = setup_buffer(carc_buffer, 0);
+
+ if (carc_names == NULL)
+ return;
+
+ fputs("\n ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(carc_buffer, stats, carc_names);
+ fputs(carc_buffer, stdout);
+}
+
+void
+u_carc(int *stats)
+{
+ static char *new = NULL;
+
+ new = setup_buffer(new, 0);
+
+ if (carc_names == NULL)
+ return;
+
+ /* format the new line */
+ summary_format(new, stats, carc_names);
+ line_update(carc_buffer, new, x_carc, y_carc);
+}
+
+/*
+ * *_swap(stats) - print "Swap: " followed by the swap summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_swap ONLY: cursor is on the previous line
+ */
+
+static char *swap_buffer = NULL;
+
+void
+i_swap(int *stats)
+{
+ swap_buffer = setup_buffer(swap_buffer, 0);
+
+ if (swap_names == NULL)
+ return;
+
+ fputs("\nSwap: ", stdout);
+ lastline++;
+
+ /* format and print the swap summary */
+ summary_format(swap_buffer, stats, swap_names);
+ fputs(swap_buffer, stdout);
+}
+
+void
+u_swap(int *stats)
+{
+ static char *new = NULL;
+
+ new = setup_buffer(new, 0);
+
+ if (swap_names == NULL)
+ return;
+
+ /* format the new line */
+ summary_format(new, stats, swap_names);
+ line_update(swap_buffer, new, x_swap, y_swap);
+}
+
+/*
+ * *_message() - print the next pending message line, or erase the one
+ * that is there.
+ *
+ * Note that u_message is (currently) the same as i_message.
+ *
+ * Assumptions: lastline is consistent
+ */
+
+/*
+ * i_message is funny because it gets its message asynchronously (with
+ * respect to screen updates).
+ */
+
+#define NEXT_MSG_ADDLEN 5
+static char *next_msg = NULL;
+static int msglen = 0;
+/* Invariant: msglen is always the length of the message currently displayed
+ on the screen (even when next_msg doesn't contain that message). */
+
+void
+i_message(void)
+{
+ next_msg = setup_buffer(next_msg, NEXT_MSG_ADDLEN);
+
+ while (lastline < y_message)
+ {
+ fputc('\n', stdout);
+ lastline++;
+ }
+ if (next_msg[0] != '\0')
+ {
+ top_standout(next_msg);
+ msglen = strlen(next_msg);
+ next_msg[0] = '\0';
+ }
+ else if (msglen > 0)
+ {
+ (void) clear_eol(msglen);
+ msglen = 0;
+ }
+}
+
+void
+u_message(void)
+{
+ i_message();
+}
+
+static int header_length;
+
+/*
+ * Trim a header string to the current display width and return a newly
+ * allocated area with the trimmed header.
+ */
+
+char *
+trim_header(const char *text)
+{
+ char *s;
+ int width;
+
+ s = NULL;
+ width = screen_width;
+ header_length = strlen(text);
+ if (header_length >= width) {
+ s = strndup(text, width);
+ if (s == NULL)
+ return (NULL);
+ }
+ return (s);
+}
+
+/*
+ * *_header(text) - print the header for the process area
+ *
+ * Assumptions: cursor is on the previous line and lastline is consistent
+ */
+
+void
+i_header(const char *text)
+{
+ char *s;
+
+ s = trim_header(text);
+ if (s != NULL)
+ text = s;
+
+ if (header_status == ON)
+ {
+ putchar('\n');
+ fputs(text, stdout);
+ lastline++;
+ }
+ else if (header_status == ERASE)
+ {
+ header_status = OFF;
+ }
+ free(s);
+}
+
+void
+u_header(const char *text __unused)
+{
+
+ if (header_status == ERASE)
+ {
+ putchar('\n');
+ lastline++;
+ clear_eol(header_length);
+ header_status = OFF;
+ }
+}
+
+/*
+ * *_process(line, thisline) - print one process line
+ *
+ * Assumptions: lastline is consistent
+ */
+
+void
+i_process(int line, char *thisline)
+{
+ char *p;
+ char *base;
+
+ /* make sure we are on the correct line */
+ while (lastline < y_procs + line)
+ {
+ putchar('\n');
+ lastline++;
+ }
+
+ /* truncate the line to conform to our current screen width */
+ int len = strlen(thisline);
+ if (screen_width < len)
+ {
+ thisline[screen_width] = '\0';
+ }
+
+ /* write the line out */
+ fputs(thisline, stdout);
+
+ /* copy it in to our buffer */
+ base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
+ p = stpcpy(base, thisline);
+
+ /* zero fill the rest of it */
+ if (p - base < screen_width)
+ {
+ memset(p, 0, screen_width - (p - base));
+ }
+}
+
+void
+u_process(int line, char *newline)
+{
+ char *optr;
+ int screen_line = line + Header_lines;
+ char *bufferline;
+
+ /* remember a pointer to the current line in the screen buffer */
+ bufferline = &screenbuf[lineindex(line)];
+
+ /* truncate the line to conform to our current screen width */
+ int len = strlen(newline);
+ if (screen_width < len)
+ {
+ newline[screen_width] = '\0';
+ }
+
+ /* is line higher than we went on the last display? */
+ if (line >= last_hi)
+ {
+ /* yes, just ignore screenbuf and write it out directly */
+ /* get positioned on the correct line */
+ if (screen_line - lastline == 1)
+ {
+ putchar('\n');
+ lastline++;
+ }
+ else
+ {
+ Move_to(0, screen_line);
+ lastline = screen_line;
+ }
+
+ /* now write the line */
+ fputs(newline, stdout);
+
+ /* copy it in to the buffer */
+ optr = stpcpy(bufferline, newline);
+
+ /* zero fill the rest of it */
+ if (optr - bufferline < screen_width)
+ {
+ memset(optr, 0, screen_width - (optr - bufferline));
+ }
+ }
+ else
+ {
+ line_update(bufferline, newline, 0, line + Header_lines);
+ }
+}
+
+void
+u_endscreen(int hi)
+{
+ int screen_line = hi + Header_lines;
+ int i;
+
+ if (smart_terminal)
+ {
+ if (hi < last_hi)
+ {
+ /* need to blank the remainder of the screen */
+ /* but only if there is any screen left below this line */
+ if (lastline + 1 < screen_length)
+ {
+ /* efficiently move to the end of currently displayed info */
+ if (screen_line - lastline < 5)
+ {
+ while (lastline < screen_line)
+ {
+ putchar('\n');
+ lastline++;
+ }
+ }
+ else
+ {
+ Move_to(0, screen_line);
+ lastline = screen_line;
+ }
+
+ if (clear_to_end)
+ {
+ /* we can do this the easy way */
+ putcap(clear_to_end);
+ }
+ else
+ {
+ /* use clear_eol on each line */
+ i = hi;
+ while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
+ {
+ putchar('\n');
+ }
+ }
+ }
+ }
+ last_hi = hi;
+
+ /* move the cursor to a pleasant place */
+ Move_to(x_idlecursor, y_idlecursor);
+ lastline = y_idlecursor;
+ }
+ else
+ {
+ /* separate this display from the next with some vertical room */
+ fputs("\n\n", stdout);
+ }
+}
+
+void
+display_header(int t)
+{
+
+ if (t)
+ {
+ header_status = ON;
+ }
+ else if (header_status == ON)
+ {
+ header_status = ERASE;
+ }
+}
+
+void
+new_message(int type, const char *msgfmt, ...)
+{
+ va_list args;
+ size_t i;
+
+ va_start(args, msgfmt);
+
+ /* first, format the message */
+ vsnprintf(next_msg, setup_buffer_bufsiz + NEXT_MSG_ADDLEN,
+ msgfmt, args);
+
+ va_end(args);
+
+ if (msglen > 0)
+ {
+ /* message there already -- can we clear it? */
+ if (!overstrike)
+ {
+ /* yes -- write it and clear to end */
+ i = strlen(next_msg);
+ if ((type & MT_delayed) == 0)
+ {
+ if (type & MT_standout) {
+ top_standout(next_msg);
+ } else {
+ fputs(next_msg, stdout);
+ }
+ clear_eol(msglen - i);
+ msglen = i;
+ next_msg[0] = '\0';
+ }
+ }
+ }
+ else
+ {
+ if ((type & MT_delayed) == 0)
+ {
+ if (type & MT_standout) {
+ top_standout(next_msg);
+ } else {
+ fputs(next_msg, stdout);
+ }
+ msglen = strlen(next_msg);
+ next_msg[0] = '\0';
+ }
+ }
+}
+
+void
+clear_message(void)
+{
+ if (clear_eol(msglen) == 1)
+ {
+ putchar('\r');
+ }
+}
+
+int
+readline(char *buffer, int size, int numeric)
+{
+ char *ptr = buffer;
+ char ch;
+ char cnt = 0;
+ char maxcnt = 0;
+
+ /* allow room for null terminator */
+ size -= 1;
+
+ /* read loop */
+ while ((fflush(stdout), read(0, ptr, 1) > 0))
+ {
+ /* newline means we are done */
+ if ((ch = *ptr) == '\n' || ch == '\r')
+ {
+ break;
+ }
+
+ /* handle special editing characters */
+ if (ch == ch_kill)
+ {
+ /* kill line -- account for overstriking */
+ if (overstrike)
+ {
+ msglen += maxcnt;
+ }
+
+ /* return null string */
+ *buffer = '\0';
+ putchar('\r');
+ return(-1);
+ }
+ else if (ch == ch_erase)
+ {
+ /* erase previous character */
+ if (cnt <= 0)
+ {
+ /* none to erase! */
+ putchar('\7');
+ }
+ else
+ {
+ fputs("\b \b", stdout);
+ ptr--;
+ cnt--;
+ }
+ }
+ /* check for character validity and buffer overflow */
+ else if (cnt == size || (numeric && !isdigit(ch)) ||
+ !isprint(ch))
+ {
+ /* not legal */
+ putchar('\7');
+ }
+ else
+ {
+ /* echo it and store it in the buffer */
+ putchar(ch);
+ ptr++;
+ cnt++;
+ if (cnt > maxcnt)
+ {
+ maxcnt = cnt;
+ }
+ }
+ }
+
+ /* all done -- null terminate the string */
+ *ptr = '\0';
+
+ /* account for the extra characters in the message area */
+ /* (if terminal overstrikes, remember the furthest they went) */
+ msglen += overstrike ? maxcnt : cnt;
+
+ /* return either inputted number or string length */
+ putchar('\r');
+ return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
+}
+
+/* internal support routines */
+
+static void
+summary_format(char *str, int *numbers, const char * const *names)
+{
+ char *p;
+ int num;
+ const char *thisname;
+ char rbuf[6];
+
+ /* format each number followed by its string */
+ p = str;
+ while ((thisname = *names++) != NULL)
+ {
+ /* get the number to format */
+ num = *numbers++;
+
+ /* display only non-zero numbers */
+ if (num > 0)
+ {
+ /* is this number in kilobytes? */
+ if (thisname[0] == 'K')
+ {
+ /* yes: format it as a memory value */
+ p = stpcpy(p, format_k(num));
+
+ /* skip over the K, since it was included by format_k */
+ p = stpcpy(p, thisname+1);
+ }
+ /* is this number a ratio? */
+ else if (thisname[0] == ':')
+ {
+ (void) snprintf(rbuf, sizeof(rbuf), "%.2f",
+ (float)*(numbers - 2) / (float)num);
+ p = stpcpy(p, rbuf);
+ p = stpcpy(p, thisname);
+ }
+ else
+ {
+ p = stpcpy(p, itoa(num));
+ p = stpcpy(p, thisname);
+ }
+ }
+
+ /* ignore negative numbers, but display corresponding string */
+ else if (num < 0)
+ {
+ p = stpcpy(p, thisname);
+ }
+ }
+
+ /* if the last two characters in the string are ", ", delete them */
+ p -= 2;
+ if (p >= str && p[0] == ',' && p[1] == ' ')
+ {
+ *p = '\0';
+ }
+}
+
+static void
+line_update(char *old, char *new, int start, int line)
+{
+ int ch;
+ int diff;
+ int newcol = start + 1;
+ int lastcol = start;
+ char cursor_on_line = false;
+ char *current;
+
+ /* compare the two strings and only rewrite what has changed */
+ current = old;
+#ifdef DEBUG
+ fprintf(debug, "line_update, starting at %d\n", start);
+ fputs(old, debug);
+ fputc('\n', debug);
+ fputs(new, debug);
+ fputs("\n-\n", debug);
+#endif
+
+ /* start things off on the right foot */
+ /* this is to make sure the invariants get set up right */
+ if ((ch = *new++) != *old)
+ {
+ if (line - lastline == 1 && start == 0)
+ {
+ putchar('\n');
+ }
+ else
+ {
+ Move_to(start, line);
+ }
+ cursor_on_line = true;
+ putchar(ch);
+ *old = ch;
+ lastcol = start + 1;
+ }
+ old++;
+
+ /*
+ * main loop -- check each character. If the old and new aren't the
+ * same, then update the display. When the distance from the
+ * current cursor position to the new change is small enough,
+ * the characters that belong there are written to move the
+ * cursor over.
+ *
+ * Invariants:
+ * lastcol is the column where the cursor currently is sitting
+ * (always one beyond the end of the last mismatch).
+ */
+ do /* yes, a do...while */
+ {
+ if ((ch = *new++) != *old)
+ {
+ /* new character is different from old */
+ /* make sure the cursor is on top of this character */
+ diff = newcol - lastcol;
+ if (diff > 0)
+ {
+ /* some motion is required--figure out which is shorter */
+ if (diff < 6 && cursor_on_line)
+ {
+ /* overwrite old stuff--get it out of the old buffer */
+ printf("%.*s", diff, &current[lastcol-start]);
+ }
+ else
+ {
+ /* use cursor addressing */
+ Move_to(newcol, line);
+ cursor_on_line = true;
+ }
+ /* remember where the cursor is */
+ lastcol = newcol + 1;
+ }
+ else
+ {
+ /* already there, update position */
+ lastcol++;
+ }
+
+ /* write what we need to */
+ if (ch == '\0')
+ {
+ /* at the end--terminate with a clear-to-end-of-line */
+ (void) clear_eol(strlen(old));
+ }
+ else
+ {
+ /* write the new character */
+ putchar(ch);
+ }
+ /* put the new character in the screen buffer */
+ *old = ch;
+ }
+
+ /* update working column and screen buffer pointer */
+ newcol++;
+ old++;
+
+ } while (ch != '\0');
+
+ /* zero out the rest of the line buffer -- MUST BE DONE! */
+ diff = screen_width - newcol;
+ if (diff > 0)
+ {
+ memset(old, 0, diff);
+ }
+
+ /* remember where the current line is */
+ if (cursor_on_line)
+ {
+ lastline = line;
+ }
+}
+
+void
+i_uptime(struct timeval *bt, time_t *tod)
+{
+ time_t uptime;
+ int days, hrs, mins, secs;
+
+ if (bt->tv_sec != -1) {
+ uptime = *tod - bt->tv_sec;
+ days = uptime / 86400;
+ uptime %= 86400;
+ hrs = uptime / 3600;
+ uptime %= 3600;
+ mins = uptime / 60;
+ secs = uptime % 60;
+
+ /*
+ * Display the uptime.
+ */
+
+ if (smart_terminal)
+ {
+ Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0);
+ }
+ else
+ {
+ fputs(" ", stdout);
+ }
+ printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs);
+ }
+}
+
+void
+i_battery(int nbat, int batt)
+{
+
+ if (nbat > 0) {
+ printf("; battery: %d%%", batt);
+ }
+}
+
+#define SETUPBUFFER_MIN_SCREENWIDTH 80
+#define SETUPBUFFER_REQUIRED_ADDBUFSIZ 2
+
+static char *
+setup_buffer(char *buffer, int addlen)
+{
+ size_t len, old_len;
+ char *new_buffer;
+
+ setup_buffer_bufsiz = screen_width;
+ if (setup_buffer_bufsiz < SETUPBUFFER_MIN_SCREENWIDTH)
+ {
+ setup_buffer_bufsiz = SETUPBUFFER_MIN_SCREENWIDTH;
+ }
+
+ len = setup_buffer_bufsiz + addlen + SETUPBUFFER_REQUIRED_ADDBUFSIZ;
+ new_buffer = calloc(len, sizeof(char));
+ if (new_buffer == NULL)
+ {
+ errx(4, "can't allocate sufficient memory");
+ }
+ if (buffer != NULL)
+ {
+ old_len = strlen(buffer);
+ memcpy(new_buffer, buffer, old_len < len - 1 ? old_len : len - 1);
+ free(buffer);
+ }
+
+ return new_buffer;
+}
diff --git a/usr.bin/top/display.h b/usr.bin/top/display.h
new file mode 100644
index 000000000000..6e930f5ae6eb
--- /dev/null
+++ b/usr.bin/top/display.h
@@ -0,0 +1,41 @@
+/* constants needed for display.c */
+
+#define MT_standout 1
+#define MT_delayed 2
+
+#include <sys/time.h>
+struct statics;
+
+int display_updatecpus(struct statics *statics);
+void clear_message(void);
+int display_resize(void);
+void i_header(const char *text);
+void display_header(int t);
+int display_init(struct statics *statics);
+void i_arc(int *stats);
+void i_battery(int nbat, int batt);
+void i_carc(int *stats);
+void i_cpustates(int *states);
+void i_loadave(int mpid, double *avenrun);
+void i_memory(int *stats);
+void i_message(void);
+void i_process(int line, char *thisline);
+void i_procstates(int total, int *brkdn);
+void i_swap(int *stats);
+void i_timeofday(time_t *tod);
+void i_uptime(struct timeval *bt, time_t *tod);
+void new_message(int type, const char *msgfmt, ...);
+int readline(char *buffer, int size, int numeric);
+char *trim_header(const char *text);
+void u_arc(int *stats);
+void u_carc(int *stats);
+void u_cpustates(int *states);
+void u_endscreen(int hi);
+void u_header(const char *text);
+void u_loadave(int mpid, double *avenrun);
+void u_memory(int *stats);
+void u_message(void);
+void u_process(int line, char *newline);
+void u_procstates(int total, int *brkdn);
+void u_swap(int *stats);
+void z_cpustates(void);
diff --git a/usr.bin/top/layout.h b/usr.bin/top/layout.h
new file mode 100644
index 000000000000..0d4f0161ba9b
--- /dev/null
+++ b/usr.bin/top/layout.h
@@ -0,0 +1,33 @@
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * This file defines the locations on tne screen for various parts of the
+ * display. These definitions are used by the routines in "display.c" for
+ * cursor addressing.
+ */
+
+extern int x_lastpid; /* 10 */
+extern int y_lastpid; /* 0 */
+extern int x_loadave; /* 33 */
+extern int x_loadave_nompid; /* 15 */
+extern int y_loadave; /* 0 */
+extern int x_procstate; /* 0 */
+extern int y_procstate; /* 1 */
+extern int x_brkdn; /* 15 */
+extern int y_brkdn; /* 1 */
+extern int x_mem; /* 5 */
+extern int y_mem; /* 3 */
+extern int x_arc; /* 5 */
+extern int y_arc; /* 4 */
+extern int x_carc; /* 5 */
+extern int y_carc; /* 5 */
+extern int x_swap; /* 6 */
+extern int y_swap; /* 4 */
+extern int y_message; /* 5 */
+extern int x_header; /* 0 */
+extern int y_header; /* 6 */
+extern int x_idlecursor; /* 0 */
+extern int y_idlecursor; /* 5 */
+extern int y_procs; /* 7 */
+
+extern int y_cpustates; /* 2 */
diff --git a/usr.bin/top/loadavg.h b/usr.bin/top/loadavg.h
new file mode 100644
index 000000000000..17171e426b9e
--- /dev/null
+++ b/usr.bin/top/loadavg.h
@@ -0,0 +1,25 @@
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * Defines required to access load average figures.
+ *
+ * This include file sets up everything we need to access the load average
+ * values in the kernel in a machine independent way. First, it sets the
+ * typedef "load_avg" to be either double or long (depending on what is
+ * needed), then it defines these macros appropriately:
+ *
+ * loaddouble(la) - convert load_avg to double.
+ * intload(i) - convert integer to load_avg.
+ */
+
+#ifndef LOADAVG_H
+#define LOADAVG_H
+
+#include <sys/param.h>
+
+typedef long pctcpu;
+#define pctdouble(p) ((double)(p) / FSCALE)
+
+typedef fixpt_t load_avg;
+#define loaddouble(la) ((double)(la) / FSCALE)
+#endif /* LOADAVG_H */
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
new file mode 100644
index 000000000000..a76d77a80ce4
--- /dev/null
+++ b/usr.bin/top/machine.c
@@ -0,0 +1,1616 @@
+/*
+ * top - a top users display for Unix
+ *
+ * DESCRIPTION:
+ * Originally written for BSD4.4 system by Christos Zoulas.
+ * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
+ * Order support hacked in from top-3.5beta6/machine/m_aix41.c
+ * by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/)
+ *
+ * AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
+ * Steven Wallace <swallace@FreeBSD.org>
+ * Wolfram Schneider <wosch@FreeBSD.org>
+ * Thomas Moestl <tmoestl@gmx.net>
+ * Eitan Adler <eadler@FreeBSD.org>
+ */
+
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/priority.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/user.h>
+
+#include <assert.h>
+#include <err.h>
+#include <libgen.h>
+#include <kvm.h>
+#include <math.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <vis.h>
+
+#include "top.h"
+#include "display.h"
+#include "machine.h"
+#include "loadavg.h"
+#include "screen.h"
+#include "utils.h"
+#include "layout.h"
+
+#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
+
+extern struct timeval timeout;
+static int smpmode;
+enum displaymodes displaymode;
+static const int namelength = 10;
+/* TOP_JID_LEN based on max of 999999 */
+#define TOP_JID_LEN 6
+#define TOP_SWAP_LEN 5
+
+/* get_process_info passes back a handle. This is what it looks like: */
+
+struct handle {
+ struct kinfo_proc **next_proc; /* points to next valid proc pointer */
+ int remaining; /* number of pointers remaining */
+};
+
+
+/* define what weighted cpu is. */
+#define weighted_cpu(pct, pp) ((pp)->ki_swtime == 0 ? 0.0 : \
+ ((pct) / (1.0 - exp((pp)->ki_swtime * logcpu))))
+
+/* what we consider to be process size: */
+#define PROCSIZE(pp) ((pp)->ki_size / 1024)
+
+#define RU(pp) (&(pp)->ki_rusage)
+
+#define PCTCPU(pp) (pcpu[pp - pbase])
+
+/* process state names for the "STATE" column of the display */
+/* the extra nulls in the string "run" are for adding a slash and
+ the processor number when needed */
+
+static const char *state_abbrev[] = {
+ "", "START", "RUN\0\0\0", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK"
+};
+
+
+static kvm_t *kd;
+
+/* values that we stash away in _init and use in later routines */
+
+static double logcpu;
+
+/* these are retrieved from the kernel in _init */
+
+static load_avg ccpu;
+
+/* these are used in the get_ functions */
+
+static int lastpid;
+
+/* these are for calculating cpu state percentages */
+
+static long cp_time[CPUSTATES];
+static long cp_old[CPUSTATES];
+static long cp_diff[CPUSTATES];
+
+/* these are for detailing the process states */
+
+static const char *procstatenames[] = {
+ "", " starting, ", " running, ", " sleeping, ", " stopped, ",
+ " zombie, ", " waiting, ", " lock, ",
+ NULL
+};
+static int process_states[nitems(procstatenames)];
+
+/* these are for detailing the cpu states */
+
+static int cpu_states[CPUSTATES];
+static const char *cpustatenames[] = {
+ "user", "nice", "system", "interrupt", "idle", NULL
+};
+
+/* these are for detailing the memory statistics */
+
+static const char *memorynames[] = {
+ "K Active, ", "K Inact, ", "K Laundry, ", "K Wired, ", "K Buf, ",
+ "K Free", NULL
+};
+static int memory_stats[nitems(memorynames)];
+
+static const char *arcnames[] = {
+ "K Total, ", "K MFU, ", "K MRU, ", "K Anon, ", "K Header, ", "K Other",
+ NULL
+};
+static int arc_stats[nitems(arcnames)];
+
+static const char *carcnames[] = {
+ "K Compressed, ", "K Uncompressed, ", ":1 Ratio, ",
+ NULL
+};
+static int carc_stats[nitems(carcnames)];
+
+static const char *swapnames[] = {
+ "K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
+ NULL
+};
+static int swap_stats[nitems(swapnames)];
+
+static int has_swap;
+
+/* these are for keeping track of the proc array */
+
+static int nproc;
+static int onproc = -1;
+static int pref_len;
+static struct kinfo_proc *pbase;
+static struct kinfo_proc **pref;
+static struct kinfo_proc *previous_procs;
+static struct kinfo_proc **previous_pref;
+static int previous_proc_count = 0;
+static int previous_proc_count_max = 0;
+static int previous_thread;
+
+/* data used for recalculating pctcpu */
+static double *pcpu;
+static struct timespec proc_uptime;
+static struct timeval proc_wall_time;
+static struct timeval previous_wall_time;
+static uint64_t previous_interval = 0;
+
+/* total number of io operations */
+static long total_inblock;
+static long total_oublock;
+static long total_majflt;
+
+/* these are for getting the memory statistics */
+
+static int arc_enabled;
+static int carc_enabled;
+static int pageshift; /* log base 2 of the pagesize */
+
+/* define pagetok in terms of pageshift */
+
+#define pagetok(size) ((size) << pageshift)
+
+/* swap usage */
+#define ki_swap(kip) \
+ ((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0)
+
+/*
+ * Sorting orders. The first element is the default.
+ */
+static const char *ordernames[] = {
+ "cpu", "size", "res", "time", "pri", "threads",
+ "total", "read", "write", "fault", "vcsw", "ivcsw",
+ "jid", "swap", "pid", NULL
+};
+
+/* Per-cpu time states */
+static int maxcpu;
+static int maxid;
+static int ncpus;
+static cpuset_t cpumask;
+static long *times;
+static long *pcpu_cp_time;
+static long *pcpu_cp_old;
+static long *pcpu_cp_diff;
+static int *pcpu_cpu_states;
+
+/* Battery units and states */
+static int battery_units;
+static int battery_life;
+
+static int compare_swap(const void *a, const void *b);
+static int compare_jid(const void *a, const void *b);
+static int compare_pid(const void *a, const void *b);
+static int compare_tid(const void *a, const void *b);
+static const char *format_nice(const struct kinfo_proc *pp);
+static void getsysctl(const char *name, void *ptr, size_t len);
+static int swapmode(int *retavail, int *retfree);
+static void update_layout(void);
+static int find_uid(uid_t needle, int *haystack);
+static int cmd_matches(struct kinfo_proc *, const char *);
+
+static int
+find_uid(uid_t needle, int *haystack)
+{
+ size_t i = 0;
+
+ for (; i < TOP_MAX_UIDS; ++i)
+ if ((uid_t)haystack[i] == needle)
+ return 1;
+ return (0);
+}
+
+void
+toggle_pcpustats(void)
+{
+
+ if (ncpus == 1)
+ return;
+ update_layout();
+}
+
+/* Adjust display based on ncpus and the ARC state. */
+static void
+update_layout(void)
+{
+
+ y_mem = 3;
+ y_arc = 4;
+ y_carc = 5;
+ y_swap = 3 + arc_enabled + carc_enabled + has_swap;
+ y_idlecursor = 4 + arc_enabled + carc_enabled + has_swap;
+ y_message = 4 + arc_enabled + carc_enabled + has_swap;
+ y_header = 5 + arc_enabled + carc_enabled + has_swap;
+ y_procs = 6 + arc_enabled + carc_enabled + has_swap;
+ Header_lines = 6 + arc_enabled + carc_enabled + has_swap;
+
+ if (pcpu_stats) {
+ y_mem += ncpus - 1;
+ y_arc += ncpus - 1;
+ y_carc += ncpus - 1;
+ y_swap += ncpus - 1;
+ y_idlecursor += ncpus - 1;
+ y_message += ncpus - 1;
+ y_header += ncpus - 1;
+ y_procs += ncpus - 1;
+ Header_lines += ncpus - 1;
+ }
+}
+
+int
+machine_init(struct statics *statics)
+{
+ int i, j, empty, pagesize;
+ uint64_t arc_size;
+ int carc_en, nswapdev;
+ size_t size;
+
+ size = sizeof(smpmode);
+ if (sysctlbyname("kern.smp.active", &smpmode, &size, NULL, 0) != 0 ||
+ size != sizeof(smpmode))
+ smpmode = 0;
+
+ size = sizeof(arc_size);
+ if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arc_size, &size,
+ NULL, 0) == 0 && arc_size != 0)
+ arc_enabled = 1;
+ size = sizeof(carc_en);
+ if (arc_enabled &&
+ sysctlbyname("vfs.zfs.compressed_arc_enabled", &carc_en, &size,
+ NULL, 0) == 0 && carc_en == 1) {
+ uint64_t uncomp_sz;
+
+ /*
+ * Don't report compression stats if no data is in the ARC.
+ * Otherwise, we end up printing a blank line.
+ */
+ size = sizeof(uncomp_sz);
+ if (sysctlbyname("kstat.zfs.misc.arcstats.uncompressed_size",
+ &uncomp_sz, &size, NULL, 0) == 0 && uncomp_sz != 0)
+ carc_enabled = 1;
+ }
+
+ kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
+ if (kd == NULL)
+ return (-1);
+
+ size = sizeof(nswapdev);
+ if (sysctlbyname("vm.nswapdev", &nswapdev, &size, NULL, 0) == 0 &&
+ nswapdev != 0)
+ has_swap = 1;
+
+ GETSYSCTL("kern.ccpu", ccpu);
+
+ /* this is used in calculating WCPU -- calculate it ahead of time */
+ logcpu = log(loaddouble(ccpu));
+
+ pbase = NULL;
+ pref = NULL;
+ pcpu = NULL;
+ nproc = 0;
+ onproc = -1;
+
+ /* get the page size and calculate pageshift from it */
+ pagesize = getpagesize();
+ pageshift = 0;
+ while (pagesize > 1) {
+ pageshift++;
+ pagesize >>= 1;
+ }
+
+ /* we only need the amount of log(2)1024 for our conversion */
+ pageshift -= LOG1024;
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ if (arc_enabled)
+ statics->arc_names = arcnames;
+ else
+ statics->arc_names = NULL;
+ if (carc_enabled)
+ statics->carc_names = carcnames;
+ else
+ statics->carc_names = NULL;
+ if (has_swap)
+ statics->swap_names = swapnames;
+ else
+ statics->swap_names = NULL;
+ statics->order_names = ordernames;
+
+ /* Allocate state for per-CPU stats. */
+ GETSYSCTL("kern.smp.maxcpus", maxcpu);
+ times = calloc(maxcpu * CPUSTATES, sizeof(long));
+ if (times == NULL)
+ err(1, "calloc for kern.smp.maxcpus");
+ size = sizeof(long) * maxcpu * CPUSTATES;
+ if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1)
+ err(1, "sysctlbyname kern.cp_times");
+ pcpu_cp_time = calloc(1, size);
+ maxid = MIN(size / CPUSTATES / sizeof(long) - 1, CPU_SETSIZE - 1);
+ CPU_ZERO(&cpumask);
+ for (i = 0; i <= maxid; i++) {
+ empty = 1;
+ for (j = 0; empty && j < CPUSTATES; j++) {
+ if (times[i * CPUSTATES + j] != 0)
+ empty = 0;
+ }
+ if (!empty)
+ CPU_SET(i, &cpumask);
+ }
+ ncpus = CPU_COUNT(&cpumask);
+ assert(ncpus > 0);
+ pcpu_cp_old = calloc(ncpus * CPUSTATES, sizeof(long));
+ pcpu_cp_diff = calloc(ncpus * CPUSTATES, sizeof(long));
+ pcpu_cpu_states = calloc(ncpus * CPUSTATES, sizeof(int));
+ statics->ncpus = ncpus;
+
+ /* Allocate state of battery units reported via ACPI. */
+ battery_units = 0;
+ size = sizeof(int);
+ sysctlbyname("hw.acpi.battery.units", &battery_units, &size, NULL, 0);
+ statics->nbatteries = battery_units;
+
+ update_layout();
+
+ /* all done! */
+ return (0);
+}
+
+char *
+format_header(const char *uname_field)
+{
+ static struct sbuf* header = NULL;
+
+ /* clean up from last time. */
+ if (header != NULL) {
+ sbuf_clear(header);
+ } else {
+ header = sbuf_new_auto();
+ }
+
+ switch (displaymode) {
+ case DISP_CPU: {
+ sbuf_printf(header, " %s", ps.thread_id ? " THR" : "PID");
+ sbuf_printf(header, "%*s", ps.jail ? TOP_JID_LEN : 0,
+ ps.jail ? " JID" : "");
+ sbuf_printf(header, " %-*.*s ", namelength, namelength, uname_field);
+ if (!ps.thread) {
+ sbuf_cat(header, "THR ");
+ }
+ sbuf_cat(header, "PRI NICE SIZE RES ");
+ if (ps.swap) {
+ sbuf_printf(header, "%*s ", TOP_SWAP_LEN - 1, "SWAP");
+ }
+ sbuf_cat(header, "STATE ");
+ if (smpmode) {
+ sbuf_cat(header, "C ");
+ }
+ sbuf_cat(header, "TIME ");
+ sbuf_printf(header, " %6s ", ps.wcpu ? "WCPU" : "CPU");
+ sbuf_cat(header, "COMMAND");
+ sbuf_finish(header);
+ break;
+ }
+ case DISP_IO: {
+ sbuf_printf(header, " %s%*s %-*.*s",
+ ps.thread_id ? " THR" : "PID",
+ ps.jail ? TOP_JID_LEN : 0, ps.jail ? " JID" : "",
+ namelength, namelength, uname_field);
+ sbuf_cat(header, " VCSW IVCSW READ WRITE FAULT TOTAL PERCENT COMMAND");
+ sbuf_finish(header);
+ break;
+ }
+ case DISP_MAX:
+ assert("displaymode must not be set to DISP_MAX");
+ }
+
+ return sbuf_data(header);
+}
+
+static int swappgsin = -1;
+static int swappgsout = -1;
+
+
+void
+get_system_info(struct system_info *si)
+{
+ struct loadavg sysload;
+ int mib[2];
+ struct timeval boottime;
+ uint64_t arc_stat, arc_stat2;
+ int i, j;
+ size_t size;
+
+ /* get the CPU stats */
+ size = (maxid + 1) * CPUSTATES * sizeof(long);
+ if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1)
+ err(1, "sysctlbyname kern.cp_times");
+ GETSYSCTL("kern.cp_time", cp_time);
+ GETSYSCTL("vm.loadavg", sysload);
+ GETSYSCTL("kern.lastpid", lastpid);
+
+ /* convert load averages to doubles */
+ for (i = 0; i < 3; i++)
+ si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
+
+ /* convert cp_time counts to percentages */
+ for (i = j = 0; i <= maxid; i++) {
+ if (!CPU_ISSET(i, &cpumask))
+ continue;
+ percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES],
+ &pcpu_cp_time[j * CPUSTATES],
+ &pcpu_cp_old[j * CPUSTATES],
+ &pcpu_cp_diff[j * CPUSTATES]);
+ j++;
+ }
+ percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+
+ /* sum memory & swap statistics */
+ {
+ static unsigned int swap_delay = 0;
+ static int swapavail = 0;
+ static int swapfree = 0;
+ static long bufspace = 0;
+ static uint64_t nspgsin, nspgsout;
+
+ GETSYSCTL("vfs.bufspace", bufspace);
+ GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]);
+ GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]);
+ GETSYSCTL("vm.stats.vm.v_laundry_count", memory_stats[2]);
+ GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[3]);
+ GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]);
+ GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin);
+ GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout);
+ /* convert memory stats to Kbytes */
+ memory_stats[0] = pagetok(memory_stats[0]);
+ memory_stats[1] = pagetok(memory_stats[1]);
+ memory_stats[2] = pagetok(memory_stats[2]);
+ memory_stats[3] = pagetok(memory_stats[3]);
+ memory_stats[4] = bufspace / 1024;
+ memory_stats[5] = pagetok(memory_stats[5]);
+ memory_stats[6] = -1;
+
+ /* first interval */
+ if (swappgsin < 0) {
+ swap_stats[4] = 0;
+ swap_stats[5] = 0;
+ }
+
+ /* compute differences between old and new swap statistic */
+ else {
+ swap_stats[4] = pagetok(((nspgsin - swappgsin)));
+ swap_stats[5] = pagetok(((nspgsout - swappgsout)));
+ }
+
+ swappgsin = nspgsin;
+ swappgsout = nspgsout;
+
+ /* call CPU heavy swapmode() only for changes */
+ if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
+ swap_stats[3] = swapmode(&swapavail, &swapfree);
+ swap_stats[0] = swapavail;
+ swap_stats[1] = swapavail - swapfree;
+ swap_stats[2] = swapfree;
+ }
+ swap_delay = 1;
+ swap_stats[6] = -1;
+ }
+
+ if (arc_enabled) {
+ GETSYSCTL("kstat.zfs.misc.arcstats.size", arc_stat);
+ arc_stats[0] = arc_stat >> 10;
+ GETSYSCTL("vfs.zfs.mfu_size", arc_stat);
+ arc_stats[1] = arc_stat >> 10;
+ GETSYSCTL("vfs.zfs.mru_size", arc_stat);
+ arc_stats[2] = arc_stat >> 10;
+ GETSYSCTL("vfs.zfs.anon_size", arc_stat);
+ arc_stats[3] = arc_stat >> 10;
+ GETSYSCTL("kstat.zfs.misc.arcstats.hdr_size", arc_stat);
+ GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc_stat2);
+ arc_stats[4] = (arc_stat + arc_stat2) >> 10;
+ GETSYSCTL("kstat.zfs.misc.arcstats.bonus_size", arc_stat);
+ arc_stats[5] = arc_stat >> 10;
+ GETSYSCTL("kstat.zfs.misc.arcstats.dnode_size", arc_stat);
+ arc_stats[5] += arc_stat >> 10;
+ GETSYSCTL("kstat.zfs.misc.arcstats.dbuf_size", arc_stat);
+ arc_stats[5] += arc_stat >> 10;
+ si->arc = arc_stats;
+ }
+ if (carc_enabled) {
+ GETSYSCTL("kstat.zfs.misc.arcstats.compressed_size", arc_stat);
+ carc_stats[0] = arc_stat >> 10;
+ carc_stats[2] = arc_stat >> 10; /* For ratio */
+ GETSYSCTL("kstat.zfs.misc.arcstats.uncompressed_size", arc_stat);
+ carc_stats[1] = arc_stat >> 10;
+ si->carc = carc_stats;
+ }
+
+ /* set arrays and strings */
+ if (pcpu_stats) {
+ si->cpustates = pcpu_cpu_states;
+ si->ncpus = ncpus;
+ } else {
+ si->cpustates = cpu_states;
+ si->ncpus = 1;
+ }
+ si->memory = memory_stats;
+ si->swap = swap_stats;
+
+
+ if (lastpid > 0) {
+ si->last_pid = lastpid;
+ } else {
+ si->last_pid = -1;
+ }
+
+ /*
+ * Print how long system has been up.
+ * (Found by looking getting "boottime" from the kernel)
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ size = sizeof(boottime);
+ if (sysctl(mib, nitems(mib), &boottime, &size, NULL, 0) != -1 &&
+ boottime.tv_sec != 0) {
+ si->boottime = boottime;
+ } else {
+ si->boottime.tv_sec = -1;
+ }
+
+ battery_life = 0;
+ if (battery_units > 0) {
+ GETSYSCTL("hw.acpi.battery.life", battery_life);
+ }
+ si->battery = battery_life;
+}
+
+#define NOPROC ((void *)-1)
+
+/*
+ * We need to compare data from the old process entry with the new
+ * process entry.
+ * To facilitate doing this quickly we stash a pointer in the kinfo_proc
+ * structure to cache the mapping. We also use a negative cache pointer
+ * of NOPROC to avoid duplicate lookups.
+ * XXX: this could be done when the actual processes are fetched, we do
+ * it here out of laziness.
+ */
+static const struct kinfo_proc *
+get_old_proc(struct kinfo_proc *pp)
+{
+ const struct kinfo_proc * const *oldpp, *oldp;
+
+ /*
+ * If this is the first fetch of the kinfo_procs then we don't have
+ * any previous entries.
+ */
+ if (previous_proc_count == 0)
+ return (NULL);
+ /* negative cache? */
+ if (pp->ki_udata == NOPROC)
+ return (NULL);
+ /* cached? */
+ if (pp->ki_udata != NULL)
+ return (pp->ki_udata);
+ /*
+ * Not cached,
+ * 1) look up based on pid.
+ * 2) compare process start.
+ * If we fail here, then setup a negative cache entry, otherwise
+ * cache it.
+ */
+ oldpp = bsearch(&pp, previous_pref, previous_proc_count,
+ sizeof(*previous_pref), ps.thread ? compare_tid : compare_pid);
+ if (oldpp == NULL) {
+ pp->ki_udata = NOPROC;
+ return (NULL);
+ }
+ oldp = *oldpp;
+ if (memcmp(&oldp->ki_start, &pp->ki_start, sizeof(pp->ki_start)) != 0) {
+ pp->ki_udata = NOPROC;
+ return (NULL);
+ }
+ pp->ki_udata = __DECONST(void *, oldp);
+ return (oldp);
+}
+
+/*
+ * Return the total amount of IO done in blocks in/out and faults.
+ * store the values individually in the pointers passed in.
+ */
+static long
+get_io_stats(const struct kinfo_proc *pp, long *inp, long *oup, long *flp,
+ long *vcsw, long *ivcsw)
+{
+ const struct kinfo_proc *oldp;
+ static struct kinfo_proc dummy;
+ long ret;
+
+ oldp = get_old_proc(__DECONST(struct kinfo_proc *, pp));
+ if (oldp == NULL) {
+ memset(&dummy, 0, sizeof(dummy));
+ oldp = &dummy;
+ }
+ *inp = RU(pp)->ru_inblock - RU(oldp)->ru_inblock;
+ *oup = RU(pp)->ru_oublock - RU(oldp)->ru_oublock;
+ *flp = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
+ *vcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw;
+ *ivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw;
+ ret =
+ (RU(pp)->ru_inblock - RU(oldp)->ru_inblock) +
+ (RU(pp)->ru_oublock - RU(oldp)->ru_oublock) +
+ (RU(pp)->ru_majflt - RU(oldp)->ru_majflt);
+ return (ret);
+}
+
+/*
+ * If there was a previous update, use the delta in ki_runtime over
+ * the previous interval to calculate pctcpu. Otherwise, fall back
+ * to using the kernel's ki_pctcpu.
+ */
+static double
+proc_calc_pctcpu(struct kinfo_proc *pp)
+{
+ const struct kinfo_proc *oldp;
+
+ if (previous_interval != 0) {
+ oldp = get_old_proc(pp);
+ if (oldp != NULL)
+ return ((double)(pp->ki_runtime - oldp->ki_runtime)
+ / previous_interval);
+
+ /*
+ * If this process/thread was created during the previous
+ * interval, charge it's total runtime to the previous
+ * interval.
+ */
+ else if (pp->ki_start.tv_sec > previous_wall_time.tv_sec ||
+ (pp->ki_start.tv_sec == previous_wall_time.tv_sec &&
+ pp->ki_start.tv_usec >= previous_wall_time.tv_usec))
+ return ((double)pp->ki_runtime / previous_interval);
+ }
+ return (pctdouble(pp->ki_pctcpu));
+}
+
+/*
+ * Return true if this process has used any CPU time since the
+ * previous update.
+ */
+static int
+proc_used_cpu(struct kinfo_proc *pp)
+{
+ const struct kinfo_proc *oldp;
+
+ oldp = get_old_proc(pp);
+ if (oldp == NULL)
+ return (PCTCPU(pp) != 0);
+ return (pp->ki_runtime != oldp->ki_runtime ||
+ RU(pp)->ru_nvcsw != RU(oldp)->ru_nvcsw ||
+ RU(pp)->ru_nivcsw != RU(oldp)->ru_nivcsw);
+}
+
+/*
+ * Return the total number of block in/out and faults by a process.
+ */
+static long
+get_io_total(const struct kinfo_proc *pp)
+{
+ long dummy;
+
+ return (get_io_stats(pp, &dummy, &dummy, &dummy, &dummy, &dummy));
+}
+
+static struct handle handle;
+
+void *
+get_process_info(struct system_info *si, struct process_select *sel,
+ int (*compare)(const void *, const void *))
+{
+ int i;
+ int total_procs;
+ long p_io;
+ long p_inblock, p_oublock, p_majflt, p_vcsw, p_ivcsw;
+ long nsec;
+ int active_procs;
+ struct kinfo_proc **prefp;
+ struct kinfo_proc *pp;
+ struct timespec previous_proc_uptime;
+
+ /*
+ * If thread state was toggled, don't cache the previous processes.
+ */
+ if (previous_thread != sel->thread)
+ nproc = 0;
+ previous_thread = sel->thread;
+
+ /*
+ * Save the previous process info.
+ */
+ if (previous_proc_count_max < nproc) {
+ free(previous_procs);
+ previous_procs = calloc(nproc, sizeof(*previous_procs));
+ free(previous_pref);
+ previous_pref = calloc(nproc, sizeof(*previous_pref));
+ if (previous_procs == NULL || previous_pref == NULL) {
+ fprintf(stderr, "top: Out of memory.\n");
+ quit(TOP_EX_SYS_ERROR);
+ }
+ previous_proc_count_max = nproc;
+ }
+ if (nproc) {
+ for (i = 0; i < nproc; i++)
+ previous_pref[i] = &previous_procs[i];
+ memcpy(previous_procs, pbase, nproc * sizeof(*previous_procs));
+ qsort(previous_pref, nproc, sizeof(*previous_pref),
+ ps.thread ? compare_tid : compare_pid);
+ }
+ previous_proc_count = nproc;
+ previous_proc_uptime = proc_uptime;
+ previous_wall_time = proc_wall_time;
+ previous_interval = 0;
+
+ pbase = kvm_getprocs(kd, sel->thread ? KERN_PROC_ALL : KERN_PROC_PROC,
+ 0, &nproc);
+ gettimeofday(&proc_wall_time, NULL);
+ if (clock_gettime(CLOCK_UPTIME, &proc_uptime) != 0)
+ memset(&proc_uptime, 0, sizeof(proc_uptime));
+ else if (previous_proc_uptime.tv_sec != 0 &&
+ previous_proc_uptime.tv_nsec != 0) {
+ previous_interval = (proc_uptime.tv_sec -
+ previous_proc_uptime.tv_sec) * 1000000;
+ nsec = proc_uptime.tv_nsec - previous_proc_uptime.tv_nsec;
+ if (nsec < 0) {
+ previous_interval -= 1000000;
+ nsec += 1000000000;
+ }
+ previous_interval += nsec / 1000;
+ }
+ if (nproc > onproc) {
+ pref = realloc(pref, sizeof(*pref) * nproc);
+ pcpu = realloc(pcpu, sizeof(*pcpu) * nproc);
+ onproc = nproc;
+ }
+ if (pref == NULL || pbase == NULL || pcpu == NULL) {
+ fprintf(stderr, "top: Out of memory.\n");
+ quit(TOP_EX_SYS_ERROR);
+ }
+ /* get a pointer to the states summary array */
+ si->procstates = process_states;
+
+ /* count up process states and get pointers to interesting procs */
+ total_procs = 0;
+ active_procs = 0;
+ total_inblock = 0;
+ total_oublock = 0;
+ total_majflt = 0;
+ memset(process_states, 0, sizeof(process_states));
+ prefp = pref;
+ for (pp = pbase, i = 0; i < nproc; pp++, i++) {
+
+ if (pp->ki_stat == 0)
+ /* not in use */
+ continue;
+
+ if (!sel->self && pp->ki_pid == mypid && sel->pid == -1)
+ /* skip self */
+ continue;
+
+ if (!sel->system && (pp->ki_flag & P_SYSTEM) && sel->pid == -1)
+ /* skip system process */
+ continue;
+
+ p_io = get_io_stats(pp, &p_inblock, &p_oublock, &p_majflt,
+ &p_vcsw, &p_ivcsw);
+ total_inblock += p_inblock;
+ total_oublock += p_oublock;
+ total_majflt += p_majflt;
+ total_procs++;
+ process_states[(unsigned char)pp->ki_stat]++;
+
+ if (pp->ki_stat == SZOMB)
+ /* skip zombies */
+ continue;
+
+ if (!sel->kidle && pp->ki_tdflags & TDF_IDLETD && sel->pid == -1)
+ /* skip kernel idle process */
+ continue;
+
+ PCTCPU(pp) = proc_calc_pctcpu(pp);
+ if (sel->thread && PCTCPU(pp) > 1.0)
+ PCTCPU(pp) = 1.0;
+ if (displaymode == DISP_CPU && !sel->idle &&
+ (!proc_used_cpu(pp) ||
+ pp->ki_stat == SSTOP || pp->ki_stat == SIDL))
+ /* skip idle or non-running processes */
+ continue;
+
+ if (displaymode == DISP_IO && !sel->idle && p_io == 0)
+ /* skip processes that aren't doing I/O */
+ continue;
+
+ if (sel->jid != -1 && pp->ki_jid != sel->jid)
+ /* skip proc. that don't belong to the selected JID */
+ continue;
+
+ if (sel->uid[0] != -1 && !find_uid(pp->ki_ruid, sel->uid))
+ /* skip proc. that don't belong to the selected UID */
+ continue;
+
+ if (sel->pid != -1 && pp->ki_pid != sel->pid)
+ continue;
+
+ if (!cmd_matches(pp, sel->command))
+ /* skip proc. that doesn't match grep string */
+ continue;
+
+ *prefp++ = pp;
+ active_procs++;
+ }
+
+ /* if requested, sort the "interesting" processes */
+ if (compare != NULL)
+ qsort(pref, active_procs, sizeof(*pref), compare);
+
+ /* remember active and total counts */
+ si->p_total = total_procs;
+ si->p_pactive = pref_len = active_procs;
+
+ /* pass back a handle */
+ handle.next_proc = pref;
+ handle.remaining = active_procs;
+ return (&handle);
+}
+
+static int
+cmd_matches(struct kinfo_proc *proc, const char *term)
+{
+ char **args = NULL;
+
+ if (!term) {
+ /* No command filter set */
+ return 1;
+ } else {
+ /* Filter set, does process name contain term? */
+ if (strstr(proc->ki_comm, term))
+ return 1;
+ /* Search arguments only if arguments are displayed */
+ if (show_args) {
+ args = kvm_getargv(kd, proc, 1024);
+ if (args == NULL) {
+ /* Failed to get arguments so can't search them */
+ return 0;
+ }
+ while (*args != NULL) {
+ if (strstr(*args, term))
+ return 1;
+ args++;
+ }
+ }
+ }
+ return 0;
+}
+
+char *
+format_next_process(struct handle * xhandle, char *(*get_userid)(int), int flags)
+{
+ struct kinfo_proc *pp;
+ const struct kinfo_proc *oldp;
+ long cputime;
+ char status[22];
+ size_t state;
+ struct rusage ru, *rup;
+ long p_tot, s_tot;
+ char *cmdbuf = NULL;
+ char **args;
+ static struct sbuf* procbuf = NULL;
+
+ /* clean up from last time. */
+ if (procbuf != NULL) {
+ sbuf_clear(procbuf);
+ } else {
+ procbuf = sbuf_new_auto();
+ }
+
+
+ /* find and remember the next proc structure */
+ pp = *(xhandle->next_proc++);
+ xhandle->remaining--;
+
+ /* get the process's command name */
+ if ((pp->ki_flag & P_INMEM) == 0) {
+ /*
+ * Print swapped processes as <pname>
+ */
+ size_t len;
+
+ len = strlen(pp->ki_comm);
+ if (len > sizeof(pp->ki_comm) - 3)
+ len = sizeof(pp->ki_comm) - 3;
+ memmove(pp->ki_comm + 1, pp->ki_comm, len);
+ pp->ki_comm[0] = '<';
+ pp->ki_comm[len + 1] = '>';
+ pp->ki_comm[len + 2] = '\0';
+ }
+
+ /*
+ * Convert the process's runtime from microseconds to seconds. This
+ * time includes the interrupt time although that is not wanted here.
+ * ps(1) is similarly sloppy.
+ */
+ cputime = (pp->ki_runtime + 500000) / 1000000;
+
+ /* generate "STATE" field */
+ switch (state = pp->ki_stat) {
+ case SRUN:
+ if (smpmode && pp->ki_oncpu != NOCPU)
+ sprintf(status, "CPU%d", pp->ki_oncpu);
+ else
+ strcpy(status, "RUN");
+ break;
+ case SLOCK:
+ if (pp->ki_kiflag & KI_LOCKBLOCK) {
+ sprintf(status, "*%.6s", pp->ki_lockname);
+ break;
+ }
+ /* fall through */
+ case SSLEEP:
+ sprintf(status, "%.6s", pp->ki_wmesg);
+ break;
+ default:
+
+ if (state < nitems(state_abbrev)) {
+ sprintf(status, "%.6s", state_abbrev[state]);
+ } else {
+ sprintf(status, "?%5zu", state);
+ }
+ break;
+ }
+
+ cmdbuf = calloc(screen_width + 1, 1);
+ if (cmdbuf == NULL) {
+ warn("calloc(%d)", screen_width + 1);
+ return NULL;
+ }
+
+ if (!(flags & FMT_SHOWARGS)) {
+ if (ps.thread && pp->ki_flag & P_HADTHREADS &&
+ pp->ki_tdname[0]) {
+ snprintf(cmdbuf, screen_width, "%s{%s%s}", pp->ki_comm,
+ pp->ki_tdname, pp->ki_moretdname);
+ } else {
+ snprintf(cmdbuf, screen_width, "%s", pp->ki_comm);
+ }
+ } else {
+ if (pp->ki_flag & P_SYSTEM ||
+ (args = kvm_getargv(kd, pp, screen_width)) == NULL ||
+ !(*args)) {
+ if (ps.thread && pp->ki_flag & P_HADTHREADS &&
+ pp->ki_tdname[0]) {
+ snprintf(cmdbuf, screen_width,
+ "[%s{%s%s}]", pp->ki_comm, pp->ki_tdname,
+ pp->ki_moretdname);
+ } else {
+ snprintf(cmdbuf, screen_width,
+ "[%s]", pp->ki_comm);
+ }
+ } else {
+ const char *src;
+ char *dst, *argbuf;
+ const char *cmd;
+ size_t argbuflen;
+ size_t len;
+
+ argbuflen = screen_width * 4;
+ argbuf = calloc(argbuflen + 1, 1);
+ if (argbuf == NULL) {
+ warn("calloc(%zu)", argbuflen + 1);
+ free(cmdbuf);
+ return NULL;
+ }
+
+ dst = argbuf;
+
+ /* Extract cmd name from argv */
+ cmd = basename(*args);
+
+ for (; (src = *args++) != NULL; ) {
+ if (*src == '\0')
+ continue;
+ len = (argbuflen - (dst - argbuf) - 1) / 4;
+ strvisx(dst, src,
+ MIN(strlen(src), len),
+ VIS_NL | VIS_TAB | VIS_CSTYLE | VIS_OCTAL);
+ while (*dst != '\0')
+ dst++;
+ if ((argbuflen - (dst - argbuf) - 1) / 4 > 0)
+ *dst++ = ' '; /* add delimiting space */
+ }
+ if (dst != argbuf && dst[-1] == ' ')
+ dst--;
+ *dst = '\0';
+
+ if (strcmp(cmd, pp->ki_comm) != 0) {
+ if (ps.thread && pp->ki_flag & P_HADTHREADS &&
+ pp->ki_tdname[0])
+ snprintf(cmdbuf, screen_width,
+ "%s (%s){%s%s}", argbuf,
+ pp->ki_comm, pp->ki_tdname,
+ pp->ki_moretdname);
+ else
+ snprintf(cmdbuf, screen_width,
+ "%s (%s)", argbuf, pp->ki_comm);
+ } else {
+ if (ps.thread && pp->ki_flag & P_HADTHREADS &&
+ pp->ki_tdname[0])
+ snprintf(cmdbuf, screen_width,
+ "%s{%s%s}", argbuf, pp->ki_tdname,
+ pp->ki_moretdname);
+ else
+ strlcpy(cmdbuf, argbuf, screen_width);
+ }
+ free(argbuf);
+ }
+ }
+
+ if (displaymode == DISP_IO) {
+ oldp = get_old_proc(pp);
+ if (oldp != NULL) {
+ ru.ru_inblock = RU(pp)->ru_inblock -
+ RU(oldp)->ru_inblock;
+ ru.ru_oublock = RU(pp)->ru_oublock -
+ RU(oldp)->ru_oublock;
+ ru.ru_majflt = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
+ ru.ru_nvcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw;
+ ru.ru_nivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw;
+ rup = &ru;
+ } else {
+ rup = RU(pp);
+ }
+ p_tot = rup->ru_inblock + rup->ru_oublock + rup->ru_majflt;
+ s_tot = total_inblock + total_oublock + total_majflt;
+
+ sbuf_printf(procbuf, "%5d ", (ps.thread_id) ? pp->ki_tid : pp->ki_pid);
+
+ if (ps.jail) {
+ sbuf_printf(procbuf, "%*d ", TOP_JID_LEN - 1, pp->ki_jid);
+ }
+ sbuf_printf(procbuf, "%-*.*s", namelength, namelength, (*get_userid)(pp->ki_ruid));
+ sbuf_printf(procbuf, "%6ld ", rup->ru_nvcsw);
+ sbuf_printf(procbuf, "%6ld ", rup->ru_nivcsw);
+ sbuf_printf(procbuf, "%6ld ", rup->ru_inblock);
+ sbuf_printf(procbuf, "%6ld ", rup->ru_oublock);
+ sbuf_printf(procbuf, "%6ld ", rup->ru_majflt);
+ sbuf_printf(procbuf, "%6ld ", p_tot);
+ sbuf_printf(procbuf, "%6.2f%% ", s_tot == 0 ? 0.0 : (p_tot * 100.0 / s_tot));
+
+ } else {
+ sbuf_printf(procbuf, "%5d ", (ps.thread_id) ? pp->ki_tid : pp->ki_pid);
+ if (ps.jail) {
+ sbuf_printf(procbuf, "%*d ", TOP_JID_LEN - 1, pp->ki_jid);
+ }
+ sbuf_printf(procbuf, "%-*.*s ", namelength, namelength, (*get_userid)(pp->ki_ruid));
+
+ if (!ps.thread) {
+ sbuf_printf(procbuf, "%4d ", pp->ki_numthreads);
+ } else {
+ sbuf_printf(procbuf, " ");
+ }
+
+ sbuf_printf(procbuf, "%3d ", pp->ki_pri.pri_level - PZERO);
+ sbuf_printf(procbuf, "%4s", format_nice(pp));
+ sbuf_printf(procbuf, "%7s ", format_k(PROCSIZE(pp)));
+ sbuf_printf(procbuf, "%6s ", format_k(pagetok(pp->ki_rssize)));
+ if (ps.swap) {
+ sbuf_printf(procbuf, "%*s ",
+ TOP_SWAP_LEN - 1,
+ format_k(pagetok(ki_swap(pp))));
+ }
+ sbuf_printf(procbuf, "%-6.6s ", status);
+ if (smpmode) {
+ int cpu;
+ if (state == SRUN && pp->ki_oncpu != NOCPU) {
+ cpu = pp->ki_oncpu;
+ } else {
+ cpu = pp->ki_lastcpu;
+ }
+ sbuf_printf(procbuf, "%3d ", cpu);
+ }
+ sbuf_printf(procbuf, "%6s ", format_time(cputime));
+ sbuf_printf(procbuf, "%6.2f%% ", ps.wcpu ? 100.0 * weighted_cpu(PCTCPU(pp), pp) : 100.0 * PCTCPU(pp));
+ }
+ sbuf_printf(procbuf, "%s", cmdbuf);
+ free(cmdbuf);
+ return (sbuf_data(procbuf));
+}
+
+static void
+getsysctl(const char *name, void *ptr, size_t len)
+{
+ size_t nlen = len;
+
+ if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
+ fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
+ strerror(errno));
+ quit(TOP_EX_SYS_ERROR);
+ }
+ if (nlen != len) {
+ fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n",
+ name, (unsigned long)len, (unsigned long)nlen);
+ quit(TOP_EX_SYS_ERROR);
+ }
+}
+
+static const char *
+format_nice(const struct kinfo_proc *pp)
+{
+ const char *fifo, *kproc;
+ int rtpri;
+ static char nicebuf[4 + 1];
+
+ fifo = PRI_NEED_RR(pp->ki_pri.pri_class) ? "" : "F";
+ kproc = (pp->ki_flag & P_KPROC) ? "k" : "";
+ switch (PRI_BASE(pp->ki_pri.pri_class)) {
+ case PRI_ITHD:
+ return ("-");
+ case PRI_REALTIME:
+ /*
+ * XXX: the kernel doesn't tell us the original rtprio and
+ * doesn't really know what it was, so to recover it we
+ * must be more chummy with the implementation than the
+ * implementation is with itself. pri_user gives a
+ * constant "base" priority, but is only initialized
+ * properly for user threads. pri_native gives what the
+ * kernel calls the "base" priority, but it isn't constant
+ * since it is changed by priority propagation. pri_native
+ * also isn't properly initialized for all threads, but it
+ * is properly initialized for kernel realtime and idletime
+ * threads. Thus we use pri_user for the base priority of
+ * user threads (it is always correct) and pri_native for
+ * the base priority of kernel realtime and idletime threads
+ * (there is nothing better, and it is usually correct).
+ *
+ * The field width and thus the buffer are too small for
+ * values like "kr31F", but such values shouldn't occur,
+ * and if they do then the tailing "F" is not displayed.
+ */
+ rtpri = ((pp->ki_flag & P_KPROC) ? pp->ki_pri.pri_native :
+ pp->ki_pri.pri_user) - PRI_MIN_REALTIME;
+ snprintf(nicebuf, sizeof(nicebuf), "%sr%d%s",
+ kproc, rtpri, fifo);
+ break;
+ case PRI_TIMESHARE:
+ if (pp->ki_flag & P_KPROC)
+ return ("-");
+ snprintf(nicebuf, sizeof(nicebuf), "%d", pp->ki_nice - NZERO);
+ break;
+ case PRI_IDLE:
+ /* XXX: as above. */
+ rtpri = ((pp->ki_flag & P_KPROC) ? pp->ki_pri.pri_native :
+ pp->ki_pri.pri_user) - PRI_MIN_IDLE;
+ snprintf(nicebuf, sizeof(nicebuf), "%si%d%s",
+ kproc, rtpri, fifo);
+ break;
+ default:
+ return ("?");
+ }
+ return (nicebuf);
+}
+
+/* comparison routines for qsort */
+
+static int
+compare_pid(const void *p1, const void *p2)
+{
+ const struct kinfo_proc * const *pp1 = p1;
+ const struct kinfo_proc * const *pp2 = p2;
+
+ assert((*pp2)->ki_pid >= 0 && (*pp1)->ki_pid >= 0);
+
+ return ((*pp1)->ki_pid - (*pp2)->ki_pid);
+}
+
+static int
+compare_tid(const void *p1, const void *p2)
+{
+ const struct kinfo_proc * const *pp1 = p1;
+ const struct kinfo_proc * const *pp2 = p2;
+
+ assert((*pp2)->ki_tid >= 0 && (*pp1)->ki_tid >= 0);
+
+ return ((*pp1)->ki_tid - (*pp2)->ki_tid);
+}
+
+/*
+ * proc_compare - comparison function for "qsort"
+ * Compares the resource consumption of two processes using five
+ * distinct keys. The keys (in descending order of importance) are:
+ * percent cpu, cpu ticks, state, resident set size, total virtual
+ * memory usage. The process states are ordered as follows (from least
+ * to most important): run, zombie, idle, interrupt wait, stop, sleep.
+ * The array declaration below maps a process state index into a
+ * number that reflects this ordering.
+ */
+
+static const int sorted_state[] = {
+ [SIDL] = 3, /* being created */
+ [SRUN] = 1, /* running/runnable */
+ [SSLEEP] = 6, /* sleeping */
+ [SSTOP] = 5, /* stopped/suspended */
+ [SZOMB] = 2, /* zombie */
+ [SWAIT] = 4, /* intr */
+ [SLOCK] = 7, /* blocked on lock */
+};
+
+
+#define ORDERKEY_PCTCPU(a, b) do { \
+ double diff; \
+ if (ps.wcpu) \
+ diff = weighted_cpu(PCTCPU((b)), (b)) - \
+ weighted_cpu(PCTCPU((a)), (a)); \
+ else \
+ diff = PCTCPU((b)) - PCTCPU((a)); \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_CPTICKS(a, b) do { \
+ int64_t diff = (int64_t)(b)->ki_runtime - (int64_t)(a)->ki_runtime; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_STATE(a, b) do { \
+ int diff = sorted_state[(unsigned char)(b)->ki_stat] - sorted_state[(unsigned char)(a)->ki_stat]; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_PRIO(a, b) do { \
+ int diff = (int)(b)->ki_pri.pri_level - (int)(a)->ki_pri.pri_level; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_THREADS(a, b) do { \
+ int diff = (int)(b)->ki_numthreads - (int)(a)->ki_numthreads; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_RSSIZE(a, b) do { \
+ long diff = (long)(b)->ki_rssize - (long)(a)->ki_rssize; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_MEM(a, b) do { \
+ long diff = (long)PROCSIZE((b)) - (long)PROCSIZE((a)); \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_JID(a, b) do { \
+ int diff = (int)(b)->ki_jid - (int)(a)->ki_jid; \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+#define ORDERKEY_SWAP(a, b) do { \
+ int diff = (int)ki_swap(b) - (int)ki_swap(a); \
+ if (diff != 0) \
+ return (diff > 0 ? 1 : -1); \
+} while (0)
+
+/* compare_cpu - the comparison function for sorting by cpu percentage */
+
+static int
+compare_cpu(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* compare_size - the comparison function for sorting by total memory usage */
+
+static int
+compare_size(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_MEM(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+
+ return (0);
+}
+
+/* compare_res - the comparison function for sorting by resident set size */
+
+static int
+compare_res(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+
+ return (0);
+}
+
+/* compare_time - the comparison function for sorting by total cpu time */
+
+static int
+compare_time(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *) arg2;
+
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* compare_prio - the comparison function for sorting by priority */
+
+static int
+compare_prio(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* compare_threads - the comparison function for sorting by threads */
+static int
+compare_threads(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_THREADS(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* compare_jid - the comparison function for sorting by jid */
+static int
+compare_jid(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_JID(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* compare_swap - the comparison function for sorting by swap */
+static int
+compare_swap(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+
+ ORDERKEY_SWAP(p1, p2);
+ ORDERKEY_PCTCPU(p1, p2);
+ ORDERKEY_CPTICKS(p1, p2);
+ ORDERKEY_STATE(p1, p2);
+ ORDERKEY_PRIO(p1, p2);
+ ORDERKEY_RSSIZE(p1, p2);
+ ORDERKEY_MEM(p1, p2);
+
+ return (0);
+}
+
+/* assorted comparison functions for sorting by i/o */
+
+static int
+compare_iototal(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc * const p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc * const p2 = *(const struct kinfo_proc * const *)arg2;
+
+ return (get_io_total(p2) - get_io_total(p1));
+}
+
+static int
+compare_ioread(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+ long dummy, inp1, inp2;
+
+ (void) get_io_stats(p1, &inp1, &dummy, &dummy, &dummy, &dummy);
+ (void) get_io_stats(p2, &inp2, &dummy, &dummy, &dummy, &dummy);
+
+ return (inp2 - inp1);
+}
+
+static int
+compare_iowrite(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+ long dummy, oup1, oup2;
+
+ (void) get_io_stats(p1, &dummy, &oup1, &dummy, &dummy, &dummy);
+ (void) get_io_stats(p2, &dummy, &oup2, &dummy, &dummy, &dummy);
+
+ return (oup2 - oup1);
+}
+
+static int
+compare_iofault(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+ long dummy, flp1, flp2;
+
+ (void) get_io_stats(p1, &dummy, &dummy, &flp1, &dummy, &dummy);
+ (void) get_io_stats(p2, &dummy, &dummy, &flp2, &dummy, &dummy);
+
+ return (flp2 - flp1);
+}
+
+static int
+compare_vcsw(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+ long dummy, flp1, flp2;
+
+ (void) get_io_stats(p1, &dummy, &dummy, &dummy, &flp1, &dummy);
+ (void) get_io_stats(p2, &dummy, &dummy, &dummy, &flp2, &dummy);
+
+ return (flp2 - flp1);
+}
+
+static int
+compare_ivcsw(const void *arg1, const void *arg2)
+{
+ const struct kinfo_proc *p1 = *(const struct kinfo_proc * const *)arg1;
+ const struct kinfo_proc *p2 = *(const struct kinfo_proc * const *)arg2;
+ long dummy, flp1, flp2;
+
+ (void) get_io_stats(p1, &dummy, &dummy, &dummy, &dummy, &flp1);
+ (void) get_io_stats(p2, &dummy, &dummy, &dummy, &dummy, &flp2);
+
+ return (flp2 - flp1);
+}
+
+int (*compares[])(const void *arg1, const void *arg2) = {
+ compare_cpu,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_prio,
+ compare_threads,
+ compare_iototal,
+ compare_ioread,
+ compare_iowrite,
+ compare_iofault,
+ compare_vcsw,
+ compare_ivcsw,
+ compare_jid,
+ compare_swap,
+ compare_pid,
+ NULL
+};
+
+
+static int
+swapmode(int *retavail, int *retfree)
+{
+ int n;
+ struct kvm_swap swapary[1];
+ static int pagesize = 0;
+ static unsigned long swap_maxpages = 0;
+
+ *retavail = 0;
+ *retfree = 0;
+
+#define CONVERT(v) ((quad_t)(v) * pagesize / 1024)
+
+ n = kvm_getswapinfo(kd, swapary, 1, 0);
+ if (n < 0 || swapary[0].ksw_total == 0)
+ return (0);
+
+ if (pagesize == 0)
+ pagesize = getpagesize();
+ if (swap_maxpages == 0)
+ GETSYSCTL("vm.swap_maxpages", swap_maxpages);
+
+ /* ksw_total contains the total size of swap all devices which may
+ exceed the maximum swap size allocatable in the system */
+ if ( swapary[0].ksw_total > swap_maxpages )
+ swapary[0].ksw_total = swap_maxpages;
+
+ *retavail = CONVERT(swapary[0].ksw_total);
+ *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
+
+#undef CONVERT
+
+ n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total);
+ return (n);
+}
diff --git a/usr.bin/top/machine.h b/usr.bin/top/machine.h
new file mode 100644
index 000000000000..57f2846cdba5
--- /dev/null
+++ b/usr.bin/top/machine.h
@@ -0,0 +1,98 @@
+/*
+ */
+
+/*
+ * This file defines the interface between top and the machine-dependent
+ * module. It is NOT machine dependent and should not need to be changed
+ * for any specific machine.
+ */
+#ifndef MACHINE_H
+#define MACHINE_H
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#define NUM_AVERAGES 3
+
+/* Log base 2 of 1024 is 10 (2^10 == 1024) */
+#define LOG1024 10
+
+/*
+ * the statics struct is filled in by machine_init
+ */
+struct statics
+{
+ const char * const *procstate_names;
+ const char * const *cpustate_names;
+ const char * const *memory_names;
+ const char * const *arc_names;
+ const char * const *carc_names;
+ const char * const *swap_names;
+ const char * const *order_names;
+ int nbatteries;
+ int ncpus;
+};
+
+/*
+ * the system_info struct is filled in by a machine dependent routine.
+ */
+
+struct system_info
+{
+ int last_pid;
+ double load_avg[NUM_AVERAGES];
+ int p_total;
+ int p_pactive; /* number of procs considered "active" */
+ int *procstates;
+ int *cpustates;
+ int *memory;
+ int *arc;
+ int *carc;
+ int *swap;
+ struct timeval boottime;
+ int battery;
+ int ncpus;
+};
+
+/*
+ * the process_select struct tells get_process_info what processes
+ * and information we are interested in seeing
+ */
+
+struct process_select
+{
+ bool idle; /* show idle processes */
+ bool self; /* show self */
+ bool system; /* show system processes */
+ bool thread; /* show threads */
+ bool thread_id; /* show thread ids */
+#define TOP_MAX_UIDS 8
+ int uid[TOP_MAX_UIDS]; /* only these uids (unless uid[0] == -1) */
+ bool wcpu; /* show weighted cpu */
+ int jid; /* only this jid (unless jid == -1) */
+ bool jail; /* show jail ID */
+ bool swap; /* show swap usage */
+ bool kidle; /* show per-CPU idle threads */
+ int pid; /* only this pid (unless pid == -1) */
+ char *command; /* only this command (unless == NULL) */
+};
+
+/* routines defined by the machine dependent module */
+
+struct handle;
+
+char *format_header(const char *uname_field);
+char *format_next_process(struct handle* handle, char *(*get_userid)(int),
+ int flags);
+void toggle_pcpustats(void);
+void get_system_info(struct system_info *si);
+int machine_init(struct statics *statics);
+
+/* non-int routines typically used by the machine dependent module */
+extern struct process_select ps;
+
+void *
+get_process_info(struct system_info *si, struct process_select *sel,
+ int (*compare)(const void *, const void *));
+
+#endif /* MACHINE_H */
diff --git a/usr.bin/top/screen.c b/usr.bin/top/screen.c
new file mode 100644
index 000000000000..733d9dcb8930
--- /dev/null
+++ b/usr.bin/top/screen.c
@@ -0,0 +1,316 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/* This file contains the routines that interface to termcap and stty/gtty.
+ *
+ * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
+ *
+ * I put in code to turn on the TOSTOP bit while top was running, but I
+ * didn't really like the results. If you desire it, turn on the
+ * preprocessor variable "TOStop". --wnl
+ */
+
+#include <sys/ioctl.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <curses.h>
+#include <termcap.h>
+#include <unistd.h>
+
+#include "screen.h"
+#include "top.h"
+
+int overstrike;
+int screen_length;
+int screen_width;
+char ch_erase;
+char ch_kill;
+char smart_terminal;
+static char termcap_buf[1024];
+static char string_buffer[1024];
+static char home[15];
+static char lower_left[15];
+char *clear_line;
+static char *clear_screen;
+char *clear_to_end;
+char *cursor_motion;
+static char *start_standout;
+static char *end_standout;
+static char *terminal_init;
+static char *terminal_end;
+
+static struct termios old_settings;
+static struct termios new_settings;
+static char is_a_terminal = false;
+
+#define NON_INTERACTIVE_MODE_VIRTUAL_SCREEN_WIDTH 1024
+
+void
+init_termcap(bool interactive)
+{
+ char *bufptr;
+ char *PCptr;
+ char *term_name;
+ int status;
+
+ screen_width = 0;
+ screen_length = 0;
+
+ if (!interactive)
+ {
+ /* pretend we have a dumb terminal */
+ screen_width = NON_INTERACTIVE_MODE_VIRTUAL_SCREEN_WIDTH;
+ smart_terminal = false;
+ return;
+ }
+
+ /* assume we have a smart terminal until proven otherwise */
+ smart_terminal = true;
+
+ /* get the terminal name */
+ term_name = getenv("TERM");
+
+ /* if there is no TERM, assume it's a dumb terminal */
+ /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
+ if (term_name == NULL)
+ {
+ smart_terminal = false;
+ return;
+ }
+
+ /* now get the termcap entry */
+ if ((status = tgetent(termcap_buf, term_name)) != 1)
+ {
+ if (status == -1)
+ {
+ warnx("can't open termcap file");
+ }
+ else
+ {
+ warnx("no termcap entry for a `%s' terminal", term_name);
+ }
+
+ /* pretend it's dumb and proceed */
+ smart_terminal = false;
+ return;
+ }
+
+ /* "hardcopy" immediately indicates a very stupid terminal */
+ if (tgetflag("hc"))
+ {
+ smart_terminal = false;
+ return;
+ }
+
+ /* set up common terminal capabilities */
+ if ((screen_length = tgetnum("li")) <= 0)
+ {
+ screen_length = smart_terminal = 0;
+ return;
+ }
+
+ /* screen_width is a little different */
+ if ((screen_width = tgetnum("co")) == -1)
+ {
+ screen_width = 79;
+ }
+ else
+ {
+ screen_width -= 1;
+ }
+
+ /* terminals that overstrike need special attention */
+ overstrike = tgetflag("os");
+
+ /* initialize the pointer into the termcap string buffer */
+ bufptr = string_buffer;
+
+ /* get "ce", clear to end */
+ if (!overstrike)
+ {
+ clear_line = tgetstr("ce", &bufptr);
+ }
+
+ /* get necessary capabilities */
+ if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
+ (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
+ {
+ smart_terminal = false;
+ return;
+ }
+
+ /* get some more sophisticated stuff -- these are optional */
+ clear_to_end = tgetstr("cd", &bufptr);
+ terminal_init = tgetstr("ti", &bufptr);
+ terminal_end = tgetstr("te", &bufptr);
+ start_standout = tgetstr("so", &bufptr);
+ end_standout = tgetstr("se", &bufptr);
+
+ /* pad character */
+ PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
+
+ /* set convenience strings */
+ strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
+ home[sizeof(home) - 1] = '\0';
+ /* (lower_left is set in get_screensize) */
+
+ /* get the actual screen size with an ioctl, if needed */
+ /* This may change screen_width and screen_length, and it always
+ sets lower_left. */
+ get_screensize();
+
+ /* if stdout is not a terminal, pretend we are a dumb terminal */
+ if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
+ {
+ smart_terminal = false;
+ }
+}
+
+void
+init_screen(void)
+{
+ /* get the old settings for safe keeping */
+ if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
+ {
+ /* copy the settings so we can modify them */
+ new_settings = old_settings;
+
+ /* turn off ICANON, character echo and tab expansion */
+ new_settings.c_lflag &= ~(ICANON|ECHO);
+ new_settings.c_oflag &= ~(TAB3);
+ new_settings.c_cc[VMIN] = 1;
+ new_settings.c_cc[VTIME] = 0;
+ tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
+
+ /* remember the erase and kill characters */
+ ch_erase = old_settings.c_cc[VERASE];
+ ch_kill = old_settings.c_cc[VKILL];
+
+ /* remember that it really is a terminal */
+ is_a_terminal = true;
+
+ /* send the termcap initialization string */
+ putcap(terminal_init);
+ }
+
+ if (!is_a_terminal)
+ {
+ /* not a terminal at all---consider it dumb */
+ smart_terminal = false;
+ }
+}
+
+void
+end_screen(void)
+{
+ /* move to the lower left, clear the line and send "te" */
+ if (smart_terminal)
+ {
+ putcap(lower_left);
+ putcap(clear_line);
+ fflush(stdout);
+ putcap(terminal_end);
+ }
+
+ /* if we have settings to reset, then do so */
+ if (is_a_terminal)
+ {
+ tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
+ }
+}
+
+void
+reinit_screen(void)
+{
+ /* install our settings if it is a terminal */
+ if (is_a_terminal)
+ {
+ tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
+ }
+
+ /* send init string */
+ if (smart_terminal)
+ {
+ putcap(terminal_init);
+ }
+}
+
+void
+get_screensize(void)
+{
+ struct winsize ws;
+
+ if (ioctl (1, TIOCGWINSZ, &ws) != -1)
+ {
+ if (ws.ws_row != 0)
+ {
+ screen_length = ws.ws_row;
+ }
+ if (ws.ws_col != 0)
+ {
+ screen_width = ws.ws_col - 1;
+ }
+ }
+
+
+ (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
+ sizeof(lower_left) - 1);
+ lower_left[sizeof(lower_left) - 1] = '\0';
+}
+
+void
+top_standout(const char *msg)
+{
+ if (smart_terminal)
+ {
+ putcap(start_standout);
+ fputs(msg, stdout);
+ putcap(end_standout);
+ }
+ else
+ {
+ fputs(msg, stdout);
+ }
+}
+
+void
+top_clear(void)
+{
+ if (smart_terminal)
+ {
+ putcap(clear_screen);
+ }
+}
+
+int
+clear_eol(int len)
+{
+ if (smart_terminal && !overstrike && len > 0)
+ {
+ if (clear_line)
+ {
+ putcap(clear_line);
+ return(0);
+ }
+ else
+ {
+ while (len-- > 0)
+ {
+ putchar(' ');
+ }
+ return(1);
+ }
+ }
+ return(-1);
+}
diff --git a/usr.bin/top/screen.h b/usr.bin/top/screen.h
new file mode 100644
index 000000000000..c5782a10f8b6
--- /dev/null
+++ b/usr.bin/top/screen.h
@@ -0,0 +1,34 @@
+/*
+ * top - a top users display for Unix 4.2
+ *
+ * This file contains all the definitions necessary to use the hand-written
+ * screen package in "screen.c"
+ */
+
+#define TCputs(str) tputs(str, 1, putchar)
+#define putcap(str) (void)((str) != NULL ? TCputs(str) : 0)
+#define Move_to(x, y) TCputs(tgoto(cursor_motion, x, y))
+
+extern char ch_erase; /* set to the user's erase character */
+extern char ch_kill; /* set to the user's kill character */
+extern char smart_terminal; /* set if the terminal has sufficient termcap
+ capabilities for normal operation */
+
+/* These are some termcap strings for use outside of "screen.c" */
+extern char *cursor_motion;
+extern char *clear_line;
+extern char *clear_to_end;
+
+/* rows and columns on the screen according to termcap */
+extern int screen_length;
+extern int screen_width;
+
+int clear_eol(int len);
+void top_standout(const char *msg);
+void top_clear(void);
+void reinit_screen(void);
+void get_screensize(void);
+void init_termcap(bool interactive);
+void end_screen(void);
+void init_screen(void);
+
diff --git a/usr.bin/top/top.1 b/usr.bin/top/top.1
new file mode 100644
index 000000000000..ca74860aaa35
--- /dev/null
+++ b/usr.bin/top/top.1
@@ -0,0 +1,533 @@
+.Dd November 18, 2021
+.Dt TOP 1
+.Os
+.Sh NAME
+.Nm top
+.Nd display and update information about the top cpu processes
+.Sh SYNOPSIS
+.Nm
+.Op Fl abCHIijnPpqSTtuvxz
+.Op Fl d Ar count
+.Op Fl J Ar jail
+.Op Fl m Ar mode
+.Op Fl o Ar field
+.Op Fl p Ar pid
+.Op Fl s Ar time
+.Op Fl U Ar uid
+.Op Ar number
+.Sh DESCRIPTION
+.Nm
+displays the top
+processes on the system and periodically updates this information.
+If standard output is an intelligent terminal (see below) then
+as many processes as will fit on the terminal screen are displayed
+by default.
+Otherwise, a good number of them are shown (around 20).
+Raw cpu percentage is used to rank the processes.
+If
+.Ar number
+is given, then the top
+.Ar number
+processes will be displayed instead of the default.
+.Pp
+.Nm
+makes a distinction between terminals that support advanced capabilities
+and those that do not.
+This distinction affects the choice of defaults for certain options.
+In the remainder of this document, an
+.Dq intelligent
+terminal is one that
+supports cursor addressing, clear screen, and clear to end of line.
+Conversely, a
+.Dq dumb
+terminal is one that does not support such
+features.
+If the output of
+.Nm
+is redirected to a file, it acts as if it were being run on a dumb
+terminal.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Display command names derived from the argv[] vector, rather than real
+executable name.
+It it useful when you want to watch applications, that
+puts their status information there.
+If the real name differs from argv[0],
+it will be displayed in parenthesis.
+Non-printable characters in the command line are
+encoded in C-style backslash sequences or
+a three digit octal sequences.
+.It Fl b
+Use
+.Dq batch
+mode.
+In this mode, all input from the terminal is
+ignored.
+Interrupt characters (such as ^C and ^\e) still have an effect.
+This is the default on a dumb terminal, or when the output is not a terminal.
+.It Fl C
+Toggle CPU display mode.
+By default top displays the weighted CPU percentage in the WCPU column
+(this is the same value that
+.Xr ps 1
+displays as CPU).
+Each time
+.Fl C
+flag is passed it toggles between
+.Dq raw cpu
+mode and
+.Dq weighted cpu
+mode, showing the
+.Dq CPU
+or the
+.Dq WCPU
+column respectively.
+.It Fl d Ar count
+Show only
+.Ar count
+displays, then exit.
+A display is considered to be one update of the
+screen.
+The default is 1 for dumb terminals.
+Note that for
+.Ar count
+= 1
+no information is available about the percentage of time spent by the CPU in every state.
+.It Fl H
+Display each thread for a multithreaded process individually.
+By default a single summary line is displayed for each process.
+.It Fl I
+Do not display idle processes.
+By default, top displays both active and idle processes.
+.It Fl i
+Use
+.Dq interactive
+mode.
+In this mode, any input is immediately
+read for processing.
+See the section on
+.Dq Interactive Mode
+for an explanation of
+which keys perform what functions.
+After the command is processed, the
+screen will immediately be updated, even if the command was not
+understood.
+This mode is the default when standard output is an
+intelligent terminal.
+.It Fl J Ar jail
+Show only those processes owned by
+.Ar jail .
+This may be either the
+.Ar jid
+or
+.Ar name
+of the jail.
+Use
+0
+to limit to host processes.
+Using this option implies
+.Fl j .
+.It Fl j
+Display the
+.Xr jail 8
+ID.
+.It Fl m Ar mode
+Display statistics in the specified
+.Ar mode .
+Available modes are
+.Cm cpu
+and
+.Cm io .
+Default is
+.Cm cpu .
+.It Fl n
+Use
+.Dq non-interactive
+mode.
+This is identical to
+.Dq batch
+mode.
+.It Fl o Ar field
+Sort the process display area on the specified field.
+The field name
+is the name of the column as seen in the output, but in lower case:
+.Dq cpu ,
+.Dq size ,
+.Dq res ,
+.Dq time ,
+.Dq pri ,
+.Dq threads ,
+.Dq total ,
+.Dq read ,
+.Dq write ,
+.Dq fault ,
+.Dq vcsw ,
+.Dq ivcsw ,
+.Dq jid ,
+.Dq swap ,
+or
+.Dq pid .
+.It Fl P
+Display per-cpu CPU usage statistics.
+.It Fl p Ar pid
+Show only the process
+.Ar pid .
+.It Fl q
+Renice
+.Nm
+to -20 so that it will run faster.
+This can be used when the system is
+being very sluggish to improve the possibility of discovering the problem.
+This option can only be used by root.
+.It Fl S
+Show system processes in the display.
+Normally, system processes such as the pager and the swapper are not shown.
+This option makes them visible.
+.It Fl s Ar time
+Set the delay between screen updates to
+.Ar time
+seconds, which may be fractional.
+The default delay between updates is 1 second.
+.It Fl T
+Toggle displaying thread ID (tid) instead of process id (pid).
+.It Fl t
+Do not display the
+.Nm
+process itself.
+.It Fl U Ar username
+Show only those processes owned by
+.Ar username .
+This option currently only accepts usernames and will not understand
+uid numbers.
+.It Fl u
+Do not map uid numbers to usernames.
+Normally,
+.Nm
+will read as much of the file
+.Pa /etc/passwd
+as is necessary to map
+all the user id numbers it encounters into login names.
+This option disables all that, while possibly decreasing execution time.
+The uid numbers are displayed instead of the names.
+.It Fl v
+Write version number information to stderr then exit immediately.
+.It Fl w
+Display approximate swap usage for each process.
+.It Fl z
+Do not display the system idle process.
+.El
+.Pp
+Both
+.Ar count
+and
+.Ar number
+fields can be specified as
+.Dq infinite ,
+indicating that they can
+stretch as far as possible.
+This is accomplished by using any proper
+prefix of the keywords
+.Dq infinity ,
+.Dq maximum ,
+or
+.Dq all .
+Boolean flags are toggles.
+A second specification of any of these options will negate the first.
+.Sh "INTERACTIVE MODE"
+When
+.Nm
+is running in
+.Dq interactive mode ,
+it reads commands from the
+terminal and acts upon them accordingly.
+In this mode, the terminal is
+put in
+.Dq CBREAK ,
+so that a character will be
+processed as soon as it is typed.
+Almost always, a key will be
+pressed when
+.Nm
+is between displays; that is, while it is waiting for
+.Ar time
+seconds to elapse.
+If this is the case, the command will be
+processed and the display will be updated immediately thereafter
+(reflecting any changes that the command may have specified).
+This
+happens even if the command was incorrect.
+If a key is pressed while
+.Nm
+is in the middle of updating the display, it will finish the update and
+then process the command.
+Some commands require additional information,
+and the user will be prompted accordingly.
+While typing this information
+in, the user's erase and kill keys (as set up by the command
+.Xr stty 1 )
+are recognized, and a newline terminates the input.
+.Pp
+These commands are currently recognized (^L refers to control-L):
+.Bl -tag -width indent
+.It ^L
+Redraw the screen.
+.It h
+Display a summary of the commands (help screen).
+Version information
+is included in this display.
+.It q
+Quit
+.Nm
+.It d
+Change the number of displays to show (prompt for new number).
+Remember that the next display counts as one, so typing 'd1' will make
+.Nm
+show one final display and then immediately exit.
+.It /
+Display only processes that contain the specified string in their
+command name.
+If displaying arguments is enabled, the arguments are searched
+too. '+' shows all processes.
+.It m
+Toggle the display between 'cpu' and 'io' modes.
+.It n or #
+Change the number of processes to display (prompt for new number).
+.It s
+Change the number of seconds to delay between displays
+(prompt for new number).
+.It S
+Toggle the display of system processes.
+.It a
+Toggle the display of process titles.
+.It k
+Send a signal
+.Pq SIGKILL by default
+to a list of processes.
+This acts similarly to the command
+.Xr kill 1 .
+.It r
+Change the priority
+.Pq the Dq nice
+of a list of processes.
+This acts similarly to
+.Xr renice 8 .
+.It u
+Display only processes owned by a specific set of usernames (prompt for
+username).
+If the username specified is simply
+.Dq +
+or
+.Dq - ,
+then processes belonging to all users will be displayed.
+Usernames can be added
+to and removed from the set by prepending them with
+.Dq +
+and
+.Dq - ,
+respectively.
+.It o
+Change the order in which the display is sorted.
+The sort key names include
+.Dq cpu ,
+.Dq res ,
+.Dq size ,
+and
+.Dq time.
+The default is cpu.
+.It p
+Display a specific process (prompt for pid).
+If the pid specified is simply
+.Dq + ,
+then show all processes.
+.It e
+Display a list of system errors (if any) generated by the last
+command.
+.It H
+Toggle the display of threads.
+.It i or I
+Toggle the display of idle processes.
+.It j
+Toggle the display of
+.Xr jail 8
+ID.
+.It J
+Display only processes owned by a specific jail (prompt for jail).
+If the jail specified is simply
+.Dq + ,
+then processes belonging
+to all jails and the host will be displayed.
+This will also enable the display of JID.
+.It P
+Toggle the display of per-CPU statistics.
+.It T
+Toggle display of TID and PID
+.It t
+Toggle the display of the
+.Nm
+process.
+.It w
+Toggle the display of swap usage.
+.It z
+Toggle the display of the system idle process.
+.El
+.Sh "THE DISPLAY"
+The top few lines of the display show general information
+about the state of the system, including
+the last process id assigned to a process (on most systems),
+the three load averages,
+the current time,
+the number of existing processes,
+the number of processes in each state
+(sleeping, running, starting, zombies, and stopped),
+and a percentage of time spent in each of the processor states
+(user, nice, system, and idle).
+It also includes information about physical and virtual memory allocation.
+.Pp
+The remainder of the screen displays information about individual
+processes.
+This display is similar in spirit to
+.Xr ps 1
+but it is not exactly the same.
+PID is the process id,
+JID, when displayed, is the
+.Xr jail 8
+ID corresponding to the process,
+USERNAME is the name of the process's owner (if
+.Fl u
+is specified, a UID column will be substituted for USERNAME),
+PRI is the current priority of the process,
+NICE is the
+.Xr nice 1
+amount,
+SIZE is the total size of the process (text, data, and stack),
+RES is the current amount of resident memory,
+SWAP is the approximate amount of swap, if enabled
+(SIZE, RES and SWAP are given in kilobytes),
+STATE is the current state (one of
+.Dq START ,
+.Dq RUN
+(shown as
+.Dq CPUn
+on SMP systems),
+.Dq SLEEP ,
+.Dq STOP ,
+.Dq ZOMB ,
+.Dq WAIT ,
+.Dq LOCK ,
+or the event on which the process waits),
+C is the processor number on which the process is executing
+(visible only on SMP systems),
+TIME is the number of system and user cpu seconds that the process has used,
+WCPU, when displayed, is the weighted cpu percentage (this is the same
+value that
+.Xr ps 1
+displays as CPU),
+CPU is the raw percentage and is the field that is sorted to determine
+the order of the processes, and
+COMMAND is the name of the command that the process is currently running
+(if the process is swapped out, this column is marked
+.Dq <swapped> ) .
+.Pp
+If a process is in the
+.Dq SLEEP
+or
+.Dq LOCK
+state,
+the state column will report the name of the event or lock on which the
+process is waiting.
+Lock names are prefixed with an asterisk
+.Dq *
+while sleep events
+are not.
+.Sh DESCRIPTION OF MEMORY
+.Bd -literal
+Mem: 61M Active, 86M Inact, 368K Laundry, 22G Wired, 102G Free
+ARC: 15G Total, 9303M MFU, 6155M MRU, 1464K Anon, 98M Header, 35M Other
+ 15G Compressed, 27G Uncompressed, 1.75:1 Ratio, 174M Overhead
+Swap: 4096M Total, 532M Free, 13% Inuse, 80K In, 104K Out
+.Ed
+.Ss Physical Memory Stats
+.Bl -tag -width "Uncompressed" -compact
+.It Em Active
+number of bytes active
+.It Em Inact
+number of clean bytes inactive
+.It Em Laundry
+number of dirty bytes queued for laundering
+.It Em Wired
+number of bytes wired down, including IO-level cached file data pages
+.It Em Buf
+number of bytes used for IO-level disk caching
+.It Em Free
+number of bytes free
+.El
+.Ss ZFS ARC Stats
+These stats are only displayed when the ARC is in use.
+.Pp
+.Bl -tag -width "Uncompressed" -compact
+.It Em Total
+number of wired bytes used for the ZFS ARC
+.It Em MRU
+number of ARC bytes holding most recently used data
+.It Em MFU
+number of ARC bytes holding most frequently used data
+.It Em Anon
+number of ARC bytes holding in flight data
+.It Em Header
+number of ARC bytes holding headers
+.It Em Other
+miscellaneous ARC bytes
+.It Em Compressed
+bytes of memory used by ARC caches
+.It Em Uncompressed
+bytes of data stored in ARC caches before compression
+.It Em Ratio
+compression ratio of data cached in the ARC
+.El
+.Ss Swap Stats
+.Bl -tag -width "Uncompressed" -compact
+.It Em Total
+total available swap usage
+.It Em Free
+total free swap usage
+.It Em Inuse
+swap usage
+.It Em \&In
+bytes paged in from swap devices (last interval)
+.It Em Out
+bytes paged out to swap devices (last interval)
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width "Uncompressed"
+.It Ev TOP
+Default set of arguments to
+.Nm .
+.It Ev LC_CTYPE
+The locale to use when displaying the
+.Va argv
+vector when
+.Fl a
+flag is specified.
+.El
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr ps 1 ,
+.Xr stty 1 ,
+.Xr getrusage 2 ,
+.Xr humanize_number 3 ,
+.Xr mem 4 ,
+.Xr renice 8
+.Sh AUTHORS
+.An William LeFebvre, EECS Department, Northwestern University
+.Sh BUGS
+The command name for swapped processes should be tracked down, but this
+would make the program run slower.
+.Pp
+As with
+.Xr ps 1 ,
+things can change while
+.Nm
+is collecting information for an update.
+The picture it gives is only a close approximation to reality.
diff --git a/usr.bin/top/top.c b/usr.bin/top/top.c
new file mode 100644
index 000000000000..8712e56d43ba
--- /dev/null
+++ b/usr.bin/top/top.c
@@ -0,0 +1,1234 @@
+/*-
+ * Top users/processes display for Unix
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
+ * Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
+ * Copyright (c) 1996, William LeFebvre, Group sys Consulting
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/cdefs.h>
+#include <sys/limits.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/signal.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <jail.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "commands.h"
+#include "display.h" /* interface to display package */
+#include "screen.h" /* interface to screen package */
+#include "top.h"
+#include "machine.h"
+#include "utils.h"
+#include "username.h"
+
+/* Size of the stdio buffer given to stdout */
+#define Buffersize 2048
+
+char copyright[] =
+ "Copyright (c) 1984 through 1996, William LeFebvre";
+
+typedef void sigret_t;
+
+/* The buffer that stdio will use */
+static char stdoutbuf[Buffersize];
+
+static int fmt_flags = 0;
+int show_args = false;
+int pcpu_stats = false;
+
+/* signal handling routines */
+static sigret_t leave(int);
+static sigret_t tstop(int);
+static sigret_t top_winch(int);
+
+static volatile sig_atomic_t leaveflag;
+static volatile sig_atomic_t tstopflag;
+static volatile sig_atomic_t winchflag;
+
+/* values which need to be accessed by signal handlers */
+static int max_topn; /* maximum displayable processes */
+
+/* miscellaneous things */
+struct process_select ps;
+pid_t mypid;
+
+/* pointers to display routines */
+static void (*d_loadave)(int mpid, double *avenrun) = i_loadave;
+static void (*d_procstates)(int total, int *brkdn) = i_procstates;
+static void (*d_cpustates)(int *states) = i_cpustates;
+static void (*d_memory)(int *stats) = i_memory;
+static void (*d_arc)(int *stats) = i_arc;
+static void (*d_carc)(int *stats) = i_carc;
+static void (*d_swap)(int *stats) = i_swap;
+static void (*d_message)(void) = i_message;
+static void (*d_header)(const char *text) = i_header;
+static void (*d_process)(int line, char *thisline) = i_process;
+
+static void reset_display(void);
+
+static const struct option longopts[] = {
+ { "cpu-display-mode", no_argument, NULL, 'C' }, /* differs from orignal */
+ /* D reserved */
+ { "thread", no_argument, NULL, 'H' },
+ { "idle-procs", no_argument, NULL, 'I' },
+ { "jail", required_argument, NULL, 'J' },
+ { "per-cpu", no_argument, NULL, 'P' },
+ { "system-procs", no_argument, NULL, 'S' },
+ { "thread-id", no_argument, NULL, 'T' }, /* differs from orignal */
+ { "user", required_argument, NULL, 'U' },
+ { "all", no_argument, NULL, 'a' },
+ { "batch", no_argument, NULL, 'b' },
+ /* c reserved */
+ { "displays", required_argument, NULL, 'd' },
+ { "interactive", no_argument, NULL, 'i' },
+ { "jail-id", no_argument, NULL, 'j' },
+ { "display-mode", required_argument, NULL, 'm' },
+ /* n is identical to batch */
+ { "sort-order", required_argument, NULL, 'o' },
+ { "pid", required_argument, NULL, 'p' },
+ { "quick", no_argument, NULL, 'q' },
+ { "delay", required_argument, NULL, 's' },
+ { "threads", no_argument, NULL, 't' },
+ { "uids", no_argument, NULL, 'u' },
+ { "version", no_argument, NULL, 'v' },
+ { "swap", no_argument, NULL, 'w' },
+ { "system-idle-procs", no_argument, NULL, 'z' },
+ { NULL, 0, NULL, 0 }
+};
+
+static void
+reset_uids(void)
+{
+ for (size_t i = 0; i < TOP_MAX_UIDS; ++i)
+ ps.uid[i] = -1;
+}
+
+static int
+add_uid(int uid)
+{
+ size_t i = 0;
+
+ /* Add the uid if there's room */
+ for (; i < TOP_MAX_UIDS; ++i)
+ {
+ if (ps.uid[i] == -1 || ps.uid[i] == uid)
+ {
+ ps.uid[i] = uid;
+ break;
+ }
+ }
+
+ return (i == TOP_MAX_UIDS);
+}
+
+static void
+rem_uid(int uid)
+{
+ size_t i = 0;
+ size_t where = TOP_MAX_UIDS;
+
+ /* Look for the user to remove - no problem if it's not there */
+ for (; i < TOP_MAX_UIDS; ++i)
+ {
+ if (ps.uid[i] == -1)
+ break;
+ if (ps.uid[i] == uid)
+ where = i;
+ }
+
+ /* Make sure we don't leave a hole in the middle */
+ if (where != TOP_MAX_UIDS)
+ {
+ ps.uid[where] = ps.uid[i-1];
+ ps.uid[i-1] = -1;
+ }
+}
+
+static int
+handle_user(char *buf, size_t buflen)
+{
+ int rc = 0;
+ int uid = -1;
+ char *buf2 = buf;
+
+ new_message(MT_standout, "Username to show (+ for all): ");
+ if (readline(buf, buflen, false) <= 0)
+ {
+ clear_message();
+ return (rc);
+ }
+
+ if (buf[0] == '+' || buf[0] == '-')
+ {
+ if (buf[1] == '\0')
+ {
+ reset_uids();
+ goto end;
+ }
+ else
+ ++buf2;
+ }
+
+ if ((uid = userid(buf2)) == -1)
+ {
+ new_message(MT_standout, " %s: unknown user", buf2);
+ rc = 1;
+ goto end;
+ }
+
+ if (buf2 == buf)
+ {
+ reset_uids();
+ ps.uid[0] = uid;
+ goto end;
+ }
+
+ if (buf[0] == '+')
+ {
+ if (add_uid(uid))
+ {
+ new_message(MT_standout, " too many users, reset with '+'");
+ rc = 1;
+ goto end;
+ }
+ }
+ else
+ rem_uid(uid);
+
+end:
+ putchar('\r');
+ return (rc);
+}
+
+int
+main(int argc, const char *argv[])
+{
+ int i;
+ int active_procs;
+
+ struct system_info system_info;
+ struct statics statics;
+ void * processes;
+
+ static char tempbuf1[50];
+ static char tempbuf2[50];
+ sigset_t old_sigmask, new_sigmask;
+ int topn = Infinity;
+ struct timeval delay = { 2, 0 };
+ int displays = 0; /* indicates unspecified */
+ int sel_ret = 0;
+ time_t curr_time;
+ char *(*get_userid)(int) = username;
+ const char *uname_field = "USERNAME";
+ const char *header_text;
+ char *env_top;
+ const char **preset_argv;
+ int preset_argc = 0;
+ const char **av = NULL;
+ int ac = -1;
+ bool do_unames = true;
+ char interactive = 2;
+ char warnings = 0;
+ char topn_specified = false;
+ char ch;
+ char no_command = 1;
+ struct timeval timeout;
+ char *order_name = NULL;
+ int order_index = 0;
+ fd_set readfds;
+ char *nptr;
+
+ /* set the buffer for stdout */
+#ifdef DEBUG
+ extern FILE *debug;
+ debug = fopen("debug.run", "w");
+ setbuffer(stdout, NULL, 0);
+#else
+ setbuffer(stdout, stdoutbuf, Buffersize);
+#endif
+
+ if (setlocale(LC_ALL, "") == NULL) {
+ warnx("invalid locale, check your environment");
+ sleep(2);
+ }
+
+ mypid = getpid();
+
+ /* get our name */
+ /* initialize some selection options */
+ ps.idle = true;
+ ps.self = true;
+ ps.system = false;
+ reset_uids();
+ ps.thread = false;
+ ps.wcpu = 1;
+ ps.jid = -1;
+ ps.jail = false;
+ ps.swap = false;
+ ps.kidle = true;
+ ps.pid = -1;
+ ps.command = NULL;
+ ps.thread_id = false;
+
+ /* get preset options from the environment */
+ if ((env_top = getenv("TOP")) != NULL)
+ {
+ av = preset_argv = argparse(env_top, &preset_argc);
+ ac = preset_argc;
+
+ /* set the dummy argument to an explanatory message, in case
+ getopt encounters a bad argument */
+ preset_argv[0] = "while processing environment";
+ }
+
+ /* process options */
+ do {
+ /* if we're done doing the presets, then process the real arguments */
+ if (preset_argc == 0)
+ {
+ ac = argc;
+ av = argv;
+
+ /* this should keep getopt happy... */
+ optind = 1;
+ }
+
+ while ((i = getopt_long(ac, __DECONST(char * const *, av), "CSIHPabijJ:nquvzs:d:U:m:o:p:Ttw", longopts, NULL)) != EOF)
+ {
+ switch(i)
+ {
+ case 'v': /* show version number */
+ errx(0, "version FreeBSD");
+ break;
+
+ case 'u': /* toggle uid/username display */
+ do_unames = !do_unames;
+ break;
+
+ case 'U': /* display only username's processes */
+ if ((ps.uid[0] = userid(optarg)) == -1)
+ {
+ errx(1, "%s: unknown user\n", optarg);
+ }
+ break;
+
+ case 'S': /* show system processes */
+ ps.system = true;
+ break;
+
+ case 'I': /* show idle processes */
+ ps.idle = !ps.idle;
+ break;
+
+ case 'i': /* go interactive regardless */
+ interactive = 1;
+ break;
+
+ case 'n': /* batch, or non-interactive */
+ case 'b':
+ interactive = 0;
+ break;
+
+ case 'a':
+ fmt_flags ^= FMT_SHOWARGS;
+ break;
+
+ case 'd': /* number of displays to show */
+ if ((i = atoiwi(optarg)) == Invalid || i == 0)
+ {
+ warnx("warning: display count should be positive -- option ignored");
+ warnings++;
+ }
+ else
+ {
+ displays = i;
+ }
+ break;
+ case 'p': {
+ unsigned long long num;
+ const char *errstr;
+
+ num = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL || !find_pid(num)) {
+ fprintf(stderr, "%s: unknown pid\n", optarg);
+ exit(1);
+ }
+ ps.pid = (pid_t)num;
+ ps.system = true;
+ break;
+ }
+
+ case 's':
+ {
+ double delay_d = strtod(optarg, &nptr);
+ if (nptr == optarg)
+ {
+ warnx("warning: invalid delay");
+ warnings++;
+ }
+ else if (delay_d <= 0)
+ {
+ warnx("warning: seconds delay should be positive -- using default");
+ warnings++;
+ }
+ else
+ {
+ delay.tv_sec = delay_d;
+ delay.tv_usec = (delay_d - delay.tv_sec) * 1e6;
+ }
+ break;
+ }
+
+ case 'q': /* be quick about it */
+ errno = 0;
+ i = setpriority(PRIO_PROCESS, 0, PRIO_MIN);
+ if (i == -1 && errno != 0) {
+ warnx("warning: `-q' option failed (%m)");
+ warnings++;
+ }
+ break;
+
+ case 'm': /* select display mode */
+ if (strcmp(optarg, "io") == 0) {
+ displaymode = DISP_IO;
+ } else if (strcmp(optarg, "cpu") == 0) {
+ displaymode = DISP_CPU;
+ } else {
+ errx(1, "warning: `-m' option can only take args 'io' or 'cpu'");
+ }
+ break;
+
+ case 'o': /* select sort order */
+ order_name = optarg;
+ break;
+
+ case 't':
+ ps.self = !ps.self;
+ break;
+
+ case 'C':
+ ps.wcpu = !ps.wcpu;
+ break;
+
+ case 'H':
+ ps.thread = !ps.thread;
+ break;
+
+ case 'T':
+ ps.thread_id = !ps.thread_id;
+ break;
+
+ case 'j':
+ ps.jail = !ps.jail;
+ break;
+
+ case 'J': /* display only jail's processes */
+ if ((ps.jid = jail_getid(optarg)) == -1)
+ {
+ fprintf(stderr, "%s: unknown jail\n", optarg);
+ exit(1);
+ }
+ ps.jail = 1;
+ break;
+
+ case 'P':
+ pcpu_stats = !pcpu_stats;
+ break;
+
+ case 'w':
+ ps.swap = 1;
+ break;
+
+ case 'z':
+ ps.kidle = !ps.kidle;
+ break;
+
+ default:
+ errx(1,
+"[-abCHIijnPqStuvwz] [-d count] [-J jail] [-m cpu | io] [-o field]\n"
+" [-p pid] [-s time] [-U username] [number]");
+ }
+ }
+
+ /* get count of top processes to display (if any) */
+ if (optind < ac)
+ {
+ if ((topn = atoiwi(av[optind])) == Invalid)
+ {
+ warnx("warning: process display count should be non-negative -- using default");
+ warnings++;
+ }
+ else
+ {
+ topn_specified = true;
+ }
+ }
+
+ /* tricky: remember old value of preset_argc & set preset_argc = 0 */
+ i = preset_argc;
+ preset_argc = 0;
+
+ /* repeat only if we really did the preset arguments */
+ } while (i != 0);
+
+ /* set constants for username/uid display correctly */
+ if (!do_unames)
+ {
+ uname_field = " UID ";
+ get_userid = itoa7;
+ }
+
+ /* initialize the kernel memory interface */
+ if (machine_init(&statics) == -1)
+ {
+ exit(1);
+ }
+
+ /* determine sorting order index, if necessary */
+ if (order_name != NULL)
+ {
+ if ((order_index = string_index(order_name, statics.order_names)) == -1)
+ {
+ const char * const *pp;
+
+ warnx("'%s' is not a recognized sorting order.", order_name);
+ fprintf(stderr, "\tTry one of these:");
+ pp = statics.order_names;
+ while (*pp != NULL)
+ {
+ fprintf(stderr, " %s", *pp++);
+ }
+ fputc('\n', stderr);
+ exit(1);
+ }
+ }
+
+ /* initialize termcap */
+ init_termcap(interactive);
+
+ /* get the string to use for the process area header */
+ header_text = format_header(uname_field);
+
+ /* initialize display interface */
+ if ((max_topn = display_init(&statics)) == -1)
+ {
+ errx(4, "can't allocate sufficient memory");
+ }
+
+ /* print warning if user requested more processes than we can display */
+ if (topn > max_topn)
+ {
+ warnx("warning: this terminal can only display %d processes.", max_topn);
+ warnings++;
+ }
+
+ /* adjust for topn == Infinity */
+ if (topn == Infinity)
+ {
+ /*
+ * For smart terminals, infinity really means everything that can
+ * be displayed, or Largest.
+ * On dumb terminals, infinity means every process in the system!
+ * We only really want to do that if it was explicitly specified.
+ * This is always the case when "Default_TOPN != Infinity". But if
+ * topn wasn't explicitly specified and we are on a dumb terminal
+ * and the default is Infinity, then (and only then) we use
+ * "Nominal_TOPN" instead.
+ */
+ topn = smart_terminal ? Largest :
+ (topn_specified ? Largest : Nominal_TOPN);
+ }
+
+ /* set header display accordingly */
+ display_header(topn > 0);
+
+ /* determine interactive state */
+ if (interactive == 2)
+ {
+ interactive = smart_terminal;
+ }
+
+ /* if # of displays not specified, fill it in */
+ if (displays == 0)
+ {
+ displays = smart_terminal ? Infinity : 1;
+ }
+
+ /* hold interrupt signals while setting up the screen and the handlers */
+
+ sigemptyset(&new_sigmask);
+ sigaddset(&new_sigmask, SIGINT);
+ sigaddset(&new_sigmask, SIGQUIT);
+ sigaddset(&new_sigmask, SIGTSTP);
+ sigprocmask(SIG_BLOCK, &new_sigmask, &old_sigmask);
+ init_screen();
+ signal(SIGINT, leave);
+ signal(SIGQUIT, leave);
+ signal(SIGTSTP, tstop);
+ signal(SIGWINCH, top_winch);
+ sigprocmask(SIG_SETMASK, &old_sigmask, NULL);
+ if (warnings)
+ {
+ fputs("....", stderr);
+ fflush(stderr);
+ sleep(3 * warnings);
+ fputc('\n', stderr);
+ }
+
+restart:
+
+ /*
+ * main loop -- repeat while display count is positive or while it
+ * indicates infinity (by being -1)
+ */
+
+ while ((displays == -1) || (displays-- > 0))
+ {
+ int (*compare)(const void * const, const void * const);
+
+
+ /* get the current stats */
+ get_system_info(&system_info);
+
+ compare = compares[order_index];
+
+ /* get the current set of processes */
+ processes =
+ get_process_info(&system_info, &ps, compare);
+
+ /* display the load averages */
+ (*d_loadave)(system_info.last_pid,
+ system_info.load_avg);
+
+ /* display the battery info (if any) */
+ i_battery(statics.nbatteries, system_info.battery);
+
+ /* display the current time */
+ /* this method of getting the time SHOULD be fairly portable */
+ time(&curr_time);
+ i_uptime(&system_info.boottime, &curr_time);
+ i_timeofday(&curr_time);
+
+ /* display process state breakdown */
+ (*d_procstates)(system_info.p_total,
+ system_info.procstates);
+ (*d_cpustates)(system_info.cpustates);
+
+ /* display memory stats */
+ (*d_memory)(system_info.memory);
+ (*d_arc)(system_info.arc);
+ (*d_carc)(system_info.carc);
+
+ /* display swap stats */
+ (*d_swap)(system_info.swap);
+
+ /* handle message area */
+ (*d_message)();
+
+ /* update the header area */
+ (*d_header)(header_text);
+
+ if (topn > 0)
+ {
+ /* determine number of processes to actually display */
+ /* this number will be the smallest of: active processes,
+ number user requested, number current screen accommodates */
+ active_procs = system_info.p_pactive;
+ if (active_procs > topn)
+ {
+ active_procs = topn;
+ }
+ if (active_procs > max_topn)
+ {
+ active_procs = max_topn;
+ }
+
+ /* now show the top "n" processes. */
+ for (i = 0; i < active_procs; i++)
+ {
+ (*d_process)(i, format_next_process(processes, get_userid,
+ fmt_flags));
+ }
+ }
+ else
+ {
+ i = 0;
+ }
+
+ /* do end-screen processing */
+ u_endscreen(i);
+
+ /* now, flush the output buffer */
+ if (fflush(stdout) != 0)
+ {
+ new_message(MT_standout, " Write error on stdout");
+ putchar('\r');
+ quit(1);
+ }
+
+ /* only do the rest if we have more displays to show */
+ if (displays)
+ {
+ /* switch out for new display on smart terminals */
+ if (smart_terminal)
+ {
+ if (overstrike)
+ {
+ reset_display();
+ }
+ else
+ {
+ d_loadave = u_loadave;
+ d_procstates = u_procstates;
+ d_cpustates = u_cpustates;
+ d_memory = u_memory;
+ d_arc = u_arc;
+ d_carc = u_carc;
+ d_swap = u_swap;
+ d_message = u_message;
+ d_header = u_header;
+ d_process = u_process;
+ }
+ }
+
+ no_command = true;
+ if (!interactive)
+ {
+ timeout = delay;
+ select(0, NULL, NULL, NULL, &timeout);
+ if (leaveflag) {
+ end_screen();
+ exit(0);
+ }
+ }
+ else while (no_command)
+ {
+ /* assume valid command unless told otherwise */
+ no_command = false;
+
+ /* set up arguments for select with timeout */
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds); /* for standard input */
+ timeout = delay;
+
+ if (leaveflag) {
+ end_screen();
+ exit(0);
+ }
+
+ if (tstopflag) {
+ /* move to the lower left */
+ end_screen();
+ fflush(stdout);
+
+ /* default the signal handler action */
+ signal(SIGTSTP, SIG_DFL);
+
+ /* unblock the signal and send ourselves one */
+ sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
+ kill(0, SIGTSTP);
+
+ /* reset the signal handler */
+ signal(SIGTSTP, tstop);
+
+ /* reinit screen */
+ reinit_screen();
+ reset_display();
+ tstopflag = 0;
+ goto restart;
+ }
+
+ if (winchflag) {
+ /* reascertain the screen dimensions */
+ get_screensize();
+
+ /* tell display to resize */
+ max_topn = display_resize();
+
+ /* reset the signal handler */
+ signal(SIGWINCH, top_winch);
+
+ reset_display();
+ winchflag = 0;
+ goto restart;
+ }
+
+ /* wait for either input or the end of the delay period */
+ sel_ret = select(2, &readfds, NULL, NULL, &timeout);
+ if (sel_ret < 0 && errno != EINTR)
+ quit(0);
+ if (sel_ret > 0)
+ {
+ int newval;
+ const char *errmsg;
+ const struct command *cptr;
+
+ /* something to read -- clear the message area first */
+ clear_message();
+
+ /* now read it and convert to command strchr */
+ /* (use "change" as a temporary to hold strchr) */
+ if (read(0, &ch, 1) != 1)
+ {
+ /* read error: either 0 or -1 */
+ new_message(MT_standout, " Read error on stdin");
+ putchar('\r');
+ quit(1);
+ }
+ if (ch == '\r' || ch == '\n') {
+ continue;
+ }
+ cptr = all_commands;
+ while (cptr->c != '\0') {
+ if (cptr->c == ch) {
+ break;
+ }
+ cptr++;
+ }
+ if (cptr->c == '\0') {
+ new_message(MT_standout, " Command not understood");
+ putchar('\r');
+ no_command = true;
+ }
+ if (overstrike && !cptr->available_to_dumb)
+ {
+ new_message(MT_standout,
+ " Command cannot be handled by this terminal");
+ putchar('\r');
+ no_command = true;
+ }
+ if (!no_command) {
+ switch(cptr->id)
+ {
+ case CMD_redraw: /* redraw screen */
+ reset_display();
+ break;
+
+ case CMD_update: /* merely update display */
+ break;
+
+ case CMD_quit:
+ quit(0);
+ break;
+
+ case CMD_help:
+ reset_display();
+ top_clear();
+ show_help();
+ top_standout("Hit any key to continue: ");
+ fflush(stdout);
+ read(0, &ch, 1);
+ break;
+
+ case CMD_errors: /* show errors */
+ if (error_count() == 0)
+ {
+ new_message(MT_standout,
+ " Currently no errors to report.");
+ putchar('\r');
+ no_command = true;
+ }
+ else
+ {
+ reset_display();
+ top_clear();
+ show_errors();
+ top_standout("Hit any key to continue: ");
+ fflush(stdout);
+ read(0, &ch, 1);
+ }
+ break;
+
+ case CMD_number:
+ new_message(MT_standout,
+ "Number of processes to show: ");
+ newval = readline(tempbuf1, 8, true);
+ if (newval > -1)
+ {
+ if (newval > max_topn)
+ {
+ new_message(MT_standout | MT_delayed,
+ " This terminal can only display %d processes.",
+ max_topn);
+ putchar('\r');
+ }
+
+ if (newval == 0)
+ {
+ /* inhibit the header */
+ display_header(false);
+ }
+ else if (newval > topn && topn == 0)
+ {
+ /* redraw the header */
+ display_header(true);
+ d_header = i_header;
+ }
+ topn = newval;
+ }
+ break;
+
+ case CMD_delay: /* new seconds delay */
+ new_message(MT_standout, "Seconds to delay: ");
+ if ((i = readline(tempbuf1, 8, false)) > 0)
+ {
+ double delay_d = strtod(tempbuf1, &nptr);
+ if (nptr == tempbuf1 || delay_d <= 0)
+ {
+ new_message(MT_standout, " Invalid delay");
+ putchar('\r');
+ no_command = true;
+ }
+ else
+ {
+ delay.tv_sec = delay_d;
+ delay.tv_usec = (delay_d - delay.tv_sec) * 1e6;
+ clear_message();
+ }
+ }
+ break;
+
+ case CMD_grep: /* grep command name */
+ new_message(MT_standout,
+ "Grep command name (+ for all): ");
+ if (readline(tempbuf1, sizeof(tempbuf1), false) > 0) {
+ free(ps.command);
+ if (tempbuf1[0] == '+' && tempbuf1[1] == '\0') {
+ ps.command = NULL;
+ } else if ((ps.command = strdup(tempbuf1)) == NULL)
+ quit(1);
+ }
+ clear_message();
+ break;
+
+ case CMD_displays: /* change display count */
+ new_message(MT_standout,
+ "Displays to show (currently %s): ",
+ displays == -1 ? "infinite" :
+ itoa(displays));
+ if ((i = readline(tempbuf1, 10, true)) > 0)
+ {
+ displays = i;
+ }
+ else if (i == 0)
+ {
+ quit(0);
+ }
+ clear_message();
+ break;
+
+ case CMD_kill: /* kill program */
+ new_message(0, "kill ");
+ if (readline(tempbuf2, sizeof(tempbuf2), false) > 0)
+ {
+ if ((errmsg = kill_procs(tempbuf2)) != NULL)
+ {
+ new_message(MT_standout, "%s", errmsg);
+ putchar('\r');
+ no_command = true;
+ }
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_renice: /* renice program */
+ new_message(0, "renice ");
+ if (readline(tempbuf2, sizeof(tempbuf2), false) > 0)
+ {
+ if ((errmsg = renice_procs(tempbuf2)) != NULL)
+ {
+ new_message(MT_standout, "%s", errmsg);
+ putchar('\r');
+ no_command = true;
+ }
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_idletog:
+ ps.idle = !ps.idle;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying idle processes.",
+ ps.idle ? "D" : "Not d");
+ putchar('\r');
+ break;
+
+ case CMD_selftog:
+ ps.self = !ps.self;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying self.",
+ (ps.self) ? "D" : "Not d");
+ putchar('\r');
+ break;
+
+ case CMD_user:
+ if (handle_user(tempbuf2, sizeof(tempbuf2)))
+ no_command = true;
+ break;
+
+ case CMD_thrtog:
+ ps.thread = !ps.thread;
+ new_message(MT_standout | MT_delayed,
+ " Displaying threads %s",
+ ps.thread ? "separately" : "as a count");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+
+ case CMD_toggletid:
+ ps.thread_id = !ps.thread_id;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %s",
+ ps.thread_id ? "tid" : "pid");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+
+ case CMD_wcputog:
+ ps.wcpu = !ps.wcpu;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %s CPU",
+ ps.wcpu ? "weighted" : "raw");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_viewtog:
+ displaymode = displaymode == DISP_IO ? DISP_CPU : DISP_IO;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %s statistics.",
+ displaymode == DISP_IO ? "IO" : "CPU");
+ header_text = format_header(uname_field);
+ display_header(true);
+ d_header = i_header;
+ reset_display();
+ break;
+ case CMD_viewsys:
+ ps.system = !ps.system;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying system processes.",
+ ps.system ? "D" : "Not d");
+ break;
+ case CMD_showargs:
+ fmt_flags ^= FMT_SHOWARGS;
+ show_args = fmt_flags & FMT_SHOWARGS;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying process arguments.",
+ fmt_flags & FMT_SHOWARGS ? "D" : "Not d");
+ break;
+ case CMD_order:
+ new_message(MT_standout,
+ "Order to sort: ");
+ if (readline(tempbuf2, sizeof(tempbuf2), false) > 0)
+ {
+ if ((i = string_index(tempbuf2, statics.order_names)) == -1)
+ {
+ new_message(MT_standout,
+ " %s: unrecognized sorting order", tempbuf2);
+ no_command = true;
+ }
+ else
+ {
+ order_index = i;
+ }
+ putchar('\r');
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+ case CMD_jidtog:
+ ps.jail = !ps.jail;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying jail ID.",
+ ps.jail ? "D" : "Not d");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+
+ case CMD_jail:
+ new_message(MT_standout,
+ "Jail to show (+ for all): ");
+ if (readline(tempbuf2, sizeof(tempbuf2), false) > 0)
+ {
+ if (tempbuf2[0] == '+' &&
+ tempbuf2[1] == '\0')
+ {
+ ps.jid = -1;
+ }
+ else if ((i = jail_getid(tempbuf2)) == -1)
+ {
+ new_message(MT_standout,
+ " %s: unknown jail", tempbuf2);
+ no_command = true;
+ }
+ else
+ {
+ ps.jid = i;
+ }
+ if (ps.jail == 0) {
+ ps.jail = 1;
+ new_message(MT_standout |
+ MT_delayed, " Displaying jail "
+ "ID.");
+ header_text =
+ format_header(uname_field);
+ reset_display();
+ }
+ putchar('\r');
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_kidletog:
+ ps.kidle = !ps.kidle;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying system idle process.",
+ ps.kidle ? "D" : "Not d");
+ putchar('\r');
+ break;
+ case CMD_pcputog:
+ pcpu_stats = !pcpu_stats;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %sCPU statistics.",
+ pcpu_stats ? "per-" : "global ");
+ toggle_pcpustats();
+ max_topn = display_updatecpus(&statics);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_swaptog:
+ ps.swap = !ps.swap;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying per-process swap usage.",
+ ps.swap ? "D" : "Not d");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_pid:
+ new_message(MT_standout,
+ "Process id to show (+ for all): ");
+ if (readline(tempbuf2, sizeof(tempbuf2), false) > 0) {
+ if (tempbuf2[0] == '+' &&
+ tempbuf2[1] == '\0') {
+ ps.pid = (pid_t)-1;
+ } else {
+ unsigned long long num;
+ const char *errstr;
+
+ num = strtonum(tempbuf2, 0, INT_MAX,
+ &errstr);
+ if (errstr != NULL || !find_pid(num)) {
+ new_message(MT_standout,
+ " %s: unknown pid",
+ tempbuf2);
+ no_command = true;
+ } else {
+ ps.pid = (pid_t)num;
+ }
+ }
+ putchar('\r');
+ } else
+ clear_message();
+ break;
+ case CMD_NONE:
+ assert(false && "reached switch without command");
+ }
+ }
+ }
+
+ /* flush out stuff that may have been written */
+ fflush(stdout);
+ }
+ }
+ }
+
+#ifdef DEBUG
+ fclose(debug);
+#endif
+ quit(0);
+}
+
+/*
+ * reset_display() - reset all the display routine pointers so that entire
+ * screen will get redrawn.
+ */
+
+static void
+reset_display(void)
+{
+ d_loadave = i_loadave;
+ d_procstates = i_procstates;
+ d_cpustates = i_cpustates;
+ d_memory = i_memory;
+ d_arc = i_arc;
+ d_carc = i_carc;
+ d_swap = i_swap;
+ d_message = i_message;
+ d_header = i_header;
+ d_process = i_process;
+}
+
+/*
+ * signal handlers
+ */
+
+static sigret_t
+leave(int i __unused) /* exit under normal conditions -- INT handler */
+{
+
+ leaveflag = 1;
+}
+
+static sigret_t
+tstop(int i __unused) /* SIGTSTP handler */
+{
+
+ tstopflag = 1;
+}
+
+static sigret_t
+top_winch(int i __unused) /* SIGWINCH handler */
+{
+
+ winchflag = 1;
+}
+
+void __dead2
+quit(int status) /* exit under duress */
+{
+ end_screen();
+ exit(status);
+}
diff --git a/usr.bin/top/top.h b/usr.bin/top/top.h
new file mode 100644
index 000000000000..233f41c1dd38
--- /dev/null
+++ b/usr.bin/top/top.h
@@ -0,0 +1,67 @@
+/*-
+ * Top - a top users display for Berkeley Unix
+ */
+
+#ifndef TOP_H
+#define TOP_H
+
+#include <unistd.h>
+
+/* Number of lines of header information on the standard screen */
+extern int Header_lines;
+
+/* Special atoi routine returns either a non-negative number or one of: */
+#define Infinity -1
+#define Invalid -2
+
+/* maximum number we can have */
+#define Largest 0x7fffffff
+
+/* Exit code for system errors */
+#define TOP_EX_SYS_ERROR 23
+
+enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
+
+/*
+ * Format modifiers
+ */
+#define FMT_SHOWARGS 0x00000001
+
+extern enum displaymodes displaymode;
+
+extern int pcpu_stats;
+extern int overstrike;
+extern pid_t mypid;
+
+extern int (*compares[])(const void*, const void*);
+
+extern int show_args;
+
+const char* kill_procs(char *);
+const char* renice_procs(char *);
+
+extern char copyright[];
+
+void quit(int);
+
+/*
+ * The space command forces an immediate update. Sometimes, on loaded
+ * systems, this update will take a significant period of time (because all
+ * the output is buffered). So, if the short-term load average is above
+ * "LoadMax", then top will put the cursor home immediately after the space
+ * is pressed before the next update is attempted. This serves as a visual
+ * acknowledgement of the command.
+ */
+#define LoadMax 5.0
+
+/*
+ * "Nominal_TOPN" is used as the default TOPN when
+ * the output is a dumb terminal. If we didn't do this, then
+ * we will get every
+ * process in the system when running top on a dumb terminal (or redirected
+ * to a file). Note that Nominal_TOPN is a default: it can still be
+ * overridden on the command line, even with the value "infinity".
+ */
+#define Nominal_TOPN 18
+
+#endif /* TOP_H */
diff --git a/usr.bin/top/username.c b/usr.bin/top/username.c
new file mode 100644
index 000000000000..37ccfe60c3ef
--- /dev/null
+++ b/usr.bin/top/username.c
@@ -0,0 +1,134 @@
+/*
+ * Top users/processes display for Unix
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * Username translation code for top.
+ *
+ * These routines handle uid to username mapping.
+ * They use a hashing table scheme to reduce reading overhead.
+ * For the time being, these are very straightforward hashing routines.
+ * Maybe someday I'll put in something better. But with the advent of
+ * "random access" password files, it might not be worth the effort.
+ *
+ * Changes to these have been provided by John Gilmore (gnu@toad.com).
+ *
+ * The hash has been simplified in this release, to avoid the
+ * table overflow problems of previous releases. If the value
+ * at the initial hash location is not right, it is replaced
+ * by the right value. Collisions will cause us to call getpw*
+ * but hey, this is a cache, not the Library of Congress.
+ * This makes the table size independent of the passwd file size.
+ */
+
+#include <sys/param.h>
+
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+#include "username.h"
+
+struct hash_el {
+ int uid;
+ char name[MAXLOGNAME];
+};
+
+#define is_empty_hash(x) (hash_table[x].name[0] == 0)
+
+/* simple minded hashing function */
+#define hashit(i) (abs(i) % Table_size)
+
+/* K&R requires that statically declared tables be initialized to zero. */
+/* We depend on that for hash_table and YOUR compiler had BETTER do it! */
+static struct hash_el hash_table[Table_size];
+
+
+char *
+username(int uid)
+{
+ int hashindex;
+
+ hashindex = hashit(uid);
+ if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid))
+ {
+ /* not here or not right -- get it out of passwd */
+ hashindex = get_user(uid);
+ }
+ return(hash_table[hashindex].name);
+}
+
+int
+userid(char username_[])
+{
+ struct passwd *pwd;
+
+ /* Eventually we want this to enter everything in the hash table,
+ but for now we just do it simply and remember just the result.
+ */
+
+ if ((pwd = getpwnam(username_)) == NULL)
+ {
+ return(-1);
+ }
+
+ /* enter the result in the hash table */
+ enter_user(pwd->pw_uid, username_, 1);
+
+ /* return our result */
+ return(pwd->pw_uid);
+}
+
+/* wecare 1 = enter it always, 0 = nice to have */
+int
+enter_user(int uid, char name[], bool wecare)
+{
+ int hashindex;
+
+#ifdef DEBUG
+ fprintf(stderr, "enter_hash(%d, %s, %d)\n", uid, name, wecare);
+#endif
+
+ hashindex = hashit(uid);
+
+ if (!is_empty_hash(hashindex))
+ {
+ if (!wecare)
+ return (0); /* Don't clobber a slot for trash */
+ if (hash_table[hashindex].uid == uid)
+ return(hashindex); /* Fortuitous find */
+ }
+
+ /* empty or wrong slot -- fill it with new value */
+ hash_table[hashindex].uid = uid;
+ (void) strncpy(hash_table[hashindex].name, name, MAXLOGNAME - 1);
+ return(hashindex);
+}
+
+/*
+ * Get a userid->name mapping from the system.
+ */
+
+int
+get_user(int uid)
+{
+ struct passwd *pwd;
+
+ /* no performance penalty for using getpwuid makes it easy */
+ if ((pwd = getpwuid(uid)) != NULL)
+ {
+ return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
+ }
+
+ /* if we can't find the name at all, then use the uid as the name */
+ return(enter_user(uid, itoa7(uid), 1));
+}
diff --git a/usr.bin/top/username.h b/usr.bin/top/username.h
new file mode 100644
index 000000000000..3eca38bed4a8
--- /dev/null
+++ b/usr.bin/top/username.h
@@ -0,0 +1,30 @@
+/*
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ * Copyright (c) 2016, Randy Westlund
+ */
+#ifndef USERNAME_H
+#define USERNAME_H
+
+#include <stdbool.h>
+
+int enter_user(int uid, char *name, bool wecare);
+int get_user(int uid);
+void init_hash(void);
+char *username(int uid);
+int userid(char *username);
+
+/*
+ * "Table_size" defines the size of the hash tables used to map uid to
+ * username. The number of users in /etc/passwd CANNOT be greater than
+ * this number. If the error message "table overflow: too many users"
+ * is printed by top, then "Table_size" needs to be increased. Things will
+ * work best if the number is a prime number that is about twice the number
+ * of lines in /etc/passwd.
+ */
+#define Table_size 20011
+
+#endif /* USERNAME_H */
diff --git a/usr.bin/top/utils.c b/usr.bin/top/utils.c
new file mode 100644
index 000000000000..cde89a211b53
--- /dev/null
+++ b/usr.bin/top/utils.c
@@ -0,0 +1,329 @@
+/*
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 2018, Eitan Adler
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * This file contains various handy utilities used by top.
+ */
+
+#include "top.h"
+#include "utils.h"
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <libutil.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <kvm.h>
+
+int
+atoiwi(const char *str)
+{
+ size_t len;
+
+ len = strlen(str);
+ if (len != 0)
+ {
+ if (strncmp(str, "infinity", len) == 0 ||
+ strncmp(str, "all", len) == 0 ||
+ strncmp(str, "maximum", len) == 0)
+ {
+ return(Infinity);
+ }
+ else if (str[0] == '-')
+ {
+ return(Invalid);
+ }
+ else
+ {
+ return((int)strtol(str, NULL, 10));
+ }
+ }
+ return(0);
+}
+
+/*
+ * itoa - convert integer (decimal) to ascii string for positive numbers
+ * only (we don't bother with negative numbers since we know we
+ * don't use them).
+ */
+
+ /*
+ * How do we know that 16 will suffice?
+ * Because the biggest number that we will
+ * ever convert will be 2^32-1, which is 10
+ * digits.
+ */
+_Static_assert(sizeof(int) <= 4, "buffer too small for this sized int");
+
+char *
+itoa(unsigned int val)
+{
+ static char buffer[16]; /* result is built here */
+ /* 16 is sufficient since the largest number
+ we will ever convert will be 2^32-1,
+ which is 10 digits. */
+
+ sprintf(buffer, "%u", val);
+ return (buffer);
+}
+
+/*
+ * itoa7(val) - like itoa, except the number is right justified in a 7
+ * character field. This code is a duplication of itoa instead of
+ * a front end to a more general routine for efficiency.
+ */
+
+char *
+itoa7(int val)
+{
+ static char buffer[16]; /* result is built here */
+ /* 16 is sufficient since the largest number
+ we will ever convert will be 2^32-1,
+ which is 10 digits. */
+
+ sprintf(buffer, "%6u", val);
+ return (buffer);
+}
+
+/*
+ * digits(val) - return number of decimal digits in val. Only works for
+ * non-negative numbers.
+ */
+
+int __pure2
+digits(int val)
+{
+ int cnt = 0;
+ if (val == 0) {
+ return 1;
+ }
+
+ while (val > 0) {
+ cnt++;
+ val /= 10;
+ }
+ return(cnt);
+}
+
+/*
+ * string_index(string, array) - find string in array and return index
+ */
+
+int
+string_index(const char *string, const char * const *array)
+{
+ size_t i = 0;
+
+ while (*array != NULL)
+ {
+ if (strcmp(string, *array) == 0)
+ {
+ return(i);
+ }
+ array++;
+ i++;
+ }
+ return(-1);
+}
+
+/*
+ * argparse(line, cntp) - parse arguments in string "line", separating them
+ * out into an argv-like array, and setting *cntp to the number of
+ * arguments encountered. This is a simple parser that doesn't understand
+ * squat about quotes.
+ */
+
+const char **
+argparse(char *line, int *cntp)
+{
+ const char **ap;
+ static const char *argv[1024] = {0};
+
+ *cntp = 1;
+ ap = &argv[1];
+ while ((*ap = strsep(&line, " ")) != NULL) {
+ if (**ap != '\0') {
+ (*cntp)++;
+ if (*cntp >= (int)nitems(argv)) {
+ break;
+ }
+ ap++;
+ }
+ }
+ return (argv);
+}
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages i "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on for calculating cpu state percentages.
+ */
+
+long
+percentages(int cnt, int *out, long *new, long *old, long *diffs)
+{
+ int i;
+ long change;
+ long total_change;
+ long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
+
+/* format_time(seconds) - format number of seconds into a suitable
+ * display that will fit within 6 characters. Note that this
+ * routine builds its string in a static area. If it needs
+ * to be called more than once without overwriting previous data,
+ * then we will need to adopt a technique similar to the
+ * one used for format_k.
+ */
+
+/* Explanation:
+ We want to keep the output within 6 characters. For low values we use
+ the format mm:ss. For values that exceed 999:59, we switch to a format
+ that displays hours and fractions: hhh.tH. For values that exceed
+ 999.9, we use hhhh.t and drop the "H" designator. For values that
+ exceed 9999.9, we use "???".
+ */
+
+const char *
+format_time(long seconds)
+{
+ static char result[10];
+
+ /* sanity protection */
+ if (seconds < 0 || seconds > (99999l * 360l))
+ {
+ strcpy(result, " ???");
+ }
+ else if (seconds >= (1000l * 60l))
+ {
+ /* alternate (slow) method displaying hours and tenths */
+ sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l));
+
+ /* It is possible that the sprintf took more than 6 characters.
+ If so, then the "H" appears as result[6]. If not, then there
+ is a \0 in result[6]. Either way, it is safe to step on.
+ */
+ result[6] = '\0';
+ }
+ else
+ {
+ /* standard method produces MMM:SS */
+ sprintf(result, "%3ld:%02ld",
+ seconds / 60l, seconds % 60l);
+ }
+ return(result);
+}
+
+/*
+ * format_k(amt) - format a kilobyte memory value, returning a string
+ * suitable for display. Returns a pointer to a static
+ * area that changes each call. "amt" is converted to a fixed
+ * size humanize_number call
+ */
+
+/*
+ * Compromise time. We need to return a string, but we don't want the
+ * caller to have to worry about freeing a dynamically allocated string.
+ * Unfortunately, we can't just return a pointer to a static area as one
+ * of the common uses of this function is in a large call to sprintf where
+ * it might get invoked several times. Our compromise is to maintain an
+ * array of strings and cycle thru them with each invocation. We make the
+ * array large enough to handle the above mentioned case. The constant
+ * NUM_STRINGS defines the number of strings in this array: we can tolerate
+ * up to NUM_STRINGS calls before we start overwriting old information.
+ * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
+ * to convert the modulo operation into something quicker. What a hack!
+ */
+
+#define NUM_STRINGS 8
+
+char *
+format_k(int64_t amt)
+{
+ static char retarray[NUM_STRINGS][16];
+ static int index_ = 0;
+ char *ret;
+
+ ret = retarray[index_];
+ index_ = (index_ + 1) % NUM_STRINGS;
+ humanize_number(ret, 6, amt * 1024, "", HN_AUTOSCALE, HN_NOSPACE |
+ HN_B);
+ return (ret);
+}
+
+int
+find_pid(pid_t pid)
+{
+ kvm_t *kd = NULL;
+ struct kinfo_proc *pbase = NULL;
+ int nproc;
+ int ret = 0;
+
+ kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
+ if (kd == NULL) {
+ fprintf(stderr, "top: kvm_open() failed.\n");
+ quit(TOP_EX_SYS_ERROR);
+ }
+
+ pbase = kvm_getprocs(kd, KERN_PROC_PID, pid, &nproc);
+ if (pbase == NULL) {
+ goto done;
+ }
+
+ if ((nproc == 1) && (pbase->ki_pid == pid)) {
+ ret = 1;
+ }
+
+done:
+ kvm_close(kd);
+ return ret;
+}
diff --git a/usr.bin/top/utils.h b/usr.bin/top/utils.h
new file mode 100644
index 000000000000..a730e339d200
--- /dev/null
+++ b/usr.bin/top/utils.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Top users/processes display for Unix
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+#include <unistd.h>
+
+int atoiwi(const char *);
+char *itoa(unsigned int);
+char *itoa7(int);
+int digits(int);
+const char **argparse(char *, int *);
+long percentages(int, int *, long *, long *, long *);
+const char *format_time(long);
+char *format_k(int64_t);
+int string_index(const char *string, const char * const *array);
+int find_pid(pid_t pid);
+
diff --git a/usr.bin/touch/Makefile b/usr.bin/touch/Makefile
new file mode 100644
index 000000000000..2e9253ddac4c
--- /dev/null
+++ b/usr.bin/touch/Makefile
@@ -0,0 +1,7 @@
+.include <src.opts.mk>
+
+PROG= touch
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/touch/Makefile.depend b/usr.bin/touch/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/touch/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/touch/tests/Makefile b/usr.bin/touch/tests/Makefile
new file mode 100644
index 000000000000..543b682b96a0
--- /dev/null
+++ b/usr.bin/touch/tests/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= tests
+ATF_TESTS_SH= touch_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/touch/tests/Makefile.depend b/usr.bin/touch/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/touch/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/touch/tests/touch_test.sh b/usr.bin/touch/tests/touch_test.sh
new file mode 100644
index 000000000000..da39abef622e
--- /dev/null
+++ b/usr.bin/touch/tests/touch_test.sh
@@ -0,0 +1,157 @@
+#
+# Copyright (c) 2024 Dag-Erling Smørgrav
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+export TZ=UTC
+
+atf_check_mtime()
+{
+ local mtime=$1 filename=$2
+ atf_check -o inline:"$((mtime))\n" stat -f%m "$filename"
+}
+
+atf_test_case touch_none
+touch_none_head()
+{
+ atf_set descr "No arguments"
+}
+touch_none_body()
+{
+ atf_check -s exit:1 -e match:"^usage" touch
+}
+
+atf_test_case touch_one
+touch_one_head()
+{
+ atf_set descr "One argument"
+}
+touch_one_body()
+{
+ atf_check touch foo
+ atf_check test -f foo
+}
+
+atf_test_case touch_multiple
+touch_multiple_head()
+{
+ atf_set descr "Multiple arguments"
+}
+touch_multiple_body()
+{
+ atf_check touch foo bar baz
+ atf_check test -f foo -a -f bar -a -f baz
+}
+
+atf_test_case touch_absolute
+touch_absolute_head()
+{
+ atf_set descr "Absolute date / time"
+}
+touch_absolute_body()
+{
+ atf_check touch -t 7001010101 foo
+ atf_check_mtime 3660 foo
+ atf_check rm foo
+
+ atf_check touch -t 7001010101.01 foo
+ atf_check_mtime 3661 foo
+ atf_check rm foo
+
+ atf_check touch -t 196912312359 foo
+ atf_check_mtime -60 foo
+ atf_check rm foo
+
+ atf_check touch -t 196912312359.58 foo
+ atf_check_mtime -2 foo
+ atf_check rm foo
+
+ atf_check touch -t 196912312359.59 foo
+ atf_expect_fail "VFS interprets -1 as “do not setâ€"
+ atf_check_mtime -1 foo
+ atf_check rm foo
+
+ atf_check touch -d1969-12-31T23:59:58 foo
+ atf_check_mtime -2 foo
+ atf_check rm foo
+
+ atf_check touch -d1969-12-31\ 23:59:58 foo
+ atf_check_mtime -2 foo
+ atf_check rm foo
+
+ atf_check env TZ=CET touch -d1970-01-01T00:59:58 foo
+ atf_check_mtime -2 foo
+ atf_check rm foo
+
+ atf_check env TZ=CET touch -d1970-01-01T00:59:58Z foo
+ atf_check_mtime 3598 foo
+ atf_check rm foo
+
+ atf_check touch -d1969-12-31T23:59:59Z foo
+ atf_expect_fail "VFS interprets -1 as “do not setâ€"
+ atf_check_mtime -1 foo
+ atf_check rm foo
+}
+
+atf_test_case touch_relative
+touch_relative_head()
+{
+ atf_set descr "Relative date / time"
+}
+touch_relative_body()
+{
+ atf_check touch -t 202403241234.56 foo
+ atf_check_mtime 1711283696 foo
+ atf_check touch -A -36 foo
+ atf_check_mtime 1711283660 foo
+ atf_check touch -A -0100 foo
+ atf_check_mtime 1711283600 foo
+ atf_check touch -A -010000 foo
+ atf_check_mtime 1711280000 foo
+ atf_check touch -A 010136 foo
+ atf_check_mtime 1711283696 foo
+}
+
+atf_test_case touch_copy
+touch_copy_head()
+{
+ atf_set descr "Copy time from another file"
+}
+touch_copy_body()
+{
+ atf_check touch -t 202403241234.56 foo
+ atf_check_mtime 1711283696 foo
+ atf_check touch -t 7001010000 bar
+ atf_check_mtime 0 bar
+ atf_check touch -r foo bar
+ atf_check_mtime 1711283696 bar
+}
+
+atf_test_case touch_nocreate
+touch_nocreate_head()
+{
+ atf_set descr "Do not create file"
+}
+touch_nocreate_body()
+{
+ atf_check touch -t 202403241234.56 foo
+ atf_check_mtime 1711283696 foo
+ atf_check touch -c -t 7001010000 foo bar
+ atf_check_mtime 0 foo
+ atf_check -s exit:1 test -f bar
+ atf_check touch -c bar
+ atf_check -s exit:1 test -f bar
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case touch_none
+ atf_add_test_case touch_one
+ atf_add_test_case touch_multiple
+ atf_add_test_case touch_absolute
+ atf_add_test_case touch_relative
+ atf_add_test_case touch_copy
+ atf_add_test_case touch_nocreate
+ # TODO: add test cases for -a, -h, -m
+}
diff --git a/usr.bin/touch/touch.1 b/usr.bin/touch/touch.1
new file mode 100644
index 000000000000..623a387f304d
--- /dev/null
+++ b/usr.bin/touch/touch.1
@@ -0,0 +1,247 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 1, 2018
+.Dt TOUCH 1
+.Os
+.Sh NAME
+.Nm touch
+.Nd change file access and modification times
+.Sh SYNOPSIS
+.Nm
+.Op Fl A Ar [-][[hh]mm]SS
+.Op Fl achm
+.Op Fl r Ar file
+.Op Fl t Ar [[CC]YY]MMDDhhmm[.SS]
+.Op Fl d Ar YYYY-MM-DDThh:mm:SS[.frac][tz]
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility sets the modification and access times of files.
+If any file does not exist, it is created with default permissions.
+.Pp
+By default,
+.Nm
+changes both modification and access times.
+The
+.Fl a
+and
+.Fl m
+flags may be used to select the access time or the modification time
+individually.
+Selecting both is equivalent to the default.
+By default, the timestamps are set to the current time.
+The
+.Fl d
+and
+.Fl t
+flags explicitly specify a different time, and the
+.Fl r
+flag specifies to set the times those of the specified file.
+The
+.Fl A
+flag adjusts the values by a specified amount.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl A
+Adjust the access and modification time stamps for the file by the
+specified value.
+This flag is intended for use in modifying files with incorrectly set
+time stamps.
+.Pp
+The argument is of the form
+.Dq [-][[hh]mm]SS
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Ar -
+Make the adjustment negative: the new time stamp is set to be before
+the old one.
+.It Ar hh
+The number of hours, from 00 to 99.
+.It Ar mm
+The number of minutes, from 00 to 59.
+.It Ar SS
+The number of seconds, from 00 to 59.
+.El
+.Pp
+The
+.Fl A
+flag implies the
+.Fl c
+flag: if any file specified does not exist, it will be silently ignored.
+.It Fl a
+Change the access time of the file.
+The modification time of the file is not changed unless the
+.Fl m
+flag is also specified.
+.It Fl c
+Do not create the file if it does not exist.
+The
+.Nm
+utility does not treat this as an error.
+No error messages are displayed and the exit value is not affected.
+.It Fl d
+Change the access and modification times to the specified date time instead
+of the current time of day.
+The argument is of the form
+.Dq YYYY-MM-DDThh:mm:SS[.frac][tz]
+where the letters represent the following:
+.Bl -tag -width Ds -compact -offset indent
+.It Ar YYYY
+At least four decimal digits representing the year.
+.It Ar MM , Ar DD , Ar hh , Ar mm , Ar SS
+As with
+.Fl t
+time.
+.It Ar T
+The letter
+.Li T
+or a space is the time designator.
+.It Ar .frac
+An optional fraction, consisting of a period or a comma followed by one or
+more digits.
+The number of significant digits depends on the kernel configuration and the
+filesystem, and may be zero.
+.It Ar tz
+An optional letter
+.Li Z
+indicating the time is in
+.Tn UTC .
+Otherwise, the time is assumed to be in local time.
+Local time is affected by the value of the
+.Ev TZ
+environment variable.
+.El
+.It Fl h
+If the file is a symbolic link, change the times of the link
+itself rather than the file that the link points to.
+Note that
+.Fl h
+implies
+.Fl c
+and thus will not create any new files.
+.It Fl m
+Change the modification time of the file.
+The access time of the file is not changed unless the
+.Fl a
+flag is also specified.
+.It Fl r
+Use the access and modifications times from the specified file
+instead of the current time of day.
+.It Fl t
+Change the access and modification times to the specified time instead
+of the current time of day.
+The argument is of the form
+.Dq [[CC]YY]MMDDhhmm[.SS]
+where each pair of letters represents the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Ar CC
+The first two digits of the year (the century).
+.It Ar YY
+The second two digits of the year.
+If
+.Dq YY
+is specified, but
+.Dq CC
+is not, a value for
+.Dq YY
+between 69 and 99 results in a
+.Dq CC
+value of 19.
+Otherwise, a
+.Dq CC
+value of 20 is used.
+.It Ar MM
+The month of the year, from 01 to 12.
+.It Ar DD
+the day of the month, from 01 to 31.
+.It Ar hh
+The hour of the day, from 00 to 23.
+.It Ar mm
+The minute of the hour, from 00 to 59.
+.It Ar SS
+The second of the minute, from 00 to 60.
+.El
+.Pp
+If the
+.Dq CC
+and
+.Dq YY
+letter pairs are not specified, the values default to the current
+year.
+If the
+.Dq SS
+letter pair is not specified, the value defaults to 0.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh COMPATIBILITY
+The obsolescent form of
+.Nm ,
+where a time format is specified as the first argument, is supported.
+When no
+.Fl r
+or
+.Fl t
+option is specified, there are at least two arguments, and the first
+argument is a string of digits either eight or ten characters in length,
+the first argument is interpreted as a time specification of the form
+.Dq MMDDhhmm[YY] .
+.Pp
+The
+.Dq MM ,
+.Dq DD ,
+.Dq hh
+and
+.Dq mm
+letter pairs are treated as their counterparts specified to the
+.Fl t
+option.
+If the
+.Dq YY
+letter pair is in the range 39 to 99, the year is set to 1939 to 1999,
+otherwise, the year is set in the 21st century.
+.Sh SEE ALSO
+.Xr utimensat 2
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2
+specification.
+.Sh HISTORY
+A
+.Nm
+utility appeared in
+.At v7 .
diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c
new file mode 100644
index 000000000000..70257e320a60
--- /dev/null
+++ b/usr.bin/touch/touch.c
@@ -0,0 +1,407 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static void stime_arg1(const char *, struct timespec *);
+static void stime_arg2(const char *, int, struct timespec *);
+static void stime_darg(const char *, struct timespec *);
+static void stime_file(const char *, struct timespec *);
+static int timeoffset(const char *);
+static void usage(const char *);
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ struct timespec ts[2];
+ int atflag;
+ int Aflag, aflag, cflag, mflag, ch, fd, len, rval, timeset;
+ char *p;
+ char *myname;
+
+ myname = basename(argv[0]);
+ Aflag = aflag = cflag = mflag = timeset = 0;
+ atflag = 0;
+ ts[0].tv_sec = ts[1].tv_sec = 0;
+ ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW;
+
+ while ((ch = getopt(argc, argv, "A:acd:fhmr:t:")) != -1)
+ switch(ch) {
+ case 'A':
+ Aflag = timeoffset(optarg);
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ timeset = 1;
+ stime_darg(optarg, ts);
+ break;
+ case 'f':
+ /* No-op for compatibility. */
+ break;
+ case 'h':
+ cflag = 1;
+ atflag = AT_SYMLINK_NOFOLLOW;
+ break;
+ case 'm':
+ mflag = 1;
+ break;
+ case 'r':
+ timeset = 1;
+ stime_file(optarg, ts);
+ break;
+ case 't':
+ timeset = 1;
+ stime_arg1(optarg, ts);
+ break;
+ default:
+ usage(myname);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (aflag == 0 && mflag == 0)
+ aflag = mflag = 1;
+
+ if (timeset) {
+ if (Aflag) {
+ /*
+ * We're setting the time to an offset from a specified
+ * time. God knows why, but it means that we can set
+ * that time once and for all here.
+ */
+ if (aflag)
+ ts[0].tv_sec += Aflag;
+ if (mflag)
+ ts[1].tv_sec += Aflag;
+ Aflag = 0; /* done our job */
+ }
+ } else {
+ /*
+ * If no -r or -t flag, at least two operands, the first of
+ * which is an 8 or 10 digit number, use the obsolete time
+ * specification, otherwise use the current time.
+ */
+ if (argc > 1) {
+ strtol(argv[0], &p, 10);
+ len = p - argv[0];
+ if (*p == '\0' && (len == 8 || len == 10)) {
+ timeset = 1;
+ stime_arg2(*argv++, len == 10, ts);
+ }
+ }
+ /* Both times default to the same. */
+ ts[1] = ts[0];
+ }
+
+ if (!aflag)
+ ts[0].tv_nsec = UTIME_OMIT;
+ if (!mflag)
+ ts[1].tv_nsec = UTIME_OMIT;
+
+ if (*argv == NULL)
+ usage(myname);
+
+ if (Aflag)
+ cflag = 1;
+
+ for (rval = 0; *argv; ++argv) {
+ /* See if the file exists. */
+ if (fstatat(AT_FDCWD, *argv, &sb, atflag) != 0) {
+ if (errno != ENOENT) {
+ rval = 1;
+ warn("%s", *argv);
+ continue;
+ }
+ if (!cflag) {
+ /* Create the file. */
+ fd = open(*argv,
+ O_WRONLY | O_CREAT, DEFFILEMODE);
+ if (fd == -1) {
+ rval = 1;
+ warn("%s", *argv);
+ continue;
+ }
+ if (fstat(fd, &sb) < 0) {
+ warn("%s", *argv);
+ rval = 1;
+ }
+ if (close(fd) < 0) {
+ warn("%s", *argv);
+ rval = 1;
+ }
+
+ /* If using the current time, we're done. */
+ if (!timeset)
+ continue;
+ } else
+ continue;
+ }
+
+ /*
+ * We're adjusting the times based on the file times, not a
+ * specified time (that gets handled above).
+ */
+ if (Aflag) {
+ if (aflag) {
+ ts[0] = sb.st_atim;
+ ts[0].tv_sec += Aflag;
+ }
+ if (mflag) {
+ ts[1] = sb.st_mtim;
+ ts[1].tv_sec += Aflag;
+ }
+ }
+
+ if (!utimensat(AT_FDCWD, *argv, ts, atflag))
+ continue;
+
+ rval = 1;
+ warn("%s", *argv);
+ }
+ exit(rval);
+}
+
+#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
+
+static void
+stime_arg1(const char *arg, struct timespec *tvp)
+{
+ time_t now;
+ struct tm *t;
+ int yearset;
+ char *p;
+
+ now = time(NULL);
+ if ((t = localtime(&now)) == NULL)
+ err(1, "localtime");
+ /* [[CC]YY]MMDDhhmm[.SS] */
+ if ((p = strchr(arg, '.')) == NULL)
+ t->tm_sec = 0; /* Seconds defaults to 0. */
+ else {
+ if (strlen(p + 1) != 2)
+ goto terr;
+ *p++ = '\0';
+ t->tm_sec = ATOI2(p);
+ }
+
+ yearset = 0;
+ switch (strlen(arg)) {
+ case 12: /* CCYYMMDDhhmm */
+ t->tm_year = ATOI2(arg);
+ t->tm_year *= 100;
+ yearset = 1;
+ /* FALLTHROUGH */
+ case 10: /* YYMMDDhhmm */
+ if (yearset) {
+ yearset = ATOI2(arg);
+ t->tm_year += yearset;
+ } else {
+ yearset = ATOI2(arg);
+ if (yearset < 69)
+ t->tm_year = yearset + 2000;
+ else
+ t->tm_year = yearset + 1900;
+ }
+ t->tm_year -= 1900; /* Convert to UNIX time. */
+ /* FALLTHROUGH */
+ case 8: /* MMDDhhmm */
+ t->tm_mon = ATOI2(arg);
+ --t->tm_mon; /* Convert from 01-12 to 00-11 */
+ t->tm_mday = ATOI2(arg);
+ t->tm_hour = ATOI2(arg);
+ t->tm_min = ATOI2(arg);
+ break;
+ default:
+ goto terr;
+ }
+
+ t->tm_isdst = -1; /* Figure out DST. */
+ t->tm_yday = -1;
+ tvp[0].tv_sec = tvp[1].tv_sec = mktime(t);
+ if (t->tm_yday == -1)
+ goto terr;
+
+ tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
+ return;
+
+terr:
+ errx(1, "out of range or illegal time specification: "
+ "[[CC]YY]MMDDhhmm[.SS]");
+}
+
+static void
+stime_arg2(const char *arg, int year, struct timespec *tvp)
+{
+ time_t now;
+ struct tm *t;
+
+ now = time(NULL);
+ if ((t = localtime(&now)) == NULL)
+ err(1, "localtime");
+
+ t->tm_mon = ATOI2(arg); /* MMDDhhmm[yy] */
+ --t->tm_mon; /* Convert from 01-12 to 00-11 */
+ t->tm_mday = ATOI2(arg);
+ t->tm_hour = ATOI2(arg);
+ t->tm_min = ATOI2(arg);
+ if (year) {
+ t->tm_year = ATOI2(arg);
+ if (t->tm_year < 39) /* support 2000-2038 not 1902-1969 */
+ t->tm_year += 100;
+ }
+
+ t->tm_isdst = -1; /* Figure out DST. */
+ t->tm_yday = -1;
+ tvp[0].tv_sec = tvp[1].tv_sec = mktime(t);
+ if (t->tm_yday == -1)
+ errx(1, "out of range or illegal time specification: "
+ "MMDDhhmm[yy]");
+
+ tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
+}
+
+static void
+stime_darg(const char *arg, struct timespec *tvp)
+{
+ struct tm t = { .tm_sec = 0 };
+ const char *fmt, *colon;
+ char *p;
+ int val, isutc = 0;
+
+ tvp[0].tv_nsec = 0;
+ t.tm_isdst = -1;
+ colon = strchr(arg, ':');
+ if (colon == NULL || strchr(colon + 1, ':') == NULL)
+ goto bad;
+ fmt = strchr(arg, 'T') != NULL ? "%Y-%m-%dT%H:%M:%S" :
+ "%Y-%m-%d %H:%M:%S";
+ p = strptime(arg, fmt, &t);
+ if (p == NULL)
+ goto bad;
+ /* POSIX: must have at least one digit after dot */
+ if ((*p == '.' || *p == ',') && isdigit((unsigned char)p[1])) {
+ p++;
+ val = 100000000;
+ while (isdigit((unsigned char)*p)) {
+ tvp[0].tv_nsec += val * (*p - '0');
+ p++;
+ val /= 10;
+ }
+ }
+ if (*p == 'Z') {
+ isutc = 1;
+ p++;
+ }
+ if (*p != '\0')
+ goto bad;
+
+ t.tm_yday = -1;
+ tvp[0].tv_sec = isutc ? timegm(&t) : mktime(&t);
+ if (t.tm_yday == -1)
+ goto bad;
+
+ tvp[1] = tvp[0];
+ return;
+
+bad:
+ errx(1, "out of range or illegal time specification: "
+ "YYYY-MM-DDThh:mm:SS[.frac][tz]");
+}
+
+/* Calculate a time offset in seconds, given an arg of the format [-]HHMMSS. */
+int
+timeoffset(const char *arg)
+{
+ int offset;
+ int isneg;
+
+ offset = 0;
+ isneg = *arg == '-';
+ if (isneg)
+ arg++;
+ switch (strlen(arg)) {
+ default: /* invalid */
+ errx(1, "Invalid offset spec, must be [-][[HH]MM]SS");
+
+ case 6: /* HHMMSS */
+ offset = ATOI2(arg);
+ /* FALLTHROUGH */
+ case 4: /* MMSS */
+ offset = offset * 60 + ATOI2(arg);
+ /* FALLTHROUGH */
+ case 2: /* SS */
+ offset = offset * 60 + ATOI2(arg);
+ }
+ if (isneg)
+ return (-offset);
+ else
+ return (offset);
+}
+
+static void
+stime_file(const char *fname, struct timespec *tsp)
+{
+ struct stat sb;
+
+ if (stat(fname, &sb))
+ err(1, "%s", fname);
+ tsp[0] = sb.st_atim;
+ tsp[1] = sb.st_mtim;
+}
+
+static void
+usage(const char *myname)
+{
+ fprintf(stderr, "usage: %s [-A [-][[hh]mm]SS] [-achm] [-r file] "
+ "[-t [[CC]YY]MMDDhhmm[.SS]]\n"
+ " [-d YYYY-MM-DDThh:mm:SS[.frac][tz]] "
+ "file ...\n", myname);
+ exit(1);
+}
diff --git a/usr.bin/tr/Makefile b/usr.bin/tr/Makefile
new file mode 100644
index 000000000000..d789e500c237
--- /dev/null
+++ b/usr.bin/tr/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+PROG= tr
+SRCS= cmap.c cset.c str.c tr.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tr/Makefile.depend b/usr.bin/tr/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/tr/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tr/cmap.c b/usr.bin/tr/cmap.c
new file mode 100644
index 000000000000..3789a91ced88
--- /dev/null
+++ b/usr.bin/tr/cmap.c
@@ -0,0 +1,212 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/*
+ * "Character map" ADT. Stores mappings between pairs of characters in a
+ * splay tree, with a lookup table cache to simplify looking up the first
+ * bunch of characters (which are presumably more common than others).
+ */
+
+#include <sys/cdefs.h>
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "cmap.h"
+
+static struct cmapnode *cmap_splay(struct cmapnode *, wint_t);
+
+/*
+ * cmap_alloc --
+ * Allocate a character map.
+ */
+struct cmap *
+cmap_alloc(void)
+{
+ struct cmap *cm;
+
+ cm = malloc(sizeof(*cm));
+ if (cm == NULL)
+ return (NULL);
+ cm->cm_root = NULL;
+ cm->cm_def = CM_DEF_SELF;
+ cm->cm_havecache = false;
+ cm->cm_min = cm->cm_max = 0;
+ return (cm);
+}
+
+/*
+ * cmap_add --
+ * Add a mapping from "from" to "to" to the map.
+ */
+bool
+cmap_add(struct cmap *cm, wint_t from, wint_t to)
+{
+ struct cmapnode *cmn, *ncmn;
+
+ cm->cm_havecache = false;
+
+ if (cm->cm_root == NULL) {
+ cmn = malloc(sizeof(*cmn));
+ if (cmn == NULL)
+ return (false);
+ cmn->cmn_from = from;
+ cmn->cmn_to = to;
+ cmn->cmn_left = cmn->cmn_right = NULL;
+ cm->cm_root = cmn;
+ cm->cm_min = cm->cm_max = from;
+ return (true);
+ }
+
+ cmn = cm->cm_root = cmap_splay(cm->cm_root, from);
+
+ if (cmn->cmn_from == from) {
+ cmn->cmn_to = to;
+ return (true);
+ }
+
+ ncmn = malloc(sizeof(*ncmn));
+ if (ncmn == NULL)
+ return (false);
+ ncmn->cmn_from = from;
+ ncmn->cmn_to = to;
+ if (from < cmn->cmn_from) {
+ ncmn->cmn_left = cmn->cmn_left;
+ ncmn->cmn_right = cmn;
+ cmn->cmn_left = NULL;
+ } else {
+ ncmn->cmn_right = cmn->cmn_right;
+ ncmn->cmn_left = cmn;
+ cmn->cmn_right = NULL;
+ }
+ if (from < cm->cm_min)
+ cm->cm_min = from;
+ if (from > cm->cm_max)
+ cm->cm_max = from;
+ cm->cm_root = ncmn;
+
+ return (true);
+}
+
+/*
+ * cmap_lookup_hard --
+ * Look up the mapping for a character without using the cache.
+ */
+wint_t
+cmap_lookup_hard(struct cmap *cm, wint_t ch)
+{
+
+ if (cm->cm_root != NULL) {
+ cm->cm_root = cmap_splay(cm->cm_root, ch);
+ if (cm->cm_root->cmn_from == ch)
+ return (cm->cm_root->cmn_to);
+ }
+ return (cm->cm_def == CM_DEF_SELF ? ch : cm->cm_def);
+}
+
+/*
+ * cmap_cache --
+ * Update the cache.
+ */
+void
+cmap_cache(struct cmap *cm)
+{
+ wint_t ch;
+
+ for (ch = 0; ch < CM_CACHE_SIZE; ch++)
+ cm->cm_cache[ch] = cmap_lookup_hard(cm, ch);
+
+ cm->cm_havecache = true;
+}
+
+/*
+ * cmap_default --
+ * Change the value that characters without mappings map to, and
+ * return the old value. The special character value CM_MAP_SELF
+ * means characters map to themselves.
+ */
+wint_t
+cmap_default(struct cmap *cm, wint_t def)
+{
+ wint_t old;
+
+ old = cm->cm_def;
+ cm->cm_def = def;
+ cm->cm_havecache = false;
+ return (old);
+}
+
+static struct cmapnode *
+cmap_splay(struct cmapnode *t, wint_t ch)
+{
+ struct cmapnode N, *l, *r, *y;
+
+ /*
+ * Based on public domain code from Sleator.
+ */
+
+ assert(t != NULL);
+
+ N.cmn_left = N.cmn_right = NULL;
+ l = r = &N;
+ for (;;) {
+ if (ch < t->cmn_from) {
+ if (t->cmn_left != NULL &&
+ ch < t->cmn_left->cmn_from) {
+ y = t->cmn_left;
+ t->cmn_left = y->cmn_right;
+ y->cmn_right = t;
+ t = y;
+ }
+ if (t->cmn_left == NULL)
+ break;
+ r->cmn_left = t;
+ r = t;
+ t = t->cmn_left;
+ } else if (ch > t->cmn_from) {
+ if (t->cmn_right != NULL &&
+ ch > t->cmn_right->cmn_from) {
+ y = t->cmn_right;
+ t->cmn_right = y->cmn_left;
+ y->cmn_left = t;
+ t = y;
+ }
+ if (t->cmn_right == NULL)
+ break;
+ l->cmn_right = t;
+ l = t;
+ t = t->cmn_right;
+ } else
+ break;
+ }
+ l->cmn_right = t->cmn_left;
+ r->cmn_left = t->cmn_right;
+ t->cmn_left = N.cmn_right;
+ t->cmn_right = N.cmn_left;
+ return (t);
+}
diff --git a/usr.bin/tr/cmap.h b/usr.bin/tr/cmap.h
new file mode 100644
index 000000000000..6bcae292c02c
--- /dev/null
+++ b/usr.bin/tr/cmap.h
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 CMAP_H
+#define CMAP_H
+
+#include <limits.h>
+#include <stdbool.h>
+#include <wchar.h>
+
+struct cmapnode {
+ wint_t cmn_from;
+ wint_t cmn_to;
+ struct cmapnode *cmn_left;
+ struct cmapnode *cmn_right;
+};
+
+struct cmap {
+#define CM_CACHE_SIZE 128
+ wint_t cm_cache[CM_CACHE_SIZE];
+ bool cm_havecache;
+ struct cmapnode *cm_root;
+#define CM_DEF_SELF -2
+ wint_t cm_def;
+ wint_t cm_min;
+ wint_t cm_max;
+};
+
+struct cmap * cmap_alloc(void);
+bool cmap_add(struct cmap *, wint_t, wint_t);
+wint_t cmap_lookup_hard(struct cmap *, wint_t);
+void cmap_cache(struct cmap *);
+wint_t cmap_default(struct cmap *, wint_t);
+
+static __inline wint_t
+cmap_lookup(struct cmap *cm, wint_t from)
+{
+
+ if (from < CM_CACHE_SIZE && cm->cm_havecache)
+ return (cm->cm_cache[from]);
+ return (cmap_lookup_hard(cm, from));
+}
+
+static __inline wint_t
+cmap_min(struct cmap *cm)
+{
+
+ return (cm->cm_min);
+}
+
+static __inline wint_t
+cmap_max(struct cmap *cm)
+{
+
+ return (cm->cm_max);
+}
+
+#endif
diff --git a/usr.bin/tr/cset.c b/usr.bin/tr/cset.c
new file mode 100644
index 000000000000..3fc20a977915
--- /dev/null
+++ b/usr.bin/tr/cset.c
@@ -0,0 +1,290 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/*
+ * "Set of characters" ADT implemented as a splay tree of extents, with
+ * a lookup table cache to simplify looking up the first bunch of
+ * characters (which are presumably more common than others).
+ */
+
+#include <sys/cdefs.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "cset.h"
+
+static struct csnode * cset_delete(struct csnode *, wchar_t);
+static __inline int cset_rangecmp(struct csnode *, wchar_t);
+static struct csnode * cset_splay(struct csnode *, wchar_t);
+
+/*
+ * cset_alloc --
+ * Allocate a set of characters.
+ */
+struct cset *
+cset_alloc(void)
+{
+ struct cset *cs;
+
+ if ((cs = malloc(sizeof(*cs))) == NULL)
+ return (NULL);
+ cs->cs_root = NULL;
+ cs->cs_classes = NULL;
+ cs->cs_havecache = false;
+ cs->cs_invert = false;
+ return (cs);
+}
+
+/*
+ * cset_add --
+ * Add a character to the set.
+ */
+bool
+cset_add(struct cset *cs, wchar_t ch)
+{
+ struct csnode *csn, *ncsn;
+ wchar_t oval;
+
+ cs->cs_havecache = false;
+
+ /*
+ * Inserting into empty tree; new item becomes the root.
+ */
+ if (cs->cs_root == NULL) {
+ csn = malloc(sizeof(*cs->cs_root));
+ if (csn == NULL)
+ return (false);
+ csn->csn_left = csn->csn_right = NULL;
+ csn->csn_min = csn->csn_max = ch;
+ cs->cs_root = csn;
+ return (true);
+ }
+
+ /*
+ * Splay to check whether the item already exists, and otherwise,
+ * where we should put it.
+ */
+ csn = cs->cs_root = cset_splay(cs->cs_root, ch);
+
+ /*
+ * Avoid adding duplicate nodes.
+ */
+ if (cset_rangecmp(csn, ch) == 0)
+ return (true);
+
+ /*
+ * Allocate a new node and make it the new root.
+ */
+ ncsn = malloc(sizeof(*ncsn));
+ if (ncsn == NULL)
+ return (false);
+ ncsn->csn_min = ncsn->csn_max = ch;
+ if (cset_rangecmp(csn, ch) < 0) {
+ ncsn->csn_left = csn->csn_left;
+ ncsn->csn_right = csn;
+ csn->csn_left = NULL;
+ } else {
+ ncsn->csn_right = csn->csn_right;
+ ncsn->csn_left = csn;
+ csn->csn_right = NULL;
+ }
+ cs->cs_root = ncsn;
+
+ /*
+ * Coalesce with left and right neighbours if possible.
+ */
+ if (ncsn->csn_left != NULL) {
+ ncsn->csn_left = cset_splay(ncsn->csn_left, ncsn->csn_min - 1);
+ if (ncsn->csn_left->csn_max == ncsn->csn_min - 1) {
+ oval = ncsn->csn_left->csn_min;
+ ncsn->csn_left = cset_delete(ncsn->csn_left,
+ ncsn->csn_left->csn_min);
+ ncsn->csn_min = oval;
+ }
+ }
+ if (ncsn->csn_right != NULL) {
+ ncsn->csn_right = cset_splay(ncsn->csn_right,
+ ncsn->csn_max + 1);
+ if (ncsn->csn_right->csn_min == ncsn->csn_max + 1) {
+ oval = ncsn->csn_right->csn_max;
+ ncsn->csn_right = cset_delete(ncsn->csn_right,
+ ncsn->csn_right->csn_min);
+ ncsn->csn_max = oval;
+ }
+ }
+
+ return (true);
+}
+
+/*
+ * cset_in_hard --
+ * Determine whether a character is in the set without using
+ * the cache.
+ */
+bool
+cset_in_hard(struct cset *cs, wchar_t ch)
+{
+ struct csclass *csc;
+
+ for (csc = cs->cs_classes; csc != NULL; csc = csc->csc_next)
+ if (csc->csc_invert ^ (iswctype(ch, csc->csc_type) != 0))
+ return (cs->cs_invert ^ true);
+ if (cs->cs_root != NULL) {
+ cs->cs_root = cset_splay(cs->cs_root, ch);
+ return (cs->cs_invert ^ (cset_rangecmp(cs->cs_root, ch) == 0));
+ }
+ return (cs->cs_invert ^ false);
+}
+
+/*
+ * cset_cache --
+ * Update the cache.
+ */
+void
+cset_cache(struct cset *cs)
+{
+ wchar_t i;
+
+ for (i = 0; i < CS_CACHE_SIZE; i++)
+ cs->cs_cache[i] = cset_in_hard(cs, i);
+
+ cs->cs_havecache = true;
+}
+
+/*
+ * cset_invert --
+ * Invert the character set.
+ */
+void
+cset_invert(struct cset *cs)
+{
+
+ cs->cs_invert ^= true;
+ cs->cs_havecache = false;
+}
+
+/*
+ * cset_addclass --
+ * Add a wctype()-style character class to the set, optionally
+ * inverting it.
+ */
+bool
+cset_addclass(struct cset *cs, wctype_t type, bool invert)
+{
+ struct csclass *csc;
+
+ csc = malloc(sizeof(*csc));
+ if (csc == NULL)
+ return (false);
+ csc->csc_type = type;
+ csc->csc_invert = invert;
+ csc->csc_next = cs->cs_classes;
+ cs->cs_classes = csc;
+ cs->cs_havecache = false;
+ return (true);
+}
+
+static __inline int
+cset_rangecmp(struct csnode *t, wchar_t ch)
+{
+
+ if (ch < t->csn_min)
+ return (-1);
+ if (ch > t->csn_max)
+ return (1);
+ return (0);
+}
+
+static struct csnode *
+cset_splay(struct csnode *t, wchar_t ch)
+{
+ struct csnode N, *l, *r, *y;
+
+ /*
+ * Based on public domain code from Sleator.
+ */
+
+ assert(t != NULL);
+
+ N.csn_left = N.csn_right = NULL;
+ l = r = &N;
+ for (;;) {
+ if (cset_rangecmp(t, ch) < 0) {
+ if (t->csn_left != NULL &&
+ cset_rangecmp(t->csn_left, ch) < 0) {
+ y = t->csn_left;
+ t->csn_left = y->csn_right;
+ y->csn_right = t;
+ t = y;
+ }
+ if (t->csn_left == NULL)
+ break;
+ r->csn_left = t;
+ r = t;
+ t = t->csn_left;
+ } else if (cset_rangecmp(t, ch) > 0) {
+ if (t->csn_right != NULL &&
+ cset_rangecmp(t->csn_right, ch) > 0) {
+ y = t->csn_right;
+ t->csn_right = y->csn_left;
+ y->csn_left = t;
+ t = y;
+ }
+ if (t->csn_right == NULL)
+ break;
+ l->csn_right = t;
+ l = t;
+ t = t->csn_right;
+ } else
+ break;
+ }
+ l->csn_right = t->csn_left;
+ r->csn_left = t->csn_right;
+ t->csn_left = N.csn_right;
+ t->csn_right = N.csn_left;
+ return (t);
+}
+
+static struct csnode *
+cset_delete(struct csnode *t, wchar_t ch)
+{
+ struct csnode *x;
+
+ assert(t != NULL);
+ t = cset_splay(t, ch);
+ assert(cset_rangecmp(t, ch) == 0);
+ if (t->csn_left == NULL)
+ x = t->csn_right;
+ else {
+ x = cset_splay(t->csn_left, ch);
+ x->csn_right = t->csn_right;
+ }
+ free(t);
+ return x;
+}
diff --git a/usr.bin/tr/cset.h b/usr.bin/tr/cset.h
new file mode 100644
index 000000000000..e03897e70f8d
--- /dev/null
+++ b/usr.bin/tr/cset.h
@@ -0,0 +1,74 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 CSET_H
+#define CSET_H
+
+#include <stdbool.h>
+#include <wchar.h>
+#include <wctype.h>
+
+struct csnode {
+ wchar_t csn_min;
+ wchar_t csn_max;
+ struct csnode *csn_left;
+ struct csnode *csn_right;
+};
+
+struct csclass {
+ wctype_t csc_type;
+ bool csc_invert;
+ struct csclass *csc_next;
+};
+
+struct cset {
+#define CS_CACHE_SIZE 256
+ bool cs_cache[CS_CACHE_SIZE];
+ bool cs_havecache;
+ struct csclass *cs_classes;
+ struct csnode *cs_root;
+ bool cs_invert;
+};
+
+bool cset_addclass(struct cset *, wctype_t, bool);
+struct cset * cset_alloc(void);
+bool cset_add(struct cset *, wchar_t);
+void cset_invert(struct cset *);
+bool cset_in_hard(struct cset *, wchar_t);
+void cset_cache(struct cset *);
+
+static __inline bool
+cset_in(struct cset *cs, wchar_t ch)
+{
+
+ if (ch < CS_CACHE_SIZE && cs->cs_havecache)
+ return (cs->cs_cache[ch]);
+ return (cset_in_hard(cs, ch));
+}
+
+#endif /* CSET_H */
diff --git a/usr.bin/tr/extern.h b/usr.bin/tr/extern.h
new file mode 100644
index 000000000000..1a0de52ade66
--- /dev/null
+++ b/usr.bin/tr/extern.h
@@ -0,0 +1,50 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+#include <limits.h>
+
+#define NCHARS_SB (UCHAR_MAX + 1) /* Number of single-byte characters. */
+#define OOBCH -1 /* Out of band character value. */
+
+typedef struct {
+ enum { STRING1, STRING2 } which;
+ enum { EOS, INFINITE, NORMAL, RANGE, SEQUENCE,
+ CCLASS, CCLASS_UPPER, CCLASS_LOWER, SET } state;
+ int cnt; /* character count */
+ wint_t lastch; /* last character */
+ wctype_t cclass; /* character class from wctype() */
+ wint_t equiv[NCHARS_SB]; /* equivalence set */
+ wint_t *set; /* set of characters */
+ char *str; /* user's string */
+} STR;
+
+wint_t next(STR *);
+int charcoll(const void *, const void *);
diff --git a/usr.bin/tr/str.c b/usr.bin/tr/str.c
new file mode 100644
index 000000000000..db7d8d2e7986
--- /dev/null
+++ b/usr.bin/tr/str.c
@@ -0,0 +1,383 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "extern.h"
+
+static int backslash(STR *, int *);
+static int bracket(STR *);
+static void genclass(STR *);
+static void genequiv(STR *);
+static int genrange(STR *, int);
+static void genseq(STR *);
+
+wint_t
+next(STR *s)
+{
+ int is_octal;
+ wint_t ch;
+ wchar_t wch;
+ size_t clen;
+
+ switch (s->state) {
+ case EOS:
+ return (0);
+ case INFINITE:
+ return (1);
+ case NORMAL:
+ switch (*s->str) {
+ case '\0':
+ s->state = EOS;
+ return (0);
+ case '\\':
+ s->lastch = backslash(s, &is_octal);
+ break;
+ case '[':
+ if (bracket(s))
+ return (next(s));
+ /* FALLTHROUGH */
+ default:
+ clen = mbrtowc(&wch, s->str, MB_LEN_MAX, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2 ||
+ clen == 0)
+ errc(1, EILSEQ, NULL);
+ is_octal = 0;
+ s->lastch = wch;
+ s->str += clen;
+ break;
+ }
+
+ /* We can start a range at any time. */
+ if (s->str[0] == '-' && genrange(s, is_octal))
+ return (next(s));
+ return (1);
+ case RANGE:
+ if (s->cnt-- == 0) {
+ s->state = NORMAL;
+ return (next(s));
+ }
+ ++s->lastch;
+ return (1);
+ case SEQUENCE:
+ if (s->cnt-- == 0) {
+ s->state = NORMAL;
+ return (next(s));
+ }
+ return (1);
+ case CCLASS:
+ case CCLASS_UPPER:
+ case CCLASS_LOWER:
+ s->cnt++;
+ ch = nextwctype(s->lastch, s->cclass);
+ if (ch == -1) {
+ s->state = NORMAL;
+ return (next(s));
+ }
+ s->lastch = ch;
+ return (1);
+ case SET:
+ if ((ch = s->set[s->cnt++]) == OOBCH) {
+ s->state = NORMAL;
+ return (next(s));
+ }
+ s->lastch = ch;
+ return (1);
+ default:
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+static int
+bracket(STR *s)
+{
+ char *p;
+
+ switch (s->str[1]) {
+ case ':': /* "[:class:]" */
+ if ((p = strchr(s->str + 2, ']')) == NULL)
+ return (0);
+ if (*(p - 1) != ':' || p - s->str < 4)
+ goto repeat;
+ *(p - 1) = '\0';
+ s->str += 2;
+ genclass(s);
+ s->str = p + 1;
+ return (1);
+ case '=': /* "[=equiv=]" */
+ if (s->str[2] == '\0' || (p = strchr(s->str + 3, ']')) == NULL)
+ return (0);
+ if (*(p - 1) != '=' || p - s->str < 4)
+ goto repeat;
+ s->str += 2;
+ genequiv(s);
+ return (1);
+ default: /* "[\###*n]" or "[#*n]" */
+ repeat:
+ if ((p = strpbrk(s->str + 2, "*]")) == NULL)
+ return (0);
+ if (p[0] != '*' || strchr(p, ']') == NULL)
+ return (0);
+ s->str += 1;
+ genseq(s);
+ return (1);
+ }
+ /* NOTREACHED */
+}
+
+static void
+genclass(STR *s)
+{
+
+ if ((s->cclass = wctype(s->str)) == 0)
+ errx(1, "unknown class %s", s->str);
+ s->cnt = 0;
+ s->lastch = -1; /* incremented before check in next() */
+ if (strcmp(s->str, "upper") == 0)
+ s->state = CCLASS_UPPER;
+ else if (strcmp(s->str, "lower") == 0)
+ s->state = CCLASS_LOWER;
+ else
+ s->state = CCLASS;
+}
+
+static void
+genequiv(STR *s)
+{
+ int i, p, pri;
+ char src[2], dst[3];
+ size_t clen;
+ wchar_t wc;
+
+ if (*s->str == '\\') {
+ s->equiv[0] = backslash(s, NULL);
+ if (*s->str != '=')
+ errx(1, "misplaced equivalence equals sign");
+ s->str += 2;
+ } else {
+ clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2 || clen == 0)
+ errc(1, EILSEQ, NULL);
+ s->equiv[0] = wc;
+ if (s->str[clen] != '=')
+ errx(1, "misplaced equivalence equals sign");
+ s->str += clen + 2;
+ }
+
+ /*
+ * Calculate the set of all characters in the same equivalence class
+ * as the specified character (they will have the same primary
+ * collation weights).
+ * XXX Knows too much about how strxfrm() is implemented. Assumes
+ * it fills the string with primary collation weight bytes. Only one-
+ * to-one mappings are supported.
+ * XXX Equivalence classes not supported in multibyte locales.
+ */
+ src[0] = (char)s->equiv[0];
+ src[1] = '\0';
+ if (MB_CUR_MAX == 1 && strxfrm(dst, src, sizeof(dst)) == 1) {
+ pri = (unsigned char)*dst;
+ for (p = 1, i = 1; i < NCHARS_SB; i++) {
+ *src = i;
+ if (strxfrm(dst, src, sizeof(dst)) == 1 && pri &&
+ pri == (unsigned char)*dst)
+ s->equiv[p++] = i;
+ }
+ s->equiv[p] = OOBCH;
+ }
+
+ s->cnt = 0;
+ s->state = SET;
+ s->set = s->equiv;
+}
+
+static int
+genrange(STR *s, int was_octal)
+{
+ int stopval, octal;
+ char *savestart;
+ int n, cnt, *p;
+ size_t clen;
+ wchar_t wc;
+
+ octal = 0;
+ savestart = s->str;
+ if (*++s->str == '\\')
+ stopval = backslash(s, &octal);
+ else {
+ clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ errc(1, EILSEQ, NULL);
+ stopval = wc;
+ s->str += clen;
+ }
+ /*
+ * XXX Characters are not ordered according to collating sequence in
+ * multibyte locales.
+ */
+ if (octal || was_octal || MB_CUR_MAX > 1) {
+ if (stopval < s->lastch) {
+ s->str = savestart;
+ return (0);
+ }
+ s->cnt = stopval - s->lastch + 1;
+ s->state = RANGE;
+ --s->lastch;
+ return (1);
+ }
+ if (charcoll((const void *)&stopval, (const void *)&(s->lastch)) < 0) {
+ s->str = savestart;
+ return (0);
+ }
+ if ((s->set = p = malloc((NCHARS_SB + 1) * sizeof(int))) == NULL)
+ err(1, "genrange() malloc");
+ for (cnt = 0; cnt < NCHARS_SB; cnt++)
+ if (charcoll((const void *)&cnt, (const void *)&(s->lastch)) >= 0 &&
+ charcoll((const void *)&cnt, (const void *)&stopval) <= 0)
+ *p++ = cnt;
+ *p = OOBCH;
+ n = p - s->set;
+
+ s->cnt = 0;
+ s->state = SET;
+ if (n > 1)
+ mergesort(s->set, n, sizeof(*(s->set)), charcoll);
+ return (1);
+}
+
+static void
+genseq(STR *s)
+{
+ char *ep;
+ wchar_t wc;
+ size_t clen;
+
+ if (s->which == STRING1)
+ errx(1, "sequences only valid in string2");
+
+ if (*s->str == '\\')
+ s->lastch = backslash(s, NULL);
+ else {
+ clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ errc(1, EILSEQ, NULL);
+ s->lastch = wc;
+ s->str += clen;
+ }
+ if (*s->str != '*')
+ errx(1, "misplaced sequence asterisk");
+
+ switch (*++s->str) {
+ case '\\':
+ s->cnt = backslash(s, NULL);
+ break;
+ case ']':
+ s->cnt = 0;
+ ++s->str;
+ break;
+ default:
+ if (isdigit((u_char)*s->str)) {
+ s->cnt = strtol(s->str, &ep, 0);
+ if (*ep == ']') {
+ s->str = ep + 1;
+ break;
+ }
+ }
+ errx(1, "illegal sequence count");
+ /* NOTREACHED */
+ }
+
+ s->state = s->cnt ? SEQUENCE : INFINITE;
+}
+
+/*
+ * Translate \??? into a character. Up to 3 octal digits, if no digits either
+ * an escape code or a literal character.
+ */
+static int
+backslash(STR *s, int *is_octal)
+{
+ int ch, cnt, val;
+
+ if (is_octal != NULL)
+ *is_octal = 0;
+ for (cnt = val = 0;;) {
+ ch = (u_char)*++s->str;
+ if (!isdigit(ch) || ch > '7')
+ break;
+ val = val * 8 + ch - '0';
+ if (++cnt == 3) {
+ ++s->str;
+ break;
+ }
+ }
+ if (cnt) {
+ if (is_octal != NULL)
+ *is_octal = 1;
+ return (val);
+ }
+ if (ch != '\0')
+ ++s->str;
+ switch (ch) {
+ case 'a': /* escape characters */
+ return ('\7');
+ case 'b':
+ return ('\b');
+ case 'f':
+ return ('\f');
+ case 'n':
+ return ('\n');
+ case 'r':
+ return ('\r');
+ case 't':
+ return ('\t');
+ case 'v':
+ return ('\13');
+ case '\0': /* \" -> \ */
+ s->state = EOS;
+ return ('\\');
+ default: /* \x" -> x */
+ return (ch);
+ }
+}
diff --git a/usr.bin/tr/tests/Makefile b/usr.bin/tr/tests/Makefile
new file mode 100644
index 000000000000..ed2d548b8277
--- /dev/null
+++ b/usr.bin/tr/tests/Makefile
@@ -0,0 +1,23 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.00.out
+${PACKAGE}FILES+= regress.01.out
+${PACKAGE}FILES+= regress.02.out
+${PACKAGE}FILES+= regress.03.out
+${PACKAGE}FILES+= regress.04.out
+${PACKAGE}FILES+= regress.05.out
+${PACKAGE}FILES+= regress.06.out
+${PACKAGE}FILES+= regress.07.out
+${PACKAGE}FILES+= regress.08.out
+${PACKAGE}FILES+= regress.09.out
+${PACKAGE}FILES+= regress.0a.out
+${PACKAGE}FILES+= regress.0b.out
+${PACKAGE}FILES+= regress.0c.out
+${PACKAGE}FILES+= regress.0d.out
+${PACKAGE}FILES+= regress.in
+${PACKAGE}FILES+= regress.sh
+${PACKAGE}FILES+= regress2.in
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tr/tests/Makefile.depend b/usr.bin/tr/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tr/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tr/tests/legacy_test.sh b/usr.bin/tr/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/tr/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/tr/tests/regress.00.out b/usr.bin/tr/tests/regress.00.out
new file mode 100644
index 000000000000..5a7d1c7c11a1
--- /dev/null
+++ b/usr.bin/tr/tests/regress.00.out
@@ -0,0 +1,4 @@
+qui3k 2rown
+fox jump54
+ov5r th5 l1zy
+4og
diff --git a/usr.bin/tr/tests/regress.01.out b/usr.bin/tr/tests/regress.01.out
new file mode 100644
index 000000000000..5252b480a520
--- /dev/null
+++ b/usr.bin/tr/tests/regress.01.out
@@ -0,0 +1,4 @@
+quick brown
+fox jumped
+over the lazy
+dog
diff --git a/usr.bin/tr/tests/regress.02.out b/usr.bin/tr/tests/regress.02.out
new file mode 100644
index 000000000000..67a6dea8adb2
--- /dev/null
+++ b/usr.bin/tr/tests/regress.02.out
@@ -0,0 +1,4 @@
+quik brown
+fox jumpd
+ovr th lzy
+do
diff --git a/usr.bin/tr/tests/regress.03.out b/usr.bin/tr/tests/regress.03.out
new file mode 100644
index 000000000000..c18e3cf5b6a9
--- /dev/null
+++ b/usr.bin/tr/tests/regress.03.out
@@ -0,0 +1,4 @@
+QUICK BROWN
+FOX JUMPED
+OVER THE LAZY
+DOG
diff --git a/usr.bin/tr/tests/regress.04.out b/usr.bin/tr/tests/regress.04.out
new file mode 100644
index 000000000000..c01413cfb141
--- /dev/null
+++ b/usr.bin/tr/tests/regress.04.out
@@ -0,0 +1,4 @@
+..... .....
+... ......
+.... ... ....
+...
diff --git a/usr.bin/tr/tests/regress.05.out b/usr.bin/tr/tests/regress.05.out
new file mode 100644
index 000000000000..5252b480a520
--- /dev/null
+++ b/usr.bin/tr/tests/regress.05.out
@@ -0,0 +1,4 @@
+quick brown
+fox jumped
+over the lazy
+dog
diff --git a/usr.bin/tr/tests/regress.06.out b/usr.bin/tr/tests/regress.06.out
new file mode 100644
index 000000000000..5ca0a4fe6f5c
--- /dev/null
+++ b/usr.bin/tr/tests/regress.06.out
@@ -0,0 +1,9 @@
+??? bottles of beer on the wall, ??? bottles of beer.
+Take one down and pass it around - ?? bottles of beer on the wall.
+?? bottles of beer on the wall, ?? bottles of beer.
+Take one down and pass it around - ?? bottles of beer on the wall.
+...
+? bottles of beer on the wall, ? bottles of beer!!!
+Take one down and pass it around - ? bottle of beer on the wall.
+? bottle of beer on the wall, ? bottle of beer!!!
+Take it down and pass it around - NO MORE bottles of beer on the wall!!!
diff --git a/usr.bin/tr/tests/regress.07.out b/usr.bin/tr/tests/regress.07.out
new file mode 100644
index 000000000000..999fe478f92c
--- /dev/null
+++ b/usr.bin/tr/tests/regress.07.out
@@ -0,0 +1,9 @@
+### ####### ## #### ## ### ####, ### ####### ## ####.
+#### ### #### ### #### ## ###### - ## ####### ## #### ## ### ####.
+## ####### ## #### ## ### ####, ## ####### ## ####.
+#### ### #### ### #### ## ###### - ## ####### ## #### ## ### ####.
+...
+# ####### ## #### ## ### ####, # ####### ## ####!!!
+#### ### #### ### #### ## ###### - # ###### ## #### ## ### ####.
+# ###### ## #### ## ### ####, # ###### ## ####!!!
+#### ## #### ### #### ## ###### - ## #### ####### ## #### ## ### ####!!!
diff --git a/usr.bin/tr/tests/regress.08.out b/usr.bin/tr/tests/regress.08.out
new file mode 100644
index 000000000000..34abcc1d8b0a
--- /dev/null
+++ b/usr.bin/tr/tests/regress.08.out
@@ -0,0 +1,9 @@
+100,100.
+-99.
+99,99.
+-98.
+...
+2,2!!!
+-1.
+1,1!!!
+-!!!
diff --git a/usr.bin/tr/tests/regress.09.out b/usr.bin/tr/tests/regress.09.out
new file mode 100644
index 000000000000..2419e3a77139
--- /dev/null
+++ b/usr.bin/tr/tests/regress.09.out
@@ -0,0 +1 @@
+?#
diff --git a/usr.bin/tr/tests/regress.0a.out b/usr.bin/tr/tests/regress.0a.out
new file mode 100644
index 000000000000..e703f63ac459
--- /dev/null
+++ b/usr.bin/tr/tests/regress.0a.out
@@ -0,0 +1 @@
+$?$$$$$$$$
diff --git a/usr.bin/tr/tests/regress.0b.out b/usr.bin/tr/tests/regress.0b.out
new file mode 100644
index 000000000000..8d26586ca775
--- /dev/null
+++ b/usr.bin/tr/tests/regress.0b.out
@@ -0,0 +1 @@
+100befbeeea100befbeeaeedadaad99befbeeea99befbeeea99befbeeaeedadaad98befbeeea2befbeeea2befbeeaeedadaad1befbeeea1befbeeea1befbeeaedadaadEbefbeeea
diff --git a/usr.bin/tr/tests/regress.0c.out b/usr.bin/tr/tests/regress.0c.out
new file mode 100644
index 000000000000..4e125eaadb4f
--- /dev/null
+++ b/usr.bin/tr/tests/regress.0c.out
@@ -0,0 +1 @@
+[[[[
diff --git a/usr.bin/tr/tests/regress.0d.out b/usr.bin/tr/tests/regress.0d.out
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/usr.bin/tr/tests/regress.0d.out
@@ -0,0 +1 @@
+
diff --git a/usr.bin/tr/tests/regress.in b/usr.bin/tr/tests/regress.in
new file mode 100644
index 000000000000..5252b480a520
--- /dev/null
+++ b/usr.bin/tr/tests/regress.in
@@ -0,0 +1,4 @@
+quick brown
+fox jumped
+over the lazy
+dog
diff --git a/usr.bin/tr/tests/regress.sh b/usr.bin/tr/tests/regress.sh
new file mode 100644
index 000000000000..ea8313c7ca58
--- /dev/null
+++ b/usr.bin/tr/tests/regress.sh
@@ -0,0 +1,21 @@
+
+echo 1..14
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`00', `tr abcde 12345 <${SRCDIR}/regress.in')
+REGRESSION_TEST(`01', `tr 12345 abcde <${SRCDIR}/regress.in')
+REGRESSION_TEST(`02', `tr -d aceg <${SRCDIR}/regress.in')
+REGRESSION_TEST(`03', `tr "[[:lower:]]" "[[:upper:]]" <${SRCDIR}/regress.in')
+REGRESSION_TEST(`04', `tr "[[:alpha:]]" . <${SRCDIR}/regress.in')
+REGRESSION_TEST(`05', `tr "[[:lower:]]" "[[:upper:]]" <${SRCDIR}/regress.in | tr "[[:upper:]]" "[[:lower:]]"')
+REGRESSION_TEST(`06', `tr "[[:digit:]]" "?" <${SRCDIR}/regress2.in')
+REGRESSION_TEST(`07', `tr "[[:alnum:]]" "#" <${SRCDIR}/regress2.in')
+REGRESSION_TEST(`08', `tr "[[:upper:]]" "[[:lower:]]" <${SRCDIR}/regress2.in | tr -d "[^[:alpha:]] "')
+REGRESSION_TEST(`09', `printf "\\f\\r\\n" | tr "\\014\\r" "?#"')
+REGRESSION_TEST(`0a', `printf "0xdeadbeef\\n" | tr "x[[:xdigit:]]" "?\$"')
+REGRESSION_TEST(`0b', `(tr -cd "[[:xdigit:]]" <${SRCDIR}/regress2.in ; echo)')
+REGRESSION_TEST(`0c', `echo "[[[[]]]]" | tr -d "[=]=]"')
+REGRESSION_TEST(`0d', `echo "]=[" | tr -d "[=]"')
+
+REGRESSION_END()
diff --git a/usr.bin/tr/tests/regress2.in b/usr.bin/tr/tests/regress2.in
new file mode 100644
index 000000000000..c416463d24fd
--- /dev/null
+++ b/usr.bin/tr/tests/regress2.in
@@ -0,0 +1,9 @@
+100 bottles of beer on the wall, 100 bottles of beer.
+Take one down and pass it around - 99 bottles of beer on the wall.
+99 bottles of beer on the wall, 99 bottles of beer.
+Take one down and pass it around - 98 bottles of beer on the wall.
+...
+2 bottles of beer on the wall, 2 bottles of beer!!!
+Take one down and pass it around - 1 bottle of beer on the wall.
+1 bottle of beer on the wall, 1 bottle of beer!!!
+Take it down and pass it around - NO MORE bottles of beer on the wall!!!
diff --git a/usr.bin/tr/tr.1 b/usr.bin/tr/tr.1
new file mode 100644
index 000000000000..ed1805c21eeb
--- /dev/null
+++ b/usr.bin/tr/tr.1
@@ -0,0 +1,422 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd October 13, 2006
+.Dt TR 1
+.Os
+.Sh NAME
+.Nm tr
+.Nd translate characters
+.Sh SYNOPSIS
+.Nm
+.Op Fl Ccsu
+.Ar string1 string2
+.Nm
+.Op Fl Ccu
+.Fl d
+.Ar string1
+.Nm
+.Op Fl Ccu
+.Fl s
+.Ar string1
+.Nm
+.Op Fl Ccu
+.Fl ds
+.Ar string1 string2
+.Sh DESCRIPTION
+The
+.Nm
+utility copies the standard input to the standard output with substitution
+or deletion of selected characters.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl C
+Complement the set of characters in
+.Ar string1 ,
+that is
+.Dq Fl C Li ab
+includes every character except for
+.Ql a
+and
+.Ql b .
+.It Fl c
+Same as
+.Fl C
+but complement the set of values in
+.Ar string1 .
+.It Fl d
+Delete characters in
+.Ar string1
+from the input.
+.It Fl s
+Squeeze multiple occurrences of the characters listed in the last
+operand (either
+.Ar string1
+or
+.Ar string2 )
+in the input into a single instance of the character.
+This occurs after all deletion and translation is completed.
+.It Fl u
+Guarantee that any output is unbuffered.
+.El
+.Pp
+In the first synopsis form, the characters in
+.Ar string1
+are translated into the characters in
+.Ar string2
+where the first character in
+.Ar string1
+is translated into the first character in
+.Ar string2
+and so on.
+If
+.Ar string1
+is longer than
+.Ar string2 ,
+the last character found in
+.Ar string2
+is duplicated until
+.Ar string1
+is exhausted.
+.Pp
+In the second synopsis form, the characters in
+.Ar string1
+are deleted from the input.
+.Pp
+In the third synopsis form, the characters in
+.Ar string1
+are compressed as described for the
+.Fl s
+option.
+.Pp
+In the fourth synopsis form, the characters in
+.Ar string1
+are deleted from the input, and the characters in
+.Ar string2
+are compressed as described for the
+.Fl s
+option.
+.Pp
+The following conventions can be used in
+.Ar string1
+and
+.Ar string2
+to specify sets of characters:
+.Bl -tag -width [:equiv:]
+.It character
+Any character not described by one of the following conventions
+represents itself.
+.It \eoctal
+A backslash followed by 1, 2 or 3 octal digits represents a character
+with that encoded value.
+To follow an octal sequence with a digit as a character, left zero-pad
+the octal sequence to the full 3 octal digits.
+.It \echaracter
+A backslash followed by certain special characters maps to special
+values.
+.Bl -column "\ea"
+.It "\ea <alert character>"
+.It "\eb <backspace>"
+.It "\ef <form-feed>"
+.It "\en <newline>"
+.It "\er <carriage return>"
+.It "\et <tab>"
+.It "\ev <vertical tab>"
+.El
+.Pp
+A backslash followed by any other character maps to that character.
+.It c-c
+For non-octal range endpoints
+represents the range of characters between the range endpoints, inclusive,
+in ascending order,
+as defined by the collation sequence.
+If either or both of the range endpoints are octal sequences, it
+represents the range of specific coded values between the
+range endpoints, inclusive.
+.Pp
+.Bf Em
+See the
+.Sx COMPATIBILITY
+section below for an important note regarding
+differences in the way the current
+implementation interprets range expressions differently from
+previous implementations.
+.Ef
+.It [:class:]
+Represents all characters belonging to the defined character class.
+Class names are:
+.Bl -column "phonogram"
+.It "alnum <alphanumeric characters>"
+.It "alpha <alphabetic characters>"
+.It "blank <whitespace characters>"
+.It "cntrl <control characters>"
+.It "digit <numeric characters>"
+.It "graph <graphic characters>"
+.It "ideogram <ideographic characters>"
+.It "lower <lower-case alphabetic characters>"
+.It "phonogram <phonographic characters>"
+.It "print <printable characters>"
+.It "punct <punctuation characters>"
+.It "rune <valid characters>"
+.It "space <space characters>"
+.It "special <special characters>"
+.It "upper <upper-case characters>"
+.It "xdigit <hexadecimal characters>"
+.El
+.Pp
+.\" All classes may be used in
+.\" .Ar string1 ,
+.\" and in
+.\" .Ar string2
+.\" when both the
+.\" .Fl d
+.\" and
+.\" .Fl s
+.\" options are specified.
+.\" Otherwise, only the classes ``upper'' and ``lower'' may be used in
+.\" .Ar string2
+.\" and then only when the corresponding class (``upper'' for ``lower''
+.\" and vice-versa) is specified in the same relative position in
+.\" .Ar string1 .
+.\" .Pp
+When
+.Dq Li [:lower:]
+appears in
+.Ar string1
+and
+.Dq Li [:upper:]
+appears in the same relative position in
+.Ar string2 ,
+it represents the characters pairs from the
+.Dv toupper
+mapping in the
+.Ev LC_CTYPE
+category of the current locale.
+When
+.Dq Li [:upper:]
+appears in
+.Ar string1
+and
+.Dq Li [:lower:]
+appears in the same relative position in
+.Ar string2 ,
+it represents the characters pairs from the
+.Dv tolower
+mapping in the
+.Ev LC_CTYPE
+category of the current locale.
+.Pp
+With the exception of case conversion,
+characters in the classes are in unspecified order.
+.Pp
+For specific information as to which
+.Tn ASCII
+characters are included
+in these classes, see
+.Xr ctype 3
+and related manual pages.
+.It [=equiv=]
+Represents all characters belonging to the same equivalence class as
+.Ar equiv ,
+ordered by their encoded values.
+.It [#*n]
+Represents
+.Ar n
+repeated occurrences of the character represented by
+.Ar # .
+This
+expression is only valid when it occurs in
+.Ar string2 .
+If
+.Ar n
+is omitted or is zero, it is be interpreted as large enough to extend
+.Ar string2
+sequence to the length of
+.Ar string1 .
+If
+.Ar n
+has a leading zero, it is interpreted as an octal value, otherwise,
+it is interpreted as a decimal value.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_CTYPE
+and
+.Ev LC_COLLATE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The following examples are shown as given to the shell:
+.Pp
+Create a list of the words in file1, one per line, where a word is taken to
+be a maximal string of letters.
+.Pp
+.D1 Li "tr -cs \*q[:alpha:]\*q \*q\en\*q < file1"
+.Pp
+Translate the contents of file1 to upper-case.
+.Pp
+.D1 Li "tr \*q[:lower:]\*q \*q[:upper:]\*q < file1"
+.Pp
+(This should be preferred over the traditional
+.Ux
+idiom of
+.Dq Li "tr a-z A-Z" ,
+since it works correctly in all locales.)
+.Pp
+Strip out non-printable characters from file1.
+.Pp
+.D1 Li "tr -cd \*q[:print:]\*q < file1"
+.Pp
+Remove diacritical marks from all accented variants of the letter
+.Ql e :
+.Pp
+.Dl "tr \*q[=e=]\*q \*qe\*q"
+.Sh COMPATIBILITY
+Previous
+.Fx
+implementations of
+.Nm
+did not order characters in range expressions according to the current
+locale's collation order, making it possible to convert unaccented Latin
+characters (esp.\& as found in English text) from upper to lower case using
+the traditional
+.Ux
+idiom of
+.Dq Li "tr A-Z a-z" .
+Since
+.Nm
+now obeys the locale's collation order, this idiom may not produce
+correct results when there is not a 1:1 mapping between lower and
+upper case, or when the order of characters within the two cases differs.
+As noted in the
+.Sx EXAMPLES
+section above, the character class expressions
+.Dq Li [:lower:]
+and
+.Dq Li [:upper:]
+should be used instead of explicit character ranges like
+.Dq Li a-z
+and
+.Dq Li A-Z .
+.Pp
+.Dq Li [=equiv=]
+expression and collation for ranges
+are implemented for single byte locales only.
+.Pp
+System V has historically implemented character ranges using the syntax
+.Dq Li [c-c]
+instead of the
+.Dq Li c-c
+used by historic
+.Bx
+implementations and
+standardized by POSIX.
+System V shell scripts should work under this implementation as long as
+the range is intended to map in another range, i.e., the command
+.Dq Li "tr [a-z] [A-Z]"
+will work as it will map the
+.Ql \&[
+character in
+.Ar string1
+to the
+.Ql \&[
+character in
+.Ar string2 .
+However, if the shell script is deleting or squeezing characters as in
+the command
+.Dq Li "tr -d [a-z]" ,
+the characters
+.Ql \&[
+and
+.Ql \&]
+will be
+included in the deletion or compression list which would not have happened
+under a historic System V implementation.
+Additionally, any scripts that depended on the sequence
+.Dq Li a-z
+to
+represent the three characters
+.Ql a ,
+.Ql \-
+and
+.Ql z
+will have to be
+rewritten as
+.Dq Li a\e-z .
+.Pp
+The
+.Nm
+utility has historically not permitted the manipulation of NUL bytes in
+its input and, additionally, stripped NUL's from its input stream.
+This implementation has removed this behavior as a bug.
+.Pp
+The
+.Nm
+utility has historically been extremely forgiving of syntax errors,
+for example, the
+.Fl c
+and
+.Fl s
+options were ignored unless two strings were specified.
+This implementation will not permit illegal syntax.
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+The
+.Dq ideogram ,
+.Dq phonogram ,
+.Dq rune ,
+and
+.Dq special
+character classes are extensions.
+.Pp
+It should be noted that the feature wherein the last character of
+.Ar string2
+is duplicated if
+.Ar string2
+has less characters than
+.Ar string1
+is permitted by POSIX but is not required.
+Shell scripts attempting to be portable to other POSIX systems should use
+the
+.Dq Li [#*]
+convention instead of relying on this behavior.
+The
+.Fl u
+option is an extension to the
+.St -p1003.1-2001
+standard.
diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c
new file mode 100644
index 000000000000..d31a51a73542
--- /dev/null
+++ b/usr.bin/tr/tr.c
@@ -0,0 +1,370 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "cmap.h"
+#include "cset.h"
+#include "extern.h"
+
+static STR s1 = { STRING1, NORMAL, 0, OOBCH, 0, { 0, OOBCH }, NULL, NULL };
+static STR s2 = { STRING2, NORMAL, 0, OOBCH, 0, { 0, OOBCH }, NULL, NULL };
+
+static struct cset *setup(char *, STR *, int, int);
+static void usage(void) __dead2;
+
+int
+main(int argc, char **argv)
+{
+ static int carray[NCHARS_SB];
+ struct cmap *map;
+ struct cset *delete, *squeeze;
+ int n, *p;
+ int Cflag, cflag, dflag, sflag, isstring2;
+ wint_t ch, cnt, lastch;
+
+ (void)setlocale(LC_ALL, "");
+
+ if (caph_limit_stdio() == -1)
+ err(1, "unable to limit stdio");
+
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ Cflag = cflag = dflag = sflag = 0;
+ while ((ch = getopt(argc, argv, "Ccdsu")) != -1)
+ switch((char)ch) {
+ case 'C':
+ Cflag = 1;
+ cflag = 0;
+ break;
+ case 'c':
+ cflag = 1;
+ Cflag = 0;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case 'u':
+ setbuf(stdout, (char *)NULL);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch(argc) {
+ case 0:
+ default:
+ usage();
+ /* NOTREACHED */
+ case 1:
+ isstring2 = 0;
+ break;
+ case 2:
+ isstring2 = 1;
+ break;
+ }
+
+ /*
+ * tr -ds [-Cc] string1 string2
+ * Delete all characters (or complemented characters) in string1.
+ * Squeeze all characters in string2.
+ */
+ if (dflag && sflag) {
+ if (!isstring2)
+ usage();
+
+ delete = setup(argv[0], &s1, cflag, Cflag);
+ squeeze = setup(argv[1], &s2, 0, 0);
+
+ for (lastch = OOBCH; (ch = getwchar()) != WEOF;)
+ if (!cset_in(delete, ch) &&
+ (lastch != ch || !cset_in(squeeze, ch))) {
+ lastch = ch;
+ (void)putwchar(ch);
+ }
+ if (ferror(stdin))
+ err(1, NULL);
+ exit(0);
+ }
+
+ /*
+ * tr -d [-Cc] string1
+ * Delete all characters (or complemented characters) in string1.
+ */
+ if (dflag) {
+ if (isstring2)
+ usage();
+
+ delete = setup(argv[0], &s1, cflag, Cflag);
+
+ while ((ch = getwchar()) != WEOF)
+ if (!cset_in(delete, ch))
+ (void)putwchar(ch);
+ if (ferror(stdin))
+ err(1, NULL);
+ exit(0);
+ }
+
+ /*
+ * tr -s [-Cc] string1
+ * Squeeze all characters (or complemented characters) in string1.
+ */
+ if (sflag && !isstring2) {
+ squeeze = setup(argv[0], &s1, cflag, Cflag);
+
+ for (lastch = OOBCH; (ch = getwchar()) != WEOF;)
+ if (lastch != ch || !cset_in(squeeze, ch)) {
+ lastch = ch;
+ (void)putwchar(ch);
+ }
+ if (ferror(stdin))
+ err(1, NULL);
+ exit(0);
+ }
+
+ /*
+ * tr [-Ccs] string1 string2
+ * Replace all characters (or complemented characters) in string1 with
+ * the character in the same position in string2. If the -s option is
+ * specified, squeeze all the characters in string2.
+ */
+ if (!isstring2)
+ usage();
+
+ map = cmap_alloc();
+ if (map == NULL)
+ err(1, NULL);
+ squeeze = cset_alloc();
+ if (squeeze == NULL)
+ err(1, NULL);
+
+ s1.str = argv[0];
+
+ if (Cflag || cflag) {
+ cmap_default(map, OOBCH);
+ if ((s2.str = strdup(argv[1])) == NULL)
+ errx(1, "strdup(argv[1])");
+ } else
+ s2.str = argv[1];
+
+ if (!next(&s2))
+ errx(1, "empty string2");
+
+ /*
+ * For -s result will contain only those characters defined
+ * as the second characters in each of the toupper or tolower
+ * pairs.
+ */
+
+ /* If string2 runs out of characters, use the last one specified. */
+ while (next(&s1)) {
+ again:
+ if (s1.state == CCLASS_LOWER &&
+ s2.state == CCLASS_UPPER &&
+ s1.cnt == 1 && s2.cnt == 1) {
+ do {
+ ch = towupper(s1.lastch);
+ cmap_add(map, s1.lastch, ch);
+ if (sflag && iswupper(ch))
+ cset_add(squeeze, ch);
+ if (!next(&s1))
+ goto endloop;
+ } while (s1.state == CCLASS_LOWER && s1.cnt > 1);
+ /* skip upper set */
+ do {
+ if (!next(&s2))
+ break;
+ } while (s2.state == CCLASS_UPPER && s2.cnt > 1);
+ goto again;
+ } else if (s1.state == CCLASS_UPPER &&
+ s2.state == CCLASS_LOWER &&
+ s1.cnt == 1 && s2.cnt == 1) {
+ do {
+ ch = towlower(s1.lastch);
+ cmap_add(map, s1.lastch, ch);
+ if (sflag && iswlower(ch))
+ cset_add(squeeze, ch);
+ if (!next(&s1))
+ goto endloop;
+ } while (s1.state == CCLASS_UPPER && s1.cnt > 1);
+ /* skip lower set */
+ do {
+ if (!next(&s2))
+ break;
+ } while (s2.state == CCLASS_LOWER && s2.cnt > 1);
+ goto again;
+ } else {
+ cmap_add(map, s1.lastch, s2.lastch);
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
+ }
+ (void)next(&s2);
+ }
+endloop:
+ if (cflag || (Cflag && MB_CUR_MAX > 1)) {
+ /*
+ * This is somewhat tricky: since the character set is
+ * potentially huge, we need to avoid allocating a map
+ * entry for every character. Our strategy is to set the
+ * default mapping to the last character of string #2
+ * (= the one that gets automatically repeated), then to
+ * add back identity mappings for characters that should
+ * remain unchanged. We don't waste space on identity mappings
+ * for non-characters with the -C option; those are simulated
+ * in the I/O loop.
+ */
+ s2.str = argv[1];
+ s2.state = NORMAL;
+ for (cnt = 0; cnt < WINT_MAX; cnt++) {
+ if (Cflag && !iswrune(cnt))
+ continue;
+ if (cmap_lookup(map, cnt) == OOBCH) {
+ if (next(&s2)) {
+ cmap_add(map, cnt, s2.lastch);
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
+ }
+ } else
+ cmap_add(map, cnt, cnt);
+ if ((s2.state == EOS || s2.state == INFINITE) &&
+ cnt >= cmap_max(map))
+ break;
+ }
+ cmap_default(map, s2.lastch);
+ } else if (Cflag) {
+ for (p = carray, cnt = 0; cnt < NCHARS_SB; cnt++) {
+ if (cmap_lookup(map, cnt) == OOBCH && iswrune(cnt))
+ *p++ = cnt;
+ else
+ cmap_add(map, cnt, cnt);
+ }
+ n = p - carray;
+ if (Cflag && n > 1)
+ (void)mergesort(carray, n, sizeof(*carray), charcoll);
+
+ s2.str = argv[1];
+ s2.state = NORMAL;
+ for (cnt = 0; cnt < n; cnt++) {
+ (void)next(&s2);
+ cmap_add(map, carray[cnt], s2.lastch);
+ /*
+ * Chars taken from s2 can be different this time
+ * due to lack of complex upper/lower processing,
+ * so fill string2 again to not miss some.
+ */
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
+ }
+ }
+
+ cset_cache(squeeze);
+ cmap_cache(map);
+
+ if (sflag)
+ for (lastch = OOBCH; (ch = getwchar()) != WEOF;) {
+ if (!Cflag || iswrune(ch))
+ ch = cmap_lookup(map, ch);
+ if (lastch != ch || !cset_in(squeeze, ch)) {
+ lastch = ch;
+ (void)putwchar(ch);
+ }
+ }
+ else
+ while ((ch = getwchar()) != WEOF) {
+ if (!Cflag || iswrune(ch))
+ ch = cmap_lookup(map, ch);
+ (void)putwchar(ch);
+ }
+ if (ferror(stdin))
+ err(1, NULL);
+ exit (0);
+}
+
+static struct cset *
+setup(char *arg, STR *str, int cflag, int Cflag)
+{
+ struct cset *cs;
+
+ cs = cset_alloc();
+ if (cs == NULL)
+ err(1, NULL);
+ str->str = arg;
+ while (next(str))
+ cset_add(cs, str->lastch);
+ if (Cflag)
+ cset_addclass(cs, wctype("rune"), true);
+ if (cflag || Cflag)
+ cset_invert(cs);
+ cset_cache(cs);
+ return (cs);
+}
+
+int
+charcoll(const void *a, const void *b)
+{
+ static char sa[2], sb[2];
+
+ sa[0] = *(const int *)a;
+ sb[0] = *(const int *)b;
+ return (strcoll(sa, sb));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
+ "usage: tr [-Ccsu] string1 string2",
+ " tr [-Ccu] -d string1",
+ " tr [-Ccu] -s string1",
+ " tr [-Ccu] -ds string1 string2");
+ exit(1);
+}
diff --git a/usr.bin/true/Makefile b/usr.bin/true/Makefile
new file mode 100644
index 000000000000..1285b818d78e
--- /dev/null
+++ b/usr.bin/true/Makefile
@@ -0,0 +1,3 @@
+PROG= true
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/true/Makefile.depend b/usr.bin/true/Makefile.depend
new file mode 100644
index 000000000000..8e1db63914e6
--- /dev/null
+++ b/usr.bin/true/Makefile.depend
@@ -0,0 +1,13 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/true/true.1 b/usr.bin/true/true.1
new file mode 100644
index 000000000000..8690b4a86930
--- /dev/null
+++ b/usr.bin/true/true.1
@@ -0,0 +1,60 @@
+.\" Copyright (c) 1983, 1985, 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 9, 1993
+.Dt TRUE 1
+.Os
+.Sh NAME
+.Nm true
+.Nd return true value
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility always returns with an exit code of zero.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr false 1 ,
+.Xr sh 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
diff --git a/usr.bin/true/true.c b/usr.bin/true/true.c
new file mode 100644
index 000000000000..5ff915d5e820
--- /dev/null
+++ b/usr.bin/true/true.c
@@ -0,0 +1,36 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+int
+main(void)
+{
+ return 0;
+}
diff --git a/usr.bin/truncate/Makefile b/usr.bin/truncate/Makefile
new file mode 100644
index 000000000000..0b27f0c87588
--- /dev/null
+++ b/usr.bin/truncate/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PROG= truncate
+LIBADD= util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/truncate/Makefile.depend b/usr.bin/truncate/Makefile.depend
new file mode 100644
index 000000000000..678747db6f2c
--- /dev/null
+++ b/usr.bin/truncate/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/truncate/tests/Makefile b/usr.bin/truncate/tests/Makefile
new file mode 100644
index 000000000000..64e05e50b87f
--- /dev/null
+++ b/usr.bin/truncate/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH= truncate_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/truncate/tests/Makefile.depend b/usr.bin/truncate/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/truncate/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/truncate/tests/truncate_test.sh b/usr.bin/truncate/tests/truncate_test.sh
new file mode 100644
index 000000000000..ec219059de42
--- /dev/null
+++ b/usr.bin/truncate/tests/truncate_test.sh
@@ -0,0 +1,462 @@
+#
+# Copyright 2014, Google Inc. All rights reserved.
+#
+# 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 written permission.
+#
+# 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.
+#
+#
+
+# Helper function that is always used to create and fill stderr.txt for these
+# tests.
+_custom_create_file()
+{
+ # The first argument is a command.
+ # The second is just a string.
+ case "${1}" in
+ creat) > stderr.txt ;;
+ print) [ "${2}" ] && \
+ printf "%s\n" "${2}" >> stderr.txt ;;
+ esac
+}
+
+# Helper function that create the file stderr.txt that contains the string
+# passed in as the first argument.
+create_stderr_file()
+{
+ _custom_create_file creat
+ _custom_create_file print "${1}"
+}
+
+# Helper function that create the file stderr.txt that contains the expected
+# truncate utility usage message.
+create_stderr_usage_file()
+{
+ _custom_create_file creat
+ _custom_create_file print "${1}"
+ _custom_create_file print \
+ "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ..."
+ _custom_create_file print " truncate [-c] -r rfile file ..."
+ _custom_create_file print " truncate [-c] -d [-o offset[K|k|M|m|G|g|T|t]] -l length[K|k|M|m|G|g|T|t] file ..."
+}
+
+atf_test_case illegal_option
+illegal_option_head()
+{
+ atf_set "descr" "Verifies that truncate exits >0 when passed an" \
+ "invalid command line option"
+}
+illegal_option_body()
+{
+ create_stderr_usage_file 'truncate: illegal option -- 7'
+
+ # We expect the error message, with no new files.
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt
+ [ ! -e output.txt ] || atf_fail "output.txt should not exist"
+}
+
+atf_test_case illegal_size
+illegal_size_head()
+{
+ atf_set "descr" "Verifies that truncate exits >0 when passed an" \
+ "invalid power of two convention"
+}
+illegal_size_body()
+{
+ create_stderr_file "truncate: invalid size argument \`+1L'"
+
+ # We expect the error message, with no new files.
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt
+ [ ! -e output.txt ] || atf_fail "output.txt should not exist"
+}
+
+atf_test_case too_large_size
+too_large_size_head()
+{
+ atf_set "descr" "Verifies that truncate exits >0 when passed an" \
+ "a size that is INT64_MAX < size <= UINT64_MAX"
+}
+too_large_size_body()
+{
+ create_stderr_file "truncate: invalid size argument \`8388608t'"
+
+ # We expect the error message, with no new files.
+ atf_check -s not-exit:0 -e file:stderr.txt \
+ truncate -s8388608t output.txt
+ [ ! -e output.txt ] || atf_fail "output.txt should not exist"
+}
+
+atf_test_case opt_c
+opt_c_head()
+{
+ atf_set "descr" "Verifies that -c prevents creation of new files"
+}
+opt_c_body()
+{
+ # No new files and truncate returns 0 as if this is a success.
+ atf_check truncate -c -s 0 doesnotexist.txt
+ [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
+ > reference
+ atf_check truncate -c -r reference doesnotexist.txt
+ [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist"
+
+ create_stderr_file
+
+ # The existing file will be altered by truncate.
+ > exists.txt
+ atf_check -e file:stderr.txt truncate -c -s1 exists.txt
+ [ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes"
+}
+
+atf_test_case opt_rs
+opt_rs_head()
+{
+ atf_set "descr" "Verifies that truncate command line flags" \
+ "-s and -r cannot be specifed together"
+}
+opt_rs_body()
+{
+ create_stderr_usage_file
+
+ # Force an error due to the use of both -s and -r.
+ > afile
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile
+}
+
+atf_test_case no_files
+no_files_head()
+{
+ atf_set "descr" "Verifies that truncate needs a list of files on" \
+ "the command line"
+}
+no_files_body()
+{
+ create_stderr_usage_file
+
+ # A list of files must be present on the command line.
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -s1
+}
+
+atf_test_case bad_refer
+bad_refer_head()
+{
+ atf_set "descr" "Verifies that truncate detects a non-existent" \
+ "reference file"
+}
+bad_refer_body()
+{
+ create_stderr_file "truncate: afile: No such file or directory"
+
+ # The reference file must exist before you try to use it.
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile
+ [ ! -e afile ] || atf_fail "afile should not exist"
+}
+
+atf_test_case bad_truncate
+bad_truncate_head()
+{
+ atf_set "descr" "Verifies that truncate reports an error during" \
+ "truncation"
+ atf_set "require.user" "unprivileged"
+}
+bad_truncate_body()
+{
+ create_stderr_file "truncate: exists.txt: Permission denied"
+
+ # Trying to get the ftruncate() call to return -1.
+ > exists.txt
+ atf_check chmod 444 exists.txt
+
+ atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt
+}
+
+atf_test_case new_absolute_grow
+new_absolute_grow_head()
+{
+ atf_set "descr" "Verifies truncate can make and grow a new 1m file"
+}
+new_absolute_grow_body()
+{
+ create_stderr_file
+
+ # Create a new file and grow it to 1024 bytes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+
+ create_stderr_file
+
+ # Grow the existing file to 1M. We are using absolute sizes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
+}
+
+atf_test_case new_absolute_shrink
+new_absolute_shrink_head()
+{
+ atf_set "descr" "Verifies that truncate can make and" \
+ "shrink a new 1m file"
+}
+new_absolute_shrink_body()
+{
+ create_stderr_file
+
+ # Create a new file and grow it to 1048576 bytes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
+
+ create_stderr_file
+
+ # Shrink the existing file to 1k. We are using absolute sizes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+}
+
+atf_test_case new_relative_grow
+new_relative_grow_head()
+{
+ atf_set "descr" "Verifies truncate can make and grow a new 1m file" \
+ "using relative sizes"
+}
+new_relative_grow_body()
+{
+ create_stderr_file
+
+ # Create a new file and grow it to 1024 bytes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+
+ create_stderr_file
+
+ # Grow the existing file to 1M. We are using relative sizes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m"
+}
+
+atf_test_case new_relative_shrink
+new_relative_shrink_head()
+{
+ atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \
+ "using relative sizes"
+}
+new_relative_shrink_body()
+{
+ create_stderr_file
+
+ # Create a new file and grow it to 1049600 bytes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m"
+
+ create_stderr_file
+
+ # Shrink the existing file to 1k. We are using relative sizes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt
+ atf_check -s exit:1 cmp -s output.txt /dev/zero
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+}
+
+atf_test_case cannot_open
+cannot_open_head()
+{
+ atf_set "descr" "Verifies truncate handles open failures correctly" \
+ "in a list of files"
+ atf_set "require.user" "unprivileged"
+}
+cannot_open_body()
+{
+ # Create three files -- the middle file cannot allow writes.
+ > before
+ > 0000
+ > after
+ atf_check chmod 0000 0000
+
+ create_stderr_file "truncate: 0000: Permission denied"
+
+ # Create a new file and grow it to 1024 bytes.
+ atf_check -s not-exit:0 -e file:stderr.txt \
+ truncate -c -s1k before 0000 after
+ eval $(stat -s before)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+ eval $(stat -s after)
+ [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k"
+ eval $(stat -s 0000)
+ [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
+}
+
+atf_test_case reference
+reference_head()
+{
+ atf_set "descr" "Verifies that truncate can use a reference file"
+}
+reference_body()
+{
+ # Create a 4 byte reference file.
+ printf "123\n" > reference
+ eval $(stat -s reference)
+ [ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes"
+
+ create_stderr_file
+
+ # Create a new file and grow it to 4 bytes.
+ atf_check -e file:stderr.txt truncate -r reference afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes"
+}
+
+atf_test_case new_zero
+new_zero_head()
+{
+ atf_set "descr" "Verifies truncate can make and grow zero byte file"
+}
+new_zero_body()
+{
+ create_stderr_file
+
+ # Create a new file and grow it to zero bytes.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
+
+ # Pretend to grow the file.
+ atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt
+ eval $(stat -s output.txt)
+ [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero"
+}
+
+atf_test_case negative
+negative_head()
+{
+ atf_set "descr" "Verifies truncate treats negative sizes as zero"
+}
+negative_body()
+{
+ # Create a 5 byte file.
+ printf "abcd\n" > afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+ create_stderr_file
+
+ # Create a new file and do a 100 byte negative relative shrink.
+ atf_check -e file:stderr.txt truncate -s-100 afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes"
+}
+
+atf_test_case roundup
+roundup_head()
+{
+ atf_set "descr" "Verifies truncate round up"
+}
+roundup_body()
+{
+ # Create a 5 byte file.
+ printf "abcd\n" > afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+ create_stderr_file
+
+ # Create a new file and do a 100 byte roundup.
+ atf_check -e file:stderr.txt truncate -s%100 afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 100 ] || atf_fail "new file should now be 100 bytes"
+}
+
+atf_test_case rounddown
+rounddown_head()
+{
+ atf_set "descr" "Verifies truncate round down"
+}
+rounddown_body()
+{
+ # Create a 5 byte file.
+ printf "abcd\n" > afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+ create_stderr_file
+
+ # Create a new file and do a 2 byte roundup.
+ atf_check -e file:stderr.txt truncate -s/2 afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 4 ] || atf_fail "new file should now be 4 bytes"
+}
+
+atf_test_case rounddown_zero
+rounddown_zero_head()
+{
+ atf_set "descr" "Verifies truncate round down to zero"
+}
+rounddown_zero_body()
+{
+ # Create a 5 byte file.
+ printf "abcd\n" > afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+ create_stderr_file
+
+ # Create a new file and do a 10 byte roundup.
+ atf_check -e file:stderr.txt truncate -s/10 afile
+ eval $(stat -s afile)
+ [ ${st_size} -eq 0 ] || atf_fail "new file should now be 0 bytes"
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case illegal_option
+ atf_add_test_case illegal_size
+ atf_add_test_case too_large_size
+ atf_add_test_case opt_c
+ atf_add_test_case opt_rs
+ atf_add_test_case no_files
+ atf_add_test_case bad_refer
+ atf_add_test_case bad_truncate
+ atf_add_test_case cannot_open
+ atf_add_test_case new_absolute_grow
+ atf_add_test_case new_absolute_shrink
+ atf_add_test_case new_relative_grow
+ atf_add_test_case new_relative_shrink
+ atf_add_test_case reference
+ atf_add_test_case new_zero
+ atf_add_test_case negative
+ atf_add_test_case roundup
+ atf_add_test_case rounddown
+ atf_add_test_case rounddown_zero
+}
diff --git a/usr.bin/truncate/truncate.1 b/usr.bin/truncate/truncate.1
new file mode 100644
index 000000000000..f6b8b0cc37c9
--- /dev/null
+++ b/usr.bin/truncate/truncate.1
@@ -0,0 +1,256 @@
+.\"
+.\" Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
+.\" All rights reserved.
+.\" Copyright (c) 2021 The FreeBSD Foundation
+.\"
+.\" Portions of this manual page were written by Ka Ho Ng <khng@FreeBSD.org>
+.\" under sponsorship from the FreeBSD Foundation.
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 March 6, 2025
+.Dt TRUNCATE 1
+.Os
+.Sh NAME
+.Nm truncate
+.Nd truncate, extend the length of files, or perform space management in files
+.Sh SYNOPSIS
+.Nm
+.Op Fl c
+.Bk -words
+.Fl s Xo
+.Sm off
+.Op Cm + | - | % | /
+.Ar size
+.Op Cm SUFFIX
+.Sm on
+.Xc
+.Ek
+.Ar
+.Nm
+.Op Fl c
+.Bk -words
+.Fl r Ar rfile
+.Ek
+.Ar
+.Nm
+.Op Fl c
+.Bk -words
+.Fl d
+.Oo
+.Fl o Xo
+.Sm off
+.Ar offset
+.Op Cm SUFFIX
+.Sm on
+.Xc
+.Oc
+.Fl l Xo
+.Sm off
+.Ar length
+.Op Cm SUFFIX
+.Sm on
+.Xc
+.Ek
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility adjusts the length of each regular file given on the command-line, or
+performs space management with the given offset and the length over a regular
+file given on the command-line.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Do not create files if they do not exist.
+The
+.Nm
+utility does not treat this as an error.
+No error messages are displayed
+and the exit value is not affected.
+.It Fl r Ar rfile
+Truncate or extend files to the length of the file
+.Ar rfile .
+.It Fl s Xo
+.Sm off
+.Op Cm + | - | % | /
+.Ar size
+.Op Cm SUFFIX
+.Sm on
+.Xc
+If the
+.Ar size
+argument is preceded by a plus sign
+.Pq Cm + ,
+files will be extended by this number of bytes.
+If the
+.Ar size
+argument is preceded by a dash
+.Pq Cm - ,
+file lengths will be reduced by no more than this number of bytes,
+to a minimum length of zero bytes.
+If the
+.Ar size
+argument is preceded by a percent sign
+.Pq Cm % ,
+files will be round up to a multiple of this number of bytes.
+If the
+.Ar size
+argument is preceded by a slash sign
+.Pq Cm / ,
+files will be round down to a multiple of this number of bytes,
+to a minimum length of zero bytes.
+Otherwise, the
+.Ar size
+argument specifies an absolute length to which all files
+should be extended or reduced as appropriate.
+.It Fl d
+Zero a region in the specified file.
+If the underlying file system of the given file supports hole-punching,
+file system space deallocation may be performed in the operation region.
+.It Fl o Ar offset
+The space management operation is performed at the given
+.Ar offset
+bytes in the file.
+If this option is not specified, the operation is performed at the beginning of the file.
+.It Fl l Ar length
+The length of the operation range in bytes.
+This option must always be specified if option
+.Fl d
+is specified, and must be greater than 0.
+.El
+.Pp
+The
+.Ar size ,
+.Ar offset
+and
+.Ar length
+arguments may be suffixed with one of
+.Cm K ,
+.Cm M ,
+.Cm G
+or
+.Cm T
+(either upper or lower case) to indicate a multiple of
+Kilobytes, Megabytes, Gigabytes or Terabytes
+respectively.
+.Pp
+Exactly one of the
+.Fl r ,
+.Fl s
+and
+.Fl d
+options must be specified.
+.Pp
+If a file is made smaller, its extra data is lost.
+If a file is made larger,
+it will be extended as if by writing bytes with the value zero.
+If the file does not exist,
+it is created unless the
+.Fl c
+option is specified.
+.Pp
+Note that,
+while truncating a file causes space on disk to be freed,
+extending a file does not cause space to be allocated.
+To extend a file and actually allocate the space,
+it is necessary to explicitly write data to it,
+using (for example) the shell's
+.Ql >>
+redirection syntax, or
+.Xr dd 1 .
+.Sh EXIT STATUS
+.Ex -std
+If the operation fails for an argument,
+.Nm
+will issue a diagnostic
+and continue processing the remaining arguments.
+.Sh EXAMPLES
+Adjust the size of the file
+.Pa test_file
+to 10 megabytes but do not create it if it does not exist:
+.Bd -literal -offset indent
+truncate -c -s 10M test_file
+.Ed
+.Pp
+Same as above but create the file if it does not exist:
+.Bd -literal -offset indent
+truncate -s 10M test_file
+ls -l test_file
+-rw-r--r-- 1 root wheel 10485760 Jul 22 18:48 test_file
+.Ed
+.Pp
+Adjust the size of
+.Pa test_file
+to the size of the kernel and create another file
+.Pa test_file2
+with the same size:
+.Bd -literal -offset indent
+truncate -r /boot/kernel/kernel test_file test_file2
+ls -l /boot/kernel/kernel test_file*
+-r-xr-xr-x 1 root wheel 31352552 May 15 14:18 /boot/kernel/kernel
+-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file
+-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2
+.Ed
+.Pp
+Increase the size of the file
+.Pa test_file
+by 5 megabytes but do not create it if it does not exist:
+.Bd -literal -offset indent
+truncate -s +5M test_file
+ls -l test_file*
+-rw-r--r-- 1 root wheel 36595432 Sep 20 19:17 test_file
+-rw-r--r-- 1 root wheel 31352552 Sep 20 19:15 test_file2
+.Ed
+.Pp
+Reduce the size of the file
+.Pa test_file
+by 5 megabytes:
+.Bd -literal -offset indent
+truncate -s -5M test_file
+ls -l test_file*
+-rw-r--r-- 1 root wheel 31352552 Jul 22 19:19 test_file
+-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2
+.Ed
+.Sh SEE ALSO
+.Xr dd 1 ,
+.Xr touch 1 ,
+.Xr fspacectl 2 ,
+.Xr truncate 2
+.Sh STANDARDS
+The
+.Nm
+utility conforms to no known standards.
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 4.2 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Sheldon Hearn Aq Mt sheldonh@starjuice.net .
+Hole-punching support of this
+utility was developed by
+.An Ka Ho Ng Aq Mt khng@FreeBSD.org .
diff --git a/usr.bin/truncate/truncate.c b/usr.bin/truncate/truncate.c
new file mode 100644
index 000000000000..d8484257294a
--- /dev/null
+++ b/usr.bin/truncate/truncate.c
@@ -0,0 +1,226 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Ka Ho Ng <khng@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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 <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+static void usage(void);
+
+int
+main(int argc, char **argv)
+{
+ struct stat sb;
+ mode_t omode;
+ off_t oflow, rsize, sz, tsize, round, off, len;
+ uint64_t usz;
+ int ch, error, fd, oflags, r;
+ int do_dealloc;
+ int do_truncate;
+ int no_create;
+ int do_relative;
+ int do_round;
+ int do_refer;
+ int got_size;
+ char *fname, *rname;
+ struct spacectl_range sr;
+
+ fd = -1;
+ rsize = tsize = sz = off = 0;
+ len = -1;
+ do_dealloc = no_create = do_relative = do_round = do_refer =
+ got_size = 0;
+ do_truncate = 1;
+ error = r = 0;
+ rname = NULL;
+ while ((ch = getopt(argc, argv, "cdr:s:o:l:")) != -1)
+ switch (ch) {
+ case 'c':
+ no_create = 1;
+ break;
+ case 'd':
+ do_dealloc = 1;
+ do_truncate = 0;
+ break;
+ case 'r':
+ do_refer = 1;
+ rname = optarg;
+ break;
+ case 's':
+ if (*optarg == '+' || *optarg == '-') {
+ do_relative = 1;
+ } else if (*optarg == '%' || *optarg == '/') {
+ do_round = 1;
+ }
+ if (expand_number(do_relative || do_round ?
+ optarg + 1 : optarg,
+ &usz) == -1 || (off_t)usz < 0)
+ errx(EXIT_FAILURE,
+ "invalid size argument `%s'", optarg);
+
+ sz = (*optarg == '-' || *optarg == '/') ?
+ -(off_t)usz : (off_t)usz;
+ got_size = 1;
+ break;
+ case 'o':
+ if (expand_number(optarg, &usz) == -1 ||
+ (off_t)usz < 0)
+ errx(EXIT_FAILURE,
+ "invalid offset argument `%s'", optarg);
+
+ off = usz;
+ break;
+ case 'l':
+ if (expand_number(optarg, &usz) == -1 ||
+ (off_t)usz <= 0)
+ errx(EXIT_FAILURE,
+ "invalid length argument `%s'", optarg);
+
+ len = usz;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ /*
+ * Exactly one of do_refer, got_size or do_dealloc must be specified.
+ * Since do_relative implies got_size, do_relative, do_refer and
+ * do_dealloc are also mutually exclusive. If do_dealloc is specified,
+ * the length argument must be set. See usage() for allowed
+ * invocations.
+ */
+ if (argc < 1 || do_refer + got_size + do_dealloc != 1 ||
+ (do_dealloc == 1 && len == -1))
+ usage();
+ if (do_refer == 1) {
+ if (stat(rname, &sb) == -1)
+ err(EXIT_FAILURE, "%s", rname);
+ tsize = sb.st_size;
+ } else if (do_relative == 1 || do_round == 1)
+ rsize = sz;
+ else if (do_dealloc == 0)
+ tsize = sz;
+
+ if (no_create)
+ oflags = O_WRONLY;
+ else
+ oflags = O_WRONLY | O_CREAT;
+ omode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+ while ((fname = *argv++) != NULL) {
+ if (fd != -1)
+ close(fd);
+ if ((fd = open(fname, oflags, omode)) == -1) {
+ if (errno != ENOENT) {
+ warn("%s", fname);
+ error++;
+ }
+ continue;
+ }
+ if (do_relative == 1) {
+ if (fstat(fd, &sb) == -1) {
+ warn("%s", fname);
+ error++;
+ continue;
+ }
+ oflow = sb.st_size + rsize;
+ if (oflow < (sb.st_size + rsize)) {
+ errno = EFBIG;
+ warn("%s", fname);
+ error++;
+ continue;
+ }
+ tsize = oflow;
+ }
+ if (do_round == 1) {
+ if (fstat(fd, &sb) == -1) {
+ warn("%s", fname);
+ error++;
+ continue;
+ }
+ sz = rsize;
+ if (sz < 0)
+ sz = -sz;
+ if (sb.st_size % sz) {
+ round = sb.st_size / sz;
+ if (round != sz && rsize < 0)
+ round--;
+ else if (rsize > 0)
+ round++;
+ tsize = (round < 0 ? 0 : round) * sz;
+ } else
+ tsize = sb.st_size;
+ }
+ if (tsize < 0)
+ tsize = 0;
+
+ if (do_dealloc == 1) {
+ sr.r_offset = off;
+ sr.r_len = len;
+ r = fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, &sr);
+ }
+ if (do_truncate == 1)
+ r = ftruncate(fd, tsize);
+ if (r == -1) {
+ warn("%s", fname);
+ error++;
+ }
+ }
+ if (fd != -1)
+ close(fd);
+
+ return (error ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n%s\n",
+ "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
+ " truncate [-c] -r rfile file ...",
+ " truncate [-c] -d [-o offset[K|k|M|m|G|g|T|t]] -l length[K|k|M|m|G|g|T|t] file ...");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/truss/Makefile b/usr.bin/truss/Makefile
new file mode 100644
index 000000000000..a31f985cbb01
--- /dev/null
+++ b/usr.bin/truss/Makefile
@@ -0,0 +1,9 @@
+PROG= truss
+SRCS= main.c setup.c syscalls.c
+
+LIBADD= sysdecode
+
+#CFLAGS+= -I${.CURDIR} -I. -I${SRCTOP}/sys
+CFLAGS+= -I${SRCTOP}/sys
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/truss/Makefile.depend b/usr.bin/truss/Makefile.depend
new file mode 100644
index 000000000000..c6583a740018
--- /dev/null
+++ b/usr.bin/truss/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsysdecode \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/truss/extern.h b/usr.bin/truss/extern.h
new file mode 100644
index 000000000000..a58ae33e098e
--- /dev/null
+++ b/usr.bin/truss/extern.h
@@ -0,0 +1,39 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright 1997 Sean Eric Fagan
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sean Eric Fagan
+ * 4. Neither the name of the author may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+extern int print_line_prefix(struct trussinfo *);
+extern void setup_and_wait(struct trussinfo *, char **);
+extern void start_tracing(struct trussinfo *, pid_t);
+extern void restore_proc(int);
+extern void decode_siginfo(FILE *, siginfo_t *);
+extern void eventloop(struct trussinfo *);
diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
new file mode 100644
index 000000000000..217066681746
--- /dev/null
+++ b/usr.bin/truss/main.c
@@ -0,0 +1,207 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright 1997 Sean Eric Fagan
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sean Eric Fagan
+ * 4. Neither the name of the author may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+/*
+ * The main module for truss. Surprisingly simple, but, then, the other
+ * files handle the bulk of the work. And, of course, the kernel has to
+ * do a lot of the work :).
+ */
+
+#include <sys/ptrace.h>
+
+#include <err.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysdecode.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "truss.h"
+#include "extern.h"
+#include "syscall.h"
+
+static __dead2 void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: truss [-cfaedDHS] [-o file] [-s strsize] -p pid",
+ " truss [-cfaedDHS] [-o file] [-s strsize] command [args]");
+ exit(1);
+}
+
+int
+main(int ac, char **av)
+{
+ struct sigaction sa;
+ struct trussinfo *trussinfo;
+ char *fname;
+ char **command;
+ const char *errstr;
+ pid_t pid;
+ int c;
+
+ fname = NULL;
+
+ /* Initialize the trussinfo struct */
+ trussinfo = (struct trussinfo *)calloc(1, sizeof(struct trussinfo));
+ if (trussinfo == NULL)
+ errx(1, "calloc() failed");
+
+ pid = 0;
+ trussinfo->outfile = stderr;
+ trussinfo->strsize = 32;
+ trussinfo->curthread = NULL;
+ LIST_INIT(&trussinfo->proclist);
+ while ((c = getopt(ac, av, "p:o:facedDs:SH")) != -1) {
+ switch (c) {
+ case 'p': /* specified pid */
+ pid = atoi(optarg);
+ /* make sure i don't trace me */
+ if (pid == getpid()) {
+ errx(2, "attempt to grab self.");
+ }
+ break;
+ case 'f': /* Follow fork()'s */
+ trussinfo->flags |= FOLLOWFORKS;
+ break;
+ case 'a': /* Print execve() argument strings. */
+ trussinfo->flags |= EXECVEARGS;
+ break;
+ case 'c': /* Count number of system calls and time. */
+ trussinfo->flags |= (COUNTONLY | NOSIGS);
+ break;
+ case 'e': /* Print execve() environment strings. */
+ trussinfo->flags |= EXECVEENVS;
+ break;
+ case 'd': /* Absolute timestamps */
+ trussinfo->flags |= ABSOLUTETIMESTAMPS;
+ break;
+ case 'D': /* Relative timestamps */
+ trussinfo->flags |= RELATIVETIMESTAMPS;
+ break;
+ case 'o': /* Specified output file */
+ fname = optarg;
+ break;
+ case 's': /* Specified string size */
+ trussinfo->strsize = (int)strtonum(optarg, 0, INT_MAX,
+ &errstr);
+ if (errstr)
+ errx(1, "maximum string size is %s: %s", errstr, optarg);
+ break;
+ case 'S': /* Don't trace signals */
+ trussinfo->flags |= NOSIGS;
+ break;
+ case 'H':
+ trussinfo->flags |= DISPLAYTIDS;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ ac -= optind; av += optind;
+ if ((pid == 0 && ac == 0) ||
+ (pid != 0 && ac != 0))
+ usage();
+
+ if (fname != NULL) { /* Use output file */
+ /*
+ * Set close-on-exec ('e'), so that the output file is not
+ * shared with the traced process.
+ */
+ if ((trussinfo->outfile = fopen(fname, "we")) == NULL)
+ err(1, "cannot open %s", fname);
+ }
+
+ /*
+ * If truss starts the process itself, it will ignore some signals --
+ * they should be passed off to the process, which may or may not
+ * exit. If, however, we are examining an already-running process,
+ * then we restore the event mask on these same signals.
+ */
+ if (pid == 0) {
+ /* Start a command ourselves */
+ command = av;
+ setup_and_wait(trussinfo, command);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ } else {
+ sa.sa_handler = restore_proc;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ start_tracing(trussinfo, pid);
+ }
+
+ /*
+ * At this point, if we started the process, it is stopped waiting to
+ * be woken up, either in exit() or in execve().
+ */
+ if (LIST_FIRST(&trussinfo->proclist)->abi == NULL) {
+ /*
+ * If we are not able to handle this ABI, detach from the
+ * process and exit. If we just created a new process to
+ * run a command, kill the new process rather than letting
+ * it run untraced.
+ */
+ if (pid == 0)
+ kill(LIST_FIRST(&trussinfo->proclist)->pid, SIGKILL);
+ ptrace(PT_DETACH, LIST_FIRST(&trussinfo->proclist)->pid, NULL,
+ 0);
+ return (1);
+ }
+ ptrace(PT_SYSCALL, LIST_FIRST(&trussinfo->proclist)->pid, (caddr_t)1,
+ 0);
+
+ /*
+ * At this point, it's a simple loop, waiting for the process to
+ * stop, finding out why, printing out why, and then continuing it.
+ * All of the grunt work is done in the support routines.
+ */
+ clock_gettime(CLOCK_REALTIME, &trussinfo->start_time);
+
+ eventloop(trussinfo);
+
+ if (trussinfo->flags & COUNTONLY)
+ print_summary(trussinfo);
+
+ fflush(trussinfo->outfile);
+
+ return (0);
+}
diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c
new file mode 100644
index 000000000000..d5fa1ed50ce1
--- /dev/null
+++ b/usr.bin/truss/setup.c
@@ -0,0 +1,832 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright 1997 Sean Eric Fagan
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sean Eric Fagan
+ * 4. Neither the name of the author may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+/*
+ * Various setup functions for truss. Not the cleanest-written code,
+ * I'm afraid.
+ */
+
+#include <sys/ptrace.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdecode.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "truss.h"
+#include "syscall.h"
+#include "extern.h"
+
+struct procabi_table {
+ const char *name;
+ struct procabi *abi;
+};
+
+static sig_atomic_t detaching;
+
+static void enter_syscall(struct trussinfo *, struct threadinfo *,
+ struct ptrace_lwpinfo *);
+static void new_proc(struct trussinfo *, pid_t, lwpid_t);
+
+
+static struct procabi freebsd = {
+ .type = "FreeBSD",
+ .abi = SYSDECODE_ABI_FREEBSD,
+ .pointer_size = sizeof(void *),
+ .extra_syscalls = STAILQ_HEAD_INITIALIZER(freebsd.extra_syscalls),
+ .syscalls = { NULL }
+};
+
+#if !defined(__SIZEOF_POINTER__)
+#error "Use a modern compiler."
+#endif
+
+#if __SIZEOF_POINTER__ > 4
+static struct procabi freebsd32 = {
+ .type = "FreeBSD32",
+ .abi = SYSDECODE_ABI_FREEBSD32,
+ .pointer_size = sizeof(uint32_t),
+ .compat_prefix = "freebsd32_",
+ .extra_syscalls = STAILQ_HEAD_INITIALIZER(freebsd32.extra_syscalls),
+ .syscalls = { NULL }
+};
+#endif
+
+static struct procabi linux = {
+ .type = "Linux",
+ .abi = SYSDECODE_ABI_LINUX,
+ .pointer_size = sizeof(void *),
+ .extra_syscalls = STAILQ_HEAD_INITIALIZER(linux.extra_syscalls),
+ .syscalls = { NULL }
+};
+
+#if __SIZEOF_POINTER__ > 4
+static struct procabi linux32 = {
+ .type = "Linux32",
+ .abi = SYSDECODE_ABI_LINUX32,
+ .pointer_size = sizeof(uint32_t),
+ .extra_syscalls = STAILQ_HEAD_INITIALIZER(linux32.extra_syscalls),
+ .syscalls = { NULL }
+};
+#endif
+
+static struct procabi_table abis[] = {
+#if __SIZEOF_POINTER__ == 4
+ { "FreeBSD ELF32", &freebsd },
+#elif __SIZEOF_POINTER__ == 8
+ { "FreeBSD ELF64", &freebsd },
+ { "FreeBSD ELF32", &freebsd32 },
+#else
+#error "Unsupported pointer size"
+#endif
+#if defined(__powerpc64__)
+ { "FreeBSD ELF64 V2", &freebsd },
+#endif
+#if defined(__amd64__)
+ { "FreeBSD a.out", &freebsd32 },
+#endif
+#if defined(__i386__)
+ { "FreeBSD a.out", &freebsd },
+#endif
+#if __SIZEOF_POINTER__ >= 8
+ { "Linux ELF64", &linux },
+ { "Linux ELF32", &linux32 },
+#else
+ { "Linux ELF32", &linux },
+#endif
+};
+
+/*
+ * setup_and_wait() is called to start a process. All it really does
+ * is fork(), enable tracing in the child, and then exec the given
+ * command. At that point, the child process stops, and the parent
+ * can wake up and deal with it.
+ */
+void
+setup_and_wait(struct trussinfo *info, char *command[])
+{
+ pid_t pid;
+
+ pid = vfork();
+ if (pid == -1)
+ err(1, "fork failed");
+ if (pid == 0) { /* Child */
+ ptrace(PT_TRACE_ME, 0, 0, 0);
+ execvp(command[0], command);
+ err(1, "execvp %s", command[0]);
+ }
+
+ /* Only in the parent here */
+ if (waitpid(pid, NULL, 0) < 0)
+ err(1, "unexpected stop in waitpid");
+
+ new_proc(info, pid, 0);
+}
+
+/*
+ * start_tracing is called to attach to an existing process.
+ */
+void
+start_tracing(struct trussinfo *info, pid_t pid)
+{
+ int ret, retry;
+
+ retry = 10;
+ do {
+ ret = ptrace(PT_ATTACH, pid, NULL, 0);
+ usleep(200);
+ } while (ret && retry-- > 0);
+ if (ret)
+ err(1, "Cannot attach to target process");
+
+ if (waitpid(pid, NULL, 0) < 0)
+ err(1, "Unexpected stop in waitpid");
+
+ new_proc(info, pid, 0);
+}
+
+/*
+ * Restore a process back to it's pre-truss state.
+ * Called for SIGINT, SIGTERM, SIGQUIT. This only
+ * applies if truss was told to monitor an already-existing
+ * process.
+ */
+void
+restore_proc(int signo __unused)
+{
+
+ detaching = 1;
+}
+
+static void
+detach_proc(pid_t pid)
+{
+ int sig, status;
+
+ /*
+ * Stop the child so that we can detach. Filter out possible
+ * lingering SIGTRAP events buffered in the threads.
+ */
+ kill(pid, SIGSTOP);
+ for (;;) {
+ if (waitpid(pid, &status, 0) < 0)
+ err(1, "Unexpected error in waitpid");
+ sig = WIFSTOPPED(status) ? WSTOPSIG(status) : 0;
+ if (sig == SIGSTOP)
+ break;
+ if (sig == SIGTRAP)
+ sig = 0;
+ if (ptrace(PT_CONTINUE, pid, (caddr_t)1, sig) < 0)
+ err(1, "Can not continue for detach");
+ }
+
+ if (ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0)
+ err(1, "Can not detach the process");
+
+ kill(pid, SIGCONT);
+}
+
+/*
+ * Determine the ABI. This is called after every exec, and when
+ * a process is first monitored.
+ */
+static struct procabi *
+find_abi(pid_t pid)
+{
+ size_t len;
+ unsigned int i;
+ int error;
+ int mib[4];
+ char progt[32];
+
+ len = sizeof(progt);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_SV_NAME;
+ mib[3] = pid;
+ error = sysctl(mib, 4, progt, &len, NULL, 0);
+ if (error != 0)
+ err(2, "can not get sysvec name");
+
+ for (i = 0; i < nitems(abis); i++) {
+ if (strcmp(abis[i].name, progt) == 0)
+ return (abis[i].abi);
+ }
+ warnx("ABI %s for pid %ld is not supported", progt, (long)pid);
+ return (NULL);
+}
+
+static struct threadinfo *
+new_thread(struct procinfo *p, lwpid_t lwpid)
+{
+ struct threadinfo *nt;
+
+ /*
+ * If this happens it means there is a bug in truss. Unfortunately
+ * this will kill any processes truss is attached to.
+ */
+ LIST_FOREACH(nt, &p->threadlist, entries) {
+ if (nt->tid == lwpid)
+ errx(1, "Duplicate thread for LWP %ld", (long)lwpid);
+ }
+
+ nt = calloc(1, sizeof(struct threadinfo));
+ if (nt == NULL)
+ err(1, "calloc() failed");
+ nt->proc = p;
+ nt->tid = lwpid;
+ LIST_INSERT_HEAD(&p->threadlist, nt, entries);
+ return (nt);
+}
+
+static void
+free_thread(struct threadinfo *t)
+{
+
+ LIST_REMOVE(t, entries);
+ free(t);
+}
+
+static void
+add_threads(struct trussinfo *info, struct procinfo *p)
+{
+ struct ptrace_lwpinfo pl;
+ struct threadinfo *t;
+ lwpid_t *lwps;
+ int i, nlwps;
+
+ nlwps = ptrace(PT_GETNUMLWPS, p->pid, NULL, 0);
+ if (nlwps == -1)
+ err(1, "Unable to fetch number of LWPs");
+ assert(nlwps > 0);
+ lwps = calloc(nlwps, sizeof(*lwps));
+ nlwps = ptrace(PT_GETLWPLIST, p->pid, (caddr_t)lwps, nlwps);
+ if (nlwps == -1)
+ err(1, "Unable to fetch LWP list");
+ for (i = 0; i < nlwps; i++) {
+ t = new_thread(p, lwps[i]);
+ if (ptrace(PT_LWPINFO, lwps[i], (caddr_t)&pl, sizeof(pl)) == -1)
+ err(1, "ptrace(PT_LWPINFO)");
+ if (pl.pl_flags & PL_FLAG_SCE) {
+ info->curthread = t;
+ enter_syscall(info, t, &pl);
+ }
+ }
+ free(lwps);
+}
+
+static void
+new_proc(struct trussinfo *info, pid_t pid, lwpid_t lwpid)
+{
+ struct procinfo *np;
+
+ /*
+ * If this happens it means there is a bug in truss. Unfortunately
+ * this will kill any processes truss is attached to.
+ */
+ LIST_FOREACH(np, &info->proclist, entries) {
+ if (np->pid == pid)
+ errx(1, "Duplicate process for pid %ld", (long)pid);
+ }
+
+ if (info->flags & FOLLOWFORKS)
+ if (ptrace(PT_FOLLOW_FORK, pid, NULL, 1) == -1)
+ err(1, "Unable to follow forks for pid %ld", (long)pid);
+ if (ptrace(PT_LWP_EVENTS, pid, NULL, 1) == -1)
+ err(1, "Unable to enable LWP events for pid %ld", (long)pid);
+ np = calloc(1, sizeof(struct procinfo));
+ np->pid = pid;
+ np->abi = find_abi(pid);
+ LIST_INIT(&np->threadlist);
+ LIST_INSERT_HEAD(&info->proclist, np, entries);
+
+ if (lwpid != 0)
+ new_thread(np, lwpid);
+ else
+ add_threads(info, np);
+}
+
+static void
+free_proc(struct procinfo *p)
+{
+ struct threadinfo *t, *t2;
+
+ LIST_FOREACH_SAFE(t, &p->threadlist, entries, t2) {
+ free(t);
+ }
+ LIST_REMOVE(p, entries);
+ free(p);
+}
+
+static void
+detach_all_procs(struct trussinfo *info)
+{
+ struct procinfo *p, *p2;
+
+ LIST_FOREACH_SAFE(p, &info->proclist, entries, p2) {
+ detach_proc(p->pid);
+ free_proc(p);
+ }
+}
+
+static struct procinfo *
+find_proc(struct trussinfo *info, pid_t pid)
+{
+ struct procinfo *np;
+
+ LIST_FOREACH(np, &info->proclist, entries) {
+ if (np->pid == pid)
+ return (np);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Change curthread member based on (pid, lwpid).
+ */
+static void
+find_thread(struct trussinfo *info, pid_t pid, lwpid_t lwpid)
+{
+ struct procinfo *np;
+ struct threadinfo *nt;
+
+ np = find_proc(info, pid);
+ assert(np != NULL);
+
+ LIST_FOREACH(nt, &np->threadlist, entries) {
+ if (nt->tid == lwpid) {
+ info->curthread = nt;
+ return;
+ }
+ }
+ errx(1, "could not find thread");
+}
+
+/*
+ * When a process exits, it should have exactly one thread left.
+ * All of the other threads should have reported thread exit events.
+ */
+static void
+find_exit_thread(struct trussinfo *info, pid_t pid)
+{
+ struct procinfo *p;
+
+ p = find_proc(info, pid);
+ assert(p != NULL);
+
+ info->curthread = LIST_FIRST(&p->threadlist);
+ assert(info->curthread != NULL);
+ assert(LIST_NEXT(info->curthread, entries) == NULL);
+}
+
+static void
+alloc_syscall(struct threadinfo *t, struct ptrace_lwpinfo *pl)
+{
+ u_int i;
+
+ assert(t->in_syscall == 0);
+ assert(t->cs.number == 0);
+ assert(t->cs.sc == NULL);
+ assert(t->cs.nargs == 0);
+ for (i = 0; i < nitems(t->cs.s_args); i++)
+ assert(t->cs.s_args[i] == NULL);
+ memset(t->cs.args, 0, sizeof(t->cs.args));
+ t->cs.number = pl->pl_syscall_code;
+ t->in_syscall = 1;
+}
+
+static void
+free_syscall(struct threadinfo *t)
+{
+ u_int i;
+
+ for (i = 0; i < t->cs.nargs; i++)
+ free(t->cs.s_args[i]);
+ memset(&t->cs, 0, sizeof(t->cs));
+ t->in_syscall = 0;
+}
+
+static void
+enter_syscall(struct trussinfo *info, struct threadinfo *t,
+ struct ptrace_lwpinfo *pl)
+{
+ struct syscall *sc;
+ u_int i, narg;
+
+ alloc_syscall(t, pl);
+ narg = MIN(pl->pl_syscall_narg, nitems(t->cs.args));
+ if (narg != 0 && ptrace(PT_GET_SC_ARGS, t->tid, (caddr_t)t->cs.args,
+ sizeof(t->cs.args)) != 0) {
+ free_syscall(t);
+ return;
+ }
+
+ sc = get_syscall(t, t->cs.number, narg);
+ if (sc->unknown)
+ fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n",
+ t->proc->abi->type, t->cs.number);
+
+ t->cs.nargs = sc->decode.nargs;
+ assert(sc->decode.nargs <= nitems(t->cs.s_args));
+
+ t->cs.sc = sc;
+
+ /*
+ * At this point, we set up the system call arguments.
+ * We ignore any OUT ones, however -- those are arguments that
+ * are set by the system call, and so are probably meaningless
+ * now. This doesn't currently support arguments that are
+ * passed in *and* out, however.
+ */
+#if DEBUG
+ fprintf(stderr, "syscall %s(", sc->name);
+#endif
+ for (i = 0; i < t->cs.nargs; i++) {
+#if DEBUG
+ fprintf(stderr, "0x%lx%s",
+ t->cs.args[sc->decode.args[i].offset],
+ i < (t->cs.nargs - 1) ? "," : "");
+#endif
+ if (!(sc->decode.args[i].type & OUT)) {
+ t->cs.s_args[i] = print_arg(&sc->decode.args[i],
+ t->cs.args, NULL, info);
+ }
+ }
+#if DEBUG
+ fprintf(stderr, ")\n");
+#endif
+
+ clock_gettime(CLOCK_REALTIME, &t->before);
+}
+
+/*
+ * When a thread exits voluntarily (including when a thread calls
+ * exit() to trigger a process exit), the thread's internal state
+ * holds the arguments passed to the exit system call. When the
+ * thread's exit is reported, log that system call without a return
+ * value.
+ */
+static void
+thread_exit_syscall(struct trussinfo *info)
+{
+ struct threadinfo *t;
+
+ t = info->curthread;
+ if (!t->in_syscall)
+ return;
+
+ clock_gettime(CLOCK_REALTIME, &t->after);
+
+ print_syscall_ret(info, 0, NULL);
+ free_syscall(t);
+}
+
+static void
+exit_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl)
+{
+ struct threadinfo *t;
+ struct procinfo *p;
+ struct syscall *sc;
+ struct ptrace_sc_ret psr;
+ u_int i;
+
+ t = info->curthread;
+ if (!t->in_syscall)
+ return;
+
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ p = t->proc;
+ if (ptrace(PT_GET_SC_RET, t->tid, (caddr_t)&psr, sizeof(psr)) != 0) {
+ free_syscall(t);
+ return;
+ }
+
+ sc = t->cs.sc;
+ /*
+ * Here, we only look for arguments that have OUT masked in --
+ * otherwise, they were handled in enter_syscall().
+ */
+ for (i = 0; i < sc->decode.nargs; i++) {
+ char *temp;
+
+ if (sc->decode.args[i].type & OUT) {
+ /*
+ * If an error occurred, then don't bother
+ * getting the data; it may not be valid.
+ */
+ if (psr.sr_error != 0) {
+ asprintf(&temp, "0x%lx",
+ (long)t->cs.args[sc->decode.args[i].offset]);
+ } else {
+ temp = print_arg(&sc->decode.args[i],
+ t->cs.args, psr.sr_retval, info);
+ }
+ t->cs.s_args[i] = temp;
+ }
+ }
+
+ print_syscall_ret(info, psr.sr_error, psr.sr_retval);
+ free_syscall(t);
+
+ /*
+ * If the process executed a new image, check the ABI. If the
+ * new ABI isn't supported, stop tracing this process.
+ */
+ if (pl->pl_flags & PL_FLAG_EXEC) {
+ assert(LIST_NEXT(LIST_FIRST(&p->threadlist), entries) == NULL);
+ p->abi = find_abi(p->pid);
+ if (p->abi == NULL) {
+ if (ptrace(PT_DETACH, p->pid, (caddr_t)1, 0) < 0)
+ err(1, "Can not detach the process");
+ free_proc(p);
+ }
+ }
+}
+
+int
+print_line_prefix(struct trussinfo *info)
+{
+ struct timespec timediff;
+ struct threadinfo *t;
+ int len;
+
+ len = 0;
+ t = info->curthread;
+ if (info->flags & (FOLLOWFORKS | DISPLAYTIDS)) {
+ if (info->flags & FOLLOWFORKS)
+ len += fprintf(info->outfile, "%5d", t->proc->pid);
+ if ((info->flags & (FOLLOWFORKS | DISPLAYTIDS)) ==
+ (FOLLOWFORKS | DISPLAYTIDS))
+ len += fprintf(info->outfile, " ");
+ if (info->flags & DISPLAYTIDS)
+ len += fprintf(info->outfile, "%6d", t->tid);
+ len += fprintf(info->outfile, ": ");
+ }
+ if (info->flags & ABSOLUTETIMESTAMPS) {
+ timespecsub(&t->after, &info->start_time, &timediff);
+ len += fprintf(info->outfile, "%jd.%09ld ",
+ (intmax_t)timediff.tv_sec, timediff.tv_nsec);
+ }
+ if (info->flags & RELATIVETIMESTAMPS) {
+ timespecsub(&t->after, &t->before, &timediff);
+ len += fprintf(info->outfile, "%jd.%09ld ",
+ (intmax_t)timediff.tv_sec, timediff.tv_nsec);
+ }
+ return (len);
+}
+
+static void
+report_thread_death(struct trussinfo *info)
+{
+ struct threadinfo *t;
+
+ t = info->curthread;
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ print_line_prefix(info);
+ fprintf(info->outfile, "<thread %ld exited>\n", (long)t->tid);
+}
+
+static void
+report_thread_birth(struct trussinfo *info)
+{
+ struct threadinfo *t;
+
+ t = info->curthread;
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ t->before = t->after;
+ print_line_prefix(info);
+ fprintf(info->outfile, "<new thread %ld>\n", (long)t->tid);
+}
+
+static void
+report_exit(struct trussinfo *info, siginfo_t *si)
+{
+ struct threadinfo *t;
+
+ t = info->curthread;
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ print_line_prefix(info);
+ if (si->si_code == CLD_EXITED)
+ fprintf(info->outfile, "process exit, rval = %u\n",
+ si->si_status);
+ else
+ fprintf(info->outfile, "process killed, signal = %u%s\n",
+ si->si_status, si->si_code == CLD_DUMPED ?
+ " (core dumped)" : "");
+}
+
+static void
+report_new_child(struct trussinfo *info)
+{
+ struct threadinfo *t;
+
+ t = info->curthread;
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ t->before = t->after;
+ print_line_prefix(info);
+ fprintf(info->outfile, "<new process>\n");
+}
+
+void
+decode_siginfo(FILE *fp, siginfo_t *si)
+{
+ const char *str;
+
+ fprintf(fp, " code=");
+ str = sysdecode_sigcode(si->si_signo, si->si_code);
+ if (str == NULL)
+ fprintf(fp, "%d", si->si_code);
+ else
+ fprintf(fp, "%s", str);
+ switch (si->si_code) {
+ case SI_NOINFO:
+ break;
+ case SI_QUEUE:
+ fprintf(fp, " value=%p", si->si_value.sival_ptr);
+ /* FALLTHROUGH */
+ case SI_USER:
+ case SI_LWP:
+ fprintf(fp, " pid=%jd uid=%jd", (intmax_t)si->si_pid,
+ (intmax_t)si->si_uid);
+ break;
+ case SI_TIMER:
+ fprintf(fp, " value=%p", si->si_value.sival_ptr);
+ fprintf(fp, " timerid=%d", si->si_timerid);
+ fprintf(fp, " overrun=%d", si->si_overrun);
+ if (si->si_errno != 0)
+ fprintf(fp, " errno=%d", si->si_errno);
+ break;
+ case SI_ASYNCIO:
+ fprintf(fp, " value=%p", si->si_value.sival_ptr);
+ break;
+ case SI_MESGQ:
+ fprintf(fp, " value=%p", si->si_value.sival_ptr);
+ fprintf(fp, " mqd=%d", si->si_mqd);
+ break;
+ default:
+ switch (si->si_signo) {
+ case SIGILL:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ fprintf(fp, " trapno=%d", si->si_trapno);
+ fprintf(fp, " addr=%p", si->si_addr);
+ break;
+ case SIGCHLD:
+ fprintf(fp, " pid=%jd uid=%jd", (intmax_t)si->si_pid,
+ (intmax_t)si->si_uid);
+ fprintf(fp, " status=%d", si->si_status);
+ break;
+ }
+ }
+}
+
+static void
+report_signal(struct trussinfo *info, siginfo_t *si, struct ptrace_lwpinfo *pl)
+{
+ struct threadinfo *t;
+ const char *signame;
+
+ t = info->curthread;
+ clock_gettime(CLOCK_REALTIME, &t->after);
+ print_line_prefix(info);
+ signame = sysdecode_signal(si->si_status);
+ if (signame == NULL)
+ signame = "?";
+ fprintf(info->outfile, "SIGNAL %u (%s)", si->si_status, signame);
+ if (pl->pl_event == PL_EVENT_SIGNAL && pl->pl_flags & PL_FLAG_SI)
+ decode_siginfo(info->outfile, &pl->pl_siginfo);
+ fprintf(info->outfile, "\n");
+
+}
+
+/*
+ * Wait for events until all the processes have exited or truss has been
+ * asked to stop.
+ */
+void
+eventloop(struct trussinfo *info)
+{
+ struct ptrace_lwpinfo pl;
+ siginfo_t si;
+ int pending_signal;
+
+ while (!LIST_EMPTY(&info->proclist)) {
+ if (detaching) {
+ detach_all_procs(info);
+ return;
+ }
+
+ if (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) {
+ if (errno == EINTR)
+ continue;
+ err(1, "Unexpected error from waitid");
+ }
+
+ assert(si.si_signo == SIGCHLD);
+
+ switch (si.si_code) {
+ case CLD_EXITED:
+ case CLD_KILLED:
+ case CLD_DUMPED:
+ find_exit_thread(info, si.si_pid);
+ if ((info->flags & COUNTONLY) == 0) {
+ if (si.si_code == CLD_EXITED)
+ thread_exit_syscall(info);
+ report_exit(info, &si);
+ }
+ free_proc(info->curthread->proc);
+ info->curthread = NULL;
+ break;
+ case CLD_TRAPPED:
+ if (ptrace(PT_LWPINFO, si.si_pid, (caddr_t)&pl,
+ sizeof(pl)) == -1)
+ err(1, "ptrace(PT_LWPINFO)");
+
+ if (pl.pl_flags & PL_FLAG_CHILD) {
+ new_proc(info, si.si_pid, pl.pl_lwpid);
+ assert(LIST_FIRST(&info->proclist)->abi !=
+ NULL);
+ } else if (pl.pl_flags & PL_FLAG_BORN)
+ new_thread(find_proc(info, si.si_pid),
+ pl.pl_lwpid);
+ find_thread(info, si.si_pid, pl.pl_lwpid);
+
+ if (si.si_status == SIGTRAP &&
+ (pl.pl_flags & (PL_FLAG_BORN|PL_FLAG_EXITED|
+ PL_FLAG_SCE|PL_FLAG_SCX)) != 0) {
+ if (pl.pl_flags & PL_FLAG_BORN) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_thread_birth(info);
+ } else if (pl.pl_flags & PL_FLAG_EXITED) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_thread_death(info);
+ free_thread(info->curthread);
+ info->curthread = NULL;
+ } else if (pl.pl_flags & PL_FLAG_SCE)
+ enter_syscall(info, info->curthread, &pl);
+ else if (pl.pl_flags & PL_FLAG_SCX)
+ exit_syscall(info, &pl);
+ pending_signal = 0;
+ } else if (pl.pl_flags & PL_FLAG_CHILD) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_new_child(info);
+ pending_signal = 0;
+ } else {
+ if ((info->flags & NOSIGS) == 0)
+ report_signal(info, &si, &pl);
+ pending_signal = si.si_status;
+ }
+ ptrace(PT_SYSCALL, si.si_pid, (caddr_t)1,
+ pending_signal);
+ break;
+ case CLD_STOPPED:
+ errx(1, "waitid reported CLD_STOPPED");
+ case CLD_CONTINUED:
+ break;
+ }
+ }
+}
diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h
new file mode 100644
index 000000000000..d79ef882cff0
--- /dev/null
+++ b/usr.bin/truss/syscall.h
@@ -0,0 +1,275 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright 1997 Sean Eric Fagan
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sean Eric Fagan
+ * 4. Neither the name of the author may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * System call arguments come in several flavours:
+ * Hex -- values that should be printed in hex (addresses)
+ * Octal -- Same as above, but octal
+ * Int -- normal integer values (file descriptors, for example)
+ * LongHex -- long value that should be printed in hex
+ * Name -- pointer to a NULL-terminated string.
+ * BinString -- pointer to an array of chars, printed via strvisx().
+ * Ptr -- pointer to some unspecified structure. Just print as hex for now.
+ * Stat -- a pointer to a stat buffer. Prints a couple fields.
+ * Stat11 -- a pointer to a freebsd 11 stat buffer. Prints a couple fields.
+ * StatFs -- a pointer to a statfs buffer. Prints a few fields.
+ * Ioctl -- an ioctl command. Woefully limited.
+ * Quad -- a double-word value. e.g., lseek(int, offset_t, int)
+ * Signal -- a signal number. Prints the signal name (SIGxxx)
+ * Sockaddr -- a pointer to a struct sockaddr. Prints symbolic AF, and IP:Port
+ * StringArray -- a pointer to an array of string pointers.
+ * Timespec -- a pointer to a struct timespec. Prints both elements.
+ * Timeval -- a pointer to a struct timeval. Prints both elements.
+ * Timeval2 -- a pointer to two struct timevals. Prints both elements of both.
+ * Itimerval -- a pointer to a struct itimerval. Prints all elements.
+ * Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .events.
+ * Fd_set -- a pointer to an array of fd_set. Prints the fds that are set.
+ * Sigaction -- a pointer to a struct sigaction. Prints all elements.
+ * Sigset -- a pointer to a sigset_t. Prints the signals that are set.
+ * Sigprocmask -- the first argument to sigprocmask(). Prints the name.
+ * Kevent -- a pointer to an array of struct kevents. Prints all elements.
+ * Pathconf -- the 2nd argument of pathconf().
+ * Utrace -- utrace(2) buffer.
+ * CapRights -- a pointer to a cap_rights_t. Prints all set capabilities.
+ *
+ * In addition, the pointer types (String, Ptr) may have OUT masked in --
+ * this means that the data is set on *return* from the system call -- or
+ * IN (meaning that the data is passed *into* the system call).
+ */
+
+enum Argtype {
+ None = 1,
+
+ /* Scalar integers. */
+ Socklent,
+ Octal,
+ Int,
+ UInt,
+ Hex,
+ Long,
+ LongHex,
+ Sizet,
+ Quad,
+ QuadHex,
+
+ /* Encoded scalar values. */
+ Accessmode,
+ Acltype,
+ AiofsyncOp,
+ Atfd,
+ Atflags,
+ CapFcntlRights,
+ Closerangeflags,
+ Extattrnamespace,
+ Fadvice,
+ Fcntl,
+ Fcntlflag,
+ FileFlags,
+ Flockop,
+ Getfsstatmode,
+ Idtype,
+ Ioctl,
+ Itimerwhich,
+ Kldsymcmd,
+ Kldunloadflags,
+ LioMode,
+ Madvice,
+ Minherit,
+ Msgflags,
+ Mlockall,
+ Mmapflags,
+ Mountflags,
+ Mprot,
+ Msync,
+ Open,
+ Pathconf,
+ Pipe2,
+ Procctl,
+ Priowhich,
+ Ptraceop,
+ Sendfileflags,
+ Sendfilehdtr,
+ Quotactlcmd,
+ Reboothowto,
+ Resource,
+ Rforkflags,
+ Rtpriofunc,
+ RusageWho,
+ Schedpolicy,
+ ShmFlags,
+ Shutdown,
+ Signal,
+ Sigprocmask,
+ Sockdomain,
+ Sockoptlevel,
+ Sockoptname,
+ Sockprotocol,
+ Socktype,
+ Sysarch,
+ Sysctl,
+ Umtxop,
+ Waitoptions,
+ Whence,
+
+ /* Pointers to non-structures. */
+ Ptr,
+ AiocbArray,
+ AiocbPointer,
+ BinString,
+ CapRights,
+ ExecArgs,
+ ExecEnv,
+ ExitStatus,
+ Fd_set,
+ IntArray,
+ Iovec,
+ Name,
+ PipeFds,
+ PSig,
+ PQuadHex,
+ PUInt,
+ Readlinkres,
+ ShmName,
+ StringArray,
+
+ /* Pointers to structures. */
+ Aiocb,
+ Itimerval,
+ Kevent,
+ Kevent11,
+ LinuxSockArgs,
+ Msghdr,
+ Pollfd,
+ Rlimit,
+ Rusage,
+ Schedparam,
+ Sctpsndrcvinfo,
+ Sigaction,
+ Sigevent,
+ Siginfo,
+ Sigset,
+ Sockaddr,
+ Stat,
+ Stat11,
+ StatFs,
+ Timespec,
+ Timespec2,
+ Timeval,
+ Timeval2,
+ Utrace,
+
+ MAX_ARG_TYPE,
+};
+
+#define ARG_MASK 0xff
+#define OUT 0x100
+#define IN /*0x20*/0
+
+_Static_assert(ARG_MASK > MAX_ARG_TYPE,
+ "ARG_MASK overlaps with Argtype values");
+
+struct syscall_arg {
+ enum Argtype type;
+ int offset;
+};
+
+struct syscall_decode {
+ const char *name; /* Name for calling convention lookup. */
+ /*
+ * Syscall return type:
+ * 0: no return value (e.g. exit)
+ * 1: normal return value (a single int/long/pointer)
+ * 2: off_t return value (two values for 32-bit ABIs)
+ */
+ u_int ret_type;
+ u_int nargs; /* number of meaningful arguments */
+ struct syscall_arg args[10]; /* Hopefully no syscalls with > 10 args */
+};
+
+struct syscall {
+ STAILQ_ENTRY(syscall) entries;
+ const char *name; /* Name to be displayed, might be malloc()'d */
+ struct syscall_decode decode;
+ struct timespec time; /* Time spent for this call */
+ int ncalls; /* Number of calls */
+ int nerror; /* Number of calls that returned with error */
+ bool unknown; /* Unknown system call */
+};
+
+struct syscall *get_syscall(struct threadinfo *, u_int, u_int);
+char *print_arg(struct syscall_arg *, syscallarg_t *, syscallarg_t *,
+ struct trussinfo *);
+
+/*
+ * Linux Socket defines
+ */
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+#define LINUX_SENDMSG 16
+#define LINUX_RECVMSG 17
+
+#define PAD_(t) (sizeof(syscallarg_t) <= sizeof(t) ? \
+ 0 : sizeof(syscallarg_t) - sizeof(t))
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define PADL_(t) 0
+#define PADR_(t) PAD_(t)
+#else
+#define PADL_(t) PAD_(t)
+#define PADR_(t) 0
+#endif
+
+typedef int l_int;
+typedef uint32_t l_ulong;
+
+struct linux_socketcall_args {
+ char what_l_[PADL_(l_int)]; l_int what; char what_r_[PADR_(l_int)];
+ char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)];
+};
+
+void print_syscall(struct trussinfo *);
+void print_syscall_ret(struct trussinfo *, int, syscallarg_t *);
+void print_summary(struct trussinfo *trussinfo);
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
new file mode 100644
index 000000000000..47d6aef8f6ff
--- /dev/null
+++ b/usr.bin/truss/syscalls.c
@@ -0,0 +1,2832 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright 1997 Sean Eric Fagan
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sean Eric Fagan
+ * 4. Neither the name of the author may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
+/*
+ * This file has routines used to print out system calls and their
+ * arguments.
+ */
+
+#include <sys/aio.h>
+#include <sys/capsicum.h>
+#include <sys/types.h>
+#define _WANT_FREEBSD11_KEVENT
+#include <sys/event.h>
+#include <sys/ioccom.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/poll.h>
+#include <sys/procfs.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/sched.h>
+#include <sys/socket.h>
+#define _WANT_FREEBSD11_STAT
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/sctp.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#define _WANT_KERNEL_ERRNO
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysdecode.h>
+#include <unistd.h>
+#include <vis.h>
+
+#include "truss.h"
+#include "extern.h"
+#include "syscall.h"
+
+/*
+ * This should probably be in its own file, sorted alphabetically.
+ *
+ * Note: We only scan this table on the initial syscall number to calling
+ * convention lookup, i.e. once each time a new syscall is encountered. This
+ * is unlikely to be a performance issue, but if it is we could sort this array
+ * and use a binary search instead.
+ */
+static const struct syscall_decode decoded_syscalls[] = {
+ /* Native ABI */
+ { .name = "__acl_aclcheck_fd", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_aclcheck_file", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_aclcheck_link", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_delete_fd", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Acltype, 1 } } },
+ { .name = "__acl_delete_file", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Acltype, 1 } } },
+ { .name = "__acl_delete_link", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Acltype, 1 } } },
+ { .name = "__acl_get_fd", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_get_file", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_get_link", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_set_fd", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_set_file", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__acl_set_link", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Acltype, 1 }, { Ptr, 2 } } },
+ { .name = "__cap_rights_get", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
+ { .name = "__getcwd", .ret_type = 1, .nargs = 2,
+ .args = { { Name | OUT, 0 }, { Int, 1 } } },
+ { .name = "__realpathat", .ret_type = 1, .nargs = 5,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Name | OUT, 2 },
+ { Sizet, 3 }, { Int, 4} } },
+ { .name = "_umtx_op", .ret_type = 1, .nargs = 5,
+ .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
+ { Ptr, 4 } } },
+ { .name = "accept", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+ { .name = "access", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
+ { .name = "aio_cancel", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Aiocb, 1 } } },
+ { .name = "aio_error", .ret_type = 1, .nargs = 1,
+ .args = { { Aiocb, 0 } } },
+ { .name = "aio_fsync", .ret_type = 1, .nargs = 2,
+ .args = { { AiofsyncOp, 0 }, { Aiocb, 1 } } },
+ { .name = "aio_mlock", .ret_type = 1, .nargs = 1,
+ .args = { { Aiocb, 0 } } },
+ { .name = "aio_read", .ret_type = 1, .nargs = 1,
+ .args = { { Aiocb, 0 } } },
+ { .name = "aio_return", .ret_type = 1, .nargs = 1,
+ .args = { { Aiocb, 0 } } },
+ { .name = "aio_suspend", .ret_type = 1, .nargs = 3,
+ .args = { { AiocbArray, 0 }, { Int, 1 }, { Timespec, 2 } } },
+ { .name = "aio_waitcomplete", .ret_type = 1, .nargs = 2,
+ .args = { { AiocbPointer | OUT, 0 }, { Timespec, 1 } } },
+ { .name = "aio_write", .ret_type = 1, .nargs = 1,
+ .args = { { Aiocb, 0 } } },
+ { .name = "bind", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
+ { .name = "bindat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
+ { Int, 3 } } },
+ { .name = "break", .ret_type = 1, .nargs = 1,
+ .args = { { Ptr, 0 } } },
+ { .name = "cap_fcntls_get", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { CapFcntlRights | OUT, 1 } } },
+ { .name = "cap_fcntls_limit", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { CapFcntlRights, 1 } } },
+ { .name = "cap_getmode", .ret_type = 1, .nargs = 1,
+ .args = { { PUInt | OUT, 0 } } },
+ { .name = "cap_rights_limit", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { CapRights, 1 } } },
+ { .name = "chdir", .ret_type = 1, .nargs = 1,
+ .args = { { Name, 0 } } },
+ { .name = "chflags", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
+ { .name = "chflagsat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { FileFlags, 2 },
+ { Atflags, 3 } } },
+ { .name = "chmod", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "chown", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "chroot", .ret_type = 1, .nargs = 1,
+ .args = { { Name, 0 } } },
+ { .name = "clock_gettime", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
+ { .name = "close", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "closefrom", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "close_range", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { Closerangeflags, 2 } } },
+ { .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
+ { .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat11 | OUT, 2 },
+ { Atflags, 3 } } },
+ { .name = "compat11.kevent", .ret_type = 1, .nargs = 6,
+ .args = { { Int, 0 }, { Kevent11, 1 }, { Int, 2 },
+ { Kevent11 | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
+ { .name = "compat11.lstat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
+ { .name = "compat11.mknod", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
+ { .name = "compat11.mknodat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
+ { .name = "compat11.stat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Stat11 | OUT, 1 } } },
+ { .name = "connect", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
+ { .name = "connectat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
+ { Int, 3 } } },
+ { .name = "dup", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "dup2", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Int, 1 } } },
+ { .name = "eaccess", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
+ { .name = "execve", .ret_type = 1, .nargs = 3,
+ .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
+ { ExecEnv | IN, 2 } } },
+ { .name = "exit", .ret_type = 0, .nargs = 1,
+ .args = { { Hex, 0 } } },
+ { .name = "extattr_delete_fd", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
+ { .name = "extattr_delete_file", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
+ { .name = "extattr_delete_link", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 } } },
+ { .name = "extattr_get_fd", .ret_type = 1, .nargs = 5,
+ .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | OUT, 3 }, { Sizet, 4 } } },
+ { .name = "extattr_get_file", .ret_type = 1, .nargs = 5,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | OUT, 3 }, { Sizet, 4 } } },
+ { .name = "extattr_get_link", .ret_type = 1, .nargs = 5,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | OUT, 3 }, { Sizet, 4 } } },
+ { .name = "extattr_list_fd", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
+ { Sizet, 3 } } },
+ { .name = "extattr_list_file", .ret_type = 1, .nargs = 4,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
+ { Sizet, 3 } } },
+ { .name = "extattr_list_link", .ret_type = 1, .nargs = 4,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { BinString | OUT, 2 },
+ { Sizet, 3 } } },
+ { .name = "extattr_set_fd", .ret_type = 1, .nargs = 5,
+ .args = { { Int, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | IN, 3 }, { Sizet, 4 } } },
+ { .name = "extattr_set_file", .ret_type = 1, .nargs = 5,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | IN, 3 }, { Sizet, 4 } } },
+ { .name = "extattr_set_link", .ret_type = 1, .nargs = 5,
+ .args = { { Name, 0 }, { Extattrnamespace, 1 }, { Name, 2 },
+ { BinString | IN, 3 }, { Sizet, 4 } } },
+ { .name = "extattrctl", .ret_type = 1, .nargs = 5,
+ .args = { { Name, 0 }, { Hex, 1 }, { Name, 2 },
+ { Extattrnamespace, 3 }, { Name, 4 } } },
+ { .name = "faccessat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
+ { Atflags, 3 } } },
+ { .name = "fchflags", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { FileFlags, 1 } } },
+ { .name = "fchmod", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Octal, 1 } } },
+ { .name = "fchmodat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
+ { .name = "fchown", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "fchownat", .ret_type = 1, .nargs = 5,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
+ { Atflags, 4 } } },
+ { .name = "fcntl", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
+ { .name = "fdatasync", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "flock", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Flockop, 1 } } },
+ { .name = "fstat", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Stat | OUT, 1 } } },
+ { .name = "fstatat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
+ { Atflags, 3 } } },
+ { .name = "fstatfs", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { StatFs | OUT, 1 } } },
+ { .name = "fsync", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "ftruncate", .ret_type = 1, .nargs = 2,
+ .args = { { Int | IN, 0 }, { QuadHex | IN, 1 } } },
+ { .name = "futimens", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
+ { .name = "futimes", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
+ { .name = "futimesat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
+ { .name = "getdirentries", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 },
+ { PQuadHex | OUT, 3 } } },
+ { .name = "getfsstat", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { Long, 1 }, { Getfsstatmode, 2 } } },
+ { .name = "getitimer", .ret_type = 1, .nargs = 2,
+ .args = { { Itimerwhich, 0 }, { Itimerval | OUT, 2 } } },
+ { .name = "getpeername", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+ { .name = "getpgid", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "getpriority", .ret_type = 1, .nargs = 2,
+ .args = { { Priowhich, 0 }, { Int, 1 } } },
+ { .name = "getrandom", .ret_type = 1, .nargs = 3,
+ .args = { { BinString | OUT, 0 }, { Sizet, 1 }, { UInt, 2 } } },
+ { .name = "getrlimit", .ret_type = 1, .nargs = 2,
+ .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } },
+ { .name = "getrusage", .ret_type = 1, .nargs = 2,
+ .args = { { RusageWho, 0 }, { Rusage | OUT, 1 } } },
+ { .name = "getsid", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "getsockname", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
+ { .name = "getsockopt", .ret_type = 1, .nargs = 5,
+ .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
+ { Ptr | OUT, 3 }, { Ptr | OUT, 4 } } },
+ { .name = "gettimeofday", .ret_type = 1, .nargs = 2,
+ .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } },
+ { .name = "ioctl", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Ioctl, 1 }, { Ptr, 2 } } },
+ { .name = "kevent", .ret_type = 1, .nargs = 6,
+ .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
+ { Int, 4 }, { Timespec, 5 } } },
+ { .name = "kill", .ret_type = 1, .nargs = 2,
+ .args = { { Int | IN, 0 }, { Signal | IN, 1 } } },
+ { .name = "kldfind", .ret_type = 1, .nargs = 1,
+ .args = { { Name | IN, 0 } } },
+ { .name = "kldfirstmod", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "kldload", .ret_type = 1, .nargs = 1,
+ .args = { { Name | IN, 0 } } },
+ { .name = "kldnext", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "kldstat", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Ptr, 1 } } },
+ { .name = "kldsym", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Kldsymcmd, 1 }, { Ptr, 2 } } },
+ { .name = "kldunload", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "kldunloadf", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Kldunloadflags, 1 } } },
+ { .name = "kse_release", .ret_type = 0, .nargs = 1,
+ .args = { { Timespec, 0 } } },
+ { .name = "lchflags", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { FileFlags, 1 } } },
+ { .name = "lchmod", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "lchown", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "link", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "linkat", .ret_type = 1, .nargs = 5,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
+ { Atflags, 4 } } },
+ { .name = "lio_listio", .ret_type = 1, .nargs = 4,
+ .args = { { LioMode, 0 }, { AiocbArray, 1 }, { Int, 2 },
+ { Sigevent, 3 } } },
+ { .name = "listen", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Int, 1 } } },
+ { .name = "lseek", .ret_type = 2, .nargs = 3,
+ .args = { { Int, 0 }, { QuadHex, 1 }, { Whence, 2 } } },
+ { .name = "lstat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
+ { .name = "lutimes", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
+ { .name = "madvise", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { Sizet, 1 }, { Madvice, 2 } } },
+ { .name = "minherit", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { Sizet, 1 }, { Minherit, 2 } } },
+ { .name = "mkdir", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "mkdirat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
+ { .name = "mkfifo", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "mkfifoat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
+ { .name = "mknod", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Octal, 1 }, { Quad, 2 } } },
+ { .name = "mknodat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Quad, 3 } } },
+ { .name = "mlock", .ret_type = 1, .nargs = 2,
+ .args = { { Ptr, 0 }, { Sizet, 1 } } },
+ { .name = "mlockall", .ret_type = 1, .nargs = 1,
+ .args = { { Mlockall, 0 } } },
+ { .name = "mmap", .ret_type = 1, .nargs = 6,
+ .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
+ { Int, 4 }, { QuadHex, 5 } } },
+ { .name = "modfind", .ret_type = 1, .nargs = 1,
+ .args = { { Name | IN, 0 } } },
+ { .name = "mount", .ret_type = 1, .nargs = 4,
+ .args = { { Name, 0 }, { Name, 1 }, { Mountflags, 2 }, { Ptr, 3 } } },
+ { .name = "mprotect", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { Sizet, 1 }, { Mprot, 2 } } },
+ { .name = "msync", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { Sizet, 1 }, { Msync, 2 } } },
+ { .name = "munlock", .ret_type = 1, .nargs = 2,
+ .args = { { Ptr, 0 }, { Sizet, 1 } } },
+ { .name = "munmap", .ret_type = 1, .nargs = 2,
+ .args = { { Ptr, 0 }, { Sizet, 1 } } },
+ { .name = "nanosleep", .ret_type = 1, .nargs = 1,
+ .args = { { Timespec, 0 } } },
+ { .name = "nmount", .ret_type = 1, .nargs = 3,
+ .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } },
+ { .name = "open", .ret_type = 1, .nargs = 3,
+ .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
+ { .name = "openat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
+ { Octal, 3 } } },
+ { .name = "pathconf", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Pathconf, 1 } } },
+ { .name = "pipe", .ret_type = 1, .nargs = 1,
+ .args = { { PipeFds | OUT, 0 } } },
+ { .name = "pipe2", .ret_type = 1, .nargs = 2,
+ .args = { { Ptr, 0 }, { Pipe2, 1 } } },
+ { .name = "poll", .ret_type = 1, .nargs = 3,
+ .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "posix_fadvise", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { QuadHex, 1 }, { QuadHex, 2 },
+ { Fadvice, 3 } } },
+ { .name = "posix_openpt", .ret_type = 1, .nargs = 1,
+ .args = { { Open, 0 } } },
+ { .name = "ppoll", .ret_type = 1, .nargs = 4,
+ .args = { { Pollfd, 0 }, { Int, 1 }, { Timespec | IN, 2 },
+ { Sigset | IN, 3 } } },
+ { .name = "pread", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
+ { QuadHex, 3 } } },
+ { .name = "preadv", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
+ { QuadHex, 3 } } },
+ { .name = "procctl", .ret_type = 1, .nargs = 4,
+ .args = { { Idtype, 0 }, { Quad, 1 }, { Procctl, 2 }, { Ptr, 3 } } },
+ { .name = "ptrace", .ret_type = 1, .nargs = 4,
+ .args = { { Ptraceop, 0 }, { Int, 1 }, { Ptr, 2 }, { Int, 3 } } },
+ { .name = "pwrite", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
+ { QuadHex, 3 } } },
+ { .name = "pwritev", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
+ { QuadHex, 3 } } },
+ { .name = "quotactl", .ret_type = 1, .nargs = 4,
+ .args = { { Name, 0 }, { Quotactlcmd, 1 }, { Int, 2 }, { Ptr, 3 } } },
+ { .name = "read", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 } } },
+ { .name = "readlink", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Sizet, 2 } } },
+ { .name = "readlinkat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
+ { Sizet, 3 } } },
+ { .name = "readv", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 } } },
+ { .name = "reboot", .ret_type = 1, .nargs = 1,
+ .args = { { Reboothowto, 0 } } },
+ { .name = "recvfrom", .ret_type = 1, .nargs = 6,
+ .args = { { Int, 0 }, { BinString | OUT, 1 }, { Sizet, 2 },
+ { Msgflags, 3 }, { Sockaddr | OUT, 4 },
+ { Ptr | OUT, 5 } } },
+ { .name = "recvmsg", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Msghdr | OUT, 1 }, { Msgflags, 2 } } },
+ { .name = "rename", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "renameat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
+ { .name = "rfork", .ret_type = 1, .nargs = 1,
+ .args = { { Rforkflags, 0 } } },
+ { .name = "rmdir", .ret_type = 1, .nargs = 1,
+ .args = { { Name, 0 } } },
+ { .name = "rtprio", .ret_type = 1, .nargs = 3,
+ .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
+ { .name = "rtprio_thread", .ret_type = 1, .nargs = 3,
+ .args = { { Rtpriofunc, 0 }, { Int, 1 }, { Ptr, 2 } } },
+ { .name = "sched_get_priority_max", .ret_type = 1, .nargs = 1,
+ .args = { { Schedpolicy, 0 } } },
+ { .name = "sched_get_priority_min", .ret_type = 1, .nargs = 1,
+ .args = { { Schedpolicy, 0 } } },
+ { .name = "sched_getparam", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Schedparam | OUT, 1 } } },
+ { .name = "sched_getscheduler", .ret_type = 1, .nargs = 1,
+ .args = { { Int, 0 } } },
+ { .name = "sched_rr_get_interval", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Timespec | OUT, 1 } } },
+ { .name = "sched_setparam", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Schedparam, 1 } } },
+ { .name = "sched_setscheduler", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Schedpolicy, 1 }, { Schedparam, 2 } } },
+ { .name = "sctp_generic_recvmsg", .ret_type = 1, .nargs = 7,
+ .args = { { Int, 0 }, { Iovec | OUT, 1 }, { Int, 2 },
+ { Sockaddr | OUT, 3 }, { Ptr | OUT, 4 },
+ { Sctpsndrcvinfo | OUT, 5 }, { Ptr | OUT, 6 } } },
+ { .name = "sctp_generic_sendmsg", .ret_type = 1, .nargs = 7,
+ .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 },
+ { Sockaddr | IN, 3 }, { Socklent, 4 },
+ { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
+ { .name = "sctp_generic_sendmsg_iov", .ret_type = 1, .nargs = 7,
+ .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 },
+ { Sockaddr | IN, 3 }, { Socklent, 4 },
+ { Sctpsndrcvinfo | IN, 5 }, { Msgflags, 6 } } },
+ { .name = "sendfile", .ret_type = 1, .nargs = 7,
+ .args = { { Int, 0 }, { Int, 1 }, { QuadHex, 2 }, { Sizet, 3 },
+ { Sendfilehdtr, 4 }, { QuadHex | OUT, 5 },
+ { Sendfileflags, 6 } } },
+ { .name = "select", .ret_type = 1, .nargs = 5,
+ .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
+ { Timeval, 4 } } },
+ { .name = "sendmsg", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Msghdr | IN, 1 }, { Msgflags, 2 } } },
+ { .name = "sendto", .ret_type = 1, .nargs = 6,
+ .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 },
+ { Msgflags, 3 }, { Sockaddr | IN, 4 },
+ { Socklent | IN, 5 } } },
+ { .name = "setitimer", .ret_type = 1, .nargs = 3,
+ .args = { { Itimerwhich, 0 }, { Itimerval, 1 },
+ { Itimerval | OUT, 2 } } },
+ { .name = "setpriority", .ret_type = 1, .nargs = 3,
+ .args = { { Priowhich, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "setrlimit", .ret_type = 1, .nargs = 2,
+ .args = { { Resource, 0 }, { Rlimit | IN, 1 } } },
+ { .name = "setsockopt", .ret_type = 1, .nargs = 5,
+ .args = { { Int, 0 }, { Sockoptlevel, 1 }, { Sockoptname, 2 },
+ { Ptr | IN, 3 }, { Socklent, 4 } } },
+ { .name = "shm_open", .ret_type = 1, .nargs = 3,
+ .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
+ { .name = "shm_open2", .ret_type = 1, .nargs = 5,
+ .args = { { ShmName | IN, 0 }, { Open, 1 }, { Octal, 2 },
+ { ShmFlags, 3 }, { Name | IN, 4 } } },
+ { .name = "shm_rename", .ret_type = 1, .nargs = 3,
+ .args = { { Name | IN, 0 }, { Name | IN, 1 }, { Hex, 2 } } },
+ { .name = "shm_unlink", .ret_type = 1, .nargs = 1,
+ .args = { { Name | IN, 0 } } },
+ { .name = "shutdown", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Shutdown, 1 } } },
+ { .name = "sigaction", .ret_type = 1, .nargs = 3,
+ .args = { { Signal, 0 }, { Sigaction | IN, 1 },
+ { Sigaction | OUT, 2 } } },
+ { .name = "sigpending", .ret_type = 1, .nargs = 1,
+ .args = { { Sigset | OUT, 0 } } },
+ { .name = "sigprocmask", .ret_type = 1, .nargs = 3,
+ .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
+ { .name = "sigqueue", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } },
+ { .name = "sigreturn", .ret_type = 1, .nargs = 1,
+ .args = { { Ptr, 0 } } },
+ { .name = "sigsuspend", .ret_type = 1, .nargs = 1,
+ .args = { { Sigset | IN, 0 } } },
+ { .name = "sigtimedwait", .ret_type = 1, .nargs = 3,
+ .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 },
+ { Timespec | IN, 2 } } },
+ { .name = "sigwait", .ret_type = 1, .nargs = 2,
+ .args = { { Sigset | IN, 0 }, { PSig | OUT, 1 } } },
+ { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2,
+ .args = { { Sigset | IN, 0 }, { Siginfo | OUT, 1 } } },
+ { .name = "socket", .ret_type = 1, .nargs = 3,
+ .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Sockprotocol, 2 } } },
+ { .name = "stat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
+ { .name = "statfs", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } },
+ { .name = "symlink", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "symlinkat", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
+ { .name = "sysarch", .ret_type = 1, .nargs = 2,
+ .args = { { Sysarch, 0 }, { Ptr, 1 } } },
+ { .name = "__sysctl", .ret_type = 1, .nargs = 6,
+ .args = { { Sysctl, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
+ { Ptr, 4 }, { Sizet, 5 } } },
+ { .name = "__sysctlbyname", .ret_type = 1, .nargs = 6,
+ .args = { { Name, 0 }, { Sizet, 1 }, { Ptr, 2 }, { Ptr, 3 },
+ { Ptr, 4}, { Sizet, 5 } } },
+ { .name = "thr_kill", .ret_type = 1, .nargs = 2,
+ .args = { { Long, 0 }, { Signal, 1 } } },
+ { .name = "thr_self", .ret_type = 1, .nargs = 1,
+ .args = { { Ptr, 0 } } },
+ { .name = "thr_set_name", .ret_type = 1, .nargs = 2,
+ .args = { { Long, 0 }, { Name, 1 } } },
+ { .name = "truncate", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { QuadHex | IN, 1 } } },
+ { .name = "unlink", .ret_type = 1, .nargs = 1,
+ .args = { { Name, 0 } } },
+ { .name = "unlinkat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
+ { .name = "unmount", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Mountflags, 1 } } },
+ { .name = "utimensat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
+ { Atflags, 3 } } },
+ { .name = "utimes", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
+ { .name = "utrace", .ret_type = 1, .nargs = 1,
+ .args = { { Utrace, 0 } } },
+ { .name = "wait4", .ret_type = 1, .nargs = 4,
+ .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 },
+ { Rusage | OUT, 3 } } },
+ { .name = "wait6", .ret_type = 1, .nargs = 6,
+ .args = { { Idtype, 0 }, { Quad, 1 }, { ExitStatus | OUT, 2 },
+ { Waitoptions, 3 }, { Rusage | OUT, 4 },
+ { Siginfo | OUT, 5 } } },
+ { .name = "write", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { BinString | IN, 1 }, { Sizet, 2 } } },
+ { .name = "writev", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Iovec | IN, 1 }, { Int, 2 } } },
+
+ /* Linux ABI */
+ { .name = "linux_access", .ret_type = 1, .nargs = 2,
+ .args = { { Name, 0 }, { Accessmode, 1 } } },
+ { .name = "linux_execve", .ret_type = 1, .nargs = 3,
+ .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 },
+ { ExecEnv | IN, 2 } } },
+ { .name = "linux_getitimer", .ret_type = 1, .nargs = 2,
+ .args = { { Itimerwhich, 0 }, { Itimerval | OUT, 2 } } },
+ { .name = "linux_lseek", .ret_type = 2, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
+ { .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Int, 1 } } },
+ { .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Ptr | OUT, 1 } } },
+ { .name = "linux_newlstat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
+ { .name = "linux_newstat", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
+ { .name = "linux_open", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
+ { .name = "linux_readlink", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Name | OUT, 1 }, { Sizet, 2 } } },
+ { .name = "linux_setitimer", .ret_type = 1, .nargs = 3,
+ .args = { { Itimerwhich, 0 }, { Itimerval, 1 },
+ { Itimerval | OUT, 2 } } },
+ { .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
+ { .name = "linux_stat64", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
+};
+static STAILQ_HEAD(, syscall) seen_syscalls;
+
+/* Xlat idea taken from strace */
+struct xlat {
+ int val;
+ const char *str;
+};
+
+#define X(a) { a, #a },
+#define XEND { 0, NULL }
+
+static struct xlat poll_flags[] = {
+ X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
+ X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
+ X(POLLWRBAND) X(POLLINIGNEOF) X(POLLRDHUP) XEND
+};
+
+static struct xlat sigaction_flags[] = {
+ X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP)
+ X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND
+};
+
+static struct xlat linux_socketcall_ops[] = {
+ X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN)
+ X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME)
+ X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO)
+ X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT)
+ X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG)
+ XEND
+};
+
+static struct xlat lio_modes[] = {
+ X(LIO_WAIT) X(LIO_NOWAIT)
+ XEND
+};
+
+static struct xlat lio_opcodes[] = {
+ X(LIO_WRITE) X(LIO_READ) X(LIO_READV) X(LIO_WRITEV) X(LIO_NOP)
+ XEND
+};
+
+static struct xlat aio_fsync_ops[] = {
+ X(O_SYNC)
+ XEND
+};
+
+#undef X
+#undef XEND
+
+/*
+ * Searches an xlat array for a value, and returns it if found. Otherwise
+ * return a string representation.
+ */
+static const char *
+lookup(struct xlat *xlat, int val, int base)
+{
+ static char tmp[16];
+
+ for (; xlat->str != NULL; xlat++)
+ if (xlat->val == val)
+ return (xlat->str);
+ switch (base) {
+ case 8:
+ sprintf(tmp, "0%o", val);
+ break;
+ case 16:
+ sprintf(tmp, "0x%x", val);
+ break;
+ case 10:
+ sprintf(tmp, "%u", val);
+ break;
+ default:
+ errx(1, "Unknown lookup base");
+ }
+ return (tmp);
+}
+
+static const char *
+xlookup(struct xlat *xlat, int val)
+{
+
+ return (lookup(xlat, val, 16));
+}
+
+/*
+ * Searches an xlat array containing bitfield values. Remaining bits
+ * set after removing the known ones are printed at the end:
+ * IN|0x400.
+ */
+static char *
+xlookup_bits(struct xlat *xlat, int val)
+{
+ int len, rem;
+ static char str[512];
+
+ len = 0;
+ rem = val;
+ for (; xlat->str != NULL; xlat++) {
+ if ((xlat->val & rem) == xlat->val) {
+ /*
+ * Don't print the "all-bits-zero" string unless all
+ * bits are really zero.
+ */
+ if (xlat->val == 0 && val != 0)
+ continue;
+ len += sprintf(str + len, "%s|", xlat->str);
+ rem &= ~(xlat->val);
+ }
+ }
+
+ /*
+ * If we have leftover bits or didn't match anything, print
+ * the remainder.
+ */
+ if (rem || len == 0)
+ len += sprintf(str + len, "0x%x", rem);
+ if (len && str[len - 1] == '|')
+ len--;
+ str[len] = 0;
+ return (str);
+}
+
+static void
+print_integer_arg(const char *(*decoder)(int), FILE *fp, int value)
+{
+ const char *str;
+
+ str = decoder(value);
+ if (str != NULL)
+ fputs(str, fp);
+ else
+ fprintf(fp, "%d", value);
+}
+
+static bool
+print_mask_arg_part(bool (*decoder)(FILE *, int, int *), FILE *fp, int value,
+ int *rem)
+{
+
+ return (decoder(fp, value, rem));
+}
+
+static void
+print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value)
+{
+ int rem;
+
+ if (!print_mask_arg_part(decoder, fp, value, &rem))
+ fprintf(fp, "0x%x", rem);
+ else if (rem != 0)
+ fprintf(fp, "|0x%x", rem);
+}
+
+static void
+print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), FILE *fp,
+ uint32_t value)
+{
+ uint32_t rem;
+
+ if (!decoder(fp, value, &rem))
+ fprintf(fp, "0x%x", rem);
+ else if (rem != 0)
+ fprintf(fp, "|0x%x", rem);
+}
+
+/*
+ * Add argument padding to subsequent system calls after Quad
+ * syscall arguments as needed. This used to be done by hand in the
+ * decoded_syscalls table which was ugly and error prone. It is
+ * simpler to do the fixup of offsets at initialization time than when
+ * decoding arguments.
+ */
+static void
+quad_fixup(struct syscall_decode *sc)
+{
+ int offset, prev;
+ u_int i;
+
+ offset = 0;
+ prev = -1;
+ for (i = 0; i < sc->nargs; i++) {
+ /* This arg type is a dummy that doesn't use offset. */
+ if ((sc->args[i].type & ARG_MASK) == PipeFds)
+ continue;
+
+ assert(prev < sc->args[i].offset);
+ prev = sc->args[i].offset;
+ sc->args[i].offset += offset;
+ switch (sc->args[i].type & ARG_MASK) {
+ case Quad:
+ case QuadHex:
+#if defined(__powerpc__) || defined(__arm__) || defined(__aarch64__)
+ /*
+ * 64-bit arguments on 32-bit powerpc and arm must be
+ * 64-bit aligned. If the current offset is
+ * not aligned, the calling convention inserts
+ * a 32-bit pad argument that should be skipped.
+ */
+ if (sc->args[i].offset % 2 == 1) {
+ sc->args[i].offset++;
+ offset++;
+ }
+#endif
+ offset++;
+ default:
+ break;
+ }
+ }
+}
+
+static struct syscall *
+find_syscall(struct procabi *abi, u_int number)
+{
+ struct extra_syscall *es;
+
+ if (number < nitems(abi->syscalls))
+ return (abi->syscalls[number]);
+ STAILQ_FOREACH(es, &abi->extra_syscalls, entries) {
+ if (es->number == number)
+ return (es->sc);
+ }
+ return (NULL);
+}
+
+static void
+add_syscall(struct procabi *abi, u_int number, struct syscall *sc)
+{
+ struct extra_syscall *es;
+
+ /*
+ * quad_fixup() is currently needed for all 32-bit ABIs.
+ * TODO: This should probably be a function pointer inside struct
+ * procabi instead.
+ */
+ if (abi->pointer_size == 4)
+ quad_fixup(&sc->decode);
+
+ if (number < nitems(abi->syscalls)) {
+ assert(abi->syscalls[number] == NULL);
+ abi->syscalls[number] = sc;
+ } else {
+ es = malloc(sizeof(*es));
+ es->sc = sc;
+ es->number = number;
+ STAILQ_INSERT_TAIL(&abi->extra_syscalls, es, entries);
+ }
+
+ STAILQ_INSERT_HEAD(&seen_syscalls, sc, entries);
+}
+
+/*
+ * If/when the list gets big, it might be desirable to do it
+ * as a hash table or binary search.
+ */
+struct syscall *
+get_syscall(struct threadinfo *t, u_int number, u_int nargs)
+{
+ struct syscall *sc;
+ struct procabi *procabi;
+ const char *sysdecode_name;
+ const char *lookup_name;
+ const char *name;
+ u_int i;
+
+ procabi = t->proc->abi;
+ sc = find_syscall(procabi, number);
+ if (sc != NULL)
+ return (sc);
+
+ /* Memory is not explicitly deallocated, it's released on exit(). */
+ sysdecode_name = sysdecode_syscallname(procabi->abi, number);
+ if (sysdecode_name == NULL)
+ asprintf(__DECONST(char **, &name), "#%d", number);
+ else
+ name = sysdecode_name;
+
+ sc = calloc(1, sizeof(*sc));
+ sc->name = name;
+
+ /* Also decode compat syscalls arguments by stripping the prefix. */
+ lookup_name = name;
+ if (procabi->compat_prefix != NULL && strncmp(procabi->compat_prefix,
+ name, strlen(procabi->compat_prefix)) == 0)
+ lookup_name += strlen(procabi->compat_prefix);
+
+ for (i = 0; i < nitems(decoded_syscalls); i++) {
+ if (strcmp(lookup_name, decoded_syscalls[i].name) == 0) {
+ sc->decode = decoded_syscalls[i];
+ add_syscall(t->proc->abi, number, sc);
+ return (sc);
+ }
+ }
+
+ /* It is unknown. Add it into the list. */
+#if DEBUG
+ fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name,
+ nargs);
+#endif
+ sc->unknown = sysdecode_name == NULL;
+ sc->decode.ret_type = 1; /* Assume 1 return value. */
+ sc->decode.nargs = nargs;
+ for (i = 0; i < nargs; i++) {
+ sc->decode.args[i].offset = i;
+ /* Treat all unknown arguments as LongHex. */
+ sc->decode.args[i].type = LongHex;
+ }
+ add_syscall(t->proc->abi, number, sc);
+ return (sc);
+}
+
+/*
+ * Copy a fixed amount of bytes from the process.
+ */
+static int
+get_struct(pid_t pid, psaddr_t offset, void *buf, size_t len)
+{
+ struct ptrace_io_desc iorequest;
+
+ iorequest.piod_op = PIOD_READ_D;
+ iorequest.piod_offs = (void *)(uintptr_t)offset;
+ iorequest.piod_addr = buf;
+ iorequest.piod_len = len;
+ if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
+ return (-1);
+ return (0);
+}
+
+#define MAXSIZE 4096
+
+/*
+ * Copy a string from the process. Note that it is
+ * expected to be a C string, but if max is set, it will
+ * only get that much.
+ */
+static char *
+get_string(pid_t pid, psaddr_t addr, int max)
+{
+ struct ptrace_io_desc iorequest;
+ char *buf, *nbuf;
+ size_t offset, size, totalsize;
+
+ offset = 0;
+ if (max)
+ size = max + 1;
+ else {
+ /* Read up to the end of the current page. */
+ size = PAGE_SIZE - (addr % PAGE_SIZE);
+ if (size > MAXSIZE)
+ size = MAXSIZE;
+ }
+ totalsize = size;
+ buf = malloc(totalsize);
+ if (buf == NULL)
+ return (NULL);
+ for (;;) {
+ iorequest.piod_op = PIOD_READ_D;
+ iorequest.piod_offs = (void *)((uintptr_t)addr + offset);
+ iorequest.piod_addr = buf + offset;
+ iorequest.piod_len = size;
+ if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
+ free(buf);
+ return (NULL);
+ }
+ if (memchr(buf + offset, '\0', size) != NULL)
+ return (buf);
+ offset += size;
+ if (totalsize < MAXSIZE && max == 0) {
+ size = MAXSIZE - totalsize;
+ if (size > PAGE_SIZE)
+ size = PAGE_SIZE;
+ nbuf = realloc(buf, totalsize + size);
+ if (nbuf == NULL) {
+ buf[totalsize - 1] = '\0';
+ return (buf);
+ }
+ buf = nbuf;
+ totalsize += size;
+ } else {
+ buf[totalsize - 1] = '\0';
+ return (buf);
+ }
+ }
+}
+
+static const char *
+strsig2(int sig)
+{
+ static char tmp[32];
+ const char *signame;
+
+ signame = sysdecode_signal(sig);
+ if (signame == NULL) {
+ snprintf(tmp, sizeof(tmp), "%d", sig);
+ signame = tmp;
+ }
+ return (signame);
+}
+
+static void
+print_kevent(FILE *fp, struct kevent *ke)
+{
+
+ switch (ke->filter) {
+ case EVFILT_READ:
+ case EVFILT_WRITE:
+ case EVFILT_VNODE:
+ case EVFILT_PROC:
+ case EVFILT_TIMER:
+ case EVFILT_PROCDESC:
+ case EVFILT_EMPTY:
+ fprintf(fp, "%ju", (uintmax_t)ke->ident);
+ break;
+ case EVFILT_SIGNAL:
+ fputs(strsig2(ke->ident), fp);
+ break;
+ default:
+ fprintf(fp, "%p", (void *)ke->ident);
+ }
+ fprintf(fp, ",");
+ print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
+ fprintf(fp, ",");
+ print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
+ fprintf(fp, ",");
+ sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
+ fprintf(fp, ",%#jx,%p", (uintmax_t)ke->data, ke->udata);
+}
+
+static void
+print_utrace(FILE *fp, void *utrace_addr, size_t len)
+{
+ unsigned char *utrace_buffer;
+
+ fprintf(fp, "{ ");
+ if (sysdecode_utrace(fp, utrace_addr, len)) {
+ fprintf(fp, " }");
+ return;
+ }
+
+ utrace_buffer = utrace_addr;
+ fprintf(fp, "%zu:", len);
+ while (len--)
+ fprintf(fp, " %02x", *utrace_buffer++);
+ fprintf(fp, " }");
+}
+
+static void
+print_pointer(FILE *fp, uintptr_t arg)
+{
+
+ fprintf(fp, "%p", (void *)arg);
+}
+
+static void
+print_sockaddr(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg,
+ socklen_t len)
+{
+ char addr[64];
+ struct sockaddr_in *lsin;
+ struct sockaddr_in6 *lsin6;
+ struct sockaddr_un *sun;
+ struct sockaddr *sa;
+ u_char *q;
+ pid_t pid = trussinfo->curthread->proc->pid;
+
+ if (arg == 0) {
+ fputs("NULL", fp);
+ return;
+ }
+ /* If the length is too small, just bail. */
+ if (len < sizeof(*sa)) {
+ print_pointer(fp, arg);
+ return;
+ }
+
+ sa = calloc(1, len);
+ if (get_struct(pid, arg, sa, len) == -1) {
+ free(sa);
+ print_pointer(fp, arg);
+ return;
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (len < sizeof(*lsin))
+ goto sockaddr_short;
+ lsin = (struct sockaddr_in *)(void *)sa;
+ inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
+ fprintf(fp, "{ AF_INET %s:%d }", addr,
+ htons(lsin->sin_port));
+ break;
+ case AF_INET6:
+ if (len < sizeof(*lsin6))
+ goto sockaddr_short;
+ lsin6 = (struct sockaddr_in6 *)(void *)sa;
+ inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
+ sizeof(addr));
+ fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
+ htons(lsin6->sin6_port));
+ break;
+ case AF_UNIX:
+ sun = (struct sockaddr_un *)sa;
+ fprintf(fp, "{ AF_UNIX \"%.*s\" }",
+ (int)(len - offsetof(struct sockaddr_un, sun_path)),
+ sun->sun_path);
+ break;
+ default:
+ sockaddr_short:
+ fprintf(fp,
+ "{ sa_len = %d, sa_family = %d, sa_data = {",
+ (int)sa->sa_len, (int)sa->sa_family);
+ for (q = (u_char *)sa->sa_data;
+ q < (u_char *)sa + len; q++)
+ fprintf(fp, "%s 0x%02x",
+ q == (u_char *)sa->sa_data ? "" : ",",
+ *q);
+ fputs(" } }", fp);
+ }
+ free(sa);
+}
+
+#define IOV_LIMIT 16
+
+static void
+print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
+{
+ struct iovec iov[IOV_LIMIT];
+ size_t max_string = trussinfo->strsize;
+ char tmp2[max_string + 1], *tmp3;
+ size_t len;
+ pid_t pid = trussinfo->curthread->proc->pid;
+ int i;
+ bool buf_truncated, iov_truncated;
+
+ if (iovcnt <= 0) {
+ print_pointer(fp, arg);
+ return;
+ }
+ if (iovcnt > IOV_LIMIT) {
+ iovcnt = IOV_LIMIT;
+ iov_truncated = true;
+ } else {
+ iov_truncated = false;
+ }
+ if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
+ print_pointer(fp, arg);
+ return;
+ }
+
+ fputs("[", fp);
+ for (i = 0; i < iovcnt; i++) {
+ len = iov[i].iov_len;
+ if (len > max_string) {
+ len = max_string;
+ buf_truncated = true;
+ } else {
+ buf_truncated = false;
+ }
+ fprintf(fp, "%s{", (i > 0) ? "," : "");
+ if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
+ tmp3 = malloc(len * 4 + 1);
+ while (len) {
+ if (strvisx(tmp3, tmp2, len,
+ VIS_CSTYLE|VIS_TAB|VIS_NL) <=
+ (int)max_string)
+ break;
+ len--;
+ buf_truncated = true;
+ }
+ fprintf(fp, "\"%s\"%s", tmp3,
+ buf_truncated ? "..." : "");
+ free(tmp3);
+ } else {
+ print_pointer(fp, (uintptr_t)iov[i].iov_base);
+ }
+ fprintf(fp, ",%zu}", iov[i].iov_len);
+ }
+ fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
+}
+
+static void
+print_sigval(FILE *fp, union sigval *sv)
+{
+ fprintf(fp, "{ %d, %p }", sv->sival_int, sv->sival_ptr);
+}
+
+static void
+print_sigevent(FILE *fp, struct sigevent *se)
+{
+ fputs("{ sigev_notify=", fp);
+ switch (se->sigev_notify) {
+ case SIGEV_NONE:
+ fputs("SIGEV_NONE", fp);
+ break;
+ case SIGEV_SIGNAL:
+ fprintf(fp, "SIGEV_SIGNAL, sigev_signo=%s, sigev_value=",
+ strsig2(se->sigev_signo));
+ print_sigval(fp, &se->sigev_value);
+ break;
+ case SIGEV_THREAD:
+ fputs("SIGEV_THREAD, sigev_value=", fp);
+ print_sigval(fp, &se->sigev_value);
+ break;
+ case SIGEV_KEVENT:
+ fprintf(fp, "SIGEV_KEVENT, sigev_notify_kqueue=%d, sigev_notify_kevent_flags=",
+ se->sigev_notify_kqueue);
+ print_mask_arg(sysdecode_kevent_flags, fp, se->sigev_notify_kevent_flags);
+ break;
+ case SIGEV_THREAD_ID:
+ fprintf(fp, "SIGEV_THREAD_ID, sigev_notify_thread_id=%d, sigev_signo=%s, sigev_value=",
+ se->sigev_notify_thread_id, strsig2(se->sigev_signo));
+ print_sigval(fp, &se->sigev_value);
+ break;
+ default:
+ fprintf(fp, "%d", se->sigev_notify);
+ break;
+ }
+ fputs(" }", fp);
+}
+
+static void
+print_aiocb(FILE *fp, struct aiocb *cb)
+{
+ fprintf(fp, "{ %d,%jd,%p,%zu,%s,",
+ cb->aio_fildes,
+ cb->aio_offset,
+ cb->aio_buf,
+ cb->aio_nbytes,
+ xlookup(lio_opcodes, cb->aio_lio_opcode));
+ print_sigevent(fp, &cb->aio_sigevent);
+ fputs(" }", fp);
+}
+
+static void
+print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
+{
+ u_char *q;
+
+ fputs("{", fp);
+ for (q = CMSG_DATA(cmsghdr);
+ q < (u_char *)cmsghdr + cmsghdr->cmsg_len; q++) {
+ fprintf(fp, "%s0x%02x", q == CMSG_DATA(cmsghdr) ? "" : ",", *q);
+ }
+ fputs("}", fp);
+}
+
+static void
+print_sctp_initmsg(FILE *fp, struct sctp_initmsg *init)
+{
+ fprintf(fp, "{out=%u,", init->sinit_num_ostreams);
+ fprintf(fp, "in=%u,", init->sinit_max_instreams);
+ fprintf(fp, "max_rtx=%u,", init->sinit_max_attempts);
+ fprintf(fp, "max_rto=%u}", init->sinit_max_init_timeo);
+}
+
+static void
+print_sctp_sndrcvinfo(FILE *fp, bool receive, struct sctp_sndrcvinfo *info)
+{
+ fprintf(fp, "{sid=%u,", info->sinfo_stream);
+ if (receive) {
+ fprintf(fp, "ssn=%u,", info->sinfo_ssn);
+ }
+ fputs("flgs=", fp);
+ sysdecode_sctp_sinfo_flags(fp, info->sinfo_flags);
+ fprintf(fp, ",ppid=%u,", ntohl(info->sinfo_ppid));
+ if (!receive) {
+ fprintf(fp, "ctx=%u,", info->sinfo_context);
+ fprintf(fp, "ttl=%u,", info->sinfo_timetolive);
+ }
+ if (receive) {
+ fprintf(fp, "tsn=%u,", info->sinfo_tsn);
+ fprintf(fp, "cumtsn=%u,", info->sinfo_cumtsn);
+ }
+ fprintf(fp, "id=%u}", info->sinfo_assoc_id);
+}
+
+static void
+print_sctp_sndinfo(FILE *fp, struct sctp_sndinfo *info)
+{
+ fprintf(fp, "{sid=%u,", info->snd_sid);
+ fputs("flgs=", fp);
+ print_mask_arg(sysdecode_sctp_snd_flags, fp, info->snd_flags);
+ fprintf(fp, ",ppid=%u,", ntohl(info->snd_ppid));
+ fprintf(fp, "ctx=%u,", info->snd_context);
+ fprintf(fp, "id=%u}", info->snd_assoc_id);
+}
+
+static void
+print_sctp_rcvinfo(FILE *fp, struct sctp_rcvinfo *info)
+{
+ fprintf(fp, "{sid=%u,", info->rcv_sid);
+ fprintf(fp, "ssn=%u,", info->rcv_ssn);
+ fputs("flgs=", fp);
+ print_mask_arg(sysdecode_sctp_rcv_flags, fp, info->rcv_flags);
+ fprintf(fp, ",ppid=%u,", ntohl(info->rcv_ppid));
+ fprintf(fp, "tsn=%u,", info->rcv_tsn);
+ fprintf(fp, "cumtsn=%u,", info->rcv_cumtsn);
+ fprintf(fp, "ctx=%u,", info->rcv_context);
+ fprintf(fp, "id=%u}", info->rcv_assoc_id);
+}
+
+static void
+print_sctp_nxtinfo(FILE *fp, struct sctp_nxtinfo *info)
+{
+ fprintf(fp, "{sid=%u,", info->nxt_sid);
+ fputs("flgs=", fp);
+ print_mask_arg(sysdecode_sctp_nxt_flags, fp, info->nxt_flags);
+ fprintf(fp, ",ppid=%u,", ntohl(info->nxt_ppid));
+ fprintf(fp, "len=%u,", info->nxt_length);
+ fprintf(fp, "id=%u}", info->nxt_assoc_id);
+}
+
+static void
+print_sctp_prinfo(FILE *fp, struct sctp_prinfo *info)
+{
+ fputs("{pol=", fp);
+ print_integer_arg(sysdecode_sctp_pr_policy, fp, info->pr_policy);
+ fprintf(fp, ",val=%u}", info->pr_value);
+}
+
+static void
+print_sctp_authinfo(FILE *fp, struct sctp_authinfo *info)
+{
+ fprintf(fp, "{num=%u}", info->auth_keynumber);
+}
+
+static void
+print_sctp_ipv4_addr(FILE *fp, struct in_addr *addr)
+{
+ char buf[INET_ADDRSTRLEN];
+ const char *s;
+
+ s = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
+ if (s != NULL)
+ fprintf(fp, "{addr=%s}", s);
+ else
+ fputs("{addr=???}", fp);
+}
+
+static void
+print_sctp_ipv6_addr(FILE *fp, struct in6_addr *addr)
+{
+ char buf[INET6_ADDRSTRLEN];
+ const char *s;
+
+ s = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
+ if (s != NULL)
+ fprintf(fp, "{addr=%s}", s);
+ else
+ fputs("{addr=???}", fp);
+}
+
+static void
+print_sctp_cmsg(FILE *fp, bool receive, struct cmsghdr *cmsghdr)
+{
+ void *data;
+ socklen_t len;
+
+ len = cmsghdr->cmsg_len;
+ data = CMSG_DATA(cmsghdr);
+ switch (cmsghdr->cmsg_type) {
+ case SCTP_INIT:
+ if (len == CMSG_LEN(sizeof(struct sctp_initmsg)))
+ print_sctp_initmsg(fp, (struct sctp_initmsg *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_SNDRCV:
+ if (len == CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
+ print_sctp_sndrcvinfo(fp, receive,
+ (struct sctp_sndrcvinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+#if 0
+ case SCTP_EXTRCV:
+ if (len == CMSG_LEN(sizeof(struct sctp_extrcvinfo)))
+ print_sctp_extrcvinfo(fp,
+ (struct sctp_extrcvinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+#endif
+ case SCTP_SNDINFO:
+ if (len == CMSG_LEN(sizeof(struct sctp_sndinfo)))
+ print_sctp_sndinfo(fp, (struct sctp_sndinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_RCVINFO:
+ if (len == CMSG_LEN(sizeof(struct sctp_rcvinfo)))
+ print_sctp_rcvinfo(fp, (struct sctp_rcvinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_NXTINFO:
+ if (len == CMSG_LEN(sizeof(struct sctp_nxtinfo)))
+ print_sctp_nxtinfo(fp, (struct sctp_nxtinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_PRINFO:
+ if (len == CMSG_LEN(sizeof(struct sctp_prinfo)))
+ print_sctp_prinfo(fp, (struct sctp_prinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_AUTHINFO:
+ if (len == CMSG_LEN(sizeof(struct sctp_authinfo)))
+ print_sctp_authinfo(fp, (struct sctp_authinfo *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_DSTADDRV4:
+ if (len == CMSG_LEN(sizeof(struct in_addr)))
+ print_sctp_ipv4_addr(fp, (struct in_addr *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ case SCTP_DSTADDRV6:
+ if (len == CMSG_LEN(sizeof(struct in6_addr)))
+ print_sctp_ipv6_addr(fp, (struct in6_addr *)data);
+ else
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ default:
+ print_gen_cmsg(fp, cmsghdr);
+ }
+}
+
+static void
+print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
+{
+ struct cmsghdr *cmsghdr;
+ char *cmsgbuf;
+ const char *temp;
+ socklen_t len;
+ int level, type;
+ bool first;
+
+ len = msghdr->msg_controllen;
+ if (len == 0) {
+ fputs("{}", fp);
+ return;
+ }
+ cmsgbuf = calloc(1, len);
+ if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
+ print_pointer(fp, (uintptr_t)msghdr->msg_control);
+ free(cmsgbuf);
+ return;
+ }
+ msghdr->msg_control = cmsgbuf;
+ first = true;
+ fputs("{", fp);
+ for (cmsghdr = CMSG_FIRSTHDR(msghdr);
+ cmsghdr != NULL;
+ cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr)) {
+ if (cmsghdr->cmsg_len < sizeof(*cmsghdr)) {
+ fprintf(fp, "{<invalid cmsg, len=%u>}",
+ cmsghdr->cmsg_len);
+ if (cmsghdr->cmsg_len == 0) {
+ /* Avoid looping forever. */
+ break;
+ }
+ continue;
+ }
+
+ level = cmsghdr->cmsg_level;
+ type = cmsghdr->cmsg_type;
+ len = cmsghdr->cmsg_len;
+ fprintf(fp, "%s{level=", first ? "" : ",");
+ print_integer_arg(sysdecode_sockopt_level, fp, level);
+ fputs(",type=", fp);
+ temp = sysdecode_cmsg_type(level, type);
+ if (temp) {
+ fputs(temp, fp);
+ } else {
+ fprintf(fp, "%d", type);
+ }
+ fputs(",data=", fp);
+ switch (level) {
+ case IPPROTO_SCTP:
+ print_sctp_cmsg(fp, receive, cmsghdr);
+ break;
+ default:
+ print_gen_cmsg(fp, cmsghdr);
+ break;
+ }
+ fputs("}", fp);
+ first = false;
+ }
+ fputs("}", fp);
+ free(cmsgbuf);
+}
+
+static void
+print_sysctl_oid(FILE *fp, int *oid, size_t len)
+{
+ size_t i;
+ bool first;
+
+ first = true;
+ fprintf(fp, "{ ");
+ for (i = 0; i < len; i++) {
+ fprintf(fp, "%s%d", first ? "" : ".", oid[i]);
+ first = false;
+ }
+ fprintf(fp, " }");
+}
+
+static void
+print_sysctl(FILE *fp, int *oid, size_t len)
+{
+ char name[BUFSIZ];
+ int qoid[CTL_MAXNAME + 2];
+ size_t i;
+
+ qoid[0] = CTL_SYSCTL;
+ qoid[1] = CTL_SYSCTL_NAME;
+ memcpy(qoid + 2, oid, len * sizeof(int));
+ i = sizeof(name);
+ if (sysctl(qoid, len + 2, name, &i, 0, 0) == -1)
+ print_sysctl_oid(fp, oid, len);
+ else
+ fprintf(fp, "%s", name);
+}
+
+/*
+ * Convert a 32-bit user-space pointer to psaddr_t by zero-extending.
+ */
+static psaddr_t
+user_ptr32_to_psaddr(int32_t user_pointer)
+{
+ return ((psaddr_t)(uintptr_t)user_pointer);
+}
+
+/*
+ * Converts a syscall argument into a string. Said string is
+ * allocated via malloc(), so needs to be free()'d. sc is
+ * a pointer to the syscall description (see above); args is
+ * an array of all of the system call arguments.
+ */
+char *
+print_arg(struct syscall_arg *sc, syscallarg_t *args, syscallarg_t *retval,
+ struct trussinfo *trussinfo)
+{
+ FILE *fp;
+ char *tmp;
+ size_t tmplen;
+ pid_t pid;
+
+ fp = open_memstream(&tmp, &tmplen);
+ pid = trussinfo->curthread->proc->pid;
+ switch (sc->type & ARG_MASK) {
+ case Hex:
+ fprintf(fp, "0x%x", (int)args[sc->offset]);
+ break;
+ case Octal:
+ fprintf(fp, "0%o", (int)args[sc->offset]);
+ break;
+ case Int:
+ fprintf(fp, "%d", (int)args[sc->offset]);
+ break;
+ case UInt:
+ fprintf(fp, "%u", (unsigned int)args[sc->offset]);
+ break;
+ case PUInt: {
+ unsigned int val;
+
+ if (get_struct(pid, args[sc->offset], &val,
+ sizeof(val)) == 0)
+ fprintf(fp, "{ %u }", val);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case LongHex:
+ fprintf(fp, "0x%lx", (long)args[sc->offset]);
+ break;
+ case Long:
+ fprintf(fp, "%ld", (long)args[sc->offset]);
+ break;
+ case Sizet:
+ fprintf(fp, "%zu", (size_t)args[sc->offset]);
+ break;
+ case ShmName:
+ /* Handle special SHM_ANON value. */
+ if ((char *)(uintptr_t)args[sc->offset] == SHM_ANON) {
+ fprintf(fp, "SHM_ANON");
+ break;
+ }
+ /* FALLTHROUGH */
+ case Name: {
+ /* NULL-terminated string. */
+ char *tmp2;
+
+ tmp2 = get_string(pid, args[sc->offset], 0);
+ fprintf(fp, "\"%s\"", tmp2);
+ free(tmp2);
+ break;
+ }
+ case BinString: {
+ /*
+ * Binary block of data that might have printable characters.
+ * XXX If type|OUT, assume that the length is the syscall's
+ * return value. Otherwise, assume that the length of the block
+ * is in the next syscall argument.
+ */
+ int max_string = trussinfo->strsize;
+ char tmp2[max_string + 1], *tmp3;
+ int len;
+ int truncated = 0;
+
+ if (sc->type & OUT)
+ len = retval[0];
+ else
+ len = args[sc->offset + 1];
+
+ /*
+ * Don't print more than max_string characters, to avoid word
+ * wrap. If we have to truncate put some ... after the string.
+ */
+ if (len > max_string) {
+ len = max_string;
+ truncated = 1;
+ }
+ if (len && get_struct(pid, args[sc->offset], &tmp2, len)
+ != -1) {
+ tmp3 = malloc(len * 4 + 1);
+ while (len) {
+ if (strvisx(tmp3, tmp2, len,
+ VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
+ break;
+ len--;
+ truncated = 1;
+ }
+ fprintf(fp, "\"%s\"%s", tmp3, truncated ?
+ "..." : "");
+ free(tmp3);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ break;
+ }
+ case ExecArgs:
+ case ExecEnv:
+ case StringArray: {
+ psaddr_t addr;
+ union {
+ int32_t strarray32[PAGE_SIZE / sizeof(int32_t)];
+ int64_t strarray64[PAGE_SIZE / sizeof(int64_t)];
+ char buf[PAGE_SIZE];
+ } u;
+ char *string;
+ size_t len;
+ u_int first, i;
+ size_t pointer_size =
+ trussinfo->curthread->proc->abi->pointer_size;
+
+ /*
+ * Only parse argv[] and environment arrays from exec calls
+ * if requested.
+ */
+ if (((sc->type & ARG_MASK) == ExecArgs &&
+ (trussinfo->flags & EXECVEARGS) == 0) ||
+ ((sc->type & ARG_MASK) == ExecEnv &&
+ (trussinfo->flags & EXECVEENVS) == 0)) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+
+ /*
+ * Read a page of pointers at a time. Punt if the top-level
+ * pointer is not aligned. Note that the first read is of
+ * a partial page.
+ */
+ addr = args[sc->offset];
+ if (!__is_aligned(addr, pointer_size)) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+
+ len = PAGE_SIZE - (addr & PAGE_MASK);
+ if (get_struct(pid, addr, u.buf, len) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ assert(len > 0);
+
+ fputc('[', fp);
+ first = 1;
+ i = 0;
+ for (;;) {
+ psaddr_t straddr;
+ if (pointer_size == 4) {
+ straddr = user_ptr32_to_psaddr(u.strarray32[i]);
+ } else if (pointer_size == 8) {
+ straddr = (psaddr_t)u.strarray64[i];
+ } else {
+ errx(1, "Unsupported pointer size: %zu",
+ pointer_size);
+ }
+
+ /* Stop once we read the first NULL pointer. */
+ if (straddr == 0)
+ break;
+ string = get_string(pid, straddr, 0);
+ fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
+ free(string);
+ first = 0;
+
+ i++;
+ if (i == len / pointer_size) {
+ addr += len;
+ len = PAGE_SIZE;
+ if (get_struct(pid, addr, u.buf, len) == -1) {
+ fprintf(fp, ", <inval>");
+ break;
+ }
+ i = 0;
+ }
+ }
+ fputs(" ]", fp);
+ break;
+ }
+ case Quad:
+ case QuadHex: {
+ uint64_t value;
+ size_t pointer_size =
+ trussinfo->curthread->proc->abi->pointer_size;
+
+ if (pointer_size == 4) {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ value = (uint64_t)args[sc->offset + 1] << 32 |
+ args[sc->offset];
+#else
+ value = (uint64_t)args[sc->offset] << 32 |
+ args[sc->offset + 1];
+#endif
+ } else {
+ value = (uint64_t)args[sc->offset];
+ }
+ if ((sc->type & ARG_MASK) == Quad)
+ fprintf(fp, "%jd", (intmax_t)value);
+ else
+ fprintf(fp, "0x%jx", (intmax_t)value);
+ break;
+ }
+ case PQuadHex: {
+ uint64_t val;
+
+ if (get_struct(pid, args[sc->offset], &val,
+ sizeof(val)) == 0)
+ fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Ptr:
+ print_pointer(fp, args[sc->offset]);
+ break;
+ case Readlinkres: {
+ char *tmp2;
+
+ if (retval[0] == -1)
+ break;
+ tmp2 = get_string(pid, args[sc->offset], retval[0]);
+ fprintf(fp, "\"%s\"", tmp2);
+ free(tmp2);
+ break;
+ }
+ case Ioctl: {
+ const char *temp;
+ unsigned long cmd;
+
+ cmd = args[sc->offset];
+ temp = sysdecode_ioctlname(cmd);
+ if (temp)
+ fputs(temp, fp);
+ else {
+ fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
+ cmd, cmd & IOC_OUT ? "R" : "",
+ cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
+ isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
+ cmd & 0xFF, IOCPARM_LEN(cmd));
+ }
+ break;
+ }
+ case Timespec: {
+ struct timespec ts;
+
+ if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
+ fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
+ ts.tv_nsec);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Timespec2: {
+ struct timespec ts[2];
+ const char *sep;
+ unsigned int i;
+
+ if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
+ fputs("{ ", fp);
+ sep = "";
+ for (i = 0; i < nitems(ts); i++) {
+ fputs(sep, fp);
+ sep = ", ";
+ switch (ts[i].tv_nsec) {
+ case UTIME_NOW:
+ fprintf(fp, "UTIME_NOW");
+ break;
+ case UTIME_OMIT:
+ fprintf(fp, "UTIME_OMIT");
+ break;
+ default:
+ fprintf(fp, "%jd.%09ld",
+ (intmax_t)ts[i].tv_sec,
+ ts[i].tv_nsec);
+ break;
+ }
+ }
+ fputs(" }", fp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Timeval: {
+ struct timeval tv;
+
+ if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
+ fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
+ tv.tv_usec);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Timeval2: {
+ struct timeval tv[2];
+
+ if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
+ fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
+ (intmax_t)tv[0].tv_sec, tv[0].tv_usec,
+ (intmax_t)tv[1].tv_sec, tv[1].tv_usec);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Itimerval: {
+ struct itimerval itv;
+
+ if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
+ fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
+ (intmax_t)itv.it_interval.tv_sec,
+ itv.it_interval.tv_usec,
+ (intmax_t)itv.it_value.tv_sec,
+ itv.it_value.tv_usec);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case LinuxSockArgs:
+ {
+ struct linux_socketcall_args largs;
+
+ if (get_struct(pid, args[sc->offset], (void *)&largs,
+ sizeof(largs)) != -1)
+ fprintf(fp, "{ %s, 0x%lx }",
+ lookup(linux_socketcall_ops, largs.what, 10),
+ (long unsigned int)largs.args);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Pollfd: {
+ /*
+ * XXX: A Pollfd argument expects the /next/ syscall argument
+ * to be the number of fds in the array. This matches the poll
+ * syscall.
+ */
+ struct pollfd *pfd;
+ int numfds = args[sc->offset + 1];
+ size_t bytes = sizeof(struct pollfd) * numfds;
+ int i;
+
+ if ((pfd = malloc(bytes)) == NULL)
+ err(1, "Cannot malloc %zu bytes for pollfd array",
+ bytes);
+ if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
+ fputs("{", fp);
+ for (i = 0; i < numfds; i++) {
+ fprintf(fp, " %d/%s", pfd[i].fd,
+ xlookup_bits(poll_flags, pfd[i].events));
+ }
+ fputs(" }", fp);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ free(pfd);
+ break;
+ }
+ case Fd_set: {
+ /*
+ * XXX: A Fd_set argument expects the /first/ syscall argument
+ * to be the number of fds in the array. This matches the
+ * select syscall.
+ */
+ fd_set *fds;
+ int numfds = args[0];
+ size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
+ int i;
+
+ if ((fds = malloc(bytes)) == NULL)
+ err(1, "Cannot malloc %zu bytes for fd_set array",
+ bytes);
+ if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
+ fputs("{", fp);
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, fds))
+ fprintf(fp, " %d", i);
+ }
+ fputs(" }", fp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ free(fds);
+ break;
+ }
+ case Signal:
+ fputs(strsig2(args[sc->offset]), fp);
+ break;
+ case Sigset: {
+ sigset_t ss;
+ int i, first;
+
+ if (get_struct(pid, args[sc->offset], (void *)&ss,
+ sizeof(ss)) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ fputs("{ ", fp);
+ first = 1;
+ for (i = 1; i < sys_nsig; i++) {
+ if (sigismember(&ss, i)) {
+ fprintf(fp, "%s%s", !first ? "|" : "",
+ strsig2(i));
+ first = 0;
+ }
+ }
+ if (!first)
+ fputc(' ', fp);
+ fputc('}', fp);
+ break;
+ }
+ case Sigprocmask:
+ print_integer_arg(sysdecode_sigprocmask_how, fp,
+ args[sc->offset]);
+ break;
+ case Fcntlflag:
+ /* XXX: Output depends on the value of the previous argument. */
+ if (sysdecode_fcntl_arg_p(args[sc->offset - 1]))
+ sysdecode_fcntl_arg(fp, args[sc->offset - 1],
+ args[sc->offset], 16);
+ break;
+ case Open:
+ print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]);
+ break;
+ case Fcntl:
+ print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
+ break;
+ case Closerangeflags:
+ print_mask_arg(sysdecode_close_range_flags, fp, args[sc->offset]);
+ break;
+ case Mprot:
+ print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
+ break;
+ case Mmapflags:
+ print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]);
+ break;
+ case Whence:
+ print_integer_arg(sysdecode_whence, fp, args[sc->offset]);
+ break;
+ case ShmFlags:
+ print_mask_arg(sysdecode_shmflags, fp, args[sc->offset]);
+ break;
+ case Sockdomain:
+ print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]);
+ break;
+ case Socktype:
+ print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]);
+ break;
+ case Shutdown:
+ print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]);
+ break;
+ case Resource:
+ print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]);
+ break;
+ case RusageWho:
+ print_integer_arg(sysdecode_getrusage_who, fp, args[sc->offset]);
+ break;
+ case Pathconf:
+ print_integer_arg(sysdecode_pathconf_name, fp, args[sc->offset]);
+ break;
+ case Rforkflags:
+ print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]);
+ break;
+ case Sockaddr: {
+ socklen_t len;
+
+ if (args[sc->offset] == 0) {
+ fputs("NULL", fp);
+ break;
+ }
+
+ /*
+ * Extract the address length from the next argument. If
+ * this is an output sockaddr (OUT is set), then the
+ * next argument is a pointer to a socklen_t. Otherwise
+ * the next argument contains a socklen_t by value.
+ */
+ if (sc->type & OUT) {
+ if (get_struct(pid, args[sc->offset + 1], &len,
+ sizeof(len)) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ } else
+ len = args[sc->offset + 1];
+
+ print_sockaddr(fp, trussinfo, args[sc->offset], len);
+ break;
+ }
+ case Sigaction: {
+ struct sigaction sa;
+
+ if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
+ fputs("{ ", fp);
+ if (sa.sa_handler == SIG_DFL)
+ fputs("SIG_DFL", fp);
+ else if (sa.sa_handler == SIG_IGN)
+ fputs("SIG_IGN", fp);
+ else
+ fprintf(fp, "%p", sa.sa_handler);
+ fprintf(fp, " %s ss_t }",
+ xlookup_bits(sigaction_flags, sa.sa_flags));
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Sigevent: {
+ struct sigevent se;
+
+ if (get_struct(pid, args[sc->offset], &se, sizeof(se)) != -1)
+ print_sigevent(fp, &se);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Kevent: {
+ /*
+ * XXX XXX: The size of the array is determined by either the
+ * next syscall argument, or by the syscall return value,
+ * depending on which argument number we are. This matches the
+ * kevent syscall, but luckily that's the only syscall that uses
+ * them.
+ */
+ struct kevent *ke;
+ int numevents = -1;
+ size_t bytes;
+ int i;
+
+ if (sc->offset == 1)
+ numevents = args[sc->offset+1];
+ else if (sc->offset == 3 && retval[0] != -1)
+ numevents = retval[0];
+
+ if (numevents >= 0) {
+ bytes = sizeof(struct kevent) * numevents;
+ if ((ke = malloc(bytes)) == NULL)
+ err(1,
+ "Cannot malloc %zu bytes for kevent array",
+ bytes);
+ } else
+ ke = NULL;
+ if (numevents >= 0 && get_struct(pid, args[sc->offset],
+ ke, bytes) != -1) {
+ fputc('{', fp);
+ for (i = 0; i < numevents; i++) {
+ fputc(' ', fp);
+ print_kevent(fp, &ke[i]);
+ }
+ fputs(" }", fp);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ free(ke);
+ break;
+ }
+ case Kevent11: {
+ struct freebsd11_kevent *ke11;
+ struct kevent ke;
+ int numevents = -1;
+ size_t bytes;
+ int i;
+
+ if (sc->offset == 1)
+ numevents = args[sc->offset+1];
+ else if (sc->offset == 3 && retval[0] != -1)
+ numevents = retval[0];
+
+ if (numevents >= 0) {
+ bytes = sizeof(struct freebsd11_kevent) * numevents;
+ if ((ke11 = malloc(bytes)) == NULL)
+ err(1,
+ "Cannot malloc %zu bytes for kevent array",
+ bytes);
+ } else
+ ke11 = NULL;
+ memset(&ke, 0, sizeof(ke));
+ if (numevents >= 0 && get_struct(pid, args[sc->offset],
+ ke11, bytes) != -1) {
+ fputc('{', fp);
+ for (i = 0; i < numevents; i++) {
+ fputc(' ', fp);
+ ke.ident = ke11[i].ident;
+ ke.filter = ke11[i].filter;
+ ke.flags = ke11[i].flags;
+ ke.fflags = ke11[i].fflags;
+ ke.data = ke11[i].data;
+ ke.udata = ke11[i].udata;
+ print_kevent(fp, &ke);
+ }
+ fputs(" }", fp);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ free(ke11);
+ break;
+ }
+ case Stat: {
+ struct stat st;
+
+ if (get_struct(pid, args[sc->offset], &st, sizeof(st))
+ != -1) {
+ char mode[12];
+
+ strmode(st.st_mode, mode);
+ fprintf(fp,
+ "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
+ (uintmax_t)st.st_ino, (intmax_t)st.st_size,
+ (long)st.st_blksize);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ break;
+ }
+ case Stat11: {
+ struct freebsd11_stat st;
+
+ if (get_struct(pid, args[sc->offset], &st, sizeof(st))
+ != -1) {
+ char mode[12];
+
+ strmode(st.st_mode, mode);
+ fprintf(fp,
+ "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode,
+ (uintmax_t)st.st_ino, (intmax_t)st.st_size,
+ (long)st.st_blksize);
+ } else {
+ print_pointer(fp, args[sc->offset]);
+ }
+ break;
+ }
+ case StatFs: {
+ unsigned int i;
+ struct statfs buf;
+
+ if (get_struct(pid, args[sc->offset], &buf,
+ sizeof(buf)) != -1) {
+ char fsid[17];
+
+ bzero(fsid, sizeof(fsid));
+ if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) {
+ for (i = 0; i < sizeof(buf.f_fsid); i++)
+ snprintf(&fsid[i*2],
+ sizeof(fsid) - (i*2), "%02x",
+ ((u_char *)&buf.f_fsid)[i]);
+ }
+ fprintf(fp,
+ "{ fstypename=%s,mntonname=%s,mntfromname=%s,"
+ "fsid=%s }", buf.f_fstypename, buf.f_mntonname,
+ buf.f_mntfromname, fsid);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+
+ case Rusage: {
+ struct rusage ru;
+
+ if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
+ != -1) {
+ fprintf(fp,
+ "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
+ (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
+ (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
+ ru.ru_inblock, ru.ru_oublock);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Rlimit: {
+ struct rlimit rl;
+
+ if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
+ != -1) {
+ fprintf(fp, "{ cur=%ju,max=%ju }",
+ rl.rlim_cur, rl.rlim_max);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case ExitStatus: {
+ int status;
+
+ if (get_struct(pid, args[sc->offset], &status,
+ sizeof(status)) != -1) {
+ fputs("{ ", fp);
+ if (WIFCONTINUED(status))
+ fputs("CONTINUED", fp);
+ else if (WIFEXITED(status))
+ fprintf(fp, "EXITED,val=%d",
+ WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ fprintf(fp, "SIGNALED,sig=%s%s",
+ strsig2(WTERMSIG(status)),
+ WCOREDUMP(status) ? ",cored" : "");
+ else
+ fprintf(fp, "STOPPED,sig=%s",
+ strsig2(WTERMSIG(status)));
+ fputs(" }", fp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Waitoptions:
+ print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]);
+ break;
+ case Idtype:
+ print_integer_arg(sysdecode_idtype, fp, args[sc->offset]);
+ break;
+ case Procctl:
+ print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]);
+ break;
+ case Umtxop: {
+ int rem;
+
+ if (print_mask_arg_part(sysdecode_umtx_op_flags, fp,
+ args[sc->offset], &rem))
+ fprintf(fp, "|");
+ print_integer_arg(sysdecode_umtx_op, fp, rem);
+ break;
+ }
+ case Atfd:
+ print_integer_arg(sysdecode_atfd, fp, args[sc->offset]);
+ break;
+ case Atflags:
+ print_mask_arg(sysdecode_atflags, fp, args[sc->offset]);
+ break;
+ case Accessmode:
+ print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]);
+ break;
+ case Sysarch:
+ print_integer_arg(sysdecode_sysarch_number, fp,
+ args[sc->offset]);
+ break;
+ case Sysctl: {
+ char name[BUFSIZ];
+ int oid[CTL_MAXNAME + 2];
+ size_t len;
+
+ memset(name, 0, sizeof(name));
+ len = args[sc->offset + 1];
+ if (get_struct(pid, args[sc->offset], oid,
+ len * sizeof(oid[0])) != -1) {
+ fprintf(fp, "\"");
+ if (oid[0] == CTL_SYSCTL) {
+ fprintf(fp, "sysctl.");
+ switch (oid[1]) {
+ case CTL_SYSCTL_DEBUG:
+ fprintf(fp, "debug");
+ break;
+ case CTL_SYSCTL_NAME:
+ fprintf(fp, "name ");
+ print_sysctl_oid(fp, oid + 2, len - 2);
+ break;
+ case CTL_SYSCTL_NEXT:
+ fprintf(fp, "next");
+ break;
+ case CTL_SYSCTL_NAME2OID:
+ fprintf(fp, "name2oid %s",
+ get_string(pid,
+ args[sc->offset + 4],
+ args[sc->offset + 5]));
+ break;
+ case CTL_SYSCTL_OIDFMT:
+ fprintf(fp, "oidfmt ");
+ print_sysctl(fp, oid + 2, len - 2);
+ break;
+ case CTL_SYSCTL_OIDDESCR:
+ fprintf(fp, "oiddescr ");
+ print_sysctl(fp, oid + 2, len - 2);
+ break;
+ case CTL_SYSCTL_OIDLABEL:
+ fprintf(fp, "oidlabel ");
+ print_sysctl(fp, oid + 2, len - 2);
+ break;
+ case CTL_SYSCTL_NEXTNOSKIP:
+ fprintf(fp, "nextnoskip");
+ break;
+ default:
+ print_sysctl(fp, oid + 1, len - 1);
+ }
+ } else {
+ print_sysctl(fp, oid, len);
+ }
+ fprintf(fp, "\"");
+ }
+ break;
+ }
+ case PipeFds:
+ /*
+ * The pipe() system call in the kernel returns its
+ * two file descriptors via return values. However,
+ * the interface exposed by libc is that pipe()
+ * accepts a pointer to an array of descriptors.
+ * Format the output to match the libc API by printing
+ * the returned file descriptors as a fake argument.
+ *
+ * Overwrite the first retval to signal a successful
+ * return as well.
+ */
+ fprintf(fp, "{ %d, %d }", (int)retval[0], (int)retval[1]);
+ retval[0] = 0;
+ break;
+ case Utrace: {
+ size_t len;
+ void *utrace_addr;
+
+ len = args[sc->offset + 1];
+ utrace_addr = calloc(1, len);
+ if (get_struct(pid, args[sc->offset],
+ (void *)utrace_addr, len) != -1)
+ print_utrace(fp, utrace_addr, len);
+ else
+ print_pointer(fp, args[sc->offset]);
+ free(utrace_addr);
+ break;
+ }
+ case IntArray: {
+ int descriptors[16];
+ unsigned long i, ndescriptors;
+ bool truncated;
+
+ ndescriptors = args[sc->offset + 1];
+ truncated = false;
+ if (ndescriptors > nitems(descriptors)) {
+ ndescriptors = nitems(descriptors);
+ truncated = true;
+ }
+ if (get_struct(pid, args[sc->offset],
+ descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
+ fprintf(fp, "{");
+ for (i = 0; i < ndescriptors; i++)
+ fprintf(fp, i == 0 ? " %d" : ", %d",
+ descriptors[i]);
+ fprintf(fp, truncated ? ", ... }" : " }");
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Pipe2:
+ print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]);
+ break;
+ case CapFcntlRights: {
+ uint32_t rights;
+
+ if (sc->type & OUT) {
+ if (get_struct(pid, args[sc->offset], &rights,
+ sizeof(rights)) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ } else
+ rights = args[sc->offset];
+ print_mask_arg32(sysdecode_cap_fcntlrights, fp, rights);
+ break;
+ }
+ case Fadvice:
+ print_integer_arg(sysdecode_fadvice, fp, args[sc->offset]);
+ break;
+ case FileFlags: {
+ fflags_t rem;
+
+ if (!sysdecode_fileflags(fp, args[sc->offset], &rem))
+ fprintf(fp, "0x%x", rem);
+ else if (rem != 0)
+ fprintf(fp, "|0x%x", rem);
+ break;
+ }
+ case Flockop:
+ print_mask_arg(sysdecode_flock_operation, fp, args[sc->offset]);
+ break;
+ case Getfsstatmode:
+ print_integer_arg(sysdecode_getfsstat_mode, fp,
+ args[sc->offset]);
+ break;
+ case Itimerwhich:
+ print_integer_arg(sysdecode_itimer, fp, args[sc->offset]);
+ break;
+ case Kldsymcmd:
+ print_integer_arg(sysdecode_kldsym_cmd, fp, args[sc->offset]);
+ break;
+ case Kldunloadflags:
+ print_integer_arg(sysdecode_kldunload_flags, fp,
+ args[sc->offset]);
+ break;
+ case AiofsyncOp:
+ fputs(xlookup(aio_fsync_ops, args[sc->offset]), fp);
+ break;
+ case LioMode:
+ fputs(xlookup(lio_modes, args[sc->offset]), fp);
+ break;
+ case Madvice:
+ print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
+ break;
+ case Socklent:
+ fprintf(fp, "%u", (socklen_t)args[sc->offset]);
+ break;
+ case Sockprotocol: {
+ const char *temp;
+ int domain, protocol;
+
+ domain = args[sc->offset - 2];
+ protocol = args[sc->offset];
+ if (protocol == 0) {
+ fputs("0", fp);
+ } else {
+ temp = sysdecode_socket_protocol(domain, protocol);
+ if (temp) {
+ fputs(temp, fp);
+ } else {
+ fprintf(fp, "%d", protocol);
+ }
+ }
+ break;
+ }
+ case Sockoptlevel:
+ print_integer_arg(sysdecode_sockopt_level, fp,
+ args[sc->offset]);
+ break;
+ case Sockoptname: {
+ const char *temp;
+ int level, name;
+
+ level = args[sc->offset - 1];
+ name = args[sc->offset];
+ temp = sysdecode_sockopt_name(level, name);
+ if (temp) {
+ fputs(temp, fp);
+ } else {
+ fprintf(fp, "%d", name);
+ }
+ break;
+ }
+ case Msgflags:
+ print_mask_arg(sysdecode_msg_flags, fp, args[sc->offset]);
+ break;
+ case CapRights: {
+ cap_rights_t rights;
+
+ if (get_struct(pid, args[sc->offset], &rights,
+ sizeof(rights)) != -1) {
+ fputs("{ ", fp);
+ sysdecode_cap_rights(fp, &rights);
+ fputs(" }", fp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Acltype:
+ print_integer_arg(sysdecode_acltype, fp, args[sc->offset]);
+ break;
+ case Extattrnamespace:
+ print_integer_arg(sysdecode_extattrnamespace, fp,
+ args[sc->offset]);
+ break;
+ case Minherit:
+ print_integer_arg(sysdecode_minherit_inherit, fp,
+ args[sc->offset]);
+ break;
+ case Mlockall:
+ print_mask_arg(sysdecode_mlockall_flags, fp, args[sc->offset]);
+ break;
+ case Mountflags:
+ print_mask_arg(sysdecode_mount_flags, fp, args[sc->offset]);
+ break;
+ case Msync:
+ print_mask_arg(sysdecode_msync_flags, fp, args[sc->offset]);
+ break;
+ case Priowhich:
+ print_integer_arg(sysdecode_prio_which, fp, args[sc->offset]);
+ break;
+ case Ptraceop:
+ print_integer_arg(sysdecode_ptrace_request, fp,
+ args[sc->offset]);
+ break;
+ case Sendfileflags:
+ print_mask_arg(sysdecode_sendfile_flags, fp, args[sc->offset]);
+ break;
+ case Sendfilehdtr: {
+ struct sf_hdtr hdtr;
+
+ if (get_struct(pid, args[sc->offset], &hdtr, sizeof(hdtr)) !=
+ -1) {
+ fprintf(fp, "{");
+ print_iovec(fp, trussinfo, (uintptr_t)hdtr.headers,
+ hdtr.hdr_cnt);
+ print_iovec(fp, trussinfo, (uintptr_t)hdtr.trailers,
+ hdtr.trl_cnt);
+ fprintf(fp, "}");
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Quotactlcmd:
+ if (!sysdecode_quotactl_cmd(fp, args[sc->offset]))
+ fprintf(fp, "%#x", (int)args[sc->offset]);
+ break;
+ case Reboothowto:
+ print_mask_arg(sysdecode_reboot_howto, fp, args[sc->offset]);
+ break;
+ case Rtpriofunc:
+ print_integer_arg(sysdecode_rtprio_function, fp,
+ args[sc->offset]);
+ break;
+ case Schedpolicy:
+ print_integer_arg(sysdecode_scheduler_policy, fp,
+ args[sc->offset]);
+ break;
+ case Schedparam: {
+ struct sched_param sp;
+
+ if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
+ fprintf(fp, "{ %d }", sp.sched_priority);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case PSig: {
+ int sig;
+
+ if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
+ fprintf(fp, "{ %s }", strsig2(sig));
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Siginfo: {
+ siginfo_t si;
+
+ if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
+ fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
+ decode_siginfo(fp, &si);
+ fprintf(fp, " }");
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Iovec:
+ /*
+ * Print argument as an array of struct iovec, where the next
+ * syscall argument is the number of elements of the array.
+ */
+
+ print_iovec(fp, trussinfo, args[sc->offset],
+ (int)args[sc->offset + 1]);
+ break;
+ case Aiocb: {
+ struct aiocb cb;
+
+ if (get_struct(pid, args[sc->offset], &cb, sizeof(cb)) != -1)
+ print_aiocb(fp, &cb);
+ else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case AiocbArray: {
+ /*
+ * Print argment as an array of pointers to struct aiocb, where
+ * the next syscall argument is the number of elements.
+ */
+ uintptr_t cbs[16];
+ unsigned int nent;
+ bool truncated;
+
+ nent = args[sc->offset + 1];
+ truncated = false;
+ if (nent > nitems(cbs)) {
+ nent = nitems(cbs);
+ truncated = true;
+ }
+
+ if (get_struct(pid, args[sc->offset], cbs, sizeof(uintptr_t) * nent) != -1) {
+ unsigned int i;
+ fputs("[", fp);
+ for (i = 0; i < nent; ++i) {
+ struct aiocb cb;
+ if (i > 0)
+ fputc(',', fp);
+ if (get_struct(pid, cbs[i], &cb, sizeof(cb)) != -1)
+ print_aiocb(fp, &cb);
+ else
+ print_pointer(fp, cbs[i]);
+ }
+ if (truncated)
+ fputs(",...", fp);
+ fputs("]", fp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case AiocbPointer: {
+ /*
+ * aio_waitcomplete(2) assigns a pointer to a pointer to struct
+ * aiocb, so we need to handle the extra layer of indirection.
+ */
+ uintptr_t cbp;
+ struct aiocb cb;
+
+ if (get_struct(pid, args[sc->offset], &cbp, sizeof(cbp)) != -1) {
+ if (get_struct(pid, cbp, &cb, sizeof(cb)) != -1)
+ print_aiocb(fp, &cb);
+ else
+ print_pointer(fp, cbp);
+ } else
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ case Sctpsndrcvinfo: {
+ struct sctp_sndrcvinfo info;
+
+ if (get_struct(pid, args[sc->offset],
+ &info, sizeof(struct sctp_sndrcvinfo)) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ print_sctp_sndrcvinfo(fp, sc->type & OUT, &info);
+ break;
+ }
+ case Msghdr: {
+ struct msghdr msghdr;
+
+ if (get_struct(pid, args[sc->offset],
+ &msghdr, sizeof(struct msghdr)) == -1) {
+ print_pointer(fp, args[sc->offset]);
+ break;
+ }
+ fputs("{", fp);
+ print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
+ fprintf(fp, ",%d,", msghdr.msg_namelen);
+ print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov, msghdr.msg_iovlen);
+ fprintf(fp, ",%d,", msghdr.msg_iovlen);
+ print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
+ fprintf(fp, ",%u,", msghdr.msg_controllen);
+ print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
+ fputs("}", fp);
+ break;
+ }
+
+ default:
+ errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
+ }
+ fclose(fp);
+ return (tmp);
+}
+
+/*
+ * Print (to outfile) the system call and its arguments.
+ */
+void
+print_syscall(struct trussinfo *trussinfo)
+{
+ struct threadinfo *t;
+ const char *name;
+ char **s_args;
+ int i, len, nargs;
+
+ t = trussinfo->curthread;
+
+ name = t->cs.sc->name;
+ nargs = t->cs.nargs;
+ s_args = t->cs.s_args;
+
+ len = print_line_prefix(trussinfo);
+ len += fprintf(trussinfo->outfile, "%s(", name);
+
+ for (i = 0; i < nargs; i++) {
+ if (s_args[i] != NULL)
+ len += fprintf(trussinfo->outfile, "%s", s_args[i]);
+ else
+ len += fprintf(trussinfo->outfile,
+ "<missing argument>");
+ len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ?
+ "," : "");
+ }
+ len += fprintf(trussinfo->outfile, ")");
+ for (i = 0; i < 6 - (len / 8); i++)
+ fprintf(trussinfo->outfile, "\t");
+}
+
+void
+print_syscall_ret(struct trussinfo *trussinfo, int error, syscallarg_t *retval)
+{
+ struct timespec timediff;
+ struct threadinfo *t;
+ struct syscall *sc;
+
+ t = trussinfo->curthread;
+ sc = t->cs.sc;
+ if (trussinfo->flags & COUNTONLY) {
+ timespecsub(&t->after, &t->before, &timediff);
+ timespecadd(&sc->time, &timediff, &sc->time);
+ sc->ncalls++;
+ if (error != 0)
+ sc->nerror++;
+ return;
+ }
+
+ print_syscall(trussinfo);
+ fflush(trussinfo->outfile);
+
+ if (retval == NULL) {
+ /*
+ * This system call resulted in the current thread's exit,
+ * so there is no return value or error to display.
+ */
+ fprintf(trussinfo->outfile, "\n");
+ return;
+ }
+
+ if (error == ERESTART)
+ fprintf(trussinfo->outfile, " ERESTART\n");
+ else if (error == EJUSTRETURN)
+ fprintf(trussinfo->outfile, " EJUSTRETURN\n");
+ else if (error != 0) {
+ fprintf(trussinfo->outfile, " ERR#%d '%s'\n",
+ sysdecode_freebsd_to_abi_errno(t->proc->abi->abi, error),
+ strerror(error));
+ } else if (sc->decode.ret_type == 2 &&
+ t->proc->abi->pointer_size == 4) {
+ off_t off;
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ off = (off_t)retval[1] << 32 | retval[0];
+#else
+ off = (off_t)retval[0] << 32 | retval[1];
+#endif
+ fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off,
+ (intmax_t)off);
+ } else {
+ fprintf(trussinfo->outfile, " = %jd (0x%jx)\n",
+ (intmax_t)retval[0], (intmax_t)retval[0]);
+ }
+}
+
+void
+print_summary(struct trussinfo *trussinfo)
+{
+ struct timespec total = {0, 0};
+ struct syscall *sc;
+ int ncall, nerror;
+
+ fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n",
+ "syscall", "seconds", "calls", "errors");
+ ncall = nerror = 0;
+ STAILQ_FOREACH(sc, &seen_syscalls, entries) {
+ if (sc->ncalls) {
+ fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
+ sc->name, (intmax_t)sc->time.tv_sec,
+ sc->time.tv_nsec, sc->ncalls, sc->nerror);
+ timespecadd(&total, &sc->time, &total);
+ ncall += sc->ncalls;
+ nerror += sc->nerror;
+ }
+ }
+ fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n",
+ "", "-------------", "-------", "-------");
+ fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
+ "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror);
+}
diff --git a/usr.bin/truss/truss.1 b/usr.bin/truss/truss.1
new file mode 100644
index 000000000000..a0cd90b229aa
--- /dev/null
+++ b/usr.bin/truss/truss.1
@@ -0,0 +1,116 @@
+.\"
+.Dd July 24, 2017
+.Dt TRUSS 1
+.Os
+.Sh NAME
+.Nm truss
+.Nd trace system calls
+.Sh SYNOPSIS
+.Nm
+.Op Fl facedDHS
+.Op Fl o Ar file
+.Op Fl s Ar strsize
+.Fl p Ar pid
+.Nm
+.Op Fl facedDHS
+.Op Fl o Ar file
+.Op Fl s Ar strsize
+.Ar command Op Ar args
+.Sh DESCRIPTION
+The
+.Nm
+utility traces the system calls called by the specified process or program.
+Output is to the specified output file, or standard error by default.
+It does this by stopping and restarting the process being monitored via
+.Xr ptrace 2 .
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f
+Trace descendants of the original traced process created by
+.Xr fork 2 ,
+.Xr vfork 2 ,
+etc.
+To distinguish events between processes,
+the process ID
+.Pq PID
+of the process is included in the output of each event.
+.It Fl a
+Show the argument strings that are passed in each
+.Xr execve 2
+system call.
+.It Fl c
+Do not display individual system calls or signals.
+Instead, before exiting, print a summary containing for each system call:
+the total system time used,
+the number of times the call was invoked,
+and the number of times the call returned with an error.
+.It Fl e
+Show the environment strings that are passed in each
+.Xr execve 2
+system call.
+.It Fl d
+Include timestamps in the output showing the time elapsed
+since the trace was started.
+.It Fl D
+Include timestamps in the output showing the time elapsed
+since the last recorded event.
+.It Fl H
+Include the thread ID of in the output of each event.
+.It Fl S
+Do not display information about signals received by the process.
+(Normally,
+.Nm
+displays signal as well as system call events.)
+.It Fl o Ar file
+Print the output to the specified
+.Ar file
+instead of standard error.
+.It Fl s Ar strsize
+Display strings using at most
+.Ar strsize
+characters.
+If the buffer is larger,
+.Dq Li ...
+will be displayed at the end of the string.
+The default
+.Ar strsize
+is 32.
+.It Fl p Ar pid
+Follow the process specified by
+.Ar pid
+instead of a new command.
+.It Ar command Op Ar args
+Execute
+.Ar command
+and trace the system calls of it.
+(The
+.Fl p
+and
+.Ar command
+options are mutually exclusive.)
+.El
+.Sh EXAMPLES
+Follow the system calls used in echoing "hello":
+.Dl $ truss /bin/echo hello
+.Pp
+Do the same, but put the output into a file:
+.Dl $ truss -o /tmp/truss.out /bin/echo hello
+.Pp
+Follow an already-running process:
+.Dl $ truss -p 34
+.Sh SEE ALSO
+.Xr dtrace 1 ,
+.Xr kdump 1 ,
+.Xr ktrace 1 ,
+.Xr ptrace 2 ,
+.Xr utrace 2
+.Sh HISTORY
+The
+.Nm
+command was written by
+.An Sean Eric Fagan
+for
+.Fx .
+It was modeled after
+similar commands available for System V Release 4 and SunOS.
diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h
new file mode 100644
index 000000000000..e895ca27c26e
--- /dev/null
+++ b/usr.bin/truss/truss.h
@@ -0,0 +1,116 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2001 Jamey Wood
+ *
+ * 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 AUTHOR 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 AUTHOR 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/queue.h>
+
+#define FOLLOWFORKS 0x00000001
+#define RELATIVETIMESTAMPS 0x00000002
+#define ABSOLUTETIMESTAMPS 0x00000004
+#define NOSIGS 0x00000008
+#define EXECVEARGS 0x00000010
+#define EXECVEENVS 0x00000020
+#define COUNTONLY 0x00000040
+#define DISPLAYTIDS 0x00000080
+
+struct procinfo;
+struct syscall;
+struct trussinfo;
+
+/*
+ * The lookup of normal system calls are optimized by using a fixed
+ * array for the first 1024 system calls that can be indexed directly.
+ * Unknown system calls with other IDs are stored in a linked list.
+ */
+#define SYSCALL_NORMAL_COUNT 1024
+
+struct extra_syscall {
+ STAILQ_ENTRY(extra_syscall) entries;
+ struct syscall *sc;
+ u_int number;
+};
+
+struct procabi {
+ const char *type;
+ enum sysdecode_abi abi;
+ size_t pointer_size;
+ const char *compat_prefix;
+ STAILQ_HEAD(, extra_syscall) extra_syscalls;
+ struct syscall *syscalls[SYSCALL_NORMAL_COUNT];
+};
+
+/*
+ * This is confusingly named. It holds per-thread state about the
+ * currently executing system call. syscall.h defines a struct
+ * syscall that holds metadata used to format system call arguments.
+ *
+ * NB: args[] stores the raw argument values (e.g. from registers)
+ * passed to the system call. s_args[] stores a string representation
+ * of a system call's arguments. These do not necessarily map one to
+ * one. A system call description may omit individual arguments
+ * (padding) or combine adjacent arguments (e.g. when passing an off_t
+ * argument on a 32-bit system). The nargs member contains the count
+ * of valid pointers in s_args[], not args[].
+ */
+struct current_syscall {
+ struct syscall *sc;
+ unsigned int number;
+ unsigned int nargs;
+ syscallarg_t args[10];
+ char *s_args[10]; /* the printable arguments */
+};
+
+struct threadinfo
+{
+ LIST_ENTRY(threadinfo) entries;
+ struct procinfo *proc;
+ lwpid_t tid;
+ int in_syscall;
+ struct current_syscall cs;
+ struct timespec before;
+ struct timespec after;
+};
+
+struct procinfo {
+ LIST_ENTRY(procinfo) entries;
+ pid_t pid;
+ struct procabi *abi;
+
+ LIST_HEAD(, threadinfo) threadlist;
+};
+
+struct trussinfo
+{
+ int flags;
+ int strsize;
+ FILE *outfile;
+
+ struct timespec start_time;
+
+ struct threadinfo *curthread;
+
+ LIST_HEAD(, procinfo) proclist;
+};
diff --git a/usr.bin/tsort/Makefile b/usr.bin/tsort/Makefile
new file mode 100644
index 000000000000..4603b97959bc
--- /dev/null
+++ b/usr.bin/tsort/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= tsort
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tsort/Makefile.depend b/usr.bin/tsort/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/tsort/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tsort/tests/Makefile b/usr.bin/tsort/tests/Makefile
new file mode 100644
index 000000000000..ab16c2842dd0
--- /dev/null
+++ b/usr.bin/tsort/tests/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= tsort_test
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/tsort/tests/Makefile.depend b/usr.bin/tsort/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/tsort/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tsort/tests/tsort_test.sh b/usr.bin/tsort/tests/tsort_test.sh
new file mode 100755
index 000000000000..88d4efaf2b9f
--- /dev/null
+++ b/usr.bin/tsort/tests/tsort_test.sh
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+atf_test_case basic
+basic_head()
+{
+ atf_set "descr" "Sort a basic graph"
+}
+basic_body()
+{
+ cat >input <<EOF
+A B
+A F
+B C
+B D
+D E
+EOF
+ cat >output <<EOF
+A
+F
+B
+D
+C
+E
+EOF
+ atf_check -o file:output tsort input
+ atf_check -o file:output tsort <input
+}
+
+atf_test_case cycle
+cycle_head()
+{
+ atf_set "descr" "Sort a graph with a cycle"
+}
+cycle_body()
+{
+ cat >input <<EOF
+A B
+A F
+B C
+B D
+D E
+D A
+EOF
+ cat >output<<EOF
+D
+E
+A
+F
+B
+C
+EOF
+ atf_check -e match:cycle -o file:output tsort input
+ atf_check -e match:cycle -o file:output tsort <input
+ atf_check -o file:output tsort -q input
+ atf_check -o file:output tsort -q <input
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case cycle
+}
diff --git a/usr.bin/tsort/tsort.1 b/usr.bin/tsort/tsort.1
new file mode 100644
index 000000000000..b6df3428cb3e
--- /dev/null
+++ b/usr.bin/tsort/tsort.1
@@ -0,0 +1,155 @@
+.\" Copyright (c) 1990, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This manual is derived from one contributed to Berkeley by
+.\" Michael Rendell of Memorial University of Newfoundland.
+.\"
+.\" 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.
+.\"
+.Dd August 30, 2020
+.Dt TSORT 1
+.Os
+.Sh NAME
+.Nm tsort
+.Nd topological sort of a directed graph
+.Sh SYNOPSIS
+.Nm
+.Op Fl dlq
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility takes a list of pairs of node names representing directed arcs in
+a graph and prints the nodes in topological order on standard output.
+Input is taken from the named
+.Ar file ,
+or from standard input if no file
+is given.
+.Pp
+There must be an even number of nodes in the input.
+Node names specified on the same line should be white space separated.
+.Pp
+Presence of a node in a graph can be represented by an arc from the node
+to itself.
+This is useful when a node is not connected to any other nodes.
+.Pp
+If the graph contains a cycle (and therefore cannot be properly sorted),
+one of the arcs in the cycle is ignored and the sort continues.
+Cycles are reported on standard error.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d
+Turn on debugging.
+.It Fl l
+Search for and display the longest cycle.
+Can take a very long time.
+.It Fl q
+Do not display informational messages about cycles.
+This is primarily
+intended for building libraries, where optimal ordering is not critical,
+and cycles occur often.
+.El
+.Sh EXAMPLES
+Assuming a file named
+.Pa dag
+with the following contents representing a directed acyclic graph:
+.Bd -literal -offset indent
+A B
+A F
+B C
+B D
+D E
+.Ed
+.Pp
+Sort the nodes of the graph:
+.Bd -literal -offset indent
+$ tsort dag
+A
+F
+B
+D
+C
+E
+.Ed
+.Pp
+White spaces and new line characters are considered equal.
+This file for example is considered equal to the one we defined before:
+.Bd -literal -offset indent
+$ cat dga
+A B A F B C B D D E
+.Ed
+.Pp
+Assume we add a new directed arc from D to A creating a cycle:
+.Bd -literal -offset indent
+A B
+A F
+B C
+B D
+D E
+D A
+.Ed
+.Pp
+Ordering the graph detects the cycle:
+.Bd -literal -offset indent
+$ tsort dag
+tsort: cycle in data
+tsort: A
+tsort: B
+tsort: D
+D
+E
+A
+F
+B
+C
+.Ed
+.Pp
+Same as above but silencing the warning about the cycle:
+.Bd -literal -offset indent
+$ tsort -q dag
+D
+E
+A
+F
+B
+C
+.Ed
+.Sh SEE ALSO
+.Xr ar 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.At v7 .
+This
+.Nm
+command and manual page are derived from sources contributed to Berkeley by
+.An Michael Rendell
+of Memorial University of Newfoundland.
+.Sh BUGS
+The
+.Nm
+utility does not recognize multibyte characters.
diff --git a/usr.bin/tsort/tsort.c b/usr.bin/tsort/tsort.c
new file mode 100644
index 000000000000..1be014f8125d
--- /dev/null
+++ b/usr.bin/tsort/tsort.c
@@ -0,0 +1,419 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Michael Rendell of Memorial University of Newfoundland.
+ *
+ * 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 <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Topological sort. Input is a list of pairs of strings separated by
+ * white space (spaces, tabs, and/or newlines); strings are written to
+ * standard output in sorted order, one per line.
+ *
+ * usage:
+ * tsort [-dlq] [inputfile]
+ * If no input file is specified, standard input is read.
+ *
+ * Should be compatible with AT&T tsort HOWEVER the output is not identical
+ * (i.e. for most graphs there is more than one sorted order, and this tsort
+ * usually generates a different one then the AT&T tsort). Also, cycle
+ * reporting seems to be more accurate in this version (the AT&T tsort
+ * sometimes says a node is in a cycle when it isn't).
+ *
+ * Michael Rendell, michael@stretch.cs.mun.ca - Feb 26, '90
+ */
+
+#define NF_MARK 0x1 /* marker for cycle detection */
+#define NF_ACYCLIC 0x2 /* this node is cycle free */
+#define NF_NODEST 0x4 /* Unreachable */
+
+
+typedef struct node_str NODE;
+
+struct node_str {
+ NODE **n_prevp; /* pointer to previous node's n_next */
+ NODE *n_next; /* next node in graph */
+ NODE **n_arcs; /* array of arcs to other nodes */
+ int n_narcs; /* number of arcs in n_arcs[] */
+ int n_arcsize; /* size of n_arcs[] array */
+ int n_refcnt; /* # of arcs pointing to this node */
+ int n_flags; /* NF_* */
+ char n_name[1]; /* name of this node */
+};
+
+typedef struct _buf {
+ char *b_buf;
+ int b_bsize;
+} BUF;
+
+static DB *db;
+static NODE *graph, **cycle_buf, **longest_cycle;
+static int debug, longest, quiet;
+
+static void add_arc(char *, char *);
+static int find_cycle(NODE *, NODE *, int, int);
+static NODE *get_node(char *);
+static void *grow_buf(void *, size_t);
+static void remove_node(NODE *);
+static void clear_cycle(void);
+static void tsort(void);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ BUF *b;
+ int c, n;
+ FILE *fp;
+ int bsize, ch, nused;
+ BUF bufs[2];
+
+ fp = NULL;
+ while ((ch = getopt(argc, argv, "dlq")) != -1)
+ switch (ch) {
+ case 'd':
+ debug = 1;
+ break;
+ case 'l':
+ longest = 1;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (argc) {
+ case 0:
+ fp = stdin;
+ break;
+ case 1:
+ if ((fp = fopen(*argv, "r")) == NULL)
+ err(1, "%s", *argv);
+ break;
+ default:
+ usage();
+ }
+
+ for (b = bufs, n = 2; --n >= 0; b++)
+ b->b_buf = grow_buf(NULL, b->b_bsize = 1024);
+
+ /* parse input and build the graph */
+ for (n = 0, c = getc(fp);;) {
+ while (c != EOF && isspace(c))
+ c = getc(fp);
+ if (c == EOF)
+ break;
+
+ nused = 0;
+ b = &bufs[n];
+ bsize = b->b_bsize;
+ do {
+ b->b_buf[nused++] = c;
+ if (nused == bsize)
+ b->b_buf = grow_buf(b->b_buf, bsize *= 2);
+ c = getc(fp);
+ } while (c != EOF && !isspace(c));
+
+ b->b_buf[nused] = '\0';
+ b->b_bsize = bsize;
+ if (n)
+ add_arc(bufs[0].b_buf, bufs[1].b_buf);
+ n = !n;
+ }
+ (void)fclose(fp);
+ if (n)
+ errx(1, "odd data count");
+
+ /* do the sort */
+ tsort();
+ if (ferror(stdout) != 0 || fflush(stdout) != 0)
+ err(1, "stdout");
+ exit(0);
+}
+
+/* double the size of oldbuf and return a pointer to the new buffer. */
+static void *
+grow_buf(void *bp, size_t size)
+{
+ if ((bp = realloc(bp, size)) == NULL)
+ err(1, NULL);
+ return (bp);
+}
+
+/*
+ * add an arc from node s1 to node s2 in the graph. If s1 or s2 are not in
+ * the graph, then add them.
+ */
+static void
+add_arc(char *s1, char *s2)
+{
+ NODE *n1;
+ NODE *n2;
+ int bsize, i;
+
+ n1 = get_node(s1);
+
+ if (!strcmp(s1, s2))
+ return;
+
+ n2 = get_node(s2);
+
+ /*
+ * Check if this arc is already here.
+ */
+ for (i = 0; i < n1->n_narcs; i++)
+ if (n1->n_arcs[i] == n2)
+ return;
+ /*
+ * Add it.
+ */
+ if (n1->n_narcs == n1->n_arcsize) {
+ if (!n1->n_arcsize)
+ n1->n_arcsize = 10;
+ bsize = n1->n_arcsize * sizeof(*n1->n_arcs) * 2;
+ n1->n_arcs = grow_buf(n1->n_arcs, bsize);
+ n1->n_arcsize = bsize / sizeof(*n1->n_arcs);
+ }
+ n1->n_arcs[n1->n_narcs++] = n2;
+ ++n2->n_refcnt;
+}
+
+/* Find a node in the graph (insert if not found) and return a pointer to it. */
+static NODE *
+get_node(char *name)
+{
+ DBT data, key;
+ NODE *n;
+
+ if (db == NULL &&
+ (db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == NULL)
+ err(1, "db: %s", name);
+
+ key.data = name;
+ key.size = strlen(name) + 1;
+
+ switch ((*db->get)(db, &key, &data, 0)) {
+ case 0:
+ memcpy(&n, data.data, sizeof(n));
+ return (n);
+ case 1:
+ break;
+ default:
+ case -1:
+ err(1, "db: %s", name);
+ }
+
+ if ((n = malloc(sizeof(NODE) + key.size)) == NULL)
+ err(1, NULL);
+
+ n->n_narcs = 0;
+ n->n_arcsize = 0;
+ n->n_arcs = NULL;
+ n->n_refcnt = 0;
+ n->n_flags = 0;
+ memcpy(n->n_name, name, key.size);
+
+ /* Add to linked list. */
+ if ((n->n_next = graph) != NULL)
+ graph->n_prevp = &n->n_next;
+ n->n_prevp = &graph;
+ graph = n;
+
+ /* Add to hash table. */
+ data.data = &n;
+ data.size = sizeof(n);
+ if ((*db->put)(db, &key, &data, 0))
+ err(1, "db: %s", name);
+ return (n);
+}
+
+
+/*
+ * Clear the NODEST flag from all nodes.
+ */
+static void
+clear_cycle(void)
+{
+ NODE *n;
+
+ for (n = graph; n != NULL; n = n->n_next)
+ n->n_flags &= ~NF_NODEST;
+}
+
+/* do topological sort on graph */
+static void
+tsort(void)
+{
+ NODE *n, *next;
+ int cnt, i;
+
+ while (graph != NULL) {
+ /*
+ * Keep getting rid of simple cases until there are none left,
+ * if there are any nodes still in the graph, then there is
+ * a cycle in it.
+ */
+ do {
+ for (cnt = 0, n = graph; n != NULL; n = next) {
+ next = n->n_next;
+ if (n->n_refcnt == 0) {
+ remove_node(n);
+ ++cnt;
+ }
+ }
+ } while (graph != NULL && cnt);
+
+ if (graph == NULL)
+ break;
+
+ if (!cycle_buf) {
+ /*
+ * Allocate space for two cycle logs - one to be used
+ * as scratch space, the other to save the longest
+ * cycle.
+ */
+ for (cnt = 0, n = graph; n != NULL; n = n->n_next)
+ ++cnt;
+ cycle_buf = malloc(sizeof(NODE *) * cnt);
+ longest_cycle = malloc(sizeof(NODE *) * cnt);
+ if (cycle_buf == NULL || longest_cycle == NULL)
+ err(1, NULL);
+ }
+ for (n = graph; n != NULL; n = n->n_next)
+ if (!(n->n_flags & NF_ACYCLIC)) {
+ if ((cnt = find_cycle(n, n, 0, 0))) {
+ if (!quiet) {
+ warnx("cycle in data");
+ for (i = 0; i < cnt; i++)
+ warnx("%s",
+ longest_cycle[i]->n_name);
+ }
+ remove_node(n);
+ clear_cycle();
+ break;
+ } else {
+ /* to avoid further checks */
+ n->n_flags |= NF_ACYCLIC;
+ clear_cycle();
+ }
+ }
+
+ if (n == NULL)
+ errx(1, "internal error -- could not find cycle");
+ }
+}
+
+/* print node and remove from graph (does not actually free node) */
+static void
+remove_node(NODE *n)
+{
+ NODE **np;
+ int i;
+
+ (void)printf("%s\n", n->n_name);
+ for (np = n->n_arcs, i = n->n_narcs; --i >= 0; np++)
+ --(*np)->n_refcnt;
+ n->n_narcs = 0;
+ *n->n_prevp = n->n_next;
+ if (n->n_next)
+ n->n_next->n_prevp = n->n_prevp;
+}
+
+
+/* look for the longest? cycle from node from to node to. */
+static int
+find_cycle(NODE *from, NODE *to, int longest_len, int depth)
+{
+ NODE **np;
+ int i, len;
+
+ /*
+ * avoid infinite loops and ignore portions of the graph known
+ * to be acyclic
+ */
+ if (from->n_flags & (NF_NODEST|NF_MARK|NF_ACYCLIC))
+ return (0);
+ from->n_flags |= NF_MARK;
+
+ for (np = from->n_arcs, i = from->n_narcs; --i >= 0; np++) {
+ cycle_buf[depth] = *np;
+ if (*np == to) {
+ if (depth + 1 > longest_len) {
+ longest_len = depth + 1;
+ (void)memcpy((char *)longest_cycle,
+ (char *)cycle_buf,
+ longest_len * sizeof(NODE *));
+ }
+ } else {
+ if ((*np)->n_flags & (NF_MARK|NF_ACYCLIC|NF_NODEST))
+ continue;
+ len = find_cycle(*np, to, longest_len, depth + 1);
+
+ if (debug)
+ (void)printf("%*s %s->%s %d\n", depth, "",
+ from->n_name, to->n_name, len);
+
+ if (len == 0)
+ (*np)->n_flags |= NF_NODEST;
+
+ if (len > longest_len)
+ longest_len = len;
+
+ if (len > 0 && !longest)
+ break;
+ }
+ }
+ from->n_flags &= ~NF_MARK;
+ return (longest_len);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: tsort [-dlq] [file]\n");
+ exit(1);
+}
diff --git a/usr.bin/tty/Makefile b/usr.bin/tty/Makefile
new file mode 100644
index 000000000000..e0e47132f825
--- /dev/null
+++ b/usr.bin/tty/Makefile
@@ -0,0 +1,3 @@
+PROG= tty
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/tty/Makefile.depend b/usr.bin/tty/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/tty/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/tty/tty.1 b/usr.bin/tty/tty.1
new file mode 100644
index 000000000000..9839cfd0cc13
--- /dev/null
+++ b/usr.bin/tty/tty.1
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd June 6, 1993
+.Dt TTY 1
+.Os
+.Sh NAME
+.Nm tty
+.Nd return user's terminal name
+.Sh SYNOPSIS
+.Nm
+.Op Fl s
+.Sh DESCRIPTION
+The
+.Nm
+utility writes the name of the terminal attached to standard input
+to standard output.
+The name that is written is the string returned by
+.Xr ttyname 3 .
+If the standard input is not a terminal, the message
+.Dq Li "not a tty"
+is written.
+The options are as follows:
+.Bl -tag -width indent
+.It Fl s
+Do not write the terminal name; only the exit status is affected
+when this option is specified.
+The
+.Fl s
+option is deprecated in favor of the
+.Dq Li "test -t 0"
+command.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility
+exits 0 if the standard input is a terminal, 1 if the standard input is
+not a terminal, and >1 if an error occurs.
+.Sh SEE ALSO
+.Xr test 1 ,
+.Xr ttyname 3
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compatible.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/tty/tty.c b/usr.bin/tty/tty.c
new file mode 100644
index 000000000000..a77dca6ca653
--- /dev/null
+++ b/usr.bin/tty/tty.c
@@ -0,0 +1,67 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void usage(void) __dead2;
+
+int
+main(int argc, char *argv[])
+{
+ int ch, sflag;
+ char *t;
+
+ sflag = 0;
+ while ((ch = getopt(argc, argv, "s")) != -1)
+ switch (ch) {
+ case 's':
+ sflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ t = ttyname(STDIN_FILENO);
+ if (!sflag)
+ puts(t ? t : "not a tty");
+ exit(t ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-s]\n", getprogname());
+ exit(2);
+}
diff --git a/usr.bin/ul/Makefile b/usr.bin/ul/Makefile
new file mode 100644
index 000000000000..48a487781b33
--- /dev/null
+++ b/usr.bin/ul/Makefile
@@ -0,0 +1,5 @@
+PROG= ul
+
+LIBADD= tinfow
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ul/Makefile.depend b/usr.bin/ul/Makefile.depend
new file mode 100644
index 000000000000..dd06faaab7bf
--- /dev/null
+++ b/usr.bin/ul/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ul/ul.1 b/usr.bin/ul/ul.1
new file mode 100644
index 000000000000..b9ffbe63d898
--- /dev/null
+++ b/usr.bin/ul/ul.1
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd October 7, 2020
+.Dt UL 1
+.Os
+.Sh NAME
+.Nm ul
+.Nd do underlining
+.Sh SYNOPSIS
+.Nm
+.Op Fl i
+.Op Fl t Ar terminal
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility reads the named files (or standard input if none are given)
+and translates occurrences of underscores to the sequence
+which indicates underlining for the terminal in use, as specified
+by the environment variable
+.Ev TERM .
+The file
+.Pa /etc/termcap
+is read to determine the appropriate sequences for underlining.
+If the terminal is incapable of underlining, but is capable of
+a standout mode then that is used instead.
+If the terminal can overstrike,
+or handles underlining automatically,
+.Nm
+degenerates to
+.Xr cat 1 .
+If the terminal cannot underline, underlining is ignored.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl i
+Underlining is indicated by a separate line containing appropriate
+dashes
+.Ql \- .
+.It Fl t Ar terminal
+Overrides the terminal type specified in the environment with
+.Ar terminal .
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL , LC_CTYPE
+and
+.Ev TERM
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr man 1 ,
+.Xr mandoc 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/ul/ul.c b/usr.bin/ul/ul.c
new file mode 100644
index 000000000000..68a320b398b7
--- /dev/null
+++ b/usr.bin/ul/ul.c
@@ -0,0 +1,574 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termcap.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#define IESC '\033'
+#define SO '\016'
+#define SI '\017'
+#define HFWD '9'
+#define HREV '8'
+#define FREV '7'
+#define MAXBUF 512
+
+#define NORMAL 000
+#define ALTSET 001 /* Reverse */
+#define SUPERSC 002 /* Dim */
+#define SUBSC 004 /* Dim | Ul */
+#define UNDERL 010 /* Ul */
+#define BOLD 020 /* Bold */
+
+static int must_use_uc, must_overstrike;
+static const char
+ *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
+ *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
+ *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
+
+struct CHAR {
+ char c_mode;
+ wchar_t c_char;
+ int c_width; /* width or -1 if multi-column char. filler */
+} ;
+
+static struct CHAR sobuf[MAXBUF]; /* static output buffer */
+static struct CHAR *obuf = sobuf;
+static int buflen = MAXBUF;
+static int col, maxcol;
+static int mode;
+static int halfpos;
+static int upln;
+static int iflag;
+
+static void usage(void) __dead2;
+static void setnewmode(int);
+static void initcap(void);
+static void reverse(void);
+static int outchar(int);
+static void fwd(void);
+static void initbuf(void);
+static void iattr(void);
+static void overstrike(void);
+static void flushln(void);
+static void filter(FILE *);
+static void outc(wint_t, int);
+
+#define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar)
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ const char *termtype;
+ FILE *f;
+ char termcap[1024];
+
+ setlocale(LC_ALL, "");
+
+ termtype = getenv("TERM");
+ if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
+ termtype = "lpr";
+ while ((c = getopt(argc, argv, "it:T:")) != -1)
+ switch (c) {
+ case 't':
+ case 'T': /* for nroff compatibility */
+ termtype = optarg;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ default:
+ usage();
+ }
+
+ switch (tgetent(termcap, termtype)) {
+ case 1:
+ break;
+ default:
+ warnx("trouble reading termcap");
+ /* FALLTHROUGH */
+ case 0:
+ /* No such terminal type - assume dumb */
+ (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
+ break;
+ }
+ initcap();
+ if ((tgetflag("os") && ENTER_BOLD == NULL ) ||
+ (tgetflag("ul") && ENTER_UNDERLINE == NULL && UNDER_CHAR == NULL))
+ must_overstrike = 1;
+ initbuf();
+ if (optind == argc)
+ filter(stdin);
+ else for (; optind<argc; optind++) {
+ f = fopen(argv[optind],"r");
+ if (f == NULL)
+ err(1, "%s", argv[optind]);
+ else
+ filter(f);
+ }
+ if (obuf != sobuf) {
+ free(obuf);
+ }
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: ul [-i] [-t terminal] [file ...]\n");
+ exit(1);
+}
+
+static void
+filter(FILE *f)
+{
+ wint_t c;
+ int i, w;
+ int copy;
+
+ copy = 0;
+
+ while ((c = getwc(f)) != WEOF) {
+ if (col == buflen) {
+ if (obuf == sobuf) {
+ obuf = NULL;
+ copy = 1;
+ }
+ obuf = realloc(obuf, sizeof(*obuf) * 2 * buflen);
+ if (obuf == NULL) {
+ obuf = sobuf;
+ break;
+ } else if (copy) {
+ memcpy(obuf, sobuf, sizeof(*obuf) * buflen);
+ copy = 0;
+ }
+ bzero((char *)(obuf + buflen), sizeof(*obuf) * buflen);
+ buflen *= 2;
+ }
+ switch(c) {
+ case '\b':
+ if (col > 0)
+ col--;
+ continue;
+
+ case '\t':
+ col = (col+8) & ~07;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+
+ case '\r':
+ col = 0;
+ continue;
+
+ case SO:
+ mode |= ALTSET;
+ continue;
+
+ case SI:
+ mode &= ~ALTSET;
+ continue;
+
+ case IESC:
+ switch (c = getwc(f)) {
+
+ case HREV:
+ if (halfpos == 0) {
+ mode |= SUPERSC;
+ halfpos--;
+ } else if (halfpos > 0) {
+ mode &= ~SUBSC;
+ halfpos--;
+ } else {
+ halfpos = 0;
+ reverse();
+ }
+ continue;
+
+ case HFWD:
+ if (halfpos == 0) {
+ mode |= SUBSC;
+ halfpos++;
+ } else if (halfpos < 0) {
+ mode &= ~SUPERSC;
+ halfpos++;
+ } else {
+ halfpos = 0;
+ fwd();
+ }
+ continue;
+
+ case FREV:
+ reverse();
+ continue;
+
+ default:
+ errx(1, "unknown escape sequence in input: %o, %o", IESC, c);
+ }
+ continue;
+
+ case '_':
+ if (obuf[col].c_char || obuf[col].c_width < 0) {
+ while (col > 0 && obuf[col].c_width < 0)
+ col--;
+ w = obuf[col].c_width;
+ for (i = 0; i < w; i++)
+ obuf[col++].c_mode |= UNDERL | mode;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+ }
+ obuf[col].c_char = '_';
+ obuf[col].c_width = 1;
+ /* FALLTHROUGH */
+ case ' ':
+ col++;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+
+ case '\n':
+ flushln();
+ continue;
+
+ case '\f':
+ flushln();
+ putwchar('\f');
+ continue;
+
+ default:
+ if ((w = wcwidth(c)) <= 0) /* non printing */
+ continue;
+ if (obuf[col].c_char == '\0') {
+ obuf[col].c_char = c;
+ for (i = 0; i < w; i++)
+ obuf[col + i].c_mode = mode;
+ obuf[col].c_width = w;
+ for (i = 1; i < w; i++)
+ obuf[col + i].c_width = -1;
+ } else if (obuf[col].c_char == '_') {
+ obuf[col].c_char = c;
+ for (i = 0; i < w; i++)
+ obuf[col + i].c_mode |= UNDERL|mode;
+ obuf[col].c_width = w;
+ for (i = 1; i < w; i++)
+ obuf[col + i].c_width = -1;
+ } else if ((wint_t)obuf[col].c_char == c) {
+ for (i = 0; i < w; i++)
+ obuf[col + i].c_mode |= BOLD|mode;
+ } else {
+ w = obuf[col].c_width;
+ for (i = 0; i < w; i++)
+ obuf[col + i].c_mode = mode;
+ }
+ col += w;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+ }
+ }
+ if (ferror(f))
+ err(1, NULL);
+ if (maxcol)
+ flushln();
+}
+
+static void
+flushln(void)
+{
+ int lastmode;
+ int i;
+ int hadmodes = 0;
+
+ lastmode = NORMAL;
+ for (i = 0; i < maxcol; i++) {
+ if (obuf[i].c_mode != lastmode) {
+ hadmodes++;
+ setnewmode(obuf[i].c_mode);
+ lastmode = obuf[i].c_mode;
+ }
+ if (obuf[i].c_char == '\0') {
+ if (upln)
+ PRINT(CURS_RIGHT);
+ else
+ outc(' ', 1);
+ } else
+ outc(obuf[i].c_char, obuf[i].c_width);
+ if (obuf[i].c_width > 1)
+ i += obuf[i].c_width - 1;
+ }
+ if (lastmode != NORMAL) {
+ setnewmode(0);
+ }
+ if (must_overstrike && hadmodes)
+ overstrike();
+ putwchar('\n');
+ if (iflag && hadmodes)
+ iattr();
+ (void)fflush(stdout);
+ if (upln)
+ upln--;
+ initbuf();
+}
+
+/*
+ * For terminals that can overstrike, overstrike underlines and bolds.
+ * We don't do anything with halfline ups and downs, or Greek.
+ */
+static void
+overstrike(void)
+{
+ int i;
+ wchar_t lbuf[256];
+ wchar_t *cp = lbuf;
+ int hadbold=0;
+
+ /* Set up overstrike buffer */
+ for (i=0; i<maxcol; i++)
+ switch (obuf[i].c_mode) {
+ case NORMAL:
+ default:
+ *cp++ = ' ';
+ break;
+ case UNDERL:
+ *cp++ = '_';
+ break;
+ case BOLD:
+ *cp++ = obuf[i].c_char;
+ if (obuf[i].c_width > 1)
+ i += obuf[i].c_width - 1;
+ hadbold=1;
+ break;
+ }
+ putwchar('\r');
+ for (*cp=' '; *cp==' '; cp--)
+ *cp = 0;
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp);
+ if (hadbold) {
+ putwchar('\r');
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp=='_' ? ' ' : *cp);
+ putwchar('\r');
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp=='_' ? ' ' : *cp);
+ }
+}
+
+static void
+iattr(void)
+{
+ int i;
+ wchar_t lbuf[256];
+ wchar_t *cp = lbuf;
+
+ for (i=0; i<maxcol; i++)
+ switch (obuf[i].c_mode) {
+ case NORMAL: *cp++ = ' '; break;
+ case ALTSET: *cp++ = 'g'; break;
+ case SUPERSC: *cp++ = '^'; break;
+ case SUBSC: *cp++ = 'v'; break;
+ case UNDERL: *cp++ = '_'; break;
+ case BOLD: *cp++ = '!'; break;
+ default: *cp++ = 'X'; break;
+ }
+ for (*cp=' '; *cp==' '; cp--)
+ *cp = 0;
+ for (cp=lbuf; *cp; cp++)
+ putwchar(*cp);
+ putwchar('\n');
+}
+
+static void
+initbuf(void)
+{
+
+ bzero((char *)obuf, buflen * sizeof(*obuf)); /* depends on NORMAL == 0 */
+ col = 0;
+ maxcol = 0;
+ mode &= ALTSET;
+}
+
+static void
+fwd(void)
+{
+ int oldcol, oldmax;
+
+ oldcol = col;
+ oldmax = maxcol;
+ flushln();
+ col = oldcol;
+ maxcol = oldmax;
+}
+
+static void
+reverse(void)
+{
+ upln++;
+ fwd();
+ PRINT(CURS_UP);
+ PRINT(CURS_UP);
+ upln++;
+}
+
+static void
+initcap(void)
+{
+ static char tcapbuf[512];
+ char *bp = tcapbuf;
+
+ /* This nonsense attempts to work with both old and new termcap */
+ CURS_UP = tgetstr("up", &bp);
+ CURS_RIGHT = tgetstr("ri", &bp);
+ if (CURS_RIGHT == NULL)
+ CURS_RIGHT = tgetstr("nd", &bp);
+ CURS_LEFT = tgetstr("le", &bp);
+ if (CURS_LEFT == NULL)
+ CURS_LEFT = tgetstr("bc", &bp);
+ if (CURS_LEFT == NULL && tgetflag("bs"))
+ CURS_LEFT = "\b";
+
+ ENTER_STANDOUT = tgetstr("so", &bp);
+ EXIT_STANDOUT = tgetstr("se", &bp);
+ ENTER_UNDERLINE = tgetstr("us", &bp);
+ EXIT_UNDERLINE = tgetstr("ue", &bp);
+ ENTER_DIM = tgetstr("mh", &bp);
+ ENTER_BOLD = tgetstr("md", &bp);
+ ENTER_REVERSE = tgetstr("mr", &bp);
+ EXIT_ATTRIBUTES = tgetstr("me", &bp);
+
+ if (!ENTER_BOLD && ENTER_REVERSE)
+ ENTER_BOLD = ENTER_REVERSE;
+ if (!ENTER_BOLD && ENTER_STANDOUT)
+ ENTER_BOLD = ENTER_STANDOUT;
+ if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
+ ENTER_UNDERLINE = ENTER_STANDOUT;
+ EXIT_UNDERLINE = EXIT_STANDOUT;
+ }
+ if (!ENTER_DIM && ENTER_STANDOUT)
+ ENTER_DIM = ENTER_STANDOUT;
+ if (!ENTER_REVERSE && ENTER_STANDOUT)
+ ENTER_REVERSE = ENTER_STANDOUT;
+ if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
+ EXIT_ATTRIBUTES = EXIT_STANDOUT;
+
+ /*
+ * Note that we use REVERSE for the alternate character set,
+ * not the as/ae capabilities. This is because we are modelling
+ * the model 37 teletype (since that's what nroff outputs) and
+ * the typical as/ae is more of a graphics set, not the greek
+ * letters the 37 has.
+ */
+
+ UNDER_CHAR = tgetstr("uc", &bp);
+ must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
+}
+
+static int
+outchar(int c)
+{
+ return (putwchar(c) != WEOF ? c : EOF);
+}
+
+static int curmode = 0;
+
+static void
+outc(wint_t c, int width)
+{
+ int i;
+
+ putwchar(c);
+ if (must_use_uc && (curmode&UNDERL)) {
+ for (i = 0; i < width; i++)
+ PRINT(CURS_LEFT);
+ for (i = 0; i < width; i++)
+ PRINT(UNDER_CHAR);
+ }
+}
+
+static void
+setnewmode(int newmode)
+{
+ if (!iflag) {
+ if (curmode != NORMAL && newmode != NORMAL)
+ setnewmode(NORMAL);
+ switch (newmode) {
+ case NORMAL:
+ switch(curmode) {
+ case NORMAL:
+ break;
+ case UNDERL:
+ PRINT(EXIT_UNDERLINE);
+ break;
+ default:
+ /* This includes standout */
+ PRINT(EXIT_ATTRIBUTES);
+ break;
+ }
+ break;
+ case ALTSET:
+ PRINT(ENTER_REVERSE);
+ break;
+ case SUPERSC:
+ /*
+ * This only works on a few terminals.
+ * It should be fixed.
+ */
+ PRINT(ENTER_UNDERLINE);
+ PRINT(ENTER_DIM);
+ break;
+ case SUBSC:
+ PRINT(ENTER_DIM);
+ break;
+ case UNDERL:
+ PRINT(ENTER_UNDERLINE);
+ break;
+ case BOLD:
+ PRINT(ENTER_BOLD);
+ break;
+ default:
+ /*
+ * We should have some provision here for multiple modes
+ * on at once. This will have to come later.
+ */
+ PRINT(ENTER_STANDOUT);
+ break;
+ }
+ }
+ curmode = newmode;
+}
diff --git a/usr.bin/uname/Makefile b/usr.bin/uname/Makefile
new file mode 100644
index 000000000000..fdfce1ec1974
--- /dev/null
+++ b/usr.bin/uname/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= runtime
+PROG= uname
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/uname/Makefile.depend b/usr.bin/uname/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/uname/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/uname/uname.1 b/usr.bin/uname/uname.1
new file mode 100644
index 000000000000..1b55f60bbaa8
--- /dev/null
+++ b/usr.bin/uname/uname.1
@@ -0,0 +1,170 @@
+.\" Copyright (c) 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.
+.\"
+.Dd September 14, 2022
+.Dt UNAME 1
+.Os
+.Sh NAME
+.Nm uname
+.Nd display information about the system
+.Sh SYNOPSIS
+.Nm
+.Op Fl abiKmnoprsUv
+.Sh DESCRIPTION
+The
+.Nm
+command writes the name of the operating system implementation to
+standard output.
+When options are specified, strings representing one or more system
+characteristics are written to standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Behave as though the options
+.Fl m , n , r , s ,
+and
+.Fl v
+were specified.
+.It Fl b
+Write the kernel's linker-generated build-id to standard output.
+.It Fl i
+Write the kernel ident to standard output.
+.It Fl K
+Write the
+.Fx
+version of the kernel.
+.It Fl m
+Write the type of the current hardware platform to standard output.
+.Po Xr make 1
+uses it to set the
+.Va MACHINE
+variable.
+.Pc
+.It Fl n
+Write the name of the system to standard output.
+.It Fl o
+This is a synonym for the
+.Fl s
+option, for compatibility with other systems.
+.It Fl p
+Write the type of the machine processor architecture to standard output.
+.Po Xr make 1
+uses it to set the
+.Va MACHINE_ARCH
+variable.
+.Pc
+.It Fl r
+Write the current release level of the kernel
+to standard output.
+.Xr freebsd-version 1
+can be used to print the release level of the userland.
+.It Fl s
+Write the name of the operating system implementation to standard output.
+.It Fl U
+Write the
+.Fx
+version of the user environment.
+.It Fl v
+Write the version level of this release of the operating system
+to standard output.
+.El
+.Pp
+If the
+.Fl a
+flag is specified, or multiple flags are specified, all
+output is written on a single line, separated by spaces.
+.Pp
+The
+.Fl K
+and
+.Fl U
+flags are intended to be used for fine grain differentiation of incremental
+.Fx
+development and user visible changes.
+Note that when both of these two options are specified, regardless of their
+order, the kernel version would be printed first, followed by the user
+environment version.
+.Sh ENVIRONMENT
+An environment variable composed of the string
+.Ev UNAME_
+followed by any flag to the
+.Nm
+utility (except for
+.Fl a )
+will allow the corresponding data to be set to the contents
+of the environment variable.
+See
+.Xr uname 3
+for more information.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The hardware platform
+.Pq Fl m
+can be different from the machine's processor architecture
+.Pq Fl p ,
+e.g., on 64-bit PowerPC,
+.Fl m
+would return
+.Va powerpc
+and
+.Fl p
+would return
+.Va powerpc64 .
+.Sh SEE ALSO
+.Xr freebsd-version 1 ,
+.Xr feature_present 3 ,
+.Xr getosreldate 3 ,
+.Xr sysctl 3 ,
+.Xr uname 3 ,
+.Xr sysctl 8
+.Sh STANDARDS
+The
+.Nm
+command is expected to conform to the
+.St -p1003.2
+specification.
+.Sh HISTORY
+The
+.Nm
+command appeared in PWB UNIX 1.0, however
+.Bx 4.4
+was the first Berkeley release with the
+.Nm
+command.
+.Pp
+The
+.Fl K
+and
+.Fl U
+extension flags appeared in
+.Fx 10.0 .
+The
+.Fl b
+extension flag appeared in
+.Fx 13.0 .
diff --git a/usr.bin/uname/uname.c b/usr.bin/uname/uname.c
new file mode 100644
index 000000000000..131d4d25088e
--- /dev/null
+++ b/usr.bin/uname/uname.c
@@ -0,0 +1,288 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 2002 Juli Mallett.
+ * Copyright (c) 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <osreldate.h>
+
+#define MFLAG 0x01
+#define NFLAG 0x02
+#define PFLAG 0x04
+#define RFLAG 0x08
+#define SFLAG 0x10
+#define VFLAG 0x20
+#define IFLAG 0x40
+#define UFLAG 0x80
+#define KFLAG 0x100
+#define BFLAG 0x200
+
+typedef void (*get_t)(void);
+static get_t get_buildid, get_ident, get_platform, get_hostname, get_arch,
+ get_release, get_sysname, get_kernvers, get_uservers, get_version;
+
+static void native_ident(void);
+static void native_platform(void);
+static void native_hostname(void);
+static void native_arch(void);
+static void native_release(void);
+static void native_sysname(void);
+static void native_version(void);
+static void native_kernvers(void);
+static void native_uservers(void);
+static void native_buildid(void);
+static void print_uname(u_int);
+static void setup_get(void);
+static void usage(void) __dead2;
+
+static char *buildid, *ident, *platform, *hostname, *arch, *release, *sysname,
+ *version, *kernvers, *uservers;
+static int space;
+
+int
+main(int argc, char *argv[])
+{
+ u_int flags;
+ int ch;
+
+ setup_get();
+ flags = 0;
+
+ while ((ch = getopt(argc, argv, "abiKmnoprsUv")) != -1)
+ switch(ch) {
+ case 'a':
+ flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG);
+ break;
+ case 'b':
+ flags |= BFLAG;
+ break;
+ case 'i':
+ flags |= IFLAG;
+ break;
+ case 'K':
+ flags |= KFLAG;
+ break;
+ case 'm':
+ flags |= MFLAG;
+ break;
+ case 'n':
+ flags |= NFLAG;
+ break;
+ case 'p':
+ flags |= PFLAG;
+ break;
+ case 'r':
+ flags |= RFLAG;
+ break;
+ case 's':
+ case 'o':
+ flags |= SFLAG;
+ break;
+ case 'U':
+ flags |= UFLAG;
+ break;
+ case 'v':
+ flags |= VFLAG;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ usage();
+
+ if (!flags)
+ flags |= SFLAG;
+
+ print_uname(flags);
+ exit(0);
+}
+
+#define CHECK_ENV(opt,var) \
+do { \
+ if ((var = getenv("UNAME_" opt)) == NULL) { \
+ get_##var = native_##var; \
+ } else { \
+ get_##var = (get_t)NULL; \
+ } \
+} while (0)
+
+static void
+setup_get(void)
+{
+ CHECK_ENV("s", sysname);
+ CHECK_ENV("n", hostname);
+ CHECK_ENV("r", release);
+ CHECK_ENV("v", version);
+ CHECK_ENV("m", platform);
+ CHECK_ENV("p", arch);
+ CHECK_ENV("i", ident);
+ CHECK_ENV("K", kernvers);
+ CHECK_ENV("U", uservers);
+ CHECK_ENV("b", buildid);
+}
+
+#define PRINT_FLAG(flags,flag,var) \
+ if ((flags & flag) == flag) { \
+ if (space) \
+ printf(" "); \
+ else \
+ space++; \
+ if (get_##var != NULL) \
+ (*get_##var)(); \
+ printf("%s", var); \
+ }
+
+static void
+print_uname(u_int flags)
+{
+ PRINT_FLAG(flags, SFLAG, sysname);
+ PRINT_FLAG(flags, NFLAG, hostname);
+ PRINT_FLAG(flags, RFLAG, release);
+ PRINT_FLAG(flags, VFLAG, version);
+ PRINT_FLAG(flags, MFLAG, platform);
+ PRINT_FLAG(flags, PFLAG, arch);
+ PRINT_FLAG(flags, IFLAG, ident);
+ PRINT_FLAG(flags, KFLAG, kernvers);
+ PRINT_FLAG(flags, UFLAG, uservers);
+ PRINT_FLAG(flags, BFLAG, buildid);
+ printf("\n");
+}
+
+#define NATIVE_SYSCTL2_GET(var,mib0,mib1) \
+static void \
+native_##var(void) \
+{ \
+ int mib[] = { (mib0), (mib1) }; \
+ size_t len; \
+ static char buf[1024]; \
+ char **varp = &(var); \
+ \
+ len = sizeof buf; \
+ if (sysctl(mib, sizeof mib / sizeof mib[0], \
+ &buf, &len, NULL, 0) == -1) \
+ err(1, "sysctl");
+
+#define NATIVE_SYSCTLNAME_GET(var,name) \
+static void \
+native_##var(void) \
+{ \
+ size_t len; \
+ static char buf[1024]; \
+ char **varp = &(var); \
+ \
+ len = sizeof buf; \
+ if (sysctlbyname(name, &buf, &len, NULL,\
+ 0) == -1) \
+ err(1, "sysctlbyname");
+
+#define NATIVE_SET \
+ *varp = buf; \
+ return; \
+} struct __hack
+
+#define NATIVE_BUFFER (buf)
+#define NATIVE_LENGTH (len)
+
+NATIVE_SYSCTL2_GET(sysname, CTL_KERN, KERN_OSTYPE) {
+} NATIVE_SET;
+
+NATIVE_SYSCTL2_GET(hostname, CTL_KERN, KERN_HOSTNAME) {
+} NATIVE_SET;
+
+NATIVE_SYSCTL2_GET(release, CTL_KERN, KERN_OSRELEASE) {
+} NATIVE_SET;
+
+NATIVE_SYSCTL2_GET(version, CTL_KERN, KERN_VERSION) {
+ size_t n;
+ char *p;
+
+ p = NATIVE_BUFFER;
+ n = NATIVE_LENGTH;
+ for (; n--; ++p)
+ if (*p == '\n' || *p == '\t') {
+ if (n > 1)
+ *p = ' ';
+ else
+ *p = '\0';
+ }
+} NATIVE_SET;
+
+NATIVE_SYSCTL2_GET(platform, CTL_HW, HW_MACHINE) {
+} NATIVE_SET;
+
+NATIVE_SYSCTL2_GET(arch, CTL_HW, HW_MACHINE_ARCH) {
+} NATIVE_SET;
+
+NATIVE_SYSCTLNAME_GET(ident, "kern.ident") {
+} NATIVE_SET;
+
+NATIVE_SYSCTLNAME_GET(buildid, "kern.build_id") {
+} NATIVE_SET;
+
+static void
+native_uservers(void)
+{
+ static char buf[128];
+
+ snprintf(buf, sizeof(buf), "%d", __FreeBSD_version);
+ uservers = buf;
+}
+
+static void
+native_kernvers(void)
+{
+ static char buf[128];
+
+ snprintf(buf, sizeof(buf), "%d", getosreldate());
+ kernvers = buf;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: uname [-abiKmnoprsUv]\n");
+ exit(1);
+}
diff --git a/usr.bin/unexpand/Makefile b/usr.bin/unexpand/Makefile
new file mode 100644
index 000000000000..ef5cf30459b2
--- /dev/null
+++ b/usr.bin/unexpand/Makefile
@@ -0,0 +1,4 @@
+PROG= unexpand
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/unexpand/Makefile.depend b/usr.bin/unexpand/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/unexpand/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unexpand/unexpand.c b/usr.bin/unexpand/unexpand.c
new file mode 100644
index 000000000000..cab933cd9d13
--- /dev/null
+++ b/usr.bin/unexpand/unexpand.c
@@ -0,0 +1,215 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+/*
+ * unexpand - put tabs into a file replacing blanks
+ */
+#include <ctype.h>
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+static int all;
+static int nstops;
+static int tabstops[100];
+
+static void getstops(const char *);
+static void usage(void) __dead2;
+static int tabify(const char *);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, failed;
+ char *filename;
+
+ setlocale(LC_CTYPE, "");
+
+ nstops = 1;
+ tabstops[0] = 8;
+ while ((ch = getopt(argc, argv, "at:")) != -1) {
+ switch (ch) {
+ case 'a': /* Un-expand all spaces, not just leading. */
+ all = 1;
+ break;
+ case 't': /* Specify tab list, implies -a. */
+ getstops(optarg);
+ all = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ failed = 0;
+ if (argc == 0)
+ failed |= tabify("stdin");
+ else {
+ while ((filename = *argv++) != NULL) {
+ if (freopen(filename, "r", stdin) == NULL) {
+ warn("%s", filename);
+ failed = 1;
+ } else
+ failed |= tabify(filename);
+ }
+ }
+ exit(failed != 0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: unexpand [-a | -t tablist] [file ...]\n");
+ exit(1);
+}
+
+static int
+tabify(const char *curfile)
+{
+ int dcol, doneline, limit, n, ocol, width;
+ wint_t ch;
+
+ limit = nstops == 1 ? INT_MAX : tabstops[nstops - 1] - 1;
+
+ doneline = ocol = dcol = 0;
+ while ((ch = getwchar()) != WEOF) {
+ if (ch == ' ' && !doneline) {
+ if (++dcol >= limit)
+ doneline = 1;
+ continue;
+ } else if (ch == '\t') {
+ if (nstops == 1) {
+ dcol = (1 + dcol / tabstops[0]) *
+ tabstops[0];
+ continue;
+ } else {
+ for (n = 0; n < nstops &&
+ tabstops[n] - 1 < dcol; n++)
+ ;
+ if (n < nstops - 1 && tabstops[n] - 1 < limit) {
+ dcol = tabstops[n];
+ continue;
+ }
+ doneline = 1;
+ }
+ }
+
+ /* Output maximal number of tabs. */
+ if (nstops == 1) {
+ while (((ocol + tabstops[0]) / tabstops[0])
+ <= (dcol / tabstops[0])) {
+ if (dcol - ocol < 2)
+ break;
+ putwchar('\t');
+ ocol = (1 + ocol / tabstops[0]) *
+ tabstops[0];
+ }
+ } else {
+ for (n = 0; n < nstops && tabstops[n] - 1 < ocol; n++)
+ ;
+ while (ocol < dcol && n < nstops && ocol < limit) {
+ putwchar('\t');
+ ocol = tabstops[n++];
+ }
+ }
+
+ /* Then spaces. */
+ while (ocol < dcol && ocol < limit) {
+ putwchar(' ');
+ ocol++;
+ }
+
+ if (ch == '\b') {
+ putwchar('\b');
+ if (ocol > 0)
+ ocol--, dcol--;
+ } else if (ch == '\n') {
+ putwchar('\n');
+ doneline = ocol = dcol = 0;
+ continue;
+ } else if (ch != ' ' || dcol > limit) {
+ putwchar(ch);
+ if ((width = wcwidth(ch)) > 0)
+ ocol += width, dcol += width;
+ }
+
+ /*
+ * Only processing leading blanks or we've gone past the
+ * last tab stop. Emit remainder of this line unchanged.
+ */
+ if (!all || dcol >= limit) {
+ while ((ch = getwchar()) != '\n' && ch != WEOF)
+ putwchar(ch);
+ if (ch == '\n')
+ putwchar('\n');
+ doneline = ocol = dcol = 0;
+ }
+ }
+ if (ferror(stdin)) {
+ warn("%s", curfile);
+ return (1);
+ }
+ return (0);
+}
+
+static void
+getstops(const char *cp)
+{
+ int i;
+
+ nstops = 0;
+ for (;;) {
+ i = 0;
+ while (*cp >= '0' && *cp <= '9')
+ i = i * 10 + *cp++ - '0';
+ if (i <= 0)
+ errx(1, "bad tab stop spec");
+ if (nstops > 0 && i <= tabstops[nstops-1])
+ errx(1, "bad tab stop spec");
+ if (nstops == sizeof(tabstops) / sizeof(*tabstops))
+ errx(1, "too many tab stops");
+ tabstops[nstops++] = i;
+ if (*cp == 0)
+ break;
+ if (*cp != ',' && !isblank((unsigned char)*cp))
+ errx(1, "bad tab stop spec");
+ cp++;
+ }
+}
diff --git a/usr.bin/unifdef/Makefile b/usr.bin/unifdef/Makefile
new file mode 100644
index 000000000000..82b0c5839f8e
--- /dev/null
+++ b/usr.bin/unifdef/Makefile
@@ -0,0 +1,12 @@
+.PATH: ${SRCTOP}/contrib/unifdef
+
+PROG= unifdef
+SCRIPTS=unifdefall.sh
+MLINKS= unifdef.1 unifdefall.1
+
+.include <src.opts.mk>
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/unifdef/Makefile.depend b/usr.bin/unifdef/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/unifdef/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unifdef/tests/Makefile b/usr.bin/unifdef/tests/Makefile
new file mode 100644
index 000000000000..67e98fa70480
--- /dev/null
+++ b/usr.bin/unifdef/tests/Makefile
@@ -0,0 +1,11 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= unifdef_test
+NETBSD_ATF_TESTS_SH= basic_test
+
+${PACKAGE}FILES+= d_basic.in
+${PACKAGE}FILES+= d_basic.out
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/unifdef/tests/Makefile.depend b/usr.bin/unifdef/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/unifdef/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unifdef/tests/unifdef_test.sh b/usr.bin/unifdef/tests/unifdef_test.sh
new file mode 100644
index 000000000000..7af782e8c9e2
--- /dev/null
+++ b/usr.bin/unifdef/tests/unifdef_test.sh
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+atf_test_case hash_comment
+hash_comment_head() {
+ atf_set descr "multiline comment follows directive"
+}
+hash_comment_body() {
+ cat >f <<EOF
+#if FOO
+a
+#endif /*
+*/
+EOF
+ atf_check -o file:f unifdef <f
+}
+
+atf_test_case redefine
+redefine_head() {
+ atf_set descr "redefine the same symbol"
+}
+redefine_body() {
+ cat >file <<EOF
+#if FOO
+a
+#else
+b
+#endif
+EOF
+ atf_check -s exit:1 -o inline:"a\n" unifdef -DFOO <file
+ atf_check -s exit:1 -o inline:"a\n" unifdef -UFOO -DFOO <file
+ atf_check -s exit:1 -o inline:"a\n" unifdef -DFOO=0 -DFOO <file
+ atf_check -s exit:1 -o inline:"b\n" unifdef -UFOO <file
+ atf_check -s exit:1 -o inline:"b\n" unifdef -DFOO -UFOO <file
+ atf_check -s exit:1 -o inline:"b\n" unifdef -DFOO -DFOO=0 <file
+}
+
+atf_test_case sDU
+sDU_head() {
+ atf_set descr "simultaneous use of -s and -D or -U"
+}
+sDU_body() {
+ atf_check unifdef -s -DFOO -UFOO /dev/null
+ atf_check unifdef -s -DFOO -DBAR=FOO /dev/null
+}
+
+atf_init_test_cases() {
+ atf_add_test_case hash_comment
+ atf_add_test_case redefine
+ atf_add_test_case sDU
+}
diff --git a/usr.bin/uniq/Makefile b/usr.bin/uniq/Makefile
new file mode 100644
index 000000000000..0d4d89fdaa6b
--- /dev/null
+++ b/usr.bin/uniq/Makefile
@@ -0,0 +1,8 @@
+.include <src.opts.mk>
+
+PROG= uniq
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/uniq/Makefile.depend b/usr.bin/uniq/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/uniq/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/uniq/tests/Makefile b/usr.bin/uniq/tests/Makefile
new file mode 100644
index 000000000000..55bb98e98c34
--- /dev/null
+++ b/usr.bin/uniq/tests/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= tests
+ATF_TESTS_SH= uniq_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/uniq/tests/Makefile.depend b/usr.bin/uniq/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/uniq/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/uniq/tests/uniq_test.sh b/usr.bin/uniq/tests/uniq_test.sh
new file mode 100755
index 000000000000..fc143632bdd2
--- /dev/null
+++ b/usr.bin/uniq/tests/uniq_test.sh
@@ -0,0 +1,228 @@
+#
+# Copyright (c) 2024 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+atf_check_uniq() {
+ atf_check uniq "$@" input actual
+ atf_check diff -u actual expected
+ atf_check uniq "$@" - actual <input
+ atf_check diff -u actual expected
+ atf_check -o file:expected uniq "$@" input
+ atf_check -o file:expected uniq "$@" <input
+ atf_check -o file:expected uniq "$@" - <input
+}
+
+atf_test_case basic
+basic_head() {
+ atf_set descr "basic test without options"
+}
+basic_body() {
+ printf "a\na\nb\nb\na\na\n" >input
+ printf "a\nb\na\n" >expected
+ atf_check_uniq
+}
+
+atf_test_case count
+count_head() {
+ atf_set descr "basic test showing counts"
+}
+count_body() {
+ printf "a\na\nb\nb\nb\na\na\na\na\n" >input
+ printf " 2 a\n 3 b\n 4 a\n" >expected
+ atf_check_uniq -c
+ atf_check_uniq --count
+}
+
+atf_test_case repeated
+repeated_head() {
+ atf_set descr "print repeated lines only"
+}
+repeated_body() {
+ printf "a\na\nb\na\na\n" >input
+ printf "a\na\n" >expected
+ atf_check_uniq -d
+ atf_check_uniq --repeated
+}
+
+atf_test_case count_repeated
+count_repeated_head() {
+ atf_set descr "count and print repeated lines only"
+}
+count_repeated_body() {
+ printf "a\na\nb\nb\na\n" >input
+ printf " 2 a\n 2 b\n" >expected
+ atf_check_uniq -cd
+ atf_check_uniq -c -d
+ atf_check_uniq -dc
+ atf_check_uniq -d -c
+ atf_check_uniq --count --repeated
+ atf_check_uniq --repeated --count
+}
+
+atf_test_case all_repeated
+all_repeated_head() {
+ atf_set descr "print every instance of repeated lines"
+}
+all_repeated_body() {
+ printf "a\na\nb\na\na\n" >input
+ printf "a\na\na\na\n" >expected
+ atf_check_uniq -D
+ atf_check_uniq -Dnone
+ atf_check_uniq --all-repeated
+ atf_check_uniq --all-repeated=none
+ printf "\na\na\n\na\na\n" >expected
+ atf_check_uniq -Dprepend
+ atf_check_uniq --all-repeated=prepend
+ printf "a\na\n\na\na\n" >expected
+ atf_check_uniq -Dseparate
+ atf_check_uniq --all-repeated=separate
+}
+
+atf_test_case count_all_repeated
+count_all_repeated_head() {
+ atf_set descr "count and print every instance of repeated lines"
+}
+count_all_repeated_body() {
+ printf "a\na\nb\na\na\n" >input
+ printf " 1 a\n 2 a\n 1 a\n 2 a\n" >expected
+ atf_check_uniq -D -c
+ atf_check_uniq -Dnone -c
+ atf_check_uniq -cD
+ atf_check_uniq -cDnone
+ atf_check_uniq -c -D
+ atf_check_uniq -c -Dnone
+ atf_check_uniq --all-repeated --count
+ atf_check_uniq --all-repeated=none --count
+ atf_check_uniq --count --all-repeated
+ atf_check_uniq --count --all-repeated=none
+}
+
+atf_test_case skip_fields
+skip_fields_head() {
+ atf_set descr "skip fields"
+}
+skip_fields_body() {
+ printf "1 a\n2 a\n3 b\n4 b\n5 a\n6 a\n" >input
+ printf "1 a\n3 b\n5 a\n" >expected
+ atf_check_uniq -1
+ atf_check_uniq -f 1
+ atf_check_uniq --skip-fields 1
+}
+
+atf_test_case skip_fields_tab
+skip_fields_tab_head() {
+ atf_set descr "skip fields (with tabs)"
+}
+skip_fields_tab_body() {
+ printf "1\ta\n2\ta\n3\tb\n4\tb\n5\ta\n6\ta\n" >input
+ printf "1\ta\n3\tb\n5\ta\n" >expected
+ atf_check_uniq -1
+ atf_check_uniq -f 1
+ atf_check_uniq --skip-fields 1
+}
+
+atf_test_case ignore_case
+ignore_case_head() {
+ atf_set descr "ignore case"
+}
+ignore_case_body() {
+ printf "a\nA\nb\nB\na\nA\n" >input
+ printf "a\nb\na\n" >expected
+ atf_check_uniq -i
+ atf_check_uniq --ignore-case
+}
+
+atf_test_case skip_chars
+skip_chars_head() {
+ atf_set descr "skip chars"
+}
+skip_chars_body() {
+ printf "1 a\n2 a\n3 b\n4 b\n5 a\n6 a\n" >input
+ printf "1 a\n3 b\n5 a\n" >expected
+ atf_check_uniq +2
+ atf_check_uniq -s 2
+ atf_check_uniq --skip-chars 2
+}
+
+atf_test_case unique
+unique_head() {
+ atf_set descr "print non-repeated lines only"
+}
+unique_body() {
+ printf "a\na\nb\na\na\n" >input
+ printf "b\n" >expected
+ atf_check_uniq -u
+ atf_check_uniq --unique
+}
+
+atf_test_case count_unique
+count_unique_head() {
+ atf_set descr "print non-repeated lines with count"
+}
+count_unique_body() {
+ printf "a\na\nb\n" >input
+ printf " 1 b\n" >expected
+ atf_check_uniq --unique --count
+ atf_check_uniq --count --unique
+}
+
+atf_test_case interactive
+interactive_head() {
+ atf_set descr "test interactive use"
+}
+interactive_body() {
+ sh -c 'yes | stdbuf -oL uniq >actual' &
+ pid=$!
+ sleep 1
+ kill $!
+ atf_check -o inline:"y\n" cat actual
+}
+
+atf_test_case interactive_repeated
+interactive_repeated_head() {
+ atf_set descr "test interactive use with -d"
+}
+interactive_repeated_body() {
+ sh -c 'yes | stdbuf -oL uniq -d >actual' &
+ pid=$!
+ sleep 1
+ kill $!
+ atf_check -o inline:"y\n" cat actual
+}
+
+atf_test_case stdout
+stdout_head() {
+ atf_set descr "error writing to stdout"
+}
+stdout_body() {
+ (
+ trap "" PIPE
+ # Give true(1) some time to exit.
+ sleep 1
+ echo a | uniq 2>stderr
+ echo $? >result
+ ) | true
+ atf_check -o inline:"1\n" cat result
+ atf_check -o match:"stdout" cat stderr
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case count
+ atf_add_test_case repeated
+ atf_add_test_case count_repeated
+ atf_add_test_case all_repeated
+ atf_add_test_case count_all_repeated
+ atf_add_test_case skip_fields
+ atf_add_test_case skip_fields_tab
+ atf_add_test_case ignore_case
+ atf_add_test_case skip_chars
+ atf_add_test_case unique
+ atf_add_test_case count_unique
+ atf_add_test_case interactive
+ atf_add_test_case interactive_repeated
+ atf_add_test_case stdout
+}
diff --git a/usr.bin/uniq/uniq.1 b/usr.bin/uniq/uniq.1
new file mode 100644
index 000000000000..0918420e2229
--- /dev/null
+++ b/usr.bin/uniq/uniq.1
@@ -0,0 +1,218 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd December 9, 2024
+.Dt UNIQ 1
+.Os
+.Sh NAME
+.Nm uniq
+.Nd report or filter out repeated lines in a file
+.Sh SYNOPSIS
+.Nm
+.Op Fl cdiu
+.Op Fl D Ns Op Ar septype
+.Op Fl f Ar num
+.Op Fl s Ar chars
+.Oo
+.Ar input_file
+.Op Ar output_file
+.Oc
+.Sh DESCRIPTION
+The
+.Nm
+utility reads the specified
+.Ar input_file
+comparing adjacent lines, and writes a copy of each unique input line to
+the
+.Ar output_file .
+If
+.Ar input_file
+is a single dash
+.Pq Sq Fl
+or absent, the standard input is read.
+If
+.Ar output_file
+is absent, standard output is used for output.
+The second and succeeding copies of identical adjacent input lines are
+not written.
+Repeated lines in the input will not be detected if they are not adjacent,
+so it may be necessary to sort the files first.
+.Pp
+The following options are available:
+.Bl -tag -width Ds
+.It Fl c , Fl -count
+Precede each output line with the count of the number of times the line
+occurred in the input, followed by a single space.
+.It Fl d , Fl -repeated
+Output a single copy of each line that is repeated in the input.
+Ignored if
+.Fl D
+is also specified.
+.It Fl D , Fl -all-repeated Op Ar septype
+Output all lines that are repeated (like
+.Fl d ,
+but each copy of the repeated line is written).
+The optional
+.Ar septype
+argument controls how to separate groups of repeated lines in the output;
+it must be one of the following values:
+.Pp
+.Bl -tag -compact -width separate
+.It none
+Do not separate groups of lines (this is the default).
+.It prepend
+Output an empty line before each group of lines.
+.It separate
+Output an empty line after each group of lines.
+.El
+.It Fl f Ar num , Fl -skip-fields Ar num
+Ignore the first
+.Ar num
+fields in each input line when doing comparisons.
+A field is a string of non-blank characters separated from adjacent fields
+by blanks.
+Field numbers are one based, i.e., the first field is field one.
+.It Fl i , Fl -ignore-case
+Case insensitive comparison of lines.
+.It Fl s Ar chars , Fl -skip-chars Ar chars
+Ignore the first
+.Ar chars
+characters in each input line when doing comparisons.
+If specified in conjunction with the
+.Fl f , Fl -unique
+option, the first
+.Ar chars
+characters after the first
+.Ar num
+fields will be ignored.
+Character numbers are one based, i.e., the first character is character one.
+.It Fl u , Fl -unique
+Only output lines that are not repeated in the input.
+.\".It Fl Ns Ar n
+.\"(Deprecated; replaced by
+.\".Fl f ) .
+.\"Ignore the first n
+.\"fields on each input line when doing comparisons,
+.\"where n is a number.
+.\"A field is a string of non-blank
+.\"characters separated from adjacent fields
+.\"by blanks.
+.\".It Cm \&\(pl Ns Ar n
+.\"(Deprecated; replaced by
+.\".Fl s ) .
+.\"Ignore the first
+.\".Ar m
+.\"characters when doing comparisons, where
+.\".Ar m
+.\"is a
+.\"number.
+.El
+.Sh ENVIRONMENT
+The
+.Ev LANG ,
+.Ev LC_ALL ,
+.Ev LC_COLLATE
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Assuming a file named cities.txt with the following content:
+.Bd -literal -offset indent
+Madrid
+Lisbon
+Madrid
+.Ed
+.Pp
+The following command reports three different lines since identical elements
+are not adjacent:
+.Bd -literal -offset indent
+$ uniq -u cities.txt
+Madrid
+Lisbon
+Madrid
+.Ed
+.Pp
+Sort the file and count the number of identical lines:
+.Bd -literal -offset indent
+$ sort cities.txt | uniq -c
+ 1 Lisbon
+ 2 Madrid
+.Ed
+.Pp
+Assuming the following content for the file cities.txt:
+.Bd -literal -offset indent
+madrid
+Madrid
+Lisbon
+.Ed
+.Pp
+Show repeated lines ignoring case sensitiveness:
+.Bd -literal -offset indent
+$ uniq -d -i cities.txt
+madrid
+.Ed
+.Pp
+Same as above but showing the whole group of repeated lines:
+.Bd -literal -offset indent
+$ uniq -D -i cities.txt
+madrid
+Madrid
+.Ed
+.Pp
+Report the number of identical lines ignoring the first character of every line:
+.Bd -literal -offset indent
+$ uniq -s 1 -c cities.txt
+ 2 madrid
+ 1 Lisbon
+.Ed
+.Sh COMPATIBILITY
+The historic
+.Cm \&\(pl Ns Ar number
+and
+.Fl Ns Ar number
+options have been deprecated but are still supported in this implementation.
+.Sh SEE ALSO
+.Xr sort 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001
+as amended by Cor.\& 1-2002.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v3 .
diff --git a/usr.bin/uniq/uniq.c b/usr.bin/uniq/uniq.c
new file mode 100644
index 000000000000..0650ec2e2137
--- /dev/null
+++ b/usr.bin/uniq/uniq.c
@@ -0,0 +1,373 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Case Larsen.
+ *
+ * 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/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <locale.h>
+#include <nl_types.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+
+static enum { DF_NONE, DF_NOSEP, DF_PRESEP, DF_POSTSEP } Dflag;
+static bool cflag, dflag, uflag, iflag;
+static long long numchars, numfields, repeats;
+
+static const struct option long_opts[] =
+{
+ {"all-repeated",optional_argument, NULL, 'D'},
+ {"count", no_argument, NULL, 'c'},
+ {"repeated", no_argument, NULL, 'd'},
+ {"skip-fields", required_argument, NULL, 'f'},
+ {"ignore-case", no_argument, NULL, 'i'},
+ {"skip-chars", required_argument, NULL, 's'},
+ {"unique", no_argument, NULL, 'u'},
+ {NULL, no_argument, NULL, 0}
+};
+
+static FILE *file(const char *, const char *);
+static wchar_t *convert(const char *);
+static int inlcmp(const char *, const char *);
+static void show(FILE *, const char *);
+static wchar_t *skip(wchar_t *);
+static void obsolete(char *[]);
+static void usage(void);
+
+int
+main (int argc, char *argv[])
+{
+ wchar_t *tprev, *tthis;
+ FILE *ifp, *ofp;
+ int ch, comp;
+ size_t prevbuflen, thisbuflen, b1;
+ char *prevline, *thisline, *p;
+ const char *errstr, *ifn, *ofn;
+ cap_rights_t rights;
+
+ (void) setlocale(LC_ALL, "");
+
+ obsolete(argv);
+ while ((ch = getopt_long(argc, argv, "+D::cdif:s:u", long_opts,
+ NULL)) != -1)
+ switch (ch) {
+ case 'D':
+ if (optarg == NULL || strcasecmp(optarg, "none") == 0)
+ Dflag = DF_NOSEP;
+ else if (strcasecmp(optarg, "prepend") == 0)
+ Dflag = DF_PRESEP;
+ else if (strcasecmp(optarg, "separate") == 0)
+ Dflag = DF_POSTSEP;
+ else
+ usage();
+ break;
+ case 'c':
+ cflag = true;
+ break;
+ case 'd':
+ dflag = true;
+ break;
+ case 'i':
+ iflag = true;
+ break;
+ case 'f':
+ numfields = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "field skip value is %s: %s", errstr, optarg);
+ break;
+ case 's':
+ numchars = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "character skip value is %s: %s", errstr, optarg);
+ break;
+ case 'u':
+ uflag = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 2)
+ usage();
+
+ if (Dflag && dflag)
+ dflag = false;
+
+ ifp = stdin;
+ ifn = "stdin";
+ ofp = stdout;
+ ofn = "stdout";
+ if (argc > 0 && strcmp(argv[0], "-") != 0)
+ ifp = file(ifn = argv[0], "r");
+ cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
+ if (caph_rights_limit(fileno(ifp), &rights) < 0)
+ err(1, "unable to limit rights for %s", ifn);
+ cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
+ if (argc > 1)
+ ofp = file(ofn = argv[1], "w");
+ else
+ cap_rights_set(&rights, CAP_IOCTL);
+ if (caph_rights_limit(fileno(ofp), &rights) < 0) {
+ err(1, "unable to limit rights for %s",
+ argc > 1 ? argv[1] : "stdout");
+ }
+ if (cap_rights_is_set(&rights, CAP_IOCTL)) {
+ unsigned long cmd;
+
+ cmd = TIOCGETA; /* required by isatty(3) in printf(3) */
+
+ if (caph_ioctls_limit(fileno(ofp), &cmd, 1) < 0) {
+ err(1, "unable to limit ioctls for %s",
+ argc > 1 ? argv[1] : "stdout");
+ }
+ }
+
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ prevbuflen = thisbuflen = 0;
+ prevline = thisline = NULL;
+
+ if (getline(&prevline, &prevbuflen, ifp) < 0) {
+ if (ferror(ifp))
+ err(1, "%s", ifn);
+ exit(0);
+ }
+ if (!cflag && !Dflag && !dflag && !uflag)
+ show(ofp, prevline);
+ tprev = convert(prevline);
+
+ tthis = NULL;
+ while (getline(&thisline, &thisbuflen, ifp) >= 0) {
+ if (tthis != NULL)
+ free(tthis);
+ tthis = convert(thisline);
+
+ if (tthis == NULL && tprev == NULL)
+ comp = inlcmp(thisline, prevline);
+ else if (tthis == NULL || tprev == NULL)
+ comp = 1;
+ else
+ comp = wcscoll(tthis, tprev);
+
+ if (comp) {
+ /* If different, print; set previous to new value. */
+ if (Dflag == DF_POSTSEP && repeats > 0)
+ fputc('\n', ofp);
+ if (!cflag && !Dflag && !dflag && !uflag)
+ show(ofp, thisline);
+ else if (!Dflag &&
+ (!dflag || (cflag && repeats > 0)) &&
+ (!uflag || repeats == 0))
+ show(ofp, prevline);
+ p = prevline;
+ b1 = prevbuflen;
+ prevline = thisline;
+ prevbuflen = thisbuflen;
+ if (tprev != NULL)
+ free(tprev);
+ tprev = tthis;
+ thisline = p;
+ thisbuflen = b1;
+ tthis = NULL;
+ repeats = 0;
+ } else {
+ if (Dflag) {
+ if (repeats == 0) {
+ if (Dflag == DF_PRESEP)
+ fputc('\n', ofp);
+ show(ofp, prevline);
+ }
+ } else if (dflag && !cflag) {
+ if (repeats == 0)
+ show(ofp, prevline);
+ }
+ ++repeats;
+ if (Dflag)
+ show(ofp, thisline);
+ }
+ }
+ if (ferror(ifp))
+ err(1, "%s", ifn);
+ if (!cflag && !Dflag && !dflag && !uflag)
+ /* already printed */ ;
+ else if (!Dflag &&
+ (!dflag || (cflag && repeats > 0)) &&
+ (!uflag || repeats == 0))
+ show(ofp, prevline);
+ if (fflush(ofp) != 0)
+ err(1, "%s", ofn);
+ exit(0);
+}
+
+static wchar_t *
+convert(const char *str)
+{
+ size_t n;
+ wchar_t *buf, *ret, *p;
+
+ if ((n = mbstowcs(NULL, str, 0)) == (size_t)-1)
+ return (NULL);
+ if (SIZE_MAX / sizeof(*buf) < n + 1)
+ errx(1, "conversion buffer length overflow");
+ if ((buf = malloc((n + 1) * sizeof(*buf))) == NULL)
+ err(1, "malloc");
+ if (mbstowcs(buf, str, n + 1) != n)
+ errx(1, "internal mbstowcs() error");
+ /* The last line may not end with \n. */
+ if (n > 0 && buf[n - 1] == L'\n')
+ buf[n - 1] = L'\0';
+
+ /* If requested get the chosen fields + character offsets. */
+ if (numfields || numchars) {
+ if ((ret = wcsdup(skip(buf))) == NULL)
+ err(1, "wcsdup");
+ free(buf);
+ } else
+ ret = buf;
+
+ if (iflag) {
+ for (p = ret; *p != L'\0'; p++)
+ *p = towlower(*p);
+ }
+
+ return (ret);
+}
+
+static int
+inlcmp(const char *s1, const char *s2)
+{
+ int c1, c2;
+
+ while (*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+ c1 = (unsigned char)*s1;
+ c2 = (unsigned char)*(s2 - 1);
+ /* The last line may not end with \n. */
+ if (c1 == '\n')
+ c1 = '\0';
+ if (c2 == '\n')
+ c2 = '\0';
+ return (c1 - c2);
+}
+
+/*
+ * show --
+ * Output a line depending on the flags and number of repetitions
+ * of the line.
+ */
+static void
+show(FILE *ofp, const char *str)
+{
+ if (cflag)
+ (void)fprintf(ofp, "%4lld %s", repeats + 1, str);
+ else
+ (void)fprintf(ofp, "%s", str);
+}
+
+static wchar_t *
+skip(wchar_t *str)
+{
+ long long nchars, nfields;
+
+ for (nfields = 0; *str != L'\0' && nfields++ != numfields; ) {
+ while (iswblank(*str))
+ str++;
+ while (*str != L'\0' && !iswblank(*str))
+ str++;
+ }
+ for (nchars = numchars; nchars-- && *str != L'\0'; ++str)
+ ;
+ return(str);
+}
+
+static FILE *
+file(const char *name, const char *mode)
+{
+ FILE *fp;
+
+ if ((fp = fopen(name, mode)) == NULL)
+ err(1, "%s", name);
+ return(fp);
+}
+
+static void
+obsolete(char *argv[])
+{
+ char *ap, *p;
+
+ while ((ap = *++argv)) {
+ /* Return if "--" or not an option of any form. */
+ if (ap[0] != '-') {
+ if (ap[0] != '+')
+ return;
+ } else if (ap[1] == '-') {
+ return;
+ }
+ if (!isdigit((unsigned char)ap[1]))
+ continue;
+ /*
+ * Digit signifies an old-style option. Malloc space for dash,
+ * new option and argument.
+ */
+ if (asprintf(&p, "-%c%s", ap[0] == '+' ? 's' : 'f', ap + 1) < 0)
+ err(1, "malloc");
+ *argv = p;
+ }
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: uniq [-cdiu] [-D[septype]] "
+ "[-f fields] [-s chars] [input [output]]\n");
+ exit(1);
+}
diff --git a/usr.bin/units/Makefile b/usr.bin/units/Makefile
new file mode 100644
index 000000000000..0f24f0a25f64
--- /dev/null
+++ b/usr.bin/units/Makefile
@@ -0,0 +1,12 @@
+.include <src.opts.mk>
+
+PROG= units
+FILES= definitions.units
+FILESDIR= ${SHAREDIR}/misc
+
+LIBADD= edit
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/units/Makefile.depend b/usr.bin/units/Makefile.depend
new file mode 100644
index 000000000000..694d078d7fad
--- /dev/null
+++ b/usr.bin/units/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libedit \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/units/README b/usr.bin/units/README
new file mode 100644
index 000000000000..7422b73c913f
--- /dev/null
+++ b/usr.bin/units/README
@@ -0,0 +1,17 @@
+
+This is a program which I wrote as a clone of the UNIX 'units'
+command. I threw it together in a couple days, but it seems to work,
+with some restrictions. I have tested it under DOS with Borland C and
+Ultrix 4.2, and SunOS 4.1.
+
+This program differs from the unix units program in the following
+ways:
+ it can gracefully handle exponents larger than 9 in output
+ it uses 'e' to denote exponentiation in numbers
+ prefixes are listed in the units file
+ it tries both -s and -es plurals
+ it allows use of * for multiply and ^ for exponentiation in the input
+ the output format is somewhat different
+
+Adrian Mariano (adrian@cam.cornell.edu or mariano@geom.umn.edu)
+
diff --git a/usr.bin/units/definitions.units b/usr.bin/units/definitions.units
new file mode 100644
index 000000000000..99d2f050e891
--- /dev/null
+++ b/usr.bin/units/definitions.units
@@ -0,0 +1,907 @@
+
+# primitive units
+
+m !a!
+kg !b!
+sec !c!
+coul !d!
+candela !e!
+usdollar !f!
+euro !g!
+bit !h!
+erlang !i!
+K !j!
+
+# prefixes
+
+yotta- 1e24
+zetta- 1e21
+exa- 1e18
+peta- 1e15
+tera- 1e12
+giga- 1e9
+mega- 1e6
+myria- 1e4
+kilo- 1e3
+hecto- 1e2
+deka- 1e1
+deca- deka
+deci- 1e-1
+centi- 1e-2
+milli- 1e-3
+micro- 1e-6
+nano- 1e-9
+pico- 1e-12
+femto- 1e-15
+atto- 1e-18
+zopto- 1e-21
+zepto- zopto
+yocto- 1e-24
+
+quarter- 1|4
+semi- .5
+demi- .5
+hemi- .5
+half- .5
+double- 2
+triple- 3
+
+Y- yotta
+Z- zetta
+E- exa
+P- peta
+T- tera
+G- giga
+M- mega
+k- kilo
+h- hecto
+da- deka
+d- deci
+c- centi
+m- milli
+u- micro
+n- nano
+p- pico
+f- femto
+a- atto
+z- zopto
+y- yocto
+
+# binary prefixes introduced in 1999
+exbi- 1152921504606846976
+pebi- 1125899906842624
+tebi- 1099511627776
+gibi- 1073741824
+mebi- 1048576
+kibi- 1024
+
+Ei- exbi
+Pi- pebi
+Ti- tebi
+Gi- gibi
+Mi- mebi
+Ki- kibi
+
+# constants
+
+fuzz 1
+pi 3.14159265358979323846
+c 2.99792458e+8 m/sec
+g0 9.80665 m/sec2
+g g0
+bigG 6.67428e-11 m3/kg/s2
+AU 1.49597870691e+11 m fuzz
+au AU
+mole 6.0221417930e+23 fuzz
+e 1.6021917e-19 coul fuzz
+energy c2
+force g
+mercury 1.3332239e+5 kg/m2-sec2
+hg mercury
+mmHg 0.001 m hg
+#mu 4.e-7 pi-N/A2
+epsilon 1.0 /mu/c2
+alpha 0.5 mu-c-e2/planck
+planck 6.6260755e-34 joule-sec
+hbar 0.5 planck/pi
+electronmass 9.1093821545-31 kg
+protonmass 1.6726217129-27 kg
+neutronmass 1.6749272928-27 kg
+
+# dimensionless
+
+radian .5 / pi
+degree 1|180 pi-radian
+circle 2 pi-radian
+turn 2 pi-radian
+revolution turn
+rev turn
+grade .9 degree
+arcdeg 1 degree
+arcmin 1|60 arcdeg
+ccs 1|36 erlang
+arcsec 1|60 arcmin
+
+steradian radian2
+sphere 4 pi-steradian
+sr steradian
+
+# Time
+
+second sec
+s sec
+minute 60 sec
+min minute
+hour 60 min
+hr hour
+day 24 hr
+da day
+week 7 day
+year 365.24219879 day fuzz
+yr year
+month 1|12 year
+us microsec
+
+# Mass
+
+gram millikg
+gm gram
+metricton kilokg
+
+# Avoirdupois
+
+lb .45359237 kg
+pound lb
+lbf lb g
+ounce 1|16 lb
+oz ounce
+dram 1|16 oz
+dr dram
+grain 1|7000 lb
+gr grain
+shortton 2000 lb
+ton shortton
+longton 2240 lb
+
+# Apothecary
+
+scruple 20 grain
+apdram 60 grain
+apounce 480 grain
+appound 5760 grain
+troypound appound
+
+# Mining
+
+troyounce apounce
+troz apounce
+pennyweight 1|20 troz
+pwt pennyweight
+dwt pennyweight
+
+# Length
+
+meter m
+micron micrometer
+angstrom decinanometer
+ao 0.25 alpha/pi/rydbergconst
+
+inch 2.54 cm
+in inch
+foot 12 in
+feet foot
+ft foot
+yard 3 ft
+yd yard
+rod 5.5 yd
+rd rod
+mile 5280 ft
+mi mile
+
+british 1200|3937 m/ft
+nmile 1852 m
+
+acre 4840 yd2
+
+cc cm3
+liter kilocc
+ml milliliter
+
+# US Liquid
+
+gallon 231 in3
+imperial 1.20095
+gal gallon
+quart 1|4 gal
+qt quart
+pint 1|2 qt
+pt pint
+
+floz 1|16 pt
+fldr 1|8 floz
+shot 3|2 floz
+
+# US Dry
+
+dry 268.8025 in3/gallon fuzz
+peck 8 dry-quart
+pk peck
+bushel 4 peck
+bu bushel
+chaldron 36 bushel
+
+# British
+
+brgallon 277.420 in3 fuzz
+brquart 1|4 brgallon
+brpint 1|2 brquart
+brfloz 1|20 brpint
+brpeck 554.84 in3 fuzz
+brbushel 4 brpeck
+brhundredweight 112 lb
+
+# Bottles
+
+bottle 750 milliliter
+#bottle fifth
+
+miniature 100 milliliter
+split 1|4 bottle
+half 1|2 bottle
+magnum 2 bottle
+jeroboam 4 bottle
+rehoboam 6 bottle
+methuselah 8 bottle
+salmanazar 12 bottle
+balthazar 16 bottle
+nebuchadnezzar 20 bottle
+sovereign 34 bottle
+
+# Bottles - alternate names and spellings
+
+pony split
+fillette half
+tappit-hen 3 imperial
+rheoboam rehoboam
+shalmaneser salmanazar
+
+# Russian
+berkovets 10 pood
+pood 40 funt
+funt 0.40951 kg
+lot 1|32 funt
+zolotnik 1|3 lot
+dolya 1|96 zolotnik
+rumile 7 verst
+mezhevayaverst 2 verst
+verst 1066.8 m
+sazhen 1|500 verst
+kosayasazhen 1|430.2 verst
+arshin 1|1500 verst
+# is not exactly defined
+ruell 16.54 in
+liniya 1|10 in
+vershok 1.75 in
+pyad 7 in
+vedro 12.3 liter
+shtoff 1|10 vedro
+vinebottle 1|16 vedro
+vodkabottle 1|20 vedro
+charka 1|100 vedro
+shkalik 1|200 vedro
+desyatina_state 109.3 are
+desyatina_farmery 0.75 desyatina_state
+sqverst 104.2 desyatina_state
+sqarshin 1|21600 desyatina_state
+sqfoot 1|117600 desyatina_state
+
+# Energy Work
+
+newton kg-m/sec2
+nt newton
+N newton
+joule nt-m
+J joule
+cal 4.1868 joule
+ergon erg
+
+# Electrical
+
+coulomb coul
+C coul
+ampere coul/sec
+A ampere
+amp ampere
+watt joule/sec
+W watt
+volt watt/amp
+ohm volt/amp
+mho /ohm
+farad coul/volt
+F farad
+henry sec2/farad
+H henry
+weber volt-sec
+Wb weber
+
+# Light
+
+cd candela
+lumen cd sr
+lux cd sr/m2
+
+# EMU currencies have constant exchange rate against Euro since 1.1.1999.
+# See https://en.wikipedia.org/wiki/Euro for details.
+austriaschilling 1|13.7603 euro
+belgiumfranc 1|40.3399 euro
+finlandmarkka 1|5.94573 euro
+francefranc 1|6.55957 euro
+germanymark 1|1.95583 euro
+greecedrachma 1|340.750 euro
+irelandpunt 1|0.787564 euro
+italylira 1|1936.27 euro
+luxembourgfranc 1|40.3399 euro
+netherlandsguilder 1|2.20371 euro
+portugalescudo 1|200.482 euro
+spainpeseta 1|166.386 euro
+sloveniantolar 1|239.640 euro
+cypriotpound 1|0.585274 euro
+malteselira 1|0.429300 euro
+slovakkoruna 1|30.1260 euro
+
+# These ones are pegged to the Euro
+# See https://en.wikipedia.org/wiki/Euro for details.
+bosniaherzegovinamark 1|1.95583 euro
+bulgarianlev 1|1.95583 euro
+capeverdeanescudo 1|110.265 euro
+centralafricancfafranc 1|655.957 euro
+comorosfranc 1|491.96775 euro
+danishkrone 1|7.46038 euro
+estoniakroon 1|15.6466 euro
+lithuanianlitas 1|3.45280 euro
+pacificfrancexchange 1|0.00838 euro
+westafricancfafranc 1|655.957 euro
+
+# ISO Currency Codes
+
+AED uaedirham
+AFN afghanafghani
+ALL albanialek
+AMD armeniadram
+AOA angolakwanza
+ARS argentinapeso
+AUD australiadollar
+AWG arubaflorin
+AZN azerbaijanmanat
+BAM bosniaconvertiblemark
+BBD barbadosdollar
+BDT bangladeshtaka
+BGN bulgarialev
+BHD bahraindinar
+BIF burundifranc
+BMD bermudadollar
+BND bruneidollar
+BOB boliviaboliviano
+BRL brazilreal
+BSD bahamasdollar
+BTN bhutanngultrum
+BWP botswanapula
+BYR belarusruble
+BZD belizedollar
+CAD canadadollar
+CDF drcfranccongolais
+CHF swissfranc
+CLP chilepeso
+CMG sintmaartencaribbeanguilder
+CNY chinayuan
+COP colombiapeso
+CRC costaricacolon
+CUP cubapeso
+CVE capeverdeescudo
+CZK czechkoruna
+DJF djiboutifranc
+DKK denmarkkrona
+DOP dominicanrepublicpeso
+DZD algeriadinar
+EGP egyptpound
+ERN eritreanakfa
+ETB ethiopianbirr
+EUR euro
+FJD fijidollar
+FKP falklandislandspound
+GBP ukpound
+GEL georgialari
+GGP guernseypound
+GHS ghanacedi
+GIP gibraltarpound
+GMD gambiadalasi
+GNF guineafranc
+GTQ guatemalaquetzal
+GYD guyanadollar
+HKD hongkongdollar
+HNL honduraslempira
+HRK croatiakuna
+HTG haitigourde
+HUF hungariaforint
+IDR indonesiarupiah
+ILS israelnewshekel
+IMP manxpound
+INR indiarupee
+IQD iraqdinar
+IRR iranrial
+ISK icelandkrona
+JEP jerseypound
+JMD jamaicadollar
+JOD jordandinar
+JPY japanyen
+KES kenyaschilling
+KGS kyrgyzstansom
+KHR cambodiariel
+KMF comorosfranc
+KPW northkoreawon
+KRW southkoreawon
+KWD kuwaitdinar
+KYD caymanislandsdollar
+KZT kazakhstantenge
+LAK laokip
+LBP lebanonpound
+LKR srilankanrupee
+LRD liberiadollar
+LTL lithuanialita
+LVL latvialat
+LYD libyadinar
+MAD moroccodirham
+MDL moldovaleu
+MGA madagascarariary
+MKD macedoniadenar
+MMK myanmarkyat
+MNT mongoliatugrik
+MOP macaupataca
+MRO mauritaniaouguiya
+MUR mauritiusrupee
+MVR maldiverufiyaa
+MWK malawikwacha
+MXN mexicopeso
+MYR malaysiaringgit
+MZN mozambicanmetical
+NAD namibiadollar
+NGN nigerianaira
+NIO nicaraguacordobaoro
+NOK norwaykrone
+NPR nepalrupee
+NZD newzealanddollar
+OMR omanrial
+PAB panamabalboa
+PEN perunuevosol
+PGK papuanewguineakina
+PHP philippinepeso
+PKR pakistanrupee
+PLN polandzloty
+PYG paraguayguarani
+QAR qatarrial
+RON romanianewlei
+RSD serbiadinar
+RUB russiarouble
+RWF rwandafranc
+SAR saudiarabiariyal
+SBD solomonislandsdollar
+SCR seychellesrupee
+SDG sudanpound
+SEK swedenkrona
+SGD singaporedollar
+SHP sainthelenapound
+SLL sierraleoneleone
+SOS somaliaschilling
+SRD surinamedollar
+STD saotome&principedobra
+SVC elsalvadorcolon
+SYP syriapound
+SZL swazilandlilangeni
+THB thailandbaht
+TJS tajikistansomoni
+TMT turkmenistanmanat
+TND tunisiadinar
+TOP tongapa'anga
+TRY turkeylira
+TTD trinidadandtobagodollar
+TVD tuvaludollar
+TWD taiwandollar
+TZS tanzaniashilling
+UAH ukrainehryvnia
+UGX ugandaschilling
+USD usdollar
+UYU uruguaypeso
+UZS uzbekistansum
+VEF venezuelabolivar
+VND vietnamdong
+VUV vanuatuvatu
+WST samoatala
+XAF centralafricancfafranc
+XCD eastcaribbeandollar
+XDR specialdrawingrights
+XOF westafricanfranc
+XPF cfpfranc
+YER yemenrial
+ZAR southafricarand
+ZMW zambiakwacha
+ZWL zimbabwedollar
+
+# These ones are pegged on the US Dollar
+# See https://en.wikipedia.org/wiki/USD for details.
+dollar usdollar
+arubanflorin 1|1.75 usdollar
+bahamiandollar 1|1 usdollar
+bahrainidinar 1|0.376 usdollar
+barbadiandollar 1|2 usdollar
+belizedollar 1|2 usdollar
+belarusianruble 1|2135 usdollar
+bermudiandollar 1|1 usdollar
+caymanislandsdollar 1.2 usdollar
+cubanconvertiblepeso 1.08 usdollar
+djiboutianfranc 1|177.721 usdollar
+eastcaribbeandollar 1|2.7 usdollar
+eritreannakfa 1|15 usdollar
+hongkongdollar 1|7.80 usdollar
+macanesepatacas 1|1.03 hongkongdollar
+jordaniandinar 1|0.709 usdollar
+lebanesepound 1|1507.5 usdollar
+maldivianrufiyaa 1|12.8 usdollar
+netherlandsantilleanguilder 1|1.79 usdollar
+omanirial 2.6008 usdollar
+qataririyal 1|3.64 usdollar
+saudiriyal 1|3.75 usdollar
+unitedarabemiratesdirham 1|3.6725 usdollar
+
+bosniamark bosniaherzegovinamark
+cfafranc centralafricancfafranc
+cfpfranc pacificfrancexchange
+drachma greecedrachma
+escudo portugalescudo
+franc francefranc
+guilder netherlandsguilder
+herzegovinamark bosniaherzegovinamark
+hollandguilder netherlandsguilder
+lira italylira
+mark germanymark
+markka finlandmarkka
+peseta spainpeseta
+rand southafricarand
+
+# computer
+
+baud bit/sec
+nibble 4 bit
+nybble nibble
+byte 8 bit
+word 2 byte
+block 512 byte
+kbyte 1024 byte
+megabyte 1024 kbyte
+gigabyte 1024 megabyte
+terabyte 1024 gigabyte
+petabyte 1024 terabyte
+exabyte 1024 petabyte
+zettabyte 1024 exabyte
+yottabyte 1024 zettabyte
+kilobyte kbyte
+meg megabyte
+
+
+# Trivia
+
+% 1|100
+abampere 10 ampere
+admiraltyknot 6080 ft/hr
+apostilb cd/pi-m2
+are 1e+2 m2
+asb apostilb
+arpentcan 27.52 mi
+arpentlin 191.835 ft
+astronomicalunit au
+atmosphere 1.01325e+5 nt/m2
+atm atmosphere
+atomicmassunit 1.66053878283e-27 kg fuzz
+# year 3.15569259747e7 sec fuzz
+amu atomicmassunit
+bag 94 lb
+bakersdozen 13
+bar 1e+5 nt/m2
+barie 1e-1 nt/m2
+barleycorn 1|3 in
+beardsecond 5 nm
+barn 1e-28 m2
+oilbarrel 42 gal
+barrel oilbarrel
+barye 1e-1 nt/m2
+baryl microbar
+bev 1e+9 e-volt
+biot 10 amp
+blondel cd/pi-m2
+boardfoot 144 in3
+bolt 40 yd
+bottommeasure 1|40 in
+britishthermalunit 1.05506e+3 joule fuzz
+btu britishthermalunit
+refrigeration 12000 btu/ton-hour
+buck usdollar
+cable 720 ft
+caliber 1e-2 in
+calorie cal
+carat 205 milligram
+caratgold 1|24
+cent centidollar
+cental 100 lb
+centesimalminute 1e-2 grade
+centesimalsecond 1e-4 grade
+century 100 year
+cfs ft3/sec
+chain 66 ft
+circularinch 1|4 pi-in2
+circularmil 1e-6|4 pi-in2
+clusec 1e-8 mm-hg m3/s
+coomb 4 bu
+cord 128 ft3
+cordfoot cord
+crith 9.06e-2 gm
+cubit 18 in
+cup 1|2 pt
+curie 3.7e+10 /sec
+dalton amu
+decade 10 yr
+dioptre /m
+displacementton 35 ft3
+doppelzentner 100 kg
+dozen 12
+drop .03 cm3
+dyne cm-gm/sec2
+electronvolt e-volt
+ell 45 in
+engineerschain 100 ft
+engineerslink 100|100 ft
+equivalentfootcandle lumen/pi-ft2
+equivalentlux lumen/pi-m2
+equivalentphot cd/pi-cm2
+erg cm2-gm/sec2
+ev e-volt
+faraday 9.6485309e+4 coul
+fathom 6 ft
+fermi 1e-15 m
+fifth 4|5 qt
+fin 5 usdollar
+finger 7|8 in
+firkin 9 gal
+footcandle lumen/ft2
+footlambert cd/pi-ft2
+fortnight 14 da
+franklin 3.33564e-10 coul
+frigorie kilocal
+furlong 220 yd
+galileo 1e-2 m/sec2
+gamma 1e-9 weber/m2
+gauss 1e-4 weber/m2
+G gauss
+geodeticfoot british-ft
+geographicalmile 1852 m
+gilbert 2.5 amp/pi
+gill 1|4 pt
+gross 144
+gunterschain 22 yd
+hand 4 in
+hartree 2 rydberg
+head water
+hectare 1e+4 m2
+hefnercandle .92 cd
+hertz /sec
+Hz hertz
+hogshead 63 gallon
+hd hogshead
+homestead 1|4 mi2
+horsepower 735.50 watt
+donkeypower 250 watt
+hp horsepower
+hubble 1e9 ly
+hyl gm force sec2/m
+hz /sec
+imaginarycubicfoot 1.4 ft3
+jansky 1e-26 W/m2-Hz
+Jy jansky
+karat 1|24
+kayser /cm
+key kg
+kilderkin 18 gal
+knot nmile/hr
+kn knot
+lambert cd/pi-cm2
+Lb lambert
+langley cal/cm2
+last 80 bu
+league 3 mi
+lightyear c-yr
+ly lightyear
+line 1|12 in
+link 66|100 ft
+longhundredweight 112 lb
+longquarter 28 lb
+lusec 1e-6 mm-hg m3/s
+m_earth 5.97223e24 kg
+m_moon 7.34e22 kg
+m_sun 1.98843e30 kg
+mach 331.46 m/sec
+marineleague 3 nmile
+maxwell 1e-8 weber
+Mx maxwell
+metriccarat 200 milligram
+mgd megagal/day
+mh millihenry
+mil 1e-3 in
+millennium 1000 year
+minersinch 1.5 ft3/min
+minim 1|60 fldr
+mo month
+mpg mile/gal
+mph mile/hr
+nail 1|16 yd
+nauticalmile nmile
+nit cd/m2
+noggin 1|8 qt
+nox 1e-3 lux
+oersted 2.5e+2 amp/m/pi
+Oe oersted
+pace 36 in
+pair 2
+palm 3 in
+parasang 3.5 mi
+parsec AU-radian/arcsec
+pascal nt/m2
+Pa pascal
+pc parsec
+percent %
+perch rd
+phot lumen/cm2
+pica 1|6 in
+pieze 1e+3 nt/m2
+pipe 4 barrel
+point 1|72 in
+poise gm/cm-sec
+P poise
+pole rd
+pond 9.80665e-3 nt
+potrzebie 2.263348517438173216473 mm
+poundal ft-lb/sec2
+pdl poundal
+proof 1|200
+psi lb-g/in2
+quarter 9 in
+quartersection 1|4 mi2
+quintal 100 kg
+quire 25
+r_earth 6.378e8 cm
+r_moon 1.738e7 cm
+r_sun 6.9599e10 cm
+rackunit 1.75 in
+rad 100 erg/gm
+ream 500
+registerton 100 ft3
+rem 0.01 J/kg
+rhe 10 m2/nt-sec
+rontgen 2.58e-4 curie/kg
+roentgen rontgen
+rood 1.21e+3 yd
+rope 20 ft
+RU rackunit
+rutherford 1e+6 /sec
+rydbergconst 0.5 elctronmass-c-alpha2/planck
+rydberg rydbergconst-planck-c
+sabin 1 ft2
+sack 3 bu
+score 20
+seam 8 bu
+section mi2
+shed 1e-24 barn
+shippington 40 ft3
+shorthundredweight 100 lb
+shortquarter 25 lb
+siemens /ohm
+sigma microsec
+skein 120 yd
+skot 1e-3 apostilb
+slug lb-g-sec2/ft
+smoot 67 in
+span 9 in
+spat 4 pi sr
+spindle 14400 yd
+square 100 ft2
+stere m3
+sthene 1e+3 nt
+stilb cd/cm2
+sb stilb
+stoke 1e-4 m2/sec
+stone 14 lb
+strike 2 bu
+surveyfoot british-ft
+surveyyard 3 surveyfoot
+surveyorschain 66 ft
+surveyorslink 66|100 ft
+tablespoon 4 fldr
+tbl tablespoon
+tbsp tablespoon
+teaspoon 4|3 fldr
+tesla weber/m2
+T tesla
+therm 1e+5 btu
+thermie 1e+6 cal
+timberfoot ft3
+tnt 4.6e+6 m2/sec2
+tonne 1e+6 gm
+torr mm hg
+township 36 mi2
+tsp teaspoon
+tun 8 barrel
+water gram g / cc
+wey 40 bu
+weymass 252 lb
+Xunit 1.00206e-13 m
+k 1.38047e-16 erg/degC
+
+
+degC 1&+273.15 K
+kelvin K
+brewster 1e-12 m2/newton
+degF 5|9&255.37222222222222222222 K
+degreesrankine 5|9 K
+degrankine degreesrankine
+degreerankine degreesrankine
+degreaumur 10|8&+273.15 K
+gasmark 25|1&250 degF
+Stufe 25|1&125 degC
+drachm 60 grain
+poncelet 100 kg m g / sec
+denier .05|450 gram / m
+tex .001 gram / m
+englishell 45 inch
+scottishell 37.2 inch
+flemishell 27 inch
+V volt
+eV e V
+bohrradius hbar2-C2/8.988e9 N m2-e2-electronmass
+becquerel 1|3.7e10 curie
+fresnel 1e12 hertz
+statcoul 1|2.99792458e9 coul
+statamp 1|2.99792458e9 amp
+statvolt 2.99792458e2 volt
+statcoulomb statcoul
+statampere statamp
+debye 3.33564e-30 coul-m
+pulsatance 2 pi/sec
+rpm rev/minute
+rps rev/sec
+kilohm kiloohm
+megohm megaohm
+siderealyear 365.256360417 day
+siderealday 23.934469444 hour
+siderealhour 1|24 sidereal day
+lunarmonth 29.5305555 day
+synodicmonth lunarmonth
+siderealmonth 27.32152777 day
+tropicalyear year
+solaryear year
+lunaryear 12 lunarmonth
+cran 37.5 brgallon
+kip 1000 lbf
+frenchfoot 16|15 ft
+frenchfeet frenchfoot
+toise 6 frenchfeet
+sievert 8.4 rontgen
+candle 1.02 candela
+militarypace 2.5 feet
+metre meter
+litre liter
+gramme gram
+iudiptheria 62.8 microgram
+iupenicillin .6 microgram
+iuinsulin 41.67 microgram
+cottonyarncount 2520 ft/pound
+linenyarncount 900 ft/pound
+worstedyarncount 1680 ft/pound
+metricyarncount meter/gram
+jewlerspoint 2 milligram
diff --git a/usr.bin/units/tests/Makefile b/usr.bin/units/tests/Makefile
new file mode 100644
index 000000000000..f330d0fc8950
--- /dev/null
+++ b/usr.bin/units/tests/Makefile
@@ -0,0 +1,5 @@
+.include <bsd.own.mk>
+
+TAP_TESTS_SH= basics_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/units/tests/Makefile.depend b/usr.bin/units/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/units/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/units/tests/basics_test.sh b/usr.bin/units/tests/basics_test.sh
new file mode 100644
index 000000000000..20d6cb97c83b
--- /dev/null
+++ b/usr.bin/units/tests/basics_test.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..3"
+
+assert_equals() {
+ testnum="$1"
+ expected="$2"
+ fn="$3"
+ if [ "$expected" = "$($fn)" ]
+ then
+ echo "ok $testnum - $fn"
+ else
+ echo "not ok $testnum - $fn"
+ fi
+}
+
+assert_equals 1 1 "units -t ft ft"
+assert_equals 2 12 "units -t ft in"
+assert_equals 3 0.083333333 "units -t in ft"
diff --git a/usr.bin/units/units.1 b/usr.bin/units/units.1
new file mode 100644
index 000000000000..c462c0d7f665
--- /dev/null
+++ b/usr.bin/units/units.1
@@ -0,0 +1,473 @@
+.Dd March 17, 2020
+.Dt UNITS 1
+.Os
+.Sh NAME
+.Nm units
+.Nd conversion calculator
+.Sh SYNOPSIS
+.Nm
+.Op Fl ehqtUVv
+.Op Fl f Ar unitsfile
+.Op Fl o Ar format
+.Op Ar from to
+.Sh DESCRIPTION
+The
+.Nm
+program converts quantities expressed in various scales to
+their equivalents in other scales.
+It can only
+handle multiplicative or affine scale changes.
+.Pp
+.Nm
+can work interactively by prompting
+the user for input
+.Pq see Sx EXAMPLES
+or non-interactively, providing a conversion for given arguments
+.Ar from
+and
+.Ar to .
+.Pp
+The following options are available:
+.Bl -tag -width "from to"
+.It Fl e , Fl -exponential
+Same as
+.Fl o
+.Cm %6e
+(see the description of the
+.Fl o
+flag).
+.It Fl f Ar unitsfile , Fl -file Ar unitsfile
+Specify the name of the units data file to load.
+This option may be specified multiple times.
+.It Fl H Ar historyfile , Fl -history Ar historyfile
+Ignored, for compatibility with GNU units.
+.It Fl h , Fl -help
+Show an overview of options.
+.It Fl o Ar format , Fl -output-format Ar format
+Select the output format string by which numbers are printed.
+Defaults to
+.Dq Li %.8g .
+.It Fl q , Fl -quiet
+Suppress prompting of the user for units and the display of statistics
+about the number of units loaded.
+.It Fl t , Fl -terse
+Only print the result.
+This is used when calling
+.Nm
+from other programs for easy to parse results.
+.It Fl U , Fl -unitsfile
+Print the location of the default unit file if it exists.
+Otherwise, print
+.Dq Units data file not found .
+.It Fl V , Fl -version
+Print the version number
+.Pq which is fixed at Dq Fx units ,
+the path to the units data file and exit.
+.It Fl v , Fl -verbose
+Print the units in the conversion output.
+Be more verbose in general.
+.It Ar from to
+Allow a single unit conversion to be done directly from the command
+line.
+The program will not print prompts.
+It will print out the result of the single specified conversion.
+Both arguments, i.e.,
+.Ar from
+and
+.Ar to ,
+can be just a unit
+.Pq e.g., Dq Cm cm ,
+a quantity
+.Pq e.g., Dq Cm 42 ,
+or a quantity with a unit
+.Pq e.g., Dq Cm 42 cm
+.El
+.Ss Mathematical operators
+.Bl -dash -compact
+.It
+Powers of units can be specified using the
+.Dq Ic ^
+character as shown in the example, or by simple concatenation:
+.Dq Ic cm3
+is
+equivalent to
+.Dq Ic cm^3 .
+See the
+.Sx BUGS
+section
+for details on the limitations of exponent values.
+.It
+Multiplication of units can be specified by using spaces
+.Pq Dq " " ,
+a dash
+.Pq Dq -
+or an asterisk
+.Pq Dq * .
+.It
+Division of units is indicated by the slash
+.Pq Dq Ic / .
+.It
+Division of numbers
+must be indicated using the vertical bar
+.Pq Dq Ic \&| Ns .
+.El
+.Pp
+Note that multiplication has a higher precedence than division,
+so
+.Dq Ic m/s/s
+is the same as
+.Dq Ic m/s^2
+or
+.Dq Ic m/s s .
+.Ss Units
+The conversion information is read from a units data file.
+The default
+file includes definitions for most familiar units, abbreviations and
+metric prefixes.
+Some constants of nature included are:
+.Pp
+.Bl -column -offset indent -compact "mercury"
+.It "pi ratio of circumference to diameter"
+.It "c speed of light"
+.It "e charge on an electron"
+.It "g acceleration of gravity"
+.It "force same as g"
+.It "mole Avogadro's number"
+.It "water pressure per unit height of water"
+.It "mercury pressure per unit height of mercury"
+.It "au astronomical unit"
+.El
+.Pp
+The unit
+.Dq Ic pound
+is a unit of mass.
+Compound names are run together
+so
+.Dq Ic pound force
+is a unit of force.
+The unit
+.Dq Ic ounce
+is also a unit of mass.
+The fluid ounce is
+.Dq Ic floz .
+British units that differ from
+their US counterparts are prefixed with
+.Dq br ,
+and currency is prefixed with its country name:
+.Dq Ic belgiumfranc ,
+.Dq Ic britainpound .
+When searching
+for a unit, if the specified string does not appear exactly as a unit
+name, then
+.Nm
+will try to remove a trailing
+.Dq s
+or a trailing
+.Dq es
+and check again for a match.
+.Ss Units file format
+To find out what units are available read the standard units file.
+If you want to add your own units you can supply your own file.
+A unit is specified on a single line by
+giving its name and an equivalence.
+Be careful to define
+new units in terms of old ones so that a reduction leads to the
+primitive units which are marked with
+.Dq \&!
+characters.
+The
+.Nm
+program will not detect infinite loops that could be caused
+by careless unit definitions.
+Comments in the unit definition file
+begin with a
+.Dq #
+or
+.Dq /
+character at the beginning of a line.
+.Pp
+Prefixes are defined in the same way as standard units, but with
+a trailing dash
+.Pq Dq -
+at the end of the prefix name.
+If a unit is not found
+even after removing trailing
+.Dq s
+or
+.Dq es ,
+then it will be checked against the list of prefixes.
+Prefixes will be removed until a legal
+base unit is identified.
+.Sh ENVIRONMENT
+.Bl -tag -width PATH
+.It Ev PATH
+The colon-separated list of root directories at which
+.Nm
+tries to find
+.Pa /usr/share/misc/definitions.units .
+.Pp
+For example if
+.Ev PATH
+is set to
+.Dq Li /tmp:/:/usr/local ,
+no
+.Fl f
+flags are provided, and
+.Pa /usr/share/misc/definitions.units
+is missing then
+.Nm
+tries to open the following files as the default units file:
+.Pa /tmp/usr/share/misc/definitions.units ,
+.Pa /usr/share/misc/definitions.units ,
+and
+.Pa /usr/local/usr/share/misc/definitions.units .
+.El
+.Sh FILES
+.Bl -tag -width /usr/share/misc/definitions.units -compact
+.It Pa /usr/share/misc/definitions.units
+The standard units file.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Bl -tag -width 0n
+.It Sy Example 1 : No Simple conversion of units
+.Pp
+This example shows how to do simple conversions, for example from gigabytes
+to bytes:
+.Bd -literal -offset 2n
+.Li $ Ic units -o %0.f -t '4 gigabytes' bytes
+4294967296
+.Ed
+.Pp
+The
+.Fl o Cm %0.f
+part of the command is required to print the result in a non-scientific
+notation (e.g, 4294967296 instead of 4.29497e+09).
+.It Sy Example 2 : No Interactive usage
+.Pp
+Here is an example of an interactive session where the user is prompted for
+units:
+.Bd -literal -offset 2n
+.Li You have : Ic meters
+.Li You want : Ic feet
+ * 3.2808399
+ / 0.3048
+
+.Li You have : Ic cm^3
+.Li You want : Ic gallons
+ * 0.00026417205
+ / 3785.4118
+
+.Li You have : Ic meters/s
+.Li You want : Ic furlongs/fortnight
+ * 6012.8848
+ / 0.00016630952
+
+.Li You have : Ic 1|2 inch
+.Li You want : Ic cm
+ * 1.27
+ / 0.78740157
+
+.Li You have : Ic 85 degF
+.Li You want : Ic degC
+ 29.444444
+.Ed
+.It Sy Example 3 : No Difference between Do Ic \&| Dc No and Do Ic / Dc No division
+.Pp
+The following command shows how to convert half a meter to centimeters.
+.Bd -literal -offset 2n
+.Li $ Ic units '1|2 meter' cm
+ * 50
+ / 0.02
+.Ed
+.Pp
+.Nm
+prints the expected result because the division operator for numbers
+.Pq Dq Li \&|
+was used.
+.Pp
+Using the division operator for units
+.Pq Dq Li /
+would result in an error:
+.Bd -literal -offset 2n
+.Li $ Ic units '1/2 meter' cm
+conformability error
+ 0.5 / m
+ 0.01 m
+.Ed
+.Pp
+It is because
+.Nm
+interprets
+.Dq Ic 1/2 meter
+as
+.Dq Ic 0.5/meter ,
+which is not conformable to
+.Dq Ic cm .
+.It Sy Example 4 : No Simple units file
+Here is an example of a short units file that defines some basic
+units:
+.Pp
+.Bl -column -offset 2n -compact "minute"
+.It "m !a!"
+.It "sec !b!"
+.It "micro- 1e-6"
+.It "minute 60 sec"
+.It "hour 60 min"
+.It "inch 0.0254 m"
+.It "ft 12 inches"
+.It "mile 5280 ft"
+.El
+.It Sy Example 5 : No Viewing units and conversions of the default units file
+The following shell one-liner allows the user to view the contents of the
+default units file:
+.Bd -literal -offset 2n
+.Li $ Ic less \&"$(units -U)"
+.Ed
+.El
+.Sh DIAGNOSTICS
+.Bl -diag
+.It can't find units file '%s'
+The default units file is not in its default location
+.Pq see Sx FILES
+and it is not present in any file tree starting with their roots at directories from
+.Ev PATH
+.Pq see Sx ENVIRONMENT .
+.It cap_rights_limit\&() failed
+See
+.Xr capsicum 4 .
+.It conformability error
+It is not possible to reduce the given units to one common unit:
+they are not conformable.
+Instead of a conversion,
+.Nm
+will display the reduced form for each provided unit:
+.Bd -literal -offset 2n
+.Li You have : Ic ergs/hour
+.Li You want : Ic fathoms kg^2 / day
+conformability error
+ 2.7777778e-11 kg m^2 / sec^3
+ 2.1166667e-05 kg^2 m / sec
+.Ed
+.It Could not initialize history
+See
+.Xr editline 3 .
+.It dupstr
+.Xr strdup 3
+failed.
+.It memory for prefixes exceeded in line %d
+Over 100 prefixes were defined.
+.It memory for units exceeded in line %d
+Over 1000 prefixes were defined.
+.It memory overflow in unit reduction
+The requested conversion involves too many units
+.Pq see Sx BUGS .
+.It redefinition of prefix '%s' on line %d ignored
+.No ""
+.It redefinition of unit '%s' on line %d ignored
+.No ""
+.It unexpected end of prefix on line %d
+.No ""
+.It unexpected end of unit on line %d
+.No ""
+.It Units data file not found
+The default units file is missing.
+.It unable to enter capability mode
+See
+.Xr capsicum 4 .
+.It unable to open units file '%s'
+One of the user-specified units files cannot be opened.
+.It unit reduces to zero
+.No ""
+.It unknown unit '%s'
+The provided unit cannot be found in the units file.
+.It WARNING: conversion of non-proportional quantities.
+.Nm
+may fail to convert
+.Ar from
+to
+.Ar to
+because the units are not proportional.
+The warning is printed when a quantity is a part of the
+.Ar to
+argument.
+It can be illustrated on an example of conversion from Fahrenheit to Celsius:
+.Bd -literal -offset 2n
+.Li $ Ic units \&"degF" \&"degC"
+ (-> x*0.55555556g -17.777778g)
+ (<- y*1.8g 32g)
+.Li $ Ic units \&"degF" \&"1 degC"
+WARNING: conversion of non-proportional quantities.
+ (-> x*0.55555556g -17.777778g)
+ (<- y*1.8g 32g)
+.Li $ Ic units \&"1 degF" \&"1 degC"
+WARNING: conversion of non-proportional quantities.
+ -17.222222
+.Ed
+.El
+.Sh SEE ALSO
+.Xr bc 1
+.Sh HISTORY
+The
+.Nm
+first appeared in
+.Nx
+and was ported to
+.Fx 2.2.0 .
+.Pp
+The manual page was significantly rewritten in
+.Fx 13.0
+by
+.An Mateusz Piotrowski Aq Mt 0mp@FreeBSD.org .
+.Sh AUTHORS
+.An Adrian Mariano Aq Mt adrian@cam.cornell.edu
+.Sh BUGS
+The effect of including a
+.Dq /
+in a prefix is surprising.
+.Pp
+Exponents entered by the user can be only one digit.
+You can work around this by multiplying several terms.
+.Pp
+The user must use
+.Dq Ic \&|
+to indicate division of numbers and
+.Dq Ic /
+to indicate division of symbols.
+This distinction should not
+be necessary.
+.Pp
+The program contains various arbitrary limits on the length
+of the units converted and on the length of the data file.
+.Pp
+The program should use a hash table to store units so that
+it does not take so long to load the units list and check
+for duplication.
+.Pp
+It is not possible to convert a negative value.
+.Pp
+The
+.Nm
+program
+does not handle reductions of long lists of units very well:
+.Bd -literal -offset 2n
+.Li $ Ic units \&"$(yes m | head -n 154)" \&"$(yes cm | head -n 154)"
+ * 1e+308
+ / 1e-308
+.Li $ Ic units \&"$(yes m | head -n 333)" \&"$(yes cm | head -n 333)"
+ * inf
+ / 0
+.Li $ Ic units \&"$(yes m | head -n 500)" \&"$(yes cm | head -n 500)"
+units: memory overflow in unit reduction
+conformability error
+ 1 m^500
+ 1 centi cm^499
+.Li $ Ic units \&"$(yes m | head -n 501)" \&"$(yes cm | head -n 501)"
+units: memory overflow in unit reduction
+units: memory overflow in unit reduction
+units: memory overflow in unit reduction
+conformability error
+ 1 m^500
+ 1 centi cm^499
+.Ed
diff --git a/usr.bin/units/units.c b/usr.bin/units/units.c
new file mode 100644
index 000000000000..1b6d0ed90b4a
--- /dev/null
+++ b/usr.bin/units/units.c
@@ -0,0 +1,886 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * units.c Copyright (c) 1993 by Adrian Mariano (adrian@cam.cornell.edu)
+ *
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * Disclaimer: This software is provided by the author "as is". The author
+ * shall not be liable for any damages caused in any way by this software.
+ *
+ * I would appreciate (though I do not require) receiving a copy of any
+ * improvements you might make to this program.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <histedit.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <capsicum_helpers.h>
+
+#ifndef UNITSFILE
+#define UNITSFILE "/usr/share/misc/definitions.units"
+#endif
+
+#define MAXUNITS 1000
+#define MAXPREFIXES 100
+
+#define MAXSUBUNITS 500
+
+#define PRIMITIVECHAR '!'
+
+static const char *powerstring = "^";
+static const char *numfmt = "%.8g";
+
+static struct {
+ char *uname;
+ char *uval;
+} unittable[MAXUNITS];
+
+struct unittype {
+ char *numerator[MAXSUBUNITS];
+ char *denominator[MAXSUBUNITS];
+ double factor;
+ double offset;
+ int quantity;
+};
+
+static struct {
+ char *prefixname;
+ char *prefixval;
+} prefixtable[MAXPREFIXES];
+
+
+static char NULLUNIT[] = "";
+
+#define SEPARATOR ":"
+
+static int unitcount;
+static int prefixcount;
+static bool verbose = false;
+static bool terse = false;
+static const char * outputformat;
+static const char * havestr;
+static const char * wantstr;
+
+static int addsubunit(char *product[], char *toadd);
+static int addunit(struct unittype *theunit, const char *toadd, int flip, int quantity);
+static void cancelunit(struct unittype * theunit);
+static int compare(const void *item1, const void *item2);
+static int compareproducts(char **one, char **two);
+static int compareunits(struct unittype * first, struct unittype * second);
+static int completereduce(struct unittype * unit);
+static char *dupstr(const char *str);
+static void initializeunit(struct unittype * theunit);
+static char *lookupunit(const char *unit);
+static void readunits(const char *userfile);
+static int reduceproduct(struct unittype * theunit, int flip);
+static int reduceunit(struct unittype * theunit);
+static void showanswer(struct unittype * have, struct unittype * want);
+static void showunit(struct unittype * theunit);
+static void sortunit(struct unittype * theunit);
+static void usage(void);
+static void zeroerror(void);
+
+static const char* promptstr = "";
+
+static const char * prompt(EditLine *e __unused) {
+ return promptstr;
+}
+
+static char *
+dupstr(const char *str)
+{
+ char *ret;
+
+ ret = strdup(str);
+ if (!ret)
+ err(3, "dupstr");
+ return (ret);
+}
+
+
+static void
+readunits(const char *userfile)
+{
+ FILE *unitfile;
+ char line[512], *lineptr;
+ int len, linenum, i;
+ cap_rights_t unitfilerights;
+
+ unitcount = 0;
+ linenum = 0;
+
+ if (userfile) {
+ unitfile = fopen(userfile, "r");
+ if (!unitfile)
+ errx(1, "unable to open units file '%s'", userfile);
+ }
+ else {
+ unitfile = fopen(UNITSFILE, "r");
+ if (!unitfile) {
+ char *direc, *env;
+ char filename[1000];
+
+ env = getenv("PATH");
+ if (env) {
+ direc = strtok(env, SEPARATOR);
+ while (direc) {
+ snprintf(filename, sizeof(filename),
+ "%s/%s", direc, UNITSFILE);
+ unitfile = fopen(filename, "rt");
+ if (unitfile)
+ break;
+ direc = strtok(NULL, SEPARATOR);
+ }
+ }
+ if (!unitfile)
+ errx(1, "can't find units file '%s'", UNITSFILE);
+ }
+ }
+ cap_rights_init(&unitfilerights, CAP_READ, CAP_FSTAT);
+ if (caph_rights_limit(fileno(unitfile), &unitfilerights) < 0)
+ err(1, "cap_rights_limit() failed");
+ while (!feof(unitfile)) {
+ if (!fgets(line, sizeof(line), unitfile))
+ break;
+ linenum++;
+ lineptr = line;
+ if (*lineptr == '/' || *lineptr == '#')
+ continue;
+ lineptr += strspn(lineptr, " \n\t");
+ len = strcspn(lineptr, " \n\t");
+ lineptr[len] = 0;
+ if (!strlen(lineptr))
+ continue;
+ if (lineptr[strlen(lineptr) - 1] == '-') { /* it's a prefix */
+ if (prefixcount == MAXPREFIXES) {
+ warnx("memory for prefixes exceeded in line %d", linenum);
+ continue;
+ }
+ lineptr[strlen(lineptr) - 1] = 0;
+ prefixtable[prefixcount].prefixname = dupstr(lineptr);
+ for (i = 0; i < prefixcount; i++)
+ if (!strcmp(prefixtable[i].prefixname, lineptr)) {
+ warnx("redefinition of prefix '%s' on line %d ignored",
+ lineptr, linenum);
+ continue;
+ }
+ lineptr += len + 1;
+ lineptr += strspn(lineptr, " \n\t");
+ len = strcspn(lineptr, "\n\t");
+ if (len == 0) {
+ warnx("unexpected end of prefix on line %d",
+ linenum);
+ continue;
+ }
+ lineptr[len] = 0;
+ prefixtable[prefixcount++].prefixval = dupstr(lineptr);
+ }
+ else { /* it's not a prefix */
+ if (unitcount == MAXUNITS) {
+ warnx("memory for units exceeded in line %d", linenum);
+ continue;
+ }
+ unittable[unitcount].uname = dupstr(lineptr);
+ for (i = 0; i < unitcount; i++)
+ if (!strcmp(unittable[i].uname, lineptr)) {
+ warnx("redefinition of unit '%s' on line %d ignored",
+ lineptr, linenum);
+ continue;
+ }
+ lineptr += len + 1;
+ lineptr += strspn(lineptr, " \n\t");
+ if (!strlen(lineptr)) {
+ warnx("unexpected end of unit on line %d",
+ linenum);
+ continue;
+ }
+ len = strcspn(lineptr, "\n\t");
+ lineptr[len] = 0;
+ unittable[unitcount++].uval = dupstr(lineptr);
+ }
+ }
+ fclose(unitfile);
+}
+
+static void
+initializeunit(struct unittype * theunit)
+{
+ theunit->numerator[0] = theunit->denominator[0] = NULL;
+ theunit->factor = 1.0;
+ theunit->offset = 0.0;
+ theunit->quantity = 0;
+}
+
+
+static int
+addsubunit(char *product[], char *toadd)
+{
+ char **ptr;
+
+ for (ptr = product; *ptr && *ptr != NULLUNIT; ptr++);
+ if (ptr >= product + MAXSUBUNITS) {
+ warnx("memory overflow in unit reduction");
+ return 1;
+ }
+ if (!*ptr)
+ *(ptr + 1) = NULL;
+ *ptr = dupstr(toadd);
+ return 0;
+}
+
+
+static void
+showunit(struct unittype * theunit)
+{
+ char **ptr;
+ int printedslash;
+ int counter = 1;
+
+ printf(numfmt, theunit->factor);
+ if (theunit->offset)
+ printf("&%.8g", theunit->offset);
+ for (ptr = theunit->numerator; *ptr; ptr++) {
+ if (ptr > theunit->numerator && **ptr &&
+ !strcmp(*ptr, *(ptr - 1)))
+ counter++;
+ else {
+ if (counter > 1)
+ printf("%s%d", powerstring, counter);
+ if (**ptr)
+ printf(" %s", *ptr);
+ counter = 1;
+ }
+ }
+ if (counter > 1)
+ printf("%s%d", powerstring, counter);
+ counter = 1;
+ printedslash = 0;
+ for (ptr = theunit->denominator; *ptr; ptr++) {
+ if (ptr > theunit->denominator && **ptr &&
+ !strcmp(*ptr, *(ptr - 1)))
+ counter++;
+ else {
+ if (counter > 1)
+ printf("%s%d", powerstring, counter);
+ if (**ptr) {
+ if (!printedslash)
+ printf(" /");
+ printedslash = 1;
+ printf(" %s", *ptr);
+ }
+ counter = 1;
+ }
+ }
+ if (counter > 1)
+ printf("%s%d", powerstring, counter);
+ printf("\n");
+}
+
+
+void
+zeroerror(void)
+{
+ warnx("unit reduces to zero");
+}
+
+/*
+ Adds the specified string to the unit.
+ Flip is 0 for adding normally, 1 for adding reciprocal.
+ Quantity is 1 if this is a quantity to be converted rather than a pure unit.
+
+ Returns 0 for successful addition, nonzero on error.
+*/
+
+static int
+addunit(struct unittype * theunit, const char *toadd, int flip, int quantity)
+{
+ char *scratch, *savescr;
+ char *item;
+ char *divider, *slash, *offset;
+ int doingtop;
+
+ if (!strlen(toadd))
+ return 1;
+
+ savescr = scratch = dupstr(toadd);
+ for (slash = scratch + 1; *slash; slash++)
+ if (*slash == '-' &&
+ (tolower(*(slash - 1)) != 'e' ||
+ !strchr(".0123456789", *(slash + 1))))
+ *slash = ' ';
+ slash = strchr(scratch, '/');
+ if (slash)
+ *slash = 0;
+ doingtop = 1;
+ do {
+ item = strtok(scratch, " *\t\n/");
+ while (item) {
+ if (strchr("0123456789.", *item)) { /* item is a number */
+ double num, offsetnum;
+
+ if (quantity)
+ theunit->quantity = 1;
+
+ offset = strchr(item, '&');
+ if (offset) {
+ *offset = 0;
+ offsetnum = atof(offset+1);
+ } else
+ offsetnum = 0.0;
+
+ divider = strchr(item, '|');
+ if (divider) {
+ *divider = 0;
+ num = atof(item);
+ if (!num) {
+ zeroerror();
+ free(savescr);
+ return 1;
+ }
+ if (doingtop ^ flip) {
+ theunit->factor *= num;
+ theunit->offset *= num;
+ } else {
+ theunit->factor /= num;
+ theunit->offset /= num;
+ }
+ num = atof(divider + 1);
+ if (!num) {
+ zeroerror();
+ free(savescr);
+ return 1;
+ }
+ if (doingtop ^ flip) {
+ theunit->factor /= num;
+ theunit->offset /= num;
+ } else {
+ theunit->factor *= num;
+ theunit->offset *= num;
+ }
+ }
+ else {
+ num = atof(item);
+ if (!num) {
+ zeroerror();
+ free(savescr);
+ return 1;
+ }
+ if (doingtop ^ flip) {
+ theunit->factor *= num;
+ theunit->offset *= num;
+ } else {
+ theunit->factor /= num;
+ theunit->offset /= num;
+ }
+ }
+ if (doingtop ^ flip)
+ theunit->offset += offsetnum;
+ }
+ else { /* item is not a number */
+ int repeat = 1;
+
+ if (strchr("23456789",
+ item[strlen(item) - 1])) {
+ repeat = item[strlen(item) - 1] - '0';
+ item[strlen(item) - 1] = 0;
+ }
+ for (; repeat; repeat--) {
+ if (addsubunit(doingtop ^ flip ? theunit->numerator : theunit->denominator, item)) {
+ free(savescr);
+ return 1;
+ }
+ }
+ }
+ item = strtok(NULL, " *\t/\n");
+ }
+ doingtop--;
+ if (slash) {
+ scratch = slash + 1;
+ }
+ else
+ doingtop--;
+ } while (doingtop >= 0);
+ free(savescr);
+ return 0;
+}
+
+
+static int
+compare(const void *item1, const void *item2)
+{
+ return strcmp(*(const char * const *)item1, *(const char * const *)item2);
+}
+
+
+static void
+sortunit(struct unittype * theunit)
+{
+ char **ptr;
+ unsigned int count;
+
+ for (count = 0, ptr = theunit->numerator; *ptr; ptr++, count++);
+ qsort(theunit->numerator, count, sizeof(char *), compare);
+ for (count = 0, ptr = theunit->denominator; *ptr; ptr++, count++);
+ qsort(theunit->denominator, count, sizeof(char *), compare);
+}
+
+
+void
+cancelunit(struct unittype * theunit)
+{
+ char **den, **num;
+ int comp;
+
+ den = theunit->denominator;
+ num = theunit->numerator;
+
+ while (*num && *den) {
+ comp = strcmp(*den, *num);
+ if (!comp) {
+/* if (*den!=NULLUNIT) free(*den);
+ if (*num!=NULLUNIT) free(*num);*/
+ *den++ = NULLUNIT;
+ *num++ = NULLUNIT;
+ }
+ else if (comp < 0)
+ den++;
+ else
+ num++;
+ }
+}
+
+
+
+
+/*
+ Looks up the definition for the specified unit.
+ Returns a pointer to the definition or a null pointer
+ if the specified unit does not appear in the units table.
+*/
+
+static char buffer[100]; /* buffer for lookupunit answers with
+ prefixes */
+
+char *
+lookupunit(const char *unit)
+{
+ int i;
+ char *copy;
+
+ for (i = 0; i < unitcount; i++) {
+ if (!strcmp(unittable[i].uname, unit))
+ return unittable[i].uval;
+ }
+
+ if (unit[strlen(unit) - 1] == '^') {
+ copy = dupstr(unit);
+ copy[strlen(copy) - 1] = 0;
+ for (i = 0; i < unitcount; i++) {
+ if (!strcmp(unittable[i].uname, copy)) {
+ strlcpy(buffer, copy, sizeof(buffer));
+ free(copy);
+ return buffer;
+ }
+ }
+ free(copy);
+ } else if (unit[strlen(unit) - 1] == 's') {
+ copy = dupstr(unit);
+ copy[strlen(copy) - 1] = 0;
+ for (i = 0; i < unitcount; i++) {
+ if (!strcmp(unittable[i].uname, copy)) {
+ strlcpy(buffer, copy, sizeof(buffer));
+ free(copy);
+ return buffer;
+ }
+ }
+ if (copy[strlen(copy) - 1] == 'e') {
+ copy[strlen(copy) - 1] = 0;
+ for (i = 0; i < unitcount; i++) {
+ if (!strcmp(unittable[i].uname, copy)) {
+ strlcpy(buffer, copy, sizeof(buffer));
+ free(copy);
+ return buffer;
+ }
+ }
+ }
+ free(copy);
+ }
+ for (i = 0; i < prefixcount; i++) {
+ size_t len = strlen(prefixtable[i].prefixname);
+ if (!strncmp(prefixtable[i].prefixname, unit, len)) {
+ if (!strlen(unit + len) || lookupunit(unit + len)) {
+ snprintf(buffer, sizeof(buffer), "%s %s",
+ prefixtable[i].prefixval, unit + len);
+ return buffer;
+ }
+ }
+ }
+ return 0;
+}
+
+
+
+/*
+ reduces a product of symbolic units to primitive units.
+ The three low bits are used to return flags:
+
+ bit 0 (1) set on if reductions were performed without error.
+ bit 1 (2) set on if no reductions are performed.
+ bit 2 (4) set on if an unknown unit is discovered.
+*/
+
+
+#define ERROR 4
+
+static int
+reduceproduct(struct unittype * theunit, int flip)
+{
+
+ char *toadd;
+ char **product;
+ int didsomething = 2;
+
+ if (flip)
+ product = theunit->denominator;
+ else
+ product = theunit->numerator;
+
+ for (; *product; product++) {
+
+ for (;;) {
+ if (!strlen(*product))
+ break;
+ toadd = lookupunit(*product);
+ if (!toadd) {
+ printf("unknown unit '%s'\n", *product);
+ return ERROR;
+ }
+ if (strchr(toadd, PRIMITIVECHAR))
+ break;
+ didsomething = 1;
+ if (*product != NULLUNIT) {
+ free(*product);
+ *product = NULLUNIT;
+ }
+ if (addunit(theunit, toadd, flip, 0))
+ return ERROR;
+ }
+ }
+ return didsomething;
+}
+
+
+/*
+ Reduces numerator and denominator of the specified unit.
+ Returns 0 on success, or 1 on unknown unit error.
+*/
+
+static int
+reduceunit(struct unittype * theunit)
+{
+ int ret;
+
+ ret = 1;
+ while (ret & 1) {
+ ret = reduceproduct(theunit, 0) | reduceproduct(theunit, 1);
+ if (ret & 4)
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+compareproducts(char **one, char **two)
+{
+ while (*one || *two) {
+ if (!*one && *two != NULLUNIT)
+ return 1;
+ if (!*two && *one != NULLUNIT)
+ return 1;
+ if (*one == NULLUNIT)
+ one++;
+ else if (*two == NULLUNIT)
+ two++;
+ else if (strcmp(*one, *two))
+ return 1;
+ else {
+ one++;
+ two++;
+ }
+ }
+ return 0;
+}
+
+
+/* Return zero if units are compatible, nonzero otherwise */
+
+static int
+compareunits(struct unittype * first, struct unittype * second)
+{
+ return
+ compareproducts(first->numerator, second->numerator) ||
+ compareproducts(first->denominator, second->denominator);
+}
+
+
+static int
+completereduce(struct unittype * unit)
+{
+ if (reduceunit(unit))
+ return 1;
+ sortunit(unit);
+ cancelunit(unit);
+ return 0;
+}
+
+static void
+showanswer(struct unittype * have, struct unittype * want)
+{
+ double ans;
+ char* oformat;
+
+ if (compareunits(have, want)) {
+ printf("conformability error\n");
+ if (verbose)
+ printf("\t%s = ", havestr);
+ else if (!terse)
+ printf("\t");
+ showunit(have);
+ if (!terse) {
+ if (verbose)
+ printf("\t%s = ", wantstr);
+ else
+ printf("\t");
+ showunit(want);
+ }
+ }
+ else if (have->offset != want->offset) {
+ if (want->quantity)
+ printf("WARNING: conversion of non-proportional quantities.\n");
+ if (have->quantity) {
+ asprintf(&oformat, "\t%s\n", outputformat);
+ printf(oformat,
+ (have->factor + have->offset-want->offset)/want->factor);
+ free(oformat);
+ }
+ else {
+ asprintf(&oformat, "\t (-> x*%sg %sg)\n\t (<- y*%sg %sg)\n",
+ outputformat, outputformat, outputformat, outputformat);
+ printf(oformat,
+ have->factor / want->factor,
+ (have->offset-want->offset)/want->factor,
+ want->factor / have->factor,
+ (want->offset - have->offset)/have->factor);
+ }
+ }
+ else {
+ ans = have->factor / want->factor;
+
+ if (verbose) {
+ printf("\t%s = ", havestr);
+ printf(outputformat, ans);
+ printf(" * %s", wantstr);
+ printf("\n");
+ }
+ else if (terse) {
+ printf(outputformat, ans);
+ printf("\n");
+ }
+ else {
+ printf("\t* ");
+ printf(outputformat, ans);
+ printf("\n");
+ }
+
+ if (verbose) {
+ printf("\t%s = (1 / ", havestr);
+ printf(outputformat, 1/ans);
+ printf(") * %s\n", wantstr);
+ }
+ else if (!terse) {
+ printf("\t/ ");
+ printf(outputformat, 1/ans);
+ printf("\n");
+ }
+ }
+}
+
+
+static void __dead2
+usage(void)
+{
+ fprintf(stderr,
+ "usage: units [-ehqtUVv] [-f unitsfile] [-o format] [from to]\n");
+ exit(3);
+}
+
+static struct option longopts[] = {
+ {"exponential", no_argument, NULL, 'e'},
+ {"file", required_argument, NULL, 'f'},
+ {"history", required_argument, NULL, 'H'},
+ {"help", no_argument, NULL, 'h'},
+ {"output-format", required_argument, NULL, 'o'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"terse", no_argument, NULL, 't'},
+ {"unitsfile", no_argument, NULL, 'U'},
+ {"version", no_argument, NULL, 'V'},
+ {"verbose", no_argument, NULL, 'v'},
+ { 0, 0, 0, 0 }
+};
+
+
+int
+main(int argc, char **argv)
+{
+
+ struct unittype have, want;
+ int optchar;
+ bool quiet;
+ bool readfile;
+ bool quit;
+ History *inhistory;
+ EditLine *el;
+ HistEvent ev;
+ int inputsz;
+
+ quiet = false;
+ readfile = false;
+ outputformat = numfmt;
+ quit = false;
+ while ((optchar = getopt_long(argc, argv, "+ehf:o:qtvH:UV", longopts, NULL)) != -1) {
+ switch (optchar) {
+ case 'e':
+ outputformat = "%6e";
+ break;
+ case 'f':
+ readfile = true;
+ if (strlen(optarg) == 0)
+ readunits(NULL);
+ else
+ readunits(optarg);
+ break;
+ case 'H':
+ /* Ignored, for compatibility with GNU units. */
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 't':
+ terse = true;
+ break;
+ case 'o':
+ outputformat = optarg;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'V':
+ fprintf(stderr, "FreeBSD units\n");
+ /* FALLTHROUGH */
+ case 'U':
+ if (access(UNITSFILE, F_OK) == 0)
+ printf("%s\n", UNITSFILE);
+ else
+ printf("Units data file not found");
+ exit(0);
+ case 'h':
+ /* FALLTHROUGH */
+
+ default:
+ usage();
+ }
+ }
+
+ if (!readfile)
+ readunits(NULL);
+
+ if (optind == argc - 2) {
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ havestr = argv[optind];
+ wantstr = argv[optind + 1];
+ initializeunit(&have);
+ addunit(&have, havestr, 0, 1);
+ completereduce(&have);
+ initializeunit(&want);
+ addunit(&want, wantstr, 0, 1);
+ completereduce(&want);
+ showanswer(&have, &want);
+ } else {
+ inhistory = history_init();
+ el = el_init(argv[0], stdin, stdout, stderr);
+ el_set(el, EL_PROMPT, &prompt);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_SIGNAL, 1);
+ el_set(el, EL_HIST, history, inhistory);
+ el_source(el, NULL);
+ history(inhistory, &ev, H_SETSIZE, 800);
+ if (inhistory == 0)
+ err(1, "Could not initialize history");
+
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ if (!quiet)
+ printf("%d units, %d prefixes\n", unitcount,
+ prefixcount);
+ while (!quit) {
+ do {
+ initializeunit(&have);
+ if (!quiet)
+ promptstr = "You have: ";
+ havestr = el_gets(el, &inputsz);
+ if (havestr == NULL) {
+ quit = true;
+ break;
+ }
+ if (inputsz > 0)
+ history(inhistory, &ev, H_ENTER,
+ havestr);
+ } while (addunit(&have, havestr, 0, 1) ||
+ completereduce(&have));
+ if (quit) {
+ break;
+ }
+ do {
+ initializeunit(&want);
+ if (!quiet)
+ promptstr = "You want: ";
+ wantstr = el_gets(el, &inputsz);
+ if (wantstr == NULL) {
+ quit = true;
+ break;
+ }
+ if (inputsz > 0)
+ history(inhistory, &ev, H_ENTER,
+ wantstr);
+ } while (addunit(&want, wantstr, 0, 1) ||
+ completereduce(&want));
+ if (quit) {
+ break;
+ }
+ showanswer(&have, &want);
+ }
+
+ history_end(inhistory);
+ el_end(el);
+ }
+
+ return (0);
+}
diff --git a/usr.bin/unvis/Makefile b/usr.bin/unvis/Makefile
new file mode 100644
index 000000000000..1189bd1c4ecc
--- /dev/null
+++ b/usr.bin/unvis/Makefile
@@ -0,0 +1,5 @@
+PROG= unvis
+
+.PATH: ${SRCTOP}/contrib/unvis
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/unvis/Makefile.depend b/usr.bin/unvis/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/unvis/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unzip/Makefile b/usr.bin/unzip/Makefile
new file mode 100644
index 000000000000..2db5e9ac4c99
--- /dev/null
+++ b/usr.bin/unzip/Makefile
@@ -0,0 +1,30 @@
+.include <src.opts.mk>
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+_LIBARCHIVECONFDIR= ${SRCTOP}/lib/libarchive
+
+PROG= bsdunzip
+
+BSDUNZIP_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.],,gp;q;}' \
+ ${_LIBARCHIVEDIR}/libarchive/archive.h
+
+.PATH: ${_LIBARCHIVEDIR}/unzip
+SRCS= bsdunzip.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+SRCS+= cmdline.c err.c passphrase.c
+
+CFLAGS+= -DBSDUNZIP_VERSION_STRING=\"${BSDUNZIP_VERSION_STRING}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\"
+CFLAGS+= -I${_LIBARCHIVEDIR}/unzip -I${_LIBARCHIVEDIR}/libarchive_fe
+
+LIBADD= archive
+
+SYMLINKS=bsdunzip ${BINDIR}/unzip
+MLINKS= bsdunzip.1 unzip.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
+# DO NOT DELETE
diff --git a/usr.bin/unzip/Makefile.depend b/usr.bin/unzip/Makefile.depend
new file mode 100644
index 000000000000..850d785a03af
--- /dev/null
+++ b/usr.bin/unzip/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unzip/tests/Makefile b/usr.bin/unzip/tests/Makefile
new file mode 100644
index 000000000000..404a546410e4
--- /dev/null
+++ b/usr.bin/unzip/tests/Makefile
@@ -0,0 +1,75 @@
+PACKAGE= tests
+
+_LIBARCHIVEDIR= ${SRCTOP}/contrib/libarchive
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR= ${TESTSDIR}
+
+PROGS+= bsdunzip_test
+
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+= -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
+
+CFLAGS+= -I${.OBJDIR}
+CFLAGS+= -I${_LIBARCHIVEDIR}/unzip -I${_LIBARCHIVEDIR}/unzip/test
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
+
+# Uncomment to link against dmalloc
+#LDADD+= -L/usr/local/lib -ldmalloc
+#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+
+CFLAGS.test_utils.c+= -Wno-cast-align
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+UNZIP_SRCS+= err.c
+
+.PATH: ${_LIBARCHIVEDIR}/unzip/test
+TESTS_SRCS= \
+ test_0.c \
+ test_C.c \
+ test_I.c \
+ test_L.c \
+ test_P_encryption.c \
+ test_Z1.c \
+ test_basic.c \
+ test_d.c \
+ test_doubledash.c \
+ test_glob.c \
+ test_j.c \
+ test_n.c \
+ test_not_exist.c \
+ test_o.c \
+ test_p.c \
+ test_q.c \
+ test_singlefile.c \
+ test_t.c \
+ test_t_bad.c \
+ test_version.c \
+ test_x.c
+
+SRCS.bsdunzip_test= list.h \
+ ${UNZIP_SRCS} \
+ ${TESTS_SRCS}
+
+.PATH: ${_LIBARCHIVEDIR}/test_utils
+SRCS.bsdunzip_test+= test_main.c \
+ test_utils.c
+
+LIBADD.bsdunzip_test= archive
+
+list.h: ${TESTS_SRCS} Makefile
+ @(cd ${_LIBARCHIVEDIR}/unzip/test && \
+ grep -h DEFINE_TEST ${.ALLSRC:N*Makefile}) > ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+CLEANFILES+= list.h list.h.tmp
+
+${PACKAGE}FILES+= test_I.zip.uu
+${PACKAGE}FILES+= test_basic.zip.uu
+${PACKAGE}FILES+= test_encrypted.zip.uu
+${PACKAGE}FILES+= test_singlefile.zip.uu
+${PACKAGE}FILES+= test_t_bad.zip.uu
+
+.include <bsd.test.mk>
diff --git a/usr.bin/unzip/tests/Makefile.depend b/usr.bin/unzip/tests/Makefile.depend
new file mode 100644
index 000000000000..5f5ceeb3eee7
--- /dev/null
+++ b/usr.bin/unzip/tests/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unzip/tests/functional_test.sh b/usr.bin/unzip/tests/functional_test.sh
new file mode 100755
index 000000000000..e668453d8882
--- /dev/null
+++ b/usr.bin/unzip/tests/functional_test.sh
@@ -0,0 +1,55 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+SRCDIR=$(atf_get_srcdir)
+TESTER="${SRCDIR}/bsdunzip_test"
+export BSDUNZIP=$(which bsdunzip)
+
+check()
+{
+ local testcase=${1}; shift
+
+ # For some odd reason /bin/sh spuriously writes
+ # "write error on stdout" with some of the testcases
+ #
+ # Probably an issue with how they're written as it calls system(3) to
+ # clean up directories..
+ atf_check -e ignore -o ignore -s exit:0 ${TESTER} -d -r "${SRCDIR}" -v "${testcase}"
+}
+
+atf_init_test_cases()
+{
+ # Redirect stderr to stdout for the usage message because if you don't
+ # kyua list/kyua test will break:
+ # https://github.com/jmmv/kyua/issues/149
+ testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }')
+ for testcase in ${testcases}; do
+ atf_test_case ${testcase}
+ eval "${testcase}_body() { check ${testcase}; }"
+ atf_add_test_case ${testcase}
+ done
+}
diff --git a/usr.bin/usbhidaction/Makefile b/usr.bin/usbhidaction/Makefile
new file mode 100644
index 000000000000..623211e73fab
--- /dev/null
+++ b/usr.bin/usbhidaction/Makefile
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile,v 1.4 2002/02/02 16:54:26 veego Exp $
+
+PROG= usbhidaction
+
+LIBADD= usbhid
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/usbhidaction/Makefile.depend b/usr.bin/usbhidaction/Makefile.depend
new file mode 100644
index 000000000000..8059cfc8663f
--- /dev/null
+++ b/usr.bin/usbhidaction/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libusbhid \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/usbhidaction/usbhidaction.1 b/usr.bin/usbhidaction/usbhidaction.1
new file mode 100644
index 000000000000..b5a1826a6147
--- /dev/null
+++ b/usr.bin/usbhidaction/usbhidaction.1
@@ -0,0 +1,172 @@
+.\" $NetBSD: usbhidaction.1,v 1.8 2003/02/25 10:35:59 wiz Exp $
+.\"
+.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Lennart Augustsson (lennart@augustsson.net).
+.\"
+.\" 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 March 14, 2022
+.Dt USBHIDACTION 1
+.Os
+.Sh NAME
+.Nm usbhidaction
+.Nd perform actions according to USB HID controls
+.Sh SYNOPSIS
+.Nm
+.Op Fl diev
+.Fl c Ar config-file
+.Fl f Ar device
+.Op Fl p Ar pidfile
+.Op Fl t Ar tablefile
+.Ar arg ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+can be used to execute commands when certain values appear on HID controls.
+The normal operation for this program is to read the configuration file
+and then become a daemon and execute commands as the HID items specify.
+If a read from the HID device fails, the program dies; this will make it
+die when the USB device is unplugged.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d
+Toggle the daemon flag.
+.It Fl e
+Instruct
+.Nm
+to die early.
+Useful when specified with multiple verbose options to see how files are parsed.
+.It Fl i
+Ignore HID items in the configuration file that do not exist in the device.
+.It Fl v
+Be verbose, and do not become a daemon.
+.It Fl c Ar config-file
+Specify a path name for the configuration file.
+.It Fl t Ar tablefile
+Specify a path name for the HID usage table file.
+.It Fl f Ar device
+Specify a path name for the device to operate on.
+If
+.Ar device
+is numeric, it is taken to be the USB HID device number.
+If it is a relative
+path, it is taken to be the name of the device under
+.Pa /dev .
+An absolute path is taken to be the literal device pathname.
+.It Fl p Ar pidfile
+Specify an alternate file in which to store the process ID.
+.El
+.Pp
+The configuration file will be re-read if the process gets a
+.Dv SIGHUP
+signal.
+.Sh CONFIGURATION
+The configuration file has a very simple format.
+Each line describes an
+action; if a line begins with a whitespace, it is considered a continuation
+of the previous line.
+Lines beginning with
+.Ql #
+are considered as comments.
+.Pp
+Each line has four parts: a name of a USB HID item, a value for that item,
+a debounce value, and an action.
+There must be whitespace between the parts.
+.Pp
+The item names are similar to those used by
+.Xr usbhidctl 1 .
+.Pp
+The value is simply a numeric value.
+When the item reports this value,
+the action will be performed.
+If the value is
+.Ql * ,
+it will match any value.
+.Pp
+The debounce value is an integer not less than 0.
+The value of 0 indicates that no debouncing should occur.
+A value of 1 will only execute the action when the state changes.
+Values greater than one specify that an action should be performed
+only when the value changes by that amount.
+.Pp
+The action is a normal command that is executed with
+.Xr system 3 .
+Before it is executed some substitution will occur:
+.Ql $n
+will be replaced by the
+.Ar n Ns th
+argument on the command line,
+.Ql $V
+will be replaced by the numeric value of the HID item,
+.Ql $N
+will be replaced by the name of the control, and
+.Ql $H
+will be replaced by the name of the HID device.
+.Sh FILES
+.Bl -tag -width ".Pa /usr/share/misc/usb_hid_usages"
+.It Pa /usr/share/misc/usb_hid_usages
+The HID usage table.
+.It Pa /var/run/usbaction.pid
+The default location of the PID file.
+.El
+.Sh EXAMPLES
+The following configuration file can be used to control a pair
+of Philips USB speakers with the HID controls on the speakers.
+.Bd -literal -offset indent
+# Configuration for various Philips USB speakers
+Consumer:Volume_Increment 1 0 mixer -f $1 vol.volume=+1%
+Consumer:Volume_Decrement 1 0 mixer -f $1 vol.volume=-1%
+Consumer:Mute 1 0 mixer -f $1 vol.mute=^
+Consumer:Channel_Top.Microsoft:Base_Up 1 0 mixer -f $1 bass.volume=+1%
+Consumer:Channel_Top.Microsoft:Base_Down 1 0 mixer -f $1 bass.volume=-1%
+.Ed
+.Pp
+A sample invocation using this configuration would be
+.Pp
+.Dl "usbhidaction -f /dev/uhid1 -c conf /dev/mixer1"
+.Pp
+The following example controls the mixer volume using a Logitech Wingman.
+Notice the debounce of 1 for buttons and 5 for the slider.
+.Bd -literal -offset indent
+Button:Button_1 1 1 mixer vol.volume=+10%
+Button:Button_2 1 1 mixer vol.volume=-10%
+Generic_Desktop:Z * 5 mixer vol.volume=`echo $V | awk '{printf("%.02f", $$1/255)}'`
+.Ed
+.Sh SEE ALSO
+.Xr usbhidctl 1 ,
+.Xr usbhid 3 ,
+.Xr uhid 4 ,
+.Xr usb 4
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Nx 1.6 .
+The
+.Nm
+command appeared in
+.Fx 5.1 .
diff --git a/usr.bin/usbhidaction/usbhidaction.c b/usr.bin/usbhidaction/usbhidaction.c
new file mode 100644
index 000000000000..c12adfa81e8a
--- /dev/null
+++ b/usr.bin/usbhidaction/usbhidaction.c
@@ -0,0 +1,519 @@
+/* $NetBSD: usbhidaction.c,v 1.8 2002/06/11 06:06:21 itojun Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson <lennart@augustsson.net>.
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dev/usb/usbhid.h>
+#include <usbhid.h>
+#include <syslog.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+static int verbose = 0;
+static int isdemon = 0;
+static int reparse = 1;
+static const char * pidfile = "/var/run/usbaction.pid";
+
+struct command {
+ struct command *next;
+ int line;
+
+ struct hid_item item;
+ int value;
+ int lastseen;
+ int lastused;
+ int debounce;
+ char anyvalue;
+ char *name;
+ char *action;
+};
+static struct command *commands;
+
+#define SIZE 4000
+
+void usage(void);
+struct command *parse_conf(const char *, report_desc_t, int, int);
+void docmd(struct command *, int, const char *, int, char **);
+void freecommands(struct command *);
+
+static void
+sighup(int sig __unused)
+{
+ reparse = 1;
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *conf = NULL;
+ const char *dev = NULL;
+ const char *table = NULL;
+ int fd, fp, ch, n, val, i;
+ size_t sz, sz1;
+ int demon, ignore, dieearly;
+ report_desc_t repd;
+ char buf[100];
+ char devnamebuf[PATH_MAX];
+ struct command *cmd;
+ int reportid = -1;
+
+ demon = 1;
+ ignore = 0;
+ dieearly = 0;
+ while ((ch = getopt(argc, argv, "c:def:ip:r:t:v")) != -1) {
+ switch(ch) {
+ case 'c':
+ conf = optarg;
+ break;
+ case 'd':
+ demon ^= 1;
+ break;
+ case 'e':
+ dieearly = 1;
+ break;
+ case 'i':
+ ignore++;
+ break;
+ case 'f':
+ dev = optarg;
+ break;
+ case 'p':
+ pidfile = optarg;
+ break;
+ case 'r':
+ reportid = atoi(optarg);
+ break;
+ case 't':
+ table = optarg;
+ break;
+ case 'v':
+ demon = 0;
+ verbose++;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (conf == NULL || dev == NULL)
+ usage();
+
+ hid_init(table);
+
+ if (dev[0] != '/') {
+ snprintf(devnamebuf, sizeof(devnamebuf), "/dev/%s%s",
+ isdigit(dev[0]) ? "uhid" : "", dev);
+ dev = devnamebuf;
+ }
+
+ fd = open(dev, O_RDWR);
+ if (fd < 0)
+ err(1, "%s", dev);
+ repd = hid_get_report_desc(fd);
+ if (repd == NULL)
+ err(1, "hid_get_report_desc() failed");
+
+ commands = parse_conf(conf, repd, reportid, ignore);
+
+ sz = (size_t)hid_report_size(repd, hid_input, -1);
+
+ if (verbose)
+ printf("report size %zu\n", sz);
+ if (sz > sizeof buf)
+ errx(1, "report too large");
+
+ (void)signal(SIGHUP, sighup);
+
+ if (demon) {
+ fp = open(pidfile, O_WRONLY|O_CREAT, S_IRUSR|S_IRGRP|S_IROTH);
+ if (fp < 0)
+ err(1, "%s", pidfile);
+ if (daemon(0, 0) < 0)
+ err(1, "daemon()");
+ snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
+ sz1 = strlen(buf);
+ if (write(fp, buf, sz1) < 0)
+ err(1, "%s", pidfile);
+ close(fp);
+ isdemon = 1;
+ }
+
+ for(;;) {
+ n = read(fd, buf, sz);
+ if (verbose > 2) {
+ printf("read %d bytes:", n);
+ for (i = 0; i < n; i++)
+ printf(" %02x", buf[i]);
+ printf("\n");
+ }
+ if (n < 0) {
+ if (verbose)
+ err(1, "read");
+ else
+ exit(1);
+ }
+#if 0
+ if (n != sz) {
+ err(2, "read size");
+ }
+#endif
+ for (cmd = commands; cmd; cmd = cmd->next) {
+ if (cmd->item.report_ID != 0 &&
+ buf[0] != cmd->item.report_ID)
+ continue;
+ if (cmd->item.flags & HIO_VARIABLE)
+ val = hid_get_data(buf, &cmd->item);
+ else {
+ uint32_t pos = cmd->item.pos;
+ for (i = 0; i < cmd->item.report_count; i++) {
+ val = hid_get_data(buf, &cmd->item);
+ if (val == cmd->value)
+ break;
+ cmd->item.pos += cmd->item.report_size;
+ }
+ cmd->item.pos = pos;
+ val = (i < cmd->item.report_count) ?
+ cmd->value : -1;
+ }
+ if (cmd->value != val && cmd->anyvalue == 0)
+ goto next;
+ if ((cmd->debounce == 0) ||
+ ((cmd->debounce == 1) && ((cmd->lastseen == -1) ||
+ (cmd->lastseen != val)))) {
+ docmd(cmd, val, dev, argc, argv);
+ goto next;
+ }
+ if ((cmd->debounce > 1) &&
+ ((cmd->lastused == -1) ||
+ (abs(cmd->lastused - val) >= cmd->debounce))) {
+ docmd(cmd, val, dev, argc, argv);
+ cmd->lastused = val;
+ goto next;
+ }
+next:
+ cmd->lastseen = val;
+ }
+
+ if (dieearly)
+ exit(0);
+
+ if (reparse) {
+ struct command *cmds =
+ parse_conf(conf, repd, reportid, ignore);
+ if (cmds) {
+ freecommands(commands);
+ commands = cmds;
+ }
+ reparse = 0;
+ }
+ }
+
+ exit(0);
+}
+
+void
+usage(void)
+{
+
+ fprintf(stderr, "Usage: %s [-deiv] -c config_file -f hid_dev "
+ "[-p pidfile] [-t tablefile]\n", getprogname());
+ exit(1);
+}
+
+static int
+peek(FILE *f)
+{
+ int c;
+
+ c = getc(f);
+ if (c != EOF)
+ ungetc(c, f);
+ return c;
+}
+
+struct command *
+parse_conf(const char *conf, report_desc_t repd, int reportid, int ignore)
+{
+ FILE *f;
+ char *p;
+ int line;
+ char buf[SIZE], name[SIZE], value[SIZE], debounce[SIZE], action[SIZE];
+ char usbuf[SIZE], coll[SIZE], *tmp;
+ struct command *cmd, *cmds;
+ struct hid_data *d;
+ struct hid_item h;
+ int inst, cinst, u, lo, hi, range, t;
+
+ f = fopen(conf, "r");
+ if (f == NULL)
+ err(1, "%s", conf);
+
+ cmds = NULL;
+ for (line = 1; ; line++) {
+ if (fgets(buf, sizeof buf, f) == NULL)
+ break;
+ if (buf[0] == '#' || buf[0] == '\n')
+ continue;
+ p = strchr(buf, '\n');
+ while (p && isspace(peek(f))) {
+ if (fgets(p, sizeof buf - strlen(buf), f) == NULL)
+ break;
+ p = strchr(buf, '\n');
+ }
+ if (p)
+ *p = 0;
+ if (sscanf(buf, "%s %s %s %[^\n]",
+ name, value, debounce, action) != 4) {
+ if (isdemon) {
+ syslog(LOG_WARNING, "config file `%s', line %d"
+ ", syntax error: %s", conf, line, buf);
+ freecommands(cmds);
+ return (NULL);
+ } else {
+ errx(1, "config file `%s', line %d,"
+ ", syntax error: %s", conf, line, buf);
+ }
+ }
+ tmp = strchr(name, '#');
+ if (tmp != NULL) {
+ *tmp = 0;
+ inst = atoi(tmp + 1);
+ } else
+ inst = 0;
+
+ cmd = malloc(sizeof *cmd);
+ if (cmd == NULL)
+ err(1, "malloc failed");
+ cmd->next = cmds;
+ cmds = cmd;
+ cmd->line = line;
+
+ if (strcmp(value, "*") == 0) {
+ cmd->anyvalue = 1;
+ } else {
+ cmd->anyvalue = 0;
+ if (sscanf(value, "%d", &cmd->value) != 1) {
+ if (isdemon) {
+ syslog(LOG_WARNING,
+ "config file `%s', line %d, "
+ "bad value: %s (should be * or a number)\n",
+ conf, line, value);
+ freecommands(cmds);
+ return (NULL);
+ } else {
+ errx(1, "config file `%s', line %d, "
+ "bad value: %s (should be * or a number)\n",
+ conf, line, value);
+ }
+ }
+ }
+
+ if (sscanf(debounce, "%d", &cmd->debounce) != 1) {
+ if (isdemon) {
+ syslog(LOG_WARNING,
+ "config file `%s', line %d, "
+ "bad value: %s (should be a number >= 0)\n",
+ conf, line, debounce);
+ freecommands(cmds);
+ return (NULL);
+ } else {
+ errx(1, "config file `%s', line %d, "
+ "bad value: %s (should be a number >= 0)\n",
+ conf, line, debounce);
+ }
+ }
+
+ coll[0] = 0;
+ cinst = 0;
+ for (d = hid_start_parse(repd, 1 << hid_input, reportid);
+ hid_get_item(d, &h); ) {
+ if (verbose > 2)
+ printf("kind=%d usage=%x\n", h.kind, h.usage);
+ if (h.flags & HIO_CONST)
+ continue;
+ switch (h.kind) {
+ case hid_input:
+ if (h.usage_minimum != 0 ||
+ h.usage_maximum != 0) {
+ lo = h.usage_minimum;
+ hi = h.usage_maximum;
+ range = 1;
+ } else {
+ lo = h.usage;
+ hi = h.usage;
+ range = 0;
+ }
+ for (u = lo; u <= hi; u++) {
+ if (coll[0]) {
+ snprintf(usbuf, sizeof usbuf,
+ "%s.%s:%s", coll+1,
+ hid_usage_page(HID_PAGE(u)),
+ hid_usage_in_page(u));
+ } else {
+ snprintf(usbuf, sizeof usbuf,
+ "%s:%s",
+ hid_usage_page(HID_PAGE(u)),
+ hid_usage_in_page(u));
+ }
+ if (verbose > 2)
+ printf("usage %s\n", usbuf);
+ t = strlen(usbuf) - strlen(name);
+ if (t > 0) {
+ if (strcmp(usbuf + t, name))
+ continue;
+ if (usbuf[t - 1] != '.')
+ continue;
+ } else if (strcmp(usbuf, name))
+ continue;
+ if (inst == cinst++)
+ goto foundhid;
+ }
+ break;
+ case hid_collection:
+ snprintf(coll + strlen(coll),
+ sizeof coll - strlen(coll), ".%s:%s",
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ break;
+ case hid_endcollection:
+ if (coll[0])
+ *strrchr(coll, '.') = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ if (ignore) {
+ if (verbose)
+ warnx("ignore item '%s'", name);
+ continue;
+ }
+ if (isdemon) {
+ syslog(LOG_WARNING, "config file `%s', line %d, HID "
+ "item not found: `%s'\n", conf, line, name);
+ freecommands(cmds);
+ return (NULL);
+ } else {
+ errx(1, "config file `%s', line %d, HID item "
+ "not found: `%s'\n", conf, line, name);
+ }
+
+ foundhid:
+ hid_end_parse(d);
+ cmd->lastseen = -1;
+ cmd->lastused = -1;
+ cmd->item = h;
+ cmd->name = strdup(name);
+ cmd->action = strdup(action);
+ if (range) {
+ if (cmd->value == 1)
+ cmd->value = u - lo;
+ else
+ cmd->value = -1;
+ }
+
+ if (verbose)
+ printf("PARSE:%d %s, %d, '%s'\n", cmd->line, name,
+ cmd->value, cmd->action);
+ }
+ fclose(f);
+ return (cmds);
+}
+
+void
+docmd(struct command *cmd, int value, const char *hid, int argc, char **argv)
+{
+ char cmdbuf[SIZE], *p, *q;
+ size_t len;
+ int n, r;
+
+ for (p = cmd->action, q = cmdbuf; *p && q < &cmdbuf[SIZE-1]; ) {
+ if (*p == '$') {
+ p++;
+ len = &cmdbuf[SIZE-1] - q;
+ if (isdigit(*p)) {
+ n = strtol(p, &p, 10) - 1;
+ if (n >= 0 && n < argc) {
+ strncpy(q, argv[n], len);
+ q += strlen(q);
+ }
+ } else if (*p == 'V') {
+ p++;
+ snprintf(q, len, "%d", value);
+ q += strlen(q);
+ } else if (*p == 'N') {
+ p++;
+ strncpy(q, cmd->name, len);
+ q += strlen(q);
+ } else if (*p == 'H') {
+ p++;
+ strncpy(q, hid, len);
+ q += strlen(q);
+ } else if (*p) {
+ *q++ = *p++;
+ }
+ } else {
+ *q++ = *p++;
+ }
+ }
+ *q = 0;
+
+ if (verbose)
+ printf("system '%s'\n", cmdbuf);
+ r = system(cmdbuf);
+ if (verbose > 1 && r)
+ printf("return code = 0x%x\n", r);
+}
+
+void
+freecommands(struct command *cmd)
+{
+ struct command *next;
+
+ while (cmd) {
+ next = cmd->next;
+ free(cmd);
+ cmd = next;
+ }
+}
diff --git a/usr.bin/usbhidctl/Makefile b/usr.bin/usbhidctl/Makefile
new file mode 100644
index 000000000000..a96b2bd7e661
--- /dev/null
+++ b/usr.bin/usbhidctl/Makefile
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile,v 1.4 1999/05/11 21:02:25 augustss Exp $
+
+PROG= usbhidctl
+SRCS= usbhid.c
+
+LIBADD= usbhid
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/usbhidctl/Makefile.depend b/usr.bin/usbhidctl/Makefile.depend
new file mode 100644
index 000000000000..8059cfc8663f
--- /dev/null
+++ b/usr.bin/usbhidctl/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libusbhid \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/usbhidctl/usbhid.c b/usr.bin/usbhidctl/usbhid.c
new file mode 100644
index 000000000000..dbb05030e908
--- /dev/null
+++ b/usr.bin/usbhidctl/usbhid.c
@@ -0,0 +1,532 @@
+/* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@netbsd.org).
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <ctype.h>
+#include <errno.h>
+#include <usbhid.h>
+#include <dev/usb/usbhid.h>
+
+static struct variable {
+ char *name;
+ int instance;
+ int val;
+ struct hid_item h;
+ struct variable *next;
+} *vars;
+
+static int verbose = 0;
+static int noname = 0;
+static int hexdump = 0;
+static int wflag = 0;
+static int zflag = 0;
+
+static void usage(void) __dead2;
+static void dumpitem(const char *label, struct hid_item *h);
+static void dumpitems(report_desc_t r);
+static void prdata(u_char *buf, struct hid_item *h);
+static void dumpdata(int f, report_desc_t r, int loop);
+static void writedata(int f, report_desc_t r);
+
+static void
+parceargs(report_desc_t r, int all, int nnames, char **names)
+{
+ struct hid_data *d;
+ struct hid_item h;
+ char colls[1000];
+ char hname[1000], *tmp1, *tmp2;
+ struct variable *var, **pnext;
+ int i, instance, cp, t;
+
+ pnext = &vars;
+ if (all) {
+ if (wflag)
+ errx(1, "Must not specify -w to read variables");
+ cp = 0;
+ for (d = hid_start_parse(r,
+ 1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
+ hid_get_item(d, &h); ) {
+ if (h.kind == hid_collection) {
+ cp += sprintf(&colls[cp], "%s%s:%s",
+ cp != 0 ? "." : "",
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ } else if (h.kind == hid_endcollection) {
+ tmp1 = strrchr(colls, '.');
+ if (tmp1 != NULL) {
+ cp -= strlen(tmp1);
+ tmp1[0] = 0;
+ } else {
+ cp = 0;
+ colls[0] = 0;
+ }
+ }
+ if ((h.kind != hid_input && h.kind != hid_output &&
+ h.kind != hid_feature) || (h.flags & HIO_CONST))
+ continue;
+ var = malloc(sizeof(*var));
+ memset(var, 0, sizeof(*var));
+ asprintf(&var->name, "%s%s%s:%s",
+ colls, colls[0] != 0 ? "." : "",
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ var->h = h;
+ *pnext = var;
+ pnext = &var->next;
+ }
+ hid_end_parse(d);
+ return;
+ }
+ for (i = 0; i < nnames; i++) {
+ var = malloc(sizeof(*var));
+ memset(var, 0, sizeof(*var));
+ tmp1 = tmp2 = strdup(names[i]);
+ strsep(&tmp2, "=");
+ var->name = strsep(&tmp1, "#");
+ if (tmp1 != NULL)
+ var->instance = atoi(tmp1);
+ if (tmp2 != NULL) {
+ if (!wflag)
+ errx(1, "Must specify -w to write variables");
+ var->val = atoi(tmp2);
+ } else
+ if (wflag)
+ errx(1, "Must not specify -w to read variables");
+ *pnext = var;
+ pnext = &var->next;
+
+ instance = 0;
+ cp = 0;
+ for (d = hid_start_parse(r,
+ 1<<hid_input | 1<<hid_output | 1<<hid_feature, -1);
+ hid_get_item(d, &h); ) {
+ if (h.kind == hid_collection) {
+ cp += sprintf(&colls[cp], "%s%s:%s",
+ cp != 0 ? "." : "",
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ } else if (h.kind == hid_endcollection) {
+ tmp1 = strrchr(colls, '.');
+ if (tmp1 != NULL) {
+ cp -= strlen(tmp1);
+ tmp1[0] = 0;
+ } else {
+ cp = 0;
+ colls[0] = 0;
+ }
+ }
+ if ((h.kind != hid_input && h.kind != hid_output &&
+ h.kind != hid_feature) || (h.flags & HIO_CONST))
+ continue;
+ snprintf(hname, sizeof(hname), "%s%s%s:%s",
+ colls, colls[0] != 0 ? "." : "",
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ t = strlen(hname) - strlen(var->name);
+ if (t > 0) {
+ if (strcmp(hname + t, var->name) != 0)
+ continue;
+ if (hname[t - 1] != '.')
+ continue;
+ } else if (strcmp(hname, var->name) != 0)
+ continue;
+ if (var->instance != instance++)
+ continue;
+ var->h = h;
+ break;
+ }
+ hid_end_parse(d);
+ if (var->h.usage == 0)
+ errx(1, "Unknown item '%s'", var->name);
+ }
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: %s -f device "
+ "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] name ...\n",
+ getprogname());
+ fprintf(stderr,
+ " %s -f device "
+ "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] -a\n",
+ getprogname());
+ fprintf(stderr,
+ " %s -f device "
+ "[-t tablefile] [-v] [-z] -w name=value\n",
+ getprogname());
+ exit(1);
+}
+
+static void
+dumpitem(const char *label, struct hid_item *h)
+{
+ if ((h->flags & HIO_CONST) && !verbose)
+ return;
+ printf("%s rid=%d pos=%d size=%d count=%d page=%s usage=%s%s%s", label,
+ h->report_ID, h->pos, h->report_size, h->report_count,
+ hid_usage_page(HID_PAGE(h->usage)),
+ hid_usage_in_page(h->usage),
+ h->flags & HIO_CONST ? " Const" : "",
+ h->flags & HIO_VARIABLE ? "" : " Array");
+ printf(", logical range %d..%d",
+ h->logical_minimum, h->logical_maximum);
+ if (h->physical_minimum != h->physical_maximum)
+ printf(", physical range %d..%d",
+ h->physical_minimum, h->physical_maximum);
+ if (h->unit)
+ printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent);
+ printf("\n");
+}
+
+static const char *
+hid_collection_type(int32_t type)
+{
+ static char num[8];
+
+ switch (type) {
+ case 0: return ("Physical");
+ case 1: return ("Application");
+ case 2: return ("Logical");
+ case 3: return ("Report");
+ case 4: return ("Named_Array");
+ case 5: return ("Usage_Switch");
+ case 6: return ("Usage_Modifier");
+ }
+ snprintf(num, sizeof(num), "0x%02x", type);
+ return (num);
+}
+
+static void
+dumpitems(report_desc_t r)
+{
+ struct hid_data *d;
+ struct hid_item h;
+ int size;
+
+ for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) {
+ switch (h.kind) {
+ case hid_collection:
+ printf("Collection type=%s page=%s usage=%s\n",
+ hid_collection_type(h.collection),
+ hid_usage_page(HID_PAGE(h.usage)),
+ hid_usage_in_page(h.usage));
+ break;
+ case hid_endcollection:
+ printf("End collection\n");
+ break;
+ case hid_input:
+ dumpitem("Input ", &h);
+ break;
+ case hid_output:
+ dumpitem("Output ", &h);
+ break;
+ case hid_feature:
+ dumpitem("Feature", &h);
+ break;
+ }
+ }
+ hid_end_parse(d);
+ size = hid_report_size(r, hid_input, -1);
+ printf("Total input size %d bytes\n", size);
+
+ size = hid_report_size(r, hid_output, -1);
+ printf("Total output size %d bytes\n", size);
+
+ size = hid_report_size(r, hid_feature, -1);
+ printf("Total feature size %d bytes\n", size);
+}
+
+static void
+prdata(u_char *buf, struct hid_item *h)
+{
+ u_int data;
+ int i, pos;
+
+ pos = h->pos;
+ for (i = 0; i < h->report_count; i++) {
+ data = hid_get_data(buf, h);
+ if (i > 0)
+ printf(" ");
+ if (h->logical_minimum < 0)
+ printf("%d", (int)data);
+ else
+ printf("%u", data);
+ if (hexdump)
+ printf(" [0x%x]", data);
+ h->pos += h->report_size;
+ }
+ h->pos = pos;
+}
+
+static void
+dumpdata(int f, report_desc_t rd, int loop)
+{
+ struct variable *var;
+ int dlen, havedata, i, match, r, rid, use_rid;
+ u_char *dbuf;
+ enum hid_kind kind;
+
+ kind = zflag ? 3 : 0;
+ rid = -1;
+ use_rid = !!hid_get_report_id(f);
+ do {
+ if (kind < 3) {
+ if (++rid >= 256) {
+ rid = 0;
+ kind++;
+ }
+ if (kind >= 3)
+ rid = -1;
+ for (var = vars; var; var = var->next) {
+ if (rid == var->h.report_ID &&
+ kind == var->h.kind)
+ break;
+ }
+ if (var == NULL)
+ continue;
+ }
+ dlen = hid_report_size(rd, kind < 3 ? kind : hid_input, rid);
+ if (dlen <= 0)
+ continue;
+ dbuf = malloc(dlen);
+ memset(dbuf, 0, dlen);
+ if (kind < 3) {
+ dbuf[0] = rid;
+ r = hid_get_report(f, kind, dbuf, dlen);
+ if (r < 0)
+ warn("hid_get_report(rid %d)", rid);
+ havedata = !r && (rid == 0 || dbuf[0] == rid);
+ if (rid != 0)
+ dbuf[0] = rid;
+ } else {
+ r = read(f, dbuf, dlen);
+ if (r < 1)
+ err(1, "read error");
+ havedata = 1;
+ }
+ if (verbose) {
+ printf("Got %s report %d (%d bytes):",
+ kind == hid_output ? "output" :
+ kind == hid_feature ? "feature" : "input",
+ use_rid ? dbuf[0] : 0, dlen);
+ if (havedata) {
+ for (i = 0; i < dlen; i++)
+ printf(" %02x", dbuf[i]);
+ }
+ printf("\n");
+ }
+ match = 0;
+ for (var = vars; var; var = var->next) {
+ if ((kind < 3 ? kind : hid_input) != var->h.kind)
+ continue;
+ if (var->h.report_ID != 0 &&
+ dbuf[0] != var->h.report_ID)
+ continue;
+ match = 1;
+ if (!noname)
+ printf("%s=", var->name);
+ if (havedata)
+ prdata(dbuf, &var->h);
+ printf("\n");
+ }
+ if (match)
+ printf("\n");
+ free(dbuf);
+ } while (loop || kind < 3);
+}
+
+static void
+writedata(int f, report_desc_t rd)
+{
+ struct variable *var;
+ int dlen, i, r, rid;
+ u_char *dbuf;
+ enum hid_kind kind;
+
+ kind = 0;
+ rid = 0;
+ for (kind = 0; kind < 3; kind ++) {
+ for (rid = 0; rid < 256; rid ++) {
+ for (var = vars; var; var = var->next) {
+ if (rid == var->h.report_ID && kind == var->h.kind)
+ break;
+ }
+ if (var == NULL)
+ continue;
+ dlen = hid_report_size(rd, kind, rid);
+ if (dlen <= 0)
+ continue;
+ dbuf = malloc(dlen);
+ memset(dbuf, 0, dlen);
+ dbuf[0] = rid;
+ if (!zflag && hid_get_report(f, kind, dbuf, dlen) == 0) {
+ if (verbose) {
+ printf("Got %s report %d (%d bytes):",
+ kind == hid_input ? "input" :
+ kind == hid_output ? "output" : "feature",
+ rid, dlen);
+ for (i = 0; i < dlen; i++)
+ printf(" %02x", dbuf[i]);
+ printf("\n");
+ }
+ } else if (!zflag) {
+ warn("hid_get_report(rid %d)", rid);
+ if (verbose) {
+ printf("Can't get %s report %d (%d bytes). "
+ "Will be initialized with zeros.\n",
+ kind == hid_input ? "input" :
+ kind == hid_output ? "output" : "feature",
+ rid, dlen);
+ }
+ }
+ for (var = vars; var; var = var->next) {
+ if (rid != var->h.report_ID || kind != var->h.kind)
+ continue;
+ hid_set_data(dbuf, &var->h, var->val);
+ }
+ if (verbose) {
+ printf("Setting %s report %d (%d bytes):",
+ kind == hid_output ? "output" :
+ kind == hid_feature ? "feature" : "input",
+ rid, dlen);
+ for (i = 0; i < dlen; i++)
+ printf(" %02x", dbuf[i]);
+ printf("\n");
+ }
+ r = hid_set_report(f, kind, dbuf, dlen);
+ if (r != 0)
+ warn("hid_set_report(rid %d)", rid);
+ free(dbuf);
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ report_desc_t r;
+ char *table = 0;
+ char devnam[100], *dev = NULL;
+ int f;
+ int all = 0;
+ int ch;
+ int repdump = 0;
+ int loop = 0;
+
+ while ((ch = getopt(argc, argv, "af:lnrt:vwxz")) != -1) {
+ switch(ch) {
+ case 'a':
+ all++;
+ break;
+ case 'f':
+ dev = optarg;
+ break;
+ case 'l':
+ loop ^= 1;
+ break;
+ case 'n':
+ noname++;
+ break;
+ case 'r':
+ repdump++;
+ break;
+ case 't':
+ table = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'w':
+ wflag = 1;
+ break;
+ case 'x':
+ hexdump = 1;
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (dev == NULL)
+ usage();
+
+ if (argc == 0 && !all && !repdump)
+ usage();
+
+ if (dev[0] != '/') {
+ if (isdigit(dev[0]))
+ snprintf(devnam, sizeof(devnam), "/dev/uhid%s", dev);
+ else
+ snprintf(devnam, sizeof(devnam), "/dev/%s", dev);
+ dev = devnam;
+ }
+
+ hid_init(table);
+
+ f = open(dev, O_RDWR);
+ if (f < 0)
+ err(1, "%s", dev);
+
+ r = hid_get_report_desc(f);
+ if (r == 0)
+ errx(1, "USB_GET_REPORT_DESC");
+
+ if (repdump) {
+ printf("Report descriptor:\n");
+ dumpitems(r);
+ }
+ if (argc != 0 || all) {
+ parceargs(r, all, argc, argv);
+ if (wflag)
+ writedata(f, r);
+ else
+ dumpdata(f, r, loop);
+ }
+
+ hid_dispose_report_desc(r);
+ exit(0);
+}
diff --git a/usr.bin/usbhidctl/usbhidctl.1 b/usr.bin/usbhidctl/usbhidctl.1
new file mode 100644
index 000000000000..d1cbe67ba85c
--- /dev/null
+++ b/usr.bin/usbhidctl/usbhidctl.1
@@ -0,0 +1,150 @@
+.\" $NetBSD: usbhidctl.1,v 1.8 1999/05/11 21:03:58 augustss Exp $
+.\"
+.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Lennart Augustsson.
+.\"
+.\" 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 1, 2011
+.Dt USBHIDCTL 1
+.Os
+.Sh NAME
+.Nm usbhidctl
+.Nd manipulate USB HID devices
+.Sh SYNOPSIS
+.Nm
+.Fl f Ar device
+.Op Fl t Ar table
+.Op Fl v
+.Op Fl x
+.Fl r
+.Nm
+.Fl f Ar device
+.Op Fl t Ar table
+.Op Fl l
+.Op Fl v
+.Op Fl x
+.Op Fl z
+.Fl a
+.Nm
+.Fl f Ar device
+.Op Fl t Ar table
+.Op Fl l
+.Op Fl n
+.Op Fl v
+.Op Fl x
+.Op Fl z
+.Ar item ...
+.Nm
+.Fl f Ar device
+.Op Fl t Ar table
+.Op Fl v
+.Op Fl z
+.Fl w
+.Ar item=value ...
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to dump and modify the state of a USB HID (Human
+Interface Device).
+Each named
+.Ar item
+is printed.
+If the
+.Fl w
+flag is specified
+.Nm
+attempts to set the specified items to the given values.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Show all items and their current values if device returns.
+.It Fl f Ar device
+Specify a path name for the device to operate on.
+.It Fl l
+Loop and dump the device data every time it changes.
+.It Fl n
+Suppress printing of the item name.
+.It Fl r
+Dump the report descriptor.
+.It Fl t Ar table
+Specify a path name for the HID usage table file.
+.It Fl v
+Be verbose.
+.It Fl w
+Change item values.
+Only 'output' and 'feature' kinds can be set with this option.
+.It Fl x
+Dump data in hexadecimal as well as decimal.
+.It Fl z
+Reset reports to zero before processing other arguments.
+If not specified, current values will be requested from device.
+.El
+.Sh SYNTAX
+.Nm
+compares the names of items specified on the command line against the human
+interface items reported by the USB device.
+Each human interface item is mapped from its native form to a human readable
+name, using the HID usage table file.
+Command line items are compared with the generated item names,
+and the USB HID device is operated on when a match is found.
+.Pp
+Each human interface item is named by the
+.Qq page
+it appears in, the
+.Qq usage
+within that page, and the list of
+.Qq collections
+containing the item.
+Each collection in turn is also identified by page, and
+the usage within that page.
+.Pp
+On the
+.Nm
+command line the page name is separated from the usage name with the character
+.Sq Cm \&: .
+The collections are separated by the character
+.Sq Cm \&. .
+.Pp
+Some devices give the same name to more than one item.
+.Nm
+supports isolating each item by appending a
+.Sq Cm \&# .
+character and a decimal item instance number, starting at zero.
+.Sh FILES
+.Bl -tag -width 30n
+.It Pa /usr/share/misc/usb_hid_usages
+The default HID usage table.
+.El
+.Sh SEE ALSO
+.Xr usbhid 3 ,
+.Xr uhid 4 ,
+.Xr usb 4
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Nx 1.4 .
diff --git a/usr.bin/users/Makefile b/usr.bin/users/Makefile
new file mode 100644
index 000000000000..dfaf41dc2857
--- /dev/null
+++ b/usr.bin/users/Makefile
@@ -0,0 +1,6 @@
+WARNS?= 3
+PROG_CXX= users
+PACKAGE= acct
+CXXFLAGS+= -fno-rtti
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/users/Makefile.depend b/usr.bin/users/Makefile.depend
new file mode 100644
index 000000000000..622fa64736eb
--- /dev/null
+++ b/usr.bin/users/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libc++ \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+ lib/libcxxrt \
+ lib/msun \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/users/users.1 b/usr.bin/users/users.1
new file mode 100644
index 000000000000..48448f375b5f
--- /dev/null
+++ b/usr.bin/users/users.1
@@ -0,0 +1,54 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd January 21, 2010
+.Dt USERS 1
+.Os
+.Sh NAME
+.Nm users
+.Nd list current users
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility lists the login names of the users currently on the system,
+in sorted order, space separated, on a single line.
+.Sh FILES
+.Bl -tag -width /var/run/utx.active
+.It Pa /var/run/utx.active
+.El
+.Sh SEE ALSO
+.Xr finger 1 ,
+.Xr last 1 ,
+.Xr who 1 ,
+.Xr getutxent 3
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/users/users.cc b/usr.bin/users/users.cc
new file mode 100644
index 000000000000..76e09db12c08
--- /dev/null
+++ b/usr.bin/users/users.cc
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2014 Pietro Cerutti <gahr@FreeBSD.org>
+ * 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/capsicum.h>
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <errno.h>
+#include <utmpx.h>
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <set>
+#include <string>
+using namespace std;
+
+int
+main(int argc, char **)
+{
+ struct utmpx *ut;
+ set<string> names;
+
+ if (argc > 1) {
+ cerr << "usage: users" << endl;
+ return (1);
+ }
+
+ setutxent();
+
+ if (caph_enter())
+ err(1, "Failed to enter capability mode.");
+
+ while ((ut = getutxent()) != NULL)
+ if (ut->ut_type == USER_PROCESS)
+ names.insert(ut->ut_user);
+ endutxent();
+
+ if (!names.empty()) {
+ set<string>::iterator last = names.end();
+ --last;
+ copy(names.begin(), last, ostream_iterator<string>(cout, " "));
+ cout << *last << endl;
+ }
+}
diff --git a/usr.bin/vacation/Makefile b/usr.bin/vacation/Makefile
new file mode 100644
index 000000000000..db69e1d6cb80
--- /dev/null
+++ b/usr.bin/vacation/Makefile
@@ -0,0 +1,28 @@
+SENDMAIL_DIR=${SRCTOP}/contrib/sendmail
+.PATH: ${SENDMAIL_DIR}/vacation
+
+PROG= vacation
+SRCS= vacation.c
+CFLAGS+=-I${SENDMAIL_DIR}/src -I${SENDMAIL_DIR}/include -I.
+CFLAGS+=-DNEWDB -DNOT_SENDMAIL
+CFLAGS+=-D_FFR_LISTDB -D_FFR_DEBUG
+
+WARNS?= 2
+
+LIBADD= smdb smutil sm
+
+SRCS+= sm_os.h
+CLEANFILES+=sm_os.h
+
+# User customizations to the sendmail build environment
+CFLAGS+=${SENDMAIL_CFLAGS}
+DPADD+=${SENDMAIL_DPADD}
+LDADD+=${SENDMAIL_LDADD}
+LDFLAGS+=${SENDMAIL_LDFLAGS}
+
+sm_os.h: ${SENDMAIL_DIR}/include/sm/os/sm_os_freebsd.h .NOMETA
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.include <bsd.prog.mk>
+
+CWARNFLAGS+= ${NO_WDEPRECATED_NON_PROTOTYPE}
diff --git a/usr.bin/vacation/Makefile.depend b/usr.bin/vacation/Makefile.depend
new file mode 100644
index 000000000000..ec81c06f90f1
--- /dev/null
+++ b/usr.bin/vacation/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsm \
+ lib/libsmdb \
+ lib/libsmutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vgrind/Makefile b/usr.bin/vgrind/Makefile
new file mode 100644
index 000000000000..6ab148768aa6
--- /dev/null
+++ b/usr.bin/vgrind/Makefile
@@ -0,0 +1,24 @@
+PROG= vfontedpr
+SRCS= regexp.c vfontedpr.c
+SCRIPTS=vgrind.sh
+FILES= vgrindefs.src vgrindefs.src.db tmac.vgrind
+FILESNAME_vgrindefs.src= vgrindefs
+FILESNAME_vgrindefs.src.db= vgrindefs.db
+FILESDIR= ${SHAREDIR}/misc
+FILESDIR_tmac.vgrind= ${SHAREDIR}/tmac
+MAN= vgrind.1 vgrindefs.5
+
+WARNS?= 3
+
+BINDIR= ${LIBEXECDIR}
+SCRIPTSDIR=/usr/bin
+
+CLEANFILES= vgrindefs.src.db
+
+.include <bsd.endian.mk>
+.include <src.tools.mk>
+
+vgrindefs.src.db: vgrindefs.src
+ ${CAP_MKDB_CMD} ${CAP_MKDB_ENDIAN} -f vgrindefs.src ${.ALLSRC}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vgrind/Makefile.depend b/usr.bin/vgrind/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/vgrind/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vgrind/extern.h b/usr.bin/vgrind/extern.h
new file mode 100644
index 000000000000..a6d4331ef7f2
--- /dev/null
+++ b/usr.bin/vgrind/extern.h
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+extern bool _escaped; /* if last character was an escape */
+extern char *s_start; /* start of the current string */
+extern char *l_acmbeg; /* string introducing a comment */
+extern char *l_acmend; /* string ending a comment */
+extern char *l_blkbeg; /* string beginning of a block */
+extern char *l_blkend; /* string ending a block */
+extern char *l_chrbeg; /* delimiter for character constant */
+extern char *l_chrend; /* delimiter for character constant */
+extern char *l_combeg; /* string introducing a comment */
+extern char *l_comend; /* string ending a comment */
+extern char l_escape; /* character used to escape characters */
+extern char *l_keywds[]; /* keyword table address */
+extern bool l_onecase; /* upper and lower case are equivalent */
+extern char *l_prcbeg; /* regular expr for procedure begin */
+extern char *l_strbeg; /* delimiter for string constant */
+extern char *l_strend; /* delimiter for string constant */
+extern bool l_toplex; /* procedures only defined at top lex level */
+extern const char *language; /* the language indicator */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int STRNCMP(char *, char *, int);
+extern char *convexp(char *);
+extern char *expmatch(char *, char *, char *);
+__END_DECLS
+
diff --git a/usr.bin/vgrind/pathnames.h b/usr.bin/vgrind/pathnames.h
new file mode 100644
index 000000000000..597abd21eeb6
--- /dev/null
+++ b/usr.bin/vgrind/pathnames.h
@@ -0,0 +1,32 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_VGRINDEFS "/usr/share/misc/vgrindefs"
diff --git a/usr.bin/vgrind/regexp.c b/usr.bin/vgrind/regexp.c
new file mode 100644
index 000000000000..0cd616569ae2
--- /dev/null
+++ b/usr.bin/vgrind/regexp.c
@@ -0,0 +1,584 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "extern.h"
+
+static void expconv(void);
+
+bool _escaped; /* true if we are currently x_escaped */
+char *s_start; /* start of string */
+bool l_onecase; /* true if upper and lower equivalent */
+
+#define makelower(c) (isupper((c)) ? tolower((c)) : (c))
+
+/* STRNCMP - like strncmp except that we convert the
+ * first string to lower case before comparing
+ * if l_onecase is set.
+ */
+
+int
+STRNCMP(register char *s1, register char *s2, register int len)
+{
+ if (l_onecase) {
+ do
+ if (*s2 - makelower(*s1))
+ return (*s2 - makelower(*s1));
+ else {
+ s2++;
+ s1++;
+ }
+ while (--len);
+ } else {
+ do
+ if (*s2 - *s1)
+ return (*s2 - *s1);
+ else {
+ s2++;
+ s1++;
+ }
+ while (--len);
+ }
+ return(0);
+}
+
+/* The following routine converts an irregular expression to
+ * internal format.
+ *
+ * Either meta symbols (\a \d or \p) or character strings or
+ * operations ( alternation or parenthesizing ) can be
+ * specified. Each starts with a descriptor byte. The descriptor
+ * byte has STR set for strings, META set for meta symbols
+ * and OPER set for operations.
+ * The descriptor byte can also have the OPT bit set if the object
+ * defined is optional. Also ALT can be set to indicate an alternation.
+ *
+ * For metasymbols the byte following the descriptor byte identities
+ * the meta symbol (containing an ascii 'a', 'd', 'p', '|', or '('). For
+ * strings the byte after the descriptor is a character count for
+ * the string:
+ *
+ * meta symbols := descriptor
+ * symbol
+ *
+ * strings := descriptor
+ * character count
+ * the string
+ *
+ * operations := descriptor
+ * symbol
+ * character count
+ */
+
+/*
+ * handy macros for accessing parts of match blocks
+ */
+#define MSYM(A) (*(A+1)) /* symbol in a meta symbol block */
+#define MNEXT(A) (A+2) /* character following a metasymbol block */
+
+#define OSYM(A) (*(A+1)) /* symbol in an operation block */
+#define OCNT(A) (*(A+2)) /* character count */
+#define ONEXT(A) (A+3) /* next character after the operation */
+#define OPTR(A) (A+*(A+2)) /* place pointed to by the operator */
+
+#define SCNT(A) (*(A+1)) /* byte count of a string */
+#define SSTR(A) (A+2) /* address of the string */
+#define SNEXT(A) (A+2+*(A+1)) /* character following the string */
+
+/*
+ * bit flags in the descriptor
+ */
+#define OPT 1
+#define STR 2
+#define META 4
+#define ALT 8
+#define OPER 16
+
+static char *ccre; /* pointer to current position in converted exp*/
+static char *ure; /* pointer current position in unconverted exp */
+
+/* re: unconverted irregular expression */
+char *
+convexp(char *re)
+{
+ register char *cre; /* pointer to converted regular expression */
+
+ /* allocate room for the converted expression */
+ if (re == NULL)
+ return (NULL);
+ if (*re == '\0')
+ return (NULL);
+ cre = malloc(4 * strlen(re) + 3);
+ ccre = cre;
+ ure = re;
+
+ /* start the conversion with a \a */
+ *cre = META | OPT;
+ MSYM(cre) = 'a';
+ ccre = MNEXT(cre);
+
+ /* start the conversion (its recursive) */
+ expconv ();
+ *ccre = 0;
+ return (cre);
+}
+
+static void
+expconv()
+{
+ register char *cs; /* pointer to current symbol in converted exp */
+ register char c; /* character being processed */
+ register char *acs; /* pinter to last alternate */
+ register int temp;
+
+ /* let the conversion begin */
+ acs = NULL;
+ cs = NULL;
+ while (*ure) {
+ switch (c = *ure++) {
+
+ case '\\':
+ switch (c = *ure++) {
+
+ /* escaped characters are just characters */
+ default:
+ if (cs == NULL || (*cs & STR) == 0) {
+ cs = ccre;
+ *cs = STR;
+ SCNT(cs) = 1;
+ ccre += 2;
+ } else
+ SCNT(cs)++;
+ *ccre++ = c;
+ break;
+
+ /* normal(?) metacharacters */
+ case 'a':
+ case 'd':
+ case 'e':
+ case 'p':
+ if (acs != NULL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NULL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ break;
+ }
+ break;
+
+ /* just put the symbol in */
+ case '^':
+ case '$':
+ if (acs != NULL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NULL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ break;
+
+ /* mark the last match sequence as optional */
+ case '?':
+ if (cs)
+ *cs = *cs | OPT;
+ break;
+
+ /* recurse and define a subexpression */
+ case '(':
+ if (acs != NULL && acs != cs) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NULL;
+ }
+ cs = ccre;
+ *cs = OPER;
+ OSYM(cs) = '(';
+ ccre = ONEXT(cs);
+ expconv();
+ OCNT(cs) = ccre - cs; /* offset to next symbol */
+ break;
+
+ /* return from a recursion */
+ case ')':
+ if (acs != NULL) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NULL;
+ }
+ cs = ccre;
+ *cs = META;
+ MSYM(cs) = c;
+ ccre = MNEXT(cs);
+ return;
+
+ /* mark the last match sequence as having an alternate */
+ /* the third byte will contain an offset to jump over the */
+ /* alternate match in case the first did not fail */
+ case '|':
+ if (acs != NULL && acs != cs)
+ OCNT(ccre) = ccre - acs; /* make a back pointer */
+ else
+ OCNT(ccre) = 0;
+ *cs |= ALT;
+ cs = ccre;
+ *cs = OPER;
+ OSYM(cs) = '|';
+ ccre = ONEXT(cs);
+ acs = cs; /* remember that the pointer is to be filles */
+ break;
+
+ /* if its not a metasymbol just build a scharacter string */
+ default:
+ if (cs == NULL || (*cs & STR) == 0) {
+ cs = ccre;
+ *cs = STR;
+ SCNT(cs) = 1;
+ ccre = SSTR(cs);
+ } else
+ SCNT(cs)++;
+ *ccre++ = c;
+ break;
+ }
+ }
+ if (acs != NULL) {
+ do {
+ temp = OCNT(acs);
+ OCNT(acs) = ccre - acs;
+ acs -= temp;
+ } while (temp != 0);
+ acs = NULL;
+ }
+ return;
+}
+/* end of convertre */
+
+
+/*
+ * The following routine recognises an irregular expression
+ * with the following special characters:
+ *
+ * \? - means last match was optional
+ * \a - matches any number of characters
+ * \d - matches any number of spaces and tabs
+ * \p - matches any number of alphanumeric
+ * characters. The
+ * characters matched will be copied into
+ * the area pointed to by 'name'.
+ * \| - alternation
+ * \( \) - grouping used mostly for alternation and
+ * optionality
+ *
+ * The irregular expression must be translated to internal form
+ * prior to calling this routine
+ *
+ * The value returned is the pointer to the first non \a
+ * character matched.
+ */
+
+/*
+ * s: string to check for a match in
+ * re: a converted irregular expression
+ * mstring: where to put whatever matches a \p
+ */
+char *
+expmatch (register char *s, register char *re, register char *mstring)
+{
+ register char *cs; /* the current symbol */
+ register char *ptr,*s1; /* temporary pointer */
+ bool matched; /* a temporary bool */
+
+ /* initial conditions */
+ if (re == NULL)
+ return (NULL);
+ cs = re;
+ matched = false;
+
+ /* loop till expression string is exhausted (or at least pretty tired) */
+ while (*cs) {
+ switch (*cs & (OPER | STR | META)) {
+
+ /* try to match a string */
+ case STR:
+ matched = !STRNCMP (s, SSTR(cs), SCNT(cs));
+ if (matched) {
+
+ /* hoorah it matches */
+ s += SCNT(cs);
+ cs = SNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* alternation, skip to next expression */
+ cs = SNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* the match is optional */
+ cs = SNEXT(cs);
+ matched = 1; /* indicate a successful match */
+ } else {
+
+ /* no match, error return */
+ return (NULL);
+ }
+ break;
+
+ /* an operator, do something fancy */
+ case OPER:
+ switch (OSYM(cs)) {
+
+ /* this is an alternation */
+ case '|':
+ if (matched)
+
+ /* last thing in the alternation was a match, skip ahead */
+ cs = OPTR(cs);
+ else
+
+ /* no match, keep trying */
+ cs = ONEXT(cs);
+ break;
+
+ /* this is a grouping, recurse */
+ case '(':
+ ptr = expmatch(s, ONEXT(cs), mstring);
+ if (ptr != NULL) {
+
+ /* the subexpression matched */
+ matched = 1;
+ s = ptr;
+ } else if (*cs & ALT) {
+
+ /* alternation, skip to next expression */
+ matched = 0;
+ } else if (*cs & OPT) {
+
+ /* the match is optional */
+ matched = 1; /* indicate a successful match */
+ } else {
+
+ /* no match, error return */
+ return (NULL);
+ }
+ cs = OPTR(cs);
+ break;
+ }
+ break;
+
+ /* try to match a metasymbol */
+ case META:
+ switch (MSYM(cs)) {
+
+ /* try to match anything and remember what was matched */
+ case 'p':
+ /*
+ * This is really the same as trying the match the
+ * remaining parts of the expression to any subset
+ * of the string.
+ */
+ s1 = s;
+ do {
+ ptr = expmatch(s1, MNEXT(cs), mstring);
+ if (ptr != NULL && s1 != s) {
+
+ /* we have a match, remember the match */
+ strncpy (mstring, s, s1 - s);
+ mstring[s1 - s] = '\0';
+ return (ptr);
+ } else if (ptr != NULL && (*cs & OPT)) {
+
+ /* it was aoptional so no match is ok */
+ return (ptr);
+ } else if (ptr != NULL) {
+
+ /* not optional and we still matched */
+ return (NULL);
+ }
+ if (!(isalnum(*s1) || *s1 == '_' ||
+ /* C++ destructor */
+ *s1 == '~' ||
+ /* C++ scope operator */
+ (strlen(s1) > 1 && *s1 == ':' && s1[1] == ':' &&
+ (s1++, true))))
+ return (NULL);
+ if (*s1 == '\\')
+ _escaped = _escaped ? false : true;
+ else
+ _escaped = false;
+ } while (*s1++);
+ return (NULL);
+
+ /* try to match anything */
+ case 'a':
+ /*
+ * This is really the same as trying the match the
+ * remaining parts of the expression to any subset
+ * of the string.
+ */
+ s1 = s;
+ do {
+ ptr = expmatch(s1, MNEXT(cs), mstring);
+ if (ptr != NULL && s1 != s) {
+
+ /* we have a match */
+ return (ptr);
+ } else if (ptr != NULL && (*cs & OPT)) {
+
+ /* it was aoptional so no match is ok */
+ return (ptr);
+ } else if (ptr != NULL) {
+
+ /* not optional and we still matched */
+ return (NULL);
+ }
+ if (*s1 == '\\')
+ _escaped = _escaped ? false : true;
+ else
+ _escaped = false;
+ } while (*s1++);
+ return (NULL);
+
+ /* fail if we are currently _escaped */
+ case 'e':
+ if (_escaped)
+ return(NULL);
+ cs = MNEXT(cs);
+ break;
+
+ /* match any number of tabs and spaces */
+ case 'd':
+ ptr = s;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (s != ptr || s == s_start) {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*s == '\n' || *s == '\0') {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NULL);
+ break;
+
+ /* check for end of line */
+ case '$':
+ if (*s == '\0' || *s == '\n') {
+
+ /* match, be happy */
+ s++;
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NULL);
+ break;
+
+ /* check for start of line */
+ case '^':
+ if (s == s_start) {
+
+ /* match, be happy */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else if (*cs & ALT) {
+
+ /* try the next part */
+ matched = 0;
+ cs = MNEXT(cs);
+ } else if (*cs & OPT) {
+
+ /* doesn't matter */
+ matched = 1;
+ cs = MNEXT(cs);
+ } else
+
+ /* no match, error return */
+ return (NULL);
+ break;
+
+ /* end of a subexpression, return success */
+ case ')':
+ return (s);
+ }
+ break;
+ }
+ }
+ return (s);
+}
diff --git a/usr.bin/vgrind/tmac.vgrind b/usr.bin/vgrind/tmac.vgrind
new file mode 100644
index 000000000000..57ad70efa61f
--- /dev/null
+++ b/usr.bin/vgrind/tmac.vgrind
@@ -0,0 +1,71 @@
+.am vS
+..
+.am vE
+..
+'ss 23
+'ds _ \d\(mi\u
+'ps 9z
+'vs 10p
+'ds - \(mi
+'ds / \\h'\\w' 'u-\\w'/'u'/
+'ds /* \\h'\\w' 'u-\\w'/'u'/*
+'bd B 3
+'bd S B 3
+'nr cm 0
+'nf
+'de vH
+'ev 2
+'ft 1
+'sp .35i
+'tl '\s14\f3\\*(=F\fP\s0'\\*(=H'\f3\s14\\*(=F\fP\s0'
+'sp .25i
+'ft 1
+\f2\s12\h'\\n(.lu-\w'\\*(=f'u'\\*(=f\fP\s0\h'|0u'
+.sp .05i
+'ev
+'ds =G \\*(=F
+..
+'de vF
+'ev 2
+'sp .35i
+'ie o 'tl '\f2\\*(=M''Page % of \\*(=G\fP'
+'el 'tl '\f2Page % of \\*(=G''\\*(=M\fP'
+'bp
+'ev
+'ft 1
+'if \\n(cm=1 'ft 2
+..
+'de ()
+'pn 1
+..
+'de +C
+'nr cm 1
+'ft 2
+'ds +K
+'ds -K
+..
+'de -C
+'nr cm 0
+'ft 1
+'ds +K \f3
+'ds -K \fP
+..
+'+C
+'-C
+'am +C
+'ne 3
+..
+'de FN
+\f2\s14\h'\\n(.lu-\w'\\$1'u'\\$1\fP\s0\h'|0u'\c
+.if r x .if \\nx .if d =F .tm \\$1 \\*(=F \\n%
+'ds =f \&...\\$1
+..
+'de FC
+.if r x .if \\nx .if d =F .tm \\$1 \\*(=F \\n%
+'ds =f \&...\\$1
+..
+'de -F
+'rm =f
+..
+'ft 1
+'lg 0
diff --git a/usr.bin/vgrind/vfontedpr.c b/usr.bin/vgrind/vfontedpr.c
new file mode 100644
index 000000000000..9a45ec35253b
--- /dev/null
+++ b/usr.bin/vgrind/vfontedpr.c
@@ -0,0 +1,704 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include "pathnames.h"
+#include "extern.h"
+
+#define STANDARD 0
+#define ALTERNATE 1
+
+/*
+ * Vfontedpr.
+ *
+ * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy)
+ *
+ */
+
+#define STRLEN 10 /* length of strings introducing things */
+#define PNAMELEN 40 /* length of a function/procedure name */
+#define PSMAX 20 /* size of procedure name stacking */
+
+static int iskw(char *);
+static bool isproc(char *);
+static void putKcp(char *, char *, bool);
+static void putScp(char *);
+static void putcp(int);
+static int tabs(char *, char *);
+static int width(char *, char *);
+
+/*
+ * The state variables
+ */
+
+static bool filter = false; /* act as a filter (like eqn) */
+static bool inchr; /* in a string constant */
+static bool incomm; /* in a comment of the primary type */
+static bool idx = false; /* form an index */
+static bool instr; /* in a string constant */
+static bool nokeyw = false; /* no keywords being flagged */
+static bool pass = false; /*
+ * when acting as a filter, pass indicates
+ * whether we are currently processing
+ * input.
+ */
+
+static int blklevel; /* current nesting level */
+static int comtype; /* type of comment */
+static char * defsfile[2] = { _PATH_VGRINDEFS, 0 };
+ /* name of language definitions file */
+static int margin;
+static int plstack[PSMAX]; /* the procedure nesting level stack */
+static char pname[BUFSIZ+1];
+static bool prccont; /* continue last procedure */
+static int psptr; /* the stack index of the current procedure */
+static char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */
+
+/*
+ * The language specific globals
+ */
+
+char *l_acmbeg; /* string introducing a comment */
+char *l_acmend; /* string ending a comment */
+char *l_blkbeg; /* string beginning of a block */
+char *l_blkend; /* string ending a block */
+char *l_chrbeg; /* delimiter for character constant */
+char *l_chrend; /* delimiter for character constant */
+char *l_combeg; /* string introducing a comment */
+char *l_comend; /* string ending a comment */
+char l_escape; /* character used to escape characters */
+char *l_keywds[BUFSIZ/2]; /* keyword table address */
+char *l_nocom; /* regexp for non-comments */
+char *l_prcbeg; /* regular expr for procedure begin */
+char *l_strbeg; /* delimiter for string constant */
+char *l_strend; /* delimiter for string constant */
+bool l_toplex; /* procedures only defined at top lex level */
+const char *language = "c"; /* the language indicator */
+
+#define ps(x) printf("%s", x)
+static char minus[] = "-";
+static char minusn[] = "-n";
+
+int
+main(int argc, char **argv)
+{
+ const char *fname = "";
+ struct stat stbuf;
+ char buf[BUFSIZ];
+ char *defs;
+ int needbp = 0;
+
+ argc--, argv++;
+ do {
+ char *cp;
+ int i;
+
+ if (argc > 0) {
+ if (!strcmp(argv[0], "-h")) {
+ if (argc == 1) {
+ printf("'ds =H\n");
+ argc = 0;
+ goto rest;
+ }
+ printf("'ds =H %s\n", argv[1]);
+ argc--, argv++;
+ argc--, argv++;
+ if (argc > 0)
+ continue;
+ goto rest;
+ }
+
+ /* act as a filter like eqn */
+ if (!strcmp(argv[0], "-f")) {
+ filter = true;
+ argv[0] = argv[argc-1];
+ argv[argc-1] = minus;
+ continue;
+ }
+
+ /* take input from the standard place */
+ if (!strcmp(argv[0], "-")) {
+ argc = 0;
+ goto rest;
+ }
+
+ /* build an index */
+ if (!strcmp(argv[0], "-x")) {
+ idx = true;
+ argv[0] = minusn;
+ }
+
+ /* indicate no keywords */
+ if (!strcmp(argv[0], "-n")) {
+ nokeyw = true;
+ argc--, argv++;
+ continue;
+ }
+
+ /* specify the font size */
+ if (!strncmp(argv[0], "-s", 2)) {
+ i = 0;
+ cp = argv[0] + 2;
+ while (*cp)
+ i = i * 10 + (*cp++ - '0');
+ printf("'ps %d\n'vs %d\n", i, i+1);
+ argc--, argv++;
+ continue;
+ }
+
+ /* specify the language */
+ if (!strncmp(argv[0], "-l", 2)) {
+ language = argv[0]+2;
+ argc--, argv++;
+ continue;
+ }
+
+ /* specify the language description file */
+ if (!strncmp(argv[0], "-d", 2)) {
+ defsfile[0] = argv[1];
+ argc--, argv++;
+ argc--, argv++;
+ continue;
+ }
+
+ /* open the file for input */
+ if (freopen(argv[0], "r", stdin) == NULL)
+ err(1, "%s", argv[0]);
+ if (idx)
+ printf("'ta 4i 4.25i 5.5iR\n'in .5i\n");
+ fname = argv[0];
+ argc--, argv++;
+ }
+ rest:
+
+ /*
+ * get the language definition from the defs file
+ */
+ i = cgetent(&defs, defsfile, language);
+ if (i == -1) {
+ fprintf (stderr, "no entry for language %s\n", language);
+ exit(0);
+ } else if (i == -2) { fprintf(stderr,
+ "cannot find vgrindefs file %s\n", defsfile[0]);
+ exit(0);
+ } else if (i == -3) { fprintf(stderr,
+ "potential reference loop detected in vgrindefs file %s\n",
+ defsfile[0]);
+ exit(0);
+ }
+ if (cgetustr(defs, "kw", &cp) == -1)
+ nokeyw = true;
+ else {
+ char **cpp;
+
+ cpp = l_keywds;
+ while (*cp) {
+ while (*cp == ' ' || *cp =='\t')
+ *cp++ = '\0';
+ if (*cp)
+ *cpp++ = cp;
+ while (*cp != ' ' && *cp != '\t' && *cp)
+ cp++;
+ }
+ *cpp = NULL;
+ }
+ cgetustr(defs, "pb", &cp);
+ l_prcbeg = convexp(cp);
+ cgetustr(defs, "cb", &cp);
+ l_combeg = convexp(cp);
+ cgetustr(defs, "ce", &cp);
+ l_comend = convexp(cp);
+ cgetustr(defs, "ab", &cp);
+ l_acmbeg = convexp(cp);
+ cgetustr(defs, "ae", &cp);
+ l_acmend = convexp(cp);
+ cgetustr(defs, "sb", &cp);
+ l_strbeg = convexp(cp);
+ cgetustr(defs, "se", &cp);
+ l_strend = convexp(cp);
+ cgetustr(defs, "bb", &cp);
+ l_blkbeg = convexp(cp);
+ cgetustr(defs, "be", &cp);
+ l_blkend = convexp(cp);
+ cgetustr(defs, "lb", &cp);
+ l_chrbeg = convexp(cp);
+ cgetustr(defs, "le", &cp);
+ l_chrend = convexp(cp);
+ if (cgetustr(defs, "nc", &cp) >= 0)
+ l_nocom = convexp(cp);
+ l_escape = '\\';
+ l_onecase = (cgetcap(defs, "oc", ':') != NULL);
+ l_toplex = (cgetcap(defs, "tl", ':') != NULL);
+
+ /* initialize the program */
+
+ incomm = false;
+ instr = false;
+ inchr = false;
+ _escaped = false;
+ blklevel = 0;
+ for (psptr=0; psptr<PSMAX; psptr++) {
+ pstack[psptr][0] = '\0';
+ plstack[psptr] = 0;
+ }
+ psptr = -1;
+ ps("'-F\n");
+ if (!filter) {
+ printf(".ds =F %s\n", fname);
+ ps("'wh 0 vH\n");
+ ps("'wh -1i vF\n");
+ }
+ if (needbp) {
+ needbp = 0;
+ printf(".()\n");
+ printf(".bp\n");
+ }
+ if (!filter) {
+ fstat(fileno(stdin), &stbuf);
+ cp = ctime(&stbuf.st_mtime);
+ cp[16] = '\0';
+ cp[24] = '\0';
+ printf(".ds =M %s %s\n", cp+4, cp+20);
+ }
+
+ /*
+ * MAIN LOOP!!!
+ */
+ while (fgets(buf, sizeof buf, stdin) != NULL) {
+ if (buf[0] == '\f') {
+ printf(".bp\n");
+ }
+ if (buf[0] == '.') {
+ printf("%s", buf);
+ if (!strncmp (buf+1, "vS", 2))
+ pass = true;
+ if (!strncmp (buf+1, "vE", 2))
+ pass = false;
+ continue;
+ }
+ prccont = false;
+ if (!filter || pass)
+ putScp(buf);
+ else
+ printf("%s", buf);
+ if (prccont && (psptr >= 0)) {
+ ps("'FC ");
+ ps(pstack[psptr]);
+ ps("\n");
+ }
+#ifdef DEBUG
+ printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr);
+#endif
+ margin = 0;
+ }
+ needbp = 1;
+ } while (argc > 0);
+ exit(0);
+}
+
+#define isidchr(c) (isalnum(c) || (c) == '_')
+
+static void
+putScp(char *os)
+{
+ register char *s = os; /* pointer to unmatched string */
+ char dummy[BUFSIZ]; /* dummy to be used by expmatch */
+ char *comptr; /* end of a comment delimiter */
+ char *acmptr; /* end of a comment delimiter */
+ char *strptr; /* end of a string delimiter */
+ char *chrptr; /* end of a character const delimiter */
+ char *blksptr; /* end of a lexical block start */
+ char *blkeptr; /* end of a lexical block end */
+ char *nocomptr; /* end of a non-comment delimiter */
+
+ s_start = os; /* remember the start for expmatch */
+ _escaped = false;
+ if (nokeyw || incomm || instr)
+ goto skip;
+ if (isproc(s)) {
+ ps("'FN ");
+ ps(pname);
+ ps("\n");
+ if (psptr < PSMAX) {
+ ++psptr;
+ strncpy (pstack[psptr], pname, PNAMELEN);
+ pstack[psptr][PNAMELEN] = '\0';
+ plstack[psptr] = blklevel;
+ }
+ }
+skip:
+ do {
+ /* check for string, comment, blockstart, etc */
+ if (!incomm && !instr && !inchr) {
+
+ blkeptr = expmatch(s, l_blkend, dummy);
+ blksptr = expmatch(s, l_blkbeg, dummy);
+ comptr = expmatch(s, l_combeg, dummy);
+ acmptr = expmatch(s, l_acmbeg, dummy);
+ strptr = expmatch(s, l_strbeg, dummy);
+ chrptr = expmatch(s, l_chrbeg, dummy);
+ nocomptr = expmatch (s, l_nocom, dummy);
+
+ /* start of non-comment? */
+ if (nocomptr != NULL)
+ if ((nocomptr <= comptr || comptr == NULL)
+ && (nocomptr <= acmptr || acmptr == NULL)) {
+ /* continue after non-comment */
+ putKcp (s, nocomptr-1, false);
+ s = nocomptr;
+ continue;
+ }
+
+ /* start of a comment? */
+ if (comptr != NULL)
+ if ((comptr < strptr || strptr == NULL)
+ && (comptr < acmptr || acmptr == NULL)
+ && (comptr < chrptr || chrptr == NULL)
+ && (comptr < blksptr || blksptr == NULL)
+ && (comptr < blkeptr || blkeptr == NULL)) {
+ putKcp(s, comptr-1, false);
+ s = comptr;
+ incomm = true;
+ comtype = STANDARD;
+ if (s != os)
+ ps("\\c");
+ ps("\\c\n'+C\n");
+ continue;
+ }
+
+ /* start of a comment? */
+ if (acmptr != NULL)
+ if ((acmptr < strptr || strptr == NULL)
+ && (acmptr < chrptr || chrptr == NULL)
+ && (acmptr < blksptr || blksptr == NULL)
+ && (acmptr < blkeptr || blkeptr == NULL)) {
+ putKcp(s, acmptr-1, false);
+ s = acmptr;
+ incomm = true;
+ comtype = ALTERNATE;
+ if (s != os)
+ ps("\\c");
+ ps("\\c\n'+C\n");
+ continue;
+ }
+
+ /* start of a string? */
+ if (strptr != NULL)
+ if ((strptr < chrptr || chrptr == NULL)
+ && (strptr < blksptr || blksptr == NULL)
+ && (strptr < blkeptr || blkeptr == NULL)) {
+ putKcp(s, strptr-1, false);
+ s = strptr;
+ instr = true;
+ continue;
+ }
+
+ /* start of a character string? */
+ if (chrptr != NULL)
+ if ((chrptr < blksptr || blksptr == NULL)
+ && (chrptr < blkeptr || blkeptr == NULL)) {
+ putKcp(s, chrptr-1, false);
+ s = chrptr;
+ inchr = true;
+ continue;
+ }
+
+ /* end of a lexical block */
+ if (blkeptr != NULL) {
+ if (blkeptr < blksptr || blksptr == NULL) {
+ putKcp(s, blkeptr - 1, false);
+ s = blkeptr;
+ if (blklevel > 0 /* sanity */)
+ blklevel--;
+ if (psptr >= 0 && plstack[psptr] >= blklevel) {
+
+ /* end of current procedure */
+ if (s != os)
+ ps("\\c");
+ ps("\\c\n'-F\n");
+ blklevel = plstack[psptr];
+
+ /* see if we should print the last proc name */
+ if (--psptr >= 0)
+ prccont = true;
+ else
+ psptr = -1;
+ }
+ continue;
+ }
+ }
+
+ /* start of a lexical block */
+ if (blksptr != NULL) {
+ putKcp(s, blksptr - 1, false);
+ s = blksptr;
+ blklevel++;
+ continue;
+ }
+
+ /* check for end of comment */
+ } else if (incomm) {
+ comptr = expmatch(s, l_comend, dummy);
+ acmptr = expmatch(s, l_acmend, dummy);
+ if (((comtype == STANDARD) && (comptr != NULL)) ||
+ ((comtype == ALTERNATE) && (acmptr != NULL))) {
+ if (comtype == STANDARD) {
+ putKcp(s, comptr-1, true);
+ s = comptr;
+ } else {
+ putKcp(s, acmptr-1, true);
+ s = acmptr;
+ }
+ incomm = false;
+ ps("\\c\n'-C\n");
+ continue;
+ } else {
+ putKcp(s, s + strlen(s) -1, true);
+ s = s + strlen(s);
+ continue;
+ }
+
+ /* check for end of string */
+ } else if (instr) {
+ if ((strptr = expmatch(s, l_strend, dummy)) != NULL) {
+ putKcp(s, strptr-1, true);
+ s = strptr;
+ instr = false;
+ continue;
+ } else {
+ putKcp(s, s+strlen(s)-1, true);
+ s = s + strlen(s);
+ continue;
+ }
+
+ /* check for end of character string */
+ } else if (inchr) {
+ if ((chrptr = expmatch(s, l_chrend, dummy)) != NULL) {
+ putKcp(s, chrptr-1, true);
+ s = chrptr;
+ inchr = false;
+ continue;
+ } else {
+ putKcp(s, s+strlen(s)-1, true);
+ s = s + strlen(s);
+ continue;
+ }
+ }
+
+ /* print out the line */
+ putKcp(s, s + strlen(s) -1, false);
+ s = s + strlen(s);
+ } while (*s);
+}
+
+/*
+ * start: start of string to write
+ * end: end of string to write
+ * force: true if we should force nokeyw
+ */
+static void
+putKcp(char *start, char *end, bool force)
+{
+ int i;
+ int xfld = 0;
+
+ while (start <= end) {
+ if (idx) {
+ if (*start == ' ' || *start == '\t') {
+ if (xfld == 0)
+ printf("\001");
+ printf("\t");
+ xfld = 1;
+ while (*start == ' ' || *start == '\t')
+ start++;
+ continue;
+ }
+ }
+
+ /* take care of nice tab stops */
+ if (*start == '\t') {
+ while (*start == '\t')
+ start++;
+ i = tabs(s_start, start) - margin / 8;
+ printf("\\h'|%dn'", i * 10 + 1 - margin % 8);
+ continue;
+ }
+
+ if (!nokeyw && !force)
+ if ((*start == '#' || isidchr(*start))
+ && (start == s_start || !isidchr(start[-1]))) {
+ i = iskw(start);
+ if (i > 0) {
+ ps("\\*(+K");
+ do
+ putcp((unsigned char)*start++);
+ while (--i > 0);
+ ps("\\*(-K");
+ continue;
+ }
+ }
+
+ putcp((unsigned char)*start++);
+ }
+}
+
+
+static int
+tabs(char *s, char *os)
+{
+
+ return (width(s, os) / 8);
+}
+
+static int
+width(register char *s, register char *os)
+{
+ register int i = 0;
+
+ while (s < os) {
+ if (*s == '\t') {
+ i = (i + 8) &~ 7;
+ s++;
+ continue;
+ }
+ if (*s < ' ')
+ i += 2;
+ else
+ i++;
+ s++;
+ }
+ return (i);
+}
+
+static void
+putcp(register int c)
+{
+
+ switch(c) {
+
+ case 0:
+ break;
+
+ case '\f':
+ break;
+
+ case '\r':
+ break;
+
+ case '{':
+ ps("\\*(+K{\\*(-K");
+ break;
+
+ case '}':
+ ps("\\*(+K}\\*(-K");
+ break;
+
+ case '\\':
+ ps("\\e");
+ break;
+
+ case '_':
+ ps("\\*_");
+ break;
+
+ case '-':
+ ps("\\*-");
+ break;
+
+ case '`':
+ ps("\\`");
+ break;
+
+ case '\'':
+ ps("\\'");
+ break;
+
+ case '.':
+ ps("\\&.");
+ break;
+
+ case '*':
+ ps("\\fI*\\fP");
+ break;
+
+ case '/':
+ ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP");
+ break;
+
+ default:
+ if (c < 040)
+ putchar('^'), c |= '@';
+ case '\t':
+ case '\n':
+ putchar(c);
+ }
+}
+
+/*
+ * look for a process beginning on this line
+ */
+static bool
+isproc(char *s)
+{
+ pname[0] = '\0';
+ if (!l_toplex || blklevel == 0)
+ if (expmatch(s, l_prcbeg, pname) != NULL) {
+ return (true);
+ }
+ return (false);
+}
+
+
+/* iskw - check to see if the next word is a keyword
+ */
+
+static int
+iskw(register char *s)
+{
+ register char **ss = l_keywds;
+ register int i = 1;
+ register char *cp = s;
+
+ while (++cp, isidchr(*cp))
+ i++;
+ while ((cp = *ss++))
+ if (!STRNCMP(s,cp,i) && !isidchr(cp[i]))
+ return (i);
+ return (0);
+}
diff --git a/usr.bin/vgrind/vgrind.1 b/usr.bin/vgrind/vgrind.1
new file mode 100644
index 000000000000..0a089577562e
--- /dev/null
+++ b/usr.bin/vgrind/vgrind.1
@@ -0,0 +1,239 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd August 29, 2006
+.Dt VGRIND 1
+.Os
+.Sh NAME
+.Nm vgrind
+.Nd grind nice listings of programs
+.Sh SYNOPSIS
+.Nm
+.Op Fl
+.Op Fl W
+.Op Fl d Ar file
+.Op Fl f
+.Op Fl h Ar header
+.Op Fl l Ns Ar language
+.Op Fl n
+.Op Fl p Ar postproc
+.Op Fl s Ar pointsize
+.Op Fl t
+.Op Fl x
+.Ar name Ar ...
+.Sh DESCRIPTION
+The
+.Nm
+utility formats the program sources specified as arguments
+on the command line in a nice style using
+.Xr troff 1 Pq Pa ports/textproc/groff .
+Comments are placed in italics, keywords in bold face,
+and the name of the current function is listed down the margin of each
+page as it is encountered.
+.Pp
+The
+.Nm
+utility runs in two basic modes, filter mode (see the
+.Fl f
+option) or regular mode.
+In filter mode
+.Nm
+acts as a filter in a manner similar to
+.Xr tbl 1 .
+The standard input is passed directly to the standard output except
+for lines bracketed by the
+.Em troff-like
+macros:
+.Bl -tag -width Ds
+.It \&.vS
+starts processing
+.It \&.vE
+ends processing
+.El
+.Pp
+These lines are formatted as described above.
+The output from this
+filter can be passed to
+.Xr troff 1 Pq Pa ports/textproc/groff
+for output.
+There need be no particular ordering with
+.Xr eqn 1 Pq Pa ports/textproc/groff
+or
+.Xr tbl 1 Pq Pa ports/textproc/groff .
+.Pp
+In regular mode
+.Nm
+accepts input files, processes them, and passes them to the postprocessor
+for output,
+.Xr psroff 1
+by default.
+.Pp
+In both modes
+.Nm
+passes any lines beginning with a decimal point without conversion.
+.Pp
+The options are:
+.Bl -tag -width Ar
+.It Fl
+forces input to be taken from standard input (default if
+.Fl f
+is specified)
+.It Fl W
+forces output to the (wide) Versatec printer rather than the (narrow)
+Varian
+.It Fl d Ar file
+specifies an alternate language definitions
+file (default is
+.Pa /usr/share/misc/vgrindefs )
+.It Fl f
+forces filter mode
+.It Fl h Ar header
+specifies a particular header to put on every output page (default is
+the file name)
+.It Fl l
+specifies the language to use.
+Currently known are
+.Tn PASCAL
+.Pq Fl l Ns Ar p ,
+.Tn MODEL
+.Pq Fl l Ns Ar m ,
+C
+.Pf ( Fl l Ns Ar c
+or the default),
+.Tn C++
+.Pq Fl l Ns Ar c++ ,
+.Tn CSH
+.Pq Fl l Ns Ar csh ,
+.Tn SHELL
+.Pq Fl l Ns Ar sh ,
+.Tn RATFOR
+.Pq Fl l Ns Ar r ,
+.Tn MODULA2
+.Pq Fl l Ns Ar mod2 ,
+.Tn YACC
+.Pq Fl l Ns Ar yacc ,
+.Tn LISP
+.Pq Fl l Ns Ar isp ,
+.Tn ICON
+.Pq Fl l Ns Ar I ,
+and
+.Tn PERL
+.Pq Fl l Ns Ar perl .
+.It Fl n
+forces no keyword bolding
+.It Fl p Ar postproc
+use
+.Ar postproc
+to post-process the output,
+.Xr psroff 1
+by default.
+.It Fl s Ar pointsize
+specifies a point size to use on output (exactly the same as the argument
+of a .ps)
+.It Fl t
+similar to the same option in
+.Xr troff 1 Pq Pa ports/textproc/groff
+causing formatted text to go to the standard output
+.It Fl x
+outputs the index file in a ``pretty'' format.
+The index file itself is produced whenever
+.Nm
+is run with a file called
+.Pa index
+in the current directory.
+The index of function
+definitions can then be run off by giving
+.Nm
+the
+.Fl x
+option and the file
+.Pa index
+as argument.
+.El
+.Sh FILES
+.Bl -tag -width /usr/share/misc/vgrindefsxx -compact
+.It Pa index
+file where source for index is created
+.It Pa /usr/share/tmac/tmac.vgrind
+macro package
+.It Pa /usr/libexec/vfontedpr
+preprocessor
+.It Pa /usr/share/misc/vgrindefs
+language descriptions
+.El
+.Sh SEE ALSO
+.Xr getcap 3 ,
+.Xr vgrindefs 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh BUGS
+The vfontedpr preprocessor assumes that a certain programming style is
+followed:
+.Pp
+For
+.Tn C
+\- function names can be preceded on a line only by spaces, tabs, or an
+asterisk.
+The parenthesized arguments must also be on the same line.
+.Pp
+For
+.Tn PASCAL
+\- function names need to appear on the same line as the keywords
+.Em function
+or
+.Em procedure .
+.Pp
+For
+.Tn MODEL
+\- function names need to appear on the same line as the keywords
+.Em is beginproc .
+.Pp
+If these conventions are not followed, the indexing and marginal function
+name comment mechanisms will fail.
+.Pp
+More generally, arbitrary formatting styles for programs mostly look bad.
+The use of spaces to align source code fails miserably; if you plan to
+.Nm
+your program you should use tabs.
+This is somewhat inevitable since the
+font used by
+.Nm
+is variable width.
+.Pp
+The mechanism of
+.Xr ctags 1
+in recognizing functions should be used here.
+.Pp
+Filter mode does not work in documents using the
+.Fl me
+or
+.Fl ms
+macros.
+(So what use is it anyway?)
diff --git a/usr.bin/vgrind/vgrind.sh b/usr.bin/vgrind/vgrind.sh
new file mode 100644
index 000000000000..1b52a3862736
--- /dev/null
+++ b/usr.bin/vgrind/vgrind.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Copyright (c) 1980, 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.
+
+voptions=""
+options=""
+files=""
+f=""
+head=""
+vf="/usr/libexec/vfontedpr"
+tm="/usr/share/tmac"
+postproc="psroff"
+
+# Parse args
+while test $# -gt 0; do
+ case $1 in
+ -f)
+ f="filter"
+ options="$options -f"
+ ;;
+ -t)
+ voptions="$voptions -t"
+ ;;
+ -o*)
+ voptions="$voptions $1"
+ ;;
+ -W)
+ voptions="$voptions -W"
+ ;;
+ -d)
+ if test $# -lt 2; then
+ echo "$0: option $1 must have argument" >&2
+ exit 1
+ fi
+ options="$options $1 $2"
+ shift
+ ;;
+ -h)
+ if test $# -lt 2; then
+ echo "$0: option $1 must have argument" >&2
+ exit 1
+ fi
+ head="$2"
+ shift
+ ;;
+ -p)
+ if test $# -lt 2; then
+ echo "$0: option $1 must have argument" >&2
+ exit 1
+ fi
+ postproc="$2"
+ shift
+ ;;
+ -*)
+ options="$options $1"
+ ;;
+ *)
+ files="$files $1"
+ ;;
+ esac
+ shift
+done
+
+if test -r index; then
+ echo > nindex
+ for i in $files; do
+ # make up a sed delete command for filenames
+ # being careful about slashes.
+ echo "? $i ?d" | sed -e "s:/:\\/:g" -e "s:?:/:g" >> nindex
+ done
+ sed -f nindex index > xindex
+ if test "x$f" = xfilter; then
+ if test "x$head" != x; then
+ $vf $options -h "$head" $files
+ else
+ $vf $options $files
+ fi | cat $tm/tmac.vgrind -
+ else
+ if test "x$head" != x; then
+ $vf $options -h "$head" $files
+ else
+ $vf $options $files
+ fi | sh -c "$postproc -rx1 $voptions -i -mvgrind 2>> xindex"
+ fi
+ sort -df -k 1,2 xindex > index
+ rm nindex xindex
+else
+ if test "x$f" = xfilter; then
+ if test "x$head" != x; then
+ $vf $options -h "$head" $files
+ else
+ $vf $options $files
+ fi | cat $tm/tmac.vgrind -
+ else
+ if test "x$head" != x; then
+ $vf $options -h "$head" $files
+ else
+ $vf $options $files
+ fi | $postproc -i $voptions -mvgrind
+ fi
+fi
diff --git a/usr.bin/vgrind/vgrindefs.5 b/usr.bin/vgrind/vgrindefs.5
new file mode 100644
index 000000000000..df6ff68749d5
--- /dev/null
+++ b/usr.bin/vgrind/vgrindefs.5
@@ -0,0 +1,167 @@
+.\" 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.
+.\"
+.Dd June 6, 1993
+.Dt VGRINDEFS 5
+.Os
+.Sh NAME
+.Nm vgrindefs
+.Nd language definition data base for
+.Xr vgrind 1
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+file
+contains all language definitions for
+.Xr vgrind 1 .
+The data base is
+very similar to
+.Xr termcap 5 .
+.Sh FIELDS
+The following table names and describes each field.
+.Bl -column Namexxx Tpexxx
+.It Sy "Name Type Description"
+.It "ab str regular expression for the start of an alternate comment"
+.It "ae str regular expression for the end of an alternate comment"
+.It "pb str regular expression for start of a procedure"
+.It "bb str regular expression for start of a lexical block"
+.It "be str regular expression for the end of a lexical block"
+.It "cb str regular expression for the start of a comment"
+.It "ce str regular expression for the end of a comment"
+.It "sb str regular expression for the start of a string"
+.It "se str regular expression for the end of a string"
+.It "lb str regular expression for the start of a character constant"
+.It "le str regular expression for the end of a character constant"
+.It "nc str regular expression for a non-comment (see below)"
+.It "tl bool present means procedures are only defined at the top lexical level"
+.It "oc bool present means upper and lower case are equivalent"
+.It "kw str a list of keywords separated by spaces"
+.El
+.Pp
+Non-comments are required to describe a certain context where a
+sequence that would normally start a comment loses its special
+meaning.
+A typical example for this can be found in Perl, where
+comments are normally starting with
+.Ql # ,
+while the string
+.Ql $#
+is an operator on an array.
+.Sh REGULAR EXPRESSIONS
+.Nm Vgrindefs
+uses regular expression which are very similar to those of
+.Xr ex 1
+and
+.Xr lex 1 .
+The characters `^', `$', `:' and `\e'
+are reserved characters and must be
+"quoted" with a preceding
+.Ql \e
+if they
+are to be included as normal characters.
+The metasymbols and their meanings are:
+.Bl -tag -width indent
+.It $
+the end of a line
+.It \&^
+the beginning of a line
+.It \ed
+a delimiter (space, tab, newline, start of line)
+.It \ea
+matches any string of symbols (like .* in lex)
+.It \ep
+matches any alphanumeric name.
+In a procedure definition (pb) the string
+that matches this symbol is used as the procedure name.
+.It ()
+grouping
+.It \&|
+alternation
+.It ?
+last item is optional
+.It \ee
+preceding any string means that the string will not match an
+input string if the input string is preceded by an escape character (\e).
+This is typically used for languages (like C) which can include the
+string delimiter in a string by escaping it.
+.El
+.Pp
+Unlike other regular expressions in the system, these match words
+and not characters.
+Hence something like "(tramp|steamer)flies?"
+would match "tramp", "steamer", "trampflies", or "steamerflies".
+.Sh KEYWORD LIST
+The keyword list is just a list of keywords in the language separated
+by spaces.
+If the "oc" boolean is specified, indicating that upper
+and lower case are equivalent, then all the keywords should be
+specified in lower case.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/vgrindefs -compact
+.It Pa /usr/share/misc/vgrindefs
+File containing terminal descriptions.
+.El
+.Sh EXAMPLES
+The following entry, which describes the C language, is
+typical of a language entry.
+.Bd -literal
+C|c:\
+:pb=^\ed?*?\ed?\ep\ed?\e(\ea?\e):bb={:be=}:cb=/*:ce=*/:sb=":se=\ee":\e
+:lb=':le=\ee':tl:\e
+:kw=asm auto break case char continue default do double else enum\e
+extern float for fortran goto if int long register return short\e
+sizeof static struct switch typedef union unsigned while #define\e
+#else #endif #if #ifdef #ifndef #include #undef # define else endif\e
+if ifdef ifndef include undef:
+.Ed
+.Pp
+Note that the first field is just the language name (and any variants
+of it).
+Thus the C language could be specified to
+.Xr vgrind 1
+as "c" or "C".
+.Pp
+Entries may continue onto multiple lines by giving a \e as the last
+character of a line.
+Capabilities in
+.Nm
+are of two types:
+Boolean capabilities which indicate that the language has
+some particular feature
+and string
+capabilities which give a regular expression or
+keyword list.
+.Sh SEE ALSO
+.Xr troff 1 Pq Pa ports/textproc/groff ,
+.Xr vgrind 1
+.Sh HISTORY
+The
+.Nm
+file format appeared in
+.Bx 4.2 .
diff --git a/usr.bin/vgrind/vgrindefs.src b/usr.bin/vgrind/vgrindefs.src
new file mode 100644
index 000000000000..8a6ba576c1b6
--- /dev/null
+++ b/usr.bin/vgrind/vgrindefs.src
@@ -0,0 +1,153 @@
+# Copyright (c) 1987, 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.
+#
+
+C|c:\
+ :pb=^\a?\d?*?\d?\p\d?\(\a?\)(\d|{):\
+ :bb={:be=}:cb=/*:ce=*/:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=asm auto break case char continue default do double else enum\
+ extern float for fortran goto if int long register return short\
+ sizeof static struct switch typedef union unsigned void while #define\
+ #else #endif #if #ifdef #ifndef #include #undef # define else endif\
+ if ifdef ifndef include undef:
+model|mod|m:\
+ :pb=^\d(space\d\p\drep)|(\p\dis|inline|public\dbeginproc):\
+ :bb=\dbeginproc|space|case\d:be=\dendproc|end\d|;:\
+ :cb=\$:ce=\$|$:sb=":se=":lb=':le=\a|$:\
+ :kw=abs and array beginproc boolean by case cdnl char copied dispose\
+ div do dynamic else elsif end endproc entry external FALSE false\
+ fi file for formal fortran global if iff ift\
+ in integer include inline is lbnd\
+ max min mod new NIL nil noresult not notin od of or procedure public\
+ read readln readonly record recursive rem rep repeat res\
+ result return set\
+ space string subscript such then TRUE true type ubnd union until\
+ varies while width:
+pascal|pasc|p:\
+ :pb=(^\d?procedure|function|program\d\p\d|\(|;|\:)|(=\d?record\d):\
+ :bb=\dcase|begin\d:be=\dend|forward\d|;:\
+ :cb={:ce=}:\
+ :ab=\(*:ae=*\):\
+ :sb=':se=':\
+ :kw=and array assert begin case const div do downto else end file for\
+ forward function goto if in label mod nil not of or packed procedure\
+ program record repeat set then to type until var while with oct hex\
+ external:
+ISP|isp|i:\
+ :cb=!:ce=!|$:oc:\
+ :kw=and begin decode define end eql eqv geq gtr if leave leq lss mod\
+ neq next not or otherwise repeat restart resume sr0 sr1 srd srr sl0 sl1\
+ sld slr tst xor:
+SH|sh:\
+ :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=break case cd continue do done \
+ elif else esac eval exec exit export \
+ fi for if in then while until \
+ read readonly set shift test trap umask wait:
+CSH|csh:\
+ :bb={:be=}:cb=#:ce=$:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=alias alloc break breaksw case cd chdir continue default\
+ echo else end endif endsw exec exit foreach \
+ glob goto history if logout nice nohup onintr repeat set\
+ setenv shift source switch then time \
+ while umask unalias unset wait while @ env \
+ argv child home ignoreeof noclobber noglob \
+ nomatch path prompt shell status verbose :
+ldl|LDL:\
+ :pb=^\p\::bb=\::be=;:cb=/*:ce=*/:sb=":se=\e":\
+ :kw=constant functions grammar reswords tokens add1 addste\
+ car cdr check colno cond cons copy defun divide empty enter\
+ eq equal findattr firstchild ge getattr getfield gt hash label\
+ lambda lastchild le leftsibling lookone lookup lt minus name ne\
+ newnode nextcom nil null parent plus precnl prevcom prog progn\
+ quote reglob return rightsibling self set setattr setfield setq\
+ stjoin sub1 t times tnull tokno ttype:
+Icon|icon|I:\
+ :pb=^\d?procedure\d\p\d?\(\a?\):\
+ :bb=(^\d?procedure\d\p\d?\(\a?\))|{:be=}|(^\d?end\d?$):\
+ :cb=#:ce=$:\
+ :sb=":se=\e":lb=':le=\e':tl:\
+ :kw=break by case create default do dynamic else end every external\
+ fail global if initial local next not of procedure record\
+ repeat return static suspend then to until using while\
+ &ascii &clock &cset &date &dateline &errout &fail &host &input\
+ &lcase &level &main &null &output &pos &random &source &subject\
+ &time &trace &ucase &version:
+ratfor|rat|r:\
+ :pb=(subroutine|function)\d\p\d?\(\a?\):\
+ :bb=(subroutine|function)\d\p\d?\(\a?\):be=^\d?end:\
+ :cb=#:ce=$:\
+ :sb=":se=\e":lb=':le=\e':oc:\
+ :kw=DRETURN DRIVER arith break case character default define do\
+ else elsedef enddef filedes for function goto if ifdef ifelse\
+ ifnotdef include incr integer linepointer next opeq pointer\
+ real repeat return select string subroutine substr until:
+modula2|mod2|m2:\
+ :pb=(^\d?(procedure|function|module)\d\p\d|\(|;|\:):\
+ :bb=\d(begin|case|for|if|loop|record|repeat|while|with)\d:\
+ :be=\dend|;:\
+ :cb={:ce=}:\
+ :ab=\(*:ae=*\):\
+ :sb=":se=":\
+ :oc:\
+ :kw=and array begin by case const\
+ definition div do else elsif end exit export\
+ for from if implementation import in\
+ loop mod module not of or pointer procedure qualified\
+ record repeat return set then to type\
+ until var while with:
+yacc|Yacc|y:\
+ :cb=/*:ce=*/:sb=":se=\e":lb=':le=\e':tl:\
+ :kw=%{ %} %% %union %token %type\
+ #else #endif #if #ifdef #ifndef #include #undef # define else endif\
+ if ifdef ifndef include undef:
+C++|c++:\
+ :pb=^\a?\d?*?\d?\p\d?\(\a?\)(\d|{):\
+ :bb={:be=}:cb=/*:ce=*/:ab=//:\
+ :ae=$:sb=":se=\e":lb=':\
+ :le=\e':tl:\
+ :kw=asm auto break case char continue default do double else enum\
+ extern float for fortran goto if int long register return short\
+ sizeof static struct switch typedef union unsigned while void #define\
+ #else #endif #if #ifdef #ifndef #include #undef # define endif\
+ ifdef ifndef include undef defined\
+ class const delete friend inline new operator overload private\
+ protected public virtual:
+#
+# Hack alert: defining function calls as `alternate comments' (ab/ae) seems
+# to be the only way to avoid major confusion inside vfontedpr for calls like:
+# &packagename'function;
+#
+Perl|perl|pl:\
+ :pb=sub\d\p\d:bb={:be=}:cb=#:ce=$:nc=\$#:tl:\
+ :ab=&:ae=(;|\d|,):\
+ :sb=":se=(\e"|$):lb=':le=(\e'|$):\
+ :kw=do if unless while until else elsif for foreach continue\
+ next redo sub last goto return die exit require:
diff --git a/usr.bin/vi/Makefile b/usr.bin/vi/Makefile
new file mode 100644
index 000000000000..a37a2ce4fe4c
--- /dev/null
+++ b/usr.bin/vi/Makefile
@@ -0,0 +1,76 @@
+#
+#
+
+.include <src.opts.mk>
+
+PACKAGE= vi
+SRCDIR= ${SRCTOP}/contrib/nvi
+SUBDIR+= catalog
+
+WARNS?= 0 # some warn issues on 32 bit machines
+
+VI= nvi
+EX= nex
+VIEW= nview
+
+PROG= nvi
+
+CFLAGS+= -D__REGEX_PRIVATE -D_XOPEN_SOURCE_EXTENDED=1
+
+LINKS= ${BINDIR}/${VI} ${BINDIR}/${EX} ${BINDIR}/${VI} ${BINDIR}/${VIEW}
+LINKS+= ${BINDIR}/${VI} ${BINDIR}/vi ${BINDIR}/${EX} ${BINDIR}/ex
+LINKS+= ${BINDIR}/${VI} ${BINDIR}/view
+
+MAN= ${SRCDIR}/man/vi.1
+MLINKS+=vi.1 ex.1 vi.1 view.1
+MLINKS+=vi.1 nex.1 vi.1 nview.1 vi.1 nvi.1
+
+.PATH: ${SRCDIR}/common
+.PATH: ${SRCDIR}/ex
+.PATH: ${SRCDIR}/cl
+.PATH: ${SRCDIR}/vi
+.PATH: ${SRCDIR}/regex
+
+CFLAGS+=-I${.CURDIR} -I${SRCDIR} -I${SRCDIR}/regex \
+ -I${.CURDIR}/ex
+
+LIBADD= util tinfow ncursesw
+
+.if ${MK_ICONV} == "yes" && !defined(RESCUE)
+CFLAGS+= -DUSE_ICONV -DICONV_TRADITIONAL
+.endif
+
+CLEANFILES+=${EX}
+
+# Vi curses sources
+SRCS+= cl_funcs.c cl_main.c cl_read.c cl_screen.c cl_term.c
+
+# General sources.
+SRCS+= conv.c cut.c delete.c encoding.c exf.c key.c line.c log.c main.c mark.c msg.c options.c \
+ options_f.c put.c recover.c screen.c search.c seq.c util.c
+
+# Ex source.
+SRCS+= ex.c ex_abbrev.c ex_append.c ex_args.c ex_argv.c ex_at.c ex_bang.c \
+ ex_cd.c ex_cmd.c ex_cscope.c ex_delete.c ex_display.c \
+ ex_edit.c ex_equal.c ex_file.c ex_filter.c ex_global.c \
+ ex_init.c ex_join.c ex_map.c ex_mark.c ex_mkexrc.c ex_move.c \
+ ex_open.c ex_preserve.c ex_print.c ex_put.c ex_quit.c \
+ ex_read.c ex_screen.c ex_script.c ex_set.c ex_shell.c \
+ ex_shift.c ex_source.c ex_stop.c ex_subst.c ex_tag.c \
+ ex_txt.c ex_undo.c ex_usage.c ex_util.c ex_version.c ex_visual.c \
+ ex_write.c ex_yank.c ex_z.c
+
+# Vi source.
+SRCS+= getc.c v_at.c v_ch.c v_cmd.c v_delete.c v_ex.c v_increment.c v_init.c \
+ v_itxt.c v_left.c v_mark.c v_match.c v_paragraph.c v_put.c v_redraw.c \
+ v_replace.c v_right.c v_screen.c v_scroll.c v_search.c v_section.c \
+ v_sentence.c v_status.c v_txt.c v_ulcase.c v_undo.c \
+ v_util.c v_word.c v_xchar.c v_yank.c v_z.c v_zexit.c vi.c
+
+# Vi screen source.
+SRCS+= vs_line.c vs_msg.c vs_refresh.c vs_relative.c vs_smap.c vs_split.c
+
+# Wide char regex
+SRCS+= regcomp.c regerror.c regexec.c regfree.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vi/Makefile.depend b/usr.bin/vi/Makefile.depend
new file mode 100644
index 000000000000..6cf2238b9f30
--- /dev/null
+++ b/usr.bin/vi/Makefile.depend
@@ -0,0 +1,19 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vi/catalog/Makefile b/usr.bin/vi/catalog/Makefile
new file mode 100644
index 000000000000..ec76271139f4
--- /dev/null
+++ b/usr.bin/vi/catalog/Makefile
@@ -0,0 +1,166 @@
+# $Id: Makefile,v 9.0 2012/10/19 15:13:11 zy Exp $
+
+.include <bsd.own.mk>
+
+PACKAGE=vi
+V= ${.CURDIR}/../../../contrib/nvi
+
+FILESGROUPS+=VICAT
+CAT= dutch english french german polish ru_RU.KOI8-R spanish swedish \
+ uk_UA.KOI8-U zh_CN.GB2312 tr_TR.ISO8859-9 tr_TR.UTF-8
+VICAT= ${CAT}
+VICATDIR= ${FILESDIR}
+VICATPACKAGE= ${PACKAGE}
+
+SCAN= ${V}/cl/*.c ${V}/common/*.c ${V}/ex/*.c ${V}/vi/*.c
+
+.PATH: ${V}/catalog
+
+all: dump
+
+build-tools: dump
+WARNS= 3
+
+# Helper since iconv is non trivial to make a build tool
+utf8convert:
+.for c in dutch french german spanish swedish
+ iconv -f ISO8859-1 -t UTF-8 $V/catalog/$c.base > $c.UTF-8.base
+.endfor
+ iconv -f ISO8859-2 -t UTF-8 $V/catalog/polish.base > polish.UTF-8.base
+ iconv -f GB2312 -t UTF-8 $V/catalog/zh_CN.GB2312.base > zh_CN.UTF-8.base
+ iconv -f KOI8-R -t UTF-8 $V/catalog/ru_RU.KOI8-R.base > ru_RU.UTF-8.base
+ iconv -f KOI8-U -t UTF-8 $V/catalog/uk_UA.KOI8-U.base > uk_UA.UTF-8.base
+
+.for c in dutch french german polish spanish swedish zh_CN ru_RU uk_UA
+CAT+= $c.UTF-8
+.endfor
+
+.for c in ${CAT}
+${c}: ${c}.base
+ echo "... $c"; \
+ rm -f $c; \
+ env LC_ALL=C sort -u ${.ALLSRC} | \
+ awk '{ \
+ if ($$1 == 1) { \
+ print "\nMESSAGE NUMBER 1 IS NOT LEGAL"; \
+ exit 1; \
+ } \
+ if (++nline > $$1) { \
+ print "DUPLICATE MESSAGE NUMBER " $$1; \
+ exit 1; \
+ } \
+ print $$0; \
+ }' | \
+ sed -e '1s/^/$$set 1~$$quote "~/; 1y/~/\n/' | \
+ gencat $c /dev/stdin; \
+ chmod 444 $c; \
+ if grep DUPLICATE $c > /dev/null; then \
+ grep DUPLICATE $@; \
+ fi; \
+ if grep 'NOT LEGAL' $c > /dev/null; then \
+ grep 'NOT LEGAL' $@; \
+ fi
+.endfor
+
+CHK= dutch.check english.check french.check german.check \
+ polish.check ru_RU.KOI8-R.check spanish.check swedish.check \
+ uk_UA.KOI8-U.check zh_CN.GB2312.check
+check: ${CHK}
+.for c in ${CAT}
+${c}.check: ${c}.base
+ @echo "... $c"; \
+ f=${.ALLSRC:S;.base$;;}; \
+ (echo "Unused message id's (this is okay):"; \
+ awk '{ \
+ while (++nline < $$1) \
+ printf "%03d\n", nline; \
+ }' < $$f.base; \
+ echo =========================; \
+ echo "MISSING ERROR MESSAGES (Please add!):"; \
+ awk '{print $$1}' < $$f.base | sort -u > __ck1; \
+ awk '{print $$1}' < english.base | sort -u > __ck2; \
+ comm -13 __ck1 __ck2; \
+ echo =========================; \
+ echo "Extra error messages (just delete them):"; \
+ comm -23 __ck1 __ck2; \
+ echo =========================; \
+ echo "MESSAGES WITH THE SAME MESSAGE ID's (FIX!):"; \
+ for j in \
+ `sed '/^$$/d' < $$f.base | LC_ALL=C sort -u | \
+ awk '{print $$1}' | uniq -d`; do \
+ egrep $$j $$f.base; \
+ done; \
+ echo =========================; \
+ echo "Duplicate messages, both id and message (this is okay):"; \
+ sed '/^$$/d' < $$f.base | LC_ALL=C sort | uniq -c | \
+ awk '$$1 != 1 { print $$0 }' | sort -n; \
+ echo =========================) > $c
+.endfor
+
+english.base: dump ${SCAN} #Makefile
+ ${BTOOLSPATH:U.}/dump ${SCAN} |\
+ sed -e '/|/!d' \
+ -e 's/|/ "/' \
+ -e 's/^"//' |\
+ LC_ALL=C sort -nu > $@
+
+
+DEPENDOBJS+= dump
+dump: ${BUILD_TOOLS_META}
+
+CLEANFILES+= dump ${CAT} english.base *.check __ck1 __ck2
+
+CATALOGS= ${CAT}
+NLLINKS= nl_NL
+ENLINKS= en_AU en_CA en_GB en_NZ en_US
+FRLINKS= fr_BE fr_CA fr_CH fr_FR
+DELINKS= de_AT de_CH de_DE
+ESLINKS= es_ES
+SVLINKS= sv_SE
+PLLINKS= pl_PL
+
+FILES= ${CATALOGS}
+FILESDIR= ${SHAREDIR}/vi/catalog
+SYMLINKS=
+.for l in ${NLLINKS}
+SYMLINKS+= dutch ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= dutch ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= dutch.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+.for l in ${ENLINKS}
+SYMLINKS+= english ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= english ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= english ${FILESDIR}/$l.US-ASCII
+SYMLINKS+= english ${FILESDIR}/$l.UTF-8
+.endfor
+SYMLINKS+= english ${FILESDIR}/POSIX
+SYMLINKS+= english ${FILESDIR}/C
+.for l in ${FRLINKS}
+SYMLINKS+= french ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= french ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= french.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+.for l in ${DELINKS}
+SYMLINKS+= german ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= german ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= german.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+.for l in ${ESLINKS}
+SYMLINKS+= spanish ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= spanish ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= spanish.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+.for l in ${SVLINKS}
+SYMLINKS+= swedish ${FILESDIR}/$l.ISO8859-1
+SYMLINKS+= swedish ${FILESDIR}/$l.ISO8859-15
+SYMLINKS+= swedish.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+.for l in ${PLLINKS}
+SYMLINKS+= polish ${FILESDIR}/$l.ISO8859-2
+SYMLINKS+= polish.UTF-8 ${FILESDIR}/$l.UTF-8
+.endfor
+SYMLINKS+= zh_CN.GB2312 ${FILESDIR}/zh_CN.GB18030
+SYMLINKS+= zh_CN.GB2312 ${FILESDIR}/zh_CN.GBK
+SYMLINKS+= zh_CN.GB2312 ${FILESDIR}/zh_CN.eucCN
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vi/catalog/Makefile.depend b/usr.bin/vi/catalog/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/vi/catalog/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vi/catalog/dutch.UTF-8.base b/usr.bin/vi/catalog/dutch.UTF-8.base
new file mode 100644
index 000000000000..eca193c28c04
--- /dev/null
+++ b/usr.bin/vi/catalog/dutch.UTF-8.base
@@ -0,0 +1,306 @@
+002 "regel te lang"
+003 "kan regel %lu niet verwijderen"
+004 "kan niet toevoegen aan regel %lu"
+005 "kan niet invoegen vooraan regel %lu"
+006 "kan regel %lu niet opslaan"
+007 "kan laatste regel niet lezen"
+008 "Fout: kan regel %lu niet vinden"
+009 "log bestand"
+010 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+011 "geen wijzigingen om ongedaan te maken"
+012 "Er vindt geen logging plaats, kan wijzigingen niet ongedaan maken"
+013 "Er vindt geen logging plaats, herhaling niet mogelijk"
+014 "geen wijzigingen om te herhalen"
+015 "%s/%d: schrijven naar log mislukt"
+016 "Vi's standaard invoer en uitvoer moeten aan een terminal gekoppeld zijn"
+017 "Merk %s: niet gezet"
+018 "Merk %s: de regel is verwijderd"
+019 "Merk %s: de cursor positie bestaat niet meer"
+020 "Fout: "
+021 "nieuw bestand"
+022 "naam veranderd"
+023 "gewijzigd"
+024 "ongewijzigd"
+025 "NIET BEVEILIGD"
+026 "niet schrijfbaar"
+027 "regel %lu uit %lu [%ld%%]"
+028 "leeg bestand"
+029 "regel %lu"
+030 "Het bestand %s is geen message catalog"
+031 "Niet in staat om de standaard %s optie in te stellen"
+032 "Gebruik: %s"
+033 "set: optie %s onbekend: 'set all' laat alle opties zien"
+034 "set: [no]%s optie kan geen waarde hebben"
+035 "set: %s optie moet een waarde hebben"
+036 "set: %s optie: %s"
+037 "set: %s optie: %s: getal is te groot"
+038 "set: %s optie: %s is een ongeldige waarde"
+039 "set: %s optie moet een waarde hebben"
+040 "Te weinig kolommen op het scherm, minder dan %d"
+041 "Aantal kolommen te groot, meer dan %d"
+042 "Te weinig regels op het scherm, minder dan %d"
+043 "Aantal regels te groot, meer dan %d"
+044 "De lisp optie is niet ondersteund"
+045 "messages niet uitgeschakeld: %s"
+046 "messages niet geactiveerd: %s"
+047 "De %s optie moet karakter paren bevatten"
+053 "De standaard buffer is leeg"
+054 "Buffer %s is leeg"
+055 "Bestanden met newlines in de naam kunnen niet hersteld worden"
+056 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+057 "Bestand wordt gecopieerd voor herstel..."
+058 "Herstel mechanisme werkt niet: %s"
+059 "Wijzigingen kunnen niet ongedaan gemaakt worden als deze sessie mislukt"
+060 "Kon bestand niet veilig stellen: %s"
+061 "Bestand wordt gecopieerd voor herstel..."
+062 "Informatie met betrekking tot gebruiker nummer %u niet gevonden"
+063 "Kan herstel bestand niet beveiligen"
+064 "herstel buffer overgelopen"
+065 "herstel bestand"
+066 "%s: verminkt herstel bestand"
+067 "%s: verminkt herstel bestand"
+068 "U heeft geen bestand genaamd %s te herstellen"
+069 "U kan eerdere versies van dit bestand herstellen"
+070 "U kan nog meer bestanden herstellen"
+071 "kan geen email versturen: %s"
+072 "Bestand leeg; niets om te doorzoeken"
+073 "Einde van het bestand bereikt zonder dat het patroon gevonden is"
+074 "Geen vorig zoek patroon"
+075 "Patroon niet gevonden"
+076 "Begin van het bestand bereikt zonder dat het patroon gevonden is"
+077 "Zoek-operatie omgeslagen"
+078 "Bezig met zoeken..."
+079 "Geen niet-printbaar karakter gevonden"
+080 "Onbekend commando"
+082 "Commando niet beschikbaar in ex mode"
+083 "Aantal mag niet nul zijn"
+084 "%s: ongeldige regel aanduiding"
+085 "Interne fout in syntax tabel (%s: %s)"
+086 "Gebruik: %s"
+087 "%s: tijdelijke buffer niet vrijgegeven"
+088 "Vlag offset voor regel 1"
+089 "Vlag offset voorbij bestands einde"
+090 "bestand/scherm veranderd tijdens uitvoeren van @ in een blok"
+091 "bestand/scherm veranderd tijdens uitvoeren van globaal/v commando"
+092 "Ex commando mislukt: rest van commando(s) genegeerd"
+093 "Ex commando mislukt: gemappede toetsen genegeerd"
+094 "Het tweede adres is kleiner dan het eerste"
+095 "Geen merk naam opgegeven"
+096 "\\ niet gevolgd door / of ?"
+097 "Referentie aan een regel nummer kleiner dan 0"
+098 "Het %s commando is onbekend"
+099 "Adres waarde te groot"
+100 "Adres waarde te klein"
+101 "Ongeldige adres combinatie"
+102 "Ongeldig adres: slechts %lu regels in het bestand aanwezig"
+103 "Ongeldig adres: het bestand is leeg"
+104 "Het %s commando staat het adres 0 niet toe"
+105 "Geen afkortingen om weer te geven"
+106 "Afkortingen moeten eindigen met een \"woord\" letter"
+107 "Afkortingen mogen geen tabulaties of spaties bevatten"
+108 "Afkortingen mogen geen woord/niet-woord karakters mengen, behalve aan het einde"
+109 "\"%s\" is geen afkorting"
+110 "Vi commando mislukt: gemappede toetsen genegeerd"
+111 "Dit is het laatste bestand"
+112 "Dit is het eerste bestand"
+113 "Dit is het eerste bestand"
+114 "lijst met bestanden is leeg"
+115 "Geen voorgaand commando om \"!\" te vervangen"
+116 "Geen bestandsnaam voor %%"
+117 "Geen bestandsnaam voor #"
+118 "Fout: execl: %s"
+119 "I/O fout: %s"
+120 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+121 "Kan uw home directory niet vinden"
+122 "Nieuwe huidige directory: %s"
+123 "Geen cut buffers aanwezig"
+124 "Het %s commando kan niet gebruikt worden in een globaal of v commando"
+125 "%s/%s: niet gelezen: noch U noch root is de eigenaar"
+126 "%s/%s: niet gelezen: U bent niet de eigenaar"
+127 "%s/%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+128 "%s: niet gelezen: noch U noch root is de eigenaar"
+129 "%s: niet gelezen: U bent niet de eigenaar"
+130 "%s: niet gelezen: kan gewijzigd worden door andere gebruikers"
+131 "Geen volgende regel om samen te voegen"
+132 "Geen input map entries"
+133 "Geen command map entries"
+134 "Het %s karakter kan niet ge-remapped worden"
+135 "\"%s\" is niet gemapped"
+136 "Merk naam moet een enkel karakter zijn"
+137 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+138 "Nieuw .exrc bestand: %s. "
+139 "doel regel ligt in het blok"
+140 "Het open commando vereist dat de open optie actief is"
+141 "Het open commando is nog niet ondersteund"
+142 "Kan dit bestand niet veilig stellen"
+143 "Bestand veilig gesteld"
+144 "%s resulteert in te veel bestandsnamen"
+145 "Alleen echte bestanden en named pipes kunnen gelezen worden"
+146 "%s: lees beveiliging niet beschikbaar"
+147 "Bezig met lezen..."
+148 "%s: %lu regels, %lu karakters"
+149 "Geen achtergrond schermen aanwezig"
+150 "Het script commando is alleen beschikbaar in vi mode"
+151 "Geen comando om uit te voeren"
+152 "shiftwidth optie op 0 gezet"
+153 "Count te groot"
+154 "Count te klein"
+155 "Reguliere expressie opgegeven; r vlag heeft geen betekenis"
+156 "De #, l en p vlaggen kunnen niet gecombineerd worden met de c vlag in vi mode"
+157 "Geen match gevonden"
+158 "Geen voorafgaande tag aanwezig"
+159 "Minder dan %s elementen op de tags stapel; gebruik :display t[ags]"
+160 "Geen bestand genaamd %s op de tags stapel; gebruik :display t[ags]"
+161 "Kies Enter om door te gaan: "
+162 "%s: tag niet gevonden"
+163 "%s: verminkte tag in %s"
+164 "%s: Het regel nummer van deze tag is voorbij het einde van het bestand"
+165 "De tags stapel is leeg"
+166 "%s: zoek patroon niet gevonden"
+167 "%d andere bestanden te wijzigen"
+168 "Buffer %s is leeg"
+169 "Bevestig wijziging? [n]"
+170 "Onderbroken"
+171 "Geen voorafgaande buffer om uit te voeren"
+172 "Geen vorige reguliere expressie"
+173 "Het %s commando vereist dat er een bestand geladen is"
+174 "Gebruik: %s"
+175 "Het visual commando vereist dat de open optie actief is"
+177 "Leeg bestand"
+178 "Geen voorafgaand F, f, T of t zoek commando"
+179 "%s niet gevonden"
+180 "Geen voorafgaand bestand te bewerken"
+181 "Cursor niet op een getal"
+182 "Getal wordt te groot"
+183 "Getal wordt te klein"
+184 "Geen overeenkomstig karakter op deze regel"
+185 "Overeenkomstig karakter niet gevonden"
+186 "Geen karakters te vervangen"
+187 "Geen ander scherm aanwezig"
+188 "Karakters achter het zoek patroon, de regel offset, en/of het z commando"
+189 "Geen voorafgaand zoek patroon"
+190 "Zoekopdracht na omslag teruggekeerd op originele positie"
+191 "Afkorting overschrijdt expansie limiet: karakters genegeerd"
+192 "Ongeldig karakter; quote to enter"
+193 "Reeds aan het begin van de invoer"
+194 "Niet meer karakters te verwijderen"
+195 "Verplaatsing voorbij het einde van het bestand"
+196 "Verplaatsing voorbij het einde van de regel"
+197 "Cursor niet verplaatst"
+198 "Reeds aan het begin van het bestand"
+199 "Verplaatsing voorbij het begin van het bestand"
+200 "Reeds in de eerste kolom"
+201 "Buffers moeten voor het commando opgegeven worden"
+202 "Reeds bij het einde van het bestand"
+203 "Reeds bij het einde van de regel"
+204 "%s is geen vi commando"
+205 "Gebruik: %s"
+206 "Geen karakters te verwijderen"
+207 "Het Q commando vereist de ex terminal interface"
+208 "Geen commando om te herhalen"
+209 "Het bestand is leeg"
+210 "%s mag niet gebruikt worden als een verplaatsings commando"
+211 "Al in commando mode"
+212 "Cursor niet in een woord"
+214 "Windows optie waarde is te groot, maximum is %u"
+215 "Toevoegen"
+216 "Veranderen"
+217 "Commando"
+218 "Invoegen"
+219 "Vervangen"
+220 "Verplaatsing voorbij het eind van het scherm"
+221 "Verplaatsing voorbij het begin van het scherm"
+222 "Scherm moet meer dan %d regels hebben om het te kunnen splitsen"
+223 "Er zijn geen achtergrond schermen"
+224 "Er is geen achtergrond scherm waarin U bestand %s aan het bewerken bent"
+225 "U kan uw enige scherm niet in de achtergrond zetten"
+226 "Het scherm kan slechts verkleind worden tot %d regels"
+227 "Het scherm kan niet kleiner"
+228 "Het scherm kan niet groter"
+230 "Dit scherm kan niet gesuspend worden"
+231 "Onderbroken: gemappede toetsen genegeerd"
+232 "vi: tijdelijke buffer niet vrijgegeven"
+233 "Deze terminal heeft geen %s toets"
+234 "Er kan slechts een buffer opgegeven worden"
+235 "Getal groter dan %lu"
+236 "Onderbroken"
+237 "Aanmaken van tijdelijk bestand is mislukt"
+238 "Waarschuwing: %s is geen regulier bestand"
+239 "%s is al geopend, bestand is in deze sessie niet schrijfbaar"
+240 "%s: verwijdering mislukt"
+241 "%s: sluiting mislukt"
+242 "%s: verwijdering mislukt"
+243 "%s: verwijdering mislukt"
+244 "Bestand niet schrijfbaar, niet weggeschreven; gebruik ! om het te forceren"
+245 "Bestand niet schrijfbaar, niet weggeschreven"
+246 "%s bestaat al, niet weggeschreven; gebruik ! om het te forceren"
+247 "%s bestaat al, niet weggeschreven"
+248 "Gebruik ! om een incompleet bestand weg te schrijven"
+249 "Bestand incompleet, niet weggeschreven"
+250 "%s: bestand op disk nieuwer dan deze versie; gebruik ! om het te forceren"
+251 "%s: bestand op disk nieuwer dan deze versie"
+252 "%s: schrijf beveiliging niet beschikbaar"
+253 "Bezig met schrijven..."
+254 "%s: WAARSCHUWING: BESTAND INCOMPLEET"
+255 "Reeds op de eerste tag van deze groep"
+256 "%s: nieuw bestand: %lu regels, %lu karakters"
+257 "%s: %lu regels, %lu karakters"
+258 "%s resulteert in te veel bestandsnamen"
+259 "%s: geen normaal bestand"
+260 "%s: U bent niet de eigenaar"
+261 "%s: kan gewijzigd worden door andere gebruikers"
+262 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+263 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik :edit! om het te forceren"
+264 "Bestand gewijzigd sinds laatste schrijfactie; schrijf het weg of gebruik ! om het te forceren"
+265 "Tijdelijk bestand; exit negeert wijzigingen"
+266 "Bestand niet schrijfbaar, wijzigingen niet automatisch weggeschreven"
+267 "log opnieuw gestart"
+268 "Bevestig? [ynq]"
+269 "Druk op een toets om door te gaan: "
+270 "Druk op een toets om door te gaan [: voor meer ex commandos]: "
+271 "Druk op een toets om door te gaan [q om te stoppen]: "
+272 "Deze vorm van %s vereist de ex terminal interface"
+273 "Entering ex input mode."
+274 "Commando mislukt, nog geen bestand geladen."
+275 " doorgaan?"
+276 "Onverwacht character event"
+277 "Onverwacht end-of-file event"
+278 "Geen match gevonden voor dit patroon"
+279 "Onverwacht interrupt event"
+280 "Onverwacht quit event"
+281 "Onverwacht repaint event"
+282 "Reeds op de laatste tag van deze groep"
+283 "Het %s command vereist de ex terminal interface"
+284 "Deze vorm van %s is niet ondersteund als de secure edit optie actief is"
+285 "Onverwacht string event"
+286 "Onverwacht timeout event"
+287 "Onverwacht write event"
+289 "Shell expansies zijn niet ondersteund als de secure edit optie actief is"
+290 "Het %s commando is niet ondersteund als de secure edit optie actief is"
+291 "set: %s mag niet uitgezet worden"
+292 "Scherm te klein."
+293 "toegevoegd"
+294 "gewijzigd"
+295 "verwijderd"
+296 "samengevoegd"
+297 "verplaatst"
+298 "verschoven"
+299 "gebufferd"
+300 "regel"
+301 "regels"
+302 "Vi was niet geladen met een Tcl interpreter"
+303 "Bestand gewijzigd sinds het de laatste keer weg is geschreven."
+304 "Shell expansie mislukt"
+305 "Geen %s edit optie opgegeven"
+306 "Vi was niet geladen met een Perl interpreter"
+307 "Geen ex commando om uit te voeren"
+308 "Kies <CR> om commando uit te voeren, :q om te stoppen"
+309 "Gebruik \"cscope help\" voor uitleg"
+310 "Nog geen cscope connectie aanwezig"
+311 "%s: onbekend zoek type: gebruik een van %s"
+312 "%d: onbekende cscope sessie"
+313 "set: de %s optie mag nooit aangezet worden"
+314 "set: de %s optie mag nooit op 0 gezet worden"
+315 "%s: toegevoegd: %lu regels, %lu karakters"
+316 "Onverwacht resize event"
+317 "%d bestanden te wijzigen"
diff --git a/usr.bin/vi/catalog/french.UTF-8.base b/usr.bin/vi/catalog/french.UTF-8.base
new file mode 100644
index 000000000000..eb6aad000f36
--- /dev/null
+++ b/usr.bin/vi/catalog/french.UTF-8.base
@@ -0,0 +1,306 @@
+002 "Dépassement de longueur de ligne"
+003 "impossible de supprimer la ligne %lu"
+004 "impossible d'ajouter à la ligne %lu"
+005 "impossible d'insérer devant la ligne %lu"
+006 "impossible de stocker la ligne %lu"
+007 "impossible d'obtenir la dernière ligne"
+008 "Erreur : impossible de récupérer la ligne %lu"
+009 "Fichier journal"
+010 "Aucune journalisation n'étant effectuée, impossible d'annuler"
+011 "Aucune action à annuler"
+012 "Aucune journalisation n'étant effectuée, impossible d'annuler"
+013 "Aucune journalisation n'étant effectuée, reprise actualisée impossible"
+014 "Aucune action à refaire"
+015 "%s/%d : Erreur d'écriture de journal"
+016 "L'entrée et la sortie Vi standards doivent être un terminal"
+017 "Marque %s : non définie"
+018 "Marque %s : la ligne a été supprimée"
+019 "Marque %s : la position du curseur n'existe plus"
+020 "Erreur : "
+021 "nouveau fichier"
+022 "le nom a changé"
+023 "modifié"
+024 "non modifié"
+025 "DÉVERROUILLÉ"
+026 "lecture seule"
+027 "ligne %lu de %lu [%ld%%]"
+028 "fichier vide"
+029 "ligne %lu"
+030 "Ce fichier %s n'est pas un catalogue de messages"
+031 "Impossible de configurer option %s par défaut"
+032 "Utilisation : %s"
+033 "Définition : pas d'option %s : 'set all' donne toutes les valeurs optionnelles"
+034 "Définition : option [no]%s ne prend pas de valeur"
+035 "Définition : l'option %s n'est pas booléenne"
+036 "Définition : option %s : %s"
+037 "Définition : option %s : %s : Dépassement de valeur"
+038 "Définition : option %s : %s n'est pas un nombre valide"
+039 "Définition : l'option %s n'est pas booléenne"
+040 "Les colonnes de l'écran sont trop petites, inférieures à %d"
+041 "Les colonnes de l'écran sont trop grandes, supérieures à %d"
+042 "Les lignes de l'écran sont trop courtes, inférieures à %d"
+043 "Les lignes de l'écran sont trop longues, supérieures à %d"
+044 "L'option lisp n'est pas implémentée"
+045 "Les messages ne sont pas désactivés : %s"
+046 "Les messages ne sont pas activés : %s"
+047 "L'option de %s doit être en groupe de deux caractères"
+053 "Le tampon par défaut est vide"
+054 "Le tampon %s est vide"
+055 "Les fichiers dont le nom contient des caractères de saut de ligne sont irrécupérables"
+056 "Impossible de récupérer les modifications si la session échoue"
+057 "Copie en cours du fichier pour récupération..."
+058 "La préservation a échoué : %s"
+059 "Impossible de récupérer les modifications si la session échoue"
+060 "La sauvegarde du fichier a échoué : %s"
+061 "Copie en cours du fichier pour récupération..."
+062 "Les renseignements sur l'identité %u de l'utilisateur sont introuvables"
+063 "Impossible de verrouiller le fichier de récupération"
+064 "Débordement de tampon du fichier de récupération"
+065 "Fichier de récupération"
+066 "%s : Fichier de récupération malformé"
+067 "%s : Fichier de récupération malformé"
+068 "Aucun fichier nommé %s à récupérer, que vous puissiez lire"
+069 "Il existe des versions récupérables antérieures à ce fichier"
+070 "Vous avez d'autres fichiers à récupérer"
+071 "pas d'envoi d'email : %s"
+072 "Fichier vide, rien à rechercher"
+073 "Fin de fichier atteinte sans trouver le motif"
+074 "Pas de motif de recherche précédent"
+075 "Motif introuvable"
+076 "Début du fichier atteint sans trouver le motif"
+077 "La recherche est revenue à son point de départ"
+078 "Recherche en cours..."
+079 "Caractère non-imprimable introuvable"
+080 "Nom de commande inconnu"
+082 "%s : Commande non disponible en ex mode"
+083 "Le compteur ne peut être zéro"
+084 "%s : mauvaise spécification de ligne"
+085 "Erreur de tableau de syntaxe interne (%s: %s)"
+086 "Utilisation : %s"
+087 "%s : tampon temporaire non libéré"
+088 "Décalage de drapeau hors de la ligne 1"
+089 "Décalage de drapeau hors de la fin du fichier"
+090 "@ avec plage, en cours d'exécution quand le fichier/l'écran a changé"
+091 "Commande Global/v en cours d'exécution quand le fichier/l'écran a changé"
+092 "La commande ex a échoué : commandes en attente abandonnées"
+093 "La commande ex a échoué : les touches affectées sont abandonnées"
+094 "La deuxième adresse est plus petite que la première"
+095 "Aucun nom de marque fourni"
+096 "\\ non suivi par / ou ?"
+097 "Référence à un numéro de ligne inférieure à 0"
+098 "La commande %s est inconnue"
+099 "Dépassement de la valeur adresse"
+100 "Dépassement négatif de la valeur adresse"
+101 "Combinaison d'adresse non valide"
+102 "Adresse non valide : il n'y a que %lu lignes dans ce fichier"
+103 "Adresse non valide : le fichier est vide"
+104 "La commande %s ne permet pas une adresse de 0"
+105 "Pas d'abréviations à afficher"
+106 "Les abréviations doivent finir par un caractère \"mot\""
+107 "Les abréviations ne peuvent pas contenir de tabulations ni d'espaces"
+108 "Les abréviations ne peuvent pas contenir un mélange de caractères mot/non-mot, sauf à la fin"
+109 "\"%s\" n'est pas une abréviation"
+110 "La commande Vi a échoué : Les touches affectées ont été abandonnées"
+111 "Plus de fichiers à éditer"
+112 "Pas de fichiers précédents à éditer"
+113 "Pas de fichiers précédents à rembobiner"
+114 "Pas de liste de fichiers à afficher"
+115 "Pas de commande précédente à remplacer \"!\""
+116 "Pas de nom de fichier à substituer à %%"
+117 "Pas de nom de fichier à substituer à #"
+118 "Erreur : execl : %s"
+119 "Erreur E/S : %s"
+120 "Fichier modifié depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
+121 "Impossible de trouver l'emplacement du répertoire d'origine"
+122 "Nouveau répertoire en cours : %s"
+123 "Pas de tampon de coupure à afficher"
+124 "La commande %s ne peut pas être utilisée à l'intérieur d'une commande globale ou commande v"
+125 "%s/%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires "
+126 "%s/%s : échec de source : vous n'êtes pas le propriétaire"
+127 "%s/%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
+128 "%s : échec de source : ni vous ni le super-utilisateur n'êtes les propriétaires"
+129 "%s : échec de source : vous n'êtes pas le propriétaire"
+130 "%s : échec de source : peut être écrit par un utilisateur autre que le propriétaire"
+131 "Pas de lignes suivantes à joindre"
+132 "Pas d'entrées de mappage d'entrée"
+133 "Pas d'entrées de mappage de commandes"
+134 "Le caractère %s ne peut pas être remappé"
+135 "\"%s\" n'est pas actuellement mappé"
+136 "Les noms de marque ne doivent avoir qu'un caractère"
+137 "%s existe, non enregistré; utiliser ! pour outrepasser"
+138 "Nouveau fichier exrc : %s"
+139 "La ligne de destination est à l'intérieur de la plage à déplacer"
+140 "La commande ouverte nécessite que l'option ouverte soit définie"
+141 "La commande ouverte n'est pas encore implémentée"
+142 "La préservation de ce fichier est impossible"
+143 "Fichier préservé"
+144 "%s: étendu dans trop de noms de fichiers"
+145 "Vous ne pouvez lire que les fichiers standards et les canaux de transmission nommés"
+146 "%s: Interdiction de lecture non disponible"
+147 "Lecture en cours..."
+148 "%s: %lu lignes, %lu caractères"
+149 "Pas d'écrans d'arrière-plan à afficher"
+150 "La commande script n'est disponible qu'en mode vi"
+151 "Pas de commande à exécuter"
+152 "Option de largeur de décalage définie sur 0"
+153 "Compter dépassement"
+154 "Compter dépassement négatif"
+155 "Expression standard spécifiée; drapeau r superflu"
+156 "Vous ne pouvez pas en mode vi, combiner les drapeaux #, l et p avec le drapeau c"
+157 "Aucune correspondance trouvée"
+158 "Aucune marque précédente entrée"
+159 "Moins de %s entrées dans la pile de marques ; utilisez t[ags]"
+160 "Pas de fichier %s vers lequel retourner dans la pile de marques ; utiliser : affichage t[ags]"
+161 "Appuyez sur Entrée pour continuer :"
+162 "%s : marque introuvable"
+163 "%s : marque corrompue en %s"
+164 "%s : le numéro de ligne de la marque dépasse la fin du fichier"
+165 "La pile de marques est vide"
+166 "%s : motif de recherche introuvable"
+167 "%d fichiers supplémentaires à éditer"
+168 "Le tampon %s est vide
+169 "Confirmer les changements ? [n]"
+170 "Interrompu"
+171 "Pas de tampon précédent à exécuter"
+172 "Pas d'expression standard précédente"
+173 "La commande %s nécessite qu'un fichier ait déjà été lu en mémoire"
+174 "Utilisation : %s"
+175 "La commande visual nécessite que l'option open soit définie"
+177 "Fichier vide"
+178 "Pas de recherche précédente F, f, T ou t"
+179 "%s introuvable"
+180 "Pas de fichier précédent à éditer"
+181 "Le curseur n'est pas dans un nombre"
+182 "Le nombre obtenu est trop grand"
+183 "Le nombre obtenu est trop petit"
+184 "Pas de correspondance de caractère sur cette ligne"
+185 "Caractère correspondant introuvable"
+186 "Pas de caractères à remplacer"
+187 "Pas d'autre écran vers lequel basculer"
+188 "Caractères après la chaîne de recherche, décalage de ligne et/ou commande z"
+189 "Pas de motif de recherche précédent"
+190 "La recherche est revenue à son point de départ"
+191 "L'abréviation a dépassé la limite de l'expansion : caractères abandonnés"
+192 "Caractère non valide ; guillemet pour saisir"
+193 "Déjà au début de l'insertion"
+194 "Plus de caractères à effacer"
+195 "Déplacement hors de fin de fichier"
+196 "Déplacement hors de fin de ligne"
+197 "Aucun mouvement de curseur n'a été effectué"
+198 "Déjà au début du fichier"
+199 "Déplacement hors du début du fichier"
+200 "Déjà dans la première colonne"
+201 "Les tampons doivent être spécifiés avant la commande"
+202 "Déjà à la fin du fichier"
+203 "Déjà à la fin de la ligne"
+204 "%s n'est pas une commande vi"
+205 "Utilisation : %s"
+206 "Pas de caractères à supprimer"
+207 "La commande Q nécessite une interface terminal ex"
+208 "Pas de commande à répéter"
+209 "Le fichier est vide"
+210 "Vous ne pouvez pas utiliser %s comme commande de déplacement"
+211 "Déjà en mode commande"
+212 "Le curseur n'est pas dans un mot"
+214 "Valeur optionnelle de fenêtre trop grande, maximum est %u"
+215 "Ajouter"
+216 "Changer"
+217 "Commande"
+218 "Insérer"
+219 "Remplacer"
+220 "Déplacement hors de la fin d'écran"
+221 "Déplacement hors du début d'écran"
+222 "L'écran doit être supérieur à %d lignes pour se fractionner"
+223 "Il n'y a pas d'écran d'arrière-plan"
+224 "Il n'y a pas d'écran d'arrière-plan qui édite un fichier nommé %s"
+225 "Vous ne pouvez pas mettre à l'arrière-plan votre seul écran affiché"
+226 "L'écran ne peut être réduit qu'à %d rangs"
+227 "L'écran n'est pas auto-réductible"
+228 "L'écran n'est pas auto-extensible"
+230 "Vous ne pouvez pas mettre cet écran en attente"
+231 "Interrompu : les touches affectées ont été abandonnées"
+232 "vi : le tampon temporaire n' a pas été libéré"
+233 "Ce terminal n'a pas de touche %s"
+234 "Vous ne pouvez spécifier qu'un seul tampon"
+235 "Nombre supérieur à %lu"
+236 "Interrompu"
+237 "Impossible de créer un fichier temporaire"
+238 "Avertissement : %s n'est pas un fichier standard"
+239 "%s déjà verrouillé, session en lecture seule"
+240 "%s: supprimer"
+241 "%s: fermer"
+242 "%s: supprimer"
+243 "%s: supprimer"
+244 "Fichier en lecture seule, non écrit, utiliser ! pour outrepasser"
+245 "Fichier en lecture seule, non écrit"
+246 "%s existe, non écrit; utiliser ! pour outrepasser"
+247 "%s existe, non écrit"
+248 "Fichier partiel, non écrit; utiliser ! pour outrepasser"
+249 "Fichier partiel, non écrit"
+250 "%s: fichier modifié plus récemment que cet exemplaire; utiliser ! pour outrepasser"
+251 "%s: fichier modifié plus récemment que cet exemplaire"
+252 "%s: interdiction d'écriture non disponible"
+253 "Ecriture en cours..."
+254 "%s: AVERTISSEMENT : FICHIER TRONQUÉ"
+255 "Première marque de ce groupe déjà atteinte"
+256 "%s: nouveau fichier : %lu lignes, %lu caractères"
+257 "%s: %lu lignes, %lu caractères"
+258 "%s étendue à trop de noms de fichiers"
+259 "%s: pas un fichier standard"
+260 "%s: ne vous appartient pas"
+261 "%s: accessible par un utilisateur autre que son propriétaire"
+262 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser "
+263 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser :edit! pour outrepasser"
+264 "Fichier modifé depuis la dernière écriture complète ; écrire ou utiliser ! pour outrepasser"
+265 "Fichier temporaire ; quitter annulera les modifications"
+266 "Fichier en lecture seule ; les modifications ne sont pas écrites automatiquement"
+267 "Journal redémarré"
+268 "confirmer ? [ynq]"
+269 "Appuyez sur n'importe quelle touche pour continuer : "
+270 "Appuyez sur n'importe quelle touche pour continuer [: pour entrer plus de commandes ex] : "
+271 "Appuyez sur n'importe quelle touche pour continuer [q pour Quitter]: "
+272 "Cette forme de %s nécessite l'interface de terminal ex"
+273 "Entrée de mode entrée ex."
+274 "La commande a échoué, aucun fichier n'a encore été lu."
+275 "cont?"
+276 "Evénement imprévu de caractère"
+277 "Evénement imprévu de fin-de-fichier"
+278 "Pas de correspondances pour cette requête"
+279 "Evénement imprévu d'interruption"
+280 "Evénement quitter imprévu"
+281 "Evénement imprévu de rafraîchissement"
+282 "La dernière marque de ce groupe a déjà été atteinte"
+283 "La commande %s nécessite l'interface de terminal ex"
+284 "Cette forme de %s n'est pas reconnue quand l'option d'édition protégée est activée"
+285 "Evénement imprévu de chaîne"
+286 "Evénement imprévu de délai imparti"
+287 "Evénement d'écriture imprévu"
+289 "Les expansions du shell ne sont pas reconnues quand l'option d'édition protégée est activée"
+290 "La commande %s n'est pas reconnue quand l'option d'édition protégée est activée"
+291 "Définition : l'option %s ne peut pas être désactivée"
+292 "Affichage trop petit."
+293 "ajouté"
+294 "changé"
+295 "supprimé"
+296 "joint"
+297 "déplacé"
+298 "décalé"
+299 "coupé"
+300 "ligne"
+301 "lignes"
+302 "Vi n'a pas été chargé avec un interprétateur Tcl"
+303 "Ficher modifié depuis le dernier enregistrement."
+304 "L'expansion du shell a échoué"
+305 "Pas d'option d'édition %s spécifiée"
+306 "Vi n'a pas été chargé avec un interprétateur Perl"
+307 "Pas de commande ex à exécuter"
+308 "Entrez <CR> pour exécuter une commande, :q pour quitter"
+309 "Utiliser \"cscope help\" pour obtenir de l'aide"
+310 "Aucune connexion cscope n'est lancée"
+311 "%s : type de recherche inconnu : utiliser un des %s"
+312 "%d : Il n'existe pas de telle session cscope"
+313 "Définition : l'option %s ne peut jamais être activée"
+314 "Définition : l'option %s ne peut jamais être définie sur 0"
+315 "%s: joints : %lu lignes, %lu caractères"
+316 "événement imprévu de redimensionnement"
+317 "%d fichiers à éditer"
diff --git a/usr.bin/vi/catalog/german.UTF-8.base b/usr.bin/vi/catalog/german.UTF-8.base
new file mode 100644
index 000000000000..956fd82fd9a0
--- /dev/null
+++ b/usr.bin/vi/catalog/german.UTF-8.base
@@ -0,0 +1,306 @@
+002 "Zeilenlängen-Überlauf"
+003 "kann Zeile %lu nicht löschen"
+004 "kann an Zeile %lu nicht anfügen"
+005 "kann in Zeile %lu nicht einfügen"
+006 "kann Zeile %lu nicht speichern"
+007 "kann letzte Zeile nicht lesen"
+008 "Fehler: kann Zeile %lu nicht wiederherstellen"
+009 "Protokolldatei"
+010 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
+011 "Keine Änderungen rückgängig zu machen"
+012 "Keine Protokollierung aktiv, Rückgängigmachen nicht möglich"
+013 "Keine Protokollierung aktiv, Wiederholung von Änderungen nicht möglich"
+014 "Keine Änderungen zu wiederholen"
+015 "%s/%d: Protokollschreibfehler"
+016 "Vi's Standardein- und -ausgabe muß ein Terminal sein"
+017 "Marke %s: nicht gesetzt"
+018 "Marke %s: die Zeile wurde gelöscht"
+019 "Marke %s: Cursorposition existiert nicht mehr"
+020 "Fehler: "
+021 "neue Datei"
+022 "Name geändert"
+023 "geändert"
+024 "nicht geändert"
+025 "NICHT GELOCKT"
+026 "nur zum Lesen"
+027 "Zeile %lu von %lu [%ld%%]"
+028 "leere Datei"
+029 "Zeile %lu"
+030 "Die Datei %s ist kein Meldungskatalog"
+031 "Setzen der Voreinstellung für %s Option nicht möglich"
+032 "Benutzung: %s"
+033 "set: keine %s Option: 'set all' zeigt alle Optionen mit Werten an"
+034 "set: der [no]%s Option kann kein Wert zugewiesen werden"
+035 "set: %s ist keine Boolsche Option"
+036 "set: %s Option: %s"
+037 "set: %s Option: %s: Werte-Ãœberlauf"
+038 "set: %s Option: %s ist eine ungültige Zahl"
+039 "set: %s ist keine Boolsche Option"
+040 "Bildschirm hat zu wenig Spalten, weniger als %d"
+041 "Bildschirm hat zu viele Spalten, mehr als %d"
+042 "Bildschirm hat zu wenig Zeilen, weniger als %d"
+043 "Bildschirm hat zu viele Zeilen, mehr als %d"
+044 "Die lisp-Option ist nicht implementiert"
+045 "Meldungen nicht abgeschaltet: %s"
+046 "Meldungen nicht eingeschaltet: %s"
+047 "Die %s-Option muß Gruppen zu zwei Zeichen enthalten"
+053 "Der Standardpuffer ist leer"
+054 "Puffer %s ist leer"
+055 "Dateien mit newlines im Namen sind nicht wiederherstellbar"
+056 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
+057 "kopiere Datei für Wiederherstellung ..."
+058 "Rettungsmechanismus funktioniert nicht: %s"
+059 "Änderungen nicht wiederherstellbar, falls die Editorsitzung schiefgeht"
+060 "Sicherung der Datei gescheitert: %s"
+061 "kopiere Datei für Wiederherstellung ..."
+062 "Informationen über den Benutzer mit id %u nicht gefunden"
+063 "Wiederherstellungsdatei kann nicht gelockt werden"
+064 "Puffer der Wiederherstellungsdatei übergelaufen"
+065 "Wiederherstellungsdatei"
+066 "%s: Wiederherstellungsdatei hat falsches Format"
+067 "%s: Wiederherstellungsdatei hat falsches Format"
+068 "Keine von Ihnen lesbaren Dateien mit Namen %s zum Wiederherstellen"
+069 "Es gibt ältere Versionen dieser Datei von Ihnen zum Wiederherstellen"
+070 "Sie haben noch andere Dateien zum Wiederherstellen"
+071 "schicke keine email: %s"
+072 "Datei leer; nichts zu suchen"
+073 "Dateiende erreicht, ohne das Suchmuster zu finden"
+074 "Kein altes Suchmuster"
+075 "Suchmuster nicht gefunden"
+076 "Dateianfang erreicht, ohne das Suchmuster zu finden"
+077 "Suche beginnt von vorn"
+078 "suche ..."
+079 "Keine nichtdruckbaren Zeichen gefunden"
+080 "Unbekannter Kommandoname"
+082 "%s: Kommando im ex-Modus nicht verfügbar"
+083 "Anzahl darf nicht Null sein"
+084 "%s: falsche Zeilenangabe"
+085 "Interner Syntaxtabellenfehler (%s: %s)"
+086 "Benutzung: %s"
+087 "%s: temporärer Puffer nicht freigegeben"
+088 "Flagoffset vor Zeile 1"
+089 "Flagoffset hinter dem Dateiende"
+090 "@ mit Bereich lief, als Datei/Anzeige geändert wurde"
+091 "globales oder v-Kommando lief, als Datei/Anzeige geändert wurde"
+092 "Ex-Kommando mißlungen: restliche Kommandoeingabe ignoriert"
+093 "Ex-Kommando mißlungen: umdefinierte Tasten ungültig"
+094 "Die zweite Adresse ist kleiner als die erste"
+095 "Kein Markenname angegeben"
+096 "\\ ohne folgenden / oder ?"
+097 "Referenz auf eine negative Zeilennummer"
+098 "Das Kommando %s ist unbekannt"
+099 "Adreßwert zu groß"
+100 "Adreßwert zu klein"
+101 "Ungültige Adreßkombination"
+102 "Ungültige Adresse: nur %lu Zeilen in der Datei"
+103 "Ungültige Adresse: die Datei ist leer"
+104 "Das Kommando %s erlaubt keine Adresse 0"
+105 "Keine Abkürzungen zum Anzeigen"
+106 "Abkürzungen müssen mit einem \"Wort\"-Zeichen enden"
+107 "Abkürzungen dürfen keine Tabulator- oder Leerzeichen enthalten"
+108 "In Abkürzungen dürfen außer am Ende Wort- und Nicht-Wort-Zeichen nicht gemischt werden"
+109 "\"%s\" ist keine Abkürzung"
+110 "Vi Kommando mißlungen: umdefinierte Tasten ungültig"
+111 "Keine weiteren Dateien zu editieren"
+112 "Keine vorhergehenden Dateien zu editieren"
+113 "Keine vorhergehenden Dateien für rewind"
+114 "Keine Dateiliste zum Anzeigen"
+115 "Kein vorhergehendes Kommando, um \"!\" zu ersetzen"
+116 "Kein Dateiname für %%"
+117 "Kein Dateiname für #"
+118 "Fehler: execl: %s"
+119 "E/A-Fehler: %s"
+120 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+121 "Kann Homedirectory nicht bestimmen"
+122 "Neues aktuelles Directory: %s"
+123 "Keine Puffer anzuzeigen"
+124 "Das Kommando %s kann nicht als Teil eines global oder v Kommandos verwendet werden"
+125 "%s/%s: nicht gelesen: gehört weder Ihnen noch root"
+126 "%s/%s: nicht gelesen: gehört nicht Ihnen"
+127 "%s/%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
+128 "%s: nicht gelesen: gehört weder Ihnen noch root"
+129 "%s: nicht gelesen: gehört nicht Ihnen"
+130 "%s: nicht gelesen: anderer Benutzer als Eigentümer hat Schreibrecht"
+131 "Keine folgenden Zeilen zum Verbinden"
+132 "Kein input-Map Eintrag"
+133 "Kein command-Map Eintrag"
+134 "Das %s Zeichen kann nicht umgemappt werden"
+135 "\"%s\" ist momentan nicht gemappt"
+136 "Markennamen müssen einzelne Buchstaben sein"
+137 "%s existiert, nicht geschrieben; verwende ! zum Ãœberschreiben"
+138 "Neue .exrc Datei: %s. "
+139 "Zielzeile ist innerhalb des Verschiebebereichs"
+140 "Das open Kommando verlangt, daß die open Option gesetzt ist"
+141 "Das open Kommando ist nocht nicht implementiert"
+142 "Rettung dieser Datei nicht möglich"
+143 "Datei gerettet"
+144 "%s wurde in zu viele Dateinamen expandiert"
+145 "Nur reguläre Dateien und named pipes können gelesen werden"
+146 "%s: Locken zum Lesen war nicht möglich"
+147 "lese ..."
+148 "%s: %lu Zeilen, %lu Zeichen"
+149 "Keine Hintergrundanzeigen vorhanden"
+150 "Das script Kommando ist nur im vi Modus verfügbar"
+151 "Kein Kommando auszuführen"
+152 "shiftwidth Option auf 0 gesetzt"
+153 "Anzahl-Ãœberlauf"
+154 "Anzahl-Unterlauf"
+155 "Regulärer Ausdruck angegeben; r Flag bedeutungslos"
+156 "Die #, l und p Flags können im vi Modus nicht mit dem c Flag kombiniert werden"
+157 "Keine Ãœbereinstimmung gefunden"
+158 "Kein vorhergehender 'tag' angegeben"
+159 "Weniger als %s Einträge auf dem 'tag'-Stack; verwende :display t[ags]"
+160 "Keine Datei namens %s auf dem 'tag'-Stack; verwende :display t[ags]"
+161 "Drücke Enter um fortzufahren: "
+162 "%s: 'tag' nicht gefunden"
+163 "%s: kaputter 'tag' in %s"
+164 "%s: die Zeilennummer des 'tag' ist hinter dem Dateiende"
+165 "Der 'tag' Stack ist leer"
+166 "%s: Suchmuster nicht gefunden"
+167 "%d weitere Dateien zu editieren"
+168 "Puffer %s ist leer"
+169 "Bestätige Änderung [n]"
+170 "Unterbrochen."
+171 "Kein vorhergehender Puffer zum Ausführen"
+172 "Kein vorhergehender regulärer Ausdruck"
+173 "Das Kommando %s verlangt, daß bereits eine Datei eingelesen wurde"
+174 "Benutzung: %s"
+175 "Das visual Kommando verlangt daß die open Option gesetzt ist"
+177 "Leere Datei"
+178 "Keine vorhergehende F, f, T oder t Suche"
+179 "%s nicht gefunden"
+180 "Keine vorhergehende Datei zu editieren"
+181 "Cursor nicht auf einer Zahl"
+182 "Sich ergebende Zahl ist zu groß"
+183 "Sich ergebende Zahl ist zu klein"
+184 "Kein korrespondierendes Zeichen in dieser Zeile"
+185 "Korrespondierendes Zeichen nicht gefunden"
+186 "Keine Zeichen zu ersetzen"
+187 "Keine andere Anzeige zum Hinschalten"
+188 "Zeichen nach Suchmuster, Zeilenoffset und/oder z Kommando"
+189 "Kein altes Suchmuster"
+190 "Suche zur ursprünglichen Position zurückgekehrt"
+191 "Abkürzung überschreitet Expansionsgrenze: Zeichen weggelassen"
+192 "Nicht erlaubtes Zeichen; maskiere zum Eingeben"
+193 "Bereits am Anfang der Eingabe"
+194 "Keine weiteren Zeichen zu löschen"
+195 "Bewegung hinter das Dateiende"
+196 "Bewegung hinter das Zeilenende"
+197 "Keine Cursorbewegung gemacht"
+198 "Bereits am Dateianfang"
+199 "Bewegung vor den Dateianfang"
+200 "Bereits in der ersten Spalte"
+201 "Puffer sollen vor dem Kommando angegeben werden"
+202 "Bereits am Dateiende"
+203 "Bereits am Zeilenende"
+204 "%s ist kein vi Kommando"
+205 "Benutzung: %s"
+206 "Keine Zeichen zu löschen"
+207 "Das Q Kommando benötigt das ex Terminal Interface"
+208 "Kein Kommando zu wiederholen"
+209 "Die Datei ist leer"
+210 "%s kann nicht als Bewegungskommando verwendet werden"
+211 "Bereits im Kommando-Modus"
+212 " Cursor nicht auf einem Wort"
+214 "Wert der Window Option ist zu groß, max ist %u"
+215 "Anhängen"
+216 "Ändern"
+217 "Kommando"
+218 "Einfügen"
+219 "Ersetzen"
+220 "Bewegung hinter das Anzeigenende"
+221 "Bewegung vor den Anzeigenanfang"
+222 "Anzeige muß für Bildschirmteilung größer als %d sein"
+223 "Keine Hintergrundanzeigen vorhanden"
+224 "Es gibt keine Hintergrundanzeige, die eine Datei namens %s editiert"
+225 "Die einzige dargestellte Anzeige kann nicht in den Hintergrund gebracht werden"
+226 "Die Anzeige kann nur auf %d Zeilen verkleinert werden"
+227 "Die Anzeige kann nicht verkleinert werden"
+228 "Die Anzeige kann nicht vergrößert werden"
+230 "Diese Anzeige kann nicht gestopt werden"
+231 "Unterbrochen: umdefinierte Tasten ungültig"
+232 "vi: temporärer Puffer nicht freigegeben"
+233 "Dieses Terminal hat keine %s Taste"
+234 "es kann nur ein Puffer angegeben werden"
+235 "Zahl größer als %lu"
+236 "Unterbrochen"
+237 "Nicht möglich, temporäre Datei anzulegen"
+238 "Warnung: %s ist keine reguläre Datei"
+239 "%s ist bereits gelockt, Editorsitzung schreibgeschützt"
+240 "%s: löschen"
+241 "%s: schließen"
+242 "%s: löschen"
+243 "%s: löschen"
+244 "Datei nicht schreibbar, nicht geschrieben; verwende ! zum Ãœberschreiben"
+245 "Datei nicht schreibbar, nicht geschrieben"
+246 "%s existiert, nicht geschrieben; verwende ! zum Ãœberschreiben"
+247 "%s existiert, nicht geschrieben"
+248 "Teil der Datei, nicht geschrieben; verwende ! zum Ãœberschreiben"
+249 "Teil der Datei, nicht geschrieben"
+250 "%s: Datei wurde später als diese Kopie verändert; verwende ! zum Überschreiben"
+251 "%s: Datei wurde später als diese Kopie verändert"
+252 "%s: Locken zum Schreiben war nicht möglich"
+253 "schreibe ..."
+254 "%s: WARNUNG: DATEI ABGESCHNITTEN"
+255 "Bereits am ersten 'tag' dieser Gruppe"
+256 "%s: neue Datei: %lu Zeilen, %lu Zeichen"
+257 "%s: %lu Zeilen, %lu Zeichen"
+258 "%s wurde in zu viele Dateinamen expandiert"
+259 "%s: keine reguläre Datei"
+260 "%s: gehört nicht Ihnen"
+261 "%s: anderer Benutzer als Eigentümer hat Zugriff"
+262 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+263 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende :edit! zum ignorieren"
+264 "Datei wurde seit dem letzten vollständigen Schreiben geändert; schreibe oder verwende ! zum ignorieren"
+265 "Datei ist temporär; beim Verlassen gehen die Änderungen verloren"
+266 "Datei ist schreibgeschützt, Änderungen werden nicht automatisch geschrieben"
+267 "Portokollierung neu begonnen"
+268 "bestätigen [ynq]"
+269 "Drücke beliebige Taste um fortzufahren"
+270 "Drücke beliebige Taste um fortzufahren [: um weitere Kommandos einzugeben]: "
+271 "Drücke beliebige Taste um fortzufahren [q zum Verlassen]: "
+272 "Diese Form von %s benötigt das ex Terminal-Interface"
+273 "Gehe in ex Eingabe-Modus.\n"
+274 "Kommando schiefgelaufen, noch keine Datei eingelesen"
+275 " weiter?"
+276 "unerwartetes Zeichen - Ereignis"
+277 "unerwartetes Dateiende - Ereignis"
+278 "Keine Position zum Anspringen gefunden"
+279 "unerwartetes Unterbrechungs - Ereignis"
+280 "unerwartetes Verlassen - Ereignis"
+281 "unerwartetes Wiederherstellungs - Ereignis"
+282 "Bereits am letzten 'tag' dieser Gruppe"
+283 "Das %s Kommando benötigt das ex Terminal-Interface"
+284 "Diese Form von %s wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+285 "unerwartetes Zeichenketten - Ereignis"
+286 "unerwartetes timeout - Ereignis"
+287 "unerwartetes Schreibe - Ereignis"
+289 "Shell Expandierungen nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+290 "Das %s Kommando wird nicht unterstützt wenn die 'secure edit' - Option gesetzt ist"
+291 "set: %s kann nicht ausgeschaltet werden"
+292 "Anzeige zu klein."
+293 "angefügt"
+294 "geändert"
+295 "gelöscht"
+296 "verbunden"
+297 "verschoben"
+298 "geschoben"
+299 "in Puffer geschrieben"
+300 "Zeile"
+301 "Zeilen"
+302 "Vi wurde nicht mit dem Tcl Interpreter gelinkt"
+303 "Datei wurde seit dem letzten Schreiben verändert."
+304 "Shell Expansion hat nicht geklappt"
+305 "Es ist keine %s Editieroption angegeben"
+306 "Vi wurde nicht mit einem Perl Interpreter geladen"
+307 "Kein ex Kommando auszuführen"
+308 "Drücke <CR> um ein Kommando auszuführen, :q zum verlassen"
+309 "Verwende \"cscope help\" für Hilestellung"
+310 "Keine cscope Verbindung aktiv"
+311 "%s: unbekannter Suchtyp: verwende einen aus %s"
+312 "%d: keine solche cscope Verbindung"
+313 "set: die %s Option kann nicht eingeschaltet werden"
+314 "set: die %s Option kann nicht auf 0 gesetzt werden"
+315 "%s: angefügt: %lu Zeilen, %lu Zeichen"
+316 "unerwartetes Größenveränderungs - Ereignis"
+317 "%d Dateien zu edieren"
diff --git a/usr.bin/vi/catalog/polish.UTF-8.base b/usr.bin/vi/catalog/polish.UTF-8.base
new file mode 100644
index 000000000000..9648e78ced38
--- /dev/null
+++ b/usr.bin/vi/catalog/polish.UTF-8.base
@@ -0,0 +1,306 @@
+002 "Zbyt długa linia"
+003 "nie można usunąć linii %lu"
+004 "nie można dodać do linii %lu"
+005 "nie można wstawić w linii %lu"
+006 "nie można zachować linii %lu"
+007 "nie można pobrać ostatniej linii"
+008 "Błąd: nie można pobrać linii %lu"
+009 "Plik logu"
+010 "Brak logowania, anulowanie (undo) niemożliwe"
+011 "Brak zmian do anulowania"
+012 "Brak logowania, anulowanie (undo) niemożliwe"
+013 "Brak logowania, nie można przeglądać do przodu"
+014 "Brak zmian do powtórzenia"
+015 "%s/%d: błąd zapisu do logu"
+016 "Standardowe wejście i wyjście vi musi być terminalem"
+017 "Znacznik %s: nie ustawiony"
+018 "Znacznik %s: linia została usunięta"
+019 "Znacznik %s: pozycja kursora już nie istnieje"
+020 "BÅ‚Ä…d: "
+021 "nowy plik"
+022 "nazwa została zmieniona"
+023 "zmieniony"
+024 "nie zmieniony"
+025 "ODBLOKOWANY"
+026 "tylko do odczytu"
+027 "linia %lu z %lu [%ld%%]"
+028 "pusty plik"
+029 "linia %lu"
+030 "Plik %s nie jest katalogiem komunikatów"
+031 "Nie można ustawić domyślnej opcji %s"
+032 "Sposób użycia: %s"
+033 "set: brak opcji %s: 'set all' wyświetla wartości opcji"
+034 "set: opcja no]%s nie pobiera wartości"
+035 "set: opcja %s nie jest zmiennÄ… boolowskÄ…"
+036 "set: opcja %s: %s"
+037 "set: opcja %s: %s: przepełnienie"
+038 "set: opcja %s: %s nie jest poprawnÄ… liczbÄ…"
+039 "set: opcja %s nie jest zmiennÄ… boolowskÄ…"
+040 "Zbyt mała liczba kolumn ekranu, mniejsza niż %d"
+041 "Zbyt duża liczba kolumn, większa niż %d"
+042 "Zbyt mała liczba wierszy ekranu, mniejsza niż %d"
+043 "Zbyt duża liczba wierszy ekranu, większa niż %d"
+044 "Opcja lisp nie jest zaimplementowana"
+045 "komunikaty nie wyłączone: %s"
+046 "komunikaty nie włączone: %s"
+047 "Opcja %s musi składać się z dwóch grup symboli"
+053 "Domyślny bufor jest pusty"
+054 "Bufor %s jest pusty"
+055 "Pliki z symbolem nowego wiersza w nazwie nie mogą być odtworzone"
+056 "Zmiany nie do odtworzenia, jeśli sesja zostanie przerwana"
+057 "Tworzenie kopii zapasowej..."
+058 "BÅ‚Ä…d podczas zachowywania: %s"
+059 "Zmiany nie do odtworzenia, jeśli sesja zostanie przerwana"
+060 "BÅ‚Ä…d podczas tworzenia kopii zapasowej: %s"
+061 "Tworzenie kopii zapasowej..."
+062 "Nie znaleziono informacji o użytkowniku numer %u"
+063 "Nie można zablokować kopii zapasowej"
+064 "Przepełnienie bufora kopii zapasowej"
+065 "Kopia zapasowa"
+066 "%s: błędna kopia zapasowa"
+067 "%s: błędna kopia zapasowa"
+068 "Brak plików o nazwie %s, które mógłbyś odczytać, do odzyskania"
+069 "Istnieją starsze wersje tego pliku, które można odzyskać"
+070 "Istnieją inne pliki, które można odzyskać"
+071 "nie wysyłam poczty: %s"
+072 "Pusty plik; nie ma czego szukać"
+073 "Dotarto do końca pliku bez znalezienia szukanego wzorca"
+074 "Brak poprzedniego wzorca poszukiwań"
+075 "Nie znaleziono wzorca"
+076 "Dotarto do poczÄ…tku pliku bez znalezienia szukanego wzorca"
+077 "Poszukiwanie od poczÄ…tku"
+078 "Szukam..."
+079 "Nie znaleziono niedrukowalnych znaków"
+080 "Nieznana nazwa polecenia"
+082 "%s: polecenie niedostępne w trybie edytora ex"
+083 "Liczba nie może być zerem"
+084 "%s: błędny numer linii"
+085 "Wewnętrzny błąd tablicy składni (%s: %s)"
+086 "Sposób użycia: %s"
+087 "%s: tymczasowy bufor nie został zwolniony"
+088 "Przesunięcie przed linię 1"
+089 "Przesunięcie poza koniec pliku"
+090 "@ with range running when the file/screen changed"
+091 "Wykonywano polecenie globalne/wizualne podczas zmiany pliku/ekranu"
+092 "Błąd polecenie ex: pozostałe polecenia anulowane"
+093 "BÅ‚Ä…d polecenia ex: mapowanie klawiszy anulowane"
+094 "Drugi adres jest mniejszy od pierwszego"
+095 "Nie podano nazwy znacznika"
+096 "\\ bez / lub ?"
+097 "Odniesienie do linii o numerze mniejszym od 0"
+098 "Nieznane polecenie %s"
+099 "Przepełnienie wartości adresu"
+100 "Niedomiar wartości adresu"
+101 "Niedozwolona kombinacja adresu"
+102 "Niedozwolony adres: jest tylko %lu linii w pliku"
+103 "Niedozwolony adres: plik jest pusty"
+104 "Polecenie %s nie zezwala na użycie adresu 0"
+105 "Brak skrótów do wyświetlenia"
+106 "Skróty muszą się kończyć symbolem \"słowo\""
+107 "Skróty nie mogą zawierać spacji lub tabulacji"
+108 "Skróty nie mogą przeplatać symboli słowo/nie-słowo, z wyjątkiem na końcu linii"
+109 "\"%s\" nie jest skrótem"
+110 "BÅ‚Ä…d polecenia vi: mapowanie klawiszy odrzucone"
+111 "Nie ma więcej plików do edycji"
+112 "Nie ma poprzednich plików do edycji"
+113 "Nie ma poprzednich plików do przewinięcia wstecz"
+114 "Nie ma listy plików do wyświetlenia"
+115 "Nie ma poprzedniego polecenia do zastÄ…pienia \"!\""
+116 "Nie ma nazwy pliku do zastÄ…pienia %%"
+117 "Nie ma nazwy pliku do zastÄ…pienia #"
+118 "BÅ‚Ä…d: execl: %s"
+119 "BÅ‚Ä…d I/O: %s"
+120 "Plik zmodyfikowany od ostatniego zapisu; zapisz lub użyj ! żeby wymusić"
+121 "Nie mozna znaleźć katalogu domowego (home)"
+122 "Nowy katalog bieżący: %s"
+123 "Nie ma buforów edycji do wyświetlenia"
+124 "Polecenie %s nie może być użyte jako część polecenia globalnego lub wizualnego"
+125 "%s/%s: nie wczytany: nie należy do ciebie ani do roota"
+126 "%s/%s: nie wczytany: nie należy do ciebie"
+127 "%s/%s: nie wczytany: inny użytkownik niż właściciel ma prawo do zapisu"
+128 "%s: nie wczytany: nie należy do ciebie ani do roota"
+129 "%s: nie wczytany: nie należy do ciebie"
+130 "%s: nie wczytany: inny uzytkownik niż właściciel ma prawo do zapisu"
+131 "Brak kolejnych linii do połączenia"
+132 "Brak pozycji map wejściowych"
+133 "Brak pozycji map poleceń"
+134 "Znak %s nie może być przemapowany"
+135 "\"%s\" obecnie nie jest mapowany"
+136 "Nazwa znacznika musi być pojedyńczą literą"
+137 "%s istnieje, nie zapisany; użyj ! żeby wymusić"
+138 "Nowy plik exrc: %s"
+139 "Linia docelowa jest wewnÄ…trz przenoszonego obszaru"
+140 "Polecenie open wymaga ustawienia opcji open"
+141 "Polecenie open jest niezaimplementowane"
+142 "Niemożliwe jest zachowanie tego pliku"
+143 "Plik zachowany"
+144 "%s: rozwija się na zbyt wiele nazw plików"
+145 "Tylko zwykłe pliki i nazwane łącza (named pipes) można czytać"
+146 "%s: nie można założyć blokady do odczytu"
+147 "Czytanie..."
+148 "%s: %lu linii, %lu znaków"
+149 "Brak ekranów w tle do wyświetlenia"
+150 "Polecenie script dostępne jest tylko w trybie vi"
+151 "Brak polecenia do wykonania"
+152 "Opcja shiftwidth ustawiona na 0"
+153 "Przepełnienie licznika"
+154 "Niedomiar licznika"
+155 "Podano wyrażenie regularne; flaga r nie ma znaczenia"
+156 "Flagi #, l oraz p nie mogą być łączone z flagą c w trybie vi"
+157 "Nie znaleziono wzorca"
+158 "Brak poprzedniego znacznika"
+159 "Mniej niż %s na stosie znaczników; użyj :display t[ags]"
+160 "Brak pliku %s na stosie znaczników do powrotu; użyj :display t[ags]"
+161 "Naciśnij Enter: "
+162 "%s: znacznik nie znaleziony"
+163 "%s: błędny znacznik w %s"
+164 "%s: numer linii znacznika wykracza poza koniec pliku"
+165 "Stos znaczników jest pusty"
+166 "%s: nie znaleziono szukanego wzorca"
+167 "%d plików jeszcze do edycji"
+168 "Bufor %s jest pusty"
+169 "Potwierdzasz zmianÄ™? [n]"
+170 "Przerwany"
+171 "Brak poprzedniego bufora do wykonania"
+172 "Brak poprzedniego wyrażenia regularnego"
+173 "Polecenie %s wymaga uprzedniego wczytania pliku"
+174 "Sposób użycia: %s"
+175 "Polecenie wizualne wymaga ustawienia opcji open"
+177 "Pusty plik"
+178 "Brak poprzedniego szukania F, f, T lub t"
+179 "%s nie znaleziono"
+180 "Brak poprzedniego pliku do edycji"
+181 "Kursor nie na liczbie"
+182 "Liczba wynikowa zbyt duża"
+183 "Liczba wynikowa zbyt mała"
+184 "Brak pasujących znaków w tej linii"
+185 "Nie znaleziono pasujących znaków"
+186 "Brak znaków do zamiany"
+187 "Brak innego ekranu do przełączenia"
+188 "Znaki poza napisem do szukania, przesunięciem linii i/lub poleceniem z"
+189 "Brak poprzedniego wzorca szukania"
+190 "Szukanie wróciło do pierwotnej pozycji"
+191 "Skrót przekroczył limit rozwinięcia: część znaków odrzucono"
+192 "Niedozwolony znak; zacytuj, żeby wprowadzić"
+193 "Już na początku wstawiania"
+194 "Brak kolejnych znaków do usunięcia"
+195 "Przesunięcie poza koniec pliku"
+196 "Przesunięcie poza koniec linii"
+197 "Nie wykonano przesunięcia kursora"
+198 "Już na początku pliku"
+199 "Przesunięcie przed początek pliku"
+200 "Już w pierwszej kolumnie"
+201 "Należy podać bufory przed poleceniem"
+202 "Już na końcu pliku"
+203 "Już na końcu linii"
+204 "%s nie jest poleceniem vi"
+205 "Sposób użycia: %s"
+206 "Brak znaków do usunięcia"
+207 "Polecenie Q wymaga interfejsu terminala ex"
+208 "Brak polecenia do powtórzenia"
+209 "Plik jest pusty"
+210 "%s nie może być użyte jako polecenie przesunięcia"
+211 "Już w trybie poleceń"
+212 "Kursor nie na słowie"
+214 "Wartości opcji okna zbyt duże, max to %u"
+215 "Dołącz"
+216 "Zmień"
+217 "Polecenie"
+218 "Wstaw"
+219 "Zamień"
+220 "Przesunięcie poza koniec ekranu"
+221 "Przesunięcie przed początek ekranu"
+222 "Ekran musi mieć więcej niż %d linii, żeby go podzielić"
+223 "Brak ekranów w tle"
+224 "Nie ma ekranu w tle z edycjÄ… pliku o nazwie %s"
+225 "Nie można schować w tle jedynego ekranu edycyjnego"
+226 "Można zmniejszyć ekran tylko do %d wierszy"
+227 "Ekran nie może być zmniejszony"
+228 "Ekran nie może być zwiększony"
+230 "Ekran nie może być zawieszony"
+231 "Przerwano: odrzucono mapowane klawisze"
+232 "vi: nie zwolniono bufora tymczasowego"
+233 "Ten terminal nie posiada klawisza %s"
+234 "Można podać tylko jeden bufor"
+235 "Liczba większa niż %lu"
+236 "Przerwano"
+237 "Nie można utworzyć pliku tymczasowego"
+238 "Uwaga: %s nie jest zwykłym plikiem"
+239 "%s już zablokowany, sesja tylko do odczytu"
+240 "%s: usuń"
+241 "%s: zamknij"
+242 "%s: usuń"
+243 "%s: usuń"
+244 "Plik tylko do odczytu, nie zapisany; użyj ! żeby wymusić"
+245 "Plik tylko do odczytu, nie zapisany"
+246 "%s istnieje, nie zapisany; użyj ! żeby wymusić"
+247 "%s istnieje, nie zapisany"
+248 "Plik częściowy, nie zapisany; użyj ! żeby wymusić"
+249 "Plik częściowy, nie zapisany"
+250 "%s: plik zmodyfikowany później, niż ta kopia; użyj ! żeby wymusić"
+251 "%s: plik zmodyfikowany później, niż ta kopia"
+252 "%s: nie można zablokować do pisania"
+253 "Zapisywanie..."
+254 "%s: OSTRZEŻENIE: PLIK ZOSTAŠOBCIĘTY"
+255 "Już przy pierwszym znaczniku z tej grupy"
+256 "%s: nowy plik: %lu linii, %lu znaków"
+257 "%s: %lu linii, %lu znaków"
+258 "%s rozwija się na zbyt wiele nazw plików"
+259 "%s: nie jest zwykłym plikiem"
+260 "%s: nie jesteś właścicielem"
+261 "%s: dostępny dla użytkownika innego niż właściciel"
+262 "Plik zmodyfikowany od ostatniego zapisu; zapisz lub użyj ! żeby wymusić"
+263 "Plik zmodyfikowany od ostatniego zapisu; zapisz lub użyj :edit! żeby wymusić"
+264 "Plik zmodyfikowany od ostatniego zapisu; zapisz lub użyj ! żeby wymusić"
+265 "To jest plik tymczasowy; wyjście anuluje zmiany"
+266 "Plik tylko do odczytu, nie ma autozapisu zmian"
+267 "Ponownie rozpoczęto logowanie"
+268 "potwierdzasz? [ynq]"
+269 "Naciśnij dowolny klawisz: "
+270 "Naciśnij dowolny klawisz [: żeby podać następne polecenia ex]: "
+271 "Naciśnij dowolny klawisz [q żeby zakończyć]: "
+272 "Ta forma %s wymaga interfejsu terminala ex"
+273 "WchodzÄ™ w tryb wprowadzania ex."
+274 "BÅ‚Ä…d polecenia, jeszcze nie wczytano pliku."
+275 " dalej?"
+276 "Nieoczekiwany symbol"
+277 "Nieoczekiwany koniec pliku"
+278 "Brak wzorców pasujących do zapytania"
+279 "Nieoczekiwane przerwanie"
+280 "Nieoczekiwane polecenie koniec"
+281 "Nieoczekiwane polecenie odświeżenia"
+282 "Już przy ostatnim znaczniku z tej grupy"
+283 "Polecenie %s wymaga interfejsu terminala ex"
+284 "Ta forma %s jest niedostępna, kiedy ustawiona jest opcja bezpiecznej edycji"
+285 "Nieoczekiwany ciąg znaków"
+286 "Nieoczekiwany timeout"
+287 "Nieoczekiwane polecenie zapisu"
+289 "Rozwinięcia shella niedostępne w trybie bezpiecznej edycji"
+290 "Polecenie %s jest niedostępne w trybie bezpiecznej edycji"
+291 "set: opcji %s nie można wyłączyć"
+292 "Ekran zbyt mały."
+293 "dodano"
+294 "zmieniono"
+295 "usunięto"
+296 "połączono"
+297 "przeniesiono"
+298 "przesunięto"
+299 "wczytano"
+300 "linia"
+301 "linii"
+302 "Vi nie został uruchomiony z interpreterem Tcl"
+303 "Plik zmodyfikowany od ostatniego zapisu"
+304 "Błąd rozwinięcia shella"
+305 "Brak opcji %s edycji"
+306 "Vi nie został uruchomiony z interpreterem Perl"
+307 "Brak polecenia ex do wykonania"
+308 "Naciśnij <CR> żeby wykonac polecenie, :q żeby wyjść"
+309 "Użyj \"cscope help\" w celu uzyskania pomocy"
+310 "Brak aktywnych połączeń cscope"
+311 "%s: nieznany typ poszukiwań: użyj jednego z %s"
+312 "%d: brak takiej sesji cscope"
+313 "set: nie można nigdy włączyć opcji %s"
+314 "set: opcja %s nie może nigdy mieć wartości 0"
+315 "%s: dodano: %lu linii, %lu znaków"
+316 "Nieoczekiwane polecenie zmiany rozmiaru"
+317 "%d plików do edycji"
diff --git a/usr.bin/vi/catalog/ru_RU.UTF-8.base b/usr.bin/vi/catalog/ru_RU.UTF-8.base
new file mode 100644
index 000000000000..b358015544ef
--- /dev/null
+++ b/usr.bin/vi/catalog/ru_RU.UTF-8.base
@@ -0,0 +1,311 @@
+002 "Переполнение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ð¸Ð½Ñ‹ Ñтроки"
+003 "невозможно удалить Ñтроку %lu"
+004 "невозможно добавить к Ñтроке %lu"
+005 "невозможно вÑтавить в Ñтроку %lu"
+006 "невозможно Ñохранить Ñтроку %lu"
+007 "невозможно доÑтать поÑледнюю Ñтроку"
+008 "Ошибка: не удалоÑÑŒ получить Ñтроку %lu"
+009 "Файл запиÑей"
+010 "ЗапиÑи не велиÑÑŒ, невозможно отменить поÑледнюю команду"
+011 "Ðет изменений Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹"
+012 "ЗапиÑи не велиÑÑŒ, невозможно отменить поÑледнюю команду"
+013 "ЗапиÑи не велиÑÑŒ, невозможно проÑмотреть вперед"
+014 "Ðет изменений Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ´ÐµÐ»ÐºÐ¸"
+015 "%s/%d: ошибка при запиÑи протокола"
+016 "Стандартный ввод/вывод Ð´Ð»Ñ VI должен быть терминал"
+017 "Отметка %s: не уÑтановлена"
+018 "Отметка %s: Ñтрока была удалена"
+019 "Отметка %s: позиции курÑора больше не ÑущеÑтвует"
+020 "Ошибка: "
+021 "новый файл"
+022 "Ð¸Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¾"
+023 "модифицировано"
+024 "не модифицировано"
+025 "РÐЗБЛОКИРОВÐÐО"
+026 "только чтение"
+027 "Ñтрока %lu из %lu [%ld%%]"
+028 "пуÑтой файл"
+029 "Ñтрока %lu"
+030 "Файл %s не ÑвлÑетÑÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼ Ñообщений"
+031 "Ðевозможно уÑтановить опцию %s по умолчанию"
+032 "ИÑпользование: %s"
+033 "Опции %s нет: 'set all' показывает вÑе возможные опции"
+034 "set: [no]%s не принимает такого значениÑ"
+035 "set: %s Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ðµ ÑвлÑетÑÑ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкой"
+036 "set: %s опциÑ: %s"
+037 "set: %s опциÑ: %s: значение переполнениÑ"
+038 "set: неправильное значение %s"
+039 "set: %s Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ðµ ÑвлÑетÑÑ Ð»Ð¾Ð³Ð¸Ñ‡ÐµÑкой"
+040 "КоличеÑтво колонок Ñкрана Ñлишком мало, меньше чем %d"
+041 "КоличеÑтво колонок Ñкрана Ñлишком велико, больше чем %d"
+042 "КоличеÑтво Ñтрок Ñкрана Ñлишком мало, меньше чем %d"
+043 "КоличеÑтво Ñтрок Ñкрана Ñлишком велико, больше чем %d"
+044 "ÐžÐ¿Ñ†Ð¸Ñ lisp отÑутÑтвует"
+045 "Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ðµ выключены: %s"
+046 "Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ðµ включены: %s"
+047 "ÐžÐ¿Ñ†Ð¸Ñ %s должна ÑоÑтоÑÑ‚ÑŒ из групп Ñ Ð´Ð²ÑƒÐ¼Ñ Ñимволами"
+053 "Стартовый буфер пуÑÑ‚"
+054 "Буфер %s пуÑÑ‚"
+055 "Файлы Ñ Ñимволами перевода Ñтроки в имени не могут быть воÑÑтановлены"
+056 "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ Ñохранены при крахе ÑеÑÑии"
+057 "Копирование файла Ð´Ð»Ñ Ð²Ð¾ÑÑтановлениÑ..."
+058 "Сохранение не удалоÑÑŒ: %s"
+059 "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ ÑохранÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¸ обрыве ÑеÑÑии"
+060 "Сохранение копии файла не удалоÑÑŒ: %s"
+061 "Копирование файла Ð´Ð»Ñ Ð²Ð¾ÑÑтановлениÑ..."
+062 "Информации на Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ %u не найдено"
+063 "Ðевозможно защитить ÑпаÑенный файл"
+064 "Буфер воÑÑтановленного файла переполнен"
+065 "ВоÑÑтановленный файл"
+066 "%s: не до конца воÑÑтановленный файл"
+067 "%s: не до конца воÑÑтановленный файл"
+068 "Файлов Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ %s, которые Ð’Ñ‹ можете читать, не ÑущеÑтвует"
+069 "ЕÑÑ‚ÑŒ Ñтарые верÑии файла, которые можно воÑÑтановить"
+070 "СущеÑтвуют другие файлы, которые можно воÑÑтановить"
+071 "е-mail не поÑлан: %s"
+072 "Файл пуÑÑ‚ - иÑкать нечего"
+073 "ДоÑтигнут конец файла без Ð½Ð°Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ñ†Ð° поиÑка"
+074 "Ðе задан образец поиÑка"
+075 "Образец поиÑка не найден"
+076 "ДоÑтупно начало файла без Ð½Ð°Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·Ñ†Ð° поиÑка"
+077 "ПоиÑк зациклен"
+078 "ПоиÑк..."
+079 "Ðепечатных Ñимволов не найдено"
+080 "ÐеизвеÑÑ‚Ð½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°"
+082 "%s: команда не доÑтупна в режиме ex"
+083 "Счетчик не может быть нулем"
+084 "%s: неправильное указание Ñтроки"
+085 "ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° в ÑинтакÑиÑе (%s: %s)"
+086 "ИÑпользование: %s"
+087 "%s: временный буфер не иÑпользован"
+088 "Метка поÑтавлена перед Ñтрокой 1"
+089 "Метка поÑтавлена поÑле конца файла"
+090 "@ Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¾Ð¼ выполнÑетÑÑ ÐºÐ¾Ð³Ð´Ð° файл/Ñкран изменены"
+091 "ГлобальнаÑ/v команда выполнÑетÑÑ ÐºÐ¾Ð³Ð´Ð° файл/Ñкран изменены"
+092 "Команда ex не удалаÑÑŒ: поÑледующие команды забыты"
+093 "Команда ex не удалаÑÑŒ: назначенные клавиши забыты"
+094 "Второй Ð°Ð´Ñ€ÐµÑ Ð¼ÐµÐ½ÑŒÑˆÐµ чем первый"
+095 "Ðе указано название отметки"
+096 "\\ не завершаетÑÑ / или ?"
+097 "СÑылка к Ñтроке Ñ Ð½Ð¾Ð¼ÐµÑ€Ð¾Ð¼ меньше 0"
+098 "Команда %s неизвеÑтна"
+099 "Переполнение Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа"
+100 "Ðедобор Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð°Ð´Ñ€ÐµÑа"
+101 "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð² адреÑе"
+102 "Ðеправильный адреÑ: вÑего %lu Ñтрок в файле"
+103 "Ðеправильный адреÑ: файл пуÑÑ‚"
+104 "Команда %s не может иÑпользовать Ð°Ð´Ñ€ÐµÑ 0"
+105 "Ðббревиатуры отÑутÑтвуют"
+106 "Ðббревиатуры должны заканчиватьÑÑ Ñимволом \"Ñлов\""
+107 "Ðббревиатуры не могут Ñодержать Ñимволы табулÑции или пробелы"
+108 "Ðббревиатуры не могут ÑочетатьÑÑ Ñ Ñимволами Ñлов/не-Ñлов, за иÑключением конца Ñтроки"
+109 "\"%s\" не ÑвлÑетÑÑ Ð°Ð±Ð±Ñ€ÐµÐ²Ð¸Ð°Ñ‚ÑƒÑ€Ð¾Ð¹"
+110 "Vi команда не удалаÑÑŒ: назначенные клавиши забыты"
+111 "Файлов Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ нет"
+112 "ОтÑутÑтвие предыдущего файла Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ"
+113 "ОтÑутÑтвие предыдущего файла Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра назад"
+114 "Ðет файлов"
+115 "ОтÑутÑтвие предыдущей команды Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ‹ \"!\""
+116 "ОтÑутÑтвие замены Ð´Ð»Ñ %%"
+117 "ОтÑутÑтвие замены Ð´Ð»Ñ #"
+118 "Ошибка: execl: %s"
+119 "Ошибка ввода/вывода: %s"
+120 "Файл изменен Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° поÑледней полной запиÑи: иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+121 "Ðевозможно найти домашний каталог"
+122 "Ðовый каталог: %s"
+123 "Ðет вырезанных буферов"
+124 "Команда %s не может быть иÑпользована внутри глобальной или v команды"
+125 "%s/%s: не открыт: не принадлежит Вам или root-у"
+126 "%s/%s: не открыт: не принадлежит Вам"
+127 "%s/%s: не открыт: возможноÑÑ‚ÑŒ запиÑи у пользователÑ, не ÑвлÑющегоÑÑ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼"
+128 "%s: не Ñчитан: не принадлежит Вам или root-у"
+129 "%s: не Ñчитан: не принадлежит Вам"
+130 "%s: не Ñчитан: возможноÑÑ‚ÑŒ запиÑи у пользователÑ, не ÑвлÑющегоÑÑ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼"
+131 "ПоÑледующие Ñтроки отÑутÑтвуют"
+132 "ОтÑутÑтвие параметров ввода"
+133 "ОтÑутÑтвие параметров команды"
+134 "Символ %s не может быть переназначен"
+135 "\"%s\" на данный момент не назначен"
+136 "Ð˜Ð¼Ñ Ð¼ÐµÑ‚ÐºÐ¸ должно быть одним Ñимволом"
+137 "%s ÑущеÑтвует, не запиÑан; иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+138 "Ðовый файл exrc: %s"
+139 "Строка переноÑа находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ параметров переноÑа"
+140 "Команда open подразумевает уÑтановку опции open"
+141 "Команда open не реализована"
+142 "Защита файла невозможна"
+143 "Файл защищен"
+144 "%s раÑширилÑÑ Ð² Ñлишком большое количеÑтво имен файлов"
+145 "Только обычные файлы или именованные каналы могут быть прочитаны"
+146 "%s: защита на чтение была недоÑтупна"
+147 "Чтение..."
+148 "%s: %lu Ñтрок, %lu Ñимволов"
+149 "Ðет теневых окон"
+150 "Команда script иÑпользуетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ в режиме vi"
+151 "Ðет команды Ð´Ð»Ñ Ð¸ÑполнениÑ"
+152 "ÐžÐ¿Ñ†Ð¸Ñ shiftwidth уÑтановлена на 0"
+153 "Переполнение Ñчетчика"
+154 "Цикл выполнен не до конца"
+155 "Указано регулÑрное выражение: флаг r не нужен"
+156 "Флаги #, l и p не могут быть объединены Ñ Ñ„Ð»Ð°Ð³Ð¾Ð¼ c в режиме vi"
+157 "Совпадений нет"
+158 "Метка отÑутÑтвует"
+159 "Ð’ Ñтеке меток запиÑей меньше, чем %s, иÑпользуйте :display t[ags]"
+160 "Файла Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ %s в Ñтеке меток нет; иÑпользуйте :display t[ags]"
+161 "Ðажмите Enter чтобы продолжить: "
+162 "%s: метка не найдена"
+163 "%s: Ð¿Ð»Ð¾Ñ…Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° в %s"
+164 "%s: номер Ñтроки метки вышел за конец файла"
+165 "Стек меток пуÑÑ‚"
+166 "%s: образец поиÑка не найден"
+167 "еще %d файлов Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ"
+168 "Буфер %s пуÑÑ‚"
+169 "Подтвердить изменениÑ? [n]"
+170 "Прервано"
+171 "ОтÑутÑтвие буфера Ð´Ð»Ñ Ð¸ÑпользованиÑ"
+172 "Ðет предыдущего регулÑрного выражениÑ"
+173 "Команда %s подразумевает наличие прочтенного файла"
+174 "ИÑпользование: %s"
+175 "Команда visual подразумевает обÑзательную уÑтановку опции open"
+177 "ПуÑтой файл"
+178 "Ðет предыдущего поиÑка F, f, T, или t"
+179 "%s не найдено"
+180 "Ðет предыдущего файла Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ"
+181 "КурÑор Ñтоит не на цифре"
+182 "Полученное чиÑло Ñлишком велико"
+183 "Полученное чиÑло Ñлишком мало"
+184 "ПодходÑщего Ñимвола нет на Ñтой Ñтроке"
+185 "ПодходÑщий Ñимвол не найден"
+186 "Ðет Ñимволов Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ"
+187 "Другого Ñкрана не ÑущеÑтвует"
+188 "Символы поÑле Ñтроки Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка, ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñтроки и/или команды z"
+189 "Прошлый образец поиÑка отÑутÑтвует"
+190 "ПоиÑк завершилÑÑ Ð½Ð° начальной позиции"
+191 "Ðббревиатура превыÑила лимит раÑширениÑ: Ñимволы забыты"
+192 "Символ неправилен; квотируйте Ð´Ð»Ñ Ð²Ð²Ð¾Ð´Ð°"
+193 "Уже на начале вÑтавки"
+194 "Ðет Ñимволов Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ"
+195 "Передвижение за конец файла"
+196 "Передвижение за конец Ñтроки"
+197 "Движение Ñтроки не Ñделано"
+198 "Уже на начале файла"
+199 "Движение курÑора за начало файла"
+200 "Уже в первой колонке"
+201 "Буферы должны быть указаны до Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹"
+202 "Уже на конце файла"
+203 "Уже на конце Ñтроки"
+204 "%s не ÑвлÑетÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹ VI"
+205 "ИÑпользование: %s"
+206 "Ðет Ñимволов Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ"
+207 "Команда Q требует ex Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ñ‚ÐµÑ€Ð¼Ð¸Ð½Ð°Ð»Ð°"
+208 "Ðет команды Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð°"
+209 "Файл пуÑÑ‚"
+210 "Команда %s не может быть иÑпользована как команда перемещениÑ"
+211 "Уже в командном режиме"
+212 "КурÑор находитÑÑ Ð½Ðµ на Ñлове"
+214 "Значение опции windows Ñлишком велико, макÑимальное значение = %u"
+215 "Добавить"
+216 "Изменить"
+217 "Команда"
+218 "Ð’Ñтавить"
+219 "Заменить"
+220 "Движение курÑора за конец Ñкрана"
+221 "Движение курÑора за начало Ñкрана"
+222 "Ð”Ð»Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñкран должен быть больше чем Ñтроки %d"
+223 "Теневых окон нет"
+224 "Ðе ÑущеÑтвует теневого окна Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ¼ файла %s"
+225 "Ð’Ñ‹ не можете Ñделать единÑтвенное окно теневым"
+226 "Экран может быть Ñжат"
+227 "Экран не может быть Ñжат только до %d Ñтрок"
+228 "Экран не может быть раÑширен"
+230 "Этот Ñкран не может быть приоÑтановлен"
+231 "Прервано: назначенные клавиши забыты"
+232 "vi: временный буфер не оÑвобожден"
+233 "Данный тип терминала не имеет клавиши %s"
+234 "Может быть указан только один буфер"
+235 "ЧиÑло больше чем %lu"
+236 "Прервано"
+237 "Ðевозможно Ñоздать временный файл"
+238 "Внимание: %s Ñпециальный файл"
+239 "%s уже заблокирован, доÑтупен только на чтение"
+240 "%s: удален"
+241 "%s: закрыт"
+242 "%s: удален"
+243 "%s: удален"
+244 "Файл только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ, не запиÑан: ИÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+245 "Файл только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ, не запиÑан"
+246 "%s ÑущеÑтвует, не запиÑан; иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+247 "%s ÑущеÑтвует, не запиÑан"
+248 "ИÑпользуйте ! Ð´Ð»Ñ Ñ‡Ð°Ñтичной запиÑи файла"
+249 "ЧаÑÑ‚ÑŒ файла, файл не запиÑан"
+250 "%s: Файл изменÑлÑÑ Ð¿Ð¾Ð·Ð´Ð½ÐµÐµ, чем Ð´Ð°Ð½Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ: иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+251 "%s: Файл изменÑлÑÑ Ð¿Ð¾Ð·Ð´Ð½ÐµÐµ, чем Ð´Ð°Ð½Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ"
+252 "%s: защита на запиÑÑŒ была недоÑтупна"
+253 "ЗапиÑÑŒ..."
+254 "%s: Ð’ÐИМÐÐИЕ: ФÐЙЛ УСЕЧЕÐ"
+255 "Уже приÑутÑтвует в первой метке данной группы"
+256 "%s: новый файл: %lu Ñтрок, %lu Ñимволов"
+257 "%s: %lu Ñтрок, %lu Ñимволов"
+258 "%s раÑширилÑÑ Ð² Ñлишком большое количеÑтво имен файлов"
+259 "%s: Ñпециальный файл"
+260 "%s: не принадлежит Вам"
+261 "%s: доÑтупен не только Вам"
+262 "Файл изменен Ñо времени поÑледней запиÑи: Ñохраните или иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+263 "Файл изменен Ñо времени поÑледней запиÑи: Ñохраните или иÑпользуйте :edit Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+264 "Файл изменен Ñо времени поÑледней запиÑи: Ñохраните или иÑпользуйте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð°"
+265 "Файл временный: выход Ñотрет любые изменениÑ"
+266 "Файл только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ, автозапиÑÑŒ не Ñработала"
+267 "ЗапиÑи начаты заново"
+268 "подтвердить? [ynq]"
+269 "Ðажмите любую клавишу чтобы продолжить: "
+270 "Ðажмите любую клавишу чтобы продолжить [: чтобы ввеÑти еще ex команды]: "
+271 "Ðажмите любую клавишу чтобы продолжить [q чтобы выйти]: "
+272 "Эта форма %s требует ex Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ñ‚ÐµÑ€Ð¼Ð¸Ð½Ð°Ð»Ð°"
+273 "Вход в режим ввода ex."
+274 "Команда не удалаÑÑŒ, файл еще не прочтен."
+275 " прод?"
+276 "Ðеожиданное Ñимвольное Ñобытие"
+277 "Ðеожиданное Ñобытие 'конец файла'"
+278 "По запроÑу Ñовпадений нет"
+279 "Ðеожиданное Ñобытие прерываниÑ"
+280 "Ðеожиданное Ñобытие выхода"
+281 "Ðеожиданное Ñобытие перериÑовки"
+282 "Уже приÑутÑтвует в поÑледней метке данной группы"
+283 "Команда %s требует ex Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ñ‚ÐµÑ€Ð¼Ð¸Ð½Ð°Ð»Ð°"
+284 "Эта форма %s не поддерживаетÑÑ Ð¿Ð¾ÐºÐ° уÑтановлена Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñного редактированиÑ"
+285 "Ðеожиданное Ñтроковое Ñобытие"
+286 "Ðеожиданное Ñобытие таймаута"
+287 "Ðеожиданное Ñобытие запиÑи"
+288 "Ð”Ð»Ñ Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñкран должен быть больше чем Ñтолбцы %d"
+289 "Shell раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð½Ðµ поддерживаютÑÑ Ð¿Ð¾ÐºÐ° уÑтановлена Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñного редактированиÑ"
+290 "Команда %s не поддерживаетÑÑ Ð¿Ð¾ÐºÐ° уÑтановлена Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñного редактированиÑ"
+291 "set: Ð¾Ð¿Ñ†Ð¸Ñ %s не может быть выключена"
+292 "Экран Ñлишком мал"
+293 "добавлено"
+294 "изменено"
+295 "удалено"
+296 "приÑоединено"
+297 "перемещено"
+298 "Ñмещено"
+299 "Ñкопировано"
+300 "Ñтрока"
+301 "Ñтроки"
+303 "Файл изменен Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° поÑледней запиÑи."
+304 "Shell раÑширение не удалоÑÑŒ"
+305 "Ðет указанной %s опции редактированиÑ"
+307 "Ðет ex команды Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ"
+308 "Введите <CR> Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹, :q чтобы выйти"
+309 "ИÑпользуйте \"cscope help\" Ð´Ð»Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ð¸"
+310 "Ðет запущенного cscope ÑоединениÑ"
+311 "%s: неизвеÑтный тип поиÑка: иÑпользуйте один из %s"
+312 "%d: нет такого cscope ÑеанÑа"
+313 "set: %s Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не может быть включена"
+314 "set: %s Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не может быть уÑтановлена в 0"
+315 "%s: добавлено: %lu Ñтрок, %lu Ñимволов"
+316 "Ðеожиданное Ñобытие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð°"
+317 "%d файлов Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ"
+319 "%d Ñкранов в фоновом режиме; иÑпользуйте :display чтобы перечиÑлить их"
+320 "ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ ÐºÑƒÑ€Ñора"
+321 "Преобразование кодировки файлов не поддерживаетÑÑ"
+322 "Преобразование кодировки ввода не поддерживаетÑÑ"
+323 "Ðеверный ввод. УÑечено."
+324 "Ошибка Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² Ñтроке %d"
diff --git a/usr.bin/vi/catalog/spanish.UTF-8.base b/usr.bin/vi/catalog/spanish.UTF-8.base
new file mode 100644
index 000000000000..4a3059a84ca7
--- /dev/null
+++ b/usr.bin/vi/catalog/spanish.UTF-8.base
@@ -0,0 +1,306 @@
+002 "Desbordamiento de longitud de línea"
+003 "no se puede borrar la línea %lu"
+004 "no se puede añadir la línea %lu"
+005 "no se puede insertar en la línea %lu"
+006 "no se puede guardar la línea %lu"
+007 "no se puede obtener la última línea"
+008 "Error: no se puede recuperar la línea %lu"
+009 "Archivo de log"
+010 "No se realiza log, no se puede deshacer"
+011 "No hay cambios para deshacer"
+012 "No se realiza log, no se puede deshacer"
+013 "No se realiza log, no se puede remontar hacia adelante"
+014 "No hay cambios para rehacer"
+015 "%s/%d: error de log"
+016 "La entrada y salida estándar de Vi debe ser una terminal"
+017 "Marcar %s: no determinado"
+018 "Marcar %s: se borró la línea"
+019 "Marcar %s: la posición del cursor ya no existe"
+020 "Error: "
+021 "nuevo archivo"
+022 "nombre cambiado"
+023 "modificado"
+024 "no modificado"
+025 "DESTRABADO"
+026 "lectura solamente"
+027 "línea %lu de %lu [%ld%%]"
+028 "archivo vacío"
+029 "línea %lu"
+030 "El archivo %s no es un catálogo de mensajes"
+031 "No se puede determinar la opción por omisión %s"
+032 "Uso: %s"
+033 "determinar: no hay opción %s: 'determinar todo' establece todos los valores de opción"
+034 "determinar: [no] hay opción %s no tiene valor"
+035 "determinar: opción %s no es booleano"
+036 "determinar: opción %s: %s"
+037 "determinar: opción %s: %s: desbordamiento de valores"
+038 "determinar: opción %s: %s es un número ilegal"
+039 "determinar: opción %s no es booleano"
+040 "Las columnas en pantalla son demasiado pequeñas, menos de %d"
+041 "Las columnas en pantalla son demasiado grandes, más de %d"
+042 "Las líneas en pantalla son demasiado pequeñas, menos de %d"
+043 "Las líneas en pantalla son demasiado grandes, más de %d"
+044 "La opción lisp no está implementada"
+045 "mensajes no desconectados: %s"
+046 "mensajes no conectados: %s"
+047 "La opción de %s debe estar en dos grupos de caracteres"
+053 "El buffer por omisión está vacío"
+054 "El buffer %s está vacío"
+055 "Los archivos con nuevas líneas en el nombre son irrecuperables"
+056 "Las modificaciones no pueden recuperarse si la sesión falla"
+057 "Copiando archivo para recuperación..."
+058 "Preservación fracasada: %s"
+059 "Las modificaciones no pueden recuperarse si la sesión falla"
+060 "Archivo de respaldo fracasado: %s"
+061 "Copiando archivo para recuperación..."
+062 "Información sobre identificación del usuario %u no encontrada"
+063 "No se puede trabar archivo de recuperación"
+064 "Desbordamiento de buffer de archivo de recuperación"
+065 "Archivo de recuperación"
+066 "%s: archivo de recuperación defectuoso"
+067 "%s: archivo de recuperación defectuoso"
+068 "No hay archivos denominados %s, que usted pueda leer, para recuperar"
+069 "Existen versiones más antiguas de este archivo que usted puede recuperar"
+070 "Existen otros archivos que usted puede recuperar"
+071 "no envía email: %s"
+072 "Archivo vacío; no hay nada para buscar"
+073 "Se alcanzó el final del archivo sin encontrar el patrón"
+074 "No hay patrón anterior de búsqueda"
+075 "No se encontró el patrón"
+076 " Se alcanzó el principio del archivo sin encontrar el patrón"
+077 "Búsqueda reiniciada"
+078 "Buscando..."
+079 "No se encontró ningún carácter no imprimible"
+080 "Nombre de comando desconocido"
+082 "%s: comando no disponible en modalidad ex"
+083 "La cuenta no puede ser cero"
+084 "%s: mala especificación de línea"
+085 "Error interno de tabla de sintaxis (%s: %s)"
+086 "Uso: %s"
+087 "%s: buffer temporario no liberado"
+088 "Desplazamiento de marcador a antes de la línea 1"
+089 "Desplazamiento de marcador más allá del final del archivo"
+090 "@ con rango que corre cuando se cambia el archivo/la pantalla"
+091 "Comando global/v que corre cuando se cambia el archivo/la pantalla"
+092 "Comando Ex fracasado: comandos pendientes descartados"
+093 "Comando Ex fracasado: teclas mapeadas descartadas"
+094 "La segunda dirección es más pequeña que la primera"
+095 "No se suministra nombre de marca"
+096 "\\ no es seguido por / o ?"
+097 "Referencia a un número de línea menor que 0"
+098 "El comando %s es desconocido"
+099 "Desbordamiento de valor de dirección"
+100 "Subdesbordamiento de valor de dirección"
+101 "Combinación de dirección ilegal"
+102 "Dirección ilegal: sólo %lu líneas en el archivo"
+103 "Dirección ilegal: el archivo está vacío"
+104 "El comando %s no permite una dirección de 0"
+105 "No hay abreviaturas para visualizar"
+106 "Las abreviaturas deben terminar con un carácter de \"palabra\" "
+107 "Las abreviaturas no pueden contener tabs o espacios"
+108 "Las abreviaturas no pueden mezclar caracteres palabra/no-palabra, salvo al final"
+109 "\"%s\" no es una abreviatura"
+110 "Comando Vi fracasado: teclas mapeadas descartadas"
+111 "No hay más archivos para editar"
+112 "No hay archivos anteriores para editar"
+113 "No hay archivos anteriores para rebobinar"
+114 "No hay lista de archivos para visualizar"
+115 "No hay un comando anterior para reemplazar a \"!\""
+116 "No hay nombre de archivo para sustituir por %%"
+117 "No hay nombre de archivo para sustituir por #"
+118 "Error: execl: %s"
+119 "Error de E/S: %s"
+120 "Archivo modificado desde la última escritura completa; escribir o usar ! para alterar"
+121 "No se puede encontrar la ubicación del directorio inicial"
+122 "Nuevo directorio actual: %s"
+123 "No hay buffers sueltos para visualizar"
+124 "El comando %s no puede usarse como parte de un comando global o v"
+125 "%s/%s: sin fuente: no le pertenece a usted o a raíz"
+126 "%s/%s: sin fuente: no le pertenece a usted"
+127 "%s/%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+128 "%s: sin fuente: no le pertenece a usted o a raíz"
+129 "%s: sin fuente: no le pertenece a usted"
+130 "%s: sin fuente: puede ser escrito por un usuario que no sea el propietario"
+131 "No hay líneas siguientes para unir"
+132 "No hay anotaciones de mapa de entrada"
+133 "No hay anotaciones de mapa de comando"
+134 "El carácter %s no puede remapearse"
+135 "\"%s\" no está mapeado actualmente"
+136 "Marca de nombres debe ser un sólo carácter"
+137 "%s existe, no está escrito; usar ! para alterar"
+138 "Nuevo archivo exrc: %s"
+139 "La línea de destino se encuentra dentro del rango de movimiento"
+140 "El comando abierto requiere que se determine la opción abierta"
+141 "El comando abierto no se ha implementado aún"
+142 "No es posible preservar este archivo"
+143 "Archivo preservado"
+144 "%s: expandido a demasiados nombres de archivo"
+145 "Sólo pueden leerse los archivos regulares y los conductos nombrados"
+146 "%s: traba de lectura no disponible"
+147 "Leyendo..."
+148 "%s: %lu líneas, %lu caracteres"
+149 "No hay pantallas de fondo para mostrar"
+150 "El comando de script sólo está disponible en modalidad vi"
+151 "No hay comando para ejecutar"
+152 "opción de ancho de desplazamiento en 0"
+153 "Desbordamiento de cuenta"
+154 "Subdesbordamiento de cuenta"
+155 "Expresión regular especificada; marcador r no tiene significado"
+156 "Los marcadores #, l y p no pueden combinarse con el marcador c en la modalidad vi"
+157 "No se encontró coincidencia"
+158 "No se ingresó un identificador anterior"
+159 "Se encontraron menos de %s anotaciones en la pila de identificadores; usar :visualizar i[dentificadores]"
+160 "No hay archivo %s en la pila de identificadores al que se pueda volver; usar :visualizar i[dentificadores]"
+161 "Presionar Intro para continuar: "
+162 "%s: no se encontró el identificador"
+163 "%s: identificador corrompido en %s"
+164 "%s: el número de línea del identificador es posterior al final del archivo"
+165 "La pila de identificadores está vacía"
+166 "%s: patrón de búsqueda no encontrado"
+167 "%d archivos más para editar"
+168 "El buffer %s está vacío"
+169 "¿Confirmar cambio? [n]"
+170 "Interrumpido"
+171 "No hay buffer anterior para ejecutar"
+172 "No hay expresión regular anterior"
+173 "El comando %s requiere que se haya leído un archivo"
+174 "Uso: %s"
+175 "El comando visual requiere que se determine la opción abierta"
+177 "Archivo vacío"
+178 "No hay búsqueda F, f, T o t anterior"
+179 "%s no se encontró"
+180 "No hay archivo anterior para editar"
+181 "El cursor no está en un número"
+182 "El número resultante es demasiado grande"
+183 " El número resultante es demasiado pequeño"
+184 "No hay carácter coincidente en esta línea"
+185 "No se encontró un carácter coincidente"
+186 "No hay caracteres para reemplazar"
+187 "No hay otra pantalla a la que se pueda pasar"
+188 "Caracteres tras de cadena de búsqueda, desplazamiento de línea y/o comando z"
+189 "No hay patrón anterior de búsqueda"
+190 "Búsqueda vuelve a la posición inicial"
+191 "Se superó el límite de expansión de abreviatura: se descartaron caracteres"
+192 "Carácter ilegal; mencionar para entrar"
+193 "Ya se encuentra al principio de la inserción"
+194 "No hay más caracteres para borrar"
+195 "Movimiento más allá del final del archivo"
+196 "Movimiento más allá del final de la línea"
+197 "No hay movimiento del cursor"
+198 "Ya se encuentra al principio del archivo"
+199 "Movimiento más allá del principio del archivo"
+200 "Ya se encuentra en la primera columna"
+201 "Los buffers deben especificarse antes del comando"
+202 "Ya se encuentra al final del archivo"
+203 "Ya se encuentra al final de la línea"
+204 "%s no es un comando vi"
+205 "Uso: %s"
+206 "No hay caracteres para borrar"
+207 "El comando Q requiere la interfase de terminal ex"
+208 "No hay comando para repetir"
+209 "El archivo está vacío"
+210 "%s no puede usarse como comando de movimiento"
+211 "Ya se encuentra en modalidad de comando"
+212 "El cursor no se encuentra en una palabra"
+214 "El valor de opción de Windows es demasiado grande, el máx. es %u"
+215 "Añadir"
+216 "Cambiar"
+217 "Comando"
+218 "Insertar"
+219 "Reemplazar"
+220 "El movimiento va más allá del final de la pantalla"
+221 "El movimiento va más allá del principio de la pantalla"
+222 "La pantalla debe tener más de %d líneas para dividirse"
+223 "No hay pantallas de fondo"
+224 "No hay pantalla de fondo editando un archivo denominado %s"
+225 "No se puede poner fondo a la única pantalla que se visualiza"
+226 "La pantalla sólo puede reducirse a %d hileras"
+227 "La pantalla no puede reducirse"
+228 "La pantalla no puede aumentarse"
+230 "Esta pantalla no puede suspenderse"
+231 "Interrumpido: teclas mapeadas descartadas"
+232 "vi: buffer temporario no liberado"
+233 "Esta terminal no tiene tecla %s"
+234 "Sólo un buffer puede especificarse"
+235 "Número mayor que %lu"
+236 "Interrumpido"
+237 "No se puede crear archivo temporario"
+238 "Advertencia: %s no es un archivo regular"
+239 "%s ya se encuentra trabado, la sesión es de lectura solamente"
+240 "%s: eliminar"
+241 "%s: cerrar"
+242 "%s: eliminar"
+243 "%s: eliminar"
+244 "Archivo de lectura solamente, no escrito; usar ! para alterar"
+245 " Archivo de lectura solamente, no escrito"
+246 "%s existe, no escrito; usar ! para alterar"
+247 "%s existe, no escrito"
+248 "Archivo parcial, no escrito; usar ! para alterar"
+249 "Archivo parcial, no escrito"
+250 "%s: archivo modificado más recientemente que esta copia; usar ! para alterar"
+251 "%s: archivo modificado más recientemente que esta copia"
+252 "%s: la traba de escritura no estaba disponible"
+253 "Escribiendo..."
+254 "%s: ADVERTENCIA: ARCHIVO TRUNCADO"
+255 "Ya se encuentra en el primer identificador de este grupo"
+256 "%s: nuevo archivo: %lu líneas, %lu caracteres"
+257 "%s: %lu líneas, %lu caracteres"
+258 "%s expandido a demasiados nombres de archivos"
+259 "%s: no es un archivo regular"
+260 "%s: no le pertenece"
+261 "%s: accesible por un usuario que no sea el propietario"
+262 "Archivo modificado desde la última escritura completa; escribir o usar ! para alterar"
+263 "Archivo modificado desde la última escritura completa; escribir o usar :editar! para alterar"
+264 "Archivo modificado desde la última escritura completa; escribir o usar ! para alterar"
+265 "El archivo es temporario; al salir se descartarán las modificaciones"
+266 "Archivo de lectura solamente, las modificaciones no se autoescriben"
+267 "Se reinició el log"
+268 "confirmar? [snq]"
+269 "Presionar cualquier tecla para continuar: "
+270 "Presionar cualquier tecla para continuar [: para ingresar más comandos ex]: "
+271 "Presionar cualquier tecla para continuar [q para salir]: "
+272 "Esta forma de %s requiere la interfase terminal ex"
+273 "Ingresando en la modalidad de entrada ex."
+274 "Comando fracasado, no hay archivo leído aun."
+275 " cont?"
+276 "Evento inesperado de carácter"
+277 "Evento inesperado de final de archivo"
+278 "No hay coincidencias para consulta"
+279 "Evento inesperado de interrupción"
+280 "Evento inesperado de salida"
+281 "Evento inesperado de repintura"
+282 "Ya se encuentra en el último identificador de este grupo"
+283 "El comando %s requiere la interfase terminal ex"
+284 "Esta forma de %s no se encuentra soportada cuando se determina la opción de edición segura"
+285 "Evento inesperado de cadena"
+286 "Evento inesperado de tiempo excedido"
+287 "Evento inesperado de escritura"
+289 "Las expansiones de shell no se encuentran soportadas cuando se determina la opción de edición segura"
+290 "El comando %s no se encuentra soportado cuando se determina la opción de edición segura"
+291 "determinar: la opción %s puede no estar desconectada"
+292 "El monitor es demasiado pequeño."
+293 "agregado"
+294 "cambiado"
+295 "borrado"
+296 "unido"
+297 "movido"
+298 "desplazado"
+299 "arrancado"
+300 "línea"
+301 "líneas"
+302 "Vi no se cargó con un intérprete Tcl"
+303 "Archivo modificado desde la última escritura."
+304 "Expansión de shell fracasada"
+305 "No hay opción de edición %s especificada"
+306 "Vi no se cargó con un intérprete Perl"
+307 "No hay comando ex para ejecutar"
+308 "Ingresar <CR> para ejecutar un comando, :q para salir"
+309 "Usar \"cscope ayuda\" para obtener ayuda"
+310 "No hay conexiones cscope corriendo"
+311 "%s: tipo de búsqueda desconocido: usar uno de %s"
+312 "%d: no existe esta sesión cscope"
+313 "determinar: la opción %s no puede conectarse nunca"
+314 "determinar: la opción %s no puede determinarse nunca en 0"
+315 "%s: añadido: %lu líneas, %lu caracteres"
+316 "Evento inesperado de modificación de tamaño"
+317 "%d archivos para editar"
diff --git a/usr.bin/vi/catalog/swedish.UTF-8.base b/usr.bin/vi/catalog/swedish.UTF-8.base
new file mode 100644
index 000000000000..fc08dfc8cd2d
--- /dev/null
+++ b/usr.bin/vi/catalog/swedish.UTF-8.base
@@ -0,0 +1,306 @@
+002 "För långa rader"
+003 "kan inte ta bort rad %lu"
+004 "kan inte lägga till på rad %lu"
+005 "kan inte sätta in på rad %lu"
+006 "kan inte lagra rad %lu"
+007 "kan inte hämta sista raden"
+008 "Fel: kan inte hämta rad %lu"
+009 "Loggningsfil"
+010 "Loggning utförs inte, ångra är inte möjligt"
+011 "Inga ändringar att ångra"
+012 "Loggning utförs inte, ångra är inte möjligt"
+013 "Loggning utförs inte, ångra ångra är inte möjligt"
+014 "Inga ändringar att återgöra"
+015 "%s/%d: fel vid loggning"
+016 "Vi:s standard in och ut måste gå till en terminal"
+017 "Markering %s: inte satt"
+018 "Markering %s: raden har tagits bort"
+019 "Markering %s: markörpositionen finns inte längre"
+020 "Fel: "
+021 "ny fil"
+022 "namnet ändrades"
+023 "ändrad"
+024 "oförändrad"
+025 "OLÃ…ST"
+026 "inte skrivbar"
+027 "rad %lu av %lu [%ld%%]"
+028 "tom fil"
+029 "rad %lu"
+030 "Filen %s är ingen meddelandekatalog"
+031 "Kan inte sätta standardvärde för %s flaggan"
+032 "Användning: %s"
+033 "set: %s är en okänd flagga: \"set all\" visar alla flaggor"
+034 "set: [no]%s flaggan kan inte ges ett värde"
+035 "set: %s flaggan är inte boleansk"
+036 "set: %s flaggan: %s"
+037 "set: %s flaggan: %s: för stort värde"
+038 "set: %s flaggan: %s är ett otillåtet tal"
+039 "set: %s flaggan är inte boleansk"
+040 "Fönsterkolumnerna är för få, mindre än %d"
+041 "Fönsterkolumnerna är för många, fler än %d"
+042 "Fönsterraderna är för få, mindre än %d"
+043 "Fönsterraderna är för många, fler än %d"
+044 "Lisp flaggan är inte implementerad"
+045 "meddelanden är inte avslagna: %s"
+046 "meddelanden är inte påslagna: %s"
+047 "%s flaggan måste ges i teckengrupper om två"
+053 "Standardbufferten är tom"
+054 "Buffer %s är tom"
+055 "Filer med radmatning i namnet kan inte återskapas"
+056 "Ändringar kan inte återskapas om programmet kraschar"
+057 "Kopierar filen för återskapning..."
+058 "Säkerhetskopiering misslyckades: %s"
+059 "Ändringar kan inte återskapas om programmet kraschar"
+060 "Misslyckades att säkerhetskopiera filen: %s"
+061 "Kopierar filen för återskapning..."
+062 "Kan inte hitta information om användaridentitet %u"
+063 "Kan inte låsa återskapningsfilen"
+064 "Återskapningsfilens buffer överskriven"
+065 "Ã…terskapningsfil"
+066 "%s: Återskapningsfilen är korrupt"
+067 "%s: Återskapningsfilen är korrupt"
+068 "Det finns ingen fil %s, läsbar av dig, att återskapa"
+069 "Det finns äldre versioner av denna fil som du kan återskapa"
+070 "Det finns andra filer du kan återskapa"
+071 "skickar inte email: %s"
+072 "Filen är tom; inget att söka i"
+073 "Kom till slutet på filen utan att hitta söksträngen"
+074 "Ingen tidigare söksträng"
+075 "Hittar inte söksträngen"
+076 "Kom till början av filen utan att hitta söksträngen"
+077 "Sökningen slog runt"
+078 "Söker..."
+079 "Inga icke skrivbara tecken funna"
+080 "Okänt kommandonamn"
+082 "%s: kommandot är inte tillgängligt i \"ex\" läge"
+083 "Talet får inte vara noll"
+084 "%s: Ogiltig radspecifikation"
+085 "Fel i intern syntaxtabell (%s: %s)"
+086 "Användning: %s"
+087 "%s: temporärbuffert inte frisläppt"
+088 "Offset är före rad 1"
+089 "Offset är efter slutet på filen"
+090 "@ med intervall exekverades när filen/fönstret ändrades"
+091 "Global/v kommando exekverades när filen/fönstret ändrades"
+092 "Ex kommando misslyckades: efterföljande kommandon ignorerade"
+093 "Ex kommando misslyckades: omdefinierade tangenter ignorerade"
+094 "Den andra adressen är mindre än den första"
+095 "Inget namn på markering givet"
+096 "\\ följs inte av / eller ?"
+097 "Referens till ett radnummer mindre än 0"
+098 "%s kommandot är inte känt"
+099 "Värdet på adressen är för stort"
+100 "Värdet på adressen är för litet"
+101 "Otillåten adresskombination"
+102 "Otillåten adress: bara %lu rader finns i filen"
+103 "Otillåten adress: filen är tom"
+104 "%s kommandot tillåter inte en adress som är 0"
+105 "Inga förkortningar att visa"
+106 "Förkortningar måste sluta med ett \"ord\" tecken"
+107 "Förkortningar kan inte innehålla mellanslag eller tab"
+108 "Förkortningar kan inte blanda \"ord\"/\"icke ord\" tecken, utom i slutet"
+109 "\"%s\" är ingen förkortning"
+110 "Vi kommando misslyckades: omdefinierade tangenter ignorerade"
+111 "Inga fler filer att editera"
+112 "Inga tidigare filer att editera"
+113 "Inga tidigare filer att spela tillbaka"
+114 "Ingen fillista att visa"
+115 "Inget tidigare kommando att ersätta \"!\" med"
+116 "Inget filnamn att ersätta %% med"
+117 "Inget filnamn att ersätta # med"
+118 "Fel: execl: %s"
+119 "I/O fel: %s"
+120 "Filen ändrad efter sista skrivning; spara eller använd !"
+121 "Kan inte hitta hemkatalog"
+122 "Ny nuvarande katalog: %s"
+123 "Inga \"cut buffers\" att visa"
+124 "%s kommandot kan inte används som del i ett \"global\" eller v kommando"
+125 "%s/%s: inte läst: varken du eller root är ägare"
+126 "%s/%s: inte läst: du är inte ägare"
+127 "%s/%s: inte läst: skrivbar av annan än ägaren"
+128 "%s: inte läst: varken du eller root är ägare"
+129 "%s: inte läst: du är inte ägare"
+130 "%s: inte läst: skrivbar av annan än ägaren"
+131 "Ingen nästa rad att sätta ihop med"
+132 "Det finns inget i inmatningsmappningen"
+133 "Det finns inget i kommandomappningen"
+134 "%s tecknet kan inte mappas om"
+135 "\"%s\" är inte ommappat just nu"
+136 "Namn på markeringar måste vara ett tecken långa"
+137 "%s finns, inget sparat; använd ! för att spara"
+138 "Ny exrc fil: %s"
+139 "Målraden ligger inne i området som ska flyttas"
+140 "Open kommandot kräver att open flaggan är satt"
+141 "Open kommandot är inte implementerat ännu"
+142 "Säkerhetskopiering av filen är inte möjligt"
+143 "Filen säkerhetskopierad"
+144 "%s expanderade till för många filnamn"
+145 "Endast vanliga filer och namngivna rör kan läsas"
+146 "%s: läslåset är otillgängligt"
+147 "Läser..."
+148 "%s: %lu rader, %lu tecken"
+149 "Inga bakgrundsfönster att visa"
+150 "Script kommandot finns bara i \"vi\" läge"
+151 "Inget kommando att exekvera"
+152 "shiftwidth flaggan satt till 0"
+153 "Talet har för stort värde"
+154 "Talet har för litet värde"
+155 "Reguljärt uttryck är givet; r flaggan är meningslös"
+156 "#, l och p flaggorna kan inte kombineras med c flaggan i \"vi\" läge"
+157 "Ingen matchande text funnen"
+158 "Inget tidigare märke har givits"
+159 "Det är färre än %s märken i stacken; använd :display t[ags]"
+160 "Det finns ingen fil %s i märkesstacken; använd :display t[ags]"
+161 "Tryck Enter för att fortsätta: "
+162 "%s: märke inte funnet"
+163 "%s: korrupt märke i %s"
+164 "%s: märkets radnummer är bortom filslutet"
+165 "Märkesstacken är tom"
+166 "%s: söksträngen inte funnen"
+167 "%d filer till att editera"
+168 "Buffert %s är tom"
+169 "Bekräfta ändring? [n]"
+170 "Avbruten"
+171 "Ingen tidigare buffert att exekvera"
+172 "Inget tidigare reguljärt uttryck"
+173 "%s kommandot kräver att en fil redan lästs in"
+174 "Användning: %s"
+175 "Visual kommandot kräver att open flaggan är satt"
+177 "Tom fil"
+178 "Ingen tidigare F, f, T eller t sökning"
+179 "%s inte funnen"
+180 "Ingen tidigare fil att editera"
+181 "Markören är inte i ett tal"
+182 "Det resulterande talet är för stort"
+183 "Det resulterande talet är för litet"
+184 "Inget matchande tecken på denna rad"
+185 "Matchande tecken inte funnet"
+186 "Det finns inga tecken att ersätta"
+187 "Det finns inget fönster att byta till"
+188 "Tecken efter söksträng, radoffset och/eller z kommandot"
+189 "Ingen tidigare söksträng"
+190 "Sökningen slog runt till ursprungliga positionen"
+191 "Förkortning överskred expanderingsgränsen: tecken har tagits bort"
+192 "Ogiltigt tecken; använd \"quote\" för att sätta in"
+193 "Redan i början på insättningen"
+194 "Inga fler tecken att ta bort"
+195 "Försök att gå bortom slutet på filen"
+196 "Försök att gå bortom slutet på raden"
+197 "Ingen förflyttning gjord"
+198 "Redan i början på filen"
+199 "Försök att gå före början på filen"
+200 "Redan i första kolumnen"
+201 "Buffertar måste anges före kommandot"
+202 "Redan i slutet av filen"
+203 "Redan på slutet av raden"
+204 "%s är inte ett \"vi\" kommando"
+205 "Användning: %s"
+206 "Inga tecken att ta bort"
+207 "Q kommandot kräver \"ex\" i terminalläge"
+208 "Inget kommando att repetera"
+209 "Filen är tom"
+210 "%s kan inte användas som ett förflyttningskommando"
+211 "Redan i kommando läge"
+212 "Markören är inte i ett ord"
+214 "Windows flaggans värde är för stor, största värde är %u"
+215 "Lägg till"
+216 "Ändra"
+217 "Kommando"
+218 "Sätt in"
+219 "Ersätt"
+220 "Förflyttning bortom fönsterslut"
+221 "Förflyttning till före fönstrets början"
+222 "Fönstret måste vara större än %d rader för delning"
+223 "Det finns inga fönster i bakgrunden"
+224 "Det finns inget fönster i bakgrunden som editerar filen %s"
+225 "Du får inte sätta ditt enda synliga fönster i bakgrunden"
+226 "Fönstret kan bara krympa till %d rader"
+227 "Fönstret kan inte krympa"
+228 "Fönstret kan inte växa"
+230 "Detta fönster kan inte pausas"
+231 "Avbrutet: omdefinierade tangenter ignorerade"
+232 "vi: temporärbuffertar inte frisläppta"
+233 "Denna terminal har ingen %s tangent"
+234 "Endast en buffert kan anges"
+235 "Talet är större än %lu"
+236 "Avbrutet"
+237 "Kan inte skapa temporär fil"
+238 "Warning: %s är inte en normal fil"
+239 "%s är redan låst, detta blir en icke skrivbar session"
+240 "%s: ta bort"
+241 "%s: stäng"
+242 "%s: ta bort"
+243 "%s: ta bort"
+244 "Ej skrivbar fil, filen inte sparad; använd ! för att skriva över"
+245 "Ej skrivbar fil, filen inte sparad"
+246 "%s finns, ej sparad; använd ! för att utföra operationen"
+247 "%s finns, filen inte sparad"
+248 "Ofullständig fil, filen inte sparad, använd ! för att skriva över"
+249 "Ofullständig fil, filen inte sparad"
+250 "%s: filen ändrad efter denna kopia togs; använd ! för att utföra operationen"
+251 "%s: filen ändrad efter denna kopia togs"
+252 "%s: skrivlåset är otillgängligt"
+253 "Skriver..."
+254 "%s: VARNING: FILEN TRUNKERAD"
+255 "Redan vid första märket i denna grupp"
+256 "%s: ny fil: %lu rader, %lu tecken"
+257 "%s: %lu rader, %lu tecken"
+258 "%s expanderade till för många filnamn"
+259 "%s är inte en normal fil"
+260 "%s ägs inte av dig"
+261 "%s är åtkomstbar av andra än ägaren"
+262 "Filen har ändrats efter den sparats; spara eller använd !"
+263 "Filen har ändrats efter den sparats; spara eller använd :edit!"
+264 "Filen har ändrats efter den sparats; spara eller använd !"
+265 "Filen är temporär; exit kastar bort ändringarna"
+266 "Ej skrivbar fil, ändringar har inte automatsparats"
+267 "Loggningen startar om"
+268 "bekräfta? [ynq]"
+269 "Tryck på en tangent för att fortsätta: "
+270 "Tryck på en tangent för att fortsätta [: för att ge fler kommandon]: "
+271 "Tryck på en tangent för att fortsätta [q för att avsluta]: "
+272 "Den formen av %s kräver \"ex\" i terminalläge"
+273 "Går till \"ex\" inmatningsläge."
+274 "Kommandot misslyckades, ingen fil inläst ännu."
+275 " forts?"
+276 "Oväntad teckenhändelse"
+277 "Oväntad filslutshändelse"
+278 "Sökningen hittade ingenting"
+279 "Oväntad avbrottshändelse"
+280 "Oväntad avslutningshändelse"
+281 "Oväntad omritningshändelse"
+282 "Redan vid sista märket i denna grupp"
+283 "%s kommandot kräver \"ex\" i terminalläge"
+284 "Den formen av %s är inte tillgänglig när secure edit flaggan är satt"
+285 "Oväntad stränghändelse"
+286 "Oväntad tidshändelse"
+287 "Oväntad skrivhändelse"
+289 "Skalexpansion är inte tillgänglig när secure edit flaggan är satt"
+290 "%s kommandot är inte tillgänglig när secure edit flaggan är satt"
+291 "set: %s kan inte slås av"
+292 "Fönstret för litet."
+293 "tillagda"
+294 "ändrade"
+295 "borttagna"
+296 "ihopsatta"
+297 "flyttade"
+298 "flyttade"
+299 "inklistrade"
+300 "rad"
+301 "rader"
+302 "Vi har inte länkats med en Tcl tolk"
+303 "Filen har ändrats efter den sparats."
+304 "Skalexpansion misslyckades"
+305 "Ingen %s edit flagga given"
+306 "Vi har inte länkats med en Perl tolk"
+307 "Inga \"ex\" kommandon att exekvera"
+308 "Tryck <CR> för att exekvera kommando, :q för att avsluta"
+309 "Gör \"cscope help\" för hjälp"
+310 "Inga cscope kopplingar körs"
+311 "%s: okänd söktyp: använd en av %s"
+312 "%d: ingen sådan cscope session"
+313 "set: %s flaggan får aldrig slås på"
+314 "set: %s flaggan får aldrig sättas till 0"
+315 "%s: tillagt: %lu rader, %lu tecken"
+316 "Oväntad storleksändring"
+317 "%d filer att editera"
diff --git a/usr.bin/vi/catalog/uk_UA.UTF-8.base b/usr.bin/vi/catalog/uk_UA.UTF-8.base
new file mode 100644
index 000000000000..b4d6887a011b
--- /dev/null
+++ b/usr.bin/vi/catalog/uk_UA.UTF-8.base
@@ -0,0 +1,306 @@
+002 "ÐŸÐµÑ€ÐµÐ¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸ Ñ€Ñдку"
+003 "неможливо Ñтерти Ñ€Ñдок %lu"
+004 "неможливо додати до Ñ€Ñдку %lu"
+005 "неможливо вÑтавити в Ñ€Ñдок %lu"
+006 "неможливо розміÑтити Ñ€Ñдок %lu"
+007 "неможливо діÑтати оÑтанній Ñ€Ñдок"
+008 "Помилка: неможливо отримати Ñ€Ñдок %lu"
+009 "Файл запиÑів"
+010 "ЗапиÑи не велиÑÑ, неможливо відмінити оÑтанню команду"
+011 "Ðема чого відмінÑти"
+012 "ЗапиÑи не велиÑÑ, неможливо відмінити оÑтанню команду"
+013 "ЗапиÑи не велиÑÑ, неможливо продивитиÑÑ Ð²Ð¿ÐµÑ€ÐµÐ´"
+014 "Ðема чого повторювати"
+015 "%s/%d: помилка запиÑу протоколу"
+016 "Стандартним введеннÑм/виведеннÑм Ð´Ð»Ñ vi має бути термінал"
+017 "Мітка %s: не вÑтановлено"
+018 "Мітка %s: Ñ€Ñдок Ñтерто"
+019 "Мітка %s: позиції курÑору більше не Ñ–Ñнує"
+020 "Помилка: "
+021 "Ðовий файл"
+022 "Iм'Ñ Ð·Ð¼Ñ–Ð½Ð¸Ð»Ð¾ÑÑŒ"
+023 "змінений"
+024 "не змінений"
+025 "РO3БЛOКOÐ’ÐÐO"
+026 "тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
+027 "Ñ€Ñдок %lu з %lu [%ld%%]"
+028 "пуÑтий файл"
+029 "Ñ€Ñдок %lu"
+030 "Файл %s не є файлом повідомленнь"
+031 "Ðеможливо вÑтановити опцію %s за змовчаннÑм"
+032 "ВикориÑтаннÑ: %s"
+033 "Опції %s немає: 'set all' показує вÑÑ– можливі опції"
+034 "set: [no]%s не набуває такого значеннÑ"
+035 "set: %s Ð¾Ð¿Ñ†Ñ–Ñ Ð½Ðµ Ñ” логічною"
+036 "set: Ð¾Ð¿Ñ†Ñ–Ñ %s: %s"
+037 "set: Ð¾Ð¿Ñ†Ñ–Ñ %s: %s: переповненнÑ"
+038 "set: неправильне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ %s"
+039 "set: %s Ð¾Ð¿Ñ†Ñ–Ñ Ð½Ðµ Ñ” логічною"
+040 "КількіÑÑ‚ÑŒ колонок на Ñкрані надто мала, менше ніж %d"
+041 "КількіÑÑ‚ÑŒ колонок на Ñкрані надто велика, більше ніж %d"
+042 "КількіÑÑ‚ÑŒ Ñ€Ñдків на Ñкрані надто мала, менше ніж %d"
+043 "КількіÑÑ‚ÑŒ Ñ€Ñдків на Ñкрані надто велика, більше ніж %d"
+044 "ÐžÐ¿Ñ†Ñ–Ñ lisp відÑутнÑ"
+045 "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вимкнені: %s"
+046 "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ ввімкнені: %s"
+047 "ÐžÐ¿Ñ†Ñ–Ñ %s повинна міÑтити групи з двох Ñимволів"
+053 "Стартовий буфер порожній"
+054 "Буфер %s порожній"
+055 "Ðеможливо відновити файл, що міÑтить в імені Ñимволи Ð¿ÐµÑ€ÐµÐ²ÐµÐ´ÐµÐ½Ð½Ñ ÐºÐ°Ñ€ÐµÑ‚ÐºÐ¸"
+056 "Зміни не можна буде відновити піÑÐ»Ñ ÐºÑ€Ð°Ñ…Ñƒ ÑеÑÑ–Ñ—"
+057 "ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ..."
+058 "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ðµ вдалоÑÑŒ: %s"
+059 "Зміни не можна буде відновити піÑÐ»Ñ ÐºÑ€Ð°Ñ…Ñƒ ÑеÑÑ–Ñ—"
+060 "Ð—Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð¿Ñ–Ñ— файлу не вдалоÑÑŒ: %s"
+061 "ÐšÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ..."
+062 "Iнформацію про кориÑтувача %u не знайдено"
+063 "Заблокувати відновленний файл неможливо"
+064 "Буфер відновленого файлу переповнено"
+065 "Відновленний файл"
+066 "%s: файл відновленний не до кінцÑ"
+067 "%s: файл відновленний не до кінцÑ"
+068 "Ðе Ñ–Ñнуює файлів з іменем %s, Ñкі Ви можете прочитати"
+069 "IÑнують Ñтарі верÑÑ–Ñ— файлу, Ñкі можна відновити"
+070 "IÑнують інші файли, Ñкі можна відновити"
+071 "e-mail не відіÑлано: %s"
+072 "Файл пуÑтий - нема чого шукати"
+073 "ДоÑÑнуто ÐºÑ–Ð½Ñ†Ñ Ñ„Ð°Ð¹Ð»Ñƒ без Ð·Ð½Ð°Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð½Ñ Ð·Ñ€Ð°Ð·ÐºÑƒ пошуку"
+074 "Ðе задано зразок пошуку"
+075 "Зразок пошуку не знайдено"
+076 "ДоÑÑнуто початку файлу без Ð·Ð½Ð°Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð½Ñ Ð·Ñ€Ð°Ð·ÐºÑƒ пошуку"
+077 "Пошук зациклено"
+078 "Пошук..."
+079 "Ðепечатних Ñимволів не знайдено"
+080 "Ðевідома команда"
+082 "%s: команда не доÑтупна в режимі ex"
+083 "Лічильник не може бути нулем"
+084 "%s: неправильне Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ñдку"
+085 "Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° в ÑинтакÑиÑÑ– (%s: %s)"
+086 "ВикориÑтаннÑ: %s"
+087 "%s: тимчаÑовий буфер не викориÑтано"
+088 "Мітку поÑтавлено перед першим Ñ€Ñдком"
+089 "Мітку поÑтавлено піÑÐ»Ñ ÐºÑ–Ð½Ñ†Ñ Ñ„Ð°Ð¹Ð»Ñƒ"
+090 "@ з діапазоном працює коли змінено файл/вікно"
+091 "Команда Global/v працює коли змінено файл/вікно"
+092 "Команда ex не вдалаÑÑŒ: наÑтупні команди з'ігноровано"
+093 "Команда ex не вдалаÑÑŒ: відображені клавіші з'ігноровано"
+094 "Друга адреÑа менше ніж перша"
+095 "Ðе вказано ім'Ñ Ð¼Ñ–Ñ‚ÐºÐ¸"
+096 "\\ не закінчуєтьÑÑ / чи ?"
+097 "ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñ€Ñдок з номером, меншим ніж 0"
+098 "Команда %s невідома"
+099 "ÐŸÐµÑ€ÐµÐ¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° адреÑ"
+100 "Ðедобір лічильника адреÑ"
+101 "ÐедопуÑтима ÐºÐ¾Ð¼Ð±Ñ–Ð½Ð°Ñ†Ñ–Ñ Ð² адреÑÑ–"
+102 "Ðеправильна адреÑа: вÑього %lu Ñ€Ñдків у файлі"
+103 "Ðеправильна адреÑа: файл пуÑтий"
+104 "Команда %s не може викориÑтовувати адреÑу 0"
+105 "Ðемає абревіатур"
+106 "Ðбревіатури повинні закінчуватиÑÑ Ñимволом \"Ñлів\""
+107 "Ð’ абревіатурі не можна викориÑтовувати Ñимволи табулÑції та пробіли"
+108 "Ðбревіатури не можуть змішувати Ñимволи Ñлів/не-Ñлів, хіба що в кінці Ñ€Ñдку"
+109 "\"%s\" не абревіатура"
+110 "Команда Vi не вдалаÑÑŒ: відображені клавіші з'ігноровано"
+111 "Файлів Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ немає"
+112 "Попереднього файлу Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¼Ð°Ñ”"
+113 "Попереднього файлу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду немає"
+114 "Ðемає файлів"
+115 "Ðемає попередньої команди Ð´Ð»Ñ Ð·Ð°Ð¼Ñ–Ð½Ð¸ \"!\""
+116 "ВідÑутнє ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¼Ñ–Ð½Ð¸ %%"
+117 "ВідÑутнє ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¼Ñ–Ð½Ð¸ #"
+118 "Помилка: execl: %s"
+119 "Помилка введеннÑ/виведеннÑ: %s"
+120 "Файл модифіковано піÑÐ»Ñ Ð¾Ñтанньої команди повного запиÑу: збережіть чи викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+121 "Ðеможливо знайти домашній каталог"
+122 "Ðовий каталог: %s"
+123 "Ðемає наповнених буферів"
+124 "Команда %s не викориÑтовуєтьÑÑ Ñк чаÑтина команди global чи v"
+125 "%s/%s: не відкрито: не належить Вам чи адмініÑтратору"
+126 "%s/%s: не відкрито: не належить Вам"
+127 "%s/%s: не відкрито: можливіÑÑ‚ÑŒ запиÑу кориÑтувачем, Ñкий не Ñ” влаÑником"
+128 "%s: не відкрито: не належить Вам чи адмініÑтратору"
+129 "%s: не відкрито: не належить Вам"
+130 "%s: не відкрито: можливіÑÑ‚ÑŒ запиÑу кориÑтувачем, Ñкий не Ñ” влаÑником"
+131 "Ðемає більше Ñ€Ñдків Ð´Ð»Ñ Ð¾Ð±'єднаннÑ"
+132 "Ðемає параметрів введеннÑ"
+133 "Ðемає параметрів команди"
+134 "Символ %s не можна переназначити"
+135 "\"%s\" зараз не переназначено"
+136 "Iм'Ñ Ð¼Ñ–Ñ‚ÐºÐ¸ -- один Ñимвол"
+137 "%s Ñ–Ñнує, не запиÑано; викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+138 "Ðовий файл exrÑ: %s"
+139 "РÑдок Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾ вÑередині діапазону переміщеннÑ"
+140 "Команда open вимагає вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð¿Ñ†Ñ–Ñ— open"
+141 "Команду open ще не реалізовано"
+142 "ЗахиÑÑ‚ файлу неможливий"
+143 "Файл захищено"
+144 "%s розширивÑÑ Ð² надто велику кількіÑÑ‚ÑŒ імен файлів"
+145 "Прочитати можна тільки проÑтий файл чи іменований канал(pipe)"
+146 "%s: Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ"
+147 "Зчитую..."
+148 "%s: %lu Ñ€Ñдків, %lu Ñимволів"
+149 "Ðемає тіньових вікон"
+150 "Команда script доÑтупна лише в режимі vi"
+151 "Ðема команди Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ"
+152 "Опцію shiftwidth вÑтановлено в 0"
+153 "ÐŸÐµÑ€ÐµÐ¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ°"
+154 "Цикл виконано не до кінцÑ"
+155 "Вказано регулÑрний вираз; параметр 'r' не має ÑенÑу"
+156 "Параметри #, l та p не можна комбінувати з параметром 'c' в режимі vi"
+157 "Співпадань немає"
+158 "Tег відÑутній"
+159 "Менше ніж %s запиÑів у Ñтеку тегів; викориÑтайте :display t[ags]"
+160 "Ðемає файлу %s в Ñтеку тегів Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ; викориÑтайте :display t[ags]"
+161 "ÐатиÑніть ENTER Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ: "
+162 "%s: тег не знайдено"
+163 "%s: зіпÑований тег в %s"
+164 "%s: номер Ñ€Ñдку тега знаходитьÑÑ Ð·Ð° кінцем файлу"
+165 "Стек тегів порожній"
+166 "%s: зразок пошуку не знайдено"
+167 "ЗалишилоÑÑŒ %d файлів Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ"
+168 "Буфер %s порожній"
+169 "Змінити? [n]"
+170 "Перервано"
+171 "Ðемає буферу Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ"
+172 "Ðемає попереднього регулÑрного виразу"
+173 "Команда %s вимагає вже прочитаний файл"
+174 "ВикориÑтаннÑ: %s"
+175 "Команда visual вимагає вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð¿Ñ†Ñ–Ñ— open"
+177 "ПуÑтий файл"
+178 "Ðемає попереднього пошуку F, f, T, чи t"
+179 "%s не знайдено"
+180 "Ðемає попереднього файлу Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ"
+181 "КурÑор Ñтоїть не на цифрі"
+182 "Oтримане чиÑло надто велике"
+183 "Oтримане чиÑло надто мале"
+184 "Ðемає відповідного Ñимволу в цьому Ñ€Ñдку"
+185 "Відповідний Ñимвол не знайдено"
+186 "Ðемає Ñимволів Ð´Ð»Ñ Ð·Ð°Ð¼Ñ–Ð½Ð¸"
+187 "Ðемає іншого вікна"
+188 "Символи піÑÐ»Ñ Ñ€Ñдку Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ, Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ€Ñдку та/чи команди z"
+189 "Ðемає попереднього зразку пошуку"
+190 "Пошук закінчивÑÑ Ð½Ð° початковій позиції"
+191 "Ðбревіатура перевищила ліміт розширеннÑ: Ñимволи з'ігноровано"
+192 "Ðедозволений Ñимвол: задайте в дужках"
+193 "Вже на початку вÑтавки"
+194 "Ðемає Ñимволів Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
+195 "Рух за кінець файлу"
+196 "Рух за кінець Ñ€Ñдку"
+197 "КурÑор не переміщувавÑÑ"
+198 "Вже на початку файлу"
+199 "Рух курÑору за початок файлу"
+200 "Вже в першій колонці"
+201 "Буфер треба вказувати перед командою"
+202 "Вже на кінці файлу"
+203 "Вже на кінці Ñ€Ñдку"
+204 "%s не команда Vi"
+205 "ВикориÑтаннÑ: %s"
+206 "Ðемає Ñимволів Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
+207 "Команда Q вимагає інтерфейÑу ex"
+208 "Ðемає команди Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ"
+209 "Файл пуÑтий"
+210 "Команду %s не можна викориÑтати Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ"
+211 "Вже в командному режимі"
+212 "КурÑор Ñтоїть не на Ñлові"
+214 "Ð—Ð½Ð°Ñ‡Ð½ÐµÐ½Ð½Ñ Ð¾Ð¿Ñ†Ñ–Ñ— Windows надто велике, макÑимум = %u"
+215 "ДопиÑати"
+216 "Змінити"
+217 "Команда"
+218 "Ð’Ñтавити"
+219 "Замінити"
+220 "Рух курÑору за кінець Ñкрану"
+221 "Рух курÑору за початок Ñкрану"
+222 "Ð”Ð»Ñ Ñ€Ð¾Ð·Ð±Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–ÐºÐ½Ð¾ має міÑтити більше ніж %d Ñ€Ñдків"
+223 "Тіньових вікон немає"
+224 "Ðемає тіньового вікна з редагуваннÑм файлу %s"
+225 "Ðе можна зробити тіньовим єдине вікно"
+226 "Вікно можна ÑтиÑнути лише до %d Ñ€Ñдків"
+227 "Вікно не можна ÑтиÑнути"
+228 "Вікно не можна розширити"
+230 "Це вікно не можна призупинити"
+231 "Перервано: відображені клавіші з'ігноровано"
+232 "vi: тимчаÑовий буфур не вивільнено"
+233 "Цей тип терміналу немає клавіші %s"
+234 "Можна вказати лише один буфер"
+235 "ЧиÑло більше, ніж %lu"
+236 "Перервано"
+237 "Ðеможлу Ñтворити тимчаÑовий файл"
+238 "УВÐГÐ: %s Ñпеціальний файл"
+239 "%s вже заблоковано, доÑтупний тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
+240 "%s: Ñтерто"
+241 "%s: закрито"
+242 "%s: Ñтерто"
+243 "%s: Ñтерто"
+244 "Файл тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ, не запиÑано: ВикориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+245 "Файл тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ, не запиÑано"
+246 "%s Ñ–Ñнує, не запиÑано; викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+247 "%s Ñ–Ñнує, не запиÑано"
+248 "ВикориÑтайте ! Ð´Ð»Ñ Ñ‡Ð°Ñткового запиÑу файлу"
+249 "ЧаÑтина файлу, файл не запиÑано"
+250 "%s: Файл змінювавÑÑ Ð¿Ñ–Ð·Ð½Ñ–ÑˆÐµ, ніж Ñ†Ñ ÐºÐ¾Ð¿Ñ–Ñ: викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+251 "%s: Файл змінювавÑÑ Ð¿Ñ–Ð·Ð½Ñ–ÑˆÐµ, ніж Ñ†Ñ ÐºÐ¾Ð¿Ñ–Ñ"
+252 "%s: захиÑÑ‚ від запиÑу недоÑтупний"
+253 "ЗапиÑ..."
+254 "%s: УВÐГÐ: файл обрізано"
+255 "Вже на першому тегу в цій групі"
+256 "%s: новий файл: %lu Ñ€Ñдків, %lu Ñимволів"
+257 "%s: %lu Ñ€Ñдків, %lu Ñимволів"
+258 "%s розширивÑÑ Ð² надто велику кількіÑÑ‚ÑŒ імен файлів"
+259 "%s: Ñпеціальний файл"
+260 "%s: не належить Вам"
+261 "%s: доÑтупний не лише Вам
+262 "Файл модифіковано піÑÐ»Ñ Ð¾Ñтанньої команди запиÑу: збережіть чи викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+263 "Файл модифіковано піÑÐ»Ñ Ð¾Ñтанньої команди запиÑу: збережіть чи викориÑтайте :edit Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+264 "Файл модифіковано піÑÐ»Ñ Ð¾Ñтанньої команди запиÑу: збережіть чи викориÑтайте ! Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ñƒ"
+265 "ТимчаÑовий файл: вихід зітре зміни"
+266 "Файл тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ, зміни не запишутьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾"
+267 "ЗапиÑи початі заново"
+268 "Підтверджуєте? [ynq]"
+269 "ÐатиÑніть ENTER Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ: "
+270 "ÐатиÑніть ENTER Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ [: Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… команд] "
+271 "ÐатиÑніть ENTER Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ [q Ð´Ð»Ñ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ]: "
+272 "Tака форма %s вимагає інтерфейÑу ex"
+273 "Входим в режим Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ ex"
+274 "Збій команди, файл не прочитано"
+275 "Продовжити?"
+276 "Ðеочікувана Ñимвольна подіÑ"
+277 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ ÐºÑ–Ð½Ñ†Ñ Ñ„Ð°Ð¹Ð»Ñƒ"
+278 "Ðемає Ñпівпадань за запитом"
+279 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ð¿ÐµÑ€ÐµÑ€Ð¸Ð²Ð°Ð½Ð½Ñ"
+280 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ"
+281 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ð¿ÐµÑ€ÐµÑ€Ð¸Ñовки"
+282 "Вже на оÑтанньму Тегу в цій групі"
+283 "Команда %s вимагає інтерфейÑу ex"
+284 "Tака форма %s не дозволÑєтьÑÑ Ð¿Ñ€Ð¸ вÑтановленій опції secure edit"
+285 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ñ€Ñдку"
+286 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ñ‚Ð°Ð¹Ð¼-ауту"
+287 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ð·Ð°Ð¿Ð¸Ñу"
+289 "Shell'івÑке Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð½Ðµ дозволÑєтьÑÑ Ð¿Ñ€Ð¸ вÑтановленій опції secure edit"
+290 "Команда %s не дозволÑєтьÑÑ Ð¿Ñ€Ð¸ вÑтановленій опції secure edit"
+291 "set: опцію %s неможна виÑтавити вимкненою"
+292 "Екран надто малий."
+293 "додано"
+294 "змінено"
+295 "Ñтерто"
+296 "об'єднано"
+297 "переміщено"
+298 "здвинуто"
+299 "вÑтавлено"
+300 "Ñ€Ñдок"
+301 "Ñ€Ñдків"
+302 "Vi завантажено без інтерпретатора Tcl"
+303 "Файл модифіковано піÑÐ»Ñ Ð¾Ñтанньої команди запиÑу."
+304 "Ðевдача shell'івÑького доповненнÑ"
+305 "Oпції Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ %s не вказано"
+306 "Vi завантажено без інтерпретатора Perl"
+307 "Ðемає команди ex Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ"
+308 "ÐатиÑніть ENTER щоб виконати команду, q щоб вийти"
+309 "Введіть 'cscope help' Ð´Ð»Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ—"
+310 "Ðемає cscope з'єднаннь"
+311 "%s: невідомий тип пошуку: викориÑтовуйте один з %s"
+312 "%d: немає такої ÑеÑÑ–Ñ— cscope"
+313 "set: опцію %s неможна виÑтавити увімкненою"
+314 "set: опцію %s неможна виÑтавити в 0"
+315 "%s: додано: %lu Ñ€Ñдків, %lu Ñимволів"
+316 "Ðеочікувана Ð¿Ð¾Ð´Ñ–Ñ Ð·Ð¼Ñ–Ð½Ð¸ розміру"
+317 "%d файлів Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ"
diff --git a/usr.bin/vi/catalog/zh_CN.UTF-8.base b/usr.bin/vi/catalog/zh_CN.UTF-8.base
new file mode 100644
index 000000000000..c51a7c373497
--- /dev/null
+++ b/usr.bin/vi/catalog/zh_CN.UTF-8.base
@@ -0,0 +1,311 @@
+002 "行长度溢出"
+003 "无法删除第 %lu 行"
+004 "无法å‘第 %lu 行追加"
+005 "无法å‘第 %lu è¡Œæ’å…¥"
+006 "无法存储第 %lu 行"
+007 "无法获得最åŽä¸€è¡Œ"
+008 "错误:无法获å–第 %lu è¡Œ"
+009 "日志文件"
+010 "日志未记录,无法撤销"
+011 "未åšä¿®æ”¹ï¼Œæ— æ³•æ’¤é”€"
+012 "日志未记录,无法撤销"
+013 "日志未记录,无法回滚"
+014 "未åšä¿®æ”¹ï¼Œæ— æ³•é‡åš"
+015 "%s/%d: 日志错误"
+016 "Vi 的标准输入和输出必须是终端"
+017 "标记 %s: 未设置"
+018 "标记 %s: 该行被删除"
+019 "标记 %s: 光标ä½ç½®ä¸å­˜åœ¨"
+020 "错误:"
+021 "新文件"
+022 "文件åå˜æ›´"
+023 "已修改"
+024 "未修改"
+025 "已解é”"
+026 "åªè¯»"
+027 "第 %lu è¡Œï¼å…± %lu è¡Œ [%ld%%]"
+028 "空文件"
+029 "第 %lu 行"
+030 "文件 %s ä¸æ˜¯æ¶ˆæ¯ç›®å½•"
+031 "无法设置选项 %s 的默认值"
+032 "用法 %s"
+033 "set: ä¸å­˜åœ¨é€‰é¡¹ %s;用 'set all' 查看所有选项的值"
+034 "set: 选项 [no]%s ä¸æŽ¥å—赋值"
+035 "set: 选项 %s ä¸æ˜¯å¼€å…³"
+036 "set: 选项 %s: %s"
+037 "set: 选项 %s: %s: 值溢出"
+038 "set: 选项 %s: %s 是一个éžæ³•æ•°å­—"
+039 "set: 选项 %s ä¸æ˜¯å¼€å…³"
+040 "å±å¹•å¤ªçª„,列宽å°äºŽ %d"
+041 "å±å¹•å¤ªå®½ï¼Œåˆ—宽大于 %d"
+042 "å±å¹•å¤ªçŸ®ï¼Œè¡Œé«˜å°äºŽ %d"
+043 "å±å¹•å¤ªé«˜ï¼Œè¡Œé«˜å¤§äºŽ %d"
+044 "lisp 选项未实现"
+045 "消æ¯æœªå…³é—­ï¼š%s"
+046 "消æ¯æœªæ‰“开:%s"
+047 "%s 选项必须æ¯ä¸¤ä¸ªå­—符一组"
+053 "默认缓冲区为空"
+054 "缓冲区 %s 为空"
+055 "文件å中有æ¢è¡Œçš„文件是无法æ¢å¤çš„"
+056 "一旦会è¯å¤±è´¥ï¼Œä¿®æ”¹æ— æ³•æ¢å¤"
+057 "正在备份文件……"
+058 "ä¿å­˜å¤±è´¥ï¼š%s"
+059 "一旦会è¯å¤±è´¥ï¼Œä¿®æ”¹æ— æ³•æ¢å¤"
+060 "文件备份失败:%s"
+061 "正在备份文件……"
+062 "ID 为 %u 的用户未找到"
+063 "无法给æ¢å¤æ–‡ä»¶åŠ é”"
+064 "æ¢å¤æ–‡ä»¶ç¼“冲区溢出"
+065 "æ¢å¤æ–‡ä»¶"
+066 "%s: æ¢å¤æ–‡ä»¶æ ¼å¼å¼‚常"
+067 "%s: æ¢å¤æ–‡ä»¶æ ¼å¼å¼‚常"
+068 "ä¸å­˜åœ¨å为 %s 的,å¯è¯»å¹¶éœ€è¦æ¢å¤çš„文件"
+069 "存在此文件的旧版本需è¦æ‚¨æ¢å¤"
+070 "存在其它需è¦æ‚¨æ¢å¤çš„文件"
+071 "邮件未å‘出:%s"
+072 "文件为空,无法æœç´¢"
+073 "到达文件尾,未找到模å¼"
+074 "没有上一个æœç´¢æ¨¡å¼"
+075 "模å¼æœªæ‰¾åˆ°"
+076 "到达文件头,未找到模å¼"
+077 "æœç´¢å›žè½¬"
+078 "正在æœç´¢â€¦â€¦"
+079 "未找到ä¸å¯æ‰“å°å­—符"
+080 "命令åä¸æ˜Ž"
+082 "%s: 命令在 ex 模å¼ä¸‹ä¸å¯ç”¨"
+083 "命令计数ä¸å¯ä¸º 0"
+084 "%s: 错误的行æè¿°"
+085 "内部语法表错误 (%s: %s)"
+086 "用法:%s"
+087 "%s: 临时缓冲区未释放"
+088 "修饰符å移é‡åœ¨ç¬¬ä¸€è¡Œä¹‹å‰"
+089 "修饰符å移é‡è¶…过最åŽä¸€è¡Œ"
+090 "文件ï¼å±å¹•æ”¹å˜æ—¶æœ‰å¸¦èŒƒå›´çš„ @ 命令正在è¿è¡Œ"
+091 "文件ï¼å±å¹•æ”¹å˜æ—¶æœ‰å…¨å±€å‘½ä»¤ï¼v 命令正在è¿è¡Œ"
+092 "Ex 命令失败:等待中的命令已丢弃"
+093 "Ex 命令失败:键映射已丢弃"
+094 "第二地å€å°äºŽç¬¬ä¸€åœ°å€"
+095 "未æ供标记å"
+096 "\\ 没有跟在 / 或 ? åŽé¢"
+097 "引用了å°äºŽ 0 çš„è¡Œå·"
+098 "%s 命令ä¸æ˜Ž"
+099 "地å€å€¼æº¢å‡º"
+100 "地å€å€¼ä¸‹æº¢"
+101 "éžæ³•çš„地å€ç»„åˆ"
+102 "éžæ³•åœ°å€ï¼šæ–‡ä»¶åªæœ‰ %lu è¡Œ"
+103 "éžæ³•åœ°å€ï¼šæ–‡ä»¶ä¸ºç©º"
+104 "命令 %s ä¸å…许地å€ä¸º 0"
+105 "没有å¯æ˜¾ç¤ºçš„缩写"
+106 "缩写必须以「å•è¯ã€å­—符结æŸ"
+107 "缩写ä¸èƒ½åŒ…å«åˆ¶è¡¨ç¬¦æˆ–空格"
+108 "缩写ä¸èƒ½åœ¨ç»“尾之外的地方混用å•è¯ï¼éžå•è¯å­—符"
+109 "\"%s\" ä¸æ˜¯ç¼©å†™"
+110 "Vi 命令失败:键映射已丢弃"
+111 "没有剩余的待编辑文件"
+112 "没有上一个待编辑文件"
+113 "没有上一个需é‡æ–°ç¼–辑的文件"
+114 "没有å¯æ˜¾ç¤ºçš„文件列表"
+115 "ç¼ºå°‘ç”¨äºŽæ›¿æ¢ \"!\" 的上一æ¡å‘½ä»¤"
+116 "ç¼ºå°‘ç”¨äºŽæ›¿æ¢ %% 的文件å"
+117 "ç¼ºå°‘ç”¨äºŽæ›¿æ¢ # 的文件å"
+118 "错误:execl: %s"
+119 "输入ï¼è¾“出错误:%s"
+120 "文件在上一次完整写入åŽè¢«ä¿®æ”¹ï¼›å†™å…¥æ–‡ä»¶ï¼Œæˆ–使用 ! 强制切æ¢ç›®å½•"
+121 "无法找到用户起始目录"
+122 "新的当å‰ç›®å½•ï¼š%s"
+123 "没有å¯æ˜¾ç¤ºçš„剪切缓冲区"
+124 "%s 命令ä¸èƒ½è¢«ç”¨ä½œå…¨å±€å‘½ä»¤æˆ– v 命令的一部分"
+125 "%s/%s: 未引入:ä¸å±žäºŽæ‚¨æˆ–根用户"
+126 "%s/%s: 未引入:ä¸å±žäºŽæ‚¨"
+127 "%s/%s: 未引入:å¯ä»¥è¢«æ–‡ä»¶å±žä¸»ä»¥å¤–的用户写入"
+128 "%s: 未引入:ä¸å±žäºŽæ‚¨æˆ–根用户"
+129 "%s: 未引入:ä¸å±žäºŽæ‚¨"
+130 "%s: 未引入:å¯ä»¥è¢«æ–‡ä»¶å±žä¸»ä»¥å¤–的用户写入"
+131 "缺少å¯ä»¥åˆå¹¶çš„è¡Œ"
+132 "缺少输入映射"
+133 "缺少命令映射"
+134 "%s 字符ä¸èƒ½è¢«é‡æ–°æ˜ å°„"
+135 "\"%s\" ç›®å‰æœªè¢«æ˜ å°„"
+136 "标记å必须是å•ä¸ªå­—符"
+137 "%s 已存在,未写入;用 ! 覆盖文件"
+138 "新建 exrc 文件:%s"
+139 "目标行在移动范围之内"
+140 "open è¦æ±‚å¼€å¯ open 选项"
+141 "open 命令未实现"
+142 "无法ä¿æŒæ­¤æ–‡ä»¶"
+143 "文件已ä¿æŒ"
+144 "%s: 展开的文件å过多"
+145 "åªèƒ½è¯»å–常规文件和具å管é“"
+146 "%s: 读é”ä¸å¯ç”¨"
+147 "正在读å–……"
+148 "%s: %lu 行,%lu 个字符"
+149 "没有å¯æ˜¾ç¤ºçš„åŽå°å±å¹•"
+150 "script 命令仅在 vi 模å¼ä¸‹å¯ç”¨"
+151 "没有è¦æ‰§è¡Œçš„命令"
+152 "shiftwidth 选项被设为 0"
+153 "命令计数溢出"
+154 "命令计数下溢"
+155 "正则表达å¼å·²æŒ‡å®šï¼›r 修饰符无效"
+156 "#, l å’Œ p 修饰符在 vi 模å¼ä¸‹ä¸èƒ½ä¸Ž c 修饰符组åˆ"
+157 "未找到匹é…"
+158 "没有上一次进入的 tag"
+159 "tags 栈上的记录少于 %s æ¡ï¼›ç”¨ :display t[ags] 显示它们"
+160 "tags 栈上ä¸å­˜åœ¨æ–‡ä»¶ %s,无法返回;用 :display t[ags] 查看"
+161 "按回车键继续:"
+162 "%s: tag 未找到"
+163 "%s: æŸåçš„ tag 在 %s 中"
+164 "%s: tag çš„è¡Œå·è¶…过了文件尾"
+165 "tags 栈为空"
+166 "%s: æœç´¢æ¨¡å¼æœªæ‰¾åˆ°"
+167 "还有 %d 个待编辑文件"
+168 "缓冲区 %s 为空"
+169 "确认修改?[n]"
+170 "已中断"
+171 "没有上一个å¯ä¾›æ‰§è¡Œçš„缓冲区"
+172 "没有上一æ¡æ­£åˆ™è¡¨è¾¾å¼"
+173 "%s è¦æ±‚存在一个已读入的文件"
+174 "用法:%s"
+175 "visual 命令è¦æ±‚å¼€å¯ open 选项"
+177 "空文件"
+178 "没有上一次 F, f, T 或 t æœç´¢"
+179 "%s 未找到"
+180 "没有上一个待编辑文件"
+181 "光标ä¸åœ¨æ•°å­—上"
+182 "结果数字过大"
+183 "结果数字过å°"
+184 "这一行上没有匹é…的字符"
+185 "匹é…字符未找到"
+186 "没有å¯æ›¿æ¢çš„字符"
+187 "没有其它å±å¹•å¯ä»¥åˆ‡æ¢"
+188 "在æœç´¢å­—符串ã€è¡Œå移é‡æˆ– z 命令之åŽæœ‰å¤šä½™å­—符"
+189 "没有上一个æœç´¢æ¨¡å¼"
+190 "æœç´¢å›žè½¬åˆ°äº†åˆå§‹ä½ç½®"
+191 "缩写展开超过é™åˆ¶ï¼šå­—符已丢弃"
+192 "éžæ³•å­—符;用引å·æ‹¬èµ·æ¥å†è¾“å…¥"
+193 "已到æ’入点的开始"
+194 "没有å¯æ“¦é™¤çš„剩余字符"
+195 "移动超过文件尾"
+196 "移动超过行末"
+197 "光标未移动"
+198 "已到文件头"
+199 "移动超过文件头"
+200 "å·²ä½äºŽç¬¬ä¸€åˆ—"
+201 "缓冲区应在命令å‰æŒ‡å®š"
+202 "已到文件尾"
+203 "已到行末"
+204 "%s ä¸æ˜¯ vi 命令"
+205 "用法 %s"
+206 "没有å¯åˆ é™¤çš„字符"
+207 "Q å‘½ä»¤éœ€è¦ ex 终端界é¢"
+208 "没有å¯é‡å¤çš„命令"
+209 "文件为空"
+210 "%s ä¸èƒ½è¢«ç”¨ä½œç§»åŠ¨å‘½ä»¤"
+211 "已处于命令模å¼"
+212 "光标ä¸åœ¨å•è¯ä¸Š"
+214 "窗å£é€‰é¡¹çš„值过大,最大值 %u"
+215 "追加"
+216 "修改"
+217 "命令"
+218 "æ’å…¥"
+219 "替æ¢"
+220 "移动超过å±å¹•ç»ˆç‚¹"
+221 "移动超过å±å¹•èµ·ç‚¹"
+222 "分å±éœ€è¦å¤šäºŽ %d è¡Œ"
+223 "没有åŽå°å±å¹•"
+224 "ä¸å­˜åœ¨æ­£åœ¨ç¼–辑文件 %s çš„åŽå°å±å¹•"
+225 "ä¸èƒ½æŠŠæ‚¨å”¯ä¸€çš„å±å¹•ç½®äºŽåŽå°"
+226 "å±å¹•åªèƒ½æ”¶ç¼©åˆ° %d è¡Œ"
+227 "å±å¹•ä¸èƒ½æ”¶ç¼©"
+228 "å±å¹•ä¸èƒ½å¢žé«˜"
+230 "ä¸èƒ½æŒ‚èµ·æ­¤å±å¹•"
+231 "已中断:键映射已丢弃"
+232 "vi: 临时缓冲区未释放"
+233 "此终端没有 %s 键"
+234 "åªèƒ½æŒ‡å®šä¸€ä¸ªç¼“冲区"
+235 "数字大于 %lu"
+236 "已中断"
+237 "无法创建临时文件"
+238 "警告:%s ä¸æ˜¯å¸¸è§„文件"
+239 "%s 已加é”,会è¯ä¸ºåªè¯»"
+240 "%s: 移除"
+241 "%s: 关闭"
+242 "%s: 移除"
+243 "%s: 移除"
+244 "åªè¯»æ–‡ä»¶ï¼Œæœªå†™å…¥ï¼›ç”¨ ! 强制写入"
+245 "åªè¯»æ–‡ä»¶ï¼Œæœªå†™å…¥"
+246 "%s 已存在,未写入;用 ! 覆盖文件"
+247 "%s 已存在,未写入"
+248 "是已存在文件的一部分,未写入;用 ! 强制写入"
+249 "是已存在文件的一部分,未写入"
+250 "%s: 文件被修改,新于当å‰æ‹·è´ï¼›ç”¨ ! 强制写入"
+251 "%s: 文件被修改,新于当å‰æ‹·è´"
+252 "%s: 写é”ä¸å¯ç”¨"
+253 "正在写入……"
+254 "%s: 警告:文件被截断"
+255 "å·²ä½äºŽè¿™ç»„ tags 中的第一个"
+256 "%s: 新文件:%lu 行,%lu 个字符"
+257 "%s: %lu 行,%lu 个字符"
+258 "%s: 展开的文件å过多"
+259 "%s: ä¸æ˜¯å¸¸è§„文件"
+260 "%s: ä¸å±žäºŽæ‚¨"
+261 "%s: å¯è¢«æ–‡ä»¶å±žä¸»ä»¥å¤–的用户访问"
+262 "文件在上一次完整写入åŽè¢«ä¿®æ”¹ï¼›å†™å…¥æ–‡ä»¶ï¼Œæˆ–使用 ! 强制载入"
+263 "文件在上一次完整写入åŽè¢«ä¿®æ”¹ï¼›å†™å…¥æ–‡ä»¶ï¼Œæˆ–使用 :edit! 强制编辑"
+264 "文件在上一次完整写入åŽè¢«ä¿®æ”¹ï¼›å†™å…¥æ–‡ä»¶ï¼Œæˆ–使用 ! 强制执行"
+265 "临时文件,退出将丢弃全部修改"
+266 "文件åªè¯»ï¼Œä¿®æ”¹æœªè¢«è‡ªåŠ¨å†™å…¥"
+267 "日志é‡å¯"
+268 "确认?[ynq]"
+269 "按任æ„键继续:"
+270 "按任æ„键继续[按 : 键输入 ex 命令]:"
+271 "按任æ„键继续[按 q 键推出]:"
+272 "该形å¼çš„ %s å‘½ä»¤éœ€è¦ ex 终端界é¢"
+273 "进入 ex 输入模å¼"
+274 "命令失败,尚未读入文件"
+275 " 继续?"
+276 "æ„外的字符事件"
+277 "以外的文件尾事件"
+278 "查询未找到匹é…"
+279 "æ„外的中断事件"
+280 "æ„外的退出事件"
+281 "æ„外的é‡ç»˜äº‹ä»¶"
+282 "å·²ä½äºŽè¿™ç»„ tags 中的最åŽä¸€ä¸ª"
+283 "%s å‘½ä»¤éœ€è¦ ex 终端界é¢"
+284 "secure 编辑选项开å¯æ—¶ä¸æ”¯æŒè¯¥å½¢å¼çš„ %s 命令"
+285 "æ„外的字符串事件"
+286 "æ„外的超时事件"
+287 "æ„外的写入事件"
+288 "分å±éœ€è¦å¤šäºŽ %d 列"
+289 "secure 编辑选项开å¯æ—¶ä¸æ”¯æŒ shell 展开"
+290 "secure 编辑选项开å¯æ—¶ä¸æ”¯æŒ %s 命令"
+291 "set: 选项 %s ä¸èƒ½å…³é—­"
+292 "显示空间太å°"
+293 "已添加"
+294 "已修改"
+295 "已删除"
+296 "å·²åˆå¹¶"
+297 "已移动"
+298 "å·²å移"
+299 "å·²å¤åˆ¶"
+300 "行"
+301 "行"
+303 "文件在上一次写入åŽè¢«ä¿®æ”¹"
+304 "Shell 展开失败"
+305 "未指定 %s 编辑选项"
+307 "没有è¦æ‰§è¡Œçš„ ex 命令"
+308 "键入回车执行一æ¡å‘½ä»¤ï¼Œ:q 退出"
+309 "使用 \"cscope help\" 查看帮助"
+310 "没有正在è¿è¡Œçš„ cscope 连接"
+311 "%s: æœç´¢ç±»åž‹ä¸æ˜Žï¼šä½¿ç”¨ %s 中的一个"
+312 "%d: æ— æ­¤ cscope 会è¯"
+313 "set: 选项 %s ç»å¯¹ä¸èƒ½å¼€å¯"
+314 "set: 选项 %s ç»å¯¹ä¸èƒ½è¢«è®¾ä¸º 0"
+315 "%s: 已追加:%lu 行,%lu 个字符"
+316 "æ„外的大å°è°ƒæ•´äº‹ä»¶"
+317 "%d 个待编辑的文件"
+319 "%d 个åŽå°å±å¹•ï¼›ç”¨ :display 列出它们"
+320 "光标ä½ç½®ä¸æ˜Ž"
+321 "ä¸æ”¯æŒæ–‡ä»¶ç¼–ç è½¬æ¢"
+322 "ä¸æ”¯æŒè¾“入编ç è½¬æ¢"
+323 "无效输入,已截断"
+324 "第 %d 行上有转æ¢é”™è¯¯"
diff --git a/usr.bin/vi/config.h b/usr.bin/vi/config.h
new file mode 100644
index 000000000000..8041fb76dce9
--- /dev/null
+++ b/usr.bin/vi/config.h
@@ -0,0 +1,27 @@
+
+/* Define when using wide characters */
+#define USE_WIDECHAR
+
+/* Define when iconv can be used */
+/* #undef USE_ICONV */
+
+/* Define when the 2nd argument of iconv(3) is not const */
+/* #undef ICONV_TRADITIONAL */
+
+/* Define if you have <libutil.h> */
+#define HAVE_LIBUTIL_H
+
+/* Define if you have <ncurses.h> */
+#define HAVE_NCURSES_H
+
+/* Define if you have <ncursesw/ncurses.h> */
+/* #undef HAVE_NCURSESW_NCURSES_H */
+
+/* Define if you have <pty.h> */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have <term.h> */
+#define HAVE_TERM_H
+
+/* Define if struct dirent has field d_namlen */
+#define HAVE_DIRENT_D_NAMLEN
diff --git a/usr.bin/vi/ex/version.h b/usr.bin/vi/ex/version.h
new file mode 100644
index 000000000000..1c18911cc593
--- /dev/null
+++ b/usr.bin/vi/ex/version.h
@@ -0,0 +1 @@
+#define VI_VERSION "2.2.1 (2023-09-25)"
diff --git a/usr.bin/vi/ex_def.h b/usr.bin/vi/ex_def.h
new file mode 100644
index 000000000000..7afb7b19d677
--- /dev/null
+++ b/usr.bin/vi/ex_def.h
@@ -0,0 +1,76 @@
+#define C_SCROLL 0
+#define C_BANG 1
+#define C_HASH 2
+#define C_SUBAGAIN 3
+#define C_STAR 4
+#define C_SHIFTL 5
+#define C_EQUAL 6
+#define C_SHIFTR 7
+#define C_AT 8
+#define C_APPEND 9
+#define C_ABBR 10
+#define C_ARGS 11
+#define C_BG 12
+#define C_CHANGE 13
+#define C_CD 14
+#define C_CHDIR 15
+#define C_COPY 16
+#define C_CSCOPE 17
+#define C_DELETE 18
+#define C_DISPLAY 19
+#define C_EDIT 20
+#define C_EX 21
+#define C_EXUSAGE 22
+#define C_FILE 23
+#define C_FG 24
+#define C_GLOBAL 25
+#define C_HELP 26
+#define C_INSERT 27
+#define C_JOIN 28
+#define C_K 29
+#define C_LIST 30
+#define C_MOVE 31
+#define C_MARK 32
+#define C_MAP 33
+#define C_MKEXRC 34
+#define C_NEXT 35
+#define C_NUMBER 36
+#define C_OPEN 37
+#define C_PRINT 38
+#define C_PRESERVE 39
+#define C_PREVIOUS 40
+#define C_PUT 41
+#define C_QUIT 42
+#define C_READ 43
+#define C_RECOVER 44
+#define C_RESIZE 45
+#define C_REWIND 46
+#define C_SUBSTITUTE 47
+#define C_SCRIPT 48
+#define C_SET 49
+#define C_SHELL 50
+#define C_SOURCE 51
+#define C_STOP 52
+#define C_SUSPEND 53
+#define C_T 54
+#define C_TAG 55
+#define C_TAGNEXT 56
+#define C_TAGPOP 57
+#define C_TAGPREV 58
+#define C_TAGTOP 59
+#define C_UNDO 60
+#define C_UNABBREVIATE 61
+#define C_UNMAP 62
+#define C_V 63
+#define C_VERSION 64
+#define C_VISUAL_EX 65
+#define C_VISUAL_VI 66
+#define C_VIUSAGE 67
+#define C_VSPLIT 68
+#define C_WRITE 69
+#define C_WN 70
+#define C_WQ 71
+#define C_XIT 72
+#define C_YANK 73
+#define C_Z 74
+#define C_SUBTILDE 75
diff --git a/usr.bin/vi/extern.h b/usr.bin/vi/extern.h
new file mode 100644
index 000000000000..1252726d9d8b
--- /dev/null
+++ b/usr.bin/vi/extern.h
@@ -0,0 +1,444 @@
+#ifdef CL_IN_EX /* cl.h */
+int cl_waddstr(SCR *, const CHAR_T *, size_t);
+int cl_addstr(SCR *, const char *, size_t);
+int cl_attr(SCR *, scr_attr_t, int);
+int cl_baud(SCR *, u_long *);
+int cl_bell(SCR *);
+int cl_clrtoeol(SCR *);
+int cl_cursor(SCR *, size_t *, size_t *);
+int cl_deleteln(SCR *);
+int cl_discard(SCR *, SCR **);
+int cl_ex_adjust(SCR *, exadj_t);
+int cl_insertln(SCR *);
+int cl_keyval(SCR *, scr_keyval_t, CHAR_T *, int *);
+int cl_move(SCR *, size_t, size_t);
+int cl_refresh(SCR *, int);
+int cl_rename(SCR *, char *, int);
+void cl_setname(GS *, char *);
+int cl_split(SCR *, SCR *);
+int cl_suspend(SCR *, int *);
+void cl_usage(void);
+int sig_init(GS *, SCR *);
+int cl_event(SCR *, EVENT *, u_int32_t, int);
+int cl_screen(SCR *, u_int32_t);
+int cl_quit(GS *);
+int cl_getcap(SCR *, char *, char **);
+int cl_term_init(SCR *);
+int cl_term_end(GS *);
+int cl_fmap(SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t);
+int cl_optchange(SCR *, int, char *, u_long *);
+int cl_omesg(SCR *, CL_PRIVATE *, int);
+int cl_ssize(SCR *, int, size_t *, size_t *, int *);
+int cl_putchar(int);
+#endif
+#ifdef EXP /* ex.h */
+int ex(SCR **);
+int ex_cmd(SCR *);
+int ex_range(SCR *, EXCMD *, int *);
+int ex_is_abbrev(CHAR_T *, size_t);
+int ex_is_unmap(CHAR_T *, size_t);
+void ex_badaddr
+ (SCR *, EXCMDLIST const *, enum badaddr, enum nresult);
+int ex_abbr(SCR *, EXCMD *);
+int ex_unabbr(SCR *, EXCMD *);
+int ex_append(SCR *, EXCMD *);
+int ex_change(SCR *, EXCMD *);
+int ex_insert(SCR *, EXCMD *);
+int ex_next(SCR *, EXCMD *);
+int ex_prev(SCR *, EXCMD *);
+int ex_rew(SCR *, EXCMD *);
+int ex_args(SCR *, EXCMD *);
+char **ex_buildargv(SCR *, EXCMD *, char *);
+int argv_init(SCR *, EXCMD *);
+int argv_exp0(SCR *, EXCMD *, CHAR_T *, size_t);
+int argv_exp1(SCR *, EXCMD *, CHAR_T *, size_t, int);
+int argv_exp2(SCR *, EXCMD *, CHAR_T *, size_t);
+int argv_exp3(SCR *, EXCMD *, CHAR_T *, size_t);
+int argv_flt_ex(SCR *, EXCMD *, CHAR_T *, size_t);
+int argv_free(SCR *);
+int argv_flt_path(SCR *, EXCMD *, CHAR_T *, size_t);
+CHAR_T *argv_esc(SCR *, EXCMD *, CHAR_T *, size_t);
+CHAR_T *argv_uesc(SCR *, EXCMD *, CHAR_T *, size_t);
+int ex_at(SCR *, EXCMD *);
+int ex_bang(SCR *, EXCMD *);
+int ex_cd(SCR *, EXCMD *);
+int ex_cscope(SCR *, EXCMD *);
+int cscope_end(SCR *);
+int cscope_display(SCR *);
+int cscope_search(SCR *, TAGQ *, TAG *);
+int ex_delete(SCR *, EXCMD *);
+int ex_display(SCR *, EXCMD *);
+int ex_edit(SCR *, EXCMD *);
+int ex_equal(SCR *, EXCMD *);
+int ex_file(SCR *, EXCMD *);
+int ex_filter(SCR *,
+ EXCMD *, MARK *, MARK *, MARK *, CHAR_T *, enum filtertype);
+int ex_global(SCR *, EXCMD *);
+int ex_v(SCR *, EXCMD *);
+int ex_g_insdel(SCR *, lnop_t, recno_t);
+int ex_screen_copy(SCR *, SCR *);
+int ex_screen_end(SCR *);
+int ex_optchange(SCR *, int, char *, u_long *);
+int ex_exrc(SCR *);
+int ex_run_str(SCR *, char *, CHAR_T *, size_t, int, int);
+int ex_join(SCR *, EXCMD *);
+int ex_map(SCR *, EXCMD *);
+int ex_unmap(SCR *, EXCMD *);
+int ex_mark(SCR *, EXCMD *);
+int ex_mkexrc(SCR *, EXCMD *);
+int ex_copy(SCR *, EXCMD *);
+int ex_move(SCR *, EXCMD *);
+int ex_open(SCR *, EXCMD *);
+int ex_preserve(SCR *, EXCMD *);
+int ex_recover(SCR *, EXCMD *);
+int ex_list(SCR *, EXCMD *);
+int ex_number(SCR *, EXCMD *);
+int ex_pr(SCR *, EXCMD *);
+int ex_print(SCR *, EXCMD *, MARK *, MARK *, u_int32_t);
+int ex_ldisplay(SCR *, const CHAR_T *, size_t, size_t, u_int);
+int ex_scprint(SCR *, MARK *, MARK *);
+int ex_printf(SCR *, const char *, ...);
+int ex_puts(SCR *, const char *);
+int ex_fflush(SCR *sp);
+int ex_put(SCR *, EXCMD *);
+int ex_quit(SCR *, EXCMD *);
+int ex_read(SCR *, EXCMD *);
+int ex_readfp(SCR *, char *, FILE *, MARK *, recno_t *, int);
+int ex_bg(SCR *, EXCMD *);
+int ex_fg(SCR *, EXCMD *);
+int ex_resize(SCR *, EXCMD *);
+int ex_sdisplay(SCR *);
+int ex_script(SCR *, EXCMD *);
+int sscr_exec(SCR *, recno_t);
+int sscr_input(SCR *);
+int sscr_end(SCR *);
+int ex_set(SCR *, EXCMD *);
+int ex_shell(SCR *, EXCMD *);
+int ex_exec_proc(SCR *, EXCMD *, char *, const char *, int);
+int proc_wait(SCR *, long, const char *, int, int);
+int ex_shiftl(SCR *, EXCMD *);
+int ex_shiftr(SCR *, EXCMD *);
+int ex_retab(SCR *, EXCMD *);
+int ex_source(SCR *, EXCMD *);
+int ex_stop(SCR *, EXCMD *);
+int ex_s(SCR *, EXCMD *);
+int ex_subagain(SCR *, EXCMD *);
+int ex_subtilde(SCR *, EXCMD *);
+int re_compile(SCR *,
+ CHAR_T *, size_t, CHAR_T **, size_t *, regex_t *, u_int);
+void re_error(SCR *, int, regex_t *);
+int ex_tag_first(SCR *, CHAR_T *);
+int ex_tag_push(SCR *, EXCMD *);
+int ex_tag_next(SCR *, EXCMD *);
+int ex_tag_prev(SCR *, EXCMD *);
+int ex_tag_nswitch(SCR *, TAG *, int);
+int ex_tag_Nswitch(SCR *, TAG *, int);
+int ex_tag_pop(SCR *, EXCMD *);
+int ex_tag_top(SCR *, EXCMD *);
+int ex_tag_display(SCR *);
+int ex_tag_copy(SCR *, SCR *);
+int tagq_free(SCR *, TAGQ *);
+int tagq_push(SCR*, TAGQ*, int, int );
+void tag_msg(SCR *, tagmsg_t, char *);
+int ex_tagf_alloc(SCR *, char *);
+int ex_tag_free(SCR *);
+int ex_txt(SCR *, TEXTH *, ARG_CHAR_T, u_int32_t);
+int ex_undo(SCR *, EXCMD *);
+int ex_help(SCR *, EXCMD *);
+int ex_usage(SCR *, EXCMD *);
+int ex_viusage(SCR *, EXCMD *);
+void ex_cinit(SCR *, EXCMD *, int, int, recno_t, recno_t, int);
+int ex_getline(SCR *, FILE *, size_t *);
+int ex_ncheck(SCR *, int);
+int ex_init(SCR *);
+void ex_wemsg(SCR *, CHAR_T *, exm_t);
+void ex_emsg(SCR *, char *, exm_t);
+int ex_version(SCR *, EXCMD *);
+int ex_visual(SCR *, EXCMD *);
+int ex_wn(SCR *, EXCMD *);
+int ex_wq(SCR *, EXCMD *);
+int ex_write(SCR *, EXCMD *);
+int ex_xit(SCR *, EXCMD *);
+int ex_writefp(SCR *,
+ char *, FILE *, MARK *, MARK *, u_long *, u_long *, int);
+int ex_yank(SCR *, EXCMD *);
+int ex_z(SCR *, EXCMD *);
+#endif
+#ifdef V_ABS /* vi.h */
+int cs_init(SCR *, VCS *);
+int cs_next(SCR *, VCS *);
+int cs_fspace(SCR *, VCS *);
+int cs_fblank(SCR *, VCS *);
+int cs_prev(SCR *, VCS *);
+int cs_bblank(SCR *, VCS *);
+int v_at(SCR *, VICMD *);
+int v_chrepeat(SCR *, VICMD *);
+int v_chrrepeat(SCR *, VICMD *);
+int v_cht(SCR *, VICMD *);
+int v_chf(SCR *, VICMD *);
+int v_chT(SCR *, VICMD *);
+int v_chF(SCR *, VICMD *);
+int v_delete(SCR *, VICMD *);
+int v_again(SCR *, VICMD *);
+int v_exmode(SCR *, VICMD *);
+int v_join(SCR *, VICMD *);
+int v_shiftl(SCR *, VICMD *);
+int v_shiftr(SCR *, VICMD *);
+int v_suspend(SCR *, VICMD *);
+int v_switch(SCR *, VICMD *);
+int v_tagpush(SCR *, VICMD *);
+int v_tagpop(SCR *, VICMD *);
+int v_filter(SCR *, VICMD *);
+int v_ex(SCR *, VICMD *);
+int v_ecl_exec(SCR *);
+int v_increment(SCR *, VICMD *);
+int v_screen_copy(SCR *, SCR *);
+int v_screen_end(SCR *);
+int v_optchange(SCR *, int, char *, u_long *);
+int v_iA(SCR *, VICMD *);
+int v_ia(SCR *, VICMD *);
+int v_iI(SCR *, VICMD *);
+int v_ii(SCR *, VICMD *);
+int v_iO(SCR *, VICMD *);
+int v_io(SCR *, VICMD *);
+int v_change(SCR *, VICMD *);
+int v_Replace(SCR *, VICMD *);
+int v_subst(SCR *, VICMD *);
+int v_left(SCR *, VICMD *);
+int v_cfirst(SCR *, VICMD *);
+int v_first(SCR *, VICMD *);
+int v_ncol(SCR *, VICMD *);
+int v_zero(SCR *, VICMD *);
+int v_mark(SCR *, VICMD *);
+int v_bmark(SCR *, VICMD *);
+int v_fmark(SCR *, VICMD *);
+int v_emark(SCR *, VICMD *);
+int v_match(SCR *, VICMD *);
+int v_buildmcs(SCR *, char *);
+int v_paragraphf(SCR *, VICMD *);
+int v_paragraphb(SCR *, VICMD *);
+int v_buildps(SCR *, char *, char *);
+int v_Put(SCR *, VICMD *);
+int v_put(SCR *, VICMD *);
+int v_redraw(SCR *, VICMD *);
+int v_replace(SCR *, VICMD *);
+int v_right(SCR *, VICMD *);
+int v_dollar(SCR *, VICMD *);
+int v_screen(SCR *, VICMD *);
+int v_lgoto(SCR *, VICMD *);
+int v_home(SCR *, VICMD *);
+int v_middle(SCR *, VICMD *);
+int v_bottom(SCR *, VICMD *);
+int v_up(SCR *, VICMD *);
+int v_cr(SCR *, VICMD *);
+int v_down(SCR *, VICMD *);
+int v_hpageup(SCR *, VICMD *);
+int v_hpagedown(SCR *, VICMD *);
+int v_pagedown(SCR *, VICMD *);
+int v_pageup(SCR *, VICMD *);
+int v_lineup(SCR *, VICMD *);
+int v_linedown(SCR *, VICMD *);
+int v_searchb(SCR *, VICMD *);
+int v_searchf(SCR *, VICMD *);
+int v_searchN(SCR *, VICMD *);
+int v_searchn(SCR *, VICMD *);
+int v_searchw(SCR *, VICMD *);
+int v_correct(SCR *, VICMD *, int);
+int v_sectionf(SCR *, VICMD *);
+int v_sectionb(SCR *, VICMD *);
+int v_sentencef(SCR *, VICMD *);
+int v_sentenceb(SCR *, VICMD *);
+int v_status(SCR *, VICMD *);
+int v_tcmd(SCR *, VICMD *, ARG_CHAR_T, u_int);
+int v_txt(SCR *, VICMD *, MARK *,
+ const CHAR_T *, size_t, ARG_CHAR_T, recno_t, u_long, u_int32_t);
+int v_txt_auto(SCR *, recno_t, TEXT *, size_t, TEXT *);
+int v_ulcase(SCR *, VICMD *);
+int v_mulcase(SCR *, VICMD *);
+int v_Undo(SCR *, VICMD *);
+int v_undo(SCR *, VICMD *);
+void v_eof(SCR *, MARK *);
+void v_eol(SCR *, MARK *);
+void v_nomove(SCR *);
+void v_sof(SCR *, MARK *);
+void v_sol(SCR *);
+int v_isempty(CHAR_T *, size_t);
+void v_emsg(SCR *, char *, vim_t);
+int v_wordW(SCR *, VICMD *);
+int v_wordw(SCR *, VICMD *);
+int v_wordE(SCR *, VICMD *);
+int v_worde(SCR *, VICMD *);
+int v_wordB(SCR *, VICMD *);
+int v_wordb(SCR *, VICMD *);
+int v_xchar(SCR *, VICMD *);
+int v_Xchar(SCR *, VICMD *);
+int v_yank(SCR *, VICMD *);
+int v_z(SCR *, VICMD *);
+int vs_crel(SCR *, long);
+int v_zexit(SCR *, VICMD *);
+int vi(SCR **);
+int v_curword(SCR *);
+int vs_line(SCR *, SMAP *, size_t *, size_t *);
+int vs_number(SCR *);
+void vs_busy(SCR *, const char *, busy_t);
+void vs_home(SCR *);
+void vs_update(SCR *, const char *, const CHAR_T *);
+void vs_msg(SCR *, mtype_t, char *, size_t);
+int vs_ex_resolve(SCR *, int *);
+int vs_resolve(SCR *, SCR *, int);
+int vs_repaint(SCR *, EVENT *);
+int vs_refresh(SCR *, int);
+int vs_column(SCR *, size_t *);
+size_t vs_screens(SCR *, recno_t, size_t *);
+size_t vs_columns(SCR *, CHAR_T *, recno_t, size_t *, size_t *);
+size_t vs_rcm(SCR *, recno_t, int);
+size_t vs_colpos(SCR *, recno_t, size_t);
+int vs_change(SCR *, recno_t, lnop_t);
+int vs_sm_fill(SCR *, recno_t, pos_t);
+int vs_sm_scroll(SCR *, MARK *, recno_t, scroll_t);
+int vs_sm_1up(SCR *);
+int vs_sm_1down(SCR *);
+int vs_sm_next(SCR *, SMAP *, SMAP *);
+int vs_sm_prev(SCR *, SMAP *, SMAP *);
+int vs_sm_cursor(SCR *, SMAP **);
+int vs_sm_position(SCR *, MARK *, u_long, pos_t);
+recno_t vs_sm_nlines(SCR *, SMAP *, recno_t, size_t);
+int vs_split(SCR *, SCR *, int);
+int vs_vsplit(SCR *, SCR *);
+int vs_discard(SCR *, SCR **);
+int vs_fg(SCR *, SCR **, CHAR_T *, int);
+int vs_bg(SCR *);
+int vs_swap(SCR *, SCR **, char *);
+int vs_resize(SCR *, long, adj_t);
+#endif /* common.h */
+char * codeset(void);
+void conv_init(SCR *, SCR *);
+int conv_enc(SCR *, int, char *);
+void conv_end(SCR *);
+int cut(SCR *, CHAR_T *, MARK *, MARK *, int);
+int cut_line(SCR *, recno_t, size_t, size_t, CB *);
+void cut_close(GS *);
+TEXT *text_init(SCR *, const CHAR_T *, size_t, size_t);
+void text_lfree(TEXTH *);
+void text_free(TEXT *);
+int del(SCR *, MARK *, MARK *, int);
+int looks_utf8(const char *, size_t);
+int looks_utf16(const char *, size_t);
+int decode_utf8(const char *);
+int decode_utf16(const char *, int);
+FREF *file_add(SCR *, char *);
+int file_init(SCR *, FREF *, char *, int);
+int file_end(SCR *, EXF *, int);
+int file_write(SCR *, MARK *, MARK *, char *, int);
+int file_m1(SCR *, int, int);
+int file_m2(SCR *, int);
+int file_m3(SCR *, int);
+int file_aw(SCR *, int);
+void set_alt_name(SCR *, char *);
+lockr_t file_lock(SCR *, char *, int, int);
+int v_key_init(SCR *);
+void v_key_ilookup(SCR *);
+size_t v_key_len(SCR *, ARG_CHAR_T);
+char *v_key_name(SCR *, ARG_CHAR_T);
+e_key_t v_key_val(SCR *, ARG_CHAR_T);
+int v_event_push(SCR *, EVENT *, CHAR_T *, size_t, u_int);
+int v_event_get(SCR *, EVENT *, int, u_int32_t);
+void v_event_err(SCR *, EVENT *);
+int v_event_flush(SCR *, u_int);
+int db_eget(SCR *, recno_t, CHAR_T **, size_t *, int *);
+int db_get(SCR *, recno_t, u_int32_t, CHAR_T **, size_t *);
+int db_delete(SCR *, recno_t);
+int db_append(SCR *, int, recno_t, CHAR_T *, size_t);
+int db_insert(SCR *, recno_t, CHAR_T *, size_t);
+int db_set(SCR *, recno_t, CHAR_T *, size_t);
+int db_exist(SCR *, recno_t);
+int db_last(SCR *, recno_t *);
+int db_rget(SCR *, recno_t, char **, size_t *);
+int db_rset(SCR *, recno_t, char *, size_t);
+void db_err(SCR *, recno_t);
+int log_init(SCR *, EXF *);
+int log_end(SCR *, EXF *);
+int log_cursor(SCR *);
+int log_line(SCR *, recno_t, u_int);
+int log_mark(SCR *, LMARK *);
+int log_backward(SCR *, MARK *);
+int log_setline(SCR *);
+int log_forward(SCR *, MARK *);
+int editor(GS *, int, char *[]);
+void v_end(GS *);
+int mark_init(SCR *, EXF *);
+int mark_end(SCR *, EXF *);
+int mark_get(SCR *, ARG_CHAR_T, MARK *, mtype_t);
+int mark_set(SCR *, ARG_CHAR_T, MARK *, int);
+int mark_insdel(SCR *, lnop_t, recno_t);
+void msgq(SCR *, mtype_t, const char *, ...);
+void msgq_wstr(SCR *, mtype_t, const CHAR_T *, const char *);
+void msgq_str(SCR *, mtype_t, const char *, const char *);
+void mod_rpt(SCR *);
+void msgq_status(SCR *, recno_t, u_int);
+int msg_open(SCR *, char *);
+void msg_close(GS *);
+const char *msg_cmsg(SCR *, cmsg_t, size_t *);
+const char *msg_cat(SCR *, const char *, size_t *);
+char *msg_print(SCR *, const char *, int *);
+int opts_init(SCR *, int *);
+int opts_set(SCR *, ARGS *[], char *);
+int o_set(SCR *, int, u_int, char *, u_long);
+int opts_empty(SCR *, int, int);
+void opts_dump(SCR *, enum optdisp);
+int opts_save(SCR *, FILE *);
+OPTLIST const *opts_search(CHAR_T *);
+void opts_nomatch(SCR *, CHAR_T *);
+int opts_copy(SCR *, SCR *);
+void opts_free(SCR *);
+int f_altwerase(SCR *, OPTION *, char *, u_long *);
+int f_columns(SCR *, OPTION *, char *, u_long *);
+int f_lines(SCR *, OPTION *, char *, u_long *);
+int f_lisp(SCR *, OPTION *, char *, u_long *);
+int f_msgcat(SCR *, OPTION *, char *, u_long *);
+int f_print(SCR *, OPTION *, char *, u_long *);
+int f_readonly(SCR *, OPTION *, char *, u_long *);
+int f_recompile(SCR *, OPTION *, char *, u_long *);
+int f_reformat(SCR *, OPTION *, char *, u_long *);
+int f_ttywerase(SCR *, OPTION *, char *, u_long *);
+int f_w300(SCR *, OPTION *, char *, u_long *);
+int f_w1200(SCR *, OPTION *, char *, u_long *);
+int f_w9600(SCR *, OPTION *, char *, u_long *);
+int f_window(SCR *, OPTION *, char *, u_long *);
+int f_encoding(SCR *, OPTION *, char *, u_long *);
+int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int);
+int rcv_tmp(SCR *, EXF *, char *);
+int rcv_init(SCR *);
+int rcv_sync(SCR *, u_int);
+int rcv_list(SCR *);
+int rcv_read(SCR *, FREF *);
+int screen_init(GS *, SCR *, SCR **);
+int screen_end(SCR *);
+SCR *screen_next(SCR *);
+int f_search(SCR *,
+ MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int);
+int b_search(SCR *,
+ MARK *, MARK *, CHAR_T *, size_t, CHAR_T **, u_int);
+void search_busy(SCR *, busy_t);
+int seq_set(SCR *, CHAR_T *,
+ size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int);
+int seq_delete(SCR *, CHAR_T *, size_t, seq_t);
+int seq_free(SEQ *);
+SEQ *seq_find
+ (SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *);
+void seq_close(GS *);
+int seq_dump(SCR *, seq_t, int);
+int seq_save(SCR *, FILE *, char *, seq_t);
+int e_memcmp(CHAR_T *, EVENT *, size_t);
+void *binc(SCR *, void *, size_t *, size_t);
+int nonblank(SCR *, recno_t, size_t *);
+char *join(char *, char *);
+char *expanduser(char *);
+char *quote(char *);
+char *v_strdup(SCR *, const char *, size_t);
+CHAR_T *v_wstrdup(SCR *, const CHAR_T *, size_t);
+enum nresult nget_uslong(u_long *, const CHAR_T *, CHAR_T **, int);
+enum nresult nget_slong(long *, const CHAR_T *, CHAR_T **, int);
+void timepoint_steady(struct timespec *);
+void timepoint_system(struct timespec *);
+void TRACE(SCR *, const char *, ...);
diff --git a/usr.bin/vi/options_def.h b/usr.bin/vi/options_def.h
new file mode 100644
index 000000000000..15104845c380
--- /dev/null
+++ b/usr.bin/vi/options_def.h
@@ -0,0 +1,86 @@
+#define O_ALTNOTATION 0
+#define O_ALTWERASE 1
+#define O_AUTOINDENT 2
+#define O_AUTOPRINT 3
+#define O_AUTOWRITE 4
+#define O_BACKUP 5
+#define O_BEAUTIFY 6
+#define O_CDPATH 7
+#define O_CEDIT 8
+#define O_COLUMNS 9
+#define O_COMBINED 10
+#define O_COMMENT 11
+#define O_TMPDIR 12
+#define O_EDCOMPATIBLE 13
+#define O_ERRORBELLS 14
+#define O_ESCAPETIME 15
+#define O_EXPANDTAB 16
+#define O_EXRC 17
+#define O_EXTENDED 18
+#define O_FILEC 19
+#define O_FILEENCODING 20
+#define O_FLASH 21
+#define O_HARDTABS 22
+#define O_ICLOWER 23
+#define O_IGNORECASE 24
+#define O_INPUTENCODING 25
+#define O_KEYTIME 26
+#define O_LEFTRIGHT 27
+#define O_LINES 28
+#define O_LISP 29
+#define O_LIST 30
+#define O_LOCKFILES 31
+#define O_MAGIC 32
+#define O_MATCHCHARS 33
+#define O_MATCHTIME 34
+#define O_MESG 35
+#define O_MODELINE 36
+#define O_MSGCAT 37
+#define O_NOPRINT 38
+#define O_NUMBER 39
+#define O_OCTAL 40
+#define O_OPEN 41
+#define O_OPTIMIZE 42
+#define O_PARAGRAPHS 43
+#define O_PATH 44
+#define O_PRINT 45
+#define O_PROMPT 46
+#define O_READONLY 47
+#define O_RECDIR 48
+#define O_REDRAW 49
+#define O_REMAP 50
+#define O_REPORT 51
+#define O_RULER 52
+#define O_SCROLL 53
+#define O_SEARCHINCR 54
+#define O_SECTIONS 55
+#define O_SECURE 56
+#define O_SHELL 57
+#define O_SHELLMETA 58
+#define O_SHIFTWIDTH 59
+#define O_SHOWFILENAME 60
+#define O_SHOWMATCH 61
+#define O_SHOWMODE 62
+#define O_SIDESCROLL 63
+#define O_SLOWOPEN 64
+#define O_SOURCEANY 65
+#define O_TABSTOP 66
+#define O_TAGLENGTH 67
+#define O_TAGS 68
+#define O_TERM 69
+#define O_TERSE 70
+#define O_TILDEOP 71
+#define O_TIMEOUT 72
+#define O_TTYWERASE 73
+#define O_VERBOSE 74
+#define O_W1200 75
+#define O_W300 76
+#define O_W9600 77
+#define O_WARN 78
+#define O_WINDOW 79
+#define O_WINDOWNAME 80
+#define O_WRAPLEN 81
+#define O_WRAPMARGIN 82
+#define O_WRAPSCAN 83
+#define O_WRITEANY 84
+#define O_OPTIONCOUNT 85
diff --git a/usr.bin/vi/pathnames.h b/usr.bin/vi/pathnames.h
new file mode 100644
index 000000000000..f1c706f5ecbd
--- /dev/null
+++ b/usr.bin/vi/pathnames.h
@@ -0,0 +1,26 @@
+
+/* Read standard system paths first. */
+#include <paths.h>
+
+#ifndef _PATH_EXRC
+#define _PATH_EXRC ".exrc"
+#endif
+
+#ifndef _PATH_MSGCAT
+#define _PATH_MSGCAT "/usr/share/vi/catalog/"
+#endif
+
+#ifndef _PATH_NEXRC
+#define _PATH_NEXRC ".nexrc"
+#endif
+
+/* On linux _PATH_PRESERVE is only writable by root */
+#define NVI_PATH_PRESERVE "/var/tmp/vi.recover/"
+
+#ifndef _PATH_SYSEXRC
+#define _PATH_SYSEXRC "/etc/vi.exrc"
+#endif
+
+#ifndef _PATH_TAGS
+#define _PATH_TAGS "tags"
+#endif
diff --git a/usr.bin/vis/Makefile b/usr.bin/vis/Makefile
new file mode 100644
index 000000000000..ad60828bad90
--- /dev/null
+++ b/usr.bin/vis/Makefile
@@ -0,0 +1,7 @@
+PROG= vis
+SRCS= vis.c foldit.c
+
+.PATH: ${SRCTOP}/contrib/vis
+CFLAGS+= -I${SRCTOP}/contrib/vis
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vis/Makefile.depend b/usr.bin/vis/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/vis/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vmstat/Makefile b/usr.bin/vmstat/Makefile
new file mode 100644
index 000000000000..6efbb186f43a
--- /dev/null
+++ b/usr.bin/vmstat/Makefile
@@ -0,0 +1,10 @@
+.include <src.opts.mk>
+
+PROG= vmstat
+MAN= vmstat.8
+LIBADD= devstat kvm memstat xo util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vmstat/Makefile.depend b/usr.bin/vmstat/Makefile.depend
new file mode 100644
index 000000000000..2f53a834d741
--- /dev/null
+++ b/usr.bin/vmstat/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libdevstat \
+ lib/libkvm \
+ lib/libmemstat \
+ lib/libutil \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vmstat/tests/Makefile b/usr.bin/vmstat/tests/Makefile
new file mode 100644
index 000000000000..67c759df3864
--- /dev/null
+++ b/usr.bin/vmstat/tests/Makefile
@@ -0,0 +1,7 @@
+PACKAGE= tests
+
+NETBSD_ATF_TESTS_SH= vmstat_test
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/usr.bin/vmstat/tests/Makefile.depend b/usr.bin/vmstat/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/vmstat/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vmstat/vmstat.8 b/usr.bin/vmstat/vmstat.8
new file mode 100644
index 000000000000..de4176c9361c
--- /dev/null
+++ b/usr.bin/vmstat/vmstat.8
@@ -0,0 +1,394 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.Dd June 21, 2021
+.Dt VMSTAT 8
+.Os
+.Sh NAME
+.Nm vmstat
+.Nd report virtual memory statistics
+.Sh SYNOPSIS
+.Nm
+.\" .Op Fl fimst
+.Op Fl -libxo
+.Op Fl afHhimoPsz
+.Op Fl M Ar core Op Fl N Ar system
+.Op Fl c Ar count
+.Op Fl n Ar devs
+.Oo
+.Fl p
+.Sm off
+.Ar type , if , pass
+.Sm on
+.Oc
+.Op Fl w Ar wait
+.Op Ar disks ...
+.Op wait Op count
+.Sh DESCRIPTION
+The
+.Nm
+utility reports certain kernel statistics kept about process, virtual memory,
+disk, trap and cpu activity.
+.Pp
+If the
+.Fl M
+option is not specified, information is obtained from
+the currently running kernel via the
+.Xr sysctl 3
+interface.
+Otherwise, information is read from the specified core file,
+using the name list from the specified kernel image (or from
+the default image).
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl a
+When used with
+.Fl i ,
+include statistics about interrupts that have never been generated.
+.It Fl c
+Repeat the display
+.Ar count
+times.
+The first display is for the time since a reboot and each subsequent
+report is for the time period since the last display.
+If no repeat
+.Ar count
+is specified, and
+.Fl w
+is specified, the default is infinity, otherwise the default is one.
+.It Fl f
+Report on the number
+.Xr fork 2 ,
+.Xr vfork 2
+and
+.Xr rfork 2
+system calls since system startup, and the number of pages of virtual memory
+involved in each.
+.It Fl h
+Changes memory columns into more easily human readable form.
+The default if
+standard output is a terminal device.
+.It Fl H
+Changes memory columns into straight numbers.
+The default if standard output
+is not a terminal device (such as a script).
+.It Fl i
+Report on the number of interrupts taken by each device since system
+startup.
+.It Fl M
+Extract values associated with the name list from the specified
+.Ar core .
+.It Fl N
+If
+.Fl M
+is also specified,
+extract the name list from the specified
+.Ar system
+instead of the default,
+which is the kernel image the system has booted from.
+.It Fl m
+Report on the usage of kernel dynamic memory allocated using
+.Xr malloc 9
+by type.
+.It Fl n
+Change the maximum number of disks to display from the default of 2.
+.It Fl o
+Display a list of virtual memory objects in the system and the resident
+memory used by each object.
+.It Fl P
+Report per-cpu system/user/idle cpu statistics.
+.It Fl p
+Specify which types of devices to display.
+There are three different
+categories of devices:
+.Pp
+.Bl -tag -width indent -compact
+.It device type:
+.Bl -tag -width 9n -compact
+.It da
+Direct Access devices
+.It sa
+Sequential Access devices
+.It printer
+Printers
+.It proc
+Processor devices
+.It worm
+Write Once Read Multiple devices
+.It cd
+CD devices
+.It scanner
+Scanner devices
+.It optical
+Optical Memory devices
+.It changer
+Medium Changer devices
+.It comm
+Communication devices
+.It array
+Storage Array devices
+.It enclosure
+Enclosure Services devices
+.It floppy
+Floppy devices
+.El
+.Pp
+.It interface:
+.Bl -tag -width 9n -compact
+.It IDE
+Integrated Drive Electronics devices
+.It SCSI
+Small Computer System Interface devices
+.It NVME
+NVM Express Interface devices
+.It other
+Any other device interface
+.El
+.Pp
+.It passthrough:
+.Bl -tag -width 9n -compact
+.It pass
+Passthrough devices
+.El
+.El
+.Pp
+The user must specify at least one device type, and may specify at most
+one device type from each category.
+Multiple device types in a single
+device type statement must be separated by commas.
+.Pp
+Any number of
+.Fl p
+arguments may be specified on the command line.
+All
+.Fl p
+arguments are ORed together to form a matching expression against which
+all devices in the system are compared.
+Any device that fully matches
+any
+.Fl p
+argument will be included in the
+.Nm
+output, up to two devices, or the maximum number of devices specified
+by the user.
+.It Fl s
+Display the contents of the
+.Em sum
+structure, giving the total number of several kinds of paging related
+events which have occurred since system startup.
+.It Fl w
+Pause
+.Ar wait
+seconds between each display.
+If no repeat
+.Ar wait
+interval is specified, the default is 1 second.
+The
+.Nm
+command will accept and honor a non-integer number of seconds.
+.It Fl z
+Report on memory used by the kernel zone allocator,
+.Xr uma 9 ,
+by zone.
+.El
+.Pp
+The
+.Ar wait
+and
+.Ar count
+arguments may be given after their respective flags at any point
+on the command line before the
+.Ar disks
+argument(s), or without their flags, as the final argument(s).
+The latter form is accepted for backwards compatibility, but it is
+preferred to use the forms with
+.Fl w
+and
+.Fl c
+to avoid ambiguity.
+.Pp
+By default,
+.Nm
+displays the following information:
+.Bl -tag -width indent
+.It procs
+Information about the number of threads in various states:
+.Pp
+.Bl -tag -width indent -compact
+.It r
+running or in run queue
+.It b
+blocked for resources (i/o, paging, etc.)
+.It w
+swapped out
+.El
+.It memory
+Information about the usage of virtual and real memory.
+.Pp
+Mapped virtual memory is a sum of all of the virtual pages belonging
+to mapped virtual memory objects.
+Note that the entire memory object's size is considered mapped even if
+only a subset of the object's pages are currently mapped.
+This statistic is not related to the active page queue which is used to track
+real memory.
+.Pp
+.Bl -tag -width indent -compact
+.It avm
+mapped virtual memory
+.Po previously called active in
+.Nm
+output
+.Pc
+.It fre
+size of the free list
+.El
+.It page
+Information about page faults and paging activity.
+These are given in units per second.
+.Pp
+.Bl -tag -width indent -compact
+.It flt
+total number of page faults
+.It re
+pages reactivated (found in laundry or inactive queues)
+.\" .It at
+.\" pages attached (found in free list)
+.It pi
+pages paged in
+.It po
+pages paged out
+.It fr
+pages freed
+.\" .It de
+.\" anticipated short term memory shortfall
+.It sr
+pages scanned by page daemon
+.El
+.It disks
+Disk operations per second (this field is system dependent).
+Typically paging will be split across the available drives.
+The header of the field is the first two characters of the disk name and
+the unit number.
+If more than two disk drives are configured in the system,
+.Nm
+displays only the first two drives, unless the user specifies the
+.Fl n
+argument to increase the number of drives displayed.
+This will probably
+cause the display to exceed 80 columns, however.
+To force
+.Nm
+to display specific drives, their names may be supplied on the command line.
+The
+.Nm
+utility
+defaults to show disks first, and then various other random devices in the
+system to add up to two devices, if there are that many devices in the
+system.
+If devices are specified on the command line, or if a device type
+matching pattern is specified (see above),
+.Nm
+will only display the given devices or the devices matching the pattern,
+and will not randomly select other devices in the system.
+.It faults
+Trap/interrupt rates per second.
+.Pp
+.Bl -tag -width indent -compact
+.It in
+device interrupts (including clock interrupts)
+.It sy
+system calls
+.It cs
+cpu context switches
+.El
+.It cpu
+Breakdown of percentage usage of CPU time.
+.Pp
+.Bl -tag -width indent -compact
+.It us
+user time for normal and low priority processes
+.It sy
+system and interrupt time
+.It id
+cpu idle
+.El
+.El
+.Sh FILES
+.Bl -tag -width /boot/kernel/kernel -compact
+.It Pa /boot/kernel/kernel
+default kernel namelist
+.It Pa /dev/kmem
+default memory file
+.El
+.Sh EXAMPLES
+The command:
+.Dl vmstat -w 5
+will print what the system is doing every five
+seconds.
+.Pp
+The command:
+.Dl vmstat -p da -p cd -w 1
+will tell vmstat to select the first two direct access or CDROM devices
+and display statistics on those devices, as well as other systems
+statistics every second.
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr nfsstat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr libmemstat 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
+.Xr gstat 8 ,
+.Xr iostat 8 ,
+.Xr pstat 8 ,
+.Xr sysctl 8 ,
+.Xr malloc 9 ,
+.Xr uma 9
+.Pp
+The sections starting with ``Interpreting system activity'' in
+.%T "Installing and Operating 4.3BSD" .
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Bx 3 .
+.Sh BUGS
+The
+.Fl c
+and
+.Fl w
+options are only available with the default output.
diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c
new file mode 100644
index 000000000000..7a7c83fe1ac8
--- /dev/null
+++ b/usr.bin/vmstat/vmstat.c
@@ -0,0 +1,1626 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1986, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/namei.h>
+#include <sys/malloc.h>
+#include <sys/signal.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#define _WANT_VMMETER
+#include <sys/vmmeter.h>
+#include <sys/pcpu.h>
+
+#include <vm/vm_param.h>
+
+#include <ctype.h>
+#include <devstat.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <kvm.h>
+#include <limits.h>
+#include <memstat.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <libxo/xo.h>
+
+#define VMSTAT_XO_VERSION "2"
+
+static char da[] = "da";
+
+enum x_stats { X_SUM, X_HZ, X_STATHZ, X_NCHSTATS, X_INTRNAMES, X_SINTRNAMES,
+ X_INTRCNT, X_SINTRCNT, X_NINTRCNT };
+
+static struct nlist namelist[] = {
+ [X_SUM] = { .n_name = "_vm_cnt", },
+ [X_HZ] = { .n_name = "_hz", },
+ [X_STATHZ] = { .n_name = "_stathz", },
+ [X_NCHSTATS] = { .n_name = "_nchstats", },
+ [X_INTRNAMES] = { .n_name = "_intrnames", },
+ [X_SINTRNAMES] = { .n_name = "_sintrnames", },
+ [X_INTRCNT] = { .n_name = "_intrcnt", },
+ [X_SINTRCNT] = { .n_name = "_sintrcnt", },
+ [X_NINTRCNT] = { .n_name = "_nintrcnt", },
+ { .n_name = NULL, },
+};
+
+static struct devstat_match *matches;
+static struct device_selection *dev_select;
+static struct statinfo cur, last;
+static devstat_select_mode select_mode;
+static size_t size_cp_times;
+static long *cur_cp_times, *last_cp_times;
+static long generation, select_generation;
+static int hz, hdrcnt, maxshowdevs;
+static int num_devices, num_devices_specified;
+static int num_matches, num_selected, num_selections;
+static char **specified_devices;
+
+static struct __vmmeter {
+ uint64_t v_swtch;
+ uint64_t v_trap;
+ uint64_t v_syscall;
+ uint64_t v_intr;
+ uint64_t v_soft;
+ uint64_t v_vm_faults;
+ uint64_t v_io_faults;
+ uint64_t v_cow_faults;
+ uint64_t v_cow_optim;
+ uint64_t v_zfod;
+ uint64_t v_ozfod;
+ uint64_t v_swapin;
+ uint64_t v_swapout;
+ uint64_t v_swappgsin;
+ uint64_t v_swappgsout;
+ uint64_t v_vnodein;
+ uint64_t v_vnodeout;
+ uint64_t v_vnodepgsin;
+ uint64_t v_vnodepgsout;
+ uint64_t v_intrans;
+ uint64_t v_reactivated;
+ uint64_t v_pdwakeups;
+ uint64_t v_pdpages;
+ uint64_t v_pdshortfalls;
+ uint64_t v_dfree;
+ uint64_t v_pfree;
+ uint64_t v_tfree;
+ uint64_t v_forks;
+ uint64_t v_vforks;
+ uint64_t v_rforks;
+ uint64_t v_kthreads;
+ uint64_t v_forkpages;
+ uint64_t v_vforkpages;
+ uint64_t v_rforkpages;
+ uint64_t v_kthreadpages;
+ u_int v_page_size;
+ u_int v_page_count;
+ u_int v_free_reserved;
+ u_int v_free_target;
+ u_int v_free_min;
+ u_int v_free_count;
+ u_int v_wire_count;
+ u_long v_user_wire_count;
+ u_int v_nofree_count;
+ u_int v_active_count;
+ u_int v_inactive_target;
+ u_int v_inactive_count;
+ u_int v_laundry_count;
+ u_int v_pageout_free_min;
+ u_int v_interrupt_free_min;
+ u_int v_free_severe;
+} sum, osum;
+
+#define VMSTAT_DEFAULT_LINES 20 /* Default number of `winlines'. */
+static volatile sig_atomic_t wresized; /* Tty resized when non-zero. */
+static int winlines = VMSTAT_DEFAULT_LINES; /* Current number of tty rows. */
+
+static int aflag;
+static int nflag;
+static int Pflag;
+static int hflag;
+
+static kvm_t *kd;
+
+#define FORKSTAT 0x01
+#define INTRSTAT 0x02
+#define MEMSTAT 0x04
+#define SUMSTAT 0x08
+#define TIMESTAT 0x10
+#define VMSTAT 0x20
+#define ZMEMSTAT 0x40
+#define OBJSTAT 0x80
+
+static void cpustats(void);
+static void pcpustats(u_long, int);
+static void devstats(void);
+static void doforkst(void);
+static void dointr(unsigned int, int);
+static void doobjstat(void);
+static void dosum(void);
+static void dovmstat(unsigned int, int);
+static void domemstat_malloc(void);
+static void domemstat_zone(void);
+static void kread(int, void *, size_t);
+static void kreado(int, void *, size_t, size_t);
+static void kreadptr(uintptr_t, void *, size_t);
+static void needhdr(int);
+static void needresize(int);
+static void doresize(void);
+static void printhdr(int, u_long);
+static void usage(void);
+
+static long pct(long, long);
+static long long getuptime(void);
+
+static char **getdrivedata(char **);
+
+int
+main(int argc, char *argv[])
+{
+ char *bp, *buf, *memf, *nlistf;
+ float f;
+ int bufsize, c, reps, todo;
+ size_t len;
+ unsigned int interval;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ memf = nlistf = NULL;
+ interval = reps = todo = 0;
+ maxshowdevs = 2;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return (argc);
+
+ hflag = isatty(1);
+
+ while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:sw:z")) != -1) {
+ switch (c) {
+ case 'a':
+ aflag++;
+ break;
+ case 'c':
+ reps = atoi(optarg);
+ break;
+ case 'P':
+ Pflag++;
+ break;
+ case 'f':
+ todo |= FORKSTAT;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'H':
+ hflag = 0;
+ break;
+ case 'i':
+ todo |= INTRSTAT;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'm':
+ todo |= MEMSTAT;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ nflag = 1;
+ maxshowdevs = atoi(optarg);
+ if (maxshowdevs < 0)
+ xo_errx(1, "number of devices %d is < 0",
+ maxshowdevs);
+ break;
+ case 'o':
+ todo |= OBJSTAT;
+ break;
+ case 'p':
+ if (devstat_buildmatch(optarg, &matches, &num_matches)
+ != 0)
+ xo_errx(1, "%s", devstat_errbuf);
+ break;
+ case 's':
+ todo |= SUMSTAT;
+ break;
+ case 'w':
+ /* Convert to milliseconds. */
+ f = atof(optarg);
+ interval = f * 1000;
+ break;
+ case 'z':
+ todo |= ZMEMSTAT;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ xo_set_version(VMSTAT_XO_VERSION);
+ xo_open_container("vmstat");
+ if (!hflag)
+ xo_set_options(NULL, "no-humanize");
+ if (todo == 0)
+ todo = VMSTAT;
+
+ if (memf != NULL) {
+ kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ if (kd == NULL)
+ xo_errx(1, "kvm_openfiles: %s", errbuf);
+ }
+
+retry_nlist:
+ if (kd != NULL && (c = kvm_nlist(kd, namelist)) != 0) {
+ if (c > 0) {
+ bufsize = 0;
+ len = 0;
+
+ /*
+ * 'cnt' was renamed to 'vm_cnt'. If 'vm_cnt' is not
+ * found try looking up older 'cnt' symbol.
+ * */
+ if (namelist[X_SUM].n_type == 0 &&
+ strcmp(namelist[X_SUM].n_name, "_vm_cnt") == 0) {
+ namelist[X_SUM].n_name = "_cnt";
+ goto retry_nlist;
+ }
+
+ /*
+ * 'nintrcnt' doesn't exist in older kernels, but
+ * that isn't fatal.
+ */
+ if (namelist[X_NINTRCNT].n_type == 0 && c == 1)
+ goto nlist_ok;
+
+ for (c = 0; c < (int)(nitems(namelist)); c++)
+ if (namelist[c].n_type == 0)
+ bufsize += strlen(namelist[c].n_name)
+ + 1;
+ bufsize += len + 1;
+ buf = bp = alloca(bufsize);
+
+ for (c = 0; c < (int)(nitems(namelist)); c++)
+ if (namelist[c].n_type == 0) {
+ xo_error(" %s",
+ namelist[c].n_name);
+ len = strlen(namelist[c].n_name);
+ *bp++ = ' ';
+ memcpy(bp, namelist[c].n_name, len);
+ bp += len;
+ }
+ *bp = '\0';
+ xo_error("undefined symbols:\n", buf);
+ } else
+ xo_warnx("kvm_nlist: %s", kvm_geterr(kd));
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_FAILURE);
+ }
+nlist_ok:
+ if (kd && Pflag)
+ xo_errx(1, "Cannot use -P with crash dumps");
+
+ if (todo & VMSTAT) {
+ /*
+ * Make sure that the userland devstat version matches the
+ * kernel devstat version. If not, exit and print a
+ * message informing the user of his mistake.
+ */
+ if (devstat_checkversion(NULL) < 0)
+ xo_errx(1, "%s", devstat_errbuf);
+
+
+ argv = getdrivedata(argv);
+ }
+
+ if (*argv) {
+ f = atof(*argv);
+ interval = f * 1000;
+ if (*++argv)
+ reps = atoi(*argv);
+ }
+
+ if (interval) {
+ if (!reps)
+ reps = -1;
+ } else if (reps)
+ interval = 1 * 1000;
+
+ if (todo & FORKSTAT)
+ doforkst();
+ if (todo & MEMSTAT)
+ domemstat_malloc();
+ if (todo & ZMEMSTAT)
+ domemstat_zone();
+ if (todo & SUMSTAT)
+ dosum();
+ if (todo & OBJSTAT)
+ doobjstat();
+ if (todo & INTRSTAT)
+ dointr(interval, reps);
+ if (todo & VMSTAT)
+ dovmstat(interval, reps);
+ xo_close_container("vmstat");
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_SUCCESS);
+}
+
+static int
+mysysctl(const char *name, void *oldp, size_t *oldlenp)
+{
+ int error;
+
+ error = sysctlbyname(name, oldp, oldlenp, NULL, 0);
+ if (error != 0 && errno != ENOMEM)
+ xo_err(1, "sysctl(%s)", name);
+ return (error);
+}
+
+static char **
+getdrivedata(char **argv)
+{
+
+ if ((num_devices = devstat_getnumdevs(NULL)) < 0)
+ xo_errx(1, "%s", devstat_errbuf);
+
+ cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
+ last.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
+
+ if (devstat_getdevs(NULL, &cur) == -1)
+ xo_errx(1, "%s", devstat_errbuf);
+
+ num_devices = cur.dinfo->numdevs;
+ generation = cur.dinfo->generation;
+
+ specified_devices = malloc(sizeof(char *));
+ for (num_devices_specified = 0; *argv; ++argv) {
+ if (isdigit(**argv))
+ break;
+ num_devices_specified++;
+ specified_devices = reallocf(specified_devices,
+ sizeof(char *) * num_devices_specified);
+ if (specified_devices == NULL) {
+ xo_errx(1, "%s", "reallocf (specified_devices)");
+ }
+ specified_devices[num_devices_specified - 1] = *argv;
+ }
+ dev_select = NULL;
+
+ if (nflag == 0 && maxshowdevs < num_devices_specified)
+ maxshowdevs = num_devices_specified;
+
+ /*
+ * People are generally only interested in disk statistics when
+ * they're running vmstat. So, that's what we're going to give
+ * them if they don't specify anything by default. We'll also give
+ * them any other random devices in the system so that we get to
+ * maxshowdevs devices, if that many devices exist. If the user
+ * specifies devices on the command line, either through a pattern
+ * match or by naming them explicitly, we will give the user only
+ * those devices.
+ */
+ if ((num_devices_specified == 0) && (num_matches == 0)) {
+ if (devstat_buildmatch(da, &matches, &num_matches) != 0)
+ xo_errx(1, "%s", devstat_errbuf);
+ select_mode = DS_SELECT_ADD;
+ } else
+ select_mode = DS_SELECT_ONLY;
+
+ /*
+ * At this point, selectdevs will almost surely indicate that the
+ * device list has changed, so we don't look for return values of 0
+ * or 1. If we get back -1, though, there is an error.
+ */
+ if (devstat_selectdevs(&dev_select, &num_selected, &num_selections,
+ &select_generation, generation, cur.dinfo->devices,
+ num_devices, matches, num_matches, specified_devices,
+ num_devices_specified, select_mode,
+ maxshowdevs, 0) == -1)
+ xo_errx(1, "%s", devstat_errbuf);
+
+ return(argv);
+}
+
+/* Return system uptime in nanoseconds */
+static long long
+getuptime(void)
+{
+ struct timespec sp;
+
+ (void)clock_gettime(CLOCK_UPTIME, &sp);
+ return((long long)sp.tv_sec * 1000000000LL + sp.tv_nsec);
+}
+
+static void
+fill_vmmeter(struct __vmmeter *vmmp)
+{
+ struct vmmeter vm_cnt;
+ size_t size;
+
+ if (kd != NULL) {
+ kread(X_SUM, &vm_cnt, sizeof(vm_cnt));
+#define GET_COUNTER(name) \
+ vmmp->name = kvm_counter_u64_fetch(kd, (u_long)vm_cnt.name)
+ GET_COUNTER(v_swtch);
+ GET_COUNTER(v_trap);
+ GET_COUNTER(v_syscall);
+ GET_COUNTER(v_intr);
+ GET_COUNTER(v_soft);
+ GET_COUNTER(v_vm_faults);
+ GET_COUNTER(v_io_faults);
+ GET_COUNTER(v_cow_faults);
+ GET_COUNTER(v_cow_optim);
+ GET_COUNTER(v_zfod);
+ GET_COUNTER(v_ozfod);
+ GET_COUNTER(v_swapin);
+ GET_COUNTER(v_swapout);
+ GET_COUNTER(v_swappgsin);
+ GET_COUNTER(v_swappgsout);
+ GET_COUNTER(v_vnodein);
+ GET_COUNTER(v_vnodeout);
+ GET_COUNTER(v_vnodepgsin);
+ GET_COUNTER(v_vnodepgsout);
+ GET_COUNTER(v_intrans);
+ GET_COUNTER(v_tfree);
+ GET_COUNTER(v_forks);
+ GET_COUNTER(v_vforks);
+ GET_COUNTER(v_rforks);
+ GET_COUNTER(v_kthreads);
+ GET_COUNTER(v_forkpages);
+ GET_COUNTER(v_vforkpages);
+ GET_COUNTER(v_rforkpages);
+ GET_COUNTER(v_kthreadpages);
+#undef GET_COUNTER
+ } else {
+#define GET_VM_STATS(cat, name) do { \
+ size = sizeof(vmmp->name); \
+ mysysctl("vm.stats." #cat "." #name, &vmmp->name, &size); \
+} while (0)
+ /* sys */
+ GET_VM_STATS(sys, v_swtch);
+ GET_VM_STATS(sys, v_trap);
+ GET_VM_STATS(sys, v_syscall);
+ GET_VM_STATS(sys, v_intr);
+ GET_VM_STATS(sys, v_soft);
+
+ /* vm */
+ GET_VM_STATS(vm, v_vm_faults);
+ GET_VM_STATS(vm, v_io_faults);
+ GET_VM_STATS(vm, v_cow_faults);
+ GET_VM_STATS(vm, v_cow_optim);
+ GET_VM_STATS(vm, v_zfod);
+ GET_VM_STATS(vm, v_ozfod);
+ GET_VM_STATS(vm, v_swapin);
+ GET_VM_STATS(vm, v_swapout);
+ GET_VM_STATS(vm, v_swappgsin);
+ GET_VM_STATS(vm, v_swappgsout);
+ GET_VM_STATS(vm, v_vnodein);
+ GET_VM_STATS(vm, v_vnodeout);
+ GET_VM_STATS(vm, v_vnodepgsin);
+ GET_VM_STATS(vm, v_vnodepgsout);
+ GET_VM_STATS(vm, v_intrans);
+ GET_VM_STATS(vm, v_reactivated);
+ GET_VM_STATS(vm, v_pdwakeups);
+ GET_VM_STATS(vm, v_pdpages);
+ GET_VM_STATS(vm, v_pdshortfalls);
+ GET_VM_STATS(vm, v_dfree);
+ GET_VM_STATS(vm, v_pfree);
+ GET_VM_STATS(vm, v_tfree);
+ GET_VM_STATS(vm, v_page_size);
+ GET_VM_STATS(vm, v_page_count);
+ GET_VM_STATS(vm, v_free_reserved);
+ GET_VM_STATS(vm, v_free_target);
+ GET_VM_STATS(vm, v_free_min);
+ GET_VM_STATS(vm, v_free_count);
+ GET_VM_STATS(vm, v_wire_count);
+ GET_VM_STATS(vm, v_user_wire_count);
+ GET_VM_STATS(vm, v_nofree_count);
+ GET_VM_STATS(vm, v_active_count);
+ GET_VM_STATS(vm, v_inactive_target);
+ GET_VM_STATS(vm, v_inactive_count);
+ GET_VM_STATS(vm, v_laundry_count);
+ GET_VM_STATS(vm, v_pageout_free_min);
+ GET_VM_STATS(vm, v_interrupt_free_min);
+ /*GET_VM_STATS(vm, v_free_severe);*/
+ GET_VM_STATS(vm, v_forks);
+ GET_VM_STATS(vm, v_vforks);
+ GET_VM_STATS(vm, v_rforks);
+ GET_VM_STATS(vm, v_kthreads);
+ GET_VM_STATS(vm, v_forkpages);
+ GET_VM_STATS(vm, v_vforkpages);
+ GET_VM_STATS(vm, v_rforkpages);
+ GET_VM_STATS(vm, v_kthreadpages);
+#undef GET_VM_STATS
+ }
+}
+
+static void
+fill_vmtotal(struct vmtotal *vmtp)
+{
+ size_t size;
+
+ if (kd != NULL) {
+ /* XXX fill vmtp */
+ xo_errx(1, "not implemented");
+ } else {
+ size = sizeof(*vmtp);
+ mysysctl("vm.vmtotal", vmtp, &size);
+ if (size != sizeof(*vmtp))
+ xo_errx(1, "vm.total size mismatch");
+ }
+}
+
+/* Determine how many cpu columns, and what index they are in kern.cp_times */
+static void
+getcpuinfo(u_long *maskp, int *maxidp)
+{
+ long *times;
+ u_long mask;
+ size_t size;
+ int empty, i, j, maxcpu, maxid;
+
+ if (kd != NULL)
+ xo_errx(1, "not implemented");
+ mask = 0;
+ size = sizeof(maxcpu);
+ mysysctl("kern.smp.maxcpus", &maxcpu, &size);
+ if (size != sizeof(maxcpu))
+ xo_errx(1, "sysctl kern.smp.maxcpus");
+ size = sizeof(long) * maxcpu * CPUSTATES;
+ times = malloc(size);
+ if (times == NULL)
+ xo_err(1, "malloc %zd bytes", size);
+ mysysctl("kern.cp_times", times, &size);
+ maxid = (size / CPUSTATES / sizeof(long)) - 1;
+ for (i = 0; i <= maxid; i++) {
+ empty = 1;
+ for (j = 0; empty && j < CPUSTATES; j++) {
+ if (times[i * CPUSTATES + j] != 0)
+ empty = 0;
+ }
+ if (!empty)
+ mask |= (1ul << i);
+ }
+ if (maskp)
+ *maskp = mask;
+ if (maxidp)
+ *maxidp = maxid;
+}
+
+static void
+dovmstat(unsigned int interval, int reps)
+{
+ struct clockinfo clockrate;
+ struct vmtotal total;
+ struct devinfo *tmp_dinfo;
+ u_long cpumask;
+ size_t size;
+ time_t uptime, halfuptime;
+ int maxid, rate_adj, retval;
+
+ uptime = getuptime() / 1000000000LL;
+ halfuptime = uptime / 2;
+ rate_adj = 1;
+ maxid = 0;
+ cpumask = 0;
+
+ /*
+ * If the user stops the program (control-Z) and then resumes it,
+ * print out the header again.
+ */
+ (void)signal(SIGCONT, needhdr);
+
+ /*
+ * If our standard output is a tty, then install a SIGWINCH handler
+ * and set wresized so that our first iteration through the main
+ * vmstat loop will peek at the terminal's current rows to find out
+ * how many lines can fit in a screenful of output.
+ */
+ if (isatty(fileno(stdout)) != 0) {
+ wresized = 1;
+ (void)signal(SIGWINCH, needresize);
+ } else {
+ wresized = 0;
+ winlines = VMSTAT_DEFAULT_LINES;
+ }
+
+ if (kd != NULL) {
+ if (namelist[X_STATHZ].n_type != 0 &&
+ namelist[X_STATHZ].n_value != 0)
+ kread(X_STATHZ, &hz, sizeof(hz));
+ if (!hz)
+ kread(X_HZ, &hz, sizeof(hz));
+ } else {
+ size = sizeof(clockrate);
+ mysysctl("kern.clockrate", &clockrate, &size);
+ if (size != sizeof(clockrate))
+ xo_errx(1, "clockrate size mismatch");
+ hz = clockrate.hz;
+ }
+
+ if (Pflag) {
+ getcpuinfo(&cpumask, &maxid);
+ size_cp_times = sizeof(long) * (maxid + 1) * CPUSTATES;
+ cur_cp_times = calloc(1, size_cp_times);
+ last_cp_times = calloc(1, size_cp_times);
+ }
+ for (hdrcnt = 1;;) {
+ if (!--hdrcnt)
+ printhdr(maxid, cpumask);
+ if (kd != NULL) {
+ if (kvm_getcptime(kd, cur.cp_time) < 0)
+ xo_errx(1, "kvm_getcptime: %s", kvm_geterr(kd));
+ } else {
+ size = sizeof(cur.cp_time);
+ mysysctl("kern.cp_time", &cur.cp_time, &size);
+ if (size != sizeof(cur.cp_time))
+ xo_errx(1, "cp_time size mismatch");
+ }
+ if (Pflag) {
+ size = size_cp_times;
+ mysysctl("kern.cp_times", cur_cp_times, &size);
+ if (size != size_cp_times)
+ xo_errx(1, "cp_times mismatch");
+ }
+
+ tmp_dinfo = last.dinfo;
+ last.dinfo = cur.dinfo;
+ cur.dinfo = tmp_dinfo;
+ last.snap_time = cur.snap_time;
+
+ /*
+ * Here what we want to do is refresh our device stats.
+ * getdevs() returns 1 when the device list has changed.
+ * If the device list has changed, we want to go through
+ * the selection process again, in case a device that we
+ * were previously displaying has gone away.
+ */
+ switch (devstat_getdevs(NULL, &cur)) {
+ case -1:
+ xo_errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ num_devices = cur.dinfo->numdevs;
+ generation = cur.dinfo->generation;
+
+ retval = devstat_selectdevs(&dev_select, &num_selected,
+ &num_selections, &select_generation,
+ generation, cur.dinfo->devices,
+ num_devices, matches, num_matches,
+ specified_devices,
+ num_devices_specified, select_mode,
+ maxshowdevs, 0);
+ switch (retval) {
+ case -1:
+ xo_errx(1, "%s", devstat_errbuf);
+ break;
+ case 1:
+ printhdr(maxid, cpumask);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ fill_vmmeter(&sum);
+ fill_vmtotal(&total);
+ xo_open_container("processes");
+ xo_emit("{:runnable/%2d} {:waiting/%2ld} "
+ "{:swapped-out/%2ld}", total.t_rq - 1, total.t_dw +
+ total.t_pw, total.t_sw);
+ xo_close_container("processes");
+ xo_open_container("memory");
+#define rate(x) (unsigned long)(((x) * rate_adj + halfuptime) / uptime)
+ xo_emit(" {[:4}{h,hn-decimal:available-memory/%ju}{]:}",
+ (uintmax_t)total.t_avm * sum.v_page_size);
+ xo_emit(" {[:4}{h,hn-decimal:free-memory/%ju}{]:}",
+ (uintmax_t)total.t_free * sum.v_page_size);
+ xo_emit(" {[:4}{h,hn-decimal,hn-1000:total-page-faults/%lu}{]:} ",
+ rate(sum.v_vm_faults - osum.v_vm_faults));
+ xo_close_container("memory");
+
+ xo_open_container("paging-rates");
+ xo_emit("{:page-reactivated/%3lu} ",
+ rate(sum.v_reactivated - osum.v_reactivated));
+ xo_emit("{:paged-in/%3lu} ",
+ rate(sum.v_swapin + sum.v_vnodein -
+ (osum.v_swapin + osum.v_vnodein)));
+ xo_emit("{:paged-out/%3lu}",
+ rate(sum.v_swapout + sum.v_vnodeout -
+ (osum.v_swapout + osum.v_vnodeout)));
+ xo_emit(" {[:4}{h,hn-decimal,hn-1000:freed/%lu}{]:}",
+ rate(sum.v_tfree - osum.v_tfree));
+ xo_emit(" {[:4}{h,hn-decimal,hn-1000:scanned/%lu}{]:}",
+ rate(sum.v_pdpages - osum.v_pdpages));
+ xo_close_container("paging-rates");
+
+ devstats();
+ xo_open_container("fault-rates");
+ xo_emit(" {[:4}{h,hn-decimal,hn-1000:interrupts/%lu}{]:}"
+ " {[:4}{h,hn-decimal,hn-1000:system-calls/%lu}{]:}"
+ " {[:4}{h,hn-decimal,hn-1000:context-switches/%lu}{]:}",
+ rate(sum.v_intr - osum.v_intr),
+ rate(sum.v_syscall - osum.v_syscall),
+ rate(sum.v_swtch - osum.v_swtch));
+ xo_close_container("fault-rates");
+ if (Pflag)
+ pcpustats(cpumask, maxid);
+ else
+ cpustats();
+ xo_emit("\n");
+ if (xo_flush() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ if (reps >= 0 && --reps <= 0)
+ break;
+ osum = sum;
+ uptime = interval;
+ rate_adj = 1000;
+ /*
+ * We round upward to avoid losing low-frequency events
+ * (i.e., >= 1 per interval but < 1 per millisecond).
+ */
+ if (interval != 1)
+ halfuptime = (uptime + 1) / 2;
+ else
+ halfuptime = 0;
+ (void)usleep(interval * 1000);
+ }
+}
+
+static void
+printhdr(int maxid, u_long cpumask)
+{
+ int i, num_shown;
+
+ num_shown = MIN(num_selected, maxshowdevs);
+ xo_emit(" {T:procs} {T:memory} {T:/page%*s}", 19, "");
+ if (num_shown > 1)
+ xo_emit(" {T:/disks %*s} ", num_shown * 5 - 7, "");
+ else if (num_shown == 1)
+ xo_emit(" {T:disks} ");
+ xo_emit(" {T:faults} ");
+ if (Pflag) {
+ for (i = 0; i <= maxid; i++) {
+ if (cpumask & (1ul << i))
+ xo_emit(" {T:/cpu%d} ", i);
+ }
+ xo_emit("\n");
+ } else
+ xo_emit(" {T:cpu}\n");
+ xo_emit(" {T:r} {T:b} {T:w} {T:avm} {T:fre} {T:flt} {T:re}"
+ " {T:pi} {T:po} {T:fr} {T:sr} ");
+ for (i = 0; i < num_devices; i++)
+ if ((dev_select[i].selected) &&
+ (dev_select[i].selected <= maxshowdevs))
+ xo_emit("{T:/%3.3s%d} ", dev_select[i].device_name,
+ dev_select[i].unit_number);
+ xo_emit(" {T:in} {T:sy} {T:cs}");
+ if (Pflag) {
+ for (i = 0; i <= maxid; i++) {
+ if (cpumask & (1ul << i))
+ xo_emit(" {T:us} {T:sy} {T:id}");
+ }
+ xo_emit("\n");
+ } else
+ xo_emit(" {T:us} {T:sy} {T:id}\n");
+ if (wresized != 0)
+ doresize();
+ hdrcnt = winlines;
+}
+
+/*
+ * Force a header to be prepended to the next output.
+ */
+static void
+needhdr(int dummy __unused)
+{
+
+ hdrcnt = 1;
+}
+
+/*
+ * When the terminal is resized, force an update of the maximum number of rows
+ * printed between each header repetition. Then force a new header to be
+ * prepended to the next output.
+ */
+void
+needresize(int signo __unused)
+{
+
+ wresized = 1;
+ hdrcnt = 1;
+}
+
+/*
+ * Update the global `winlines' count of terminal rows.
+ */
+void
+doresize(void)
+{
+ struct winsize w;
+ int status;
+
+ for (;;) {
+ status = ioctl(fileno(stdout), TIOCGWINSZ, &w);
+ if (status == -1 && errno == EINTR)
+ continue;
+ else if (status == -1)
+ xo_err(1, "ioctl");
+ if (w.ws_row > 3)
+ winlines = w.ws_row - 3;
+ else
+ winlines = VMSTAT_DEFAULT_LINES;
+ break;
+ }
+
+ /*
+ * Inhibit doresize() calls until we are rescheduled by SIGWINCH.
+ */
+ wresized = 0;
+}
+
+static long
+pct(long top, long bot)
+{
+ long ans;
+
+ if (bot == 0)
+ return(0);
+ ans = (quad_t)top * 100 / bot;
+ return (ans);
+}
+
+#define PCT(top, bot) pct((long)(top), (long)(bot))
+
+static void
+dosum(void)
+{
+ struct nchstats lnchstats;
+ size_t size;
+ long nchtotal;
+
+ fill_vmmeter(&sum);
+ xo_open_container("summary-statistics");
+ xo_emit("{:context-switches/%9u} {N:cpu context switches}\n",
+ sum.v_swtch);
+ xo_emit("{:interrupts/%9u} {N:device interrupts}\n",
+ sum.v_intr);
+ xo_emit("{:software-interrupts/%9u} {N:software interrupts}\n",
+ sum.v_soft);
+ xo_emit("{:traps/%9u} {N:traps}\n", sum.v_trap);
+ xo_emit("{:system-calls/%9u} {N:system calls}\n",
+ sum.v_syscall);
+ xo_emit("{:kernel-threads/%9u} {N:kernel threads created}\n",
+ sum.v_kthreads);
+ xo_emit("{:forks/%9u} {N: fork() calls}\n", sum.v_forks);
+ xo_emit("{:vforks/%9u} {N:vfork() calls}\n",
+ sum.v_vforks);
+ xo_emit("{:rforks/%9u} {N:rfork() calls}\n",
+ sum.v_rforks);
+ xo_emit("{:swap-ins/%9u} {N:swap pager pageins}\n",
+ sum.v_swapin);
+ xo_emit("{:swap-in-pages/%9u} {N:swap pager pages paged in}\n",
+ sum.v_swappgsin);
+ xo_emit("{:swap-outs/%9u} {N:swap pager pageouts}\n",
+ sum.v_swapout);
+ xo_emit("{:swap-out-pages/%9u} {N:swap pager pages paged out}\n",
+ sum.v_swappgsout);
+ xo_emit("{:vnode-page-ins/%9u} {N:vnode pager pageins}\n",
+ sum.v_vnodein);
+ xo_emit("{:vnode-page-in-pages/%9u} {N:vnode pager pages paged in}\n",
+ sum.v_vnodepgsin);
+ xo_emit("{:vnode-page-outs/%9u} {N:vnode pager pageouts}\n",
+ sum.v_vnodeout);
+ xo_emit("{:vnode-page-out-pages/%9u} {N:vnode pager pages paged out}\n",
+ sum.v_vnodepgsout);
+ xo_emit("{:page-daemon-wakeups/%9u} {N:page daemon wakeups}\n",
+ sum.v_pdwakeups);
+ xo_emit("{:page-daemon-pages/%9u} {N:pages examined by the page "
+ "daemon}\n", sum.v_pdpages);
+ xo_emit("{:page-reclamation-shortfalls/%9u} {N:clean page reclamation "
+ "shortfalls}\n", sum.v_pdshortfalls);
+ xo_emit("{:reactivated/%9u} {N:pages reactivated by the page daemon}\n",
+ sum.v_reactivated);
+ xo_emit("{:copy-on-write-faults/%9u} {N:copy-on-write faults}\n",
+ sum.v_cow_faults);
+ xo_emit("{:copy-on-write-optimized-faults/%9u} {N:copy-on-write "
+ "optimized faults}\n", sum.v_cow_optim);
+ xo_emit("{:zero-fill-pages/%9u} {N:zero fill pages zeroed}\n",
+ sum.v_zfod);
+ xo_emit("{:zero-fill-prezeroed/%9u} {N:zero fill pages prezeroed}\n",
+ sum.v_ozfod);
+ xo_emit("{:intransit-blocking/%9u} {N:intransit blocking page faults}\n",
+ sum.v_intrans);
+ xo_emit("{:total-faults/%9u} {N:total VM faults taken}\n",
+ sum.v_vm_faults);
+ xo_emit("{:faults-requiring-io/%9u} {N:page faults requiring I\\/O}\n",
+ sum.v_io_faults);
+ xo_emit("{:faults-from-thread-creation/%9u} {N:pages affected by "
+ "kernel thread creation}\n", sum.v_kthreadpages);
+ xo_emit("{:faults-from-fork/%9u} {N:pages affected by fork}()\n",
+ sum.v_forkpages);
+ xo_emit("{:faults-from-vfork/%9u} {N:pages affected by vfork}()\n",
+ sum.v_vforkpages);
+ xo_emit("{:pages-rfork/%9u} {N:pages affected by rfork}()\n",
+ sum.v_rforkpages);
+ xo_emit("{:pages-freed/%9u} {N:pages freed}\n",
+ sum.v_tfree);
+ xo_emit("{:pages-freed-by-daemon/%9u} {N:pages freed by daemon}\n",
+ sum.v_dfree);
+ xo_emit("{:pages-freed-on-exit/%9u} {N:pages freed by exiting processes}\n",
+ sum.v_pfree);
+ xo_emit("{:active-pages/%9u} {N:pages active}\n",
+ sum.v_active_count);
+ xo_emit("{:inactive-pages/%9u} {N:pages inactive}\n",
+ sum.v_inactive_count);
+ xo_emit("{:laundry-pages/%9u} {N:pages in the laundry queue}\n",
+ sum.v_laundry_count);
+ xo_emit("{:wired-pages/%9u} {N:pages wired down}\n",
+ sum.v_wire_count);
+ xo_emit("{:virtual-user-wired-pages/%9lu} {N:virtual user pages wired "
+ "down}\n", sum.v_user_wire_count);
+ xo_emit("{:nofree-pages/%9u} {N:permanently allocated pages}\n",
+ sum.v_nofree_count);
+ xo_emit("{:free-pages/%9u} {N:pages free}\n",
+ sum.v_free_count);
+ xo_emit("{:bytes-per-page/%9u} {N:bytes per page}\n", sum.v_page_size);
+ if (kd != NULL) {
+ kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats));
+ } else {
+ size = sizeof(lnchstats);
+ mysysctl("vfs.cache.nchstats", &lnchstats, &size);
+ if (size != sizeof(lnchstats))
+ xo_errx(1, "vfs.cache.nchstats size mismatch");
+ }
+ nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits +
+ lnchstats.ncs_badhits + lnchstats.ncs_falsehits +
+ lnchstats.ncs_miss + lnchstats.ncs_long;
+ xo_emit("{:total-name-lookups/%9ld} {N:total name lookups}\n",
+ nchtotal);
+ xo_emit("{P:/%9s} {N:cache hits} "
+ "({:positive-cache-hits/%ld}% pos + "
+ "{:negative-cache-hits/%ld}% {N:neg}) "
+ "system {:cache-hit-percent/%ld}% per-directory\n",
+ "", PCT(lnchstats.ncs_goodhits, nchtotal),
+ PCT(lnchstats.ncs_neghits, nchtotal),
+ PCT(lnchstats.ncs_pass2, nchtotal));
+ xo_emit("{P:/%9s} {L:deletions} {:deletions/%ld}%, "
+ "{L:falsehits} {:false-hits/%ld}%, "
+ "{L:toolong} {:too-long/%ld}%\n", "",
+ PCT(lnchstats.ncs_badhits, nchtotal),
+ PCT(lnchstats.ncs_falsehits, nchtotal),
+ PCT(lnchstats.ncs_long, nchtotal));
+ xo_close_container("summary-statistics");
+}
+
+static void
+doforkst(void)
+{
+
+ fill_vmmeter(&sum);
+ xo_open_container("fork-statistics");
+ xo_emit("{:fork/%u} {N:forks}, {:fork-pages/%u} {N:pages}, "
+ "{L:average} {:fork-average/%.2f}\n",
+ sum.v_forks, sum.v_forkpages,
+ sum.v_forks == 0 ? 0.0 :
+ (double)sum.v_forkpages / sum.v_forks);
+ xo_emit("{:vfork/%u} {N:vforks}, {:vfork-pages/%u} {N:pages}, "
+ "{L:average} {:vfork-average/%.2f}\n",
+ sum.v_vforks, sum.v_vforkpages,
+ sum.v_vforks == 0 ? 0.0 :
+ (double)sum.v_vforkpages / sum.v_vforks);
+ xo_emit("{:rfork/%u} {N:rforks}, {:rfork-pages/%u} {N:pages}, "
+ "{L:average} {:rfork-average/%.2f}\n",
+ sum.v_rforks, sum.v_rforkpages,
+ sum.v_rforks == 0 ? 0.0 :
+ (double)sum.v_rforkpages / sum.v_rforks);
+ xo_close_container("fork-statistics");
+}
+
+static void
+devstats(void)
+{
+ long double busy_seconds, transfers_per_second;
+ long tmp;
+ int di, dn, state;
+
+ for (state = 0; state < CPUSTATES; ++state) {
+ tmp = cur.cp_time[state];
+ cur.cp_time[state] -= last.cp_time[state];
+ last.cp_time[state] = tmp;
+ }
+
+ busy_seconds = cur.snap_time - last.snap_time;
+
+ xo_open_list("device");
+ for (dn = 0; dn < num_devices; dn++) {
+ if (dev_select[dn].selected == 0 ||
+ dev_select[dn].selected > maxshowdevs)
+ continue;
+
+ di = dev_select[dn].position;
+
+ if (devstat_compute_statistics(&cur.dinfo->devices[di],
+ &last.dinfo->devices[di], busy_seconds,
+ DSM_TRANSFERS_PER_SECOND, &transfers_per_second,
+ DSM_NONE) != 0)
+ xo_errx(1, "%s", devstat_errbuf);
+
+ xo_open_instance("device");
+ xo_emit("{ekq:name/%s%d}",
+ dev_select[dn].device_name,
+ dev_select[dn].unit_number);
+ xo_emit("{[:5}{h,hn-decimal,hn-1000:transfers/%ju}{]:}",
+ (uintmax_t)transfers_per_second);
+ xo_close_instance("device");
+ }
+ xo_close_list("device");
+}
+
+static void
+percent(const char *name, long pctv, int *over)
+{
+ char fmt[64];
+
+ snprintf(fmt, sizeof(fmt), " {:%s/%%%uld/%%ld}", name,
+ (*over && pctv <= 9) ? 1 : 2);
+ xo_emit(fmt, pctv);
+ if (*over && pctv <= 9)
+ (*over)--;
+ else if (pctv >= 100)
+ (*over)++;
+}
+
+static void
+cpustats(void)
+{
+ long total;
+ int state, over;
+
+ total = 0;
+ for (state = 0; state < CPUSTATES; ++state)
+ total += cur.cp_time[state];
+ if (total == 0)
+ total = 1;
+ over = 0;
+ xo_open_container("cpu-statistics");
+ percent("user", 100LL * (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) /
+ total, &over);
+ percent("system", 100LL * (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) /
+ total, &over);
+ percent("idle", 100LL * cur.cp_time[CP_IDLE] / total, &over);
+ xo_close_container("cpu-statistics");
+}
+
+static void
+pcpustats(u_long cpumask, int maxid)
+{
+ long tmp, total;
+ int i, state, over;
+
+ /* devstats does this for cp_time */
+ for (i = 0; i <= maxid; i++) {
+ if ((cpumask & (1ul << i)) == 0)
+ continue;
+ for (state = 0; state < CPUSTATES; ++state) {
+ tmp = cur_cp_times[i * CPUSTATES + state];
+ cur_cp_times[i * CPUSTATES + state] -= last_cp_times[i *
+ CPUSTATES + state];
+ last_cp_times[i * CPUSTATES + state] = tmp;
+ }
+ }
+
+ over = 0;
+ xo_open_list("cpu");
+ for (i = 0; i <= maxid; i++) {
+ if ((cpumask & (1ul << i)) == 0)
+ continue;
+ xo_open_instance("cpu");
+ xo_emit("{ke:name/%d}", i);
+ total = 0;
+ for (state = 0; state < CPUSTATES; ++state)
+ total += cur_cp_times[i * CPUSTATES + state];
+ if (total == 0)
+ total = 1;
+ percent("user",
+ 100LL * (cur_cp_times[i * CPUSTATES + CP_USER] +
+ cur_cp_times[i * CPUSTATES + CP_NICE]) / total, &over);
+ percent("system",
+ 100LL * (cur_cp_times[i * CPUSTATES + CP_SYS] +
+ cur_cp_times[i * CPUSTATES + CP_INTR]) / total, &over);
+ percent("idle",
+ 100LL * cur_cp_times[i * CPUSTATES + CP_IDLE] / total,
+ &over);
+ xo_close_instance("cpu");
+ }
+ xo_close_list("cpu");
+}
+
+static unsigned int
+read_intrcnts(unsigned long **intrcnts)
+{
+ size_t intrcntlen;
+ uintptr_t kaddr;
+
+ if (kd != NULL) {
+ kread(X_SINTRCNT, &intrcntlen, sizeof(intrcntlen));
+ if ((*intrcnts = malloc(intrcntlen)) == NULL)
+ xo_err(1, "malloc()");
+ if (namelist[X_NINTRCNT].n_type == 0)
+ kread(X_INTRCNT, *intrcnts, intrcntlen);
+ else {
+ kread(X_INTRCNT, &kaddr, sizeof(kaddr));
+ kreadptr(kaddr, *intrcnts, intrcntlen);
+ }
+ } else {
+ for (*intrcnts = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
+ *intrcnts = reallocf(*intrcnts, intrcntlen);
+ if (*intrcnts == NULL)
+ xo_err(1, "reallocf()");
+ if (mysysctl("hw.intrcnt", *intrcnts, &intrcntlen) == 0)
+ break;
+ }
+ }
+
+ return (intrcntlen / sizeof(unsigned long));
+}
+
+static void
+print_intrcnts(unsigned long *intrcnts, unsigned long *old_intrcnts,
+ char *intrnames, unsigned int nintr, size_t istrnamlen, long long period_ms)
+{
+ uint64_t inttotal, old_inttotal, total_count, total_rate;
+ unsigned long count, rate;
+ unsigned int i;
+
+ inttotal = 0;
+ old_inttotal = 0;
+ xo_open_list("interrupt");
+ for (i = 0; i < nintr; i++) {
+ if (intrnames[0] != '\0' && (*intrcnts != 0 || aflag)) {
+ count = *intrcnts - *old_intrcnts;
+ rate = ((uint64_t)count * 1000 + period_ms / 2) / period_ms;
+ xo_open_instance("interrupt");
+ xo_emit("{d:name/%-*s}{ket:name/%s} "
+ "{:total/%20lu} {:rate/%10lu}\n",
+ (int)istrnamlen, intrnames, intrnames, count, rate);
+ xo_close_instance("interrupt");
+ }
+ intrnames += strlen(intrnames) + 1;
+ inttotal += *intrcnts++;
+ old_inttotal += *old_intrcnts++;
+ }
+ total_count = inttotal - old_inttotal;
+ total_rate = (total_count * 1000 + period_ms / 2) / period_ms;
+ xo_close_list("interrupt");
+ xo_emit("{L:/%-*s} {:total-interrupts/%20ju} "
+ "{:total-rate/%10ju}\n", (int)istrnamlen,
+ "Total", (uintmax_t)total_count, (uintmax_t)total_rate);
+}
+
+static void
+dointr(unsigned int interval, int reps)
+{
+ unsigned long *intrcnts, *old_intrcnts;
+ char *intrname, *intrnames;
+ long long period_ms, old_uptime, uptime;
+ size_t clen, inamlen, istrnamlen;
+ uintptr_t kaddr;
+ unsigned int nintr;
+
+ old_intrcnts = NULL;
+ uptime = getuptime();
+
+ /* Get the names of each interrupt source */
+ if (kd != NULL) {
+ kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
+ if ((intrnames = malloc(inamlen)) == NULL)
+ xo_err(1, "malloc()");
+ if (namelist[X_NINTRCNT].n_type == 0)
+ kread(X_INTRNAMES, intrnames, inamlen);
+ else {
+ kread(X_INTRNAMES, &kaddr, sizeof(kaddr));
+ kreadptr(kaddr, intrnames, inamlen);
+ }
+ } else {
+ for (intrnames = NULL, inamlen = 1024; ; inamlen *= 2) {
+ if ((intrnames = reallocf(intrnames, inamlen)) == NULL)
+ xo_err(1, "reallocf()");
+ if (mysysctl("hw.intrnames", intrnames, &inamlen) == 0)
+ break;
+ }
+ }
+
+ /* Determine the length of the longest interrupt name */
+ intrname = intrnames;
+ istrnamlen = strlen("interrupt");
+ while (intrname < intrnames + inamlen) {
+ clen = strlen(intrname);
+ if (clen > istrnamlen)
+ istrnamlen = clen;
+ intrname += strlen(intrname) + 1;
+ }
+ xo_emit("{T:/%-*s} {T:/%20s} {T:/%10s}\n",
+ (int)istrnamlen, "interrupt", "total", "rate");
+
+ /*
+ * Loop reps times printing differential interrupt counts. If reps is
+ * zero, then run just once, printing total counts
+ */
+ xo_open_container("interrupt-statistics");
+
+ period_ms = uptime / 1000000;
+ while(1) {
+ nintr = read_intrcnts(&intrcnts);
+ /*
+ * Initialize old_intrcnts to 0 for the first pass, so
+ * print_intrcnts will print total interrupts since boot
+ */
+ if (old_intrcnts == NULL) {
+ old_intrcnts = calloc(nintr, sizeof(unsigned long));
+ if (old_intrcnts == NULL)
+ xo_err(1, "calloc()");
+ }
+
+ print_intrcnts(intrcnts, old_intrcnts, intrnames, nintr,
+ istrnamlen, period_ms);
+ if (xo_flush() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+
+ free(old_intrcnts);
+ old_intrcnts = intrcnts;
+ if (reps >= 0 && --reps <= 0)
+ break;
+ usleep(interval * 1000);
+ old_uptime = uptime;
+ uptime = getuptime();
+ period_ms = (uptime - old_uptime) / 1000000;
+ }
+
+ xo_close_container("interrupt-statistics");
+}
+
+static void
+domemstat_malloc(void)
+{
+ struct memory_type_list *mtlp;
+ struct memory_type *mtp;
+ size_t i, zones;
+ int error, first;
+
+ mtlp = memstat_mtl_alloc();
+ if (mtlp == NULL) {
+ xo_warn("memstat_mtl_alloc");
+ return;
+ }
+ if (kd == NULL) {
+ if (memstat_sysctl_malloc(mtlp, 0) < 0) {
+ xo_warnx("memstat_sysctl_malloc: %s",
+ memstat_strerror(memstat_mtl_geterror(mtlp)));
+ return;
+ }
+ } else {
+ if (memstat_kvm_malloc(mtlp, kd) < 0) {
+ error = memstat_mtl_geterror(mtlp);
+ if (error == MEMSTAT_ERROR_KVM)
+ xo_warnx("memstat_kvm_malloc: %s",
+ kvm_geterr(kd));
+ else
+ xo_warnx("memstat_kvm_malloc: %s",
+ memstat_strerror(error));
+ }
+ }
+ xo_open_container("malloc-statistics");
+ xo_emit("{T:/%16s} {T:/%4s} {T:/%5s} {T:/%3s} {T:Size(s)}\n",
+ "Type", "Use", "Memory", "Req");
+ xo_open_list("memory");
+ zones = memstat_malloc_zone_get_count();
+ for (mtp = memstat_mtl_first(mtlp); mtp != NULL;
+ mtp = memstat_mtl_next(mtp)) {
+ if (memstat_get_numallocs(mtp) == 0 &&
+ memstat_get_count(mtp) == 0)
+ continue;
+ xo_open_instance("memory");
+ xo_emit("{k:type/%16s/%s} "
+ "{[:4}{h,hn-decimal,hn-1000:in-use/%ju}{]:} "
+ "{[:5}{h,hn-decimal:memory-use/%ju}{]:} "
+ "{[:4}{h,hn-decimal,hn-1000:requests/%ju}{]:} ",
+ memstat_get_name(mtp), (uintmax_t)memstat_get_count(mtp),
+ (uintmax_t)memstat_get_bytes(mtp),
+ (uintmax_t)memstat_get_numallocs(mtp));
+ first = 1;
+ xo_open_list("size");
+ for (i = 0; i < zones; i++) {
+ if (memstat_malloc_zone_used(mtp, i)) {
+ if (!first)
+ xo_emit(",");
+ xo_emit("{lh:size/%d}", memstat_malloc_zone_get_size(i));
+ first = 0;
+ }
+ }
+ xo_close_list("size");
+ xo_close_instance("memory");
+ xo_emit("\n");
+ }
+ xo_close_list("memory");
+ xo_close_container("malloc-statistics");
+ memstat_mtl_free(mtlp);
+}
+
+static void
+domemstat_zone(void)
+{
+ struct memory_type_list *mtlp;
+ struct memory_type *mtp;
+ int error, len;
+
+ mtlp = memstat_mtl_alloc();
+ if (mtlp == NULL) {
+ xo_warn("memstat_mtl_alloc");
+ return;
+ }
+ if (kd == NULL) {
+ if (memstat_sysctl_uma(mtlp, 0) < 0) {
+ xo_warnx("memstat_sysctl_uma: %s",
+ memstat_strerror(memstat_mtl_geterror(mtlp)));
+ return;
+ }
+ } else {
+ if (memstat_kvm_uma(mtlp, kd) < 0) {
+ error = memstat_mtl_geterror(mtlp);
+ if (error == MEMSTAT_ERROR_KVM)
+ xo_warnx("memstat_kvm_uma: %s",
+ kvm_geterr(kd));
+ else
+ xo_warnx("memstat_kvm_uma: %s",
+ memstat_strerror(error));
+ }
+ }
+ xo_open_container("memory-zone-statistics");
+ xo_emit("{T:/%-19s} {T:/%7s} {T:/%7s} {T:/%8s} {T:/%8s} {T:/%8s} "
+ "{T:/%4s} {T:/%4s} {T:/%4s}\n", "ITEM", "SIZE",
+ "LIMIT", "USED", "FREE", "REQ", "FAIL", "SLEEP", "XDOM");
+ xo_open_list("zone");
+ for (mtp = memstat_mtl_first(mtlp); mtp != NULL;
+ mtp = memstat_mtl_next(mtp)) {
+ len = strlen(memstat_get_name(mtp));
+ xo_open_instance("zone");
+ xo_emit("{k:name/%s}:{d:size/%*ju}{e:size/%ju},"
+ "{:limit/%7ju},{:used/%8ju},"
+ "{:free/%8ju},{:requests/%8ju},"
+ "{:fail/%4ju},{:sleep/%4ju},{:xdomain/%4ju}\n",
+ memstat_get_name(mtp), MAX(1, 26 - len),
+ (uintmax_t)memstat_get_size(mtp),
+ (uintmax_t)memstat_get_size(mtp),
+ (uintmax_t)memstat_get_countlimit(mtp),
+ (uintmax_t)memstat_get_count(mtp),
+ (uintmax_t)memstat_get_free(mtp),
+ (uintmax_t)memstat_get_numallocs(mtp),
+ (uintmax_t)memstat_get_failures(mtp),
+ (uintmax_t)memstat_get_sleeps(mtp),
+ (uintmax_t)memstat_get_xdomain(mtp));
+ xo_close_instance("zone");
+ }
+ memstat_mtl_free(mtlp);
+ xo_close_list("zone");
+ xo_close_container("memory-zone-statistics");
+}
+
+static void
+display_object(struct kinfo_vmobject *kvo)
+{
+ const char *str;
+
+ xo_open_instance("object");
+ xo_emit("{:resident/%5ju} ", (uintmax_t)kvo->kvo_resident);
+ xo_emit("{:active/%5ju} ", (uintmax_t)kvo->kvo_active);
+ xo_emit("{:inactive/%5ju} ", (uintmax_t)kvo->kvo_inactive);
+ xo_emit("{:laundry/%5ju} ", (uintmax_t)kvo->kvo_laundry);
+ xo_emit("{:refcount/%3d} ", kvo->kvo_ref_count);
+ xo_emit("{:shadowcount/%3d} ", kvo->kvo_shadow_count);
+
+#define MEMATTR_STR(type, val) \
+ if (kvo->kvo_memattr == (type)) { \
+ str = (val); \
+ } else
+#ifdef VM_MEMATTR_UNCACHEABLE
+ MEMATTR_STR(VM_MEMATTR_UNCACHEABLE, "UC")
+#endif
+#ifdef VM_MEMATTR_WRITE_COMBINING
+ MEMATTR_STR(VM_MEMATTR_WRITE_COMBINING, "WC")
+#endif
+#ifdef VM_MEMATTR_WRITE_THROUGH
+ MEMATTR_STR(VM_MEMATTR_WRITE_THROUGH, "WT")
+#endif
+#ifdef VM_MEMATTR_WRITE_PROTECTED
+ MEMATTR_STR(VM_MEMATTR_WRITE_PROTECTED, "WP")
+#endif
+#ifdef VM_MEMATTR_WRITE_BACK
+ MEMATTR_STR(VM_MEMATTR_WRITE_BACK, "WB")
+#endif
+#ifdef VM_MEMATTR_WEAK_UNCACHEABLE
+ MEMATTR_STR(VM_MEMATTR_WEAK_UNCACHEABLE, "UC-")
+#endif
+#ifdef VM_MEMATTR_WB_WA
+ MEMATTR_STR(VM_MEMATTR_WB_WA, "WB")
+#endif
+#ifdef VM_MEMATTR_NOCACHE
+ MEMATTR_STR(VM_MEMATTR_NOCACHE, "NC")
+#endif
+#ifdef VM_MEMATTR_DEVICE
+ MEMATTR_STR(VM_MEMATTR_DEVICE, "DEV")
+#endif
+#ifdef VM_MEMATTR_DEVICE_NP
+ MEMATTR_STR(VM_MEMATTR_DEVICE, "NP")
+#endif
+#ifdef VM_MEMATTR_CACHEABLE
+ MEMATTR_STR(VM_MEMATTR_CACHEABLE, "C")
+#endif
+#ifdef VM_MEMATTR_PREFETCHABLE
+ MEMATTR_STR(VM_MEMATTR_PREFETCHABLE, "PRE")
+#endif
+ {
+ str = "??";
+ }
+#undef MEMATTR_STR
+ xo_emit("{:attribute/%-3s} ", str);
+ switch (kvo->kvo_type) {
+ case KVME_TYPE_NONE:
+ str = "--";
+ break;
+ case KVME_TYPE_DEFAULT:
+ str = "df";
+ break;
+ case KVME_TYPE_VNODE:
+ str = "vn";
+ break;
+ case KVME_TYPE_SWAP:
+ str = "sw";
+ break;
+ case KVME_TYPE_DEVICE:
+ str = "dv";
+ break;
+ case KVME_TYPE_PHYS:
+ str = "ph";
+ break;
+ case KVME_TYPE_DEAD:
+ str = "dd";
+ break;
+ case KVME_TYPE_SG:
+ str = "sg";
+ break;
+ case KVME_TYPE_MGTDEVICE:
+ str = "md";
+ break;
+ case KVME_TYPE_UNKNOWN:
+ default:
+ str = "??";
+ break;
+ }
+ xo_emit("{:type/%-2s} ", str);
+ if ((kvo->kvo_flags & KVMO_FLAG_SYSVSHM) != 0)
+ xo_emit("{:sysvshm/sysvshm(%ju:%u)} ",
+ (uintmax_t)kvo->kvo_vn_fileid, kvo->kvo_vn_fsid_freebsd11);
+ if ((kvo->kvo_flags & KVMO_FLAG_POSIXSHM) != 0)
+ xo_emit("{:posixshm/posixshm@/posixshm}");
+ xo_emit("{:path/%-s}\n", kvo->kvo_path);
+ xo_close_instance("object");
+}
+
+static void
+doobjstat(void)
+{
+ struct kinfo_vmobject *kvo;
+ int cnt, i;
+
+ kvo = kinfo_getvmobject(&cnt);
+ if (kvo == NULL) {
+ xo_warn("Failed to fetch VM object list");
+ return;
+ }
+ xo_emit("{T:RES/%5s} {T:ACT/%5s} {T:INACT/%5s} {T:LAUND/%5s} "
+ "{T:REF/%3s} {T:SHD/%3s} {T:CM/%2s} {T:TP/%3s} {T:PATH/%s}\n");
+ xo_open_list("object");
+ for (i = 0; i < cnt; i++)
+ display_object(&kvo[i]);
+ free(kvo);
+ xo_close_list("object");
+}
+
+/*
+ * kread reads something from the kernel, given its nlist index.
+ */
+static void
+kreado(int nlx, void *addr, size_t size, size_t offset)
+{
+ const char *sym;
+
+ if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
+ sym = namelist[nlx].n_name;
+ if (*sym == '_')
+ ++sym;
+ xo_errx(1, "symbol %s not defined", sym);
+ }
+ if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr,
+ size) != size) {
+ sym = namelist[nlx].n_name;
+ if (*sym == '_')
+ ++sym;
+ xo_errx(1, "%s: %s", sym, kvm_geterr(kd));
+ }
+}
+
+static void
+kread(int nlx, void *addr, size_t size)
+{
+
+ kreado(nlx, addr, size, 0);
+}
+
+static void
+kreadptr(uintptr_t addr, void *buf, size_t size)
+{
+
+ if ((size_t)kvm_read(kd, addr, buf, size) != size)
+ xo_errx(1, "%s", kvm_geterr(kd));
+}
+
+static void __dead2
+usage(void)
+{
+ xo_error("%s%s",
+ "usage: vmstat [-afHhimoPsz] [-M core [-N system]] [-c count] [-n devs]\n",
+ " [-p type,if,pass] [-w wait] [disks] [wait [count]]\n");
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/vtfontcvt/Makefile b/usr.bin/vtfontcvt/Makefile
new file mode 100644
index 000000000000..de011660ca28
--- /dev/null
+++ b/usr.bin/vtfontcvt/Makefile
@@ -0,0 +1,9 @@
+PROG= vtfontcvt
+SRCS= vtfontcvt.c lz4.c
+MAN8= vtfontcvt.8
+
+# lz4 compression functionality
+.PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
+CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/vtfontcvt/Makefile.depend b/usr.bin/vtfontcvt/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/vtfontcvt/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/vtfontcvt/vtfontcvt.8 b/usr.bin/vtfontcvt/vtfontcvt.8
new file mode 100644
index 000000000000..1e643f175668
--- /dev/null
+++ b/usr.bin/vtfontcvt/vtfontcvt.8
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2014 The FreeBSD Foundation.
+.\"
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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 July 19, 2022
+.Dt VTFONTCVT 8
+.Os
+.Sh NAME
+.Nm vtfontcvt
+.Nd "convert font files for use by the video console"
+.Sh SYNOPSIS
+.Nm
+.Op Fl nv
+.Op Fl f Ar format
+.Op Fl h Ar height
+.Op Fl w Ar width
+.Fl o Ar output_file
+.Ar normal_font
+.Op Ar bold_font
+.Sh DESCRIPTION
+The
+.Nm
+utility reads source font files in either BDF or Unifont HEX format and
+outputs a file in one of the available output formats.
+.Pp
+HEX format files
+.Po Ar normal_font
+and
+.Ar bold_font Pc
+must have the file extension
+.Pa .hex .
+.Pp
+The following options are available:
+.Bl -tag -width "-o output_file"
+.It Fl f Ar format
+Specify the output format.
+Available formats are:
+.Bl -tag -width "compressed-source"
+.It Cm compressed-source
+C source with font data compressed by using LZ4 compression method.
+.It Cm font
+A binary font file
+.Pq default .
+.It Cm source
+C source.
+.El
+.Pp
+The output in C source is intended to be used to embed the font into program
+binary.
+.Pp
+The binary font file is for use by
+.Xr vt 4 .
+.It Fl h Ar height
+Set font height.
+The default is 16.
+Font height is set automatically for BDF files and for HEX files that have a
+.D1 # Height: Ar height
+comment before any font data.
+.It Fl n
+Do not apply output filtering with C source output.
+.It Fl o Ar output_file
+Specify the name for the output file.
+.It Fl v
+Display verbose statistics about the converted font.
+.It Fl w Ar width
+Set font width.
+The default is 8.
+Font width is set automatically for BDF files and for HEX files that have a
+.D1 # Width: Ar width
+comment before any font data.
+.El
+.Sh SEE ALSO
+.Xr vidcontrol 1 ,
+.Xr vt 4
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 10.1 .
diff --git a/usr.bin/vtfontcvt/vtfontcvt.c b/usr.bin/vtfontcvt/vtfontcvt.c
new file mode 100644
index 000000000000..773072813d8a
--- /dev/null
+++ b/usr.bin/vtfontcvt/vtfontcvt.c
@@ -0,0 +1,1120 @@
+/*-
+ * Copyright (c) 2009, 2014 The FreeBSD Foundation
+ *
+ * This software was developed by Ed Schouten under sponsorship from the
+ * FreeBSD Foundation.
+ *
+ * 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 AUTHOR 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 AUTHOR 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/endian.h>
+#include <sys/fnv_hash.h>
+#include <sys/font.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <err.h>
+#include <lz4.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define VFNT_MAXGLYPHS 131072
+#define VFNT_MAXDIMENSION 128
+
+static unsigned int width = 8, wbytes, height = 16;
+
+struct glyph {
+ TAILQ_ENTRY(glyph) g_list;
+ SLIST_ENTRY(glyph) g_hash;
+ uint8_t *g_data;
+ unsigned int g_index;
+};
+
+#define FONTCVT_NHASH 4096
+TAILQ_HEAD(glyph_list, glyph);
+static SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH];
+static struct glyph_list glyphs[VFNT_MAPS] = {
+ TAILQ_HEAD_INITIALIZER(glyphs[0]),
+ TAILQ_HEAD_INITIALIZER(glyphs[1]),
+ TAILQ_HEAD_INITIALIZER(glyphs[2]),
+ TAILQ_HEAD_INITIALIZER(glyphs[3]),
+};
+static unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe;
+
+struct mapping {
+ TAILQ_ENTRY(mapping) m_list;
+ unsigned int m_char;
+ unsigned int m_length;
+ struct glyph *m_glyph;
+};
+
+TAILQ_HEAD(mapping_list, mapping);
+static struct mapping_list maps[VFNT_MAPS] = {
+ TAILQ_HEAD_INITIALIZER(maps[0]),
+ TAILQ_HEAD_INITIALIZER(maps[1]),
+ TAILQ_HEAD_INITIALIZER(maps[2]),
+ TAILQ_HEAD_INITIALIZER(maps[3]),
+};
+static unsigned int mapping_total, map_count[4], map_folded_count[4],
+ mapping_unique, mapping_dupe;
+
+enum output_format {
+ VT_FONT, /* default */
+ VT_C_SOURCE, /* C source for built in fonts */
+ VT_C_COMPRESSED /* C source with compressed font data */
+};
+
+struct whitelist {
+ uint32_t c;
+ uint32_t len;
+};
+
+/*
+ * Compressed font glyph list. To be used with boot loader, we need to have
+ * ascii set and box drawing chars.
+ */
+static struct whitelist c_list[] = {
+ { .c = 0, .len = 0 }, /* deault char */
+ { .c = 0x20, .len = 0x5f },
+ { .c = 0x2500, .len = 0 }, /* single frame */
+ { .c = 0x2502, .len = 0 },
+ { .c = 0x250c, .len = 0 },
+ { .c = 0x2510, .len = 0 },
+ { .c = 0x2514, .len = 0 },
+ { .c = 0x2518, .len = 0 },
+ { .c = 0x2550, .len = 1 }, /* double frame */
+ { .c = 0x2554, .len = 0 },
+ { .c = 0x2557, .len = 0 },
+ { .c = 0x255a, .len = 0 },
+ { .c = 0x255d, .len = 0 },
+};
+
+/*
+ * Uncompressed source. For x86 we need cp437 so the vga text mode
+ * can program font into the vga card.
+ */
+static struct whitelist s_list[] = {
+ { .c = 0, .len = 0 }, /* deault char */
+ { .c = 0x20, .len = 0x5f }, /* ascii set */
+ { .c = 0xA0, .len = 0x5f }, /* latin 1 */
+ { .c = 0x0192, .len = 0 },
+ { .c = 0x0332, .len = 0 }, /* composing lower line */
+ { .c = 0x0393, .len = 0 },
+ { .c = 0x0398, .len = 0 },
+ { .c = 0x03A3, .len = 0 },
+ { .c = 0x03A6, .len = 0 },
+ { .c = 0x03A9, .len = 0 },
+ { .c = 0x03B1, .len = 1 },
+ { .c = 0x03B4, .len = 0 },
+ { .c = 0x03C0, .len = 0 },
+ { .c = 0x03C3, .len = 0 },
+ { .c = 0x03C4, .len = 0 },
+ { .c = 0x207F, .len = 0 },
+ { .c = 0x20A7, .len = 0 },
+ { .c = 0x2205, .len = 0 },
+ { .c = 0x220A, .len = 0 },
+ { .c = 0x2219, .len = 1 },
+ { .c = 0x221E, .len = 0 },
+ { .c = 0x2229, .len = 0 },
+ { .c = 0x2248, .len = 0 },
+ { .c = 0x2261, .len = 0 },
+ { .c = 0x2264, .len = 1 },
+ { .c = 0x2310, .len = 0 },
+ { .c = 0x2320, .len = 1 },
+ { .c = 0x2500, .len = 0 },
+ { .c = 0x2502, .len = 0 },
+ { .c = 0x250C, .len = 0 },
+ { .c = 0x2510, .len = 0 },
+ { .c = 0x2514, .len = 0 },
+ { .c = 0x2518, .len = 0 },
+ { .c = 0x251C, .len = 0 },
+ { .c = 0x2524, .len = 0 },
+ { .c = 0x252C, .len = 0 },
+ { .c = 0x2534, .len = 0 },
+ { .c = 0x253C, .len = 0 },
+ { .c = 0x2550, .len = 0x1c },
+ { .c = 0x2580, .len = 0 },
+ { .c = 0x2584, .len = 0 },
+ { .c = 0x2588, .len = 0 },
+ { .c = 0x258C, .len = 0 },
+ { .c = 0x2590, .len = 3 },
+ { .c = 0x25A0, .len = 0 },
+};
+
+static bool filter = true;
+static enum output_format format = VT_FONT;
+/* Type for write callback. */
+typedef size_t (*vt_write)(const void *, size_t, size_t, FILE *);
+static uint8_t *uncompressed;
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: vtfontcvt "
+ "[-nv] [-f format] [-h height] [-w width]\n"
+ "\t-o output_file normal_font [bold_font]\n");
+ exit(1);
+}
+
+static void *
+xmalloc(size_t size)
+{
+ void *m;
+
+ if ((m = calloc(1, size)) == NULL)
+ errx(1, "memory allocation failure");
+ return (m);
+}
+
+static int
+add_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx)
+{
+ struct mapping *mp, *mp_temp;
+ struct mapping_list *ml;
+
+ mapping_total++;
+
+ mp = xmalloc(sizeof *mp);
+ mp->m_char = c;
+ mp->m_glyph = gl;
+ mp->m_length = 0;
+
+ ml = &maps[map_idx];
+ if (TAILQ_LAST(ml, mapping_list) == NULL ||
+ TAILQ_LAST(ml, mapping_list)->m_char < c) {
+ /* Common case: empty list or new char at end of list. */
+ TAILQ_INSERT_TAIL(ml, mp, m_list);
+ } else {
+ /* Find insertion point for char; cannot be at end. */
+ TAILQ_FOREACH(mp_temp, ml, m_list) {
+ if (mp_temp->m_char >= c) {
+ TAILQ_INSERT_BEFORE(mp_temp, mp, m_list);
+ break;
+ }
+ }
+ }
+
+ map_count[map_idx]++;
+ mapping_unique++;
+
+ return (0);
+}
+
+static int
+dedup_mapping(unsigned int map_idx)
+{
+ struct mapping *mp_bold, *mp_normal, *mp_temp;
+ unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD;
+
+ assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RIGHT);
+ mp_normal = TAILQ_FIRST(&maps[normal_map_idx]);
+ TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) {
+ while (mp_normal->m_char < mp_bold->m_char)
+ mp_normal = TAILQ_NEXT(mp_normal, m_list);
+ if (mp_bold->m_char != mp_normal->m_char)
+ errx(1, "Character %u not in normal font!",
+ mp_bold->m_char);
+ if (mp_bold->m_glyph != mp_normal->m_glyph)
+ continue;
+
+ /* No mapping is needed if it's equal to the normal mapping. */
+ TAILQ_REMOVE(&maps[map_idx], mp_bold, m_list);
+ free(mp_bold);
+ mapping_dupe++;
+ }
+ return (0);
+}
+
+static struct glyph *
+add_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback)
+{
+ struct glyph *gl;
+ int hash;
+
+ glyph_total++;
+ glyph_count[map_idx]++;
+
+ /* Return existing glyph if we have an identical one. */
+ hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH;
+ SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) {
+ if (memcmp(gl->g_data, bytes, wbytes * height) == 0) {
+ glyph_dupe++;
+ return (gl);
+ }
+ }
+
+ /* Allocate new glyph. */
+ gl = xmalloc(sizeof *gl);
+ gl->g_data = xmalloc(wbytes * height);
+ memcpy(gl->g_data, bytes, wbytes * height);
+ if (fallback)
+ TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list);
+ else
+ TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list);
+ SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash);
+
+ glyph_unique++;
+ if (glyph_unique > VFNT_MAXGLYPHS)
+ errx(1, "too many glyphs (%u)", glyph_unique);
+ return (gl);
+}
+
+static bool
+check_whitelist(unsigned c)
+{
+ struct whitelist *w = NULL;
+ int i, n = 0;
+
+ if (filter == false)
+ return (true);
+
+ if (format == VT_C_SOURCE) {
+ w = s_list;
+ n = sizeof(s_list) / sizeof(s_list[0]);
+ }
+ if (format == VT_C_COMPRESSED) {
+ w = c_list;
+ n = sizeof(c_list) / sizeof(c_list[0]);
+ }
+ if (w == NULL)
+ return (true);
+ for (i = 0; i < n; i++) {
+ if (c >= w[i].c && c <= w[i].c + w[i].len)
+ return (true);
+ }
+ return (false);
+}
+
+static int
+add_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r)
+{
+ struct glyph *gl;
+
+ /* Prevent adding two glyphs for 0xFFFD */
+ if (curchar == 0xFFFD) {
+ if (map_idx < VFNT_MAP_BOLD)
+ gl = add_glyph(bytes, 0, 1);
+ } else if (filter == false || curchar >= 0x20) {
+ gl = add_glyph(bytes, map_idx, 0);
+ if (add_mapping(gl, curchar, map_idx) != 0)
+ return (1);
+ if (bytes_r != NULL) {
+ gl = add_glyph(bytes_r, map_idx + 1, 0);
+ if (add_mapping(gl, curchar, map_idx + 1) != 0)
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Right-shift glyph row.
+ */
+static void
+rshift_row(uint8_t *buf, size_t len, size_t shift)
+{
+ ssize_t i, off_byte = shift / 8;
+ size_t off_bit = shift % 8;
+
+ if (shift == 0)
+ return;
+ for (i = len - 1; i >= 0; i--)
+ buf[i] = (i >= off_byte ? buf[i - off_byte] >> off_bit : 0) |
+ (i > off_byte ? buf[i - off_byte - 1] << (8 - off_bit) : 0);
+}
+
+/*
+ * Split double-width characters into left and right half. Single-width
+ * characters in _left_ only.
+ */
+static int
+split_row(uint8_t *left, uint8_t *right, uint8_t *line, size_t w)
+{
+ size_t s, i;
+
+ s = wbytes * 8 - width;
+
+ memcpy(left, line, wbytes);
+ *(left + wbytes - 1) &= 0xFF << s;
+
+ if (w > width) { /* Double-width character. */
+ uint8_t t;
+
+ for (i = 0; i < wbytes; i++) {
+ t = *(line + wbytes + i - 1);
+ t <<= 8 - s;
+ t |= *(line + wbytes + i) >> s;
+ *(right + i) = t;
+ }
+ *(right + wbytes - 1) &= 0xFF << s;
+ }
+ return (0);
+}
+
+static void
+set_height(int h)
+{
+ if (h <= 0 || h > VFNT_MAXDIMENSION)
+ errx(1, "invalid height %d", h);
+ height = h;
+}
+
+static void
+set_width(int w)
+{
+ if (w <= 0 || w > VFNT_MAXDIMENSION)
+ errx(1, "invalid width %d", w);
+ width = w;
+ wbytes = howmany(width, 8);
+}
+
+static int
+parse_bdf(FILE *fp, unsigned int map_idx)
+{
+ char *ln, *p;
+ size_t length;
+ uint8_t *line, *bytes, *bytes_r;
+ unsigned int curchar = 0, i, j, linenum = 0, bbwbytes;
+ int bbw, bbh, bbox, bboy; /* Glyph bounding box. */
+ int fbbw = 0, fbbh, fbbox, fbboy; /* Font bounding box. */
+ int dwidth = 0, dwy = 0;
+ int rv = -1;
+ char spc = '\0';
+
+ /*
+ * Step 1: Parse FONT logical font descriptor and FONTBOUNDINGBOX
+ * bounding box.
+ */
+ while ((ln = fgetln(fp, &length)) != NULL) {
+ linenum++;
+ ln[length - 1] = '\0';
+
+ if (strncmp(ln, "FONT ", 5) == 0) {
+ p = ln + 5;
+ i = 0;
+ while ((p = strchr(p, '-')) != NULL) {
+ p++;
+ i++;
+ if (i == 11) {
+ spc = *p;
+ break;
+ }
+ }
+ } else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0) {
+ if (sscanf(ln + 16, "%d %d %d %d", &fbbw, &fbbh, &fbbox,
+ &fbboy) != 4)
+ errx(1, "invalid FONTBOUNDINGBOX at line %u",
+ linenum);
+ set_width(fbbw);
+ set_height(fbbh);
+ break;
+ }
+ }
+ if (fbbw == 0)
+ errx(1, "broken font header");
+ if (spc != 'c' && spc != 'C')
+ errx(1, "font spacing \"C\" (character cell) required");
+
+ /* Step 2: Validate DWIDTH (Device Width) of all glyphs. */
+ while ((ln = fgetln(fp, &length)) != NULL) {
+ linenum++;
+ ln[length - 1] = '\0';
+
+ if (strncmp(ln, "DWIDTH ", 7) == 0) {
+ if (sscanf(ln + 7, "%d %d", &dwidth, &dwy) != 2)
+ errx(1, "invalid DWIDTH at line %u", linenum);
+ if (dwy != 0 || (dwidth != fbbw && dwidth * 2 != fbbw))
+ errx(1, "bitmap with unsupported DWIDTH %d %d (not %d or %d) at line %u",
+ dwidth, dwy, fbbw, 2 * fbbw, linenum);
+ if (dwidth < fbbw)
+ set_width(dwidth);
+ }
+ }
+
+ /* Step 3: Restart at the beginning of the file and read glyph data. */
+ dwidth = bbw = bbh = 0;
+ rewind(fp);
+ linenum = 0;
+ bbwbytes = 0; /* GCC 4.2.1 "may be used uninitialized" workaround. */
+ bytes = xmalloc(wbytes * height);
+ bytes_r = xmalloc(wbytes * height);
+ line = xmalloc(wbytes * 2);
+ while ((ln = fgetln(fp, &length)) != NULL) {
+ linenum++;
+ ln[length - 1] = '\0';
+
+ if (strncmp(ln, "ENCODING ", 9) == 0) {
+ curchar = atoi(ln + 9);
+ } else if (strncmp(ln, "DWIDTH ", 7) == 0) {
+ dwidth = atoi(ln + 7);
+ } else if (strncmp(ln, "BBX ", 4) == 0) {
+ if (sscanf(ln + 4, "%d %d %d %d", &bbw, &bbh, &bbox,
+ &bboy) != 4)
+ errx(1, "invalid BBX at line %u", linenum);
+ if (bbw < 1 || bbh < 1 || bbw > fbbw || bbh > fbbh ||
+ bbox < fbbox || bboy < fbboy ||
+ bbh + bboy > fbbh + fbboy)
+ errx(1, "broken bitmap with BBX %d %d %d %d at line %u",
+ bbw, bbh, bbox, bboy, linenum);
+ bbwbytes = howmany(bbw, 8);
+ } else if (strncmp(ln, "BITMAP", 6) == 0 &&
+ (ln[6] == ' ' || ln[6] == '\0')) {
+ if (dwidth == 0 || bbw == 0 || bbh == 0)
+ errx(1, "broken char header at line %u!",
+ linenum);
+ memset(bytes, 0, wbytes * height);
+ memset(bytes_r, 0, wbytes * height);
+
+ /*
+ * Assume that the next _bbh_ lines are bitmap data.
+ * ENDCHAR is allowed to terminate the bitmap
+ * early but is not otherwise checked; any extra data
+ * is ignored.
+ */
+ for (i = (fbbh + fbboy) - (bbh + bboy);
+ i < (unsigned int)((fbbh + fbboy) - bboy); i++) {
+ if ((ln = fgetln(fp, &length)) == NULL)
+ errx(1, "unexpected EOF");
+ linenum++;
+ ln[length - 1] = '\0';
+ if (strcmp(ln, "ENDCHAR") == 0)
+ break;
+ if (strlen(ln) < bbwbytes * 2)
+ errx(1, "broken bitmap at line %u",
+ linenum);
+ memset(line, 0, wbytes * 2);
+ for (j = 0; j < bbwbytes; j++) {
+ unsigned int val;
+ if (sscanf(ln + j * 2, "%2x", &val) ==
+ 0)
+ break;
+ *(line + j) = (uint8_t)val;
+ }
+
+ rshift_row(line, wbytes * 2, bbox - fbbox);
+ rv = split_row(bytes + i * wbytes,
+ bytes_r + i * wbytes, line, dwidth);
+ if (rv != 0)
+ goto out;
+ }
+
+ if (check_whitelist(curchar) == true) {
+ rv = add_char(curchar, map_idx, bytes,
+ dwidth > (int)width ? bytes_r : NULL);
+ if (rv != 0)
+ goto out;
+ }
+
+ dwidth = bbw = bbh = 0;
+ }
+ }
+
+out:
+ free(bytes);
+ free(bytes_r);
+ free(line);
+ return (rv);
+}
+
+static int
+parse_hex(FILE *fp, unsigned int map_idx)
+{
+ char *ln, *p;
+ size_t length;
+ uint8_t *bytes = NULL, *bytes_r = NULL, *line = NULL;
+ unsigned curchar = 0, gwidth, gwbytes, i, j, chars_per_row;
+ int rv = 0;
+
+ while ((ln = fgetln(fp, &length)) != NULL) {
+ ln[length - 1] = '\0';
+
+ if (strncmp(ln, "# Height: ", 10) == 0) {
+ if (bytes != NULL)
+ errx(1, "malformed input: Height tag after font data");
+ set_height(atoi(ln + 10));
+ } else if (strncmp(ln, "# Width: ", 9) == 0) {
+ if (bytes != NULL)
+ errx(1, "malformed input: Width tag after font data");
+ set_width(atoi(ln + 9));
+ } else if (sscanf(ln, "%6x:", &curchar) == 1) {
+ if (bytes == NULL) {
+ bytes = xmalloc(wbytes * height);
+ bytes_r = xmalloc(wbytes * height);
+ line = xmalloc(wbytes * 2);
+ }
+ /* ln is guaranteed to have a colon here. */
+ p = strchr(ln, ':') + 1;
+ chars_per_row = strlen(p) / height;
+ if (chars_per_row < wbytes * 2)
+ errx(1,
+ "malformed input: broken bitmap, character %06x",
+ curchar);
+ gwidth = width * 2;
+ gwbytes = howmany(gwidth, 8);
+ if (chars_per_row < gwbytes * 2 || gwidth <= 8) {
+ gwidth = width; /* Single-width character. */
+ gwbytes = wbytes;
+ }
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < gwbytes; j++) {
+ unsigned int val;
+ if (sscanf(p + j * 2, "%2x", &val) == 0)
+ break;
+ *(line + j) = (uint8_t)val;
+ }
+ rv = split_row(bytes + i * wbytes,
+ bytes_r + i * wbytes, line, gwidth);
+ if (rv != 0)
+ goto out;
+ p += gwbytes * 2;
+ }
+
+ if (check_whitelist(curchar) == true) {
+ rv = add_char(curchar, map_idx, bytes,
+ gwidth != width ? bytes_r : NULL);
+ if (rv != 0)
+ goto out;
+ }
+ }
+ }
+out:
+ free(bytes);
+ free(bytes_r);
+ free(line);
+ return (rv);
+}
+
+static int
+parse_file(const char *filename, unsigned int map_idx)
+{
+ FILE *fp;
+ size_t len;
+ int rv;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ perror(filename);
+ return (1);
+ }
+ len = strlen(filename);
+ if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0)
+ rv = parse_hex(fp, map_idx);
+ else
+ rv = parse_bdf(fp, map_idx);
+ fclose(fp);
+ return (rv);
+}
+
+static void
+number_glyphs(void)
+{
+ struct glyph *gl;
+ unsigned int i, idx = 0;
+
+ for (i = 0; i < VFNT_MAPS; i++)
+ TAILQ_FOREACH(gl, &glyphs[i], g_list)
+ gl->g_index = idx++;
+}
+
+/* Note we only deal with byte stream here. */
+static size_t
+write_glyph_source(const void *ptr, size_t size, size_t nitems, FILE *stream)
+{
+ const uint8_t *data = ptr;
+ size_t i;
+
+ size *= nitems;
+ for (i = 0; i < size; i++) {
+ if ((i % wbytes) == 0) {
+ if (fprintf(stream, "\n") < 0)
+ return (0);
+ }
+ if (fprintf(stream, "0x%02x, ", data[i]) < 0)
+ return (0);
+ }
+ if (fprintf(stream, "\n") < 0)
+ nitems = 0;
+
+ return (nitems);
+}
+
+/* Write to buffer */
+static size_t
+write_glyph_buf(const void *ptr, size_t size, size_t nitems,
+ FILE *stream __unused)
+{
+ static size_t index = 0;
+
+ size *= nitems;
+ (void) memmove(uncompressed + index, ptr, size);
+ index += size;
+
+ return (nitems);
+}
+
+static int
+write_glyphs(FILE *fp, vt_write cb)
+{
+ struct glyph *gl;
+ unsigned int i;
+
+ for (i = 0; i < VFNT_MAPS; i++) {
+ TAILQ_FOREACH(gl, &glyphs[i], g_list)
+ if (cb(gl->g_data, wbytes * height, 1, fp) != 1)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+fold_mappings(unsigned int map_idx)
+{
+ struct mapping_list *ml = &maps[map_idx];
+ struct mapping *mn, *mp, *mbase;
+
+ mp = mbase = TAILQ_FIRST(ml);
+ for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) {
+ mn = TAILQ_NEXT(mp, m_list);
+ if (mn != NULL && mn->m_char == mp->m_char + 1 &&
+ mn->m_glyph->g_index == mp->m_glyph->g_index + 1)
+ continue;
+ mbase->m_length = mp->m_char - mbase->m_char + 1;
+ mbase = mp = mn;
+ map_folded_count[map_idx]++;
+ }
+}
+
+static int
+write_mappings(FILE *fp, unsigned int map_idx)
+{
+ struct mapping_list *ml = &maps[map_idx];
+ struct mapping *mp;
+ vfnt_map_t fm;
+ unsigned int i = 0, j = 0;
+
+ TAILQ_FOREACH(mp, ml, m_list) {
+ j++;
+ if (mp->m_length > 0) {
+ i += mp->m_length;
+ fm.vfm_src = htobe32(mp->m_char);
+ fm.vfm_dst = htobe16(mp->m_glyph->g_index);
+ fm.vfm_len = htobe16(mp->m_length - 1);
+ if (fwrite(&fm, sizeof fm, 1, fp) != 1)
+ return (1);
+ }
+ }
+ assert(i == j);
+ return (0);
+}
+
+static int
+write_source_mappings(FILE *fp, unsigned int map_idx)
+{
+ struct mapping_list *ml = &maps[map_idx];
+ struct mapping *mp;
+ unsigned int i = 0, j = 0;
+
+ TAILQ_FOREACH(mp, ml, m_list) {
+ j++;
+ if (mp->m_length > 0) {
+ i += mp->m_length;
+ if (fprintf(fp, "\t{ 0x%08x, 0x%04x, 0x%04x },\n",
+ mp->m_char, mp->m_glyph->g_index,
+ mp->m_length - 1) < 0)
+ return (1);
+ }
+ }
+ assert(i == j);
+ return (0);
+}
+
+static int
+write_fnt(const char *filename)
+{
+ FILE *fp;
+ struct font_header fh = {
+ .fh_magic = FONT_HEADER_MAGIC,
+ };
+
+ fp = fopen(filename, "wb");
+ if (fp == NULL) {
+ perror(filename);
+ return (1);
+ }
+
+ fh.fh_width = width;
+ fh.fh_height = height;
+ fh.fh_glyph_count = htobe32(glyph_unique);
+ fh.fh_map_count[0] = htobe32(map_folded_count[0]);
+ fh.fh_map_count[1] = htobe32(map_folded_count[1]);
+ fh.fh_map_count[2] = htobe32(map_folded_count[2]);
+ fh.fh_map_count[3] = htobe32(map_folded_count[3]);
+ if (fwrite(&fh, sizeof(fh), 1, fp) != 1) {
+ perror(filename);
+ fclose(fp);
+ return (1);
+ }
+
+ if (write_glyphs(fp, &fwrite) != 0 ||
+ write_mappings(fp, VFNT_MAP_NORMAL) != 0 ||
+ write_mappings(fp, VFNT_MAP_NORMAL_RIGHT) != 0 ||
+ write_mappings(fp, VFNT_MAP_BOLD) != 0 ||
+ write_mappings(fp, VFNT_MAP_BOLD_RIGHT) != 0) {
+ perror(filename);
+ fclose(fp);
+ return (1);
+ }
+
+ fclose(fp);
+ return (0);
+}
+
+static int
+write_fnt_source(bool lz4, const char *filename)
+{
+ FILE *fp;
+ int rv = 1;
+ size_t uncompressed_size = wbytes * height * glyph_unique;
+ size_t compressed_size = uncompressed_size;
+ uint8_t *compressed = NULL;
+
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ perror(filename);
+ return (1);
+ }
+
+ if (lz4 == true) {
+ uncompressed = xmalloc(uncompressed_size);
+ compressed = xmalloc(uncompressed_size);
+ }
+ if (fprintf(fp, "/* Generated %ux%u console font source. */\n\n",
+ width, height) < 0)
+ goto done;
+ if (fprintf(fp, "#include <sys/types.h>\n") < 0)
+ goto done;
+ if (fprintf(fp, "#include <sys/param.h>\n") < 0)
+ goto done;
+ if (fprintf(fp, "#include <sys/font.h>\n\n") < 0)
+ goto done;
+
+ /* Write font bytes. */
+ if (fprintf(fp, "static uint8_t FONTDATA_%ux%u[] = {\n",
+ width, height) < 0)
+ goto done;
+ if (lz4 == true) {
+ if (write_glyphs(fp, &write_glyph_buf) != 0)
+ goto done;
+ compressed_size = lz4_compress(uncompressed, compressed,
+ uncompressed_size, compressed_size, 0);
+ if (write_glyph_source(compressed, compressed_size, 1, fp) != 1)
+ goto done;
+ free(uncompressed);
+ free(compressed);
+ } else {
+ if (write_glyphs(fp, &write_glyph_source) != 0)
+ goto done;
+ }
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+
+ /* Write font maps. */
+ if (!TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL])) {
+ if (fprintf(fp, "static vfnt_map_t "
+ "FONTMAP_NORMAL_%ux%u[] = {\n", width, height) < 0)
+ goto done;
+ if (write_source_mappings(fp, VFNT_MAP_NORMAL) != 0)
+ goto done;
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+ }
+ if (!TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL_RIGHT])) {
+ if (fprintf(fp, "static vfnt_map_t "
+ "FONTMAP_NORMAL_RH_%ux%u[] = {\n", width, height) < 0)
+ goto done;
+ if (write_source_mappings(fp, VFNT_MAP_NORMAL_RIGHT) != 0)
+ goto done;
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+ }
+ if (!TAILQ_EMPTY(&maps[VFNT_MAP_BOLD])) {
+ if (fprintf(fp, "static vfnt_map_t "
+ "FONTMAP_BOLD_%ux%u[] = {\n", width, height) < 0)
+ goto done;
+ if (write_source_mappings(fp, VFNT_MAP_BOLD) != 0)
+ goto done;
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+ }
+ if (!TAILQ_EMPTY(&maps[VFNT_MAP_BOLD_RIGHT])) {
+ if (fprintf(fp, "static vfnt_map_t "
+ "FONTMAP_BOLD_RH_%ux%u[] = {\n", width, height) < 0)
+ goto done;
+ if (write_source_mappings(fp, VFNT_MAP_BOLD_RIGHT) != 0)
+ goto done;
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+ }
+
+ /* Write struct font. */
+ if (fprintf(fp, "struct vt_font font_%ux%u = {\n",
+ width, height) < 0)
+ goto done;
+ if (fprintf(fp, "\t.vf_map\t= {\n") < 0)
+ goto done;
+ if (TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL])) {
+ if (fprintf(fp, "\t\t\tNULL,\n") < 0)
+ goto done;
+ } else {
+ if (fprintf(fp, "\t\t\tFONTMAP_NORMAL_%ux%u,\n",
+ width, height) < 0)
+ goto done;
+ }
+ if (TAILQ_EMPTY(&maps[VFNT_MAP_NORMAL_RIGHT])) {
+ if (fprintf(fp, "\t\t\tNULL,\n") < 0)
+ goto done;
+ } else {
+ if (fprintf(fp, "\t\t\tFONTMAP_NORMAL_RH_%ux%u,\n",
+ width, height) < 0)
+ goto done;
+ }
+ if (TAILQ_EMPTY(&maps[VFNT_MAP_BOLD])) {
+ if (fprintf(fp, "\t\t\tNULL,\n") < 0)
+ goto done;
+ } else {
+ if (fprintf(fp, "\t\t\tFONTMAP_BOLD_%ux%u,\n",
+ width, height) < 0)
+ goto done;
+ }
+ if (TAILQ_EMPTY(&maps[VFNT_MAP_BOLD_RIGHT])) {
+ if (fprintf(fp, "\t\t\tNULL\n") < 0)
+ goto done;
+ } else {
+ if (fprintf(fp, "\t\t\tFONTMAP_BOLD_RH_%ux%u\n",
+ width, height) < 0)
+ goto done;
+ }
+ if (fprintf(fp, "\t\t},\n") < 0)
+ goto done;
+ if (lz4 == true) {
+ if (fprintf(fp, "\t.vf_bytes\t= NULL,\n") < 0)
+ goto done;
+ } else {
+ if (fprintf(fp, "\t.vf_bytes\t= FONTDATA_%ux%u,\n",
+ width, height) < 0) {
+ goto done;
+ }
+ }
+ if (fprintf(fp, "\t.vf_width\t= %u,\n", width) < 0)
+ goto done;
+ if (fprintf(fp, "\t.vf_height\t= %u,\n", height) < 0)
+ goto done;
+ if (fprintf(fp, "\t.vf_map_count\t= { %u, %u, %u, %u }\n",
+ map_folded_count[0], map_folded_count[1], map_folded_count[2],
+ map_folded_count[3]) < 0) {
+ goto done;
+ }
+ if (fprintf(fp, "};\n\n") < 0)
+ goto done;
+
+ /* Write bitmap data. */
+ if (fprintf(fp, "vt_font_bitmap_data_t font_data_%ux%u = {\n",
+ width, height) < 0)
+ goto done;
+ if (fprintf(fp, "\t.vfbd_width\t= %u,\n", width) < 0)
+ goto done;
+ if (fprintf(fp, "\t.vfbd_height\t= %u,\n", height) < 0)
+ goto done;
+ if (lz4 == true) {
+ if (fprintf(fp, "\t.vfbd_compressed_size\t= %zu,\n",
+ compressed_size) < 0) {
+ goto done;
+ }
+ if (fprintf(fp, "\t.vfbd_uncompressed_size\t= %zu,\n",
+ uncompressed_size) < 0) {
+ goto done;
+ }
+ if (fprintf(fp, "\t.vfbd_compressed_data\t= FONTDATA_%ux%u,\n",
+ width, height) < 0) {
+ goto done;
+ }
+ } else {
+ if (fprintf(fp, "\t.vfbd_compressed_size\t= 0,\n") < 0)
+ goto done;
+ if (fprintf(fp, "\t.vfbd_uncompressed_size\t= %zu,\n",
+ uncompressed_size) < 0) {
+ goto done;
+ }
+ if (fprintf(fp, "\t.vfbd_compressed_data\t= NULL,\n") < 0)
+ goto done;
+ }
+ if (fprintf(fp, "\t.vfbd_font = &font_%ux%u\n", width, height) < 0)
+ goto done;
+ if (fprintf(fp, "};\n") < 0)
+ goto done;
+
+ rv = 0;
+done:
+ if (rv != 0)
+ perror(filename);
+ fclose(fp);
+ return (0);
+}
+
+static void
+print_font_info(void)
+{
+ printf(
+"Statistics:\n"
+"- width: %6u\n"
+"- height: %6u\n"
+"- glyph_total: %6u\n"
+"- glyph_normal: %6u\n"
+"- glyph_normal_right: %6u\n"
+"- glyph_bold: %6u\n"
+"- glyph_bold_right: %6u\n"
+"- glyph_unique: %6u\n"
+"- glyph_dupe: %6u\n"
+"- mapping_total: %6u\n"
+"- mapping_normal: %6u\n"
+"- mapping_normal_folded: %6u\n"
+"- mapping_normal_right: %6u\n"
+"- mapping_normal_right_folded: %6u\n"
+"- mapping_bold: %6u\n"
+"- mapping_bold_folded: %6u\n"
+"- mapping_bold_right: %6u\n"
+"- mapping_bold_right_folded: %6u\n"
+"- mapping_unique: %6u\n"
+"- mapping_dupe: %6u\n",
+ width, height,
+ glyph_total,
+ glyph_count[0],
+ glyph_count[1],
+ glyph_count[2],
+ glyph_count[3],
+ glyph_unique, glyph_dupe,
+ mapping_total,
+ map_count[0], map_folded_count[0],
+ map_count[1], map_folded_count[1],
+ map_count[2], map_folded_count[2],
+ map_count[3], map_folded_count[3],
+ mapping_unique, mapping_dupe);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, verbose = 0, rv = 0;
+ char *outfile = NULL;
+
+ assert(sizeof(struct font_header) == 32);
+ assert(sizeof(vfnt_map_t) == 8);
+
+ while ((ch = getopt(argc, argv, "nf:h:vw:o:")) != -1) {
+ switch (ch) {
+ case 'f':
+ if (strcmp(optarg, "font") == 0)
+ format = VT_FONT;
+ else if (strcmp(optarg, "source") == 0)
+ format = VT_C_SOURCE;
+ else if (strcmp(optarg, "compressed-source") == 0)
+ format = VT_C_COMPRESSED;
+ else
+ errx(1, "Invalid format: %s", optarg);
+ break;
+ case 'h':
+ height = atoi(optarg);
+ break;
+ case 'n':
+ filter = false;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'w':
+ width = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (outfile == NULL && (argc < 2 || argc > 3))
+ usage();
+
+ if (outfile == NULL) {
+ outfile = argv[argc - 1];
+ argc--;
+ }
+
+ set_width(width);
+ set_height(height);
+
+ if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0)
+ return (1);
+ argc--;
+ argv++;
+ if (argc == 1) {
+ if (parse_file(argv[0], VFNT_MAP_BOLD) != 0)
+ return (1);
+ argc--;
+ argv++;
+ }
+ number_glyphs();
+ dedup_mapping(VFNT_MAP_BOLD);
+ dedup_mapping(VFNT_MAP_BOLD_RIGHT);
+ fold_mappings(0);
+ fold_mappings(1);
+ fold_mappings(2);
+ fold_mappings(3);
+
+ switch (format) {
+ case VT_FONT:
+ rv = write_fnt(outfile);
+ break;
+ case VT_C_SOURCE:
+ rv = write_fnt_source(false, outfile);
+ break;
+ case VT_C_COMPRESSED:
+ rv = write_fnt_source(true, outfile);
+ break;
+ }
+
+ if (verbose)
+ print_font_info();
+
+ return (rv);
+}
diff --git a/usr.bin/w/Makefile b/usr.bin/w/Makefile
new file mode 100644
index 000000000000..7ebf27d40ca5
--- /dev/null
+++ b/usr.bin/w/Makefile
@@ -0,0 +1,9 @@
+PROG= w
+SRCS= fmt.c pr_time.c proc_compare.c w.c
+MAN= w.1 uptime.1
+LIBADD= kvm sbuf xo util
+LINKS= ${BINDIR}/w ${BINDIR}/uptime
+
+.PATH: ${SRCTOP}/bin/ps
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/w/Makefile.depend b/usr.bin/w/Makefile.depend
new file mode 100644
index 000000000000..0f7f37d0523e
--- /dev/null
+++ b/usr.bin/w/Makefile.depend
@@ -0,0 +1,20 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libkvm \
+ lib/libsbuf \
+ lib/libutil \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/w/extern.h b/usr.bin/w/extern.h
new file mode 100644
index 000000000000..6e3ce23f2449
--- /dev/null
+++ b/usr.bin/w/extern.h
@@ -0,0 +1,37 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 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.
+ */
+
+extern int use_ampm;
+
+struct kinfo_proc;
+int pr_attime(time_t *, time_t *);
+int pr_idle(time_t);
+int proc_compare(struct kinfo_proc *, struct kinfo_proc *);
diff --git a/usr.bin/w/pr_time.c b/usr.bin/w/pr_time.c
new file mode 100644
index 000000000000..aef8b5dfaa87
--- /dev/null
+++ b/usr.bin/w/pr_time.c
@@ -0,0 +1,126 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993, 1994
+ * 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <libxo/xo.h>
+
+#include "extern.h"
+
+/*
+ * pr_attime --
+ * Print the time since the user logged in.
+ */
+int
+pr_attime(time_t *started, time_t *now)
+{
+ static wchar_t buf[256];
+ struct tm tp, tm;
+ time_t diff;
+ const wchar_t *fmt;
+ int len, width, offset = 0;
+
+ tp = *localtime(started);
+ tm = *localtime(now);
+ diff = *now - *started;
+
+ /* If more than a week, use day-month-year. */
+ if (diff > 86400 * 7)
+ fmt = L"%d%b%y";
+
+ /* If not today, use day-hour-am/pm. */
+ else if (tm.tm_mday != tp.tm_mday ||
+ tm.tm_mon != tp.tm_mon ||
+ tm.tm_year != tp.tm_year) {
+ /* The line below does not take DST into consideration */
+ /* else if (*now / 86400 != *started / 86400) { */
+ fmt = use_ampm ? L"%a%I%p" : L"%a%H";
+ }
+
+ /* Default is hh:mm{am,pm}. */
+ else {
+ fmt = use_ampm ? L"%l:%M%p" : L"%k:%M";
+ }
+
+ (void)wcsftime(buf, sizeof(buf), fmt, &tp);
+ len = wcslen(buf);
+ width = wcswidth(buf, len);
+ xo_attr("since", "%lu", (unsigned long) *started);
+ xo_attr("delta", "%lu", (unsigned long) diff);
+ if (len == width)
+ xo_emit("{:login-time/%-7.7ls/%ls}", buf);
+ else if (width < 7)
+ xo_emit("{:login-time/%ls}%.*s", buf, 7 - width, " ");
+ else {
+ xo_emit("{:login-time/%ls}", buf);
+ offset = width - 7;
+ }
+ return (offset);
+}
+
+/*
+ * pr_idle --
+ * Display the idle time.
+ * Returns number of excess characters that were used for long idle time.
+ */
+int
+pr_idle(time_t idle)
+{
+ /* If idle more than 36 hours, print as a number of days. */
+ if (idle >= 36 * 3600) {
+ int days = idle / 86400;
+ xo_emit(" {:idle/%dday%s} ", days, days > 1 ? "s" : " " );
+ if (days >= 100)
+ return (2);
+ if (days >= 10)
+ return (1);
+ }
+
+ /* If idle more than an hour, print as HH:MM. */
+ else if (idle >= 3600)
+ xo_emit(" {:idle/%2d:%02d/} ",
+ (int)(idle / 3600), (int)((idle % 3600) / 60));
+
+ else if (idle / 60 == 0)
+ xo_emit(" - ");
+
+ /* Else print the minutes idle. */
+ else
+ xo_emit(" {:idle/%2d} ", (int)(idle / 60));
+
+ return (0); /* not idle longer than 9 days */
+}
diff --git a/usr.bin/w/proc_compare.c b/usr.bin/w/proc_compare.c
new file mode 100644
index 000000000000..36a63d31cc4a
--- /dev/null
+++ b/usr.bin/w/proc_compare.c
@@ -0,0 +1,114 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/user.h>
+
+#include "extern.h"
+
+/*
+ * Returns 1 if p2 is "better" than p1
+ *
+ * The algorithm for picking the "interesting" process is thus:
+ *
+ * 1) Only foreground processes are eligible - implied.
+ * 2) Runnable processes are favored over anything else. The runner
+ * with the highest cpu utilization is picked (p_estcpu). Ties are
+ * broken by picking the highest pid.
+ * 3) The sleeper with the shortest sleep time is next. With ties,
+ * we pick out just "short-term" sleepers (TDF_SINTR == 0).
+ * 4) Further ties are broken by picking the highest pid.
+ *
+ * If you change this, be sure to consider making the change in the kernel
+ * too (^T in kern/tty.c).
+ *
+ * TODO - consider whether pctcpu should be used.
+ */
+
+#define ISRUN(p) (((p)->ki_stat == SRUN) || ((p)->ki_stat == SIDL))
+#define TESTAB(a, b) ((a)<<1 | (b))
+#define ONLYA 2
+#define ONLYB 1
+#define BOTH 3
+
+int
+proc_compare(struct kinfo_proc *p1, struct kinfo_proc *p2)
+{
+
+ if (p1 == NULL)
+ return (1);
+ /*
+ * see if at least one of them is runnable
+ */
+ switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
+ case ONLYA:
+ return (0);
+ case ONLYB:
+ return (1);
+ case BOTH:
+ /*
+ * tie - favor one with highest recent cpu utilization
+ */
+ if (p2->ki_estcpu > p1->ki_estcpu)
+ return (1);
+ if (p1->ki_estcpu > p2->ki_estcpu)
+ return (0);
+ return (p2->ki_pid > p1->ki_pid); /* tie - return highest pid */
+ }
+ /*
+ * weed out zombies
+ */
+ switch (TESTAB(p1->ki_stat == SZOMB, p2->ki_stat == SZOMB)) {
+ case ONLYA:
+ return (1);
+ case ONLYB:
+ return (0);
+ case BOTH:
+ return (p2->ki_pid > p1->ki_pid); /* tie - return highest pid */
+ }
+ /*
+ * pick the one with the smallest sleep time
+ */
+ if (p2->ki_slptime > p1->ki_slptime)
+ return (0);
+ if (p1->ki_slptime > p2->ki_slptime)
+ return (1);
+ /*
+ * favor one sleeping in a non-interruptible sleep
+ */
+ if (p1->ki_tdflags & TDF_SINTR && (p2->ki_tdflags & TDF_SINTR) == 0)
+ return (1);
+ if (p2->ki_tdflags & TDF_SINTR && (p1->ki_tdflags & TDF_SINTR) == 0)
+ return (0);
+ return (p2->ki_pid > p1->ki_pid); /* tie - return highest pid */
+}
diff --git a/usr.bin/w/uptime.1 b/usr.bin/w/uptime.1
new file mode 100644
index 000000000000..b93972d3f932
--- /dev/null
+++ b/usr.bin/w/uptime.1
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1980, 1990, 1993, 1994
+.\" 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.
+.\"
+.Dd August 18, 2020
+.Dt UPTIME 1
+.Os
+.Sh NAME
+.Nm uptime
+.Nd show how long system has been running
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the current time,
+the length of time the system has been up,
+the number of users, and the load average of the system over the last
+1, 5, and 15 minutes.
+.Sh FILES
+.Bl -tag -width /boot/kernel/kernel
+.It Pa /boot/kernel/kernel
+system name list
+.El
+.Sh EXAMPLES
+.Bd -literal -offset indent
+$ uptime
+11:23AM up 3:01, 8 users, load averages: 21.09, 15.43, 12.79
+.Ed
+.Sh SEE ALSO
+.Xr w 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
diff --git a/usr.bin/w/w.1 b/usr.bin/w/w.1
new file mode 100644
index 000000000000..a92edc6f0059
--- /dev/null
+++ b/usr.bin/w/w.1
@@ -0,0 +1,188 @@
+.\" Copyright (c) 1980, 1990, 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.
+.\"
+.Dd August 24, 2020
+.Dt W 1
+.Os
+.Sh NAME
+.Nm w
+.Nd "display who is logged in and what they are doing"
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl dhin
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Ar user ...
+.Sh DESCRIPTION
+The
+.Nm
+utility prints a summary of the current activity on the system,
+including what each user is doing.
+The first line displays the current time of day, how long the system has
+been running, the number of users logged into the system, and the load
+averages.
+The load average numbers give the number of jobs in the run queue averaged
+over 1, 5 and 15 minutes.
+.Pp
+The fields output are the user's login name, the name of the terminal the
+user is on, the host from which the user is logged in, the time the user
+logged on, the time since the user last typed anything,
+and the name and arguments of the current process.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl d
+dumps out the entire process list on a per controlling
+tty basis, instead of just the top level process.
+.It Fl h
+Suppress the heading.
+.It Fl i
+Output is sorted by idle time.
+.It Fl M
+Extract values associated with the name list from the specified
+core instead of the default
+.Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the
+default
+.Pa /boot/kernel/kernel .
+.It Fl n
+Do not attempt to resolve network addresses (normally
+.Nm
+interprets addresses and attempts to display them as names).
+When
+.Fl n
+is specified more than once, hostnames stored in utmp are attempted to
+resolve to display them as network addresses.
+.El
+.Pp
+If one or more
+.Ar user
+names are specified, the output is restricted to those users.
+.Sh FILES
+.Bl -tag -width ".Pa /var/run/utx.active" -compact
+.It Pa /var/run/utx.active
+list of users on the system
+.El
+.Sh EXAMPLES
+Show global activity of the system:
+.Bd -literal -offset indent
+$ w
+ 8:05PM up 35 mins, 3 users, load averages: 0.09, 0.35, 0.27
+USER TTY FROM LOGIN@ IDLE WHAT
+fernape v0 - 7:30PM - tmux: client (/tmp/tmux-1001/default) (tmux)
+root v1 - 8:03PM 1 -bash (bash)
+fernape pts/0 tmux(1391).%0 8:04PM - w
+.Ed
+.Pp
+Show the entire process list per tty:
+.Bd -literal -offset indent
+$ w -d
+ 8:12PM up 42 mins, 3 users, load averages: 0.01, 0.11, 0.17
+USER TTY FROM LOGIN@ IDLE WHAT
+ 1199 login [pam] (login)
+ 1207 -bash (bash)
+ 1507 tmux: client (/tmp/tmux-1001/default) (tmux)
+fernape v0 - 7:30PM - tmux: client (/tmp/tmux-1001/default) (tmux)
+ 1488 login [pam] (login)
+ 1489 -bash (bash)
+root v1 - 8:08PM 3 -bash (bash)
+ 1510 -bash (bash)
+ 1515 w -d
+fernape pts/0 tmux(1509).%0 8:11PM - w -d
+.Ed
+.Pp
+Same as above but only for the root user and omitting the heading:
+.Bd -literal -offset indent
+$ w -d -h root
+ 1183 login [pam] (login)
+ 1204 -bash (bash)
+root v1 - 7:15PM - -bash (bash)
+.Ed
+.Sh COMPATIBILITY
+The
+.Fl f ,
+.Fl l ,
+.Fl s ,
+and
+.Fl w
+flags are no longer supported.
+.Sh SEE ALSO
+.Xr finger 1 ,
+.Xr ps 1 ,
+.Xr uptime 1 ,
+.Xr who 1 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh BUGS
+The notion of the
+.Dq current process
+is muddy.
+The current algorithm is
+.Do
+the highest numbered process on the terminal
+that is not ignoring interrupts, or, if there is none, the highest numbered
+process on the terminal
+.Dc .
+This fails, for example, in critical sections of programs like the shell
+and editor, or when faulty programs running in the background fork and fail
+to ignore interrupts.
+(In cases where no process can be found,
+.Nm
+prints
+.Ql \- . )
+.Pp
+The CPU time is only an estimate, in particular, if someone leaves a background
+process running after logging out, the person currently on that terminal is
+.Dq charged
+with the time.
+.Pp
+Background processes are not shown, even though they account for
+much of the load on the system.
+.Pp
+Sometimes processes, typically those in the background, are printed with
+null or garbaged arguments.
+In these cases, the name of the command is printed in parentheses.
+.Pp
+The
+.Nm
+utility does not know about the new conventions for detection of background
+jobs.
+It will sometimes find a background job instead of the right one.
diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c
new file mode 100644
index 000000000000..ac1df96077d3
--- /dev/null
+++ b/usr.bin/w/w.c
@@ -0,0 +1,582 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1991, 1993, 1994
+ * 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.
+ */
+
+/*
+ * w - print system status (who and what)
+ *
+ * This program is similar to the systat command on Tenex/Tops 10/20
+ *
+ */
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/tty.h>
+#include <sys/types.h>
+
+#include <machine/cpu.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <langinfo.h>
+#include <libgen.h>
+#include <libutil.h>
+#include <limits.h>
+#include <locale.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <timeconv.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <vis.h>
+#include <libxo/xo.h>
+
+#include "extern.h"
+
+static struct utmpx *utmp;
+static struct winsize ws;
+static kvm_t *kd;
+static time_t now; /* the current time of day */
+static size_t ttywidth; /* width of tty */
+static size_t fromwidth = 0; /* max width of "from" field */
+static size_t argwidth; /* width of arguments */
+static int header = 1; /* true if -h flag: don't print heading */
+static int nflag; /* true if -n flag: don't convert addrs */
+static int dflag; /* true if -d flag: output debug info */
+static int sortidle; /* sort by idle time */
+int use_ampm; /* use AM/PM time */
+static int use_comma; /* use comma as floats separator */
+static char **sel_users; /* login array of particular users selected */
+
+/*
+ * One of these per active utmp entry.
+ */
+static struct entry {
+ struct entry *next;
+ struct utmpx utmp;
+ dev_t tdev; /* dev_t of terminal */
+ time_t idle; /* idle time of terminal in seconds */
+ struct kinfo_proc *kp; /* `most interesting' proc */
+ char *args; /* arg list of interesting process */
+ struct kinfo_proc *dkp; /* debug option proc list */
+ char *from; /* "from": name or addr */
+ char *save_from; /* original "from": name or addr */
+} *ep, *ehead = NULL, **nextp = &ehead;
+
+#define debugproc(p) *(&((struct kinfo_proc *)p)->ki_udata)
+
+#define W_XO_VERSION "1"
+
+#define W_DISPUSERSIZE 10
+#define W_DISPLINESIZE 8
+#define W_MAXHOSTSIZE 40
+
+static void pr_header(time_t *, int);
+static struct stat *ttystat(char *);
+static void usage(int);
+
+char *fmt_argv(char **, char *, char *, size_t); /* ../../bin/ps/fmt.c */
+
+int
+main(int argc, char *argv[])
+{
+ struct kinfo_proc *kp;
+ struct kinfo_proc *dkp;
+ struct stat *stp;
+ time_t touched;
+ size_t width;
+ int ch, i, nentries, nusers, wcmd, longidle, longattime;
+ const char *memf, *nlistf, *p, *save_p;
+ char *x_suffix;
+ char errbuf[_POSIX2_LINE_MAX];
+ char buf[MAXHOSTNAMELEN], fn[MAXHOSTNAMELEN];
+ char *dot;
+
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+ if (xo_get_style(NULL) == XO_STYLE_TEXT) {
+ setlocale(LC_ALL, "");
+ }
+ use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
+ use_comma = (*nl_langinfo(RADIXCHAR) != ',');
+ /* Are we w(1) or uptime(1)? */
+ if (strcmp(basename(argv[0]), "uptime") == 0) {
+ wcmd = 0;
+ p = "";
+ } else {
+ wcmd = 1;
+ p = "dhiflM:N:nsuw";
+ }
+
+ memf = _PATH_DEVNULL;
+ nlistf = NULL;
+ while ((ch = getopt(argc, argv, p)) != -1)
+ switch (ch) {
+ case 'd':
+ dflag = 1;
+ break;
+ case 'h':
+ header = 0;
+ break;
+ case 'i':
+ sortidle = 1;
+ break;
+ case 'M':
+ header = 0;
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ nflag += 1;
+ break;
+ case 'f': case 'l': case 's': case 'u': case 'w':
+ xo_warnx("-%c no longer supported", ch);
+ /* FALLTHROUGH */
+ case '?':
+ default:
+ usage(wcmd);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!(_res.options & RES_INIT))
+ res_init();
+ _res.retrans = 2; /* resolver timeout to 2 seconds per try */
+ _res.retry = 1; /* only try once.. */
+
+ if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
+ xo_errx(1, "%s", errbuf);
+
+ (void)time(&now);
+
+ if (*argv)
+ sel_users = argv;
+
+ setutxent();
+ for (nusers = 0; (utmp = getutxent()) != NULL;) {
+ struct addrinfo hints, *res;
+ struct sockaddr_storage ss;
+ struct sockaddr *sa = (struct sockaddr *)&ss;
+ struct sockaddr_in *lsin = (struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)&ss;
+ int isaddr;
+
+ if (utmp->ut_type != USER_PROCESS)
+ continue;
+ if (!(stp = ttystat(utmp->ut_line)))
+ continue; /* corrupted record */
+ ++nusers;
+ if (wcmd == 0)
+ continue;
+ if (sel_users) {
+ int usermatch;
+ char **user;
+
+ usermatch = 0;
+ for (user = sel_users; !usermatch && *user; user++)
+ if (!strcmp(utmp->ut_user, *user))
+ usermatch = 1;
+ if (!usermatch)
+ continue;
+ }
+ if ((ep = calloc(1, sizeof(struct entry))) == NULL)
+ xo_errx(1, "calloc");
+ *nextp = ep;
+ nextp = &ep->next;
+ memmove(&ep->utmp, utmp, sizeof *utmp);
+ ep->tdev = stp->st_rdev;
+ /*
+ * If this is the console device, attempt to ascertain
+ * the true console device dev_t.
+ */
+ if (ep->tdev == 0) {
+ size_t size;
+
+ size = sizeof(dev_t);
+ (void)sysctlbyname("machdep.consdev", &ep->tdev, &size, NULL, 0);
+ }
+ touched = stp->st_atime;
+ if (touched < ep->utmp.ut_tv.tv_sec) {
+ /* tty untouched since before login */
+ touched = ep->utmp.ut_tv.tv_sec;
+ }
+ if ((ep->idle = now - touched) < 0)
+ ep->idle = 0;
+
+ save_p = p = *ep->utmp.ut_host ? ep->utmp.ut_host : "-";
+ if ((x_suffix = strrchr(p, ':')) != NULL) {
+ if ((dot = strchr(x_suffix, '.')) != NULL &&
+ strchr(dot+1, '.') == NULL)
+ *x_suffix++ = '\0';
+ else
+ x_suffix = NULL;
+ }
+
+ isaddr = 0;
+ memset(&ss, '\0', sizeof(ss));
+ if (inet_pton(AF_INET6, p, &lsin6->sin6_addr) == 1) {
+ lsin6->sin6_len = sizeof(*lsin6);
+ lsin6->sin6_family = AF_INET6;
+ isaddr = 1;
+ } else if (inet_pton(AF_INET, p, &lsin->sin_addr) == 1) {
+ lsin->sin_len = sizeof(*lsin);
+ lsin->sin_family = AF_INET;
+ isaddr = 1;
+ }
+ if (nflag == 0) {
+ /* Attempt to change an IP address into a name */
+ if (isaddr && realhostname_sa(fn, sizeof(fn), sa,
+ sa->sa_len) == HOSTNAME_FOUND)
+ p = fn;
+ } else if (!isaddr && nflag > 1) {
+ /*
+ * If a host has only one A/AAAA RR, change a
+ * name into an IP address
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(p, NULL, &hints, &res) == 0) {
+ if (res->ai_next == NULL &&
+ getnameinfo(res->ai_addr, res->ai_addrlen,
+ fn, sizeof(fn), NULL, 0,
+ NI_NUMERICHOST) == 0)
+ p = fn;
+ freeaddrinfo(res);
+ }
+ }
+
+ if (x_suffix) {
+ (void)snprintf(buf, sizeof(buf), "%s:%s", p, x_suffix);
+ p = buf;
+ }
+ ep->from = strdup(p);
+ if ((width = strlen(p)) > fromwidth)
+ fromwidth = width;
+ if (save_p != p)
+ ep->save_from = strdup(save_p);
+ }
+ endutxent();
+
+#define HEADER_USER "USER"
+#define HEADER_TTY "TTY"
+#define HEADER_FROM "FROM"
+#define HEADER_LOGIN_IDLE "LOGIN@ IDLE "
+#define HEADER_WHAT "WHAT\n"
+#define WUSED (W_DISPUSERSIZE + W_DISPLINESIZE + fromwidth + \
+ sizeof(HEADER_LOGIN_IDLE) + 3) /* header width incl. spaces */
+
+ if (sizeof(HEADER_FROM) > fromwidth)
+ fromwidth = sizeof(HEADER_FROM);
+ fromwidth++;
+ if (fromwidth > W_MAXHOSTSIZE)
+ fromwidth = W_MAXHOSTSIZE;
+
+ xo_set_version(W_XO_VERSION);
+ xo_open_container("uptime-information");
+
+ if (header || wcmd == 0) {
+ pr_header(&now, nusers);
+ if (wcmd == 0) {
+ xo_close_container("uptime-information");
+ if (xo_finish() < 0)
+ xo_err(1, "stdout");
+ (void)kvm_close(kd);
+ exit(0);
+ }
+
+ xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%s}",
+ W_DISPUSERSIZE, W_DISPUSERSIZE, HEADER_USER,
+ W_DISPLINESIZE, W_DISPLINESIZE, HEADER_TTY,
+ fromwidth, fromwidth, HEADER_FROM,
+ HEADER_LOGIN_IDLE HEADER_WHAT);
+ }
+
+ if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL)
+ xo_err(1, "%s", kvm_geterr(kd));
+ for (i = 0; i < nentries; i++, kp++) {
+ if (kp->ki_stat == SIDL || kp->ki_stat == SZOMB ||
+ kp->ki_tdev == NODEV)
+ continue;
+ for (ep = ehead; ep != NULL; ep = ep->next) {
+ if (ep->tdev == kp->ki_tdev) {
+ /*
+ * proc is associated with this terminal
+ */
+ if (ep->kp == NULL && kp->ki_pgid == kp->ki_tpgid) {
+ /*
+ * Proc is 'most interesting'
+ */
+ if (proc_compare(ep->kp, kp))
+ ep->kp = kp;
+ }
+ /*
+ * Proc debug option info; add to debug
+ * list using kinfo_proc ki_spare[0]
+ * as next pointer; ptr to ptr avoids the
+ * ptr = long assumption.
+ */
+ dkp = ep->dkp;
+ ep->dkp = kp;
+ debugproc(kp) = dkp;
+ }
+ }
+ }
+ if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
+ ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
+ ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
+ ttywidth = 79;
+ else
+ ttywidth = ws.ws_col - 1;
+ argwidth = ttywidth - WUSED;
+ if (argwidth < 4)
+ argwidth = 8;
+ /* Don't truncate if we're outputting json or XML. */
+ if (xo_get_style(NULL) != XO_STYLE_TEXT)
+ argwidth = ARG_MAX;
+ for (ep = ehead; ep != NULL; ep = ep->next) {
+ if (ep->kp == NULL) {
+ ep->args = strdup("-");
+ continue;
+ }
+ ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
+ ep->kp->ki_comm, NULL, MAXCOMLEN);
+ if (ep->args == NULL)
+ xo_err(1, "fmt_argv");
+ }
+ /* sort by idle time */
+ if (sortidle && ehead != NULL) {
+ struct entry *from, *save;
+
+ from = ehead;
+ ehead = NULL;
+ while (from != NULL) {
+ for (nextp = &ehead;
+ (*nextp) && from->idle >= (*nextp)->idle;
+ nextp = &(*nextp)->next)
+ continue;
+ save = from;
+ from = from->next;
+ save->next = *nextp;
+ *nextp = save;
+ }
+ }
+
+ xo_open_container("user-table");
+ xo_open_list("user-entry");
+
+ for (ep = ehead; ep != NULL; ep = ep->next) {
+ time_t t;
+
+ xo_open_instance("user-entry");
+
+ if (dflag) {
+ xo_open_container("process-table");
+ xo_open_list("process-entry");
+
+ for (dkp = ep->dkp; dkp != NULL; dkp = debugproc(dkp)) {
+ const char *ptr;
+
+ ptr = fmt_argv(kvm_getargv(kd, dkp, argwidth),
+ dkp->ki_comm, NULL, MAXCOMLEN);
+ if (ptr == NULL)
+ ptr = "-";
+ xo_open_instance("process-entry");
+ xo_emit("\t\t{:process-id/%-9d/%d} "
+ "{:command/%hs}\n", dkp->ki_pid, ptr);
+ xo_close_instance("process-entry");
+ }
+ xo_close_list("process-entry");
+ xo_close_container("process-table");
+ }
+ xo_emit("{:user/%-*.*s/%@**@s} {:tty/%-*.*s/%@**@s} ",
+ W_DISPUSERSIZE, W_DISPUSERSIZE, ep->utmp.ut_user,
+ W_DISPLINESIZE, W_DISPLINESIZE,
+ *ep->utmp.ut_line ?
+ (strncmp(ep->utmp.ut_line, "tty", 3) &&
+ strncmp(ep->utmp.ut_line, "cua", 3) ?
+ ep->utmp.ut_line : ep->utmp.ut_line + 3) : "-");
+
+ if (ep->save_from)
+ xo_attr("address", "%s", ep->save_from);
+ xo_emit("{:from/%-*.*s/%@**@s} ",
+ (int)fromwidth, (int)fromwidth, ep->from);
+ t = ep->utmp.ut_tv.tv_sec;
+ longattime = pr_attime(&t, &now);
+ longidle = pr_idle(ep->idle);
+ xo_emit("{:command/%.*hs/%@*@hs}\n",
+ (int)argwidth - longidle - longattime,
+ ep->args);
+
+ xo_close_instance("user-entry");
+ }
+
+ xo_close_list("user-entry");
+ xo_close_container("user-table");
+ xo_close_container("uptime-information");
+ if (xo_finish() < 0)
+ xo_err(1, "stdout");
+
+ (void)kvm_close(kd);
+ exit(0);
+}
+
+static void
+pr_header(time_t *nowp, int nusers)
+{
+ char buf[64];
+ struct sbuf upbuf;
+ double avenrun[3];
+ struct timespec tp;
+ unsigned long days, hrs, mins, secs;
+ unsigned int i;
+
+ /*
+ * Print time of day.
+ */
+ if (strftime(buf, sizeof(buf),
+ use_ampm ? "%l:%M%p" : "%k:%M", localtime(nowp)) != 0)
+ xo_emit("{:time-of-day/%s} ", buf);
+ /*
+ * Print how long system has been up.
+ */
+ (void)sbuf_new(&upbuf, buf, sizeof(buf), SBUF_FIXEDLEN);
+ if (clock_gettime(CLOCK_UPTIME, &tp) != -1) {
+ xo_emit(" up");
+ secs = tp.tv_sec;
+ xo_emit("{e:uptime/%lu}", secs);
+ mins = secs / 60;
+ secs %= 60;
+ hrs = mins / 60;
+ mins %= 60;
+ days = hrs / 24;
+ hrs %= 24;
+ xo_emit("{e:days/%ld}{e:hours/%ld}{e:minutes/%ld}{e:seconds/%ld}",
+ days, hrs, mins, secs);
+
+ /* If we've been up longer than 60 s, round to nearest min */
+ if (tp.tv_sec > 60) {
+ secs = tp.tv_sec + 30;
+ mins = secs / 60;
+ secs = 0;
+ hrs = mins / 60;
+ mins %= 60;
+ days = hrs / 24;
+ hrs %= 24;
+ }
+
+ if (days > 0)
+ sbuf_printf(&upbuf, " %ld day%s,",
+ days, days > 1 ? "s" : "");
+ if (hrs > 0 && mins > 0)
+ sbuf_printf(&upbuf, " %2ld:%02ld,", hrs, mins);
+ else if (hrs > 0)
+ sbuf_printf(&upbuf, " %ld hr%s,",
+ hrs, hrs > 1 ? "s" : "");
+ else if (mins > 0)
+ sbuf_printf(&upbuf, " %ld min%s,",
+ mins, mins > 1 ? "s" : "");
+ else
+ sbuf_printf(&upbuf, " %ld sec%s,",
+ secs, secs > 1 ? "s" : "");
+ if (sbuf_finish(&upbuf) != 0)
+ xo_err(1, "Could not generate output");
+ xo_emit("{:uptime-human/%s}", sbuf_data(&upbuf));
+ sbuf_delete(&upbuf);
+ }
+
+ /* Print number of users logged in to system */
+ xo_emit(" {:users/%d} {Np:user,users}", nusers);
+
+ /*
+ * Print 1, 5, and 15 minute load averages.
+ */
+ if (getloadavg(avenrun, nitems(avenrun)) == -1)
+ xo_emit(", no load average information available\n");
+ else {
+ static const char *format[] = {
+ " {:load-average-1/%.2f}",
+ " {:load-average-5/%.2f}",
+ " {:load-average-15/%.2f}",
+ };
+ xo_emit(", load averages:");
+ for (i = 0; i < nitems(avenrun); i++) {
+ if (use_comma && i > 0)
+ xo_emit(",");
+ xo_emit(format[i], avenrun[i]);
+ }
+ xo_emit("\n");
+ }
+}
+
+static struct stat *
+ttystat(char *line)
+{
+ static struct stat sb;
+ char ttybuf[MAXPATHLEN];
+
+ (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
+ if (stat(ttybuf, &sb) == 0 && S_ISCHR(sb.st_mode))
+ return (&sb);
+ return (NULL);
+}
+
+static void
+usage(int wcmd)
+{
+ if (wcmd)
+ xo_error("usage: w [-dhin] [-M core] [-N system] [user ...]\n");
+ else
+ xo_error("usage: uptime\n");
+ xo_finish();
+ exit(1);
+}
diff --git a/usr.bin/wall/Makefile b/usr.bin/wall/Makefile
new file mode 100644
index 000000000000..1b0df1271354
--- /dev/null
+++ b/usr.bin/wall/Makefile
@@ -0,0 +1,6 @@
+PROG= wall
+SRCS= ttymsg.c wall.c
+BINGRP= tty
+BINMODE=2555
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/wall/Makefile.depend b/usr.bin/wall/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/wall/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/wall/ttymsg.c b/usr.bin/wall/ttymsg.c
new file mode 100644
index 000000000000..4f1c367c505f
--- /dev/null
+++ b/usr.bin/wall/ttymsg.c
@@ -0,0 +1,163 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ttymsg.h"
+
+/*
+ * Display the contents of a uio structure on a terminal. Used by wall(1),
+ * syslogd(8), and talkd(8). Forks and finishes in child if write would block,
+ * waiting up to tmout seconds. Returns pointer to error string on unexpected
+ * error; string is not newline-terminated. Various "normal" errors are
+ * ignored (exclusive-use, lack of permission, etc.).
+ */
+const char *
+ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
+{
+ struct iovec localiov[TTYMSG_IOV_MAX];
+ ssize_t left, wret;
+ int cnt, fd;
+ char device[MAXNAMLEN] = _PATH_DEV;
+ static char errbuf[1024];
+ char *p;
+ int forked;
+
+ forked = 0;
+ if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0])))
+ return ("too many iov's (change code in wall/ttymsg.c)");
+
+ strlcat(device, line, sizeof(device));
+ p = device + sizeof(_PATH_DEV) - 1;
+ if (strncmp(p, "pts/", 4) == 0)
+ p += 4;
+ if (strchr(p, '/') != NULL) {
+ /* A slash is an attempt to break security... */
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "Too many '/' in \"%s\"", device);
+ return (errbuf);
+ }
+
+ /*
+ * open will fail on slip lines or exclusive-use lines
+ * if not running as root; not an error.
+ */
+ if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
+ if (errno == EBUSY || errno == EACCES)
+ return (NULL);
+ (void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device,
+ strerror(errno));
+ return (errbuf);
+ }
+
+ for (cnt = 0, left = 0; cnt < iovcnt; ++cnt)
+ left += iov[cnt].iov_len;
+
+ for (;;) {
+ wret = writev(fd, iov, iovcnt);
+ if (wret >= left)
+ break;
+ if (wret >= 0) {
+ left -= wret;
+ if (iov != localiov) {
+ bcopy(iov, localiov,
+ iovcnt * sizeof(struct iovec));
+ iov = localiov;
+ }
+ for (cnt = 0; (size_t)wret >= iov->iov_len; ++cnt) {
+ wret -= iov->iov_len;
+ ++iov;
+ --iovcnt;
+ }
+ if (wret) {
+ iov->iov_base = (char *)iov->iov_base + wret;
+ iov->iov_len -= wret;
+ }
+ continue;
+ }
+ if (errno == EWOULDBLOCK) {
+ int cpid;
+
+ if (forked) {
+ (void) close(fd);
+ _exit(1);
+ }
+ cpid = fork();
+ if (cpid < 0) {
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "fork: %s", strerror(errno));
+ (void) close(fd);
+ return (errbuf);
+ }
+ if (cpid) { /* parent */
+ (void) close(fd);
+ return (NULL);
+ }
+ forked++;
+ /* wait at most tmout seconds */
+ (void) signal(SIGALRM, SIG_DFL);
+ (void) signal(SIGTERM, SIG_DFL); /* XXX */
+ (void) sigsetmask(0);
+ (void) alarm((u_int)tmout);
+ (void) fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */
+ continue;
+ }
+ /*
+ * We get ENODEV on a slip line if we're running as root,
+ * and EIO if the line just went away.
+ */
+ if (errno == ENODEV || errno == EIO)
+ break;
+ (void) close(fd);
+ if (forked)
+ _exit(1);
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "%s: %s", device, strerror(errno));
+ return (errbuf);
+ }
+
+ (void) close(fd);
+ if (forked)
+ _exit(0);
+ return (NULL);
+}
diff --git a/usr.bin/wall/ttymsg.h b/usr.bin/wall/ttymsg.h
new file mode 100644
index 000000000000..be97592f5e1c
--- /dev/null
+++ b/usr.bin/wall/ttymsg.h
@@ -0,0 +1,4 @@
+
+#define TTYMSG_IOV_MAX 32
+
+const char *ttymsg(struct iovec *, int, const char *, int);
diff --git a/usr.bin/wall/wall.1 b/usr.bin/wall/wall.1
new file mode 100644
index 000000000000..9fc438032fc2
--- /dev/null
+++ b/usr.bin/wall/wall.1
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1989, 1990, 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.
+.\"
+.Dd February 24, 2012
+.Dt WALL 1
+.Os
+.Sh NAME
+.Nm wall
+.Nd write a message to users
+.Sh SYNOPSIS
+.Nm
+.Op Fl g Ar group
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the contents of
+.Ar file
+or, by default, its standard input, on the terminals of all
+currently logged in users.
+.Pp
+Only the super-user can write on the
+terminals of users who have chosen
+to deny messages or are using a program which
+automatically denies messages.
+.Bl -tag -width indent
+.It Fl g
+Send messages to users in this group.
+This option may be specified
+multiple times, and any user in any of the specified groups will
+receive the message.
+.El
+.Sh SEE ALSO
+.Xr mesg 1 ,
+.Xr talk 1 ,
+.Xr write 1 ,
+.Xr shutdown 8
+.Sh HISTORY
+A
+.Nm
+command appeared in PWB UNIX.
+.Sh BUGS
+The sender's
+.Ev LC_CTYPE
+setting is used to determine which characters are safe to write to a
+terminal, not the receiver's (which
+.Nm
+has no way of knowing).
diff --git a/usr.bin/wall/wall.c b/usr.bin/wall/wall.c
new file mode 100644
index 000000000000..fcfcdcb3fbce
--- /dev/null
+++ b/usr.bin/wall/wall.c
@@ -0,0 +1,280 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1988, 1990, 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.
+ */
+
+/*
+ * This program is not related to David Wall, whose Stanford Ph.D. thesis
+ * is entitled "Mechanisms for Broadcast and Selective Broadcast".
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <grp.h>
+#include <locale.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "ttymsg.h"
+
+static void makemsg(char *);
+static void usage(void) __dead2;
+
+static struct wallgroup {
+ struct wallgroup *next;
+ char *name;
+ gid_t gid;
+} *grouplist;
+static int nobanner;
+static int mbufsize;
+static char *mbuf;
+
+static int
+ttystat(char *line)
+{
+ struct stat sb;
+ char ttybuf[MAXPATHLEN];
+
+ (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
+ if (stat(ttybuf, &sb) == 0) {
+ return (0);
+ } else
+ return (-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct iovec iov;
+ struct utmpx *utmp;
+ int ch;
+ int ingroup;
+ struct wallgroup *g;
+ struct group *grp;
+ char **np;
+ const char *p;
+ struct passwd *pw;
+
+ (void)setlocale(LC_CTYPE, "");
+
+ while ((ch = getopt(argc, argv, "g:n")) != -1)
+ switch (ch) {
+ case 'n':
+ /* undoc option for shutdown: suppress banner */
+ if (geteuid() == 0)
+ nobanner = 1;
+ break;
+ case 'g':
+ g = (struct wallgroup *)malloc(sizeof *g);
+ g->next = grouplist;
+ g->name = optarg;
+ g->gid = -1;
+ grouplist = g;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc > 1)
+ usage();
+
+ for (g = grouplist; g; g = g->next) {
+ grp = getgrnam(g->name);
+ if (grp != NULL)
+ g->gid = grp->gr_gid;
+ else
+ warnx("%s: no such group", g->name);
+ }
+
+ makemsg(*argv);
+
+ iov.iov_base = mbuf;
+ iov.iov_len = mbufsize;
+ /* NOSTRICT */
+ while ((utmp = getutxent()) != NULL) {
+ if (utmp->ut_type != USER_PROCESS)
+ continue;
+ if (ttystat(utmp->ut_line) != 0)
+ continue;
+ if (grouplist) {
+ ingroup = 0;
+ pw = getpwnam(utmp->ut_user);
+ if (!pw)
+ continue;
+ for (g = grouplist; g && ingroup == 0; g = g->next) {
+ if (g->gid == (gid_t)-1)
+ continue;
+ if (g->gid == pw->pw_gid)
+ ingroup = 1;
+ else if ((grp = getgrgid(g->gid)) != NULL) {
+ for (np = grp->gr_mem; *np; np++) {
+ if (strcmp(*np, utmp->ut_user) == 0) {
+ ingroup = 1;
+ break;
+ }
+ }
+ }
+ }
+ if (ingroup == 0)
+ continue;
+ }
+ if ((p = ttymsg(&iov, 1, utmp->ut_line, 60*5)) != NULL)
+ warnx("%s", p);
+ }
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: wall [-g group] [file]\n");
+ exit(1);
+}
+
+void
+makemsg(char *fname)
+{
+ int cnt;
+ wchar_t ch;
+ struct tm *lt;
+ struct passwd *pw;
+ struct stat sbuf;
+ time_t now;
+ FILE *fp;
+ int fd;
+ char hostname[MAXHOSTNAMELEN], tmpname[64];
+ wchar_t *p, *tmp, lbuf[256], codebuf[13];
+ const char *tty;
+ const char *whom;
+ gid_t egid;
+
+ (void)snprintf(tmpname, sizeof(tmpname), "%s/wall.XXXXXX", _PATH_TMP);
+ if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+")))
+ err(1, "can't open temporary file");
+ (void)unlink(tmpname);
+
+ if (!nobanner) {
+ tty = ttyname(STDERR_FILENO);
+ if (tty == NULL)
+ tty = "no tty";
+
+ if (!(whom = getlogin()))
+ whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
+ (void)gethostname(hostname, sizeof(hostname));
+ (void)time(&now);
+ lt = localtime(&now);
+
+ /*
+ * all this stuff is to blank out a square for the message;
+ * we wrap message lines at column 79, not 80, because some
+ * terminals wrap after 79, some do not, and we can't tell.
+ * Which means that we may leave a non-blank character
+ * in column 80, but that can't be helped.
+ */
+ (void)fwprintf(fp, L"\r%79s\r\n", " ");
+ (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t),
+ L"Broadcast Message from %s@%s",
+ whom, hostname);
+ (void)fwprintf(fp, L"%-79.79S\007\007\r\n", lbuf);
+ (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t),
+ L" (%s) at %d:%02d %s...", tty,
+ lt->tm_hour, lt->tm_min, lt->tm_zone);
+ (void)fwprintf(fp, L"%-79.79S\r\n", lbuf);
+ }
+ (void)fwprintf(fp, L"%79s\r\n", " ");
+
+ if (fname) {
+ egid = getegid();
+ setegid(getgid());
+ if (freopen(fname, "r", stdin) == NULL)
+ err(1, "can't read %s", fname);
+ if (setegid(egid) != 0)
+ err(1, "setegid failed");
+ }
+ cnt = 0;
+ while (fgetws(lbuf, sizeof(lbuf)/sizeof(wchar_t), stdin)) {
+ for (p = lbuf; (ch = *p) != L'\0'; ++p, ++cnt) {
+ if (ch == L'\r') {
+ putwc(L'\r', fp);
+ cnt = 0;
+ continue;
+ } else if (ch == L'\n') {
+ for (; cnt < 79; ++cnt)
+ putwc(L' ', fp);
+ putwc(L'\r', fp);
+ putwc(L'\n', fp);
+ break;
+ }
+ if (cnt == 79) {
+ putwc(L'\r', fp);
+ putwc(L'\n', fp);
+ cnt = 0;
+ }
+ if (iswprint(ch) || iswspace(ch) || ch == L'\a' || ch == L'\b') {
+ putwc(ch, fp);
+ } else {
+ (void)swprintf(codebuf, sizeof(codebuf)/sizeof(wchar_t), L"<0x%X>", ch);
+ for (tmp = codebuf; *tmp != L'\0'; ++tmp) {
+ putwc(*tmp, fp);
+ if (++cnt == 79) {
+ putwc(L'\r', fp);
+ putwc(L'\n', fp);
+ cnt = 0;
+ }
+ }
+ --cnt;
+ }
+ }
+ }
+ (void)fwprintf(fp, L"%79s\r\n", " ");
+ rewind(fp);
+
+ if (fstat(fd, &sbuf))
+ err(1, "can't stat temporary file");
+ mbufsize = sbuf.st_size;
+ if (!(mbuf = malloc((u_int)mbufsize)))
+ err(1, "out of memory");
+ if ((int)fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize)
+ err(1, "can't read temporary file");
+ fclose(fp);
+}
diff --git a/usr.bin/wc/Makefile b/usr.bin/wc/Makefile
new file mode 100644
index 000000000000..e4fe6cb452d6
--- /dev/null
+++ b/usr.bin/wc/Makefile
@@ -0,0 +1,15 @@
+.include <src.opts.mk>
+
+PROG= wc
+LIBADD= xo
+
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+=-DWITH_CASPER
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/wc/Makefile.depend b/usr.bin/wc/Makefile.depend
new file mode 100644
index 000000000000..58dd23ba0203
--- /dev/null
+++ b/usr.bin/wc/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/wc/Makefile.depend.options b/usr.bin/wc/Makefile.depend.options
new file mode 100644
index 000000000000..16ba822617d3
--- /dev/null
+++ b/usr.bin/wc/Makefile.depend.options
@@ -0,0 +1,7 @@
+# This file is not autogenerated - take care!
+
+DIRDEPS_OPTIONS= CASPER
+
+DIRDEPS.CASPER.yes= lib/libcasper/services/cap_fileargs
+
+.include <dirdeps-options.mk>
diff --git a/usr.bin/wc/tests/Makefile b/usr.bin/wc/tests/Makefile
new file mode 100644
index 000000000000..18002a8d70f4
--- /dev/null
+++ b/usr.bin/wc/tests/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= tests
+
+ATF_TESTS_SH= wc_test
+BINDIR= ${TESTSDIR}
+
+.include <bsd.test.mk>
diff --git a/usr.bin/wc/tests/Makefile.depend b/usr.bin/wc/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/wc/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/wc/tests/wc_test.sh b/usr.bin/wc/tests/wc_test.sh
new file mode 100755
index 000000000000..70eb5f5a2b37
--- /dev/null
+++ b/usr.bin/wc/tests/wc_test.sh
@@ -0,0 +1,248 @@
+#
+# Copyright (c) 2023 Klara, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+#
+# These tests need to run in a multibyte locale with non-localized
+# error messages.
+#
+export LC_CTYPE=C.UTF-8
+export LC_MESSAGES=C
+
+#
+# Size of wc's read buffer.
+#
+MAXBSIZE=65536
+
+#
+# Sample text containing multibyte characters
+#
+tv="Der bode en underlig gråsprængt en
+på den yderste nøgne ø; –
+han gjorde visst intet menneske mén
+hverken på land eller sjø;
+dog stundom gnistred hans øjne stygt, –
+helst mod uroligt vejr, –
+og da mente folk, at han var forrykt,
+og da var der få, som uden frykt
+kom Terje Vigen nær.
+"
+tvl=10
+tvw=55
+tvc=300
+tvm=283
+tvcL=42
+tvmL=39
+
+#
+# Run a series of tests using the same input file. The first argument
+# is the name of the file. The next three are the expected line,
+# word, and byte counts. The optional fifth is the expected character
+# count; if not provided, it is expected to be identical to the byte
+# count.
+#
+atf_check_wc() {
+ local file="$1"
+ local l="$2"
+ local w="$3"
+ local c="$4"
+ local m="${5-$4}"
+
+ atf_check -o match:"^ +${l} +${w} +${c}\$" wc <"${file}"
+ atf_check -o match:"^ +${l}\$" wc -l <"${file}"
+ atf_check -o match:"^ +${w}\$" wc -w <"${file}"
+ atf_check -o match:"^ +${c}\$" wc -c <"${file}"
+ atf_check -o match:"^ +${m}\$" wc -m <"${file}"
+ atf_check -o match:"^ +${l} +${w} +${c} ${file}\$" wc "$file"
+ atf_check -o match:"^ +${l} ${file}\$" wc -l "$file"
+ atf_check -o match:"^ +${w} ${file}\$" wc -w "$file"
+ atf_check -o match:"^ +${c} ${file}\$" wc -c "$file"
+ atf_check -o match:"^ +${m} ${file}\$" wc -m "$file"
+}
+
+atf_test_case basic
+basic_head()
+{
+ atf_set "descr" "Basic test case"
+}
+basic_body()
+{
+ printf "a b\n" >foo
+ atf_check_wc foo 1 2 4
+}
+
+atf_test_case blank
+blank_head()
+{
+ atf_set "descr" "Input containing only blank lines"
+}
+blank_body()
+{
+ printf "\n\n\n" >foo
+ atf_check_wc foo 3 0 3
+}
+
+atf_test_case empty
+empty_head()
+{
+ atf_set "descr" "Empty input"
+}
+empty_body()
+{
+ printf "" >foo
+ atf_check_wc foo 0 0 0
+}
+
+atf_test_case invalid
+invalid_head()
+{
+ atf_set "descr" "Invalid multibyte input"
+}
+invalid_body()
+{
+ printf "a\377b\n" >foo
+ atf_check \
+ -e match:"Illegal byte sequence" \
+ -o match:"^ +4 foo$" \
+ wc -m foo
+}
+
+atf_test_case multiline
+multiline_head()
+{
+ atf_set "descr" "Multiline, multibyte input"
+}
+multiline_body()
+{
+ printf "%s\n" "$tv" >foo
+ atf_check_wc foo $tvl $tvw $tvc $tvm
+ # longest line in bytes
+ atf_check -o match:"^ +$tvc +$tvcL foo" wc -cL foo
+ atf_check -o match:"^ +$tvc +$tvcL" wc -cL <foo
+ # longest line in characters
+ atf_check -o match:"^ +$tvm +$tvmL foo" wc -mL foo
+ atf_check -o match:"^ +$tvm +$tvmL" wc -mL <foo
+}
+
+atf_test_case multiline_repeated
+multiline_repeated_head()
+{
+ atf_set "descr" "Multiline input exceeding the input buffer size"
+}
+multiline_repeated_body()
+{
+ local c=0
+ while [ $c -lt 1000 ] ; do
+ printf "%1\$s\n%1\$s\n%1\$s\n%1\$s\n%1\$s\n" "$tv"
+ c=$((c+5))
+ done >foo
+ atf_check_wc foo $((tvl*c)) $((tvw*c)) $((tvc*c)) $((tvm*c))
+}
+
+atf_test_case nul
+nul_head()
+{
+ atf_set "descr" "Input containing NUL"
+}
+nul_body()
+{
+ printf "a\0b\n" >foo
+ atf_check_wc foo 1 1 4
+}
+
+atf_test_case poop
+poop_head()
+{
+ atf_set "descr" "Multibyte sequence across buffer boundary"
+}
+poop_body()
+{
+ local l=0 w=0 c=0 m=0
+ # The code below produces a stream of 4-byte UTF-8 sequences
+ # aligned on 5-byte boundaries, ensuring that the first full
+ # read of length MAXBSIZE will end in a partial sequence —
+ # unless MAXBSIZE is a multiple of 5 (not possible since it's
+ # a power of 2) or one less than a multiple of 5 (e.g. 2^18 =
+ # 262,144 = (52429 * 5) - 1) in which case we prepend a single
+ # newline to push our sequence out of phase.
+ atf_check_not_equal 0 $((MAXBSIZE % 5))
+ :>foo
+ if [ $((MAXBSIZE % 5)) -eq 4 ] ; then
+ printf "\n"
+ l=$((l + 1))
+ c=$((c + 1))
+ m=$((m + 1))
+ fi >>foo
+ while [ $c -le $MAXBSIZE ] ; do
+ printf "💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩.💩\n"
+ l=$((l + 1))
+ w=$((w + 1))
+ c=$((c + 80)) # 80 bytes
+ m=$((m + 32)) # 32 multibyte characters
+ done >>foo
+ atf_check_wc foo $l $w $c $m
+}
+
+atf_test_case total
+total_head()
+{
+ atf_set "descr" "Multiple inputs"
+}
+total_body()
+{
+ printf "%s\n" "$tv" >foo
+ printf "%s\n" "$tv" >bar
+ atf_check \
+ -o match:"^ +$((tvl*2)) +$((tvw*2)) +$((tvc*2)) total$" \
+ wc foo bar
+}
+
+atf_test_case unterminated
+unterminated_head()
+{
+ atf_set "descr" "Input not ending in newline"
+}
+unterminated_body()
+{
+ printf "a b" >foo
+ atf_check_wc foo 0 2 3
+}
+
+atf_test_case usage
+usage_head()
+{
+ atf_set "descr" "Trigger usage message"
+}
+usage_body()
+{
+ atf_check -s exit:1 -e match:"usage: wc" wc -\?
+}
+
+atf_test_case whitespace
+whitespace_head()
+{
+ atf_set "descr" "Input containing only whitespace and newlines"
+}
+whitespace_body()
+{
+ printf "\n \n\t\n" >foo
+ atf_check_wc foo 3 0 5
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case basic
+ atf_add_test_case blank
+ atf_add_test_case empty
+ atf_add_test_case invalid
+ atf_add_test_case multiline
+ atf_add_test_case multiline_repeated
+ atf_add_test_case nul
+ atf_add_test_case poop
+ atf_add_test_case total
+ atf_add_test_case unterminated
+ atf_add_test_case usage
+ atf_add_test_case whitespace
+}
diff --git a/usr.bin/wc/wc.1 b/usr.bin/wc/wc.1
new file mode 100644
index 000000000000..482145c8f01f
--- /dev/null
+++ b/usr.bin/wc/wc.1
@@ -0,0 +1,209 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. 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.
+.\"
+.Dd April 11, 2020
+.Dt WC 1
+.Os
+.Sh NAME
+.Nm wc
+.Nd word, line, character, and byte count
+.Sh SYNOPSIS
+.Nm
+.Op Fl -libxo
+.Op Fl Lclmw
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility displays the number of lines, words, and bytes contained in each
+input
+.Ar file ,
+or standard input (if no file is specified) to the standard output.
+A line is defined as a string of characters delimited by a
+.Aq newline
+character.
+Characters beyond the final
+.Aq newline
+character will not be included
+in the line count.
+.Pp
+A word is defined as a string of characters delimited by white space
+characters.
+White space characters are the set of characters for which the
+.Xr iswspace 3
+function returns true.
+If more than one input file is specified, a line of cumulative counts
+for all the files is displayed on a separate line after the output for
+the last file.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
+.It Fl L
+Write the length of the line containing the most bytes (default) or characters
+(when
+.Fl m
+is provided)
+to standard output.
+When more than one
+.Ar file
+argument is specified, the longest input line of
+.Em all
+files is reported as the value of the final
+.Dq total .
+.It Fl c
+The number of bytes in each input file
+is written to the standard output.
+This will cancel out any prior usage of the
+.Fl m
+option.
+.It Fl l
+The number of lines in each input file
+is written to the standard output.
+.It Fl m
+The number of characters in each input file is written to the standard output.
+If the current locale does not support multibyte characters, this
+is equivalent to the
+.Fl c
+option.
+This will cancel out any prior usage of the
+.Fl c
+option.
+.It Fl w
+The number of words in each input file
+is written to the standard output.
+.El
+.Pp
+When an option is specified,
+.Nm
+only reports the information requested by that option.
+The order of output always takes the form of line, word,
+byte, and file name.
+The default action is equivalent to specifying the
+.Fl c , l
+and
+.Fl w
+options.
+.Pp
+If no files are specified, the standard input is used and no
+file name is displayed.
+The prompt will accept input until receiving EOF, or
+.Bq ^D
+in most environments.
+.Pp
+If
+.Nm
+receives a
+.Dv SIGINFO
+(see the
+.Cm status
+argument for
+.Xr stty 1 )
+signal, the interim data will be written
+to the standard error output in the same format
+as the standard completion message.
+.Sh ENVIRONMENT
+The
+.Ev LANG , LC_ALL
+and
+.Ev LC_CTYPE
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Count the number of characters, words and lines in each of the files
+.Pa report1
+and
+.Pa report2
+as well as the totals for both:
+.Pp
+.Dl "wc -mlw report1 report2"
+.Pp
+Find the longest line in a list of files:
+.Pp
+.Dl "wc -L file1 file2 file3 | fgrep total"
+.Sh COMPATIBILITY
+Historically, the
+.Nm
+utility was documented to define a word as a
+.Do
+maximal string of
+characters delimited by <space>, <tab> or <newline> characters
+.Dc .
+The implementation, however, did not handle non-printing characters
+correctly so that
+.Dq Li "\ \ ^D^E\ \ "
+counted as 6 spaces, while
+.Dq Li foo^D^Ebar
+counted as 8 characters.
+.Bx 4
+systems after
+.Bx 4.3
+modified the implementation to be consistent
+with the documentation.
+This implementation defines a
+.Dq word
+in terms of the
+.Xr iswspace 3
+function, as required by
+.St -p1003.2 .
+.Pp
+The
+.Fl L
+option is a non-standard
+.Fx
+extension, compatible with the
+.Fl L
+option of the GNU
+.Nm
+utility.
+.Sh SEE ALSO
+.Xr iswspace 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/wc/wc.c b/usr.bin/wc/wc.c
new file mode 100644
index 000000000000..7b83412f3c42
--- /dev/null
+++ b/usr.bin/wc/wc.c
@@ -0,0 +1,358 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1987, 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.
+ */
+
+#include <sys/capsicum.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <libxo/xo.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
+
+#define WC_XO_VERSION "1"
+
+static const char *stdin_filename = "stdin";
+
+static fileargs_t *fa;
+static uintmax_t tlinect, twordct, tcharct, tlongline;
+static bool doline, doword, dochar, domulti, dolongline;
+static volatile sig_atomic_t siginfo;
+static xo_handle_t *stderr_handle;
+
+static void show_cnt(const char *file, uintmax_t linect, uintmax_t wordct,
+ uintmax_t charct, uintmax_t llct);
+static int cnt(const char *);
+static void usage(void);
+
+static void
+siginfo_handler(int sig __unused)
+{
+
+ siginfo = 1;
+}
+
+static void
+reset_siginfo(void)
+{
+
+ signal(SIGINFO, SIG_DFL);
+ siginfo = 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, errors, total;
+ cap_rights_t rights;
+
+ (void) setlocale(LC_CTYPE, "");
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(EXIT_FAILURE);
+
+ while ((ch = getopt(argc, argv, "clmwL")) != -1)
+ switch((char)ch) {
+ case 'l':
+ doline = true;
+ break;
+ case 'w':
+ doword = true;
+ break;
+ case 'c':
+ dochar = true;
+ domulti = false;
+ break;
+ case 'L':
+ dolongline = true;
+ break;
+ case 'm':
+ domulti = true;
+ dochar = false;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+ fa = fileargs_init(argc, argv, O_RDONLY, 0,
+ cap_rights_init(&rights, CAP_READ, CAP_FSTAT), FA_OPEN);
+ if (fa == NULL)
+ xo_err(EXIT_FAILURE, "Unable to initialize casper");
+ caph_cache_catpages();
+ if (caph_limit_stdio() < 0)
+ xo_err(EXIT_FAILURE, "Unable to limit stdio");
+ if (caph_enter_casper() < 0)
+ xo_err(EXIT_FAILURE, "Unable to enter capability mode");
+
+ /* Wc's flags are on by default. */
+ if (!(doline || doword || dochar || domulti || dolongline))
+ doline = doword = dochar = true;
+
+ stderr_handle = xo_create_to_file(stderr, XO_STYLE_TEXT, 0);
+
+ xo_set_version(WC_XO_VERSION);
+ xo_open_container("wc");
+ xo_open_list("file");
+
+ (void)signal(SIGINFO, siginfo_handler);
+ errors = 0;
+ total = 0;
+ if (argc == 0) {
+ xo_open_instance("file");
+ if (cnt(NULL) != 0)
+ ++errors;
+ xo_close_instance("file");
+ } else {
+ while (argc--) {
+ xo_open_instance("file");
+ if (cnt(*argv++) != 0)
+ ++errors;
+ xo_close_instance("file");
+ ++total;
+ }
+ }
+
+ xo_close_list("file");
+
+ if (total > 1) {
+ xo_open_container("total");
+ show_cnt("total", tlinect, twordct, tcharct, tlongline);
+ xo_close_container("total");
+ }
+
+ fileargs_free(fa);
+ xo_close_container("wc");
+ if (xo_finish() < 0)
+ xo_err(EXIT_FAILURE, "stdout");
+ exit(errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void
+show_cnt(const char *file, uintmax_t linect, uintmax_t wordct,
+ uintmax_t charct, uintmax_t llct)
+{
+ xo_handle_t *xop;
+
+ if (!siginfo)
+ xop = NULL;
+ else {
+ xop = stderr_handle;
+ siginfo = 0;
+ }
+
+ if (doline)
+ xo_emit_h(xop, " {:lines/%7ju/%ju}", linect);
+ if (doword)
+ xo_emit_h(xop, " {:words/%7ju/%ju}", wordct);
+ if (dochar || domulti)
+ xo_emit_h(xop, " {:characters/%7ju/%ju}", charct);
+ if (dolongline)
+ xo_emit_h(xop, " {:long-lines/%7ju/%ju}", llct);
+ if (file != stdin_filename)
+ xo_emit_h(xop, " {:filename/%s}\n", file);
+ else
+ xo_emit_h(xop, "\n");
+}
+
+static int
+cnt(const char *file)
+{
+ static char buf[MAXBSIZE];
+ struct stat sb;
+ mbstate_t mbs;
+ const char *p;
+ uintmax_t linect, wordct, charct, llct, tmpll;
+ ssize_t len;
+ size_t clen;
+ int fd;
+ wchar_t wch;
+ bool gotsp, warned;
+
+ linect = wordct = charct = llct = tmpll = 0;
+ if (file == NULL) {
+ fd = STDIN_FILENO;
+ file = stdin_filename;
+ } else if ((fd = fileargs_open(fa, file)) < 0) {
+ xo_warn("%s: open", file);
+ return (1);
+ }
+ if (doword || (domulti && MB_CUR_MAX != 1))
+ goto word;
+ /*
+ * If all we need is the number of characters and it's a regular file,
+ * just stat it.
+ */
+ if (doline == 0 && dolongline == 0) {
+ if (fstat(fd, &sb)) {
+ xo_warn("%s: fstat", file);
+ (void)close(fd);
+ return (1);
+ }
+ /* pseudo-filesystems advertize a zero size */
+ if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
+ reset_siginfo();
+ charct = sb.st_size;
+ show_cnt(file, linect, wordct, charct, llct);
+ tcharct += charct;
+ (void)close(fd);
+ return (0);
+ }
+ }
+ /*
+ * For files we can't stat, or if we need line counting, slurp the
+ * file. Line counting is split out because it's a lot faster to get
+ * lines than to get words, since the word count requires locale
+ * handling.
+ */
+ while ((len = read(fd, buf, sizeof(buf))) != 0) {
+ if (len < 0) {
+ xo_warn("%s: read", file);
+ (void)close(fd);
+ return (1);
+ }
+ if (siginfo)
+ show_cnt(file, linect, wordct, charct, llct);
+ charct += len;
+ if (doline || dolongline) {
+ for (p = buf; len > 0; --len, ++p) {
+ if (*p == '\n') {
+ if (tmpll > llct)
+ llct = tmpll;
+ tmpll = 0;
+ ++linect;
+ } else {
+ tmpll++;
+ }
+ }
+ }
+ }
+ reset_siginfo();
+ if (doline)
+ tlinect += linect;
+ if (dochar)
+ tcharct += charct;
+ if (dolongline && llct > tlongline)
+ tlongline = llct;
+ show_cnt(file, linect, wordct, charct, llct);
+ (void)close(fd);
+ return (0);
+
+ /* Do it the hard way... */
+word: gotsp = true;
+ warned = false;
+ memset(&mbs, 0, sizeof(mbs));
+ while ((len = read(fd, buf, sizeof(buf))) != 0) {
+ if (len < 0) {
+ xo_warn("%s: read", file);
+ (void)close(fd);
+ return (1);
+ }
+ p = buf;
+ while (len > 0) {
+ if (siginfo)
+ show_cnt(file, linect, wordct, charct, llct);
+ if (!domulti || MB_CUR_MAX == 1) {
+ clen = 1;
+ wch = (unsigned char)*p;
+ } else if ((clen = mbrtowc(&wch, p, len, &mbs)) == 0) {
+ clen = 1;
+ } else if (clen == (size_t)-1) {
+ if (!warned) {
+ errno = EILSEQ;
+ xo_warn("%s", file);
+ warned = true;
+ }
+ memset(&mbs, 0, sizeof(mbs));
+ clen = 1;
+ wch = (unsigned char)*p;
+ } else if (clen == (size_t)-2) {
+ break;
+ }
+ charct++;
+ if (wch != L'\n')
+ tmpll++;
+ len -= clen;
+ p += clen;
+ if (wch == L'\n') {
+ if (tmpll > llct)
+ llct = tmpll;
+ tmpll = 0;
+ ++linect;
+ }
+ if (iswspace(wch)) {
+ gotsp = true;
+ } else if (gotsp) {
+ gotsp = false;
+ ++wordct;
+ }
+ }
+ }
+ reset_siginfo();
+ if (domulti && MB_CUR_MAX > 1) {
+ if (mbrtowc(NULL, NULL, 0, &mbs) == (size_t)-1 && !warned)
+ xo_warn("%s", file);
+ }
+ if (doline)
+ tlinect += linect;
+ if (doword)
+ twordct += wordct;
+ if (dochar || domulti)
+ tcharct += charct;
+ if (dolongline && llct > tlongline)
+ tlongline = llct;
+ show_cnt(file, linect, wordct, charct, llct);
+ (void)close(fd);
+ return (0);
+}
+
+static void
+usage(void)
+{
+ xo_error("usage: wc [-Lclmw] [file ...]\n");
+ exit(EXIT_FAILURE);
+}
diff --git a/usr.bin/wg/Makefile b/usr.bin/wg/Makefile
new file mode 100644
index 000000000000..4d7ffc19764c
--- /dev/null
+++ b/usr.bin/wg/Makefile
@@ -0,0 +1,37 @@
+PROG= wg
+MAN= wg.8
+
+LIBADD= nv
+
+.PATH: ${SRCTOP}/contrib/wireguard-tools
+.PATH: ${SRCTOP}/contrib/wireguard-tools/man
+
+SRCS+= wg.c
+
+SRCS+= config.c
+SRCS+= encoding.c
+SRCS+= ipc.c
+SRCS+= terminal.c
+
+SRCS+= curve25519.c
+
+# Subcommands
+SRCS+= show.c
+SRCS+= showconf.c
+SRCS+= set.c
+SRCS+= setconf.c
+SRCS+= genkey.c
+SRCS+= pubkey.c
+
+# Base should pull RUNSTATEDIR from paths.h, _PATH_VARRUN
+CFLAGS+= -include paths.h
+CFLAGS+= -DRUNSTATEDIR="_PATH_VARRUN"
+
+# Not going to change this one.
+CWARNFLAGS.curve25519.c+= -Wno-shadow
+
+# sockaddr{,_in} alignment
+CWARNFLAGS.config.c+= -Wno-cast-align
+CWARNFLAGS.ipc.c+= -Wno-cast-align
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/what/Makefile b/usr.bin/what/Makefile
new file mode 100644
index 000000000000..7b242889d371
--- /dev/null
+++ b/usr.bin/what/Makefile
@@ -0,0 +1,4 @@
+PACKAGE= runtime
+PROG= what
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/what/Makefile.depend b/usr.bin/what/Makefile.depend
new file mode 100644
index 000000000000..93249906da4f
--- /dev/null
+++ b/usr.bin/what/Makefile.depend
@@ -0,0 +1,14 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/what/what.1 b/usr.bin/what/what.1
new file mode 100644
index 000000000000..d821896be971
--- /dev/null
+++ b/usr.bin/what/what.1
@@ -0,0 +1,85 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd December 14, 2006
+.Dt WHAT 1
+.Os
+.Sh NAME
+.Nm what
+.Nd "show what versions of object modules were used to construct a file"
+.Sh SYNOPSIS
+.Nm
+.Op Fl qs
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility searches each specified
+.Ar file
+for sequences of the form
+.Dq Li @(#)
+as inserted by the
+.Tn SCCS
+source code control system.
+It prints the remainder
+of the string following this marker, up to a NUL character, newline, double
+quote,
+.Ql \&>
+character, or backslash.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl q
+Only output the match text, rather than formatting it.
+.It Fl s
+Stop searching each file after the first match.
+.El
+.Sh EXIT STATUS
+Exit status is 0 if any matches were found, otherwise 1.
+.Sh SEE ALSO
+.Xr ident 1 ,
+.Xr strings 1
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+The
+.Fl q
+option is a non-standard
+.Fx
+extension which may not be available on other operating systems.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
+.Sh BUGS
+This is a rewrite of the
+.Tn SCCS
+command of the same name,
+and behavior may not be identical.
diff --git a/usr.bin/what/what.c b/usr.bin/what/what.c
new file mode 100644
index 000000000000..9ebefe02d842
--- /dev/null
+++ b/usr.bin/what/what.c
@@ -0,0 +1,125 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 1988, 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.
+ */
+
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void usage(void) __dead2;
+static bool search(bool, bool, FILE *);
+
+int
+main(int argc, char *argv[])
+{
+ const char *file;
+ FILE *in;
+ bool found, qflag, sflag;
+ int c;
+
+ qflag = sflag = false;
+
+ while ((c = getopt(argc, argv, "qs")) != -1) {
+ switch (c) {
+ case 'q':
+ qflag = true;
+ break;
+ case 's':
+ sflag = true;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ found = false;
+
+ if (argc == 0) {
+ if (search(sflag, qflag, stdin))
+ found = true;
+ } else {
+ while (argc--) {
+ file = *argv++;
+ in = fopen(file, "r");
+ if (in == NULL) {
+ if (!qflag)
+ warn("%s", file);
+ continue;
+ }
+ if (!qflag)
+ printf("%s:\n", file);
+ if (search(sflag, qflag, in))
+ found = true;
+ fclose(in);
+ }
+ }
+ exit(found ? 0 : 1);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: what [-qs] [file ...]\n");
+ exit(1);
+}
+
+bool
+search(bool one, bool quiet, FILE *in)
+{
+ bool found;
+ int c;
+
+ found = false;
+
+ while ((c = getc(in)) != EOF) {
+loop: if (c != '@')
+ continue;
+ if ((c = getc(in)) != '(')
+ goto loop;
+ if ((c = getc(in)) != '#')
+ goto loop;
+ if ((c = getc(in)) != ')')
+ goto loop;
+ if (!quiet)
+ putchar('\t');
+ while ((c = getc(in)) != EOF && c && c != '"' &&
+ c != '>' && c != '\\' && c != '\n')
+ putchar(c);
+ putchar('\n');
+ found = true;
+ if (one)
+ break;
+ }
+ return (found);
+}
diff --git a/usr.bin/whereis/Makefile b/usr.bin/whereis/Makefile
new file mode 100644
index 000000000000..5803279820fe
--- /dev/null
+++ b/usr.bin/whereis/Makefile
@@ -0,0 +1,3 @@
+PROG= whereis
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/whereis/Makefile.depend b/usr.bin/whereis/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/whereis/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/whereis/pathnames.h b/usr.bin/whereis/pathnames.h
new file mode 100644
index 000000000000..b7ac47ca93e9
--- /dev/null
+++ b/usr.bin/whereis/pathnames.h
@@ -0,0 +1,55 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright © 2002, Jörg Wunsch
+ *
+ * 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 AUTHOR(S) ``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(S) 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.
+ */
+
+/* Where to look for libexec */
+#define PATH_LIBEXEC "/usr/libexec"
+
+/* Where to look for sources. */
+#define PATH_SOURCES \
+"/usr/src/bin:/usr/src/usr.bin:/usr/src/sbin:" \
+"/usr/src/usr.sbin:/usr/src/libexec:" \
+"/usr/src/gnu/bin:/usr/src/gnu/usr.bin:" \
+"/usr/src/gnu/sbin:/usr/src/gnu/usr.sbin:" \
+"/usr/src/contrib:" \
+"/usr/src/secure/bin:/usr/src/secure/usr.bin:" \
+"/usr/src/secure/sbin:/usr/src/secure/usr.sbin:" \
+"/usr/src/secure/libexec:/usr/src/crypto:" \
+"/usr/src/games"
+
+/* Each subdirectory of PATH_PORTS will be appended to PATH_SOURCES. */
+#define PATH_PORTS "/usr/ports"
+
+/* How to query the current manpath. */
+#define MANPATHCMD "manpath -q"
+
+/* How to obtain the location of manpages, and how to match this result. */
+#define MANWHEREISCMD "man -S1:8:6 -w %s 2>/dev/null"
+#define MANWHEREISALLCMD "man -a -w %s 2>/dev/null"
+#define MANWHEREISMATCH "^.* [(]source: (.*)[)]$"
+
+/* Command used to locate sources that have not been found yet. */
+#define LOCATECMD "locate '*'/%s 2>/dev/null"
diff --git a/usr.bin/whereis/whereis.1 b/usr.bin/whereis/whereis.1
new file mode 100644
index 000000000000..90922ce61db5
--- /dev/null
+++ b/usr.bin/whereis/whereis.1
@@ -0,0 +1,181 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Copyright 2002 Joerg Wunsch
+.\"
+.\" 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.
+.\"
+.Dd August 22, 2002
+.Dt WHEREIS 1
+.Os
+.Sh NAME
+.Nm whereis
+.Nd locate programs
+.Sh SYNOPSIS
+.Nm
+.Op Fl abmqsux
+.Op Fl BMS Ar dir ... Fl f
+.Ar program ...
+.Sh DESCRIPTION
+The
+.Nm
+utility checks the standard binary, manual page, and source
+directories for the specified programs, printing out the paths of any
+it finds.
+The supplied program names are first stripped of leading
+path name components, any single trailing extension added by
+.Xr gzip 1 ,
+.Xr compress 1 ,
+or
+.Xr bzip2 1 ,
+and the leading
+.Ql s.\&
+or trailing
+.Ql ,v
+from a source code control system.
+.Pp
+The default path searched is the string returned by the
+.Xr sysctl 8
+utility for the
+.Dq user.cs_path
+string, with
+.Pa /usr/libexec
+and the current user's
+.Ev $PATH
+appended.
+Manual pages are searched by default along the
+.Ev $MANPATH .
+Program sources are located in a list of known standard places,
+including all the subdirectories of
+.Pa /usr/src
+and
+.Pa /usr/ports .
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl B
+Specify directories to search for binaries.
+Requires the
+.Fl f
+option.
+.It Fl M
+Specify directories to search for manual pages.
+Requires the
+.Fl f
+option.
+.It Fl S
+Specify directories to search for program sources.
+Requires the
+.Fl f
+option.
+.It Fl a
+Report all matches instead of only the first of each requested type.
+.It Fl b
+Search for binaries.
+.It Fl f
+Delimits the list of directories after the
+.Fl B ,
+.Fl M ,
+or
+.Fl S
+options, and indicates the beginning of the
+.Ar program
+list.
+.It Fl m
+Search for manual pages.
+.It Fl q
+.Pq Dq quiet .
+Suppress the output of the utility name in front of the normal
+output line.
+This can become handy for use in a backquote substitution of a
+shell command line, see
+.Sx EXAMPLES .
+.It Fl s
+Search for source directories.
+.It Fl u
+Search for
+.Dq unusual
+entries.
+A file is said to be unusual if it does not have at least
+one entry of each requested type.
+Only the name of the unusual entry is printed.
+.It Fl x
+Do not use
+.Dq expensive
+tools when searching for source directories.
+Normally, after unsuccessfully searching all the first-level
+subdirectories of the source directory list,
+.Nm
+will ask
+.Xr locate 1
+to find the entry on its behalf.
+Since this can take much longer, it can be turned off with
+.Fl x .
+.El
+.Sh EXAMPLES
+The following finds all utilities under
+.Pa /usr/bin
+that do not have documentation:
+.Pp
+.Dl whereis -m -u /usr/bin/*
+.Pp
+Change to the source code directory of
+.Xr ls 1 :
+.Pp
+.Dl cd `whereis -sq ls`
+.Sh SEE ALSO
+.Xr find 1 ,
+.Xr locate 1 ,
+.Xr man 1 ,
+.Xr which 1 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 3.0 .
+This version re-implements the historical
+functionality that was lost in
+.Bx 4.4 .
+.Sh AUTHORS
+This implementation of the
+.Nm
+command was written by
+.An J\(:org Wunsch .
+.Sh BUGS
+This re-implementation of the
+.Nm
+utility is not bug-for-bug compatible with historical versions.
+It is believed to be compatible with the version that was shipping with
+.Fx 2.2
+through
+.Fx 4.5
+though.
+.Pp
+The
+.Nm
+utility can report some unrelated source entries when the
+.Fl a
+option is specified.
diff --git a/usr.bin/whereis/whereis.c b/usr.bin/whereis/whereis.c
new file mode 100644
index 000000000000..8de56b9cf654
--- /dev/null
+++ b/usr.bin/whereis/whereis.c
@@ -0,0 +1,688 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright © 2002, Jörg Wunsch
+ *
+ * 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 AUTHOR(S) ``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(S) 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.
+ */
+
+/*
+ * 4.3BSD UI-compatible whereis(1) utility. Rewritten from scratch
+ * since the original 4.3BSD version suffers legal problems that
+ * prevent it from being redistributed, and since the 4.4BSD version
+ * was pretty inferior in functionality.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+#define NO_BIN_FOUND 1
+#define NO_MAN_FOUND 2
+#define NO_SRC_FOUND 4
+
+typedef const char *ccharp;
+
+static int opt_a, opt_b, opt_m, opt_q, opt_s, opt_u, opt_x;
+static ccharp *bindirs, *mandirs, *sourcedirs;
+static char **query;
+
+static const char *sourcepath = PATH_SOURCES;
+
+static char *colonify(ccharp *);
+static int contains(ccharp *, const char *);
+static void decolonify(char *, ccharp **, int *);
+static void defaults(void);
+static void scanopts(int, char **);
+static void usage(void);
+
+/*
+ * Throughout this program, a number of strings are dynamically
+ * allocated but never freed. Their memory is written to when
+ * splitting the strings into string lists which will later be
+ * processed. Since it's important that those string lists remain
+ * valid even after the functions allocating the memory returned,
+ * those functions cannot free them. They could be freed only at end
+ * of main(), which is pretty pointless anyway.
+ *
+ * The overall amount of memory to be allocated for processing the
+ * strings is not expected to exceed a few kilobytes. For that
+ * reason, allocation can usually always be assumed to succeed (within
+ * a virtual memory environment), thus we simply bail out using
+ * abort(3) in case of an allocation failure.
+ */
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: whereis [-abmqsux] [-BMS dir ... -f] program ...\n");
+ exit(EX_USAGE);
+}
+
+/*
+ * Scan options passed to program.
+ *
+ * Note that the -B/-M/-S options expect a list of directory
+ * names that must be terminated with -f.
+ */
+static void
+scanopts(int argc, char **argv)
+{
+ int c, i;
+ ccharp **dirlist;
+
+ while ((c = getopt(argc, argv, "BMSabfmqsux")) != -1)
+ switch (c) {
+ case 'B':
+ dirlist = &bindirs;
+ goto dolist;
+
+ case 'M':
+ dirlist = &mandirs;
+ goto dolist;
+
+ case 'S':
+ dirlist = &sourcedirs;
+ dolist:
+ i = 0;
+ *dirlist = realloc(*dirlist, (i + 1) * sizeof(char *));
+ (*dirlist)[i] = NULL;
+ while (optind < argc &&
+ strcmp(argv[optind], "-f") != 0 &&
+ strcmp(argv[optind], "-B") != 0 &&
+ strcmp(argv[optind], "-M") != 0 &&
+ strcmp(argv[optind], "-S") != 0) {
+ decolonify(argv[optind], dirlist, &i);
+ optind++;
+ }
+ break;
+
+ case 'a':
+ opt_a = 1;
+ break;
+
+ case 'b':
+ opt_b = 1;
+ break;
+
+ case 'f':
+ goto breakout;
+
+ case 'm':
+ opt_m = 1;
+ break;
+
+ case 'q':
+ opt_q = 1;
+ break;
+
+ case 's':
+ opt_s = 1;
+ break;
+
+ case 'u':
+ opt_u = 1;
+ break;
+
+ case 'x':
+ opt_x = 1;
+ break;
+
+ default:
+ usage();
+ }
+ breakout:
+ if (optind == argc)
+ usage();
+ query = argv + optind;
+}
+
+/*
+ * Find out whether string `s' is contained in list `cpp'.
+ */
+static int
+contains(ccharp *cpp, const char *s)
+{
+ ccharp cp;
+
+ if (cpp == NULL)
+ return (0);
+
+ while ((cp = *cpp) != NULL) {
+ if (strcmp(cp, s) == 0)
+ return (1);
+ cpp++;
+ }
+ return (0);
+}
+
+/*
+ * Split string `s' at colons, and pass it to the string list pointed
+ * to by `cppp' (which has `*ip' elements). Note that the original
+ * string is modified by replacing the colon with a NUL byte. The
+ * partial string is only added if it has a length greater than 0, and
+ * if it's not already contained in the string list.
+ */
+static void
+decolonify(char *s, ccharp **cppp, int *ip)
+{
+ char *cp;
+
+ while ((cp = strchr(s, ':')), *s != '\0') {
+ if (cp)
+ *cp = '\0';
+ if (strlen(s) && !contains(*cppp, s)) {
+ *cppp = realloc(*cppp, (*ip + 2) * sizeof(char *));
+ if (*cppp == NULL)
+ abort();
+ (*cppp)[*ip] = s;
+ (*cppp)[*ip + 1] = NULL;
+ (*ip)++;
+ }
+ if (cp)
+ s = cp + 1;
+ else
+ break;
+ }
+}
+
+/*
+ * Join string list `cpp' into a colon-separated string.
+ */
+static char *
+colonify(ccharp *cpp)
+{
+ size_t s;
+ char *cp;
+ int i;
+
+ if (cpp == NULL)
+ return (0);
+
+ for (s = 0, i = 0; cpp[i] != NULL; i++)
+ s += strlen(cpp[i]) + 1;
+ if ((cp = malloc(s + 1)) == NULL)
+ abort();
+ for (i = 0, *cp = '\0'; cpp[i] != NULL; i++) {
+ strcat(cp, cpp[i]);
+ strcat(cp, ":");
+ }
+ cp[s - 1] = '\0'; /* eliminate last colon */
+
+ return (cp);
+}
+
+/*
+ * Provide defaults for all options and directory lists.
+ */
+static void
+defaults(void)
+{
+ size_t s;
+ char *b, buf[BUFSIZ], *cp;
+ int nele;
+ FILE *p;
+ DIR *dir;
+ struct stat sb;
+ struct dirent *dirp;
+ const int oid[2] = {CTL_USER, USER_CS_PATH};
+
+ /* default to -bms if none has been specified */
+ if (!opt_b && !opt_m && !opt_s)
+ opt_b = opt_m = opt_s = 1;
+
+ /* -b defaults to default path + /usr/libexec +
+ * user's path */
+ if (!bindirs) {
+ if (sysctl(oid, 2, NULL, &s, NULL, 0) == -1)
+ err(EX_OSERR, "sysctl(\"user.cs_path\")");
+ if ((b = malloc(s + 1)) == NULL)
+ abort();
+ if (sysctl(oid, 2, b, &s, NULL, 0) == -1)
+ err(EX_OSERR, "sysctl(\"user.cs_path\")");
+ nele = 0;
+ decolonify(b, &bindirs, &nele);
+ bindirs = realloc(bindirs, (nele + 2) * sizeof(char *));
+ if (bindirs == NULL)
+ abort();
+ bindirs[nele++] = PATH_LIBEXEC;
+ bindirs[nele] = NULL;
+ if ((cp = getenv("PATH")) != NULL) {
+ /* don't destroy the original environment... */
+ b = strdup(cp);
+ if (b == NULL)
+ abort();
+ decolonify(b, &bindirs, &nele);
+ }
+ }
+
+ /* -m defaults to $(manpath) */
+ if (!mandirs) {
+ if ((p = popen(MANPATHCMD, "r")) == NULL)
+ err(EX_OSERR, "cannot execute manpath command");
+ if (fgets(buf, BUFSIZ - 1, p) == NULL ||
+ pclose(p))
+ err(EX_OSERR, "error processing manpath results");
+ if ((b = strchr(buf, '\n')) != NULL)
+ *b = '\0';
+ b = strdup(buf);
+ if (b == NULL)
+ abort();
+ nele = 0;
+ decolonify(b, &mandirs, &nele);
+ }
+
+ /* -s defaults to precompiled list, plus subdirs of /usr/ports */
+ if (!sourcedirs) {
+ b = strdup(sourcepath);
+ if (b == NULL)
+ abort();
+ nele = 0;
+ decolonify(b, &sourcedirs, &nele);
+
+ if (stat(PATH_PORTS, &sb) == -1) {
+ if (errno == ENOENT)
+ /* no /usr/ports, we are done */
+ return;
+ err(EX_OSERR, "stat(" PATH_PORTS ")");
+ }
+ if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ /* /usr/ports is not a directory, ignore */
+ return;
+ if (access(PATH_PORTS, R_OK | X_OK) != 0)
+ return;
+ if ((dir = opendir(PATH_PORTS)) == NULL)
+ err(EX_OSERR, "opendir" PATH_PORTS ")");
+ while ((dirp = readdir(dir)) != NULL) {
+ /*
+ * Not everything below PATH_PORTS is of
+ * interest. First, all dot files and
+ * directories (e. g. .snap) can be ignored.
+ * Also, all subdirectories starting with a
+ * capital letter are not going to be
+ * examined, as they are used for internal
+ * purposes (Mk, Tools, ...). This also
+ * matches a possible CVS subdirectory.
+ * Finally, the distfiles subdirectory is also
+ * special, and should not be considered to
+ * avoid false matches.
+ */
+ if (dirp->d_name[0] == '.' ||
+ /*
+ * isupper() not used on purpose: the
+ * check is supposed to default to the C
+ * locale instead of the current user's
+ * locale.
+ */
+ (dirp->d_name[0] >= 'A' && dirp->d_name[0] <= 'Z') ||
+ strcmp(dirp->d_name, "distfiles") == 0)
+ continue;
+ if ((b = malloc(sizeof PATH_PORTS + 1 + dirp->d_namlen))
+ == NULL)
+ abort();
+ strcpy(b, PATH_PORTS);
+ strcat(b, "/");
+ strcat(b, dirp->d_name);
+ if (stat(b, &sb) == -1 ||
+ (sb.st_mode & S_IFMT) != S_IFDIR ||
+ access(b, R_OK | X_OK) != 0) {
+ free(b);
+ continue;
+ }
+ sourcedirs = realloc(sourcedirs,
+ (nele + 2) * sizeof(char *));
+ if (sourcedirs == NULL)
+ abort();
+ sourcedirs[nele++] = b;
+ sourcedirs[nele] = NULL;
+ }
+ closedir(dir);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int unusual, i, printed;
+ char *bin, buf[BUFSIZ], *cp, *cp2, *man, *name, *src;
+ ccharp *dp;
+ size_t nlen, olen, s;
+ struct stat sb;
+ regex_t re, re2;
+ regmatch_t matches[2];
+ regoff_t rlen;
+ FILE *p;
+
+ setlocale(LC_ALL, "");
+
+ scanopts(argc, argv);
+ defaults();
+
+ if (mandirs == NULL)
+ opt_m = 0;
+ if (bindirs == NULL)
+ opt_b = 0;
+ if (sourcedirs == NULL)
+ opt_s = 0;
+ if (opt_m + opt_b + opt_s == 0)
+ errx(EX_DATAERR, "no directories to search");
+
+ if (opt_m) {
+ setenv("MANPATH", colonify(mandirs), 1);
+ if ((i = regcomp(&re, MANWHEREISMATCH, REG_EXTENDED)) != 0) {
+ regerror(i, &re, buf, BUFSIZ - 1);
+ errx(EX_UNAVAILABLE, "regcomp(%s) failed: %s",
+ MANWHEREISMATCH, buf);
+ }
+ }
+
+ for (; (name = *query) != NULL; query++) {
+ /* strip leading path name component */
+ if ((cp = strrchr(name, '/')) != NULL)
+ name = cp + 1;
+ /* strip SCCS or RCS suffix/prefix */
+ if (strlen(name) > 2 && strncmp(name, "s.", 2) == 0)
+ name += 2;
+ if ((s = strlen(name)) > 2 && strcmp(name + s - 2, ",v") == 0)
+ name[s - 2] = '\0';
+ /* compression suffix */
+ s = strlen(name);
+ if (s > 2 &&
+ (strcmp(name + s - 2, ".z") == 0 ||
+ strcmp(name + s - 2, ".Z") == 0))
+ name[s - 2] = '\0';
+ else if (s > 3 &&
+ strcmp(name + s - 3, ".gz") == 0)
+ name[s - 3] = '\0';
+ else if (s > 4 &&
+ strcmp(name + s - 4, ".bz2") == 0)
+ name[s - 4] = '\0';
+
+ unusual = 0;
+ bin = man = src = NULL;
+ s = strlen(name);
+
+ if (opt_b) {
+ /*
+ * Binaries have to match exactly, and must be regular
+ * executable files.
+ */
+ unusual = unusual | NO_BIN_FOUND;
+ for (dp = bindirs; *dp != NULL; dp++) {
+ cp = malloc(strlen(*dp) + 1 + s + 1);
+ if (cp == NULL)
+ abort();
+ strcpy(cp, *dp);
+ strcat(cp, "/");
+ strcat(cp, name);
+ if (stat(cp, &sb) == 0 &&
+ (sb.st_mode & S_IFMT) == S_IFREG &&
+ (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+ != 0) {
+ unusual = unusual & ~NO_BIN_FOUND;
+ if (bin == NULL) {
+ bin = strdup(cp);
+ } else {
+ olen = strlen(bin);
+ nlen = strlen(cp);
+ bin = realloc(bin,
+ olen + nlen + 2);
+ if (bin == NULL)
+ abort();
+ strcat(bin, " ");
+ strcat(bin, cp);
+ }
+ if (!opt_a) {
+ free(cp);
+ break;
+ }
+ }
+ free(cp);
+ }
+ }
+
+ if (opt_m) {
+ /*
+ * Ask the man command to perform the search for us.
+ */
+ unusual = unusual | NO_MAN_FOUND;
+ if (opt_a)
+ cp = malloc(sizeof MANWHEREISALLCMD - 2 + s);
+ else
+ cp = malloc(sizeof MANWHEREISCMD - 2 + s);
+
+ if (cp == NULL)
+ abort();
+
+ if (opt_a)
+ sprintf(cp, MANWHEREISALLCMD, name);
+ else
+ sprintf(cp, MANWHEREISCMD, name);
+
+ if ((p = popen(cp, "r")) != NULL) {
+
+ while (fgets(buf, BUFSIZ - 1, p) != NULL) {
+ unusual = unusual & ~NO_MAN_FOUND;
+
+ if ((cp2 = strchr(buf, '\n')) != NULL)
+ *cp2 = '\0';
+ if (regexec(&re, buf, 2,
+ matches, 0) == 0 &&
+ (rlen = matches[1].rm_eo -
+ matches[1].rm_so) > 0) {
+ /*
+ * man -w found formatted
+ * page, need to pick up
+ * source page name.
+ */
+ cp2 = malloc(rlen + 1);
+ if (cp2 == NULL)
+ abort();
+ memcpy(cp2,
+ buf + matches[1].rm_so,
+ rlen);
+ cp2[rlen] = '\0';
+ } else {
+ /*
+ * man -w found plain source
+ * page, use it.
+ */
+ cp2 = strdup(buf);
+ if (cp2 == NULL)
+ abort();
+ }
+
+ if (man == NULL) {
+ man = strdup(cp2);
+ } else {
+ olen = strlen(man);
+ nlen = strlen(cp2);
+ man = realloc(man,
+ olen + nlen + 2);
+ if (man == NULL)
+ abort();
+ strcat(man, " ");
+ strcat(man, cp2);
+ }
+
+ free(cp2);
+
+ if (!opt_a)
+ break;
+ }
+ pclose(p);
+ free(cp);
+ }
+ }
+
+ if (opt_s) {
+ /*
+ * Sources match if a subdir with the exact
+ * name is found.
+ */
+ unusual = unusual | NO_SRC_FOUND;
+ for (dp = sourcedirs; *dp != NULL; dp++) {
+ cp = malloc(strlen(*dp) + 1 + s + 1);
+ if (cp == NULL)
+ abort();
+ strcpy(cp, *dp);
+ strcat(cp, "/");
+ strcat(cp, name);
+ if (stat(cp, &sb) == 0 &&
+ (sb.st_mode & S_IFMT) == S_IFDIR) {
+ unusual = unusual & ~NO_SRC_FOUND;
+ if (src == NULL) {
+ src = strdup(cp);
+ } else {
+ olen = strlen(src);
+ nlen = strlen(cp);
+ src = realloc(src,
+ olen + nlen + 2);
+ if (src == NULL)
+ abort();
+ strcat(src, " ");
+ strcat(src, cp);
+ }
+ if (!opt_a) {
+ free(cp);
+ break;
+ }
+ }
+ free(cp);
+ }
+ /*
+ * If still not found, ask locate to search it
+ * for us. This will find sources for things
+ * like lpr that are well hidden in the
+ * /usr/src tree, but takes a lot longer.
+ * Thus, option -x (`expensive') prevents this
+ * search.
+ *
+ * Do only match locate output that starts
+ * with one of our source directories, and at
+ * least one further level of subdirectories.
+ */
+ if (opt_x || (src && !opt_a))
+ goto done_sources;
+
+ cp = malloc(sizeof LOCATECMD - 2 + s);
+ if (cp == NULL)
+ abort();
+ sprintf(cp, LOCATECMD, name);
+ if ((p = popen(cp, "r")) == NULL)
+ goto done_sources;
+ while ((src == NULL || opt_a) &&
+ (fgets(buf, BUFSIZ - 1, p)) != NULL) {
+ if ((cp2 = strchr(buf, '\n')) != NULL)
+ *cp2 = '\0';
+ for (dp = sourcedirs;
+ (src == NULL || opt_a) && *dp != NULL;
+ dp++) {
+ cp2 = malloc(strlen(*dp) + 9);
+ if (cp2 == NULL)
+ abort();
+ strcpy(cp2, "^");
+ strcat(cp2, *dp);
+ strcat(cp2, "/[^/]+/");
+ if ((i = regcomp(&re2, cp2,
+ REG_EXTENDED|REG_NOSUB))
+ != 0) {
+ regerror(i, &re, buf,
+ BUFSIZ - 1);
+ errx(EX_UNAVAILABLE,
+ "regcomp(%s) failed: %s",
+ cp2, buf);
+ }
+ free(cp2);
+ if (regexec(&re2, buf, 0,
+ (regmatch_t *)NULL, 0)
+ == 0) {
+ unusual = unusual &
+ ~NO_SRC_FOUND;
+ if (src == NULL) {
+ src = strdup(buf);
+ } else {
+ olen = strlen(src);
+ nlen = strlen(buf);
+ src = realloc(src,
+ olen +
+ nlen + 2);
+ if (src == NULL)
+ abort();
+ strcat(src, " ");
+ strcat(src, buf);
+ }
+ }
+ regfree(&re2);
+ }
+ }
+ pclose(p);
+ free(cp);
+ }
+ done_sources:
+
+ if (opt_u && !unusual)
+ continue;
+
+ printed = 0;
+ if (!opt_q) {
+ printf("%s:", name);
+ printed++;
+ }
+ if (bin) {
+ if (printed++)
+ putchar(' ');
+ fputs(bin, stdout);
+ }
+ if (man) {
+ if (printed++)
+ putchar(' ');
+ fputs(man, stdout);
+ }
+ if (src) {
+ if (printed++)
+ putchar(' ');
+ fputs(src, stdout);
+ }
+ if (printed)
+ putchar('\n');
+ }
+
+ if (opt_m)
+ regfree(&re);
+
+ return (0);
+}
diff --git a/usr.bin/which/Makefile b/usr.bin/which/Makefile
new file mode 100644
index 000000000000..097d238dfbb6
--- /dev/null
+++ b/usr.bin/which/Makefile
@@ -0,0 +1,3 @@
+PROG= which
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/which/Makefile.depend b/usr.bin/which/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/which/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/which/which.1 b/usr.bin/which/which.1
new file mode 100644
index 000000000000..5a6b041563cd
--- /dev/null
+++ b/usr.bin/which/which.1
@@ -0,0 +1,125 @@
+.\" Manpage Copyright (c) 1995, Jordan Hubbard <jkh@FreeBSD.org>
+.\"
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the FreeBSD Project
+.\" its contributors.
+.\" 4. Neither the name of the FreeBSD Project 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 CONTRIBUTOR ``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 CONTRIBUTOR 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 September 24, 2020
+.Dt WHICH 1
+.Os
+.Sh NAME
+.Nm which
+.Nd "locate a program file in the user's path"
+.Sh SYNOPSIS
+.Nm
+.Op Fl as
+.Ar program ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+takes a list of command names and searches the path for each executable
+file that would be run had these commands actually been invoked.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl a
+List all instances of executables found (instead of just the first one
+of each).
+.It Fl s
+No output, just return 0 if all of the executables are found, or 1 if
+some were not found.
+.El
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
+.Sh EXAMPLES
+Locate the
+.Xr ls 1
+and
+.Xr cp 1
+commands:
+.Bd -literal -offset indent
+$ /usr/bin/which ls cp
+/bin/ls
+/bin/cp
+.Ed
+.Pp
+Same as above with a specific
+.Ev PATH
+and showing all occurrences:
+.Bd -literal -offset indent
+$ PATH=/bin:/rescue /usr/bin/which -a ls cp
+/bin/ls
+/rescue/ls
+/bin/cp
+/rescue/cp
+.Ed
+.Pp
+.Nm which
+will show duplicates if the same executable is found more than once:
+.Bd -literal -offset indent
+$ PATH=/bin:/bin /usr/bin/which -a ls
+/bin/ls
+/bin/ls
+.Ed
+.Pp
+Do not show output.
+Just exit with an appropriate return code:
+.Bd -literal -offset indent
+$ /usr/bin/which -s ls cp
+$ echo $?
+0
+
+$ /usr/bin/which -s fakecommand
+$ echo $?
+1
+.Ed
+.Sh SEE ALSO
+.Xr builtin 1 ,
+.Xr csh 1 ,
+.Xr find 1 ,
+.Xr locate 1 ,
+.Xr whereis 1
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 2.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility was originally written in Perl and was contributed by
+.An Wolfram Schneider Aq Mt wosch@FreeBSD.org .
+The current version of
+.Nm
+was rewritten in C by
+.An Daniel Papasian Aq Mt dpapasia@andrew.cmu.edu .
diff --git a/usr.bin/which/which.c b/usr.bin/which/which.c
new file mode 100644
index 000000000000..dc22efb815d8
--- /dev/null
+++ b/usr.bin/which/which.c
@@ -0,0 +1,144 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2000 Dan Papasian. 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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void usage(void);
+static int print_matches(char *, char *);
+
+static int silent;
+static int allpaths;
+
+int
+main(int argc, char **argv)
+{
+ char *p, *path;
+ size_t pathlen;
+ int opt, status;
+
+ status = EXIT_SUCCESS;
+
+ while ((opt = getopt(argc, argv, "as")) != -1) {
+ switch (opt) {
+ case 'a':
+ allpaths = 1;
+ break;
+ case 's':
+ silent = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc == 0)
+ usage();
+
+ if ((p = getenv("PATH")) == NULL)
+ exit(EXIT_FAILURE);
+ pathlen = strlen(p) + 1;
+ path = malloc(pathlen);
+ if (path == NULL)
+ err(EXIT_FAILURE, NULL);
+
+ while (argc > 0) {
+ memcpy(path, p, pathlen);
+
+ if (strlen(*argv) >= FILENAME_MAX ||
+ print_matches(path, *argv) == -1)
+ status = EXIT_FAILURE;
+
+ argv++;
+ argc--;
+ }
+
+ exit(status);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: which [-as] program ...\n");
+ exit(EXIT_FAILURE);
+}
+
+static int
+is_there(char *candidate)
+{
+ struct stat fin;
+
+ /* XXX work around access(2) false positives for superuser */
+ if (access(candidate, X_OK) == 0 &&
+ stat(candidate, &fin) == 0 &&
+ S_ISREG(fin.st_mode) &&
+ (getuid() != 0 ||
+ (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+ if (!silent)
+ printf("%s\n", candidate);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+print_matches(char *path, char *filename)
+{
+ char candidate[PATH_MAX];
+ const char *d;
+ int found;
+
+ if (strchr(filename, '/') != NULL)
+ return (is_there(filename) ? 0 : -1);
+ found = 0;
+ while ((d = strsep(&path, ":")) != NULL) {
+ if (*d == '\0')
+ d = ".";
+ if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
+ filename) >= (int)sizeof(candidate))
+ continue;
+ if (is_there(candidate)) {
+ found = 1;
+ if (!allpaths)
+ break;
+ }
+ }
+ return (found ? 0 : -1);
+}
+
diff --git a/usr.bin/who/Makefile b/usr.bin/who/Makefile
new file mode 100644
index 000000000000..77626f51824a
--- /dev/null
+++ b/usr.bin/who/Makefile
@@ -0,0 +1,4 @@
+PROG= who
+PACKAGE= acct
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/who/Makefile.depend b/usr.bin/who/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/who/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/who/who.1 b/usr.bin/who/who.1
new file mode 100644
index 000000000000..e6e29b568f48
--- /dev/null
+++ b/usr.bin/who/who.1
@@ -0,0 +1,195 @@
+.\" Copyright (c) 1986, 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.
+.\"
+.Dd August 30, 2020
+.Dt WHO 1
+.Os
+.Sh NAME
+.Nm who
+.Nd display who is on the system
+.Sh SYNOPSIS
+.Nm
+.Op Fl abHmqsTu
+.Op Cm am I
+.Op Ar file
+.Sh DESCRIPTION
+The
+.Nm
+utility displays information about currently logged in users.
+By default, this includes the login name, tty name, date and time of login and
+remote hostname if not local.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Equivalent to
+.Fl bTu ,
+with the exception that output is not restricted to the time and date of
+the last system reboot.
+.It Fl b
+Write the time and date of the last system reboot.
+.It Fl H
+Write column headings above the output.
+.It Fl m
+Show information about the terminal attached to standard input only.
+.It Fl q
+.Dq "Quick mode" :
+List the names and number of logged in users in columns.
+All other command line options are ignored.
+.It Fl s
+Show the name, line and time fields only.
+This is the default.
+.It Fl T
+Indicate whether each user is accepting messages.
+One of the following characters is written:
+.Pp
+.Bl -tag -width 1n -compact
+.It Li +
+User is accepting messages.
+.It Li \&-
+User is not accepting messages.
+.It Li \&?
+An error occurred.
+.El
+.It Fl u
+Show idle time for each user in hours and minutes as
+.Ar hh : Ns Ar mm ,
+.Ql \&.
+if the user has been idle less than a minute, and
+.Dq Li old
+if the user has been idle more than 24 hours.
+.It Cm am I
+Equivalent to
+.Fl m .
+.El
+.Pp
+By default,
+.Nm
+gathers information from the file
+.Pa /var/run/utx.active .
+An alternate
+.Ar file
+may be specified which is usually
+.Pa /var/log/utx.log
+(or
+.Pa /var/log/utx.log.[0-6]
+depending on site policy as
+.Pa utx.log
+can grow quite large and daily versions may or may not
+be kept around after compression by
+.Xr ac 8 ) .
+The
+.Pa utx.log
+file contains a record of every login, logout,
+crash, shutdown and date change
+since
+.Pa utx.log
+was last truncated or
+created.
+.Pp
+If
+.Pa /var/log/utx.log
+is being used as the file, the user name may be empty
+or one of the special characters '|', '}' and '~'.
+Logouts produce
+an output line without any user name.
+For more information on the
+special characters, see
+.Xr getutxent 3 .
+.Sh ENVIRONMENT
+The
+.Ev COLUMNS , LANG , LC_ALL
+and
+.Ev LC_TIME
+environment variables affect the execution of
+.Nm
+as described in
+.Xr environ 7 .
+.Sh FILES
+.Bl -tag -width /var/log/utx.log.[0-6] -compact
+.It Pa /var/run/utx.active
+.It Pa /var/log/utx.log
+.It Pa /var/log/utx.log.[0-6]
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Show a brief summary of who is logged in:
+.Bd -literal -offset indent
+$ who -q
+fernape root root
+# users = 3
+.Ed
+.Pp
+Show who is logged in along with the line and time fields (without the headers):
+.Bd -literal -offset indent
+$ who -s
+fernape ttyv0 Aug 26 16:23
+root ttyv1 Aug 26 16:23
+root ttyv2 Aug 26 16:23
+.Ed
+.Pp
+Show information about the terminal attached to standard input:
+.Bd -literal -offset indent
+$ who am i
+fernape Aug 26 16:24
+.Ed
+.Pp
+Show time and date of the last system reboot, whether the users accept messages
+and the idle time for each of them:
+.Bd -literal -offset indent
+$ who -a
+ - system boot Aug 26 16:23 .
+fernape - ttyv0 Aug 26 16:23 .
+root - ttyv1 Aug 26 16:23 .
+root - ttyv2 Aug 26 16:23 .
+.Ed
+.Pp
+Same as above but showing headers:
+.Bd -literal -offset indent
+$ who -aH
+NAME S LINE TIME IDLE FROM
+ - system boot Aug 26 16:23 .
+fernape - ttyv0 Aug 26 16:23 .
+root - ttyv1 Aug 26 16:23 00:01
+root - ttyv2 Aug 26 16:23 00:01
+.Ed
+.Sh SEE ALSO
+.Xr last 1 ,
+.Xr users 1 ,
+.Xr w 1 ,
+.Xr getutxent 3
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
diff --git a/usr.bin/who/who.c b/usr.bin/who/who.c
new file mode 100644
index 000000000000..3416d5eac0c9
--- /dev/null
+++ b/usr.bin/who/who.c
@@ -0,0 +1,315 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2002 Tim J. Robbins.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <locale.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <timeconv.h>
+#include <unistd.h>
+#include <utmpx.h>
+
+static void heading(void);
+static void process_utmp(void);
+static void quick(void);
+static void row(const struct utmpx *);
+static int ttywidth(void);
+static void usage(void);
+static void whoami(void);
+
+static int Hflag; /* Write column headings */
+static int aflag; /* Print all entries */
+static int bflag; /* Show date of the last reboot */
+static int mflag; /* Show info about current terminal */
+static int qflag; /* "Quick" mode */
+static int sflag; /* Show name, line, time */
+static int Tflag; /* Show terminal state */
+static int uflag; /* Show idle time */
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ setlocale(LC_TIME, "");
+
+ while ((ch = getopt(argc, argv, "HTabmqsu")) != -1) {
+ switch (ch) {
+ case 'H': /* Write column headings */
+ Hflag = 1;
+ break;
+ case 'T': /* Show terminal state */
+ Tflag = 1;
+ break;
+ case 'a': /* Same as -bdlprtTu */
+ aflag = bflag = Tflag = uflag = 1;
+ break;
+ case 'b': /* Show date of the last reboot */
+ bflag = 1;
+ break;
+ case 'm': /* Show info about current terminal */
+ mflag = 1;
+ break;
+ case 'q': /* "Quick" mode */
+ qflag = 1;
+ break;
+ case 's': /* Show name, line, time */
+ sflag = 1;
+ break;
+ case 'u': /* Show idle time */
+ uflag = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc >= 2 && strcmp(argv[0], "am") == 0 &&
+ (strcmp(argv[1], "i") == 0 || strcmp(argv[1], "I") == 0)) {
+ /* "who am i" or "who am I", equivalent to -m */
+ mflag = 1;
+ argc -= 2;
+ argv += 2;
+ }
+ if (argc > 1)
+ usage();
+
+ if (*argv != NULL) {
+ if (setutxdb(UTXDB_ACTIVE, *argv) != 0)
+ err(1, "%s", *argv);
+ }
+
+ if (qflag)
+ quick();
+ else {
+ if (sflag)
+ Tflag = uflag = 0;
+ if (Hflag)
+ heading();
+ if (mflag)
+ whoami();
+ else
+ process_utmp();
+ }
+
+ endutxent();
+
+ exit(0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: who [-abHmqsTu] [am I] [file]\n");
+ exit(1);
+}
+
+static void
+heading(void)
+{
+
+ printf("%-16s ", "NAME");
+ if (Tflag)
+ printf("S ");
+ printf("%-12s %-12s ", "LINE", "TIME");
+ if (uflag)
+ printf("IDLE ");
+ printf("%-16s\n", "FROM");
+}
+
+static void
+row(const struct utmpx *ut)
+{
+ char buf[80], tty[PATH_MAX];
+ struct stat sb;
+ time_t idle, t;
+ static int d_first = -1;
+ struct tm *tm;
+ char state;
+
+ if (d_first < 0)
+ d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
+
+ state = '?';
+ idle = 0;
+ if (Tflag || uflag) {
+ snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, ut->ut_line);
+ if (stat(tty, &sb) == 0) {
+ state = sb.st_mode & (S_IWOTH|S_IWGRP) ?
+ '+' : '-';
+ idle = time(NULL) - sb.st_mtime;
+ }
+ }
+
+ printf("%-16s ", ut->ut_user);
+ if (Tflag)
+ printf("%c ", state);
+ if (ut->ut_type == BOOT_TIME)
+ printf("%-12s ", "system boot");
+ else
+ printf("%-12s ", ut->ut_line);
+ t = ut->ut_tv.tv_sec;
+ tm = localtime(&t);
+ strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm);
+ printf("%-*s ", 12, buf);
+ if (uflag) {
+ if (idle < 60)
+ printf(" . ");
+ else if (idle < 24 * 60 * 60)
+ printf("%02d:%02d ", (int)(idle / 60 / 60),
+ (int)(idle / 60 % 60));
+ else
+ printf(" old ");
+ }
+ if (*ut->ut_host != '\0')
+ printf("(%s)", ut->ut_host);
+ putchar('\n');
+}
+
+static int
+ttystat(char *line)
+{
+ struct stat sb;
+ char ttybuf[MAXPATHLEN];
+
+ if (line == NULL)
+ return (0);
+ (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
+ if (stat(ttybuf, &sb) == 0) {
+ return (0);
+ } else
+ return (-1);
+}
+
+static void
+process_utmp(void)
+{
+ struct utmpx *utx;
+
+ while ((utx = getutxent()) != NULL) {
+ if ((aflag || !bflag) && utx->ut_type == USER_PROCESS) {
+ if (ttystat(utx->ut_line) == 0)
+ row(utx);
+ } else if (bflag && utx->ut_type == BOOT_TIME)
+ row(utx);
+ }
+}
+
+static void
+quick(void)
+{
+ struct utmpx *utx;
+ int col, ncols, num;
+
+ ncols = ttywidth();
+ col = num = 0;
+ while ((utx = getutxent()) != NULL) {
+ if (utx->ut_type != USER_PROCESS)
+ continue;
+ printf("%-16s", utx->ut_user);
+ if (++col < ncols / (16 + 1))
+ putchar(' ');
+ else {
+ col = 0;
+ putchar('\n');
+ }
+ num++;
+ }
+ if (col != 0)
+ putchar('\n');
+
+ printf("# users = %d\n", num);
+}
+
+static void
+whoami(void)
+{
+ struct utmpx ut, *utx;
+ struct passwd *pwd;
+ const char *name, *tty;
+
+ if ((tty = ttyname(STDIN_FILENO)) == NULL)
+ tty = "tty??";
+ else if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
+ tty += sizeof _PATH_DEV - 1;
+ strlcpy(ut.ut_line, tty, sizeof ut.ut_line);
+
+ /* Search utmp for our tty, dump first matching record. */
+ if ((utx = getutxline(&ut)) != NULL && utx->ut_type == USER_PROCESS) {
+ row(utx);
+ return;
+ }
+
+ /* Not found; fill the utmp structure with the information we have. */
+ memset(&ut, 0, sizeof(ut));
+ if ((pwd = getpwuid(getuid())) != NULL)
+ name = pwd->pw_name;
+ else
+ name = "?";
+ strlcpy(ut.ut_user, name, sizeof ut.ut_user);
+ gettimeofday(&ut.ut_tv, NULL);
+ row(&ut);
+}
+
+static int
+ttywidth(void)
+{
+ struct winsize ws;
+ long width;
+ char *cols, *ep;
+
+ if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') {
+ errno = 0;
+ width = strtol(cols, &ep, 10);
+ if (errno || width <= 0 || width > INT_MAX || ep == cols ||
+ *ep != '\0')
+ warnx("invalid COLUMNS environment variable ignored");
+ else
+ return (width);
+ }
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
+ return (ws.ws_col);
+
+ return (80);
+}
diff --git a/usr.bin/whois/Makefile b/usr.bin/whois/Makefile
new file mode 100644
index 000000000000..794d9a06ee89
--- /dev/null
+++ b/usr.bin/whois/Makefile
@@ -0,0 +1,10 @@
+PROG= whois
+
+.if defined(SOCKS)
+CFLAGS+=-DSOCKS
+CFLAGS+=-Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dlisten=Rlisten \
+ -Daccept=Raccept -Drcmd=Rrcmd -Dbind=Rbind -Dselect=Rselect
+LDADD+= -lsocks
+.endif
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/whois/Makefile.depend b/usr.bin/whois/Makefile.depend
new file mode 100644
index 000000000000..344a5d0e9310
--- /dev/null
+++ b/usr.bin/whois/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/whois/whois.1 b/usr.bin/whois/whois.1
new file mode 100644
index 000000000000..565c2b2fbad1
--- /dev/null
+++ b/usr.bin/whois/whois.1
@@ -0,0 +1,292 @@
+.\" Copyright (c) 1985, 1990, 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.
+.\"
+.Dd August 1, 2019
+.Dt WHOIS 1
+.Os
+.Sh NAME
+.Nm whois
+.Nd "Internet domain name and network number directory service"
+.Sh SYNOPSIS
+.Nm
+.Op Fl aAbfgiIklmPQrRS
+.Op Fl c Ar TLD | Fl h Ar host
+.Op Fl p Ar port
+.Op Fl -
+.Ar name ...
+.Sh DESCRIPTION
+The
+.Nm
+utility looks up records in the databases maintained by several
+Network Information Centers
+.Pq Tn NICs .
+.Pp
+By default
+.Nm
+starts by querying the Internet Assigned Numbers Authority (IANA) whois server,
+and follows referrals to whois servers
+that have more specific details about the query
+.Ar name .
+The IANA whois server knows about
+IP address and AS numbers
+as well as domain names.
+.Pp
+There are a few special cases where referrals do not work, so
+.Nm
+goes directly to the appropriate server.
+These include point-of-contact handles for ARIN,
+.Pa nic.at ,
+NORID, and RIPE,
+and domain names under
+.Pa ac.uk .
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Use the American Registry for Internet Numbers
+.Pq Tn ARIN
+database.
+It contains network numbers used in those parts of the world covered neither by
+.Tn APNIC , AfriNIC , LACNIC ,
+nor by
+.Tn RIPE .
+The query syntax is documented at
+.Pa https://www.arin.net/resources/whoisrws/whois_api.html#nicname
+.It Fl A
+Use the Asia/Pacific Network Information Center
+.Pq Tn APNIC
+database.
+It contains network numbers used in East Asia, Australia,
+New Zealand, and the Pacific islands.
+Get query syntax documentation using
+.Ic whois -A help
+.It Fl b
+Use the Network Abuse Clearinghouse database.
+It contains addresses to which network abuse should be reported,
+indexed by domain name.
+.It Fl c Ar TLD
+This is the equivalent of using the
+.Fl h
+option with an argument of
+.Qq Ar TLD Ns Li .whois-servers.net .
+This can be helpful for locating country-class TLD whois servers.
+.It Fl f
+Use the African Network Information Centre
+.Pq Tn AfriNIC
+database.
+It contains network numbers used in Africa and the islands of the
+western Indian Ocean.
+Get query syntax documentation using
+.Ic whois -f help
+.It Fl g
+Use the US non-military federal government database, which contains points of
+contact for subdomains of
+.Pa .GOV .
+.It Fl h Ar host
+Use the specified host instead of the default.
+Either a host name or an IP address may be specified.
+.It Fl i
+Use the traditional Network Information Center (InterNIC)
+.Pq Pa whois.internic.net
+database.
+This now contains only registrations for domain names under
+.Pa .COM ,
+.Pa .NET ,
+.Pa .EDU .
+You can specify the type of object to search for like
+.Ic whois -i ' Ns Ar type Ar name Ns Ic '
+where
+.Ar type
+can be
+.Nm domain , nameserver , registrar .
+The
+.Ar name
+can contain
+.Li *
+wildcards.
+.It Fl I
+Use the Internet Assigned Numbers Authority
+.Pq Tn IANA
+database.
+.It Fl k
+Use the National Internet Development Agency of Korea's
+.Pq Tn KRNIC
+database.
+It contains network numbers and domain contact information
+for Korea.
+.It Fl l
+Use the Latin American and Caribbean IP address Regional Registry
+.Pq Tn LACNIC
+database.
+It contains network numbers used in much of Latin America and the
+Caribbean.
+.It Fl m
+Use the Route Arbiter Database
+.Pq Tn RADB
+database.
+It contains route policy specifications for a large
+number of operators' networks.
+.It Fl p Ar port
+Connect to the whois server on
+.Ar port .
+If this option is not specified,
+.Nm
+defaults to port 43.
+.It Fl P
+Use the PeeringDB database of AS numbers.
+It contains details about presence at internet peering points
+for many network operators.
+.It Fl Q
+Do a quick lookup;
+.Nm
+will not attempt to follow referrals to other whois servers.
+This is the default if a server is explicitly specified
+using one of the other options or in an environment variable.
+See also the
+.Fl R
+option.
+.It Fl r
+Use the R\(aaeseaux IP Europ\(aaeens
+.Pq Tn RIPE
+database.
+It contains network numbers and domain contact information
+for Europe.
+Get query syntax documentation using
+.Ic whois -r help
+.It Fl R
+Do a recursive lookup;
+.Nm
+will attempt to follow referrals to other whois servers.
+This is the default if no server is explicitly specified.
+See also the
+.Fl Q
+option.
+.It Fl S
+By default
+.Nm
+adjusts simple queries (without spaces) to produce more useful output
+from certain whois servers,
+and it suppresses some uninformative output.
+With the
+.Fl S
+option,
+.Nm
+sends the query and prints the output verbatim.
+.El
+.Pp
+The operands specified to
+.Nm
+are treated independently and may be used
+as queries on different whois servers.
+.Sh ENVIRONMENT
+.Bl -tag -width WHOIS_SERVER
+.It Ev WHOIS_SERVER
+The primary default whois server.
+If this is unset,
+.Nm
+uses the
+.Ev RA_SERVER
+environment variable.
+.It Ev RA_SERVER
+The secondary default whois server.
+If this is unset,
+.Nm
+will use
+.Pa whois.iana.org .
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+To obtain contact information about an
+administrator located in the Russian
+.Tn TLD
+domain
+.Qq Li RU ,
+use the
+.Fl c
+option as shown in the following example, where
+.Ar CONTACT-ID
+is substituted with the actual contact identifier.
+.Pp
+.Dl Ic whois -c RU CONTACT-ID
+.Pp
+(Note: This example is specific to the
+.Tn TLD
+.Qq Li RU ,
+but other
+.Tn TLDs
+can be queried by using a similar syntax.)
+.Pp
+The following example demonstrates how to query
+a whois server using a non-standard port, where
+.Dq Li query-data
+is the query to be sent to
+.Dq Li whois.example.com
+on port
+.Dq Li rwhois
+(written numerically as 4321).
+.Pp
+.Dl Ic whois -h whois.example.com -p rwhois query-data
+.Pp
+Some whois servers support complex queries
+with dash-letter options.
+You can use the
+.Fl -
+option to separate
+.Nm
+command options from whois server query options.
+A query containing spaces must be quoted as one
+argument to the
+.Nm
+command.
+The following example asks the RIPE whois server
+to return a brief description of its
+.Dq Li domain
+object type:
+.Pp
+.Dl Ic whois -r -- '-t domain'
+.Sh STANDARDS
+.Rs
+.%A K. Harrenstien
+.%A M. Stahl
+.%A E. Feinler
+.%D October 1985
+.%R RFC 954
+.%T NICNAME/WHOIS
+.Re
+.Pp
+.Rs
+.%A L. Daigle
+.%D September 2004
+.%R RFC 3912
+.%T WHOIS Protocol Specification
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c
new file mode 100644
index 000000000000..5d88cf4d9821
--- /dev/null
+++ b/usr.bin/whois/whois.c
@@ -0,0 +1,610 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <err.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define ABUSEHOST "whois.abuse.net"
+#define ANICHOST "whois.arin.net"
+#define DENICHOST "whois.denic.de"
+#define DKNICHOST "whois.dk-hostmaster.dk"
+#define FNICHOST "whois.afrinic.net"
+#define GNICHOST "whois.nic.gov"
+#define IANAHOST "whois.iana.org"
+#define INICHOST "whois.internic.net"
+#define KNICHOST "whois.krnic.net"
+#define LNICHOST "whois.lacnic.net"
+#define MNICHOST "whois.ra.net"
+#define PDBHOST "whois.peeringdb.com"
+#define PNICHOST "whois.apnic.net"
+#define QNICHOST_TAIL ".whois-servers.net"
+#define RNICHOST "whois.ripe.net"
+#define VNICHOST "whois.verisign-grs.com"
+
+#define DEFAULT_PORT "whois"
+
+#define WHOIS_RECURSE 0x01
+#define WHOIS_QUICK 0x02
+#define WHOIS_SPAM_ME 0x04
+
+#define CHOPSPAM ">>> Last update of WHOIS database:"
+
+#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-')
+
+#define SCAN(p, end, check) \
+ while ((p) < (end)) \
+ if (check) ++(p); \
+ else break
+
+static struct {
+ const char *suffix, *server;
+} whoiswhere[] = {
+ /* Various handles */
+ { "-ARIN", ANICHOST },
+ { "-NICAT", "at" QNICHOST_TAIL },
+ { "-NORID", "no" QNICHOST_TAIL },
+ { "-RIPE", RNICHOST },
+ /* Nominet's whois server doesn't return referrals to JANET */
+ { ".ac.uk", "ac.uk" QNICHOST_TAIL },
+ { ".gov.uk", "ac.uk" QNICHOST_TAIL },
+ { "", IANAHOST }, /* default */
+ { NULL, NULL } /* safety belt */
+};
+
+#define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 }
+static struct {
+ const char *prefix;
+ size_t len;
+} whois_referral[] = {
+ WHOIS_REFERRAL("whois:"), /* IANA */
+ WHOIS_REFERRAL("Whois Server:"),
+ WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */
+ WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */
+ WHOIS_REFERRAL("ReferralServer: rwhois://"), /* ARIN */
+ WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */
+ { NULL, 0 }
+};
+
+/*
+ * We have a list of patterns for RIRs that assert ignorance rather than
+ * providing referrals. If that happens, we guess that ARIN will be more
+ * helpful. But, before following a referral to an RIR, we check if we have
+ * asked that RIR already, and if so we make another guess.
+ */
+static const char *actually_arin[] = {
+ "netname: ERX-NETBLOCK\n", /* APNIC */
+ "netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n",
+ NULL
+};
+
+static struct {
+ int loop;
+ const char *host;
+} try_rir[] = {
+ { 0, ANICHOST },
+ { 0, RNICHOST },
+ { 0, PNICHOST },
+ { 0, FNICHOST },
+ { 0, LNICHOST },
+ { 0, NULL }
+};
+
+static void
+reset_rir(void) {
+ int i;
+
+ for (i = 0; try_rir[i].host != NULL; i++)
+ try_rir[i].loop = 0;
+}
+
+static const char *port = DEFAULT_PORT;
+
+static const char *choose_server(char *);
+static struct addrinfo *gethostinfo(const char *, const char *, int);
+static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3);
+static void usage(void) __dead2;
+static void whois(const char *, const char *, const char *, int);
+
+int
+main(int argc, char *argv[])
+{
+ const char *country, *host;
+ int ch, flags;
+
+#ifdef SOCKS
+ SOCKSinit(argv[0]);
+#endif
+
+ country = host = NULL;
+ flags = 0;
+ while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) {
+ switch (ch) {
+ case 'a':
+ host = ANICHOST;
+ break;
+ case 'A':
+ host = PNICHOST;
+ break;
+ case 'b':
+ host = ABUSEHOST;
+ break;
+ case 'c':
+ country = optarg;
+ break;
+ case 'f':
+ host = FNICHOST;
+ break;
+ case 'g':
+ host = GNICHOST;
+ break;
+ case 'h':
+ host = optarg;
+ break;
+ case 'i':
+ host = INICHOST;
+ break;
+ case 'I':
+ host = IANAHOST;
+ break;
+ case 'k':
+ host = KNICHOST;
+ break;
+ case 'l':
+ host = LNICHOST;
+ break;
+ case 'm':
+ host = MNICHOST;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'P':
+ host = PDBHOST;
+ break;
+ case 'Q':
+ flags |= WHOIS_QUICK;
+ break;
+ case 'r':
+ host = RNICHOST;
+ break;
+ case 'R':
+ flags |= WHOIS_RECURSE;
+ break;
+ case 'S':
+ flags |= WHOIS_SPAM_ME;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!argc || (country != NULL && host != NULL))
+ usage();
+
+ /*
+ * If no host or country is specified, rely on referrals from IANA.
+ */
+ if (host == NULL && country == NULL) {
+ if ((host = getenv("WHOIS_SERVER")) == NULL &&
+ (host = getenv("RA_SERVER")) == NULL) {
+ if (!(flags & WHOIS_QUICK))
+ flags |= WHOIS_RECURSE;
+ }
+ }
+ while (argc-- > 0) {
+ if (country != NULL) {
+ char *qnichost;
+ s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL);
+ whois(*argv, qnichost, port, flags);
+ free(qnichost);
+ } else
+ whois(*argv, host != NULL ? host :
+ choose_server(*argv), port, flags);
+ reset_rir();
+ argv++;
+ }
+ exit(0);
+}
+
+static const char *
+choose_server(char *domain)
+{
+ size_t len = strlen(domain);
+ int i;
+
+ for (i = 0; whoiswhere[i].suffix != NULL; i++) {
+ size_t suffix_len = strlen(whoiswhere[i].suffix);
+ if (len > suffix_len &&
+ strcasecmp(domain + len - suffix_len,
+ whoiswhere[i].suffix) == 0)
+ return (whoiswhere[i].server);
+ }
+ errx(EX_SOFTWARE, "no default whois server");
+}
+
+static struct addrinfo *
+gethostinfo(const char *host, const char *hport, int exit_on_noname)
+{
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ res = NULL;
+ error = getaddrinfo(host, hport, &hints, &res);
+ if (error && (exit_on_noname || error != EAI_NONAME))
+ err(EX_NOHOST, "%s: %s", host, gai_strerror(error));
+ return (res);
+}
+
+/*
+ * Wrapper for asprintf(3) that exits on error.
+ */
+static void
+s_asprintf(char **ret, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if (vasprintf(ret, format, ap) == -1) {
+ va_end(ap);
+ err(EX_OSERR, "vasprintf()");
+ }
+ va_end(ap);
+}
+
+static int
+connect_to_any_host(struct addrinfo *hostres)
+{
+ struct addrinfo *res;
+ nfds_t i, j;
+ size_t count;
+ struct pollfd *fds;
+ int timeout = 180, s = -1;
+
+ for (res = hostres, count = 0; res; res = res->ai_next)
+ count++;
+ fds = calloc(count, sizeof(*fds));
+ if (fds == NULL)
+ err(EX_OSERR, "calloc()");
+
+ /*
+ * Traverse the result list elements and make non-block
+ * connection attempts.
+ */
+ count = i = 0;
+ for (res = hostres; res != NULL; res = res->ai_next) {
+ s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK,
+ res->ai_protocol);
+ if (s < 0)
+ continue;
+ if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ if (errno == EINPROGRESS) {
+ /* Add the socket to poll list */
+ fds[i].fd = s;
+ fds[i].events = POLLERR | POLLHUP |
+ POLLIN | POLLOUT;
+ /*
+ * From here until a socket connects, the
+ * socket fd is owned by the fds[] poll array.
+ */
+ s = -1;
+ count++;
+ i++;
+ } else {
+ close(s);
+ s = -1;
+
+ /*
+ * Poll only if we have something to poll,
+ * otherwise just go ahead and try next
+ * address
+ */
+ if (count == 0)
+ continue;
+ }
+ } else
+ goto done;
+
+ /*
+ * If we are at the last address, poll until a connection is
+ * established or we failed all connection attempts.
+ */
+ if (res->ai_next == NULL)
+ timeout = INFTIM;
+
+ /*
+ * Poll the watched descriptors for successful connections:
+ * if we still have more untried resolved addresses, poll only
+ * once; otherwise, poll until all descriptors have errors,
+ * which will be considered as ETIMEDOUT later.
+ */
+ do {
+ int n;
+
+ n = poll(fds, i, timeout);
+ if (n == 0) {
+ /*
+ * No event reported in time. Try with a
+ * smaller timeout (but cap at 2-3ms)
+ * after a new host have been added.
+ */
+ if (timeout >= 3)
+ timeout >>= 1;
+
+ break;
+ } else if (n < 0) {
+ /*
+ * errno here can only be EINTR which we would
+ * want to clean up and bail out.
+ */
+ s = -1;
+ goto done;
+ }
+
+ /*
+ * Check for the event(s) we have seen.
+ */
+ for (j = 0; j < i; j++) {
+ if (fds[j].fd == -1 || fds[j].events == 0 ||
+ fds[j].revents == 0)
+ continue;
+ if (fds[j].revents & ~(POLLIN | POLLOUT)) {
+ close(fds[j].fd);
+ fds[j].fd = -1;
+ fds[j].events = 0;
+ count--;
+ continue;
+ } else if (fds[j].revents & (POLLIN | POLLOUT)) {
+ /* Connect succeeded. */
+ s = fds[j].fd;
+ fds[j].fd = -1;
+
+ goto done;
+ }
+
+ }
+ } while (timeout == INFTIM && count != 0);
+ }
+
+ /* All attempts were failed */
+ s = -1;
+ if (count == 0)
+ errno = ETIMEDOUT;
+
+done:
+ /* Close all watched fds except the succeeded one */
+ for (j = 0; j < i; j++)
+ if (fds[j].fd != -1)
+ close(fds[j].fd);
+ free(fds);
+ return (s);
+}
+
+static void
+whois(const char *query, const char *hostname, const char *hostport, int flags)
+{
+ FILE *fp;
+ struct addrinfo *hostres;
+ char *buf, *host, *nhost, *nport, *p;
+ int comment, s, f;
+ size_t len, i;
+
+ hostres = gethostinfo(hostname, hostport, 1);
+ s = connect_to_any_host(hostres);
+ if (s == -1)
+ err(EX_OSERR, "connect()");
+
+ /* Restore default blocking behavior. */
+ if ((f = fcntl(s, F_GETFL)) == -1)
+ err(EX_OSERR, "fcntl()");
+ f &= ~O_NONBLOCK;
+ if (fcntl(s, F_SETFL, f) == -1)
+ err(EX_OSERR, "fcntl()");
+
+ fp = fdopen(s, "r+");
+ if (fp == NULL)
+ err(EX_OSERR, "fdopen()");
+
+ if (!(flags & WHOIS_SPAM_ME) &&
+ (strcasecmp(hostname, DENICHOST) == 0 ||
+ strcasecmp(hostname, "de" QNICHOST_TAIL) == 0)) {
+ const char *q;
+ int idn = 0;
+ for (q = query; *q != '\0'; q++)
+ if (!isascii(*q))
+ idn = 1;
+ fprintf(fp, "-T dn%s %s\r\n", idn ? "" : ",ace", query);
+ } else if (!(flags & WHOIS_SPAM_ME) &&
+ (strcasecmp(hostname, DKNICHOST) == 0 ||
+ strcasecmp(hostname, "dk" QNICHOST_TAIL) == 0))
+ fprintf(fp, "--show-handles %s\r\n", query);
+ else if ((flags & WHOIS_SPAM_ME) ||
+ strchr(query, ' ') != NULL)
+ fprintf(fp, "%s\r\n", query);
+ else if (strcasecmp(hostname, ANICHOST) == 0) {
+ if (strncasecmp(query, "AS", 2) == 0 &&
+ strspn(query+2, "0123456789") == strlen(query+2))
+ fprintf(fp, "+ a %s\r\n", query+2);
+ else
+ fprintf(fp, "+ %s\r\n", query);
+ } else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0)
+ fprintf(fp, "domain %s\r\n", query);
+ else
+ fprintf(fp, "%s\r\n", query);
+ fflush(fp);
+
+ comment = 0;
+ if (!(flags & WHOIS_SPAM_ME) &&
+ (strcasecmp(hostname, ANICHOST) == 0 ||
+ strcasecmp(hostname, RNICHOST) == 0)) {
+ comment = 2;
+ }
+
+ nhost = NULL;
+ while ((buf = fgetln(fp, &len)) != NULL) {
+ /* Nominet */
+ if (!(flags & WHOIS_SPAM_ME) &&
+ len == 5 && strncmp(buf, "-- \r\n", 5) == 0)
+ break;
+ /* RIRs */
+ if (comment == 1 && buf[0] == '#')
+ break;
+ else if (comment == 2) {
+ if (strchr("#%\r\n", buf[0]) != NULL)
+ continue;
+ else
+ comment = 1;
+ }
+
+ printf("%.*s", (int)len, buf);
+
+ if ((flags & WHOIS_RECURSE) && nhost == NULL) {
+ for (i = 0; whois_referral[i].prefix != NULL; i++) {
+ p = buf;
+ SCAN(p, buf+len, *p == ' ');
+ if (strncasecmp(p, whois_referral[i].prefix,
+ whois_referral[i].len) != 0)
+ continue;
+ p += whois_referral[i].len;
+ SCAN(p, buf+len, *p == ' ');
+ host = p;
+ SCAN(p, buf+len, ishost(*p));
+ if (p > host) {
+ char *pstr;
+
+ s_asprintf(&nhost, "%.*s",
+ (int)(p - host), host);
+
+ if (*p != ':') {
+ s_asprintf(&nport, "%s", port);
+ break;
+ }
+
+ pstr = ++p;
+ SCAN(p, buf+len, isdigit(*p));
+ if (p > pstr && (p - pstr) < 6) {
+ s_asprintf(&nport, "%.*s",
+ (int)(p - pstr), pstr);
+ break;
+ }
+
+ /* Invalid port; don't recurse */
+ free(nhost);
+ nhost = NULL;
+ }
+ break;
+ }
+ for (i = 0; actually_arin[i] != NULL; i++) {
+ if (strncmp(buf, actually_arin[i], len) == 0) {
+ s_asprintf(&nhost, "%s", ANICHOST);
+ s_asprintf(&nport, "%s", port);
+ break;
+ }
+ }
+ }
+ /* Verisign etc. */
+ if (!(flags & WHOIS_SPAM_ME) &&
+ len >= sizeof(CHOPSPAM)-1 &&
+ (strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 ||
+ strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) {
+ printf("\n");
+ break;
+ }
+ }
+ fclose(fp);
+ freeaddrinfo(hostres);
+
+ f = 0;
+ for (i = 0; try_rir[i].host != NULL; i++) {
+ /* Remember visits to RIRs */
+ if (try_rir[i].loop == 0 &&
+ strcasecmp(try_rir[i].host, hostname) == 0)
+ try_rir[i].loop = 1;
+ /* Do we need to find an alternative RIR? */
+ if (try_rir[i].loop != 0 && nhost != NULL &&
+ strcasecmp(try_rir[i].host, nhost) == 0) {
+ free(nhost);
+ nhost = NULL;
+ free(nport);
+ nport = NULL;
+ f = 1;
+ }
+ }
+ if (f) {
+ /* Find a replacement RIR */
+ for (i = 0; try_rir[i].host != NULL; i++) {
+ if (try_rir[i].loop == 0) {
+ s_asprintf(&nhost, "%s", try_rir[i].host);
+ s_asprintf(&nport, "%s", port);
+ break;
+ }
+ }
+ }
+ if (nhost != NULL) {
+ /* Ignore self-referrals */
+ if (strcasecmp(hostname, nhost) != 0) {
+ printf("# %s\n\n", nhost);
+ whois(query, nhost, nport, flags);
+ }
+ free(nhost);
+ free(nport);
+ }
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: whois [-aAbfgiIklmPQrRS] [-c country-code | -h hostname] "
+ "[-p port] name ...\n");
+ exit(EX_USAGE);
+}
diff --git a/usr.bin/write/Makefile b/usr.bin/write/Makefile
new file mode 100644
index 000000000000..d7e362cc9c8f
--- /dev/null
+++ b/usr.bin/write/Makefile
@@ -0,0 +1,5 @@
+PROG= write
+BINMODE=2555
+BINGRP= tty
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/write/Makefile.depend b/usr.bin/write/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/write/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/write/write.1 b/usr.bin/write/write.1
new file mode 100644
index 000000000000..d94957a2e777
--- /dev/null
+++ b/usr.bin/write/write.1
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
+.\"
+.\" 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.
+.\"
+.Dd February 13, 2012
+.Dt WRITE 1
+.Os
+.Sh NAME
+.Nm write
+.Nd send a message to another user
+.Sh SYNOPSIS
+.Nm
+.Ar user
+.Op Ar tty
+.Sh DESCRIPTION
+The
+.Nm
+utility allows you to communicate with other users, by copying lines from
+your terminal to theirs.
+.Pp
+When you run the
+.Nm
+command, the user you are writing to gets a message of the form:
+.Pp
+.Dl Message from yourname@yourhost on yourtty at hh:mm ...
+.Pp
+Any further lines you enter will be copied to the specified user's
+terminal.
+If the other user wants to reply, they must run
+.Nm
+as well.
+.Pp
+When you are done, type an end-of-file or interrupt character.
+The other user will see the message
+.Ql EOF
+indicating that the
+conversation is over.
+.Pp
+You can prevent people (other than the super-user) from writing to you
+with the
+.Xr mesg 1
+command.
+.Pp
+If the user you want to write to is logged in on more than one terminal,
+you can specify which terminal to write to by specifying the terminal
+name as the second operand to the
+.Nm
+command.
+Alternatively, you can let
+.Nm
+select one of the terminals \- it will pick the one with the shortest
+idle time.
+This is so that if the user is logged in at work and also dialed up from
+home, the message will go to the right place.
+.Pp
+The traditional protocol for writing to someone is that the string
+.Ql \-o ,
+either at the end of a line or on a line by itself, means that it is the
+other person's turn to talk.
+The string
+.Ql oo
+means that the person believes the conversation to be
+over.
+.Sh SEE ALSO
+.Xr mesg 1 ,
+.Xr talk 1 ,
+.Xr wall 1 ,
+.Xr who 1
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+.Sh BUGS
+The sender's
+.Ev LC_CTYPE
+setting is used to determine which characters are safe to write to a
+terminal, not the receiver's (which
+.Nm
+has no way of knowing).
diff --git a/usr.bin/write/write.c b/usr.bin/write/write.c
new file mode 100644
index 000000000000..cbdc34ec0f4f
--- /dev/null
+++ b/usr.bin/write/write.c
@@ -0,0 +1,344 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
+ *
+ * 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>
+#include <sys/capsicum.h>
+#include <sys/filio.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include <wchar.h>
+#include <wctype.h>
+
+void done(int);
+void do_write(int, char *, char *, const char *);
+static void usage(void) __dead2;
+int term_chk(int, char *, int *, time_t *, int);
+void wr_fputs(wchar_t *s);
+void search_utmp(int, char *, char *, char *, uid_t);
+int utmp_chk(char *, char *);
+
+int
+main(int argc, char **argv)
+{
+ unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ, FIODGNAME };
+ cap_rights_t rights;
+ struct passwd *pwd;
+ time_t atime;
+ uid_t myuid;
+ int msgsok, myttyfd;
+ char tty[MAXPATHLEN], *mytty;
+ const char *login;
+ int devfd;
+
+ (void)setlocale(LC_CTYPE, "");
+
+ devfd = open(_PATH_DEV, O_RDONLY);
+ if (devfd < 0)
+ err(1, "open(/dev)");
+ cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_LOOKUP,
+ CAP_PWRITE);
+ if (caph_rights_limit(devfd, &rights) < 0)
+ err(1, "can't limit devfd rights");
+
+ /*
+ * Can't use capsicum helpers here because we need the additional
+ * FIODGNAME ioctl.
+ */
+ cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_READ,
+ CAP_WRITE);
+ if (caph_rights_limit(STDIN_FILENO, &rights) < 0 ||
+ caph_rights_limit(STDOUT_FILENO, &rights) < 0 ||
+ caph_rights_limit(STDERR_FILENO, &rights) < 0 ||
+ caph_ioctls_limit(STDIN_FILENO, cmds, nitems(cmds)) < 0 ||
+ caph_ioctls_limit(STDOUT_FILENO, cmds, nitems(cmds)) < 0 ||
+ caph_ioctls_limit(STDERR_FILENO, cmds, nitems(cmds)) < 0 ||
+ caph_fcntls_limit(STDIN_FILENO, CAP_FCNTL_GETFL) < 0 ||
+ caph_fcntls_limit(STDOUT_FILENO, CAP_FCNTL_GETFL) < 0 ||
+ caph_fcntls_limit(STDERR_FILENO, CAP_FCNTL_GETFL) < 0)
+ err(1, "can't limit stdio rights");
+
+ caph_cache_catpages();
+ caph_cache_tzdata();
+
+ /*
+ * Cache UTX database fds.
+ */
+ setutxent();
+
+ /*
+ * Determine our login name before we reopen() stdout
+ * and before entering capability sandbox.
+ */
+ myuid = getuid();
+ if ((login = getlogin()) == NULL) {
+ if ((pwd = getpwuid(myuid)))
+ login = pwd->pw_name;
+ else
+ login = "???";
+ }
+
+ if (caph_enter() < 0)
+ err(1, "cap_enter");
+
+ while (getopt(argc, argv, "") != -1)
+ usage();
+ argc -= optind;
+ argv += optind;
+
+ /* check that sender has write enabled */
+ if (isatty(fileno(stdin)))
+ myttyfd = fileno(stdin);
+ else if (isatty(fileno(stdout)))
+ myttyfd = fileno(stdout);
+ else if (isatty(fileno(stderr)))
+ myttyfd = fileno(stderr);
+ else
+ errx(1, "can't find your tty");
+ if (!(mytty = ttyname(myttyfd)))
+ errx(1, "can't find your tty's name");
+ if (!strncmp(mytty, _PATH_DEV, strlen(_PATH_DEV)))
+ mytty += strlen(_PATH_DEV);
+ if (term_chk(devfd, mytty, &msgsok, &atime, 1))
+ exit(1);
+ if (!msgsok)
+ errx(1, "you have write permission turned off");
+
+ /* check args */
+ switch (argc) {
+ case 1:
+ search_utmp(devfd, argv[0], tty, mytty, myuid);
+ do_write(devfd, tty, mytty, login);
+ break;
+ case 2:
+ if (!strncmp(argv[1], _PATH_DEV, strlen(_PATH_DEV)))
+ argv[1] += strlen(_PATH_DEV);
+ if (utmp_chk(argv[0], argv[1]))
+ errx(1, "%s is not logged in on %s", argv[0], argv[1]);
+ if (term_chk(devfd, argv[1], &msgsok, &atime, 1))
+ exit(1);
+ if (myuid && !msgsok)
+ errx(1, "%s has messages disabled on %s", argv[0], argv[1]);
+ do_write(devfd, argv[1], mytty, login);
+ break;
+ default:
+ usage();
+ }
+ done(0);
+ return (0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: write user [tty]\n");
+ exit(1);
+}
+
+/*
+ * utmp_chk - checks that the given user is actually logged in on
+ * the given tty
+ */
+int
+utmp_chk(char *user, char *tty)
+{
+ struct utmpx lu, *u;
+
+ strncpy(lu.ut_line, tty, sizeof lu.ut_line);
+ while ((u = getutxline(&lu)) != NULL)
+ if (u->ut_type == USER_PROCESS &&
+ strcmp(user, u->ut_user) == 0) {
+ endutxent();
+ return(0);
+ }
+ endutxent();
+ return(1);
+}
+
+/*
+ * search_utmp - search utmp for the "best" terminal to write to
+ *
+ * Ignores terminals with messages disabled, and of the rest, returns
+ * the one with the most recent access time. Returns as value the number
+ * of the user's terminals with messages enabled, or -1 if the user is
+ * not logged in at all.
+ *
+ * Special case for writing to yourself - ignore the terminal you're
+ * writing from, unless that's the only terminal with messages enabled.
+ */
+void
+search_utmp(int devfd, char *user, char *tty, char *mytty, uid_t myuid)
+{
+ struct utmpx *u;
+ time_t bestatime, atime;
+ int nloggedttys, nttys, msgsok, user_is_me;
+
+ nloggedttys = nttys = 0;
+ bestatime = 0;
+ user_is_me = 0;
+
+ while ((u = getutxent()) != NULL)
+ if (u->ut_type == USER_PROCESS &&
+ strcmp(user, u->ut_user) == 0) {
+ ++nloggedttys;
+ if (term_chk(devfd, u->ut_line, &msgsok, &atime, 0))
+ continue; /* bad term? skip */
+ if (myuid && !msgsok)
+ continue; /* skip ttys with msgs off */
+ if (strcmp(u->ut_line, mytty) == 0) {
+ user_is_me = 1;
+ continue; /* don't write to yourself */
+ }
+ ++nttys;
+ if (atime > bestatime) {
+ bestatime = atime;
+ (void)strlcpy(tty, u->ut_line, MAXPATHLEN);
+ }
+ }
+ endutxent();
+
+ if (nloggedttys == 0)
+ errx(1, "%s is not logged in", user);
+ if (nttys == 0) {
+ if (user_is_me) { /* ok, so write to yourself! */
+ (void)strlcpy(tty, mytty, MAXPATHLEN);
+ return;
+ }
+ errx(1, "%s has messages disabled", user);
+ } else if (nttys > 1) {
+ warnx("%s is logged in more than once; writing to %s", user, tty);
+ }
+}
+
+/*
+ * term_chk - check that a terminal exists, and get the message bit
+ * and the access time
+ */
+int
+term_chk(int devfd, char *tty, int *msgsokP, time_t *atimeP, int showerror)
+{
+ struct stat s;
+
+ if (fstatat(devfd, tty, &s, 0) < 0) {
+ if (showerror)
+ warn("%s%s", _PATH_DEV, tty);
+ return(1);
+ }
+ *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */
+ *atimeP = s.st_atime;
+ return(0);
+}
+
+/*
+ * do_write - actually make the connection
+ */
+void
+do_write(int devfd, char *tty, char *mytty, const char *login)
+{
+ char *nows;
+ time_t now;
+ char host[MAXHOSTNAMELEN];
+ wchar_t line[512];
+ int fd;
+
+ fd = openat(devfd, tty, O_WRONLY);
+ if (fd < 0)
+ err(1, "openat(%s%s)", _PATH_DEV, tty);
+ fclose(stdout);
+ stdout = fdopen(fd, "w");
+ if (stdout == NULL)
+ err(1, "%s%s", _PATH_DEV, tty);
+
+ (void)signal(SIGINT, done);
+ (void)signal(SIGHUP, done);
+
+ /* print greeting */
+ if (gethostname(host, sizeof(host)) < 0)
+ (void)strcpy(host, "???");
+ now = time((time_t *)NULL);
+ nows = ctime(&now);
+ nows[16] = '\0';
+ (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n",
+ login, host, mytty, nows + 11);
+
+ while (fgetws(line, sizeof(line)/sizeof(wchar_t), stdin) != NULL)
+ wr_fputs(line);
+}
+
+/*
+ * done - cleanup and exit
+ */
+void
+done(int n __unused)
+{
+ (void)printf("EOF\r\n");
+ exit(0);
+}
+
+/*
+ * wr_fputs - like fputs(), but makes control characters visible and
+ * turns \n into \r\n
+ */
+void
+wr_fputs(wchar_t *s)
+{
+
+#define PUTC(c) if (putwchar(c) == WEOF) err(1, NULL);
+
+ for (; *s != L'\0'; ++s) {
+ if (*s == L'\n') {
+ PUTC(L'\r');
+ PUTC(L'\n');
+ } else if (iswprint(*s) || iswspace(*s)) {
+ PUTC(*s);
+ } else {
+ wprintf(L"<0x%X>", *s);
+ }
+ }
+ return;
+#undef PUTC
+}
diff --git a/usr.bin/xargs/Makefile b/usr.bin/xargs/Makefile
new file mode 100644
index 000000000000..3202d0e7322a
--- /dev/null
+++ b/usr.bin/xargs/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= xargs
+SRCS= xargs.c strnsubst.c
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xargs/Makefile.depend b/usr.bin/xargs/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/xargs/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xargs/Makefile.depend.host b/usr.bin/xargs/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/xargs/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xargs/Makefile.depend.options b/usr.bin/xargs/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/xargs/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/xargs/pathnames.h b/usr.bin/xargs/pathnames.h
new file mode 100644
index 000000000000..b804276da175
--- /dev/null
+++ b/usr.bin/xargs/pathnames.h
@@ -0,0 +1,32 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 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.
+ */
+
+#define _PATH_ECHO "/bin/echo"
diff --git a/usr.bin/xargs/strnsubst.c b/usr.bin/xargs/strnsubst.c
new file mode 100644
index 000000000000..1d4eaac77727
--- /dev/null
+++ b/usr.bin/xargs/strnsubst.c
@@ -0,0 +1,112 @@
+/* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */
+
+/*
+ * Copyright (c) 2002 J. Mallett. All rights reserved.
+ * You may do whatever you want with this file as long as
+ * the above copyright and this notice remain intact, along
+ * with the following statement:
+ * For the man who taught me vi, and who got too old, too young.
+ */
+
+#include <sys/cdefs.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+bool strnsubst(char **, const char *, const char *, size_t);
+
+/*
+ * Replaces str with a string consisting of str with match replaced with
+ * replstr as many times as can be done before the constructed string is
+ * maxsize bytes large. It does not free the string pointed to by str, it
+ * is up to the calling program to be sure that the original contents of
+ * str as well as the new contents are handled in an appropriate manner.
+ * If replstr is NULL, then that internally is changed to a nil-string, so
+ * that we can still pretend to do somewhat meaningful substitution.
+ *
+ * Returns true if truncation was needed to do the replacement, false if
+ * truncation was not required.
+ */
+bool
+strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
+{
+ char *s1, *s2, *this;
+ bool error = false;
+
+ s1 = *str;
+ if (s1 == NULL)
+ return false;
+ /*
+ * If maxsize is 0 then set it to the length of s1, because we have
+ * to duplicate s1. XXX we maybe should double-check whether the match
+ * appears in s1. If it doesn't, then we also have to set the length
+ * to the length of s1, to avoid modifying the argument. It may make
+ * sense to check if maxsize is <= strlen(s1), because in that case we
+ * want to return the unmodified string, too.
+ */
+ if (maxsize == 0) {
+ match = NULL;
+ maxsize = strlen(s1) + 1;
+ }
+ s2 = calloc(1, maxsize);
+ if (s2 == NULL)
+ err(1, "calloc");
+
+ if (replstr == NULL)
+ replstr = "";
+
+ if (match == NULL || replstr == NULL || maxsize == strlen(s1)) {
+ strlcpy(s2, s1, maxsize);
+ goto done;
+ }
+
+ for (;;) {
+ this = strstr(s1, match);
+ if (this == NULL)
+ break;
+ if ((strlen(s2) + strlen(s1) + strlen(replstr) -
+ strlen(match) + 1) > maxsize) {
+ strlcat(s2, s1, maxsize);
+ error = true;
+ goto done;
+ }
+ strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1);
+ strcat(s2, replstr);
+ s1 = this + strlen(match);
+ }
+ strcat(s2, s1);
+done:
+ *str = s2;
+ return error;
+}
+
+#ifdef TEST
+#include <stdio.h>
+
+int
+main(void)
+{
+ char *x, *y, *z, *za;
+
+ x = "{}%$";
+ strnsubst(&x, "%$", "{} enpury!", 255);
+ y = x;
+ strnsubst(&y, "}{}", "ybir", 255);
+ z = y;
+ strnsubst(&z, "{", "v ", 255);
+ za = z;
+ strnsubst(&z, NULL, za, 255);
+ if (strcmp(z, "v ybir enpury!") == 0)
+ printf("strnsubst() seems to work!\n");
+ else
+ printf("strnsubst() is broken.\n");
+ printf("%s\n", z);
+ free(x);
+ free(y);
+ free(z);
+ free(za);
+ return 0;
+}
+#endif
diff --git a/usr.bin/xargs/tests/Makefile b/usr.bin/xargs/tests/Makefile
new file mode 100644
index 000000000000..b1e6782069de
--- /dev/null
+++ b/usr.bin/xargs/tests/Makefile
@@ -0,0 +1,28 @@
+PACKAGE= tests
+
+TAP_TESTS_SH= legacy_test
+
+${PACKAGE}FILES+= regress.0.in
+${PACKAGE}FILES+= regress.0.out
+${PACKAGE}FILES+= regress.0I.out
+${PACKAGE}FILES+= regress.0J.out
+${PACKAGE}FILES+= regress.0L.out
+${PACKAGE}FILES+= regress.0P1.out
+${PACKAGE}FILES+= regress.I.out
+${PACKAGE}FILES+= regress.J.out
+${PACKAGE}FILES+= regress.L.out
+${PACKAGE}FILES+= regress.P1.out
+${PACKAGE}FILES+= regress.R.out
+${PACKAGE}FILES+= regress.R-1.out
+${PACKAGE}FILES+= regress.in
+${PACKAGE}FILES+= regress.n1.out
+${PACKAGE}FILES+= regress.n2.out
+${PACKAGE}FILES+= regress.n2147483647.out
+${PACKAGE}FILES+= regress.n2P0.out
+${PACKAGE}FILES+= regress.n3.out
+${PACKAGE}FILES+= regress.normal.out
+${PACKAGE}FILES+= regress.quotes.in
+${PACKAGE}FILES+= regress.quotes.out
+${PACKAGE}FILES+= regress.sh
+
+.include <bsd.test.mk>
diff --git a/usr.bin/xargs/tests/Makefile.depend b/usr.bin/xargs/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/xargs/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xargs/tests/legacy_test.sh b/usr.bin/xargs/tests/legacy_test.sh
new file mode 100644
index 000000000000..3c7842d07bf0
--- /dev/null
+++ b/usr.bin/xargs/tests/legacy_test.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh
diff --git a/usr.bin/xargs/tests/regress.0.in b/usr.bin/xargs/tests/regress.0.in
new file mode 100644
index 000000000000..448ba5367d4e
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0.in
Binary files differ
diff --git a/usr.bin/xargs/tests/regress.0.out b/usr.bin/xargs/tests/regress.0.out
new file mode 100644
index 000000000000..2bc97257af69
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0.out
@@ -0,0 +1,8 @@
+quick ' brown
+fox jumped
+over "the lazy
+dog
+quick brown fox
+jumped over the
+lazy dog
+
diff --git a/usr.bin/xargs/tests/regress.0I.out b/usr.bin/xargs/tests/regress.0I.out
new file mode 100644
index 000000000000..16009c092b01
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0I.out
@@ -0,0 +1,18 @@
+The quick ' brown quick ' brownquick ' brown quick ' brown
+The fox jumped
+over "the lazy fox jumped
+over "the lazyfox jumped
+over "the lazy fox jumped
+over "the lazy
+The
+The dog
+quick brown fox dog
+quick brown foxdog
+quick brown fox dog
+quick brown fox
+The jumped over the jumped over thejumped over the jumped over the
+The lazy dog
+ lazy dog
+lazy dog
+ lazy dog
+
diff --git a/usr.bin/xargs/tests/regress.0J.out b/usr.bin/xargs/tests/regress.0J.out
new file mode 100644
index 000000000000..69c87f9fa52e
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0J.out
@@ -0,0 +1,4 @@
+The quick ' brown fox jumped
+over "the lazy dog
+quick brown fox jumped over the lazy dog
+ again.
diff --git a/usr.bin/xargs/tests/regress.0L.out b/usr.bin/xargs/tests/regress.0L.out
new file mode 100644
index 000000000000..2d13fcc0d388
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0L.out
@@ -0,0 +1,6 @@
+quick ' brown fox jumped
+over "the lazy
+dog
+quick brown fox
+jumped over the lazy dog
+
diff --git a/usr.bin/xargs/tests/regress.0P1.out b/usr.bin/xargs/tests/regress.0P1.out
new file mode 100644
index 000000000000..a95e9a252575
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.0P1.out
@@ -0,0 +1,4 @@
+quick ' brown fox jumped
+over "the lazy dog
+quick brown fox jumped over the lazy dog
+
diff --git a/usr.bin/xargs/tests/regress.I.out b/usr.bin/xargs/tests/regress.I.out
new file mode 100644
index 000000000000..f2a6a1e82e22
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.I.out
@@ -0,0 +1,4 @@
+The quick brown quick brown quick brown quick brownquick brown quick brown %
+The fox jumped fox jumped fox jumped fox jumpedfox jumped fox jumped %
+The over the lazy over the lazy over the lazy over the lazyover the lazy over the lazy %
+The dog dog dog dogdog dog %
diff --git a/usr.bin/xargs/tests/regress.J.out b/usr.bin/xargs/tests/regress.J.out
new file mode 100644
index 000000000000..b88a41e5076b
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.J.out
@@ -0,0 +1 @@
+The quick brown fox jumped over the lazy dog again.
diff --git a/usr.bin/xargs/tests/regress.L.out b/usr.bin/xargs/tests/regress.L.out
new file mode 100644
index 000000000000..7359dee8f366
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.L.out
@@ -0,0 +1,2 @@
+quick brown fox jumped over the lazy
+dog
diff --git a/usr.bin/xargs/tests/regress.P1.out b/usr.bin/xargs/tests/regress.P1.out
new file mode 100644
index 000000000000..cc32a92a2199
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.P1.out
@@ -0,0 +1 @@
+quick brown fox jumped over the lazy dog
diff --git a/usr.bin/xargs/tests/regress.R-1.out b/usr.bin/xargs/tests/regress.R-1.out
new file mode 100644
index 000000000000..7bdf58090c60
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.R-1.out
@@ -0,0 +1,4 @@
+The quick brown quick brown quick brown quick brownquick brown quick brown quick brown
+The fox jumped fox jumped fox jumped fox jumpedfox jumped fox jumped fox jumped
+The over the lazy over the lazy over the lazy over the lazyover the lazy over the lazy over the lazy
+The dog dog dog dogdog dog dog
diff --git a/usr.bin/xargs/tests/regress.R.out b/usr.bin/xargs/tests/regress.R.out
new file mode 100644
index 000000000000..6fe947f0d9e4
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.R.out
@@ -0,0 +1,4 @@
+The quick brown % % %% % %
+The fox jumped % % %% % %
+The over the lazy % % %% % %
+The dog % % %% % %
diff --git a/usr.bin/xargs/tests/regress.in b/usr.bin/xargs/tests/regress.in
new file mode 100644
index 000000000000..5252b480a520
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.in
@@ -0,0 +1,4 @@
+quick brown
+fox jumped
+over the lazy
+dog
diff --git a/usr.bin/xargs/tests/regress.n1.out b/usr.bin/xargs/tests/regress.n1.out
new file mode 100644
index 000000000000..77ef6c555c2d
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.n1.out
@@ -0,0 +1,8 @@
+quick
+brown
+fox
+jumped
+over
+the
+lazy
+dog
diff --git a/usr.bin/xargs/tests/regress.n2.out b/usr.bin/xargs/tests/regress.n2.out
new file mode 100644
index 000000000000..4fa3f55161d6
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.n2.out
@@ -0,0 +1,4 @@
+quick brown
+fox jumped
+over the
+lazy dog
diff --git a/usr.bin/xargs/tests/regress.n2147483647.out b/usr.bin/xargs/tests/regress.n2147483647.out
new file mode 100644
index 000000000000..cc32a92a2199
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.n2147483647.out
@@ -0,0 +1 @@
+quick brown fox jumped over the lazy dog
diff --git a/usr.bin/xargs/tests/regress.n2P0.out b/usr.bin/xargs/tests/regress.n2P0.out
new file mode 100644
index 000000000000..de062b213dd5
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.n2P0.out
@@ -0,0 +1,4 @@
+fox jumped
+lazy dog
+over the
+quick brown
diff --git a/usr.bin/xargs/tests/regress.n3.out b/usr.bin/xargs/tests/regress.n3.out
new file mode 100644
index 000000000000..21b2c1e97416
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.n3.out
@@ -0,0 +1,3 @@
+quick brown fox
+jumped over the
+lazy dog
diff --git a/usr.bin/xargs/tests/regress.normal.out b/usr.bin/xargs/tests/regress.normal.out
new file mode 100644
index 000000000000..458d9cb930c4
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.normal.out
@@ -0,0 +1 @@
+The quick brown fox jumped over the lazy dog
diff --git a/usr.bin/xargs/tests/regress.quotes.in b/usr.bin/xargs/tests/regress.quotes.in
new file mode 100644
index 000000000000..11388a05b046
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.quotes.in
@@ -0,0 +1,4 @@
+a 'b "c' \'d
+e\ f "g ' h"
+i\
+j
diff --git a/usr.bin/xargs/tests/regress.quotes.out b/usr.bin/xargs/tests/regress.quotes.out
new file mode 100644
index 000000000000..f79ad41ad0fd
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.quotes.out
@@ -0,0 +1,7 @@
+a
+b "c
+'d
+e f
+g ' h
+i
+j
diff --git a/usr.bin/xargs/tests/regress.sh b/usr.bin/xargs/tests/regress.sh
new file mode 100644
index 000000000000..9b4839d2a8ec
--- /dev/null
+++ b/usr.bin/xargs/tests/regress.sh
@@ -0,0 +1,32 @@
+
+echo 1..21
+
+REGRESSION_START($1)
+
+REGRESSION_TEST(`normal', `xargs echo The <${SRCDIR}/regress.in')
+REGRESSION_TEST(`I', `xargs -I% echo The % % % %% % % <${SRCDIR}/regress.in')
+REGRESSION_TEST(`J', `xargs -J% echo The % again. <${SRCDIR}/regress.in')
+REGRESSION_TEST(`L', `xargs -L3 echo <${SRCDIR}/regress.in')
+REGRESSION_TEST(`P1', `xargs -P1 echo <${SRCDIR}/regress.in')
+REGRESSION_TEST(`R', `xargs -I% -R1 echo The % % % %% % % <${SRCDIR}/regress.in')
+REGRESSION_TEST(`R-1', `xargs -I% -R-1 echo The % % % %% % % <${SRCDIR}/regress.in')
+REGRESSION_TEST(`n1', `xargs -n1 echo <${SRCDIR}/regress.in')
+REGRESSION_TEST(`n2', `xargs -n2 echo <${SRCDIR}/regress.in')
+# This test may consume a large amount of memory, making it unsuited to CI
+# environments. Disable it for now.
+#REGRESSION_TEST(`n2147483647', `xargs -n2147483647 <${SRCDIR}/regress.in')
+REGRESSION_TEST(`n2P0',`xargs -n2 -P0 echo <${SRCDIR}/regress.in | sort')
+REGRESSION_TEST(`n3', `xargs -n3 echo <${SRCDIR}/regress.in')
+REGRESSION_TEST(`0', `xargs -0 -n1 echo <${SRCDIR}/regress.0.in')
+REGRESSION_TEST(`0I', `xargs -0 -I% echo The % %% % <${SRCDIR}/regress.0.in')
+REGRESSION_TEST(`0J', `xargs -0 -J% echo The % again. <${SRCDIR}/regress.0.in')
+REGRESSION_TEST(`0L', `xargs -0 -L2 echo <${SRCDIR}/regress.0.in')
+REGRESSION_TEST(`0P1', `xargs -0 -P1 echo <${SRCDIR}/regress.0.in')
+REGRESSION_TEST(`quotes', `xargs -n1 echo <${SRCDIR}/regress.quotes.in')
+
+REGRESSION_TEST_FREEFORM(`parallel1', `echo /var/empty /var/empty | xargs -n1 -P2 test -d; [ $? = 0 ]')
+REGRESSION_TEST_FREEFORM(`parallel2', `echo /var/empty /var/empty/nodir | xargs -n1 -P2 test -d; [ $? = 1 ]')
+REGRESSION_TEST_FREEFORM(`parallel3', `echo /var/empty/nodir /var/empty | xargs -n1 -P2 test -d; [ $? = 1 ]')
+REGRESSION_TEST_FREEFORM(`parallel4', `echo /var/empty/nodir /var/empty/nodir | xargs -n1 -P2 test -d; [ $? = 1 ]')
+
+REGRESSION_END()
diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1
new file mode 100644
index 000000000000..f72ca911037e
--- /dev/null
+++ b/usr.bin/xargs/xargs.1
@@ -0,0 +1,388 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" John B. Roll Jr. and 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.
+.\" $xMach: xargs.1,v 1.2 2002/02/23 05:23:37 tim Exp $
+.\"
+.Dd September 21, 2020
+.Dt XARGS 1
+.Os
+.Sh NAME
+.Nm xargs
+.Nd "construct argument list(s) and execute utility"
+.Sh SYNOPSIS
+.Nm
+.Op Fl 0oprt
+.Op Fl E Ar eofstr
+.Oo
+.Fl I Ar replstr
+.Op Fl R Ar replacements
+.Op Fl S Ar replsize
+.Oc
+.Op Fl J Ar replstr
+.Op Fl L Ar number
+.Oo
+.Fl n Ar number
+.Op Fl x
+.Oc
+.Op Fl P Ar maxprocs
+.Op Fl s Ar size
+.Op Ar utility Op Ar argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility reads space, tab, newline and end-of-file delimited strings
+from the standard input and executes
+.Ar utility
+with the strings as
+arguments.
+.Pp
+Any arguments specified on the command line are given to
+.Ar utility
+upon each invocation, followed by some number of the arguments read
+from the standard input of
+.Nm .
+This is repeated until standard input is exhausted.
+.Pp
+Spaces, tabs and newlines may be embedded in arguments using single
+(``\ '\ '')
+or double (``"'') quotes or backslashes (``\e'').
+Single quotes escape all non-single quote characters, excluding newlines,
+up to the matching single quote.
+Double quotes escape all non-double quote characters, excluding newlines,
+up to the matching double quote.
+Any single character, including newlines, may be escaped by a backslash.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl 0 , Fl -null
+Change
+.Nm
+to expect NUL
+(``\\0'')
+characters as separators, instead of spaces and newlines.
+This is expected to be used in concert with the
+.Fl print0
+function in
+.Xr find 1 .
+.It Fl E Ar eofstr
+Use
+.Ar eofstr
+as a logical EOF marker.
+.It Fl I Ar replstr
+Execute
+.Ar utility
+for each input line, replacing one or more occurrences of
+.Ar replstr
+in up to
+.Ar replacements
+(or 5 if no
+.Fl R
+flag is specified) arguments to
+.Ar utility
+with the entire line of input.
+The resulting arguments, after replacement is done, will not be allowed to grow
+beyond
+.Ar replsize
+(or 255 if no
+.Fl S
+flag is specified)
+bytes; this is implemented by concatenating as much of the argument
+containing
+.Ar replstr
+as possible, to the constructed arguments to
+.Ar utility ,
+up to
+.Ar replsize
+bytes.
+The size limit does not apply to arguments to
+.Ar utility
+which do not contain
+.Ar replstr ,
+and furthermore, no replacement will be done on
+.Ar utility
+itself.
+Implies
+.Fl x .
+.It Fl J Ar replstr
+If this option is specified,
+.Nm
+will use the data read from standard input to replace the first occurrence of
+.Ar replstr
+instead of appending that data after all other arguments.
+This option will not affect how many arguments will be read from input
+.Pq Fl n ,
+or the size of the command(s)
+.Nm
+will generate
+.Pq Fl s .
+The option just moves where those arguments will be placed in the command(s)
+that are executed.
+The
+.Ar replstr
+must show up as a distinct
+.Ar argument
+to
+.Nm .
+It will not be recognized if, for instance, it is in the middle of a
+quoted string.
+Furthermore, only the first occurrence of the
+.Ar replstr
+will be replaced.
+For example, the following command will copy the list of files and
+directories which start with an uppercase letter in the current
+directory to
+.Pa destdir :
+.Pp
+.Dl /bin/ls -1d [A-Z]* | xargs -J % cp -Rp % destdir
+.It Fl L Ar number
+Call
+.Ar utility
+for every
+.Ar number
+lines read.
+If EOF is reached and fewer lines have been read than
+.Ar number
+then
+.Ar utility
+will be called with the available lines.
+.It Fl n Ar number , Fl -max-args= Ns Ar number
+Set the maximum number of arguments taken from standard input for each
+invocation of
+.Ar utility .
+An invocation of
+.Ar utility
+will use less than
+.Ar number
+standard input arguments if the number of bytes accumulated (see the
+.Fl s
+option) exceeds the specified
+.Ar size
+or there are fewer than
+.Ar number
+arguments remaining for the last invocation of
+.Ar utility .
+The current default value for
+.Ar number
+is 5000.
+.It Fl o
+Reopen stdin as
+.Pa /dev/tty
+in the child process before executing the command.
+This is useful if you want
+.Nm
+to run an interactive application.
+.It Fl P Ar maxprocs , Fl -max-procs= Ns Ar maxprocs
+Parallel mode: run at most
+.Ar maxprocs
+invocations of
+.Ar utility
+at once.
+If
+.Ar maxprocs
+is set to 0,
+.Nm
+will run as many processes as possible.
+.It Fl p , Fl -interactive
+Echo each command to be executed and ask the user whether it should be
+executed.
+An affirmative response,
+.Ql y
+in the POSIX locale,
+causes the command to be executed, any other response causes it to be
+skipped.
+No commands are executed if the process is not attached to a terminal.
+.It Fl r , Fl -no-run-if-empty
+Compatibility with GNU
+.Nm .
+The GNU version of
+.Nm
+runs the
+.Ar utility
+argument at least once, even if
+.Nm
+input is empty, and it supports a
+.Fl r
+option to inhibit this behavior.
+The
+.Fx
+version of
+.Nm
+does not run the
+.Ar utility
+argument on empty input, but it supports the
+.Fl r
+option for command-line compatibility with GNU
+.Nm ,
+but the
+.Fl r
+option does nothing in the
+.Fx
+version of
+.Nm .
+.It Fl R Ar replacements
+Specify the maximum number of arguments that
+.Fl I
+will do replacement in.
+If
+.Ar replacements
+is negative, the number of arguments in which to replace is unbounded.
+.It Fl S Ar replsize
+Specify the amount of space (in bytes) that
+.Fl I
+can use for replacements.
+The default for
+.Ar replsize
+is 255.
+.It Fl s Ar size , Fl -max-chars= Ns Ar size
+Set the maximum number of bytes for the command line length provided to
+.Ar utility .
+The sum of the length of the utility name, the arguments passed to
+.Ar utility
+(including
+.Dv NULL
+terminators) and the current environment will be less than or equal to
+this number.
+The current default value for
+.Ar size
+is
+.Dv ARG_MAX
+- 4096.
+.It Fl t , Fl -verbose
+Echo the command to be executed to standard error immediately before it
+is executed.
+.It Fl x , Fl -exit
+Force
+.Nm
+to terminate immediately if a command line containing
+.Ar number
+arguments will not fit in the specified (or default) command line length.
+.El
+.Pp
+If
+.Ar utility
+is omitted,
+.Xr echo 1
+is used.
+.Pp
+Undefined behavior may occur if
+.Ar utility
+reads from the standard input.
+.Pp
+If a command line cannot be assembled, or
+cannot be invoked, or if an invocation of
+.Ar utility
+is terminated by a signal,
+or an invocation of
+.Ar utility
+exits with a value of 255, the
+.Nm
+utility stops processing input and exits after all invocations of
+.Ar utility
+finish processing.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with a value of 0 if no error occurs.
+If
+.Ar utility
+cannot be found,
+.Nm
+exits with a value of 127, otherwise if
+.Ar utility
+cannot be executed,
+.Nm
+exits with a value of 126.
+If any other error occurs,
+.Nm
+exits with a value of 1.
+.Sh EXAMPLES
+Create a 3x3 matrix with numbers from 1 to 9.
+Every
+.Xr echo 1
+instance receives three lines as arguments:
+.Bd -literal -offset indent
+$ seq 1 9 | xargs -L3 echo
+1 2 3
+4 5 6
+7 8 9
+.Ed
+.Pp
+Duplicate every line from standard input:
+.Bd -literal -offset indent
+$ echo -e "one\\ntwo\\nthree" | xargs -I % echo % %
+one one
+two two
+three three
+.Ed
+.Pp
+Execute at most 2 concurrent instances of
+.Xr find 1
+every one of them using one of the directories from the standard input:
+.Bd -literal -offset indent
+echo -e "/usr/ports\\n/etc\\n/usr/local" | xargs -J % -P2 -n1 find % -name file
+.Ed
+.Sh SEE ALSO
+.Xr echo 1 ,
+.Xr find 1 ,
+.Xr execvp 3
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be
+.St -p1003.2
+compliant.
+The
+.Fl J , o , P , R
+and
+.Fl S
+options are non-standard
+.Fx
+extensions which may not be available on other operating systems.
+.Sh HISTORY
+The
+.Nm
+utility appeared in PWB UNIX.
+.Sh BUGS
+If
+.Ar utility
+attempts to invoke another command such that the number of arguments or the
+size of the environment is increased, it risks
+.Xr execvp 3
+failing with
+.Er E2BIG .
+.Pp
+The
+.Nm
+utility does not take multibyte characters into account when performing
+string comparisons for the
+.Fl I
+and
+.Fl J
+options, which may lead to incorrect results in some locales.
diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c
new file mode 100644
index 000000000000..237beff26504
--- /dev/null
+++ b/usr.bin/xargs/xargs.c
@@ -0,0 +1,803 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * John B. Roll Jr.
+ *
+ * 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.
+ *
+ * $xMach: xargs.c,v 1.6 2002/02/23 05:27:47 tim Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/limits.h>
+#include <sys/resource.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <paths.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+static void parse_input(int, char *[]);
+static void prerun(int, char *[]);
+static int prompt(void);
+static void run(char **);
+static void usage(void);
+bool strnsubst(char **, const char *, const char *, size_t);
+static pid_t xwait(int block, int *status);
+static void xexit(const char *, const int);
+static void waitchildren(const char *, int);
+static void pids_init(void);
+static int pids_empty(void);
+static int pids_full(void);
+static void pids_add(pid_t pid);
+static int pids_remove(pid_t pid);
+static int findslot(pid_t pid);
+static int findfreeslot(void);
+static void clearslot(int slot);
+
+static char echo[] = _PATH_ECHO;
+static char **av, **bxp, **ep, **endxp, **xp;
+static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
+static const char *eofstr;
+static long eoflen;
+static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag;
+static int cnt, Iflag, jfound, Lflag, Sflag, wasquoted, xflag;
+static int curprocs, maxprocs;
+static pid_t *childpids;
+
+static volatile int childerr;
+
+extern char **environ;
+
+static const char *optstr = "+0E:I:J:L:n:oP:pR:S:s:rtx";
+
+static const struct option long_options[] =
+{
+ {"exit", no_argument, NULL, 'x'},
+ {"interactive", no_argument, NULL, 'p'},
+ {"max-args", required_argument, NULL, 'n'},
+ {"max-chars", required_argument, NULL, 's'},
+ {"max-procs", required_argument, NULL, 'P'},
+ {"no-run-if-empty", no_argument, NULL, 'r'},
+ {"null", no_argument, NULL, '0'},
+ {"verbose", no_argument, NULL, 't'},
+
+ {NULL, no_argument, NULL, 0},
+};
+
+int
+main(int argc, char *argv[])
+{
+ long arg_max;
+ int ch, Jflag, nargs, nflag, nline;
+ size_t linelen;
+ struct rlimit rl;
+ const char *errstr;
+
+ inpline = replstr = NULL;
+ ep = environ;
+ eofstr = "";
+ eoflen = 0;
+ Jflag = nflag = 0;
+
+ (void)setlocale(LC_ALL, "");
+
+ /*
+ * POSIX.2 limits the exec line length to ARG_MAX - 2K. Running that
+ * caused some E2BIG errors, so it was changed to ARG_MAX - 4K. Given
+ * that the smallest argument is 2 bytes in length, this means that
+ * the number of arguments is limited to:
+ *
+ * (ARG_MAX - 4K - LENGTH(utility + arguments)) / 2.
+ *
+ * We arbitrarily limit the number of arguments to 5000. This is
+ * allowed by POSIX.2 as long as the resulting minimum exec line is
+ * at least LINE_MAX. Realloc'ing as necessary is possible, but
+ * probably not worthwhile.
+ */
+ nargs = 5000;
+ if ((arg_max = sysconf(_SC_ARG_MAX)) == -1)
+ errx(1, "sysconf(_SC_ARG_MAX) failed");
+ nline = arg_max - 4 * 1024;
+ while (*ep != NULL) {
+ /* 1 byte for each '\0' */
+ nline -= strlen(*ep++) + 1 + sizeof(*ep);
+ }
+ maxprocs = 1;
+ while ((ch = getopt_long(argc, argv, optstr, long_options, NULL)) != -1)
+ switch (ch) {
+ case 'E':
+ eofstr = optarg;
+ eoflen = strlen(eofstr);
+ break;
+ case 'I':
+ Jflag = 0;
+ Iflag = 1;
+ Lflag = 1;
+ replstr = optarg;
+ break;
+ case 'J':
+ Iflag = 0;
+ Jflag = 1;
+ replstr = optarg;
+ break;
+ case 'L':
+ Lflag = (int)strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ break;
+ case 'n':
+ nflag = 1;
+ nargs = (int)strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ break;
+ case 'o':
+ oflag = 1;
+ break;
+ case 'P':
+ maxprocs = (int)strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ if (getrlimit(RLIMIT_NPROC, &rl) != 0)
+ errx(1, "getrlimit failed");
+ if (maxprocs == 0 || maxprocs > rl.rlim_cur)
+ maxprocs = rl.rlim_cur;
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'R':
+ Rflag = (int)strtonum(optarg, INT_MIN, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ if (!Rflag)
+ errx(1, "-%c %s: %s", ch, optarg, "must be non-zero");
+ break;
+ case 'r':
+ /* GNU compatibility */
+ break;
+ case 'S':
+ Sflag = (int)strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ break;
+ case 's':
+ nline = (int)strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "-%c %s: %s", ch, optarg, errstr);
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
+ case '0':
+ zflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!Iflag && Rflag)
+ usage();
+ if (!Iflag && Sflag)
+ usage();
+ if (Iflag && !Rflag)
+ Rflag = 5;
+ if (Iflag && !Sflag)
+ Sflag = 255;
+ if (xflag && !nflag)
+ usage();
+ if (Iflag || Lflag)
+ xflag = 1;
+ if (replstr != NULL && *replstr == '\0')
+ errx(1, "replstr may not be empty");
+
+ pids_init();
+
+ /*
+ * Allocate pointers for the utility name, the utility arguments,
+ * the maximum arguments to be read from stdin and the trailing
+ * NULL.
+ */
+ linelen = 1 + argc + (size_t)nargs + 1;
+ if ((av = bxp = malloc(linelen * sizeof(char *))) == NULL)
+ errx(1, "malloc failed");
+
+ /*
+ * Use the user's name for the utility as argv[0], just like the
+ * shell. Echo is the default. Set up pointers for the user's
+ * arguments.
+ */
+ if (*argv == NULL)
+ cnt = strlen(*bxp++ = echo);
+ else {
+ do {
+ if (Jflag && strcmp(*argv, replstr) == 0) {
+ char **avj;
+ jfound = 1;
+ argv++;
+ for (avj = argv; *avj; avj++)
+ cnt += strlen(*avj) + 1;
+ break;
+ }
+ cnt += strlen(*bxp++ = *argv) + 1;
+ } while (*++argv != NULL);
+ }
+
+ /*
+ * Set up begin/end/traversing pointers into the array. The -n
+ * count doesn't include the trailing NULL pointer, so the malloc
+ * added in an extra slot.
+ */
+ endxp = (xp = bxp) + nargs;
+
+ /*
+ * Allocate buffer space for the arguments read from stdin and the
+ * trailing NULL. Buffer space is defined as the default or specified
+ * space, minus the length of the utility name and arguments. Set up
+ * begin/end/traversing pointers into the array. The -s count does
+ * include the trailing NULL, so the malloc didn't add in an extra
+ * slot.
+ */
+ nline -= cnt;
+ if (nline <= 0)
+ errx(1, "insufficient space for command");
+
+ if ((bbp = malloc((size_t)(nline + 1))) == NULL)
+ errx(1, "malloc failed");
+ ebp = (argp = p = bbp) + nline - 1;
+ for (;;)
+ parse_input(argc, argv);
+}
+
+static void
+parse_input(int argc, char *argv[])
+{
+ int ch, foundeof;
+ char **avj;
+
+ foundeof = 0;
+
+ switch (ch = getchar()) {
+ case EOF:
+ /* No arguments since last exec. */
+ if (p == bbp) {
+ waitchildren(*av, 1);
+ exit(rval);
+ }
+ goto arg1;
+ case ' ':
+ case '\t':
+ /* Quotes escape tabs and spaces. */
+ if (insingle || indouble || zflag)
+ goto addch;
+ goto arg2;
+ case '\0':
+ if (zflag) {
+ /*
+ * Increment 'count', so that nulls will be treated
+ * as end-of-line, as well as end-of-argument. This
+ * is needed so -0 works properly with -I and -L.
+ */
+ count++;
+ goto arg2;
+ }
+ goto addch;
+ case '\n':
+ if (zflag)
+ goto addch;
+ count++; /* Indicate end-of-line (used by -L) */
+
+ /* Quotes do not escape newlines. */
+arg1: if (insingle || indouble) {
+ warnx("unterminated quote");
+ xexit(*av, 1);
+ }
+arg2:
+ foundeof = eoflen != 0 && p - argp == eoflen &&
+ strncmp(argp, eofstr, eoflen) == 0;
+
+ /* Do not make empty args unless they are quoted */
+ if ((argp != p || wasquoted) && !foundeof) {
+ *p++ = '\0';
+ *xp++ = argp;
+ if (Iflag) {
+ size_t curlen;
+
+ if (inpline == NULL)
+ curlen = 0;
+ else {
+ /*
+ * If this string is not zero
+ * length, append a space for
+ * separation before the next
+ * argument.
+ */
+ if ((curlen = strlen(inpline)))
+ strcat(inpline, " ");
+ }
+ curlen++;
+ /*
+ * Allocate enough to hold what we will
+ * be holding in a second, and to append
+ * a space next time through, if we have
+ * to.
+ */
+ inpline = realloc(inpline, curlen + 2 +
+ strlen(argp));
+ if (inpline == NULL) {
+ warnx("realloc failed");
+ xexit(*av, 1);
+ }
+ if (curlen == 1)
+ strcpy(inpline, argp);
+ else
+ strcat(inpline, argp);
+ }
+ }
+
+ /*
+ * If max'd out on args or buffer, or reached EOF,
+ * run the command. If xflag and max'd out on buffer
+ * but not on args, object. Having reached the limit
+ * of input lines, as specified by -L is the same as
+ * maxing out on arguments.
+ */
+ if (xp == endxp || p > ebp || ch == EOF ||
+ (Lflag <= count && xflag) || foundeof) {
+ if (xflag && xp != endxp && p > ebp) {
+ warnx("insufficient space for arguments");
+ xexit(*av, 1);
+ }
+ if (jfound) {
+ for (avj = argv; *avj; avj++)
+ *xp++ = *avj;
+ }
+ prerun(argc, av);
+ if (ch == EOF || foundeof) {
+ waitchildren(*av, 1);
+ exit(rval);
+ }
+ p = bbp;
+ xp = bxp;
+ count = 0;
+ }
+ argp = p;
+ wasquoted = 0;
+ break;
+ case '\'':
+ if (indouble || zflag)
+ goto addch;
+ insingle = !insingle;
+ wasquoted = 1;
+ break;
+ case '"':
+ if (insingle || zflag)
+ goto addch;
+ indouble = !indouble;
+ wasquoted = 1;
+ break;
+ case '\\':
+ if (zflag)
+ goto addch;
+ /* Backslash escapes anything, is escaped by quotes. */
+ if (!insingle && !indouble && (ch = getchar()) == EOF) {
+ warnx("backslash at EOF");
+ xexit(*av, 1);
+ }
+ /* FALLTHROUGH */
+ default:
+addch: if (p < ebp) {
+ *p++ = ch;
+ break;
+ }
+
+ /* If only one argument, not enough buffer space. */
+ if (bxp == xp) {
+ warnx("insufficient space for argument");
+ xexit(*av, 1);
+ }
+ /* Didn't hit argument limit, so if xflag object. */
+ if (xflag) {
+ warnx("insufficient space for arguments");
+ xexit(*av, 1);
+ }
+
+ if (jfound) {
+ for (avj = argv; *avj; avj++)
+ *xp++ = *avj;
+ }
+ prerun(argc, av);
+ xp = bxp;
+ cnt = ebp - argp;
+ memcpy(bbp, argp, (size_t)cnt);
+ p = (argp = bbp) + cnt;
+ *p++ = ch;
+ break;
+ }
+}
+
+/*
+ * Do things necessary before run()'ing, such as -I substitution,
+ * and then call run().
+ */
+static void
+prerun(int argc, char *argv[])
+{
+ char **tmp, **tmp2, **avj;
+ int repls;
+
+ repls = Rflag;
+
+ if (argc == 0 || repls == 0) {
+ *xp = NULL;
+ run(argv);
+ return;
+ }
+
+ avj = argv;
+
+ /*
+ * Allocate memory to hold the argument list, and
+ * a NULL at the tail.
+ */
+ tmp = malloc((argc + 1) * sizeof(char *));
+ if (tmp == NULL) {
+ warnx("malloc failed");
+ xexit(*argv, 1);
+ }
+ tmp2 = tmp;
+
+ /*
+ * Save the first argument and iterate over it, we
+ * cannot do strnsubst() to it.
+ */
+ if ((*tmp++ = strdup(*avj++)) == NULL) {
+ warnx("strdup failed");
+ xexit(*argv, 1);
+ }
+
+ /*
+ * For each argument to utility, if we have not used up
+ * the number of replacements we are allowed to do, and
+ * if the argument contains at least one occurrence of
+ * replstr, call strnsubst(), else just save the string.
+ * Iterations over elements of avj and tmp are done
+ * where appropriate.
+ */
+ while (--argc) {
+ *tmp = *avj++;
+ if (repls && strstr(*tmp, replstr) != NULL) {
+ if (strnsubst(tmp++, replstr, inpline, (size_t)Sflag)) {
+ warnx("command line cannot be assembled, too long");
+ xexit(*argv, 1);
+ }
+ if (repls > 0)
+ repls--;
+ } else {
+ if ((*tmp = strdup(*tmp)) == NULL) {
+ warnx("strdup failed");
+ xexit(*argv, 1);
+ }
+ tmp++;
+ }
+ }
+
+ /*
+ * Run it.
+ */
+ *tmp = NULL;
+ run(tmp2);
+
+ /*
+ * Walk from the tail to the head, free along the way.
+ */
+ for (; tmp2 != tmp; tmp--)
+ free(*tmp);
+ /*
+ * Now free the list itself.
+ */
+ free(tmp2);
+
+ /*
+ * Free the input line buffer, if we have one.
+ */
+ if (inpline != NULL) {
+ free(inpline);
+ inpline = NULL;
+ }
+}
+
+static void
+run(char **argv)
+{
+ pid_t pid;
+ int fd;
+ char **avec;
+
+ /*
+ * If the user wants to be notified of each command before it is
+ * executed, notify them. If they want the notification to be
+ * followed by a prompt, then prompt them.
+ */
+ if (tflag || pflag) {
+ (void)fprintf(stderr, "%s", *argv);
+ for (avec = argv + 1; *avec != NULL; ++avec)
+ (void)fprintf(stderr, " %s", *avec);
+ /*
+ * If the user has asked to be prompted, do so.
+ */
+ if (pflag)
+ /*
+ * If they asked not to exec, return without execution
+ * but if they asked to, go to the execution. If we
+ * could not open their tty, break the switch and drop
+ * back to -t behaviour.
+ */
+ switch (prompt()) {
+ case 0:
+ return;
+ case 1:
+ goto exec;
+ case 2:
+ break;
+ }
+ (void)fprintf(stderr, "\n");
+ (void)fflush(stderr);
+ }
+exec:
+ childerr = 0;
+ switch (pid = vfork()) {
+ case -1:
+ warn("vfork");
+ xexit(*argv, 1);
+ case 0:
+ if (oflag) {
+ if ((fd = open(_PATH_TTY, O_RDONLY)) == -1)
+ err(1, "can't open /dev/tty");
+ } else {
+ fd = open(_PATH_DEVNULL, O_RDONLY);
+ }
+ if (fd > STDIN_FILENO) {
+ if (dup2(fd, STDIN_FILENO) != 0)
+ err(1, "can't dup2 to stdin");
+ close(fd);
+ }
+ execvp(argv[0], argv);
+ childerr = errno;
+ _exit(1);
+ }
+ pids_add(pid);
+ waitchildren(*argv, 0);
+}
+
+/*
+ * Wait for a tracked child to exit and return its pid and exit status.
+ *
+ * Ignores (discards) all untracked child processes.
+ * Returns -1 and sets errno to ECHILD if no tracked children exist.
+ * If block is set, waits indefinitely for a child process to exit.
+ * If block is not set and no children have exited, returns 0 immediately.
+ */
+static pid_t
+xwait(int block, int *status) {
+ pid_t pid;
+
+ if (pids_empty()) {
+ errno = ECHILD;
+ return (-1);
+ }
+
+ while ((pid = waitpid(-1, status, block ? 0 : WNOHANG)) > 0)
+ if (pids_remove(pid))
+ break;
+
+ return (pid);
+}
+
+static void
+xexit(const char *name, const int exit_code) {
+ waitchildren(name, 1);
+ exit(exit_code);
+}
+
+static void
+waitchildren(const char *name, int waitall)
+{
+ pid_t pid;
+ int status;
+ int cause_exit = 0;
+
+ while ((pid = xwait(waitall || pids_full(), &status)) > 0) {
+ /*
+ * If we couldn't invoke the utility or if utility exited
+ * because of a signal or with a value of 255, warn (per
+ * POSIX), and then wait until all other children have
+ * exited before exiting 1-125. POSIX requires us to stop
+ * reading if child exits because of a signal or with 255,
+ * but it does not require us to exit immediately; waiting
+ * is preferable to orphaning.
+ */
+ if (childerr != 0 && cause_exit == 0) {
+ errno = childerr;
+ waitall = 1;
+ cause_exit = errno == ENOENT ? 127 : 126;
+ warn("%s", name);
+ } else if (WIFSIGNALED(status)) {
+ waitall = cause_exit = 1;
+ warnx("%s: terminated with signal %d; aborting",
+ name, WTERMSIG(status));
+ } else if (WEXITSTATUS(status) == 255) {
+ waitall = cause_exit = 1;
+ warnx("%s: exited with status 255; aborting", name);
+ } else if (WEXITSTATUS(status))
+ rval = 1;
+ }
+
+ if (cause_exit)
+ exit(cause_exit);
+ if (pid == -1 && errno != ECHILD)
+ err(1, "waitpid");
+}
+
+#define NOPID (0)
+
+static void
+pids_init(void)
+{
+ int i;
+
+ if ((childpids = malloc(maxprocs * sizeof(*childpids))) == NULL)
+ errx(1, "malloc failed");
+
+ for (i = 0; i < maxprocs; i++)
+ clearslot(i);
+}
+
+static int
+pids_empty(void)
+{
+
+ return (curprocs == 0);
+}
+
+static int
+pids_full(void)
+{
+
+ return (curprocs >= maxprocs);
+}
+
+static void
+pids_add(pid_t pid)
+{
+ int slot;
+
+ slot = findfreeslot();
+ childpids[slot] = pid;
+ curprocs++;
+}
+
+static int
+pids_remove(pid_t pid)
+{
+ int slot;
+
+ if ((slot = findslot(pid)) < 0)
+ return (0);
+
+ clearslot(slot);
+ curprocs--;
+ return (1);
+}
+
+static int
+findfreeslot(void)
+{
+ int slot;
+
+ if ((slot = findslot(NOPID)) < 0)
+ errx(1, "internal error: no free pid slot");
+ return (slot);
+}
+
+static int
+findslot(pid_t pid)
+{
+ int slot;
+
+ for (slot = 0; slot < maxprocs; slot++)
+ if (childpids[slot] == pid)
+ return (slot);
+ return (-1);
+}
+
+static void
+clearslot(int slot)
+{
+
+ childpids[slot] = NOPID;
+}
+
+/*
+ * Prompt the user about running a command.
+ */
+static int
+prompt(void)
+{
+ regex_t cre;
+ size_t rsize = 0;
+ int match;
+ char *response = NULL;
+ FILE *ttyfp;
+
+ if ((ttyfp = fopen(_PATH_TTY, "r")) == NULL)
+ return (2); /* Indicate that the TTY failed to open. */
+ (void)fprintf(stderr, "?...");
+ (void)fflush(stderr);
+ if (getline(&response, &rsize, ttyfp) < 0 ||
+ regcomp(&cre, nl_langinfo(YESEXPR), REG_EXTENDED) != 0) {
+ (void)fclose(ttyfp);
+ return (0);
+ }
+ match = regexec(&cre, response, 0, NULL, 0);
+ free(response);
+ (void)fclose(ttyfp);
+ regfree(&cre);
+ return (match == 0);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+"usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements] [-S replsize]]\n"
+" [-J replstr] [-L number] [-n number [-x]] [-P maxprocs]\n"
+" [-s size] [utility [argument ...]]\n");
+ exit(1);
+}
diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile
new file mode 100644
index 000000000000..fd95b97160fe
--- /dev/null
+++ b/usr.bin/xinstall/Makefile
@@ -0,0 +1,25 @@
+.include <src.opts.mk>
+
+PACKAGE= runtime
+
+PROG= xinstall
+PROGNAME= install
+SRCS= xinstall.c getid.c
+MAN= install.1
+
+.PATH: ${SRCTOP}/contrib/mtree
+CFLAGS+= -I${SRCTOP}/contrib/mtree
+CFLAGS+= -I${SRCTOP}/lib/libnetbsd
+
+LIBADD= md
+CFLAGS+= -DWITH_MD5 -DWITH_RIPEMD160
+
+.ifdef BOOTSTRAPPING
+# For the bootstrap we disable copy_file_range()
+CFLAGS+= -DBOOTSTRAP_XINSTALL
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xinstall/Makefile.depend b/usr.bin/xinstall/Makefile.depend
new file mode 100644
index 000000000000..dd01030911f8
--- /dev/null
+++ b/usr.bin/xinstall/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libmd \
+ lib/libutil \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1
new file mode 100644
index 000000000000..c923321f20fe
--- /dev/null
+++ b/usr.bin/xinstall/install.1
@@ -0,0 +1,366 @@
+.\" Copyright (c) 1987, 1990, 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.
+.\"
+.Dd April 16, 2024
+.Dt INSTALL 1
+.Os
+.Sh NAME
+.Nm install
+.Nd install binaries
+.Sh SYNOPSIS
+.Nm
+.Op Fl bCcpSsUv
+.Op Fl B Ar suffix
+.Op Fl D Ar destdir
+.Op Fl f Ar flags
+.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl l Ar linkflags
+.Op Fl M Ar metalog
+.Op Fl m Ar mode
+.Op Fl N Ar dbdir
+.Op Fl o Ar owner
+.Op Fl T Ar tags
+.Ar file1 file2
+.Nm
+.Op Fl bCcpSsUv
+.Op Fl B Ar suffix
+.Op Fl D Ar destdir
+.Op Fl f Ar flags
+.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl l Ar linkflags
+.Op Fl M Ar metalog
+.Op Fl m Ar mode
+.Op Fl N Ar dbdir
+.Op Fl o Ar owner
+.Op Fl T Ar tags
+.Ar file1 ... fileN directory
+.Nm
+.Fl d
+.Op Fl Uv
+.Op Fl D Ar destdir
+.Op Fl g Ar group
+.Op Fl h Ar hash
+.Op Fl M Ar metalog
+.Op Fl m Ar mode
+.Op Fl N Ar dbdir
+.Op Fl o Ar owner
+.Op Fl T Ar tags
+.Ar directory ...
+.Sh DESCRIPTION
+The file(s) are copied
+(or linked if the
+.Fl l
+option is specified) to the target file or directory.
+If the destination is a directory, then the
+.Ar file
+is copied into
+.Ar directory
+with its original filename.
+If the target file already exists, it is
+either renamed to
+.Ar file Ns Pa .old
+if the
+.Fl b
+option is given
+or overwritten
+if permissions allow.
+An alternate backup suffix may be specified via the
+.Fl B
+option's argument.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl B Ar suffix
+Use
+.Ar suffix
+as the backup suffix if
+.Fl b
+is given.
+.It Fl b
+Back up any existing files before overwriting them by renaming
+them to
+.Ar file Ns Pa .old .
+See
+.Fl B
+for specifying a different backup suffix.
+.It Fl C
+Copy the file.
+If the target file already exists and the files are the same,
+then do not change the modification time of the target.
+If the target's file flags and mode need not to be changed,
+the target's inode change time is also unchanged.
+.It Fl c
+Copy the file.
+This is actually the default.
+The
+.Fl c
+option is only included for backwards compatibility.
+.It Fl D Ar destdir
+Specify the
+.Ev DESTDIR
+(top of the file hierarchy) that the items are installed in to.
+If
+.Fl M Ar metalog
+is in use, a leading string of
+.Dq Ar destdir
+will be removed from the file names logged to the
+.Ar metalog .
+This option does not affect where the actual files are installed.
+.It Fl d
+Create directories.
+Missing parent directories are created as required.
+.It Fl f Ar flags
+Specify the target's file flags; see
+.Xr chflags 1
+for a list of possible flags and their meanings.
+.It Fl g Ar group
+Specify a group.
+A numeric GID is allowed.
+.It Fl h Ar hash
+When copying, calculate the digest of the files with
+.Ar hash
+to store in the
+.Fl M Ar metalog .
+When
+.Fl d
+is given no hash is emitted.
+Supported digests:
+.Bl -tag -width rmd160 -offset indent
+.It Sy none
+No hash.
+This is the default.
+.It Sy md5
+The MD5 cryptographic message digest.
+.It Sy rmd160
+The RMD-160 cryptographic message digest.
+.It Sy sha1
+The SHA-1 cryptographic message digest.
+.It Sy sha256
+The 256-bits SHA-2 cryptographic message digest of the file.
+.It Sy sha512
+The 512-bits SHA-2 cryptographic message digest of the file.
+.El
+.It Fl l Ar linkflags
+Instead of copying the file make a link to the source.
+The type of the link is determined by the
+.Ar linkflags
+argument.
+Valid
+.Ar linkflags
+are:
+.Ar a
+(absolute),
+.Ar r
+(relative),
+.Ar h
+(hard),
+.Ar s
+(symbolic),
+.Ar m
+(mixed).
+Absolute and relative have effect only for symbolic links.
+Mixed links
+are hard links for files on the same filesystem, symbolic otherwise.
+.It Fl M Ar metalog
+Write the metadata associated with each item installed to
+.Ar metalog
+in an
+.Xr mtree 8
+.Dq full path
+specification line.
+The metadata includes: the file name and file type, and depending upon
+other options, the owner, group, file flags, modification time, and tags.
+.It Fl m Ar mode
+Specify an alternate mode.
+The default mode is set to rwxr-xr-x (0755).
+The specified mode may be either an octal or symbolic value; see
+.Xr chmod 1
+for a description of possible mode values.
+.It Fl N Ar dbdir
+Use the user database text file
+.Pa master.passwd
+and group database text file
+.Pa group
+from
+.Ar dbdir ,
+rather than using the results from the system's
+.Xr getpwnam 3
+and
+.Xr getgrnam 3
+(and related) library calls.
+.It Fl o Ar owner
+Specify an owner.
+A numeric UID is allowed.
+.It Fl p
+Preserve the access and modification times.
+Copy the file, as if the
+.Fl C
+(compare and copy) option is specified,
+except if the target file does not already exist or is different,
+then preserve the access and modification times of the source file.
+.It Fl S
+Flush each file to disk after copying.
+This has a non-negligible impact on performance, but reduces the risk
+of being left with a partial file if the system crashes or loses power
+shortly after
+.Nm
+runs.
+.Pp
+Historically,
+.Fl S
+also enabled the use of temporary files to ensure atomicity when
+replacing an existing target.
+Temporary files are no longer optional.
+.It Fl s
+.Nm
+exec's the command
+.Xr strip 1
+to strip binaries so that
+.Nm
+can be portable over a large
+number of systems and binary types.
+See below for how
+.Nm
+can be instructed to use another program to strip binaries.
+.It Fl T Ar tags
+Specify the
+.Xr mtree 8
+tags to write out for the file when using
+.Fl M Ar metalog .
+.It Fl U
+Indicate that install is running unprivileged, and that it should not
+try to change the owner, the group, or the file flags of the destination.
+The information that would have been updated can be stored in a log
+file with
+.Fl M Ar metalog .
+.It Fl v
+Cause
+.Nm
+to be verbose,
+showing files as they are installed or backed up.
+.El
+.Pp
+By default,
+.Nm
+preserves all file flags, with the exception of the
+.Dq nodump
+flag.
+.Pp
+The
+.Nm
+utility attempts to prevent moving a file onto itself.
+.Pp
+Installing
+.Pa /dev/null
+creates an empty file.
+.Sh ENVIRONMENT
+The
+.Nm
+utility checks for the presence of the
+.Ev STRIPBIN
+environment variable and if present,
+uses the assigned value as the program to run if and when the
+.Fl s
+option has been specified.
+.Pp
+If the
+.Ev DONTSTRIP
+environment variable is present,
+.Nm
+will ignore any specification of the
+.Fl s
+option.
+This is mainly for use in debugging the
+.Fx
+Ports Collection.
+.Sh FILES
+.Bl -tag -width "INS@XXXXXX" -compact
+.It Pa INS@XXXXXX
+Temporary files named
+.Pa INS@XXXXXX ,
+where
+.Pa XXXXXX
+is decided by
+.Xr mkstemp 3 ,
+are created in the target directory.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh COMPATIBILITY
+Historically
+.Nm
+moved files by default.
+The default was changed to copy in
+.Fx 4.4 .
+.Sh SEE ALSO
+.Xr chflags 1 ,
+.Xr chgrp 1 ,
+.Xr chmod 1 ,
+.Xr cp 1 ,
+.Xr mv 1 ,
+.Xr strip 1 ,
+.Xr getgrnam 3 ,
+.Xr getpwnam 3 ,
+.Xr chown 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.2 .
+.Sh BUGS
+The meaning of the
+.Fl M
+option has changed as of
+.Fx 9.2
+and it now takes an argument.
+Command lines that used the old
+.Fl M
+will get an error or in rare cases will append logs to the first of
+multiple source files rather than installing it.
+.Pp
+Temporary files may be left in the target directory if
+.Nm
+exits abnormally.
+.Pp
+File flags cannot be set by
+.Xr fchflags 2
+over a NFS file system.
+Other file systems do not have a concept of flags.
+The
+.Nm
+utility will only warn when flags could not be set on a file system
+that does not support them.
+.Pp
+The
+.Nm
+utility with
+.Fl v
+falsely says a file is copied when
+.Fl C
+snaps hard links.
diff --git a/usr.bin/xinstall/tests/Makefile b/usr.bin/xinstall/tests/Makefile
new file mode 100644
index 000000000000..46b47dc97c65
--- /dev/null
+++ b/usr.bin/xinstall/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH+= install_test
+
+.include <bsd.test.mk>
diff --git a/usr.bin/xinstall/tests/Makefile.depend b/usr.bin/xinstall/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/xinstall/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh
new file mode 100755
index 000000000000..0f1f93ab4c63
--- /dev/null
+++ b/usr.bin/xinstall/tests/install_test.sh
@@ -0,0 +1,560 @@
+#
+# Copyright (c) 2016 Jilles Tjoelker
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+
+atf_test_case copy_to_empty
+copy_to_empty_body() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check -s not-exit:0 -e match:"empty string" \
+ install testf ""
+}
+
+atf_test_case copy_to_nonexistent_dir
+copy_to_nonexistent_dir_body() {
+ local dir="/nonexistent"
+
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check -s not-exit:0 -e match:$dir": No such file or directory" \
+ install testf $dir/testf
+}
+
+copy_to_nonexistent_with_opts() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install "$@" testf copyf
+ cmp testf copyf || atf_fail "bad copy"
+ [ ! testf -nt copyf ] || atf_fail "bad timestamp"
+ [ ! -e copyf.bak ] || atf_fail "no backup expected"
+}
+
+atf_test_case copy_to_nonexistent
+copy_to_nonexistent_body() {
+ copy_to_nonexistent_with_opts
+}
+
+atf_test_case copy_to_nonexistent_safe
+copy_to_nonexistent_safe_body() {
+ copy_to_nonexistent_with_opts -S
+}
+
+atf_test_case copy_to_nonexistent_comparing
+copy_to_nonexistent_comparing_body() {
+ copy_to_nonexistent_with_opts -C
+}
+
+atf_test_case copy_to_nonexistent_safe_comparing
+copy_to_nonexistent_safe_comparing_body() {
+ copy_to_nonexistent_with_opts -S -C
+}
+
+atf_test_case copy_to_nonexistent_backup
+copy_to_nonexistent_backup_body() {
+ copy_to_nonexistent_with_opts -b -B.bak
+}
+
+atf_test_case copy_to_nonexistent_backup_safe
+copy_to_nonexistent_backup_safe_body() {
+ copy_to_nonexistent_with_opts -b -B.bak -S
+}
+
+atf_test_case copy_to_nonexistent_preserving
+copy_to_nonexistent_preserving_body() {
+ copy_to_nonexistent_with_opts -p
+ [ ! testf -ot copyf ] || atf_fail "bad timestamp 2"
+}
+
+copy_self_with_opts() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0z' >testf2
+ atf_check -s not-exit:0 -o empty -e match:. install "$@" testf testf
+ cmp testf testf2 || atf_fail "file changed after self-copy attempt"
+}
+
+atf_test_case copy_self
+copy_self_body() {
+ copy_self_with_opts
+}
+
+atf_test_case copy_self_safe
+copy_self_safe_body() {
+ copy_self_with_opts -S
+}
+
+atf_test_case copy_self_comparing
+copy_self_comparing_body() {
+ copy_self_with_opts -C
+}
+
+atf_test_case copy_self_safe_comparing
+copy_self_safe_comparing_body() {
+ copy_self_with_opts -S -C
+}
+
+overwrite_with_opts() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0w' >otherf
+ atf_check install "$@" testf otherf
+ cmp testf otherf || atf_fail "bad overwrite"
+ [ ! testf -nt otherf ] || atf_fail "bad timestamp"
+}
+
+atf_test_case overwrite
+overwrite_body() {
+ overwrite_with_opts
+}
+
+atf_test_case overwrite_safe
+overwrite_safe_body() {
+ overwrite_with_opts -S
+}
+
+atf_test_case overwrite_comparing
+overwrite_comparing_body() {
+ overwrite_with_opts -C
+}
+
+atf_test_case overwrite_safe_comparing
+overwrite_safe_comparing_body() {
+ overwrite_with_opts -S -C
+}
+
+overwrite_eq_with_opts() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0z' >otherf
+ atf_check install "$@" testf otherf
+ cmp testf otherf || atf_fail "bad overwrite"
+ [ ! testf -nt otherf ] || atf_fail "bad timestamp"
+}
+
+atf_test_case overwrite_eq
+overwrite_eq_body() {
+ overwrite_eq_with_opts
+}
+
+atf_test_case overwrite_eq_safe
+overwrite_eq_safe_body() {
+ overwrite_eq_with_opts -S
+}
+
+atf_test_case overwrite_eq_comparing
+overwrite_eq_comparing_body() {
+ overwrite_eq_with_opts -C
+}
+
+atf_test_case overwrite_eq_safe_comparing
+overwrite_eq_safe_comparing_body() {
+ overwrite_eq_with_opts -S -C
+}
+
+overwrite_backup_with_opts() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0w' >otherf
+ printf 'test\n123\r456\r\n789\0w' >otherf2
+ atf_check install -b -B.bak "$@" testf otherf
+ cmp testf otherf || atf_fail "bad overwrite"
+ [ ! testf -nt otherf ] || atf_fail "bad timestamp"
+ cmp otherf.bak otherf2 || atf_fail "bad backup"
+}
+
+atf_test_case overwrite_backup
+overwrite_backup_body() {
+ overwrite_backup_with_opts
+}
+
+atf_test_case overwrite_backup_safe
+overwrite_backup_safe_body() {
+ overwrite_backup_with_opts -S
+}
+
+atf_test_case overwrite_backup_comparing
+overwrite_backup_comparing_body() {
+ overwrite_backup_with_opts -C
+}
+
+atf_test_case overwrite_backup_safe_comparing
+overwrite_backup_safe_comparing_body() {
+ overwrite_backup_with_opts -S -C
+}
+
+setup_stripbin() {
+ cat <<\STRIPBIN >stripbin
+#!/bin/sh
+[ "$1" = "-o" ] && dst="$2" && shift 2
+[ "$1" = "--" ] && shift
+[ -z "$dst" ] && dst="$1"
+STRIPBIN
+ [ "$1" = "true" ] && cmd="cat" || cmd="tr z @"
+ echo $cmd '<"$1" >"$1.new" && mv -- "$1.new" "$dst"' >>stripbin
+ chmod 755 stripbin
+ export STRIPBIN="$PWD/stripbin"
+}
+
+strip_changing_with_opts() {
+ setup_stripbin
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -s "$@" testf copyf
+ [ ! testf -nt copyf ] || atf_fail "bad timestamp"
+ printf 'test\n123\r456\r\n789\0@' >otherf
+ cmp otherf copyf || atf_fail "bad stripped copy"
+}
+
+atf_test_case strip_changing
+strip_changing_body() {
+ strip_changing_with_opts
+}
+
+atf_test_case strip_changing_comparing
+strip_changing_comparing_body() {
+ strip_changing_with_opts -C
+}
+
+strip_changing_overwrite_with_opts() {
+ setup_stripbin
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0w' >copyf
+ atf_check install -s "$@" testf copyf
+ [ ! testf -nt copyf ] || atf_fail "bad timestamp"
+ printf 'test\n123\r456\r\n789\0@' >otherf
+ cmp otherf copyf || atf_fail "bad stripped copy"
+}
+
+atf_test_case strip_changing_overwrite
+strip_changing_overwrite_body() {
+ strip_changing_overwrite_with_opts
+}
+
+atf_test_case strip_changing_overwrite_comparing
+strip_changing_overwrite_comparing_body() {
+ strip_changing_overwrite_with_opts -C
+}
+
+strip_changing_overwrite_eq_with_opts() {
+ setup_stripbin
+ printf 'test\n123\r456\r\n789\0z' >testf
+ printf 'test\n123\r456\r\n789\0@' >copyf
+ atf_check install -s "$@" testf copyf
+ [ ! testf -nt copyf ] || atf_fail "bad timestamp"
+ printf 'test\n123\r456\r\n789\0@' >otherf
+ cmp otherf copyf || atf_fail "bad stripped copy"
+}
+
+atf_test_case strip_changing_overwrite_eq
+strip_changing_overwrite_eq_body() {
+ strip_changing_overwrite_eq_with_opts
+}
+
+atf_test_case strip_changing_overwrite_eq_comparing
+strip_changing_overwrite_eq_comparing_body() {
+ strip_changing_overwrite_eq_with_opts -C
+}
+
+atf_test_case strip_noop
+strip_noop_body() {
+ setup_stripbin true
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -s testf copyf
+ [ ! testf -nt copyf ] || atf_fail "bad timestamp"
+ printf 'test\n123\r456\r\n789\0z' >otherf
+ cmp otherf copyf || atf_fail "bad stripped copy"
+}
+
+atf_test_case hard_link
+hard_link_body() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -l h testf copyf
+ [ testf -ef copyf ] || atf_fail "not same file"
+ [ ! -L copyf ] || atf_fail "copy is symlink"
+}
+
+atf_test_case symbolic_link
+symbolic_link_body() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -l s testf copyf
+ [ testf -ef copyf ] || atf_fail "not same file"
+ [ -L copyf ] || atf_fail "copy is not symlink"
+}
+
+atf_test_case symbolic_link_absolute
+symbolic_link_absolute_body() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -l sa testf copyf
+ [ testf -ef copyf ] || atf_fail "not same file"
+ [ -L copyf ] || atf_fail "copy is not symlink"
+ copyf_path=$(readlink copyf)
+ testf_path="$(pwd -P)/testf"
+ if [ "$copyf_path" != "$testf_path" ]; then
+ atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')"
+ fi
+}
+
+atf_test_case symbolic_link_relative
+symbolic_link_relative_body() {
+ printf 'test\n123\r456\r\n789\0z' >testf
+ atf_check install -l sr testf copyf
+ [ testf -ef copyf ] || atf_fail "not same file"
+ [ -L copyf ] || atf_fail "copy is not symlink"
+ copyf_path=$(readlink copyf)
+ testf_path="testf"
+ if [ "$copyf_path" != "$testf_path" ]; then
+ atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')"
+ fi
+}
+
+atf_test_case symbolic_link_relative_absolute_source_and_dest1
+symbolic_link_relative_absolute_source_and_dest1_head() {
+ atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf)"
+}
+symbolic_link_relative_absolute_source_and_dest1_body() {
+ src_path=a/b/c/testf
+ src_path_prefixed=$PWD/$src_path
+ dest_path=$PWD/copyf
+
+ atf_check mkdir -p a/b/c
+ atf_check touch $src_path
+ atf_check install -l sr $src_path_prefixed $dest_path
+ [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
+ [ -L $dest_path ] || atf_fail "copy is not symlink"
+ dest_path_relative=$(readlink $dest_path)
+ src_path_relative="$src_path"
+ if [ "$src_path_relative" != "$dest_path_relative" ]; then
+ atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
+ fi
+}
+
+atf_test_case symbolic_link_relative_absolute_source_and_dest1_double_slash
+symbolic_link_relative_absolute_source_and_dest1_double_slash_head() {
+ atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf), using double-slashes"
+}
+symbolic_link_relative_absolute_source_and_dest1_double_slash_body() {
+ src_path=a//b//c//testf
+ src_path_prefixed=$PWD/$src_path
+ dest_path=$PWD/copyf
+
+ atf_check mkdir -p a/b/c
+ atf_check touch $src_path
+ atf_check install -l sr $src_path_prefixed $dest_path
+ [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
+ [ -L $dest_path ] || atf_fail "copy is not symlink"
+ dest_path_relative=$(readlink $dest_path)
+ src_path_relative="$(echo $src_path | sed -e 's,//,/,g')"
+ if [ "$src_path_relative" != "$dest_path_relative" ]; then
+ atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
+ fi
+}
+
+atf_test_case symbolic_link_relative_absolute_source_and_dest2
+symbolic_link_relative_absolute_source_and_dest2_head() {
+ atf_set "descr" "Verify -l rs with absolute paths (.../a/b/c/copyf -> .../testf)"
+}
+symbolic_link_relative_absolute_source_and_dest2_body() {
+ src_path=testf
+ src_path_prefixed=$PWD/$src_path
+ dest_path=$PWD/a/b/c/copyf
+
+ atf_check mkdir -p a/b/c
+ atf_check touch $src_path
+ atf_check install -l sr $src_path_prefixed $dest_path
+ [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file"
+ [ -L $dest_path ] || atf_fail "copy is not symlink"
+ dest_path_relative=$(readlink $dest_path)
+ src_path_relative="../../../$src_path"
+ if [ "$src_path_relative" != "$dest_path_relative" ]; then
+ atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
+ fi
+}
+
+atf_test_case mkdir_simple
+mkdir_simple_body() {
+ atf_check install -d dir1/dir2
+ [ -d dir1 ] || atf_fail "dir1 missing"
+ [ -d dir1/dir2 ] || atf_fail "dir2 missing"
+ atf_check install -d dir1/dir2/dir3
+ [ -d dir1/dir2/dir3 ] || atf_fail "dir3 missing"
+ atf_check install -d dir1
+ atf_check install -d dir1/dir2/dir3
+}
+
+atf_test_case symbolic_link_relative_absolute_common
+symbolic_link_relative_absolute_common_head() {
+ atf_set "descr" "Verify -l rs with absolute paths having common components"
+}
+symbolic_link_relative_absolute_common_body() {
+ filename=foo.so
+ src_path=lib
+ src_path_prefixed=$PWD/$src_path
+ dest_path=$PWD/libexec/
+ src_file=$src_path_prefixed/$filename
+ dest_file=$dest_path/$filename
+
+ atf_check mkdir $src_path_prefixed $dest_path
+ atf_check touch $src_file
+ atf_check install -l sr $src_file $dest_path
+
+ dest_path_relative=$(readlink $dest_file)
+ src_path_relative="../lib/$filename"
+ if [ "$src_path_relative" != "$dest_path_relative" ]; then
+ atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')"
+ fi
+}
+
+atf_test_case set_owner_group_mode
+set_owner_group_mode_head() {
+ atf_set "require.user" "root"
+}
+set_owner_group_mode_body() {
+ local fu=65531 fg=65531
+ local cu=65532 cg=65532
+ local u="$(id -u)"
+ local g="$(id -g)"
+ local m=0755 cm=4444
+ printf "test" >testf
+ atf_check chown "$fu:$fg" testf
+ atf_check chmod "$m" testf
+
+ atf_check install testf testc
+ atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -o "$cu" testf testc
+ atf_check_equal "$cu:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -g "$cg" testf testc
+ atf_check_equal "$u:$cg:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -o "$cu" -g "$cg" testf testc
+ atf_check_equal "$cu:$cg:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -m "$cm" testf testc
+ atf_check_equal "$u:$g:10$cm" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -o "$cu" -m "$cm" testf testc
+ atf_check_equal "$cu:$g:10$cm" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -g "$cg" -m "$cm" testf testc
+ atf_check_equal "$u:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -o "$cu" -g "$cg" -m "$cm" testf testc
+ atf_check_equal "$cu:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)"
+}
+
+atf_test_case set_owner_group_mode_unpriv
+set_owner_group_mode_unpriv_head() {
+ atf_set "require.user" "root"
+}
+set_owner_group_mode_unpriv_body() {
+ local fu=65531 fg=65531
+ local cu=65532 cg=65532
+ local u="$(id -u)"
+ local g="$(id -g)"
+ local m=0755 cm=4444 cM=0444
+ printf "test" >testf
+ atf_check chown "$fu:$fg" testf
+ atf_check chmod "$m" testf
+
+ atf_check install -U testf testc
+ atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -o "$cu" testf testc
+ atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -g "$cg" testf testc
+ atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -o "$cu" -g "$cg" testf testc
+ atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -m "$cm" testf testc
+ atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -o "$cu" -m "$cm" testf testc
+ atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -g "$cg" -m "$cm" testf testc
+ atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
+
+ atf_check install -U -o "$cu" -g "$cg" -m "$cm" testf testc
+ atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)"
+}
+
+atf_test_case set_optional_exec
+set_optional_exec_head() {
+ atf_set "require.user" "unprivileged"
+}
+set_optional_exec_body()
+{
+ echo "abc" > testfile.src
+
+ atf_check install -d -m ug+rX testdir
+ atf_check test -x testdir
+
+ atf_check install -m ug+rX testfile.src testfile
+ atf_check test ! -x testfile
+}
+
+atf_init_test_cases() {
+ atf_add_test_case copy_to_empty
+ atf_add_test_case copy_to_nonexistent
+ atf_add_test_case copy_to_nonexistent_dir
+ atf_add_test_case copy_to_nonexistent_safe
+ atf_add_test_case copy_to_nonexistent_comparing
+ atf_add_test_case copy_to_nonexistent_safe_comparing
+ atf_add_test_case copy_to_nonexistent_backup
+ atf_add_test_case copy_to_nonexistent_backup_safe
+ atf_add_test_case copy_to_nonexistent_preserving
+ atf_add_test_case copy_self
+ atf_add_test_case copy_self_safe
+ atf_add_test_case copy_self_comparing
+ atf_add_test_case copy_self_safe_comparing
+ atf_add_test_case overwrite
+ atf_add_test_case overwrite_safe
+ atf_add_test_case overwrite_comparing
+ atf_add_test_case overwrite_safe_comparing
+ atf_add_test_case overwrite_eq
+ atf_add_test_case overwrite_eq_safe
+ atf_add_test_case overwrite_eq_comparing
+ atf_add_test_case overwrite_eq_safe_comparing
+ atf_add_test_case overwrite_backup
+ atf_add_test_case overwrite_backup_safe
+ atf_add_test_case overwrite_backup_comparing
+ atf_add_test_case overwrite_backup_safe_comparing
+ atf_add_test_case strip_changing
+ atf_add_test_case strip_changing_comparing
+ atf_add_test_case strip_changing_overwrite
+ atf_add_test_case strip_changing_overwrite_comparing
+ atf_add_test_case strip_changing_overwrite_eq
+ atf_add_test_case strip_changing_overwrite_eq_comparing
+ atf_add_test_case strip_noop
+ atf_add_test_case hard_link
+ atf_add_test_case symbolic_link
+ atf_add_test_case symbolic_link_absolute
+ atf_add_test_case symbolic_link_relative
+ atf_add_test_case symbolic_link_relative_absolute_source_and_dest1
+ atf_add_test_case symbolic_link_relative_absolute_source_and_dest1_double_slash
+ atf_add_test_case symbolic_link_relative_absolute_source_and_dest2
+ atf_add_test_case symbolic_link_relative_absolute_common
+ atf_add_test_case mkdir_simple
+ atf_add_test_case set_owner_group_mode
+ atf_add_test_case set_owner_group_mode_unpriv
+ atf_add_test_case set_optional_exec
+}
diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c
new file mode 100644
index 000000000000..02b3eeccf8a7
--- /dev/null
+++ b/usr.bin/xinstall/xinstall.c
@@ -0,0 +1,1499 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2012, 2013 SRI International
+ * Copyright (c) 1987, 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.
+ */
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <libgen.h>
+#ifdef WITH_MD5
+#include <md5.h>
+#endif
+#include <paths.h>
+#include <pwd.h>
+#ifdef WITH_RIPEMD160
+#include <ripemd.h>
+#endif
+#include <sha.h>
+#include <sha256.h>
+#include <sha512.h>
+#include <spawn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <vis.h>
+
+#include "mtree.h"
+
+/*
+ * Memory strategy threshold, in pages: if physmem is larger than this, use a
+ * large buffer.
+ */
+#define PHYSPAGES_THRESHOLD (32*1024)
+
+/* Maximum buffer size in bytes - do not allow it to grow larger than this. */
+#define BUFSIZE_MAX (2*1024*1024)
+
+/*
+ * Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS.
+ */
+#define BUFSIZE_SMALL (MAXPHYS)
+
+/*
+ * We need to build xinstall during the bootstrap stage when building on a
+ * non-FreeBSD system. Linux does not have the st_flags and st_birthtime
+ * members in struct stat so we need to omit support for changing those fields.
+ */
+#ifdef UF_SETTABLE
+#define HAVE_STRUCT_STAT_ST_FLAGS 1
+#else
+#define HAVE_STRUCT_STAT_ST_FLAGS 0
+#endif
+
+#define MAX_CMP_SIZE (16 * 1024 * 1024)
+
+#define LN_ABSOLUTE 0x01
+#define LN_RELATIVE 0x02
+#define LN_HARD 0x04
+#define LN_SYMBOLIC 0x08
+#define LN_MIXED 0x10
+
+#define DIRECTORY 0x01 /* Tell install it's a directory. */
+#define SETFLAGS 0x02 /* Tell install to set flags. */
+#define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
+#define BACKUP_SUFFIX ".old"
+
+typedef union {
+#ifdef WITH_MD5
+ MD5_CTX MD5;
+#endif
+#ifdef WITH_RIPEMD160
+ RIPEMD160_CTX RIPEMD160;
+#endif
+ SHA1_CTX SHA1;
+ SHA256_CTX SHA256;
+ SHA512_CTX SHA512;
+} DIGEST_CTX;
+
+static enum {
+ DIGEST_NONE = 0,
+#ifdef WITH_MD5
+ DIGEST_MD5,
+#endif
+#ifdef WITH_RIPEMD160
+ DIGEST_RIPEMD160,
+#endif
+ DIGEST_SHA1,
+ DIGEST_SHA256,
+ DIGEST_SHA512,
+} digesttype = DIGEST_NONE;
+
+extern char **environ;
+
+static gid_t gid;
+static uid_t uid;
+static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv,
+ safecopy, verbose;
+static int haveopt_f, haveopt_g, haveopt_m, haveopt_o;
+static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+static FILE *metafp;
+static const char *group, *owner;
+static const char *suffix = BACKUP_SUFFIX;
+static char *destdir, *digest, *fflags, *metafile, *tags;
+
+static int compare(int, const char *, size_t, int, const char *, size_t,
+ char **);
+static char *copy(int, const char *, int, const char *, off_t);
+static int create_tempfile(const char *, char *, size_t);
+static char *quiet_mktemp(char *template);
+static char *digest_file(const char *);
+static void digest_init(DIGEST_CTX *);
+static void digest_update(DIGEST_CTX *, const char *, size_t);
+static char *digest_end(DIGEST_CTX *, char *);
+static int do_link(const char *, const char *, const struct stat *);
+static void do_symlink(const char *, const char *, const struct stat *);
+static void makelink(const char *, const char *, const struct stat *);
+static void install(const char *, const char *, u_long, u_int);
+static void install_dir(char *);
+static void metadata_log(const char *, const char *, struct timespec *,
+ const char *, const char *, off_t);
+static int parseid(const char *, id_t *);
+static int strip(const char *, int, const char *, char **);
+static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct stat from_sb, to_sb;
+ mode_t *set;
+ u_long fset;
+ int ch, no_target;
+ u_int iflags;
+ char *p;
+ const char *to_name;
+
+ fset = 0;
+ iflags = 0;
+ set = NULL;
+ group = owner = NULL;
+ while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) !=
+ -1)
+ switch((char)ch) {
+ case 'B':
+ suffix = optarg;
+ /* FALLTHROUGH */
+ case 'b':
+ dobackup = 1;
+ break;
+ case 'C':
+ docompare = 1;
+ break;
+ case 'c':
+ /* For backwards compatibility. */
+ break;
+ case 'D':
+ destdir = optarg;
+ break;
+ case 'd':
+ dodir = 1;
+ break;
+ case 'f':
+ haveopt_f = 1;
+ fflags = optarg;
+ break;
+ case 'g':
+ haveopt_g = 1;
+ group = optarg;
+ break;
+ case 'h':
+ digest = optarg;
+ break;
+ case 'l':
+ for (p = optarg; *p != '\0'; p++)
+ switch (*p) {
+ case 's':
+ dolink &= ~(LN_HARD|LN_MIXED);
+ dolink |= LN_SYMBOLIC;
+ break;
+ case 'h':
+ dolink &= ~(LN_SYMBOLIC|LN_MIXED);
+ dolink |= LN_HARD;
+ break;
+ case 'm':
+ dolink &= ~(LN_SYMBOLIC|LN_HARD);
+ dolink |= LN_MIXED;
+ break;
+ case 'a':
+ dolink &= ~LN_RELATIVE;
+ dolink |= LN_ABSOLUTE;
+ break;
+ case 'r':
+ dolink &= ~LN_ABSOLUTE;
+ dolink |= LN_RELATIVE;
+ break;
+ default:
+ errx(1, "%c: invalid link type", *p);
+ /* NOTREACHED */
+ }
+ break;
+ case 'M':
+ metafile = optarg;
+ break;
+ case 'm':
+ haveopt_m = 1;
+ free(set);
+ if (!(set = setmode(optarg)))
+ errx(EX_USAGE, "invalid file mode: %s",
+ optarg);
+ break;
+ case 'N':
+ if (!setup_getid(optarg))
+ err(EX_OSERR, "Unable to use user and group "
+ "databases in `%s'", optarg);
+ break;
+ case 'o':
+ haveopt_o = 1;
+ owner = optarg;
+ break;
+ case 'p':
+ docompare = dopreserve = 1;
+ break;
+ case 'S':
+ safecopy = 1;
+ break;
+ case 's':
+ dostrip = 1;
+ break;
+ case 'T':
+ tags = optarg;
+ break;
+ case 'U':
+ dounpriv = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* some options make no sense when creating directories */
+ if (dostrip && dodir) {
+ warnx("-d and -s may not be specified together");
+ usage();
+ }
+
+ /*
+ * Default permissions based on whether we're a directory or not, since
+ * an +X may mean that we need to set the execute bit.
+ */
+ if (set != NULL)
+ mode = getmode(set, dodir ? S_IFDIR : 0) & ~S_IFDIR;
+ free(set);
+
+ if (getenv("DONTSTRIP") != NULL) {
+ warnx("DONTSTRIP set - will not strip installed binaries");
+ dostrip = 0;
+ }
+
+ /* must have at least two arguments, except when creating directories */
+ if (argc == 0 || (argc == 1 && !dodir))
+ usage();
+
+ if (digest != NULL) {
+ if (strcmp(digest, "none") == 0) {
+ digesttype = DIGEST_NONE;
+#ifdef WITH_MD5
+ } else if (strcmp(digest, "md5") == 0) {
+ digesttype = DIGEST_MD5;
+#endif
+#ifdef WITH_RIPEMD160
+ } else if (strcmp(digest, "rmd160") == 0) {
+ digesttype = DIGEST_RIPEMD160;
+#endif
+ } else if (strcmp(digest, "sha1") == 0) {
+ digesttype = DIGEST_SHA1;
+ } else if (strcmp(digest, "sha256") == 0) {
+ digesttype = DIGEST_SHA256;
+ } else if (strcmp(digest, "sha512") == 0) {
+ digesttype = DIGEST_SHA512;
+ } else {
+ warnx("unknown digest `%s'", digest);
+ usage();
+ }
+ }
+
+ /* get group and owner id's */
+ if (group != NULL && !dounpriv) {
+ if (gid_from_group(group, &gid) == -1) {
+ id_t id;
+ if (!parseid(group, &id))
+ errx(1, "unknown group %s", group);
+ gid = id;
+ }
+ } else
+ gid = (gid_t)-1;
+
+ if (owner != NULL && !dounpriv) {
+ if (uid_from_user(owner, &uid) == -1) {
+ id_t id;
+ if (!parseid(owner, &id))
+ errx(1, "unknown user %s", owner);
+ uid = id;
+ }
+ } else
+ uid = (uid_t)-1;
+
+ if (fflags != NULL && !dounpriv) {
+ if (strtofflags(&fflags, &fset, NULL))
+ errx(EX_USAGE, "%s: invalid flag", fflags);
+ iflags |= SETFLAGS;
+ }
+
+ if (metafile != NULL) {
+ if ((metafp = fopen(metafile, "a")) == NULL)
+ warn("open %s", metafile);
+ } else
+ digesttype = DIGEST_NONE;
+
+ if (dodir) {
+ for (; *argv != NULL; ++argv)
+ install_dir(*argv);
+ exit(EX_OK);
+ /* NOTREACHED */
+ }
+
+ to_name = argv[argc - 1];
+ no_target = stat(to_name, &to_sb);
+ if (!no_target && S_ISDIR(to_sb.st_mode)) {
+ if (dolink & LN_SYMBOLIC) {
+ if (lstat(to_name, &to_sb) != 0)
+ err(EX_OSERR, "%s vanished", to_name);
+ if (S_ISLNK(to_sb.st_mode)) {
+ if (argc != 2) {
+ errc(EX_CANTCREAT, ENOTDIR, "%s",
+ to_name);
+ }
+ install(*argv, to_name, fset, iflags);
+ exit(EX_OK);
+ }
+ }
+ for (; *argv != to_name; ++argv)
+ install(*argv, to_name, fset, iflags | DIRECTORY);
+ exit(EX_OK);
+ /* NOTREACHED */
+ }
+
+ /* can't do file1 file2 directory/file */
+ if (argc != 2) {
+ if (no_target)
+ warnx("target directory `%s' does not exist",
+ argv[argc - 1]);
+ else
+ warnx("target `%s' is not a directory",
+ argv[argc - 1]);
+ usage();
+ }
+
+ if (!no_target && !dolink) {
+ if (stat(*argv, &from_sb))
+ err(EX_OSERR, "%s", *argv);
+ if (!S_ISREG(to_sb.st_mode))
+ errc(EX_CANTCREAT, EFTYPE, "%s", to_name);
+ if (to_sb.st_dev == from_sb.st_dev &&
+ to_sb.st_ino == from_sb.st_ino) {
+ errx(EX_USAGE, "%s and %s are the same file",
+ *argv, to_name);
+ }
+ }
+ install(*argv, to_name, fset, iflags);
+ exit(EX_OK);
+ /* NOTREACHED */
+}
+
+static char *
+digest_file(const char *name)
+{
+
+ switch (digesttype) {
+#ifdef WITH_MD5
+ case DIGEST_MD5:
+ return (MD5File(name, NULL));
+#endif
+#ifdef WITH_RIPEMD160
+ case DIGEST_RIPEMD160:
+ return (RIPEMD160_File(name, NULL));
+#endif
+ case DIGEST_SHA1:
+ return (SHA1_File(name, NULL));
+ case DIGEST_SHA256:
+ return (SHA256_File(name, NULL));
+ case DIGEST_SHA512:
+ return (SHA512_File(name, NULL));
+ default:
+ return (NULL);
+ }
+}
+
+static void
+digest_init(DIGEST_CTX *c)
+{
+
+ switch (digesttype) {
+ case DIGEST_NONE:
+ break;
+#ifdef WITH_MD5
+ case DIGEST_MD5:
+ MD5Init(&(c->MD5));
+ break;
+#endif
+#ifdef WITH_RIPEMD160
+ case DIGEST_RIPEMD160:
+ RIPEMD160_Init(&(c->RIPEMD160));
+ break;
+#endif
+ case DIGEST_SHA1:
+ SHA1_Init(&(c->SHA1));
+ break;
+ case DIGEST_SHA256:
+ SHA256_Init(&(c->SHA256));
+ break;
+ case DIGEST_SHA512:
+ SHA512_Init(&(c->SHA512));
+ break;
+ }
+}
+
+static void
+digest_update(DIGEST_CTX *c, const char *data, size_t len)
+{
+
+ switch (digesttype) {
+ case DIGEST_NONE:
+ break;
+#ifdef WITH_MD5
+ case DIGEST_MD5:
+ MD5Update(&(c->MD5), data, len);
+ break;
+#endif
+#ifdef WITH_RIPEMD160
+ case DIGEST_RIPEMD160:
+ RIPEMD160_Update(&(c->RIPEMD160), data, len);
+ break;
+#endif
+ case DIGEST_SHA1:
+ SHA1_Update(&(c->SHA1), data, len);
+ break;
+ case DIGEST_SHA256:
+ SHA256_Update(&(c->SHA256), data, len);
+ break;
+ case DIGEST_SHA512:
+ SHA512_Update(&(c->SHA512), data, len);
+ break;
+ }
+}
+
+static char *
+digest_end(DIGEST_CTX *c, char *buf)
+{
+
+ switch (digesttype) {
+#ifdef WITH_MD5
+ case DIGEST_MD5:
+ return (MD5End(&(c->MD5), buf));
+#endif
+#ifdef WITH_RIPEMD160
+ case DIGEST_RIPEMD160:
+ return (RIPEMD160_End(&(c->RIPEMD160), buf));
+#endif
+ case DIGEST_SHA1:
+ return (SHA1_End(&(c->SHA1), buf));
+ case DIGEST_SHA256:
+ return (SHA256_End(&(c->SHA256), buf));
+ case DIGEST_SHA512:
+ return (SHA512_End(&(c->SHA512), buf));
+ default:
+ return (NULL);
+ }
+}
+
+/*
+ * parseid --
+ * parse uid or gid from arg into id, returning non-zero if successful
+ */
+static int
+parseid(const char *name, id_t *id)
+{
+ char *ep;
+ errno = 0;
+ *id = (id_t)strtoul(name, &ep, 10);
+ if (errno || *ep != '\0')
+ return (0);
+ return (1);
+}
+
+/*
+ * quiet_mktemp --
+ * mktemp implementation used mkstemp to avoid mktemp warnings. We
+ * really do need mktemp semantics here as we will be creating a link.
+ */
+static char *
+quiet_mktemp(char *template)
+{
+ int fd;
+
+ if ((fd = mkstemp(template)) == -1)
+ return (NULL);
+ close (fd);
+ if (unlink(template) == -1)
+ err(EX_OSERR, "unlink %s", template);
+ return (template);
+}
+
+/*
+ * do_link --
+ * make a hard link, obeying dorename if set
+ * return -1 on failure
+ */
+static int
+do_link(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
+{
+ char tmpl[MAXPATHLEN];
+ int ret;
+
+ if (target_sb != NULL) {
+ (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
+ /* This usage is safe. */
+ if (quiet_mktemp(tmpl) == NULL)
+ err(EX_OSERR, "%s: mktemp", tmpl);
+ ret = link(from_name, tmpl);
+ if (ret == 0) {
+ if (target_sb->st_mode & S_IFDIR && rmdir(to_name) ==
+ -1) {
+ unlink(tmpl);
+ err(EX_OSERR, "%s", to_name);
+ }
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ if (target_sb->st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, target_sb->st_flags &
+ ~NOCHANGEBITS);
+#endif
+ if (verbose)
+ printf("install: link %s -> %s\n",
+ from_name, to_name);
+ ret = rename(tmpl, to_name);
+ /*
+ * If rename has posix semantics, then the temporary
+ * file may still exist when from_name and to_name point
+ * to the same file, so unlink it unconditionally.
+ */
+ (void)unlink(tmpl);
+ }
+ return (ret);
+ } else {
+ if (verbose)
+ printf("install: link %s -> %s\n",
+ from_name, to_name);
+ return (link(from_name, to_name));
+ }
+}
+
+/*
+ * do_symlink --
+ * Make a symbolic link, obeying dorename if set. Exit on failure.
+ */
+static void
+do_symlink(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
+{
+ char tmpl[MAXPATHLEN];
+
+ if (target_sb != NULL) {
+ (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
+ /* This usage is safe. */
+ if (quiet_mktemp(tmpl) == NULL)
+ err(EX_OSERR, "%s: mktemp", tmpl);
+
+ if (symlink(from_name, tmpl) == -1)
+ err(EX_OSERR, "symlink %s -> %s", from_name, tmpl);
+
+ if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == -1) {
+ (void)unlink(tmpl);
+ err(EX_OSERR, "%s", to_name);
+ }
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ if (target_sb->st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, target_sb->st_flags &
+ ~NOCHANGEBITS);
+#endif
+ if (verbose)
+ printf("install: symlink %s -> %s\n",
+ from_name, to_name);
+ if (rename(tmpl, to_name) == -1) {
+ /* Remove temporary link before exiting. */
+ (void)unlink(tmpl);
+ err(EX_OSERR, "%s: rename", to_name);
+ }
+ } else {
+ if (verbose)
+ printf("install: symlink %s -> %s\n",
+ from_name, to_name);
+ if (symlink(from_name, to_name) == -1)
+ err(EX_OSERR, "symlink %s -> %s", from_name, to_name);
+ }
+}
+
+/*
+ * makelink --
+ * make a link from source to destination
+ */
+static void
+makelink(const char *from_name, const char *to_name,
+ const struct stat *target_sb)
+{
+ char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
+ char *to_name_copy, *d, *ld, *ls, *s;
+ const char *base, *dir;
+ struct stat to_sb;
+
+ /* Try hard links first. */
+ if (dolink & (LN_HARD|LN_MIXED)) {
+ if (do_link(from_name, to_name, target_sb) == -1) {
+ if ((dolink & LN_HARD) || errno != EXDEV)
+ err(EX_OSERR, "link %s -> %s", from_name, to_name);
+ } else {
+ if (stat(to_name, &to_sb))
+ err(EX_OSERR, "%s: stat", to_name);
+ if (S_ISREG(to_sb.st_mode)) {
+ /*
+ * XXX: hard links to anything other than
+ * plain files are not metalogged
+ */
+ int omode;
+ const char *oowner, *ogroup;
+ char *offlags;
+ char *dres;
+
+ /*
+ * XXX: use underlying perms, unless
+ * overridden on command line.
+ */
+ omode = mode;
+ if (!haveopt_m)
+ mode = (to_sb.st_mode & 0777);
+ oowner = owner;
+ if (!haveopt_o)
+ owner = NULL;
+ ogroup = group;
+ if (!haveopt_g)
+ group = NULL;
+ offlags = fflags;
+ if (!haveopt_f)
+ fflags = NULL;
+ dres = digest_file(from_name);
+ metadata_log(to_name, "file", NULL, NULL,
+ dres, to_sb.st_size);
+ free(dres);
+ mode = omode;
+ owner = oowner;
+ group = ogroup;
+ fflags = offlags;
+ }
+ return;
+ }
+ }
+
+ /* Symbolic links. */
+ if (dolink & LN_ABSOLUTE) {
+ /* Convert source path to absolute. */
+ if (realpath(from_name, src) == NULL)
+ err(EX_OSERR, "%s: realpath", from_name);
+ do_symlink(src, to_name, target_sb);
+ /* XXX: src may point outside of destdir */
+ metadata_log(to_name, "link", NULL, src, NULL, 0);
+ return;
+ }
+
+ if (dolink & LN_RELATIVE) {
+ if (*from_name != '/') {
+ /* this is already a relative link */
+ do_symlink(from_name, to_name, target_sb);
+ /* XXX: from_name may point outside of destdir. */
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0);
+ return;
+ }
+
+ /* Resolve pathnames. */
+ if (realpath(from_name, src) == NULL)
+ err(EX_OSERR, "%s: realpath", from_name);
+
+ /*
+ * The last component of to_name may be a symlink,
+ * so use realpath to resolve only the directory.
+ */
+ to_name_copy = strdup(to_name);
+ if (to_name_copy == NULL)
+ err(EX_OSERR, "%s: strdup", to_name);
+ base = basename(to_name_copy);
+ if (base == to_name_copy) {
+ /* destination is a file in cwd */
+ (void)strlcpy(dst, "./", sizeof(dst));
+ } else if (base == to_name_copy + 1) {
+ /* destination is a file in the root */
+ (void)strlcpy(dst, "/", sizeof(dst));
+ } else {
+ /* all other cases: safe to call dirname() */
+ dir = dirname(to_name_copy);
+ if (realpath(dir, dst) == NULL)
+ err(EX_OSERR, "%s: realpath", dir);
+ if (strcmp(dst, "/") != 0 &&
+ strlcat(dst, "/", sizeof(dst)) >= sizeof(dst))
+ errx(1, "resolved pathname too long");
+ }
+ if (strlcat(dst, base, sizeof(dst)) >= sizeof(dst))
+ errx(1, "resolved pathname too long");
+ free(to_name_copy);
+
+ /* Trim common path components. */
+ ls = ld = NULL;
+ for (s = src, d = dst; *s == *d; ls = s, ld = d, s++, d++)
+ continue;
+ /*
+ * If we didn't end after a directory separator, then we've
+ * falsely matched the last component. For example, if one
+ * invoked install -lrs /lib/foo.so /libexec/ then the source
+ * would terminate just after the separator while the
+ * destination would terminate in the middle of 'libexec',
+ * leading to a full directory getting falsely eaten.
+ */
+ if ((ls != NULL && *ls != '/') || (ld != NULL && *ld != '/'))
+ s--, d--;
+ while (*s != '/')
+ s--, d--;
+
+ /* Count the number of directories we need to backtrack. */
+ for (++d, lnk[0] = '\0'; *d; d++)
+ if (*d == '/')
+ (void)strlcat(lnk, "../", sizeof(lnk));
+
+ (void)strlcat(lnk, ++s, sizeof(lnk));
+
+ do_symlink(lnk, to_name, target_sb);
+ /* XXX: Link may point outside of destdir. */
+ metadata_log(to_name, "link", NULL, lnk, NULL, 0);
+ return;
+ }
+
+ /*
+ * If absolute or relative was not specified, try the names the
+ * user provided.
+ */
+ do_symlink(from_name, to_name, target_sb);
+ /* XXX: from_name may point outside of destdir. */
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0);
+}
+
+/*
+ * install --
+ * build a path name and install the file
+ */
+static void
+install(const char *from_name, const char *to_name, u_long fset, u_int flags)
+{
+ struct stat from_sb, temp_sb, to_sb;
+ struct timespec tsb[2];
+ int devnull, files_match, from_fd, serrno, stripped, target;
+ int temp_fd, to_fd;
+ char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
+ char *digestresult;
+
+ digestresult = NULL;
+ files_match = stripped = 0;
+ from_fd = -1;
+ to_fd = -1;
+
+ /* If try to install NULL file to a directory, fails. */
+ if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
+ if (!dolink) {
+ if (stat(from_name, &from_sb))
+ err(EX_OSERR, "%s", from_name);
+ if (!S_ISREG(from_sb.st_mode))
+ errc(EX_OSERR, EFTYPE, "%s", from_name);
+ }
+ /* Build the target path. */
+ if (flags & DIRECTORY) {
+ (void)snprintf(pathbuf, sizeof(pathbuf), "%s%s%s",
+ to_name,
+ to_name[strlen(to_name) - 1] == '/' ? "" : "/",
+ (p = strrchr(from_name, '/')) ? ++p : from_name);
+ to_name = pathbuf;
+ }
+ devnull = 0;
+ } else {
+ devnull = 1;
+ }
+ if (*to_name == '\0')
+ errx(EX_USAGE, "destination cannot be an empty string");
+
+ target = (lstat(to_name, &to_sb) == 0);
+
+ if (dolink) {
+ makelink(from_name, to_name, target ? &to_sb : NULL);
+ return;
+ }
+
+ if (target && !S_ISREG(to_sb.st_mode) && !S_ISLNK(to_sb.st_mode))
+ errc(EX_CANTCREAT, EFTYPE, "%s", to_name);
+
+ if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0)
+ err(EX_OSERR, "%s", from_name);
+
+ /* If we don't strip, we can compare first. */
+ if (docompare && !dostrip && target && S_ISREG(to_sb.st_mode)) {
+ if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
+ err(EX_OSERR, "%s", to_name);
+ if (devnull)
+ files_match = to_sb.st_size == 0;
+ else
+ files_match = !(compare(from_fd, from_name,
+ (size_t)from_sb.st_size, to_fd,
+ to_name, (size_t)to_sb.st_size, &digestresult));
+
+ /* Close "to" file unless we match. */
+ if (!files_match)
+ (void)close(to_fd);
+ }
+
+ if (!files_match) {
+ to_fd = create_tempfile(to_name, tempfile,
+ sizeof(tempfile));
+ if (to_fd < 0)
+ err(EX_OSERR, "%s", dirname(tempfile));
+ if (!devnull) {
+ if (dostrip) {
+ stripped = strip(tempfile, to_fd, from_name,
+ &digestresult);
+ }
+ if (!stripped) {
+ digestresult = copy(from_fd, from_name, to_fd,
+ tempfile, from_sb.st_size);
+ }
+ }
+ }
+
+ if (dostrip) {
+ if (!stripped)
+ (void)strip(tempfile, to_fd, NULL, &digestresult);
+
+ /*
+ * Re-open our fd on the target, in case
+ * we did not strip in-place.
+ */
+ close(to_fd);
+ to_fd = open(tempfile, O_RDONLY, 0);
+ if (to_fd < 0)
+ err(EX_OSERR, "stripping %s", to_name);
+ }
+
+ /*
+ * Compare the stripped temp file with the target.
+ */
+ if (docompare && dostrip && target && S_ISREG(to_sb.st_mode)) {
+ temp_fd = to_fd;
+
+ /* Re-open to_fd using the real target name. */
+ if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
+ err(EX_OSERR, "%s", to_name);
+
+ if (fstat(temp_fd, &temp_sb)) {
+ serrno = errno;
+ (void)unlink(tempfile);
+ errno = serrno;
+ err(EX_OSERR, "%s", tempfile);
+ }
+
+ if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
+ to_name, (size_t)to_sb.st_size, &digestresult)
+ == 0) {
+ /*
+ * If target has more than one link we need to
+ * replace it in order to snap the extra links.
+ * Need to preserve target file times, though.
+ */
+ if (to_sb.st_nlink != 1) {
+ tsb[0] = to_sb.st_atim;
+ tsb[1] = to_sb.st_mtim;
+ (void)utimensat(AT_FDCWD, tempfile, tsb, 0);
+ } else {
+ files_match = 1;
+ (void)unlink(tempfile);
+ }
+ (void) close(temp_fd);
+ }
+ } else if (dostrip)
+ digestresult = digest_file(tempfile);
+
+ /*
+ * Move the new file into place if the files are different (or
+ * just not compared).
+ */
+ if (!files_match) {
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ /* Try to turn off the immutable bits. */
+ if (to_sb.st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS);
+#endif
+ if (target && dobackup) {
+ if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,
+ suffix) != strlen(to_name) + strlen(suffix)) {
+ unlink(tempfile);
+ errx(EX_OSERR, "%s: backup filename too long",
+ to_name);
+ }
+ if (verbose)
+ (void)printf("install: %s -> %s\n", to_name, backup);
+ if (unlink(backup) < 0 && errno != ENOENT) {
+ serrno = errno;
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ if (to_sb.st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, to_sb.st_flags);
+#endif
+ unlink(tempfile);
+ errno = serrno;
+ err(EX_OSERR, "unlink: %s", backup);
+ }
+ if (link(to_name, backup) < 0) {
+ serrno = errno;
+ unlink(tempfile);
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ if (to_sb.st_flags & NOCHANGEBITS)
+ (void)chflags(to_name, to_sb.st_flags);
+#endif
+ errno = serrno;
+ err(EX_OSERR, "link: %s to %s", to_name,
+ backup);
+ }
+ }
+ if (verbose)
+ (void)printf("install: %s -> %s\n", from_name, to_name);
+ if (rename(tempfile, to_name) < 0) {
+ serrno = errno;
+ unlink(tempfile);
+ errno = serrno;
+ err(EX_OSERR, "rename: %s to %s",
+ tempfile, to_name);
+ }
+
+ /* Re-open to_fd so we aren't hosed by the rename(2). */
+ (void) close(to_fd);
+ if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
+ err(EX_OSERR, "%s", to_name);
+ }
+
+ /*
+ * Preserve the timestamp of the source file if necessary.
+ */
+ if (dopreserve && !files_match && !devnull) {
+ tsb[0] = from_sb.st_atim;
+ tsb[1] = from_sb.st_mtim;
+ (void)utimensat(AT_FDCWD, to_name, tsb, 0);
+ }
+
+ if (fstat(to_fd, &to_sb) == -1) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s", to_name);
+ }
+
+ /*
+ * Set owner, group, mode for target; do the chown first,
+ * chown may lose the setuid bits.
+ */
+ if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+ (uid != (uid_t)-1 && uid != to_sb.st_uid) ||
+ (mode != (to_sb.st_mode & ALLPERMS)))) {
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ /* Try to turn off the immutable bits. */
+ if (to_sb.st_flags & NOCHANGEBITS)
+ (void)fchflags(to_fd, to_sb.st_flags & ~NOCHANGEBITS);
+#endif
+ }
+
+ if (!dounpriv && ((gid != (gid_t)-1 && gid != to_sb.st_gid) ||
+ (uid != (uid_t)-1 && uid != to_sb.st_uid))) {
+ if (fchown(to_fd, uid, gid) == -1) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR,"%s: chown/chgrp", to_name);
+ }
+ }
+ if (mode != (to_sb.st_mode & ALLPERMS)) {
+ if (fchmod(to_fd,
+ dounpriv ? mode & (S_IRWXU|S_IRWXG|S_IRWXO) : mode)) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s: chmod", to_name);
+ }
+ }
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ /*
+ * If provided a set of flags, set them, otherwise, preserve the
+ * flags, except for the dump flag.
+ * NFS does not support flags. Ignore EOPNOTSUPP flags if we're just
+ * trying to turn off UF_NODUMP. If we're trying to set real flags,
+ * then warn if the fs doesn't support it, otherwise fail.
+ */
+ if (!dounpriv && !devnull && (flags & SETFLAGS ||
+ (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) &&
+ fchflags(to_fd,
+ flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
+ if (flags & SETFLAGS) {
+ if (errno == EOPNOTSUPP)
+ warn("%s: chflags", to_name);
+ else {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s: chflags", to_name);
+ }
+ }
+ }
+#endif
+
+ (void)close(to_fd);
+ if (!devnull)
+ (void)close(from_fd);
+
+ metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size);
+ free(digestresult);
+}
+
+/*
+ * compare --
+ * Compare two files; non-zero means files differ.
+ * Compute digest and return its address in *dresp
+ * unless it points to pre-computed digest.
+ */
+static int
+compare(int from_fd, const char *from_name __unused, size_t from_len,
+ int to_fd, const char *to_name __unused, size_t to_len,
+ char **dresp)
+{
+ int rv;
+ int do_digest;
+ DIGEST_CTX ctx;
+
+ if (from_len != to_len)
+ return 1;
+
+ do_digest = (digesttype != DIGEST_NONE && dresp != NULL &&
+ *dresp == NULL);
+ if (from_len <= MAX_CMP_SIZE) {
+ static char *buf, *buf1, *buf2;
+ static size_t bufsize;
+ int n1, n2;
+
+ if (do_digest)
+ digest_init(&ctx);
+
+ if (buf == NULL) {
+ /*
+ * Note that buf and bufsize are static. If
+ * malloc() fails, it will fail at the start
+ * and not copy only some files.
+ */
+ if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
+ bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+ else
+ bufsize = BUFSIZE_SMALL;
+ buf = malloc(bufsize * 2);
+ if (buf == NULL)
+ err(1, "Not enough memory");
+ buf1 = buf;
+ buf2 = buf + bufsize;
+ }
+ rv = 0;
+ lseek(from_fd, 0, SEEK_SET);
+ lseek(to_fd, 0, SEEK_SET);
+ while (rv == 0) {
+ n1 = read(from_fd, buf1, bufsize);
+ if (n1 == 0)
+ break; /* EOF */
+ else if (n1 > 0) {
+ n2 = read(to_fd, buf2, n1);
+ if (n2 == n1)
+ rv = memcmp(buf1, buf2, n1);
+ else
+ rv = 1; /* out of sync */
+ } else
+ rv = 1; /* read failure */
+ if (do_digest)
+ digest_update(&ctx, buf1, n1);
+ }
+ lseek(from_fd, 0, SEEK_SET);
+ lseek(to_fd, 0, SEEK_SET);
+ } else {
+ rv = 1; /* don't bother in this case */
+ }
+
+ if (do_digest) {
+ if (rv == 0)
+ *dresp = digest_end(&ctx, NULL);
+ else
+ (void)digest_end(&ctx, NULL);
+ }
+
+ return rv;
+}
+
+/*
+ * create_tempfile --
+ * create a temporary file based on path and open it
+ */
+static int
+create_tempfile(const char *path, char *temp, size_t tsize)
+{
+ char *p;
+
+ (void)strncpy(temp, path, tsize);
+ temp[tsize - 1] = '\0';
+ if ((p = strrchr(temp, '/')) != NULL)
+ p++;
+ else
+ p = temp;
+ (void)strncpy(p, "INS@XXXXXX", &temp[tsize - 1] - p);
+ temp[tsize - 1] = '\0';
+ return (mkstemp(temp));
+}
+
+/*
+ * copy --
+ * copy from one file to another
+ */
+static char *
+copy(int from_fd, const char *from_name, int to_fd, const char *to_name,
+ off_t size)
+{
+ static char *buf = NULL;
+ static size_t bufsize;
+ int nr, nw;
+ int serrno;
+#ifndef BOOTSTRAP_XINSTALL
+ ssize_t ret;
+#endif
+ DIGEST_CTX ctx;
+
+ /* Rewind file descriptors. */
+ if (lseek(from_fd, 0, SEEK_SET) < 0)
+ err(EX_OSERR, "lseek: %s", from_name);
+ if (lseek(to_fd, 0, SEEK_SET) < 0)
+ err(EX_OSERR, "lseek: %s", to_name);
+
+#ifndef BOOTSTRAP_XINSTALL
+ /* Try copy_file_range() if no digest is requested */
+ if (digesttype == DIGEST_NONE) {
+ do {
+ ret = copy_file_range(from_fd, NULL, to_fd, NULL,
+ (size_t)size, 0);
+ } while (ret > 0);
+ if (ret == 0)
+ goto done;
+ if (errno != EINVAL) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s", to_name);
+ }
+ /* Fall back */
+ }
+#endif
+ digest_init(&ctx);
+
+ if (buf == NULL) {
+ /*
+ * Note that buf and bufsize are static. If
+ * malloc() fails, it will fail at the start
+ * and not copy only some files.
+ */
+ if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
+ bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+ else
+ bufsize = BUFSIZE_SMALL;
+ buf = malloc(bufsize);
+ if (buf == NULL)
+ err(1, "Not enough memory");
+ }
+ while ((nr = read(from_fd, buf, bufsize)) > 0) {
+ if ((nw = write(to_fd, buf, nr)) != nr) {
+ serrno = errno;
+ (void)unlink(to_name);
+ if (nw >= 0) {
+ errx(EX_OSERR,
+ "short write to %s: %jd bytes written, "
+ "%jd bytes asked to write",
+ to_name, (uintmax_t)nw,
+ (uintmax_t)size);
+ } else {
+ errno = serrno;
+ err(EX_OSERR, "%s", to_name);
+ }
+ }
+ digest_update(&ctx, buf, nr);
+ }
+ if (nr != 0) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s", from_name);
+ }
+#ifndef BOOTSTRAP_XINSTALL
+done:
+#endif
+ if (safecopy && fsync(to_fd) == -1) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "fsync failed for %s", to_name);
+ }
+ return (digest_end(&ctx, NULL));
+}
+
+/*
+ * strip --
+ * Use strip(1) to strip the target file.
+ * Just invoke strip(1) on to_name if from_name is NULL, else try
+ * to run "strip -o to_name from_name" and return 0 on failure.
+ * Return 1 on success and assign result of digest_file(to_name)
+ * to *dresp.
+ */
+static int
+strip(const char *to_name, int to_fd, const char *from_name, char **dresp)
+{
+ const char *stripbin;
+ const char *args[5];
+ char *prefixed_from_name;
+ pid_t pid;
+ int error, serrno, status;
+
+ prefixed_from_name = NULL;
+ stripbin = getenv("STRIPBIN");
+ if (stripbin == NULL)
+ stripbin = "strip";
+ args[0] = stripbin;
+ if (from_name == NULL) {
+ args[1] = to_name;
+ args[2] = NULL;
+ } else {
+ args[1] = "-o";
+ args[2] = to_name;
+
+ /* Prepend './' if from_name begins with '-' */
+ if (from_name[0] == '-') {
+ if (asprintf(&prefixed_from_name, "./%s", from_name) == -1)
+ return (0);
+ args[3] = prefixed_from_name;
+ } else {
+ args[3] = from_name;
+ }
+ args[4] = NULL;
+ }
+ error = posix_spawnp(&pid, stripbin, NULL, NULL,
+ __DECONST(char **, args), environ);
+ if (error != 0) {
+ (void)unlink(to_name);
+ errc(error == EAGAIN || error == EPROCLIM || error == ENOMEM ?
+ EX_TEMPFAIL : EX_OSERR, error, "spawn %s", stripbin);
+ }
+ free(prefixed_from_name);
+ if (waitpid(pid, &status, 0) == -1) {
+ error = errno;
+ (void)unlink(to_name);
+ errc(EX_SOFTWARE, error, "wait");
+ /* NOTREACHED */
+ }
+ if (status != 0) {
+ if (from_name != NULL)
+ return (0);
+ (void)unlink(to_name);
+ errx(EX_SOFTWARE, "strip command %s failed on %s",
+ stripbin, to_name);
+ }
+ if (from_name != NULL && safecopy && fsync(to_fd) == -1) {
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "fsync failed for %s", to_name);
+ }
+ if (dresp != NULL)
+ *dresp = digest_file(to_name);
+ return (1);
+}
+
+/*
+ * install_dir --
+ * build directory hierarchy
+ */
+static void
+install_dir(char *path)
+{
+ char *p;
+ struct stat sb;
+ int ch, tried_mkdir;
+
+ for (p = path;; ++p)
+ if (!*p || (p != path && *p == '/')) {
+ tried_mkdir = 0;
+ ch = *p;
+ *p = '\0';
+again:
+ if (stat(path, &sb) != 0) {
+ if (errno != ENOENT || tried_mkdir)
+ err(EX_OSERR, "stat %s", path);
+ if (mkdir(path, 0755) < 0) {
+ tried_mkdir = 1;
+ if (errno == EEXIST)
+ goto again;
+ err(EX_OSERR, "mkdir %s", path);
+ }
+ if (verbose)
+ (void)printf("install: mkdir %s\n",
+ path);
+ } else if (!S_ISDIR(sb.st_mode))
+ errx(EX_OSERR, "%s exists but is not a directory", path);
+ if (!(*p = ch))
+ break;
+ }
+
+ if (!dounpriv) {
+ if ((gid != (gid_t)-1 || uid != (uid_t)-1) &&
+ chown(path, uid, gid))
+ warn("chown %u:%u %s", uid, gid, path);
+ /* XXXBED: should we do the chmod in the dounpriv case? */
+ if (chmod(path, mode))
+ warn("chmod %o %s", mode, path);
+ }
+ metadata_log(path, "dir", NULL, NULL, NULL, 0);
+}
+
+/*
+ * metadata_log --
+ * if metafp is not NULL, output mtree(8) full path name and settings to
+ * metafp, to allow permissions to be set correctly by other tools,
+ * or to allow integrity checks to be performed.
+ */
+static void
+metadata_log(const char *path, const char *type, struct timespec *ts,
+ const char *slink, const char *digestresult, off_t size)
+{
+ static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
+ const char *p;
+ char *buf;
+ size_t buflen, destlen;
+ struct flock metalog_lock;
+
+ if (!metafp)
+ return;
+ /* Buffer for strsnvis(3), used for both path and slink. */
+ buflen = strlen(path);
+ if (slink && strlen(slink) > buflen)
+ buflen = strlen(slink);
+ buflen = 4 * buflen + 1;
+ if ((buf = malloc(buflen)) == NULL) {
+ warn(NULL);
+ return;
+ }
+
+ /* Lock log file. */
+ metalog_lock.l_start = 0;
+ metalog_lock.l_len = 0;
+ metalog_lock.l_whence = SEEK_SET;
+ metalog_lock.l_type = F_WRLCK;
+ if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1) {
+ warn("can't lock %s", metafile);
+ free(buf);
+ return;
+ }
+
+ /* Remove destdir. */
+ p = path;
+ if (destdir) {
+ destlen = strlen(destdir);
+ if (strncmp(p, destdir, destlen) == 0 &&
+ (p[destlen] == '/' || p[destlen] == '\0'))
+ p += destlen;
+ }
+ while (*p && *p == '/')
+ p++;
+ strsnvis(buf, buflen, p, VIS_OCTAL, extra);
+ p = buf;
+ /* Print details. */
+ fprintf(metafp, ".%s%s type=%s", *p ? "/" : "", p, type);
+ if (owner) {
+ id_t id;
+
+ if (parseid(owner, &id))
+ fprintf(metafp, " uid=%jd", (intmax_t)id);
+ else
+ fprintf(metafp, " uname=%s", owner);
+ }
+ if (group) {
+ id_t id;
+
+ if (parseid(group, &id))
+ fprintf(metafp, " gid=%jd", (intmax_t)id);
+ else
+ fprintf(metafp, " gname=%s", group);
+ }
+ fprintf(metafp, " mode=%#o", mode);
+ if (slink) {
+ strsnvis(buf, buflen, slink, VIS_CSTYLE, extra);
+ fprintf(metafp, " link=%s", buf);
+ }
+ if (*type == 'f') /* type=file */
+ fprintf(metafp, " size=%lld", (long long)size);
+ if (ts != NULL && dopreserve)
+ fprintf(metafp, " time=%lld.%09ld",
+ (long long)ts[1].tv_sec, ts[1].tv_nsec);
+ if (digestresult && digest)
+ fprintf(metafp, " %s=%s", digest, digestresult);
+ if (fflags)
+ fprintf(metafp, " flags=%s", fflags);
+ if (tags)
+ fprintf(metafp, " tags=%s", tags);
+ fputc('\n', metafp);
+ /* Flush line. */
+ fflush(metafp);
+
+ /* Unlock log file. */
+ metalog_lock.l_type = F_UNLCK;
+ if (fcntl(fileno(metafp), F_SETLKW, &metalog_lock) == -1)
+ warn("can't unlock %s", metafile);
+ free(buf);
+}
+
+/*
+ * usage --
+ * print a usage message and die
+ */
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+"usage: install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" [-B suffix] [-l linkflags] [-N dbdir]\n"
+" file1 file2\n"
+" install [-bCcpSsUv] [-f flags] [-g group] [-m mode] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" [-B suffix] [-l linkflags] [-N dbdir]\n"
+" file1 ... fileN directory\n"
+" install -dU [-vU] [-g group] [-m mode] [-N dbdir] [-o owner]\n"
+" [-M log] [-D dest] [-h hash] [-T tags]\n"
+" directory ...\n");
+ exit(EX_USAGE);
+ /* NOTREACHED */
+}
diff --git a/usr.bin/xo/Makefile b/usr.bin/xo/Makefile
new file mode 100644
index 000000000000..82c0940f490f
--- /dev/null
+++ b/usr.bin/xo/Makefile
@@ -0,0 +1,24 @@
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xo
+
+PROG= xo
+MAN= xo.1
+
+# XXX For xoversion.h
+CFLAGS+=-I${LIBXOSRC}/libxo
+
+# XXX For xo_config.h
+CFLAGS+=-I${SRCTOP}/lib/libxo/libxo
+
+LIBADD= xo util
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
+
+CWARNFLAGS+= ${NO_WUNUSED_BUT_SET_VARIABLE}
diff --git a/usr.bin/xo/Makefile.depend b/usr.bin/xo/Makefile.depend
new file mode 100644
index 000000000000..b915f0b12d3b
--- /dev/null
+++ b/usr.bin/xo/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libutil \
+ lib/libxo/libxo \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xo/tests/Makefile b/usr.bin/xo/tests/Makefile
new file mode 100644
index 000000000000..6bb9d9c00292
--- /dev/null
+++ b/usr.bin/xo/tests/Makefile
@@ -0,0 +1,39 @@
+PACKAGE= tests
+
+.include <bsd.own.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH: ${LIBXOSRC}/tests/xo ${LIBXOSRC}/tests/xo/saved
+
+.c.out .o.out:
+
+BINDIR= ${TESTSDIR}
+
+ATF_TESTS_SH+= functional_test
+
+${PACKAGE}FILES+= xo_01.H.err
+${PACKAGE}FILES+= xo_01.H.out
+${PACKAGE}FILES+= xo_01.HIPx.err
+${PACKAGE}FILES+= xo_01.HIPx.out
+${PACKAGE}FILES+= xo_01.HP.err
+${PACKAGE}FILES+= xo_01.HP.out
+${PACKAGE}FILES+= xo_01.J.err
+${PACKAGE}FILES+= xo_01.J.out
+${PACKAGE}FILES+= xo_01.JP.err
+${PACKAGE}FILES+= xo_01.JP.out
+${PACKAGE}FILES+= xo_01.T.err
+${PACKAGE}FILES+= xo_01.T.out
+${PACKAGE}FILES+= xo_01.X.err
+${PACKAGE}FILES+= xo_01.X.out
+${PACKAGE}FILES+= xo_01.XP.err
+${PACKAGE}FILES+= xo_01.XP.out
+
+SCRIPTS+= xo_01
+CLEANFILES+= xo_01
+
+LIBADD+= xo
+
+.include <bsd.test.mk>
+
+.SUFFIXES: .sh
diff --git a/usr.bin/xo/tests/Makefile.depend b/usr.bin/xo/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/xo/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xo/tests/functional_test.sh b/usr.bin/xo/tests/functional_test.sh
new file mode 100755
index 000000000000..74143f40bd2c
--- /dev/null
+++ b/usr.bin/xo/tests/functional_test.sh
@@ -0,0 +1,71 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# 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.
+#
+# 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.
+#
+
+SRCDIR=$(atf_get_srcdir)
+
+check()
+{
+ local tc=${1}; shift
+ local xo_fmt=${1}; shift
+
+ XO=$(atf_config_get usr.bin.xo.test_xo /usr/bin/xo)
+
+ local err_file="${SRCDIR}/${tc}${xo_fmt:+.${xo_fmt}}.err"
+ [ -s "${err_file}" ] && err_flag="-e file:${err_file}"
+ local out_file="${SRCDIR}/${tc}${xo_fmt:+.${xo_fmt}}.out"
+ [ -s "${out_file}" ] && out_flag="-o file:${out_file}"
+
+ atf_check -s exit:0 -e file:${err_file} -o file:${out_file} \
+ env LC_ALL=en_US.UTF-8 \
+ TZ="EST" "${SRCDIR}/${tc}" \
+ "${XO} --libxo:W${xo_fmt}"
+}
+
+add_testcase()
+{
+ local tc=${1}
+ local tc_escaped
+
+ oldIFS=$IFS
+ IFS='.'
+ set -- $tc
+ tc_script=${1}
+ [ $# -eq 3 ] && xo_fmt=${2} # Don't set xo_fmt to `out'
+ IFS=$oldIFS
+ tc_escaped="${tc_script}${xo_fmt:+__${xo_fmt}}"
+
+ atf_test_case ${tc_escaped}
+ eval "${tc_escaped}_body() { check ${tc_script} ${xo_fmt}; }"
+ atf_add_test_case ${tc_escaped}
+}
+
+atf_init_test_cases()
+{
+ for path in $(find -Es "${SRCDIR}" -name '*.out'); do
+ add_testcase ${path##*/}
+ done
+}
diff --git a/usr.bin/xohtml/Makefile b/usr.bin/xohtml/Makefile
new file mode 100644
index 000000000000..7b79280f36b3
--- /dev/null
+++ b/usr.bin/xohtml/Makefile
@@ -0,0 +1,29 @@
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xohtml
+
+SCRIPTS= xohtml.sh
+MAN= xohtml.1
+
+EXTERNAL_FILES = \
+ external/jquery.js \
+ external/jquery.qtip.css \
+ external/jquery.qtip.js
+
+INTERNAL_FILES = \
+ xohtml.js \
+ xohtml.css
+
+FILES= ${INTERNAL_FILES} ${EXTERNAL_FILES}
+FILESDIR= /usr/share/xohtml
+FILESMODE= ${NOBINMODE}
+
+beforeinstall: mkfilesdir
+mkfilesdir:
+ test -d ${DESTDIR}${FILESDIR} \
+ || ${INSTALL} -d -o ${FILESOWN} -g ${FILESGRP} -m 755 ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xohtml/xohtml.sh b/usr.bin/xohtml/xohtml.sh
new file mode 100755
index 000000000000..b020d1517dfb
--- /dev/null
+++ b/usr.bin/xohtml/xohtml.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#!/bin/sh
+#
+# Copyright (c) 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+# Phil Shafer, July 2014
+#
+
+BASE=/usr/share/libxo
+VERSION=1.6.0
+CMD=cat
+DONE=
+WEB=http://juniper.github.io/libxo/${VERSION}/xohtml
+
+do_help () {
+ echo "xohtml: wrap libxo-enabled output in HTML"
+ echo "Usage: xohtml [options] [command [arguments]]"
+ echo "Valid options are:"
+ echo " -b <basepath> | --base <basepath>"
+ echo " -c <command> | --command <command>"
+ echo " -f <output-file> | --file <output-file>"
+ exit 1
+}
+
+while [ -z "$DONE" -a ! -z "$1" ]; do
+ case "$1" in
+ -b|--base)
+ shift;
+ BASE="$1";
+ shift;
+ ;;
+ -c|--command)
+ shift;
+ CMD="$1";
+ shift;
+ ;;
+ -f|--file)
+ shift;
+ FILE="$1";
+ shift;
+ exec > "$FILE";
+ ;;
+ -w|--web)
+ shift;
+ BASE="${WEB}";
+ ;;
+
+ -*)
+ do_help
+ ;;
+ *)
+ DONE=1;
+ XX=$1;
+ shift;
+ CMD="$XX --libxo=html $@"
+ ;;
+ esac
+done
+
+if [ "$CMD" = "cat" -a -t 0 ]; then
+ do_help
+fi
+
+echo '<html>'
+echo '<head>'
+echo '<meta http-equiv="content-type" content="text/html; charset=utf-8"/>'
+echo '<link rel="stylesheet" href="'$BASE'/xohtml.css">'
+echo '<link rel="stylesheet" href="'$BASE'/external/jquery.qtip.css"/>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.qtip.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/xohtml.js"></script>'
+echo '<script>'
+echo '</script>'
+echo '</head>'
+echo '<body>'
+
+$CMD
+
+echo '</body>'
+echo '</html>'
+
+exit 0
diff --git a/usr.bin/xolint/Makefile b/usr.bin/xolint/Makefile
new file mode 100644
index 000000000000..2a35bc946f49
--- /dev/null
+++ b/usr.bin/xolint/Makefile
@@ -0,0 +1,11 @@
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xolint
+
+SCRIPTS= xolint.pl
+MAN= xolint.1
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xopo/Makefile b/usr.bin/xopo/Makefile
new file mode 100644
index 000000000000..6dae6ac233b8
--- /dev/null
+++ b/usr.bin/xopo/Makefile
@@ -0,0 +1,19 @@
+.include <src.opts.mk>
+
+LIBXOSRC= ${SRCTOP}/contrib/libxo
+
+.PATH:
+.PATH: ${LIBXOSRC}/xopo
+
+PROG= xopo
+MAN= xopo.1
+
+# XXX For xoversion.h
+CFLAGS+=-I${LIBXOSRC}/libxo
+
+# XXX For xo_config.h
+CFLAGS+=-I${SRCTOP}/lib/libxo
+
+LIBADD= xo util
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xstr/Makefile b/usr.bin/xstr/Makefile
new file mode 100644
index 000000000000..290d553a4ed6
--- /dev/null
+++ b/usr.bin/xstr/Makefile
@@ -0,0 +1,3 @@
+PROG= xstr
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xstr/Makefile.depend b/usr.bin/xstr/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/xstr/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xstr/pathnames.h b/usr.bin/xstr/pathnames.h
new file mode 100644
index 000000000000..bc75f70df626
--- /dev/null
+++ b/usr.bin/xstr/pathnames.h
@@ -0,0 +1,32 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 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.
+ */
+
+#define _PATH_TMP "/tmp/xstrXXXXXX"
diff --git a/usr.bin/xstr/xstr.1 b/usr.bin/xstr/xstr.1
new file mode 100644
index 000000000000..7319b2b881b5
--- /dev/null
+++ b/usr.bin/xstr/xstr.1
@@ -0,0 +1,160 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd December 30, 1993
+.Dt XSTR 1
+.Os
+.Sh NAME
+.Nm xstr
+.Nd "extract strings from C programs to implement shared strings"
+.Sh SYNOPSIS
+.Nm
+.Op Fl cv
+.Op Fl
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility maintains a file
+.Pa strings
+into which strings in component parts of a large program are hashed.
+These strings are replaced with references to this common area.
+This serves to implement shared constant strings, most useful if they
+are also read-only.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl
+Read from the standard input.
+.It Fl c
+Extract the strings from the C source
+.Ar file
+or the standard input
+.Pq Fl ,
+replacing
+string references by expressions of the form
+.Li (&xstr[number])
+for some
+.Ar number .
+An appropriate declaration of
+.Va xstr
+is prepended to the file.
+The resulting C text is placed in the file
+.Pa x.c ,
+to then be compiled.
+The strings from this file are placed in the
+.Pa strings
+data base if they are not there already.
+Repeated strings and strings which are suffixes of existing strings
+do not cause changes to the data base.
+.It Fl v
+Verbose mode.
+.El
+.Pp
+After all components of a large program have been compiled a file
+.Pa xs.c
+declaring the common
+.Va xstr
+space can be created by a command of the form
+.Pp
+.Dl xstr
+.Pp
+The file
+.Pa xs.c
+should then be compiled and loaded with the rest
+of the program.
+If possible, the array can be made read-only (shared) saving
+space and swap overhead.
+.Pp
+The
+.Nm
+utility can also be used on a single file.
+A command
+.Bd -literal -offset indent
+xstr name
+.Ed
+.Pp
+creates files
+.Pa x.c
+and
+.Pa xs.c
+as before, without using or affecting any
+.Pa strings
+file in the same directory.
+.Pp
+It may be useful to run
+.Nm
+after the C preprocessor if any macro definitions yield strings
+or if there is conditional code which contains strings
+which may not, in fact, be needed.
+An appropriate command sequence for running
+.Nm
+after the C preprocessor is:
+.Pp
+.Bd -literal -offset indent -compact
+cc -E name.c | xstr -c -
+cc -c x.c
+mv x.o name.o
+.Ed
+.Pp
+The
+.Nm
+utility does not touch the file
+.Pa strings
+unless new items are added, thus
+.Xr make 1
+can avoid remaking
+.Pa xs.o
+unless truly necessary.
+.Sh FILES
+.Bl -tag -width ".Pa /tmp/xs*" -compact
+.It Pa strings
+data base of strings
+.It Pa x.c
+massaged C source
+.It Pa xs.c
+C source for definition of array
+.Va xstr
+.It Pa /tmp/xs*
+temporary file when
+.Dq Li "xstr name"
+does not touch
+.Pa strings
+.El
+.Sh SEE ALSO
+.Xr mkstr 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 3.0 .
+.Sh BUGS
+If a string is a suffix of another string in the data base,
+but the shorter string is seen first by
+.Nm
+both strings will be placed in the data base, when just
+placing the longer one there will do.
diff --git a/usr.bin/xstr/xstr.c b/usr.bin/xstr/xstr.c
new file mode 100644
index 000000000000..39acc77333b9
--- /dev/null
+++ b/usr.bin/xstr/xstr.c
@@ -0,0 +1,480 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1980, 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.
+ */
+
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+/*
+ * xstr - extract and hash strings in a C program
+ *
+ * Bill Joy UCB
+ * November, 1978
+ */
+
+#define ignore(a) ((void) a)
+
+static off_t tellpt;
+
+static off_t mesgpt;
+static char cstrings[] = "strings";
+static char *strings = cstrings;
+
+static int cflg;
+static int vflg;
+static int readstd;
+
+static char lastchr(char *);
+
+static int fgetNUL(char *, int, FILE *);
+static int istail(char *, char *);
+static int octdigit(char);
+static int xgetc(FILE *);
+
+static off_t hashit(char *, int);
+static off_t yankstr(char **);
+
+static void usage(void) __dead2;
+
+static void flushsh(void);
+static void found(int, off_t, char *);
+static void inithash(void);
+static void onintr(int);
+static void process(const char *);
+static void prstr(char *);
+static void xsdotc(void);
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int fdesc;
+
+ while ((c = getopt(argc, argv, "-cv")) != -1)
+ switch (c) {
+ case '-':
+ readstd++;
+ break;
+ case 'c':
+ cflg++;
+ break;
+ case 'v':
+ vflg++;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (signal(SIGINT, SIG_IGN) == SIG_DFL)
+ signal(SIGINT, onintr);
+ if (cflg || (argc == 0 && !readstd))
+ inithash();
+ else {
+ strings = strdup(_PATH_TMP);
+ if (strings == NULL)
+ err(1, "strdup() failed");
+ fdesc = mkstemp(strings);
+ if (fdesc == -1)
+ err(1, "Unable to create temporary file");
+ close(fdesc);
+ }
+
+ while (readstd || argc > 0) {
+ if (freopen("x.c", "w", stdout) == NULL)
+ err(1, "x.c");
+ if (!readstd && freopen(argv[0], "r", stdin) == NULL)
+ err(2, "%s", argv[0]);
+ process("x.c");
+ if (readstd == 0)
+ argc--, argv++;
+ else
+ readstd = 0;
+ }
+ flushsh();
+ if (cflg == 0)
+ xsdotc();
+ if (strings[0] == '/')
+ ignore(unlink(strings));
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: xstr [-cv] [-] [file ...]\n");
+ exit (1);
+}
+
+static char linebuf[BUFSIZ];
+
+static void
+process(const char *name)
+{
+ char *cp;
+ int c;
+ int incomm = 0;
+ int ret;
+
+ printf("extern char\txstr[];\n");
+ for (;;) {
+ if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
+ if (ferror(stdin))
+ err(3, "%s", name);
+ break;
+ }
+ if (linebuf[0] == '#') {
+ if (linebuf[1] == ' ' && isdigit(linebuf[2]))
+ printf("#line%s", &linebuf[1]);
+ else
+ printf("%s", linebuf);
+ continue;
+ }
+ for (cp = linebuf; (c = *cp++);) switch (c) {
+
+ case '"':
+ if (incomm)
+ goto def;
+ if ((ret = (int) yankstr(&cp)) == -1)
+ goto out;
+ printf("(&xstr[%d])", ret);
+ break;
+
+ case '\'':
+ if (incomm)
+ goto def;
+ putchar(c);
+ if (*cp)
+ putchar(*cp++);
+ break;
+
+ case '/':
+ if (incomm || *cp != '*')
+ goto def;
+ incomm = 1;
+ cp++;
+ printf("/*");
+ continue;
+
+ case '*':
+ if (incomm && *cp == '/') {
+ incomm = 0;
+ cp++;
+ printf("*/");
+ continue;
+ }
+ goto def;
+
+def:
+ default:
+ putchar(c);
+ break;
+ }
+ }
+out:
+ if (ferror(stdout))
+ warn("x.c"), onintr(0);
+}
+
+static off_t
+yankstr(char **cpp)
+{
+ char *cp = *cpp;
+ int c, ch;
+ char dbuf[BUFSIZ];
+ char *dp = dbuf;
+ char *tp;
+ static char tmp[] = "b\bt\tr\rn\nf\f\\\\\"\"";
+
+ while ((c = *cp++)) {
+ if (dp == dbuf + sizeof(dbuf) - 3)
+ errx(1, "message too long");
+ switch (c) {
+
+ case '"':
+ cp++;
+ goto out;
+
+ case '\\':
+ c = *cp++;
+ if (c == 0)
+ break;
+ if (c == '\n') {
+ if (fgets(linebuf, sizeof linebuf, stdin)
+ == NULL) {
+ if (ferror(stdin))
+ err(3, "x.c");
+ return(-1);
+ }
+ cp = linebuf;
+ continue;
+ }
+ for (tp = tmp; (ch = *tp++); tp++)
+ if (c == ch) {
+ c = *tp;
+ goto gotc;
+ }
+ if (!octdigit(c)) {
+ *dp++ = '\\';
+ break;
+ }
+ c -= '0';
+ if (!octdigit(*cp))
+ break;
+ c <<= 3, c += *cp++ - '0';
+ if (!octdigit(*cp))
+ break;
+ c <<= 3, c += *cp++ - '0';
+ break;
+ }
+gotc:
+ *dp++ = c;
+ }
+out:
+ *cpp = --cp;
+ *dp = 0;
+ return (hashit(dbuf, 1));
+}
+
+static int
+octdigit(char c)
+{
+ return (isdigit(c) && c != '8' && c != '9');
+}
+
+static void
+inithash(void)
+{
+ char buf[BUFSIZ];
+ FILE *mesgread = fopen(strings, "r");
+
+ if (mesgread == NULL)
+ return;
+ for (;;) {
+ mesgpt = tellpt;
+ if (fgetNUL(buf, sizeof buf, mesgread) == 0)
+ break;
+ ignore(hashit(buf, 0));
+ }
+ ignore(fclose(mesgread));
+}
+
+static int
+fgetNUL(char *obuf, int rmdr, FILE *file)
+{
+ int c;
+ char *buf = obuf;
+
+ while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
+ *buf++ = c;
+ *buf++ = 0;
+ return ((feof(file) || ferror(file)) ? 0 : 1);
+}
+
+static int
+xgetc(FILE *file)
+{
+
+ tellpt++;
+ return (getc(file));
+}
+
+#define BUCKETS 128
+
+static struct hash {
+ off_t hpt;
+ char *hstr;
+ struct hash *hnext;
+ short hnew;
+} bucket[BUCKETS];
+
+static off_t
+hashit(char *str, int new)
+{
+ int i;
+ struct hash *hp, *hp0;
+
+ hp = hp0 = &bucket[lastchr(str) & 0177];
+ while (hp->hnext) {
+ hp = hp->hnext;
+ i = istail(str, hp->hstr);
+ if (i >= 0)
+ return (hp->hpt + i);
+ }
+ if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL)
+ errx(8, "calloc");
+ hp->hpt = mesgpt;
+ if (!(hp->hstr = strdup(str)))
+ err(1, NULL);
+ mesgpt += strlen(hp->hstr) + 1;
+ hp->hnext = hp0->hnext;
+ hp->hnew = new;
+ hp0->hnext = hp;
+ return (hp->hpt);
+}
+
+static void
+flushsh(void)
+{
+ int i;
+ struct hash *hp;
+ FILE *mesgwrit;
+ int old = 0, new = 0;
+
+ for (i = 0; i < BUCKETS; i++)
+ for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
+ if (hp->hnew)
+ new++;
+ else
+ old++;
+ if (new == 0 && old != 0)
+ return;
+ mesgwrit = fopen(strings, old ? "r+" : "w");
+ if (mesgwrit == NULL)
+ err(4, "%s", strings);
+ for (i = 0; i < BUCKETS; i++)
+ for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
+ found(hp->hnew, hp->hpt, hp->hstr);
+ if (hp->hnew) {
+ fseek(mesgwrit, hp->hpt, 0);
+ ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
+ if (ferror(mesgwrit))
+ err(4, "%s", strings);
+ }
+ }
+ if (fclose(mesgwrit) == EOF)
+ err(4, "%s", strings);
+}
+
+static void
+found(int new, off_t off, char *str)
+{
+ if (vflg == 0)
+ return;
+ if (!new)
+ fprintf(stderr, "found at %d:", (int) off);
+ else
+ fprintf(stderr, "new at %d:", (int) off);
+ prstr(str);
+ fprintf(stderr, "\n");
+}
+
+static void
+prstr(char *cp)
+{
+ int c;
+
+ while ((c = (*cp++ & 0377)))
+ if (c < ' ')
+ fprintf(stderr, "^%c", c + '`');
+ else if (c == 0177)
+ fprintf(stderr, "^?");
+ else if (c > 0200)
+ fprintf(stderr, "\\%03o", c);
+ else
+ fprintf(stderr, "%c", c);
+}
+
+static void
+xsdotc(void)
+{
+ FILE *strf = fopen(strings, "r");
+ FILE *xdotcf;
+
+ if (strf == NULL)
+ err(5, "%s", strings);
+ xdotcf = fopen("xs.c", "w");
+ if (xdotcf == NULL)
+ err(6, "xs.c");
+ fprintf(xdotcf, "char\txstr[] = {\n");
+ for (;;) {
+ int i, c;
+
+ for (i = 0; i < 8; i++) {
+ c = getc(strf);
+ if (ferror(strf)) {
+ warn("%s", strings);
+ onintr(0);
+ }
+ if (feof(strf)) {
+ fprintf(xdotcf, "\n");
+ goto out;
+ }
+ fprintf(xdotcf, "0x%02x,", c);
+ }
+ fprintf(xdotcf, "\n");
+ }
+out:
+ fprintf(xdotcf, "};\n");
+ ignore(fclose(xdotcf));
+ ignore(fclose(strf));
+}
+
+static char
+lastchr(char *cp)
+{
+
+ while (cp[0] && cp[1])
+ cp++;
+ return (*cp);
+}
+
+static int
+istail(char *str, char *of)
+{
+ int d = strlen(of) - strlen(str);
+
+ if (d < 0 || strcmp(&of[d], str) != 0)
+ return (-1);
+ return (d);
+}
+
+static void
+onintr(int dummy __unused)
+{
+
+ ignore(signal(SIGINT, SIG_IGN));
+ if (strings[0] == '/')
+ ignore(unlink(strings));
+ ignore(unlink("x.c"));
+ ignore(unlink("xs.c"));
+ exit(7);
+}
diff --git a/usr.bin/xz/Makefile b/usr.bin/xz/Makefile
new file mode 100644
index 000000000000..f56c6883b90a
--- /dev/null
+++ b/usr.bin/xz/Makefile
@@ -0,0 +1,49 @@
+.include <src.opts.mk>
+
+PROG= xz
+
+LINKS= ${BINDIR}/xz ${BINDIR}/unxz
+LINKS+= ${BINDIR}/xz ${BINDIR}/lzma
+LINKS+= ${BINDIR}/xz ${BINDIR}/unlzma
+LINKS+= ${BINDIR}/xz ${BINDIR}/xzcat
+LINKS+= ${BINDIR}/xz ${BINDIR}/lzcat
+
+MLINKS= xz.1 unxz.1 xz.1 lzma.1 xz.1 unlzma.1 xz.1 xzcat.1 xz.1 lzcat.1
+
+XZDIR= ${SRCTOP}/contrib/xz/src
+LZMALIBDIR= ${SRCTOP}/lib/liblzma
+
+.PATH: ${XZDIR}/xz
+
+SRCS= args.c \
+ coder.c \
+ file_io.c \
+ hardware.c \
+ list.c \
+ main.c \
+ message.c \
+ mytime.c \
+ options.c \
+ sandbox.c \
+ signals.c \
+ suffix.c \
+ util.c
+
+.PATH: ${XZDIR}/common
+
+SRCS+= tuklib_open_stdxxx.c \
+ tuklib_progname.c \
+ tuklib_exit.c \
+ tuklib_cpucores.c \
+ tuklib_mbstr_width.c \
+ tuklib_mbstr_fw.c
+
+WARNS?= 3
+
+CFLAGS+= -DHAVE_CONFIG_H \
+ -I${LZMALIBDIR} \
+ -I${XZDIR}/common
+
+LIBADD= lzma
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xz/Makefile.depend b/usr.bin/xz/Makefile.depend
new file mode 100644
index 000000000000..b6a7bfecc03d
--- /dev/null
+++ b/usr.bin/xz/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/liblzma \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/xzdec/Makefile b/usr.bin/xzdec/Makefile
new file mode 100644
index 000000000000..361315fab8b9
--- /dev/null
+++ b/usr.bin/xzdec/Makefile
@@ -0,0 +1,25 @@
+PROG= xzdec
+
+LINKS= ${BINDIR}/xzdec ${BINDIR}/lzdec
+
+MLINKS= xzdec.1 lzmadec.1
+
+XZDIR= ${SRCTOP}/contrib/xz/src
+LZMALIBDIR= ${SRCTOP}/lib/liblzma
+
+.PATH: ${XZDIR}/xzdec
+
+SRCS= xzdec.c
+
+.PATH: ${XZDIR}/common
+
+SRCS+= tuklib_progname.c \
+ tuklib_exit.c
+
+CFLAGS+= -DHAVE_CONFIG_H \
+ -I${LZMALIBDIR} \
+ -I${XZDIR}/common
+
+LIBADD= lzma
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/xzdec/Makefile.depend b/usr.bin/xzdec/Makefile.depend
new file mode 100644
index 000000000000..b6a7bfecc03d
--- /dev/null
+++ b/usr.bin/xzdec/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/liblzma \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/yacc/Makefile b/usr.bin/yacc/Makefile
new file mode 100644
index 000000000000..42ee10952e06
--- /dev/null
+++ b/usr.bin/yacc/Makefile
@@ -0,0 +1,22 @@
+.include <src.opts.mk>
+
+BYACC_SRC= ${SRCTOP}/contrib/byacc
+.PATH: ${BYACC_SRC}
+
+PROG= yacc
+SRCS= closure.c error.c graph.c lalr.c lr0.c main.c mkpar.c mstring.c output.c \
+ reader.c yaccpar.c symtab.c verbose.c warshall.c
+
+CFLAGS+= -DHAVE_CONFIG_H -I${.CURDIR}
+CFLAGS+= -DMAXTABLE=INT_MAX
+
+YYPATCH!= cat ${BYACC_SRC}/VERSION
+CFLAGS+= -DYYPATCH=${YYPATCH}
+
+LINKS= ${BINDIR}/yacc ${BINDIR}/byacc
+MLINKS= yacc.1 byacc.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/yacc/Makefile.depend b/usr.bin/yacc/Makefile.depend
new file mode 100644
index 000000000000..6ef78fac5cbf
--- /dev/null
+++ b/usr.bin/yacc/Makefile.depend
@@ -0,0 +1,15 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/yacc/Makefile.depend.host b/usr.bin/yacc/Makefile.depend.host
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/yacc/Makefile.depend.host
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/yacc/Makefile.depend.options b/usr.bin/yacc/Makefile.depend.options
new file mode 100644
index 000000000000..4dcc6c412671
--- /dev/null
+++ b/usr.bin/yacc/Makefile.depend.options
@@ -0,0 +1,6 @@
+DIRDEPS_OPTIONS = host_egacy
+
+DIRDEPS.host_egacy.yes = tools/build
+
+.include <dirdeps-options.mk>
+
diff --git a/usr.bin/yacc/config.h b/usr.bin/yacc/config.h
new file mode 100644
index 000000000000..c9a9fe59139b
--- /dev/null
+++ b/usr.bin/yacc/config.h
@@ -0,0 +1,113 @@
+/* config.h. Generated automatically by configure. */
+/* config_h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to noreturn-attribute for gcc */
+#define GCC_NORETURN __attribute__((noreturn))
+
+/* Define to 1 if the compiler supports gcc-like printf attribute. */
+#define GCC_PRINTF 1
+
+/* Define to printf-attribute for gcc */
+#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
+
+/* Define to 1 if the compiler supports gcc-like scanf attribute. */
+#define GCC_SCANF 1
+
+/* Define to sscanf-attribute for gcc */
+#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var)))
+
+/* Define to unused-attribute for gcc */
+#define GCC_UNUSED __attribute__((unused))
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if getopt variables are declared in header */
+#define HAVE_GETOPT_HEADER 1
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the `dbmalloc' library (-ldbmalloc). */
+/* #undef HAVE_LIBDBMALLOC */
+
+/* Define if you have the `dmalloc' library (-ldmalloc). */
+/* #undef HAVE_LIBDMALLOC */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if mkstemp() is available and working. */
+#define HAVE_MKSTEMP 1
+
+/* Define if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if <stdnoreturn.h> header is available and working */
+/* #undef HAVE_STDNORETURN_H */
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to maximum table size (default: 32500) */
+/* #undef MAXTABLE */
+
+/* Define to 1 if filesystem supports mixed-case filenames. */
+#define MIXEDCASE_FILENAMES 1
+
+/* Define to 1 if we must include getopt.h */
+/* #undef NEED_GETOPT_H */
+
+/* Define to 1 if you want to perform memory-leak testing. */
+/* #undef NO_LEAKS */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if C11 _Noreturn keyword is supported */
+/* #undef STDC_NORETURN */
+
+/* Define to the system name. */
+#define SYSTEM_NAME "freebsd14.0"
+
+/* "Define to 1 if you want to use dbmalloc for testing." */
+/* #undef USE_DBMALLOC */
+
+/* "Define to 1 if you want to use dmalloc for testing." */
+/* #undef USE_DMALLOC */
+
+/* "Define to 1 if you want to use valgrind for testing." */
+/* #undef USE_VALGRIND */
+
+/* Define to 1 to enable backtracking extension */
+/* #undef YYBTYACC */
+
+/* Define to 1 if you want to perform memory-leak testing. */
+/* #undef YY_NO_LEAKS */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
diff --git a/usr.bin/yacc/tests/Makefile b/usr.bin/yacc/tests/Makefile
new file mode 100644
index 000000000000..c2832bc06853
--- /dev/null
+++ b/usr.bin/yacc/tests/Makefile
@@ -0,0 +1,375 @@
+.include <bsd.own.mk>
+
+TEST_DIR= ${SRCTOP}/contrib/byacc/test
+
+.PATH: ${TEST_DIR} ${TEST_DIR}/yacc
+
+PLAIN_TESTS_SH= yacc_tests
+# NOTE: due to caveats with how permissions are handled on FreeBSD
+# with root, this must be run as a non-privileged user; otherwise
+# the testcases will fail unexpectedly.
+TEST_METADATA.yacc_tests+= required_user="unprivileged"
+
+SCRIPTS= run_test
+SCRIPTSDIR= ${TESTSDIR}
+
+CLEANFILES= run_test
+
+FILESGROUPS+= FILEStest FILEStest_yacc
+FILEStestPACKAGE=${PACKAGE}
+FILEStest_yaccPACKAGE=${PACKAGE}
+
+FILEStestDIR= ${TESTSDIR}
+
+FILEStest+= calc_code_all.y
+FILEStest+= calc_code_default.y
+FILEStest+= calc_code_imports.y
+FILEStest+= calc_code_provides.y
+FILEStest+= calc_code_requires.y
+FILEStest+= calc_code_top.y
+FILEStest+= calc.y
+FILEStest+= calc1.y
+FILEStest+= calc2.y
+FILEStest+= calc3.y
+FILEStest+= code_calc.y
+FILEStest+= code_debug.y
+FILEStest+= code_error.y
+FILEStest+= empty.y
+FILEStest+= err_syntax1.y
+FILEStest+= err_syntax10.y
+FILEStest+= err_syntax11.y
+FILEStest+= err_syntax12.y
+FILEStest+= err_syntax13.y
+FILEStest+= err_syntax14.y
+FILEStest+= err_syntax15.y
+FILEStest+= err_syntax16.y
+FILEStest+= err_syntax17.y
+FILEStest+= err_syntax18.y
+FILEStest+= err_syntax19.y
+FILEStest+= err_syntax2.y
+FILEStest+= err_syntax20.y
+FILEStest+= err_syntax21.y
+FILEStest+= err_syntax22.y
+FILEStest+= err_syntax23.y
+FILEStest+= err_syntax24.y
+FILEStest+= err_syntax25.y
+FILEStest+= err_syntax26.y
+FILEStest+= err_syntax27.y
+FILEStest+= err_syntax3.y
+FILEStest+= err_syntax4.y
+FILEStest+= err_syntax5.y
+FILEStest+= err_syntax6.y
+FILEStest+= err_syntax7.y
+FILEStest+= err_syntax7a.y
+FILEStest+= err_syntax7b.y
+FILEStest+= err_syntax8.y
+FILEStest+= err_syntax8a.y
+FILEStest+= err_syntax9.y
+FILEStest+= error.y
+FILEStest+= expr.oxout.y
+FILEStest+= grammar.y
+FILEStest+= ok_syntax1.y
+FILEStest+= pure_calc.y
+FILEStest+= pure_error.y
+FILEStest+= quote_calc.y
+FILEStest+= quote_calc2.y
+FILEStest+= quote_calc3.y
+FILEStest+= quote_calc4.y
+FILEStest+= varsyntax_calc1.y
+
+FILEStest_yaccDIR= ${TESTSDIR}/yacc
+
+FILEStest_yacc+= big_b.error
+FILEStest_yacc+= big_b.output
+FILEStest_yacc+= big_l.error
+FILEStest_yacc+= big_l.output
+FILEStest_yacc+= calc_code_all.error
+FILEStest_yacc+= calc_code_all.output
+FILEStest_yacc+= calc_code_all.tab.c
+FILEStest_yacc+= calc_code_all.tab.h
+FILEStest_yacc+= calc_code_default.error
+FILEStest_yacc+= calc_code_default.output
+FILEStest_yacc+= calc_code_default.tab.c
+FILEStest_yacc+= calc_code_default.tab.h
+FILEStest_yacc+= calc_code_imports.error
+FILEStest_yacc+= calc_code_imports.output
+FILEStest_yacc+= calc_code_imports.tab.c
+FILEStest_yacc+= calc_code_imports.tab.h
+FILEStest_yacc+= calc_code_provides.error
+FILEStest_yacc+= calc_code_provides.output
+FILEStest_yacc+= calc_code_provides.tab.c
+FILEStest_yacc+= calc_code_provides.tab.h
+FILEStest_yacc+= calc_code_requires.error
+FILEStest_yacc+= calc_code_requires.output
+FILEStest_yacc+= calc_code_requires.tab.c
+FILEStest_yacc+= calc_code_requires.tab.h
+FILEStest_yacc+= calc_code_top.error
+FILEStest_yacc+= calc_code_top.output
+FILEStest_yacc+= calc_code_top.tab.c
+FILEStest_yacc+= calc_code_top.tab.h
+FILEStest_yacc+= calc.error
+FILEStest_yacc+= calc.output
+FILEStest_yacc+= calc.tab.c
+FILEStest_yacc+= calc.tab.h
+FILEStest_yacc+= calc1.error
+FILEStest_yacc+= calc1.output
+FILEStest_yacc+= calc1.tab.c
+FILEStest_yacc+= calc1.tab.h
+FILEStest_yacc+= calc2.error
+FILEStest_yacc+= calc2.output
+FILEStest_yacc+= calc2.tab.c
+FILEStest_yacc+= calc2.tab.h
+FILEStest_yacc+= calc3.error
+FILEStest_yacc+= calc3.output
+FILEStest_yacc+= calc3.tab.c
+FILEStest_yacc+= calc3.tab.h
+FILEStest_yacc+= code_calc.code.c
+FILEStest_yacc+= code_calc.error
+FILEStest_yacc+= code_calc.output
+FILEStest_yacc+= code_calc.tab.c
+FILEStest_yacc+= code_calc.tab.h
+FILEStest_yacc+= code_error.code.c
+FILEStest_yacc+= code_error.error
+FILEStest_yacc+= code_error.output
+FILEStest_yacc+= code_error.tab.c
+FILEStest_yacc+= code_error.tab.h
+FILEStest_yacc+= defines1.calc.c
+FILEStest_yacc+= defines1.calc.h
+FILEStest_yacc+= defines1.error
+FILEStest_yacc+= defines1.output
+FILEStest_yacc+= defines2.calc.c
+FILEStest_yacc+= defines2.calc.h
+FILEStest_yacc+= defines2.error
+FILEStest_yacc+= defines2.output
+FILEStest_yacc+= defines3.calc.c
+FILEStest_yacc+= defines3.calc.h
+FILEStest_yacc+= defines3.error
+FILEStest_yacc+= defines3.output
+FILEStest_yacc+= empty.error
+FILEStest_yacc+= empty.output
+FILEStest_yacc+= empty.tab.c
+FILEStest_yacc+= empty.tab.h
+FILEStest_yacc+= err_syntax1.error
+FILEStest_yacc+= err_syntax1.output
+FILEStest_yacc+= err_syntax1.tab.c
+FILEStest_yacc+= err_syntax1.tab.h
+FILEStest_yacc+= err_syntax10.error
+FILEStest_yacc+= err_syntax10.output
+FILEStest_yacc+= err_syntax10.tab.c
+FILEStest_yacc+= err_syntax10.tab.h
+FILEStest_yacc+= err_syntax11.error
+FILEStest_yacc+= err_syntax11.output
+FILEStest_yacc+= err_syntax11.tab.c
+FILEStest_yacc+= err_syntax11.tab.h
+FILEStest_yacc+= err_syntax12.error
+FILEStest_yacc+= err_syntax12.output
+FILEStest_yacc+= err_syntax12.tab.c
+FILEStest_yacc+= err_syntax12.tab.h
+FILEStest_yacc+= err_syntax13.error
+FILEStest_yacc+= err_syntax13.output
+FILEStest_yacc+= err_syntax13.tab.c
+FILEStest_yacc+= err_syntax13.tab.h
+FILEStest_yacc+= err_syntax14.error
+FILEStest_yacc+= err_syntax14.output
+FILEStest_yacc+= err_syntax14.tab.c
+FILEStest_yacc+= err_syntax14.tab.h
+FILEStest_yacc+= err_syntax15.error
+FILEStest_yacc+= err_syntax15.output
+FILEStest_yacc+= err_syntax15.tab.c
+FILEStest_yacc+= err_syntax15.tab.h
+FILEStest_yacc+= err_syntax16.error
+FILEStest_yacc+= err_syntax16.output
+FILEStest_yacc+= err_syntax16.tab.c
+FILEStest_yacc+= err_syntax16.tab.h
+FILEStest_yacc+= err_syntax17.error
+FILEStest_yacc+= err_syntax17.output
+FILEStest_yacc+= err_syntax17.tab.c
+FILEStest_yacc+= err_syntax17.tab.h
+FILEStest_yacc+= err_syntax18.error
+FILEStest_yacc+= err_syntax18.output
+FILEStest_yacc+= err_syntax18.tab.c
+FILEStest_yacc+= err_syntax18.tab.h
+FILEStest_yacc+= err_syntax19.error
+FILEStest_yacc+= err_syntax19.output
+FILEStest_yacc+= err_syntax19.tab.c
+FILEStest_yacc+= err_syntax19.tab.h
+FILEStest_yacc+= err_syntax2.error
+FILEStest_yacc+= err_syntax2.output
+FILEStest_yacc+= err_syntax2.tab.c
+FILEStest_yacc+= err_syntax2.tab.h
+FILEStest_yacc+= err_syntax20.error
+FILEStest_yacc+= err_syntax20.output
+FILEStest_yacc+= err_syntax20.tab.c
+FILEStest_yacc+= err_syntax20.tab.h
+FILEStest_yacc+= err_syntax21.error
+FILEStest_yacc+= err_syntax21.output
+FILEStest_yacc+= err_syntax21.tab.c
+FILEStest_yacc+= err_syntax21.tab.h
+FILEStest_yacc+= err_syntax22.error
+FILEStest_yacc+= err_syntax22.output
+FILEStest_yacc+= err_syntax22.tab.c
+FILEStest_yacc+= err_syntax22.tab.h
+FILEStest_yacc+= err_syntax23.error
+FILEStest_yacc+= err_syntax23.output
+FILEStest_yacc+= err_syntax23.tab.c
+FILEStest_yacc+= err_syntax23.tab.h
+FILEStest_yacc+= err_syntax24.error
+FILEStest_yacc+= err_syntax24.output
+FILEStest_yacc+= err_syntax24.tab.c
+FILEStest_yacc+= err_syntax24.tab.h
+FILEStest_yacc+= err_syntax25.error
+FILEStest_yacc+= err_syntax25.output
+FILEStest_yacc+= err_syntax25.tab.c
+FILEStest_yacc+= err_syntax25.tab.h
+FILEStest_yacc+= err_syntax26.error
+FILEStest_yacc+= err_syntax26.output
+FILEStest_yacc+= err_syntax26.tab.c
+FILEStest_yacc+= err_syntax26.tab.h
+FILEStest_yacc+= err_syntax27.error
+FILEStest_yacc+= err_syntax27.output
+FILEStest_yacc+= err_syntax27.tab.c
+FILEStest_yacc+= err_syntax27.tab.h
+FILEStest_yacc+= err_syntax3.error
+FILEStest_yacc+= err_syntax3.output
+FILEStest_yacc+= err_syntax3.tab.c
+FILEStest_yacc+= err_syntax3.tab.h
+FILEStest_yacc+= err_syntax4.error
+FILEStest_yacc+= err_syntax4.output
+FILEStest_yacc+= err_syntax4.tab.c
+FILEStest_yacc+= err_syntax4.tab.h
+FILEStest_yacc+= err_syntax5.error
+FILEStest_yacc+= err_syntax5.output
+FILEStest_yacc+= err_syntax5.tab.c
+FILEStest_yacc+= err_syntax5.tab.h
+FILEStest_yacc+= err_syntax6.error
+FILEStest_yacc+= err_syntax6.output
+FILEStest_yacc+= err_syntax6.tab.c
+FILEStest_yacc+= err_syntax6.tab.h
+FILEStest_yacc+= err_syntax7.error
+FILEStest_yacc+= err_syntax7.output
+FILEStest_yacc+= err_syntax7.tab.c
+FILEStest_yacc+= err_syntax7.tab.h
+FILEStest_yacc+= err_syntax7a.error
+FILEStest_yacc+= err_syntax7a.output
+FILEStest_yacc+= err_syntax7a.tab.c
+FILEStest_yacc+= err_syntax7a.tab.h
+FILEStest_yacc+= err_syntax7b.error
+FILEStest_yacc+= err_syntax7b.output
+FILEStest_yacc+= err_syntax7b.tab.c
+FILEStest_yacc+= err_syntax7b.tab.h
+FILEStest_yacc+= err_syntax8.error
+FILEStest_yacc+= err_syntax8.output
+FILEStest_yacc+= err_syntax8.tab.c
+FILEStest_yacc+= err_syntax8.tab.h
+FILEStest_yacc+= err_syntax8a.error
+FILEStest_yacc+= err_syntax8a.output
+FILEStest_yacc+= err_syntax8a.tab.c
+FILEStest_yacc+= err_syntax8a.tab.h
+FILEStest_yacc+= err_syntax9.error
+FILEStest_yacc+= err_syntax9.output
+FILEStest_yacc+= err_syntax9.tab.c
+FILEStest_yacc+= err_syntax9.tab.h
+FILEStest_yacc+= error.error
+FILEStest_yacc+= error.output
+FILEStest_yacc+= error.tab.c
+FILEStest_yacc+= error.tab.h
+FILEStest_yacc+= expr.oxout.error
+FILEStest_yacc+= expr.oxout.output
+FILEStest_yacc+= expr.oxout.tab.c
+FILEStest_yacc+= expr.oxout.tab.h
+FILEStest_yacc+= grammar.dot
+FILEStest_yacc+= grammar.error
+FILEStest_yacc+= grammar.output
+FILEStest_yacc+= grammar.tab.c
+FILEStest_yacc+= grammar.tab.h
+FILEStest_yacc+= help.error
+FILEStest_yacc+= help.output
+FILEStest_yacc+= no_b_opt.error
+FILEStest_yacc+= no_b_opt.output
+FILEStest_yacc+= no_b_opt1.error
+FILEStest_yacc+= no_b_opt1.output
+FILEStest_yacc+= no_code_c.error
+FILEStest_yacc+= no_code_c.output
+FILEStest_yacc+= no_defines.error
+FILEStest_yacc+= no_defines.output
+FILEStest_yacc+= no_graph.error
+FILEStest_yacc+= no_graph.output
+FILEStest_yacc+= no_include.error
+FILEStest_yacc+= no_include.output
+FILEStest_yacc+= no_opts.error
+FILEStest_yacc+= no_opts.output
+FILEStest_yacc+= no_output.error
+FILEStest_yacc+= no_output.output
+FILEStest_yacc+= no_output1.error
+FILEStest_yacc+= no_output1.output
+FILEStest_yacc+= no_output2.error
+FILEStest_yacc+= no_output2.output
+FILEStest_yacc+= no_p_opt.error
+FILEStest_yacc+= no_p_opt.output
+FILEStest_yacc+= no_p_opt1.error
+FILEStest_yacc+= no_p_opt1.output
+FILEStest_yacc+= no_verbose.error
+FILEStest_yacc+= no_verbose.output
+FILEStest_yacc+= nostdin.error
+FILEStest_yacc+= nostdin.output
+FILEStest_yacc+= ok_syntax1.error
+FILEStest_yacc+= ok_syntax1.output
+FILEStest_yacc+= ok_syntax1.tab.c
+FILEStest_yacc+= ok_syntax1.tab.h
+FILEStest_yacc+= pure_calc.error
+FILEStest_yacc+= pure_calc.output
+FILEStest_yacc+= pure_calc.tab.c
+FILEStest_yacc+= pure_calc.tab.h
+FILEStest_yacc+= pure_error.error
+FILEStest_yacc+= pure_error.output
+FILEStest_yacc+= pure_error.tab.c
+FILEStest_yacc+= pure_error.tab.h
+FILEStest_yacc+= quote_calc-s.error
+FILEStest_yacc+= quote_calc-s.output
+FILEStest_yacc+= quote_calc-s.tab.c
+FILEStest_yacc+= quote_calc-s.tab.h
+FILEStest_yacc+= quote_calc.error
+FILEStest_yacc+= quote_calc.output
+FILEStest_yacc+= quote_calc.tab.c
+FILEStest_yacc+= quote_calc.tab.h
+FILEStest_yacc+= quote_calc2-s.error
+FILEStest_yacc+= quote_calc2-s.output
+FILEStest_yacc+= quote_calc2-s.tab.c
+FILEStest_yacc+= quote_calc2-s.tab.h
+FILEStest_yacc+= quote_calc2.error
+FILEStest_yacc+= quote_calc2.output
+FILEStest_yacc+= quote_calc2.tab.c
+FILEStest_yacc+= quote_calc2.tab.h
+FILEStest_yacc+= quote_calc3-s.error
+FILEStest_yacc+= quote_calc3-s.output
+FILEStest_yacc+= quote_calc3-s.tab.c
+FILEStest_yacc+= quote_calc3-s.tab.h
+FILEStest_yacc+= quote_calc3.error
+FILEStest_yacc+= quote_calc3.output
+FILEStest_yacc+= quote_calc3.tab.c
+FILEStest_yacc+= quote_calc3.tab.h
+FILEStest_yacc+= quote_calc4-s.error
+FILEStest_yacc+= quote_calc4-s.output
+FILEStest_yacc+= quote_calc4-s.tab.c
+FILEStest_yacc+= quote_calc4-s.tab.h
+FILEStest_yacc+= quote_calc4.error
+FILEStest_yacc+= quote_calc4.output
+FILEStest_yacc+= quote_calc4.tab.c
+FILEStest_yacc+= quote_calc4.tab.h
+FILEStest_yacc+= rename_debug.c
+FILEStest_yacc+= rename_debug.error
+FILEStest_yacc+= rename_debug.h
+FILEStest_yacc+= rename_debug.i
+FILEStest_yacc+= rename_debug.output
+FILEStest_yacc+= stdin1.calc.c
+FILEStest_yacc+= stdin1.error
+FILEStest_yacc+= stdin1.output
+FILEStest_yacc+= stdin2.calc.c
+FILEStest_yacc+= stdin2.error
+FILEStest_yacc+= stdin2.output
+FILEStest_yacc+= varsyntax_calc1.error
+FILEStest_yacc+= varsyntax_calc1.output
+FILEStest_yacc+= varsyntax_calc1.tab.c
+FILEStest_yacc+= varsyntax_calc1.tab.h
+
+.include <bsd.test.mk>
diff --git a/usr.bin/yacc/tests/Makefile.depend b/usr.bin/yacc/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.bin/yacc/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/yacc/tests/yacc_tests.sh b/usr.bin/yacc/tests/yacc_tests.sh
new file mode 100755
index 000000000000..08130355678f
--- /dev/null
+++ b/usr.bin/yacc/tests/yacc_tests.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+# Setup the environment for run_test
+# - run_test looks for `#define YYBTYACC` in ../config.h
+# - run_test assumes a yacc binary exists in ../yacc instead of running "yacc"
+# - run_test spams the test dir with files (polluting subsequent test runs),
+# so it's better to copy all the files to a temporary directory created by
+# kyua
+echo > "./config.h"
+mkdir "test"
+cp -Rf "$(dirname "$0")"/* "test"
+cp -p /usr/bin/yacc ./yacc
+
+cd "test" && ./run_test
diff --git a/usr.bin/yes/Makefile b/usr.bin/yes/Makefile
new file mode 100644
index 000000000000..b1d4075b5917
--- /dev/null
+++ b/usr.bin/yes/Makefile
@@ -0,0 +1,3 @@
+PROG= yes
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/yes/Makefile.depend b/usr.bin/yes/Makefile.depend
new file mode 100644
index 000000000000..38d979787478
--- /dev/null
+++ b/usr.bin/yes/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/yes/yes.1 b/usr.bin/yes/yes.1
new file mode 100644
index 000000000000..8ed8beab0d28
--- /dev/null
+++ b/usr.bin/yes/yes.1
@@ -0,0 +1,52 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.Dd June 4, 2014
+.Dt YES 1
+.Os
+.Sh NAME
+.Nm yes
+.Nd be repetitively affirmative
+.Sh SYNOPSIS
+.Nm
+.Op Ar expletive
+.Sh DESCRIPTION
+The
+.Nm
+utility outputs
+.Ar expletive ,
+or, by default,
+.Dq y ,
+forever.
+.Sh SEE ALSO
+.Xr jot 1 ,
+.Xr seq 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.At v7 .
diff --git a/usr.bin/yes/yes.c b/usr.bin/yes/yes.c
new file mode 100644
index 000000000000..d9e896b6ea27
--- /dev/null
+++ b/usr.bin/yes/yes.c
@@ -0,0 +1,74 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1987, 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.
+ */
+
+#include <capsicum_helpers.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ char buf[8192];
+ char y[2] = { 'y', '\n' };
+ char * exp = y;
+ size_t buflen = 0;
+ size_t explen = sizeof(y);
+ size_t more;
+ ssize_t ret;
+
+ if (caph_limit_stdio() < 0 || caph_enter() < 0)
+ err(1, "capsicum");
+
+ if (argc > 1) {
+ exp = argv[1];
+ explen = strlen(exp) + 1;
+ exp[explen - 1] = '\n';
+ }
+
+ if (explen <= sizeof(buf)) {
+ while (buflen < sizeof(buf) - explen) {
+ memcpy(buf + buflen, exp, explen);
+ buflen += explen;
+ }
+ exp = buf;
+ explen = buflen;
+ }
+
+ more = explen;
+ while ((ret = write(STDOUT_FILENO, exp + (explen - more), more)) > 0)
+ if ((more -= ret) == 0)
+ more = explen;
+
+ err(1, "stdout");
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/ypcat/Makefile b/usr.bin/ypcat/Makefile
new file mode 100644
index 000000000000..15a48cf94e9a
--- /dev/null
+++ b/usr.bin/ypcat/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= yp
+PROG= ypcat
+
+WARNS?= 3
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ypcat/Makefile.depend b/usr.bin/ypcat/Makefile.depend
new file mode 100644
index 000000000000..a2d89550fa2b
--- /dev/null
+++ b/usr.bin/ypcat/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ypcat/ypcat.1 b/usr.bin/ypcat/ypcat.1
new file mode 100644
index 000000000000..de943ce6c138
--- /dev/null
+++ b/usr.bin/ypcat/ypcat.1
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1993 Winning Strategies, Inc.
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. 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.
+.\"
+.Dd September 3, 2015
+.Dt YPCAT 1
+.Os
+.Sh NAME
+.Nm ypcat
+.Nd print the values of all keys in a NIS database
+.Sh SYNOPSIS
+.Nm
+.Op Fl kt
+.Op Fl d Ar domainname
+.Ar mapname
+.Nm
+.Fl x
+.Sh DESCRIPTION
+The
+.Nm
+utility prints out the values of all keys from the
+.Tn NIS
+database specified by
+.Ar mapname ,
+which may be a map name or a map nickname.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domainname
+Specify a domain other than the default domain.
+.It Fl k
+Display map keys.
+This option is useful with maps in which the values are null or the key
+is not part of the value.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr domainname 1 ,
+.Xr ypmatch 1 ,
+.Xr yp 8 ,
+.Xr ypbind 8 ,
+.Xr ypset 8
+.Sh AUTHORS
+.An Theo De Raadt Aq Mt deraadt@theos.com .
diff --git a/usr.bin/ypcat/ypcat.c b/usr.bin/ypcat/ypcat.c
new file mode 100644
index 000000000000..0b3b1c9879c8
--- /dev/null
+++ b/usr.bin/ypcat/ypcat.c
@@ -0,0 +1,141 @@
+/* $OpenBSD: ypcat.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
+ * 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.
+ *
+ * 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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+static const struct ypalias {
+ char *alias, *name;
+} ypaliases[] = {
+ { "passwd", "passwd.byname" },
+ { "master.passwd", "master.passwd.byname" },
+ { "shadow", "shadow.byname" },
+ { "group", "group.byname" },
+ { "networks", "networks.byaddr" },
+ { "hosts", "hosts.byaddr" },
+ { "protocols", "protocols.bynumber" },
+ { "services", "services.byname" },
+ { "aliases", "mail.aliases" },
+ { "ethers", "ethers.byname" },
+};
+
+static int key;
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: ypcat [-kt] [-d domainname] mapname",
+ " ypcat -x");
+ exit(1);
+}
+
+static int
+printit(u_long instatus, char *inkey, int inkeylen, char *inval, int invallen,
+ void *indata)
+{
+ if (instatus != YP_TRUE)
+ return (instatus);
+ if (key)
+ printf("%*.*s ", inkeylen, inkeylen, inkey);
+ printf("%*.*s\n", invallen, invallen, inval);
+ return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *domain = NULL, *inmap;
+ struct ypall_callback ypcb;
+ int c, notrans, r;
+ u_int i;
+
+ notrans = key = 0;
+ while ((c = getopt(argc, argv, "xd:kt")) != -1)
+ switch (c) {
+ case 'x':
+ for (i = 0; i < nitems(ypaliases); i++)
+ printf("Use \"%s\" for \"%s\"\n",
+ ypaliases[i].alias, ypaliases[i].name);
+ exit(0);
+ case 'd':
+ domain = optarg;
+ break;
+ case 't':
+ notrans = 1;
+ break;
+ case 'k':
+ key = 1;
+ break;
+ default:
+ usage();
+ }
+
+ if (optind + 1 != argc)
+ usage();
+
+ if (domain == NULL)
+ yp_get_default_domain(&domain);
+
+ inmap = argv[optind];
+ if (notrans == 0) {
+ for (i = 0; i < nitems(ypaliases); i++)
+ if (strcmp(inmap, ypaliases[i].alias) == 0)
+ inmap = ypaliases[i].name;
+ }
+ ypcb.foreach = printit;
+ ypcb.data = NULL;
+
+ r = yp_all(domain, inmap, &ypcb);
+ switch (r) {
+ case 0:
+ break;
+ case YPERR_YPBIND:
+ errx(1, "not running ypbind");
+ default:
+ errx(1, "no such map %s. Reason: %s",
+ inmap, yperr_string(r));
+ }
+ exit(0);
+}
diff --git a/usr.bin/ypmatch/Makefile b/usr.bin/ypmatch/Makefile
new file mode 100644
index 000000000000..2d04ff96116c
--- /dev/null
+++ b/usr.bin/ypmatch/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= yp
+PROG= ypmatch
+
+WARNS?= 3
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ypmatch/Makefile.depend b/usr.bin/ypmatch/Makefile.depend
new file mode 100644
index 000000000000..a2d89550fa2b
--- /dev/null
+++ b/usr.bin/ypmatch/Makefile.depend
@@ -0,0 +1,17 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ypmatch/ypmatch.1 b/usr.bin/ypmatch/ypmatch.1
new file mode 100644
index 000000000000..82f1fdc98071
--- /dev/null
+++ b/usr.bin/ypmatch/ypmatch.1
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1993 Winning Strategies, Inc.
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. 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.
+.\"
+.Dd September 3, 2015
+.Dt YPMATCH 1
+.Os
+.Sh NAME
+.Nm ypmatch
+.Nd print the values of one or more keys in a NIS database
+.Sh SYNOPSIS
+.Nm
+.Op Fl kt
+.Op Fl d Ar domainname
+.Ar key ...
+.Ar mapname
+.Nm
+.Fl x
+.Sh DESCRIPTION
+The
+.Nm
+utility prints out the values of one or more keys from the
+.Tn NIS
+database specified by
+.Ar mapname ,
+which may be a map name or a map nickname.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domainname
+Specify a domain other than the default domain.
+.It Fl k
+Display map keys.
+This option is useful with maps in which the values are null or the key
+is not part of the value.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr domainname 1 ,
+.Xr ypcat 1 ,
+.Xr yp 8 ,
+.Xr ypbind 8 ,
+.Xr ypset 8
+.Sh AUTHORS
+.An Theo De Raadt Aq Mt deraadt@theos.com .
diff --git a/usr.bin/ypmatch/ypmatch.c b/usr.bin/ypmatch/ypmatch.c
new file mode 100644
index 000000000000..24af4b8c8993
--- /dev/null
+++ b/usr.bin/ypmatch/ypmatch.c
@@ -0,0 +1,139 @@
+/* $OpenBSD: ypmatch.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */
+/* $NetBSD: ypmatch.c,v 1.8 1996/05/07 01:24:52 jtc Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
+ * 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.
+ *
+ * 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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+static const struct ypalias {
+ char *alias, *name;
+} ypaliases[] = {
+ { "passwd", "passwd.byname" },
+ { "master.passwd", "master.passwd.byname" },
+ { "shadow", "shadow.byname" },
+ { "group", "group.byname" },
+ { "networks", "networks.byaddr" },
+ { "hosts", "hosts.byname" },
+ { "protocols", "protocols.bynumber" },
+ { "services", "services.byname" },
+ { "aliases", "mail.aliases" },
+ { "ethers", "ethers.byname" },
+};
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: ypmatch [-kt] [-d domainname] key ... mapname",
+ " ypmatch -x");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *domainname, *inkey, *inmap, *outbuf;
+ int outbuflen, key, notrans, rval;
+ int c, r;
+ u_int i;
+
+ domainname = NULL;
+ notrans = key = 0;
+ while ((c = getopt(argc, argv, "xd:kt")) != -1)
+ switch (c) {
+ case 'x':
+ for (i = 0; i < nitems(ypaliases); i++)
+ printf("Use \"%s\" for \"%s\"\n",
+ ypaliases[i].alias,
+ ypaliases[i].name);
+ exit(0);
+ case 'd':
+ domainname = optarg;
+ break;
+ case 't':
+ notrans = 1;
+ break;
+ case 'k':
+ key = 1;
+ break;
+ default:
+ usage();
+ }
+
+ if (argc - optind < 2)
+ usage();
+
+ if (domainname == NULL)
+ yp_get_default_domain(&domainname);
+
+ inmap = argv[argc-1];
+ if (notrans == 0) {
+ for (i = 0; i < nitems(ypaliases); i++)
+ if (strcmp(inmap, ypaliases[i].alias) == 0)
+ inmap = ypaliases[i].name;
+ }
+
+ rval = 0;
+ for (; optind < argc - 1; optind++) {
+ inkey = argv[optind];
+
+ r = yp_match(domainname, inmap, inkey,
+ strlen(inkey), &outbuf, &outbuflen);
+ switch (r) {
+ case 0:
+ if (key)
+ printf("%s: ", inkey);
+ printf("%*.*s\n", outbuflen, outbuflen, outbuf);
+ break;
+ case YPERR_YPBIND:
+ errx(1, "not running ypbind");
+ default:
+ errx(1, "can't match key %s in map %s. reason: %s",
+ inkey, inmap, yperr_string(r));
+ rval = 1;
+ break;
+ }
+ }
+ exit(rval);
+}
diff --git a/usr.bin/ypwhich/Makefile b/usr.bin/ypwhich/Makefile
new file mode 100644
index 000000000000..eaca41db1bf9
--- /dev/null
+++ b/usr.bin/ypwhich/Makefile
@@ -0,0 +1,12 @@
+YPSERV=${SRCTOP}/usr.sbin/ypserv/common
+.PATH: ${YPSERV}
+
+PACKAGE= yp
+PROG= ypwhich
+SRCS= yplib_host.c ypwhich.c
+
+CFLAGS+= -I${YPSERV} -I.
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ypwhich/Makefile.depend b/usr.bin/ypwhich/Makefile.depend
new file mode 100644
index 000000000000..732a025c9552
--- /dev/null
+++ b/usr.bin/ypwhich/Makefile.depend
@@ -0,0 +1,18 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/arpa \
+ include/rpc \
+ include/rpcsvc \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/ypwhich/ypwhich.1 b/usr.bin/ypwhich/ypwhich.1
new file mode 100644
index 000000000000..baa7e62942ee
--- /dev/null
+++ b/usr.bin/ypwhich/ypwhich.1
@@ -0,0 +1,101 @@
+.\" $NetBSD: ypwhich.1,v 1.3 1996/05/13 02:43:46 thorpej Exp $
+.\"
+.\" Copyright (c) 1994 Christopher G. Demetriou
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Christopher G. Demetriou.
+.\" 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.
+.\"
+.Dd September 3, 2015
+.Dt YPWHICH 1
+.Os
+.Sh NAME
+.Nm ypwhich
+.Nd return hostname of NIS server of map master
+.Sh SYNOPSIS
+.Nm
+.Op Fl d Ar domain
+.Oo
+.Op Fl t
+.Fl m Oo Ar mname Oc | Ar host
+.Oc
+.Nm
+.Fl x
+.Sh DESCRIPTION
+The
+.Nm
+utility tells which
+.Tn NIS
+server supplies
+.Tn NIS
+services to a client, or which is the master for a map.
+If invoked without arguments, it gives the
+.Tn NIS
+server for the local machine.
+If
+.Ar host
+is specified, that machine is queried to find out
+which
+.Tn NIS
+server it is using.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar domain
+Specify a domain other than the default domain.
+.It Fl t
+Inhibit translation of map nicknames
+to their corresponding map names.
+.It Fl m Op Ar mname
+Find the master
+.Tn NIS
+server for the named map.
+No
+.Ar host
+may be specified with the
+.Fl m
+option.
+The
+.Ar mname
+argument
+can be a map name or nickname.
+If
+.Ar mname
+is omitted,
+.Nm
+will produce a list of available maps.
+.It Fl x
+Display the map nickname table.
+.El
+.Sh SEE ALSO
+.Xr domainname 1 ,
+.Xr ypcat 1 ,
+.Xr ypmatch 1 ,
+.Xr yp 8 ,
+.Xr ypbind 8 ,
+.Xr yppoll 8 ,
+.Xr ypset 8
+.Sh AUTHORS
+.An Theo De Raadt
diff --git a/usr.bin/ypwhich/ypwhich.c b/usr.bin/ypwhich/ypwhich.c
new file mode 100644
index 000000000000..a76fea2c4693
--- /dev/null
+++ b/usr.bin/ypwhich/ypwhich.c
@@ -0,0 +1,276 @@
+/* $OpenBSD: ypwhich.c,v 1.23 2015/02/08 23:40:35 deraadt Exp $ */
+/* $NetBSD: ypwhich.c,v 1.6 1996/05/13 02:43:48 thorpej Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
+ * 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.
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "yplib_host.h"
+
+static const struct ypalias {
+ char *alias, *name;
+} ypaliases[] = {
+ { "passwd", "passwd.byname" },
+ { "master.passwd", "master.passwd.byname" },
+ { "shadow", "shadow.byname" },
+ { "group", "group.byname" },
+ { "networks", "networks.byaddr" },
+ { "hosts", "hosts.byaddr" },
+ { "protocols", "protocols.bynumber" },
+ { "services", "services.byname" },
+ { "aliases", "mail.aliases" },
+ { "ethers", "ethers.byname" },
+};
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: ypwhich [-t] [-d domain] [[-h] host]\n"
+ " ypwhich [-t] [-d domain] [-h host] -m [mname]\n"
+ " ypwhich -x\n");
+ exit(1);
+}
+
+
+/*
+ * Like yp_bind except can query a specific host
+ */
+static int
+bind_host(char *dom, struct sockaddr_in *sin)
+{
+ struct hostent *hent = NULL;
+ struct ypbind_resp ypbr;
+ struct in_addr ss_addr;
+ struct timeval tv;
+ CLIENT *client;
+ int sock, r;
+
+ sock = RPC_ANYSOCK;
+ tv.tv_sec = 15;
+ tv.tv_usec = 0;
+ client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
+
+ if (client == NULL) {
+ warnx("host is not bound to a ypmaster");
+ return (YPERR_YPBIND);
+ }
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+
+ r = clnt_call(client, YPBINDPROC_DOMAIN,
+ (xdrproc_t)xdr_domainname, &dom,
+ (xdrproc_t)xdr_ypbind_resp, &ypbr, tv);
+ if (r != RPC_SUCCESS) {
+ warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND));
+ clnt_destroy(client);
+ return (YPERR_YPBIND);
+ } else {
+ if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
+ warnx("can't yp_bind: reason: %s",
+ yperr_string(ypbr.ypbind_status));
+ clnt_destroy(client);
+ return (r);
+ }
+ }
+ clnt_destroy(client);
+
+ memmove(&ss_addr.s_addr, &ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+ sizeof (ss_addr));
+
+ hent = gethostbyaddr((char *)&ss_addr.s_addr, sizeof(ss_addr.s_addr),
+ AF_INET);
+ if (hent != NULL)
+ printf("%s\n", hent->h_name);
+ else
+ printf("%s\n", inet_ntoa(ss_addr));
+
+ return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *domain, *master, *map = NULL, *host = NULL;
+ int notrans = 0, mode = 0, c, r, i;
+ struct ypmaplist *ypml, *y;
+ struct sockaddr_in sin;
+ struct hostent *hent;
+ CLIENT *client = NULL;
+
+ yp_get_default_domain(&domain);
+ if (domain == NULL)
+ errx(1, "YP domain name not set");
+
+ while ((c = getopt(argc, argv, "xd:h:mt")) != -1)
+ switch (c) {
+ case 'x':
+ for (i = 0; i < nitems(ypaliases); i++)
+ printf("\"%s\" is an alias for \"%s\"\n",
+ ypaliases[i].alias,
+ ypaliases[i].name);
+ exit(0);
+ case 'h':
+ host = optarg;
+ break;
+ case 'd':
+ domain = optarg;
+ break;
+ case 't':
+ notrans = 1;
+ break;
+ case 'm':
+ mode = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (mode == 0) {
+ switch (argc) {
+ case 0:
+ memset(&sin, 0, sizeof sin);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ if (bind_host(domain, &sin))
+ exit(1);
+ break;
+ case 1:
+ bzero(&sin, sizeof sin);
+ sin.sin_family = AF_INET;
+ if (inet_aton(argv[0], &sin.sin_addr) == 0) {
+ hent = gethostbyname(argv[0]);
+ if (!hent) {
+ errx(1, "host %s unknown",
+ argv[0]);
+ }
+ }
+ if (bind_host(domain, &sin))
+ exit(1);
+ break;
+ default:
+ usage();
+ }
+ exit(0);
+ }
+
+ if (argc > 1)
+ usage();
+
+ if (host != NULL)
+ client = yp_bind_host(host, YPPROG, YPVERS, 0, 1);
+
+ if (argv[0]) {
+ map = argv[0];
+ if (notrans == 0) {
+ for (i = 0; i < nitems(ypaliases); i++)
+ if (strcmp(map, ypaliases[i].alias) == 0)
+ map = ypaliases[i].name;
+ }
+
+ if (host != NULL)
+ r = yp_master_host(client, domain, map, &master);
+ else
+ r = yp_master(domain, map, &master);
+
+ switch (r) {
+ case 0:
+ printf("%s\n", master);
+ free(master);
+ break;
+ case YPERR_YPBIND:
+ errx(1, "not running ypbind");
+ default:
+ errx(1, "can't find master for map %s: reason: %s",
+ map, yperr_string(r));
+ }
+ exit(0);
+ }
+
+ ypml = NULL;
+ if (host != NULL)
+ r = yp_maplist_host(client, domain, &ypml);
+ else
+ r = yp_maplist(domain, &ypml);
+
+ r = 0;
+ switch (r) {
+ case 0:
+ for (y = ypml; y; ) {
+ ypml = y;
+ if (host != NULL) {
+ r = yp_master_host(client,
+ domain, ypml->map, &master);
+ } else {
+ r = yp_master(domain, ypml->map, &master);
+ }
+ switch (r) {
+ case 0:
+ printf("%s %s\n", ypml->map, master);
+ free(master);
+ break;
+ default:
+ warnx("can't find the master of %s: reason: %s",
+ ypml->map, yperr_string(r));
+ break;
+ }
+ y = ypml->next;
+ free(ypml);
+ }
+ break;
+ case YPERR_YPBIND:
+ errx(1, "not running ypbind");
+ default:
+ errx(1, "can't get map list for domain %s: reason: %s",
+ domain, yperr_string(r));
+ }
+ exit(0);
+}
diff --git a/usr.bin/zstd/Makefile b/usr.bin/zstd/Makefile
new file mode 100644
index 000000000000..0e73e2eb0dd2
--- /dev/null
+++ b/usr.bin/zstd/Makefile
@@ -0,0 +1,32 @@
+PROG= zstd
+SRCS= \
+ benchfn.c \
+ benchzstd.c \
+ datagen.c \
+ dibio.c \
+ fileio.c \
+ timefn.c \
+ util.c \
+ zstdcli.c \
+ zstdcli_trace.c
+
+CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/programs \
+ -I${SRCTOP}/sys/contrib/zstd/lib/common \
+ -I${SRCTOP}/sys/contrib/zstd/lib/compress \
+ -I${SRCTOP}/sys/contrib/zstd/lib/dictBuilder \
+ -I${SRCTOP}/sys/contrib/zstd/lib \
+ -DXXH_NAMESPACE=ZSTD_ \
+ -DHAVE_THREAD=1 \
+ -DZSTD_MULTITHREAD=1
+LINKS= ${BINDIR}/zstd ${BINDIR}/unzstd \
+ ${BINDIR}/zstd ${BINDIR}/zstdcat \
+ ${BINDIR}/zstd ${BINDIR}/zstdmt
+MLINKS= zstd.1 unzstd.1 \
+ zstd.1 zstdcat.1 \
+ zstd.1 zstdmt.1
+
+WARNS?= 2
+LIBADD= zstd
+.PATH: ${SRCTOP}/sys/contrib/zstd/programs
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/zstd/Makefile.depend b/usr.bin/zstd/Makefile.depend
new file mode 100644
index 000000000000..cedebd481549
--- /dev/null
+++ b/usr.bin/zstd/Makefile.depend
@@ -0,0 +1,16 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libzstd \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif